Card.h 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. /*
  2. * Copyright (c) 2020, Till Mayer <till.mayer@web.de>
  3. * Copyright (c) 2022, the SerenityOS developers.
  4. * Copyright (c) 2022, Sam Atkins <atkinssj@serenityos.org>
  5. * Copyright (c) 2023, David Ganz <david.g.ganz@gmail.com>
  6. *
  7. * SPDX-License-Identifier: BSD-2-Clause
  8. */
  9. #pragma once
  10. #include <AK/Format.h>
  11. #include <LibCore/EventReceiver.h>
  12. #include <LibGUI/Painter.h>
  13. #include <LibGfx/Bitmap.h>
  14. #include <LibGfx/CharacterBitmap.h>
  15. #include <LibGfx/Rect.h>
  16. namespace Cards {
  17. enum class Rank : u8 {
  18. Ace,
  19. Two,
  20. Three,
  21. Four,
  22. Five,
  23. Six,
  24. Seven,
  25. Eight,
  26. Nine,
  27. Ten,
  28. Jack,
  29. Queen,
  30. King,
  31. __Count
  32. };
  33. constexpr StringView card_rank_label(Rank rank)
  34. {
  35. switch (rank) {
  36. case Rank::Ace:
  37. return "A"sv;
  38. case Rank::Two:
  39. return "2"sv;
  40. case Rank::Three:
  41. return "3"sv;
  42. case Rank::Four:
  43. return "4"sv;
  44. case Rank::Five:
  45. return "5"sv;
  46. case Rank::Six:
  47. return "6"sv;
  48. case Rank::Seven:
  49. return "7"sv;
  50. case Rank::Eight:
  51. return "8"sv;
  52. case Rank::Nine:
  53. return "9"sv;
  54. case Rank::Ten:
  55. return "10"sv;
  56. case Rank::Jack:
  57. return "J"sv;
  58. case Rank::Queen:
  59. return "Q"sv;
  60. case Rank::King:
  61. return "K"sv;
  62. case Rank::__Count:
  63. VERIFY_NOT_REACHED();
  64. }
  65. VERIFY_NOT_REACHED();
  66. }
  67. enum class Suit : u8 {
  68. Clubs,
  69. Diamonds,
  70. Spades,
  71. Hearts,
  72. __Count
  73. };
  74. class Card final : public Core::EventReceiver {
  75. C_OBJECT(Card)
  76. public:
  77. static constexpr int width = 80;
  78. static constexpr int height = 110;
  79. static constexpr int card_count = to_underlying(Rank::__Count);
  80. static constexpr int card_radius = 7;
  81. virtual ~Card() override = default;
  82. Gfx::IntRect& rect() { return m_rect; }
  83. Gfx::IntRect const& rect() const { return m_rect; }
  84. Gfx::IntPoint position() const { return m_rect.location(); }
  85. Gfx::IntPoint old_position() const { return m_old_position; }
  86. Rank rank() const { return m_rank; }
  87. Suit suit() const { return m_suit; }
  88. bool is_old_position_valid() const { return m_old_position_valid; }
  89. bool is_moving() const { return m_moving; }
  90. bool is_upside_down() const { return m_upside_down; }
  91. bool is_inverted() const { return m_inverted; }
  92. bool is_previewed() const { return m_previewed; }
  93. bool is_disabled() const { return m_disabled; }
  94. Gfx::Color color() const { return (m_suit == Suit::Diamonds || m_suit == Suit::Hearts) ? Color::Red : Color::Black; }
  95. void set_position(const Gfx::IntPoint p) { m_rect.set_location(p); }
  96. void set_moving(bool moving) { m_moving = moving; }
  97. void set_upside_down(bool upside_down) { m_upside_down = upside_down; }
  98. void set_inverted(bool inverted) { m_inverted = inverted; }
  99. void set_previewed(bool previewed) { m_previewed = previewed; }
  100. void set_disabled(bool disabled) { m_disabled = disabled; }
  101. void save_old_position();
  102. void paint(GUI::Painter&, bool highlighted = false) const;
  103. void clear(GUI::Painter&, Color background_color) const;
  104. void clear_and_paint(GUI::Painter& painter, Color background_color, bool highlighted);
  105. private:
  106. Card(Suit, Rank);
  107. Gfx::IntRect m_rect;
  108. Gfx::IntPoint m_old_position;
  109. Suit m_suit;
  110. Rank m_rank;
  111. bool m_old_position_valid { false };
  112. bool m_moving { false };
  113. bool m_upside_down { false };
  114. bool m_inverted { false };
  115. bool m_previewed { false };
  116. bool m_disabled { false };
  117. };
  118. enum class Shuffle {
  119. No,
  120. Yes,
  121. };
  122. ErrorOr<Vector<NonnullRefPtr<Card>>> create_standard_deck(Shuffle);
  123. ErrorOr<Vector<NonnullRefPtr<Card>>> create_deck(unsigned full_club_suit_count, unsigned full_diamond_suit_count, unsigned full_heart_suit_count, unsigned full_spade_suit_count, Shuffle);
  124. }
  125. template<>
  126. struct AK::Formatter<Cards::Card> : Formatter<FormatString> {
  127. ErrorOr<void> format(FormatBuilder& builder, Cards::Card const& card)
  128. {
  129. StringView suit;
  130. switch (card.suit()) {
  131. case Cards::Suit::Clubs:
  132. suit = "C"sv;
  133. break;
  134. case Cards::Suit::Diamonds:
  135. suit = "D"sv;
  136. break;
  137. case Cards::Suit::Hearts:
  138. suit = "H"sv;
  139. break;
  140. case Cards::Suit::Spades:
  141. suit = "S"sv;
  142. break;
  143. default:
  144. VERIFY_NOT_REACHED();
  145. }
  146. return Formatter<FormatString>::format(builder, "{:>2}{}"sv, Cards::card_rank_label(card.rank()), suit);
  147. }
  148. };