]> git.saurik.com Git - wxWidgets.git/blame - src/generic/hyperlinkg.cpp
Make wxOwnerDrawnComboBox::DoGetBestSize() twice as fast.
[wxWidgets.git] / src / generic / hyperlinkg.cpp
CommitLineData
17e91437 1/////////////////////////////////////////////////////////////////////////////
c105dda0 2// Name: src/generic/hyperlinkg.cpp
17e91437
VZ
3// Purpose: Hyperlink control
4// Author: David Norris <danorris@gmail.com>, Otto Wyss
5// Modified by: Ryan Norton, Francesco Montorsi
6// Created: 04/02/2005
17e91437
VZ
7// Copyright: (c) 2005 David Norris
8// Licence: wxWindows licence
9/////////////////////////////////////////////////////////////////////////////
10
11// ============================================================================
12// declarations
13// ============================================================================
14
15//---------------------------------------------------------------------------
16// Pre-compiled header stuff
17//---------------------------------------------------------------------------
18
17e91437
VZ
19// For compilers that support precompilation, includes "wx.h".
20#include "wx/wxprec.h"
21
22#ifdef __BORLANDC__
3cb3b8b8 23 #pragma hdrstop
17e91437
VZ
24#endif
25
98159dd8
WS
26#if wxUSE_HYPERLINKCTRL
27
17e91437
VZ
28//---------------------------------------------------------------------------
29// Includes
30//---------------------------------------------------------------------------
31
32#include "wx/hyperlink.h"
17e91437 33
98159dd8
WS
34#ifndef WX_PRECOMP
35 #include "wx/utils.h" // for wxLaunchDefaultBrowser
33f9f48e
WS
36 #include "wx/dcclient.h"
37 #include "wx/menu.h"
38 #include "wx/log.h"
28f92d74 39 #include "wx/dataobj.h"
98159dd8 40#endif
17e91437 41
98159dd8 42#include "wx/clipbrd.h"
bc927c9a 43#include "wx/renderer.h"
17e91437
VZ
44
45// ============================================================================
46// implementation
47// ============================================================================
48
17e91437 49// reserved for internal use only
c105dda0 50#define wxHYPERLINK_POPUP_COPY_ID 16384
b85db900 51
17e91437 52// ----------------------------------------------------------------------------
c105dda0 53// wxGenericHyperlinkCtrl
17e91437
VZ
54// ----------------------------------------------------------------------------
55
c105dda0 56bool wxGenericHyperlinkCtrl::Create(wxWindow *parent, wxWindowID id,
17e91437
VZ
57 const wxString& label, const wxString& url, const wxPoint& pos,
58 const wxSize& size, long style, const wxString& name)
59{
c105dda0
VZ
60 // do validation checks:
61 CheckParams(label, url, style);
914f5157 62
6d020baf
PC
63 if ((style & wxHL_ALIGN_LEFT) == 0)
64 style |= wxFULL_REPAINT_ON_RESIZE;
65
17e91437
VZ
66 if (!wxControl::Create(parent, id, pos, size, style, wxDefaultValidator, name))
67 return false;
68
69 // set to non empty strings both the url and the label
c105dda0
VZ
70 SetURL(url.empty() ? label : url);
71 SetLabel(label.empty() ? url : label);
17e91437 72
b815cf68 73 Init();
17e91437
VZ
74 SetForegroundColour(m_normalColour);
75
76 // by default the font of an hyperlink control is underlined
77 wxFont f = GetFont();
78 f.SetUnderlined(true);
79 SetFont(f);
80
170acdc9 81 SetInitialSize(size);
c105dda0
VZ
82
83
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):
90
91 Connect( wxEVT_PAINT, wxPaintEventHandler(wxGenericHyperlinkCtrl::OnPaint) );
bc927c9a
VZ
92 Connect( wxEVT_SET_FOCUS, wxFocusEventHandler(wxGenericHyperlinkCtrl::OnFocus) );
93 Connect( wxEVT_KILL_FOCUS, wxFocusEventHandler(wxGenericHyperlinkCtrl::OnFocus) );
94 Connect( wxEVT_CHAR, wxKeyEventHandler(wxGenericHyperlinkCtrl::OnChar) );
c105dda0
VZ
95 Connect( wxEVT_LEAVE_WINDOW, wxMouseEventHandler(wxGenericHyperlinkCtrl::OnLeaveWindow) );
96
97 Connect( wxEVT_LEFT_DOWN, wxMouseEventHandler(wxGenericHyperlinkCtrl::OnLeftDown) );
98 Connect( wxEVT_LEFT_UP, wxMouseEventHandler(wxGenericHyperlinkCtrl::OnLeftUp) );
c105dda0
VZ
99 Connect( wxEVT_MOTION, wxMouseEventHandler(wxGenericHyperlinkCtrl::OnMotion) );
100
b815cf68 101 ConnectMenuHandlers();
c105dda0 102
17e91437
VZ
103 return true;
104}
105
b815cf68 106void wxGenericHyperlinkCtrl::Init()
17e91437 107{
b815cf68
VZ
108 m_rollover = false;
109 m_clicking = false;
110 m_visited = false;
17e91437 111
b815cf68
VZ
112 // colours
113 m_normalColour = *wxBLUE;
114 m_hoverColour = *wxRED;
115 m_visitedColour = wxColour("#551a8b");
116}
117
118void wxGenericHyperlinkCtrl::ConnectMenuHandlers()
119{
120 // Connect the event handlers for the context menu.
121 Connect( wxEVT_RIGHT_UP, wxMouseEventHandler(wxGenericHyperlinkCtrl::OnRightUp) );
ce7fe42e 122 Connect( wxHYPERLINK_POPUP_COPY_ID, wxEVT_MENU,
b815cf68
VZ
123 wxCommandEventHandler(wxGenericHyperlinkCtrl::OnPopUpCopy) );
124}
17e91437 125
b815cf68
VZ
126wxSize wxGenericHyperlinkCtrl::DoGetBestClientSize() const
127{
128 wxClientDC dc((wxWindow *)this);
129 return dc.GetTextExtent(GetLabel());
17e91437
VZ
130}
131
17e91437 132
c105dda0 133void wxGenericHyperlinkCtrl::SetNormalColour(const wxColour &colour)
17e91437
VZ
134{
135 m_normalColour = colour;
136 if (!m_visited)
137 {
138 SetForegroundColour(m_normalColour);
139 Refresh();
140 }
141}
142
c105dda0 143void wxGenericHyperlinkCtrl::SetVisitedColour(const wxColour &colour)
17e91437
VZ
144{
145 m_visitedColour = colour;
146 if (m_visited)
147 {
148 SetForegroundColour(m_visitedColour);
149 Refresh();
150 }
151}
152
c105dda0 153void wxGenericHyperlinkCtrl::DoContextMenu(const wxPoint &pos)
17e91437
VZ
154{
155 wxMenu *menuPopUp = new wxMenu(wxEmptyString, wxMENU_TEAROFF);
28dd9a9d 156 menuPopUp->Append(wxHYPERLINK_POPUP_COPY_ID, _("&Copy URL"));
17e91437
VZ
157 PopupMenu( menuPopUp, pos );
158 delete menuPopUp;
159}
160
c105dda0 161wxRect wxGenericHyperlinkCtrl::GetLabelRect() const
914f5157
VZ
162{
163 // our best size is always the size of the label without borders
164 wxSize c(GetClientSize()), b(GetBestSize());
165 wxPoint offset;
166
167 // the label is always centered vertically
168 offset.y = (c.GetHeight()-b.GetHeight())/2;
169
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))
175 offset.x = 0;
176 return wxRect(offset, b);
177}
178
17e91437
VZ
179
180
181// ----------------------------------------------------------------------------
c105dda0 182// wxGenericHyperlinkCtrl - event handlers
17e91437
VZ
183// ----------------------------------------------------------------------------
184
c105dda0 185void wxGenericHyperlinkCtrl::OnPaint(wxPaintEvent& WXUNUSED(event))
17e91437
VZ
186{
187 wxPaintDC dc(this);
188 dc.SetFont(GetFont());
189 dc.SetTextForeground(GetForegroundColour());
190 dc.SetTextBackground(GetBackgroundColour());
914f5157
VZ
191
192 dc.DrawText(GetLabel(), GetLabelRect().GetTopLeft());
bc927c9a
VZ
193 if (HasFocus())
194 {
195 wxRendererNative::Get().DrawFocusRect(this, dc, GetClientRect(), wxCONTROL_SELECTED);
196 }
197}
198
199void wxGenericHyperlinkCtrl::OnFocus(wxFocusEvent& event)
200{
201 Refresh();
202 event.Skip();
203}
204
205void wxGenericHyperlinkCtrl::OnChar(wxKeyEvent& event)
206{
207 switch (event.m_keyCode)
208 {
209 default:
210 event.Skip();
211 break;
212 case WXK_SPACE:
213 case WXK_NUMPAD_SPACE:
214 SetForegroundColour(m_visitedColour);
215 m_visited = true;
216 SendEvent();
217 break;
218 }
17e91437
VZ
219}
220
c105dda0 221void wxGenericHyperlinkCtrl::OnLeftDown(wxMouseEvent& event)
17e91437 222{
914f5157 223 // the left click must start from the hyperlink rect
22a35096 224 m_clicking = GetLabelRect().Contains(event.GetPosition());
17e91437
VZ
225}
226
c105dda0 227void wxGenericHyperlinkCtrl::OnLeftUp(wxMouseEvent& event)
17e91437 228{
914f5157 229 // the click must be started and ended in the hyperlink rect
03647350 230 if (!m_clicking || !GetLabelRect().Contains(event.GetPosition()))
914f5157 231 return;
17e91437
VZ
232
233 SetForegroundColour(m_visitedColour);
234 m_visited = true;
235 m_clicking = false;
236
237 // send the event
c105dda0 238 SendEvent();
17e91437
VZ
239}
240
c105dda0 241void wxGenericHyperlinkCtrl::OnRightUp(wxMouseEvent& event)
17e91437
VZ
242{
243 if( GetWindowStyle() & wxHL_CONTEXTMENU )
22a35096 244 if ( GetLabelRect().Contains(event.GetPosition()) )
914f5157 245 DoContextMenu(wxPoint(event.m_x, event.m_y));
17e91437
VZ
246}
247
c105dda0 248void wxGenericHyperlinkCtrl::OnMotion(wxMouseEvent& event)
17e91437 249{
914f5157
VZ
250 wxRect textrc = GetLabelRect();
251
22a35096 252 if (textrc.Contains(event.GetPosition()))
914f5157
VZ
253 {
254 SetCursor(wxCursor(wxCURSOR_HAND));
255 SetForegroundColour(m_hoverColour);
256 m_rollover = true;
257 Refresh();
258 }
259 else if (m_rollover)
260 {
261 SetCursor(*wxSTANDARD_CURSOR);
262 SetForegroundColour(!m_visited ? m_normalColour : m_visitedColour);
263 m_rollover = false;
264 Refresh();
265 }
17e91437
VZ
266}
267
c105dda0 268void wxGenericHyperlinkCtrl::OnLeaveWindow(wxMouseEvent& WXUNUSED(event) )
17e91437 269{
914f5157
VZ
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...
274
17e91437
VZ
275 if (m_rollover)
276 {
914f5157 277 SetCursor(*wxSTANDARD_CURSOR);
17e91437
VZ
278 SetForegroundColour(!m_visited ? m_normalColour : m_visitedColour);
279 m_rollover = false;
280 Refresh();
281 }
282}
283
c105dda0 284void wxGenericHyperlinkCtrl::OnPopUpCopy( wxCommandEvent& WXUNUSED(event) )
17e91437 285{
3cb3b8b8 286#if wxUSE_CLIPBOARD
17e91437
VZ
287 if (!wxTheClipboard->Open())
288 return;
289
290 wxTextDataObject *data = new wxTextDataObject( m_url );
291 wxTheClipboard->SetData( data );
292 wxTheClipboard->Close();
3cb3b8b8 293#endif // wxUSE_CLIPBOARD
17e91437
VZ
294}
295
296#endif // wxUSE_HYPERLINKCTRL