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