X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/925e9792d32e353233985f53a4845f154e455a58..3c01c5951189e13b8b4a5d7b288b54d4a57a30f8:/samples/drawing/drawing.cpp?ds=sidebyside diff --git a/samples/drawing/drawing.cpp b/samples/drawing/drawing.cpp index fa8d1938f7..9b288944fb 100644 --- a/samples/drawing/drawing.cpp +++ b/samples/drawing/drawing.cpp @@ -1,5 +1,5 @@ ///////////////////////////////////////////////////////////////////////////// -// Name: drawing.cpp +// Name: samples/drawing/drawing.cpp // Purpose: shows and tests wxDC features // Author: Robert Roebling // Modified by: @@ -17,11 +17,6 @@ // headers // ---------------------------------------------------------------------------- -#if defined(__GNUG__) && !defined(__APPLE__) - #pragma implementation "drawing.cpp" - #pragma interface "drawing.cpp" -#endif - // For compilers that support precompilation, includes "wx/wx.h". #include "wx/wxprec.h" @@ -38,9 +33,15 @@ #include "wx/colordlg.h" #include "wx/image.h" #include "wx/artprov.h" +#include "wx/dcgraph.h" +#include "wx/overlay.h" +#include "wx/graphics.h" +#include "wx/filename.h" + +#define TEST_CAIRO_EVERYWHERE 0 // ---------------------------------------------------------------------------- -// ressources +// resources // ---------------------------------------------------------------------------- // the application icon @@ -48,25 +49,6 @@ #include "mondrian.xpm" #endif -// ---------------------------------------------------------------------------- -// constants -// ---------------------------------------------------------------------------- - -// what do we show on screen (there are too many shapes to put them all on -// screen simultaneously) -enum ScreenToShow -{ - Show_Default, - Show_Text, - Show_Lines, - Show_Brushes, - Show_Polygons, - Show_Mask, - Show_Ops, - Show_Regions, - Show_Circles -}; - // ---------------------------------------------------------------------------- // global variables // ---------------------------------------------------------------------------- @@ -116,6 +98,9 @@ public: void OnQuit(wxCommandEvent& event); void OnAbout(wxCommandEvent& event); void OnClip(wxCommandEvent& event); +#if wxUSE_GRAPHICS_CONTEXT + void OnGraphicContext(wxCommandEvent& event); +#endif void OnShow(wxCommandEvent &event); void OnOption(wxCommandEvent &event); @@ -126,7 +111,7 @@ public: int m_backgroundMode; int m_textureBackground; - int m_mapMode; + wxMappingMode m_mapMode; double m_xUserScale; double m_yUserScale; int m_xLogicalOrigin; @@ -151,32 +136,56 @@ public: void OnPaint(wxPaintEvent &event); void OnMouseMove(wxMouseEvent &event); + void OnMouseDown(wxMouseEvent &event); + void OnMouseUp(wxMouseEvent &event); - void ToShow(ScreenToShow show) { m_show = show; Refresh(); } + 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 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); + 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; - ScreenToShow m_show; + 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 DECLARE_EVENT_TABLE() }; @@ -189,22 +198,32 @@ private: enum { // menu items - File_Quit = 1, - File_About, + File_Quit = wxID_EXIT, + File_About = wxID_ABOUT, - MenuShow_First, + 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, - MenuShow_Last = 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 MenuOption_First, @@ -272,8 +291,12 @@ bool MyApp::LoadImages() 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(_T(".")); pathList.Add(_T("..")); + pathList.Add(_T("../..")); wxString path = pathList.FindValidPath(_T("pat4.bmp")); if ( !path ) @@ -317,6 +340,9 @@ bool MyApp::LoadImages() // `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(_T("Drawing sample"), wxPoint(50, 50), wxSize(550, 340)); @@ -331,13 +357,10 @@ bool MyApp::OnInit() wxT("for this sample from the current or parent ") wxT("directory, please copy them there.")); - // stop here - DeleteBitmaps(); - - return false; + // still continue, the sample can be used without images too if they're + // missing for whatever reason } - // ok, continue return true; } @@ -369,6 +392,8 @@ void MyApp::DeleteBitmaps() 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" @@ -378,10 +403,14 @@ MyCanvas::MyCanvas(MyFrame *parent) wxHSCROLL | wxVSCROLL | wxNO_FULL_REPAINT_ON_RESIZE) { m_owner = parent; - m_show = Show_Default; + 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 } void MyCanvas::DrawTestBrushes(wxDC& dc) @@ -513,11 +542,16 @@ void MyCanvas::DrawDefault(wxDC& dc) // mark the origin dc.DrawCircle(0, 0, 10); +#if !defined(wxMAC_USE_CORE_GRAPHICS) || !wxMAC_USE_CORE_GRAPHICS + // GetPixel and FloodFill not supported by Mac OS X CoreGraphics + // (FloodFill uses Blit from a non-wxMemoryDC) //flood fill using brush, starting at 1,1 and replacing whatever colour we find there dc.SetBrush(wxBrush(wxColour(128,128,0), wxSOLID)); + wxColour tmpColour ; dc.GetPixel(1,1, &tmpColour); dc.FloodFill(1,1, tmpColour, wxFLOOD_SURFACE); +#endif dc.DrawCheckMark(5, 80, 15, 15); dc.DrawCheckMark(25, 80, 30, 30); @@ -664,7 +698,7 @@ void MyCanvas::DrawDefault(wxDC& dc) // Added by JACS to demonstrate bizarre behaviour. // With a size of 70, we get a missing red RHS, - // and the hight is too small, so we get yellow + // 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; @@ -734,9 +768,9 @@ void MyCanvas::DrawText(wxDC& dc) dc.DrawText( _T("This is Swiss 18pt text."), 110, 40 ); - long length; - long height; - long descent; + wxCoord length; + wxCoord height; + wxCoord descent; dc.GetTextExtent( _T("This is Swiss 18pt text."), &length, &height, &descent ); text.Printf( wxT("Dimensions are length %ld, height %ld, descent %ld"), length, height, descent ); dc.DrawText( text, 110, 80 ); @@ -749,26 +783,26 @@ void MyCanvas::DrawText(wxDC& dc) // test the logical function effect wxCoord y = 150; dc.SetLogicalFunction(wxINVERT); - dc.DrawText( _T("There should be no text below"), 110, 150 ); + // text drawing should ignore logical function + dc.DrawText( _T("There should be a text below"), 110, 150 ); dc.DrawRectangle( 110, y, 100, height ); - // twice drawn inverted should result in invisible y += height; - dc.DrawText( _T("Invisible text"), 110, y ); + dc.DrawText( _T("Visible text"), 110, y ); dc.DrawRectangle( 110, y, 100, height ); - dc.DrawText( _T("Invisible text"), 110, y ); + dc.DrawText( _T("Visible text"), 110, y ); dc.DrawRectangle( 110, y, 100, height ); dc.SetLogicalFunction(wxCOPY); y += height; dc.DrawRectangle( 110, y, 100, height ); - dc.DrawText( _T("Visible text"), 110, y ); + dc.DrawText( _T("Another visible text"), 110, y ); } static const struct { const wxChar *name; - int rop; + wxRasterOperationMode rop; } rasterOperations[] = { { wxT("wxAND"), wxAND }, @@ -788,7 +822,7 @@ static const struct { wxT("wxXOR"), wxXOR }, }; -void MyCanvas::DrawImages(wxDC& dc) +void MyCanvas::DrawImages(wxDC& dc, DrawMode mode) { dc.DrawText(_T("original image"), 0, 0); dc.DrawBitmap(*gs_bmpNoMask, 0, 20, 0); @@ -810,7 +844,15 @@ void MyCanvas::DrawImages(wxDC& dc) dc.DrawText(rasterOperations[n].name, x, y - 20); memDC.SelectObject(*gs_bmpWithColMask); - dc.Blit(x, y, cx, cy, &memDC, 0, 0, rasterOperations[n].rop, true); + 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); + } } } @@ -850,12 +892,207 @@ void MyCanvas::DrawWithLogicalOps(wxDC& dc) } } +#if wxUSE_GRAPHICS_CONTEXT +#ifdef __WXGTK20__ +void MyCanvas::DrawAlpha(wxDC& no_dc) +#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, 255 ),12, wxSOLID)); + dc.SetBrush( wxBrush( wxColour( 255, 0, 0, 255),wxSOLID)); + + 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, 255 ),12, wxSOLID)); + dc.SetBrush( wxBrush( wxColour( 0, 0, 255, 255),wxSOLID)); + + 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, 255 ),12, wxSOLID)); + dc.SetBrush( wxBrush( wxColour( 192, 192, 0, 255),wxSOLID)); + + 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", 1)); + 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(); +} +#endif + void MyCanvas::DrawCircles(wxDC& dc) { int x = 100, y = 100, r = 20; + dc.SetPen( *wxRED_PEN ); + dc.SetBrush( *wxGREEN_BRUSH ); + + dc.DrawText(_T("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(_T("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(_T("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(_T("Some circles"), 0, y); dc.DrawCircle(x, y, r); dc.DrawCircle(x + 2*r, y, r); @@ -878,6 +1115,174 @@ void MyCanvas::DrawCircles(wxDC& dc) 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(_T("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( wxT("blue"), 1, wxDOT) ); + dc.DrawLines(5, letters[m]); + dc.SetPen( wxPen( wxT("black"), 4, wxSOLID) ); + dc.DrawSpline(5, letters[m]); + } + +#else + dc.DrawText(_T("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(_T("wxRIGHT"), r.x, r.y); + r.Offset(0, TEXT_HEIGHT); + dc.GradientFillLinear(r, *wxWHITE, *wxBLUE, wxRIGHT); + + r.Offset(0, r.height + 10); + dc.DrawText(_T("wxLEFT"), r.x, r.y); + r.Offset(0, TEXT_HEIGHT); + dc.GradientFillLinear(r, *wxWHITE, *wxBLUE, wxLEFT); + + r.Offset(0, r.height + 10); + dc.DrawText(_T("wxDOWN"), r.x, r.y); + r.Offset(0, TEXT_HEIGHT); + dc.GradientFillLinear(r, *wxWHITE, *wxBLUE, wxDOWN); + + r.Offset(0, r.height + 10); + dc.DrawText(_T("wxUP"), r.x, r.y); + r.Offset(0, TEXT_HEIGHT); + dc.GradientFillLinear(r, *wxWHITE, *wxBLUE, wxUP); + + + // RHS: concentric + r = wxRect(200, 10, 50, 50); + dc.DrawText(_T("Blue inside"), r.x, r.y); + r.Offset(0, TEXT_HEIGHT); + dc.GradientFillConcentric(r, *wxBLUE, *wxWHITE); + + r.Offset(0, r.height + 10); + dc.DrawText(_T("White inside"), r.x, r.y); + r.Offset(0, TEXT_HEIGHT); + dc.GradientFillConcentric(r, *wxWHITE, *wxBLUE); + + r.Offset(0, r.height + 10); + dc.DrawText(_T("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(_T("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(wxPen(wxColour(255, 0, 0))); + dc.DrawRectangle(r); + r.Deflate(1); + dc.GradientFillLinear(r, wxColour(0,255,0), wxColour(0,0,0), wxNORTH); + dc.DrawRectangle(r2); + r2.Deflate(1); + dc.GradientFillLinear(r2, wxColour(0,0,0), wxColour(0,255,0), wxSOUTH); + dc.DrawRectangle(r3); + r3.Deflate(1); + dc.GradientFillLinear(r3, wxColour(0,255,0), wxColour(0,0,0), wxEAST); + dc.DrawRectangle(r4); + r4.Deflate(1); + dc.GradientFillLinear(r4, wxColour(0,0,0), wxColour(0,255,0), wxWEST); } void MyCanvas::DrawRegions(wxDC& dc) @@ -920,7 +1325,7 @@ void MyCanvas::DrawRegionsHelper(wxDC& dc, wxCoord x, bool firstTime) if ( !firstTime ) region.Offset(10, 10); #endif - dc.SetClippingRegion(region); + dc.SetDeviceClippingRegion(region); dc.SetBrush( *wxGREY_BRUSH ); dc.DrawRectangle( x, y, 310, 310 ); @@ -935,9 +1340,26 @@ void MyCanvas::DrawRegionsHelper(wxDC& dc, wxCoord x, bool firstTime) } } +#if TEST_CAIRO_EVERYWHERE +extern wxGraphicsRenderer* gCairoRenderer; +#endif + void MyCanvas::OnPaint(wxPaintEvent &WXUNUSED(event)) { - wxPaintDC dc(this); + wxPaintDC pdc(this); + +#if wxUSE_GRAPHICS_CONTEXT +#if TEST_CAIRO_EVERYWHERE + wxGCDC gdc; + gdc.SetGraphicsContext( gCairoRenderer->CreateContext( pdc ) ); +#else + wxGCDC gdc( pdc ) ; +#endif + wxDC &dc = m_useContext ? (wxDC&) gdc : (wxDC&) pdc ; +#else + wxDC &dc = pdc ; +#endif + PrepareDC(dc); m_owner->PrepareDC(dc); @@ -972,65 +1394,151 @@ void MyCanvas::OnPaint(wxPaintEvent &WXUNUSED(event)) switch ( m_show ) { - case Show_Default: + case File_ShowDefault: DrawDefault(dc); break; - case Show_Circles: + case File_ShowCircles: DrawCircles(dc); break; - case Show_Regions: + case File_ShowSplines: + DrawSplines(dc); + break; + + case File_ShowRegions: DrawRegions(dc); break; - case Show_Text: + case File_ShowText: DrawText(dc); break; - case Show_Lines: + 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 Show_Brushes: + case File_ShowBrushes: DrawTestBrushes(dc); break; - case Show_Polygons: + case File_ShowPolygons: DrawTestPoly(dc); break; - case Show_Mask: - DrawImages(dc); + case File_ShowMask: + DrawImages(dc, Draw_Normal); break; - case Show_Ops: + 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 ); + { + 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, wxSOLID ) ); + 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; + + int x,y,xx,yy ; + event.GetPosition(&x,&y); + CalcUnscrolledPosition( x, y, &xx, &yy ); + + wxString str; + str.Printf( wxT("Rectangle selection from %d,%d to %d,%d"), + m_anchorpoint.x, m_anchorpoint.y , (int)xx, (int)yy ); + wxMessageBox( str , wxT("Rubber-Banding") ); + + } +} + // ---------------------------------------------------------------------------- // MyFrame // ---------------------------------------------------------------------------- @@ -1042,6 +1550,9 @@ 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_RANGE(MenuShow_First, MenuShow_Last, MyFrame::OnShow) @@ -1063,11 +1574,23 @@ MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size) menuFile->Append(File_ShowBrushes, _T("&Brushes screen\tF4")); menuFile->Append(File_ShowPolygons, _T("&Polygons screen\tF5")); menuFile->Append(File_ShowMask, _T("&Mask screen\tF6")); - menuFile->Append(File_ShowOps, _T("&ROP screen\tF7")); + menuFile->Append(File_ShowMaskStretch, _T("1/&2 scaled mask\tShift-F6")); + menuFile->Append(File_ShowOps, _T("&Raster operations screen\tF7")); menuFile->Append(File_ShowRegions, _T("Re&gions screen\tF8")); menuFile->Append(File_ShowCircles, _T("&Circles screen\tF9")); +#if wxUSE_GRAPHICS_CONTEXT + menuFile->Append(File_ShowAlpha, _T("&Alpha screen\tF10")); +#endif + menuFile->Append(File_ShowSplines, _T("&Splines screen\tF11")); + menuFile->Append(File_ShowGradients, _T("&Gradients screen\tF12")); +#if wxUSE_GRAPHICS_CONTEXT + menuFile->Append(File_ShowGraphics, _T("&Graphics screen")); +#endif menuFile->AppendSeparator(); menuFile->AppendCheckItem(File_Clip, _T("&Clip\tCtrl-C"), _T("Clip/unclip drawing")); +#if wxUSE_GRAPHICS_CONTEXT + menuFile->AppendCheckItem(File_GraphicContext, _T("&Use GraphicContext\tCtrl-Y"), _T("Use GraphicContext")); +#endif menuFile->AppendSeparator(); menuFile->Append(File_About, _T("&About...\tCtrl-A"), _T("Show about dialog")); menuFile->AppendSeparator(); @@ -1168,9 +1691,16 @@ 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::OnShow(wxCommandEvent& event) { - m_canvas->ToShow((ScreenToShow)(event.GetId() - MenuShow_First)); + m_canvas->ToShow(event.GetId()); } void MyFrame::OnOption(wxCommandEvent& event) @@ -1296,4 +1826,3 @@ wxColour MyFrame::SelectColour() return col; } #endif // wxUSE_COLOURDLG -