]> git.saurik.com Git - wxWidgets.git/blob - src/common/tbarbase.cpp
- Moved wxApp::SendIdleEvents and wxApp::ProcessIdle into common code.
[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
9 // Licence: wxWindows licence
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 #include "wx/control.h"
35 #endif
36
37 #include "wx/frame.h"
38 #include "wx/image.h"
39 #include "wx/settings.h"
40
41 #include "wx/tbarbase.h"
42
43 // ----------------------------------------------------------------------------
44 // wxWindows macros
45 // ----------------------------------------------------------------------------
46
47 IMPLEMENT_CLASS(wxToolBarBase, wxControl)
48
49 BEGIN_EVENT_TABLE(wxToolBarBase, wxControl)
50 END_EVENT_TABLE()
51
52 #include "wx/listimpl.cpp"
53
54 WX_DEFINE_LIST(wxToolBarToolsList);
55
56 // ============================================================================
57 // implementation
58 // ============================================================================
59
60 // ----------------------------------------------------------------------------
61 // wxToolBarToolBase
62 // ----------------------------------------------------------------------------
63
64 bool wxToolBarToolBase::Enable(bool enable)
65 {
66 if ( m_enabled == enable )
67 return FALSE;
68
69 m_enabled = enable;
70
71 return TRUE;
72 }
73
74 bool wxToolBarToolBase::Toggle(bool toggle)
75 {
76 wxASSERT_MSG( CanBeToggled(), _T("can't toggle this tool") );
77
78 if ( m_toggled == toggle )
79 return FALSE;
80
81 m_toggled = toggle;
82
83 return TRUE;
84 }
85
86 bool wxToolBarToolBase::SetToggle(bool toggle)
87 {
88 wxItemKind kind = toggle ? wxITEM_CHECK : wxITEM_NORMAL;
89 if ( m_kind == kind )
90 return FALSE;
91
92 m_kind = kind;
93
94 return TRUE;
95 }
96
97 bool wxToolBarToolBase::SetShortHelp(const wxString& help)
98 {
99 if ( m_shortHelpString == help )
100 return FALSE;
101
102 m_shortHelpString = help;
103
104 return TRUE;
105 }
106
107 bool wxToolBarToolBase::SetLongHelp(const wxString& help)
108 {
109 if ( m_longHelpString == help )
110 return FALSE;
111
112 m_longHelpString = help;
113
114 return TRUE;
115 }
116
117 wxToolBarToolBase::~wxToolBarToolBase()
118 {
119 }
120
121 // ----------------------------------------------------------------------------
122 // wxToolBarBase adding/deleting items
123 // ----------------------------------------------------------------------------
124
125 wxToolBarBase::wxToolBarBase()
126 {
127 // the list owns the pointers
128 m_tools.DeleteContents(TRUE);
129
130 m_xMargin = m_yMargin = 0;
131
132 m_maxRows = m_maxCols = 0;
133 }
134
135 wxToolBarToolBase *wxToolBarBase::DoAddTool(int id,
136 const wxString& label,
137 const wxBitmap& bitmap,
138 const wxBitmap& bmpDisabled,
139 wxItemKind kind,
140 const wxString& shortHelp,
141 const wxString& longHelp,
142 wxObject *clientData,
143 wxCoord WXUNUSED(xPos),
144 wxCoord WXUNUSED(yPos))
145 {
146 return InsertTool(GetToolsCount(), id, label, bitmap, bmpDisabled,
147 kind, shortHelp, longHelp, clientData);
148 }
149
150 wxToolBarToolBase *wxToolBarBase::InsertTool(size_t pos,
151 int id,
152 const wxString& label,
153 const wxBitmap& bitmap,
154 const wxBitmap& bmpDisabled,
155 wxItemKind kind,
156 const wxString& shortHelp,
157 const wxString& longHelp,
158 wxObject *clientData)
159 {
160 wxCHECK_MSG( pos <= GetToolsCount(), (wxToolBarToolBase *)NULL,
161 _T("invalid position in wxToolBar::InsertTool()") );
162
163 wxToolBarToolBase *tool = CreateTool(id, label, bitmap, bmpDisabled, kind,
164 clientData, shortHelp, longHelp);
165
166 if ( !InsertTool(pos, tool) )
167 {
168 delete tool;
169
170 return NULL;
171 }
172
173 return tool;
174 }
175
176 wxToolBarToolBase *wxToolBarBase::AddTool(wxToolBarToolBase *tool)
177 {
178 return InsertTool(GetToolsCount(), tool);
179 }
180
181 wxToolBarToolBase *
182 wxToolBarBase::InsertTool(size_t pos, wxToolBarToolBase *tool)
183 {
184 wxCHECK_MSG( pos <= GetToolsCount(), (wxToolBarToolBase *)NULL,
185 _T("invalid position in wxToolBar::InsertTool()") );
186
187 if ( !tool || !DoInsertTool(pos, tool) )
188 {
189 return NULL;
190 }
191
192 m_tools.Insert(pos, tool);
193
194 return tool;
195 }
196
197 wxToolBarToolBase *wxToolBarBase::AddControl(wxControl *control)
198 {
199 return InsertControl(GetToolsCount(), control);
200 }
201
202 wxToolBarToolBase *wxToolBarBase::InsertControl(size_t pos, wxControl *control)
203 {
204 wxCHECK_MSG( control, (wxToolBarToolBase *)NULL,
205 _T("toolbar: can't insert NULL control") );
206
207 wxCHECK_MSG( control->GetParent() == this, (wxToolBarToolBase *)NULL,
208 _T("control must have toolbar as parent") );
209
210 wxCHECK_MSG( pos <= GetToolsCount(), (wxToolBarToolBase *)NULL,
211 _T("invalid position in wxToolBar::InsertControl()") );
212
213 wxToolBarToolBase *tool = CreateTool(control);
214
215 if ( !InsertTool(pos, tool) )
216 {
217 delete tool;
218
219 return NULL;
220 }
221
222 return tool;
223 }
224
225 wxControl *wxToolBarBase::FindControl( int id )
226 {
227 for ( wxToolBarToolsList::Node* node = m_tools.GetFirst();
228 node;
229 node = node->GetNext() )
230 {
231 const wxToolBarToolBase * const tool = node->GetData();
232 if ( tool->IsControl() )
233 {
234 wxControl * const control = tool->GetControl();
235
236 if ( !control )
237 {
238 wxFAIL_MSG( _T("NULL control in toolbar?") );
239 }
240 else if ( control->GetId() == id )
241 {
242 // found
243 return control;
244 }
245 }
246 }
247
248 return NULL;
249 }
250
251 wxToolBarToolBase *wxToolBarBase::AddSeparator()
252 {
253 return InsertSeparator(GetToolsCount());
254 }
255
256 wxToolBarToolBase *wxToolBarBase::InsertSeparator(size_t pos)
257 {
258 wxCHECK_MSG( pos <= GetToolsCount(), (wxToolBarToolBase *)NULL,
259 _T("invalid position in wxToolBar::InsertSeparator()") );
260
261 wxToolBarToolBase *tool = CreateTool(wxID_SEPARATOR,
262 wxEmptyString,
263 wxNullBitmap, wxNullBitmap,
264 wxITEM_SEPARATOR, (wxObject *)NULL,
265 wxEmptyString, wxEmptyString);
266
267 if ( !tool || !DoInsertTool(pos, tool) )
268 {
269 delete tool;
270
271 return NULL;
272 }
273
274 m_tools.Insert(pos, tool);
275
276 return tool;
277 }
278
279 wxToolBarToolBase *wxToolBarBase::RemoveTool(int id)
280 {
281 size_t pos = 0;
282 wxToolBarToolsList::Node *node;
283 for ( node = m_tools.GetFirst(); node; node = node->GetNext() )
284 {
285 if ( node->GetData()->GetId() == id )
286 break;
287
288 pos++;
289 }
290
291 if ( !node )
292 {
293 // don't give any error messages - sometimes we might call RemoveTool()
294 // without knowing whether the tool is or not in the toolbar
295 return (wxToolBarToolBase *)NULL;
296 }
297
298 wxToolBarToolBase *tool = node->GetData();
299 if ( !DoDeleteTool(pos, tool) )
300 {
301 return (wxToolBarToolBase *)NULL;
302 }
303
304 // the node would delete the data, so set it to NULL to avoid this
305 node->SetData(NULL);
306
307 m_tools.DeleteNode(node);
308
309 return tool;
310 }
311
312 bool wxToolBarBase::DeleteToolByPos(size_t pos)
313 {
314 wxCHECK_MSG( pos < GetToolsCount(), FALSE,
315 _T("invalid position in wxToolBar::DeleteToolByPos()") );
316
317 wxToolBarToolsList::Node *node = m_tools.Item(pos);
318
319 if ( !DoDeleteTool(pos, node->GetData()) )
320 {
321 return FALSE;
322 }
323
324 m_tools.DeleteNode(node);
325
326 return TRUE;
327 }
328
329 bool wxToolBarBase::DeleteTool(int id)
330 {
331 size_t pos = 0;
332 wxToolBarToolsList::Node *node;
333 for ( node = m_tools.GetFirst(); node; node = node->GetNext() )
334 {
335 if ( node->GetData()->GetId() == id )
336 break;
337
338 pos++;
339 }
340
341 if ( !node || !DoDeleteTool(pos, node->GetData()) )
342 {
343 return FALSE;
344 }
345
346 m_tools.DeleteNode(node);
347
348 return TRUE;
349 }
350
351 wxToolBarToolBase *wxToolBarBase::FindById(int id) const
352 {
353 wxToolBarToolBase *tool = (wxToolBarToolBase *)NULL;
354
355 for ( wxToolBarToolsList::Node *node = m_tools.GetFirst();
356 node;
357 node = node->GetNext() )
358 {
359 tool = node->GetData();
360 if ( tool->GetId() == id )
361 {
362 // found
363 break;
364 }
365
366 tool = NULL;
367 }
368
369 return tool;
370 }
371
372 void wxToolBarBase::ClearTools()
373 {
374 m_tools.Clear();
375 }
376
377 bool wxToolBarBase::Realize()
378 {
379 return TRUE;
380 }
381
382 wxToolBarBase::~wxToolBarBase()
383 {
384 }
385
386 // ----------------------------------------------------------------------------
387 // wxToolBarBase tools state
388 // ----------------------------------------------------------------------------
389
390 void wxToolBarBase::EnableTool(int id, bool enable)
391 {
392 wxToolBarToolBase *tool = FindById(id);
393 if ( tool )
394 {
395 if ( tool->Enable(enable) )
396 {
397 DoEnableTool(tool, enable);
398 }
399 }
400 }
401
402 void wxToolBarBase::ToggleTool(int id, bool toggle)
403 {
404 wxToolBarToolBase *tool = FindById(id);
405 if ( tool && tool->CanBeToggled() )
406 {
407 if ( tool->Toggle(toggle) )
408 {
409 DoToggleTool(tool, toggle);
410 }
411 }
412 }
413
414 void wxToolBarBase::SetToggle(int id, bool toggle)
415 {
416 wxToolBarToolBase *tool = FindById(id);
417 if ( tool )
418 {
419 if ( tool->SetToggle(toggle) )
420 {
421 DoSetToggle(tool, toggle);
422 }
423 }
424 }
425
426 void wxToolBarBase::SetToolShortHelp(int id, const wxString& help)
427 {
428 wxToolBarToolBase *tool = FindById(id);
429 if ( tool )
430 {
431 (void)tool->SetShortHelp(help);
432 }
433 }
434
435 void wxToolBarBase::SetToolLongHelp(int id, const wxString& help)
436 {
437 wxToolBarToolBase *tool = FindById(id);
438 if ( tool )
439 {
440 (void)tool->SetLongHelp(help);
441 }
442 }
443
444 wxObject *wxToolBarBase::GetToolClientData(int id) const
445 {
446 wxToolBarToolBase *tool = FindById(id);
447
448 return tool ? tool->GetClientData() : (wxObject *)NULL;
449 }
450
451 void wxToolBarBase::SetToolClientData(int id, wxObject *clientData)
452 {
453 wxToolBarToolBase *tool = FindById(id);
454
455 wxCHECK_RET( tool, _T("no such tool in wxToolBar::SetToolClientData") );
456
457 tool->SetClientData(clientData);
458 }
459
460 int wxToolBarBase::GetToolPos(int id) const
461 {
462 size_t pos = 0;
463 wxToolBarToolsList::Node *node;
464
465 for ( node = m_tools.GetFirst(); node; node = node->GetNext() )
466 {
467 if ( node->GetData()->GetId() == id )
468 return pos;
469
470 pos++;
471 }
472
473 return wxNOT_FOUND;
474 }
475
476 bool wxToolBarBase::GetToolState(int id) const
477 {
478 wxToolBarToolBase *tool = FindById(id);
479 wxCHECK_MSG( tool, FALSE, _T("no such tool") );
480
481 return tool->IsToggled();
482 }
483
484 bool wxToolBarBase::GetToolEnabled(int id) const
485 {
486 wxToolBarToolBase *tool = FindById(id);
487 wxCHECK_MSG( tool, FALSE, _T("no such tool") );
488
489 return tool->IsEnabled();
490 }
491
492 wxString wxToolBarBase::GetToolShortHelp(int id) const
493 {
494 wxToolBarToolBase *tool = FindById(id);
495 wxCHECK_MSG( tool, _T(""), _T("no such tool") );
496
497 return tool->GetShortHelp();
498 }
499
500 wxString wxToolBarBase::GetToolLongHelp(int id) const
501 {
502 wxToolBarToolBase *tool = FindById(id);
503 wxCHECK_MSG( tool, _T(""), _T("no such tool") );
504
505 return tool->GetLongHelp();
506 }
507
508 // ----------------------------------------------------------------------------
509 // wxToolBarBase geometry
510 // ----------------------------------------------------------------------------
511
512 void wxToolBarBase::SetMargins(int x, int y)
513 {
514 m_xMargin = x;
515 m_yMargin = y;
516 }
517
518 void wxToolBarBase::SetRows(int WXUNUSED(nRows))
519 {
520 // nothing
521 }
522
523 // ----------------------------------------------------------------------------
524 // event processing
525 // ----------------------------------------------------------------------------
526
527 // Only allow toggle if returns TRUE
528 bool wxToolBarBase::OnLeftClick(int id, bool toggleDown)
529 {
530 wxCommandEvent event(wxEVT_COMMAND_TOOL_CLICKED, id);
531 event.SetEventObject(this);
532
533 // we use SetInt() to make wxCommandEvent::IsChecked() return toggleDown
534 event.SetInt((int)toggleDown);
535
536 // and SetExtraLong() for backwards compatibility
537 event.SetExtraLong((long)toggleDown);
538
539 // Send events to this toolbar instead (and thence up the window hierarchy)
540 GetEventHandler()->ProcessEvent(event);
541
542 return TRUE;
543 }
544
545 // Call when right button down.
546 void wxToolBarBase::OnRightClick(int id,
547 long WXUNUSED(x),
548 long WXUNUSED(y))
549 {
550 wxCommandEvent event(wxEVT_COMMAND_TOOL_RCLICKED, id);
551 event.SetEventObject(this);
552 event.SetInt(id);
553
554 GetEventHandler()->ProcessEvent(event);
555 }
556
557 // Called when the mouse cursor enters a tool bitmap (no button pressed).
558 // Argument is -1 if mouse is exiting the toolbar.
559 // Note that for this event, the id of the window is used,
560 // and the integer parameter of wxCommandEvent is used to retrieve
561 // the tool id.
562 void wxToolBarBase::OnMouseEnter(int id)
563 {
564 wxCommandEvent event(wxEVT_COMMAND_TOOL_ENTER, GetId());
565 event.SetEventObject(this);
566 event.SetInt(id);
567
568 wxFrame *frame = wxDynamicCast(GetParent(), wxFrame);
569 if( frame )
570 {
571 wxToolBarToolBase* tool = id == -1 ? (wxToolBarToolBase*)0 : FindById(id);
572 wxString help = tool ? tool->GetLongHelp() : wxString();
573 frame->DoGiveHelp( help, id != -1 );
574 }
575
576 (void)GetEventHandler()->ProcessEvent(event);
577 }
578
579 // ----------------------------------------------------------------------------
580 // UI updates
581 // ----------------------------------------------------------------------------
582
583 // Do the toolbar button updates (check for EVT_UPDATE_UI handlers)
584 void wxToolBarBase::UpdateWindowUI(long flags)
585 {
586 wxWindowBase::UpdateWindowUI(flags);
587
588 wxEvtHandler* evtHandler = GetEventHandler() ;
589
590 for ( wxToolBarToolsList::Node* node = m_tools.GetFirst();
591 node;
592 node = node->GetNext() )
593 {
594 int id = node->GetData()->GetId();
595
596 wxUpdateUIEvent event(id);
597 event.SetEventObject(this);
598
599 if ( evtHandler->ProcessEvent(event) )
600 {
601 if ( event.GetSetEnabled() )
602 EnableTool(id, event.GetEnabled());
603 if ( event.GetSetChecked() )
604 ToggleTool(id, event.GetChecked());
605 #if 0
606 if ( event.GetSetText() )
607 // Set tooltip?
608 #endif // 0
609 }
610 }
611 }
612
613 // Helper function, used by wxCreateGreyedImage
614
615 static void wxGreyOutImage( const wxImage& src,
616 wxImage& dest,
617 const wxColour& darkCol,
618 const wxColour& lightCol,
619 const wxColour& bgCol )
620 {
621 // Second attempt, just making things monochrome
622 int width = src.GetWidth();
623 int height = src.GetHeight();
624
625 int redCur, greenCur, blueCur;
626 for ( int x = 0; x < width; x++ )
627 {
628 for ( int y = 1; y < height; y++ )
629 {
630 redCur = src.GetRed(x, y);
631 greenCur = src.GetGreen(x, y);
632 blueCur = src.GetBlue(x, y);
633
634 // Change light things to the background colour
635 if ( redCur >= (lightCol.Red() - 50) && greenCur >= (lightCol.Green() - 50) && blueCur >= (lightCol.Blue() - 50) )
636 {
637 dest.SetRGB(x,y, bgCol.Red(), bgCol.Green(), bgCol.Blue());
638 }
639 else if ( redCur == bgCol.Red() && greenCur == bgCol.Green() && blueCur == bgCol.Blue() )
640 {
641 // Leave the background colour as-is
642 // dest.SetRGB(x,y, bgCol.Red(), bgCol.Green(), bgCol.Blue());
643 }
644 else // if ( redCur <= darkCol.Red() && greenCur <= darkCol.Green() && blueCur <= darkCol.Blue() )
645 {
646 // Change dark things to really dark
647 dest.SetRGB(x,y, darkCol.Red(), darkCol.Green(), darkCol.Blue());
648 }
649 }
650 }
651 }
652
653 /*
654 * Make a greyed-out image suitable for disabled buttons.
655 * This code is adapted from wxNewBitmapButton in FL.
656 */
657
658 bool wxCreateGreyedImage(const wxImage& in, wxImage& out)
659 {
660 out = in.Copy();
661
662 // assuming the pixels along the edges are of the background color
663 wxColour bgCol(in.GetRed(0, 0), in.GetGreen(0, 0), in.GetBlue(0, 0));
664
665 wxColour darkCol = wxSystemSettings::GetColour(wxSYS_COLOUR_3DSHADOW) ;
666 wxColour lightCol = wxSystemSettings::GetColour(wxSYS_COLOUR_3DHIGHLIGHT) ;
667
668 wxGreyOutImage(in, out, darkCol, lightCol, bgCol);
669
670 return TRUE;
671 }
672
673 #endif // wxUSE_TOOLBAR