]> git.saurik.com Git - wxWidgets.git/commitdiff
Added wxCanvas prototype and sample
authorRobert Roebling <robert@roebling.de>
Tue, 29 Aug 2000 08:54:17 +0000 (08:54 +0000)
committerRobert Roebling <robert@roebling.de>
Tue, 29 Aug 2000 08:54:17 +0000 (08:54 +0000)
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@8205 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

contrib/configure
contrib/configure.in
contrib/include/wx/canvas/canvas.h [new file with mode: 0644]
contrib/samples/Makefile.in
contrib/samples/canvas/Makefile.in [new file with mode: 0644]
contrib/samples/canvas/test/Makefile.in [new file with mode: 0644]
contrib/samples/canvas/test/smile.xpm [new file with mode: 0644]
contrib/samples/canvas/test/test.cpp [new file with mode: 0644]
contrib/src/canvas/Makefile.in [new file with mode: 0644]
contrib/src/canvas/canvas.cpp [new file with mode: 0644]

index 3970312332de0ca31d132fc0649e7073b053af98..4cf145f63920b16d992d525f15f1223e3ed294ca 100755 (executable)
@@ -818,16 +818,19 @@ trap 'rm -fr `echo "
             src/mmedia/Makefile
             src/stc/Makefile
             src/xml/Makefile
-           src/gizmos/Makefile
+            src/canvas/Makefile
+            src/gizmos/Makefile
             samples/Makefile
             samples/mmedia/Makefile
             samples/ogl/Makefile
             samples/ogl/ogledit/Makefile
             samples/ogl/studio/Makefile
             samples/stc/Makefile
-           samples/gizmos/Makefile
-           samples/gizmos/multicell/Makefile
-           samples/gizmos/splittree/Makefile
+            samples/canvas/Makefile
+            samples/canvas/test/Makefile
+            samples/gizmos/Makefile
+            samples/gizmos/multicell/Makefile
+            samples/gizmos/splittree/Makefile
             utils/Makefile
             utils/wxrc/Makefile
             utils/wxrcedit/Makefile
@@ -915,16 +918,19 @@ CONFIG_FILES=\${CONFIG_FILES-"Makefile
             src/mmedia/Makefile
             src/stc/Makefile
             src/xml/Makefile
-           src/gizmos/Makefile
+            src/canvas/Makefile
+            src/gizmos/Makefile
             samples/Makefile
             samples/mmedia/Makefile
             samples/ogl/Makefile
             samples/ogl/ogledit/Makefile
             samples/ogl/studio/Makefile
             samples/stc/Makefile
-           samples/gizmos/Makefile
-           samples/gizmos/multicell/Makefile
-           samples/gizmos/splittree/Makefile
+            samples/canvas/Makefile
+            samples/canvas/test/Makefile
+            samples/gizmos/Makefile
+            samples/gizmos/multicell/Makefile
+            samples/gizmos/splittree/Makefile
             utils/Makefile
             utils/wxrc/Makefile
             utils/wxrcedit/Makefile
index c7ea557193f49f02b61ed732c6987cc3d2f52580..53c1dd041215027023555b7f079509d542271f90 100644 (file)
@@ -43,16 +43,19 @@ AC_OUTPUT([
             src/mmedia/Makefile
             src/stc/Makefile
             src/xml/Makefile
-           src/gizmos/Makefile
+            src/canvas/Makefile
+            src/gizmos/Makefile
             samples/Makefile
             samples/mmedia/Makefile
             samples/ogl/Makefile
             samples/ogl/ogledit/Makefile
             samples/ogl/studio/Makefile
             samples/stc/Makefile
-           samples/gizmos/Makefile
-           samples/gizmos/multicell/Makefile
-           samples/gizmos/splittree/Makefile
+            samples/canvas/Makefile
+            samples/canvas/test/Makefile
+            samples/gizmos/Makefile
+            samples/gizmos/multicell/Makefile
+            samples/gizmos/splittree/Makefile
             utils/Makefile
             utils/wxrc/Makefile
             utils/wxrcedit/Makefile
diff --git a/contrib/include/wx/canvas/canvas.h b/contrib/include/wx/canvas/canvas.h
new file mode 100644 (file)
index 0000000..4c2e43b
--- /dev/null
@@ -0,0 +1,128 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        canvas.h
+// Author:      Robert Roebling
+// Created:     XX/XX/XX
+// Copyright:   2000 (c) Robert Roebling
+// Licence:     wxWindows Licence
+/////////////////////////////////////////////////////////////////////////////
+
+#ifndef __WXCANVAS_H__
+#define __WXCANVAS_H__
+
+#ifdef __GNUG__
+    #pragma interface "canvas.cpp"
+#endif
+
+#ifndef WX_PRECOMP
+    #include "wx/wx.h"
+#endif
+
+#include "wx/image.h"
+#include "wx/txtstrm.h"
+                        
+class wxCanvas;
+
+// WDR: class declarations
+
+//----------------------------------------------------------------------------
+// wxCanvasObject
+//----------------------------------------------------------------------------
+
+class wxCanvasObject: public wxEvtHandler
+{
+public:
+    wxCanvasObject( int x, int y, int width, int height );
+    
+    virtual void Move( int x, int y );
+    virtual void Render( int clip_x, int clip_y, int clip_width, int clip_height );
+    virtual void WriteSVG( wxTextOutputStream &stream );
+    
+    wxCanvas   *GetOwner()              { return m_owner; }
+    void SetOwner( wxCanvas *owner )    { m_owner = owner; }
+    
+    bool        IsControl()     { return m_isControl; }
+    bool        IsVector()      { return m_isVector; }
+    bool        IsImage()       { return m_isImage; }
+    inline int  GetX()          { return m_area.x; }
+    inline int  GetY()          { return m_area.y; }
+    inline int  GetWidth()      { return m_area.width; }
+    inline int  GetHeight()     { return m_area.height; }
+
+protected:
+    wxCanvas   *m_owner;
+    bool        m_isControl;
+    bool        m_isVector;
+    bool        m_isImage;
+    wxRect      m_area;
+    
+    friend class wxCanvas;
+};
+
+//----------------------------------------------------------------------------
+// wxCanvasImage
+//----------------------------------------------------------------------------
+
+class wxCanvasImage: public wxCanvasObject
+{
+public:
+    wxCanvasImage( const wxImage &image, int x, int y );
+    
+    virtual void Render( int clip_x, int clip_y, int clip_width, int clip_height );
+    virtual void WriteSVG( wxTextOutputStream &stream );
+    
+private:
+    wxImage     m_image;
+};
+
+//----------------------------------------------------------------------------
+// wxCanvas
+//----------------------------------------------------------------------------
+
+class wxCanvas: public wxScrolledWindow
+{
+public:
+    // constructors and destructors
+    wxCanvas( wxWindow *parent, wxWindowID id = -1,
+        const wxPoint& pos = wxDefaultPosition,
+        const wxSize& size = wxDefaultSize,
+        long style = wxScrolledWindowStyle );
+    virtual ~wxCanvas();
+    
+    virtual void SetArea( int width, int height );
+    virtual void Update( int x, int y, int width, int height );
+    virtual void UpdateNow();
+    
+    virtual void Prepend( wxCanvasObject* obj );
+    virtual void Append( wxCanvasObject* obj );
+    virtual void Insert( size_t before, wxCanvasObject* obj );
+    virtual void Remove( wxCanvasObject* obj );
+    
+    wxImage *GetBuffer()         { return &m_buffer; }
+    bool NeedUpdate()            { return m_needUpdate; }
+    
+private:
+    wxImage     m_buffer;
+    bool        m_needUpdate;
+    wxList      m_updateRects;
+    wxList      m_objects;
+    
+    friend class wxCanvasObject;
+    
+private:
+    void OnChar( wxKeyEvent &event );
+    void OnPaint( wxPaintEvent &event );
+    void OnMouse( wxMouseEvent &event );
+    void OnSize( wxSizeEvent &event );
+    void OnIdle( wxIdleEvent &event );
+    void OnSetFocus( wxFocusEvent &event );
+    void OnKillFocus( wxFocusEvent &event );
+
+private:
+    DECLARE_CLASS(wxCanvas)
+    DECLARE_EVENT_TABLE()
+};
+
+
+#endif
+    // WXCANVAS
+
index 743f2eabb920321f7c8dfd2888c437a8f9a8c934..f867c03d66ed3afc461cdc02dd4ad214abf19583 100644 (file)
@@ -1,6 +1,6 @@
 # $Id$
 
-CONTRIB_SAMPLES=mmedia ogl stc gizmos
+CONTRIB_SAMPLES=mmedia ogl stc gizmos canvas
 
 all:
        @for d in $(CONTRIB_SAMPLES); do (cd $$d && $(MAKE)); done
diff --git a/contrib/samples/canvas/Makefile.in b/contrib/samples/canvas/Makefile.in
new file mode 100644 (file)
index 0000000..bde66ce
--- /dev/null
@@ -0,0 +1,10 @@
+# $Id$
+
+CONTRIB_SAMPLES=test
+
+all:
+       @for d in $(CONTRIB_SAMPLES); do (cd $$d && $(MAKE)); done
+
+clean:
+       @for d in $(CONTRIB_SAMPLES); do (cd $$d && $(MAKE) clean); done
+
diff --git a/contrib/samples/canvas/test/Makefile.in b/contrib/samples/canvas/test/Makefile.in
new file mode 100644 (file)
index 0000000..bce306e
--- /dev/null
@@ -0,0 +1,23 @@
+#
+# File:                Makefile.in
+# Author:      Julian Smart
+# Created:     2000
+# Updated:     
+# Copyright:   (c) 2000 Julian Smart
+#
+# "%W% %G%"
+#
+# Makefile for the multicell example (UNIX).
+
+top_srcdir = @top_srcdir@/..
+top_builddir = ../../../..
+program_dir = contrib/samples/canvas/test
+
+PROGRAM=test
+
+OBJECTS=test.o
+
+APPEXTRALIBS=$(top_builddir)/lib/libcanvas.@WX_TARGET_LIBRARY_TYPE@
+APPEXTRADEFS=-I$(top_srcdir)/contrib/include
+
+include $(top_builddir)/src/makeprog.env
diff --git a/contrib/samples/canvas/test/smile.xpm b/contrib/samples/canvas/test/smile.xpm
new file mode 100644 (file)
index 0000000..4773967
--- /dev/null
@@ -0,0 +1,42 @@
+/* XPM */
+static char * smile_xpm[] = {
+/* width height ncolors chars_per_pixel */
+"32 32 4 1",
+/* colors */
+"      s None  c None",
+".     c #000000",
+"+     c #ff0000",
+"@     c #ffff00",
+/* pixels */
+"            ........            ",
+"         ...@@@@@@@@...         ",
+"       ..@@@@@@@@@@@@@@..       ",
+"      ..@@@@@@@@@@@@@@@@..      ",
+"     .@@@@@@@@@@@@@@@@@@@@.     ",
+"    .@@@@@@@@@@@@@@@@@@@@@@.    ",
+"   .@@@@@@@@@@@@@@@@@@@@@@@@.   ",
+"  ..@@@@@@@@@@@@@@@@@@@@@@@@..  ",
+"  .@@@@@@@@  @@@@@@  @@@@@@@@.  ",
+" .@@@@@@@@    @@@@    @@@@@@@@. ",
+" .@@@@@@@@    @@@@    @@@@@@@@. ",
+" .@@@@@@@@    @@@@    @@@@@@@@. ",
+".@@@@@@@@@    @@@@    @@@@@@@@@.",
+".@@@@@@@@@    @@@@    @@@@@@@@@.",
+".@@@@@@@@@@  @@@@@@  @@@@@@@@@@.",
+".@@@@@@@.@@@@@@@@@@@@@@.@@@@@@@.",
+".@@@@@@@.@@@@@@@@@@@@@@.@@@@@@@.",
+".@@@@@@.@@@@@@@@@@@@@@@@.@@@@@@.",
+".@@@....@@@@@@@@@@@@@@@@....@@@.",
+".@@@@@@@.@@@@@@@@@@@@@@.@@@@@@@.",
+" .@@@@@@@.@@@@@@@@@@@@.@@@@@@@. ",
+" .@@@@@@@..@@@@@@@@@@..@@@@@@@. ",
+" .@@@@@@@@...@@@@@@...@@@@@@@@. ",
+"  .@@@@@@@@.+......+.@@@@@@@@.  ",
+"  ..@@@@@@@@.++++++.@@@@@@@@..  ",
+"   .@@@@@@@@@.++++.@@@@@@@@@.   ",
+"    .@@@@@@@@@....@@@@@@@@@.    ",
+"     .@@@@@@@@@@@@@@@@@@@@.     ",
+"      ..@@@@@@@@@@@@@@@@..      ",
+"       ..@@@@@@@@@@@@@@..       ",
+"         ...@@@@@@@@...         ",
+"            ........            "};
diff --git a/contrib/samples/canvas/test/test.cpp b/contrib/samples/canvas/test/test.cpp
new file mode 100644 (file)
index 0000000..c64b2ea
--- /dev/null
@@ -0,0 +1,152 @@
+/*
+ * Program: canvas
+ *
+ * Author: Robert Roebling
+ *
+ * Copyright: (C) 1998, Robert Roebling
+ *
+ */
+// For compilers that support precompilation, includes "wx/wx.h".
+#include "wx/wxprec.h"
+
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+
+#ifndef WX_PRECOMP
+#include "wx/wx.h"
+#endif
+
+#include <wx/image.h>
+#include <wx/file.h>
+#include <wx/timer.h>
+
+#include "smile.xpm"
+
+#include "wx/canvas/canvas.h"
+
+// derived classes
+
+class MyFrame;
+class MyApp;
+
+// MyFrame
+
+class MyFrame: public wxFrame
+{
+public:
+    MyFrame();
+    ~MyFrame();
+
+    void OnAbout( wxCommandEvent &event );
+    void OnNewFrame( wxCommandEvent &event );
+    void OnQuit( wxCommandEvent &event );
+    void OnTimer( wxTimerEvent &event );
+
+    wxCanvas        *m_canvas;
+    wxCanvasObject  *m_co;
+    wxTimer         *m_timer;
+
+private:
+    DECLARE_DYNAMIC_CLASS(MyFrame)
+    DECLARE_EVENT_TABLE()
+};
+
+// MyApp
+
+class MyApp: public wxApp
+{
+public:
+    virtual bool OnInit();
+};
+
+// main program
+
+IMPLEMENT_APP(MyApp)
+
+// MyFrame
+
+const int ID_QUIT  = 108;
+const int ID_ABOUT = 109;
+
+IMPLEMENT_DYNAMIC_CLASS( MyFrame, wxFrame )
+
+BEGIN_EVENT_TABLE(MyFrame,wxFrame)
+  EVT_MENU    (ID_ABOUT, MyFrame::OnAbout)
+  EVT_MENU    (ID_QUIT,  MyFrame::OnQuit)
+  EVT_TIMER   (-1,       MyFrame::OnTimer)
+END_EVENT_TABLE()
+
+MyFrame::MyFrame()
+       : wxFrame( (wxFrame *)NULL, -1, "wxCanvas sample",
+                  wxPoint(20,20), wxSize(470,360) )
+{
+  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->SetArea( 400, 600 );
+  
+  wxBitmap bitmap( smile_xpm );
+  wxImage image( bitmap );
+  m_co = new wxCanvasImage( image, 10, 50 );
+  m_canvas->Append( m_co );
+  
+  m_canvas->Append( new wxCanvasImage( image, 80, 50 ) );
+  
+  m_timer = new wxTimer( this );
+  m_timer->Start( 150, FALSE );
+}
+
+MyFrame::~MyFrame()
+{
+   delete m_timer;
+}
+
+void MyFrame::OnQuit( wxCommandEvent &WXUNUSED(event) )
+{
+    Close( TRUE );
+}
+
+void MyFrame::OnTimer( wxTimerEvent &WXUNUSED(event) )
+{
+    m_co->Move( m_co->GetX()+1, m_co->GetY() );
+    wxWakeUpIdle();
+}
+
+void MyFrame::OnAbout( wxCommandEvent &WXUNUSED(event) )
+{
+   (void)wxMessageBox( "wxCanvas demo\n"
+                      "Robert Roebling (c) 1998,2000",
+                      "About wxCanvas Demo", wxICON_INFORMATION | wxOK );
+}
+
+//-----------------------------------------------------------------------------
+// MyApp
+//-----------------------------------------------------------------------------
+
+bool MyApp::OnInit()
+{
+#if wxUSE_LIBPNG
+  wxImage::AddHandler( new wxPNGHandler );
+#endif
+
+  wxFrame *frame = new MyFrame();
+  frame->Show( TRUE );
+
+  return TRUE;
+}
+
+
diff --git a/contrib/src/canvas/Makefile.in b/contrib/src/canvas/Makefile.in
new file mode 100644 (file)
index 0000000..3cf2445
--- /dev/null
@@ -0,0 +1,23 @@
+# $Id$
+
+top_srcdir = @top_srcdir@/..
+top_builddir = ../../..
+libsrc_dir = contrib/src/canvas
+
+TARGET_LIBNAME=libcanvas
+
+LIBVERSION_CURRENT=1
+LIBVERSION_REVISION=0
+LIBVERSION_AGE=0
+
+HEADER_PATH=$(top_srcdir)/contrib/include/wx
+HEADER_SUBDIR=canvas
+
+HEADERS=canvas.h
+
+OBJECTS=canvas.o
+
+APPEXTRADEFS=-I$(top_srcdir)/contrib/include
+
+include $(top_builddir)/src/makelib.env
+
diff --git a/contrib/src/canvas/canvas.cpp b/contrib/src/canvas/canvas.cpp
new file mode 100644 (file)
index 0000000..5f0b371
--- /dev/null
@@ -0,0 +1,324 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        canvas.cpp
+// Author:      Robert Roebling
+// Created:     XX/XX/XX
+// Copyright:   2000 (c) Robert Roebling
+// Licence:     wxWindows Licence
+/////////////////////////////////////////////////////////////////////////////
+
+#ifdef __GNUG__
+    #pragma implementation "canvas.cpp"
+#endif
+
+// For compilers that support precompilation, includes "wx/wx.h".
+#include "wx/wxprec.h"
+
+#ifdef __BORLANDC__
+    #pragma hdrstop
+#endif
+
+#include "wx/canvas/canvas.h"
+
+#ifdef __WXGTK__
+    #include <gtk/gtk.h>
+    #include <gdk/gdkrgb.h>
+    #include "wx/gtk/win_gtk.h"
+#endif
+
+// WDR: class implementations
+
+//----------------------------------------------------------------------------
+// wxCanvasObject
+//----------------------------------------------------------------------------
+
+wxCanvasObject::wxCanvasObject( int x, int y, int width, int height )
+{
+    m_owner = NULL;
+    m_area.x = x;
+    m_area.y = y;
+    m_area.width = width;
+    m_area.height = height;
+    m_isControl = FALSE;
+    m_isVector = FALSE;
+    m_isImage = FALSE;
+}
+
+void wxCanvasObject::Move( int x, int y )
+{
+    int old_x = m_area.x;
+    int old_y = m_area.y;
+    
+    m_area.x = x;
+    m_area.y = y;
+    
+    if (!m_isControl)
+    {
+        // TODO: sometimes faster to merge into 1 Update or
+        // to break up into four
+        m_owner->Update( old_x, old_y, m_area.width, m_area.height );
+        m_owner->Update( x, y, m_area.width, m_area.height );
+    }
+}
+
+void wxCanvasObject::WriteSVG( wxTextOutputStream &stream )
+{
+}
+
+void wxCanvasObject::Render( int clip_x, int clip_y, int clip_width, int clip_height )
+{
+}
+
+//----------------------------------------------------------------------------
+// wxCanvasImage
+//----------------------------------------------------------------------------
+
+wxCanvasImage::wxCanvasImage( const wxImage &image, int x, int y )
+   : wxCanvasObject( x, y, image.GetWidth(), image.GetHeight() )
+{
+    m_image = image;
+    m_isImage = TRUE;
+}
+
+void wxCanvasImage::Render( int clip_x, int clip_y, int clip_width, int clip_height )
+{
+    m_owner->GetBuffer()->Paste( m_image, m_area.x, m_area.y );
+}
+
+void wxCanvasImage::WriteSVG( wxTextOutputStream &stream )
+{
+    // no idea
+}
+
+//----------------------------------------------------------------------------
+// wxCanvas
+//----------------------------------------------------------------------------
+
+IMPLEMENT_CLASS(wxCanvas,wxScrolledWindow)
+
+BEGIN_EVENT_TABLE(wxCanvas,wxScrolledWindow)
+    EVT_CHAR( wxCanvas::OnChar )
+    EVT_PAINT( wxCanvas::OnPaint )
+    EVT_SIZE( wxCanvas::OnSize )
+    EVT_IDLE( wxCanvas::OnIdle )
+    EVT_MOUSE_EVENTS( wxCanvas::OnMouse )
+    EVT_SET_FOCUS( wxCanvas::OnSetFocus )
+    EVT_KILL_FOCUS( wxCanvas::OnKillFocus )
+END_EVENT_TABLE()
+
+wxCanvas::wxCanvas( wxWindow *parent, wxWindowID id,
+    const wxPoint &position, const wxSize& size, long style ) :
+    wxScrolledWindow( parent, id, position, size, style )
+{
+    m_needUpdate = FALSE;
+    m_objects.DeleteContents( TRUE );
+}
+
+wxCanvas::~wxCanvas()
+{
+    wxNode *node = m_updateRects.First();
+    while (node)
+    {
+        wxRect *rect = (wxRect*) node->Data();
+        delete rect;
+        m_updateRects.DeleteNode( node );
+        node = m_updateRects.First();
+    }
+}
+
+void wxCanvas::SetArea( int width, int height )
+{
+    m_buffer = wxImage( width, height );
+    SetScrollbars( 10, 10, width/10, height/10 );
+}
+
+void wxCanvas::Update( int x, int y, int width, int height )
+{
+    m_needUpdate = TRUE;
+    
+    m_updateRects.Append(
+        (wxObject*) new wxRect( x,y,width,height ) );
+    
+    // speed up with direct access
+    int xx,yy,ww,hh;
+    for (yy = y; yy < y+height; yy++)
+        for (xx = x; xx < x+width; xx++)
+            m_buffer.SetRGB( xx, yy, 0, 0, 0 );
+
+    wxNode *node = m_objects.First();
+    while (node)
+    {
+        wxCanvasObject *obj = (wxCanvasObject*) node->Data();
+        xx = obj->GetX();
+        yy = obj->GetY();
+        ww = obj->GetWidth();
+        hh = obj->GetHeight();
+            
+        // if intersect
+        {
+            obj->Render( x, y, width, height );
+        }
+            
+        node = node->Next();
+    }
+}
+
+void wxCanvas::UpdateNow()
+{
+    if (!m_needUpdate) return;
+    
+    wxClientDC dc( this );
+    PrepareDC( dc );
+    
+    wxNode *node = m_updateRects.First();
+    while (node)
+    {
+        wxRect *rect = (wxRect*) node->Data();
+        wxImage sub_image( m_buffer.GetSubImage( *rect ) );
+
+        // DirectDraw here, please
+
+#ifdef __WXGTK__
+        int bpp = wxDisplayDepth(); 
+        if (bpp > 8)
+        {
+            // the init code is doubled in wxImage
+            static bool s_hasInitialized = FALSE;
+
+            if (!s_hasInitialized)
+            {
+                gdk_rgb_init();
+                s_hasInitialized = TRUE;
+            }
+            
+            int x = rect->x;
+            int y = rect->y;
+            CalcScrolledPosition( x, y, &x, &y );
+
+            gdk_draw_rgb_image( GTK_PIZZA(m_wxwindow)->bin_window,
+                            m_wxwindow->style->black_gc,
+                            x, y,
+                            sub_image.GetWidth(), sub_image.GetHeight(),
+                            GDK_RGB_DITHER_NONE,
+                            sub_image.GetData(),
+                            sub_image.GetWidth()*3 );
+        }
+        else
+        {
+            wxBitmap bitmap( sub_image.ConvertToBitmap() );
+            dc.DrawBitmap( bitmap, rect->x, rect->y );
+        }
+#endif
+
+#ifndef __WXGTK__
+        wxBitmap bitmap( sub_image.ConvertToBitmap() );
+        dc.DrawBitmap( bitmap, rect->x, rect->y );
+#endif
+        
+        delete rect;
+        m_updateRects.DeleteNode( node );
+        node = m_updateRects.First();
+    }
+}
+
+void wxCanvas::Prepend( wxCanvasObject* obj )
+{
+    m_objects.Insert( obj );
+    
+    obj->SetOwner( this );
+    
+    if (!obj->IsControl())
+        Update( obj->GetX(), obj->GetY(), obj->GetWidth(), obj->GetHeight() );
+}
+
+void wxCanvas::Append( wxCanvasObject* obj )
+{
+    m_objects.Append( obj );
+    
+    obj->SetOwner( this );
+    
+    if (!obj->IsControl())
+        Update( obj->GetX(), obj->GetY(), obj->GetWidth(), obj->GetHeight() );
+}
+
+void wxCanvas::Insert( size_t before, wxCanvasObject* obj )
+{
+    m_objects.Insert( before, obj );
+    
+    obj->SetOwner( this );
+    
+    if (!obj->IsControl())
+        Update( obj->GetX(), obj->GetY(), obj->GetWidth(), obj->GetHeight() );
+}
+
+void wxCanvas::Remove( wxCanvasObject* obj )
+{
+    int x = obj->GetX();
+    int y = obj->GetY();
+    int w = obj->GetWidth();
+    int h = obj->GetHeight();
+    bool ic = obj->IsControl();
+    
+    m_objects.DeleteObject( obj );
+    
+    if (!ic)
+        Update( x, y, w, h );
+}
+
+void wxCanvas::OnPaint(wxPaintEvent &event)
+{
+#ifdef __WXMSW__
+    wxPaintDC dc(this);
+#endif
+    
+    m_needUpdate = TRUE;
+
+    wxRegionIterator it( GetUpdateRegion() );
+    while (it)
+    {
+        int x = it.GetX();
+        int y = it.GetY();
+        CalcUnscrolledPosition( x, y, &x, &y );
+        
+        int w = it.GetWidth();
+        int h = it.GetHeight();
+        if (x + w > m_buffer.GetWidth())
+            w = m_buffer.GetWidth()-x;
+        if (y + h > m_buffer.GetHeight())
+            h = m_buffer.GetHeight()-y;
+        
+        m_updateRects.Append( (wxObject*) new wxRect( x, y, w, h ) );
+        
+        it++;
+    }
+}
+
+void wxCanvas::OnMouse(wxMouseEvent &event)
+{
+    // Propagate to objects here
+}
+
+void wxCanvas::OnSize(wxSizeEvent &event)
+{
+    event.Skip();
+}
+
+void wxCanvas::OnIdle(wxIdleEvent &event)
+{
+    UpdateNow();
+    event.Skip();
+}
+
+void wxCanvas::OnSetFocus(wxFocusEvent &event)
+{
+}
+
+void wxCanvas::OnKillFocus(wxFocusEvent &event)
+{
+}
+
+void wxCanvas::OnChar(wxKeyEvent &event)
+{
+    event.Skip();
+}
+
+