]> git.saurik.com Git - wxWidgets.git/blame - src/gtk/toolbar.cpp
missing commit
[wxWidgets.git] / src / gtk / toolbar.cpp
CommitLineData
c801d85f 1/////////////////////////////////////////////////////////////////////////////
0b83552a 2// Name: src/gtk/toolbar.cpp
c801d85f
KB
3// Purpose: GTK toolbar
4// Author: Robert Roebling
8a0681f9 5// Modified: 13.12.99 by VZ to derive from wxToolBarBase
32e9da8b 6// RCS-ID: $Id$
c801d85f 7// Copyright: (c) Robert Roebling
65571936 8// Licence: wxWindows licence
c801d85f
KB
9/////////////////////////////////////////////////////////////////////////////
10
14f355c2
VS
11// For compilers that support precompilation, includes "wx.h".
12#include "wx/wxprec.h"
13
8a0681f9 14#if wxUSE_TOOLBAR_NATIVE
dcf924a3 15
4e3e485b
WS
16#include "wx/toolbar.h"
17
9dc44eff 18#include <gtk/gtk.h>
9e691f46 19#include "wx/gtk/private.h"
9dc44eff 20#include "wx/gtk/private/gtk2-compat.h"
fc6557a6 21
8a0681f9
VZ
22// ----------------------------------------------------------------------------
23// globals
24// ----------------------------------------------------------------------------
acfd422a 25
314055fa 26// data
9b7e522a
RR
27extern bool g_blockEventsOnDrag;
28extern wxCursor g_globalCursor;
314055fa 29
8a0681f9
VZ
30// ----------------------------------------------------------------------------
31// wxToolBarTool
32// ----------------------------------------------------------------------------
33
34class wxToolBarTool : public wxToolBarToolBase
35{
36public:
37 wxToolBarTool(wxToolBar *tbar,
38 int id,
e76c0b5f 39 const wxString& label,
8a0681f9
VZ
40 const wxBitmap& bitmap1,
41 const wxBitmap& bitmap2,
e76c0b5f 42 wxItemKind kind,
8a0681f9
VZ
43 wxObject *clientData,
44 const wxString& shortHelpString,
45 const wxString& longHelpString)
e76c0b5f 46 : wxToolBarToolBase(tbar, id, label, bitmap1, bitmap2, kind,
8a0681f9
VZ
47 clientData, shortHelpString, longHelpString)
48 {
a1cb0b11 49 m_item = NULL;
8a0681f9
VZ
50 }
51
07d02e9e
VZ
52 wxToolBarTool(wxToolBar *tbar, wxControl *control, const wxString& label)
53 : wxToolBarToolBase(tbar, control, label)
8a0681f9 54 {
a1cb0b11 55 m_item = NULL;
1be45608
VZ
56 }
57
a1cb0b11
PC
58 void SetImage();
59 void CreateDropDown();
60 void ShowDropdown(GtkToggleButton* button);
8a0681f9 61
a1cb0b11 62 GtkToolItem* m_item;
8a0681f9
VZ
63};
64
65// ----------------------------------------------------------------------------
66// wxWin macros
67// ----------------------------------------------------------------------------
68
2eb10e2a 69IMPLEMENT_DYNAMIC_CLASS(wxToolBar, wxControl)
8a0681f9
VZ
70
71// ============================================================================
72// implementation
73// ============================================================================
74
c801d85f 75//-----------------------------------------------------------------------------
a1cb0b11 76// "clicked" from m_item
c801d85f
KB
77//-----------------------------------------------------------------------------
78
865bb325 79extern "C" {
a1cb0b11 80static void item_clicked(GtkToolButton*, wxToolBarTool* tool)
c801d85f 81{
1144d24d 82 if (g_blockEventsOnDrag) return;
a3622daa 83
a1cb0b11
PC
84 tool->GetToolBar()->OnLeftClick(tool->GetId(), false);
85}
86}
7062497f 87
a1cb0b11
PC
88//-----------------------------------------------------------------------------
89// "toggled" from m_item
90//-----------------------------------------------------------------------------
8a0681f9 91
a1cb0b11
PC
92extern "C" {
93static void item_toggled(GtkToggleToolButton* button, wxToolBarTool* tool)
94{
95 if (g_blockEventsOnDrag) return;
38762f09 96
a1cb0b11
PC
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;
a3622daa 101
a1cb0b11 102 if (!tool->GetToolBar()->OnLeftClick(tool->GetId(), active))
6bb7cee4
VZ
103 {
104 // revert back
105 tool->Toggle();
6bb7cee4 106 }
fc008f25 107}
865bb325 108}
c801d85f 109
729b4756 110//-----------------------------------------------------------------------------
a1cb0b11 111// "button_press_event" from m_item child
729b4756 112//-----------------------------------------------------------------------------
a1cb0b11 113
729b4756 114extern "C" {
a1cb0b11
PC
115static gboolean
116button_press_event(GtkWidget*, GdkEventButton* event, wxToolBarTool* tool)
729b4756
RR
117{
118 if (event->button != 3)
119 return FALSE;
120
729b4756 121 if (g_blockEventsOnDrag) return TRUE;
729b4756 122
a1cb0b11
PC
123 tool->GetToolBar()->OnRightClick(
124 tool->GetId(), int(event->x), int(event->y));
729b4756
RR
125
126 return TRUE;
127}
128}
129
fc6557a6 130//-----------------------------------------------------------------------------
a1cb0b11 131// "child_detached" from m_widget
fc6557a6
RR
132//-----------------------------------------------------------------------------
133
134extern "C" {
a1cb0b11 135static void child_detached(GtkWidget*, GtkToolbar* toolbar, void*)
fc6557a6 136{
a1cb0b11
PC
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);
fc6557a6
RR
140}
141}
142
143//-----------------------------------------------------------------------------
a1cb0b11 144// "child_attached" from m_widget
fc6557a6
RR
145//-----------------------------------------------------------------------------
146
a1cb0b11
PC
147extern "C" {
148static void child_attached(GtkWidget*, GtkToolbar* toolbar, void*)
fc6557a6 149{
a1cb0b11 150 gtk_toolbar_set_show_arrow(toolbar, true);
fc6557a6
RR
151}
152}
153
2f2aa628 154//-----------------------------------------------------------------------------
a1cb0b11 155// "enter_notify_event" / "leave_notify_event" from m_item
2f2aa628
RR
156//-----------------------------------------------------------------------------
157
865bb325 158extern "C" {
a1cb0b11
PC
159static gboolean
160enter_notify_event(GtkWidget*, GdkEventCrossing* event, wxToolBarTool* tool)
314055fa 161{
1144d24d 162 if (g_blockEventsOnDrag) return TRUE;
248bcf0a 163
a1cb0b11
PC
164 int id = -1;
165 if (event->type == GDK_ENTER_NOTIFY)
166 id = tool->GetId();
167 tool->GetToolBar()->OnMouseEnter(id);
248bcf0a 168
1144d24d 169 return FALSE;
314055fa 170}
865bb325 171}
314055fa 172
a1cb0b11
PC
173//-----------------------------------------------------------------------------
174// "expose_event" from GtkImage inside m_item
175//-----------------------------------------------------------------------------
176
177extern "C" {
178static gboolean
9dc44eff
PC
179#ifdef __WXGTK3__
180image_draw(GtkWidget* widget, cairo_t* cr, wxToolBarTool* tool)
181#else
a1cb0b11 182image_expose_event(GtkWidget* widget, GdkEventExpose*, wxToolBarTool* tool)
9dc44eff 183#endif
a1cb0b11
PC
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
385e8575
PC
190 GtkAllocation alloc;
191 gtk_widget_get_allocation(widget, &alloc);
192 GtkRequisition req;
193 gtk_widget_get_requisition(widget, &req);
9dc44eff
PC
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
a1cb0b11 199 gdk_draw_pixbuf(
385e8575 200 gtk_widget_get_window(widget), gtk_widget_get_style(widget)->black_gc, bitmap.GetPixbuf(),
9dc44eff 201 0, 0, x, y,
a1cb0b11 202 -1, -1, GDK_RGB_DITHER_NORMAL, 0, 0);
9dc44eff 203#endif
a1cb0b11
PC
204 return true;
205}
206}
207
208//-----------------------------------------------------------------------------
209// "toggled" from dropdown menu button
210//-----------------------------------------------------------------------------
211
212extern "C" {
213static 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
227extern "C" {
228static gboolean
229arrow_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
48200154 244void wxToolBar::AddChildGTK(wxWindowGTK* child)
bf9e3e73 245{
205177b0
PC
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);
205177b0 251 // position will be corrected in DoInsertTool if necessary
385e8575 252 gtk_toolbar_insert(GTK_TOOLBAR(gtk_bin_get_child(GTK_BIN(m_widget))), item, -1);
bf9e3e73
RR
253}
254
8a0681f9
VZ
255// ----------------------------------------------------------------------------
256// wxToolBarTool
257// ----------------------------------------------------------------------------
c801d85f 258
a1cb0b11 259void wxToolBarTool::SetImage()
8a0681f9 260{
a1cb0b11
PC
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
271void wxToolBarTool::CreateDropDown()
272{
273 gtk_tool_item_set_homogeneous(m_item, false);
1897abe1
PC
274 GtkOrientation orient = GTK_ORIENTATION_HORIZONTAL;
275 GtkArrowType arrowType = GTK_ARROW_DOWN;
a1cb0b11
PC
276 if (GetToolBar()->HasFlag(wxTB_LEFT | wxTB_RIGHT))
277 {
1897abe1
PC
278 orient = GTK_ORIENTATION_VERTICAL;
279 arrowType = GTK_ARROW_RIGHT;
a1cb0b11 280 }
1897abe1
PC
281 GtkWidget* box = gtk_box_new(orient, 0);
282 GtkWidget* arrow = gtk_arrow_new(arrowType, GTK_SHADOW_NONE);
385e8575 283 GtkWidget* tool_button = gtk_bin_get_child(GTK_BIN(m_item));
a1cb0b11
PC
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
298void wxToolBarTool::ShowDropdown(GtkToggleButton* button)
299{
300 wxToolBarBase* toolbar = GetToolBar();
ce7fe42e 301 wxCommandEvent event(wxEVT_TOOL_DROPDOWN, GetId());
a1cb0b11
PC
302 if (!toolbar->HandleWindowEvent(event))
303 {
304 wxMenu* menu = GetDropdownMenu();
305 if (menu)
306 {
385e8575 307 GtkAllocation alloc;
628e8d44 308 gtk_widget_get_allocation(GTK_WIDGET(button), &alloc);
a1cb0b11
PC
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 }
8a0681f9 318}
c801d85f 319
8a0681f9 320wxToolBarToolBase *wxToolBar::CreateTool(int id,
e76c0b5f 321 const wxString& text,
8a0681f9
VZ
322 const wxBitmap& bitmap1,
323 const wxBitmap& bitmap2,
e76c0b5f 324 wxItemKind kind,
8a0681f9
VZ
325 wxObject *clientData,
326 const wxString& shortHelpString,
327 const wxString& longHelpString)
328{
e76c0b5f 329 return new wxToolBarTool(this, id, text, bitmap1, bitmap2, kind,
8a0681f9
VZ
330 clientData, shortHelpString, longHelpString);
331}
b1da76e1 332
07d02e9e
VZ
333wxToolBarToolBase *
334wxToolBar::CreateTool(wxControl *control, const wxString& label)
c801d85f 335{
07d02e9e 336 return new wxToolBarTool(this, control, label);
fc008f25 337}
c801d85f 338
8a0681f9
VZ
339//-----------------------------------------------------------------------------
340// wxToolBar construction
341//-----------------------------------------------------------------------------
342
343void wxToolBar::Init()
c801d85f 344{
d3b9f782 345 m_toolbar = NULL;
a1cb0b11 346 m_tooltips = NULL;
fc008f25 347}
c801d85f 348
a3622daa 349wxToolBar::~wxToolBar()
c801d85f 350{
9dc44eff 351#ifndef __WXGTK3__
85314957 352 if (m_tooltips) // always NULL if GTK >= 2.12
a1cb0b11
PC
353 {
354 gtk_object_destroy(GTK_OBJECT(m_tooltips));
355 g_object_unref(m_tooltips);
356 }
9dc44eff 357#endif
fc008f25 358}
c801d85f 359
8a0681f9
VZ
360bool wxToolBar::Create( wxWindow *parent,
361 wxWindowID id,
362 const wxPoint& pos,
363 const wxSize& size,
364 long style,
365 const wxString& name )
c801d85f 366{
8a0681f9
VZ
367 if ( !PreCreation( parent, pos, size ) ||
368 !CreateBase( parent, id, pos, size, style, wxDefaultValidator, name ))
4dcaf11a 369 {
223d09f6 370 wxFAIL_MSG( wxT("wxToolBar creation failed") );
c801d85f 371
91af0895 372 return false;
8a0681f9 373 }
a3622daa 374
d408730c
VZ
375 FixupStyle();
376
9e691f46 377 m_toolbar = GTK_TOOLBAR( gtk_toolbar_new() );
9dc44eff 378#ifndef __WXGTK3__
85314957
VZ
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 }
385e8575 385#endif
e76c0b5f 386 GtkSetStyle();
99e8cb50 387
3502e687
RR
388 if (style & wxTB_DOCKABLE)
389 {
390 m_widget = gtk_handle_box_new();
a1cb0b11
PC
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);
8a0681f9 396
f03fc89f 397 if (style & wxTB_FLAT)
858b5bdd 398 gtk_handle_box_set_shadow_type( GTK_HANDLE_BOX(m_widget), GTK_SHADOW_NONE );
3502e687
RR
399 }
400 else
248bcf0a
RD
401 {
402 m_widget = gtk_event_box_new();
248bcf0a 403 ConnectWidget( m_widget );
3502e687 404 }
9ff9d30c 405 g_object_ref(m_widget);
a1cb0b11
PC
406 gtk_container_add(GTK_CONTAINER(m_widget), GTK_WIDGET(m_toolbar));
407 gtk_widget_show(GTK_WIDGET(m_toolbar));
be25e480 408
f03fc89f 409 m_parent->DoAddChild( this );
8a0681f9 410
abdeb9e7 411 PostCreation(size);
a3622daa 412
91af0895 413 return true;
fc008f25 414}
c801d85f 415
e4161a2a 416GdkWindow *wxToolBar::GTKGetWindow(wxArrayGdkWindows& WXUNUSED(windows)) const
48468900 417{
385e8575 418 return gtk_widget_get_window(GTK_WIDGET(m_toolbar));
48468900
RR
419}
420
e76c0b5f
VZ
421void wxToolBar::GtkSetStyle()
422{
a1cb0b11
PC
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 }
e76c0b5f 436
9dc44eff 437#ifdef __WXGTK3__
385e8575
PC
438 gtk_orientable_set_orientation(GTK_ORIENTABLE(m_toolbar), orient);
439#else
e76c0b5f 440 gtk_toolbar_set_orientation(m_toolbar, orient);
385e8575 441#endif
e76c0b5f
VZ
442 gtk_toolbar_set_style(m_toolbar, style);
443}
444
445void wxToolBar::SetWindowStyleFlag( long style )
446{
447 wxToolBarBase::SetWindowStyleFlag(style);
8ad31f9d 448
e76c0b5f
VZ
449 if ( m_toolbar )
450 GtkSetStyle();
451}
452
9067c6c5
VZ
453bool 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
8a0681f9 479bool wxToolBar::DoInsertTool(size_t pos, wxToolBarToolBase *toolBase)
c801d85f 480{
5c33522f 481 wxToolBarTool* tool = static_cast<wxToolBarTool*>(toolBase);
248bcf0a 482
a1cb0b11 483 GSList* radioGroup;
fbf49ef2 484 GtkWidget* bin_child;
8a0681f9
VZ
485 switch ( tool->GetStyle() )
486 {
487 case wxTOOL_STYLE_BUTTON:
a1cb0b11 488 switch (tool->GetKind())
8a0681f9 489 {
a1cb0b11
PC
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);
d4a762e3 497 if (!radioGroup)
38762f09
VZ
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
91af0895 502 tool->Toggle(true);
38762f09 503 }
a1cb0b11
PC
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);
9dc44eff
PC
525#ifdef __WXGTK3__
526 g_signal_connect(image, "draw",
527 G_CALLBACK(image_draw), tool);
528#else
a1cb0b11
PC
529 g_signal_connect(image, "expose_event",
530 G_CALLBACK(image_expose_event), tool);
9dc44eff 531#endif
8a0681f9 532 }
a1cb0b11
PC
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 {
85314957 542#if GTK_CHECK_VERSION(2, 12, 0)
385e8575 543 if (GTK_CHECK_VERSION(3,0,0) || gtk_check_version(2,12,0) == NULL)
85314957
VZ
544 {
545 gtk_tool_item_set_tooltip_text(tool->m_item,
546 wxGTK_CONV(tool->GetShortHelp()));
547 }
548 else
549#endif
550 {
9dc44eff 551#ifndef __WXGTK3__
85314957
VZ
552 gtk_tool_item_set_tooltip(tool->m_item,
553 m_tooltips, wxGTK_CONV(tool->GetShortHelp()), "");
385e8575 554#endif
85314957 555 }
a1cb0b11 556 }
fbf49ef2
PC
557 bin_child = gtk_bin_get_child(GTK_BIN(tool->m_item));
558 g_signal_connect(bin_child, "button_press_event",
a1cb0b11 559 G_CALLBACK(button_press_event), tool);
fbf49ef2 560 g_signal_connect(bin_child, "enter_notify_event",
a1cb0b11 561 G_CALLBACK(enter_notify_event), tool);
fbf49ef2 562 g_signal_connect(bin_child, "leave_notify_event",
a1cb0b11
PC
563 G_CALLBACK(enter_notify_event), tool);
564
565 if (tool->GetKind() == wxITEM_DROPDOWN)
566 tool->CreateDropDown();
205177b0 567 gtk_toolbar_insert(m_toolbar, tool->m_item, int(pos));
8a0681f9
VZ
568 break;
569
570 case wxTOOL_STYLE_SEPARATOR:
a1cb0b11 571 tool->m_item = gtk_separator_tool_item_new();
cc260109
VZ
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 }
205177b0 581 gtk_toolbar_insert(m_toolbar, tool->m_item, int(pos));
1be45608 582 break;
bf9e3e73 583
8a0681f9 584 case wxTOOL_STYLE_CONTROL:
a1cb0b11 585 wxWindow* control = tool->GetControl();
385e8575 586 if (gtk_widget_get_parent(control->m_widget) == NULL)
48200154 587 AddChildGTK(control);
385e8575 588 tool->m_item = GTK_TOOL_ITEM(gtk_widget_get_parent(gtk_widget_get_parent(control->m_widget)));
205177b0
PC
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 }
8a0681f9
VZ
597 break;
598 }
a1cb0b11 599 gtk_widget_show(GTK_WIDGET(tool->m_item));
bf9e3e73 600
9f884528 601 InvalidateBestSize();
bf9e3e73 602
91af0895 603 return true;
bf9e3e73
RR
604}
605
a1cb0b11 606bool wxToolBar::DoDeleteTool(size_t /* pos */, wxToolBarToolBase* toolBase)
c801d85f 607{
5c33522f 608 wxToolBarTool* tool = static_cast<wxToolBarTool*>(toolBase);
c801d85f 609
a1cb0b11 610 if (tool->GetStyle() == wxTOOL_STYLE_CONTROL)
97d7bfb8 611 {
a1cb0b11
PC
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;
385e8575 617 gtk_container_remove(GTK_CONTAINER(gtk_widget_get_parent(widget)), widget);
8a0681f9 618 }
9dc44eff 619 gtk_widget_destroy(GTK_WIDGET(tool->m_item));
a1cb0b11 620 tool->m_item = NULL;
c801d85f 621
9f884528 622 InvalidateBestSize();
91af0895 623 return true;
fc008f25 624}
46dc76ba 625
a1cb0b11
PC
626GSList* 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
8a0681f9
VZ
647// ----------------------------------------------------------------------------
648// wxToolBar tools state
649// ----------------------------------------------------------------------------
650
651void wxToolBar::DoEnableTool(wxToolBarToolBase *toolBase, bool enable)
c801d85f 652{
5c33522f 653 wxToolBarTool* tool = static_cast<wxToolBarTool*>(toolBase);
8a0681f9 654
8a0681f9 655 if (tool->m_item)
a1cb0b11 656 gtk_widget_set_sensitive(GTK_WIDGET(tool->m_item), enable);
fc008f25 657}
c801d85f 658
248bcf0a 659void wxToolBar::DoToggleTool( wxToolBarToolBase *toolBase, bool toggle )
c801d85f 660{
5c33522f 661 wxToolBarTool* tool = static_cast<wxToolBarTool*>(toolBase);
8a0681f9 662
a1cb0b11 663 if (tool->m_item)
1144d24d 664 {
a1cb0b11 665 g_signal_handlers_block_by_func(tool->m_item, (void*)item_toggled, tool);
8a0681f9 666
a1cb0b11
PC
667 gtk_toggle_tool_button_set_active(
668 GTK_TOGGLE_TOOL_BUTTON(tool->m_item), toggle);
248bcf0a 669
a1cb0b11 670 g_signal_handlers_unblock_by_func(tool->m_item, (void*)item_toggled, tool);
1144d24d 671 }
fc008f25 672}
c801d85f 673
8a0681f9
VZ
674void wxToolBar::DoSetToggle(wxToolBarToolBase * WXUNUSED(tool),
675 bool WXUNUSED(toggle))
c801d85f 676{
8a0681f9 677 // VZ: absolutely no idea about how to do it
9a83f860 678 wxFAIL_MSG( wxT("not implemented") );
fc008f25 679}
c801d85f 680
8a0681f9
VZ
681// ----------------------------------------------------------------------------
682// wxToolBar geometry
683// ----------------------------------------------------------------------------
684
a1cb0b11
PC
685wxSize 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
8a0681f9
VZ
698wxToolBarToolBase *wxToolBar::FindToolForPosition(wxCoord WXUNUSED(x),
699 wxCoord WXUNUSED(y)) const
c801d85f 700{
8a0681f9 701 // VZ: GTK+ doesn't seem to have such thing
9a83f860 702 wxFAIL_MSG( wxT("wxToolBar::FindToolForPosition() not implemented") );
8a0681f9 703
d3b9f782 704 return NULL;
fc008f25 705}
c801d85f 706
a1f79c1e
VZ
707void wxToolBar::SetToolShortHelp( int id, const wxString& helpString )
708{
5c33522f 709 wxToolBarTool* tool = static_cast<wxToolBarTool*>(FindById(id));
a1f79c1e
VZ
710
711 if ( tool )
712 {
713 (void)tool->SetShortHelp(helpString);
a1cb0b11
PC
714 if (tool->m_item)
715 {
85314957 716#if GTK_CHECK_VERSION(2, 12, 0)
385e8575 717 if (GTK_CHECK_VERSION(3,0,0) || gtk_check_version(2,12,0) == NULL)
85314957
VZ
718 {
719 gtk_tool_item_set_tooltip_text(tool->m_item,
720 wxGTK_CONV(helpString));
721 }
722 else
723#endif
724 {
9dc44eff 725#ifndef __WXGTK3__
85314957
VZ
726 gtk_tool_item_set_tooltip(tool->m_item,
727 m_tooltips, wxGTK_CONV(helpString), "");
385e8575 728#endif
85314957 729 }
a1cb0b11 730 }
a1f79c1e
VZ
731 }
732}
733
bbd321ff
RD
734void wxToolBar::SetToolNormalBitmap( int id, const wxBitmap& bitmap )
735{
5c33522f 736 wxToolBarTool* tool = static_cast<wxToolBarTool*>(FindById(id));
bbd321ff
RD
737 if ( tool )
738 {
739 wxCHECK_RET( tool->IsButton(), wxT("Can only set bitmap on button tools."));
740
741 tool->SetNormalBitmap(bitmap);
a1cb0b11 742 tool->SetImage();
f4322df6 743 }
bbd321ff
RD
744}
745
746void wxToolBar::SetToolDisabledBitmap( int id, const wxBitmap& bitmap )
747{
5c33522f 748 wxToolBarTool* tool = static_cast<wxToolBarTool*>(FindById(id));
bbd321ff
RD
749 if ( tool )
750 {
751 wxCHECK_RET( tool->IsButton(), wxT("Can only set bitmap on button tools."));
752
753 tool->SetDisabledBitmap(bitmap);
f4322df6 754 }
bbd321ff
RD
755}
756
9d522606
RD
757// ----------------------------------------------------------------------------
758
759// static
760wxVisualAttributes
761wxToolBar::GetClassDefaultAttributes(wxWindowVariant WXUNUSED(variant))
762{
7fff16b8 763 return GetDefaultAttributesFromGTKWidget(gtk_toolbar_new());
9d522606
RD
764}
765
a1f79c1e 766#endif // wxUSE_TOOLBAR_NATIVE