samples/demo/demo.rb in wxruby3-shapes-0.9.0.pre.beta.3 vs samples/demo/demo.rb in wxruby3-shapes-0.9.5

- old
+ new

@@ -1,16 +1,20 @@ # Wx::SF - Demo ThumbFrame, MainFrame and App # Copyright (c) M.J.N. Corino, The Netherlands +require 'nokogiri' require 'wx/shapes' +require 'wx/mdap' require_relative './frame_canvas' class ThumbFrame < Wx::Frame 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) super + set_icon(Wx::Icon(:logo)) + set_size_hints(Wx::DEFAULT_SIZE) main_sizer = Wx::VBoxSizer.new @thumbnail = Wx::SF::Thumbnail.new(self) @@ -42,24 +46,34 @@ ORTHOLINE = self.new(12) ROUNDORTHOLINE = self.new(13) GRID = self.new(14) FLEXGRID = self.new(15) STANDALONELINE = self.new(16) + VBOX = self.new(17) + HBOX = self.new(18) end module ID include Wx::IDHelper # menu IDs #---------------------------------------------------------------# M_SAVEASBITMAP = self.next_id + M_SHAPE_LIST = self.next_id + M_GRID_COLUMNS = self.next_id + M_GRIDCOLS_1 = self.next_id + M_GRIDCOLS_2 = self.next_id + M_GRIDCOLS_3 = self.next_id + M_GRIDCOLS_4 = self.next_id + M_GRIDCOLS_5 = self.next_id + M_GRIDCOLS_CUSTOM = self.next_id + M_GRIDCOLS_NR = self.next_id # tool IDs #---------------------------------------------------------------# T_FIRST_TOOLMARKER = self.next_id - T_GRID = self.next_id - T_SHADOW = self.next_id + T_SETTINGS = self.next_id T_GC = self.next_id T_TOOL = self.next_id T_RECTSHP = self.next_id T_SQUARESHP = self.next_id T_RNDRECTSHP = self.next_id @@ -69,10 +83,12 @@ T_TEXTSHP = self.next_id T_EDITTEXTSHP = self.next_id T_BITMAPSHP = self.next_id T_GRIDSHP = self.next_id T_FLEXGRIDSHP = self.next_id + T_VBOXSHP = self.next_id + T_HBOXSHP = self.next_id T_LINESHP = self.next_id T_STANDALONELINESHP = self.next_id T_CURVESHP = self.next_id T_ORTHOSHP = self.next_id T_RNDORTHOSHP = self.next_id @@ -90,48 +106,169 @@ # other controls #---------------------------------------------------------------# T_COLORPICKER = self.next_id(M_AUTOLAYOUT_LAST) + 1 end - + + FILE_MASK = 'JSON files (*.json)|*.json|YAML files (*.yaml,*.yml)|*.yaml;*.yml|XML files (*.xml)|*.xml' + if Wx::PLATFORM == 'WXMSW' + FILE_MASK << '|All files (*.*)|*.*' + else + FILE_MASK << '|All files (*)|*' + end + + class DiagramFileDialog < Wx::FileDialogCustomizeHook + + FORMATS = %w[json yaml xml] + + def initialize(dlg, compact: nil) + super() + @format = nil + @compact = compact.nil? ? nil : !!compact + @choice = nil + @checkbox = nil + @dialog = dlg + @dialog.set_customize_hook(self) + end + + attr_reader :format, :compact + + def add_custom_controls(customizer) + customizer.add_static_text('Format:') + @choice = customizer.add_choice(FORMATS) + unless @compact.nil? + @checkbox = customizer.add_check_box('Compact content') + @checkbox.set_value(true) + end + end + + def get_filter_index + if Wx::PLATFORM == 'WXGTK' + @dialog.get_filter_index + else + @dialog.get_currently_selected_filter_index + end + end + + def update_custom_controls + if get_filter_index<0 || get_filter_index >= FORMATS.size + @choice.enable(true) + else + @choice.enable(false) + end + end + + def transfer_data_from_custom_controls + @format = case @choice.get_selection + when Wx::NOT_FOUND then nil + else + FORMATS[@choice.get_selection].to_sym + end + @compact = @checkbox.get_value if @checkbox + @dialog = nil + end + end + def initialize(parent, title: 'wxShapeFramework Demo Application', style: Wx::CLOSE_BOX|Wx::DEFAULT_FRAME_STYLE|Wx::RESIZE_BORDER|Wx::TAB_TRAVERSAL) super - set_icon(Wx::Icon(:sample)) + set_icon(Wx::Icon(:logo)) setup_frame - @file_menu.append(Wx::ID_NEW, "&New\tCtrl+N", "New chart", Wx::ITEM_NORMAL) - @file_menu.append(Wx::ID_OPEN, "&Open\tCtrl+O", "Load a chart from file", Wx::ITEM_NORMAL) - @file_menu.append(Wx::ID_SAVE, "&Save as...\tCtrl+Shift+S", "Save the chart to file", Wx::ITEM_NORMAL) + mi = Wx::MenuItem.new(@file_menu, Wx::ID_NEW, "&New\tCtrl+N", "New chart") + mi.set_bitmap(Wx::ArtProvider.get_bitmap(Wx::ART_NEW, Wx::ART_MENU)) + @file_menu.append mi + mi = Wx::MenuItem.new(@file_menu, Wx::ID_OPEN, "&Open\tCtrl+O", "Load a chart from file") + mi.set_bitmap(Wx::ArtProvider.get_bitmap(Wx::ART_FILE_OPEN, Wx::ART_MENU)) + @file_menu.append mi + mi = Wx::MenuItem.new(@file_menu, Wx::ID_SAVE, "&Save as...\tCtrl+Shift+S", "Save the chart to file") + mi.set_bitmap(Wx::ArtProvider.get_bitmap(Wx::ART_FILE_SAVE, Wx::ART_MENU)) + @file_menu.append mi @file_menu.append_separator @file_menu.append(ID::M_SAVEASBITMAP, "&Export to image...", "Export the chart to BMP file", Wx::ITEM_NORMAL) @file_menu.append_separator - @file_menu.append(Wx::ID_PRINT, "&Print...\tCtrl+P", "Open print dialog", Wx::ITEM_NORMAL) - @file_menu.append(Wx::ID_PREVIEW, "Print pre&view...\tAlt+P", "Open print preview window", Wx::ITEM_NORMAL) + mi = Wx::MenuItem.new(@file_menu, Wx::ID_PRINT, "&Print...\tCtrl+P", "Open print dialog") + mi.set_bitmap(Wx::ArtProvider.get_bitmap(Wx::ART_PRINT, Wx::ART_MENU)) + @file_menu.append mi + mi = Wx::MenuItem.new(@file_menu, Wx::ID_PREVIEW, "Print pre&view...\tAlt+P", "Open print preview window") + mi.set_bitmap(Wx::ArtProvider.get_bitmap(Wx::ART_FIND, Wx::ART_MENU)) + @file_menu.append mi @file_menu.append(Wx::ID_PAGE_SETUP, "Pa&ge setup...", "Set print page properties", Wx::ITEM_NORMAL) @file_menu.append_separator - @file_menu.append(Wx::ID_EXIT, "E&xit\tAlt+X", "Close application", Wx::ITEM_NORMAL) - - @edit_menu.append(Wx::ID_UNDO, "&Undo\tCtrl+Z", "Discard previous action", Wx::ITEM_NORMAL) - @edit_menu.append(Wx::ID_REDO, "&Redo\tCtrl+Y", "Re-do previously discarded action", Wx::ITEM_NORMAL) + mi = Wx::MenuItem.new(@file_menu, Wx::ID_EXIT, "E&xit\tAlt+X", "Close application") + mi.set_bitmap(Wx::ArtProvider.get_bitmap(Wx::ART_QUIT, Wx::ART_MENU)) + @file_menu.append mi + + mi = Wx::MenuItem.new(@edit_menu, Wx::ID_UNDO, "&Undo\tCtrl+Z", "Discard previous action") + mi.set_bitmap(Wx::ArtProvider.get_bitmap(Wx::ART_UNDO, Wx::ART_MENU)) + @edit_menu.append mi + mi = Wx::MenuItem.new(@edit_menu, Wx::ID_REDO, "&Redo\tCtrl+Y", "Re-do previously discarded action") + mi.set_bitmap(Wx::ArtProvider.get_bitmap(Wx::ART_REDO, Wx::ART_MENU)) + @edit_menu.append mi @edit_menu.append_separator - @edit_menu.append(Wx::ID_SELECTALL, "Select &all\tCtrl+A", "Select all shapes", Wx::ITEM_NORMAL) + mi = Wx::MenuItem.new(@edit_menu, Wx::ID_SELECTALL, "Select &all\tCtrl+A", "Select all shapes") + mi.set_bitmap(Wx::ArtProvider.get_bitmap(Wx::MDAP::ART_SELECT_ALL, Wx::MDAP::ART_MATERIAL_DESIGN_OUTLINED, + Wx::ArtProvider.get_native_size_hint(Wx::ART_MENU))) + @edit_menu.append mi @edit_menu.append_separator - @edit_menu.append(Wx::ID_COPY, "&Copy\tCtrl+C", "Copy shapes to the clipboard", Wx::ITEM_NORMAL) - @edit_menu.append(Wx::ID_CUT, "Cu&t\tCtrl+X", "Cut shapes to the clipboard", Wx::ITEM_NORMAL) - @edit_menu.append(Wx::ID_PASTE, "&Paste\tCtrl+V", "Paste shapes to the canvas", Wx::ITEM_NORMAL) + mi = Wx::MenuItem.new(@edit_menu, Wx::ID_COPY, "&Copy\tCtrl+C", "Copy shapes to the clipboard") + mi.set_bitmap(Wx::ArtProvider.get_bitmap(Wx::ART_COPY, Wx::ART_MENU)) + @edit_menu.append mi + mi = Wx::MenuItem.new(@edit_menu, Wx::ID_CUT, "Cu&t\tCtrl+X", "Cut shapes to the clipboard") + mi.set_bitmap(Wx::ArtProvider.get_bitmap(Wx::ART_CUT, Wx::ART_MENU)) + @edit_menu.append mi + mi = Wx::MenuItem.new(@edit_menu, Wx::ID_PASTE, "&Paste\tCtrl+V", "Paste shapes to the canvas") + mi.set_bitmap(Wx::ArtProvider.get_bitmap(Wx::ART_PASTE, Wx::ART_MENU)) + @edit_menu.append mi + submenu = Wx::Menu.new + submenu.append_radio_item(ID::T_TOOL, 'Design tool', 'Design tool') + submenu.append_radio_item(ID::T_RECTSHP, 'Rectangle', 'Rectangle') + submenu.append_radio_item(ID::T_SQUARESHP, 'Square', 'Square') + submenu.append_radio_item(ID::T_RNDRECTSHP, 'RoundRect', 'Rounded ractangle') + submenu.append_radio_item(ID::T_ELLIPSESHP, 'Ellipse', 'Ellipse') + submenu.append_radio_item(ID::T_CIRCLESHP, 'Circle', 'Circle') + submenu.append_radio_item(ID::T_DIAMONDSHP, 'Diamond', 'Diamond') + submenu.append_radio_item(ID::T_TEXTSHP, 'Text', 'Text') + submenu.append_radio_item(ID::T_EDITTEXTSHP, 'Editable Text', 'Editable Text') + submenu.append_radio_item(ID::T_BITMAPSHP, 'Bitmap', 'Bitmap') + submenu.append_radio_item(ID::T_GRIDSHP, 'Grid', 'Grid') + submenu.append_radio_item(ID::T_FLEXGRIDSHP, 'Flexible Grid', 'Flexible Grid') + submenu.append_radio_item(ID::T_VBOXSHP, 'Vertical Box', 'Vertical Box') + submenu.append_radio_item(ID::T_HBOXSHP, 'Horizontal Box', 'Horizontal Box') + submenu.append_radio_item(ID::T_LINESHP, 'Line', 'Connector Line') + submenu.append_radio_item(ID::T_CURVESHP, 'Curved Line', 'Curved Connector Line') + submenu.append_radio_item(ID::T_ORTHOSHP, 'Orthogonal Line', 'Orthogonal Connector Line') + submenu.append_radio_item(ID::T_RNDORTHOSHP, 'Rounded Orthogonal Line', 'Rounded Orthogonal Connector Line') + submenu.append_radio_item(ID::T_STANDALONELINESHP, 'Standalone Line', 'Standalone Line') + mi = Wx::MenuItem.new(@shape_menu, ID::M_SHAPE_LIST, 'Select shape', 'Select shape', Wx::ITEM_NORMAL, submenu) + @shape_menu.append(mi) + @shape_menu.append_separator + submenu = Wx::Menu.new + submenu.append_radio_item(ID::M_GRIDCOLS_1, '1 column', '1 column') + submenu.append_radio_item(ID::M_GRIDCOLS_2, '2 columns', '2 columns') + mi = submenu.append_radio_item(ID::M_GRIDCOLS_3, '3 columns', '3 columns') + mi.check(true) + submenu.append_radio_item(ID::M_GRIDCOLS_4, '4 columns', '4 columns') + submenu.append_radio_item(ID::M_GRIDCOLS_5, '5 columns', '5 columns') + @mi_gridcols_custom = submenu.append_radio_item(ID::M_GRIDCOLS_CUSTOM, 'Custom', 'Enter custom column number') + @mi_gridcol_nr = submenu.append(ID::M_GRIDCOLS_NR, 'Number of grid columns (3)', 'Select to change nr. of grid columns') + @mi_gridcol_nr.enable(false) + mi = Wx::MenuItem.new(@shape_menu, ID::M_GRID_COLUMNS, 'Set grid columns', 'Select number of grid columns', Wx::ITEM_NORMAL, submenu) + @shape_menu.append(mi) + Wx::SF::AutoLayout.layout_algorithms.each_with_index do |la_name, i| @auto_layout_menu.append(ID::M_AUTOLAYOUT_FIRST + i, la_name) end - - @help_menu.append(Wx::ID_ABOUT, '&About...', 'About application...', Wx::ITEM_NORMAL) - # set shape canvas and associate it with diagram - @diagram = Wx::SF::Diagram.new - @shape_canvas = FrameCanvas.new(@diagram, @canvas_panel, Wx::ID_ANY) + mi = Wx::MenuItem.new(@help_menu, Wx::ID_ABOUT, '&About...', 'About application...') + mi.set_bitmap(Wx::ArtProvider.get_bitmap(Wx::ART_INFORMATION, Wx::ART_MENU)) + @help_menu.append mi + + # set shape canvas and associate it with a new, empty, diagram + @shape_canvas = FrameCanvas.new(Wx::SF::Diagram.new, @canvas_panel, Wx::ID_ANY) @canvas_sizer.add(@shape_canvas, 1, Wx::EXPAND, 0) @canvas_panel.layout # enable using Wx::GraphicsContext by default # (effective only if wxUSE_GRAPHICS_CONTEXT if set to 1 for wxRuby) Wx::SF::ShapeCanvas::enable_gc @@ -139,20 +276,11 @@ # create and show canvas thumbnail @thumb_frm = ThumbFrame.new(self) @thumb_frm.thumbnail.set_canvas(@shape_canvas) @thumb_frm.show - # create colour picker - if Wx::PLATFORM == 'WXMSW' - @cpicker = Wx::ColourPickerCtrl.new(@tool_bar, ID::T_COLORPICKER, Wx::Colour.new(120, 120, 255), Wx::DEFAULT_POSITION, Wx::Size.new(22, 22)) - else - @cpicker = Wx::ColourPickerCtrl.new(@tool_bar, ID::T_COLORPICKER, Wx::Colour.new(120, 120, 255), Wx::DEFAULT_POSITION, Wx::Size.new(28, 28)) - end - @cpicker.set_tool_tip('Set hover color') - - # add m_pToolBar tools - @tool_bar.set_tool_bitmap_size([16, 15]) + # add tool_bar tools @tool_bar.add_tool(Wx::ID_NEW, 'New', Wx::ArtProvider.get_bitmap(Wx::ART_NEW, Wx::ART_MENU), 'New diagram') @tool_bar.add_tool(Wx::ID_OPEN, 'Load', Wx::ArtProvider.get_bitmap(Wx::ART_FILE_OPEN, Wx::ART_MENU), 'Open file...') @tool_bar.add_tool(Wx::ID_SAVE, 'Save', Wx::ArtProvider.get_bitmap(Wx::ART_FILE_SAVE, Wx::ART_MENU), 'Save file...') @tool_bar.add_separator @tool_bar.add_tool(Wx::ID_PRINT, 'Print', Wx::ArtProvider.get_bitmap(Wx::ART_PRINT, Wx::ART_MENU), 'Print...') @@ -163,26 +291,26 @@ @tool_bar.add_tool(Wx::ID_PASTE, 'Paste', Wx::ArtProvider.get_bitmap(Wx::ART_PASTE, Wx::ART_MENU), 'Paste from clipboard') @tool_bar.add_separator @tool_bar.add_tool(Wx::ID_UNDO, 'Undo', Wx::ArtProvider.get_bitmap(Wx::ART_UNDO, Wx::ART_MENU), 'Undo') @tool_bar.add_tool(Wx::ID_REDO, 'Redo', Wx::ArtProvider.get_bitmap(Wx::ART_REDO, Wx::ART_MENU), 'Redo') @tool_bar.add_separator - @tool_bar.add_check_tool(ID::T_GRID, 'Grid', Wx::Bitmap(:Grid), Wx::NULL_BITMAP, 'Show/hide grid') - @tool_bar.add_check_tool(ID::T_SHADOW, 'Shadows', Wx::Bitmap(:Shadow), Wx::NULL_BITMAP, 'Show/hide shadows') - @tool_bar.add_check_tool(ID::T_GC, 'Enhanced graphics context', Wx::Bitmap(:GC), Wx::NULL_BITMAP, 'Use enhanced graphics context (Wx::GraphicsContext)') + @tool_bar.add_tool(ID::T_SETTINGS, 'Settings', Wx::ArtProvider.get_bitmap(Wx::ART_HELP_SETTINGS, Wx::ART_MENU), 'Settings') @tool_bar.add_separator @tool_bar.add_radio_tool(ID::T_TOOL, 'Tool', Wx::Bitmap(:Tool), Wx::NULL_BITMAP, 'Design tool') @tool_bar.add_radio_tool(ID::T_RECTSHP, 'Rectangle', Wx::Bitmap(:Rect), Wx::NULL_BITMAP, 'Rectangle') - @tool_bar.add_radio_tool(ID::T_SQUARESHP, 'Fixed rectangle', Wx::Bitmap(:FixedRect), Wx::NULL_BITMAP, 'Fixed rectangle') + @tool_bar.add_radio_tool(ID::T_SQUARESHP, 'Square', Wx::Bitmap(:FixedRect), Wx::NULL_BITMAP, 'Square') @tool_bar.add_radio_tool(ID::T_RNDRECTSHP, 'RoundRect', Wx::Bitmap(:RoundRect), Wx::NULL_BITMAP, 'Rounded rectangle') @tool_bar.add_radio_tool(ID::T_ELLIPSESHP, 'Ellipse', Wx::Bitmap(:Ellipse), Wx::NULL_BITMAP, 'Ellipse') @tool_bar.add_radio_tool(ID::T_CIRCLESHP, 'Circle', Wx::Bitmap(:Circle), Wx::NULL_BITMAP, 'Circle') @tool_bar.add_radio_tool(ID::T_DIAMONDSHP, 'Diamond', Wx::Bitmap(:Diamond), Wx::NULL_BITMAP, 'Diamond') @tool_bar.add_radio_tool(ID::T_TEXTSHP, 'Text', Wx::Bitmap(:Text), Wx::NULL_BITMAP, 'Text') @tool_bar.add_radio_tool(ID::T_EDITTEXTSHP, 'Editable text', Wx::Bitmap(:EditText), Wx::NULL_BITMAP, 'Editable text') @tool_bar.add_radio_tool(ID::T_BITMAPSHP, 'Bitmap', Wx::Bitmap(:Bitmap), Wx::NULL_BITMAP, 'Bitmap') @tool_bar.add_radio_tool(ID::T_GRIDSHP, 'Grid shape', Wx::Bitmap(:Grid), Wx::NULL_BITMAP, 'Grid shape') @tool_bar.add_radio_tool(ID::T_FLEXGRIDSHP, 'Flexible grid shape', Wx::Bitmap(:FlexGrid), Wx::NULL_BITMAP, 'Flexible grid shape') + @tool_bar.add_radio_tool(ID::T_VBOXSHP, 'Vertical Box shape', Wx::Bitmap(:VBox), Wx::NULL_BITMAP, 'Vertical Box shape') + @tool_bar.add_radio_tool(ID::T_HBOXSHP, 'Horizontal Box shape', Wx::Bitmap(:HBox), Wx::NULL_BITMAP, 'Horizontal Box shape') @tool_bar.add_radio_tool(ID::T_LINESHP, 'Line', Wx::Bitmap(:Line), Wx::NULL_BITMAP, 'Polyline connection') @tool_bar.add_radio_tool(ID::T_CURVESHP, 'Curve', Wx::Bitmap(:Curve), Wx::NULL_BITMAP, 'Curve connection') @tool_bar.add_radio_tool(ID::T_ORTHOSHP, 'Ortho line', Wx::Bitmap(:OrthoLine), Wx::NULL_BITMAP, 'Orthogonal connection') @tool_bar.add_radio_tool(ID::T_RNDORTHOSHP, 'Rounded ortho line', Wx::Bitmap(:RoundOrthoLine), Wx::NULL_BITMAP, 'Rounded orthogonal connection') @tool_bar.add_radio_tool(ID::T_STANDALONELINESHP, 'Stand alone line', Wx::Bitmap(:StandAloneLine), Wx::NULL_BITMAP, 'Stand alone line') @@ -191,21 +319,21 @@ @tool_bar.add_tool(ID::T_ALIGN_RIGHT, 'Align right', Wx::Bitmap(:AlignRight), 'Align selected shapes to the right') @tool_bar.add_tool(ID::T_ALIGN_TOP, 'Align top', Wx::Bitmap(:AlignTop), 'Align selected shapes to the top') @tool_bar.add_tool(ID::T_ALIGN_BOTTOM, 'Align bottom', Wx::Bitmap(:AlignBottom), 'Align selected shapes to the bottom') @tool_bar.add_tool(ID::T_ALIGN_MIDDLE, 'Align middle', Wx::Bitmap(:AlignMiddle), 'Align selected shapes to the middle') @tool_bar.add_tool(ID::T_ALIGN_CENTER, 'Align center', Wx::Bitmap(:AlignCenter), 'Align selected shapes to the center') - @tool_bar.add_separator - @tool_bar.add_control(@cpicker) @tool_bar.realize @status_bar.set_status_text('Ready') # initialize data members @tool_mode = MODE::DESIGN + @grid_columns = 3 @show_grid = true @show_shadows = false + set_size([1280, 800]) centre # setup event handlers evt_close(:on_close) evt_menu(Wx::ID_EXIT, :on_exit) @@ -224,62 +352,74 @@ evt_menu(Wx::ID_PREVIEW, :on_print_preview) evt_menu(Wx::ID_PAGE_SETUP, :on_page_setup) evt_menu_range(ID::M_AUTOLAYOUT_FIRST, ID::M_AUTOLAYOUT_LAST, :on_auto_layout) evt_command_scroll(Wx::ID_ZOOM_FIT, :on_slider) evt_tool_range(ID::T_FIRST_TOOLMARKER, ID::T_LAST_TOOLMARKER, :on_tool) + evt_menu_range(ID::M_GRIDCOLS_1, ID::M_GRIDCOLS_NR, :on_grid_columns) evt_colourpicker_changed(ID::T_COLORPICKER, :on_hover_color) evt_update_ui(Wx::ID_COPY, :on_update_copy) evt_update_ui(Wx::ID_CUT, :on_update_cut) evt_update_ui(Wx::ID_PASTE, :on_update_paste) evt_update_ui(Wx::ID_UNDO, :on_update_undo) evt_update_ui(Wx::ID_REDO, :on_update_redo) evt_update_ui_range(ID::T_FIRST_TOOLMARKER, ID::T_LAST_TOOLMARKER, :on_update_tool) evt_update_ui_range(ID::M_AUTOLAYOUT_FIRST, ID::M_AUTOLAYOUT_LAST, :on_update_auto_layout) + evt_update_ui(@mi_gridcol_nr, :on_update_gridcol_nr) evt_idle(:on_idle) end attr_accessor :tool_mode, :show_grid, :show_shadows - attr_reader :zoom_slider + attr_reader :grid_columns, :zoom_slider + def diagram + @shape_canvas&.diagram + end + private :diagram + def setup_frame - if Wx::PLATFORM == 'WXMSW' - set_size_hints([1024,700]) - else - set_size_hints([1100,700]) - end + set_size_hints([1024, 640]) @menu_bar = Wx::MenuBar.new(0) @file_menu = Wx::Menu.new @menu_bar.append(@file_menu, "&File") @edit_menu = Wx::Menu.new @menu_bar.append(@edit_menu, "&Edit") - + + @shape_menu = Wx::Menu.new + @menu_bar.append(@shape_menu, "&Shapes") + @auto_layout_menu = Wx::Menu.new @menu_bar.append(@auto_layout_menu, "&AutoLayout") @help_menu = Wx::Menu.new @menu_bar.append(@help_menu, "&Help") set_menu_bar(@menu_bar) - - @tool_bar = create_tool_bar(Wx::TB_HORIZONTAL, Wx::ID_ANY) - @tool_bar.realize - + @status_bar = create_status_bar(1, Wx::STB_SIZEGRIP, Wx::ID_ANY) - main_sizer = Wx::FlexGridSizer.new(2, 1, 0, 0) + main_sizer = Wx::FlexGridSizer.new(3, 1, 0, 0) main_sizer.add_growable_col(0) - main_sizer.add_growable_row(0) + main_sizer.add_growable_row(1) main_sizer.set_flexible_direction(Wx::BOTH) main_sizer.set_non_flexible_grow_mode(Wx::FLEX_GROWMODE_SPECIFIED) - + + tool_bar_panel = Wx::Panel.new(self, Wx::ID_ANY) + tool_bar_sizer = Wx::VBoxSizer.new + @tool_bar = Wx::ToolBar.new(tool_bar_panel, style: Wx::TB_HORIZONTAL | Wx::NO_BORDER | Wx::TB_FLAT) + @tool_bar.realize + tool_bar_sizer.add(@tool_bar, 0, Wx::EXPAND) + tool_bar_panel.sizer = tool_bar_sizer + tool_bar_panel.layout + main_sizer.add(tool_bar_panel, 0, Wx::EXPAND, 5) + @canvas_panel = Wx::Panel.new(self, Wx::ID_ANY, style: Wx::TAB_TRAVERSAL) @canvas_panel.set_extra_style(Wx::WS_EX_BLOCK_EVENTS) @canvas_sizer = Wx::VBoxSizer.new - + @canvas_panel.set_sizer(@canvas_sizer) @canvas_panel.layout @canvas_sizer.fit(@canvas_panel) main_sizer.add(@canvas_panel, 1, Wx::EXPAND, 5) @@ -297,12 +437,12 @@ private :setup_frame protected def clean_up - @diagram.set_shape_canvas(nil) - @diagram.clear + diagram.set_shape_canvas(nil) + diagram.clear @thumb_frm.hide @thumb_frm.thumbnail.set_canvas(nil) destroy @@ -312,11 +452,11 @@ def on_close(_event) clean_up end def on_idle(_event) - if @diagram.is_modified + if diagram.is_modified set_title('wxRuby ShapeFramework Demo (diagram is modified)') else set_title('wxRuby ShapeFramework Demo') end end @@ -327,38 +467,93 @@ end def on_new(_event) if Wx.message_box('Current chart will be lost. Do you want to proceed?', 'wxRuby ShapeFramework', Wx::YES_NO | Wx::ICON_QUESTION) == Wx::YES - @diagram.clear + diagram.clear @shape_canvas.clear_canvas_history @shape_canvas.save_canvas_state @shape_canvas.refresh end end def on_save(_event) - Wx::FileDialog(self, 'Save canvas to file...', Dir.getwd, '', 'JSON Files (*.json)|*.json', Wx::FD_SAVE | Wx::FD_OVERWRITE_PROMPT) do |dlg| + Wx.FileDialog(self, 'Save canvas to file...', __dir__, '', FILE_MASK, Wx::FD_SAVE) do |dlg| + dlg.set_filter_index(0) + dlg_hook = DiagramFileDialog.new(dlg, compact: true) if dlg.show_modal == Wx::ID_OK - @shape_canvas.save_canvas(dlg.get_path) + check_overwrite = Wx::PLATFORM != 'WXOSX' + begin + path = dlg.get_path.dup + selected_filter = dlg.get_filter_index + ext = File.extname(path) + if ext == '.' && !(Wx::PLATFORM == 'WXOSX' && File.exist?(path)) + ext = '' + path = File.join(File.dirname(path), File.basename(path, '.*')) + check_overwrite = true + end + if ext.empty? + format = if selected_filter < 0 || selected_filter >= DiagramFileDialog::FORMATS.size + dlg_hook.format || :json + else + DiagramFileDialog::FORMATS[selected_filter].to_sym + end + if selected_filter < DiagramFileDialog::FORMATS.size && !(Wx::PLATFORM == 'WXOSX' && File.exist?(path)) + # determine extension to provide + case format + when :json then path << '.json' + when :yaml then path << '.yaml' + when :xml then path << '.xml' + end + check_overwrite = true + end + else + format = case File.extname(dlg.get_path) + when '.json' then :json + when '.yaml', '.yml' then :yaml + when '.xml' then :xml + else + if selected_filter < 0 || selected_filter >= DiagramFileDialog::FORMATS.size + dlg_hook.format || :json + else + DiagramFileDialog::FORMATS[selected_filter].to_sym + end + end + end + if !check_overwrite || !File.exist?(path) || + 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 + @shape_canvas.save_canvas(path, compact: dlg_hook.compact, format: format) - Wx.message_box("The chart has been saved to '#{dlg.get_path}'.", 'wxRuby ShapeFramework') + Wx.MessageDialog(self, "The chart has been saved to '#{path}'.", 'wxRuby ShapeFramework', Wx::OK | Wx::ICON_INFORMATION) + end + rescue Exception => ex + Wx.MessageDialog(self, "Failed to save the chart: #{ex.message}", 'wxRuby ShapeFramework', Wx::OK | Wx::ICON_ERROR) + end end end end def on_load(_event) - Wx::FileDialog(self, 'Load canvas from file...', Dir.getwd, '', 'JSON Files (*.json)|*.json', Wx::FD_OPEN | Wx::FD_FILE_MUST_EXIST) do |dlg| + Wx.FileDialog(self, 'Load canvas from file...', __dir__, '', FILE_MASK, Wx::FD_OPEN | Wx::FD_FILE_MUST_EXIST) do |dlg| + dlg_hook = DiagramFileDialog.new(dlg) if dlg.show_modal == Wx::ID_OK - @shape_canvas.load_canvas(dlg.get_path) - @diagram = @shape_canvas.get_diagram + begin + format = case File.extname(dlg.get_path) + when '.json' then :json + when '.yaml', '.yml' then :yaml + when '.xml' then :xml + else + dlg_hook.format || :json + end + @shape_canvas.load_canvas(dlg.get_path, format: format) - @zoom_slider.set_value((@shape_canvas.get_scale*50).to_i) - - @cpicker.set_colour(@shape_canvas.get_hover_colour) + @zoom_slider.set_value((@shape_canvas.get_scale*50).to_i) + rescue Exception => ex + Wx.MessageDialog(self, "Failed to load the chart: #{ex.message}", 'wxRuby ShapeFramework', Wx::OK | Wx::ICON_ERROR) + end end end end def on_undo(_event) @@ -446,34 +641,18 @@ def on_tool(event) @shape_canvas.abort_interactive_connection if @shape_canvas.get_mode == Wx::SF::ShapeCanvas::MODE::CREATECONNECTION case event.get_id - when ID::T_GRID - @show_grid = !@show_grid - if @show_grid - @shape_canvas.add_style(Wx::SF::ShapeCanvas::STYLE::GRID_SHOW) - @shape_canvas.add_style(Wx::SF::ShapeCanvas::STYLE::GRID_USE) - else - @shape_canvas.remove_style(Wx::SF::ShapeCanvas::STYLE::GRID_SHOW) - @shape_canvas.remove_style(Wx::SF::ShapeCanvas::STYLE::GRID_USE) - end - @shape_canvas.refresh(false) + when ID::T_SETTINGS + Dialogs::WXSFPreferencesDialog(self, @shape_canvas) - when ID::T_SHADOW - @show_shadows = !@show_shadows - - @shape_canvas.show_shadows(@show_shadows, Wx::SF::ShapeCanvas::SHADOWMODE::ALL) - # also shadows for topmost shapes only are allowed: - # @shape_canvas.show_shadows(@show_shadows, Wx::SF::ShapeCanvas::SHADOWMODE::TOPMOST) - @shape_canvas.refresh(false) - when ID::T_GC if Wx.has_feature?(:USE_GRAPHICS_CONTEXT) Wx::SF::ShapeCanvas.enable_gc(!Wx::SF::ShapeCanvas.gc_enabled?) # update all shapes in the manager - @diagram.update_all + diagram.update_all # refresh shape canvas @shape_canvas.refresh(false) else Wx.message_box('Could not enable enhanced graphics context due to wxUSE_GRAPHICS_CONTEXT=0', 'wxRuby ShapeFramework', Wx::OK | Wx::ICON_WARNING) end @@ -506,10 +685,16 @@ @tool_mode = MODE::GRID when ID::T_FLEXGRIDSHP @tool_mode = MODE::FLEXGRID + when ID::T_VBOXSHP + @tool_mode = MODE::VBOX + + when ID::T_HBOXSHP + @tool_mode = MODE::HBOX + when ID::T_LINESHP @tool_mode = MODE::LINE when ID::T_STANDALONELINESHP @tool_mode = MODE::STANDALONELINE @@ -550,10 +735,20 @@ else event.skip end end + def on_grid_columns(event) + if event.get_id == ID::M_GRIDCOLS_CUSTOM || event.get_id == ID::M_GRIDCOLS_NR + n = Wx.get_number_from_user('Enter custom grid column number.', 'Nr. of columns:', + 'Grid columns', @grid_columns, 1, 100, self) + @grid_columns = n unless n <= 0 + else + @grid_columns = 1 + event.get_id-ID::M_GRIDCOLS_1 + end + end + def on_hover_color(event) @shape_canvas.set_hover_colour(event.get_colour) end def on_update_copy(event) @@ -576,13 +771,10 @@ event.enable(@shape_canvas.can_redo?) if @shape_canvas end def on_update_tool(event) case event.get_id - when ID::T_GRID - event.check(@show_grid) - when ID::T_GC event.check(Wx::SF::ShapeCanvas.gc_enabled?) when ID::T_BITMAPSHP event.check(@tool_mode == MODE::BITMAP) @@ -612,10 +804,16 @@ event.check(@tool_mode == MODE::GRID) when ID::T_FLEXGRIDSHP event.check(@tool_mode == MODE::FLEXGRID) + when ID::T_VBOXSHP + event.check(@tool_mode == MODE::VBOX) + + when ID::T_HBOXSHP + event.check(@tool_mode == MODE::HBOX) + when ID::T_LINESHP event.check(@tool_mode == MODE::LINE) when ID::T_STANDALONELINESHP event.check(@tool_mode == MODE::STANDALONELINE) @@ -647,12 +845,24 @@ event.skip end end def on_update_auto_layout(event) - event.enable(!@diagram.empty?) + event.enable(!diagram.empty?) end + + def on_update_gridcol_nr(_event) + @mi_gridcol_nr.enable(@mi_gridcols_custom.checked?) + @mi_gridcol_nr.set_item_label("Number of grid columns (#{@grid_columns})") + end + end +if Wx::PLATFORM == 'WXOSX' && !Wx.const_defined?(:OSX_FILEDIALOG_ALWAYS_SHOW_TYPES) + Wx::OSX_FILEDIALOG_ALWAYS_SHOW_TYPES = 'osx.openfiledialog.always-show-types' +end + Wx::App.run do + Wx::SystemOptions.set_option(Wx::OSX_FILEDIALOG_ALWAYS_SHOW_TYPES, 1) if Wx::PLATFORM == 'WXOSX' + Wx::ArtProvider.push(Wx::MDAP::MaterialDesignArtProvider.new) MainFrame.new(nil).show end