Kirix Support Forums

wxAUI keyboard navigation: wxSwitcherDialog

Please post any wxAUI patches or modifications you've created here. Thanks!

wxAUI keyboard navigation: wxSwitcherDialog

Postby Julian Smart on Thu Aug 23, 2007 8:40 am

Hi,

As prompted by a bug report about the lack of keyboard navigation in wxAUI, here's a class that can help a bit (though we should still strive for 'native' navigation through all the windows in an app).

Screenshot:
http://www.anthemion.co.uk/wxwin/switch ... indows.jpg

Code and Windows binary of the wxAUI demo app (press Ctrl+Tab):
http://www.anthemion.co.uk/wxwin/switcher.zip

Readme:
http://www.anthemion.co.uk/wxwin/readme.txt

I'll include the readme below. It's a general-purpose class but can very easily be used for wxAUI applications. Perhaps it's something that we should think of including in wxWidgets 2.9/3 if we don't have another built-in method of navigating around wxAUI panes.

BTW you can also see this class in action in DialogBlocks 4.15 (Windows, Linux, Solaris, FreeBSD and Mac).

Regards,

Julian


wxSwitcherDialog
==========================

Julian Smart, August 2007

Overview
========

The idea of wxSwitcherDialog is to make it easier to implement keyboard
navigation in wxAUI and other applications that have multiple panes and
tabs.

A key combination with a modifier (such as Ctrl+Tab) shows the dialog, and
the user holds down the modifier whilst navigating with Tab and arrow keys before
releasing the modifier to dismiss the dialog and activate the selected pane.

The switcher dialog is a multi-column menu with no scrolling, implemented
by the wxMultiColumnListCtrl class. You can have headings for your items
for logical grouping, and you can force a column break if you need to.

The modifier used for invoking and dismissing the dialog can be customised,
as can the colours, number of rows, and the key used for cycling through
the items. So you can use different keys on different platforms if
required (especially since Ctrl+Tab is reserved on some platforms).

Items are shown as names and optional 16x16 images.

Using wxSwitcherDialog
======================

To use the dialog, you set up the items in a wxSwitcherItems object,
before passing this to the wxSwitcherDialog instance.

Call AddItem and optionally AddGroup to add items and headings. These
functions take a label (to be displayed to the user, an identifying name,
an integer id, and a bitmap. The name and id are purely for application-defined
identification. You may also set a description to be displayed when each
item is selected; and you can set a window pointer for convenience when
activating the desired window after the dialog returns.

Have created the dialog, you call ShowModal(), and if the return value is
wxID_OK, retrieve the selection from the dialog and activate the pane.

The sample code below shows a generic method of finding panes and notebook
tabs within the current wxAuiManager, and using the pane name or
notebook tab position to display the pane.

The only other code to add is a menu item with the desired accelerator,
whose modifier matches the one you pass to wxSwitcherDialog::SetModifierKey
(the default being WXK_CONTROL).

wxAUI Example
=============

Menu item:
----------
Code: Select all
#if defined(__WXMAC__)
    wxString switcherAccel = wxT("Alt+Tab");
#elif defined(__WXGTK__)
    wxString switcherAccel = wxT("Ctrl+/");
#else
    wxString switcherAccel = wxT("Ctrl+Tab");
#endif

    view_menu->Append(ID_SwitchPane, wxString(_("S&witch Window...")) + wxT("\t") + switcherAccel);


Event handler:
--------------

Code: Select all
void MyFrame::OnSwitchPane(wxCommandEvent& WXUNUSED(evt))
{
    wxSwitcherItems items;
    items.SetRowCount(12);

    // Add the main windows and toolbars, in two separate columns

    // We'll use the item 'id' to store the notebook selection, or -1 if not a page

    size_t i;
    size_t k;
    for (k = 0; k < 2; k++)
    {
        if (k == 0)
            items.AddGroup(_("Main Windows"), wxT("mainwindows"));
        else
            items.AddGroup(_("Toolbars"), wxT("toolbars")).BreakColumn();

        for (i = 0; i < m_mgr.GetAllPanes().GetCount(); i++)
        {
            wxAuiPaneInfo& info = m_mgr.GetAllPanes()[i];

            wxString name = info.name;
            wxString caption = info.caption;

            wxToolBar* toolBar = wxDynamicCast(info.window, wxToolBar);

            if (!caption.IsEmpty() && ((toolBar != NULL && k == 1) || (toolBar == NULL && k == 0)))
            {
                items.AddItem(caption, name, -1).SetWindow(toolBar);
            }
        }
    }

    // Now add the wxAuiNotebook pages

    items.AddGroup(_("Notebook Pages"), wxT("pages")).BreakColumn();

    for (i = 0; i < m_mgr.GetAllPanes().GetCount(); i++)
    {
        wxAuiPaneInfo& info = m_mgr.GetAllPanes()[i];

        wxAuiNotebook* nb = wxDynamicCast(info.window, wxAuiNotebook);
        if (nb)
        {
            size_t j;
            for (j = 0; j < nb->GetPageCount(); j++)
            {
                wxString name = nb->GetPageText(j);
                wxWindow* win = nb->GetPage(j);

                items.AddItem(name, name, j, nb->GetPageBitmap(j)).SetWindow(win);
            }
        }
    }

    // Select the focused window

    int idx = items.GetIndexForFocus();
    if (idx != wxNOT_FOUND)
        items.SetSelection(idx);

#ifdef __WXMAC__
    items.SetBackgroundColour(*wxWHITE);
#endif
   
    // Show the switcher dialog

    wxSwitcherDialog dlg(items, wxGetApp().GetTopWindow());

    // In GTK+ we can't use Ctrl+Tab; we use Ctrl+/ instead and tell the switcher
    // to treat / in the same was as tab (i.e. cycle through the names)

#ifdef __WXGTK__
    dlg.SetExtraNavigationKey(wxT('/'));
#endif

#ifdef __WXMAC__
    dlg.SetBackgroundColour(*wxWHITE);
    dlg.SetModifierKey(WXK_ALT);
#endif

    int ans = dlg.ShowModal();

    if (ans == wxID_OK && dlg.GetSelection() != -1)
    {
        wxSwitcherItem& item = items.GetItem(dlg.GetSelection());

        if (item.GetId() == -1)
        {
            wxAuiPaneInfo& info = m_mgr.GetPane(item.GetName());
            info.Show();
            m_mgr.Update();
            info.window->SetFocus();
        }
        else
        {
            wxAuiNotebook* nb = wxDynamicCast(item.GetWindow()->GetParent(), wxAuiNotebook);
            wxWindow* win = item.GetWindow();
            if (nb)
            {
                nb->SetSelection(item.GetId());
                win->SetFocus();
            }
        }
    }
}
Julian Smart
Registered User
 
Posts: 17
Joined: Sun Nov 05, 2006 4:45 pm

Return to wxAUI Patches & Modifications