]> git.saurik.com Git - wxWidgets.git/blob - src/gtk/tbargtk.cpp
crash for frames without children corrected
[wxWidgets.git] / src / gtk / tbargtk.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: tbargtk.cpp
3 // Purpose: GTK toolbar
4 // Author: Robert Roebling
5 // RCS-ID: $Id$
6 // Copyright: (c) Robert Roebling
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
9
10 #ifdef __GNUG__
11 #pragma implementation "tbargtk.h"
12 #endif
13
14 #include "wx/toolbar.h"
15
16 #include "glib.h"
17 #include "gdk/gdk.h"
18 #include "gtk/gtk.h"
19
20 //-----------------------------------------------------------------------------
21 // data
22 //-----------------------------------------------------------------------------
23
24 extern bool g_blockEventsOnDrag;
25
26 //-----------------------------------------------------------------------------
27 // "clicked" (internal from gtk_toolbar)
28 //-----------------------------------------------------------------------------
29
30 static void gtk_toolbar_callback( GtkWidget *WXUNUSED(widget), wxToolBarTool *tool )
31 {
32 if (g_blockEventsOnDrag) return;
33 if (!tool->m_enabled) return;
34
35 if (tool->m_isToggle) tool->m_toggleState = !tool->m_toggleState;
36
37 tool->m_owner->OnLeftClick( tool->m_index, tool->m_toggleState );
38 }
39
40 //-----------------------------------------------------------------------------
41 // "enter_notify_event"
42 //-----------------------------------------------------------------------------
43
44 static gint gtk_toolbar_enter_callback( GtkWidget *WXUNUSED(widget),
45 GdkEventCrossing *WXUNUSED(gdk_event), wxToolBarTool *tool )
46 {
47 if (g_blockEventsOnDrag) return TRUE;
48
49 /* we grey-out the tip text of disabled tool */
50
51 wxToolBar *tb = tool->m_owner;
52
53 if (tool->m_enabled)
54 {
55 if (tb->m_fg->red != 0)
56 {
57 tb->m_fg->red = 0;
58 tb->m_fg->green = 0;
59 tb->m_fg->blue = 0;
60 gdk_color_alloc( gtk_widget_get_colormap( GTK_WIDGET(tb->m_toolbar) ), tb->m_fg );
61 gtk_tooltips_set_colors( GTK_TOOLBAR(tb->m_toolbar)->tooltips, tb->m_bg, tb->m_fg );
62 }
63 }
64 else
65 {
66 if (tb->m_fg->red == 0)
67 {
68 tb->m_fg->red = 33000;
69 tb->m_fg->green = 33000;
70 tb->m_fg->blue = 33000;
71 gdk_color_alloc( gtk_widget_get_colormap( GTK_WIDGET(tb->m_toolbar) ), tb->m_fg );
72 gtk_tooltips_set_colors( GTK_TOOLBAR(tb->m_toolbar)->tooltips, tb->m_bg, tb->m_fg );
73 }
74 }
75
76 /* emit the event */
77
78 tb->OnMouseEnter( tool->m_index );
79
80 return FALSE;
81 }
82
83 //-----------------------------------------------------------------------------
84 // wxToolBar
85 //-----------------------------------------------------------------------------
86
87 IMPLEMENT_DYNAMIC_CLASS(wxToolBar,wxControl)
88
89 wxToolBar::wxToolBar()
90 {
91 }
92
93 wxToolBar::wxToolBar( wxWindow *parent, wxWindowID id,
94 const wxPoint& pos, const wxSize& size,
95 long style, const wxString& name )
96 {
97 Create( parent, id, pos, size, style, name );
98 }
99
100 wxToolBar::~wxToolBar()
101 {
102 delete m_fg;
103 delete m_bg;
104 }
105
106 bool wxToolBar::Create( wxWindow *parent, wxWindowID id,
107 const wxPoint& pos, const wxSize& size,
108 long style, const wxString& name )
109 {
110 m_needParent = TRUE;
111
112 PreCreation( parent, id, pos, size, style, name );
113
114 m_tools.DeleteContents( TRUE );
115
116 m_toolbar = GTK_TOOLBAR( gtk_toolbar_new( GTK_ORIENTATION_HORIZONTAL,
117 GTK_TOOLBAR_ICONS ) );
118
119 m_separation = 5;
120 gtk_toolbar_set_space_size( m_toolbar, m_separation );
121 m_hasToolAlready = FALSE;
122
123 if (style & wxTB_DOCKABLE)
124 {
125 m_widget = gtk_handle_box_new();
126 gtk_container_add( GTK_CONTAINER(m_widget), GTK_WIDGET(m_toolbar) );
127 gtk_widget_show( GTK_WIDGET(m_toolbar) );
128 }
129 else
130 {
131 m_widget = GTK_WIDGET(m_toolbar);
132 }
133
134 gtk_toolbar_set_tooltips( GTK_TOOLBAR(m_toolbar), TRUE );
135
136 m_fg = new GdkColor;
137 m_fg->red = 0;
138 m_fg->green = 0;
139 m_fg->blue = 0;
140 gdk_color_alloc( gtk_widget_get_colormap( GTK_WIDGET(m_toolbar) ), m_fg );
141
142 m_bg = new GdkColor;
143 m_bg->red = 65535;
144 m_bg->green = 65535;
145 m_bg->blue = 50000;
146 gdk_color_alloc( gtk_widget_get_colormap( GTK_WIDGET(m_toolbar) ), m_bg );
147
148 gtk_tooltips_set_colors( GTK_TOOLBAR(m_toolbar)->tooltips, m_bg, m_fg );
149
150 m_xMargin = 0;
151 m_yMargin = 0;
152
153 m_parent->AddChild( this );
154
155 (m_parent->m_insertCallback)( m_parent, this );
156
157 PostCreation();
158
159 Show( TRUE );
160
161 return TRUE;
162 }
163
164 bool wxToolBar::OnLeftClick( int toolIndex, bool toggleDown )
165 {
166 wxCommandEvent event( wxEVT_COMMAND_TOOL_CLICKED, toolIndex );
167 event.SetEventObject(this);
168 event.SetInt( toolIndex );
169 event.SetExtraLong((long) toggleDown);
170
171 GetEventHandler()->ProcessEvent(event);
172
173 return TRUE;
174 }
175
176 void wxToolBar::OnRightClick( int toolIndex, float WXUNUSED(x), float WXUNUSED(y) )
177 {
178 wxCommandEvent event( wxEVT_COMMAND_TOOL_RCLICKED, toolIndex );
179 event.SetEventObject( this );
180 event.SetInt( toolIndex );
181
182 GetEventHandler()->ProcessEvent(event);
183 }
184
185 void wxToolBar::OnMouseEnter( int toolIndex )
186 {
187 wxCommandEvent event( wxEVT_COMMAND_TOOL_ENTER, GetId() );
188 event.SetEventObject(this);
189 event.SetInt( toolIndex );
190
191 GetEventHandler()->ProcessEvent(event);
192 }
193
194 wxToolBarTool *wxToolBar::AddTool( int toolIndex, const wxBitmap& bitmap,
195 const wxBitmap& pushedBitmap, bool toggle,
196 float WXUNUSED(xPos), float WXUNUSED(yPos), wxObject *clientData,
197 const wxString& helpString1, const wxString& helpString2 )
198 {
199 m_hasToolAlready = TRUE;
200
201 wxCHECK_MSG( bitmap.Ok(), (wxToolBarTool *)NULL,
202 "invalid bitmap for wxToolBar icon" );
203
204 wxCHECK_MSG( bitmap.GetBitmap() == NULL, (wxToolBarTool *)NULL,
205 "wxToolBar doesn't support GdkBitmap" );
206
207 wxCHECK_MSG( bitmap.GetPixmap() != NULL, (wxToolBarTool *)NULL,
208 "wxToolBar::Add needs a wxBitmap" );
209
210 GtkWidget *tool_pixmap = (GtkWidget *)NULL;
211
212 GdkPixmap *pixmap = bitmap.GetPixmap();
213
214 GdkBitmap *mask = (GdkBitmap *)NULL;
215 if ( bitmap.GetMask() )
216 mask = bitmap.GetMask()->GetBitmap();
217
218 tool_pixmap = gtk_pixmap_new( pixmap, mask );
219
220 gtk_misc_set_alignment( GTK_MISC(tool_pixmap), 0.5, 0.5 );
221
222 wxToolBarTool *tool = new wxToolBarTool( this, toolIndex, bitmap, pushedBitmap,
223 toggle, clientData,
224 helpString1, helpString2,
225 tool_pixmap );
226
227 GtkToolbarChildType ctype = toggle ? GTK_TOOLBAR_CHILD_TOGGLEBUTTON
228 : GTK_TOOLBAR_CHILD_BUTTON;
229
230 GtkWidget *item = gtk_toolbar_append_element
231 (
232 GTK_TOOLBAR(m_toolbar),
233 ctype,
234 (GtkWidget *)NULL,
235 (const char *)NULL,
236 helpString1,
237 "",
238 tool_pixmap,
239 (GtkSignalFunc)gtk_toolbar_callback,
240 (gpointer)tool
241 );
242
243 tool->m_item = item;
244
245 gtk_signal_connect( GTK_OBJECT(tool->m_item),
246 "enter_notify_event",
247 GTK_SIGNAL_FUNC(gtk_toolbar_enter_callback),
248 (gpointer)tool );
249
250 m_tools.Append( tool );
251
252 return tool;
253 }
254
255 void wxToolBar::AddSeparator()
256 {
257 gtk_toolbar_append_space( m_toolbar );
258 }
259
260 void wxToolBar::ClearTools()
261 {
262 wxFAIL_MSG( "wxToolBar::ClearTools not implemented" );
263 }
264
265 bool wxToolBar::Realize()
266 {
267 m_x = 0;
268 m_y = 0;
269 m_width = 100;
270 m_height = 0;
271
272 wxNode *node = m_tools.First();
273 while (node)
274 {
275 wxToolBarTool *tool = (wxToolBarTool*)node->Data();
276 if (tool->m_bitmap1.Ok())
277 {
278 int tool_height = tool->m_bitmap1.GetHeight();
279 if (tool_height > m_height) m_height = tool_height;
280 }
281
282 node = node->Next();
283 }
284
285 m_height += 5 + 2*m_yMargin;
286
287 return TRUE;
288 }
289
290 void wxToolBar::EnableTool(int toolIndex, bool enable)
291 {
292 wxNode *node = m_tools.First();
293 while (node)
294 {
295 wxToolBarTool *tool = (wxToolBarTool*)node->Data();
296 if (tool->m_index == toolIndex)
297 {
298 tool->m_enabled = enable;
299
300 /* we don't disable the tools for now as the bitmaps don't get
301 greyed anyway and this also disables tooltips
302
303 if (tool->m_item)
304 gtk_widget_set_sensitive( tool->m_item, enable );
305 */
306
307 return;
308 }
309 node = node->Next();
310 }
311
312 wxFAIL_MSG( "wrong toolbar index" );
313 }
314
315 void wxToolBar::ToggleTool( int toolIndex, bool toggle )
316 {
317 wxNode *node = m_tools.First();
318 while (node)
319 {
320 wxToolBarTool *tool = (wxToolBarTool*)node->Data();
321 if (tool->m_index == toolIndex)
322 {
323 tool->m_toggleState = toggle;
324 if ((tool->m_item) && (GTK_IS_TOGGLE_BUTTON(tool->m_item)))
325 gtk_toggle_button_set_state( GTK_TOGGLE_BUTTON(tool->m_item), toggle );
326 return;
327 }
328 node = node->Next();
329 }
330
331 wxFAIL_MSG( "wrong toolbar index" );
332 }
333
334 wxObject *wxToolBar::GetToolClientData( int index ) const
335 {
336 wxNode *node = m_tools.First();
337 while (node)
338 {
339 wxToolBarTool *tool = (wxToolBarTool*)node->Data();
340 if (tool->m_index == index) return tool->m_clientData;;
341 node = node->Next();
342 }
343
344 wxFAIL_MSG( "wrong toolbar index" );
345
346 return (wxObject*)NULL;
347 }
348
349 bool wxToolBar::GetToolState(int toolIndex) const
350 {
351 wxNode *node = m_tools.First();
352 while (node)
353 {
354 wxToolBarTool *tool = (wxToolBarTool*)node->Data();
355 if (tool->m_index == toolIndex) return tool->m_toggleState;
356 node = node->Next();
357 }
358
359 wxFAIL_MSG( "wrong toolbar index" );
360
361 return FALSE;
362 }
363
364 bool wxToolBar::GetToolEnabled(int toolIndex) const
365 {
366 wxNode *node = m_tools.First();
367 while (node)
368 {
369 wxToolBarTool *tool = (wxToolBarTool*)node->Data();
370 if (tool->m_index == toolIndex) return tool->m_enabled;
371 node = node->Next();
372 }
373
374 wxFAIL_MSG( "wrong toolbar index" );
375
376 return FALSE;
377 }
378
379 void wxToolBar::SetMargins( int x, int y )
380 {
381 wxCHECK_RET( !m_hasToolAlready, "wxToolBar::SetMargins must be called before adding tool." );
382
383 if (x > 2) gtk_toolbar_append_space( m_toolbar ); // oh well
384
385 m_xMargin = x;
386 m_yMargin = y;
387 }
388
389 void wxToolBar::SetToolPacking( int WXUNUSED(packing) )
390 {
391 wxFAIL_MSG( "wxToolBar::SetToolPacking not implemented" );
392 }
393
394 void wxToolBar::SetToolSeparation( int separation )
395 {
396 gtk_toolbar_set_space_size( m_toolbar, separation );
397 m_separation = separation;
398 }
399
400 int wxToolBar::GetToolPacking()
401 {
402 return 0;
403 }
404
405 int wxToolBar::GetToolSeparation()
406 {
407 return m_separation;
408 }
409
410 wxString wxToolBar::GetToolLongHelp(int toolIndex)
411 {
412 wxNode *node = m_tools.First();
413 while (node)
414 {
415 wxToolBarTool *tool = (wxToolBarTool*)node->Data();
416 if (tool->m_index == toolIndex)
417 {
418 return tool->m_longHelpString;
419 }
420 node = node->Next();
421 }
422
423 wxFAIL_MSG( "wrong toolbar index" );
424
425 return "";
426 }
427
428 wxString wxToolBar::GetToolShortHelp(int toolIndex)
429 {
430 wxNode *node = m_tools.First();
431 while (node)
432 {
433 wxToolBarTool *tool = (wxToolBarTool*)node->Data();
434 if (tool->m_index == toolIndex)
435 {
436 return tool->m_shortHelpString;
437 }
438 node = node->Next();
439 }
440
441 wxFAIL_MSG( "wrong toolbar index" );
442
443 return "";
444 }
445
446 void wxToolBar::SetToolLongHelp(int toolIndex, const wxString& helpString)
447 {
448 wxNode *node = m_tools.First();
449 while (node)
450 {
451 wxToolBarTool *tool = (wxToolBarTool*)node->Data();
452 if (tool->m_index == toolIndex)
453 {
454 tool->m_longHelpString = helpString;
455 return;
456 }
457 node = node->Next();
458 }
459
460 wxFAIL_MSG( "wrong toolbar index" );
461
462 return;
463 }
464
465 void wxToolBar::SetToolShortHelp(int toolIndex, const wxString& helpString)
466 {
467 wxNode *node = m_tools.First();
468 while (node)
469 {
470 wxToolBarTool *tool = (wxToolBarTool*)node->Data();
471 if (tool->m_index == toolIndex)
472 {
473 tool->m_shortHelpString = helpString;
474 return;
475 }
476 node = node->Next();
477 }
478
479 wxFAIL_MSG( "wrong toolbar index" );
480
481 return;
482 }
483
484