]>
Commit | Line | Data |
---|---|---|
c08a4f00 RR |
1 | ///////////////////////////////////////////////////////////////////////////// |
2 | // Name: src/univ/toolbar.cpp | |
3216dbf5 VZ |
3 | // Purpose: implementation of wxToolBar for wxUniversal |
4 | // Author: Robert Roebling, Vadim Zeitlin (universalization) | |
5 | // Modified by: | |
6 | // Created: 20.02.02 | |
c08a4f00 | 7 | // Id: $Id$ |
3216dbf5 VZ |
8 | // Copyright: (c) 2001 Robert Roebling, |
9 | // (c) 2002 SciTech Software, Inc. (www.scitechsoft.com) | |
c08a4f00 RR |
10 | // Licence: wxWindows licence |
11 | ///////////////////////////////////////////////////////////////////////////// | |
12 | ||
13 | // ============================================================================ | |
14 | // declarations | |
15 | // ============================================================================ | |
16 | ||
17 | // ---------------------------------------------------------------------------- | |
18 | // headers | |
19 | // ---------------------------------------------------------------------------- | |
20 | ||
21 | #ifdef __GNUG__ | |
22 | #pragma implementation "univtoolbar.h" | |
23 | #endif | |
24 | ||
25 | // For compilers that support precompilation, includes "wx.h". | |
26 | #include "wx/wxprec.h" | |
27 | ||
28 | #ifdef __BORLANDC__ | |
29 | #pragma hdrstop | |
30 | #endif | |
31 | ||
6a317e61 VZ |
32 | #if wxUSE_TOOLBAR |
33 | ||
c08a4f00 RR |
34 | #ifndef WX_PRECOMP |
35 | #include "wx/utils.h" | |
36 | #include "wx/app.h" | |
3216dbf5 VZ |
37 | |
38 | #include "wx/univ/renderer.h" | |
c08a4f00 RR |
39 | #endif |
40 | ||
41 | #include "wx/toolbar.h" | |
c229e50d | 42 | #include "wx/image.h" |
c08a4f00 | 43 | |
3216dbf5 VZ |
44 | // ---------------------------------------------------------------------------- |
45 | // constants | |
46 | // ---------------------------------------------------------------------------- | |
47 | ||
48 | // value meaning that m_widthSeparator is not initialized | |
49 | static const wxCoord INVALID_WIDTH = -1; | |
50 | ||
51 | // ---------------------------------------------------------------------------- | |
52 | // wxToolBarTool: our implementation of wxToolBarToolBase | |
53 | // ---------------------------------------------------------------------------- | |
54 | ||
55 | class WXDLLEXPORT wxToolBarTool : public wxToolBarToolBase | |
16c9a425 | 56 | { |
3216dbf5 VZ |
57 | public: |
58 | wxToolBarTool( wxToolBarBase *tbar = (wxToolBarBase *)NULL, | |
59 | int id = wxID_SEPARATOR, | |
60 | const wxBitmap& bitmap1 = wxNullBitmap, | |
61 | const wxBitmap& bitmap2 = wxNullBitmap, | |
62 | bool toggle = FALSE, | |
63 | wxObject *clientData = (wxObject *) NULL, | |
64 | const wxString& shortHelpString = wxEmptyString, | |
65 | const wxString& longHelpString = wxEmptyString ) | |
66 | : wxToolBarToolBase(tbar, id, bitmap1, bitmap2, toggle, clientData, | |
67 | shortHelpString, longHelpString) | |
68 | { | |
69 | // no position yet | |
70 | m_x = | |
71 | m_y = -1; | |
5a73d082 VZ |
72 | |
73 | // not pressed yet | |
74 | m_isInverted = FALSE; | |
3216dbf5 VZ |
75 | } |
76 | ||
5a73d082 VZ |
77 | // is this tool pressed, even temporarily? (this is different from being |
78 | // permanently toggled which is what IsToggled() returns) | |
79 | bool IsPressed() const | |
80 | { return CanBeToggled() ? IsToggled() != m_isInverted : m_isInverted; } | |
81 | ||
82 | // are we temporarily pressed/unpressed? | |
83 | bool IsInverted() const { return m_isInverted; } | |
84 | ||
85 | // press the tool temporarily by inverting its toggle state | |
86 | void Invert() { m_isInverted = !m_isInverted; } | |
87 | ||
3216dbf5 VZ |
88 | public: |
89 | // the tool position (the size is known by the toolbar itself) | |
90 | int m_x, | |
91 | m_y; | |
5a73d082 VZ |
92 | |
93 | private: | |
94 | // TRUE if the tool is pressed | |
95 | bool m_isInverted; | |
3216dbf5 VZ |
96 | }; |
97 | ||
98 | // ============================================================================ | |
99 | // wxToolBar implementation | |
100 | // ============================================================================ | |
101 | ||
102 | IMPLEMENT_DYNAMIC_CLASS(wxToolBar, wxControl); | |
103 | ||
104 | // ---------------------------------------------------------------------------- | |
105 | // wxToolBar creation | |
106 | // ---------------------------------------------------------------------------- | |
c08a4f00 RR |
107 | |
108 | void wxToolBar::Init() | |
109 | { | |
3216dbf5 VZ |
110 | // no tools yet |
111 | m_needsLayout = FALSE; | |
112 | ||
113 | // unknown widths for the tools and separators | |
114 | m_widthSeparator = INVALID_WIDTH; | |
115 | ||
116 | m_maxWidth = | |
16c9a425 JS |
117 | m_maxHeight = 0; |
118 | ||
5a73d082 | 119 | m_toolPressed = NULL; |
3216dbf5 VZ |
120 | m_toolCurrent = NULL; |
121 | ||
122 | wxRenderer *renderer = GetRenderer(); | |
123 | ||
124 | SetToolBitmapSize(renderer->GetToolBarButtonSize(&m_widthSeparator)); | |
125 | SetMargins(renderer->GetToolBarMargin()); | |
c08a4f00 RR |
126 | } |
127 | ||
3216dbf5 VZ |
128 | bool wxToolBar::Create(wxWindow *parent, |
129 | wxWindowID id, | |
130 | const wxPoint& pos, | |
131 | const wxSize& size, | |
132 | long style, | |
133 | const wxString& name) | |
134 | { | |
135 | if ( !wxToolBarBase::Create(parent, id, pos, size, style, | |
136 | wxDefaultValidator, name) ) | |
137 | { | |
138 | return FALSE; | |
139 | } | |
140 | ||
141 | CreateInputHandler(wxINP_HANDLER_TOOLBAR); | |
142 | ||
143 | SetBestSize(size); | |
144 | ||
145 | return TRUE; | |
146 | } | |
147 | ||
148 | wxToolBar::~wxToolBar() | |
149 | { | |
150 | } | |
151 | ||
152 | // ---------------------------------------------------------------------------- | |
153 | // wxToolBar tool-related methods | |
154 | // ---------------------------------------------------------------------------- | |
155 | ||
c08a4f00 RR |
156 | wxToolBarToolBase *wxToolBar::FindToolForPosition(wxCoord x, wxCoord y) const |
157 | { | |
3216dbf5 VZ |
158 | // check the "other" direction first: it must be inside the toolbar or we |
159 | // don't risk finding anything | |
160 | if ( IsVertical() ) | |
161 | { | |
162 | if ( x < 0 || x > m_maxWidth ) | |
163 | return NULL; | |
164 | ||
165 | // we always use x, even for a vertical toolbar, this makes the code | |
166 | // below simpler | |
167 | x = y; | |
168 | } | |
169 | else // horizontal | |
170 | { | |
171 | if ( y < 0 || y > m_maxHeight ) | |
172 | return NULL; | |
173 | } | |
174 | ||
175 | for ( wxToolBarToolsList::Node *node = m_tools.GetFirst(); | |
176 | node; | |
177 | node = node->GetNext() ) | |
178 | { | |
179 | wxToolBarToolBase *tool = node->GetData(); | |
180 | wxRect rectTool = GetToolRect(tool); | |
181 | ||
182 | wxCoord startTool, endTool; | |
183 | GetRectLimits(rectTool, &startTool, &endTool); | |
184 | ||
185 | if ( x >= startTool && x <= endTool ) | |
186 | { | |
187 | // don't return the separators from here, they don't accept any | |
188 | // input anyhow | |
189 | return tool->IsSeparator() ? NULL : tool; | |
190 | } | |
191 | } | |
192 | ||
c08a4f00 RR |
193 | return NULL; |
194 | } | |
195 | ||
3216dbf5 | 196 | void wxToolBar::SetToolShortHelp(int id, const wxString& help) |
c08a4f00 | 197 | { |
3216dbf5 VZ |
198 | wxToolBarToolBase *tool = FindById(id); |
199 | ||
200 | wxCHECK_RET( tool, _T("SetToolShortHelp: no such tool") ); | |
201 | ||
202 | tool->SetShortHelp(help); | |
c08a4f00 RR |
203 | } |
204 | ||
3216dbf5 VZ |
205 | bool wxToolBar::DoInsertTool(size_t WXUNUSED(pos), |
206 | wxToolBarToolBase * WXUNUSED(tool)) | |
c08a4f00 | 207 | { |
3216dbf5 VZ |
208 | // recalculate the toolbar geometry before redrawing it the next time |
209 | m_needsLayout = TRUE; | |
210 | ||
211 | // and ensure that we indeed are going to redraw | |
212 | Refresh(); | |
213 | ||
c08a4f00 RR |
214 | return TRUE; |
215 | } | |
216 | ||
3216dbf5 VZ |
217 | bool wxToolBar::DoDeleteTool(size_t WXUNUSED(pos), |
218 | wxToolBarToolBase * WXUNUSED(tool)) | |
c08a4f00 | 219 | { |
3216dbf5 VZ |
220 | // as above |
221 | m_needsLayout = TRUE; | |
222 | ||
223 | Refresh(); | |
224 | ||
c08a4f00 RR |
225 | return TRUE; |
226 | } | |
227 | ||
228 | void wxToolBar::DoEnableTool(wxToolBarToolBase *tool, bool enable) | |
229 | { | |
3216dbf5 VZ |
230 | // created disabled-state bitmap on demand |
231 | if ( !enable && !tool->GetDisabledBitmap().Ok() ) | |
c229e50d | 232 | { |
3216dbf5 | 233 | wxImage image( tool->GetNormalBitmap() ); |
c229e50d | 234 | |
3216dbf5 | 235 | // TODO: don't hardcode 180 |
bb312b54 RR |
236 | unsigned char bg_red = 180; |
237 | unsigned char bg_green = 180; | |
238 | unsigned char bg_blue = 180; | |
3216dbf5 | 239 | |
bb312b54 RR |
240 | unsigned char mask_red = image.GetMaskRed(); |
241 | unsigned char mask_green = image.GetMaskGreen(); | |
242 | unsigned char mask_blue = image.GetMaskBlue(); | |
3216dbf5 | 243 | |
bb312b54 | 244 | bool has_mask = image.HasMask(); |
3216dbf5 | 245 | |
bb312b54 RR |
246 | int x,y; |
247 | for (y = 0; y < image.GetHeight(); y++) | |
248 | { | |
3216dbf5 | 249 | for (x = 0; x < image.GetWidth(); x++) |
bb312b54 RR |
250 | { |
251 | unsigned char red = image.GetRed(x,y); | |
252 | unsigned char green = image.GetGreen(x,y); | |
253 | unsigned char blue = image.GetBlue(x,y); | |
254 | if (!has_mask || red != mask_red || green != mask_green || blue != mask_blue) | |
255 | { | |
256 | red = (((wxInt32) red - bg_red) >> 1) + bg_red; | |
257 | green = (((wxInt32) green - bg_green) >> 1) + bg_green; | |
258 | blue = (((wxInt32) blue - bg_blue) >> 1) + bg_blue; | |
3216dbf5 | 259 | image.SetRGB( x, y, red, green, blue ); |
bb312b54 RR |
260 | } |
261 | } | |
262 | } | |
c229e50d | 263 | |
bb312b54 RR |
264 | for (y = 0; y < image.GetHeight(); y++) |
265 | { | |
3216dbf5 | 266 | for (x = y % 2; x < image.GetWidth(); x += 2) |
bb312b54 RR |
267 | { |
268 | unsigned char red = image.GetRed(x,y); | |
269 | unsigned char green = image.GetGreen(x,y); | |
270 | unsigned char blue = image.GetBlue(x,y); | |
271 | if (!has_mask || red != mask_red || green != mask_green || blue != mask_blue) | |
272 | { | |
273 | red = (((wxInt32) red - bg_red) >> 1) + bg_red; | |
274 | green = (((wxInt32) green - bg_green) >> 1) + bg_green; | |
275 | blue = (((wxInt32) blue - bg_blue) >> 1) + bg_blue; | |
276 | image.SetRGB( x, y, red, green, blue ); | |
277 | } | |
278 | } | |
279 | } | |
280 | ||
3216dbf5 | 281 | tool->SetDisabledBitmap( image.ConvertToBitmap() ); |
c229e50d | 282 | } |
3216dbf5 VZ |
283 | |
284 | RefreshTool(tool); | |
c08a4f00 RR |
285 | } |
286 | ||
3216dbf5 | 287 | void wxToolBar::DoToggleTool(wxToolBarToolBase *tool, bool WXUNUSED(toggle)) |
c08a4f00 | 288 | { |
3216dbf5 VZ |
289 | // note that if we're called the tool did change state (the base class |
290 | // checks for it), so it's not necessary to check for this again here | |
291 | RefreshTool(tool); | |
c08a4f00 RR |
292 | } |
293 | ||
3216dbf5 | 294 | void wxToolBar::DoSetToggle(wxToolBarToolBase *tool, bool WXUNUSED(toggle)) |
c08a4f00 | 295 | { |
3216dbf5 | 296 | RefreshTool(tool); |
c08a4f00 RR |
297 | } |
298 | ||
299 | wxToolBarToolBase *wxToolBar::CreateTool(int id, | |
3216dbf5 VZ |
300 | const wxBitmap& bitmap1, |
301 | const wxBitmap& bitmap2, | |
302 | bool toggle, | |
303 | wxObject *clientData, | |
304 | const wxString& shortHelpString, | |
305 | const wxString& longHelpString) | |
c08a4f00 RR |
306 | { |
307 | return new wxToolBarTool( this, id, bitmap1, bitmap2, toggle, | |
308 | clientData, shortHelpString, longHelpString); | |
309 | } | |
3216dbf5 | 310 | |
c08a4f00 RR |
311 | wxToolBarToolBase *wxToolBar::CreateTool(wxControl *control) |
312 | { | |
3216dbf5 VZ |
313 | wxFAIL_MSG( wxT("Toolbar doesn't support controls yet (TODO)") ); |
314 | ||
c08a4f00 RR |
315 | return NULL; |
316 | } | |
317 | ||
3216dbf5 VZ |
318 | // ---------------------------------------------------------------------------- |
319 | // wxToolBar geometry | |
320 | // ---------------------------------------------------------------------------- | |
c08a4f00 | 321 | |
3216dbf5 | 322 | wxRect wxToolBar::GetToolRect(wxToolBarToolBase *toolBase) const |
c08a4f00 | 323 | { |
3216dbf5 VZ |
324 | const wxToolBarTool *tool = (wxToolBarTool *)toolBase; |
325 | ||
326 | wxRect rect; | |
327 | ||
328 | wxCHECK_MSG( tool, rect, _T("GetToolRect: NULL tool") ); | |
329 | ||
330 | // ensure that we always have the valid tool position | |
331 | if ( m_needsLayout ) | |
bb312b54 | 332 | { |
3216dbf5 | 333 | wxConstCast(this, wxToolBar)->DoLayout(); |
bb312b54 | 334 | } |
3216dbf5 VZ |
335 | |
336 | rect.x = tool->m_x - m_xMargin; | |
337 | rect.y = tool->m_y - m_yMargin; | |
338 | ||
339 | if ( IsVertical() ) | |
c08a4f00 | 340 | { |
3216dbf5 VZ |
341 | rect.width = m_defaultWidth; |
342 | rect.height = tool->IsSeparator() ? m_widthSeparator : m_defaultHeight; | |
c08a4f00 | 343 | } |
3216dbf5 | 344 | else // horizontal |
c08a4f00 | 345 | { |
3216dbf5 VZ |
346 | rect.width = tool->IsSeparator() ? m_widthSeparator : m_defaultWidth; |
347 | rect.height = m_defaultHeight; | |
c08a4f00 | 348 | } |
3216dbf5 VZ |
349 | |
350 | rect.width += 2*m_xMargin; | |
351 | rect.height += 2*m_yMargin; | |
352 | ||
353 | return rect; | |
c08a4f00 RR |
354 | } |
355 | ||
3216dbf5 | 356 | bool wxToolBar::Realize() |
c08a4f00 | 357 | { |
3216dbf5 VZ |
358 | if ( !wxToolBarBase::Realize() ) |
359 | return FALSE; | |
360 | ||
361 | m_needsLayout = TRUE; | |
362 | DoLayout(); | |
363 | ||
364 | SetBestSize(wxDefaultSize); | |
365 | ||
366 | return TRUE; | |
367 | } | |
368 | ||
369 | void wxToolBar::DoLayout() | |
370 | { | |
371 | wxASSERT_MSG( m_needsLayout, _T("why are we called?") ); | |
372 | ||
373 | m_needsLayout = FALSE; | |
374 | ||
375 | wxCoord x = m_xMargin, | |
376 | y = m_yMargin; | |
377 | ||
378 | const wxCoord widthTool = IsVertical() ? m_defaultHeight : m_defaultWidth; | |
379 | wxCoord margin = IsVertical() ? m_xMargin : m_yMargin, | |
380 | *pCur = IsVertical() ? &y : &x; | |
381 | ||
382 | // calculate the positions of all elements | |
c08a4f00 RR |
383 | for ( wxToolBarToolsList::Node *node = m_tools.GetFirst(); |
384 | node; | |
385 | node = node->GetNext() ) | |
386 | { | |
3216dbf5 VZ |
387 | wxToolBarTool *tool = (wxToolBarTool *) node->GetData(); |
388 | ||
389 | tool->m_x = x; | |
390 | tool->m_y = y; | |
391 | ||
392 | *pCur += (tool->IsSeparator() ? m_widthSeparator : widthTool) + margin; | |
c08a4f00 | 393 | } |
3216dbf5 VZ |
394 | |
395 | // calculate the total toolbar size | |
396 | wxCoord xMin = m_defaultWidth + 2*m_xMargin, | |
397 | yMin = m_defaultHeight + 2*m_yMargin; | |
398 | ||
399 | m_maxWidth = x < xMin ? xMin : x; | |
400 | m_maxHeight = y < yMin ? yMin : y; | |
c08a4f00 RR |
401 | } |
402 | ||
3216dbf5 | 403 | wxSize wxToolBar::DoGetBestClientSize() const |
c08a4f00 | 404 | { |
3216dbf5 VZ |
405 | return wxSize(m_maxWidth, m_maxHeight); |
406 | } | |
407 | ||
408 | // ---------------------------------------------------------------------------- | |
409 | // wxToolBar drawing | |
410 | // ---------------------------------------------------------------------------- | |
c08a4f00 | 411 | |
3216dbf5 VZ |
412 | void wxToolBar::RefreshTool(wxToolBarToolBase *tool) |
413 | { | |
414 | RefreshRect(GetToolRect(tool)); | |
415 | } | |
416 | ||
417 | void wxToolBar::GetRectLimits(const wxRect& rect, | |
418 | wxCoord *start, | |
419 | wxCoord *end) const | |
420 | { | |
421 | wxCHECK_RET( start && end, _T("NULL pointer in GetRectLimits") ); | |
422 | ||
423 | if ( IsVertical() ) | |
16c9a425 | 424 | { |
3216dbf5 VZ |
425 | *start = rect.GetTop(); |
426 | *end = rect.GetBottom(); | |
16c9a425 | 427 | } |
3216dbf5 | 428 | else // horizontal |
16c9a425 | 429 | { |
3216dbf5 VZ |
430 | *start = rect.GetLeft(); |
431 | *end = rect.GetRight(); | |
16c9a425 | 432 | } |
3216dbf5 | 433 | } |
c08a4f00 | 434 | |
3216dbf5 VZ |
435 | void wxToolBar::DoDraw(wxControlRenderer *renderer) |
436 | { | |
437 | // prepare the variables used below | |
438 | wxDC& dc = renderer->GetDC(); | |
439 | wxRenderer *rend = renderer->GetRenderer(); | |
440 | // dc.SetFont(GetFont()); -- uncomment when we support labels | |
441 | ||
442 | // draw the border separating us from the menubar (if there is no menubar | |
443 | // we probably shouldn't draw it?) | |
444 | if ( !IsVertical() ) | |
445 | { | |
446 | rend->DrawHorizontalLine(dc, 0, 0, GetClientSize().x); | |
447 | } | |
448 | ||
449 | // get the update rect and its limits depending on the orientation | |
450 | wxRect rectUpdate = GetUpdateClientRect(); | |
451 | wxCoord start, end; | |
452 | GetRectLimits(rectUpdate, &start, &end); | |
453 | ||
454 | // and redraw all the tools intersecting it | |
c08a4f00 RR |
455 | for ( wxToolBarToolsList::Node *node = m_tools.GetFirst(); |
456 | node; | |
457 | node = node->GetNext() ) | |
458 | { | |
3216dbf5 VZ |
459 | wxToolBarToolBase *tool = node->GetData(); |
460 | wxRect rectTool = GetToolRect(tool); | |
461 | wxCoord startTool, endTool; | |
462 | GetRectLimits(rectTool, &startTool, &endTool); | |
463 | ||
464 | if ( endTool < start ) | |
c08a4f00 | 465 | { |
3216dbf5 VZ |
466 | // we're still to the left of the area to redraw |
467 | continue; | |
16c9a425 | 468 | } |
3216dbf5 VZ |
469 | |
470 | if ( startTool > end ) | |
16c9a425 | 471 | { |
3216dbf5 VZ |
472 | // we're beyond the area to redraw, nothing left to do |
473 | break; | |
474 | } | |
475 | ||
476 | // deal with the flags | |
477 | int flags = 0; | |
478 | ||
479 | if ( tool->IsEnabled() ) | |
480 | { | |
481 | // the toolbars without wxTB_FLAT don't react to the mouse hovering | |
482 | if ( HasFlag(wxTB_FLAT) && (tool == m_toolCurrent) ) | |
483 | flags |= wxCONTROL_CURRENT; | |
484 | } | |
485 | else // disabled tool | |
486 | { | |
487 | flags |= wxCONTROL_DISABLED; | |
c08a4f00 | 488 | } |
3216dbf5 | 489 | |
5a73d082 VZ |
490 | if ( tool == m_toolPressed ) |
491 | flags |= wxCONTROL_FOCUSED; | |
492 | ||
493 | if ( ((wxToolBarTool *)tool)->IsPressed() ) | |
3216dbf5 VZ |
494 | flags |= wxCONTROL_PRESSED; |
495 | ||
496 | wxString label; | |
497 | wxBitmap bitmap; | |
498 | if ( !tool->IsSeparator() ) | |
499 | { | |
500 | label = tool->GetLabel(); | |
501 | bitmap = tool->GetBitmap(); | |
502 | } | |
503 | //else: leave both the label and the bitmap invalid to draw a separator | |
504 | ||
505 | rend->DrawToolBarButton(dc, label, bitmap, rectTool, flags); | |
16c9a425 | 506 | } |
3216dbf5 | 507 | } |
16c9a425 | 508 | |
3216dbf5 VZ |
509 | // ---------------------------------------------------------------------------- |
510 | // wxToolBar actions | |
511 | // ---------------------------------------------------------------------------- | |
512 | ||
513 | void wxToolBar::Press() | |
514 | { | |
515 | wxCHECK_RET( m_toolCurrent, _T("no tool to press?") ); | |
516 | ||
4e89ceb1 VZ |
517 | wxLogTrace(_T("toolbar"), |
518 | _T("Button '%s' pressed."), | |
519 | m_toolCurrent->GetShortHelp().c_str()); | |
520 | ||
5a73d082 VZ |
521 | // this is the tool whose state is going to change |
522 | m_toolPressed = (wxToolBarTool *)m_toolCurrent; | |
3216dbf5 | 523 | |
5a73d082 VZ |
524 | // we must toggle it regardless of whether it is a checkable tool or not, |
525 | // so use Invert() and not Toggle() here | |
526 | m_toolPressed->Invert(); | |
527 | ||
528 | RefreshTool(m_toolPressed); | |
3216dbf5 VZ |
529 | } |
530 | ||
531 | void wxToolBar::Release() | |
532 | { | |
533 | wxCHECK_RET( m_toolPressed, _T("no tool to release?") ); | |
534 | ||
4e89ceb1 VZ |
535 | wxLogTrace(_T("toolbar"), |
536 | _T("Button '%s' released."), | |
537 | m_toolCurrent->GetShortHelp().c_str()); | |
538 | ||
5a73d082 | 539 | wxASSERT_MSG( m_toolPressed->IsInverted(), _T("release unpressed button?") ); |
5e885a58 | 540 | |
5a73d082 | 541 | m_toolPressed->Invert(); |
3216dbf5 | 542 | |
5a73d082 | 543 | RefreshTool(m_toolPressed); |
c08a4f00 RR |
544 | } |
545 | ||
3216dbf5 | 546 | void wxToolBar::Toggle() |
bb312b54 | 547 | { |
3216dbf5 | 548 | m_toolCurrent = m_toolPressed; |
5a73d082 VZ |
549 | |
550 | Release(); | |
3216dbf5 VZ |
551 | |
552 | Click(); | |
bb312b54 RR |
553 | } |
554 | ||
3216dbf5 | 555 | void wxToolBar::Click() |
bb312b54 | 556 | { |
3216dbf5 VZ |
557 | wxCHECK_RET( m_toolCurrent, _T("no tool to click?") ); |
558 | ||
5a73d082 VZ |
559 | bool isToggled; |
560 | if ( m_toolCurrent->CanBeToggled() ) | |
561 | { | |
562 | m_toolCurrent->Toggle(); | |
563 | ||
564 | RefreshTool(m_toolCurrent); | |
565 | ||
566 | isToggled = m_toolCurrent->IsToggled(); | |
567 | } | |
568 | else // simple non-checkable tool | |
569 | { | |
570 | isToggled = FALSE; | |
571 | } | |
572 | ||
573 | OnLeftClick(m_toolCurrent->GetId(), isToggled); | |
bb312b54 RR |
574 | } |
575 | ||
3216dbf5 VZ |
576 | bool wxToolBar::PerformAction(const wxControlAction& action, |
577 | long numArg, | |
578 | const wxString& strArg) | |
c08a4f00 | 579 | { |
3216dbf5 VZ |
580 | if ( action == wxACTION_TOOLBAR_TOGGLE ) |
581 | Toggle(); | |
582 | else if ( action == wxACTION_TOOLBAR_PRESS ) | |
583 | Press(); | |
584 | else if ( action == wxACTION_TOOLBAR_RELEASE ) | |
585 | Release(); | |
586 | else if ( action == wxACTION_TOOLBAR_CLICK ) | |
587 | Click(); | |
588 | else if ( action == wxACTION_TOOLBAR_ENTER ) | |
c08a4f00 | 589 | { |
3216dbf5 VZ |
590 | wxToolBarToolBase *toolCurrentOld = m_toolCurrent; |
591 | m_toolCurrent = FindById((int)numArg); | |
592 | ||
593 | if ( m_toolCurrent != toolCurrentOld ) | |
c08a4f00 | 594 | { |
3216dbf5 VZ |
595 | // the appearance of the current tool only changes for the flat |
596 | // toolbars | |
597 | if ( HasFlag(wxTB_FLAT) ) | |
598 | { | |
599 | // and only if the tool was/is enabled | |
600 | if ( toolCurrentOld && toolCurrentOld->IsEnabled() ) | |
601 | RefreshTool(toolCurrentOld); | |
602 | ||
603 | if ( m_toolCurrent ) | |
604 | { | |
605 | if ( m_toolCurrent->IsEnabled() ) | |
606 | RefreshTool(m_toolCurrent); | |
607 | } | |
608 | else | |
609 | { | |
610 | wxFAIL_MSG( _T("no current tool in wxACTION_TOOLBAR_ENTER?") ); | |
611 | } | |
612 | } | |
c08a4f00 RR |
613 | } |
614 | } | |
3216dbf5 | 615 | else if ( action == wxACTION_TOOLBAR_LEAVE ) |
bb312b54 | 616 | { |
3216dbf5 | 617 | if ( m_toolCurrent ) |
bb312b54 | 618 | { |
3216dbf5 VZ |
619 | wxToolBarToolBase *toolCurrentOld = m_toolCurrent; |
620 | m_toolCurrent = NULL; | |
621 | ||
622 | RefreshTool(toolCurrentOld); | |
bb312b54 | 623 | } |
c08a4f00 | 624 | } |
3216dbf5 VZ |
625 | else |
626 | return wxControl::PerformAction(action, numArg, strArg); | |
627 | ||
628 | return TRUE; | |
629 | } | |
630 | ||
631 | // ============================================================================ | |
632 | // wxStdToolbarInputHandler implementation | |
633 | // ============================================================================ | |
634 | ||
635 | wxStdToolbarInputHandler::wxStdToolbarInputHandler(wxInputHandler *handler) | |
636 | : wxStdButtonInputHandler(handler) | |
637 | { | |
638 | } | |
639 | ||
640 | bool wxStdToolbarInputHandler::HandleKey(wxInputConsumer *consumer, | |
641 | const wxKeyEvent& event, | |
642 | bool pressed) | |
643 | { | |
644 | // TODO: when we have a current button we should allow the arrow | |
645 | // keys to move it | |
646 | return wxStdInputHandler::HandleKey(consumer, event, pressed); | |
647 | } | |
648 | ||
4e89ceb1 VZ |
649 | bool wxStdToolbarInputHandler::HandleMouse(wxInputConsumer *consumer, |
650 | const wxMouseEvent& event) | |
651 | { | |
652 | // don't let the base class press the disabled buttons but simply ignore | |
653 | // all events on them | |
654 | wxToolBar *tbar = wxStaticCast(consumer->GetInputWindow(), wxToolBar); | |
655 | wxToolBarToolBase *tool = tbar->FindToolForPosition(event.GetX(), event.GetY()); | |
656 | ||
8b3fddc4 | 657 | if ( !tool || !tool->IsEnabled() ) |
4e89ceb1 VZ |
658 | return TRUE; |
659 | ||
660 | return wxStdButtonInputHandler::HandleMouse(consumer, event); | |
661 | } | |
662 | ||
3216dbf5 VZ |
663 | bool wxStdToolbarInputHandler::HandleMouseMove(wxInputConsumer *consumer, |
664 | const wxMouseEvent& event) | |
665 | { | |
666 | if ( !wxStdButtonInputHandler::HandleMouseMove(consumer, event) ) | |
c08a4f00 | 667 | { |
3216dbf5 VZ |
668 | wxToolBarToolBase *tool; |
669 | ||
670 | if ( event.Leaving() ) | |
c08a4f00 | 671 | { |
3216dbf5 | 672 | tool = NULL; |
c08a4f00 | 673 | } |
3216dbf5 | 674 | else |
c08a4f00 | 675 | { |
3216dbf5 VZ |
676 | wxToolBar *tbar = wxStaticCast(consumer->GetInputWindow(), wxToolBar); |
677 | tool = tbar->FindToolForPosition(event.GetX(), event.GetY()); | |
c08a4f00 | 678 | } |
3216dbf5 VZ |
679 | |
680 | if ( tool ) | |
681 | consumer->PerformAction(wxACTION_TOOLBAR_ENTER, tool->GetId()); | |
682 | else | |
683 | consumer->PerformAction(wxACTION_TOOLBAR_LEAVE); | |
684 | ||
685 | return TRUE; | |
bb312b54 | 686 | } |
3216dbf5 VZ |
687 | |
688 | return FALSE; | |
689 | } | |
690 | ||
691 | bool wxStdToolbarInputHandler::HandleFocus(wxInputConsumer *consumer, | |
692 | const wxFocusEvent& event) | |
693 | { | |
694 | // we shouldn't be left with a highlighted button | |
695 | consumer->PerformAction(wxACTION_TOOLBAR_LEAVE); | |
696 | ||
697 | return TRUE; | |
698 | } | |
699 | ||
700 | bool wxStdToolbarInputHandler::HandleActivation(wxInputConsumer *consumer, | |
701 | bool activated) | |
702 | { | |
703 | // as above | |
704 | if ( !activated ) | |
705 | consumer->PerformAction(wxACTION_TOOLBAR_LEAVE); | |
706 | ||
707 | return TRUE; | |
c08a4f00 RR |
708 | } |
709 | ||
6a317e61 VZ |
710 | #endif // wxUSE_TOOLBAR |
711 |