drawing.cpp 63 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065
  1. /////////////////////////////////////////////////////////////////////////////
  2. // Name: samples/drawing/drawing.cpp
  3. // Purpose: shows and tests wxDC features
  4. // Author: Robert Roebling
  5. // Modified by:
  6. // Created: 04/01/98
  7. // Copyright: (c) Robert Roebling
  8. // Licence: wxWindows licence
  9. /////////////////////////////////////////////////////////////////////////////
  10. // ============================================================================
  11. // declarations
  12. // ============================================================================
  13. // ----------------------------------------------------------------------------
  14. // headers
  15. // ----------------------------------------------------------------------------
  16. // For compilers that support precompilation, includes "wx/wx.h".
  17. #include "wx/wxprec.h"
  18. #ifdef __BORLANDC__
  19. #pragma hdrstop
  20. #endif
  21. // for all others, include the necessary headers (this file is usually all you
  22. // need because it includes almost all "standard" wxWidgets headers
  23. #ifndef WX_PRECOMP
  24. #include "wx/wx.h"
  25. #endif
  26. #include "wx/colordlg.h"
  27. #include "wx/image.h"
  28. #include "wx/artprov.h"
  29. #include "wx/dcbuffer.h"
  30. #include "wx/dcgraph.h"
  31. #include "wx/overlay.h"
  32. #include "wx/graphics.h"
  33. #include "wx/filename.h"
  34. #include "wx/metafile.h"
  35. #define TEST_CAIRO_EVERYWHERE 0
  36. // ----------------------------------------------------------------------------
  37. // resources
  38. // ----------------------------------------------------------------------------
  39. // the application icon
  40. #ifndef wxHAS_IMAGES_IN_RESOURCES
  41. #include "../sample.xpm"
  42. #endif
  43. // ----------------------------------------------------------------------------
  44. // global variables
  45. // ----------------------------------------------------------------------------
  46. static wxBitmap *gs_bmpNoMask = NULL,
  47. *gs_bmpWithColMask = NULL,
  48. *gs_bmpMask = NULL,
  49. *gs_bmpWithMask = NULL,
  50. *gs_bmp4 = NULL,
  51. *gs_bmp4_mono = NULL,
  52. *gs_bmp36 = NULL;
  53. // ----------------------------------------------------------------------------
  54. // private classes
  55. // ----------------------------------------------------------------------------
  56. // Define a new application type, each program should derive a class from wxApp
  57. class MyApp : public wxApp
  58. {
  59. public:
  60. // override base class virtuals
  61. // ----------------------------
  62. // this one is called on application startup and is a good place for the app
  63. // initialization (doing it here and not in the ctor allows to have an error
  64. // return: if OnInit() returns false, the application terminates)
  65. virtual bool OnInit();
  66. virtual int OnExit() { DeleteBitmaps(); return 0; }
  67. protected:
  68. void DeleteBitmaps();
  69. bool LoadImages();
  70. };
  71. class MyCanvas;
  72. // Define a new frame type: this is going to be our main frame
  73. class MyFrame : public wxFrame
  74. {
  75. public:
  76. // ctor(s)
  77. MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size);
  78. // event handlers (these functions should _not_ be virtual)
  79. void OnQuit(wxCommandEvent& event);
  80. void OnAbout(wxCommandEvent& event);
  81. void OnClip(wxCommandEvent& event);
  82. #if wxUSE_GRAPHICS_CONTEXT
  83. void OnGraphicContext(wxCommandEvent& event);
  84. #endif
  85. void OnBuffer(wxCommandEvent& event);
  86. void OnCopy(wxCommandEvent& event);
  87. void OnSave(wxCommandEvent& event);
  88. void OnShow(wxCommandEvent &event);
  89. void OnOption(wxCommandEvent &event);
  90. #if wxUSE_COLOURDLG
  91. wxColour SelectColour();
  92. #endif // wxUSE_COLOURDLG
  93. void PrepareDC(wxDC& dc);
  94. int m_backgroundMode;
  95. int m_textureBackground;
  96. wxMappingMode m_mapMode;
  97. double m_xUserScale;
  98. double m_yUserScale;
  99. int m_xLogicalOrigin;
  100. int m_yLogicalOrigin;
  101. bool m_xAxisReversed,
  102. m_yAxisReversed;
  103. wxColour m_colourForeground, // these are _text_ colours
  104. m_colourBackground;
  105. wxBrush m_backgroundBrush;
  106. MyCanvas *m_canvas;
  107. private:
  108. // any class wishing to process wxWidgets events must use this macro
  109. wxDECLARE_EVENT_TABLE();
  110. };
  111. // define a scrollable canvas for drawing onto
  112. class MyCanvas: public wxScrolledWindow
  113. {
  114. public:
  115. MyCanvas( MyFrame *parent );
  116. void OnPaint(wxPaintEvent &event);
  117. void OnMouseMove(wxMouseEvent &event);
  118. void OnMouseDown(wxMouseEvent &event);
  119. void OnMouseUp(wxMouseEvent &event);
  120. void ToShow(int show) { m_show = show; Refresh(); }
  121. // set or remove the clipping region
  122. void Clip(bool clip) { m_clip = clip; Refresh(); }
  123. #if wxUSE_GRAPHICS_CONTEXT
  124. void UseGraphicContext(bool use) { m_useContext = use; Refresh(); }
  125. #endif
  126. void UseBuffer(bool use) { m_useBuffer = use; Refresh(); }
  127. void Draw(wxDC& dc);
  128. protected:
  129. enum DrawMode
  130. {
  131. Draw_Normal,
  132. Draw_Stretch
  133. };
  134. void DrawTestLines( int x, int y, int width, wxDC &dc );
  135. void DrawTestPoly(wxDC& dc);
  136. void DrawTestBrushes(wxDC& dc);
  137. void DrawText(wxDC& dc);
  138. void DrawImages(wxDC& dc, DrawMode mode);
  139. void DrawWithLogicalOps(wxDC& dc);
  140. #if wxUSE_GRAPHICS_CONTEXT
  141. void DrawAlpha(wxDC& dc);
  142. void DrawGraphics(wxGraphicsContext* gc);
  143. #endif
  144. void DrawRegions(wxDC& dc);
  145. void DrawCircles(wxDC& dc);
  146. void DrawSplines(wxDC& dc);
  147. void DrawDefault(wxDC& dc);
  148. void DrawGradients(wxDC& dc);
  149. void DrawRegionsHelper(wxDC& dc, wxCoord x, bool firstTime);
  150. private:
  151. MyFrame *m_owner;
  152. int m_show;
  153. wxBitmap m_smile_bmp;
  154. wxIcon m_std_icon;
  155. bool m_clip;
  156. wxOverlay m_overlay;
  157. bool m_rubberBand;
  158. wxPoint m_anchorpoint;
  159. wxPoint m_currentpoint;
  160. #if wxUSE_GRAPHICS_CONTEXT
  161. bool m_useContext ;
  162. #endif
  163. bool m_useBuffer;
  164. wxDECLARE_EVENT_TABLE();
  165. };
  166. // ----------------------------------------------------------------------------
  167. // constants
  168. // ----------------------------------------------------------------------------
  169. // IDs for the controls and the menu commands
  170. enum
  171. {
  172. // menu items
  173. File_Quit = wxID_EXIT,
  174. File_About = wxID_ABOUT,
  175. MenuShow_First = wxID_HIGHEST,
  176. File_ShowDefault = MenuShow_First,
  177. File_ShowText,
  178. File_ShowLines,
  179. File_ShowBrushes,
  180. File_ShowPolygons,
  181. File_ShowMask,
  182. File_ShowMaskStretch,
  183. File_ShowOps,
  184. File_ShowRegions,
  185. File_ShowCircles,
  186. File_ShowSplines,
  187. #if wxUSE_GRAPHICS_CONTEXT
  188. File_ShowAlpha,
  189. File_ShowGraphics,
  190. #endif
  191. File_ShowGradients,
  192. MenuShow_Last = File_ShowGradients,
  193. File_Clip,
  194. #if wxUSE_GRAPHICS_CONTEXT
  195. File_GraphicContext,
  196. #endif
  197. File_Buffer,
  198. File_Copy,
  199. File_Save,
  200. MenuOption_First,
  201. MapMode_Text = MenuOption_First,
  202. MapMode_Lometric,
  203. MapMode_Twips,
  204. MapMode_Points,
  205. MapMode_Metric,
  206. UserScale_StretchHoriz,
  207. UserScale_ShrinkHoriz,
  208. UserScale_StretchVertic,
  209. UserScale_ShrinkVertic,
  210. UserScale_Restore,
  211. AxisMirror_Horiz,
  212. AxisMirror_Vertic,
  213. LogicalOrigin_MoveDown,
  214. LogicalOrigin_MoveUp,
  215. LogicalOrigin_MoveLeft,
  216. LogicalOrigin_MoveRight,
  217. LogicalOrigin_Set,
  218. LogicalOrigin_Restore,
  219. #if wxUSE_COLOURDLG
  220. Colour_TextForeground,
  221. Colour_TextBackground,
  222. Colour_Background,
  223. #endif // wxUSE_COLOURDLG
  224. Colour_BackgroundMode,
  225. Colour_TextureBackgound,
  226. MenuOption_Last = Colour_TextureBackgound
  227. };
  228. // ----------------------------------------------------------------------------
  229. // event tables and other macros for wxWidgets
  230. // ----------------------------------------------------------------------------
  231. // Create a new application object: this macro will allow wxWidgets to create
  232. // the application object during program execution (it's better than using a
  233. // static object for many reasons) and also declares the accessor function
  234. // wxGetApp() which will return the reference of the right type (i.e. MyApp and
  235. // not wxApp)
  236. IMPLEMENT_APP(MyApp)
  237. // ============================================================================
  238. // implementation
  239. // ============================================================================
  240. // ----------------------------------------------------------------------------
  241. // the application class
  242. // ----------------------------------------------------------------------------
  243. bool MyApp::LoadImages()
  244. {
  245. gs_bmpNoMask = new wxBitmap;
  246. gs_bmpWithColMask = new wxBitmap;
  247. gs_bmpMask = new wxBitmap;
  248. gs_bmpWithMask = new wxBitmap;
  249. gs_bmp4 = new wxBitmap;
  250. gs_bmp4_mono = new wxBitmap;
  251. gs_bmp36 = new wxBitmap;
  252. wxPathList pathList;
  253. // special hack for Unix in-tree sample build, don't do this in real
  254. // programs, use wxStandardPaths instead
  255. pathList.Add(wxFileName(argv[0]).GetPath());
  256. pathList.Add(wxT("."));
  257. pathList.Add(wxT(".."));
  258. pathList.Add(wxT("../.."));
  259. wxString path = pathList.FindValidPath(wxT("pat4.bmp"));
  260. if ( !path )
  261. return false;
  262. /* 4 colour bitmap */
  263. gs_bmp4->LoadFile(path, wxBITMAP_TYPE_BMP);
  264. /* turn into mono-bitmap */
  265. gs_bmp4_mono->LoadFile(path, wxBITMAP_TYPE_BMP);
  266. wxMask* mask4 = new wxMask(*gs_bmp4_mono, *wxBLACK);
  267. gs_bmp4_mono->SetMask(mask4);
  268. path = pathList.FindValidPath(wxT("pat36.bmp"));
  269. if ( !path )
  270. return false;
  271. gs_bmp36->LoadFile(path, wxBITMAP_TYPE_BMP);
  272. wxMask* mask36 = new wxMask(*gs_bmp36, *wxBLACK);
  273. gs_bmp36->SetMask(mask36);
  274. path = pathList.FindValidPath(wxT("image.bmp"));
  275. if ( !path )
  276. return false;
  277. gs_bmpNoMask->LoadFile(path, wxBITMAP_TYPE_BMP);
  278. gs_bmpWithMask->LoadFile(path, wxBITMAP_TYPE_BMP);
  279. gs_bmpWithColMask->LoadFile(path, wxBITMAP_TYPE_BMP);
  280. path = pathList.FindValidPath(wxT("mask.bmp"));
  281. if ( !path )
  282. return false;
  283. gs_bmpMask->LoadFile(path, wxBITMAP_TYPE_BMP);
  284. wxMask *mask = new wxMask(*gs_bmpMask, *wxBLACK);
  285. gs_bmpWithMask->SetMask(mask);
  286. mask = new wxMask(*gs_bmpWithColMask, *wxWHITE);
  287. gs_bmpWithColMask->SetMask(mask);
  288. return true;
  289. }
  290. // `Main program' equivalent: the program execution "starts" here
  291. bool MyApp::OnInit()
  292. {
  293. if ( !wxApp::OnInit() )
  294. return false;
  295. // Create the main application window
  296. MyFrame *frame = new MyFrame(wxT("Drawing sample"),
  297. wxDefaultPosition, wxSize(550, 840));
  298. // Show it
  299. frame->Show(true);
  300. if ( !LoadImages() )
  301. {
  302. wxLogError(wxT("Can't load one of the bitmap files needed ")
  303. wxT("for this sample from the current or parent ")
  304. wxT("directory, please copy them there."));
  305. // still continue, the sample can be used without images too if they're
  306. // missing for whatever reason
  307. }
  308. #if wxUSE_LIBPNG
  309. wxImage::AddHandler( new wxPNGHandler );
  310. #endif
  311. return true;
  312. }
  313. void MyApp::DeleteBitmaps()
  314. {
  315. wxDELETE(gs_bmpNoMask);
  316. wxDELETE(gs_bmpWithColMask);
  317. wxDELETE(gs_bmpMask);
  318. wxDELETE(gs_bmpWithMask);
  319. wxDELETE(gs_bmp4);
  320. wxDELETE(gs_bmp4_mono);
  321. wxDELETE(gs_bmp36);
  322. }
  323. // ----------------------------------------------------------------------------
  324. // MyCanvas
  325. // ----------------------------------------------------------------------------
  326. // the event tables connect the wxWidgets events with the functions (event
  327. // handlers) which process them.
  328. wxBEGIN_EVENT_TABLE(MyCanvas, wxScrolledWindow)
  329. EVT_PAINT (MyCanvas::OnPaint)
  330. EVT_MOTION (MyCanvas::OnMouseMove)
  331. EVT_LEFT_DOWN (MyCanvas::OnMouseDown)
  332. EVT_LEFT_UP (MyCanvas::OnMouseUp)
  333. wxEND_EVENT_TABLE()
  334. #include "smile.xpm"
  335. MyCanvas::MyCanvas(MyFrame *parent)
  336. : wxScrolledWindow(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize,
  337. wxHSCROLL | wxVSCROLL | wxNO_FULL_REPAINT_ON_RESIZE)
  338. {
  339. m_owner = parent;
  340. m_show = File_ShowDefault;
  341. m_smile_bmp = wxBitmap(smile_xpm);
  342. m_std_icon = wxArtProvider::GetIcon(wxART_INFORMATION);
  343. m_clip = false;
  344. m_rubberBand = false;
  345. #if wxUSE_GRAPHICS_CONTEXT
  346. m_useContext = false;
  347. #endif
  348. m_useBuffer = false;
  349. }
  350. void MyCanvas::DrawTestBrushes(wxDC& dc)
  351. {
  352. static const wxCoord WIDTH = 200;
  353. static const wxCoord HEIGHT = 80;
  354. wxCoord x = 10,
  355. y = 10;
  356. dc.SetBrush(*wxGREEN_BRUSH);
  357. dc.DrawRectangle(x, y, WIDTH, HEIGHT);
  358. dc.DrawText(wxT("Solid green"), x + 10, y + 10);
  359. y += HEIGHT;
  360. dc.SetBrush(wxBrush(*wxRED, wxBRUSHSTYLE_CROSSDIAG_HATCH));
  361. dc.DrawRectangle(x, y, WIDTH, HEIGHT);
  362. dc.DrawText(wxT("Diagonally hatched red"), x + 10, y + 10);
  363. y += HEIGHT;
  364. dc.SetBrush(wxBrush(*wxBLUE, wxBRUSHSTYLE_CROSS_HATCH));
  365. dc.DrawRectangle(x, y, WIDTH, HEIGHT);
  366. dc.DrawText(wxT("Cross hatched blue"), x + 10, y + 10);
  367. y += HEIGHT;
  368. dc.SetBrush(wxBrush(*wxCYAN, wxBRUSHSTYLE_VERTICAL_HATCH));
  369. dc.DrawRectangle(x, y, WIDTH, HEIGHT);
  370. dc.DrawText(wxT("Vertically hatched cyan"), x + 10, y + 10);
  371. y += HEIGHT;
  372. dc.SetBrush(wxBrush(*wxBLACK, wxBRUSHSTYLE_HORIZONTAL_HATCH));
  373. dc.DrawRectangle(x, y, WIDTH, HEIGHT);
  374. dc.DrawText(wxT("Horizontally hatched black"), x + 10, y + 10);
  375. y += HEIGHT;
  376. dc.SetBrush(wxBrush(*gs_bmpMask));
  377. dc.DrawRectangle(x, y, WIDTH, HEIGHT);
  378. dc.DrawText(wxT("Stipple mono"), x + 10, y + 10);
  379. y += HEIGHT;
  380. dc.SetBrush(wxBrush(*gs_bmpNoMask));
  381. dc.DrawRectangle(x, y, WIDTH, HEIGHT);
  382. dc.DrawText(wxT("Stipple colour"), x + 10, y + 10);
  383. }
  384. void MyCanvas::DrawTestPoly(wxDC& dc)
  385. {
  386. wxBrush brushHatch(*wxRED, wxBRUSHSTYLE_FDIAGONAL_HATCH);
  387. dc.SetBrush(brushHatch);
  388. wxPoint star[5];
  389. star[0] = wxPoint(100, 60);
  390. star[1] = wxPoint(60, 150);
  391. star[2] = wxPoint(160, 100);
  392. star[3] = wxPoint(40, 100);
  393. star[4] = wxPoint(140, 150);
  394. dc.DrawText(wxT("You should see two (irregular) stars below, the left one ")
  395. wxT("hatched"), 10, 10);
  396. dc.DrawText(wxT("except for the central region and the right ")
  397. wxT("one entirely hatched"), 10, 30);
  398. dc.DrawText(wxT("The third star only has a hatched outline"), 10, 50);
  399. dc.DrawPolygon(WXSIZEOF(star), star, 0, 30);
  400. dc.DrawPolygon(WXSIZEOF(star), star, 160, 30, wxWINDING_RULE);
  401. wxPoint star2[10];
  402. star2[0] = wxPoint(0, 100);
  403. star2[1] = wxPoint(-59, -81);
  404. star2[2] = wxPoint(95, 31);
  405. star2[3] = wxPoint(-95, 31);
  406. star2[4] = wxPoint(59, -81);
  407. star2[5] = wxPoint(0, 80);
  408. star2[6] = wxPoint(-47, -64);
  409. star2[7] = wxPoint(76, 24);
  410. star2[8] = wxPoint(-76, 24);
  411. star2[9] = wxPoint(47, -64);
  412. int count[2] = {5, 5};
  413. dc.DrawPolyPolygon(WXSIZEOF(count), count, star2, 450, 150);
  414. }
  415. void MyCanvas::DrawTestLines( int x, int y, int width, wxDC &dc )
  416. {
  417. dc.SetPen( wxPen( *wxBLACK, width ) );
  418. dc.SetBrush( *wxRED_BRUSH );
  419. dc.DrawText(wxString::Format(wxT("Testing lines of width %d"), width), x + 10, y - 10);
  420. dc.DrawRectangle( x+10, y+10, 100, 190 );
  421. dc.DrawText(wxT("Solid/dot/short dash/long dash/dot dash"), x + 150, y + 10);
  422. dc.SetPen( wxPen( *wxBLACK, width ) );
  423. dc.DrawLine( x+20, y+20, 100, y+20 );
  424. dc.SetPen( wxPen( *wxBLACK, width, wxPENSTYLE_DOT) );
  425. dc.DrawLine( x+20, y+30, 100, y+30 );
  426. dc.SetPen( wxPen( *wxBLACK, width, wxPENSTYLE_SHORT_DASH) );
  427. dc.DrawLine( x+20, y+40, 100, y+40 );
  428. dc.SetPen( wxPen( *wxBLACK, width, wxPENSTYLE_LONG_DASH) );
  429. dc.DrawLine( x+20, y+50, 100, y+50 );
  430. dc.SetPen( wxPen( *wxBLACK, width, wxPENSTYLE_DOT_DASH) );
  431. dc.DrawLine( x+20, y+60, 100, y+60 );
  432. dc.DrawText(wxT("Misc hatches"), x + 150, y + 70);
  433. dc.SetPen( wxPen( *wxBLACK, width, wxPENSTYLE_BDIAGONAL_HATCH) );
  434. dc.DrawLine( x+20, y+70, 100, y+70 );
  435. dc.SetPen( wxPen( *wxBLACK, width, wxPENSTYLE_CROSSDIAG_HATCH) );
  436. dc.DrawLine( x+20, y+80, 100, y+80 );
  437. dc.SetPen( wxPen( *wxBLACK, width, wxPENSTYLE_FDIAGONAL_HATCH) );
  438. dc.DrawLine( x+20, y+90, 100, y+90 );
  439. dc.SetPen( wxPen( *wxBLACK, width, wxPENSTYLE_CROSS_HATCH) );
  440. dc.DrawLine( x+20, y+100, 100, y+100 );
  441. dc.SetPen( wxPen( *wxBLACK, width, wxPENSTYLE_HORIZONTAL_HATCH) );
  442. dc.DrawLine( x+20, y+110, 100, y+110 );
  443. dc.SetPen( wxPen( *wxBLACK, width, wxPENSTYLE_VERTICAL_HATCH) );
  444. dc.DrawLine( x+20, y+120, 100, y+120 );
  445. dc.DrawText(wxT("User dash"), x + 150, y + 140);
  446. wxPen ud( *wxBLACK, width, wxPENSTYLE_USER_DASH );
  447. wxDash dash1[6];
  448. dash1[0] = 8; // Long dash <---------+
  449. dash1[1] = 2; // Short gap |
  450. dash1[2] = 3; // Short dash |
  451. dash1[3] = 2; // Short gap |
  452. dash1[4] = 3; // Short dash |
  453. dash1[5] = 2; // Short gap and repeat +
  454. ud.SetDashes( 6, dash1 );
  455. dc.SetPen( ud );
  456. dc.DrawLine( x+20, y+140, 100, y+140 );
  457. dash1[0] = 5; // Make first dash shorter
  458. ud.SetDashes( 6, dash1 );
  459. dc.SetPen( ud );
  460. dc.DrawLine( x+20, y+150, 100, y+150 );
  461. dash1[2] = 5; // Make second dash longer
  462. ud.SetDashes( 6, dash1 );
  463. dc.SetPen( ud );
  464. dc.DrawLine( x+20, y+160, 100, y+160 );
  465. dash1[4] = 5; // Make third dash longer
  466. ud.SetDashes( 6, dash1 );
  467. dc.SetPen( ud );
  468. dc.DrawLine( x+20, y+170, 100, y+170 );
  469. }
  470. void MyCanvas::DrawDefault(wxDC& dc)
  471. {
  472. // Draw circle centered at the origin, then flood fill it with a different
  473. // color. Done with a wxMemoryDC because Blit (used by generic
  474. // wxDoFloodFill) from a window that is being painted gives unpredictable
  475. // results on wxGTK
  476. {
  477. wxImage img(21, 21, false);
  478. img.Clear(1);
  479. wxBitmap bmp(img);
  480. {
  481. wxMemoryDC mdc(bmp);
  482. mdc.SetBrush(dc.GetBrush());
  483. mdc.SetPen(dc.GetPen());
  484. mdc.DrawCircle(10, 10, 10);
  485. wxColour c;
  486. if (mdc.GetPixel(11, 11, &c))
  487. {
  488. mdc.SetBrush(wxColour(128, 128, 0));
  489. mdc.FloodFill(11, 11, c, wxFLOOD_SURFACE);
  490. }
  491. }
  492. bmp.SetMask(new wxMask(bmp, wxColour(1, 1, 1)));
  493. dc.DrawBitmap(bmp, -10, -10, true);
  494. }
  495. dc.DrawCheckMark(5, 80, 15, 15);
  496. dc.DrawCheckMark(25, 80, 30, 30);
  497. dc.DrawCheckMark(60, 80, 60, 60);
  498. // this is the test for "blitting bitmap into DC damages selected brush" bug
  499. wxCoord rectSize = m_std_icon.GetWidth() + 10;
  500. wxCoord x = 100;
  501. dc.SetPen(*wxTRANSPARENT_PEN);
  502. dc.SetBrush( *wxGREEN_BRUSH );
  503. dc.DrawRectangle(x, 10, rectSize, rectSize);
  504. dc.DrawBitmap(m_std_icon, x + 5, 15, true);
  505. x += rectSize + 10;
  506. dc.DrawRectangle(x, 10, rectSize, rectSize);
  507. dc.DrawIcon(m_std_icon, x + 5, 15);
  508. x += rectSize + 10;
  509. dc.DrawRectangle(x, 10, rectSize, rectSize);
  510. // test for "transparent" bitmap drawing (it intersects with the last
  511. // rectangle above)
  512. //dc.SetBrush( *wxTRANSPARENT_BRUSH );
  513. if (m_smile_bmp.IsOk())
  514. dc.DrawBitmap(m_smile_bmp, x + rectSize - 20, rectSize - 10, true);
  515. dc.SetBrush( *wxBLACK_BRUSH );
  516. dc.DrawRectangle( 0, 160, 1000, 300 );
  517. // draw lines
  518. wxBitmap bitmap(20,70);
  519. wxMemoryDC memdc;
  520. memdc.SelectObject( bitmap );
  521. memdc.SetBrush( *wxBLACK_BRUSH );
  522. memdc.SetPen( *wxWHITE_PEN );
  523. memdc.DrawRectangle(0,0,20,70);
  524. memdc.DrawLine( 10,0,10,70 );
  525. // to the right
  526. wxPen pen = *wxRED_PEN;
  527. memdc.SetPen(pen);
  528. memdc.DrawLine( 10, 5,10, 5 );
  529. memdc.DrawLine( 10,10,11,10 );
  530. memdc.DrawLine( 10,15,12,15 );
  531. memdc.DrawLine( 10,20,13,20 );
  532. /*
  533. memdc.SetPen(*wxRED_PEN);
  534. memdc.DrawLine( 12, 5,12, 5 );
  535. memdc.DrawLine( 12,10,13,10 );
  536. memdc.DrawLine( 12,15,14,15 );
  537. memdc.DrawLine( 12,20,15,20 );
  538. */
  539. // same to the left
  540. memdc.DrawLine( 10,25,10,25 );
  541. memdc.DrawLine( 10,30, 9,30 );
  542. memdc.DrawLine( 10,35, 8,35 );
  543. memdc.DrawLine( 10,40, 7,40 );
  544. // XOR draw lines
  545. dc.SetPen(*wxWHITE_PEN);
  546. memdc.SetLogicalFunction( wxINVERT );
  547. memdc.SetPen( *wxWHITE_PEN );
  548. memdc.DrawLine( 10,50,10,50 );
  549. memdc.DrawLine( 10,55,11,55 );
  550. memdc.DrawLine( 10,60,12,60 );
  551. memdc.DrawLine( 10,65,13,65 );
  552. memdc.DrawLine( 12,50,12,50 );
  553. memdc.DrawLine( 12,55,13,55 );
  554. memdc.DrawLine( 12,60,14,60 );
  555. memdc.DrawLine( 12,65,15,65 );
  556. memdc.SelectObject( wxNullBitmap );
  557. dc.DrawBitmap( bitmap, 10, 170 );
  558. wxImage image = bitmap.ConvertToImage();
  559. image.Rescale( 60,210 );
  560. bitmap = wxBitmap(image);
  561. dc.DrawBitmap( bitmap, 50, 170 );
  562. // test the rectangle outline drawing - there should be one pixel between
  563. // the rect and the lines
  564. dc.SetPen(*wxWHITE_PEN);
  565. dc.SetBrush( *wxTRANSPARENT_BRUSH );
  566. dc.DrawRectangle(150, 170, 49, 29);
  567. dc.DrawRectangle(200, 170, 49, 29);
  568. dc.SetPen(*wxWHITE_PEN);
  569. dc.DrawLine(250, 210, 250, 170);
  570. dc.DrawLine(260, 200, 150, 200);
  571. // test the rectangle filled drawing - there should be one pixel between
  572. // the rect and the lines
  573. dc.SetPen(*wxTRANSPARENT_PEN);
  574. dc.SetBrush( *wxWHITE_BRUSH );
  575. dc.DrawRectangle(300, 170, 49, 29);
  576. dc.DrawRectangle(350, 170, 49, 29);
  577. dc.SetPen(*wxWHITE_PEN);
  578. dc.DrawLine(400, 170, 400, 210);
  579. dc.DrawLine(300, 200, 410, 200);
  580. // a few more tests of this kind
  581. dc.SetPen(*wxRED_PEN);
  582. dc.SetBrush( *wxWHITE_BRUSH );
  583. dc.DrawRectangle(300, 220, 1, 1);
  584. dc.DrawRectangle(310, 220, 2, 2);
  585. dc.DrawRectangle(320, 220, 3, 3);
  586. dc.DrawRectangle(330, 220, 4, 4);
  587. dc.SetPen(*wxTRANSPARENT_PEN);
  588. dc.SetBrush( *wxWHITE_BRUSH );
  589. dc.DrawRectangle(300, 230, 1, 1);
  590. dc.DrawRectangle(310, 230, 2, 2);
  591. dc.DrawRectangle(320, 230, 3, 3);
  592. dc.DrawRectangle(330, 230, 4, 4);
  593. // and now for filled rect with outline
  594. dc.SetPen(*wxRED_PEN);
  595. dc.SetBrush( *wxWHITE_BRUSH );
  596. dc.DrawRectangle(500, 170, 49, 29);
  597. dc.DrawRectangle(550, 170, 49, 29);
  598. dc.SetPen(*wxWHITE_PEN);
  599. dc.DrawLine(600, 170, 600, 210);
  600. dc.DrawLine(500, 200, 610, 200);
  601. // test the rectangle outline drawing - there should be one pixel between
  602. // the rect and the lines
  603. dc.SetPen(*wxWHITE_PEN);
  604. dc.SetBrush( *wxTRANSPARENT_BRUSH );
  605. dc.DrawRoundedRectangle(150, 270, 49, 29, 6);
  606. dc.DrawRoundedRectangle(200, 270, 49, 29, 6);
  607. dc.SetPen(*wxWHITE_PEN);
  608. dc.DrawLine(250, 270, 250, 310);
  609. dc.DrawLine(150, 300, 260, 300);
  610. // test the rectangle filled drawing - there should be one pixel between
  611. // the rect and the lines
  612. dc.SetPen(*wxTRANSPARENT_PEN);
  613. dc.SetBrush( *wxWHITE_BRUSH );
  614. dc.DrawRoundedRectangle(300, 270, 49, 29, 6);
  615. dc.DrawRoundedRectangle(350, 270, 49, 29, 6);
  616. dc.SetPen(*wxWHITE_PEN);
  617. dc.DrawLine(400, 270, 400, 310);
  618. dc.DrawLine(300, 300, 410, 300);
  619. // Added by JACS to demonstrate bizarre behaviour.
  620. // With a size of 70, we get a missing red RHS,
  621. // and the height is too small, so we get yellow
  622. // showing. With a size of 40, it draws as expected:
  623. // it just shows a white rectangle with red outline.
  624. int totalWidth = 70;
  625. int totalHeight = 70;
  626. wxBitmap bitmap2(totalWidth, totalHeight);
  627. wxMemoryDC memdc2;
  628. memdc2.SelectObject(bitmap2);
  629. memdc2.SetBackground(*wxYELLOW_BRUSH);
  630. memdc2.Clear();
  631. // Now draw a white rectangle with red outline. It should
  632. // entirely eclipse the yellow background.
  633. memdc2.SetPen(*wxRED_PEN);
  634. memdc2.SetBrush(*wxWHITE_BRUSH);
  635. memdc2.DrawRectangle(0, 0, totalWidth, totalHeight);
  636. memdc2.SetPen(wxNullPen);
  637. memdc2.SetBrush(wxNullBrush);
  638. memdc2.SelectObject(wxNullBitmap);
  639. dc.DrawBitmap(bitmap2, 500, 270);
  640. // Repeat, but draw directly on dc
  641. // Draw a yellow rectangle filling the bitmap
  642. x = 600; int y = 270;
  643. dc.SetPen(*wxYELLOW_PEN);
  644. dc.SetBrush(*wxYELLOW_BRUSH);
  645. dc.DrawRectangle(x, y, totalWidth, totalHeight);
  646. // Now draw a white rectangle with red outline. It should
  647. // entirely eclipse the yellow background.
  648. dc.SetPen(*wxRED_PEN);
  649. dc.SetBrush(*wxWHITE_BRUSH);
  650. dc.DrawRectangle(x, y, totalWidth, totalHeight);
  651. }
  652. void MyCanvas::DrawText(wxDC& dc)
  653. {
  654. // set underlined font for testing
  655. dc.SetFont( wxFont(12, wxMODERN, wxNORMAL, wxNORMAL, true) );
  656. dc.DrawText( wxT("This is text"), 110, 10 );
  657. dc.DrawRotatedText( wxT("That is text"), 20, 10, -45 );
  658. // use wxSWISS_FONT and not wxNORMAL_FONT as the latter can't be rotated
  659. // under Win9x (it is not TrueType)
  660. dc.SetFont( *wxSWISS_FONT );
  661. wxString text;
  662. dc.SetBackgroundMode(wxTRANSPARENT);
  663. for ( int n = -180; n < 180; n += 30 )
  664. {
  665. text.Printf(wxT(" %d rotated text"), n);
  666. dc.DrawRotatedText(text , 400, 400, n);
  667. }
  668. dc.SetFont( wxFont( 18, wxSWISS, wxNORMAL, wxNORMAL ) );
  669. dc.DrawText( wxT("This is Swiss 18pt text."), 110, 40 );
  670. wxCoord length;
  671. wxCoord height;
  672. wxCoord descent;
  673. dc.GetTextExtent( wxT("This is Swiss 18pt text."), &length, &height, &descent );
  674. text.Printf( wxT("Dimensions are length %d, height %d, descent %d"), length, height, descent );
  675. dc.DrawText( text, 110, 80 );
  676. text.Printf( wxT("CharHeight() returns: %d"), dc.GetCharHeight() );
  677. dc.DrawText( text, 110, 120 );
  678. dc.DrawRectangle( 100, 40, 4, height );
  679. // test the logical function effect
  680. wxCoord y = 150;
  681. dc.SetLogicalFunction(wxINVERT);
  682. // text drawing should ignore logical function
  683. dc.DrawText( wxT("There should be a text below"), 110, 150 );
  684. dc.DrawRectangle( 110, y, 100, height );
  685. y += height;
  686. dc.DrawText( wxT("Visible text"), 110, y );
  687. dc.DrawRectangle( 110, y, 100, height );
  688. dc.DrawText( wxT("Visible text"), 110, y );
  689. dc.DrawRectangle( 110, y, 100, height );
  690. dc.SetLogicalFunction(wxCOPY);
  691. y += height;
  692. dc.DrawRectangle( 110, y, 100, height );
  693. dc.DrawText( wxT("Another visible text"), 110, y );
  694. y += height;
  695. dc.DrawText("And\nmore\ntext on\nmultiple\nlines", 110, y);
  696. }
  697. static const struct
  698. {
  699. const wxChar *name;
  700. wxRasterOperationMode rop;
  701. } rasterOperations[] =
  702. {
  703. { wxT("wxAND"), wxAND },
  704. { wxT("wxAND_INVERT"), wxAND_INVERT },
  705. { wxT("wxAND_REVERSE"), wxAND_REVERSE },
  706. { wxT("wxCLEAR"), wxCLEAR },
  707. { wxT("wxCOPY"), wxCOPY },
  708. { wxT("wxEQUIV"), wxEQUIV },
  709. { wxT("wxINVERT"), wxINVERT },
  710. { wxT("wxNAND"), wxNAND },
  711. { wxT("wxNO_OP"), wxNO_OP },
  712. { wxT("wxOR"), wxOR },
  713. { wxT("wxOR_INVERT"), wxOR_INVERT },
  714. { wxT("wxOR_REVERSE"), wxOR_REVERSE },
  715. { wxT("wxSET"), wxSET },
  716. { wxT("wxSRC_INVERT"), wxSRC_INVERT },
  717. { wxT("wxXOR"), wxXOR },
  718. };
  719. void MyCanvas::DrawImages(wxDC& dc, DrawMode mode)
  720. {
  721. dc.DrawText(wxT("original image"), 0, 0);
  722. dc.DrawBitmap(*gs_bmpNoMask, 0, 20, 0);
  723. dc.DrawText(wxT("with colour mask"), 0, 100);
  724. dc.DrawBitmap(*gs_bmpWithColMask, 0, 120, true);
  725. dc.DrawText(wxT("the mask image"), 0, 200);
  726. dc.DrawBitmap(*gs_bmpMask, 0, 220, 0);
  727. dc.DrawText(wxT("masked image"), 0, 300);
  728. dc.DrawBitmap(*gs_bmpWithMask, 0, 320, true);
  729. int cx = gs_bmpWithColMask->GetWidth(),
  730. cy = gs_bmpWithColMask->GetHeight();
  731. wxMemoryDC memDC;
  732. for ( size_t n = 0; n < WXSIZEOF(rasterOperations); n++ )
  733. {
  734. wxCoord x = 120 + 150*(n%4),
  735. y = 20 + 100*(n/4);
  736. dc.DrawText(rasterOperations[n].name, x, y - 20);
  737. memDC.SelectObject(*gs_bmpWithColMask);
  738. if ( mode == Draw_Stretch )
  739. {
  740. dc.StretchBlit(x, y, cx, cy, &memDC, 0, 0, cx/2, cy/2,
  741. rasterOperations[n].rop, true);
  742. }
  743. else
  744. {
  745. dc.Blit(x, y, cx, cy, &memDC, 0, 0, rasterOperations[n].rop, true);
  746. }
  747. }
  748. }
  749. void MyCanvas::DrawWithLogicalOps(wxDC& dc)
  750. {
  751. static const wxCoord w = 60;
  752. static const wxCoord h = 60;
  753. // reuse the text colour here
  754. dc.SetPen(wxPen(m_owner->m_colourForeground));
  755. dc.SetBrush(*wxTRANSPARENT_BRUSH);
  756. size_t n;
  757. for ( n = 0; n < WXSIZEOF(rasterOperations); n++ )
  758. {
  759. wxCoord x = 20 + 150*(n%4),
  760. y = 20 + 100*(n/4);
  761. dc.DrawText(rasterOperations[n].name, x, y - 20);
  762. dc.SetLogicalFunction(rasterOperations[n].rop);
  763. dc.DrawRectangle(x, y, w, h);
  764. dc.DrawLine(x, y, x + w, y + h);
  765. dc.DrawLine(x + w, y, x, y + h);
  766. }
  767. // now some filled rectangles
  768. dc.SetBrush(wxBrush(m_owner->m_colourForeground));
  769. for ( n = 0; n < WXSIZEOF(rasterOperations); n++ )
  770. {
  771. wxCoord x = 20 + 150*(n%4),
  772. y = 500 + 100*(n/4);
  773. dc.DrawText(rasterOperations[n].name, x, y - 20);
  774. dc.SetLogicalFunction(rasterOperations[n].rop);
  775. dc.DrawRectangle(x, y, w, h);
  776. }
  777. }
  778. #if wxUSE_GRAPHICS_CONTEXT
  779. #ifdef __WXGTK20__
  780. void MyCanvas::DrawAlpha(wxDC& WXUNUSED(dummyDC))
  781. #else
  782. void MyCanvas::DrawAlpha(wxDC& dc)
  783. #endif
  784. {
  785. #ifdef __WXGTK__
  786. wxGCDC dc( this );
  787. PrepareDC( dc );
  788. #endif
  789. wxDouble margin = 20 ;
  790. wxDouble width = 180 ;
  791. wxDouble radius = 30 ;
  792. dc.SetPen( wxPen( wxColour( 128, 0, 0 ), 12 ));
  793. dc.SetBrush(*wxRED_BRUSH);
  794. wxRect r(margin,margin+width*0.66,width,width) ;
  795. dc.DrawRoundedRectangle( r.x, r.y, r.width, r.width, radius ) ;
  796. dc.SetPen( wxPen( wxColour( 0, 0, 128 ), 12));
  797. dc.SetBrush(*wxBLUE_BRUSH);
  798. r.Offset( width * 0.8 , - width * 0.66 ) ;
  799. dc.DrawRoundedRectangle( r.x, r.y, r.width, r.width, radius ) ;
  800. dc.SetPen( wxPen( wxColour( 128, 128, 0 ), 12));
  801. dc.SetBrush( wxBrush( wxColour( 192, 192, 0)));
  802. r.Offset( width * 0.8 , width *0.5 ) ;
  803. dc.DrawRoundedRectangle( r.x, r.y, r.width, r.width, radius ) ;
  804. dc.SetPen( *wxTRANSPARENT_PEN ) ;
  805. dc.SetBrush( wxBrush( wxColour(255,255,128,128) ) );
  806. dc.DrawRoundedRectangle( 0 , margin + width / 2 , width * 3 , 100 , radius) ;
  807. dc.SetTextForeground( wxColour(255,255,0,128) );
  808. dc.SetFont( wxFont( 40, wxFONTFAMILY_SWISS, wxFONTSTYLE_ITALIC, wxFONTWEIGHT_NORMAL ) );
  809. dc.DrawText( wxT("Hello!"), 120, 80 );
  810. }
  811. #endif
  812. #if wxUSE_GRAPHICS_CONTEXT
  813. const int BASE = 80.0;
  814. const int BASE2 = BASE/2;
  815. const int BASE4 = BASE/4;
  816. static inline double DegToRad(double deg) { return (deg * M_PI) / 180.0; }
  817. // modeled along Robin Dunn's GraphicsContext.py sample
  818. void MyCanvas::DrawGraphics(wxGraphicsContext* gc)
  819. {
  820. wxFont font = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);
  821. gc->SetFont(font,*wxBLACK);
  822. // make a path that contains a circle and some lines, centered at 0,0
  823. wxGraphicsPath path = gc->CreatePath() ;
  824. path.AddCircle( 0, 0, BASE2 );
  825. path.MoveToPoint(0, -BASE2);
  826. path.AddLineToPoint(0, BASE2);
  827. path.MoveToPoint(-BASE2, 0);
  828. path.AddLineToPoint(BASE2, 0);
  829. path.CloseSubpath();
  830. path.AddRectangle(-BASE4, -BASE4/2, BASE2, BASE4);
  831. // Now use that path to demonstrate various capbilites of the grpahics context
  832. gc->PushState(); // save current translation/scale/other state
  833. gc->Translate(60, 75); // reposition the context origin
  834. gc->SetPen(wxPen("navy"));
  835. gc->SetBrush(wxBrush("pink"));
  836. for( int i = 0 ; i < 3 ; ++i )
  837. {
  838. wxString label;
  839. switch( i )
  840. {
  841. case 0 :
  842. label = "StrokePath";
  843. break;
  844. case 1 :
  845. label = "FillPath";
  846. break;
  847. case 2 :
  848. label = "DrawPath";
  849. break;
  850. }
  851. wxDouble w, h;
  852. gc->GetTextExtent(label, &w, &h, NULL, NULL);
  853. gc->DrawText(label, -w/2, -BASE2-h-4);
  854. switch( i )
  855. {
  856. case 0 :
  857. gc->StrokePath(path);
  858. break;
  859. case 1 :
  860. gc->FillPath(path);
  861. break;
  862. case 2 :
  863. gc->DrawPath(path);
  864. break;
  865. }
  866. gc->Translate(2*BASE, 0);
  867. }
  868. gc->PopState(); // restore saved state
  869. gc->PushState(); // save it again
  870. gc->Translate(60, 200); // offset to the lower part of the window
  871. gc->DrawText("Scale", 0, -BASE2);
  872. gc->Translate(0, 20);
  873. gc->SetBrush(wxBrush(wxColour(178, 34, 34, 128)));// 128 == half transparent
  874. for( int i = 0 ; i < 8 ; ++i )
  875. {
  876. gc->Scale(1.08, 1.08); // increase scale by 8%
  877. gc->Translate(5,5);
  878. gc->DrawPath(path);
  879. }
  880. gc->PopState(); // restore saved state
  881. gc->PushState(); // save it again
  882. gc->Translate(400, 200);
  883. gc->DrawText("Rotate", 0, -BASE2);
  884. // Move the origin over to the next location
  885. gc->Translate(0, 75);
  886. // draw our path again, rotating it about the central point,
  887. // and changing colors as we go
  888. for ( int angle = 0 ; angle < 360 ; angle += 30 )
  889. {
  890. gc->PushState(); // save this new current state so we can
  891. // pop back to it at the end of the loop
  892. wxImage::RGBValue val = wxImage::HSVtoRGB(wxImage::HSVValue(float(angle)/360, 1, 1));
  893. gc->SetBrush(wxBrush(wxColour(val.red, val.green, val.blue, 64)));
  894. gc->SetPen(wxPen(wxColour(val.red, val.green, val.blue, 128)));
  895. // use translate to artfully reposition each drawn path
  896. gc->Translate(1.5 * BASE2 * cos(DegToRad(angle)),
  897. 1.5 * BASE2 * sin(DegToRad(angle)));
  898. // use Rotate to rotate the path
  899. gc->Rotate(DegToRad(angle));
  900. // now draw it
  901. gc->DrawPath(path);
  902. gc->PopState();
  903. }
  904. gc->PopState();
  905. gc->PushState();
  906. gc->Translate(60, 400);
  907. gc->DrawText("Scaled smiley inside a square", 0, 0);
  908. gc->DrawRectangle(BASE2, BASE2, 100, 100);
  909. gc->DrawBitmap(m_smile_bmp, BASE2, BASE2, 100, 100);
  910. gc->PopState();
  911. }
  912. #endif // wxUSE_GRAPHICS_CONTEXT
  913. void MyCanvas::DrawCircles(wxDC& dc)
  914. {
  915. int x = 100,
  916. y = 100,
  917. r = 20;
  918. dc.SetPen( *wxRED_PEN );
  919. dc.SetBrush( *wxGREEN_BRUSH );
  920. dc.DrawText(wxT("Some circles"), 0, y);
  921. dc.DrawCircle(x, y, r);
  922. dc.DrawCircle(x + 2*r, y, r);
  923. dc.DrawCircle(x + 4*r, y, r);
  924. y += 2*r;
  925. dc.DrawText(wxT("And ellipses"), 0, y);
  926. dc.DrawEllipse(x - r, y, 2*r, r);
  927. dc.DrawEllipse(x + r, y, 2*r, r);
  928. dc.DrawEllipse(x + 3*r, y, 2*r, r);
  929. y += 2*r;
  930. dc.DrawText(wxT("And arcs"), 0, y);
  931. dc.DrawArc(x - r, y, x + r, y, x, y);
  932. dc.DrawArc(x + 4*r, y, x + 2*r, y, x + 3*r, y);
  933. dc.DrawArc(x + 5*r, y, x + 5*r, y, x + 6*r, y);
  934. y += 2*r;
  935. dc.DrawEllipticArc(x - r, y, 2*r, r, 0, 90);
  936. dc.DrawEllipticArc(x + r, y, 2*r, r, 90, 180);
  937. dc.DrawEllipticArc(x + 3*r, y, 2*r, r, 180, 270);
  938. dc.DrawEllipticArc(x + 5*r, y, 2*r, r, 270, 360);
  939. // same as above, just transparent brush
  940. dc.SetPen( *wxRED_PEN );
  941. dc.SetBrush( *wxTRANSPARENT_BRUSH );
  942. y += 2*r;
  943. dc.DrawText(wxT("Some circles"), 0, y);
  944. dc.DrawCircle(x, y, r);
  945. dc.DrawCircle(x + 2*r, y, r);
  946. dc.DrawCircle(x + 4*r, y, r);
  947. y += 2*r;
  948. dc.DrawText(wxT("And ellipses"), 0, y);
  949. dc.DrawEllipse(x - r, y, 2*r, r);
  950. dc.DrawEllipse(x + r, y, 2*r, r);
  951. dc.DrawEllipse(x + 3*r, y, 2*r, r);
  952. y += 2*r;
  953. dc.DrawText(wxT("And arcs"), 0, y);
  954. dc.DrawArc(x - r, y, x + r, y, x, y);
  955. dc.DrawArc(x + 4*r, y, x + 2*r, y, x + 3*r, y);
  956. dc.DrawArc(x + 5*r, y, x + 5*r, y, x + 6*r, y);
  957. y += 2*r;
  958. dc.DrawEllipticArc(x - r, y, 2*r, r, 0, 90);
  959. dc.DrawEllipticArc(x + r, y, 2*r, r, 90, 180);
  960. dc.DrawEllipticArc(x + 3*r, y, 2*r, r, 180, 270);
  961. dc.DrawEllipticArc(x + 5*r, y, 2*r, r, 270, 360);
  962. }
  963. void MyCanvas::DrawSplines(wxDC& dc)
  964. {
  965. #if wxUSE_SPLINES
  966. dc.DrawText(wxT("Some splines"), 10, 5);
  967. // values are hardcoded rather than randomly generated
  968. // so the output can be compared between native
  969. // implementations on platforms with different random
  970. // generators
  971. const int R = 300;
  972. const wxPoint center( R + 20, R + 20 );
  973. const int angles[7] = { 0, 10, 33, 77, 13, 145, 90 };
  974. const int radii[5] = { 100 , 59, 85, 33, 90 };
  975. const int n = 200;
  976. wxPoint pts[n];
  977. // background spline calculation
  978. unsigned int radius_pos = 0;
  979. unsigned int angle_pos = 0;
  980. int angle = 0;
  981. for ( int i = 0; i < n; i++ )
  982. {
  983. angle += angles[ angle_pos ];
  984. int r = R * radii[ radius_pos ] / 100;
  985. pts[ i ].x = center.x + (wxCoord)( r * cos( M_PI * angle / 180.0) );
  986. pts[ i ].y = center.y + (wxCoord)( r * sin( M_PI * angle / 180.0) );
  987. angle_pos++;
  988. if ( angle_pos >= WXSIZEOF(angles) ) angle_pos = 0;
  989. radius_pos++;
  990. if ( radius_pos >= WXSIZEOF(radii) ) radius_pos = 0;
  991. }
  992. // background spline drawing
  993. dc.SetPen(*wxRED_PEN);
  994. dc.DrawSpline(WXSIZEOF(pts), pts);
  995. // less detailed spline calculation
  996. wxPoint letters[4][5];
  997. // w
  998. letters[0][0] = wxPoint( 0,1); // O O
  999. letters[0][1] = wxPoint( 1,3); // * *
  1000. letters[0][2] = wxPoint( 2,2); // * O *
  1001. letters[0][3] = wxPoint( 3,3); // * * * *
  1002. letters[0][4] = wxPoint( 4,1); // O O
  1003. // x1
  1004. letters[1][0] = wxPoint( 5,1); // O*O
  1005. letters[1][1] = wxPoint( 6,1); // *
  1006. letters[1][2] = wxPoint( 7,2); // O
  1007. letters[1][3] = wxPoint( 8,3); // *
  1008. letters[1][4] = wxPoint( 9,3); // O*O
  1009. // x2
  1010. letters[2][0] = wxPoint( 5,3); // O*O
  1011. letters[2][1] = wxPoint( 6,3); // *
  1012. letters[2][2] = wxPoint( 7,2); // O
  1013. letters[2][3] = wxPoint( 8,1); // *
  1014. letters[2][4] = wxPoint( 9,1); // O*O
  1015. // W
  1016. letters[3][0] = wxPoint(10,0); // O O
  1017. letters[3][1] = wxPoint(11,3); // * *
  1018. letters[3][2] = wxPoint(12,1); // * O *
  1019. letters[3][3] = wxPoint(13,3); // * * * *
  1020. letters[3][4] = wxPoint(14,0); // O O
  1021. const int dx = 2 * R / letters[3][4].x;
  1022. const int h[4] = { -R/2, 0, R/4, R/2 };
  1023. for ( int m = 0; m < 4; m++ )
  1024. {
  1025. for ( int n = 0; n < 5; n++ )
  1026. {
  1027. letters[m][n].x = center.x - R + letters[m][n].x * dx;
  1028. letters[m][n].y = center.y + h[ letters[m][n].y ];
  1029. }
  1030. dc.SetPen( wxPen( *wxBLUE, 1, wxDOT) );
  1031. dc.DrawLines(5, letters[m]);
  1032. dc.SetPen( wxPen( *wxBLACK, 4) );
  1033. dc.DrawSpline(5, letters[m]);
  1034. }
  1035. #else
  1036. dc.DrawText(wxT("Splines not supported."), 10, 5);
  1037. #endif
  1038. }
  1039. void MyCanvas::DrawGradients(wxDC& dc)
  1040. {
  1041. static const int TEXT_HEIGHT = 15;
  1042. // LHS: linear
  1043. wxRect r(10, 10, 50, 50);
  1044. dc.DrawText(wxT("wxRIGHT"), r.x, r.y);
  1045. r.Offset(0, TEXT_HEIGHT);
  1046. dc.GradientFillLinear(r, *wxWHITE, *wxBLUE, wxRIGHT);
  1047. r.Offset(0, r.height + 10);
  1048. dc.DrawText(wxT("wxLEFT"), r.x, r.y);
  1049. r.Offset(0, TEXT_HEIGHT);
  1050. dc.GradientFillLinear(r, *wxWHITE, *wxBLUE, wxLEFT);
  1051. r.Offset(0, r.height + 10);
  1052. dc.DrawText(wxT("wxDOWN"), r.x, r.y);
  1053. r.Offset(0, TEXT_HEIGHT);
  1054. dc.GradientFillLinear(r, *wxWHITE, *wxBLUE, wxDOWN);
  1055. r.Offset(0, r.height + 10);
  1056. dc.DrawText(wxT("wxUP"), r.x, r.y);
  1057. r.Offset(0, TEXT_HEIGHT);
  1058. dc.GradientFillLinear(r, *wxWHITE, *wxBLUE, wxUP);
  1059. wxRect gfr = wxRect(r);
  1060. // RHS: concentric
  1061. r = wxRect(200, 10, 50, 50);
  1062. dc.DrawText(wxT("Blue inside"), r.x, r.y);
  1063. r.Offset(0, TEXT_HEIGHT);
  1064. dc.GradientFillConcentric(r, *wxBLUE, *wxWHITE);
  1065. r.Offset(0, r.height + 10);
  1066. dc.DrawText(wxT("White inside"), r.x, r.y);
  1067. r.Offset(0, TEXT_HEIGHT);
  1068. dc.GradientFillConcentric(r, *wxWHITE, *wxBLUE);
  1069. r.Offset(0, r.height + 10);
  1070. dc.DrawText(wxT("Blue in top left corner"), r.x, r.y);
  1071. r.Offset(0, TEXT_HEIGHT);
  1072. dc.GradientFillConcentric(r, *wxBLUE, *wxWHITE, wxPoint(0, 0));
  1073. r.Offset(0, r.height + 10);
  1074. dc.DrawText(wxT("Blue in bottom right corner"), r.x, r.y);
  1075. r.Offset(0, TEXT_HEIGHT);
  1076. dc.GradientFillConcentric(r, *wxBLUE, *wxWHITE, wxPoint(r.width, r.height));
  1077. // check that the area filled by the gradient is exactly the interior of
  1078. // the rectangle
  1079. r.x = 350;
  1080. r.y = 30;
  1081. dc.DrawText("The interior should be filled but", r.x, r.y);
  1082. r.y += 15;
  1083. dc.DrawText(" the red border should remain visible:", r.x, r.y);
  1084. r.y += 15;
  1085. r.width =
  1086. r.height = 50;
  1087. wxRect r2 = r;
  1088. r2.x += 60;
  1089. wxRect r3 = r;
  1090. r3.y += 60;
  1091. wxRect r4 = r2;
  1092. r4.y += 60;
  1093. dc.SetPen(*wxRED_PEN);
  1094. dc.DrawRectangle(r);
  1095. r.Deflate(1);
  1096. dc.GradientFillLinear(r, *wxGREEN, *wxBLACK, wxNORTH);
  1097. dc.DrawRectangle(r2);
  1098. r2.Deflate(1);
  1099. dc.GradientFillLinear(r2, *wxBLACK, *wxGREEN, wxSOUTH);
  1100. dc.DrawRectangle(r3);
  1101. r3.Deflate(1);
  1102. dc.GradientFillLinear(r3, *wxGREEN, *wxBLACK, wxEAST);
  1103. dc.DrawRectangle(r4);
  1104. r4.Deflate(1);
  1105. dc.GradientFillLinear(r4, *wxBLACK, *wxGREEN, wxWEST);
  1106. #if wxUSE_GRAPHICS_CONTEXT
  1107. if (m_useContext)
  1108. {
  1109. wxGCDC &gdc = (wxGCDC&)dc;
  1110. wxGraphicsContext *gc = gdc.GetGraphicsContext();
  1111. wxGraphicsPath pth;
  1112. wxGraphicsGradientStops stops;
  1113. gfr.Offset(0, gfr.height + 10);
  1114. dc.DrawText(wxT("Linear Gradient with Stops"), gfr.x, gfr.y);
  1115. gfr.Offset(0, TEXT_HEIGHT);
  1116. stops = wxGraphicsGradientStops(*wxRED, *wxBLUE);
  1117. stops.Add(wxColour(255,255,0), 0.33f);
  1118. stops.Add(*wxGREEN, 0.67f);
  1119. gc->SetBrush(gc->CreateLinearGradientBrush(gfr.x, gfr.y,
  1120. gfr.x + gfr.width, gfr.y + gfr.height,
  1121. stops));
  1122. pth = gc->CreatePath();
  1123. pth.MoveToPoint(gfr.x,gfr.y);
  1124. pth.AddLineToPoint(gfr.x + gfr.width,gfr.y);
  1125. pth.AddLineToPoint(gfr.x + gfr.width,gfr.y+gfr.height);
  1126. pth.AddLineToPoint(gfr.x,gfr.y+gfr.height);
  1127. pth.CloseSubpath();
  1128. gc->FillPath(pth);
  1129. gfr.Offset(0, gfr.height + 10);
  1130. dc.DrawText(wxT("Radial Gradient with Stops"), gfr.x, gfr.y);
  1131. gfr.Offset(0, TEXT_HEIGHT);
  1132. gc->SetBrush(gc->CreateRadialGradientBrush(gfr.x + gfr.width / 2,
  1133. gfr.y + gfr.height / 2,
  1134. gfr.x + gfr.width / 2,
  1135. gfr.y + gfr.height / 2,
  1136. gfr.width / 2,
  1137. stops));
  1138. pth = gc->CreatePath();
  1139. pth.MoveToPoint(gfr.x,gfr.y);
  1140. pth.AddLineToPoint(gfr.x + gfr.width,gfr.y);
  1141. pth.AddLineToPoint(gfr.x + gfr.width,gfr.y+gfr.height);
  1142. pth.AddLineToPoint(gfr.x,gfr.y+gfr.height);
  1143. pth.CloseSubpath();
  1144. gc->FillPath(pth);
  1145. gfr.Offset(0, gfr.height + 10);
  1146. dc.DrawText(wxT("Linear Gradient with Stops and Gaps"), gfr.x, gfr.y);
  1147. gfr.Offset(0, TEXT_HEIGHT);
  1148. stops = wxGraphicsGradientStops(*wxRED, *wxBLUE);
  1149. stops.Add(wxColour(255,255,0), 0.33f);
  1150. stops.Add(wxTransparentColour, 0.33f);
  1151. stops.Add(wxTransparentColour, 0.67f);
  1152. stops.Add(*wxGREEN, 0.67f);
  1153. gc->SetBrush(gc->CreateLinearGradientBrush(gfr.x, gfr.y + gfr.height,
  1154. gfr.x + gfr.width, gfr.y,
  1155. stops));
  1156. pth = gc->CreatePath();
  1157. pth.MoveToPoint(gfr.x,gfr.y);
  1158. pth.AddLineToPoint(gfr.x + gfr.width,gfr.y);
  1159. pth.AddLineToPoint(gfr.x + gfr.width,gfr.y+gfr.height);
  1160. pth.AddLineToPoint(gfr.x,gfr.y+gfr.height);
  1161. pth.CloseSubpath();
  1162. gc->FillPath(pth);
  1163. gfr.Offset(0, gfr.height + 10);
  1164. dc.DrawText(wxT("Radial Gradient with Stops and Gaps"), gfr.x, gfr.y);
  1165. gfr.Offset(0, TEXT_HEIGHT);
  1166. gc->SetBrush(gc->CreateRadialGradientBrush(gfr.x + gfr.width / 2,
  1167. gfr.y + gfr.height / 2,
  1168. gfr.x + gfr.width / 2,
  1169. gfr.y + gfr.height / 2,
  1170. gfr.width / 2,
  1171. stops));
  1172. pth = gc->CreatePath();
  1173. pth.MoveToPoint(gfr.x,gfr.y);
  1174. pth.AddLineToPoint(gfr.x + gfr.width,gfr.y);
  1175. pth.AddLineToPoint(gfr.x + gfr.width,gfr.y+gfr.height);
  1176. pth.AddLineToPoint(gfr.x,gfr.y+gfr.height);
  1177. pth.CloseSubpath();
  1178. gc->FillPath(pth);
  1179. gfr.Offset(0, gfr.height + 10);
  1180. dc.DrawText(wxT("Gradients with Stops and Transparency"), gfr.x, gfr.y);
  1181. gfr.Offset(0, TEXT_HEIGHT);
  1182. stops = wxGraphicsGradientStops(*wxRED, wxTransparentColour);
  1183. stops.Add(*wxRED, 0.33f);
  1184. stops.Add(wxTransparentColour, 0.33f);
  1185. stops.Add(wxTransparentColour, 0.67f);
  1186. stops.Add(*wxBLUE, 0.67f);
  1187. stops.Add(*wxBLUE, 1.0f);
  1188. pth = gc->CreatePath();
  1189. pth.MoveToPoint(gfr.x,gfr.y);
  1190. pth.AddLineToPoint(gfr.x + gfr.width,gfr.y);
  1191. pth.AddLineToPoint(gfr.x + gfr.width,gfr.y+gfr.height);
  1192. pth.AddLineToPoint(gfr.x,gfr.y+gfr.height);
  1193. pth.CloseSubpath();
  1194. gc->SetBrush(gc->CreateRadialGradientBrush(gfr.x + gfr.width / 2,
  1195. gfr.y + gfr.height / 2,
  1196. gfr.x + gfr.width / 2,
  1197. gfr.y + gfr.height / 2,
  1198. gfr.width / 2,
  1199. stops));
  1200. gc->FillPath(pth);
  1201. stops = wxGraphicsGradientStops(wxColour(255,0,0, 128), wxColour(0,0,255, 128));
  1202. stops.Add(wxColour(255,255,0,128), 0.33f);
  1203. stops.Add(wxColour(0,255,0,128), 0.67f);
  1204. gc->SetBrush(gc->CreateLinearGradientBrush(gfr.x, gfr.y,
  1205. gfr.x + gfr.width, gfr.y,
  1206. stops));
  1207. gc->FillPath(pth);
  1208. }
  1209. #endif // wxUSE_GRAPHICS_CONTEXT
  1210. }
  1211. void MyCanvas::DrawRegions(wxDC& dc)
  1212. {
  1213. dc.DrawText(wxT("You should see a red rect partly covered by a cyan one ")
  1214. wxT("on the left"), 10, 5);
  1215. dc.DrawText(wxT("and 5 smileys from which 4 are partially clipped on the right"),
  1216. 10, 5 + dc.GetCharHeight());
  1217. dc.DrawText(wxT("The second copy should be identical but right part of it ")
  1218. wxT("should be offset by 10 pixels."),
  1219. 10, 5 + 2*dc.GetCharHeight());
  1220. DrawRegionsHelper(dc, 10, true);
  1221. DrawRegionsHelper(dc, 350, false);
  1222. }
  1223. void MyCanvas::DrawRegionsHelper(wxDC& dc, wxCoord x, bool firstTime)
  1224. {
  1225. wxCoord y = 100;
  1226. dc.DestroyClippingRegion();
  1227. dc.SetBrush( *wxWHITE_BRUSH );
  1228. dc.SetPen( *wxTRANSPARENT_PEN );
  1229. dc.DrawRectangle( x, y, 310, 310 );
  1230. dc.SetClippingRegion( x + 10, y + 10, 100, 270 );
  1231. dc.SetBrush( *wxRED_BRUSH );
  1232. dc.DrawRectangle( x, y, 310, 310 );
  1233. dc.SetClippingRegion( x + 10, y + 10, 100, 100 );
  1234. dc.SetBrush( *wxCYAN_BRUSH );
  1235. dc.DrawRectangle( x, y, 310, 310 );
  1236. dc.DestroyClippingRegion();
  1237. wxRegion region(x + 110, y + 20, 100, 270);
  1238. #if !defined(__WXMOTIF__)
  1239. if ( !firstTime )
  1240. region.Offset(10, 10);
  1241. #endif
  1242. dc.SetDeviceClippingRegion(region);
  1243. dc.SetBrush( *wxGREY_BRUSH );
  1244. dc.DrawRectangle( x, y, 310, 310 );
  1245. if (m_smile_bmp.IsOk())
  1246. {
  1247. dc.DrawBitmap( m_smile_bmp, x + 150, y + 150, true );
  1248. dc.DrawBitmap( m_smile_bmp, x + 130, y + 10, true );
  1249. dc.DrawBitmap( m_smile_bmp, x + 130, y + 280, true );
  1250. dc.DrawBitmap( m_smile_bmp, x + 100, y + 70, true );
  1251. dc.DrawBitmap( m_smile_bmp, x + 200, y + 70, true );
  1252. }
  1253. }
  1254. void MyCanvas::OnPaint(wxPaintEvent &WXUNUSED(event))
  1255. {
  1256. if ( m_useBuffer )
  1257. {
  1258. wxBufferedPaintDC bpdc(this);
  1259. Draw(bpdc);
  1260. }
  1261. else
  1262. {
  1263. wxPaintDC pdc(this);
  1264. Draw(pdc);
  1265. }
  1266. }
  1267. void MyCanvas::Draw(wxDC& pdc)
  1268. {
  1269. #if wxUSE_GRAPHICS_CONTEXT
  1270. wxGCDC gdc;
  1271. wxGraphicsRenderer* const renderer = wxGraphicsRenderer::
  1272. #if TEST_CAIRO_EVERYWHERE
  1273. GetCairoRenderer()
  1274. #else
  1275. GetDefaultRenderer()
  1276. #endif
  1277. ;
  1278. wxGraphicsContext* context;
  1279. if ( wxPaintDC *paintdc = wxDynamicCast(&pdc, wxPaintDC) )
  1280. {
  1281. context = renderer->CreateContext(*paintdc);
  1282. }
  1283. else if ( wxMemoryDC *memdc = wxDynamicCast(&pdc, wxMemoryDC) )
  1284. {
  1285. context = renderer->CreateContext(*memdc);
  1286. }
  1287. #if wxUSE_METAFILE && defined(wxMETAFILE_IS_ENH)
  1288. else if ( wxMetafileDC *metadc = wxDynamicCast(&pdc, wxMetafileDC) )
  1289. {
  1290. context = renderer->CreateContext(*metadc);
  1291. }
  1292. #endif
  1293. else
  1294. {
  1295. wxFAIL_MSG( "Unknown wxDC kind" );
  1296. return;
  1297. }
  1298. gdc.SetGraphicsContext(context);
  1299. wxDC &dc = m_useContext ? (wxDC&) gdc : (wxDC&) pdc ;
  1300. #else
  1301. wxDC &dc = pdc ;
  1302. #endif
  1303. PrepareDC(dc);
  1304. m_owner->PrepareDC(dc);
  1305. dc.SetBackgroundMode( m_owner->m_backgroundMode );
  1306. if ( m_owner->m_backgroundBrush.IsOk() )
  1307. dc.SetBackground( m_owner->m_backgroundBrush );
  1308. if ( m_owner->m_colourForeground.IsOk() )
  1309. dc.SetTextForeground( m_owner->m_colourForeground );
  1310. if ( m_owner->m_colourBackground.IsOk() )
  1311. dc.SetTextBackground( m_owner->m_colourBackground );
  1312. if ( m_owner->m_textureBackground) {
  1313. if ( ! m_owner->m_backgroundBrush.IsOk() ) {
  1314. dc.SetBackground(wxBrush(wxColour(0, 128, 0)));
  1315. }
  1316. }
  1317. if ( m_clip )
  1318. dc.SetClippingRegion(100, 100, 100, 100);
  1319. dc.Clear();
  1320. if ( m_owner->m_textureBackground )
  1321. {
  1322. dc.SetPen(*wxMEDIUM_GREY_PEN);
  1323. for ( int i = 0; i < 200; i++ )
  1324. dc.DrawLine(0, i*10, i*10, 0);
  1325. }
  1326. switch ( m_show )
  1327. {
  1328. case File_ShowDefault:
  1329. DrawDefault(dc);
  1330. break;
  1331. case File_ShowCircles:
  1332. DrawCircles(dc);
  1333. break;
  1334. case File_ShowSplines:
  1335. DrawSplines(dc);
  1336. break;
  1337. case File_ShowRegions:
  1338. DrawRegions(dc);
  1339. break;
  1340. case File_ShowText:
  1341. DrawText(dc);
  1342. break;
  1343. case File_ShowLines:
  1344. DrawTestLines( 0, 100, 0, dc );
  1345. DrawTestLines( 0, 320, 1, dc );
  1346. DrawTestLines( 0, 540, 2, dc );
  1347. DrawTestLines( 0, 760, 6, dc );
  1348. break;
  1349. case File_ShowBrushes:
  1350. DrawTestBrushes(dc);
  1351. break;
  1352. case File_ShowPolygons:
  1353. DrawTestPoly(dc);
  1354. break;
  1355. case File_ShowMask:
  1356. DrawImages(dc, Draw_Normal);
  1357. break;
  1358. case File_ShowMaskStretch:
  1359. DrawImages(dc, Draw_Stretch);
  1360. break;
  1361. case File_ShowOps:
  1362. DrawWithLogicalOps(dc);
  1363. break;
  1364. #if wxUSE_GRAPHICS_CONTEXT
  1365. case File_ShowAlpha:
  1366. DrawAlpha(dc);
  1367. break;
  1368. case File_ShowGraphics:
  1369. DrawGraphics(gdc.GetGraphicsContext());
  1370. break;
  1371. #endif
  1372. case File_ShowGradients:
  1373. DrawGradients(dc);
  1374. break;
  1375. default:
  1376. break;
  1377. }
  1378. }
  1379. void MyCanvas::OnMouseMove(wxMouseEvent &event)
  1380. {
  1381. #if wxUSE_STATUSBAR
  1382. {
  1383. wxClientDC dc(this);
  1384. PrepareDC(dc);
  1385. m_owner->PrepareDC(dc);
  1386. wxPoint pos = event.GetPosition();
  1387. long x = dc.DeviceToLogicalX( pos.x );
  1388. long y = dc.DeviceToLogicalY( pos.y );
  1389. wxString str;
  1390. str.Printf( wxT("Current mouse position: %d,%d"), (int)x, (int)y );
  1391. m_owner->SetStatusText( str );
  1392. }
  1393. if ( m_rubberBand )
  1394. {
  1395. int x,y, xx, yy ;
  1396. event.GetPosition(&x,&y);
  1397. CalcUnscrolledPosition( x, y, &xx, &yy );
  1398. m_currentpoint = wxPoint( xx , yy ) ;
  1399. wxRect newrect ( m_anchorpoint , m_currentpoint ) ;
  1400. wxClientDC dc( this ) ;
  1401. PrepareDC( dc ) ;
  1402. wxDCOverlay overlaydc( m_overlay, &dc );
  1403. overlaydc.Clear();
  1404. #ifdef __WXMAC__
  1405. dc.SetPen( *wxGREY_PEN );
  1406. dc.SetBrush( wxColour( 192,192,192,64 ) );
  1407. #else
  1408. dc.SetPen( wxPen( *wxLIGHT_GREY, 2 ) );
  1409. dc.SetBrush( *wxTRANSPARENT_BRUSH );
  1410. #endif
  1411. dc.DrawRectangle( newrect );
  1412. }
  1413. #else
  1414. wxUnusedVar(event);
  1415. #endif // wxUSE_STATUSBAR
  1416. }
  1417. void MyCanvas::OnMouseDown(wxMouseEvent &event)
  1418. {
  1419. int x,y,xx,yy ;
  1420. event.GetPosition(&x,&y);
  1421. CalcUnscrolledPosition( x, y, &xx, &yy );
  1422. m_anchorpoint = wxPoint( xx , yy ) ;
  1423. m_currentpoint = m_anchorpoint ;
  1424. m_rubberBand = true ;
  1425. CaptureMouse() ;
  1426. }
  1427. void MyCanvas::OnMouseUp(wxMouseEvent &event)
  1428. {
  1429. if ( m_rubberBand )
  1430. {
  1431. ReleaseMouse();
  1432. {
  1433. wxClientDC dc( this );
  1434. PrepareDC( dc );
  1435. wxDCOverlay overlaydc( m_overlay, &dc );
  1436. overlaydc.Clear();
  1437. }
  1438. m_overlay.Reset();
  1439. m_rubberBand = false;
  1440. wxPoint endpoint = CalcUnscrolledPosition(event.GetPosition());
  1441. // Don't pop up the message box if nothing was actually selected.
  1442. if ( endpoint != m_anchorpoint )
  1443. {
  1444. wxLogMessage("Selected rectangle from (%d, %d) to (%d, %d)",
  1445. m_anchorpoint.x, m_anchorpoint.y,
  1446. endpoint.x, endpoint.y);
  1447. }
  1448. }
  1449. }
  1450. // ----------------------------------------------------------------------------
  1451. // MyFrame
  1452. // ----------------------------------------------------------------------------
  1453. // the event tables connect the wxWidgets events with the functions (event
  1454. // handlers) which process them. It can be also done at run-time, but for the
  1455. // simple menu events like this the static method is much simpler.
  1456. wxBEGIN_EVENT_TABLE(MyFrame, wxFrame)
  1457. EVT_MENU (File_Quit, MyFrame::OnQuit)
  1458. EVT_MENU (File_About, MyFrame::OnAbout)
  1459. EVT_MENU (File_Clip, MyFrame::OnClip)
  1460. #if wxUSE_GRAPHICS_CONTEXT
  1461. EVT_MENU (File_GraphicContext, MyFrame::OnGraphicContext)
  1462. #endif
  1463. EVT_MENU (File_Buffer, MyFrame::OnBuffer)
  1464. EVT_MENU (File_Copy, MyFrame::OnCopy)
  1465. EVT_MENU (File_Save, MyFrame::OnSave)
  1466. EVT_MENU_RANGE(MenuShow_First, MenuShow_Last, MyFrame::OnShow)
  1467. EVT_MENU_RANGE(MenuOption_First, MenuOption_Last, MyFrame::OnOption)
  1468. wxEND_EVENT_TABLE()
  1469. // frame constructor
  1470. MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size)
  1471. : wxFrame((wxFrame *)NULL, wxID_ANY, title, pos, size,
  1472. wxDEFAULT_FRAME_STYLE | wxNO_FULL_REPAINT_ON_RESIZE)
  1473. {
  1474. // set the frame icon
  1475. SetIcon(wxICON(sample));
  1476. wxMenu *menuFile = new wxMenu;
  1477. menuFile->Append(File_ShowDefault, wxT("&Default screen\tF1"));
  1478. menuFile->Append(File_ShowText, wxT("&Text screen\tF2"));
  1479. menuFile->Append(File_ShowLines, wxT("&Lines screen\tF3"));
  1480. menuFile->Append(File_ShowBrushes, wxT("&Brushes screen\tF4"));
  1481. menuFile->Append(File_ShowPolygons, wxT("&Polygons screen\tF5"));
  1482. menuFile->Append(File_ShowMask, wxT("&Mask screen\tF6"));
  1483. menuFile->Append(File_ShowMaskStretch, wxT("1/&2 scaled mask\tShift-F6"));
  1484. menuFile->Append(File_ShowOps, wxT("&Raster operations screen\tF7"));
  1485. menuFile->Append(File_ShowRegions, wxT("Re&gions screen\tF8"));
  1486. menuFile->Append(File_ShowCircles, wxT("&Circles screen\tF9"));
  1487. #if wxUSE_GRAPHICS_CONTEXT
  1488. menuFile->Append(File_ShowAlpha, wxT("&Alpha screen\tF10"));
  1489. #endif
  1490. menuFile->Append(File_ShowSplines, wxT("Spl&ines screen\tF11"));
  1491. menuFile->Append(File_ShowGradients, wxT("&Gradients screen\tF12"));
  1492. #if wxUSE_GRAPHICS_CONTEXT
  1493. menuFile->Append(File_ShowGraphics, wxT("&Graphics screen"));
  1494. #endif
  1495. menuFile->AppendSeparator();
  1496. menuFile->AppendCheckItem(File_Clip, wxT("&Clip\tCtrl-C"), wxT("Clip/unclip drawing"));
  1497. #if wxUSE_GRAPHICS_CONTEXT
  1498. menuFile->AppendCheckItem(File_GraphicContext, wxT("&Use GraphicContext\tCtrl-Y"), wxT("Use GraphicContext"));
  1499. #endif
  1500. menuFile->AppendCheckItem(File_Buffer, wxT("&Use wx&BufferedPaintDC\tCtrl-Z"), wxT("Buffer painting"));
  1501. menuFile->AppendSeparator();
  1502. #if wxUSE_METAFILE && defined(wxMETAFILE_IS_ENH)
  1503. menuFile->Append(File_Copy, wxT("Copy to clipboard"));
  1504. #endif
  1505. menuFile->Append(File_Save, wxT("&Save...\tCtrl-S"), wxT("Save drawing to file"));
  1506. menuFile->AppendSeparator();
  1507. menuFile->Append(File_About, wxT("&About\tCtrl-A"), wxT("Show about dialog"));
  1508. menuFile->AppendSeparator();
  1509. menuFile->Append(File_Quit, wxT("E&xit\tAlt-X"), wxT("Quit this program"));
  1510. wxMenu *menuMapMode = new wxMenu;
  1511. menuMapMode->Append( MapMode_Text, wxT("&TEXT map mode") );
  1512. menuMapMode->Append( MapMode_Lometric, wxT("&LOMETRIC map mode") );
  1513. menuMapMode->Append( MapMode_Twips, wxT("T&WIPS map mode") );
  1514. menuMapMode->Append( MapMode_Points, wxT("&POINTS map mode") );
  1515. menuMapMode->Append( MapMode_Metric, wxT("&METRIC map mode") );
  1516. wxMenu *menuUserScale = new wxMenu;
  1517. menuUserScale->Append( UserScale_StretchHoriz, wxT("Stretch &horizontally\tCtrl-H") );
  1518. menuUserScale->Append( UserScale_ShrinkHoriz, wxT("Shrin&k horizontally\tCtrl-G") );
  1519. menuUserScale->Append( UserScale_StretchVertic, wxT("Stretch &vertically\tCtrl-V") );
  1520. menuUserScale->Append( UserScale_ShrinkVertic, wxT("&Shrink vertically\tCtrl-W") );
  1521. menuUserScale->AppendSeparator();
  1522. menuUserScale->Append( UserScale_Restore, wxT("&Restore to normal\tCtrl-0") );
  1523. wxMenu *menuAxis = new wxMenu;
  1524. menuAxis->AppendCheckItem( AxisMirror_Horiz, wxT("Mirror horizontally\tCtrl-M") );
  1525. menuAxis->AppendCheckItem( AxisMirror_Vertic, wxT("Mirror vertically\tCtrl-N") );
  1526. wxMenu *menuLogical = new wxMenu;
  1527. menuLogical->Append( LogicalOrigin_MoveDown, wxT("Move &down\tCtrl-D") );
  1528. menuLogical->Append( LogicalOrigin_MoveUp, wxT("Move &up\tCtrl-U") );
  1529. menuLogical->Append( LogicalOrigin_MoveLeft, wxT("Move &right\tCtrl-L") );
  1530. menuLogical->Append( LogicalOrigin_MoveRight, wxT("Move &left\tCtrl-R") );
  1531. menuLogical->AppendSeparator();
  1532. menuLogical->Append( LogicalOrigin_Set, wxT("Set to (&100, 100)\tShift-Ctrl-1") );
  1533. menuLogical->Append( LogicalOrigin_Restore, wxT("&Restore to normal\tShift-Ctrl-0") );
  1534. wxMenu *menuColour = new wxMenu;
  1535. #if wxUSE_COLOURDLG
  1536. menuColour->Append( Colour_TextForeground, wxT("Text &foreground...") );
  1537. menuColour->Append( Colour_TextBackground, wxT("Text &background...") );
  1538. menuColour->Append( Colour_Background, wxT("Background &colour...") );
  1539. #endif // wxUSE_COLOURDLG
  1540. menuColour->AppendCheckItem( Colour_BackgroundMode, wxT("&Opaque/transparent\tCtrl-B") );
  1541. menuColour->AppendCheckItem( Colour_TextureBackgound, wxT("Draw textured back&ground\tCtrl-T") );
  1542. // now append the freshly created menu to the menu bar...
  1543. wxMenuBar *menuBar = new wxMenuBar;
  1544. menuBar->Append(menuFile, wxT("&File"));
  1545. menuBar->Append(menuMapMode, wxT("&Mode"));
  1546. menuBar->Append(menuUserScale, wxT("&Scale"));
  1547. menuBar->Append(menuAxis, wxT("&Axis"));
  1548. menuBar->Append(menuLogical, wxT("&Origin"));
  1549. menuBar->Append(menuColour, wxT("&Colours"));
  1550. // ... and attach this menu bar to the frame
  1551. SetMenuBar(menuBar);
  1552. #if wxUSE_STATUSBAR
  1553. CreateStatusBar(2);
  1554. SetStatusText(wxT("Welcome to wxWidgets!"));
  1555. #endif // wxUSE_STATUSBAR
  1556. m_mapMode = wxMM_TEXT;
  1557. m_xUserScale = 1.0;
  1558. m_yUserScale = 1.0;
  1559. m_xLogicalOrigin = 0;
  1560. m_yLogicalOrigin = 0;
  1561. m_xAxisReversed =
  1562. m_yAxisReversed = false;
  1563. m_backgroundMode = wxSOLID;
  1564. m_colourForeground = *wxBLACK;
  1565. m_colourBackground = *wxLIGHT_GREY;
  1566. m_textureBackground = false;
  1567. m_canvas = new MyCanvas( this );
  1568. m_canvas->SetScrollbars( 10, 10, 100, 240 );
  1569. }
  1570. // event handlers
  1571. void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
  1572. {
  1573. // true is to force the frame to close
  1574. Close(true);
  1575. }
  1576. void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
  1577. {
  1578. wxString msg;
  1579. msg.Printf( wxT("This is the about dialog of the drawing sample.\n")
  1580. wxT("This sample tests various primitive drawing functions\n")
  1581. wxT("(without any attempts to prevent flicker).\n")
  1582. wxT("Copyright (c) Robert Roebling 1999")
  1583. );
  1584. wxMessageBox(msg, wxT("About Drawing"), wxOK | wxICON_INFORMATION, this);
  1585. }
  1586. void MyFrame::OnClip(wxCommandEvent& event)
  1587. {
  1588. m_canvas->Clip(event.IsChecked());
  1589. }
  1590. #if wxUSE_GRAPHICS_CONTEXT
  1591. void MyFrame::OnGraphicContext(wxCommandEvent& event)
  1592. {
  1593. m_canvas->UseGraphicContext(event.IsChecked());
  1594. }
  1595. #endif
  1596. void MyFrame::OnBuffer(wxCommandEvent& event)
  1597. {
  1598. m_canvas->UseBuffer(event.IsChecked());
  1599. }
  1600. void MyFrame::OnCopy(wxCommandEvent& WXUNUSED(event))
  1601. {
  1602. #if wxUSE_METAFILE && defined(wxMETAFILE_IS_ENH)
  1603. wxMetafileDC dc;
  1604. if (!dc.IsOk())
  1605. return;
  1606. m_canvas->Draw(dc);
  1607. wxMetafile *mf = dc.Close();
  1608. if (!mf)
  1609. return;
  1610. mf->SetClipboard();
  1611. delete mf;
  1612. #endif
  1613. }
  1614. void MyFrame::OnSave(wxCommandEvent& WXUNUSED(event))
  1615. {
  1616. wxFileDialog dlg(this, wxT("Save as bitmap"), wxT(""), wxT(""),
  1617. #if wxUSE_LIBPNG
  1618. wxT("PNG image (*.png)|*.png;*.PNG|")
  1619. #endif
  1620. wxT("Bitmap image (*.bmp)|*.bmp;*.BMP"),
  1621. wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
  1622. if (dlg.ShowModal() == wxID_OK)
  1623. {
  1624. wxBitmap bmp(500, 800);
  1625. wxMemoryDC mdc(bmp);
  1626. m_canvas->Draw(mdc);
  1627. bmp.ConvertToImage().SaveFile(dlg.GetPath());
  1628. }
  1629. }
  1630. void MyFrame::OnShow(wxCommandEvent& event)
  1631. {
  1632. m_canvas->ToShow(event.GetId());
  1633. }
  1634. void MyFrame::OnOption(wxCommandEvent& event)
  1635. {
  1636. switch (event.GetId())
  1637. {
  1638. case MapMode_Text:
  1639. m_mapMode = wxMM_TEXT;
  1640. break;
  1641. case MapMode_Lometric:
  1642. m_mapMode = wxMM_LOMETRIC;
  1643. break;
  1644. case MapMode_Twips:
  1645. m_mapMode = wxMM_TWIPS;
  1646. break;
  1647. case MapMode_Points:
  1648. m_mapMode = wxMM_POINTS;
  1649. break;
  1650. case MapMode_Metric:
  1651. m_mapMode = wxMM_METRIC;
  1652. break;
  1653. case LogicalOrigin_MoveDown:
  1654. m_yLogicalOrigin += 10;
  1655. break;
  1656. case LogicalOrigin_MoveUp:
  1657. m_yLogicalOrigin -= 10;
  1658. break;
  1659. case LogicalOrigin_MoveLeft:
  1660. m_xLogicalOrigin += 10;
  1661. break;
  1662. case LogicalOrigin_MoveRight:
  1663. m_xLogicalOrigin -= 10;
  1664. break;
  1665. case LogicalOrigin_Set:
  1666. m_xLogicalOrigin =
  1667. m_yLogicalOrigin = -100;
  1668. break;
  1669. case LogicalOrigin_Restore:
  1670. m_xLogicalOrigin =
  1671. m_yLogicalOrigin = 0;
  1672. break;
  1673. case UserScale_StretchHoriz:
  1674. m_xUserScale *= 1.10;
  1675. break;
  1676. case UserScale_ShrinkHoriz:
  1677. m_xUserScale /= 1.10;
  1678. break;
  1679. case UserScale_StretchVertic:
  1680. m_yUserScale *= 1.10;
  1681. break;
  1682. case UserScale_ShrinkVertic:
  1683. m_yUserScale /= 1.10;
  1684. break;
  1685. case UserScale_Restore:
  1686. m_xUserScale =
  1687. m_yUserScale = 1.0;
  1688. break;
  1689. case AxisMirror_Vertic:
  1690. m_yAxisReversed = !m_yAxisReversed;
  1691. break;
  1692. case AxisMirror_Horiz:
  1693. m_xAxisReversed = !m_xAxisReversed;
  1694. break;
  1695. #if wxUSE_COLOURDLG
  1696. case Colour_TextForeground:
  1697. m_colourForeground = SelectColour();
  1698. break;
  1699. case Colour_TextBackground:
  1700. m_colourBackground = SelectColour();
  1701. break;
  1702. case Colour_Background:
  1703. {
  1704. wxColour col = SelectColour();
  1705. if ( col.IsOk() )
  1706. {
  1707. m_backgroundBrush.SetColour(col);
  1708. }
  1709. }
  1710. break;
  1711. #endif // wxUSE_COLOURDLG
  1712. case Colour_BackgroundMode:
  1713. m_backgroundMode = m_backgroundMode == wxSOLID ? wxTRANSPARENT
  1714. : wxSOLID;
  1715. break;
  1716. case Colour_TextureBackgound:
  1717. m_textureBackground = ! m_textureBackground;
  1718. break;
  1719. default:
  1720. // skip Refresh()
  1721. return;
  1722. }
  1723. m_canvas->Refresh();
  1724. }
  1725. void MyFrame::PrepareDC(wxDC& dc)
  1726. {
  1727. dc.SetLogicalOrigin( m_xLogicalOrigin, m_yLogicalOrigin );
  1728. dc.SetAxisOrientation( !m_xAxisReversed, m_yAxisReversed );
  1729. dc.SetUserScale( m_xUserScale, m_yUserScale );
  1730. dc.SetMapMode( m_mapMode );
  1731. }
  1732. #if wxUSE_COLOURDLG
  1733. wxColour MyFrame::SelectColour()
  1734. {
  1735. wxColour col;
  1736. wxColourData data;
  1737. wxColourDialog dialog(this, &data);
  1738. if ( dialog.ShowModal() == wxID_OK )
  1739. {
  1740. col = dialog.GetColourData().GetColour();
  1741. }
  1742. return col;
  1743. }
  1744. #endif // wxUSE_COLOURDLG