diff --git a/src/data/format/clipboard.cpp b/src/data/format/clipboard.cpp index 42db25ec..19f7eacc 100644 --- a/src/data/format/clipboard.cpp +++ b/src/data/format/clipboard.cpp @@ -39,50 +39,62 @@ void deserialize_from_clipboard(T& object, Package& package, const String& data) // ----------------------------------------------------------------------------- : CardDataObject -/// A wrapped card for storing on the clipboard -struct WrappedCard { - Game* expected_game; - String game_name; - CardP card; +/// A wrapped cards for storing on the clipboard +struct WrappedCards { + Game* expected_game; + String game_name; + vector cards; DECLARE_REFLECTION(); }; -IMPLEMENT_REFLECTION(WrappedCard) { +IMPLEMENT_REFLECTION(WrappedCards) { REFLECT(game_name); if (game_name == expected_game->name()) { 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) { - WrappedCard data = { set->game.get(), set->game->name(), card }; - bool has_styling = card->has_styling && !card->stylesheet; - if (has_styling) { - // set the stylsheet, so when deserializing we know whos style options we are reading - card->stylesheet = set->stylesheet; +CardsDataObject::CardsDataObject(const SetP& set, const vector& cards) { + // set the stylesheet, so when deserializing we know whos style options we are reading + bool* has_styling = new bool[cards.size()]; + for (size_t i = 0 ; i < cards.size() ; ++i) { + has_styling[i] = cards[i]->has_styling && !cards[i]->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)); - if (has_styling) { - card->stylesheet = StyleSheetP(); // restore card + // restore cards + for (size_t i = 0 ; i < cards.size() ; ++i) { + if (has_styling[i]) { + cards[i]->stylesheet = StyleSheetP(); + } } SetFormat(format); + delete [] has_styling; } -CardDataObject::CardDataObject() { +CardsDataObject::CardsDataObject() { SetFormat(format); } -CardP CardDataObject::getCard(const SetP& set) { - CardP card(new Card(*set->game)); - WrappedCard data = { set->game.get(), set->game->name(), card}; +bool CardsDataObject::getCards(const SetP& set, vector& out) { + WrappedCards data = { set->game.get(), set->game->name() }; deserialize_from_clipboard(data, *set, GetText()); - if (data.game_name != set->game->name()) return CardP(); // Card is from a different game - else return card; + if (data.cards.empty()) return false; + if (data.game_name == set->game->name()) { + // Cards are from the same game + out = data.cards; + return true; + } else { + return false; + } } // ----------------------------------------------------------------------------- : KeywordDataObject @@ -127,12 +139,14 @@ KeywordP KeywordDataObject::getKeyword(const SetP& set) { // ----------------------------------------------------------------------------- : Card on clipboard -CardOnClipboard::CardOnClipboard(const SetP& set, const CardP& card) { +CardsOnClipboard::CardsOnClipboard(const SetP& set, const vector& cards) { // Conversion to text format // TODO //Add( new TextDataObject(_("card"))) // 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 - Add(new CardDataObject(set, card), true); + Add(new CardsDataObject(set, cards), true); } diff --git a/src/data/format/clipboard.hpp b/src/data/format/clipboard.hpp index cb3352b7..2751d7ce 100644 --- a/src/data/format/clipboard.hpp +++ b/src/data/format/clipboard.hpp @@ -19,17 +19,18 @@ DECLARE_POINTER_TYPE(Keyword); // ----------------------------------------------------------------------------- : CardDataObject /// The data format for cards on the clipboard -class CardDataObject : public wxTextDataObject { +class CardsDataObject : public wxTextDataObject { public: /// Name of the format of MSE cards static wxDataFormat format; - CardDataObject(); + CardsDataObject(); /// Store a card - CardDataObject(const SetP& set, const CardP& card); + CardsDataObject(const SetP& set, const vector& cards); - /// Retrieve a card, only if it is made with the same game as set - CardP getCard(const SetP& set); + /// Retrieve the cards, only if it is made with the same game as set + /** Return true if the cards are correctly retrieved, and there is at least one card */ + bool getCards(const SetP& set, vector& out); }; // ----------------------------------------------------------------------------- : KeywordDataObject @@ -50,10 +51,10 @@ class KeywordDataObject : public wxTextDataObject { // ----------------------------------------------------------------------------- : Card on clipboard -/// A DataObject for putting a card on the clipboard, in multiple formats -class CardOnClipboard : public wxDataObjectComposite { +/// A DataObject for putting one or more cards on the clipboard, in multiple formats +class CardsOnClipboard : public wxDataObjectComposite { public: - CardOnClipboard(const SetP& set, const CardP& card); + CardsOnClipboard(const SetP& set, const vector& cards); }; // ----------------------------------------------------------------------------- : EOF diff --git a/src/gui/control/card_list.cpp b/src/gui/control/card_list.cpp index 5c23c499..13b76070 100644 --- a/src/gui/control/card_list.cpp +++ b/src/gui/control/card_list.cpp @@ -132,13 +132,23 @@ void CardListBase::sendEvent() { bool CardListBase::canCopy() const { return !!selected_item; } bool CardListBase::canCut() const { return canCopy() && allowModify(); } bool CardListBase::canPaste() const { - return allowModify() && wxTheClipboard->IsSupported(CardDataObject::format); + return allowModify() && wxTheClipboard->IsSupported(CardsDataObject::format); } bool CardListBase::doCopy() { if (!canCopy()) return false; + // cards to copy + vector 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; - bool ok = wxTheClipboard->SetData(new CardOnClipboard(set, getCard())); // ignore result + bool ok = wxTheClipboard->SetData(new CardsOnClipboard(set, cards_to_copy)); // ignore result wxTheClipboard->Close(); return ok; } @@ -153,22 +163,30 @@ bool CardListBase::doPaste() { // get data if (!canPaste()) return false; if (!wxTheClipboard->Open()) return false; - CardDataObject data; + CardsDataObject data; bool ok = wxTheClipboard->GetData(data); wxTheClipboard->Close(); if (!ok) return false; + // get cards + vector new_cards; + ok = data.getCards(set, new_cards); + if (!ok) return false; // add card to set - CardP card = data.getCard(set); - if (card) { - set->actions.add(new AddCardAction(ADD, *set, card)); - return true; - } else { - return false; - } + set->actions.add(new AddCardAction(ADD, *set, new_cards)); + return true; } bool CardListBase::doDelete() { - //vector<> - set->actions.add(new AddCardAction(REMOVE, *set, getCard())); + // cards to delete + vector 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; } diff --git a/src/gui/value/image.cpp b/src/gui/value/image.cpp index 5c616679..b43727fc 100644 --- a/src/gui/value/image.cpp +++ b/src/gui/value/image.cpp @@ -61,7 +61,7 @@ bool ImageValueEditor::canCopy() const { bool ImageValueEditor::canPaste() const { 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() {