X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/e3b81044ee30ead362ba6e1bf95af13248afe41c..3c01c5951189e13b8b4a5d7b288b54d4a57a30f8:/samples/drawing/drawing.cpp diff --git a/samples/drawing/drawing.cpp b/samples/drawing/drawing.cpp index 2c217f8826..9b288944fb 100644 --- a/samples/drawing/drawing.cpp +++ b/samples/drawing/drawing.cpp @@ -33,22 +33,15 @@ #include "wx/colordlg.h" #include "wx/image.h" #include "wx/artprov.h" - -#define wxTEST_GRAPHICS 1 - -#if wxTEST_GRAPHICS +#include "wx/dcgraph.h" +#include "wx/overlay.h" #include "wx/graphics.h" -#if wxUSE_GRAPHICS_CONTEXT == 0 -#undef wxTEST_GRAPHICS -#define wxTEST_GRAPHICS 0 -#endif -#else -#undef wxUSE_GRAPHICS_CONTEXT -#define wxUSE_GRAPHICS_CONTEXT 0 -#endif +#include "wx/filename.h" + +#define TEST_CAIRO_EVERYWHERE 0 // ---------------------------------------------------------------------------- -// ressources +// resources // ---------------------------------------------------------------------------- // the application icon @@ -56,32 +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_Mask_Stretch, - Show_Ops, - Show_Regions, - Show_Circles, - Show_Splines, -#if wxUSE_GRAPHICS_CONTEXT - Show_Alpha, -#endif - Show_Gradient, - Show_Max -}; - // ---------------------------------------------------------------------------- // global variables // ---------------------------------------------------------------------------- @@ -144,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; @@ -169,8 +136,10 @@ 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(); } @@ -193,6 +162,7 @@ protected: 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); @@ -205,10 +175,14 @@ protected: 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 @@ -241,6 +215,7 @@ enum File_ShowSplines, #if wxUSE_GRAPHICS_CONTEXT File_ShowAlpha, + File_ShowGraphics, #endif File_ShowGradients, MenuShow_Last = File_ShowGradients, @@ -316,6 +291,9 @@ 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("../..")); @@ -379,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; } @@ -417,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" @@ -426,10 +403,11 @@ 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 @@ -790,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 ); @@ -805,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 }, @@ -962,6 +940,121 @@ void MyCanvas::DrawAlpha(wxDC& dc) #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, @@ -1159,6 +1252,37 @@ void MyCanvas::DrawGradients(wxDC& dc) 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) @@ -1201,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 ); @@ -1216,12 +1340,21 @@ void MyCanvas::DrawRegionsHelper(wxDC& dc, wxCoord x, bool firstTime) } } +#if TEST_CAIRO_EVERYWHERE +extern wxGraphicsRenderer* gCairoRenderer; +#endif + void MyCanvas::OnPaint(wxPaintEvent &WXUNUSED(event)) { 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 ; @@ -1261,60 +1394,63 @@ 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_Splines: + case File_ShowSplines: DrawSplines(dc); break; - case Show_Regions: + 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: + case File_ShowMask: DrawImages(dc, Draw_Normal); break; - case Show_Mask_Stretch: + case File_ShowMaskStretch: DrawImages(dc, Draw_Stretch); break; - case Show_Ops: + case File_ShowOps: DrawWithLogicalOps(dc); break; #if wxUSE_GRAPHICS_CONTEXT - case Show_Alpha: + case File_ShowAlpha: DrawAlpha(dc); break; + case File_ShowGraphics: + DrawGraphics(gdc.GetGraphicsContext()); + break; #endif - case Show_Gradient: + case File_ShowGradients: DrawGradients(dc); break; @@ -1326,21 +1462,83 @@ void MyCanvas::OnPaint(wxPaintEvent &WXUNUSED(event)) 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 // ---------------------------------------------------------------------------- @@ -1377,7 +1575,7 @@ MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size) menuFile->Append(File_ShowPolygons, _T("&Polygons screen\tF5")); menuFile->Append(File_ShowMask, _T("&Mask screen\tF6")); menuFile->Append(File_ShowMaskStretch, _T("1/&2 scaled mask\tShift-F6")); - menuFile->Append(File_ShowOps, _T("&ROP screen\tF7")); + 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 @@ -1385,6 +1583,9 @@ MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size) #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 @@ -1499,7 +1700,7 @@ void MyFrame::OnGraphicContext(wxCommandEvent& event) void MyFrame::OnShow(wxCommandEvent& event) { - m_canvas->ToShow((ScreenToShow)(event.GetId() - MenuShow_First)); + m_canvas->ToShow(event.GetId()); } void MyFrame::OnOption(wxCommandEvent& event)