1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/generic/hyperlink.cpp
3 // Purpose: Hyperlink control
4 // Author: David Norris <danorris@gmail.com>, Otto Wyss
5 // Modified by: Ryan Norton, Francesco Montorsi
8 // Copyright: (c) 2005 David Norris
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 // ============================================================================
14 // ============================================================================
16 //---------------------------------------------------------------------------
17 // Pre-compiled header stuff
18 //---------------------------------------------------------------------------
20 // For compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
27 #if wxUSE_HYPERLINKCTRL
29 //---------------------------------------------------------------------------
31 //---------------------------------------------------------------------------
33 #include "wx/hyperlink.h"
36 #include "wx/utils.h" // for wxLaunchDefaultBrowser
37 #include "wx/dcclient.h"
40 #include "wx/dataobj.h"
43 #include "wx/clipbrd.h"
45 // ============================================================================
47 // ============================================================================
49 IMPLEMENT_DYNAMIC_CLASS(wxHyperlinkCtrl
, wxControl
)
50 IMPLEMENT_DYNAMIC_CLASS(wxHyperlinkEvent
, wxCommandEvent
)
51 DEFINE_EVENT_TYPE(wxEVT_COMMAND_HYPERLINK
)
53 // reserved for internal use only
54 #define wxHYPERLINKCTRL_POPUP_COPY_ID 16384
56 const wxChar wxHyperlinkCtrlNameStr
[] = wxT("hyperlink");
58 // ----------------------------------------------------------------------------
60 // ----------------------------------------------------------------------------
62 BEGIN_EVENT_TABLE(wxHyperlinkCtrl
, wxControl
)
63 EVT_PAINT(wxHyperlinkCtrl::OnPaint
)
64 EVT_LEFT_DOWN(wxHyperlinkCtrl::OnLeftDown
)
65 EVT_LEFT_UP(wxHyperlinkCtrl::OnLeftUp
)
66 EVT_RIGHT_UP(wxHyperlinkCtrl::OnRightUp
)
67 EVT_MOTION(wxHyperlinkCtrl::OnMotion
)
68 EVT_LEAVE_WINDOW(wxHyperlinkCtrl::OnLeaveWindow
)
69 EVT_SIZE(wxHyperlinkCtrl::OnSize
)
71 // for the context menu
72 EVT_MENU(wxHYPERLINKCTRL_POPUP_COPY_ID
, wxHyperlinkCtrl::OnPopUpCopy
)
75 bool wxHyperlinkCtrl::Create(wxWindow
*parent
, wxWindowID id
,
76 const wxString
& label
, const wxString
& url
, const wxPoint
& pos
,
77 const wxSize
& size
, long style
, const wxString
& name
)
79 wxASSERT_MSG(!url
.empty() || !label
.empty(),
80 wxT("Both URL and label are empty ?"));
83 int alignment
= (int)((style
& wxHL_ALIGN_LEFT
) != 0) +
84 (int)((style
& wxHL_ALIGN_CENTRE
) != 0) +
85 (int)((style
& wxHL_ALIGN_RIGHT
) != 0);
86 wxASSERT_MSG(alignment
== 1,
87 wxT("Specify exactly one align flag!"));
90 if (!wxControl::Create(parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
))
93 // set to non empty strings both the url and the label
109 m_normalColour
= *wxBLUE
;
110 m_hoverColour
= *wxRED
;
111 SetForegroundColour(m_normalColour
);
113 // by default the font of an hyperlink control is underlined
114 wxFont f
= GetFont();
115 f
.SetUnderlined(true);
118 SetInitialSize(size
);
123 wxSize
wxHyperlinkCtrl::DoGetBestSize() const
127 wxClientDC
dc((wxWindow
*)this);
128 dc
.SetFont(GetFont());
129 dc
.GetTextExtent(GetLabel(), &w
, &h
);
137 void wxHyperlinkCtrl::SetNormalColour(const wxColour
&colour
)
139 m_normalColour
= colour
;
142 SetForegroundColour(m_normalColour
);
147 void wxHyperlinkCtrl::SetVisitedColour(const wxColour
&colour
)
149 m_visitedColour
= colour
;
152 SetForegroundColour(m_visitedColour
);
157 void wxHyperlinkCtrl::DoContextMenu(const wxPoint
&pos
)
159 wxMenu
*menuPopUp
= new wxMenu(wxEmptyString
, wxMENU_TEAROFF
);
160 menuPopUp
->Append(wxHYPERLINKCTRL_POPUP_COPY_ID
, wxT("Copy URL"));
161 PopupMenu( menuPopUp
, pos
);
165 wxRect
wxHyperlinkCtrl::GetLabelRect() const
167 // our best size is always the size of the label without borders
168 wxSize
c(GetClientSize()), b(GetBestSize());
171 // the label is always centered vertically
172 offset
.y
= (c
.GetHeight()-b
.GetHeight())/2;
174 if (HasFlag(wxHL_ALIGN_CENTRE
))
175 offset
.x
= (c
.GetWidth()-b
.GetWidth())/2;
176 else if (HasFlag(wxHL_ALIGN_RIGHT
))
177 offset
.x
= c
.GetWidth()-b
.GetWidth();
178 else if (HasFlag(wxHL_ALIGN_LEFT
))
180 return wxRect(offset
, b
);
185 // ----------------------------------------------------------------------------
186 // wxHyperlinkCtrl - event handlers
187 // ----------------------------------------------------------------------------
189 void wxHyperlinkCtrl::OnPaint(wxPaintEvent
& WXUNUSED(event
))
192 dc
.SetFont(GetFont());
193 dc
.SetTextForeground(GetForegroundColour());
194 dc
.SetTextBackground(GetBackgroundColour());
196 dc
.DrawText(GetLabel(), GetLabelRect().GetTopLeft());
199 void wxHyperlinkCtrl::OnLeftDown(wxMouseEvent
& event
)
201 // the left click must start from the hyperlink rect
202 m_clicking
= GetLabelRect().Contains(event
.GetPosition());
205 void wxHyperlinkCtrl::OnLeftUp(wxMouseEvent
& event
)
207 // the click must be started and ended in the hyperlink rect
208 if (!m_clicking
|| !GetLabelRect().Contains(event
.GetPosition()))
211 SetForegroundColour(m_visitedColour
);
216 wxHyperlinkEvent
linkEvent(this, GetId(), m_url
);
217 if (!GetEventHandler()->ProcessEvent(linkEvent
)) // was the event skipped ?
218 if (!wxLaunchDefaultBrowser(m_url
))
219 wxLogWarning(wxT("Could not launch the default browser with url '%s' !"), m_url
.c_str());
222 void wxHyperlinkCtrl::OnRightUp(wxMouseEvent
& event
)
224 if( GetWindowStyle() & wxHL_CONTEXTMENU
)
225 if ( GetLabelRect().Contains(event
.GetPosition()) )
226 DoContextMenu(wxPoint(event
.m_x
, event
.m_y
));
229 void wxHyperlinkCtrl::OnMotion(wxMouseEvent
& event
)
231 wxRect textrc
= GetLabelRect();
233 if (textrc
.Contains(event
.GetPosition()))
235 SetCursor(wxCursor(wxCURSOR_HAND
));
236 SetForegroundColour(m_hoverColour
);
242 SetCursor(*wxSTANDARD_CURSOR
);
243 SetForegroundColour(!m_visited
? m_normalColour
: m_visitedColour
);
249 void wxHyperlinkCtrl::OnLeaveWindow(wxMouseEvent
& WXUNUSED(event
) )
251 // NB: when the label rect and the client size rect have the same
252 // height this function is indispensable to remove the "rollover"
253 // effect as the OnMotion() event handler could not be called
254 // in that case moving the mouse out of the label vertically...
258 SetCursor(*wxSTANDARD_CURSOR
);
259 SetForegroundColour(!m_visited
? m_normalColour
: m_visitedColour
);
265 void wxHyperlinkCtrl::OnPopUpCopy( wxCommandEvent
& WXUNUSED(event
) )
268 if (!wxTheClipboard
->Open())
271 wxTextDataObject
*data
= new wxTextDataObject( m_url
);
272 wxTheClipboard
->SetData( data
);
273 wxTheClipboard
->Close();
274 #endif // wxUSE_CLIPBOARD
277 void wxHyperlinkCtrl::OnSize(wxSizeEvent
& WXUNUSED(event
))
279 // update the position of the label in the screen respecting
280 // the selected align flag
284 #endif // wxUSE_HYPERLINKCTRL