Commit 041c87a7 authored by twanvl's avatar twanvl

Copy/pasting multiple cards

parent b7fd8888
...@@ -39,50 +39,62 @@ void deserialize_from_clipboard(T& object, Package& package, const String& data) ...@@ -39,50 +39,62 @@ void deserialize_from_clipboard(T& object, Package& package, const String& data)
// ----------------------------------------------------------------------------- : CardDataObject // ----------------------------------------------------------------------------- : CardDataObject
/// A wrapped card for storing on the clipboard /// A wrapped cards for storing on the clipboard
struct WrappedCard { struct WrappedCards {
Game* expected_game; Game* expected_game;
String game_name; String game_name;
CardP card; vector<CardP> cards;
DECLARE_REFLECTION(); DECLARE_REFLECTION();
}; };
IMPLEMENT_REFLECTION(WrappedCard) { IMPLEMENT_REFLECTION(WrappedCards) {
REFLECT(game_name); REFLECT(game_name);
if (game_name == expected_game->name()) { if (game_name == expected_game->name()) {
WITH_DYNAMIC_ARG(game_for_reading, expected_game); WITH_DYNAMIC_ARG(game_for_reading, expected_game);
REFLECT(card); REFLECT(cards);
} }
} }
wxDataFormat CardDataObject::format = _("application/x-mse-card"); wxDataFormat CardsDataObject::format = _("application/x-mse-cards");
CardDataObject::CardDataObject(const SetP& set, const CardP& card) { CardsDataObject::CardsDataObject(const SetP& set, const vector<CardP>& cards) {
WrappedCard data = { set->game.get(), set->game->name(), card }; // set the stylesheet, so when deserializing we know whos style options we are reading
bool has_styling = card->has_styling && !card->stylesheet; bool* has_styling = new bool[cards.size()];
if (has_styling) { for (size_t i = 0 ; i < cards.size() ; ++i) {
// set the stylsheet, so when deserializing we know whos style options we are reading has_styling[i] = cards[i]->has_styling && !cards[i]->stylesheet;
card->stylesheet = set->stylesheet; if (has_styling[i]) {
cards[i]->stylesheet = set->stylesheet;
}
} }
WrappedCards data = { set->game.get(), set->game->name(), cards };
SetText(serialize_for_clipboard(*set, data)); SetText(serialize_for_clipboard(*set, data));
if (has_styling) { // restore cards
card->stylesheet = StyleSheetP(); // restore card for (size_t i = 0 ; i < cards.size() ; ++i) {
if (has_styling[i]) {
cards[i]->stylesheet = StyleSheetP();
}
} }
SetFormat(format); SetFormat(format);
delete [] has_styling;
} }
CardDataObject::CardDataObject() { CardsDataObject::CardsDataObject() {
SetFormat(format); SetFormat(format);
} }
CardP CardDataObject::getCard(const SetP& set) { bool CardsDataObject::getCards(const SetP& set, vector<CardP>& out) {
CardP card(new Card(*set->game)); WrappedCards data = { set->game.get(), set->game->name() };
WrappedCard data = { set->game.get(), set->game->name(), card};
deserialize_from_clipboard(data, *set, GetText()); deserialize_from_clipboard(data, *set, GetText());
if (data.game_name != set->game->name()) return CardP(); // Card is from a different game if (data.cards.empty()) return false;
else return card; if (data.game_name == set->game->name()) {
// Cards are from the same game
out = data.cards;
return true;
} else {
return false;
}
} }
// ----------------------------------------------------------------------------- : KeywordDataObject // ----------------------------------------------------------------------------- : KeywordDataObject
...@@ -127,12 +139,14 @@ KeywordP KeywordDataObject::getKeyword(const SetP& set) { ...@@ -127,12 +139,14 @@ KeywordP KeywordDataObject::getKeyword(const SetP& set) {
// ----------------------------------------------------------------------------- : Card on clipboard // ----------------------------------------------------------------------------- : Card on clipboard
CardOnClipboard::CardOnClipboard(const SetP& set, const CardP& card) { CardsOnClipboard::CardsOnClipboard(const SetP& set, const vector<CardP>& cards) {
// Conversion to text format // Conversion to text format
// TODO // TODO
//Add( new TextDataObject(_("card"))) //Add( new TextDataObject(_("card")))
// Conversion to bitmap format // Conversion to bitmap format
Add(new wxBitmapDataObject(export_bitmap(set, card))); if (cards.size() == 1) {
Add(new wxBitmapDataObject(export_bitmap(set, cards[0])));
}
// Conversion to serialized card format // Conversion to serialized card format
Add(new CardDataObject(set, card), true); Add(new CardsDataObject(set, cards), true);
} }
...@@ -19,17 +19,18 @@ DECLARE_POINTER_TYPE(Keyword); ...@@ -19,17 +19,18 @@ DECLARE_POINTER_TYPE(Keyword);
// ----------------------------------------------------------------------------- : CardDataObject // ----------------------------------------------------------------------------- : CardDataObject
/// The data format for cards on the clipboard /// The data format for cards on the clipboard
class CardDataObject : public wxTextDataObject { class CardsDataObject : public wxTextDataObject {
public: public:
/// Name of the format of MSE cards /// Name of the format of MSE cards
static wxDataFormat format; static wxDataFormat format;
CardDataObject(); CardsDataObject();
/// Store a card /// Store a card
CardDataObject(const SetP& set, const CardP& card); CardsDataObject(const SetP& set, const vector<CardP>& cards);
/// Retrieve a card, only if it is made with the same game as set /// Retrieve the cards, only if it is made with the same game as set
CardP getCard(const SetP& set); /** Return true if the cards are correctly retrieved, and there is at least one card */
bool getCards(const SetP& set, vector<CardP>& out);
}; };
// ----------------------------------------------------------------------------- : KeywordDataObject // ----------------------------------------------------------------------------- : KeywordDataObject
...@@ -50,10 +51,10 @@ class KeywordDataObject : public wxTextDataObject { ...@@ -50,10 +51,10 @@ class KeywordDataObject : public wxTextDataObject {
// ----------------------------------------------------------------------------- : Card on clipboard // ----------------------------------------------------------------------------- : Card on clipboard
/// A DataObject for putting a card on the clipboard, in multiple formats /// A DataObject for putting one or more cards on the clipboard, in multiple formats
class CardOnClipboard : public wxDataObjectComposite { class CardsOnClipboard : public wxDataObjectComposite {
public: public:
CardOnClipboard(const SetP& set, const CardP& card); CardsOnClipboard(const SetP& set, const vector<CardP>& cards);
}; };
// ----------------------------------------------------------------------------- : EOF // ----------------------------------------------------------------------------- : EOF
......
...@@ -132,13 +132,23 @@ void CardListBase::sendEvent() { ...@@ -132,13 +132,23 @@ void CardListBase::sendEvent() {
bool CardListBase::canCopy() const { return !!selected_item; } bool CardListBase::canCopy() const { return !!selected_item; }
bool CardListBase::canCut() const { return canCopy() && allowModify(); } bool CardListBase::canCut() const { return canCopy() && allowModify(); }
bool CardListBase::canPaste() const { bool CardListBase::canPaste() const {
return allowModify() && wxTheClipboard->IsSupported(CardDataObject::format); return allowModify() && wxTheClipboard->IsSupported(CardsDataObject::format);
} }
bool CardListBase::doCopy() { bool CardListBase::doCopy() {
if (!canCopy()) return false; if (!canCopy()) return false;
// cards to copy
vector<CardP> cards_to_copy;
long count = GetItemCount();
for (long pos = 0 ; pos < count ; ++pos) {
if (IsSelected(pos)) {
cards_to_copy.push_back(getCard(pos));
}
}
if (cards_to_copy.empty()) return false;
// put on clipboard
if (!wxTheClipboard->Open()) return false; if (!wxTheClipboard->Open()) return false;
bool ok = wxTheClipboard->SetData(new CardOnClipboard(set, getCard())); // ignore result bool ok = wxTheClipboard->SetData(new CardsOnClipboard(set, cards_to_copy)); // ignore result
wxTheClipboard->Close(); wxTheClipboard->Close();
return ok; return ok;
} }
...@@ -153,22 +163,30 @@ bool CardListBase::doPaste() { ...@@ -153,22 +163,30 @@ bool CardListBase::doPaste() {
// get data // get data
if (!canPaste()) return false; if (!canPaste()) return false;
if (!wxTheClipboard->Open()) return false; if (!wxTheClipboard->Open()) return false;
CardDataObject data; CardsDataObject data;
bool ok = wxTheClipboard->GetData(data); bool ok = wxTheClipboard->GetData(data);
wxTheClipboard->Close(); wxTheClipboard->Close();
if (!ok) return false; if (!ok) return false;
// get cards
vector<CardP> new_cards;
ok = data.getCards(set, new_cards);
if (!ok) return false;
// add card to set // add card to set
CardP card = data.getCard(set); set->actions.add(new AddCardAction(ADD, *set, new_cards));
if (card) { return true;
set->actions.add(new AddCardAction(ADD, *set, card));
return true;
} else {
return false;
}
} }
bool CardListBase::doDelete() { bool CardListBase::doDelete() {
//vector<> // cards to delete
set->actions.add(new AddCardAction(REMOVE, *set, getCard())); vector<CardP> cards_to_delete;
long count = GetItemCount();
for (long pos = 0 ; pos < count ; ++pos) {
if (IsSelected(pos)) {
cards_to_delete.push_back(getCard(pos));
}
}
if (cards_to_delete.empty()) return false;
// delete cards
set->actions.add(new AddCardAction(REMOVE, *set, cards_to_delete));
return true; return true;
} }
......
...@@ -61,7 +61,7 @@ bool ImageValueEditor::canCopy() const { ...@@ -61,7 +61,7 @@ bool ImageValueEditor::canCopy() const {
bool ImageValueEditor::canPaste() const { bool ImageValueEditor::canPaste() const {
return wxTheClipboard->IsSupported(wxDF_BITMAP) && return wxTheClipboard->IsSupported(wxDF_BITMAP) &&
!wxTheClipboard->IsSupported(CardDataObject::format); // we don't want to (accidentally) paste card images !wxTheClipboard->IsSupported(CardsDataObject::format); // we don't want to (accidentally) paste card images
} }
bool ImageValueEditor::doCopy() { bool ImageValueEditor::doCopy() {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment