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