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