1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/generic/hyperlinkg.cpp
3 // Purpose: Hyperlink control
4 // Author: David Norris <danorris@gmail.com>, Otto Wyss
5 // Modified by: Ryan Norton, Francesco Montorsi
7 // Copyright: (c) 2005 David Norris
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
11 // ============================================================================
13 // ============================================================================
15 //---------------------------------------------------------------------------
16 // Pre-compiled header stuff
17 //---------------------------------------------------------------------------
19 // For compilers that support precompilation, includes "wx.h".
20 #include "wx/wxprec.h"
26 #if wxUSE_HYPERLINKCTRL
28 //---------------------------------------------------------------------------
30 //---------------------------------------------------------------------------
32 #include "wx/hyperlink.h"
35 #include "wx/utils.h" // for wxLaunchDefaultBrowser
36 #include "wx/dcclient.h"
39 #include "wx/dataobj.h"
42 #include "wx/clipbrd.h"
43 #include "wx/renderer.h"
45 // ============================================================================
47 // ============================================================================
49 // reserved for internal use only
50 #define wxHYPERLINK_POPUP_COPY_ID 16384
52 // ----------------------------------------------------------------------------
53 // wxGenericHyperlinkCtrl
54 // ----------------------------------------------------------------------------
56 bool wxGenericHyperlinkCtrl::Create(wxWindow
*parent
, wxWindowID id
,
57 const wxString
& label
, const wxString
& url
, const wxPoint
& pos
,
58 const wxSize
& size
, long style
, const wxString
& name
)
60 // do validation checks:
61 CheckParams(label
, url
, style
);
63 if ((style
& wxHL_ALIGN_LEFT
) == 0)
64 style
|= wxFULL_REPAINT_ON_RESIZE
;
66 if (!wxControl::Create(parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
))
69 // set to non empty strings both the url and the label
70 SetURL(url
.empty() ? label
: url
);
71 SetLabel(label
.empty() ? url
: label
);
74 SetForegroundColour(m_normalColour
);
76 // by default the font of an hyperlink control is underlined
78 f
.SetUnderlined(true);
84 // connect our event handlers:
85 // NOTE: since this class is the base class of the GTK+'s native implementation
86 // of wxHyperlinkCtrl, we cannot use the static macros in BEGIN/END_EVENT_TABLE
87 // blocks, otherwise the GTK+'s native impl of wxHyperlinkCtrl would not
88 // behave correctly (as we intercept events doing things which interfere
89 // with GTK+'s native handling):
91 Connect( wxEVT_PAINT
, wxPaintEventHandler(wxGenericHyperlinkCtrl::OnPaint
) );
92 Connect( wxEVT_SET_FOCUS
, wxFocusEventHandler(wxGenericHyperlinkCtrl::OnFocus
) );
93 Connect( wxEVT_KILL_FOCUS
, wxFocusEventHandler(wxGenericHyperlinkCtrl::OnFocus
) );
94 Connect( wxEVT_CHAR
, wxKeyEventHandler(wxGenericHyperlinkCtrl::OnChar
) );
95 Connect( wxEVT_LEAVE_WINDOW
, wxMouseEventHandler(wxGenericHyperlinkCtrl::OnLeaveWindow
) );
97 Connect( wxEVT_LEFT_DOWN
, wxMouseEventHandler(wxGenericHyperlinkCtrl::OnLeftDown
) );
98 Connect( wxEVT_LEFT_UP
, wxMouseEventHandler(wxGenericHyperlinkCtrl::OnLeftUp
) );
99 Connect( wxEVT_MOTION
, wxMouseEventHandler(wxGenericHyperlinkCtrl::OnMotion
) );
101 ConnectMenuHandlers();
106 void wxGenericHyperlinkCtrl::Init()
113 m_normalColour
= *wxBLUE
;
114 m_hoverColour
= *wxRED
;
115 m_visitedColour
= wxColour("#551a8b");
118 void wxGenericHyperlinkCtrl::ConnectMenuHandlers()
120 // Connect the event handlers for the context menu.
121 Connect( wxEVT_RIGHT_UP
, wxMouseEventHandler(wxGenericHyperlinkCtrl::OnRightUp
) );
122 Connect( wxHYPERLINK_POPUP_COPY_ID
, wxEVT_MENU
,
123 wxCommandEventHandler(wxGenericHyperlinkCtrl::OnPopUpCopy
) );
126 wxSize
wxGenericHyperlinkCtrl::DoGetBestClientSize() const
128 wxClientDC
dc((wxWindow
*)this);
129 return dc
.GetTextExtent(GetLabel());
133 void wxGenericHyperlinkCtrl::SetNormalColour(const wxColour
&colour
)
135 m_normalColour
= colour
;
138 SetForegroundColour(m_normalColour
);
143 void wxGenericHyperlinkCtrl::SetVisitedColour(const wxColour
&colour
)
145 m_visitedColour
= colour
;
148 SetForegroundColour(m_visitedColour
);
153 void wxGenericHyperlinkCtrl::DoContextMenu(const wxPoint
&pos
)
155 wxMenu
*menuPopUp
= new wxMenu(wxEmptyString
, wxMENU_TEAROFF
);
156 menuPopUp
->Append(wxHYPERLINK_POPUP_COPY_ID
, _("&Copy URL"));
157 PopupMenu( menuPopUp
, pos
);
161 wxRect
wxGenericHyperlinkCtrl::GetLabelRect() const
163 // our best size is always the size of the label without borders
164 wxSize
c(GetClientSize()), b(GetBestSize());
167 // the label is always centered vertically
168 offset
.y
= (c
.GetHeight()-b
.GetHeight())/2;
170 if (HasFlag(wxHL_ALIGN_CENTRE
))
171 offset
.x
= (c
.GetWidth()-b
.GetWidth())/2;
172 else if (HasFlag(wxHL_ALIGN_RIGHT
))
173 offset
.x
= c
.GetWidth()-b
.GetWidth();
174 else if (HasFlag(wxHL_ALIGN_LEFT
))
176 return wxRect(offset
, b
);
181 // ----------------------------------------------------------------------------
182 // wxGenericHyperlinkCtrl - event handlers
183 // ----------------------------------------------------------------------------
185 void wxGenericHyperlinkCtrl::OnPaint(wxPaintEvent
& WXUNUSED(event
))
188 dc
.SetFont(GetFont());
189 dc
.SetTextForeground(GetForegroundColour());
190 dc
.SetTextBackground(GetBackgroundColour());
192 dc
.DrawText(GetLabel(), GetLabelRect().GetTopLeft());
195 wxRendererNative::Get().DrawFocusRect(this, dc
, GetClientRect(), wxCONTROL_SELECTED
);
199 void wxGenericHyperlinkCtrl::OnFocus(wxFocusEvent
& event
)
205 void wxGenericHyperlinkCtrl::OnChar(wxKeyEvent
& event
)
207 switch (event
.m_keyCode
)
213 case WXK_NUMPAD_SPACE
:
214 SetForegroundColour(m_visitedColour
);
221 void wxGenericHyperlinkCtrl::OnLeftDown(wxMouseEvent
& event
)
223 // the left click must start from the hyperlink rect
224 m_clicking
= GetLabelRect().Contains(event
.GetPosition());
227 void wxGenericHyperlinkCtrl::OnLeftUp(wxMouseEvent
& event
)
229 // the click must be started and ended in the hyperlink rect
230 if (!m_clicking
|| !GetLabelRect().Contains(event
.GetPosition()))
233 SetForegroundColour(m_visitedColour
);
241 void wxGenericHyperlinkCtrl::OnRightUp(wxMouseEvent
& event
)
243 if( GetWindowStyle() & wxHL_CONTEXTMENU
)
244 if ( GetLabelRect().Contains(event
.GetPosition()) )
245 DoContextMenu(wxPoint(event
.m_x
, event
.m_y
));
248 void wxGenericHyperlinkCtrl::OnMotion(wxMouseEvent
& event
)
250 wxRect textrc
= GetLabelRect();
252 if (textrc
.Contains(event
.GetPosition()))
254 SetCursor(wxCursor(wxCURSOR_HAND
));
255 SetForegroundColour(m_hoverColour
);
261 SetCursor(*wxSTANDARD_CURSOR
);
262 SetForegroundColour(!m_visited
? m_normalColour
: m_visitedColour
);
268 void wxGenericHyperlinkCtrl::OnLeaveWindow(wxMouseEvent
& WXUNUSED(event
) )
270 // NB: when the label rect and the client size rect have the same
271 // height this function is indispensable to remove the "rollover"
272 // effect as the OnMotion() event handler could not be called
273 // in that case moving the mouse out of the label vertically...
277 SetCursor(*wxSTANDARD_CURSOR
);
278 SetForegroundColour(!m_visited
? m_normalColour
: m_visitedColour
);
284 void wxGenericHyperlinkCtrl::OnPopUpCopy( wxCommandEvent
& WXUNUSED(event
) )
287 if (!wxTheClipboard
->Open())
290 wxTextDataObject
*data
= new wxTextDataObject( m_url
);
291 wxTheClipboard
->SetData( data
);
292 wxTheClipboard
->Close();
293 #endif // wxUSE_CLIPBOARD
296 #endif // wxUSE_HYPERLINKCTRL