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