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