Files
Music-Notation/interfejs/interfejs.cpp
T
2013-06-19 22:49:25 +02:00

772 lines
25 KiB
C++

//---------------------------------------------------------------------------------------
// This file is part of the Lomse library.
// Copyright (c) 2010-2012 Cecilio Salmeron. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright notice, this
// list of conditions and the following disclaimer in the documentation and/or
// other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
// DAMAGE.
//
// For any comment, suggestion or feature request, please contact the manager of
// the project at cecilios@users.sourceforge.net
//---------------------------------------------------------------------------------------
// For compilers that support precompilation, includes "wx/wx.h".
#include "wx/wxprec.h"
#ifdef __BORLANDC__
#pragma hdrstop
#endif
#ifndef WX_PRECOMP
#include <wx/app.h>
#include <wx/frame.h>
#include <wx/menu.h>
#include <wx/msgdlg.h>
#include <wx/filedlg.h>
#include <wx/image.h>
#include <wx/dc.h>
#include <wx/dcmemory.h>
#include <wx/event.h>
#include <wx/sizer.h>
#include <wx/textctrl.h>
#include <wx/button.h>
#endif
#include <iostream>
//lomse headers
#include <lomse_doorway.h>
#include <lomse_document.h>
#include <lomse_graphic_view.h>
#include <lomse_interactor.h>
#include <lomse_presenter.h>
#include <lomse_events.h>
using namespace lomse;
//---------------------------------------------------------------------------------------
// Define the application
class MyApp: public wxApp
{
public:
bool OnInit();
};
//forward declarations
class MyCanvas;
//---------------------------------------------------------------------------------------
// Define the main frame
class MyFrame: public wxFrame
{
public:
MyFrame();
virtual ~MyFrame();
//commands
void open_test_document();
//event handlers (these functions should _not_ be virtual)
void OnQuit(wxCommandEvent& event);
void OnAbout(wxCommandEvent& event);
protected:
//accessors
MyCanvas* get_active_canvas() const { return m_canvas; }
//event handlers
void OnOpen(wxCommandEvent& WXUNUSED(event));
void OnZoomIn(wxCommandEvent& WXUNUSED(event));
void OnZoomOut(wxCommandEvent& WXUNUSED(event));
void OnClick(wxCommandEvent& WXUNUSED(event));
//lomse related
void initialize_lomse();
void create_menu();
LomseDoorway m_lomse; //the Lomse library doorway
MyCanvas* m_canvas;
wxTextCtrl *MainEditBox;
wxButton *button;
DECLARE_EVENT_TABLE()
};
//---------------------------------------------------------------------------------------
// MyCanvas is a window on which we show the scores
class MyCanvas : public wxWindow
{
public:
MyCanvas(wxFrame *frame, LomseDoorway& lomse);
~MyCanvas();
void update_view_content();
//callback wrappers
static void wrapper_update_window(void* pThis, SpEventInfo pEvent);
//commands
void open_test_document();
void open_file(const wxString& fullname);
void zoom_in();
void zoom_out();
void getTextFromBox(const char *text);
protected:
//event handlers
void OnPaint(wxPaintEvent& WXUNUSED(event));
void OnSize(wxSizeEvent& event);
void OnKeyDown(wxKeyEvent& event);
void OnMouseEvent(wxMouseEvent& event);
void delete_rendering_buffer();
void create_rendering_buffer(int width, int height);
void copy_buffer_on_dc(wxDC& dc);
void update_rendering_buffer_if_needed();
void force_redraw();
void update_window();
void on_key(int x, int y, unsigned key, unsigned flags);
unsigned get_keyboard_flags(wxKeyEvent& event);
unsigned get_mouse_flags(wxMouseEvent& event);
// In this first example we are just going to display an score on the window.
// Let's define the necessary variables:
LomseDoorway& m_lomse; //the Lomse library doorway
Presenter* m_pPresenter;
//the Lomse View renders its content on a bitmap. To manage it, Lomse
//associates the bitmap to a RenderingBuffer object.
//It is your responsibility to render the bitmap on a window.
//Here you define the rendering buffer and its associated bitmap to be
//used by the previously defined View.
RenderingBuffer m_rbuf_window;
wxImage* m_buffer; //the image to serve as buffer
unsigned char* m_pdata; //ptr to the bitmap
int m_nBufWidth, m_nBufHeight; //size of the bitmap
//some additinal variables
bool m_view_needs_redraw; //to control when the View must be re-drawn
DECLARE_EVENT_TABLE()
};
//=======================================================================================
// MyApp implementation
//=======================================================================================
IMPLEMENT_APP(MyApp)
// 'Main program' equivalent: the program execution "starts" here
bool MyApp::OnInit()
{
MyFrame* frame = new MyFrame;
frame->Show(true);
SetTopWindow(frame);
frame->open_test_document();
return true;
}
//=======================================================================================
// MyFrame implementation
//=======================================================================================
//---------------------------------------------------------------------------------------
// constants for menu IDs
enum
{
//new IDs
k_menu_file_open = wxID_HIGHEST + 1,
//using standard IDs
//it is important for the id corresponding to the "About" command to have
//this standard value as otherwise it won't be handled properly under Mac
//(where it is special and put into the "Apple" menu)
k_menu_file_quit = wxID_EXIT,
k_menu_help_about = wxID_ABOUT,
k_menu_zoom_in = wxID_ZOOM_IN,
k_menu_zoom_out = wxID_ZOOM_OUT,
BUTTON_Hello = wxID_REFRESH,
};
//---------------------------------------------------------------------------------------
// events table
BEGIN_EVENT_TABLE(MyFrame, wxFrame)
EVT_MENU(k_menu_file_quit, MyFrame::OnQuit)
EVT_MENU(k_menu_help_about, MyFrame::OnAbout)
EVT_MENU(k_menu_file_open, MyFrame::OnOpen)
EVT_MENU(k_menu_zoom_in, MyFrame::OnZoomIn)
EVT_MENU(k_menu_zoom_out, MyFrame::OnZoomOut)
EVT_BUTTON ( BUTTON_Hello, MyFrame::OnClick )
END_EVENT_TABLE()
//---------------------------------------------------------------------------------------
MyFrame::MyFrame()
: wxFrame(NULL, wxID_ANY, _T("Lomse sample for wxWidgets"),
wxDefaultPosition, wxSize(850, 600))
{
create_menu();
initialize_lomse();
// create our one and only child -- it will take our entire client area
m_canvas = new MyCanvas(this, m_lomse);
wxSizer *sz = new wxBoxSizer(wxVERTICAL);
sz->Add(m_canvas, 3, wxGROW);
MainEditBox = new wxTextCtrl(this, wxID_HIGHEST + 1,
wxT("Hi!dsfsdsdf"), wxDefaultPosition, wxSize(850,40),
wxTE_MULTILINE | wxTE_RICH , wxDefaultValidator, wxTextCtrlNameStr);
sz->Add(MainEditBox);
button = new wxButton(this,BUTTON_Hello,_T("Generuj"), wxDefaultPosition, wxDefaultSize, 0);
sz->Add(button);
SetSizer(sz);
}
//---------------------------------------------------------------------------------------
MyFrame::~MyFrame()
{
}
//---------------------------------------------------------------------------------------
void MyFrame::create_menu()
{
wxMenu *fileMenu = new wxMenu;
fileMenu->Append(k_menu_file_open, _T("&Open..."));
fileMenu->AppendSeparator();
fileMenu->Append(k_menu_file_quit, _T("E&xit"));
wxMenu* zoomMenu = new wxMenu;
zoomMenu->Append(k_menu_zoom_in);
zoomMenu->Append(k_menu_zoom_out);
wxMenu *helpMenu = new wxMenu;
helpMenu->Append(k_menu_help_about, _T("&About"));
wxMenuBar* menuBar = new wxMenuBar;
menuBar->Append(fileMenu, _T("&File"));
menuBar->Append(zoomMenu, _T("&Zoom"));
menuBar->Append(helpMenu, _T("&Help"));
SetMenuBar(menuBar);
}
//---------------------------------------------------------------------------------------
void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
{
Close(true /*force to close*/);
}
//---------------------------------------------------------------------------------------
void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
{
wxMessageBox(_T("Lomse: sample 1 for wxWidgets"),
_T("About wxWidgets Lomse sample"),
wxOK | wxICON_INFORMATION, this);
}
//---------------------------------------------------------------------------------------
void MyFrame::initialize_lomse()
{
// Lomse knows nothing about windows. It renders everything on bitmaps and the
// user application uses them. For instance, to display it on a wxWindows.
// Lomse supports a lot of bitmap formats and pixel formats. Therefore, before
// using the Lomse library you MUST specify which bitmap formap to use.
//
// For wxWidgets, I would suggets using a platform independent format. So
// I will use a wxImage as the rendering buffer. wxImage is platform independent
// and its buffer is an array of characters in RGBRGBRGB... format, in the
// top-to-bottom, left-to-right order. That is, the first RGB triplet corresponds
// to the first pixel of the first row; the second RGB triplet, to the second
// pixel of the first row, and so on until the end of the first row,
// with second row following after it and so on.
// Therefore, the pixel format is RGB 24 bits.
//
// Let's define the requiered information:
//the pixel format
int pixel_format = k_pix_format_rgb24; //RGB 24bits
//the desired resolution. For Linux and Windows 96 pixels per inch works ok.
int resolution = 96; //96 ppi
//Normal y axis direction is 0 coordinate at top and increase downwards. You
//must specify if you would like just the opposite behaviour. For Windows and
//Linux the default behaviour is the right behaviour.
bool reverse_y_axis = false;
//initialize the library with these values
m_lomse.init_library(pixel_format,resolution, reverse_y_axis);
}
//---------------------------------------------------------------------------------------
void MyFrame::open_test_document()
{
get_active_canvas()->open_test_document();
//BUG_BYPASS
// In Linux there are problems to catch Key Up/Down events. See for instance
// http://forums.wxwidgets.org/viewtopic.php?t=33057&p=137567
// Following line is not needed for Windows (doen't hurt) but it is
// necessary for Linux, in order to receive Key Up/Down events
get_active_canvas()->SetFocus();
}
//---------------------------------------------------------------------------------------
void MyFrame::OnOpen(wxCommandEvent& WXUNUSED(event))
{
wxString defaultPath = wxT("../../../test-scores/");
wxString filename = wxFileSelector(_("Open score"), defaultPath,
wxEmptyString, wxEmptyString, wxT("LenMus files|*.lms;*.lmd"));
if (filename.empty())
return;
get_active_canvas()->open_file(filename);
}
void MyFrame::OnClick(wxCommandEvent& WXUNUSED(event)){
wxString mystring=MainEditBox->GetValue();
get_active_canvas()->getTextFromBox(mystring.mb_str(wxConvUTF8));
}
//---------------------------------------------------------------------------------------
void MyFrame::OnZoomIn(wxCommandEvent& WXUNUSED(event))
{
get_active_canvas()->zoom_in();
}
//---------------------------------------------------------------------------------------
void MyFrame::OnZoomOut(wxCommandEvent& WXUNUSED(event))
{
get_active_canvas()->zoom_out();
}
//=======================================================================================
// MyCanvas implementation
//=======================================================================================
BEGIN_EVENT_TABLE(MyCanvas, wxWindow)
EVT_KEY_DOWN(MyCanvas::OnKeyDown)
EVT_MOUSE_EVENTS(MyCanvas::OnMouseEvent)
EVT_SIZE(MyCanvas::OnSize)
EVT_PAINT(MyCanvas::OnPaint)
END_EVENT_TABLE()
//---------------------------------------------------------------------------------------
MyCanvas::MyCanvas(wxFrame *frame, LomseDoorway& lomse)
: wxWindow(frame, wxID_ANY)
, m_lomse(lomse)
, m_pPresenter(NULL)
, m_buffer(NULL)
, m_view_needs_redraw(true)
{
}
//---------------------------------------------------------------------------------------
MyCanvas::~MyCanvas()
{
delete_rendering_buffer();
//delete the Presenter. This will also delete the Document, the Interactor,
//the View and other related objects
delete m_pPresenter;
}
//---------------------------------------------------------------------------------------
void MyCanvas::getTextFromBox(const char *text){
try{
std::string input(text);
delete m_pPresenter;
m_pPresenter = m_lomse.new_document(ViewFactory::k_view_horizontal_book,input);
//get the pointer to the interactor, set the rendering buffer and register for
//receiving desired events
if (SpInteractor spInteractor = m_pPresenter->get_interactor(0).lock())
{
//connect the View with the window buffer
spInteractor->set_rendering_buffer(&m_rbuf_window);
//ask to receive desired events
spInteractor->add_event_handler(k_update_window_event, this, wrapper_update_window);
//hide edition caret
spInteractor->hide_caret();
}
//render the new score
m_view_needs_redraw = true;
Refresh(false /* don't erase background */);
}catch(...){
wxMessageBox( wxT("Błąd składni!") );
}
}
void MyCanvas::open_file(const wxString& fullname)
{
//create a new View
std::string filename( fullname.mb_str(wxConvUTF8) );
delete m_pPresenter;
m_pPresenter = m_lomse.open_document(ViewFactory::k_view_horizontal_book,
filename);
//get the pointer to the interactor, set the rendering buffer and register for
//receiving desired events
if (SpInteractor spInteractor = m_pPresenter->get_interactor(0).lock())
{
//connect the View with the window buffer
spInteractor->set_rendering_buffer(&m_rbuf_window);
//ask to receive desired events
spInteractor->add_event_handler(k_update_window_event, this, wrapper_update_window);
//hide edition caret
spInteractor->hide_caret();
}
//render the new score
m_view_needs_redraw = true;
Refresh(false /* don't erase background */);
}
//---------------------------------------------------------------------------------------
void MyCanvas::OnSize(wxSizeEvent& WXUNUSED(event))
{
wxSize size = this->GetClientSize();
create_rendering_buffer(size.GetWidth(), size.GetHeight());
Refresh(false /* don't erase background */);
}
//---------------------------------------------------------------------------------------
void MyCanvas::OnPaint(wxPaintEvent& event)
{
if (!m_pPresenter)
event.Skip(false);
else
{
update_rendering_buffer_if_needed();
wxPaintDC dc(this);
copy_buffer_on_dc(dc);
}
}
//---------------------------------------------------------------------------------------
void MyCanvas::update_rendering_buffer_if_needed()
{
if (m_view_needs_redraw)
update_view_content();
m_view_needs_redraw = false;
}
//---------------------------------------------------------------------------------------
void MyCanvas::delete_rendering_buffer()
{
delete m_buffer;
}
//---------------------------------------------------------------------------------------
void MyCanvas::create_rendering_buffer(int width, int height)
{
//creates a bitmap of specified size and associates it to the rendering
//buffer for the view. Any existing buffer is automatically deleted
// allocate a new rendering buffer
delete_rendering_buffer();
m_nBufWidth = width;
m_nBufHeight = height;
m_buffer = new wxImage(width, height);
//get pointer to wxImage internal bitmap
m_pdata = m_buffer->GetData();
//Attach this bitmap to Lomse rendering buffer
#define BYTES_PER_PIXEL 3 //wxImage has RGB, 24 bits format
int stride = m_nBufWidth * BYTES_PER_PIXEL; //number of bytes per row
m_rbuf_window.attach(m_pdata, m_nBufWidth, m_nBufHeight, stride);
m_view_needs_redraw = true;
}
//-------------------------------------------------------------------------
void MyCanvas::open_test_document()
{
//Normally you will load the content of a file. But in this
//simple example we will create an empty document and define its content
//from a text string
//first, we will create a 'presenter'. It takes care of cretaing and maintaining
//all objects and relationships between the document, its views and the interactors
//to interct with the view
delete m_pPresenter;
m_pPresenter = m_lomse.new_document(ViewFactory::k_view_vertical_book,
"(lenmusdoc (vers 0.0) (content (score (vers 1.6) "
"(instrument (name \"Violin\")(abbrev \"Vln.\")(musicData "
"(clef F4)(key E)(time 2 4)(n +c3 e.)(barline)"
"(n e2 q)(n e3 q)(barline)"
"(n f2 e (beam 1 +))(n g2 e (beam 1 -))"
"(n f3 e (beam 3 +))(n g3 e (beam 3 -))(barline)"
"(n f2 e. (beam 4 +))(n g2 s (beam 4 -b))"
"(n f3 s (beam 5 +f))(n g3 e. (beam 5 -))(barline)"
"(n g2 e. (beam 2 +))(n e3 s (beam 2 -b))(n g3 q)(barline)"
"(n a2 e (beam 6 +))(n g2 e (beam 6 -))(n a3 q)(barline)"
"(n -b2 q)(n =b3 q)(barline)"
"(n xc3 q)(n ++c4 q)(barline)"
"(n d3 q)(n --d4 q)(barline)"
"(chord (n e3 q)(n c3 q)(n g3 q))"
"(n e4 q)(barline)"
"(n f3 q)(n f4 q)(barline end)"
"))"
"(instrument (name \"piano\")(abbrev \"P.\")(staves 2)(musicData "
"(clef G p1)(clef F4 p2)(key F)(time 12 8)"
"(n c5 e. p1)(barline)"
"(n e4 e p1 (beam 10 +))(n g3 e p2 (beam 10 -))"
"(n e4 e p1 (stem up)(beam 11 +))(n e5 e p1 (stem down)(beam 11 -))(barline)"
"(n e4 s p1 (beam 12 ++))(n f4 s p1 (beam 12 ==))"
"(n g4 s p1 (beam 12 ==))(n a4 s p1 (beam 12 --))"
"(n c5 q p1)(barline)"
"(n c4 q (slur 1 start))(n e4 q)"
"(barline)"
"(n g4 q )(n c5 q (slur 1 stop))"
"(barline)"
"(n e4 q (tie 1 start))(n e4 q (tie 1 stop))"
"(barline)"
"(n c4 e g+ t3/2)(n e4 e)(n d4 e g- t-)(n g4 q)"
"(barline)"
"(n c4 e t3/2)(n e4 e)(n d4 e t-)(n g4 q)"
"(barline)"
"))"
")))" );
//get the pointer to the interactor, set the rendering buffer and register for
//receiving desired events
if (SpInteractor spInteractor = m_pPresenter->get_interactor(0).lock())
{
//connect the View with the window buffer
spInteractor->set_rendering_buffer(&m_rbuf_window);
//ask to receive desired events
spInteractor->add_event_handler(k_update_window_event, this, wrapper_update_window);
//hide edition caret
spInteractor->hide_caret();
}
}
//---------------------------------------------------------------------------------------
void MyCanvas::force_redraw()
{
update_view_content();
update_window();
}
//---------------------------------------------------------------------------------------
void MyCanvas::wrapper_update_window(void* pThis, SpEventInfo pEvent)
{
static_cast<MyCanvas*>(pThis)->update_window();
}
//---------------------------------------------------------------------------------------
void MyCanvas::update_window()
{
// Invoking update_window() results in just putting immediately the content
// of the currently rendered buffer to the window without neither calling
// any lomse methods nor generating any events (i.e. Refresh() window)
wxClientDC dc(this);
copy_buffer_on_dc(dc);
}
//---------------------------------------------------------------------------------------
void MyCanvas::copy_buffer_on_dc(wxDC& dc)
{
if (!m_buffer || !m_buffer->IsOk())
return;
wxBitmap bitmap(*m_buffer);
dc.DrawBitmap(bitmap, 0, 0, false /* don't use mask */);
}
//-------------------------------------------------------------------------
void MyCanvas::update_view_content()
{
//request the view to re-draw the bitmap
if (!m_pPresenter) return;
if (SpInteractor spInteractor = m_pPresenter->get_interactor(0).lock())
spInteractor->redraw_bitmap();
}
//---------------------------------------------------------------------------------------
void MyCanvas::OnKeyDown(wxKeyEvent& event)
{
if (!m_pPresenter) return;
int nKeyCode = event.GetKeyCode();
unsigned flags = get_keyboard_flags(event);
//fix ctrol+key codes
if (nKeyCode > 0 && nKeyCode < 27)
{
nKeyCode += int('A') - 1;
flags |= k_kbd_ctrl;
}
//process key
switch (nKeyCode)
{
case WXK_SHIFT:
case WXK_ALT:
case WXK_CONTROL:
return; //do nothing
default:
on_key(event.GetX(), event.GetY(), nKeyCode, flags);;
}
}
//-------------------------------------------------------------------------
void MyCanvas::on_key(int x, int y, unsigned key, unsigned flags)
{
if (SpInteractor spInteractor = m_pPresenter->get_interactor(0).lock())
{
switch (key)
{
case 'D':
spInteractor->switch_task(TaskFactory::k_task_drag_view);
break;
case 'S':
spInteractor->switch_task(TaskFactory::k_task_selection);
break;
case '+':
spInteractor->zoom_in(x, y);
force_redraw();
break;
case '-':
spInteractor->zoom_out(x, y);
force_redraw();
break;
default:
return;
}
}
}
//-------------------------------------------------------------------------
void MyCanvas::zoom_in()
{
if (!m_pPresenter) return;
//do zoom in centered on window center
if (SpInteractor spInteractor = m_pPresenter->get_interactor(0).lock())
{
wxSize size = this->GetClientSize();
spInteractor->zoom_in(size.GetWidth()/2, size.GetHeight()/2);
force_redraw();
}
}
//-------------------------------------------------------------------------
void MyCanvas::zoom_out()
{
if (!m_pPresenter) return;
//do zoom out centered on window center
if (SpInteractor spInteractor = m_pPresenter->get_interactor(0).lock())
{
wxSize size = this->GetClientSize();
spInteractor->zoom_out(size.GetWidth()/2, size.GetHeight()/2);
force_redraw();
}
}
//---------------------------------------------------------------------------------------
unsigned MyCanvas::get_mouse_flags(wxMouseEvent& event)
{
unsigned flags = 0;
if (event.LeftIsDown()) flags |= k_mouse_left;
if (event.RightIsDown()) flags |= k_mouse_right;
if (event.MiddleDown()) flags |= k_mouse_middle;
if (event.ShiftDown()) flags |= k_kbd_shift;
if (event.AltDown()) flags |= k_kbd_alt;
if (event.ControlDown()) flags |= k_kbd_ctrl;
return flags;
}
//---------------------------------------------------------------------------------------
unsigned MyCanvas::get_keyboard_flags(wxKeyEvent& event)
{
unsigned flags = 0;
if (event.ShiftDown()) flags |= k_kbd_shift;
if (event.AltDown()) flags |= k_kbd_alt;
if (event.ControlDown()) flags |= k_kbd_ctrl;
return flags;
}
//-------------------------------------------------------------------------
void MyCanvas::OnMouseEvent(wxMouseEvent& event)
{
if (!m_pPresenter) return;
if (SpInteractor spInteractor = m_pPresenter->get_interactor(0).lock())
{
wxEventType nEventType = event.GetEventType();
wxPoint pos = event.GetPosition();
unsigned flags = get_mouse_flags(event);
if (nEventType==wxEVT_LEFT_DOWN)
{
flags |= k_mouse_left;
spInteractor->on_mouse_button_down(pos.x, pos.y, flags);
}
else if (nEventType==wxEVT_LEFT_UP)
{
flags |= k_mouse_left;
spInteractor->on_mouse_button_up(pos.x, pos.y, flags);
}
else if (nEventType==wxEVT_RIGHT_DOWN)
{
flags |= k_mouse_right;
spInteractor->on_mouse_button_down(pos.x, pos.y, flags);
}
else if (nEventType==wxEVT_RIGHT_UP)
{
flags |= k_mouse_right;
spInteractor->on_mouse_button_up(pos.x, pos.y, flags);
}
else if (nEventType==wxEVT_MOTION)
spInteractor->on_mouse_move(pos.x, pos.y, flags);
}
}