diff --git a/Userland/Libraries/LibCards/CardGame.cpp b/Userland/Libraries/LibCards/CardGame.cpp index 6917da40ab6..96a5d7e8b70 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 87e8a5a940a..7ca1645ac2f 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; }; }