#include "wx/image.h"
#include "wx/txtstrm.h"
-
+
class wxCanvas;
// WDR: class declarations
{
public:
wxCanvasObject();
-
+
// Area occupied by object. Used for clipping, intersection,
// mouse enter etc. Screen coordinates
void SetArea( int x, int y, int width, int height );
void SetArea( wxRect rect );
-
+
// These are for screen output only therefore use
// int as coordinates.
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 );
-
+
// use doubles later
virtual void Move( int x, int y );
-
+
// Once we have world coordinates in doubles, this will get
// called for every object if the world coordinate system
// changes (zooming).
// Later...
virtual void WriteSVG( wxTextOutputStream &stream );
-
- wxCanvas *GetOwner() { return m_owner; }
- void SetOwner( wxCanvas *owner ) { m_owner = owner; }
-
+
+ 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 GetWidth() { return m_area.width; }
inline int GetHeight() { return m_area.height; }
+ void CaptureMouse();
+ void ReleaseMouse();
+ bool IsCapturedMouse();
+
protected:
wxCanvas *m_owner;
bool m_isControl;
bool m_isVector;
bool m_isImage;
wxRect m_area;
-
+
friend class wxCanvas;
};
class wxCanvasRect: public wxCanvasObject
{
public:
- wxCanvasRect( double x, double y, double w, double h,
+ wxCanvasRect( double x, double y, double w, double h,
unsigned char red, unsigned char green, unsigned char blue );
-
+
virtual void Recreate();
-
+
virtual void Render( int clip_x, int clip_y, int clip_width, int clip_height );
virtual void WriteSVG( wxTextOutputStream &stream );
-
+
private:
double m_x;
double m_y;
double m_width;
- double m_height;
+ double m_height;
unsigned char m_red;
unsigned char m_green;
class wxCanvasLine: public wxCanvasObject
{
public:
- wxCanvasLine( double x1, double y1, double x1, double y1,
+ wxCanvasLine( double x1, double y1, double x2, double y2,
unsigned char red, unsigned char green, unsigned char blue );
-
+
virtual void Recreate();
-
+
virtual void Render( int clip_x, int clip_y, int clip_width, int clip_height );
virtual void WriteSVG( wxTextOutputStream &stream );
double m_y1;
double m_x2;
double m_y2;
-
+
unsigned char m_red;
unsigned char m_green;
unsigned char m_blue;
public:
wxCanvasText( const wxString &text, double x, double y, const wxString &foneFile, int size );
~wxCanvasText();
-
+
void Recreate();
-
+
virtual void Render( int clip_x, int clip_y, int clip_width, int clip_height );
virtual void WriteSVG( wxTextOutputStream &stream );
void SetRGB( unsigned char red, unsigned char green, unsigned char blue );
void SetFlag( int flag );
int GetFlag() { return m_flag; }
-
+
private:
wxString m_text;
double m_x;
const wxSize& size = wxDefaultSize,
long style = wxScrolledWindowStyle );
virtual ~wxCanvas();
-
+
virtual void SetArea( int width, int height );
virtual void SetColour( unsigned char red, unsigned char green, unsigned char blue );
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 );
virtual void Remove( wxCanvasObject* obj );
-
+
// override these to change your coordiate system ...
virtual int GetDeviceX( double x );
virtual int GetDeviceY( double y );
virtual int GetDeviceWidth( double width );
virtual int GetDeviceHeight( double height );
-
+
// ... and call this to tell all objets to recreate then
virtual void Recreate();
- void CaptureMouse( wxCanvasObject *obj );
- void ReleaseMouse();
-
wxImage *GetBuffer() { return &m_buffer; }
bool NeedUpdate() { return m_needUpdate; }
bool IsFrozen() { return m_frozen; }
-
+
void BlitBuffer( wxDC &dc );
-
+
+ void SetCaptureMouse( wxCanvasObject *obj );
+
+
private:
wxImage m_buffer;
bool m_needUpdate;
bool m_frozen;
wxCanvasObject *m_lastMouse;
wxCanvasObject *m_captureMouse;
-
+
friend class wxCanvasObject;
-
+
private:
void OnChar( wxKeyEvent &event );
void OnPaint( wxPaintEvent &event );
{
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
(y <= m_area.y+m_area.height+margin));
}
+void wxCanvasObject::CaptureMouse()
+{
+ m_owner->SetCaptureMouse( this );
+}
+
+void wxCanvasObject::ReleaseMouse()
+{
+ m_owner->SetCaptureMouse( NULL );
+}
+
+bool wxCanvasObject::IsCapturedMouse()
+{
+ return m_owner->m_captureMouse==this;
+}
+
+
void wxCanvasObject::Render( int clip_x, int clip_y, int clip_width, int clip_height )
{
}
// wxCanvasRect
//----------------------------------------------------------------------------
-wxCanvasRect::wxCanvasRect( double x, double y, double w, double h,
+wxCanvasRect::wxCanvasRect( double x, double y, double w, double h,
unsigned char red, unsigned char green, unsigned char blue )
: wxCanvasObject()
{
m_y = y;
m_width = w;
m_height = h;
-
+
m_red = red;
m_green = green;
m_blue = blue;
ii = x2;
jj = y2;
-
+
if (ai > aj)
{
// iterate over i
- d = aj - (ai >> 1);
-
+ d = aj - (ai >> 1);
+
while (ii != x1)
{
if ((ii >= clip_x) && (ii <= clip_x+clip_width) &&
if (d >= 0)
{
jj += sj;
- d -= ai;
+ d -= ai;
}
ii += si;
d += aj;
if (d >= 0)
{
ii += si;
- d -= aj;
+ d -= aj;
}
jj += sj;
d += ai;
m_y = y;
m_width = w;
m_height = h;
-
+
m_image = image;
m_isImage = TRUE;
}
m_owner->GetDeviceY( m_y ),
m_owner->GetDeviceWidth( m_width ),
m_owner->GetDeviceHeight( m_height ) );
-
+
if ((m_area.width == m_image.GetWidth()) &&
(m_area.width == m_image.GetWidth()))
m_tmp = m_image;
void wxCanvasImage::Render( int clip_x, int clip_y, int clip_width, int clip_height )
{
- if ((clip_x == m_area.x) &&
- (clip_y == m_area.y) &&
+ if ((clip_x == m_area.x) &&
+ (clip_y == m_area.y) &&
(clip_width == m_area.width) &&
(clip_height == m_area.height))
{
// local coordinates
int start_x = clip_x - m_area.x;
int start_y = clip_y - m_area.y;
-
+
wxRect rect( start_x, start_y, clip_width, clip_height );
wxImage sub_image( m_tmp.GetSubImage( rect ) );
m_owner->GetBuffer()->Paste( sub_image, clip_x, clip_y );
FT_Face m_face;
#else
void *m_dummy;
-#endif
+#endif
};
wxCanvasText::wxCanvasText( const wxString &text, double x, double y, const wxString &fontFile, int size )
m_text = text;
m_fontFileName = fontFile;
m_size = size;
-
+
m_red = 0;
m_green = 0;
m_blue = 0;
-
+
m_alpha = NULL;
-
+
m_x = x;
m_y = y;
-
-#if wxUSE_FREETYPE
+
+#if wxUSE_FREETYPE
wxFaceData *data = new wxFaceData;
m_faceData = data;
-
+
int error = FT_New_Face( g_freetypeLibrary,
m_fontFileName,
0,
int red1 = (m_red * alpha) / 255;
int green1 = (m_green * alpha) / 255;
int blue1 = (m_blue * alpha) / 255;
-
+
alpha = 255-alpha;
int red2 = image->GetRed( image_x, image_y );
int green2 = image->GetGreen( image_x, image_y );
void wxCanvasText::Recreate()
{
if (m_alpha) delete [] m_alpha;
-
+
m_area.x = m_owner->GetDeviceX( m_x );
m_area.y = m_owner->GetDeviceY( m_y );
-
+
m_area.width = 100; // TODO, calculate length
m_area.height = m_size;
m_alpha = new unsigned char[100*m_size];
for (int n = 0; n < (int)m_text.Len(); n++)
{
FT_UInt index = FT_Get_Char_Index( face, m_text[n] );
-
+
int error = FT_Load_Glyph( face, index, FT_LOAD_DEFAULT );
if (error) continue;
{
unsigned char alpha = buffer[ y*bitmap->pitch + x ];
if (alpha == 0) continue;
-
+
int xx = pen_x + slot->bitmap_left + x;
int yy = pen_y - slot->bitmap_top + y;
m_alpha[ yy * m_area.width + xx ] = alpha;
m_red = red;
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++)
for (int x = 0; x < m_buffer.GetWidth(); x++)
{
}
}
-void wxCanvas::CaptureMouse( wxCanvasObject *obj )
-{
- wxWindow::CaptureMouse();
- m_captureMouse = obj;
-}
-
-void wxCanvas::ReleaseMouse()
+void wxCanvas::SetCaptureMouse( wxCanvasObject *obj )
{
- m_captureMouse = (wxCanvasObject*) NULL;
- wxWindow::ReleaseMouse();
+ if (obj)
+ {
+ wxWindow::CaptureMouse();
+ m_captureMouse = obj;
+ }
+ else
+ {
+ wxWindow::ReleaseMouse();
+ m_captureMouse = NULL;
+ }
}
void wxCanvas::Freeze()
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)
{
x = 0;
}
if (width < 0) return;
-
+
if (y < 0)
{
height -= y;
y = 0;
}
if (height < 0) return;
-
+
if (x+width > m_buffer.GetWidth())
{
width = m_buffer.GetWidth() - x;
}
if (width < 0) return;
-
+
if (y+height > m_buffer.GetHeight())
{
height = m_buffer.GetHeight() - y;
}
if (height < 0) return;
-
+
// update is within the buffer
m_needUpdate = TRUE;
-
+
// has to be blitted to screen later
m_updateRects.Append(
(wxObject*) new wxRect( x,y,width,height ) );
-
+
// speed up with direct access, maybe add wxImage::Clear(x,y,w,h,r,g,b)
for (int yy = y; yy < y+height; yy++)
for (int xx = x; xx < x+width; xx++)
while (node)
{
wxCanvasObject *obj = (wxCanvasObject*) node->Data();
-
+
if (!obj->IsControl())
{
// If we have 10.000 objects, we will go through
{
if (clip_x + clip_width > x + width)
clip_width = x+width-clip_x;
-
+
if (clip_width > 0)
{
int clip_y = obj->GetY();
{
if (clip_y + clip_height > y + height)
clip_height = y+height-clip_y;
-
+
if (clip_height > 0)
obj->Render( clip_x, clip_y, clip_width, clip_height );
}
}
}
}
-
+
node = node->Next();
}
}
// DirectDraw here, please
#ifdef __WXGTK__
- int bpp = wxDisplayDepth();
+ int bpp = wxDisplayDepth();
if (bpp > 8)
{
// the init code is doubled in wxImage
gdk_rgb_init();
s_hasInitialized = TRUE;
}
-
+
int x = rect->x;
int y = rect->y;
CalcScrolledPosition( x, y, &x, &y );
wxBitmap bitmap( sub_image.ConvertToBitmap() );
dc.DrawBitmap( bitmap, rect->x, rect->y );
#endif
-
+
delete rect;
m_updateRects.DeleteNode( node );
node = m_updateRects.First();
}
-
+
m_needUpdate = FALSE;
}
void wxCanvas::UpdateNow()
{
if (!m_needUpdate) return;
-
+
wxClientDC dc( this );
PrepareDC( dc );
-
+
BlitBuffer( dc );
}
while (node)
{
wxCanvasObject *obj = (wxCanvasObject*) node->Data();
-
+
obj->Recreate();
-
+
node = node->Next();
}
}
void wxCanvas::Prepend( wxCanvasObject* obj )
{
m_objects.Insert( obj );
-
+
obj->SetOwner( this );
obj->Recreate();
-
+
if (!obj->IsControl())
Update( obj->GetX(), obj->GetY(), obj->GetWidth(), obj->GetHeight() );
}
void wxCanvas::Append( wxCanvasObject* obj )
{
m_objects.Append( obj );
-
+
obj->SetOwner( this );
obj->Recreate();
-
+
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 );
obj->Recreate();
-
+
if (!obj->IsControl())
Update( obj->GetX(), obj->GetY(), obj->GetWidth(), obj->GetHeight() );
}
int w = obj->GetWidth();
int h = obj->GetHeight();
bool ic = obj->IsControl();
-
+
m_objects.DeleteObject( obj );
-
+
if (!ic)
Update( x, y, w, h );
}
{
wxPaintDC dc(this);
PrepareDC( dc );
-
+
m_needUpdate = TRUE;
wxRegionIterator it( GetUpdateRegion() );
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;
-
+
if ((w > 0) && (h > 0))
m_updateRects.Append( (wxObject*) new wxRect( x, y, w, h ) );
-
+
it++;
}
-
+
BlitBuffer( dc );
}
void wxCanvas::OnMouse(wxMouseEvent &event)
{
- // 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.Last();
- while (node)
+ if (m_captureMouse) //no matter what go to this one
{
- wxCanvasObject *obj = (wxCanvasObject*) node->Data();
-
- if (!obj->IsControl())
- {
- if (obj->IsHit(x,y))
+ wxMouseEvent child_event( wxEVT_MOTION );
+ child_event.SetEventObject(m_captureMouse);
+ child_event.m_x = x - m_captureMouse->GetX();
+ child_event.m_y = y - m_captureMouse->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_captureMouse->ProcessEvent( child_event );
+ }
+ else
+ {
+ wxNode *node = m_objects.Last();
+ while (node)
+ {
+ wxCanvasObject *obj = (wxCanvasObject*) node->Data();
+
+ if (!obj->IsControl())
{
- 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))
+ if (obj->IsHit(x,y))
{
- 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 );
+ 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;
}
- obj->ProcessEvent( child_event );
- return;
}
+ node = node->Previous();
}
- node = node->Previous();
}
if (m_lastMouse)
{
child_event.m_altDown = event.m_altDown;
child_event.m_metaDown = event.m_metaDown;
m_lastMouse->ProcessEvent( child_event );
-
+
m_lastMouse = (wxCanvasObject*) NULL;
return;
}