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