diff --git a/build/cmake/samples/CMakeLists.txt b/build/cmake/samples/CMakeLists.txt index 97989996c4..2a03425b3f 100644 --- a/build/cmake/samples/CMakeLists.txt +++ b/build/cmake/samples/CMakeLists.txt @@ -44,7 +44,7 @@ wx_add_sample(dragimag dragimag.cpp dragimag.h RES dragimag.rc DEPENDS wxUSE_DRAGIMAGE) wx_add_sample(drawing DATA pat4.bmp pat35.bmp pat36.bmp image.bmp mask.bmp) wx_add_sample(erase) -wx_add_sample(event event.cpp gestures.cpp gestures.h) +wx_add_sample(event event.cpp gestures.cpp gestures.h chessboard.cpp chessboard.h) wx_add_sample(except DEPENDS wxUSE_EXCEPTIONS) wx_add_sample(exec) wx_add_sample(font DATA wxprivate.ttf) diff --git a/samples/event/Makefile.in b/samples/event/Makefile.in index aeed0e2c22..2851a20125 100644 --- a/samples/event/Makefile.in +++ b/samples/event/Makefile.in @@ -51,7 +51,8 @@ EVENT_CXXFLAGS = -D__WX$(TOOLKIT)__ $(__WXUNIV_DEFINE_p) $(__DEBUG_DEFINE_p) \ EVENT_OBJECTS = \ $(__event___win32rc) \ event_event.o \ - event_gestures.o + event_gestures.o \ + event_chessboard.o ### Conditionally set variables: ### @@ -185,6 +186,9 @@ event_event.o: $(srcdir)/event.cpp event_gestures.o: $(srcdir)/gestures.cpp $(CXXC) -c -o $@ $(EVENT_CXXFLAGS) $(srcdir)/gestures.cpp +event_chessboard.o: $(srcdir)/chessboard.cpp + $(CXXC) -c -o $@ $(EVENT_CXXFLAGS) $(srcdir)/chessboard.cpp + # Include dependency info, if present: @IF_GNU_MAKE@-include ./.deps/*.d diff --git a/samples/event/chessboard.cpp b/samples/event/chessboard.cpp new file mode 100644 index 0000000000..d90a5ac675 --- /dev/null +++ b/samples/event/chessboard.cpp @@ -0,0 +1,214 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: samples/event/chessboard.cpp +// Purpose: Part of wxWidgets event sample, shows how to create a new wxEvent class +// Author: PB +// Created: 2019-10-29 +// Copyright: (c) 2019 wxWidgets development team +// Licence: wxWindows licence +///////////////////////////////////////////////////////////////////////////// + +#include "chessboard.h" + + +// +// ChessBoardEvent +// + +// Define new event types associated with ChessBoardEvent +wxDEFINE_EVENT(myEVT_CHESSBOARD_CLICKED, ChessBoardEvent); +wxDEFINE_EVENT(myEVT_CHESSBOARD_DRAGGED, ChessBoardEvent); + + +// +// ChessBoard +// +class ChessBoard : public wxPanel +{ +public: + ChessBoard(wxWindow* parent); + +private: + static const wxUint8 SquaresPerSide = 8; + static const int SquareSizeInDIPs = 40; + + // square on which mouse left button was pressed + char m_fileLeftMDown; + wxUint8 m_rankLeftMDown; + + bool ConvertMousePosToFileAndRank(const wxPoint& pos, + char& file, wxUint8& rank) const; + + void OnPaint(wxPaintEvent& event); + void OnMouseLeftDown(wxMouseEvent& event); + void OnMouseLeftUp(wxMouseEvent& event); + + virtual wxSize DoGetBestClientSize() const wxOVERRIDE; +}; + +ChessBoard::ChessBoard(wxWindow* parent) + : wxPanel(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxBORDER_RAISED), + m_fileLeftMDown('a'), m_rankLeftMDown(1) +{ + SetCursor(wxCursor(wxCURSOR_HAND)); + SetBackgroundColour(*wxWHITE); + + Bind(wxEVT_PAINT, &ChessBoard::OnPaint, this); + Bind(wxEVT_LEFT_DOWN, &ChessBoard::OnMouseLeftDown, this); + Bind(wxEVT_LEFT_UP, &ChessBoard::OnMouseLeftUp, this); +} + + bool ChessBoard::ConvertMousePosToFileAndRank(const wxPoint& pos, + char& file, wxUint8& rank) const +{ + static const char FileLetters[SquaresPerSide] = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'}; + + const int squareSizeInPx = FromDIP(SquareSizeInDIPs); + const int colIdx = pos.x / squareSizeInPx; + const int rowIdx = pos.y / squareSizeInPx; + + if ( colIdx < 0 || colIdx >= SquaresPerSide + || rowIdx < 0 || rowIdx >= SquaresPerSide ) + { + return false; // not on a square + } + + file = FileLetters[colIdx], + // convert rowIdx (top to down 0 to 7) to rank (top to down 8 to 1) + rank = static_cast(SquaresPerSide - rowIdx); + + return true; +} + +// Background is already painted white, +// so we need to draw only the black squares over it. +void ChessBoard::OnPaint(wxPaintEvent& WXUNUSED(event)) +{ + const int squareSizeInPx = FromDIP(SquareSizeInDIPs); + + wxPaintDC dc(this); + wxDCPenChanger penChanger(dc, *wxTRANSPARENT_PEN); + wxDCBrushChanger brushChanger(dc, *wxBLACK_BRUSH); + wxRect squareRect(wxSize(squareSizeInPx, squareSizeInPx)); + + // draw from top to down, left to right + for ( size_t rank = SquaresPerSide; rank >= 1; --rank ) + { + if ( rank % 2 ) + squareRect.SetLeft(0); // odd ranks start with a black square + else + squareRect.SetLeft(squareSizeInPx); // even ranks start with a white square + + for ( size_t file = 0; file < SquaresPerSide / 2; ++file ) + { + dc.DrawRectangle(squareRect); + squareRect.Offset(2 * squareSizeInPx, 0); + } + + squareRect.Offset(0, squareSizeInPx); + } +} + +void ChessBoard::OnMouseLeftDown(wxMouseEvent& event) +{ + char file; + wxUint8 rank; + + event.Skip(); + + if ( !ConvertMousePosToFileAndRank(event.GetPosition(), file, rank) ) + return; // mouse cursor not on a square + + m_fileLeftMDown = file; + m_rankLeftMDown = rank; + CaptureMouse(); +} + +void ChessBoard::OnMouseLeftUp(wxMouseEvent& event) +{ + event.Skip(); + + if ( !HasCapture() ) + return; // capture lost or mouse left down was not on a square + + const wxRect clientRect = GetClientRect(); + char file; + wxUint8 rank; + + ReleaseMouse(); + + if ( !clientRect.Contains(event.GetPosition()) || + !ConvertMousePosToFileAndRank(event.GetPosition(), file, rank) ) + { + return; // mouse cursor not on a square + } + + ChessBoardEvent chessBoardEvent; + + chessBoardEvent.SetId(GetId()); + chessBoardEvent.SetEventObject(this); + chessBoardEvent.SetFile(m_fileLeftMDown); + chessBoardEvent.SetRank(m_rankLeftMDown); + + if ( file == m_fileLeftMDown && rank == m_rankLeftMDown ) + { // mouse left and down on the same square, consider it a click + chessBoardEvent.SetEventType(myEVT_CHESSBOARD_CLICKED); + } + else + { // mouse dragged from one square to another + chessBoardEvent.SetEventType(myEVT_CHESSBOARD_DRAGGED); + chessBoardEvent.SetFileTo(file); + chessBoardEvent.SetRankTo(rank); + } + + ProcessWindowEvent(chessBoardEvent); +} + +wxSize ChessBoard::DoGetBestClientSize() const +{ + const int boardSideSizeInPx = SquaresPerSide * FromDIP(SquareSizeInDIPs); + + return wxSize(boardSideSizeInPx, boardSideSizeInPx); +} + +// +// MyChessBoardDialog implementation +// + +// For demonstration, event table is used for myEVT_CHESSBOARD_CLICKED +// while Bind() is used for myEVT_CHESSBOARD_DRAGGED. +wxBEGIN_EVENT_TABLE(MyChessBoardDialog, wxDialog) + EVT_CHESSBOARD_CLICKED(wxID_ANY, MyChessBoardDialog::OnChessBoardClicked) +wxEND_EVENT_TABLE() + +MyChessBoardDialog::MyChessBoardDialog(wxWindow* parent) + : wxDialog(parent, wxID_ANY, "New event class demonstration") +{ + wxSizer* mainSizer = new wxBoxSizer(wxVERTICAL); + + mainSizer->Add( + new wxStaticText(this, wxID_ANY, "Click or drag the mouse over the chessboard"), + wxSizerFlags().Border().CenterHorizontal()); + + mainSizer->Add(new ChessBoard(this), + wxSizerFlags().TripleBorder().CenterHorizontal()); + + mainSizer->Add(CreateStdDialogButtonSizer(wxCLOSE), + wxSizerFlags().Expand().Border()); + + SetSizerAndFit(mainSizer); + + Bind(myEVT_CHESSBOARD_DRAGGED, &MyChessBoardDialog::OnChessBoardDragged, this); +} + +void MyChessBoardDialog::OnChessBoardClicked(ChessBoardEvent& event) +{ + wxLogMessage("myEVT_CHESSBOARD_CLICKED: %c%hhu", + event.GetFile(), event.GetRank()); +} + +void MyChessBoardDialog::OnChessBoardDragged(ChessBoardEvent& event) +{ + wxLogMessage("myEVT_CHESSBOARD_DRAGGED: from %c%hhu to %c%hhu", + event.GetFile(), event.GetRank(), + event.GetFileTo(), event.GetRankTo()); +} diff --git a/samples/event/chessboard.h b/samples/event/chessboard.h new file mode 100644 index 0000000000..b9d3fcad7b --- /dev/null +++ b/samples/event/chessboard.h @@ -0,0 +1,93 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: samples/event/chessboard.h +// Purpose: Part of wxWidgets event sample, shows how to create a new wxEvent class +// Author: PB +// Created: 2019-10-29 +// Copyright: (c) 2019 wxWidgets development team +// Licence: wxWindows licence +///////////////////////////////////////////////////////////////////////////// + +#ifndef _WX_CHESSBOARD_H_ + +#include "wx/wx.h" + +// A chessboard consists of 8x8 squares organized +// in columns (called files) and rows (called ranks). +// In a 2D view, files are labeled from left to right +// 'a' to 'h' while ranks are numbered from bottom to +// top 1 to 8. +// ChessBoardEvent tells us something happened on +// the chessboard. Either a square was clicked +// (myEVT_CHESSBOARD_CLICKED) or the mouse cursor was dragged +// from one square to another (myEVT_CHESSBOARD_DRAGGED). +class ChessBoardEvent : public wxCommandEvent +{ +public: + ChessBoardEvent(wxEventType commandEventType = wxEVT_NULL, int id = 0) + : wxCommandEvent(commandEventType, id), + m_file('a'), m_rank(1), m_fileTo('a'), m_rankTo(1) + {} + + // myEVT_CHESSBOARD_CLICKED: Returns File/Rank for the square clicked. + // myEVT_CHESSBOARD_DRAGGED: Returns File/Rank for the square + // the mouse cursor was dragged from. + char GetFile() const { return m_file; } + wxUint8 GetRank() const { return m_rank; } + + // Valid only for myEVT_CHESSBOARD_DRAGGED, + // returns File/Rank for the square where the mouse cursor was dragged to. + char GetFileTo() const { return m_fileTo; } + wxUint8 GetRankTo() const { return m_rankTo; } + + void SetFile(char file) { m_file = file; } + void SetRank(wxUint8 rank) { m_rank = rank; } + + void SetFileTo(char file) { m_fileTo = file; } + void SetRankTo(wxUint8 rank) { m_rankTo = rank; } + + virtual wxEvent* Clone() const wxOVERRIDE { return new ChessBoardEvent(*this); } +private: + char m_file; + wxUint8 m_rank; + char m_fileTo; + wxUint8 m_rankTo; +}; + + +// Declare new event types, +// the matching definitions are in chessboard.cpp. +wxDECLARE_EVENT(myEVT_CHESSBOARD_CLICKED, ChessBoardEvent); +wxDECLARE_EVENT(myEVT_CHESSBOARD_DRAGGED, ChessBoardEvent); + +// The following typedef and macro are needed only when the new event +// class is to be used with event table macros or the legacy Connect(), +// to cast the type of a function handling it to the type expected by +// the event table machinery, see its use in EVT_CHESSBOARD_xxx below. +// I.e., when only Bind() is going to be used you do not need them. +typedef void (wxEvtHandler::*ChessBoardEventFunction)(ChessBoardEvent&); +#define ChessBoardEventHandler(func) wxEVENT_HANDLER_CAST(ChessBoardEventFunction, func) + +// These defines are needed only if the new event is to be used with +// event tables, i.e., when only Bind() is going to be used you do not need them. +#define EVT_CHESSBOARD_CLICKED(id, func) \ + wx__DECLARE_EVT1(myEVT_CHESSBOARD_CLICKED, id, ChessBoardEventHandler(func)) +#define EVT_CHESSBOARD_DRAGGED(id, func) \ + wx__DECLARE_EVT1(myEVT_CHESSBOARD_DRAGGED, id, ChessBoardEventHandler(func)) + + +// Dialog displaying the chessboard +// and handling ChessBoardEvents +class MyChessBoardDialog : public wxDialog +{ +public: + MyChessBoardDialog(wxWindow* parent); +private: + void OnChessBoardClicked(ChessBoardEvent& event); + void OnChessBoardDragged(ChessBoardEvent& event); + + // Just for demonstration, we will use an event table + // for myEVT_CHESSBOARD_CLICKED. + wxDECLARE_EVENT_TABLE(); +}; + +#endif // #ifndef _WX_CHESSBOARD_H_ diff --git a/samples/event/event.bkl b/samples/event/event.bkl index ab8ee98c5a..591150b2ee 100644 --- a/samples/event/event.bkl +++ b/samples/event/event.bkl @@ -4,8 +4,8 @@ - event.cpp gestures.cpp - gestures.h + event.cpp gestures.cpp chessboard.cpp + gestures.h chessboard.h core base diff --git a/samples/event/event.cpp b/samples/event/event.cpp index bbaf6bae67..a6bb8ddf08 100644 --- a/samples/event/event.cpp +++ b/samples/event/event.cpp @@ -36,6 +36,7 @@ #include #include #include "gestures.h" +#include "chessboard.h" // ---------------------------------------------------------------------------- // event constants @@ -147,6 +148,9 @@ public: // Gesture void OnGesture(wxCommandEvent& event); + // Demonstrates using a new event class + void OnNewEventClass(wxCommandEvent& event); + private: // symbolic names for the status bar fields enum @@ -226,7 +230,8 @@ enum Event_Pop, Event_Custom, Event_Test, - Event_Gesture + Event_Gesture, + Event_NewEventClass }; // ---------------------------------------------------------------------------- @@ -259,6 +264,7 @@ wxBEGIN_EVENT_TABLE(MyFrame, wxFrame) EVT_MENU(Event_Push, MyFrame::OnPushEventHandler) EVT_MENU(Event_Pop, MyFrame::OnPopEventHandler) EVT_MENU(Event_Gesture, MyFrame::OnGesture) + EVT_MENU(Event_NewEventClass, MyFrame::OnNewEventClass) EVT_UPDATE_UI(Event_Pop, MyFrame::OnUpdateUIPop) @@ -390,6 +396,8 @@ MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size) "Generate a custom event"); menuEvent->Append(Event_Gesture, "&Gesture events\tCtrl-G", "Gesture event"); + menuEvent->Append(Event_NewEventClass, "&New wxEvent class demo\tCtrl-N", + "Demonstrates a new wxEvent-derived class"); // now append the freshly created menu to the menu bar... wxMenuBar *menuBar = new wxMenuBar(); @@ -591,6 +599,13 @@ void MyFrame::OnGesture(wxCommandEvent& WXUNUSED(event)) } } +void MyFrame::OnNewEventClass(wxCommandEvent& WXUNUSED(event)) +{ + MyChessBoardDialog dlg(this); + + dlg.ShowModal(); +} + void MyFrame::OnTest(wxCommandEvent& WXUNUSED(event)) { wxLogMessage("This is the test event handler in the main frame"); diff --git a/samples/event/event_vc7.vcproj b/samples/event/event_vc7.vcproj index 0036a2c140..57906ee33f 100644 --- a/samples/event/event_vc7.vcproj +++ b/samples/event/event_vc7.vcproj @@ -283,6 +283,9 @@ Name="Source Files" Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx" UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"> + + @@ -294,6 +297,9 @@ Name="Header Files" Filter="h;hpp;hxx;hm;inl;inc;xsd" UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"> + + diff --git a/samples/event/event_vc8.vcproj b/samples/event/event_vc8.vcproj index 91fb217c90..708f64e893 100644 --- a/samples/event/event_vc8.vcproj +++ b/samples/event/event_vc8.vcproj @@ -806,6 +806,10 @@ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx" UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}" > + + @@ -820,6 +824,10 @@ Filter="h;hpp;hxx;hm;inl;inc;xsd" UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}" > + + diff --git a/samples/event/event_vc9.vcproj b/samples/event/event_vc9.vcproj index 414f8963fd..52859e4281 100644 --- a/samples/event/event_vc9.vcproj +++ b/samples/event/event_vc9.vcproj @@ -778,6 +778,10 @@ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx" UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}" > + + @@ -792,6 +796,10 @@ Filter="h;hpp;hxx;hm;inl;inc;xsd" UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}" > + + diff --git a/samples/event/makefile.bcc b/samples/event/makefile.bcc index e8a47ef0f3..f6e79e4574 100644 --- a/samples/event/makefile.bcc +++ b/samples/event/makefile.bcc @@ -37,7 +37,8 @@ EVENT_CXXFLAGS = $(__RUNTIME_LIBS_7) -I$(BCCDIR)\include $(__DEBUGINFO) \ $(__DLLFLAG_p) -I.\..\..\samples -DNOPCH $(CPPFLAGS) $(CXXFLAGS) EVENT_OBJECTS = \ $(OBJS)\event_event.obj \ - $(OBJS)\event_gestures.obj + $(OBJS)\event_gestures.obj \ + $(OBJS)\event_chessboard.obj ### Conditionally set variables: ### @@ -241,3 +242,6 @@ $(OBJS)\event_event.obj: .\event.cpp $(OBJS)\event_gestures.obj: .\gestures.cpp $(CXX) -q -c -P -o$@ $(EVENT_CXXFLAGS) .\gestures.cpp +$(OBJS)\event_chessboard.obj: .\chessboard.cpp + $(CXX) -q -c -P -o$@ $(EVENT_CXXFLAGS) .\chessboard.cpp + diff --git a/samples/event/makefile.gcc b/samples/event/makefile.gcc index 40dbe04f0e..081b3fb97d 100644 --- a/samples/event/makefile.gcc +++ b/samples/event/makefile.gcc @@ -31,7 +31,8 @@ EVENT_CXXFLAGS = $(__DEBUGINFO) $(__OPTIMIZEFLAG_2) $(__THREADSFLAG) \ EVENT_OBJECTS = \ $(OBJS)\event_sample_rc.o \ $(OBJS)\event_event.o \ - $(OBJS)\event_gestures.o + $(OBJS)\event_gestures.o \ + $(OBJS)\event_chessboard.o ### Conditionally set variables: ### @@ -233,6 +234,9 @@ $(OBJS)\event_event.o: ./event.cpp $(OBJS)\event_gestures.o: ./gestures.cpp $(CXX) -c -o $@ $(EVENT_CXXFLAGS) $(CPPDEPS) $< +$(OBJS)\event_chessboard.o: ./chessboard.cpp + $(CXX) -c -o $@ $(EVENT_CXXFLAGS) $(CPPDEPS) $< + .PHONY: all clean diff --git a/samples/event/makefile.unx b/samples/event/makefile.unx index fc5c5950de..c364699202 100644 --- a/samples/event/makefile.unx +++ b/samples/event/makefile.unx @@ -54,7 +54,8 @@ EVENT_CXXFLAGS = -I. `$(WX_CONFIG) --cxxflags $(WX_CONFIG_FLAGS)` $(CPPFLAGS) \ $(CXXFLAGS) EVENT_OBJECTS = \ event_event.o \ - event_gestures.o + event_gestures.o \ + event_chessboard.o ### Conditionally set variables: ### @@ -97,6 +98,9 @@ event_event.o: ./event.cpp event_gestures.o: ./gestures.cpp $(CXX) -c -o $@ $(EVENT_CXXFLAGS) $(CPPDEPS) $< +event_chessboard.o: ./chessboard.cpp + $(CXX) -c -o $@ $(EVENT_CXXFLAGS) $(CPPDEPS) $< + .PHONY: all install uninstall clean