summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTimothy Flynn <trflynn89@pm.me>2023-01-05 10:16:16 -0500
committerAndreas Kling <kling@serenityos.org>2023-01-06 12:02:10 +0100
commit4cbdc747abbef74a3de8b05428fa5c0ca0dd09ba (patch)
tree47353fcaf7e5fc1bd8bd8d40b41cd480a503730a
parent8d8fcd0d648d3b851283d1122f6294ca80181c92 (diff)
downloadserenity-4cbdc747abbef74a3de8b05428fa5c0ca0dd09ba.zip
LibCards+Solitaire: Elevate card highlight management to the card stack
Instead of indicating which individual cards should be highlighted, card games now indicate which stack is highlighted. This lets the stack draw empty stacks with a highlight (e.g. the Foundation stack in Solitaire). If the stack is non-empty, the stack can delegate highlighting to the top-most card.
-rw-r--r--Userland/Games/Solitaire/Game.cpp26
-rw-r--r--Userland/Games/Solitaire/Game.h4
-rw-r--r--Userland/Libraries/LibCards/Card.cpp8
-rw-r--r--Userland/Libraries/LibCards/Card.h6
-rw-r--r--Userland/Libraries/LibCards/CardStack.cpp22
-rw-r--r--Userland/Libraries/LibCards/CardStack.h3
6 files changed, 41 insertions, 28 deletions
diff --git a/Userland/Games/Solitaire/Game.cpp b/Userland/Games/Solitaire/Game.cpp
index cc9cfb5bf6..302d3d86fe 100644
--- a/Userland/Games/Solitaire/Game.cpp
+++ b/Userland/Games/Solitaire/Game.cpp
@@ -272,7 +272,7 @@ void Game::mousedown_event(GUI::MouseEvent& event)
void Game::mouseup_event(GUI::MouseEvent& event)
{
GUI::Frame::mouseup_event(event);
- clear_hovered_card();
+ clear_hovered_stack();
if (!is_moving_cards() || m_game_over_animation || m_new_game_animation)
return;
@@ -313,16 +313,16 @@ void Game::mousemove_event(GUI::MouseEvent& event)
int dx = click_location.dx_relative_to(m_mouse_down_location);
int dy = click_location.dy_relative_to(m_mouse_down_location);
- if (auto target_stack = find_stack_to_drop_on(Cards::CardStack::MovementRule::Alternating); target_stack && !target_stack->is_empty()) {
- if (auto& top_card = target_stack->peek(); top_card != m_hovered_card) {
- clear_hovered_card();
- m_hovered_card = top_card;
+ if (auto target_stack = find_stack_to_drop_on(Cards::CardStack::MovementRule::Alternating)) {
+ if (target_stack != m_hovered_stack) {
+ clear_hovered_stack();
- m_hovered_card->set_highlighted(true);
- update(m_hovered_card->rect());
+ m_hovered_stack = move(target_stack);
+ m_hovered_stack->set_highlighted(true);
+ update(m_hovered_stack->bounding_box());
}
} else {
- clear_hovered_card();
+ clear_hovered_stack();
}
for (auto& to_intersect : moving_cards()) {
@@ -632,14 +632,14 @@ void Game::perform_undo()
invalidate_layout();
}
-void Game::clear_hovered_card()
+void Game::clear_hovered_stack()
{
- if (!m_hovered_card)
+ if (!m_hovered_stack)
return;
- m_hovered_card->set_highlighted(false);
- update(m_hovered_card->rect());
- m_hovered_card = nullptr;
+ m_hovered_stack->set_highlighted(false);
+ update(m_hovered_stack->bounding_box());
+ m_hovered_stack = nullptr;
}
}
diff --git a/Userland/Games/Solitaire/Game.h b/Userland/Games/Solitaire/Game.h
index 9e2f1e87a0..1b8d2a024b 100644
--- a/Userland/Games/Solitaire/Game.h
+++ b/Userland/Games/Solitaire/Game.h
@@ -174,7 +174,7 @@ private:
void create_new_animation_card();
void set_background_fill_enabled(bool);
void check_for_game_over();
- void clear_hovered_card();
+ void clear_hovered_stack();
virtual void paint_event(GUI::PaintEvent&) override;
virtual void mousedown_event(GUI::MouseEvent&) override;
@@ -205,7 +205,7 @@ private:
bool m_auto_collect { false };
- RefPtr<Card> m_hovered_card;
+ RefPtr<CardStack> m_hovered_stack;
};
}
diff --git a/Userland/Libraries/LibCards/Card.cpp b/Userland/Libraries/LibCards/Card.cpp
index 46c16aefee..00f85894d0 100644
--- a/Userland/Libraries/LibCards/Card.cpp
+++ b/Userland/Libraries/LibCards/Card.cpp
@@ -20,13 +20,13 @@ Card::Card(Suit suit, Rank rank)
VERIFY(to_underlying(rank) < card_count);
}
-void Card::paint(GUI::Painter& painter) const
+void Card::paint(GUI::Painter& painter, bool highlighted) const
{
auto& card_painter = CardPainter::the();
auto bitmap = [&]() {
if (m_inverted)
return m_upside_down ? card_painter.card_back_inverted() : card_painter.card_front_inverted(m_suit, m_rank);
- if (m_highlighted) {
+ if (highlighted) {
VERIFY(!m_upside_down);
return card_painter.card_front_highlighted(m_suit, m_rank);
}
@@ -46,12 +46,12 @@ void Card::save_old_position()
m_old_position_valid = true;
}
-void Card::clear_and_paint(GUI::Painter& painter, Color background_color)
+void Card::clear_and_paint(GUI::Painter& painter, Color background_color, bool highlighted)
{
if (is_old_position_valid())
clear(painter, background_color);
- paint(painter);
+ paint(painter, highlighted);
save_old_position();
}
diff --git a/Userland/Libraries/LibCards/Card.h b/Userland/Libraries/LibCards/Card.h
index 5cfd9d53cc..72101ff0af 100644
--- a/Userland/Libraries/LibCards/Card.h
+++ b/Userland/Libraries/LibCards/Card.h
@@ -104,13 +104,12 @@ public:
void set_moving(bool moving) { m_moving = moving; }
void set_upside_down(bool upside_down) { m_upside_down = upside_down; }
void set_inverted(bool inverted) { m_inverted = inverted; }
- void set_highlighted(bool highlighted) { m_highlighted = highlighted; }
void save_old_position();
- void paint(GUI::Painter&) const;
+ void paint(GUI::Painter&, bool highlighted = false) const;
void clear(GUI::Painter&, Color background_color) const;
- void clear_and_paint(GUI::Painter& painter, Color background_color);
+ void clear_and_paint(GUI::Painter& painter, Color background_color, bool highlighted);
private:
Card(Suit, Rank);
@@ -123,7 +122,6 @@ private:
bool m_moving { false };
bool m_upside_down { false };
bool m_inverted { false };
- bool m_highlighted { false };
};
enum class Shuffle {
diff --git a/Userland/Libraries/LibCards/CardStack.cpp b/Userland/Libraries/LibCards/CardStack.cpp
index 1e0e65b4fc..9e7c297225 100644
--- a/Userland/Libraries/LibCards/CardStack.cpp
+++ b/Userland/Libraries/LibCards/CardStack.cpp
@@ -43,8 +43,18 @@ void CardStack::paint(GUI::Painter& painter, Gfx::Color background_color)
return false;
if (!is_empty() && (m_stack.size() != number_of_moving_cards))
return false;
- painter.fill_rect_with_rounded_corners(m_base, background_color.darkened(0.5), Card::card_radius);
- painter.fill_rect_with_rounded_corners(m_base.shrunken(2, 2), background_color, Card::card_radius - 1);
+
+ auto paint_rect = m_base;
+ painter.fill_rect_with_rounded_corners(paint_rect, background_color.darkened(0.5), Card::card_radius);
+ paint_rect.shrink(2, 2);
+
+ if (m_highlighted) {
+ auto background_complement = background_color.xored(Color::White);
+ painter.fill_rect_with_rounded_corners(paint_rect, background_complement, Card::card_radius - 1);
+ paint_rect.shrink(4, 4);
+ }
+
+ painter.fill_rect_with_rounded_corners(paint_rect, background_color, Card::card_radius - 1);
return true;
};
@@ -83,9 +93,11 @@ void CardStack::paint(GUI::Painter& painter, Gfx::Color background_color)
return;
}
- for (auto& card : m_stack) {
- if (!card.is_moving())
- card.clear_and_paint(painter, Gfx::Color::Transparent);
+ for (size_t i = 0; i < m_stack.size(); ++i) {
+ if (auto& card = m_stack[i]; !card.is_moving()) {
+ auto highlighted = m_highlighted && (i == m_stack.size() - 1);
+ card.clear_and_paint(painter, Gfx::Color::Transparent, highlighted);
+ }
}
}
diff --git a/Userland/Libraries/LibCards/CardStack.h b/Userland/Libraries/LibCards/CardStack.h
index b558c18a19..bebbb10a39 100644
--- a/Userland/Libraries/LibCards/CardStack.h
+++ b/Userland/Libraries/LibCards/CardStack.h
@@ -53,6 +53,8 @@ public:
void paint(GUI::Painter&, Gfx::Color background_color);
void clear();
+ void set_highlighted(bool highlighted) { m_highlighted = highlighted; }
+
private:
struct StackRules {
uint8_t shift_x { 0 };
@@ -92,6 +94,7 @@ private:
Type m_type { Type::Invalid };
StackRules m_rules;
Gfx::IntRect m_base;
+ bool m_highlighted { false };
};
}