def _initializeUIElements(self): """ Instantiate all the UI elements """ self.__splitter = SplitterWindow(self.__parent, ID_ANY) self.__projectTree = TreeCtrl(self.__splitter, ID_ANY, style=TR_HIDE_ROOT + TR_HAS_BUTTONS) self.__projectTreeRoot = self.__projectTree.AddRoot(_("Root")) # self.__projectTree.SetPyData(self.__projectTreeRoot, None) # Expand root, since wx.TR_HIDE_ROOT is not supported under windows # Not supported for hidden tree since wx.Python 2.3.3.1 ? # self.__projectTree.Expand(self.__projectTreeRoot) # diagram container self.__notebook = Notebook(self.__splitter, ID_ANY, style=CLIP_CHILDREN) # Set splitter self.__splitter.SetMinimumPaneSize(20) self.__splitter.SplitVertically(self.__projectTree, self.__notebook, 160) self.__notebookCurrentPage = -1 # Callbacks self.__parent.Bind(EVT_NOTEBOOK_PAGE_CHANGED, self.__onNotebookPageChanged) self.__parent.Bind(EVT_TREE_SEL_CHANGED, self.__onProjectTreeSelChanged) self.__projectTree.Bind(EVT_TREE_ITEM_RIGHT_CLICK, self.__onProjectTreeRightClick)
def __init__(self, parent, title): Frame.__init__(self, parent, title=title, size=(500, 400)) self.setup_xmlrpc_server() self.completed = False # Create the notebook self.notebook = Notebook(self, style=NB_MULTILINE) # Setting up the menu file_menu = Menu() exit_item = file_menu.Append(ID_EXIT, '&Exit...', 'Exit Settings Window') self.Bind(EVT_MENU, self.prepare_for_exit, exit_item) menu_bar = MenuBar() menu_bar.Append(file_menu, '&File') self.SetMenuBar(menu_bar) alpha = settings.SETTINGS.keys() alpha.sort() self.fields = [] for top in alpha: self.make_page(top) self.CenterOnScreen() self.Show() self.Bind(EVT_CLOSE, self.xmlrpc_kill) def start_server(): while not self.server_quit: self.server.handle_request() Timer(0.5, start_server).start() Timer(300, self.xmlrpc_kill).start()
def __init__(self, parent, title, server): Frame.__init__(self, parent, title=title, size=(500, 400)) global SETTINGS_FRAME SETTINGS_FRAME = self self.server = server self.setup_xmlrpc_server() self.completed = False self.notebook = Notebook(self, style=NB_MULTILINE) file_menu = Menu() self.next_page = file_menu.Append(ID_ANY, '&Next page\tRAWCTRL+TAB', 'Next page') self.prev_page = file_menu.Append(ID_ANY, '&Prev page\tRAWCTRL+SHIFT+TAB', 'Prev page') self.Bind(EVT_MENU, self.OnTab, self.next_page) self.Bind(EVT_MENU, self.OnTab, self.prev_page) exit_item = file_menu.Append(ID_EXIT, '&Exit...', 'Exit Settings Window') self.Bind(EVT_MENU, self.prepare_for_exit, exit_item) menu_bar = MenuBar() menu_bar.Append(file_menu, '&File') self.SetMenuBar(menu_bar) self.fields = [] for top in sorted(settings.SETTINGS.keys()): # pylint: disable=no-member self.make_page(top) self.CenterOnScreen() self.Show() self.Bind(EVT_ON_KILL, self.OnKill) self.Bind(EVT_ON_COMPLETE, self.OnComplete) self.Bind(EVT_CLOSE, self.xmlrpc_kill) self.expiration = threading.Timer(300, self.xmlrpc_kill) self.expiration.start()
def search_for_page(notebook: wx.Notebook, page_name: str): """ Search for a page with a specific name inside the notebook. """ n_pages = notebook.GetPageCount() l_pages = [notebook.GetPageText(i) for i in range(n_pages)] return page_name in l_pages
def __init__(self, parent: wx.Notebook, *args, **kwargs): super().__init__(parent, *args, **kwargs) parent.GetParent().Connect(-1, -1, models.EVT_APP_CLEAR, self.OnClearApp) parent.GetParent().Connect(-1, -1, models.EVT_CALC_RAIDGROUPS, self.OnCalcRaidGroups) config.RAID_GROUPS = raidgroups.GroupBuilder() ########################### # Raid Groups Frame (Tab 5) ########################### self.raidgroups_main_box = wx.WrapSizer() self.label_font = wx.Font(11, wx.DEFAULT, wx.DEFAULT, wx.BOLD) self.no_groups_text = wx.StaticText( self, label="No raid groups have been calculated.\n\n" "Please select an entry from the Attendance Logs " "panel to use for group calculation.") self.no_groups_text.SetFont(self.label_font) self.raidgroups_main_box.Add(self.no_groups_text, flag=wx.TOP | wx.LEFT, border=10) # Finalize Tab self.SetSizer(self.raidgroups_main_box) parent.AddPage(self, 'Raid Groups')
def construct_notebook(self): """Constructs the main Notebook panel""" panel = Panel(self) self.notebook = Notebook(panel, style=NB_LEFT) self.construct_tabs() sizer = BoxSizer(HORIZONTAL) sizer.Add(self.notebook, 1, EXPAND) panel.SetSizer(sizer)
def delete_all_excluding(notebook: wx.Notebook, exclusion_list: list): """ Delete all pages in the notebook, except specified ones. :exclusion_list: is a list of string, containing some page names. """ if exclusion_list: l_index = [] n_pages = notebook.GetPageCount() for i in range(n_pages): if notebook.GetPageText(i) not in exclusion_list: l_index.append(i) # Gather index of pages to delete l_index.sort(reverse=True) for index in l_index: notebook.DeletePage(index) else: notebook.DeleteAllPages()
def __init__(self, parent: wx.Notebook, *args, **kwargs): super().__init__(parent, *args, **kwargs) parent.GetParent().Connect(-1, -1, models.EVT_KILL, self.OnKill) parent.GetParent().Connect(-1, -1, models.EVT_APP_CLEAR, self.OnClearApp) ########################### # Kill Timers Frame (Tab 4) ########################### killtimers_main_box = wx.BoxSizer(wx.VERTICAL) # List killtimers_list = ObjectListView.GroupListView(self, wx.ID_ANY, style=wx.LC_REPORT, size=wx.Size(600, 1080), useExpansionColumn=True) killtimers_main_box.Add(killtimers_list, flag=wx.EXPAND | wx.ALL) self.killtimers_list = killtimers_list def killtimerGroupKey(kill): group_key = kill.island() return group_key killtimers_list.SetColumns([ ObjectListView.ColumnDefn("Time", "left", 180, "time", groupKeyGetter=killtimerGroupKey, groupKeyConverter='Island %s', fixedWidth=180), ObjectListView.ColumnDefn("Mob", "left", 400, "name", groupKeyGetter=killtimerGroupKey, groupKeyConverter='Island %s', fixedWidth=400), ]) killtimers_list.SetObjects(config.KILL_TIMERS) killtimers_list.SetEmptyListMsg("No tracked mob deaths witnessed.") # Finalize Tab self.SetSizer(killtimers_main_box) parent.AddPage(self, 'Time of Death Tracking')
def __init__(self, parent: Window, wxID: int = wxNewIdRef()): """ Args: parent: Parent window wxID: A control ID if caller wants one """ super().__init__(parent, wxID, 'Configure', style=CAPTION | CLOSE_BOX | DIALOG_EX_METAL) self.Center(BOTH) pane: SizedPanel = self.GetContentsPane() pane.SetSizerType('vertical') book: Notebook = Notebook(pane, ID_ANY, style=BK_DEFAULT | NB_TOP) tokensConfigurationPanel: TokensConfigurationPanel = TokensConfigurationPanel( book) todoistConfigurationPanel: TodoistConfigurationPanel = TodoistConfigurationPanel( book) gitHubConfigurationPanel: GitHubConfigurationPanel = GitHubConfigurationPanel( book) book.AddPage(tokensConfigurationPanel, 'Tokens', select=True) book.AddPage(todoistConfigurationPanel, 'Todoist', select=False) book.AddPage(gitHubConfigurationPanel, 'GitHub', select=False) self.SetButtonSizer(self.CreateStdDialogButtonSizer(OK | CANCEL)) self.Fit() self.SetMinSize(self.GetSize()) self.Bind(EVT_BUTTON, self.__onCmdOk, id=ID_OK) self.Bind(EVT_BUTTON, self.__onClose, id=ID_CANCEL) self.Bind(EVT_CLOSE, self.__onClose)
class SettingsFrame(Frame): def __init__(self, parent, title): Frame.__init__(self, parent, title=title, size=(500, 400)) self.setup_xmlrpc_server() self.completed = False # Create the notebook self.notebook = Notebook(self, style=NB_MULTILINE) # Setting up the menu file_menu = Menu() exit_item = file_menu.Append(ID_EXIT, '&Exit...', 'Exit Settings Window') self.Bind(EVT_MENU, self.prepare_for_exit, exit_item) menu_bar = MenuBar() menu_bar.Append(file_menu, '&File') self.SetMenuBar(menu_bar) alpha = settings.SETTINGS.keys() alpha.sort() self.fields = [] for top in alpha: self.make_page(top) self.CenterOnScreen() self.Show() self.Bind(EVT_CLOSE, self.xmlrpc_kill) def start_server(): while not self.server_quit: self.server.handle_request() Timer(0.5, start_server).start() Timer(300, self.xmlrpc_kill).start() def prepare_for_exit(self, e): self.Hide() self.completed = True threading.Timer(10, self.xmlrpc_kill).start() def tree_to_dictionary(self, t=None): d = {} children = None if t is None: children = self.fields else: children = t.children for field in children: value = None if isinstance(field.wx_field, TextCtrl): value = field.wx_field.GetValue() if field.text_type == list: d[field.original] = [ x for x in value.replace(", ", ",").split(",") if x ] # don't count empty strings elif field.text_type == int: d[field.original] = int(value) else: d[field.original] = value.replace("\\", "/") elif isinstance(field.wx_field, (Panel, ScrolledPanel)): d[field.original] = self.tree_to_dictionary(field) elif isinstance(field.wx_field, CheckBox): d[field.original] = field.wx_field.GetValue() return d def setup_xmlrpc_server(self): self.server_quit = 0 comm = Communicator() self.server = SimpleXMLRPCServer( (Communicator.LOCALHOST, comm.com_registry["hmc"]), allow_none=True) self.server.register_function(self.xmlrpc_get_message, "get_message") self.server.register_function(self.xmlrpc_complete, "complete") self.server.register_function(self.xmlrpc_kill, "kill") def xmlrpc_kill(self, e=None): self.server_quit = 1 os.kill(os.getpid(), signal.SIGTERM) self.Close() def xmlrpc_get_message(self): if self.completed: Timer(1, self.xmlrpc_kill).start() return self.tree_to_dictionary() else: return None def xmlrpc_complete(self): self.completed = True self.Hide() def make_page(self, title): page = ScrolledPanel(parent=self.notebook, id=-1) vbox = BoxSizer(VERTICAL) field = Field(page, title) self.get_fields(page, vbox, field) self.fields.append(field) page.SetupScrolling() page.SetSizer(vbox) self.notebook.AddPage(page, title) def get_fields(self, page, vbox, field): keys = settings.SETTINGS[field.original].keys() keys.sort() for label in keys: hbox = BoxSizer(HORIZONTAL) value = settings.SETTINGS[field.original][label] lbl = StaticText(page, label=label) hbox.Add(lbl, flag=RIGHT, border=8) subfield = Field(None, label) item = self.field_from_value(page, value, subfield) field.add_child(subfield) if item != None: hbox.Add(item, proportion=1) vbox.Add(hbox, flag=EXPAND | LEFT | RIGHT | TOP, border=5) vbox.Add((-1, 5)) def field_from_value(self, window, value, field): item = None if isinstance(value, basestring): item = TextCtrl(window, value=value) field.text_type = basestring elif isinstance(value, list): item = TextCtrl(window, value=", ".join(value)) field.text_type = list elif isinstance(value, bool): item = CheckBox(window, -1, '', (120, 75)) item.SetValue(value) elif isinstance(value, int): item = TextCtrl(window, value=str(value)) field.text_type = int elif isinstance(value, dict): subpage = Panel(window) vbox = BoxSizer(VERTICAL) alpha = value.keys() alpha.sort() for lbl in alpha: hbox = BoxSizer(HORIZONTAL) value2 = value[lbl] label = StaticText(subpage, label=lbl) hbox.Add(label, flag=RIGHT, border=8) subfield = Field(None, lbl) item = self.field_from_value(subpage, value2, subfield) field.add_child(subfield) if item != None: hbox.Add(item, proportion=1) vbox.Add(hbox, flag=EXPAND | LEFT | RIGHT | TOP, border=5) vbox.Add((-1, 5)) subpage.SetSizer(vbox) subpage.Show() item = subpage field.wx_field = item return item
def __init__(self, parent: wx.Notebook, *args, **kwargs): super().__init__(parent, *args, **kwargs) parent.GetParent().Connect(-1, -1, models.EVT_DROP, self.OnDrop) parent.GetParent().Connect(-1, -1, models.EVT_BID, self.OnBid) parent.GetParent().Connect(-1, -1, models.EVT_APP_CLEAR, self.OnClearApp) ####################### # Bidding Frame (Tab 1) ####################### # bidding_frame = wx.Window(notebook) bidding_splitter = wx.lib.splitter.MultiSplitterWindow( self, wx.ID_ANY, style=wx.SP_3D | wx.SP_BORDER) bidding_splitter.SetOrientation(wx.VERTICAL) pane_1 = wx.Panel(bidding_splitter, wx.ID_ANY) pane_2 = wx.Panel(bidding_splitter, wx.ID_ANY) pane_3 = wx.Panel(bidding_splitter, wx.ID_ANY) bidding_main_box1 = wx.BoxSizer(wx.VERTICAL) bidding_main_box2 = wx.BoxSizer(wx.VERTICAL) bidding_main_box3 = wx.BoxSizer(wx.VERTICAL) label_font = wx.Font(11, wx.DEFAULT, wx.DEFAULT, wx.BOLD) # ---------------- # Pending Loot Box # ---------------- pending_label = wx.StaticText( pane_1, label="Pending Drops", style=wx.ALIGN_LEFT) pending_label.SetFont(label_font) bidding_main_box1.Add( pending_label, flag=wx.LEFT | wx.TOP, border=10) pending_box = wx.BoxSizer(wx.HORIZONTAL) bidding_main_box1.Add( pending_box, flag=wx.EXPAND | wx.LEFT | wx.RIGHT, border=10) # List pending_list = ObjectListView.ObjectListView( pane_1, wx.ID_ANY, size=wx.Size(725, 1000), style=wx.LC_REPORT | wx.LC_SINGLE_SEL) pending_box.Add(pending_list, flag=wx.EXPAND) pending_list.Bind(wx.EVT_COMMAND_LEFT_CLICK, self.UpdateMinDKP) pending_list.Bind(wx.EVT_LEFT_DCLICK, self.OnIgnorePending) self.pending_list = pending_list pending_list.SetColumns([ ObjectListView.ColumnDefn("Report Time", "left", 170, "timestamp", fixedWidth=170), ObjectListView.ColumnDefn("Reporter", "left", 95, "reporter", fixedWidth=95), ObjectListView.ColumnDefn("Item", "left", 225, "name", fixedWidth=225), ObjectListView.ColumnDefn("Min. DKP", "center", 61, "min_dkp", fixedWidth=61), ObjectListView.ColumnDefn("Restrictions", "left", 85, "classes", fixedWidth=85), ObjectListView.ColumnDefn("Droppable", "center", 70, "droppable", fixedWidth=70), ]) pending_list.SetObjects(config.PENDING_AUCTIONS) pending_list.SetEmptyListMsg("No drops pending.") pending_list.SetToolTip("Double click an item to ignore it") # Buttons pending_buttons_box = wx.BoxSizer(wx.VERTICAL) pending_box.Add(pending_buttons_box, flag=wx.EXPAND | wx.TOP | wx.LEFT, border=10) pending_button_ignore = wx.Button(pane_1, label="Ignore") pending_button_dkp = wx.Button(pane_1, label="DKP Bid") pending_button_roll = wx.Button(pane_1, label="Roll") # pending_buttonspacer = wx.StaticLine(self) pending_button_wiki = wx.Button(pane_1, label="Wiki?") pending_buttons_box.Add(pending_button_ignore, flag=wx.TOP) pending_buttons_box.Add(pending_button_dkp, flag=wx.TOP, border=10) pending_buttons_box.Add(pending_button_roll, flag=wx.TOP, border=10) # pending_buttons_box.Add(pending_buttonspacer, flag=wx.TOP, border=10) pending_buttons_box.Add(pending_button_wiki, flag=wx.TOP, border=10) min_dkp_font = wx.Font(10, wx.DEFAULT, wx.DEFAULT, wx.BOLD) min_dkp_label = wx.StaticText( pane_1, label="Min. DKP") min_dkp_label.SetFont(min_dkp_font) min_dkp_spinner = wx.SpinCtrl(pane_1, value=str(config.MIN_DKP)) min_dkp_spinner.SetRange(0, 10000) min_dkp_spinner.Bind(wx.EVT_SPINCTRL, self.OnMinDkpSpin) self.min_dkp_spinner = min_dkp_spinner pending_buttons_box.Add(min_dkp_label, flag=wx.TOP | wx.LEFT, border=10) pending_buttons_box.Add(min_dkp_spinner, flag=wx.LEFT, border=10) pending_button_ignore.Bind(wx.EVT_BUTTON, self.OnIgnorePending) pending_button_dkp.Bind(wx.EVT_BUTTON, self.StartAuctionDKP) pending_button_roll.Bind(wx.EVT_BUTTON, self.StartAuctionRandom) pending_button_wiki.Bind(wx.EVT_BUTTON, self.ShowWikiPending) # --------------- # Active Loot Box # --------------- active_label = wx.StaticText( pane_2, label="Active Auctions", style=wx.ALIGN_LEFT) active_label.SetFont(label_font) bidding_main_box2.Add( active_label, flag=wx.LEFT | wx.TOP, border=10) active_box = wx.BoxSizer(wx.HORIZONTAL) bidding_main_box2.Add( active_box, flag=wx.EXPAND | wx.LEFT | wx.RIGHT, border=10) # List active_list = ObjectListView.ObjectListView( pane_2, wx.ID_ANY, size=wx.Size(725, 1000), style=wx.LC_REPORT | wx.LC_SINGLE_SEL) active_box.Add(active_list, flag=wx.EXPAND) active_list.Bind(wx.EVT_LEFT_DCLICK, self.ShowActiveDetail) self.active_list = active_list active_list.SetColumns([ ObjectListView.ColumnDefn("Item", "left", 215, "name", fixedWidth=215), ObjectListView.ColumnDefn("Restrictions", "left", 95, "classes", fixedWidth=95), ObjectListView.ColumnDefn("Droppable", "center", 70, "droppable", fixedWidth=70), ObjectListView.ColumnDefn("Rand/Min", "left", 70, "get_target_min", fixedWidth=70), ObjectListView.ColumnDefn("Bid/Roll", "left", 65, "highest_number", fixedWidth=65), ObjectListView.ColumnDefn("Leading", "left", 90, "highest_players", fixedWidth=90), ObjectListView.ColumnDefn("Time Left", "left", 100, "time_remaining_text", fixedWidth=100), ]) active_list.SetObjects(list(config.ACTIVE_AUCTIONS.values())) active_list.SetEmptyListMsg("No auctions pending.") active_list.SetToolTip( "Double click an auction to edit bid the history") self.active_list_refresh_timer = wx.Timer(self, id=1) self.Bind(wx.EVT_TIMER, self.refresh_active_list, self.active_list_refresh_timer) self.active_list_refresh_timer.Start(1000) # Buttons active_buttons_box = wx.BoxSizer(wx.VERTICAL) active_box.Add(active_buttons_box, flag=wx.EXPAND | wx.TOP | wx.LEFT, border=10) active_button_undo = wx.Button(pane_2, label="Undo") active_buttonspacer = wx.StaticLine(pane_2) active_buttons_timebox = wx.BoxSizer(wx.HORIZONTAL) self.active_buttons_timespinner = wx.SpinCtrl( pane_2, min=1, max=30, initial=1, size=(40, 22)) self.active_buttons_timespinner.SetToolTip("Minutes to add/remove") active_button_timeadd = wx.Button(pane_2, label="+", size=(15, 22)) active_button_timeadd.SetToolTip("Add time to Auction") active_button_timesub = wx.Button(pane_2, label="-", size=(15, 22)) active_button_timesub.SetToolTip("Remove time from Auction") active_buttons_timebox.Add(active_button_timesub) active_buttons_timebox.Add(self.active_buttons_timespinner) active_buttons_timebox.Add(active_button_timeadd) active_button_gettext = wx.Button(pane_2, label="Copy Bid") active_button_complete = wx.Button(pane_2, label="Complete") active_button_wiki = wx.Button(pane_2, label="Wiki?") active_cb_bid_target = wx.ComboBox( pane_2, size=wx.Size(70, 22), choices=list(config.BID_CHANNEL_OPTIONS), value=config.PRIMARY_BID_CHANNEL, style=wx.CB_READONLY) active_cb_bid_target.SetToolTip("Selected channel will be used for " "Auction clipboard messages") active_buttons_box.Add(active_button_undo, flag=wx.TOP) active_buttons_box.Add(active_buttonspacer, flag=wx.TOP, border=6) active_buttons_box.Add(active_buttons_timebox, flag=wx.TOP, border=6) active_buttons_box.Add(active_button_gettext, flag=wx.TOP, border=6) active_buttons_box.Add(active_button_complete, flag=wx.TOP, border=6) active_buttons_box.Add(active_button_wiki, flag=wx.TOP, border=6) active_buttons_box.Add(active_cb_bid_target, flag=wx.TOP, border=6) active_button_undo.Bind(wx.EVT_BUTTON, self.UndoStart) active_button_timeadd.Bind(wx.EVT_BUTTON, self.AucTimeDelta) active_button_timesub.Bind(wx.EVT_BUTTON, self.AucTimeDelta) active_button_gettext.Bind(wx.EVT_BUTTON, self.CopyBidText) active_button_complete.Bind(wx.EVT_BUTTON, self.CompleteAuction) active_button_wiki.Bind(wx.EVT_BUTTON, self.ShowWikiActive) active_cb_bid_target.Bind(wx.EVT_COMBOBOX, self.SelectBidTarget) # ------------------- # Historical Loot Box # ------------------- history_label = wx.StaticText( pane_3, label="Historical Auctions", style=wx.ALIGN_LEFT) history_label.SetFont(label_font) bidding_main_box3.Add( history_label, flag=wx.LEFT | wx.TOP, border=10) history_box = wx.BoxSizer(wx.HORIZONTAL) bidding_main_box3.Add( history_box, flag=wx.EXPAND | wx.LEFT | wx.RIGHT, border=10) # List history_list = ObjectListView.ObjectListView( pane_3, wx.ID_ANY, size=wx.Size(725, 1000), style=wx.LC_REPORT | wx.LC_SINGLE_SEL) history_box.Add(history_list, flag=wx.EXPAND | wx.BOTTOM, border=10) history_list.Bind(wx.EVT_LEFT_DCLICK, self.ShowHistoryDetail) self.history_list = history_list history_list.SetColumns([ ObjectListView.ColumnDefn("Item", "left", 240, "name", fixedWidth=240), ObjectListView.ColumnDefn("Restrictions", "left", 95, "classes", fixedWidth=95), ObjectListView.ColumnDefn("Droppable", "center", 70, "droppable", fixedWidth=70), ObjectListView.ColumnDefn("Rand/Min", "left", 65, "get_target_min", fixedWidth=65), ObjectListView.ColumnDefn("Bid/Roll", "left", 65, "highest_number", fixedWidth=65), ObjectListView.ColumnDefn("Winner", "left", 108, "highest_players", fixedWidth=108), ]) history_list.SetObjects( list(config.HISTORICAL_AUCTIONS.values())) history_list.SetEmptyListMsg("No auctions completed.") history_list.SetToolTip( "Double click an auction to edit bid the history") # Buttons history_buttons_box = wx.BoxSizer(wx.VERTICAL) history_box.Add(history_buttons_box, flag=wx.EXPAND | wx.TOP | wx.LEFT, border=10) history_button_undo = wx.Button(pane_3, label="Undo") history_buttonspacer = wx.StaticLine(pane_3) history_button_gettext = wx.Button(pane_3, label="Copy Text") history_button_wiki = wx.Button(pane_3, label="Wiki?") history_button_hiderot = wx.CheckBox(pane_3, label="Hide Rots") history_buttons_box.Add(history_button_undo, flag=wx.TOP) history_buttons_box.Add(history_buttonspacer, flag=wx.TOP, border=10) history_buttons_box.Add(history_button_gettext, flag=wx.TOP, border=10) history_buttons_box.Add(history_button_wiki, flag=wx.TOP, border=10) history_buttons_box.Add(history_button_hiderot, flag=wx.TOP, border=10) history_button_undo.Bind(wx.EVT_BUTTON, self.UndoComplete) history_button_gettext.Bind(wx.EVT_BUTTON, self.CopyWinText) history_button_wiki.Bind(wx.EVT_BUTTON, self.ShowWikiHistory) history_button_hiderot.Bind(wx.EVT_CHECKBOX, self.OnHideRot) self.history_button_hiderot = history_button_hiderot history_button_hiderot.SetValue(config.HIDE_ROTS) if config.HIDE_ROTS: self.OnHideRot(None) # Finalize Tab pane_1.SetSizer(bidding_main_box1) pane_2.SetSizer(bidding_main_box2) pane_3.SetSizer(bidding_main_box3) bidding_splitter.AppendWindow(pane_1) bidding_splitter.AppendWindow(pane_2) bidding_splitter.AppendWindow(pane_3) bidding_main_box = wx.BoxSizer() bidding_main_box.Add(bidding_splitter, 1, wx.EXPAND, 0) self.SetSizer(bidding_main_box) bidding_splitter.SetMinimumPaneSize(215) bidding_splitter.SetSashPosition(0, config.ACTIVE_SASH_POS) bidding_splitter.SetSashPosition(1, config.HISTORICAL_SASH_POS) self.Bind(wx.EVT_SPLITTER_SASH_POS_CHANGED, self.OnSashChanged, source=bidding_splitter) parent.AddPage(self, 'Bidding')
def __init__(self, parent, tabs_and_title=None): Notebook.__init__(self, parent) if tabs_and_title and len(tabs_and_title): for tab, title in tabs_and_title: self.AddPage(tab(self), title)
class MainUI: """ The main portion of the User Interface. Used by the main application frame (AppFrame) to host all UML frames, the notebook and the project tree. Handles the the project files, projects, documents and their relationship to the various UI Tree elements and the notebook tabs in the UI All actions called from AppFrame are executed on the current frame """ MAX_NOTEBOOK_PAGE_NAME_LENGTH: int = 12 def __init__(self, parent, mediator): """ Args: parent: An AppFrame mediator: Our one and only mediator """ self.logger: Logger = getLogger(__name__) from org.pyut.ui.AppFrame import AppFrame # Prevent recursion import problem from org.pyut.general.Mediator import Mediator self.__parent: AppFrame = parent self._mediator: Mediator = mediator self._projects: List[PyutProject] = [] self._currentProject: PyutProject = cast(PyutProject, None) self._currentFrame: UmlDiagramsFrame = cast(UmlDiagramsFrame, None) if not self._mediator.isInScriptMode(): self.__splitter: SplitterWindow = cast(SplitterWindow, None) self.__projectTree: TreeCtrl = cast(TreeCtrl, None) self.__projectTreeRoot: TreeItemId = cast(TreeItemId, None) self.__notebook: Notebook = cast(Notebook, None) self.__projectPopupMenu: Menu = cast(Menu, None) self.__documentPopupMenu: Menu = cast(Menu, None) self._initializeUIElements() def registerUmlFrame(self, frame): """ Register the current UML Frame Args: frame: """ self._currentFrame = frame self._currentProject = self.getProjectFromFrame(frame) def showFrame(self, frame): self._frame = frame frame.Show() def getProjects(self): """ Returns: Return all projects """ return self._projects def isProjectLoaded(self, filename) -> bool: """ Args: filename: Returns: `True` if the project is already loaded """ for project in self._projects: if project.getFilename == filename: return True return False def isDefaultFilename(self, filename: str) -> bool: """ Args: filename: Returns: `True` if the filename is the default filename """ return filename == PyutConstants.DefaultFilename def openFile(self, filename, project=None) -> bool: """ Open a file Args: filename: project: Returns: `True` if operation succeeded """ # Exit if the file is already loaded if not self.isDefaultFilename(filename) and self.isProjectLoaded(filename): PyutUtils.displayError(_("The selected file is already loaded !")) return False # Create a new project ? if project is None: project = PyutProject(PyutConstants.DefaultFilename, self.__notebook, self.__projectTree, self.__projectTreeRoot) # print ">>>FileHandling-openFile-3" # Load the project and add it try: if not project.loadFromFilename(filename): PyutUtils.displayError(_("The specified file can't be loaded !")) return False self._projects.append(project) # self._ctrl.registerCurrentProject(project) self._currentProject = project except (ValueError, Exception) as e: PyutUtils.displayError(_(f"An error occurred while loading the project ! {e}")) return False try: if not self._mediator.isInScriptMode(): for document in project.getDocuments(): diagramTitle: str = document.getTitle() shortName: str = self.shortenNotebookPageFileName(diagramTitle) self.__notebook.AddPage(document.getFrame(), shortName) self.__notebookCurrentPage = self.__notebook.GetPageCount()-1 self.__notebook.SetSelection(self.__notebookCurrentPage) if len(project.getDocuments()) > 0: self._currentFrame = project.getDocuments()[0].getFrame() except (ValueError, Exception) as e: PyutUtils.displayError(_(f"An error occurred while adding the project to the notebook {e}")) return False return True def insertFile(self, filename): """ Insert a file in the current project Args: filename: filename of the project to insert """ # Get current project project = self._currentProject # Save number of initial documents nbInitialDocuments = len(project.getDocuments()) # Load data... if not project.insertProject(filename): PyutUtils.displayError(_("The specified file can't be loaded !")) return False # ... if not self._mediator.isInScriptMode(): try: for document in project.getDocuments()[nbInitialDocuments:]: self.__notebook.AddPage(document.getFrame(), document.getFullyQualifiedName()) self.__notebookCurrentPage = self.__notebook.GetPageCount()-1 self.__notebook.SetSelection(self.__notebookCurrentPage) except (ValueError, Exception) as e: PyutUtils.displayError(_(f"An error occurred while adding the project to the notebook {e}")) return False # Select first frame as current frame if len(project.getDocuments()) > nbInitialDocuments: self._frame = project.getDocuments()[nbInitialDocuments].getFrame() def saveFile(self) -> bool: """ save to the current filename Returns: `True` if the save succeeds else `False` """ currentProject = self._currentProject if currentProject is None: PyutUtils.displayError(_("No diagram to save !"), _("Error")) return False if currentProject.getFilename() is None or currentProject.getFilename() == PyutConstants.DefaultFilename: return self.saveFileAs() else: return currentProject.saveXmlPyut() def saveFileAs(self): """ Ask for a filename and save the diagram data Returns: `True` if the save succeeds else `False` """ if self._mediator.isInScriptMode(): PyutUtils.displayError(_("Save File As is not accessible in script mode !")) return # Test if no diagram exists if self._mediator.getDiagram() is None: PyutUtils.displayError(_("No diagram to save !"), _("Error")) return # Ask for filename filenameOK = False # TODO revisit this to figure out how to get rid of Pycharm warning 'dlg referenced before assignment' # Bad thing is dlg can be either a FileDialog or a MessageDialog dlg: DialogType = cast(DialogType, None) while not filenameOK: dlg = FileDialog(self.__parent, defaultDir=self.__parent.getCurrentDir(), wildcard=_("Pyut file (*.put)|*.put"), style=FD_SAVE | FD_OVERWRITE_PROMPT) # Return False if canceled if dlg.ShowModal() != ID_OK: dlg.Destroy() return False # Find if a specified filename is already opened filename = dlg.GetPath() if len([project for project in self._projects if project.getFilename() == filename]) > 0: dlg = MessageDialog(self.__parent, _("Error ! The filename '%s" + "' correspond to a project which is currently opened !" + " Please choose another filename !") % str(filename), _("Save change, filename error"), OK | ICON_ERROR) dlg.ShowModal() dlg.Destroy() return filenameOK = True project = self._currentProject project.setFilename(dlg.GetPath()) project.saveXmlPyut() # Modify notebook text for i in range(self.__notebook.GetPageCount()): frame = self.__notebook.GetPage(i) document = [document for document in project.getDocuments() if document.getFrame() is frame] if len(document) > 0: document = document[0] if frame in project.getFrames(): diagramTitle: str = document.getTitle() shortName: str = self.shortenNotebookPageFileName(diagramTitle) self.__notebook.SetPageText(i, shortName) else: self.logger.info("Not updating notebook in FileHandling") self.__parent.updateCurrentDir(dlg.GetPath()) project.setModified(False) dlg.Destroy() return True def newProject(self): """ Begin a new project """ project = PyutProject(PyutConstants.DefaultFilename, self.__notebook, self.__projectTree, self.__projectTreeRoot) self._projects.append(project) self._currentProject = project self._currentFrame = None def newDocument(self, docType: DiagramType): """ Begin a new document Args: docType: Type of document """ project = self._currentProject if project is None: self.newProject() project = self.getCurrentProject() frame = project.newDocument(docType).getFrame() self._currentFrame = frame self._currentProject = project if not self._mediator.isInScriptMode(): shortName: str = self.shortenNotebookPageFileName(project.getFilename()) self.__notebook.AddPage(frame, shortName) wxYield() self.__notebookCurrentPage = self.__notebook.GetPageCount() - 1 self.logger.info(f'Current notebook page: {self.__notebookCurrentPage}') self.__notebook.SetSelection(self.__notebookCurrentPage) def getCurrentFrame(self): """ Returns: Get the current frame """ return self._currentFrame def getCurrentProject(self) -> PyutProject: """ Get the current working project Returns: the current project or None if not found """ return self._currentProject def getProjectFromFrame(self, frame: UmlDiagramsFrame) -> PyutProject: """ Return the project that owns a given frame Args: frame: the frame to get This project Returns: PyutProject or None if not found """ for project in self._projects: if frame in project.getFrames(): return project return cast(PyutProject, None) def getCurrentDocument(self) -> PyutDocument: """ Get the current document. Returns: the current document or None if not found """ project = self.getCurrentProject() if project is None: return cast(PyutDocument, None) for document in project.getDocuments(): if document.getFrame() is self._currentFrame: return document return cast(PyutDocument, None) def onClose(self) -> bool: """ Close all files Returns: True if everything is ok """ # Display warning if we are in scripting mode if self._mediator.isInScriptMode(): print("WARNING : in script mode, the non-saved projects are closed without warning") # Close projects and ask for unsaved but modified projects if not self._mediator.isInScriptMode(): for project in self._projects: if project.getModified() is True: frames = project.getFrames() if len(frames) > 0: frame = frames[0] frame.SetFocus() wxYield() # if self._ctrl is not None: # self._ctrl.registerUMLFrame(frame) self.showFrame(frame) dlg = MessageDialog(self.__parent, _("Your diagram has not been saved! Would you like to save it ?"), _("Save changes ?"), YES_NO | ICON_QUESTION) if dlg.ShowModal() == ID_YES: # save if self.saveFile() is False: return False dlg.Destroy() # dereference all self.__parent = None self._mediator = None self.__splitter = None self.__projectTree = None self.__notebook.DeleteAllPages() self.__notebook = None self.__splitter = None self._projects = None self._currentProject = None self._currentFrame = None def setModified(self, theNewValue: bool = True): """ Set the Modified flag of the currently opened diagram Args: theNewValue: """ if self._currentProject is not None: self._currentProject.setModified(theNewValue) self._mediator.updateTitle() def closeCurrentProject(self): """ Close the current project Returns: True if everything is ok """ if self._currentProject is None and self._currentFrame is not None: self._currentProject = self.getProjectFromFrame(self._currentFrame) if self._currentProject is None: PyutUtils.displayError(_("No frame to close !"), _("Error...")) return False # Display warning if we are in scripting mode if self._mediator.isInScriptMode(): self.logger.warning("WARNING : in script mode, the non-saved projects are closed without warning") # Close the file if self._currentProject.getModified() is True and not self._mediator.isInScriptMode(): frame = self._currentProject.getFrames()[0] frame.SetFocus() self.showFrame(frame) dlg = MessageDialog(self.__parent, _("Your project has not been saved. " "Would you like to save it ?"), _("Save changes ?"), YES_NO | ICON_QUESTION) if dlg.ShowModal() == ID_YES: if self.saveFile() is False: return False # Remove the frame in the notebook if not self._mediator.isInScriptMode(): # Python 3 update pages = list(range(self.__notebook.GetPageCount())) pages.reverse() for i in pages: pageFrame = self.__notebook.GetPage(i) if pageFrame in self._currentProject.getFrames(): self.__notebook.DeletePage(i) self._currentProject.removeFromTree() self._projects.remove(self._currentProject) self._currentProject = None self._currentFrame = None return True def removeAllReferencesToUmlFrame(self, umlFrame): """ Remove all my references to a given uml frame Args: umlFrame: """ # Current frame ? if self._currentFrame is umlFrame: self._currentFrame = None # Exit if we are in scripting mode if self._mediator.isInScriptMode(): return for i in range(self.__notebook.GetPageCount()): pageFrame = self.__notebook.GetPage(i) if pageFrame is umlFrame: self.__notebook.DeletePage(i) break def getProjectFromOglObjects(self, oglObjects) -> PyutProject: """ Get a project that owns oglObjects Args: oglObjects: Objects to find their parents Returns: PyutProject if found, None else """ for project in self._projects: for frame in project.getFrames(): diagram = frame.getDiagram() shapes = diagram.GetShapes() for obj in oglObjects: if obj in shapes: self.logger.info(f'obj: {obj} is part of project: {project}') return project self.logger.warning(f'The oglObjects: {oglObjects} appear to not belong to any project') return cast(PyutProject, None) def _initializeUIElements(self): """ Instantiate all the UI elements """ self.__splitter = SplitterWindow(self.__parent, ID_ANY) self.__projectTree = TreeCtrl(self.__splitter, ID_ANY, style=TR_HIDE_ROOT + TR_HAS_BUTTONS) self.__projectTreeRoot = self.__projectTree.AddRoot(_("Root")) # self.__projectTree.SetPyData(self.__projectTreeRoot, None) # Expand root, since wx.TR_HIDE_ROOT is not supported under windows # Not supported for hidden tree since wx.Python 2.3.3.1 ? # self.__projectTree.Expand(self.__projectTreeRoot) # diagram container self.__notebook = Notebook(self.__splitter, ID_ANY, style=CLIP_CHILDREN) # Set splitter self.__splitter.SetMinimumPaneSize(20) self.__splitter.SplitVertically(self.__projectTree, self.__notebook, 160) self.__notebookCurrentPage = -1 # Callbacks self.__parent.Bind(EVT_NOTEBOOK_PAGE_CHANGED, self.__onNotebookPageChanged) self.__parent.Bind(EVT_TREE_SEL_CHANGED, self.__onProjectTreeSelChanged) self.__projectTree.Bind(EVT_TREE_ITEM_RIGHT_CLICK, self.__onProjectTreeRightClick) # noinspection PyUnusedLocal def __onNotebookPageChanged(self, event): """ Callback for notebook page changed Args: event: """ self.__notebookCurrentPage = self.__notebook.GetSelection() if self._mediator is not None: # hasii maybe I got this right from the old pre PEP-8 code # self._ctrl.registerUMLFrame(self._getCurrentFrame()) self._currentFrame = self._getCurrentFrameFromNotebook() self.__parent.notifyTitleChanged() # self.__projectTree.SelectItem(getID(self.getCurrentFrame())) # TODO : how can I do getID ??? # Register the current project self._currentProject = self.getProjectFromFrame(self._currentFrame) def __onProjectTreeSelChanged(self, event: TreeEvent): """ Callback for notebook page changed Args: event: """ itm: TreeItemId = event.GetItem() pyutData: TreeDataType = self.__projectTree.GetItemData(itm) self.logger.debug(f'Clicked on: `{pyutData}`') # Use our own base type if isinstance(pyutData, UmlDiagramsFrame): frame: UmlDiagramsFrame = pyutData self._currentFrame = frame self._currentProject = self.getProjectFromFrame(frame) # Select the frame in the notebook for i in range(self.__notebook.GetPageCount()): pageFrame = self.__notebook.GetPage(i) if pageFrame is frame: self.__notebook.SetSelection(i) return elif isinstance(pyutData, PyutProject): self._currentProject = pyutData def _getCurrentFrameFromNotebook(self): """ Get the current frame in the notebook Returns: """ # Return None if we are in scripting mode if self._mediator.isInScriptMode(): return None noPage = self.__notebookCurrentPage if noPage == -1: return None frame = self.__notebook.GetPage(noPage) return frame def __onProjectTreeRightClick(self, treeEvent: TreeEvent): itemId: TreeItemId = treeEvent.GetItem() data = self.__projectTree.GetItemData(item=itemId) self.logger.info(f'Item Data: `{data}`') if isinstance(data, PyutProject): self.__popupProjectMenu() elif isinstance(data, UmlDiagramsFrame): self.__popupProjectDocumentMenu() def __popupProjectMenu(self): self._mediator.resetStatusText() if self.__projectPopupMenu is None: self.logger.info(f'Create the project popup menu') [closeProjectMenuID] = PyutUtils.assignID(1) popupMenu: Menu = Menu('Actions') popupMenu.AppendSeparator() popupMenu.Append(closeProjectMenuID, 'Close Project', 'Remove project from tree', ITEM_NORMAL) popupMenu.Bind(EVT_MENU, self.__onCloseProject, id=closeProjectMenuID) self.__projectPopupMenu = popupMenu self.logger.info(f'currentProject: `{self._currentProject}`') self.__parent.PopupMenu(self.__projectPopupMenu) def __popupProjectDocumentMenu(self): if self.__documentPopupMenu is None: self.logger.info(f'Create the document popup menu') [editDocumentNameMenuID, removeDocumentMenuID] = PyutUtils.assignID(2) popupMenu: Menu = Menu('Actions') popupMenu.AppendSeparator() popupMenu.Append(editDocumentNameMenuID, 'Edit Document Name', 'Change document name', ITEM_NORMAL) popupMenu.Append(removeDocumentMenuID, 'Remove Document', 'Delete it', ITEM_NORMAL) popupMenu.Bind(EVT_MENU, self.__onEditDocumentName, id=editDocumentNameMenuID) popupMenu.Bind(EVT_MENU, self.__onRemoveDocument, id=removeDocumentMenuID) self.__documentPopupMenu = popupMenu self.logger.info(f'Current Document: `{self.getCurrentDocument()}`') self.__parent.PopupMenu(self.__documentPopupMenu) # noinspection PyUnusedLocal def __onCloseProject(self, event: CommandEvent): self.closeCurrentProject() # noinspection PyUnusedLocal def __onEditDocumentName(self, event: CommandEvent): self.logger.info(f'self.__notebookCurrentPage: {self.__notebookCurrentPage} nb Selection: {self.__notebook.GetSelection()}') if self.__notebookCurrentPage == -1: self.__notebookCurrentPage = self.__notebook.GetSelection() # must be default empty project currentDocument: PyutDocument = self.getCurrentDocument() dlgEditDocument: DlgEditDocument = DlgEditDocument(parent=self.getCurrentFrame(), dialogIdentifier=ID_ANY, document=currentDocument) dlgEditDocument.Destroy() self.__notebook.SetPageText(page=self.__notebookCurrentPage, text=currentDocument.title) currentDocument.updateTreeText() # noinspection PyUnusedLocal def __onRemoveDocument(self, event: CommandEvent): """ Invoked from the popup menu in the tree Args: event: """ project: PyutProject = self.getCurrentProject() currentDocument: PyutDocument = self.getCurrentDocument() project.removeDocument(currentDocument) def shortenNotebookPageFileName(self, filename: str) -> str: """ Return a shorter filename to display; For file names longer than `MAX_NOTEBOOK_PAGE_NAME_LENGTH` this method takes the first four characters and the last eight as the shortened file name Args: filename: The file name to display Returns: A better file name """ justFileName: str = osPath.split(filename)[1] if len(justFileName) > MainUI.MAX_NOTEBOOK_PAGE_NAME_LENGTH: firstFour: str = justFileName[:4] lastEight: str = justFileName[-8:] return f'{firstFour}{lastEight}' else: return justFileName
def __init__(self, parent: wx.Notebook, *args, **kwargs): super().__init__(parent, *args, **kwargs) parent.GetParent().Connect(-1, -1, models.EVT_WHO, self.OnWho) parent.GetParent().Connect(-1, -1, models.EVT_CLEAR_WHO, self.OnClearWho) parent.GetParent().Connect(-1, -1, models.EVT_WHO_END, self.ResetPopPreview) parent.GetParent().Connect(-1, -1, models.EVT_APP_CLEAR, self.OnClearApp) self.player_affiliations = config.WX_LAST_WHO_SNAPSHOT or list() config.WX_LAST_WHO_SNAPSHOT = self.player_affiliations self.pop_adjustments = dict() self.pop_preview = list() ########################## # Population Frame (Tab 3) ########################## label_font = wx.Font(11, wx.DEFAULT, wx.DEFAULT, wx.BOLD) population_main_box = wx.BoxSizer(wx.VERTICAL) population_label = wx.StaticText(self, label="Population Count", style=wx.ALIGN_LEFT) population_label.SetFont(label_font) population_main_box.Add(population_label, flag=wx.LEFT | wx.TOP, border=10) population_box = wx.BoxSizer(wx.HORIZONTAL) population_main_box.Add(population_box, flag=wx.EXPAND | wx.LEFT | wx.RIGHT | wx.BOTTOM, border=10) # List population_list = ObjectListView.GroupListView(self, wx.ID_ANY, style=wx.LC_REPORT, size=wx.Size(625, 1200), useExpansionColumn=True) population_box.Add(population_list, flag=wx.EXPAND | wx.ALL) self.population_list = population_list def popGroupKey(player): return config.ALLIANCE_MAP.get(player.guild, player.guild or '') population_list.SetColumns([ ObjectListView.ColumnDefn("Name", "left", 180, "name", groupKeyGetter=popGroupKey, fixedWidth=180), ObjectListView.ColumnDefn("Class", "left", 100, "pclass", groupKeyGetter=popGroupKey, fixedWidth=100), ObjectListView.ColumnDefn("Level", "left", 40, "level", groupKeyGetter=popGroupKey, fixedWidth=40), ObjectListView.ColumnDefn("Guild", "left", 148, "guild", groupKeyGetter=popGroupKey, fixedWidth=148), ]) population_list.SetObjects(self.player_affiliations) population_list.SetEmptyListMsg( "No player affiliation data loaded.\nPlease type `/who` ingame.") # Buttons / Adjustments population_buttons_box = wx.BoxSizer(wx.VERTICAL) population_box.Add(population_buttons_box, flag=wx.EXPAND | wx.TOP | wx.LEFT, border=10) # Autogenerate adjustments for each Alliance adj_alliance_font = wx.Font(11, wx.DEFAULT, wx.DEFAULT, wx.BOLD) adj_alliance_header = wx.StaticText(self, label="Adjustments:") adj_alliance_header.SetFont(adj_alliance_font) population_buttons_box.Add(adj_alliance_header, flag=wx.BOTTOM, border=10) for alliance in config.ALLIANCES: adj_alliance_box = wx.GridBagSizer(1, 2) adj_alliance_label = wx.StaticText(self, label=alliance, size=(100, 20), style=wx.ALIGN_RIGHT) adj_alliance_label.SetFont(adj_alliance_font) adj_alliance_spinner = wx.SpinCtrl(self, value='0') adj_alliance_spinner.SetRange(-1000, 1000) # Why limit things? :D adj_alliance_spinner.Bind(wx.EVT_SPINCTRL, self.ResetPopPreview) self.pop_adjustments[alliance] = adj_alliance_spinner adj_alliance_box.Add(adj_alliance_label, pos=(0, 0), flag=wx.RIGHT | wx.TOP, border=3) adj_alliance_box.Add(adj_alliance_spinner, pos=(0, 1), flag=wx.LEFT, border=7) population_buttons_box.Add(adj_alliance_box, flag=wx.BOTTOM | wx.EXPAND, border=10) # Small Pop-List Display population_preview_list = ObjectListView.ObjectListView( self, wx.ID_ANY, style=wx.LC_REPORT | wx.LC_SINGLE_SEL, size=wx.Size(120, 140)) population_buttons_box.Add(population_preview_list, flag=wx.EXPAND | wx.ALL) self.population_preview_list = population_preview_list population_preview_list.SetColumns([ ObjectListView.ColumnDefn("Alliance", "left", 125, "alliance", fixedWidth=125), ObjectListView.ColumnDefn("Pop", "left", 40, "population", fixedWidth=40), ]) population_preview_list.SetObjects(self.pop_preview) population_preview_list.SetEmptyListMsg("No pop data found.") population_button_half = wx.Button(self, label="Halve") population_button_reset = wx.Button(self, label="Reset") population_box_half_reset = wx.BoxSizer(wx.HORIZONTAL) population_box_half_reset.Add(population_button_half, flag=wx.LEFT, border=5) population_box_half_reset.Add(population_button_reset, flag=wx.LEFT, border=10) population_button_poptext = wx.Button(self, label="Copy Populations", size=(160, 23)) population_button_randtext = wx.Button(self, label="Copy Roll Text", size=(160, 23)) population_buttons_box.Add(population_box_half_reset, flag=wx.TOP | wx.BOTTOM, border=10) population_buttons_box.Add(population_button_poptext, flag=wx.LEFT | wx.BOTTOM, border=5) population_buttons_box.Add(population_button_randtext, flag=wx.LEFT | wx.TOP, border=5) population_button_half.Bind(wx.EVT_BUTTON, self.HalvePopPreview) population_button_reset.Bind(wx.EVT_BUTTON, self.ResetPopPreview) population_button_poptext.Bind(wx.EVT_BUTTON, self.CopyPopText) population_button_randtext.Bind(wx.EVT_BUTTON, self.CopyPopRandom) self.ResetPopPreview(None) # Finalize Tab self.SetSizer(population_main_box) parent.AddPage(self, 'Population Rolls')
def __init__(self, master: wx.Notebook): super().__init__( parent=master, size=master.GetSize() ) self.browserObj = browser.Browser(self)
class ConfigFrame(Frame): # pylint: disable=too-many-public-methods """ConfigFrame is used as the primary app context""" BOUND_ACTIONS = 12 PROMPTS = { 'dirty_values': 'You have unsaved changes. ', 'probably_modified': 'File has been modified. ' } config = None dirty_values = [] groups = None menu_bar = None notebook = None def __init__(self, parent, title=""): Frame.__init__(self, parent=parent, id=ID_ANY, size=(800, 640), title=title) self.construct_config() self.construct_gui() self.bind_events() def construct_config(self, config_path=None): """Constucts the Rofi config object and parses its groups""" self.config = Rofi() self.config.build(config_path) self.groups = {} for _, entry in self.config.config.items(): if entry.group in self.groups: self.groups[entry.group].append(entry) else: self.groups[entry.group] = [entry] def construct_tabs(self): """Constructs all available tabs""" for key, config_list in self.groups.items(): page = ConfigPage(self.notebook, config_list) self.notebook.AddPage(page, key) self.clean_edit_state() def construct_notebook(self): """Constructs the main Notebook panel""" panel = Panel(self) self.notebook = Notebook(panel, style=NB_LEFT) self.construct_tabs() sizer = BoxSizer(HORIZONTAL) sizer.Add(self.notebook, 1, EXPAND) panel.SetSizer(sizer) def construct_gui(self): """Constructs ConfigFrame's GUI""" self.menu_bar = ConfigFrameMenuBar() self.SetMenuBar(self.menu_bar) self.status_bar = ConfigFrameStatusBar(self) self.SetStatusBar(self.status_bar) self.construct_notebook() self.toggle_restoration() def bind_events(self): """Binds events on ConfigFrame""" self.Bind(EVT_MENU, self.open, self.menu_bar.open_menu_item) self.Bind(EVT_MENU, self.force_refresh_config, self.menu_bar.refresh_menu_item) self.Bind(EVT_MENU, self.restore, self.menu_bar.restore_menu_item) self.Bind(EVT_MENU, self.save_as, self.menu_bar.save_as_menu_item) self.Bind(EVT_MENU, self.save, self.menu_bar.save_menu_item) self.Bind(EVT_MENU, self.menu_bar.exit, self.menu_bar.exit_menu_item) self.Bind(EVT_MENU, self.modi_launcher, self.menu_bar.launch_menu_item) self.Bind(EVT_MENU, self.menu_bar.toggle_display, self.menu_bar.help_values_menu_item) self.Bind(EVT_MENU, self.menu_bar.toggle_display, self.menu_bar.man_values_menu_item) self.Bind(EVT_CHECKBOX, self.dirty_edit_state) self.Bind(EVT_SPINCTRL, self.dirty_edit_state) self.Bind(EVT_TEXT, self.dirty_edit_state) def modi_launcher(self, event=None): # pylint: disable=unused-argument """Launches a modi selection dialog""" ModiLauncher(self.config.available_modi) def update_config_entry(self, key_name, entry): """Updates the value for a single entry""" widget = FindWindowByName(key_name) if hasattr(widget, 'GetValue'): value = widget.GetValue() elif hasattr(widget, 'GetLabel'): value = widget.GetLabel() else: value = entry.current self.config.config[key_name].current = value def update_config(self): """Updates the entire config object""" for key_name, entry in self.config.config.items(): self.update_config_entry(key_name, entry) def save(self, event=None): # pylint: disable=unused-argument """Saves the config file""" self.update_config() self.config.save(backup=self.menu_bar.backup_on_menu_item.IsChecked()) send('status_update', message='Saved!') self.clean_edit_state() self.toggle_refresh() self.toggle_restoration() def toggle_restoration(self, event=None): # pylint: disable=unused-argument """Enables/disables the restore menu item""" self.menu_bar.restore_menu_item.Enable(self.config.can_restore()) def refresh_config(self, event=None, config_path=None): # pylint: disable=unused-argument """Refreshes the config object and controls""" current_page = self.notebook.GetSelection() self.construct_config(config_path) while self.notebook.GetPageCount() > 0: self.notebook.DeletePage(0) self.construct_tabs() if current_page >= 0 and current_page < self.notebook.GetPageCount(): self.notebook.SetSelection(current_page) self.toggle_refresh() self.toggle_restoration() def restore(self, event=None): # pylint: disable=unused-argument """Restores a previously backed up config""" if self.config.can_restore(): self.config.backup(restore=True) self.refresh_config() def clean_edit_state(self): """Resets the dirty value list""" self.dirty_values = [] def dirty_edit_state(self, event=None): """Updates the dirty value list""" if event is None: return control_value = event.EventObject.GetValue() control_name = event.EventObject.GetName() config_value = self.config.config[control_name].current is_dirty = control_value != config_value if is_dirty: if not control_name in self.dirty_values: self.dirty_values.append(control_name) else: self.dirty_values = [ key for key in self.dirty_values if control_name != key ] self.toggle_refresh() def toggle_refresh(self): """Toggle refresh availability""" self.menu_bar.refresh_menu_item.Enable( len(self.dirty_values) > 0 or self.config.probably_modified()) @staticmethod def ignore_dirty_state(prompt=None): """Checks if dirty state can be abandoned""" with MessageDialog(None, "%sContinue?" % prompt, 'Confirm overwrite', YES_NO | ICON_QUESTION) as dialog: if ID_YES == dialog.ShowModal(): return True return False def force_refresh_config(self, event=None): # pylint: disable=unused-argument """Forces a config refresh""" if self.dirty_values: if self.ignore_dirty_state(self.PROMPTS['dirty_values']): self.refresh_config() elif self.config.probably_modified(): if self.ignore_dirty_state(self.PROMPTS['probably_modified']): self.refresh_config() def file_dialog(self, style=None): """Opens a dialog to find a file""" with FileDialog( None, 'Choose a file', dirname(self.config.active_file), wildcard='Rasi files (*.rasi)|*.rasi|All Files (*.*)|*.*', style=style) as dialog: if ID_OK == dialog.ShowModal(): return dialog.GetPath() return None def pick_save_file(self): """Launches a dialog to pick the save location""" return self.file_dialog(FD_SAVE | FD_OVERWRITE_PROMPT) def save_as(self, event=None): # pylint: disable=unused-argument """Saves the config as an arbitrary file""" new_location = self.pick_save_file() if new_location: self.config.active_file = new_location self.save() def pick_open_file(self): """Launches a dialog to pick the open location""" return self.file_dialog(FD_OPEN | FD_FILE_MUST_EXIST) def open(self, event=None): # pylint: disable=unused-argument """Opens the chosen config for editing""" new_location = self.pick_open_file() if new_location: self.refresh_config(config_path=new_location)
def __init__(self, parent: wx.Notebook, *args, **kwargs): super().__init__(parent, *args, **kwargs) parent.GetParent().Connect(-1, -1, models.EVT_WHO_HISTORY, self.OnWhoHistory) parent.GetParent().Connect(-1, -1, models.EVT_CREDITT, self.OnCreditt) parent.GetParent().Connect(-1, -1, models.EVT_GRATSS, self.OnGratss) parent.GetParent().Connect(-1, -1, models.EVT_APP_CLEAR, self.OnClearApp) ############################## # Attendance Log Frame (Tab 2) ############################## attendance_main_box = wx.BoxSizer(wx.VERTICAL) attendance_splitter = wx.lib.splitter.MultiSplitterWindow( self, wx.ID_ANY, style=wx.SP_3D | wx.SP_BORDER) attendance_splitter.SetOrientation(wx.VERTICAL) pane_1 = wx.Panel(attendance_splitter, wx.ID_ANY) pane_2 = wx.Panel(attendance_splitter, wx.ID_ANY) pane_3 = wx.Panel(attendance_splitter, wx.ID_ANY) # Attendance / Raidtick List attendance_box = wx.BoxSizer(wx.HORIZONTAL) attendance_list = ObjectListView.ObjectListView( pane_1, wx.ID_ANY, style=wx.LC_REPORT, size=wx.Size(680, 600)) attendance_box.Add(attendance_list, flag=wx.EXPAND | wx.ALL) attendance_list.Bind(wx.EVT_LEFT_DCLICK, self.ShowAttendanceDetail) attendance_list.Bind(wx.EVT_RIGHT_DCLICK, self.OnMarkRaidtick) self.attendance_list = attendance_list attendance_list.SetColumns([ ObjectListView.ColumnDefn( "Time", "left", 140, "time", fixedWidth=140), ObjectListView.ColumnDefn( "Name", "left", 140, "tick_name", fixedWidth=140), ObjectListView.ColumnDefn( "RT", "left", 25, "raidtick_display", fixedWidth=25), ObjectListView.ColumnDefn( "Populations", "left", 357, "populations", fixedWidth=357), ]) attendance_list.SetObjects(config.ATTENDANCE_LOGS) attendance_list.SetEmptyListMsg( "No who log history.\nPlease type `/who` ingame.") attendance_list.SetToolTip( "Double left-click an attendance record to edit it in a detailed " "view.\n" "Double right-click an attendance record to toggle its RaidTick " "status.") # Attendance / Raidtick Buttons attendance_buttons_box = wx.BoxSizer(wx.VERTICAL) attendance_box.Add(attendance_buttons_box, flag=wx.EXPAND | wx.TOP | wx.LEFT, border=10) attendance_button_raidtick = wx.CheckBox( pane_1, label="Show RaidTicks Only") attendance_buttons_box.Add(attendance_button_raidtick, flag=wx.ALL, border=6) attendance_button_raidtick.Bind(wx.EVT_CHECKBOX, self.OnRaidtickOnly) self.attendance_button_raidtick = attendance_button_raidtick attendance_button_raidtick.SetValue(config.SHOW_RAIDTICK_ONLY) if config.SHOW_RAIDTICK_ONLY: self.OnRaidtickOnly(None) attendance_toggle_raidtick = wx.Button( pane_1, label="Toggle RaidTick", size=(140, 22)) attendance_toggle_raidtick.Bind(wx.EVT_BUTTON, self.OnMarkRaidtick) attendance_buttons_box.Add( attendance_toggle_raidtick, border=5, flag=wx.ALL) attendance_use_raidgroups = wx.Button( pane_1, label="Calculate Raid Groups", size=(140, 22)) attendance_use_raidgroups.Bind(wx.EVT_BUTTON, self.OnCalcRaidGroups) attendance_buttons_box.Add( attendance_use_raidgroups, border=5, flag=wx.ALL) # Creditt Log creditt_box = wx.BoxSizer(wx.HORIZONTAL) creditt_list = ObjectListView.ObjectListView( pane_2, wx.ID_ANY, style=wx.LC_REPORT, size=wx.Size(650, 200)) creditt_box.Add(creditt_list, flag=wx.EXPAND | wx.ALL) # creditt_list.Bind(wx.EVT_LEFT_DCLICK, self.OnEditCreditt) self.creditt_list = creditt_list creditt_list.SetColumns([ ObjectListView.ColumnDefn( "Time", "left", 160, "time", fixedWidth=160), ObjectListView.ColumnDefn( "From", "left", 120, "user", fixedWidth=120), ObjectListView.ColumnDefn( "Message", "left", 350, "message", fixedWidth=350), ]) creditt_list.SetObjects(config.CREDITT_LOG) creditt_list.SetEmptyListMsg("No creditt messages received.") # Creditt Buttons creditt_buttons_box = wx.BoxSizer(wx.VERTICAL) creditt_box.Add(creditt_buttons_box, flag=wx.EXPAND | wx.TOP | wx.LEFT, border=10) creditt_button_ignore = wx.Button( pane_2, label="Ignore Creditt", size=(140, 22)) creditt_buttons_box.Add(creditt_button_ignore) creditt_button_ignore.Bind(wx.EVT_BUTTON, self.OnIgnoreCreditt) # Gratss Log gratss_box = wx.BoxSizer(wx.HORIZONTAL) gratss_list = ObjectListView.ObjectListView( pane_3, wx.ID_ANY, style=wx.LC_REPORT, size=wx.Size(650, 200)) gratss_box.Add(gratss_list, flag=wx.EXPAND | wx.ALL) # gratss_list.Bind(wx.EVT_LEFT_DCLICK, self.OnEditGratss) self.gratss_list = gratss_list gratss_list.SetColumns([ ObjectListView.ColumnDefn( "Time", "left", 160, "time", fixedWidth=160), ObjectListView.ColumnDefn( "From", "left", 120, "user", fixedWidth=120), ObjectListView.ColumnDefn( "Message", "left", 350, "message", fixedWidth=350), ]) gratss_list.SetObjects(config.GRATSS_LOG) gratss_list.SetEmptyListMsg("No gratss messages received.") # Gratss Buttons gratss_buttons_box = wx.BoxSizer(wx.VERTICAL) gratss_box.Add(gratss_buttons_box, flag=wx.EXPAND | wx.TOP | wx.LEFT, border=10) gratss_button_ignore = wx.Button( pane_3, label="Ignore Gratss", size=(140, 22)) gratss_buttons_box.Add(gratss_button_ignore) gratss_button_ignore.Bind(wx.EVT_BUTTON, self.OnIgnoreGratss) # Set up Splitter pane_1.SetSizer(attendance_box) pane_2.SetSizer(creditt_box) pane_3.SetSizer(gratss_box) attendance_splitter.AppendWindow(pane_1) attendance_splitter.AppendWindow(pane_2) attendance_splitter.AppendWindow(pane_3) attendance_main_box.Add(attendance_splitter, 1, wx.EXPAND, 0) # Finalize Tab self.SetSizer(attendance_main_box) attendance_main_box.Fit(self) attendance_splitter.SetMinimumPaneSize(80) attendance_splitter.SetSashPosition(0, config.CREDITT_SASH_POS) attendance_splitter.SetSashPosition(1, config.GRATSS_SASH_POS) self.Bind(wx.EVT_SPLITTER_SASH_POS_CHANGED, self.OnSashChanged, source=attendance_splitter) parent.AddPage(self, 'Attendance Logs')
class SettingsFrame(Frame): def __init__(self, parent, title, server): Frame.__init__(self, parent, title=title, size=(500, 400)) global SETTINGS_FRAME SETTINGS_FRAME = self self.server = server self.setup_xmlrpc_server() self.completed = False self.notebook = Notebook(self, style=NB_MULTILINE) file_menu = Menu() self.next_page = file_menu.Append(ID_ANY, '&Next page\tRAWCTRL+TAB', 'Next page') self.prev_page = file_menu.Append(ID_ANY, '&Prev page\tRAWCTRL+SHIFT+TAB', 'Prev page') self.Bind(EVT_MENU, self.OnTab, self.next_page) self.Bind(EVT_MENU, self.OnTab, self.prev_page) exit_item = file_menu.Append(ID_EXIT, '&Exit...', 'Exit Settings Window') self.Bind(EVT_MENU, self.prepare_for_exit, exit_item) menu_bar = MenuBar() menu_bar.Append(file_menu, '&File') self.SetMenuBar(menu_bar) self.fields = [] for top in sorted(settings.SETTINGS.keys()): # pylint: disable=no-member self.make_page(top) self.CenterOnScreen() self.Show() self.Bind(EVT_ON_KILL, self.OnKill) self.Bind(EVT_ON_COMPLETE, self.OnComplete) self.Bind(EVT_CLOSE, self.xmlrpc_kill) self.expiration = threading.Timer(300, self.xmlrpc_kill) self.expiration.start() def OnTab(self, event): the_id = event.GetId() curr = self.notebook.GetSelection() next = curr + 1 if the_id == self.next_page.GetId() else curr - 1 page_count = self.notebook.GetPageCount() next = 0 if next == page_count else page_count - 1 if next < 0 else next self.notebook.ChangeSelection(next) def OnKill(self, event): self.expiration.cancel() self.server.shutdown() self.Destroy() def OnComplete(self, event): self.completed = True self.Hide() def prepare_for_exit(self, e): self.Hide() self.completed = True threading.Timer(10, self.xmlrpc_kill).start() def tree_to_dictionary(self, t=None): d = {} children = self.fields if t is None else t.children for field in children: value = None if isinstance(field.widget, TextCtrl): value = field.widget.GetValue() if field.text_type == STRING_LIST_SETTING: d[field.original] = [ x for x in value.replace(", ", ",").split(",") if x ] # don't count empty strings elif field.text_type == NUMBER_LIST_SETTING: temp_list = (float(x) for x in value.replace(", ", ",").split(",") if x) # don't count empty strings d[field.original] = [ int(x) if x.is_integer() else x for x in temp_list ] elif field.text_type == NUMBER_SETTING: value = float(value) if value.is_integer(): value = int(value) d[field.original] = float(value) else: d[field.original] = value.replace("\\", "/") elif isinstance(field.widget, (Panel, ScrolledPanel)): d[field.original] = self.tree_to_dictionary(field) elif isinstance(field.widget, CheckBox): d[field.original] = field.widget.GetValue() return d def setup_xmlrpc_server(self): self.server.register_function(self.xmlrpc_get_message, "get_message") self.server.register_function(self.xmlrpc_complete, "complete") self.server.register_function(self.xmlrpc_kill, "kill") server_thread = threading.Thread(target=self.server.serve_forever) server_thread.daemon = True server_thread.start() def xmlrpc_kill(self, e=None): wx.PostEvent(SETTINGS_FRAME, OnKillEvent()) def xmlrpc_get_message(self): if self.completed: threading.Timer(1, self.xmlrpc_kill).start() return self.tree_to_dictionary() else: return None def xmlrpc_complete(self): wx.PostEvent(SETTINGS_FRAME, OnCompleteEvent()) def make_page(self, title): page = ScrolledPanel(parent=self.notebook, id=-1) vbox = BoxSizer(VERTICAL) field = Field(page, title) self.get_fields(page, vbox, field) self.fields.append(field) page.SetupScrolling() page.SetSizer(vbox) self.notebook.AddPage(page, title) def get_fields(self, page, vbox, field): for label in sorted(settings.SETTINGS[field.original].keys()): hbox = BoxSizer(HORIZONTAL) value = settings.SETTINGS[field.original][label] lbl = StaticText(page, label=label) hbox.Add(lbl, flag=RIGHT, border=8) subfield = Field(None, label) item = self.field_from_value(page, value, subfield) field.add_child(subfield) if item is not None: hbox.Add(item, proportion=1) vbox.Add(hbox, flag=EXPAND | LEFT | RIGHT | TOP, border=5) vbox.Add((-1, 5)) def field_from_value(self, window, value, field): item = None if isinstance(value, six.string_types): item = TextCtrl(window, value=value) field.text_type = STRING_SETTING elif isinstance(value, list): if isinstance(value[0], six.string_types): item = TextCtrl(window, value=", ".join(value)) field.text_type = STRING_LIST_SETTING elif isinstance(value[0], numbers.Real): item = TextCtrl(window, value=", ".join((str(x) for x in value))) field.text_type = NUMBER_LIST_SETTING elif isinstance(value, bool): item = CheckBox(window, -1, '', (120, 75)) item.SetValue(value) elif isinstance(value, numbers.Real): item = TextCtrl(window, value=str(value)) field.text_type = NUMBER_SETTING elif isinstance(value, dict): subpage = Panel(window) vbox = BoxSizer(VERTICAL) for lbl in sorted(value.keys()): hbox = BoxSizer(HORIZONTAL) value2 = value[lbl] label = StaticText(subpage, label=lbl) hbox.Add(label, flag=RIGHT, border=8) subfield = Field(None, lbl) item = self.field_from_value(subpage, value2, subfield) field.add_child(subfield) if item is not None: hbox.Add(item, proportion=1) vbox.Add(hbox, flag=EXPAND | LEFT | RIGHT | TOP, border=5) vbox.Add((-1, 5)) subpage.SetSizer(vbox) subpage.Show() item = subpage else: # This is left for bug reporting purposes. printer.out(("{} from the field {} was not assigned to " + "{} because type {} wasn't properly handled.").format( value, field, window, type(value))) field.widget = item return item