From 517c03f92031ea2767e9fb5d1a58c4d1e9e40f4a Mon Sep 17 00:00:00 2001 From: thankyouverycool <66646555+thankyouverycool@users.noreply.github.com> Date: Thu, 4 Aug 2022 10:16:26 -0400 Subject: [PATCH] Minesweeper: Update GML and fix layout issues Converts Minesweeper's main widget to GML, polishes the custom game window, formats the clock as human readable digital time, and defers invoking Field's callback until the main widget has finished relayout. Fixes inability to downsize the main window when shrinking field size. --- Userland/Games/Minesweeper/CMakeLists.txt | 2 + .../Games/Minesweeper/CustomGameDialog.cpp | 3 +- Userland/Games/Minesweeper/Field.cpp | 9 ++-- .../MinesweeperCustomGameWindow.gml | 12 +++-- .../Games/Minesweeper/MinesweeperWindow.gml | 52 +++++++++++++++++++ Userland/Games/Minesweeper/main.cpp | 50 ++++-------------- 6 files changed, 77 insertions(+), 51 deletions(-) create mode 100644 Userland/Games/Minesweeper/MinesweeperWindow.gml diff --git a/Userland/Games/Minesweeper/CMakeLists.txt b/Userland/Games/Minesweeper/CMakeLists.txt index ac76c1bb5f..5c5e219068 100644 --- a/Userland/Games/Minesweeper/CMakeLists.txt +++ b/Userland/Games/Minesweeper/CMakeLists.txt @@ -5,9 +5,11 @@ serenity_component( ) compile_gml(MinesweeperCustomGameWindow.gml MinesweeperCustomGameWindowGML.h minesweeper_custom_game_window_gml) +compile_gml(MinesweeperWindow.gml MinesweeperWindowGML.h minesweeper_window_gml) set(SOURCES MinesweeperCustomGameWindowGML.h + MinesweeperWindowGML.h CustomGameDialog.cpp Field.cpp main.cpp diff --git a/Userland/Games/Minesweeper/CustomGameDialog.cpp b/Userland/Games/Minesweeper/CustomGameDialog.cpp index ce5194d767..fd52f43932 100644 --- a/Userland/Games/Minesweeper/CustomGameDialog.cpp +++ b/Userland/Games/Minesweeper/CustomGameDialog.cpp @@ -42,8 +42,7 @@ void CustomGameDialog::set_max_mines() CustomGameDialog::CustomGameDialog(Window* parent_window) : Dialog(parent_window) { - resize(305, 90); - center_on_screen(); + resize(300, 82); set_resizable(false); set_title("Custom game"); diff --git a/Userland/Games/Minesweeper/Field.cpp b/Userland/Games/Minesweeper/Field.cpp index 46a5628e9b..01059d6958 100644 --- a/Userland/Games/Minesweeper/Field.cpp +++ b/Userland/Games/Minesweeper/Field.cpp @@ -7,6 +7,7 @@ #include "Field.h" #include +#include #include #include #include @@ -115,7 +116,7 @@ Field::Field(GUI::Label& flag_label, GUI::Label& time_label, GUI::Button& face_b m_timer = Core::Timer::create_repeating( 1000, [this] { ++m_time_elapsed; - m_time_label.set_text(String::number(m_time_elapsed)); + m_time_label.set_text(human_readable_digital_time(m_time_elapsed)); }, this); m_mine_bitmap = Gfx::Bitmap::try_load_from_file("/res/icons/minesweeper/mine.png"sv).release_value_but_fixme_should_propagate_errors(); @@ -199,7 +200,7 @@ void Field::reset() m_first_click = true; set_updates_enabled(false); m_time_elapsed = 0; - m_time_label.set_text("0"); + m_time_label.set_text("00:00"); m_flags_left = m_mine_count; m_flag_label.set_text(String::number(m_flags_left)); m_timer->stop(); @@ -520,7 +521,9 @@ void Field::set_field_size(Difficulty difficulty, size_t rows, size_t columns, s m_mine_count = mine_count; set_fixed_size(frame_thickness() * 2 + m_columns * square_size(), frame_thickness() * 2 + m_rows * square_size()); reset(); - m_on_size_changed(Gfx::IntSize(min_size())); + deferred_invoke([this] { + m_on_size_changed(Gfx::IntSize(min_size())); + }); } void Field::set_single_chording(bool enabled) diff --git a/Userland/Games/Minesweeper/MinesweeperCustomGameWindow.gml b/Userland/Games/Minesweeper/MinesweeperCustomGameWindow.gml index 754060ae8e..9230be05f9 100644 --- a/Userland/Games/Minesweeper/MinesweeperCustomGameWindow.gml +++ b/Userland/Games/Minesweeper/MinesweeperCustomGameWindow.gml @@ -2,13 +2,14 @@ fill_with_background_color: true layout: @GUI::VerticalBoxLayout { margins: [4] + spacing: 6 } @GUI::GroupBox { title: "Field" autosize: true layout: @GUI::HorizontalBoxLayout { - margins: [16, 6, 6] + margins: [6] } @GUI::Label { @@ -23,7 +24,7 @@ fixed_width: 40 } - @GUI::VerticalSeparator {} + @GUI::Layout::Spacer {} @GUI::Label { text: "Rows: " @@ -37,7 +38,7 @@ fixed_width: 40 } - @GUI::VerticalSeparator {} + @GUI::Layout::Spacer {} @GUI::Label { text: "Mines: " @@ -53,8 +54,9 @@ } @GUI::Widget { - max_height: 24 - layout: @GUI::HorizontalBoxLayout {} + layout: @GUI::HorizontalBoxLayout { + spacing: 10 + } @GUI::Layout::Spacer {} diff --git a/Userland/Games/Minesweeper/MinesweeperWindow.gml b/Userland/Games/Minesweeper/MinesweeperWindow.gml new file mode 100644 index 0000000000..b4ca40408e --- /dev/null +++ b/Userland/Games/Minesweeper/MinesweeperWindow.gml @@ -0,0 +1,52 @@ +@GUI::Widget { + fill_with_background_color: true + layout: @GUI::VerticalBoxLayout { + spacing: 0 + } + + @GUI::HorizontalSeparator { + name: "separator" + fixed_height: 2 + } + + @GUI::Widget { + name: "container" + fixed_height: 36 + layout: @GUI::HorizontalBoxLayout {} + + @GUI::Layout::Spacer {} + + @GUI::ImageWidget { + name: "flag_image" + bitmap: "/res/icons/minesweeper/flag.png" + } + + @GUI::Label { + name: "flag_label" + autosize: true + } + + @GUI::Layout::Spacer {} + + @GUI::Button { + name: "face_button" + fixed_size: [36, 36] + focus_policy: "TabFocus" + button_style: "Coolbar" + } + + @GUI::Layout::Spacer {} + + @GUI::ImageWidget { + name: "time_image" + bitmap: "/res/icons/minesweeper/timer.png" + } + + @GUI::Label { + name: "time_label" + autosize: true + } + + @GUI::Layout::Spacer {} + } +} diff --git a/Userland/Games/Minesweeper/main.cpp b/Userland/Games/Minesweeper/main.cpp index 883271acc4..91d5a5fd59 100644 --- a/Userland/Games/Minesweeper/main.cpp +++ b/Userland/Games/Minesweeper/main.cpp @@ -7,6 +7,7 @@ #include "CustomGameDialog.h" #include "Field.h" #include +#include #include #include #include @@ -46,51 +47,18 @@ ErrorOr serenity_main(Main::Arguments arguments) auto window = TRY(GUI::Window::try_create()); window->set_resizable(false); window->set_title("Minesweeper"); - window->resize(139, 175); + window->resize(139, 177); auto widget = TRY(window->try_set_main_widget()); - (void)TRY(widget->try_set_layout()); - widget->layout()->set_spacing(0); - - auto top_line = TRY(widget->try_add(Gfx::Orientation::Horizontal)); - top_line->set_fixed_height(2); - - auto container = TRY(widget->try_add()); - container->set_fill_with_background_color(true); - container->set_fixed_height(36); - (void)TRY(container->try_set_layout()); - - container->layout()->add_spacer(); - - auto flag_image = TRY(container->try_add()); - flag_image->set_icon(Gfx::Bitmap::try_load_from_file("/res/icons/minesweeper/flag.png"sv).release_value_but_fixme_should_propagate_errors()); - flag_image->set_fixed_width(16); - - auto flag_label = TRY(container->try_add()); - flag_label->set_autosize(true); - flag_label->set_text_alignment(Gfx::TextAlignment::CenterLeft); - - container->layout()->add_spacer(); - - auto face_button = TRY(container->try_add()); - face_button->set_focus_policy(GUI::FocusPolicy::TabFocus); - face_button->set_button_style(Gfx::ButtonStyle::Coolbar); - face_button->set_fixed_size(36, 36); - - container->layout()->add_spacer(); - - auto time_image = TRY(container->try_add()); - time_image->set_fixed_width(16); - time_image->set_icon(Gfx::Bitmap::try_load_from_file("/res/icons/minesweeper/timer.png"sv).release_value_but_fixme_should_propagate_errors()); - - auto time_label = TRY(container->try_add()); - time_label->set_fixed_width(50); - time_label->set_text_alignment(Gfx::TextAlignment::CenterLeft); - - container->layout()->add_spacer(); + widget->load_from_gml(minesweeper_window_gml); + auto& separator = *widget->find_descendant_of_type_named("separator"); + auto& container = *widget->find_descendant_of_type_named("container"); + auto& flag_label = *widget->find_descendant_of_type_named("flag_label"); + auto& time_label = *widget->find_descendant_of_type_named("time_label"); + auto& face_button = *widget->find_descendant_of_type_named("face_button"); auto field = TRY(widget->try_add(flag_label, time_label, face_button, [&](auto size) { - size.set_height(size.height() + container->min_size().height().as_int()); + size.set_height(size.height() + separator.height() + container.height()); window->resize(size); }));