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