]> git.saurik.com Git - wxWidgets.git/blob - src/gtk/tbargtk.cpp
[ 1793012 ] wxSpinCtrl::SetValue() doesn't update internal counter
[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 // ============================================================================
12 // declarations
13 // ============================================================================
14
15 // ----------------------------------------------------------------------------
16 // headers
17 // ----------------------------------------------------------------------------
18
19 // For compilers that support precompilation, includes "wx.h".
20 #include "wx/wxprec.h"
21
22 #if wxUSE_TOOLBAR_NATIVE
23
24 #include "wx/toolbar.h"
25
26 #ifndef WX_PRECOMP
27 #include "wx/frame.h"
28 #endif
29
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
37 #include "wx/gtk/private.h"
38 #include "wx/menu.h"
39
40
41 /* XPM */
42 static 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
57
58 // ----------------------------------------------------------------------------
59 // globals
60 // ----------------------------------------------------------------------------
61
62 // data
63 extern bool g_blockEventsOnDrag;
64 extern wxCursor g_globalCursor;
65
66 // ----------------------------------------------------------------------------
67 // private functions
68 // ----------------------------------------------------------------------------
69
70 // translate wxWidgets toolbar style flags to GTK orientation and style
71 static void GetGtkStyle(long style,
72 GtkOrientation *orient, GtkToolbarStyle *gtkStyle)
73 {
74 *orient = ( style & wxTB_LEFT || style & wxTB_RIGHT ) ? GTK_ORIENTATION_VERTICAL : GTK_ORIENTATION_HORIZONTAL;
75
76
77 if ( style & wxTB_TEXT )
78 {
79 *gtkStyle = style & wxTB_NOICONS
80 ? GTK_TOOLBAR_TEXT
81 : (
82 style & wxTB_HORZ_LAYOUT ? GTK_TOOLBAR_BOTH_HORIZ :
83 GTK_TOOLBAR_BOTH);
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
91 // ----------------------------------------------------------------------------
92 // wxToolBarTool
93 // ----------------------------------------------------------------------------
94
95 class wxToolBarTool : public wxToolBarToolBase
96 {
97 public:
98 wxToolBarTool(wxToolBar *tbar,
99 int id,
100 const wxString& label,
101 const wxBitmap& bitmap1,
102 const wxBitmap& bitmap2,
103 wxItemKind kind,
104 wxObject *clientData,
105 const wxString& shortHelpString,
106 const wxString& longHelpString)
107 : wxToolBarToolBase(tbar, id, label, bitmap1, bitmap2, kind,
108 clientData, shortHelpString, longHelpString)
109 {
110 Init();
111 }
112
113 wxToolBarTool(wxToolBar *tbar, wxControl *control, const wxString& label)
114 : wxToolBarToolBase(tbar, control, label)
115 {
116 Init();
117 }
118
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
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
140 case wxITEM_DROPDOWN:
141 case wxITEM_NORMAL:
142 return GTK_TOOLBAR_CHILD_BUTTON;
143 }
144 }
145
146 void SetImage(const wxBitmap& bitmap)
147 {
148 if (bitmap.Ok())
149 {
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());
152 }
153 }
154
155 GtkWidget *m_item;
156 GtkWidget *m_image;
157
158 protected:
159 void Init();
160 };
161
162 // ----------------------------------------------------------------------------
163 // wxWin macros
164 // ----------------------------------------------------------------------------
165
166 IMPLEMENT_DYNAMIC_CLASS(wxToolBar, wxControl)
167
168 // ============================================================================
169 // implementation
170 // ============================================================================
171
172 //-----------------------------------------------------------------------------
173 // "clicked" (internal from gtk_toolbar)
174 //-----------------------------------------------------------------------------
175
176 extern "C" {
177 static void gtk_toolbar_callback( GtkWidget *widget,
178 wxToolBarTool *tool )
179 {
180 wxToolBar *tbar = (wxToolBar *)tool->GetToolBar();
181
182 if (tbar->m_blockEvent) return;
183
184 if (g_blockEventsOnDrag) return;
185 if (!tool->IsEnabled()) return;
186
187 if (tool->CanBeToggled())
188 {
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 }
196
197 tool->Toggle();
198
199 tool->SetImage(tool->GetBitmap());
200
201 if ( tool->IsRadio() && !tool->IsToggled() )
202 {
203 // radio button went up, don't report this as a wxWin event
204 return;
205 }
206 }
207
208 if( !tbar->OnLeftClick( tool->GetId(), tool->IsToggled() ) && tool->CanBeToggled() )
209 {
210 // revert back
211 tool->Toggle();
212
213 tool->SetImage(tool->GetBitmap());
214 }
215 }
216 }
217
218 //-----------------------------------------------------------------------------
219 // "right-click"
220 //-----------------------------------------------------------------------------
221 extern "C" {
222 static 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
242 //-----------------------------------------------------------------------------
243 // "enter_notify_event" / "leave_notify_event" from dropdown
244 //-----------------------------------------------------------------------------
245
246 extern "C" {
247 static 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
257 static 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 //-----------------------------------------------------------------------------
269 // "left-click" on dropdown
270 //-----------------------------------------------------------------------------
271
272 extern "C"
273 {
274 static void gtk_pop_tb_hide_callback( GtkWidget *WXUNUSED(menu), GtkToggleButton *button )
275 {
276 gtk_toggle_button_set_active( button, FALSE );
277 }
278
279 static 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 }
298
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 );
305
306 g_signal_connect (menu->m_menu, "hide",
307 G_CALLBACK (gtk_pop_tb_hide_callback),
308 widget);
309
310 tbar->PopupMenu( menu, widget->allocation.x,
311 widget->allocation.y + widget->allocation.height );
312
313
314 return TRUE;
315 }
316 }
317
318 //-----------------------------------------------------------------------------
319 // "enter_notify_event" / "leave_notify_event"
320 //-----------------------------------------------------------------------------
321
322 extern "C" {
323 static gint gtk_toolbar_tool_callback( GtkWidget *WXUNUSED(widget),
324 GdkEventCrossing *gdk_event,
325 wxToolBarTool *tool )
326 {
327 if (g_blockEventsOnDrag) return TRUE;
328
329 wxToolBar *tb = (wxToolBar *)tool->GetToolBar();
330
331 // emit the event
332 if( gdk_event->type == GDK_ENTER_NOTIFY )
333 tb->OnMouseEnter( tool->GetId() );
334 else
335 tb->OnMouseEnter( -1 );
336
337 return FALSE;
338 }
339 }
340
341 extern "C" {
342 static
343 void gtktoolwidget_size_callback( GtkWidget *widget,
344 GtkAllocation *alloc,
345 wxWindow *win )
346 {
347 // this shouldn't happen...
348 if (win->GetParent()->m_wxwindow) return;
349
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 }
362 //-----------------------------------------------------------------------------
363 // InsertChild callback for wxToolBar
364 //-----------------------------------------------------------------------------
365
366 static void wxInsertChildInToolBar( wxWindow* WXUNUSED(parent),
367 wxWindow* child)
368 {
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);
372 }
373
374 // ----------------------------------------------------------------------------
375 // wxToolBarTool
376 // ----------------------------------------------------------------------------
377
378 void wxToolBarTool::Init()
379 {
380 m_item =
381 m_image = NULL;
382 }
383
384 wxToolBarToolBase *wxToolBar::CreateTool(int id,
385 const wxString& text,
386 const wxBitmap& bitmap1,
387 const wxBitmap& bitmap2,
388 wxItemKind kind,
389 wxObject *clientData,
390 const wxString& shortHelpString,
391 const wxString& longHelpString)
392 {
393 return new wxToolBarTool(this, id, text, bitmap1, bitmap2, kind,
394 clientData, shortHelpString, longHelpString);
395 }
396
397 wxToolBarToolBase *
398 wxToolBar::CreateTool(wxControl *control, const wxString& label)
399 {
400 return new wxToolBarTool(this, control, label);
401 }
402
403 //-----------------------------------------------------------------------------
404 // wxToolBar construction
405 //-----------------------------------------------------------------------------
406
407 void wxToolBar::Init()
408 {
409 m_toolbar = (GtkToolbar *)NULL;
410 m_blockEvent = false;
411 m_defaultWidth = 32;
412 m_defaultHeight = 32;
413 }
414
415 wxToolBar::~wxToolBar()
416 {
417 }
418
419 bool wxToolBar::Create( wxWindow *parent,
420 wxWindowID id,
421 const wxPoint& pos,
422 const wxSize& size,
423 long style,
424 const wxString& name )
425 {
426 m_insertCallback = wxInsertChildInToolBar;
427
428 if ( !PreCreation( parent, pos, size ) ||
429 !CreateBase( parent, id, pos, size, style, wxDefaultValidator, name ))
430 {
431 wxFAIL_MSG( wxT("wxToolBar creation failed") );
432
433 return false;
434 }
435
436 FixupStyle();
437
438 m_toolbar = GTK_TOOLBAR( gtk_toolbar_new() );
439 GtkSetStyle();
440
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);
444
445 SetToolSeparation(7);
446
447 if (style & wxTB_DOCKABLE)
448 {
449 m_widget = gtk_handle_box_new();
450 gtk_container_add( GTK_CONTAINER(m_widget), GTK_WIDGET(m_toolbar) );
451 gtk_widget_show( GTK_WIDGET(m_toolbar) );
452
453 if (style & wxTB_FLAT)
454 gtk_handle_box_set_shadow_type( GTK_HANDLE_BOX(m_widget), GTK_SHADOW_NONE );
455 }
456 else
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));
462 }
463
464 // FIXME: there is no such function for toolbars in 2.0
465 #if 0
466 if (style & wxTB_FLAT)
467 gtk_toolbar_set_button_relief( GTK_TOOLBAR(m_toolbar), GTK_RELIEF_NONE );
468 #endif
469
470 m_parent->DoAddChild( this );
471
472 PostCreation(size);
473
474 return true;
475 }
476
477 GdkWindow *wxToolBar::GTKGetWindow(wxArrayGdkWindows& windows) const
478 {
479 return GTK_WIDGET(m_toolbar)->window;
480 }
481
482 void 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);
490 gtk_toolbar_set_tooltips(m_toolbar, !(style & wxTB_NO_TOOLTIPS));
491 }
492
493 void wxToolBar::SetWindowStyleFlag( long style )
494 {
495 wxToolBarBase::SetWindowStyleFlag(style);
496
497 if ( m_toolbar )
498 GtkSetStyle();
499 }
500
501 bool wxToolBar::DoInsertTool(size_t pos, wxToolBarToolBase *toolBase)
502 {
503 wxToolBarTool* tool = wx_static_cast(wxToolBarTool*, toolBase);
504
505 if ( tool->IsButton() )
506 {
507 if ( !HasFlag(wxTB_NOICONS) )
508 {
509 wxBitmap bitmap = tool->GetNormalBitmap();
510
511 wxCHECK_MSG( bitmap.Ok(), false,
512 wxT("invalid bitmap for wxToolBar icon") );
513
514 tool->m_image = gtk_image_new();
515 tool->SetImage(bitmap);
516
517 gtk_misc_set_alignment((GtkMisc*)tool->m_image, 0.5, 0.5);
518 }
519 }
520
521 int posGtk = 0;
522 if ( pos > 0 )
523 {
524 for ( size_t i = 0; i < pos; i++ )
525 {
526 posGtk++;
527
528 // if we have a dropdown menu, we use 2 GTK tools internally
529 wxToolBarToolsList::compatibility_iterator node = m_tools.Item( i );
530 wxToolBarTool *tool = (wxToolBarTool*) node->GetData();
531 if ( tool->IsButton() && (tool->GetKind() == wxITEM_DROPDOWN) )
532 posGtk++;
533 }
534 }
535
536
537 switch ( tool->GetStyle() )
538 {
539 case wxTOOL_STYLE_BUTTON:
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
543 {
544 GtkWidget *widget = NULL;
545
546 if ( tool->IsRadio() )
547 {
548 wxToolBarToolsList::compatibility_iterator node
549 = wxToolBarToolsList::compatibility_iterator();
550 if ( pos )
551 node = m_tools.Item(pos - 1);
552
553 while ( node )
554 {
555 wxToolBarTool *toolNext = (wxToolBarTool *)node->GetData();
556 if ( !toolNext->IsRadio() )
557 break;
558
559 widget = toolNext->m_item;
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
569 tool->Toggle(true);
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
580 : (const char*) wxGTK_CONV( tool->GetLabel() ),
581 tool->GetShortHelp().empty()
582 ? NULL
583 : (const char*) wxGTK_CONV( tool->GetShortHelp() ),
584 "", // tooltip_private_text (?)
585 tool->m_image,
586 (GtkSignalFunc)gtk_toolbar_callback,
587 (gpointer)tool,
588 posGtk
589 );
590
591 wxCHECK_MSG(tool->m_item != NULL, false, _T("gtk_toolbar_insert_element() failed"));
592
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);
599 g_signal_connect(tool->m_item, "button-press-event",
600 G_CALLBACK (gtk_toolbar_tool_rclick_callback),
601 tool);
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 );
610
611 if (GetWindowStyle() & wxTB_FLAT)
612 gtk_button_set_relief( GTK_BUTTON(dropdown), GTK_RELIEF_NONE );
613 GTK_WIDGET_UNSET_FLAGS (dropdown, GTK_CAN_FOCUS);
614 gtk_widget_show( dropdown );
615
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);
625
626 GtkRequisition req;
627 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(tool->m_item) )->size_request )
628 (tool->m_item, &req );
629 gtk_widget_set_size_request( dropdown, -1, req.height );
630
631 gtk_toolbar_insert_widget(
632 m_toolbar,
633 dropdown,
634 (const char *) NULL,
635 (const char *) NULL,
636 posGtk+1
637 );
638 }
639 }
640 break;
641
642 case wxTOOL_STYLE_SEPARATOR:
643 gtk_toolbar_insert_space( m_toolbar, posGtk );
644
645 // skip the rest
646 return true;
647
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,
654 posGtk
655 );
656 // release reference obtained by wxInsertChildInToolBar
657 g_object_unref(tool->GetControl()->m_widget);
658
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());
662
663 break;
664 }
665
666 GtkRequisition req;
667 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(m_widget) )->size_request )
668 (m_widget, &req );
669 m_width = req.width + m_xMargin;
670 m_height = req.height + 2*m_yMargin;
671 InvalidateBestSize();
672
673 return true;
674 }
675
676 bool wxToolBar::DoDeleteTool(size_t pos, wxToolBarToolBase *toolBase)
677 {
678 wxToolBarTool* tool = wx_static_cast(wxToolBarTool*, toolBase);
679
680 switch ( tool->GetStyle() )
681 {
682 case wxTOOL_STYLE_CONTROL:
683 tool->GetControl()->Destroy();
684 break;
685
686 case wxTOOL_STYLE_BUTTON:
687 gtk_widget_destroy( tool->m_item );
688 break;
689
690 case wxTOOL_STYLE_SEPARATOR:
691 gtk_toolbar_remove_space( m_toolbar, pos );
692 break;
693 }
694
695 InvalidateBestSize();
696 return true;
697 }
698
699 // ----------------------------------------------------------------------------
700 // wxToolBar tools state
701 // ----------------------------------------------------------------------------
702
703 void wxToolBar::DoEnableTool(wxToolBarToolBase *toolBase, bool enable)
704 {
705 wxToolBarTool* tool = wx_static_cast(wxToolBarTool*, toolBase);
706
707 if (tool->m_item)
708 {
709 gtk_widget_set_sensitive( tool->m_item, enable );
710 }
711 }
712
713 void wxToolBar::DoToggleTool( wxToolBarToolBase *toolBase, bool toggle )
714 {
715 wxToolBarTool* tool = wx_static_cast(wxToolBarTool*, toolBase);
716
717 GtkWidget *item = tool->m_item;
718 if ( item && GTK_IS_TOGGLE_BUTTON(item) )
719 {
720 tool->SetImage(tool->GetBitmap());
721
722 m_blockEvent = true;
723
724 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(item), toggle );
725
726 m_blockEvent = false;
727 }
728 }
729
730 void wxToolBar::DoSetToggle(wxToolBarToolBase * WXUNUSED(tool),
731 bool WXUNUSED(toggle))
732 {
733 // VZ: absolutely no idea about how to do it
734 wxFAIL_MSG( _T("not implemented") );
735 }
736
737 // ----------------------------------------------------------------------------
738 // wxToolBar geometry
739 // ----------------------------------------------------------------------------
740
741 wxToolBarToolBase *wxToolBar::FindToolForPosition(wxCoord WXUNUSED(x),
742 wxCoord WXUNUSED(y)) const
743 {
744 // VZ: GTK+ doesn't seem to have such thing
745 wxFAIL_MSG( _T("wxToolBar::FindToolForPosition() not implemented") );
746
747 return (wxToolBarToolBase *)NULL;
748 }
749
750 void wxToolBar::SetMargins( int x, int y )
751 {
752 wxCHECK_RET( GetToolsCount() == 0,
753 wxT("wxToolBar::SetMargins must be called before adding tools.") );
754
755 m_xMargin = x;
756 m_yMargin = y;
757 }
758
759 void wxToolBar::SetToolSeparation( int separation )
760 {
761 // FIXME: this function disappeared
762 #if 0
763 gtk_toolbar_set_space_size( m_toolbar, separation );
764 #endif
765
766 m_toolSeparation = separation;
767 }
768
769 void wxToolBar::SetToolShortHelp( int id, const wxString& helpString )
770 {
771 wxToolBarTool* tool = wx_static_cast(wxToolBarTool*, FindById(id));
772
773 if ( tool )
774 {
775 (void)tool->SetShortHelp(helpString);
776 gtk_tooltips_set_tip(m_toolbar->tooltips, tool->m_item,
777 wxGTK_CONV( helpString ), "");
778 }
779 }
780
781 void 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());
790 }
791 }
792
793 void 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());
802 }
803 }
804
805 // ----------------------------------------------------------------------------
806 // wxToolBar idle handling
807 // ----------------------------------------------------------------------------
808
809 void wxToolBar::OnInternalIdle()
810 {
811 // Check if we have to show window now
812 if (GtkShowFromOnIdle()) return;
813
814 wxCursor cursor = m_cursor;
815 if (g_globalCursor.Ok()) cursor = g_globalCursor;
816
817 if (cursor.Ok())
818 {
819 /* I now set the cursor the anew in every OnInternalIdle call
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. */
823
824 if (HasFlag(wxTB_DOCKABLE) && (m_widget->window))
825 {
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
835 wxToolBarToolsList::compatibility_iterator node = m_tools.GetFirst();
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 }
851 }
852 }
853
854 if (wxUpdateUIEvent::CanUpdate(this))
855 UpdateWindowUI(wxUPDATE_UI_FROMIDLE);
856 }
857
858
859 // ----------------------------------------------------------------------------
860
861 // static
862 wxVisualAttributes
863 wxToolBar::GetClassDefaultAttributes(wxWindowVariant WXUNUSED(variant))
864 {
865 return GetDefaultAttributesFromGTKWidget(gtk_toolbar_new);
866 }
867
868 #endif // wxUSE_TOOLBAR_NATIVE