1998-05-20 10:01:55 -04:00
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
2005-12-19 05:03:04 -05:00
|
|
|
// Name: src/gtk/control.cpp
|
|
|
|
// Purpose: wxControl implementation for wxGTK
|
1998-05-20 10:01:55 -04:00
|
|
|
// Author: Robert Roebling
|
1998-10-26 05:56:58 -05:00
|
|
|
// Id: $Id$
|
1998-10-24 13:12:05 -04:00
|
|
|
// Copyright: (c) 1998 Robert Roebling, Julian Smart and Vadim Zeitlin
|
2004-05-23 16:53:33 -04:00
|
|
|
// Licence: wxWindows licence
|
1998-05-20 10:01:55 -04:00
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
2003-08-09 08:46:53 -04:00
|
|
|
// For compilers that support precompilation, includes "wx.h".
|
|
|
|
#include "wx/wxprec.h"
|
|
|
|
|
2001-06-26 16:59:19 -04:00
|
|
|
#if wxUSE_CONTROLS
|
|
|
|
|
2005-12-19 05:03:04 -05:00
|
|
|
#include "wx/log.h"
|
1998-05-20 10:01:55 -04:00
|
|
|
#include "wx/control.h"
|
2004-05-06 13:26:25 -04:00
|
|
|
#include "wx/fontutil.h"
|
|
|
|
#include "wx/settings.h"
|
2005-12-18 11:37:56 -05:00
|
|
|
#include "wx/gtk/private.h"
|
1999-04-09 14:01:17 -04:00
|
|
|
|
2005-12-19 05:03:04 -05:00
|
|
|
// ============================================================================
|
|
|
|
// wxControl implementation
|
|
|
|
// ============================================================================
|
|
|
|
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
// wxControl creation
|
|
|
|
// ----------------------------------------------------------------------------
|
1998-05-20 10:01:55 -04:00
|
|
|
|
1999-10-18 11:45:28 -04:00
|
|
|
IMPLEMENT_DYNAMIC_CLASS(wxControl, wxWindow)
|
1998-05-20 10:01:55 -04:00
|
|
|
|
1999-07-23 17:03:02 -04:00
|
|
|
wxControl::wxControl()
|
1998-05-20 10:01:55 -04:00
|
|
|
{
|
1998-12-17 03:40:34 -05:00
|
|
|
m_needParent = TRUE;
|
1998-08-14 06:07:38 -04:00
|
|
|
}
|
1998-05-20 10:01:55 -04:00
|
|
|
|
2000-01-04 12:20:21 -05:00
|
|
|
bool wxControl::Create( wxWindow *parent,
|
1999-07-23 17:03:02 -04:00
|
|
|
wxWindowID id,
|
|
|
|
const wxPoint &pos,
|
|
|
|
const wxSize &size,
|
|
|
|
long style,
|
1999-12-23 14:23:13 -05:00
|
|
|
const wxValidator& validator,
|
2000-01-04 12:20:21 -05:00
|
|
|
const wxString &name )
|
1999-12-23 14:23:13 -05:00
|
|
|
{
|
2000-01-04 12:20:21 -05:00
|
|
|
bool ret = wxWindow::Create(parent, id, pos, size, style, name);
|
2005-12-18 11:37:56 -05:00
|
|
|
|
2000-01-04 12:20:21 -05:00
|
|
|
#if wxUSE_VALIDATORS
|
1999-12-23 14:23:13 -05:00
|
|
|
SetValidator(validator);
|
|
|
|
#endif
|
|
|
|
|
2000-01-04 12:20:21 -05:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
1999-11-19 16:01:20 -05:00
|
|
|
wxSize wxControl::DoGetBestSize() const
|
|
|
|
{
|
2000-01-01 18:21:04 -05:00
|
|
|
// Do not return any arbitrary default value...
|
|
|
|
wxASSERT_MSG( m_widget, wxT("DoGetBestSize called before creation") );
|
|
|
|
|
1999-11-19 16:01:20 -05:00
|
|
|
GtkRequisition req;
|
2000-01-03 06:42:49 -05:00
|
|
|
req.width = 2;
|
|
|
|
req.height = 2;
|
2000-07-19 06:28:26 -04:00
|
|
|
(* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(m_widget) )->size_request )
|
1999-11-19 16:01:20 -05:00
|
|
|
(m_widget, &req );
|
|
|
|
|
2004-06-24 16:09:45 -04:00
|
|
|
wxSize best(req.width, req.height);
|
|
|
|
CacheBestSize(best);
|
|
|
|
return best;
|
1999-11-19 16:01:20 -05:00
|
|
|
}
|
|
|
|
|
2004-05-04 03:09:32 -04:00
|
|
|
|
|
|
|
void wxControl::PostCreation(const wxSize& size)
|
|
|
|
{
|
|
|
|
wxWindow::PostCreation();
|
2004-06-14 13:34:00 -04:00
|
|
|
|
|
|
|
// NB: GetBestSize needs to know the style, otherwise it will assume
|
|
|
|
// default font and if the user uses a different font, determined
|
|
|
|
// best size will be different (typically, smaller) than the desired
|
|
|
|
// size. This call ensure that a style is available at the time
|
|
|
|
// GetBestSize is called.
|
|
|
|
gtk_widget_ensure_style(m_widget);
|
2005-12-18 11:37:56 -05:00
|
|
|
|
2004-05-04 03:09:32 -04:00
|
|
|
ApplyWidgetStyle();
|
|
|
|
SetInitialBestSize(size);
|
|
|
|
}
|
|
|
|
|
2005-12-18 11:37:56 -05:00
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
// wxControl dealing with labels
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
void wxControl::SetLabel( const wxString &label )
|
|
|
|
{
|
|
|
|
// keep the original string internally to be able to return it later (for
|
|
|
|
// consistency with the other ports)
|
|
|
|
m_label = label;
|
|
|
|
|
|
|
|
InvalidateBestSize();
|
|
|
|
}
|
|
|
|
|
|
|
|
wxString wxControl::GetLabel() const
|
|
|
|
{
|
|
|
|
return m_label;
|
|
|
|
}
|
|
|
|
|
|
|
|
void wxControl::GTKSetLabelForLabel(GtkLabel *w, const wxString& label)
|
|
|
|
{
|
|
|
|
// don't call the virtual function which might call this one back again
|
|
|
|
wxControl::SetLabel(label);
|
|
|
|
|
|
|
|
const wxString labelGTK = GTKConvertMnemonics(label);
|
2004-05-04 03:09:32 -04:00
|
|
|
|
2003-03-05 10:58:10 -05:00
|
|
|
#ifdef __WXGTK20__
|
2005-12-18 11:37:56 -05:00
|
|
|
gtk_label_set_text_with_mnemonic(w, wxGTK_CONV(labelGTK));
|
|
|
|
#else
|
|
|
|
gtk_label_set(w, wxGTK_CONV(labelGTK));
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
void wxControl::GTKSetLabelForFrame(GtkFrame *w, const wxString& label)
|
|
|
|
{
|
|
|
|
wxControl::SetLabel(label);
|
|
|
|
|
|
|
|
// frames don't support mnemonics even under GTK+ 2
|
|
|
|
const wxString labelGTK = GTKRemoveMnemonics(label);
|
|
|
|
|
|
|
|
gtk_frame_set_label(w, labelGTK.empty() ? (char *)NULL
|
|
|
|
: wxGTK_CONV(labelGTK));
|
|
|
|
}
|
|
|
|
|
|
|
|
// worker function implementing both GTKConvert/RemoveMnemonics()
|
|
|
|
//
|
|
|
|
// notice that under GTK+ 1 we only really need to support MNEMONICS_REMOVE as
|
|
|
|
// it doesn't support mnemonics anyhow but this would make the code so ugly
|
|
|
|
// that we do the same thing for GKT+ 1 and 2
|
|
|
|
enum MnemonicsFlag
|
2003-03-04 18:34:52 -05:00
|
|
|
{
|
2005-12-18 11:37:56 -05:00
|
|
|
MNEMONICS_REMOVE,
|
|
|
|
MNEMONICS_CONVERT
|
|
|
|
};
|
|
|
|
|
|
|
|
static wxString GTKProcessMnemonics(const wxString& label, MnemonicsFlag flag)
|
|
|
|
{
|
|
|
|
const size_t len = label.length();
|
|
|
|
wxString labelGTK;
|
|
|
|
labelGTK.reserve(len);
|
|
|
|
for ( size_t i = 0; i < len; i++ )
|
2003-03-04 18:34:52 -05:00
|
|
|
{
|
2005-12-18 11:37:56 -05:00
|
|
|
wxChar ch = label[i];
|
|
|
|
|
|
|
|
switch ( ch )
|
2003-03-04 18:34:52 -05:00
|
|
|
{
|
2005-12-18 11:37:56 -05:00
|
|
|
case wxT('&'):
|
|
|
|
if ( i == len - 1 )
|
|
|
|
{
|
|
|
|
// "&" at the end of string is an error
|
|
|
|
wxLogDebug(wxT("Invalid label \"%s\"."), label.c_str());
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
ch = label[++i]; // skip '&' itself
|
|
|
|
switch ( ch )
|
|
|
|
{
|
|
|
|
case wxT('&'):
|
|
|
|
// special case: "&&" is not a mnemonic at all but just
|
|
|
|
// an escaped "&"
|
|
|
|
labelGTK += wxT('&');
|
|
|
|
break;
|
|
|
|
|
|
|
|
case wxT('_'):
|
|
|
|
if ( flag == MNEMONICS_CONVERT )
|
|
|
|
{
|
|
|
|
// '_' can't be a GTK mnemonic apparently so
|
|
|
|
// replace it with something similar
|
|
|
|
labelGTK += wxT("_-");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
//else: fall through
|
|
|
|
|
|
|
|
default:
|
|
|
|
if ( flag == MNEMONICS_CONVERT )
|
|
|
|
labelGTK += wxT('_');
|
|
|
|
labelGTK += ch;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case wxT('_'):
|
|
|
|
if ( flag == MNEMONICS_CONVERT )
|
|
|
|
{
|
|
|
|
// escape any existing underlines in the string so that
|
|
|
|
// they don't become mnemonics accidentally
|
|
|
|
labelGTK += wxT("__");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
//else: fall through
|
|
|
|
|
|
|
|
default:
|
|
|
|
labelGTK += ch;
|
2003-03-04 18:34:52 -05:00
|
|
|
}
|
|
|
|
}
|
2005-12-18 11:37:56 -05:00
|
|
|
|
|
|
|
return labelGTK;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* static */
|
|
|
|
wxString wxControl::GTKRemoveMnemonics(const wxString& label)
|
|
|
|
{
|
|
|
|
return GTKProcessMnemonics(label, MNEMONICS_REMOVE);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* static */
|
|
|
|
wxString wxControl::GTKConvertMnemonics(const wxString& label)
|
|
|
|
{
|
2005-12-23 21:21:00 -05:00
|
|
|
#ifdef __WXGTK20__
|
2005-12-18 11:37:56 -05:00
|
|
|
return GTKProcessMnemonics(label, MNEMONICS_CONVERT);
|
2005-12-23 21:21:00 -05:00
|
|
|
#else
|
|
|
|
return GTKRemoveMnemonics(label);
|
|
|
|
#endif
|
2003-03-04 18:34:52 -05:00
|
|
|
}
|
|
|
|
|
2005-12-18 11:37:56 -05:00
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
// wxControl styles (a.k.a. attributes)
|
|
|
|
// ----------------------------------------------------------------------------
|
2004-05-06 13:26:25 -04:00
|
|
|
|
|
|
|
wxVisualAttributes wxControl::GetDefaultAttributes() const
|
|
|
|
{
|
|
|
|
return GetDefaultAttributesFromGTKWidget(m_widget,
|
|
|
|
UseGTKStyleBase());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#define SHIFT (8*(sizeof(short int)-sizeof(char)))
|
|
|
|
|
|
|
|
// static
|
|
|
|
wxVisualAttributes
|
|
|
|
wxControl::GetDefaultAttributesFromGTKWidget(GtkWidget* widget,
|
|
|
|
bool useBase,
|
|
|
|
int state)
|
|
|
|
{
|
|
|
|
GtkStyle* style;
|
|
|
|
wxVisualAttributes attr;
|
|
|
|
|
|
|
|
style = gtk_rc_get_style(widget);
|
|
|
|
if (!style)
|
|
|
|
style = gtk_widget_get_default_style();
|
|
|
|
|
|
|
|
if (!style)
|
|
|
|
{
|
|
|
|
return wxWindow::GetClassDefaultAttributes(wxWINDOW_VARIANT_NORMAL);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (state == -1)
|
|
|
|
state = GTK_STATE_NORMAL;
|
2005-12-18 11:37:56 -05:00
|
|
|
|
2004-05-06 13:26:25 -04:00
|
|
|
// get the style's colours
|
|
|
|
attr.colFg = wxColour(style->fg[state].red >> SHIFT,
|
|
|
|
style->fg[state].green >> SHIFT,
|
|
|
|
style->fg[state].blue >> SHIFT);
|
|
|
|
if (useBase)
|
|
|
|
attr.colBg = wxColour(style->base[state].red >> SHIFT,
|
|
|
|
style->base[state].green >> SHIFT,
|
|
|
|
style->base[state].blue >> SHIFT);
|
|
|
|
else
|
|
|
|
attr.colBg = wxColour(style->bg[state].red >> SHIFT,
|
|
|
|
style->bg[state].green >> SHIFT,
|
|
|
|
style->bg[state].blue >> SHIFT);
|
|
|
|
|
|
|
|
// get the style's font
|
|
|
|
#ifdef __WXGTK20__
|
|
|
|
if ( !style->font_desc )
|
2005-12-18 11:37:56 -05:00
|
|
|
style = gtk_widget_get_default_style();
|
2004-05-06 13:26:25 -04:00
|
|
|
if ( style && style->font_desc )
|
2005-12-18 11:37:56 -05:00
|
|
|
{
|
|
|
|
wxNativeFontInfo info;
|
2004-07-02 16:54:12 -04:00
|
|
|
info.description = pango_font_description_copy(style->font_desc);
|
2005-12-18 11:37:56 -05:00
|
|
|
attr.font = wxFont(info);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2004-05-06 13:26:25 -04:00
|
|
|
GtkSettings *settings = gtk_settings_get_default();
|
|
|
|
gchar *font_name = NULL;
|
|
|
|
g_object_get ( settings,
|
2005-12-18 11:37:56 -05:00
|
|
|
"gtk-font-name",
|
2004-05-06 13:26:25 -04:00
|
|
|
&font_name,
|
|
|
|
NULL);
|
|
|
|
if (!font_name)
|
|
|
|
attr.font = wxSystemSettings::GetFont( wxSYS_DEFAULT_GUI_FONT );
|
|
|
|
else
|
|
|
|
attr.font = wxFont(wxString::FromAscii(font_name));
|
|
|
|
g_free (font_name);
|
2005-12-18 11:37:56 -05:00
|
|
|
}
|
2004-05-06 13:26:25 -04:00
|
|
|
#else
|
|
|
|
// TODO: isn't there a way to get a standard gtk 1.2 font?
|
|
|
|
attr.font = wxFont( 12, wxSWISS, wxNORMAL, wxNORMAL );
|
|
|
|
#endif
|
2005-12-18 11:37:56 -05:00
|
|
|
|
2004-05-06 13:26:25 -04:00
|
|
|
return attr;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//static
|
|
|
|
wxVisualAttributes
|
2005-03-21 18:42:26 -05:00
|
|
|
wxControl::GetDefaultAttributesFromGTKWidget(wxGtkWidgetNew_t widget_new,
|
2004-05-06 13:26:25 -04:00
|
|
|
bool useBase,
|
|
|
|
int state)
|
|
|
|
{
|
|
|
|
wxVisualAttributes attr;
|
2004-08-15 12:03:06 -04:00
|
|
|
// NB: we need toplevel window so that GTK+ can find the right style
|
|
|
|
GtkWidget *wnd = gtk_window_new(GTK_WINDOW_TOPLEVEL);
|
2004-05-06 13:26:25 -04:00
|
|
|
GtkWidget* widget = widget_new();
|
2004-08-15 12:03:06 -04:00
|
|
|
gtk_container_add(GTK_CONTAINER(wnd), widget);
|
2004-05-06 13:26:25 -04:00
|
|
|
attr = GetDefaultAttributesFromGTKWidget(widget, useBase, state);
|
2004-08-15 12:03:06 -04:00
|
|
|
gtk_widget_destroy(wnd);
|
2004-05-06 13:26:25 -04:00
|
|
|
return attr;
|
|
|
|
}
|
|
|
|
|
|
|
|
//static
|
|
|
|
wxVisualAttributes
|
2005-03-21 18:42:26 -05:00
|
|
|
wxControl::GetDefaultAttributesFromGTKWidget(wxGtkWidgetNewFromStr_t widget_new,
|
2004-05-06 13:26:25 -04:00
|
|
|
bool useBase,
|
|
|
|
int state)
|
|
|
|
{
|
|
|
|
wxVisualAttributes attr;
|
2004-08-15 12:03:06 -04:00
|
|
|
// NB: we need toplevel window so that GTK+ can find the right style
|
|
|
|
GtkWidget *wnd = gtk_window_new(GTK_WINDOW_TOPLEVEL);
|
2004-05-06 13:26:25 -04:00
|
|
|
GtkWidget* widget = widget_new("");
|
2004-08-15 12:03:06 -04:00
|
|
|
gtk_container_add(GTK_CONTAINER(wnd), widget);
|
2004-05-06 13:26:25 -04:00
|
|
|
attr = GetDefaultAttributesFromGTKWidget(widget, useBase, state);
|
2004-08-15 12:03:06 -04:00
|
|
|
gtk_widget_destroy(wnd);
|
2004-05-06 13:26:25 -04:00
|
|
|
return attr;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//static
|
|
|
|
wxVisualAttributes
|
2005-03-21 18:42:26 -05:00
|
|
|
wxControl::GetDefaultAttributesFromGTKWidget(wxGtkWidgetNewFromAdj_t widget_new,
|
2004-05-06 13:26:25 -04:00
|
|
|
bool useBase,
|
|
|
|
int state)
|
|
|
|
{
|
|
|
|
wxVisualAttributes attr;
|
2004-08-15 12:03:06 -04:00
|
|
|
// NB: we need toplevel window so that GTK+ can find the right style
|
|
|
|
GtkWidget *wnd = gtk_window_new(GTK_WINDOW_TOPLEVEL);
|
2004-05-06 13:26:25 -04:00
|
|
|
GtkWidget* widget = widget_new(NULL);
|
2004-08-15 12:03:06 -04:00
|
|
|
gtk_container_add(GTK_CONTAINER(wnd), widget);
|
2004-05-06 13:26:25 -04:00
|
|
|
attr = GetDefaultAttributesFromGTKWidget(widget, useBase, state);
|
2004-08-15 12:03:06 -04:00
|
|
|
gtk_widget_destroy(wnd);
|
2004-05-06 13:26:25 -04:00
|
|
|
return attr;
|
|
|
|
}
|
|
|
|
|
2001-06-26 16:59:19 -04:00
|
|
|
#endif // wxUSE_CONTROLS
|
|
|
|
|