]> git.saurik.com Git - wxWidgets.git/blob - src/generic/hyperlinkg.cpp
native wxHyperlinkCtrl implementation for GTK+ 2.10+ (patch 1661851)
[wxWidgets.git] / src / generic / hyperlinkg.cpp
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
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
49 IMPLEMENT_DYNAMIC_CLASS(wxGenericHyperlinkCtrl, wxControl)
50
51 // reserved for internal use only
52 #define wxHYPERLINK_POPUP_COPY_ID 16384
53
54 // ----------------------------------------------------------------------------
55 // wxGenericHyperlinkCtrl
56 // ----------------------------------------------------------------------------
57
58 bool wxGenericHyperlinkCtrl::Create(wxWindow *parent, wxWindowID id,
59 const wxString& label, const wxString& url, const wxPoint& pos,
60 const wxSize& size, long style, const wxString& name)
61 {
62 // do validation checks:
63 CheckParams(label, url, style);
64
65 if (!wxControl::Create(parent, id, pos, size, style, wxDefaultValidator, name))
66 return false;
67
68 // set to non empty strings both the url and the label
69 SetURL(url.empty() ? label : url);
70 SetLabel(label.empty() ? url : label);
71
72 m_rollover = false;
73 m_clicking = false;
74 m_visited = false;
75
76 // colours
77 m_normalColour = *wxBLUE;
78 m_hoverColour = *wxRED;
79 SetForegroundColour(m_normalColour);
80
81 // by default the font of an hyperlink control is underlined
82 wxFont f = GetFont();
83 f.SetUnderlined(true);
84 SetFont(f);
85
86 SetInitialSize(size);
87
88
89 // connect our event handlers:
90 // NOTE: since this class is the base class of the GTK+'s native implementation
91 // of wxHyperlinkCtrl, we cannot use the static macros in BEGIN/END_EVENT_TABLE
92 // blocks, otherwise the GTK+'s native impl of wxHyperlinkCtrl would not
93 // behave correctly (as we intercept events doing things which interfere
94 // with GTK+'s native handling):
95
96 Connect( wxEVT_PAINT, wxPaintEventHandler(wxGenericHyperlinkCtrl::OnPaint) );
97 Connect( wxEVT_SIZE, wxSizeEventHandler(wxGenericHyperlinkCtrl::OnSize) );
98 Connect( wxEVT_LEAVE_WINDOW, wxMouseEventHandler(wxGenericHyperlinkCtrl::OnLeaveWindow) );
99
100 Connect( wxEVT_LEFT_DOWN, wxMouseEventHandler(wxGenericHyperlinkCtrl::OnLeftDown) );
101 Connect( wxEVT_LEFT_UP, wxMouseEventHandler(wxGenericHyperlinkCtrl::OnLeftUp) );
102 Connect( wxEVT_RIGHT_UP, wxMouseEventHandler(wxGenericHyperlinkCtrl::OnRightUp) );
103 Connect( wxEVT_MOTION, wxMouseEventHandler(wxGenericHyperlinkCtrl::OnMotion) );
104
105 Connect( wxHYPERLINK_POPUP_COPY_ID, wxEVT_COMMAND_MENU_SELECTED,
106 wxCommandEventHandler(wxGenericHyperlinkCtrl::OnPopUpCopy) );
107
108 return true;
109 }
110
111 wxSize wxGenericHyperlinkCtrl::DoGetBestSize() const
112 {
113 int w, h;
114
115 wxClientDC dc((wxWindow *)this);
116 dc.SetFont(GetFont());
117 dc.GetTextExtent(GetLabel(), &w, &h);
118
119 wxSize best(w, h);
120 CacheBestSize(best);
121 return best;
122 }
123
124
125 void wxGenericHyperlinkCtrl::SetNormalColour(const wxColour &colour)
126 {
127 m_normalColour = colour;
128 if (!m_visited)
129 {
130 SetForegroundColour(m_normalColour);
131 Refresh();
132 }
133 }
134
135 void wxGenericHyperlinkCtrl::SetVisitedColour(const wxColour &colour)
136 {
137 m_visitedColour = colour;
138 if (m_visited)
139 {
140 SetForegroundColour(m_visitedColour);
141 Refresh();
142 }
143 }
144
145 void wxGenericHyperlinkCtrl::DoContextMenu(const wxPoint &pos)
146 {
147 wxMenu *menuPopUp = new wxMenu(wxEmptyString, wxMENU_TEAROFF);
148 menuPopUp->Append(wxHYPERLINK_POPUP_COPY_ID, wxT("Copy URL"));
149 PopupMenu( menuPopUp, pos );
150 delete menuPopUp;
151 }
152
153 wxRect wxGenericHyperlinkCtrl::GetLabelRect() const
154 {
155 // our best size is always the size of the label without borders
156 wxSize c(GetClientSize()), b(GetBestSize());
157 wxPoint offset;
158
159 // the label is always centered vertically
160 offset.y = (c.GetHeight()-b.GetHeight())/2;
161
162 if (HasFlag(wxHL_ALIGN_CENTRE))
163 offset.x = (c.GetWidth()-b.GetWidth())/2;
164 else if (HasFlag(wxHL_ALIGN_RIGHT))
165 offset.x = c.GetWidth()-b.GetWidth();
166 else if (HasFlag(wxHL_ALIGN_LEFT))
167 offset.x = 0;
168 return wxRect(offset, b);
169 }
170
171
172
173 // ----------------------------------------------------------------------------
174 // wxGenericHyperlinkCtrl - event handlers
175 // ----------------------------------------------------------------------------
176
177 void wxGenericHyperlinkCtrl::OnPaint(wxPaintEvent& WXUNUSED(event))
178 {
179 wxPaintDC dc(this);
180 dc.SetFont(GetFont());
181 dc.SetTextForeground(GetForegroundColour());
182 dc.SetTextBackground(GetBackgroundColour());
183
184 dc.DrawText(GetLabel(), GetLabelRect().GetTopLeft());
185 }
186
187 void wxGenericHyperlinkCtrl::OnLeftDown(wxMouseEvent& event)
188 {
189 // the left click must start from the hyperlink rect
190 m_clicking = GetLabelRect().Contains(event.GetPosition());
191 }
192
193 void wxGenericHyperlinkCtrl::OnLeftUp(wxMouseEvent& event)
194 {
195 // the click must be started and ended in the hyperlink rect
196 if (!m_clicking || !GetLabelRect().Contains(event.GetPosition()))
197 return;
198
199 SetForegroundColour(m_visitedColour);
200 m_visited = true;
201 m_clicking = false;
202
203 // send the event
204 SendEvent();
205 }
206
207 void wxGenericHyperlinkCtrl::OnRightUp(wxMouseEvent& event)
208 {
209 if( GetWindowStyle() & wxHL_CONTEXTMENU )
210 if ( GetLabelRect().Contains(event.GetPosition()) )
211 DoContextMenu(wxPoint(event.m_x, event.m_y));
212 }
213
214 void wxGenericHyperlinkCtrl::OnMotion(wxMouseEvent& event)
215 {
216 wxRect textrc = GetLabelRect();
217
218 if (textrc.Contains(event.GetPosition()))
219 {
220 SetCursor(wxCursor(wxCURSOR_HAND));
221 SetForegroundColour(m_hoverColour);
222 m_rollover = true;
223 Refresh();
224 }
225 else if (m_rollover)
226 {
227 SetCursor(*wxSTANDARD_CURSOR);
228 SetForegroundColour(!m_visited ? m_normalColour : m_visitedColour);
229 m_rollover = false;
230 Refresh();
231 }
232 }
233
234 void wxGenericHyperlinkCtrl::OnLeaveWindow(wxMouseEvent& WXUNUSED(event) )
235 {
236 // NB: when the label rect and the client size rect have the same
237 // height this function is indispensable to remove the "rollover"
238 // effect as the OnMotion() event handler could not be called
239 // in that case moving the mouse out of the label vertically...
240
241 if (m_rollover)
242 {
243 SetCursor(*wxSTANDARD_CURSOR);
244 SetForegroundColour(!m_visited ? m_normalColour : m_visitedColour);
245 m_rollover = false;
246 Refresh();
247 }
248 }
249
250 void wxGenericHyperlinkCtrl::OnPopUpCopy( wxCommandEvent& WXUNUSED(event) )
251 {
252 #if wxUSE_CLIPBOARD
253 if (!wxTheClipboard->Open())
254 return;
255
256 wxTextDataObject *data = new wxTextDataObject( m_url );
257 wxTheClipboard->SetData( data );
258 wxTheClipboard->Close();
259 #endif // wxUSE_CLIPBOARD
260 }
261
262 void wxGenericHyperlinkCtrl::OnSize(wxSizeEvent& WXUNUSED(event))
263 {
264 // update the position of the label in the screen respecting
265 // the selected align flag
266 Refresh();
267 }
268
269 #endif // wxUSE_HYPERLINKCTRL