Files
wxWidgets/src/gtk/hyperlink.cpp
Vadim Zeitlin d6af0236c5 Simplify GTK+ 2 version checks with a helper function
Use wx_is_at_least_gtk2(minor) instead of gtk_check_version(2, minor)
because it is more clear and also works as expected (i.e. returns true)
when using GTK+ 3 instead of creating difficult to notice bugs in the
code by failing the version check in this case.

See #18004.
2017-11-23 13:15:31 +01:00

334 lines
9.2 KiB
C++

/////////////////////////////////////////////////////////////////////////////
// Name: src/gtk/hyperlink.cpp
// Purpose: Hyperlink control
// Author: Francesco Montorsi
// Created: 14/2/2007
// Copyright: (c) 2007 Francesco Montorsi
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
// ============================================================================
// declarations
// ============================================================================
// --------------------------------------------------------------------------
// headers
// --------------------------------------------------------------------------
// For compilers that support precompilation, includes "wx.h".
#include "wx/wxprec.h"
#ifdef __BORLANDC__
#pragma hdrstop
#endif
#if wxUSE_HYPERLINKCTRL && defined(__WXGTK210__) && !defined(__WXUNIVERSAL__)
#include "wx/hyperlink.h"
#ifndef WX_PRECOMP
#endif
#include <gtk/gtk.h>
#include "wx/gtk/private.h"
// ----------------------------------------------------------------------------
// local functions
// ----------------------------------------------------------------------------
static inline bool UseNative()
{
// native gtk_link_button widget is only available in GTK+ 2.10 and later
return wx_is_at_least_gtk2(10);
}
// ============================================================================
// implementation
// ============================================================================
// ----------------------------------------------------------------------------
// "clicked"
// ----------------------------------------------------------------------------
#ifdef __WXGTK3__
extern "C" {
static gboolean activate_link(GtkWidget*, wxHyperlinkCtrl* win)
{
win->SetVisited(true);
win->SendEvent();
return true;
}
}
#else
static GSList* gs_hyperlinkctrl_list;
extern "C" {
static void clicked_hook(GtkLinkButton* button, const char*, void*)
{
for (GSList* p = gs_hyperlinkctrl_list; p; p = p->next)
{
wxHyperlinkCtrl* win = static_cast<wxHyperlinkCtrl*>(p->data);
if (win->m_widget == (GtkWidget*)button)
{
win->SetVisited(true);
win->SendEvent();
return;
}
}
gtk_link_button_set_uri_hook(NULL, NULL, NULL);
GTK_BUTTON_GET_CLASS(button)->clicked(GTK_BUTTON(button));
gtk_link_button_set_uri_hook(clicked_hook, NULL, NULL);
}
}
#endif
// ----------------------------------------------------------------------------
// wxHyperlinkCtrl
// ----------------------------------------------------------------------------
wxHyperlinkCtrl::wxHyperlinkCtrl()
{
}
wxHyperlinkCtrl::wxHyperlinkCtrl(wxWindow *parent,
wxWindowID id,
const wxString& label,
const wxString& url,
const wxPoint& pos,
const wxSize& size,
long style,
const wxString& name)
{
(void)Create(parent, id, label, url, pos, size, style, name);
}
wxHyperlinkCtrl::~wxHyperlinkCtrl()
{
#ifndef __WXGTK3__
gs_hyperlinkctrl_list = g_slist_remove(gs_hyperlinkctrl_list, this);
#endif
}
bool wxHyperlinkCtrl::Create(wxWindow *parent, wxWindowID id,
const wxString& label, const wxString& url, const wxPoint& pos,
const wxSize& size, long style, const wxString& name)
{
if ( UseNative() )
{
// do validation checks:
CheckParams(label, url, style);
if (!PreCreation( parent, pos, size ) ||
!CreateBase( parent, id, pos, size, style, wxDefaultValidator, name ))
{
wxFAIL_MSG( wxT("wxHyperlinkCtrl creation failed") );
return false;
}
m_widget = gtk_link_button_new("asdfsaf asdfdsaf asdfdsa");
g_object_ref(m_widget);
// alignment
float x_alignment = 0.5;
if (HasFlag(wxHL_ALIGN_LEFT))
x_alignment = 0.0;
else if (HasFlag(wxHL_ALIGN_RIGHT))
x_alignment = 1.0;
wxGCC_WARNING_SUPPRESS(deprecated-declarations)
gtk_button_set_alignment(GTK_BUTTON(m_widget), x_alignment, 0.5);
wxGCC_WARNING_RESTORE()
// set to non empty strings both the url and the label
SetURL(url.empty() ? label : url);
SetLabel(label.empty() ? url : label);
#ifdef __WXGTK3__
g_signal_connect(m_widget, "activate_link", G_CALLBACK(activate_link), this);
#else
gs_hyperlinkctrl_list = g_slist_prepend(gs_hyperlinkctrl_list, this);
gtk_link_button_set_uri_hook(clicked_hook, NULL, NULL);
#endif
m_parent->DoAddChild( this );
PostCreation(size);
// wxWindowGTK will connect to the enter_notify and leave_notify GTK+ signals
// thus overriding GTK+'s internal signal handlers which set the cursor of
// the widget - thus we need to manually set it here:
SetCursor(wxCursor(wxCURSOR_HAND));
}
else
return wxGenericHyperlinkCtrl::Create(parent, id, label, url, pos, size, style, name);
return true;
}
wxSize wxHyperlinkCtrl::DoGetBestSize() const
{
if ( UseNative() )
return wxControl::DoGetBestSize();
return wxGenericHyperlinkCtrl::DoGetBestSize();
}
wxSize wxHyperlinkCtrl::DoGetBestClientSize() const
{
if ( UseNative() )
return wxControl::DoGetBestClientSize();
return wxGenericHyperlinkCtrl::DoGetBestClientSize();
}
void wxHyperlinkCtrl::SetLabel(const wxString &label)
{
if ( UseNative() )
{
wxControl::SetLabel(label);
const wxString labelGTK = GTKConvertMnemonics(label);
gtk_button_set_label(GTK_BUTTON(m_widget), wxGTK_CONV(labelGTK));
}
else
wxGenericHyperlinkCtrl::SetLabel(label);
}
void wxHyperlinkCtrl::SetURL(const wxString &uri)
{
if ( UseNative() )
gtk_link_button_set_uri(GTK_LINK_BUTTON(m_widget), wxGTK_CONV(uri));
else
wxGenericHyperlinkCtrl::SetURL(uri);
}
wxString wxHyperlinkCtrl::GetURL() const
{
if ( UseNative() )
{
const gchar *str = gtk_link_button_get_uri(GTK_LINK_BUTTON(m_widget));
return wxString::FromUTF8(str);
}
return wxGenericHyperlinkCtrl::GetURL();
}
void wxHyperlinkCtrl::SetNormalColour(const wxColour &colour)
{
if ( UseNative() )
{
// simply do nothing: GTK+ does not allow us to change it :(
}
else
wxGenericHyperlinkCtrl::SetNormalColour(colour);
}
wxColour wxHyperlinkCtrl::GetNormalColour() const
{
wxColour ret;
if ( UseNative() )
{
GdkColor* link_color;
GdkColor color = { 0, 0, 0, 0xeeee };
GtkWidget* widget = gtk_bin_get_child(GTK_BIN(m_widget));
wxGCC_WARNING_SUPPRESS(deprecated-declarations)
gtk_widget_ensure_style(widget);
gtk_widget_style_get(widget, "link-color", &link_color, NULL);
if (link_color)
{
color = *link_color;
gdk_color_free(link_color);
}
wxGCC_WARNING_RESTORE()
ret = wxColour(color);
}
else
ret = wxGenericHyperlinkCtrl::GetNormalColour();
return ret;
}
void wxHyperlinkCtrl::SetVisitedColour(const wxColour &colour)
{
if ( UseNative() )
{
// simply do nothing: GTK+ does not allow us to change it :(
}
else
wxGenericHyperlinkCtrl::SetVisitedColour(colour);
}
wxColour wxHyperlinkCtrl::GetVisitedColour() const
{
wxColour ret;
if ( UseNative() )
{
GdkColor* link_color;
GdkColor color = { 0, 0x5555, 0x1a1a, 0x8b8b };
GtkWidget* widget = gtk_bin_get_child(GTK_BIN(m_widget));
wxGCC_WARNING_SUPPRESS(deprecated-declarations)
gtk_widget_ensure_style(widget);
gtk_widget_style_get(widget, "visited-link-color", &link_color, NULL);
if (link_color)
{
color = *link_color;
gdk_color_free(link_color);
}
wxGCC_WARNING_RESTORE()
ret = wxColour(color);
}
else
ret = base_type::GetVisitedColour();
return ret;
}
void wxHyperlinkCtrl::SetVisited(bool visited)
{
base_type::SetVisited(visited);
#if GTK_CHECK_VERSION(2,14,0)
if (wx_is_at_least_gtk2(14))
{
gtk_link_button_set_visited(GTK_LINK_BUTTON(m_widget), visited);
}
#endif
}
bool wxHyperlinkCtrl::GetVisited() const
{
#if GTK_CHECK_VERSION(2,14,0)
if (wx_is_at_least_gtk2(14))
{
return gtk_link_button_get_visited(GTK_LINK_BUTTON(m_widget)) != 0;
}
#endif
return base_type::GetVisited();
}
void wxHyperlinkCtrl::SetHoverColour(const wxColour &colour)
{
if ( UseNative() )
{
// simply do nothing: GTK+ does not allow us to change it :(
}
else
wxGenericHyperlinkCtrl::SetHoverColour(colour);
}
wxColour wxHyperlinkCtrl::GetHoverColour() const
{
if ( UseNative() )
{
// hover colour == normal colour for native GTK+ widget
return GetNormalColour();
}
return wxGenericHyperlinkCtrl::GetHoverColour();
}
GdkWindow *wxHyperlinkCtrl::GTKGetWindow(wxArrayGdkWindows& windows) const
{
return UseNative() ? gtk_button_get_event_window(GTK_BUTTON(m_widget))
: wxGenericHyperlinkCtrl::GTKGetWindow(windows);
}
#endif // wxUSE_HYPERLINKCTRL && GTK+ 2.10+