| 1 | \section{wxTab classes overview}\label{wxtaboverview} |
| 2 | |
| 3 | Classes: \helpref{wxTabView}{wxtabview}, \helpref{wxPanelTabView}{wxpaneltabview}, |
| 4 | \helpref{wxTabbedPanel}{wxtabbedpanel}, \helpref{wxTabbedDialog}{wxtabbeddialog}, |
| 5 | \helpref{wxTabControl}{wxtabcontrol} |
| 6 | |
| 7 | The tab classes provides a way to display rows of tabs (like file divider tabs), which can be |
| 8 | used to switch between panels or other information. Tabs are most |
| 9 | commonly used in dialog boxes where the number of options is too great |
| 10 | to fit on one dialog. |
| 11 | |
| 12 | {\bf Please note} that the preferred class for programming tabbed windows is \helpref{wxNotebook}{wxnotebook}. |
| 13 | The old tab classes are retained for backward compatibility and also to implement |
| 14 | wxNotebook on platforms that don't have native tab controls. |
| 15 | |
| 16 | \wxheading{The appearance and behaviour of a wxTabbedDialog} |
| 17 | |
| 18 | The following screenshot shows the appearance of the sample tabbed dialog application. |
| 19 | |
| 20 | $$\image{8cm;0cm}{wxtab1.eps}$$ |
| 21 | |
| 22 | By clicking on the tabs, the user can display a different set of controls. In the example, |
| 23 | the Close and Help buttons remain constant. These two buttons are children of the main dialog box, |
| 24 | whereas the other controls are children of panels which are shown and hidden according to |
| 25 | which tab is active. |
| 26 | |
| 27 | A tabbed dialog may have several layers (rows) of tabs, each being |
| 28 | offset vertically and horizontally from the previous. Tabs work in |
| 29 | columns, in that when a tab is pressed, it swaps place with the tab on |
| 30 | the first row of the same column, in order to give the effect of |
| 31 | displaying that tab. All tabs must be of the same width. |
| 32 | This is a constraint of the implementation, but it also |
| 33 | means that the user will find it easier to find tabs since there are |
| 34 | distinct tab columns. On some tabbed dialog implementations, tabs jump around |
| 35 | seemingly randomly because tabs have different widths. |
| 36 | In this implementation, a tab can always be found on the same column. |
| 37 | |
| 38 | Tabs are always drawn along the top of the view area; the implementation does |
| 39 | not allow for vertical tabs or any other configuration. |
| 40 | |
| 41 | \wxheading{Using tabs} |
| 42 | |
| 43 | The tab classes provide facilities for switching between contexts by |
| 44 | means of `tabs', which look like file divider tabs. |
| 45 | |
| 46 | You must create both a {\it view} to handle the tabs, and a {\it window} to display the tabs |
| 47 | and related information. The wxTabbedDialog and wxTabbedPanel classes are provided for |
| 48 | convenience, but you could equally well construct your own window class and derived |
| 49 | tab view. |
| 50 | |
| 51 | If you wish to display a tabbed dialog - the most common use - you should follow these steps. |
| 52 | |
| 53 | \begin{enumerate}\itemsep=0pt |
| 54 | \item Create a new wxTabbedDialog class, and any buttons you wish always to be displayed |
| 55 | (regardless of which tab is active). |
| 56 | \item Create a new wxPanelTabView, passing the dialog as the first argument. |
| 57 | \item Set the view rectangle with \helpref{wxTabView::SetViewRect}{wxtabviewsetviewrect}, |
| 58 | to specify the area in which child panels will be |
| 59 | shown. The tabs will sit on top of this view rectangle. |
| 60 | \item Call \helpref{wxTabView::CalculateTabWidth}{wxtabviewcalculatetabwidth} to calculate |
| 61 | the width of the tabs based on the view area. This is optional if, for example, you have one row |
| 62 | of tabs which does not extend the full width of the view area. |
| 63 | \item Call \helpref{wxTabView::AddTab}{wxtabviewaddtab} for each of the tabs you wish to create, passing |
| 64 | a unique identifier and a tab label. |
| 65 | \item Construct a number of windows, one for each tab, and call \helpref{wxPanelTabView::AddTabWindow}{wxpaneltabviewaddtabwindow} for |
| 66 | each of these, passing a tab identifier and the window. |
| 67 | \item Set the tab selection. |
| 68 | \item Show the dialog. |
| 69 | \end{enumerate} |
| 70 | |
| 71 | Under Motif, you may also need to size the dialog just before setting the tab selection, for unknown reasons. |
| 72 | |
| 73 | Some constraints you need to be aware of: |
| 74 | |
| 75 | \begin{itemize}\itemsep=0pt |
| 76 | \item All tabs must be of the same width. |
| 77 | \item Omit the wxTAB\_STYLE\_COLOUR\_INTERIOR flag to ensure that the dialog background |
| 78 | and tab backgrounds match. |
| 79 | \end{itemize} |
| 80 | |
| 81 | \subsection{Example} |
| 82 | |
| 83 | The following fragment is taken from the file test.cpp. |
| 84 | |
| 85 | {\small |
| 86 | \begin{verbatim} |
| 87 | void MyDialog::Init(void) |
| 88 | { |
| 89 | int dialogWidth = 365; |
| 90 | int dialogHeight = 390; |
| 91 | |
| 92 | wxButton *okButton = new wxButton(this, wxID_OK, "Close", wxPoint(100, 330), wxSize(80, 25)); |
| 93 | wxButton *cancelButton = new wxButton(this, wxID_CANCEL, "Cancel", wxPoint(185, 330), wxSize(80, 25)); |
| 94 | wxButton *HelpButton = new wxButton(this, wxID_HELP, "Help", wxPoint(270, 330), wxSize(80, 25)); |
| 95 | okButton->SetDefault(); |
| 96 | |
| 97 | // Note, omit the wxTAB_STYLE_COLOUR_INTERIOR, so we will guarantee a match |
| 98 | // with the panel background, and save a bit of time. |
| 99 | wxPanelTabView *view = new wxPanelTabView(this, wxTAB_STYLE_DRAW_BOX); |
| 100 | |
| 101 | wxRectangle rect; |
| 102 | rect.x = 5; |
| 103 | rect.y = 70; |
| 104 | // Could calculate the view width from the tab width and spacing, |
| 105 | // as below, but let's assume we have a fixed view width. |
| 106 | // rect.width = view->GetTabWidth()*4 + 3*view->GetHorizontalTabSpacing(); |
| 107 | rect.width = 326; |
| 108 | rect.height = 250; |
| 109 | |
| 110 | view->SetViewRect(rect); |
| 111 | |
| 112 | // Calculate the tab width for 4 tabs, based on a view width of 326 and |
| 113 | // the current horizontal spacing. Adjust the view width to exactly fit |
| 114 | // the tabs. |
| 115 | view->CalculateTabWidth(4, true); |
| 116 | |
| 117 | if (!view->AddTab(TEST_TAB_CAT, wxString("Cat"))) |
| 118 | return; |
| 119 | |
| 120 | if (!view->AddTab(TEST_TAB_DOG, wxString("Dog"))) |
| 121 | return; |
| 122 | if (!view->AddTab(TEST_TAB_GUINEAPIG, wxString("Guinea Pig"))) |
| 123 | return; |
| 124 | if (!view->AddTab(TEST_TAB_GOAT, wxString("Goat"))) |
| 125 | return; |
| 126 | if (!view->AddTab(TEST_TAB_ANTEATER, wxString("Ant-eater"))) |
| 127 | return; |
| 128 | if (!view->AddTab(TEST_TAB_SHEEP, wxString("Sheep"))) |
| 129 | return; |
| 130 | if (!view->AddTab(TEST_TAB_COW, wxString("Cow"))) |
| 131 | return; |
| 132 | if (!view->AddTab(TEST_TAB_HORSE, wxString("Horse"))) |
| 133 | return; |
| 134 | if (!view->AddTab(TEST_TAB_PIG, wxString("Pig"))) |
| 135 | return; |
| 136 | if (!view->AddTab(TEST_TAB_OSTRICH, wxString("Ostrich"))) |
| 137 | return; |
| 138 | if (!view->AddTab(TEST_TAB_AARDVARK, wxString("Aardvark"))) |
| 139 | return; |
| 140 | if (!view->AddTab(TEST_TAB_HUMMINGBIRD,wxString("Hummingbird"))) |
| 141 | return; |
| 142 | |
| 143 | // Add some panels |
| 144 | wxPanel *panel1 = new wxPanel(this, -1, wxPoint(rect.x + 20, rect.y + 10), wxSize(290, 220), wxTAB_TRAVERSAL); |
| 145 | (void)new wxButton(panel1, -1, "Press me", wxPoint(10, 10)); |
| 146 | (void)new wxTextCtrl(panel1, -1, "1234", wxPoint(10, 40), wxSize(120, 150)); |
| 147 | |
| 148 | view->AddTabWindow(TEST_TAB_CAT, panel1); |
| 149 | |
| 150 | wxPanel *panel2 = new wxPanel(this, -1, wxPoint(rect.x + 20, rect.y + 10), wxSize(290, 220)); |
| 151 | |
| 152 | wxString animals[] = { "Fox", "Hare", "Rabbit", "Sabre-toothed tiger", "T Rex" }; |
| 153 | (void)new wxListBox(panel2, -1, wxPoint(5, 5), wxSize(170, 80), 5, animals); |
| 154 | |
| 155 | (void)new wxTextCtrl(panel2, -1, "Some notes about the animals in this house", wxPoint(5, 100), wxSize(170, 100)), |
| 156 | wxTE_MULTILINE; |
| 157 | |
| 158 | view->AddTabWindow(TEST_TAB_DOG, panel2); |
| 159 | |
| 160 | // Don't know why this is necessary under Motif... |
| 161 | #ifdef wx_motif |
| 162 | this->SetSize(dialogWidth, dialogHeight-20); |
| 163 | #endif |
| 164 | |
| 165 | view->SetTabSelection(TEST_TAB_CAT); |
| 166 | |
| 167 | this->Centre(wxBOTH); |
| 168 | } |
| 169 | \end{verbatim} |
| 170 | } |
| 171 | |
| 172 | \section{wxTabView overview}\label{wxtabviewoverview} |
| 173 | |
| 174 | Classes: \helpref{wxTabView}{wxtabview}, \helpref{wxPanelTabView}{wxpaneltabview} |
| 175 | |
| 176 | A wxTabView manages and draws a number of tabs. Because it is separate |
| 177 | from the tabbed window implementation, it can be reused in a number of contexts. |
| 178 | This library provides tabbed dialog and panel classes to use with the |
| 179 | wxPanelTabView class, but an application could derive other kinds of |
| 180 | view from wxTabView. |
| 181 | |
| 182 | For example, a help application might draw a representation of a book on |
| 183 | a window, with a row of tabs along the top. The new tab view class might |
| 184 | be called wxCanvasTabView, for example, with the wxBookCanvas posting |
| 185 | the OnEvent function to the wxCanvasTabView before processing further, |
| 186 | application-specific event processing. |
| 187 | |
| 188 | A window class designed to work with a view class must call the view's |
| 189 | OnEvent and Draw functions at appropriate times. |
| 190 | |