wxruby3-shapes 0.9.0.pre.beta.3 → 0.9.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (97) hide show
  1. checksums.yaml +4 -4
  2. data/INSTALL.md +5 -7
  3. data/README.md +38 -6
  4. data/assets/logo.svg +339 -0
  5. data/assets/logo.xpm +60 -0
  6. data/assets/screenshot.png +0 -0
  7. data/assets/social.png +0 -0
  8. data/bin/wx-shapes +1 -1
  9. data/lib/wx/shapes/arrow_base.rb +4 -11
  10. data/lib/wx/shapes/arrows/circle_arrow.rb +22 -11
  11. data/lib/wx/shapes/arrows/circle_prong_arrow.rb +48 -0
  12. data/lib/wx/shapes/arrows/cross_bar_arrow.rb +57 -0
  13. data/lib/wx/shapes/arrows/cross_bar_circle_arrow.rb +56 -0
  14. data/lib/wx/shapes/arrows/cross_bar_prong_arrow.rb +49 -0
  15. data/lib/wx/shapes/arrows/crossed_circle.rb +46 -0
  16. data/lib/wx/shapes/arrows/cup_arrow.rb +65 -0
  17. data/lib/wx/shapes/arrows/diamond_arrow.rb +8 -13
  18. data/lib/wx/shapes/arrows/double_cross_bar_arrow.rb +27 -0
  19. data/lib/wx/shapes/arrows/filled_arrow.rb +60 -0
  20. data/lib/wx/shapes/arrows/line_arrow.rb +67 -0
  21. data/lib/wx/shapes/arrows/open_arrow.rb +22 -23
  22. data/lib/wx/shapes/arrows/prong_arrow.rb +42 -0
  23. data/lib/wx/shapes/arrows/solid_arrow.rb +21 -35
  24. data/lib/wx/shapes/arrows/square_arrow.rb +37 -0
  25. data/lib/wx/shapes/auto_layout.rb +2 -2
  26. data/lib/wx/shapes/base.rb +1 -1
  27. data/lib/wx/shapes/canvas_history.rb +20 -0
  28. data/lib/wx/shapes/connection_point.rb +10 -6
  29. data/lib/wx/shapes/diagram.rb +98 -78
  30. data/lib/wx/shapes/events.rb +8 -8
  31. data/lib/wx/shapes/printout.rb +3 -16
  32. data/lib/wx/shapes/serializable.rb +2 -436
  33. data/lib/wx/shapes/serialize/wx.rb +30 -18
  34. data/lib/wx/shapes/shape.rb +211 -168
  35. data/lib/wx/shapes/shape_canvas.rb +728 -267
  36. data/lib/wx/shapes/shape_data_object.rb +99 -18
  37. data/lib/wx/shapes/shape_handle.rb +18 -11
  38. data/lib/wx/shapes/shape_list.rb +34 -67
  39. data/lib/wx/shapes/shapes/bitmap_shape.rb +23 -24
  40. data/lib/wx/shapes/shapes/box_shape.rb +389 -0
  41. data/lib/wx/shapes/shapes/circle_shape.rb +19 -22
  42. data/lib/wx/shapes/shapes/control_shape.rb +77 -41
  43. data/lib/wx/shapes/shapes/curve_shape.rb +38 -31
  44. data/lib/wx/shapes/shapes/diamond_shape.rb +7 -17
  45. data/lib/wx/shapes/shapes/edit_text_shape.rb +6 -9
  46. data/lib/wx/shapes/shapes/ellipse_shape.rb +12 -15
  47. data/lib/wx/shapes/shapes/flex_grid_shape.rb +58 -33
  48. data/lib/wx/shapes/shapes/grid_shape.rb +259 -161
  49. data/lib/wx/shapes/shapes/line_shape.rb +155 -161
  50. data/lib/wx/shapes/shapes/manager_shape.rb +77 -0
  51. data/lib/wx/shapes/shapes/multi_sel_rect.rb +8 -8
  52. data/lib/wx/shapes/shapes/ortho_shape.rb +31 -36
  53. data/lib/wx/shapes/shapes/polygon_shape.rb +23 -29
  54. data/lib/wx/shapes/shapes/rect_shape.rb +95 -53
  55. data/lib/wx/shapes/shapes/round_ortho_shape.rb +6 -8
  56. data/lib/wx/shapes/shapes/round_rect_shape.rb +20 -24
  57. data/lib/wx/shapes/shapes/square_shape.rb +14 -17
  58. data/lib/wx/shapes/shapes/text_shape.rb +95 -53
  59. data/lib/wx/shapes/version.rb +1 -1
  60. data/lib/wx/shapes/wx.rb +16 -7
  61. data/lib/wx/wx-shapes/cmd/test.rb +1 -1
  62. data/samples/demo/arrows.json +1 -0
  63. data/samples/demo/arrows.yaml +793 -0
  64. data/samples/demo/art/HBox.xpm +22 -0
  65. data/samples/demo/art/VBox.xpm +22 -0
  66. data/samples/demo/art/logo.xpm +60 -0
  67. data/samples/demo/class.json +1 -0
  68. data/samples/demo/class.yaml +5631 -0
  69. data/samples/demo/demo.rb +301 -91
  70. data/samples/demo/dialogs.rb +1405 -0
  71. data/samples/demo/erd.json +1 -0
  72. data/samples/demo/erd.yaml +4072 -0
  73. data/samples/demo/frame_canvas.rb +409 -33
  74. data/samples/sample1/art/logo.xpm +60 -0
  75. data/samples/sample1/sample.rb +11 -11
  76. data/samples/sample2/art/logo.xpm +60 -0
  77. data/samples/sample2/sample.rb +2 -2
  78. data/samples/sample2/sample_shape.rb +15 -15
  79. data/samples/sample3/art/logo.xpm +60 -0
  80. data/samples/sample3/sample.rb +3 -3
  81. data/samples/sample4/art/logo.xpm +60 -0
  82. data/samples/sample4/sample.rb +2 -2
  83. data/tests/lib/wxapp_runner.rb +4 -0
  84. data/tests/serializer_tests.rb +8 -441
  85. data/tests/test_grid_shapes.rb +2 -2
  86. data/tests/test_serialize_xml.rb +17 -0
  87. data/tests/test_serialize_yaml.rb +2 -2
  88. metadata +78 -28
  89. data/lib/wx/shapes/serialize/core.rb +0 -40
  90. data/lib/wx/shapes/serialize/id.rb +0 -82
  91. data/lib/wx/shapes/serializer/json.rb +0 -258
  92. data/lib/wx/shapes/serializer/yaml.rb +0 -125
  93. data/samples/demo/art/sample.xpm +0 -251
  94. data/samples/sample1/art/sample.xpm +0 -251
  95. data/samples/sample2/art/sample.xpm +0 -251
  96. data/samples/sample3/art/sample.xpm +0 -251
  97. data/samples/sample4/art/sample.xpm +0 -251
data/samples/demo/demo.rb CHANGED
@@ -1,7 +1,9 @@
1
1
  # Wx::SF - Demo ThumbFrame, MainFrame and App
2
2
  # Copyright (c) M.J.N. Corino, The Netherlands
3
3
 
4
+ require 'nokogiri'
4
5
  require 'wx/shapes'
6
+ require 'wx/mdap'
5
7
  require_relative './frame_canvas'
6
8
 
7
9
  class ThumbFrame < Wx::Frame
@@ -9,6 +11,8 @@ class ThumbFrame < Wx::Frame
9
11
  def initialize(parent, title: 'Thumbnail', size: Wx::Size.new( 200,150 ), style: Wx::CAPTION|Wx::FRAME_FLOAT_ON_PARENT|Wx::FRAME_TOOL_WINDOW|Wx::RESIZE_BORDER|Wx::TAB_TRAVERSAL)
10
12
  super
11
13
 
14
+ set_icon(Wx::Icon(:logo))
15
+
12
16
  set_size_hints(Wx::DEFAULT_SIZE)
13
17
 
14
18
  main_sizer = Wx::VBoxSizer.new
@@ -44,6 +48,8 @@ class MainFrame < Wx::Frame
44
48
  GRID = self.new(14)
45
49
  FLEXGRID = self.new(15)
46
50
  STANDALONELINE = self.new(16)
51
+ VBOX = self.new(17)
52
+ HBOX = self.new(18)
47
53
  end
48
54
 
49
55
  module ID
@@ -52,12 +58,20 @@ class MainFrame < Wx::Frame
52
58
  # menu IDs
53
59
  #---------------------------------------------------------------#
54
60
  M_SAVEASBITMAP = self.next_id
61
+ M_SHAPE_LIST = self.next_id
62
+ M_GRID_COLUMNS = self.next_id
63
+ M_GRIDCOLS_1 = self.next_id
64
+ M_GRIDCOLS_2 = self.next_id
65
+ M_GRIDCOLS_3 = self.next_id
66
+ M_GRIDCOLS_4 = self.next_id
67
+ M_GRIDCOLS_5 = self.next_id
68
+ M_GRIDCOLS_CUSTOM = self.next_id
69
+ M_GRIDCOLS_NR = self.next_id
55
70
 
56
71
  # tool IDs
57
72
  #---------------------------------------------------------------#
58
73
  T_FIRST_TOOLMARKER = self.next_id
59
- T_GRID = self.next_id
60
- T_SHADOW = self.next_id
74
+ T_SETTINGS = self.next_id
61
75
  T_GC = self.next_id
62
76
  T_TOOL = self.next_id
63
77
  T_RECTSHP = self.next_id
@@ -71,6 +85,8 @@ class MainFrame < Wx::Frame
71
85
  T_BITMAPSHP = self.next_id
72
86
  T_GRIDSHP = self.next_id
73
87
  T_FLEXGRIDSHP = self.next_id
88
+ T_VBOXSHP = self.next_id
89
+ T_HBOXSHP = self.next_id
74
90
  T_LINESHP = self.next_id
75
91
  T_STANDALONELINESHP = self.next_id
76
92
  T_CURVESHP = self.next_id
@@ -92,44 +108,165 @@ class MainFrame < Wx::Frame
92
108
  #---------------------------------------------------------------#
93
109
  T_COLORPICKER = self.next_id(M_AUTOLAYOUT_LAST) + 1
94
110
  end
95
-
111
+
112
+ FILE_MASK = 'JSON files (*.json)|*.json|YAML files (*.yaml,*.yml)|*.yaml;*.yml|XML files (*.xml)|*.xml'
113
+ if Wx::PLATFORM == 'WXMSW'
114
+ FILE_MASK << '|All files (*.*)|*.*'
115
+ else
116
+ FILE_MASK << '|All files (*)|*'
117
+ end
118
+
119
+ class DiagramFileDialog < Wx::FileDialogCustomizeHook
120
+
121
+ FORMATS = %w[json yaml xml]
122
+
123
+ def initialize(dlg, compact: nil)
124
+ super()
125
+ @format = nil
126
+ @compact = compact.nil? ? nil : !!compact
127
+ @choice = nil
128
+ @checkbox = nil
129
+ @dialog = dlg
130
+ @dialog.set_customize_hook(self)
131
+ end
132
+
133
+ attr_reader :format, :compact
134
+
135
+ def add_custom_controls(customizer)
136
+ customizer.add_static_text('Format:')
137
+ @choice = customizer.add_choice(FORMATS)
138
+ unless @compact.nil?
139
+ @checkbox = customizer.add_check_box('Compact content')
140
+ @checkbox.set_value(true)
141
+ end
142
+ end
143
+
144
+ def get_filter_index
145
+ if Wx::PLATFORM == 'WXGTK'
146
+ @dialog.get_filter_index
147
+ else
148
+ @dialog.get_currently_selected_filter_index
149
+ end
150
+ end
151
+
152
+ def update_custom_controls
153
+ if get_filter_index<0 || get_filter_index >= FORMATS.size
154
+ @choice.enable(true)
155
+ else
156
+ @choice.enable(false)
157
+ end
158
+ end
159
+
160
+ def transfer_data_from_custom_controls
161
+ @format = case @choice.get_selection
162
+ when Wx::NOT_FOUND then nil
163
+ else
164
+ FORMATS[@choice.get_selection].to_sym
165
+ end
166
+ @compact = @checkbox.get_value if @checkbox
167
+ @dialog = nil
168
+ end
169
+ end
170
+
96
171
  def initialize(parent, title: 'wxShapeFramework Demo Application', style: Wx::CLOSE_BOX|Wx::DEFAULT_FRAME_STYLE|Wx::RESIZE_BORDER|Wx::TAB_TRAVERSAL)
97
172
  super
98
173
 
99
- set_icon(Wx::Icon(:sample))
174
+ set_icon(Wx::Icon(:logo))
100
175
 
101
176
  setup_frame
102
177
 
103
- @file_menu.append(Wx::ID_NEW, "&New\tCtrl+N", "New chart", Wx::ITEM_NORMAL)
104
- @file_menu.append(Wx::ID_OPEN, "&Open\tCtrl+O", "Load a chart from file", Wx::ITEM_NORMAL)
105
- @file_menu.append(Wx::ID_SAVE, "&Save as...\tCtrl+Shift+S", "Save the chart to file", Wx::ITEM_NORMAL)
178
+ mi = Wx::MenuItem.new(@file_menu, Wx::ID_NEW, "&New\tCtrl+N", "New chart")
179
+ mi.set_bitmap(Wx::ArtProvider.get_bitmap(Wx::ART_NEW, Wx::ART_MENU))
180
+ @file_menu.append mi
181
+ mi = Wx::MenuItem.new(@file_menu, Wx::ID_OPEN, "&Open\tCtrl+O", "Load a chart from file")
182
+ mi.set_bitmap(Wx::ArtProvider.get_bitmap(Wx::ART_FILE_OPEN, Wx::ART_MENU))
183
+ @file_menu.append mi
184
+ mi = Wx::MenuItem.new(@file_menu, Wx::ID_SAVE, "&Save as...\tCtrl+Shift+S", "Save the chart to file")
185
+ mi.set_bitmap(Wx::ArtProvider.get_bitmap(Wx::ART_FILE_SAVE, Wx::ART_MENU))
186
+ @file_menu.append mi
106
187
  @file_menu.append_separator
107
188
  @file_menu.append(ID::M_SAVEASBITMAP, "&Export to image...", "Export the chart to BMP file", Wx::ITEM_NORMAL)
108
189
  @file_menu.append_separator
109
- @file_menu.append(Wx::ID_PRINT, "&Print...\tCtrl+P", "Open print dialog", Wx::ITEM_NORMAL)
110
- @file_menu.append(Wx::ID_PREVIEW, "Print pre&view...\tAlt+P", "Open print preview window", Wx::ITEM_NORMAL)
190
+ mi = Wx::MenuItem.new(@file_menu, Wx::ID_PRINT, "&Print...\tCtrl+P", "Open print dialog")
191
+ mi.set_bitmap(Wx::ArtProvider.get_bitmap(Wx::ART_PRINT, Wx::ART_MENU))
192
+ @file_menu.append mi
193
+ mi = Wx::MenuItem.new(@file_menu, Wx::ID_PREVIEW, "Print pre&view...\tAlt+P", "Open print preview window")
194
+ mi.set_bitmap(Wx::ArtProvider.get_bitmap(Wx::ART_FIND, Wx::ART_MENU))
195
+ @file_menu.append mi
111
196
  @file_menu.append(Wx::ID_PAGE_SETUP, "Pa&ge setup...", "Set print page properties", Wx::ITEM_NORMAL)
112
197
  @file_menu.append_separator
113
- @file_menu.append(Wx::ID_EXIT, "E&xit\tAlt+X", "Close application", Wx::ITEM_NORMAL)
114
-
115
- @edit_menu.append(Wx::ID_UNDO, "&Undo\tCtrl+Z", "Discard previous action", Wx::ITEM_NORMAL)
116
- @edit_menu.append(Wx::ID_REDO, "&Redo\tCtrl+Y", "Re-do previously discarded action", Wx::ITEM_NORMAL)
198
+ mi = Wx::MenuItem.new(@file_menu, Wx::ID_EXIT, "E&xit\tAlt+X", "Close application")
199
+ mi.set_bitmap(Wx::ArtProvider.get_bitmap(Wx::ART_QUIT, Wx::ART_MENU))
200
+ @file_menu.append mi
201
+
202
+ mi = Wx::MenuItem.new(@edit_menu, Wx::ID_UNDO, "&Undo\tCtrl+Z", "Discard previous action")
203
+ mi.set_bitmap(Wx::ArtProvider.get_bitmap(Wx::ART_UNDO, Wx::ART_MENU))
204
+ @edit_menu.append mi
205
+ mi = Wx::MenuItem.new(@edit_menu, Wx::ID_REDO, "&Redo\tCtrl+Y", "Re-do previously discarded action")
206
+ mi.set_bitmap(Wx::ArtProvider.get_bitmap(Wx::ART_REDO, Wx::ART_MENU))
207
+ @edit_menu.append mi
117
208
  @edit_menu.append_separator
118
- @edit_menu.append(Wx::ID_SELECTALL, "Select &all\tCtrl+A", "Select all shapes", Wx::ITEM_NORMAL)
209
+ mi = Wx::MenuItem.new(@edit_menu, Wx::ID_SELECTALL, "Select &all\tCtrl+A", "Select all shapes")
210
+ mi.set_bitmap(Wx::ArtProvider.get_bitmap(Wx::MDAP::ART_SELECT_ALL, Wx::MDAP::ART_MATERIAL_DESIGN_OUTLINED,
211
+ Wx::ArtProvider.get_native_size_hint(Wx::ART_MENU)))
212
+ @edit_menu.append mi
119
213
  @edit_menu.append_separator
120
- @edit_menu.append(Wx::ID_COPY, "&Copy\tCtrl+C", "Copy shapes to the clipboard", Wx::ITEM_NORMAL)
121
- @edit_menu.append(Wx::ID_CUT, "Cu&t\tCtrl+X", "Cut shapes to the clipboard", Wx::ITEM_NORMAL)
122
- @edit_menu.append(Wx::ID_PASTE, "&Paste\tCtrl+V", "Paste shapes to the canvas", Wx::ITEM_NORMAL)
214
+ mi = Wx::MenuItem.new(@edit_menu, Wx::ID_COPY, "&Copy\tCtrl+C", "Copy shapes to the clipboard")
215
+ mi.set_bitmap(Wx::ArtProvider.get_bitmap(Wx::ART_COPY, Wx::ART_MENU))
216
+ @edit_menu.append mi
217
+ mi = Wx::MenuItem.new(@edit_menu, Wx::ID_CUT, "Cu&t\tCtrl+X", "Cut shapes to the clipboard")
218
+ mi.set_bitmap(Wx::ArtProvider.get_bitmap(Wx::ART_CUT, Wx::ART_MENU))
219
+ @edit_menu.append mi
220
+ mi = Wx::MenuItem.new(@edit_menu, Wx::ID_PASTE, "&Paste\tCtrl+V", "Paste shapes to the canvas")
221
+ mi.set_bitmap(Wx::ArtProvider.get_bitmap(Wx::ART_PASTE, Wx::ART_MENU))
222
+ @edit_menu.append mi
223
+
224
+ submenu = Wx::Menu.new
225
+ submenu.append_radio_item(ID::T_TOOL, 'Design tool', 'Design tool')
226
+ submenu.append_radio_item(ID::T_RECTSHP, 'Rectangle', 'Rectangle')
227
+ submenu.append_radio_item(ID::T_SQUARESHP, 'Square', 'Square')
228
+ submenu.append_radio_item(ID::T_RNDRECTSHP, 'RoundRect', 'Rounded ractangle')
229
+ submenu.append_radio_item(ID::T_ELLIPSESHP, 'Ellipse', 'Ellipse')
230
+ submenu.append_radio_item(ID::T_CIRCLESHP, 'Circle', 'Circle')
231
+ submenu.append_radio_item(ID::T_DIAMONDSHP, 'Diamond', 'Diamond')
232
+ submenu.append_radio_item(ID::T_TEXTSHP, 'Text', 'Text')
233
+ submenu.append_radio_item(ID::T_EDITTEXTSHP, 'Editable Text', 'Editable Text')
234
+ submenu.append_radio_item(ID::T_BITMAPSHP, 'Bitmap', 'Bitmap')
235
+ submenu.append_radio_item(ID::T_GRIDSHP, 'Grid', 'Grid')
236
+ submenu.append_radio_item(ID::T_FLEXGRIDSHP, 'Flexible Grid', 'Flexible Grid')
237
+ submenu.append_radio_item(ID::T_VBOXSHP, 'Vertical Box', 'Vertical Box')
238
+ submenu.append_radio_item(ID::T_HBOXSHP, 'Horizontal Box', 'Horizontal Box')
239
+ submenu.append_radio_item(ID::T_LINESHP, 'Line', 'Connector Line')
240
+ submenu.append_radio_item(ID::T_CURVESHP, 'Curved Line', 'Curved Connector Line')
241
+ submenu.append_radio_item(ID::T_ORTHOSHP, 'Orthogonal Line', 'Orthogonal Connector Line')
242
+ submenu.append_radio_item(ID::T_RNDORTHOSHP, 'Rounded Orthogonal Line', 'Rounded Orthogonal Connector Line')
243
+ submenu.append_radio_item(ID::T_STANDALONELINESHP, 'Standalone Line', 'Standalone Line')
244
+ mi = Wx::MenuItem.new(@shape_menu, ID::M_SHAPE_LIST, 'Select shape', 'Select shape', Wx::ITEM_NORMAL, submenu)
245
+ @shape_menu.append(mi)
246
+ @shape_menu.append_separator
247
+ submenu = Wx::Menu.new
248
+ submenu.append_radio_item(ID::M_GRIDCOLS_1, '1 column', '1 column')
249
+ submenu.append_radio_item(ID::M_GRIDCOLS_2, '2 columns', '2 columns')
250
+ mi = submenu.append_radio_item(ID::M_GRIDCOLS_3, '3 columns', '3 columns')
251
+ mi.check(true)
252
+ submenu.append_radio_item(ID::M_GRIDCOLS_4, '4 columns', '4 columns')
253
+ submenu.append_radio_item(ID::M_GRIDCOLS_5, '5 columns', '5 columns')
254
+ @mi_gridcols_custom = submenu.append_radio_item(ID::M_GRIDCOLS_CUSTOM, 'Custom', 'Enter custom column number')
255
+ @mi_gridcol_nr = submenu.append(ID::M_GRIDCOLS_NR, 'Number of grid columns (3)', 'Select to change nr. of grid columns')
256
+ @mi_gridcol_nr.enable(false)
257
+ mi = Wx::MenuItem.new(@shape_menu, ID::M_GRID_COLUMNS, 'Set grid columns', 'Select number of grid columns', Wx::ITEM_NORMAL, submenu)
258
+ @shape_menu.append(mi)
123
259
 
124
260
  Wx::SF::AutoLayout.layout_algorithms.each_with_index do |la_name, i|
125
261
  @auto_layout_menu.append(ID::M_AUTOLAYOUT_FIRST + i, la_name)
126
262
  end
127
-
128
- @help_menu.append(Wx::ID_ABOUT, '&About...', 'About application...', Wx::ITEM_NORMAL)
129
263
 
130
- # set shape canvas and associate it with diagram
131
- @diagram = Wx::SF::Diagram.new
132
- @shape_canvas = FrameCanvas.new(@diagram, @canvas_panel, Wx::ID_ANY)
264
+ mi = Wx::MenuItem.new(@help_menu, Wx::ID_ABOUT, '&About...', 'About application...')
265
+ mi.set_bitmap(Wx::ArtProvider.get_bitmap(Wx::ART_INFORMATION, Wx::ART_MENU))
266
+ @help_menu.append mi
267
+
268
+ # set shape canvas and associate it with a new, empty, diagram
269
+ @shape_canvas = FrameCanvas.new(Wx::SF::Diagram.new, @canvas_panel, Wx::ID_ANY)
133
270
  @canvas_sizer.add(@shape_canvas, 1, Wx::EXPAND, 0)
134
271
  @canvas_panel.layout
135
272
  # enable using Wx::GraphicsContext by default
@@ -141,16 +278,7 @@ class MainFrame < Wx::Frame
141
278
  @thumb_frm.thumbnail.set_canvas(@shape_canvas)
142
279
  @thumb_frm.show
143
280
 
144
- # create colour picker
145
- if Wx::PLATFORM == 'WXMSW'
146
- @cpicker = Wx::ColourPickerCtrl.new(@tool_bar, ID::T_COLORPICKER, Wx::Colour.new(120, 120, 255), Wx::DEFAULT_POSITION, Wx::Size.new(22, 22))
147
- else
148
- @cpicker = Wx::ColourPickerCtrl.new(@tool_bar, ID::T_COLORPICKER, Wx::Colour.new(120, 120, 255), Wx::DEFAULT_POSITION, Wx::Size.new(28, 28))
149
- end
150
- @cpicker.set_tool_tip('Set hover color')
151
-
152
- # add m_pToolBar tools
153
- @tool_bar.set_tool_bitmap_size([16, 15])
281
+ # add tool_bar tools
154
282
  @tool_bar.add_tool(Wx::ID_NEW, 'New', Wx::ArtProvider.get_bitmap(Wx::ART_NEW, Wx::ART_MENU), 'New diagram')
155
283
  @tool_bar.add_tool(Wx::ID_OPEN, 'Load', Wx::ArtProvider.get_bitmap(Wx::ART_FILE_OPEN, Wx::ART_MENU), 'Open file...')
156
284
  @tool_bar.add_tool(Wx::ID_SAVE, 'Save', Wx::ArtProvider.get_bitmap(Wx::ART_FILE_SAVE, Wx::ART_MENU), 'Save file...')
@@ -165,13 +293,11 @@ class MainFrame < Wx::Frame
165
293
  @tool_bar.add_tool(Wx::ID_UNDO, 'Undo', Wx::ArtProvider.get_bitmap(Wx::ART_UNDO, Wx::ART_MENU), 'Undo')
166
294
  @tool_bar.add_tool(Wx::ID_REDO, 'Redo', Wx::ArtProvider.get_bitmap(Wx::ART_REDO, Wx::ART_MENU), 'Redo')
167
295
  @tool_bar.add_separator
168
- @tool_bar.add_check_tool(ID::T_GRID, 'Grid', Wx::Bitmap(:Grid), Wx::NULL_BITMAP, 'Show/hide grid')
169
- @tool_bar.add_check_tool(ID::T_SHADOW, 'Shadows', Wx::Bitmap(:Shadow), Wx::NULL_BITMAP, 'Show/hide shadows')
170
- @tool_bar.add_check_tool(ID::T_GC, 'Enhanced graphics context', Wx::Bitmap(:GC), Wx::NULL_BITMAP, 'Use enhanced graphics context (Wx::GraphicsContext)')
296
+ @tool_bar.add_tool(ID::T_SETTINGS, 'Settings', Wx::ArtProvider.get_bitmap(Wx::ART_HELP_SETTINGS, Wx::ART_MENU), 'Settings')
171
297
  @tool_bar.add_separator
172
298
  @tool_bar.add_radio_tool(ID::T_TOOL, 'Tool', Wx::Bitmap(:Tool), Wx::NULL_BITMAP, 'Design tool')
173
299
  @tool_bar.add_radio_tool(ID::T_RECTSHP, 'Rectangle', Wx::Bitmap(:Rect), Wx::NULL_BITMAP, 'Rectangle')
174
- @tool_bar.add_radio_tool(ID::T_SQUARESHP, 'Fixed rectangle', Wx::Bitmap(:FixedRect), Wx::NULL_BITMAP, 'Fixed rectangle')
300
+ @tool_bar.add_radio_tool(ID::T_SQUARESHP, 'Square', Wx::Bitmap(:FixedRect), Wx::NULL_BITMAP, 'Square')
175
301
  @tool_bar.add_radio_tool(ID::T_RNDRECTSHP, 'RoundRect', Wx::Bitmap(:RoundRect), Wx::NULL_BITMAP, 'Rounded rectangle')
176
302
  @tool_bar.add_radio_tool(ID::T_ELLIPSESHP, 'Ellipse', Wx::Bitmap(:Ellipse), Wx::NULL_BITMAP, 'Ellipse')
177
303
  @tool_bar.add_radio_tool(ID::T_CIRCLESHP, 'Circle', Wx::Bitmap(:Circle), Wx::NULL_BITMAP, 'Circle')
@@ -181,6 +307,8 @@ class MainFrame < Wx::Frame
181
307
  @tool_bar.add_radio_tool(ID::T_BITMAPSHP, 'Bitmap', Wx::Bitmap(:Bitmap), Wx::NULL_BITMAP, 'Bitmap')
182
308
  @tool_bar.add_radio_tool(ID::T_GRIDSHP, 'Grid shape', Wx::Bitmap(:Grid), Wx::NULL_BITMAP, 'Grid shape')
183
309
  @tool_bar.add_radio_tool(ID::T_FLEXGRIDSHP, 'Flexible grid shape', Wx::Bitmap(:FlexGrid), Wx::NULL_BITMAP, 'Flexible grid shape')
310
+ @tool_bar.add_radio_tool(ID::T_VBOXSHP, 'Vertical Box shape', Wx::Bitmap(:VBox), Wx::NULL_BITMAP, 'Vertical Box shape')
311
+ @tool_bar.add_radio_tool(ID::T_HBOXSHP, 'Horizontal Box shape', Wx::Bitmap(:HBox), Wx::NULL_BITMAP, 'Horizontal Box shape')
184
312
  @tool_bar.add_radio_tool(ID::T_LINESHP, 'Line', Wx::Bitmap(:Line), Wx::NULL_BITMAP, 'Polyline connection')
185
313
  @tool_bar.add_radio_tool(ID::T_CURVESHP, 'Curve', Wx::Bitmap(:Curve), Wx::NULL_BITMAP, 'Curve connection')
186
314
  @tool_bar.add_radio_tool(ID::T_ORTHOSHP, 'Ortho line', Wx::Bitmap(:OrthoLine), Wx::NULL_BITMAP, 'Orthogonal connection')
@@ -193,17 +321,17 @@ class MainFrame < Wx::Frame
193
321
  @tool_bar.add_tool(ID::T_ALIGN_BOTTOM, 'Align bottom', Wx::Bitmap(:AlignBottom), 'Align selected shapes to the bottom')
194
322
  @tool_bar.add_tool(ID::T_ALIGN_MIDDLE, 'Align middle', Wx::Bitmap(:AlignMiddle), 'Align selected shapes to the middle')
195
323
  @tool_bar.add_tool(ID::T_ALIGN_CENTER, 'Align center', Wx::Bitmap(:AlignCenter), 'Align selected shapes to the center')
196
- @tool_bar.add_separator
197
- @tool_bar.add_control(@cpicker)
198
324
  @tool_bar.realize
199
325
 
200
326
  @status_bar.set_status_text('Ready')
201
327
 
202
328
  # initialize data members
203
329
  @tool_mode = MODE::DESIGN
330
+ @grid_columns = 3
204
331
  @show_grid = true
205
332
  @show_shadows = false
206
333
 
334
+ set_size([1280, 800])
207
335
  centre
208
336
 
209
337
  # setup event handlers
@@ -226,6 +354,7 @@ class MainFrame < Wx::Frame
226
354
  evt_menu_range(ID::M_AUTOLAYOUT_FIRST, ID::M_AUTOLAYOUT_LAST, :on_auto_layout)
227
355
  evt_command_scroll(Wx::ID_ZOOM_FIT, :on_slider)
228
356
  evt_tool_range(ID::T_FIRST_TOOLMARKER, ID::T_LAST_TOOLMARKER, :on_tool)
357
+ evt_menu_range(ID::M_GRIDCOLS_1, ID::M_GRIDCOLS_NR, :on_grid_columns)
229
358
  evt_colourpicker_changed(ID::T_COLORPICKER, :on_hover_color)
230
359
  evt_update_ui(Wx::ID_COPY, :on_update_copy)
231
360
  evt_update_ui(Wx::ID_CUT, :on_update_cut)
@@ -234,19 +363,21 @@ class MainFrame < Wx::Frame
234
363
  evt_update_ui(Wx::ID_REDO, :on_update_redo)
235
364
  evt_update_ui_range(ID::T_FIRST_TOOLMARKER, ID::T_LAST_TOOLMARKER, :on_update_tool)
236
365
  evt_update_ui_range(ID::M_AUTOLAYOUT_FIRST, ID::M_AUTOLAYOUT_LAST, :on_update_auto_layout)
366
+ evt_update_ui(@mi_gridcol_nr, :on_update_gridcol_nr)
237
367
  evt_idle(:on_idle)
238
368
  end
239
369
 
240
370
  attr_accessor :tool_mode, :show_grid, :show_shadows
241
371
 
242
- attr_reader :zoom_slider
372
+ attr_reader :grid_columns, :zoom_slider
373
+
374
+ def diagram
375
+ @shape_canvas&.diagram
376
+ end
377
+ private :diagram
243
378
 
244
379
  def setup_frame
245
- if Wx::PLATFORM == 'WXMSW'
246
- set_size_hints([1024,700])
247
- else
248
- set_size_hints([1100,700])
249
- end
380
+ set_size_hints([1024, 640])
250
381
 
251
382
  @menu_bar = Wx::MenuBar.new(0)
252
383
  @file_menu = Wx::Menu.new
@@ -254,7 +385,10 @@ class MainFrame < Wx::Frame
254
385
 
255
386
  @edit_menu = Wx::Menu.new
256
387
  @menu_bar.append(@edit_menu, "&Edit")
257
-
388
+
389
+ @shape_menu = Wx::Menu.new
390
+ @menu_bar.append(@shape_menu, "&Shapes")
391
+
258
392
  @auto_layout_menu = Wx::Menu.new
259
393
  @menu_bar.append(@auto_layout_menu, "&AutoLayout")
260
394
 
@@ -262,22 +396,28 @@ class MainFrame < Wx::Frame
262
396
  @menu_bar.append(@help_menu, "&Help")
263
397
 
264
398
  set_menu_bar(@menu_bar)
265
-
266
- @tool_bar = create_tool_bar(Wx::TB_HORIZONTAL, Wx::ID_ANY)
267
- @tool_bar.realize
268
-
399
+
269
400
  @status_bar = create_status_bar(1, Wx::STB_SIZEGRIP, Wx::ID_ANY)
270
- main_sizer = Wx::FlexGridSizer.new(2, 1, 0, 0)
401
+ main_sizer = Wx::FlexGridSizer.new(3, 1, 0, 0)
271
402
  main_sizer.add_growable_col(0)
272
- main_sizer.add_growable_row(0)
403
+ main_sizer.add_growable_row(1)
273
404
  main_sizer.set_flexible_direction(Wx::BOTH)
274
405
  main_sizer.set_non_flexible_grow_mode(Wx::FLEX_GROWMODE_SPECIFIED)
275
-
406
+
407
+ tool_bar_panel = Wx::Panel.new(self, Wx::ID_ANY)
408
+ tool_bar_sizer = Wx::VBoxSizer.new
409
+ @tool_bar = Wx::ToolBar.new(tool_bar_panel, style: Wx::TB_HORIZONTAL | Wx::NO_BORDER | Wx::TB_FLAT)
410
+ @tool_bar.realize
411
+ tool_bar_sizer.add(@tool_bar, 0, Wx::EXPAND)
412
+ tool_bar_panel.sizer = tool_bar_sizer
413
+ tool_bar_panel.layout
414
+ main_sizer.add(tool_bar_panel, 0, Wx::EXPAND, 5)
415
+
276
416
  @canvas_panel = Wx::Panel.new(self, Wx::ID_ANY, style: Wx::TAB_TRAVERSAL)
277
417
  @canvas_panel.set_extra_style(Wx::WS_EX_BLOCK_EVENTS)
278
418
 
279
419
  @canvas_sizer = Wx::VBoxSizer.new
280
-
420
+
281
421
  @canvas_panel.set_sizer(@canvas_sizer)
282
422
  @canvas_panel.layout
283
423
  @canvas_sizer.fit(@canvas_panel)
@@ -299,8 +439,8 @@ class MainFrame < Wx::Frame
299
439
  protected
300
440
 
301
441
  def clean_up
302
- @diagram.set_shape_canvas(nil)
303
- @diagram.clear
442
+ diagram.set_shape_canvas(nil)
443
+ diagram.clear
304
444
 
305
445
  @thumb_frm.hide
306
446
  @thumb_frm.thumbnail.set_canvas(nil)
@@ -314,7 +454,7 @@ class MainFrame < Wx::Frame
314
454
  end
315
455
 
316
456
  def on_idle(_event)
317
- if @diagram.is_modified
457
+ if diagram.is_modified
318
458
  set_title('wxRuby ShapeFramework Demo (diagram is modified)')
319
459
  else
320
460
  set_title('wxRuby ShapeFramework Demo')
@@ -329,7 +469,7 @@ class MainFrame < Wx::Frame
329
469
  def on_new(_event)
330
470
  if Wx.message_box('Current chart will be lost. Do you want to proceed?',
331
471
  'wxRuby ShapeFramework', Wx::YES_NO | Wx::ICON_QUESTION) == Wx::YES
332
- @diagram.clear
472
+ diagram.clear
333
473
 
334
474
  @shape_canvas.clear_canvas_history
335
475
  @shape_canvas.save_canvas_state
@@ -339,24 +479,79 @@ class MainFrame < Wx::Frame
339
479
  end
340
480
 
341
481
  def on_save(_event)
342
- Wx::FileDialog(self, 'Save canvas to file...', Dir.getwd, '', 'JSON Files (*.json)|*.json', Wx::FD_SAVE | Wx::FD_OVERWRITE_PROMPT) do |dlg|
482
+ Wx.FileDialog(self, 'Save canvas to file...', __dir__, '', FILE_MASK, Wx::FD_SAVE) do |dlg|
483
+ dlg.set_filter_index(0)
484
+ dlg_hook = DiagramFileDialog.new(dlg, compact: true)
343
485
  if dlg.show_modal == Wx::ID_OK
344
- @shape_canvas.save_canvas(dlg.get_path)
345
-
346
- Wx.message_box("The chart has been saved to '#{dlg.get_path}'.", 'wxRuby ShapeFramework')
486
+ check_overwrite = Wx::PLATFORM != 'WXOSX'
487
+ begin
488
+ path = dlg.get_path.dup
489
+ selected_filter = dlg.get_filter_index
490
+ ext = File.extname(path)
491
+ if ext == '.' && !(Wx::PLATFORM == 'WXOSX' && File.exist?(path))
492
+ ext = ''
493
+ path = File.join(File.dirname(path), File.basename(path, '.*'))
494
+ check_overwrite = true
495
+ end
496
+ if ext.empty?
497
+ format = if selected_filter < 0 || selected_filter >= DiagramFileDialog::FORMATS.size
498
+ dlg_hook.format || :json
499
+ else
500
+ DiagramFileDialog::FORMATS[selected_filter].to_sym
501
+ end
502
+ if selected_filter < DiagramFileDialog::FORMATS.size && !(Wx::PLATFORM == 'WXOSX' && File.exist?(path))
503
+ # determine extension to provide
504
+ case format
505
+ when :json then path << '.json'
506
+ when :yaml then path << '.yaml'
507
+ when :xml then path << '.xml'
508
+ end
509
+ check_overwrite = true
510
+ end
511
+ else
512
+ format = case File.extname(dlg.get_path)
513
+ when '.json' then :json
514
+ when '.yaml', '.yml' then :yaml
515
+ when '.xml' then :xml
516
+ else
517
+ if selected_filter < 0 || selected_filter >= DiagramFileDialog::FORMATS.size
518
+ dlg_hook.format || :json
519
+ else
520
+ DiagramFileDialog::FORMATS[selected_filter].to_sym
521
+ end
522
+ end
523
+ end
524
+ if !check_overwrite || !File.exist?(path) ||
525
+ Wx.message_box("File '#{File.basename(path)}' already exists in folder '#{File.dirname(path)}'.\nDo you want to overwrite it?", 'Confirm', Wx::YES_NO) == Wx::YES
526
+ @shape_canvas.save_canvas(path, compact: dlg_hook.compact, format: format)
527
+
528
+ Wx.MessageDialog(self, "The chart has been saved to '#{path}'.", 'wxRuby ShapeFramework', Wx::OK | Wx::ICON_INFORMATION)
529
+ end
530
+ rescue Exception => ex
531
+ Wx.MessageDialog(self, "Failed to save the chart: #{ex.message}", 'wxRuby ShapeFramework', Wx::OK | Wx::ICON_ERROR)
532
+ end
347
533
  end
348
534
  end
349
535
  end
350
536
 
351
537
  def on_load(_event)
352
- Wx::FileDialog(self, 'Load canvas from file...', Dir.getwd, '', 'JSON Files (*.json)|*.json', Wx::FD_OPEN | Wx::FD_FILE_MUST_EXIST) do |dlg|
538
+ Wx.FileDialog(self, 'Load canvas from file...', __dir__, '', FILE_MASK, Wx::FD_OPEN | Wx::FD_FILE_MUST_EXIST) do |dlg|
539
+ dlg_hook = DiagramFileDialog.new(dlg)
353
540
  if dlg.show_modal == Wx::ID_OK
354
- @shape_canvas.load_canvas(dlg.get_path)
355
- @diagram = @shape_canvas.get_diagram
356
-
357
- @zoom_slider.set_value((@shape_canvas.get_scale*50).to_i)
358
-
359
- @cpicker.set_colour(@shape_canvas.get_hover_colour)
541
+ begin
542
+ format = case File.extname(dlg.get_path)
543
+ when '.json' then :json
544
+ when '.yaml', '.yml' then :yaml
545
+ when '.xml' then :xml
546
+ else
547
+ dlg_hook.format || :json
548
+ end
549
+ @shape_canvas.load_canvas(dlg.get_path, format: format)
550
+
551
+ @zoom_slider.set_value((@shape_canvas.get_scale*50).to_i)
552
+ rescue Exception => ex
553
+ Wx.MessageDialog(self, "Failed to load the chart: #{ex.message}", 'wxRuby ShapeFramework', Wx::OK | Wx::ICON_ERROR)
554
+ end
360
555
  end
361
556
  end
362
557
  end
@@ -448,30 +643,14 @@ class MainFrame < Wx::Frame
448
643
  @shape_canvas.abort_interactive_connection if @shape_canvas.get_mode == Wx::SF::ShapeCanvas::MODE::CREATECONNECTION
449
644
 
450
645
  case event.get_id
451
- when ID::T_GRID
452
- @show_grid = !@show_grid
453
- if @show_grid
454
- @shape_canvas.add_style(Wx::SF::ShapeCanvas::STYLE::GRID_SHOW)
455
- @shape_canvas.add_style(Wx::SF::ShapeCanvas::STYLE::GRID_USE)
456
- else
457
- @shape_canvas.remove_style(Wx::SF::ShapeCanvas::STYLE::GRID_SHOW)
458
- @shape_canvas.remove_style(Wx::SF::ShapeCanvas::STYLE::GRID_USE)
459
- end
460
- @shape_canvas.refresh(false)
461
-
462
- when ID::T_SHADOW
463
- @show_shadows = !@show_shadows
464
-
465
- @shape_canvas.show_shadows(@show_shadows, Wx::SF::ShapeCanvas::SHADOWMODE::ALL)
466
- # also shadows for topmost shapes only are allowed:
467
- # @shape_canvas.show_shadows(@show_shadows, Wx::SF::ShapeCanvas::SHADOWMODE::TOPMOST)
468
- @shape_canvas.refresh(false)
646
+ when ID::T_SETTINGS
647
+ Dialogs::WXSFPreferencesDialog(self, @shape_canvas)
469
648
 
470
649
  when ID::T_GC
471
650
  if Wx.has_feature?(:USE_GRAPHICS_CONTEXT)
472
651
  Wx::SF::ShapeCanvas.enable_gc(!Wx::SF::ShapeCanvas.gc_enabled?)
473
652
  # update all shapes in the manager
474
- @diagram.update_all
653
+ diagram.update_all
475
654
  # refresh shape canvas
476
655
  @shape_canvas.refresh(false)
477
656
  else
@@ -508,6 +687,12 @@ class MainFrame < Wx::Frame
508
687
  when ID::T_FLEXGRIDSHP
509
688
  @tool_mode = MODE::FLEXGRID
510
689
 
690
+ when ID::T_VBOXSHP
691
+ @tool_mode = MODE::VBOX
692
+
693
+ when ID::T_HBOXSHP
694
+ @tool_mode = MODE::HBOX
695
+
511
696
  when ID::T_LINESHP
512
697
  @tool_mode = MODE::LINE
513
698
 
@@ -552,6 +737,16 @@ class MainFrame < Wx::Frame
552
737
  end
553
738
  end
554
739
 
740
+ def on_grid_columns(event)
741
+ if event.get_id == ID::M_GRIDCOLS_CUSTOM || event.get_id == ID::M_GRIDCOLS_NR
742
+ n = Wx.get_number_from_user('Enter custom grid column number.', 'Nr. of columns:',
743
+ 'Grid columns', @grid_columns, 1, 100, self)
744
+ @grid_columns = n unless n <= 0
745
+ else
746
+ @grid_columns = 1 + event.get_id-ID::M_GRIDCOLS_1
747
+ end
748
+ end
749
+
555
750
  def on_hover_color(event)
556
751
  @shape_canvas.set_hover_colour(event.get_colour)
557
752
  end
@@ -578,9 +773,6 @@ class MainFrame < Wx::Frame
578
773
 
579
774
  def on_update_tool(event)
580
775
  case event.get_id
581
- when ID::T_GRID
582
- event.check(@show_grid)
583
-
584
776
  when ID::T_GC
585
777
  event.check(Wx::SF::ShapeCanvas.gc_enabled?)
586
778
 
@@ -614,6 +806,12 @@ class MainFrame < Wx::Frame
614
806
  when ID::T_FLEXGRIDSHP
615
807
  event.check(@tool_mode == MODE::FLEXGRID)
616
808
 
809
+ when ID::T_VBOXSHP
810
+ event.check(@tool_mode == MODE::VBOX)
811
+
812
+ when ID::T_HBOXSHP
813
+ event.check(@tool_mode == MODE::HBOX)
814
+
617
815
  when ID::T_LINESHP
618
816
  event.check(@tool_mode == MODE::LINE)
619
817
 
@@ -649,10 +847,22 @@ class MainFrame < Wx::Frame
649
847
  end
650
848
 
651
849
  def on_update_auto_layout(event)
652
- event.enable(!@diagram.empty?)
850
+ event.enable(!diagram.empty?)
851
+ end
852
+
853
+ def on_update_gridcol_nr(_event)
854
+ @mi_gridcol_nr.enable(@mi_gridcols_custom.checked?)
855
+ @mi_gridcol_nr.set_item_label("Number of grid columns (#{@grid_columns})")
653
856
  end
857
+
858
+ end
859
+
860
+ if Wx::PLATFORM == 'WXOSX' && !Wx.const_defined?(:OSX_FILEDIALOG_ALWAYS_SHOW_TYPES)
861
+ Wx::OSX_FILEDIALOG_ALWAYS_SHOW_TYPES = 'osx.openfiledialog.always-show-types'
654
862
  end
655
863
 
656
864
  Wx::App.run do
865
+ Wx::SystemOptions.set_option(Wx::OSX_FILEDIALOG_ALWAYS_SHOW_TYPES, 1) if Wx::PLATFORM == 'WXOSX'
866
+ Wx::ArtProvider.push(Wx::MDAP::MaterialDesignArtProvider.new)
657
867
  MainFrame.new(nil).show
658
868
  end