1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_svtools.hxx" 30 31 #define _TASKBAR_CXX 32 33 #include <tools/list.hxx> 34 #include <tools/debug.hxx> 35 #include <tools/date.hxx> 36 #include <vcl/image.hxx> 37 #include <vcl/help.hxx> 38 #include <vcl/svapp.hxx> 39 #include <unotools/calendarwrapper.hxx> 40 #include <unotools/syslocale.hxx> 41 #include <svtools/taskbar.hxx> 42 43 // ======================================================================= 44 45 #define TASKSTATUSBAR_CLOCXOFFX 3 46 #define TASKSTATUSBAR_IMAGEOFFX 1 47 48 // ======================================================================= 49 50 struct ImplTaskSBFldItem 51 { 52 TaskStatusFieldItem maItem; 53 sal_uInt16 mnId; 54 long mnOffX; 55 }; 56 57 DECLARE_LIST( ImplTaskSBItemList, ImplTaskSBFldItem* ) 58 59 // ======================================================================= 60 61 sal_Bool ITaskStatusNotify::MouseButtonDown( sal_uInt16, const MouseEvent& ) 62 { 63 return sal_False; 64 } 65 66 // ----------------------------------------------------------------------- 67 68 sal_Bool ITaskStatusNotify::MouseButtonUp( sal_uInt16, const MouseEvent& ) 69 { 70 return sal_False; 71 } 72 73 // ----------------------------------------------------------------------- 74 75 sal_Bool ITaskStatusNotify::MouseMove( sal_uInt16, const MouseEvent& ) 76 { 77 return sal_False; 78 } 79 80 // ----------------------------------------------------------------------- 81 82 sal_Bool ITaskStatusNotify::Command( sal_uInt16, const CommandEvent& ) 83 { 84 return sal_False; 85 } 86 87 // ----------------------------------------------------------------------- 88 89 sal_Bool ITaskStatusNotify::UpdateHelp( sal_uInt16 ) 90 { 91 return sal_False; 92 } 93 94 // ======================================================================= 95 96 TaskStatusFieldItem::TaskStatusFieldItem() 97 { 98 mpNotify = NULL; 99 mnFlags = 0; 100 } 101 102 // ----------------------------------------------------------------------- 103 104 TaskStatusFieldItem::TaskStatusFieldItem( const TaskStatusFieldItem& rItem ) : 105 mpNotify( rItem.mpNotify ), 106 maImage( rItem.maImage ), 107 maQuickHelpText( rItem.maQuickHelpText ), 108 maHelpText( rItem.maHelpText ), 109 mnFlags( rItem.mnFlags ) 110 { 111 } 112 113 // ----------------------------------------------------------------------- 114 115 TaskStatusFieldItem::TaskStatusFieldItem( ITaskStatusNotify* pNotify, 116 const Image& rImage, 117 const XubString& rQuickHelpText, 118 const XubString& rHelpText, 119 sal_uInt16 nFlags ) : 120 mpNotify( pNotify ), 121 maImage( rImage ), 122 maQuickHelpText( rQuickHelpText ), 123 maHelpText( rHelpText ), 124 mnFlags( nFlags ) 125 { 126 } 127 128 // ----------------------------------------------------------------------- 129 130 TaskStatusFieldItem::~TaskStatusFieldItem() 131 { 132 } 133 134 // ----------------------------------------------------------------------- 135 136 const TaskStatusFieldItem& TaskStatusFieldItem::operator=( const TaskStatusFieldItem& rItem ) 137 { 138 mpNotify = rItem.mpNotify; 139 maImage = rItem.maImage; 140 maQuickHelpText = rItem.maQuickHelpText; 141 maHelpText = rItem.maHelpText; 142 mnFlags = rItem.mnFlags; 143 return *this; 144 } 145 146 // ======================================================================= 147 148 TaskStatusBar::TaskStatusBar( Window* pParent, WinBits nWinStyle ) : 149 StatusBar( pParent, nWinStyle | WB_3DLOOK ), 150 maTime( 0, 0, 0 ) 151 { 152 mpFieldItemList = NULL; 153 mpNotifyTaskBar = NULL; 154 mpNotify = NULL; 155 mnClockWidth = 0; 156 mnItemWidth = 0; 157 mnFieldWidth = 0; 158 mnFieldFlags = 0; 159 mbFlashItems = sal_False; 160 mbOutInterval = sal_False; 161 162 maTimer.SetTimeoutHdl( LINK( this, TaskStatusBar, ImplTimerHdl ) ); 163 } 164 165 // ----------------------------------------------------------------------- 166 167 TaskStatusBar::~TaskStatusBar() 168 { 169 if ( mpFieldItemList ) 170 { 171 ImplTaskSBFldItem* pItem = mpFieldItemList->First(); 172 while ( pItem ) 173 { 174 delete pItem; 175 pItem = mpFieldItemList->Next(); 176 } 177 178 delete mpFieldItemList; 179 } 180 } 181 182 // ----------------------------------------------------------------------- 183 184 IMPL_LINK( TaskStatusBar, ImplTimerHdl, Timer*, EMPTYARG ) 185 { 186 sal_Bool bUpdate = ImplUpdateClock(); 187 if ( ImplUpdateFlashItems() ) 188 bUpdate = sal_True; 189 if ( bUpdate ) 190 SetItemData( TASKSTATUSBAR_STATUSFIELDID, NULL ); 191 192 return 0; 193 } 194 195 // ----------------------------------------------------------------------- 196 197 ImplTaskSBFldItem* TaskStatusBar::ImplGetFieldItem( sal_uInt16 nItemId ) const 198 { 199 if ( !mpFieldItemList ) 200 return NULL; 201 202 ImplTaskSBFldItem* pItem = mpFieldItemList->First(); 203 while ( pItem ) 204 { 205 if ( pItem->mnId == nItemId ) 206 return pItem; 207 208 pItem = mpFieldItemList->Next(); 209 } 210 211 return NULL; 212 } 213 214 // ----------------------------------------------------------------------- 215 216 ImplTaskSBFldItem* TaskStatusBar::ImplGetFieldItem( const Point& rPos, sal_Bool& rFieldRect ) const 217 { 218 if ( GetItemId( rPos ) == TASKSTATUSBAR_STATUSFIELDID ) 219 { 220 rFieldRect = sal_True; 221 222 if ( mpFieldItemList ) 223 { 224 long nX = rPos.X()-GetItemRect( TASKSTATUSBAR_STATUSFIELDID ).Left(); 225 ImplTaskSBFldItem* pItem = mpFieldItemList->First(); 226 while ( pItem ) 227 { 228 if ( nX < pItem->mnOffX+pItem->maItem.GetImage().GetSizePixel().Width() ) 229 return pItem; 230 231 pItem = mpFieldItemList->Next(); 232 } 233 } 234 } 235 else 236 rFieldRect = sal_False; 237 238 return NULL; 239 } 240 241 // ----------------------------------------------------------------------- 242 243 sal_Bool TaskStatusBar::ImplUpdateClock() 244 { 245 if ( mnFieldFlags & TASKSTATUSFIELD_CLOCK ) 246 { 247 Time aTime; 248 maTimer.SetTimeout( ((long)60000)-((aTime.GetSec()*1000)+(aTime.Get100Sec()*10)) ); 249 if ( (aTime.GetMin() != maTime.GetMin()) || 250 (aTime.GetHour() != maTime.GetHour()) ) 251 { 252 maTime = aTime; 253 maTimeText = SvtSysLocale().GetLocaleData().getTime( aTime, sal_False, sal_False ); 254 return sal_True; 255 } 256 } 257 258 return sal_False; 259 } 260 261 // ----------------------------------------------------------------------- 262 263 sal_Bool TaskStatusBar::ImplUpdateFlashItems() 264 { 265 if ( mbFlashItems ) 266 { 267 if ( mbOutInterval ) 268 { 269 maTimer.SetTimeout( 900 ); 270 mbOutInterval = sal_False; 271 } 272 else 273 { 274 maTimer.SetTimeout( 700 ); 275 mbOutInterval = sal_True; 276 } 277 278 return sal_True; 279 } 280 281 return sal_False; 282 } 283 284 // ----------------------------------------------------------------------- 285 286 void TaskStatusBar::ImplUpdateField( sal_Bool bItems ) 287 { 288 maTimer.Stop(); 289 290 if ( bItems ) 291 { 292 ImplTaskSBFldItem* pItem = mpFieldItemList->First(); 293 mnItemWidth = 0; 294 mbFlashItems = sal_False; 295 mbOutInterval = sal_False; 296 while ( pItem ) 297 { 298 mnItemWidth += TASKSTATUSBAR_IMAGEOFFX; 299 pItem->mnOffX = mnItemWidth; 300 mnItemWidth += pItem->maItem.GetImage().GetSizePixel().Width(); 301 if ( pItem->maItem.GetFlags() & TASKSTATUSFIELDITEM_FLASH ) 302 mbFlashItems = sal_True; 303 304 pItem = mpFieldItemList->Next(); 305 } 306 } 307 else 308 { 309 if ( mnFieldFlags & TASKSTATUSFIELD_CLOCK ) 310 { 311 XubString aStr = SvtSysLocale().GetLocaleData().getTime( Time( 23, 59, 59 ), sal_False, sal_False ); 312 mnClockWidth = GetTextWidth( aStr )+(TASKSTATUSBAR_CLOCXOFFX*2); 313 } 314 else 315 mnClockWidth = 0; 316 } 317 318 long nNewWidth = mnItemWidth+mnClockWidth; 319 if ( mnItemWidth && !mnClockWidth ) 320 nNewWidth += TASKSTATUSBAR_IMAGEOFFX; 321 if ( nNewWidth != mnFieldWidth ) 322 { 323 RemoveItem( TASKSTATUSBAR_STATUSFIELDID ); 324 325 if ( mnItemWidth || mnClockWidth ) 326 { 327 mnFieldWidth = nNewWidth; 328 long nOffset = GetItemOffset( TASKSTATUSBAR_STATUSFIELDID ); 329 sal_uInt16 nItemPos = GetItemPos( TASKSTATUSBAR_STATUSFIELDID ); 330 InsertItem( TASKSTATUSBAR_STATUSFIELDID, nNewWidth, SIB_RIGHT | SIB_IN | SIB_USERDRAW, nOffset, nItemPos ); 331 } 332 else 333 mnFieldWidth = 0; 334 335 if ( mpNotifyTaskBar ) 336 mpNotifyTaskBar->Resize(); 337 } 338 else 339 SetItemData( TASKSTATUSBAR_STATUSFIELDID, NULL ); 340 341 if ( mbFlashItems || (mnFieldFlags & TASKSTATUSFIELD_CLOCK) ) 342 { 343 ImplUpdateClock(); 344 mbOutInterval = sal_True; 345 ImplUpdateFlashItems(); 346 maTimer.Start(); 347 } 348 } 349 350 // ----------------------------------------------------------------------- 351 352 void TaskStatusBar::MouseButtonDown( const MouseEvent& rMEvt ) 353 { 354 sal_Bool bFieldRect; 355 sal_Bool bBaseClass = sal_False; 356 ImplTaskSBFldItem* pItem = ImplGetFieldItem( rMEvt.GetPosPixel(), bFieldRect ); 357 358 ITaskStatusNotify* pNotify = mpNotify; 359 sal_uInt16 nItemId = 0; 360 361 if ( bFieldRect ) 362 nItemId = TASKSTATUSBAR_CLOCKID; 363 364 if ( pItem ) 365 { 366 pNotify = pItem->maItem.GetNotifyObject(); 367 nItemId = pItem->mnId; 368 } 369 370 if ( pNotify ) 371 bBaseClass = pNotify->MouseButtonDown( nItemId, rMEvt ); 372 373 if ( bBaseClass ) 374 StatusBar::MouseButtonDown( rMEvt ); 375 } 376 377 // ----------------------------------------------------------------------- 378 379 void TaskStatusBar::MouseButtonUp( const MouseEvent& rMEvt ) 380 { 381 sal_Bool bFieldRect; 382 sal_Bool bBaseClass = sal_False; 383 ImplTaskSBFldItem* pItem = ImplGetFieldItem( rMEvt.GetPosPixel(), bFieldRect ); 384 385 ITaskStatusNotify* pNotify = mpNotify; 386 sal_uInt16 nItemId = 0; 387 388 if ( bFieldRect ) 389 nItemId = TASKSTATUSBAR_CLOCKID; 390 391 if ( pItem ) 392 { 393 pNotify = pItem->maItem.GetNotifyObject(); 394 nItemId = pItem->mnId; 395 } 396 397 if ( pNotify ) 398 bBaseClass = pNotify->MouseButtonUp( nItemId, rMEvt ); 399 400 if ( bBaseClass ) 401 StatusBar::MouseButtonUp( rMEvt ); 402 } 403 404 // ----------------------------------------------------------------------- 405 406 void TaskStatusBar::MouseMove( const MouseEvent& rMEvt ) 407 { 408 sal_Bool bFieldRect; 409 sal_Bool bBaseClass = sal_False; 410 ImplTaskSBFldItem* pItem = ImplGetFieldItem( rMEvt.GetPosPixel(), bFieldRect ); 411 412 ITaskStatusNotify* pNotify = mpNotify; 413 sal_uInt16 nItemId = 0; 414 415 if ( bFieldRect ) 416 nItemId = TASKSTATUSBAR_CLOCKID; 417 418 if ( pItem ) 419 { 420 pNotify = pItem->maItem.GetNotifyObject(); 421 nItemId = pItem->mnId; 422 } 423 424 if ( pNotify ) 425 bBaseClass = pNotify->MouseMove( nItemId, rMEvt ); 426 427 if ( bBaseClass ) 428 StatusBar::MouseMove( rMEvt ); 429 } 430 431 // ----------------------------------------------------------------------- 432 433 void TaskStatusBar::Command( const CommandEvent& rCEvt ) 434 { 435 sal_Bool bFieldRect; 436 sal_Bool bBaseClass = sal_False; 437 ImplTaskSBFldItem* pItem = ImplGetFieldItem( rCEvt.GetMousePosPixel(), bFieldRect ); 438 439 ITaskStatusNotify* pNotify = mpNotify; 440 sal_uInt16 nItemId = 0; 441 442 if ( bFieldRect ) 443 nItemId = TASKSTATUSBAR_CLOCKID; 444 445 if ( pItem ) 446 { 447 pNotify = pItem->maItem.GetNotifyObject(); 448 nItemId = pItem->mnId; 449 } 450 451 if ( pNotify ) 452 bBaseClass = pNotify->Command( nItemId, rCEvt ); 453 454 if ( bBaseClass ) 455 StatusBar::Command( rCEvt ); 456 } 457 458 // ----------------------------------------------------------------------- 459 460 void TaskStatusBar::RequestHelp( const HelpEvent& rHEvt ) 461 { 462 sal_Bool bFieldRect; 463 ImplTaskSBFldItem* pItem = ImplGetFieldItem( ScreenToOutputPixel( rHEvt.GetMousePosPixel() ), bFieldRect ); 464 if ( bFieldRect ) 465 { 466 ITaskStatusNotify* pNotify = mpNotify; 467 sal_uInt16 nItemId = 0; 468 469 if ( pItem ) 470 { 471 pNotify = pItem->maItem.GetNotifyObject(); 472 nItemId = pItem->mnId; 473 } 474 475 if ( pNotify ) 476 pNotify->UpdateHelp( nItemId ); 477 478 if ( rHEvt.GetMode() & (HELPMODE_BALLOON | HELPMODE_QUICK) ) 479 { 480 Rectangle aItemRect = GetItemRect( TASKSTATUSBAR_STATUSFIELDID ); 481 Point aPt = OutputToScreenPixel( aItemRect.TopLeft() ); 482 aItemRect.Left() = aPt.X(); 483 aItemRect.Top() = aPt.Y(); 484 aPt = OutputToScreenPixel( aItemRect.BottomRight() ); 485 aItemRect.Right() = aPt.X(); 486 aItemRect.Bottom() = aPt.Y(); 487 if ( pItem ) 488 { 489 if ( rHEvt.GetMode() & HELPMODE_BALLOON ) 490 { 491 XubString aStr = pItem->maItem.GetHelpText(); 492 if ( !aStr.Len() ) 493 aStr = pItem->maItem.GetQuickHelpText(); 494 Help::ShowBalloon( this, aItemRect.Center(), aItemRect, aStr ); 495 } 496 else 497 Help::ShowQuickHelp( this, aItemRect, pItem->maItem.GetQuickHelpText() ); 498 } 499 else 500 { 501 SvtSysLocale aSL; 502 const LocaleDataWrapper& rLDW = aSL.GetLocaleData(); 503 CalendarWrapper aCal( rLDW.getServiceFactory()); 504 aCal.loadDefaultCalendar( rLDW.getLoadedLocale()); 505 XubString aStr = rLDW.getLongDate( Date(), aCal ); 506 if ( rHEvt.GetMode() & HELPMODE_BALLOON ) 507 Help::ShowBalloon( this, aItemRect.Center(), aItemRect, aStr ); 508 else 509 Help::ShowQuickHelp( this, aItemRect, aStr ); 510 } 511 return; 512 } 513 else if ( rHEvt.GetMode() & HELPMODE_EXTENDED ) 514 { 515 if ( pItem ) 516 { 517 rtl::OUString aHelpId( rtl::OStringToOUString( pItem->maItem.GetHelpId(), RTL_TEXTENCODING_UTF8 ) ); 518 if ( aHelpId.getLength() ) 519 { 520 // Wenn eine Hilfe existiert, dann ausloesen 521 Help* pHelp = Application::GetHelp(); 522 if ( pHelp ) 523 pHelp->Start( aHelpId, this ); 524 return; 525 } 526 } 527 } 528 } 529 530 StatusBar::RequestHelp( rHEvt ); 531 } 532 533 // ----------------------------------------------------------------------- 534 535 void TaskStatusBar::UserDraw( const UserDrawEvent& rUDEvt ) 536 { 537 if ( rUDEvt.GetItemId() == TASKSTATUSBAR_STATUSFIELDID ) 538 { 539 OutputDevice* pDev = rUDEvt.GetDevice(); 540 Rectangle aRect = rUDEvt.GetRect(); 541 542 if ( mpFieldItemList ) 543 { 544 ImplTaskSBFldItem* pItem = mpFieldItemList->First(); 545 while ( pItem ) 546 { 547 if ( !mbOutInterval || !(pItem->maItem.GetFlags() & TASKSTATUSFIELDITEM_FLASH) ) 548 { 549 const Image& rImage = pItem->maItem.GetImage(); 550 Size aImgSize = rImage.GetSizePixel(); 551 pDev->DrawImage( Point( aRect.Left()+pItem->mnOffX, 552 aRect.Top()+((aRect.GetHeight()-aImgSize.Width())/2) ), 553 rImage ); 554 } 555 556 pItem = mpFieldItemList->Next(); 557 } 558 } 559 560 if ( mnFieldFlags & TASKSTATUSFIELD_CLOCK ) 561 { 562 long nX = mnItemWidth+TASKSTATUSBAR_CLOCXOFFX; 563 Point aPos = GetItemTextPos( TASKSTATUSBAR_STATUSFIELDID ); 564 aPos.X() = aRect.Left()+nX; 565 pDev->DrawText( aPos, maTimeText ); 566 } 567 } 568 else 569 StatusBar::UserDraw( rUDEvt ); 570 } 571 572 // ----------------------------------------------------------------------- 573 574 void TaskStatusBar::InsertStatusField( long, sal_uInt16, 575 sal_uInt16 nFlags ) 576 { 577 mnFieldFlags = nFlags; 578 ImplUpdateField( sal_False ); 579 } 580 581 // ----------------------------------------------------------------------- 582 583 void TaskStatusBar::SetFieldFlags( sal_uInt16 nFlags ) 584 { 585 if ( mnFieldFlags != nFlags ) 586 { 587 mnFieldFlags = nFlags; 588 ImplUpdateField( sal_False ); 589 } 590 } 591 592 // ----------------------------------------------------------------------- 593 594 void TaskStatusBar::AddStatusFieldItem( sal_uInt16 nItemId, const TaskStatusFieldItem& rItem, 595 sal_uInt16 nPos ) 596 { 597 DBG_ASSERT( nItemId, "TaskStatusBar::AddStatusFieldItem() - Item is 0" ); 598 DBG_ASSERT( !ImplGetFieldItem( nItemId ), "TaskStatusBar::AddStatusFieldItem() - Item-Id already exist" ); 599 600 if ( !mpFieldItemList ) 601 mpFieldItemList = new ImplTaskSBItemList; 602 603 ImplTaskSBFldItem* pItem = new ImplTaskSBFldItem; 604 pItem->maItem = rItem; 605 pItem->mnId = nItemId; 606 pItem->mnOffX = 0; 607 mpFieldItemList->Insert( pItem, (sal_uLong)nPos ); 608 609 ImplUpdateField( sal_True ); 610 } 611 612 // ----------------------------------------------------------------------- 613 614 void TaskStatusBar::ModifyStatusFieldItem( sal_uInt16 nItemId, const TaskStatusFieldItem& rItem ) 615 { 616 ImplTaskSBFldItem* pItem = ImplGetFieldItem( nItemId ); 617 if ( pItem ) 618 { 619 sal_Bool bUpdate = (pItem->maItem.GetImage() != rItem.GetImage()) || 620 (pItem->maItem.GetFlags() != rItem.GetFlags()); 621 pItem->maItem = rItem; 622 if ( bUpdate ) 623 ImplUpdateField( sal_True ); 624 } 625 } 626 627 // ----------------------------------------------------------------------- 628 629 void TaskStatusBar::RemoveStatusFieldItem( sal_uInt16 nItemId ) 630 { 631 ImplTaskSBFldItem* pItem = ImplGetFieldItem( nItemId ); 632 if ( pItem ) 633 { 634 mpFieldItemList->Remove( pItem ); 635 delete pItem; 636 ImplUpdateField( sal_True ); 637 } 638 } 639 640 // ----------------------------------------------------------------------- 641 642 sal_Bool TaskStatusBar::GetStatusFieldItem( sal_uInt16 nItemId, TaskStatusFieldItem& rItem ) const 643 { 644 ImplTaskSBFldItem* pItem = ImplGetFieldItem( nItemId ); 645 if ( pItem ) 646 { 647 rItem = pItem->maItem; 648 return sal_True; 649 } 650 651 return sal_False; 652 } 653 654