]>
Commit | Line | Data |
---|---|---|
4bb6408c JS |
1 | ///////////////////////////////////////////////////////////////////////////// |
2 | // Name: toolbar.cpp | |
3 | // Purpose: wxToolBar | |
4 | // Author: Julian Smart | |
5 | // Modified by: | |
6 | // Created: 04/01/98 | |
7 | // RCS-ID: $Id$ | |
8 | // Copyright: (c) Julian Smart | |
bf6c2b35 | 9 | // Licence: wxWindows licence |
4bb6408c JS |
10 | ///////////////////////////////////////////////////////////////////////////// |
11 | ||
12 | #ifdef __GNUG__ | |
13 | #pragma implementation "toolbar.h" | |
14 | #endif | |
15 | ||
16 | #include "wx/wx.h" | |
1a3ac83f JS |
17 | #include "wx/app.h" |
18 | #include "wx/timer.h" | |
1ccbb61a | 19 | #include "wx/toolbar.h" |
0d57be45 | 20 | |
338dd992 JJ |
21 | #ifdef __VMS__ |
22 | #pragma message disable nosimpint | |
23 | #endif | |
0d57be45 JS |
24 | #include <Xm/Xm.h> |
25 | #include <Xm/PushBG.h> | |
26 | #include <Xm/PushB.h> | |
1a3ac83f | 27 | #include <Xm/Label.h> |
0d57be45 JS |
28 | #include <Xm/ToggleB.h> |
29 | #include <Xm/ToggleBG.h> | |
30 | #include <Xm/Form.h> | |
338dd992 JJ |
31 | #ifdef __VMS__ |
32 | #pragma message enable nosimpint | |
33 | #endif | |
0d57be45 JS |
34 | |
35 | #include "wx/motif/private.h" | |
4bb6408c JS |
36 | |
37 | #if !USE_SHARED_LIBRARY | |
38 | IMPLEMENT_DYNAMIC_CLASS(wxToolBar, wxToolBarBase) | |
39 | ||
40 | BEGIN_EVENT_TABLE(wxToolBar, wxToolBarBase) | |
41 | END_EVENT_TABLE() | |
42 | #endif | |
43 | ||
1a3ac83f | 44 | static void wxToolButtonCallback (Widget w, XtPointer clientData, |
bf6c2b35 | 45 | XtPointer ptr); |
1a3ac83f JS |
46 | static void wxToolButtonPopupCallback (Widget w, XtPointer client_data, |
47 | XEvent *event, Boolean *continue_to_dispatch); | |
48 | ||
1a3ac83f JS |
49 | class wxToolBarTimer: public wxTimer |
50 | { | |
51 | public: | |
52 | wxToolBarTimer() { } | |
53 | virtual void Notify(); | |
54 | ||
55 | static Widget help_popup; | |
56 | static Widget buttonWidget; | |
57 | static wxString helpString; | |
58 | }; | |
59 | ||
60 | static wxToolBarTimer* wxTheToolBarTimer = (wxToolBarTimer*) NULL; | |
61 | ||
62 | Widget wxToolBarTimer::help_popup = (Widget) 0; | |
63 | Widget wxToolBarTimer::buttonWidget = (Widget) 0; | |
64 | wxString wxToolBarTimer::helpString = ""; | |
65 | ||
0d57be45 JS |
66 | wxToolBar::wxToolBar(): |
67 | m_widgets(wxKEY_INTEGER) | |
4bb6408c JS |
68 | { |
69 | m_maxWidth = -1; | |
70 | m_maxHeight = -1; | |
71 | m_defaultWidth = 24; | |
72 | m_defaultHeight = 22; | |
4bb6408c JS |
73 | } |
74 | ||
75 | bool wxToolBar::Create(wxWindow *parent, wxWindowID id, const wxPoint& pos, const wxSize& size, | |
76 | long style, const wxString& name) | |
77 | { | |
af111fc3 | 78 | m_windowId = id; |
4bb6408c JS |
79 | m_maxWidth = -1; |
80 | m_maxHeight = -1; | |
bf6c2b35 | 81 | |
4bb6408c JS |
82 | m_defaultWidth = 24; |
83 | m_defaultHeight = 22; | |
84 | SetName(name); | |
0d57be45 JS |
85 | m_backgroundColour = wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DFACE); |
86 | m_foregroundColour = parent->GetForegroundColour(); | |
4bb6408c JS |
87 | m_windowStyle = style; |
88 | ||
89 | SetParent(parent); | |
90 | ||
91 | if (parent) parent->AddChild(this); | |
92 | ||
0d57be45 JS |
93 | Widget parentWidget = (Widget) parent->GetClientWidget(); |
94 | ||
95 | Widget toolbar = XtVaCreateManagedWidget("toolbar", | |
7fe7d506 JS |
96 | xmBulletinBoardWidgetClass, (Widget) parentWidget, |
97 | XmNmarginWidth, 0, | |
98 | XmNmarginHeight, 0, | |
99 | XmNresizePolicy, XmRESIZE_NONE, | |
100 | NULL); | |
101 | /* | |
102 | Widget toolbar = XtVaCreateManagedWidget("toolbar", | |
103 | xmFormWidgetClass, (Widget) m_clientWidget, | |
0d57be45 JS |
104 | XmNtraversalOn, False, |
105 | XmNhorizontalSpacing, 0, | |
106 | XmNverticalSpacing, 0, | |
1a3ac83f JS |
107 | XmNleftOffset, 0, |
108 | XmNrightOffset, 0, | |
109 | XmNmarginWidth, 0, | |
110 | XmNmarginHeight, 0, | |
0d57be45 | 111 | NULL); |
7fe7d506 | 112 | */ |
0d57be45 JS |
113 | |
114 | m_mainWidget = (WXWidget) toolbar; | |
115 | ||
da175b2c | 116 | m_font = parent->GetFont(); |
4b5f3fe6 JS |
117 | ChangeFont(FALSE); |
118 | ||
0d57be45 JS |
119 | SetCanAddEventHandler(TRUE); |
120 | AttachWidget (parent, m_mainWidget, (WXWidget) NULL, pos.x, pos.y, size.x, size.y); | |
121 | ||
0d57be45 | 122 | ChangeBackgroundColour(); |
bf6c2b35 | 123 | |
0d57be45 | 124 | return TRUE; |
4bb6408c JS |
125 | } |
126 | ||
127 | wxToolBar::~wxToolBar() | |
128 | { | |
1a3ac83f JS |
129 | delete wxTheToolBarTimer; |
130 | wxTheToolBarTimer = NULL; | |
131 | ClearTools(); | |
132 | DestroyPixmaps(); | |
4bb6408c JS |
133 | } |
134 | ||
7fe7d506 JS |
135 | bool wxToolBar::CreateTools() |
136 | { | |
137 | if (m_tools.Number() == 0) | |
138 | return FALSE; | |
139 | ||
140 | // Separator spacing | |
141 | const int separatorSize = GetToolSeparation(); // 8; | |
142 | wxSize margins = GetToolMargins(); | |
143 | int marginX = margins.x; | |
144 | int marginY = margins.y; | |
145 | ||
146 | int currentX = marginX; | |
147 | int currentY = marginY; | |
148 | ||
149 | int buttonHeight = 0; | |
150 | ||
151 | int currentSpacing = 0; | |
152 | ||
153 | m_widgets.Clear(); | |
154 | Widget prevButton = (Widget) 0; | |
155 | wxNode* node = m_tools.First(); | |
156 | while (node) | |
157 | { | |
158 | wxToolBarTool *tool = (wxToolBarTool *)node->Data(); | |
159 | ||
160 | if (tool->m_toolStyle == wxTOOL_STYLE_SEPARATOR) | |
161 | currentX += separatorSize; | |
162 | else if (tool->m_bitmap1.Ok()) | |
163 | { | |
164 | Widget button = (Widget) 0; | |
165 | ||
166 | if (tool->m_isToggle) | |
167 | { | |
bf6c2b35 | 168 | button = XtVaCreateWidget("toggleButton", |
7fe7d506 JS |
169 | xmToggleButtonWidgetClass, (Widget) m_mainWidget, |
170 | XmNx, currentX, XmNy, currentY, | |
bf6c2b35 | 171 | // XmNpushButtonEnabled, True, |
7fe7d506 JS |
172 | XmNmultiClick, XmMULTICLICK_KEEP, |
173 | XmNlabelType, XmPIXMAP, | |
174 | NULL); | |
175 | XtAddCallback ((Widget) button, XmNvalueChangedCallback, (XtCallbackProc) wxToolButtonCallback, | |
bf6c2b35 | 176 | (XtPointer) this); |
a91b47e8 JS |
177 | |
178 | XtVaSetValues ((Widget) button, | |
179 | XmNselectColor, m_backgroundColour.AllocColour(XtDisplay((Widget) button)), | |
180 | NULL); | |
7fe7d506 JS |
181 | } |
182 | else | |
183 | { | |
bf6c2b35 | 184 | button = XtVaCreateWidget("button", |
7fe7d506 JS |
185 | xmPushButtonWidgetClass, (Widget) m_mainWidget, |
186 | XmNx, currentX, XmNy, currentY, | |
187 | XmNpushButtonEnabled, True, | |
188 | XmNmultiClick, XmMULTICLICK_KEEP, | |
189 | XmNlabelType, XmPIXMAP, | |
190 | NULL); | |
191 | XtAddCallback (button, | |
192 | XmNactivateCallback, (XtCallbackProc) wxToolButtonCallback, | |
193 | (XtPointer) this); | |
194 | } | |
195 | ||
94b49b93 JS |
196 | DoChangeBackgroundColour((WXWidget) button, m_backgroundColour, TRUE); |
197 | ||
7fe7d506 JS |
198 | // For each button, if there is a mask, we must create |
199 | // a new wxBitmap that has the correct background colour | |
200 | // for the button. Otherwise the background will just be | |
201 | // e.g. black if a transparent XPM has been loaded. | |
202 | wxBitmap originalBitmap = tool->m_bitmap1; | |
203 | ||
204 | if (tool->m_bitmap1.GetMask()) | |
205 | { | |
206 | int backgroundPixel; | |
207 | XtVaGetValues(button, XmNbackground, &backgroundPixel, | |
bf6c2b35 | 208 | NULL); |
7fe7d506 JS |
209 | |
210 | ||
211 | wxColour col; | |
212 | col.SetPixel(backgroundPixel); | |
bf6c2b35 | 213 | |
7fe7d506 JS |
214 | wxBitmap newBitmap = wxCreateMaskedBitmap(tool->m_bitmap1, col); |
215 | ||
216 | tool->m_bitmap1 = newBitmap; | |
217 | } | |
218 | ||
219 | // Create a selected/toggled bitmap. If there isn't a m_bitmap2, | |
220 | // we need to create it (with a darker, selected background) | |
221 | int backgroundPixel; | |
222 | if (tool->m_isToggle) | |
223 | XtVaGetValues(button, XmNselectColor, &backgroundPixel, | |
bf6c2b35 | 224 | NULL); |
7fe7d506 JS |
225 | else |
226 | XtVaGetValues(button, XmNarmColor, &backgroundPixel, | |
bf6c2b35 | 227 | NULL); |
7fe7d506 JS |
228 | |
229 | wxColour col; | |
230 | col.SetPixel(backgroundPixel); | |
231 | ||
232 | if (tool->m_bitmap2.Ok() && tool->m_bitmap2.GetMask()) | |
233 | { | |
234 | // Use what's there | |
235 | wxBitmap newBitmap = wxCreateMaskedBitmap(tool->m_bitmap2, col); | |
236 | tool->m_bitmap2 = newBitmap; | |
237 | } | |
238 | else | |
239 | { | |
240 | // Use unselected bitmap | |
241 | if (originalBitmap.GetMask()) | |
242 | { | |
243 | wxBitmap newBitmap = wxCreateMaskedBitmap(originalBitmap, col); | |
244 | tool->m_bitmap2 = newBitmap; | |
bf6c2b35 | 245 | } |
7fe7d506 JS |
246 | else |
247 | tool->m_bitmap2 = tool->m_bitmap1; | |
248 | } | |
249 | ||
250 | Pixmap pixmap = (Pixmap) tool->m_bitmap1.GetPixmap(); | |
251 | Pixmap insensPixmap = (Pixmap) tool->m_bitmap1.GetInsensPixmap(); | |
252 | ||
253 | if (tool->m_isToggle) | |
254 | { | |
255 | // Toggle button | |
256 | Pixmap pixmap2 = (Pixmap) 0; | |
257 | Pixmap insensPixmap2 = (Pixmap) 0; | |
258 | ||
259 | // If there's a bitmap for the toggled state, use it, | |
260 | // otherwise generate one. | |
261 | if (tool->m_bitmap2.Ok()) | |
262 | { | |
263 | pixmap2 = (Pixmap) tool->m_bitmap2.GetPixmap(); | |
264 | insensPixmap2 = (Pixmap) tool->m_bitmap2.GetInsensPixmap(); | |
265 | } | |
266 | else | |
267 | { | |
268 | pixmap2 = (Pixmap) tool->m_bitmap1.GetArmPixmap(button); | |
269 | insensPixmap2 = XCreateInsensitivePixmap((Display*) wxGetDisplay(), pixmap2); | |
270 | m_pixmaps.Append((wxObject*) insensPixmap2); // Store for later deletion | |
271 | } | |
272 | XtVaSetValues (button, | |
273 | XmNindicatorOn, False, | |
bf6c2b35 VZ |
274 | XmNshadowThickness, 2, |
275 | // XmNborderWidth, 0, | |
276 | // XmNspacing, 0, | |
277 | XmNmarginWidth, 0, | |
278 | XmNmarginHeight, 0, | |
7fe7d506 JS |
279 | XmNfillOnSelect, True, |
280 | XmNlabelPixmap, pixmap, | |
281 | XmNselectPixmap, pixmap2, | |
282 | XmNlabelInsensitivePixmap, insensPixmap, | |
283 | XmNselectInsensitivePixmap, insensPixmap2, | |
284 | XmNlabelType, XmPIXMAP, | |
285 | NULL); | |
286 | } | |
287 | else | |
288 | { | |
289 | Pixmap pixmap2 = (Pixmap) 0; | |
290 | ||
291 | // If there's a bitmap for the armed state, use it, | |
292 | // otherwise generate one. | |
293 | if (tool->m_bitmap2.Ok()) | |
294 | { | |
295 | pixmap2 = (Pixmap) tool->m_bitmap2.GetPixmap(); | |
296 | } | |
297 | else | |
298 | { | |
299 | pixmap2 = (Pixmap) tool->m_bitmap1.GetArmPixmap(button); | |
300 | ||
301 | } | |
302 | // Normal button | |
303 | XtVaSetValues(button, | |
304 | XmNlabelPixmap, pixmap, | |
305 | XmNlabelInsensitivePixmap, insensPixmap, | |
306 | XmNarmPixmap, pixmap2, | |
307 | NULL); | |
308 | } | |
309 | XtManageChild(button); | |
310 | ||
311 | Dimension width, height; | |
312 | XtVaGetValues(button, XmNwidth, & width, XmNheight, & height, | |
bf6c2b35 | 313 | NULL); |
7fe7d506 JS |
314 | currentX += width + marginX; |
315 | buttonHeight = wxMax(buttonHeight, height); | |
316 | ||
bf6c2b35 | 317 | XtAddEventHandler (button, EnterWindowMask | LeaveWindowMask, |
7fe7d506 JS |
318 | False, wxToolButtonPopupCallback, (XtPointer) this); |
319 | m_widgets.Append(tool->m_index, (wxObject*) button); | |
320 | ||
321 | prevButton = button; | |
322 | currentSpacing = 0; | |
323 | } | |
324 | node = node->Next(); | |
325 | } | |
326 | ||
327 | SetSize(-1, -1, currentX, buttonHeight + 2*marginY); | |
328 | ||
329 | return TRUE; | |
330 | } | |
331 | ||
4bb6408c JS |
332 | void wxToolBar::SetToolBitmapSize(const wxSize& size) |
333 | { | |
4b5f3fe6 | 334 | // TODO not necessary? |
4bb6408c | 335 | m_defaultWidth = size.x; m_defaultHeight = size.y; |
4bb6408c JS |
336 | } |
337 | ||
338 | wxSize wxToolBar::GetMaxSize() const | |
339 | { | |
4b5f3fe6 JS |
340 | int w, h; |
341 | GetSize(& w, & h); | |
342 | ||
343 | return wxSize(w, h); | |
4bb6408c JS |
344 | } |
345 | ||
346 | // The button size is bigger than the bitmap size | |
347 | wxSize wxToolBar::GetToolSize() const | |
348 | { | |
4b5f3fe6 | 349 | // TODO not necessary? |
4bb6408c JS |
350 | return wxSize(m_defaultWidth + 8, m_defaultHeight + 7); |
351 | } | |
352 | ||
353 | void wxToolBar::EnableTool(int toolIndex, bool enable) | |
354 | { | |
355 | wxNode *node = m_tools.Find((long)toolIndex); | |
356 | if (node) | |
357 | { | |
358 | wxToolBarTool *tool = (wxToolBarTool *)node->Data(); | |
359 | tool->m_enabled = enable; | |
1a3ac83f JS |
360 | |
361 | WXWidget widget = FindWidgetForIndex(tool->m_index); | |
362 | if (widget == (WXWidget) 0) | |
363 | return; | |
364 | ||
365 | XtSetSensitive((Widget) widget, (Boolean) enable); | |
4bb6408c JS |
366 | } |
367 | } | |
368 | ||
369 | void wxToolBar::ToggleTool(int toolIndex, bool toggle) | |
370 | { | |
371 | wxNode *node = m_tools.Find((long)toolIndex); | |
372 | if (node) | |
373 | { | |
374 | wxToolBarTool *tool = (wxToolBarTool *)node->Data(); | |
375 | if (tool->m_isToggle) | |
376 | { | |
377 | tool->m_toggleState = toggle; | |
1a3ac83f JS |
378 | |
379 | WXWidget widget = FindWidgetForIndex(tool->m_index); | |
380 | if (widget == (WXWidget) 0) | |
381 | return; | |
382 | ||
383 | XmToggleButtonSetState((Widget) widget, (Boolean) toggle, False); | |
4bb6408c JS |
384 | } |
385 | } | |
386 | } | |
387 | ||
388 | void wxToolBar::ClearTools() | |
389 | { | |
0d57be45 JS |
390 | wxNode* node = m_widgets.First(); |
391 | while (node) | |
392 | { | |
393 | Widget button = (Widget) node->Data(); | |
394 | XtDestroyWidget(button); | |
395 | node = node->Next(); | |
396 | } | |
397 | m_widgets.Clear(); | |
1a3ac83f | 398 | DestroyPixmaps(); |
0d57be45 | 399 | |
4bb6408c JS |
400 | wxToolBarBase::ClearTools(); |
401 | } | |
402 | ||
1a3ac83f JS |
403 | void wxToolBar::DestroyPixmaps() |
404 | { | |
405 | wxNode* node = m_pixmaps.First(); | |
406 | while (node) | |
407 | { | |
408 | Pixmap pixmap = (Pixmap) node->Data(); | |
409 | XmDestroyPixmap (DefaultScreenOfDisplay ((Display*) GetXDisplay()), pixmap); | |
410 | node = node->Next(); | |
411 | } | |
412 | m_pixmaps.Clear(); | |
413 | } | |
414 | ||
4bb6408c JS |
415 | // If pushedBitmap is NULL, a reversed version of bitmap is |
416 | // created and used as the pushed/toggled image. | |
417 | // If toggle is TRUE, the button toggles between the two states. | |
418 | ||
af111fc3 | 419 | wxToolBarTool *wxToolBar::AddTool(int index, const wxBitmap& bitmap, const wxBitmap& WXUNUSED(pushedBitmap), |
148c45ed | 420 | bool toggle, wxCoord xPos, wxCoord yPos, wxObject *clientData, const wxString& helpString1, const wxString& helpString2) |
4bb6408c | 421 | { |
c0ed460c | 422 | wxToolBarTool *tool = new wxToolBarTool(index, bitmap, wxNullBitmap, toggle, xPos, yPos, helpString1, helpString2); |
4bb6408c JS |
423 | tool->m_clientData = clientData; |
424 | ||
425 | if (xPos > -1) | |
426 | tool->m_x = xPos; | |
427 | else | |
428 | tool->m_x = m_xMargin; | |
429 | ||
430 | if (yPos > -1) | |
431 | tool->m_y = yPos; | |
432 | else | |
433 | tool->m_y = m_yMargin; | |
434 | ||
a91b47e8 | 435 | wxSize size = GetToolSize(); |
1ccbb61a | 436 | tool->SetSize(size.x, size.y); |
4bb6408c JS |
437 | |
438 | m_tools.Append((long)index, tool); | |
439 | return tool; | |
440 | } | |
441 | ||
1a3ac83f JS |
442 | int wxToolBar::FindIndexForWidget(WXWidget w) |
443 | { | |
444 | wxNode* node = m_widgets.First(); | |
445 | while (node) | |
446 | { | |
447 | WXWidget widget = (WXWidget) node->Data(); | |
448 | if (widget == w) | |
4fabb575 | 449 | return (int) node->GetKeyInteger(); |
1a3ac83f JS |
450 | node = node->Next(); |
451 | } | |
452 | return -1; | |
453 | } | |
454 | ||
455 | WXWidget wxToolBar::FindWidgetForIndex(int index) | |
456 | { | |
457 | wxNode* node = m_widgets.Find((long) index); | |
458 | if (!node) | |
459 | return (WXWidget) 0; | |
460 | else | |
461 | return (WXWidget) node->Data(); | |
462 | } | |
463 | ||
7fe7d506 JS |
464 | WXWidget wxToolBar::GetTopWidget() const |
465 | { | |
466 | return m_mainWidget; | |
467 | } | |
468 | ||
469 | WXWidget wxToolBar::GetClientWidget() const | |
470 | { | |
471 | return m_mainWidget; | |
472 | } | |
473 | ||
474 | WXWidget wxToolBar::GetMainWidget() const | |
475 | { | |
476 | return m_mainWidget; | |
477 | } | |
478 | ||
479 | ||
1a3ac83f | 480 | void wxToolButtonCallback (Widget w, XtPointer clientData, |
af111fc3 | 481 | XtPointer WXUNUSED(ptr)) |
1a3ac83f JS |
482 | { |
483 | wxToolBar *toolBar = (wxToolBar *) clientData; | |
484 | int index = toolBar->FindIndexForWidget((WXWidget) w); | |
485 | ||
486 | if (index != -1) | |
487 | { | |
488 | wxNode *node = toolBar->GetTools().Find((long)index); | |
489 | if (!node) | |
490 | return; | |
491 | wxToolBarTool *tool = (wxToolBarTool *)node->Data(); | |
492 | if (tool->m_isToggle) | |
a91b47e8 | 493 | tool->m_toggleState = !tool->m_toggleState; |
1a3ac83f JS |
494 | |
495 | (void) toolBar->OnLeftClick(index, tool->m_toggleState); | |
496 | } | |
497 | ||
498 | } | |
499 | ||
1a3ac83f JS |
500 | |
501 | static void wxToolButtonPopupCallback (Widget w, XtPointer client_data, | |
af111fc3 | 502 | XEvent *event, Boolean *WXUNUSED(continue_to_dispatch)) |
1a3ac83f JS |
503 | { |
504 | // TODO: retrieve delay before popping up tooltip from wxSystemSettings. | |
505 | int delayMilli = 800; | |
506 | wxToolBar* toolBar = (wxToolBar*) client_data; | |
507 | ||
508 | int index = toolBar->FindIndexForWidget((WXWidget) w); | |
509 | ||
510 | if (index != -1) | |
511 | { | |
512 | wxNode *node = toolBar->GetTools().Find((long)index); | |
513 | if (!node) | |
514 | return; | |
1a3ac83f JS |
515 | wxString str(toolBar->GetToolShortHelp(index)); |
516 | if (str.IsNull() || str == "") | |
517 | return; | |
518 | ||
519 | if (!wxTheToolBarTimer) | |
520 | wxTheToolBarTimer = new wxToolBarTimer; | |
521 | ||
bf6c2b35 VZ |
522 | wxToolBarTimer::buttonWidget = w; |
523 | wxToolBarTimer::helpString = str; | |
1a3ac83f JS |
524 | |
525 | ||
526 | /************************************************************/ | |
527 | /* Popup help label */ | |
528 | /************************************************************/ | |
529 | if (event->type == EnterNotify) | |
530 | { | |
531 | if (wxToolBarTimer::help_popup != (Widget) 0) | |
532 | { | |
533 | XtDestroyWidget (wxToolBarTimer::help_popup); | |
534 | XtPopdown (wxToolBarTimer::help_popup); | |
bf6c2b35 | 535 | } |
1a3ac83f JS |
536 | wxToolBarTimer::help_popup = (Widget) 0; |
537 | ||
538 | // One shot | |
539 | wxTheToolBarTimer->Start(delayMilli, TRUE); | |
540 | ||
541 | } | |
542 | /************************************************************/ | |
543 | /* Popdown help label */ | |
544 | /************************************************************/ | |
545 | else if (event->type == LeaveNotify) | |
546 | { | |
547 | if (wxTheToolBarTimer) | |
548 | wxTheToolBarTimer->Stop(); | |
549 | if (wxToolBarTimer::help_popup != (Widget) 0) | |
550 | { | |
551 | XtDestroyWidget (wxToolBarTimer::help_popup); | |
552 | XtPopdown (wxToolBarTimer::help_popup); | |
bf6c2b35 | 553 | } |
1a3ac83f JS |
554 | wxToolBarTimer::help_popup = (Widget) 0; |
555 | } | |
556 | } | |
557 | } | |
558 | ||
559 | void wxToolBarTimer::Notify() | |
560 | { | |
561 | Position x, y; | |
562 | ||
563 | /************************************************************/ | |
564 | /* Create shell without window decorations */ | |
565 | /************************************************************/ | |
bf6c2b35 VZ |
566 | help_popup = XtVaCreatePopupShell ("shell", |
567 | overrideShellWidgetClass, (Widget) wxTheApp->GetTopLevelWidget(), | |
1a3ac83f JS |
568 | NULL); |
569 | ||
570 | /************************************************************/ | |
571 | /* Get absolute position on display of toolbar button */ | |
572 | /************************************************************/ | |
573 | XtTranslateCoords (buttonWidget, | |
bf6c2b35 VZ |
574 | (Position) 0, |
575 | (Position) 0, | |
1a3ac83f JS |
576 | &x, &y); |
577 | ||
578 | // Move the tooltip more or less above the button | |
579 | int yOffset = 20; // TODO: What should be really? | |
580 | y -= yOffset; | |
581 | if (y < yOffset) y = 0; | |
582 | ||
583 | /************************************************************/ | |
584 | /* Set the position of the help popup */ | |
585 | /************************************************************/ | |
bf6c2b35 VZ |
586 | XtVaSetValues (help_popup, |
587 | XmNx, (Position) x, | |
588 | XmNy, (Position) y, | |
1a3ac83f | 589 | NULL); |
bf6c2b35 | 590 | |
1a3ac83f JS |
591 | /************************************************************/ |
592 | /* Create help label */ | |
593 | /************************************************************/ | |
594 | XmString text = XmStringCreateSimple ((char*) (const char*) helpString); | |
bf6c2b35 VZ |
595 | XtVaCreateManagedWidget ("help_label", |
596 | xmLabelWidgetClass, help_popup, | |
1a3ac83f | 597 | XmNlabelString, text, |
bf6c2b35 VZ |
598 | XtVaTypedArg, |
599 | XmNforeground, XtRString, "black", | |
600 | strlen("black")+1, | |
601 | XtVaTypedArg, | |
602 | XmNbackground, XtRString, "LightGoldenrod", | |
603 | strlen("LightGoldenrod")+1, | |
1a3ac83f JS |
604 | NULL); |
605 | XmStringFree (text); | |
606 | ||
607 | /************************************************************/ | |
608 | /* Popup help label */ | |
609 | /************************************************************/ | |
610 | XtPopup (help_popup, XtGrabNone); | |
611 | } | |
612 |