215 lines
6.3 KiB
C++
215 lines
6.3 KiB
C++
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
// Name: samples/event/chessboard.cpp
|
||
|
// Purpose: Part of wxWidgets event sample, shows how to create a new wxEvent class
|
||
|
// Author: PB <pbfordev@gmail.com>
|
||
|
// 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<wxUint8>(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());
|
||
|
}
|