support mnemonics for wxStatic/RadioBox and made it easier to add support for more controls by virtualizing the mnemonics support logic (patch 1448178)

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@38027 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin
2006-03-12 14:21:19 +00:00
parent 186344760d
commit 2e1f50128a
11 changed files with 136 additions and 36 deletions

View File

@@ -151,6 +151,11 @@ wxGTK:
--enable-gstreamer8 to force configure to check for GStreamer 0.8.\
- Fixed problem with choice editor in wxGrid whereby the editor
lost focus when the combobox menu was shown.
- Fixed focusing with mnemonic accelerator keys on wxStaticText which
is now able to focus on wxComboBox and possibly other controls
previously unable to be focused upon before
- Enabled mnemonics and the corresponding accelerator keys for
wxStaticBox and wxRadioBox
- Fixed problem trying to print from a preview, whereby wrong printer
class was used.
- Worked around pango crashes in strncmp on Solaris 10.

View File

@@ -66,8 +66,11 @@ protected:
// sets the label to the given string and also sets it for the given widget
void GTKSetLabelForLabel(GtkLabel *w, const wxString& label);
// as GTKSetLabelForLabel() but for a GtkFrame widget
// GtkFrame helpers
GtkWidget* GTKCreateFrame(const wxString& label);
void GTKSetLabelForFrame(GtkFrame *w, const wxString& label);
void GTKFrameApplyWidgetStyle(GtkFrame* w, GtkRcStyle* rc);
void GTKFrameSetMnemonicWidget(GtkFrame* w, GtkWidget* widget);
// remove mnemonics ("&"s) from the label
static wxString GTKRemoveMnemonics(const wxString& label);

View File

@@ -127,6 +127,9 @@ public:
protected:
void DoApplyWidgetStyle(GtkRcStyle *style);
virtual bool GTKWidgetNeedsMnemonic() const;
virtual void GTKWidgetDoSetMnemonic(GtkWidget* w);
// common part of all ctors
void Init();

View File

@@ -43,6 +43,9 @@ public:
virtual bool IsTransparentForMouse() const { return TRUE; }
protected:
virtual bool GTKWidgetNeedsMnemonic() const;
virtual void GTKWidgetDoSetMnemonic(GtkWidget* w);
void DoApplyWidgetStyle(GtkRcStyle *style);
private:

View File

@@ -65,6 +65,9 @@ public:
// --------------
protected:
virtual bool GTKWidgetNeedsMnemonic() const;
virtual void GTKWidgetDoSetMnemonic(GtkWidget* w);
virtual void DoSetSize(int x, int y,
int width, int height,
int sizeFlags = wxSIZE_AUTO);

View File

@@ -156,6 +156,13 @@ public:
virtual bool IsOwnGtkWindow( GdkWindow *window );
void ConnectWidget( GtkWidget *widget );
// Override GTKWidgetNeedsMnemonic and return true if your
// needs to set its mnemonic widget, such as for a
// GtkLabel for wxStaticText, then do the actual
// setting of the widget inside GTKWidgetDoSetMnemonic
virtual bool GTKWidgetNeedsMnemonic() const;
virtual void GTKWidgetDoSetMnemonic(GtkWidget* w);
// Returns the default context which usually is anti-aliased
PangoContext *GtkGetPangoDefaultContext();

View File

@@ -66,7 +66,6 @@ wxSize wxControl::DoGetBestSize() const
return best;
}
void wxControl::PostCreation(const wxSize& size)
{
wxWindow::PostCreation();
@@ -110,22 +109,54 @@ void wxControl::GTKSetLabelForLabel(GtkLabel *w, const wxString& label)
gtk_label_set_text_with_mnemonic(w, wxGTK_CONV(labelGTK));
}
void wxControl::GTKSetLabelForFrame(GtkFrame *w, const wxString& label)
// ----------------------------------------------------------------------------
// GtkFrame helpers
//
// GtkFrames do in fact support mnemonics in GTK2+ but not through
// gtk_frame_set_label, rather you need to use a custom label widget
// instead (idea gleaned from the native gtk font dialog code in GTK)
// ----------------------------------------------------------------------------
GtkWidget* wxControl::GTKCreateFrame(const wxString& label)
{
wxControl::SetLabel(label);
const wxString labelGTK = GTKConvertMnemonics(label);
GtkWidget* labelwidget = gtk_label_new_with_mnemonic(wxGTK_CONV(labelGTK));
gtk_widget_show(labelwidget); // without this it won't show...
// frames don't support mnemonics even under GTK+ 2
const wxString labelGTK = GTKRemoveMnemonics(label);
GtkWidget* framewidget = gtk_frame_new(NULL);
gtk_frame_set_label_widget(GTK_FRAME(framewidget), labelwidget);
gtk_frame_set_label(w, labelGTK.empty() ? (char *)NULL
: wxGTK_CONV(labelGTK));
return framewidget; //note that the label is already set so you'll
//only need to call wxControl::SetLabel afterwards
}
void wxControl::GTKSetLabelForFrame(GtkFrame *w, const wxString& label)
{
GtkLabel* labelwidget = GTK_LABEL(gtk_frame_get_label_widget(w));
GTKSetLabelForLabel(labelwidget, label);
}
void wxControl::GTKFrameApplyWidgetStyle(GtkFrame* w, GtkRcStyle* style)
{
gtk_widget_modify_style(GTK_WIDGET(w), style);
gtk_widget_modify_style(gtk_frame_get_label_widget (w), style);
}
void wxControl::GTKFrameSetMnemonicWidget(GtkFrame* w, GtkWidget* widget)
{
GtkLabel* labelwidget = GTK_LABEL(gtk_frame_get_label_widget(w));
gtk_label_set_mnemonic_widget(labelwidget, widget);
}
// ----------------------------------------------------------------------------
// 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
{
MNEMONICS_REMOVE,

View File

@@ -205,8 +205,8 @@ bool wxRadioBox::Create( wxWindow *parent, wxWindowID id, const wxString& title,
return false;
}
m_widget = gtk_frame_new(NULL);
SetLabel(title);
m_widget = GTKCreateFrame(title);
wxControl::SetLabel(title);
// majorDim may be 0 if all trailing parameters were omitted, so don't
// assert here but just use the correct value for it
@@ -530,8 +530,7 @@ void wxRadioBox::GtkEnableEvents()
void wxRadioBox::DoApplyWidgetStyle(GtkRcStyle *style)
{
gtk_widget_modify_style( m_widget, style );
gtk_widget_modify_style(GTK_FRAME(m_widget)->label_widget, style);
GTKFrameApplyWidgetStyle(GTK_FRAME(m_widget), style);
wxList::compatibility_iterator node = m_boxes.GetFirst();
while (node)
@@ -545,6 +544,16 @@ void wxRadioBox::DoApplyWidgetStyle(GtkRcStyle *style)
}
}
bool wxRadioBox::GTKWidgetNeedsMnemonic() const
{
return true;
}
void wxRadioBox::GTKWidgetDoSetMnemonic(GtkWidget* w)
{
GTKFrameSetMnemonicWidget(GTK_FRAME(m_widget), w);
}
#if wxUSE_TOOLTIPS
void wxRadioBox::ApplyToolTip( GtkTooltips *tips, const wxChar *tip )
{

View File

@@ -56,8 +56,8 @@ bool wxStaticBox::Create( wxWindow *parent,
return FALSE;
}
m_widget = gtk_frame_new(NULL);
SetLabel(label);
m_widget = GTKCreateFrame(label);
wxControl::SetLabel(label);
m_parent->DoAddChild( this );
@@ -87,8 +87,17 @@ void wxStaticBox::SetLabel( const wxString& label )
void wxStaticBox::DoApplyWidgetStyle(GtkRcStyle *style)
{
gtk_widget_modify_style(m_widget, style);
gtk_widget_modify_style(GTK_FRAME(m_widget)->label_widget, style);
GTKFrameApplyWidgetStyle(GTK_FRAME(m_widget), style);
}
bool wxStaticBox::GTKWidgetNeedsMnemonic() const
{
return true;
}
void wxStaticBox::GTKWidgetDoSetMnemonic(GtkWidget* w)
{
GTKFrameSetMnemonicWidget(GTK_FRAME(m_widget), w);
}
// static

View File

@@ -166,6 +166,16 @@ bool wxStaticText::SetForegroundColour(const wxColour& colour)
return true;
}
bool wxStaticText::GTKWidgetNeedsMnemonic() const
{
return true;
}
void wxStaticText::GTKWidgetDoSetMnemonic(GtkWidget* w)
{
gtk_label_set_mnemonic_widget(GTK_LABEL(m_widget), w);
}
// static
wxVisualAttributes
wxStaticText::GetClassDefaultAttributes(wxWindowVariant WXUNUSED(variant))

View File

@@ -50,7 +50,6 @@
#include "wx/settings.h"
#include "wx/log.h"
#include "wx/fontutil.h"
#include "wx/stattext.h"
#ifdef __WXDEBUG__
#include "wx/thread.h"
@@ -3606,44 +3605,62 @@ void wxWindowGTK::DoMoveInTabOrder(wxWindow *win, MoveKind move)
wxapp_install_idle_handler();
}
bool wxWindowGTK::GTKWidgetNeedsMnemonic() const
{
// none needed by default
return false;
}
void wxWindowGTK::GTKWidgetDoSetMnemonic(GtkWidget* WXUNUSED(w))
{
// nothing to do by default since none is needed
}
void wxWindowGTK::RealizeTabOrder()
{
if (m_wxwindow)
{
if ( !m_children.empty() )
{
#if wxUSE_STATTEXT
// we don't only construct the correct focus chain but also use
// this opportunity to update the mnemonic widgets for all labels
//
// it would be nice to extract this code from here and put it in
// stattext.cpp to reduce dependencies but there is no really easy
// way to do it unfortunately
wxStaticText *lastLabel = NULL;
#endif // wxUSE_STATTEXT
// this opportunity to update the mnemonic widgets for the widgets
// that need them
GList *chain = NULL;
wxWindowGTK* mnemonicWindow = NULL;
for ( wxWindowList::const_iterator i = m_children.begin();
i != m_children.end();
++i )
{
wxWindowGTK *win = *i;
#if wxUSE_STATTEXT
if ( lastLabel )
if ( mnemonicWindow )
{
if ( win->AcceptsFocusFromKeyboard() )
{
GtkLabel *l = GTK_LABEL(lastLabel->m_widget);
gtk_label_set_mnemonic_widget(l, win->m_widget);
lastLabel = NULL;
}
}
else // check if this one is a label
// wxComboBox et al. needs to focus on on a different
// widget than m_widget, so if the main widget isn't
// focusable try the connect widget
GtkWidget* w = win->m_widget;
if ( !GTK_WIDGET_CAN_FOCUS(w) )
{
lastLabel = wxDynamicCast(win, wxStaticText);
w = win->GetConnectWidget();
if ( !GTK_WIDGET_CAN_FOCUS(w) )
w = NULL;
}
if ( w )
{
mnemonicWindow->GTKWidgetDoSetMnemonic(w);
mnemonicWindow = NULL;
}
}
}
else if ( win->GTKWidgetNeedsMnemonic() )
{
mnemonicWindow = win;
}
#endif // wxUSE_STATTEXT
chain = g_list_prepend(chain, win->m_widget);
}