diff --git a/include/wx/gtk/menuitem.h b/include/wx/gtk/menuitem.h index e84a48500c..0575a81dab 100644 --- a/include/wx/gtk/menuitem.h +++ b/include/wx/gtk/menuitem.h @@ -73,6 +73,8 @@ public: // implementation void SetMenuItem(GtkWidget *menuItem) { m_menuItem = menuItem; } GtkWidget *GetMenuItem() const { return m_menuItem; } + + wxString GetHotKey() const { return m_hotKey; } void SetCheckedFlag(bool checked) { m_isChecked = checked; } bool GetCheckedFlag() const { return m_isChecked; } @@ -80,6 +82,7 @@ public: private: int m_id; wxString m_text; + wxString m_hotKey; bool m_isCheckMenu; bool m_isChecked; bool m_isEnabled; diff --git a/include/wx/gtk1/menuitem.h b/include/wx/gtk1/menuitem.h index e84a48500c..0575a81dab 100644 --- a/include/wx/gtk1/menuitem.h +++ b/include/wx/gtk1/menuitem.h @@ -73,6 +73,8 @@ public: // implementation void SetMenuItem(GtkWidget *menuItem) { m_menuItem = menuItem; } GtkWidget *GetMenuItem() const { return m_menuItem; } + + wxString GetHotKey() const { return m_hotKey; } void SetCheckedFlag(bool checked) { m_isChecked = checked; } bool GetCheckedFlag() const { return m_isChecked; } @@ -80,6 +82,7 @@ public: private: int m_id; wxString m_text; + wxString m_hotKey; bool m_isCheckMenu; bool m_isChecked; bool m_isEnabled; diff --git a/samples/controls/controls.cpp b/samples/controls/controls.cpp index 21de316c79..895095231a 100644 --- a/samples/controls/controls.cpp +++ b/samples/controls/controls.cpp @@ -506,7 +506,7 @@ m_text(NULL), m_notebook(NULL) (*m_multitext) << " Appended."; m_multitext->SetInsertionPoint(0); m_multitext->WriteText( "Prepended. " ); - m_multitext->AppendText( "\nPress function keys to test different wxTextCtrl functions." ); + m_multitext->AppendText( "\nPress function keys for test different tests." ); (*m_multitext) << "\nDoes it have cross cursor?"; m_multitext->SetCursor(*wxCROSS_CURSOR); diff --git a/samples/minimal/minimal.cpp b/samples/minimal/minimal.cpp index 9e0758f642..8db65d0ad9 100644 --- a/samples/minimal/minimal.cpp +++ b/samples/minimal/minimal.cpp @@ -151,9 +151,9 @@ MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size) // create a menu bar wxMenu *menuFile = new wxMenu; - menuFile->Append(Minimal_About, "&About...", "Show about dialog"); + menuFile->Append(Minimal_About, "&About...\tCtrl-A", "Show about dialog"); menuFile->AppendSeparator(); - menuFile->Append(Minimal_Quit, "E&xit", "Quit this program"); + menuFile->Append(Minimal_Quit, "E&xit\tAlt-X", "Quit this program"); // now append the freshly created menu to the menu bar... wxMenuBar *menuBar = new wxMenuBar; diff --git a/src/gtk/frame.cpp b/src/gtk/frame.cpp index 459043b402..987b75e89e 100644 --- a/src/gtk/frame.cpp +++ b/src/gtk/frame.cpp @@ -769,16 +769,16 @@ void wxFrame::OnSize( wxSizeEvent &WXUNUSED(event) ) } else { - // do we have exactly one child? + /* do we have exactly one child? */ wxWindow *child = (wxWindow *)NULL; for ( wxNode *node = GetChildren().First(); node; node = node->Next() ) { wxWindow *win = (wxWindow *)node->Data(); if ( !wxIS_KIND_OF(win,wxFrame) && !wxIS_KIND_OF(win,wxDialog) ) { - if ( child ) + if (child) { - // it's the second one: do nothing + /* it's the second one: do nothing */ return; } @@ -786,10 +786,10 @@ void wxFrame::OnSize( wxSizeEvent &WXUNUSED(event) ) } } - // no children at all? - if ( child ) + /* no children at all? */ + if (child) { - // yes: set it's size to fill all the frame + /* yes: set it's size to fill all the frame */ int client_x, client_y; GetClientSize( &client_x, &client_y ); child->SetSize( 1, 1, client_x-2, client_y-2 ); @@ -800,6 +800,12 @@ void wxFrame::OnSize( wxSizeEvent &WXUNUSED(event) ) static void SetInvokingWindow( wxMenu *menu, wxWindow *win ) { menu->SetInvokingWindow( win ); + +#if (GTK_MINOR_VERSION > 0) + /* support for native hot keys */ + gtk_accel_group_attach( menu->m_accel, GTK_OBJECT(win->m_widget)); +#endif + wxNode *node = menu->GetItems().First(); while (node) { @@ -819,8 +825,8 @@ void wxFrame::SetMenuBar( wxMenuBar *menuBar ) if (m_frameMenuBar) { - /* support for native key accelerators indicated by underscroes */ #if (GTK_MINOR_VERSION > 0) && (GTK_MICRO_VERSION > 0) + /* support for native key accelerators indicated by underscroes */ gtk_accel_group_attach( m_frameMenuBar->m_accel, GTK_OBJECT(m_widget)); #endif diff --git a/src/gtk/menu.cpp b/src/gtk/menu.cpp index 56ddd5ac50..b66fc7b9fb 100644 --- a/src/gtk/menu.cpp +++ b/src/gtk/menu.cpp @@ -474,8 +474,10 @@ wxMenuItem::wxMenuItem() // it's valid for this function to be called even if m_menuItem == NULL void wxMenuItem::SetName( const wxString& str ) { + /* '\t' is the deliminator indicating a hot key */ m_text = _T(""); - for ( const wxChar *pc = str; *pc != _T('\0'); pc++ ) + const wxChar *pc = str; + for (; (*pc != _T('\0')) && (*pc != _T('\t')); pc++ ) { if (*pc == _T('&')) { @@ -486,6 +488,13 @@ void wxMenuItem::SetName( const wxString& str ) else m_text << *pc; } + + /* only GTK 1.2 know about hot keys */ + m_hotKey = _T(""); +#if (GTK_MINOR_VERSION > 0) + pc++; + m_hotKey = pc; +#endif if (m_menuItem) { @@ -607,7 +616,6 @@ void wxMenu::Append( int id, const wxString &item, const wxString &helpStr, bool GtkItemFactoryEntry entry; entry.path = buf; - entry.accelerator = (gchar*) NULL; entry.callback = (GtkItemFactoryCallback) gtk_menu_clicked_callback; entry.callback_action = 0; if (checkable) @@ -615,12 +623,48 @@ void wxMenu::Append( int id, const wxString &item, const wxString &helpStr, bool else entry.item_type = ""; + entry.accelerator = (gchar*) NULL; + char hotbuf[50]; + wxString hotkey( mitem->GetHotKey() ); + if (!hotkey.IsEmpty()) + { + switch (hotkey[0]) + { + case _T('a'): /* Alt */ + case _T('A'): + case _T('m'): /* Meta */ + case _T('M'): + { + strcpy( hotbuf, "" ); + wxString last = hotkey.Right(1); + strcat( hotbuf, last.mb_str() ); + entry.accelerator = hotbuf; + break; + } + case _T('c'): /* Ctrl */ + case _T('C'): + case _T('s'): /* Strg, yeah man, I'm German */ + case _T('S'): + { + strcpy( hotbuf, "" ); + wxString last = hotkey.Right(1); + strcat( hotbuf, last.mb_str() ); + entry.accelerator = hotbuf; + break; + } + default: + { + } + } + } + gtk_item_factory_create_item( m_factory, &entry, (gpointer) this, 2 ); /* what is 2 ? */ /* in order to get the pointer to the item we need the item text _without_ underscores */ wxString s = _T("
/"); for ( const wxChar *pc = text; *pc != _T('\0'); pc++ ) { + if (*pc == _T('\t')) break; if (*pc == _T('_')) pc++; /* skip it */ s << *pc; } diff --git a/src/gtk/textctrl.cpp b/src/gtk/textctrl.cpp index 4969acb19f..cd52a4dc49 100644 --- a/src/gtk/textctrl.cpp +++ b/src/gtk/textctrl.cpp @@ -65,9 +65,9 @@ gtk_scrollbar_changed_callback( GtkWidget *WXUNUSED(widget), wxTextCtrl *win ) { if (g_isIdle) wxapp_install_idle_handler(); - if (!win->m_hasVMT) return; - win->CalculateScrollbar(); + + if (!win->m_hasVMT) return; } //----------------------------------------------------------------------------- @@ -140,7 +140,7 @@ bool wxTextCtrl::Create( wxWindow *parent, wxWindowID id, const wxString &value, m_vScrollbarVisible = FALSE; bool multi_line = (style & wxTE_MULTILINE) != 0; - if ( multi_line ) + if (multi_line) { /* a multi-line edit control: create a vertical scrollbar by default and horizontal if requested */ @@ -171,9 +171,14 @@ bool wxTextCtrl::Create( wxWindow *parent, wxWindowID id, const wxString &value, gtk_widget_show(hscrollbar); } - /* we create the vertical scrollbar on demand */ - m_vScrollbar = (GtkWidget*) NULL; - + /* finally, put the vertical scrollbar in the upper right corner */ + m_vScrollbar = gtk_vscrollbar_new( GTK_TEXT(m_text)->vadj ); + GTK_WIDGET_UNSET_FLAGS( m_vScrollbar, GTK_CAN_FOCUS ); + + gtk_table_attach(GTK_TABLE(m_widget), m_vScrollbar, 1, 2, 0, 1, + GTK_FILL, + (GtkAttachOptions)(GTK_EXPAND | GTK_FILL | GTK_SHRINK), + 0, 0); } else { @@ -194,15 +199,18 @@ bool wxTextCtrl::Create( wxWindow *parent, wxWindowID id, const wxString &value, PostCreation(); if (multi_line) - { -// gtk_widget_realize(m_text); gtk_widget_show(m_text); - } /* we want to be notified about text changes */ gtk_signal_connect( GTK_OBJECT(m_text), "changed", GTK_SIGNAL_FUNC(gtk_text_changed_callback), (gpointer)this); + if (multi_line) + { + gtk_signal_connect(GTK_OBJECT(GTK_TEXT(m_text)->vadj), "changed", + (GtkSignalFunc) gtk_scrollbar_changed_callback, (gpointer) this ); + } + if (!value.IsEmpty()) { gint tmp = 0; @@ -243,12 +251,6 @@ bool wxTextCtrl::Create( wxWindow *parent, wxWindowID id, const wxString &value, Show( TRUE ); - if (multi_line) - { - gtk_signal_connect(GTK_OBJECT(GTK_TEXT(m_text)->vadj), "changed", - (GtkSignalFunc) gtk_scrollbar_changed_callback, (gpointer) this ); - } - return TRUE; } @@ -271,18 +273,6 @@ void wxTextCtrl::CalculateScrollbar() { if (!m_vScrollbarVisible) { - if (!m_vScrollbar) - { - /* finally, put the vertical scrollbar in the upper right corner */ - m_vScrollbar = gtk_vscrollbar_new( GTK_TEXT(m_text)->vadj ); - GTK_WIDGET_UNSET_FLAGS( m_vScrollbar, GTK_CAN_FOCUS ); - - gtk_table_attach(GTK_TABLE(m_widget), m_vScrollbar, 1, 2, 0, 1, - GTK_FILL, - (GtkAttachOptions)(GTK_EXPAND | GTK_FILL | GTK_SHRINK), - 0, 0); - } - gtk_widget_show( m_vScrollbar ); m_vScrollbarVisible = TRUE; diff --git a/src/gtk1/frame.cpp b/src/gtk1/frame.cpp index 459043b402..987b75e89e 100644 --- a/src/gtk1/frame.cpp +++ b/src/gtk1/frame.cpp @@ -769,16 +769,16 @@ void wxFrame::OnSize( wxSizeEvent &WXUNUSED(event) ) } else { - // do we have exactly one child? + /* do we have exactly one child? */ wxWindow *child = (wxWindow *)NULL; for ( wxNode *node = GetChildren().First(); node; node = node->Next() ) { wxWindow *win = (wxWindow *)node->Data(); if ( !wxIS_KIND_OF(win,wxFrame) && !wxIS_KIND_OF(win,wxDialog) ) { - if ( child ) + if (child) { - // it's the second one: do nothing + /* it's the second one: do nothing */ return; } @@ -786,10 +786,10 @@ void wxFrame::OnSize( wxSizeEvent &WXUNUSED(event) ) } } - // no children at all? - if ( child ) + /* no children at all? */ + if (child) { - // yes: set it's size to fill all the frame + /* yes: set it's size to fill all the frame */ int client_x, client_y; GetClientSize( &client_x, &client_y ); child->SetSize( 1, 1, client_x-2, client_y-2 ); @@ -800,6 +800,12 @@ void wxFrame::OnSize( wxSizeEvent &WXUNUSED(event) ) static void SetInvokingWindow( wxMenu *menu, wxWindow *win ) { menu->SetInvokingWindow( win ); + +#if (GTK_MINOR_VERSION > 0) + /* support for native hot keys */ + gtk_accel_group_attach( menu->m_accel, GTK_OBJECT(win->m_widget)); +#endif + wxNode *node = menu->GetItems().First(); while (node) { @@ -819,8 +825,8 @@ void wxFrame::SetMenuBar( wxMenuBar *menuBar ) if (m_frameMenuBar) { - /* support for native key accelerators indicated by underscroes */ #if (GTK_MINOR_VERSION > 0) && (GTK_MICRO_VERSION > 0) + /* support for native key accelerators indicated by underscroes */ gtk_accel_group_attach( m_frameMenuBar->m_accel, GTK_OBJECT(m_widget)); #endif diff --git a/src/gtk1/menu.cpp b/src/gtk1/menu.cpp index 56ddd5ac50..b66fc7b9fb 100644 --- a/src/gtk1/menu.cpp +++ b/src/gtk1/menu.cpp @@ -474,8 +474,10 @@ wxMenuItem::wxMenuItem() // it's valid for this function to be called even if m_menuItem == NULL void wxMenuItem::SetName( const wxString& str ) { + /* '\t' is the deliminator indicating a hot key */ m_text = _T(""); - for ( const wxChar *pc = str; *pc != _T('\0'); pc++ ) + const wxChar *pc = str; + for (; (*pc != _T('\0')) && (*pc != _T('\t')); pc++ ) { if (*pc == _T('&')) { @@ -486,6 +488,13 @@ void wxMenuItem::SetName( const wxString& str ) else m_text << *pc; } + + /* only GTK 1.2 know about hot keys */ + m_hotKey = _T(""); +#if (GTK_MINOR_VERSION > 0) + pc++; + m_hotKey = pc; +#endif if (m_menuItem) { @@ -607,7 +616,6 @@ void wxMenu::Append( int id, const wxString &item, const wxString &helpStr, bool GtkItemFactoryEntry entry; entry.path = buf; - entry.accelerator = (gchar*) NULL; entry.callback = (GtkItemFactoryCallback) gtk_menu_clicked_callback; entry.callback_action = 0; if (checkable) @@ -615,12 +623,48 @@ void wxMenu::Append( int id, const wxString &item, const wxString &helpStr, bool else entry.item_type = ""; + entry.accelerator = (gchar*) NULL; + char hotbuf[50]; + wxString hotkey( mitem->GetHotKey() ); + if (!hotkey.IsEmpty()) + { + switch (hotkey[0]) + { + case _T('a'): /* Alt */ + case _T('A'): + case _T('m'): /* Meta */ + case _T('M'): + { + strcpy( hotbuf, "" ); + wxString last = hotkey.Right(1); + strcat( hotbuf, last.mb_str() ); + entry.accelerator = hotbuf; + break; + } + case _T('c'): /* Ctrl */ + case _T('C'): + case _T('s'): /* Strg, yeah man, I'm German */ + case _T('S'): + { + strcpy( hotbuf, "" ); + wxString last = hotkey.Right(1); + strcat( hotbuf, last.mb_str() ); + entry.accelerator = hotbuf; + break; + } + default: + { + } + } + } + gtk_item_factory_create_item( m_factory, &entry, (gpointer) this, 2 ); /* what is 2 ? */ /* in order to get the pointer to the item we need the item text _without_ underscores */ wxString s = _T("
/"); for ( const wxChar *pc = text; *pc != _T('\0'); pc++ ) { + if (*pc == _T('\t')) break; if (*pc == _T('_')) pc++; /* skip it */ s << *pc; } diff --git a/src/gtk1/textctrl.cpp b/src/gtk1/textctrl.cpp index 4969acb19f..cd52a4dc49 100644 --- a/src/gtk1/textctrl.cpp +++ b/src/gtk1/textctrl.cpp @@ -65,9 +65,9 @@ gtk_scrollbar_changed_callback( GtkWidget *WXUNUSED(widget), wxTextCtrl *win ) { if (g_isIdle) wxapp_install_idle_handler(); - if (!win->m_hasVMT) return; - win->CalculateScrollbar(); + + if (!win->m_hasVMT) return; } //----------------------------------------------------------------------------- @@ -140,7 +140,7 @@ bool wxTextCtrl::Create( wxWindow *parent, wxWindowID id, const wxString &value, m_vScrollbarVisible = FALSE; bool multi_line = (style & wxTE_MULTILINE) != 0; - if ( multi_line ) + if (multi_line) { /* a multi-line edit control: create a vertical scrollbar by default and horizontal if requested */ @@ -171,9 +171,14 @@ bool wxTextCtrl::Create( wxWindow *parent, wxWindowID id, const wxString &value, gtk_widget_show(hscrollbar); } - /* we create the vertical scrollbar on demand */ - m_vScrollbar = (GtkWidget*) NULL; - + /* finally, put the vertical scrollbar in the upper right corner */ + m_vScrollbar = gtk_vscrollbar_new( GTK_TEXT(m_text)->vadj ); + GTK_WIDGET_UNSET_FLAGS( m_vScrollbar, GTK_CAN_FOCUS ); + + gtk_table_attach(GTK_TABLE(m_widget), m_vScrollbar, 1, 2, 0, 1, + GTK_FILL, + (GtkAttachOptions)(GTK_EXPAND | GTK_FILL | GTK_SHRINK), + 0, 0); } else { @@ -194,15 +199,18 @@ bool wxTextCtrl::Create( wxWindow *parent, wxWindowID id, const wxString &value, PostCreation(); if (multi_line) - { -// gtk_widget_realize(m_text); gtk_widget_show(m_text); - } /* we want to be notified about text changes */ gtk_signal_connect( GTK_OBJECT(m_text), "changed", GTK_SIGNAL_FUNC(gtk_text_changed_callback), (gpointer)this); + if (multi_line) + { + gtk_signal_connect(GTK_OBJECT(GTK_TEXT(m_text)->vadj), "changed", + (GtkSignalFunc) gtk_scrollbar_changed_callback, (gpointer) this ); + } + if (!value.IsEmpty()) { gint tmp = 0; @@ -243,12 +251,6 @@ bool wxTextCtrl::Create( wxWindow *parent, wxWindowID id, const wxString &value, Show( TRUE ); - if (multi_line) - { - gtk_signal_connect(GTK_OBJECT(GTK_TEXT(m_text)->vadj), "changed", - (GtkSignalFunc) gtk_scrollbar_changed_callback, (gpointer) this ); - } - return TRUE; } @@ -271,18 +273,6 @@ void wxTextCtrl::CalculateScrollbar() { if (!m_vScrollbarVisible) { - if (!m_vScrollbar) - { - /* finally, put the vertical scrollbar in the upper right corner */ - m_vScrollbar = gtk_vscrollbar_new( GTK_TEXT(m_text)->vadj ); - GTK_WIDGET_UNSET_FLAGS( m_vScrollbar, GTK_CAN_FOCUS ); - - gtk_table_attach(GTK_TABLE(m_widget), m_vScrollbar, 1, 2, 0, 1, - GTK_FILL, - (GtkAttachOptions)(GTK_EXPAND | GTK_FILL | GTK_SHRINK), - 0, 0); - } - gtk_widget_show( m_vScrollbar ); m_vScrollbarVisible = TRUE;