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