| Home | Trees | Indices | Help |
|---|
|
|
1 # --------------------------------------------------------------------------------- #
2 # SUPERTOOLTIP wxPython IMPLEMENTATION
3 #
4 # Andrea Gavana, @ 07 October 2008
5 # Latest Revision: 07 October 2008, 22.00 GMT
6 #
7 #
8 # TODO List
9 #
10 # 1) Maybe add some more customization like multiline text
11 # in the header and footer;
12 # 2) Check whether it's possible to use rounded corners and
13 # shadows on the Mac
14 #
15 #
16 # For all kind of problems, requests of enhancements and bug reports, please
17 # write to me at:
18 #
19 # andrea.gavana@gmail.com
20 # gavana@kpo.kz
21 #
22 # Or, obviously, to the wxPython mailing list!!!
23 #
24 #
25 # End Of Comments
26 # --------------------------------------------------------------------------------- #
27
28 """
29 Description
30 ===========
31
32 SuperToolTip is a class that mimics the behaviour of wx.TipWindow and generic tooltip
33 windows, although it is a custom-drawn widget.
34 This class supports:
35
36 * Blended triple-gradient for the tooltip background;
37 * Header text and header image, with possibility to set the header font indipendently;
38 * Footer text and footer image, with possibility to set the footer font indipendently;
39 * Multiline text message in the tooltip body, plus an optional image as "body image";
40 * Bold lines and hyperlink lines in the tooltip body;
41 * A wide set of predefined drawing styles for the tooltip background;
42 * Drawing of separator lines after the header and/or before the footer;
43 * Rounded corners and shadows below the tooltip window (Windows XP only);
44 * Fade in/fade out effects (Windows XP only);
45 * User-settable delays for the delay after which the tooltip appears and the delay
46 after which the tooltip is destroyed.
47
48 And a lot more. Check the demo for an almost complete review of the functionalities.
49
50
51 Supported Platforms
52 ===================
53
54 SuperToolTip has been tested on the following platforms:
55 * Windows (Windows XP).
56
57
58 Latest Revision: Andrea Gavana @ 07 October 2008, 22.00 GMT
59 Version 0.1
60
61 """
62
63 import wx
64 import webbrowser
65
66 # Let's see if we can add few nice shadows to our tooltips (Windows only)
67 _libimported = None
68
69 if wx.Platform == "__WXMSW__":
70 osVersion = wx.GetOsVersion()
71 # Shadows behind menus are supported only in XP
72 if osVersion[1] == 5 and osVersion[2] == 1:
73 try:
74 # Try Mark Hammond's win32all extensions
75 import win32api
76 import win32con
77 import win32gui
78 import winxpgui
79 _libimported = "MH"
80 except ImportError:
81 _libimported = None
82 else:
83 _libimported = None
84
85
86 # Define a bunch of predefined colour schemes...
87
88 _colorSchemes = {"Beige": (wx.Colour(255,255,255), wx.Colour(242,242,223), wx.Colour(198,195,160), wx.Colour(0,0,0)),
89 "Blue": (wx.Colour(255,255,255), wx.Colour(202,220,246), wx.Colour(150,180,222), wx.Colour(0,0,0)),
90 "Blue 2": (wx.Colour(255,255,255), wx.Colour(228,236,248), wx.Colour(198,214,235), wx.Colour(0,0,0)),
91 "Blue 3": (wx.Colour(255,255,255), wx.Colour(213,233,243), wx.Colour(151,195,216), wx.Colour(0,0,0)),
92 "Blue 4": (wx.Colour(255,255,255), wx.Colour(227,235,255), wx.Colour(102,153,255), wx.Colour(0,0,0)),
93 "Blue Glass": (wx.Colour(182,226,253), wx.Colour(137,185,232), wx.Colour(188,244,253), wx.Colour(0,0,0)),
94 "Blue Glass 2": (wx.Colour(192,236,255), wx.Colour(147,195,242), wx.Colour(198,254,255), wx.Colour(0,0,0)),
95 "Blue Glass 3": (wx.Colour(212,255,255), wx.Colour(167,215,255), wx.Colour(218,255,255), wx.Colour(0,0,0)),
96 "Blue Inverted": (wx.Colour(117,160,222), wx.Colour(167,210,240), wx.Colour(233,243,255), wx.Colour(0,0,0)),
97 "Blue Shift": (wx.Colour(124,178,190), wx.Colour(13,122,153), wx.Colour(0,89,116), wx.Colour(255,255,255)),
98 "CodeProject": (wx.Colour(255,250,172), wx.Colour(255,207,157), wx.Colour(255,153,0), wx.Colour(0,0,0)),
99 "Dark Gray": (wx.Colour(195,195,195), wx.Colour(168,168,168), wx.Colour(134,134,134), wx.Colour(255,255,255)),
100 "Deep Purple": (wx.Colour(131,128,164), wx.Colour(112,110,143), wx.Colour(90,88,117), wx.Colour(255,255,255)),
101 "Electric Blue": (wx.Colour(224,233,255), wx.Colour(135,146,251), wx.Colour(99,109,233), wx.Colour(0,0,0)),
102 "Firefox": (wx.Colour(255,254,207), wx.Colour(254,248,125), wx.Colour(225,119,24), wx.Colour(0,0,0)),
103 "Gold": (wx.Colour(255,202,0), wx.Colour(255,202,0), wx.Colour(255,202,0), wx.Colour(0,0,0)),
104 "Gold Shift": (wx.Colour(178,170,107), wx.Colour(202,180,32), wx.Colour(162,139,1), wx.Colour(255,255,255)),
105 "Gray": (wx.Colour(255,255,255), wx.Colour(228,228,228), wx.Colour(194,194,194), wx.Colour(0,0,0)),
106 "Green": (wx.Colour(234,241,223), wx.Colour(211,224,180), wx.Colour(182,200,150), wx.Colour(0,0,0)),
107 "Green Shift": (wx.Colour(129,184,129), wx.Colour(13,185,15), wx.Colour(1,125,1), wx.Colour(255,255,255)),
108 "Light Green": (wx.Colour(174,251,171), wx.Colour(145,221,146), wx.Colour(90,176,89), wx.Colour(0,0,0)),
109 "NASA Blue": (wx.Colour(0,91,134), wx.Colour(0,100,150), wx.Colour(0,105,160), wx.Colour(255,255,255)),
110 "Office 2007 Blue": (wx.Colour(255,255,255), wx.Colour(242,246,251), wx.Colour(202,218,239), wx.Colour(76,76,76)),
111 "Orange Shift": (wx.Colour(179,120,80), wx.Colour(183,92,19), wx.Colour(157,73,1), wx.Colour(255,255,255)),
112 "Outlook Green": (wx.Colour(236,242,208), wx.Colour(219,230,187), wx.Colour(195,210,155), wx.Colour(0,0,0)),
113 "Pale Green": (wx.Colour(249,255,248), wx.Colour(206,246,209), wx.Colour(148,225,155), wx.Colour(0,0,0)),
114 "Pink Blush": (wx.Colour(255,254,255), wx.Colour(255,231,242), wx.Colour(255,213,233), wx.Colour(0,0,0)),
115 "Pink Shift": (wx.Colour(202,135,188), wx.Colour(186,8,158), wx.Colour(146,2,116), wx.Colour(255,255,255)),
116 "Pretty Pink": (wx.Colour(255,240,249), wx.Colour(253,205,217), wx.Colour(255,150,177), wx.Colour(0,0,0)),
117 "Red": (wx.Colour(255,183,176), wx.Colour(253,157,143), wx.Colour(206,88,78), wx.Colour(0,0,0)),
118 "Red Shift": (wx.Colour(186,102,102), wx.Colour(229,23,9), wx.Colour(182,11,1), wx.Colour(255,255,255)),
119 "Silver": (wx.Colour(255,255,255), wx.Colour(242,242,246), wx.Colour(212,212,224), wx.Colour(0,0,0)),
120 "Silver 2": (wx.Colour(255,255,255), wx.Colour(242,242,248), wx.Colour(222,222,228), wx.Colour(0,0,0)),
121 "Silver Glass": (wx.Colour(158,158,158), wx.Colour(255,255,255), wx.Colour(105,105,105), wx.Colour(0,0,0)),
122 "Silver Inverted": (wx.Colour(161,160,186), wx.Colour(199,201,213), wx.Colour(255,255,255), wx.Colour(0,0,0)),
123 "Silver Inverted 2": (wx.Colour(181,180,206), wx.Colour(219,221,233), wx.Colour(255,255,255), wx.Colour(0,0,0)),
124 "Soylent Green": (wx.Colour(134,211,131), wx.Colour(105,181,106), wx.Colour(50,136,49), wx.Colour(255,255,255)),
125 "Spring Green": (wx.Colour(154,231,151), wx.Colour(125,201,126), wx.Colour(70,156,69), wx.Colour(255,255,255)),
126 "Too Blue": (wx.Colour(255,255,255), wx.Colour(225,235,244), wx.Colour(188,209,226), wx.Colour(0,0,0)),
127 "Totally Green": (wx.Colour(190,230,160), wx.Colour(190,230,160), wx.Colour(190,230,160), wx.Colour(0,0,0)),
128 "XP Blue": (wx.Colour(119,185,236), wx.Colour(81,144,223), wx.Colour(36,76,171), wx.Colour(255,255,255)),
129 "Yellow": (wx.Colour(255,255,220), wx.Colour(255,231,161), wx.Colour(254,218,108), wx.Colour(0,0,0))}
130
131
132
134 """ Returns the predefined styles keywords. """
135
136 schemes = _colorSchemes.keys()
137 schemes.sort()
138 return schemes
139
140
142 """
143 Makes a font bold. Utility method.
144
145 @param font: the font to be made bold.
146 """
147
148 newFont = wx.Font(font.GetPointSize(), font.GetFamily(), font.GetStyle(),
149 wx.BOLD, font.GetUnderlined(), font.GetFaceName())
150
151 return newFont
152
153
155 """
156 Extract the link from an hyperlink line.
157
158 @param line: the line of text to be processed.
159 """
160
161 line = line[4:]
162 indxStart = line.find("{")
163 indxEnd = line.find("}")
164 hl = line[indxStart+1:indxEnd].strip()
165 line = line[0:indxStart].strip()
166
167 return line, hl
168
169
171 """ Base class for the different Windows and Mac implementation. """
172
174 """
175 Default class constructor.
176
177 @param parent: the L{SuperToolTip} parent widget;
178 @param classParent: the L{SuperToolTip} class object.
179 """
180
181 self._spacing = 6
182 self._wasOnLink = False
183 self._hyperlinkRect, self._hyperlinkWeb = [], []
184
185 self._classParent = classParent
186 self._alphaTimer = wx.Timer(self, wx.ID_ANY)
187
188 # Initialize the fonts
189 self.InitFont()
190
191 # Bind the events
192 self.Bind(wx.EVT_PAINT, self.OnPaint)
193 self.Bind(wx.EVT_SIZE, self.OnSize)
194 self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground)
195 self.Bind(wx.EVT_MOTION, self.OnMouseMotion)
196 self.Bind(wx.EVT_TIMER, self.AlphaCycle)
197 self.Bind(wx.EVT_KILL_FOCUS, self.OnDestroy)
198 self.Bind(wx.EVT_LEFT_DOWN, self.OnDestroy)
199 self.Bind(wx.EVT_LEFT_DCLICK, self.OnDestroy)
200
201
203 """ Initalizes the fonts for L{SuperToolTip}. """
204
205 self._messageFont = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
206 self._headerFont = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
207 self._headerFont.SetWeight(wx.BOLD)
208 self._footerFont = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
209 self._footerFont.SetWeight(wx.BOLD)
210 self._hyperlinkFont = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
211 self._hyperlinkFont.SetWeight(wx.BOLD)
212 self._hyperlinkFont.SetUnderlined(True)
213
214
216 """ Handles the wx.EVT_PAINT event for L{SuperToolTip}. """
217
218 # Go with double buffering...
219 dc = wx.BufferedPaintDC(self)
220
221 frameRect = self.GetClientRect()
222 x, y, width, height = frameRect
223 # Store the rects for the hyperlink lines
224 self._hyperlinkRect, self._hyperlinkWeb = [], []
225 classParent = self._classParent
226
227 # Retrieve the colours for the blended triple-gradient background
228 topColour, middleColour, bottomColour = classParent.GetTopGradientColour(), \
229 classParent.GetMiddleGradientColour(), \
230 classParent.GetBottomGradientColour()
231
232 # Get the user options for header, bitmaps etc...
233 drawHeader, drawFooter = classParent.GetDrawHeaderLine(), classParent.GetDrawFooterLine()
234 topRect = wx.Rect(frameRect.x, frameRect.y, frameRect.width, frameRect.height/2)
235 bottomRect = wx.Rect(frameRect.x, frameRect.y+frameRect.height/2, frameRect.width, frameRect.height/2+1)
236 # Fill the triple-gradient
237 dc.GradientFillLinear(topRect, topColour, middleColour, wx.SOUTH)
238 dc.GradientFillLinear(bottomRect, middleColour, bottomColour, wx.SOUTH)
239
240 header, headerBmp = classParent.GetHeader(), classParent.GetHeaderBitmap()
241 xPos, yPos = self._spacing, 0
242 bmpXPos = bmpYPos = 0
243 bmpHeight = textHeight = bmpWidth = 0
244
245 if headerBmp and headerBmp.IsOk():
246 # We got the header bitmap
247 bmpHeight, bmpWidth = headerBmp.GetHeight(), headerBmp.GetWidth()
248 bmpXPos = self._spacing
249
250 if header:
251 # We got the header text
252 dc.SetFont(self._headerFont)
253 textWidth, textHeight = dc.GetTextExtent(header)
254
255 # Calculate the header height
256 height = max(textHeight, bmpHeight)
257 if header:
258 dc.DrawText(header, bmpXPos+bmpWidth+self._spacing, (height-textHeight+self._spacing)/2)
259 if headerBmp and headerBmp.IsOk():
260 dc.DrawBitmap(headerBmp, bmpXPos, (height-bmpHeight+self._spacing)/2)
261
262 if header or (headerBmp and headerBmp.IsOk()):
263 yPos += height
264 if drawHeader:
265 # Draw the separator line after the header
266 dc.SetPen(wx.GREY_PEN)
267 dc.DrawLine(self._spacing, yPos+self._spacing, width-self._spacing, yPos+self._spacing)
268
269 # Get the big body image (if any)
270 embeddedImage = classParent.GetBodyImage()
271 bmpWidth = bmpHeight = -1
272 if embeddedImage and embeddedImage.IsOk():
273 bmpWidth, bmpHeight = embeddedImage.GetWidth(), embeddedImage.GetHeight()
274
275 # A bunch of calculations to draw the main body message
276 messageHeight = 0
277 textSpacing = (bmpWidth > 0 and [3*self._spacing] or [2*self._spacing])[0]
278 lines = classParent.GetMessage().split("\n")
279 yText = yPos
280 normalText = wx.SystemSettings_GetColour(wx.SYS_COLOUR_MENUTEXT)
281 hyperLinkText = wx.BLUE
282
283 for indx, line in enumerate(lines):
284 # Loop over all the lines in the message
285 isLink = False
286 dc.SetTextForeground(normalText)
287 if line.startswith("</b>"): # is a bold line
288 line = line[4:]
289 font = MakeBold(self._messageFont)
290 dc.SetFont(font)
291 elif line.startswith("</l>"): # is a link
292 dc.SetFont(self._hyperlinkFont)
293 isLink = True
294 line, hl = ExtractLink(line)
295 dc.SetTextForeground(hyperLinkText)
296 else:
297 # Is a normal line
298 dc.SetFont(self._messageFont)
299
300 textWidth, textHeight = dc.GetTextExtent(line)
301 if textHeight == 0:
302 textWidth, textHeight = dc.GetTextExtent("a")
303
304 messageHeight += textHeight
305
306 xText = (bmpWidth > 0 and [bmpWidth+2*self._spacing] or [self._spacing])[0]
307 yText += textHeight/2+self._spacing
308
309 dc.DrawText(line, xText, yText)
310 if isLink:
311 # Store the hyperlink rectangle and link
312 self._hyperlinkRect.append(wx.Rect(xText, yText, textWidth, textHeight))
313 self._hyperlinkWeb.append(hl)
314
315 if indx == 0:
316 messagePos = yText
317
318 toAdd = 0
319 if bmpHeight > textHeight:
320 yPos += 2*self._spacing + bmpHeight
321 toAdd = self._spacing
322 else:
323 yPos += messageHeight + 2*self._spacing
324
325 yText = max(messageHeight, bmpHeight+2*self._spacing)
326 if embeddedImage and embeddedImage.IsOk():
327 # Draw the main body image
328 dc.DrawBitmap(embeddedImage, self._spacing, messagePos)
329
330 footer, footerBmp = classParent.GetFooter(), classParent.GetFooterBitmap()
331 bmpHeight = bmpWidth = textHeight = textWidth = 0
332 bmpXPos = bmpYPos = 0
333
334 if footerBmp and footerBmp.IsOk():
335 # Got the footer bitmap
336 bmpHeight, bmpWidth = footerBmp.GetHeight(), footerBmp.GetWidth()
337 bmpXPos = self._spacing
338
339 if footer:
340 # Got the footer text
341 dc.SetFont(self._footerFont)
342 textWidth, textHeight = dc.GetTextExtent(footer)
343
344 if textHeight or bmpHeight:
345 if drawFooter:
346 # Draw the separator line before the footer
347 dc.SetPen(wx.GREY_PEN)
348 dc.DrawLine(self._spacing, yPos-self._spacing/2+toAdd, width-self._spacing, yPos-self._spacing/2+toAdd)
349
350 # Draw the footer and footer bitmap (if any)
351 dc.SetTextForeground(normalText)
352 height = max(textHeight, bmpHeight)
353 yPos += toAdd
354 if footer:
355 dc.DrawText(footer, bmpXPos+bmpWidth+self._spacing, yPos + (height-textHeight+self._spacing)/2)
356 if footerBmp and footerBmp.IsOk():
357 dc.DrawBitmap(footerBmp, bmpXPos, yPos + (height-bmpHeight+self._spacing)/2)
358
359
361 """ Handles the wx.EVT_ERASE_BACKGROUND event for L{SuperToolTip}. """
362
363 # This is intentionally empty to reduce flicker
364 pass
365
366
368 """ Handles the wx.EVT_SIZE event for L{SuperToolTip}. """
369
370 self.Refresh()
371 event.Skip()
372
373
375 """ Handles the wx.EVT_MOTION event for L{SuperToolTip}. """
376
377 x, y = event.GetPosition()
378 for rect in self._hyperlinkRect:
379 if rect.Contains((x, y)):
380 # We are over one hyperlink...
381 self.SetCursor(wx.StockCursor(wx.CURSOR_HAND))
382 self._wasOnLink = True
383 return
384
385 if self._wasOnLink:
386 # Restore the normal cursor
387 self._wasOnLink = False
388 self.SetCursor(wx.NullCursor)
389
390
392 """
393 Handles the wx.EVT_LEFT_DOWN, wx.EVT_LEFT_DCLICK and wx.EVT_KILL_FOCUS
394 events for L{SuperToolTip}. All these events destroy the L{SuperToolTip},
395 unless the user clicked on one hyperlink.
396 """
397
398 if not isinstance(event, wx.MouseEvent):
399 # We haven't clicked a link
400 self.Destroy()
401 return
402
403 x, y = event.GetPosition()
404 for indx, rect in enumerate(self._hyperlinkRect):
405 if rect.Contains((x, y)):
406 # Run the webbrowser with the clicked link
407 webbrowser.open_new_tab(self._hyperlinkWeb[indx])
408 return
409
410 if self._classParent.GetUseFade():
411 # Fade out...
412 self.StartAlpha(False)
413 else:
414 self.Destroy()
415
416
418 """
419 Start the timer which set the alpha channel for L{SuperToolTip}.
420
421 @param isShow: whether L{SuperToolTip} is being shown or deleted.
422 """
423
424 if self._alphaTimer.IsRunning():
425 return
426
427 # Calculate starting alpha value and its step
428 self.amount = (isShow and [0] or [255])[0]
429 self.delta = (isShow and [5] or [-5])[0]
430 # Start the timer
431 self._alphaTimer.Start(30)
432
433
435 """
436 Sets the L{SuperToolTip} font globally.
437
438 @param font: the font to set.
439 """
440
441 wx.PopupWindow.SetFont(self, font)
442 self.InitFont()
443 self.Invalidate()
444
445
447 """ Invalidate L{SuperToolTip} size and repaint it. """
448
449 if not self._classParent.GetMessage():
450 # No message yet...
451 return
452
453 self.CalculateBestSize()
454 self.Refresh()
455
456
458 """
459 Adds a shadow under the window (Windows XP only).
460
461 @param drop: whether to drop a shadow or not.
462 """
463
464 if not _libimported:
465 # No Mark Hammond's win32all extension
466 return
467
468 if wx.Platform != "__WXMSW__":
469 # This works only on Windows XP
470 return
471
472 hwnd = self.GetHandle()
473
474 # Create a rounded rectangle region
475 size = self.GetSize()
476 if drop:
477 rgn = win32gui.CreateRoundRectRgn(0, 0, size.x, size.y, 9, 9)
478 win32gui.SetWindowRgn(hwnd, rgn, True)
479
480 CS_DROPSHADOW = 0x00020000
481 # Load the user32 library
482 if not hasattr(self, "_winlib"):
483 self._winlib = win32api.LoadLibrary("user32")
484
485 csstyle = win32api.GetWindowLong(hwnd, win32con.GCL_STYLE)
486 if drop:
487 if csstyle & CS_DROPSHADOW:
488 return
489 else:
490 csstyle |= CS_DROPSHADOW #Nothing to be done
491 else:
492 csstyle &= ~CS_DROPSHADOW
493
494 # Drop the shadow underneath the window
495 GCL_STYLE= -26
496 cstyle= win32gui.GetClassLong(hwnd, GCL_STYLE)
497 if drop:
498 if cstyle & CS_DROPSHADOW == 0:
499 win32api.SetClassLong(hwnd, GCL_STYLE, cstyle | CS_DROPSHADOW)
500 else:
501 win32api.SetClassLong(hwnd, GCL_STYLE, cstyle &~ CS_DROPSHADOW)
502
503
505 """ Handles the wx.EVT_TIMER event for L{SuperToolTip}. """
506
507 # Increase (or decrease) the alpha channel
508 self.amount += self.delta
509
510 if self.amount > 255 or self.amount < 0:
511 # We're done, stop the timer
512 self._alphaTimer.Stop()
513 if self.amount < 0:
514 # Destroy the SuperToolTip, we are fading out
515 self.Destroy()
516 return
517
518 # Make the SuperToolTip more or less transparent
519 self.MakeWindowTransparent(self.amount)
520 if not self.IsShown():
521 self.Show()
522
523
525 """
526 Makes the L{SuperToolTip} window transparent.
527
528 @param amount: the alpha channel value.
529 """
530
531 if not _libimported:
532 # No way, only Windows XP with Mark Hammond's win32all
533 return
534
535 # this API call is not in all SDKs, only the newer ones, so
536 # we will runtime bind this
537 if wx.Platform != "__WXMSW__":
538 return
539
540 hwnd = self.GetHandle()
541
542 if not hasattr(self, "_winlib"):
543 self._winlib = win32api.LoadLibrary("user32")
544
545 pSetLayeredWindowAttributes = win32api.GetProcAddress(self._winlib,
546 "SetLayeredWindowAttributes")
547
548 if pSetLayeredWindowAttributes == None:
549 return
550
551 exstyle = win32api.GetWindowLong(hwnd, win32con.GWL_EXSTYLE)
552 if 0 == (exstyle & 0x80000):
553 win32api.SetWindowLong(hwnd, win32con.GWL_EXSTYLE, exstyle | 0x80000)
554
555 winxpgui.SetLayeredWindowAttributes(hwnd, 0, amount, 2)
556
557
559 """ Calculates the L{SuperToolTip} window best size. """
560
561 # See the OnPaint method for explanations...
562 maxWidth = maxHeight = 0
563 dc = wx.ClientDC(self)
564
565 classParent = self._classParent
566 header, headerBmp = classParent.GetHeader(), classParent.GetHeaderBitmap()
567
568 textHeight, bmpHeight = 0, 0
569 if header:
570 dc.SetFont(self._headerFont)
571 textWidth, textHeight = dc.GetTextExtent(header)
572 maxWidth = max(maxWidth, textWidth + 2*self._spacing)
573 maxHeight += self._spacing/2
574 if headerBmp and headerBmp.IsOk():
575 maxWidth += headerBmp.GetWidth() + 2*self._spacing
576 bmpHeight = headerBmp.GetHeight()
577 if not header:
578 maxHeight += self._spacing/2
579
580 maxHeight += max(textHeight, bmpHeight)
581 if textHeight or bmpHeight:
582 maxHeight += self._spacing/2
583
584 # See the OnPaint method for explanations...
585 bmpWidth = bmpHeight = -1
586 embeddedImage = classParent.GetBodyImage()
587 if embeddedImage and embeddedImage.IsOk():
588 bmpWidth, bmpHeight = embeddedImage.GetWidth(), embeddedImage.GetHeight()
589
590 messageHeight = 0
591 textSpacing = (bmpWidth and [3*self._spacing] or [2*self._spacing])[0]
592 lines = classParent.GetMessage().split("\n")
593
594 for line in lines:
595 if line.startswith("</b>"): # is a bold line
596 font = MakeBold(self._messageFont)
597 dc.SetFont(font)
598 line = line[4:]
599 elif line.startswith("</l>"): # is a link
600 dc.SetFont(self._hyperlinkFont)
601 line, hl = ExtractLink(line)
602 else:
603 dc.SetFont(self._messageFont)
604
605 textWidth, textHeight = dc.GetTextExtent(line)
606 if textHeight == 0:
607 textWidth, textHeight = dc.GetTextExtent("a")
608
609 maxWidth = max(maxWidth, textWidth + textSpacing + bmpWidth)
610 messageHeight += textHeight
611
612 # See the OnPaint method for explanations...
613 messageHeight = max(messageHeight, bmpHeight)
614 maxHeight += messageHeight
615 toAdd = 0
616 if bmpHeight > textHeight:
617 maxHeight += 2*self._spacing
618 toAdd = self._spacing
619 else:
620 maxHeight += 2*self._spacing
621
622 footer, footerBmp = classParent.GetFooter(), classParent.GetFooterBitmap()
623 textHeight, bmpHeight = 0, 0
624
625 # See the OnPaint method for explanations...
626 if footer:
627 dc.SetFont(self._footerFont)
628 textWidth, textHeight = dc.GetTextExtent(footer)
629 maxWidth = max(maxWidth, textWidth + 2*self._spacing)
630 maxHeight += self._spacing/2
631
632 if footerBmp and footerBmp.IsOk():
633 bmpWidth, bmpHeight = footerBmp.GetWidth(), footerBmp.GetHeight()
634 maxWidth = max(maxWidth, textWidth + 3*self._spacing + bmpWidth)
635 if not footer:
636 maxHeight += self._spacing/2
637
638 if textHeight or bmpHeight:
639 maxHeight += self._spacing/2 + max(textHeight, bmpHeight)
640
641 maxHeight += toAdd
642 self.SetSize((maxWidth, maxHeight))
643
644
645 # Handle Mac and Windows/GTK differences...
646
647 if wx.Platform == "__WXMAC__":
648
650 """ Popup window that works on wxMac. """
651
653 """
654 Default class constructor.
655
656 @param parent: the L{SuperToolTip} widget parent;
657 @param classParent: the L{SuperToolTip} object parent.
658 """
659
660 wx.Frame.__init__(self, parent, style=wx.NO_BORDER|wx.FRAME_FLOAT_ON_PARENT|wx.FRAME_NO_TASKBAR|wx.POPUP_WINDOW)
661 # Call the base class
662 ToolTipWindowBase.__init__(self, parent, classParent)
663
664 else:
665
667 """
668 A simple wx.PopupWindow that holds fancy tooltips.
669 Not available on Mac as wx.PopupWindow is not implemented.
670 """
671
673 """
674 Default class constructor.
675
676 @param parent: the L{SuperToolTip} parent;
677 @param classParent: the L{SuperToolTip} object parent.
678 """
679
680 wx.PopupWindow.__init__(self, parent)
681 # Call the base class
682 ToolTipWindowBase.__init__(self, parent, classParent)
683
684
686 """
687 The main class for L{SuperToolTip}, which holds all the methods
688 and setters/getters available to the user.
689 """
690
691 - def __init__(self, message, bodyImage=wx.NullBitmap, header="", headerBmp=wx.NullBitmap,
692 footer="", footerBmp=wx.NullBitmap):
693 """
694 Default class constructor.
695
696 @param message: the main message in L{SuperToolTip} body;
697 @param bodyImage: the image in the L{SuperToolTip} body;
698 @param header: the header text;
699 @param headerBmp: the header bitmap;
700 @param footer: the footer text;
701 @param footerBmp: the footer bitmap.
702 """
703
704 self._superToolTip = None
705
706 # Set all the initial options
707 self.SetMessage(message)
708 self.SetBodyImage(bodyImage)
709 self.SetHeader(header)
710 self.SetHeaderBitmap(headerBmp)
711 self.SetFooter(footer)
712 self.SetFooterBitmap(footerBmp)
713 self._dropShadow = False
714 self._useFade = False
715
716 # Get the running applications
717 self._runningApp = wx.GetApp()
718 self._runningApp.__superToolTip = True
719
720 # Build a couple of timers...
721 self._startTimer = wx.PyTimer(self.OnStartTimer)
722 self._endTimer = wx.PyTimer(self.OnEndTimer)
723
724 self.SetStartDelay()
725 self.SetEndDelay()
726
727
729 """
730 Sets the target window for L{SuperToolTip}.
731
732 @param widget: the widget to which L{SuperToolTip} is associated.
733 """
734
735 self._widget = widget
736
737 self._widget.Bind(wx.EVT_ENTER_WINDOW, self.OnWidgetEnter)
738 self._widget.Bind(wx.EVT_LEAVE_WINDOW, self.OnWidgetLeave)
739
740
742 """ Returns the target window for L{SuperToolTip}. """
743
744 if not hasattr(self, "_widget"):
745 raise Exception("\nError: the widget target for L{SuperToolTip} has not been set.")
746
747 return self._widget
748
749
751 """
752 Sets the time delay (in seconds) after which the L{SuperToolTip} is created.
753
754 @param delay: the delay in seconds.
755 """
756
757 self._startDelayTime = float(delay)
758
759
761 """ Returns the tim delay (in seconds) after which the L{SuperToolTip} is created."""
762
763 return self._startDelayTime
764
765
767 """
768 Sets the delay time (in seconds) after which the L{SuperToolTip} is destroyed.
769
770 @param delay: the delay in seconds.
771 """
772
773 self._endDelayTime = float(delay)
774
775
777 """ Returns the delay time (in seconds) after which the L{SuperToolTip} is destroyed."""
778
779 return self._endDelayTime
780
781
783 """Starts the L{SuperToolTip} timer for creation, handles the wx.EVT_ENTER_WINDOW event."""
784
785 if self._superToolTip:
786 # Not yet created
787 return
788
789 if not self._runningApp.__superToolTip:
790 # The running app doesn't want tooltips...
791 return
792
793 if self._startTimer.IsRunning():
794 # We are already running
795 event.Skip()
796 return
797
798 self._startTimer.Start(self._startDelayTime*1000)
799 event.Skip()
800
801
803 """ Handles the wx.EVT_LEAVE_WINDOW for the target widgets. """
804
805 pos = wx.GetMousePosition()
806 realPos = self._widget.ScreenToClient(pos)
807 rect = self._widget.GetClientRect()
808
809 if rect.Contains(realPos):
810 # We get fake leave events...
811 event.Skip()
812 return
813
814 if self._superToolTip:
815 if self.GetUseFade():
816 # Fade out...
817 self._superToolTip.StartAlpha(False)
818 else:
819 self._superToolTip.Destroy()
820
821 self._startTimer.Stop()
822 self._endTimer.Stop()
823
824 event.Skip()
825
826
828 """ The creation time has expired, create the L{SuperToolTip}. """
829
830 tip = ToolTipWindow(self._widget, self)
831 self._superToolTip = tip
832 self._superToolTip.CalculateBestSize()
833 self._superToolTip.SetPosition(wx.GetMousePosition())
834 self._superToolTip.DropShadow(self.GetDropShadow())
835
836 if self.GetUseFade():
837 self._superToolTip.StartAlpha(True)
838 else:
839 self._superToolTip.Show()
840
841 self._startTimer.Stop()
842 self._endTimer.Start(self._endDelayTime*1000)
843
844
846 """ The show time for L{SuperToolTip} has expired, destroy the L{SuperToolTip}. """
847
848 if self._superToolTip:
849 if self.GetUseFade():
850 self._superToolTip.StartAlpha(False)
851 else:
852 self._superToolTip.Destroy()
853
854 self._endTimer.Stop()
855
856
858 """ Handles the L{SuperToolTip} target destruction. """
859
860 if self._superToolTip:
861 # Unbind the events!
862 self._widget.Unbind(wx.EVT_LEAVE_WINDOW)
863 self._widget.Unbind(wx.EVT_ENTER_WINDOW)
864
865 self._superToolTip.Destroy()
866 del self._superToolTip
867 self._superToolTip = None
868
869
871 """
872 Sets the header bitmap for L{SuperToolTip}.
873
874 @param bmp: the bitmap to use.
875 """
876
877 self._headerBmp = bmp
878 if self._superToolTip:
879 self._superToolTip.Invalidate()
880
881
886
887
889 """
890 Sets the header text.
891
892 @param header: the header text to display.
893 """
894
895 self._header = header
896 if self._superToolTip:
897 self._superToolTip.Invalidate()
898
899
904
905
907 """
908 Whether to draw a separator line after the header or not.
909
910 @param draw: bool value.
911 """
912
913 self._topLine = draw
914 if self._superToolTip:
915 self._superToolTip.Refresh()
916
917
919 """ Returns whether the separator line after the header is drawn or not. """
920
921 return self._topLine
922
923
925 """
926 Sets the main body bitmap for L{SuperToolTip}.
927
928 @param bmp: the bitmap to use.
929 """
930
931 self._embeddedImage = bmp
932 if self._superToolTip:
933 self._superToolTip.Invalidate()
934
935
937 """ Returns the main body bitmap used in L{SuperToolTip}. """
938
939 return self._embeddedImage
940
941
952
953
958
959
970
971
976
977
988
989
994
995
997 """
998 Sets the main body message for L{SuperToolTip}.
999
1000 @param message: the message to display in the body.
1001 """
1002
1003 self._message = message
1004 if self._superToolTip:
1005 self._superToolTip.Invalidate()
1006
1007
1012
1013
1015 """
1016 Sets the top gradient colour for L{SuperToolTip}.
1017
1018 @param colour: the colour to use as top colour.
1019 """
1020
1021 self._topColour = colour
1022 if self._superToolTip:
1023 self._superToolTip.Refresh()
1024
1025
1027 """
1028 Sets the middle gradient colour for L{SuperToolTip}.
1029
1030 @param colour: the colour to use as middle colour.
1031 """
1032
1033 self._middleColour = colour
1034 if self._superToolTip:
1035 self._superToolTip.Refresh()
1036
1037
1039 """
1040 Sets the bottom gradient colour for L{SuperToolTip}.
1041
1042 @param colour: the colour to use as bottom colour.
1043 """
1044
1045 self._bottomColour = colour
1046 if self._superToolTip:
1047 self._superToolTip.Refresh()
1048
1049
1051 """
1052 Sets the text colour for L{SuperToolTip}.
1053
1054 @param colour: the colour to use as text colour.
1055 """
1056
1057 self._textColour = colour
1058 if self._superToolTip:
1059 self._superToolTip.Refresh()
1060
1061
1066
1067
1072
1073
1078
1079
1084
1085
1086 SetTopGradientColor = SetTopGradientColour
1087 SetMiddleGradientColor = SetMiddleGradientColour
1088 SetBottomGradientColor = SetBottomGradientColour
1089 GetTopGradientColor = GetTopGradientColour
1090 GetMiddleGradientColor = GetMiddleGradientColour
1091 GetBottomGradientColor = GetBottomGradientColour
1092 SetTextColor = SetTextColour
1093 GetTextColor = GetTextColour
1094
1095
1097 """
1098 Sets the font for the main body message.
1099
1100 @param font: the font to use for the main body message.
1101 """
1102
1103 self._messageFont = font
1104 if self._superToolTip:
1105 self._superToolTip.Invalidate()
1106
1107
1109 """
1110 Sets the font for the header text.
1111
1112 @param font: the font to use for the header text.
1113 """
1114
1115 self._headerFont = font
1116 if self._superToolTip:
1117 self._superToolTip.Invalidate()
1118
1119
1130
1131
1136
1137
1142
1143
1148
1149
1151 """
1152 Whether to draw a shadow below L{SuperToolTip} or not.
1153
1154 @param drop: boolean value.
1155 @note: this functionality is available only in Windows XP
1156 with Mark Hammond win32all extensions installed.
1157 """
1158
1159 self._dropShadow = drop
1160 if self._superToolTip:
1161 self._superToolTip.Invalidate()
1162
1163
1165 """
1166 Returns whether a shadow below L{SuperToolTip} is drawn or not.
1167
1168 @note: this functionality is available only in Windows XP
1169 with Mark Hammond win32all extensions installed.
1170 """
1171
1172 return self._dropShadow
1173
1174
1176 """
1177 Whether to use a fade in/fade out effect or not.
1178
1179 @param fade: boolean value.
1180 @note: this functionality is available only in Windows XP
1181 with Mark Hammond win32all extensions installed.
1182 """
1183
1184 self._useFade = fade
1185
1186
1188 """
1189 Returns whether a fade in/fade out effect is used or not.
1190
1191 @note: this functionality is available only in Windows XP
1192 with Mark Hammond win32all extensions installed.
1193 """
1194
1195 return self._useFade
1196
1197
1199 """
1200 Applies none of the predefined styles.
1201
1202 @param style: one of the predefined styles available at the
1203 beginning of the module.
1204 """
1205
1206 if style not in _colorSchemes:
1207 raise Exception("Invalid style '%s' selected"%style)
1208
1209 top, middle, bottom, text = _colorSchemes[style]
1210 self._topColour = top
1211 self._middleColour = middle
1212 self._bottomColour = bottom
1213 self._textColour = text
1214
1215 if self._superToolTip:
1216 self._superToolTip.Refresh()
1217
1218
1220 """
1221 Globally (application-wide) enables/disables L{SuperToolTip}.
1222
1223 @param enable: whether to enable or disable L{SuperToolTip}.
1224 """
1225
1226 wx.GetApp().__superToolTip = enable
1227 if not enable and self._superToolTip:
1228 self._superToolTip.Destroy()
1229 self._superToolTip = None
1230 del self._superToolTip
1231
| Home | Trees | Indices | Help |
|---|
| Generated by Epydoc 3.0.1 on Wed Oct 08 13:53:55 2008 | http://epydoc.sourceforge.net |