]> git.saurik.com Git - wxWidgets.git/blob - src/x11/toolbar.cpp
Removing OS/2 specific positioning methods, no longer needed
[wxWidgets.git] / src / x11 / toolbar.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: x11/toolbar.cpp
3 // Purpose: wxToolBar
4 // Author: Julian Smart
5 // Modified by: 13.12.99 by VZ during toolbar classes reorganization
6 // Created: 04/01/98
7 // RCS-ID: $Id$
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 // ============================================================================
13 // declarations
14 // ============================================================================
15
16 // ----------------------------------------------------------------------------
17 // headers
18 // ----------------------------------------------------------------------------
19
20 #ifdef __GNUG__
21 #pragma implementation "toolbar.h"
22 #endif
23
24 #ifdef __VMS
25 #define XtDisplay XTDISPLAY
26 #endif
27
28 #include "wx/wx.h"
29 #include "wx/app.h"
30 #include "wx/timer.h"
31 #include "wx/toolbar.h"
32
33 #ifdef __VMS__
34 #pragma message disable nosimpint
35 #endif
36 #ifdef __VMS__
37 #pragma message enable nosimpint
38 #endif
39
40
41
42 #include "wx/x11/private.h"
43
44 // ----------------------------------------------------------------------------
45 // wxWin macros
46 // ----------------------------------------------------------------------------
47
48 IMPLEMENT_DYNAMIC_CLASS(wxToolBar, wxToolBarBase)
49
50 // TODO: a decent generic toolbar implementation that
51 // we can put in src/generic
52 #if 0
53
54 // ----------------------------------------------------------------------------
55 // private functions
56 // ----------------------------------------------------------------------------
57
58 static void wxToolButtonCallback (Widget w, XtPointer clientData,
59 XtPointer ptr);
60 static void wxToolButtonPopupCallback (Widget w, XtPointer client_data,
61 XEvent *event, Boolean *continue_to_dispatch);
62
63 // ----------------------------------------------------------------------------
64 // private classes
65 // ----------------------------------------------------------------------------
66
67 class wxToolBarTimer : public wxTimer
68 {
69 public:
70 virtual void Notify();
71
72 static Widget help_popup;
73 static Widget buttonWidget;
74 static wxString helpString;
75 };
76
77 class wxToolBarTool : public wxToolBarToolBase
78 {
79 public:
80 wxToolBarTool(wxToolBar *tbar,
81 int id,
82 const wxBitmap& bitmap1,
83 const wxBitmap& bitmap2,
84 bool toggle,
85 wxObject *clientData,
86 const wxString& shortHelpString,
87 const wxString& longHelpString)
88 : wxToolBarToolBase(tbar, id, bitmap1, bitmap2, toggle,
89 clientData, shortHelpString, longHelpString)
90 {
91 Init();
92 }
93
94 wxToolBarTool(wxToolBar *tbar, wxControl *control)
95 : wxToolBarToolBase(tbar, control)
96 {
97 Init();
98 }
99
100 virtual ~wxToolBarTool();
101
102 // accessors
103 void SetWidget(Widget widget) { m_widget = widget; }
104 Widget GetButtonWidget() const { return m_widget; }
105
106 void SetPixmap(Pixmap pixmap) { m_pixmap = pixmap; }
107 Pixmap GetPixmap() const { return m_pixmap; }
108
109 protected:
110 void Init();
111
112 Widget m_widget;
113 Pixmap m_pixmap;
114 };
115
116 // ----------------------------------------------------------------------------
117 // globals
118 // ----------------------------------------------------------------------------
119
120 static wxToolBarTimer* wxTheToolBarTimer = (wxToolBarTimer*) NULL;
121
122 Widget wxToolBarTimer::help_popup = (Widget) 0;
123 Widget wxToolBarTimer::buttonWidget = (Widget) 0;
124 wxString wxToolBarTimer::helpString;
125
126 // ============================================================================
127 // implementation
128 // ============================================================================
129
130 // ----------------------------------------------------------------------------
131 // wxToolBarTool
132 // ----------------------------------------------------------------------------
133
134 wxToolBarToolBase *wxToolBar::CreateTool(int id,
135 const wxBitmap& bitmap1,
136 const wxBitmap& bitmap2,
137 bool toggle,
138 wxObject *clientData,
139 const wxString& shortHelpString,
140 const wxString& longHelpString)
141 {
142 return new wxToolBarTool(this, id, bitmap1, bitmap2, toggle,
143 clientData, shortHelpString, longHelpString);
144 }
145
146 wxToolBarToolBase *wxToolBar::CreateTool(wxControl *control)
147 {
148 return new wxToolBarTool(this, control);
149 }
150
151 void wxToolBarTool::Init()
152 {
153 m_widget = (Widget)0;
154 m_pixmap = (Pixmap)0;
155 }
156
157 wxToolBarTool::~wxToolBarTool()
158 {
159 if ( m_widget )
160 XtDestroyWidget(m_widget);
161 if ( m_pixmap )
162 XmDestroyPixmap(DefaultScreenOfDisplay((Display*)wxGetDisplay()),
163 m_pixmap);
164 }
165
166 // ----------------------------------------------------------------------------
167 // wxToolBar construction
168 // ----------------------------------------------------------------------------
169
170 void wxToolBar::Init()
171 {
172 m_maxWidth = -1;
173 m_maxHeight = -1;
174 m_defaultWidth = 24;
175 m_defaultHeight = 22;
176 m_toolPacking = 2;
177 m_toolSeparation = 8;
178 m_xMargin = 2;
179 m_yMargin = 2;
180 m_maxRows = 100;
181 m_maxCols = 100;
182 }
183
184 bool wxToolBar::Create(wxWindow *parent,
185 wxWindowID id,
186 const wxPoint& pos,
187 const wxSize& size,
188 long style,
189 const wxString& name)
190 {
191 Init();
192
193 m_windowId = id;
194
195 SetName(name);
196 m_backgroundColour = wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE);
197 m_foregroundColour = parent->GetForegroundColour();
198 m_windowStyle = style;
199
200 SetParent(parent);
201
202 if (parent) parent->AddChild(this);
203
204 Widget parentWidget = (Widget) parent->GetClientWidget();
205
206 Widget toolbar = XtVaCreateManagedWidget("toolbar",
207 xmBulletinBoardWidgetClass, (Widget) parentWidget,
208 XmNmarginWidth, 0,
209 XmNmarginHeight, 0,
210 XmNresizePolicy, XmRESIZE_NONE,
211 NULL);
212 /*
213 Widget toolbar = XtVaCreateManagedWidget("toolbar",
214 xmFormWidgetClass, (Widget) m_clientWidget,
215 XmNtraversalOn, False,
216 XmNhorizontalSpacing, 0,
217 XmNverticalSpacing, 0,
218 XmNleftOffset, 0,
219 XmNrightOffset, 0,
220 XmNmarginWidth, 0,
221 XmNmarginHeight, 0,
222 NULL);
223 */
224
225 m_mainWidget = (WXWidget) toolbar;
226
227 m_font = parent->GetFont();
228 ChangeFont(FALSE);
229
230 SetCanAddEventHandler(TRUE);
231 AttachWidget (parent, m_mainWidget, (WXWidget) NULL, pos.x, pos.y, size.x, size.y);
232
233 ChangeBackgroundColour();
234
235 return TRUE;
236 }
237
238 wxToolBar::~wxToolBar()
239 {
240 delete wxTheToolBarTimer;
241 wxTheToolBarTimer = NULL;
242 }
243
244 bool wxToolBar::Realize()
245 {
246 if ( m_tools.GetCount() == 0 )
247 {
248 // nothing to do
249 return TRUE;
250 }
251
252 // Separator spacing
253 const int separatorSize = GetToolSeparation(); // 8;
254 wxSize margins = GetToolMargins();
255 int packing = GetToolPacking();
256 int marginX = margins.x;
257 int marginY = margins.y;
258
259 int currentX = marginX;
260 int currentY = marginY;
261
262 int buttonHeight = 0;
263
264 int currentSpacing = 0;
265
266 Widget button;
267 Pixmap pixmap, insensPixmap;
268 wxBitmap bmp;
269
270 wxToolBarToolsList::Node *node = m_tools.GetFirst();
271 while ( node )
272 {
273 wxToolBarTool *tool = (wxToolBarTool *)node->GetData();
274
275 switch ( tool->GetStyle() )
276 {
277 case wxTOOL_STYLE_CONTROL:
278 {
279 wxControl* control = tool->GetControl();
280 wxSize sz = control->GetSize();
281 wxPoint pos = control->GetPosition();
282 control->Move(currentX, pos.y);
283 currentX += sz.x + packing;
284
285 break;
286 }
287 case wxTOOL_STYLE_SEPARATOR:
288 currentX += separatorSize;
289 break;
290
291 case wxTOOL_STYLE_BUTTON:
292 button = (Widget) 0;
293
294 if ( tool->CanBeToggled() )
295 {
296 button = XtVaCreateWidget("toggleButton",
297 xmToggleButtonWidgetClass, (Widget) m_mainWidget,
298 XmNx, currentX, XmNy, currentY,
299 XmNindicatorOn, False,
300 XmNshadowThickness, 2,
301 XmNborderWidth, 0,
302 XmNspacing, 0,
303 XmNmarginWidth, 0,
304 XmNmarginHeight, 0,
305 XmNmultiClick, XmMULTICLICK_KEEP,
306 XmNlabelType, XmPIXMAP,
307 NULL);
308 XtAddCallback ((Widget) button, XmNvalueChangedCallback, (XtCallbackProc) wxToolButtonCallback,
309 (XtPointer) this);
310
311 XtVaSetValues ((Widget) button,
312 XmNselectColor, m_backgroundColour.AllocColour(XtDisplay((Widget) button)),
313 NULL);
314 }
315 else
316 {
317 button = XtVaCreateWidget("button",
318 xmPushButtonWidgetClass, (Widget) m_mainWidget,
319 XmNx, currentX, XmNy, currentY,
320 XmNpushButtonEnabled, True,
321 XmNmultiClick, XmMULTICLICK_KEEP,
322 XmNlabelType, XmPIXMAP,
323 NULL);
324 XtAddCallback (button,
325 XmNactivateCallback, (XtCallbackProc) wxToolButtonCallback,
326 (XtPointer) this);
327 }
328
329 DoChangeBackgroundColour((WXWidget) button, m_backgroundColour, TRUE);
330
331 tool->SetWidget(button);
332
333 // For each button, if there is a mask, we must create
334 // a new wxBitmap that has the correct background colour
335 // for the button. Otherwise the background will just be
336 // e.g. black if a transparent XPM has been loaded.
337 bmp = tool->GetBitmap1();
338 if ( bmp.GetMask() )
339 {
340 int backgroundPixel;
341 XtVaGetValues(button, XmNbackground, &backgroundPixel,
342 NULL);
343
344 wxColour col;
345 col.SetPixel(backgroundPixel);
346
347 bmp = wxCreateMaskedBitmap(bmp, col);
348
349 tool->SetBitmap1(bmp);
350 }
351
352 // Create a selected/toggled bitmap. If there isn't a 2nd
353 // bitmap, we need to create it (with a darker, selected
354 // background)
355 int backgroundPixel;
356 if ( tool->CanBeToggled() )
357 XtVaGetValues(button, XmNselectColor, &backgroundPixel,
358 NULL);
359 else
360 XtVaGetValues(button, XmNarmColor, &backgroundPixel,
361 NULL);
362
363 wxColour col;
364 col.SetPixel(backgroundPixel);
365
366 if (tool->GetBitmap2().Ok() && tool->GetBitmap2().GetMask())
367 {
368 // Use what's there
369 wxBitmap newBitmap = wxCreateMaskedBitmap(tool->GetBitmap2(), col);
370 tool->SetBitmap2(newBitmap);
371 }
372 else
373 {
374 // Use unselected bitmap
375 if ( bmp.GetMask() )
376 {
377 wxBitmap newBitmap = wxCreateMaskedBitmap(bmp, col);
378 tool->SetBitmap2(newBitmap);
379 }
380 else
381 tool->SetBitmap2(bmp);
382 }
383
384 pixmap = (Pixmap) bmp.GetPixmap();
385 insensPixmap = (Pixmap) bmp.GetInsensPixmap();
386
387 if (tool->CanBeToggled())
388 {
389 // Toggle button
390 Pixmap pixmap2 = (Pixmap) 0;
391 Pixmap insensPixmap2 = (Pixmap) 0;
392
393 // If there's a bitmap for the toggled state, use it,
394 // otherwise generate one.
395 if (tool->GetBitmap2().Ok())
396 {
397 wxBitmap bmp2 = tool->GetBitmap2();
398 pixmap2 = (Pixmap) bmp2.GetPixmap();
399 insensPixmap2 = (Pixmap) bmp2.GetInsensPixmap();
400 }
401 else
402 {
403 pixmap2 = (Pixmap) bmp.GetArmPixmap(button);
404 insensPixmap2 = XCreateInsensitivePixmap((Display*) wxGetDisplay(), pixmap2);
405 }
406
407 tool->SetPixmap(pixmap2);
408
409 XtVaSetValues (button,
410 XmNfillOnSelect, True,
411 XmNlabelPixmap, pixmap,
412 XmNselectPixmap, pixmap2,
413 XmNlabelInsensitivePixmap, insensPixmap,
414 XmNselectInsensitivePixmap, insensPixmap2,
415 XmNlabelType, XmPIXMAP,
416 NULL);
417 }
418 else
419 {
420 Pixmap pixmap2 = (Pixmap) 0;
421
422 // If there's a bitmap for the armed state, use it,
423 // otherwise generate one.
424 if (tool->GetBitmap2().Ok())
425 {
426 pixmap2 = (Pixmap) tool->GetBitmap2().GetPixmap();
427 }
428 else
429 {
430 pixmap2 = (Pixmap) bmp.GetArmPixmap(button);
431
432 }
433
434 tool->SetPixmap(pixmap2);
435
436 // Normal button
437 XtVaSetValues(button,
438 XmNlabelPixmap, pixmap,
439 XmNlabelInsensitivePixmap, insensPixmap,
440 XmNarmPixmap, pixmap2,
441 NULL);
442 }
443
444 XtManageChild(button);
445
446 {
447 Dimension width, height;
448 XtVaGetValues(button,
449 XmNwidth, &width,
450 XmNheight, & height,
451 NULL);
452 currentX += width + packing;
453 buttonHeight = wxMax(buttonHeight, height);
454 }
455
456 XtAddEventHandler (button, EnterWindowMask | LeaveWindowMask,
457 False, wxToolButtonPopupCallback, (XtPointer) this);
458
459 currentSpacing = 0;
460 break;
461 }
462
463 node = node->GetNext();
464 }
465
466 SetSize(-1, -1, currentX, buttonHeight + 2*marginY);
467
468 return TRUE;
469 }
470
471 wxToolBarToolBase *wxToolBar::FindToolForPosition(wxCoord WXUNUSED(x),
472 wxCoord WXUNUSED(y)) const
473 {
474 wxFAIL_MSG( _T("TODO") );
475
476 return (wxToolBarToolBase *)NULL;
477 }
478
479 bool wxToolBar::DoInsertTool(size_t WXUNUSED(pos), wxToolBarToolBase *tool)
480 {
481 tool->Attach(this);
482
483 return TRUE;
484 }
485
486 bool wxToolBar::DoDeleteTool(size_t WXUNUSED(pos), wxToolBarToolBase *tool)
487 {
488 tool->Detach();
489
490 return TRUE;
491 }
492
493 void wxToolBar::DoEnableTool(wxToolBarToolBase *toolBase, bool enable)
494 {
495 wxToolBarTool *tool = (wxToolBarTool *)toolBase;
496
497 XtSetSensitive(tool->GetButtonWidget(), (Boolean) enable);
498 }
499
500 void wxToolBar::DoToggleTool(wxToolBarToolBase *toolBase, bool toggle)
501 {
502 wxToolBarTool *tool = (wxToolBarTool *)toolBase;
503
504 XmToggleButtonSetState(tool->GetButtonWidget(), (Boolean) toggle, False);
505 }
506
507 void wxToolBar::DoSetToggle(wxToolBarToolBase * WXUNUSED(tool),
508 bool WXUNUSED(toggle))
509 {
510 // nothing to do
511 }
512
513 // ----------------------------------------------------------------------------
514 // Motif callbacks
515 // ----------------------------------------------------------------------------
516
517 wxToolBarToolBase *wxToolBar::FindToolByWidget(WXWidget w) const
518 {
519 wxToolBarToolsList::Node* node = m_tools.GetFirst();
520 while ( node )
521 {
522 wxToolBarTool *tool = (wxToolBarTool *)node->GetData();
523 if ( tool->GetButtonWidget() == w)
524 {
525 return tool;
526 }
527
528 node = node->GetNext();
529 }
530
531 return (wxToolBarToolBase *)NULL;
532 }
533
534 static void wxToolButtonCallback(Widget w,
535 XtPointer clientData,
536 XtPointer WXUNUSED(ptr))
537 {
538 wxToolBar *toolBar = (wxToolBar *) clientData;
539 wxToolBarToolBase *tool = toolBar->FindToolByWidget((WXWidget) w);
540 if ( !tool )
541 return;
542
543 if ( tool->CanBeToggled() )
544 tool->Toggle();
545
546 if ( !toolBar->OnLeftClick(tool->GetId(), tool->IsToggled()) )
547 {
548 // revert
549 tool->Toggle();
550 }
551 }
552
553
554 static void wxToolButtonPopupCallback(Widget w,
555 XtPointer client_data,
556 XEvent *event,
557 Boolean *WXUNUSED(continue_to_dispatch))
558 {
559 // TODO: retrieve delay before popping up tooltip from wxSystemSettings.
560 static const int delayMilli = 800;
561
562 wxToolBar* toolBar = (wxToolBar*) client_data;
563 wxToolBarToolBase *tool = toolBar->FindToolByWidget((WXWidget) w);
564
565 if ( !tool )
566 return;
567
568 wxString tooltip = tool->GetShortHelp();
569 if ( !tooltip )
570 return;
571
572 if (!wxTheToolBarTimer)
573 wxTheToolBarTimer = new wxToolBarTimer;
574
575 wxToolBarTimer::buttonWidget = w;
576 wxToolBarTimer::helpString = tooltip;
577
578 /************************************************************/
579 /* Popup help label */
580 /************************************************************/
581 if (event->type == EnterNotify)
582 {
583 if (wxToolBarTimer::help_popup != (Widget) 0)
584 {
585 XtDestroyWidget (wxToolBarTimer::help_popup);
586 XtPopdown (wxToolBarTimer::help_popup);
587 }
588 wxToolBarTimer::help_popup = (Widget) 0;
589
590 // One shot
591 wxTheToolBarTimer->Start(delayMilli, TRUE);
592
593 }
594 /************************************************************/
595 /* Popdown help label */
596 /************************************************************/
597 else if (event->type == LeaveNotify)
598 {
599 if (wxTheToolBarTimer)
600 wxTheToolBarTimer->Stop();
601 if (wxToolBarTimer::help_popup != (Widget) 0)
602 {
603 XtDestroyWidget (wxToolBarTimer::help_popup);
604 XtPopdown (wxToolBarTimer::help_popup);
605 }
606 wxToolBarTimer::help_popup = (Widget) 0;
607 }
608 }
609
610 void wxToolBarTimer::Notify()
611 {
612 Position x, y;
613
614 /************************************************************/
615 /* Create shell without window decorations */
616 /************************************************************/
617 help_popup = XtVaCreatePopupShell ("shell",
618 overrideShellWidgetClass, (Widget) wxTheApp->GetTopLevelWidget(),
619 NULL);
620
621 /************************************************************/
622 /* Get absolute position on display of toolbar button */
623 /************************************************************/
624 XtTranslateCoords (buttonWidget,
625 (Position) 0,
626 (Position) 0,
627 &x, &y);
628
629 // Move the tooltip more or less above the button
630 int yOffset = 20; // TODO: What should be really?
631 y -= yOffset;
632 if (y < yOffset) y = 0;
633
634 /************************************************************/
635 /* Set the position of the help popup */
636 /************************************************************/
637 XtVaSetValues (help_popup,
638 XmNx, (Position) x,
639 XmNy, (Position) y,
640 NULL);
641
642 /************************************************************/
643 /* Create help label */
644 /************************************************************/
645 XmString text = XmStringCreateSimple ((char*) (const char*) helpString);
646 XtVaCreateManagedWidget ("help_label",
647 xmLabelWidgetClass, help_popup,
648 XmNlabelString, text,
649 XtVaTypedArg,
650 XmNforeground, XtRString, "black",
651 strlen("black")+1,
652 XtVaTypedArg,
653 XmNbackground, XtRString, "LightGoldenrod",
654 strlen("LightGoldenrod")+1,
655 NULL);
656 XmStringFree (text);
657
658 /************************************************************/
659 /* Popup help label */
660 /************************************************************/
661 XtPopup (help_popup, XtGrabNone);
662 }
663
664 #endif