]> git.saurik.com Git - wxWidgets.git/blob - wxPython/wx/lib/hyperlink.py
generate middle click events (backport from HEAD of the patch 1521314)
[wxWidgets.git] / wxPython / wx / lib / hyperlink.py
1 # --------------------------------------------------------------------------- #
2 # HYPERLINKSCTRL wxPython IMPLEMENTATION
3 # Ported From Angelo Mandato C++ Code By:
4 #
5 # Andrea Gavana, @ 27 Mar 2005
6 # Latest Revision: 05 Nov 2005, 22.30 CET
7 #
8 #
9 # Original Web Site (For The C++ Code):
10 #
11 # http://www.spaceblue.com/codedetail.php?CodeID=7
12 #
13 #
14 # Thanks to E. A. Tacao for his nice suggestions and improvements of the code.
15 #
16 # For all kind of problems, requests of enhancements and bug reports, please
17 # write to me at:
18 #
19 # andrea.gavana@agip.it
20 # andrea_gavan@tin.it
21 #
22 # Or, obviously, to the wxPython mailing list!!!
23 #
24 #
25 # End Of Comments
26 # --------------------------------------------------------------------------- #
27
28 """
29 `HyperLinkCtrl` is a control for wxPython that acts like a hyper link
30 in a typical browser. Latest features include the ability to capture
31 your own Left, Middle, and Right click events to perform your own
32 custom event handling and ability to open link in a new or current
33 browser window.
34
35 Special thanks to Robin Dunn for the event binder for the 3 mouse buttons.
36
37
38 Latest Revision: Andrea Gavana @ 05 Nov 2005, 22.30 CET
39
40 """
41
42 import wx
43 from wx.lib.stattext import GenStaticText as StaticText
44
45 # Import the useful webbrowser module for platform-independent results
46 import webbrowser
47
48 # Set no delay time to open the web page
49 webbrowser.PROCESS_CREATION_DELAY = 0
50
51 # To show a popup that copies the hyperlinks on the clipboard
52 wxHYPERLINKS_POPUP_COPY = 1000
53
54
55 #-----------------------------------#
56 # HyperLinksEvents
57 #-----------------------------------#
58
59 # wxEVT_HYPERLINK_LEFT: Respond To A Left Mouse Button Event
60 # wxEVT_HYPERLINK_MIDDLE: Respond To A Middle Mouse Button Event
61 # wxEVT_HYPERLINK_RIGHT: Respond To A Right Mouse Button Event
62
63 wxEVT_HYPERLINK_LEFT = wx.NewEventType()
64 wxEVT_HYPERLINK_MIDDLE = wx.NewEventType()
65 wxEVT_HYPERLINK_RIGHT = wx.NewEventType()
66
67 EVT_HYPERLINK_LEFT = wx.PyEventBinder(wxEVT_HYPERLINK_LEFT, 1)
68 EVT_HYPERLINK_MIDDLE = wx.PyEventBinder(wxEVT_HYPERLINK_MIDDLE, 1)
69 EVT_HYPERLINK_RIGHT = wx.PyEventBinder(wxEVT_HYPERLINK_RIGHT, 1)
70
71
72 # ------------------------------------------------------------
73 # This class implements the event listener for the hyperlinks
74 # ------------------------------------------------------------
75
76 class HyperLinkEvent(wx.PyCommandEvent):
77 """
78 Event object sent in response to clicking on a `HyperLinkCtrl`.
79 """
80
81 def __init__(self, eventType, id):
82 """ Default Class Constructor. """
83 wx.PyCommandEvent.__init__(self, eventType, id)
84 self._eventType = eventType
85
86
87 def SetPosition(self, pos):
88 """ Sets Event Position """
89 self._pos = pos
90
91
92 def GetPosition(self):
93 """ Returns Event Position """
94 return self._pos
95
96
97 # -------------------------------------------------
98 # This is the main HyperLinkCtrl implementation
99 # it user the StatiText from wx.lib.stattext
100 # because of its "quasi-dynamic" behavior
101 # -------------------------------------------------
102
103 class HyperLinkCtrl(StaticText):
104 """
105 `HyperLinkCtrl` is a control for wxPython that acts like a hyper
106 link in a typical browser. Latest features include the ability to
107 capture your own Left, Middle, and Right click events to perform
108 your own custom event handling and ability to open link in a new
109 or current browser window.
110
111 Events
112 ------
113 ==================== =======================================
114 EVT_HYPERLINK_LEFT Sent when the left mouse button is
115 clicked, but only if `AutoBrowse` is set
116 to ``False``.
117 EVT_HYPERLINK_MIDDLE Sent when the middle mouse button is
118 clicked.
119 EVT_HYPERLINK_RIGHT Sent when the right mouse button is
120 clicked, but only if `DoPopup` is set
121 to ``False``.
122 ==================== =======================================
123 """
124
125 def __init__(self, parent, id=-1, label="", pos=wx.DefaultPosition,
126 size=wx.DefaultSize, style=0, name="staticText", URL=""):
127 """
128 Default class constructor.
129
130 Pass URL == "" to use the label as the url link to navigate to
131 """
132
133 StaticText.__init__(self, parent, id, label, pos, size,
134 style, name)
135
136 if URL.strip() == "":
137 self._URL = label
138 else:
139 self._URL = URL
140
141 # Set Tooltip
142 self.SetToolTip(wx.ToolTip(self._URL))
143
144 # Set default properties
145 # default: True
146 self.ReportErrors()
147
148 # default: True, True, True
149 self.SetUnderlines()
150
151 # default: blue, violet, blue
152 self.SetColours()
153
154 # default: False
155 self.SetVisited()
156
157 # default: False
158 self.EnableRollover()
159
160 # default: False
161 self.SetBold()
162
163 # default: wx.CURSOR_HAND
164 self.SetLinkCursor()
165
166 # default True
167 self.AutoBrowse()
168
169 # default True
170 self.DoPopup()
171
172 # default False
173 self.OpenInSameWindow()
174
175 # Set control properties and refresh
176 self.UpdateLink(True)
177
178 self.Bind(wx.EVT_MOUSE_EVENTS, self.OnMouseEvent)
179 self.Bind(wx.EVT_MOTION, self.OnMouseEvent)
180
181
182 def GotoURL(self, URL, ReportErrors=True, NotSameWinIfPossible=False):
183 """
184 Goto The Specified URL.
185
186 :param ReportErrors: Use True to display error dialog if an
187 error occurrs navigating to the URL.
188
189 :param NotSameWinIfPossible: Use True to attempt to open the
190 URL in new browser window.
191
192 """
193
194 logOff = wx.LogNull()
195
196 try:
197 webbrowser.open(URL, new=NotSameWinIfPossible)
198 self.SetVisited(True)
199 self.UpdateLink(True)
200
201 return True
202
203 except:
204 self.DisplayError("Unable To Launch Browser.", ReportErrors)
205 return False
206
207
208 def OnMouseEvent(self, event):
209 """ Captures mouse events for cursor, link colors and underlines. """
210
211 if event.Moving():
212 # Mouse Is Moving On The StaticText
213 # Set The Hand Cursor On The Link
214 self.SetCursor(self._CursorHand)
215
216 if self._EnableRollover:
217 fontTemp = self.GetFont()
218 fontTemp.SetUnderlined(self._RolloverUnderline)
219 if self._Bold:
220 fontTemp.SetWeight(wx.BOLD)
221
222 needRefresh = False
223
224 if self.GetFont() != fontTemp:
225 self.SetFont(fontTemp)
226 needRefresh = True
227
228 if self.GetForegroundColour() != self._LinkRolloverColor:
229 self.SetForegroundColour(self._LinkRolloverColor)
230 needRefresh = True
231
232 if needRefresh:
233 self.Refresh()
234
235 else:
236 # Restore The Original Cursor
237 self.SetCursor(wx.NullCursor)
238 if self._EnableRollover:
239 self.UpdateLink(True)
240
241 if event.LeftUp():
242 # Left Button Was Pressed
243 if self._AutoBrowse:
244 self.GotoURL(self._URL, self._ReportErrors,
245 self._NotSameWinIfPossible)
246
247 else:
248 eventOut = HyperLinkEvent(wxEVT_HYPERLINK_LEFT, self.GetId())
249 eventOut.SetEventObject(self)
250 eventOut.SetPosition(event.GetPosition())
251 self.GetEventHandler().ProcessEvent(eventOut)
252
253 self.SetVisited(True)
254
255 elif event.RightUp():
256 # Right Button Was Pressed
257 if self._DoPopup:
258 # Popups A Menu With The "Copy HyperLynks" Feature
259 menuPopUp = wx.Menu("", wx.MENU_TEAROFF)
260 menuPopUp.Append(wxHYPERLINKS_POPUP_COPY, "Copy HyperLink")
261 self.Bind(wx.EVT_MENU, self.OnPopUpCopy, id=wxHYPERLINKS_POPUP_COPY)
262 self.PopupMenu(menuPopUp, wx.Point(event.m_x, event.m_y))
263 menuPopUp.Destroy()
264 self.Unbind(wx.EVT_MENU, id=wxHYPERLINKS_POPUP_COPY)
265
266 else:
267 eventOut = HyperLinkEvent(wxEVT_HYPERLINK_RIGHT, self.GetId())
268 eventOut.SetEventObject(self)
269 eventOut.SetPosition(event.GetPosition())
270 self.GetEventHandler().ProcessEvent(eventOut)
271
272 elif event.MiddleUp():
273 # Middle Button Was Pressed
274 eventOut = HyperLinkEvent(wxEVT_HYPERLINK_MIDDLE, self.GetId())
275 eventOut.SetEventObject(self)
276 eventOut.SetPosition(event.GetPosition())
277 self.GetEventHandler().ProcessEvent(eventOut)
278
279 event.Skip()
280
281
282 def OnPopUpCopy(self, event):
283 """ Copy data from the HyperLink to the clipboard. """
284
285 wx.TheClipboard.UsePrimarySelection(False)
286 if not wx.TheClipboard.Open():
287 return
288 data = wx.TextDataObject(self._URL)
289 wx.TheClipboard.SetData(data)
290 wx.TheClipboard.Close()
291
292
293 def UpdateLink(self, OnRefresh=True):
294 """
295 Updates the link.
296
297 Changing text properties if:
298 - User Specific Setting
299 - Link Visited
300 - New Link
301
302 """
303
304 fontTemp = self.GetFont()
305
306 if self._Visited:
307 self.SetForegroundColour(self._VisitedColour)
308 fontTemp.SetUnderlined(self._VisitedUnderline)
309
310 else:
311
312 self.SetForegroundColour(self._LinkColour)
313 fontTemp.SetUnderlined(self._LinkUnderline)
314
315 if self._Bold:
316 fontTemp.SetWeight(wx.BOLD)
317
318 if self.GetFont() != fontTemp:
319 self.SetFont(fontTemp)
320 self.Refresh(OnRefresh)
321
322
323 def DisplayError(self, ErrorMessage, ReportErrors=True):
324 """
325 Displays an error message (according to ReportErrors variable)
326 in a MessageBox.
327 """
328 if ReportErrors:
329 wx.MessageBox(ErrorMessage, "HyperLinks Error", wx.OK | wx.CENTRE | wx.ICON_ERROR)
330
331
332 def SetColours(self,
333 link=wx.Colour(0, 0, 255),
334 visited=wx.Colour(79, 47, 79),
335 rollover=wx.Colour(0, 0, 255)):
336 """ Sets the colours for the link, the visited link and the mouse rollover.
337
338 Defaults Are:
339 - New Link: RED
340 - Visited Link: VIOLET
341 - Rollover: BLUE
342
343 """
344 self._LinkColour = link
345 self._VisitedColour = visited
346 self._LinkRolloverColor = rollover
347
348
349 def GetColours(self):
350 """
351 Gets the colours for the link, the visited link and the mouse
352 rollover.
353 """
354 return self._LinkColour, self._VisitedColour, self._LinkRolloverColor
355
356
357 def SetUnderlines(self, link=True, visited=True, rollover=True):
358 """ Underlines Properties. """
359 self._LinkUnderline = link
360 self._RolloverUnderline = rollover
361 self._VisitedUnderline = visited
362
363
364 def GetUnderlines(self):
365 """
366 Returns if link is underlined, if the mouse rollover is
367 underlined and if the visited link is underlined.
368 """
369 return self._LinkUnderline, self._RolloverUnderline, self._VisitedUnderline
370
371
372 def SetLinkCursor(self, cur=wx.CURSOR_HAND):
373 """ Sets link cursor properties. """
374 self._CursorHand = wx.StockCursor(cur)
375
376
377 def GetLinkCursor(self):
378 """ Gets the link cursor. """
379 return self._CursorHand
380
381
382 def SetVisited(self, Visited=False):
383 """ Sets a link as visited. """
384
385 self._Visited = Visited
386
387
388 def GetVisited(self):
389 """ Returns whether a link has been visited or not. """
390 return self._Visited
391
392
393 def SetBold(self, Bold=False):
394 """ Sets the HyperLink in bold text. """
395 self._Bold = Bold
396
397
398 def GetBold(self):
399 """ Returns whether the HyperLink has text in bold or not. """
400 return self._Bold
401
402
403 def SetURL(self, URL):
404 """ Sets the HyperLink text to the specified URL. """
405 self._URL = URL
406
407
408 def GetURL(self):
409 """ Retrieve the URL associated to the HyperLink. """
410 return self._URL
411
412
413 def OpenInSameWindow(self, NotSameWinIfPossible=False):
414 """ Open multiple URL in the same window (if possible). """
415 self._NotSameWinIfPossible = NotSameWinIfPossible
416
417
418 def EnableRollover(self, EnableRollover=False):
419 """ Enable/disable rollover. """
420 self._EnableRollover = EnableRollover
421
422
423 def ReportErrors(self, ReportErrors=True):
424 """ Set whether to report browser errors or not. """
425 self._ReportErrors = ReportErrors
426
427
428 def AutoBrowse(self, AutoBrowse=True):
429 """
430 Automatically browse to URL when clicked. set to False to
431 receive EVT_HYPERLINK_LEFT event.
432 """
433 self._AutoBrowse = AutoBrowse
434
435
436 def DoPopup(self, DoPopup=True):
437 """ Sets whether to show popup menu on right click or not. """
438 self._DoPopup = DoPopup
439
440