diff --git a/demo/agw/CustomTreeCtrl.py b/demo/agw/CustomTreeCtrl.py index 3c59d74b..68d8a284 100644 --- a/demo/agw/CustomTreeCtrl.py +++ b/demo/agw/CustomTreeCtrl.py @@ -979,10 +979,14 @@ class CustomTreeCtrlDemo(wx.Panel): self.checkvista = wx.CheckBox(pnl, -1, "Windows Vista Theme") self.checkvista.Bind(wx.EVT_CHECKBOX, self.OnVista) + self.dragFullScreen = wx.CheckBox(pnl, -1, "Fullscreen Drag/Drop") + self.dragFullScreen.Bind(wx.EVT_CHECKBOX, self.OnDragFullScreen) + themessizer.Add(sizera, 0, wx.EXPAND) themessizer.Add(sizerb, 0, wx.EXPAND) themessizer.Add((0, 5)) themessizer.Add(self.checkvista, 0, wx.EXPAND|wx.ALL, 3) + themessizer.Add(self.dragFullScreen, 0, wx.EXPAND|wx.ALL, 3) mainsizer.Add(stylesizer, 0, wx.EXPAND|wx.ALL, 5) mainsizer.Add(colourssizer, 0, wx.EXPAND|wx.ALL, 5) @@ -1280,6 +1284,12 @@ class CustomTreeCtrlDemo(wx.Panel): event.Skip() + def OnDragFullScreen(self, event): + + self.tree.SetDragFullScreen(event.IsChecked()) + event.Skip() + + #--------------------------------------------------------------------------- # CustomTreeCtrl Demo Implementation #--------------------------------------------------------------------------- @@ -1293,8 +1303,6 @@ class CustomTreeCtrl(CT.CustomTreeCtrl): CT.CustomTreeCtrl.__init__(self, parent, id, pos, size, style, agwStyle) - self.SetBackgroundColour(wx.WHITE) - alldata = dir(CT) treestyles = [] @@ -1581,7 +1589,7 @@ class CustomTreeCtrl(CT.CustomTreeCtrl): menu = wx.Menu() - item1 = menu.Append(wx.ID_ANY, "Change item background colour") + item1 = menu.Append(wx.ID_ANY, "Change Item Text") item2 = menu.Append(wx.ID_ANY, "Modify item text colour") menu.AppendSeparator() @@ -1592,6 +1600,7 @@ class CustomTreeCtrl(CT.CustomTreeCtrl): item3 = menu.Append(wx.ID_ANY, strs) item4 = menu.Append(wx.ID_ANY, "Change item font") + item16 = menu.Append(wx.ID_ANY, "Change Item Background Colour") menu.AppendSeparator() if ishtml: @@ -1621,6 +1630,9 @@ class CustomTreeCtrl(CT.CustomTreeCtrl): item7 = menu.Append(wx.ID_ANY, "Disable item") + menu.AppendSeparator() + item14 = menu.Append(wx.ID_ANY, "Hide Item") + item15 = menu.Append(wx.ID_ANY, "Unhide All Items") menu.AppendSeparator() item8 = menu.Append(wx.ID_ANY, "Change item icons") menu.AppendSeparator() @@ -1635,7 +1647,7 @@ class CustomTreeCtrl(CT.CustomTreeCtrl): item11 = menu.Append(wx.ID_ANY, "Prepend an item") item12 = menu.Append(wx.ID_ANY, "Append an item") - self.Bind(wx.EVT_MENU, self.OnItemBackground, item1) + self.Bind(wx.EVT_MENU, self.OnItemText, item1) self.Bind(wx.EVT_MENU, self.OnItemForeground, item2) self.Bind(wx.EVT_MENU, self.OnItemBold, item3) self.Bind(wx.EVT_MENU, self.OnItemFont, item4) @@ -1648,11 +1660,26 @@ class CustomTreeCtrl(CT.CustomTreeCtrl): self.Bind(wx.EVT_MENU, self.OnItemPrepend, item11) self.Bind(wx.EVT_MENU, self.OnItemAppend, item12) self.Bind(wx.EVT_MENU, self.OnSeparatorInsert, item13) + self.Bind(wx.EVT_MENU, self.OnHideItem, item14) + self.Bind(wx.EVT_MENU, self.OnUnhideItems, item15) + self.Bind(wx.EVT_MENU, self.OnItemBackground, item16) self.PopupMenu(menu) menu.Destroy() + def OnItemText(self, event): + + diag = wx.TextEntryDialog(self, "Item Text", caption="Input Item Text", + value=self.GetItemText(self.current), + style=wx.OK | wx.CANCEL | wx.TE_MULTILINE) + reply = diag.ShowModal() + text = diag.GetValue() + diag.Destroy() + if reply in (wx.OK, wx.ID_OK): + self.SetItemText(self.current, text) + + def OnItemBackground(self, event): colourdata = wx.ColourData() @@ -1724,6 +1751,22 @@ class CustomTreeCtrl(CT.CustomTreeCtrl): self.EnableItem(self.current, False) + def OnHideItem(self, event): + + self.HideItem(self.current) + event.Skip() + + + def OnUnhideItems(self, event): + + item = self.GetRootItem() + while item: + if item.IsHidden(): + self.HideItem(item, False) + item = self.GetNext(item) + event.Skip() + + def OnItemIcons(self, event): bitmaps = [self.itemdict["normal"], self.itemdict["selected"], @@ -1972,8 +2015,7 @@ class CustomTreeCtrl(CT.CustomTreeCtrl): self.item = event.GetItem() if self.item: - self.log.write("Beginning Drag..." + "\n") - + self.log.write("Beginning Drag... fullscreen=%s\n" % self.GetDragFullScreen()) event.Allow() @@ -1981,16 +2023,19 @@ class CustomTreeCtrl(CT.CustomTreeCtrl): self.item = event.GetItem() if self.item: - self.log.write("Beginning Right Drag..." + "\n") - + self.log.write("Beginning Right Drag... fullscreen=%s\n" % self.GetDragFullScreen()) event.Allow() def OnEndDrag(self, event): - self.item = event.GetItem() - if self.item: - self.log.write("Ending Drag!" + "\n") + if self.GetDragFullScreen() is True: + wnd = wx.FindWindowAtPoint(self.ClientToScreen(event.GetPoint())) + self.log.write("Ending Drag! window=%s\n" % repr(wnd)) + else: + self.item = event.GetItem() + name = self.GetItemText(self.item) if self.item else 'None' + self.log.write("Ending Drag! item=%s\n" % name) event.Skip() diff --git a/demo/agw/HyperTreeList.py b/demo/agw/HyperTreeList.py index 77cb2ec1..c88e6729 100644 --- a/demo/agw/HyperTreeList.py +++ b/demo/agw/HyperTreeList.py @@ -1055,7 +1055,7 @@ class HyperTreeListDemo(wx.Frame): splitter.SplitVertically(self.leftpanel, panel, 300) splitter.SetMinimumPaneSize(120) - self.leftpanel.SetBackgroundColour(wx.WHITE) + #self.leftpanel.SetBackgroundColour(wx.WHITE) self.leftpanel.SetScrollRate(20, 20) self.Fit() @@ -1339,10 +1339,14 @@ class HyperTreeListDemo(wx.Frame): self.checkvista = wx.CheckBox(self.leftpanel, -1, "Windows Vista Theme") self.checkvista.Bind(wx.EVT_CHECKBOX, self.OnVista) + self.dragFullScreen = wx.CheckBox(self.leftpanel, -1, "Fullscreen Drag/Drop") + self.dragFullScreen.Bind(wx.EVT_CHECKBOX, self.OnDragFullScreen) + themessizer.Add(sizera, 0, wx.EXPAND) themessizer.Add(sizerb, 0, wx.EXPAND) themessizer.Add((0, 5)) themessizer.Add(self.checkvista, 0, wx.EXPAND|wx.ALL, 3) + themessizer.Add(self.dragFullScreen, 0, wx.EXPAND|wx.ALL, 3) mainsizer.Add(stylesizer, 0, wx.EXPAND|wx.ALL, 5) mainsizer.Add(columnssizer, 0, wx.EXPAND|wx.ALL, 5) @@ -1738,6 +1742,11 @@ class HyperTreeListDemo(wx.Frame): event.Skip() + def OnDragFullScreen(self, event): + + self.tree.SetDragFullScreen(event.IsChecked()) + event.Skip() + #--------------------------------------------------------------------------- # HyperTreeList Implementation @@ -1766,6 +1775,7 @@ class HyperTreeList(HTL.HyperTreeList): for evt in ["EVT_TREE_GET_INFO", "EVT_TREE_SET_INFO", "EVT_TREE_ITEM_MIDDLE_CLICK", "EVT_TREE_STATE_IMAGE_CLICK"]: events.remove(evt) + events.extend(('EVT_LIST_COL_CLICK', 'EVT_LIST_COL_RIGHT_CLICK')) treestyles = treestyles + [i for i in dir(wx) if i.startswith("TR_")] treeset = {} @@ -1776,6 +1786,8 @@ class HyperTreeList(HTL.HyperTreeList): self.events = events self.styles = treestyles self.item = None + self.sortIcon = wx.HDR_SORT_ICON_NONE + self.sortColumn = 0 il = wx.ImageList(16, 16) @@ -1906,7 +1918,8 @@ class HyperTreeList(HTL.HyperTreeList): 'EVT_TREE_ITEM_EXPANDING': self.OnItemExpanding, 'EVT_TREE_ITEM_GETTOOLTIP': self.OnToolTip, 'EVT_TREE_ITEM_MENU': self.OnItemMenu, 'EVT_TREE_ITEM_RIGHT_CLICK': self.OnRightDown, 'EVT_TREE_KEY_DOWN': self.OnKey, 'EVT_TREE_SEL_CHANGED': self.OnSelChanged, - 'EVT_TREE_SEL_CHANGING': self.OnSelChanging, "EVT_TREE_ITEM_HYPERLINK": self.OnHyperLink} + 'EVT_TREE_SEL_CHANGING': self.OnSelChanging, "EVT_TREE_ITEM_HYPERLINK": self.OnHyperLink, + 'EVT_LIST_COL_CLICK': self.OnColClick, 'EVT_LIST_COL_RIGHT_CLICK': self.OnColRightClick} mainframe = wx.GetTopLevelParent(self) @@ -2100,7 +2113,7 @@ class HyperTreeList(HTL.HyperTreeList): "itemtype": itemtype, "text": text, "pydata": pydata, "enabled": enabled} menu = wx.Menu() - + item1 = menu.Append(wx.ID_ANY, "Change Item Text") item2 = menu.Append(wx.ID_ANY, "Modify Item Text Colour") menu.AppendSeparator() if isbold: @@ -2135,6 +2148,7 @@ class HyperTreeList(HTL.HyperTreeList): item11 = menu.Append(wx.ID_ANY, "Prepend An Item") item12 = menu.Append(wx.ID_ANY, "Append An Item") + self.Bind(wx.EVT_MENU, self.OnItemText, item1) self.Bind(wx.EVT_MENU, self.OnItemForeground, item2) self.Bind(wx.EVT_MENU, self.OnItemBold, item3) self.Bind(wx.EVT_MENU, self.OnItemFont, item4) @@ -2154,6 +2168,23 @@ class HyperTreeList(HTL.HyperTreeList): event.Skip() + def OnItemText(self, event): + + col = wx.GetNumberFromUser("Choose column number to change text", + "Col", "Column To Modify", 0, 0, + self.GetColumnCount() - 1, self) + if col >= 0 and col < self.GetColumnCount(): + diag = wx.TextEntryDialog(self, "%s Text" % self.GetColumnText(col), + caption="Input text for column %d" % col, + value=self.GetItemText(self.current,col), + style=wx.OK | wx.CANCEL | wx.TE_MULTILINE) + reply = diag.ShowModal() + text = diag.GetValue() + diag.Destroy() + if reply in (wx.OK, wx.ID_OK): + self.SetItemText(self.current, text, col) + + def OnItemForeground(self, event): colourdata = wx.ColourData() @@ -2381,14 +2412,16 @@ class HyperTreeList(HTL.HyperTreeList): def OnItemExpanded(self, event): item = event.GetItem() - if item: + # Ignore wx.TreeCtrl TREE events (item=wx.TreeItemId) from item window. + if item and isinstance(item, HTL.TreeListItem): self.log.write("OnItemExpanded: %s\n" % self.GetItemText(item)) def OnItemExpanding(self, event): item = event.GetItem() - if item: + # Ignore wx.TreeCtrl TREE events (item=wx.TreeItemId) from item window. + if item and isinstance(item, HTL.TreeListItem): self.log.write("OnItemExpanding: %s\n" % self.GetItemText(item)) event.Skip() @@ -2397,14 +2430,16 @@ class HyperTreeList(HTL.HyperTreeList): def OnItemCollapsed(self, event): item = event.GetItem() - if item: + # Ignore wx.TreeCtrl TREE events (item=wx.TreeItemId) from item window. + if item and isinstance(item, HTL.TreeListItem): self.log.write("OnItemCollapsed: %s" % self.GetItemText(item)) def OnItemCollapsing(self, event): item = event.GetItem() - if item: + # Ignore wx.TreeCtrl TREE events (item=wx.TreeItemId) from item window. + if item and isinstance(item, HTL.TreeListItem): self.log.write("OnItemCollapsing: %s\n" % self.GetItemText(item)) event.Skip() @@ -2412,8 +2447,11 @@ class HyperTreeList(HTL.HyperTreeList): def OnSelChanged(self, event): - self.item = event.GetItem() - if self.item: + item = event.GetItem() + # Ignore wx.TreeCtrl TREE events (item=wx.TreeItemId) from item window. + if item and isinstance(item, HTL.TreeListItem): + # This event was from the HyperTreeList and not the TreeCtrl. + self.item = item self.log.write("OnSelChanged: %s" % self.GetItemText(self.item)) if wx.Platform == '__WXMSW__': self.log.write(", BoundingRect: %s\n" % self.GetBoundingRect(self.item, True)) @@ -2426,9 +2464,10 @@ class HyperTreeList(HTL.HyperTreeList): def OnSelChanging(self, event): item = event.GetItem() - olditem = event.GetOldItem() - - if item: + # Ignore wx.TreeCtrl TREE events (item=wx.TreeItemId) from item window. + if item and isinstance(item, HTL.TreeListItem): + # This event was from the HyperTreeList and not the TreeCtrl. + olditem = event.GetOldItem() if not olditem: olditemtext = "None" else: @@ -2437,13 +2476,26 @@ class HyperTreeList(HTL.HyperTreeList): event.Skip() + def OnColClick(self, event): + column = event.GetColumn() + self.log.write("OnColClick: Column %d clicked" % column) + # Cycle through the sort icons. + if column != self.sortColumn: + self.sortIcon = wx.HDR_SORT_ICON_NONE + self.sortColumn = column + self.sortIcon = wx.HDR_SORT_ICON_DOWN if self.sortIcon == wx.HDR_SORT_ICON_UP else wx.HDR_SORT_ICON_UP + self.SetColumnSortIcon(column, self.sortIcon) + + def OnColRightClick(self, event): + column = event.GetColumn() + self.log.write("OnColRightClick: Column %d clicked" % column) + self.SetColumnSortIcon(column, wx.HDR_SORT_ICON_NONE) def OnBeginDrag(self, event): self.item = event.GetItem() if self.item: - self.log.write("Beginning Drag...\n") - + self.log.write("Beginning Drag... fullscreen=%s\n" % self.GetDragFullScreen()) event.Allow() @@ -2451,16 +2503,19 @@ class HyperTreeList(HTL.HyperTreeList): self.item = event.GetItem() if self.item: - self.log.write("Beginning Right Drag...\n") - + self.log.write("Beginning Right Drag... fullscreen=%s\n" % self.GetDragFullScreen()) event.Allow() def OnEndDrag(self, event): - self.item = event.GetItem() - if self.item: - self.log.write("Ending Drag!\n") + if self.GetDragFullScreen() is True: + wnd = wx.FindWindowAtPoint(self.ClientToScreen(event.GetPoint())) + self.log.write("Ending Drag! window=%s\n" % repr(wnd)) + else: + self.item = event.GetItem() + name = self.GetItemText(self.item) if self.item else 'None' + self.log.write("Ending Drag! item=%s\n" % name) event.Skip() diff --git a/demo/run.py b/demo/run.py index a3d88d31..85e64ffc 100755 --- a/demo/run.py +++ b/demo/run.py @@ -160,6 +160,7 @@ def main(argv): app = RunDemoApp(name, module, useShell) + locale = wx.Locale(wx.LANGUAGE_DEFAULT) app.MainLoop() diff --git a/wx/lib/agw/customtreectrl.py b/wx/lib/agw/customtreectrl.py index 713d5e59..82105bfe 100644 --- a/wx/lib/agw/customtreectrl.py +++ b/wx/lib/agw/customtreectrl.py @@ -40,8 +40,8 @@ """ -:class:`~wx.lib.agw.customtreectrl.CustomTreeCtrl` is a class that mimics the behaviour of :class:`TreeCtrl`, with some more -enhancements. +The ``customtreectrl`` module contains the :class:`~wx.lib.agw.customtreectrl.CustomTreeCtrl` class +which mimics the behaviour of :class:`TreeCtrl`, with some more enhancements. Description @@ -100,6 +100,7 @@ to the standard :class:`TreeCtrl` behaviour this class supports: style (`New in version 0.9.3`); * Tooltips on long items when the horizontal space is low, via the ``TR_TOOLTIP_ON_LONG_ITEMS`` style (`New in version 0.9.3`). +* Hiding items And a lot more. Check the demo for an almost complete review of the functionalities. @@ -218,6 +219,30 @@ And to hyperlink-type items: after the ``EVT_TREE_SEL_CHANGED`` event). +Drag and Drop +============= + +A simplified drag and drop is available and can be initiated by calling +``event.Allow`` on the ``EVT_TREE_BEGIN_DRAG`` or ``EVT_TREE_BEGIN_RDRAG`` +events. When the event handler returns, a ``wx.DragImage`` of the item will be +generated and the user can drag it to other items within the tree. When the +user releases the drag button a ``EVT_TREE_END_DRAG`` event will be sent and +``event.GetItem`` can be called to find out which item the drag ended at. +This simplified method is best when only a single item at a time needs to +be dragged (i.e. ``TR_MULTIPLE`` not set) and only for dragging items within +the tree control. + +Alternately, the normal wxPython drag/drop can be invoked in the ``EVT_TREE_BEGIN_DRAG`` +handler in which a :class:`wx.DropSource` must be generated, followed by a call +to :meth:`~wx.DropSource.DoDragDrop` which will block until the drag is finished. +This is much more flexible but more complicated to implement. + +:note: The class value _DRAG_TIMER_TICKS controls how long the mouse must + linger before the drag can start. It defaults to 250 milliseconds which can + be far too long for today's quick 'swiping' generation. It can be lowered for + a more responsive drag. + + Supported Platforms =================== @@ -230,33 +255,56 @@ Supported Platforms Window Styles ============= -This class supports the following window styles: +This class takes in a regular wxPython ``style`` and an extended ``agwStyle``. +The ``style`` can be used with normal wxPython styles such as ``wx.WANTS_CHARS`` +while the ``agwStyle`` specifies the behavior of the tree itself. +It supports the following ``agwStyle`` flags: -============================== =========== ================================================== -Window Styles Hex Value Description -============================== =========== ================================================== -``TR_NO_BUTTONS`` 0x0 For convenience to document that no buttons are to be drawn. -``TR_SINGLE`` 0x0 For convenience to document that only one item may be selected at a time. Selecting another item causes the current selection, if any, to be deselected. This is the default. -``TR_HAS_BUTTONS`` 0x1 Use this style to show + and - buttons to the left of parent items. -``TR_NO_LINES`` 0x4 Use this style to hide vertical level connectors. -``TR_LINES_AT_ROOT`` 0x8 Use this style to show lines between root nodes. Only applicable if ``TR_HIDE_ROOT`` is set and ``TR_NO_LINES`` is not set. -``TR_DEFAULT_STYLE`` 0x9 The set of flags that are closest to the defaults for the native control for a particular toolkit. -``TR_TWIST_BUTTONS`` 0x10 Use old Mac-twist style buttons. -``TR_MULTIPLE`` 0x20 Use this style to allow a range of items to be selected. If a second range is selected, the current range, if any, is deselected. -``TR_EXTENDED`` 0x40 Use this style to allow disjoint items to be selected. (Only partially implemented; may not work in all cases). -``TR_HAS_VARIABLE_ROW_HEIGHT`` 0x80 Use this style to cause row heights to be just big enough to fit the content. If not set, all rows use the largest row height. The default is that this flag is unset. -``TR_EDIT_LABELS`` 0x200 Use this style if you wish the user to be able to edit labels in the tree control. -``TR_ROW_LINES`` 0x400 Use this style to draw a contrasting border between displayed rows. -``TR_HIDE_ROOT`` 0x800 Use this style to suppress the display of the root node, effectively causing the first-level nodes to appear as a series of root nodes. -``TR_FULL_ROW_HIGHLIGHT`` 0x2000 Use this style to have the background colour and the selection highlight extend over the entire horizontal row of the tree control window. -``TR_AUTO_CHECK_CHILD`` 0x4000 Only meaningful for checkbox-type items: when a parent item is checked/unchecked its children are checked/unchecked as well. -``TR_AUTO_TOGGLE_CHILD`` 0x8000 Only meaningful for checkbox-type items: when a parent item is checked/unchecked its children are toggled accordingly. -``TR_AUTO_CHECK_PARENT`` 0x10000 Only meaningful for checkbox-type items: when a child item is checked/unchecked its parent item is checked/unchecked as well. -``TR_ALIGN_WINDOWS`` 0x20000 Flag used to align windows (in items with windows) at the same horizontal position. -``TR_ALIGN_WINDOWS_RIGHT`` 0x40000 Flag used to align windows (in items with windows) to the rightmost edge of :class:`CustomTreeCtrl`. -``TR_ELLIPSIZE_LONG_ITEMS`` 0x80000 Flag used to ellipsize long items when the horizontal space for :class:`CustomTreeCtrl` is low. -``TR_TOOLTIP_ON_LONG_ITEMS`` 0x100000 Flag used to show tooltips on long items when the horizontal space for :class:`CustomTreeCtrl` is low. -============================== =========== ================================================== +================================= =========== ================================================== +Window agwStyle Flags Hex Value Description +================================= =========== ================================================== +**wx.TR_DEFAULT_STYLE** *varies* The set of flags that are closest to the defaults for the native control for a particular toolkit. Should always be used. +``wx.TR_NO_BUTTONS`` 0x0 For convenience to document that no buttons are to be drawn. +``wx.TR_SINGLE`` 0x0 For convenience to document that only one item may be selected at a time. Selecting another item causes the current selection, if any, to be deselected. This is the default. +``wx.TR_HAS_BUTTONS`` 0x1 Use this style to show + and - buttons to the left of parent items. +``wx.TR_NO_LINES`` 0x4 Use this style to hide vertical level connectors. +``wx.TR_LINES_AT_ROOT`` 0x8 Use this style to show lines between root nodes. Only applicable if ``TR_HIDE_ROOT`` is set and ``TR_NO_LINES`` is not set. +``wx.TR_TWIST_BUTTONS`` 0x10 Use old Mac-twist style buttons. +``wx.TR_MULTIPLE`` 0x20 Use this style to allow a range of items to be selected. If a second range is selected, the current range, if any, is deselected. +``wx.TR_HAS_VARIABLE_ROW_HEIGHT`` 0x80 Use this style to cause row heights to be just big enough to fit the content. If not set, all rows use the largest row height. The default is that this flag is unset. +``wx.TR_EDIT_LABELS`` 0x200 Use this style if you wish the user to be able to edit labels in the tree control. +``wx.TR_ROW_LINES`` 0x400 Use this style to draw a contrasting border between displayed rows. +``wx.TR_HIDE_ROOT`` 0x800 Use this style to suppress the display of the root node, effectively causing the first-level nodes to appear as a series of root nodes. +``wx.TR_FULL_ROW_HIGHLIGHT`` 0x2000 Use this style to have the background colour and the selection highlight extend over the entire horizontal row of the tree control window. +**Styles from customtreectrl:** +``TR_EXTENDED`` 0x40 Use this style to allow disjoint items to be selected. (Only partially implemented; may not work in all cases). +``TR_AUTO_CHECK_CHILD`` 0x4000 Only meaningful for checkbox-type items: when a parent item is checked/unchecked its children are checked/unchecked as well. +``TR_AUTO_TOGGLE_CHILD`` 0x8000 Only meaningful for checkbox-type items: when a parent item is checked/unchecked its children are toggled accordingly. +``TR_AUTO_CHECK_PARENT`` 0x10000 Only meaningful for checkbox-type items: when a child item is checked/unchecked its parent item is checked/unchecked as well. +``TR_ALIGN_WINDOWS`` 0x20000 Flag used to align windows (in items with windows) at the same horizontal position. +``TR_ALIGN_WINDOWS_RIGHT`` 0x40000 Flag used to align windows (in items with windows) to the rightmost edge of :class:`CustomTreeCtrl`. +``TR_ELLIPSIZE_LONG_ITEMS`` 0x80000 Flag used to ellipsize long items when the horizontal space for :class:`CustomTreeCtrl` is low. +``TR_TOOLTIP_ON_LONG_ITEMS`` 0x100000 Flag used to show tooltips on long items when the horizontal space for :class:`CustomTreeCtrl` is low. +================================= =========== ================================================== + +The ``wx.TR_HAS_VARIABLE_LINE_HEIGHT`` style should be set if item rows might +not all be the same height. This can happen if certain rows have a larger font +size, multi-line text, or windows added to them. This style will automatically +adjust each item's height to be just big enough to show its contents. + +When the ``wx.TR_HAS_VARIABLE_LINE_HEIGHT`` is not set, adding a new item with +multi-line text or with a window specified will throw an exception. However the +tree won't prevent you from adding multiline text with :meth:`~TreeListMainWindow.SetItemText` +or assigning a window with :meth:`~TreeListMainWindow.SetItemWindow` to an +existing item. It's generally a bad idea to do either of these without this +style as it will result in an ugly tree. By default the ``wx.TR_HAS_VARIABLE_LINE_HEIGHT`` +is not set. This means that all item rows will use the same height. This is the +height of the largest item in the tree. If an item with a larger height is +added or revealed, ALL row heights will increase to this larger size. The +larger row height remains persistent even if the large items are hidden or +deleted. You must call :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.CalculateLineHeight` +to reset the row height. This somewhat bizarre behavior is why the ``wx.TR_HAS_VARIABLE_LINE_HEIGHT`` +style is almost always used. Events Processing @@ -636,12 +684,16 @@ def ChopText(dc, text, max_size): .. versionadded:: 0.9.3 """ - # first check if the text fits with no problems + # first check if the text fits with no problems (converts to Unicode). x, y, dummy = dc.GetFullMultiLineTextExtent(text) if x <= max_size: return text + # We cannot chop text that is UTF-8, as it could produce invalid sequences. + if isinstance(text, bytes): + # Convert UTF-8 (Phoenix's mandatory encoding) to Unicode. + text = text.decode('utf-8') textLen = len(text) last_good_length = 0 @@ -1650,6 +1702,7 @@ class GenericTreeItem(object): self._enabled = True # flag to enable/disable an item self._hypertext = False # indicates if the item is hypertext self._visited = False # visited state for an hypertext item + self._hidden = False # hidden items are not painted if self._type > 0: # do not construct the array for normal items @@ -1698,10 +1751,11 @@ class GenericTreeItem(object): :return: A Python list containing instances of :class:`GenericTreeItem`, representing this item's children. + :note: The returned value is a reference to the list of children - used internally by the tree. It is advised not to change this list - and to make a copy before calling other tree methods as they could - change the contents of the list. + used internally by the tree. It is advised not to change this list + and to make a copy before calling other tree methods as they could + change the contents of the list. """ return self._children @@ -1795,7 +1849,8 @@ class GenericTreeItem(object): :param integer `which`: the image kind. :see: :meth:`~GenericTreeItem.GetImage` for a description of the `which` parameter. - :note: Call :meth:`~CustomTreeCtrl.SetItemImage` instead to refresh the tree properly. + + :note: Call :meth:`CustomTreeCtrl.SetItemImage` instead to refresh the tree properly. """ self._images[which] = image @@ -1808,7 +1863,8 @@ class GenericTreeItem(object): :param integer `image`: an index within the left image list specifying the image to use for the item in the leftmost part of the client area. - :note: Call :meth:`~CustomTreeCtrl.SetItemLeftImage` instead to refresh the tree properly. + + :note: Call :meth:`CustomTreeCtrl.SetItemLeftImage` instead to refresh the tree properly. """ self._leftimage = image @@ -1829,7 +1885,8 @@ class GenericTreeItem(object): Sets whether an item has the 'plus' button. :param bool `has`: ``True`` to set the 'plus' button on the item, ``False`` otherwise. - :note: Call :meth:`~CustomTreeCtrl.SetItemHasChildren` instead to refresh the tree properly. + + :note: Call :meth:`CustomTreeCtrl.SetItemHasChildren` instead to refresh the tree properly. """ self._hasPlus = has @@ -1840,7 +1897,8 @@ class GenericTreeItem(object): Sets the item font bold. :parameter bool `bold`: ``True`` to have a bold font item, ``False`` otherwise. - :note: Call :meth:`~CustomTreeCtrl.SetItemBold` instead to refresh the tree properly. + + :note: Call :meth:`CustomTreeCtrl.SetItemBold` instead to refresh the tree properly. """ self._isBold = bold @@ -1851,7 +1909,8 @@ class GenericTreeItem(object): Sets the item font italic. :parameter bool `italic`: ``True`` to have an italic font item, ``False`` otherwise. - :note: Call :meth:`~CustomTreeCtrl.SetItemItalic` instead to refresh the tree properly. + + :note: Call :meth:`CustomTreeCtrl.SetItemItalic` instead to refresh the tree properly. """ self._isItalic = italic @@ -1890,20 +1949,29 @@ class GenericTreeItem(object): def GetHeight(self): - """ Returns the height of the item, in pixels. """ + """ Returns the height of the item, in pixels. + + This will be 0 when the item is first created and always 0 for hidden + items. It is updated when the item is calculated. + """ return self._height def GetWidth(self): - """ Returns the width of the item, in pixels. """ + """ Returns the width of the item's contents, in pixels. + + This is the width of the item's text plus the widths of the item's + image, checkbox, and window (if they exist). + A separator's width is the width of the entire client area. + """ return self._width def SetHeight(self, h): """ - Sets the item's height. + Sets the item's height. Used internally. :param integer `h`: an integer specifying the item's height, in pixels. """ @@ -1913,7 +1981,7 @@ class GenericTreeItem(object): def SetWidth(self, w): """ - Sets the item's width. + Sets the item's width. Used internally. :param integer `w`: an integer specifying the item's width, in pixels. """ @@ -1932,7 +2000,8 @@ class GenericTreeItem(object): on the left of text and overlapping the image. New in wxPython 4.0.4. :raise: `Exception` if the input `item` is a separator and `wnd` is not ``None``. - :note: Always use :meth:`~CustomTreeCtrl.SetItemWindow` instead to update the tree properly. + + :note: Always use :meth:`CustomTreeCtrl.SetItemWindow` instead to update the tree properly. """ if self.IsSeparator() and wnd is not None: @@ -1984,7 +2053,7 @@ class GenericTreeItem(object): def DeleteWindow(self): """ Deletes the window associated to the item (if any). Internal use only. - :note: Always use :meth:`~CustomTreeCtrl.DeleteItemWindow` instead to update the tree properly. + :note: Always use :meth:`CustomTreeCtrl.DeleteItemWindow` instead to update the tree properly. """ if self._wnd: @@ -2103,7 +2172,8 @@ class GenericTreeItem(object): must be unchecked. - If a radiobutton node becomes unchecked, then all of its child nodes will become inactive. - :note: Call :meth:`~CustomTreeCtrl.SetItemType` instead to refresh the tree properly. + + :note: Call :meth:`CustomTreeCtrl.SetItemType` instead to refresh the tree properly. """ self._type = ct_type @@ -2114,7 +2184,8 @@ class GenericTreeItem(object): Sets whether the item is hypertext or not. :param bool `hyper`: ``True`` to set hypertext behaviour, ``False`` otherwise. - :note: Call :meth:`~CustomTreeCtrl.SetItemHyperText` instead to refresh the tree properly. + + :note: Call :meth:`CustomTreeCtrl.SetItemHyperText` instead to refresh the tree properly. """ self._hypertext = hyper @@ -2125,7 +2196,8 @@ class GenericTreeItem(object): Sets whether an hypertext item was visited or not. :param bool `visited`: ``True`` to set a hypertext item as visited, ``False`` otherwise. - :note: Call :meth:`~CustomTreeCtrl.SetItemVisited` instead to refresh the tree properly. + + :note: Call :meth:`CustomTreeCtrl.SetItemVisited` instead to refresh the tree properly. """ self._visited = visited @@ -2143,6 +2215,24 @@ class GenericTreeItem(object): return self._hypertext + def IsHidden(self): + """ Returns whether the item is hidden or not. """ + + return self._hidden + + + def Hide(self, hide): + """ + Hides/shows the item. Internal use only. + + :param `hide`: ``True`` to hide the item, ``False`` to show it. + + :note: Always use :meth:`CustomTreeCtrl.HideItem` instead to update the tree properly. + """ + + self._hidden = hide + + def GetParent(self): """ Gets the item parent (another instance of :class:`GenericTreeItem` or ``None`` for @@ -2168,7 +2258,7 @@ class GenericTreeItem(object): def Expand(self): """ Expands the item. Internal use only. - :note: Always use :meth:`~CustomTreeCtrl.Expand` instead to update the tree properly and send events. + :note: Always use :meth:`CustomTreeCtrl.Expand` instead to update the tree properly and send events. """ self._isCollapsed = False @@ -2177,7 +2267,7 @@ class GenericTreeItem(object): def Collapse(self): """ Collapses the item. Internal use only. - :note: Always use :meth:`~CustomTreeCtrl.Collapse` instead to update the tree properly and send events. + :note: Always use :meth:`CustomTreeCtrl.Collapse` instead to update the tree properly and send events. """ self._isCollapsed = True @@ -2188,7 +2278,8 @@ class GenericTreeItem(object): Sets the item focus/unfocus. :param bool `set`: ``True`` to set the focus to the item, ``False`` otherwise. - :note: Call :meth:`~CustomTreeCtrl.SelectItem` instead to update the tree properly and send events. + + :note: Call :meth:`CustomTreeCtrl.SelectItem` instead to update the tree properly and send events. """ self._hasHilight = set @@ -2216,11 +2307,12 @@ class GenericTreeItem(object): def IsExpanded(self): """ - Returns whether the item is expanded or not. + Returns whether the item is expanded or not. Hidden items always return False. :return: ``True`` if the item is expanded, ``False`` if it is collapsed. """ - + if self.IsHidden(): + return False return not self._isCollapsed @@ -2330,7 +2422,8 @@ class GenericTreeItem(object): :param bool `checked`: ``True`` to check an item, ``False`` to uncheck it. :note: This is meaningful only for checkbox-like and radiobutton-like items. - :note: Always use :meth:`~CustomTreeCtrl.CheckItem` instead to update the tree properly and send events. + + :note: Always use :meth:`CustomTreeCtrl.CheckItem` instead to update the tree properly and send events. """ assert checked in [True, False] self._checked = checked @@ -2371,7 +2464,8 @@ class GenericTreeItem(object): Enables/disables the item. :param bool `enable`: ``True`` to enable the item, ``False`` to disable it. - :note: Call :meth:`~CustomTreeCtrl.EnableItem` instead to update the tree properly. + + :note: Call :meth:`CustomTreeCtrl.EnableItem` instead to update the tree properly. """ self._enabled = enable @@ -2379,11 +2473,12 @@ class GenericTreeItem(object): def IsEnabled(self): """ - Returns whether the item is enabled or not. + Returns whether the item is enabled or not. Hidden items always return False. :return: ``True`` if the item is enabled, ``False`` if it is disabled. """ - + if self.IsHidden(): + return False return self._enabled @@ -2442,7 +2537,8 @@ class GenericTreeItem(object): Deletes the item children. Internal use only. :param `tree`: the main :class:`CustomTreeCtrl` instance. - :note: Always use :meth:`~CustomTreeCtrl.DeleteChildren` instead to update the tree properly. + + :note: Always use :meth:`CustomTreeCtrl.DeleteChildren` instead to update the tree properly. """ for child in self._children: @@ -2475,7 +2571,8 @@ class GenericTreeItem(object): :param string `text`: the new item label. :raise: `Exception` if the item is a separator. - :note: Call :meth:`~CustomTreeCtrl.SetItemText` to refresh the tree properly. + + :note: Call :meth:`CustomTreeCtrl.SetItemText` to refresh the tree properly. """ if self.IsSeparator(): @@ -2544,7 +2641,12 @@ class GenericTreeItem(object): :param integer `level`: the item's level inside the tree hierarchy. :see: :meth:`CustomTreeCtrl.HitTest() ` method for the flags explanation. + + :return: A 2-tuple of (item, flags). The item may be ``None``. """ + # Hidden items are never evaluated. + if self.IsHidden(): + return None, flags # for a hidden root node, don't evaluate it, but do evaluate children if not (level == 0 and theCtrl.HasAGWFlag(TR_HIDE_ROOT)): @@ -2718,35 +2820,8 @@ class CustomTreeCtrl(wx.ScrolledWindow): chosen by either the windowing system or wxPython, depending on platform; :type `size`: tuple or :class:`wx.Size` :param integer `style`: the underlying :class:`ScrolledWindow` style; - :param integer `agwStyle`: the AGW-specific window style for :class:`CustomTreeCtrl`. It can be a - combination of the following bits: - - ============================== =========== ================================================== - Window Styles Hex Value Description - ============================== =========== ================================================== - ``TR_NO_BUTTONS`` 0x0 For convenience to document that no buttons are to be drawn. - ``TR_SINGLE`` 0x0 For convenience to document that only one item may be selected at a time. Selecting another item causes the current selection, if any, to be deselected. This is the default. - ``TR_HAS_BUTTONS`` 0x1 Use this style to show + and - buttons to the left of parent items. - ``TR_NO_LINES`` 0x4 Use this style to hide vertical level connectors. - ``TR_LINES_AT_ROOT`` 0x8 Use this style to show lines between root nodes. Only applicable if ``TR_HIDE_ROOT`` is set and ``TR_NO_LINES`` is not set. - ``TR_DEFAULT_STYLE`` 0x9 The set of flags that are closest to the defaults for the native control for a particular toolkit. - ``TR_TWIST_BUTTONS`` 0x10 Use old Mac-twist style buttons. - ``TR_MULTIPLE`` 0x20 Use this style to allow a range of items to be selected. If a second range is selected, the current range, if any, is deselected. - ``TR_EXTENDED`` 0x40 Use this style to allow disjoint items to be selected. (Only partially implemented; may not work in all cases). - ``TR_HAS_VARIABLE_ROW_HEIGHT`` 0x80 Use this style to cause row heights to be just big enough to fit the content. If not set, all rows use the largest row height. The default is that this flag is unset. - ``TR_EDIT_LABELS`` 0x200 Use this style if you wish the user to be able to edit labels in the tree control. - ``TR_ROW_LINES`` 0x400 Use this style to draw a contrasting border between displayed rows. - ``TR_HIDE_ROOT`` 0x800 Use this style to suppress the display of the root node, effectively causing the first-level nodes to appear as a series of root nodes. - ``TR_FULL_ROW_HIGHLIGHT`` 0x2000 Use this style to have the background colour and the selection highlight extend over the entire horizontal row of the tree control window. - ``TR_AUTO_CHECK_CHILD`` 0x4000 Only meaningful for checkbox-type items: when a parent item is checked/unchecked its children are checked/unchecked as well. - ``TR_AUTO_TOGGLE_CHILD`` 0x8000 Only meaningful for checkbox-type items: when a parent item is checked/unchecked its children are toggled accordingly. - ``TR_AUTO_CHECK_PARENT`` 0x10000 Only meaningful for checkbox-type items: when a child item is checked/unchecked its parent item is checked/unchecked as well. - ``TR_ALIGN_WINDOWS`` 0x20000 Flag used to align windows (in items with windows) at the same horizontal position. - ``TR_ALIGN_WINDOWS_RIGHT`` 0x40000 Flag used to align windows (in items with windows) to the rightmost edge of :class:`CustomTreeCtrl`. - ``TR_ELLIPSIZE_LONG_ITEMS`` 0x80000 Flag used to ellipsize long items when the horizontal space for :class:`CustomTreeCtrl` is low. - ``TR_TOOLTIP_ON_LONG_ITEMS`` 0x100000 Flag used to show tooltips on long items when the horizontal space for :class:`CustomTreeCtrl` is low. - ============================== =========== ================================================== - + :param integer `agwStyle`: can be a combination of various bits. See + :mod:`~wx.lib.agw.customtreectrl` for a full list of flags. :param wx.Validator `validator`: window validator; :param string `name`: window name. """ @@ -2783,6 +2858,7 @@ class CustomTreeCtrl(wx.ScrolledWindow): self._isDragging = False self._dropTarget = self._oldSelection = None self._dragImage = None + self._dragFullScreen = False self._underMouse = None # EditCtrl initial settings for editable items @@ -2893,7 +2969,7 @@ class CustomTreeCtrl(wx.ScrolledWindow): self.SetValidator(validator) - attr = self.GetDefaultAttributes() + attr = wx.ListCtrl.GetClassDefaultAttributes() self.SetOwnForegroundColour(attr.colFg) self.SetOwnBackgroundColour(attr.colBg) @@ -3036,18 +3112,19 @@ class CustomTreeCtrl(wx.ScrolledWindow): def GetSelection(self): """ - Returns the current selection. + Returns the current selected item (i.e. focused item). :return: An instance of :class:`GenericTreeItem`. - :note: - - This method is valid only with the style ``TR_SINGLE`` set. Use - :meth:`~CustomTreeCtrl.GetSelections` for multiple-selections trees. + :note: Similar to GetFocusedItem of wx.TreeCtrl. Use + :meth:`~CustomTreeCtrl.GetSelections` for obtaining all items + selected in multiple-selection trees (i.e. TR_MULTIPLE flag set). """ return self._current + GetFocusedItem = GetSelection + def ToggleItemSelection(self, item): """ @@ -3746,9 +3823,16 @@ class CustomTreeCtrl(wx.ScrolledWindow): raise Exception("Separator items can not have text") dc = wx.ClientDC(self) + oldtext = item.GetText() item.SetText(text) - self.CalculateSize(item, dc) - self.RefreshLine(item) + # Avoid Calculating tree unless number of lines changed (slow). + if oldtext.count('\n') != text.count('\n'): + self.CalculatePositions() + self.Refresh() + self.AdjustMyScrollbars() + else: + self.CalculateSize(item, dc) + self.RefreshLine(item) def SetItemImage(self, item, image, which=TreeItemIcon_Normal): @@ -4448,6 +4532,36 @@ class CustomTreeCtrl(wx.ScrolledWindow): self.Refresh() + def GetDragFullScreen(self): + """ + Returns whether built-in drag/drop will be full screen or not. + + :return: ``True`` if the drag/drop operation will be full screen, or + ``False`` if only within the tree. + """ + + return self._dragFullScreen + + + def SetDragFullScreen(self, fullScreen=False): + """ + Sets whether a drag operation will be performed full screen or not. + + A full screen drag allows the user to drag outside of the tree to + other controls. When the drag is finished the destination will have + to be found manually in the ``EVT_TREE_END_DRAG`` handler with + something like: + + example:: + + wnd = wx.FindWindowAtPoint(self.ClientToScreen(event.GetPoint())) + + :param bool `fullScreen`: False (default) to drag within tree only. + """ + + self._dragFullScreen = bool(fullScreen) + + # ----------------------------------------------------------------------------- # item status inquiries # ----------------------------------------------------------------------------- @@ -4455,13 +4569,16 @@ class CustomTreeCtrl(wx.ScrolledWindow): def IsVisible(self, item): """ Returns whether the item is visible or not (i.e., its hierarchy is expanded - enough to show the item). + enough to show the item, and it has not been hidden). :param `item`: an instance of :class:`GenericTreeItem`. :return: ``True`` if the item is visible, ``False`` if it is hidden. """ - + # Hidden items are never visible. + if item.IsHidden(): + return False + # An item is only visible if it's not a descendant of a collapsed item parent = item.GetParent() @@ -5582,6 +5699,39 @@ class CustomTreeCtrl(wx.ScrolledWindow): wnd.Hide() + def HideItemWindows(self, item): + """Hide all windows belonging to the item and its children.""" + wnd = item.GetWindow() + if wnd: + wnd.Hide() + for child in item.GetChildren(): + self.HideItemWindows(child) + + + def HideItem(self, item, hide=True): + """ + Hides/shows an item. + + :param `item`: an instance of :class:`GenericTreeItem`; + :param `hide`: ``True`` to hide the item, ``False`` to show it. + + :note: A hidden item always reports that it is collapsed and disabled. + """ + if hide == item.IsHidden(): + # Item already in correct state. Don't do anything. + return + item.Hide(hide) + + if hide is True and self._hasWindows: + # Hide all windows for this item and its children. + self.HideItemWindows(item) + + # Refresh the tree. + self.CalculatePositions() + self.Refresh() + self.AdjustMyScrollbars() + + def Unselect(self): """ Unselects the current selection. """ @@ -6073,7 +6223,13 @@ class CustomTreeCtrl(wx.ScrolledWindow): def CalculateLineHeight(self): - """ Calculates the height of a line. """ + """Calculates the base height for all lines in the tree. + + Only used if the TR_HAS_VARIABLE_ROW_HEIGHT style is not used. + This base line height gets adjusted to the max line height + of all items as they are displayed. All rows use this largest + height until this method is called to reset it. + """ dc = wx.ClientDC(self) self._lineHeight = dc.GetCharHeight() @@ -6362,6 +6518,11 @@ class CustomTreeCtrl(wx.ScrolledWindow): def AdjustMyScrollbars(self): """ Internal method used to adjust the :class:`ScrolledWindow` scrollbars. """ + if self._freezeCount: + # Skip if frozen. Set dirty flag to adjust when thawed. + self._dirty = True + return + if self._anchor: x, y = self._anchor.GetSize(0, 0, self) @@ -6864,6 +7025,9 @@ class CustomTreeCtrl(wx.ScrolledWindow): =============== ========================================= """ + # Don't paint hidden items. + if item.IsHidden(): + return y x = level*self._indent @@ -7268,7 +7432,7 @@ class CustomTreeCtrl(wx.ScrolledWindow): elif keyCode in (wx.WXK_RETURN, wx.WXK_SPACE, wx.WXK_NUMPAD_ENTER): - if not self.IsItemEnabled(self._current): + if not self._current or not self.IsItemEnabled(self._current): event.Skip() return @@ -7685,6 +7849,13 @@ class CustomTreeCtrl(wx.ScrolledWindow): :note: The rectangle coordinates are logical, not physical ones. So, for example, the `x` coordinate may be negative if the tree has a horizontal scrollbar and its position is not ``0``. + + .. warning:: The ``textOnly`` flag is currently ignored and this method + always returns the rectangle including the item's image, checkbox, + and window (if they exist) along with the item's text. A separator's + bounding box stretches the width of the entire client area. The height + may be 0 for newly added items until :meth:`CustomTreeCtrl.CalculateSize` + is called while the tree is not frozen. """ i = item @@ -7739,7 +7910,7 @@ class CustomTreeCtrl(wx.ScrolledWindow): def GetEditControl(self): """ - Returns a pointer to the edit :class:`TreeTextCtrl` if the item is being edited or + Returns a reference to the edit :class:`TreeTextCtrl` if the item is being edited or ``None`` otherwise (it is assumed that no more than one item may be edited simultaneously). """ @@ -7931,7 +8102,7 @@ class CustomTreeCtrl(wx.ScrolledWindow): # Create the custom draw image from the icons and the text of the item self._dragImage = DragImage(self, self._current) - self._dragImage.BeginDrag(wx.Point(0,0), self) + self._dragImage.BeginDrag(wx.Point(0,0), self, fullScreen=self._dragFullScreen) self._dragImage.Show() self._dragImage.Move(self.CalcScrolledPosition(*pt)) @@ -7939,6 +8110,10 @@ class CustomTreeCtrl(wx.ScrolledWindow): self._dragImage.Move(self.CalcScrolledPosition(*pt)) + if self._dragFullScreen is True: + # Don't highlight target items if dragging full-screen. + return + if self._countDrag == 0 and item: self._oldItem = item @@ -8222,6 +8397,15 @@ class CustomTreeCtrl(wx.ScrolledWindow): """ + if self._freezeCount: + # Skip calculate if frozen. Set dirty flag to do this when thawed. + self._dirty = True + return + if item.IsHidden(): + # Hidden items have a height of 0. + item.SetHeight(0) + return + attr = item.GetAttributes() if attr and attr.HasFont(): @@ -8336,6 +8520,9 @@ class CustomTreeCtrl(wx.ScrolledWindow): # set its position item.SetX(x+self._spacing) item.SetY(y) + # hidden items don't get a height (height=0). + if item.IsHidden(): + return y height = self.GetLineHeight(item) wnd = item.GetWindow() @@ -8369,6 +8556,10 @@ class CustomTreeCtrl(wx.ScrolledWindow): if not self._anchor: return + if self._freezeCount: + # Don't calculate positions if frozen as it is CPU intensive. + self._dirty = True + return self.absoluteWindows = {} @@ -8500,7 +8691,9 @@ class CustomTreeCtrl(wx.ScrolledWindow): for all controls so it is mostly just a hint to wxWidgets and not a mandatory directive. """ - + ## Note: We manage freezing ourselves because a normal call to + ## Freeze() also freezes all child item windows and for + ## some reason this can cause them to glitch out. self._freezeCount = self._freezeCount + 1 diff --git a/wx/lib/agw/hypertreelist.py b/wx/lib/agw/hypertreelist.py index d6cb424f..12302f3b 100644 --- a/wx/lib/agw/hypertreelist.py +++ b/wx/lib/agw/hypertreelist.py @@ -42,10 +42,23 @@ """ -:class:`~wx.lib.agw.hypertreelist.HyperTreeList` is a class that combines the -multicolumn features of a :class:`wx.ListCtrl` in report mode with the -hierarchical features of a :class:`wx.TreeCtrl`. Although it looks more like a -:class:`wx.ListCtrl`, the API tends to follow the API of :class:`wx.TreeCtrl`. +The ``hypertreelist`` module contains the :class:`~wx.lib.agw.hypertreelist.HyperTreeList` class +that combines the multicolumn features of a :class:`wx.ListCtrl` in report mode +with the hierarchical features of a :class:`wx.TreeCtrl`. Although it looks +more like a :class:`wx.ListCtrl`, the API tends to follow the API of +:class:`wx.TreeCtrl`. + +The :class:`~wx.lib.agw.hypertreelist.HyperTreeList` class actually consists of +two sub-windows: + +* :class:`TreeListHeaderWindow` displays the column headers. +* :class:`TreeListMainWindow` is the main tree list based off :class:`~wx.lib.agw.customtreectrl.CustomTreeCtrl`. + +These widgets can be obtained by the :meth:`~HyperTreeList.GetHeaderWindow` +and :meth:`~HyperTreeList.GetMainWindow` methods respectively althought this +shouldn't be needed in normal usage because most of the methods of the +sub-windows are monkey-patched and can be called directly from the +:class:`~wx.lib.agw.hypertreelist.HyperTreeList` itself. Description @@ -80,13 +93,14 @@ class supports: * Column headers are fully customizable in terms of icons, colour, font, alignment etc...; * Default selection style, gradient (horizontal/vertical) selection style and Windows Vista selection style; -* Customized drag and drop images built on the fly; +* Customized drag and drop images built on the fly (see :mod:`~wx.lib.agw.customtreectrl` for more info); * Setting the :class:`HyperTreeList` item buttons to a personalized imagelist; * Setting the :class:`HyperTreeList` check/radio item icons to a personalized imagelist; * Changing the style of the lines that connect the items (in terms of :class:`wx.Pen` styles); * Using an image as a :class:`HyperTreeList` background (currently only in "tile" mode); * Ellipsization of long items when the horizontal space is low, via the ``TR_ELLIPSIZE_LONG_ITEMS`` style (`New in version 0.9.3`). +* Hiding items And a lot more. Check the demo for an almost complete review of the functionalities. @@ -94,7 +108,7 @@ And a lot more. Check the demo for an almost complete review of the functionalit Base Functionalities ==================== -:class:`HyperTreeList` supports all the :class:`wx.TreeCtrl` styles, except: +:class:`HyperTreeList` supports all the :mod:`~wx.lib.agw.customtreectrl` styles, except: - ``TR_EXTENDED``: supports for this style is on the todo list (Am I sure of this?). @@ -130,30 +144,32 @@ Usage example:: class MyFrame(wx.Frame): - def __init__(self, parent): + def __init__(self): + wx.Frame.__init__(self, None, title="HyperTreeList Demo") - wx.Frame.__init__(self, parent, -1, "HyperTreeList Demo") + tree = HTL.HyperTreeList(self, agwStyle=wx.TR_DEFAULT_STYLE | + HTL.TR_ELLIPSIZE_LONG_ITEMS) + tree.AddColumn("Tree Column", width=200) + tree.AddColumn("Column 1", width=200, flag=wx.ALIGN_LEFT) + root = tree.AddRoot("Root") - tree_list = HTL.HyperTreeList(self) + parent = tree.AppendItem(root, "First child") + tree.SetItemText(parent, "Child of root", column=1) + + child = tree.AppendItem(parent, "First Grandchild") + tree.SetItemText(child, "Column1 Text", column=1) - tree_list.AddColumn("First column") - - root = tree_list.AddRoot("Root") - - parent = tree_list.AppendItem(root, "First child") - child = tree_list.AppendItem(parent, "First Grandchild") - - tree_list.AppendItem(root, "Second child") + child2 = tree.AppendItem(root, "Second child") + button = wx.Button(tree.GetMainWindow(), label="Button1") + tree.SetItemWindow(child2, button, column=1) # our normal wxApp-derived class, as usual - - app = wx.App(0) - - frame = MyFrame(None) + app = wx.App(redirect=False) + locale = wx.Locale(wx.LANGUAGE_DEFAULT) + frame = MyFrame() app.SetTopWindow(frame) frame.Show() - app.MainLoop() @@ -161,8 +177,8 @@ Usage example:: Events ====== -All the events supported by :class:`wx.TreeCtrl` and some from :class:`wx.ListCtrl` are -also available in :class:`HyperTreeList`, with a few exceptions: +All the events supported by :mod:`~wx.lib.agw.customtreectrl` are also +available in :class:`HyperTreeList`, with a few exceptions: - ``EVT_TREE_GET_INFO`` (don't know what this means); - ``EVT_TREE_SET_INFO`` (don't know what this means); @@ -192,34 +208,40 @@ Supported Platforms Window Styles ============= -This class supports the following window styles: +The :class:`HyperTreeList` class takes a regular wxPython ``style`` and an +extended ``agwStyle``. The ``style`` can be used with normal wxPython styles +such as ``wx.WANTS_CHARS`` while the ``agwStyle`` specifies the behavior of the +tree itself. It supports the following ``agwStyle`` flags: -============================== =========== ================================================== -Window Styles Hex Value Description -============================== =========== ================================================== -``TR_NO_BUTTONS`` 0x0 For convenience to document that no buttons are to be drawn. -``TR_SINGLE`` 0x0 For convenience to document that only one item may be selected at a time. Selecting another item causes the current selection, if any, to be deselected. This is the default. -``TR_HAS_BUTTONS`` 0x1 Use this style to show + and - buttons to the left of parent items. -``TR_NO_LINES`` 0x4 Use this style to hide vertical level connectors. -``TR_LINES_AT_ROOT`` 0x8 Use this style to show lines between root nodes. Only applicable if ``TR_HIDE_ROOT`` is set and ``TR_NO_LINES`` is not set. -``TR_DEFAULT_STYLE`` 0x9 The set of flags that are closest to the defaults for the native control for a particular toolkit. -``TR_TWIST_BUTTONS`` 0x10 Use old Mac-twist style buttons. -``TR_MULTIPLE`` 0x20 Use this style to allow a range of items to be selected. If a second range is selected, the current range, if any, is deselected. -``TR_EXTENDED`` 0x40 Use this style to allow disjoint items to be selected. (Only partially implemented; may not work in all cases). -``TR_HAS_VARIABLE_ROW_HEIGHT`` 0x80 Use this style to cause row heights to be just big enough to fit the content. If not set, all rows use the largest row height. The default is that this flag is unset. -``TR_EDIT_LABELS`` 0x200 Use this style if you wish the user to be able to edit labels in the tree control. -``TR_ROW_LINES`` 0x400 Use this style to draw a contrasting border between displayed rows. -``TR_HIDE_ROOT`` 0x800 Use this style to suppress the display of the root node, effectively causing the first-level nodes to appear as a series of root nodes. -``TR_COLUMN_LINES`` 0x1000 Use this style to draw a contrasting border between displayed columns. -``TR_FULL_ROW_HIGHLIGHT`` 0x2000 Use this style to have the background colour and the selection highlight extend over the entire horizontal row of the tree control window. -``TR_AUTO_CHECK_CHILD`` 0x4000 Only meaningful for checkbox-type items: when a parent item is checked/unchecked its children are checked/unchecked as well. -``TR_AUTO_TOGGLE_CHILD`` 0x8000 Only meaningful for checkbox-type items: when a parent item is checked/unchecked its children are toggled accordingly. -``TR_AUTO_CHECK_PARENT`` 0x10000 Only meaningful for checkbox-type items: when a child item is checked/unchecked its parent item is checked/unchecked as well. -``TR_ALIGN_WINDOWS`` 0x20000 Flag used to align windows (in items with windows) at the same horizontal position. -``TR_NO_HEADER`` 0x40000 Use this style to hide the columns header. -``TR_ELLIPSIZE_LONG_ITEMS`` 0x80000 Flag used to ellipsize long items when the horizontal space for :class:`HyperTreeList` columns is low. -``TR_VIRTUAL`` 0x100000 :class:`HyperTreeList` will have virtual behaviour. -============================== =========== ================================================== +================================= =========== ================================================== +Window agwStyle Flags Hex Value Description +================================= =========== ================================================== +**wx.TR_DEFAULT_STYLE** *varies* The set of flags that are closest to the defaults for the native control for a particular toolkit. Should always be used. +``wx.TR_NO_BUTTONS`` 0x0 For convenience to document that no buttons are to be drawn. +``wx.TR_SINGLE`` 0x0 For convenience to document that only one item may be selected at a time. Selecting another item causes the current selection, if any, to be deselected. This is the default. +``wx.TR_HAS_BUTTONS`` 0x1 Use this style to show + and - buttons to the left of parent items. +``wx.TR_NO_LINES`` 0x4 Use this style to hide vertical level connectors. +``wx.TR_LINES_AT_ROOT`` 0x8 Use this style to show lines between root nodes. Only applicable if ``TR_HIDE_ROOT`` is set and ``TR_NO_LINES`` is not set. +``wx.TR_TWIST_BUTTONS`` 0x10 Use old Mac-twist style buttons. +``wx.TR_MULTIPLE`` 0x20 Use this style to allow a range of items to be selected. If a second range is selected, the current range, if any, is deselected. +``wx.TR_HAS_VARIABLE_ROW_HEIGHT`` 0x80 Use this style to cause row heights to be just big enough to fit the content. If not set, all rows use the largest row height. The default is that this flag is unset. +``wx.TR_EDIT_LABELS`` 0x200 Use this style if you wish the user to be able to edit labels in the tree control. +``wx.TR_ROW_LINES`` 0x400 Use this style to draw a contrasting border between displayed rows. +``wx.TR_HIDE_ROOT`` 0x800 Use this style to suppress the display of the root node, effectively causing the first-level nodes to appear as a series of root nodes. +``wx.TR_FULL_ROW_HIGHLIGHT`` 0x2000 Use this style to have the background colour and the selection highlight extend over the entire horizontal row of the tree control window. +**Styles from hypertreelist:** +``TR_EXTENDED`` 0x40 Use this style to allow disjoint items to be selected. (Only partially implemented; may not work in all cases). +``TR_COLUMN_LINES`` 0x1000 Use this style to draw a contrasting border between displayed columns. +``TR_AUTO_CHECK_CHILD`` 0x4000 Only meaningful for checkbox-type items: when a parent item is checked/unchecked its children are checked/unchecked as well. +``TR_AUTO_TOGGLE_CHILD`` 0x8000 Only meaningful for checkbox-type items: when a parent item is checked/unchecked its children are toggled accordingly. +``TR_AUTO_CHECK_PARENT`` 0x10000 Only meaningful for checkbox-type items: when a child item is checked/unchecked its parent item is checked/unchecked as well. +``TR_ALIGN_WINDOWS`` 0x20000 Has no effect in HyperTreeList. +``TR_NO_HEADER`` 0x40000 Use this style to hide the columns header. +``TR_ELLIPSIZE_LONG_ITEMS`` 0x80000 Flag used to ellipsize long items when the horizontal space for :class:`HyperTreeList` columns is low. +``TR_VIRTUAL`` 0x100000 :class:`HyperTreeList` will have virtual behaviour. +================================= =========== ================================================== + +See :mod:`~wx.lib.agw.customtreectrl` for more information on styles. Events Processing @@ -235,7 +257,7 @@ Event Name Description ``EVT_LIST_COL_DRAGGING`` The divider between columns is being dragged. ``EVT_LIST_COL_END_DRAG`` A column has been resized by the user. ``EVT_LIST_COL_RIGHT_CLICK`` A column has been right-clicked. -``EVT_TREE_BEGIN_DRAG`` Begin dragging with the left mouse button. +``EVT_TREE_BEGIN_DRAG`` Begin dragging with the left mouse button. See :mod:`wx.lib.agw.customtreectrl` Drag/Drop section for more information. ``EVT_TREE_BEGIN_LABEL_EDIT`` Begin editing a label. This can be prevented by calling :meth:`TreeEvent.Veto() `. ``EVT_TREE_BEGIN_RDRAG`` Begin dragging with the right mouse button. ``EVT_TREE_DELETE_ITEM`` Delete an item. @@ -456,7 +478,8 @@ class TreeListColumnInfo(object): self._edit = input._edit self._colour = input._colour self._font = input._font - + self._sort_icon = wx.HDR_SORT_ICON_NONE + self._sort_icon_colour = None # get/set def GetText(self): @@ -617,6 +640,33 @@ class TreeListColumnInfo(object): return self._font + def GetSortIcon(self): + """ Returns the column sort icon displayed in the header. """ + + return self._sort_icon + + + def SetSortIcon(self, sortIcon, colour=None): + """ + Sets the column sort icon displayed in the header. + + :param `sortIcon`: the sort icon to display, one of ``wx.HDR_SORT_ICON_NONE``, + ``wx.HDR_SORT_ICON_UP``, ``wx.HDR_SORT_ICON_DOWN``. + :param `colour`: the colour of the sort icon as a wx.Colour. Optional. + Set to ``None`` to restore native colour. + """ + + self._sort_icon = sortIcon + self._sort_icon_colour = colour + return self + + + def GetSortIconColour(self): + """Return the colour of the sort icon (``None`` = Default). """ + + return self._sort_icon_colour + + #----------------------------------------------------------------------------- # TreeListHeaderWindow (internal) #----------------------------------------------------------------------------- @@ -665,7 +715,7 @@ class TreeListHeaderWindow(wx.Window): :param `buffered`: ``True`` to use double-buffering, ``False`` otherwise. - :note: Currently we are using double-buffering only on Windows XP. + :note: Currently double-buffering is only enabled by default for Windows XP. """ self._buffered = buffered @@ -886,6 +936,10 @@ class TreeListHeaderWindow(wx.Window): params.m_labelText = column.GetText() params.m_labelAlignment = column.GetAlignment() + sortIcon = column.GetSortIcon() + sortIconColour = column.GetSortIconColour() + if sortIconColour: + params.m_arrowColour = sortIconColour image = column.GetImage() imageList = self._owner.GetImageList() @@ -897,7 +951,7 @@ class TreeListHeaderWindow(wx.Window): self._headerCustomRenderer.DrawHeaderButton(dc, rect, flags, params) else: wx.RendererNative.Get().DrawHeaderButton(self, dc, rect, flags, - wx.HDR_SORT_ICON_NONE, params) + sortIcon, params) # Fill up any unused space to the right of the columns if x < w: @@ -1144,6 +1198,9 @@ class TreeListHeaderWindow(wx.Window): # window, so why should it get positions relative to it? le.m_pointDrag.y -= self.GetSize().y le.m_col = self._column + # Set point/column with Setters for Phoenix compatibility. + le.SetPoint(le.m_pointDrag) + le.SetColumn(self._column) parent.GetEventHandler().ProcessEvent(le) @@ -1279,6 +1336,30 @@ class TreeListHeaderWindow(wx.Window): self._owner._dirty = True + def SetSortIcon(self, column, sortIcon, colour=None): + """ + Sets the sort icon to be displayed in the column header. + + The sort icon will be displayed in the specified column number + and all other columns will have the sort icon cleared. + + :param `column`: an integer specifying the column index; + :param `sortIcon`: the sort icon to display, one of ``wx.HDR_SORT_ICON_NONE``, + ``wx.HDR_SORT_ICON_UP``, ``wx.HDR_SORT_ICON_DOWN``. + :param `colour`: the colour of the sort icon as a wx.Colour. Optional. + Set to ``None`` to restore native colour. + """ + if column < 0 or column >= self.GetColumnCount(): + raise Exception("Invalid column") + + for num in range(self.GetColumnCount()): + if num == column: + self.GetColumn(num).SetSortIcon(sortIcon, colour) + else: + self.GetColumn(num).SetSortIcon(wx.HDR_SORT_ICON_NONE, colour) + self.Refresh() + + # --------------------------------------------------------------------------- # TreeListItem # --------------------------------------------------------------------------- @@ -1331,7 +1412,6 @@ class TreeListItem(GenericTreeItem): self._col_images = [] self._owner = mainWin - self._hidden = False # We don't know the height here yet. self._text_x = 0 @@ -1345,23 +1425,6 @@ class TreeListItem(GenericTreeItem): self.SetWindow(wnd) - def IsHidden(self): - """ Returns whether the item is hidden or not. """ - - return self._hidden - - - def Hide(self, hide): - """ - Hides/shows the :class:`TreeListItem`. - - :param `hide`: ``True`` to hide the item, ``False`` to show it. - :note: Always use :meth:`~HyperTreeList.HideItem` instead to update the tree properly. - """ - - self._hidden = hide - - def DeleteChildren(self, tree): """ Deletes the item children. @@ -1404,6 +1467,8 @@ class TreeListItem(GenericTreeItem): :param `level`: the item's level inside the tree hierarchy. :see: :meth:`TreeListMainWindow.HitTest() ` method for the flags explanation. + + :return: A 3-tuple of (item, flags, column). The item may be ``None``. """ # Hidden items are never evaluated. if self.IsHidden(): @@ -1593,7 +1658,8 @@ class TreeListItem(GenericTreeItem): :param `column`: if not ``None``, an integer specifying the column index. If it is ``None``, the main column index is used; :param `text`: a string specifying the new item label. - :note: Call :meth:`~HyperTreeList.SetItemText` instead to refresh the tree properly. + + :note: Call :meth:`~TreeListMainWindow.SetItemText` instead to refresh the tree properly. """ column = (column is not None and [column] or [self._owner.GetMainColumn()])[0] @@ -1615,7 +1681,8 @@ class TreeListItem(GenericTreeItem): :param `which`: the item state. :see: :meth:`~TreeListItem.GetImage` for a list of valid item states. - :note: Call :meth:`~HyperTreeList.SetItemImage` instead to refresh the tree properly. + + :note: Call :meth:`~TreeListMainWindow.SetItemImage` instead to refresh the tree properly. """ column = (column is not None and [column] or [self._owner.GetMainColumn()])[0] @@ -1653,7 +1720,8 @@ class TreeListItem(GenericTreeItem): :param `wnd`: a non-toplevel window to be displayed next to the item; :param `column`: if not ``None``, an integer specifying the column index. If it is ``None``, the main column index is used. - :note: Always use :meth:`~HyperTreeList.SetItemWindow` instead to update the tree properly. + + :note: Always use :meth:`~TreeListMainWindow.SetItemWindow` instead to update the tree properly. """ column = (column is not None and [column] or [self._owner.GetMainColumn()])[0] @@ -1693,6 +1761,8 @@ class TreeListItem(GenericTreeItem): treectrl = self._owner select = treectrl.GetSelection() + # Refresh header window since child focus could have moved scrollbars. + treectrl.GetParent().GetHeaderWindow().Refresh() # If the window is associated to an item that currently is selected # (has focus) we don't kill the focus. Otherwise we do it. @@ -2114,35 +2184,8 @@ class TreeListMainWindow(CustomTreeCtrl): :param `size`: the control size. A value of (-1, -1) indicates a default size, chosen by either the windowing system or wxPython, depending on platform; :param `style`: the underlying :class:`ScrolledWindow` style; - :param `agwStyle`: the AGW-specific :class:`TreeListMainWindow` window style. This can be a - combination of the following bits: - - ============================== =========== ================================================== - Window Styles Hex Value Description - ============================== =========== ================================================== - ``TR_NO_BUTTONS`` 0x0 For convenience to document that no buttons are to be drawn. - ``TR_SINGLE`` 0x0 For convenience to document that only one item may be selected at a time. Selecting another item causes the current selection, if any, to be deselected. This is the default. - ``TR_HAS_BUTTONS`` 0x1 Use this style to show + and - buttons to the left of parent items. - ``TR_NO_LINES`` 0x4 Use this style to hide vertical level connectors. - ``TR_LINES_AT_ROOT`` 0x8 Use this style to show lines between root nodes. Only applicable if ``TR_HIDE_ROOT`` is set and ``TR_NO_LINES`` is not set. - ``TR_DEFAULT_STYLE`` 0x9 The set of flags that are closest to the defaults for the native control for a particular toolkit. - ``TR_TWIST_BUTTONS`` 0x10 Use old Mac-twist style buttons. - ``TR_MULTIPLE`` 0x20 Use this style to allow a range of items to be selected. If a second range is selected, the current range, if any, is deselected. - ``TR_EXTENDED`` 0x40 Use this style to allow disjoint items to be selected. (Only partially implemented; may not work in all cases). - ``TR_HAS_VARIABLE_ROW_HEIGHT`` 0x80 Use this style to cause row heights to be just big enough to fit the content. If not set, all rows use the largest row height. The default is that this flag is unset. - ``TR_EDIT_LABELS`` 0x200 Use this style if you wish the user to be able to edit labels in the tree control. - ``TR_ROW_LINES`` 0x400 Use this style to draw a contrasting border between displayed rows. - ``TR_HIDE_ROOT`` 0x800 Use this style to suppress the display of the root node, effectively causing the first-level nodes to appear as a series of root nodes. - ``TR_FULL_ROW_HIGHLIGHT`` 0x2000 Use this style to have the background colour and the selection highlight extend over the entire horizontal row of the tree control window. - ``TR_AUTO_CHECK_CHILD`` 0x4000 Only meaningful for checkbox-type items: when a parent item is checked/unchecked its children are checked/unchecked as well. - ``TR_AUTO_TOGGLE_CHILD`` 0x8000 Only meaningful for checkbox-type items: when a parent item is checked/unchecked its children are toggled accordingly. - ``TR_AUTO_CHECK_PARENT`` 0x10000 Only meaningful for checkbox-type items: when a child item is checked/unchecked its parent item is checked/unchecked as well. - ``TR_ALIGN_WINDOWS`` 0x20000 Flag used to align windows (in items with windows) at the same horizontal position. - ``TR_NO_HEADER`` 0x40000 Use this style to hide the columns header. - ``TR_ELLIPSIZE_LONG_ITEMS`` 0x80000 Flag used to ellipsize long items when the horizontal space for :class:`~wx.lib.agw.customtreectrl.CustomTreeCtrl` is low. - ``TR_VIRTUAL`` 0x100000 :class:`HyperTreeList` will have virtual behaviour. - ============================== =========== ================================================== - + :param `agwStyle`: can be a combination of various bits. See + :mod:`~wx.lib.agw.hypertreelist` for a full list of flags. :param `validator`: window validator; :param `name`: window name. """ @@ -2297,9 +2340,9 @@ class TreeListMainWindow(CustomTreeCtrl): :param `column`: if not ``None``, an integer specifying the column index. If it is ``None``, the main column index is used. - :note: The window parent should not be the :class:`HyperTreeList` itself, but actually - an instance of :class:`TreeListMainWindow`. The current solution here is to reparent - the window to this class. + :note: The window being added should have its parent set to the :class:`TreeListMainWindow` + which can be obtained with :meth:`~HyperTreeList.GetHeaderWindow`. If this is not the case + the window will be re-parented which may cause some flicker. """ # Reparent the window to ourselves @@ -2370,34 +2413,10 @@ class TreeListMainWindow(CustomTreeCtrl): Returns whether the item is visible or not. :param `item`: an instance of :class:`TreeListItem`; + + :note: This method is renamed from :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.IsVisible` """ - if item.IsHidden(): - return False - # An item is only visible if it's not a descendant of a collapsed item - parent = item.GetParent() - - while parent: - - if not parent.IsExpanded(): - return False - - parent = parent.GetParent() - - startX, startY = self.GetViewStart() - clientSize = self.GetClientSize() - - rect = self.GetBoundingRect(item) - - if not rect: - return False - if rect.GetWidth() == 0 or rect.GetHeight() == 0: - return False - if rect.GetBottom() < 0 or rect.GetTop() > clientSize.y: - return False - if rect.GetRight() < 0 or rect.GetLeft() > clientSize.x: - return False - - return True + return self.IsVisible(item) def GetPrevChild(self, item, cookie): @@ -2455,7 +2474,7 @@ class TreeListMainWindow(CustomTreeCtrl): return None if not self.HasAGWFlag(TR_HIDE_ROOT): - if self.IsVisible(root): + if self.IsItemVisible(root): return root return self.GetNextVisible(root) @@ -2687,6 +2706,18 @@ class TreeListMainWindow(CustomTreeCtrl): wnd.Hide() + def HideItemWindows(self, item): + """Hides all windows belonging to given item and its children.""" + # Hide windows for this item. + for column in range(self.GetColumnCount()): + wnd = item.GetWindow(column) + if wnd and wnd.IsShown(): + wnd.Hide() + # Hide its child windows. + for child in item.GetChildren(): + self.HideItemWindows(child) + + def EnableItem(self, item, enable=True, torefresh=True): """ Enables/disables an item. @@ -2729,9 +2760,12 @@ class TreeListMainWindow(CustomTreeCtrl): def GetCurrentItem(self): - """ Returns the current item. """ + """Returns the current item. - return self._current + This is the same as :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.GetSelection`. + """ + + return self.GetSelection() def GetColumnCount(self): @@ -2827,6 +2861,11 @@ class TreeListMainWindow(CustomTreeCtrl): def AdjustMyScrollbars(self): """ Internal method used to adjust the :class:`ScrolledWindow` scrollbars. """ + if self._freezeCount: + # Skip if frozen. Set dirty flag to adjust when thawed. + self._dirty = True + return + if self._anchor: xUnit, yUnit = self.GetScrollPixelsPerUnit() if xUnit == 0: @@ -3157,11 +3196,6 @@ class TreeListMainWindow(CustomTreeCtrl): item.GetY() + ((total_h > hcheck) and [(total_h-hcheck)//2] or [0])[0]+1, wx.IMAGELIST_DRAW_TRANSPARENT) - text_w, text_h, dummy = dc.GetFullMultiLineTextExtent(text) - text_extraH = (total_h > text_h and [(total_h - text_h)//2] or [0])[0] - text_y = item.GetY() + text_extraH - textrect = wx.Rect(text_x, text_y, text_w, text_h) - if self.HasAGWFlag(TR_ELLIPSIZE_LONG_ITEMS): if i == self.GetMainColumn(): maxsize = col_w - text_x - _MARGIN @@ -3170,6 +3204,11 @@ class TreeListMainWindow(CustomTreeCtrl): text = ChopText(dc, text, maxsize) + text_w, text_h, dummy = dc.GetFullMultiLineTextExtent(text) + text_extraH = (total_h > text_h and [(total_h - text_h)//2] or [0])[0] + text_y = item.GetY() + text_extraH + textrect = wx.Rect(text_x, text_y, text_w, text_h) + if not item.IsEnabled(): foreground = dc.GetTextForeground() dc.SetTextForeground(self._disabledColour) @@ -3186,9 +3225,23 @@ class TreeListMainWindow(CustomTreeCtrl): wnd = item.GetWindow(i) if wnd: if text_w == 0: - wndx = text_x + # No text. Honor column alignment for window. + if alignment == wx.ALIGN_RIGHT: + # text_x = right edge of window + wndx = text_x - wnd.GetSize().width + elif alignment == wx.ALIGN_CENTER: + # text_x = center of window + wndx = text_x - (wnd.GetSize().width // 2) + else: + # text_x = left of window (default). + wndx = text_x else: - wndx = text_x + text_w + 2*_MARGIN + if alignment == wx.ALIGN_RIGHT: + # Place window left of text with 2*_MARGIN in between. + wndx = text_x - 2*_MARGIN - wnd.GetSize().width + else: + # Place window at end of text plus 2*_MARGIN (default). + wndx = text_x + text_w + 2*_MARGIN xa, ya = self.CalcScrolledPosition(0, item.GetY()) wndx += xa if item.GetHeight() > item.GetWindowSize(i)[1]: @@ -3218,10 +3271,13 @@ class TreeListMainWindow(CustomTreeCtrl): :param `y`: the current vertical position in the :class:`ScrolledWindow`; :param `x_maincol`: the horizontal position of the main column. """ - + # Don't paint hidden items. if item.IsHidden(): return y, x_maincol + # Save window text color. + colText = wx.Colour(*dc.GetTextForeground()) + # Handle hide root (only level 0) if self.HasAGWFlag(wx.TR_HIDE_ROOT) and level == 0: for child in item.GetChildren(): @@ -3364,7 +3420,7 @@ class TreeListMainWindow(CustomTreeCtrl): # restore DC objects dc.SetBrush(wx.WHITE_BRUSH) dc.SetPen(self._dottedPen) - dc.SetTextForeground(wx.BLACK) + dc.SetTextForeground(colText) if item.IsExpanded(): @@ -3707,11 +3763,18 @@ class TreeListMainWindow(CustomTreeCtrl): if not self._dragImage: # Create the custom draw image from the icons and the text of the item self._dragImage = DragImage(self, self._current or item) - self._dragImage.BeginDrag(wx.Point(0,0), self) + # BeginDrag captures mouse. GTK cannot capture mouse twice. + if self.HasCapture() is True: + self.ReleaseMouse() + self._dragImage.BeginDrag(wx.Point(0,0), self, fullScreen=self._dragFullScreen) self._dragImage.Show() self._dragImage.Move(p) + if self._dragFullScreen is True: + # Don't highlight target items if dragging full-screen. + return + if self._countDrag == 0 and item: self._oldItem = self._current self._oldSelection = self._current @@ -3765,6 +3828,7 @@ class TreeListMainWindow(CustomTreeCtrl): # we're going to drag this item self._isDragging = True + self._left_down_selection = True # Stop DoSelect on drag end. if not self.HasCapture(): self.CaptureMouse() self.RefreshSelected() @@ -3966,6 +4030,10 @@ class TreeListMainWindow(CustomTreeCtrl): :param `item`: an instance of :class:`TreeListItem`; :param `dc`: an instance of :class:`wx.DC`. """ + if self._freezeCount: + # Skip calculate if frozen. Set dirty flag to do this when thawed. + self._dirty = True + return if item.IsHidden(): # Hidden items have a height of 0. item.SetHeight(0) @@ -4107,6 +4175,10 @@ class TreeListMainWindow(CustomTreeCtrl): if not self._anchor: return + if self._freezeCount: + # Skip calculate if frozen. Set dirty flag to do this when thawed. + self._dirty = True + return dc = wx.ClientDC(self) self.PrepareDC(dc) @@ -4134,9 +4206,16 @@ class TreeListMainWindow(CustomTreeCtrl): """ dc = wx.ClientDC(self) + oldtext = item.GetText(column) item.SetText(column, text) - self.CalculateSize(item, dc) - self.RefreshLine(item) + # Avoid Calculating tree unless number of lines changed (slow). + if oldtext.count('\n') != text.count('\n'): + self.CalculatePositions() + self.Refresh() + self.AdjustMyScrollbars() + else: + self.CalculateSize(item, dc) + self.RefreshLine(item) def GetItemText(self, item, column=None): @@ -4185,13 +4264,16 @@ class TreeListMainWindow(CustomTreeCtrl): # calculate width width = w + 2*_MARGIN if column == self.GetMainColumn(): - width += _MARGIN + width += 2*_MARGIN if self.HasAGWFlag(wx.TR_LINES_AT_ROOT): width += _LINEATROOT if self.HasButtons(): width += self._btnWidth + _LINEATROOT if item.GetCurrentImage() != _NO_IMAGE: width += self._imgWidth + if item.GetType() != 0 and self._imageListCheck: + wcheck, hcheck = self._imageListCheck.GetSize(item.GetType()) + width += wcheck # count indent level level = 0 @@ -4260,28 +4342,12 @@ class TreeListMainWindow(CustomTreeCtrl): return max(10, width) # Prevent zero column width - def HideItem(self, item, hide=True): - """ - Hides/shows an item. - - :param `item`: an instance of :class:`TreeListItem`; - :param `hide`: ``True`` to hide the item, ``False`` to show it. - """ - - item.Hide(hide) - # Recalculate positions and hide child windows. - self.CalculatePositions() - if self._hasWindows: - self.HideWindows() - # Refresh the tree. - self.Refresh() - self.AdjustMyScrollbars() - - #---------------------------------------------------------------------------- # TreeListCtrl - the multicolumn tree control #---------------------------------------------------------------------------- +## Monkey patch methods. Be sure to modify the docstring for HyperTreeList +## to reflect any changes to this list. _methods = ["GetIndent", "SetIndent", "GetSpacing", "SetSpacing", "GetImageList", "GetStateImageList", "GetButtonsImageList", "AssignImageList", "AssignStateImageList", "AssignButtonsImageList", "SetImageList", "SetButtonsImageList", "SetStateImageList", @@ -4290,7 +4356,7 @@ _methods = ["GetIndent", "SetIndent", "GetSpacing", "SetSpacing", "GetImageList" "SetItemHasChildren", "SetItemBackgroundColour", "SetItemFont", "IsItemVisible", "HasChildren", "IsExpanded", "IsSelected", "IsBold", "GetCount", "GetChildrenCount", "GetRootItem", "GetSelection", "GetSelections", "GetItemParent", "GetFirstChild", "GetNextChild", "GetPrevChild", "GetLastChild", "GetNextSibling", - "GetPrevSibling", "GetNext", "GetFirstExpandedItem", "GetNextExpanded", "GetPrevExpanded", + "GetPrevSibling", "GetNext", "GetFirstExpandedItem", "GetNextExpanded", "GetPrevExpanded", "GetFocusedItem", "GetFirstVisibleItem", "GetNextVisible", "GetPrevVisible", "AddRoot", "PrependItem", "InsertItem", "AppendItem", "Delete", "DeleteChildren", "DeleteRoot", "Expand", "ExpandAll", "ExpandAllChildren", "Collapse", "CollapseAndReset", "Toggle", "Unselect", "UnselectAll", "SelectItem", "SelectAll", @@ -4307,8 +4373,8 @@ _methods = ["GetIndent", "SetIndent", "GetSpacing", "SetSpacing", "GetImageList" "CheckChilds", "CheckSameLevel", "GetItemWindowEnabled", "SetItemWindowEnabled", "GetItemType", "IsDescendantOf", "SetItemHyperText", "IsItemHyperText", "SetItemBold", "SetItemDropHighlight", "SetItemItalic", "GetEditControl", "ShouldInheritColours", "GetItemWindow", "SetItemWindow", "DeleteItemWindow", "SetItemTextColour", - "HideItem", "DeleteAllItems", "ItemHasChildren", "ToggleItemSelection", "SetItemType", "GetCurrentItem", - "SetItem3State", "SetItem3StateValue", "GetItem3StateValue", "IsItem3State", "GetPrev", + "HideItem", "DeleteAllItems", "ItemHasChildren", "ToggleItemSelection", "SetItemType", "GetDragFullScreen", "SetDragFullScreen", + "GetCurrentItem", "SetItem3State", "SetItem3StateValue", "GetItem3StateValue", "IsItem3State", "GetPrev", "GetNextShown", "GetPrevShown"] @@ -4320,16 +4386,174 @@ class HyperTreeList(wx.Control): as it is a full owner-drawn tree-list control. It manages two widgets internally: - :class:`TreeListHeaderWindow` - :class:`TreeListMainWindow` based off :class:`CustomTreeCtrl` + + * :class:`TreeListHeaderWindow` displays the column headers. + * :class:`TreeListMainWindow` is the main tree list based off :class:`~wx.lib.agw.customtreectrl.CustomTreeCtrl`. + These widgets can be obtained by the :meth:`~HyperTreeList.GetHeaderWindow` and :meth:`~HyperTreeList.GetMainWindow` methods respectively althought this shouldn't be needed in normal usage. - Please note that although the methods are not explicitly defined or - documented here, most of the API in :class:`TreeListMainWindow` and - :class:`CustomTreeCtrl` can be called directly from :class:`HyperTreeList` - via monkey-patched delegates. + Please note that in addition to the defined methods of :class:`HyperTreeList` + many more methods are delegated to the internal :class:`TreeListMainWindow` + and its subclass :class:`~wx.lib.agw.customtreectrl.CustomTreeCtrl`. These + methods can be called directly from the ``HyperTreeList`` class: + + ================================================================================ ================================================================================== + :meth:`~wx.lib.agw.hypertreelist.TreeListMainWindow.AddRoot` Adds a root item to the :class:`TreeListMainWindow`. + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.AppendItem` Appends an item as a last child of its parent. + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.AssignButtonsImageList` Assigns the button image list. + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.AssignImageList` Assigns the normal image list. + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.AssignStateImageList` Assigns the state image list. + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.AutoCheckChild` Transverses the tree and checks/unchecks the items. + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.AutoCheckParent` Traverses up the tree and checks/unchecks parent items. + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.AutoToggleChild` Transverses the tree and toggles the items. + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.CheckChilds` Programatically check/uncheck item children. + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.CheckItem` Actually checks/uncheks an item, sending the two related events. + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.CheckItem2` Used internally to avoid ``EVT_TREE_ITEM_CHECKED`` events. + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.CheckSameLevel` Uncheck radio items which are on the same level of the checked one. + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.Collapse` Collapse an item, sending the two related events. + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.CollapseAndReset` Collapse the given item and deletes its children. + :meth:`~wx.lib.agw.hypertreelist.TreeListMainWindow.Delete` Deletes an item. + :meth:`~wx.lib.agw.hypertreelist.TreeListMainWindow.DeleteAllItems` Delete all items in the :class:`TreeListMainWindow`. + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.DeleteChildren` Delete all the item's children. + :meth:`~wx.lib.agw.hypertreelist.TreeListMainWindow.DeleteItemWindow` Deletes the window in the column associated to an item (if any). + :meth:`~wx.lib.agw.hypertreelist.TreeListMainWindow.DeleteRoot` Removes the tree root item (and subsequently all the items in the tree). + :meth:`~wx.lib.agw.hypertreelist.TreeListMainWindow.EditLabel` Starts editing an item label. + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.EnableChildren` Enables/disables the item children. + :meth:`~wx.lib.agw.hypertreelist.TreeListMainWindow.EnableItem` Enables/disables an item. + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.EnableSelectionGradient` Globally enables/disables drawing of gradient selections. + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.EnableSelectionVista` Globally enables/disables drawing of Windows Vista selections. + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.EnsureVisible` Scrolls and/or expands items to ensure that the given item is visible. + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.Expand` Expands an item, sending the two related events. + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.ExpandAll` Expands all :class:`TreeListMainWindow` items. + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.ExpandAllChildren` Expands all the items children of the input item. + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.FindItem` Finds the first item starting with the given prefix after the given parent. + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.GetBackgroundImage` Returns the :class:`TreeListMainWindow` background image (if any). + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.GetBorderPen` Returns the pen used to draw the selected item border. + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.GetBoundingRect` Retrieves the rectangle bounding the item. + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.GetButtonsImageList` Returns the buttons image list associated with :class:`TreeListMainWindow`. + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.GetChildrenCount` Returns the item children count. + :meth:`~wx.lib.agw.hypertreelist.TreeListMainWindow.GetColumnCount` Returns the total number of columns. + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.GetConnectionPen` Returns the pen used to draw the connecting lines between items. + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.GetCount` Returns the global number of items in the tree. + :meth:`~wx.lib.agw.hypertreelist.TreeListMainWindow.GetCurrentItem` Returns the current item. Simply calls :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.GetSelection`. + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.GetDisabledColour` Returns the colour for items in a disabled state. + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.GetDragFullScreen` Returns whether built-in drag/drop will be full screen or not. + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.GetEditControl` Returns a reference to the edit :class:`~wx.lib.agw.customtreectrl.TreeTextCtrl` if the item is being edited. + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.GetFirstChild` Returns the item's first child and an integer value 'cookie'. + :meth:`~wx.lib.agw.hypertreelist.TreeListMainWindow.GetFirstExpandedItem` Returns the first item which is in the expanded state. + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.GetFirstGradientColour` Returns the first gradient colour for gradient-style selections. + :meth:`~wx.lib.agw.hypertreelist.TreeListMainWindow.GetFirstVisibleItem` Returns the first visible item. + GetFocusedItem Another name for :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.GetSelection` + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.GetGradientStyle` Returns the gradient style for gradient-style selections. + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.GetHilightFocusColour` Returns the colour used to highlight focused selected items. + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.GetHilightNonFocusColour` Returns the colour used to highlight unfocused selected items. + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.GetHyperTextFont` Returns the font used to render hypertext items. + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.GetHyperTextNewColour` Returns the colour used to render a non-visited hypertext item. + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.GetHyperTextVisitedColour` Returns the colour used to render a visited hypertext item. + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.GetImageList` Returns the normal image list associated with :class:`TreeListMainWindow`. + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.GetImageListCheck` Returns the ``wx.ImageList`` used for the check/radio buttons in :class:`TreeListMainWindow`. + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.GetIndent` Returns the item indentation, in pixels. + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.GetItem3StateValue` Gets the state of a 3-state checkbox item. + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.GetItemBackgroundColour` Returns the item background colour. + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.GetItemFont` Returns the item font. + :meth:`~wx.lib.agw.hypertreelist.TreeListMainWindow.GetItemImage` Returns the item image. + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.GetItemParent` Returns the item parent (can be ``None`` for root items). + GetItemPyData Another name for :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.GetPyData` + :meth:`~wx.lib.agw.hypertreelist.TreeListMainWindow.GetItemText` Returns the item text label. + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.GetItemTextColour` Returns the item text colour or separator horizontal line colour. + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.GetItemType` Returns the item type. + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.GetItemVisited` Returns whether an hypertext item was visited. + :meth:`~wx.lib.agw.hypertreelist.TreeListMainWindow.GetItemWindow` Returns the window associated with an item. + :meth:`~wx.lib.agw.hypertreelist.TreeListMainWindow.GetItemWindowEnabled` Returns whether the window associated with an item is enabled or not. + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.GetLastChild` Returns the item last child. + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.GetNext` Returns the next item. Only for internal use right now. + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.GetNextChild` Returns the item's next child. + :meth:`~wx.lib.agw.hypertreelist.TreeListMainWindow.GetNextExpanded` Returns the next expanded item after the input one. + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.GetNextShown` Returns the next displayed item in the tree, visible or not. + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.GetNextSibling` Returns the next sibling of an item. + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.GetNextVisible` Returns the next item that is visible to the user. + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.GetPrev` Returns the previous item. Only for internal use right now. + :meth:`~wx.lib.agw.hypertreelist.TreeListMainWindow.GetPrevChild` Returns the previous child of an item. + :meth:`~wx.lib.agw.hypertreelist.TreeListMainWindow.GetPrevExpanded` Returns the previous expanded item before the input one. + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.GetPrevShown` Returns the previous displayed item in the tree, visible or not. + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.GetPrevSibling` Returns the previous sibling of an item. + :meth:`~wx.lib.agw.hypertreelist.TreeListMainWindow.GetPrevVisible` Returns the previous item visible to the user. + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.GetPyData` Returns the data associated to an item. + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.GetRootItem` Returns the root item, an instance of :class:`GenericTreeItem`. + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.GetSecondGradientColour` Returns the second gradient colour for gradient-style selections. + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.GetSelection` Returns the current selection. + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.GetSelections` Returns a list of selected items. + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.GetSpacing` Returns the spacing between the start and the text, in pixels. + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.GetStateImageList` Returns the state image list associated with :class:`TreeListMainWindow`. + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.HasChildren` Returns whether an item has children or not. + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.HideItem` Hides/shows an item. + :meth:`~wx.lib.agw.hypertreelist.TreeListMainWindow.HitTest` Finds which (if any) item is under the given point, returning the item plus flags. + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.InsertItem` Inserts an item after the given previous. + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.IsBold` Returns whether the item font is bold or not. + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.IsDescendantOf` Checks if the given item is under another one in the tree hierarchy. + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.IsExpanded` Returns whether the item is expanded or not. + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.IsItem3State` Returns whether or not the checkbox item is a 3-state checkbox. + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.IsItemChecked` Returns whether an item is checked or not. + :meth:`~wx.lib.agw.hypertreelist.TreeListMainWindow.IsItemEnabled` Returns whether an item is enabled or disabled. + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.IsItemHyperText` Returns whether an item is hypertext or not. + :meth:`~wx.lib.agw.hypertreelist.TreeListMainWindow.IsItemVisible` Returns whether the item is visible or not. + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.IsSelected` Returns whether the item is selected or not. + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.ItemHasChildren` Returns whether the item has children or not. + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.PrependItem` Prepends an item as a first child of parent. + :meth:`~wx.lib.agw.hypertreelist.TreeListMainWindow.ScrollTo` Scrolls the specified item into view. + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.SelectAll` Selects all the item in the tree. + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.SelectAllChildren` Selects all the children of the given item. + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.SelectItem` Selects/deselects an item. + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.SetBackgroundImage` Sets the :class:`TreeListMainWindow` background image. + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.SetBorderPen` Sets the pen used to draw the selected item border. + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.SetButtonsImageList` Sets the buttons image list for :class:`TreeListMainWindow`. + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.SetConnectionPen` Sets the pen used to draw the connecting lines between items. + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.SetDisabledColour` Sets the colour for items in a disabled state. + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.SetDragFullScreen` Sets whether a drag operation will be performed full screen or not. + :meth:`~wx.lib.agw.hypertreelist.TreeListMainWindow.SetDragItem` Sets the specified item as member of a current drag and drop operation. + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.SetFirstGradientColour` Sets the first gradient colour for gradient-style selections. + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.SetGradientStyle` Sets the gradient style for gradient-style selections. + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.SetHilightFocusColour` Sets the colour used to highlight focused selected items. + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.SetHilightNonFocusColour` Sets the colour used to highlight unfocused selected items. + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.SetHyperTextFont` Sets the font used to render hypertext items. + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.SetHyperTextNewColour` Sets the colour used to render a non-visited hypertext item. + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.SetHyperTextVisitedColour` Sets the colour used to render a visited hypertext item. + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.SetImageList` Sets the normal image list for :class:`TreeListMainWindow`. + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.SetImageListCheck` Sets the checkbox/radiobutton image list. + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.SetIndent` Currently has no effect on ``HyperTreeList``. The indent is auto-calculated. + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.SetItem3State` Sets whether the item has a 3-state value checkbox assigned to it or not. + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.SetItem3StateValue` Sets the checkbox item to the given `state`. + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.SetItemBackgroundColour` Sets the item background colour. + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.SetItemBold` Sets the item font as bold/unbold. + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.SetItemDropHighlight` Gives the item the visual feedback for drag and drop operations. + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.SetItemFont` Sets the item font. + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.SetItemHasChildren` Forces the appearance/disappearance of the button next to the item. + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.SetItemHyperText` Sets whether the item is hypertext or not. + :meth:`~wx.lib.agw.hypertreelist.TreeListMainWindow.SetItemImage` Sets the item image for a particular item state. + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.SetItemItalic` Sets the item font as italic/non-italic. + SetItemPyData Another name for :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.SetPyData` + :meth:`~wx.lib.agw.hypertreelist.TreeListMainWindow.SetItemText` Sets the item text label. + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.SetItemTextColour` Sets the item text colour or separator horizontal line colour. + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.SetItemType` Sets the item type. + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.SetItemVisited` Sets whether an hypertext item was visited. + :meth:`~wx.lib.agw.hypertreelist.TreeListMainWindow.SetItemWindow` Sets the window associated to an item. + :meth:`~wx.lib.agw.hypertreelist.TreeListMainWindow.SetItemWindowEnabled` Sets whether the window associated with an item is enabled or not. + :meth:`~wx.lib.agw.hypertreelist.TreeListMainWindow.SetMainColumn` Sets the :class:`HyperTreeList` main column (i.e. the column of the tree). + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.SetPyData` Sets the data associated to an item. + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.SetSecondGradientColour` Sets the second gradient colour for gradient-style selections. + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.SetSpacing` Currently has no effect on ``HyperTreeList``. + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.SetStateImageList` Sets the state image list for :class:`TreeListMainWindow` + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.ShouldInheritColours` Return ``True`` to allow the window colours to be changed by `InheritAttributes`. + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.Toggle` Toggles the item state (collapsed/expanded). + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.ToggleItemSelection` Toggles the item selection. + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.UnCheckRadioParent` Used internally to handle radio node parent correctly. + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.Unselect` Unselects the current selection. + :meth:`~wx.lib.agw.customtreectrl.CustomTreeCtrl.UnselectAll` Unselect all the items. + ================================================================================ ================================================================================== + + """ def __init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition, size=wx.DefaultSize, @@ -4345,36 +4569,8 @@ class HyperTreeList(wx.Control): :param `size`: the control size. A value of (-1, -1) indicates a default size, chosen by either the windowing system or wxPython, depending on platform; :param `style`: the underlying :class:`wx.Control` style; - :param `agwStyle`: the AGW-specific :class:`HyperTreeList` window style. This can be a combination - of the following bits: - - ============================== =========== ================================================== - Window Styles Hex Value Description - ============================== =========== ================================================== - ``TR_NO_BUTTONS`` 0x0 For convenience to document that no buttons are to be drawn. - ``TR_SINGLE`` 0x0 For convenience to document that only one item may be selected at a time. Selecting another item causes the current selection, if any, to be deselected. This is the default. - ``TR_HAS_BUTTONS`` 0x1 Use this style to show + and - buttons to the left of parent items. - ``TR_NO_LINES`` 0x4 Use this style to hide vertical level connectors. - ``TR_LINES_AT_ROOT`` 0x8 Use this style to show lines between root nodes. Only applicable if ``TR_HIDE_ROOT`` is set and ``TR_NO_LINES`` is not set. - ``TR_DEFAULT_STYLE`` 0x9 The set of flags that are closest to the defaults for the native control for a particular toolkit. - ``TR_TWIST_BUTTONS`` 0x10 Use old Mac-twist style buttons. - ``TR_MULTIPLE`` 0x20 Use this style to allow a range of items to be selected. If a second range is selected, the current range, if any, is deselected. - ``TR_EXTENDED`` 0x40 Use this style to allow disjoint items to be selected. (Only partially implemented; may not work in all cases). - ``TR_HAS_VARIABLE_ROW_HEIGHT`` 0x80 Use this style to cause row heights to be just big enough to fit the content. If not set, all rows use the largest row height. The default is that this flag is unset. - ``TR_EDIT_LABELS`` 0x200 Use this style if you wish the user to be able to edit labels in the tree control. - ``TR_ROW_LINES`` 0x400 Use this style to draw a contrasting border between displayed rows. - ``TR_HIDE_ROOT`` 0x800 Use this style to suppress the display of the root node, effectively causing the first-level nodes to appear as a series of root nodes. - ``TR_COLUMN_LINES`` 0x1000 Use this style to draw a contrasting border between displayed columns. - ``TR_FULL_ROW_HIGHLIGHT`` 0x2000 Use this style to have the background colour and the selection highlight extend over the entire horizontal row of the tree control window. - ``TR_AUTO_CHECK_CHILD`` 0x4000 Only meaningful for checkbox-type items: when a parent item is checked/unchecked its children are checked/unchecked as well. - ``TR_AUTO_TOGGLE_CHILD`` 0x8000 Only meaningful for checkbox-type items: when a parent item is checked/unchecked its children are toggled accordingly. - ``TR_AUTO_CHECK_PARENT`` 0x10000 Only meaningful for checkbox-type items: when a child item is checked/unchecked its parent item is checked/unchecked as well. - ``TR_ALIGN_WINDOWS`` 0x20000 Flag used to align windows (in items with windows) at the same horizontal position. - ``TR_NO_HEADER`` 0x40000 Use this style to hide the columns header. - ``TR_ELLIPSIZE_LONG_ITEMS`` 0x80000 Flag used to ellipsize long items when the horizontal space for :class:`~wx.lib.agw.customtreectrl.CustomTreeCtrl` is low. - ``TR_VIRTUAL`` 0x100000 :class:`HyperTreeList` will have virtual behaviour. - ============================== =========== ================================================== - + :param `agwStyle`: the AGW-specific :class:`HyperTreeList` window style. + see :mod:`~wx.lib.agw.hypertreelist` for a full list of flags. :param `validator`: window validator; :param `name`: window name. """ @@ -4400,6 +4596,7 @@ class HyperTreeList(wx.Control): self.CalculateAndSetHeaderHeight() self.Bind(wx.EVT_SIZE, self.OnSize) + self.Bind(wx.EVT_SET_FOCUS, self.OnHTLFocus) self.SetBuffered(IsBufferingSupported()) self._main_win.SetAGWWindowStyleFlag(agwStyle) @@ -4418,6 +4615,35 @@ class HyperTreeList(wx.Control): self._header_win.SetBuffered(buffered) + def Freeze(self): + """ + Freeze :class:`HyperTreeList` to allow rapid changes to the tree. + + Freezes the HyperTreeList main (tree) and and header windows. + This prevents any re-calculation or updates from taking place + allowing mass updates to the tree very quickly. :meth:`~Thaw` + must be called to reenable updates. Calls to these two + functions may be nested. + """ + self._main_win.Freeze() + self._header_win.Freeze() + + + def Thaw(self): + """ + Thaw :class:`HyperTreeList`. + + Reenables updates to the main (tree) and header windows after a + previous call to :meth:`~Freeze`. To really thaw the control, it + must be called exactly the same number of times as :meth:`~Freeze`. + When fully thawed the tree will re-calculate and update itself. + + :raise: `Exception` if :meth:`~Thaw` has been called without an un-matching :meth:`~Freeze`. + """ + self._main_win.Thaw() + self._header_win.Thaw() + + def CalculateAndSetHeaderHeight(self): """ Calculates the best header height and stores it. """ @@ -4457,6 +4683,16 @@ class HyperTreeList(wx.Control): self.DoHeaderLayout() + def OnHTLFocus(self, event): + """ + Handles the ``wx.EVT_SET_FOCUS`` event for :class:`HyperTreeList`. + + :param `event`: a :class:`wx.SizeEvent` event to be processed. + """ + # Pass focus to TreeListMainWindow so keyboard controls work. + self.GetMainWindow().SetFocus() + + def SetFont(self, font): """ Sets the default font for the header window and the main window. @@ -4507,34 +4743,8 @@ class HyperTreeList(wx.Control): """ Sets the window style for :class:`HyperTreeList`. - :param `agwStyle`: can be a combination of the following bits: - - ============================== =========== ================================================== - Window Styles Hex Value Description - ============================== =========== ================================================== - ``TR_NO_BUTTONS`` 0x0 For convenience to document that no buttons are to be drawn. - ``TR_SINGLE`` 0x0 For convenience to document that only one item may be selected at a time. Selecting another item causes the current selection, if any, to be deselected. This is the default. - ``TR_HAS_BUTTONS`` 0x1 Use this style to show + and - buttons to the left of parent items. - ``TR_NO_LINES`` 0x4 Use this style to hide vertical level connectors. - ``TR_LINES_AT_ROOT`` 0x8 Use this style to show lines between root nodes. Only applicable if ``TR_HIDE_ROOT`` is set and ``TR_NO_LINES`` is not set. - ``TR_DEFAULT_STYLE`` 0x9 The set of flags that are closest to the defaults for the native control for a particular toolkit. - ``TR_TWIST_BUTTONS`` 0x10 Use old Mac-twist style buttons. - ``TR_MULTIPLE`` 0x20 Use this style to allow a range of items to be selected. If a second range is selected, the current range, if any, is deselected. - ``TR_EXTENDED`` 0x40 Use this style to allow disjoint items to be selected. (Only partially implemented; may not work in all cases). - ``TR_HAS_VARIABLE_ROW_HEIGHT`` 0x80 Use this style to cause row heights to be just big enough to fit the content. If not set, all rows use the largest row height. The default is that this flag is unset. - ``TR_EDIT_LABELS`` 0x200 Use this style if you wish the user to be able to edit labels in the tree control. - ``TR_ROW_LINES`` 0x400 Use this style to draw a contrasting border between displayed rows. - ``TR_HIDE_ROOT`` 0x800 Use this style to suppress the display of the root node, effectively causing the first-level nodes to appear as a series of root nodes. - ``TR_COLUMN_LINES`` 0x1000 Use this style to draw a contrasting border between displayed columns. - ``TR_FULL_ROW_HIGHLIGHT`` 0x2000 Use this style to have the background colour and the selection highlight extend over the entire horizontal row of the tree control window. - ``TR_AUTO_CHECK_CHILD`` 0x4000 Only meaningful for checkbox-type items: when a parent item is checked/unchecked its children are checked/unchecked as well. - ``TR_AUTO_TOGGLE_CHILD`` 0x8000 Only meaningful for checkbox-type items: when a parent item is checked/unchecked its children are toggled accordingly. - ``TR_AUTO_CHECK_PARENT`` 0x10000 Only meaningful for checkbox-type items: when a child item is checked/unchecked its parent item is checked/unchecked as well. - ``TR_ALIGN_WINDOWS`` 0x20000 Flag used to align windows (in items with windows) at the same horizontal position. - ``TR_NO_HEADER`` 0x40000 Use this style to hide the columns header. - ``TR_ELLIPSIZE_LONG_ITEMS`` 0x80000 Flag used to ellipsize long items when the horizontal space for :class:`~wx.lib.agw.customtreectrl.CustomTreeCtrl` is low. - ``TR_VIRTUAL`` 0x100000 :class:`HyperTreeList` will have virtual behaviour. - ============================== =========== ================================================== + :param `agwStyle`: can be a combination of various bits. See + :mod:`~wx.lib.agw.hypertreelist` for a full list of flags. :note: Please note that some styles cannot be changed after the window creation and that `Refresh()` might need to be be called after changing the others for @@ -4923,6 +5133,22 @@ class HyperTreeList(wx.Control): return self._header_win.GetColumn(column).GetFont() + def SetColumnSortIcon(self, column, sortIcon, colour=None): + """ + Sets the sort icon to be displayed in the column header. + + The sort icon will be displayed in the specified column number + and all other columns will have the sort icon cleared. + + :param `column`: an integer specifying the column index; + :param `sortIcon`: the sort icon to display, one of ``wx.HDR_SORT_ICON_NONE``, + ``wx.HDR_SORT_ICON_UP``, ``wx.HDR_SORT_ICON_DOWN``. + :param `colour`: the colour of the sort icon as a wx.Colour. Optional. + Set to ``None`` to restore native colour. + """ + return self._header_win.SetSortIcon(column, sortIcon, colour) + + def Refresh(self, erase=True, rect=None): """ Causes this window, and all of its children recursively (except under wxGTK1 @@ -4975,9 +5201,9 @@ class HyperTreeList(wx.Control): def OnGetItemText(self, item, column): """ - This function **must** be overloaded in the derived class for a control - with ``TR_VIRTUAL`` style. It should return the string containing the - text of the given column for the specified item. + If the ``TR_VIRTUAL`` style is set this function **must** be overloaded + in the derived class. It should return the string containing the text + of the given column for the specified item. :param `item`: an instance of :class:`TreeListItem`; :param `column`: an integer specifying the column index. @@ -5004,7 +5230,7 @@ class HyperTreeList(wx.Control): def OnCompareItems(self, item1, item2): """ - Returns whether 2 items have the same text. + Returns the comparison of two items. Used for sorting. Override this function in the derived class to change the sort order of the items in the :class:`HyperTreeList`. The function should return a negative, zero or positive