added missing include; minor reformatting
[wxWidgets.git] / src / generic / toolbkg.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/generic/toolbkg.cpp
3 // Purpose: generic implementation of wxToolbook
4 // Author: Julian Smart
5 // Modified by:
6 // Created: 2006-01-29
7 // RCS-ID: $Id$
8 // Copyright: (c) 2006 Julian Smart
9 // Licence: wxWindows licence
10 ///////////////////////////////////////////////////////////////////////////////
11
12 // For compilers that support precompilation, includes "wx.h".
13 #include "wx/wxprec.h"
14
15 #ifdef __BORLANDC__
16 #pragma hdrstop
17 #endif
18
19 #if wxUSE_TOOLBOOK
20
21 #include "wx/imaglist.h"
22 #include "wx/icon.h"
23 #include "wx/toolbar.h"
24 #include "wx/toolbook.h"
25 #include "wx/settings.h"
26 #include "wx/sysopt.h"
27
28 // ----------------------------------------------------------------------------
29 // various wxWidgets macros
30 // ----------------------------------------------------------------------------
31
32 // check that the page index is valid
33 #define IS_VALID_PAGE(nPage) ((nPage) < GetPageCount())
34
35 // ----------------------------------------------------------------------------
36 // event table
37 // ----------------------------------------------------------------------------
38
39 IMPLEMENT_DYNAMIC_CLASS(wxToolbook, wxBookCtrlBase)
40 IMPLEMENT_DYNAMIC_CLASS(wxToolbookEvent, wxNotifyEvent)
41
42 const wxEventType wxEVT_COMMAND_TOOLBOOK_PAGE_CHANGING = wxNewEventType();
43 const wxEventType wxEVT_COMMAND_TOOLBOOK_PAGE_CHANGED = wxNewEventType();
44 const int wxID_TOOLBOOKTOOLBAR = wxNewId();
45
46 BEGIN_EVENT_TABLE(wxToolbook, wxBookCtrlBase)
47 EVT_SIZE(wxToolbook::OnSize)
48 EVT_TOOL_RANGE(1, 50, wxToolbook::OnToolSelected)
49 EVT_IDLE(wxToolbook::OnIdle)
50 END_EVENT_TABLE()
51
52 // ============================================================================
53 // wxToolbook implementation
54 // ============================================================================
55
56 // ----------------------------------------------------------------------------
57 // wxToolbook creation
58 // ----------------------------------------------------------------------------
59
60 void wxToolbook::Init()
61 {
62 m_selection = wxNOT_FOUND;
63 m_needsRealizing = false;
64 }
65
66 bool wxToolbook::Create(wxWindow *parent,
67 wxWindowID id,
68 const wxPoint& pos,
69 const wxSize& size,
70 long style,
71 const wxString& name)
72 {
73 if ( (style & wxBK_ALIGN_MASK) == wxBK_DEFAULT )
74 style |= wxBK_TOP;
75
76 // no border for this control
77 style &= ~wxBORDER_MASK;
78 style |= wxBORDER_NONE;
79
80 if ( !wxControl::Create(parent, id, pos, size, style,
81 wxDefaultValidator, name) )
82 return false;
83
84 int orient = wxTB_HORIZONTAL;
85 if ( (style & (wxBK_LEFT | wxBK_RIGHT)) != 0)
86 orient = wxTB_VERTICAL;
87
88 // TODO: make more configurable
89 m_bookctrl = new wxToolBar
90 (
91 this,
92 wxID_TOOLBOOKTOOLBAR,
93 wxDefaultPosition,
94 wxDefaultSize,
95 orient | wxTB_TEXT|wxTB_FLAT|wxTB_NODIVIDER
96 );
97
98 return true;
99 }
100
101 // ----------------------------------------------------------------------------
102 // wxToolbook geometry management
103 // ----------------------------------------------------------------------------
104
105 wxSize wxToolbook::GetControllerSize() const
106 {
107 const wxSize sizeClient = GetClientSize(),
108 sizeBorder = m_bookctrl->GetSize() - m_bookctrl->GetClientSize(),
109 sizeToolBar = GetToolBar()->GetSize() + sizeBorder;
110
111 wxSize size;
112
113 if ( IsVertical() )
114 {
115 size.x = sizeClient.x;
116 size.y = sizeToolBar.y;
117 }
118 else // left/right aligned
119 {
120 size.x = sizeToolBar.x;
121 size.y = sizeClient.y;
122 }
123
124 return size;
125 }
126
127 void wxToolbook::OnSize(wxSizeEvent& event)
128 {
129 if (m_needsRealizing)
130 Realize();
131
132 wxBookCtrlBase::OnSize(event);
133 }
134
135 wxSize wxToolbook::CalcSizeFromPage(const wxSize& sizePage) const
136 {
137 // we need to add the size of the list control and the border between
138 const wxSize sizeToolBar = GetControllerSize();
139
140 wxSize size = sizePage;
141 if ( IsVertical() )
142 {
143 size.y += sizeToolBar.y + GetInternalBorder();
144 }
145 else // left/right aligned
146 {
147 size.x += sizeToolBar.x + GetInternalBorder();
148 }
149
150 return size;
151 }
152
153 // ----------------------------------------------------------------------------
154 // accessing the pages
155 // ----------------------------------------------------------------------------
156
157 bool wxToolbook::SetPageText(size_t n, const wxString& strText)
158 {
159 // Assume tool ids start from 1
160 wxToolBarToolBase* tool = GetToolBar()->FindById(n + 1);
161 if (tool)
162 {
163 tool->SetLabel(strText);
164 return true;
165 }
166 else
167 return false;
168 }
169
170 wxString wxToolbook::GetPageText(size_t n) const
171 {
172 wxToolBarToolBase* tool = GetToolBar()->FindById(n + 1);
173 if (tool)
174 return tool->GetLabel();
175 else
176 return wxEmptyString;
177 }
178
179 int wxToolbook::GetPageImage(size_t WXUNUSED(n)) const
180 {
181 wxFAIL_MSG( _T("wxToolbook::GetPageImage() not implemented") );
182
183 return wxNOT_FOUND;
184 }
185
186 bool wxToolbook::SetPageImage(size_t n, int imageId)
187 {
188 wxASSERT( GetImageList() != NULL );
189 if (!GetImageList())
190 return false;
191
192 wxToolBarToolBase* tool = GetToolBar()->FindById(n + 1);
193 if (tool)
194 {
195 // Find the image list index for this tool
196 wxBitmap bitmap = GetImageList()->GetBitmap(imageId);
197 tool->SetNormalBitmap(bitmap);
198 return true;
199 }
200 else
201 return false;
202 }
203
204 // ----------------------------------------------------------------------------
205 // image list stuff
206 // ----------------------------------------------------------------------------
207
208 void wxToolbook::SetImageList(wxImageList *imageList)
209 {
210 wxBookCtrlBase::SetImageList(imageList);
211 }
212
213 // ----------------------------------------------------------------------------
214 // selection
215 // ----------------------------------------------------------------------------
216
217 int wxToolbook::GetSelection() const
218 {
219 return m_selection;
220 }
221
222 int wxToolbook::SetSelection(size_t n)
223 {
224 wxCHECK_MSG( IS_VALID_PAGE(n), wxNOT_FOUND,
225 wxT("invalid page index in wxToolbook::SetSelection()") );
226
227 const int oldSel = m_selection;
228
229 if ( int(n) != m_selection )
230 {
231 wxToolbookEvent event(wxEVT_COMMAND_TOOLBOOK_PAGE_CHANGING, m_windowId);
232 event.SetSelection(n);
233 event.SetOldSelection(m_selection);
234 event.SetEventObject(this);
235 if ( !GetEventHandler()->ProcessEvent(event) || event.IsAllowed() )
236 {
237 if ( m_selection != wxNOT_FOUND )
238 m_pages[m_selection]->Hide();
239
240 wxWindow *page = m_pages[n];
241 page->SetSize(GetPageRect());
242 page->Show();
243
244 // change m_selection now to ignore the selection change event
245 m_selection = n;
246 GetToolBar()->ToggleTool(n + 1, true);
247
248 // program allows the page change
249 event.SetEventType(wxEVT_COMMAND_TOOLBOOK_PAGE_CHANGED);
250 (void)GetEventHandler()->ProcessEvent(event);
251 }
252 }
253
254 return oldSel;
255 }
256
257 // Not part of the wxBookctrl API, but must be called in OnIdle or
258 // by application to realize the toolbar and select the initial page.
259 void wxToolbook::Realize()
260 {
261 if (m_needsRealizing)
262 {
263 GetToolBar()->SetToolBitmapSize(m_maxBitmapSize);
264
265 int remap = wxSystemOptions::GetOptionInt(wxT("msw.remap"));
266 wxSystemOptions::SetOption(wxT("msw.remap"), 0);
267 GetToolBar()->Realize();
268 wxSystemOptions::SetOption(wxT("msw.remap"), remap);
269 }
270
271 m_needsRealizing = false;
272
273 if (m_selection == -1)
274 m_selection = 0;
275
276 if (GetPageCount() > 0)
277 {
278 int sel = m_selection;
279 m_selection = -1;
280 SetSelection(sel);
281 }
282
283 DoSize();
284 }
285
286 void wxToolbook::OnIdle(wxIdleEvent& event)
287 {
288 if (m_needsRealizing)
289 Realize();
290 event.Skip();
291 }
292
293 // ----------------------------------------------------------------------------
294 // adding/removing the pages
295 // ----------------------------------------------------------------------------
296
297 bool wxToolbook::InsertPage(size_t n,
298 wxWindow *page,
299 const wxString& text,
300 bool bSelect,
301 int imageId)
302 {
303 if ( !wxBookCtrlBase::InsertPage(n, page, text, bSelect, imageId) )
304 return false;
305
306 m_needsRealizing = true;
307
308 wxASSERT(GetImageList() != NULL);
309
310 if (!GetImageList())
311 return false;
312
313 // TODO: make sure all platforms can convert between icon and bitmap,
314 // and/or test whether the image is a bitmap or an icon.
315 #ifdef __WXMAC__
316 wxBitmap bitmap = GetImageList()->GetBitmap(imageId);
317 #else
318 // On Windows, we can lose information by using GetBitmap, so extract icon instead
319 wxIcon icon = GetImageList()->GetIcon(imageId);
320 wxBitmap bitmap;
321 bitmap.CopyFromIcon(icon);
322 #endif
323
324 m_maxBitmapSize.x = wxMax(bitmap.GetWidth(), m_maxBitmapSize.x);
325 m_maxBitmapSize.y = wxMax(bitmap.GetHeight(), m_maxBitmapSize.y);
326
327 GetToolBar()->SetToolBitmapSize(m_maxBitmapSize);
328 GetToolBar()->AddRadioTool(n + 1, text, bitmap, wxNullBitmap, text);
329
330 if (bSelect)
331 {
332 // GetToolBar()->ToggleTool(n, true);
333 m_selection = n;
334 }
335 else
336 page->Hide();
337
338 InvalidateBestSize();
339 return true;
340 }
341
342 wxWindow *wxToolbook::DoRemovePage(size_t page)
343 {
344 const size_t page_count = GetPageCount();
345 wxWindow *win = wxBookCtrlBase::DoRemovePage(page);
346
347 if ( win )
348 {
349 GetToolBar()->DeleteTool(page + 1);
350
351 if (m_selection >= (int)page)
352 {
353 // force new sel valid if possible
354 int sel = m_selection - 1;
355 if (page_count == 1)
356 sel = wxNOT_FOUND;
357 else if ((page_count == 2) || (sel == -1))
358 sel = 0;
359
360 // force sel invalid if deleting current page - don't try to hide it
361 m_selection = (m_selection == (int)page) ? wxNOT_FOUND : m_selection - 1;
362
363 if ((sel != wxNOT_FOUND) && (sel != m_selection))
364 SetSelection(sel);
365 }
366 }
367
368 return win;
369 }
370
371
372 bool wxToolbook::DeleteAllPages()
373 {
374 GetToolBar()->ClearTools();
375 return wxBookCtrlBase::DeleteAllPages();
376 }
377
378 // ----------------------------------------------------------------------------
379 // wxToolbook events
380 // ----------------------------------------------------------------------------
381
382 void wxToolbook::OnToolSelected(wxCommandEvent& event)
383 {
384 const int selNew = event.GetId() - 1;
385
386 if ( selNew == m_selection )
387 {
388 // this event can only come from our own Select(m_selection) below
389 // which we call when the page change is vetoed, so we should simply
390 // ignore it
391 return;
392 }
393
394 SetSelection(selNew);
395
396 // change wasn't allowed, return to previous state
397 if (m_selection != selNew)
398 GetToolBar()->ToggleTool(m_selection, false);
399 }
400
401 #endif // wxUSE_TOOLBOOK