1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45 """
46 Description
47 ===========
48
49 CustomTreeCtrl is a class that mimics the behaviour of wx.TreeCtrl, with almost the
50 same base functionalities plus some more enhancements. This class does not rely on
51 the native control, as it is a full owner-drawn tree control.
52 Apart of the base functionalities of CustomTreeCtrl (described below), in addition
53 to the standard wx.TreeCtrl behaviour this class supports:
54
55 * CheckBox-type items: checkboxes are easy to handle, just selected or unselected
56 state with no particular issues in handling the item's children;
57
58 * RadioButton-type items: since I elected to put radiobuttons in CustomTreeCtrl, I
59 needed some way to handle them, that made sense. So, I used the following approach:
60 - All peer-nodes that are radiobuttons will be mutually exclusive. In other words,
61 only one of a set of radiobuttons that share a common parent can be checked at
62 once. If a radiobutton node becomes checked, then all of its peer radiobuttons
63 must be unchecked.
64 - If a radiobutton node becomes unchecked, then all of its child nodes will become
65 inactive.
66
67 * Hyperlink-type items: they look like an hyperlink, with the proper mouse cursor on
68 hovering.
69
70 * Multiline text items.
71
72 * Enabling/disabling items (together with their plain or grayed out icons).
73
74 * Whatever non-toplevel widget can be attached next to an item.
75
76 * Default selection style, gradient (horizontal/vertical) selection style and Windows
77 Vista selection style.
78
79 * Customized drag and drop images built on the fly.
80
81 * Setting the CustomTreeCtrl item buttons to a personalized imagelist.
82
83 * Setting the CustomTreeCtrl check/radio item icons to a personalized imagelist.
84
85 * Changing the style of the lines that connect the items (in terms of wx.Pen styles).
86
87 * Using an image as a CustomTreeCtrl background (currently only in "tile" mode).
88
89 And a lot more. Check the demo for an almost complete review of the functionalities.
90
91
92 Base Functionalities
93 ====================
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
98 Plus it has 2 more styles to handle checkbox-type items:
99 - TR_AUTO_CHECK_CHILD : automatically checks/unchecks the item children;
100 - TR_AUTO_TOGGLE_CHILD: automatically toggles the item children.
101
102 All the methods available in wx.TreeCtrl are also available in CustomTreeCtrl.
103
104
105 Events
106 ======
107
108 All the events supported by wx.TreeCtrl are also available in CustomTreeCtrl, with
109 a few exceptions:
110
111 - EVT_TREE_GET_INFO (don't know what this means);
112 - EVT_TREE_SET_INFO (don't know what this means);
113 - EVT_TREE_ITEM_MIDDLE_CLICK (not implemented, but easy to add);
114 - EVT_TREE_STATE_IMAGE_CLICK: no need for that, look at the checking events below.
115
116 Plus, CustomTreeCtrl supports the events related to the checkbutton-type items:
117
118 - EVT_TREE_ITEM_CHECKING: an item is being checked;
119 - EVT_TREE_ITEM_CHECKED: an item has been checked.
120
121 And to hyperlink-type items:
122
123 - EVT_TREE_ITEM_HYPERLINK: an hyperlink item has been clicked (this event is sent
124 after the EVT_TREE_SEL_CHANGED event).
125
126
127 Supported Platforms
128 ===================
129
130 CustomTreeCtrl has been tested on the following platforms:
131 * Windows (Windows XP);
132 * GTK (Thanks to Michele Petrazzo);
133 * Mac OS (Thanks to John Jackson).
134
135
136 Latest Revision: Andrea Gavana @ 26 May 2006, 11.30 CET
137 Version 0.7
138
139 """
140
141
142 import wx
143 import zlib
144 import cStringIO
145
146
147
148
149
150 _NO_IMAGE = -1
151 _PIXELS_PER_UNIT = 10
152
153
154
155 _DELAY = 500
156
157
158
159
160
161
162 TreeItemIcon_Normal = 0
163 TreeItemIcon_Selected = 1
164 TreeItemIcon_Expanded = 2
165 TreeItemIcon_SelectedExpanded = 3
166
167 TreeItemIcon_Checked = 0
168 TreeItemIcon_NotChecked = 1
169 TreeItemIcon_Flagged = 2
170 TreeItemIcon_NotFlagged = 3
171
172
173
174
175
176 TR_NO_BUTTONS = wx.TR_NO_BUTTONS
177 TR_HAS_BUTTONS = wx.TR_HAS_BUTTONS
178 TR_NO_LINES = wx.TR_NO_LINES
179 TR_LINES_AT_ROOT = wx.TR_LINES_AT_ROOT
180 TR_TWIST_BUTTONS = wx.TR_TWIST_BUTTONS
181
182 TR_SINGLE = wx.TR_SINGLE
183 TR_MULTIPLE = wx.TR_MULTIPLE
184 TR_EXTENDED = wx.TR_EXTENDED
185 TR_HAS_VARIABLE_ROW_HEIGHT = wx.TR_HAS_VARIABLE_ROW_HEIGHT
186
187 TR_EDIT_LABELS = wx.TR_EDIT_LABELS
188 TR_ROW_LINES = wx.TR_ROW_LINES
189 TR_HIDE_ROOT = wx.TR_HIDE_ROOT
190
191 TR_FULL_ROW_HIGHLIGHT = wx.TR_FULL_ROW_HIGHLIGHT
192
193 TR_AUTO_CHECK_CHILD = 0x4000
194 TR_AUTO_TOGGLE_CHILD = 0x8000
195
196 TR_DEFAULT_STYLE = wx.TR_DEFAULT_STYLE
197
198
199
200
201 TREE_HITTEST_ABOVE = wx.TREE_HITTEST_ABOVE
202 TREE_HITTEST_BELOW = wx.TREE_HITTEST_BELOW
203 TREE_HITTEST_NOWHERE = wx.TREE_HITTEST_NOWHERE
204
205 TREE_HITTEST_ONITEMBUTTON = wx.TREE_HITTEST_ONITEMBUTTON
206
207 TREE_HITTEST_ONITEMICON = wx.TREE_HITTEST_ONITEMICON
208
209 TREE_HITTEST_ONITEMINDENT = wx.TREE_HITTEST_ONITEMINDENT
210
211 TREE_HITTEST_ONITEMLABEL = wx.TREE_HITTEST_ONITEMLABEL
212
213 TREE_HITTEST_ONITEMRIGHT = wx.TREE_HITTEST_ONITEMRIGHT
214
215 TREE_HITTEST_ONITEMSTATEICON = wx.TREE_HITTEST_ONITEMSTATEICON
216
217 TREE_HITTEST_TOLEFT = wx.TREE_HITTEST_TOLEFT
218
219 TREE_HITTEST_TORIGHT = wx.TREE_HITTEST_TORIGHT
220
221 TREE_HITTEST_ONITEMUPPERPART = wx.TREE_HITTEST_ONITEMUPPERPART
222
223 TREE_HITTEST_ONITEMLOWERPART = wx.TREE_HITTEST_ONITEMLOWERPART
224
225 TREE_HITTEST_ONITEMCHECKICON = 0x4000
226
227 TREE_HITTEST_ONITEM = TREE_HITTEST_ONITEMICON | TREE_HITTEST_ONITEMLABEL | TREE_HITTEST_ONITEMCHECKICON
228
229
230
231 _StyleTile = 0
232 _StyleStretch = 1
233
234
235 _rgbSelectOuter = wx.Colour(170, 200, 245)
236 _rgbSelectInner = wx.Colour(230, 250, 250)
237 _rgbSelectTop = wx.Colour(210, 240, 250)
238 _rgbSelectBottom = wx.Colour(185, 215, 250)
239 _rgbNoFocusTop = wx.Colour(250, 250, 250)
240 _rgbNoFocusBottom = wx.Colour(235, 235, 235)
241 _rgbNoFocusOuter = wx.Colour(220, 220, 220)
242 _rgbNoFocusInner = wx.Colour(245, 245, 245)
243
244
245
246 __version__ = "0.7"
247
248
249
250
251
252
253 wxEVT_TREE_BEGIN_DRAG = wx.wxEVT_COMMAND_TREE_BEGIN_DRAG
254 wxEVT_TREE_BEGIN_RDRAG = wx.wxEVT_COMMAND_TREE_BEGIN_RDRAG
255 wxEVT_TREE_BEGIN_LABEL_EDIT = wx.wxEVT_COMMAND_TREE_BEGIN_LABEL_EDIT
256 wxEVT_TREE_END_LABEL_EDIT = wx.wxEVT_COMMAND_TREE_END_LABEL_EDIT
257 wxEVT_TREE_DELETE_ITEM = wx.wxEVT_COMMAND_TREE_DELETE_ITEM
258 wxEVT_TREE_GET_INFO = wx.wxEVT_COMMAND_TREE_GET_INFO
259 wxEVT_TREE_SET_INFO = wx.wxEVT_COMMAND_TREE_SET_INFO
260 wxEVT_TREE_ITEM_EXPANDED = wx.wxEVT_COMMAND_TREE_ITEM_EXPANDED
261 wxEVT_TREE_ITEM_EXPANDING = wx.wxEVT_COMMAND_TREE_ITEM_EXPANDING
262 wxEVT_TREE_ITEM_COLLAPSED = wx.wxEVT_COMMAND_TREE_ITEM_COLLAPSED
263 wxEVT_TREE_ITEM_COLLAPSING = wx.wxEVT_COMMAND_TREE_ITEM_COLLAPSING
264 wxEVT_TREE_SEL_CHANGED = wx.wxEVT_COMMAND_TREE_SEL_CHANGED
265 wxEVT_TREE_SEL_CHANGING = wx.wxEVT_COMMAND_TREE_SEL_CHANGING
266 wxEVT_TREE_KEY_DOWN = wx.wxEVT_COMMAND_TREE_KEY_DOWN
267 wxEVT_TREE_ITEM_ACTIVATED = wx.wxEVT_COMMAND_TREE_ITEM_ACTIVATED
268 wxEVT_TREE_ITEM_RIGHT_CLICK = wx.wxEVT_COMMAND_TREE_ITEM_RIGHT_CLICK
269 wxEVT_TREE_ITEM_MIDDLE_CLICK = wx.wxEVT_COMMAND_TREE_ITEM_MIDDLE_CLICK
270 wxEVT_TREE_END_DRAG = wx.wxEVT_COMMAND_TREE_END_DRAG
271 wxEVT_TREE_STATE_IMAGE_CLICK = wx.wxEVT_COMMAND_TREE_STATE_IMAGE_CLICK
272 wxEVT_TREE_ITEM_GETTOOLTIP = wx.wxEVT_COMMAND_TREE_ITEM_GETTOOLTIP
273 wxEVT_TREE_ITEM_MENU = wx.wxEVT_COMMAND_TREE_ITEM_MENU
274 wxEVT_TREE_ITEM_CHECKING = wx.NewEventType()
275 wxEVT_TREE_ITEM_CHECKED = wx.NewEventType()
276 wxEVT_TREE_ITEM_HYPERLINK = wx.NewEventType()
277
278 EVT_TREE_BEGIN_DRAG = wx.EVT_TREE_BEGIN_DRAG
279 EVT_TREE_BEGIN_RDRAG = wx.EVT_TREE_BEGIN_RDRAG
280 EVT_TREE_BEGIN_LABEL_EDIT = wx.EVT_TREE_BEGIN_LABEL_EDIT
281 EVT_TREE_END_LABEL_EDIT = wx.EVT_TREE_END_LABEL_EDIT
282 EVT_TREE_DELETE_ITEM = wx.EVT_TREE_DELETE_ITEM
283 EVT_TREE_GET_INFO = wx.EVT_TREE_GET_INFO
284 EVT_TREE_SET_INFO = wx.EVT_TREE_SET_INFO
285 EVT_TREE_ITEM_EXPANDED = wx.EVT_TREE_ITEM_EXPANDED
286 EVT_TREE_ITEM_EXPANDING = wx.EVT_TREE_ITEM_EXPANDING
287 EVT_TREE_ITEM_COLLAPSED = wx.EVT_TREE_ITEM_COLLAPSED
288 EVT_TREE_ITEM_COLLAPSING = wx.EVT_TREE_ITEM_COLLAPSING
289 EVT_TREE_SEL_CHANGED = wx.EVT_TREE_SEL_CHANGED
290 EVT_TREE_SEL_CHANGING = wx.EVT_TREE_SEL_CHANGING
291 EVT_TREE_KEY_DOWN = wx.EVT_TREE_KEY_DOWN
292 EVT_TREE_ITEM_ACTIVATED = wx.EVT_TREE_ITEM_ACTIVATED
293 EVT_TREE_ITEM_RIGHT_CLICK = wx.EVT_TREE_ITEM_RIGHT_CLICK
294 EVT_TREE_ITEM_MIDDLE_CLICK = wx.EVT_TREE_ITEM_MIDDLE_CLICK
295 EVT_TREE_END_DRAG = wx.EVT_TREE_END_DRAG
296 EVT_TREE_STATE_IMAGE_CLICK = wx.EVT_TREE_STATE_IMAGE_CLICK
297 EVT_TREE_ITEM_GETTOOLTIP = wx.EVT_TREE_ITEM_GETTOOLTIP
298 EVT_TREE_ITEM_MENU = wx.EVT_TREE_ITEM_MENU
299 EVT_TREE_ITEM_CHECKING = wx.PyEventBinder(wxEVT_TREE_ITEM_CHECKING, 1)
300 EVT_TREE_ITEM_CHECKED = wx.PyEventBinder(wxEVT_TREE_ITEM_CHECKED, 1)
301 EVT_TREE_ITEM_HYPERLINK = wx.PyEventBinder(wxEVT_TREE_ITEM_HYPERLINK, 1)
302
303
305 return zlib.decompress(
306 'x\xda\x012\x02\xcd\xfd\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\r\x00\
307 \x00\x00\r\x08\x06\x00\x00\x00r\xeb\xe4|\x00\x00\x00\x04sBIT\x08\x08\x08\x08\
308 |\x08d\x88\x00\x00\x01\xe9IDAT(\x91u\x92\xd1K\xd3a\x14\x86\x9f\xef|J2J\xc3%\
309 \x85\x8e\x1cb\x93Hl\xd9,\x06F]4\x10\tD3\x83\x88\xc8\xbf\xc0\xb4\xaeBP1\xe9\
310 \xa2(\xec\xaan\xc3\x82pD\xa1\x84\xb0\x88@3\x8c\xc9\xa2bT\xa2^\x8c\x81V3\xb6\
311 \xb5\x9f\xce9\xbe.j\xb20\xdf\xeb\xf7\xe19\x07^\xa5D\x93\x9f\x9ea\xbf\t\x04\
312 \xbf\x12\x8b[\xd8Kl\xf8<.\xeet\xb5\xab\xfc\x8e\xca\x87*ZzM\xf3\xb1j|G\xab\
313 \xf0\xd4\x94\x13\x9a_&0\xbb\xc8\xd8\xf4g\xa2\xcfo\xa8-P\xc7\xf5\x07\xa6\xedD\
314 \r\x8d\xb5\xfb\x11\x11\xb4\xd6\x88h\xb4\xd6L}\x8a\xf0\xe4\xd5G\x1e\rt*\x00\
315 \xc9\x19\xb6\x03D4\xa7\xdcU\\8\xed\xa6\xa2\xa5\xd7\x00\xe8\xab\xf7\x9e\x9a\
316 \xca\xb2\x9d\\\xf2\xd5!"dT\x86\xc9\xe4\x14\x83s\x83HF\xe3\xdc\xe5\xa4\xa8\
317 \xb0\x88\xaa\xf2=D\x7f$il>\xdf\xafSe\xf5\xfd\x9dM\x87\xa9\xdc\xb7\x1b\xad5\
318 \x93\xc9)\xfc\xe9Q\x12\xe9\x04\x13\x0b\x13\x94\xaaR\xdc{\x8f "\xec(,\xe0\xfe\
319 \xb3\xb7H,a\xe1\xa9)\xdf<e$2Ble\x85\x94e\xb1\x96\xcep\xfb\xdd-D\x04\xa5\x14\
320 \xdeZ\'\xb1\x84\x85\xd8\x8bm\x84\xe6\x977\x7f8kog)\xba\xc4\xb7\xe5\xef$\xe2?\
321 \xe9\xa9\xbf\x86R\n\x11a&\x1c\xc1^lC|\r.\x02\xb3\x8b\x9b\xa6&G\x13W\xaa\xbb\
322 \x91_\x05\x0c\x1d\xbfI\xc7\xa1\x8e\xbf&a|:\x8c\xaf\xc1\x05J4\x8e\xd6>36\x192\
323 \xc9d\xdc\xa4RI\xb3\xbaj\x99tz\xcd\xac\xaf\xa7\xcd\xc6F\xc6d\xb3Y\xf32\xf8\
324 \xc58Z\xfb\x8c\x12\xfd\x07R\xa2\xb98\xf0\xd0\xbcx\xf3a[\xe0\xf2\xd0c\x93\xeb\
325 nYD\xdb\xc9:\xcex\x0f\xe2\xadu2\x13\x8e0>\x1d\xc6\xff\xfa\xfd\xff\x17\x91K\
326 \xf7\xf0\xa8\t\x04\xe7X\x89[\x94\x96\xd8\xf0y\x0ep\xb7\xeb\xdc?\xdb\xfb\r|\
327 \xd0\xd1]\x98\xbdm\xdc\x00\x00\x00\x00IEND\xaeB`\x82\x91\xe2\x08\x8f' )
328
331
333 stream = cStringIO.StringIO(GetFlaggedData())
334 return wx.ImageFromStream(stream)
335
336
338 return zlib.decompress(
339 'x\xda\x01\xad\x01R\xfe\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\r\x00\
340 \x00\x00\r\x08\x06\x00\x00\x00r\xeb\xe4|\x00\x00\x00\x04sBIT\x08\x08\x08\x08\
341 |\x08d\x88\x00\x00\x01dIDAT(\x91\x95\xd21K\x82a\x14\x86\xe1\xe7=\xef798\xb8\
342 \x89\x0e"|Cd\x94\x88\x83\x065\x88\x108\x88Q\x8b-\xd1\x1f\x88\x9a\n\x04\x11j\
343 \x8eh\x08\xdaZ\x84(\x82\xc2 0\xc1 $\xb4P\xa1\x10\x11D\xb061\xd4\xd4\xcc\xe44\
344 \x84 \xa8Hg~.\xcer\x0bA\x12\x83\xb7ux\xce\xd1T\x01\xd5z\x0b:\xad\x06n\xbb\
345 \x8a\x83\xcdU1\xb8\x11\x83\xc8\xe0\r\xf0\x92\xdd\x0c\x97\xd5\x04\x9b\xaaG\
346 \xb6XA,]B\xe41\x8f\xf7\xab=1\x84Vv\x8e\xd97\xaf\xc29m\x04\x91\x84\x94\n\xa4\
347 \x94P\x14\x05\x89\xd77\x9c\xc5_\x10\x0em\x08\x00\xa0\xfe\x87q@J\x89\xc593\
348 \xfc\xaeY\x18\xbc\x01\x06\x00\xb1}t\xc9\xf5F\x03\x01\xbfs$ \x92 "\x10I\xec\
349 \x9e\xdcBQ\x08\x14M\x15\xe0\xb2\x9a&\x02"\x82\xc71\x85h\xaa\x00\xaa\xd6[\xb0\
350 \xa9\xfa\x89\x80\x88\xe0\xb0\x98P\xad\xb7@:\xad\x06\xd9be" "$se\xe8\xb4\x1a\
351 \x90\xdb\xae"\x96.M\x04D\x84H"\x07\xb7]\x05\x04I\x18}A\xbe\xbe\x7f\xe6Z\xed\
352 \x83\x1b\x8d\x1a7\x9b\x9f\xdcn\xb7\xb8\xd3\xf9\xe2n\xf7\x9b{\xbd\x1f\xbe{\
353 \xca\xb3\xd1\x17dA\xf2\x0f\t\x92X\x0b\x9d\xf2\xcdCf,X\xdf\x0fs\x7f;T\xc4\xf2\
354 \xc2\x0c<\x8e)8,&$seD\x129\\\xc43\xa3\x8b\xf8O{\xbf\xf1\xb5\xa5\x990\x0co\
355 \xd6\x00\x00\x00\x00IEND\xaeB`\x82&\x11\xab!' )
356
359
361 stream = cStringIO.StringIO(GetNotFlaggedData())
362 return wx.ImageFromStream(stream)
363
364
366 return zlib.decompress(
367 "x\xda\xeb\x0c\xf0s\xe7\xe5\x92\xe2b``\xe0\xf5\xf4p\t\x02\xd1 \xcc\xc1\x06$\
368 \x8b^?\xa9\x01R,\xc5N\x9e!\x1c@P\xc3\x91\xd2\x01\xe4\xaf\xf4tq\x0c\xd1\x98\
369 \x98<\x853\xe7\xc7y\x07\xa5\x84\xc4\x84\x84\x04\x0b3C1\xbd\x03'N\x1c9p\x84\
370 \xe5\xe0\x993gx||\xce\x14\xcc\xea\xec\xect4^7\xbf\x91\xf3&\x8b\x93\xd4\x8c\
371 \x19\n\xa7fv\\L\xd8p\x90C\xebx\xcf\x05\x17\x0ff \xb8c\xb6Cm\x06\xdb\xea\xd8\
372 \xb2\x08\xd3\x03W\x0c\x8c\x8c\x16e%\xa5\xb5E\xe4\xee\xba\xca\xe4|\xb8\xb7\
373 \xe35OOO\xcf\n\xb3\x83>m\x8c1R\x12\x92\x81s\xd8\x0b/\xb56\x14k|l\\\xc7x\xb4\
374 \xf2\xc4\xc1*\xd5'B~\xbc\x19uNG\x98\x85\x85\x8d\xe3x%\x16\xb2_\xee\xf1\x07\
375 \x99\xcb\xacl\x99\xc9\xcf\xb0\xc0_.\x87+\xff\x99\x05\xd0\xd1\x0c\x9e\xae~.\
376 \xeb\x9c\x12\x9a\x00\x92\xccS\x9f" )
377
380
382 stream = cStringIO.StringIO(GetCheckedData())
383 return wx.ImageFromStream(stream)
384
385
387 return zlib.decompress(
388 "x\xda\xeb\x0c\xf0s\xe7\xe5\x92\xe2b``\xe0\xf5\xf4p\t\x02\xd1 \xcc\xc1\x06$\
389 \x8b^?\xa9\x01R,\xc5N\x9e!\x1c@P\xc3\x91\xd2\x01\xe4\xe7z\xba8\x86hL\x9c{\
390 \xe9 o\x83\x01\x07\xeb\x85\xf3\xed\x86w\x0ed\xdaT\x96\x8a\xbc\x9fw\xe7\xc4\
391 \xd9/\x01\x8b\x97\x8a\xd7\xab*\xfar\xf0Ob\x93^\xf6\xd5%\x9d\x85A\xe6\xf6\x1f\
392 \x11\x8f{/\x0b\xf8wX+\x9d\xf2\xb6:\x96\xca\xfe\x9a3\xbeA\xe7\xed\x1b\xc6%\
393 \xfb=X3'sI-il\t\xb9\xa0\xc0;#\xd4\x835m\x9a\xf9J\x85\xda\x16.\x86\x03\xff\
394 \xee\xdcc\xdd\xc0\xce\xf9\xc8\xcc(\xbe\x1bh1\x83\xa7\xab\x9f\xcb:\xa7\x84&\
395 \x00\x87S=\xbe" )
396
399
401 stream = cStringIO.StringIO(GetNotCheckedData())
402 return wx.ImageFromStream(stream)
403
404
406 """
407 Convert the given image (in place) to a grayed-out version,
408 appropriate for a 'disabled' appearance.
409 """
410
411 factor = 0.7
412
413 if anImage.HasMask():
414 maskColor = (anImage.GetMaskRed(), anImage.GetMaskGreen(), anImage.GetMaskBlue())
415 else:
416 maskColor = None
417
418 data = map(ord, list(anImage.GetData()))
419
420 for i in range(0, len(data), 3):
421
422 pixel = (data[i], data[i+1], data[i+2])
423 pixel = MakeGray(pixel, factor, maskColor)
424
425 for x in range(3):
426 data[i+x] = pixel[x]
427
428 anImage.SetData(''.join(map(chr, data)))
429
430 return anImage
431
432
433 -def MakeGray((r,g,b), factor, maskColor):
434 """
435 Make a pixel grayed-out. If the pixel matches the maskcolor, it won't be
436 changed.
437 """
438
439 if (r,g,b) != maskColor:
440 return map(lambda x: int((230 - x) * factor) + x, (r,g,b))
441 else:
442 return (r,g,b)
443
444
469
470
471
472
473 if wx.VERSION_STRING < "2.6.2.1":
474 _CONTROL_EXPANDED = 8
475 _CONTROL_CURRENT = 16
476 _drawingfunction = DrawTreeItemButton
477 else:
478 _CONTROL_EXPANDED = wx.CONTROL_EXPANDED
479 _CONTROL_CURRENT = wx.CONTROL_CURRENT
480 _drawingfunction = wx.RendererNative.Get().DrawTreeItemButton
481
482
483
484
485
486
487
489 """
490 This class handles the creation of a custom image in case of item drag
491 and drop.
492 """
493
495 """
496 Default class constructor.
497 For internal use: do not call it in your code!
498 """
499
500 text = item.GetText()
501 font = item.Attr().GetFont()
502 colour = item.Attr().GetTextColour()
503 if colour is None:
504 colour = wx.BLACK
505 if font is None:
506 font = treeCtrl._normalFont
507
508 backcolour = treeCtrl.GetBackgroundColour()
509 r, g, b = int(backcolour.Red()), int(backcolour.Green()), int(backcolour.Blue())
510 backcolour = ((r >> 1) + 20, (g >> 1) + 20, (b >> 1) + 20)
511 backcolour = wx.Colour(backcolour[0], backcolour[1], backcolour[2])
512 self._backgroundColour = backcolour
513
514 tempdc = wx.ClientDC(treeCtrl)
515 tempdc.SetFont(font)
516 width, height, dummy = tempdc.GetMultiLineTextExtent(text + "M")
517
518 image = item.GetCurrentImage()
519
520 image_w, image_h = 0, 0
521 wcheck, hcheck = 0, 0
522 itemcheck = None
523 itemimage = None
524 ximagepos = 0
525 yimagepos = 0
526 xcheckpos = 0
527 ycheckpos = 0
528
529 if image != _NO_IMAGE:
530 if treeCtrl._imageListNormal:
531 image_w, image_h = treeCtrl._imageListNormal.GetSize(image)
532 image_w += 4
533 itemimage = treeCtrl._imageListNormal.GetBitmap(image)
534
535 checkimage = item.GetCurrentCheckedImage()
536
537 if checkimage is not None:
538 if treeCtrl._imageListCheck:
539 wcheck, hcheck = treeCtrl._imageListCheck.GetSize(checkimage)
540 wcheck += 4
541 itemcheck = treeCtrl._imageListCheck.GetBitmap(checkimage)
542
543 total_h = max(hcheck, height)
544 total_h = max(image_h, total_h)
545
546 if image_w:
547 ximagepos = wcheck
548 yimagepos = ((total_h > image_h) and [(total_h-image_h)/2] or [0])[0]
549
550 if checkimage is not None:
551 xcheckpos = 2
552 ycheckpos = ((total_h > image_h) and [(total_h-image_h)/2] or [0])[0] + 2
553
554 extraH = ((total_h > height) and [(total_h - height)/2] or [0])[0]
555
556 xtextpos = wcheck + image_w
557 ytextpos = extraH
558
559 total_h = max(image_h, hcheck)
560 total_h = max(total_h, height)
561
562 if total_h < 30:
563 total_h += 2
564 else:
565 total_h += total_h/10
566
567 total_w = image_w + wcheck + width
568
569 self._total_w = total_w
570 self._total_h = total_h
571 self._itemimage = itemimage
572 self._itemcheck = itemcheck
573 self._text = text
574 self._colour = colour
575 self._font = font
576 self._xtextpos = xtextpos
577 self._ytextpos = ytextpos
578 self._ximagepos = ximagepos
579 self._yimagepos = yimagepos
580 self._xcheckpos = xcheckpos
581 self._ycheckpos = ycheckpos
582 self._textwidth = width
583 self._textheight = height
584 self._extraH = extraH
585
586 self._bitmap = self.CreateBitmap()
587
588 wx.DragImage.__init__(self, self._bitmap)
589
590
592 """Actually creates the dnd bitmap."""
593
594 memory = wx.MemoryDC()
595
596 bitmap = wx.EmptyBitmap(self._total_w, self._total_h)
597 memory.SelectObject(bitmap)
598
599 memory.SetTextBackground(self._backgroundColour)
600 memory.SetBackground(wx.Brush(self._backgroundColour))
601 memory.SetFont(self._font)
602 memory.SetTextForeground(self._colour)
603 memory.Clear()
604
605 if self._itemimage:
606 memory.DrawBitmap(self._itemimage, self._ximagepos, self._yimagepos, True)
607
608 if self._itemcheck:
609 memory.DrawBitmap(self._itemcheck, self._xcheckpos, self._ycheckpos, True)
610
611 textrect = wx.Rect(self._xtextpos, self._ytextpos+self._extraH, self._textwidth, self._textheight)
612 memory.DrawLabel(self._text, textrect)
613
614 memory.SelectObject(wx.NullBitmap)
615
616 return bitmap
617
618
619
620
621
622
624 """Creates the item attributes (text colour, background colour and font)."""
625
626 - def __init__(self, colText=wx.NullColour, colBack=wx.NullColour, font=wx.NullFont):
627 """
628 Default class constructor.
629 For internal use: do not call it in your code!"
630 """
631
632 self._colText = colText
633 self._colBack = colBack
634 self._font = font
635
636
637 - def SetTextColour(self, colText):
638 """Sets the attribute text colour."""
639
640 self._colText = colText
641
642
644 """Sets the attribute background colour."""
645
646 self._colBack = colBack
647
648
650 """Sets the attribute font."""
651
652 self._font = font
653
654
655
656 - def HasTextColour(self):
657 """Returns whether the attribute has text colour."""
658
659 return self._colText != wx.NullColour
660
661
663 """Returns whether the attribute has background colour."""
664
665 return self._colBack != wx.NullColour
666
667
669 """Returns whether the attribute has font."""
670
671 return self._font != wx.NullFont
672
673
674
675 - def GetTextColour(self):
676 """Returns the attribute text colour."""
677
678 return self._colText
679
680
682 """Returns the attribute background colour."""
683
684 return self._colBack
685
686
688 """Returns the attribute font."""
689
690 return self._font
691
692
693
694
695
696
697
698
699
701 """
702 CommandTreeEvent is a special subclassing of wx.PyCommandEvent.
703 NB: note that not all the accessors make sense for all the events, see the
704 event description for every method in this class.
705 """
706
707 - def __init__(self, type, id, item=None, evtKey=None, point=None,
708 label=None, **kwargs):
709 """
710 Default class constructor.
711 For internal use: do not call it in your code!
712 """
713
714 wx.PyCommandEvent.__init__(self, type, id, **kwargs)
715 self._item = item
716 self._evtKey = evtKey
717 self._pointDrag = point
718 self._label = label
719
720
722 """
723 Gets the item on which the operation was performed or the newly selected
724 item for EVT_TREE_SEL_CHANGED/ING events.
725 """
726
727 return self._item
728
729
731 """
732 Sets the item on which the operation was performed or the newly selected
733 item for EVT_TREE_SEL_CHANGED/ING events.
734 """
735
736 self._item = item
737
738
740 """For EVT_TREE_SEL_CHANGED/ING events, gets the previously selected item."""
741
742 return self._itemOld
743
744
746 """For EVT_TREE_SEL_CHANGED/ING events, sets the previously selected item."""
747
748 self._itemOld = item
749
750
752 """
753 Returns the point where the mouse was when the drag operation started
754 (for EVT_TREE_BEGIN(R)DRAG events only) or the click position.
755 """
756
757 return self._pointDrag
758
759
761 """
762 Sets the point where the mouse was when the drag operation started
763 (for EVT_TREE_BEGIN(R)DRAG events only) or the click position.
764 """
765
766 self._pointDrag = pt
767
768
770 """Keyboard data (for EVT_TREE_KEY_DOWN only)."""
771
772 return self._evtKey
773
774
776 """Returns the integer key code (for EVT_TREE_KEY_DOWN only)."""
777
778 return self._evtKey.GetKeyCode()
779
780
782 """Keyboard data (for EVT_TREE_KEY_DOWN only)."""
783
784 self._evtKey = evt
785
786
788 """Returns the label-itemtext (for EVT_TREE_BEGIN|END_LABEL_EDIT only)."""
789
790 return self._label
791
792
794 """Sets the label-itemtext (for EVT_TREE_BEGIN|END_LABEL_EDIT only)."""
795
796 self._label = label
797
798
800 """Returns the edit cancel flag (for EVT_TREE_BEGIN|END_LABEL_EDIT only)."""
801
802 return self._editCancelled
803
804
806 """Sets the edit cancel flag (for EVT_TREE_BEGIN|END_LABEL_EDIT only)."""
807
808 self._editCancelled = editCancelled
809
810
812 """Sets the tooltip for the item (for EVT_TREE_ITEM_GETTOOLTIP events)."""
813
814 self._label = toolTip
815
816
818 """Gets the tooltip for the item (for EVT_TREE_ITEM_GETTOOLTIP events)."""
819
820 return self._label
821
822
823
824
825
826
827
828
829
831
832 - def __init__(self, type, id, item=None, evtKey=None, point=None,
833 label=None, **kwargs):
834 """
835 Default class constructor.
836 For internal use: do not call it in your code!"
837 """
838
839 CommandTreeEvent.__init__(self, type, id, item, evtKey, point, label, **kwargs)
840 self.notify = wx.NotifyEvent(type, id)
841
842
844 """Returns the actual wx.NotifyEvent."""
845
846 return self.notify
847
848
850 """Returns whether the event is allowed or not."""
851
852 return self.notify.IsAllowed()
853
854
856 """Vetos the event."""
857
858 self.notify.Veto()
859
860
862 """The event is allowed."""
863
864 self.notify.Allow()
865
866
867
868
869
870
872 """Timer used for enabling in-place edit."""
873
875 """
876 Default class constructor.
877 For internal use: do not call it in your code!"
878 """
879
880 wx.Timer.__init__(self)
881 self._owner = owner
882
883
885 """The timer has expired."""
886
887 self._owner.OnRenameTimer()
888
889
890
891
892
893
894
895 -class TreeTextCtrl(wx.TextCtrl):
896 """Control used for in-place edit."""
897
898 - def __init__(self, owner, item=None):
899 """
900 Default class constructor.
901 For internal use: do not call it in your code!"
902 """
903
904 self._owner = owner
905 self._itemEdited = item
906 self._startValue = item.GetText()
907 self._finished = False
908 self._aboutToFinish = False
909
910 w = self._itemEdited.GetWidth()
911 h = self._itemEdited.GetHeight()
912
913 wnd = self._itemEdited.GetWindow()
914 if wnd:
915 w = w - self._itemEdited.GetWindowSize()[0]
916 h = 0
917
918 x, y = self._owner.CalcScrolledPosition(item.GetX(), item.GetY())
919
920 image_h = 0
921 image_w = 0
922
923 image = item.GetCurrentImage()
924
925 if image != _NO_IMAGE:
926
927 if self._owner._imageListNormal:
928 image_w, image_h = self._owner._imageListNormal.GetSize(image)
929 image_w += 4
930
931 else:
932
933 raise "\n ERROR: You Must Create An Image List To Use Images!"
934
935 checkimage = item.GetCurrentCheckedImage()
936
937 if checkimage is not None:
938 wcheck, hcheck = self._owner._imageListCheck.GetSize(checkimage)
939 wcheck += 4
940 else:
941 wcheck = 0
942
943 if wnd:
944 h = max(hcheck, image_h)
945 dc = wx.ClientDC(self._owner)
946 h = max(h, dc.GetTextExtent("Aq")[1])
947 h = h + 2
948
949
950 x += image_w + wcheck
951 w -= image_w + 4 + wcheck
952
953 if wx.Platform == "__WXMAC__":
954 bs = self.DoGetBestSize()
955
956 if h > bs.y - 8:
957 diff = h - ( bs.y - 8 )
958 h -= diff
959 y += diff / 2
960
961 wx.TextCtrl.__init__(self, self._owner, wx.ID_ANY, self._startValue,
962 wx.Point(x - 4, y), wx.Size(w + 15, h))
963
964 self.Bind(wx.EVT_CHAR, self.OnChar)
965 self.Bind(wx.EVT_KEY_UP, self.OnKeyUp)
966 self.Bind(wx.EVT_KILL_FOCUS, self.OnKillFocus)
967
968
969 - def AcceptChanges(self):
970 """Accepts/refuses the changes made by the user."""
971
972 value = self.GetValue()
973
974 if value == self._startValue:
975
976
977
978
979
980 self._owner.OnRenameCancelled(self._itemEdited)
981 return True
982
983 if not self._owner.OnRenameAccept(self._itemEdited, value):
984
985 return False
986
987
988 self._owner.SetItemText(self._itemEdited, value)
989
990 return True
991
992
994 """Finish editing."""
995
996 if not self._finished:
997
998
999 self._finished = True
1000 self._owner.SetFocusIgnoringChildren()
1001 self._owner.ResetTextControl()
1002
1003
1004 - def OnChar(self, event):
1005 """Handles the wx.EVT_CHAR event for TreeTextCtrl."""
1006
1007 keycode = event.GetKeyCode()
1008
1009 if keycode == wx.WXK_RETURN:
1010 self._aboutToFinish = True
1011
1012 self.AcceptChanges()
1013
1014 wx.CallAfter(self.Finish)
1015
1016 elif keycode == wx.WXK_ESCAPE:
1017 self.StopEditing()
1018
1019 else:
1020 event.Skip()
1021
1022
1023 - def OnKeyUp(self, event):
1024 """Handles the wx.EVT_KEY_UP event for TreeTextCtrl."""
1025
1026 if not self._finished:
1027
1028
1029 parentSize = self._owner.GetSize()
1030 myPos = self.GetPosition()
1031 mySize = self.GetSize()
1032
1033 sx, sy = self.GetTextExtent(self.GetValue() + "M")
1034 if myPos.x + sx > parentSize.x:
1035 sx = parentSize.x - myPos.x
1036 if mySize.x > sx:
1037 sx = mySize.x
1038
1039 self.SetSize((sx, -1))
1040
1041 event.Skip()
1042
1043
1044 - def OnKillFocus(self, event):
1045 """Handles the wx.EVT_KILL_FOCUS event for TreeTextCtrl."""
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061 event.Skip()
1062
1063
1064 - def StopEditing(self):
1065 """Suddenly stops the editing."""
1066
1067 self._owner.OnRenameCancelled(self._itemEdited)
1068 self.Finish()
1069
1070
1072 """Returns the item currently edited."""
1073
1074 return self._itemEdited
1075
1076
1077
1078
1079
1080
1081
1082
1084 """
1085 Timer used to clear CustomTreeCtrl._findPrefix if no key was pressed
1086 for a sufficiently long time.
1087 """
1088
1090 """
1091 Default class constructor.
1092 For internal use: do not call it in your code!"
1093 """
1094
1095 wx.Timer.__init__(self)
1096 self._owner = owner
1097
1098
1100 """The timer has expired."""
1101
1102 self._owner._findPrefix = ""
1103
1104
1105
1106
1107
1108
1109
1110
1112 """
1113 This class holds all the information and methods for every single item in
1114 CustomTreeCtrl. No wx based.
1115 """
1116
1117 - def __init__(self, parent, text="", ct_type=0, wnd=None, image=-1, selImage=-1, data=None):
1118 """
1119 Default class constructor.
1120 For internal use: do not call it in your code!"
1121 """
1122
1123
1124
1125
1126 self._text = text
1127 self._data = data
1128
1129 self._children = []
1130 self._parent = parent
1131
1132 self._attr = None
1133
1134
1135
1136 self._images = [-1, -1, -1, -1]
1137 self._images[TreeItemIcon_Normal] = image
1138 self._images[TreeItemIcon_Selected] = selImage
1139 self._images[TreeItemIcon_Expanded] = _NO_IMAGE
1140 self._images[TreeItemIcon_SelectedExpanded] = _NO_IMAGE
1141
1142 self._checkedimages = [None, None, None, None]
1143
1144 self._x = 0
1145 self._y = 0
1146 self._width = 0
1147 self._height = 0
1148
1149 self._isCollapsed = True
1150 self._hasHilight = False
1151 self._hasPlus = False
1152
1153 self._isBold = False
1154 self._isItalic = False
1155 self._ownsAttr = False
1156 self._type = ct_type
1157 self._checked = False
1158 self._enabled = True
1159 self._hypertext = False
1160 self._visited = False
1161
1162 if self._type > 0:
1163
1164 self._checkedimages[TreeItemIcon_Checked] = 0
1165 self._checkedimages[TreeItemIcon_NotChecked] = 1
1166 self._checkedimages[TreeItemIcon_Flagged] = 2
1167 self._checkedimages[TreeItemIcon_NotFlagged] = 3
1168
1169 if parent:
1170 if parent.GetType() == 2 and not parent.IsChecked():
1171
1172 self._enabled = False
1173
1174 self._wnd = wnd
1175
1176 if wnd:
1177 if wnd.GetSizer():
1178 size = wnd.GetBestSize()
1179 else:
1180 size = wnd.GetSize()
1181
1182
1183
1184
1185
1186 self._wnd.Bind(wx.EVT_SET_FOCUS, self.OnSetFocus)
1187
1188 self._height = size.GetHeight() + 2
1189 self._width = size.GetWidth()
1190 self._windowsize = size
1191
1192
1193 if self._isCollapsed:
1194 self._wnd.Show(False)
1195
1196
1197 self._wnd.Enable(self._enabled)
1198 self._windowenabled = self._enabled
1199
1200
1202 """
1203 Returns whether the item is ok or not. Useless on Python, but added for
1204 backward compatibility with the C++ implementation.
1205 """
1206
1207 return True
1208
1209
1211 """Returns the item's children."""
1212
1213 return self._children
1214
1215
1216 - def GetText(self):
1217 """Returns the item text."""
1218
1219 return self._text
1220
1221
1223 """Returns the item image for a particular state."""
1224
1225 return self._images[which]
1226
1227
1229 """Returns the item check image. Meaningful only for radio & check items."""
1230
1231 return self._checkedimages[which]
1232
1233
1235 """Returns the data associated to this item."""
1236
1237 return self._data
1238
1239
1241 """Sets the item image."""
1242
1243 self._images[which] = image
1244
1245
1247 """Sets the data associated to this item."""
1248
1249 self._data = data
1250
1251
1253 """Sets whether an item has the 'plus' button."""
1254
1255 self._hasPlus = has
1256
1257
1259 """Sets the item font bold."""
1260
1261 self._isBold = bold
1262
1263
1265 """Sets the item font italic."""
1266
1267 self._isItalic = italic
1268
1269
1271 """Returns the x position on an item in the ScrolledWindow."""
1272
1273 return self._x
1274
1275
1277 """Returns the y position on an item in the ScrolledWindow."""
1278
1279 return self._y
1280
1281
1282 - def SetX(self, x):
1283 """Sets the x position on an item in the ScrolledWindow."""
1284
1285 self._x = x
1286
1287
1288 - def SetY(self, y):
1289 """Sets the y position on an item in the ScrolledWindow."""
1290
1291 self._y = y
1292
1293
1295 """Returns the height of the item."""
1296
1297 return self._height
1298
1299
1301 """Returns the width of the item."""
1302
1303 return self._width
1304
1305
1307 """Sets the height of the item."""
1308
1309 self._height = h
1310
1311
1313 """Sets the width of the item."""
1314
1315 self._width = w
1316
1317
1319 """Sets the window associated to the item."""
1320
1321 self._wnd = wnd
1322
1323
1325 """Returns the window associated to the item."""
1326
1327 return self._wnd
1328
1329
1331 """Returns whether the associated window is enabled or not."""
1332
1333 if not self._wnd:
1334 raise "\nERROR: This Item Has No Window Associated"
1335
1336 return self._windowenabled
1337
1338
1340 """Sets whether the associated window is enabled or not."""
1341
1342 if not self._wnd:
1343 raise "\nERROR: This Item Has No Window Associated"
1344
1345 self._windowenabled = enable
1346 self._wnd.Enable(enable)
1347
1348
1350 """Returns the associated window size."""
1351
1352 return self._windowsize
1353
1354
1356 """Handles the wx.EVT_SET_FOCUS event for the associated window."""
1357
1358 treectrl = self._wnd.GetParent()
1359 select = treectrl.GetSelection()
1360
1361
1362
1363 if select != self:
1364 treectrl._hasFocus = False
1365 else:
1366 treectrl._hasFocus = True
1367
1368 event.Skip()
1369
1370
1372 """
1373 Returns the item type. It should be one of:
1374 0: normal items
1375 1: checkbox item
1376 2: radiobutton item
1377 """
1378
1379 return self._type
1380
1381
1382 - def SetHyperText(self, hyper=True):
1383 """Sets whether the item is hypertext or not."""
1384
1385 self._hypertext = hyper
1386
1387
1389 """Sets whether an hypertext item was visited or not."""
1390
1391 self._visited = visited
1392
1393
1395 """Returns whether an hypertext item was visited or not."""
1396
1397 return self._visited
1398
1399
1400 - def IsHyperText(self):
1401 """Returns whether the item is hypetext or not."""
1402
1403 return self._hypertext
1404
1405
1407 """Gets the item parent."""
1408
1409 return self._parent
1410
1411
1412 - def Insert(self, child, index):
1413 """Inserts an item in the item children."""
1414
1415 self._children.insert(index, child)
1416
1417
1419 """Expand the item."""
1420
1421 self._isCollapsed = False
1422
1423
1425 """Collapse the item."""
1426
1427 self._isCollapsed = True
1428
1429
1431 """Sets the item focus/unfocus."""
1432
1433 self._hasHilight = set
1434
1435
1437 """Returns whether the item has children or not."""
1438
1439 return len(self._children) > 0
1440
1441
1443 """Returns whether the item is selected or not."""
1444
1445 return self._hasHilight != 0
1446
1447
1449 """Returns whether the item is expanded or not."""
1450
1451 return not self._isCollapsed
1452
1453
1455 """Returns whether the item is checked or not."""
1456
1457 return self._checked
1458
1459
1460 - def Check(self, checked=True):
1461 """Check an item. Meaningful only for check and radio items."""
1462
1463 self._checked = checked
1464
1465
1467 """Returns whether the item has the plus button or not."""
1468
1469 return self._hasPlus or self.HasChildren()
1470
1471
1473 """Returns whether the item font is bold or not."""
1474
1475 return self._isBold != 0
1476
1477
1479 """Returns whether the item font is italic or not."""
1480
1481 return self._isItalic != 0
1482
1483
1484 - def Enable(self, enable=True):
1485 """Enables/disables the item."""
1486
1487 self._enabled = enable
1488
1489
1491 """Returns whether the item is enabled or not."""
1492
1493 return self._enabled
1494
1495
1497 """Returns the item attributes (font, colours)."""
1498
1499 return self._attr
1500
1501
1503 """Creates a new attribute (font, colours)."""
1504
1505 if not self._attr:
1506
1507 self._attr = TreeItemAttr()
1508 self._ownsAttr = True
1509
1510 return self._attr
1511
1512
1514 """Sets the item attributes (font, colours)."""
1515
1516 if self._ownsAttr:
1517 del self._attr
1518
1519 self._attr = attr
1520 self._ownsAttr = False
1521
1522
1524 """Assigns the item attributes (font, colours)."""
1525
1526 self.SetAttributes(attr)
1527 self._ownsAttr = True
1528
1529
1531 """Deletes the item children."""
1532
1533 for child in self._children:
1534 if tree:
1535 tree.SendDeleteEvent(child)
1536
1537 child.DeleteChildren(tree)
1538
1539 if child == tree._select_me:
1540 tree._select_me = None
1541
1542
1543 wnd = child.GetWindow()
1544 if wnd:
1545 wnd.Destroy()
1546 child._wnd = None
1547
1548 if child in tree._itemWithWindow:
1549 tree._itemWithWindow.remove(child)
1550
1551 del child
1552
1553 self._children = []
1554
1555
1556 - def SetText(self, text):
1557 """Sets the item text."""
1558
1559 self._text = text
1560
1561
1563 """Gets the number of children."""
1564
1565 count = len(self._children)
1566
1567 if not recursively:
1568 return count
1569
1570 total = count
1571
1572 for n in xrange(count):
1573 total += self._children[n].GetChildrenCount()
1574
1575 return total
1576
1577
1578 - def GetSize(self, x, y, theButton):
1579 """Returns the item size."""
1580
1581 bottomY = self._y + theButton.GetLineHeight(self)
1582
1583 if y < bottomY:
1584 y = bottomY
1585
1586 width = self._x + self._width
1587
1588 if x < width:
1589 x = width
1590
1591 if self.IsExpanded():
1592 for child in self._children:
1593 x, y = child.GetSize(x, y, theButton)
1594
1595 return x, y
1596
1597
1598 - def HitTest(self, point, theCtrl, flags=0, level=0):
1599 """
1600 HitTest method for an item. Called from the main window HitTest.
1601 see the CustomTreeCtrl HitTest method for the flags explanation.
1602 """
1603
1604
1605 if not (level == 0 and theCtrl.HasFlag(TR_HIDE_ROOT)):
1606
1607
1608 h = theCtrl.GetLineHeight(self)
1609
1610 if point.y > self._y and point.y < self._y + h:
1611
1612 y_mid = self._y + h/2
1613
1614 if point.y < y_mid:
1615 flags |= TREE_HITTEST_ONITEMUPPERPART
1616 else:
1617 flags |= TREE_HITTEST_ONITEMLOWERPART
1618
1619 xCross = self._x - theCtrl.GetSpacing()
1620
1621 if wx.Platform == "__WXMAC__":
1622
1623
1624 if point.x > xCross-4 and point.x < xCross+10 and point.y > y_mid-4 and \
1625 point.y < y_mid+10 and self.HasPlus() and theCtrl.HasButtons():
1626
1627 flags |= TREE_HITTEST_ONITEMBUTTON
1628 return self, flags
1629 else:
1630
1631 if point.x > xCross-6 and point.x < xCross+6 and point.y > y_mid-6 and \
1632 point.y < y_mid+6 and self.HasPlus() and theCtrl.HasButtons():
1633
1634 flags |= TREE_HITTEST_ONITEMBUTTON
1635 return self, flags
1636
1637 if point.x >= self._x and point.x <= self._x + self._width:
1638
1639 image_w = -1
1640 wcheck = 0
1641
1642
1643 if self.GetImage() != _NO_IMAGE and theCtrl._imageListNormal:
1644 image_w, image_h = theCtrl._imageListNormal.GetSize(self.GetImage())
1645
1646 if self.GetCheckedImage() is not None:
1647 wcheck, hcheck = theCtrl._imageListCheck.GetSize(self.GetCheckedImage())
1648
1649 if wcheck and point.x <= self._x + wcheck + 1:
1650 flags |= TREE_HITTEST_ONITEMCHECKICON
1651 return self, flags
1652
1653 if image_w != -1 and point.x <= self._x + wcheck + image_w + 1:
1654 flags |= TREE_HITTEST_ONITEMICON
1655 else:
1656 flags |= TREE_HITTEST_ONITEMLABEL
1657
1658 return self, flags
1659
1660 if point.x < self._x:
1661 flags |= TREE_HITTEST_ONITEMINDENT
1662 if point.x > self._x + self._width:
1663 flags |= TREE_HITTEST_ONITEMRIGHT
1664
1665 return self, flags
1666
1667
1668 if self._isCollapsed:
1669 return None, 0
1670
1671
1672 for child in self._children:
1673 res, flags = child.HitTest(point, theCtrl, flags, level + 1)
1674 if res != None:
1675 return res, flags
1676
1677 return None, 0
1678
1679
1708
1709
1726
1727
1729 """
1730 Translate the key or mouse event flag to the type of selection we
1731 are dealing with.
1732 """
1733
1734 is_multiple = (style & TR_MULTIPLE) != 0
1735 extended_select = shiftDown and is_multiple
1736 unselect_others = not (extended_select or (ctrlDown and is_multiple))
1737
1738 return is_multiple, extended_select, unselect_others
1739
1740
1741
1742
1743
1744
1745
1747
1748 - def __init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition, size=wx.DefaultSize,
1749 style=0, ctstyle=TR_DEFAULT_STYLE, validator=wx.DefaultValidator,
1750 name="CustomTreeCtrl"):
1751 """
1752 Default class constructor.
1753
1754 parent: parent window. Must not be none.
1755
1756 id: window identifier. A value of -1 indicates a default value.
1757
1758 pos: window position.
1759
1760 size: window size. If the default size (-1, -1) is specified then the window is sized appropriately.
1761
1762 style: the underlying wx.ScrolledWindow style
1763
1764 ctstyle: CustomTreeCtrl window style. This can be one of:
1765 TR_NO_BUTTONS
1766 TR_HAS_BUTTONS # draw collapsed/expanded btns
1767 TR_NO_LINES # don't draw lines at all
1768 TR_LINES_AT_ROOT # connect top-level nodes
1769 TR_TWIST_BUTTONS # draw mac-like twist buttons
1770 TR_SINGLE # single selection mode
1771 TR_MULTIPLE # can select multiple items
1772 TR_EXTENDED # todo: allow extended selection
1773 TR_HAS_VARIABLE_ROW_HEIGHT # allows rows to have variable height
1774 TR_EDIT_LABELS # can edit item labels
1775 TR_ROW_LINES # put border around items
1776 TR_HIDE_ROOT # don't display root node
1777 TR_FULL_ROW_HIGHLIGHT # highlight full horizontal space
1778 TR_AUTO_CHECK_CHILD # only meaningful for checkboxes
1779 TR_AUTO_TOGGLE_CHILD # only meaningful for checkboxes
1780
1781 validator: window validator.
1782
1783 name: window name.
1784 """
1785
1786 self._current = self._key_current = self._anchor = self._select_me = None
1787 self._hasFocus = False
1788 self._dirty = False
1789
1790
1791 self._lineHeight = 10
1792
1793 self._indent = 15
1794
1795 self._spacing = 18
1796
1797
1798 self._hilightBrush = wx.Brush(wx.SystemSettings_GetColour(wx.SYS_COLOUR_HIGHLIGHT))
1799 btnshadow = wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNSHADOW)
1800 self._hilightUnfocusedBrush = wx.Brush(btnshadow)
1801 r, g, b = btnshadow.Red(), btnshadow.Green(), btnshadow.Blue()
1802 backcolour = ((r >> 1) - 20, (g >> 1) - 20, (b >> 1) - 20)
1803 backcolour = wx.Colour(backcolour[0], backcolour[1], backcolour[2])
1804 self._hilightUnfocusedBrush2 = wx.Brush(backcolour)
1805
1806
1807 self._imageListNormal = self._imageListButtons = self._imageListState = self._imageListCheck = None
1808 self._ownsImageListNormal = self._ownsImageListButtons = self._ownsImageListState = False
1809
1810
1811 self._dragCount = 0
1812 self._countDrag = 0
1813 self._isDragging = False
1814 self._dropTarget = self._oldSelection = None
1815 self._dragImage = None
1816 self._underMouse = None
1817
1818
1819 self._textCtrl = None
1820 self._renameTimer = None
1821
1822
1823 self._freezeCount = 0
1824
1825 self._findPrefix = ""
1826 self._findTimer = None
1827
1828 self._dropEffectAboveItem = False
1829 self._lastOnSame = False
1830
1831
1832 self._hasFont = True
1833 self._normalFont = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
1834 self._boldFont = wx.Font(self._normalFont.GetPointSize(), self._normalFont.GetFamily(),
1835 self._normalFont.GetStyle(), wx.BOLD, self._normalFont.GetUnderlined(),
1836 self._normalFont.GetFaceName(), self._normalFont.GetEncoding())
1837
1838
1839
1840 self._hypertextfont = wx.Font(self._normalFont.GetPointSize(), self._normalFont.GetFamily(),
1841 self._normalFont.GetStyle(), wx.NORMAL, True,
1842 self._normalFont.GetFaceName(), self._normalFont.GetEncoding())
1843 self._hypertextnewcolour = wx.BLUE
1844 self._hypertextvisitedcolour = wx.Colour(200, 47, 200)
1845 self._isonhyperlink = False
1846
1847
1848 self._backgroundColour = wx.WHITE
1849
1850
1851 self._backgroundImage = None
1852 self._imageStretchStyle = _StyleTile
1853
1854
1855 self._disabledColour = wx.Colour(180, 180, 180)
1856
1857
1858 self._firstcolour = color= wx.SystemSettings_GetColour(wx.SYS_COLOUR_HIGHLIGHT)
1859 self._secondcolour = wx.WHITE
1860 self._usegradients = False
1861 self._gradientstyle = 0
1862
1863
1864 self._vistaselection = False
1865
1866
1867 if wx.Platform != "__WXMAC__":
1868 self._dottedPen = wx.Pen("grey", 1, wx.USER_DASH)
1869 self._dottedPen.SetDashes([1,1])
1870 self._dottedPen.SetCap(wx.CAP_BUTT)
1871 else:
1872 self._dottedPen = wx.Pen("grey", 1)
1873
1874
1875 self._borderPen = wx.BLACK_PEN
1876 self._cursor = wx.StockCursor(wx.CURSOR_ARROW)
1877
1878
1879 self._hasWindows = False
1880 self._itemWithWindow = []
1881
1882 if wx.Platform == "__WXMAC__":
1883
1884 platform, major, minor = wx.GetOsVersion()
1885
1886 ctstyle &= ~TR_LINES_AT_ROOT
1887 ctstyle |= TR_NO_LINES
1888
1889 if major < 10:
1890 ctstyle |= TR_ROW_LINES
1891
1892 self._windowStyle = ctstyle
1893
1894
1895 self.SetImageListCheck(13, 13)
1896
1897
1898 wx.ScrolledWindow.__init__(self, parent, id, pos, size, style|wx.HSCROLL|wx.VSCROLL, name)
1899
1900
1901
1902
1903 if not self.HasButtons() and not self.HasFlag(TR_NO_LINES):
1904 self._indent= 10
1905 self._spacing = 10
1906
1907 self.SetValidator(validator)
1908
1909 attr = self.GetDefaultAttributes()
1910 self.SetOwnForegroundColour(attr.colFg)
1911 self.SetOwnBackgroundColour(wx.WHITE)
1912
1913 if not self._hasFont:
1914 self.SetOwnFont(attr.font)
1915
1916 self.SetSize(size)
1917
1918
1919 self.Bind(wx.EVT_PAINT, self.OnPaint)
1920 self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground)
1921 self.Bind(wx.EVT_MOUSE_EVENTS, self.OnMouse)
1922 self.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown)
1923 self.Bind(wx.EVT_SET_FOCUS, self.OnSetFocus)
1924 self.Bind(wx.EVT_KILL_FOCUS, self.OnKillFocus)
1925 self.Bind(EVT_TREE_ITEM_GETTOOLTIP, self.OnGetToolTip)
1926 self.Bind(wx.EVT_IDLE, self.OnInternalIdle)
1927 self.Bind(wx.EVT_WINDOW_DESTROY, self.OnDestroy)
1928
1929
1930
1931 self.SetFocus()
1932
1933 return True
1934
1935
1937 """Handles the wx.EVT_WINDOW_DESTROY event."""
1938
1939
1940
1941 if self._renameTimer and self._renameTimer.IsRunning():
1942 self._renameTimer.Stop()
1943 del self._renameTimer
1944
1945 if self._findTimer and self._findTimer.IsRunning():
1946 self._findTimer.Stop()
1947 del self._findTimer
1948
1949 event.Skip()
1950
1951
1953 """Returns the global number of items in the tree."""
1954
1955 if not self._anchor:
1956
1957 return 0
1958
1959 count = self._anchor.GetChildrenCount()
1960
1961 if not self.HasFlag(TR_HIDE_ROOT):
1962
1963 count = count + 1
1964
1965 return count
1966
1967
1969 """Returns the item indentation."""
1970
1971 return self._indent
1972
1973
1975 """Returns the spacing between the start and the text."""
1976
1977 return self._spacing
1978
1979
1981 """Returns the root item."""
1982
1983 return self._anchor
1984
1985
1987 """Returns the current selection: TR_SINGLE only."""
1988
1989 return self._current
1990
1991
1993 """Toggles the item selection."""
1994
1995 if not item:
1996 raise "\nERROR: Invalid Tree Item. "
1997
1998 self.SelectItem(item, not self.IsSelected(item))
1999
2000
2020
2021
2022 - def EnableItem(self, item, enable=True, torefresh=True):
2051
2052
2054 """Returns whether an item is enabled or disabled."""
2055
2056 if not item:
2057 raise "\nERROR: Invalid Tree Item. "
2058
2059 return item.IsEnabled()
2060
2061
2063 """Sets the items disabled colour."""
2064
2065 self._disabledColour = colour
2066 self._dirty = True
2067
2068
2070 """Returns the items disabled colour."""
2071
2072 return self._disabledColour
2073
2074
2076 """Returns whether an item is checked or not."""
2077
2078 if not item:
2079 raise "\nERROR: Invalid Tree Item. "
2080
2081 return item.IsChecked()
2082
2083
2084 - def CheckItem2(self, item, checked=True, torefresh=False):
2096
2097
2118
2119
2168
2169
2171 """Transverses the tree and toggles the items. Meaningful only for check items."""
2172
2173 if not item:
2174 raise "\nERROR: Invalid Tree Item. "
2175
2176 child, cookie = self.GetFirstChild(item)
2177
2178 torefresh = False
2179 if item.IsExpanded():
2180 torefresh = True
2181
2182
2183 while child:
2184 if child.GetType() == 1 and child.IsEnabled():
2185 self.CheckItem2(child, not child.IsChecked(), torefresh=torefresh)
2186 self.AutoToggleChild(child)
2187 (child, cookie) = self.GetNextChild(item, cookie)
2188
2189
2191 """Transverses the tree and checks/unchecks the items. Meaningful only for check items."""
2192
2193 if not item:
2194 raise "\nERROR: Invalid Tree Item. "
2195
2196 (child, cookie) = self.GetFirstChild(item)
2197
2198 torefresh = False
2199 if item.IsExpanded():
2200 torefresh = True
2201
2202 while child:
2203 if child.GetType() == 1 and child.IsEnabled():
2204 self.CheckItem2(child, checked, torefresh=torefresh)
2205 self.AutoCheckChild(child, checked)
2206 (child, cookie) = self.GetNextChild(item, cookie)
2207
2208
2210 """Programatically check/uncheck item children. Does not generate EVT_TREE_CHECK* events."""
2211
2212 if not item:
2213 raise "\nERROR: Invalid Tree Item. "
2214
2215 if checked == None:
2216 self.AutoToggleChild(item)
2217 else:
2218 self.AutoCheckChild(item, checked)
2219
2220
2222 """
2223 Uncheck radio items which are on the same level of the checked one.
2224 Used internally.
2225 """
2226
2227 parent = item.GetParent()
2228
2229 if not parent:
2230 return
2231
2232 torefresh = False
2233 if parent.IsExpanded():
2234 torefresh = True
2235
2236 (child, cookie) = self.GetFirstChild(parent)
2237 while child:
2238 if child.GetType() == 2 and child != item:
2239 self.CheckItem2(child, checked, torefresh=torefresh)
2240 if child.GetType != 2 or (child.GetType() == 2 and child.IsChecked()):
2241 self.EnableChildren(child, checked)
2242 (child, cookie) = self.GetNextChild(parent, cookie)
2243
2244
2246 """Starts editing an item label."""
2247
2248 if not item:
2249 raise "\nERROR: Invalid Tree Item. "
2250
2251 self.Edit(item)
2252
2253
2255 """We don't inherit colours from anyone."""
2256
2257 return False
2258
2259
2261 """Sets item indentation."""
2262
2263 self._indent = indent
2264 self._dirty = True
2265
2266
2268 """Sets item spacing."""
2269
2270 self._spacing = spacing
2271 self._dirty = True
2272
2273
2275 """Returns whether CustomTreeCtrl has a flag."""
2276
2277 return self._windowStyle & flag
2278
2279
2281 """Returns whether an item has children or not."""
2282
2283 if not item:
2284 raise "\nERROR: Invalid Tree Item. "
2285
2286 return len(item.GetChildren()) > 0
2287
2288
2290 """Gets the item children count."""
2291
2292 if not item:
2293 raise "\nERROR: Invalid Tree Item. "
2294
2295 return item.GetChildrenCount(recursively)
2296
2297
2299 """Sets the CustomTreeCtrl style. See __init__ method for the styles explanation."""
2300
2301
2302 if self._anchor and not self.HasFlag(TR_HIDE_ROOT) and styles & TR_HIDE_ROOT:
2303
2304
2305 self._anchor.SetHasPlus()
2306 self._anchor.Expand()
2307 self.CalculatePositions()
2308
2309
2310
2311
2312
2313 if self._windowStyle & TR_MULTIPLE and not (styles & TR_MULTIPLE):
2314 selections = self.GetSelections()
2315 for select in selections[0:-1]:
2316 self.SelectItem(select, False)
2317
2318 self._windowStyle = styles
2319 self._dirty = True
2320
2321
2323 """Returns the CustomTreeCtrl style."""
2324
2325 return self._windowStyle
2326
2327
2332
2333
2334
2335
2336
2337
2338 - def GetItemText(self, item):
2339 """Returns the item text."""
2340
2341 if not item:
2342 raise "\nERROR: Invalid Tree Item. "
2343
2344 return item.GetText()
2345
2346
2348 """Returns the item image."""
2349
2350 if not item:
2351 raise "\nERROR: Invalid Tree Item. "
2352
2353 return item.GetImage(which)
2354
2355
2357 """Returns the data associated to an item."""
2358
2359 if not item:
2360 raise "\nERROR: Invalid Tree Item. "
2361
2362 return item.GetData()
2363
2364 GetItemPyData = GetPyData
2365
2366
2367 - def GetItemTextColour(self, item):
2368 """Returns the item text colour."""
2369
2370 if not item:
2371 raise "\nERROR: Invalid Tree Item. "
2372
2373 return item.Attr().GetTextColour()
2374
2375
2377 """Returns the item background colour."""
2378
2379 if not item:
2380 raise "\nERROR: Invalid Tree Item. "
2381
2382 return item.Attr().GetBackgroundColour()
2383
2384
2386 """Returns the item font."""
2387
2388 if not item:
2389 raise "\nERROR: Invalid Tree Item. "
2390
2391 return item.Attr().GetFont()
2392
2393
2394 - def IsItemHyperText(self, item):
2395 """Returns whether an item is hypertext or not."""
2396
2397 if not item:
2398 raise "\nERROR: Invalid Tree Item. "
2399
2400 return item.IsHyperText()
2401
2402
2403 - def SetItemText(self, item, text):
2404 """Sets the item text."""
2405
2406 if not item:
2407 raise "\nERROR: Invalid Tree Item. "
2408
2409 dc = wx.ClientDC(self)
2410 item.SetText(text)
2411 self.CalculateSize(item, dc)
2412 self.RefreshLine(item)
2413
2414
2416 """Sets the item image, depending on the item state."""
2417
2418 if not item:
2419 raise "\nERROR: Invalid Tree Item. "
2420
2421 item.SetImage(image, which)
2422
2423 dc = wx.ClientDC(self)
2424 self.CalculateSize(item, dc)
2425 self.RefreshLine(item)
2426
2427
2429 """Sets the data associated to an item."""
2430
2431 if not item:
2432 raise "\nERROR: Invalid Tree Item. "
2433
2434 item.SetData(data)
2435
2436 SetItemPyData = SetPyData
2437
2438
2440 """Forces the appearance of the button next to the item."""
2441
2442 if not item:
2443 raise "\nERROR: Invalid Tree Item. "
2444
2445 item.SetHasPlus(has)
2446 self.RefreshLine(item)
2447
2448
2450 """Sets the item font bold/unbold."""
2451
2452 if not item:
2453 raise "\nERROR: Invalid Tree Item. "
2454
2455
2456 if item.IsBold() != bold:
2457 item.SetBold(bold)
2458 self._dirty = True
2459
2460
2462 """Sets the item font italic/non-italic."""
2463
2464 if not item:
2465 raise "\nERROR: Invalid Tree Item. "
2466
2467 if item.IsItalic() != italic:
2468 itemFont = self.GetItemFont(item)
2469 if itemFont != wx.NullFont:
2470 style = wx.ITALIC
2471 if not italic:
2472 style = ~style
2473
2474 item.SetItalic(italic)
2475 itemFont.SetStyle(style)
2476 self.SetItemFont(item, itemFont)
2477 self._dirty = True
2478
2479
2481 """
2482 Gives the item the visual feedback for drag and drop operations.
2483 This is useful when something is dragged from outside the CustomTreeCtrl.
2484 """
2485
2486 if not item:
2487 raise "\nERROR: Invalid Tree Item. "
2488
2489 if highlight:
2490 bg = wx.SystemSettings_GetColour(wx.SYS_COLOUR_HIGHLIGHT)
2491 fg = wx.SystemSettings_GetColour(wx.SYS_COLOUR_HIGHLIGHTTEXT)
2492
2493 item.Attr().SetTextColour(fg)
2494 item.Attr.SetBackgroundColour(bg)
2495 self.RefreshLine(item)
2496
2497
2498 - def SetItemTextColour(self, item, col):
2499 """Sets the item text colour."""
2500
2501 if not item:
2502 raise "\nERROR: Invalid Tree Item. "
2503
2504 if self.GetItemTextColour(item) == col:
2505 return
2506
2507 item.Attr().SetTextColour(col)
2508 self.RefreshLine(item)
2509
2510
2519
2520
2521 - def SetItemHyperText(self, item, hyper=True):
2522 """Sets whether the item is hypertext or not."""
2523
2524 if not item:
2525 raise "\nERROR: Invalid Tree Item. "
2526
2527 item.SetHyperText(hyper)
2528 self.RefreshLine(item)
2529
2530
2532 """Sets the item font."""
2533
2534 if not item:
2535 raise "\nERROR: Invalid Tree Item. "
2536
2537 if self.GetItemFont(item) == font:
2538 return
2539
2540 item.Attr().SetFont(font)
2541 self._dirty = True
2542
2543
2545 """Sets the CustomTreeCtrl font."""
2546
2547 wx.ScrolledWindow.SetFont(self, font)
2548
2549 self._normalFont = font
2550 self._boldFont = wx.Font(self._normalFont.GetPointSize(), self._normalFont.GetFamily(),
2551 self._normalFont.GetStyle(), wx.BOLD, self._normalFont.GetUnderlined(),
2552 self._normalFont.GetFaceName(), self._normalFont.GetEncoding())
2553
2554 return True
2555
2556
2557 - def GetHyperTextFont(self):
2558 """Returns the font used to render an hypertext item."""
2559
2560 return self._hypertextfont
2561
2562
2563 - def SetHyperTextFont(self, font):
2564 """Sets the font used to render an hypertext item."""
2565
2566 self._hypertextfont = font
2567 self._dirty = True
2568
2569
2570 - def SetHyperTextNewColour(self, colour):
2571 """Sets the colour used to render a non-visited hypertext item."""
2572
2573 self._hypertextnewcolour = colour
2574 self._dirty = True
2575
2576
2578 """Returns the colour used to render a non-visited hypertext item."""
2579
2580 return self._hypertextnewcolour
2581
2582
2584 """Sets the colour used to render a visited hypertext item."""
2585
2586 self._hypertextvisitedcolour = colour
2587 self._dirty = True
2588
2589
2591 """Returns the colour used to render a visited hypertext item."""
2592
2593 return self._hypertextvisitedcolour
2594
2595
2597 """Sets whether an hypertext item was visited."""
2598
2599 if not item:
2600 raise "\nERROR: Invalid Tree Item. "
2601
2602 item.SetVisited(visited)
2603 self.RefreshLine(item)
2604
2605
2607 """Returns whether an hypertext item was visited."""
2608
2609 if not item:
2610 raise "\nERROR: Invalid Tree Item. "
2611
2612 return item.GetVisited()
2613
2614
2616 """
2617 Sets the colour used to highlight focused selected items.
2618 This is applied only if gradient and Windows Vista styles are disabled.
2619 """
2620
2621 self._hilightBrush = wx.Brush(colour)
2622 self.RefreshSelected()
2623
2624
2626 """
2627 Sets the colour used to highlight unfocused selected items.
2628 This is applied only if gradient and Windows Vista styles are disabled.
2629 """
2630
2631 self._hilightUnfocusedBrush = wx.Brush(colour)
2632 self.RefreshSelected()
2633
2634
2636 """
2637 Returns the colour used to highlight focused selected items.
2638 This is applied only if gradient and Windows Vista styles are disabled.
2639 """
2640
2641 return self._hilightBrush.GetColour()
2642
2643
2645 """
2646 Returns the colour used to highlight unfocused selected items.
2647 This is applied only if gradient and Windows Vista styles are disabled.
2648 """
2649
2650 return self._hilightUnfocusedBrush.GetColour()
2651
2652
2654 """Sets the first gradient colour."""
2655
2656 if colour is None:
2657 colour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_HIGHLIGHT)
2658
2659 self._firstcolour = colour
2660 if self._usegradients:
2661 self.RefreshSelected()
2662
2663
2665 """Sets the second gradient colour."""
2666
2667 if colour is None:
2668
2669
2670 color = self.GetBackgroundColour()
2671 r, g, b = int(color.Red()), int(color.Green()), int(color.Blue())
2672 color = ((r >> 1) + 20, (g >> 1) + 20, (b >> 1) + 20)
2673 colour = wx.Colour(color[0], color[1], color[2])
2674
2675 self._secondcolour = colour
2676
2677 if self._usegradients:
2678 self.RefreshSelected()
2679
2680
2682 """Returns the first gradient colour."""
2683
2684 return self._firstcolour
2685
2686
2688 """Returns the second gradient colour."""
2689
2690 return self._secondcolour
2691
2692
2694 """Globally enables/disables drawing of gradient selection."""
2695
2696 self._usegradients = enable
2697 self._vistaselection = False
2698 self.RefreshSelected()
2699
2700
2702 """
2703 Sets the gradient style:
2704 0: horizontal gradient
2705 1: vertical gradient
2706 """
2707
2708
2709 self._gradientstyle = vertical
2710
2711 if self._usegradients:
2712 self.RefreshSelected()
2713
2714
2716 """
2717 Returns the gradient style:
2718 0: horizontal gradient
2719 1: vertical gradient
2720 """
2721
2722 return self._gradientstyle
2723
2724
2726 """Globally enables/disables drawing of Windows Vista selection."""
2727
2728 self._usegradients = False
2729 self._vistaselection = enable
2730 self.RefreshSelected()
2731
2732
2734 """
2735 Sets the pen used to draw the selected item border.
2736 The border pen is not used if the Windows Vista style is applied.
2737 """
2738
2739 self._borderPen = pen
2740 self.RefreshSelected()
2741
2742
2744 """
2745 Returns the pen used to draw the selected item border.
2746 The border pen is not used if the Windows Vista style is applied.
2747 """
2748
2749 return self._borderPen
2750
2751
2753 """Sets the pen used to draw the connecting lines between items."""
2754
2755 self._dottedPen = pen
2756 self._dirty = True
2757
2758
2760 """Returns the pen used to draw the connecting lines between items."""
2761
2762 return self._dottedPen
2763
2764
2766 """Sets the CustomTreeCtrl background image (can be none)."""
2767
2768 self._backgroundImage = image
2769 self.Refresh()
2770
2771
2773 """Returns the CustomTreeCtrl background image (can be none)."""
2774
2775 return self._backgroundImage
2776
2777
2779 """Returns the window associated to the item (if any)."""
2780
2781 if not item:
2782 raise "\nERROR: Invalid Item"
2783
2784 return item.GetWindow()
2785
2786
2788 """Returns whether the window associated to the item is enabled."""
2789
2790 if not item:
2791 raise "\nERROR: Invalid Item"
2792
2793 return item.GetWindowEnabled()
2794
2795
2797 """Enables/disables the window associated to the item."""
2798
2799 if not item:
2800 raise "\nERROR: Invalid Item"
2801
2802 item.SetWindowEnabled(enable)
2803
2804
2806 """
2807 Returns the item type:
2808 0: normal
2809 1: checkbox item
2810 2: radiobutton item
2811 """
2812
2813 if not item:
2814 raise "\nERROR: Invalid Item"
2815
2816 return item.GetType()
2817
2818
2819
2820
2821
2823 """Returns whether the item is visible or not."""
2824
2825 if not item:
2826 raise "\nERROR: Invalid Tree Item. "
2827
2828
2829 parent = item.GetParent()
2830
2831 while parent:
2832
2833 if not parent.IsExpanded():
2834 return False
2835
2836 parent = parent.GetParent()
2837
2838 startX, startY = self.GetViewStart()
2839 clientSize = self.GetClientSize()
2840
2841 rect = self.GetBoundingRect(item)
2842
2843 if not rect:
2844 return False
2845 if rect.GetWidth() == 0 or rect.GetHeight() == 0:
2846 return False
2847 if rect.GetBottom() < 0 or rect.GetTop() > clientSize.y:
2848 return False
2849 if rect.GetRight() < 0 or rect.GetLeft() > clientSize.x:
2850 return False
2851
2852 return True
2853
2854
2856 """Returns whether the item has children or not."""
2857
2858 if not item:
2859 raise "\nERROR: Invalid Tree Item. "
2860
2861
2862
2863
2864
2865
2866 return item.HasPlus()
2867
2868
2870 """Returns whether the item is expanded or not."""
2871
2872 if not item:
2873 raise "\nERROR: Invalid Tree Item. "
2874
2875 return item.IsExpanded()
2876
2877
2879 """Returns whether the item is selected or not."""
2880
2881 if not item:
2882 raise "\nERROR: Invalid Tree Item. "
2883
2884 return item.IsSelected()
2885
2886
2888 """Returns whether the item font is bold or not."""
2889
2890 if not item:
2891 raise "\nERROR: Invalid Tree Item. "
2892
2893 return item.IsBold()
2894
2895
2897 """Returns whether the item font is italic or not."""
2898
2899 if not item:
2900 raise "\nERROR: Invalid Tree Item. "
2901
2902 return item.IsItalic()
2903
2904
2905
2906
2907
2908
2910 """Gets the item parent."""
2911
2912 if not item:
2913 raise "\nERROR: Invalid Tree Item. "
2914
2915 return item.GetParent()
2916
2917
2919 """Gets the item first child."""
2920
2921 if not item:
2922 raise "\nERROR: Invalid Tree Item. "
2923
2924 cookie = 0
2925 return self.GetNextChild(item, cookie)
2926
2927
2929 """
2930 Gets the item next child based on the 'cookie' parameter.
2931 This method has no sense if you do not call GetFirstChild() before.
2932 """
2933
2934 if not item:
2935 raise "\nERROR: Invalid Tree Item. "
2936
2937 children = item.GetChildren()
2938
2939
2940
2941
2942 if cookie < len(children):
2943
2944 return children[cookie], cookie+1
2945
2946 else:
2947
2948
2949 return None, cookie
2950
2951
2953 """Gets the item last child."""
2954
2955 if not item:
2956 raise "\nERROR: Invalid Tree Item. "
2957
2958 children = item.GetChildren()
2959 return (len(children) == 0 and [None] or [children[-1]])[0]
2960
2961
2963 """Gets the next sibling of an item."""
2964
2965 if not item:
2966 raise "\nERROR: Invalid Tree Item. "
2967
2968 i = item
2969 parent = i.GetParent()
2970
2971 if parent == None:
2972
2973
2974 return None
2975
2976 siblings = parent.GetChildren()
2977 index = siblings.index(i)
2978
2979 n = index + 1
2980 return (n == len(siblings) and [None] or [siblings[n]])[0]
2981
2982
2984 """Gets the previous sibling of an item."""
2985
2986 if not item:
2987 raise "\nERROR: Invalid Tree Item. "
2988
2989 i = item
2990 parent = i.GetParent()
2991
2992 if parent == None:
2993
2994
2995 return None
2996
2997 siblings = parent.GetChildren()
2998 index = siblings.index(i)
2999
3000 return (index == 0 and [None] or [siblings[index-1]])[0]
3001
3002
3004 """Gets the next item. Only for internal use right now."""
3005
3006 if not item:
3007 raise "\nERROR: Invalid Tree Item. "
3008
3009 i = item
3010
3011
3012 children = i.GetChildren()
3013 if len(children) > 0:
3014 return children[0]
3015 else:
3016
3017 p = item
3018 toFind = None
3019 while p and not toFind:
3020 toFind = self.GetNextSibling(p)
3021 p = self.GetItemParent(p)
3022
3023 return toFind
3024
3025
3027 """Returns the first visible item."""
3028
3029 id = self.GetRootItem()
3030 if not id:
3031 return id
3032
3033 while id:
3034 if self.IsVisible(id):
3035 return id
3036 id = self.GetNext(id)
3037
3038 return None
3039
3040
3042 """Returns the next visible item."""
3043
3044 if not item:
3045 raise "\nERROR: Invalid Tree Item. "
3046
3047 id = item
3048
3049 while id:
3050 id = self.GetNext(id)
3051 if id and self.IsVisible(id):
3052 return id
3053
3054 return None
3055
3056
3058
3059 if not item:
3060 raise "\nERROR: Invalid Tree Item. "
3061
3062 raise "\nERROR: Not Implemented"
3063
3064 return None
3065
3066
3067 - def ResetTextControl(self):
3068 """Called by TreeTextCtrl when it marks itself for deletion."""
3069
3070 self._textCtrl.Destroy()
3071 self._textCtrl = None
3072
3073
3074 - def FindItem(self, idParent, prefixOrig):
3075 """Finds the first item starting with the given prefix after the given item."""
3076
3077
3078
3079
3080 prefix = prefixOrig.lower()
3081
3082
3083
3084
3085
3086 id = idParent
3087
3088 if len(prefix) == 1:
3089 id = self.GetNext(id)
3090
3091
3092 while id and not self.GetItemText(id).lower().startswith(prefix):
3093
3094 id = self.GetNext(id)
3095
3096
3097 if not id:
3098
3099
3100 id = self.GetRootItem()
3101 if self.HasFlag(TR_HIDE_ROOT):
3102
3103 id = self.GetNext(id)
3104
3105
3106 while id != idParent and not self.GetItemText(id).lower().startswith(prefix):
3107 id = self.GetNext(id)
3108
3109 return id
3110
3111
3112
3113
3114
3115
3116 - def DoInsertItem(self, parentId, previous, text, ct_type=0, wnd=None, image=-1, selImage=-1, data=None):
3117 """Actually inserts an item in the tree."""
3118
3119 if wnd is not None and not (self._windowStyle & TR_HAS_VARIABLE_ROW_HEIGHT):
3120 raise "\nERROR: In Order To Append/Insert Controls You Have To Use The Style TR_HAS_VARIABLE_ROW_HEIGHT"
3121
3122 if text.find("\n") >= 0 and not (self._windowStyle & TR_HAS_VARIABLE_ROW_HEIGHT):
3123 raise "\nERROR: In Order To Append/Insert A MultiLine Text You Have To Use The Style TR_HAS_VARIABLE_ROW_HEIGHT"
3124
3125 if ct_type < 0 or ct_type > 2:
3126 raise "\nERROR: Item Type Should Be 0 (Normal), 1 (CheckBox) or 2 (RadioButton). "
3127
3128 parent = parentId
3129
3130 if not parent:
3131
3132
3133 return self.AddRoot(text, ct_type, wnd, image, selImage, data)
3134
3135 self._dirty = True
3136
3137 item = GenericTreeItem(parent, text, ct_type, wnd, image, selImage, data)
3138
3139 if wnd is not None:
3140 self._hasWindows = True
3141 self._itemWithWindow.append(item)
3142
3143 parent.Insert(item, previous)
3144
3145 return item
3146
3147
3148 - def AddRoot(self, text, ct_type=0, wnd=None, image=-1, selImage=-1, data=None):
3149 """Adds a root to the CustomTreeCtrl. Only one root must exist."""
3150
3151 if self._anchor:
3152 raise "\nERROR: Tree Can Have Only One Root"
3153
3154 if wnd is not None and not (self._windowStyle & TR_HAS_VARIABLE_ROW_HEIGHT):
3155 raise "\nERROR: In Order To Append/Insert Controls You Have To Use The Style TR_HAS_VARIABLE_ROW_HEIGHT"
3156
3157 if text.find("\n") >= 0 and not (self._windowStyle & TR_HAS_VARIABLE_ROW_HEIGHT):
3158 raise "\nERROR: In Order To Append/Insert A MultiLine Text You Have To Use The Style TR_HAS_VARIABLE_ROW_HEIGHT"
3159
3160 if ct_type < 0 or ct_type > 2:
3161 raise "\nERROR: Item Type Should Be 0 (Normal), 1 (CheckBox) or 2 (RadioButton). "
3162
3163 self._dirty = True
3164
3165 self._anchor = GenericTreeItem(None, text, ct_type, wnd, image, selImage, data)
3166
3167 if wnd is not None:
3168 self._hasWindows = True
3169 self._itemWithWindow.append(self._anchor)
3170
3171 if self.HasFlag(TR_HIDE_ROOT):
3172
3173
3174
3175 self._anchor.SetHasPlus()
3176 self._anchor.Expand()
3177 self.CalculatePositions()
3178
3179 if not self.HasFlag(TR_MULTIPLE):
3180
3181 self._current = self._key_current = self._anchor
3182 self._current.SetHilight(True)
3183
3184 return self._anchor
3185
3186
3187 - def PrependItem(self, parent, text, ct_type=0, wnd=None, image=-1, selImage=-1, data=None):
3188 """Appends an item as a first child of parent."""
3189
3190 if wnd is not None and not (self._windowStyle & TR_HAS_VARIABLE_ROW_HEIGHT):
3191 raise "\nERROR: In Order To Append/Insert Controls You Have To Use The Style TR_HAS_VARIABLE_ROW_HEIGHT"
3192
3193 if text.find("\n") >= 0 and not (self._windowStyle & TR_HAS_VARIABLE_ROW_HEIGHT):
3194 raise "\nERROR: In Order To Append/Insert A MultiLine Text You Have To Use The Style TR_HAS_VARIABLE_ROW_HEIGHT"
3195
3196 return self.DoInsertItem(parent, 0, text, ct_type, wnd, image, selImage, data)
3197
3198
3199 - def InsertItemByItem(self, parentId, idPrevious, text, ct_type=0, wnd=None, image=-1, selImage=-1, data=None):
3200 """Auxiliary function to cope with the C++ hideous multifunction."""
3201
3202 if wnd is not None and not (self._windowStyle & TR_HAS_VARIABLE_ROW_HEIGHT):
3203 raise "\nERROR: In Order To Append/Insert Controls You Have To Use The Style TR_HAS_VARIABLE_ROW_HEIGHT"
3204
3205 if text.find("\n") >= 0 and not (self._windowStyle & TR_HAS_VARIABLE_ROW_HEIGHT):
3206 raise "\nERROR: In Order To Append/Insert A MultiLine Text You Have To Use The Style TR_HAS_VARIABLE_ROW_HEIGHT"
3207
3208 parent = parentId
3209
3210 if not parent:
3211
3212 return self.AddRoot(text, ct_type, wnd, image, selImage, data)
3213
3214 index = -1
3215 if idPrevious:
3216
3217 try:
3218 index = parent.GetChildren().index(idPrevious)
3219 except:
3220 raise "ERROR: Previous Item In CustomTreeCtrl.InsertItem() Is Not A Sibling"
3221
3222 return self.DoInsertItem(parentId, index+1, text, ct_type, wnd, image, selImage, data)
3223
3224
3225 - def InsertItemByIndex(self, parentId, before, text, ct_type=0, wnd=None, image=-1, selImage=-1, data=None):
3226 """Auxiliary function to cope with the C++ hideous multifunction."""
3227
3228 if wnd is not None and not (self._windowStyle & TR_HAS_VARIABLE_ROW_HEIGHT):
3229 raise "\nERROR: In Order To Append/Insert Controls You Have To Use The Style TR_HAS_VARIABLE_ROW_HEIGHT"
3230
3231 if text.find("\n") >= 0 and not (self._windowStyle & TR_HAS_VARIABLE_ROW_HEIGHT):
3232 raise "\nERROR: In Order To Append/Insert A MultiLine Text You Have To Use The Style TR_HAS_VARIABLE_ROW_HEIGHT"
3233
3234 parent = parentId
3235
3236 if not parent:
3237
3238 return self.AddRoot(text, ct_type, wnd, image, selImage, data)
3239
3240 return self.DoInsertItem(parentId, before, text, ct_type, wnd, image, selImage, data)
3241
3242
3243 - def InsertItem(self, parentId, input, text, ct_type=0, wnd=None, image=-1, selImage=-1, data=None):
3244 """Inserts an item after the given previous."""
3245
3246 if wnd is not None and not (self._windowStyle & TR_HAS_VARIABLE_ROW_HEIGHT):
3247 raise "\nERROR: In Order To Append/Insert Controls You Have To Use The Style TR_HAS_VARIABLE_ROW_HEIGHT"
3248
3249 if text.find("\n") >= 0 and not (self._windowStyle & TR_HAS_VARIABLE_ROW_HEIGHT):
3250 raise "\nERROR: In Order To Append/Insert A MultiLine Text You Have To Use The Style TR_HAS_VARIABLE_ROW_HEIGHT"
3251
3252 if type(input) == type(1):
3253 return self.InsertItemByIndex(parentId, input, text, ct_type, wnd, image, selImage, data)
3254 else:
3255 return self.InsertItemByItem(parentId, input, text, ct_type, wnd, image, selImage, data)
3256
3257
3258 - def AppendItem(self, parentId, text, ct_type=0, wnd=None, image=-1, selImage=-1, data=None):
3259 """Appends an item as a last child of its parent."""
3260
3261 if wnd is not None and not (self._windowStyle & TR_HAS_VARIABLE_ROW_HEIGHT):
3262 raise "\nERROR: In Order To Append/Insert Controls You Have To Use The Style TR_HAS_VARIABLE_ROW_HEIGHT"
3263
3264 if text.find("\n") >= 0 and not (self._windowStyle & TR_HAS_VARIABLE_ROW_HEIGHT):
3265 raise "\nERROR: In Order To Append/Insert A MultiLine Text You Have To Use The Style TR_HAS_VARIABLE_ROW_HEIGHT"
3266
3267 parent = parentId
3268
3269 if not parent:
3270
3271 return self.AddRoot(text, ct_type, wnd, image, selImage, data)
3272
3273 return self.DoInsertItem(parent, len(parent.GetChildren()), text, ct_type, wnd, image, selImage, data)
3274
3275
3277 """Actully sends the EVT_TREE_DELETE_ITEM event."""
3278
3279 event = TreeEvent(wxEVT_TREE_DELETE_ITEM, self.GetId())
3280 event._item = item
3281 event.SetEventObject(self)
3282 self.ProcessEvent(event)
3283
3284
3286 """Checks if the given item is under another one."""
3287
3288 while item:
3289
3290 if item == parent:
3291
3292
3293 return True
3294
3295 item = item.GetParent()
3296
3297 return False
3298
3299
3300
3317
3318
3329
3330
3332 """Delete an item."""
3333
3334 if not item:
3335 raise "\nERROR: Invalid Tree Item. "
3336
3337 self._dirty = True
3338
3339 if self._textCtrl != None and self.IsDescendantOf(item, self._textCtrl.item()):
3340
3341 self._textCtrl.StopEditing()
3342
3343 parent = item.GetParent()
3344
3345
3346 if self.IsDescendantOf(item, self._key_current):
3347
3348
3349
3350
3351
3352
3353 self._key_current = None
3354
3355
3356
3357 if self._select_me and self.IsDescendantOf(item, self._select_me):
3358 self._select_me = parent
3359
3360 if self.IsDescendantOf(item, self._current):
3361
3362
3363
3364
3365
3366
3367 self._current = None
3368 self._select_me = parent
3369
3370
3371 if parent:
3372
3373 parent.GetChildren().remove(item)
3374
3375 else:
3376
3377
3378 self._anchor = None
3379
3380
3381 item.DeleteChildren(self)
3382 self.SendDeleteEvent(item)
3383
3384 if item == self._select_me:
3385 self._select_me = None
3386
3387
3388 if item in self._itemWithWindow:
3389 wnd = item.GetWindow()
3390 wnd.Hide()
3391 wnd.Destroy()
3392 item._wnd = None
3393 self._itemWithWindow.remove(item)
3394
3395 del item
3396
3397
3399 """Delete all items in the CustomTreeCtrl."""
3400
3401 if self._anchor:
3402 self.Delete(self._anchor)
3403
3404
3442
3443
3460
3461
3495
3496
3502
3503
3511
3512
3514 """Hides the windows associated to the items. Used internally."""
3515
3516 for child in self._itemWithWindow:
3517 if not self.IsVisible(child):
3518 wnd = child.GetWindow()
3519 wnd.Hide()
3520
3521
3523 """Unselects the current selection."""
3524
3525 if self._current:
3526
3527 self._current.SetHilight(False)
3528 self.RefreshLine(self._current)
3529
3530 self._current = None
3531 self._select_me = None
3532
3533
3545
3546
3555
3556
3557
3558
3559
3560
3561
3562
3563
3565 """Used internally."""
3566
3567 parent = crt_item.GetParent()
3568
3569 if parent == None:
3570 return self.TagAllChildrenUntilLast(crt_item, last_item, select)
3571
3572 children = parent.GetChildren()
3573 index = children.index(crt_item)
3574
3575 count = len(children)
3576
3577 for n in xrange(index+1, count):
3578 if self.TagAllChildrenUntilLast(children[n], last_item, select):
3579 return True
3580
3581 return self.TagNextChildren(parent, last_item, select)
3582
3583
3585 """Used internally."""
3586
3587 crt_item.SetHilight(select)
3588 self.RefreshLine(crt_item)
3589
3590 if crt_item == last_item:
3591 return True
3592
3593 if crt_item.HasChildren():
3594 for child in crt_item.GetChildren():
3595 if self.TagAllChildrenUntilLast(child, last_item, select):
3596 return True
3597
3598 return False
3599
3600
3602 """Selects all the items between item1 and item2."""
3603
3604 self._select_me = None
3605
3606
3607
3608 first = (item1.GetY() < item2.GetY() and [item1] or [item2])[0]
3609 last = (item1.GetY() < item2.GetY() and [item2] or [item1])[0]
3610
3611 select = self._current.IsSelected()
3612
3613 if self.TagAllChildrenUntilLast(first, last, select):
3614 return
3615
3616 self.TagNextChildren(first, last, select)
3617
3618
3619 - def DoSelectItem(self, item, unselect_others=True, extended_select=False):
3620 """Actually selects/unselects an item, sending a EVT_TREE_SEL_CHANGED event."""
3621
3622 if not item:
3623 raise "\nERROR: Invalid Tree Item. "
3624
3625 self._select_me = None
3626
3627 is_single = not (self.GetTreeStyle() & TR_MULTIPLE)
3628
3629
3630 if is_single:
3631 if item.IsSelected():
3632 return
3633 unselect_others = True
3634 extended_select = False
3635
3636 elif unselect_others and item.IsSelected():
3637
3638
3639 if len(self.GetSelections()) == 1:
3640 return
3641
3642 event = TreeEvent(wxEVT_TREE_SEL_CHANGING, self.GetId())
3643 event._item = item
3644 event._itemOld = self._current
3645 event.SetEventObject(self)
3646
3647
3648 if self.GetEventHandler().ProcessEvent(event) and not event.IsAllowed():
3649 return
3650
3651 parent = self.GetItemParent(item)
3652 while parent:
3653 if not self.IsExpanded(parent):
3654 self.Expand(parent)
3655
3656 parent = self.GetItemParent(parent)
3657
3658
3659 if unselect_others:
3660 if is_single:
3661 self.Unselect()
3662 else:
3663 self.UnselectAll()
3664
3665
3666 if extended_select:
3667 if not self._current:
3668 self._current = self._key_current = self.GetRootItem()
3669
3670
3671 self.SelectItemRange(self._current, item)
3672
3673 else:
3674
3675 select = True
3676
3677
3678 if not unselect_others:
3679 select = not item.IsSelected()
3680
3681 self._current = self._key_current = item
3682 self._current.SetHilight(select)
3683 self.RefreshLine(self._current)
3684
3685
3686
3687
3688 self.EnsureVisible(item)
3689
3690 event.SetEventType(wxEVT_TREE_SEL_CHANGED)
3691 self.GetEventHandler().ProcessEvent(event)
3692
3693
3694 if self.IsItemHyperText(item):
3695 event = TreeEvent(wxEVT_TREE_ITEM_HYPERLINK, self.GetId())
3696 event._item = item
3697 self.GetEventHandler().ProcessEvent(event)
3698
3699
3714
3715
3717 """
3718 Internal function. Used to populate an array of selected items when
3719 the style TR_MULTIPLE is used.
3720 """
3721
3722 if not array:
3723 array = []
3724
3725 if item.IsSelected():
3726 array.append(item)
3727
3728 if item.HasChildren():
3729 for child in item.GetChildren():
3730 array = self.FillArray(child, array)
3731
3732 return array
3733
3734
3736 """
3737 Returns a list of selected items. This can be used only if CustomTreeCtrl has
3738 the TR_MULTIPLE style set.
3739 """
3740
3741 array = []
3742 idRoot = self.GetRootItem()
3743 if idRoot:
3744 array = self.FillArray(idRoot, array)
3745
3746
3747
3748 return array
3749
3750
3752 """Ensure that an item is visible in CustomTreeCtrl."""
3753
3754 if not item:
3755 raise "\nERROR: Invalid Tree Item. "
3756
3757
3758 parent = item.GetParent()
3759
3760 if self.HasFlag(TR_HIDE_ROOT):
3761 while parent and parent != self._anchor:
3762 self.Expand(parent)
3763 parent = parent.GetParent()
3764 else:
3765 while parent:
3766 self.Expand(parent)
3767 parent = parent.GetParent()
3768
3769 self.ScrollTo(item)
3770
3771
3816
3817
3819 """
3820 Returns whether 2 items have the same text.
3821 Override this function in the derived class to change the sort order of the items
3822 in the CustomTreeCtrl. The function should return a negative, zero or positive
3823 value if the first item is less than, equal to or greater than the second one.
3824
3825 The base class version compares items alphabetically.
3826 """
3827
3828 return self.GetItemText(item1) == self.GetItemText(item2)
3829
3830
3832 """
3833 Sorts the children of the given item using OnCompareItems method of CustomTreeCtrl.
3834 You should override that method to change the sort order (the default is ascending
3835 case-sensitive alphabetical order).
3836 """
3837
3838 if not item:
3839 raise "\nERROR: Invalid Tree Item. "
3840
3841 children = item.GetChildren()
3842
3843 if len(children) > 1:
3844 self._dirty = True
3845 children.sort(self.OnCompareItems)
3846
3847
3849 """Returns the normal image list."""
3850
3851 return self._imageListNormal
3852
3853
3855 """Returns the buttons image list (from which application-defined button images are taken)."""
3856
3857 return self._imageListButtons
3858
3859
3861 """Returns the state image list (from which application-defined state images are taken)."""
3862
3863 return self._imageListState
3864
3865
3867 """Returns the image list used to build the check/radio buttons."""
3868
3869 return self._imageListCheck
3870
3871
3873 """Calculates the height of a line."""
3874
3875 dc = wx.ClientDC(self)
3876 self._lineHeight = dc.GetCharHeight()
3877
3878 if self._imageListNormal:
3879
3880
3881
3882
3883 n = self._imageListNormal.GetImageCount()
3884
3885 for i in xrange(n):
3886
3887 width, height = self._imageListNormal.GetSize(i)
3888
3889 if height > self._lineHeight:
3890 self._lineHeight = height
3891
3892 if self._imageListButtons:
3893
3894
3895
3896
3897 n = self._imageListButtons.GetImageCount()
3898
3899 for i in xrange(n):
3900
3901 width, height = self._imageListButtons.GetSize(i)
3902
3903 if height > self._lineHeight:
3904 self._lineHeight = height
3905
3906 if self._imageListCheck:
3907
3908
3909
3910
3911 n = self._imageListCheck.GetImageCount()
3912
3913 for i in xrange(n):
3914
3915 width, height = self._imageListCheck.GetSize(i)
3916
3917 if height > self._lineHeight:
3918 self._lineHeight = height
3919
3920 if self._lineHeight < 30:
3921 self._lineHeight += 2
3922 else:
3923 self._lineHeight += self._lineHeight/10
3924
3925
3927 """Sets the normal image list."""
3928
3929 if self._ownsImageListNormal:
3930 del self._imageListNormal
3931
3932 self._imageListNormal = imageList
3933 self._ownsImageListNormal = False
3934 self._dirty = True
3935
3936
3937 if imageList:
3938 self.CalculateLineHeight()
3939
3940
3941 self._grayedImageList = wx.ImageList(16, 16, True, 0)
3942
3943 for ii in xrange(imageList.GetImageCount()):
3944
3945 bmp = imageList.GetBitmap(ii)
3946 image = wx.ImageFromBitmap(bmp)
3947 image = GrayOut(image)
3948 newbmp = wx.BitmapFromImage(image)
3949 self._grayedImageList.Add(newbmp)
3950
3951
3953 """Sets the state image list (from which application-defined state images are taken)."""
3954
3955 if self._ownsImageListState:
3956 del self._imageListState
3957
3958 self._imageListState = imageList
3959 self._ownsImageListState = False
3960
3961
3972
3973
3975 """Sets the check image list."""
3976
3977 if imglist is None:
3978
3979 self._imageListCheck = wx.ImageList(sizex, sizey)
3980 self._imageListCheck.Add(GetCheckedBitmap())
3981 self._imageListCheck.Add(GetNotCheckedBitmap())
3982 self._imageListCheck.Add(GetFlaggedBitmap())
3983 self._imageListCheck.Add(GetNotFlaggedBitmap())
3984
3985 else:
3986
3987 sizex, sizey = imglist.GetSize(0)
3988 self._imageListCheck = imglist
3989
3990
3991 self._grayedCheckList = wx.ImageList(sizex, sizey, True, 0)
3992
3993 for ii in xrange(self._imageListCheck.GetImageCount()):
3994
3995 bmp = self._imageListCheck.GetBitmap(ii)
3996 image = wx.ImageFromBitmap(bmp)
3997 image = GrayOut(image)
3998 newbmp = wx.BitmapFromImage(image)
3999 self._grayedCheckList.Add(newbmp)
4000
4001 self._dirty = True
4002
4003 if imglist:
4004 self.CalculateLineHeight()
4005
4006
4008 """Assigns the normal image list."""
4009
4010 self.SetImageList(imageList)
4011 self._ownsImageListNormal = True
4012
4013
4015 """Assigns the state image list."""
4016
4017 self.SetStateImageList(imageList)
4018 self._ownsImageListState = True
4019
4020
4026
4027
4028
4029
4030
4031
4047
4048
4056
4057
4059 """Gradient fill from colour 1 to colour 2 from top to bottom."""
4060
4061 dc.DrawRectangleRect(rect)
4062 border = self._borderPen.GetWidth()
4063
4064 dc.SetPen(wx.TRANSPARENT_PEN)
4065
4066
4067 if hasfocus:
4068 col2 = self._secondcolour
4069 col1 = self._firstcolour
4070 else:
4071 col2 = self._hilightUnfocusedBrush.GetColour()
4072 col1 = self._hilightUnfocusedBrush2.GetColour()
4073
4074 r1, g1, b1 = int(col1.Red()), int(col1.Green()), int(col1.Blue())
4075 r2, g2, b2 = int(col2.Red()), int(col2.Green()), int(col2.Blue())
4076
4077 flrect = float(rect.height)
4078
4079 rstep = float((r2 - r1)) / flrect
4080 gstep = float((g2 - g1)) / flrect
4081 bstep = float((b2 - b1)) / flrect
4082
4083 rf, gf, bf = 0, 0, 0
4084
4085 for y in xrange(rect.y+border, rect.y + rect.height-border):
4086 currCol = (r1 + rf, g1 + gf, b1 + bf)
4087 dc.SetBrush(wx.Brush(currCol, wx.SOLID))
4088 dc.DrawRectangle(rect.x+border, y, rect.width-2*border, 1)
4089 rf = rf + rstep
4090 gf = gf + gstep
4091 bf = bf + bstep
4092
4093
4095 """Gradient fill from colour 1 to colour 2 from left to right."""
4096
4097 dc.DrawRectangleRect(rect)
4098 border = self._borderPen.GetWidth()
4099
4100 dc.SetPen(wx.TRANSPARENT_PEN)
4101
4102
4103
4104 if hasfocus:
4105 col2 = self._secondcolour
4106 col1 = self._firstcolour
4107 else:
4108 col2 = self._hilightUnfocusedBrush.GetColour()
4109 col1 = self._hilightUnfocusedBrush2.GetColour()
4110
4111 r1, g1, b1 = int(col1.Red()), int(col1.Green()), int(col1.Blue())
4112 r2, g2, b2 = int(col2.Red()), int(col2.Green()), int(col2.Blue())
4113
4114 flrect = float(rect.width)
4115
4116 rstep = float((r2 - r1)) / flrect
4117 gstep = float((g2 - g1)) / flrect
4118 bstep = float((b2 - b1)) / flrect
4119
4120 rf, gf, bf = 0, 0, 0
4121
4122 for x in xrange(rect.x+border, rect.x + rect.width-border):
4123 currCol = (int(r1 + rf), int(g1 + gf), int(b1 + bf))
4124 dc.SetBrush(wx.Brush(currCol, wx.SOLID))
4125 dc.DrawRectangle(x, rect.y+border, 1, rect.height-2*border)
4126 rf = rf + rstep
4127 gf = gf + gstep
4128 bf = bf + bstep
4129
4130
4132 """Draw the selected item(s) with the Windows Vista style."""
4133
4134 if hasfocus:
4135
4136 outer = _rgbSelectOuter
4137 inner = _rgbSelectInner
4138 top = _rgbSelectTop
4139 bottom = _rgbSelectBottom
4140
4141 else:
4142
4143 outer = _rgbNoFocusOuter
4144 inner = _rgbNoFocusInner
4145 top = _rgbNoFocusTop
4146 bottom = _rgbNoFocusBottom
4147
4148 oldpen = dc.GetPen()
4149 oldbrush = dc.GetBrush()
4150
4151 dc.SetBrush(wx.TRANSPARENT_BRUSH)
4152 dc.SetPen(wx.Pen(outer))
4153 dc.DrawRoundedRectangleRect(rect, 3)
4154 rect.Deflate(1, 1)
4155 dc.SetPen(wx.Pen(inner))
4156 dc.DrawRoundedRectangleRect(rect, 2)
4157 rect.Deflate(1, 1)
4158
4159 r1, g1, b1 = int(top.Red()), int(top.Green()), int(top.Blue())
4160 r2, g2, b2 = int(bottom.Red()), int(bottom.Green()), int(bottom.Blue())
4161
4162 flrect = float(rect.height)
4163
4164 rstep = float((r2 - r1)) / flrect
4165 gstep = float((g2 - g1)) / flrect
4166 bstep = float((b2 - b1)) / flrect
4167
4168 rf, gf, bf = 0, 0, 0
4169 dc.SetPen(wx.TRANSPARENT_PEN)
4170
4171 for y in xrange(rect.y, rect.y + rect.height):
4172 currCol = (r1 + rf, g1 + gf, b1 + bf)
4173 dc.SetBrush(wx.Brush(currCol, wx.SOLID))
4174 dc.DrawRectangle(rect.x, y, rect.width, 1)
4175 rf = rf + rstep
4176 gf = gf + gstep
4177 bf = bf + bstep
4178
4179 dc.SetPen(oldpen)
4180 dc.SetBrush(oldbrush)
4181
4182
4184 """Actually paint an item."""
4185
4186 attr = item.GetAttributes()
4187
4188 if attr and attr.HasFont():
4189 dc.SetFont(attr.GetFont())
4190 elif item.IsBold():
4191 dc.SetFont(self._boldFont)
4192 if item.IsHyperText():
4193 dc.SetFont(self.GetHyperTextFont())
4194 if item.GetVisited():
4195 dc.SetTextForeground(self.GetHyperTextVisitedColour())
4196 else:
4197 dc.SetTextForeground(self.GetHyperTextNewColour())
4198
4199 text_w, text_h, dummy = dc.GetMultiLineTextExtent(item.GetText())
4200
4201 image = item.GetCurrentImage()
4202 checkimage = item.GetCurrentCheckedImage()
4203 image_w, image_h = 0, 0
4204
4205 if image != _NO_IMAGE:
4206
4207 if self._imageListNormal:
4208
4209 image_w, image_h = self._imageListNormal.GetSize(image)
4210 image_w += 4
4211
4212 else:
4213
4214 image = _NO_IMAGE
4215
4216 if item.GetType() != 0:
4217 wcheck, hcheck = self._imageListCheck.GetSize(item.GetType())
4218 wcheck += 4
4219 else:
4220 wcheck, hcheck = 0, 0
4221
4222 total_h = self.GetLineHeight(item)
4223 drawItemBackground = False
4224
4225 if item.IsSelected():
4226
4227
4228 if wx.Platform == "__WXMAC__":
4229 if not self._hasFocus:
4230 dc.SetBrush(wx.TRANSPARENT_BRUSH)
4231 dc.SetPen(wx.Pen(wx.SystemSettings_GetColour(wx.SYS_COLOUR_HIGHLIGHT), 1, wx.SOLID))
4232 else:
4233 dc.SetBrush(self._hilightBrush)
4234 else:
4235 dc.SetBrush((self._hasFocus and [self._hilightBrush] or [self._hilightUnfocusedBrush])[0])
4236 drawItemBackground = True
4237 else:
4238 if attr and attr.HasBackgroundColour():
4239 drawItemBackground = True
4240 colBg = attr.GetBackgroundColour()
4241 else:
4242 colBg = self._backgroundColour
4243
4244 dc.SetBrush(wx.Brush(colBg, wx.SOLID))
4245 dc.SetPen(wx.TRANSPARENT_PEN)
4246
4247 offset = (self.HasFlag(TR_ROW_LINES) and [1] or [0])[0]
4248
4249 if self.HasFlag(TR_FULL_ROW_HIGHLIGHT):
4250
4251 oldpen = dc.GetPen()
4252 dc.SetPen(wx.TRANSPARENT_PEN)
4253 x, y = self.GetPosition()
4254 w, h = self.GetSize()
4255
4256 itemrect = wx.Rect(x, item.GetY()+offset, w, total_h-offset)
4257
4258 if item.IsSelected():
4259 if self._usegradients:
4260 if self._gradientstyle == 0:
4261 self.DrawHorizontalGradient(dc, itemrect, self._hasFocus)
4262 else:
4263 self.DrawVerticalGradient(dc, itemrect, self._hasFocus)
4264 elif self._vistaselection:
4265 self.DrawVistaRectangle(dc, itemrect, self._hasFocus)
4266 else:
4267 dc.DrawRectangleRect(itemrect)
4268
4269 dc.SetPen(oldpen)
4270
4271 else:
4272
4273 if item.IsSelected() and image != _NO_IMAGE:
4274
4275
4276
4277
4278
4279 wnd = item.GetWindow()
4280 wndx = 0
4281 if wnd:
4282 wndx, wndy = item.GetWindowSize()
4283
4284 itemrect = wx.Rect(item.GetX() + wcheck + image_w - 2, item.GetY()+offset,
4285 item.GetWidth() - image_w - wcheck + 2 - wndx, total_h-offset)
4286
4287 if self._usegradients:
4288 if self._gradientstyle == 0:
4289 self.DrawHorizontalGradient(dc, itemrect, self._hasFocus)
4290 else:
4291 self.DrawVerticalGradient(dc, itemrect, self._hasFocus)
4292 elif self._vistaselection:
4293 self.DrawVistaRectangle(dc, itemrect, self._hasFocus)
4294 else:
4295 dc.DrawRectangleRect(itemrect)
4296
4297
4298
4299
4300 elif drawItemBackground:
4301
4302 minusicon = wcheck + image_w - 2
4303 itemrect = wx.Rect(item.GetX()+minusicon, item.GetY()+offset, item.GetWidth()-minusicon, total_h-offset)
4304
4305 if self._usegradients and self._hasFocus:
4306 if self._gradientstyle == 0:
4307 self.DrawHorizontalGradient(dc, itemrect, self._hasFocus)
4308 else:
4309 self.DrawVerticalGradient(dc, itemrect, self._hasFocus)
4310 else:
4311 dc.DrawRectangleRect(itemrect)
4312
4313 if image != _NO_IMAGE:
4314
4315 dc.SetClippingRegion(item.GetX(), item.GetY(), wcheck+image_w-2, total_h)
4316 if item.IsEnabled():
4317 imglist = self._imageListNormal
4318 else:
4319 imglist = self._grayedImageList
4320
4321 imglist.Draw(image, dc,
4322 item.GetX() + wcheck,
4323 item.GetY() + ((total_h > image_h) and [(total_h-image_h)/2] or [0])[0],
4324 wx.IMAGELIST_DRAW_TRANSPARENT)
4325
4326 dc.DestroyClippingRegion()
4327
4328 if wcheck:
4329 if item.IsEnabled():
4330 imglist = self._imageListCheck
4331 else:
4332 imglist = self._grayedCheckList
4333
4334 imglist.Draw(checkimage, dc,
4335 item.GetX(),
4336 item.GetY() + ((total_h > hcheck) and [(total_h-hcheck)/2] or [0])[0],
4337 wx.IMAGELIST_DRAW_TRANSPARENT)
4338
4339 dc.SetBackgroundMode(wx.TRANSPARENT)
4340 extraH = ((total_h > text_h) and [(total_h - text_h)/2] or [0])[0]
4341
4342 textrect = wx.Rect(wcheck + image_w + item.GetX(), item.GetY() + extraH, text_w, text_h)
4343
4344 if not item.IsEnabled():
4345 foreground = dc.GetTextForeground()
4346 dc.SetTextForeground(self._disabledColour)
4347 dc.DrawLabel(item.GetText(), textrect)
4348 dc.SetTextForeground(foreground)
4349 else:
4350 dc.DrawLabel(item.GetText(), textrect)
4351
4352 wnd = item.GetWindow()
4353 if wnd:
4354 wndx = wcheck + image_w + item.GetX() + text_w + 4
4355 xa, ya = self.CalcScrolledPosition((0, item.GetY()))
4356 if not wnd.IsShown():
4357 wnd.Show()
4358 if wnd.GetPosition() != (wndx, ya):
4359 wnd.SetPosition((wndx, ya))
4360
4361
4362 dc.SetFont(self._normalFont)
4363
4364
4365
4367 """Paint a level of CustomTreeCtrl."""
4368
4369 x = level*self._indent
4370
4371 if not self.HasFlag(TR_HIDE_ROOT):
4372
4373 x += self._indent
4374
4375 elif level == 0:
4376
4377
4378 origY = y
4379 children = item.GetChildren()
4380 count = len(children)
4381
4382 if count > 0:
4383 n = 0
4384 while n < count:
4385 oldY = y
4386 y = self.PaintLevel(children[n], dc, 1, y)
4387 n = n + 1
4388
4389 if not self.HasFlag(TR_NO_LINES) and self.HasFlag(TR_LINES_AT_ROOT) and count > 0:
4390
4391
4392 origY += self.GetLineHeight(children[0])>>1
4393 oldY += self.GetLineHeight(children[n-1])>>1
4394 dc.DrawLine(3, origY, 3, oldY)
4395
4396 return y
4397
4398 item.SetX(x+self._spacing)
4399 item.SetY(y)
4400
4401 h = self.GetLineHeight(item)
4402 y_top = y
4403 y_mid = y_top + (h>>1)
4404 y += h
4405
4406 exposed_x = dc.LogicalToDeviceX(0)
4407 exposed_y = dc.LogicalToDeviceY(y_top)
4408
4409 if self.IsExposed(exposed_x, exposed_y, 10000, h):
4410 if wx.Platform == "__WXMAC__":
4411
4412
4413 pen = ((item.IsSelected() and self._hasFocus) and [self._borderPen] or [wx.TRANSPARENT_PEN])[0]
4414 else:
4415 pen = self._borderPen
4416
4417 if item.IsSelected():
4418 if (wx.Platform == "__WXMAC__" and self._hasFocus):
4419 colText = wx.SystemSettings_GetColour(wx.SYS_COLOUR_HIGHLIGHTTEXT)
4420 else:
4421 colText = wx.SystemSettings_GetColour(wx.SYS_COLOUR_HIGHLIGHTTEXT)
4422 else:
4423 attr = item.GetAttributes()
4424 if attr and attr.HasTextColour():
4425 colText = attr.GetTextColour()
4426 else:
4427 colText = self.GetForegroundColour()
4428
4429 if self._vistaselection:
4430 colText = wx.BLACK
4431
4432
4433 dc.SetTextForeground(colText)
4434 dc.SetPen(pen)
4435 oldpen = pen
4436
4437
4438 self.PaintItem(item, dc)
4439
4440 if self.HasFlag(TR_ROW_LINES):
4441
4442
4443
4444 medium_grey = wx.Pen(wx.Colour(200, 200, 200))
4445 dc.SetPen(((self.GetBackgroundColour() == wx.WHITE) and [medium_grey] or [wx.WHITE_PEN])[0])
4446 dc.DrawLine(0, y_top, 10000, y_top)
4447 dc.DrawLine(0, y, 10000, y)
4448
4449
4450 dc.SetBrush(wx.WHITE_BRUSH)
4451 dc.SetTextForeground(wx.BLACK)
4452
4453 if not self.HasFlag(TR_NO_LINES):
4454
4455
4456 dc.SetPen(self._dottedPen)
4457 x_start = x
4458 if x > self._indent:
4459 x_start -= self._indent
4460 elif self.HasFlag(TR_LINES_AT_ROOT):
4461 x_start = 3
4462 dc.DrawLine(x_start, y_mid, x + self._spacing, y_mid)
4463 dc.SetPen(oldpen)
4464
4465
4466 if item.HasPlus() and self.HasButtons():
4467
4468 if self._imageListButtons:
4469
4470
4471 image_h = 0
4472 image_w = 0
4473 image = (item.IsExpanded() and [TreeItemIcon_Expanded] or [TreeItemIcon_Normal])[0]
4474 if item.IsSelected():
4475 image += TreeItemIcon_Selected - TreeItemIcon_Normal
4476
4477 image_w, image_h = self._imageListButtons.GetSize(image)
4478 xx = x - image_w/2
4479 yy = y_mid - image_h/2
4480
4481 dc.SetClippingRegion(xx, yy, image_w, image_h)
4482 self._imageListButtons.Draw(image, dc, xx, yy,
4483 wx.IMAGELIST_DRAW_TRANSPARENT)
4484 dc.DestroyClippingRegion()
4485
4486 else:
4487
4488 if self._windowStyle & TR_TWIST_BUTTONS:
4489
4490
4491 dc.SetPen(wx.BLACK_PEN)
4492 dc.SetBrush(self._hilightBrush)
4493 button = [wx.Point(), wx.Point(), wx.Point()]
4494
4495 if item.IsExpanded():
4496 button[0].x = x - 5
4497 button[0].y = y_mid - 3
4498 button[1].x = x + 5
4499 button[1].y = button[0].y
4500 button[2].x = x
4501 button[2].y = button[0].y + 6
4502 else:
4503 button[0].x = x - 3
4504 button[0].y = y_mid - 5
4505 button[1].x = button[0].x
4506 button[1].y = y_mid + 5
4507 button[2].x = button[0].x + 5
4508 button[2].y = y_mid
4509
4510 dc.DrawPolygon(button)
4511
4512 else:
4513
4514
4515 wImage = 9
4516 hImage = 9
4517
4518 flag = 0
4519
4520 if item.IsExpanded():
4521 flag |= _CONTROL_EXPANDED
4522 if item == self._underMouse:
4523 flag |= _CONTROL_CURRENT
4524
4525 _drawingfunction(self, dc, wx.Rect(x - wImage/2, y_mid - hImage/2,wImage, hImage), flag)
4526
4527 if item.IsExpanded():
4528
4529 children = item.GetChildren()
4530 count = len(children)
4531
4532 if count > 0:
4533
4534 n = 0
4535 level = level + 1
4536
4537 while n < count:
4538 oldY = y
4539 y = self.PaintLevel(children[n], dc, level, y)
4540 n = n + 1
4541
4542 if not self.HasFlag(TR_NO_LINES) and count > 0:
4543
4544
4545 oldY += self.GetLineHeight(children[n-1])>>1
4546 if self.HasButtons():
4547 y_mid += 5
4548
4549
4550 xOrigin, yOrigin = dc.GetDeviceOrigin()
4551 yOrigin = abs(yOrigin)
4552 width, height = self.GetClientSize()
4553
4554
4555 if y_mid < yOrigin:
4556 y_mid = yOrigin
4557 if oldY > yOrigin + height:
4558 oldY = yOrigin + height
4559
4560
4561
4562 if y_mid < oldY:
4563 dc.SetPen(self._dottedPen)
4564 dc.DrawLine(x, y_mid, x, oldY)
4565
4566 return y
4567
4568
4569
4570
4571
4572
4574 """Handles the wx.EVT_PAINT event."""
4575
4576 dc = wx.PaintDC(self)
4577 self.PrepareDC(dc)
4578
4579 if not self._anchor:
4580 return
4581
4582 dc.SetFont(self._normalFont)
4583 dc.SetPen(self._dottedPen)
4584
4585 y = 2
4586 self.PaintLevel(self._anchor, dc, 0, y)
4587
4588
4590 """Handles the wx.EVT_ERASE_BACKGROUND event."""
4591
4592
4593
4594
4595
4596 if not self._backgroundImage:
4597 event.Skip()
4598 return
4599
4600 if self._imageStretchStyle == _StyleTile:
4601 dc = event.GetDC()
4602
4603 if not dc:
4604 dc = wx.ClientDC(self)
4605 rect = self.GetUpdateRegion().GetBox()
4606 dc.SetClippingRect(rect)
4607
4608 self.TileBackground(dc)
4609
4610
4612 """Tiles the background image to fill all the available area."""
4613
4614 sz = self.GetClientSize()
4615 w = self._backgroundImage.GetWidth()
4616 h = self._backgroundImage.GetHeight()
4617
4618 x = 0
4619
4620 while x < sz.width:
4621 y = 0
4622
4623 while y < sz.height:
4624 dc.DrawBitmap(self._backgroundImage, x, y, True)
4625 y = y + h
4626
4627 x = x + w
4628
4629
4631 """Handles the wx.EVT_SET_FOCUS event."""
4632
4633 self._hasFocus = True
4634 self.RefreshSelected()
4635 event.Skip()
4636
4637
4639 """Handles the wx.EVT_KILL_FOCUS event."""
4640
4641 self._hasFocus = False
4642 self.RefreshSelected()
4643 event.Skip()
4644
4645
4647 """Handles the wx.EVT_CHAR event, sending a EVT_TREE_KEY_DOWN event."""
4648
4649 te = TreeEvent(wxEVT_TREE_KEY_DOWN, self.GetId())
4650 te._evtKey = event
4651 te.SetEventObject(self)
4652
4653 if self.GetEventHandler().ProcessEvent(te):
4654
4655 return
4656
4657 if self._current is None or self._key_current is None:
4658
4659 event.Skip()
4660 return
4661
4662
4663 is_multiple, extended_select, unselect_others = EventFlagsToSelType(self.GetTreeStyle(), event.ShiftDown(), event.CmdDown())
4664
4665
4666
4667
4668
4669
4670
4671
4672
4673
4674
4675
4676
4677 keyCode = event.GetKeyCode()
4678
4679 if keyCode in [ord("+"), wx.WXK_ADD]:
4680 if self._current.HasPlus() and not self.IsExpanded(self._current) and self.IsEnabled(self._current):
4681 self.Expand(self._current)
4682
4683 elif keyCode in [ord("*"), wx.WXK_MULTIPLY]:
4684 if not self.IsExpanded(self._current) and self.IsEnabled(self._current):
4685
4686 self.ExpandAll(self._current)
4687
4688 elif keyCode in [ord("-"), wx.WXK_SUBTRACT]:
4689 if self.IsExpanded(self._current):
4690 self.Collapse(self._current)
4691
4692 elif keyCode == wx.WXK_MENU:
4693
4694 itemRect = self.GetBoundingRect(self._current, True)
4695 event = TreeEvent(wxEVT_TREE_ITEM_MENU, self.GetId())
4696 event._item = self._current
4697
4698 event._pointDrag = wx.Point(ItemRect.GetX(), ItemRect.GetY() + ItemRect.GetHeight()/2)
4699 event.SetEventObject(self)
4700 self.GetEventHandler().ProcessEvent(event)
4701
4702 elif keyCode in [wx.WXK_RETURN, wx.WXK_SPACE]:
4703
4704 if not self.IsEnabled(self._current):
4705 event.Skip()
4706 return
4707
4708 if not event.HasModifiers():
4709 event = TreeEvent(wxEVT_TREE_ITEM_ACTIVATED, self.GetId())
4710 event._item = self._current
4711 event.SetEventObject(self)
4712 self.GetEventHandler().ProcessEvent(event)
4713
4714 if keyCode == wx.WXK_SPACE and self.GetItemType(self._current) > 0:
4715 checked = not self.IsItemChecked(self._current)
4716 self.CheckItem(self._current, checked)
4717
4718
4719
4720
4721
4722
4723 event.Skip()
4724
4725
4726
4727 elif keyCode == wx.WXK_UP:
4728 prev = self.GetPrevSibling(self._key_current)
4729 if not prev:
4730 prev = self.GetItemParent(self._key_current)
4731 if prev == self.GetRootItem() and self.HasFlag(TR_HIDE_ROOT):
4732 return
4733
4734 if prev:
4735 current = self._key_current
4736
4737 if current == self.GetFirstChild(prev)[0] and self.IsEnabled(prev):
4738
4739 self.DoSelectItem(prev, unselect_others, extended_select)
4740 self._key_current = prev
4741
4742 else:
4743 current = self._key_current
4744
4745
4746 while self.IsExpanded(prev) and self.HasChildren(prev):
4747 child = self.GetLastChild(prev)
4748 if child:
4749 prev = child
4750 current = prev
4751
4752
4753 while prev and not self.IsEnabled(prev):
4754 prev = self.GetPrevSibling(prev)
4755
4756 if not prev:
4757
4758 prev = self.GetItemParent(current)
4759 while prev and not self.IsEnabled(prev):
4760 prev = self.GetItemParent(prev)
4761
4762 if prev:
4763 self.DoSelectItem(prev, unselect_others, extended_select)
4764 self._key_current = prev
4765
4766
4767 elif keyCode == wx.WXK_LEFT:
4768
4769 prev = self.GetItemParent(self._current)
4770 if prev == self.GetRootItem() and self.HasFlag(TR_HIDE_ROOT):
4771
4772 prev = self.GetPrevSibling(self._current)
4773
4774 if self.IsExpanded(self._current):
4775 self.Collapse(self._current)
4776 else:
4777 if prev and self.IsEnabled(prev):
4778 self.DoSelectItem(prev, unselect_others, extended_select)
4779
4780 elif keyCode == wx.WXK_RIGHT:
4781
4782
4783 if self.IsExpanded(self._current) and self.HasChildren(self._current):
4784 child, cookie = self.GetFirstChild(self._key_current)
4785 if self.IsEnabled(child):
4786 self.DoSelectItem(child, unselect_others, extended_select)
4787 self._key_current = child
4788 else:
4789 self.Expand(self._current)
4790
4791
4792 elif keyCode == wx.WXK_DOWN:
4793 if self.IsExpanded(self._key_current) and self.HasChildren(self._key_current):
4794
4795 child = self.GetNextActiveItem(self._key_current)
4796
4797 if child:
4798 self.DoSelectItem(child, unselect_others, extended_select)
4799 self._key_current = child
4800
4801 else:
4802
4803 next = self.GetNextSibling(self._key_current)
4804
4805 if not next:
4806 current = self._key_current
4807 while current and not next:
4808 current = self.GetItemParent(current)
4809 if current:
4810 next = self.GetNextSibling(current)
4811 if not self.IsEnabled(next):
4812 next = None
4813
4814 else:
4815 while next and not self.IsEnabled(next):
4816 next = self.GetNext(next)
4817
4818 if next:
4819 self.DoSelectItem(next, unselect_others, extended_select)
4820 self._key_current = next
4821
4822
4823
4824 elif keyCode == wx.WXK_END:
4825
4826 last = self.GetRootItem()
4827
4828 while last and self.IsExpanded(last):
4829
4830 lastChild = self.GetLastChild(last)
4831
4832
4833
4834
4835 if not lastChild:
4836 break
4837
4838 last = lastChild
4839
4840 if last and self.IsEnabled(last):
4841
4842 self.DoSelectItem(last, unselect_others, extended_select)
4843
4844
4845 elif keyCode == wx.WXK_HOME:
4846
4847 prev = self.GetRootItem()
4848
4849 if not prev:
4850 return
4851
4852 if self.HasFlag(TR_HIDE_ROOT):
4853 prev, cookie = self.GetFirstChild(prev)
4854 if not prev:
4855 return
4856
4857 if self.IsEnabled(prev):
4858 self.DoSelectItem(prev, unselect_others, extended_select)
4859
4860 else:
4861
4862 if not event.HasModifiers() and ((keyCode >= ord('0') and keyCode <= ord('9')) or \
4863 (keyCode >= ord('a') and keyCode <= ord('z')) or \
4864 (keyCode >= ord('A') and keyCode <= ord('Z'))):
4865
4866
4867 ch = chr(keyCode)
4868 id = self.FindItem(self._current, self._findPrefix + ch)
4869
4870 if not id:
4871
4872 return
4873
4874 if self.IsEnabled(id):
4875 self.SelectItem(id)
4876 self._findPrefix += ch
4877
4878
4879
4880
4881 if not self._findTimer:
4882 self._findTimer = TreeFindTimer(self)
4883
4884 self._findTimer.Start(_DELAY, wx.TIMER_ONE_SHOT)
4885
4886 else:
4887
4888 event.Skip()
4889
4890
4892 """Returns the next active item. Used Internally at present. """
4893
4894 if down:
4895 sibling = self.GetNextSibling
4896 else:
4897 sibling = self.GetPrevSibling
4898
4899 if self.GetItemType(item) == 2 and not self.IsItemChecked(item):
4900
4901
4902 found = 0
4903
4904 while 1:
4905 child = sibling(item)
4906 if (child and self.IsEnabled(child)) or not child:
4907 break
4908 item = child
4909
4910 else:
4911
4912
4913 child, cookie = self.GetFirstChild(item)
4914 while child and not self.IsEnabled(child):
4915 child, cookie = self.GetNextChild(item, cookie)
4916
4917 if child and self.IsEnabled(child):
4918 return child
4919
4920 return None
4921
4922
4923 - def HitTest(self, point, flags=0):
4924 """
4925 Calculates which (if any) item is under the given point, returning the tree item
4926 at this point plus extra information flags. Flags is a bitlist of the following:
4927
4928 TREE_HITTEST_ABOVE above the client area
4929 TREE_HITTEST_BELOW below the client area
4930 TREE_HITTEST_NOWHERE no item has been hit
4931 TREE_HITTEST_ONITEMBUTTON on the button associated to an item
4932 TREE_HITTEST_ONITEMICON on the icon associated to an item
4933 TREE_HITTEST_ONITEMCHECKICON on the check/radio icon, if present
4934 TREE_HITTEST_ONITEMINDENT on the indent associated to an item
4935 TREE_HITTEST_ONITEMLABEL on the label (string) associated to an item
4936 TREE_HITTEST_ONITEMRIGHT on the right of the label associated to an item
4937 TREE_HITTEST_TOLEFT on the left of the client area
4938 TREE_HITTEST_TORIGHT on the right of the client area
4939 TREE_HITTEST_ONITEMUPPERPART on the upper part (first half) of the item
4940 TREE_HITTEST_ONITEMLOWERPART on the lower part (second half) of the item
4941 TREE_HITTEST_ONITEM anywhere on the item
4942
4943 Note: both the item (if any, None otherwise) and the flag are always returned as a tuple.
4944 """
4945
4946 w, h = self.GetSize()
4947 flags = 0
4948
4949 if point.x < 0:
4950 flags |= TREE_HITTEST_TOLEFT
4951 if point.x > w:
4952 flags |= TREE_HITTEST_TORIGHT
4953 if point.y < 0:
4954 flags |= TREE_HITTEST_ABOVE
4955 if point.y > h:
4956 flags |= TREE_HITTEST_BELOW
4957
4958 if flags:
4959 return None, flags
4960
4961 if self._anchor == None:
4962 flags = TREE_HITTEST_NOWHERE
4963 return None, flags
4964
4965 hit, flags = self._anchor.HitTest(self.CalcUnscrolledPosition(point), self, flags, 0)
4966
4967 if hit == None:
4968 flags = TREE_HITTEST_NOWHERE
4969 return None, flags
4970
4971 if not self.IsEnabled(hit):
4972 return None, flags
4973
4974 return hit, flags
4975
4976
4978 """Gets the bounding rectangle of the item."""
4979
4980 if not item:
4981 raise "\nERROR: Invalid Tree Item. "
4982
4983 i = item
4984
4985 startX, startY = self.GetViewStart()
4986 rect = wx.Rect()
4987
4988 rect.x = i.GetX() - startX*_PIXELS_PER_UNIT
4989 rect.y = i.GetY() - startY*_PIXELS_PER_UNIT
4990 rect.width = i.GetWidth()
4991 rect.height = self.GetLineHeight(i)
4992
4993 return rect
4994
4995
4996 - def Edit(self, item):
4997 """
4998 Internal function. Starts the editing of an item label, sending a
4999 EVT_TREE_BEGIN_LABEL_EDIT event.
5000 """
5001
5002 te = TreeEvent(wxEVT_TREE_BEGIN_LABEL_EDIT, self.GetId())
5003 te._item = item
5004 te.SetEventObject(self)
5005 if self.GetEventHandler().ProcessEvent(te) and not te.IsAllowed():
5006
5007 return
5008
5009
5010
5011
5012 if self._dirty:
5013 if wx.Platform in ["__WXMSW__", "__WXMAC__"]:
5014 self.Update()
5015 else:
5016 wx.YieldIfNeeded()
5017
5018 if self._textCtrl != None and item != self._textCtrl.item():
5019 self._textCtrl.StopEditing()
5020
5021 self._textCtrl = TreeTextCtrl(self, item=item)
5022 self._textCtrl.SetFocus()
5023
5024
5026 """
5027 Returns a pointer to the edit TextCtrl if the item is being edited or
5028 None otherwise (it is assumed that no more than one item may be edited
5029 simultaneously).
5030 """
5031
5032 return self._textCtrl
5033
5034
5036 """
5037 Called by TreeTextCtrl, to accept the changes and to send the
5038 EVT_TREE_END_LABEL_EDIT event.
5039 """
5040
5041 le = TreeEvent(wxEVT_TREE_END_LABEL_EDIT, self.GetId())
5042 le._item = item
5043 le.SetEventObject(self)
5044 le._label = value
5045 le._editCancelled = False
5046
5047 return not self.GetEventHandler().ProcessEvent(le) or le.IsAllowed()
5048
5049
5051 """
5052 Called by TreeTextCtrl, to cancel the changes and to send the
5053 EVT_TREE_END_LABEL_EDIT event.
5054 """
5055
5056
5057 le = TreeEvent(wxEVT_TREE_END_LABEL_EDIT, self.GetId())
5058 le._item = item
5059 le.SetEventObject(self)
5060 le._label = ""
5061 le._editCancelled = True
5062
5063 self.GetEventHandler().ProcessEvent(le)
5064
5065
5067 """The timer for renaming has expired. Start editing."""
5068
5069 self.Edit(self._current)
5070
5071
5073 """Handles a bunch of wx.EVT_MOUSE_EVENTS events."""
5074
5075 if not self._anchor:
5076 return
5077
5078 pt = self.CalcUnscrolledPosition(event.GetPosition())
5079
5080
5081 flags = 0
5082 thisItem, flags = self._anchor.HitTest(pt, self, flags, 0)
5083 underMouse = thisItem
5084 underMouseChanged = underMouse != self._underMouse
5085
5086 if underMouse and (flags & TREE_HITTEST_ONITEMBUTTON) and not event.LeftIsDown() and \
5087 not self._isDragging and (not self._renameTimer or not self._renameTimer.IsRunning()):
5088 underMouse = underMouse
5089 else:
5090 underMouse = None
5091
5092 if underMouse != self._underMouse:
5093 if self._underMouse:
5094
5095 self._underMouse = None
5096
5097 self._underMouse = underMouse
5098
5099
5100 hoverItem = thisItem
5101
5102
5103 if underMouseChanged and not self._isDragging and (not self._renameTimer or not self._renameTimer.IsRunning()):
5104
5105 if hoverItem is not None:
5106
5107 hevent = TreeEvent(wxEVT_TREE_ITEM_GETTOOLTIP, self.GetId())
5108 hevent._item = hoverItem
5109 hevent.SetEventObject(self)
5110
5111 if self.GetEventHandler().ProcessEvent(hevent) and hevent.IsAllowed():
5112 self.SetToolTip(hevent._label)
5113
5114 if hoverItem.IsHyperText() and (flags & TREE_HITTEST_ONITEMLABEL) and hoverItem.IsEnabled():
5115 self.SetCursor(wx.StockCursor(wx.CURSOR_HAND))
5116 self._isonhyperlink = True
5117 else:
5118 if self._isonhyperlink:
5119 self.SetCursor(wx.StockCursor(wx.CURSOR_ARROW))
5120 self._isonhyperlink = False
5121
5122
5123
5124
5125
5126 if not (event.LeftDown() or event.LeftUp() or event.RightDown() or event.LeftDClick() or \
5127 event.Dragging() or ((event.Moving() or event.RightUp()) and self._isDragging)):
5128
5129 event.Skip()
5130 return
5131
5132 flags = 0
5133 item, flags = self._anchor.HitTest(pt, self, flags, 0)
5134
5135 if event.Dragging() and not self._isDragging and ((flags & TREE_HITTEST_ONITEMICON) or (flags & TREE_HITTEST_ONITEMLABEL)):
5136
5137 if self._dragCount == 0:
5138 self._dragStart = pt
5139
5140 self._countDrag = 0
5141 self._dragCount = self._dragCount + 1
5142
5143 if self._dragCount != 3:
5144
5145 return
5146
5147 command = (event.RightIsDown() and [wxEVT_TREE_BEGIN_RDRAG] or [wxEVT_TREE_BEGIN_DRAG])[0]
5148
5149 nevent = TreeEvent(command, self.GetId())
5150 nevent._item = self._current
5151 nevent.SetEventObject(self)
5152 newpt = self.CalcScrolledPosition(pt)
5153 nevent.SetPoint(newpt)
5154
5155
5156
5157 nevent.Veto()
5158
5159 if self.GetEventHandler().ProcessEvent(nevent) and nevent.IsAllowed():
5160
5161
5162 self._isDragging = True
5163
5164
5165
5166 self._oldCursor = self._cursor
5167
5168
5169 if not (self.GetTreeStyle() & TR_MULTIPLE):
5170 self._oldSelection = self.GetSelection()
5171
5172 if self._oldSelection:
5173
5174 self._oldSelection.SetHilight(False)
5175 self.RefreshLine(self._oldSelection)
5176 else:
5177 selections = self.GetSelections()
5178 if len(selections) == 1:
5179 self._oldSelection = selections[0]
5180 self._oldSelection.SetHilight(False)
5181 self.RefreshLine(self._oldSelection)
5182
5183 if self._dragImage:
5184 del self._dragImage
5185
5186
5187 self._dragImage = DragImage(self, self._current)
5188 self._dragImage.BeginDrag(wx.Point(0,0), self)
5189 self._dragImage.Show()
5190 self._dragImage.Move(self.CalcScrolledPosition(pt))
5191
5192 elif event.Dragging() and self._isDragging:
5193
5194 self._dragImage.Move(self.CalcScrolledPosition(pt))
5195
5196 if self._countDrag == 0 and item:
5197 self._oldItem = item
5198
5199 if item != self._dropTarget:
5200
5201
5202 if self._dropTarget:
5203 self._dropTarget.SetHilight(False)
5204 self.RefreshLine(self._dropTarget)
5205 if item:
5206 item.SetHilight(True)
5207 self.RefreshLine(item)
5208 self._countDrag = self._countDrag + 1
5209 self._dropTarget = item
5210
5211 self.Update()
5212
5213 if self._countDrag >= 3:
5214
5215 self.RefreshLine(self._oldItem)
5216 self._countDrag = 0
5217
5218 elif (event.LeftUp() or event.RightUp()) and self._isDragging:
5219
5220 if self._dragImage:
5221 self._dragImage.EndDrag()
5222
5223 if self._dropTarget:
5224 self._dropTarget.SetHilight(False)
5225
5226 if self._oldSelection:
5227
5228 self._oldSelection.SetHilight(True)
5229 self.RefreshLine(self._oldSelection)
5230 self._oldSelection = None
5231
5232
5233 event = TreeEvent(wxEVT_TREE_END_DRAG, self.GetId())
5234 event._item = item
5235 event._pointDrag = self.CalcScrolledPosition(pt)
5236 event.SetEventObject(self)
5237
5238 self.GetEventHandler().ProcessEvent(event)
5239
5240 self._isDragging = False
5241 self._dropTarget = None
5242
5243 self.SetCursor(self._oldCursor)
5244
5245 if wx.Platform in ["__WXMSW__", "__WXMAC__"]:
5246 self.Refresh()
5247 else:
5248
5249 wx.YieldIfNeeded()
5250
5251 else:
5252
5253
5254
5255
5256
5257
5258 if event.LeftDown():
5259 self._hasFocus = True
5260 self.SetFocusIgnoringChildren()
5261 event.Skip()
5262
5263
5264
5265 self._dragCount = 0
5266
5267 if item == None:
5268 if self._textCtrl != None and item != self._textCtrl.item():
5269 self._textCtrl.StopEditing()
5270 return
5271
5272 if event.RightDown():
5273
5274 if self._textCtrl != None and item != self._textCtrl.item():
5275 self._textCtrl.StopEditing()
5276
5277 self._hasFocus = True
5278 self.SetFocusIgnoringChildren()
5279
5280
5281
5282 if not self.IsSelected(item):
5283
5284 self.DoSelectItem(item, True, False)
5285
5286 nevent = TreeEvent(wxEVT_TREE_ITEM_RIGHT_CLICK, self.GetId())
5287 nevent._item = item
5288 nevent._pointDrag = self.CalcScrolledPosition(pt)
5289 nevent.SetEventObject(self)
5290 event.Skip(not self.GetEventHandler().ProcessEvent(nevent))
5291
5292
5293
5294 nevent2 = TreeEvent(wxEVT_TREE_ITEM_MENU, self.GetId())
5295 nevent2._item = item
5296 nevent2._pointDrag = self.CalcScrolledPosition(pt)
5297 nevent2.SetEventObject(self)
5298 self.GetEventHandler().ProcessEvent(nevent2)
5299
5300 elif event.LeftUp():
5301
5302
5303
5304 if self.HasFlag(TR_MULTIPLE):
5305
5306 selections = self.GetSelections()
5307
5308 if len(selections) > 1 and not event.CmdDown() and not event.ShiftDown():
5309
5310 self.DoSelectItem(item, True, False)
5311
5312 if self._lastOnSame:
5313
5314 if item == self._current and (flags & TREE_HITTEST_ONITEMLABEL) and self.HasFlag(TR_EDIT_LABELS):
5315
5316 if self._renameTimer:
5317
5318 if self._renameTimer.IsRunning():
5319
5320 self._renameTimer.Stop()
5321
5322 else:
5323
5324 self._renameTimer = TreeRenameTimer(self)
5325
5326 self._renameTimer.Start(_DELAY, True)
5327
5328 self._lastOnSame = False
5329
5330
5331 else:
5332
5333 if not item or not item.IsEnabled():
5334 if self._textCtrl != None and item != self._textCtrl.item():
5335 self._textCtrl.StopEditing()
5336 return
5337
5338 if self._textCtrl != None and item != self._textCtrl.item():
5339 self._textCtrl.StopEditing()
5340
5341 self._hasFocus = True
5342 self.SetFocusIgnoringChildren()
5343
5344 if event.LeftDown():
5345
5346 self._lastOnSame = item == self._current
5347
5348 if flags & TREE_HITTEST_ONITEMBUTTON:
5349
5350
5351
5352 if event.LeftDown():
5353
5354 self.Toggle(item)
5355
5356
5357 return
5358
5359 if item.GetType() > 0 and (flags & TREE_HITTEST_ONITEMCHECKICON):
5360
5361 if event.LeftDown():
5362
5363 self.CheckItem(item, not self.IsItemChecked(item))
5364
5365 return
5366
5367
5368
5369
5370
5371
5372 if not self.IsSelected(item) or event.CmdDown():
5373
5374 if flags & TREE_HITTEST_ONITEM:
5375
5376 if item.IsHyperText():
5377 self.SetItemVisited(item, True)
5378
5379 is_multiple, extended_select, unselect_others = EventFlagsToSelType(self.GetTreeStyle(),
5380 event.ShiftDown(),
5381 event.CmdDown())
5382
5383 self.DoSelectItem(item, unselect_others, extended_select)
5384
5385
5386
5387 if event.LeftDClick():
5388
5389
5390 if self._renameTimer:
5391 self._renameTimer.Stop()
5392
5393 self._lastOnSame = False
5394
5395
5396 nevent = TreeEvent(wxEVT_TREE_ITEM_ACTIVATED, self.GetId())
5397 nevent._item = item
5398 nevent._pointDrag = self.CalcScrolledPosition(pt)
5399 nevent.SetEventObject(self)
5400 if not self.GetEventHandler().ProcessEvent(nevent):
5401
5402
5403
5404
5405
5406 self.Toggle(item)
5407
5408
5438
5439
5441 """Calculates overall position and size of an item."""
5442
5443 attr = item.GetAttributes()
5444
5445 if attr and attr.HasFont():
5446 dc.SetFont(attr.GetFont())
5447 elif item.IsBold():
5448 dc.SetFont(self._boldFont)
5449 else:
5450 dc.SetFont(self._normalFont)
5451
5452 text_w, text_h, dummy = dc.GetMultiLineTextExtent(item.GetText())
5453 text_h+=2
5454
5455
5456 dc.SetFont(self._normalFont)
5457
5458 image_w, image_h = 0, 0
5459 image = item.GetCurrentImage()
5460
5461 if image != _NO_IMAGE:
5462
5463 if self._imageListNormal:
5464
5465 image_w, image_h = self._imageListNormal.GetSize(image)
5466 image_w += 4
5467
5468 total_h = ((image_h > text_h) and [image_h] or [text_h])[0]
5469
5470 checkimage = item.GetCurrentCheckedImage()
5471 if checkimage is not None:
5472 wcheck, hcheck = self._imageListCheck.GetSize(checkimage)
5473 wcheck += 4
5474 else:
5475 wcheck = 0
5476
5477 if total_h < 30:
5478 total_h += 2
5479 else:
5480 total_h += total_h/10
5481
5482 if total_h > self._lineHeight:
5483 self._lineHeight = total_h
5484
5485 if not item.GetWindow():
5486 item.SetWidth(image_w+text_w+wcheck+2)
5487 item.SetHeight(total_h)
5488 else:
5489 item.SetWidth(item.GetWindowSize()[0]+image_w+text_w+wcheck+2)
5490
5491
5493 """Calculates the level of an item."""
5494
5495 x = level*self._indent
5496
5497 if not self.HasFlag(TR_HIDE_ROOT):
5498
5499 x += self._indent
5500
5501 elif level == 0:
5502
5503
5504
5505 children = item.GetChildren()
5506 count = len(children)
5507 level = level + 1
5508 for n in xrange(count):
5509 y = self.CalculateLevel(children[n], dc, level, y)
5510
5511 self.CalculateSize(item, dc)
5512
5513
5514 item.SetX(x+self._spacing)
5515 item.SetY(y)
5516 y += self.GetLineHeight(item)
5517
5518 if not item.IsExpanded():
5519
5520 return y
5521
5522 children = item.GetChildren()
5523 count = len(children)
5524 level = level + 1
5525 for n in xrange(count):
5526 y = self.CalculateLevel(children[n], dc, level, y)
5527
5528 return y
5529
5530
5532 """Calculates all the positions of the visible items."""
5533
5534 if not self._anchor:
5535 return
5536
5537 dc = wx.ClientDC(self)
5538 self.PrepareDC(dc)
5539
5540 dc.SetFont(self._normalFont)
5541 dc.SetPen(self._dottedPen)
5542 y = 2
5543 y = self.CalculateLevel(self._anchor, dc, 0, y)
5544
5545
5547 """Refreshes a damaged subtree of an item."""
5548
5549 if self._dirty:
5550 return
5551 if self._freezeCount:
5552 return
5553
5554 client = self.GetClientSize()
5555
5556 rect = wx.Rect()
5557 x, rect.y = self.CalcScrolledPosition(0, item.GetY())
5558 rect.width = client.x
5559 rect.height = client.y
5560
5561 self.Refresh(True, rect)
5562 self.AdjustMyScrollbars()
5563
5564
5566 """Refreshes a damaged item line."""
5567
5568 if self._dirty:
5569 return
5570 if self._freezeCount:
5571 return
5572
5573 rect = wx.Rect()
5574 x, rect.y = self.CalcScrolledPosition(0, item.GetY())
5575 rect.width = self.GetClientSize().x
5576 rect.height = self.GetLineHeight(item)
5577
5578 self.Refresh(True, rect)
5579
5580
5582 """Refreshes a damaged selected item line."""
5583
5584 if self._freezeCount:
5585 return
5586
5587
5588
5589 if self._anchor:
5590 self.RefreshSelectedUnder(self._anchor)
5591
5592
5605
5606
5608 """Freeze CustomTreeCtrl."""
5609
5610 self._freezeCount = self._freezeCount + 1
5611
5612
5614 """Thaw CustomTreeCtrl."""
5615
5616 if self._freezeCount == 0:
5617 raise "\nERROR: Thawing Unfrozen Tree Control?"
5618
5619 self._freezeCount = self._freezeCount - 1
5620
5621 if not self._freezeCount:
5622 self.Refresh()
5623
5624
5625
5626
5627
5628
5630 """Changes the background colour of CustomTreeCtrl."""
5631
5632 if not wx.Window.SetBackgroundColour(self, colour):
5633 return False
5634
5635 if self._freezeCount:
5636 return True
5637
5638 self.Refresh()
5639
5640 return True
5641
5642
5644 """Changes the foreground colour of CustomTreeCtrl."""
5645
5646 if not wx.Window.SetForegroundColour(self, colour):
5647 return False
5648
5649 if self._freezeCount:
5650 return True
5651
5652 self.Refresh()
5653
5654 return True
5655
5656
5664
5665
5667 """Something is better than nothing..."""
5668
5669
5670
5671
5672
5673 return wx.Size(100, 80)
5674
5675
5677 """Gets the class default attributes."""
5678
5679 attr = wx.VisualAttributes()
5680 attr.colFg = wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOWTEXT)
5681 attr.colBg = wx.SystemSettings_GetColour(wx.SYS_COLOUR_LISTBOX)
5682 attr.font = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
5683 return attr
5684