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