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