]> git.saurik.com Git - wxWidgets.git/blob - src/common/tbarbase.cpp
Restored previous mouse release/capture behaviour for some ports
[wxWidgets.git] / src / common / tbarbase.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: common/tbarbase.cpp
3 // Purpose: wxToolBarBase implementation
4 // Author: Julian Smart
5 // Modified by: VZ at 11.12.99 (wxScrollableToolBar splitted off)
6 // Created: 04/01/98
7 // RCS-ID: $Id$
8 // Copyright: (c) Julian Smart and Markus Holzem
9 // Licence: wxWindows license
10 /////////////////////////////////////////////////////////////////////////////
11
12 // ============================================================================
13 // declarations
14 // ============================================================================
15
16 // ----------------------------------------------------------------------------
17 // headers
18 // ----------------------------------------------------------------------------
19
20 #ifdef __GNUG__
21 #pragma implementation "tbarbase.h"
22 #endif
23
24 // For compilers that support precompilation, includes "wx.h".
25 #include "wx/wxprec.h"
26
27 #ifdef __BORLANDC__
28 #pragma hdrstop
29 #endif
30
31 #if wxUSE_TOOLBAR
32
33 #ifndef WX_PRECOMP
34 #endif
35
36 #include "wx/frame.h"
37
38 // For ::UpdateWindow
39 #ifdef __WXMSW__
40 #include <windows.h>
41 #endif
42
43 #include "wx/tbarbase.h"
44
45 // ----------------------------------------------------------------------------
46 // wxWindows macros
47 // ----------------------------------------------------------------------------
48
49 IMPLEMENT_CLASS(wxToolBarBase, wxControl)
50
51 BEGIN_EVENT_TABLE(wxToolBarBase, wxControl)
52 EVT_IDLE(wxToolBarBase::OnIdle)
53 END_EVENT_TABLE()
54
55 #include "wx/listimpl.cpp"
56
57 WX_DEFINE_LIST(wxToolBarToolsList);
58
59 // ============================================================================
60 // implementation
61 // ============================================================================
62
63 // ----------------------------------------------------------------------------
64 // wxToolBarToolBase
65 // ----------------------------------------------------------------------------
66
67 bool wxToolBarToolBase::Enable(bool enable)
68 {
69 if ( m_enabled == enable )
70 return FALSE;
71
72 m_enabled = enable;
73
74 return TRUE;
75 }
76
77 bool wxToolBarToolBase::Toggle(bool toggle)
78 {
79 wxASSERT_MSG( m_isToggle, _T("can't toggle this tool") );
80
81 if ( m_toggled == toggle )
82 return FALSE;
83
84 m_toggled = toggle;
85
86 return TRUE;
87 }
88
89 bool wxToolBarToolBase::SetToggle(bool toggle)
90 {
91 if ( m_isToggle == toggle )
92 return FALSE;
93
94 m_isToggle = toggle;
95
96 return TRUE;
97 }
98
99 bool wxToolBarToolBase::SetShortHelp(const wxString& help)
100 {
101 if ( m_shortHelpString == help )
102 return FALSE;
103
104 m_shortHelpString = help;
105
106 return TRUE;
107 }
108
109 bool wxToolBarToolBase::SetLongHelp(const wxString& help)
110 {
111 if ( m_longHelpString == help )
112 return FALSE;
113
114 m_longHelpString = help;
115
116 return TRUE;
117 }
118
119 wxToolBarToolBase::~wxToolBarToolBase()
120 {
121 }
122
123 // ----------------------------------------------------------------------------
124 // wxToolBarBase adding/deleting items
125 // ----------------------------------------------------------------------------
126
127 wxToolBarBase::wxToolBarBase()
128 {
129 // the list owns the pointers
130 m_tools.DeleteContents(TRUE);
131
132 m_xMargin = m_yMargin = 0;
133
134 m_maxRows = m_maxCols = 0;
135 }
136
137 wxToolBarToolBase *wxToolBarBase::AddTool(int id,
138 const wxBitmap& bitmap,
139 const wxBitmap& pushedBitmap,
140 bool toggle,
141 wxCoord WXUNUSED(xPos),
142 wxCoord WXUNUSED(yPos),
143 wxObject *clientData,
144 const wxString& helpString1,
145 const wxString& helpString2)
146 {
147 return InsertTool(GetToolsCount(), id, bitmap, pushedBitmap,
148 toggle, clientData, helpString1, helpString2);
149 }
150
151 wxToolBarToolBase *wxToolBarBase::InsertTool(size_t pos,
152 int id,
153 const wxBitmap& bitmap,
154 const wxBitmap& pushedBitmap,
155 bool toggle,
156 wxObject *clientData,
157 const wxString& helpString1,
158 const wxString& helpString2)
159 {
160 wxCHECK_MSG( pos <= GetToolsCount(), (wxToolBarToolBase *)NULL,
161 _T("invalid position in wxToolBar::InsertTool()") );
162
163 wxToolBarToolBase *tool = CreateTool(id, bitmap, pushedBitmap, toggle,
164 clientData, helpString1, helpString2);
165
166 if ( !tool || !DoInsertTool(pos, tool) )
167 {
168 delete tool;
169
170 return NULL;
171 }
172
173 m_tools.Insert(pos, tool);
174
175 return tool;
176 }
177
178 wxToolBarToolBase *wxToolBarBase::AddControl(wxControl *control)
179 {
180 return InsertControl(GetToolsCount(), control);
181 }
182
183 wxToolBarToolBase *wxToolBarBase::InsertControl(size_t pos, wxControl *control)
184 {
185 wxCHECK_MSG( control, (wxToolBarToolBase *)NULL,
186 _T("toolbar: can't insert NULL control") );
187
188 wxCHECK_MSG( control->GetParent() == this, (wxToolBarToolBase *)NULL,
189 _T("control must have toolbar as parent") );
190
191 wxCHECK_MSG( pos <= GetToolsCount(), (wxToolBarToolBase *)NULL,
192 _T("invalid position in wxToolBar::InsertControl()") );
193
194 wxToolBarToolBase *tool = CreateTool(control);
195
196 if ( !tool || !DoInsertTool(pos, tool) )
197 {
198 delete tool;
199
200 return NULL;
201 }
202
203 m_tools.Insert(pos, tool);
204
205 return tool;
206 }
207
208 wxToolBarToolBase *wxToolBarBase::AddSeparator()
209 {
210 return InsertSeparator(GetToolsCount());
211 }
212
213 wxToolBarToolBase *wxToolBarBase::InsertSeparator(size_t pos)
214 {
215 wxCHECK_MSG( pos <= GetToolsCount(), (wxToolBarToolBase *)NULL,
216 _T("invalid position in wxToolBar::InsertSeparator()") );
217
218 wxToolBarToolBase *tool = CreateTool(wxID_SEPARATOR,
219 wxNullBitmap, wxNullBitmap,
220 FALSE, (wxObject *)NULL,
221 wxEmptyString, wxEmptyString);
222
223 if ( !tool || !DoInsertTool(pos, tool) )
224 {
225 delete tool;
226
227 return NULL;
228 }
229
230 m_tools.Insert(pos, tool);
231
232 return tool;
233 }
234
235 wxToolBarToolBase *wxToolBarBase::RemoveTool(int id)
236 {
237 size_t pos = 0;
238 wxToolBarToolsList::Node *node;
239 for ( node = m_tools.GetFirst(); node; node = node->GetNext() )
240 {
241 if ( node->GetData()->GetId() == id )
242 break;
243
244 pos++;
245 }
246
247 if ( !node )
248 {
249 // don't give any error messages - sometimes we might call RemoveTool()
250 // without knowing whether the tool is or not in the toolbar
251 return (wxToolBarToolBase *)NULL;
252 }
253
254 wxToolBarToolBase *tool = node->GetData();
255 if ( !DoDeleteTool(pos, tool) )
256 {
257 return (wxToolBarToolBase *)NULL;
258 }
259
260 // the node would delete the data, so set it to NULL to avoid this
261 node->SetData(NULL);
262
263 m_tools.DeleteNode(node);
264
265 return tool;
266 }
267
268 bool wxToolBarBase::DeleteToolByPos(size_t pos)
269 {
270 wxCHECK_MSG( pos < GetToolsCount(), FALSE,
271 _T("invalid position in wxToolBar::DeleteToolByPos()") );
272
273 wxToolBarToolsList::Node *node = m_tools.Item(pos);
274
275 if ( !DoDeleteTool(pos, node->GetData()) )
276 {
277 return FALSE;
278 }
279
280 m_tools.DeleteNode(node);
281
282 return TRUE;
283 }
284
285 bool wxToolBarBase::DeleteTool(int id)
286 {
287 size_t pos = 0;
288 wxToolBarToolsList::Node *node;
289 for ( node = m_tools.GetFirst(); node; node = node->GetNext() )
290 {
291 if ( node->GetData()->GetId() == id )
292 break;
293
294 pos++;
295 }
296
297 if ( !node || !DoDeleteTool(pos, node->GetData()) )
298 {
299 return FALSE;
300 }
301
302 m_tools.DeleteNode(node);
303
304 return TRUE;
305 }
306
307 wxToolBarToolBase *wxToolBarBase::FindById(int id) const
308 {
309 wxToolBarToolBase *tool = (wxToolBarToolBase *)NULL;
310
311 for ( wxToolBarToolsList::Node *node = m_tools.GetFirst();
312 node;
313 node = node->GetNext() )
314 {
315 tool = node->GetData();
316 if ( tool->GetId() == id )
317 {
318 // found
319 break;
320 }
321
322 tool = NULL;
323 }
324
325 return tool;
326 }
327
328 void wxToolBarBase::ClearTools()
329 {
330 m_tools.Clear();
331 }
332
333 bool wxToolBarBase::Realize()
334 {
335 return TRUE;
336 }
337
338 wxToolBarBase::~wxToolBarBase()
339 {
340 }
341
342 // ----------------------------------------------------------------------------
343 // wxToolBarBase tools state
344 // ----------------------------------------------------------------------------
345
346 void wxToolBarBase::EnableTool(int id, bool enable)
347 {
348 wxToolBarToolBase *tool = FindById(id);
349 if ( tool )
350 {
351 if ( tool->Enable(enable) )
352 {
353 DoEnableTool(tool, enable);
354 }
355 }
356 }
357
358 void wxToolBarBase::ToggleTool(int id, bool toggle)
359 {
360 wxToolBarToolBase *tool = FindById(id);
361 if ( tool && tool->CanBeToggled() )
362 {
363 if ( tool->Toggle(toggle) )
364 {
365 DoToggleTool(tool, toggle);
366 }
367 }
368 }
369
370 void wxToolBarBase::SetToggle(int id, bool toggle)
371 {
372 wxToolBarToolBase *tool = FindById(id);
373 if ( tool )
374 {
375 if ( tool->SetToggle(toggle) )
376 {
377 DoSetToggle(tool, toggle);
378 }
379 }
380 }
381
382 void wxToolBarBase::SetToolShortHelp(int id, const wxString& help)
383 {
384 wxToolBarToolBase *tool = FindById(id);
385 if ( tool )
386 {
387 (void)tool->SetShortHelp(help);
388 }
389 }
390
391 void wxToolBarBase::SetToolLongHelp(int id, const wxString& help)
392 {
393 wxToolBarToolBase *tool = FindById(id);
394 if ( tool )
395 {
396 (void)tool->SetLongHelp(help);
397 }
398 }
399
400 wxObject *wxToolBarBase::GetToolClientData(int id) const
401 {
402 wxToolBarToolBase *tool = FindById(id);
403
404 return tool ? tool->GetClientData() : (wxObject *)NULL;
405 }
406
407 void wxToolBarBase::SetToolClientData(int id, wxObject *clientData)
408 {
409 wxToolBarToolBase *tool = FindById(id);
410
411 wxCHECK_RET( tool, _T("no such tool in wxToolBar::SetToolClientData") );
412
413 tool->SetClientData(clientData);
414 }
415
416 bool wxToolBarBase::GetToolState(int id) const
417 {
418 wxToolBarToolBase *tool = FindById(id);
419 wxCHECK_MSG( tool, FALSE, _T("no such tool") );
420
421 return tool->IsToggled();
422 }
423
424 bool wxToolBarBase::GetToolEnabled(int id) const
425 {
426 wxToolBarToolBase *tool = FindById(id);
427 wxCHECK_MSG( tool, FALSE, _T("no such tool") );
428
429 return tool->IsEnabled();
430 }
431
432 wxString wxToolBarBase::GetToolShortHelp(int id) const
433 {
434 wxToolBarToolBase *tool = FindById(id);
435 wxCHECK_MSG( tool, _T(""), _T("no such tool") );
436
437 return tool->GetShortHelp();
438 }
439
440 wxString wxToolBarBase::GetToolLongHelp(int id) const
441 {
442 wxToolBarToolBase *tool = FindById(id);
443 wxCHECK_MSG( tool, _T(""), _T("no such tool") );
444
445 return tool->GetLongHelp();
446 }
447
448 // ----------------------------------------------------------------------------
449 // wxToolBarBase geometry
450 // ----------------------------------------------------------------------------
451
452 void wxToolBarBase::SetMargins(int x, int y)
453 {
454 m_xMargin = x;
455 m_yMargin = y;
456 }
457
458 void wxToolBarBase::SetRows(int WXUNUSED(nRows))
459 {
460 // nothing
461 }
462
463 // ----------------------------------------------------------------------------
464 // event processing
465 // ----------------------------------------------------------------------------
466
467 // Only allow toggle if returns TRUE
468 bool wxToolBarBase::OnLeftClick(int id, bool toggleDown)
469 {
470 wxCommandEvent event(wxEVT_COMMAND_TOOL_CLICKED, id);
471 event.SetEventObject(this);
472
473 // we use SetInt() to make wxCommandEvent::IsChecked() return toggleDown
474 event.SetInt((int)toggleDown);
475
476 // and SetExtraLong() for backwards compatibility
477 event.SetExtraLong((long)toggleDown);
478
479 // Send events to this toolbar instead (and thence up the window hierarchy)
480 GetEventHandler()->ProcessEvent(event);
481
482 return TRUE;
483 }
484
485 // Call when right button down.
486 void wxToolBarBase::OnRightClick(int id,
487 long WXUNUSED(x),
488 long WXUNUSED(y))
489 {
490 wxCommandEvent event(wxEVT_COMMAND_TOOL_RCLICKED, id);
491 event.SetEventObject(this);
492 event.SetInt(id);
493
494 GetEventHandler()->ProcessEvent(event);
495 }
496
497 // Called when the mouse cursor enters a tool bitmap (no button pressed).
498 // Argument is -1 if mouse is exiting the toolbar.
499 // Note that for this event, the id of the window is used,
500 // and the integer parameter of wxCommandEvent is used to retrieve
501 // the tool id.
502 void wxToolBarBase::OnMouseEnter(int id)
503 {
504 wxCommandEvent event(wxEVT_COMMAND_TOOL_ENTER, GetId());
505 event.SetEventObject(this);
506 event.SetInt(id);
507
508 (void)GetEventHandler()->ProcessEvent(event);
509
510 wxToolBarToolBase *tool = FindById(id);
511 if ( !tool || !tool->GetLongHelp() )
512 return;
513
514 wxFrame *frame = wxDynamicCast(GetParent(), wxFrame);
515 if ( !frame )
516 return;
517
518 frame->SetStatusText(tool->GetLongHelp());
519 }
520
521 // ----------------------------------------------------------------------------
522 // UI updates
523 // ----------------------------------------------------------------------------
524
525 void wxToolBarBase::OnIdle(wxIdleEvent& event)
526 {
527 DoToolbarUpdates();
528
529 event.Skip();
530 }
531
532 // Do the toolbar button updates (check for EVT_UPDATE_UI handlers)
533 void wxToolBarBase::DoToolbarUpdates()
534 {
535 wxWindow* parent = this;
536 while (parent->GetParent())
537 parent = parent->GetParent();
538
539 #ifdef __WXMSW__
540 wxWindow* focusWin = wxFindFocusDescendant(parent);
541 #else
542 wxWindow* focusWin = (wxWindow*) NULL;
543 #endif
544
545 wxEvtHandler* evtHandler = focusWin ? focusWin->GetEventHandler() : GetEventHandler() ;
546
547 for ( wxToolBarToolsList::Node* node = m_tools.GetFirst();
548 node;
549 node = node->GetNext() )
550 {
551 int id = node->GetData()->GetId();
552
553 wxUpdateUIEvent event(id);
554 event.SetEventObject(this);
555
556 if ( evtHandler->ProcessEvent(event) )
557 {
558 if ( event.GetSetEnabled() )
559 EnableTool(id, event.GetEnabled());
560 if ( event.GetSetChecked() )
561 ToggleTool(id, event.GetChecked());
562 #if 0
563 if ( event.GetSetText() )
564 // Set tooltip?
565 #endif // 0
566 }
567 }
568 }
569
570 #endif // wxUSE_TOOLBAR