150 lines
8.7 KiB
C++
150 lines
8.7 KiB
C++
#include "MainFrame.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, // указываем то, что у этого окна нет родителя, оно может иметь любой 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(); // Создание пунктов меню
|
||
bindMenu(); // Подключение обработчиков пунктов меню
|
||
|
||
Bind(wxEVT_SHOW, [this](wxShowEvent& _) -> void { // обработчик события отображения окна
|
||
if (!layoutPath.IsEmpty() || openLayout()) // если пользователь выбрал схему
|
||
startGame();
|
||
});
|
||
|
||
Bind(END_EVT, [this](wxCommandEvent& evt) -> void { // обработчик кастомного события окончания игры
|
||
wxMessageDialog dlg(this, _("Хотите сыграть снова?"),
|
||
_("Игра окончена"), wxYES_NO); // Создаём диалог с предложением начать игру заново
|
||
dlg.SetExtendedMessage(_("Поздравляем, вы закончили игру за ") +
|
||
evt.GetString()); // Устанавливаем время, затраченное на полное выполнение карты
|
||
if (dlg.ShowModal() == wxID_YES) // Если пользователь хочет,
|
||
startGame(); // начинаме игру заново
|
||
});
|
||
|
||
CreateStatusBar(2); // Создаём статусбар с двумя колонками
|
||
|
||
panel = new GamePanel(this); // Создаём
|
||
panel->SetFocus(); // и показываем панель, где отрисовывается игровое поле
|
||
}
|
||
|
||
void MainFrame::initMenu() {
|
||
wxMenu* menuGame = new wxMenu; // Создаём подменю
|
||
menuGame->Append(IDM_New_Game, _("Начать сначала\tCTRL+N")); // Создаем пункт меню с id обработчика IDM_New_Game, далее аналогично
|
||
menuGame->Append(IDM_Open, _("Открыть карту\tCTRL+O"));
|
||
menuGame->AppendCheckItem(IDM_Solveable, _("Генерировать решаемую карту"));
|
||
menuGame->AppendSeparator(); // Добавляем горизонтальный разделитель в меню
|
||
menuGame->Append(IDM_Undo, _("Отменить ход"));
|
||
menuGame->Append(IDM_Reshuffle, _("Перемешать поле"));
|
||
menuGame->AppendSeparator();
|
||
menuGame->Append(IDM_Exit, _("Выход\tCTRL+Q"));
|
||
|
||
wxMenu* menuHelp = new wxMenu;
|
||
menuHelp->Append(IDM_Help, _("Инструкция"));
|
||
menuHelp->Append(IDM_Rules, _("Правила игры"));
|
||
menuHelp->Append(IDM_About, _("О программе"));
|
||
|
||
wxMenuBar* menuBar = new wxMenuBar; // Создаём меню бар,
|
||
menuBar->Append(menuGame, _("Игра")); // куда подключаем созданные выше подменю
|
||
menuBar->Append(menuHelp, _("Помощь"));
|
||
|
||
SetMenuBar(menuBar); // И устанавливаем его как основной для этой панели
|
||
}
|
||
|
||
void MainFrame::bindMenu() {
|
||
Bind(
|
||
wxEVT_MENU, [this](wxCommandEvent& _) -> void { Close(); }, IDM_Exit); // Вешаем обработчик закртытия игры при выборе соответствующего пункта меню
|
||
|
||
Bind( // Вешаем обработчик для открытия схемы и запуска соответствующей игры
|
||
wxEVT_MENU,
|
||
[this](wxCommandEvent& _) -> void {
|
||
if (openLayout()) // запрашиваем в диалоге путь до файла карты и если получаем,
|
||
startGame(); // запускаем игру
|
||
},
|
||
IDM_Open);
|
||
|
||
Bind( // Вешаем обработчик для открытия диалога с "помощью"
|
||
wxEVT_MENU,
|
||
[this](wxCommandEvent& _) -> void {
|
||
(new TextDlg(this, wxID_ANY, _("Помощь"), TXTContents::help))->Show();
|
||
},
|
||
IDM_Help);
|
||
|
||
Bind( // Вешаем обработчик для открытия диалога с "правилами"
|
||
wxEVT_MENU,
|
||
[this](wxCommandEvent& _) -> void {
|
||
(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(); // если путь был, или открыт в диалоге, начинаем игру
|
||
},
|
||
IDM_New_Game);
|
||
|
||
Bind( // Вешаем обработчик для установки режима генерации поля
|
||
wxEVT_MENU,
|
||
[this](wxCommandEvent& evt) -> void { solveable = evt.IsChecked(); }, // устанавливаем флаг способа генерации поля согласно значению чекбокса в меню
|
||
IDM_Solveable);
|
||
|
||
Bind( // Вешаем обработчик для отмены хода
|
||
wxEVT_MENU, [this](wxCommandEvent& _) -> void { panel->undo(); },
|
||
IDM_Undo);
|
||
|
||
Bind( // Вешаем обработчик для перемешивания поля
|
||
wxEVT_MENU,
|
||
[this](wxCommandEvent& _) -> void { panel->reshuffle(solveable); },
|
||
IDM_Reshuffle);
|
||
}
|
||
|
||
/**
|
||
* Shows a file opening dialog asking for .smlf file if succed, sets its path to
|
||
* layoutPath
|
||
* @return true if user have chosen a file, false if cancelled
|
||
*/
|
||
bool MainFrame::openLayout() {
|
||
wxFileDialog openFileDlg( // Создаём диалог для запроса файла схемы
|
||
this, _("Открыть карту"),
|
||
dataDirPath + wxFileName::GetPathSeparator() + _("layouts"), // Стандартный путь до файлов приложения
|
||
_("Turtle.smlf"), _("Файлы Mahjong карт (*.smlf)|*.smlf"), // Стандартный файл и поддерживаемые форматы файлов
|
||
wxFD_OPEN | wxFD_FILE_MUST_EXIST);
|
||
|
||
if (openFileDlg.ShowModal() == wxID_CANCEL) // если пользователь не выбрал файл
|
||
return false; // возвращаем false, т.к. открытие карты не успешно
|
||
|
||
layoutPath = openFileDlg.GetPath(); // сохраняем путь до файла
|
||
return true;
|
||
}
|
||
|
||
void MainFrame::startGame() {
|
||
panel->Start(layoutPath, solveable, // запускаем игру с путём до схемы, выбранным режимом заполнения поля
|
||
setMinSize_fn // и проброшенной функцией установки минимального размера окна
|
||
);
|
||
}
|