From 239c1f50b033b9205f3c371ad803a6e9d1d9b3fd Mon Sep 17 00:00:00 2001 From: Robert Roebling Date: Sat, 2 Sep 2000 18:01:32 +0000 Subject: [PATCH] Added wxCanvasLine, Freeze() and Thaw() and mouse events (untested) git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@8241 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- contrib/include/wx/canvas/canvas.h | 37 ++++- contrib/samples/canvas/test/test.cpp | 102 +++++++++----- contrib/src/canvas/canvas.cpp | 196 ++++++++++++++++++++++++++- 3 files changed, 294 insertions(+), 41 deletions(-) diff --git a/contrib/include/wx/canvas/canvas.h b/contrib/include/wx/canvas/canvas.h index cdcb441b0d..6c3747eed2 100644 --- a/contrib/include/wx/canvas/canvas.h +++ b/contrib/include/wx/canvas/canvas.h @@ -34,6 +34,8 @@ public: wxCanvasObject( int x, int y, int width, int height ); virtual void Move( int x, int y ); + virtual bool IsHit( int x, int y, int margin = 0 ); + virtual void Render( int clip_x, int clip_y, int clip_width, int clip_height ); virtual void WriteSVG( wxTextOutputStream &stream ); @@ -76,6 +78,24 @@ private: unsigned char m_blue; }; +//---------------------------------------------------------------------------- +// wxCanvasLine +//---------------------------------------------------------------------------- + +class wxCanvasLine: public wxCanvasObject +{ +public: + wxCanvasLine( int x, int y, int w, int h, unsigned char red, unsigned char green, unsigned char blue ); + + virtual void Render( int clip_x, int clip_y, int clip_width, int clip_height ); + virtual void WriteSVG( wxTextOutputStream &stream ); + +private: + unsigned char m_red; + unsigned char m_green; + unsigned char m_blue; +}; + //---------------------------------------------------------------------------- // wxCanvasImage //---------------------------------------------------------------------------- @@ -125,6 +145,7 @@ public: void CreateBuffer(); void SetRGB( unsigned char red, unsigned char green, unsigned char blue ); void SetFlag( int flag ); + int GetFlag() { return m_flag; } private: wxString m_text; @@ -157,6 +178,9 @@ public: virtual void Update( int x, int y, int width, int height ); virtual void UpdateNow(); + virtual void Freeze(); + virtual void Thaw(); + virtual void Prepend( wxCanvasObject* obj ); virtual void Append( wxCanvasObject* obj ); virtual void Insert( size_t before, wxCanvasObject* obj ); @@ -168,11 +192,14 @@ public: void BlitBuffer( wxDC &dc ); private: - wxImage m_buffer; - bool m_needUpdate; - wxList m_updateRects; - wxList m_objects; - unsigned char m_green,m_red,m_blue; + wxImage m_buffer; + bool m_needUpdate; + wxList m_updateRects; + wxList m_objects; + unsigned char m_green,m_red,m_blue; + bool m_frozen; + wxCanvasObject *m_lastMouse; + friend class wxCanvasObject; diff --git a/contrib/samples/canvas/test/test.cpp b/contrib/samples/canvas/test/test.cpp index e31de9ae4a..6f109d3f2c 100644 --- a/contrib/samples/canvas/test/test.cpp +++ b/contrib/samples/canvas/test/test.cpp @@ -20,6 +20,8 @@ #include #include #include +#include + #include "smile.xpm" @@ -43,10 +45,13 @@ public: void OnQuit( wxCommandEvent &event ); void OnTimer( wxTimerEvent &event ); - wxCanvas *m_canvas; - wxCanvasObject *m_sm1; - wxCanvasObject *m_sm2; - wxTimer *m_timer; + wxCanvas *m_canvas; + wxCanvasObject *m_sm1; + wxCanvasObject *m_sm2; + wxCanvasObject *m_sm3; + wxCanvasObject *m_sm4; + wxTimer *m_timer; + wxTextCtrl *m_log; private: DECLARE_DYNAMIC_CLASS(MyFrame) @@ -85,51 +90,76 @@ END_EVENT_TABLE() MyFrame::MyFrame() : wxFrame( (wxFrame *)NULL, -1, "wxCanvas sample", - wxPoint(20,20), wxSize(470,360) ) + wxPoint(20,20), wxSize(470,460) ) { - wxMenu *file_menu = new wxMenu(); - file_menu->Append( ID_ABOUT, "&About..."); - file_menu->AppendSeparator(); - file_menu->Append( ID_QUIT, "E&xit"); + wxMenu *file_menu = new wxMenu(); + file_menu->Append( ID_ABOUT, "&About..."); + file_menu->AppendSeparator(); + file_menu->Append( ID_QUIT, "E&xit"); + + wxMenuBar *menu_bar = new wxMenuBar(); + menu_bar->Append(file_menu, "&File"); + + SetMenuBar( menu_bar ); + + CreateStatusBar(2); + int widths[] = { -1, 100 }; + SetStatusWidths( 2, widths ); + + m_canvas = new wxCanvas( this, -1, wxPoint(0,0), wxSize(10,10) ); + + m_canvas->Freeze(); + + m_canvas->SetArea( 400, 600 ); + m_canvas->SetColour( 255, 255, 255 ); - wxMenuBar *menu_bar = new wxMenuBar(); - menu_bar->Append(file_menu, "&File"); + wxBitmap bitmap( smile_xpm ); + wxImage image( bitmap ); - SetMenuBar( menu_bar ); + m_sm1 = new wxCanvasImage( image, 0, 70 ); + m_canvas->Append( m_sm1 ); - CreateStatusBar(2); - int widths[] = { -1, 100 }; - SetStatusWidths( 2, widths ); + int i; + for (i = 10; i < 300; i+=10) + m_canvas->Append( new wxCanvasRect( i,50,3,140, 255,0,0 ) ); - m_canvas = new wxCanvas( this, -1, wxPoint(0,0), wxSize(10,10) ); + m_sm2 = new wxCanvasImage( image, 0, 140 ); + m_canvas->Append( m_sm2 ); - m_canvas->SetArea( 400, 600 ); - m_canvas->SetColour( 255, 255, 255 ); + for (i = 15; i < 300; i+=10) + m_canvas->Append( new wxCanvasRect( i,50,3,140, 255,0,0 ) ); - wxBitmap bitmap( smile_xpm ); - wxImage image( bitmap ); + wxButton *button = new wxButton( m_canvas, -1, "Hello", wxPoint(80,50) ); + m_canvas->Append( new wxCanvasControl( button ) ); - m_sm1 = new wxCanvasImage( image, 0, 70 ); - m_canvas->Append( m_sm1 ); + m_canvas->Append( new wxCanvasText( "Hello", 180, 50, + wxGetApp().GetFontPath() + "/times.ttf", 20 ) ); - int i; - for (i = 10; i < 300; i+=10) - m_canvas->Append( new wxCanvasRect( i,50,3,140, 255,0,0 ) ); + m_sm3 = new wxCanvasImage( image, 0, 210 ); + m_canvas->Append( m_sm3 ); - m_sm2 = new wxCanvasImage( image, 0, 140 ); - m_canvas->Append( m_sm2 ); + for (i = 10; i < 300; i+=10) + m_canvas->Append( new wxCanvasLine( 10,150,i,200, 0,255,0 ) ); + + m_sm4 = new wxCanvasImage( image, 0, 270 ); + m_canvas->Append( m_sm4 ); - for (i = 15; i < 300; i+=10) - m_canvas->Append( new wxCanvasRect( i,50,3,140, 255,0,0 ) ); + m_canvas->Thaw(); - wxButton *button = new wxButton( m_canvas, -1, "Hello", wxPoint(80,50) ); - m_canvas->Append( new wxCanvasControl( button ) ); + m_log = new wxTextCtrl( this, -1, "", wxPoint(0,0), wxSize(100,100), wxTE_MULTILINE ); + wxLog *old_log = wxLog::SetActiveTarget( new wxLogTextCtrl( m_log ) ); + delete old_log; + + wxBoxSizer *topsizer = new wxBoxSizer( wxVERTICAL ); + + topsizer->Add( m_canvas, 1, wxEXPAND ); + topsizer->Add( m_log, 0, wxEXPAND ); - m_canvas->Append( new wxCanvasText( "Hello", 180, 50, - wxGetApp().GetFontPath() + "/times.ttf", 20 ) ); + SetAutoLayout( TRUE ); + SetSizer( topsizer ); - m_timer = new wxTimer( this ); - m_timer->Start( 100, FALSE ); + m_timer = new wxTimer( this ); + m_timer->Start( 100, FALSE ); } MyFrame::~MyFrame() @@ -146,6 +176,8 @@ void MyFrame::OnTimer( wxTimerEvent &WXUNUSED(event) ) { m_sm1->Move( m_sm1->GetX()+1, m_sm1->GetY() ); m_sm2->Move( m_sm2->GetX()+1, m_sm2->GetY() ); + m_sm3->Move( m_sm3->GetX()+1, m_sm3->GetY() ); + m_sm4->Move( m_sm4->GetX()+1, m_sm4->GetY() ); wxWakeUpIdle(); } diff --git a/contrib/src/canvas/canvas.cpp b/contrib/src/canvas/canvas.cpp index 109ec8f2da..e248757bdc 100644 --- a/contrib/src/canvas/canvas.cpp +++ b/contrib/src/canvas/canvas.cpp @@ -72,6 +72,14 @@ void wxCanvasObject::Move( int x, int y ) } } +bool wxCanvasObject::IsHit( int x, int y, int margin ) +{ + return ((x >= m_area.x-margin) && + (x <= m_area.x+m_area.width+margin) && + (y >= m_area.y-margin) && + (y <= m_area.y+m_area.height+margin)); +} + void wxCanvasObject::WriteSVG( wxTextOutputStream &stream ) { } @@ -105,6 +113,93 @@ void wxCanvasRect::WriteSVG( wxTextOutputStream &stream ) { } +//---------------------------------------------------------------------------- +// wxCanvasLine +//---------------------------------------------------------------------------- + +wxCanvasLine::wxCanvasLine( int x, int y, int w, int h, unsigned char red, unsigned char green, unsigned char blue ) + : wxCanvasObject( x, y, w, h ) +{ + m_red = red; + m_green = green; + m_blue = blue; +} + +void wxCanvasLine::Render( int clip_x, int clip_y, int clip_width, int clip_height ) +{ + wxImage *image = m_owner->GetBuffer(); + + if ((m_area.width == 0) && (m_area.height == 0)) + { + image->SetRGB( m_area.x, m_area.y, m_red, m_green, m_blue ); + } + else + { + int x1 = m_area.x; + int y1 = m_area.y; + int x2 = m_area.x+m_area.width; + int y2 = m_area.y+m_area.height; + + wxInt32 d, ii, jj, di, ai, si, dj, aj, sj; + di = x1 - x2; + ai = abs(di) << 1; + si = (di < 0)? -1 : 1; + dj = y1 - y2; + aj = abs(dj) << 1; + sj = (dj < 0)? -1 : 1; + + ii = x2; + jj = y2; + + if (ai > aj) + { + // iterate over i + d = aj - (ai >> 1); + + while (ii != x1) + { + if ((ii >= clip_x) && (ii <= clip_x+clip_width) && + (jj >= clip_y) && (jj <= clip_y+clip_height)) + { + image->SetRGB( ii, jj, m_red, m_blue, m_green ); + } + if (d >= 0) + { + jj += sj; + d -= ai; + } + ii += si; + d += aj; + } + } + else + { + // iterate over j + d = ai - (aj >> 1); + + while (jj != y1) + { + if ((ii >= clip_x) && (ii <= clip_x+clip_width) && + (jj >= clip_y) && (jj <= clip_y+clip_height)) + { + image->SetRGB( ii, jj, m_red, m_blue, m_green ); + } + if (d >= 0) + { + ii += si; + d -= aj; + } + jj += sj; + d += ai; + } + } + } +} + +void wxCanvasLine::WriteSVG( wxTextOutputStream &stream ) +{ +} + //---------------------------------------------------------------------------- // wxCanvasImage //---------------------------------------------------------------------------- @@ -349,6 +444,8 @@ wxCanvas::wxCanvas( wxWindow *parent, wxWindowID id, m_red = 0; m_green = 0; m_blue = 0; + m_lastMouse = (wxCanvasObject*)NULL; + m_frozen = FALSE; } wxCanvas::~wxCanvas() @@ -375,6 +472,8 @@ void wxCanvas::SetColour( unsigned char red, unsigned char green, unsigned char m_green = green; m_blue = blue; + if (m_frozen) return; + unsigned char *data = m_buffer.GetData(); for (int y = 0; y < m_buffer.GetHeight(); y++) @@ -389,8 +488,31 @@ void wxCanvas::SetColour( unsigned char red, unsigned char green, unsigned char } } +void wxCanvas::Freeze() +{ + m_frozen = TRUE; +} + +void wxCanvas::Thaw() +{ + wxNode *node = m_updateRects.First(); + while (node) + { + wxRect *rect = (wxRect*) node->Data(); + delete rect; + m_updateRects.DeleteNode( node ); + node = m_updateRects.First(); + } + + m_frozen = FALSE; + + Update( 0, 0, m_buffer.GetWidth(), m_buffer.GetHeight() ); +} + void wxCanvas::Update( int x, int y, int width, int height ) { + if (m_frozen) return; + // clip to buffer if (x < 0) { @@ -620,7 +742,79 @@ void wxCanvas::OnPaint(wxPaintEvent &event) void wxCanvas::OnMouse(wxMouseEvent &event) { - // Propagate to objects here + // should we implement mouse capture ? + + int x = event.GetX(); + int y = event.GetY(); + CalcUnscrolledPosition( x, y, &x, &y ); + + if (event.GetEventType() == wxEVT_MOTION) + { + wxNode *node = m_objects.First(); + while (node) + { + wxCanvasObject *obj = (wxCanvasObject*) node->Data(); + + if (!obj->IsControl()) + { + if (obj->IsHit(x,y)) + { + wxMouseEvent child_event( wxEVT_MOTION ); + child_event.SetEventObject( obj ); + child_event.m_x = x + obj->GetX(); + child_event.m_y = y + obj->GetY(); + child_event.m_leftDown = event.m_leftDown; + child_event.m_rightDown = event.m_rightDown; + child_event.m_middleDown = event.m_middleDown; + child_event.m_controlDown = event.m_controlDown; + child_event.m_shiftDown = event.m_shiftDown; + child_event.m_altDown = event.m_altDown; + child_event.m_metaDown = event.m_metaDown; + + if ((obj != m_lastMouse) && (m_lastMouse != NULL)) + { + child_event.SetEventType( wxEVT_LEAVE_WINDOW ); + child_event.SetEventObject( m_lastMouse ); + child_event.m_x = x + m_lastMouse->GetX(); + child_event.m_y = y + m_lastMouse->GetY(); + m_lastMouse->ProcessEvent( child_event ); + + m_lastMouse = obj; + child_event.SetEventType( wxEVT_ENTER_WINDOW ); + child_event.SetEventObject( m_lastMouse ); + child_event.m_x = x + m_lastMouse->GetX(); + child_event.m_y = y + m_lastMouse->GetY(); + m_lastMouse->ProcessEvent( child_event ); + + child_event.SetEventType( wxEVT_MOTION ); + child_event.SetEventObject( obj ); + } + obj->ProcessEvent( child_event ); + return; + } + } + node = node->Next(); + } + if (m_lastMouse) + { + wxMouseEvent child_event( wxEVT_LEAVE_WINDOW ); + child_event.SetEventObject( m_lastMouse ); + child_event.m_x = x + m_lastMouse->GetX(); + child_event.m_y = y + m_lastMouse->GetY(); + child_event.m_leftDown = event.m_leftDown; + child_event.m_rightDown = event.m_rightDown; + child_event.m_middleDown = event.m_middleDown; + child_event.m_controlDown = event.m_controlDown; + child_event.m_shiftDown = event.m_shiftDown; + child_event.m_altDown = event.m_altDown; + child_event.m_metaDown = event.m_metaDown; + m_lastMouse->ProcessEvent( child_event ); + + m_lastMouse = (wxCanvasObject*) NULL; + return; + } + } + event.Skip(); } void wxCanvas::OnSize(wxSizeEvent &event) -- 2.47.2