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_desktop.hxx" 30 31 #include "svtools/controldims.hrc" 32 33 #include "dp_gui.h" 34 #include "dp_gui_extlistbox.hxx" 35 #include "dp_gui_theextmgr.hxx" 36 #include "dp_gui_dialog2.hxx" 37 #include "dp_dependencies.hxx" 38 39 #include "comphelper/processfactory.hxx" 40 #include "com/sun/star/i18n/CollatorOptions.hpp" 41 #include "com/sun/star/deployment/DependencyException.hpp" 42 #include "com/sun/star/deployment/DeploymentException.hpp" 43 #include "cppuhelper/weakref.hxx" 44 45 #define OUSTR(x) ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(x) ) 46 47 #define USER_PACKAGE_MANAGER OUSTR("user") 48 #define SHARED_PACKAGE_MANAGER OUSTR("shared") 49 #define BUNDLED_PACKAGE_MANAGER OUSTR("bundled") 50 51 using namespace ::com::sun::star; 52 53 namespace dp_gui { 54 55 namespace { 56 57 struct FindWeakRef 58 { 59 const uno::Reference<deployment::XPackage> m_extension; 60 61 FindWeakRef( uno::Reference<deployment::XPackage> const & ext): m_extension(ext) {} 62 bool operator () (uno::WeakReference< deployment::XPackage > const & ref); 63 }; 64 65 bool FindWeakRef::operator () (uno::WeakReference< deployment::XPackage > const & ref) 66 { 67 const uno::Reference<deployment::XPackage> ext(ref); 68 if (ext == m_extension) 69 return true; 70 return false; 71 } 72 73 } // end namespace 74 //------------------------------------------------------------------------------ 75 // struct Entry_Impl 76 //------------------------------------------------------------------------------ 77 Entry_Impl::Entry_Impl( const uno::Reference< deployment::XPackage > &xPackage, 78 const PackageState eState, const bool bReadOnly ) : 79 m_bActive( false ), 80 m_bLocked( bReadOnly ), 81 m_bHasOptions( false ), 82 m_bUser( false ), 83 m_bShared( false ), 84 m_bNew( false ), 85 m_bChecked( false ), 86 m_bMissingDeps( false ), 87 m_bHasButtons( false ), 88 m_bMissingLic( false ), 89 m_eState( eState ), 90 m_pPublisher( NULL ), 91 m_xPackage( xPackage ) 92 { 93 try 94 { 95 m_sTitle = xPackage->getDisplayName(); 96 m_sVersion = xPackage->getVersion(); 97 m_sDescription = xPackage->getDescription(); 98 m_sLicenseText = xPackage->getLicenseText(); 99 100 beans::StringPair aInfo( m_xPackage->getPublisherInfo() ); 101 m_sPublisher = aInfo.First; 102 m_sPublisherURL = aInfo.Second; 103 104 // get the icons for the package if there are any 105 uno::Reference< graphic::XGraphic > xGraphic = xPackage->getIcon( false ); 106 if ( xGraphic.is() ) 107 m_aIcon = Image( xGraphic ); 108 109 xGraphic = xPackage->getIcon( true ); 110 if ( xGraphic.is() ) 111 m_aIconHC = Image( xGraphic ); 112 else 113 m_aIconHC = m_aIcon; 114 115 if ( eState == AMBIGUOUS ) 116 m_sErrorText = DialogHelper::getResourceString( RID_STR_ERROR_UNKNOWN_STATUS ); 117 else if ( eState == NOT_REGISTERED ) 118 checkDependencies(); 119 } 120 catch (deployment::ExtensionRemovedException &) {} 121 catch (uno::RuntimeException &) {} 122 } 123 124 //------------------------------------------------------------------------------ 125 Entry_Impl::~Entry_Impl() 126 {} 127 128 //------------------------------------------------------------------------------ 129 StringCompare Entry_Impl::CompareTo( const CollatorWrapper *pCollator, const TEntry_Impl pEntry ) const 130 { 131 StringCompare eCompare = (StringCompare) pCollator->compareString( m_sTitle, pEntry->m_sTitle ); 132 if ( eCompare == COMPARE_EQUAL ) 133 { 134 eCompare = m_sVersion.CompareTo( pEntry->m_sVersion ); 135 if ( eCompare == COMPARE_EQUAL ) 136 { 137 sal_Int32 nCompare = m_xPackage->getRepositoryName().compareTo( pEntry->m_xPackage->getRepositoryName() ); 138 if ( nCompare < 0 ) 139 eCompare = COMPARE_LESS; 140 else if ( nCompare > 0 ) 141 eCompare = COMPARE_GREATER; 142 } 143 } 144 return eCompare; 145 } 146 147 //------------------------------------------------------------------------------ 148 void Entry_Impl::checkDependencies() 149 { 150 try { 151 m_xPackage->checkDependencies( uno::Reference< ucb::XCommandEnvironment >() ); 152 } 153 catch ( deployment::DeploymentException &e ) 154 { 155 deployment::DependencyException depExc; 156 if ( e.Cause >>= depExc ) 157 { 158 rtl::OUString aMissingDep( DialogHelper::getResourceString( RID_STR_ERROR_MISSING_DEPENDENCIES ) ); 159 for ( sal_Int32 i = 0; i < depExc.UnsatisfiedDependencies.getLength(); ++i ) 160 { 161 aMissingDep += OUSTR("\n"); 162 aMissingDep += dp_misc::Dependencies::getErrorText( depExc.UnsatisfiedDependencies[i]); 163 } 164 aMissingDep += OUSTR("\n"); 165 m_sErrorText = aMissingDep; 166 m_bMissingDeps = true; 167 } 168 } 169 } 170 //------------------------------------------------------------------------------ 171 // ExtensionRemovedListener 172 //------------------------------------------------------------------------------ 173 void ExtensionRemovedListener::disposing( lang::EventObject const & rEvt ) 174 throw ( uno::RuntimeException ) 175 { 176 uno::Reference< deployment::XPackage > xPackage( rEvt.Source, uno::UNO_QUERY ); 177 178 if ( xPackage.is() ) 179 { 180 m_pParent->removeEntry( xPackage ); 181 } 182 } 183 184 //------------------------------------------------------------------------------ 185 ExtensionRemovedListener::~ExtensionRemovedListener() 186 { 187 } 188 189 //------------------------------------------------------------------------------ 190 // ExtensionBox_Impl 191 //------------------------------------------------------------------------------ 192 ExtensionBox_Impl::ExtensionBox_Impl( Dialog* pParent, TheExtensionManager *pManager ) : 193 IExtensionListBox( pParent, WB_BORDER | WB_TABSTOP | WB_CHILDDLGCTRL ), 194 m_bHasScrollBar( false ), 195 m_bHasActive( false ), 196 m_bNeedsRecalc( true ), 197 m_bHasNew( false ), 198 m_bInCheckMode( false ), 199 m_bAdjustActive( false ), 200 m_bInDelete( false ), 201 m_nActive( 0 ), 202 m_nTopIndex( 0 ), 203 m_nActiveHeight( 0 ), 204 m_nExtraHeight( 2 ), 205 m_aSharedImage( DialogHelper::getResId( RID_IMG_SHARED ) ), 206 m_aSharedImageHC( DialogHelper::getResId( RID_IMG_SHARED_HC ) ), 207 m_aLockedImage( DialogHelper::getResId( RID_IMG_LOCKED ) ), 208 m_aLockedImageHC( DialogHelper::getResId( RID_IMG_LOCKED_HC ) ), 209 m_aWarningImage( DialogHelper::getResId( RID_IMG_WARNING ) ), 210 m_aWarningImageHC( DialogHelper::getResId( RID_IMG_WARNING_HC ) ), 211 m_aDefaultImage( DialogHelper::getResId( RID_IMG_EXTENSION ) ), 212 m_aDefaultImageHC( DialogHelper::getResId( RID_IMG_EXTENSION_HC ) ), 213 m_pScrollBar( NULL ), 214 m_pManager( pManager ) 215 { 216 SetHelpId( HID_EXTENSION_MANAGER_LISTBOX ); 217 218 m_pScrollBar = new ScrollBar( this, WB_VERT ); 219 m_pScrollBar->SetScrollHdl( LINK( this, ExtensionBox_Impl, ScrollHdl ) ); 220 m_pScrollBar->EnableDrag(); 221 222 SetPaintTransparent( true ); 223 SetPosPixel( Point( RSC_SP_DLG_INNERBORDER_LEFT, RSC_SP_DLG_INNERBORDER_TOP ) ); 224 long nIconHeight = 2*TOP_OFFSET + SMALL_ICON_SIZE; 225 long nTitleHeight = 2*TOP_OFFSET + GetTextHeight(); 226 if ( nIconHeight < nTitleHeight ) 227 m_nStdHeight = nTitleHeight; 228 else 229 m_nStdHeight = nIconHeight; 230 m_nStdHeight += GetTextHeight() + TOP_OFFSET; 231 232 nIconHeight = ICON_HEIGHT + 2*TOP_OFFSET + 1; 233 if ( m_nStdHeight < nIconHeight ) 234 m_nStdHeight = nIconHeight; 235 236 m_nActiveHeight = m_nStdHeight; 237 238 const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings(); 239 if( IsControlBackground() ) 240 SetBackground( GetControlBackground() ); 241 else 242 SetBackground( rStyleSettings.GetFieldColor() ); 243 244 m_xRemoveListener = new ExtensionRemovedListener( this ); 245 246 m_pLocale = new lang::Locale( Application::GetSettings().GetLocale() ); 247 m_pCollator = new CollatorWrapper( ::comphelper::getProcessServiceFactory() ); 248 m_pCollator->loadDefaultCollator( *m_pLocale, i18n::CollatorOptions::CollatorOptions_IGNORE_CASE ); 249 250 Show(); 251 } 252 253 //------------------------------------------------------------------------------ 254 ExtensionBox_Impl::~ExtensionBox_Impl() 255 { 256 if ( ! m_bInDelete ) 257 DeleteRemoved(); 258 259 m_bInDelete = true; 260 261 typedef std::vector< TEntry_Impl >::iterator ITER; 262 263 for ( ITER iIndex = m_vEntries.begin(); iIndex < m_vEntries.end(); ++iIndex ) 264 { 265 if ( (*iIndex)->m_pPublisher ) 266 { 267 delete (*iIndex)->m_pPublisher; 268 (*iIndex)->m_pPublisher = NULL; 269 } 270 (*iIndex)->m_xPackage->removeEventListener( uno::Reference< lang::XEventListener > ( m_xRemoveListener, uno::UNO_QUERY ) ); 271 } 272 273 m_vEntries.clear(); 274 275 delete m_pScrollBar; 276 277 m_xRemoveListener.clear(); 278 279 delete m_pLocale; 280 delete m_pCollator; 281 } 282 283 //------------------------------------------------------------------------------ 284 sal_Int32 ExtensionBox_Impl::getItemCount() const 285 { 286 return static_cast< sal_Int32 >( m_vEntries.size() ); 287 } 288 289 //------------------------------------------------------------------------------ 290 sal_Int32 ExtensionBox_Impl::getSelIndex() const 291 { 292 if ( m_bHasActive ) 293 { 294 OSL_ASSERT( m_nActive >= -1); 295 return static_cast< sal_Int32 >( m_nActive ); 296 } 297 else 298 return static_cast< sal_Int32 >( EXTENSION_LISTBOX_ENTRY_NOTFOUND ); 299 } 300 301 //------------------------------------------------------------------------------ 302 void ExtensionBox_Impl::checkIndex( sal_Int32 nIndex ) const 303 { 304 if ( nIndex < 0 ) 305 throw lang::IllegalArgumentException( OUSTR("The list index starts with 0"),0, 0 ); 306 if ( static_cast< sal_uInt32 >( nIndex ) >= m_vEntries.size()) 307 throw lang::IllegalArgumentException( OUSTR("There is no element at the provided position." 308 "The position exceeds the number of available list entries"),0, 0 ); 309 } 310 311 //------------------------------------------------------------------------------ 312 rtl::OUString ExtensionBox_Impl::getItemName( sal_Int32 nIndex ) const 313 { 314 const ::osl::MutexGuard aGuard( m_entriesMutex ); 315 checkIndex( nIndex ); 316 return m_vEntries[ nIndex ]->m_sTitle; 317 } 318 319 //------------------------------------------------------------------------------ 320 rtl::OUString ExtensionBox_Impl::getItemVersion( sal_Int32 nIndex ) const 321 { 322 const ::osl::MutexGuard aGuard( m_entriesMutex ); 323 checkIndex( nIndex ); 324 return m_vEntries[ nIndex ]->m_sVersion; 325 } 326 327 //------------------------------------------------------------------------------ 328 rtl::OUString ExtensionBox_Impl::getItemDescription( sal_Int32 nIndex ) const 329 { 330 const ::osl::MutexGuard aGuard( m_entriesMutex ); 331 checkIndex( nIndex ); 332 return m_vEntries[ nIndex ]->m_sDescription; 333 } 334 335 //------------------------------------------------------------------------------ 336 rtl::OUString ExtensionBox_Impl::getItemPublisher( sal_Int32 nIndex ) const 337 { 338 const ::osl::MutexGuard aGuard( m_entriesMutex ); 339 checkIndex( nIndex ); 340 return m_vEntries[ nIndex ]->m_sPublisher; 341 } 342 343 //------------------------------------------------------------------------------ 344 rtl::OUString ExtensionBox_Impl::getItemPublisherLink( sal_Int32 nIndex ) const 345 { 346 const ::osl::MutexGuard aGuard( m_entriesMutex ); 347 checkIndex( nIndex ); 348 return m_vEntries[ nIndex ]->m_sPublisherURL; 349 } 350 351 //------------------------------------------------------------------------------ 352 void ExtensionBox_Impl::select( sal_Int32 nIndex ) 353 { 354 const ::osl::MutexGuard aGuard( m_entriesMutex ); 355 checkIndex( nIndex ); 356 selectEntry( nIndex ); 357 } 358 359 //------------------------------------------------------------------------------ 360 void ExtensionBox_Impl::select( const rtl::OUString & sName ) 361 { 362 const ::osl::MutexGuard aGuard( m_entriesMutex ); 363 typedef ::std::vector< TEntry_Impl >::const_iterator It; 364 365 for ( It iIter = m_vEntries.begin(); iIter < m_vEntries.end(); iIter++ ) 366 { 367 if ( sName.equals( (*iIter)->m_sTitle ) ) 368 { 369 long nPos = iIter - m_vEntries.begin(); 370 selectEntry( nPos ); 371 break; 372 } 373 } 374 } 375 376 //------------------------------------------------------------------------------ 377 //------------------------------------------------------------------------------ 378 // Title + description 379 void ExtensionBox_Impl::CalcActiveHeight( const long nPos ) 380 { 381 const ::osl::MutexGuard aGuard( m_entriesMutex ); 382 383 // get title height 384 long aTextHeight; 385 long nIconHeight = 2*TOP_OFFSET + SMALL_ICON_SIZE; 386 long nTitleHeight = 2*TOP_OFFSET + GetTextHeight(); 387 if ( nIconHeight < nTitleHeight ) 388 aTextHeight = nTitleHeight; 389 else 390 aTextHeight = nIconHeight; 391 392 // calc description height 393 Size aSize = GetOutputSizePixel(); 394 if ( m_bHasScrollBar ) 395 aSize.Width() -= m_pScrollBar->GetSizePixel().Width(); 396 397 aSize.Width() -= ICON_OFFSET; 398 aSize.Height() = 10000; 399 400 rtl::OUString aText( m_vEntries[ nPos ]->m_sErrorText ); 401 if ( aText.getLength() ) 402 aText += OUSTR("\n"); 403 aText += m_vEntries[ nPos ]->m_sDescription; 404 405 Rectangle aRect = GetTextRect( Rectangle( Point(), aSize ), aText, 406 TEXT_DRAW_MULTILINE | TEXT_DRAW_WORDBREAK ); 407 aTextHeight += aRect.GetHeight(); 408 409 if ( aTextHeight < m_nStdHeight ) 410 aTextHeight = m_nStdHeight; 411 412 if ( m_vEntries[ nPos ]->m_bHasButtons ) 413 m_nActiveHeight = aTextHeight + m_nExtraHeight; 414 else 415 m_nActiveHeight = aTextHeight + 2; 416 } 417 418 //------------------------------------------------------------------------------ 419 const Size ExtensionBox_Impl::GetMinOutputSizePixel() const 420 { 421 return Size( 200, 80 ); 422 } 423 424 //------------------------------------------------------------------------------ 425 Rectangle ExtensionBox_Impl::GetEntryRect( const long nPos ) const 426 { 427 const ::osl::MutexGuard aGuard( m_entriesMutex ); 428 429 Size aSize( GetOutputSizePixel() ); 430 431 if ( m_bHasScrollBar ) 432 aSize.Width() -= m_pScrollBar->GetSizePixel().Width(); 433 434 if ( m_vEntries[ nPos ]->m_bActive ) 435 aSize.Height() = m_nActiveHeight; 436 else 437 aSize.Height() = m_nStdHeight; 438 439 Point aPos( 0, -m_nTopIndex + nPos * m_nStdHeight ); 440 if ( m_bHasActive && ( nPos < m_nActive ) ) 441 aPos.Y() += m_nActiveHeight - m_nStdHeight; 442 443 return Rectangle( aPos, aSize ); 444 } 445 446 //------------------------------------------------------------------------------ 447 void ExtensionBox_Impl::DeleteRemoved() 448 { 449 const ::osl::MutexGuard aGuard( m_entriesMutex ); 450 451 m_bInDelete = true; 452 453 if ( ! m_vRemovedEntries.empty() ) 454 { 455 typedef std::vector< TEntry_Impl >::iterator ITER; 456 457 for ( ITER iIndex = m_vRemovedEntries.begin(); iIndex < m_vRemovedEntries.end(); ++iIndex ) 458 { 459 if ( (*iIndex)->m_pPublisher ) 460 { 461 delete (*iIndex)->m_pPublisher; 462 (*iIndex)->m_pPublisher = NULL; 463 } 464 } 465 466 m_vRemovedEntries.clear(); 467 } 468 469 m_bInDelete = false; 470 } 471 472 //------------------------------------------------------------------------------ 473 //This function may be called with nPos < 0 474 void ExtensionBox_Impl::selectEntry( const long nPos ) 475 { 476 //ToDo whe should not use the guard at such a big scope here. 477 //Currently it is used to gard m_vEntries and m_nActive. m_nActive will be 478 //modified in this function. 479 //It would be probably best to always use a copy of m_vEntries 480 //and some other state variables from ExtensionBox_Impl for 481 //the whole painting operation. See issue i86993 482 ::osl::ClearableMutexGuard guard(m_entriesMutex); 483 484 if ( m_bInCheckMode ) 485 return; 486 487 if ( m_bHasActive ) 488 { 489 if ( nPos == m_nActive ) 490 return; 491 492 m_bHasActive = false; 493 m_vEntries[ m_nActive ]->m_bActive = false; 494 } 495 496 if ( ( nPos >= 0 ) && ( nPos < (long) m_vEntries.size() ) ) 497 { 498 m_bHasActive = true; 499 m_nActive = nPos; 500 m_vEntries[ nPos ]->m_bActive = true; 501 502 if ( IsReallyVisible() ) 503 { 504 m_bAdjustActive = true; 505 } 506 } 507 508 if ( IsReallyVisible() ) 509 { 510 m_bNeedsRecalc = true; 511 Invalidate(); 512 } 513 514 guard.clear(); 515 } 516 517 // ----------------------------------------------------------------------- 518 void ExtensionBox_Impl::DrawRow( const Rectangle& rRect, const TEntry_Impl pEntry ) 519 { 520 const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings(); 521 522 if ( pEntry->m_bActive ) 523 SetTextColor( rStyleSettings.GetHighlightTextColor() ); 524 else if ( ( pEntry->m_eState != REGISTERED ) && ( pEntry->m_eState != NOT_AVAILABLE ) ) 525 SetTextColor( rStyleSettings.GetDisableColor() ); 526 else if ( IsControlForeground() ) 527 SetTextColor( GetControlForeground() ); 528 else 529 SetTextColor( rStyleSettings.GetFieldTextColor() ); 530 531 if ( pEntry->m_bActive ) 532 { 533 SetLineColor(); 534 SetFillColor( rStyleSettings.GetHighlightColor() ); 535 DrawRect( rRect ); 536 } 537 else 538 { 539 if( IsControlBackground() ) 540 SetBackground( GetControlBackground() ); 541 else 542 SetBackground( rStyleSettings.GetFieldColor() ); 543 544 SetTextFillColor(); 545 Erase( rRect ); 546 } 547 548 // Draw extension icon 549 Point aPos( rRect.TopLeft() ); 550 aPos += Point( TOP_OFFSET, TOP_OFFSET ); 551 Image aImage; 552 if ( ! pEntry->m_aIcon ) 553 aImage = isHCMode() ? m_aDefaultImageHC : m_aDefaultImage; 554 else 555 aImage = isHCMode() ? pEntry->m_aIconHC : pEntry->m_aIcon; 556 Size aImageSize = aImage.GetSizePixel(); 557 if ( ( aImageSize.Width() <= ICON_WIDTH ) && ( aImageSize.Height() <= ICON_HEIGHT ) ) 558 DrawImage( Point( aPos.X()+((ICON_WIDTH-aImageSize.Width())/2), aPos.Y()+((ICON_HEIGHT-aImageSize.Height())/2) ), aImage ); 559 else 560 DrawImage( aPos, Size( ICON_WIDTH, ICON_HEIGHT ), aImage ); 561 562 // Setup fonts 563 Font aStdFont( GetFont() ); 564 Font aBoldFont( aStdFont ); 565 aBoldFont.SetWeight( WEIGHT_BOLD ); 566 SetFont( aBoldFont ); 567 long aTextHeight = GetTextHeight(); 568 569 // Init publisher link here 570 if ( !pEntry->m_pPublisher && pEntry->m_sPublisher.Len() ) 571 { 572 pEntry->m_pPublisher = new svt::FixedHyperlink( this ); 573 pEntry->m_pPublisher->SetBackground(); 574 pEntry->m_pPublisher->SetPaintTransparent( true ); 575 pEntry->m_pPublisher->SetURL( pEntry->m_sPublisherURL ); 576 pEntry->m_pPublisher->SetDescription( pEntry->m_sPublisher ); 577 Size aSize = FixedText::CalcMinimumTextSize( pEntry->m_pPublisher ); 578 pEntry->m_pPublisher->SetSizePixel( aSize ); 579 580 if ( m_aClickHdl.IsSet() ) 581 pEntry->m_pPublisher->SetClickHdl( m_aClickHdl ); 582 } 583 584 // Get max title width 585 long nMaxTitleWidth = rRect.GetWidth() - ICON_OFFSET; 586 nMaxTitleWidth -= ( 2 * SMALL_ICON_SIZE ) + ( 4 * SPACE_BETWEEN ); 587 if ( pEntry->m_pPublisher ) 588 { 589 nMaxTitleWidth -= pEntry->m_pPublisher->GetSizePixel().Width() + (2*SPACE_BETWEEN); 590 } 591 592 long aVersionWidth = GetTextWidth( pEntry->m_sVersion ); 593 long aTitleWidth = GetTextWidth( pEntry->m_sTitle ) + (aTextHeight / 3); 594 595 aPos = rRect.TopLeft() + Point( ICON_OFFSET, TOP_OFFSET ); 596 597 if ( aTitleWidth > nMaxTitleWidth - aVersionWidth ) 598 { 599 aTitleWidth = nMaxTitleWidth - aVersionWidth - (aTextHeight / 3); 600 String aShortTitle = GetEllipsisString( pEntry->m_sTitle, aTitleWidth ); 601 DrawText( aPos, aShortTitle ); 602 aTitleWidth += (aTextHeight / 3); 603 } 604 else 605 DrawText( aPos, pEntry->m_sTitle ); 606 607 SetFont( aStdFont ); 608 DrawText( Point( aPos.X() + aTitleWidth, aPos.Y() ), pEntry->m_sVersion ); 609 610 long nIconHeight = TOP_OFFSET + SMALL_ICON_SIZE; 611 long nTitleHeight = TOP_OFFSET + GetTextHeight(); 612 if ( nIconHeight < nTitleHeight ) 613 aTextHeight = nTitleHeight; 614 else 615 aTextHeight = nIconHeight; 616 617 // draw description 618 String sDescription; 619 if ( pEntry->m_sErrorText.Len() ) 620 { 621 if ( pEntry->m_bActive ) 622 sDescription = pEntry->m_sErrorText + OUSTR("\n") + pEntry->m_sDescription; 623 else 624 sDescription = pEntry->m_sErrorText; 625 } 626 else 627 sDescription = pEntry->m_sDescription; 628 629 aPos.Y() += aTextHeight; 630 if ( pEntry->m_bActive ) 631 { 632 long nExtraHeight = 0; 633 634 if ( pEntry->m_bHasButtons ) 635 nExtraHeight = m_nExtraHeight; 636 637 DrawText( Rectangle( aPos.X(), aPos.Y(), rRect.Right(), rRect.Bottom() - nExtraHeight ), 638 sDescription, TEXT_DRAW_MULTILINE | TEXT_DRAW_WORDBREAK ); 639 } 640 else 641 { 642 const long nWidth = GetTextWidth( sDescription ); 643 if ( nWidth > rRect.GetWidth() - aPos.X() ) 644 sDescription = GetEllipsisString( sDescription, rRect.GetWidth() - aPos.X() ); 645 DrawText( aPos, sDescription ); 646 } 647 648 // Draw publisher link 649 if ( pEntry->m_pPublisher ) 650 { 651 pEntry->m_pPublisher->Show(); 652 aPos = rRect.TopLeft() + Point( ICON_OFFSET + nMaxTitleWidth + (2*SPACE_BETWEEN), TOP_OFFSET ); 653 pEntry->m_pPublisher->SetPosPixel( aPos ); 654 } 655 656 // Draw status icons 657 if ( !pEntry->m_bUser ) 658 { 659 aPos = rRect.TopRight() + Point( -(RIGHT_ICON_OFFSET + SMALL_ICON_SIZE), TOP_OFFSET ); 660 if ( pEntry->m_bLocked ) 661 DrawImage( aPos, Size( SMALL_ICON_SIZE, SMALL_ICON_SIZE ), isHCMode() ? m_aLockedImageHC : m_aLockedImage ); 662 else 663 DrawImage( aPos, Size( SMALL_ICON_SIZE, SMALL_ICON_SIZE ), isHCMode() ? m_aSharedImageHC : m_aSharedImage ); 664 } 665 if ( ( pEntry->m_eState == AMBIGUOUS ) || pEntry->m_bMissingDeps || pEntry->m_bMissingLic ) 666 { 667 aPos = rRect.TopRight() + Point( -(RIGHT_ICON_OFFSET + SPACE_BETWEEN + 2*SMALL_ICON_SIZE), TOP_OFFSET ); 668 DrawImage( aPos, Size( SMALL_ICON_SIZE, SMALL_ICON_SIZE ), isHCMode() ? m_aWarningImageHC : m_aWarningImage ); 669 } 670 671 SetLineColor( Color( COL_LIGHTGRAY ) ); 672 DrawLine( rRect.BottomLeft(), rRect.BottomRight() ); 673 } 674 675 // ----------------------------------------------------------------------- 676 void ExtensionBox_Impl::RecalcAll() 677 { 678 if ( m_bHasActive ) 679 CalcActiveHeight( m_nActive ); 680 681 SetupScrollBar(); 682 683 if ( m_bHasActive ) 684 { 685 Rectangle aEntryRect = GetEntryRect( m_nActive ); 686 687 if ( m_bAdjustActive ) 688 { 689 m_bAdjustActive = false; 690 691 // If the top of the selected entry isn't visible, make it visible 692 if ( aEntryRect.Top() < 0 ) 693 { 694 m_nTopIndex += aEntryRect.Top(); 695 aEntryRect.Move( 0, -aEntryRect.Top() ); 696 } 697 698 // If the bottom of the selected entry isn't visible, make it visible even if now the top 699 // isn't visible any longer ( the buttons are more important ) 700 Size aOutputSize = GetOutputSizePixel(); 701 if ( aEntryRect.Bottom() > aOutputSize.Height() ) 702 { 703 m_nTopIndex += ( aEntryRect.Bottom() - aOutputSize.Height() ); 704 aEntryRect.Move( 0, -( aEntryRect.Bottom() - aOutputSize.Height() ) ); 705 } 706 707 // If there is unused space below the last entry but all entries don't fit into the box, 708 // move the content down to use the whole space 709 const long nTotalHeight = GetTotalHeight(); 710 if ( m_bHasScrollBar && ( aOutputSize.Height() + m_nTopIndex > nTotalHeight ) ) 711 { 712 long nOffset = m_nTopIndex; 713 m_nTopIndex = nTotalHeight - aOutputSize.Height(); 714 nOffset -= m_nTopIndex; 715 aEntryRect.Move( 0, nOffset ); 716 } 717 718 if ( m_bHasScrollBar ) 719 m_pScrollBar->SetThumbPos( m_nTopIndex ); 720 } 721 } 722 723 m_bNeedsRecalc = false; 724 } 725 726 // ----------------------------------------------------------------------- 727 bool ExtensionBox_Impl::HandleTabKey( bool ) 728 { 729 return false; 730 } 731 732 // ----------------------------------------------------------------------- 733 bool ExtensionBox_Impl::HandleCursorKey( sal_uInt16 nKeyCode ) 734 { 735 if ( m_vEntries.empty() ) 736 return true; 737 738 long nSelect = 0; 739 740 if ( m_bHasActive ) 741 { 742 long nPageSize = GetOutputSizePixel().Height() / m_nStdHeight; 743 if ( nPageSize < 2 ) 744 nPageSize = 2; 745 746 if ( ( nKeyCode == KEY_DOWN ) || ( nKeyCode == KEY_RIGHT ) ) 747 nSelect = m_nActive + 1; 748 else if ( ( nKeyCode == KEY_UP ) || ( nKeyCode == KEY_LEFT ) ) 749 nSelect = m_nActive - 1; 750 else if ( nKeyCode == KEY_HOME ) 751 nSelect = 0; 752 else if ( nKeyCode == KEY_END ) 753 nSelect = m_vEntries.size() - 1; 754 else if ( nKeyCode == KEY_PAGEUP ) 755 nSelect = m_nActive - nPageSize + 1; 756 else if ( nKeyCode == KEY_PAGEDOWN ) 757 nSelect = m_nActive + nPageSize - 1; 758 } 759 else // when there is no selected entry, we will select the first or the last. 760 { 761 if ( ( nKeyCode == KEY_DOWN ) || ( nKeyCode == KEY_PAGEDOWN ) || ( nKeyCode == KEY_HOME ) ) 762 nSelect = 0; 763 else if ( ( nKeyCode == KEY_UP ) || ( nKeyCode == KEY_PAGEUP ) || ( nKeyCode == KEY_END ) ) 764 nSelect = m_vEntries.size() - 1; 765 } 766 767 if ( nSelect < 0 ) 768 nSelect = 0; 769 if ( nSelect >= (long) m_vEntries.size() ) 770 nSelect = m_vEntries.size() - 1; 771 772 selectEntry( nSelect ); 773 774 return true; 775 } 776 777 // ----------------------------------------------------------------------- 778 void ExtensionBox_Impl::Paint( const Rectangle &/*rPaintRect*/ ) 779 { 780 if ( !m_bInDelete ) 781 DeleteRemoved(); 782 783 if ( m_bNeedsRecalc ) 784 RecalcAll(); 785 786 Point aStart( 0, -m_nTopIndex ); 787 Size aSize( GetOutputSizePixel() ); 788 789 if ( m_bHasScrollBar ) 790 aSize.Width() -= m_pScrollBar->GetSizePixel().Width(); 791 792 const ::osl::MutexGuard aGuard( m_entriesMutex ); 793 794 typedef std::vector< TEntry_Impl >::iterator ITER; 795 for ( ITER iIndex = m_vEntries.begin(); iIndex < m_vEntries.end(); ++iIndex ) 796 { 797 aSize.Height() = (*iIndex)->m_bActive ? m_nActiveHeight : m_nStdHeight; 798 Rectangle aEntryRect( aStart, aSize ); 799 DrawRow( aEntryRect, *iIndex ); 800 aStart.Y() += aSize.Height(); 801 } 802 } 803 804 // ----------------------------------------------------------------------- 805 long ExtensionBox_Impl::GetTotalHeight() const 806 { 807 long nHeight = m_vEntries.size() * m_nStdHeight; 808 809 if ( m_bHasActive ) 810 { 811 nHeight += m_nActiveHeight - m_nStdHeight; 812 } 813 814 return nHeight; 815 } 816 817 // ----------------------------------------------------------------------- 818 void ExtensionBox_Impl::SetupScrollBar() 819 { 820 const Size aSize = GetOutputSizePixel(); 821 const long nScrBarSize = GetSettings().GetStyleSettings().GetScrollBarSize(); 822 const long nTotalHeight = GetTotalHeight(); 823 const bool bNeedsScrollBar = ( nTotalHeight > aSize.Height() ); 824 825 if ( bNeedsScrollBar ) 826 { 827 if ( m_nTopIndex + aSize.Height() > nTotalHeight ) 828 m_nTopIndex = nTotalHeight - aSize.Height(); 829 830 m_pScrollBar->SetPosSizePixel( Point( aSize.Width() - nScrBarSize, 0 ), 831 Size( nScrBarSize, aSize.Height() ) ); 832 m_pScrollBar->SetRangeMax( nTotalHeight ); 833 m_pScrollBar->SetVisibleSize( aSize.Height() ); 834 m_pScrollBar->SetPageSize( ( aSize.Height() * 4 ) / 5 ); 835 m_pScrollBar->SetLineSize( m_nStdHeight ); 836 m_pScrollBar->SetThumbPos( m_nTopIndex ); 837 838 if ( !m_bHasScrollBar ) 839 m_pScrollBar->Show(); 840 } 841 else if ( m_bHasScrollBar ) 842 { 843 m_pScrollBar->Hide(); 844 m_nTopIndex = 0; 845 } 846 847 m_bHasScrollBar = bNeedsScrollBar; 848 } 849 850 // ----------------------------------------------------------------------- 851 void ExtensionBox_Impl::Resize() 852 { 853 RecalcAll(); 854 } 855 856 //------------------------------------------------------------------------------ 857 long ExtensionBox_Impl::PointToPos( const Point& rPos ) 858 { 859 long nPos = ( rPos.Y() + m_nTopIndex ) / m_nStdHeight; 860 861 if ( m_bHasActive && ( nPos > m_nActive ) ) 862 { 863 if ( rPos.Y() + m_nTopIndex <= m_nActive*m_nStdHeight + m_nActiveHeight ) 864 nPos = m_nActive; 865 else 866 nPos = ( rPos.Y() + m_nTopIndex - (m_nActiveHeight - m_nStdHeight) ) / m_nStdHeight; 867 } 868 869 return nPos; 870 } 871 872 //------------------------------------------------------------------------------ 873 void ExtensionBox_Impl::MouseButtonDown( const MouseEvent& rMEvt ) 874 { 875 long nPos = PointToPos( rMEvt.GetPosPixel() ); 876 877 if ( rMEvt.IsLeft() ) 878 { 879 if ( rMEvt.IsMod1() && m_bHasActive ) 880 selectEntry( m_vEntries.size() ); // Selecting an not existing entry will deselect the current one 881 else 882 selectEntry( nPos ); 883 } 884 } 885 886 //------------------------------------------------------------------------------ 887 long ExtensionBox_Impl::Notify( NotifyEvent& rNEvt ) 888 { 889 if ( !m_bInDelete ) 890 DeleteRemoved(); 891 892 bool bHandled = false; 893 894 if ( rNEvt.GetType() == EVENT_KEYINPUT ) 895 { 896 const KeyEvent* pKEvt = rNEvt.GetKeyEvent(); 897 KeyCode aKeyCode = pKEvt->GetKeyCode(); 898 sal_uInt16 nKeyCode = aKeyCode.GetCode(); 899 900 if ( nKeyCode == KEY_TAB ) 901 bHandled = HandleTabKey( aKeyCode.IsShift() ); 902 else if ( aKeyCode.GetGroup() == KEYGROUP_CURSOR ) 903 bHandled = HandleCursorKey( nKeyCode ); 904 } 905 906 if ( rNEvt.GetType() == EVENT_COMMAND ) 907 { 908 if ( m_bHasScrollBar && 909 ( rNEvt.GetCommandEvent()->GetCommand() == COMMAND_WHEEL ) ) 910 { 911 const CommandWheelData* pData = rNEvt.GetCommandEvent()->GetWheelData(); 912 if ( pData->GetMode() == COMMAND_WHEEL_SCROLL ) 913 { 914 long nThumbPos = m_pScrollBar->GetThumbPos(); 915 if ( pData->GetDelta() < 0 ) 916 m_pScrollBar->DoScroll( nThumbPos + m_nStdHeight ); 917 else 918 m_pScrollBar->DoScroll( nThumbPos - m_nStdHeight ); 919 bHandled = true; 920 } 921 } 922 } 923 924 if ( !bHandled ) 925 return Control::Notify( rNEvt ); 926 else 927 return true; 928 } 929 930 //------------------------------------------------------------------------------ 931 bool ExtensionBox_Impl::FindEntryPos( const TEntry_Impl pEntry, const long nStart, 932 const long nEnd, long &nPos ) 933 { 934 nPos = nStart; 935 if ( nStart > nEnd ) 936 return false; 937 938 StringCompare eCompare; 939 940 if ( nStart == nEnd ) 941 { 942 eCompare = pEntry->CompareTo( m_pCollator, m_vEntries[ nStart ] ); 943 if ( eCompare == COMPARE_LESS ) 944 return false; 945 else if ( eCompare == COMPARE_EQUAL ) 946 { 947 //Workaround. See i86963. 948 if (pEntry->m_xPackage != m_vEntries[nStart]->m_xPackage) 949 return false; 950 951 if ( m_bInCheckMode ) 952 m_vEntries[ nStart ]->m_bChecked = true; 953 return true; 954 } 955 else 956 { 957 nPos = nStart + 1; 958 return false; 959 } 960 } 961 962 const long nMid = nStart + ( ( nEnd - nStart ) / 2 ); 963 eCompare = pEntry->CompareTo( m_pCollator, m_vEntries[ nMid ] ); 964 965 if ( eCompare == COMPARE_LESS ) 966 return FindEntryPos( pEntry, nStart, nMid-1, nPos ); 967 else if ( eCompare == COMPARE_GREATER ) 968 return FindEntryPos( pEntry, nMid+1, nEnd, nPos ); 969 else 970 { 971 //Workaround.See i86963. 972 if (pEntry->m_xPackage != m_vEntries[nMid]->m_xPackage) 973 return false; 974 975 if ( m_bInCheckMode ) 976 m_vEntries[ nMid ]->m_bChecked = true; 977 nPos = nMid; 978 return true; 979 } 980 } 981 982 void ExtensionBox_Impl::cleanVecListenerAdded() 983 { 984 typedef ::std::vector<uno::WeakReference<deployment::XPackage> >::iterator IT; 985 IT i = m_vListenerAdded.begin(); 986 while( i != m_vListenerAdded.end()) 987 { 988 const uno::Reference<deployment::XPackage> hardRef(*i); 989 if (!hardRef.is()) 990 i = m_vListenerAdded.erase(i); 991 else 992 ++i; 993 } 994 } 995 996 void ExtensionBox_Impl::addEventListenerOnce( 997 uno::Reference<deployment::XPackage > const & extension) 998 { 999 //make sure to only add the listener once 1000 cleanVecListenerAdded(); 1001 if ( ::std::find_if(m_vListenerAdded.begin(), m_vListenerAdded.end(), 1002 FindWeakRef(extension)) 1003 == m_vListenerAdded.end()) 1004 { 1005 extension->addEventListener( uno::Reference< lang::XEventListener > ( 1006 m_xRemoveListener, uno::UNO_QUERY ) ); 1007 m_vListenerAdded.push_back(extension); 1008 } 1009 } 1010 1011 //------------------------------------------------------------------------------ 1012 long ExtensionBox_Impl::addEntry( const uno::Reference< deployment::XPackage > &xPackage, 1013 bool bLicenseMissing ) 1014 { 1015 long nPos = 0; 1016 PackageState eState = m_pManager->getPackageState( xPackage ); 1017 bool bLocked = m_pManager->isReadOnly( xPackage ); 1018 1019 TEntry_Impl pEntry( new Entry_Impl( xPackage, eState, bLocked ) ); 1020 1021 // Don't add empty entries 1022 if ( ! pEntry->m_sTitle.Len() ) 1023 return 0; 1024 1025 ::osl::ClearableMutexGuard guard(m_entriesMutex); 1026 if ( m_vEntries.empty() ) 1027 { 1028 addEventListenerOnce(xPackage); 1029 m_vEntries.push_back( pEntry ); 1030 } 1031 else 1032 { 1033 if ( !FindEntryPos( pEntry, 0, m_vEntries.size()-1, nPos ) ) 1034 { 1035 addEventListenerOnce(xPackage); 1036 m_vEntries.insert( m_vEntries.begin()+nPos, pEntry ); 1037 } 1038 else if ( !m_bInCheckMode ) 1039 { 1040 OSL_ENSURE( 0, "ExtensionBox_Impl::addEntry(): Will not add duplicate entries" ); 1041 } 1042 } 1043 1044 pEntry->m_bHasOptions = m_pManager->supportsOptions( xPackage ); 1045 pEntry->m_bUser = xPackage->getRepositoryName().equals( USER_PACKAGE_MANAGER ); 1046 pEntry->m_bShared = xPackage->getRepositoryName().equals( SHARED_PACKAGE_MANAGER ); 1047 pEntry->m_bNew = m_bInCheckMode; 1048 pEntry->m_bMissingLic = bLicenseMissing; 1049 1050 if ( bLicenseMissing ) 1051 pEntry->m_sErrorText = DialogHelper::getResourceString( RID_STR_ERROR_MISSING_LICENSE ); 1052 1053 //access to m_nActive must be guarded 1054 if ( !m_bInCheckMode && m_bHasActive && ( m_nActive >= nPos ) ) 1055 m_nActive += 1; 1056 1057 guard.clear(); 1058 1059 if ( IsReallyVisible() ) 1060 Invalidate(); 1061 1062 m_bNeedsRecalc = true; 1063 1064 return nPos; 1065 } 1066 1067 //------------------------------------------------------------------------------ 1068 void ExtensionBox_Impl::updateEntry( const uno::Reference< deployment::XPackage > &xPackage ) 1069 { 1070 typedef std::vector< TEntry_Impl >::iterator ITER; 1071 for ( ITER iIndex = m_vEntries.begin(); iIndex < m_vEntries.end(); ++iIndex ) 1072 { 1073 if ( (*iIndex)->m_xPackage == xPackage ) 1074 { 1075 PackageState eState = m_pManager->getPackageState( xPackage ); 1076 (*iIndex)->m_bHasOptions = m_pManager->supportsOptions( xPackage ); 1077 (*iIndex)->m_eState = eState; 1078 (*iIndex)->m_sTitle = xPackage->getDisplayName(); 1079 (*iIndex)->m_sVersion = xPackage->getVersion(); 1080 (*iIndex)->m_sDescription = xPackage->getDescription(); 1081 1082 if ( eState == REGISTERED ) 1083 (*iIndex)->m_bMissingLic = false; 1084 1085 if ( eState == AMBIGUOUS ) 1086 (*iIndex)->m_sErrorText = DialogHelper::getResourceString( RID_STR_ERROR_UNKNOWN_STATUS ); 1087 else if ( ! (*iIndex)->m_bMissingLic ) 1088 (*iIndex)->m_sErrorText = String(); 1089 1090 if ( IsReallyVisible() ) 1091 Invalidate(); 1092 break; 1093 } 1094 } 1095 } 1096 1097 //------------------------------------------------------------------------------ 1098 //This function is also called as a result of removing an extension. 1099 //see PackageManagerImpl::removePackage 1100 //The gui is a registered as listener on the package. Removing it will cause the 1101 //listeners to be notified an then this function is called. At this moment xPackage 1102 //is in the disposing state and all calls on it may result in a DisposedException. 1103 void ExtensionBox_Impl::removeEntry( const uno::Reference< deployment::XPackage > &xPackage ) 1104 { 1105 if ( ! m_bInDelete ) 1106 { 1107 ::osl::ClearableMutexGuard aGuard( m_entriesMutex ); 1108 1109 typedef std::vector< TEntry_Impl >::iterator ITER; 1110 1111 for ( ITER iIndex = m_vEntries.begin(); iIndex < m_vEntries.end(); ++iIndex ) 1112 { 1113 if ( (*iIndex)->m_xPackage == xPackage ) 1114 { 1115 long nPos = iIndex - m_vEntries.begin(); 1116 1117 // Entries mustn't removed here, because they contain a hyperlink control 1118 // which can only be deleted when the thread has the solar mutex. Therefor 1119 // the entry will be moved into the m_vRemovedEntries list which will be 1120 // cleared on the next paint event 1121 m_vRemovedEntries.push_back( *iIndex ); 1122 (*iIndex)->m_xPackage->removeEventListener( 1123 uno::Reference<lang::XEventListener>(m_xRemoveListener, uno::UNO_QUERY)); 1124 m_vEntries.erase( iIndex ); 1125 1126 m_bNeedsRecalc = true; 1127 1128 if ( IsReallyVisible() ) 1129 Invalidate(); 1130 1131 if ( m_bHasActive ) 1132 { 1133 if ( nPos < m_nActive ) 1134 m_nActive -= 1; 1135 else if ( ( nPos == m_nActive ) && 1136 ( nPos == (long) m_vEntries.size() ) ) 1137 m_nActive -= 1; 1138 1139 m_bHasActive = false; 1140 //clear before calling out of this method 1141 aGuard.clear(); 1142 selectEntry( m_nActive ); 1143 } 1144 break; 1145 } 1146 } 1147 } 1148 } 1149 1150 //------------------------------------------------------------------------------ 1151 void ExtensionBox_Impl::RemoveUnlocked() 1152 { 1153 bool bAllRemoved = false; 1154 1155 while ( ! bAllRemoved ) 1156 { 1157 bAllRemoved = true; 1158 1159 ::osl::ClearableMutexGuard aGuard( m_entriesMutex ); 1160 1161 typedef std::vector< TEntry_Impl >::iterator ITER; 1162 1163 for ( ITER iIndex = m_vEntries.begin(); iIndex < m_vEntries.end(); ++iIndex ) 1164 { 1165 if ( !(*iIndex)->m_bLocked ) 1166 { 1167 bAllRemoved = false; 1168 uno::Reference< deployment::XPackage> xPackage = (*iIndex)->m_xPackage; 1169 aGuard.clear(); 1170 removeEntry( xPackage ); 1171 break; 1172 } 1173 } 1174 } 1175 } 1176 1177 //------------------------------------------------------------------------------ 1178 void ExtensionBox_Impl::prepareChecking() 1179 { 1180 m_bInCheckMode = true; 1181 typedef std::vector< TEntry_Impl >::iterator ITER; 1182 for ( ITER iIndex = m_vEntries.begin(); iIndex < m_vEntries.end(); ++iIndex ) 1183 { 1184 (*iIndex)->m_bChecked = false; 1185 (*iIndex)->m_bNew = false; 1186 } 1187 } 1188 1189 //------------------------------------------------------------------------------ 1190 void ExtensionBox_Impl::checkEntries() 1191 { 1192 long nNewPos = -1; 1193 long nPos = 0; 1194 bool bNeedsUpdate = false; 1195 1196 ::osl::ClearableMutexGuard guard(m_entriesMutex); 1197 typedef std::vector< TEntry_Impl >::iterator ITER; 1198 ITER iIndex = m_vEntries.begin(); 1199 while ( iIndex < m_vEntries.end() ) 1200 { 1201 if ( (*iIndex)->m_bChecked == false ) 1202 { 1203 (*iIndex)->m_bChecked = true; 1204 bNeedsUpdate = true; 1205 nPos = iIndex-m_vEntries.begin(); 1206 if ( (*iIndex)->m_bNew ) 1207 { // add entry to list and correct active pos 1208 if ( nNewPos == - 1) 1209 nNewPos = nPos; 1210 if ( nPos <= m_nActive ) 1211 m_nActive += 1; 1212 iIndex++; 1213 } 1214 else 1215 { // remove entry from list 1216 if ( nPos < m_nActive ) 1217 m_nActive -= 1; 1218 else if ( ( nPos == m_nActive ) && ( nPos == (long) m_vEntries.size() - 1 ) ) 1219 m_nActive -= 1; 1220 m_vRemovedEntries.push_back( *iIndex ); 1221 m_vEntries.erase( iIndex ); 1222 iIndex = m_vEntries.begin() + nPos; 1223 } 1224 } 1225 else 1226 iIndex++; 1227 } 1228 guard.clear(); 1229 1230 m_bInCheckMode = false; 1231 1232 if ( nNewPos != - 1) 1233 selectEntry( nNewPos ); 1234 1235 if ( bNeedsUpdate ) 1236 { 1237 m_bNeedsRecalc = true; 1238 if ( IsReallyVisible() ) 1239 Invalidate(); 1240 } 1241 } 1242 //------------------------------------------------------------------------------ 1243 bool ExtensionBox_Impl::isHCMode() 1244 { 1245 return (bool)GetSettings().GetStyleSettings().GetHighContrastMode(); 1246 } 1247 1248 //------------------------------------------------------------------------------ 1249 void ExtensionBox_Impl::SetScrollHdl( const Link& rLink ) 1250 { 1251 if ( m_pScrollBar ) 1252 m_pScrollBar->SetScrollHdl( rLink ); 1253 } 1254 1255 // ----------------------------------------------------------------------- 1256 void ExtensionBox_Impl::DoScroll( long nDelta ) 1257 { 1258 m_nTopIndex += nDelta; 1259 Point aNewSBPt( m_pScrollBar->GetPosPixel() ); 1260 1261 Rectangle aScrRect( Point(), GetOutputSizePixel() ); 1262 aScrRect.Right() -= m_pScrollBar->GetSizePixel().Width(); 1263 Scroll( 0, -nDelta, aScrRect ); 1264 1265 m_pScrollBar->SetPosPixel( aNewSBPt ); 1266 } 1267 1268 // ----------------------------------------------------------------------- 1269 IMPL_LINK( ExtensionBox_Impl, ScrollHdl, ScrollBar*, pScrBar ) 1270 { 1271 DoScroll( pScrBar->GetDelta() ); 1272 1273 return 1; 1274 } 1275 1276 } //namespace dp_gui 1277