Added updating size on bigger board opening and set contents of help, rules and about dialogs

This commit is contained in:
Dmitriy Shishkov 2022-06-09 19:54:17 +03:00
parent af1f429c01
commit de5621e925
No known key found for this signature in database
GPG Key ID: 26720CB2A9608C97
9 changed files with 151 additions and 58 deletions

View File

@ -1,4 +0,0 @@
#include "AboutDlg.h"
AboutDlg::AboutDlg(wxWindow* parent, wxWindowID id)
: wxDialog::wxDialog(parent, id, _("О программе")) {}

View File

@ -1,11 +0,0 @@
#ifndef ABOUTDLG_H
#define ABOUTDLG_H
#include "wxw.h"
class AboutDlg : public wxDialog {
public:
AboutDlg(wxWindow* parent, wxWindowID id);
};
#endif

View File

@ -1,17 +1,24 @@
#include "MainFrame.h"
#include "AboutDlg.h"
#include "HelpDlg.h"
#include "RulesDlg.h"
#include "TextDlg.h"
#include "TXTContents.h"
#include <wx/filename.h>
#include <wx/stdpaths.h>
#include "events.h"
#include "resources/icon.xpm"
MainFrame::MainFrame()
: wxFrame(nullptr, wxID_ANY, _("Маджонг (пасьянс)"), wxDefaultPosition,
wxSize(800, 600)),
dataDirPath(wxStandardPaths::Get().GetUserDataDir()) {
: wxFrame(nullptr, wxID_ANY, _("Маджонг (пасьянс)"), wxDefaultPosition, // указываем то, что у этого окна нет родителя, оно может иметь любой id, так же устанавливаем заголовок и позицию на усмотрение оконного менеджера
wxSize(800, 600)), // устанавливаем стандартный размер окна
dataDirPath(wxStandardPaths::Get().GetUserDataDir()), // сохраняем стандартный путь до ресурсов программы
setMinSize_fn{[this](const wxSize& size) -> void { // создаём лямбду с замыканием внутри неё методов для установки минимального размера окна и передачи её как аргумент в метод другого класса
this->SetMinClientSize(size); // устанавливаем минимальный размер окна для оконного менеджера
const auto& curr = this->GetClientSize(); // считываем нынешний размер окна
this->SetClientSize({mmax(size.x, curr.x), mmax(size.y, curr.y)}); // если нынешний размер окна меньше, чем требует карта, увеличиваем ту сторону окна до минимальной необходимой
}} {
SetIcon(logo_icon);
initMenu(); // Создание пунктов меню
@ -67,43 +74,43 @@ void MainFrame::bindMenu() {
Bind( // Вешаем обработчик для открытия схемы и запуска соответствующей игры
wxEVT_MENU,
[this](wxCommandEvent& _) -> void {
if (openLayout())
startGame();
if (openLayout()) // запрашиваем в диалоге путь до файла карты и если получаем,
startGame(); // запускаем игру
},
IDM_Open);
Bind( // Вешаем обработчик для открытия диалога с "помощью"
wxEVT_MENU,
[this](wxCommandEvent& _) -> void {
(new HelpDlg(this, wxID_ANY))->Show();
(new TextDlg(this, wxID_ANY, _("Помощь"), TXTContents::help))->Show();
},
IDM_Help);
Bind( // Вешаем обработчик для открытия диалога "о программе"
wxEVT_MENU,
[this](wxCommandEvent& _) -> void {
(new AboutDlg(this, wxID_ANY))->Show();
},
IDM_About);
Bind( // Вешаем обработчик для открытия диалога с "правилами"
wxEVT_MENU,
[this](wxCommandEvent& _) -> void {
(new RulesDlg(this, wxID_ANY))->Show();
(new TextDlg(this, wxID_ANY, _("Правила игры"), TXTContents::rules))->Show();
},
IDM_Rules);
Bind( // Вешаем обработчик для открытия диалога "о программе"
wxEVT_MENU,
[this](wxCommandEvent& _) -> void {
(new TextDlg(this, wxID_ANY, _("О программе"), TXTContents::about))->Show();
},
IDM_About);
Bind( // Вешаем обработчик для запуска новой игры
wxEVT_MENU,
[this](wxCommandEvent& _) -> void {
if (!layoutPath.IsEmpty() || openLayout())
startGame();
if (!layoutPath.IsEmpty() || openLayout()) // если ещё не выбран файл с картой, открываем диалог для его выбора
startGame(); // если путь был, или открыт в диалоге, начинаем игру
},
IDM_New_Game);
Bind( // Вешаем обработчик для установки режима генерации поля
wxEVT_MENU,
[this](wxCommandEvent& evt) -> void { solveable = evt.IsChecked(); },
[this](wxCommandEvent& evt) -> void { solveable = evt.IsChecked(); }, // устанавливаем флаг способа генерации поля согласно значению чекбокса в меню
IDM_Solveable);
Bind( // Вешаем обработчик для отмены хода
@ -128,10 +135,10 @@ bool MainFrame::openLayout() {
_("Turtle.smlf"), _("Файлы Mahjong карт (*.smlf)|*.smlf"), // Стандартный файл и поддерживаемые форматы файлов
wxFD_OPEN | wxFD_FILE_MUST_EXIST);
if (openFileDlg.ShowModal() == wxID_CANCEL)
return false;
if (openFileDlg.ShowModal() == wxID_CANCEL) // если пользователь не выбрал файл
return false; // возвращаем false, т.к. открытие карты не успешно
layoutPath = openFileDlg.GetPath();
layoutPath = openFileDlg.GetPath(); // сохраняем путь до файла
return true;
}

View File

@ -5,9 +5,6 @@
#include "GamePanel.h"
#include <wx/filename.h>
#include <wx/stdpaths.h>
class MainFrame : public wxFrame {
public:
MainFrame();
@ -23,8 +20,7 @@ private:
bool openLayout();
void startGame();
const std::function<void(const wxSize&)> setMinSize_fn =
[this](const wxSize& size) -> void { this->SetMinClientSize(size); };
const std::function<void(const wxSize&)> setMinSize_fn;
const wxString dataDirPath;

View File

@ -1,4 +0,0 @@
#include "RulesDlg.h"
RulesDlg::RulesDlg(wxWindow* parent, wxWindowID id)
: wxDialog::wxDialog(parent, id, _("Правила игры")) {}

View File

@ -1,11 +0,0 @@
#ifndef RULESDLG_H
#define RULESDLG_H
#include "wxw.h"
class RulesDlg : public wxDialog {
public:
RulesDlg(wxWindow* parent, wxWindowID id);
};
#endif

74
TXTContents.h Normal file
View File

@ -0,0 +1,74 @@
#ifndef TXTCONTENTS_H
#define TXTCONTENTS_H
#include "wxw.h"
namespace TXTContents {
// clang-format off
const wxString help(_(
" При запуске программы вы получили запрос на выбор файла с картой. В случае, если вы его выбрали, перед вами должно быть игровое поле и вы можете приступать к игре, при необходимости ознакомившись с правилами (F1, или в меню \"Помощь->Правила игры\").\n"
" Для выбора камня, необходимо нажать на него левой кнопкой мыши. Если он доступен для удаления, он подсветится зелёным цветом. При выборе второго такого же они оба исчезают. \n При клике на другой доступный камень (не считающийся с ним одинаковым), выделение с предыдущего снимается и выделяется другой. \n"
" При желании вы можете изменить размеры окна. При этом все элементы окна и игровое поле подстроятся под новый. \n"
" Для того, чтобы начать игру сначала, можно нажать в меню \"Игра->Начать сначала\" (или Ctrl+N). \n"
" Если вы хотите сменить карту, выберите в меню \"Игра->Открыть карту\" (или Ctrl+O). \n"
" Приложение поддерживает два режима генерации карты: полностью случайный и имеющий хотя бы один способ решения. Для выбора, в каком режиме генерировать, в меню есть флажок \"Игра->Генерировать решаемую карту\". \n"
" Если в процессе игры вам понадобилось отменить ход, или у вас не осталось ходов, вы можете воспользоваться кнопками \"Игра->Отменить ход\" и \"Игра->Перемешать\" соответственно. \n"
" Для выхода из игры, нажмите \"Игра->Выход\" (или Ctrl+Q) \n"
" Во вкладке \"Помощь\" так же расположены сведения \"О программе\", где приведены список использованных ресурсов и лицензии. \n"
" В нижней части экрана расположена строка состояния. В ней слева выводится время, прошедшее с начала игры, или подскаски по пунктам меню при наведении на них мыши. Справа выводится процент оставшихся камней, которые необходимо убрать, то есть, в начале игры это 100%, когда останется половина камней, будет 50%, а когда будут убраны все, 0%."
));
// clang-format on
// clang-format off
const wxString rules(_(
" Игра Маджонг настольная игра для одного человека, напоминающая карточный пасьянс. В ней используется набор из 144 костей таких же как в одноимённой азартной игре. Они раскладываются на поле в случайном порядке, образуя многослойную фигуру. \n"
" В игре используются фишки трёх видов: масти, козыри и цветы. Существуют три масти медяки, бамбуки и тьмы, пронумерованные от одного до девяти, по четыре комплекта каждой. Козыри подразделяются на ветры и драконов. Есть четыре ветра Восточный, Южный, Западный и Северный по 4 шт. каждого вида. И три дракона Красный, Зелёный и Белый по 4 шт. каждого вида. Цветы делятся на 4 цветка слива, орхидея, хризантема и бамбук и 4 времени года весна, лето, зима и осень, каждых по 1 шт. \n"
" Цель игры состоит в том, чтобы, убирая пары одинаковых не заблокированных фишек, очистить поле. Заблокированными считаются фишки, накрытые другими, или не имеющие свободной правой, или левой стороны. \n"
" Одинаковыми считаются медяки, козыри и цветы одной масти и достоинства, одинаковые драконы и ветра. Все четыре кости-цветка и времени года считаются одинаковыми."
));
// clang-format on
// clang-format off
const wxString about(_(
"Приложение wxMahjong (Solitare) \n"
"Разработчик: Шишков Дмитрий Андреевич (dm1sh) \n"
"Группа: 1181 \n"
"Проверяющий: Ситников И.Ю. \n"
"\n"
" Приложение разработано с использованием кроссплатформенной библиотеки wxWidgets. Она использовалась для создания интерфейса программы и работы с файлами схем карт.\n"
" Приложение поддерживает схемы карт в формате .smlf (подробнее можно прочитать здесь https://star.physics.yale.edu/~ullrich/software/SolitaireMahjong/layouts.html). В состав распространяемого набора файлов входят схемы, взятые из программы Томаса Уллрича (https://star.physics.yale.edu/~ullrich/), распространяемы по лицении GNU GPL. \n"
" В качестве иконок используется набор, нарисованный FluffyStuff (https://github.com/FluffyStuff/riichi-mahjong-tiles), лицензированные по CC BY 4.0 \n"
"\n"
" Лицензии программы и используемых сторонних ресурсов: \n"
"\n"
"wxMahjong (Solitare):\n"
"\n"
"Copyright 2022 dm1sh\n"
"\n"
"Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n"
"\n"
"The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n"
"\n"
"THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n"
"\n"
"\n"
"Схемы smlf:\n"
"\n"
"Solitaire Mahjong 2.2\n"
"\n"
"Copyright (C) 2005-2017 Thomas S. Ullrich\n"
"\n"
"This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or any later version.\n"
"\n"
"This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n"
"\n"
"You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.\n"
"\n"
"Картинок для камней:\n"
"\n"
"This work is licensed under the Creative Commons Attribution 4.0 International License. To view a copy of this license, visit http://creativecommons.org/licenses/by/4.0/.\n"
));
// clang-format on
}
#endif

35
TextDlg.cpp Normal file
View File

@ -0,0 +1,35 @@
#include "TextDlg.h"
#include "utils.h"
TextDlg::TextDlg(wxWindow* parent, wxWindowID id, const wxString& title, const wxString& content)
: wxDialog::wxDialog(parent, id, title) {
wxBoxSizer* sizer = new wxBoxSizer(wxVERTICAL); // создаём сайзер для окна прокрутки
SetSizer(sizer); // устанавливаем его как главный сайзер окна
wxScrolledWindow* scrollableWnd = new wxScrolledWindow( // создаём окно прокрутки
this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxVSCROLL); // указываем стандартные параметры и говорим, что прокрутка должна быть только вертикальная
sizer->Add(scrollableWnd, 1, wxGROW | wxALL, 5); // добавляем в сайзер окно прокрутки с отступами по краям в 5 пикселей
wxStaticText* text = // внутри окна прокрутки создаём статический текст, содержащий `content`, поддерживающий перенос строки
new wxStaticText(scrollableWnd, wxID_ANY, content, wxDefaultPosition,
wxDefaultSize, wxSP_WRAP);
const wxClientDC dc(text); // создаём dc, используя для него настройки статического текста
const wxSize lineSize = dc.GetTextExtent(wxString('W', 40U)); // получаем из dc размеры строчки из 40 символов 'W' (так как текст удобнее всего читать, если в нём около 40-60 символов в строке)
scrollableWnd->SetScrollbars(lineSize.x, lineSize.y, 0, 0); // устанавливаем скорость скролла (количество пикселей, прокручиваемых при одинарном прокручивании колеса мыши, или нажатие кнопки)
text->Wrap(lineSize.x); // Делаем перенос строк для того, чтобы вместить текст в ширину строки
auto textSize = text->GetClientSize(); // получаем размер статического текста
scrollableWnd->SetVirtualSize(textSize.x, textSize.y); // устанавливаем виртуальный размер окна прокрутки равным размерам статического текста
SetClientSize( // размер видимого окна устанавливаем равным
textSize.x + 10, // по ширине: ширина текста
mmin(textSize.y, lineSize.y * 30) + 10); // по высоте: минимум из реальной высоты текста, или 30 строк
// + отступы по 5 пикселей с обеих сторон
}

11
TextDlg.h Normal file
View File

@ -0,0 +1,11 @@
#ifndef TEXTDLG_H
#define TEXTDLG_H
#include "wxw.h"
class TextDlg : public wxDialog {
public:
TextDlg(wxWindow* parent, wxWindowID id, const wxString& title, const wxString& content);
};
#endif