""" Widgets for Retromancer GUI: Quest mode! """ import wx import traceback import wx.lib.mixins.listctrl as listmix class QuestListCtrl(wx.ListCtrl): """ A ListCtrl, with some column sizing behavior. """ def __init__(self, parent, ID, pos = wx.DefaultPosition, size = wx.DefaultSize, style = 0): wx.ListCtrl.__init__(self, parent, ID, pos, size, style) #self.ResizeColumnMinWidth = None #listmix.ListCtrlAutoWidthMixin.__init__(self) #self.Bind(wx.EVT_SIZE, self.HandleResize) #self.Bind(wx.EVT_LIST_COL_END_DRAG, self.HandleResize, self) def HandleResize(self, Event): if 'gtk2' in wx.PlatformInfo: self.DoResize() else: self.DoResize() #wx.CallAfter(self.DoResize) #Event.Skip() def DoResize(self): """ Special resizing method. """ if not self: # avoid a PyDeadObject error return if self.GetSize().height < 32: return # avoid an endless update bug when the height is small. ColumnCount = self.GetColumnCount() if ColumnCount == 0: return # Nothing to resize. ResizeColumnNumber = ColumnCount ResizeColumnIndex = ResizeColumnNumber - 1 if self.ResizeColumnMinWidth == None: self.ResizeColumnMinWidth = self.GetColumnWidth(ResizeColumnIndex) / 2 # We're showing the vertical scrollbar -> allow for scrollbar width # NOTE: on GTK, the scrollbar is included in the client size, but on # Windows it is not included ListWidth = self.GetClientSize().width if wx.Platform != '__WXMSW__': if self.GetItemCount() > self.GetCountPerPage(): ScrollWidth = wx.SystemSettings_GetMetric(wx.SYS_VSCROLL_X) ListWidth = ListWidth - ScrollWidth ListWidth -= 10 #%%% HACK TotalColumnWidth = 0 # Width of all columns except last one. for ColumnIndex in range(ColumnCount): if ColumnIndex != ResizeColumnIndex: TotalColumnWidth += self.GetColumnWidth(ColumnIndex) ResizeColWidth = self.GetColumnWidth(ResizeColumnIndex) if ResizeColWidth + self.ResizeColumnMinWidth > ListWidth: # We haven't got the width to show the last column at its minimum # width -> set it to its minimum width and allow the horizontal # scrollbar to show. self.SetColumnWidth(ResizeColumnIndex, self.ResizeColumnMinWidth) return # Resize the last column to take up the remaining available space. self.SetColumnWidth(ResizeColumnIndex, ListWidth - TotalColumnWidth) Log("Size column %s to %s-%s=%s"%(ResizeColumnIndex, ListWidth, TotalColumnWidth, ListWidth - TotalColumnWidth)) class QuestListPanel(wx.SashLayoutWindow, listmix.ColumnSorterMixin): """ Upper pane of the QuestPanel; container for QuestList. """ def __init__(self, *args, **kw): wx.SashLayoutWindow.__init__(self, *args, **kw) self.ImageList = wx.ImageList(16, 16) self.ListSortDownImage = self.ImageList.Add(UIImages.GetSmallDnArrowBitmap()) self.ListSortUpImage = self.ImageList.Add(UIImages.GetSmallUpArrowBitmap()) def GetListCtrl(self): "Used by the ColumnSorterMixin" return self.QuestList def PrepareColumnSorting(self): listmix.ColumnSorterMixin.__init__(self, 4) class QuestPanel(wx.Panel): """ Panel with two sub-panes: Left pane for quest list, right pane for instructions! """ def __init__(self, Parent, ID): wx.Panel.__init__(self, Parent, ID) self.SelectedQuest = None self.SelectedQuestIndex = None self.Bind(wx.EVT_SIZE, self.OnSize) def OnSize(self, Event): wx.LayoutAlgorithm().LayoutWindow(self) self.Refresh() def OnSashDrag(self, Event): if Event.GetDragStatus() == wx.SASH_STATUS_OUT_OF_RANGE: Log("drag is out of range") return EventObject = Event.GetEventObject() if EventObject is self.PaneA: self.PaneA.SetDefaultSize((Event.GetDragRect().width, 1000)) Log("PaneA width-> %s"%Event.GetDragRect().height) elif EventObject is self.PaneB: self.PaneB.SetDefaultSize((Event.GetDragRect().width, 1000)) Log("PaneB default height -> %s"%Event.GetDragRect().height) else: Log("wtf?") ## if EventObject is self.PaneA: ## self.PaneA.SetDefaultSize((1000, Event.GetDragRect().height)) ## print "TopWindow default height -> %s"%Event.GetDragRect().height ## elif EventObject is self.PaneB: ## self.PaneB.SetDefaultSize((1000, Event.GetDragRect().height)) ## print "BottomWindow default height -> %s"%Event.GetDragRect().height ## else: ## print "wtf?" wx.LayoutAlgorithm().LayoutWindow(self) self.Refresh() def BuildWidgets(self): # Put some crap in the panel: PaneIDs = [] ############################################################ # FIRST half: self.PaneA = QuestListPanel(self, -1, wx.DefaultPosition, (200, 30), wx.NO_BORDER | wx.SW_3D) self.PaneA.SetDefaultSize((300, 1000)) self.PaneA.SetOrientation(wx.LAYOUT_VERTICAL) self.PaneA.SetAlignment(wx.LAYOUT_LEFT) #self.PaneA.SetOrientation(wx.LAYOUT_HORIZONTAL) #self.PaneA.SetAlignment(wx.LAYOUT_TOP) self.PaneA.SetBackgroundColour(wx.Colour(55, 55, 55)) #self.PaneA.SetSashVisible(wx.SASH_BOTTOM, True) self.PaneA.SetSashVisible(wx.SASH_RIGHT, True) PaneIDs.append(self.PaneA.GetId()) self.BuildQuestList(self.PaneA) ############################################################ # SECOND half: self.PaneB = wx.SashLayoutWindow(RootWindow, -1, wx.DefaultPosition, (200, 30), wx.NO_BORDER|wx.SW_3D) self.PaneB.SetDefaultSize((300, 1000)) self.PaneB.SetOrientation(wx.LAYOUT_VERTICAL) self.PaneB.SetAlignment(wx.LAYOUT_RIGHT) #self.PaneB.SetOrientation(wx.LAYOUT_HORIZONTAL) #self.PaneB.SetAlignment(wx.LAYOUT_BOTTOM) #self.PaneB.SetBackgroundColour(wx.Colour(155, 55, 55)) # Note: You can't have two sash-layout-windows which abut and both have visible sashes! # (If you do, then the "bottom" sash is forbidden to drag above the "top" sash) #self.PaneB.SetSashVisible(wx.SASH_TOP, True) PaneIDs.append(self.PaneA.GetId()) TextStyle = wx.TE_READONLY | wx.TE_MULTILINE ###################################################### InstructionsHolder = wx.Panel(self.PaneB, -1) GameInstructionsStatic = wx.StaticText(InstructionsHolder, -1, "Game Instructions:") self.GameInstructionsText = wx.TextCtrl(InstructionsHolder, -1, "", wx.DefaultPosition, (500, 150), style = TextStyle) self.GameInstructionsText.SetBackgroundColour(wx.Colour(155, 155, 155)) QuestInstructionsStatic = wx.StaticText(InstructionsHolder, -1, "Quest Instructions:") self.QuestInstructionsText = wx.TextCtrl(InstructionsHolder, -1, "", wx.DefaultPosition, (1000, 150), style = TextStyle) self.QuestInstructionsText.SetBackgroundColour(wx.Colour(155, 155, 155)) #self.InstructionsText = wx.TextCtrl(self.PaneB, -1, style = TextStyle) # Bind events: self.Bind(wx.EVT_SASH_DRAGGED_RANGE, self.OnSashDrag, id = min(PaneIDs), id2 = max(PaneIDs)) # Layout: Box = wx.BoxSizer(wx.VERTICAL) #Box.AddSpacer(10) Box.Add(GameInstructionsStatic, 0, wx.EXPAND | wx.TOP | wx.LEFT | wx.BOTTOM, 4) Box.Add(self.GameInstructionsText, 1, wx.EXPAND | wx.LEFT, 10) Box.Add(QuestInstructionsStatic, 0, wx.EXPAND | wx.TOP | wx.LEFT | wx.BOTTOM, 4) Box.Add(self.QuestInstructionsText, 1, wx.EXPAND | wx.LEFT, 10) InstructionsHolder.SetAutoLayout(True) InstructionsHolder.SetSizer(Box) InstructionsHolder.Layout() def BuildQuestList(self, Parent): """ Build QuestListCtrl: """ #self.QuestList = self.QuestPanel.TopWindow.BuildListControl(self) Style = wx.LC_REPORT | wx.BORDER_NONE | wx.LC_SORT_ASCENDING self.QuestList = QuestListCtrl(Parent, -1, style = Style) self.QuestPanel.TopWindow.QuestList = self.QuestList # bind events: self.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnQuestSelected, self.QuestList) self.Bind(wx.EVT_LIST_ITEM_DESELECTED, self.OnQuestDeselected, self.QuestList) self.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.OnQuestDoubleClick, self.QuestList) #self.QuestList.Bind(wx.EVT_LEFT_DCLICK, self.OnQuestDoubleClick) self.QuestList.Bind(wx.EVT_COMMAND_RIGHT_CLICK, self.OnQuestRightClick) # for wxMSW self.QuestList.Bind(wx.EVT_RIGHT_UP, self.OnQuestRightClick) # for wxGTK # Add columns: self.QuestList.InsertColumn(0, "Quest") self.QuestList.InsertColumn(1, "Type") self.QuestList.InsertColumn(2, "Driver") self.QuestList.InsertColumn(3, "Completion") self.QuestList.SetColumnWidth(0, 250) self.QuestList.SetColumnWidth(1, 50) self.QuestList.SetColumnWidth(2, 150) self.QuestList.SetColumnWidth(3, 90) self.QuestPanel.TopWindow.PrepareColumnSorting() self.PopulateQuestList() # *After* populating the quest list, we init the column sorter mixin: def PopulateQuestList(self): """ Populate self.QuestList, our list control. """ self.QuestList.DeleteAllItems() ItemDataMap = {} if Global.QGroup: Log("PopulateQuestList!") for QuestIndex in range(len(Global.QGroup.Quests)): Quest = Global.QGroup.Quests[QuestIndex] Index = self.QuestList.InsertStringItem(sys.maxint, Quest.Name) GameTypeStr = Quest.GetGameType() self.QuestList.SetStringItem(Index, 1, GameTypeStr) DriverNameStr = Quest.GetDisplayDriverName() self.QuestList.SetStringItem(Index, 2, DriverNameStr) CompletionStr = Quest.GetBestCompletionString() self.QuestList.SetStringItem(Index, 3, CompletionStr) self.QuestList.SetItemData(Index, QuestIndex) DataValues = (Quest.Name, GameTypeStr, DriverNameStr, CompletionStr) ItemDataMap[QuestIndex] = tuple(DataValues) self.QuestPanel.TopWindow.itemDataMap = ItemDataMap #self.QuestPanel.TopWindow.PrepareColumnSorting()