wxWidgets/samples/drawing/drawing.cpp
Vadim Zeitlin 9273033d5a Partially account for the shifted origin in wxBufferedDC.
This change slightly improves wxBufferedDC and wxBufferedPaintDC behaviour
when the origin of the DC is shifted, but they still don't work quite right in
this case as they don't use the buffer area of correct size in this case,
which results in cropping the final bitmap (as can be seen in the drawing
sample, which was modified to show wxBufferedPaintDC in action).

Closes #15497.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@74951 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
2013-10-07 09:58:56 +00:00

2066 lines
63 KiB
C++

/////////////////////////////////////////////////////////////////////////////
// Name: samples/drawing/drawing.cpp
// Purpose: shows and tests wxDC features
// Author: Robert Roebling
// Modified by:
// Created: 04/01/98
// Copyright: (c) Robert Roebling
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
// ============================================================================
// declarations
// ============================================================================
// ----------------------------------------------------------------------------
// headers
// ----------------------------------------------------------------------------
// For compilers that support precompilation, includes "wx/wx.h".
#include "wx/wxprec.h"
#ifdef __BORLANDC__
#pragma hdrstop
#endif
// for all others, include the necessary headers (this file is usually all you
// need because it includes almost all "standard" wxWidgets headers
#ifndef WX_PRECOMP
#include "wx/wx.h"
#endif
#include "wx/colordlg.h"
#include "wx/image.h"
#include "wx/artprov.h"
#include "wx/dcbuffer.h"
#include "wx/dcgraph.h"
#include "wx/overlay.h"
#include "wx/graphics.h"
#include "wx/filename.h"
#include "wx/metafile.h"
#define TEST_CAIRO_EVERYWHERE 0
// ----------------------------------------------------------------------------
// resources
// ----------------------------------------------------------------------------
// the application icon
#ifndef wxHAS_IMAGES_IN_RESOURCES
#include "../sample.xpm"
#endif
// ----------------------------------------------------------------------------
// global variables
// ----------------------------------------------------------------------------
static wxBitmap *gs_bmpNoMask = NULL,
*gs_bmpWithColMask = NULL,
*gs_bmpMask = NULL,
*gs_bmpWithMask = NULL,
*gs_bmp4 = NULL,
*gs_bmp4_mono = NULL,
*gs_bmp36 = NULL;
// ----------------------------------------------------------------------------
// private classes
// ----------------------------------------------------------------------------
// Define a new application type, each program should derive a class from wxApp
class MyApp : public wxApp
{
public:
// override base class virtuals
// ----------------------------
// this one is called on application startup and is a good place for the app
// initialization (doing it here and not in the ctor allows to have an error
// return: if OnInit() returns false, the application terminates)
virtual bool OnInit();
virtual int OnExit() { DeleteBitmaps(); return 0; }
protected:
void DeleteBitmaps();
bool LoadImages();
};
class MyCanvas;
// Define a new frame type: this is going to be our main frame
class MyFrame : public wxFrame
{
public:
// ctor(s)
MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size);
// event handlers (these functions should _not_ be virtual)
void OnQuit(wxCommandEvent& event);
void OnAbout(wxCommandEvent& event);
void OnClip(wxCommandEvent& event);
#if wxUSE_GRAPHICS_CONTEXT
void OnGraphicContext(wxCommandEvent& event);
#endif
void OnBuffer(wxCommandEvent& event);
void OnCopy(wxCommandEvent& event);
void OnSave(wxCommandEvent& event);
void OnShow(wxCommandEvent &event);
void OnOption(wxCommandEvent &event);
#if wxUSE_COLOURDLG
wxColour SelectColour();
#endif // wxUSE_COLOURDLG
void PrepareDC(wxDC& dc);
int m_backgroundMode;
int m_textureBackground;
wxMappingMode m_mapMode;
double m_xUserScale;
double m_yUserScale;
int m_xLogicalOrigin;
int m_yLogicalOrigin;
bool m_xAxisReversed,
m_yAxisReversed;
wxColour m_colourForeground, // these are _text_ colours
m_colourBackground;
wxBrush m_backgroundBrush;
MyCanvas *m_canvas;
private:
// any class wishing to process wxWidgets events must use this macro
DECLARE_EVENT_TABLE()
};
// define a scrollable canvas for drawing onto
class MyCanvas: public wxScrolledWindow
{
public:
MyCanvas( MyFrame *parent );
void OnPaint(wxPaintEvent &event);
void OnMouseMove(wxMouseEvent &event);
void OnMouseDown(wxMouseEvent &event);
void OnMouseUp(wxMouseEvent &event);
void ToShow(int show) { m_show = show; Refresh(); }
// set or remove the clipping region
void Clip(bool clip) { m_clip = clip; Refresh(); }
#if wxUSE_GRAPHICS_CONTEXT
void UseGraphicContext(bool use) { m_useContext = use; Refresh(); }
#endif
void UseBuffer(bool use) { m_useBuffer = use; Refresh(); }
void Draw(wxDC& dc);
protected:
enum DrawMode
{
Draw_Normal,
Draw_Stretch
};
void DrawTestLines( int x, int y, int width, wxDC &dc );
void DrawTestPoly(wxDC& dc);
void DrawTestBrushes(wxDC& dc);
void DrawText(wxDC& dc);
void DrawImages(wxDC& dc, DrawMode mode);
void DrawWithLogicalOps(wxDC& dc);
#if wxUSE_GRAPHICS_CONTEXT
void DrawAlpha(wxDC& dc);
void DrawGraphics(wxGraphicsContext* gc);
#endif
void DrawRegions(wxDC& dc);
void DrawCircles(wxDC& dc);
void DrawSplines(wxDC& dc);
void DrawDefault(wxDC& dc);
void DrawGradients(wxDC& dc);
void DrawRegionsHelper(wxDC& dc, wxCoord x, bool firstTime);
private:
MyFrame *m_owner;
int m_show;
wxBitmap m_smile_bmp;
wxIcon m_std_icon;
bool m_clip;
wxOverlay m_overlay;
bool m_rubberBand;
wxPoint m_anchorpoint;
wxPoint m_currentpoint;
#if wxUSE_GRAPHICS_CONTEXT
bool m_useContext ;
#endif
bool m_useBuffer;
DECLARE_EVENT_TABLE()
};
// ----------------------------------------------------------------------------
// constants
// ----------------------------------------------------------------------------
// IDs for the controls and the menu commands
enum
{
// menu items
File_Quit = wxID_EXIT,
File_About = wxID_ABOUT,
MenuShow_First = wxID_HIGHEST,
File_ShowDefault = MenuShow_First,
File_ShowText,
File_ShowLines,
File_ShowBrushes,
File_ShowPolygons,
File_ShowMask,
File_ShowMaskStretch,
File_ShowOps,
File_ShowRegions,
File_ShowCircles,
File_ShowSplines,
#if wxUSE_GRAPHICS_CONTEXT
File_ShowAlpha,
File_ShowGraphics,
#endif
File_ShowGradients,
MenuShow_Last = File_ShowGradients,
File_Clip,
#if wxUSE_GRAPHICS_CONTEXT
File_GraphicContext,
#endif
File_Buffer,
File_Copy,
File_Save,
MenuOption_First,
MapMode_Text = MenuOption_First,
MapMode_Lometric,
MapMode_Twips,
MapMode_Points,
MapMode_Metric,
UserScale_StretchHoriz,
UserScale_ShrinkHoriz,
UserScale_StretchVertic,
UserScale_ShrinkVertic,
UserScale_Restore,
AxisMirror_Horiz,
AxisMirror_Vertic,
LogicalOrigin_MoveDown,
LogicalOrigin_MoveUp,
LogicalOrigin_MoveLeft,
LogicalOrigin_MoveRight,
LogicalOrigin_Set,
LogicalOrigin_Restore,
#if wxUSE_COLOURDLG
Colour_TextForeground,
Colour_TextBackground,
Colour_Background,
#endif // wxUSE_COLOURDLG
Colour_BackgroundMode,
Colour_TextureBackgound,
MenuOption_Last = Colour_TextureBackgound
};
// ----------------------------------------------------------------------------
// event tables and other macros for wxWidgets
// ----------------------------------------------------------------------------
// Create a new application object: this macro will allow wxWidgets to create
// the application object during program execution (it's better than using a
// static object for many reasons) and also declares the accessor function
// wxGetApp() which will return the reference of the right type (i.e. MyApp and
// not wxApp)
IMPLEMENT_APP(MyApp)
// ============================================================================
// implementation
// ============================================================================
// ----------------------------------------------------------------------------
// the application class
// ----------------------------------------------------------------------------
bool MyApp::LoadImages()
{
gs_bmpNoMask = new wxBitmap;
gs_bmpWithColMask = new wxBitmap;
gs_bmpMask = new wxBitmap;
gs_bmpWithMask = new wxBitmap;
gs_bmp4 = new wxBitmap;
gs_bmp4_mono = new wxBitmap;
gs_bmp36 = new wxBitmap;
wxPathList pathList;
// special hack for Unix in-tree sample build, don't do this in real
// programs, use wxStandardPaths instead
pathList.Add(wxFileName(argv[0]).GetPath());
pathList.Add(wxT("."));
pathList.Add(wxT(".."));
pathList.Add(wxT("../.."));
wxString path = pathList.FindValidPath(wxT("pat4.bmp"));
if ( !path )
return false;
/* 4 colour bitmap */
gs_bmp4->LoadFile(path, wxBITMAP_TYPE_BMP);
/* turn into mono-bitmap */
gs_bmp4_mono->LoadFile(path, wxBITMAP_TYPE_BMP);
wxMask* mask4 = new wxMask(*gs_bmp4_mono, *wxBLACK);
gs_bmp4_mono->SetMask(mask4);
path = pathList.FindValidPath(wxT("pat36.bmp"));
if ( !path )
return false;
gs_bmp36->LoadFile(path, wxBITMAP_TYPE_BMP);
wxMask* mask36 = new wxMask(*gs_bmp36, *wxBLACK);
gs_bmp36->SetMask(mask36);
path = pathList.FindValidPath(wxT("image.bmp"));
if ( !path )
return false;
gs_bmpNoMask->LoadFile(path, wxBITMAP_TYPE_BMP);
gs_bmpWithMask->LoadFile(path, wxBITMAP_TYPE_BMP);
gs_bmpWithColMask->LoadFile(path, wxBITMAP_TYPE_BMP);
path = pathList.FindValidPath(wxT("mask.bmp"));
if ( !path )
return false;
gs_bmpMask->LoadFile(path, wxBITMAP_TYPE_BMP);
wxMask *mask = new wxMask(*gs_bmpMask, *wxBLACK);
gs_bmpWithMask->SetMask(mask);
mask = new wxMask(*gs_bmpWithColMask, *wxWHITE);
gs_bmpWithColMask->SetMask(mask);
return true;
}
// `Main program' equivalent: the program execution "starts" here
bool MyApp::OnInit()
{
if ( !wxApp::OnInit() )
return false;
// Create the main application window
MyFrame *frame = new MyFrame(wxT("Drawing sample"),
wxDefaultPosition, wxSize(550, 840));
// Show it
frame->Show(true);
if ( !LoadImages() )
{
wxLogError(wxT("Can't load one of the bitmap files needed ")
wxT("for this sample from the current or parent ")
wxT("directory, please copy them there."));
// still continue, the sample can be used without images too if they're
// missing for whatever reason
}
#if wxUSE_LIBPNG
wxImage::AddHandler( new wxPNGHandler );
#endif
return true;
}
void MyApp::DeleteBitmaps()
{
wxDELETE(gs_bmpNoMask);
wxDELETE(gs_bmpWithColMask);
wxDELETE(gs_bmpMask);
wxDELETE(gs_bmpWithMask);
wxDELETE(gs_bmp4);
wxDELETE(gs_bmp4_mono);
wxDELETE(gs_bmp36);
}
// ----------------------------------------------------------------------------
// MyCanvas
// ----------------------------------------------------------------------------
// the event tables connect the wxWidgets events with the functions (event
// handlers) which process them.
BEGIN_EVENT_TABLE(MyCanvas, wxScrolledWindow)
EVT_PAINT (MyCanvas::OnPaint)
EVT_MOTION (MyCanvas::OnMouseMove)
EVT_LEFT_DOWN (MyCanvas::OnMouseDown)
EVT_LEFT_UP (MyCanvas::OnMouseUp)
END_EVENT_TABLE()
#include "smile.xpm"
MyCanvas::MyCanvas(MyFrame *parent)
: wxScrolledWindow(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize,
wxHSCROLL | wxVSCROLL | wxNO_FULL_REPAINT_ON_RESIZE)
{
m_owner = parent;
m_show = File_ShowDefault;
m_smile_bmp = wxBitmap(smile_xpm);
m_std_icon = wxArtProvider::GetIcon(wxART_INFORMATION);
m_clip = false;
m_rubberBand = false;
#if wxUSE_GRAPHICS_CONTEXT
m_useContext = false;
#endif
m_useBuffer = false;
}
void MyCanvas::DrawTestBrushes(wxDC& dc)
{
static const wxCoord WIDTH = 200;
static const wxCoord HEIGHT = 80;
wxCoord x = 10,
y = 10;
dc.SetBrush(*wxGREEN_BRUSH);
dc.DrawRectangle(x, y, WIDTH, HEIGHT);
dc.DrawText(wxT("Solid green"), x + 10, y + 10);
y += HEIGHT;
dc.SetBrush(wxBrush(*wxRED, wxBRUSHSTYLE_CROSSDIAG_HATCH));
dc.DrawRectangle(x, y, WIDTH, HEIGHT);
dc.DrawText(wxT("Diagonally hatched red"), x + 10, y + 10);
y += HEIGHT;
dc.SetBrush(wxBrush(*wxBLUE, wxBRUSHSTYLE_CROSS_HATCH));
dc.DrawRectangle(x, y, WIDTH, HEIGHT);
dc.DrawText(wxT("Cross hatched blue"), x + 10, y + 10);
y += HEIGHT;
dc.SetBrush(wxBrush(*wxCYAN, wxBRUSHSTYLE_VERTICAL_HATCH));
dc.DrawRectangle(x, y, WIDTH, HEIGHT);
dc.DrawText(wxT("Vertically hatched cyan"), x + 10, y + 10);
y += HEIGHT;
dc.SetBrush(wxBrush(*wxBLACK, wxBRUSHSTYLE_HORIZONTAL_HATCH));
dc.DrawRectangle(x, y, WIDTH, HEIGHT);
dc.DrawText(wxT("Horizontally hatched black"), x + 10, y + 10);
y += HEIGHT;
dc.SetBrush(wxBrush(*gs_bmpMask));
dc.DrawRectangle(x, y, WIDTH, HEIGHT);
dc.DrawText(wxT("Stipple mono"), x + 10, y + 10);
y += HEIGHT;
dc.SetBrush(wxBrush(*gs_bmpNoMask));
dc.DrawRectangle(x, y, WIDTH, HEIGHT);
dc.DrawText(wxT("Stipple colour"), x + 10, y + 10);
}
void MyCanvas::DrawTestPoly(wxDC& dc)
{
wxBrush brushHatch(*wxRED, wxBRUSHSTYLE_FDIAGONAL_HATCH);
dc.SetBrush(brushHatch);
wxPoint star[5];
star[0] = wxPoint(100, 60);
star[1] = wxPoint(60, 150);
star[2] = wxPoint(160, 100);
star[3] = wxPoint(40, 100);
star[4] = wxPoint(140, 150);
dc.DrawText(wxT("You should see two (irregular) stars below, the left one ")
wxT("hatched"), 10, 10);
dc.DrawText(wxT("except for the central region and the right ")
wxT("one entirely hatched"), 10, 30);
dc.DrawText(wxT("The third star only has a hatched outline"), 10, 50);
dc.DrawPolygon(WXSIZEOF(star), star, 0, 30);
dc.DrawPolygon(WXSIZEOF(star), star, 160, 30, wxWINDING_RULE);
wxPoint star2[10];
star2[0] = wxPoint(0, 100);
star2[1] = wxPoint(-59, -81);
star2[2] = wxPoint(95, 31);
star2[3] = wxPoint(-95, 31);
star2[4] = wxPoint(59, -81);
star2[5] = wxPoint(0, 80);
star2[6] = wxPoint(-47, -64);
star2[7] = wxPoint(76, 24);
star2[8] = wxPoint(-76, 24);
star2[9] = wxPoint(47, -64);
int count[2] = {5, 5};
dc.DrawPolyPolygon(WXSIZEOF(count), count, star2, 450, 150);
}
void MyCanvas::DrawTestLines( int x, int y, int width, wxDC &dc )
{
dc.SetPen( wxPen( *wxBLACK, width ) );
dc.SetBrush( *wxRED_BRUSH );
dc.DrawText(wxString::Format(wxT("Testing lines of width %d"), width), x + 10, y - 10);
dc.DrawRectangle( x+10, y+10, 100, 190 );
dc.DrawText(wxT("Solid/dot/short dash/long dash/dot dash"), x + 150, y + 10);
dc.SetPen( wxPen( *wxBLACK, width ) );
dc.DrawLine( x+20, y+20, 100, y+20 );
dc.SetPen( wxPen( *wxBLACK, width, wxPENSTYLE_DOT) );
dc.DrawLine( x+20, y+30, 100, y+30 );
dc.SetPen( wxPen( *wxBLACK, width, wxPENSTYLE_SHORT_DASH) );
dc.DrawLine( x+20, y+40, 100, y+40 );
dc.SetPen( wxPen( *wxBLACK, width, wxPENSTYLE_LONG_DASH) );
dc.DrawLine( x+20, y+50, 100, y+50 );
dc.SetPen( wxPen( *wxBLACK, width, wxPENSTYLE_DOT_DASH) );
dc.DrawLine( x+20, y+60, 100, y+60 );
dc.DrawText(wxT("Misc hatches"), x + 150, y + 70);
dc.SetPen( wxPen( *wxBLACK, width, wxPENSTYLE_BDIAGONAL_HATCH) );
dc.DrawLine( x+20, y+70, 100, y+70 );
dc.SetPen( wxPen( *wxBLACK, width, wxPENSTYLE_CROSSDIAG_HATCH) );
dc.DrawLine( x+20, y+80, 100, y+80 );
dc.SetPen( wxPen( *wxBLACK, width, wxPENSTYLE_FDIAGONAL_HATCH) );
dc.DrawLine( x+20, y+90, 100, y+90 );
dc.SetPen( wxPen( *wxBLACK, width, wxPENSTYLE_CROSS_HATCH) );
dc.DrawLine( x+20, y+100, 100, y+100 );
dc.SetPen( wxPen( *wxBLACK, width, wxPENSTYLE_HORIZONTAL_HATCH) );
dc.DrawLine( x+20, y+110, 100, y+110 );
dc.SetPen( wxPen( *wxBLACK, width, wxPENSTYLE_VERTICAL_HATCH) );
dc.DrawLine( x+20, y+120, 100, y+120 );
dc.DrawText(wxT("User dash"), x + 150, y + 140);
wxPen ud( *wxBLACK, width, wxPENSTYLE_USER_DASH );
wxDash dash1[6];
dash1[0] = 8; // Long dash <---------+
dash1[1] = 2; // Short gap |
dash1[2] = 3; // Short dash |
dash1[3] = 2; // Short gap |
dash1[4] = 3; // Short dash |
dash1[5] = 2; // Short gap and repeat +
ud.SetDashes( 6, dash1 );
dc.SetPen( ud );
dc.DrawLine( x+20, y+140, 100, y+140 );
dash1[0] = 5; // Make first dash shorter
ud.SetDashes( 6, dash1 );
dc.SetPen( ud );
dc.DrawLine( x+20, y+150, 100, y+150 );
dash1[2] = 5; // Make second dash longer
ud.SetDashes( 6, dash1 );
dc.SetPen( ud );
dc.DrawLine( x+20, y+160, 100, y+160 );
dash1[4] = 5; // Make third dash longer
ud.SetDashes( 6, dash1 );
dc.SetPen( ud );
dc.DrawLine( x+20, y+170, 100, y+170 );
}
void MyCanvas::DrawDefault(wxDC& dc)
{
// Draw circle centered at the origin, then flood fill it with a different
// color. Done with a wxMemoryDC because Blit (used by generic
// wxDoFloodFill) from a window that is being painted gives unpredictable
// results on wxGTK
{
wxImage img(21, 21, false);
img.Clear(1);
wxBitmap bmp(img);
{
wxMemoryDC mdc(bmp);
mdc.SetBrush(dc.GetBrush());
mdc.SetPen(dc.GetPen());
mdc.DrawCircle(10, 10, 10);
wxColour c;
if (mdc.GetPixel(11, 11, &c))
{
mdc.SetBrush(wxColour(128, 128, 0));
mdc.FloodFill(11, 11, c, wxFLOOD_SURFACE);
}
}
bmp.SetMask(new wxMask(bmp, wxColour(1, 1, 1)));
dc.DrawBitmap(bmp, -10, -10, true);
}
dc.DrawCheckMark(5, 80, 15, 15);
dc.DrawCheckMark(25, 80, 30, 30);
dc.DrawCheckMark(60, 80, 60, 60);
// this is the test for "blitting bitmap into DC damages selected brush" bug
wxCoord rectSize = m_std_icon.GetWidth() + 10;
wxCoord x = 100;
dc.SetPen(*wxTRANSPARENT_PEN);
dc.SetBrush( *wxGREEN_BRUSH );
dc.DrawRectangle(x, 10, rectSize, rectSize);
dc.DrawBitmap(m_std_icon, x + 5, 15, true);
x += rectSize + 10;
dc.DrawRectangle(x, 10, rectSize, rectSize);
dc.DrawIcon(m_std_icon, x + 5, 15);
x += rectSize + 10;
dc.DrawRectangle(x, 10, rectSize, rectSize);
// test for "transparent" bitmap drawing (it intersects with the last
// rectangle above)
//dc.SetBrush( *wxTRANSPARENT_BRUSH );
if (m_smile_bmp.IsOk())
dc.DrawBitmap(m_smile_bmp, x + rectSize - 20, rectSize - 10, true);
dc.SetBrush( *wxBLACK_BRUSH );
dc.DrawRectangle( 0, 160, 1000, 300 );
// draw lines
wxBitmap bitmap(20,70);
wxMemoryDC memdc;
memdc.SelectObject( bitmap );
memdc.SetBrush( *wxBLACK_BRUSH );
memdc.SetPen( *wxWHITE_PEN );
memdc.DrawRectangle(0,0,20,70);
memdc.DrawLine( 10,0,10,70 );
// to the right
wxPen pen = *wxRED_PEN;
memdc.SetPen(pen);
memdc.DrawLine( 10, 5,10, 5 );
memdc.DrawLine( 10,10,11,10 );
memdc.DrawLine( 10,15,12,15 );
memdc.DrawLine( 10,20,13,20 );
/*
memdc.SetPen(*wxRED_PEN);
memdc.DrawLine( 12, 5,12, 5 );
memdc.DrawLine( 12,10,13,10 );
memdc.DrawLine( 12,15,14,15 );
memdc.DrawLine( 12,20,15,20 );
*/
// same to the left
memdc.DrawLine( 10,25,10,25 );
memdc.DrawLine( 10,30, 9,30 );
memdc.DrawLine( 10,35, 8,35 );
memdc.DrawLine( 10,40, 7,40 );
// XOR draw lines
dc.SetPen(*wxWHITE_PEN);
memdc.SetLogicalFunction( wxINVERT );
memdc.SetPen( *wxWHITE_PEN );
memdc.DrawLine( 10,50,10,50 );
memdc.DrawLine( 10,55,11,55 );
memdc.DrawLine( 10,60,12,60 );
memdc.DrawLine( 10,65,13,65 );
memdc.DrawLine( 12,50,12,50 );
memdc.DrawLine( 12,55,13,55 );
memdc.DrawLine( 12,60,14,60 );
memdc.DrawLine( 12,65,15,65 );
memdc.SelectObject( wxNullBitmap );
dc.DrawBitmap( bitmap, 10, 170 );
wxImage image = bitmap.ConvertToImage();
image.Rescale( 60,210 );
bitmap = wxBitmap(image);
dc.DrawBitmap( bitmap, 50, 170 );
// test the rectangle outline drawing - there should be one pixel between
// the rect and the lines
dc.SetPen(*wxWHITE_PEN);
dc.SetBrush( *wxTRANSPARENT_BRUSH );
dc.DrawRectangle(150, 170, 49, 29);
dc.DrawRectangle(200, 170, 49, 29);
dc.SetPen(*wxWHITE_PEN);
dc.DrawLine(250, 210, 250, 170);
dc.DrawLine(260, 200, 150, 200);
// test the rectangle filled drawing - there should be one pixel between
// the rect and the lines
dc.SetPen(*wxTRANSPARENT_PEN);
dc.SetBrush( *wxWHITE_BRUSH );
dc.DrawRectangle(300, 170, 49, 29);
dc.DrawRectangle(350, 170, 49, 29);
dc.SetPen(*wxWHITE_PEN);
dc.DrawLine(400, 170, 400, 210);
dc.DrawLine(300, 200, 410, 200);
// a few more tests of this kind
dc.SetPen(*wxRED_PEN);
dc.SetBrush( *wxWHITE_BRUSH );
dc.DrawRectangle(300, 220, 1, 1);
dc.DrawRectangle(310, 220, 2, 2);
dc.DrawRectangle(320, 220, 3, 3);
dc.DrawRectangle(330, 220, 4, 4);
dc.SetPen(*wxTRANSPARENT_PEN);
dc.SetBrush( *wxWHITE_BRUSH );
dc.DrawRectangle(300, 230, 1, 1);
dc.DrawRectangle(310, 230, 2, 2);
dc.DrawRectangle(320, 230, 3, 3);
dc.DrawRectangle(330, 230, 4, 4);
// and now for filled rect with outline
dc.SetPen(*wxRED_PEN);
dc.SetBrush( *wxWHITE_BRUSH );
dc.DrawRectangle(500, 170, 49, 29);
dc.DrawRectangle(550, 170, 49, 29);
dc.SetPen(*wxWHITE_PEN);
dc.DrawLine(600, 170, 600, 210);
dc.DrawLine(500, 200, 610, 200);
// test the rectangle outline drawing - there should be one pixel between
// the rect and the lines
dc.SetPen(*wxWHITE_PEN);
dc.SetBrush( *wxTRANSPARENT_BRUSH );
dc.DrawRoundedRectangle(150, 270, 49, 29, 6);
dc.DrawRoundedRectangle(200, 270, 49, 29, 6);
dc.SetPen(*wxWHITE_PEN);
dc.DrawLine(250, 270, 250, 310);
dc.DrawLine(150, 300, 260, 300);
// test the rectangle filled drawing - there should be one pixel between
// the rect and the lines
dc.SetPen(*wxTRANSPARENT_PEN);
dc.SetBrush( *wxWHITE_BRUSH );
dc.DrawRoundedRectangle(300, 270, 49, 29, 6);
dc.DrawRoundedRectangle(350, 270, 49, 29, 6);
dc.SetPen(*wxWHITE_PEN);
dc.DrawLine(400, 270, 400, 310);
dc.DrawLine(300, 300, 410, 300);
// Added by JACS to demonstrate bizarre behaviour.
// With a size of 70, we get a missing red RHS,
// and the height is too small, so we get yellow
// showing. With a size of 40, it draws as expected:
// it just shows a white rectangle with red outline.
int totalWidth = 70;
int totalHeight = 70;
wxBitmap bitmap2(totalWidth, totalHeight);
wxMemoryDC memdc2;
memdc2.SelectObject(bitmap2);
memdc2.SetBackground(*wxYELLOW_BRUSH);
memdc2.Clear();
// Now draw a white rectangle with red outline. It should
// entirely eclipse the yellow background.
memdc2.SetPen(*wxRED_PEN);
memdc2.SetBrush(*wxWHITE_BRUSH);
memdc2.DrawRectangle(0, 0, totalWidth, totalHeight);
memdc2.SetPen(wxNullPen);
memdc2.SetBrush(wxNullBrush);
memdc2.SelectObject(wxNullBitmap);
dc.DrawBitmap(bitmap2, 500, 270);
// Repeat, but draw directly on dc
// Draw a yellow rectangle filling the bitmap
x = 600; int y = 270;
dc.SetPen(*wxYELLOW_PEN);
dc.SetBrush(*wxYELLOW_BRUSH);
dc.DrawRectangle(x, y, totalWidth, totalHeight);
// Now draw a white rectangle with red outline. It should
// entirely eclipse the yellow background.
dc.SetPen(*wxRED_PEN);
dc.SetBrush(*wxWHITE_BRUSH);
dc.DrawRectangle(x, y, totalWidth, totalHeight);
}
void MyCanvas::DrawText(wxDC& dc)
{
// set underlined font for testing
dc.SetFont( wxFont(12, wxMODERN, wxNORMAL, wxNORMAL, true) );
dc.DrawText( wxT("This is text"), 110, 10 );
dc.DrawRotatedText( wxT("That is text"), 20, 10, -45 );
// use wxSWISS_FONT and not wxNORMAL_FONT as the latter can't be rotated
// under Win9x (it is not TrueType)
dc.SetFont( *wxSWISS_FONT );
wxString text;
dc.SetBackgroundMode(wxTRANSPARENT);
for ( int n = -180; n < 180; n += 30 )
{
text.Printf(wxT(" %d rotated text"), n);
dc.DrawRotatedText(text , 400, 400, n);
}
dc.SetFont( wxFont( 18, wxSWISS, wxNORMAL, wxNORMAL ) );
dc.DrawText( wxT("This is Swiss 18pt text."), 110, 40 );
wxCoord length;
wxCoord height;
wxCoord descent;
dc.GetTextExtent( wxT("This is Swiss 18pt text."), &length, &height, &descent );
text.Printf( wxT("Dimensions are length %d, height %d, descent %d"), length, height, descent );
dc.DrawText( text, 110, 80 );
text.Printf( wxT("CharHeight() returns: %d"), dc.GetCharHeight() );
dc.DrawText( text, 110, 120 );
dc.DrawRectangle( 100, 40, 4, height );
// test the logical function effect
wxCoord y = 150;
dc.SetLogicalFunction(wxINVERT);
// text drawing should ignore logical function
dc.DrawText( wxT("There should be a text below"), 110, 150 );
dc.DrawRectangle( 110, y, 100, height );
y += height;
dc.DrawText( wxT("Visible text"), 110, y );
dc.DrawRectangle( 110, y, 100, height );
dc.DrawText( wxT("Visible text"), 110, y );
dc.DrawRectangle( 110, y, 100, height );
dc.SetLogicalFunction(wxCOPY);
y += height;
dc.DrawRectangle( 110, y, 100, height );
dc.DrawText( wxT("Another visible text"), 110, y );
y += height;
dc.DrawText("And\nmore\ntext on\nmultiple\nlines", 110, y);
}
static const struct
{
const wxChar *name;
wxRasterOperationMode rop;
} rasterOperations[] =
{
{ wxT("wxAND"), wxAND },
{ wxT("wxAND_INVERT"), wxAND_INVERT },
{ wxT("wxAND_REVERSE"), wxAND_REVERSE },
{ wxT("wxCLEAR"), wxCLEAR },
{ wxT("wxCOPY"), wxCOPY },
{ wxT("wxEQUIV"), wxEQUIV },
{ wxT("wxINVERT"), wxINVERT },
{ wxT("wxNAND"), wxNAND },
{ wxT("wxNO_OP"), wxNO_OP },
{ wxT("wxOR"), wxOR },
{ wxT("wxOR_INVERT"), wxOR_INVERT },
{ wxT("wxOR_REVERSE"), wxOR_REVERSE },
{ wxT("wxSET"), wxSET },
{ wxT("wxSRC_INVERT"), wxSRC_INVERT },
{ wxT("wxXOR"), wxXOR },
};
void MyCanvas::DrawImages(wxDC& dc, DrawMode mode)
{
dc.DrawText(wxT("original image"), 0, 0);
dc.DrawBitmap(*gs_bmpNoMask, 0, 20, 0);
dc.DrawText(wxT("with colour mask"), 0, 100);
dc.DrawBitmap(*gs_bmpWithColMask, 0, 120, true);
dc.DrawText(wxT("the mask image"), 0, 200);
dc.DrawBitmap(*gs_bmpMask, 0, 220, 0);
dc.DrawText(wxT("masked image"), 0, 300);
dc.DrawBitmap(*gs_bmpWithMask, 0, 320, true);
int cx = gs_bmpWithColMask->GetWidth(),
cy = gs_bmpWithColMask->GetHeight();
wxMemoryDC memDC;
for ( size_t n = 0; n < WXSIZEOF(rasterOperations); n++ )
{
wxCoord x = 120 + 150*(n%4),
y = 20 + 100*(n/4);
dc.DrawText(rasterOperations[n].name, x, y - 20);
memDC.SelectObject(*gs_bmpWithColMask);
if ( mode == Draw_Stretch )
{
dc.StretchBlit(x, y, cx, cy, &memDC, 0, 0, cx/2, cy/2,
rasterOperations[n].rop, true);
}
else
{
dc.Blit(x, y, cx, cy, &memDC, 0, 0, rasterOperations[n].rop, true);
}
}
}
void MyCanvas::DrawWithLogicalOps(wxDC& dc)
{
static const wxCoord w = 60;
static const wxCoord h = 60;
// reuse the text colour here
dc.SetPen(wxPen(m_owner->m_colourForeground));
dc.SetBrush(*wxTRANSPARENT_BRUSH);
size_t n;
for ( n = 0; n < WXSIZEOF(rasterOperations); n++ )
{
wxCoord x = 20 + 150*(n%4),
y = 20 + 100*(n/4);
dc.DrawText(rasterOperations[n].name, x, y - 20);
dc.SetLogicalFunction(rasterOperations[n].rop);
dc.DrawRectangle(x, y, w, h);
dc.DrawLine(x, y, x + w, y + h);
dc.DrawLine(x + w, y, x, y + h);
}
// now some filled rectangles
dc.SetBrush(wxBrush(m_owner->m_colourForeground));
for ( n = 0; n < WXSIZEOF(rasterOperations); n++ )
{
wxCoord x = 20 + 150*(n%4),
y = 500 + 100*(n/4);
dc.DrawText(rasterOperations[n].name, x, y - 20);
dc.SetLogicalFunction(rasterOperations[n].rop);
dc.DrawRectangle(x, y, w, h);
}
}
#if wxUSE_GRAPHICS_CONTEXT
#ifdef __WXGTK20__
void MyCanvas::DrawAlpha(wxDC& WXUNUSED(dummyDC))
#else
void MyCanvas::DrawAlpha(wxDC& dc)
#endif
{
#ifdef __WXGTK__
wxGCDC dc( this );
PrepareDC( dc );
#endif
wxDouble margin = 20 ;
wxDouble width = 180 ;
wxDouble radius = 30 ;
dc.SetPen( wxPen( wxColour( 128, 0, 0 ), 12 ));
dc.SetBrush(*wxRED_BRUSH);
wxRect r(margin,margin+width*0.66,width,width) ;
dc.DrawRoundedRectangle( r.x, r.y, r.width, r.width, radius ) ;
dc.SetPen( wxPen( wxColour( 0, 0, 128 ), 12));
dc.SetBrush(*wxBLUE_BRUSH);
r.Offset( width * 0.8 , - width * 0.66 ) ;
dc.DrawRoundedRectangle( r.x, r.y, r.width, r.width, radius ) ;
dc.SetPen( wxPen( wxColour( 128, 128, 0 ), 12));
dc.SetBrush( wxBrush( wxColour( 192, 192, 0)));
r.Offset( width * 0.8 , width *0.5 ) ;
dc.DrawRoundedRectangle( r.x, r.y, r.width, r.width, radius ) ;
dc.SetPen( *wxTRANSPARENT_PEN ) ;
dc.SetBrush( wxBrush( wxColour(255,255,128,128) ) );
dc.DrawRoundedRectangle( 0 , margin + width / 2 , width * 3 , 100 , radius) ;
dc.SetTextForeground( wxColour(255,255,0,128) );
dc.SetFont( wxFont( 40, wxFONTFAMILY_SWISS, wxFONTSTYLE_ITALIC, wxFONTWEIGHT_NORMAL ) );
dc.DrawText( wxT("Hello!"), 120, 80 );
}
#endif
#if wxUSE_GRAPHICS_CONTEXT
const int BASE = 80.0;
const int BASE2 = BASE/2;
const int BASE4 = BASE/4;
static inline double DegToRad(double deg) { return (deg * M_PI) / 180.0; }
// modeled along Robin Dunn's GraphicsContext.py sample
void MyCanvas::DrawGraphics(wxGraphicsContext* gc)
{
wxFont font = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);
gc->SetFont(font,*wxBLACK);
// make a path that contains a circle and some lines, centered at 0,0
wxGraphicsPath path = gc->CreatePath() ;
path.AddCircle( 0, 0, BASE2 );
path.MoveToPoint(0, -BASE2);
path.AddLineToPoint(0, BASE2);
path.MoveToPoint(-BASE2, 0);
path.AddLineToPoint(BASE2, 0);
path.CloseSubpath();
path.AddRectangle(-BASE4, -BASE4/2, BASE2, BASE4);
// Now use that path to demonstrate various capbilites of the grpahics context
gc->PushState(); // save current translation/scale/other state
gc->Translate(60, 75); // reposition the context origin
gc->SetPen(wxPen("navy"));
gc->SetBrush(wxBrush("pink"));
for( int i = 0 ; i < 3 ; ++i )
{
wxString label;
switch( i )
{
case 0 :
label = "StrokePath";
break;
case 1 :
label = "FillPath";
break;
case 2 :
label = "DrawPath";
break;
}
wxDouble w, h;
gc->GetTextExtent(label, &w, &h, NULL, NULL);
gc->DrawText(label, -w/2, -BASE2-h-4);
switch( i )
{
case 0 :
gc->StrokePath(path);
break;
case 1 :
gc->FillPath(path);
break;
case 2 :
gc->DrawPath(path);
break;
}
gc->Translate(2*BASE, 0);
}
gc->PopState(); // restore saved state
gc->PushState(); // save it again
gc->Translate(60, 200); // offset to the lower part of the window
gc->DrawText("Scale", 0, -BASE2);
gc->Translate(0, 20);
gc->SetBrush(wxBrush(wxColour(178, 34, 34, 128)));// 128 == half transparent
for( int i = 0 ; i < 8 ; ++i )
{
gc->Scale(1.08, 1.08); // increase scale by 8%
gc->Translate(5,5);
gc->DrawPath(path);
}
gc->PopState(); // restore saved state
gc->PushState(); // save it again
gc->Translate(400, 200);
gc->DrawText("Rotate", 0, -BASE2);
// Move the origin over to the next location
gc->Translate(0, 75);
// draw our path again, rotating it about the central point,
// and changing colors as we go
for ( int angle = 0 ; angle < 360 ; angle += 30 )
{
gc->PushState(); // save this new current state so we can
// pop back to it at the end of the loop
wxImage::RGBValue val = wxImage::HSVtoRGB(wxImage::HSVValue(float(angle)/360, 1, 1));
gc->SetBrush(wxBrush(wxColour(val.red, val.green, val.blue, 64)));
gc->SetPen(wxPen(wxColour(val.red, val.green, val.blue, 128)));
// use translate to artfully reposition each drawn path
gc->Translate(1.5 * BASE2 * cos(DegToRad(angle)),
1.5 * BASE2 * sin(DegToRad(angle)));
// use Rotate to rotate the path
gc->Rotate(DegToRad(angle));
// now draw it
gc->DrawPath(path);
gc->PopState();
}
gc->PopState();
gc->PushState();
gc->Translate(60, 400);
gc->DrawText("Scaled smiley inside a square", 0, 0);
gc->DrawRectangle(BASE2, BASE2, 100, 100);
gc->DrawBitmap(m_smile_bmp, BASE2, BASE2, 100, 100);
gc->PopState();
}
#endif // wxUSE_GRAPHICS_CONTEXT
void MyCanvas::DrawCircles(wxDC& dc)
{
int x = 100,
y = 100,
r = 20;
dc.SetPen( *wxRED_PEN );
dc.SetBrush( *wxGREEN_BRUSH );
dc.DrawText(wxT("Some circles"), 0, y);
dc.DrawCircle(x, y, r);
dc.DrawCircle(x + 2*r, y, r);
dc.DrawCircle(x + 4*r, y, r);
y += 2*r;
dc.DrawText(wxT("And ellipses"), 0, y);
dc.DrawEllipse(x - r, y, 2*r, r);
dc.DrawEllipse(x + r, y, 2*r, r);
dc.DrawEllipse(x + 3*r, y, 2*r, r);
y += 2*r;
dc.DrawText(wxT("And arcs"), 0, y);
dc.DrawArc(x - r, y, x + r, y, x, y);
dc.DrawArc(x + 4*r, y, x + 2*r, y, x + 3*r, y);
dc.DrawArc(x + 5*r, y, x + 5*r, y, x + 6*r, y);
y += 2*r;
dc.DrawEllipticArc(x - r, y, 2*r, r, 0, 90);
dc.DrawEllipticArc(x + r, y, 2*r, r, 90, 180);
dc.DrawEllipticArc(x + 3*r, y, 2*r, r, 180, 270);
dc.DrawEllipticArc(x + 5*r, y, 2*r, r, 270, 360);
// same as above, just transparent brush
dc.SetPen( *wxRED_PEN );
dc.SetBrush( *wxTRANSPARENT_BRUSH );
y += 2*r;
dc.DrawText(wxT("Some circles"), 0, y);
dc.DrawCircle(x, y, r);
dc.DrawCircle(x + 2*r, y, r);
dc.DrawCircle(x + 4*r, y, r);
y += 2*r;
dc.DrawText(wxT("And ellipses"), 0, y);
dc.DrawEllipse(x - r, y, 2*r, r);
dc.DrawEllipse(x + r, y, 2*r, r);
dc.DrawEllipse(x + 3*r, y, 2*r, r);
y += 2*r;
dc.DrawText(wxT("And arcs"), 0, y);
dc.DrawArc(x - r, y, x + r, y, x, y);
dc.DrawArc(x + 4*r, y, x + 2*r, y, x + 3*r, y);
dc.DrawArc(x + 5*r, y, x + 5*r, y, x + 6*r, y);
y += 2*r;
dc.DrawEllipticArc(x - r, y, 2*r, r, 0, 90);
dc.DrawEllipticArc(x + r, y, 2*r, r, 90, 180);
dc.DrawEllipticArc(x + 3*r, y, 2*r, r, 180, 270);
dc.DrawEllipticArc(x + 5*r, y, 2*r, r, 270, 360);
}
void MyCanvas::DrawSplines(wxDC& dc)
{
#if wxUSE_SPLINES
dc.DrawText(wxT("Some splines"), 10, 5);
// values are hardcoded rather than randomly generated
// so the output can be compared between native
// implementations on platforms with different random
// generators
const int R = 300;
const wxPoint center( R + 20, R + 20 );
const int angles[7] = { 0, 10, 33, 77, 13, 145, 90 };
const int radii[5] = { 100 , 59, 85, 33, 90 };
const int n = 200;
wxPoint pts[n];
// background spline calculation
unsigned int radius_pos = 0;
unsigned int angle_pos = 0;
int angle = 0;
for ( int i = 0; i < n; i++ )
{
angle += angles[ angle_pos ];
int r = R * radii[ radius_pos ] / 100;
pts[ i ].x = center.x + (wxCoord)( r * cos( M_PI * angle / 180.0) );
pts[ i ].y = center.y + (wxCoord)( r * sin( M_PI * angle / 180.0) );
angle_pos++;
if ( angle_pos >= WXSIZEOF(angles) ) angle_pos = 0;
radius_pos++;
if ( radius_pos >= WXSIZEOF(radii) ) radius_pos = 0;
}
// background spline drawing
dc.SetPen(*wxRED_PEN);
dc.DrawSpline(WXSIZEOF(pts), pts);
// less detailed spline calculation
wxPoint letters[4][5];
// w
letters[0][0] = wxPoint( 0,1); // O O
letters[0][1] = wxPoint( 1,3); // * *
letters[0][2] = wxPoint( 2,2); // * O *
letters[0][3] = wxPoint( 3,3); // * * * *
letters[0][4] = wxPoint( 4,1); // O O
// x1
letters[1][0] = wxPoint( 5,1); // O*O
letters[1][1] = wxPoint( 6,1); // *
letters[1][2] = wxPoint( 7,2); // O
letters[1][3] = wxPoint( 8,3); // *
letters[1][4] = wxPoint( 9,3); // O*O
// x2
letters[2][0] = wxPoint( 5,3); // O*O
letters[2][1] = wxPoint( 6,3); // *
letters[2][2] = wxPoint( 7,2); // O
letters[2][3] = wxPoint( 8,1); // *
letters[2][4] = wxPoint( 9,1); // O*O
// W
letters[3][0] = wxPoint(10,0); // O O
letters[3][1] = wxPoint(11,3); // * *
letters[3][2] = wxPoint(12,1); // * O *
letters[3][3] = wxPoint(13,3); // * * * *
letters[3][4] = wxPoint(14,0); // O O
const int dx = 2 * R / letters[3][4].x;
const int h[4] = { -R/2, 0, R/4, R/2 };
for ( int m = 0; m < 4; m++ )
{
for ( int n = 0; n < 5; n++ )
{
letters[m][n].x = center.x - R + letters[m][n].x * dx;
letters[m][n].y = center.y + h[ letters[m][n].y ];
}
dc.SetPen( wxPen( *wxBLUE, 1, wxDOT) );
dc.DrawLines(5, letters[m]);
dc.SetPen( wxPen( *wxBLACK, 4) );
dc.DrawSpline(5, letters[m]);
}
#else
dc.DrawText(wxT("Splines not supported."), 10, 5);
#endif
}
void MyCanvas::DrawGradients(wxDC& dc)
{
static const int TEXT_HEIGHT = 15;
// LHS: linear
wxRect r(10, 10, 50, 50);
dc.DrawText(wxT("wxRIGHT"), r.x, r.y);
r.Offset(0, TEXT_HEIGHT);
dc.GradientFillLinear(r, *wxWHITE, *wxBLUE, wxRIGHT);
r.Offset(0, r.height + 10);
dc.DrawText(wxT("wxLEFT"), r.x, r.y);
r.Offset(0, TEXT_HEIGHT);
dc.GradientFillLinear(r, *wxWHITE, *wxBLUE, wxLEFT);
r.Offset(0, r.height + 10);
dc.DrawText(wxT("wxDOWN"), r.x, r.y);
r.Offset(0, TEXT_HEIGHT);
dc.GradientFillLinear(r, *wxWHITE, *wxBLUE, wxDOWN);
r.Offset(0, r.height + 10);
dc.DrawText(wxT("wxUP"), r.x, r.y);
r.Offset(0, TEXT_HEIGHT);
dc.GradientFillLinear(r, *wxWHITE, *wxBLUE, wxUP);
wxRect gfr = wxRect(r);
// RHS: concentric
r = wxRect(200, 10, 50, 50);
dc.DrawText(wxT("Blue inside"), r.x, r.y);
r.Offset(0, TEXT_HEIGHT);
dc.GradientFillConcentric(r, *wxBLUE, *wxWHITE);
r.Offset(0, r.height + 10);
dc.DrawText(wxT("White inside"), r.x, r.y);
r.Offset(0, TEXT_HEIGHT);
dc.GradientFillConcentric(r, *wxWHITE, *wxBLUE);
r.Offset(0, r.height + 10);
dc.DrawText(wxT("Blue in top left corner"), r.x, r.y);
r.Offset(0, TEXT_HEIGHT);
dc.GradientFillConcentric(r, *wxBLUE, *wxWHITE, wxPoint(0, 0));
r.Offset(0, r.height + 10);
dc.DrawText(wxT("Blue in bottom right corner"), r.x, r.y);
r.Offset(0, TEXT_HEIGHT);
dc.GradientFillConcentric(r, *wxBLUE, *wxWHITE, wxPoint(r.width, r.height));
// check that the area filled by the gradient is exactly the interior of
// the rectangle
r.x = 350;
r.y = 30;
dc.DrawText("The interior should be filled but", r.x, r.y);
r.y += 15;
dc.DrawText(" the red border should remain visible:", r.x, r.y);
r.y += 15;
r.width =
r.height = 50;
wxRect r2 = r;
r2.x += 60;
wxRect r3 = r;
r3.y += 60;
wxRect r4 = r2;
r4.y += 60;
dc.SetPen(*wxRED_PEN);
dc.DrawRectangle(r);
r.Deflate(1);
dc.GradientFillLinear(r, *wxGREEN, *wxBLACK, wxNORTH);
dc.DrawRectangle(r2);
r2.Deflate(1);
dc.GradientFillLinear(r2, *wxBLACK, *wxGREEN, wxSOUTH);
dc.DrawRectangle(r3);
r3.Deflate(1);
dc.GradientFillLinear(r3, *wxGREEN, *wxBLACK, wxEAST);
dc.DrawRectangle(r4);
r4.Deflate(1);
dc.GradientFillLinear(r4, *wxBLACK, *wxGREEN, wxWEST);
#if wxUSE_GRAPHICS_CONTEXT
if (m_useContext)
{
wxGCDC &gdc = (wxGCDC&)dc;
wxGraphicsContext *gc = gdc.GetGraphicsContext();
wxGraphicsPath pth;
wxGraphicsGradientStops stops;
gfr.Offset(0, gfr.height + 10);
dc.DrawText(wxT("Linear Gradient with Stops"), gfr.x, gfr.y);
gfr.Offset(0, TEXT_HEIGHT);
stops = wxGraphicsGradientStops(*wxRED, *wxBLUE);
stops.Add(wxColour(255,255,0), 0.33f);
stops.Add(*wxGREEN, 0.67f);
gc->SetBrush(gc->CreateLinearGradientBrush(gfr.x, gfr.y,
gfr.x + gfr.width, gfr.y + gfr.height,
stops));
pth = gc->CreatePath();
pth.MoveToPoint(gfr.x,gfr.y);
pth.AddLineToPoint(gfr.x + gfr.width,gfr.y);
pth.AddLineToPoint(gfr.x + gfr.width,gfr.y+gfr.height);
pth.AddLineToPoint(gfr.x,gfr.y+gfr.height);
pth.CloseSubpath();
gc->FillPath(pth);
gfr.Offset(0, gfr.height + 10);
dc.DrawText(wxT("Radial Gradient with Stops"), gfr.x, gfr.y);
gfr.Offset(0, TEXT_HEIGHT);
gc->SetBrush(gc->CreateRadialGradientBrush(gfr.x + gfr.width / 2,
gfr.y + gfr.height / 2,
gfr.x + gfr.width / 2,
gfr.y + gfr.height / 2,
gfr.width / 2,
stops));
pth = gc->CreatePath();
pth.MoveToPoint(gfr.x,gfr.y);
pth.AddLineToPoint(gfr.x + gfr.width,gfr.y);
pth.AddLineToPoint(gfr.x + gfr.width,gfr.y+gfr.height);
pth.AddLineToPoint(gfr.x,gfr.y+gfr.height);
pth.CloseSubpath();
gc->FillPath(pth);
gfr.Offset(0, gfr.height + 10);
dc.DrawText(wxT("Linear Gradient with Stops and Gaps"), gfr.x, gfr.y);
gfr.Offset(0, TEXT_HEIGHT);
stops = wxGraphicsGradientStops(*wxRED, *wxBLUE);
stops.Add(wxColour(255,255,0), 0.33f);
stops.Add(wxTransparentColour, 0.33f);
stops.Add(wxTransparentColour, 0.67f);
stops.Add(*wxGREEN, 0.67f);
gc->SetBrush(gc->CreateLinearGradientBrush(gfr.x, gfr.y + gfr.height,
gfr.x + gfr.width, gfr.y,
stops));
pth = gc->CreatePath();
pth.MoveToPoint(gfr.x,gfr.y);
pth.AddLineToPoint(gfr.x + gfr.width,gfr.y);
pth.AddLineToPoint(gfr.x + gfr.width,gfr.y+gfr.height);
pth.AddLineToPoint(gfr.x,gfr.y+gfr.height);
pth.CloseSubpath();
gc->FillPath(pth);
gfr.Offset(0, gfr.height + 10);
dc.DrawText(wxT("Radial Gradient with Stops and Gaps"), gfr.x, gfr.y);
gfr.Offset(0, TEXT_HEIGHT);
gc->SetBrush(gc->CreateRadialGradientBrush(gfr.x + gfr.width / 2,
gfr.y + gfr.height / 2,
gfr.x + gfr.width / 2,
gfr.y + gfr.height / 2,
gfr.width / 2,
stops));
pth = gc->CreatePath();
pth.MoveToPoint(gfr.x,gfr.y);
pth.AddLineToPoint(gfr.x + gfr.width,gfr.y);
pth.AddLineToPoint(gfr.x + gfr.width,gfr.y+gfr.height);
pth.AddLineToPoint(gfr.x,gfr.y+gfr.height);
pth.CloseSubpath();
gc->FillPath(pth);
gfr.Offset(0, gfr.height + 10);
dc.DrawText(wxT("Gradients with Stops and Transparency"), gfr.x, gfr.y);
gfr.Offset(0, TEXT_HEIGHT);
stops = wxGraphicsGradientStops(*wxRED, wxTransparentColour);
stops.Add(*wxRED, 0.33f);
stops.Add(wxTransparentColour, 0.33f);
stops.Add(wxTransparentColour, 0.67f);
stops.Add(*wxBLUE, 0.67f);
stops.Add(*wxBLUE, 1.0f);
pth = gc->CreatePath();
pth.MoveToPoint(gfr.x,gfr.y);
pth.AddLineToPoint(gfr.x + gfr.width,gfr.y);
pth.AddLineToPoint(gfr.x + gfr.width,gfr.y+gfr.height);
pth.AddLineToPoint(gfr.x,gfr.y+gfr.height);
pth.CloseSubpath();
gc->SetBrush(gc->CreateRadialGradientBrush(gfr.x + gfr.width / 2,
gfr.y + gfr.height / 2,
gfr.x + gfr.width / 2,
gfr.y + gfr.height / 2,
gfr.width / 2,
stops));
gc->FillPath(pth);
stops = wxGraphicsGradientStops(wxColour(255,0,0, 128), wxColour(0,0,255, 128));
stops.Add(wxColour(255,255,0,128), 0.33f);
stops.Add(wxColour(0,255,0,128), 0.67f);
gc->SetBrush(gc->CreateLinearGradientBrush(gfr.x, gfr.y,
gfr.x + gfr.width, gfr.y,
stops));
gc->FillPath(pth);
}
#endif // wxUSE_GRAPHICS_CONTEXT
}
void MyCanvas::DrawRegions(wxDC& dc)
{
dc.DrawText(wxT("You should see a red rect partly covered by a cyan one ")
wxT("on the left"), 10, 5);
dc.DrawText(wxT("and 5 smileys from which 4 are partially clipped on the right"),
10, 5 + dc.GetCharHeight());
dc.DrawText(wxT("The second copy should be identical but right part of it ")
wxT("should be offset by 10 pixels."),
10, 5 + 2*dc.GetCharHeight());
DrawRegionsHelper(dc, 10, true);
DrawRegionsHelper(dc, 350, false);
}
void MyCanvas::DrawRegionsHelper(wxDC& dc, wxCoord x, bool firstTime)
{
wxCoord y = 100;
dc.DestroyClippingRegion();
dc.SetBrush( *wxWHITE_BRUSH );
dc.SetPen( *wxTRANSPARENT_PEN );
dc.DrawRectangle( x, y, 310, 310 );
dc.SetClippingRegion( x + 10, y + 10, 100, 270 );
dc.SetBrush( *wxRED_BRUSH );
dc.DrawRectangle( x, y, 310, 310 );
dc.SetClippingRegion( x + 10, y + 10, 100, 100 );
dc.SetBrush( *wxCYAN_BRUSH );
dc.DrawRectangle( x, y, 310, 310 );
dc.DestroyClippingRegion();
wxRegion region(x + 110, y + 20, 100, 270);
#if !defined(__WXMOTIF__)
if ( !firstTime )
region.Offset(10, 10);
#endif
dc.SetDeviceClippingRegion(region);
dc.SetBrush( *wxGREY_BRUSH );
dc.DrawRectangle( x, y, 310, 310 );
if (m_smile_bmp.IsOk())
{
dc.DrawBitmap( m_smile_bmp, x + 150, y + 150, true );
dc.DrawBitmap( m_smile_bmp, x + 130, y + 10, true );
dc.DrawBitmap( m_smile_bmp, x + 130, y + 280, true );
dc.DrawBitmap( m_smile_bmp, x + 100, y + 70, true );
dc.DrawBitmap( m_smile_bmp, x + 200, y + 70, true );
}
}
void MyCanvas::OnPaint(wxPaintEvent &WXUNUSED(event))
{
if ( m_useBuffer )
{
wxBufferedPaintDC bpdc(this);
Draw(bpdc);
}
else
{
wxPaintDC pdc(this);
Draw(pdc);
}
}
void MyCanvas::Draw(wxDC& pdc)
{
#if wxUSE_GRAPHICS_CONTEXT
wxGCDC gdc;
wxGraphicsRenderer* const renderer = wxGraphicsRenderer::
#if TEST_CAIRO_EVERYWHERE
GetCairoRenderer()
#else
GetDefaultRenderer()
#endif
;
wxGraphicsContext* context;
if ( wxPaintDC *paintdc = wxDynamicCast(&pdc, wxPaintDC) )
{
context = renderer->CreateContext(*paintdc);
}
else if ( wxMemoryDC *memdc = wxDynamicCast(&pdc, wxMemoryDC) )
{
context = renderer->CreateContext(*memdc);
}
#if wxUSE_METAFILE && defined(wxMETAFILE_IS_ENH)
else if ( wxMetafileDC *metadc = wxDynamicCast(&pdc, wxMetafileDC) )
{
context = renderer->CreateContext(*metadc);
}
#endif
else
{
wxFAIL_MSG( "Unknown wxDC kind" );
return;
}
gdc.SetGraphicsContext(context);
wxDC &dc = m_useContext ? (wxDC&) gdc : (wxDC&) pdc ;
#else
wxDC &dc = pdc ;
#endif
PrepareDC(dc);
m_owner->PrepareDC(dc);
dc.SetBackgroundMode( m_owner->m_backgroundMode );
if ( m_owner->m_backgroundBrush.IsOk() )
dc.SetBackground( m_owner->m_backgroundBrush );
if ( m_owner->m_colourForeground.IsOk() )
dc.SetTextForeground( m_owner->m_colourForeground );
if ( m_owner->m_colourBackground.IsOk() )
dc.SetTextBackground( m_owner->m_colourBackground );
if ( m_owner->m_textureBackground) {
if ( ! m_owner->m_backgroundBrush.IsOk() ) {
dc.SetBackground(wxBrush(wxColour(0, 128, 0)));
}
}
if ( m_clip )
dc.SetClippingRegion(100, 100, 100, 100);
dc.Clear();
if ( m_owner->m_textureBackground )
{
dc.SetPen(*wxMEDIUM_GREY_PEN);
for ( int i = 0; i < 200; i++ )
dc.DrawLine(0, i*10, i*10, 0);
}
switch ( m_show )
{
case File_ShowDefault:
DrawDefault(dc);
break;
case File_ShowCircles:
DrawCircles(dc);
break;
case File_ShowSplines:
DrawSplines(dc);
break;
case File_ShowRegions:
DrawRegions(dc);
break;
case File_ShowText:
DrawText(dc);
break;
case File_ShowLines:
DrawTestLines( 0, 100, 0, dc );
DrawTestLines( 0, 320, 1, dc );
DrawTestLines( 0, 540, 2, dc );
DrawTestLines( 0, 760, 6, dc );
break;
case File_ShowBrushes:
DrawTestBrushes(dc);
break;
case File_ShowPolygons:
DrawTestPoly(dc);
break;
case File_ShowMask:
DrawImages(dc, Draw_Normal);
break;
case File_ShowMaskStretch:
DrawImages(dc, Draw_Stretch);
break;
case File_ShowOps:
DrawWithLogicalOps(dc);
break;
#if wxUSE_GRAPHICS_CONTEXT
case File_ShowAlpha:
DrawAlpha(dc);
break;
case File_ShowGraphics:
DrawGraphics(gdc.GetGraphicsContext());
break;
#endif
case File_ShowGradients:
DrawGradients(dc);
break;
default:
break;
}
}
void MyCanvas::OnMouseMove(wxMouseEvent &event)
{
#if wxUSE_STATUSBAR
{
wxClientDC dc(this);
PrepareDC(dc);
m_owner->PrepareDC(dc);
wxPoint pos = event.GetPosition();
long x = dc.DeviceToLogicalX( pos.x );
long y = dc.DeviceToLogicalY( pos.y );
wxString str;
str.Printf( wxT("Current mouse position: %d,%d"), (int)x, (int)y );
m_owner->SetStatusText( str );
}
if ( m_rubberBand )
{
int x,y, xx, yy ;
event.GetPosition(&x,&y);
CalcUnscrolledPosition( x, y, &xx, &yy );
m_currentpoint = wxPoint( xx , yy ) ;
wxRect newrect ( m_anchorpoint , m_currentpoint ) ;
wxClientDC dc( this ) ;
PrepareDC( dc ) ;
wxDCOverlay overlaydc( m_overlay, &dc );
overlaydc.Clear();
#ifdef __WXMAC__
dc.SetPen( *wxGREY_PEN );
dc.SetBrush( wxColour( 192,192,192,64 ) );
#else
dc.SetPen( wxPen( *wxLIGHT_GREY, 2 ) );
dc.SetBrush( *wxTRANSPARENT_BRUSH );
#endif
dc.DrawRectangle( newrect );
}
#else
wxUnusedVar(event);
#endif // wxUSE_STATUSBAR
}
void MyCanvas::OnMouseDown(wxMouseEvent &event)
{
int x,y,xx,yy ;
event.GetPosition(&x,&y);
CalcUnscrolledPosition( x, y, &xx, &yy );
m_anchorpoint = wxPoint( xx , yy ) ;
m_currentpoint = m_anchorpoint ;
m_rubberBand = true ;
CaptureMouse() ;
}
void MyCanvas::OnMouseUp(wxMouseEvent &event)
{
if ( m_rubberBand )
{
ReleaseMouse();
{
wxClientDC dc( this );
PrepareDC( dc );
wxDCOverlay overlaydc( m_overlay, &dc );
overlaydc.Clear();
}
m_overlay.Reset();
m_rubberBand = false;
wxPoint endpoint = CalcUnscrolledPosition(event.GetPosition());
// Don't pop up the message box if nothing was actually selected.
if ( endpoint != m_anchorpoint )
{
wxLogMessage("Selected rectangle from (%d, %d) to (%d, %d)",
m_anchorpoint.x, m_anchorpoint.y,
endpoint.x, endpoint.y);
}
}
}
// ----------------------------------------------------------------------------
// MyFrame
// ----------------------------------------------------------------------------
// the event tables connect the wxWidgets events with the functions (event
// handlers) which process them. It can be also done at run-time, but for the
// simple menu events like this the static method is much simpler.
BEGIN_EVENT_TABLE(MyFrame, wxFrame)
EVT_MENU (File_Quit, MyFrame::OnQuit)
EVT_MENU (File_About, MyFrame::OnAbout)
EVT_MENU (File_Clip, MyFrame::OnClip)
#if wxUSE_GRAPHICS_CONTEXT
EVT_MENU (File_GraphicContext, MyFrame::OnGraphicContext)
#endif
EVT_MENU (File_Buffer, MyFrame::OnBuffer)
EVT_MENU (File_Copy, MyFrame::OnCopy)
EVT_MENU (File_Save, MyFrame::OnSave)
EVT_MENU_RANGE(MenuShow_First, MenuShow_Last, MyFrame::OnShow)
EVT_MENU_RANGE(MenuOption_First, MenuOption_Last, MyFrame::OnOption)
END_EVENT_TABLE()
// frame constructor
MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size)
: wxFrame((wxFrame *)NULL, wxID_ANY, title, pos, size,
wxDEFAULT_FRAME_STYLE | wxNO_FULL_REPAINT_ON_RESIZE)
{
// set the frame icon
SetIcon(wxICON(sample));
wxMenu *menuFile = new wxMenu;
menuFile->Append(File_ShowDefault, wxT("&Default screen\tF1"));
menuFile->Append(File_ShowText, wxT("&Text screen\tF2"));
menuFile->Append(File_ShowLines, wxT("&Lines screen\tF3"));
menuFile->Append(File_ShowBrushes, wxT("&Brushes screen\tF4"));
menuFile->Append(File_ShowPolygons, wxT("&Polygons screen\tF5"));
menuFile->Append(File_ShowMask, wxT("&Mask screen\tF6"));
menuFile->Append(File_ShowMaskStretch, wxT("1/&2 scaled mask\tShift-F6"));
menuFile->Append(File_ShowOps, wxT("&Raster operations screen\tF7"));
menuFile->Append(File_ShowRegions, wxT("Re&gions screen\tF8"));
menuFile->Append(File_ShowCircles, wxT("&Circles screen\tF9"));
#if wxUSE_GRAPHICS_CONTEXT
menuFile->Append(File_ShowAlpha, wxT("&Alpha screen\tF10"));
#endif
menuFile->Append(File_ShowSplines, wxT("Spl&ines screen\tF11"));
menuFile->Append(File_ShowGradients, wxT("&Gradients screen\tF12"));
#if wxUSE_GRAPHICS_CONTEXT
menuFile->Append(File_ShowGraphics, wxT("&Graphics screen"));
#endif
menuFile->AppendSeparator();
menuFile->AppendCheckItem(File_Clip, wxT("&Clip\tCtrl-C"), wxT("Clip/unclip drawing"));
#if wxUSE_GRAPHICS_CONTEXT
menuFile->AppendCheckItem(File_GraphicContext, wxT("&Use GraphicContext\tCtrl-Y"), wxT("Use GraphicContext"));
#endif
menuFile->AppendCheckItem(File_Buffer, wxT("&Use wx&BufferedPaintDC\tCtrl-Z"), wxT("Buffer painting"));
menuFile->AppendSeparator();
#if wxUSE_METAFILE && defined(wxMETAFILE_IS_ENH)
menuFile->Append(File_Copy, wxT("Copy to clipboard"));
#endif
menuFile->Append(File_Save, wxT("&Save...\tCtrl-S"), wxT("Save drawing to file"));
menuFile->AppendSeparator();
menuFile->Append(File_About, wxT("&About\tCtrl-A"), wxT("Show about dialog"));
menuFile->AppendSeparator();
menuFile->Append(File_Quit, wxT("E&xit\tAlt-X"), wxT("Quit this program"));
wxMenu *menuMapMode = new wxMenu;
menuMapMode->Append( MapMode_Text, wxT("&TEXT map mode") );
menuMapMode->Append( MapMode_Lometric, wxT("&LOMETRIC map mode") );
menuMapMode->Append( MapMode_Twips, wxT("T&WIPS map mode") );
menuMapMode->Append( MapMode_Points, wxT("&POINTS map mode") );
menuMapMode->Append( MapMode_Metric, wxT("&METRIC map mode") );
wxMenu *menuUserScale = new wxMenu;
menuUserScale->Append( UserScale_StretchHoriz, wxT("Stretch &horizontally\tCtrl-H") );
menuUserScale->Append( UserScale_ShrinkHoriz, wxT("Shrin&k horizontally\tCtrl-G") );
menuUserScale->Append( UserScale_StretchVertic, wxT("Stretch &vertically\tCtrl-V") );
menuUserScale->Append( UserScale_ShrinkVertic, wxT("&Shrink vertically\tCtrl-W") );
menuUserScale->AppendSeparator();
menuUserScale->Append( UserScale_Restore, wxT("&Restore to normal\tCtrl-0") );
wxMenu *menuAxis = new wxMenu;
menuAxis->AppendCheckItem( AxisMirror_Horiz, wxT("Mirror horizontally\tCtrl-M") );
menuAxis->AppendCheckItem( AxisMirror_Vertic, wxT("Mirror vertically\tCtrl-N") );
wxMenu *menuLogical = new wxMenu;
menuLogical->Append( LogicalOrigin_MoveDown, wxT("Move &down\tCtrl-D") );
menuLogical->Append( LogicalOrigin_MoveUp, wxT("Move &up\tCtrl-U") );
menuLogical->Append( LogicalOrigin_MoveLeft, wxT("Move &right\tCtrl-L") );
menuLogical->Append( LogicalOrigin_MoveRight, wxT("Move &left\tCtrl-R") );
menuLogical->AppendSeparator();
menuLogical->Append( LogicalOrigin_Set, wxT("Set to (&100, 100)\tShift-Ctrl-1") );
menuLogical->Append( LogicalOrigin_Restore, wxT("&Restore to normal\tShift-Ctrl-0") );
wxMenu *menuColour = new wxMenu;
#if wxUSE_COLOURDLG
menuColour->Append( Colour_TextForeground, wxT("Text &foreground...") );
menuColour->Append( Colour_TextBackground, wxT("Text &background...") );
menuColour->Append( Colour_Background, wxT("Background &colour...") );
#endif // wxUSE_COLOURDLG
menuColour->AppendCheckItem( Colour_BackgroundMode, wxT("&Opaque/transparent\tCtrl-B") );
menuColour->AppendCheckItem( Colour_TextureBackgound, wxT("Draw textured back&ground\tCtrl-T") );
// now append the freshly created menu to the menu bar...
wxMenuBar *menuBar = new wxMenuBar;
menuBar->Append(menuFile, wxT("&File"));
menuBar->Append(menuMapMode, wxT("&Mode"));
menuBar->Append(menuUserScale, wxT("&Scale"));
menuBar->Append(menuAxis, wxT("&Axis"));
menuBar->Append(menuLogical, wxT("&Origin"));
menuBar->Append(menuColour, wxT("&Colours"));
// ... and attach this menu bar to the frame
SetMenuBar(menuBar);
#if wxUSE_STATUSBAR
CreateStatusBar(2);
SetStatusText(wxT("Welcome to wxWidgets!"));
#endif // wxUSE_STATUSBAR
m_mapMode = wxMM_TEXT;
m_xUserScale = 1.0;
m_yUserScale = 1.0;
m_xLogicalOrigin = 0;
m_yLogicalOrigin = 0;
m_xAxisReversed =
m_yAxisReversed = false;
m_backgroundMode = wxSOLID;
m_colourForeground = *wxBLACK;
m_colourBackground = *wxLIGHT_GREY;
m_textureBackground = false;
m_canvas = new MyCanvas( this );
m_canvas->SetScrollbars( 10, 10, 100, 240 );
}
// event handlers
void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
{
// true is to force the frame to close
Close(true);
}
void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
{
wxString msg;
msg.Printf( wxT("This is the about dialog of the drawing sample.\n")
wxT("This sample tests various primitive drawing functions\n")
wxT("(without any attempts to prevent flicker).\n")
wxT("Copyright (c) Robert Roebling 1999")
);
wxMessageBox(msg, wxT("About Drawing"), wxOK | wxICON_INFORMATION, this);
}
void MyFrame::OnClip(wxCommandEvent& event)
{
m_canvas->Clip(event.IsChecked());
}
#if wxUSE_GRAPHICS_CONTEXT
void MyFrame::OnGraphicContext(wxCommandEvent& event)
{
m_canvas->UseGraphicContext(event.IsChecked());
}
#endif
void MyFrame::OnBuffer(wxCommandEvent& event)
{
m_canvas->UseBuffer(event.IsChecked());
}
void MyFrame::OnCopy(wxCommandEvent& WXUNUSED(event))
{
#if wxUSE_METAFILE && defined(wxMETAFILE_IS_ENH)
wxMetafileDC dc;
if (!dc.IsOk())
return;
m_canvas->Draw(dc);
wxMetafile *mf = dc.Close();
if (!mf)
return;
mf->SetClipboard();
delete mf;
#endif
}
void MyFrame::OnSave(wxCommandEvent& WXUNUSED(event))
{
wxFileDialog dlg(this, wxT("Save as bitmap"), wxT(""), wxT(""),
#if wxUSE_LIBPNG
wxT("PNG image (*.png)|*.png;*.PNG|")
#endif
wxT("Bitmap image (*.bmp)|*.bmp;*.BMP"),
wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
if (dlg.ShowModal() == wxID_OK)
{
wxBitmap bmp(500, 800);
wxMemoryDC mdc(bmp);
m_canvas->Draw(mdc);
bmp.ConvertToImage().SaveFile(dlg.GetPath());
}
}
void MyFrame::OnShow(wxCommandEvent& event)
{
m_canvas->ToShow(event.GetId());
}
void MyFrame::OnOption(wxCommandEvent& event)
{
switch (event.GetId())
{
case MapMode_Text:
m_mapMode = wxMM_TEXT;
break;
case MapMode_Lometric:
m_mapMode = wxMM_LOMETRIC;
break;
case MapMode_Twips:
m_mapMode = wxMM_TWIPS;
break;
case MapMode_Points:
m_mapMode = wxMM_POINTS;
break;
case MapMode_Metric:
m_mapMode = wxMM_METRIC;
break;
case LogicalOrigin_MoveDown:
m_yLogicalOrigin += 10;
break;
case LogicalOrigin_MoveUp:
m_yLogicalOrigin -= 10;
break;
case LogicalOrigin_MoveLeft:
m_xLogicalOrigin += 10;
break;
case LogicalOrigin_MoveRight:
m_xLogicalOrigin -= 10;
break;
case LogicalOrigin_Set:
m_xLogicalOrigin =
m_yLogicalOrigin = -100;
break;
case LogicalOrigin_Restore:
m_xLogicalOrigin =
m_yLogicalOrigin = 0;
break;
case UserScale_StretchHoriz:
m_xUserScale *= 1.10;
break;
case UserScale_ShrinkHoriz:
m_xUserScale /= 1.10;
break;
case UserScale_StretchVertic:
m_yUserScale *= 1.10;
break;
case UserScale_ShrinkVertic:
m_yUserScale /= 1.10;
break;
case UserScale_Restore:
m_xUserScale =
m_yUserScale = 1.0;
break;
case AxisMirror_Vertic:
m_yAxisReversed = !m_yAxisReversed;
break;
case AxisMirror_Horiz:
m_xAxisReversed = !m_xAxisReversed;
break;
#if wxUSE_COLOURDLG
case Colour_TextForeground:
m_colourForeground = SelectColour();
break;
case Colour_TextBackground:
m_colourBackground = SelectColour();
break;
case Colour_Background:
{
wxColour col = SelectColour();
if ( col.IsOk() )
{
m_backgroundBrush.SetColour(col);
}
}
break;
#endif // wxUSE_COLOURDLG
case Colour_BackgroundMode:
m_backgroundMode = m_backgroundMode == wxSOLID ? wxTRANSPARENT
: wxSOLID;
break;
case Colour_TextureBackgound:
m_textureBackground = ! m_textureBackground;
break;
default:
// skip Refresh()
return;
}
m_canvas->Refresh();
}
void MyFrame::PrepareDC(wxDC& dc)
{
dc.SetLogicalOrigin( m_xLogicalOrigin, m_yLogicalOrigin );
dc.SetAxisOrientation( !m_xAxisReversed, m_yAxisReversed );
dc.SetUserScale( m_xUserScale, m_yUserScale );
dc.SetMapMode( m_mapMode );
}
#if wxUSE_COLOURDLG
wxColour MyFrame::SelectColour()
{
wxColour col;
wxColourData data;
wxColourDialog dialog(this, &data);
if ( dialog.ShowModal() == wxID_OK )
{
col = dialog.GetColourData().GetColour();
}
return col;
}
#endif // wxUSE_COLOURDLG