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