]> git.saurik.com Git - wxWidgets.git/blob - src/gtk/tbargtk.cpp
Several fixes for removing/readding controls to the toolbar:
[wxWidgets.git] / src / gtk / tbargtk.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/gtk/tbargtk.cpp
3 // Purpose: GTK toolbar
4 // Author: Robert Roebling
5 // Modified: 13.12.99 by VZ to derive from wxToolBarBase
6 // RCS-ID: $Id$
7 // Copyright: (c) Robert Roebling
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
10
11 // For compilers that support precompilation, includes "wx.h".
12 #include "wx/wxprec.h"
13
14 #if wxUSE_TOOLBAR_NATIVE
15
16 #include "wx/toolbar.h"
17
18 #ifndef WX_PRECOMP
19 #include "wx/menu.h"
20 #endif
21
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.
24 #undef GTK_DISABLE_DEPRECATED
25
26 #include "wx/gtk/private.h"
27
28 /* XPM */
29 static 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
44
45 // ----------------------------------------------------------------------------
46 // globals
47 // ----------------------------------------------------------------------------
48
49 // data
50 extern bool g_blockEventsOnDrag;
51 extern wxCursor g_globalCursor;
52
53 // ----------------------------------------------------------------------------
54 // private functions
55 // ----------------------------------------------------------------------------
56
57 // translate wxWidgets toolbar style flags to GTK orientation and style
58 static void GetGtkStyle(long style,
59 GtkOrientation *orient, GtkToolbarStyle *gtkStyle)
60 {
61 *orient = ( style & wxTB_LEFT || style & wxTB_RIGHT ) ? GTK_ORIENTATION_VERTICAL : GTK_ORIENTATION_HORIZONTAL;
62
63
64 if ( style & wxTB_TEXT )
65 {
66 *gtkStyle = style & wxTB_NOICONS
67 ? GTK_TOOLBAR_TEXT
68 : (
69 style & wxTB_HORZ_LAYOUT ? GTK_TOOLBAR_BOTH_HORIZ :
70 GTK_TOOLBAR_BOTH);
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
78 // ----------------------------------------------------------------------------
79 // wxToolBarTool
80 // ----------------------------------------------------------------------------
81
82 class wxToolBarTool : public wxToolBarToolBase
83 {
84 public:
85 wxToolBarTool(wxToolBar *tbar,
86 int id,
87 const wxString& label,
88 const wxBitmap& bitmap1,
89 const wxBitmap& bitmap2,
90 wxItemKind kind,
91 wxObject *clientData,
92 const wxString& shortHelpString,
93 const wxString& longHelpString)
94 : wxToolBarToolBase(tbar, id, label, bitmap1, bitmap2, kind,
95 clientData, shortHelpString, longHelpString)
96 {
97 Init();
98 }
99
100 wxToolBarTool(wxToolBar *tbar, wxControl *control, const wxString& label)
101 : wxToolBarToolBase(tbar, control, label)
102 {
103 Init();
104 }
105
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
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
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
138 case wxITEM_DROPDOWN:
139 case wxITEM_NORMAL:
140 return GTK_TOOLBAR_CHILD_BUTTON;
141 }
142 }
143
144 void SetImage(const wxBitmap& bitmap)
145 {
146 if (bitmap.Ok())
147 {
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());
150 }
151 }
152
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;
159
160 protected:
161 void Init();
162 };
163
164 // ----------------------------------------------------------------------------
165 // wxWin macros
166 // ----------------------------------------------------------------------------
167
168 IMPLEMENT_DYNAMIC_CLASS(wxToolBar, wxControl)
169
170 // ============================================================================
171 // implementation
172 // ============================================================================
173
174 //-----------------------------------------------------------------------------
175 // "clicked" (internal from gtk_toolbar)
176 //-----------------------------------------------------------------------------
177
178 extern "C" {
179 static void gtk_toolbar_callback( GtkWidget *widget,
180 wxToolBarTool *tool )
181 {
182 wxToolBar *tbar = (wxToolBar *)tool->GetToolBar();
183
184 if (tbar->m_blockEvent) return;
185
186 if (g_blockEventsOnDrag) return;
187 if (!tool->IsEnabled()) return;
188
189 if (tool->CanBeToggled())
190 {
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 }
198
199 tool->Toggle();
200
201 tool->SetImage(tool->GetBitmap());
202
203 if ( tool->IsRadio() && !tool->IsToggled() )
204 {
205 // radio button went up, don't report this as a wxWin event
206 return;
207 }
208 }
209
210 if( !tbar->OnLeftClick( tool->GetId(), tool->IsToggled() ) && tool->CanBeToggled() )
211 {
212 // revert back
213 tool->Toggle();
214
215 tool->SetImage(tool->GetBitmap());
216 }
217 }
218 }
219
220 //-----------------------------------------------------------------------------
221 // "right-click"
222 //-----------------------------------------------------------------------------
223 extern "C" {
224 static 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
244 //-----------------------------------------------------------------------------
245 // "enter_notify_event" / "leave_notify_event" from dropdown
246 //-----------------------------------------------------------------------------
247
248 extern "C" {
249 static 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
259 static 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 //-----------------------------------------------------------------------------
271 // "left-click" on dropdown
272 //-----------------------------------------------------------------------------
273
274 extern "C"
275 {
276 static void gtk_pop_tb_hide_callback( GtkWidget *WXUNUSED(menu), GtkToggleButton *button )
277 {
278 gtk_toggle_button_set_active( button, FALSE );
279 }
280
281 static 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() );
296 if ( tbar->HandleWindowEvent(evt) )
297 {
298 return TRUE;
299 }
300
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 );
307
308 g_signal_connect (menu->m_menu, "hide",
309 G_CALLBACK (gtk_pop_tb_hide_callback),
310 widget);
311
312 tbar->PopupMenu( menu, widget->allocation.x,
313 widget->allocation.y + widget->allocation.height );
314
315
316 return TRUE;
317 }
318 }
319
320 //-----------------------------------------------------------------------------
321 // "enter_notify_event" / "leave_notify_event"
322 //-----------------------------------------------------------------------------
323
324 extern "C" {
325 static gint gtk_toolbar_tool_callback( GtkWidget *WXUNUSED(widget),
326 GdkEventCrossing *gdk_event,
327 wxToolBarTool *tool )
328 {
329 if (g_blockEventsOnDrag) return TRUE;
330
331 wxToolBar *tb = (wxToolBar *)tool->GetToolBar();
332
333 // emit the event
334 if( gdk_event->type == GDK_ENTER_NOTIFY )
335 tb->OnMouseEnter( tool->GetId() );
336 else
337 tb->OnMouseEnter( -1 );
338
339 return FALSE;
340 }
341 }
342
343 //-----------------------------------------------------------------------------
344 // "size_request" from m_toolbar
345 //-----------------------------------------------------------------------------
346
347 extern "C" {
348 static void
349 size_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
357 //-----------------------------------------------------------------------------
358 // InsertChild callback for wxToolBar
359 //-----------------------------------------------------------------------------
360
361 static void wxInsertChildInToolBar( wxWindow* WXUNUSED(parent),
362 wxWindow* child)
363 {
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);
367 }
368
369 // ----------------------------------------------------------------------------
370 // wxToolBarTool
371 // ----------------------------------------------------------------------------
372
373 void wxToolBarTool::Init()
374 {
375 m_item =
376 m_image = NULL;
377 }
378
379 wxToolBarToolBase *wxToolBar::CreateTool(int id,
380 const wxString& text,
381 const wxBitmap& bitmap1,
382 const wxBitmap& bitmap2,
383 wxItemKind kind,
384 wxObject *clientData,
385 const wxString& shortHelpString,
386 const wxString& longHelpString)
387 {
388 return new wxToolBarTool(this, id, text, bitmap1, bitmap2, kind,
389 clientData, shortHelpString, longHelpString);
390 }
391
392 wxToolBarToolBase *
393 wxToolBar::CreateTool(wxControl *control, const wxString& label)
394 {
395 return new wxToolBarTool(this, control, label);
396 }
397
398 //-----------------------------------------------------------------------------
399 // wxToolBar construction
400 //-----------------------------------------------------------------------------
401
402 void wxToolBar::Init()
403 {
404 m_toolbar = (GtkToolbar *)NULL;
405 m_blockEvent = false;
406 m_defaultWidth = 32;
407 m_defaultHeight = 32;
408 }
409
410 wxToolBar::~wxToolBar()
411 {
412 }
413
414 bool wxToolBar::Create( wxWindow *parent,
415 wxWindowID id,
416 const wxPoint& pos,
417 const wxSize& size,
418 long style,
419 const wxString& name )
420 {
421 m_insertCallback = wxInsertChildInToolBar;
422
423 if ( !PreCreation( parent, pos, size ) ||
424 !CreateBase( parent, id, pos, size, style, wxDefaultValidator, name ))
425 {
426 wxFAIL_MSG( wxT("wxToolBar creation failed") );
427
428 return false;
429 }
430
431 FixupStyle();
432
433 m_toolbar = GTK_TOOLBAR( gtk_toolbar_new() );
434 GtkSetStyle();
435
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);
439
440 SetToolSeparation(7);
441
442 if (style & wxTB_DOCKABLE)
443 {
444 m_widget = gtk_handle_box_new();
445 gtk_container_add( GTK_CONTAINER(m_widget), GTK_WIDGET(m_toolbar) );
446 gtk_widget_show( GTK_WIDGET(m_toolbar) );
447
448 if (style & wxTB_FLAT)
449 gtk_handle_box_set_shadow_type( GTK_HANDLE_BOX(m_widget), GTK_SHADOW_NONE );
450 }
451 else
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));
457 }
458
459 // FIXME: there is no such function for toolbars in 2.0
460 #if 0
461 if (style & wxTB_FLAT)
462 gtk_toolbar_set_button_relief( GTK_TOOLBAR(m_toolbar), GTK_RELIEF_NONE );
463 #endif
464
465 m_parent->DoAddChild( this );
466
467 PostCreation(size);
468
469 g_signal_connect_after(m_toolbar, "size_request",
470 G_CALLBACK(size_request), this);
471
472 return true;
473 }
474
475 GdkWindow *wxToolBar::GTKGetWindow(wxArrayGdkWindows& WXUNUSED(windows)) const
476 {
477 return GTK_WIDGET(m_toolbar)->window;
478 }
479
480 void 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);
488 gtk_toolbar_set_tooltips(m_toolbar, !(style & wxTB_NO_TOOLTIPS));
489 }
490
491 void wxToolBar::SetWindowStyleFlag( long style )
492 {
493 wxToolBarBase::SetWindowStyleFlag(style);
494
495 if ( m_toolbar )
496 GtkSetStyle();
497 }
498
499 bool wxToolBar::DoInsertTool(size_t pos, wxToolBarToolBase *toolBase)
500 {
501 wxToolBarTool* tool = wx_static_cast(wxToolBarTool*, toolBase);
502
503 if ( tool->IsButton() )
504 {
505 if ( !HasFlag(wxTB_NOICONS) )
506 {
507 wxBitmap bitmap = tool->GetNormalBitmap();
508
509 wxCHECK_MSG( bitmap.Ok(), false,
510 wxT("invalid bitmap for wxToolBar icon") );
511
512 tool->m_image = gtk_image_new();
513 tool->SetImage(bitmap);
514
515 gtk_misc_set_alignment((GtkMisc*)tool->m_image, 0.5, 0.5);
516 }
517 }
518
519 int posGtk = 0;
520 if ( pos > 0 )
521 {
522 for ( size_t i = 0; i < pos; i++ )
523 {
524 posGtk++;
525
526 // if we have a dropdown menu, we use 2 GTK tools internally
527 wxToolBarToolsList::compatibility_iterator node = m_tools.Item( i );
528 wxToolBarTool * const tool2 = (wxToolBarTool*) node->GetData();
529 if ( tool2->IsButton() && tool2->GetKind() == wxITEM_DROPDOWN )
530 posGtk++;
531 }
532 }
533
534
535 switch ( tool->GetStyle() )
536 {
537 case wxTOOL_STYLE_BUTTON:
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
541 {
542 GtkWidget *widget = NULL;
543
544 if ( tool->IsRadio() )
545 {
546 wxToolBarToolsList::compatibility_iterator node
547 = wxToolBarToolsList::compatibility_iterator();
548 if ( pos )
549 node = m_tools.Item(pos - 1);
550
551 while ( node )
552 {
553 wxToolBarTool *toolNext = (wxToolBarTool *)node->GetData();
554 if ( !toolNext->IsRadio() )
555 break;
556
557 widget = toolNext->m_item;
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
567 tool->Toggle(true);
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
578 : (const char*) wxGTK_CONV( tool->GetLabel() ),
579 tool->GetShortHelp().empty()
580 ? NULL
581 : (const char*) wxGTK_CONV( tool->GetShortHelp() ),
582 "", // tooltip_private_text (?)
583 tool->m_image,
584 (GtkSignalFunc)gtk_toolbar_callback,
585 (gpointer)tool,
586 posGtk
587 );
588
589 wxCHECK_MSG(tool->m_item != NULL, false, _T("gtk_toolbar_insert_element() failed"));
590
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);
597 g_signal_connect(tool->m_item, "button-press-event",
598 G_CALLBACK (gtk_toolbar_tool_rclick_callback),
599 tool);
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 );
608
609 if (GetWindowStyle() & wxTB_FLAT)
610 gtk_button_set_relief( GTK_BUTTON(dropdown), GTK_RELIEF_NONE );
611 GTK_WIDGET_UNSET_FLAGS (dropdown, GTK_CAN_FOCUS);
612 gtk_widget_show( dropdown );
613
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);
623
624 GtkRequisition req;
625 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(tool->m_item) )->size_request )
626 (tool->m_item, &req );
627 gtk_widget_set_size_request( dropdown, -1, req.height );
628
629 gtk_toolbar_insert_widget(m_toolbar, dropdown, NULL, NULL,
630 posGtk + 1);
631 }
632 }
633 break;
634
635 case wxTOOL_STYLE_SEPARATOR:
636 gtk_toolbar_insert_space( m_toolbar, posGtk );
637 break;
638
639 case wxTOOL_STYLE_CONTROL:
640 GtkWidget * const align = gtk_alignment_new(0.5, 0.5, 0, 0);
641 gtk_widget_show(align);
642 gtk_container_add(GTK_CONTAINER(align),
643 tool->GetControl()->m_widget);
644 gtk_toolbar_insert_widget(m_toolbar, align, NULL, NULL, posGtk);
645
646 // release reference obtained by wxInsertChildInToolBar
647 g_object_unref(tool->GetControl()->m_widget);
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;
652 break;
653 }
654
655 InvalidateBestSize();
656
657 return true;
658 }
659
660 bool wxToolBar::DoDeleteTool(size_t pos, wxToolBarToolBase *toolBase)
661 {
662 wxToolBarTool* tool = wx_static_cast(wxToolBarTool*, toolBase);
663
664 switch ( tool->GetStyle() )
665 {
666 case wxTOOL_STYLE_CONTROL:
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
677
678 case wxTOOL_STYLE_BUTTON:
679 gtk_widget_destroy( tool->m_item );
680 tool->m_item = NULL;
681 break;
682
683 case wxTOOL_STYLE_SEPARATOR:
684 gtk_toolbar_remove_space( m_toolbar, pos );
685 break;
686
687 default:
688 wxFAIL_MSG( "unknown tool style" );
689 return false;
690 }
691
692 InvalidateBestSize();
693 return true;
694 }
695
696 // ----------------------------------------------------------------------------
697 // wxToolBar tools state
698 // ----------------------------------------------------------------------------
699
700 void wxToolBar::DoEnableTool(wxToolBarToolBase *toolBase, bool enable)
701 {
702 wxToolBarTool* tool = wx_static_cast(wxToolBarTool*, toolBase);
703
704 if (tool->m_item)
705 {
706 gtk_widget_set_sensitive( tool->m_item, enable );
707 }
708 }
709
710 void wxToolBar::DoToggleTool( wxToolBarToolBase *toolBase, bool toggle )
711 {
712 wxToolBarTool* tool = wx_static_cast(wxToolBarTool*, toolBase);
713
714 GtkWidget *item = tool->m_item;
715 if ( item && GTK_IS_TOGGLE_BUTTON(item) )
716 {
717 tool->SetImage(tool->GetBitmap());
718
719 m_blockEvent = true;
720
721 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(item), toggle );
722
723 m_blockEvent = false;
724 }
725 }
726
727 void wxToolBar::DoSetToggle(wxToolBarToolBase * WXUNUSED(tool),
728 bool WXUNUSED(toggle))
729 {
730 // VZ: absolutely no idea about how to do it
731 wxFAIL_MSG( _T("not implemented") );
732 }
733
734 // ----------------------------------------------------------------------------
735 // wxToolBar geometry
736 // ----------------------------------------------------------------------------
737
738 wxToolBarToolBase *wxToolBar::FindToolForPosition(wxCoord WXUNUSED(x),
739 wxCoord WXUNUSED(y)) const
740 {
741 // VZ: GTK+ doesn't seem to have such thing
742 wxFAIL_MSG( _T("wxToolBar::FindToolForPosition() not implemented") );
743
744 return (wxToolBarToolBase *)NULL;
745 }
746
747 void wxToolBar::SetMargins( int x, int y )
748 {
749 wxCHECK_RET( GetToolsCount() == 0,
750 wxT("wxToolBar::SetMargins must be called before adding tools.") );
751
752 m_xMargin = x;
753 m_yMargin = y;
754 }
755
756 void wxToolBar::SetToolSeparation( int separation )
757 {
758 // FIXME: this function disappeared
759 #if 0
760 gtk_toolbar_set_space_size( m_toolbar, separation );
761 #endif
762
763 m_toolSeparation = separation;
764 }
765
766 void wxToolBar::SetToolShortHelp( int id, const wxString& helpString )
767 {
768 wxToolBarTool* tool = wx_static_cast(wxToolBarTool*, FindById(id));
769
770 if ( tool )
771 {
772 (void)tool->SetShortHelp(helpString);
773 gtk_tooltips_set_tip(m_toolbar->tooltips, tool->m_item,
774 wxGTK_CONV( helpString ), "");
775 }
776 }
777
778 void 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());
787 }
788 }
789
790 void 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());
799 }
800 }
801
802 // ----------------------------------------------------------------------------
803 // wxToolBar idle handling
804 // ----------------------------------------------------------------------------
805
806 void wxToolBar::OnInternalIdle()
807 {
808 // Check if we have to show window now
809 if (GtkShowFromOnIdle()) return;
810
811 wxCursor cursor = m_cursor;
812 if (g_globalCursor.Ok()) cursor = g_globalCursor;
813
814 if (cursor.Ok())
815 {
816 /* I now set the cursor the anew in every OnInternalIdle call
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. */
820
821 if (HasFlag(wxTB_DOCKABLE) && (m_widget->window))
822 {
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
832 wxToolBarToolsList::compatibility_iterator node = m_tools.GetFirst();
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 }
848 }
849 }
850
851 if (wxUpdateUIEvent::CanUpdate(this))
852 UpdateWindowUI(wxUPDATE_UI_FROMIDLE);
853 }
854
855
856 // ----------------------------------------------------------------------------
857
858 // static
859 wxVisualAttributes
860 wxToolBar::GetClassDefaultAttributes(wxWindowVariant WXUNUSED(variant))
861 {
862 return GetDefaultAttributesFromGTKWidget(gtk_toolbar_new);
863 }
864
865 #endif // wxUSE_TOOLBAR_NATIVE