Poodletooth-iLand/panda/python/Lib/site-packages/wx/lib/agw/hyperlink.py
2015-03-06 06:11:40 -06:00

664 lines
20 KiB
Python

# --------------------------------------------------------------------------- #
# HYPERLINKSCTRL wxPython IMPLEMENTATION
# Ported From Angelo Mandato C++ Code By:
#
# Andrea Gavana, @ 27 Mar 2005
# Latest Revision: 16 Jul 2012, 15.00 GMT
#
#
# Original Web Site (For The C++ Code):
#
# http://www.spaceblue.com/codedetail.php?CodeID=7
#
#
# Thanks to E. A. Tacao for his nice suggestions and improvements of the code.
#
# For all kind of problems, requests of enhancements and bug reports, please
# write to me at:
#
# andrea.gavana@gmail.com
# andrea.gavana@maerskoil.com
#
# Or, obviously, to the wxPython mailing list!!!
#
# Tags: phoenix-port, unittest, documented, py3-port
#
# End Of Comments
# --------------------------------------------------------------------------- #
"""
:class:`HyperLinkCtrl` is a control for wxPython that acts like a hyper link
in a typical browser.
Description
===========
:class:`HyperLinkCtrl` is a control for wxPython that acts like a hyper link
in a typical browser. Latest features include the ability to capture
your own left, middle, and right click events to perform your own
custom event handling and ability to open link in a new or current
browser window.
Special thanks to Robin Dunn for the event binder for the 3 mouse buttons.
Usage
=====
Usage example::
import wx
import wx.lib.agw.hyperlink as hl
class MyFrame(wx.Frame):
def __init__(self, parent):
wx.Frame.__init__(self, parent, -1, "HyperLink Demo")
panel = wx.Panel(self, -1)
# Default Web links:
hyper1 = hl.HyperLinkCtrl(panel, -1, "wxPython Main Page", pos=(100, 100),
URL="http://www.wxpython.org/")
# Web link with underline rollovers, opens in same window
hyper2 = hl.HyperLinkCtrl(panel, -1, "My Home Page", pos=(100, 150),
URL="http://xoomer.virgilio.it/infinity77/")
hyper2.AutoBrowse(False)
hyper2.SetColours("BLUE", "BLUE", "BLUE")
hyper2.EnableRollover(True)
hyper2.SetUnderlines(False, False, True)
hyper2.SetBold(True)
hyper2.OpenInSameWindow(True)
hyper2.SetToolTip(wx.ToolTip("Hello World!"))
hyper2.UpdateLink()
# our normal wxApp-derived class, as usual
app = wx.App(0)
frame = MyFrame(None)
app.SetTopWindow(frame)
frame.Show()
app.MainLoop()
Window Styles
=============
`No particular window styles are available for this class.`
Events Processing
=================
This class processes the following events:
======================== ==================================================
Event Name Description
======================== ==================================================
``EVT_HYPERLINK_LEFT`` Responds to a left mouse button event. Sent when the left mouse button is clicked, but only if `AutoBrowse` is set to ``False``.
``EVT_HYPERLINK_MIDDLE`` Responds to a middle mouse button event. Sent when the middle mouse button is clicked.
``EVT_HYPERLINK_RIGHT`` Handles a right mouse button event. Sent when the right mouse button is clicked, but only if `DoPopup` is set to ``False``.
======================== ==================================================
License And Version
===================
:class:`HyperLinkCtrl` is distributed under the wxPython license.
Latest Revision: Andrea Gavana @ 16 Jul 2012, 15.00 GMT
Version 0.7
"""
import wx
from wx.lib.stattext import GenStaticText as StaticText
# Import the useful webbrowser module for platform-independent results
import webbrowser
# Set no delay time to open the web page
webbrowser.PROCESS_CREATION_DELAY = 0
# To show a popup that copies the hyperlinks on the clipboard
wxHYPERLINKS_POPUP_COPY = 1000
""" Flag used to show a popup that copies the hyperlinks on the clipboard. """
#-----------------------------------#
# HyperLinksEvents
#-----------------------------------#
# wxEVT_HYPERLINK_LEFT: Respond To A Left Mouse Button Event
# wxEVT_HYPERLINK_MIDDLE: Respond To A Middle Mouse Button Event
# wxEVT_HYPERLINK_RIGHT: Respond To A Right Mouse Button Event
wxEVT_HYPERLINK_LEFT = wx.NewEventType()
wxEVT_HYPERLINK_MIDDLE = wx.NewEventType()
wxEVT_HYPERLINK_RIGHT = wx.NewEventType()
EVT_HYPERLINK_LEFT = wx.PyEventBinder(wxEVT_HYPERLINK_LEFT, 1)
""" Responds to a left mouse button event. Sent when the left mouse button is""" \
""" clicked, but only if `AutoBrowse` is set to ``False``. """
EVT_HYPERLINK_MIDDLE = wx.PyEventBinder(wxEVT_HYPERLINK_MIDDLE, 1)
""" Responds to a middle mouse button event. Sent when the middle mouse button is clicked. """
EVT_HYPERLINK_RIGHT = wx.PyEventBinder(wxEVT_HYPERLINK_RIGHT, 1)
""" Handles a right mouse button event. Sent when the right mouse button is""" \
""" clicked, but only if `DoPopup` is set to ``False``. """
# ------------------------------------------------------------
# This class implements the event listener for the hyperlinks
# ------------------------------------------------------------
class HyperLinkEvent(wx.CommandEvent):
"""
Event object sent in response to clicking on a :class:`HyperLinkCtrl`.
"""
def __init__(self, eventType, eventId):
"""
Default class constructor.
:param `eventType`: the event type;
:param `eventId`: the event identifier.
"""
wx.CommandEvent.__init__(self, eventType, eventId)
self._eventType = eventType
def SetPosition(self, pos):
"""
Sets the event position.
:param `pos`: an instance of :class:`Point`.
"""
self._pos = pos
def GetPosition(self):
""" Returns the event position. """
return self._pos
# -------------------------------------------------
# This is the main HyperLinkCtrl implementation
# it user the StatiText from wx.lib.stattext
# because of its "quasi-dynamic" behavior
# -------------------------------------------------
class HyperLinkCtrl(StaticText):
"""
:class:`HyperLinkCtrl` is a control for wxPython that acts like a hyper
link in a typical browser. Latest features include the ability to
capture your own left, middle, and right click events to perform
your own custom event handling and ability to open link in a new
or current browser window.
"""
def __init__(self, parent, id=-1, label="", pos=wx.DefaultPosition,
size=wx.DefaultSize, style=0, name="staticText", URL=""):
"""
Default class constructor.
:param `parent`: the window parent. Must not be ``None``;
:param `id`: window identifier. A value of -1 indicates a default value;
:param `label`: the control label;
:param `pos`: the control position. A value of (-1, -1) indicates a default position,
chosen by either the windowing system or wxPython, depending on platform;
:param `size`: the control size. A value of (-1, -1) indicates a default size,
chosen by either the windowing system or wxPython, depending on platform;
:param `style`: the window style;
:param `name`: the window name;
:param `URL`: a string specifying the url link to navigate to.
:note: Pass URL="" to use the label as the url link to navigate to.
"""
StaticText.__init__(self, parent, id, label, pos, size,
style, name)
if URL.strip() == "":
self._URL = label
else:
self._URL = URL
# Set Tooltip
self.SetToolTip(wx.ToolTip(self._URL))
# Set default properties
# default: True
self.ReportErrors()
# default: True, True, True
self.SetUnderlines()
# default: blue, violet, blue
self.SetColours()
# default: False
self.SetVisited()
# default: False
self.EnableRollover()
# default: False
self.SetBold()
# default: wx.CURSOR_HAND
self.SetLinkCursor()
# default True
self.AutoBrowse()
# default True
self.DoPopup()
# default False
self.OpenInSameWindow()
# Set control properties and refresh
self.UpdateLink(True)
self.Bind(wx.EVT_MOUSE_EVENTS, self.OnMouseEvent)
self.Bind(wx.EVT_MOTION, self.OnMouseEvent)
def GotoURL(self, URL, ReportErrors=True, NotSameWinIfPossible=False):
"""
Goto the specified URL.
:param `URL`: the url link we wish to navigate;
:param `ReportErrors`: Use ``True`` to display error dialog if an error
occurrs navigating to the URL;
:param `NotSameWinIfPossible`: Use ``True`` to attempt to open the URL
in new browser window.
"""
logOff = wx.LogNull()
try:
webbrowser.open(URL, new=NotSameWinIfPossible)
self.SetVisited(True)
self.UpdateLink(True)
return True
except:
self.DisplayError("Unable To Launch Browser.", ReportErrors)
return False
def OnMouseEvent(self, event):
"""
Handles the ``wx.EVT_MOUSE_EVENTS`` events for :class:`HyperLinkCtrl`.
:param `event`: a :class:`MouseEvent` event to be processed.
"""
if event.Moving():
# Mouse Is Moving On The StaticText
# Set The Hand Cursor On The Link
self.SetCursor(self._CursorHand)
if self._EnableRollover:
fontTemp = self.GetFont()
fontTemp.SetUnderlined(self._RolloverUnderline)
if self._Bold:
fontTemp.SetWeight(wx.BOLD)
needRefresh = False
if self.GetFont() != fontTemp:
self.SetFont(fontTemp)
needRefresh = True
if self.GetForegroundColour() != self._LinkRolloverColour:
self.SetForegroundColour(self._LinkRolloverColour)
needRefresh = True
if needRefresh:
self.Refresh()
else:
# Restore The Original Cursor
self.SetCursor(wx.NullCursor)
if self._EnableRollover:
self.UpdateLink(True)
if event.LeftUp():
# Left Button Was Pressed
if self._AutoBrowse:
self.GotoURL(self._URL, self._ReportErrors,
self._NotSameWinIfPossible)
else:
eventOut = HyperLinkEvent(wxEVT_HYPERLINK_LEFT, self.GetId())
eventOut.SetEventObject(self)
eventOut.SetPosition(event.GetPosition())
self.GetEventHandler().ProcessEvent(eventOut)
self.SetVisited(True)
elif event.RightUp():
# Right Button Was Pressed
if self._DoPopup:
# Popups A Menu With The "Copy HyperLynks" Feature
menuPopUp = wx.Menu("", wx.MENU_TEAROFF)
menuPopUp.Append(wxHYPERLINKS_POPUP_COPY, "Copy HyperLink")
self.Bind(wx.EVT_MENU, self.OnPopUpCopy, id=wxHYPERLINKS_POPUP_COPY)
self.PopupMenu(menuPopUp, wx.Point(event.x, event.y))
menuPopUp.Destroy()
self.Unbind(wx.EVT_MENU, id=wxHYPERLINKS_POPUP_COPY)
else:
eventOut = HyperLinkEvent(wxEVT_HYPERLINK_RIGHT, self.GetId())
eventOut.SetEventObject(self)
eventOut.SetPosition(event.GetPosition())
self.GetEventHandler().ProcessEvent(eventOut)
elif event.MiddleUp():
# Middle Button Was Pressed
eventOut = HyperLinkEvent(wxEVT_HYPERLINK_MIDDLE, self.GetId())
eventOut.SetEventObject(self)
eventOut.SetPosition(event.GetPosition())
self.GetEventHandler().ProcessEvent(eventOut)
event.Skip()
def OnPopUpCopy(self, event):
"""
Handles the ``wx.EVT_MENU`` event for :class:`HyperLinkCtrl`.
:param `event`: a :class:`MenuEvent` event to be processed.
:note: This method copies the data from the :class:`HyperLinkCtrl` to the clipboard.
"""
wx.TheClipboard.UsePrimarySelection(False)
if not wx.TheClipboard.Open():
return
data = wx.TextDataObject(self._URL)
wx.TheClipboard.SetData(data)
wx.TheClipboard.Close()
def UpdateLink(self, OnRefresh=True):
"""
Updates the link, changing text properties if:
- User specific setting;
- Link visited;
- New link;
:param `OnRefresh`: ``True`` to refresh the control, ``False`` otherwise.
"""
fontTemp = self.GetFont()
if self._Visited:
self.SetForegroundColour(self._VisitedColour)
fontTemp.SetUnderlined(self._VisitedUnderline)
else:
self.SetForegroundColour(self._LinkColour)
fontTemp.SetUnderlined(self._LinkUnderline)
if self._Bold:
fontTemp.SetWeight(wx.BOLD)
if self.GetFont() != fontTemp:
self.SetFont(fontTemp)
self.Refresh(OnRefresh)
def DisplayError(self, ErrorMessage, ReportErrors=True):
"""
Displays an error message (according to the `ReportErrors` parameter) in a
:class:`MessageBox`.
:param `ErrorMessage`: a string representing the error to display;
:param `ReportErrors`: ``True`` to display error dialog if an error occurrs
navigating to the URL.
"""
if ReportErrors:
wx.MessageBox(ErrorMessage, "HyperLinks Error", wx.OK | wx.CENTRE | wx.ICON_ERROR)
def SetColours(self, link=wx.Colour(0, 0, 255), visited=wx.Colour(79, 47, 79),
rollover=wx.Colour(0, 0, 255)):
"""
Sets the colours for the link, the visited link and the mouse rollover.
- Visited link: VIOLET
- Rollover: BLUE
:param `link`: a valid :class:`Colour` to use as text foreground for new links
(default=RED);
:param `visited`: a valid :class:`Colour` to use as text foreground for visited
links (default=VIOLET);
:param `rollover`: a valid :class:`Colour` to use as text foreground for links
rollovers (default=BLUE).
"""
self._LinkColour = link
self._VisitedColour = visited
self._LinkRolloverColour = rollover
def GetColours(self):
"""
Gets the colours for the link, the visited link and the mouse
rollover.
"""
return self._LinkColour, self._VisitedColour, self._LinkRolloverColour
def SetUnderlines(self, link=True, visited=True, rollover=True):
"""
Sets whether the text should be underlined or not for new links, visited
links and rollovers.
:param `link`: ``True`` to set the text of new links as underlined, ``False``
otherwise;
:param `visited`: ``True`` to set the text of visited links as underlined,
``False`` otherwise;
:param `rollover`: ``True`` to set the text of rollovers as underlined,
``False`` otherwise.
"""
self._LinkUnderline = link
self._RolloverUnderline = rollover
self._VisitedUnderline = visited
def GetUnderlines(self):
"""
Returns if link is underlined, if the mouse rollover is
underlined and if the visited link is underlined.
"""
return self._LinkUnderline, self._RolloverUnderline, self._VisitedUnderline
def SetLinkCursor(self, cur=wx.CURSOR_HAND):
"""
Sets link cursor properties.
:param `cur`: an integer representing a :ref:`Cursor` constant.
"""
self._CursorHand = wx.Cursor(cur)
def GetLinkCursor(self):
""" Gets the link cursor. """
return self._CursorHand
def SetVisited(self, Visited=False):
"""
Sets a link as visited.
:param `Visited`: ``True`` to set a link as visited, ``False`` otherwise.
"""
self._Visited = Visited
def GetVisited(self):
""" Returns whether a link has been visited or not. """
return self._Visited
def SetBold(self, Bold=False):
"""
Sets the :class:`HyperLinkCtrl` label in bold text.
:param `Bold`: ``True`` to set the :class:`HyperLinkCtrl` label as bold, ``False``
otherwise.
"""
self._Bold = Bold
def GetBold(self):
""" Returns whether the :class:`HyperLinkCtrl` has text in bold or not. """
return self._Bold
def SetURL(self, URL):
"""
Sets the :class:`HyperLinkCtrl` text to the specified URL.
:param `URL`: the new URL associated with :class:`HyperLinkCtrl`.
"""
self._URL = URL
def GetURL(self):
""" Retrieve the URL associated to the :class:`HyperLinkCtrl`. """
return self._URL
def OpenInSameWindow(self, NotSameWinIfPossible=False):
"""
Open multiple URL in the same window (if possible).
:param `NotSameWinIfPossible`: ``True`` to open an hyperlink in a new browser
window, ``False`` to use an existing browser window.
"""
self._NotSameWinIfPossible = NotSameWinIfPossible
def EnableRollover(self, EnableRollover=False):
"""
Enable/disable rollover.
:param `EnableRollover`: ``True`` to enable text effects during rollover,
``False`` to disable them.
"""
self._EnableRollover = EnableRollover
def ReportErrors(self, ReportErrors=True):
"""
Set whether to report browser errors or not.
:param `ReportErrors`: Use ``True`` to display error dialog if an error
occurrs navigating to the URL;
"""
self._ReportErrors = ReportErrors
def AutoBrowse(self, AutoBrowse=True):
"""
Automatically browse to URL when clicked.
:param `AutoBrowse`: ``True`` to automatically browse to an URL when clicked,
``False`` otherwise.
:note: Set `AutoBrowse` to ``False`` to receive ``EVT_HYPERLINK_LEFT`` events.
"""
self._AutoBrowse = AutoBrowse
def DoPopup(self, DoPopup=True):
"""
Sets whether to show popup menu on right click or not.
:param `DoPopup`: ``True`` to show a popup menu on right click, ``False`` otherwise.
"""
self._DoPopup = DoPopup
if __name__ == '__main__':
import wx
class MyFrame(wx.Frame):
def __init__(self, parent):
wx.Frame.__init__(self, parent, -1, "HyperLink Demo")
panel = wx.Panel(self, -1)
# Default Web links:
hyper1 = HyperLinkCtrl(panel, -1, "wxPython Main Page", pos=(100, 100),
URL="http://www.wxpython.org/")
# Web link with underline rollovers, opens in same window
hyper2 = HyperLinkCtrl(panel, -1, "My Home Page", pos=(100, 150),
URL="http://xoomer.virgilio.it/infinity77/")
hyper2.AutoBrowse(False)
hyper2.SetColours("BLUE", "BLUE", "BLUE")
hyper2.EnableRollover(True)
hyper2.SetUnderlines(False, False, True)
hyper2.SetBold(True)
hyper2.OpenInSameWindow(True)
hyper2.SetToolTip(wx.ToolTip("Hello World!"))
hyper2.UpdateLink()
# our normal wxApp-derived class, as usual
app = wx.App(0)
frame = MyFrame(None)
app.SetTopWindow(frame)
frame.Show()
app.MainLoop()