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