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