]> git.saurik.com Git - wxWidgets.git/blob - src/gtk/toolbar.cpp
Use two step creation of wxListHeaderWindow to avoid reentrancy under OSX.
[wxWidgets.git] / src / gtk / toolbar.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/gtk/toolbar.cpp
3 // Purpose: GTK toolbar
4 // Author: Robert Roebling
5 // Modified: 13.12.99 by VZ to derive from wxToolBarBase
6 // RCS-ID: $Id$
7 // Copyright: (c) Robert Roebling
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
10
11 // For compilers that support precompilation, includes "wx.h".
12 #include "wx/wxprec.h"
13
14 #if wxUSE_TOOLBAR_NATIVE
15
16 #include "wx/toolbar.h"
17
18 #include <gtk/gtk.h>
19 #include "wx/gtk/private.h"
20 #include "wx/gtk/private/gtk2-compat.h"
21
22 // ----------------------------------------------------------------------------
23 // globals
24 // ----------------------------------------------------------------------------
25
26 // data
27 extern bool g_blockEventsOnDrag;
28 extern wxCursor g_globalCursor;
29
30 // ----------------------------------------------------------------------------
31 // wxToolBarTool
32 // ----------------------------------------------------------------------------
33
34 class wxToolBarTool : public wxToolBarToolBase
35 {
36 public:
37 wxToolBarTool(wxToolBar *tbar,
38 int id,
39 const wxString& label,
40 const wxBitmap& bitmap1,
41 const wxBitmap& bitmap2,
42 wxItemKind kind,
43 wxObject *clientData,
44 const wxString& shortHelpString,
45 const wxString& longHelpString)
46 : wxToolBarToolBase(tbar, id, label, bitmap1, bitmap2, kind,
47 clientData, shortHelpString, longHelpString)
48 {
49 m_item = NULL;
50 }
51
52 wxToolBarTool(wxToolBar *tbar, wxControl *control, const wxString& label)
53 : wxToolBarToolBase(tbar, control, label)
54 {
55 m_item = NULL;
56 }
57
58 void SetImage();
59 void CreateDropDown();
60 void ShowDropdown(GtkToggleButton* button);
61
62 GtkToolItem* m_item;
63 };
64
65 // ----------------------------------------------------------------------------
66 // wxWin macros
67 // ----------------------------------------------------------------------------
68
69 IMPLEMENT_DYNAMIC_CLASS(wxToolBar, wxControl)
70
71 // ============================================================================
72 // implementation
73 // ============================================================================
74
75 //-----------------------------------------------------------------------------
76 // "clicked" from m_item
77 //-----------------------------------------------------------------------------
78
79 extern "C" {
80 static void item_clicked(GtkToolButton*, wxToolBarTool* tool)
81 {
82 if (g_blockEventsOnDrag) return;
83
84 tool->GetToolBar()->OnLeftClick(tool->GetId(), false);
85 }
86 }
87
88 //-----------------------------------------------------------------------------
89 // "toggled" from m_item
90 //-----------------------------------------------------------------------------
91
92 extern "C" {
93 static void item_toggled(GtkToggleToolButton* button, wxToolBarTool* tool)
94 {
95 if (g_blockEventsOnDrag) return;
96
97 const bool active = gtk_toggle_tool_button_get_active(button) != 0;
98 tool->Toggle(active);
99 if (!active && tool->GetKind() == wxITEM_RADIO)
100 return;
101
102 if (!tool->GetToolBar()->OnLeftClick(tool->GetId(), active))
103 {
104 // revert back
105 tool->Toggle();
106 }
107 }
108 }
109
110 //-----------------------------------------------------------------------------
111 // "button_press_event" from m_item child
112 //-----------------------------------------------------------------------------
113
114 extern "C" {
115 static gboolean
116 button_press_event(GtkWidget*, GdkEventButton* event, wxToolBarTool* tool)
117 {
118 if (event->button != 3)
119 return FALSE;
120
121 if (g_blockEventsOnDrag) return TRUE;
122
123 tool->GetToolBar()->OnRightClick(
124 tool->GetId(), int(event->x), int(event->y));
125
126 return TRUE;
127 }
128 }
129
130 //-----------------------------------------------------------------------------
131 // "child_detached" from m_widget
132 //-----------------------------------------------------------------------------
133
134 extern "C" {
135 static void child_detached(GtkWidget*, GtkToolbar* toolbar, void*)
136 {
137 // disable showing overflow arrow when toolbar is detached,
138 // otherwise toolbar collapses to just an arrow
139 gtk_toolbar_set_show_arrow(toolbar, false);
140 }
141 }
142
143 //-----------------------------------------------------------------------------
144 // "child_attached" from m_widget
145 //-----------------------------------------------------------------------------
146
147 extern "C" {
148 static void child_attached(GtkWidget*, GtkToolbar* toolbar, void*)
149 {
150 gtk_toolbar_set_show_arrow(toolbar, true);
151 }
152 }
153
154 //-----------------------------------------------------------------------------
155 // "enter_notify_event" / "leave_notify_event" from m_item
156 //-----------------------------------------------------------------------------
157
158 extern "C" {
159 static gboolean
160 enter_notify_event(GtkWidget*, GdkEventCrossing* event, wxToolBarTool* tool)
161 {
162 if (g_blockEventsOnDrag) return TRUE;
163
164 int id = -1;
165 if (event->type == GDK_ENTER_NOTIFY)
166 id = tool->GetId();
167 tool->GetToolBar()->OnMouseEnter(id);
168
169 return FALSE;
170 }
171 }
172
173 //-----------------------------------------------------------------------------
174 // "expose_event" from GtkImage inside m_item
175 //-----------------------------------------------------------------------------
176
177 extern "C" {
178 static gboolean
179 #ifdef __WXGTK3__
180 image_draw(GtkWidget* widget, cairo_t* cr, wxToolBarTool* tool)
181 #else
182 image_expose_event(GtkWidget* widget, GdkEventExpose*, wxToolBarTool* tool)
183 #endif
184 {
185 const wxBitmap& bitmap = tool->GetDisabledBitmap();
186 if (tool->IsEnabled() || !bitmap.IsOk())
187 return false;
188
189 // draw disabled bitmap ourselves, GtkImage has no way to specify it
190 GtkAllocation alloc;
191 gtk_widget_get_allocation(widget, &alloc);
192 GtkRequisition req;
193 gtk_widget_get_requisition(widget, &req);
194 const int x = alloc.x + (alloc.width - req.width) / 2;
195 const int y = alloc.y + (alloc.height - req.height) / 2;
196 #ifdef __WXGTK3__
197 bitmap.Draw(cr, x, y);
198 #else
199 gdk_draw_pixbuf(
200 gtk_widget_get_window(widget), gtk_widget_get_style(widget)->black_gc, bitmap.GetPixbuf(),
201 0, 0, x, y,
202 -1, -1, GDK_RGB_DITHER_NORMAL, 0, 0);
203 #endif
204 return true;
205 }
206 }
207
208 //-----------------------------------------------------------------------------
209 // "toggled" from dropdown menu button
210 //-----------------------------------------------------------------------------
211
212 extern "C" {
213 static void arrow_toggled(GtkToggleButton* button, wxToolBarTool* tool)
214 {
215 if (gtk_toggle_button_get_active(button))
216 {
217 tool->ShowDropdown(button);
218 gtk_toggle_button_set_active(button, false);
219 }
220 }
221 }
222
223 //-----------------------------------------------------------------------------
224 // "button_press_event" from dropdown menu button
225 //-----------------------------------------------------------------------------
226
227 extern "C" {
228 static gboolean
229 arrow_button_press_event(GtkToggleButton* button, GdkEventButton* event, wxToolBarTool* tool)
230 {
231 if (event->button == 1)
232 {
233 g_signal_handlers_block_by_func(button, (void*)arrow_toggled, tool);
234 gtk_toggle_button_set_active(button, true);
235 tool->ShowDropdown(button);
236 gtk_toggle_button_set_active(button, false);
237 g_signal_handlers_unblock_by_func(button, (void*)arrow_toggled, tool);
238 return true;
239 }
240 return false;
241 }
242 }
243
244 void wxToolBar::AddChildGTK(wxWindowGTK* child)
245 {
246 GtkWidget* align = gtk_alignment_new(0.5, 0.5, 0, 0);
247 gtk_widget_show(align);
248 gtk_container_add(GTK_CONTAINER(align), child->m_widget);
249 GtkToolItem* item = gtk_tool_item_new();
250 gtk_container_add(GTK_CONTAINER(item), align);
251 // position will be corrected in DoInsertTool if necessary
252 gtk_toolbar_insert(GTK_TOOLBAR(gtk_bin_get_child(GTK_BIN(m_widget))), item, -1);
253 }
254
255 // ----------------------------------------------------------------------------
256 // wxToolBarTool
257 // ----------------------------------------------------------------------------
258
259 void wxToolBarTool::SetImage()
260 {
261 const wxBitmap& bitmap = GetNormalBitmap();
262 wxCHECK_RET(bitmap.IsOk(), "invalid bitmap for wxToolBar icon");
263
264 GtkWidget* image = gtk_tool_button_get_icon_widget(GTK_TOOL_BUTTON(m_item));
265 // always use pixbuf, because pixmap mask does not
266 // work with disabled images in some themes
267 gtk_image_set_from_pixbuf(GTK_IMAGE(image), bitmap.GetPixbuf());
268 }
269
270 // helper to create a dropdown menu item
271 void wxToolBarTool::CreateDropDown()
272 {
273 gtk_tool_item_set_homogeneous(m_item, false);
274 GtkOrientation orient = GTK_ORIENTATION_HORIZONTAL;
275 GtkArrowType arrowType = GTK_ARROW_DOWN;
276 if (GetToolBar()->HasFlag(wxTB_LEFT | wxTB_RIGHT))
277 {
278 orient = GTK_ORIENTATION_VERTICAL;
279 arrowType = GTK_ARROW_RIGHT;
280 }
281 GtkWidget* box = gtk_box_new(orient, 0);
282 GtkWidget* arrow = gtk_arrow_new(arrowType, GTK_SHADOW_NONE);
283 GtkWidget* tool_button = gtk_bin_get_child(GTK_BIN(m_item));
284 gtk_widget_reparent(tool_button, box);
285 GtkWidget* arrow_button = gtk_toggle_button_new();
286 gtk_button_set_relief(GTK_BUTTON(arrow_button),
287 gtk_tool_item_get_relief_style(GTK_TOOL_ITEM(m_item)));
288 gtk_container_add(GTK_CONTAINER(arrow_button), arrow);
289 gtk_container_add(GTK_CONTAINER(box), arrow_button);
290 gtk_widget_show_all(box);
291 gtk_container_add(GTK_CONTAINER(m_item), box);
292
293 g_signal_connect(arrow_button, "toggled", G_CALLBACK(arrow_toggled), this);
294 g_signal_connect(arrow_button, "button_press_event",
295 G_CALLBACK(arrow_button_press_event), this);
296 }
297
298 void wxToolBarTool::ShowDropdown(GtkToggleButton* button)
299 {
300 wxToolBarBase* toolbar = GetToolBar();
301 wxCommandEvent event(wxEVT_TOOL_DROPDOWN, GetId());
302 if (!toolbar->HandleWindowEvent(event))
303 {
304 wxMenu* menu = GetDropdownMenu();
305 if (menu)
306 {
307 GtkAllocation alloc;
308 gtk_widget_get_allocation(GTK_WIDGET(button), &alloc);
309 int x = alloc.x;
310 int y = alloc.y;
311 if (toolbar->HasFlag(wxTB_LEFT | wxTB_RIGHT))
312 x += alloc.width;
313 else
314 y += alloc.height;
315 toolbar->PopupMenu(menu, x, y);
316 }
317 }
318 }
319
320 wxToolBarToolBase *wxToolBar::CreateTool(int id,
321 const wxString& text,
322 const wxBitmap& bitmap1,
323 const wxBitmap& bitmap2,
324 wxItemKind kind,
325 wxObject *clientData,
326 const wxString& shortHelpString,
327 const wxString& longHelpString)
328 {
329 return new wxToolBarTool(this, id, text, bitmap1, bitmap2, kind,
330 clientData, shortHelpString, longHelpString);
331 }
332
333 wxToolBarToolBase *
334 wxToolBar::CreateTool(wxControl *control, const wxString& label)
335 {
336 return new wxToolBarTool(this, control, label);
337 }
338
339 //-----------------------------------------------------------------------------
340 // wxToolBar construction
341 //-----------------------------------------------------------------------------
342
343 void wxToolBar::Init()
344 {
345 m_toolbar = NULL;
346 m_tooltips = NULL;
347 }
348
349 wxToolBar::~wxToolBar()
350 {
351 #ifndef __WXGTK3__
352 if (m_tooltips) // always NULL if GTK >= 2.12
353 {
354 gtk_object_destroy(GTK_OBJECT(m_tooltips));
355 g_object_unref(m_tooltips);
356 }
357 #endif
358 }
359
360 bool wxToolBar::Create( wxWindow *parent,
361 wxWindowID id,
362 const wxPoint& pos,
363 const wxSize& size,
364 long style,
365 const wxString& name )
366 {
367 if ( !PreCreation( parent, pos, size ) ||
368 !CreateBase( parent, id, pos, size, style, wxDefaultValidator, name ))
369 {
370 wxFAIL_MSG( wxT("wxToolBar creation failed") );
371
372 return false;
373 }
374
375 FixupStyle();
376
377 m_toolbar = GTK_TOOLBAR( gtk_toolbar_new() );
378 #ifndef __WXGTK3__
379 if (gtk_check_version(2, 12, 0))
380 {
381 m_tooltips = gtk_tooltips_new();
382 g_object_ref(m_tooltips);
383 gtk_object_sink(GTK_OBJECT(m_tooltips));
384 }
385 #endif
386 GtkSetStyle();
387
388 if (style & wxTB_DOCKABLE)
389 {
390 m_widget = gtk_handle_box_new();
391
392 g_signal_connect(m_widget, "child_detached",
393 G_CALLBACK(child_detached), NULL);
394 g_signal_connect(m_widget, "child_attached",
395 G_CALLBACK(child_attached), NULL);
396
397 if (style & wxTB_FLAT)
398 gtk_handle_box_set_shadow_type( GTK_HANDLE_BOX(m_widget), GTK_SHADOW_NONE );
399 }
400 else
401 {
402 m_widget = gtk_event_box_new();
403 ConnectWidget( m_widget );
404 }
405 g_object_ref(m_widget);
406 gtk_container_add(GTK_CONTAINER(m_widget), GTK_WIDGET(m_toolbar));
407 gtk_widget_show(GTK_WIDGET(m_toolbar));
408
409 m_parent->DoAddChild( this );
410
411 PostCreation(size);
412
413 return true;
414 }
415
416 GdkWindow *wxToolBar::GTKGetWindow(wxArrayGdkWindows& WXUNUSED(windows)) const
417 {
418 return gtk_widget_get_window(GTK_WIDGET(m_toolbar));
419 }
420
421 void wxToolBar::GtkSetStyle()
422 {
423 GtkOrientation orient = GTK_ORIENTATION_HORIZONTAL;
424 if (HasFlag(wxTB_LEFT | wxTB_RIGHT))
425 orient = GTK_ORIENTATION_VERTICAL;
426
427 GtkToolbarStyle style = GTK_TOOLBAR_ICONS;
428 if (HasFlag(wxTB_NOICONS))
429 style = GTK_TOOLBAR_TEXT;
430 else if (HasFlag(wxTB_TEXT))
431 {
432 style = GTK_TOOLBAR_BOTH;
433 if (HasFlag(wxTB_HORZ_LAYOUT))
434 style = GTK_TOOLBAR_BOTH_HORIZ;
435 }
436
437 #ifdef __WXGTK3__
438 gtk_orientable_set_orientation(GTK_ORIENTABLE(m_toolbar), orient);
439 #else
440 gtk_toolbar_set_orientation(m_toolbar, orient);
441 #endif
442 gtk_toolbar_set_style(m_toolbar, style);
443 }
444
445 void wxToolBar::SetWindowStyleFlag( long style )
446 {
447 wxToolBarBase::SetWindowStyleFlag(style);
448
449 if ( m_toolbar )
450 GtkSetStyle();
451 }
452
453 bool wxToolBar::Realize()
454 {
455 if ( !wxToolBarBase::Realize() )
456 return false;
457
458 // bring the initial state of all the toolbar items in line with the
459 // internal state if the latter was changed by calling wxToolBarTool::
460 // Enable(): this works under MSW, where the toolbar items are only created
461 // in Realize() which uses the internal state to determine the initial
462 // button state, so make it work under GTK too
463 for ( wxToolBarToolsList::const_iterator i = m_tools.begin();
464 i != m_tools.end();
465 ++i )
466 {
467 // by default the toolbar items are enabled and not toggled, so we only
468 // have to do something if their internal state doesn't correspond to
469 // this
470 if ( !(*i)->IsEnabled() )
471 DoEnableTool(*i, false);
472 if ( (*i)->IsToggled() )
473 DoToggleTool(*i, true);
474 }
475
476 return true;
477 }
478
479 bool wxToolBar::DoInsertTool(size_t pos, wxToolBarToolBase *toolBase)
480 {
481 wxToolBarTool* tool = static_cast<wxToolBarTool*>(toolBase);
482
483 GSList* radioGroup;
484 GtkWidget* bin_child;
485 switch ( tool->GetStyle() )
486 {
487 case wxTOOL_STYLE_BUTTON:
488 switch (tool->GetKind())
489 {
490 case wxITEM_CHECK:
491 tool->m_item = gtk_toggle_tool_button_new();
492 g_signal_connect(tool->m_item, "toggled",
493 G_CALLBACK(item_toggled), tool);
494 break;
495 case wxITEM_RADIO:
496 radioGroup = GetRadioGroup(pos);
497 if (!radioGroup)
498 {
499 // this is the first button in the radio button group,
500 // it will be toggled automatically by GTK so bring the
501 // internal flag in sync
502 tool->Toggle(true);
503 }
504 tool->m_item = gtk_radio_tool_button_new(radioGroup);
505 g_signal_connect(tool->m_item, "toggled",
506 G_CALLBACK(item_toggled), tool);
507 break;
508 default:
509 wxFAIL_MSG("unknown toolbar child type");
510 // fall through
511 case wxITEM_DROPDOWN:
512 case wxITEM_NORMAL:
513 tool->m_item = gtk_tool_button_new(NULL, "");
514 g_signal_connect(tool->m_item, "clicked",
515 G_CALLBACK(item_clicked), tool);
516 break;
517 }
518 if (!HasFlag(wxTB_NOICONS))
519 {
520 GtkWidget* image = gtk_image_new();
521 gtk_tool_button_set_icon_widget(
522 GTK_TOOL_BUTTON(tool->m_item), image);
523 tool->SetImage();
524 gtk_widget_show(image);
525 #ifdef __WXGTK3__
526 g_signal_connect(image, "draw",
527 G_CALLBACK(image_draw), tool);
528 #else
529 g_signal_connect(image, "expose_event",
530 G_CALLBACK(image_expose_event), tool);
531 #endif
532 }
533 if (!tool->GetLabel().empty())
534 {
535 gtk_tool_button_set_label(
536 GTK_TOOL_BUTTON(tool->m_item), wxGTK_CONV(tool->GetLabel()));
537 // needed for labels in horizontal toolbar with wxTB_HORZ_LAYOUT
538 gtk_tool_item_set_is_important(tool->m_item, true);
539 }
540 if (!HasFlag(wxTB_NO_TOOLTIPS) && !tool->GetShortHelp().empty())
541 {
542 #if GTK_CHECK_VERSION(2, 12, 0)
543 if (GTK_CHECK_VERSION(3,0,0) || gtk_check_version(2,12,0) == NULL)
544 {
545 gtk_tool_item_set_tooltip_text(tool->m_item,
546 wxGTK_CONV(tool->GetShortHelp()));
547 }
548 else
549 #endif
550 {
551 #ifndef __WXGTK3__
552 gtk_tool_item_set_tooltip(tool->m_item,
553 m_tooltips, wxGTK_CONV(tool->GetShortHelp()), "");
554 #endif
555 }
556 }
557 bin_child = gtk_bin_get_child(GTK_BIN(tool->m_item));
558 g_signal_connect(bin_child, "button_press_event",
559 G_CALLBACK(button_press_event), tool);
560 g_signal_connect(bin_child, "enter_notify_event",
561 G_CALLBACK(enter_notify_event), tool);
562 g_signal_connect(bin_child, "leave_notify_event",
563 G_CALLBACK(enter_notify_event), tool);
564
565 if (tool->GetKind() == wxITEM_DROPDOWN)
566 tool->CreateDropDown();
567 gtk_toolbar_insert(m_toolbar, tool->m_item, int(pos));
568 break;
569
570 case wxTOOL_STYLE_SEPARATOR:
571 tool->m_item = gtk_separator_tool_item_new();
572 if ( tool->IsStretchable() )
573 {
574 gtk_separator_tool_item_set_draw
575 (
576 GTK_SEPARATOR_TOOL_ITEM(tool->m_item),
577 FALSE
578 );
579 gtk_tool_item_set_expand(tool->m_item, TRUE);
580 }
581 gtk_toolbar_insert(m_toolbar, tool->m_item, int(pos));
582 break;
583
584 case wxTOOL_STYLE_CONTROL:
585 wxWindow* control = tool->GetControl();
586 if (gtk_widget_get_parent(control->m_widget) == NULL)
587 AddChildGTK(control);
588 tool->m_item = GTK_TOOL_ITEM(gtk_widget_get_parent(gtk_widget_get_parent(control->m_widget)));
589 if (gtk_toolbar_get_item_index(m_toolbar, tool->m_item) != int(pos))
590 {
591 g_object_ref(tool->m_item);
592 gtk_container_remove(
593 GTK_CONTAINER(m_toolbar), GTK_WIDGET(tool->m_item));
594 gtk_toolbar_insert(m_toolbar, tool->m_item, int(pos));
595 g_object_unref(tool->m_item);
596 }
597 break;
598 }
599 gtk_widget_show(GTK_WIDGET(tool->m_item));
600
601 InvalidateBestSize();
602
603 return true;
604 }
605
606 bool wxToolBar::DoDeleteTool(size_t /* pos */, wxToolBarToolBase* toolBase)
607 {
608 wxToolBarTool* tool = static_cast<wxToolBarTool*>(toolBase);
609
610 if (tool->GetStyle() == wxTOOL_STYLE_CONTROL)
611 {
612 // don't destroy the control here as we can be called from
613 // RemoveTool() and then we need to keep the control alive;
614 // while if we're called from DeleteTool() the control will
615 // be destroyed when wxToolBarToolBase itself is deleted
616 GtkWidget* widget = tool->GetControl()->m_widget;
617 gtk_container_remove(GTK_CONTAINER(gtk_widget_get_parent(widget)), widget);
618 }
619 gtk_widget_destroy(GTK_WIDGET(tool->m_item));
620 tool->m_item = NULL;
621
622 InvalidateBestSize();
623 return true;
624 }
625
626 GSList* wxToolBar::GetRadioGroup(size_t pos)
627 {
628 GSList* radioGroup = NULL;
629 GtkToolItem* item = NULL;
630 if (pos > 0)
631 {
632 item = gtk_toolbar_get_nth_item(m_toolbar, int(pos) - 1);
633 if (!GTK_IS_RADIO_TOOL_BUTTON(item))
634 item = NULL;
635 }
636 if (item == NULL && pos < m_tools.size())
637 {
638 item = gtk_toolbar_get_nth_item(m_toolbar, int(pos));
639 if (!GTK_IS_RADIO_TOOL_BUTTON(item))
640 item = NULL;
641 }
642 if (item)
643 radioGroup = gtk_radio_tool_button_get_group((GtkRadioToolButton*)item);
644 return radioGroup;
645 }
646
647 // ----------------------------------------------------------------------------
648 // wxToolBar tools state
649 // ----------------------------------------------------------------------------
650
651 void wxToolBar::DoEnableTool(wxToolBarToolBase *toolBase, bool enable)
652 {
653 wxToolBarTool* tool = static_cast<wxToolBarTool*>(toolBase);
654
655 if (tool->m_item)
656 gtk_widget_set_sensitive(GTK_WIDGET(tool->m_item), enable);
657 }
658
659 void wxToolBar::DoToggleTool( wxToolBarToolBase *toolBase, bool toggle )
660 {
661 wxToolBarTool* tool = static_cast<wxToolBarTool*>(toolBase);
662
663 if (tool->m_item)
664 {
665 g_signal_handlers_block_by_func(tool->m_item, (void*)item_toggled, tool);
666
667 gtk_toggle_tool_button_set_active(
668 GTK_TOGGLE_TOOL_BUTTON(tool->m_item), toggle);
669
670 g_signal_handlers_unblock_by_func(tool->m_item, (void*)item_toggled, tool);
671 }
672 }
673
674 void wxToolBar::DoSetToggle(wxToolBarToolBase * WXUNUSED(tool),
675 bool WXUNUSED(toggle))
676 {
677 // VZ: absolutely no idea about how to do it
678 wxFAIL_MSG( wxT("not implemented") );
679 }
680
681 // ----------------------------------------------------------------------------
682 // wxToolBar geometry
683 // ----------------------------------------------------------------------------
684
685 wxSize wxToolBar::DoGetBestSize() const
686 {
687 // Unfortunately, if overflow arrow is enabled GtkToolbar only reports size
688 // of arrow. To get the real size, the arrow is temporarily disabled here.
689 // This is gross, since it will cause a queue_resize, and could potentially
690 // lead to an infinite loop. But there seems to be no alternative, short of
691 // disabling the arrow entirely.
692 gtk_toolbar_set_show_arrow(m_toolbar, false);
693 const wxSize size = wxToolBarBase::DoGetBestSize();
694 gtk_toolbar_set_show_arrow(m_toolbar, true);
695 return size;
696 }
697
698 wxToolBarToolBase *wxToolBar::FindToolForPosition(wxCoord WXUNUSED(x),
699 wxCoord WXUNUSED(y)) const
700 {
701 // VZ: GTK+ doesn't seem to have such thing
702 wxFAIL_MSG( wxT("wxToolBar::FindToolForPosition() not implemented") );
703
704 return NULL;
705 }
706
707 void wxToolBar::SetToolShortHelp( int id, const wxString& helpString )
708 {
709 wxToolBarTool* tool = static_cast<wxToolBarTool*>(FindById(id));
710
711 if ( tool )
712 {
713 (void)tool->SetShortHelp(helpString);
714 if (tool->m_item)
715 {
716 #if GTK_CHECK_VERSION(2, 12, 0)
717 if (GTK_CHECK_VERSION(3,0,0) || gtk_check_version(2,12,0) == NULL)
718 {
719 gtk_tool_item_set_tooltip_text(tool->m_item,
720 wxGTK_CONV(helpString));
721 }
722 else
723 #endif
724 {
725 #ifndef __WXGTK3__
726 gtk_tool_item_set_tooltip(tool->m_item,
727 m_tooltips, wxGTK_CONV(helpString), "");
728 #endif
729 }
730 }
731 }
732 }
733
734 void wxToolBar::SetToolNormalBitmap( int id, const wxBitmap& bitmap )
735 {
736 wxToolBarTool* tool = static_cast<wxToolBarTool*>(FindById(id));
737 if ( tool )
738 {
739 wxCHECK_RET( tool->IsButton(), wxT("Can only set bitmap on button tools."));
740
741 tool->SetNormalBitmap(bitmap);
742 tool->SetImage();
743 }
744 }
745
746 void wxToolBar::SetToolDisabledBitmap( int id, const wxBitmap& bitmap )
747 {
748 wxToolBarTool* tool = static_cast<wxToolBarTool*>(FindById(id));
749 if ( tool )
750 {
751 wxCHECK_RET( tool->IsButton(), wxT("Can only set bitmap on button tools."));
752
753 tool->SetDisabledBitmap(bitmap);
754 }
755 }
756
757 // ----------------------------------------------------------------------------
758
759 // static
760 wxVisualAttributes
761 wxToolBar::GetClassDefaultAttributes(wxWindowVariant WXUNUSED(variant))
762 {
763 return GetDefaultAttributesFromGTKWidget(gtk_toolbar_new());
764 }
765
766 #endif // wxUSE_TOOLBAR_NATIVE