wxruby3 0.9.8 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (158) hide show
  1. checksums.yaml +4 -4
  2. data/INSTALL.md +23 -1
  3. data/README.md +13 -27
  4. data/ext/mkrf_conf_ext.rb +11 -7
  5. data/lib/wx/core/app.rb +16 -0
  6. data/lib/wx/core/colour.rb +36 -28
  7. data/lib/wx/core/const.rb +19 -0
  8. data/lib/wx/core/enum.rb +17 -1
  9. data/lib/wx/core/geometry.rb +121 -0
  10. data/lib/wx/core/graphics_pen_info.rb +18 -0
  11. data/lib/wx/core/image.rb +49 -0
  12. data/lib/wx/core/menu_bar.rb +11 -0
  13. data/lib/wx/core/paintdc.rb +9 -3
  14. data/lib/wx/doc/app.rb +97 -41
  15. data/lib/wx/doc/bitmap.rb +4 -0
  16. data/lib/wx/doc/client_dc.rb +2 -2
  17. data/lib/wx/doc/clipboard.rb +1 -1
  18. data/lib/wx/doc/colour.rb +12 -0
  19. data/lib/wx/doc/const.rb +16 -0
  20. data/lib/wx/doc/cursor.rb +4 -0
  21. data/lib/wx/doc/dc_overlay.rb +34 -0
  22. data/lib/wx/doc/enum.rb +7 -1
  23. data/lib/wx/doc/event_blocker.rb +1 -1
  24. data/lib/wx/doc/evthandler.rb +25 -3
  25. data/lib/wx/doc/functions.rb +3 -6
  26. data/lib/wx/doc/gc_dc.rb +13 -4
  27. data/lib/wx/doc/geometry.rb +136 -0
  28. data/lib/wx/doc/graphics_context.rb +25 -7
  29. data/lib/wx/doc/icon.rb +4 -0
  30. data/lib/wx/doc/image.rb +56 -0
  31. data/lib/wx/doc/list_ctrl.rb +6 -6
  32. data/lib/wx/doc/memory_dc.rb +2 -11
  33. data/lib/wx/doc/mirror_dc.rb +1 -1
  34. data/lib/wx/doc/pen.rb +26 -0
  35. data/lib/wx/doc/persistence_manager.rb +1 -1
  36. data/lib/wx/doc/persistent_object.rb +1 -1
  37. data/lib/wx/doc/pg/property_grid_interface.rb +3 -3
  38. data/lib/wx/doc/prt/printer_dc.rb +2 -2
  39. data/lib/wx/doc/region_iterator.rb +1 -1
  40. data/lib/wx/doc/scaled_dc.rb +1 -1
  41. data/lib/wx/doc/screen_dc.rb +1 -1
  42. data/lib/wx/doc/svg_file_dc.rb +1 -1
  43. data/lib/wx/doc/textctrl.rb +1 -1
  44. data/lib/wx/doc/tree_ctrl.rb +2 -2
  45. data/lib/wx/doc/validator.rb +6 -6
  46. data/lib/wx/doc/variant.rb +2 -2
  47. data/lib/wx/doc/window.rb +5 -4
  48. data/lib/wx/grid/keyword_defs.rb +1 -1
  49. data/lib/wx/html/keyword_defs.rb +3 -3
  50. data/lib/wx/keyword_defs.rb +76 -71
  51. data/lib/wx/pg/keyword_defs.rb +2 -2
  52. data/lib/wx/pg/pg_property.rb +12 -0
  53. data/lib/wx/rbn/keyword_defs.rb +1 -1
  54. data/lib/wx/rtc/keyword_defs.rb +1 -1
  55. data/lib/wx/stc/keyword_defs.rb +1 -1
  56. data/lib/wx/version.rb +1 -1
  57. data/lib/wx/wxruby/cmd/setup.rb +3 -0
  58. data/rakelib/configure.rb +7 -0
  59. data/rakelib/gem.rake +3 -2
  60. data/rakelib/gem.rb +3 -2
  61. data/rakelib/lib/config/linux.rb +1 -1
  62. data/rakelib/lib/config/mingw.rb +4 -101
  63. data/rakelib/lib/config/pkgman/linux.rb +31 -8
  64. data/rakelib/lib/config/pkgman/mingw.rb +112 -0
  65. data/rakelib/lib/config/unixish.rb +6 -7
  66. data/rakelib/lib/config.rb +25 -4
  67. data/rakelib/lib/core/include/enum.inc +31 -1
  68. data/rakelib/lib/director/affine_matrix.rb +51 -0
  69. data/rakelib/lib/director/app.rb +29 -13
  70. data/rakelib/lib/director/art_provider.rb +4 -0
  71. data/rakelib/lib/director/cursor.rb +6 -2
  72. data/rakelib/lib/director/dc.rb +1 -6
  73. data/rakelib/lib/director/derived_dc.rb +88 -31
  74. data/rakelib/lib/director/dialog.rb +0 -8
  75. data/rakelib/lib/director/geometry.rb +142 -0
  76. data/rakelib/lib/director/graphics_context.rb +3 -2
  77. data/rakelib/lib/director/graphics_object.rb +18 -25
  78. data/rakelib/lib/director/image.rb +59 -0
  79. data/rakelib/lib/director/menu.rb +2 -3
  80. data/rakelib/lib/director/menu_bar.rb +0 -3
  81. data/rakelib/lib/director/pen.rb +1 -1
  82. data/rakelib/lib/director/richtext_ctrl.rb +1 -1
  83. data/rakelib/lib/director/system_settings.rb +1 -1
  84. data/rakelib/lib/director/window.rb +9 -3
  85. data/rakelib/lib/extractor/function.rb +1 -1
  86. data/rakelib/lib/generate/doc/animation_ctrl.yaml +10 -0
  87. data/rakelib/lib/generate/doc/banner_window.yaml +35 -0
  88. data/rakelib/lib/generate/doc/graphics_context.yaml +12 -0
  89. data/rakelib/lib/generate/doc/graphics_object.yaml +12 -0
  90. data/rakelib/lib/generate/doc/grid_ctrl.yaml +25 -0
  91. data/rakelib/lib/generate/doc/header_ctrl.yaml +91 -0
  92. data/rakelib/lib/generate/doc/icon.yaml +10 -0
  93. data/rakelib/lib/generate/doc/info_bar.yaml +27 -0
  94. data/rakelib/lib/generate/doc/log.yaml +1 -1
  95. data/rakelib/lib/generate/doc/media_ctrl.yaml +27 -0
  96. data/rakelib/lib/generate/doc/persistent_window.yaml +22 -0
  97. data/rakelib/lib/generate/doc/pg_editor.yaml +1 -1
  98. data/rakelib/lib/generate/doc/pg_property.yaml +4 -4
  99. data/rakelib/lib/generate/doc/rearrange_list.yaml +14 -0
  100. data/rakelib/lib/generate/doc/ribbon_panel.yaml +15 -0
  101. data/rakelib/lib/generate/doc/rich_text_formatting_dialog.yaml +26 -0
  102. data/rakelib/lib/generate/doc/text_ctrl.yaml +1 -1
  103. data/rakelib/lib/generate/doc/wizard.yaml +27 -0
  104. data/rakelib/lib/generate/doc.rb +4 -4
  105. data/rakelib/lib/generate/interface.rb +1 -1
  106. data/rakelib/lib/specs/interfaces.rb +3 -0
  107. data/rakelib/lib/swig_runner.rb +24 -3
  108. data/rakelib/lib/typemap/points_list.rb +8 -2
  109. data/rakelib/lib/typemap/richtext.rb +17 -0
  110. data/rakelib/yard/templates/default/fulldoc/html/setup.rb +3 -3
  111. data/samples/dialogs/wizard.rb +20 -19
  112. data/samples/drawing/art/drawing/image.bmp +0 -0
  113. data/samples/drawing/art/drawing/mask.bmp +0 -0
  114. data/samples/drawing/art/drawing/pat35.bmp +0 -0
  115. data/samples/drawing/art/drawing/pat36.bmp +0 -0
  116. data/samples/drawing/art/drawing/pat4.bmp +0 -0
  117. data/samples/drawing/art/drawing/smile.xpm +42 -0
  118. data/samples/drawing/drawing.rb +2276 -0
  119. data/samples/drawing/tn_drawing.png +0 -0
  120. data/samples/html/html.rb +1 -1
  121. data/samples/propgrid/propgrid.rb +1 -1
  122. data/samples/propgrid/propgrid_minimal.rb +1 -1
  123. data/samples/propgrid/sample_props.rb +1 -1
  124. data/samples/sampler/editor.rb +13 -11
  125. data/samples/sampler.rb +14 -10
  126. data/samples/text/richtext.rb +53 -0
  127. data/samples/text/scintilla.rb +1 -1
  128. data/samples/text/unicode.rb +4 -4
  129. data/tests/test_ext_controls.rb +12 -5
  130. data/tests/test_gdi_object.rb +2 -2
  131. data/tests/test_std_controls.rb +12 -12
  132. metadata +33 -32
  133. data/lib/wx/doc/extra/00_starting.md +0 -154
  134. data/lib/wx/doc/extra/01_packages.md +0 -180
  135. data/lib/wx/doc/extra/02_lifecycles.md +0 -166
  136. data/lib/wx/doc/extra/03_dialogs.md +0 -57
  137. data/lib/wx/doc/extra/04_enums.md +0 -143
  138. data/lib/wx/doc/extra/05_event-handling.md +0 -191
  139. data/lib/wx/doc/extra/06_geometry.md +0 -62
  140. data/lib/wx/doc/extra/07_colour_and_font.md +0 -52
  141. data/lib/wx/doc/extra/08_extensions.md +0 -144
  142. data/lib/wx/doc/extra/09_exceptions.md +0 -54
  143. data/lib/wx/doc/extra/10_art.md +0 -111
  144. data/lib/wx/doc/extra/11_drawing_and_dc.md +0 -62
  145. data/lib/wx/doc/extra/12_client_data.md +0 -89
  146. data/lib/wx/doc/extra/13_validators.md +0 -139
  147. data/lib/wx/doc/extra/14_config.md +0 -101
  148. data/lib/wx/doc/extra/15_persistence.md +0 -148
  149. data/samples/sampler/back.xpm +0 -21
  150. data/samples/sampler/copy.xpm +0 -44
  151. data/samples/sampler/cut.xpm +0 -46
  152. data/samples/sampler/filesave.xpm +0 -42
  153. data/samples/sampler/find.xpm +0 -62
  154. data/samples/sampler/findrepl.xpm +0 -63
  155. data/samples/sampler/forward.xpm +0 -21
  156. data/samples/sampler/paste.xpm +0 -46
  157. data/samples/sampler/redo.xpm +0 -58
  158. data/samples/sampler/undo.xpm +0 -58
@@ -0,0 +1,2276 @@
1
+ # Copyright (c) 2023 M.J.N. Corino = self.next_id The Netherlands
2
+ #
3
+ # This software is released under the MIT license.
4
+ #
5
+ # Adapted for wxRuby from wxWidgets widgets sample
6
+ # Copyright (c) Robert Roebling
7
+
8
+ require 'wx'
9
+
10
+ module Drawing
11
+
12
+ DRAWING_DC_SUPPORTS_ALPHA = %w[WXGTK WXOSX].include?(Wx::PLATFORM)
13
+
14
+ module ID
15
+ include Wx::IDHelper
16
+
17
+ # menu items
18
+ File_Quit = Wx::ID_EXIT
19
+ File_About = Wx::ID_ABOUT
20
+
21
+ MenuShow_First = self.next_id(Wx::ID_HIGHEST)
22
+ File_ShowDefault = MenuShow_First
23
+ File_ShowText = self.next_id
24
+ File_ShowLines = self.next_id
25
+ File_ShowBrushes = self.next_id
26
+ File_ShowPolygons = self.next_id
27
+ File_ShowMask = self.next_id
28
+ File_ShowMaskStretch = self.next_id
29
+ File_ShowOps = self.next_id
30
+ File_ShowRegions = self.next_id
31
+ File_ShowCircles = self.next_id
32
+ File_ShowSplines = self.next_id
33
+ File_ShowAlpha = self.next_id
34
+ File_ShowGraphics = self.next_id
35
+ File_ShowSystemColours = self.next_id
36
+ File_ShowDatabaseColours = self.next_id
37
+ File_ShowGradients = self.next_id
38
+ MenuShow_Last = File_ShowGradients
39
+
40
+ if Wx.has_feature?(:USE_GRAPHICS_CONTEXT)
41
+ File_DC = self.next_id
42
+ File_GC_Default = self.next_id
43
+ if Wx.has_feature?(:USE_CAIRO)
44
+ File_GC_Cairo = self.next_id
45
+ end # USE_CAIRO
46
+ if Wx::PLATFORM == 'WXMSW'
47
+ if Wx.has_feature?(:USE_GRAPHICS_GDIPLUS)
48
+ File_GC_GDIPlus = self.next_id
49
+ end
50
+ if Wx.has_feature?(:USE_GRAPHICS_DIRECT2D)
51
+ File_GC_Direct2D = self.next_id
52
+ end
53
+ end # WXMSW
54
+ end # USE_GRAPHICS_CONTEXT
55
+ File_BBox = self.next_id
56
+ File_Clip = self.next_id
57
+ File_Buffer = self.next_id
58
+ if Wx.has_feature?(:USE_GRAPHICS_CONTEXT)
59
+ File_AntiAliasing = self.next_id
60
+ end
61
+ File_Copy = self.next_id
62
+ File_Save = self.next_id
63
+
64
+ MenuOption_First = self.next_id
65
+
66
+ MapMode_Text = MenuOption_First
67
+ MapMode_Lometric = self.next_id
68
+ MapMode_Twips = self.next_id
69
+ MapMode_Points = self.next_id
70
+ MapMode_Metric = self.next_id
71
+
72
+ UserScale_StretchHoriz = self.next_id
73
+ UserScale_ShrinkHoriz = self.next_id
74
+ UserScale_StretchVertic = self.next_id
75
+ UserScale_ShrinkVertic = self.next_id
76
+ UserScale_Restore = self.next_id
77
+
78
+ AxisMirror_Horiz = self.next_id
79
+ AxisMirror_Vertic = self.next_id
80
+
81
+ LogicalOrigin_MoveDown = self.next_id
82
+ LogicalOrigin_MoveUp = self.next_id
83
+ LogicalOrigin_MoveLeft = self.next_id
84
+ LogicalOrigin_MoveRight = self.next_id
85
+ LogicalOrigin_Set = self.next_id
86
+ LogicalOrigin_Restore = self.next_id
87
+
88
+ TransformMatrix_Set = self.next_id
89
+ TransformMatrix_Reset = self.next_id
90
+
91
+ Colour_TextForeground = self.next_id
92
+ Colour_TextBackground = self.next_id
93
+ Colour_Background = self.next_id
94
+ Colour_BackgroundMode = self.next_id
95
+ Colour_TextureBackground = self.next_id
96
+
97
+ MenuOption_Last = Colour_TextureBackground
98
+ end
99
+
100
+ class MyCanvas < Wx::ScrolledWindow
101
+
102
+ class DrawMode < Wx::Enum
103
+ Draw_Normal = self.new(0)
104
+ Draw_Stretch = self.new(1)
105
+ end
106
+
107
+ def initialize(parent)
108
+ super(parent, Wx::ID_ANY, style: Wx::HSCROLL | Wx::VSCROLL)
109
+
110
+ @owner = parent
111
+ @show = ID::File_ShowDefault
112
+ @smile_bmp = Wx.Bitmap(:smile)
113
+ @std_icon = Wx::ArtProvider.get_icon(Wx::ART_INFORMATION)
114
+ @clip = false
115
+ @rubberBand = false
116
+ if Wx.has_feature?(:USE_GRAPHICS_CONTEXT)
117
+ @renderer = nil
118
+ @useAntiAliasing = true
119
+ end
120
+ @useBuffer = false
121
+ @showBBox = false
122
+ @sizeDIP = Wx::Size.new
123
+ @currentpoint = Wx::Point.new
124
+ @anchorpoint = Wx::Point.new
125
+ @overlay = Wx::Overlay.new
126
+
127
+ evt_paint :on_paint
128
+ evt_motion :on_mouse_move
129
+ evt_left_down :on_mouse_down
130
+ evt_left_up :on_mouse_up
131
+ end
132
+
133
+ def on_paint(_event)
134
+ if @useBuffer
135
+ Wx::BufferedPaintDC.draw_on(self) { |bpdc| draw(bpdc) }
136
+ else
137
+ self.paint { |pdc| draw(pdc) }
138
+ end
139
+ end
140
+
141
+ def on_mouse_move(event)
142
+ if Wx.has_feature?(:USE_STATUSBAR)
143
+ Wx::ClientDC.draw_on(self) do |dc|
144
+ prepare_dc(dc)
145
+ @owner.prepare_dc(dc)
146
+
147
+ pos = dc.device_to_logical(event.position)
148
+ dipPos = dc.to_dip(pos)
149
+ str = "Mouse position: #{pos.x},#{pos.y}"
150
+ str << " DIP position: #{dipPos.x},#{dipPos.y}" if pos != dipPos
151
+ @owner.set_status_text(str)
152
+ end
153
+
154
+ if @rubberBand
155
+ @currentpoint = calc_unscrolled_position(event.position)
156
+ newrect = Wx::Rect.new(@anchorpoint, @currentpoint)
157
+
158
+ Wx::ClientDC.draw_on(self) do |dc|
159
+ prepare_dc(dc)
160
+
161
+ Wx::DCOverlay.draw_on(@overlay, dc) { |overlaydc| overlaydc.clear }
162
+
163
+ if Wx::PLATFORM == 'WXMAC'
164
+ dc.set_pen(Wx::GREY_PEN )
165
+ dc.set_brush(Wx::Brush.new(Wx::Colour.new(192,192,192,64)))
166
+ else
167
+ dc.set_pen(Wx::Pen.new(Wx::LIGHT_GREY, 2))
168
+ dc.set_brush(Wx::TRANSPARENT_BRUSH)
169
+ end
170
+ dc.draw_rectangle(newrect)
171
+ end
172
+ end
173
+ end # USE_STATUSBAR
174
+ end
175
+
176
+ def on_mouse_down(event)
177
+ @anchorpoint = calc_unscrolled_position(event.position)
178
+ @currentpoint = @anchorpoint
179
+ @rubberBand = true
180
+ capture_mouse
181
+ end
182
+
183
+ def on_mouse_up(event)
184
+ if @rubberBand
185
+ release_mouse
186
+ Wx::ClientDC.draw_on(self) do |dc|
187
+ prepare_dc(dc)
188
+ Wx::DCOverlay.draw_on(@overlay, dc) { |overlaydc| overlaydc.clear }
189
+ end
190
+ @overlay.reset
191
+ @rubberBand = false
192
+
193
+ endpoint = calc_unscrolled_position(event.position)
194
+
195
+ # Don't pop up the message box if nothing was actually selected.
196
+ if endpoint != @anchorpoint
197
+ Wx.log_message('Selected rectangle from (%d, %d) to (%d, %d)',
198
+ @anchorpoint.x, @anchorpoint.y,
199
+ endpoint.x, endpoint.y)
200
+ end
201
+ end
202
+ end
203
+
204
+ def to_show(show)
205
+ @show = show
206
+ refresh
207
+ end
208
+
209
+ def get_page
210
+ @show
211
+ end
212
+
213
+ # set or remove the clipping region
214
+ def clip(clip)
215
+ @clip = clip
216
+ refresh
217
+ end
218
+
219
+ if Wx.has_feature?(:USE_GRAPHICS_CONTEXT)
220
+
221
+ def has_renderer
222
+ !!@renderer
223
+ end
224
+
225
+ def use_graphic_renderer(renderer)
226
+ @renderer = renderer
227
+ if renderer
228
+ major, minor, micro = renderer.get_version
229
+ str = 'Graphics renderer: %s %i.%i.%i' % [renderer.get_name, major, minor, micro]
230
+ @owner.set_status_text(str, 1)
231
+ else
232
+ @owner.set_status_text('', 1)
233
+ end
234
+
235
+ refresh
236
+ end
237
+
238
+ def is_default_renderer
239
+ return false unless @renderer
240
+ @renderer == Wx::GraphicsRenderer.get_default_renderer
241
+ end
242
+
243
+ def get_renderer
244
+ @renderer
245
+ end
246
+
247
+ def enable_anti_aliasing(use)
248
+ @use_anti_aliasing = use
249
+ refresh
250
+ end
251
+
252
+ end # USE_GRAPHICS_CONTEXT
253
+
254
+ def use_buffer(use)
255
+ @useBuffer = use
256
+ refresh
257
+ end
258
+
259
+ def show_bounding_box(show)
260
+ @showBBox = show
261
+ refresh
262
+ end
263
+
264
+ def get_dip_drawing_size
265
+ @sizeDIP
266
+ end
267
+
268
+ if Wx.has_feature?(:USE_GRAPHICS_CONTEXT)
269
+ def draw(pdc)
270
+ if @renderer
271
+ context = @renderer.create_context(pdc)
272
+
273
+ context.set_antialias_mode(@useAntiAliasing ? Wx::ANTIALIAS_DEFAULT : Wx::ANTIALIAS_NONE)
274
+
275
+ Wx::GCDC.draw_on do |gdc|
276
+ gdc.set_background(Wx::Brush.new(get_background_colour))
277
+ gdc.set_graphics_context(context)
278
+ # Adjust scrolled contents for screen drawing operations only.
279
+ if pdc.is_a?(Wx::BufferedPaintDC) || pdc.is_a?(Wx::PaintDC)
280
+ prepare_dc(gdc)
281
+ end
282
+
283
+ @owner.prepare_dc(gdc)
284
+
285
+ do_draw(gdc)
286
+ end
287
+ else
288
+ # Adjust scrolled contents for screen drawing operations only.
289
+ if pdc.is_a?(Wx::BufferedPaintDC) || pdc.is_a?(Wx::PaintDC)
290
+ prepare_dc(pdc)
291
+ end
292
+
293
+ @owner.prepare_dc(pdc)
294
+
295
+ do_draw(pdc)
296
+ end
297
+ end
298
+ else
299
+ def draw(pdc)
300
+ # Adjust scrolled contents for screen drawing operations only.
301
+ if pdc.is_a?(Wx::BufferedPaintDC) || pdc.is_a?(Wx::PaintDC)
302
+ prepare_dc(pdc)
303
+ end
304
+
305
+ @owner.prepare_dc(pdc)
306
+
307
+ do_draw(pdc)
308
+ end
309
+ end
310
+
311
+ protected
312
+
313
+ def do_draw(dc)
314
+ dc.set_background_mode(@owner.backgroundMode)
315
+ dc.set_background(@owner.backgroundBrush) if @owner.backgroundBrush.ok?
316
+ dc.set_text_foreground(@owner.colourForeground) if @owner.colourForeground.ok?
317
+ dc.set_text_background(@owner.colourBackground) if @owner.colourBackground.ok?
318
+
319
+ if @owner.textureBackground
320
+ unless @owner.backgroundBrush.ok?
321
+ dc.set_background(Wx::Brush.new(Wx::Colour.new(0, 128, 0)))
322
+ end
323
+ end
324
+
325
+ if @clip
326
+ dc.set_clipping_region([dc.from_dip(100), dc.from_dip(100)],
327
+ [dc.from_dip(100), dc.from_dip(100)])
328
+ end
329
+
330
+ dc.clear
331
+
332
+ if @owner.textureBackground
333
+ dc.set_pen(Wx::MEDIUM_GREY_PEN)
334
+ 200.times { |i| dc.draw_line(0, dc.from_dip(i*10), dc.from_dip(i*10), 0) }
335
+ end
336
+
337
+ case @show
338
+ when ID::File_ShowDefault
339
+ draw_default(dc)
340
+
341
+ when ID::File_ShowCircles
342
+ draw_circles(dc)
343
+
344
+ when ID::File_ShowSplines
345
+ draw_splines(dc)
346
+
347
+ when ID::File_ShowRegions
348
+ draw_regions(dc)
349
+
350
+ when ID::File_ShowText
351
+ draw_text(dc)
352
+
353
+ when ID::File_ShowLines
354
+ draw_test_lines(0, 100, 0, dc)
355
+ draw_test_lines(0, 320, 1, dc)
356
+ draw_test_lines(0, 540, 2, dc)
357
+ draw_test_lines(0, 760, 6, dc)
358
+ draw_cross_hair(0, 0, 400, 90, dc)
359
+
360
+ when ID::File_ShowBrushes
361
+ draw_test_brushes(dc)
362
+
363
+ when ID::File_ShowPolygons
364
+ draw_test_poly(dc)
365
+
366
+ when ID::File_ShowMask
367
+ draw_images(dc, DrawMode::Draw_Normal)
368
+
369
+ when ID::File_ShowMaskStretch
370
+ draw_images(dc, DrawMode::Draw_Stretch)
371
+
372
+ when ID::File_ShowOps
373
+ draw_with_logical_ops(dc)
374
+
375
+ when ID::File_ShowAlpha
376
+ draw_alpha(dc)
377
+
378
+ when ID::File_ShowGraphics
379
+ draw_graphics(dc.get_graphics_context) if dc.is_a?(Wx::GCDC)
380
+
381
+ when ID::File_ShowGradients
382
+ draw_gradients(dc)
383
+
384
+ when ID::File_ShowSystemColours
385
+ draw_system_colours(dc)
386
+
387
+ end
388
+
389
+ # For drawing with raw Wx::GraphicsContext
390
+ # there is no bounding box to obtain.
391
+ if @showBBox && !(Wx.has_feature?(:USE_GRAPHICS_CONTEXT) && @show == ID::File_ShowGraphics)
392
+ dc.set_pen(Wx::Pen.new(Wx::Colour.new(0, 128, 0), 1, Wx::PENSTYLE_DOT))
393
+ dc.set_brush(Wx::TRANSPARENT_BRUSH)
394
+ dc.draw_rectangle(dc.min_x, dc.min_y, dc.max_x-dc.min_x+1, dc.max_y-dc.min_y+1)
395
+ end
396
+
397
+ # Adjust drawing area dimensions only if screen drawing is invoked.
398
+ if dc.is_a?(Wx::BufferedPaintDC) || dc.is_a?(Wx::PaintDC)
399
+ x0, y0 = dc.get_device_origin
400
+ @sizeDIP.x = dc.to_dip(dc.logical_to_device_x(dc.max_x) - x0) + 1
401
+ @sizeDIP.y = dc.to_dip(dc.logical_to_device_y(dc.max_y) - y0) + 1
402
+ end
403
+ end
404
+
405
+ def draw_test_lines(x, y, width, dc)
406
+ dc.set_pen(Wx::Pen.new( Wx::BLACK, width))
407
+ dc.set_brush(Wx::WHITE_BRUSH)
408
+ dc.draw_text("Testing lines of width #{width}", dc.from_dip(x + 10), dc.from_dip(y - 10))
409
+ dc.draw_rectangle(dc.from_dip(x + 10), dc.from_dip(y + 10), dc.from_dip(100), dc.from_dip(190))
410
+
411
+ dc.draw_text("Solid/dot/short dash/long dash/dot dash", dc.from_dip(x + 150), dc.from_dip(y + 10))
412
+ dc.set_pen( Wx::Pen.new( Wx::BLACK, width ) )
413
+ dc.draw_line(dc.from_dip(x + 20), dc.from_dip(y + 20), dc.from_dip(100), dc.from_dip(y + 20))
414
+ dc.set_pen( Wx::Pen.new( Wx::BLACK, width, Wx::PENSTYLE_DOT) )
415
+ dc.draw_line(dc.from_dip(x + 20), dc.from_dip(y + 30), dc.from_dip(100), dc.from_dip(y + 30))
416
+ dc.set_pen( Wx::Pen.new( Wx::BLACK, width, Wx::PENSTYLE_SHORT_DASH) )
417
+ dc.draw_line(dc.from_dip(x + 20), dc.from_dip(y + 40), dc.from_dip(100), dc.from_dip(y + 40))
418
+ dc.set_pen( Wx::Pen.new( Wx::BLACK, width, Wx::PENSTYLE_LONG_DASH) )
419
+ dc.draw_line(dc.from_dip(x + 20), dc.from_dip(y + 50), dc.from_dip(100), dc.from_dip(y + 50))
420
+ dc.set_pen( Wx::Pen.new( Wx::BLACK, width, Wx::PENSTYLE_DOT_DASH) )
421
+ dc.draw_line(dc.from_dip(x + 20), dc.from_dip(y + 60), dc.from_dip(100), dc.from_dip(y + 60))
422
+
423
+ dc.draw_text("Hatches", dc.from_dip(x + 150), dc.from_dip(y + 70))
424
+ dc.set_pen( Wx::Pen.new( Wx::BLACK, width, Wx::PENSTYLE_BDIAGONAL_HATCH) )
425
+ dc.draw_line(dc.from_dip(x + 20), dc.from_dip(y + 70), dc.from_dip(100), dc.from_dip(y + 70))
426
+ dc.set_pen( Wx::Pen.new( Wx::BLACK, width, Wx::PENSTYLE_CROSSDIAG_HATCH) )
427
+ dc.draw_line(dc.from_dip(x + 20), dc.from_dip(y + 80), dc.from_dip(100), dc.from_dip(y + 80))
428
+ dc.set_pen( Wx::Pen.new( Wx::BLACK, width, Wx::PENSTYLE_FDIAGONAL_HATCH) )
429
+ dc.draw_line(dc.from_dip(x + 20), dc.from_dip(y + 90), dc.from_dip(100), dc.from_dip(y + 90))
430
+ dc.set_pen( Wx::Pen.new( Wx::BLACK, width, Wx::PENSTYLE_CROSS_HATCH) )
431
+ dc.draw_line(dc.from_dip(x + 20), dc.from_dip(y + 100), dc.from_dip(100), dc.from_dip(y + 100))
432
+ dc.set_pen( Wx::Pen.new( Wx::BLACK, width, Wx::PENSTYLE_HORIZONTAL_HATCH) )
433
+ dc.draw_line(dc.from_dip(x + 20), dc.from_dip(y + 110), dc.from_dip(100), dc.from_dip(y + 110))
434
+ dc.set_pen( Wx::Pen.new( Wx::BLACK, width, Wx::PENSTYLE_VERTICAL_HATCH) )
435
+ dc.draw_line(dc.from_dip(x + 20), dc.from_dip(y + 120), dc.from_dip(100), dc.from_dip(y + 120))
436
+
437
+ dc.draw_text("User dash", dc.from_dip(x + 150), dc.from_dip(y + 140))
438
+ ud = Wx::Pen.new( Wx::BLACK, width, Wx::PENSTYLE_USER_DASH )
439
+ dash1 = [
440
+ 8, # Long dash <---------+
441
+ 2, # Short gap |
442
+ 3, # Short dash |
443
+ 2, # Short gap |
444
+ 3, # Short dash |
445
+ 2] # Short gap and repeat +
446
+ ud.set_dashes(dash1)
447
+ dc.set_pen( ud )
448
+ dc.draw_line(dc.from_dip(x + 20), dc.from_dip(y + 140), dc.from_dip(100), dc.from_dip(y + 140))
449
+ dash1[0] = 5 # Make first dash shorter
450
+ ud.set_dashes( dash1 )
451
+ dc.set_pen( ud )
452
+ dc.draw_line(dc.from_dip(x + 20), dc.from_dip(y + 150), dc.from_dip(100), dc.from_dip(y + 150))
453
+ dash1[2] = 5 # Make second dash longer
454
+ ud.set_dashes( dash1 )
455
+ dc.set_pen( ud )
456
+ dc.draw_line(dc.from_dip(x + 20), dc.from_dip(y + 160), dc.from_dip(100), dc.from_dip(y + 160))
457
+ dash1[4] = 5 # Make third dash longer
458
+ ud.set_dashes( dash1 )
459
+ dc.set_pen( ud )
460
+ dc.draw_line(dc.from_dip(x + 20), dc.from_dip(y + 170), dc.from_dip(100), dc.from_dip(y + 170))
461
+
462
+ penWithCap = Wx::Pen.new(Wx::BLACK, width)
463
+ dc.set_pen(penWithCap)
464
+ dc.draw_text("Default cap", dc.from_dip(x + 270), dc.from_dip(y + 40))
465
+ dc.draw_line(dc.from_dip(x + 200), dc.from_dip(y + 50), dc.from_dip(x + 250), dc.from_dip(y + 50))
466
+
467
+ penWithCap.set_cap(Wx::CAP_BUTT)
468
+ dc.set_pen(penWithCap)
469
+ dc.draw_text("Butt ", dc.from_dip(x + 270), dc.from_dip(y + 60))
470
+ dc.draw_line(dc.from_dip(x + 200), dc.from_dip(y + 70), dc.from_dip(x + 250), dc.from_dip(y + 70))
471
+
472
+ penWithCap.set_cap(Wx::CAP_ROUND)
473
+ dc.set_pen(penWithCap)
474
+ dc.draw_text("Round cap", dc.from_dip(x + 270), dc.from_dip(y + 80))
475
+ dc.draw_line(dc.from_dip(x + 200), dc.from_dip(y + 90), dc.from_dip(x + 250), dc.from_dip(y + 90))
476
+
477
+ penWithCap.set_cap(Wx::CAP_PROJECTING)
478
+ dc.set_pen(penWithCap)
479
+ dc.draw_text("Projecting cap", dc.from_dip(x + 270), dc.from_dip(y + 100))
480
+ dc.draw_line(dc.from_dip(x + 200), dc.from_dip(y + 110), dc.from_dip(x + 250), dc.from_dip(y + 110))
481
+ end
482
+
483
+ def draw_cross_hair(x, y, width, height, dc)
484
+ dc.draw_text("Cross hair", dc.from_dip(x + 10), dc.from_dip(y + 10))
485
+ dc.set_clipping_region(dc.from_dip(x), dc.from_dip(y), dc.from_dip(width), dc.from_dip(height))
486
+ dc.set_pen(Wx::Pen.new(Wx::BLUE, 2))
487
+ dc.cross_hair(dc.from_dip(x + width / 2), dc.from_dip(y + height / 2))
488
+ dc.destroy_clipping_region
489
+ end
490
+
491
+ def draw_test_poly(dc)
492
+ brushHatch = Wx::Brush.new(Wx::RED, Wx::BRUSHSTYLE_FDIAGONAL_HATCH)
493
+ dc.set_brush(brushHatch)
494
+
495
+ star = [
496
+ dc.from_dip(Wx::Point.new(100, 60)),
497
+ dc.from_dip(Wx::Point.new(60, 150)),
498
+ dc.from_dip(Wx::Point.new(160, 100)),
499
+ dc.from_dip(Wx::Point.new(40, 100)),
500
+ dc.from_dip(Wx::Point.new(140, 150))]
501
+
502
+ dc.draw_text("You should see two (irregular) stars below, the left one hatched",
503
+ dc.from_dip(10), dc.from_dip(10))
504
+ dc.draw_text("except for the central region and the right one entirely hatched",
505
+ dc.from_dip(10), dc.from_dip(30))
506
+ dc.draw_text("The third star only has a hatched outline", dc.from_dip(10), dc.from_dip(50))
507
+
508
+ dc.draw_polygon(star, 0, dc.from_dip(30))
509
+ dc.draw_polygon(star, dc.from_dip(160), dc.from_dip(30), Wx::WINDING_RULE)
510
+
511
+ brushHatchGreen = Wx::Brush.new(Wx::GREEN, Wx::BRUSHSTYLE_FDIAGONAL_HATCH)
512
+ dc.set_brush(brushHatchGreen)
513
+ star2 = [
514
+ [dc.from_dip(Wx::Point.new(0, 100)),
515
+ dc.from_dip(Wx::Point.new(-59, -81)),
516
+ dc.from_dip(Wx::Point.new(95, 31)),
517
+ dc.from_dip(Wx::Point.new(-95, 31)),
518
+ dc.from_dip(Wx::Point.new(59, -81))],
519
+ [dc.from_dip(Wx::Point.new(0, 80)),
520
+ dc.from_dip(Wx::Point.new(-47, -64)),
521
+ dc.from_dip(Wx::Point.new(76, 24)),
522
+ dc.from_dip(Wx::Point.new(-76, 24)),
523
+ dc.from_dip(Wx::Point.new(47, -64))]]
524
+
525
+ dc.draw_poly_polygon(star2, dc.from_dip(450), dc.from_dip(150))
526
+ end
527
+
528
+ def draw_test_brushes(dc)
529
+ _WIDTH = dc.from_dip(200)
530
+ _HEIGHT = dc.from_dip(80)
531
+
532
+ x = dc.from_dip(10)
533
+ y = dc.from_dip(10)
534
+ o = dc.from_dip(10)
535
+
536
+ dc.set_brush(Wx::GREEN_BRUSH)
537
+ dc.draw_rectangle(x, y, _WIDTH, _HEIGHT)
538
+ dc.draw_text("Solid green", x + o, y + o)
539
+
540
+ y += _HEIGHT
541
+ dc.set_brush(Wx::Brush.new(Wx::RED, Wx::BRUSHSTYLE_CROSSDIAG_HATCH))
542
+ dc.draw_rectangle(x, y, _WIDTH, _HEIGHT)
543
+ dc.draw_text("Diagonally hatched red", x + o, y + o)
544
+
545
+ y += _HEIGHT
546
+ dc.set_brush(Wx::Brush.new(Wx::BLUE, Wx::BRUSHSTYLE_CROSS_HATCH))
547
+ dc.draw_rectangle(x, y, _WIDTH, _HEIGHT)
548
+ dc.draw_text("Cross hatched blue", x + o, y + o)
549
+
550
+ y += _HEIGHT
551
+ dc.set_brush(Wx::Brush.new(Wx::CYAN, Wx::BRUSHSTYLE_VERTICAL_HATCH))
552
+ dc.draw_rectangle(x, y, _WIDTH, _HEIGHT)
553
+ dc.draw_text("Vertically hatched cyan", x + o, y + o)
554
+
555
+ y += _HEIGHT
556
+ dc.set_brush(Wx::Brush.new(Wx::BLACK, Wx::BRUSHSTYLE_HORIZONTAL_HATCH))
557
+ dc.draw_rectangle(x, y, _WIDTH, _HEIGHT)
558
+ dc.draw_text("Horizontally hatched black", x + o, y + o)
559
+
560
+ y += _HEIGHT
561
+ dc.set_brush(Wx::Brush.new(Wx.get_app.images[:bmpMask]))
562
+ dc.draw_rectangle(x, y, _WIDTH, _HEIGHT)
563
+ dc.draw_text("Stipple mono", x + o, y + o)
564
+
565
+ y += _HEIGHT
566
+ dc.set_brush(Wx::Brush.new(Wx.get_app.images[:bmpNoMask]))
567
+ dc.draw_rectangle(x, y, _WIDTH, _HEIGHT)
568
+ dc.draw_text("Stipple colour", x + o, y + o)
569
+ end
570
+
571
+ def draw_text(dc)
572
+ # set underlined font for testing
573
+ dc.set_font(Wx::FontInfo.new(12).family(Wx::FONTFAMILY_MODERN).underlined)
574
+ dc.draw_text("This is text", dc.from_dip(110), dc.from_dip(10) )
575
+ dc.draw_rotated_text("That is text", dc.from_dip(20), dc.from_dip(10), -45)
576
+
577
+ # use wxSWISS_FONT and not wxNORMAL_FONT as the latter can't be rotated
578
+ # under MSW (it is not TrueType)
579
+ dc.set_font(Wx::SWISS_FONT)
580
+
581
+ dc.set_background_mode(Wx::BRUSHSTYLE_TRANSPARENT)
582
+
583
+ (-180..180).step(30) do |n|
584
+ text = " #{n} rotated text"
585
+ dc.draw_rotated_text(text , dc.from_dip(400), dc.from_dip(400), n)
586
+ end
587
+
588
+ dc.set_font(Wx::FontInfo.new(18).family(Wx::FONTFAMILY_SWISS))
589
+
590
+ dc.draw_text("This is Swiss 18pt text.", dc.from_dip(110), dc.from_dip(40))
591
+
592
+ length, height, descent = dc.get_text_extent("This is Swiss 18pt text.")
593
+ text = "Dimensions are length #{length}, height #{height}, descent #{descent}"
594
+ dc.draw_text(text, dc.from_dip(110), dc.from_dip(80))
595
+
596
+ text = "CharHeight() returns: #{dc.get_char_height}"
597
+ dc.draw_text(text, dc.from_dip(110), dc.from_dip(120))
598
+
599
+ dc.draw_rectangle(dc.from_dip(100), dc.from_dip(40), dc.from_dip(4), dc.from_dip(height))
600
+
601
+ # test the logical function effect
602
+ y = dc.from_dip(150)
603
+ dc.set_logical_function(Wx::INVERT)
604
+ # text drawing should ignore logical function
605
+ dc.draw_text("There should be a text below", dc.from_dip(110), y)
606
+ dc.draw_rectangle(dc.from_dip(110), y, dc.from_dip(100), height)
607
+
608
+ y += height
609
+ dc.draw_text("Visible text", dc.from_dip(110), y)
610
+ dc.draw_rectangle(dc.from_dip(110), y, dc.from_dip(100), height)
611
+ dc.draw_text("Visible text", dc.from_dip(110), y)
612
+ dc.draw_rectangle(dc.from_dip(110), y, dc.from_dip(100), height)
613
+ dc.set_logical_function(Wx::COPY)
614
+
615
+ y += height
616
+ dc.draw_rectangle(dc.from_dip(110), y, dc.from_dip(100), height)
617
+ dc.draw_text("Another visible text", dc.from_dip(110), y)
618
+
619
+ y += height
620
+ dc.draw_text("And\nmore\ntext on\nmultiple\nlines", dc.from_dip(110), y)
621
+ y += 5*height
622
+
623
+ dc.set_text_foreground(Wx::BLUE)
624
+ dc.draw_rotated_text("Rotated text\ncan have\nmultiple lines\nas well", dc.from_dip(110), y, 15)
625
+
626
+ y += 7*height
627
+ dc.set_font(Wx::FontInfo.new(12).family(Wx::FONTFAMILY_TELETYPE))
628
+ dc.set_text_foreground(Wx::Colour.new(150, 75, 0))
629
+ dc.draw_text("And some text with tab characters:\n123456789012345678901234567890\n\taa\tbbb\tcccc", dc.from_dip(10), y)
630
+ end
631
+
632
+ RASTER_OPERATIONS = [
633
+ ["Wx::AND", Wx::AND ],
634
+ ["Wx::AND_INVERT", Wx::AND_INVERT ],
635
+ ["Wx::AND_REVERSE", Wx::AND_REVERSE ],
636
+ ["Wx::CLEAR", Wx::CLEAR ],
637
+ ["Wx::COPY", Wx::COPY ],
638
+ ["Wx::EQUIV", Wx::EQUIV ],
639
+ ["Wx::INVERT", Wx::INVERT ],
640
+ ["Wx::NAND", Wx::NAND ],
641
+ ["Wx::NO_OP", Wx::NO_OP ],
642
+ ["Wx::OR", Wx::OR ],
643
+ ["Wx::OR_INVERT", Wx::OR_INVERT ],
644
+ ["Wx::OR_REVERSE", Wx::OR_REVERSE ],
645
+ ["Wx::SET", Wx::SET ],
646
+ ["Wx::SRC_INVERT", Wx::SRC_INVERT ],
647
+ ["Wx::XOR", Wx::XOR ],
648
+ ]
649
+
650
+ def draw_images(dc, mode)
651
+ dc.draw_text("original image", 0, 0)
652
+ dc.draw_bitmap(Wx.get_app.images[:bmpNoMask], 0, dc.from_dip(20), false)
653
+ dc.draw_text("with colour mask", 0, dc.from_dip(100))
654
+ dc.draw_bitmap(Wx.get_app.images[:bmpWithColMask], 0, dc.from_dip(120), true)
655
+ dc.draw_text("the mask image", 0, dc.from_dip(200))
656
+ dc.draw_bitmap(Wx.get_app.images[:bmpMask], 0, dc.from_dip(220), false)
657
+ dc.draw_text("masked image", 0, dc.from_dip(300))
658
+ dc.draw_bitmap(Wx.get_app.images[:bmpWithMask], 0, dc.from_dip(320), true)
659
+
660
+ cx = Wx.get_app.images[:bmpWithColMask].width
661
+ cy = Wx.get_app.images[:bmpWithColMask].height
662
+
663
+ Wx::MemoryDC.draw_on do |memDC|
664
+ RASTER_OPERATIONS.each_with_index do |pair, n|
665
+ x = dc.from_dip(120) + dc.from_dip(150)*(n%4)
666
+ y = dc.from_dip(20) + dc.from_dip(100)*(n/4)
667
+
668
+ name, rop = pair
669
+
670
+ dc.draw_text(name, x, y - dc.from_dip(20))
671
+ memDC.select_object(Wx.get_app.images[:bmpWithColMask])
672
+ if mode == DrawMode::Draw_Stretch
673
+ dc.stretch_blit(x, y, cx, cy, memDC, 0, 0, cx/2, cy/2,
674
+ rop, true)
675
+ else
676
+ dc.blit(x, y, cx, cy, memDC, 0, 0, rop, true)
677
+ end
678
+ end
679
+ end
680
+ end
681
+
682
+ def draw_with_logical_ops(dc)
683
+ w = dc.from_dip(60)
684
+ h = dc.from_dip(60)
685
+
686
+ # reuse the text colour here
687
+ dc.set_pen(Wx::Pen.new(@owner.colourForeground))
688
+ dc.set_brush(Wx::TRANSPARENT_BRUSH)
689
+
690
+ RASTER_OPERATIONS.each_with_index do |pair, n|
691
+ x = dc.from_dip(20) + dc.from_dip(150)*(n%4)
692
+ y = dc.from_dip(20) + dc.from_dip(100)*(n/4)
693
+
694
+ name, rop = pair
695
+
696
+ dc.draw_text(name, x, y - dc.from_dip(20))
697
+ dc.set_logical_function(rop)
698
+ dc.draw_rectangle(x, y, w, h)
699
+ dc.draw_line(x, y, x + w, y + h)
700
+ dc.draw_line(x + w, y, x, y + h)
701
+ end
702
+
703
+ # now some filled rectangles
704
+ dc.set_brush(Wx::Brush.new(@owner.colourForeground))
705
+
706
+ RASTER_OPERATIONS.each_with_index do |pair, n|
707
+ x = dc.from_dip(20) + dc.from_dip(150)*(n%4)
708
+ y = dc.from_dip(500) + dc.from_dip(100)*(n/4)
709
+
710
+ name, rop = pair
711
+
712
+ dc.draw_text(name, x, y - dc.from_dip(20))
713
+ dc.set_logical_function(rop)
714
+ dc.draw_rectangle(x, y, w, h)
715
+ end
716
+ end
717
+
718
+ def draw_alpha(dc)
719
+ if DRAWING_DC_SUPPORTS_ALPHA || Wx.has_feature?(:USE_GRAPHICS_CONTEXT)
720
+ margin = dc.from_dip(20)
721
+ width = dc.from_dip(180)
722
+ radius = dc.from_dip(30)
723
+
724
+ dc.set_pen(Wx::Pen.new(Wx::Colour.new(128, 0, 0 ), 12))
725
+ dc.set_brush(Wx::RED_BRUSH)
726
+
727
+ r = Wx::Rect.new(margin, margin + width * 2 / 3, width, width)
728
+
729
+ dc.draw_rounded_rectangle(r.x, r.y, r.width, r.width, radius)
730
+
731
+ dc.set_pen(Wx::Pen.new(Wx::Colour.new( 0, 0, 128 ), 12))
732
+ dc.set_brush(Wx::Brush.new(Wx::Colour.new(0, 0, 255, 192)))
733
+
734
+ r.offset!(width * 4 / 5, -width * 2 / 3)
735
+
736
+ dc.draw_rounded_rectangle(r.x, r.y, r.width, r.width, radius)
737
+
738
+ dc.set_pen(Wx::Pen.new(Wx::Colour.new( 128, 128, 0 ), 12))
739
+ dc.set_brush(Wx::Brush.new(Wx::Colour.new( 192, 192, 0, 192)))
740
+
741
+ r.offset!(width * 4 / 5, width / 2)
742
+
743
+ dc.draw_rounded_rectangle(r.x, r.y, r.width, r.width, radius)
744
+
745
+ dc.set_pen(Wx::TRANSPARENT_PEN)
746
+ dc.set_brush(Wx::Brush.new(Wx::Colour.new(255,255,128,128) ))
747
+ dc.draw_rounded_rectangle( 0 , margin + width / 2 , width * 3 , dc.from_dip(100) , radius)
748
+
749
+ dc.set_text_background(Wx::Colour.new(160, 192, 160, 160))
750
+ dc.set_text_foreground(Wx::Colour.new(255, 128, 128, 128))
751
+ dc.set_font(Wx::FontInfo.new(40).family(Wx::FONTFAMILY_SWISS).italic)
752
+ dc.draw_text("Hello!", dc.from_dip(120), dc.from_dip(80))
753
+ end
754
+ end
755
+
756
+ def draw_graphics(gc)
757
+ if Wx.has_feature?(:USE_GRAPHICS_CONTEXT)
758
+ _BASE = gc.from_dip(80).to_f
759
+ _BASE2 = _BASE / 2
760
+ _BASE4 = _BASE / 4
761
+
762
+ font = Wx::SystemSettings.get_font(Wx::SYS_DEFAULT_GUI_FONT)
763
+ gc.set_font(font,Wx::BLACK)
764
+
765
+ # make a path that contains a circle and some lines, centered at 0,0
766
+ path = gc.create_path
767
+ path.add_circle( 0, 0, _BASE2 )
768
+ path.move_to_point(0, -_BASE2)
769
+ path.add_line_to_point(0, _BASE2)
770
+ path.move_to_point(-_BASE2, 0)
771
+ path.add_line_to_point(_BASE2, 0)
772
+ path.close_subpath
773
+ path.add_rectangle(-_BASE4, -_BASE4/2, _BASE2, _BASE4)
774
+
775
+ # Now use that path to demonstrate various capabilities of the graphics context
776
+ gc.push_state # save current translation/scale/other state
777
+ gc.translate(gc.from_dip(60), gc.from_dip(75)) # reposition the context origin
778
+
779
+ gc.set_pen(Wx::Pen.new("navy"))
780
+ gc.set_brush(Wx::Brush.new(:pink))
781
+
782
+ 3.times do |i|
783
+ case i
784
+ when 0
785
+ label = "StrokePath"
786
+ when 1
787
+ label = "FillPath"
788
+ when 2
789
+ label = "DrawPath"
790
+ end
791
+ w, h, _, _ = gc.get_text_extent(label)
792
+ gc.draw_text(label, -w/2, -_BASE2 - h - gc.from_dip(4))
793
+ case i
794
+ when 0
795
+ gc.stroke_path(path)
796
+ when 1
797
+ gc.fill_path(path)
798
+ when 2
799
+ gc.draw_path(path)
800
+ end
801
+ gc.translate(2*_BASE, 0)
802
+ end
803
+
804
+ gc.pop_state # restore saved state
805
+ gc.push_state # save it again
806
+ gc.translate(gc.from_dip(60), gc.from_dip(200)) # offset to the lower part of the window
807
+
808
+ gc.draw_text("Scale", 0, -_BASE2)
809
+ gc.translate(0, gc.from_dip(20))
810
+
811
+ gc.set_brush(Wx::Brush.new(Wx::Colour.new(178, 34, 34, 128)))# 128 == half transparent
812
+ 8.times do
813
+ gc.scale(1.08, 1.08) # increase scale by 8%
814
+ gc.translate(gc.from_dip(5), gc.from_dip(5))
815
+ gc.draw_path(path)
816
+ end
817
+
818
+ gc.pop_state # restore saved state
819
+ gc.push_state # save it again
820
+ gc.translate(gc.from_dip(400), gc.from_dip(200))
821
+
822
+ gc.draw_text("Rotate", 0, -_BASE2)
823
+
824
+ # Move the origin over to the next location
825
+ gc.translate(0, gc.from_dip(75))
826
+
827
+ # draw our path again, rotating it about the central point,
828
+ # and changing colors as we go
829
+ (0...360).step(30) do |angle|
830
+ gc.push_state # save this new current state so we can
831
+ # pop back to it at the end of the loop
832
+ val = Wx::Image::HSVValue.new(angle / 360.0, 1.0, 1.0).to_rgb
833
+ gc.set_brush(Wx::Brush.new(Wx::Colour.new(val.red, val.green, val.blue, 64)))
834
+ gc.set_pen(Wx::Pen.new(Wx::Colour.new(val.red, val.green, val.blue, 128)))
835
+
836
+ # use translate to artfully reposition each drawn path
837
+ gc.translate(1.5 * _BASE2 * Math.cos(Wx.deg_to_rad(angle)),
838
+ 1.5 * _BASE2 * Math.sin(Wx.deg_to_rad(angle)))
839
+
840
+ # use Rotate to rotate the path
841
+ gc.rotate(Wx.deg_to_rad(angle))
842
+
843
+ # now draw it
844
+ gc.draw_path(path)
845
+ gc.pop_state
846
+ end
847
+ gc.pop_state
848
+
849
+ gc.push_state
850
+ gc.translate(gc.from_dip(60), gc.from_dip(400))
851
+ label_text = 'Scaled smiley inside a square'
852
+ gc.draw_text(label_text, 0, 0)
853
+ # Center a bitmap horizontally
854
+ textWidth, _, _, _ = gc.get_text_extent(label_text)
855
+ rectSize = gc.from_dip(100)
856
+ x0 = (textWidth - rectSize) / 2
857
+ gc.draw_rectangle(x0, _BASE2, rectSize, rectSize)
858
+ gc.draw_bitmap(@smile_bmp, x0, _BASE2, rectSize, rectSize)
859
+ gc.pop_state
860
+
861
+ # Draw graphics bitmap and its sub-bitmap
862
+ gc.push_state
863
+ gc.translate(gc.from_dip(300), gc.from_dip(400))
864
+ gc.draw_text('Smiley as a graphics bitmap', 0, 0)
865
+
866
+ gbmp1 = gc.create_bitmap(@smile_bmp)
867
+ gc.draw_bitmap(gbmp1, 0, _BASE2, gc.from_dip(50), gc.from_dip(50))
868
+ bmpw = @smile_bmp.width
869
+ bmph = @smile_bmp.height
870
+ gbmp2 = gc.create_sub_bitmap(gbmp1, 0, bmph/5, bmpw/2, bmph/2)
871
+ gc.draw_bitmap(gbmp2, gc.from_dip(80), _BASE2, gc.from_dip(50), gc.from_dip(50)*(bmph/2)/(bmpw/2))
872
+ gc.pop_state
873
+ end
874
+ end
875
+
876
+ def draw_regions(dc)
877
+ dc.draw_text("You should see a red rect partly covered by a cyan one "+
878
+ "on the left", dc.from_dip(10), dc.from_dip(5))
879
+ dc.draw_text("and 5 smileys from which 4 are partially clipped on the right",
880
+ dc.from_dip(10), dc.from_dip(5) + dc.get_char_height)
881
+ dc.draw_text("The second copy should be identical but right part of it "+
882
+ "should be offset by 10 pixels.",
883
+ dc.from_dip(10), dc.from_dip(5) + 2*dc.get_char_height)
884
+
885
+ draw_regions_helper(dc, dc.from_dip(10), true)
886
+ draw_regions_helper(dc, dc.from_dip(350), false)
887
+ end
888
+
889
+ def draw_circles(dc)
890
+ x = dc.from_dip(100)
891
+ y = dc.from_dip(100)
892
+ r = dc.from_dip(20)
893
+
894
+ dc.set_pen(Wx::RED_PEN)
895
+ dc.set_brush(Wx::GREEN_BRUSH)
896
+
897
+ dc.draw_text("Some circles", 0, y)
898
+ dc.draw_circle(x, y, r)
899
+ dc.draw_circle(x + 2*r, y, r)
900
+ dc.draw_circle(x + 4*r, y, r)
901
+
902
+ y += 2*r
903
+ dc.draw_text("And ellipses", 0, y)
904
+ dc.draw_ellipse(x - r, y, 2*r, r)
905
+ dc.draw_ellipse(x + r, y, 2*r, r)
906
+ dc.draw_ellipse(x + 3*r, y, 2*r, r)
907
+
908
+ y += 2*r
909
+ dc.draw_text("And arcs", 0, y)
910
+ dc.draw_arc(x - r, y, x + r, y, x, y)
911
+ dc.draw_arc(x + 4*r, y, x + 2*r, y, x + 3*r, y)
912
+ dc.draw_arc(x + 5*r, y, x + 5*r, y, x + 6*r, y)
913
+
914
+ y += 2*r
915
+ dc.draw_elliptic_arc(x - r, y, 2*r, r, 0, 90)
916
+ dc.draw_elliptic_arc(x + r, y, 2*r, r, 90, 180)
917
+ dc.draw_elliptic_arc(x + 3*r, y, 2*r, r, 180, 270)
918
+ dc.draw_elliptic_arc(x + 5*r, y, 2*r, r, 270, 360)
919
+
920
+ # same as above, just transparent brush
921
+
922
+ dc.set_pen(Wx::RED_PEN)
923
+ dc.set_brush(Wx::TRANSPARENT_BRUSH)
924
+
925
+ y += 2*r
926
+ dc.draw_text("Some circles", 0, y)
927
+ dc.draw_circle(x, y, r)
928
+ dc.draw_circle(x + 2*r, y, r)
929
+ dc.draw_circle(x + 4*r, y, r)
930
+
931
+ y += 2*r
932
+ dc.draw_text("And ellipses", 0, y)
933
+ dc.draw_ellipse(x - r, y, 2*r, r)
934
+ dc.draw_ellipse(x + r, y, 2*r, r)
935
+ dc.draw_ellipse(x + 3*r, y, 2*r, r)
936
+
937
+ y += 2*r
938
+ dc.draw_text("And arcs", 0, y)
939
+ dc.draw_arc(x - r, y, x + r, y, x, y)
940
+ dc.draw_arc(x + 4*r, y, x + 2*r, y, x + 3*r, y)
941
+ dc.draw_arc(x + 5*r, y, x + 5*r, y, x + 6*r, y)
942
+
943
+ y += 2*r
944
+ dc.draw_elliptic_arc(x - r, y, 2*r, r, 0, 90)
945
+ dc.draw_elliptic_arc(x + r, y, 2*r, r, 90, 180)
946
+ dc.draw_elliptic_arc(x + 3*r, y, 2*r, r, 180, 270)
947
+ dc.draw_elliptic_arc(x + 5*r, y, 2*r, r, 270, 360)
948
+ end
949
+
950
+ def draw_splines(dc)
951
+ if Wx.has_feature?(:USE_SPLINES)
952
+ dc.draw_text("Some splines", dc.from_dip(10), dc.from_dip(5))
953
+
954
+ # values are hardcoded rather than randomly generated
955
+ # so the output can be compared between native
956
+ # implementations on platforms with different random
957
+ # generators
958
+
959
+ _R = dc.from_dip(300)
960
+ center = Wx::Point.new(_R + dc.from_dip(20), _R + dc.from_dip(20))
961
+ angles = [ 0, 10, 33, 77, 13, 145, 90 ]
962
+ radii = [ 100 , 59, 85, 33, 90 ]
963
+ numPoints = 200
964
+ pts = ::Array.new(numPoints, nil)
965
+ # wxPoint pts[numPoints]
966
+
967
+ # background spline calculation
968
+ radius_pos = 0
969
+ angle_pos = 0
970
+ angle = 0
971
+ numPoints.times do |i|
972
+ angle += angles[ angle_pos ]
973
+ r = _R * radii[ radius_pos ] / 100
974
+ pts[i] = [center.x + (r * Math.cos((angle * Math::PI)/180)).to_i,
975
+ center.y + (r * Math.sin((angle * Math::PI)/180)).to_i]
976
+ angle_pos += 1
977
+ angle_pos = 0 if angle_pos >= angles.size
978
+ radius_pos += 1
979
+ radius_pos = 0 if radius_pos >= radii.size
980
+ end
981
+
982
+ # background spline drawing
983
+ dc.set_pen(Wx::RED_PEN)
984
+ dc.draw_spline(pts)
985
+
986
+ # less detailed spline calculation
987
+ letters = ::Array.new(4) { ::Array.new(5) }
988
+ # w
989
+ letters[0][0] = Wx::Point.new( 0,1) # O O
990
+ letters[0][1] = Wx::Point.new( 1,3) # * *
991
+ letters[0][2] = Wx::Point.new( 2,2) # * O *
992
+ letters[0][3] = Wx::Point.new( 3,3) # * * * *
993
+ letters[0][4] = Wx::Point.new( 4,1) # O O
994
+ # x1
995
+ letters[1][0] = Wx::Point.new( 5,1) # O*O
996
+ letters[1][1] = Wx::Point.new( 6,1) # *
997
+ letters[1][2] = Wx::Point.new( 7,2) # O
998
+ letters[1][3] = Wx::Point.new( 8,3) # *
999
+ letters[1][4] = Wx::Point.new( 9,3) # O*O
1000
+ # x2
1001
+ letters[2][0] = Wx::Point.new( 5,3) # O*O
1002
+ letters[2][1] = Wx::Point.new( 6,3) # *
1003
+ letters[2][2] = Wx::Point.new( 7,2) # O
1004
+ letters[2][3] = Wx::Point.new( 8,1) # *
1005
+ letters[2][4] = Wx::Point.new( 9,1) # O*O
1006
+ # W
1007
+ letters[3][0] = Wx::Point.new(10,0) # O O
1008
+ letters[3][1] = Wx::Point.new(11,3) # * *
1009
+ letters[3][2] = Wx::Point.new(12,1) # * O *
1010
+ letters[3][3] = Wx::Point.new(13,3) # * * * *
1011
+ letters[3][4] = Wx::Point.new(14,0) # O O
1012
+
1013
+ dx = 2 * _R / letters[3][4].x
1014
+ h = [ (-_R/2), 0, _R/4, _R/2 ]
1015
+
1016
+ letters.each_with_index do |row, m|
1017
+ row.each_with_index do |pt, n|
1018
+ pt.x = center.x - _R + (pt.x * dx)
1019
+ pt.y = center.y + h[pt.y]
1020
+ end
1021
+
1022
+ dc.set_pen(Wx::Pen.new(Wx::BLUE, 1, Wx::PENSTYLE_DOT))
1023
+ dc.draw_lines(letters[m])
1024
+ dc.set_pen(Wx::Pen.new(Wx::BLACK, 4))
1025
+ dc.draw_spline(letters[m])
1026
+ end
1027
+
1028
+ else
1029
+ dc.draw_text('Splines not supported.', 10, 5)
1030
+ end
1031
+ end
1032
+
1033
+ def draw_default(dc)
1034
+ # Draw circle centered at the origin, then flood fill it with a different
1035
+ # color. Done with a Wx::MemoryDC because Blit (used by generic
1036
+ # Wx.do_flood_fill) from a window that is being painted gives unpredictable
1037
+ # results on WXGTK
1038
+ img = Wx::Image.new(dc.from_dip(21), dc.from_dip(21), false)
1039
+ img.clear(1)
1040
+ bmp = img.to_bitmap
1041
+ Wx::MemoryDC.draw_on(bmp) do |mdc|
1042
+ mdc.set_brush(dc.get_brush)
1043
+ mdc.set_pen(dc.get_pen)
1044
+ mdc.draw_circle(dc.from_dip(10), dc.from_dip(10), dc.from_dip(10))
1045
+ c = Wx::Colour.new
1046
+ if mdc.get_pixel(dc.from_dip(11), dc.from_dip(11), c)
1047
+ mdc.set_brush(Wx::Brush.new(Wx::Colour.new(128, 128, 0)))
1048
+ mdc.flood_fill(dc.from_dip(11), dc.from_dip(11), c, Wx::FLOOD_SURFACE)
1049
+ end
1050
+ end
1051
+ bmp.set_mask(Wx::Mask.new(bmp, Wx::Colour.new(1, 1, 1)))
1052
+ dc.draw_bitmap(bmp, dc.from_dip(-10), dc.from_dip(-10), true)
1053
+
1054
+ dc.draw_check_mark(dc.from_dip(5), dc.from_dip(80), dc.from_dip(15), dc.from_dip(15))
1055
+ dc.draw_check_mark(dc.from_dip(25), dc.from_dip(80), dc.from_dip(30), dc.from_dip(30))
1056
+ dc.draw_check_mark(dc.from_dip(60), dc.from_dip(80), dc.from_dip(60), dc.from_dip(60))
1057
+
1058
+ # this is the test for "blitting bitmap into DC damages selected brush" bug
1059
+ rectSize = @std_icon.width + dc.from_dip(10)
1060
+ x = dc.from_dip(100)
1061
+ dc.set_pen(Wx::TRANSPARENT_PEN)
1062
+ dc.set_brush(Wx::GREEN_BRUSH)
1063
+ dc.draw_rectangle(x, dc.from_dip(10), rectSize, rectSize)
1064
+ dc.draw_bitmap(@std_icon.to_bitmap, x + dc.from_dip(5), dc.from_dip(15), true)
1065
+ x += rectSize + dc.from_dip(10)
1066
+ dc.draw_rectangle(x, dc.from_dip(10), rectSize, rectSize)
1067
+ dc.draw_icon(@std_icon, x + dc.from_dip(5), dc.from_dip(15))
1068
+ x += rectSize + dc.from_dip(10)
1069
+ dc.draw_rectangle(x, dc.from_dip(10), rectSize, rectSize)
1070
+
1071
+ # test for "transparent" bitmap drawing (it intersects with the last
1072
+ # rectangle above)
1073
+ #dc.set_brush(Wx::TRANSPARENT_BRUSH)
1074
+
1075
+ dc.draw_bitmap(@smile_bmp, x + rectSize - dc.from_dip(20), rectSize - dc.from_dip(10), true) if (@smile_bmp.ok?)
1076
+
1077
+ dc.set_brush(Wx::BLACK_BRUSH)
1078
+ dc.draw_rectangle(0, dc.from_dip(160), dc.from_dip(1000), dc.from_dip(300))
1079
+
1080
+ # draw lines
1081
+ bitmap = Wx::Bitmap.new(dc.from_dip([20,70]))
1082
+ Wx::MemoryDC.draw_on(bitmap) do |memdc|
1083
+ memdc.set_brush(Wx::BLACK_BRUSH)
1084
+ memdc.set_pen(Wx::WHITE_PEN)
1085
+ memdc.draw_rectangle(0, 0, dc.from_dip(20), dc.from_dip(70))
1086
+ memdc.draw_line( dc.from_dip(10), 0, dc.from_dip(10), dc.from_dip(70) )
1087
+
1088
+ # to the right
1089
+ pen = Wx::RED_PEN
1090
+ memdc.set_pen(pen)
1091
+ memdc.draw_line(dc.from_dip(10), dc.from_dip(5), dc.from_dip(10), dc.from_dip(5) )
1092
+ memdc.draw_line(dc.from_dip(10), dc.from_dip(10), dc.from_dip(11), dc.from_dip(10))
1093
+ memdc.draw_line(dc.from_dip(10), dc.from_dip(15), dc.from_dip(12), dc.from_dip(15))
1094
+ memdc.draw_line(dc.from_dip(10), dc.from_dip(20), dc.from_dip(13), dc.from_dip(20))
1095
+
1096
+ # memdc.set_pen(Wx::RED_PEN)
1097
+ # memdc.draw_line( dc.from_dip(12),dc.from_dip( 5),dc.from_dip(12),dc.from_dip( 5) )
1098
+ # memdc.draw_line( dc.from_dip(12),dc.from_dip(10),dc.from_dip(13),dc.from_dip(10) )
1099
+ # memdc.draw_line( dc.from_dip(12),dc.from_dip(15),dc.from_dip(14),dc.from_dip(15) )
1100
+ # memdc.draw_line( dc.from_dip(12),dc.from_dip(20),dc.from_dip(15),dc.from_dip(20) )
1101
+
1102
+ # same to the left
1103
+ memdc.draw_line(dc.from_dip(10), dc.from_dip(25), dc.from_dip(10), dc.from_dip(25))
1104
+ memdc.draw_line(dc.from_dip(10), dc.from_dip(30), dc.from_dip(9), dc.from_dip(30))
1105
+ memdc.draw_line(dc.from_dip(10), dc.from_dip(35), dc.from_dip(8), dc.from_dip(35))
1106
+ memdc.draw_line(dc.from_dip(10), dc.from_dip(40), dc.from_dip(7), dc.from_dip(40))
1107
+
1108
+ # XOR draw lines
1109
+ dc.set_pen(Wx::WHITE_PEN)
1110
+ memdc.set_logical_function(Wx::INVERT)
1111
+ memdc.set_pen(Wx::WHITE_PEN)
1112
+ memdc.draw_line(dc.from_dip(10), dc.from_dip(50), dc.from_dip(10), dc.from_dip(50))
1113
+ memdc.draw_line(dc.from_dip(10), dc.from_dip(55), dc.from_dip(11), dc.from_dip(55))
1114
+ memdc.draw_line(dc.from_dip(10), dc.from_dip(60), dc.from_dip(12), dc.from_dip(60))
1115
+ memdc.draw_line(dc.from_dip(10), dc.from_dip(65), dc.from_dip(13), dc.from_dip(65))
1116
+
1117
+ memdc.draw_line(dc.from_dip(12), dc.from_dip(50), dc.from_dip(12), dc.from_dip(50))
1118
+ memdc.draw_line(dc.from_dip(12), dc.from_dip(55), dc.from_dip(13), dc.from_dip(55))
1119
+ memdc.draw_line(dc.from_dip(12), dc.from_dip(60), dc.from_dip(14), dc.from_dip(60))
1120
+ memdc.draw_line(dc.from_dip(12), dc.from_dip(65), dc.from_dip(15), dc.from_dip(65))
1121
+ end
1122
+ dc.draw_bitmap(bitmap, dc.from_dip(10), dc.from_dip(170))
1123
+ image = bitmap.convert_to_image
1124
+ image.rescale(dc.from_dip(60), dc.from_dip(210))
1125
+ bitmap = image.to_bitmap
1126
+ dc.draw_bitmap(bitmap, dc.from_dip(50), dc.from_dip(170))
1127
+
1128
+ # test the rectangle outline drawing - there should be one pixel between
1129
+ # the rect and the lines
1130
+ dc.set_pen(Wx::WHITE_PEN)
1131
+ dc.set_brush(Wx::TRANSPARENT_BRUSH)
1132
+ dc.draw_rectangle(dc.from_dip(150), dc.from_dip(170), dc.from_dip(49), dc.from_dip(29))
1133
+ dc.draw_rectangle(dc.from_dip(200), dc.from_dip(170), dc.from_dip(49), dc.from_dip(29))
1134
+ dc.set_pen(Wx::WHITE_PEN)
1135
+ dc.draw_line(dc.from_dip(250), dc.from_dip(210), dc.from_dip(250), dc.from_dip(170))
1136
+ dc.draw_line(dc.from_dip(260), dc.from_dip(200), dc.from_dip(150), dc.from_dip(200))
1137
+
1138
+ # test the rectangle filled drawing - there should be one pixel between
1139
+ # the rect and the lines
1140
+ dc.set_pen(Wx::TRANSPARENT_PEN)
1141
+ dc.set_brush(Wx::WHITE_BRUSH)
1142
+ dc.draw_rectangle(dc.from_dip(300), dc.from_dip(170), dc.from_dip(49), dc.from_dip(29))
1143
+ dc.draw_rectangle(dc.from_dip(350), dc.from_dip(170), dc.from_dip(49), dc.from_dip(29))
1144
+ dc.set_pen(Wx::WHITE_PEN)
1145
+ dc.draw_line(dc.from_dip(400), dc.from_dip(170), dc.from_dip(400), dc.from_dip(210))
1146
+ dc.draw_line(dc.from_dip(300), dc.from_dip(200), dc.from_dip(410), dc.from_dip(200))
1147
+
1148
+ # a few more tests of this kind
1149
+ dc.set_pen(Wx::RED_PEN)
1150
+ dc.set_brush(Wx::WHITE_BRUSH)
1151
+ dc.draw_rectangle(dc.from_dip(300), dc.from_dip(220), dc.from_dip(1), dc.from_dip(1))
1152
+ dc.draw_rectangle(dc.from_dip(310), dc.from_dip(220), dc.from_dip(2), dc.from_dip(2))
1153
+ dc.draw_rectangle(dc.from_dip(320), dc.from_dip(220), dc.from_dip(3), dc.from_dip(3))
1154
+ dc.draw_rectangle(dc.from_dip(330), dc.from_dip(220), dc.from_dip(4), dc.from_dip(4))
1155
+
1156
+ dc.set_pen(Wx::TRANSPARENT_PEN)
1157
+ dc.set_brush(Wx::WHITE_BRUSH)
1158
+ dc.draw_rectangle(dc.from_dip(300), dc.from_dip(230), dc.from_dip(1), dc.from_dip(1))
1159
+ dc.draw_rectangle(dc.from_dip(310), dc.from_dip(230), dc.from_dip(2), dc.from_dip(2))
1160
+ dc.draw_rectangle(dc.from_dip(320), dc.from_dip(230), dc.from_dip(3), dc.from_dip(3))
1161
+ dc.draw_rectangle(dc.from_dip(330), dc.from_dip(230), dc.from_dip(4), dc.from_dip(4))
1162
+
1163
+ # and now for filled rect with outline
1164
+ dc.set_pen(Wx::RED_PEN)
1165
+ dc.set_brush(Wx::WHITE_BRUSH)
1166
+ dc.draw_rectangle(dc.from_dip(500), dc.from_dip(170), dc.from_dip(49), dc.from_dip(29))
1167
+ dc.draw_rectangle(dc.from_dip(550), dc.from_dip(170), dc.from_dip(49), dc.from_dip(29))
1168
+ dc.set_pen(Wx::WHITE_PEN)
1169
+ dc.draw_line(dc.from_dip(600), dc.from_dip(170), dc.from_dip(600), dc.from_dip(210))
1170
+ dc.draw_line(dc.from_dip(500), dc.from_dip(200), dc.from_dip(610), dc.from_dip(200))
1171
+
1172
+ # test the rectangle outline drawing - there should be one pixel between
1173
+ # the rect and the lines
1174
+ dc.set_pen(Wx::WHITE_PEN)
1175
+ dc.set_brush( Wx::TRANSPARENT_BRUSH )
1176
+ dc.draw_rounded_rectangle(dc.from_dip(150), dc.from_dip(270), dc.from_dip(49), dc.from_dip(29), dc.from_dip(6))
1177
+ dc.draw_rounded_rectangle(dc.from_dip(200), dc.from_dip(270), dc.from_dip(49), dc.from_dip(29), dc.from_dip(6))
1178
+ dc.set_pen(Wx::WHITE_PEN)
1179
+ dc.draw_line(dc.from_dip(250), dc.from_dip(270), dc.from_dip(250), dc.from_dip(310))
1180
+ dc.draw_line(dc.from_dip(150), dc.from_dip(300), dc.from_dip(260), dc.from_dip(300))
1181
+
1182
+ # test the rectangle filled drawing - there should be one pixel between
1183
+ # the rect and the lines
1184
+ dc.set_pen(Wx::TRANSPARENT_PEN)
1185
+ dc.set_brush( Wx::WHITE_BRUSH )
1186
+ dc.draw_rounded_rectangle(dc.from_dip(300), dc.from_dip(270), dc.from_dip(49), dc.from_dip(29), dc.from_dip(6))
1187
+ dc.draw_rounded_rectangle(dc.from_dip(350), dc.from_dip(270), dc.from_dip(49), dc.from_dip(29), dc.from_dip(6))
1188
+ dc.set_pen(Wx::WHITE_PEN)
1189
+ dc.draw_line(dc.from_dip(400), dc.from_dip(270), dc.from_dip(400), dc.from_dip(310))
1190
+ dc.draw_line(dc.from_dip(300), dc.from_dip(300), dc.from_dip(410), dc.from_dip(300))
1191
+
1192
+ # Added by JACS to demonstrate bizarre behaviour.
1193
+ # With a size of 70, we get a missing red RHS,
1194
+ # and the height is too small, so we get yellow
1195
+ # showing. With a size of 40, it draws as expected:
1196
+ # it just shows a white rectangle with red outline.
1197
+ totalWidth = dc.from_dip(70)
1198
+ totalHeight = dc.from_dip(70)
1199
+ bitmap2 = Wx::Bitmap.new(totalWidth, totalHeight)
1200
+
1201
+ Wx::MemoryDC.draw_on(bitmap2) do |memdc2|
1202
+ memdc2.set_background(Wx::YELLOW_BRUSH)
1203
+ memdc2.clear
1204
+
1205
+ # Now draw a white rectangle with red outline. It should
1206
+ # entirely eclipse the yellow background.
1207
+ memdc2.set_pen(Wx::RED_PEN)
1208
+ memdc2.set_brush(Wx::WHITE_BRUSH)
1209
+
1210
+ memdc2.draw_rectangle(0, 0, totalWidth, totalHeight)
1211
+ end
1212
+
1213
+ dc.draw_bitmap(bitmap2, dc.from_dip(500), dc.from_dip(270))
1214
+
1215
+ # Repeat, but draw directly on dc
1216
+ # Draw a yellow rectangle filling the bitmap
1217
+
1218
+ x = dc.from_dip(600)
1219
+ y = dc.from_dip(270)
1220
+ dc.set_pen(Wx::YELLOW_PEN)
1221
+ dc.set_brush(Wx::YELLOW_BRUSH)
1222
+ dc.draw_rectangle(x, y, totalWidth, totalHeight)
1223
+
1224
+ # Now draw a white rectangle with red outline. It should
1225
+ # entirely eclipse the yellow background.
1226
+ dc.set_pen(Wx::RED_PEN)
1227
+ dc.set_brush(Wx::WHITE_BRUSH)
1228
+
1229
+ dc.draw_rectangle(x, y, totalWidth, totalHeight)
1230
+ end
1231
+
1232
+ def draw_gradients(dc)
1233
+ text_height = dc.get_char_height
1234
+
1235
+ # LHS: linear
1236
+ r = Wx::Rect.new(dc.from_dip(10), dc.from_dip(10), dc.from_dip(50), dc.from_dip(50))
1237
+ dc.draw_text("Wx::RIGHT", r.x, r.y)
1238
+ r.offset!(0, text_height)
1239
+ dc.gradient_fill_linear(r, Wx::WHITE, Wx::BLUE, Wx::RIGHT)
1240
+
1241
+ r.offset!(0, r.height + dc.from_dip(10))
1242
+ dc.draw_text("Wx::LEFT", r.x, r.y)
1243
+ r.offset!(0, text_height)
1244
+ dc.gradient_fill_linear(r, Wx::WHITE, Wx::BLUE, Wx::LEFT)
1245
+
1246
+ r.offset!(0, r.height + dc.from_dip(10))
1247
+ dc.draw_text("Wx::DOWN", r.x, r.y)
1248
+ r.offset!(0, text_height)
1249
+ dc.gradient_fill_linear(r, Wx::WHITE, Wx::BLUE, Wx::DOWN)
1250
+
1251
+ r.offset!(0, r.height + dc.from_dip(10))
1252
+ dc.draw_text("Wx::UP", r.x, r.y)
1253
+ r.offset!(0, text_height)
1254
+ dc.gradient_fill_linear(r, Wx::WHITE, Wx::BLUE, Wx::UP)
1255
+
1256
+ gfr = Wx::Rect.new.assign(r)
1257
+
1258
+ # RHS: concentric
1259
+ r = Wx::Rect.new(dc.from_dip(200), dc.from_dip(10), dc.from_dip(50), dc.from_dip(50))
1260
+ dc.draw_text("Blue inside", r.x, r.y)
1261
+ r.offset!(0, text_height)
1262
+ dc.gradient_fill_concentric(r, Wx::BLUE, Wx::WHITE)
1263
+
1264
+ r.offset!(0, r.height + dc.from_dip(10))
1265
+ dc.draw_text("White inside", r.x, r.y)
1266
+ r.offset!(0, text_height)
1267
+ dc.gradient_fill_concentric(r, Wx::WHITE, Wx::BLUE)
1268
+
1269
+ r.offset!(0, r.height + dc.from_dip(10))
1270
+ dc.draw_text("Blue in top left corner", r.x, r.y)
1271
+ r.offset!(0, text_height)
1272
+ dc.gradient_fill_concentric(r, Wx::BLUE, Wx::WHITE, [0, 0])
1273
+
1274
+ r.offset!(0, r.height + dc.from_dip(10))
1275
+ dc.draw_text("Blue in bottom right corner", r.x, r.y)
1276
+ r.offset!(0, text_height)
1277
+ dc.gradient_fill_concentric(r, Wx::BLUE, Wx::WHITE, [r.width, r.height])
1278
+
1279
+ # check that the area filled by the gradient is exactly the interior of
1280
+ # the rectangle
1281
+ r.x = dc.from_dip(350)
1282
+ r.y = dc.from_dip(30)
1283
+ dc.draw_text("The interior should be filled but", r.x, r.y)
1284
+ r.y += text_height
1285
+ dc.draw_text(" the red border should remain visible:", r.x, r.y)
1286
+ r.y += text_height
1287
+
1288
+ r.width =
1289
+ r.height = dc.from_dip(50)
1290
+ r2 = Wx::Rect.new.assign(r)
1291
+ r2.x += dc.from_dip(60)
1292
+ r3 = Wx::Rect.new.assign(r)
1293
+ r3.y += dc.from_dip(60)
1294
+ r4 = Wx::Rect.new.assign(r2)
1295
+ r4.y += dc.from_dip(60)
1296
+ dc.set_pen(Wx::RED_PEN)
1297
+ dc.draw_rectangle(r)
1298
+ r.deflate!(1)
1299
+ dc.gradient_fill_linear(r, Wx::GREEN, Wx::BLACK, Wx::NORTH)
1300
+ dc.draw_rectangle(r2)
1301
+ r2.deflate!(1)
1302
+ dc.gradient_fill_linear(r2, Wx::BLACK, Wx::GREEN, Wx::SOUTH)
1303
+ dc.draw_rectangle(r3)
1304
+ r3.deflate!(1)
1305
+ dc.gradient_fill_linear(r3, Wx::GREEN, Wx::BLACK, Wx::EAST)
1306
+ dc.draw_rectangle(r4)
1307
+ r4.deflate!(1)
1308
+ dc.gradient_fill_linear(r4, Wx::BLACK, Wx::GREEN, Wx::WEST)
1309
+
1310
+ if Wx.has_feature?(:USE_GRAPHICS_CONTEXT)
1311
+ if @renderer
1312
+ gc = dc.get_graphics_context
1313
+ # double boxX, boxY, boxWidth, boxHeight
1314
+
1315
+ gfr.offset!(0, gfr.height + gc.from_dip(10))
1316
+ dc.draw_text("Linear Gradient with Stops", gfr.x, gfr.y)
1317
+ gfr.offset!(0, text_height)
1318
+
1319
+ stops = Wx::GraphicsGradientStops.new(Wx::RED, Wx::BLUE)
1320
+ stops.add(Wx::Colour.new(255,255,0), 0.33)
1321
+ stops.add(Wx::GREEN, 0.67)
1322
+
1323
+ gc.set_brush(gc.create_linear_gradient_brush(gfr.x, gfr.y,
1324
+ gfr.x + gfr.width, gfr.y + gfr.height,
1325
+ stops))
1326
+ pth = gc.create_path
1327
+ pth.move_to_point(gfr.x,gfr.y)
1328
+ pth.add_line_to_point(gfr.x + gfr.width,gfr.y)
1329
+ pth.add_line_to_point(gfr.x + gfr.width,gfr.y+gfr.height)
1330
+ pth.add_line_to_point(gfr.x,gfr.y+gfr.height)
1331
+ pth.close_subpath
1332
+ gc.fill_path(pth)
1333
+ boxX, boxY, boxWidth, boxHeight = pth.get_box
1334
+ dc.calc_bounding_box(boxX.round, boxY.round)
1335
+ dc.calc_bounding_box((boxX+boxWidth).round, (boxY+boxHeight).round)
1336
+
1337
+ simpleStops = Wx::GraphicsGradientStops.new(Wx::RED, Wx::BLUE)
1338
+
1339
+ gfr.offset!(0, gfr.height + gc.from_dip(10))
1340
+ dc.draw_text("Radial Gradient from Red to Blue without intermediary Stops",
1341
+ gfr.x, gfr.y)
1342
+ gfr.offset!(0, text_height)
1343
+
1344
+ gc.set_brush(gc.create_radial_gradient_brush(gfr.x + gfr.width / 2,
1345
+ gfr.y + gfr.height / 2,
1346
+ gfr.x + gfr.width / 2,
1347
+ gfr.y + gfr.height / 2,
1348
+ gfr.width / 2,
1349
+ simpleStops))
1350
+
1351
+ pth = gc.create_path
1352
+ pth.move_to_point(gfr.x,gfr.y)
1353
+ pth.add_line_to_point(gfr.x + gfr.width,gfr.y)
1354
+ pth.add_line_to_point(gfr.x + gfr.width,gfr.y+gfr.height)
1355
+ pth.add_line_to_point(gfr.x,gfr.y+gfr.height)
1356
+ pth.close_subpath
1357
+ gc.fill_path(pth)
1358
+ boxX, boxY, boxWidth, boxHeight = pth.get_box
1359
+ dc.calc_bounding_box(boxX.round, boxY.round)
1360
+ dc.calc_bounding_box((boxX+boxWidth).round, (boxY+boxHeight).round)
1361
+
1362
+ gfr.offset!(0, gfr.height + gc.from_dip(10))
1363
+ dc.draw_text("Radial Gradient from Red to Blue with Yellow and Green Stops",
1364
+ gfr.x, gfr.y)
1365
+ gfr.offset!(0, text_height)
1366
+
1367
+ gc.set_brush(gc.create_radial_gradient_brush(gfr.x + gfr.width / 2,
1368
+ gfr.y + gfr.height / 2,
1369
+ gfr.x + gfr.width / 2,
1370
+ gfr.y + gfr.height / 2,
1371
+ gfr.width / 2,
1372
+ stops))
1373
+ pth = gc.create_path
1374
+ pth.move_to_point(gfr.x,gfr.y)
1375
+ pth.add_line_to_point(gfr.x + gfr.width,gfr.y)
1376
+ pth.add_line_to_point(gfr.x + gfr.width,gfr.y+gfr.height)
1377
+ pth.add_line_to_point(gfr.x,gfr.y+gfr.height)
1378
+ pth.close_subpath
1379
+ gc.fill_path(pth)
1380
+ boxX, boxY, boxWidth, boxHeight = pth.get_box
1381
+ dc.calc_bounding_box(boxX.round, boxY.round)
1382
+ dc.calc_bounding_box((boxX+boxWidth).round, (boxY+boxHeight).round)
1383
+
1384
+ gfr.offset!(0, gfr.height + gc.from_dip(10))
1385
+ dc.draw_text("Linear Gradient with Stops and Gaps", gfr.x, gfr.y)
1386
+ gfr.offset!(0, text_height)
1387
+
1388
+ stops = Wx::GraphicsGradientStops.new(Wx::RED, Wx::BLUE)
1389
+ stops.add(Wx::Colour.new(255,255,0), 0.33)
1390
+ stops.add(Wx::TRANSPARENT_COLOUR, 0.33)
1391
+ stops.add(Wx::TRANSPARENT_COLOUR, 0.67)
1392
+ stops.add(Wx::GREEN, 0.67)
1393
+
1394
+ gc.set_brush(gc.create_linear_gradient_brush(gfr.x, gfr.y + gfr.height,
1395
+ gfr.x + gfr.width, gfr.y,
1396
+ stops))
1397
+ pth = gc.create_path
1398
+ pth.move_to_point(gfr.x,gfr.y)
1399
+ pth.add_line_to_point(gfr.x + gfr.width,gfr.y)
1400
+ pth.add_line_to_point(gfr.x + gfr.width,gfr.y+gfr.height)
1401
+ pth.add_line_to_point(gfr.x,gfr.y+gfr.height)
1402
+ pth.close_subpath
1403
+ gc.fill_path(pth)
1404
+ boxX, boxY, boxWidth, boxHeight = pth.get_box
1405
+ dc.calc_bounding_box(boxX.round, boxY.round)
1406
+ dc.calc_bounding_box((boxX+boxWidth).round, (boxY+boxHeight).round)
1407
+
1408
+ gfr.offset!(0, gfr.height + gc.from_dip(10))
1409
+ dc.draw_text("Radial Gradient with Stops and Gaps", gfr.x, gfr.y)
1410
+ gfr.offset!(0, text_height)
1411
+
1412
+ gc.set_brush(gc.create_radial_gradient_brush(gfr.x + gfr.width / 2,
1413
+ gfr.y + gfr.height / 2,
1414
+ gfr.x + gfr.width / 2,
1415
+ gfr.y + gfr.height / 2,
1416
+ gfr.width / 2,
1417
+ stops))
1418
+ pth = gc.create_path
1419
+ pth.move_to_point(gfr.x,gfr.y)
1420
+ pth.add_line_to_point(gfr.x + gfr.width,gfr.y)
1421
+ pth.add_line_to_point(gfr.x + gfr.width,gfr.y+gfr.height)
1422
+ pth.add_line_to_point(gfr.x,gfr.y+gfr.height)
1423
+ pth.close_subpath
1424
+ gc.fill_path(pth)
1425
+ boxX, boxY, boxWidth, boxHeight = pth.get_box
1426
+ dc.calc_bounding_box(boxX.round, boxY.round)
1427
+ dc.calc_bounding_box((boxX+boxWidth).round, (boxY+boxHeight).round)
1428
+
1429
+ gfr.offset!(0, gfr.height + gc.from_dip(10))
1430
+ dc.draw_text("Gradients with Stops and Transparency", gfr.x, gfr.y)
1431
+ gfr.offset!(0, text_height)
1432
+
1433
+ stops = Wx::GraphicsGradientStops.new(Wx::RED, Wx::TRANSPARENT_COLOUR)
1434
+ stops.add(Wx::RED, 0.33)
1435
+ stops.add(Wx::TRANSPARENT_COLOUR, 0.33)
1436
+ stops.add(Wx::TRANSPARENT_COLOUR, 0.67)
1437
+ stops.add(Wx::BLUE, 0.67)
1438
+ stops.add(Wx::BLUE, 1.0)
1439
+
1440
+ pth = gc.create_path
1441
+ pth.move_to_point(gfr.x,gfr.y)
1442
+ pth.add_line_to_point(gfr.x + gfr.width,gfr.y)
1443
+ pth.add_line_to_point(gfr.x + gfr.width,gfr.y+gfr.height)
1444
+ pth.add_line_to_point(gfr.x,gfr.y+gfr.height)
1445
+ pth.close_subpath
1446
+
1447
+ gc.set_brush(gc.create_radial_gradient_brush(gfr.x + gfr.width / 2,
1448
+ gfr.y + gfr.height / 2,
1449
+ gfr.x + gfr.width / 2,
1450
+ gfr.y + gfr.height / 2,
1451
+ gfr.width / 2,
1452
+ stops))
1453
+ gc.fill_path(pth)
1454
+
1455
+ stops = Wx::GraphicsGradientStops.new(Wx::Colour.new(255,0,0, 128), Wx::Colour.new(0,0,255, 128))
1456
+ stops.add(Wx::Colour.new(255,255,0,128), 0.33)
1457
+ stops.add(Wx::Colour.new(0,255,0,128), 0.67)
1458
+
1459
+ gc.set_brush(gc.create_linear_gradient_brush(gfr.x, gfr.y,
1460
+ gfr.x + gfr.width, gfr.y,
1461
+ stops))
1462
+ gc.fill_path(pth)
1463
+ boxX, boxY, boxWidth, boxHeight = pth.get_box
1464
+ dc.calc_bounding_box(boxX.round, boxY.round)
1465
+ dc.calc_bounding_box((boxX+boxWidth).round, (boxY+boxHeight).round)
1466
+
1467
+ gfr.offset!(0, gfr.height + gc.from_dip(10))
1468
+ dc.draw_text("Stroked path with a gradient pen", gfr.x, gfr.y)
1469
+ gfr.offset!(0, text_height)
1470
+
1471
+ pth = gc.create_path
1472
+ pth.move_to_point(gfr.x + gfr.width/2, gfr.y)
1473
+ pth.add_line_to_point(gfr.x + gfr.width, gfr.y + gfr.height/2)
1474
+ pth.add_line_to_point(gfr.x + gfr.width/2, gfr.y + gfr.height)
1475
+ pth.add_line_to_point(gfr.x, gfr.y + gfr.height/2)
1476
+ pth.close_subpath
1477
+
1478
+ stops = Wx::GraphicsGradientStops.new(Wx::RED, Wx::BLUE)
1479
+ stops.add(Wx::Colour.new(255,255,0), 0.33)
1480
+ stops.add(Wx::GREEN, 0.67)
1481
+
1482
+ pen = gc.create_pen(
1483
+ Wx::GraphicsPenInfo.new(Wx::Colour.new(0,0,0)).width(6).join(Wx::JOIN_BEVEL).linear_gradient(
1484
+ gfr.x + gfr.width/2, gfr.y,
1485
+ gfr.x + gfr.width/2, gfr.y + gfr.height,
1486
+ stops))
1487
+ gc.set_pen(pen)
1488
+ gc.stroke_path(pth)
1489
+ end
1490
+ end # USE_GRAPHICS_CONTEXT
1491
+ end
1492
+
1493
+ SYSTEM_COLOURS = {
1494
+ Wx::SYS_COLOUR_3DDKSHADOW => "Wx::SYS_COLOUR_3DDKSHADOW" ,
1495
+ Wx::SYS_COLOUR_3DLIGHT => "Wx::SYS_COLOUR_3DLIGHT" ,
1496
+ Wx::SYS_COLOUR_ACTIVEBORDER => "Wx::SYS_COLOUR_ACTIVEBORDER" ,
1497
+ Wx::SYS_COLOUR_ACTIVECAPTION => "Wx::SYS_COLOUR_ACTIVECAPTION" ,
1498
+ Wx::SYS_COLOUR_APPWORKSPACE => "Wx::SYS_COLOUR_APPWORKSPACE" ,
1499
+ Wx::SYS_COLOUR_BTNFACE => "Wx::SYS_COLOUR_BTNFACE" ,
1500
+ Wx::SYS_COLOUR_BTNHIGHLIGHT => "Wx::SYS_COLOUR_BTNHIGHLIGHT" ,
1501
+ Wx::SYS_COLOUR_BTNSHADOW => "Wx::SYS_COLOUR_BTNSHADOW" ,
1502
+ Wx::SYS_COLOUR_BTNTEXT => "Wx::SYS_COLOUR_BTNTEXT" ,
1503
+ Wx::SYS_COLOUR_CAPTIONTEXT => "Wx::SYS_COLOUR_CAPTIONTEXT" ,
1504
+ Wx::SYS_COLOUR_DESKTOP => "Wx::SYS_COLOUR_DESKTOP" ,
1505
+ Wx::SYS_COLOUR_GRADIENTACTIVECAPTION => "Wx::SYS_COLOUR_GRADIENTACTIVECAPTION" ,
1506
+ Wx::SYS_COLOUR_GRADIENTINACTIVECAPTION => "Wx::SYS_COLOUR_GRADIENTINACTIVECAPTION" ,
1507
+ Wx::SYS_COLOUR_GRAYTEXT => "Wx::SYS_COLOUR_GRAYTEXT" ,
1508
+ Wx::SYS_COLOUR_HIGHLIGHTTEXT => "Wx::SYS_COLOUR_HIGHLIGHTTEXT" ,
1509
+ Wx::SYS_COLOUR_HIGHLIGHT => "Wx::SYS_COLOUR_HIGHLIGHT" ,
1510
+ Wx::SYS_COLOUR_HOTLIGHT => "Wx::SYS_COLOUR_HOTLIGHT" ,
1511
+ Wx::SYS_COLOUR_INACTIVEBORDER => "Wx::SYS_COLOUR_INACTIVEBORDER" ,
1512
+ Wx::SYS_COLOUR_INACTIVECAPTIONTEXT => "Wx::SYS_COLOUR_INACTIVECAPTIONTEXT" ,
1513
+ Wx::SYS_COLOUR_INACTIVECAPTION => "Wx::SYS_COLOUR_INACTIVECAPTION" ,
1514
+ Wx::SYS_COLOUR_INFOBK => "Wx::SYS_COLOUR_INFOBK" ,
1515
+ Wx::SYS_COLOUR_INFOTEXT => "Wx::SYS_COLOUR_INFOTEXT" ,
1516
+ Wx::SYS_COLOUR_LISTBOXHIGHLIGHTTEXT => "Wx::SYS_COLOUR_LISTBOXHIGHLIGHTTEXT" ,
1517
+ Wx::SYS_COLOUR_LISTBOXTEXT => "Wx::SYS_COLOUR_LISTBOXTEXT" ,
1518
+ Wx::SYS_COLOUR_LISTBOX => "Wx::SYS_COLOUR_LISTBOX" ,
1519
+ Wx::SYS_COLOUR_MENUBAR => "Wx::SYS_COLOUR_MENUBAR" ,
1520
+ Wx::SYS_COLOUR_MENUHILIGHT => "Wx::SYS_COLOUR_MENUHILIGHT" ,
1521
+ Wx::SYS_COLOUR_MENUTEXT => "Wx::SYS_COLOUR_MENUTEXT" ,
1522
+ Wx::SYS_COLOUR_MENU => "Wx::SYS_COLOUR_MENU" ,
1523
+ Wx::SYS_COLOUR_SCROLLBAR => "Wx::SYS_COLOUR_SCROLLBAR" ,
1524
+ Wx::SYS_COLOUR_WINDOWFRAME => "Wx::SYS_COLOUR_WINDOWFRAME" ,
1525
+ Wx::SYS_COLOUR_WINDOWTEXT => "Wx::SYS_COLOUR_WINDOWTEXT" ,
1526
+ Wx::SYS_COLOUR_WINDOW => "Wx::SYS_COLOUR_WINDOW"
1527
+ }
1528
+
1529
+ def draw_system_colours(dc)
1530
+ mono = Wx::Font.new(Wx::FontInfo.new.family(Wx::FONTFAMILY_TELETYPE))
1531
+ textWidth, textHeight, _, _ = dc.with_font(mono) { dc.get_text_extent("#01234567") }
1532
+
1533
+ x = from_dip(10)
1534
+ r = Wx::Rect.new(textWidth + x, x, dc.from_dip(100), textHeight)
1535
+
1536
+ title = 'System colours'
1537
+
1538
+ appearanceName = Wx::SystemSettings.get_appearance_name
1539
+ title << " for \"#{appearanceName}\"" unless appearanceName.empty?
1540
+
1541
+ title += " (using dark system theme)" if Wx::SystemSettings.is_appearance_dark
1542
+ dc.draw_text(title, x, r.y)
1543
+ r.y += 2*textHeight
1544
+ dc.draw_text("Window background is #{Wx::SystemSettings.is_appearance_using_dark_background ? 'dark' : 'light'}",
1545
+ x, r.y)
1546
+ r.y += 3*textHeight
1547
+
1548
+ dc.set_pen(Wx::TRANSPARENT_PEN)
1549
+
1550
+ SYSTEM_COLOURS.each_pair do |index, name|
1551
+ c = Wx::Colour.new(Wx::SystemSettings.get_colour(index))
1552
+ dc.with_font(mono) { dc.draw_text(c.get_as_string(Wx::C2S_HTML_SYNTAX), x, r.y) }
1553
+
1554
+ dc.set_brush(Wx::Brush.new(c))
1555
+ dc.draw_rectangle(r)
1556
+
1557
+ dc.draw_text(name, r.right + x, r.y)
1558
+
1559
+ r.y += textHeight
1560
+ end
1561
+ end
1562
+
1563
+ def draw_regions_helper(dc, x, firstTime)
1564
+ y = dc.from_dip(100)
1565
+
1566
+ dc.destroy_clipping_region
1567
+ dc.set_brush(Wx::WHITE_BRUSH)
1568
+ dc.set_pen(Wx::TRANSPARENT_PEN)
1569
+ dc.draw_rectangle(x, y, dc.from_dip(310), dc.from_dip(310))
1570
+
1571
+ dc.set_clipping_region(x + dc.from_dip(10), y + dc.from_dip(10), dc.from_dip(100), dc.from_dip(270))
1572
+
1573
+ dc.set_brush(Wx::RED_BRUSH)
1574
+ dc.draw_rectangle(x, y, dc.from_dip(310), dc.from_dip(310))
1575
+
1576
+ dc.set_clipping_region(x + dc.from_dip(10), y + dc.from_dip(10), dc.from_dip(100), dc.from_dip(100))
1577
+
1578
+ dc.set_brush(Wx::CYAN_BRUSH)
1579
+ dc.draw_rectangle(x, y, dc.from_dip(310), dc.from_dip(310))
1580
+
1581
+ dc.destroy_clipping_region
1582
+
1583
+ region = Wx::Region.new(x + dc.from_dip(110), y + dc.from_dip(20), dc.from_dip(100), dc.from_dip(270))
1584
+ region.offset(dc.from_dip(10), dc.from_dip(10)) unless firstTime
1585
+ dc.set_device_clipping_region(region)
1586
+
1587
+ dc.set_brush(Wx::GREY_BRUSH)
1588
+ dc.draw_rectangle(x, y, dc.from_dip(310), dc.from_dip(310))
1589
+
1590
+ if @smile_bmp.ok?
1591
+ dc.draw_bitmap(@smile_bmp, x + dc.from_dip(150), y + dc.from_dip(150), true)
1592
+ dc.draw_bitmap(@smile_bmp, x + dc.from_dip(130), y + dc.from_dip(10), true)
1593
+ dc.draw_bitmap(@smile_bmp, x + dc.from_dip(130), y + dc.from_dip(280), true)
1594
+ dc.draw_bitmap(@smile_bmp, x + dc.from_dip(100), y + dc.from_dip(70), true)
1595
+ dc.draw_bitmap(@smile_bmp, x + dc.from_dip(200), y + dc.from_dip(70), true)
1596
+ end
1597
+ end
1598
+
1599
+ end
1600
+
1601
+ if Wx.has_feature?(:USE_DC_TRANSFORM_MATRIX)
1602
+
1603
+ class TransformDataDialog < Wx::Dialog
1604
+
1605
+ def initialize(parent, dx, dy, scx, scy, rotAngle)
1606
+ super(parent, Wx::ID_ANY, 'Affine transformation parameters')
1607
+ @dx = dx
1608
+ @dy = dy
1609
+ @scx = scx
1610
+ @scy = scy
1611
+ @rotAngle = rotAngle
1612
+
1613
+ sizer = Wx::VBoxSizer.new
1614
+
1615
+ border = Wx::SizerFlags.get_default_border
1616
+ paramSizer = Wx::FlexGridSizer.new(2, [border, border])
1617
+ paramSizer.add(Wx::StaticText.new(self, Wx::ID_ANY, 'Translation X:'), Wx::SizerFlags.new.centre_vertical)
1618
+ val_dx = Wx::FloatValidator.new(1, Wx::NUM_VAL_NO_TRAILING_ZEROES)
1619
+ val_dx.on_transfer_from_window { |v| @dx = v }
1620
+ val_dx.on_transfer_to_window { @dx }
1621
+ paramSizer.add(Wx::TextCtrl.new(self, Wx::ID_ANY, style: 0, validator: val_dx), Wx::SizerFlags.new.centre_vertical)
1622
+ paramSizer.add(Wx::StaticText.new(self, Wx::ID_ANY, 'Translation Y:'), Wx::SizerFlags.new.centre_vertical)
1623
+ val_dy = Wx::FloatValidator.new(1, Wx::NUM_VAL_NO_TRAILING_ZEROES)
1624
+ val_dy.on_transfer_from_window { |v| @dy = v }
1625
+ val_dy.on_transfer_to_window { @dy }
1626
+ paramSizer.add(Wx::TextCtrl.new(self, Wx::ID_ANY, style: 0, validator: val_dy), Wx::SizerFlags.new.centre_vertical)
1627
+ paramSizer.add(Wx::StaticText.new(self, Wx::ID_ANY, 'Scale X (0.2 - 5):'), Wx::SizerFlags.new.centre_vertical)
1628
+ val_scx = Wx::FloatValidator.new(1, Wx::NUM_VAL_NO_TRAILING_ZEROES)
1629
+ val_scx.on_transfer_from_window { |v| @scx = v }
1630
+ val_scx.on_transfer_to_window { @scx }
1631
+ paramSizer.add(Wx::TextCtrl.new(self, Wx::ID_ANY, style: 0, validator: val_scx), Wx::SizerFlags.new.centre_vertical)
1632
+ paramSizer.add(Wx::StaticText.new(self, Wx::ID_ANY, 'Scale Y (0.2 - 5):'), Wx::SizerFlags.new.centre_vertical)
1633
+ val_scy = Wx::FloatValidator.new(1, Wx::NUM_VAL_NO_TRAILING_ZEROES)
1634
+ val_scy.on_transfer_from_window { |v| @scy = v }
1635
+ val_scy.on_transfer_to_window { @scy }
1636
+ paramSizer.add(Wx::TextCtrl.new(self, Wx::ID_ANY, style: 0, validator: val_scy), Wx::SizerFlags.new.centre_vertical)
1637
+ paramSizer.add(Wx::StaticText.new(self, Wx::ID_ANY, 'Rotation angle (deg):'), Wx::SizerFlags.new.centre_vertical)
1638
+ val_rot = Wx::FloatValidator.new(1, Wx::NUM_VAL_NO_TRAILING_ZEROES)
1639
+ val_rot.on_transfer_from_window { |v| @rotAngle = v }
1640
+ val_rot.on_transfer_to_window { @rotAngle }
1641
+ paramSizer.add(Wx::TextCtrl.new(self, Wx::ID_ANY, style: 0, validator: val_rot), Wx::SizerFlags.new.centre_vertical)
1642
+ sizer.add(paramSizer, Wx::SizerFlags.new.double_border)
1643
+
1644
+ btnSizer = create_separated_button_sizer(Wx::OK | Wx::CANCEL)
1645
+ sizer.add(btnSizer, Wx::SizerFlags.new.expand.border)
1646
+
1647
+ set_sizer_and_fit(sizer)
1648
+ end
1649
+
1650
+ def transfer_data_from_window
1651
+ return false unless super
1652
+
1653
+ if @scx < 0.2 || @scx > 5.0 || @scy < 0.2 || @scy > 5.0
1654
+ Wx.bell unless Wx::Validator.is_silent
1655
+ return false
1656
+ end
1657
+
1658
+ true
1659
+ end
1660
+
1661
+ def get_transformation_data
1662
+ [@dx, @dy, @scx, @scy, @rotAngle]
1663
+ end
1664
+ end
1665
+
1666
+ end # USE_DC_TRANSFORM_MATRIX
1667
+
1668
+ class MyFrame < Wx::Frame
1669
+
1670
+ def initialize(title)
1671
+ super(nil, title: title)
1672
+ # set the frame icon
1673
+ self.icon = Wx.Icon(:sample, Wx::BITMAP_TYPE_XPM, art_path: File.join(__dir__, '..'))
1674
+
1675
+ # initialize attributes
1676
+ @backgroundMode = Wx::BrushStyle::BRUSHSTYLE_SOLID
1677
+ @textureBackground = false
1678
+ @mapMode = Wx::MM_TEXT
1679
+ @xUserScale = 1.0
1680
+ @yUserScale = 1.0
1681
+ @xLogicalOrigin = 0
1682
+ @yLogicalOrigin = 0
1683
+ @xAxisReversed = false
1684
+ @yAxisReversed = false
1685
+ if Wx.has_feature?(:USE_DC_TRANSFORM_MATRIX)
1686
+ @transform_dx = 0.0
1687
+ @transform_dy = 0.0
1688
+ @transform_scx = 1.0
1689
+ @transform_scy = 1.0
1690
+ @transform_rot = 0.0
1691
+ end # USE_DC_TRANSFORM_MATRIX
1692
+ @colourForeground = Wx::BLACK # these are _text_ colours
1693
+ @colourBackground = Wx::LIGHT_GREY
1694
+ @backgroundBrush = Wx::Brush.new
1695
+ @canvas = MyCanvas.new(self)
1696
+ @menuItemUseDC = nil
1697
+
1698
+ # initialize menu and status bar
1699
+ menuScreen = Wx::Menu.new
1700
+ menuScreen.append(ID::File_ShowDefault, "&Default screen\tF1")
1701
+ menuScreen.append(ID::File_ShowText, "&Text screen\tF2")
1702
+ menuScreen.append(ID::File_ShowLines, "&Lines screen\tF3")
1703
+ menuScreen.append(ID::File_ShowBrushes, "&Brushes screen\tF4")
1704
+ menuScreen.append(ID::File_ShowPolygons, "&Polygons screen\tF5")
1705
+ menuScreen.append(ID::File_ShowMask, "&Mask screen\tF6")
1706
+ menuScreen.append(ID::File_ShowMaskStretch, "1/&2 scaled mask\tShift-F6")
1707
+ menuScreen.append(ID::File_ShowOps, "&Raster operations screen\tF7")
1708
+ menuScreen.append(ID::File_ShowRegions, "Re&gions screen\tF8")
1709
+ menuScreen.append(ID::File_ShowCircles, "&Circles screen\tF9")
1710
+ if DRAWING_DC_SUPPORTS_ALPHA || Wx.has_feature?(:USE_GRAPHICS_CONTEXT)
1711
+ menuScreen.append(ID::File_ShowAlpha, "&Alpha screen\tF10")
1712
+ end # DRAWING_DC_SUPPORTS_ALPHA || USE_GRAPHICS_CONTEXT
1713
+ menuScreen.append(ID::File_ShowSplines, "Spl&ines screen\tF11")
1714
+ menuScreen.append(ID::File_ShowGradients, "&Gradients screen\tF12")
1715
+ if Wx.has_feature?(:USE_GRAPHICS_CONTEXT)
1716
+ menuScreen.append(ID::File_ShowGraphics, "&Graphics screen")
1717
+ end
1718
+ menuScreen.append(ID::File_ShowSystemColours, "System &colours")
1719
+
1720
+ menuFile = Wx::Menu.new
1721
+ if Wx.has_feature?(:USE_GRAPHICS_CONTEXT)
1722
+ # Number the different renderer choices consecutively, starting from 0.
1723
+ accel = -1
1724
+ @menuItemUseDC = menuFile.append_radio_item(
1725
+ ID::File_DC,"Use wx&DC\t#{accel += 1}")
1726
+ menuFile.append_radio_item(
1727
+ ID::File_GC_Default, "Use default wx&GraphicContext\t#{accel += 1}")
1728
+ if Wx.has_feature?(:USE_CAIRO)
1729
+ menuFile.append_radio_item(
1730
+ ID::File_GC_Cairo, "Use &Cairo\t#{accel += 1}")
1731
+ end # USE_CAIRO
1732
+ if Wx::PLATFORM == 'WXMSW'
1733
+ if Wx.has_feature?(:USE_GRAPHICS_GDIPLUS)
1734
+ menuFile.append_radio_item(
1735
+ ID::File_GC_GDIPlus, "Use &GDI+\t#{accel += 1}")
1736
+ end
1737
+ if Wx.has_feature?(:USE_GRAPHICS_DIRECT2D)
1738
+ menuFile.append_radio_item(
1739
+ ID::File_GC_Direct2D, "Use &Direct2D\t#{accel += 1}")
1740
+ end
1741
+ end # WXMSW
1742
+ end # USE_GRAPHICS_CONTEXT
1743
+ menuFile.append_separator
1744
+ menuFile.append_check_item(ID::File_BBox, "Show bounding box\tCtrl-E",
1745
+ 'Show extents used in drawing operations')
1746
+ menuFile.append_check_item(ID::File_Clip, "&Clip\tCtrl-C", 'Clip/unclip drawing')
1747
+ menuFile.append_check_item(ID::File_Buffer, "&Use wx&BufferedPaintDC\tCtrl-Z", 'Buffer painting')
1748
+ if Wx.has_feature?(:USE_GRAPHICS_CONTEXT)
1749
+ menuFile.append_check_item(ID::File_AntiAliasing,
1750
+ "&Anti-Aliasing in wxGraphicContext\tCtrl-Shift-A",
1751
+ 'Enable Anti-Aliasing in wxGraphicContext')
1752
+ .check
1753
+ end
1754
+ menuFile.append_separator
1755
+ menuFile.append(ID::File_Copy, "Copy to clipboard")
1756
+ menuFile.append(ID::File_Save, "&Save...\tCtrl-S", 'Save drawing to file')
1757
+ menuFile.append_separator
1758
+ menuFile.append(ID::File_About, "&About\tCtrl-A", 'Show about dialog')
1759
+ menuFile.append_separator
1760
+ menuFile.append(ID::File_Quit, "E&xit\tAlt-X", 'Quit this program')
1761
+
1762
+ menuMapMode = Wx::Menu.new
1763
+ menuMapMode.append(ID::MapMode_Text, "&TEXT map mode" )
1764
+ menuMapMode.append(ID::MapMode_Lometric, "&LOMETRIC map mode" )
1765
+ menuMapMode.append(ID::MapMode_Twips, "T&WIPS map mode" )
1766
+ menuMapMode.append(ID::MapMode_Points, "&POINTS map mode" )
1767
+ menuMapMode.append(ID::MapMode_Metric, "&METRIC map mode" )
1768
+
1769
+ menuUserScale = Wx::Menu.new
1770
+ menuUserScale.append(ID::UserScale_StretchHoriz, "Stretch &horizontally\tCtrl-H")
1771
+ menuUserScale.append(ID::UserScale_ShrinkHoriz, "Shrin&k horizontally\tCtrl-G")
1772
+ menuUserScale.append(ID::UserScale_StretchVertic, "Stretch &vertically\tCtrl-V")
1773
+ menuUserScale.append(ID::UserScale_ShrinkVertic, "&Shrink vertically\tCtrl-W")
1774
+ menuUserScale.append_separator
1775
+ menuUserScale.append(ID::UserScale_Restore, "&Restore to normal\tCtrl-0")
1776
+
1777
+ menuAxis = Wx::Menu.new
1778
+ menuAxis.append_check_item(ID::AxisMirror_Horiz, "Mirror horizontally\tCtrl-M")
1779
+ menuAxis.append_check_item(ID::AxisMirror_Vertic, "Mirror vertically\tCtrl-N")
1780
+
1781
+ menuLogical = Wx::Menu.new
1782
+ menuLogical.append(ID::LogicalOrigin_MoveDown, "Move &down\tCtrl-D")
1783
+ menuLogical.append(ID::LogicalOrigin_MoveUp, "Move &up\tCtrl-U")
1784
+ menuLogical.append(ID::LogicalOrigin_MoveLeft, "Move &right\tCtrl-L")
1785
+ menuLogical.append(ID::LogicalOrigin_MoveRight, "Move &left\tCtrl-R")
1786
+ menuLogical.append_separator
1787
+ menuLogical.append(ID::LogicalOrigin_Set, "Set to (&100, 100)\tShift-Ctrl-1")
1788
+ menuLogical.append(ID::LogicalOrigin_Restore, "&Restore to normal\tShift-Ctrl-0")
1789
+
1790
+ if Wx.has_feature?(:USE_DC_TRANSFORM_MATRIX)
1791
+ menuTransformMatrix = Wx::Menu.new
1792
+ menuTransformMatrix.append(ID::TransformMatrix_Set, "Set &transformation matrix")
1793
+ menuTransformMatrix.append_separator
1794
+ menuTransformMatrix.append(ID::TransformMatrix_Reset, "Restore to &normal")
1795
+ end # USE_DC_TRANSFORM_MATRIX
1796
+
1797
+ menuColour = Wx::Menu.new
1798
+ if Wx.has_feature?(:USE_COLOURDLG)
1799
+ menuColour.append(ID::Colour_TextForeground, "Text &foreground...")
1800
+ menuColour.append(ID::Colour_TextBackground, "Text &background...")
1801
+ menuColour.append(ID::Colour_Background, "Background &colour...")
1802
+ end # USE_COLOURDLG
1803
+ menuColour.append_check_item(ID::Colour_BackgroundMode, "&Opaque/transparent\tCtrl-B")
1804
+ menuColour.append_check_item(ID::Colour_TextureBackground, "Draw textured back&ground\tCtrl-T")
1805
+
1806
+ # now append the freshly created menu to the menu bar...
1807
+ menuBar = Wx::MenuBar.new
1808
+ menuBar.append(menuFile, "&Drawing")
1809
+ menuBar.append(menuScreen, "Scree&n")
1810
+ menuBar.append(menuMapMode, "&Mode")
1811
+ menuBar.append(menuUserScale, "&Scale")
1812
+ menuBar.append(menuAxis, "&Axis")
1813
+ menuBar.append(menuLogical, "&Origin")
1814
+ if Wx.has_feature?(:USE_DC_TRANSFORM_MATRIX)
1815
+ menuBar.append(menuTransformMatrix, "&Transformation")
1816
+ end # USE_DC_TRANSFORM_MATRIX
1817
+ menuBar.append(menuColour, "&Colours")
1818
+
1819
+ # ... and attach this menu bar to the frame
1820
+ set_menu_bar(menuBar)
1821
+
1822
+ if Wx.has_feature?(:USE_STATUSBAR)
1823
+ create_status_bar(2)
1824
+ set_status_text("Welcome to wxRuby3!")
1825
+ end # USE_STATUSBAR
1826
+
1827
+ # connect event handlers
1828
+ evt_menu(ID::File_Quit, :on_quit)
1829
+ evt_menu(ID::File_About, :on_about)
1830
+ evt_menu(ID::File_Clip, :on_clip)
1831
+
1832
+ if Wx.has_feature?(:USE_GRAPHICS_CONTEXT)
1833
+ evt_menu(ID::File_GC_Default, :on_graphic_context_default)
1834
+ evt_menu(ID::File_DC, :on_graphic_context_none)
1835
+ if Wx.has_feature?(:USE_CAIRO)
1836
+ evt_menu(ID::File_GC_Cairo, :on_graphic_context_cairo)
1837
+ end # USE_CAIRO
1838
+ if Wx::PLATFORM == 'WXMSW'
1839
+ if Wx.has_feature?(:USE_GRAPHICS_GDIPLUS)
1840
+ evt_menu(ID::File_GC_GDIPlus, :on_graphic_context_gdi_plus)
1841
+ end
1842
+ if Wx.has_feature?(:USE_GRAPHICS_DIRECT2D)
1843
+ evt_menu(ID::File_GC_Direct2D, :on_graphic_context_direct2d)
1844
+ end
1845
+ end # WXMSW
1846
+ evt_menu(ID::File_AntiAliasing, :on_anti_aliasing)
1847
+ evt_update_ui(ID::File_AntiAliasing, :on_anti_aliasing_update_ui)
1848
+ end # USE_GRAPHICS_CONTEXT
1849
+
1850
+ evt_menu(ID::File_Buffer, :on_buffer)
1851
+ evt_menu(ID::File_Copy, :on_copy)
1852
+ evt_menu(ID::File_Save, :on_save)
1853
+ evt_menu(ID::File_BBox, :on_bounding_box)
1854
+ evt_update_ui(ID::File_BBox, :on_bounding_box_update_ui)
1855
+
1856
+ evt_menu_range(ID::MenuShow_First, ID::MenuShow_Last, :on_show)
1857
+
1858
+ evt_menu_range(ID::MenuOption_First, ID::MenuOption_Last, :on_option)
1859
+
1860
+ @canvas.set_scrollbars(10, 10, 100, 240)
1861
+
1862
+ set_size(from_dip([800, 700]))
1863
+ center(Wx::BOTH)
1864
+ end
1865
+
1866
+ attr_reader :backgroundMode
1867
+ attr_reader :textureBackground
1868
+ attr_reader :mapMode
1869
+ attr_reader :xUserScale
1870
+ attr_reader :yUserScale
1871
+ attr_reader :xLogicalOrigin
1872
+ attr_reader :yLogicalOrigin
1873
+ attr_reader :xAxisReversed
1874
+ attr_reader :yAxisReversed
1875
+ attr_reader :transform_dx
1876
+ attr_reader :transform_dy
1877
+ attr_reader :transform_scx
1878
+ attr_reader :transform_scy
1879
+ attr_reader :transform_rot
1880
+ attr_reader :colourForeground
1881
+ attr_reader :colourBackground
1882
+ attr_reader :backgroundBrush
1883
+ attr_reader :canvas
1884
+ attr_reader :menuItemUseDC
1885
+
1886
+ # event handlers (these functions should _not_ be virtual)
1887
+ def on_quit(_event)
1888
+ # true is to force the frame to close
1889
+ close(true)
1890
+ end
1891
+
1892
+ def on_about(_event)
1893
+ msg = "This is the about dialog of the drawing sample.\n" \
1894
+ "This sample tests various primitive drawing functions\n" \
1895
+ "(without any attempts to prevent flicker).\n" \
1896
+ "Copyright (c) Martin Corino (adapted for wxRuby3; original Robert Roebling 1999)"
1897
+
1898
+ Wx.message_box(msg, "About Drawing", Wx::OK | Wx::ICON_INFORMATION, self)
1899
+ end
1900
+
1901
+ def on_clip(event)
1902
+ @canvas.clip(event.checked?)
1903
+ end
1904
+
1905
+ if Wx.has_feature?(:USE_GRAPHICS_CONTEXT)
1906
+ def on_graphic_context_none(_event)
1907
+ @canvas.use_graphic_renderer(nil)
1908
+ end
1909
+
1910
+ def on_graphic_context_default(_event)
1911
+ @canvas.use_graphic_renderer(Wx::GraphicsRenderer.get_default_renderer)
1912
+ end
1913
+
1914
+ if Wx.has_feature?(:USE_CAIRO)
1915
+ def on_graphic_context_cairo(_event)
1916
+ @canvas.use_graphic_renderer(Wx::GraphicsRenderer.get_cairo_renderer)
1917
+ end
1918
+ end # USE_CAIRO
1919
+
1920
+ if Wx::PLATFORM == 'WXMSW'
1921
+ if Wx.has_feature?(:USE_GRAPHICS_GDIPLUS)
1922
+ def on_graphic_context_gdi_plus(_event)
1923
+ @canvas.use_graphic_renderer(Wx::GraphicsRenderer.get_gdi_plus_renderer)
1924
+ end
1925
+ end
1926
+
1927
+ if Wx.has_feature?(:USE_GRAPHICS_DIRECT2D)
1928
+ def on_graphic_context_direct2d(_event)
1929
+ @canvas.use_graphic_renderer(Wx::GraphicsRenderer.get_direct2d_renderer)
1930
+ end
1931
+ end
1932
+ end # WXMSW
1933
+
1934
+ def on_anti_aliasing(event)
1935
+ @canvas.enable_anti_aliasing(event.is_checked)
1936
+ end
1937
+
1938
+ def on_anti_aliasing_update_ui(event)
1939
+ event.enable(!@canvas.get_renderer.nil?)
1940
+ end
1941
+ end # USE_GRAPHICS_CONTEXT
1942
+
1943
+ def on_buffer(event)
1944
+ @canvas.use_buffer(event.checked?)
1945
+ end
1946
+
1947
+ def on_copy(_event)
1948
+ bitmap = Wx::Bitmap.new
1949
+ bitmap.create_with_dip_size(@canvas.get_dip_drawing_size, get_dpi_scale_factor)
1950
+ Wx::MemoryDC.draw_on(bitmap) do |mdc|
1951
+ mdc.set_background(Wx::WHITE_BRUSH)
1952
+ mdc.clear
1953
+ @canvas.draw(mdc)
1954
+ end
1955
+ Wx::Clipboard.open do | clip |
1956
+ clip.place Wx::BitmapDataObject.new(bitmap)
1957
+ end
1958
+ end
1959
+
1960
+ def on_save(_event)
1961
+ wildCard = "Bitmap image (*.bmp)|*.bmp*.BMP"
1962
+ wildCard << "|PNG image (*.png)|*.png*.PNG" if Wx.has_feature?(:USE_LIBPNG)
1963
+ wildCard << "|SVG image (*.svg)|*.svg*.SVG" if Wx.has_feature?(:USE_SVG)
1964
+ wildCard << "|PostScript file (*.ps)|*.ps*.PS" if Wx.has_feature?(:USE_POSTSCRIPT)
1965
+
1966
+ Wx.FileDialog(self, "Save as bitmap", '', '', wildCard, Wx::FD_SAVE | Wx::FD_OVERWRITE_PROMPT) do |dlg|
1967
+ if dlg.show_modal == Wx::ID_OK
1968
+ canvasSize = @canvas.get_dip_drawing_size
1969
+ fn = dlg.get_path
1970
+ ext = File.extname(fn).downcase
1971
+ if Wx.has_feature?(:USE_SVG) && ext == '.svg'
1972
+ if Wx.has_feature?(:USE_GRAPHICS_CONTEXT)
1973
+ # Graphics screen can only be drawn using GraphicsContext
1974
+ if @canvas.get_page == ID::File_ShowGraphics
1975
+ Wx.log_message('Graphics screen can not be saved as SVG.')
1976
+ return
1977
+ end
1978
+ tempRenderer = @canvas.get_renderer
1979
+ @canvas.use_graphic_renderer(nil)
1980
+ end
1981
+ Wx::SVGFileDC.draw_on(dlg.path,
1982
+ canvasSize.width,
1983
+ canvasSize.height,
1984
+ 72.0,
1985
+ 'Drawing sample') do |svgdc|
1986
+ svgdc.set_bitmap_handler(Wx::SVGBitmapEmbedHandler.new)
1987
+ @canvas.draw(svgdc)
1988
+ end
1989
+ if Wx.has_feature?(:USE_GRAPHICS_CONTEXT)
1990
+ @canvas.use_graphic_renderer(tempRenderer)
1991
+ end
1992
+ elsif Wx.has_feature?(:USE_POSTSCRIPT) && ext == '.ps'
1993
+ if Wx.has_feature?(:USE_GRAPHICS_CONTEXT)
1994
+ # Graphics screen can only be drawn using wxGraphicsContext
1995
+ if @canvas.get_page == ID::File_ShowGraphics
1996
+ Wx.log_message('Graphics screen can not be saved as PostScript file.')
1997
+ return
1998
+ end
1999
+ curRenderer = @canvas.get_renderer
2000
+ @canvas.use_graphic_renderer(nil)
2001
+ end # USE_GRAPHICS_CONTEXT
2002
+ printData = Wx::PrintData.new
2003
+ printData.set_print_mode(Wx::PRINT_MODE_FILE)
2004
+ printData.set_filename(dlg.path)
2005
+ printData.set_orientation(Wx::PORTRAIT)
2006
+ printData.set_paper_id(Wx::PAPER_A4)
2007
+ Wx::PostScriptDC.draw_on(printData) do |psdc|
2008
+ # Save current scale factor
2009
+ curUserScaleX = @xUserScale
2010
+ curUserScaleY = @yUserScale
2011
+ # Change the scale temporarily to fit the drawing into the page.
2012
+ w, h = psdc.get_size
2013
+ sc = [w.to_f / canvasSize.width, h.to_f / canvasSize.height].min
2014
+ @xUserScale *= sc
2015
+ @yUserScale *= sc
2016
+ psdc.start_doc('Drawing sample')
2017
+ # Define default font.
2018
+ psdc.set_font(Wx::FontInfo.new(10).family(Wx::FONTFAMILY_MODERN))
2019
+ psdc.start_page
2020
+ @canvas.draw(psdc)
2021
+ psdc.end_page
2022
+ psdc.end_doc
2023
+ # Restore original scale factor
2024
+ @xUserScale = curUserScaleX
2025
+ @yUserScale = curUserScaleY
2026
+ end
2027
+ if Wx.has_feature?(:USE_GRAPHICS_CONTEXT)
2028
+ @canvas.use_graphic_renderer(curRenderer)
2029
+ end # USE_GRAPHICS_CONTEXT
2030
+ else
2031
+ bmp = Wx::Bitmap.new
2032
+ bmp.create_with_dip_size(canvasSize, get_dpi_scale_factor)
2033
+ Wx::MemoryDC.draw_on(bmp) do |mdc|
2034
+ mdc.set_background(Wx::WHITE_BRUSH)
2035
+ mdc.clear
2036
+ @canvas.draw(mdc)
2037
+ end
2038
+ bmp.convert_to_image.save_file(dlg.path)
2039
+ end
2040
+ end
2041
+ end
2042
+ end
2043
+
2044
+ def on_show(event)
2045
+ show = event.id
2046
+
2047
+ if DRAWING_DC_SUPPORTS_ALPHA || Wx.has_feature?(:USE_GRAPHICS_CONTEXT)
2048
+ # Make sure we do use a graphics context when selecting one of the screens
2049
+ # requiring it.
2050
+ # If DC supports drawing with alpha
2051
+ # then GC is necessary only for graphics screen.
2052
+ if (DRAWING_DC_SUPPORTS_ALPHA && show == ID::File_ShowGraphics) ||
2053
+ # DC doesn't support drawing with alpha
2054
+ # so GC is necessary both for alpha and graphics screen.
2055
+ (!DRAWING_DC_SUPPORTS_ALPHA && (show == ID::File_ShowAlpha || show == ID::File_ShowGraphics))
2056
+ @canvas.use_graphic_renderer(Wx::GraphicsRenderer.get_default_renderer) unless @canvas.has_renderer
2057
+ # Disable selecting Wx::DC, if necessary.
2058
+ @menuItemUseDC.enable(!@canvas.has_renderer)
2059
+ else
2060
+ @menuItemUseDC.enable(true)
2061
+ end
2062
+ end # DRAWING_DC_SUPPORTS_ALPHA || USE_GRAPHICS_CONTEXT
2063
+ @canvas.to_show(show)
2064
+ end
2065
+
2066
+ def on_option(event)
2067
+ case event.id
2068
+ when ID::MapMode_Text
2069
+ @mapMode = Wx::MM_TEXT
2070
+ when ID::MapMode_Lometric
2071
+ @mapMode = Wx::MM_LOMETRIC
2072
+ when ID::MapMode_Twips
2073
+ @mapMode = Wx::MM_TWIPS
2074
+ when ID::MapMode_Points
2075
+ @mapMode = Wx::MM_POINTS
2076
+ when ID::MapMode_Metric
2077
+ @mapMode = Wx::MM_METRIC
2078
+
2079
+ when ID::LogicalOrigin_MoveDown
2080
+ @yLogicalOrigin += 10
2081
+ when ID::LogicalOrigin_MoveUp
2082
+ @yLogicalOrigin -= 10
2083
+ when ID::LogicalOrigin_MoveLeft
2084
+ @xLogicalOrigin += 10
2085
+ when ID::LogicalOrigin_MoveRight
2086
+ @xLogicalOrigin -= 10
2087
+ when ID::LogicalOrigin_Set
2088
+ @xLogicalOrigin =
2089
+ @yLogicalOrigin = -100
2090
+ when ID::LogicalOrigin_Restore
2091
+ @xLogicalOrigin =
2092
+ @yLogicalOrigin = 0
2093
+
2094
+ when ID::UserScale_StretchHoriz
2095
+ @xUserScale *= 1.10
2096
+ when ID::UserScale_ShrinkHoriz
2097
+ @xUserScale /= 1.10
2098
+ when ID::UserScale_StretchVertic
2099
+ @yUserScale *= 1.10
2100
+ when ID::UserScale_ShrinkVertic
2101
+ @yUserScale /= 1.10
2102
+ when ID::UserScale_Restore
2103
+ @xUserScale =
2104
+ @yUserScale = 1.0
2105
+
2106
+ when ID::AxisMirror_Vertic
2107
+ @yAxisReversed = !@yAxisReversed
2108
+ when ID::AxisMirror_Horiz
2109
+ @xAxisReversed = !@xAxisReversed
2110
+
2111
+ when ID::TransformMatrix_Set
2112
+ if Wx.has_feature?(:USE_DC_TRANSFORM_MATRIX)
2113
+ Drawing.TransformDataDialog(self, @transform_dx, @transform_dy,
2114
+ @transform_scx, @transform_scy, @transform_rot) do |dlg|
2115
+ if dlg.show_modal == Wx::ID_OK
2116
+ @transform_dx, @transform_dy, @transform_scx, @transform_scy, @transform_rot = dlg.get_transformation_data
2117
+ end
2118
+ end
2119
+ end
2120
+
2121
+ when ID::TransformMatrix_Reset
2122
+ if Wx.has_feature?(:USE_DC_TRANSFORM_MATRIX)
2123
+ @transform_dx = 0.0
2124
+ @transform_dy = 0.0
2125
+ @transform_scx = 1.0
2126
+ @transform_scy = 1.0
2127
+ @transform_rot = 0.0
2128
+ end
2129
+
2130
+ when ID::Colour_TextForeground
2131
+ if Wx.has_feature?(:USE_COLOURDLG)
2132
+ @colourForeground = select_colour
2133
+ end
2134
+ when ID::Colour_TextBackground
2135
+ if Wx.has_feature?(:USE_COLOURDLG)
2136
+ @colourBackground = select_colour
2137
+ end
2138
+ when ID::Colour_Background
2139
+ if Wx.has_feature?(:USE_COLOURDLG)
2140
+ col = select_colour
2141
+ @backgroundBrush.set_colour(col) if col.ok?
2142
+ end
2143
+
2144
+ when ID::Colour_BackgroundMode
2145
+ @backgroundMode = (@backgroundMode == Wx::BRUSHSTYLE_SOLID ?
2146
+ Wx::BRUSHSTYLE_TRANSPARENT : Wx::BRUSHSTYLE_SOLID)
2147
+
2148
+ when ID::Colour_TextureBackground
2149
+ @textureBackground = ! @textureBackground
2150
+
2151
+ else
2152
+ return
2153
+ end
2154
+
2155
+ @canvas.refresh
2156
+ end
2157
+
2158
+ def on_bounding_box(evt)
2159
+ @canvas.show_bounding_box(evt.checked?)
2160
+ end
2161
+
2162
+ def on_bounding_box_update_ui(evt)
2163
+ if Wx.has_feature?(:USE_GRAPHICS_CONTEXT)
2164
+ evt.enable(@canvas.get_page != ID::File_ShowGraphics)
2165
+ end
2166
+ end
2167
+
2168
+ if Wx.has_feature?(:USE_COLOURDLG)
2169
+ def select_colour
2170
+ data = Wx::ColourData.new
2171
+ Wx.ColourDialog(self, data) do |dialog|
2172
+ return dialog.get_colour_data.get_colour if dialog.show_modal == Wx::ID_OK
2173
+ end
2174
+ Wx::Colour.new
2175
+ end
2176
+ end # USE_COLOURDLG
2177
+
2178
+ def prepare_dc(dc)
2179
+ if Wx.has_feature?(:USE_DC_TRANSFORM_MATRIX)
2180
+ if dc.can_use_transform_matrix
2181
+ mtx = Wx::AffineMatrix2D.new
2182
+ mtx.translate(@transform_dx, @transform_dy)
2183
+ mtx.rotate((@transform_rot * Math::PI) / 180)
2184
+ mtx.scale(@transform_scx, @transform_scy)
2185
+ dc.set_transform_matrix(mtx)
2186
+ end
2187
+ end # USE_DC_TRANSFORM_MATRIX
2188
+ dc.set_logical_origin(dc.from_dip(@xLogicalOrigin), dc.from_dip(@yLogicalOrigin))
2189
+ dc.set_axis_orientation(!@xAxisReversed, @yAxisReversed)
2190
+ dc.set_user_scale(@xUserScale, @yUserScale)
2191
+ dc.set_map_mode(@mapMode)
2192
+ end
2193
+
2194
+ end
2195
+
2196
+
2197
+ class MyApp < Wx::App
2198
+
2199
+ def initialize
2200
+ super
2201
+ @images = {}
2202
+ end
2203
+
2204
+ attr_reader :images
2205
+
2206
+ def on_init
2207
+ # Create the main application window
2208
+ frame = MyFrame.new('Drawing sample')
2209
+
2210
+ # Show it
2211
+ frame.show(true)
2212
+
2213
+ unless load_images
2214
+ Wx.log_error('Cannot load one of the bitmap files needed ' \
2215
+ 'for this sample from the current or parent ' \
2216
+ 'directory, please copy them there.')
2217
+
2218
+ # still continue, the sample can be used without images too if they're
2219
+ # missing for whatever reason
2220
+ end
2221
+
2222
+ true
2223
+ end
2224
+
2225
+ def on_exit
2226
+ delete_images
2227
+ end
2228
+
2229
+ protected
2230
+
2231
+ def load_images
2232
+ @images[:bmpNoMask] = Wx.Bitmap(:image)
2233
+ @images[:bmpWithMask] = Wx.Bitmap(:image)
2234
+ @images[:bmpWithColMask] = Wx.Bitmap(:image)
2235
+
2236
+ @images[:bmpMask] = Wx.Bitmap(:mask)
2237
+ @images[:bmpWithMask].set_mask(Wx::Mask.new(@images[:bmpMask], Wx::BLACK))
2238
+
2239
+ @images[:bmpWithColMask].set_mask(Wx::Mask.new(@images[:bmpWithColMask], Wx::WHITE))
2240
+
2241
+ @images[:bmp4] = Wx.Bitmap(:pat4)
2242
+ @images[:bmp4_mono] = Wx.Bitmap(:pat4)
2243
+ @images[:bmp4_mono].set_mask(Wx::Mask.new(@images[:bmp4_mono], Wx::BLACK))
2244
+
2245
+ @images[:bmp36] = Wx.Bitmap(:pat36)
2246
+ @images[:bmp36].set_mask(Wx::Mask.new(@images[:bmp36], Wx::BLACK))
2247
+ true
2248
+ end
2249
+
2250
+ def delete_images
2251
+ @images.clear
2252
+ end
2253
+
2254
+ end
2255
+
2256
+ end
2257
+
2258
+ module DrawingSample
2259
+
2260
+ include WxRuby::Sample if defined? WxRuby::Sample
2261
+
2262
+ def self.describe
2263
+ { file: __FILE__,
2264
+ summary: 'wxRuby Drawing example.',
2265
+ description: 'wxRuby example demonstrating and testing Wx::DC features. Adapted from wxWidgets sample.' }
2266
+ end
2267
+
2268
+ def self.run
2269
+ execute(__FILE__)
2270
+ end
2271
+
2272
+ if $0 == __FILE__
2273
+ Drawing::MyApp.run
2274
+ end
2275
+
2276
+ end