]> git.saurik.com Git - wxWidgets.git/blame - src/gtk/tbargtk.cpp
derive wxSTC from wxTextEntryBase to provide even more wxTextCtrl-like methods (see...
[wxWidgets.git] / src / gtk / tbargtk.cpp
CommitLineData
c801d85f 1/////////////////////////////////////////////////////////////////////////////
76b49cf4 2// Name: src/gtk/tbargtk.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
76b49cf4 18#ifndef WX_PRECOMP
abdf096a 19 #include "wx/menu.h"
76b49cf4 20#endif
c801d85f 21
1efb5db8
MR
22// FIXME: Use GtkImage instead of GtkPixmap. Use the new toolbar API for when gtk runtime is new enough?
23// Beware that the new and old toolbar API may not be mixed in usage.
1efb5db8 24#undef GTK_DISABLE_DEPRECATED
1efb5db8 25
9e691f46 26#include "wx/gtk/private.h"
fc6557a6
RR
27
28/* XPM */
29static const char *arrow_down_xpm[] = {
30/* columns rows colors chars-per-pixel */
31"7 7 2 1",
32" c None",
33". c Black",
34/* pixels */
35" ",
36" ",
37" ",
38".......",
39" ..... ",
40" ... ",
41" . "
42};
43
83624f79 44
8a0681f9
VZ
45// ----------------------------------------------------------------------------
46// globals
47// ----------------------------------------------------------------------------
acfd422a 48
314055fa 49// data
9b7e522a
RR
50extern bool g_blockEventsOnDrag;
51extern wxCursor g_globalCursor;
314055fa 52
e76c0b5f
VZ
53// ----------------------------------------------------------------------------
54// private functions
55// ----------------------------------------------------------------------------
56
77ffb593 57// translate wxWidgets toolbar style flags to GTK orientation and style
e76c0b5f
VZ
58static void GetGtkStyle(long style,
59 GtkOrientation *orient, GtkToolbarStyle *gtkStyle)
60{
7a976304 61 *orient = ( style & wxTB_LEFT || style & wxTB_RIGHT ) ? GTK_ORIENTATION_VERTICAL : GTK_ORIENTATION_HORIZONTAL;
e76c0b5f
VZ
62
63
64 if ( style & wxTB_TEXT )
65 {
99e8cb50
VZ
66 *gtkStyle = style & wxTB_NOICONS
67 ? GTK_TOOLBAR_TEXT
68 : (
99e8cb50 69 style & wxTB_HORZ_LAYOUT ? GTK_TOOLBAR_BOTH_HORIZ :
99e8cb50 70 GTK_TOOLBAR_BOTH);
e76c0b5f
VZ
71 }
72 else // no text, hence we must have the icons or what would we show?
73 {
74 *gtkStyle = GTK_TOOLBAR_ICONS;
75 }
76}
77
8a0681f9
VZ
78// ----------------------------------------------------------------------------
79// wxToolBarTool
80// ----------------------------------------------------------------------------
81
82class wxToolBarTool : public wxToolBarToolBase
83{
84public:
85 wxToolBarTool(wxToolBar *tbar,
86 int id,
e76c0b5f 87 const wxString& label,
8a0681f9
VZ
88 const wxBitmap& bitmap1,
89 const wxBitmap& bitmap2,
e76c0b5f 90 wxItemKind kind,
8a0681f9
VZ
91 wxObject *clientData,
92 const wxString& shortHelpString,
93 const wxString& longHelpString)
e76c0b5f 94 : wxToolBarToolBase(tbar, id, label, bitmap1, bitmap2, kind,
8a0681f9
VZ
95 clientData, shortHelpString, longHelpString)
96 {
97 Init();
98 }
99
07d02e9e
VZ
100 wxToolBarTool(wxToolBar *tbar, wxControl *control, const wxString& label)
101 : wxToolBarToolBase(tbar, control, label)
8a0681f9
VZ
102 {
103 Init();
ddb57e45
PC
104 // Hold a reference to keep control alive until DoInsertTool() is
105 // called, or if RemoveTool() is called (see DoDeleteTool)
106 g_object_ref(control->m_widget);
107 // release reference when gtk_widget_destroy() is called on control
108 g_signal_connect(
109 control->m_widget, "destroy", G_CALLBACK(g_object_unref), NULL);
1be45608
VZ
110 }
111
38762f09
VZ
112 // is this a radio button?
113 //
114 // unlike GetKind(), can be called for any kind of tools, not just buttons
115 bool IsRadio() const { return IsButton() && GetKind() == wxITEM_RADIO; }
116
e76c0b5f
VZ
117 // this is only called for the normal buttons, i.e. not separators nor
118 // controls
119 GtkToolbarChildType GetGtkChildType() const
120 {
121 switch ( GetKind() )
122 {
123 case wxITEM_CHECK:
124 return GTK_TOOLBAR_CHILD_TOGGLEBUTTON;
125
126 case wxITEM_RADIO:
127 return GTK_TOOLBAR_CHILD_RADIOBUTTON;
128
129 default:
130 wxFAIL_MSG( _T("unknown toolbar child type") );
131 // fall through
132
7062497f 133 case wxITEM_DROPDOWN:
e76c0b5f
VZ
134 case wxITEM_NORMAL:
135 return GTK_TOOLBAR_CHILD_BUTTON;
136 }
137 }
138
eba91e51 139 void SetImage(const wxBitmap& bitmap)
ab86c659
VS
140 {
141 if (bitmap.Ok())
142 {
eba91e51
PC
143 // setting from pixmap doesn't seem to work right, but pixbuf works well
144 gtk_image_set_from_pixbuf((GtkImage*)m_image, bitmap.GetPixbuf());
ab86c659
VS
145 }
146 }
147
1be45608
VZ
148 // the toolbar element for button tools or a GtkAlignment containing the
149 // control for control tools
150 GtkWidget *m_item;
ddb57e45
PC
151 // dropdown element for button tools
152 GtkWidget *m_itemDropdown;
1be45608
VZ
153
154 // a GtkImage containing the image for a button-type tool, may be NULL
155 GtkWidget *m_image;
8a0681f9
VZ
156
157protected:
158 void Init();
159};
160
161// ----------------------------------------------------------------------------
162// wxWin macros
163// ----------------------------------------------------------------------------
164
2eb10e2a 165IMPLEMENT_DYNAMIC_CLASS(wxToolBar, wxControl)
8a0681f9
VZ
166
167// ============================================================================
168// implementation
169// ============================================================================
170
c801d85f 171//-----------------------------------------------------------------------------
2f2aa628 172// "clicked" (internal from gtk_toolbar)
c801d85f
KB
173//-----------------------------------------------------------------------------
174
865bb325 175extern "C" {
91fd8ba7 176static void gtk_toolbar_callback( GtkWidget *widget,
8a0681f9 177 wxToolBarTool *tool )
c801d85f 178{
8a0681f9 179 wxToolBar *tbar = (wxToolBar *)tool->GetToolBar();
248bcf0a 180
9864c56d 181 if (tbar->m_blockEvent) return;
acfd422a 182
1144d24d 183 if (g_blockEventsOnDrag) return;
8a0681f9 184 if (!tool->IsEnabled()) return;
a3622daa 185
8a0681f9 186 if (tool->CanBeToggled())
248bcf0a 187 {
4b57db79
RR
188 if (tool->IsRadio() &&
189 gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(widget)) &&
190 tool->IsToggled())
191 {
192 // pressed an already pressed radio button
193 return;
194 }
7062497f 195
8a0681f9
VZ
196 tool->Toggle();
197
eba91e51 198 tool->SetImage(tool->GetBitmap());
38762f09
VZ
199
200 if ( tool->IsRadio() && !tool->IsToggled() )
201 {
202 // radio button went up, don't report this as a wxWin event
203 return;
204 }
85eb36c2 205 }
a3622daa 206
6bb7cee4
VZ
207 if( !tbar->OnLeftClick( tool->GetId(), tool->IsToggled() ) && tool->CanBeToggled() )
208 {
209 // revert back
210 tool->Toggle();
211
eba91e51 212 tool->SetImage(tool->GetBitmap());
6bb7cee4 213 }
fc008f25 214}
865bb325 215}
c801d85f 216
729b4756
RR
217//-----------------------------------------------------------------------------
218// "right-click"
219//-----------------------------------------------------------------------------
220extern "C" {
221static gboolean gtk_toolbar_tool_rclick_callback(GtkWidget *WXUNUSED(widget),
222 GdkEventButton *event,
223 wxToolBarToolBase *tool)
224{
225 if (event->button != 3)
226 return FALSE;
227
228 wxToolBar *tbar = (wxToolBar *)tool->GetToolBar();
229
230 if (tbar->m_blockEvent) return TRUE;
231
232 if (g_blockEventsOnDrag) return TRUE;
233 if (!tool->IsEnabled()) return TRUE;
234
235 tbar->OnRightClick( tool->GetId(), (int)event->x, (int)event->y );
236
237 return TRUE;
238}
239}
240
fc6557a6
RR
241//-----------------------------------------------------------------------------
242// "enter_notify_event" / "leave_notify_event" from dropdown
243//-----------------------------------------------------------------------------
244
245extern "C" {
246static gint gtk_toolbar_buddy_enter_callback( GtkWidget *WXUNUSED(widget),
247 GdkEventCrossing *WXUNUSED(gdk_event),
248 GtkWidget *tool )
249{
250 guint8 state = GTK_WIDGET_STATE( tool );
251 state |= GTK_STATE_PRELIGHT;
252 gtk_widget_set_state( tool, (GtkStateType) state );
253 return FALSE;
254}
255
256static gint gtk_toolbar_buddy_leave_callback( GtkWidget *WXUNUSED(widget),
257 GdkEventCrossing *WXUNUSED(gdk_event),
258 GtkWidget *tool )
259{
260 guint8 state = GTK_WIDGET_STATE( tool );
261 state &= ~GTK_STATE_PRELIGHT;
262 gtk_widget_set_state( tool, (GtkStateType) state );
263 return FALSE;
264}
265}
266
267//-----------------------------------------------------------------------------
7062497f 268// "left-click" on dropdown
fc6557a6
RR
269//-----------------------------------------------------------------------------
270
271extern "C"
272{
273static void gtk_pop_tb_hide_callback( GtkWidget *WXUNUSED(menu), GtkToggleButton *button )
274{
275 gtk_toggle_button_set_active( button, FALSE );
276}
277
278static gboolean gtk_toolbar_dropdown_lclick_callback(GtkWidget *widget,
279 GdkEventButton *event,
280 wxToolBarToolBase *tool)
281{
282 if (event->button != 1)
283 return FALSE;
284
285 wxToolBar *tbar = (wxToolBar *)tool->GetToolBar();
286
287 if (tbar->m_blockEvent) return FALSE;
288
289 if (g_blockEventsOnDrag) return FALSE;
290 if (!tool->IsEnabled()) return FALSE;
291
292 wxCommandEvent evt(wxEVT_COMMAND_TOOL_DROPDOWN_CLICKED, tool->GetId() );
937013e0 293 if ( tbar->HandleWindowEvent(evt) )
fc6557a6
RR
294 {
295 return TRUE;
296 }
7062497f 297
fc6557a6
RR
298 wxMenu * const menu = tool->GetDropdownMenu();
299 if (!menu)
300 return TRUE;
301
302 // simulate press
303 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(widget), TRUE );
7062497f 304
fc6557a6
RR
305 g_signal_connect (menu->m_menu, "hide",
306 G_CALLBACK (gtk_pop_tb_hide_callback),
307 widget);
7062497f
VZ
308
309 tbar->PopupMenu( menu, widget->allocation.x,
fc6557a6 310 widget->allocation.y + widget->allocation.height );
7062497f
VZ
311
312
fc6557a6
RR
313 return TRUE;
314}
315}
316
2f2aa628 317//-----------------------------------------------------------------------------
a8945eef 318// "enter_notify_event" / "leave_notify_event"
2f2aa628
RR
319//-----------------------------------------------------------------------------
320
865bb325 321extern "C" {
248bcf0a 322static gint gtk_toolbar_tool_callback( GtkWidget *WXUNUSED(widget),
a8945eef
MB
323 GdkEventCrossing *gdk_event,
324 wxToolBarTool *tool )
314055fa 325{
1144d24d 326 if (g_blockEventsOnDrag) return TRUE;
248bcf0a 327
8a0681f9 328 wxToolBar *tb = (wxToolBar *)tool->GetToolBar();
248bcf0a 329
47c93b63 330 // emit the event
a8945eef
MB
331 if( gdk_event->type == GDK_ENTER_NOTIFY )
332 tb->OnMouseEnter( tool->GetId() );
333 else
334 tb->OnMouseEnter( -1 );
248bcf0a 335
1144d24d 336 return FALSE;
314055fa 337}
865bb325 338}
314055fa 339
cca410b3
PC
340//-----------------------------------------------------------------------------
341// "size_request" from m_toolbar
342//-----------------------------------------------------------------------------
343
344extern "C" {
345static void
346size_request(GtkWidget*, GtkRequisition* req, wxToolBar* win)
347{
348 const wxSize margins = win->GetMargins();
349 req->width += margins.x;
350 req->height += 2 * margins.y;
351}
352}
353
bf9e3e73
RR
354//-----------------------------------------------------------------------------
355// InsertChild callback for wxToolBar
356//-----------------------------------------------------------------------------
357
c821db16 358static void wxInsertChildInToolBar( wxWindow* WXUNUSED(parent),
ddb57e45 359 wxWindow* /* child */)
bf9e3e73 360{
ddb57e45 361 // Child widget will be inserted into GtkToolbar by DoInsertTool()
bf9e3e73
RR
362}
363
8a0681f9
VZ
364// ----------------------------------------------------------------------------
365// wxToolBarTool
366// ----------------------------------------------------------------------------
c801d85f 367
8a0681f9
VZ
368void wxToolBarTool::Init()
369{
370 m_item =
ddb57e45 371 m_itemDropdown =
eba91e51 372 m_image = NULL;
8a0681f9 373}
c801d85f 374
8a0681f9 375wxToolBarToolBase *wxToolBar::CreateTool(int id,
e76c0b5f 376 const wxString& text,
8a0681f9
VZ
377 const wxBitmap& bitmap1,
378 const wxBitmap& bitmap2,
e76c0b5f 379 wxItemKind kind,
8a0681f9
VZ
380 wxObject *clientData,
381 const wxString& shortHelpString,
382 const wxString& longHelpString)
383{
e76c0b5f 384 return new wxToolBarTool(this, id, text, bitmap1, bitmap2, kind,
8a0681f9
VZ
385 clientData, shortHelpString, longHelpString);
386}
b1da76e1 387
07d02e9e
VZ
388wxToolBarToolBase *
389wxToolBar::CreateTool(wxControl *control, const wxString& label)
c801d85f 390{
07d02e9e 391 return new wxToolBarTool(this, control, label);
fc008f25 392}
c801d85f 393
8a0681f9
VZ
394//-----------------------------------------------------------------------------
395// wxToolBar construction
396//-----------------------------------------------------------------------------
397
398void wxToolBar::Init()
c801d85f 399{
8a0681f9 400 m_toolbar = (GtkToolbar *)NULL;
91af0895 401 m_blockEvent = false;
d2c0a964
RD
402 m_defaultWidth = 32;
403 m_defaultHeight = 32;
fc008f25 404}
c801d85f 405
a3622daa 406wxToolBar::~wxToolBar()
c801d85f 407{
fc008f25 408}
c801d85f 409
8a0681f9
VZ
410bool wxToolBar::Create( wxWindow *parent,
411 wxWindowID id,
412 const wxPoint& pos,
413 const wxSize& size,
414 long style,
415 const wxString& name )
c801d85f 416{
c821db16 417 m_insertCallback = wxInsertChildInToolBar;
a3622daa 418
8a0681f9
VZ
419 if ( !PreCreation( parent, pos, size ) ||
420 !CreateBase( parent, id, pos, size, style, wxDefaultValidator, name ))
4dcaf11a 421 {
223d09f6 422 wxFAIL_MSG( wxT("wxToolBar creation failed") );
c801d85f 423
91af0895 424 return false;
8a0681f9 425 }
a3622daa 426
d408730c
VZ
427 FixupStyle();
428
9e691f46 429 m_toolbar = GTK_TOOLBAR( gtk_toolbar_new() );
e76c0b5f 430 GtkSetStyle();
99e8cb50 431
2b5f62a0
VZ
432 // Doesn't work this way.
433 // GtkToolbarSpaceStyle space_style = GTK_TOOLBAR_SPACE_EMPTY;
434 // gtk_widget_style_set (GTK_WIDGET (m_toolbar), "space_style", &space_style, NULL);
a3622daa 435
8a0681f9 436 SetToolSeparation(7);
3502e687
RR
437
438 if (style & wxTB_DOCKABLE)
439 {
440 m_widget = gtk_handle_box_new();
f03fc89f
VZ
441 gtk_container_add( GTK_CONTAINER(m_widget), GTK_WIDGET(m_toolbar) );
442 gtk_widget_show( GTK_WIDGET(m_toolbar) );
8a0681f9 443
f03fc89f 444 if (style & wxTB_FLAT)
858b5bdd 445 gtk_handle_box_set_shadow_type( GTK_HANDLE_BOX(m_widget), GTK_SHADOW_NONE );
3502e687
RR
446 }
447 else
248bcf0a
RD
448 {
449 m_widget = gtk_event_box_new();
450 gtk_container_add( GTK_CONTAINER(m_widget), GTK_WIDGET(m_toolbar) );
451 ConnectWidget( m_widget );
452 gtk_widget_show(GTK_WIDGET(m_toolbar));
3502e687 453 }
8a0681f9 454
9e691f46 455 // FIXME: there is no such function for toolbars in 2.0
68567a96 456#if 0
858b5bdd
RR
457 if (style & wxTB_FLAT)
458 gtk_toolbar_set_button_relief( GTK_TOOLBAR(m_toolbar), GTK_RELIEF_NONE );
9e691f46 459#endif
be25e480 460
f03fc89f 461 m_parent->DoAddChild( this );
8a0681f9 462
abdeb9e7 463 PostCreation(size);
a3622daa 464
cca410b3
PC
465 g_signal_connect_after(m_toolbar, "size_request",
466 G_CALLBACK(size_request), this);
467
91af0895 468 return true;
fc008f25 469}
c801d85f 470
e4161a2a 471GdkWindow *wxToolBar::GTKGetWindow(wxArrayGdkWindows& WXUNUSED(windows)) const
48468900
RR
472{
473 return GTK_WIDGET(m_toolbar)->window;
474}
475
e76c0b5f
VZ
476void wxToolBar::GtkSetStyle()
477{
478 GtkOrientation orient;
479 GtkToolbarStyle style;
480 GetGtkStyle(GetWindowStyle(), &orient, &style);
481
482 gtk_toolbar_set_orientation(m_toolbar, orient);
483 gtk_toolbar_set_style(m_toolbar, style);
8c4e2405 484 gtk_toolbar_set_tooltips(m_toolbar, !(style & wxTB_NO_TOOLTIPS));
e76c0b5f
VZ
485}
486
487void wxToolBar::SetWindowStyleFlag( long style )
488{
489 wxToolBarBase::SetWindowStyleFlag(style);
8ad31f9d 490
e76c0b5f
VZ
491 if ( m_toolbar )
492 GtkSetStyle();
493}
494
8a0681f9 495bool wxToolBar::DoInsertTool(size_t pos, wxToolBarToolBase *toolBase)
c801d85f 496{
8c4e2405 497 wxToolBarTool* tool = wx_static_cast(wxToolBarTool*, toolBase);
248bcf0a 498
8a0681f9
VZ
499 if ( tool->IsButton() )
500 {
2b5f62a0
VZ
501 if ( !HasFlag(wxTB_NOICONS) )
502 {
503 wxBitmap bitmap = tool->GetNormalBitmap();
c801d85f 504
91af0895 505 wxCHECK_MSG( bitmap.Ok(), false,
2b5f62a0 506 wxT("invalid bitmap for wxToolBar icon") );
a3622daa 507
eba91e51
PC
508 tool->m_image = gtk_image_new();
509 tool->SetImage(bitmap);
248bcf0a 510
eba91e51 511 gtk_misc_set_alignment((GtkMisc*)tool->m_image, 0.5, 0.5);
2b5f62a0 512 }
8a0681f9 513 }
c801d85f 514
fc6557a6 515 int posGtk = 0;
7062497f
VZ
516 if ( pos > 0 )
517 {
518 for ( size_t i = 0; i < pos; i++ )
fc6557a6
RR
519 {
520 posGtk++;
7062497f
VZ
521
522 // if we have a dropdown menu, we use 2 GTK tools internally
fc6557a6 523 wxToolBarToolsList::compatibility_iterator node = m_tools.Item( i );
74ab5f5b
VZ
524 wxToolBarTool * const tool2 = (wxToolBarTool*) node->GetData();
525 if ( tool2->IsButton() && tool2->GetKind() == wxITEM_DROPDOWN )
fc6557a6
RR
526 posGtk++;
527 }
528 }
7062497f
VZ
529
530
8a0681f9
VZ
531 switch ( tool->GetStyle() )
532 {
533 case wxTOOL_STYLE_BUTTON:
38762f09
VZ
534 // for a radio button we need the widget which starts the radio
535 // group it belongs to, i.e. the first radio button immediately
536 // preceding this one
8a0681f9 537 {
38762f09
VZ
538 GtkWidget *widget = NULL;
539
540 if ( tool->IsRadio() )
541 {
98fc1d65
MB
542 wxToolBarToolsList::compatibility_iterator node
543 = wxToolBarToolsList::compatibility_iterator();
17a1ebd1
VZ
544 if ( pos )
545 node = m_tools.Item(pos - 1);
222ed1d6 546
38762f09
VZ
547 while ( node )
548 {
17a1ebd1
VZ
549 wxToolBarTool *toolNext = (wxToolBarTool *)node->GetData();
550 if ( !toolNext->IsRadio() )
38762f09
VZ
551 break;
552
17a1ebd1 553 widget = toolNext->m_item;
38762f09
VZ
554
555 node = node->GetPrevious();
556 }
557
558 if ( !widget )
559 {
560 // this is the first button in the radio button group,
561 // it will be toggled automatically by GTK so bring the
562 // internal flag in sync
91af0895 563 tool->Toggle(true);
38762f09
VZ
564 }
565 }
566
567 tool->m_item = gtk_toolbar_insert_element
568 (
569 m_toolbar,
570 tool->GetGtkChildType(),
571 widget,
572 tool->GetLabel().empty()
573 ? NULL
fab591c5 574 : (const char*) wxGTK_CONV( tool->GetLabel() ),
38762f09
VZ
575 tool->GetShortHelp().empty()
576 ? NULL
fab591c5 577 : (const char*) wxGTK_CONV( tool->GetShortHelp() ),
38762f09 578 "", // tooltip_private_text (?)
eba91e51 579 tool->m_image,
38762f09
VZ
580 (GtkSignalFunc)gtk_toolbar_callback,
581 (gpointer)tool,
6a1359c0 582 posGtk
38762f09
VZ
583 );
584
eba91e51 585 wxCHECK_MSG(tool->m_item != NULL, false, _T("gtk_toolbar_insert_element() failed"));
99e8cb50 586
9fa72bd2
MR
587 g_signal_connect (tool->m_item, "enter_notify_event",
588 G_CALLBACK (gtk_toolbar_tool_callback),
589 tool);
590 g_signal_connect (tool->m_item, "leave_notify_event",
591 G_CALLBACK (gtk_toolbar_tool_callback),
592 tool);
729b4756
RR
593 g_signal_connect(tool->m_item, "button-press-event",
594 G_CALLBACK (gtk_toolbar_tool_rclick_callback),
595 tool);
fc6557a6
RR
596
597 if (tool->GetKind() == wxITEM_DROPDOWN)
598 {
599 GdkPixbuf *pixbuf = gdk_pixbuf_new_from_xpm_data( arrow_down_xpm );
600 GtkWidget *dropdown = gtk_toggle_button_new();
601 GtkWidget *image = gtk_image_new_from_pixbuf( pixbuf );
602 gtk_widget_show( image );
603 gtk_container_add( GTK_CONTAINER(dropdown), image );
ddb57e45 604 g_object_unref(pixbuf);
7062497f 605
fc6557a6
RR
606 if (GetWindowStyle() & wxTB_FLAT)
607 gtk_button_set_relief( GTK_BUTTON(dropdown), GTK_RELIEF_NONE );
7062497f 608 GTK_WIDGET_UNSET_FLAGS (dropdown, GTK_CAN_FOCUS);
fc6557a6 609 gtk_widget_show( dropdown );
7062497f 610
fc6557a6
RR
611 g_signal_connect (dropdown, "enter_notify_event",
612 G_CALLBACK (gtk_toolbar_buddy_enter_callback),
613 tool->m_item);
614 g_signal_connect (dropdown, "leave_notify_event",
615 G_CALLBACK (gtk_toolbar_buddy_leave_callback),
616 tool->m_item);
617 g_signal_connect(dropdown, "button-press-event",
618 G_CALLBACK (gtk_toolbar_dropdown_lclick_callback),
619 tool);
7062497f 620
fc6557a6
RR
621 GtkRequisition req;
622 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(tool->m_item) )->size_request )
623 (tool->m_item, &req );
7062497f
VZ
624 gtk_widget_set_size_request( dropdown, -1, req.height );
625
1be45608
VZ
626 gtk_toolbar_insert_widget(m_toolbar, dropdown, NULL, NULL,
627 posGtk + 1);
ddb57e45 628 tool->m_itemDropdown = dropdown;
fc6557a6 629 }
8a0681f9 630 }
8a0681f9
VZ
631 break;
632
633 case wxTOOL_STYLE_SEPARATOR:
6a1359c0 634 gtk_toolbar_insert_space( m_toolbar, posGtk );
1be45608 635 break;
bf9e3e73 636
8a0681f9 637 case wxTOOL_STYLE_CONTROL:
1be45608 638 GtkWidget * const align = gtk_alignment_new(0.5, 0.5, 0, 0);
abdf096a 639 gtk_widget_show(align);
1be45608
VZ
640 gtk_container_add(GTK_CONTAINER(align),
641 tool->GetControl()->m_widget);
642 gtk_toolbar_insert_widget(m_toolbar, align, NULL, NULL, posGtk);
643
1be45608
VZ
644 // remember the container we're in so that we could remove
645 // ourselves from it when we're detached from the toolbar
646 tool->m_item = align;
8a0681f9
VZ
647 break;
648 }
bf9e3e73 649
9f884528 650 InvalidateBestSize();
bf9e3e73 651
91af0895 652 return true;
bf9e3e73
RR
653}
654
4a64a89c 655bool wxToolBar::DoDeleteTool(size_t pos, wxToolBarToolBase *toolBase)
c801d85f 656{
8c4e2405 657 wxToolBarTool* tool = wx_static_cast(wxToolBarTool*, toolBase);
c801d85f 658
8a0681f9 659 switch ( tool->GetStyle() )
97d7bfb8 660 {
8a0681f9 661 case wxTOOL_STYLE_CONTROL:
1be45608
VZ
662 // don't destroy the control here as we can be called from
663 // RemoveTool() and then we need to keep the control alive;
664 // while if we're called from DeleteTool() the control will
665 // be destroyed when wxToolBarToolBase itself is deleted
ddb57e45
PC
666 gtk_container_remove(
667 GTK_CONTAINER(tool->m_item), tool->GetControl()->m_widget);
1be45608 668 // fall through
97d7bfb8 669
8a0681f9
VZ
670 case wxTOOL_STYLE_BUTTON:
671 gtk_widget_destroy( tool->m_item );
1be45608 672 tool->m_item = NULL;
ddb57e45
PC
673 if (tool->m_itemDropdown)
674 {
675 gtk_widget_destroy(tool->m_itemDropdown);
676 tool->m_itemDropdown = NULL;
677 }
8a0681f9 678 break;
97d7bfb8 679
4a64a89c
RD
680 case wxTOOL_STYLE_SEPARATOR:
681 gtk_toolbar_remove_space( m_toolbar, pos );
682 break;
1be45608
VZ
683
684 default:
685 wxFAIL_MSG( "unknown tool style" );
686 return false;
8a0681f9 687 }
c801d85f 688
9f884528 689 InvalidateBestSize();
91af0895 690 return true;
fc008f25 691}
46dc76ba 692
8a0681f9
VZ
693// ----------------------------------------------------------------------------
694// wxToolBar tools state
695// ----------------------------------------------------------------------------
696
697void wxToolBar::DoEnableTool(wxToolBarToolBase *toolBase, bool enable)
c801d85f 698{
8c4e2405 699 wxToolBarTool* tool = wx_static_cast(wxToolBarTool*, toolBase);
8a0681f9 700
8a0681f9 701 if (tool->m_item)
fab591c5 702 {
8a0681f9 703 gtk_widget_set_sensitive( tool->m_item, enable );
fab591c5 704 }
fc008f25 705}
c801d85f 706
248bcf0a 707void wxToolBar::DoToggleTool( wxToolBarToolBase *toolBase, bool toggle )
c801d85f 708{
8c4e2405 709 wxToolBarTool* tool = wx_static_cast(wxToolBarTool*, toolBase);
8a0681f9
VZ
710
711 GtkWidget *item = tool->m_item;
712 if ( item && GTK_IS_TOGGLE_BUTTON(item) )
1144d24d 713 {
eba91e51 714 tool->SetImage(tool->GetBitmap());
c801d85f 715
91af0895 716 m_blockEvent = true;
8a0681f9 717
e343da37 718 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(item), toggle );
248bcf0a 719
91af0895 720 m_blockEvent = false;
1144d24d 721 }
fc008f25 722}
c801d85f 723
8a0681f9
VZ
724void wxToolBar::DoSetToggle(wxToolBarToolBase * WXUNUSED(tool),
725 bool WXUNUSED(toggle))
c801d85f 726{
8a0681f9
VZ
727 // VZ: absolutely no idea about how to do it
728 wxFAIL_MSG( _T("not implemented") );
fc008f25 729}
c801d85f 730
8a0681f9
VZ
731// ----------------------------------------------------------------------------
732// wxToolBar geometry
733// ----------------------------------------------------------------------------
734
735wxToolBarToolBase *wxToolBar::FindToolForPosition(wxCoord WXUNUSED(x),
736 wxCoord WXUNUSED(y)) const
c801d85f 737{
8a0681f9
VZ
738 // VZ: GTK+ doesn't seem to have such thing
739 wxFAIL_MSG( _T("wxToolBar::FindToolForPosition() not implemented") );
740
741 return (wxToolBarToolBase *)NULL;
fc008f25 742}
c801d85f 743
1144d24d 744void wxToolBar::SetMargins( int x, int y )
c801d85f 745{
8a0681f9
VZ
746 wxCHECK_RET( GetToolsCount() == 0,
747 wxT("wxToolBar::SetMargins must be called before adding tools.") );
248bcf0a 748
1144d24d
RR
749 m_xMargin = x;
750 m_yMargin = y;
fc008f25 751}
c801d85f 752
cf4219e7 753void wxToolBar::SetToolSeparation( int separation )
c801d85f 754{
9e691f46 755 // FIXME: this function disappeared
68567a96 756#if 0
1144d24d 757 gtk_toolbar_set_space_size( m_toolbar, separation );
9e691f46
VZ
758#endif
759
8a0681f9 760 m_toolSeparation = separation;
1144d24d
RR
761}
762
a1f79c1e
VZ
763void wxToolBar::SetToolShortHelp( int id, const wxString& helpString )
764{
8c4e2405 765 wxToolBarTool* tool = wx_static_cast(wxToolBarTool*, FindById(id));
a1f79c1e
VZ
766
767 if ( tool )
768 {
769 (void)tool->SetShortHelp(helpString);
770 gtk_tooltips_set_tip(m_toolbar->tooltips, tool->m_item,
fab591c5 771 wxGTK_CONV( helpString ), "");
a1f79c1e
VZ
772 }
773}
774
bbd321ff
RD
775void wxToolBar::SetToolNormalBitmap( int id, const wxBitmap& bitmap )
776{
777 wxToolBarTool* tool = wx_static_cast(wxToolBarTool*, FindById(id));
778 if ( tool )
779 {
780 wxCHECK_RET( tool->IsButton(), wxT("Can only set bitmap on button tools."));
781
782 tool->SetNormalBitmap(bitmap);
783 tool->SetImage(tool->GetBitmap());
f4322df6 784 }
bbd321ff
RD
785}
786
787void wxToolBar::SetToolDisabledBitmap( int id, const wxBitmap& bitmap )
788{
789 wxToolBarTool* tool = wx_static_cast(wxToolBarTool*, FindById(id));
790 if ( tool )
791 {
792 wxCHECK_RET( tool->IsButton(), wxT("Can only set bitmap on button tools."));
793
794 tool->SetDisabledBitmap(bitmap);
795 tool->SetImage(tool->GetBitmap());
f4322df6 796 }
bbd321ff
RD
797}
798
8a0681f9
VZ
799// ----------------------------------------------------------------------------
800// wxToolBar idle handling
801// ----------------------------------------------------------------------------
1144d24d 802
9b7e522a
RR
803void wxToolBar::OnInternalIdle()
804{
1417c811
RR
805 // Check if we have to show window now
806 if (GtkShowFromOnIdle()) return;
f4322df6 807
9b7e522a
RR
808 wxCursor cursor = m_cursor;
809 if (g_globalCursor.Ok()) cursor = g_globalCursor;
810
f7a11f8c 811 if (cursor.Ok())
9b7e522a 812 {
f7a11f8c 813 /* I now set the cursor the anew in every OnInternalIdle call
8a0681f9
VZ
814 as setting the cursor in a parent window also effects the
815 windows above so that checking for the current cursor is
816 not possible. */
85ec2f26
RR
817
818 if (HasFlag(wxTB_DOCKABLE) && (m_widget->window))
9b7e522a 819 {
8a0681f9
VZ
820 /* if the toolbar is dockable, then m_widget stands for the
821 GtkHandleBox widget, which uses its own window so that we
822 can set the cursor for it. if the toolbar is not dockable,
823 m_widget comes from m_toolbar which uses its parent's
824 window ("windowless windows") and thus we cannot set the
825 cursor. */
826 gdk_window_set_cursor( m_widget->window, cursor.GetCursor() );
827 }
828
222ed1d6 829 wxToolBarToolsList::compatibility_iterator node = m_tools.GetFirst();
8a0681f9
VZ
830 while ( node )
831 {
832 wxToolBarTool *tool = (wxToolBarTool *)node->GetData();
833 node = node->GetNext();
834
835 GtkWidget *item = tool->m_item;
836 if ( item )
837 {
838 GdkWindow *window = item->window;
839
840 if ( window )
841 {
842 gdk_window_set_cursor( window, cursor.GetCursor() );
843 }
844 }
9b7e522a
RR
845 }
846 }
847
ffa51479 848 if (wxUpdateUIEvent::CanUpdate(this) && IsShownOnScreen())
e39af974 849 UpdateWindowUI(wxUPDATE_UI_FROMIDLE);
9b7e522a
RR
850}
851
9d522606
RD
852
853// ----------------------------------------------------------------------------
854
855// static
856wxVisualAttributes
857wxToolBar::GetClassDefaultAttributes(wxWindowVariant WXUNUSED(variant))
858{
9d522606 859 return GetDefaultAttributesFromGTKWidget(gtk_toolbar_new);
9d522606
RD
860}
861
a1f79c1e 862#endif // wxUSE_TOOLBAR_NATIVE