def __init__(self, app): wx.Frame.__init__(self, parent=None) # Build menus and bind callback self.build_menus(app) # Bind idle callback self.Bind(wx.EVT_IDLE, app.idle) # The main sizer for the application sizer = wx.BoxSizer(wx.VERTICAL) version = '%s %s' % (koko.NAME, koko.VERSION) sizer.Add(wx.StaticText(self, label=version), flag=wx.ALIGN_RIGHT | wx.ALL, border=5) # Horizontal sizer that contains script, output, and canvases core = wx.BoxSizer(wx.HORIZONTAL) koko.IMPORT = ImportPanel(app, self) editor_panel = wx.Panel(self) editor_sizer = wx.BoxSizer(wx.VERTICAL) # Vertical sizer that contains the editor and the output panel koko.EDITOR = Editor(editor_panel, style=wx.NO_BORDER, size=(300, 400)) koko.EDITOR.load_template() koko.EDITOR.bind_callbacks(app) editor_sizer.Add(koko.EDITOR, proportion=2, flag=wx.EXPAND) self.show_editor = lambda b: editor_sizer.ShowItems(b) self._output = Editor(editor_panel, margins=False, style=wx.NO_BORDER, size=(300, 100)) self._output.SetWrapStartIndent(4) self._output.SetReadOnly(True) self._output.SetCaretLineVisible(False) self._output.SetWrapMode(wx.stc.STC_WRAP_WORD) editor_sizer.Add(self._output, proportion=1, border=10, flag=wx.EXPAND | wx.TOP) editor_panel.SetSizerAndFit(editor_sizer) self.show_editor = lambda b: editor_panel.Show(b) # Vertical / Horizontal sizer that contains the two canvases canvas_sizer = wx.BoxSizer(wx.VERTICAL) self.set_canvas_orientation = lambda o: canvas_sizer.SetOrientation(o) koko.CANVAS = Canvas(self, app, size=(300, 300)) canvas_sizer.Add(koko.CANVAS, proportion=1, flag=wx.EXPAND) koko.GLCANVAS = GLCanvas(self, size=(300, 300)) canvas_sizer.Add(koko.GLCANVAS, proportion=1, flag=wx.EXPAND) koko.GLCANVAS.Hide() core.Add(koko.IMPORT, flag=wx.EXPAND | wx.RIGHT, border=20) koko.IMPORT.Hide() core.Add(editor_panel, proportion=4, flag=wx.EXPAND | wx.RIGHT, border=10) core.Add(canvas_sizer, proportion=6, flag=wx.EXPAND | wx.RIGHT, border=10) koko.FAB = FabWorkflowPanel(self) core.Add(koko.FAB, proportion=3, flag=wx.EXPAND | wx.RIGHT, border=10) koko.FAB.Hide() sizer.Add(core, proportion=1, flag=wx.EXPAND) bottom_sizer = wx.BoxSizer(wx.HORIZONTAL) self._hint = wx.lib.stattext.GenStaticText(self) bottom_sizer.Add(self._hint, proportion=1) self._status = wx.lib.stattext.GenStaticText(self, style=wx.ALIGN_RIGHT | wx.ST_NO_AUTORESIZE) bottom_sizer.Add(self._status, proportion=1) sizer.Add(bottom_sizer, flag=wx.EXPAND | wx.ALL, border=10) self.SetSizerAndFit(sizer) APP_THEME.apply(self) self._status.SetForegroundColour(wx.Colour(100, 100, 100)) # By default, hide the output panel self._output.Hide() self.Layout() """ # Settings for screen recording self.SetClientSize((1280, 720)) self.SetPosition((0,wx.DisplaySize()[1] - self.GetSize()[1])) """ self.Maximize()
def __init__(self, callbacks): wx.Frame.__init__(self, parent=None) # Bind menu callbacks self.Bind(wx.EVT_MENU_HIGHLIGHT, self.OnMenuHighlight) self.Bind(wx.EVT_MENU_CLOSE, self.OnMenuClose) # Bind menu callbacks self.build_menus(callbacks) # Bind idle callback self.Bind(wx.EVT_IDLE, callbacks['idle']) ####################################################################### ####################################################################### # Create a canvas with a border and status text below canvasPanel = wx.Panel(self) canvasSizer = wx.BoxSizer(wx.VERTICAL) version = wx.StaticText(canvasPanel, label='%s %s ' % (koko.about.NAME, koko.about.VERSION)) canvasSizer.Add(version, flag=wx.ALIGN_RIGHT) self.canvas = Canvas(canvasPanel, callbacks, size=(300, 300)) koko.globals.CANVAS = weakref.proxy(self.canvas) canvasSizer.Add(self.canvas, proportion=2, flag=wx.TOP | wx.LEFT | wx.RIGHT | wx.EXPAND, border=20) # Add status text canvasSizer.Add((0,0), border=5, flag=wx.BOTTOM) self._status = wx.StaticText( canvasPanel, style=wx.ALIGN_RIGHT|wx.ST_NO_AUTORESIZE) canvasSizer.Add(self._status, border=20, flag=wx.EXPAND | wx.RIGHT) canvasSizer.Add((0,0), border=15, flag=wx.BOTTOM) # Add output panel for error messages, etc. self._output = Editor(canvasPanel, margins=False, style=wx.NO_BORDER, size=(300, 100)) self._output.SetReadOnly(True) self._output.SetCaretLineVisible(False) self._output.SetWrapMode(wx.stc.STC_WRAP_WORD) self.hide_output = lambda: (self._output.Hide(), canvasPanel.Layout()) self.show_output = lambda: (self._output.Show(), canvasPanel.Layout()) canvasSizer.Add(self._output, border=20, proportion=1, flag=wx.EXPAND | wx.LEFT | wx.TOP | wx.RIGHT) canvasPanel.SetSizerAndFit(canvasSizer) ####################################################################### ####################################################################### # Pack everything into the window editorPanel = wx.Panel(self) editorSizer = wx.BoxSizer(wx.VERTICAL) editorSizer.Add((0,0), border=15, flag=wx.TOP) self.editor = Editor(editorPanel, style=wx.NO_BORDER, size=(300, 400)) koko.globals.EDITOR = weakref.proxy(self.editor) self.editor.load_template() self.editor.bind_callbacks(callbacks) editorSizer.Add(self.editor, proportion=1, flag=wx.EXPAND) self._hint = wx.StaticText(editorPanel) editorSizer.Add(self._hint, border=5, flag=wx.ALL) editorPanel.SetSizerAndFit(editorSizer) ####################################################################### sizer = wx.BoxSizer(wx.HORIZONTAL) sizer.Add(editorPanel, proportion=2, flag=wx.EXPAND) sizer.Add(canvasPanel, proportion=3, flag=wx.EXPAND) self.hide_script = lambda: (editorPanel.Hide(), self.Layout()) self.show_script = lambda: (editorPanel.Show(), self.Layout()) self.SetSizerAndFit(sizer) ####################################################################### DARK_THEME.apply(self) DARK_THEME.apply(canvasPanel) DARK_THEME.apply(editorPanel) DARK_THEME.apply(version) DARK_THEME.apply(self._hint) DARK_THEME.apply(self._status) DARK_THEME.apply(self._output) DARK_THEME.apply(self.editor) self._status.SetForegroundColour(wx.Colour(100, 100, 100)) self.hide_output() self.Maximize()
class MainFrame(wx.Frame): def __init__(self, app): wx.Frame.__init__(self, parent=None) # Build menus and bind callback self.build_menus(app) # Bind idle callback self.Bind(wx.EVT_IDLE, app.idle) # The main sizer for the application sizer = wx.BoxSizer(wx.VERTICAL) version = '%s %s' % (koko.NAME, koko.VERSION) sizer.Add(wx.StaticText(self, label=version), flag=wx.ALIGN_RIGHT | wx.ALL, border=5) # Horizontal sizer that contains script, output, and canvases core = wx.BoxSizer(wx.HORIZONTAL) koko.IMPORT = ImportPanel(app, self) editor_panel = wx.Panel(self) editor_sizer = wx.BoxSizer(wx.VERTICAL) # Vertical sizer that contains the editor and the output panel koko.EDITOR = Editor(editor_panel, style=wx.NO_BORDER, size=(300, 400)) koko.EDITOR.load_template() koko.EDITOR.bind_callbacks(app) editor_sizer.Add(koko.EDITOR, proportion=2, flag=wx.EXPAND) self.show_editor = lambda b: editor_sizer.ShowItems(b) self._output = Editor(editor_panel, margins=False, style=wx.NO_BORDER, size=(300, 100)) self._output.SetWrapStartIndent(4) self._output.SetReadOnly(True) self._output.SetCaretLineVisible(False) self._output.SetWrapMode(wx.stc.STC_WRAP_WORD) editor_sizer.Add(self._output, proportion=1, border=10, flag=wx.EXPAND | wx.TOP) editor_panel.SetSizerAndFit(editor_sizer) self.show_editor = lambda b: editor_panel.Show(b) # Vertical / Horizontal sizer that contains the two canvases canvas_sizer = wx.BoxSizer(wx.VERTICAL) self.set_canvas_orientation = lambda o: canvas_sizer.SetOrientation(o) koko.CANVAS = Canvas(self, app, size=(300, 300)) canvas_sizer.Add(koko.CANVAS, proportion=1, flag=wx.EXPAND) koko.GLCANVAS = GLCanvas(self, size=(300, 300)) canvas_sizer.Add(koko.GLCANVAS, proportion=1, flag=wx.EXPAND) koko.GLCANVAS.Hide() core.Add(koko.IMPORT, flag=wx.EXPAND | wx.RIGHT, border=20) koko.IMPORT.Hide() core.Add(editor_panel, proportion=4, flag=wx.EXPAND | wx.RIGHT, border=10) core.Add(canvas_sizer, proportion=6, flag=wx.EXPAND | wx.RIGHT, border=10) koko.FAB = FabWorkflowPanel(self) core.Add(koko.FAB, proportion=3, flag=wx.EXPAND | wx.RIGHT, border=10) koko.FAB.Hide() sizer.Add(core, proportion=1, flag=wx.EXPAND) bottom_sizer = wx.BoxSizer(wx.HORIZONTAL) self._hint = wx.lib.stattext.GenStaticText(self) bottom_sizer.Add(self._hint, proportion=1) self._status = wx.lib.stattext.GenStaticText(self, style=wx.ALIGN_RIGHT | wx.ST_NO_AUTORESIZE) bottom_sizer.Add(self._status, proportion=1) sizer.Add(bottom_sizer, flag=wx.EXPAND | wx.ALL, border=10) self.SetSizerAndFit(sizer) APP_THEME.apply(self) self._status.SetForegroundColour(wx.Colour(100, 100, 100)) # By default, hide the output panel self._output.Hide() self.Layout() """ # Settings for screen recording self.SetClientSize((1280, 720)) self.SetPosition((0,wx.DisplaySize()[1] - self.GetSize()[1])) """ self.Maximize() ################################################################################ def build_menus(self, app): '''Build a set of menus and attach associated callbacks.''' def attach(menu, command, callback, shortcut='', help='', wxID=wx.ID_ANY, attach_function=None): '''Helper function to add an item to a menu and bind the associated callback.''' if shortcut: menu_text = '%s\t%s' % (command, shortcut) else: menu_text = command if attach_function is None: attach_function = menu.Append item = attach_function(wxID, menu_text, help) self.Bind(wx.EVT_MENU, callback, item) return item menu_bar = wx.MenuBar() file = wx.Menu() attach(file, 'New', app.new, 'Ctrl+N', 'Start a new design', wx.ID_NEW) file.AppendSeparator() attach(file, 'Open', app.open, 'Ctrl+O', 'Open a design file', wx.ID_OPEN) attach(file, 'Reload', app.reload, 'Ctrl+R', 'Reload the current file') file.AppendSeparator() attach(file, 'Save', app.save, 'Ctrl+S', 'Save the current file', wx.ID_SAVE) attach(file, 'Save As', app.save_as, 'Ctrl+Shift+S', 'Save the current file', wx.ID_SAVEAS) if not 'Darwin' in os.uname(): file.AppendSeparator() attach(file, 'About', show_about_box, '', 'Display an About box', wx.ID_ABOUT) attach(file, 'Exit', app.exit, 'Ctrl+Q', 'Terminate the program', wx.ID_EXIT) menu_bar.Append(file, 'File') view = wx.Menu() output = attach(view, 'Show output', self.show_output, 'Ctrl+D', 'Display errors in a separate pane', attach_function=view.AppendCheckItem) script = attach(view, 'Show script', self.show_script, 'Ctrl+T', 'Display Python script', attach_function=view.AppendCheckItem) script.Toggle() view.AppendSeparator() attach(view, '2D', app.render_mode, attach_function=view.AppendRadioItem) attach(view, '3D', app.render_mode, attach_function=view.AppendRadioItem) attach(view, 'Both', app.render_mode, attach_function=view.AppendRadioItem) view.AppendSeparator() shaders = wx.Menu() for s in ['Shaded', 'Wireframe', 'Normals', 'Subdivision']: m = shaders.AppendRadioItem(wx.ID_ANY, s) m.Enable(False) if s == 'Show shaded': m.Check(True) self.Bind(wx.EVT_MENU, lambda e: self.Refresh(), m) view.AppendSubMenu(shaders, 'Shading mode') view.AppendSeparator() attach(view, 'Show axes', lambda e: self.Refresh(), 'Display X, Y, and Z axes on frame', attach_function=view.AppendCheckItem) attach(view, 'Show bounds', lambda e: self.Refresh(), 'Display object bounds', attach_function=view.AppendCheckItem) attach(view, 'Show traverses', lambda e: self.Refresh(), 'Display toolpath traverses', attach_function=view.AppendCheckItem) view.AppendSeparator() attach(view, 'Re-render', app.mark_changed_design, 'Ctrl+Enter', 'Re-render the output image') menu_bar.Append(view, 'View') export = wx.Menu() attach(export, '.png', app.export, help='Export to image file') attach(export, '.svg', app.export, help='Export to svg file') attach(export, '.stl', app.export, help='Export to stl file') attach(export, '.dot', app.export, help='Export to dot / Graphviz file') export.AppendSeparator() attach(export, '.asdf', app.export, help='Export to .asdf file') export.AppendSeparator() attach(export, 'Show CAM panel', self.show_cam, 'Ctrl+M', '', attach_function=export.AppendCheckItem) menu_bar.Append(export, 'Export') libraries = wx.Menu() attach(libraries, 'koko.lib.shapes2d', app.show_library, help='2D Shapes library') attach(libraries, 'koko.lib.shapes3d', app.show_library, help='3D Shapes library') attach(libraries, 'koko.lib.text', app.show_library, help='Text library') menu_bar.Append(libraries, 'Libraries') self.SetMenuBar(menu_bar) self.Bind(wx.EVT_MENU_HIGHLIGHT, self.OnMenuHighlight) self.Bind(wx.EVT_MENU_CLOSE, self.OnMenuClose) ################################################################################ @property def status(self): return self._status.GetLabel() @status.setter def status(self, value): wx.CallAfter(self._status.SetLabel, value) def set_status(self, value): self.status = value ################################################################################ @property def hint(self): return self._hint.GetLabel() @hint.setter def hint(self, value): wx.CallAfter(self._hint.SetLabel, value) def set_hint(self, value): self.hint = value ################################################################################ @property def output(self): return self._output.text @output.setter def output(self, value): self._output.text = value def set_output(self, value): self.output = value ################################################################################ def OnMenuHighlight(self, event): '''Sets an appropriate hint based on the highlighted menu item.''' id = event.GetMenuId() item = self.GetMenuBar().FindItemById(id) if not item or not item.GetHelp(): self.hint = '' else: self.hint = item.GetHelp() def OnMenuClose(self, event): '''Clears the menu item hint.''' self.hint = '' def show_output(self, evt): ''' Shows or hides the output panel. ''' if type(evt) is not bool: evt = evt.Checked() if evt: if koko.EDITOR.IsShown(): self._output.Show() else: self._output.Hide() self.Layout() def show_script(self, evt): ''' Shows or hides the script panel. ''' if type(evt) is not bool: evt = evt.Checked() if evt: self.show_editor(True) self.set_canvas_orientation(wx.VERTICAL) else: self.show_editor(False) self.set_canvas_orientation(wx.HORIZONTAL) self.Layout() def show_cam(self, evt): if type(evt) is not bool: evt = evt.Checked() koko.FAB.Show(evt) self.Layout() def show_import(self, evt): if type(evt) is not bool: evt = evt.Checked() koko.IMPORT.Show(evt) self.Layout() def get_menu(self, *args): m = [m[0] for m in self.GetMenuBar().Menus if m[1] == args[0]][0] m = [m for m in m.GetMenuItems() if m.GetLabel() == args[1]][0] sub = m.GetSubMenu() if sub is None: return m else: return sub.GetMenuItems()
class MainFrame(wx.Frame): def __init__(self, callbacks): wx.Frame.__init__(self, parent=None) # Bind menu callbacks self.Bind(wx.EVT_MENU_HIGHLIGHT, self.OnMenuHighlight) self.Bind(wx.EVT_MENU_CLOSE, self.OnMenuClose) # Bind menu callbacks self.build_menus(callbacks) # Bind idle callback self.Bind(wx.EVT_IDLE, callbacks['idle']) ####################################################################### ####################################################################### # Create a canvas with a border and status text below canvasPanel = wx.Panel(self) canvasSizer = wx.BoxSizer(wx.VERTICAL) version = wx.StaticText(canvasPanel, label='%s %s ' % (koko.about.NAME, koko.about.VERSION)) canvasSizer.Add(version, flag=wx.ALIGN_RIGHT) self.canvas = Canvas(canvasPanel, callbacks, size=(300, 300)) koko.globals.CANVAS = weakref.proxy(self.canvas) canvasSizer.Add(self.canvas, proportion=2, flag=wx.TOP | wx.LEFT | wx.RIGHT | wx.EXPAND, border=20) # Add status text canvasSizer.Add((0,0), border=5, flag=wx.BOTTOM) self._status = wx.StaticText( canvasPanel, style=wx.ALIGN_RIGHT|wx.ST_NO_AUTORESIZE) canvasSizer.Add(self._status, border=20, flag=wx.EXPAND | wx.RIGHT) canvasSizer.Add((0,0), border=15, flag=wx.BOTTOM) # Add output panel for error messages, etc. self._output = Editor(canvasPanel, margins=False, style=wx.NO_BORDER, size=(300, 100)) self._output.SetReadOnly(True) self._output.SetCaretLineVisible(False) self._output.SetWrapMode(wx.stc.STC_WRAP_WORD) self.hide_output = lambda: (self._output.Hide(), canvasPanel.Layout()) self.show_output = lambda: (self._output.Show(), canvasPanel.Layout()) canvasSizer.Add(self._output, border=20, proportion=1, flag=wx.EXPAND | wx.LEFT | wx.TOP | wx.RIGHT) canvasPanel.SetSizerAndFit(canvasSizer) ####################################################################### ####################################################################### # Pack everything into the window editorPanel = wx.Panel(self) editorSizer = wx.BoxSizer(wx.VERTICAL) editorSizer.Add((0,0), border=15, flag=wx.TOP) self.editor = Editor(editorPanel, style=wx.NO_BORDER, size=(300, 400)) koko.globals.EDITOR = weakref.proxy(self.editor) self.editor.load_template() self.editor.bind_callbacks(callbacks) editorSizer.Add(self.editor, proportion=1, flag=wx.EXPAND) self._hint = wx.StaticText(editorPanel) editorSizer.Add(self._hint, border=5, flag=wx.ALL) editorPanel.SetSizerAndFit(editorSizer) ####################################################################### sizer = wx.BoxSizer(wx.HORIZONTAL) sizer.Add(editorPanel, proportion=2, flag=wx.EXPAND) sizer.Add(canvasPanel, proportion=3, flag=wx.EXPAND) self.hide_script = lambda: (editorPanel.Hide(), self.Layout()) self.show_script = lambda: (editorPanel.Show(), self.Layout()) self.SetSizerAndFit(sizer) ####################################################################### DARK_THEME.apply(self) DARK_THEME.apply(canvasPanel) DARK_THEME.apply(editorPanel) DARK_THEME.apply(version) DARK_THEME.apply(self._hint) DARK_THEME.apply(self._status) DARK_THEME.apply(self._output) DARK_THEME.apply(self.editor) self._status.SetForegroundColour(wx.Colour(100, 100, 100)) self.hide_output() self.Maximize() ################################################################################ def build_menus(self, callbacks): '''Build a set of menus and attach associated callbacks.''' def attach(menu, command, shortcut='', help='', wxID=wx.ID_ANY, attach_function = None): '''Helper function to add an item to a menu and bind the associated callback.''' if shortcut: menu_text = '%s\t%s' % (command, shortcut) else: menu_text = command if not command in callbacks.keys(): raise KeyError('Could not find callback for menu item "%s"' % command) if attach_function is None: item = menu.Append(wxID, menu_text, help) else: item = attach_function(wxID, menu_text, help) self.Bind(wx.EVT_MENU, callbacks[command], item) return item menu_bar = wx.MenuBar() file = wx.Menu() attach(file, 'New', 'Ctrl+N', 'Start a new script design', wx.ID_NEW) attach(file, 'New PCB', '', 'Start a new pcb design') file.AppendSeparator() attach(file, 'Open', 'Ctrl+O', 'Open a design file', wx.ID_OPEN) attach(file, 'Reload', 'Ctrl+R', 'Reload the current file') file.AppendSeparator() attach(file, 'Save', 'Ctrl+S', 'Save the current file', wx.ID_SAVE) attach(file, 'Save As', 'Ctrl+Shift+S', 'Save the current file', wx.ID_SAVEAS) if not 'Darwin' in os.uname(): file.AppendSeparator() attach(file, 'About', '', 'Display an About box', wx.ID_ABOUT) attach(file, 'Exit', 'Ctrl+Q', 'Terminate the program', wx.ID_EXIT) menu_bar.Append(file, 'File') view = wx.Menu() output = attach(view, 'Show output', '', 'Display errors in a separate pane', attach_function=view.AppendCheckItem) script = attach(view, 'Show script', 'Ctrl+T', 'Display Python script', attach_function=view.AppendCheckItem) script.Toggle() view.AppendSeparator() attach(view, 'Snap to bounds', '', 'Snap view to cad file bounds.') view.AppendSeparator() attach(view, 'Re-render', 'Ctrl+Enter', 'Re-render the output image') menu_bar.Append(view, 'View') export = wx.Menu() attach(export, '.math', '', 'Export to .math file') attach(export, '.png', '', 'Export to image file') attach(export, '.svg', '', 'Export to svg file') attach(export, '.stl', '', 'Export to stl file') attach(export, '.dot', '', 'Export to dot / Graphviz file') export.AppendSeparator() self.start_fab = attach(export, 'Start fab modules', '', 'Load in fab modules') self.update_fab = attach(export, 'Update fab file', '', 'Updates the file exported to the fab modules') self.update_fab.Enable(False) libraries = wx.Menu() attach(libraries, 'koko.lib.shapes', 'Standard shape library') attach(libraries, 'koko.lib.text', 'Standard text library') menu_bar.Append(export, 'Export') menu_bar.Append(libraries, 'Libraries') self.SetMenuBar(menu_bar) ################################################################################ @property def status(self): return self._status.GetLabel() @status.setter def status(self, value): wx.CallAfter(self._status.SetLabel, value) ################################################################################ @property def hint(self): return self._hint.GetLabel() @hint.setter def hint(self, value): wx.CallAfter(self._hint.SetLabel, value) ################################################################################ @property def output(self): return self._output.text @output.setter def output(self, value): self._output.text = value ################################################################################ def OnMenuHighlight(self, event): '''Sets an appropriate hint based on the highlighted menu item.''' id = event.GetMenuId() item = self.GetMenuBar().FindItemById(id) if not item or not item.GetHelp(): self.hint = '' else: self.hint = item.GetHelp() def OnMenuClose(self, event): '''Clears the menu item hint.''' self.hint = ''