From a2f0b67aea61ef3002d1763e4b67433b5b29a7aa Mon Sep 17 00:00:00 2001 From: Sam Atkins Date: Wed, 28 Sep 2022 17:05:34 +0100 Subject: [PATCH] LibCards: Add support for card dragging Solitaire and Spider have almost identical code for dragging cards from one stack to another, so it makes sense to move that here. But using the term "moving" for them, instead of "focused" which (to me at least) was not clear what it meant. --- Userland/Libraries/LibCards/CardGame.cpp | 61 ++++++++++++++++++++++++ Userland/Libraries/LibCards/CardGame.h | 13 +++++ 2 files changed, 74 insertions(+) diff --git a/Userland/Libraries/LibCards/CardGame.cpp b/Userland/Libraries/LibCards/CardGame.cpp index 6917da40ab..96a5d7e8b7 100644 --- a/Userland/Libraries/LibCards/CardGame.cpp +++ b/Userland/Libraries/LibCards/CardGame.cpp @@ -1,5 +1,7 @@ /* + * Copyright (c) 2020, Till Mayer * Copyright (c) 2022, Sam Atkins + * Copyright (c) 2022, the SerenityOS developers. * * SPDX-License-Identifier: BSD-2-Clause */ @@ -32,6 +34,65 @@ void CardGame::mark_intersecting_stacks_dirty(Cards::Card const& intersecting_ca update(intersecting_card.rect()); } +Gfx::IntRect CardGame::moving_cards_bounds() const +{ + if (!is_moving_cards()) + return {}; + + // Note: This assumes that the cards are arranged in a line. + return m_moving_cards.first().rect().united(m_moving_cards.last().rect()); +} + +void CardGame::pick_up_cards_from_stack(Cards::CardStack& stack, Gfx::IntPoint click_location, CardStack::MovementRule movement_rule) +{ + if (m_moving_cards_source_stack) + m_moving_cards_source_stack->set_focused(false); + stack.add_all_grabbed_cards(click_location, m_moving_cards, movement_rule); + stack.set_focused(true); + m_moving_cards_source_stack = stack; +} + +RefPtr CardGame::find_stack_to_drop_on(CardStack::MovementRule movement_rule) const +{ + auto bounds_to_check = moving_cards_bounds(); + + // FIXME: This currently returns only the first stack we overlap, + // but what we want is the stack we overlap the most. + for (auto const& stack : stacks()) { + if (stack.is_focused()) + continue; + + if (stack.bounding_box().intersects(bounds_to_check)) { + if (stack.is_allowed_to_push(moving_cards().at(0), moving_cards().size(), movement_rule)) { + return stack; + } + } + } + + return nullptr; +} + +void CardGame::drop_cards_on_stack(Cards::CardStack& stack, CardStack::MovementRule movement_rule) +{ + VERIFY(stack.is_allowed_to_push(m_moving_cards.at(0), m_moving_cards.size(), movement_rule)); + for (auto& to_intersect : moving_cards()) { + mark_intersecting_stacks_dirty(to_intersect); + stack.push(to_intersect); + (void)moving_cards_source_stack()->pop(); + } + + update(moving_cards_source_stack()->bounding_box()); + update(stack.bounding_box()); +} + +void CardGame::clear_moving_cards() +{ + if (!m_moving_cards_source_stack.is_null()) + m_moving_cards_source_stack->set_focused(false); + m_moving_cards_source_stack.clear(); + m_moving_cards.clear(); +} + void CardGame::dump_layout() const { dbgln("------------------------------"); diff --git a/Userland/Libraries/LibCards/CardGame.h b/Userland/Libraries/LibCards/CardGame.h index 87e8a5a940..7ca1645ac2 100644 --- a/Userland/Libraries/LibCards/CardGame.h +++ b/Userland/Libraries/LibCards/CardGame.h @@ -27,6 +27,16 @@ public: void add_stack(NonnullRefPtr); void mark_intersecting_stacks_dirty(Card const& intersecting_card); + bool is_moving_cards() const { return !m_moving_cards.is_empty(); } + NonnullRefPtrVector& moving_cards() { return m_moving_cards; } + NonnullRefPtrVector const& moving_cards() const { return m_moving_cards; } + Gfx::IntRect moving_cards_bounds() const; + RefPtr moving_cards_source_stack() const { return m_moving_cards_source_stack; } + void pick_up_cards_from_stack(CardStack&, Gfx::IntPoint click_location, CardStack::MovementRule); + RefPtr find_stack_to_drop_on(CardStack::MovementRule) const; + void drop_cards_on_stack(CardStack&, CardStack::MovementRule); + void clear_moving_cards(); + void dump_layout() const; protected: @@ -36,6 +46,9 @@ private: virtual void config_string_did_change(String const& domain, String const& group, String const& key, String const& value) override; NonnullRefPtrVector m_stacks; + + NonnullRefPtrVector m_moving_cards; + RefPtr m_moving_cards_source_stack; }; }