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