mirror of
https://github.com/RGBCube/serenity
synced 2025-07-28 09:57:36 +00:00
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.
This commit is contained in:
parent
4d09b5c4ba
commit
517c03f920
6 changed files with 77 additions and 51 deletions
|
@ -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
|
||||
|
|
|
@ -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");
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
#include "Field.h"
|
||||
#include <AK/HashTable.h>
|
||||
#include <AK/NumberFormat.h>
|
||||
#include <AK/Queue.h>
|
||||
#include <AK/Random.h>
|
||||
#include <LibConfig/Client.h>
|
||||
|
@ -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)
|
||||
|
|
|
@ -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 {}
|
||||
|
||||
|
|
52
Userland/Games/Minesweeper/MinesweeperWindow.gml
Normal file
52
Userland/Games/Minesweeper/MinesweeperWindow.gml
Normal file
|
@ -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 {}
|
||||
}
|
||||
}
|
|
@ -7,6 +7,7 @@
|
|||
#include "CustomGameDialog.h"
|
||||
#include "Field.h"
|
||||
#include <AK/URL.h>
|
||||
#include <Games/Minesweeper/MinesweeperWindowGML.h>
|
||||
#include <LibConfig/Client.h>
|
||||
#include <LibCore/System.h>
|
||||
#include <LibDesktop/Launcher.h>
|
||||
|
@ -46,51 +47,18 @@ ErrorOr<int> 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<GUI::Widget>());
|
||||
(void)TRY(widget->try_set_layout<GUI::VerticalBoxLayout>());
|
||||
widget->layout()->set_spacing(0);
|
||||
|
||||
auto top_line = TRY(widget->try_add<GUI::SeparatorWidget>(Gfx::Orientation::Horizontal));
|
||||
top_line->set_fixed_height(2);
|
||||
|
||||
auto container = TRY(widget->try_add<GUI::Widget>());
|
||||
container->set_fill_with_background_color(true);
|
||||
container->set_fixed_height(36);
|
||||
(void)TRY(container->try_set_layout<GUI::HorizontalBoxLayout>());
|
||||
|
||||
container->layout()->add_spacer();
|
||||
|
||||
auto flag_image = TRY(container->try_add<GUI::Label>());
|
||||
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<GUI::Label>());
|
||||
flag_label->set_autosize(true);
|
||||
flag_label->set_text_alignment(Gfx::TextAlignment::CenterLeft);
|
||||
|
||||
container->layout()->add_spacer();
|
||||
|
||||
auto face_button = TRY(container->try_add<GUI::Button>());
|
||||
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<GUI::Label>());
|
||||
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<GUI::Label>());
|
||||
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<GUI::HorizontalSeparator>("separator");
|
||||
auto& container = *widget->find_descendant_of_type_named<GUI::Widget>("container");
|
||||
auto& flag_label = *widget->find_descendant_of_type_named<GUI::Label>("flag_label");
|
||||
auto& time_label = *widget->find_descendant_of_type_named<GUI::Label>("time_label");
|
||||
auto& face_button = *widget->find_descendant_of_type_named<GUI::Button>("face_button");
|
||||
auto field = TRY(widget->try_add<Field>(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);
|
||||
}));
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue