PageRenderTime 220ms CodeModel.GetById 31ms RepoModel.GetById 1ms app.codeStats 1ms

/lib/pwiki/customtreectrl.py

https://bitbucket.org/xkjq/wikidpad_svn
Python | 6065 lines | 5857 code | 74 blank | 134 comment | 14 complexity | 6184bada91d2c01aab5636d1e5082b99 MD5 | raw file
Possible License(s): LGPL-2.1

Large files files are truncated, but you can click here to view the full file

  1. # --------------------------------------------------------------------------------- #
  2. # CUSTOMTREECTRL wxPython IMPLEMENTATION
  3. # Inspired By And Heavily Based On wxGenericTreeCtrl.
  4. #
  5. # Andrea Gavana, @ 17 May 2006
  6. # Latest Revision: 16 Apr 2007, 11.00 CET
  7. #
  8. #
  9. # TODO List
  10. #
  11. # Almost All The Features Of wx.TreeCtrl Are Available, And There Is Practically
  12. # No Limit In What Could Be Added To This Class. The First Things That Comes
  13. # To My Mind Are:
  14. #
  15. # 1. Implement The Style TR_EXTENDED (I Have Never Used It, But It May Be Useful).
  16. #
  17. # 2. Add Support For 3-State CheckBoxes (Is That Really Useful?).
  18. #
  19. # 3. Try To Implement A More Flicker-Free Background Image In Cases Like
  20. # Centered Or Stretched Image (Now CustomTreeCtrl Supports Only Tiled
  21. # Background Images).
  22. #
  23. # 4. Try To Mimic Windows wx.TreeCtrl Expanding/Collapsing behaviour: CustomTreeCtrl
  24. # Suddenly Expands/Collapses The Nodes On Mouse Click While The Native Control
  25. # Has Some Kind Of "Smooth" Expanding/Collapsing, Like A Wave. I Don't Even
  26. # Know Where To Start To Do That.
  27. #
  28. # 5. Speed Up General OnPaint Things? I Have No Idea, Here CustomTreeCtrl Is Quite
  29. # Fast, But We Should See On Slower Machines.
  30. #
  31. #
  32. # For All Kind Of Problems, Requests Of Enhancements And Bug Reports, Please
  33. # Write To Me At:
  34. #
  35. # gavana@kpo.kz
  36. # andrea.gavana@gmail.com
  37. #
  38. # Or, Obviously, To The wxPython Mailing List!!!
  39. #
  40. #
  41. # Modifications by Michael Butscher (mbutscher@gmx.de) based on
  42. # rev. 1.14 in wxWidgets repository
  43. #
  44. # Modifications by Michael Butscher Jan. 2007:
  45. #
  46. # - Expand buttons at the same place where they are on Windows tree
  47. # - No button for root element
  48. # - Expansion near the bottom scrolls tree appropriately
  49. # - Flicker-free expansion/collapse (not tested with background image)
  50. # - Unselect also works on single-select tree
  51. # - Option to set image list without generation of grayed icons (faster)
  52. #
  53. # Modifications by Michael Butscher May 2007:
  54. # - Tooltip if label is broader than window
  55. #
  56. # Modifications by Michael Butscher May 2010:
  57. # - Parameter in SelectItem() to suppress event generation
  58. #
  59. #
  60. # End Of Comments
  61. # --------------------------------------------------------------------------------- #
  62. """
  63. Description
  64. ===========
  65. CustomTreeCtrl is a class that mimics the behaviour of wx.TreeCtrl, with almost the
  66. same base functionalities plus some more enhancements. This class does not rely on
  67. the native control, as it is a full owner-drawn tree control.
  68. Apart of the base functionalities of CustomTreeCtrl (described below), in addition
  69. to the standard wx.TreeCtrl behaviour this class supports:
  70. * CheckBox-type items: checkboxes are easy to handle, just selected or unselected
  71. state with no particular issues in handling the item's children;
  72. * RadioButton-type items: since I elected to put radiobuttons in CustomTreeCtrl, I
  73. needed some way to handle them, that made sense. So, I used the following approach:
  74. - All peer-nodes that are radiobuttons will be mutually exclusive. In other words,
  75. only one of a set of radiobuttons that share a common parent can be checked at
  76. once. If a radiobutton node becomes checked, then all of its peer radiobuttons
  77. must be unchecked.
  78. - If a radiobutton node becomes unchecked, then all of its child nodes will become
  79. inactive.
  80. * Hyperlink-type items: they look like an hyperlink, with the proper mouse cursor on
  81. hovering.
  82. * Multiline text items.
  83. * Enabling/disabling items (together with their plain or grayed out icons).
  84. * Whatever non-toplevel widget can be attached next to an item.
  85. * Default selection style, gradient (horizontal/vertical) selection style and Windows
  86. Vista selection style.
  87. * Customized drag and drop images built on the fly.
  88. * Setting the CustomTreeCtrl item buttons to a personalized imagelist.
  89. * Setting the CustomTreeCtrl check/radio item icons to a personalized imagelist.
  90. * Changing the style of the lines that connect the items (in terms of wx.Pen styles).
  91. * Using an image as a CustomTreeCtrl background (currently only in "tile" mode).
  92. And a lot more. Check the demo for an almost complete review of the functionalities.
  93. Base Functionalities
  94. ====================
  95. CustomTreeCtrl supports all the wx.TreeCtrl styles, except:
  96. - TR_EXTENDED: supports for this style is on the todo list (Am I sure of this?).
  97. Plus it has 3 more styles to handle checkbox-type items:
  98. - TR_AUTO_CHECK_CHILD : automatically checks/unchecks the item children;
  99. - TR_AUTO_CHECK_PARENT : automatically checks/unchecks the item parent;
  100. - TR_AUTO_TOGGLE_CHILD: automatically toggles the item children.
  101. All the methods available in wx.TreeCtrl are also available in CustomTreeCtrl.
  102. Events
  103. ======
  104. All the events supported by wx.TreeCtrl are also available in CustomTreeCtrl, with
  105. a few exceptions:
  106. - EVT_TREE_GET_INFO (don't know what this means);
  107. - EVT_TREE_SET_INFO (don't know what this means);
  108. - EVT_TREE_ITEM_MIDDLE_CLICK (not implemented, but easy to add);
  109. - EVT_TREE_STATE_IMAGE_CLICK: no need for that, look at the checking events below.
  110. Plus, CustomTreeCtrl supports the events related to the checkbutton-type items:
  111. - EVT_TREE_ITEM_CHECKING: an item is being checked;
  112. - EVT_TREE_ITEM_CHECKED: an item has been checked.
  113. And to hyperlink-type items:
  114. - EVT_TREE_ITEM_HYPERLINK: an hyperlink item has been clicked (this event is sent
  115. after the EVT_TREE_SEL_CHANGED event).
  116. Supported Platforms
  117. ===================
  118. CustomTreeCtrl has been tested on the following platforms:
  119. * Windows (Windows XP);
  120. * GTK (Thanks to Michele Petrazzo);
  121. * Mac OS (Thanks to John Jackson).
  122. Latest Revision: Andrea Gavana @ 16 Apr 2007, 11.00 CET
  123. Version 1.0
  124. """
  125. import wx
  126. import zlib
  127. import cStringIO
  128. import types
  129. import traceback
  130. # ----------------------------------------------------------------------------
  131. # Constants
  132. # ----------------------------------------------------------------------------
  133. _NO_IMAGE = -1
  134. _PIXELS_PER_UNIT = 10
  135. # Bug workaround: In wxPython 2.6 these constants weren't defined
  136. # in 2.8 they are defined under a different name and with different values
  137. try:
  138. wxWINDOWS_NT = wx.OS_WINDOWS_NT
  139. except AttributeError:
  140. wxWINDOWS_NT = 18 # For wxGetOsVersion(), this includes NT 4.0, 2000, XP
  141. try:
  142. wxWIN95 = wx.OS_WINDOWS_9X
  143. except AttributeError:
  144. wxWIN95 = 20 # For wx.GetOsVersion(), this includes also Win 98 and ME
  145. # Start editing the current item after half a second (if the mouse hasn't
  146. # been clicked/moved)
  147. _DELAY = 500
  148. # ----------------------------------------------------------------------------
  149. # Constants
  150. # ----------------------------------------------------------------------------
  151. # Enum for different images associated with a treectrl item
  152. TreeItemIcon_Normal = 0 # not selected, not expanded
  153. TreeItemIcon_Selected = 1 # selected, not expanded
  154. TreeItemIcon_Expanded = 2 # not selected, expanded
  155. TreeItemIcon_SelectedExpanded = 3 # selected, expanded
  156. TreeItemIcon_Checked = 0 # check button, checked
  157. TreeItemIcon_NotChecked = 1 # check button, not checked
  158. TreeItemIcon_Flagged = 2 # radio button, selected
  159. TreeItemIcon_NotFlagged = 3 # radio button, not selected
  160. # ----------------------------------------------------------------------------
  161. # CustomTreeCtrl flags
  162. # ----------------------------------------------------------------------------
  163. TR_NO_BUTTONS = wx.TR_NO_BUTTONS # for convenience
  164. TR_HAS_BUTTONS = wx.TR_HAS_BUTTONS # draw collapsed/expanded btns
  165. TR_NO_LINES = wx.TR_NO_LINES # don't draw lines at all
  166. TR_LINES_AT_ROOT = wx.TR_LINES_AT_ROOT # connect top-level nodes
  167. TR_TWIST_BUTTONS = wx.TR_TWIST_BUTTONS # still used by wxTreeListCtrl
  168. TR_SINGLE = wx.TR_SINGLE # for convenience
  169. TR_MULTIPLE = wx.TR_MULTIPLE # can select multiple items
  170. TR_EXTENDED = wx.TR_EXTENDED # TODO: allow extended selection
  171. TR_HAS_VARIABLE_ROW_HEIGHT = wx.TR_HAS_VARIABLE_ROW_HEIGHT # what it says
  172. TR_EDIT_LABELS = wx.TR_EDIT_LABELS # can edit item labels
  173. TR_ROW_LINES = wx.TR_ROW_LINES # put border around items
  174. TR_HIDE_ROOT = wx.TR_HIDE_ROOT # don't display root node
  175. TR_FULL_ROW_HIGHLIGHT = wx.TR_FULL_ROW_HIGHLIGHT # highlight full horz space
  176. TR_AUTO_CHECK_CHILD = 0x04000 # only meaningful for checkboxes
  177. TR_AUTO_TOGGLE_CHILD = 0x08000 # only meaningful for checkboxes
  178. TR_AUTO_CHECK_PARENT = 0x10000 # only meaningful for checkboxes
  179. TR_DEFAULT_STYLE = wx.TR_DEFAULT_STYLE # default style for the tree control
  180. # Values for the `flags' parameter of CustomTreeCtrl.HitTest() which determine
  181. # where exactly the specified point is situated:
  182. TREE_HITTEST_ABOVE = wx.TREE_HITTEST_ABOVE
  183. TREE_HITTEST_BELOW = wx.TREE_HITTEST_BELOW
  184. TREE_HITTEST_NOWHERE = wx.TREE_HITTEST_NOWHERE
  185. # on the button associated with an item.
  186. TREE_HITTEST_ONITEMBUTTON = wx.TREE_HITTEST_ONITEMBUTTON
  187. # on the bitmap associated with an item.
  188. TREE_HITTEST_ONITEMICON = wx.TREE_HITTEST_ONITEMICON
  189. # on the indent associated with an item.
  190. TREE_HITTEST_ONITEMINDENT = wx.TREE_HITTEST_ONITEMINDENT
  191. # on the label (string) associated with an item.
  192. TREE_HITTEST_ONITEMLABEL = wx.TREE_HITTEST_ONITEMLABEL
  193. # on the right of the label associated with an item.
  194. TREE_HITTEST_ONITEMRIGHT = wx.TREE_HITTEST_ONITEMRIGHT
  195. # on the label (string) associated with an item.
  196. TREE_HITTEST_ONITEMSTATEICON = wx.TREE_HITTEST_ONITEMSTATEICON
  197. # on the left of the CustomTreeCtrl.
  198. TREE_HITTEST_TOLEFT = wx.TREE_HITTEST_TOLEFT
  199. # on the right of the CustomTreeCtrl.
  200. TREE_HITTEST_TORIGHT = wx.TREE_HITTEST_TORIGHT
  201. # on the upper part (first half) of the item.
  202. TREE_HITTEST_ONITEMUPPERPART = wx.TREE_HITTEST_ONITEMUPPERPART
  203. # on the lower part (second half) of the item.
  204. TREE_HITTEST_ONITEMLOWERPART = wx.TREE_HITTEST_ONITEMLOWERPART
  205. # on the check icon, if present
  206. TREE_HITTEST_ONITEMCHECKICON = 0x4000
  207. # anywhere on the item
  208. TREE_HITTEST_ONITEM = TREE_HITTEST_ONITEMICON | TREE_HITTEST_ONITEMLABEL | TREE_HITTEST_ONITEMCHECKICON
  209. # Background Image Style
  210. _StyleTile = 0
  211. _StyleStretch = 1
  212. # Windows Vista Colours
  213. _rgbSelectOuter = wx.Colour(170, 200, 245)
  214. _rgbSelectInner = wx.Colour(230, 250, 250)
  215. _rgbSelectTop = wx.Colour(210, 240, 250)
  216. _rgbSelectBottom = wx.Colour(185, 215, 250)
  217. _rgbNoFocusTop = wx.Colour(250, 250, 250)
  218. _rgbNoFocusBottom = wx.Colour(235, 235, 235)
  219. _rgbNoFocusOuter = wx.Colour(220, 220, 220)
  220. _rgbNoFocusInner = wx.Colour(245, 245, 245)
  221. # Flags for wx.RendererNative
  222. _CONTROL_EXPANDED = 8
  223. _CONTROL_CURRENT = 16
  224. # Version Info
  225. __version__ = "0.8"
  226. # ----------------------------------------------------------------------------
  227. # CustomTreeCtrl events and binding for handling them
  228. # ----------------------------------------------------------------------------
  229. wxEVT_TREE_BEGIN_DRAG = wx.wxEVT_COMMAND_TREE_BEGIN_DRAG
  230. wxEVT_TREE_BEGIN_RDRAG = wx.wxEVT_COMMAND_TREE_BEGIN_RDRAG
  231. wxEVT_TREE_BEGIN_LABEL_EDIT = wx.wxEVT_COMMAND_TREE_BEGIN_LABEL_EDIT
  232. wxEVT_TREE_END_LABEL_EDIT = wx.wxEVT_COMMAND_TREE_END_LABEL_EDIT
  233. wxEVT_TREE_DELETE_ITEM = wx.wxEVT_COMMAND_TREE_DELETE_ITEM
  234. wxEVT_TREE_GET_INFO = wx.wxEVT_COMMAND_TREE_GET_INFO
  235. wxEVT_TREE_SET_INFO = wx.wxEVT_COMMAND_TREE_SET_INFO
  236. wxEVT_TREE_ITEM_EXPANDED = wx.wxEVT_COMMAND_TREE_ITEM_EXPANDED
  237. wxEVT_TREE_ITEM_EXPANDING = wx.wxEVT_COMMAND_TREE_ITEM_EXPANDING
  238. wxEVT_TREE_ITEM_COLLAPSED = wx.wxEVT_COMMAND_TREE_ITEM_COLLAPSED
  239. wxEVT_TREE_ITEM_COLLAPSING = wx.wxEVT_COMMAND_TREE_ITEM_COLLAPSING
  240. wxEVT_TREE_SEL_CHANGED = wx.wxEVT_COMMAND_TREE_SEL_CHANGED
  241. wxEVT_TREE_SEL_CHANGING = wx.wxEVT_COMMAND_TREE_SEL_CHANGING
  242. wxEVT_TREE_KEY_DOWN = wx.wxEVT_COMMAND_TREE_KEY_DOWN
  243. wxEVT_TREE_ITEM_ACTIVATED = wx.wxEVT_COMMAND_TREE_ITEM_ACTIVATED
  244. wxEVT_TREE_ITEM_RIGHT_CLICK = wx.wxEVT_COMMAND_TREE_ITEM_RIGHT_CLICK
  245. wxEVT_TREE_ITEM_MIDDLE_CLICK = wx.wxEVT_COMMAND_TREE_ITEM_MIDDLE_CLICK
  246. wxEVT_TREE_END_DRAG = wx.wxEVT_COMMAND_TREE_END_DRAG
  247. wxEVT_TREE_STATE_IMAGE_CLICK = wx.wxEVT_COMMAND_TREE_STATE_IMAGE_CLICK
  248. wxEVT_TREE_ITEM_GETTOOLTIP = wx.wxEVT_COMMAND_TREE_ITEM_GETTOOLTIP
  249. wxEVT_TREE_ITEM_MENU = wx.wxEVT_COMMAND_TREE_ITEM_MENU
  250. wxEVT_TREE_ITEM_CHECKING = wx.NewEventType()
  251. wxEVT_TREE_ITEM_CHECKED = wx.NewEventType()
  252. wxEVT_TREE_ITEM_HYPERLINK = wx.NewEventType()
  253. EVT_TREE_BEGIN_DRAG = wx.EVT_TREE_BEGIN_DRAG
  254. EVT_TREE_BEGIN_RDRAG = wx.EVT_TREE_BEGIN_RDRAG
  255. EVT_TREE_BEGIN_LABEL_EDIT = wx.EVT_TREE_BEGIN_LABEL_EDIT
  256. EVT_TREE_END_LABEL_EDIT = wx.EVT_TREE_END_LABEL_EDIT
  257. EVT_TREE_DELETE_ITEM = wx.EVT_TREE_DELETE_ITEM
  258. EVT_TREE_GET_INFO = wx.EVT_TREE_GET_INFO
  259. EVT_TREE_SET_INFO = wx.EVT_TREE_SET_INFO
  260. EVT_TREE_ITEM_EXPANDED = wx.EVT_TREE_ITEM_EXPANDED
  261. EVT_TREE_ITEM_EXPANDING = wx.EVT_TREE_ITEM_EXPANDING
  262. EVT_TREE_ITEM_COLLAPSED = wx.EVT_TREE_ITEM_COLLAPSED
  263. EVT_TREE_ITEM_COLLAPSING = wx.EVT_TREE_ITEM_COLLAPSING
  264. EVT_TREE_SEL_CHANGED = wx.EVT_TREE_SEL_CHANGED
  265. EVT_TREE_SEL_CHANGING = wx.EVT_TREE_SEL_CHANGING
  266. EVT_TREE_KEY_DOWN = wx.EVT_TREE_KEY_DOWN
  267. EVT_TREE_ITEM_ACTIVATED = wx.EVT_TREE_ITEM_ACTIVATED
  268. EVT_TREE_ITEM_RIGHT_CLICK = wx.EVT_TREE_ITEM_RIGHT_CLICK
  269. EVT_TREE_ITEM_MIDDLE_CLICK = wx.EVT_TREE_ITEM_MIDDLE_CLICK
  270. EVT_TREE_END_DRAG = wx.EVT_TREE_END_DRAG
  271. EVT_TREE_STATE_IMAGE_CLICK = wx.EVT_TREE_STATE_IMAGE_CLICK
  272. EVT_TREE_ITEM_GETTOOLTIP = wx.EVT_TREE_ITEM_GETTOOLTIP
  273. EVT_TREE_ITEM_MENU = wx.EVT_TREE_ITEM_MENU
  274. EVT_TREE_ITEM_CHECKING = wx.PyEventBinder(wxEVT_TREE_ITEM_CHECKING, 1)
  275. EVT_TREE_ITEM_CHECKED = wx.PyEventBinder(wxEVT_TREE_ITEM_CHECKED, 1)
  276. EVT_TREE_ITEM_HYPERLINK = wx.PyEventBinder(wxEVT_TREE_ITEM_HYPERLINK, 1)
  277. def GetFlaggedData():
  278. return zlib.decompress(
  279. 'x\xda\x012\x02\xcd\xfd\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\r\x00\
  280. \x00\x00\r\x08\x06\x00\x00\x00r\xeb\xe4|\x00\x00\x00\x04sBIT\x08\x08\x08\x08\
  281. |\x08d\x88\x00\x00\x01\xe9IDAT(\x91u\x92\xd1K\xd3a\x14\x86\x9f\xef|J2J\xc3%\
  282. \x85\x8e\x1cb\x93Hl\xd9,\x06F]4\x10\tD3\x83\x88\xc8\xbf\xc0\xb4\xaeBP1\xe9\
  283. \xa2(\xec\xaan\xc3\x82pD\xa1\x84\xb0\x88@3\x8c\xc9\xa2bT\xa2^\x8c\x81V3\xb6\
  284. \xb5\x9f\xce9\xbe.j\xb20\xdf\xeb\xf7\xe19\x07^\xa5D\x93\x9f\x9ea\xbf\t\x04\
  285. \xbf\x12\x8b[\xd8Kl\xf8<.\xeet\xb5\xab\xfc\x8e\xca\x87*ZzM\xf3\xb1j|G\xab\
  286. \xf0\xd4\x94\x13\x9a_&0\xbb\xc8\xd8\xf4g\xa2\xcfo\xa8-P\xc7\xf5\x07\xa6\xedD\
  287. \r\x8d\xb5\xfb\x11\x11\xb4\xd6\x88h\xb4\xd6L}\x8a\xf0\xe4\xd5G\x1e\rt*\x00\
  288. \xc9\x19\xb6\x03D4\xa7\xdcU\\8\xed\xa6\xa2\xa5\xd7\x00\xe8\xab\xf7\x9e\x9a\
  289. \xca\xb2\x9d\\\xf2\xd5!"dT\x86\xc9\xe4\x14\x83s\x83HF\xe3\xdc\xe5\xa4\xa8\
  290. \xb0\x88\xaa\xf2=D\x7f$il>\xdf\xafSe\xf5\xfd\x9dM\x87\xa9\xdc\xb7\x1b\xad5\
  291. \x93\xc9)\xfc\xe9Q\x12\xe9\x04\x13\x0b\x13\x94\xaaR\xdc{\x8f "\xec(,\xe0\xfe\
  292. \xb3\xb7H,a\xe1\xa9)\xdf<e$2Ble\x85\x94e\xb1\x96\xcep\xfb\xdd-D\x04\xa5\x14\
  293. \xdeZ\'\xb1\x84\x85\xd8\x8bm\x84\xe6\x977\x7f8kog)\xba\xc4\xb7\xe5\xef$\xe2?\
  294. \xe9\xa9\xbf\x86R\n\x11a&\x1c\xc1^lC|\r.\x02\xb3\x8b\x9b\xa6&G\x13W\xaa\xbb\
  295. \x91_\x05\x0c\x1d\xbfI\xc7\xa1\x8e\xbf&a|:\x8c\xaf\xc1\x05J4\x8e\xd6>36\x192\
  296. \xc9d\xdc\xa4RI\xb3\xbaj\x99tz\xcd\xac\xaf\xa7\xcd\xc6F\xc6d\xb3Y\xf32\xf8\
  297. \xc58Z\xfb\x8c\x12\xfd\x07R\xa2\xb98\xf0\xd0\xbcx\xf3a[\xe0\xf2\xd0c\x93\xeb\
  298. nYD\xdb\xc9:\xcex\x0f\xe2\xadu2\x13\x8e0>\x1d\xc6\xff\xfa\xfd\xff\x17\x91K\
  299. \xf7\xf0\xa8\t\x04\xe7X\x89[\x94\x96\xd8\xf0y\x0ep\xb7\xeb\xdc?\xdb\xfb\r|\
  300. \xd0\xd1]\x98\xbdm\xdc\x00\x00\x00\x00IEND\xaeB`\x82\x91\xe2\x08\x8f' )
  301. def GetFlaggedBitmap():
  302. return wx.BitmapFromImage(GetFlaggedImage())
  303. def GetFlaggedImage():
  304. stream = cStringIO.StringIO(GetFlaggedData())
  305. return wx.ImageFromStream(stream)
  306. #----------------------------------------------------------------------
  307. def GetNotFlaggedData():
  308. return zlib.decompress(
  309. 'x\xda\x01\xad\x01R\xfe\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\r\x00\
  310. \x00\x00\r\x08\x06\x00\x00\x00r\xeb\xe4|\x00\x00\x00\x04sBIT\x08\x08\x08\x08\
  311. |\x08d\x88\x00\x00\x01dIDAT(\x91\x95\xd21K\x82a\x14\x86\xe1\xe7=\xef798\xb8\
  312. \x89\x0e"|Cd\x94\x88\x83\x065\x88\x108\x88Q\x8b-\xd1\x1f\x88\x9a\n\x04\x11j\
  313. \x8eh\x08\xdaZ\x84(\x82\xc2 0\xc1 $\xb4P\xa1\x10\x11D\xb061\xd4\xd4\xcc\xe44\
  314. \x84 \xa8Hg~.\xcer\x0bA\x12\x83\xb7ux\xce\xd1T\x01\xd5z\x0b:\xad\x06n\xbb\
  315. \x8a\x83\xcdU1\xb8\x11\x83\xc8\xe0\r\xf0\x92\xdd\x0c\x97\xd5\x04\x9b\xaaG\
  316. \xb6XA,]B\xe41\x8f\xf7\xab=1\x84Vv\x8e\xd97\xaf\xc29m\x04\x91\x84\x94\n\xa4\
  317. \x94P\x14\x05\x89\xd77\x9c\xc5_\x10\x0em\x08\x00\xa0\xfe\x87q@J\x89\xc593\
  318. \xfc\xaeY\x18\xbc\x01\x06\x00\xb1}t\xc9\xf5F\x03\x01\xbfs$ \x92 "\x10I\xec\
  319. \x9e\xdcBQ\x08\x14M\x15\xe0\xb2\x9a&\x02"\x82\xc71\x85h\xaa\x00\xaa\xd6[\xb0\
  320. \xa9\xfa\x89\x80\x88\xe0\xb0\x98P\xad\xb7@:\xad\x06\xd9be" "$se\xe8\xb4\x1a\
  321. \x90\xdb\xae"\x96.M\x04D\x84H"\x07\xb7]\x05\x04I\x18}A\xbe\xbe\x7f\xe6Z\xed\
  322. \x83\x1b\x8d\x1a7\x9b\x9f\xdcn\xb7\xb8\xd3\xf9\xe2n\xf7\x9b{\xbd\x1f\xbe{\
  323. \xca\xb3\xd1\x17dA\xf2\x0f\t\x92X\x0b\x9d\xf2\xcdCf,X\xdf\x0fs\x7f;T\xc4\xf2\
  324. \xc2\x0c<\x8e)8,&$seD\x129\\\xc43\xa3\x8b\xf8O{\xbf\xf1\xb5\xa5\x990\x0co\
  325. \xd6\x00\x00\x00\x00IEND\xaeB`\x82&\x11\xab!' )
  326. def GetNotFlaggedBitmap():
  327. return wx.BitmapFromImage(GetNotFlaggedImage())
  328. def GetNotFlaggedImage():
  329. stream = cStringIO.StringIO(GetNotFlaggedData())
  330. return wx.ImageFromStream(stream)
  331. #----------------------------------------------------------------------
  332. def GetCheckedData():
  333. return zlib.decompress(
  334. "x\xda\xeb\x0c\xf0s\xe7\xe5\x92\xe2b``\xe0\xf5\xf4p\t\x02\xd1 \xcc\xc1\x06$\
  335. \x8b^?\xa9\x01R,\xc5N\x9e!\x1c@P\xc3\x91\xd2\x01\xe4\xaf\xf4tq\x0c\xd1\x98\
  336. \x98<\x853\xe7\xc7y\x07\xa5\x84\xc4\x84\x84\x04\x0b3C1\xbd\x03'N\x1c9p\x84\
  337. \xe5\xe0\x993gx||\xce\x14\xcc\xea\xec\xect4^7\xbf\x91\xf3&\x8b\x93\xd4\x8c\
  338. \x19\n\xa7fv\\L\xd8p\x90C\xebx\xcf\x05\x17\x0ff \xb8c\xb6Cm\x06\xdb\xea\xd8\
  339. \xb2\x08\xd3\x03W\x0c\x8c\x8c\x16e%\xa5\xb5E\xe4\xee\xba\xca\xe4|\xb8\xb7\
  340. \xe35OOO\xcf\n\xb3\x83>m\x8c1R\x12\x92\x81s\xd8\x0b/\xb56\x14k|l\\\xc7x\xb4\
  341. \xf2\xc4\xc1*\xd5'B~\xbc\x19uNG\x98\x85\x85\x8d\xe3x%\x16\xb2_\xee\xf1\x07\
  342. \x99\xcb\xacl\x99\xc9\xcf\xb0\xc0_.\x87+\xff\x99\x05\xd0\xd1\x0c\x9e\xae~.\
  343. \xeb\x9c\x12\x9a\x00\x92\xccS\x9f" )
  344. def GetCheckedBitmap():
  345. return wx.BitmapFromImage(GetCheckedImage())
  346. def GetCheckedImage():
  347. stream = cStringIO.StringIO(GetCheckedData())
  348. return wx.ImageFromStream(stream)
  349. #----------------------------------------------------------------------
  350. def GetNotCheckedData():
  351. return zlib.decompress(
  352. "x\xda\xeb\x0c\xf0s\xe7\xe5\x92\xe2b``\xe0\xf5\xf4p\t\x02\xd1 \xcc\xc1\x06$\
  353. \x8b^?\xa9\x01R,\xc5N\x9e!\x1c@P\xc3\x91\xd2\x01\xe4\xe7z\xba8\x86hL\x9c{\
  354. \xe9 o\x83\x01\x07\xeb\x85\xf3\xed\x86w\x0ed\xdaT\x96\x8a\xbc\x9fw\xe7\xc4\
  355. \xd9/\x01\x8b\x97\x8a\xd7\xab*\xfar\xf0Ob\x93^\xf6\xd5%\x9d\x85A\xe6\xf6\x1f\
  356. \x11\x8f{/\x0b\xf8wX+\x9d\xf2\xb6:\x96\xca\xfe\x9a3\xbeA\xe7\xed\x1b\xc6%\
  357. \xfb=X3'sI-il\t\xb9\xa0\xc0;#\xd4\x835m\x9a\xf9J\x85\xda\x16.\x86\x03\xff\
  358. \xee\xdcc\xdd\xc0\xce\xf9\xc8\xcc(\xbe\x1bh1\x83\xa7\xab\x9f\xcb:\xa7\x84&\
  359. \x00\x87S=\xbe" )
  360. def GetNotCheckedBitmap():
  361. return wx.BitmapFromImage(GetNotCheckedImage())
  362. def GetNotCheckedImage():
  363. stream = cStringIO.StringIO(GetNotCheckedData())
  364. return wx.ImageFromStream(stream)
  365. def GrayOut(anImage):
  366. """
  367. Convert the given image (in place) to a grayed-out version,
  368. appropriate for a 'disabled' appearance.
  369. """
  370. factor = 0.7 # 0 < f < 1. Higher Is Grayer
  371. if anImage.HasMask():
  372. maskColor = (anImage.GetMaskRed(), anImage.GetMaskGreen(), anImage.GetMaskBlue())
  373. else:
  374. maskColor = None
  375. data = map(ord, list(anImage.GetData()))
  376. for i in range(0, len(data), 3):
  377. pixel = (data[i], data[i+1], data[i+2])
  378. pixel = MakeGray(pixel, factor, maskColor)
  379. for x in range(3):
  380. data[i+x] = pixel[x]
  381. anImage.SetData(''.join(map(chr, data)))
  382. return anImage
  383. def MakeGray((r,g,b), factor, maskColor):
  384. """
  385. Make a pixel grayed-out. If the pixel matches the maskcolor, it won't be
  386. changed.
  387. """
  388. if (r,g,b) != maskColor:
  389. return map(lambda x: int((230 - x) * factor) + x, (r,g,b))
  390. else:
  391. return (r,g,b)
  392. def DrawTreeItemButton(win, dc, rect, flags):
  393. """ A simple replacement of wx.RendererNative.DrawTreeItemButton. """
  394. # white background
  395. dc.SetPen(wx.GREY_PEN)
  396. dc.SetBrush(wx.WHITE_BRUSH)
  397. dc.DrawRectangleRect(rect)
  398. # black lines
  399. xMiddle = rect.x + rect.width/2
  400. yMiddle = rect.y + rect.height/2
  401. # half of the length of the horz lines in "-" and "+"
  402. halfWidth = rect.width/2 - 2
  403. dc.SetPen(wx.BLACK_PEN)
  404. dc.DrawLine(xMiddle - halfWidth, yMiddle,
  405. xMiddle + halfWidth + 1, yMiddle)
  406. if not flags & _CONTROL_EXPANDED:
  407. # turn "-" into "+"
  408. halfHeight = rect.height/2 - 2
  409. dc.DrawLine(xMiddle, yMiddle - halfHeight,
  410. xMiddle, yMiddle + halfHeight + 1)
  411. #---------------------------------------------------------------------------
  412. # DragImage Implementation
  413. # This Class Handles The Creation Of A Custom Image In Case Of Item Drag
  414. # And Drop.
  415. #---------------------------------------------------------------------------
  416. class DragImage(wx.DragImage):
  417. """
  418. This class handles the creation of a custom image in case of item drag
  419. and drop.
  420. """
  421. def __init__(self, treeCtrl, item):
  422. """
  423. Default class constructor.
  424. For internal use: do not call it in your code!
  425. """
  426. text = item.GetText()
  427. font = item.Attr().GetFont()
  428. colour = item.Attr().GetTextColour()
  429. if not colour:
  430. colour = wx.BLACK
  431. if not font:
  432. font = treeCtrl._normalFont
  433. backcolour = treeCtrl.GetBackgroundColour()
  434. r, g, b = int(backcolour.Red()), int(backcolour.Green()), int(backcolour.Blue())
  435. backcolour = ((r >> 1) + 20, (g >> 1) + 20, (b >> 1) + 20)
  436. backcolour = wx.Colour(backcolour[0], backcolour[1], backcolour[2])
  437. self._backgroundColour = backcolour
  438. tempdc = wx.ClientDC(treeCtrl)
  439. tempdc.SetFont(font)
  440. width, height, dummy = tempdc.GetMultiLineTextExtent(text + "M")
  441. image = item.GetCurrentImage()
  442. image_w, image_h = 0, 0
  443. wcheck, hcheck = 0, 0
  444. itemcheck = None
  445. itemimage = None
  446. ximagepos = 0
  447. yimagepos = 0
  448. xcheckpos = 0
  449. ycheckpos = 0
  450. if image != _NO_IMAGE:
  451. if treeCtrl._imageListNormal:
  452. image_w, image_h = treeCtrl._imageListNormal.GetSize(image)
  453. image_w += 4
  454. itemimage = treeCtrl._imageListNormal.GetBitmap(image)
  455. checkimage = item.GetCurrentCheckedImage()
  456. if checkimage is not None:
  457. if treeCtrl._imageListCheck:
  458. wcheck, hcheck = treeCtrl._imageListCheck.GetSize(checkimage)
  459. wcheck += 4
  460. itemcheck = treeCtrl._imageListCheck.GetBitmap(checkimage)
  461. total_h = max(hcheck, height)
  462. total_h = max(image_h, total_h)
  463. if image_w:
  464. ximagepos = wcheck
  465. yimagepos = ((total_h > image_h) and [(total_h-image_h)/2] or [0])[0]
  466. if checkimage is not None:
  467. xcheckpos = 2
  468. ycheckpos = ((total_h > image_h) and [(total_h-image_h)/2] or [0])[0] + 2
  469. extraH = ((total_h > height) and [(total_h - height)/2] or [0])[0]
  470. xtextpos = wcheck + image_w
  471. ytextpos = extraH
  472. total_h = max(image_h, hcheck)
  473. total_h = max(total_h, height)
  474. if total_h < 30:
  475. total_h += 2 # at least 2 pixels
  476. else:
  477. total_h += total_h/10 # otherwise 10% extra spacing
  478. total_w = image_w + wcheck + width
  479. self._total_w = total_w
  480. self._total_h = total_h
  481. self._itemimage = itemimage
  482. self._itemcheck = itemcheck
  483. self._text = text
  484. self._colour = colour
  485. self._font = font
  486. self._xtextpos = xtextpos
  487. self._ytextpos = ytextpos
  488. self._ximagepos = ximagepos
  489. self._yimagepos = yimagepos
  490. self._xcheckpos = xcheckpos
  491. self._ycheckpos = ycheckpos
  492. self._textwidth = width
  493. self._textheight = height
  494. self._extraH = extraH
  495. self._bitmap = self.CreateBitmap()
  496. wx.DragImage.__init__(self, self._bitmap)
  497. def CreateBitmap(self):
  498. """Actually creates the dnd bitmap."""
  499. memory = wx.MemoryDC()
  500. bitmap = wx.EmptyBitmap(self._total_w, self._total_h)
  501. memory.SelectObject(bitmap)
  502. memory.SetTextBackground(self._backgroundColour)
  503. memory.SetBackground(wx.Brush(self._backgroundColour))
  504. memory.SetFont(self._font)
  505. memory.SetTextForeground(self._colour)
  506. memory.Clear()
  507. if self._itemimage:
  508. memory.DrawBitmap(self._itemimage, self._ximagepos, self._yimagepos, True)
  509. if self._itemcheck:
  510. memory.DrawBitmap(self._itemcheck, self._xcheckpos, self._ycheckpos, True)
  511. textrect = wx.Rect(self._xtextpos, self._ytextpos+self._extraH, self._textwidth, self._textheight)
  512. memory.DrawLabel(self._text, textrect)
  513. memory.SelectObject(wx.NullBitmap)
  514. return bitmap
  515. # ----------------------------------------------------------------------------
  516. # TreeItemAttr: a structure containing the visual attributes of an item
  517. # ----------------------------------------------------------------------------
  518. class TreeItemAttr:
  519. """Creates the item attributes (text colour, background colour and font)."""
  520. def __init__(self, colText=wx.NullColour, colBack=wx.NullColour, font=wx.NullFont):
  521. """
  522. Default class constructor.
  523. For internal use: do not call it in your code!
  524. """
  525. self._colText = colText
  526. self._colBack = colBack
  527. self._font = font
  528. # setters
  529. def SetTextColour(self, colText):
  530. """Sets the attribute text colour."""
  531. self._colText = colText
  532. def SetBackgroundColour(self, colBack):
  533. """Sets the attribute background colour."""
  534. self._colBack = colBack
  535. def SetFont(self, font):
  536. """Sets the attribute font."""
  537. self._font = font
  538. # accessors
  539. def HasTextColour(self):
  540. """Returns whether the attribute has text colour."""
  541. return self._colText != wx.NullColour
  542. def HasBackgroundColour(self):
  543. """Returns whether the attribute has background colour."""
  544. return self._colBack != wx.NullColour
  545. def HasFont(self):
  546. """Returns whether the attribute has font."""
  547. return self._font != wx.NullFont
  548. # getters
  549. def GetTextColour(self):
  550. """Returns the attribute text colour."""
  551. return self._colText
  552. def GetBackgroundColour(self):
  553. """Returns the attribute background colour."""
  554. return self._colBack
  555. def GetFont(self):
  556. """Returns the attribute font."""
  557. return self._font
  558. # ----------------------------------------------------------------------------
  559. # CommandTreeEvent Is A Special Subclassing Of wx.PyCommandEvent
  560. #
  561. # NB: Note That Not All The Accessors Make Sense For All The Events, See The
  562. # Event Description Below.
  563. # ----------------------------------------------------------------------------
  564. class CommandTreeEvent(wx.PyCommandEvent):
  565. """
  566. CommandTreeEvent is a special subclassing of wx.PyCommandEvent.
  567. NB: note that not all the accessors make sense for all the events, see the
  568. event description for every method in this class.
  569. """
  570. def __init__(self, type, id, item=None, evtKey=None, point=None,
  571. label=None, **kwargs):
  572. """
  573. Default class constructor.
  574. For internal use: do not call it in your code!
  575. """
  576. wx.PyCommandEvent.__init__(self, type, id, **kwargs)
  577. self._item = item
  578. self._evtKey = evtKey
  579. self._pointDrag = point
  580. self._label = label
  581. def GetItem(self):
  582. """
  583. Gets the item on which the operation was performed or the newly selected
  584. item for EVT_TREE_SEL_CHANGED/ING events.
  585. """
  586. return self._item
  587. def SetItem(self, item):
  588. """
  589. Sets the item on which the operation was performed or the newly selected
  590. item for EVT_TREE_SEL_CHANGED/ING events.
  591. """
  592. self._item = item
  593. def GetOldItem(self):
  594. """For EVT_TREE_SEL_CHANGED/ING events, gets the previously selected item."""
  595. return self._itemOld
  596. def SetOldItem(self, item):
  597. """For EVT_TREE_SEL_CHANGED/ING events, sets the previously selected item."""
  598. self._itemOld = item
  599. def GetPoint(self):
  600. """
  601. Returns the point where the mouse was when the drag operation started
  602. (for EVT_TREE_BEGIN(R)DRAG events only) or the click position.
  603. """
  604. return self._pointDrag
  605. def SetPoint(self, pt):
  606. """
  607. Sets the point where the mouse was when the drag operation started
  608. (for EVT_TREE_BEGIN(R)DRAG events only) or the click position.
  609. """
  610. self._pointDrag = pt
  611. def GetKeyEvent(self):
  612. """Keyboard data (for EVT_TREE_KEY_DOWN only)."""
  613. return self._evtKey
  614. def GetKeyCode(self):
  615. """Returns the integer key code (for EVT_TREE_KEY_DOWN only)."""
  616. return self._evtKey.GetKeyCode()
  617. def SetKeyEvent(self, evt):
  618. """Keyboard data (for EVT_TREE_KEY_DOWN only)."""
  619. self._evtKey = evt
  620. def GetLabel(self):
  621. """Returns the label-itemtext (for EVT_TREE_BEGIN|END_LABEL_EDIT only)."""
  622. return self._label
  623. def SetLabel(self, label):
  624. """Sets the label-itemtext (for EVT_TREE_BEGIN|END_LABEL_EDIT only)."""
  625. self._label = label
  626. def IsEditCancelled(self):
  627. """Returns the edit cancel flag (for EVT_TREE_BEGIN|END_LABEL_EDIT only)."""
  628. return self._editCancelled
  629. def SetEditCanceled(self, editCancelled):
  630. """Sets the edit cancel flag (for EVT_TREE_BEGIN|END_LABEL_EDIT only)."""
  631. self._editCancelled = editCancelled
  632. def SetToolTip(self, toolTip):
  633. """Sets the tooltip for the item (for EVT_TREE_ITEM_GETTOOLTIP events)."""
  634. self._label = toolTip
  635. def GetToolTip(self):
  636. """Gets the tooltip for the item (for EVT_TREE_ITEM_GETTOOLTIP events)."""
  637. return self._label
  638. # ----------------------------------------------------------------------------
  639. # TreeEvent is a special class for all events associated with tree controls
  640. #
  641. # NB: note that not all accessors make sense for all events, see the event
  642. # descriptions below
  643. # ----------------------------------------------------------------------------
  644. class TreeEvent(CommandTreeEvent):
  645. def __init__(self, type, id, item=None, evtKey=None, point=None,
  646. label=None, **kwargs):
  647. """
  648. Default class constructor.
  649. For internal use: do not call it in your code!
  650. """
  651. CommandTreeEvent.__init__(self, type, id, item, evtKey, point, label, **kwargs)
  652. self.notify = wx.NotifyEvent(type, id)
  653. def GetNotifyEvent(self):
  654. """Returns the actual wx.NotifyEvent."""
  655. return self.notify
  656. def IsAllowed(self):
  657. """Returns whether the event is allowed or not."""
  658. return self.notify.IsAllowed()
  659. def Veto(self):
  660. """Vetos the event."""
  661. self.notify.Veto()
  662. def Allow(self):
  663. """The event is allowed."""
  664. self.notify.Allow()
  665. # -----------------------------------------------------------------------------
  666. # Auxiliary Classes: TreeRenameTimer
  667. # -----------------------------------------------------------------------------
  668. class TreeRenameTimer(wx.Timer):
  669. """Timer used for enabling in-place edit."""
  670. def __init__(self, owner):
  671. """
  672. Default class constructor.
  673. For internal use: do not call it in your code!
  674. """
  675. wx.Timer.__init__(self)
  676. self._owner = owner
  677. def Notify(self):
  678. """The timer has expired."""
  679. self._owner.OnRenameTimer()
  680. # -----------------------------------------------------------------------------
  681. # Auxiliary Classes: TreeTextCtrl
  682. # This Is The Temporary wx.TextCtrl Created When You Edit The Text Of An Item
  683. # -----------------------------------------------------------------------------
  684. class TreeTextCtrl(wx.TextCtrl):
  685. """Control used for in-place edit."""
  686. def __init__(self, owner, item=None):
  687. """
  688. Default class constructor.
  689. For internal use: do not call it in your code!
  690. """
  691. self._owner = owner
  692. self._itemEdited = item
  693. self._startValue = item.GetText()
  694. self._finished = False
  695. self._aboutToFinish = False
  696. w = self._itemEdited.GetWidth()
  697. h = self._itemEdited.GetHeight()
  698. wnd = self._itemEdited.GetWindow()
  699. if wnd:
  700. w = w - self._itemEdited.GetWindowSize()[0]
  701. h = 0
  702. x, y = self._owner.CalcScrolledPosition(item.GetX(), item.GetY())
  703. image_h = 0
  704. image_w = 0
  705. image = item.GetCurrentImage()
  706. if image != _NO_IMAGE:
  707. if self._owner._imageListNormal:
  708. image_w, image_h = self._owner._imageListNormal.GetSize(image)
  709. image_w += 4
  710. else:
  711. raise Exception("\n ERROR: You Must Create An Image List To Use Images!")
  712. checkimage = item.GetCurrentCheckedImage()
  713. if checkimage is not None:
  714. wcheck, hcheck = self._owner._imageListCheck.GetSize(checkimage)
  715. wcheck += 4
  716. else:
  717. wcheck = 0
  718. if wnd:
  719. h = max(hcheck, image_h)
  720. dc = wx.ClientDC(self._owner)
  721. h = max(h, dc.GetTextExtent("Aq")[1])
  722. h = h + 2
  723. # FIXME: what are all these hardcoded 4, 8 and 11s really?
  724. x += image_w + wcheck
  725. w -= image_w + 4 + wcheck
  726. wx.TextCtrl.__init__(self, self._owner, wx.ID_ANY, self._startValue,
  727. wx.Point(x - 4, y), wx.Size(w + 15, h))
  728. if wx.Platform == "__WXMAC__":
  729. self.SetFont(owner.GetFont())
  730. bs = self.GetBestSize()
  731. self.SetSize((-1, bs.height))
  732. self.Bind(wx.EVT_CHAR, self.OnChar)
  733. self.Bind(wx.EVT_KEY_UP, self.OnKeyUp)
  734. self.Bind(wx.EVT_KILL_FOCUS, self.OnKillFocus)
  735. def AcceptChanges(self):
  736. """Accepts/refuses the changes made by the user."""
  737. value = self.GetValue()
  738. if value == self._startValue:
  739. # nothing changed, always accept
  740. # when an item remains unchanged, the owner
  741. # needs to be notified that the user decided
  742. # not to change the tree item label, and that
  743. # the edit has been cancelled
  744. self._owner.OnRenameCancelled(self._itemEdited)
  745. return True
  746. if not self._owner.OnRenameAccept(self._itemEdited, value):
  747. # vetoed by the user
  748. return False
  749. # accepted, do rename the item
  750. self._owner.SetItemText(self._itemEdited, value)
  751. return True
  752. def Finish(self):
  753. """Finish editing."""
  754. if not self._finished:
  755. ## wxPendingDelete.Append(this)
  756. self._finished = True
  757. self._owner.SetFocusIgnoringChildren()
  758. self._owner.ResetTextControl()
  759. def OnChar(self, event):
  760. """Handles the wx.EVT_CHAR event for TreeTextCtrl."""
  761. keycode = event.GetKeyCode()
  762. if keycode == wx.WXK_RETURN:
  763. self._aboutToFinish = True
  764. # Notify the owner about the changes
  765. self.AcceptChanges()
  766. # Even if vetoed, close the control (consistent with MSW)
  767. wx.CallAfter(self.Finish)
  768. elif keycode == wx.WXK_ESCAPE:
  769. self.StopEditing()
  770. else:
  771. event.Skip()
  772. def OnKeyUp(self, event):
  773. """Handles the wx.EVT_KEY_UP event for TreeTextCtrl."""
  774. if not self._finished:
  775. # auto-grow the textctrl:
  776. parentSize = self._owner.GetSize()
  777. myPos = self.GetPosition()
  778. mySize = self.GetSize()
  779. sx, sy = self.GetTextExtent(self.GetValue() + "M")
  780. if myPos.x + sx > parentSize.x:
  781. sx = parentSize.x - myPos.x
  782. if mySize.x > sx:
  783. sx = mySize.x
  784. self.SetSize((sx, -1))
  785. event.Skip()
  786. def OnKillFocus(self, event):
  787. """Handles the wx.EVT_KILL_FOCUS event for TreeTextCtrl."""
  788. # I commented out those lines, and everything seems to work fine.
  789. # But why in the world are these lines of code here? Maybe GTK
  790. # or MAC give troubles?
  791. ## if not self._finished and not self._aboutToFinish:
  792. ##
  793. ## # We must finish regardless of success, otherwise we'll get
  794. ## # focus problems:
  795. ##
  796. ## if not self.AcceptChanges():
  797. ## self._owner.OnRenameCancelled(self._itemEdited)
  798. # We must let the native text control handle focus, too, otherwise
  799. # it could have problems with the cursor (e.g., in wxGTK).
  800. event.Skip()
  801. def StopEditing(self):
  802. """Suddenly stops the editing."""
  803. self._owner.OnRenameCancelled(self._itemEdited)
  804. self.Finish()
  805. def item(self):
  806. """Returns the item currently edited."""
  807. return self._itemEdited
  808. # -----------------------------------------------------------------------------
  809. # Auxiliary Classes: TreeFindTimer
  810. # Timer Used To Clear CustomTreeCtrl._findPrefix If No Key Was Pressed For A
  811. # Sufficiently Long Time.
  812. # -----------------------------------------------------------------------------
  813. class TreeFindTimer(wx.Timer):
  814. """
  815. Timer used to clear CustomTreeCtrl._findPrefix if no key was pressed
  816. for a sufficiently long time.
  817. """
  818. def __init__(self, owner):
  819. """
  820. Default class constructor.
  821. For internal use: do not call it in your code!
  822. """
  823. wx.Timer.__init__(self)
  824. self._owner = owner
  825. def Notify(self):
  826. """The timer has expired."""
  827. self._owner._findPrefix = ""
  828. # -----------------------------------------------------------------------------
  829. # GenericTreeItem Implementation.
  830. # This Class Holds All The Information And Methods For Every Single Item In
  831. # CustomTreeCtrl.
  832. # -----------------------------------------------------------------------------
  833. class GenericTreeItem:
  834. """
  835. This class holds all the information and methods for every single item in
  836. CustomTreeCtrl. No wx based.
  837. """
  838. def __init__(self, parent, text="", ct_type=0, wnd=None, image=-1, selImage=-1, data=None):
  839. """
  840. Default class constructor.
  841. For internal use: do not call it in your code!
  842. """
  843. # since there can be very many of these, we save size by chosing
  844. # the smallest representation for the elements and by ordering
  845. # the members to avoid padding.
  846. assert isinstance(text, types.StringTypes)
  847. self._text = text # label to be rendered for item
  848. self._data = data # user-provided data
  849. self._children = [] # list of children
  850. self._parent = parent # parent of this item
  851. self._attr = None # attributes???
  852. # tree ctrl images for the normal, selected, expanded and
  853. # expanded+selected states
  854. self._images = [-1, -1, -1, -1]
  855. self._images[TreeItemIcon_Normal] = image
  856. self._images[TreeItemIcon_Selected] = selImage
  857. self._images[TreeItemIcon_Expanded] = _NO_IMAGE
  858. self._images[TreeItemIcon_SelectedExpanded] = _NO_IMAGE
  859. self._checkedimages = [None, None, None, None]
  860. self._x = 0 # (virtual) offset from top
  861. self._y = 0 # (virtual) offset from left
  862. self._width = 0 # width of this item
  863. self._height = 0 # height of this item
  864. self._isCollapsed = True
  865. self._hasHilight = False # same as focused
  866. self._hasPlus = False # used for item which doesn't have
  867. # children but has a [+] button
  868. self._isBold = False # render the label in bold font
  869. self._isItalic = False # render the label in italic font
  870. self._ownsAttr = False # delete attribute when done
  871. self._type = ct_type # item type: 0=normal, 1=check, 2=radio
  872. self._checked = False # only meaningful for check and radio
  873. self._enabled = True # flag to enable/disable an item
  874. self._hypertext = False # indicates if the item is hypertext
  875. self._visited = False # visited state for an hypertext item
  876. if self._type > 0:
  877. # do not construct the array for normal items
  878. self._checkedimages[TreeItemIcon_Checked] = 0
  879. self._checkedimages[TreeItemIcon_NotChecked] = 1
  880. self._checkedimages[TreeItemIcon_Flagged] = 2
  881. self._checkedimages[TreeItemIcon_NotFlagged] = 3
  882. if parent:
  883. if parent.GetType() == 2 and not parent.IsChecked():
  884. # if the node parent is a radio not enabled, we are disabled
  885. self._enabled = False
  886. self._wnd = wnd # are we holding a window?
  887. if wnd:
  888. self.SetWindow(wnd)
  889. def IsOk(self):
  890. """
  891. Returns whether the item is ok or not. Useless on Python, but added for
  892. backward compatibility with the C++ implementation.
  893. """
  894. return True
  895. def GetChildren(self):
  896. """Returns the item's children."""
  897. return self._children
  898. def GetText(self):
  899. """Returns the item text."""
  900. return self._text
  901. def GetImage(self, which=TreeItemIcon_Normal):
  902. """Returns the item image for a particular state."""
  903. return self._images[which]
  904. def GetCheckedImage(self, which=TreeItemIcon_Checked):
  905. """Returns the item check image. Meaningful only for radio & check items."""
  906. return self._checkedimages[which]
  907. def GetData(self):
  908. """Returns the data associated to this item."""
  909. return self._data
  910. def SetImage(self, image, which):
  911. """Sets the item image."""
  912. self._images[which] = image
  913. def SetData(self, data):
  914. """Sets the data associated to this item."""
  915. self._data = data
  916. def SetHasPlus(self, has=True):
  917. """Sets whether an item has the 'plus' button."""
  918. self._hasPlus = has
  919. def SetBold(self, bold):
  920. """Sets the item font bold."""
  921. self._isBold = bold
  922. def SetItalic(self, italic):
  923. """Sets the item font italic."""
  924. self._isItalic = italic
  925. def GetX(self):
  926. """Returns the x position on an item in the ScrolledWindow."""
  927. return self._x
  928. def GetY(self):
  929. """Returns the y position on an item in the ScrolledWindow."""
  930. return self._y
  931. def SetX(self, x):
  932. """Sets the x position on an item in the ScrolledWindow."""
  933. self._x = x
  934. def SetY(self, y):
  935. """Sets the y position on an item in the ScrolledWindow."""
  936. self._y = y
  937. def GetHeight(self):
  938. """Returns the height of the item."""
  939. return self._height
  940. def GetWidth(self):
  941. """Returns the width of the item."""
  942. return self._width
  943. def SetHeight(self, h):
  944. """Sets the height of the item."""
  945. self._height = h
  946. def SetWidth(self, w):
  947. """Sets the width of the item."""
  948. self._width = w
  949. def SetWindow(self, wnd):
  950. """Sets the window associated to the item."""
  951. self._wnd = wnd
  952. if wnd.GetSizer(): # the window is a complex one hold by a sizer
  953. size = wnd.GetBestSize()
  954. else: # simple window, without sizers
  955. size = wnd.GetSize()
  956. # We have to bind the wx.EVT_SET_FOCUS for the associated window
  957. # No other solution to handle the focus changing from an item in
  958. # CustomTreeCtrl and the window associated to an item
  959. # Do better strategies exist?
  960. self._wnd.Bind(wx.EVT_SET_FOCUS, self.OnSetFocus)
  961. self._height = size.GetHeight() + 2
  962. self._width = size.GetWidth()
  963. self._windowsize = size
  964. # We don't show the window if the item is collapsed
  965. if self._isCollapsed:
  966. self._wnd.Show(False)
  967. # The window is enabled only if the item is enabled
  968. self._wnd.Enable(self._enabled)
  969. self._windowenabled = self._enabled
  970. def GetWindow(self):
  971. """Returns the window associated to the item."""
  972. return self._wnd
  973. def DeleteWindow(self):
  974. """Deletes the window associated to the item (if any)."""
  975. if self._wnd:
  976. self._wnd.Destroy()
  977. self._wnd = None
  978. def GetWindowEnabled(self):
  979. """Returns whether the associated window is enabled or not."""
  980. if not self._wnd:
  981. raise Exception("\nERROR: This Item Has No Window Associated")
  982. return self._windowenabled
  983. def SetWindowEnabled(self, enable=True):
  984. """Sets whether the associated window is enabled or not."""
  985. if not self._wnd:
  986. raise Exception("\nERROR: This Item Has No Window Associated")
  987. self._windowenabled = enable
  988. self._wnd.Enable(enable)
  989. def GetWindowSize(self):
  990. """Returns the associated window size."""
  991. return self._windowsize
  992. def OnSetFocus(self, event):
  993. """Handles the wx.EVT_SET_FOCUS event for the associated window."""
  994. treectrl = self._wnd.GetParent()
  995. select = treectrl.GetSelection()
  996. # If the window is associated to an item that currently is selected
  997. # (has focus) we don't kill the focus. Otherwise we do it.
  998. if select != self:
  999. treectrl._hasFocus = False
  1000. else:
  1001. treectrl._hasFocus = True
  1002. event.Skip()
  1003. def GetType(self):
  1004. """
  1005. Returns the item type. It should be one of:
  1006. 0: normal items
  1007. 1: checkbox item
  1008. 2: radiobutton item
  1009. """
  1010. return self._type
  1011. def SetHyperText(self, hyper=True):
  1012. """Sets whether the item is hypertext or not."""
  1013. self._hypertext = hyper
  1014. def SetVisited(self, visited=True):
  1015. """Sets whether an hypertext item was visited or not."""
  1016. self._visited = visited
  1017. def GetVisited(self):
  1018. """Returns whether an hypertext item was visited or not."""
  1019. return self._visited
  1020. def IsHyperText(self):
  1021. """Returns whether the item is hypetext or not."""
  1022. return self._hypertext
  1023. def GetParent(self):
  1024. """Gets the item parent."""
  1025. return self._parent
  1026. def Insert(self, child, index):
  1027. """Inserts an item in the item children."""
  1028. self._children.insert(index, child)
  1029. def Expand(self):
  1030. """Expand the item."""
  1031. self._isCollapsed = False
  1032. def Collapse(self):
  1033. """Collapse the item."""
  1034. self._isCollapsed = True
  1035. def SetHilight(self, set=True):
  1036. """Sets the item focus/unfocus."""
  1037. self._hasHilight = set
  1038. def HasChildr…

Large files files are truncated, but you can click here to view the full file