]> git.saurik.com Git - wxWidgets.git/blame - src/generic/hyperlink.cpp
More RTL work.
[wxWidgets.git] / src / generic / hyperlink.cpp
CommitLineData
17e91437 1/////////////////////////////////////////////////////////////////////////////
98159dd8 2// Name: src/generic/hyperlink.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"
17e91437
VZ
44
45// ============================================================================
46// implementation
47// ============================================================================
48
49IMPLEMENT_DYNAMIC_CLASS(wxHyperlinkCtrl, wxControl)
258b2ca6 50IMPLEMENT_DYNAMIC_CLASS(wxHyperlinkEvent, wxCommandEvent)
17e91437
VZ
51DEFINE_EVENT_TYPE(wxEVT_COMMAND_HYPERLINK)
52
53// reserved for internal use only
54#define wxHYPERLINKCTRL_POPUP_COPY_ID 16384
55
56// ----------------------------------------------------------------------------
57// wxHyperlinkCtrl
58// ----------------------------------------------------------------------------
59
60BEGIN_EVENT_TABLE(wxHyperlinkCtrl, wxControl)
61 EVT_PAINT(wxHyperlinkCtrl::OnPaint)
62 EVT_LEFT_DOWN(wxHyperlinkCtrl::OnLeftDown)
63 EVT_LEFT_UP(wxHyperlinkCtrl::OnLeftUp)
64 EVT_RIGHT_UP(wxHyperlinkCtrl::OnRightUp)
914f5157 65 EVT_MOTION(wxHyperlinkCtrl::OnMotion)
17e91437 66 EVT_LEAVE_WINDOW(wxHyperlinkCtrl::OnLeaveWindow)
914f5157 67 EVT_SIZE(wxHyperlinkCtrl::OnSize)
17e91437
VZ
68
69 // for the context menu
70 EVT_MENU(wxHYPERLINKCTRL_POPUP_COPY_ID, wxHyperlinkCtrl::OnPopUpCopy)
71END_EVENT_TABLE()
72
73bool wxHyperlinkCtrl::Create(wxWindow *parent, wxWindowID id,
74 const wxString& label, const wxString& url, const wxPoint& pos,
75 const wxSize& size, long style, const wxString& name)
76{
98159dd8 77 wxASSERT_MSG(!url.empty() || !label.empty(),
17e91437
VZ
78 wxT("Both URL and label are empty ?"));
79
914f5157
VZ
80#ifdef __WXDEBUG__
81 int alignment = (int)((style & wxHL_ALIGN_LEFT) != 0) +
82 (int)((style & wxHL_ALIGN_CENTRE) != 0) +
83 (int)((style & wxHL_ALIGN_RIGHT) != 0);
84 wxASSERT_MSG(alignment == 1,
85 wxT("Specify exactly one align flag!"));
86#endif
87
17e91437
VZ
88 if (!wxControl::Create(parent, id, pos, size, style, wxDefaultValidator, name))
89 return false;
90
91 // set to non empty strings both the url and the label
98159dd8
WS
92 if(url.empty())
93 SetURL(label);
94 else
06ec4d9c 95 SetURL(url);
98159dd8
WS
96
97 if(label.empty())
98 SetLabel(url);
99 else
100 SetLabel(label);
17e91437 101
17e91437
VZ
102 m_rollover = false;
103 m_clicking = false;
104 m_visited = false;
105
106 // colours
107 m_normalColour = *wxBLUE;
108 m_hoverColour = *wxRED;
109 SetForegroundColour(m_normalColour);
110
111 // by default the font of an hyperlink control is underlined
112 wxFont f = GetFont();
113 f.SetUnderlined(true);
114 SetFont(f);
115
116 CacheBestSize(DoGetBestSize());
117 SetMinSize(GetBestSize());
118 SetSize (DoGetBestSize());
119
120 return true;
121}
122
123wxSize wxHyperlinkCtrl::DoGetBestSize() const
124{
125 int w, h;
126
127 wxClientDC dc((wxWindow *)this);
128 dc.SetFont(GetFont());
129 dc.GetTextExtent(GetLabel(), &w, &h);
130
131 return wxSize(w, h);
132}
133
134void wxHyperlinkCtrl::DoGetSize(int *width, int *height) const
135{
136 if (width) *width = GetBestSize().GetWidth();
137 if (height) *height = GetBestSize().GetHeight();
138}
139
140void wxHyperlinkCtrl::SetNormalColour(const wxColour &colour)
141{
142 m_normalColour = colour;
143 if (!m_visited)
144 {
145 SetForegroundColour(m_normalColour);
146 Refresh();
147 }
148}
149
150void wxHyperlinkCtrl::SetVisitedColour(const wxColour &colour)
151{
152 m_visitedColour = colour;
153 if (m_visited)
154 {
155 SetForegroundColour(m_visitedColour);
156 Refresh();
157 }
158}
159
160void wxHyperlinkCtrl::DoContextMenu(const wxPoint &pos)
161{
162 wxMenu *menuPopUp = new wxMenu(wxEmptyString, wxMENU_TEAROFF);
163 menuPopUp->Append(wxHYPERLINKCTRL_POPUP_COPY_ID, wxT("Copy URL"));
164 PopupMenu( menuPopUp, pos );
165 delete menuPopUp;
166}
167
914f5157
VZ
168wxRect wxHyperlinkCtrl::GetLabelRect() const
169{
170 // our best size is always the size of the label without borders
171 wxSize c(GetClientSize()), b(GetBestSize());
172 wxPoint offset;
173
174 // the label is always centered vertically
175 offset.y = (c.GetHeight()-b.GetHeight())/2;
176
177 if (HasFlag(wxHL_ALIGN_CENTRE))
178 offset.x = (c.GetWidth()-b.GetWidth())/2;
179 else if (HasFlag(wxHL_ALIGN_RIGHT))
180 offset.x = c.GetWidth()-b.GetWidth();
181 else if (HasFlag(wxHL_ALIGN_LEFT))
182 offset.x = 0;
183 return wxRect(offset, b);
184}
185
17e91437
VZ
186
187
188// ----------------------------------------------------------------------------
189// wxHyperlinkCtrl - event handlers
190// ----------------------------------------------------------------------------
191
192void wxHyperlinkCtrl::OnPaint(wxPaintEvent& WXUNUSED(event))
193{
194 wxPaintDC dc(this);
195 dc.SetFont(GetFont());
196 dc.SetTextForeground(GetForegroundColour());
197 dc.SetTextBackground(GetBackgroundColour());
914f5157
VZ
198
199 dc.DrawText(GetLabel(), GetLabelRect().GetTopLeft());
17e91437
VZ
200}
201
914f5157 202void wxHyperlinkCtrl::OnLeftDown(wxMouseEvent& event)
17e91437 203{
914f5157 204 // the left click must start from the hyperlink rect
22a35096 205 m_clicking = GetLabelRect().Contains(event.GetPosition());
17e91437
VZ
206}
207
914f5157 208void wxHyperlinkCtrl::OnLeftUp(wxMouseEvent& event)
17e91437 209{
914f5157 210 // the click must be started and ended in the hyperlink rect
22a35096 211 if (!m_clicking || !GetLabelRect().Contains(event.GetPosition()))
914f5157 212 return;
17e91437
VZ
213
214 SetForegroundColour(m_visitedColour);
215 m_visited = true;
216 m_clicking = false;
217
218 // send the event
219 wxHyperlinkEvent linkEvent(this, GetId(), m_url);
220 if (!GetEventHandler()->ProcessEvent(linkEvent)) // was the event skipped ?
221 if (!wxLaunchDefaultBrowser(m_url))
222 wxLogWarning(wxT("Could not launch the default browser with url '%s' !"), m_url.c_str());
223}
224
225void wxHyperlinkCtrl::OnRightUp(wxMouseEvent& event)
226{
227 if( GetWindowStyle() & wxHL_CONTEXTMENU )
22a35096 228 if ( GetLabelRect().Contains(event.GetPosition()) )
914f5157 229 DoContextMenu(wxPoint(event.m_x, event.m_y));
17e91437
VZ
230}
231
914f5157 232void wxHyperlinkCtrl::OnMotion(wxMouseEvent& event)
17e91437 233{
914f5157
VZ
234 wxRect textrc = GetLabelRect();
235
22a35096 236 if (textrc.Contains(event.GetPosition()))
914f5157
VZ
237 {
238 SetCursor(wxCursor(wxCURSOR_HAND));
239 SetForegroundColour(m_hoverColour);
240 m_rollover = true;
241 Refresh();
242 }
243 else if (m_rollover)
244 {
245 SetCursor(*wxSTANDARD_CURSOR);
246 SetForegroundColour(!m_visited ? m_normalColour : m_visitedColour);
247 m_rollover = false;
248 Refresh();
249 }
17e91437
VZ
250}
251
914f5157 252void wxHyperlinkCtrl::OnLeaveWindow(wxMouseEvent& WXUNUSED(event) )
17e91437 253{
914f5157
VZ
254 // NB: when the label rect and the client size rect have the same
255 // height this function is indispensable to remove the "rollover"
256 // effect as the OnMotion() event handler could not be called
257 // in that case moving the mouse out of the label vertically...
258
17e91437
VZ
259 if (m_rollover)
260 {
914f5157 261 SetCursor(*wxSTANDARD_CURSOR);
17e91437
VZ
262 SetForegroundColour(!m_visited ? m_normalColour : m_visitedColour);
263 m_rollover = false;
264 Refresh();
265 }
266}
267
268void wxHyperlinkCtrl::OnPopUpCopy( wxCommandEvent& WXUNUSED(event) )
269{
3cb3b8b8 270#if wxUSE_CLIPBOARD
17e91437
VZ
271 if (!wxTheClipboard->Open())
272 return;
273
274 wxTextDataObject *data = new wxTextDataObject( m_url );
275 wxTheClipboard->SetData( data );
276 wxTheClipboard->Close();
3cb3b8b8 277#endif // wxUSE_CLIPBOARD
17e91437
VZ
278}
279
914f5157
VZ
280void wxHyperlinkCtrl::OnSize(wxSizeEvent& WXUNUSED(event))
281{
282 // update the position of the label in the screen respecting
283 // the selected align flag
284 Refresh();
285}
286
17e91437 287#endif // wxUSE_HYPERLINKCTRL