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.\ --enable-gstreamer8 to force configure to check for GStreamer 0.8.\
- Fixed problem with choice editor in wxGrid whereby the editor - Fixed problem with choice editor in wxGrid whereby the editor
lost focus when the combobox menu was shown. 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 - Fixed problem trying to print from a preview, whereby wrong printer
class was used. class was used.
- Worked around pango crashes in strncmp on Solaris 10. - 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 // sets the label to the given string and also sets it for the given widget
void GTKSetLabelForLabel(GtkLabel *w, const wxString& label); 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 GTKSetLabelForFrame(GtkFrame *w, const wxString& label);
void GTKFrameApplyWidgetStyle(GtkFrame* w, GtkRcStyle* rc);
void GTKFrameSetMnemonicWidget(GtkFrame* w, GtkWidget* widget);
// remove mnemonics ("&"s) from the label // remove mnemonics ("&"s) from the label
static wxString GTKRemoveMnemonics(const wxString& label); static wxString GTKRemoveMnemonics(const wxString& label);

View File

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

View File

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

View File

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

View File

@@ -156,6 +156,13 @@ public:
virtual bool IsOwnGtkWindow( GdkWindow *window ); virtual bool IsOwnGtkWindow( GdkWindow *window );
void ConnectWidget( GtkWidget *widget ); 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 // Returns the default context which usually is anti-aliased
PangoContext *GtkGetPangoDefaultContext(); PangoContext *GtkGetPangoDefaultContext();

View File

@@ -66,7 +66,6 @@ wxSize wxControl::DoGetBestSize() const
return best; return best;
} }
void wxControl::PostCreation(const wxSize& size) void wxControl::PostCreation(const wxSize& size)
{ {
wxWindow::PostCreation(); wxWindow::PostCreation();
@@ -110,22 +109,54 @@ void wxControl::GTKSetLabelForLabel(GtkLabel *w, const wxString& label)
gtk_label_set_text_with_mnemonic(w, wxGTK_CONV(labelGTK)); 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 GtkWidget* framewidget = gtk_frame_new(NULL);
const wxString labelGTK = GTKRemoveMnemonics(label); gtk_frame_set_label_widget(GTK_FRAME(framewidget), labelwidget);
gtk_frame_set_label(w, labelGTK.empty() ? (char *)NULL return framewidget; //note that the label is already set so you'll
: wxGTK_CONV(labelGTK)); //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() // worker function implementing both GTKConvert/RemoveMnemonics()
// //
// notice that under GTK+ 1 we only really need to support MNEMONICS_REMOVE as // 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 // 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 // that we do the same thing for GKT+ 1 and 2
// ----------------------------------------------------------------------------
enum MnemonicsFlag enum MnemonicsFlag
{ {
MNEMONICS_REMOVE, MNEMONICS_REMOVE,

View File

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

View File

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

View File

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

View File

@@ -50,7 +50,6 @@
#include "wx/settings.h" #include "wx/settings.h"
#include "wx/log.h" #include "wx/log.h"
#include "wx/fontutil.h" #include "wx/fontutil.h"
#include "wx/stattext.h"
#ifdef __WXDEBUG__ #ifdef __WXDEBUG__
#include "wx/thread.h" #include "wx/thread.h"
@@ -3606,44 +3605,62 @@ void wxWindowGTK::DoMoveInTabOrder(wxWindow *win, MoveKind move)
wxapp_install_idle_handler(); 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() void wxWindowGTK::RealizeTabOrder()
{ {
if (m_wxwindow) if (m_wxwindow)
{ {
if ( !m_children.empty() ) if ( !m_children.empty() )
{ {
#if wxUSE_STATTEXT
// we don't only construct the correct focus chain but also use // we don't only construct the correct focus chain but also use
// this opportunity to update the mnemonic widgets for all labels // this opportunity to update the mnemonic widgets for the widgets
// // that need them
// 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
GList *chain = NULL; GList *chain = NULL;
wxWindowGTK* mnemonicWindow = NULL;
for ( wxWindowList::const_iterator i = m_children.begin(); for ( wxWindowList::const_iterator i = m_children.begin();
i != m_children.end(); i != m_children.end();
++i ) ++i )
{ {
wxWindowGTK *win = *i; wxWindowGTK *win = *i;
#if wxUSE_STATTEXT
if ( lastLabel ) if ( mnemonicWindow )
{ {
if ( win->AcceptsFocusFromKeyboard() ) if ( win->AcceptsFocusFromKeyboard() )
{ {
GtkLabel *l = GTK_LABEL(lastLabel->m_widget); // wxComboBox et al. needs to focus on on a different
gtk_label_set_mnemonic_widget(l, win->m_widget); // widget than m_widget, so if the main widget isn't
lastLabel = NULL; // focusable try the connect widget
} GtkWidget* w = win->m_widget;
} if ( !GTK_WIDGET_CAN_FOCUS(w) )
else // check if this one is a label
{ {
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); chain = g_list_prepend(chain, win->m_widget);
} }