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_vcl.hxx" 30 31 #include <tools/debug.hxx> 32 33 #include <vcl/svapp.hxx> 34 #include <vcl/settings.hxx> 35 #include <vcl/event.hxx> 36 #include <vcl/scrbar.hxx> 37 #include <vcl/help.hxx> 38 #include <vcl/lstbox.h> 39 #include <vcl/unohelp.hxx> 40 #include <vcl/i18nhelp.hxx> 41 42 #include <ilstbox.hxx> 43 #include <controldata.hxx> 44 #include <svdata.hxx> 45 46 #include <com/sun/star/i18n/XCollator.hpp> 47 #include <com/sun/star/accessibility/XAccessible.hpp> 48 #include <com/sun/star/accessibility/AccessibleRole.hpp> 49 50 #define MULTILINE_ENTRY_DRAW_FLAGS ( TEXT_DRAW_WORDBREAK | TEXT_DRAW_MULTILINE | TEXT_DRAW_VCENTER ) 51 52 using namespace ::com::sun::star; 53 54 // ======================================================================= 55 56 void ImplInitFieldSettings( Window* pWin, sal_Bool bFont, sal_Bool bForeground, sal_Bool bBackground ) 57 { 58 const StyleSettings& rStyleSettings = pWin->GetSettings().GetStyleSettings(); 59 60 if ( bFont ) 61 { 62 Font aFont = rStyleSettings.GetFieldFont(); 63 if ( pWin->IsControlFont() ) 64 aFont.Merge( pWin->GetControlFont() ); 65 pWin->SetZoomedPointFont( aFont ); 66 } 67 68 if ( bFont || bForeground ) 69 { 70 Color aTextColor = rStyleSettings.GetFieldTextColor(); 71 if ( pWin->IsControlForeground() ) 72 aTextColor = pWin->GetControlForeground(); 73 pWin->SetTextColor( aTextColor ); 74 } 75 76 if ( bBackground ) 77 { 78 if( pWin->IsControlBackground() ) 79 pWin->SetBackground( pWin->GetControlBackground() ); 80 else 81 pWin->SetBackground( rStyleSettings.GetFieldColor() ); 82 } 83 } 84 85 // ----------------------------------------------------------------------- 86 87 void ImplInitDropDownButton( PushButton* pButton ) 88 { 89 if ( pButton->GetSettings().GetStyleSettings().GetOptions() & STYLE_OPTION_SPINUPDOWN ) 90 pButton->SetSymbol( SYMBOL_SPIN_UPDOWN ); 91 else 92 pButton->SetSymbol( SYMBOL_SPIN_DOWN ); 93 94 if ( pButton->IsNativeControlSupported(CTRL_LISTBOX, PART_ENTIRE_CONTROL) 95 && ! pButton->IsNativeControlSupported(CTRL_LISTBOX, PART_BUTTON_DOWN) ) 96 pButton->SetBackground(); 97 } 98 99 // ======================================================================= 100 101 ImplEntryList::ImplEntryList( Window* pWindow ) 102 { 103 mpWindow = pWindow; 104 mnLastSelected = LISTBOX_ENTRY_NOTFOUND; 105 mnSelectionAnchor = LISTBOX_ENTRY_NOTFOUND; 106 mnImages = 0; 107 mbCallSelectionChangedHdl = sal_True; 108 109 mnMRUCount = 0; 110 mnMaxMRUCount = 0; 111 } 112 113 // ----------------------------------------------------------------------- 114 115 ImplEntryList::~ImplEntryList() 116 { 117 Clear(); 118 } 119 120 // ----------------------------------------------------------------------- 121 122 void ImplEntryList::Clear() 123 { 124 mnImages = 0; 125 for ( sal_uInt16 n = GetEntryCount(); n; ) 126 { 127 ImplEntryType* pImplEntry = GetEntry( --n ); 128 delete pImplEntry; 129 } 130 List::Clear(); 131 } 132 133 // ----------------------------------------------------------------------- 134 135 void ImplEntryList::SelectEntry( sal_uInt16 nPos, sal_Bool bSelect ) 136 { 137 ImplEntryType* pImplEntry = GetEntry( nPos ); 138 if ( pImplEntry && 139 ( pImplEntry->mbIsSelected != bSelect ) && 140 ( (pImplEntry->mnFlags & LISTBOX_ENTRY_FLAG_DISABLE_SELECTION) == 0 ) ) 141 { 142 pImplEntry->mbIsSelected = bSelect; 143 if ( mbCallSelectionChangedHdl ) 144 maSelectionChangedHdl.Call( (void*)sal_IntPtr(nPos) ); 145 } 146 } 147 148 // ----------------------------------------------------------------------- 149 150 uno::Reference< i18n::XCollator > ImplGetCollator (lang::Locale &rLocale) 151 { 152 static uno::Reference< i18n::XCollator > xCollator; 153 if ( !xCollator.is() ) 154 xCollator = vcl::unohelper::CreateCollator(); 155 if( xCollator.is() ) 156 xCollator->loadDefaultCollator (rLocale, 0); 157 158 return xCollator; 159 } 160 161 sal_uInt16 ImplEntryList::InsertEntry( sal_uInt16 nPos, ImplEntryType* pNewEntry, sal_Bool bSort ) 162 { 163 if ( !!pNewEntry->maImage ) 164 mnImages++; 165 166 if ( !bSort || !Count() ) 167 { 168 Insert( pNewEntry, nPos ); 169 } 170 else 171 { 172 lang::Locale aLocale = Application::GetSettings().GetLocale(); 173 uno::Reference< i18n::XCollator > xCollator = ImplGetCollator(aLocale); 174 175 const XubString& rStr = pNewEntry->maStr; 176 sal_uLong nLow, nHigh, nMid; 177 178 nHigh = Count(); 179 180 ImplEntryType* pTemp = GetEntry( (sal_uInt16)(nHigh-1) ); 181 182 try 183 { 184 // XXX even though XCollator::compareString returns a sal_Int32 the only 185 // defined values are {-1, 0, 1} which is compatible with StringCompare 186 StringCompare eComp = xCollator.is() ? 187 (StringCompare)xCollator->compareString (rStr, pTemp->maStr) 188 : COMPARE_EQUAL; 189 190 // Schnelles Einfuegen bei sortierten Daten 191 if ( eComp != COMPARE_LESS ) 192 { 193 Insert( pNewEntry, LIST_APPEND ); 194 } 195 else 196 { 197 nLow = mnMRUCount; 198 pTemp = (ImplEntryType*)GetEntry( (sal_uInt16)nLow ); 199 200 eComp = (StringCompare)xCollator->compareString (rStr, pTemp->maStr); 201 if ( eComp != COMPARE_GREATER ) 202 { 203 Insert( pNewEntry, (sal_uLong)0 ); 204 } 205 else 206 { 207 // Binaeres Suchen 208 nHigh--; 209 do 210 { 211 nMid = (nLow + nHigh) / 2; 212 pTemp = (ImplEntryType*)GetObject( nMid ); 213 214 eComp = (StringCompare)xCollator->compareString (rStr, pTemp->maStr); 215 216 if ( eComp == COMPARE_LESS ) 217 nHigh = nMid-1; 218 else 219 { 220 if ( eComp == COMPARE_GREATER ) 221 nLow = nMid + 1; 222 else 223 break; 224 } 225 } 226 while ( nLow <= nHigh ); 227 228 if ( eComp != COMPARE_LESS ) 229 nMid++; 230 231 Insert( pNewEntry, nMid ); 232 } 233 } 234 } 235 catch (uno::RuntimeException& ) 236 { 237 // XXX this is arguable, if the exception occured because pNewEntry is 238 // garbage you wouldn't insert it. If the exception occured because the 239 // Collator implementation is garbage then give the user a chance to see 240 // his stuff 241 Insert( pNewEntry, (sal_uLong)0 ); 242 } 243 244 } 245 246 return (sal_uInt16)GetPos( pNewEntry ); 247 } 248 249 // ----------------------------------------------------------------------- 250 251 void ImplEntryList::RemoveEntry( sal_uInt16 nPos ) 252 { 253 ImplEntryType* pImplEntry = (ImplEntryType*)List::Remove( nPos ); 254 if ( pImplEntry ) 255 { 256 if ( !!pImplEntry->maImage ) 257 mnImages--; 258 259 delete pImplEntry; 260 } 261 } 262 263 // ----------------------------------------------------------------------- 264 265 sal_uInt16 ImplEntryList::FindEntry( const XubString& rString, sal_Bool bSearchMRUArea ) const 266 { 267 sal_uInt16 nEntries = GetEntryCount(); 268 for ( sal_uInt16 n = bSearchMRUArea ? 0 : GetMRUCount(); n < nEntries; n++ ) 269 { 270 ImplEntryType* pImplEntry = GetEntry( n ); 271 String aComp( vcl::I18nHelper::filterFormattingChars( pImplEntry->maStr ) ); 272 if ( aComp == rString ) 273 return n; 274 } 275 return LISTBOX_ENTRY_NOTFOUND; 276 } 277 278 // ----------------------------------------------------------------------- 279 280 sal_uInt16 ImplEntryList::FindMatchingEntry( const XubString& rStr, sal_uInt16 nStart, sal_Bool bForward, sal_Bool bLazy ) const 281 { 282 sal_uInt16 nPos = LISTBOX_ENTRY_NOTFOUND; 283 sal_uInt16 nEntryCount = GetEntryCount(); 284 if ( !bForward ) 285 nStart++; // wird sofort dekrementiert 286 287 const vcl::I18nHelper& rI18nHelper = mpWindow->GetSettings().GetLocaleI18nHelper(); 288 for ( sal_uInt16 n = nStart; bForward ? ( n < nEntryCount ) : n; ) 289 { 290 if ( !bForward ) 291 n--; 292 293 ImplEntryType* pImplEntry = GetEntry( n ); 294 sal_Bool bMatch = bLazy ? rI18nHelper.MatchString( rStr, pImplEntry->maStr ) != 0 : ( rStr.Match( pImplEntry->maStr ) == STRING_MATCH ); 295 if ( bMatch ) 296 { 297 nPos = n; 298 break; 299 } 300 301 if ( bForward ) 302 n++; 303 } 304 305 return nPos; 306 } 307 308 // ----------------------------------------------------------------------- 309 310 sal_uInt16 ImplEntryList::FindEntry( const void* pData ) const 311 { 312 sal_uInt16 nPos = LISTBOX_ENTRY_NOTFOUND; 313 for ( sal_uInt16 n = GetEntryCount(); n; ) 314 { 315 ImplEntryType* pImplEntry = GetEntry( --n ); 316 if ( pImplEntry->mpUserData == pData ) 317 { 318 nPos = n; 319 break; 320 } 321 } 322 return nPos; 323 } 324 325 // ----------------------------------------------------------------------- 326 327 long ImplEntryList::GetAddedHeight( sal_uInt16 i_nEndIndex, sal_uInt16 i_nBeginIndex, long i_nBeginHeight ) const 328 { 329 long nHeight = i_nBeginHeight; 330 sal_uInt16 nStart = i_nEndIndex > i_nBeginIndex ? i_nBeginIndex : i_nEndIndex; 331 sal_uInt16 nStop = i_nEndIndex > i_nBeginIndex ? i_nEndIndex : i_nBeginIndex; 332 sal_uInt16 nEntryCount = GetEntryCount(); 333 if( nStop != LISTBOX_ENTRY_NOTFOUND && nEntryCount != 0 ) 334 { 335 // sanity check 336 if( nStop > nEntryCount-1 ) 337 nStop = nEntryCount-1; 338 if( nStart > nEntryCount-1 ) 339 nStart = nEntryCount-1; 340 341 sal_uInt16 nIndex = nStart; 342 while( nIndex != LISTBOX_ENTRY_NOTFOUND && nIndex < nStop ) 343 { 344 nHeight += GetEntryPtr( nIndex )-> mnHeight; 345 nIndex++; 346 } 347 } 348 else 349 nHeight = 0; 350 return i_nEndIndex > i_nBeginIndex ? nHeight : -nHeight; 351 } 352 353 // ----------------------------------------------------------------------- 354 355 long ImplEntryList::GetEntryHeight( sal_uInt16 nPos ) const 356 { 357 ImplEntryType* pImplEntry = GetEntry( nPos ); 358 return pImplEntry ? pImplEntry->mnHeight : 0; 359 } 360 361 // ----------------------------------------------------------------------- 362 363 XubString ImplEntryList::GetEntryText( sal_uInt16 nPos ) const 364 { 365 XubString aEntryText; 366 ImplEntryType* pImplEntry = GetEntry( nPos ); 367 if ( pImplEntry ) 368 aEntryText = pImplEntry->maStr; 369 return aEntryText; 370 } 371 372 // ----------------------------------------------------------------------- 373 374 sal_Bool ImplEntryList::HasEntryImage( sal_uInt16 nPos ) const 375 { 376 sal_Bool bImage = sal_False; 377 ImplEntryType* pImplEntry = (ImplEntryType*)List::GetObject( nPos ); 378 if ( pImplEntry ) 379 bImage = !!pImplEntry->maImage; 380 return bImage; 381 } 382 383 // ----------------------------------------------------------------------- 384 385 Image ImplEntryList::GetEntryImage( sal_uInt16 nPos ) const 386 { 387 Image aImage; 388 ImplEntryType* pImplEntry = (ImplEntryType*)List::GetObject( nPos ); 389 if ( pImplEntry ) 390 aImage = pImplEntry->maImage; 391 return aImage; 392 } 393 394 // ----------------------------------------------------------------------- 395 396 void ImplEntryList::SetEntryData( sal_uInt16 nPos, void* pNewData ) 397 { 398 ImplEntryType* pImplEntry = (ImplEntryType*)List::GetObject( nPos ); 399 if ( pImplEntry ) 400 pImplEntry->mpUserData = pNewData; 401 } 402 403 // ----------------------------------------------------------------------- 404 405 void* ImplEntryList::GetEntryData( sal_uInt16 nPos ) const 406 { 407 ImplEntryType* pImplEntry = (ImplEntryType*)List::GetObject( nPos ); 408 return pImplEntry ? pImplEntry->mpUserData : NULL; 409 } 410 411 // ----------------------------------------------------------------------- 412 413 void ImplEntryList::SetEntryFlags( sal_uInt16 nPos, long nFlags ) 414 { 415 ImplEntryType* pImplEntry = (ImplEntryType*)List::GetObject( nPos ); 416 if ( pImplEntry ) 417 pImplEntry->mnFlags = nFlags; 418 } 419 420 // ----------------------------------------------------------------------- 421 422 long ImplEntryList::GetEntryFlags( sal_uInt16 nPos ) const 423 { 424 ImplEntryType* pImplEntry = (ImplEntryType*)List::GetObject( nPos ); 425 return pImplEntry ? pImplEntry->mnFlags : 0; 426 } 427 428 // ----------------------------------------------------------------------- 429 430 sal_uInt16 ImplEntryList::GetSelectEntryCount() const 431 { 432 sal_uInt16 nSelCount = 0; 433 for ( sal_uInt16 n = GetEntryCount(); n; ) 434 { 435 ImplEntryType* pImplEntry = GetEntry( --n ); 436 if ( pImplEntry->mbIsSelected ) 437 nSelCount++; 438 } 439 return nSelCount; 440 } 441 442 // ----------------------------------------------------------------------- 443 444 XubString ImplEntryList::GetSelectEntry( sal_uInt16 nIndex ) const 445 { 446 return GetEntryText( GetSelectEntryPos( nIndex ) ); 447 } 448 449 // ----------------------------------------------------------------------- 450 451 sal_uInt16 ImplEntryList::GetSelectEntryPos( sal_uInt16 nIndex ) const 452 { 453 sal_uInt16 nSelEntryPos = LISTBOX_ENTRY_NOTFOUND; 454 sal_uInt16 nSel = 0; 455 sal_uInt16 nEntryCount = GetEntryCount(); 456 457 for ( sal_uInt16 n = 0; n < nEntryCount; n++ ) 458 { 459 ImplEntryType* pImplEntry = GetEntry( n ); 460 if ( pImplEntry->mbIsSelected ) 461 { 462 if ( nSel == nIndex ) 463 { 464 nSelEntryPos = n; 465 break; 466 } 467 nSel++; 468 } 469 } 470 471 return nSelEntryPos; 472 } 473 474 // ----------------------------------------------------------------------- 475 476 sal_Bool ImplEntryList::IsEntrySelected( const XubString& rStr ) const 477 { 478 return IsEntryPosSelected( FindEntry( rStr ) ); 479 } 480 481 // ----------------------------------------------------------------------- 482 483 sal_Bool ImplEntryList::IsEntryPosSelected( sal_uInt16 nIndex ) const 484 { 485 ImplEntryType* pImplEntry = GetEntry( nIndex ); 486 return pImplEntry ? pImplEntry->mbIsSelected : sal_False; 487 } 488 489 // ----------------------------------------------------------------------- 490 491 bool ImplEntryList::IsEntrySelectable( sal_uInt16 nPos ) const 492 { 493 ImplEntryType* pImplEntry = GetEntry( nPos ); 494 return pImplEntry ? ((pImplEntry->mnFlags & LISTBOX_ENTRY_FLAG_DISABLE_SELECTION) == 0) : true; 495 } 496 497 // ----------------------------------------------------------------------- 498 499 sal_uInt16 ImplEntryList::FindFirstSelectable( sal_uInt16 nPos, bool bForward /* = true */ ) 500 { 501 if( IsEntrySelectable( nPos ) ) 502 return nPos; 503 504 if( bForward ) 505 { 506 for( nPos = nPos + 1; nPos < GetEntryCount(); nPos++ ) 507 { 508 if( IsEntrySelectable( nPos ) ) 509 return nPos; 510 } 511 } 512 else 513 { 514 while( nPos ) 515 { 516 nPos--; 517 if( IsEntrySelectable( nPos ) ) 518 return nPos; 519 } 520 } 521 522 return LISTBOX_ENTRY_NOTFOUND; 523 } 524 525 // ======================================================================= 526 527 ImplListBoxWindow::ImplListBoxWindow( Window* pParent, WinBits nWinStyle ) : 528 Control( pParent, 0 ), 529 maQuickSelectionEngine( *this ) 530 { 531 mpEntryList = new ImplEntryList( this ); 532 533 mnTop = 0; 534 mnLeft = 0; 535 mnBorder = 1; 536 mnSelectModifier = 0; 537 mnUserDrawEntry = LISTBOX_ENTRY_NOTFOUND; 538 mbTrack = sal_False; 539 mbImgsDiffSz = sal_False; 540 mbTravelSelect = sal_False; 541 mbTrackingSelect = sal_False; 542 mbSelectionChanged = sal_False; 543 mbMouseMoveSelect = sal_False; 544 mbMulti = sal_False; 545 mbStackMode = sal_False; 546 mbGrabFocus = sal_False; 547 mbUserDrawEnabled = sal_False; 548 mbInUserDraw = sal_False; 549 mbReadOnly = sal_False; 550 mbHasFocusRect = sal_False; 551 mbRight = ( nWinStyle & WB_RIGHT ) ? sal_True : sal_False; 552 mbCenter = ( nWinStyle & WB_CENTER ) ? sal_True : sal_False; 553 mbSimpleMode = ( nWinStyle & WB_SIMPLEMODE ) ? sal_True : sal_False; 554 mbSort = ( nWinStyle & WB_SORT ) ? sal_True : sal_False; 555 556 // pb: #106948# explicit mirroring for calc 557 mbMirroring = sal_False; 558 559 mnCurrentPos = LISTBOX_ENTRY_NOTFOUND; 560 mnTrackingSaveSelection = LISTBOX_ENTRY_NOTFOUND; 561 mnSeparatorPos = LISTBOX_ENTRY_NOTFOUND; 562 meProminentType = PROMINENT_TOP; 563 564 SetLineColor(); 565 SetTextFillColor(); 566 SetBackground( Wallpaper( GetSettings().GetStyleSettings().GetFieldColor() ) ); 567 568 ImplInitSettings( sal_True, sal_True, sal_True ); 569 ImplCalcMetrics(); 570 } 571 572 // ----------------------------------------------------------------------- 573 574 ImplListBoxWindow::~ImplListBoxWindow() 575 { 576 delete mpEntryList; 577 } 578 579 // ----------------------------------------------------------------------- 580 581 void ImplListBoxWindow::ImplInitSettings( sal_Bool bFont, sal_Bool bForeground, sal_Bool bBackground ) 582 { 583 ImplInitFieldSettings( this, bFont, bForeground, bBackground ); 584 } 585 586 // ----------------------------------------------------------------------- 587 588 void ImplListBoxWindow::ImplCalcMetrics() 589 { 590 mnMaxWidth = 0; 591 mnMaxTxtWidth = 0; 592 mnMaxImgWidth = 0; 593 mnMaxImgTxtWidth= 0; 594 mnMaxImgHeight = 0; 595 596 mnTextHeight = (sal_uInt16)GetTextHeight(); 597 mnMaxTxtHeight = mnTextHeight + mnBorder; 598 mnMaxHeight = mnMaxTxtHeight; 599 600 if ( maUserItemSize.Height() > mnMaxHeight ) 601 mnMaxHeight = (sal_uInt16) maUserItemSize.Height(); 602 if ( maUserItemSize.Width() > mnMaxWidth ) 603 mnMaxWidth= (sal_uInt16) maUserItemSize.Width(); 604 605 for ( sal_uInt16 n = mpEntryList->GetEntryCount(); n; ) 606 { 607 ImplEntryType* pEntry = mpEntryList->GetMutableEntryPtr( --n ); 608 ImplUpdateEntryMetrics( *pEntry ); 609 } 610 611 if( mnCurrentPos != LISTBOX_ENTRY_NOTFOUND ) 612 { 613 Size aSz( GetOutputSizePixel().Width(), mpEntryList->GetEntryPtr( mnCurrentPos )->mnHeight ); 614 maFocusRect.SetSize( aSz ); 615 } 616 } 617 618 // ----------------------------------------------------------------------- 619 620 void ImplListBoxWindow::Clear() 621 { 622 mpEntryList->Clear(); 623 624 mnMaxHeight = mnMaxTxtHeight; 625 mnMaxWidth = 0; 626 mnMaxTxtWidth = 0; 627 mnMaxImgTxtWidth= 0; 628 mnMaxImgWidth = 0; 629 mnMaxImgHeight = 0; 630 mnTop = 0; 631 mnLeft = 0; 632 mbImgsDiffSz = sal_False; 633 ImplClearLayoutData(); 634 635 mnCurrentPos = LISTBOX_ENTRY_NOTFOUND; 636 maQuickSelectionEngine.Reset(); 637 638 Invalidate(); 639 } 640 641 void ImplListBoxWindow::SetUserItemSize( const Size& rSz ) 642 { 643 ImplClearLayoutData(); 644 maUserItemSize = rSz; 645 ImplCalcMetrics(); 646 } 647 648 // ----------------------------------------------------------------------- 649 650 struct ImplEntryMetrics 651 { 652 sal_Bool bText; 653 sal_Bool bImage; 654 long nEntryWidth; 655 long nEntryHeight; 656 long nTextWidth; 657 long nImgWidth; 658 long nImgHeight; 659 }; 660 661 // ----------------------------------------------------------------------- 662 663 void ImplListBoxWindow::ImplUpdateEntryMetrics( ImplEntryType& rEntry ) 664 { 665 ImplEntryMetrics aMetrics; 666 aMetrics.bText = rEntry.maStr.Len() ? sal_True : sal_False; 667 aMetrics.bImage = !!rEntry.maImage; 668 aMetrics.nEntryWidth = 0; 669 aMetrics.nEntryHeight = 0; 670 aMetrics.nTextWidth = 0; 671 aMetrics.nImgWidth = 0; 672 aMetrics.nImgHeight = 0; 673 674 if ( aMetrics.bText ) 675 { 676 if( (rEntry.mnFlags & LISTBOX_ENTRY_FLAG_MULTILINE) ) 677 { 678 // multiline case 679 Size aCurSize( PixelToLogic( GetSizePixel() ) ); 680 // set the current size to a large number 681 // GetTextRect should shrink it to the actual size 682 aCurSize.Height() = 0x7fffff; 683 Rectangle aTextRect( Point( 0, 0 ), aCurSize ); 684 aTextRect = GetTextRect( aTextRect, rEntry.maStr, TEXT_DRAW_WORDBREAK | TEXT_DRAW_MULTILINE ); 685 aMetrics.nTextWidth = aTextRect.GetWidth(); 686 if( aMetrics.nTextWidth > mnMaxTxtWidth ) 687 mnMaxTxtWidth = aMetrics.nTextWidth; 688 aMetrics.nEntryWidth = mnMaxTxtWidth; 689 aMetrics.nEntryHeight = aTextRect.GetHeight() + mnBorder; 690 } 691 else 692 { 693 // normal single line case 694 aMetrics.nTextWidth = (sal_uInt16)GetTextWidth( rEntry.maStr ); 695 if( aMetrics.nTextWidth > mnMaxTxtWidth ) 696 mnMaxTxtWidth = aMetrics.nTextWidth; 697 aMetrics.nEntryWidth = mnMaxTxtWidth; 698 aMetrics.nEntryHeight = mnTextHeight + mnBorder; 699 } 700 } 701 if ( aMetrics.bImage ) 702 { 703 Size aImgSz = rEntry.maImage.GetSizePixel(); 704 aMetrics.nImgWidth = (sal_uInt16) CalcZoom( aImgSz.Width() ); 705 aMetrics.nImgHeight = (sal_uInt16) CalcZoom( aImgSz.Height() ); 706 707 if( mnMaxImgWidth && ( aMetrics.nImgWidth != mnMaxImgWidth ) ) 708 mbImgsDiffSz = sal_True; 709 else if ( mnMaxImgHeight && ( aMetrics.nImgHeight != mnMaxImgHeight ) ) 710 mbImgsDiffSz = sal_True; 711 712 if( aMetrics.nImgWidth > mnMaxImgWidth ) 713 mnMaxImgWidth = aMetrics.nImgWidth; 714 if( aMetrics.nImgHeight > mnMaxImgHeight ) 715 mnMaxImgHeight = aMetrics.nImgHeight; 716 717 mnMaxImgTxtWidth = Max( mnMaxImgTxtWidth, aMetrics.nTextWidth ); 718 aMetrics.nEntryHeight = Max( aMetrics.nImgHeight, aMetrics.nEntryHeight ); 719 720 } 721 if ( IsUserDrawEnabled() || aMetrics.bImage ) 722 { 723 aMetrics.nEntryWidth = Max( aMetrics.nImgWidth, maUserItemSize.Width() ); 724 if ( aMetrics.bText ) 725 aMetrics.nEntryWidth += aMetrics.nTextWidth + IMG_TXT_DISTANCE; 726 aMetrics.nEntryHeight = Max( Max( mnMaxImgHeight, maUserItemSize.Height() ) + 2, 727 aMetrics.nEntryHeight ); 728 } 729 730 if ( !aMetrics.bText && !aMetrics.bImage && !IsUserDrawEnabled() ) 731 { 732 // entries which have no (aka an empty) text, and no image, and are not user-drawn, should be 733 // shown nonetheless 734 aMetrics.nEntryHeight = mnTextHeight + mnBorder; 735 } 736 737 if ( aMetrics.nEntryWidth > mnMaxWidth ) 738 mnMaxWidth = aMetrics.nEntryWidth; 739 if ( aMetrics.nEntryHeight > mnMaxHeight ) 740 mnMaxHeight = aMetrics.nEntryHeight; 741 742 rEntry.mnHeight = aMetrics.nEntryHeight; 743 } 744 745 // ----------------------------------------------------------------------- 746 747 void ImplListBoxWindow::ImplCallSelect() 748 { 749 if ( !IsTravelSelect() && GetEntryList()->GetMaxMRUCount() ) 750 { 751 // Insert the selected entry as MRU, if not allready first MRU 752 sal_uInt16 nSelected = GetEntryList()->GetSelectEntryPos( 0 ); 753 sal_uInt16 nMRUCount = GetEntryList()->GetMRUCount(); 754 String aSelected = GetEntryList()->GetEntryText( nSelected ); 755 sal_uInt16 nFirstMatchingEntryPos = GetEntryList()->FindEntry( aSelected, sal_True ); 756 if ( nFirstMatchingEntryPos || !nMRUCount ) 757 { 758 sal_Bool bSelectNewEntry = sal_False; 759 if ( nFirstMatchingEntryPos < nMRUCount ) 760 { 761 RemoveEntry( nFirstMatchingEntryPos ); 762 nMRUCount--; 763 if ( nFirstMatchingEntryPos == nSelected ) 764 bSelectNewEntry = sal_True; 765 } 766 else if ( nMRUCount == GetEntryList()->GetMaxMRUCount() ) 767 { 768 RemoveEntry( nMRUCount - 1 ); 769 nMRUCount--; 770 } 771 772 ImplClearLayoutData(); 773 774 ImplEntryType* pNewEntry = new ImplEntryType( aSelected ); 775 pNewEntry->mbIsSelected = bSelectNewEntry; 776 GetEntryList()->InsertEntry( 0, pNewEntry, sal_False ); 777 ImplUpdateEntryMetrics( *pNewEntry ); 778 GetEntryList()->SetMRUCount( ++nMRUCount ); 779 SetSeparatorPos( nMRUCount ? nMRUCount-1 : 0 ); 780 maMRUChangedHdl.Call( NULL ); 781 } 782 } 783 784 maSelectHdl.Call( NULL ); 785 mbSelectionChanged = sal_False; 786 } 787 788 // ----------------------------------------------------------------------- 789 790 sal_uInt16 ImplListBoxWindow::InsertEntry( sal_uInt16 nPos, ImplEntryType* pNewEntry ) 791 { 792 ImplClearLayoutData(); 793 sal_uInt16 nNewPos = mpEntryList->InsertEntry( nPos, pNewEntry, mbSort ); 794 795 if( (GetStyle() & WB_WORDBREAK) ) 796 pNewEntry->mnFlags |= LISTBOX_ENTRY_FLAG_MULTILINE; 797 798 ImplUpdateEntryMetrics( *pNewEntry ); 799 return nNewPos; 800 } 801 802 // ----------------------------------------------------------------------- 803 804 void ImplListBoxWindow::RemoveEntry( sal_uInt16 nPos ) 805 { 806 ImplClearLayoutData(); 807 mpEntryList->RemoveEntry( nPos ); 808 if( mnCurrentPos >= mpEntryList->GetEntryCount() ) 809 mnCurrentPos = LISTBOX_ENTRY_NOTFOUND; 810 ImplCalcMetrics(); 811 } 812 813 // ----------------------------------------------------------------------- 814 815 void ImplListBoxWindow::SetEntryFlags( sal_uInt16 nPos, long nFlags ) 816 { 817 mpEntryList->SetEntryFlags( nPos, nFlags ); 818 ImplEntryType* pEntry = mpEntryList->GetMutableEntryPtr( nPos ); 819 if( pEntry ) 820 ImplUpdateEntryMetrics( *pEntry ); 821 } 822 823 // ----------------------------------------------------------------------- 824 825 void ImplListBoxWindow::ImplShowFocusRect() 826 { 827 if ( mbHasFocusRect ) 828 HideFocus(); 829 ShowFocus( maFocusRect ); 830 mbHasFocusRect = sal_True; 831 } 832 833 // ----------------------------------------------------------------------- 834 835 void ImplListBoxWindow::ImplHideFocusRect() 836 { 837 if ( mbHasFocusRect ) 838 { 839 HideFocus(); 840 mbHasFocusRect = sal_False; 841 } 842 } 843 844 845 // ----------------------------------------------------------------------- 846 847 sal_uInt16 ImplListBoxWindow::GetEntryPosForPoint( const Point& rPoint ) const 848 { 849 long nY = mnBorder; 850 851 sal_uInt16 nSelect = mnTop; 852 const ImplEntryType* pEntry = mpEntryList->GetEntryPtr( nSelect ); 853 while( pEntry && rPoint.Y() > pEntry->mnHeight + nY ) 854 { 855 nY += pEntry->mnHeight; 856 pEntry = mpEntryList->GetEntryPtr( ++nSelect ); 857 } 858 if( pEntry == NULL ) 859 nSelect = LISTBOX_ENTRY_NOTFOUND; 860 861 return nSelect; 862 } 863 864 // ----------------------------------------------------------------------- 865 866 sal_Bool ImplListBoxWindow::IsVisible( sal_uInt16 i_nEntry ) const 867 { 868 sal_Bool bRet = sal_False; 869 870 if( i_nEntry >= mnTop ) 871 { 872 if( mpEntryList->GetAddedHeight( i_nEntry, mnTop ) < 873 PixelToLogic( GetSizePixel() ).Height() ) 874 { 875 bRet = sal_True; 876 } 877 } 878 879 return bRet; 880 } 881 882 // ----------------------------------------------------------------------- 883 884 sal_uInt16 ImplListBoxWindow::GetLastVisibleEntry() const 885 { 886 sal_uInt16 nPos = mnTop; 887 long nWindowHeight = GetSizePixel().Height(); 888 sal_uInt16 nCount = mpEntryList->GetEntryCount(); 889 long nDiff; 890 for( nDiff = 0; nDiff < nWindowHeight && nPos < nCount; nDiff = mpEntryList->GetAddedHeight( nPos, mnTop ) ) 891 nPos++; 892 893 if( nDiff > nWindowHeight && nPos > mnTop ) 894 nPos--; 895 896 if( nPos >= nCount ) 897 nPos = nCount-1; 898 899 return nPos; 900 } 901 902 // ----------------------------------------------------------------------- 903 904 void ImplListBoxWindow::MouseButtonDown( const MouseEvent& rMEvt ) 905 { 906 mbMouseMoveSelect = sal_False; // Nur bis zum ersten MouseButtonDown 907 maQuickSelectionEngine.Reset(); 908 909 if ( !IsReadOnly() ) 910 { 911 if( rMEvt.GetClicks() == 1 ) 912 { 913 sal_uInt16 nSelect = GetEntryPosForPoint( rMEvt.GetPosPixel() ); 914 if( nSelect != LISTBOX_ENTRY_NOTFOUND ) 915 { 916 if ( !mbMulti && GetEntryList()->GetSelectEntryCount() ) 917 mnTrackingSaveSelection = GetEntryList()->GetSelectEntryPos( 0 ); 918 else 919 mnTrackingSaveSelection = LISTBOX_ENTRY_NOTFOUND; 920 921 mnCurrentPos = nSelect; 922 mbTrackingSelect = sal_True; 923 SelectEntries( nSelect, LET_MBDOWN, rMEvt.IsShift(), rMEvt.IsMod1() ); 924 mbTrackingSelect = sal_False; 925 if ( mbGrabFocus ) 926 GrabFocus(); 927 928 StartTracking( STARTTRACK_SCROLLREPEAT ); 929 } 930 } 931 if( rMEvt.GetClicks() == 2 ) 932 { 933 maDoubleClickHdl.Call( this ); 934 } 935 } 936 else // if ( mbGrabFocus ) 937 { 938 GrabFocus(); 939 } 940 } 941 942 // ----------------------------------------------------------------------- 943 944 void ImplListBoxWindow::MouseMove( const MouseEvent& rMEvt ) 945 { 946 if ( rMEvt.IsLeaveWindow() ) 947 { 948 if ( mbStackMode && IsMouseMoveSelect() && IsReallyVisible() ) 949 { 950 if ( rMEvt.GetPosPixel().Y() < 0 ) 951 { 952 DeselectAll(); 953 mnCurrentPos = LISTBOX_ENTRY_NOTFOUND; 954 SetTopEntry( 0 ); 955 if ( mbStackMode ) // #87072#, #92323# 956 { 957 mbTravelSelect = sal_True; 958 mnSelectModifier = rMEvt.GetModifier(); 959 ImplCallSelect(); 960 mbTravelSelect = sal_False; 961 } 962 963 } 964 } 965 } 966 else if ( ( ( !mbMulti && IsMouseMoveSelect() ) || mbStackMode ) && mpEntryList->GetEntryCount() ) 967 { 968 Point aPoint; 969 Rectangle aRect( aPoint, GetOutputSizePixel() ); 970 if( aRect.IsInside( rMEvt.GetPosPixel() ) ) 971 { 972 if ( IsMouseMoveSelect() ) 973 { 974 sal_uInt16 nSelect = GetEntryPosForPoint( rMEvt.GetPosPixel() ); 975 if( nSelect == LISTBOX_ENTRY_NOTFOUND ) 976 nSelect = mpEntryList->GetEntryCount() - 1; 977 nSelect = Min( nSelect, GetLastVisibleEntry() ); 978 nSelect = Min( nSelect, (sal_uInt16) ( mpEntryList->GetEntryCount() - 1 ) ); 979 // Select only visible Entries with MouseMove, otherwise Tracking... 980 if ( IsVisible( nSelect ) && 981 mpEntryList->IsEntrySelectable( nSelect ) && 982 ( ( nSelect != mnCurrentPos ) || !GetEntryList()->GetSelectEntryCount() || ( nSelect != GetEntryList()->GetSelectEntryPos( 0 ) ) ) ) 983 { 984 mbTrackingSelect = sal_True; 985 if ( SelectEntries( nSelect, LET_TRACKING, sal_False, sal_False ) ) 986 { 987 if ( mbStackMode ) // #87072# 988 { 989 mbTravelSelect = sal_True; 990 mnSelectModifier = rMEvt.GetModifier(); 991 ImplCallSelect(); 992 mbTravelSelect = sal_False; 993 } 994 } 995 mbTrackingSelect = sal_False; 996 } 997 } 998 999 // Falls der DD-Button gedrueckt wurde und jemand mit gedrueckter 1000 // Maustaste in die ListBox faehrt... 1001 if ( rMEvt.IsLeft() && !rMEvt.IsSynthetic() ) 1002 { 1003 if ( !mbMulti && GetEntryList()->GetSelectEntryCount() ) 1004 mnTrackingSaveSelection = GetEntryList()->GetSelectEntryPos( 0 ); 1005 else 1006 mnTrackingSaveSelection = LISTBOX_ENTRY_NOTFOUND; 1007 1008 if ( mbStackMode && ( mpEntryList->GetSelectionAnchor() == LISTBOX_ENTRY_NOTFOUND ) ) 1009 mpEntryList->SetSelectionAnchor( 0 ); 1010 1011 StartTracking( STARTTRACK_SCROLLREPEAT ); 1012 } 1013 } 1014 } 1015 } 1016 1017 // ----------------------------------------------------------------------- 1018 1019 void ImplListBoxWindow::DeselectAll() 1020 { 1021 while ( GetEntryList()->GetSelectEntryCount() ) 1022 { 1023 sal_uInt16 nS = GetEntryList()->GetSelectEntryPos( 0 ); 1024 SelectEntry( nS, sal_False ); 1025 } 1026 } 1027 1028 // ----------------------------------------------------------------------- 1029 1030 void ImplListBoxWindow::SelectEntry( sal_uInt16 nPos, sal_Bool bSelect ) 1031 { 1032 if( (mpEntryList->IsEntryPosSelected( nPos ) != bSelect) && mpEntryList->IsEntrySelectable( nPos ) ) 1033 { 1034 ImplHideFocusRect(); 1035 if( bSelect ) 1036 { 1037 if( !mbMulti ) 1038 { 1039 // Selektierten Eintrag deselektieren 1040 sal_uInt16 nDeselect = GetEntryList()->GetSelectEntryPos( 0 ); 1041 if( nDeselect != LISTBOX_ENTRY_NOTFOUND ) 1042 { 1043 //SelectEntryPos( nDeselect, sal_False ); 1044 GetEntryList()->SelectEntry( nDeselect, sal_False ); 1045 if ( IsUpdateMode() && IsReallyVisible() ) 1046 ImplPaint( nDeselect, sal_True ); 1047 } 1048 } 1049 mpEntryList->SelectEntry( nPos, sal_True ); 1050 mnCurrentPos = nPos; 1051 if ( ( nPos != LISTBOX_ENTRY_NOTFOUND ) && IsUpdateMode() ) 1052 { 1053 ImplPaint( nPos ); 1054 if ( !IsVisible( nPos ) ) 1055 { 1056 ImplClearLayoutData(); 1057 sal_uInt16 nVisibleEntries = GetLastVisibleEntry()-mnTop; 1058 if ( !nVisibleEntries || !IsReallyVisible() || ( nPos < GetTopEntry() ) ) 1059 { 1060 Resize(); 1061 ShowProminentEntry( nPos ); 1062 } 1063 else 1064 { 1065 ShowProminentEntry( nPos ); 1066 } 1067 } 1068 } 1069 } 1070 else 1071 { 1072 mpEntryList->SelectEntry( nPos, sal_False ); 1073 ImplPaint( nPos, sal_True ); 1074 } 1075 mbSelectionChanged = sal_True; 1076 } 1077 } 1078 1079 // ----------------------------------------------------------------------- 1080 1081 sal_Bool ImplListBoxWindow::SelectEntries( sal_uInt16 nSelect, LB_EVENT_TYPE eLET, sal_Bool bShift, sal_Bool bCtrl ) 1082 { 1083 sal_Bool bFocusChanged = sal_False; 1084 sal_Bool bSelectionChanged = sal_False; 1085 1086 if( IsEnabled() && mpEntryList->IsEntrySelectable( nSelect ) ) 1087 { 1088 // Hier (Single-ListBox) kann nur ein Eintrag deselektiert werden 1089 if( !mbMulti ) 1090 { 1091 sal_uInt16 nDeselect = mpEntryList->GetSelectEntryPos( 0 ); 1092 if( nSelect != nDeselect ) 1093 { 1094 SelectEntry( nSelect, sal_True ); 1095 mpEntryList->SetLastSelected( nSelect ); 1096 bFocusChanged = sal_True; 1097 bSelectionChanged = sal_True; 1098 } 1099 } 1100 // MultiListBox ohne Modifier 1101 else if( mbSimpleMode && !bCtrl && !bShift ) 1102 { 1103 sal_uInt16 nEntryCount = mpEntryList->GetEntryCount(); 1104 for ( sal_uInt16 nPos = 0; nPos < nEntryCount; nPos++ ) 1105 { 1106 sal_Bool bSelect = nPos == nSelect; 1107 if ( mpEntryList->IsEntryPosSelected( nPos ) != bSelect ) 1108 { 1109 SelectEntry( nPos, bSelect ); 1110 bFocusChanged = sal_True; 1111 bSelectionChanged = sal_True; 1112 } 1113 } 1114 mpEntryList->SetLastSelected( nSelect ); 1115 mpEntryList->SetSelectionAnchor( nSelect ); 1116 } 1117 // MultiListBox nur mit CTRL/SHIFT oder nicht im SimpleMode 1118 else if( ( !mbSimpleMode /* && !bShift */ ) || ( (mbSimpleMode && ( bCtrl || bShift )) || mbStackMode ) ) 1119 { 1120 // Space fuer Selektionswechsel 1121 if( !bShift && ( ( eLET == LET_KEYSPACE ) || ( eLET == LET_MBDOWN ) ) ) 1122 { 1123 sal_Bool bSelect = ( mbStackMode && IsMouseMoveSelect() ) ? sal_True : !mpEntryList->IsEntryPosSelected( nSelect ); 1124 if ( mbStackMode ) 1125 { 1126 sal_uInt16 n; 1127 if ( bSelect ) 1128 { 1129 // All entries before nSelect must be selected... 1130 for ( n = 0; n < nSelect; n++ ) 1131 SelectEntry( n, sal_True ); 1132 } 1133 if ( !bSelect ) 1134 { 1135 for ( n = nSelect+1; n < mpEntryList->GetEntryCount(); n++ ) 1136 SelectEntry( n, sal_False ); 1137 } 1138 } 1139 SelectEntry( nSelect, bSelect ); 1140 mpEntryList->SetLastSelected( nSelect ); 1141 mpEntryList->SetSelectionAnchor( mbStackMode ? 0 : nSelect ); 1142 if ( !mpEntryList->IsEntryPosSelected( nSelect ) ) 1143 mpEntryList->SetSelectionAnchor( LISTBOX_ENTRY_NOTFOUND ); 1144 bFocusChanged = sal_True; 1145 bSelectionChanged = sal_True; 1146 } 1147 else if( ( ( eLET == LET_TRACKING ) && ( nSelect != mnCurrentPos ) ) || 1148 ( (bShift||mbStackMode) && ( ( eLET == LET_KEYMOVE ) || ( eLET == LET_MBDOWN ) ) ) ) 1149 { 1150 mnCurrentPos = nSelect; 1151 bFocusChanged = sal_True; 1152 1153 sal_uInt16 nAnchor = mpEntryList->GetSelectionAnchor(); 1154 if( ( nAnchor == LISTBOX_ENTRY_NOTFOUND ) && ( mpEntryList->GetSelectEntryCount() || mbStackMode ) ) 1155 { 1156 nAnchor = mbStackMode ? 0 : mpEntryList->GetSelectEntryPos( mpEntryList->GetSelectEntryCount() - 1 ); 1157 } 1158 if( nAnchor != LISTBOX_ENTRY_NOTFOUND ) 1159 { 1160 // Alle Eintraege vom Anchor bis nSelect muessen selektiert sein 1161 sal_uInt16 nStart = Min( nSelect, nAnchor ); 1162 sal_uInt16 nEnd = Max( nSelect, nAnchor ); 1163 for ( sal_uInt16 n = nStart; n <= nEnd; n++ ) 1164 { 1165 if ( !mpEntryList->IsEntryPosSelected( n ) ) 1166 { 1167 SelectEntry( n, sal_True ); 1168 bSelectionChanged = sal_True; 1169 } 1170 } 1171 1172 // Ggf. muss noch was deselektiert werden... 1173 sal_uInt16 nLast = mpEntryList->GetLastSelected(); 1174 if ( nLast != LISTBOX_ENTRY_NOTFOUND ) 1175 { 1176 if ( ( nLast > nSelect ) && ( nLast > nAnchor ) ) 1177 { 1178 for ( sal_uInt16 n = nSelect+1; n <= nLast; n++ ) 1179 { 1180 if ( mpEntryList->IsEntryPosSelected( n ) ) 1181 { 1182 SelectEntry( n, sal_False ); 1183 bSelectionChanged = sal_True; 1184 } 1185 } 1186 } 1187 else if ( ( nLast < nSelect ) && ( nLast < nAnchor ) ) 1188 { 1189 for ( sal_uInt16 n = nLast; n < nSelect; n++ ) 1190 { 1191 if ( mpEntryList->IsEntryPosSelected( n ) ) 1192 { 1193 SelectEntry( n, sal_False ); 1194 bSelectionChanged = sal_True; 1195 } 1196 } 1197 } 1198 } 1199 mpEntryList->SetLastSelected( nSelect ); 1200 } 1201 } 1202 else if( eLET != LET_TRACKING ) 1203 { 1204 ImplHideFocusRect(); 1205 ImplPaint( nSelect, sal_True ); 1206 bFocusChanged = sal_True; 1207 } 1208 } 1209 else if( bShift ) 1210 { 1211 bFocusChanged = sal_True; 1212 } 1213 1214 if( bSelectionChanged ) 1215 mbSelectionChanged = sal_True; 1216 1217 if( bFocusChanged ) 1218 { 1219 long nHeightDiff = mpEntryList->GetAddedHeight( nSelect, mnTop, 0 ); 1220 maFocusRect.SetPos( Point( 0, nHeightDiff ) ); 1221 Size aSz( maFocusRect.GetWidth(), 1222 mpEntryList->GetEntryHeight( nSelect ) ); 1223 maFocusRect.SetSize( aSz ); 1224 if( HasFocus() ) 1225 ImplShowFocusRect(); 1226 } 1227 ImplClearLayoutData(); 1228 } 1229 return bSelectionChanged; 1230 } 1231 1232 // ----------------------------------------------------------------------- 1233 1234 void ImplListBoxWindow::Tracking( const TrackingEvent& rTEvt ) 1235 { 1236 Point aPoint; 1237 Rectangle aRect( aPoint, GetOutputSizePixel() ); 1238 sal_Bool bInside = aRect.IsInside( rTEvt.GetMouseEvent().GetPosPixel() ); 1239 1240 if( rTEvt.IsTrackingCanceled() || rTEvt.IsTrackingEnded() ) // MouseButtonUp 1241 { 1242 if ( bInside && !rTEvt.IsTrackingCanceled() ) 1243 { 1244 mnSelectModifier = rTEvt.GetMouseEvent().GetModifier(); 1245 ImplCallSelect(); 1246 } 1247 else 1248 { 1249 maCancelHdl.Call( NULL ); 1250 if ( !mbMulti ) 1251 { 1252 mbTrackingSelect = sal_True; 1253 SelectEntry( mnTrackingSaveSelection, sal_True ); 1254 mbTrackingSelect = sal_False; 1255 if ( mnTrackingSaveSelection != LISTBOX_ENTRY_NOTFOUND ) 1256 { 1257 long nHeightDiff = mpEntryList->GetAddedHeight( mnCurrentPos, mnTop, 0 ); 1258 maFocusRect.SetPos( Point( 0, nHeightDiff ) ); 1259 Size aSz( maFocusRect.GetWidth(), 1260 mpEntryList->GetEntryHeight( mnCurrentPos ) ); 1261 maFocusRect.SetSize( aSz ); 1262 ImplShowFocusRect(); 1263 } 1264 } 1265 } 1266 1267 mbTrack = sal_False; 1268 } 1269 else 1270 { 1271 sal_Bool bTrackOrQuickClick = mbTrack; 1272 if( !mbTrack ) 1273 { 1274 if ( bInside ) 1275 { 1276 mbTrack = sal_True; 1277 } 1278 1279 // Folgender Fall tritt nur auf, wenn man ganz kurz die Maustaste drueckt 1280 if( rTEvt.IsTrackingEnded() && mbTrack ) 1281 { 1282 bTrackOrQuickClick = sal_True; 1283 mbTrack = sal_False; 1284 } 1285 } 1286 1287 if( bTrackOrQuickClick ) 1288 { 1289 MouseEvent aMEvt = rTEvt.GetMouseEvent(); 1290 Point aPt( aMEvt.GetPosPixel() ); 1291 sal_Bool bShift = aMEvt.IsShift(); 1292 sal_Bool bCtrl = aMEvt.IsMod1(); 1293 1294 sal_uInt16 nSelect = LISTBOX_ENTRY_NOTFOUND; 1295 if( aPt.Y() < 0 ) 1296 { 1297 if ( mnCurrentPos != LISTBOX_ENTRY_NOTFOUND ) 1298 { 1299 nSelect = mnCurrentPos ? ( mnCurrentPos - 1 ) : 0; 1300 if( nSelect < mnTop ) 1301 SetTopEntry( mnTop-1 ); 1302 } 1303 } 1304 else if( aPt.Y() > GetOutputSizePixel().Height() ) 1305 { 1306 if ( mnCurrentPos != LISTBOX_ENTRY_NOTFOUND ) 1307 { 1308 nSelect = Min( (sal_uInt16)(mnCurrentPos+1), (sal_uInt16)(mpEntryList->GetEntryCount()-1) ); 1309 if( nSelect >= GetLastVisibleEntry() ) 1310 SetTopEntry( mnTop+1 ); 1311 } 1312 } 1313 else 1314 { 1315 nSelect = (sal_uInt16) ( ( aPt.Y() + mnBorder ) / mnMaxHeight ) + (sal_uInt16) mnTop; 1316 nSelect = Min( nSelect, GetLastVisibleEntry() ); 1317 nSelect = Min( nSelect, (sal_uInt16) ( mpEntryList->GetEntryCount() - 1 ) ); 1318 } 1319 1320 if ( bInside ) 1321 { 1322 if ( ( nSelect != mnCurrentPos ) || !GetEntryList()->GetSelectEntryCount() ) 1323 { 1324 mbTrackingSelect = sal_True; 1325 if ( SelectEntries( nSelect, LET_TRACKING, bShift, bCtrl ) ) 1326 { 1327 if ( mbStackMode ) // #87734# (#87072#) 1328 { 1329 mbTravelSelect = sal_True; 1330 mnSelectModifier = rTEvt.GetMouseEvent().GetModifier(); 1331 ImplCallSelect(); 1332 mbTravelSelect = sal_False; 1333 } 1334 } 1335 mbTrackingSelect = sal_False; 1336 } 1337 } 1338 else 1339 { 1340 if ( !mbMulti && GetEntryList()->GetSelectEntryCount() ) 1341 { 1342 mbTrackingSelect = sal_True; 1343 SelectEntry( GetEntryList()->GetSelectEntryPos( 0 ), sal_False ); 1344 mbTrackingSelect = sal_False; 1345 } 1346 else if ( mbStackMode ) 1347 { 1348 if ( ( rTEvt.GetMouseEvent().GetPosPixel().X() > 0 ) && ( rTEvt.GetMouseEvent().GetPosPixel().X() < aRect.Right() ) ) 1349 { 1350 if ( ( rTEvt.GetMouseEvent().GetPosPixel().Y() < 0 ) || ( rTEvt.GetMouseEvent().GetPosPixel().Y() > GetOutputSizePixel().Height() ) ) 1351 { 1352 sal_Bool bSelectionChanged = sal_False; 1353 if ( ( rTEvt.GetMouseEvent().GetPosPixel().Y() < 0 ) 1354 && !mnCurrentPos ) 1355 { 1356 if ( mpEntryList->IsEntryPosSelected( 0 ) ) 1357 { 1358 SelectEntry( 0, sal_False ); 1359 bSelectionChanged = sal_True; 1360 nSelect = LISTBOX_ENTRY_NOTFOUND; 1361 1362 } 1363 } 1364 else 1365 { 1366 mbTrackingSelect = sal_True; 1367 bSelectionChanged = SelectEntries( nSelect, LET_TRACKING, bShift, bCtrl ); 1368 mbTrackingSelect = sal_False; 1369 } 1370 1371 if ( bSelectionChanged ) 1372 { 1373 mbSelectionChanged = sal_True; 1374 mbTravelSelect = sal_True; 1375 mnSelectModifier = rTEvt.GetMouseEvent().GetModifier(); 1376 ImplCallSelect(); 1377 mbTravelSelect = sal_False; 1378 } 1379 } 1380 } 1381 } 1382 } 1383 mnCurrentPos = nSelect; 1384 if ( mnCurrentPos == LISTBOX_ENTRY_NOTFOUND ) 1385 { 1386 ImplHideFocusRect(); 1387 } 1388 else 1389 { 1390 long nHeightDiff = mpEntryList->GetAddedHeight( mnCurrentPos, mnTop, 0 ); 1391 maFocusRect.SetPos( Point( 0, nHeightDiff ) ); 1392 Size aSz( maFocusRect.GetWidth(), mpEntryList->GetEntryHeight( mnCurrentPos ) ); 1393 maFocusRect.SetSize( aSz ); 1394 ImplShowFocusRect(); 1395 } 1396 } 1397 } 1398 } 1399 1400 1401 // ----------------------------------------------------------------------- 1402 1403 void ImplListBoxWindow::KeyInput( const KeyEvent& rKEvt ) 1404 { 1405 if( !ProcessKeyInput( rKEvt ) ) 1406 Control::KeyInput( rKEvt ); 1407 } 1408 1409 // ----------------------------------------------------------------------- 1410 1411 #define IMPL_SELECT_NODIRECTION 0 1412 #define IMPL_SELECT_UP 1 1413 #define IMPL_SELECT_DOWN 2 1414 1415 sal_Bool ImplListBoxWindow::ProcessKeyInput( const KeyEvent& rKEvt ) 1416 { 1417 // zu selektierender Eintrag 1418 sal_uInt16 nSelect = LISTBOX_ENTRY_NOTFOUND; 1419 LB_EVENT_TYPE eLET = LET_KEYMOVE; 1420 1421 KeyCode aKeyCode = rKEvt.GetKeyCode(); 1422 1423 sal_Bool bShift = aKeyCode.IsShift(); 1424 sal_Bool bCtrl = aKeyCode.IsMod1() || aKeyCode.IsMod3(); 1425 sal_Bool bMod2 = aKeyCode.IsMod2(); 1426 sal_Bool bDone = sal_False; 1427 1428 switch( aKeyCode.GetCode() ) 1429 { 1430 case KEY_UP: 1431 { 1432 if ( IsReadOnly() ) 1433 { 1434 if ( GetTopEntry() ) 1435 SetTopEntry( GetTopEntry()-1 ); 1436 } 1437 else if ( !bMod2 ) 1438 { 1439 if( mnCurrentPos == LISTBOX_ENTRY_NOTFOUND ) 1440 { 1441 nSelect = mpEntryList->FindFirstSelectable( 0, true ); 1442 } 1443 else if ( mnCurrentPos ) 1444 { 1445 // search first selectable above the current position 1446 nSelect = mpEntryList->FindFirstSelectable( mnCurrentPos - 1, false ); 1447 } 1448 1449 if( ( nSelect != LISTBOX_ENTRY_NOTFOUND ) && ( nSelect < mnTop ) ) 1450 SetTopEntry( mnTop-1 ); 1451 1452 bDone = sal_True; 1453 } 1454 maQuickSelectionEngine.Reset(); 1455 } 1456 break; 1457 1458 case KEY_DOWN: 1459 { 1460 if ( IsReadOnly() ) 1461 { 1462 SetTopEntry( GetTopEntry()+1 ); 1463 } 1464 else if ( !bMod2 ) 1465 { 1466 if( mnCurrentPos == LISTBOX_ENTRY_NOTFOUND ) 1467 { 1468 nSelect = mpEntryList->FindFirstSelectable( 0, true ); 1469 } 1470 else if ( (mnCurrentPos+1) < mpEntryList->GetEntryCount() ) 1471 { 1472 // search first selectable below the current position 1473 nSelect = mpEntryList->FindFirstSelectable( mnCurrentPos + 1, true ); 1474 } 1475 1476 if( ( nSelect != LISTBOX_ENTRY_NOTFOUND ) && ( nSelect >= GetLastVisibleEntry() ) ) 1477 SetTopEntry( mnTop+1 ); 1478 1479 bDone = sal_True; 1480 } 1481 maQuickSelectionEngine.Reset(); 1482 } 1483 break; 1484 1485 case KEY_PAGEUP: 1486 { 1487 if ( IsReadOnly() ) 1488 { 1489 sal_uInt16 nCurVis = GetLastVisibleEntry() - mnTop +1; 1490 SetTopEntry( ( mnTop > nCurVis ) ? 1491 (mnTop-nCurVis) : 0 ); 1492 } 1493 else if ( !bCtrl && !bMod2 ) 1494 { 1495 if( mnCurrentPos == LISTBOX_ENTRY_NOTFOUND ) 1496 { 1497 nSelect = mpEntryList->FindFirstSelectable( 0, true ); 1498 } 1499 else if ( mnCurrentPos ) 1500 { 1501 if( mnCurrentPos == mnTop ) 1502 { 1503 sal_uInt16 nCurVis = GetLastVisibleEntry() - mnTop +1; 1504 SetTopEntry( ( mnTop > nCurVis ) ? ( mnTop-nCurVis+1 ) : 0 ); 1505 } 1506 1507 // find first selectable starting from mnTop looking foreward 1508 nSelect = mpEntryList->FindFirstSelectable( mnTop, true ); 1509 } 1510 bDone = sal_True; 1511 } 1512 maQuickSelectionEngine.Reset(); 1513 } 1514 break; 1515 1516 case KEY_PAGEDOWN: 1517 { 1518 if ( IsReadOnly() ) 1519 { 1520 SetTopEntry( GetLastVisibleEntry() ); 1521 } 1522 else if ( !bCtrl && !bMod2 ) 1523 { 1524 if( mnCurrentPos == LISTBOX_ENTRY_NOTFOUND ) 1525 { 1526 nSelect = mpEntryList->FindFirstSelectable( 0, true ); 1527 } 1528 else if ( (mnCurrentPos+1) < mpEntryList->GetEntryCount() ) 1529 { 1530 sal_uInt16 nCount = mpEntryList->GetEntryCount(); 1531 sal_uInt16 nCurVis = GetLastVisibleEntry() - mnTop; 1532 sal_uInt16 nTmp = Min( nCurVis, nCount ); 1533 nTmp += mnTop - 1; 1534 if( mnCurrentPos == nTmp && mnCurrentPos != nCount - 1 ) 1535 { 1536 long nTmp2 = Min( (long)(nCount-nCurVis), (long)((long)mnTop+(long)nCurVis-1) ); 1537 nTmp2 = Max( (long)0 , nTmp2 ); 1538 nTmp = (sal_uInt16)(nTmp2+(nCurVis-1) ); 1539 SetTopEntry( (sal_uInt16)nTmp2 ); 1540 } 1541 // find first selectable starting from nTmp looking backwards 1542 nSelect = mpEntryList->FindFirstSelectable( nTmp, false ); 1543 } 1544 bDone = sal_True; 1545 } 1546 maQuickSelectionEngine.Reset(); 1547 } 1548 break; 1549 1550 case KEY_HOME: 1551 { 1552 if ( IsReadOnly() ) 1553 { 1554 SetTopEntry( 0 ); 1555 } 1556 else if ( !bCtrl && !bMod2 ) 1557 { 1558 if ( mnCurrentPos ) 1559 { 1560 nSelect = mpEntryList->FindFirstSelectable( mpEntryList->GetEntryCount() ? 0 : LISTBOX_ENTRY_NOTFOUND, true ); 1561 if( mnTop != 0 ) 1562 SetTopEntry( 0 ); 1563 1564 bDone = sal_True; 1565 } 1566 } 1567 maQuickSelectionEngine.Reset(); 1568 } 1569 break; 1570 1571 case KEY_END: 1572 { 1573 if ( IsReadOnly() ) 1574 { 1575 SetTopEntry( 0xFFFF ); 1576 } 1577 else if ( !bCtrl && !bMod2 ) 1578 { 1579 if( mnCurrentPos == LISTBOX_ENTRY_NOTFOUND ) 1580 { 1581 nSelect = mpEntryList->FindFirstSelectable( 0, true ); 1582 } 1583 else if ( (mnCurrentPos+1) < mpEntryList->GetEntryCount() ) 1584 { 1585 sal_uInt16 nCount = mpEntryList->GetEntryCount(); 1586 nSelect = mpEntryList->FindFirstSelectable( nCount - 1, false ); 1587 sal_uInt16 nCurVis = GetLastVisibleEntry() - mnTop + 1; 1588 if( nCount > nCurVis ) 1589 SetTopEntry( nCount - nCurVis ); 1590 } 1591 bDone = sal_True; 1592 } 1593 maQuickSelectionEngine.Reset(); 1594 } 1595 break; 1596 1597 case KEY_LEFT: 1598 { 1599 if ( !bCtrl && !bMod2 ) 1600 { 1601 ScrollHorz( -HORZ_SCROLL ); 1602 bDone = sal_True; 1603 } 1604 maQuickSelectionEngine.Reset(); 1605 } 1606 break; 1607 1608 case KEY_RIGHT: 1609 { 1610 if ( !bCtrl && !bMod2 ) 1611 { 1612 ScrollHorz( HORZ_SCROLL ); 1613 bDone = sal_True; 1614 } 1615 maQuickSelectionEngine.Reset(); 1616 } 1617 break; 1618 1619 case KEY_RETURN: 1620 { 1621 if ( !bMod2 && !IsReadOnly() ) 1622 { 1623 mnSelectModifier = rKEvt.GetKeyCode().GetModifier(); 1624 ImplCallSelect(); 1625 bDone = sal_False; // RETURN nicht abfangen. 1626 } 1627 maQuickSelectionEngine.Reset(); 1628 } 1629 break; 1630 1631 case KEY_SPACE: 1632 { 1633 if ( !bMod2 && !IsReadOnly() ) 1634 { 1635 if( mbMulti && ( !mbSimpleMode || ( mbSimpleMode && bCtrl && !bShift ) || mbStackMode ) ) 1636 { 1637 nSelect = mnCurrentPos; 1638 eLET = LET_KEYSPACE; 1639 } 1640 bDone = sal_True; 1641 } 1642 maQuickSelectionEngine.Reset(); 1643 } 1644 break; 1645 1646 case KEY_A: 1647 { 1648 if( bCtrl && mbMulti ) 1649 { 1650 // paint only once 1651 sal_Bool bUpdates = IsUpdateMode(); 1652 SetUpdateMode( sal_False ); 1653 1654 sal_uInt16 nEntryCount = mpEntryList->GetEntryCount(); 1655 for( sal_uInt16 i = 0; i < nEntryCount; i++ ) 1656 SelectEntry( i, sal_True ); 1657 1658 // restore update mode 1659 SetUpdateMode( bUpdates ); 1660 Invalidate(); 1661 1662 maQuickSelectionEngine.Reset(); 1663 1664 bDone = sal_True; 1665 break; 1666 } 1667 } 1668 // fall through intentional 1669 default: 1670 { 1671 if ( !IsReadOnly() ) 1672 { 1673 bDone = maQuickSelectionEngine.HandleKeyEvent( rKEvt ); 1674 } 1675 } 1676 break; 1677 } 1678 1679 if ( ( nSelect != LISTBOX_ENTRY_NOTFOUND ) 1680 && ( ( !mpEntryList->IsEntryPosSelected( nSelect ) ) 1681 || ( eLET == LET_KEYSPACE ) 1682 ) 1683 ) 1684 { 1685 DBG_ASSERT( !mpEntryList->IsEntryPosSelected( nSelect ) || mbMulti, "ImplListBox: Selecting same Entry" ); 1686 if( nSelect >= mpEntryList->GetEntryCount() ) 1687 nSelect = mpEntryList->GetEntryCount()-1; 1688 mnCurrentPos = nSelect; 1689 if ( SelectEntries( nSelect, eLET, bShift, bCtrl ) ) 1690 { 1691 mbTravelSelect = sal_True; 1692 mnSelectModifier = rKEvt.GetKeyCode().GetModifier(); 1693 ImplCallSelect(); 1694 mbTravelSelect = sal_False; 1695 } 1696 } 1697 1698 return bDone; 1699 } 1700 1701 // ----------------------------------------------------------------------- 1702 namespace 1703 { 1704 static ::vcl::StringEntryIdentifier lcl_getEntry( const ImplEntryList& _rList, sal_uInt16 _nPos, String& _out_entryText ) 1705 { 1706 OSL_PRECOND( ( _nPos != LISTBOX_ENTRY_NOTFOUND ), "lcl_getEntry: invalid position!" ); 1707 sal_uInt16 nEntryCount( _rList.GetEntryCount() ); 1708 if ( _nPos >= nEntryCount ) 1709 _nPos = 0; 1710 _out_entryText = _rList.GetEntryText( _nPos ); 1711 1712 // ::vcl::StringEntryIdentifier does not allow for 0 values, but our position is 0-based 1713 // => normalize 1714 return reinterpret_cast< ::vcl::StringEntryIdentifier >( _nPos + 1 ); 1715 } 1716 1717 static sal_uInt16 lcl_getEntryPos( ::vcl::StringEntryIdentifier _entry ) 1718 { 1719 // our pos is 0-based, but StringEntryIdentifier does not allow for a NULL 1720 return static_cast< sal_uInt16 >( reinterpret_cast< sal_Int64 >( _entry ) ) - 1; 1721 } 1722 } 1723 1724 // ----------------------------------------------------------------------- 1725 ::vcl::StringEntryIdentifier ImplListBoxWindow::CurrentEntry( String& _out_entryText ) const 1726 { 1727 return lcl_getEntry( *GetEntryList(), ( mnCurrentPos == LISTBOX_ENTRY_NOTFOUND ) ? 0 : mnCurrentPos + 1, _out_entryText ); 1728 } 1729 1730 // ----------------------------------------------------------------------- 1731 ::vcl::StringEntryIdentifier ImplListBoxWindow::NextEntry( ::vcl::StringEntryIdentifier _currentEntry, String& _out_entryText ) const 1732 { 1733 sal_uInt16 nNextPos = lcl_getEntryPos( _currentEntry ) + 1; 1734 return lcl_getEntry( *GetEntryList(), nNextPos, _out_entryText ); 1735 } 1736 1737 // ----------------------------------------------------------------------- 1738 void ImplListBoxWindow::SelectEntry( ::vcl::StringEntryIdentifier _entry ) 1739 { 1740 sal_uInt16 nSelect = lcl_getEntryPos( _entry ); 1741 if ( mpEntryList->IsEntryPosSelected( nSelect ) ) 1742 { 1743 // ignore that. This method is a callback from the QuickSelectionEngine, which means the user attempted 1744 // to select the given entry by typing its starting letters. No need to act. 1745 return; 1746 } 1747 1748 // normalize 1749 OSL_ENSURE( nSelect < mpEntryList->GetEntryCount(), "ImplListBoxWindow::SelectEntry: how that?" ); 1750 if( nSelect >= mpEntryList->GetEntryCount() ) 1751 nSelect = mpEntryList->GetEntryCount()-1; 1752 1753 // make visible 1754 ShowProminentEntry( nSelect ); 1755 1756 // actually select 1757 mnCurrentPos = nSelect; 1758 if ( SelectEntries( nSelect, LET_KEYMOVE, sal_False, sal_False ) ) 1759 { 1760 mbTravelSelect = sal_True; 1761 mnSelectModifier = 0; 1762 ImplCallSelect(); 1763 mbTravelSelect = sal_False; 1764 } 1765 } 1766 1767 // ----------------------------------------------------------------------- 1768 1769 void ImplListBoxWindow::ImplPaint( sal_uInt16 nPos, sal_Bool bErase, bool bLayout ) 1770 { 1771 const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings(); 1772 1773 const ImplEntryType* pEntry = mpEntryList->GetEntryPtr( nPos ); 1774 if( ! pEntry ) 1775 return; 1776 1777 long nWidth = GetOutputSizePixel().Width(); 1778 long nY = mpEntryList->GetAddedHeight( nPos, mnTop ); 1779 Rectangle aRect( Point( 0, nY ), Size( nWidth, pEntry->mnHeight ) ); 1780 1781 if( ! bLayout ) 1782 { 1783 if( mpEntryList->IsEntryPosSelected( nPos ) ) 1784 { 1785 SetTextColor( !IsEnabled() ? rStyleSettings.GetDisableColor() : rStyleSettings.GetHighlightTextColor() ); 1786 SetFillColor( rStyleSettings.GetHighlightColor() ); 1787 SetTextFillColor( rStyleSettings.GetHighlightColor() ); 1788 DrawRect( aRect ); 1789 } 1790 else 1791 { 1792 ImplInitSettings( sal_False, sal_True, sal_False ); 1793 if( !IsEnabled() ) 1794 SetTextColor( rStyleSettings.GetDisableColor() ); 1795 SetTextFillColor(); 1796 if( bErase ) 1797 Erase( aRect ); 1798 } 1799 } 1800 1801 if ( IsUserDrawEnabled() ) 1802 { 1803 mbInUserDraw = sal_True; 1804 mnUserDrawEntry = nPos; 1805 aRect.Left() -= mnLeft; 1806 if ( nPos < GetEntryList()->GetMRUCount() ) 1807 nPos = GetEntryList()->FindEntry( GetEntryList()->GetEntryText( nPos ) ); 1808 nPos = sal::static_int_cast<sal_uInt16>(nPos - GetEntryList()->GetMRUCount()); 1809 UserDrawEvent aUDEvt( this, aRect, nPos, 0 ); 1810 maUserDrawHdl.Call( &aUDEvt ); 1811 mbInUserDraw = sal_False; 1812 } 1813 else 1814 { 1815 DrawEntry( nPos, sal_True, sal_True, sal_False, bLayout ); 1816 } 1817 } 1818 1819 // ----------------------------------------------------------------------- 1820 1821 void ImplListBoxWindow::DrawEntry( sal_uInt16 nPos, sal_Bool bDrawImage, sal_Bool bDrawText, sal_Bool bDrawTextAtImagePos, bool bLayout ) 1822 { 1823 const ImplEntryType* pEntry = mpEntryList->GetEntryPtr( nPos ); 1824 if( ! pEntry ) 1825 return; 1826 1827 // Bei Aenderungen in dieser Methode ggf. auch ImplWin::DrawEntry() anpassen. 1828 1829 if ( mbInUserDraw ) 1830 nPos = mnUserDrawEntry; // real entry, not the matching entry from MRU 1831 1832 long nY = mpEntryList->GetAddedHeight( nPos, mnTop ); 1833 Size aImgSz; 1834 1835 if( bDrawImage && mpEntryList->HasImages() && !bLayout ) 1836 { 1837 Image aImage = mpEntryList->GetEntryImage( nPos ); 1838 if( !!aImage ) 1839 { 1840 aImgSz = aImage.GetSizePixel(); 1841 Point aPtImg( mnBorder - mnLeft, nY + ( ( pEntry->mnHeight - aImgSz.Height() ) / 2 ) ); 1842 1843 // pb: #106948# explicit mirroring for calc 1844 if ( mbMirroring ) 1845 // right aligned 1846 aPtImg.X() = mnMaxWidth + mnBorder - aImgSz.Width() - mnLeft; 1847 1848 if ( !IsZoom() ) 1849 { 1850 DrawImage( aPtImg, aImage ); 1851 } 1852 else 1853 { 1854 aImgSz.Width() = CalcZoom( aImgSz.Width() ); 1855 aImgSz.Height() = CalcZoom( aImgSz.Height() ); 1856 DrawImage( aPtImg, aImgSz, aImage ); 1857 } 1858 } 1859 } 1860 1861 if( bDrawText ) 1862 { 1863 MetricVector* pVector = bLayout ? &mpControlData->mpLayoutData->m_aUnicodeBoundRects : NULL; 1864 String* pDisplayText = bLayout ? &mpControlData->mpLayoutData->m_aDisplayText : NULL; 1865 XubString aStr( mpEntryList->GetEntryText( nPos ) ); 1866 if ( aStr.Len() ) 1867 { 1868 long nMaxWidth = Max( static_cast< long >( mnMaxWidth ), 1869 GetOutputSizePixel().Width() - 2*mnBorder ); 1870 // a multiline entry should only be as wide a the window 1871 if( (pEntry->mnFlags & LISTBOX_ENTRY_FLAG_MULTILINE) ) 1872 nMaxWidth = GetOutputSizePixel().Width() - 2*mnBorder; 1873 1874 Rectangle aTextRect( Point( mnBorder - mnLeft, nY ), 1875 Size( nMaxWidth, pEntry->mnHeight ) ); 1876 1877 if( !bDrawTextAtImagePos && ( mpEntryList->HasEntryImage(nPos) || IsUserDrawEnabled() ) ) 1878 { 1879 long nImageWidth = Max( mnMaxImgWidth, maUserItemSize.Width() ); 1880 aTextRect.Left() += nImageWidth + IMG_TXT_DISTANCE; 1881 } 1882 1883 if( bLayout ) 1884 mpControlData->mpLayoutData->m_aLineIndices.push_back( mpControlData->mpLayoutData->m_aDisplayText.Len() ); 1885 1886 // pb: #106948# explicit mirroring for calc 1887 if ( mbMirroring ) 1888 { 1889 // right aligned 1890 aTextRect.Left() = nMaxWidth + mnBorder - GetTextWidth( aStr ) - mnLeft; 1891 if ( aImgSz.Width() > 0 ) 1892 aTextRect.Left() -= ( aImgSz.Width() + IMG_TXT_DISTANCE ); 1893 } 1894 1895 sal_uInt16 nDrawStyle = ImplGetTextStyle(); 1896 if( (pEntry->mnFlags & LISTBOX_ENTRY_FLAG_MULTILINE) ) 1897 nDrawStyle |= MULTILINE_ENTRY_DRAW_FLAGS; 1898 if( (pEntry->mnFlags & LISTBOX_ENTRY_FLAG_DRAW_DISABLED) ) 1899 nDrawStyle |= TEXT_DRAW_DISABLE; 1900 1901 DrawText( aTextRect, aStr, nDrawStyle, pVector, pDisplayText ); 1902 } 1903 } 1904 1905 if( !bLayout ) 1906 { 1907 if ( ( mnSeparatorPos != LISTBOX_ENTRY_NOTFOUND ) && 1908 ( ( nPos == mnSeparatorPos ) || ( nPos == mnSeparatorPos+1 ) ) ) 1909 { 1910 Color aOldLineColor( GetLineColor() ); 1911 SetLineColor( ( GetBackground().GetColor() != COL_LIGHTGRAY ) ? COL_LIGHTGRAY : COL_GRAY ); 1912 Point aStartPos( 0, nY ); 1913 if ( nPos == mnSeparatorPos ) 1914 aStartPos.Y() += pEntry->mnHeight-1; 1915 Point aEndPos( aStartPos ); 1916 aEndPos.X() = GetOutputSizePixel().Width(); 1917 DrawLine( aStartPos, aEndPos ); 1918 SetLineColor( aOldLineColor ); 1919 } 1920 } 1921 } 1922 1923 // ----------------------------------------------------------------------- 1924 1925 void ImplListBoxWindow::FillLayoutData() const 1926 { 1927 mpControlData->mpLayoutData = new vcl::ControlLayoutData(); 1928 const_cast<ImplListBoxWindow*>(this)-> 1929 ImplDoPaint( Rectangle( Point( 0, 0 ), GetOutputSize() ), true ); 1930 } 1931 1932 // ----------------------------------------------------------------------- 1933 1934 void ImplListBoxWindow::ImplDoPaint( const Rectangle& rRect, bool bLayout ) 1935 { 1936 sal_uInt16 nCount = mpEntryList->GetEntryCount(); 1937 1938 sal_Bool bShowFocusRect = mbHasFocusRect; 1939 if ( mbHasFocusRect && ! bLayout ) 1940 ImplHideFocusRect(); 1941 1942 long nY = 0; // + mnBorder; 1943 long nHeight = GetOutputSizePixel().Height();// - mnMaxHeight + mnBorder; 1944 1945 for( sal_uInt16 i = (sal_uInt16)mnTop; i < nCount && nY < nHeight + mnMaxHeight; i++ ) 1946 { 1947 const ImplEntryType* pEntry = mpEntryList->GetEntryPtr( i ); 1948 if( nY + pEntry->mnHeight >= rRect.Top() && 1949 nY <= rRect.Bottom() + mnMaxHeight ) 1950 { 1951 ImplPaint( i, sal_False, bLayout ); 1952 } 1953 nY += pEntry->mnHeight; 1954 } 1955 1956 long nHeightDiff = mpEntryList->GetAddedHeight( mnCurrentPos, mnTop, 0 ); 1957 maFocusRect.SetPos( Point( 0, nHeightDiff ) ); 1958 Size aSz( maFocusRect.GetWidth(), mpEntryList->GetEntryHeight( mnCurrentPos ) ); 1959 maFocusRect.SetSize( aSz ); 1960 if( HasFocus() && bShowFocusRect && !bLayout ) 1961 ImplShowFocusRect(); 1962 } 1963 1964 // ----------------------------------------------------------------------- 1965 1966 void ImplListBoxWindow::Paint( const Rectangle& rRect ) 1967 { 1968 ImplDoPaint( rRect ); 1969 } 1970 1971 // ----------------------------------------------------------------------- 1972 1973 sal_uInt16 ImplListBoxWindow::GetDisplayLineCount() const 1974 { 1975 // FIXME: LISTBOX_ENTRY_FLAG_MULTILINE 1976 1977 sal_uInt16 nCount = mpEntryList->GetEntryCount(); 1978 long nHeight = GetOutputSizePixel().Height();// - mnMaxHeight + mnBorder; 1979 sal_uInt16 nEntries = static_cast< sal_uInt16 >( ( nHeight + mnMaxHeight - 1 ) / mnMaxHeight ); 1980 if( nEntries > nCount-mnTop ) 1981 nEntries = nCount-mnTop; 1982 1983 return nEntries; 1984 } 1985 1986 // ----------------------------------------------------------------------- 1987 1988 void ImplListBoxWindow::Resize() 1989 { 1990 Control::Resize(); 1991 1992 sal_Bool bShowFocusRect = mbHasFocusRect; 1993 if ( bShowFocusRect ) 1994 ImplHideFocusRect(); 1995 1996 if( mnCurrentPos != LISTBOX_ENTRY_NOTFOUND ) 1997 { 1998 Size aSz( GetOutputSizePixel().Width(), mpEntryList->GetEntryHeight( mnCurrentPos ) ); 1999 maFocusRect.SetSize( aSz ); 2000 } 2001 2002 if ( bShowFocusRect ) 2003 ImplShowFocusRect(); 2004 2005 ImplClearLayoutData(); 2006 } 2007 2008 // ----------------------------------------------------------------------- 2009 2010 void ImplListBoxWindow::GetFocus() 2011 { 2012 sal_uInt16 nPos = mnCurrentPos; 2013 if ( nPos == LISTBOX_ENTRY_NOTFOUND ) 2014 nPos = 0; 2015 long nHeightDiff = mpEntryList->GetAddedHeight( nPos, mnTop, 0 ); 2016 maFocusRect.SetPos( Point( 0, nHeightDiff ) ); 2017 Size aSz( maFocusRect.GetWidth(), mpEntryList->GetEntryHeight( nPos ) ); 2018 maFocusRect.SetSize( aSz ); 2019 ImplShowFocusRect(); 2020 Control::GetFocus(); 2021 } 2022 2023 // ----------------------------------------------------------------------- 2024 2025 void ImplListBoxWindow::LoseFocus() 2026 { 2027 ImplHideFocusRect(); 2028 Control::LoseFocus(); 2029 } 2030 2031 // ----------------------------------------------------------------------- 2032 2033 /* 2034 void ImplListBoxWindow::RequestHelp( const HelpEvent& rHEvt ) 2035 { 2036 if ( rHEvt.GetMode() & HELPMODE_BALLOON ) 2037 Help::ShowBalloon( this, rHEvt.GetMousePosPixel(), String() ); 2038 2039 Window::RequestHelp( rHEvt ); 2040 } 2041 */ 2042 2043 // ----------------------------------------------------------------------- 2044 2045 void ImplListBoxWindow::SetTopEntry( sal_uInt16 nTop ) 2046 { 2047 if( mpEntryList->GetEntryCount() == 0 ) 2048 return; 2049 2050 long nWHeight = PixelToLogic( GetSizePixel() ).Height(); 2051 2052 sal_uInt16 nLastEntry = mpEntryList->GetEntryCount()-1; 2053 if( nTop > nLastEntry ) 2054 nTop = nLastEntry; 2055 const ImplEntryType* pLast = mpEntryList->GetEntryPtr( nLastEntry ); 2056 while( nTop > 0 && mpEntryList->GetAddedHeight( nLastEntry, nTop-1 ) + pLast->mnHeight <= nWHeight ) 2057 nTop--; 2058 2059 if ( nTop != mnTop ) 2060 { 2061 ImplClearLayoutData(); 2062 long nDiff = mpEntryList->GetAddedHeight( mnTop, nTop, 0 ); 2063 Update(); 2064 ImplHideFocusRect(); 2065 mnTop = nTop; 2066 Scroll( 0, nDiff ); 2067 Update(); 2068 if( HasFocus() ) 2069 ImplShowFocusRect(); 2070 maScrollHdl.Call( this ); 2071 } 2072 } 2073 2074 // ----------------------------------------------------------------------- 2075 2076 void ImplListBoxWindow::ShowProminentEntry( sal_uInt16 nEntryPos ) 2077 { 2078 if( meProminentType == PROMINENT_MIDDLE ) 2079 { 2080 sal_uInt16 nPos = nEntryPos; 2081 long nWHeight = PixelToLogic( GetSizePixel() ).Height(); 2082 while( nEntryPos > 0 && mpEntryList->GetAddedHeight( nPos+1, nEntryPos ) < nWHeight/2 ) 2083 nEntryPos--; 2084 } 2085 SetTopEntry( nEntryPos ); 2086 } 2087 2088 // ----------------------------------------------------------------------- 2089 2090 void ImplListBoxWindow::SetLeftIndent( long n ) 2091 { 2092 ScrollHorz( n - mnLeft ); 2093 } 2094 2095 // ----------------------------------------------------------------------- 2096 2097 void ImplListBoxWindow::ScrollHorz( long n ) 2098 { 2099 long nDiff = 0; 2100 if ( n > 0 ) 2101 { 2102 long nWidth = GetOutputSizePixel().Width(); 2103 if( ( mnMaxWidth - mnLeft + n ) > nWidth ) 2104 nDiff = n; 2105 } 2106 else if ( n < 0 ) 2107 { 2108 if( mnLeft ) 2109 { 2110 long nAbs = -n; 2111 nDiff = - ( ( mnLeft > nAbs ) ? nAbs : mnLeft ); 2112 } 2113 } 2114 2115 if ( nDiff ) 2116 { 2117 ImplClearLayoutData(); 2118 mnLeft = sal::static_int_cast<sal_uInt16>(mnLeft + nDiff); 2119 Update(); 2120 ImplHideFocusRect(); 2121 Scroll( -nDiff, 0 ); 2122 Update(); 2123 if( HasFocus() ) 2124 ImplShowFocusRect(); 2125 maScrollHdl.Call( this ); 2126 } 2127 } 2128 2129 // ----------------------------------------------------------------------- 2130 2131 Size ImplListBoxWindow::CalcSize( sal_uInt16 nMaxLines ) const 2132 { 2133 // FIXME: LISTBOX_ENTRY_FLAG_MULTILINE 2134 2135 Size aSz; 2136 // sal_uInt16 nL = Min( nMaxLines, mpEntryList->GetEntryCount() ); 2137 aSz.Height() = nMaxLines * mnMaxHeight; 2138 aSz.Width() = mnMaxWidth + 2*mnBorder; 2139 return aSz; 2140 } 2141 2142 // ----------------------------------------------------------------------- 2143 2144 Rectangle ImplListBoxWindow::GetBoundingRectangle( sal_uInt16 nItem ) const 2145 { 2146 const ImplEntryType* pEntry = mpEntryList->GetEntryPtr( nItem ); 2147 Size aSz( GetSizePixel().Width(), pEntry ? pEntry->mnHeight : GetEntryHeight() ); 2148 long nY = mpEntryList->GetAddedHeight( nItem, GetTopEntry() ) - mpEntryList->GetAddedHeight( GetTopEntry() ); 2149 Rectangle aRect( Point( 0, nY ), aSz ); 2150 return aRect; 2151 } 2152 2153 2154 // ----------------------------------------------------------------------- 2155 2156 void ImplListBoxWindow::StateChanged( StateChangedType nType ) 2157 { 2158 Control::StateChanged( nType ); 2159 2160 if ( nType == STATE_CHANGE_ZOOM ) 2161 { 2162 ImplInitSettings( sal_True, sal_False, sal_False ); 2163 ImplCalcMetrics(); 2164 Invalidate(); 2165 } 2166 else if ( nType == STATE_CHANGE_UPDATEMODE ) 2167 { 2168 if ( IsUpdateMode() && IsReallyVisible() ) 2169 Invalidate(); 2170 } 2171 else if ( nType == STATE_CHANGE_CONTROLFONT ) 2172 { 2173 ImplInitSettings( sal_True, sal_False, sal_False ); 2174 ImplCalcMetrics(); 2175 Invalidate(); 2176 } 2177 else if ( nType == STATE_CHANGE_CONTROLFOREGROUND ) 2178 { 2179 ImplInitSettings( sal_False, sal_True, sal_False ); 2180 Invalidate(); 2181 } 2182 else if ( nType == STATE_CHANGE_CONTROLBACKGROUND ) 2183 { 2184 ImplInitSettings( sal_False, sal_False, sal_True ); 2185 Invalidate(); 2186 } 2187 ImplClearLayoutData(); 2188 } 2189 2190 // ----------------------------------------------------------------------- 2191 2192 void ImplListBoxWindow::DataChanged( const DataChangedEvent& rDCEvt ) 2193 { 2194 Control::DataChanged( rDCEvt ); 2195 2196 if ( (rDCEvt.GetType() == DATACHANGED_FONTS) || 2197 (rDCEvt.GetType() == DATACHANGED_FONTSUBSTITUTION) || 2198 ((rDCEvt.GetType() == DATACHANGED_SETTINGS) && 2199 (rDCEvt.GetFlags() & SETTINGS_STYLE)) ) 2200 { 2201 ImplClearLayoutData(); 2202 ImplInitSettings( sal_True, sal_True, sal_True ); 2203 ImplCalcMetrics(); 2204 Invalidate(); 2205 } 2206 } 2207 2208 // ----------------------------------------------------------------------- 2209 2210 sal_uInt16 ImplListBoxWindow::ImplGetTextStyle() const 2211 { 2212 sal_uInt16 nTextStyle = TEXT_DRAW_VCENTER; 2213 2214 if ( mpEntryList->HasImages() ) 2215 nTextStyle |= TEXT_DRAW_LEFT; 2216 else if ( mbCenter ) 2217 nTextStyle |= TEXT_DRAW_CENTER; 2218 else if ( mbRight ) 2219 nTextStyle |= TEXT_DRAW_RIGHT; 2220 else 2221 nTextStyle |= TEXT_DRAW_LEFT; 2222 2223 return nTextStyle; 2224 } 2225 2226 // ======================================================================= 2227 2228 ImplListBox::ImplListBox( Window* pParent, WinBits nWinStyle ) : 2229 Control( pParent, nWinStyle ), 2230 maLBWindow( this, nWinStyle&(~WB_BORDER) ) 2231 { 2232 // for native widget rendering we must be able to detect this window type 2233 SetType( WINDOW_LISTBOXWINDOW ); 2234 2235 mpVScrollBar = new ScrollBar( this, WB_VSCROLL | WB_DRAG ); 2236 mpHScrollBar = new ScrollBar( this, WB_HSCROLL | WB_DRAG ); 2237 mpScrollBarBox = new ScrollBarBox( this ); 2238 2239 Link aLink( LINK( this, ImplListBox, ScrollBarHdl ) ); 2240 mpVScrollBar->SetScrollHdl( aLink ); 2241 mpHScrollBar->SetScrollHdl( aLink ); 2242 2243 mbVScroll = sal_False; 2244 mbHScroll = sal_False; 2245 mbAutoHScroll = ( nWinStyle & WB_AUTOHSCROLL ) ? sal_True : sal_False; 2246 2247 maLBWindow.SetScrollHdl( LINK( this, ImplListBox, LBWindowScrolled ) ); 2248 maLBWindow.SetMRUChangedHdl( LINK( this, ImplListBox, MRUChanged ) ); 2249 maLBWindow.Show(); 2250 } 2251 2252 // ----------------------------------------------------------------------- 2253 2254 ImplListBox::~ImplListBox() 2255 { 2256 delete mpHScrollBar; 2257 delete mpVScrollBar; 2258 delete mpScrollBarBox; 2259 } 2260 2261 // ----------------------------------------------------------------------- 2262 2263 void ImplListBox::Clear() 2264 { 2265 maLBWindow.Clear(); 2266 if ( GetEntryList()->GetMRUCount() ) 2267 { 2268 maLBWindow.GetEntryList()->SetMRUCount( 0 ); 2269 maLBWindow.SetSeparatorPos( LISTBOX_ENTRY_NOTFOUND ); 2270 } 2271 mpVScrollBar->SetThumbPos( 0 ); 2272 mpHScrollBar->SetThumbPos( 0 ); 2273 StateChanged( STATE_CHANGE_DATA ); 2274 } 2275 2276 // ----------------------------------------------------------------------- 2277 2278 sal_uInt16 ImplListBox::InsertEntry( sal_uInt16 nPos, const XubString& rStr ) 2279 { 2280 ImplEntryType* pNewEntry = new ImplEntryType( rStr ); 2281 sal_uInt16 nNewPos = maLBWindow.InsertEntry( nPos, pNewEntry ); 2282 StateChanged( STATE_CHANGE_DATA ); 2283 return nNewPos; 2284 } 2285 2286 // ----------------------------------------------------------------------- 2287 2288 sal_uInt16 ImplListBox::InsertEntry( sal_uInt16 nPos, const Image& rImage ) 2289 { 2290 ImplEntryType* pNewEntry = new ImplEntryType( rImage ); 2291 sal_uInt16 nNewPos = maLBWindow.InsertEntry( nPos, pNewEntry ); 2292 StateChanged( STATE_CHANGE_DATA ); 2293 return nNewPos; 2294 } 2295 2296 // ----------------------------------------------------------------------- 2297 2298 sal_uInt16 ImplListBox::InsertEntry( sal_uInt16 nPos, const XubString& rStr, const Image& rImage ) 2299 { 2300 ImplEntryType* pNewEntry = new ImplEntryType( rStr, rImage ); 2301 sal_uInt16 nNewPos = maLBWindow.InsertEntry( nPos, pNewEntry ); 2302 StateChanged( STATE_CHANGE_DATA ); 2303 return nNewPos; 2304 } 2305 2306 // ----------------------------------------------------------------------- 2307 2308 void ImplListBox::RemoveEntry( sal_uInt16 nPos ) 2309 { 2310 maLBWindow.RemoveEntry( nPos ); 2311 StateChanged( STATE_CHANGE_DATA ); 2312 } 2313 2314 // ----------------------------------------------------------------------- 2315 2316 void ImplListBox::SetEntryFlags( sal_uInt16 nPos, long nFlags ) 2317 { 2318 maLBWindow.SetEntryFlags( nPos, nFlags ); 2319 } 2320 2321 // ----------------------------------------------------------------------- 2322 2323 long ImplListBox::GetEntryFlags( sal_uInt16 nPos ) const 2324 { 2325 return maLBWindow.GetEntryList()->GetEntryFlags( nPos ); 2326 } 2327 2328 // ----------------------------------------------------------------------- 2329 2330 void ImplListBox::SelectEntry( sal_uInt16 nPos, sal_Bool bSelect ) 2331 { 2332 maLBWindow.SelectEntry( nPos, bSelect ); 2333 } 2334 2335 // ----------------------------------------------------------------------- 2336 2337 void ImplListBox::SetNoSelection() 2338 { 2339 maLBWindow.DeselectAll(); 2340 } 2341 2342 // ----------------------------------------------------------------------- 2343 2344 void ImplListBox::GetFocus() 2345 { 2346 maLBWindow.GrabFocus(); 2347 } 2348 2349 // ----------------------------------------------------------------------- 2350 2351 Window* ImplListBox::GetPreferredKeyInputWindow() 2352 { 2353 return &maLBWindow; 2354 } 2355 2356 // ----------------------------------------------------------------------- 2357 2358 void ImplListBox::Resize() 2359 { 2360 Control::Resize(); 2361 ImplResizeControls(); 2362 ImplCheckScrollBars(); 2363 } 2364 2365 2366 // ----------------------------------------------------------------------- 2367 2368 IMPL_LINK( ImplListBox, MRUChanged, void*, EMPTYARG ) 2369 { 2370 StateChanged( STATE_CHANGE_DATA ); 2371 return 1; 2372 } 2373 2374 // ----------------------------------------------------------------------- 2375 2376 IMPL_LINK( ImplListBox, LBWindowScrolled, void*, EMPTYARG ) 2377 { 2378 long nSet = GetTopEntry(); 2379 if( nSet > mpVScrollBar->GetRangeMax() ) 2380 mpVScrollBar->SetRangeMax( GetEntryList()->GetEntryCount() ); 2381 mpVScrollBar->SetThumbPos( GetTopEntry() ); 2382 2383 mpHScrollBar->SetThumbPos( GetLeftIndent() ); 2384 2385 maScrollHdl.Call( this ); 2386 2387 return 1; 2388 } 2389 2390 // ----------------------------------------------------------------------- 2391 2392 IMPL_LINK( ImplListBox, ScrollBarHdl, ScrollBar*, pSB ) 2393 { 2394 sal_uInt16 nPos = (sal_uInt16) pSB->GetThumbPos(); 2395 if( pSB == mpVScrollBar ) 2396 SetTopEntry( nPos ); 2397 else if( pSB == mpHScrollBar ) 2398 SetLeftIndent( nPos ); 2399 2400 return 1; 2401 } 2402 2403 // ----------------------------------------------------------------------- 2404 2405 void ImplListBox::ImplCheckScrollBars() 2406 { 2407 sal_Bool bArrange = sal_False; 2408 2409 Size aOutSz = GetOutputSizePixel(); 2410 sal_uInt16 nEntries = GetEntryList()->GetEntryCount(); 2411 sal_uInt16 nMaxVisEntries = (sal_uInt16) (aOutSz.Height() / GetEntryHeight()); 2412 2413 // vert. ScrollBar 2414 if( nEntries > nMaxVisEntries ) 2415 { 2416 if( !mbVScroll ) 2417 bArrange = sal_True; 2418 mbVScroll = sal_True; 2419 2420 // Ueberpruefung des rausgescrollten Bereichs 2421 if( GetEntryList()->GetSelectEntryCount() == 1 && 2422 GetEntryList()->GetSelectEntryPos( 0 ) != LISTBOX_ENTRY_NOTFOUND ) 2423 ShowProminentEntry( GetEntryList()->GetSelectEntryPos( 0 ) ); 2424 else 2425 SetTopEntry( GetTopEntry() ); // MaxTop wird geprueft... 2426 } 2427 else 2428 { 2429 if( mbVScroll ) 2430 bArrange = sal_True; 2431 mbVScroll = sal_False; 2432 SetTopEntry( 0 ); 2433 } 2434 2435 // horz. ScrollBar 2436 if( mbAutoHScroll ) 2437 { 2438 long nWidth = (sal_uInt16) aOutSz.Width(); 2439 if ( mbVScroll ) 2440 nWidth -= mpVScrollBar->GetSizePixel().Width(); 2441 2442 long nMaxWidth = GetMaxEntryWidth(); 2443 if( nWidth < nMaxWidth ) 2444 { 2445 if( !mbHScroll ) 2446 bArrange = sal_True; 2447 mbHScroll = sal_True; 2448 2449 if ( !mbVScroll ) // ggf. brauchen wir jetzt doch einen 2450 { 2451 nMaxVisEntries = (sal_uInt16) ( ( aOutSz.Height() - mpHScrollBar->GetSizePixel().Height() ) / GetEntryHeight() ); 2452 if( nEntries > nMaxVisEntries ) 2453 { 2454 bArrange = sal_True; 2455 mbVScroll = sal_True; 2456 2457 // Ueberpruefung des rausgescrollten Bereichs 2458 if( GetEntryList()->GetSelectEntryCount() == 1 && 2459 GetEntryList()->GetSelectEntryPos( 0 ) != LISTBOX_ENTRY_NOTFOUND ) 2460 ShowProminentEntry( GetEntryList()->GetSelectEntryPos( 0 ) ); 2461 else 2462 SetTopEntry( GetTopEntry() ); // MaxTop wird geprueft... 2463 } 2464 } 2465 2466 // Ueberpruefung des rausgescrollten Bereichs 2467 sal_uInt16 nMaxLI = (sal_uInt16) (nMaxWidth - nWidth); 2468 if ( nMaxLI < GetLeftIndent() ) 2469 SetLeftIndent( nMaxLI ); 2470 } 2471 else 2472 { 2473 if( mbHScroll ) 2474 bArrange = sal_True; 2475 mbHScroll = sal_False; 2476 SetLeftIndent( 0 ); 2477 } 2478 } 2479 2480 if( bArrange ) 2481 ImplResizeControls(); 2482 2483 ImplInitScrollBars(); 2484 } 2485 2486 // ----------------------------------------------------------------------- 2487 2488 void ImplListBox::ImplInitScrollBars() 2489 { 2490 Size aOutSz = maLBWindow.GetOutputSizePixel(); 2491 2492 if ( mbVScroll ) 2493 { 2494 sal_uInt16 nEntries = GetEntryList()->GetEntryCount(); 2495 sal_uInt16 nVisEntries = (sal_uInt16) (aOutSz.Height() / GetEntryHeight()); 2496 mpVScrollBar->SetRangeMax( nEntries ); 2497 mpVScrollBar->SetVisibleSize( nVisEntries ); 2498 mpVScrollBar->SetPageSize( nVisEntries - 1 ); 2499 } 2500 2501 if ( mbHScroll ) 2502 { 2503 mpHScrollBar->SetRangeMax( GetMaxEntryWidth() + HORZ_SCROLL ); 2504 mpHScrollBar->SetVisibleSize( (sal_uInt16)aOutSz.Width() ); 2505 mpHScrollBar->SetLineSize( HORZ_SCROLL ); 2506 mpHScrollBar->SetPageSize( aOutSz.Width() - HORZ_SCROLL ); 2507 } 2508 } 2509 2510 // ----------------------------------------------------------------------- 2511 2512 void ImplListBox::ImplResizeControls() 2513 { 2514 // Hier werden die Controls nur angeordnet, ob die Scrollbars 2515 // sichtbar sein sollen wird bereits in ImplCheckScrollBars ermittelt. 2516 2517 Size aOutSz = GetOutputSizePixel(); 2518 long nSBWidth = GetSettings().GetStyleSettings().GetScrollBarSize(); 2519 nSBWidth = CalcZoom( nSBWidth ); 2520 2521 Size aInnerSz( aOutSz ); 2522 if ( mbVScroll ) 2523 aInnerSz.Width() -= nSBWidth; 2524 if ( mbHScroll ) 2525 aInnerSz.Height() -= nSBWidth; 2526 2527 // pb: #106948# explicit mirroring for calc 2528 // Scrollbar on left or right side? 2529 sal_Bool bMirroring = maLBWindow.IsMirroring(); 2530 Point aWinPos( bMirroring && mbVScroll ? nSBWidth : 0, 0 ); 2531 maLBWindow.SetPosSizePixel( aWinPos, aInnerSz ); 2532 2533 // ScrollBarBox 2534 if( mbVScroll && mbHScroll ) 2535 { 2536 Point aBoxPos( bMirroring ? 0 : aInnerSz.Width(), aInnerSz.Height() ); 2537 mpScrollBarBox->SetPosSizePixel( aBoxPos, Size( nSBWidth, nSBWidth ) ); 2538 mpScrollBarBox->Show(); 2539 } 2540 else 2541 { 2542 mpScrollBarBox->Hide(); 2543 } 2544 2545 // vert. ScrollBar 2546 if( mbVScroll ) 2547 { 2548 // Scrollbar on left or right side? 2549 Point aVPos( bMirroring ? 0 : aOutSz.Width() - nSBWidth, 0 ); 2550 mpVScrollBar->SetPosSizePixel( aVPos, Size( nSBWidth, aInnerSz.Height() ) ); 2551 mpVScrollBar->Show(); 2552 } 2553 else 2554 { 2555 mpVScrollBar->Hide(); 2556 // #107254# Don't reset top entry after resize, but check for max top entry 2557 SetTopEntry( GetTopEntry() ); 2558 } 2559 2560 // horz. ScrollBar 2561 if( mbHScroll ) 2562 { 2563 Point aHPos( ( bMirroring && mbVScroll ) ? nSBWidth : 0, aOutSz.Height() - nSBWidth ); 2564 mpHScrollBar->SetPosSizePixel( aHPos, Size( aInnerSz.Width(), nSBWidth ) ); 2565 mpHScrollBar->Show(); 2566 } 2567 else 2568 { 2569 mpHScrollBar->Hide(); 2570 SetLeftIndent( 0 ); 2571 } 2572 } 2573 2574 // ----------------------------------------------------------------------- 2575 2576 void ImplListBox::StateChanged( StateChangedType nType ) 2577 { 2578 if ( nType == STATE_CHANGE_INITSHOW ) 2579 { 2580 ImplCheckScrollBars(); 2581 } 2582 else if ( ( nType == STATE_CHANGE_UPDATEMODE ) || ( nType == STATE_CHANGE_DATA ) ) 2583 { 2584 sal_Bool bUpdate = IsUpdateMode(); 2585 maLBWindow.SetUpdateMode( bUpdate ); 2586 // mpHScrollBar->SetUpdateMode( bUpdate ); 2587 // mpVScrollBar->SetUpdateMode( bUpdate ); 2588 if ( bUpdate && IsReallyVisible() ) 2589 ImplCheckScrollBars(); 2590 } 2591 else if( nType == STATE_CHANGE_ENABLE ) 2592 { 2593 mpHScrollBar->Enable( IsEnabled() ); 2594 mpVScrollBar->Enable( IsEnabled() ); 2595 mpScrollBarBox->Enable( IsEnabled() ); 2596 Invalidate(); 2597 } 2598 else if ( nType == STATE_CHANGE_ZOOM ) 2599 { 2600 maLBWindow.SetZoom( GetZoom() ); 2601 Resize(); 2602 } 2603 else if ( nType == STATE_CHANGE_CONTROLFONT ) 2604 { 2605 maLBWindow.SetControlFont( GetControlFont() ); 2606 } 2607 else if ( nType == STATE_CHANGE_CONTROLFOREGROUND ) 2608 { 2609 maLBWindow.SetControlForeground( GetControlForeground() ); 2610 } 2611 else if ( nType == STATE_CHANGE_CONTROLBACKGROUND ) 2612 { 2613 maLBWindow.SetControlBackground( GetControlBackground() ); 2614 } 2615 else if( nType == STATE_CHANGE_MIRRORING ) 2616 { 2617 maLBWindow.EnableRTL( IsRTLEnabled() ); 2618 mpHScrollBar->EnableRTL( IsRTLEnabled() ); 2619 mpVScrollBar->EnableRTL( IsRTLEnabled() ); 2620 ImplResizeControls(); 2621 } 2622 2623 Control::StateChanged( nType ); 2624 } 2625 2626 // ----------------------------------------------------------------------- 2627 2628 void ImplListBox::DataChanged( const DataChangedEvent& rDCEvt ) 2629 { 2630 // if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) && 2631 // (rDCEvt.GetFlags() & SETTINGS_STYLE) ) 2632 // { 2633 // maLBWindow.SetSettings( GetSettings() ); 2634 // Resize(); 2635 // } 2636 // else 2637 Control::DataChanged( rDCEvt ); 2638 } 2639 2640 // ----------------------------------------------------------------------- 2641 2642 long ImplListBox::Notify( NotifyEvent& rNEvt ) 2643 { 2644 long nDone = 0; 2645 if ( rNEvt.GetType() == EVENT_COMMAND ) 2646 { 2647 const CommandEvent& rCEvt = *rNEvt.GetCommandEvent(); 2648 if ( rCEvt.GetCommand() == COMMAND_WHEEL ) 2649 { 2650 const CommandWheelData* pData = rCEvt.GetWheelData(); 2651 if( !pData->GetModifier() && ( pData->GetMode() == COMMAND_WHEEL_SCROLL ) ) 2652 { 2653 nDone = HandleScrollCommand( rCEvt, mpHScrollBar, mpVScrollBar ); 2654 } 2655 } 2656 } 2657 2658 return nDone ? nDone : Window::Notify( rNEvt ); 2659 } 2660 2661 // ----------------------------------------------------------------------- 2662 2663 const Wallpaper& ImplListBox::GetDisplayBackground() const 2664 { 2665 return maLBWindow.GetDisplayBackground(); 2666 } 2667 2668 // ----------------------------------------------------------------------- 2669 2670 sal_Bool ImplListBox::HandleWheelAsCursorTravel( const CommandEvent& rCEvt ) 2671 { 2672 sal_Bool bDone = sal_False; 2673 if ( rCEvt.GetCommand() == COMMAND_WHEEL ) 2674 { 2675 const CommandWheelData* pData = rCEvt.GetWheelData(); 2676 if( !pData->GetModifier() && ( pData->GetMode() == COMMAND_WHEEL_SCROLL ) ) 2677 { 2678 sal_uInt16 nKey = ( pData->GetDelta() < 0 ) ? KEY_DOWN : KEY_UP; 2679 KeyEvent aKeyEvent( 0, KeyCode( nKey ) ); 2680 bDone = ProcessKeyInput( aKeyEvent ); 2681 } 2682 } 2683 return bDone; 2684 } 2685 2686 // ----------------------------------------------------------------------- 2687 2688 void ImplListBox::SetMRUEntries( const XubString& rEntries, xub_Unicode cSep ) 2689 { 2690 sal_Bool bChanges = GetEntryList()->GetMRUCount() ? sal_True : sal_False; 2691 2692 // Remove old MRU entries 2693 for ( sal_uInt16 n = GetEntryList()->GetMRUCount();n; ) 2694 maLBWindow.RemoveEntry( --n ); 2695 2696 sal_uInt16 nMRUCount = 0; 2697 sal_uInt16 nEntries = rEntries.GetTokenCount( cSep ); 2698 for ( sal_uInt16 nEntry = 0; nEntry < nEntries; nEntry++ ) 2699 { 2700 XubString aEntry = rEntries.GetToken( nEntry, cSep ); 2701 // Accept only existing entries 2702 if ( GetEntryList()->FindEntry( aEntry ) != LISTBOX_ENTRY_NOTFOUND ) 2703 { 2704 ImplEntryType* pNewEntry = new ImplEntryType( aEntry ); 2705 maLBWindow.GetEntryList()->InsertEntry( nMRUCount++, pNewEntry, sal_False ); 2706 bChanges = sal_True; 2707 } 2708 } 2709 2710 if ( bChanges ) 2711 { 2712 maLBWindow.GetEntryList()->SetMRUCount( nMRUCount ); 2713 SetSeparatorPos( nMRUCount ? nMRUCount-1 : 0 ); 2714 StateChanged( STATE_CHANGE_DATA ); 2715 } 2716 } 2717 2718 // ----------------------------------------------------------------------- 2719 2720 XubString ImplListBox::GetMRUEntries( xub_Unicode cSep ) const 2721 { 2722 String aEntries; 2723 for ( sal_uInt16 n = 0; n < GetEntryList()->GetMRUCount(); n++ ) 2724 { 2725 aEntries += GetEntryList()->GetEntryText( n ); 2726 if( n < ( GetEntryList()->GetMRUCount() - 1 ) ) 2727 aEntries += cSep; 2728 } 2729 return aEntries; 2730 } 2731 2732 // ======================================================================= 2733 2734 ImplWin::ImplWin( Window* pParent, WinBits nWinStyle ) : 2735 Control ( pParent, nWinStyle ) 2736 { 2737 if ( IsNativeControlSupported(CTRL_LISTBOX, PART_ENTIRE_CONTROL) 2738 && ! IsNativeControlSupported(CTRL_LISTBOX, PART_BUTTON_DOWN) ) 2739 SetBackground(); 2740 else 2741 SetBackground( Wallpaper( GetSettings().GetStyleSettings().GetFieldColor() ) ); 2742 2743 mbInUserDraw = sal_False; 2744 mbUserDrawEnabled = sal_False; 2745 mnItemPos = LISTBOX_ENTRY_NOTFOUND; 2746 } 2747 2748 // ----------------------------------------------------------------------- 2749 2750 sal_Bool ImplWin::SetModeImage( const Image& rImage, BmpColorMode eMode ) 2751 { 2752 if( eMode == BMP_COLOR_NORMAL ) 2753 SetImage( rImage ); 2754 else if( eMode == BMP_COLOR_HIGHCONTRAST ) 2755 maImageHC = rImage; 2756 else 2757 return sal_False; 2758 return sal_True; 2759 } 2760 2761 // ----------------------------------------------------------------------- 2762 2763 const Image& ImplWin::GetModeImage( BmpColorMode eMode ) const 2764 { 2765 if( eMode == BMP_COLOR_HIGHCONTRAST ) 2766 return maImageHC; 2767 else 2768 return maImage; 2769 } 2770 2771 // ----------------------------------------------------------------------- 2772 2773 void ImplWin::MBDown() 2774 { 2775 if( IsEnabled() ) 2776 maMBDownHdl.Call( this ); 2777 } 2778 2779 // ----------------------------------------------------------------------- 2780 2781 void ImplWin::MouseButtonDown( const MouseEvent& ) 2782 { 2783 if( IsEnabled() ) 2784 { 2785 // Control::MouseButtonDown( rMEvt ); 2786 MBDown(); 2787 } 2788 } 2789 2790 // ----------------------------------------------------------------------- 2791 2792 void ImplWin::FillLayoutData() const 2793 { 2794 mpControlData->mpLayoutData = new vcl::ControlLayoutData(); 2795 const_cast<ImplWin*>(this)->ImplDraw( true ); 2796 } 2797 2798 // ----------------------------------------------------------------------- 2799 2800 long ImplWin::PreNotify( NotifyEvent& rNEvt ) 2801 { 2802 long nDone = 0; 2803 const MouseEvent* pMouseEvt = NULL; 2804 2805 if( (rNEvt.GetType() == EVENT_MOUSEMOVE) && (pMouseEvt = rNEvt.GetMouseEvent()) != NULL ) 2806 { 2807 if( pMouseEvt->IsEnterWindow() || pMouseEvt->IsLeaveWindow() ) 2808 { 2809 // trigger redraw as mouse over state has changed 2810 if ( IsNativeControlSupported(CTRL_LISTBOX, PART_ENTIRE_CONTROL) 2811 && ! IsNativeControlSupported(CTRL_LISTBOX, PART_BUTTON_DOWN) ) 2812 { 2813 GetParent()->GetWindow( WINDOW_BORDER )->Invalidate( INVALIDATE_NOERASE ); 2814 GetParent()->GetWindow( WINDOW_BORDER )->Update(); 2815 } 2816 } 2817 } 2818 2819 return nDone ? nDone : Control::PreNotify(rNEvt); 2820 } 2821 2822 // ----------------------------------------------------------------------- 2823 2824 void ImplWin::ImplDraw( bool bLayout ) 2825 { 2826 const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings(); 2827 2828 sal_Bool bNativeOK = sal_False; 2829 2830 if( ! bLayout ) 2831 { 2832 ControlState nState = CTRL_STATE_ENABLED; 2833 if ( IsNativeControlSupported(CTRL_LISTBOX, PART_ENTIRE_CONTROL) 2834 && IsNativeControlSupported(CTRL_LISTBOX, HAS_BACKGROUND_TEXTURE) ) 2835 { 2836 // Repaint the (focused) area similarly to 2837 // ImplSmallBorderWindowView::DrawWindow() in 2838 // vcl/source/window/brdwin.cxx 2839 Window *pWin = GetParent(); 2840 2841 ImplControlValue aControlValue; 2842 if ( !pWin->IsEnabled() ) 2843 nState &= ~CTRL_STATE_ENABLED; 2844 if ( pWin->HasFocus() ) 2845 nState |= CTRL_STATE_FOCUSED; 2846 2847 // The listbox is painted over the entire control including the 2848 // border, but ImplWin does not contain the border => correction 2849 // needed. 2850 sal_Int32 nLeft, nTop, nRight, nBottom; 2851 pWin->GetBorder( nLeft, nTop, nRight, nBottom ); 2852 Point aPoint( -nLeft, -nTop ); 2853 Rectangle aCtrlRegion( aPoint - GetPosPixel(), pWin->GetSizePixel() ); 2854 2855 sal_Bool bMouseOver = sal_False; 2856 if( GetParent() ) 2857 { 2858 Window *pChild = GetParent()->GetWindow( WINDOW_FIRSTCHILD ); 2859 while( pChild && (bMouseOver = pChild->IsMouseOver()) == sal_False ) 2860 pChild = pChild->GetWindow( WINDOW_NEXT ); 2861 } 2862 2863 if( bMouseOver ) 2864 nState |= CTRL_STATE_ROLLOVER; 2865 2866 // if parent has no border, then nobody has drawn the background 2867 // since no border window exists. so draw it here. 2868 WinBits nParentStyle = pWin->GetStyle(); 2869 if( ! (nParentStyle & WB_BORDER) || (nParentStyle & WB_NOBORDER) ) 2870 { 2871 Rectangle aParentRect( Point( 0, 0 ), pWin->GetSizePixel() ); 2872 pWin->DrawNativeControl( CTRL_LISTBOX, PART_ENTIRE_CONTROL, aParentRect, 2873 nState, aControlValue, rtl::OUString() ); 2874 } 2875 2876 bNativeOK = DrawNativeControl( CTRL_LISTBOX, PART_ENTIRE_CONTROL, aCtrlRegion, nState, 2877 aControlValue, rtl::OUString() ); 2878 } 2879 2880 if( IsEnabled() ) 2881 { 2882 if( HasFocus() ) 2883 { 2884 SetTextColor( rStyleSettings.GetHighlightTextColor() ); 2885 SetFillColor( rStyleSettings.GetHighlightColor() ); 2886 DrawRect( maFocusRect ); 2887 } 2888 else 2889 { 2890 Color aColor; 2891 if( bNativeOK && (nState & CTRL_STATE_ROLLOVER) ) 2892 aColor = rStyleSettings.GetFieldRolloverTextColor(); 2893 else 2894 aColor = rStyleSettings.GetFieldTextColor(); 2895 if( IsControlForeground() ) 2896 aColor = GetControlForeground(); 2897 SetTextColor( aColor ); 2898 if ( !bNativeOK ) 2899 Erase( maFocusRect ); 2900 } 2901 } 2902 else // Disabled 2903 { 2904 SetTextColor( rStyleSettings.GetDisableColor() ); 2905 if ( !bNativeOK ) 2906 Erase( maFocusRect ); 2907 } 2908 } 2909 2910 if ( IsUserDrawEnabled() ) 2911 { 2912 mbInUserDraw = sal_True; 2913 UserDrawEvent aUDEvt( this, maFocusRect, mnItemPos, 0 ); 2914 maUserDrawHdl.Call( &aUDEvt ); 2915 mbInUserDraw = sal_False; 2916 } 2917 else 2918 { 2919 DrawEntry( sal_True, sal_True, sal_False, bLayout ); 2920 } 2921 } 2922 2923 // ----------------------------------------------------------------------- 2924 2925 void ImplWin::Paint( const Rectangle& ) 2926 { 2927 ImplDraw(); 2928 } 2929 2930 // ----------------------------------------------------------------------- 2931 2932 void ImplWin::DrawEntry( sal_Bool bDrawImage, sal_Bool bDrawText, sal_Bool bDrawTextAtImagePos, bool bLayout ) 2933 { 2934 long nBorder = 1; 2935 Size aOutSz = GetOutputSizePixel(); 2936 2937 sal_Bool bImage = !!maImage; 2938 if( bDrawImage && bImage && !bLayout ) 2939 { 2940 sal_uInt16 nStyle = 0; 2941 Size aImgSz = maImage.GetSizePixel(); 2942 Point aPtImg( nBorder, ( ( aOutSz.Height() - aImgSz.Height() ) / 2 ) ); 2943 2944 // check for HC mode 2945 Image *pImage = &maImage; 2946 2947 if( !!maImageHC ) 2948 { 2949 if( GetSettings().GetStyleSettings().GetHighContrastMode() ) 2950 pImage = &maImageHC; 2951 } 2952 2953 if ( !IsZoom() ) 2954 { 2955 DrawImage( aPtImg, *pImage, nStyle ); 2956 } 2957 else 2958 { 2959 aImgSz.Width() = CalcZoom( aImgSz.Width() ); 2960 aImgSz.Height() = CalcZoom( aImgSz.Height() ); 2961 DrawImage( aPtImg, aImgSz, *pImage, nStyle ); 2962 } 2963 } 2964 2965 if( bDrawText && maString.Len() ) 2966 { 2967 sal_uInt16 nTextStyle = TEXT_DRAW_VCENTER; 2968 2969 if ( bDrawImage && bImage && !bLayout ) 2970 nTextStyle |= TEXT_DRAW_LEFT; 2971 else if ( GetStyle() & WB_CENTER ) 2972 nTextStyle |= TEXT_DRAW_CENTER; 2973 else if ( GetStyle() & WB_RIGHT ) 2974 nTextStyle |= TEXT_DRAW_RIGHT; 2975 else 2976 nTextStyle |= TEXT_DRAW_LEFT; 2977 2978 Rectangle aTextRect( Point( nBorder, 0 ), Size( aOutSz.Width()-2*nBorder, aOutSz.Height() ) ); 2979 2980 if ( !bDrawTextAtImagePos && ( bImage || IsUserDrawEnabled() ) ) 2981 { 2982 long nMaxWidth = Max( maImage.GetSizePixel().Width(), maUserItemSize.Width() ); 2983 aTextRect.Left() += nMaxWidth + IMG_TXT_DISTANCE; 2984 } 2985 2986 MetricVector* pVector = bLayout ? &mpControlData->mpLayoutData->m_aUnicodeBoundRects : NULL; 2987 String* pDisplayText = bLayout ? &mpControlData->mpLayoutData->m_aDisplayText : NULL; 2988 DrawText( aTextRect, maString, nTextStyle, pVector, pDisplayText ); 2989 } 2990 2991 if( HasFocus() && !bLayout ) 2992 ShowFocus( maFocusRect ); 2993 } 2994 2995 // ----------------------------------------------------------------------- 2996 2997 void ImplWin::Resize() 2998 { 2999 Control::Resize(); 3000 maFocusRect.SetSize( GetOutputSizePixel() ); 3001 Invalidate(); 3002 } 3003 3004 // ----------------------------------------------------------------------- 3005 3006 void ImplWin::GetFocus() 3007 { 3008 ShowFocus( maFocusRect ); 3009 if( ImplGetSVData()->maNWFData.mbNoFocusRects && 3010 IsNativeWidgetEnabled() && 3011 IsNativeControlSupported( CTRL_LISTBOX, PART_ENTIRE_CONTROL ) ) 3012 { 3013 Window* pWin = GetParent()->GetWindow( WINDOW_BORDER ); 3014 if( ! pWin ) 3015 pWin = GetParent(); 3016 pWin->Invalidate(); 3017 } 3018 else 3019 Invalidate(); 3020 Control::GetFocus(); 3021 } 3022 3023 // ----------------------------------------------------------------------- 3024 3025 void ImplWin::LoseFocus() 3026 { 3027 HideFocus(); 3028 if( ImplGetSVData()->maNWFData.mbNoFocusRects && 3029 IsNativeWidgetEnabled() && 3030 IsNativeControlSupported( CTRL_LISTBOX, PART_ENTIRE_CONTROL ) ) 3031 { 3032 Window* pWin = GetParent()->GetWindow( WINDOW_BORDER ); 3033 if( ! pWin ) 3034 pWin = GetParent(); 3035 pWin->Invalidate(); 3036 } 3037 else 3038 Invalidate(); 3039 Control::LoseFocus(); 3040 } 3041 3042 // ======================================================================= 3043 3044 ImplBtn::ImplBtn( Window* pParent, WinBits nWinStyle ) : 3045 PushButton( pParent, nWinStyle ), 3046 mbDown ( sal_False ) 3047 { 3048 } 3049 3050 // ----------------------------------------------------------------------- 3051 3052 void ImplBtn::MBDown() 3053 { 3054 if( IsEnabled() ) 3055 maMBDownHdl.Call( this ); 3056 } 3057 3058 // ----------------------------------------------------------------------- 3059 3060 void ImplBtn::MouseButtonDown( const MouseEvent& ) 3061 { 3062 //PushButton::MouseButtonDown( rMEvt ); 3063 if( IsEnabled() ) 3064 { 3065 MBDown(); 3066 mbDown = sal_True; 3067 } 3068 } 3069 3070 // ======================================================================= 3071 3072 ImplListBoxFloatingWindow::ImplListBoxFloatingWindow( Window* pParent ) : 3073 FloatingWindow( pParent, WB_BORDER | WB_SYSTEMWINDOW | WB_NOSHADOW ) // no drop shadow for list boxes 3074 { 3075 mpImplLB = NULL; 3076 mnDDLineCount = 0; 3077 mbAutoWidth = sal_False; 3078 3079 mnPopupModeStartSaveSelection = LISTBOX_ENTRY_NOTFOUND; 3080 3081 EnableSaveBackground(); 3082 3083 Window * pBorderWindow = ImplGetBorderWindow(); 3084 if( pBorderWindow ) 3085 { 3086 SetAccessibleRole(accessibility::AccessibleRole::PANEL); 3087 pBorderWindow->SetAccessibleRole(accessibility::AccessibleRole::WINDOW); 3088 } 3089 else 3090 { 3091 SetAccessibleRole(accessibility::AccessibleRole::WINDOW); 3092 } 3093 3094 } 3095 3096 // ----------------------------------------------------------------------- 3097 3098 long ImplListBoxFloatingWindow::PreNotify( NotifyEvent& rNEvt ) 3099 { 3100 if( rNEvt.GetType() == EVENT_LOSEFOCUS ) 3101 { 3102 if( !GetParent()->HasChildPathFocus( sal_True ) ) 3103 EndPopupMode(); 3104 } 3105 3106 return FloatingWindow::PreNotify( rNEvt ); 3107 } 3108 3109 // ----------------------------------------------------------------------- 3110 3111 void ImplListBoxFloatingWindow::SetPosSizePixel( long nX, long nY, long nWidth, long nHeight, sal_uInt16 nFlags ) 3112 { 3113 FloatingWindow::SetPosSizePixel( nX, nY, nWidth, nHeight, nFlags ); 3114 3115 // Fix #60890# ( MBA ): um auch im aufgeklappten Zustand der Listbox die Gr"o\se einfach zu einen 3116 // Aufruf von Resize() "andern zu k"onnen, wird die Position hier ggf. angepa\t 3117 if ( IsReallyVisible() && ( nFlags & WINDOW_POSSIZE_HEIGHT ) ) 3118 { 3119 Point aPos = GetParent()->GetPosPixel(); 3120 aPos = GetParent()->GetParent()->OutputToScreenPixel( aPos ); 3121 3122 if ( nFlags & WINDOW_POSSIZE_X ) 3123 aPos.X() = nX; 3124 3125 if ( nFlags & WINDOW_POSSIZE_Y ) 3126 aPos.Y() = nY; 3127 3128 sal_uInt16 nIndex; 3129 SetPosPixel( ImplCalcPos( this, Rectangle( aPos, GetParent()->GetSizePixel() ), FLOATWIN_POPUPMODE_DOWN, nIndex ) ); 3130 } 3131 3132 // if( !IsReallyVisible() ) 3133 { 3134 // Die ImplListBox erhaelt kein Resize, weil nicht sichtbar. 3135 // Die Fenster muessen aber ein Resize() erhalten, damit die 3136 // Anzahl der sichtbaren Eintraege fuer PgUp/PgDown stimmt. 3137 // Die Anzahl kann auch nicht von List/Combobox berechnet werden, 3138 // weil hierfuer auch die ggf. vorhandene vertikale Scrollbar 3139 // beruecksichtigt werden muss. 3140 mpImplLB->SetSizePixel( GetOutputSizePixel() ); 3141 ((Window*)mpImplLB)->Resize(); 3142 ((Window*)mpImplLB->GetMainWindow())->Resize(); 3143 } 3144 } 3145 3146 // ----------------------------------------------------------------------- 3147 3148 void ImplListBoxFloatingWindow::Resize() 3149 { 3150 mpImplLB->GetMainWindow()->ImplClearLayoutData(); 3151 FloatingWindow::Resize(); 3152 } 3153 3154 // ----------------------------------------------------------------------- 3155 3156 Size ImplListBoxFloatingWindow::CalcFloatSize() 3157 { 3158 Size aFloatSz( maPrefSz ); 3159 3160 sal_Int32 nLeft, nTop, nRight, nBottom; 3161 GetBorder( nLeft, nTop, nRight, nBottom ); 3162 3163 sal_uInt16 nLines = mpImplLB->GetEntryList()->GetEntryCount(); 3164 if ( mnDDLineCount && ( nLines > mnDDLineCount ) ) 3165 nLines = mnDDLineCount; 3166 3167 Size aSz = mpImplLB->CalcSize( nLines ); 3168 long nMaxHeight = aSz.Height() + nTop + nBottom; 3169 3170 if ( mnDDLineCount ) 3171 aFloatSz.Height() = nMaxHeight; 3172 3173 if( mbAutoWidth ) 3174 { 3175 // AutoSize erstmal nur fuer die Breite... 3176 3177 aFloatSz.Width() = aSz.Width() + nLeft + nRight; 3178 aFloatSz.Width() += nRight; // etwas mehr Platz sieht besser aus... 3179 3180 if ( ( aFloatSz.Height() < nMaxHeight ) || ( mnDDLineCount && ( mnDDLineCount < mpImplLB->GetEntryList()->GetEntryCount() ) ) ) 3181 { 3182 // dann wird noch der vertikale Scrollbar benoetigt 3183 long nSBWidth = GetSettings().GetStyleSettings().GetScrollBarSize(); 3184 aFloatSz.Width() += nSBWidth; 3185 } 3186 } 3187 3188 if ( aFloatSz.Height() > nMaxHeight ) 3189 aFloatSz.Height() = nMaxHeight; 3190 3191 // Minimale Hoehe, falls Hoehe nicht auf Float-Hoehe eingestellt wurde. 3192 // Der Parent vom FloatWin muss die DropDown-Combo/Listbox sein. 3193 Size aParentSz = GetParent()->GetSizePixel(); 3194 if( !mnDDLineCount && ( aFloatSz.Height() < aParentSz.Height() ) ) 3195 aFloatSz.Height() = aParentSz.Height(); 3196 3197 // Nicht schmaler als der Parent werden... 3198 if( aFloatSz.Width() < aParentSz.Width() ) 3199 aFloatSz.Width() = aParentSz.Width(); 3200 3201 // Hoehe auf Entries alignen... 3202 long nInnerHeight = aFloatSz.Height() - nTop - nBottom; 3203 long nEntryHeight = mpImplLB->GetEntryHeight(); 3204 if ( nInnerHeight % nEntryHeight ) 3205 { 3206 nInnerHeight /= nEntryHeight; 3207 nInnerHeight++; 3208 nInnerHeight *= nEntryHeight; 3209 aFloatSz.Height() = nInnerHeight + nTop + nBottom; 3210 } 3211 3212 return aFloatSz; 3213 } 3214 3215 // ----------------------------------------------------------------------- 3216 3217 void ImplListBoxFloatingWindow::StartFloat( sal_Bool bStartTracking ) 3218 { 3219 if( !IsInPopupMode() ) 3220 { 3221 Size aFloatSz = CalcFloatSize(); 3222 3223 SetSizePixel( aFloatSz ); 3224 mpImplLB->SetSizePixel( GetOutputSizePixel() ); 3225 3226 sal_uInt16 nPos = mpImplLB->GetEntryList()->GetSelectEntryPos( 0 ); 3227 mnPopupModeStartSaveSelection = nPos; 3228 3229 Size aSz = GetParent()->GetSizePixel(); 3230 Point aPos = GetParent()->GetPosPixel(); 3231 aPos = GetParent()->GetParent()->OutputToScreenPixel( aPos ); 3232 // FIXME: this ugly hack is for Mac/Aqua 3233 // should be replaced by a real mechanism to place the float rectangle 3234 if( ImplGetSVData()->maNWFData.mbNoFocusRects && 3235 GetParent()->IsNativeWidgetEnabled() ) 3236 { 3237 sal_Int32 nLeft = 4, nTop = 4, nRight = 4, nBottom = 4; 3238 aPos.X() += nLeft; 3239 aPos.Y() += nTop; 3240 aSz.Width() -= nLeft + nRight; 3241 aSz.Height() -= nTop + nBottom; 3242 } 3243 Rectangle aRect( aPos, aSz ); 3244 3245 // check if the control's parent is un-mirrored which is the case for form controls in a mirrored UI 3246 // where the document is unmirrored 3247 // because StartPopupMode() expects a rectangle in mirrored coordinates we have to re-mirror 3248 if( GetParent()->GetParent()->ImplIsAntiparallel() ) 3249 GetParent()->GetParent()->ImplReMirror( aRect ); 3250 3251 StartPopupMode( aRect, FLOATWIN_POPUPMODE_DOWN ); 3252 3253 if( nPos != LISTBOX_ENTRY_NOTFOUND ) 3254 mpImplLB->ShowProminentEntry( nPos ); 3255 3256 if( bStartTracking ) 3257 mpImplLB->GetMainWindow()->EnableMouseMoveSelect( sal_True ); 3258 3259 if ( mpImplLB->GetMainWindow()->IsGrabFocusAllowed() ) 3260 mpImplLB->GetMainWindow()->GrabFocus(); 3261 3262 mpImplLB->GetMainWindow()->ImplClearLayoutData(); 3263 } 3264 } 3265