From a359219e33fdf3afb5ddfbb084563054a947b106 Mon Sep 17 00:00:00 2001 From: Loic Guegan Date: Sat, 12 Feb 2022 19:13:34 +0100 Subject: Create project --- examples/wxWidgets/CMakeLists.txt | 6 + examples/wxWidgets/MyHalfMove.cpp | 223 ++++++++++++++++++++++++++++++++++++++ examples/wxWidgets/MyHalfMove.hpp | 40 +++++++ examples/wxWidgets/demo.gif | Bin 0 -> 423585 bytes examples/wxWidgets/main.cpp | 197 +++++++++++++++++++++++++++++++++ 5 files changed, 466 insertions(+) create mode 100644 examples/wxWidgets/CMakeLists.txt create mode 100644 examples/wxWidgets/MyHalfMove.cpp create mode 100644 examples/wxWidgets/MyHalfMove.hpp create mode 100644 examples/wxWidgets/demo.gif create mode 100644 examples/wxWidgets/main.cpp (limited to 'examples/wxWidgets') diff --git a/examples/wxWidgets/CMakeLists.txt b/examples/wxWidgets/CMakeLists.txt new file mode 100644 index 0000000..af76025 --- /dev/null +++ b/examples/wxWidgets/CMakeLists.txt @@ -0,0 +1,6 @@ + +find_package(wxWidgets COMPONENTS core base REQUIRED) + +include(${wxWidgets_USE_FILE}) +add_executable(wxwidgets_example main.cpp MyHalfMove.cpp) +target_link_libraries(wxwidgets_example cgeditor ${wxWidgets_LIBRARIES}) diff --git a/examples/wxWidgets/MyHalfMove.cpp b/examples/wxWidgets/MyHalfMove.cpp new file mode 100644 index 0000000..6560006 --- /dev/null +++ b/examples/wxWidgets/MyHalfMove.cpp @@ -0,0 +1,223 @@ +#include "MyHalfMove.hpp" + +MyHalfMove::MyHalfMove(std::string move) { this->move = move; } +MyHalfMove::~MyHalfMove() {} + +void MyHalfMove::AddVariation(MyHalfMove *m) { + m->IsBlack = this->IsBlack; + m->Number = this->Number; + MyHalfMove::variations.push_back(m); + cgeditor::CGEHalfMove::variations.push_back(m); + m->SetParent(this); +} + +void MyHalfMove::SetMainline(MyHalfMove *m) { + if (!this->IsBlack) { + m->IsBlack = true; + m->Number = this->Number; + } else { + m->IsBlack = false; + m->Number = this->Number + 1; + } + MyHalfMove::mainline = m; + cgeditor::CGEHalfMove::MainLine = m; + if (m != NULL) { + m->SetParent(this); + } +} +void MyHalfMove::SetParent(MyHalfMove *m) { + MyHalfMove::parent = m; + CGEHalfMove::Parent = m; +} +void MyHalfMove::RemoveChild(MyHalfMove *m) { + std::uint32_t i = 0; + bool found = false; + for (i; i < MyHalfMove::variations.size(); i++) { + if (MyHalfMove::variations[i] == m) { + found = true; + break; + } + } + if (found) { + MyHalfMove::variations.erase(MyHalfMove::variations.begin() + i); + } + if (MyHalfMove::MainLine == m) { + MyHalfMove::MainLine = NULL; + } + cgeditor::CGEHalfMove::RemoveChild((CGEHalfMove *)m); +} + +MyHalfMove *MyHalfMove::GetParent() { return (parent); } + +MyHalfMove *MyHalfMove::GetRoot() { + MyHalfMove *m = this; + MyHalfMove *p = MyHalfMove::parent; + while (p != NULL) { + if (p->mainline != m) { + return (m); + } + m = p; + p = m->MyHalfMove::parent; + } + return (m); +} + +void MyHalfMove::SetAsMainline() { + MyHalfMove *root = GetRoot(); + MyHalfMove *lastRoot; + do { + lastRoot = root; + root->MyHalfMove::Promote(); + root = GetRoot(); + } while (root != lastRoot); + + // std::cout << IsVariation() << std::endl << std::flush; +} + +void MyHalfMove::Promote() { + if (MyHalfMove::parent != NULL) { + MyHalfMove *p = MyHalfMove::parent; + if (p->MyHalfMove::mainline != this) { + if (MyHalfMove::parent->MyHalfMove::parent != NULL) { + MyHalfMove *pp = MyHalfMove::parent->MyHalfMove::parent; + if (pp->MyHalfMove::mainline == p) { + pp->MyHalfMove::SetMainline(this); + } else { + pp->AddVariation(this); + pp->MyHalfMove::RemoveChild(p); + } + } + if (p->MyHalfMove::mainline == this) { + p->MyHalfMove::SetMainline(NULL); + } else { + p->MyHalfMove::RemoveChild(this); + } + this->AddVariation(p); + } + } +} + +bool MyHalfMove::IsVariation() { + MyHalfMove *m = this; + MyHalfMove *p = MyHalfMove::parent; + while (p != NULL) { + if (p->mainline != m) { + return (true); + } + m = p; + p = m->MyHalfMove::parent; + } + return (false); +} + +MyHalfMove *BuildExampleGame() { + MyHalfMove *m = new MyHalfMove("e4"); + MyHalfMove *toDisplay = m; + + MyHalfMove *m2 = new MyHalfMove("e5"); + m->SetMainline(m2); + m = m2; + + m2 = new MyHalfMove("Nf3"); + m->SetMainline(m2); + m = m2; + + m2 = new MyHalfMove("Nc6"); + m->SetMainline(m2); + m = m2; + + m2 = new MyHalfMove("Bc4"); + m->SetMainline(m2); + m->SetComment("Italian Opening"); + m = m2; + + m2 = new MyHalfMove("Bc5"); + m->SetMainline(m2); + m = m2; + + m2 = new MyHalfMove("c3"); + m2->SetComment("Giuoco Pianissimo"); + m->SetMainline(m2); + m = m2; + + m2 = new MyHalfMove("Nf6"); + m->SetMainline(m2); + m = m2; + + m2 = new MyHalfMove("o-o"); + m->SetMainline(m2); + m = m2; + + m2 = new MyHalfMove("d6"); + m->SetMainline(m2); + m = m2; + + m2 = new MyHalfMove("Nd2"); + m->SetMainline(m2); + m = m2; + + { + MyHalfMove *var = new MyHalfMove("Re1"); + var->SetComment("Also possible"); + m->AddVariation(var); + + MyHalfMove *var2 = new MyHalfMove("a6"); + var->SetMainline(var2); + var = var2; + + { + MyHalfMove *subvar = new MyHalfMove("Bg4"); + var->AddVariation(subvar); + + MyHalfMove *subvar2 = new MyHalfMove("Bb3"); + subvar->SetMainline(subvar2); + subvar = subvar2; + } + + var2 = new MyHalfMove("Bb3"); + var->SetMainline(var2); + var = var2; + + var2 = new MyHalfMove("Ba7"); + var->SetMainline(var2); + var = var2; + } + + m2 = new MyHalfMove("a6"); + m->SetMainline(m2); + m = m2; + + m2 = new MyHalfMove("Bb3"); + m->SetMainline(m2); + m = m2; + + m2 = new MyHalfMove("Ba7"); + m->SetMainline(m2); + m = m2; + + m2 = new MyHalfMove("Re1"); + m->SetMainline(m2); + m = m2; + + m2 = new MyHalfMove("o-o"); + m->SetMainline(m2); + m = m2; + + m2 = new MyHalfMove("Nf1"); + m->SetMainline(m2); + m = m2; + + m2 = new MyHalfMove("h6"); + m->SetMainline(m2); + m = m2; + + m2 = new MyHalfMove("Ng3"); + m->SetMainline(m2); + m = m2; + + m2 = new MyHalfMove("Nd7"); + m->SetMainline(m2); + m = m2; + + return (toDisplay); +} \ No newline at end of file diff --git a/examples/wxWidgets/MyHalfMove.hpp b/examples/wxWidgets/MyHalfMove.hpp new file mode 100644 index 0000000..dfb8860 --- /dev/null +++ b/examples/wxWidgets/MyHalfMove.hpp @@ -0,0 +1,40 @@ +#include "CGEditor.hpp" +#include + +/** + * @brief Create your custom half move class + * + * The implementation of the class should give you + * an overview of how to keep your move sync with the one of CGEditor + * + */ +class MyHalfMove : public cgeditor::CGEHalfMove { + MyHalfMove *parent = NULL; + MyHalfMove *mainline = NULL; + std::vector variations; + +public: + MyHalfMove(std::string move); + ~MyHalfMove(); + /// @brief Add variation to current move + void AddVariation(MyHalfMove *m); + /// @brief Remove the specified child from mainline and/or variations + void RemoveChild(MyHalfMove *m); + /// @brief Set value of the mailine + void SetMainline(MyHalfMove *m); + /// @brief Set this move as mainline + void SetAsMainline(); + /// @brief Promote the current move and submove + void Promote(); + /// @brief Check if current half move is within a variation + bool IsVariation(); + /// @brief Get the root of a variation + MyHalfMove* GetRoot(); + /// @brief Get parent of the current move + MyHalfMove* GetParent(); + /// @brief Set parent of the current move + void SetParent(MyHalfMove *m); +}; + +/// @brief Build the example game to use in the editor +MyHalfMove *BuildExampleGame(); \ No newline at end of file diff --git a/examples/wxWidgets/demo.gif b/examples/wxWidgets/demo.gif new file mode 100644 index 0000000..165b439 Binary files /dev/null and b/examples/wxWidgets/demo.gif differ diff --git a/examples/wxWidgets/main.cpp b/examples/wxWidgets/main.cpp new file mode 100644 index 0000000..20e6d3f --- /dev/null +++ b/examples/wxWidgets/main.cpp @@ -0,0 +1,197 @@ +#include +#ifndef WX_PRECOMP +#include +#endif + +#include "CGEditor.hpp" +#include "MyHalfMove.hpp" + +/** + * @brief CGEditor Window + * + */ +class MyFrame : public wxFrame, public cgeditor::CGEditor { + wxPaintDC *dc; + bool NeedRedraw = false; + +public: + MyFrame() + : wxFrame(NULL, wxID_ANY, "Hello World CGEditor"), CGEditor(), dc(NULL) { + CreateStatusBar(); + SetStatusText("CGEditor"); + // Create a game + CGEditor::status.Moves = BuildExampleGame(); + } + +private: + void OnExit(wxCommandEvent &event) { Close(true); } + + void OnPaint(wxPaintEvent &event) { + wxPaintDC current_dc(this); + dc = ¤t_dc; + + // Refresh canvas size + wxSize sz = GetClientSize(); + CGEditor::status.CanvasWidth = sz.GetWidth(); + CGEditor::status.CanvasHeight = sz.GetHeight(); + CGEditor::status.UseMoveImages = + false; // Piece image should be drawn before the move ? + + const wxPoint pt = wxGetMousePosition(); + CGEditor::status.MouseX = pt.x - this->GetScreenPosition().x; + CGEditor::status.MouseY = pt.y - this->GetScreenPosition().y; + CGEditor::Draw(); + } + + /** + * @brief We refresh CGEditor status according to events + * + * @param event + */ + void MouseEvent(wxMouseEvent &event) { + if (event.Dragging()) { + CGEditor::status.LeftClick = false; + CGEditor::status.IsDrag = true; + Refresh(); + } else if (event.LeftDown()) { + CGEditor::status.LeftClick = true; + Refresh(); + } else if (event.RightDown()) { + CGEditor::status.RightClick = true; + Refresh(); + } else if (event.GetWheelRotation() != 0) { + if (event.GetWheelRotation() < 0) { + CGEditor::status.EventVScroll = 50; + } else { + CGEditor::status.EventVScroll = -50; + } + Refresh(); + } + + // Should another draw of CGEditor be made? + if (NeedRedraw) { + Refresh(); + NeedRedraw = false; + } + } + + /** + * @brief Convenient fonction to center text + * + * @param e Element to center + * @return wxPoint The centered version of e according to wdWidget API + */ + wxPoint Middle(cgeditor::Element e) { + wxSize sz = dc->GetTextExtent(e.text); + return (wxPoint(e.x + (e.width - sz.GetWidth()) / 2, + e.y + (e.height - sz.GetHeight()) / 2)); + } + + /** + * @brief CGEditor is going to call this method with the elements to draw on + * the canvas + * + * @param e Element to draw + */ + void DrawElement(const cgeditor::Element &e) { + dc->SetPen(wxNullPen); + dc->SetBrush(*wxRED_BRUSH); + if (e.prop & cgeditor::Property::Rectangle) { + if (e.prop & cgeditor::Property::Scrollbarbg) { + dc->SetBrush(*wxCYAN_BRUSH); + } else if (e.prop & cgeditor::Property::Scrollbar) { + dc->SetBrush(*wxBLUE_BRUSH); + } else if (e.prop & cgeditor::Property::Margin) { + dc->SetBrush(*wxLIGHT_GREY_BRUSH); + } else if (e.prop & cgeditor::Property::Button) { + dc->SetBrush(*wxBLACK_BRUSH); + } + wxRect recToDraw(e.x, e.y, e.width, e.height); + dc->DrawRectangle(recToDraw); + } else if (e.prop & cgeditor::Property::Text || + e.prop & cgeditor::Property::Image) { + if (e.prop & cgeditor::Property::Image) { + // Draw your pieces images instead + dc->SetBrush(*wxRED_BRUSH); + wxRect recToDraw(e.x, e.y, e.width, e.height); + dc->DrawRectangle(recToDraw); + dc->DrawText(wxString(e.text), Middle(e)); + } else if (e.prop & cgeditor::Property::Comment) { + wxRect recToDraw(e.x, e.y, e.width, e.height); + dc->SetBrush(*wxYELLOW_BRUSH); + dc->DrawRectangle(recToDraw); + dc->DrawText(wxString(e.text), wxPoint(e.x, e.y)); + } else if (e.prop & cgeditor::Property::Menuitem) { + wxRect recToDraw(e.x, e.y, e.width, e.height); + dc->SetBrush(*wxLIGHT_GREY_BRUSH); + dc->DrawRectangle(recToDraw); + dc->DrawText(wxString(e.text), wxPoint(e.x, Middle(e).y)); + } else { + if (e.prop & cgeditor::Property::Move) { + if (e.prop & cgeditor::Property::Current) { + wxRect recToDraw(e.x, e.y, e.width, e.height); + dc->SetBrush(*wxLIGHT_GREY_BRUSH); + dc->DrawRectangle(recToDraw); + } + if (CGEditor::status.UseMoveImages) { + dc->DrawText(wxString(e.text), wxPoint(e.x, Middle(e).y)); + } else { + dc->DrawText(wxString(e.text), Middle(e)); + } + } else { + dc->DrawText(wxString(e.text), Middle(e)); + } + } + } + } + + /** + * @brief CGEditor events that occurs during last draw + * + * @param e event to handle + */ + void HandleEvent(const cgeditor::Event &e) { + std::string str; + if (e.type == cgeditor::Event::Type::CommentSelected) + str = "Comment Selected"; + else if (e.type == cgeditor::Event::Type::Promote) { + str = "Promote"; + static_cast(e.move)->MyHalfMove::Promote(); + NeedRedraw = true; + } else if (e.type == cgeditor::Event::Type::Delete) { + str = "Delete"; + if (e.move->Parent != NULL) { + static_cast(e.move)->GetParent()->MyHalfMove::RemoveChild( + (MyHalfMove *)e.move); + } else { + CGEditor::status.Moves = NULL; + } + NeedRedraw = true; + } else if (e.type == cgeditor::Event::Type::SetAsMainline) { + str = "Set as main line"; + static_cast(e.move)->MyHalfMove::SetAsMainline(); + NeedRedraw = true; + } else if (e.type == cgeditor::Event::Type::Goto) { + str = "Goto move"; + } + std::cout << "Event received: " << str << std::endl << std::flush; + } + + // wxWidgets specific + DECLARE_EVENT_TABLE() +}; + +wxBEGIN_EVENT_TABLE(MyFrame, wxFrame) +EVT_PAINT(MyFrame::OnPaint) +EVT_MOUSE_EVENTS(MyFrame::MouseEvent) +wxEND_EVENT_TABLE() + +class MyApp : public wxApp { +public: + virtual bool OnInit() { + MyFrame *frame = new MyFrame(); + frame->Show(true); + return true; + } +}; +wxIMPLEMENT_APP(MyApp); -- cgit v1.2.3