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 && aImgSz.Width() && aImgSz.Height()) 1860 { 1861 const Color& rTopLeft(rStyleSettings.GetEdgeBlendingTopLeftColor()); 1862 const Color& rBottomRight(rStyleSettings.GetEdgeBlendingBottomRightColor()); 1863 const sal_uInt8 nAlpha((nEdgeBlendingPercent * 255) / 100); 1864 const BitmapEx aBlendFrame(createBlendFrame(aImgSz, nAlpha, rTopLeft, rBottomRight)); 1865 1866 if(!aBlendFrame.IsEmpty()) 1867 { 1868 DrawBitmapEx(aPtImg, aBlendFrame); 1869 } 1870 } 1871 } 1872 } 1873 1874 if( bDrawText ) 1875 { 1876 MetricVector* pVector = bLayout ? &mpControlData->mpLayoutData->m_aUnicodeBoundRects : NULL; 1877 String* pDisplayText = bLayout ? &mpControlData->mpLayoutData->m_aDisplayText : NULL; 1878 XubString aStr( mpEntryList->GetEntryText( nPos ) ); 1879 if ( aStr.Len() ) 1880 { 1881 long nMaxWidth = Max( static_cast< long >( mnMaxWidth ), 1882 GetOutputSizePixel().Width() - 2*mnBorder ); 1883 // a multiline entry should only be as wide a the window 1884 if( (pEntry->mnFlags & LISTBOX_ENTRY_FLAG_MULTILINE) ) 1885 nMaxWidth = GetOutputSizePixel().Width() - 2*mnBorder; 1886 1887 Rectangle aTextRect( Point( mnBorder - mnLeft, nY ), 1888 Size( nMaxWidth, pEntry->mnHeight ) ); 1889 1890 if( !bDrawTextAtImagePos && ( mpEntryList->HasEntryImage(nPos) || IsUserDrawEnabled() ) ) 1891 { 1892 long nImageWidth = Max( mnMaxImgWidth, maUserItemSize.Width() ); 1893 aTextRect.Left() += nImageWidth + IMG_TXT_DISTANCE; 1894 } 1895 1896 if( bLayout ) 1897 mpControlData->mpLayoutData->m_aLineIndices.push_back( mpControlData->mpLayoutData->m_aDisplayText.Len() ); 1898 1899 // pb: #106948# explicit mirroring for calc 1900 if ( mbMirroring ) 1901 { 1902 // right aligned 1903 aTextRect.Left() = nMaxWidth + mnBorder - GetTextWidth( aStr ) - mnLeft; 1904 if ( aImgSz.Width() > 0 ) 1905 aTextRect.Left() -= ( aImgSz.Width() + IMG_TXT_DISTANCE ); 1906 } 1907 1908 sal_uInt16 nDrawStyle = ImplGetTextStyle(); 1909 if( (pEntry->mnFlags & LISTBOX_ENTRY_FLAG_MULTILINE) ) 1910 nDrawStyle |= MULTILINE_ENTRY_DRAW_FLAGS; 1911 if( (pEntry->mnFlags & LISTBOX_ENTRY_FLAG_DRAW_DISABLED) ) 1912 nDrawStyle |= TEXT_DRAW_DISABLE; 1913 1914 DrawText( aTextRect, aStr, nDrawStyle, pVector, pDisplayText ); 1915 } 1916 } 1917 1918 if( !bLayout ) 1919 { 1920 if ( ( mnSeparatorPos != LISTBOX_ENTRY_NOTFOUND ) && 1921 ( ( nPos == mnSeparatorPos ) || ( nPos == mnSeparatorPos+1 ) ) ) 1922 { 1923 Color aOldLineColor( GetLineColor() ); 1924 SetLineColor( ( GetBackground().GetColor() != COL_LIGHTGRAY ) ? COL_LIGHTGRAY : COL_GRAY ); 1925 Point aStartPos( 0, nY ); 1926 if ( nPos == mnSeparatorPos ) 1927 aStartPos.Y() += pEntry->mnHeight-1; 1928 Point aEndPos( aStartPos ); 1929 aEndPos.X() = GetOutputSizePixel().Width(); 1930 DrawLine( aStartPos, aEndPos ); 1931 SetLineColor( aOldLineColor ); 1932 } 1933 } 1934 } 1935 1936 // ----------------------------------------------------------------------- 1937 1938 void ImplListBoxWindow::FillLayoutData() const 1939 { 1940 mpControlData->mpLayoutData = new vcl::ControlLayoutData(); 1941 const_cast<ImplListBoxWindow*>(this)-> 1942 ImplDoPaint( Rectangle( Point( 0, 0 ), GetOutputSize() ), true ); 1943 } 1944 1945 // ----------------------------------------------------------------------- 1946 1947 void ImplListBoxWindow::ImplDoPaint( const Rectangle& rRect, bool bLayout ) 1948 { 1949 sal_uInt16 nCount = mpEntryList->GetEntryCount(); 1950 1951 sal_Bool bShowFocusRect = mbHasFocusRect; 1952 if ( mbHasFocusRect && ! bLayout ) 1953 ImplHideFocusRect(); 1954 1955 long nY = 0; // + mnBorder; 1956 long nHeight = GetOutputSizePixel().Height();// - mnMaxHeight + mnBorder; 1957 1958 for( sal_uInt16 i = (sal_uInt16)mnTop; i < nCount && nY < nHeight + mnMaxHeight; i++ ) 1959 { 1960 const ImplEntryType* pEntry = mpEntryList->GetEntryPtr( i ); 1961 if( nY + pEntry->mnHeight >= rRect.Top() && 1962 nY <= rRect.Bottom() + mnMaxHeight ) 1963 { 1964 ImplPaint( i, sal_False, bLayout ); 1965 } 1966 nY += pEntry->mnHeight; 1967 } 1968 1969 long nHeightDiff = mpEntryList->GetAddedHeight( mnCurrentPos, mnTop, 0 ); 1970 maFocusRect.SetPos( Point( 0, nHeightDiff ) ); 1971 Size aSz( maFocusRect.GetWidth(), mpEntryList->GetEntryHeight( mnCurrentPos ) ); 1972 maFocusRect.SetSize( aSz ); 1973 if( HasFocus() && bShowFocusRect && !bLayout ) 1974 ImplShowFocusRect(); 1975 } 1976 1977 // ----------------------------------------------------------------------- 1978 1979 void ImplListBoxWindow::Paint( const Rectangle& rRect ) 1980 { 1981 ImplDoPaint( rRect ); 1982 } 1983 1984 // ----------------------------------------------------------------------- 1985 1986 sal_uInt16 ImplListBoxWindow::GetDisplayLineCount() const 1987 { 1988 // FIXME: LISTBOX_ENTRY_FLAG_MULTILINE 1989 1990 sal_uInt16 nCount = mpEntryList->GetEntryCount(); 1991 long nHeight = GetOutputSizePixel().Height();// - mnMaxHeight + mnBorder; 1992 sal_uInt16 nEntries = static_cast< sal_uInt16 >( ( nHeight + mnMaxHeight - 1 ) / mnMaxHeight ); 1993 if( nEntries > nCount-mnTop ) 1994 nEntries = nCount-mnTop; 1995 1996 return nEntries; 1997 } 1998 1999 // ----------------------------------------------------------------------- 2000 2001 void ImplListBoxWindow::Resize() 2002 { 2003 Control::Resize(); 2004 2005 sal_Bool bShowFocusRect = mbHasFocusRect; 2006 if ( bShowFocusRect ) 2007 ImplHideFocusRect(); 2008 2009 if( mnCurrentPos != LISTBOX_ENTRY_NOTFOUND ) 2010 { 2011 Size aSz( GetOutputSizePixel().Width(), mpEntryList->GetEntryHeight( mnCurrentPos ) ); 2012 maFocusRect.SetSize( aSz ); 2013 } 2014 2015 if ( bShowFocusRect ) 2016 ImplShowFocusRect(); 2017 2018 ImplClearLayoutData(); 2019 } 2020 2021 // ----------------------------------------------------------------------- 2022 2023 void ImplListBoxWindow::GetFocus() 2024 { 2025 sal_uInt16 nPos = mnCurrentPos; 2026 if ( nPos == LISTBOX_ENTRY_NOTFOUND ) 2027 nPos = 0; 2028 long nHeightDiff = mpEntryList->GetAddedHeight( nPos, mnTop, 0 ); 2029 maFocusRect.SetPos( Point( 0, nHeightDiff ) ); 2030 Size aSz( maFocusRect.GetWidth(), mpEntryList->GetEntryHeight( nPos ) ); 2031 maFocusRect.SetSize( aSz ); 2032 ImplShowFocusRect(); 2033 Control::GetFocus(); 2034 } 2035 2036 // ----------------------------------------------------------------------- 2037 2038 void ImplListBoxWindow::LoseFocus() 2039 { 2040 ImplHideFocusRect(); 2041 Control::LoseFocus(); 2042 } 2043 2044 // ----------------------------------------------------------------------- 2045 2046 /* 2047 void ImplListBoxWindow::RequestHelp( const HelpEvent& rHEvt ) 2048 { 2049 if ( rHEvt.GetMode() & HELPMODE_BALLOON ) 2050 Help::ShowBalloon( this, rHEvt.GetMousePosPixel(), String() ); 2051 2052 Window::RequestHelp( rHEvt ); 2053 } 2054 */ 2055 2056 // ----------------------------------------------------------------------- 2057 2058 void ImplListBoxWindow::SetTopEntry( sal_uInt16 nTop ) 2059 { 2060 if( mpEntryList->GetEntryCount() == 0 ) 2061 return; 2062 2063 long nWHeight = PixelToLogic( GetSizePixel() ).Height(); 2064 2065 sal_uInt16 nLastEntry = mpEntryList->GetEntryCount()-1; 2066 if( nTop > nLastEntry ) 2067 nTop = nLastEntry; 2068 const ImplEntryType* pLast = mpEntryList->GetEntryPtr( nLastEntry ); 2069 while( nTop > 0 && mpEntryList->GetAddedHeight( nLastEntry, nTop-1 ) + pLast->mnHeight <= nWHeight ) 2070 nTop--; 2071 2072 if ( nTop != mnTop ) 2073 { 2074 ImplClearLayoutData(); 2075 long nDiff = mpEntryList->GetAddedHeight( mnTop, nTop, 0 ); 2076 Update(); 2077 ImplHideFocusRect(); 2078 mnTop = nTop; 2079 Scroll( 0, nDiff ); 2080 Update(); 2081 if( HasFocus() ) 2082 ImplShowFocusRect(); 2083 maScrollHdl.Call( this ); 2084 } 2085 } 2086 2087 // ----------------------------------------------------------------------- 2088 2089 void ImplListBoxWindow::ShowProminentEntry( sal_uInt16 nEntryPos ) 2090 { 2091 if( meProminentType == PROMINENT_MIDDLE ) 2092 { 2093 sal_uInt16 nPos = nEntryPos; 2094 long nWHeight = PixelToLogic( GetSizePixel() ).Height(); 2095 while( nEntryPos > 0 && mpEntryList->GetAddedHeight( nPos+1, nEntryPos ) < nWHeight/2 ) 2096 nEntryPos--; 2097 } 2098 SetTopEntry( nEntryPos ); 2099 } 2100 2101 // ----------------------------------------------------------------------- 2102 2103 void ImplListBoxWindow::SetLeftIndent( long n ) 2104 { 2105 ScrollHorz( n - mnLeft ); 2106 } 2107 2108 // ----------------------------------------------------------------------- 2109 2110 void ImplListBoxWindow::ScrollHorz( long n ) 2111 { 2112 long nDiff = 0; 2113 if ( n > 0 ) 2114 { 2115 long nWidth = GetOutputSizePixel().Width(); 2116 if( ( mnMaxWidth - mnLeft + n ) > nWidth ) 2117 nDiff = n; 2118 } 2119 else if ( n < 0 ) 2120 { 2121 if( mnLeft ) 2122 { 2123 long nAbs = -n; 2124 nDiff = - ( ( mnLeft > nAbs ) ? nAbs : mnLeft ); 2125 } 2126 } 2127 2128 if ( nDiff ) 2129 { 2130 ImplClearLayoutData(); 2131 mnLeft = sal::static_int_cast<sal_uInt16>(mnLeft + nDiff); 2132 Update(); 2133 ImplHideFocusRect(); 2134 Scroll( -nDiff, 0 ); 2135 Update(); 2136 if( HasFocus() ) 2137 ImplShowFocusRect(); 2138 maScrollHdl.Call( this ); 2139 } 2140 } 2141 2142 // ----------------------------------------------------------------------- 2143 2144 Size ImplListBoxWindow::CalcSize( sal_uInt16 nMaxLines ) const 2145 { 2146 // FIXME: LISTBOX_ENTRY_FLAG_MULTILINE 2147 2148 Size aSz; 2149 // sal_uInt16 nL = Min( nMaxLines, mpEntryList->GetEntryCount() ); 2150 aSz.Height() = nMaxLines * mnMaxHeight; 2151 aSz.Width() = mnMaxWidth + 2*mnBorder; 2152 return aSz; 2153 } 2154 2155 // ----------------------------------------------------------------------- 2156 2157 Rectangle ImplListBoxWindow::GetBoundingRectangle( sal_uInt16 nItem ) const 2158 { 2159 const ImplEntryType* pEntry = mpEntryList->GetEntryPtr( nItem ); 2160 Size aSz( GetSizePixel().Width(), pEntry ? pEntry->mnHeight : GetEntryHeight() ); 2161 long nY = mpEntryList->GetAddedHeight( nItem, GetTopEntry() ) - mpEntryList->GetAddedHeight( GetTopEntry() ); 2162 Rectangle aRect( Point( 0, nY ), aSz ); 2163 return aRect; 2164 } 2165 2166 2167 // ----------------------------------------------------------------------- 2168 2169 void ImplListBoxWindow::StateChanged( StateChangedType nType ) 2170 { 2171 Control::StateChanged( nType ); 2172 2173 if ( nType == STATE_CHANGE_ZOOM ) 2174 { 2175 ImplInitSettings( sal_True, sal_False, sal_False ); 2176 ImplCalcMetrics(); 2177 Invalidate(); 2178 } 2179 else if ( nType == STATE_CHANGE_UPDATEMODE ) 2180 { 2181 if ( IsUpdateMode() && IsReallyVisible() ) 2182 Invalidate(); 2183 } 2184 else if ( nType == STATE_CHANGE_CONTROLFONT ) 2185 { 2186 ImplInitSettings( sal_True, sal_False, sal_False ); 2187 ImplCalcMetrics(); 2188 Invalidate(); 2189 } 2190 else if ( nType == STATE_CHANGE_CONTROLFOREGROUND ) 2191 { 2192 ImplInitSettings( sal_False, sal_True, sal_False ); 2193 Invalidate(); 2194 } 2195 else if ( nType == STATE_CHANGE_CONTROLBACKGROUND ) 2196 { 2197 ImplInitSettings( sal_False, sal_False, sal_True ); 2198 Invalidate(); 2199 } 2200 ImplClearLayoutData(); 2201 } 2202 2203 // ----------------------------------------------------------------------- 2204 2205 void ImplListBoxWindow::DataChanged( const DataChangedEvent& rDCEvt ) 2206 { 2207 Control::DataChanged( rDCEvt ); 2208 2209 if ( (rDCEvt.GetType() == DATACHANGED_FONTS) || 2210 (rDCEvt.GetType() == DATACHANGED_FONTSUBSTITUTION) || 2211 ((rDCEvt.GetType() == DATACHANGED_SETTINGS) && 2212 (rDCEvt.GetFlags() & SETTINGS_STYLE)) ) 2213 { 2214 ImplClearLayoutData(); 2215 ImplInitSettings( sal_True, sal_True, sal_True ); 2216 ImplCalcMetrics(); 2217 Invalidate(); 2218 } 2219 } 2220 2221 // ----------------------------------------------------------------------- 2222 2223 sal_uInt16 ImplListBoxWindow::ImplGetTextStyle() const 2224 { 2225 sal_uInt16 nTextStyle = TEXT_DRAW_VCENTER; 2226 2227 if ( mpEntryList->HasImages() ) 2228 nTextStyle |= TEXT_DRAW_LEFT; 2229 else if ( mbCenter ) 2230 nTextStyle |= TEXT_DRAW_CENTER; 2231 else if ( mbRight ) 2232 nTextStyle |= TEXT_DRAW_RIGHT; 2233 else 2234 nTextStyle |= TEXT_DRAW_LEFT; 2235 2236 return nTextStyle; 2237 } 2238 2239 // ======================================================================= 2240 2241 ImplListBox::ImplListBox( Window* pParent, WinBits nWinStyle ) : 2242 Control( pParent, nWinStyle ), 2243 maLBWindow( this, nWinStyle&(~WB_BORDER) ) 2244 { 2245 // for native widget rendering we must be able to detect this window type 2246 SetType( WINDOW_LISTBOXWINDOW ); 2247 2248 mpVScrollBar = new ScrollBar( this, WB_VSCROLL | WB_DRAG ); 2249 mpHScrollBar = new ScrollBar( this, WB_HSCROLL | WB_DRAG ); 2250 mpScrollBarBox = new ScrollBarBox( this ); 2251 2252 Link aLink( LINK( this, ImplListBox, ScrollBarHdl ) ); 2253 mpVScrollBar->SetScrollHdl( aLink ); 2254 mpHScrollBar->SetScrollHdl( aLink ); 2255 2256 mbVScroll = false; 2257 mbHScroll = false; 2258 mbAutoHScroll = ( nWinStyle & WB_AUTOHSCROLL ); 2259 mbEdgeBlending = false; 2260 2261 maLBWindow.SetScrollHdl( LINK( this, ImplListBox, LBWindowScrolled ) ); 2262 maLBWindow.SetMRUChangedHdl( LINK( this, ImplListBox, MRUChanged ) ); 2263 maLBWindow.SetEdgeBlending(GetEdgeBlending()); 2264 maLBWindow.Show(); 2265 } 2266 2267 // ----------------------------------------------------------------------- 2268 2269 ImplListBox::~ImplListBox() 2270 { 2271 delete mpHScrollBar; 2272 delete mpVScrollBar; 2273 delete mpScrollBarBox; 2274 } 2275 2276 // ----------------------------------------------------------------------- 2277 2278 void ImplListBox::Clear() 2279 { 2280 maLBWindow.Clear(); 2281 if ( GetEntryList()->GetMRUCount() ) 2282 { 2283 maLBWindow.GetEntryList()->SetMRUCount( 0 ); 2284 maLBWindow.SetSeparatorPos( LISTBOX_ENTRY_NOTFOUND ); 2285 } 2286 mpVScrollBar->SetThumbPos( 0 ); 2287 mpHScrollBar->SetThumbPos( 0 ); 2288 StateChanged( STATE_CHANGE_DATA ); 2289 } 2290 2291 // ----------------------------------------------------------------------- 2292 2293 sal_uInt16 ImplListBox::InsertEntry( sal_uInt16 nPos, const XubString& rStr ) 2294 { 2295 ImplEntryType* pNewEntry = new ImplEntryType( rStr ); 2296 sal_uInt16 nNewPos = maLBWindow.InsertEntry( nPos, pNewEntry ); 2297 StateChanged( STATE_CHANGE_DATA ); 2298 return nNewPos; 2299 } 2300 2301 // ----------------------------------------------------------------------- 2302 2303 sal_uInt16 ImplListBox::InsertEntry( sal_uInt16 nPos, const Image& rImage ) 2304 { 2305 ImplEntryType* pNewEntry = new ImplEntryType( rImage ); 2306 sal_uInt16 nNewPos = maLBWindow.InsertEntry( nPos, pNewEntry ); 2307 StateChanged( STATE_CHANGE_DATA ); 2308 return nNewPos; 2309 } 2310 2311 // ----------------------------------------------------------------------- 2312 2313 sal_uInt16 ImplListBox::InsertEntry( sal_uInt16 nPos, const XubString& rStr, const Image& rImage ) 2314 { 2315 ImplEntryType* pNewEntry = new ImplEntryType( rStr, rImage ); 2316 sal_uInt16 nNewPos = maLBWindow.InsertEntry( nPos, pNewEntry ); 2317 StateChanged( STATE_CHANGE_DATA ); 2318 return nNewPos; 2319 } 2320 2321 // ----------------------------------------------------------------------- 2322 2323 void ImplListBox::RemoveEntry( sal_uInt16 nPos ) 2324 { 2325 maLBWindow.RemoveEntry( nPos ); 2326 StateChanged( STATE_CHANGE_DATA ); 2327 } 2328 2329 // ----------------------------------------------------------------------- 2330 2331 void ImplListBox::SetEntryFlags( sal_uInt16 nPos, long nFlags ) 2332 { 2333 maLBWindow.SetEntryFlags( nPos, nFlags ); 2334 } 2335 2336 // ----------------------------------------------------------------------- 2337 2338 long ImplListBox::GetEntryFlags( sal_uInt16 nPos ) const 2339 { 2340 return maLBWindow.GetEntryList()->GetEntryFlags( nPos ); 2341 } 2342 2343 // ----------------------------------------------------------------------- 2344 2345 void ImplListBox::SelectEntry( sal_uInt16 nPos, sal_Bool bSelect ) 2346 { 2347 maLBWindow.SelectEntry( nPos, bSelect ); 2348 } 2349 2350 // ----------------------------------------------------------------------- 2351 2352 void ImplListBox::SetNoSelection() 2353 { 2354 maLBWindow.DeselectAll(); 2355 } 2356 2357 // ----------------------------------------------------------------------- 2358 2359 void ImplListBox::GetFocus() 2360 { 2361 maLBWindow.GrabFocus(); 2362 } 2363 2364 // ----------------------------------------------------------------------- 2365 2366 Window* ImplListBox::GetPreferredKeyInputWindow() 2367 { 2368 return &maLBWindow; 2369 } 2370 2371 // ----------------------------------------------------------------------- 2372 2373 void ImplListBox::Resize() 2374 { 2375 Control::Resize(); 2376 ImplResizeControls(); 2377 ImplCheckScrollBars(); 2378 } 2379 2380 2381 // ----------------------------------------------------------------------- 2382 2383 IMPL_LINK( ImplListBox, MRUChanged, void*, EMPTYARG ) 2384 { 2385 StateChanged( STATE_CHANGE_DATA ); 2386 return 1; 2387 } 2388 2389 // ----------------------------------------------------------------------- 2390 2391 IMPL_LINK( ImplListBox, LBWindowScrolled, void*, EMPTYARG ) 2392 { 2393 long nSet = GetTopEntry(); 2394 if( nSet > mpVScrollBar->GetRangeMax() ) 2395 mpVScrollBar->SetRangeMax( GetEntryList()->GetEntryCount() ); 2396 mpVScrollBar->SetThumbPos( GetTopEntry() ); 2397 2398 mpHScrollBar->SetThumbPos( GetLeftIndent() ); 2399 2400 maScrollHdl.Call( this ); 2401 2402 return 1; 2403 } 2404 2405 // ----------------------------------------------------------------------- 2406 2407 IMPL_LINK( ImplListBox, ScrollBarHdl, ScrollBar*, pSB ) 2408 { 2409 sal_uInt16 nPos = (sal_uInt16) pSB->GetThumbPos(); 2410 if( pSB == mpVScrollBar ) 2411 SetTopEntry( nPos ); 2412 else if( pSB == mpHScrollBar ) 2413 SetLeftIndent( nPos ); 2414 2415 return 1; 2416 } 2417 2418 // ----------------------------------------------------------------------- 2419 2420 void ImplListBox::ImplCheckScrollBars() 2421 { 2422 sal_Bool bArrange = sal_False; 2423 2424 Size aOutSz = GetOutputSizePixel(); 2425 sal_uInt16 nEntries = GetEntryList()->GetEntryCount(); 2426 sal_uInt16 nMaxVisEntries = (sal_uInt16) (aOutSz.Height() / GetEntryHeight()); 2427 2428 // vert. ScrollBar 2429 if( nEntries > nMaxVisEntries ) 2430 { 2431 if( !mbVScroll ) 2432 bArrange = sal_True; 2433 mbVScroll = true; 2434 2435 // Ueberpruefung des rausgescrollten Bereichs 2436 if( GetEntryList()->GetSelectEntryCount() == 1 && 2437 GetEntryList()->GetSelectEntryPos( 0 ) != LISTBOX_ENTRY_NOTFOUND ) 2438 ShowProminentEntry( GetEntryList()->GetSelectEntryPos( 0 ) ); 2439 else 2440 SetTopEntry( GetTopEntry() ); // MaxTop wird geprueft... 2441 } 2442 else 2443 { 2444 if( mbVScroll ) 2445 bArrange = sal_True; 2446 mbVScroll = false; 2447 SetTopEntry( 0 ); 2448 } 2449 2450 // horz. ScrollBar 2451 if( mbAutoHScroll ) 2452 { 2453 long nWidth = (sal_uInt16) aOutSz.Width(); 2454 if ( mbVScroll ) 2455 nWidth -= mpVScrollBar->GetSizePixel().Width(); 2456 2457 long nMaxWidth = GetMaxEntryWidth(); 2458 if( nWidth < nMaxWidth ) 2459 { 2460 if( !mbHScroll ) 2461 bArrange = sal_True; 2462 mbHScroll = true; 2463 2464 if ( !mbVScroll ) // ggf. brauchen wir jetzt doch einen 2465 { 2466 nMaxVisEntries = (sal_uInt16) ( ( aOutSz.Height() - mpHScrollBar->GetSizePixel().Height() ) / GetEntryHeight() ); 2467 if( nEntries > nMaxVisEntries ) 2468 { 2469 bArrange = sal_True; 2470 mbVScroll = true; 2471 2472 // Ueberpruefung des rausgescrollten Bereichs 2473 if( GetEntryList()->GetSelectEntryCount() == 1 && 2474 GetEntryList()->GetSelectEntryPos( 0 ) != LISTBOX_ENTRY_NOTFOUND ) 2475 ShowProminentEntry( GetEntryList()->GetSelectEntryPos( 0 ) ); 2476 else 2477 SetTopEntry( GetTopEntry() ); // MaxTop wird geprueft... 2478 } 2479 } 2480 2481 // Ueberpruefung des rausgescrollten Bereichs 2482 sal_uInt16 nMaxLI = (sal_uInt16) (nMaxWidth - nWidth); 2483 if ( nMaxLI < GetLeftIndent() ) 2484 SetLeftIndent( nMaxLI ); 2485 } 2486 else 2487 { 2488 if( mbHScroll ) 2489 bArrange = sal_True; 2490 mbHScroll = false; 2491 SetLeftIndent( 0 ); 2492 } 2493 } 2494 2495 if( bArrange ) 2496 ImplResizeControls(); 2497 2498 ImplInitScrollBars(); 2499 } 2500 2501 // ----------------------------------------------------------------------- 2502 2503 void ImplListBox::ImplInitScrollBars() 2504 { 2505 Size aOutSz = maLBWindow.GetOutputSizePixel(); 2506 2507 if ( mbVScroll ) 2508 { 2509 sal_uInt16 nEntries = GetEntryList()->GetEntryCount(); 2510 sal_uInt16 nVisEntries = (sal_uInt16) (aOutSz.Height() / GetEntryHeight()); 2511 mpVScrollBar->SetRangeMax( nEntries ); 2512 mpVScrollBar->SetVisibleSize( nVisEntries ); 2513 mpVScrollBar->SetPageSize( nVisEntries - 1 ); 2514 } 2515 2516 if ( mbHScroll ) 2517 { 2518 mpHScrollBar->SetRangeMax( GetMaxEntryWidth() + HORZ_SCROLL ); 2519 mpHScrollBar->SetVisibleSize( (sal_uInt16)aOutSz.Width() ); 2520 mpHScrollBar->SetLineSize( HORZ_SCROLL ); 2521 mpHScrollBar->SetPageSize( aOutSz.Width() - HORZ_SCROLL ); 2522 } 2523 } 2524 2525 // ----------------------------------------------------------------------- 2526 2527 void ImplListBox::ImplResizeControls() 2528 { 2529 // Hier werden die Controls nur angeordnet, ob die Scrollbars 2530 // sichtbar sein sollen wird bereits in ImplCheckScrollBars ermittelt. 2531 2532 Size aOutSz = GetOutputSizePixel(); 2533 long nSBWidth = GetSettings().GetStyleSettings().GetScrollBarSize(); 2534 nSBWidth = CalcZoom( nSBWidth ); 2535 2536 Size aInnerSz( aOutSz ); 2537 if ( mbVScroll ) 2538 aInnerSz.Width() -= nSBWidth; 2539 if ( mbHScroll ) 2540 aInnerSz.Height() -= nSBWidth; 2541 2542 // pb: #106948# explicit mirroring for calc 2543 // Scrollbar on left or right side? 2544 sal_Bool bMirroring = maLBWindow.IsMirroring(); 2545 Point aWinPos( bMirroring && mbVScroll ? nSBWidth : 0, 0 ); 2546 maLBWindow.SetPosSizePixel( aWinPos, aInnerSz ); 2547 2548 // ScrollBarBox 2549 if( mbVScroll && mbHScroll ) 2550 { 2551 Point aBoxPos( bMirroring ? 0 : aInnerSz.Width(), aInnerSz.Height() ); 2552 mpScrollBarBox->SetPosSizePixel( aBoxPos, Size( nSBWidth, nSBWidth ) ); 2553 mpScrollBarBox->Show(); 2554 } 2555 else 2556 { 2557 mpScrollBarBox->Hide(); 2558 } 2559 2560 // vert. ScrollBar 2561 if( mbVScroll ) 2562 { 2563 // Scrollbar on left or right side? 2564 Point aVPos( bMirroring ? 0 : aOutSz.Width() - nSBWidth, 0 ); 2565 mpVScrollBar->SetPosSizePixel( aVPos, Size( nSBWidth, aInnerSz.Height() ) ); 2566 mpVScrollBar->Show(); 2567 } 2568 else 2569 { 2570 mpVScrollBar->Hide(); 2571 // #107254# Don't reset top entry after resize, but check for max top entry 2572 SetTopEntry( GetTopEntry() ); 2573 } 2574 2575 // horz. ScrollBar 2576 if( mbHScroll ) 2577 { 2578 Point aHPos( ( bMirroring && mbVScroll ) ? nSBWidth : 0, aOutSz.Height() - nSBWidth ); 2579 mpHScrollBar->SetPosSizePixel( aHPos, Size( aInnerSz.Width(), nSBWidth ) ); 2580 mpHScrollBar->Show(); 2581 } 2582 else 2583 { 2584 mpHScrollBar->Hide(); 2585 SetLeftIndent( 0 ); 2586 } 2587 } 2588 2589 // ----------------------------------------------------------------------- 2590 2591 void ImplListBox::StateChanged( StateChangedType nType ) 2592 { 2593 if ( nType == STATE_CHANGE_INITSHOW ) 2594 { 2595 ImplCheckScrollBars(); 2596 } 2597 else if ( ( nType == STATE_CHANGE_UPDATEMODE ) || ( nType == STATE_CHANGE_DATA ) ) 2598 { 2599 sal_Bool bUpdate = IsUpdateMode(); 2600 maLBWindow.SetUpdateMode( bUpdate ); 2601 // mpHScrollBar->SetUpdateMode( bUpdate ); 2602 // mpVScrollBar->SetUpdateMode( bUpdate ); 2603 if ( bUpdate && IsReallyVisible() ) 2604 ImplCheckScrollBars(); 2605 } 2606 else if( nType == STATE_CHANGE_ENABLE ) 2607 { 2608 mpHScrollBar->Enable( IsEnabled() ); 2609 mpVScrollBar->Enable( IsEnabled() ); 2610 mpScrollBarBox->Enable( IsEnabled() ); 2611 Invalidate(); 2612 } 2613 else if ( nType == STATE_CHANGE_ZOOM ) 2614 { 2615 maLBWindow.SetZoom( GetZoom() ); 2616 Resize(); 2617 } 2618 else if ( nType == STATE_CHANGE_CONTROLFONT ) 2619 { 2620 maLBWindow.SetControlFont( GetControlFont() ); 2621 } 2622 else if ( nType == STATE_CHANGE_CONTROLFOREGROUND ) 2623 { 2624 maLBWindow.SetControlForeground( GetControlForeground() ); 2625 } 2626 else if ( nType == STATE_CHANGE_CONTROLBACKGROUND ) 2627 { 2628 maLBWindow.SetControlBackground( GetControlBackground() ); 2629 } 2630 else if( nType == STATE_CHANGE_MIRRORING ) 2631 { 2632 maLBWindow.EnableRTL( IsRTLEnabled() ); 2633 mpHScrollBar->EnableRTL( IsRTLEnabled() ); 2634 mpVScrollBar->EnableRTL( IsRTLEnabled() ); 2635 ImplResizeControls(); 2636 } 2637 2638 Control::StateChanged( nType ); 2639 } 2640 2641 // ----------------------------------------------------------------------- 2642 2643 void ImplListBox::DataChanged( const DataChangedEvent& rDCEvt ) 2644 { 2645 // if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) && 2646 // (rDCEvt.GetFlags() & SETTINGS_STYLE) ) 2647 // { 2648 // maLBWindow.SetSettings( GetSettings() ); 2649 // Resize(); 2650 // } 2651 // else 2652 Control::DataChanged( rDCEvt ); 2653 } 2654 2655 // ----------------------------------------------------------------------- 2656 2657 long ImplListBox::Notify( NotifyEvent& rNEvt ) 2658 { 2659 long nDone = 0; 2660 if ( rNEvt.GetType() == EVENT_COMMAND ) 2661 { 2662 const CommandEvent& rCEvt = *rNEvt.GetCommandEvent(); 2663 if ( rCEvt.GetCommand() == COMMAND_WHEEL ) 2664 { 2665 const CommandWheelData* pData = rCEvt.GetWheelData(); 2666 if( !pData->GetModifier() && ( pData->GetMode() == COMMAND_WHEEL_SCROLL ) ) 2667 { 2668 nDone = HandleScrollCommand( rCEvt, mpHScrollBar, mpVScrollBar ); 2669 } 2670 } 2671 } 2672 2673 return nDone ? nDone : Window::Notify( rNEvt ); 2674 } 2675 2676 // ----------------------------------------------------------------------- 2677 2678 const Wallpaper& ImplListBox::GetDisplayBackground() const 2679 { 2680 return maLBWindow.GetDisplayBackground(); 2681 } 2682 2683 // ----------------------------------------------------------------------- 2684 2685 sal_Bool ImplListBox::HandleWheelAsCursorTravel( const CommandEvent& rCEvt ) 2686 { 2687 sal_Bool bDone = sal_False; 2688 if ( rCEvt.GetCommand() == COMMAND_WHEEL ) 2689 { 2690 const CommandWheelData* pData = rCEvt.GetWheelData(); 2691 if( !pData->GetModifier() && ( pData->GetMode() == COMMAND_WHEEL_SCROLL ) ) 2692 { 2693 sal_uInt16 nKey = ( pData->GetDelta() < 0 ) ? KEY_DOWN : KEY_UP; 2694 KeyEvent aKeyEvent( 0, KeyCode( nKey ) ); 2695 bDone = ProcessKeyInput( aKeyEvent ); 2696 } 2697 } 2698 return bDone; 2699 } 2700 2701 // ----------------------------------------------------------------------- 2702 2703 void ImplListBox::SetMRUEntries( const XubString& rEntries, xub_Unicode cSep ) 2704 { 2705 sal_Bool bChanges = GetEntryList()->GetMRUCount() ? sal_True : sal_False; 2706 2707 // Remove old MRU entries 2708 for ( sal_uInt16 n = GetEntryList()->GetMRUCount();n; ) 2709 maLBWindow.RemoveEntry( --n ); 2710 2711 sal_uInt16 nMRUCount = 0; 2712 sal_uInt16 nEntries = rEntries.GetTokenCount( cSep ); 2713 for ( sal_uInt16 nEntry = 0; nEntry < nEntries; nEntry++ ) 2714 { 2715 XubString aEntry = rEntries.GetToken( nEntry, cSep ); 2716 // Accept only existing entries 2717 if ( GetEntryList()->FindEntry( aEntry ) != LISTBOX_ENTRY_NOTFOUND ) 2718 { 2719 ImplEntryType* pNewEntry = new ImplEntryType( aEntry ); 2720 maLBWindow.GetEntryList()->InsertEntry( nMRUCount++, pNewEntry, sal_False ); 2721 bChanges = sal_True; 2722 } 2723 } 2724 2725 if ( bChanges ) 2726 { 2727 maLBWindow.GetEntryList()->SetMRUCount( nMRUCount ); 2728 SetSeparatorPos( nMRUCount ? nMRUCount-1 : 0 ); 2729 StateChanged( STATE_CHANGE_DATA ); 2730 } 2731 } 2732 2733 // ----------------------------------------------------------------------- 2734 2735 XubString ImplListBox::GetMRUEntries( xub_Unicode cSep ) const 2736 { 2737 String aEntries; 2738 for ( sal_uInt16 n = 0; n < GetEntryList()->GetMRUCount(); n++ ) 2739 { 2740 aEntries += GetEntryList()->GetEntryText( n ); 2741 if( n < ( GetEntryList()->GetMRUCount() - 1 ) ) 2742 aEntries += cSep; 2743 } 2744 return aEntries; 2745 } 2746 2747 // ----------------------------------------------------------------------- 2748 2749 void ImplListBox::SetEdgeBlending(bool bNew) 2750 { 2751 if(mbEdgeBlending != bNew) 2752 { 2753 mbEdgeBlending = bNew; 2754 maLBWindow.SetEdgeBlending(GetEdgeBlending()); 2755 } 2756 } 2757 2758 // ======================================================================= 2759 2760 ImplWin::ImplWin( Window* pParent, WinBits nWinStyle ) : 2761 Control ( pParent, nWinStyle ) 2762 { 2763 if ( IsNativeControlSupported(CTRL_LISTBOX, PART_ENTIRE_CONTROL) 2764 && ! IsNativeControlSupported(CTRL_LISTBOX, PART_BUTTON_DOWN) ) 2765 SetBackground(); 2766 else 2767 SetBackground( Wallpaper( GetSettings().GetStyleSettings().GetFieldColor() ) ); 2768 2769 mbInUserDraw = false; 2770 mbUserDrawEnabled = false; 2771 mbEdgeBlending = false; 2772 mnItemPos = LISTBOX_ENTRY_NOTFOUND; 2773 } 2774 2775 // ----------------------------------------------------------------------- 2776 2777 sal_Bool ImplWin::SetModeImage( const Image& rImage, BmpColorMode eMode ) 2778 { 2779 if( eMode == BMP_COLOR_NORMAL ) 2780 SetImage( rImage ); 2781 else if( eMode == BMP_COLOR_HIGHCONTRAST ) 2782 maImageHC = rImage; 2783 else 2784 return sal_False; 2785 return sal_True; 2786 } 2787 2788 // ----------------------------------------------------------------------- 2789 2790 const Image& ImplWin::GetModeImage( BmpColorMode eMode ) const 2791 { 2792 if( eMode == BMP_COLOR_HIGHCONTRAST ) 2793 return maImageHC; 2794 else 2795 return maImage; 2796 } 2797 2798 // ----------------------------------------------------------------------- 2799 2800 void ImplWin::MBDown() 2801 { 2802 if( IsEnabled() ) 2803 maMBDownHdl.Call( this ); 2804 } 2805 2806 // ----------------------------------------------------------------------- 2807 2808 void ImplWin::MouseButtonDown( const MouseEvent& ) 2809 { 2810 if( IsEnabled() ) 2811 { 2812 // Control::MouseButtonDown( rMEvt ); 2813 MBDown(); 2814 } 2815 } 2816 2817 // ----------------------------------------------------------------------- 2818 2819 void ImplWin::FillLayoutData() const 2820 { 2821 mpControlData->mpLayoutData = new vcl::ControlLayoutData(); 2822 const_cast<ImplWin*>(this)->ImplDraw( true ); 2823 } 2824 2825 // ----------------------------------------------------------------------- 2826 2827 long ImplWin::PreNotify( NotifyEvent& rNEvt ) 2828 { 2829 long nDone = 0; 2830 const MouseEvent* pMouseEvt = NULL; 2831 2832 if( (rNEvt.GetType() == EVENT_MOUSEMOVE) && (pMouseEvt = rNEvt.GetMouseEvent()) != NULL ) 2833 { 2834 if( pMouseEvt->IsEnterWindow() || pMouseEvt->IsLeaveWindow() ) 2835 { 2836 // trigger redraw as mouse over state has changed 2837 if ( IsNativeControlSupported(CTRL_LISTBOX, PART_ENTIRE_CONTROL) 2838 && ! IsNativeControlSupported(CTRL_LISTBOX, PART_BUTTON_DOWN) ) 2839 { 2840 GetParent()->GetWindow( WINDOW_BORDER )->Invalidate( INVALIDATE_NOERASE ); 2841 GetParent()->GetWindow( WINDOW_BORDER )->Update(); 2842 } 2843 } 2844 } 2845 2846 return nDone ? nDone : Control::PreNotify(rNEvt); 2847 } 2848 2849 // ----------------------------------------------------------------------- 2850 2851 void ImplWin::ImplDraw( bool bLayout ) 2852 { 2853 const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings(); 2854 2855 sal_Bool bNativeOK = sal_False; 2856 2857 if( ! bLayout ) 2858 { 2859 ControlState nState = CTRL_STATE_ENABLED; 2860 if ( IsNativeControlSupported(CTRL_LISTBOX, PART_ENTIRE_CONTROL) 2861 && IsNativeControlSupported(CTRL_LISTBOX, HAS_BACKGROUND_TEXTURE) ) 2862 { 2863 // Repaint the (focused) area similarly to 2864 // ImplSmallBorderWindowView::DrawWindow() in 2865 // vcl/source/window/brdwin.cxx 2866 Window *pWin = GetParent(); 2867 2868 ImplControlValue aControlValue; 2869 if ( !pWin->IsEnabled() ) 2870 nState &= ~CTRL_STATE_ENABLED; 2871 if ( pWin->HasFocus() ) 2872 nState |= CTRL_STATE_FOCUSED; 2873 2874 // The listbox is painted over the entire control including the 2875 // border, but ImplWin does not contain the border => correction 2876 // needed. 2877 sal_Int32 nLeft, nTop, nRight, nBottom; 2878 pWin->GetBorder( nLeft, nTop, nRight, nBottom ); 2879 Point aPoint( -nLeft, -nTop ); 2880 Rectangle aCtrlRegion( aPoint - GetPosPixel(), pWin->GetSizePixel() ); 2881 2882 sal_Bool bMouseOver = sal_False; 2883 if( GetParent() ) 2884 { 2885 Window *pChild = GetParent()->GetWindow( WINDOW_FIRSTCHILD ); 2886 while( pChild && (bMouseOver = pChild->IsMouseOver()) == sal_False ) 2887 pChild = pChild->GetWindow( WINDOW_NEXT ); 2888 } 2889 2890 if( bMouseOver ) 2891 nState |= CTRL_STATE_ROLLOVER; 2892 2893 // if parent has no border, then nobody has drawn the background 2894 // since no border window exists. so draw it here. 2895 WinBits nParentStyle = pWin->GetStyle(); 2896 if( ! (nParentStyle & WB_BORDER) || (nParentStyle & WB_NOBORDER) ) 2897 { 2898 Rectangle aParentRect( Point( 0, 0 ), pWin->GetSizePixel() ); 2899 pWin->DrawNativeControl( CTRL_LISTBOX, PART_ENTIRE_CONTROL, aParentRect, 2900 nState, aControlValue, rtl::OUString() ); 2901 } 2902 2903 bNativeOK = DrawNativeControl( CTRL_LISTBOX, PART_ENTIRE_CONTROL, aCtrlRegion, nState, 2904 aControlValue, rtl::OUString() ); 2905 } 2906 2907 if( IsEnabled() ) 2908 { 2909 if( HasFocus() ) 2910 { 2911 SetTextColor( rStyleSettings.GetHighlightTextColor() ); 2912 SetFillColor( rStyleSettings.GetHighlightColor() ); 2913 DrawRect( maFocusRect ); 2914 } 2915 else 2916 { 2917 Color aColor; 2918 if( bNativeOK && (nState & CTRL_STATE_ROLLOVER) ) 2919 aColor = rStyleSettings.GetFieldRolloverTextColor(); 2920 else 2921 aColor = rStyleSettings.GetFieldTextColor(); 2922 if( IsControlForeground() ) 2923 aColor = GetControlForeground(); 2924 SetTextColor( aColor ); 2925 if ( !bNativeOK ) 2926 Erase( maFocusRect ); 2927 } 2928 } 2929 else // Disabled 2930 { 2931 SetTextColor( rStyleSettings.GetDisableColor() ); 2932 if ( !bNativeOK ) 2933 Erase( maFocusRect ); 2934 } 2935 } 2936 2937 if ( IsUserDrawEnabled() ) 2938 { 2939 mbInUserDraw = true; 2940 UserDrawEvent aUDEvt( this, maFocusRect, mnItemPos, 0 ); 2941 maUserDrawHdl.Call( &aUDEvt ); 2942 mbInUserDraw = false; 2943 } 2944 else 2945 { 2946 DrawEntry( sal_True, sal_True, sal_False, bLayout ); 2947 } 2948 } 2949 2950 // ----------------------------------------------------------------------- 2951 2952 void ImplWin::Paint( const Rectangle& ) 2953 { 2954 ImplDraw(); 2955 } 2956 2957 // ----------------------------------------------------------------------- 2958 2959 void ImplWin::DrawEntry( sal_Bool bDrawImage, sal_Bool bDrawText, sal_Bool bDrawTextAtImagePos, bool bLayout ) 2960 { 2961 long nBorder = 1; 2962 Size aOutSz = GetOutputSizePixel(); 2963 2964 sal_Bool bImage = !!maImage; 2965 if( bDrawImage && bImage && !bLayout ) 2966 { 2967 sal_uInt16 nStyle = 0; 2968 Size aImgSz = maImage.GetSizePixel(); 2969 Point aPtImg( nBorder, ( ( aOutSz.Height() - aImgSz.Height() ) / 2 ) ); 2970 const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings(); 2971 2972 // check for HC mode 2973 Image *pImage = &maImage; 2974 2975 if( !!maImageHC ) 2976 { 2977 if( rStyleSettings.GetHighContrastMode() ) 2978 pImage = &maImageHC; 2979 } 2980 2981 if ( !IsZoom() ) 2982 { 2983 DrawImage( aPtImg, *pImage, nStyle ); 2984 } 2985 else 2986 { 2987 aImgSz.Width() = CalcZoom( aImgSz.Width() ); 2988 aImgSz.Height() = CalcZoom( aImgSz.Height() ); 2989 DrawImage( aPtImg, aImgSz, *pImage, nStyle ); 2990 } 2991 2992 const sal_uInt16 nEdgeBlendingPercent(GetEdgeBlending() ? rStyleSettings.GetEdgeBlending() : 0); 2993 2994 if(nEdgeBlendingPercent) 2995 { 2996 const Color& rTopLeft(rStyleSettings.GetEdgeBlendingTopLeftColor()); 2997 const Color& rBottomRight(rStyleSettings.GetEdgeBlendingBottomRightColor()); 2998 const sal_uInt8 nAlpha((nEdgeBlendingPercent * 255) / 100); 2999 const BitmapEx aBlendFrame(createBlendFrame(aImgSz, nAlpha, rTopLeft, rBottomRight)); 3000 3001 if(!aBlendFrame.IsEmpty()) 3002 { 3003 DrawBitmapEx(aPtImg, aBlendFrame); 3004 } 3005 } 3006 } 3007 3008 if( bDrawText && maString.Len() ) 3009 { 3010 sal_uInt16 nTextStyle = TEXT_DRAW_VCENTER; 3011 3012 if ( bDrawImage && bImage && !bLayout ) 3013 nTextStyle |= TEXT_DRAW_LEFT; 3014 else if ( GetStyle() & WB_CENTER ) 3015 nTextStyle |= TEXT_DRAW_CENTER; 3016 else if ( GetStyle() & WB_RIGHT ) 3017 nTextStyle |= TEXT_DRAW_RIGHT; 3018 else 3019 nTextStyle |= TEXT_DRAW_LEFT; 3020 3021 Rectangle aTextRect( Point( nBorder, 0 ), Size( aOutSz.Width()-2*nBorder, aOutSz.Height() ) ); 3022 3023 if ( !bDrawTextAtImagePos && ( bImage || IsUserDrawEnabled() ) ) 3024 { 3025 long nMaxWidth = Max( maImage.GetSizePixel().Width(), maUserItemSize.Width() ); 3026 aTextRect.Left() += nMaxWidth + IMG_TXT_DISTANCE; 3027 } 3028 3029 MetricVector* pVector = bLayout ? &mpControlData->mpLayoutData->m_aUnicodeBoundRects : NULL; 3030 String* pDisplayText = bLayout ? &mpControlData->mpLayoutData->m_aDisplayText : NULL; 3031 DrawText( aTextRect, maString, nTextStyle, pVector, pDisplayText ); 3032 } 3033 3034 if( HasFocus() && !bLayout ) 3035 ShowFocus( maFocusRect ); 3036 } 3037 3038 // ----------------------------------------------------------------------- 3039 3040 void ImplWin::Resize() 3041 { 3042 Control::Resize(); 3043 maFocusRect.SetSize( GetOutputSizePixel() ); 3044 Invalidate(); 3045 } 3046 3047 // ----------------------------------------------------------------------- 3048 3049 void ImplWin::GetFocus() 3050 { 3051 ShowFocus( maFocusRect ); 3052 if( ImplGetSVData()->maNWFData.mbNoFocusRects && 3053 IsNativeWidgetEnabled() && 3054 IsNativeControlSupported( CTRL_LISTBOX, PART_ENTIRE_CONTROL ) ) 3055 { 3056 Window* pWin = GetParent()->GetWindow( WINDOW_BORDER ); 3057 if( ! pWin ) 3058 pWin = GetParent(); 3059 pWin->Invalidate(); 3060 } 3061 else 3062 Invalidate(); 3063 Control::GetFocus(); 3064 } 3065 3066 // ----------------------------------------------------------------------- 3067 3068 void ImplWin::LoseFocus() 3069 { 3070 HideFocus(); 3071 if( ImplGetSVData()->maNWFData.mbNoFocusRects && 3072 IsNativeWidgetEnabled() && 3073 IsNativeControlSupported( CTRL_LISTBOX, PART_ENTIRE_CONTROL ) ) 3074 { 3075 Window* pWin = GetParent()->GetWindow( WINDOW_BORDER ); 3076 if( ! pWin ) 3077 pWin = GetParent(); 3078 pWin->Invalidate(); 3079 } 3080 else 3081 Invalidate(); 3082 Control::LoseFocus(); 3083 } 3084 3085 // ======================================================================= 3086 3087 ImplBtn::ImplBtn( Window* pParent, WinBits nWinStyle ) : 3088 PushButton( pParent, nWinStyle ), 3089 mbDown ( sal_False ) 3090 { 3091 } 3092 3093 // ----------------------------------------------------------------------- 3094 3095 void ImplBtn::MBDown() 3096 { 3097 if( IsEnabled() ) 3098 maMBDownHdl.Call( this ); 3099 } 3100 3101 // ----------------------------------------------------------------------- 3102 3103 void ImplBtn::MouseButtonDown( const MouseEvent& ) 3104 { 3105 //PushButton::MouseButtonDown( rMEvt ); 3106 if( IsEnabled() ) 3107 { 3108 MBDown(); 3109 mbDown = sal_True; 3110 } 3111 } 3112 3113 // ======================================================================= 3114 3115 ImplListBoxFloatingWindow::ImplListBoxFloatingWindow( Window* pParent ) : 3116 FloatingWindow( pParent, WB_BORDER | WB_SYSTEMWINDOW | WB_NOSHADOW ) // no drop shadow for list boxes 3117 { 3118 mpImplLB = NULL; 3119 mnDDLineCount = 0; 3120 mbAutoWidth = sal_False; 3121 3122 mnPopupModeStartSaveSelection = LISTBOX_ENTRY_NOTFOUND; 3123 3124 EnableSaveBackground(); 3125 3126 Window * pBorderWindow = ImplGetBorderWindow(); 3127 if( pBorderWindow ) 3128 { 3129 SetAccessibleRole(accessibility::AccessibleRole::PANEL); 3130 pBorderWindow->SetAccessibleRole(accessibility::AccessibleRole::WINDOW); 3131 } 3132 else 3133 { 3134 SetAccessibleRole(accessibility::AccessibleRole::WINDOW); 3135 } 3136 3137 } 3138 3139 // ----------------------------------------------------------------------- 3140 3141 long ImplListBoxFloatingWindow::PreNotify( NotifyEvent& rNEvt ) 3142 { 3143 if( rNEvt.GetType() == EVENT_LOSEFOCUS ) 3144 { 3145 if( !GetParent()->HasChildPathFocus( sal_True ) ) 3146 EndPopupMode(); 3147 } 3148 3149 return FloatingWindow::PreNotify( rNEvt ); 3150 } 3151 3152 // ----------------------------------------------------------------------- 3153 3154 void ImplListBoxFloatingWindow::SetPosSizePixel( long nX, long nY, long nWidth, long nHeight, sal_uInt16 nFlags ) 3155 { 3156 FloatingWindow::SetPosSizePixel( nX, nY, nWidth, nHeight, nFlags ); 3157 3158 // Fix #60890# ( MBA ): um auch im aufgeklappten Zustand der Listbox die Gr"o\se einfach zu einen 3159 // Aufruf von Resize() "andern zu k"onnen, wird die Position hier ggf. angepa\t 3160 if ( IsReallyVisible() && ( nFlags & WINDOW_POSSIZE_HEIGHT ) ) 3161 { 3162 Point aPos = GetParent()->GetPosPixel(); 3163 aPos = GetParent()->GetParent()->OutputToScreenPixel( aPos ); 3164 3165 if ( nFlags & WINDOW_POSSIZE_X ) 3166 aPos.X() = nX; 3167 3168 if ( nFlags & WINDOW_POSSIZE_Y ) 3169 aPos.Y() = nY; 3170 3171 sal_uInt16 nIndex; 3172 SetPosPixel( ImplCalcPos( this, Rectangle( aPos, GetParent()->GetSizePixel() ), FLOATWIN_POPUPMODE_DOWN, nIndex ) ); 3173 } 3174 3175 // if( !IsReallyVisible() ) 3176 { 3177 // Die ImplListBox erhaelt kein Resize, weil nicht sichtbar. 3178 // Die Fenster muessen aber ein Resize() erhalten, damit die 3179 // Anzahl der sichtbaren Eintraege fuer PgUp/PgDown stimmt. 3180 // Die Anzahl kann auch nicht von List/Combobox berechnet werden, 3181 // weil hierfuer auch die ggf. vorhandene vertikale Scrollbar 3182 // beruecksichtigt werden muss. 3183 mpImplLB->SetSizePixel( GetOutputSizePixel() ); 3184 ((Window*)mpImplLB)->Resize(); 3185 ((Window*)mpImplLB->GetMainWindow())->Resize(); 3186 } 3187 } 3188 3189 // ----------------------------------------------------------------------- 3190 3191 void ImplListBoxFloatingWindow::Resize() 3192 { 3193 mpImplLB->GetMainWindow()->ImplClearLayoutData(); 3194 FloatingWindow::Resize(); 3195 } 3196 3197 // ----------------------------------------------------------------------- 3198 3199 Size ImplListBoxFloatingWindow::CalcFloatSize() 3200 { 3201 Size aFloatSz( maPrefSz ); 3202 3203 sal_Int32 nLeft, nTop, nRight, nBottom; 3204 GetBorder( nLeft, nTop, nRight, nBottom ); 3205 3206 sal_uInt16 nLines = mpImplLB->GetEntryList()->GetEntryCount(); 3207 if ( mnDDLineCount && ( nLines > mnDDLineCount ) ) 3208 nLines = mnDDLineCount; 3209 3210 Size aSz = mpImplLB->CalcSize( nLines ); 3211 long nMaxHeight = aSz.Height() + nTop + nBottom; 3212 3213 if ( mnDDLineCount ) 3214 aFloatSz.Height() = nMaxHeight; 3215 3216 if( mbAutoWidth ) 3217 { 3218 // AutoSize erstmal nur fuer die Breite... 3219 3220 aFloatSz.Width() = aSz.Width() + nLeft + nRight; 3221 aFloatSz.Width() += nRight; // etwas mehr Platz sieht besser aus... 3222 3223 if ( ( aFloatSz.Height() < nMaxHeight ) || ( mnDDLineCount && ( mnDDLineCount < mpImplLB->GetEntryList()->GetEntryCount() ) ) ) 3224 { 3225 // dann wird noch der vertikale Scrollbar benoetigt 3226 long nSBWidth = GetSettings().GetStyleSettings().GetScrollBarSize(); 3227 aFloatSz.Width() += nSBWidth; 3228 } 3229 } 3230 3231 if ( aFloatSz.Height() > nMaxHeight ) 3232 aFloatSz.Height() = nMaxHeight; 3233 3234 // Minimale Hoehe, falls Hoehe nicht auf Float-Hoehe eingestellt wurde. 3235 // Der Parent vom FloatWin muss die DropDown-Combo/Listbox sein. 3236 Size aParentSz = GetParent()->GetSizePixel(); 3237 if( !mnDDLineCount && ( aFloatSz.Height() < aParentSz.Height() ) ) 3238 aFloatSz.Height() = aParentSz.Height(); 3239 3240 // Nicht schmaler als der Parent werden... 3241 if( aFloatSz.Width() < aParentSz.Width() ) 3242 aFloatSz.Width() = aParentSz.Width(); 3243 3244 // Hoehe auf Entries alignen... 3245 long nInnerHeight = aFloatSz.Height() - nTop - nBottom; 3246 long nEntryHeight = mpImplLB->GetEntryHeight(); 3247 if ( nInnerHeight % nEntryHeight ) 3248 { 3249 nInnerHeight /= nEntryHeight; 3250 nInnerHeight++; 3251 nInnerHeight *= nEntryHeight; 3252 aFloatSz.Height() = nInnerHeight + nTop + nBottom; 3253 } 3254 3255 return aFloatSz; 3256 } 3257 3258 // ----------------------------------------------------------------------- 3259 3260 void ImplListBoxFloatingWindow::StartFloat( sal_Bool bStartTracking ) 3261 { 3262 if( !IsInPopupMode() ) 3263 { 3264 Size aFloatSz = CalcFloatSize(); 3265 3266 SetSizePixel( aFloatSz ); 3267 mpImplLB->SetSizePixel( GetOutputSizePixel() ); 3268 3269 sal_uInt16 nPos = mpImplLB->GetEntryList()->GetSelectEntryPos( 0 ); 3270 mnPopupModeStartSaveSelection = nPos; 3271 3272 Size aSz = GetParent()->GetSizePixel(); 3273 Point aPos = GetParent()->GetPosPixel(); 3274 aPos = GetParent()->GetParent()->OutputToScreenPixel( aPos ); 3275 // FIXME: this ugly hack is for Mac/Aqua 3276 // should be replaced by a real mechanism to place the float rectangle 3277 if( ImplGetSVData()->maNWFData.mbNoFocusRects && 3278 GetParent()->IsNativeWidgetEnabled() ) 3279 { 3280 sal_Int32 nLeft = 4, nTop = 4, nRight = 4, nBottom = 4; 3281 aPos.X() += nLeft; 3282 aPos.Y() += nTop; 3283 aSz.Width() -= nLeft + nRight; 3284 aSz.Height() -= nTop + nBottom; 3285 } 3286 Rectangle aRect( aPos, aSz ); 3287 3288 // check if the control's parent is un-mirrored which is the case for form controls in a mirrored UI 3289 // where the document is unmirrored 3290 // because StartPopupMode() expects a rectangle in mirrored coordinates we have to re-mirror 3291 if( GetParent()->GetParent()->ImplIsAntiparallel() ) 3292 GetParent()->GetParent()->ImplReMirror( aRect ); 3293 3294 StartPopupMode( aRect, FLOATWIN_POPUPMODE_DOWN ); 3295 3296 if( nPos != LISTBOX_ENTRY_NOTFOUND ) 3297 mpImplLB->ShowProminentEntry( nPos ); 3298 3299 if( bStartTracking ) 3300 mpImplLB->GetMainWindow()->EnableMouseMoveSelect( sal_True ); 3301 3302 if ( mpImplLB->GetMainWindow()->IsGrabFocusAllowed() ) 3303 mpImplLB->GetMainWindow()->GrabFocus(); 3304 3305 mpImplLB->GetMainWindow()->ImplClearLayoutData(); 3306 } 3307 } 3308