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 );
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
//----------------------------------------------------------------------------
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;
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 );
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;
#include <wx/image.h>
#include <wx/file.h>
#include <wx/timer.h>
+#include <wx/log.h>
+
#include "smile.xpm"
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)
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()
{
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();
}
}
}
+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 )
{
}
{
}
+//----------------------------------------------------------------------------
+// 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
//----------------------------------------------------------------------------
m_red = 0;
m_green = 0;
m_blue = 0;
+ m_lastMouse = (wxCanvasObject*)NULL;
+ m_frozen = FALSE;
}
wxCanvas::~wxCanvas()
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++)
}
}
+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)
{
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)