]> git.saurik.com Git - wxWidgets.git/blame - src/generic/hyperlinkg.cpp
avoid direct struct access for GTK3
[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"
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) );
c105dda0
VZ
92 Connect( wxEVT_LEAVE_WINDOW, wxMouseEventHandler(wxGenericHyperlinkCtrl::OnLeaveWindow) );
93
94 Connect( wxEVT_LEFT_DOWN, wxMouseEventHandler(wxGenericHyperlinkCtrl::OnLeftDown) );
95 Connect( wxEVT_LEFT_UP, wxMouseEventHandler(wxGenericHyperlinkCtrl::OnLeftUp) );
c105dda0
VZ
96 Connect( wxEVT_MOTION, wxMouseEventHandler(wxGenericHyperlinkCtrl::OnMotion) );
97
b815cf68 98 ConnectMenuHandlers();
c105dda0 99
17e91437
VZ
100 return true;
101}
102
b815cf68 103void wxGenericHyperlinkCtrl::Init()
17e91437 104{
b815cf68
VZ
105 m_rollover = false;
106 m_clicking = false;
107 m_visited = false;
17e91437 108
b815cf68
VZ
109 // colours
110 m_normalColour = *wxBLUE;
111 m_hoverColour = *wxRED;
112 m_visitedColour = wxColour("#551a8b");
113}
114
115void wxGenericHyperlinkCtrl::ConnectMenuHandlers()
116{
117 // Connect the event handlers for the context menu.
118 Connect( wxEVT_RIGHT_UP, wxMouseEventHandler(wxGenericHyperlinkCtrl::OnRightUp) );
119 Connect( wxHYPERLINK_POPUP_COPY_ID, wxEVT_COMMAND_MENU_SELECTED,
120 wxCommandEventHandler(wxGenericHyperlinkCtrl::OnPopUpCopy) );
121}
17e91437 122
b815cf68
VZ
123wxSize wxGenericHyperlinkCtrl::DoGetBestClientSize() const
124{
125 wxClientDC dc((wxWindow *)this);
126 return dc.GetTextExtent(GetLabel());
17e91437
VZ
127}
128
17e91437 129
c105dda0 130void wxGenericHyperlinkCtrl::SetNormalColour(const wxColour &colour)
17e91437
VZ
131{
132 m_normalColour = colour;
133 if (!m_visited)
134 {
135 SetForegroundColour(m_normalColour);
136 Refresh();
137 }
138}
139
c105dda0 140void wxGenericHyperlinkCtrl::SetVisitedColour(const wxColour &colour)
17e91437
VZ
141{
142 m_visitedColour = colour;
143 if (m_visited)
144 {
145 SetForegroundColour(m_visitedColour);
146 Refresh();
147 }
148}
149
c105dda0 150void wxGenericHyperlinkCtrl::DoContextMenu(const wxPoint &pos)
17e91437
VZ
151{
152 wxMenu *menuPopUp = new wxMenu(wxEmptyString, wxMENU_TEAROFF);
28dd9a9d 153 menuPopUp->Append(wxHYPERLINK_POPUP_COPY_ID, _("&Copy URL"));
17e91437
VZ
154 PopupMenu( menuPopUp, pos );
155 delete menuPopUp;
156}
157
c105dda0 158wxRect wxGenericHyperlinkCtrl::GetLabelRect() const
914f5157
VZ
159{
160 // our best size is always the size of the label without borders
161 wxSize c(GetClientSize()), b(GetBestSize());
162 wxPoint offset;
163
164 // the label is always centered vertically
165 offset.y = (c.GetHeight()-b.GetHeight())/2;
166
167 if (HasFlag(wxHL_ALIGN_CENTRE))
168 offset.x = (c.GetWidth()-b.GetWidth())/2;
169 else if (HasFlag(wxHL_ALIGN_RIGHT))
170 offset.x = c.GetWidth()-b.GetWidth();
171 else if (HasFlag(wxHL_ALIGN_LEFT))
172 offset.x = 0;
173 return wxRect(offset, b);
174}
175
17e91437
VZ
176
177
178// ----------------------------------------------------------------------------
c105dda0 179// wxGenericHyperlinkCtrl - event handlers
17e91437
VZ
180// ----------------------------------------------------------------------------
181
c105dda0 182void wxGenericHyperlinkCtrl::OnPaint(wxPaintEvent& WXUNUSED(event))
17e91437
VZ
183{
184 wxPaintDC dc(this);
185 dc.SetFont(GetFont());
186 dc.SetTextForeground(GetForegroundColour());
187 dc.SetTextBackground(GetBackgroundColour());
914f5157
VZ
188
189 dc.DrawText(GetLabel(), GetLabelRect().GetTopLeft());
17e91437
VZ
190}
191
c105dda0 192void wxGenericHyperlinkCtrl::OnLeftDown(wxMouseEvent& event)
17e91437 193{
914f5157 194 // the left click must start from the hyperlink rect
22a35096 195 m_clicking = GetLabelRect().Contains(event.GetPosition());
17e91437
VZ
196}
197
c105dda0 198void wxGenericHyperlinkCtrl::OnLeftUp(wxMouseEvent& event)
17e91437 199{
914f5157 200 // the click must be started and ended in the hyperlink rect
03647350 201 if (!m_clicking || !GetLabelRect().Contains(event.GetPosition()))
914f5157 202 return;
17e91437
VZ
203
204 SetForegroundColour(m_visitedColour);
205 m_visited = true;
206 m_clicking = false;
207
208 // send the event
c105dda0 209 SendEvent();
17e91437
VZ
210}
211
c105dda0 212void wxGenericHyperlinkCtrl::OnRightUp(wxMouseEvent& event)
17e91437
VZ
213{
214 if( GetWindowStyle() & wxHL_CONTEXTMENU )
22a35096 215 if ( GetLabelRect().Contains(event.GetPosition()) )
914f5157 216 DoContextMenu(wxPoint(event.m_x, event.m_y));
17e91437
VZ
217}
218
c105dda0 219void wxGenericHyperlinkCtrl::OnMotion(wxMouseEvent& event)
17e91437 220{
914f5157
VZ
221 wxRect textrc = GetLabelRect();
222
22a35096 223 if (textrc.Contains(event.GetPosition()))
914f5157
VZ
224 {
225 SetCursor(wxCursor(wxCURSOR_HAND));
226 SetForegroundColour(m_hoverColour);
227 m_rollover = true;
228 Refresh();
229 }
230 else if (m_rollover)
231 {
232 SetCursor(*wxSTANDARD_CURSOR);
233 SetForegroundColour(!m_visited ? m_normalColour : m_visitedColour);
234 m_rollover = false;
235 Refresh();
236 }
17e91437
VZ
237}
238
c105dda0 239void wxGenericHyperlinkCtrl::OnLeaveWindow(wxMouseEvent& WXUNUSED(event) )
17e91437 240{
914f5157
VZ
241 // NB: when the label rect and the client size rect have the same
242 // height this function is indispensable to remove the "rollover"
243 // effect as the OnMotion() event handler could not be called
244 // in that case moving the mouse out of the label vertically...
245
17e91437
VZ
246 if (m_rollover)
247 {
914f5157 248 SetCursor(*wxSTANDARD_CURSOR);
17e91437
VZ
249 SetForegroundColour(!m_visited ? m_normalColour : m_visitedColour);
250 m_rollover = false;
251 Refresh();
252 }
253}
254
c105dda0 255void wxGenericHyperlinkCtrl::OnPopUpCopy( wxCommandEvent& WXUNUSED(event) )
17e91437 256{
3cb3b8b8 257#if wxUSE_CLIPBOARD
17e91437
VZ
258 if (!wxTheClipboard->Open())
259 return;
260
261 wxTextDataObject *data = new wxTextDataObject( m_url );
262 wxTheClipboard->SetData( data );
263 wxTheClipboard->Close();
3cb3b8b8 264#endif // wxUSE_CLIPBOARD
17e91437
VZ
265}
266
267#endif // wxUSE_HYPERLINKCTRL