wxruby3 0.9.8 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
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