prevent drag and drop from within the same card list

This commit is contained in:
GenevensiS
2025-12-03 17:50:48 +01:00
parent 2d6c0d2aee
commit f22046d77b
4 changed files with 31 additions and 21 deletions
+9 -6
View File
@@ -45,6 +45,7 @@ void deserialize_from_clipboard(T& object, Package& package, const String& data)
struct WrappedCards { struct WrappedCards {
Game* expected_game; Game* expected_game;
String game_name; String game_name;
String id;
vector<CardP> cards; vector<CardP> cards;
DECLARE_REFLECTION(); DECLARE_REFLECTION();
@@ -52,6 +53,7 @@ struct WrappedCards {
IMPLEMENT_REFLECTION(WrappedCards) { IMPLEMENT_REFLECTION(WrappedCards) {
REFLECT(game_name); REFLECT(game_name);
REFLECT(id);
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(cards); REFLECT(cards);
@@ -61,7 +63,7 @@ IMPLEMENT_REFLECTION(WrappedCards) {
wxDataFormat CardsDataObject::format = _("application/x-mse-cards"); wxDataFormat CardsDataObject::format = _("application/x-mse-cards");
CardsDataObject::CardsDataObject(const SetP& set, const vector<CardP>& cards) { CardsDataObject::CardsDataObject(const SetP& set, const String id, const vector<CardP>& cards) {
// set the stylesheet, so when deserializing we know whos style options we are reading // set the stylesheet, so when deserializing we know whos style options we are reading
vector<bool> has_styling; vector<bool> has_styling;
for (size_t i = 0 ; i < cards.size() ; ++i) { for (size_t i = 0 ; i < cards.size() ; ++i) {
@@ -70,7 +72,7 @@ CardsDataObject::CardsDataObject(const SetP& set, const vector<CardP>& cards) {
cards[i]->stylesheet = set->stylesheet; cards[i]->stylesheet = set->stylesheet;
} }
} }
WrappedCards data = { set->game.get(), set->game->name(), cards }; WrappedCards data = { set->game.get(), set->game->name(), id, cards };
SetText(serialize_for_clipboard(*set, data)); SetText(serialize_for_clipboard(*set, data));
// restore cards // restore cards
for (size_t i = 0 ; i < cards.size() ; ++i) { for (size_t i = 0 ; i < cards.size() ; ++i) {
@@ -85,10 +87,11 @@ CardsDataObject::CardsDataObject() {
SetFormat(format); SetFormat(format);
} }
bool CardsDataObject::getCards(const SetP& set, vector<CardP>& out) { bool CardsDataObject::getCards(const SetP& set, const String id, vector<CardP>& out) {
WrappedCards data = { set->game.get(), set->game->name() }; WrappedCards data = { set->game.get(), set->game->name() };
deserialize_from_clipboard(data, *set, GetText()); deserialize_from_clipboard(data, *set, GetText());
if (data.cards.empty()) return false; if (data.cards.empty()) return false;
if (!id.empty() && data.id == id) return false;
if (data.game_name == set->game->name()) { if (data.game_name == set->game->name()) {
// Cards are from the same game // Cards are from the same game
out = data.cards; out = data.cards;
@@ -140,7 +143,7 @@ KeywordP KeywordDataObject::getKeyword(const SetP& set) {
// ----------------------------------------------------------------------------- : Card on clipboard // ----------------------------------------------------------------------------- : Card on clipboard
CardsOnClipboard::CardsOnClipboard(const SetP& set, const vector<CardP>& cards) { CardsOnClipboard::CardsOnClipboard(const SetP& set, const String id, const vector<CardP>& cards) {
// Conversion to image file // Conversion to image file
if (cards.size() < 6) { if (cards.size() < 6) {
Image img; Image img;
@@ -156,6 +159,6 @@ CardsOnClipboard::CardsOnClipboard(const SetP& set, const vector<CardP>& cards)
data->AddFile(temp_path); data->AddFile(temp_path);
Add(data); Add(data);
} }
// Conversion to serialized card format // Conversion to serialized card format
Add(new CardsDataObject(set, cards), true); Add(new CardsDataObject(set, id, cards), true);
} }
+5 -4
View File
@@ -25,11 +25,12 @@ public:
CardsDataObject(); CardsDataObject();
/// Store a card /// Store a card
CardsDataObject(const SetP& set, const vector<CardP>& cards); CardsDataObject(const SetP& set, const String id, const vector<CardP>& cards);
/// Retrieve the cards, only if it is made with the same game as set /// Retrieve the cards, only if this is made with the same game as set
/// And if this is NOT of the same id as the given one
/** Return true if the cards are correctly retrieved, and there is at least one card */ /** Return true if the cards are correctly retrieved, and there is at least one card */
bool getCards(const SetP& set, vector<CardP>& out); bool getCards(const SetP& set, const String id, vector<CardP>& out);
}; };
// ----------------------------------------------------------------------------- : KeywordDataObject // ----------------------------------------------------------------------------- : KeywordDataObject
@@ -53,6 +54,6 @@ public:
/// A DataObject for putting one or more cards on the clipboard, in multiple formats /// A DataObject for putting one or more cards on the clipboard, in multiple formats
class CardsOnClipboard : public wxDataObjectComposite { class CardsOnClipboard : public wxDataObjectComposite {
public: public:
CardsOnClipboard(const SetP& set, const vector<CardP>& cards); CardsOnClipboard(const SetP& set, const String id, const vector<CardP>& cards);
}; };
+13 -9
View File
@@ -7,6 +7,7 @@
// ----------------------------------------------------------------------------- : Includes // ----------------------------------------------------------------------------- : Includes
#include <util/prec.hpp> #include <util/prec.hpp>
#include <util/uid.hpp>
#include <gui/control/card_list.hpp> #include <gui/control/card_list.hpp>
#include <gui/control/card_list_column_select.hpp> #include <gui/control/card_list_column_select.hpp>
#include <gui/set/window.hpp> // for sorting all cardlists in a window #include <gui/set/window.hpp> // for sorting all cardlists in a window
@@ -163,7 +164,7 @@ bool CardListBase::doCopy() {
if (cards_to_copy.empty()) return false; if (cards_to_copy.empty()) return false;
// put on clipboard // put on clipboard
if (!wxTheClipboard->Open()) return false; if (!wxTheClipboard->Open()) return false;
bool ok = wxTheClipboard->SetData(new CardsOnClipboard(set, cards_to_copy)); // ignore result bool ok = wxTheClipboard->SetData(new CardsOnClipboard(set, _(""), cards_to_copy)); // ignore result
wxTheClipboard->Close(); wxTheClipboard->Close();
return ok; return ok;
} }
@@ -189,7 +190,7 @@ bool CardListBase::doCopyCardAndLinkedCards() {
} }
} }
} }
bool ok = wxTheClipboard->SetData(new CardsOnClipboard(set, cards_to_copy)); // ignore result bool ok = wxTheClipboard->SetData(new CardsOnClipboard(set, _(""), cards_to_copy)); // ignore result
wxTheClipboard->Close(); wxTheClipboard->Close();
return ok; return ok;
} }
@@ -199,7 +200,7 @@ bool CardListBase::doPaste() {
if (!wxTheClipboard->Open()) return false; if (!wxTheClipboard->Open()) return false;
bool ok = wxTheClipboard->GetData(*drop_target->data_object); bool ok = wxTheClipboard->GetData(*drop_target->data_object);
wxTheClipboard->Close(); wxTheClipboard->Close();
if (ok) return parseData(); if (ok) return parseData(false);
return false; return false;
} }
@@ -328,14 +329,15 @@ bool CardListBase::parseText(String& text, vector<CardP>& out) {
return j < out.size(); return j < out.size();
} }
bool CardListBase::parseData() { bool CardListBase::parseData(bool ignore_cards_from_own_card_list) {
wxBusyCursor wait; wxBusyCursor wait;
wxDataFormat format = drop_target->data_object->GetReceivedFormat(); wxDataFormat format = drop_target->data_object->GetReceivedFormat();
wxDataObject *data = drop_target->data_object->GetObject(format); wxDataObject *data = drop_target->data_object->GetObject(format);
vector<CardP> new_cards; vector<CardP> new_cards;
if (CardsDataObject* card_data = dynamic_cast<CardsDataObject*>(data)) { if (CardsDataObject* card_data = dynamic_cast<CardsDataObject*>(data)) {
card_data->getCards(set, new_cards); String id = ignore_cards_from_own_card_list ? drop_target->ignored_id : _("");
card_data->getCards(set, id, new_cards);
} }
else switch (format.GetType()) else switch (format.GetType())
{ {
@@ -596,7 +598,9 @@ void CardListBase::onChar(wxKeyEvent& ev) {
void CardListBase::onBeginDrag(wxListEvent&) { void CardListBase::onBeginDrag(wxListEvent&) {
vector<CardP> cards; vector<CardP> cards;
getSelection(cards); getSelection(cards);
CardsOnClipboard* card_data = new CardsOnClipboard(set, cards); String transaction_id = generate_uid();
CardsOnClipboard* card_data = new CardsOnClipboard(set, transaction_id, cards);
drop_target->ignored_id = transaction_id;
wxDropSource drag_source(this); wxDropSource drag_source(this);
drag_source.SetData(*card_data); drag_source.SetData(*card_data);
drag_source.DoDragDrop(wxDrag_CopyOnly); drag_source.DoDragDrop(wxDrag_CopyOnly);
@@ -645,7 +649,7 @@ void CardListBase::onItemActivate(wxListEvent& ev) {
// ----------------------------------------------------------------------------- : CardListDropTarget // ----------------------------------------------------------------------------- : CardListDropTarget
CardListDropTarget::CardListDropTarget(CardListBase* card_list) CardListDropTarget::CardListDropTarget(CardListBase* card_list)
: card_list(card_list) : card_list(card_list), ignored_id(_(""))
{ {
data_object = new wxDataObjectComposite(); data_object = new wxDataObjectComposite();
data_object->Add(new CardsDataObject(), true); data_object->Add(new CardsDataObject(), true);
@@ -659,7 +663,7 @@ CardListDropTarget::~CardListDropTarget() {}
wxDragResult CardListDropTarget::OnData(wxCoord x, wxCoord y, wxDragResult defaultDragResult) { wxDragResult CardListDropTarget::OnData(wxCoord x, wxCoord y, wxDragResult defaultDragResult) {
if (!GetData()) return wxDragNone; if (!GetData()) return wxDragNone;
if (!card_list->parseData()) return wxDragError; if (!card_list->parseData(true)) return wxDragError;
return wxDragCopy; return wxDragCopy;
} }
+4 -2
View File
@@ -86,7 +86,7 @@ public:
bool doAddJSON(); bool doAddJSON();
// Look for cards inside some given data // Look for cards inside some given data
bool parseData(); bool parseData(bool ignore_cards_from_own_card_list);
bool parseUrl (String& url, vector<CardP>& out); bool parseUrl (String& url, vector<CardP>& out);
bool parseFiles(wxArrayString& filenames, vector<CardP>& out); bool parseFiles(wxArrayString& filenames, vector<CardP>& out);
bool parseText (String& text, vector<CardP>& out); bool parseText (String& text, vector<CardP>& out);
@@ -177,7 +177,9 @@ public:
wxDragResult OnData(wxCoord x, wxCoord y, wxDragResult defaultDragResult) override; wxDragResult OnData(wxCoord x, wxCoord y, wxDragResult defaultDragResult) override;
wxDataObjectComposite* data_object; ///< the object that acquires the data from the Clipboard or a Drag'n'Drop wxDataObjectComposite* data_object; ///< the object that acquires the data from the Clipboard or a Drag'n'Drop
String ignored_id; ///< the id of the transaction we need to ignore (the one coming from our own card_list)
private: private:
CardListBase* card_list; ///< the card list we are the drop target of CardListBase* card_list; ///< the card list we are the drop target of
}; };