]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/generic/hyperlink.cpp
DoGetBestSize fix, the lbWidth was not getting updated because of a
[wxWidgets.git] / src / generic / hyperlink.cpp
... / ...
CommitLineData
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
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
20// For compilers that support precompilation, includes "wx.h".
21#include "wx/wxprec.h"
22
23#ifdef __BORLANDC__
24 #pragma hdrstop
25#endif
26
27#if wxUSE_HYPERLINKCTRL
28
29//---------------------------------------------------------------------------
30// Includes
31//---------------------------------------------------------------------------
32
33#include "wx/hyperlink.h"
34
35#ifndef WX_PRECOMP
36 #include "wx/utils.h" // for wxLaunchDefaultBrowser
37 #include "wx/dcclient.h"
38 #include "wx/menu.h"
39 #include "wx/log.h"
40 #include "wx/dataobj.h"
41#endif
42
43#include "wx/clipbrd.h"
44
45// ============================================================================
46// implementation
47// ============================================================================
48
49IMPLEMENT_DYNAMIC_CLASS(wxHyperlinkCtrl, wxControl)
50IMPLEMENT_DYNAMIC_CLASS(wxHyperlinkEvent, wxCommandEvent)
51DEFINE_EVENT_TYPE(wxEVT_COMMAND_HYPERLINK)
52
53// reserved for internal use only
54#define wxHYPERLINKCTRL_POPUP_COPY_ID 16384
55
56const wxChar wxHyperlinkCtrlNameStr[] = wxT("hyperlink");
57
58// ----------------------------------------------------------------------------
59// wxHyperlinkCtrl
60// ----------------------------------------------------------------------------
61
62BEGIN_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)
70
71 // for the context menu
72 EVT_MENU(wxHYPERLINKCTRL_POPUP_COPY_ID, wxHyperlinkCtrl::OnPopUpCopy)
73END_EVENT_TABLE()
74
75bool 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)
78{
79 wxASSERT_MSG(!url.empty() || !label.empty(),
80 wxT("Both URL and label are empty ?"));
81
82#ifdef __WXDEBUG__
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!"));
88#endif
89
90 if (!wxControl::Create(parent, id, pos, size, style, wxDefaultValidator, name))
91 return false;
92
93 // set to non empty strings both the url and the label
94 if(url.empty())
95 SetURL(label);
96 else
97 SetURL(url);
98
99 if(label.empty())
100 SetLabel(url);
101 else
102 SetLabel(label);
103
104 m_rollover = false;
105 m_clicking = false;
106 m_visited = false;
107
108 // colours
109 m_normalColour = *wxBLUE;
110 m_hoverColour = *wxRED;
111 SetForegroundColour(m_normalColour);
112
113 // by default the font of an hyperlink control is underlined
114 wxFont f = GetFont();
115 f.SetUnderlined(true);
116 SetFont(f);
117
118 SetInitialSize(size);
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 wxSize best(w, h);
132 CacheBestSize(best);
133 return best;
134}
135
136
137void wxHyperlinkCtrl::SetNormalColour(const wxColour &colour)
138{
139 m_normalColour = colour;
140 if (!m_visited)
141 {
142 SetForegroundColour(m_normalColour);
143 Refresh();
144 }
145}
146
147void wxHyperlinkCtrl::SetVisitedColour(const wxColour &colour)
148{
149 m_visitedColour = colour;
150 if (m_visited)
151 {
152 SetForegroundColour(m_visitedColour);
153 Refresh();
154 }
155}
156
157void wxHyperlinkCtrl::DoContextMenu(const wxPoint &pos)
158{
159 wxMenu *menuPopUp = new wxMenu(wxEmptyString, wxMENU_TEAROFF);
160 menuPopUp->Append(wxHYPERLINKCTRL_POPUP_COPY_ID, wxT("Copy URL"));
161 PopupMenu( menuPopUp, pos );
162 delete menuPopUp;
163}
164
165wxRect wxHyperlinkCtrl::GetLabelRect() const
166{
167 // our best size is always the size of the label without borders
168 wxSize c(GetClientSize()), b(GetBestSize());
169 wxPoint offset;
170
171 // the label is always centered vertically
172 offset.y = (c.GetHeight()-b.GetHeight())/2;
173
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))
179 offset.x = 0;
180 return wxRect(offset, b);
181}
182
183
184
185// ----------------------------------------------------------------------------
186// wxHyperlinkCtrl - event handlers
187// ----------------------------------------------------------------------------
188
189void wxHyperlinkCtrl::OnPaint(wxPaintEvent& WXUNUSED(event))
190{
191 wxPaintDC dc(this);
192 dc.SetFont(GetFont());
193 dc.SetTextForeground(GetForegroundColour());
194 dc.SetTextBackground(GetBackgroundColour());
195
196 dc.DrawText(GetLabel(), GetLabelRect().GetTopLeft());
197}
198
199void wxHyperlinkCtrl::OnLeftDown(wxMouseEvent& event)
200{
201 // the left click must start from the hyperlink rect
202 m_clicking = GetLabelRect().Contains(event.GetPosition());
203}
204
205void wxHyperlinkCtrl::OnLeftUp(wxMouseEvent& event)
206{
207 // the click must be started and ended in the hyperlink rect
208 if (!m_clicking || !GetLabelRect().Contains(event.GetPosition()))
209 return;
210
211 SetForegroundColour(m_visitedColour);
212 m_visited = true;
213 m_clicking = false;
214
215 // send the event
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());
220}
221
222void wxHyperlinkCtrl::OnRightUp(wxMouseEvent& event)
223{
224 if( GetWindowStyle() & wxHL_CONTEXTMENU )
225 if ( GetLabelRect().Contains(event.GetPosition()) )
226 DoContextMenu(wxPoint(event.m_x, event.m_y));
227}
228
229void wxHyperlinkCtrl::OnMotion(wxMouseEvent& event)
230{
231 wxRect textrc = GetLabelRect();
232
233 if (textrc.Contains(event.GetPosition()))
234 {
235 SetCursor(wxCursor(wxCURSOR_HAND));
236 SetForegroundColour(m_hoverColour);
237 m_rollover = true;
238 Refresh();
239 }
240 else if (m_rollover)
241 {
242 SetCursor(*wxSTANDARD_CURSOR);
243 SetForegroundColour(!m_visited ? m_normalColour : m_visitedColour);
244 m_rollover = false;
245 Refresh();
246 }
247}
248
249void wxHyperlinkCtrl::OnLeaveWindow(wxMouseEvent& WXUNUSED(event) )
250{
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...
255
256 if (m_rollover)
257 {
258 SetCursor(*wxSTANDARD_CURSOR);
259 SetForegroundColour(!m_visited ? m_normalColour : m_visitedColour);
260 m_rollover = false;
261 Refresh();
262 }
263}
264
265void wxHyperlinkCtrl::OnPopUpCopy( wxCommandEvent& WXUNUSED(event) )
266{
267#if wxUSE_CLIPBOARD
268 if (!wxTheClipboard->Open())
269 return;
270
271 wxTextDataObject *data = new wxTextDataObject( m_url );
272 wxTheClipboard->SetData( data );
273 wxTheClipboard->Close();
274#endif // wxUSE_CLIPBOARD
275}
276
277void wxHyperlinkCtrl::OnSize(wxSizeEvent& WXUNUSED(event))
278{
279 // update the position of the label in the screen respecting
280 // the selected align flag
281 Refresh();
282}
283
284#endif // wxUSE_HYPERLINKCTRL