class Config(Page): """Page for making configuration changes. This includes source, channel configuration as well as a logging console. Note: This page constructs all source instances and adds them to the manager. """ def __init__(self, *args, **kwargs): """Construct a new Config page. """ Page.__init__(self, name='Config', *args, **kwargs) self.scrolledPanel = ScrolledPanel(self) self.initSourceConfig() self.initChannelConfig() self.initMessageArea() self.initLayout() self.selectSource() def initSourceConfig(self): """Initialize the source configuration area. """ # Generate a dictionary of configuration panels for each source. # dictionary mapping source name to a configuration panel self.srcPanels = { src.getName(): src.genConfigPanel(parent=self.scrolledPanel) for src in self.mgr.getAllSources() } self.curSrcPanel = self.srcPanels[self.src.getName()] # sizer for source configuration options general to all sources sourceGeneralSizer = wx.BoxSizer(orient=wx.HORIZONTAL) # source selector sourceControlBox = widgets.ControlBox(self.scrolledPanel, label='Source', orient=wx.VERTICAL) choices = sorted(list(self.srcPanels.keys()), key=lambda k: k.lower(), reverse=True) self.sourceComboBox = wx.ComboBox(self.scrolledPanel, id=wx.ID_ANY, choices=choices, value=self.src.getName(), style=wx.CB_READONLY) self.sourceComboBox.Bind(wx.EVT_COMBOBOX, self.selectSource, self.sourceComboBox) sourceControlBox.Add(self.sourceComboBox, proportion=0, flag=wx.ALL, border=10) # query button self.sourceQueryButton = wx.Button(self.scrolledPanel, label='Query') sourceControlBox.Add(self.sourceQueryButton, proportion=0, flag=wx.LEFT | wx.BOTTOM | wx.RIGHT | wx.EXPAND, border=10) self.Bind(wx.EVT_BUTTON, self.querySource, self.sourceQueryButton) # reset button self.sourceResetButton = wx.Button(self.scrolledPanel, label='Reset') sourceControlBox.Add(self.sourceResetButton, proportion=0, flag=wx.LEFT | wx.BOTTOM | wx.RIGHT | wx.EXPAND, border=10) #self.Bind(wx.EVT_BUTTON, self.resetSource, self.sourceResetButton) sourceGeneralSizer.Add(sourceControlBox, proportion=0, flag=wx.RIGHT | wx.TOP | wx.LEFT, border=10) bufferSizer = wx.BoxSizer(orient=wx.VERTICAL) # buffer seconds selector bufferSecsControlBox = widgets.ControlBox(self.scrolledPanel, label='Buffer Size', orient=wx.HORIZONTAL) self.bufferRollSpinCtrl = wx.SpinCtrl(self.scrolledPanel, style=wx.SP_WRAP, value=str(3), min=2, max=10, size=(100, 28)) bufferSecsControlBox.Add(self.bufferRollSpinCtrl, proportion=0, flag=wx.ALL | wx.CENTER, border=10) xStaticText = wx.StaticText(self.scrolledPanel, label='X') bufferSecsControlBox.Add(xStaticText, proportion=0, flag=wx.CENTER) self.bufferSecsSpinCtrl = wx.SpinCtrl(self.scrolledPanel, style=wx.SP_WRAP, value=str(300), min=60, max=1000, size=(125, 28)) bufferSecsControlBox.Add(self.bufferSecsSpinCtrl, proportion=0, flag=wx.ALL | wx.CENTER, border=10) bufferSizer.Add(bufferSecsControlBox, proportion=1, flag=wx.TOP | wx.RIGHT | wx.EXPAND, border=10) precisControlBox = widgets.ControlBox(self.scrolledPanel, label='Data Precision', orient=wx.HORIZONTAL) self.precisSingleButton = wx.RadioButton(self.scrolledPanel, label='Single', style=wx.RB_GROUP) precisControlBox.Add(self.precisSingleButton, proportion=0, flag=wx.TOP | wx.LEFT | wx.BOTTOM | wx.CENTER, border=10) self.precisDoubleButton = wx.RadioButton(self.scrolledPanel, label='Double') precisControlBox.Add(self.precisDoubleButton, proportion=0, flag=wx.ALL | wx.CENTER, border=10) self.precisDoubleButton.SetValue(True) #self.Bind(wx.EVT_RADIOBUTTON, self.setExtendedPrecision, self.precisExtendedButton) bufferSizer.Add(precisControlBox, proportion=1, flag=wx.TOP | wx.RIGHT | wx.EXPAND, border=10) sourceGeneralSizer.Add(bufferSizer, proportion=0, flag=wx.EXPAND) sourceSpecificSizer = wx.BoxSizer(orient=wx.VERTICAL) # add each source configuration panel (we'll hide/show as needed) for sp in self.srcPanels.values(): sourceSpecificSizer.Add(sp, proportion=1) #, flag=wx.EXPAND) # sizer for both general and specific configurations self.sourceSizer = wx.BoxSizer(orient=wx.VERTICAL) self.sourceSizer.Add(sourceGeneralSizer, proportion=0, flag=wx.EXPAND) self.sourceSizer.Add(sourceSpecificSizer, proportion=1, flag=wx.EXPAND) def initChannelConfig(self): """Initialize the channel configuration area. """ # controlbox to surround the area chanControlBox = widgets.ControlBox(self.scrolledPanel, label='Channels', orient=wx.HORIZONTAL) # only supports two columns, this could probably be done better XXX - idfah ## # left column ## leftChanSizer = wx.BoxSizer(orient=wx.VERTICAL) ## # create text controls ## self.chanTextCtrls = [] ## for c in range(16): ## curChanTextCtrl = wx.TextCtrl(self.scrolledPanel) ## self.chanTextCtrls.append(curChanTextCtrl) ## leftChanSizer.Add(curChanTextCtrl, proportion=0, ## flag=wx.RIGHT | wx.TOP | wx.LEFT, border=10) ## # add to sizer ## chanControlBox.Add(leftChanSizer) ## # right column ## rightChanSizer = wx.BoxSizer(orient=wx.VERTICAL) ## # create text controls ## for c in range(16): ## curChanTextCtrl = wx.TextCtrl(self.scrolledPanel) ## self.chanTextCtrls.append(curChanTextCtrl) ## rightChanSizer.Add(curChanTextCtrl, proportion=0, ## flag=wx.RIGHT | wx.TOP | wx.LEFT, border=10) ## # add to sizer ## chanControlBox.Add(rightChanSizer) self.chanSizer = wx.GridSizer(40, 2, 10, 10) #self.chanSizer = wx.BoxSizer(orient=wx.VERTICAL) self.chanTextCtrls = [ wx.TextCtrl(self.scrolledPanel) for i in range(40 * 2) ] self.chanSizer.AddMany(self.chanTextCtrls) #for ctc in self.chanTextCtrls: # self.chanSizer.Add(ctc, proportion=0, flag=wx.TOP | wx.LEFT | wx.RIGHT, border=2) chanControlBox.Add(self.chanSizer, flag=wx.ALL, border=10) # sizer for channel configuration area self.chanSizer = wx.BoxSizer(orient=wx.VERTICAL) self.chanSizer.Add(chanControlBox, proportion=1, flag=wx.TOP | wx.BOTTOM, border=10) def initMessageArea(self): """Initialize the message log area. """ # font for messages msgFont = wx.Font(pointSize=11, family=wx.FONTFAMILY_MODERN, style=wx.FONTSTYLE_NORMAL, weight=wx.FONTWEIGHT_NORMAL, underline=False) # font for CEBL introduction message helloFont = wx.Font(pointSize=24, family=wx.FONTFAMILY_ROMAN, style=wx.FONTSTYLE_NORMAL, weight=wx.FONTWEIGHT_BOLD, underline=True) # the message log messageControlBox = widgets.ControlBox(self.scrolledPanel, label='Message Log', orient=wx.VERTICAL) self.messageArea = wx.TextCtrl(self.scrolledPanel, style=wx.TE_MULTILINE | wx.TE_READONLY | wx.TE_RICH) self.messageArea.SetMinSize((150, 150)) messageControlBox.Add(self.messageArea, proportion=1, flag=wx.ALL | wx.EXPAND, border=10) # intro message self.messageArea.SetDefaultStyle( wx.TextAttr(colText=wx.Colour('black'), font=helloFont)) self.messageArea.AppendText('Welcome to CEBL!\n\n') # setup message style self.messageArea.SetDefaultStyle(wx.TextAttr()) self.messageArea.SetDefaultStyle( wx.TextAttr(colText=wx.Colour('black'), font=msgFont)) # add the message area text ctrl widget as a log target self.mgr.logger.addTextCtrl(self.messageArea) messageControlSizer = wx.BoxSizer(orient=wx.HORIZONTAL) # button for saving the message log to a file self.saveMessagesButton = wx.Button(self.scrolledPanel, label='Save') messageControlSizer.Add(self.saveMessagesButton, proportion=0, flag=wx.LEFT | wx.BOTTOM | wx.RIGHT, border=10) self.Bind(wx.EVT_BUTTON, self.saveMessages, self.saveMessagesButton) # button for clearing the message log self.clearMessagesButton = wx.Button(self.scrolledPanel, label='Clear') messageControlSizer.Add(self.clearMessagesButton, proportion=0, flag=wx.BOTTOM | wx.RIGHT, border=10) self.Bind(wx.EVT_BUTTON, self.clearMessages, self.clearMessagesButton) # set up verbose logging self.verboseMessagesCheckBox = wx.CheckBox(self.scrolledPanel, label='Verbose') messageControlSizer.Add(self.verboseMessagesCheckBox, proportion=0, flag=wx.BOTTOM | wx.RIGHT, border=10) messageControlBox.Add(messageControlSizer, proportion=0, flag=wx.EXPAND) # sizer for message log area self.messageSizer = wx.BoxSizer(orient=wx.VERTICAL) self.messageSizer.Add(messageControlBox, proportion=1, flag=wx.ALL | wx.EXPAND, border=10) def initLayout(self): """Initialize the page layout. """ scrolledSizer = wx.BoxSizer(orient=wx.HORIZONTAL) scrolledSizer.Add(self.sourceSizer, proportion=0) #, flag=wx.EXPAND) scrolledSizer.Add(self.chanSizer, proportion=0, flag=wx.EXPAND) scrolledSizer.Add(self.messageSizer, proportion=1, flag=wx.EXPAND) self.scrolledPanel.SetSizer(scrolledSizer) # main sizer sizer = wx.BoxSizer(orient=wx.HORIZONTAL) sizer.Add(self.scrolledPanel, proportion=1, flag=wx.EXPAND) self.SetSizer(sizer) self.scrolledPanel.Layout() self.scrolledPanel.FitInside() self.scrolledPanel.SetupScrolling() # hide after layout (prevents gtk warnings) for sp in self.srcPanels.values(): sp.deselect() def updateChanText(self): for ctc in self.chanTextCtrls: ctc.Clear() ctc.Hide() chanNames = self.src.getChanNames() ctls = self.chanTextCtrls[:len(chanNames)] for chan, ctl in zip(chanNames, ctls[0::2] + ctls[1::2]): ctl.Show() ctl.AppendText(chan) def afterUpdateSource(self): self.updateChanText() def selectSource(self, event=None): """Set a new source from the source selection combobox. """ srcName = self.sourceComboBox.GetValue() # deselect previous source config panel self.curSrcPanel.deselect() # select new source config panel self.curSrcPanel = self.srcPanels[srcName] self.curSrcPanel.select() # set the source in the manager self.mgr.setSource(srcName) # add source description to the message log wx.LogMessage(repr(self.src) + '\n') # update the text in the channel configuration area self.updateChanText() # adjust layout since we have shown and hidden panels self.scrolledPanel.Layout() self.scrolledPanel.FitInside() def querySource(self, event=None): """Call the query method on the current source and put the output in the message log. """ try: wx.LogMessage(self.src.query()) except Exception as e: wx.LogError('Failed to query source: ' + str(e)) def clearMessages(self, event=None): """Clear the message log. """ self.messageArea.Clear() def saveMessages(self, event=None): """Save the message log to file. """ saveDialog = wx.FileDialog( self.scrolledPanel, message='Save Message Log', wildcard='Text Files (*.txt)|*.txt|All Files|*', style=wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT) try: if saveDialog.ShowModal() == wx.ID_CANCEL: return with open(saveDialog.GetPath(), 'w') as fileHandle: fileHandle.write(self.messageArea.GetValue()) except Exception as e: wx.LogError('Save failed!') raise finally: saveDialog.Destroy()
def __init__(self, parent=None, *args, **kw): super().__init__(parent, title='Azur Lane Combat Counter', style=wx.CAPTION | wx.CLOSE_BOX | wx.MINIMIZE_BOX | wx.SYSTEM_MENU | wx.TAB_TRAVERSAL | wx.RESIZE_BORDER | wx.CLIP_CHILDREN, *args, **kw) self.SetSizeHints(wx.DefaultSize, wx.DefaultSize) self.SetBackgroundColour( wx.SystemSettings.GetColour(wx.SYS_COLOUR_WINDOW)) frame_sizer = wx.BoxSizer(wx.VERTICAL) self.SetSizer(frame_sizer) header_sizer = wx.BoxSizer(wx.HORIZONTAL) frame_sizer.Add(header_sizer, 0, wx.EXPAND | wx.ALL, border=5) self.spin = wx.SpinCtrl(self, min=0, max=99999, style=wx.ALIGN_CENTER_HORIZONTAL | wx.SP_ARROW_KEYS | wx.SP_WRAP | wx.TE_PROCESS_ENTER) self.spin.SetFont( wx.Font(30, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL, False, "Segoe UI")) self.spin.Bind(wx.EVT_SPINCTRL, lambda e: self.on_number_change(e.GetPosition())) self.spin.Bind(wx.EVT_TEXT, lambda e: self.on_number_change(e.GetInt())) header_sizer.Add(self.spin, 1, flag=wx.ALL) display_checkbox = wx.CheckBox(self, label='Display') display_checkbox.Bind(wx.EVT_CHECKBOX, lambda e: self.on_display_check(e.IsChecked())) header_sizer.Add(display_checkbox, flag=wx.CENTER | wx.LEFT | wx.RIGHT, border=40) info_panel = ScrolledPanel(self, style=wx.BORDER_THEME | wx.TAB_TRAVERSAL) info_panel.SetBackgroundColour( wx.SystemSettings.GetColour(wx.SYS_COLOUR_MENU)) panel_sizer = wx.BoxSizer(wx.VERTICAL) info_panel.SetSizer(panel_sizer) self.info_text = wx.StaticText(info_panel) self.info_text.Wrap(-1) self.info_text.SetFocus() # this removes focus from the SpinCtrl panel_sizer.Add(self.info_text, 0, wx.ALL, border=5) info_panel.Layout() info_panel.SetupScrolling() panel_sizer.FitInside(info_panel) frame_sizer.Add(info_panel, 1, wx.EXPAND | wx.ALL, border=5) self.Layout() self.Centre(wx.BOTH)
class MyFrame3(wx.Frame): def __init__(self, parent): wx.Frame.__init__(self, parent, id=wx.ID_ANY, title=wx.EmptyString, pos=wx.DefaultPosition, size=wx.Size(500, 300), style=wx.DEFAULT_FRAME_STYLE | wx.TAB_TRAVERSAL) self.SetSizeHintsSz(wx.DefaultSize, wx.DefaultSize) bSizer27 = wx.BoxSizer(wx.VERTICAL) self.m_splitter2 = wx.SplitterWindow(self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.SP_3D | wx.SUNKEN_BORDER) self.m_splitter2.SetMinimumPaneSize(30) self.m_panel8 = wx.Panel(self.m_splitter2, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.TAB_TRAVERSAL) bSizer29 = wx.BoxSizer(wx.VERTICAL) #self.m_scrolledWindow2 = wx.ScrolledWindow( self.m_panel8, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.HSCROLL|wx.VSCROLL ) #self.m_scrolledWindow2.SetScrollRate( 5, 5 ) #bSizer30 = wx.BoxSizer( wx.VERTICAL ) #self.m_panel10 = wx.Panel( self.m_scrolledWindow2, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.TAB_TRAVERSAL ) self.m_panel10 = ScrolledPanel(self.m_panel8, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.TAB_TRAVERSAL) bSizer32 = wx.BoxSizer(wx.VERTICAL) self.bSizer32 = bSizer32 self.m_panel10.SetSizer(bSizer32) self.m_panel10.Layout() bSizer32.Fit(self.m_panel10) #bSizer30.Add( self.m_panel10, 1, wx.EXPAND |wx.ALL, 5 ) #self.m_scrolledWindow2.SetSizer( bSizer30 ) #self.m_scrolledWindow2.Layout() #bSizer30.Fit( self.m_scrolledWindow2 ) #bSizer29.Add( self.m_scrolledWindow2, 1, wx.EXPAND |wx.ALL, 5 ) bSizer29.Add(self.m_panel10, 1, wx.EXPAND | wx.ALL, 5) self.m_panel8.SetSizer(bSizer29) self.m_panel8.Layout() bSizer29.Fit(self.m_panel8) self.m_panel9 = wx.Panel(self.m_splitter2, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.TAB_TRAVERSAL) bSizer31 = wx.BoxSizer(wx.VERTICAL) self.m_button11 = wx.Button(self.m_panel9, wx.ID_ANY, u"Add!", wx.DefaultPosition, wx.DefaultSize, 0) bSizer31.Add(self.m_button11, 0, wx.ALL, 5) self.m_panel9.SetSizer(bSizer31) self.m_panel9.Layout() bSizer31.Fit(self.m_panel9) self.m_splitter2.SplitHorizontally(self.m_panel8, self.m_panel9, -1) bSizer27.Add(self.m_splitter2, 1, wx.EXPAND, 5) self.SetSizer(bSizer27) self.Layout() self.Centre(wx.BOTH) # Connect Events self.m_button11.Bind(wx.EVT_BUTTON, self.onAddButton) def __del__(self): pass # Virtual event handlers, overide them in your derived class def onAddButton(self, event): # add the grid widget self.m_grid5 = wx.grid.Grid(self.m_panel10, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, 0) # Grid self.m_grid5.CreateGrid(10, 10) self.m_grid5.EnableEditing(True) self.m_grid5.EnableGridLines(True) self.m_grid5.EnableDragGridSize(False) self.m_grid5.SetMargins(0, 0) # Columns self.m_grid5.EnableDragColMove(False) self.m_grid5.EnableDragColSize(True) self.m_grid5.SetColLabelSize(30) self.m_grid5.SetColLabelAlignment(wx.ALIGN_CENTRE, wx.ALIGN_CENTRE) # Rows self.m_grid5.EnableDragRowSize(True) self.m_grid5.SetRowLabelSize(80) self.m_grid5.SetRowLabelAlignment(wx.ALIGN_CENTRE, wx.ALIGN_CENTRE) # Label Appearance # Cell Defaults self.m_grid5.SetDefaultCellAlignment(wx.ALIGN_LEFT, wx.ALIGN_TOP) self.bSizer32.Add(self.m_grid5, 0, wx.ALL, 5) self.bSizer32.Layout() self.m_panel10.SetupScrolling() widget = self.m_panel10 widget.Layout() while widget.GetParent(): widget = widget.GetParent() widget.Layout() if widget.IsTopLevel(): break event.Skip() def m_splitter2OnIdle(self, event): self.m_splitter2.SetSashPosition(0) self.m_splitter2.Unbind(wx.EVT_IDLE)