fixed MSLU check
[wxWidgets.git] / src / gtk1 / tbargtk.cpp
CommitLineData
c801d85f
KB
1/////////////////////////////////////////////////////////////////////////////
2// Name: tbargtk.cpp
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
a3622daa 8// Licence: wxWindows licence
c801d85f
KB
9/////////////////////////////////////////////////////////////////////////////
10
8a0681f9
VZ
11// ============================================================================
12// declarations
13// ============================================================================
14
15// ----------------------------------------------------------------------------
16// headers
17// ----------------------------------------------------------------------------
18
c801d85f 19#ifdef __GNUG__
8a0681f9 20 #pragma implementation "tbargtk.h"
c801d85f
KB
21#endif
22
23#include "wx/toolbar.h"
dcf924a3 24
8a0681f9 25#if wxUSE_TOOLBAR_NATIVE
dcf924a3 26
e702ff0f 27#include "wx/frame.h"
c801d85f 28
9e691f46
VZ
29#include <glib.h>
30#include "wx/gtk/private.h"
83624f79 31
f6bcfd97
BP
32extern GdkFont *GtkGetDefaultGuiFont();
33
8a0681f9
VZ
34// ----------------------------------------------------------------------------
35// globals
36// ----------------------------------------------------------------------------
acfd422a 37
8a0681f9 38// idle system
acfd422a
RR
39extern void wxapp_install_idle_handler();
40extern bool g_isIdle;
41
314055fa 42// data
9b7e522a
RR
43extern bool g_blockEventsOnDrag;
44extern wxCursor g_globalCursor;
314055fa 45
8a0681f9
VZ
46// ----------------------------------------------------------------------------
47// wxToolBarTool
48// ----------------------------------------------------------------------------
49
50class wxToolBarTool : public wxToolBarToolBase
51{
52public:
53 wxToolBarTool(wxToolBar *tbar,
54 int id,
55 const wxBitmap& bitmap1,
56 const wxBitmap& bitmap2,
57 bool toggle,
58 wxObject *clientData,
59 const wxString& shortHelpString,
60 const wxString& longHelpString)
61 : wxToolBarToolBase(tbar, id, bitmap1, bitmap2, toggle,
62 clientData, shortHelpString, longHelpString)
63 {
64 Init();
65 }
66
67 wxToolBarTool(wxToolBar *tbar, wxControl *control)
68 : wxToolBarToolBase(tbar, control)
69 {
70 Init();
71 }
72
73 GtkWidget *m_item;
74 GtkWidget *m_pixmap;
75
76protected:
77 void Init();
78};
79
80// ----------------------------------------------------------------------------
81// wxWin macros
82// ----------------------------------------------------------------------------
83
12ed316d 84IMPLEMENT_DYNAMIC_CLASS(wxToolBar, wxToolBarBase)
8a0681f9
VZ
85
86// ============================================================================
87// implementation
88// ============================================================================
89
c801d85f 90//-----------------------------------------------------------------------------
2f2aa628 91// "clicked" (internal from gtk_toolbar)
c801d85f
KB
92//-----------------------------------------------------------------------------
93
8a0681f9
VZ
94static void gtk_toolbar_callback( GtkWidget *WXUNUSED(widget),
95 wxToolBarTool *tool )
c801d85f 96{
59fe1666
RR
97 if (g_isIdle)
98 wxapp_install_idle_handler();
99
8a0681f9 100 wxToolBar *tbar = (wxToolBar *)tool->GetToolBar();
9864c56d
RR
101
102 if (tbar->m_blockEvent) return;
acfd422a 103
1144d24d 104 if (g_blockEventsOnDrag) return;
8a0681f9 105 if (!tool->IsEnabled()) return;
a3622daa 106
8a0681f9 107 if (tool->CanBeToggled())
85eb36c2 108 {
8a0681f9
VZ
109 tool->Toggle();
110
111 wxBitmap bitmap = tool->GetBitmap();
112 if ( bitmap.Ok() )
113 {
85eb36c2 114 GtkPixmap *pixmap = GTK_PIXMAP( tool->m_pixmap );
8a0681f9
VZ
115
116 GdkBitmap *mask = bitmap.GetMask() ? bitmap.GetMask()->GetBitmap()
117 : (GdkBitmap *)NULL;
118
85eb36c2 119 gtk_pixmap_set( pixmap, bitmap.GetPixmap(), mask );
8a0681f9 120 }
85eb36c2 121 }
a3622daa 122
8a0681f9 123 tbar->OnLeftClick( tool->GetId(), tool->IsToggled() );
fc008f25 124}
c801d85f 125
2f2aa628 126//-----------------------------------------------------------------------------
a8945eef 127// "enter_notify_event" / "leave_notify_event"
2f2aa628
RR
128//-----------------------------------------------------------------------------
129
a8945eef
MB
130static gint gtk_toolbar_tool_callback( GtkWidget *WXUNUSED(widget),
131 GdkEventCrossing *gdk_event,
132 wxToolBarTool *tool )
314055fa 133{
acfd422a
RR
134 if (g_isIdle) wxapp_install_idle_handler();
135
1144d24d 136 if (g_blockEventsOnDrag) return TRUE;
b98d804b 137
8a0681f9 138 wxToolBar *tb = (wxToolBar *)tool->GetToolBar();
b98d804b 139
47c93b63 140 // emit the event
a8945eef
MB
141 if( gdk_event->type == GDK_ENTER_NOTIFY )
142 tb->OnMouseEnter( tool->GetId() );
143 else
144 tb->OnMouseEnter( -1 );
314055fa 145
1144d24d 146 return FALSE;
314055fa
RR
147}
148
bf9e3e73
RR
149//-----------------------------------------------------------------------------
150// InsertChild callback for wxToolBar
151//-----------------------------------------------------------------------------
152
8a0681f9
VZ
153static void wxInsertChildInToolBar( wxToolBar* WXUNUSED(parent),
154 wxWindow* WXUNUSED(child) )
bf9e3e73 155{
47c93b63 156 // we don't do anything here
bf9e3e73
RR
157}
158
8a0681f9
VZ
159// ----------------------------------------------------------------------------
160// wxToolBarTool
161// ----------------------------------------------------------------------------
c801d85f 162
8a0681f9
VZ
163void wxToolBarTool::Init()
164{
165 m_item =
166 m_pixmap = (GtkWidget *)NULL;
167}
c801d85f 168
8a0681f9
VZ
169wxToolBarToolBase *wxToolBar::CreateTool(int id,
170 const wxBitmap& bitmap1,
171 const wxBitmap& bitmap2,
172 bool toggle,
173 wxObject *clientData,
174 const wxString& shortHelpString,
175 const wxString& longHelpString)
176{
177 return new wxToolBarTool(this, id, bitmap1, bitmap2, toggle,
178 clientData, shortHelpString, longHelpString);
179}
b1da76e1 180
8a0681f9 181wxToolBarToolBase *wxToolBar::CreateTool(wxControl *control)
c801d85f 182{
8a0681f9 183 return new wxToolBarTool(this, control);
fc008f25 184}
c801d85f 185
8a0681f9
VZ
186//-----------------------------------------------------------------------------
187// wxToolBar construction
188//-----------------------------------------------------------------------------
189
190void wxToolBar::Init()
c801d85f 191{
8a0681f9
VZ
192 m_fg =
193 m_bg = (GdkColor *)NULL;
8a0681f9 194 m_toolbar = (GtkToolbar *)NULL;
9864c56d 195 m_blockEvent = FALSE;
fc008f25 196}
c801d85f 197
a3622daa 198wxToolBar::~wxToolBar()
c801d85f 199{
83624f79
RR
200 delete m_fg;
201 delete m_bg;
fc008f25 202}
c801d85f 203
8a0681f9
VZ
204bool wxToolBar::Create( wxWindow *parent,
205 wxWindowID id,
206 const wxPoint& pos,
207 const wxSize& size,
208 long style,
209 const wxString& name )
c801d85f 210{
1144d24d 211 m_needParent = TRUE;
bf9e3e73 212 m_insertCallback = (wxInsertChildFunction)wxInsertChildInToolBar;
a3622daa 213
8a0681f9
VZ
214 if ( !PreCreation( parent, pos, size ) ||
215 !CreateBase( parent, id, pos, size, style, wxDefaultValidator, name ))
4dcaf11a 216 {
223d09f6 217 wxFAIL_MSG( wxT("wxToolBar creation failed") );
c801d85f 218
8a0681f9
VZ
219 return FALSE;
220 }
a3622daa 221
8a0681f9
VZ
222 GtkOrientation orient = style & wxTB_VERTICAL ? GTK_ORIENTATION_VERTICAL
223 : GTK_ORIENTATION_HORIZONTAL;
9e691f46
VZ
224
225#ifdef __WXGTK20__
226 m_toolbar = GTK_TOOLBAR( gtk_toolbar_new() );
227 gtk_toolbar_set_orientation(m_toolbar, orient);
228 gtk_toolbar_set_style(m_toolbar, GTK_TOOLBAR_ICONS);
229#else
8a0681f9 230 m_toolbar = GTK_TOOLBAR( gtk_toolbar_new( orient, GTK_TOOLBAR_ICONS ) );
9e691f46 231#endif
a3622daa 232
8a0681f9 233 SetToolSeparation(7);
3502e687
RR
234
235 if (style & wxTB_DOCKABLE)
236 {
237 m_widget = gtk_handle_box_new();
f03fc89f
VZ
238 gtk_container_add( GTK_CONTAINER(m_widget), GTK_WIDGET(m_toolbar) );
239 gtk_widget_show( GTK_WIDGET(m_toolbar) );
8a0681f9 240
f03fc89f 241 if (style & wxTB_FLAT)
858b5bdd 242 gtk_handle_box_set_shadow_type( GTK_HANDLE_BOX(m_widget), GTK_SHADOW_NONE );
3502e687
RR
243 }
244 else
245 {
246 m_widget = GTK_WIDGET(m_toolbar);
247 }
8a0681f9 248
1144d24d 249 gtk_toolbar_set_tooltips( GTK_TOOLBAR(m_toolbar), TRUE );
8a0681f9 250
9e691f46
VZ
251 // FIXME: there is no such function for toolbars in 2.0
252#ifndef __WXGTK20__
858b5bdd
RR
253 if (style & wxTB_FLAT)
254 gtk_toolbar_set_button_relief( GTK_TOOLBAR(m_toolbar), GTK_RELIEF_NONE );
9e691f46 255#endif
be25e480 256
83624f79
RR
257
258 m_fg = new GdkColor;
be25e480
RR
259 m_fg->red = 0;
260 m_fg->green = 0;
83624f79 261 m_fg->blue = 0;
be25e480
RR
262 wxColour fg(0,0,0);
263 fg.CalcPixel( gtk_widget_get_colormap( GTK_WIDGET(m_toolbar) ) );
264 m_fg->pixel = fg.GetPixel();
265
83624f79
RR
266 m_bg = new GdkColor;
267 m_bg->red = 65535;
268 m_bg->green = 65535;
be25e480
RR
269 m_bg->blue = 49980;
270 wxColour bg(255,255,196);
271 bg.CalcPixel( gtk_widget_get_colormap( GTK_WIDGET(m_toolbar) ) );
272 m_bg->pixel = bg.GetPixel();
273
fac4253c
RR
274 gtk_tooltips_force_window( GTK_TOOLBAR(m_toolbar)->tooltips );
275
276 GtkStyle *g_style =
8a0681f9
VZ
277 gtk_style_copy(
278 gtk_widget_get_style(
279 GTK_TOOLBAR(m_toolbar)->tooltips->tip_window ) );
280
fac4253c 281 g_style->bg[GTK_STATE_NORMAL] = *m_bg;
9e691f46
VZ
282
283 SET_STYLE_FONT(g_style, GtkGetDefaultGuiFont());
284
fac4253c 285 gtk_widget_set_style( GTK_TOOLBAR(m_toolbar)->tooltips->tip_window, g_style );
a3622daa 286
f03fc89f 287 m_parent->DoAddChild( this );
8a0681f9 288
1144d24d 289 PostCreation();
a3622daa 290
1144d24d 291 Show( TRUE );
a3622daa 292
1144d24d 293 return TRUE;
fc008f25 294}
c801d85f 295
8a0681f9 296bool wxToolBar::DoInsertTool(size_t pos, wxToolBarToolBase *toolBase)
c801d85f 297{
8a0681f9 298 wxToolBarTool *tool = (wxToolBarTool *)toolBase;
c801d85f 299
6f67eafe
RR
300 // we have inserted a space before all the tools
301 if (m_xMargin > 1) pos++;
302
8a0681f9
VZ
303 if ( tool->IsButton() )
304 {
305 wxBitmap bitmap = tool->GetBitmap1();
c801d85f 306
8a0681f9
VZ
307 wxCHECK_MSG( bitmap.Ok(), FALSE,
308 wxT("invalid bitmap for wxToolBar icon") );
a3622daa 309
8a0681f9
VZ
310 wxCHECK_MSG( bitmap.GetBitmap() == NULL, FALSE,
311 wxT("wxToolBar doesn't support GdkBitmap") );
03f38c58 312
8a0681f9
VZ
313 wxCHECK_MSG( bitmap.GetPixmap() != NULL, FALSE,
314 wxT("wxToolBar::Add needs a wxBitmap") );
315
316 GtkWidget *tool_pixmap = (GtkWidget *)NULL;
317
318 GdkPixmap *pixmap = bitmap.GetPixmap();
a3622daa 319
8a0681f9
VZ
320 GdkBitmap *mask = (GdkBitmap *)NULL;
321 if ( bitmap.GetMask() )
322 mask = bitmap.GetMask()->GetBitmap();
323
324 tool_pixmap = gtk_pixmap_new( pixmap, mask );
c693edf3 325#if (GTK_MINOR_VERSION > 0)
8a0681f9 326 gtk_pixmap_set_build_insensitive( GTK_PIXMAP(tool_pixmap), TRUE );
c693edf3 327#endif
8a0681f9
VZ
328
329 gtk_misc_set_alignment( GTK_MISC(tool_pixmap), 0.5, 0.5 );
a3622daa 330
8a0681f9
VZ
331 tool->m_pixmap = tool_pixmap;
332 }
c801d85f 333
8a0681f9
VZ
334 switch ( tool->GetStyle() )
335 {
336 case wxTOOL_STYLE_BUTTON:
337 tool->m_item = gtk_toolbar_insert_element
338 (
339 m_toolbar,
340 tool->CanBeToggled()
341 ? GTK_TOOLBAR_CHILD_TOGGLEBUTTON
342 : GTK_TOOLBAR_CHILD_BUTTON,
343 (GtkWidget *)NULL,
344 (const char *)NULL,
345 tool->GetShortHelp().mbc_str(),
346 "", // tooltip_private_text (?)
347 tool->m_pixmap,
348 (GtkSignalFunc)gtk_toolbar_callback,
349 (gpointer)tool,
350 pos
351 );
352
353 if ( !tool->m_item )
354 {
355 wxFAIL_MSG( _T("gtk_toolbar_insert_element() failed") );
356
357 return FALSE;
358 }
359
360 gtk_signal_connect( GTK_OBJECT(tool->m_item),
361 "enter_notify_event",
a8945eef
MB
362 GTK_SIGNAL_FUNC(gtk_toolbar_tool_callback),
363 (gpointer)tool );
364 gtk_signal_connect( GTK_OBJECT(tool->m_item),
365 "leave_notify_event",
366 GTK_SIGNAL_FUNC(gtk_toolbar_tool_callback),
8a0681f9
VZ
367 (gpointer)tool );
368 break;
369
370 case wxTOOL_STYLE_SEPARATOR:
4726948f 371 gtk_toolbar_insert_space( m_toolbar, pos );
8a0681f9
VZ
372
373 // skip the rest
374 return TRUE;
bf9e3e73 375
8a0681f9
VZ
376 case wxTOOL_STYLE_CONTROL:
377 gtk_toolbar_insert_widget(
378 m_toolbar,
379 tool->GetControl()->m_widget,
380 (const char *) NULL,
381 (const char *) NULL,
382 pos
383 );
384 break;
385 }
bf9e3e73 386
bf9e3e73 387 GtkRequisition req;
2afa14f2
OK
388 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(m_widget) )->size_request )
389 (m_widget, &req );
00655497 390 m_width = req.width + m_xMargin;
6f67eafe 391 m_height = req.height + 2*m_yMargin;
bf9e3e73 392
bf9e3e73
RR
393 return TRUE;
394}
395
9c2882d9 396bool wxToolBar::DoDeleteTool(size_t WXUNUSED(pos), wxToolBarToolBase *toolBase)
c801d85f 397{
8a0681f9 398 wxToolBarTool *tool = (wxToolBarTool *)toolBase;
c801d85f 399
8a0681f9 400 switch ( tool->GetStyle() )
97d7bfb8 401 {
8a0681f9
VZ
402 case wxTOOL_STYLE_CONTROL:
403 tool->GetControl()->Destroy();
404 break;
97d7bfb8 405
8a0681f9
VZ
406 case wxTOOL_STYLE_BUTTON:
407 gtk_widget_destroy( tool->m_item );
408 break;
97d7bfb8 409
8a0681f9
VZ
410 //case wxTOOL_STYLE_SEPARATOR: -- nothing to do
411 }
c801d85f 412
1144d24d 413 return TRUE;
fc008f25 414}
46dc76ba 415
8a0681f9
VZ
416// ----------------------------------------------------------------------------
417// wxToolBar tools state
418// ----------------------------------------------------------------------------
419
420void wxToolBar::DoEnableTool(wxToolBarToolBase *toolBase, bool enable)
c801d85f 421{
c693edf3 422#if (GTK_MINOR_VERSION > 0)
8a0681f9
VZ
423 wxToolBarTool *tool = (wxToolBarTool *)toolBase;
424
425 /* we don't disable the tools for GTK 1.0 as the bitmaps don't get
426 greyed anyway and this also disables tooltips */
427 if (tool->m_item)
428 gtk_widget_set_sensitive( tool->m_item, enable );
c693edf3 429#endif
fc008f25 430}
c801d85f 431
8a0681f9 432void wxToolBar::DoToggleTool( wxToolBarToolBase *toolBase, bool toggle )
c801d85f 433{
8a0681f9
VZ
434 wxToolBarTool *tool = (wxToolBarTool *)toolBase;
435
436 GtkWidget *item = tool->m_item;
437 if ( item && GTK_IS_TOGGLE_BUTTON(item) )
1144d24d 438 {
8a0681f9
VZ
439 wxBitmap bitmap = tool->GetBitmap();
440 if ( bitmap.Ok() )
441 {
442 GtkPixmap *pixmap = GTK_PIXMAP( tool->m_pixmap );
443
444 GdkBitmap *mask = bitmap.GetMask() ? bitmap.GetMask()->GetBitmap()
445 : (GdkBitmap *)NULL;
446
447 gtk_pixmap_set( pixmap, bitmap.GetPixmap(), mask );
1144d24d 448 }
c801d85f 449
9864c56d 450 m_blockEvent = TRUE;
8a0681f9
VZ
451
452 gtk_toggle_button_set_state( GTK_TOGGLE_BUTTON(item), toggle );
9864c56d
RR
453
454 m_blockEvent = FALSE;
1144d24d 455 }
fc008f25 456}
c801d85f 457
8a0681f9
VZ
458void wxToolBar::DoSetToggle(wxToolBarToolBase * WXUNUSED(tool),
459 bool WXUNUSED(toggle))
c801d85f 460{
8a0681f9
VZ
461 // VZ: absolutely no idea about how to do it
462 wxFAIL_MSG( _T("not implemented") );
fc008f25 463}
c801d85f 464
8a0681f9
VZ
465// ----------------------------------------------------------------------------
466// wxToolBar geometry
467// ----------------------------------------------------------------------------
468
469wxToolBarToolBase *wxToolBar::FindToolForPosition(wxCoord WXUNUSED(x),
470 wxCoord WXUNUSED(y)) const
c801d85f 471{
8a0681f9
VZ
472 // VZ: GTK+ doesn't seem to have such thing
473 wxFAIL_MSG( _T("wxToolBar::FindToolForPosition() not implemented") );
474
475 return (wxToolBarToolBase *)NULL;
fc008f25 476}
c801d85f 477
1144d24d 478void wxToolBar::SetMargins( int x, int y )
c801d85f 479{
8a0681f9
VZ
480 wxCHECK_RET( GetToolsCount() == 0,
481 wxT("wxToolBar::SetMargins must be called before adding tools.") );
1144d24d 482
00655497 483 if (x > 1) gtk_toolbar_append_space( m_toolbar ); // oh well
1144d24d
RR
484
485 m_xMargin = x;
486 m_yMargin = y;
fc008f25 487}
c801d85f 488
cf4219e7 489void wxToolBar::SetToolSeparation( int separation )
c801d85f 490{
9e691f46
VZ
491 // FIXME: this function disappeared
492#ifndef __WXGTK20__
1144d24d 493 gtk_toolbar_set_space_size( m_toolbar, separation );
9e691f46
VZ
494#endif
495
8a0681f9 496 m_toolSeparation = separation;
1144d24d
RR
497}
498
a1f79c1e
VZ
499void wxToolBar::SetToolShortHelp( int id, const wxString& helpString )
500{
501 wxToolBarTool *tool = (wxToolBarTool *)FindById(id);
502
503 if ( tool )
504 {
505 (void)tool->SetShortHelp(helpString);
506 gtk_tooltips_set_tip(m_toolbar->tooltips, tool->m_item,
507 helpString.mbc_str(), "");
508 }
509}
510
8a0681f9
VZ
511// ----------------------------------------------------------------------------
512// wxToolBar idle handling
513// ----------------------------------------------------------------------------
1144d24d 514
9b7e522a
RR
515void wxToolBar::OnInternalIdle()
516{
517 wxCursor cursor = m_cursor;
518 if (g_globalCursor.Ok()) cursor = g_globalCursor;
519
f7a11f8c 520 if (cursor.Ok())
9b7e522a 521 {
f7a11f8c 522 /* I now set the cursor the anew in every OnInternalIdle call
8a0681f9
VZ
523 as setting the cursor in a parent window also effects the
524 windows above so that checking for the current cursor is
525 not possible. */
85ec2f26
RR
526
527 if (HasFlag(wxTB_DOCKABLE) && (m_widget->window))
9b7e522a 528 {
8a0681f9
VZ
529 /* if the toolbar is dockable, then m_widget stands for the
530 GtkHandleBox widget, which uses its own window so that we
531 can set the cursor for it. if the toolbar is not dockable,
532 m_widget comes from m_toolbar which uses its parent's
533 window ("windowless windows") and thus we cannot set the
534 cursor. */
535 gdk_window_set_cursor( m_widget->window, cursor.GetCursor() );
536 }
537
538 wxToolBarToolsList::Node *node = m_tools.GetFirst();
539 while ( node )
540 {
541 wxToolBarTool *tool = (wxToolBarTool *)node->GetData();
542 node = node->GetNext();
543
544 GtkWidget *item = tool->m_item;
545 if ( item )
546 {
547 GdkWindow *window = item->window;
548
549 if ( window )
550 {
551 gdk_window_set_cursor( window, cursor.GetCursor() );
552 }
553 }
9b7e522a
RR
554 }
555 }
556
557 UpdateWindowUI();
558}
559
a1f79c1e 560#endif // wxUSE_TOOLBAR_NATIVE