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 sal_Bool bCurPosChange = (mnCurrentPos != nSelect); 921 //SelectEntries( nSelect, LET_MBDOWN, rMEvt.IsShift(), rMEvt.IsMod1() ); 922 SelectEntries( nSelect, LET_MBDOWN, rMEvt.IsShift(), rMEvt.IsMod1() ,bCurPosChange); 923 mbTrackingSelect = false; 924 if ( mbGrabFocus ) 925 GrabFocus(); 926 927 StartTracking( STARTTRACK_SCROLLREPEAT ); 928 } 929 } 930 if( rMEvt.GetClicks() == 2 ) 931 { 932 maDoubleClickHdl.Call( this ); 933 } 934 } 935 else // if ( mbGrabFocus ) 936 { 937 GrabFocus(); 938 } 939 } 940 941 // ----------------------------------------------------------------------- 942 943 void ImplListBoxWindow::MouseMove( const MouseEvent& rMEvt ) 944 { 945 if ( rMEvt.IsLeaveWindow() ) 946 { 947 if ( mbStackMode && IsMouseMoveSelect() && IsReallyVisible() ) 948 { 949 if ( rMEvt.GetPosPixel().Y() < 0 ) 950 { 951 DeselectAll(); 952 mnCurrentPos = LISTBOX_ENTRY_NOTFOUND; 953 SetTopEntry( 0 ); 954 if ( mbStackMode ) // #87072#, #92323# 955 { 956 mbTravelSelect = true; 957 mnSelectModifier = rMEvt.GetModifier(); 958 ImplCallSelect(); 959 mbTravelSelect = false; 960 } 961 962 } 963 } 964 } 965 else if ( ( ( !mbMulti && IsMouseMoveSelect() ) || mbStackMode ) && mpEntryList->GetEntryCount() ) 966 { 967 Point aPoint; 968 Rectangle aRect( aPoint, GetOutputSizePixel() ); 969 if( aRect.IsInside( rMEvt.GetPosPixel() ) ) 970 { 971 if ( IsMouseMoveSelect() ) 972 { 973 sal_uInt16 nSelect = GetEntryPosForPoint( rMEvt.GetPosPixel() ); 974 if( nSelect == LISTBOX_ENTRY_NOTFOUND ) 975 nSelect = mpEntryList->GetEntryCount() - 1; 976 nSelect = Min( nSelect, GetLastVisibleEntry() ); 977 nSelect = Min( nSelect, (sal_uInt16) ( mpEntryList->GetEntryCount() - 1 ) ); 978 // Select only visible Entries with MouseMove, otherwise Tracking... 979 if ( IsVisible( nSelect ) && 980 mpEntryList->IsEntrySelectable( nSelect ) && 981 ( ( nSelect != mnCurrentPos ) || !GetEntryList()->GetSelectEntryCount() || ( nSelect != GetEntryList()->GetSelectEntryPos( 0 ) ) ) ) 982 { 983 mbTrackingSelect = true; 984 if ( SelectEntries( nSelect, LET_TRACKING, sal_False, sal_False ) ) 985 { 986 if ( mbStackMode ) // #87072# 987 { 988 mbTravelSelect = true; 989 mnSelectModifier = rMEvt.GetModifier(); 990 ImplCallSelect(); 991 mbTravelSelect = false; 992 } 993 // When list box selection change by mouse move, notity 994 // VCLEVENT_LISTBOX_SELECT vcl event. 995 else 996 { 997 maListItemSelectHdl.Call(NULL); 998 } 999 } 1000 mbTrackingSelect = false; 1001 } 1002 } 1003 1004 // Falls der DD-Button gedrueckt wurde und jemand mit gedrueckter 1005 // Maustaste in die ListBox faehrt... 1006 if ( rMEvt.IsLeft() && !rMEvt.IsSynthetic() ) 1007 { 1008 if ( !mbMulti && GetEntryList()->GetSelectEntryCount() ) 1009 mnTrackingSaveSelection = GetEntryList()->GetSelectEntryPos( 0 ); 1010 else 1011 mnTrackingSaveSelection = LISTBOX_ENTRY_NOTFOUND; 1012 1013 if ( mbStackMode && ( mpEntryList->GetSelectionAnchor() == LISTBOX_ENTRY_NOTFOUND ) ) 1014 mpEntryList->SetSelectionAnchor( 0 ); 1015 1016 StartTracking( STARTTRACK_SCROLLREPEAT ); 1017 } 1018 } 1019 } 1020 } 1021 1022 // ----------------------------------------------------------------------- 1023 1024 void ImplListBoxWindow::DeselectAll() 1025 { 1026 while ( GetEntryList()->GetSelectEntryCount() ) 1027 { 1028 sal_uInt16 nS = GetEntryList()->GetSelectEntryPos( 0 ); 1029 SelectEntry( nS, sal_False ); 1030 } 1031 } 1032 1033 // ----------------------------------------------------------------------- 1034 1035 void ImplListBoxWindow::SelectEntry( sal_uInt16 nPos, sal_Bool bSelect ) 1036 { 1037 if( (mpEntryList->IsEntryPosSelected( nPos ) != bSelect) && mpEntryList->IsEntrySelectable( nPos ) ) 1038 { 1039 ImplHideFocusRect(); 1040 if( bSelect ) 1041 { 1042 if( !mbMulti ) 1043 { 1044 // Selektierten Eintrag deselektieren 1045 sal_uInt16 nDeselect = GetEntryList()->GetSelectEntryPos( 0 ); 1046 if( nDeselect != LISTBOX_ENTRY_NOTFOUND ) 1047 { 1048 //SelectEntryPos( nDeselect, sal_False ); 1049 GetEntryList()->SelectEntry( nDeselect, sal_False ); 1050 if ( IsUpdateMode() && IsReallyVisible() ) 1051 ImplPaint( nDeselect, sal_True ); 1052 } 1053 } 1054 mpEntryList->SelectEntry( nPos, sal_True ); 1055 mnCurrentPos = nPos; 1056 if ( ( nPos != LISTBOX_ENTRY_NOTFOUND ) && IsUpdateMode() ) 1057 { 1058 ImplPaint( nPos ); 1059 if ( !IsVisible( nPos ) ) 1060 { 1061 ImplClearLayoutData(); 1062 sal_uInt16 nVisibleEntries = GetLastVisibleEntry()-mnTop; 1063 if ( !nVisibleEntries || !IsReallyVisible() || ( nPos < GetTopEntry() ) ) 1064 { 1065 Resize(); 1066 ShowProminentEntry( nPos ); 1067 } 1068 else 1069 { 1070 ShowProminentEntry( nPos ); 1071 } 1072 } 1073 } 1074 } 1075 else 1076 { 1077 mpEntryList->SelectEntry( nPos, sal_False ); 1078 ImplPaint( nPos, sal_True ); 1079 } 1080 mbSelectionChanged = true; 1081 } 1082 } 1083 1084 // ----------------------------------------------------------------------- 1085 1086 sal_Bool ImplListBoxWindow::SelectEntries( sal_uInt16 nSelect, LB_EVENT_TYPE eLET, sal_Bool bShift, sal_Bool bCtrl, sal_Bool bSelectPosChange /*=FALSE*/ ) 1087 { 1088 sal_Bool bFocusChanged = sal_False; 1089 sal_Bool bSelectionChanged = sal_False; 1090 1091 if( IsEnabled() && mpEntryList->IsEntrySelectable( nSelect ) ) 1092 { 1093 // Hier (Single-ListBox) kann nur ein Eintrag deselektiert werden 1094 if( !mbMulti ) 1095 { 1096 sal_uInt16 nDeselect = mpEntryList->GetSelectEntryPos( 0 ); 1097 if( nSelect != nDeselect ) 1098 { 1099 SelectEntry( nSelect, sal_True ); 1100 mpEntryList->SetLastSelected( nSelect ); 1101 bFocusChanged = sal_True; 1102 bSelectionChanged = sal_True; 1103 } 1104 } 1105 // MultiListBox ohne Modifier 1106 else if( mbSimpleMode && !bCtrl && !bShift ) 1107 { 1108 sal_uInt16 nEntryCount = mpEntryList->GetEntryCount(); 1109 for ( sal_uInt16 nPos = 0; nPos < nEntryCount; nPos++ ) 1110 { 1111 sal_Bool bSelect = nPos == nSelect; 1112 if ( mpEntryList->IsEntryPosSelected( nPos ) != bSelect ) 1113 { 1114 SelectEntry( nPos, bSelect ); 1115 bFocusChanged = sal_True; 1116 bSelectionChanged = sal_True; 1117 } 1118 } 1119 mpEntryList->SetLastSelected( nSelect ); 1120 mpEntryList->SetSelectionAnchor( nSelect ); 1121 } 1122 // MultiListBox nur mit CTRL/SHIFT oder nicht im SimpleMode 1123 else if( ( !mbSimpleMode /* && !bShift */ ) || ( (mbSimpleMode && ( bCtrl || bShift )) || mbStackMode ) ) 1124 { 1125 // Space fuer Selektionswechsel 1126 if( !bShift && ( ( eLET == LET_KEYSPACE ) || ( eLET == LET_MBDOWN ) ) ) 1127 { 1128 sal_Bool bSelect = ( mbStackMode && IsMouseMoveSelect() ) ? sal_True : !mpEntryList->IsEntryPosSelected( nSelect ); 1129 if ( mbStackMode ) 1130 { 1131 sal_uInt16 n; 1132 if ( bSelect ) 1133 { 1134 // All entries before nSelect must be selected... 1135 for ( n = 0; n < nSelect; n++ ) 1136 SelectEntry( n, sal_True ); 1137 } 1138 if ( !bSelect ) 1139 { 1140 for ( n = nSelect+1; n < mpEntryList->GetEntryCount(); n++ ) 1141 SelectEntry( n, sal_False ); 1142 } 1143 } 1144 SelectEntry( nSelect, bSelect ); 1145 mpEntryList->SetLastSelected( nSelect ); 1146 mpEntryList->SetSelectionAnchor( mbStackMode ? 0 : nSelect ); 1147 if ( !mpEntryList->IsEntryPosSelected( nSelect ) ) 1148 mpEntryList->SetSelectionAnchor( LISTBOX_ENTRY_NOTFOUND ); 1149 bFocusChanged = sal_True; 1150 bSelectionChanged = sal_True; 1151 } 1152 else if( ( ( eLET == LET_TRACKING ) && ( nSelect != mnCurrentPos ) ) || 1153 ( (bShift||mbStackMode) && ( ( eLET == LET_KEYMOVE ) || ( eLET == LET_MBDOWN ) ) ) ) 1154 { 1155 mnCurrentPos = nSelect; 1156 bFocusChanged = sal_True; 1157 1158 sal_uInt16 nAnchor = mpEntryList->GetSelectionAnchor(); 1159 if( ( nAnchor == LISTBOX_ENTRY_NOTFOUND ) && ( mpEntryList->GetSelectEntryCount() || mbStackMode ) ) 1160 { 1161 nAnchor = mbStackMode ? 0 : mpEntryList->GetSelectEntryPos( mpEntryList->GetSelectEntryCount() - 1 ); 1162 } 1163 if( nAnchor != LISTBOX_ENTRY_NOTFOUND ) 1164 { 1165 // Alle Eintraege vom Anchor bis nSelect muessen selektiert sein 1166 sal_uInt16 nStart = Min( nSelect, nAnchor ); 1167 sal_uInt16 nEnd = Max( nSelect, nAnchor ); 1168 for ( sal_uInt16 n = nStart; n <= nEnd; n++ ) 1169 { 1170 if ( !mpEntryList->IsEntryPosSelected( n ) ) 1171 { 1172 SelectEntry( n, sal_True ); 1173 bSelectionChanged = sal_True; 1174 } 1175 } 1176 1177 // Ggf. muss noch was deselektiert werden... 1178 sal_uInt16 nLast = mpEntryList->GetLastSelected(); 1179 if ( nLast != LISTBOX_ENTRY_NOTFOUND ) 1180 { 1181 if ( ( nLast > nSelect ) && ( nLast > nAnchor ) ) 1182 { 1183 for ( sal_uInt16 n = nSelect+1; n <= nLast; n++ ) 1184 { 1185 if ( mpEntryList->IsEntryPosSelected( n ) ) 1186 { 1187 SelectEntry( n, sal_False ); 1188 bSelectionChanged = sal_True; 1189 } 1190 } 1191 } 1192 else if ( ( nLast < nSelect ) && ( nLast < nAnchor ) ) 1193 { 1194 for ( sal_uInt16 n = nLast; n < nSelect; n++ ) 1195 { 1196 if ( mpEntryList->IsEntryPosSelected( n ) ) 1197 { 1198 SelectEntry( n, sal_False ); 1199 bSelectionChanged = sal_True; 1200 } 1201 } 1202 } 1203 } 1204 mpEntryList->SetLastSelected( nSelect ); 1205 } 1206 } 1207 else if( eLET != LET_TRACKING ) 1208 { 1209 ImplHideFocusRect(); 1210 ImplPaint( nSelect, sal_True ); 1211 bFocusChanged = sal_True; 1212 } 1213 } 1214 else if( bShift ) 1215 { 1216 bFocusChanged = sal_True; 1217 } 1218 1219 if( bSelectionChanged ) 1220 mbSelectionChanged = true; 1221 1222 if( bFocusChanged ) 1223 { 1224 long nHeightDiff = mpEntryList->GetAddedHeight( nSelect, mnTop, 0 ); 1225 maFocusRect.SetPos( Point( 0, nHeightDiff ) ); 1226 Size aSz( maFocusRect.GetWidth(), 1227 mpEntryList->GetEntryHeight( nSelect ) ); 1228 maFocusRect.SetSize( aSz ); 1229 if( HasFocus() ) 1230 ImplShowFocusRect(); 1231 if (bSelectPosChange) 1232 { 1233 maFocusHdl.Call(reinterpret_cast<void*>(nSelect)); 1234 } 1235 } 1236 ImplClearLayoutData(); 1237 } 1238 return bSelectionChanged; 1239 } 1240 1241 // ----------------------------------------------------------------------- 1242 1243 void ImplListBoxWindow::Tracking( const TrackingEvent& rTEvt ) 1244 { 1245 Point aPoint; 1246 Rectangle aRect( aPoint, GetOutputSizePixel() ); 1247 sal_Bool bInside = aRect.IsInside( rTEvt.GetMouseEvent().GetPosPixel() ); 1248 1249 if( rTEvt.IsTrackingCanceled() || rTEvt.IsTrackingEnded() ) // MouseButtonUp 1250 { 1251 if ( bInside && !rTEvt.IsTrackingCanceled() ) 1252 { 1253 mnSelectModifier = rTEvt.GetMouseEvent().GetModifier(); 1254 ImplCallSelect(); 1255 } 1256 else 1257 { 1258 maCancelHdl.Call( NULL ); 1259 if ( !mbMulti ) 1260 { 1261 mbTrackingSelect = true; 1262 SelectEntry( mnTrackingSaveSelection, sal_True ); 1263 mbTrackingSelect = false; 1264 if ( mnTrackingSaveSelection != LISTBOX_ENTRY_NOTFOUND ) 1265 { 1266 long nHeightDiff = mpEntryList->GetAddedHeight( mnCurrentPos, mnTop, 0 ); 1267 maFocusRect.SetPos( Point( 0, nHeightDiff ) ); 1268 Size aSz( maFocusRect.GetWidth(), 1269 mpEntryList->GetEntryHeight( mnCurrentPos ) ); 1270 maFocusRect.SetSize( aSz ); 1271 ImplShowFocusRect(); 1272 } 1273 } 1274 } 1275 1276 mbTrack = false; 1277 } 1278 else 1279 { 1280 sal_Bool bTrackOrQuickClick = mbTrack; 1281 if( !mbTrack ) 1282 { 1283 if ( bInside ) 1284 { 1285 mbTrack = true; 1286 } 1287 1288 // Folgender Fall tritt nur auf, wenn man ganz kurz die Maustaste drueckt 1289 if( rTEvt.IsTrackingEnded() && mbTrack ) 1290 { 1291 bTrackOrQuickClick = sal_True; 1292 mbTrack = false; 1293 } 1294 } 1295 1296 if( bTrackOrQuickClick ) 1297 { 1298 MouseEvent aMEvt = rTEvt.GetMouseEvent(); 1299 Point aPt( aMEvt.GetPosPixel() ); 1300 sal_Bool bShift = aMEvt.IsShift(); 1301 sal_Bool bCtrl = aMEvt.IsMod1(); 1302 1303 sal_uInt16 nSelect = LISTBOX_ENTRY_NOTFOUND; 1304 if( aPt.Y() < 0 ) 1305 { 1306 if ( mnCurrentPos != LISTBOX_ENTRY_NOTFOUND ) 1307 { 1308 nSelect = mnCurrentPos ? ( mnCurrentPos - 1 ) : 0; 1309 if( nSelect < mnTop ) 1310 SetTopEntry( mnTop-1 ); 1311 } 1312 } 1313 else if( aPt.Y() > GetOutputSizePixel().Height() ) 1314 { 1315 if ( mnCurrentPos != LISTBOX_ENTRY_NOTFOUND ) 1316 { 1317 nSelect = Min( (sal_uInt16)(mnCurrentPos+1), (sal_uInt16)(mpEntryList->GetEntryCount()-1) ); 1318 if( nSelect >= GetLastVisibleEntry() ) 1319 SetTopEntry( mnTop+1 ); 1320 } 1321 } 1322 else 1323 { 1324 nSelect = (sal_uInt16) ( ( aPt.Y() + mnBorder ) / mnMaxHeight ) + (sal_uInt16) mnTop; 1325 nSelect = Min( nSelect, GetLastVisibleEntry() ); 1326 nSelect = Min( nSelect, (sal_uInt16) ( mpEntryList->GetEntryCount() - 1 ) ); 1327 } 1328 1329 if ( bInside ) 1330 { 1331 if ( ( nSelect != mnCurrentPos ) || !GetEntryList()->GetSelectEntryCount() ) 1332 { 1333 mbTrackingSelect = true; 1334 if ( SelectEntries( nSelect, LET_TRACKING, bShift, bCtrl ) ) 1335 { 1336 if ( mbStackMode ) // #87734# (#87072#) 1337 { 1338 mbTravelSelect = true; 1339 mnSelectModifier = rTEvt.GetMouseEvent().GetModifier(); 1340 ImplCallSelect(); 1341 mbTravelSelect = false; 1342 } 1343 } 1344 mbTrackingSelect = false; 1345 } 1346 } 1347 else 1348 { 1349 if ( !mbMulti && GetEntryList()->GetSelectEntryCount() ) 1350 { 1351 mbTrackingSelect = true; 1352 SelectEntry( GetEntryList()->GetSelectEntryPos( 0 ), sal_False ); 1353 mbTrackingSelect = false; 1354 } 1355 else if ( mbStackMode ) 1356 { 1357 if ( ( rTEvt.GetMouseEvent().GetPosPixel().X() > 0 ) && ( rTEvt.GetMouseEvent().GetPosPixel().X() < aRect.Right() ) ) 1358 { 1359 if ( ( rTEvt.GetMouseEvent().GetPosPixel().Y() < 0 ) || ( rTEvt.GetMouseEvent().GetPosPixel().Y() > GetOutputSizePixel().Height() ) ) 1360 { 1361 sal_Bool bSelectionChanged = sal_False; 1362 if ( ( rTEvt.GetMouseEvent().GetPosPixel().Y() < 0 ) 1363 && !mnCurrentPos ) 1364 { 1365 if ( mpEntryList->IsEntryPosSelected( 0 ) ) 1366 { 1367 SelectEntry( 0, sal_False ); 1368 bSelectionChanged = sal_True; 1369 nSelect = LISTBOX_ENTRY_NOTFOUND; 1370 1371 } 1372 } 1373 else 1374 { 1375 mbTrackingSelect = true; 1376 bSelectionChanged = SelectEntries( nSelect, LET_TRACKING, bShift, bCtrl ); 1377 mbTrackingSelect = false; 1378 } 1379 1380 if ( bSelectionChanged ) 1381 { 1382 mbSelectionChanged = true; 1383 mbTravelSelect = true; 1384 mnSelectModifier = rTEvt.GetMouseEvent().GetModifier(); 1385 ImplCallSelect(); 1386 mbTravelSelect = false; 1387 } 1388 } 1389 } 1390 } 1391 } 1392 mnCurrentPos = nSelect; 1393 if ( mnCurrentPos == LISTBOX_ENTRY_NOTFOUND ) 1394 { 1395 ImplHideFocusRect(); 1396 } 1397 else 1398 { 1399 long nHeightDiff = mpEntryList->GetAddedHeight( mnCurrentPos, mnTop, 0 ); 1400 maFocusRect.SetPos( Point( 0, nHeightDiff ) ); 1401 Size aSz( maFocusRect.GetWidth(), mpEntryList->GetEntryHeight( mnCurrentPos ) ); 1402 maFocusRect.SetSize( aSz ); 1403 ImplShowFocusRect(); 1404 } 1405 } 1406 } 1407 } 1408 1409 1410 // ----------------------------------------------------------------------- 1411 1412 void ImplListBoxWindow::KeyInput( const KeyEvent& rKEvt ) 1413 { 1414 if( !ProcessKeyInput( rKEvt ) ) 1415 Control::KeyInput( rKEvt ); 1416 } 1417 1418 // ----------------------------------------------------------------------- 1419 1420 #define IMPL_SELECT_NODIRECTION 0 1421 #define IMPL_SELECT_UP 1 1422 #define IMPL_SELECT_DOWN 2 1423 1424 sal_Bool ImplListBoxWindow::ProcessKeyInput( const KeyEvent& rKEvt ) 1425 { 1426 // zu selektierender Eintrag 1427 sal_uInt16 nSelect = LISTBOX_ENTRY_NOTFOUND; 1428 LB_EVENT_TYPE eLET = LET_KEYMOVE; 1429 1430 KeyCode aKeyCode = rKEvt.GetKeyCode(); 1431 1432 sal_Bool bShift = aKeyCode.IsShift(); 1433 sal_Bool bCtrl = aKeyCode.IsMod1() || aKeyCode.IsMod3(); 1434 sal_Bool bMod2 = aKeyCode.IsMod2(); 1435 sal_Bool bDone = sal_False; 1436 1437 switch( aKeyCode.GetCode() ) 1438 { 1439 case KEY_UP: 1440 { 1441 if ( IsReadOnly() ) 1442 { 1443 if ( GetTopEntry() ) 1444 SetTopEntry( GetTopEntry()-1 ); 1445 } 1446 else if ( !bMod2 ) 1447 { 1448 if( mnCurrentPos == LISTBOX_ENTRY_NOTFOUND ) 1449 { 1450 nSelect = mpEntryList->FindFirstSelectable( 0, true ); 1451 } 1452 else if ( mnCurrentPos ) 1453 { 1454 // search first selectable above the current position 1455 nSelect = mpEntryList->FindFirstSelectable( mnCurrentPos - 1, false ); 1456 } 1457 1458 if( ( nSelect != LISTBOX_ENTRY_NOTFOUND ) && ( nSelect < mnTop ) ) 1459 SetTopEntry( mnTop-1 ); 1460 1461 bDone = sal_True; 1462 } 1463 maQuickSelectionEngine.Reset(); 1464 } 1465 break; 1466 1467 case KEY_DOWN: 1468 { 1469 if ( IsReadOnly() ) 1470 { 1471 SetTopEntry( GetTopEntry()+1 ); 1472 } 1473 else if ( !bMod2 ) 1474 { 1475 if( mnCurrentPos == LISTBOX_ENTRY_NOTFOUND ) 1476 { 1477 nSelect = mpEntryList->FindFirstSelectable( 0, true ); 1478 } 1479 else if ( (mnCurrentPos+1) < mpEntryList->GetEntryCount() ) 1480 { 1481 // search first selectable below the current position 1482 nSelect = mpEntryList->FindFirstSelectable( mnCurrentPos + 1, true ); 1483 } 1484 1485 if( ( nSelect != LISTBOX_ENTRY_NOTFOUND ) && ( nSelect >= GetLastVisibleEntry() ) ) 1486 SetTopEntry( mnTop+1 ); 1487 1488 bDone = sal_True; 1489 } 1490 maQuickSelectionEngine.Reset(); 1491 } 1492 break; 1493 1494 case KEY_PAGEUP: 1495 { 1496 if ( IsReadOnly() ) 1497 { 1498 sal_uInt16 nCurVis = GetLastVisibleEntry() - mnTop +1; 1499 SetTopEntry( ( mnTop > nCurVis ) ? 1500 (mnTop-nCurVis) : 0 ); 1501 } 1502 else if ( !bCtrl && !bMod2 ) 1503 { 1504 if( mnCurrentPos == LISTBOX_ENTRY_NOTFOUND ) 1505 { 1506 nSelect = mpEntryList->FindFirstSelectable( 0, true ); 1507 } 1508 else if ( mnCurrentPos ) 1509 { 1510 if( mnCurrentPos == mnTop ) 1511 { 1512 sal_uInt16 nCurVis = GetLastVisibleEntry() - mnTop +1; 1513 SetTopEntry( ( mnTop > nCurVis ) ? ( mnTop-nCurVis+1 ) : 0 ); 1514 } 1515 1516 // find first selectable starting from mnTop looking foreward 1517 nSelect = mpEntryList->FindFirstSelectable( mnTop, true ); 1518 } 1519 bDone = sal_True; 1520 } 1521 maQuickSelectionEngine.Reset(); 1522 } 1523 break; 1524 1525 case KEY_PAGEDOWN: 1526 { 1527 if ( IsReadOnly() ) 1528 { 1529 SetTopEntry( GetLastVisibleEntry() ); 1530 } 1531 else if ( !bCtrl && !bMod2 ) 1532 { 1533 if( mnCurrentPos == LISTBOX_ENTRY_NOTFOUND ) 1534 { 1535 nSelect = mpEntryList->FindFirstSelectable( 0, true ); 1536 } 1537 else if ( (mnCurrentPos+1) < mpEntryList->GetEntryCount() ) 1538 { 1539 sal_uInt16 nCount = mpEntryList->GetEntryCount(); 1540 sal_uInt16 nCurVis = GetLastVisibleEntry() - mnTop; 1541 sal_uInt16 nTmp = Min( nCurVis, nCount ); 1542 nTmp += mnTop - 1; 1543 if( mnCurrentPos == nTmp && mnCurrentPos != nCount - 1 ) 1544 { 1545 long nTmp2 = Min( (long)(nCount-nCurVis), (long)((long)mnTop+(long)nCurVis-1) ); 1546 nTmp2 = Max( (long)0 , nTmp2 ); 1547 nTmp = (sal_uInt16)(nTmp2+(nCurVis-1) ); 1548 SetTopEntry( (sal_uInt16)nTmp2 ); 1549 } 1550 // find first selectable starting from nTmp looking backwards 1551 nSelect = mpEntryList->FindFirstSelectable( nTmp, false ); 1552 } 1553 bDone = sal_True; 1554 } 1555 maQuickSelectionEngine.Reset(); 1556 } 1557 break; 1558 1559 case KEY_HOME: 1560 { 1561 if ( IsReadOnly() ) 1562 { 1563 SetTopEntry( 0 ); 1564 } 1565 else if ( !bCtrl && !bMod2 ) 1566 { 1567 if ( mnCurrentPos ) 1568 { 1569 nSelect = mpEntryList->FindFirstSelectable( mpEntryList->GetEntryCount() ? 0 : LISTBOX_ENTRY_NOTFOUND, true ); 1570 if( mnTop != 0 ) 1571 SetTopEntry( 0 ); 1572 1573 bDone = sal_True; 1574 } 1575 } 1576 maQuickSelectionEngine.Reset(); 1577 } 1578 break; 1579 1580 case KEY_END: 1581 { 1582 if ( IsReadOnly() ) 1583 { 1584 SetTopEntry( 0xFFFF ); 1585 } 1586 else if ( !bCtrl && !bMod2 ) 1587 { 1588 if( mnCurrentPos == LISTBOX_ENTRY_NOTFOUND ) 1589 { 1590 nSelect = mpEntryList->FindFirstSelectable( 0, true ); 1591 } 1592 else if ( (mnCurrentPos+1) < mpEntryList->GetEntryCount() ) 1593 { 1594 sal_uInt16 nCount = mpEntryList->GetEntryCount(); 1595 nSelect = mpEntryList->FindFirstSelectable( nCount - 1, false ); 1596 sal_uInt16 nCurVis = GetLastVisibleEntry() - mnTop + 1; 1597 if( nCount > nCurVis ) 1598 SetTopEntry( nCount - nCurVis ); 1599 } 1600 bDone = sal_True; 1601 } 1602 maQuickSelectionEngine.Reset(); 1603 } 1604 break; 1605 1606 case KEY_LEFT: 1607 { 1608 if ( !bCtrl && !bMod2 ) 1609 { 1610 ScrollHorz( -HORZ_SCROLL ); 1611 bDone = sal_True; 1612 } 1613 maQuickSelectionEngine.Reset(); 1614 } 1615 break; 1616 1617 case KEY_RIGHT: 1618 { 1619 if ( !bCtrl && !bMod2 ) 1620 { 1621 ScrollHorz( HORZ_SCROLL ); 1622 bDone = sal_True; 1623 } 1624 maQuickSelectionEngine.Reset(); 1625 } 1626 break; 1627 1628 case KEY_RETURN: 1629 { 1630 if ( !bMod2 && !IsReadOnly() ) 1631 { 1632 mnSelectModifier = rKEvt.GetKeyCode().GetModifier(); 1633 ImplCallSelect(); 1634 bDone = sal_False; // RETURN nicht abfangen. 1635 } 1636 maQuickSelectionEngine.Reset(); 1637 } 1638 break; 1639 1640 case KEY_SPACE: 1641 { 1642 if ( !bMod2 && !IsReadOnly() ) 1643 { 1644 if( mbMulti && ( !mbSimpleMode || ( mbSimpleMode && bCtrl && !bShift ) || mbStackMode ) ) 1645 { 1646 nSelect = mnCurrentPos; 1647 eLET = LET_KEYSPACE; 1648 } 1649 bDone = sal_True; 1650 } 1651 maQuickSelectionEngine.Reset(); 1652 } 1653 break; 1654 1655 case KEY_A: 1656 { 1657 if( bCtrl && mbMulti ) 1658 { 1659 // paint only once 1660 sal_Bool bUpdates = IsUpdateMode(); 1661 SetUpdateMode( sal_False ); 1662 1663 sal_uInt16 nEntryCount = mpEntryList->GetEntryCount(); 1664 for( sal_uInt16 i = 0; i < nEntryCount; i++ ) 1665 SelectEntry( i, sal_True ); 1666 1667 // restore update mode 1668 SetUpdateMode( bUpdates ); 1669 Invalidate(); 1670 1671 maQuickSelectionEngine.Reset(); 1672 1673 bDone = sal_True; 1674 break; 1675 } 1676 } 1677 // fall through intentional 1678 default: 1679 { 1680 if ( !IsReadOnly() ) 1681 { 1682 bDone = maQuickSelectionEngine.HandleKeyEvent( rKEvt ); 1683 } 1684 } 1685 break; 1686 } 1687 1688 if ( ( nSelect != LISTBOX_ENTRY_NOTFOUND ) 1689 && ( ( !mpEntryList->IsEntryPosSelected( nSelect ) ) 1690 || ( eLET == LET_KEYSPACE ) 1691 ) 1692 ) 1693 { 1694 DBG_ASSERT( !mpEntryList->IsEntryPosSelected( nSelect ) || mbMulti, "ImplListBox: Selecting same Entry" ); 1695 if( nSelect >= mpEntryList->GetEntryCount() ) 1696 nSelect = mpEntryList->GetEntryCount()-1; 1697 sal_Bool bCurPosChange = (mnCurrentPos != nSelect); 1698 mnCurrentPos = nSelect; 1699 //if ( SelectEntries( nSelect, eLET, bShift, bCtrl ) ) 1700 if(SelectEntries( nSelect, eLET, bShift, bCtrl ,bCurPosChange)) 1701 { 1702 mbTravelSelect = true; 1703 mnSelectModifier = rKEvt.GetKeyCode().GetModifier(); 1704 ImplCallSelect(); 1705 mbTravelSelect = false; 1706 } 1707 } 1708 1709 return bDone; 1710 } 1711 1712 // ----------------------------------------------------------------------- 1713 namespace 1714 { 1715 static ::vcl::StringEntryIdentifier lcl_getEntry( const ImplEntryList& _rList, sal_uInt16 _nPos, String& _out_entryText ) 1716 { 1717 OSL_PRECOND( ( _nPos != LISTBOX_ENTRY_NOTFOUND ), "lcl_getEntry: invalid position!" ); 1718 sal_uInt16 nEntryCount( _rList.GetEntryCount() ); 1719 if ( _nPos >= nEntryCount ) 1720 _nPos = 0; 1721 _out_entryText = _rList.GetEntryText( _nPos ); 1722 1723 // ::vcl::StringEntryIdentifier does not allow for 0 values, but our position is 0-based 1724 // => normalize 1725 return reinterpret_cast< ::vcl::StringEntryIdentifier >( _nPos + 1 ); 1726 } 1727 1728 static sal_uInt16 lcl_getEntryPos( ::vcl::StringEntryIdentifier _entry ) 1729 { 1730 // our pos is 0-based, but StringEntryIdentifier does not allow for a NULL 1731 return static_cast< sal_uInt16 >( reinterpret_cast< sal_Int64 >( _entry ) ) - 1; 1732 } 1733 } 1734 1735 // ----------------------------------------------------------------------- 1736 ::vcl::StringEntryIdentifier ImplListBoxWindow::CurrentEntry( String& _out_entryText ) const 1737 { 1738 return lcl_getEntry( *GetEntryList(), ( mnCurrentPos == LISTBOX_ENTRY_NOTFOUND ) ? 0 : mnCurrentPos + 1, _out_entryText ); 1739 } 1740 1741 // ----------------------------------------------------------------------- 1742 ::vcl::StringEntryIdentifier ImplListBoxWindow::NextEntry( ::vcl::StringEntryIdentifier _currentEntry, String& _out_entryText ) const 1743 { 1744 sal_uInt16 nNextPos = lcl_getEntryPos( _currentEntry ) + 1; 1745 return lcl_getEntry( *GetEntryList(), nNextPos, _out_entryText ); 1746 } 1747 1748 // ----------------------------------------------------------------------- 1749 void ImplListBoxWindow::SelectEntry( ::vcl::StringEntryIdentifier _entry ) 1750 { 1751 sal_uInt16 nSelect = lcl_getEntryPos( _entry ); 1752 if ( mpEntryList->IsEntryPosSelected( nSelect ) ) 1753 { 1754 // ignore that. This method is a callback from the QuickSelectionEngine, which means the user attempted 1755 // to select the given entry by typing its starting letters. No need to act. 1756 return; 1757 } 1758 1759 // normalize 1760 OSL_ENSURE( nSelect < mpEntryList->GetEntryCount(), "ImplListBoxWindow::SelectEntry: how that?" ); 1761 if( nSelect >= mpEntryList->GetEntryCount() ) 1762 nSelect = mpEntryList->GetEntryCount()-1; 1763 1764 // make visible 1765 ShowProminentEntry( nSelect ); 1766 1767 // actually select 1768 mnCurrentPos = nSelect; 1769 if ( SelectEntries( nSelect, LET_KEYMOVE, sal_False, sal_False ) ) 1770 { 1771 mbTravelSelect = true; 1772 mnSelectModifier = 0; 1773 ImplCallSelect(); 1774 mbTravelSelect = false; 1775 } 1776 } 1777 1778 // ----------------------------------------------------------------------- 1779 1780 void ImplListBoxWindow::ImplPaint( sal_uInt16 nPos, sal_Bool bErase, bool bLayout ) 1781 { 1782 const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings(); 1783 1784 const ImplEntryType* pEntry = mpEntryList->GetEntryPtr( nPos ); 1785 if( ! pEntry ) 1786 return; 1787 1788 long nWidth = GetOutputSizePixel().Width(); 1789 long nY = mpEntryList->GetAddedHeight( nPos, mnTop ); 1790 Rectangle aRect( Point( 0, nY ), Size( nWidth, pEntry->mnHeight ) ); 1791 1792 if( ! bLayout ) 1793 { 1794 if( mpEntryList->IsEntryPosSelected( nPos ) ) 1795 { 1796 SetTextColor( !IsEnabled() ? rStyleSettings.GetDisableColor() : rStyleSettings.GetHighlightTextColor() ); 1797 SetFillColor( rStyleSettings.GetHighlightColor() ); 1798 SetTextFillColor( rStyleSettings.GetHighlightColor() ); 1799 DrawRect( aRect ); 1800 } 1801 else 1802 { 1803 ImplInitSettings( sal_False, sal_True, sal_False ); 1804 if( !IsEnabled() ) 1805 SetTextColor( rStyleSettings.GetDisableColor() ); 1806 SetTextFillColor(); 1807 if( bErase ) 1808 Erase( aRect ); 1809 } 1810 } 1811 1812 if ( IsUserDrawEnabled() ) 1813 { 1814 mbInUserDraw = true; 1815 mnUserDrawEntry = nPos; 1816 aRect.Left() -= mnLeft; 1817 if ( nPos < GetEntryList()->GetMRUCount() ) 1818 nPos = GetEntryList()->FindEntry( GetEntryList()->GetEntryText( nPos ) ); 1819 nPos = sal::static_int_cast<sal_uInt16>(nPos - GetEntryList()->GetMRUCount()); 1820 UserDrawEvent aUDEvt( this, aRect, nPos, 0 ); 1821 maUserDrawHdl.Call( &aUDEvt ); 1822 mbInUserDraw = false; 1823 } 1824 else 1825 { 1826 DrawEntry( nPos, sal_True, sal_True, sal_False, bLayout ); 1827 } 1828 } 1829 1830 // ----------------------------------------------------------------------- 1831 1832 void ImplListBoxWindow::DrawEntry( sal_uInt16 nPos, sal_Bool bDrawImage, sal_Bool bDrawText, sal_Bool bDrawTextAtImagePos, bool bLayout ) 1833 { 1834 const ImplEntryType* pEntry = mpEntryList->GetEntryPtr( nPos ); 1835 if( ! pEntry ) 1836 return; 1837 1838 // Bei Aenderungen in dieser Methode ggf. auch ImplWin::DrawEntry() anpassen. 1839 1840 if ( mbInUserDraw ) 1841 nPos = mnUserDrawEntry; // real entry, not the matching entry from MRU 1842 1843 long nY = mpEntryList->GetAddedHeight( nPos, mnTop ); 1844 Size aImgSz; 1845 1846 if( bDrawImage && mpEntryList->HasImages() && !bLayout ) 1847 { 1848 Image aImage = mpEntryList->GetEntryImage( nPos ); 1849 if( !!aImage ) 1850 { 1851 aImgSz = aImage.GetSizePixel(); 1852 Point aPtImg( mnBorder - mnLeft, nY + ( ( pEntry->mnHeight - aImgSz.Height() ) / 2 ) ); 1853 1854 // pb: #106948# explicit mirroring for calc 1855 if ( mbMirroring ) 1856 // right aligned 1857 aPtImg.X() = mnMaxWidth + mnBorder - aImgSz.Width() - mnLeft; 1858 1859 if ( !IsZoom() ) 1860 { 1861 DrawImage( aPtImg, aImage ); 1862 } 1863 else 1864 { 1865 aImgSz.Width() = CalcZoom( aImgSz.Width() ); 1866 aImgSz.Height() = CalcZoom( aImgSz.Height() ); 1867 DrawImage( aPtImg, aImgSz, aImage ); 1868 } 1869 1870 const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings(); 1871 const sal_uInt16 nEdgeBlendingPercent(GetEdgeBlending() ? rStyleSettings.GetEdgeBlending() : 0); 1872 1873 if(nEdgeBlendingPercent && aImgSz.Width() && aImgSz.Height()) 1874 { 1875 const Color& rTopLeft(rStyleSettings.GetEdgeBlendingTopLeftColor()); 1876 const Color& rBottomRight(rStyleSettings.GetEdgeBlendingBottomRightColor()); 1877 const sal_uInt8 nAlpha((nEdgeBlendingPercent * 255) / 100); 1878 const BitmapEx aBlendFrame(createBlendFrame(aImgSz, nAlpha, rTopLeft, rBottomRight)); 1879 1880 if(!aBlendFrame.IsEmpty()) 1881 { 1882 DrawBitmapEx(aPtImg, aBlendFrame); 1883 } 1884 } 1885 } 1886 } 1887 1888 if( bDrawText ) 1889 { 1890 MetricVector* pVector = bLayout ? &mpControlData->mpLayoutData->m_aUnicodeBoundRects : NULL; 1891 String* pDisplayText = bLayout ? &mpControlData->mpLayoutData->m_aDisplayText : NULL; 1892 XubString aStr( mpEntryList->GetEntryText( nPos ) ); 1893 if ( aStr.Len() ) 1894 { 1895 long nMaxWidth = Max( static_cast< long >( mnMaxWidth ), 1896 GetOutputSizePixel().Width() - 2*mnBorder ); 1897 // a multiline entry should only be as wide a the window 1898 if( (pEntry->mnFlags & LISTBOX_ENTRY_FLAG_MULTILINE) ) 1899 nMaxWidth = GetOutputSizePixel().Width() - 2*mnBorder; 1900 1901 Rectangle aTextRect( Point( mnBorder - mnLeft, nY ), 1902 Size( nMaxWidth, pEntry->mnHeight ) ); 1903 1904 if( !bDrawTextAtImagePos && ( mpEntryList->HasEntryImage(nPos) || IsUserDrawEnabled() ) ) 1905 { 1906 long nImageWidth = Max( mnMaxImgWidth, maUserItemSize.Width() ); 1907 aTextRect.Left() += nImageWidth + IMG_TXT_DISTANCE; 1908 } 1909 1910 if( bLayout ) 1911 mpControlData->mpLayoutData->m_aLineIndices.push_back( mpControlData->mpLayoutData->m_aDisplayText.Len() ); 1912 1913 // pb: #106948# explicit mirroring for calc 1914 if ( mbMirroring ) 1915 { 1916 // right aligned 1917 aTextRect.Left() = nMaxWidth + mnBorder - GetTextWidth( aStr ) - mnLeft; 1918 if ( aImgSz.Width() > 0 ) 1919 aTextRect.Left() -= ( aImgSz.Width() + IMG_TXT_DISTANCE ); 1920 } 1921 1922 sal_uInt16 nDrawStyle = ImplGetTextStyle(); 1923 if( (pEntry->mnFlags & LISTBOX_ENTRY_FLAG_MULTILINE) ) 1924 nDrawStyle |= MULTILINE_ENTRY_DRAW_FLAGS; 1925 if( (pEntry->mnFlags & LISTBOX_ENTRY_FLAG_DRAW_DISABLED) ) 1926 nDrawStyle |= TEXT_DRAW_DISABLE; 1927 1928 DrawText( aTextRect, aStr, nDrawStyle, pVector, pDisplayText ); 1929 } 1930 } 1931 1932 if( !bLayout ) 1933 { 1934 if ( ( mnSeparatorPos != LISTBOX_ENTRY_NOTFOUND ) && 1935 ( ( nPos == mnSeparatorPos ) || ( nPos == mnSeparatorPos+1 ) ) ) 1936 { 1937 Color aOldLineColor( GetLineColor() ); 1938 SetLineColor( ( GetBackground().GetColor() != COL_LIGHTGRAY ) ? COL_LIGHTGRAY : COL_GRAY ); 1939 Point aStartPos( 0, nY ); 1940 if ( nPos == mnSeparatorPos ) 1941 aStartPos.Y() += pEntry->mnHeight-1; 1942 Point aEndPos( aStartPos ); 1943 aEndPos.X() = GetOutputSizePixel().Width(); 1944 DrawLine( aStartPos, aEndPos ); 1945 SetLineColor( aOldLineColor ); 1946 } 1947 } 1948 } 1949 1950 // ----------------------------------------------------------------------- 1951 1952 void ImplListBoxWindow::FillLayoutData() const 1953 { 1954 mpControlData->mpLayoutData = new vcl::ControlLayoutData(); 1955 const_cast<ImplListBoxWindow*>(this)-> 1956 ImplDoPaint( Rectangle( Point( 0, 0 ), GetOutputSize() ), true ); 1957 } 1958 1959 // ----------------------------------------------------------------------- 1960 1961 void ImplListBoxWindow::ImplDoPaint( const Rectangle& rRect, bool bLayout ) 1962 { 1963 sal_uInt16 nCount = mpEntryList->GetEntryCount(); 1964 1965 sal_Bool bShowFocusRect = mbHasFocusRect; 1966 if ( mbHasFocusRect && ! bLayout ) 1967 ImplHideFocusRect(); 1968 1969 long nY = 0; // + mnBorder; 1970 long nHeight = GetOutputSizePixel().Height();// - mnMaxHeight + mnBorder; 1971 1972 for( sal_uInt16 i = (sal_uInt16)mnTop; i < nCount && nY < nHeight + mnMaxHeight; i++ ) 1973 { 1974 const ImplEntryType* pEntry = mpEntryList->GetEntryPtr( i ); 1975 if( nY + pEntry->mnHeight >= rRect.Top() && 1976 nY <= rRect.Bottom() + mnMaxHeight ) 1977 { 1978 ImplPaint( i, sal_False, bLayout ); 1979 } 1980 nY += pEntry->mnHeight; 1981 } 1982 1983 long nHeightDiff = mpEntryList->GetAddedHeight( mnCurrentPos, mnTop, 0 ); 1984 maFocusRect.SetPos( Point( 0, nHeightDiff ) ); 1985 Size aSz( maFocusRect.GetWidth(), mpEntryList->GetEntryHeight( mnCurrentPos ) ); 1986 maFocusRect.SetSize( aSz ); 1987 if( HasFocus() && bShowFocusRect && !bLayout ) 1988 ImplShowFocusRect(); 1989 } 1990 1991 // ----------------------------------------------------------------------- 1992 1993 void ImplListBoxWindow::Paint( const Rectangle& rRect ) 1994 { 1995 ImplDoPaint( rRect ); 1996 } 1997 1998 // ----------------------------------------------------------------------- 1999 2000 sal_uInt16 ImplListBoxWindow::GetDisplayLineCount() const 2001 { 2002 // FIXME: LISTBOX_ENTRY_FLAG_MULTILINE 2003 2004 sal_uInt16 nCount = mpEntryList->GetEntryCount(); 2005 long nHeight = GetOutputSizePixel().Height();// - mnMaxHeight + mnBorder; 2006 sal_uInt16 nEntries = static_cast< sal_uInt16 >( ( nHeight + mnMaxHeight - 1 ) / mnMaxHeight ); 2007 if( nEntries > nCount-mnTop ) 2008 nEntries = nCount-mnTop; 2009 2010 return nEntries; 2011 } 2012 2013 // ----------------------------------------------------------------------- 2014 2015 void ImplListBoxWindow::Resize() 2016 { 2017 Control::Resize(); 2018 2019 sal_Bool bShowFocusRect = mbHasFocusRect; 2020 if ( bShowFocusRect ) 2021 ImplHideFocusRect(); 2022 2023 if( mnCurrentPos != LISTBOX_ENTRY_NOTFOUND ) 2024 { 2025 Size aSz( GetOutputSizePixel().Width(), mpEntryList->GetEntryHeight( mnCurrentPos ) ); 2026 maFocusRect.SetSize( aSz ); 2027 } 2028 2029 if ( bShowFocusRect ) 2030 ImplShowFocusRect(); 2031 2032 ImplClearLayoutData(); 2033 } 2034 2035 // ----------------------------------------------------------------------- 2036 2037 void ImplListBoxWindow::GetFocus() 2038 { 2039 sal_uInt16 nPos = mnCurrentPos; 2040 if ( nPos == LISTBOX_ENTRY_NOTFOUND ) 2041 nPos = 0; 2042 long nHeightDiff = mpEntryList->GetAddedHeight( nPos, mnTop, 0 ); 2043 maFocusRect.SetPos( Point( 0, nHeightDiff ) ); 2044 Size aSz( maFocusRect.GetWidth(), mpEntryList->GetEntryHeight( nPos ) ); 2045 maFocusRect.SetSize( aSz ); 2046 ImplShowFocusRect(); 2047 Control::GetFocus(); 2048 } 2049 2050 // ----------------------------------------------------------------------- 2051 2052 void ImplListBoxWindow::LoseFocus() 2053 { 2054 ImplHideFocusRect(); 2055 Control::LoseFocus(); 2056 } 2057 2058 // ----------------------------------------------------------------------- 2059 2060 /* 2061 void ImplListBoxWindow::RequestHelp( const HelpEvent& rHEvt ) 2062 { 2063 if ( rHEvt.GetMode() & HELPMODE_BALLOON ) 2064 Help::ShowBalloon( this, rHEvt.GetMousePosPixel(), String() ); 2065 2066 Window::RequestHelp( rHEvt ); 2067 } 2068 */ 2069 2070 // ----------------------------------------------------------------------- 2071 2072 void ImplListBoxWindow::SetTopEntry( sal_uInt16 nTop ) 2073 { 2074 if( mpEntryList->GetEntryCount() == 0 ) 2075 return; 2076 2077 long nWHeight = PixelToLogic( GetSizePixel() ).Height(); 2078 2079 sal_uInt16 nLastEntry = mpEntryList->GetEntryCount()-1; 2080 if( nTop > nLastEntry ) 2081 nTop = nLastEntry; 2082 const ImplEntryType* pLast = mpEntryList->GetEntryPtr( nLastEntry ); 2083 while( nTop > 0 && mpEntryList->GetAddedHeight( nLastEntry, nTop-1 ) + pLast->mnHeight <= nWHeight ) 2084 nTop--; 2085 2086 if ( nTop != mnTop ) 2087 { 2088 ImplClearLayoutData(); 2089 long nDiff = mpEntryList->GetAddedHeight( mnTop, nTop, 0 ); 2090 Update(); 2091 ImplHideFocusRect(); 2092 mnTop = nTop; 2093 Scroll( 0, nDiff ); 2094 Update(); 2095 if( HasFocus() ) 2096 ImplShowFocusRect(); 2097 maScrollHdl.Call( this ); 2098 } 2099 } 2100 2101 // ----------------------------------------------------------------------- 2102 2103 void ImplListBoxWindow::ShowProminentEntry( sal_uInt16 nEntryPos ) 2104 { 2105 if( meProminentType == PROMINENT_MIDDLE ) 2106 { 2107 sal_uInt16 nPos = nEntryPos; 2108 long nWHeight = PixelToLogic( GetSizePixel() ).Height(); 2109 while( nEntryPos > 0 && mpEntryList->GetAddedHeight( nPos+1, nEntryPos ) < nWHeight/2 ) 2110 nEntryPos--; 2111 } 2112 SetTopEntry( nEntryPos ); 2113 } 2114 2115 // ----------------------------------------------------------------------- 2116 2117 void ImplListBoxWindow::SetLeftIndent( long n ) 2118 { 2119 ScrollHorz( n - mnLeft ); 2120 } 2121 2122 // ----------------------------------------------------------------------- 2123 2124 void ImplListBoxWindow::ScrollHorz( long n ) 2125 { 2126 long nDiff = 0; 2127 if ( n > 0 ) 2128 { 2129 long nWidth = GetOutputSizePixel().Width(); 2130 if( ( mnMaxWidth - mnLeft + n ) > nWidth ) 2131 nDiff = n; 2132 } 2133 else if ( n < 0 ) 2134 { 2135 if( mnLeft ) 2136 { 2137 long nAbs = -n; 2138 nDiff = - ( ( mnLeft > nAbs ) ? nAbs : mnLeft ); 2139 } 2140 } 2141 2142 if ( nDiff ) 2143 { 2144 ImplClearLayoutData(); 2145 mnLeft = sal::static_int_cast<sal_uInt16>(mnLeft + nDiff); 2146 Update(); 2147 ImplHideFocusRect(); 2148 Scroll( -nDiff, 0 ); 2149 Update(); 2150 if( HasFocus() ) 2151 ImplShowFocusRect(); 2152 maScrollHdl.Call( this ); 2153 } 2154 } 2155 2156 // ----------------------------------------------------------------------- 2157 2158 Size ImplListBoxWindow::CalcSize( sal_uInt16 nMaxLines ) const 2159 { 2160 // FIXME: LISTBOX_ENTRY_FLAG_MULTILINE 2161 2162 Size aSz; 2163 // sal_uInt16 nL = Min( nMaxLines, mpEntryList->GetEntryCount() ); 2164 aSz.Height() = nMaxLines * mnMaxHeight; 2165 aSz.Width() = mnMaxWidth + 2*mnBorder; 2166 return aSz; 2167 } 2168 2169 // ----------------------------------------------------------------------- 2170 2171 Rectangle ImplListBoxWindow::GetBoundingRectangle( sal_uInt16 nItem ) const 2172 { 2173 const ImplEntryType* pEntry = mpEntryList->GetEntryPtr( nItem ); 2174 Size aSz( GetSizePixel().Width(), pEntry ? pEntry->mnHeight : GetEntryHeight() ); 2175 //long nY = mpEntryList->GetAddedHeight( nItem, GetTopEntry() ) - mpEntryList->GetAddedHeight( GetTopEntry() ); 2176 long nY = mpEntryList->GetAddedHeight( nItem, GetTopEntry() ) + GetEntryList()->GetMRUCount()*GetEntryHeight(); 2177 Rectangle aRect( Point( 0, nY ), aSz ); 2178 return aRect; 2179 } 2180 2181 2182 // ----------------------------------------------------------------------- 2183 2184 void ImplListBoxWindow::StateChanged( StateChangedType nType ) 2185 { 2186 Control::StateChanged( nType ); 2187 2188 if ( nType == STATE_CHANGE_ZOOM ) 2189 { 2190 ImplInitSettings( sal_True, sal_False, sal_False ); 2191 ImplCalcMetrics(); 2192 Invalidate(); 2193 } 2194 else if ( nType == STATE_CHANGE_UPDATEMODE ) 2195 { 2196 if ( IsUpdateMode() && IsReallyVisible() ) 2197 Invalidate(); 2198 } 2199 else if ( nType == STATE_CHANGE_CONTROLFONT ) 2200 { 2201 ImplInitSettings( sal_True, sal_False, sal_False ); 2202 ImplCalcMetrics(); 2203 Invalidate(); 2204 } 2205 else if ( nType == STATE_CHANGE_CONTROLFOREGROUND ) 2206 { 2207 ImplInitSettings( sal_False, sal_True, sal_False ); 2208 Invalidate(); 2209 } 2210 else if ( nType == STATE_CHANGE_CONTROLBACKGROUND ) 2211 { 2212 ImplInitSettings( sal_False, sal_False, sal_True ); 2213 Invalidate(); 2214 } 2215 ImplClearLayoutData(); 2216 } 2217 2218 // ----------------------------------------------------------------------- 2219 2220 void ImplListBoxWindow::DataChanged( const DataChangedEvent& rDCEvt ) 2221 { 2222 Control::DataChanged( rDCEvt ); 2223 2224 if ( (rDCEvt.GetType() == DATACHANGED_FONTS) || 2225 (rDCEvt.GetType() == DATACHANGED_FONTSUBSTITUTION) || 2226 ((rDCEvt.GetType() == DATACHANGED_SETTINGS) && 2227 (rDCEvt.GetFlags() & SETTINGS_STYLE)) ) 2228 { 2229 ImplClearLayoutData(); 2230 ImplInitSettings( sal_True, sal_True, sal_True ); 2231 ImplCalcMetrics(); 2232 Invalidate(); 2233 } 2234 } 2235 2236 // ----------------------------------------------------------------------- 2237 2238 sal_uInt16 ImplListBoxWindow::ImplGetTextStyle() const 2239 { 2240 sal_uInt16 nTextStyle = TEXT_DRAW_VCENTER; 2241 2242 if ( mpEntryList->HasImages() ) 2243 nTextStyle |= TEXT_DRAW_LEFT; 2244 else if ( mbCenter ) 2245 nTextStyle |= TEXT_DRAW_CENTER; 2246 else if ( mbRight ) 2247 nTextStyle |= TEXT_DRAW_RIGHT; 2248 else 2249 nTextStyle |= TEXT_DRAW_LEFT; 2250 2251 return nTextStyle; 2252 } 2253 2254 // ======================================================================= 2255 2256 ImplListBox::ImplListBox( Window* pParent, WinBits nWinStyle ) : 2257 Control( pParent, nWinStyle ), 2258 maLBWindow( this, nWinStyle&(~WB_BORDER) ) 2259 { 2260 // for native widget rendering we must be able to detect this window type 2261 SetType( WINDOW_LISTBOXWINDOW ); 2262 2263 mpVScrollBar = new ScrollBar( this, WB_VSCROLL | WB_DRAG ); 2264 mpHScrollBar = new ScrollBar( this, WB_HSCROLL | WB_DRAG ); 2265 mpScrollBarBox = new ScrollBarBox( this ); 2266 2267 Link aLink( LINK( this, ImplListBox, ScrollBarHdl ) ); 2268 mpVScrollBar->SetScrollHdl( aLink ); 2269 mpHScrollBar->SetScrollHdl( aLink ); 2270 2271 mbVScroll = false; 2272 mbHScroll = false; 2273 mbAutoHScroll = ( nWinStyle & WB_AUTOHSCROLL ); 2274 mbEdgeBlending = false; 2275 2276 maLBWindow.SetScrollHdl( LINK( this, ImplListBox, LBWindowScrolled ) ); 2277 maLBWindow.SetMRUChangedHdl( LINK( this, ImplListBox, MRUChanged ) ); 2278 maLBWindow.SetEdgeBlending(GetEdgeBlending()); 2279 maLBWindow.Show(); 2280 } 2281 2282 // ----------------------------------------------------------------------- 2283 2284 ImplListBox::~ImplListBox() 2285 { 2286 delete mpHScrollBar; 2287 delete mpVScrollBar; 2288 delete mpScrollBarBox; 2289 } 2290 2291 // ----------------------------------------------------------------------- 2292 2293 void ImplListBox::Clear() 2294 { 2295 maLBWindow.Clear(); 2296 if ( GetEntryList()->GetMRUCount() ) 2297 { 2298 maLBWindow.GetEntryList()->SetMRUCount( 0 ); 2299 maLBWindow.SetSeparatorPos( LISTBOX_ENTRY_NOTFOUND ); 2300 } 2301 mpVScrollBar->SetThumbPos( 0 ); 2302 mpHScrollBar->SetThumbPos( 0 ); 2303 StateChanged( STATE_CHANGE_DATA ); 2304 } 2305 2306 // ----------------------------------------------------------------------- 2307 2308 sal_uInt16 ImplListBox::InsertEntry( sal_uInt16 nPos, const XubString& rStr ) 2309 { 2310 ImplEntryType* pNewEntry = new ImplEntryType( rStr ); 2311 sal_uInt16 nNewPos = maLBWindow.InsertEntry( nPos, pNewEntry ); 2312 StateChanged( STATE_CHANGE_DATA ); 2313 return nNewPos; 2314 } 2315 2316 // ----------------------------------------------------------------------- 2317 2318 sal_uInt16 ImplListBox::InsertEntry( sal_uInt16 nPos, const Image& rImage ) 2319 { 2320 ImplEntryType* pNewEntry = new ImplEntryType( rImage ); 2321 sal_uInt16 nNewPos = maLBWindow.InsertEntry( nPos, pNewEntry ); 2322 StateChanged( STATE_CHANGE_DATA ); 2323 return nNewPos; 2324 } 2325 2326 // ----------------------------------------------------------------------- 2327 2328 sal_uInt16 ImplListBox::InsertEntry( sal_uInt16 nPos, const XubString& rStr, const Image& rImage ) 2329 { 2330 ImplEntryType* pNewEntry = new ImplEntryType( rStr, rImage ); 2331 sal_uInt16 nNewPos = maLBWindow.InsertEntry( nPos, pNewEntry ); 2332 StateChanged( STATE_CHANGE_DATA ); 2333 return nNewPos; 2334 } 2335 2336 // ----------------------------------------------------------------------- 2337 2338 void ImplListBox::RemoveEntry( sal_uInt16 nPos ) 2339 { 2340 maLBWindow.RemoveEntry( nPos ); 2341 StateChanged( STATE_CHANGE_DATA ); 2342 } 2343 2344 // ----------------------------------------------------------------------- 2345 2346 void ImplListBox::SetEntryFlags( sal_uInt16 nPos, long nFlags ) 2347 { 2348 maLBWindow.SetEntryFlags( nPos, nFlags ); 2349 } 2350 2351 // ----------------------------------------------------------------------- 2352 2353 long ImplListBox::GetEntryFlags( sal_uInt16 nPos ) const 2354 { 2355 return maLBWindow.GetEntryList()->GetEntryFlags( nPos ); 2356 } 2357 2358 // ----------------------------------------------------------------------- 2359 2360 void ImplListBox::SelectEntry( sal_uInt16 nPos, sal_Bool bSelect ) 2361 { 2362 maLBWindow.SelectEntry( nPos, bSelect ); 2363 } 2364 2365 // ----------------------------------------------------------------------- 2366 2367 void ImplListBox::SetNoSelection() 2368 { 2369 maLBWindow.DeselectAll(); 2370 } 2371 2372 // ----------------------------------------------------------------------- 2373 2374 void ImplListBox::GetFocus() 2375 { 2376 maLBWindow.GrabFocus(); 2377 } 2378 2379 // ----------------------------------------------------------------------- 2380 2381 Window* ImplListBox::GetPreferredKeyInputWindow() 2382 { 2383 return &maLBWindow; 2384 } 2385 2386 // ----------------------------------------------------------------------- 2387 2388 void ImplListBox::Resize() 2389 { 2390 Control::Resize(); 2391 ImplResizeControls(); 2392 ImplCheckScrollBars(); 2393 } 2394 2395 2396 // ----------------------------------------------------------------------- 2397 2398 IMPL_LINK( ImplListBox, MRUChanged, void*, EMPTYARG ) 2399 { 2400 StateChanged( STATE_CHANGE_DATA ); 2401 return 1; 2402 } 2403 2404 // ----------------------------------------------------------------------- 2405 2406 IMPL_LINK( ImplListBox, LBWindowScrolled, void*, EMPTYARG ) 2407 { 2408 long nSet = GetTopEntry(); 2409 if( nSet > mpVScrollBar->GetRangeMax() ) 2410 mpVScrollBar->SetRangeMax( GetEntryList()->GetEntryCount() ); 2411 mpVScrollBar->SetThumbPos( GetTopEntry() ); 2412 2413 mpHScrollBar->SetThumbPos( GetLeftIndent() ); 2414 2415 maScrollHdl.Call( this ); 2416 2417 return 1; 2418 } 2419 2420 // ----------------------------------------------------------------------- 2421 2422 IMPL_LINK( ImplListBox, ScrollBarHdl, ScrollBar*, pSB ) 2423 { 2424 sal_uInt16 nPos = (sal_uInt16) pSB->GetThumbPos(); 2425 if( pSB == mpVScrollBar ) 2426 SetTopEntry( nPos ); 2427 else if( pSB == mpHScrollBar ) 2428 SetLeftIndent( nPos ); 2429 2430 return 1; 2431 } 2432 2433 // ----------------------------------------------------------------------- 2434 2435 void ImplListBox::ImplCheckScrollBars() 2436 { 2437 sal_Bool bArrange = sal_False; 2438 2439 Size aOutSz = GetOutputSizePixel(); 2440 sal_uInt16 nEntries = GetEntryList()->GetEntryCount(); 2441 sal_uInt16 nMaxVisEntries = (sal_uInt16) (aOutSz.Height() / GetEntryHeight()); 2442 2443 // vert. ScrollBar 2444 if( nEntries > nMaxVisEntries ) 2445 { 2446 if( !mbVScroll ) 2447 bArrange = sal_True; 2448 mbVScroll = true; 2449 2450 // Ueberpruefung des rausgescrollten Bereichs 2451 if( GetEntryList()->GetSelectEntryCount() == 1 && 2452 GetEntryList()->GetSelectEntryPos( 0 ) != LISTBOX_ENTRY_NOTFOUND ) 2453 ShowProminentEntry( GetEntryList()->GetSelectEntryPos( 0 ) ); 2454 else 2455 SetTopEntry( GetTopEntry() ); // MaxTop wird geprueft... 2456 } 2457 else 2458 { 2459 if( mbVScroll ) 2460 bArrange = sal_True; 2461 mbVScroll = false; 2462 SetTopEntry( 0 ); 2463 } 2464 2465 // horz. ScrollBar 2466 if( mbAutoHScroll ) 2467 { 2468 long nWidth = (sal_uInt16) aOutSz.Width(); 2469 if ( mbVScroll ) 2470 nWidth -= mpVScrollBar->GetSizePixel().Width(); 2471 2472 long nMaxWidth = GetMaxEntryWidth(); 2473 if( nWidth < nMaxWidth ) 2474 { 2475 if( !mbHScroll ) 2476 bArrange = sal_True; 2477 mbHScroll = true; 2478 2479 if ( !mbVScroll ) // ggf. brauchen wir jetzt doch einen 2480 { 2481 nMaxVisEntries = (sal_uInt16) ( ( aOutSz.Height() - mpHScrollBar->GetSizePixel().Height() ) / GetEntryHeight() ); 2482 if( nEntries > nMaxVisEntries ) 2483 { 2484 bArrange = sal_True; 2485 mbVScroll = true; 2486 2487 // Ueberpruefung des rausgescrollten Bereichs 2488 if( GetEntryList()->GetSelectEntryCount() == 1 && 2489 GetEntryList()->GetSelectEntryPos( 0 ) != LISTBOX_ENTRY_NOTFOUND ) 2490 ShowProminentEntry( GetEntryList()->GetSelectEntryPos( 0 ) ); 2491 else 2492 SetTopEntry( GetTopEntry() ); // MaxTop wird geprueft... 2493 } 2494 } 2495 2496 // Ueberpruefung des rausgescrollten Bereichs 2497 sal_uInt16 nMaxLI = (sal_uInt16) (nMaxWidth - nWidth); 2498 if ( nMaxLI < GetLeftIndent() ) 2499 SetLeftIndent( nMaxLI ); 2500 } 2501 else 2502 { 2503 if( mbHScroll ) 2504 bArrange = sal_True; 2505 mbHScroll = false; 2506 SetLeftIndent( 0 ); 2507 } 2508 } 2509 2510 if( bArrange ) 2511 ImplResizeControls(); 2512 2513 ImplInitScrollBars(); 2514 } 2515 2516 // ----------------------------------------------------------------------- 2517 2518 void ImplListBox::ImplInitScrollBars() 2519 { 2520 Size aOutSz = maLBWindow.GetOutputSizePixel(); 2521 2522 if ( mbVScroll ) 2523 { 2524 sal_uInt16 nEntries = GetEntryList()->GetEntryCount(); 2525 sal_uInt16 nVisEntries = (sal_uInt16) (aOutSz.Height() / GetEntryHeight()); 2526 mpVScrollBar->SetRangeMax( nEntries ); 2527 mpVScrollBar->SetVisibleSize( nVisEntries ); 2528 mpVScrollBar->SetPageSize( nVisEntries - 1 ); 2529 } 2530 2531 if ( mbHScroll ) 2532 { 2533 mpHScrollBar->SetRangeMax( GetMaxEntryWidth() + HORZ_SCROLL ); 2534 mpHScrollBar->SetVisibleSize( (sal_uInt16)aOutSz.Width() ); 2535 mpHScrollBar->SetLineSize( HORZ_SCROLL ); 2536 mpHScrollBar->SetPageSize( aOutSz.Width() - HORZ_SCROLL ); 2537 } 2538 } 2539 2540 // ----------------------------------------------------------------------- 2541 2542 void ImplListBox::ImplResizeControls() 2543 { 2544 // Hier werden die Controls nur angeordnet, ob die Scrollbars 2545 // sichtbar sein sollen wird bereits in ImplCheckScrollBars ermittelt. 2546 2547 Size aOutSz = GetOutputSizePixel(); 2548 long nSBWidth = GetSettings().GetStyleSettings().GetScrollBarSize(); 2549 nSBWidth = CalcZoom( nSBWidth ); 2550 2551 Size aInnerSz( aOutSz ); 2552 if ( mbVScroll ) 2553 aInnerSz.Width() -= nSBWidth; 2554 if ( mbHScroll ) 2555 aInnerSz.Height() -= nSBWidth; 2556 2557 // pb: #106948# explicit mirroring for calc 2558 // Scrollbar on left or right side? 2559 sal_Bool bMirroring = maLBWindow.IsMirroring(); 2560 Point aWinPos( bMirroring && mbVScroll ? nSBWidth : 0, 0 ); 2561 maLBWindow.SetPosSizePixel( aWinPos, aInnerSz ); 2562 2563 // ScrollBarBox 2564 if( mbVScroll && mbHScroll ) 2565 { 2566 Point aBoxPos( bMirroring ? 0 : aInnerSz.Width(), aInnerSz.Height() ); 2567 mpScrollBarBox->SetPosSizePixel( aBoxPos, Size( nSBWidth, nSBWidth ) ); 2568 mpScrollBarBox->Show(); 2569 } 2570 else 2571 { 2572 mpScrollBarBox->Hide(); 2573 } 2574 2575 // vert. ScrollBar 2576 if( mbVScroll ) 2577 { 2578 // Scrollbar on left or right side? 2579 Point aVPos( bMirroring ? 0 : aOutSz.Width() - nSBWidth, 0 ); 2580 mpVScrollBar->SetPosSizePixel( aVPos, Size( nSBWidth, aInnerSz.Height() ) ); 2581 mpVScrollBar->Show(); 2582 } 2583 else 2584 { 2585 mpVScrollBar->Hide(); 2586 // #107254# Don't reset top entry after resize, but check for max top entry 2587 SetTopEntry( GetTopEntry() ); 2588 } 2589 2590 // horz. ScrollBar 2591 if( mbHScroll ) 2592 { 2593 Point aHPos( ( bMirroring && mbVScroll ) ? nSBWidth : 0, aOutSz.Height() - nSBWidth ); 2594 mpHScrollBar->SetPosSizePixel( aHPos, Size( aInnerSz.Width(), nSBWidth ) ); 2595 mpHScrollBar->Show(); 2596 } 2597 else 2598 { 2599 mpHScrollBar->Hide(); 2600 SetLeftIndent( 0 ); 2601 } 2602 } 2603 2604 // ----------------------------------------------------------------------- 2605 2606 void ImplListBox::StateChanged( StateChangedType nType ) 2607 { 2608 if ( nType == STATE_CHANGE_INITSHOW ) 2609 { 2610 ImplCheckScrollBars(); 2611 } 2612 else if ( ( nType == STATE_CHANGE_UPDATEMODE ) || ( nType == STATE_CHANGE_DATA ) ) 2613 { 2614 sal_Bool bUpdate = IsUpdateMode(); 2615 maLBWindow.SetUpdateMode( bUpdate ); 2616 // mpHScrollBar->SetUpdateMode( bUpdate ); 2617 // mpVScrollBar->SetUpdateMode( bUpdate ); 2618 if ( bUpdate && IsReallyVisible() ) 2619 ImplCheckScrollBars(); 2620 } 2621 else if( nType == STATE_CHANGE_ENABLE ) 2622 { 2623 mpHScrollBar->Enable( IsEnabled() ); 2624 mpVScrollBar->Enable( IsEnabled() ); 2625 mpScrollBarBox->Enable( IsEnabled() ); 2626 Invalidate(); 2627 } 2628 else if ( nType == STATE_CHANGE_ZOOM ) 2629 { 2630 maLBWindow.SetZoom( GetZoom() ); 2631 Resize(); 2632 } 2633 else if ( nType == STATE_CHANGE_CONTROLFONT ) 2634 { 2635 maLBWindow.SetControlFont( GetControlFont() ); 2636 } 2637 else if ( nType == STATE_CHANGE_CONTROLFOREGROUND ) 2638 { 2639 maLBWindow.SetControlForeground( GetControlForeground() ); 2640 } 2641 else if ( nType == STATE_CHANGE_CONTROLBACKGROUND ) 2642 { 2643 maLBWindow.SetControlBackground( GetControlBackground() ); 2644 } 2645 else if( nType == STATE_CHANGE_MIRRORING ) 2646 { 2647 maLBWindow.EnableRTL( IsRTLEnabled() ); 2648 mpHScrollBar->EnableRTL( IsRTLEnabled() ); 2649 mpVScrollBar->EnableRTL( IsRTLEnabled() ); 2650 ImplResizeControls(); 2651 } 2652 2653 Control::StateChanged( nType ); 2654 } 2655 2656 // ----------------------------------------------------------------------- 2657 2658 void ImplListBox::DataChanged( const DataChangedEvent& rDCEvt ) 2659 { 2660 // if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) && 2661 // (rDCEvt.GetFlags() & SETTINGS_STYLE) ) 2662 // { 2663 // maLBWindow.SetSettings( GetSettings() ); 2664 // Resize(); 2665 // } 2666 // else 2667 Control::DataChanged( rDCEvt ); 2668 } 2669 2670 // ----------------------------------------------------------------------- 2671 2672 long ImplListBox::Notify( NotifyEvent& rNEvt ) 2673 { 2674 long nDone = 0; 2675 if ( rNEvt.GetType() == EVENT_COMMAND ) 2676 { 2677 const CommandEvent& rCEvt = *rNEvt.GetCommandEvent(); 2678 if ( rCEvt.GetCommand() == COMMAND_WHEEL ) 2679 { 2680 const CommandWheelData* pData = rCEvt.GetWheelData(); 2681 if( !pData->GetModifier() && ( pData->GetMode() == COMMAND_WHEEL_SCROLL ) ) 2682 { 2683 nDone = HandleScrollCommand( rCEvt, mpHScrollBar, mpVScrollBar ); 2684 } 2685 } 2686 } 2687 2688 return nDone ? nDone : Window::Notify( rNEvt ); 2689 } 2690 2691 // ----------------------------------------------------------------------- 2692 2693 const Wallpaper& ImplListBox::GetDisplayBackground() const 2694 { 2695 return maLBWindow.GetDisplayBackground(); 2696 } 2697 2698 // ----------------------------------------------------------------------- 2699 2700 sal_Bool ImplListBox::HandleWheelAsCursorTravel( const CommandEvent& rCEvt ) 2701 { 2702 sal_Bool bDone = sal_False; 2703 if ( rCEvt.GetCommand() == COMMAND_WHEEL ) 2704 { 2705 const CommandWheelData* pData = rCEvt.GetWheelData(); 2706 if( !pData->GetModifier() && ( pData->GetMode() == COMMAND_WHEEL_SCROLL ) ) 2707 { 2708 sal_uInt16 nKey = ( pData->GetDelta() < 0 ) ? KEY_DOWN : KEY_UP; 2709 KeyEvent aKeyEvent( 0, KeyCode( nKey ) ); 2710 bDone = ProcessKeyInput( aKeyEvent ); 2711 } 2712 } 2713 return bDone; 2714 } 2715 2716 // ----------------------------------------------------------------------- 2717 2718 void ImplListBox::SetMRUEntries( const XubString& rEntries, xub_Unicode cSep ) 2719 { 2720 sal_Bool bChanges = GetEntryList()->GetMRUCount() ? sal_True : sal_False; 2721 2722 // Remove old MRU entries 2723 for ( sal_uInt16 n = GetEntryList()->GetMRUCount();n; ) 2724 maLBWindow.RemoveEntry( --n ); 2725 2726 sal_uInt16 nMRUCount = 0; 2727 sal_uInt16 nEntries = rEntries.GetTokenCount( cSep ); 2728 for ( sal_uInt16 nEntry = 0; nEntry < nEntries; nEntry++ ) 2729 { 2730 XubString aEntry = rEntries.GetToken( nEntry, cSep ); 2731 // Accept only existing entries 2732 if ( GetEntryList()->FindEntry( aEntry ) != LISTBOX_ENTRY_NOTFOUND ) 2733 { 2734 ImplEntryType* pNewEntry = new ImplEntryType( aEntry ); 2735 maLBWindow.GetEntryList()->InsertEntry( nMRUCount++, pNewEntry, sal_False ); 2736 bChanges = sal_True; 2737 } 2738 } 2739 2740 if ( bChanges ) 2741 { 2742 maLBWindow.GetEntryList()->SetMRUCount( nMRUCount ); 2743 SetSeparatorPos( nMRUCount ? nMRUCount-1 : 0 ); 2744 StateChanged( STATE_CHANGE_DATA ); 2745 } 2746 } 2747 2748 // ----------------------------------------------------------------------- 2749 2750 XubString ImplListBox::GetMRUEntries( xub_Unicode cSep ) const 2751 { 2752 String aEntries; 2753 for ( sal_uInt16 n = 0; n < GetEntryList()->GetMRUCount(); n++ ) 2754 { 2755 aEntries += GetEntryList()->GetEntryText( n ); 2756 if( n < ( GetEntryList()->GetMRUCount() - 1 ) ) 2757 aEntries += cSep; 2758 } 2759 return aEntries; 2760 } 2761 2762 // ----------------------------------------------------------------------- 2763 2764 void ImplListBox::SetEdgeBlending(bool bNew) 2765 { 2766 if(mbEdgeBlending != bNew) 2767 { 2768 mbEdgeBlending = bNew; 2769 maLBWindow.SetEdgeBlending(GetEdgeBlending()); 2770 } 2771 } 2772 2773 // ======================================================================= 2774 2775 ImplWin::ImplWin( Window* pParent, WinBits nWinStyle ) : 2776 Control ( pParent, nWinStyle ) 2777 { 2778 if ( IsNativeControlSupported(CTRL_LISTBOX, PART_ENTIRE_CONTROL) 2779 && ! IsNativeControlSupported(CTRL_LISTBOX, PART_BUTTON_DOWN) ) 2780 SetBackground(); 2781 else 2782 SetBackground( Wallpaper( GetSettings().GetStyleSettings().GetFieldColor() ) ); 2783 2784 mbInUserDraw = false; 2785 mbUserDrawEnabled = false; 2786 mbEdgeBlending = false; 2787 mnItemPos = LISTBOX_ENTRY_NOTFOUND; 2788 } 2789 2790 // ----------------------------------------------------------------------- 2791 2792 sal_Bool ImplWin::SetModeImage( const Image& rImage, BmpColorMode eMode ) 2793 { 2794 if( eMode == BMP_COLOR_NORMAL ) 2795 SetImage( rImage ); 2796 else if( eMode == BMP_COLOR_HIGHCONTRAST ) 2797 maImageHC = rImage; 2798 else 2799 return sal_False; 2800 return sal_True; 2801 } 2802 2803 // ----------------------------------------------------------------------- 2804 2805 const Image& ImplWin::GetModeImage( BmpColorMode eMode ) const 2806 { 2807 if( eMode == BMP_COLOR_HIGHCONTRAST ) 2808 return maImageHC; 2809 else 2810 return maImage; 2811 } 2812 2813 // ----------------------------------------------------------------------- 2814 2815 void ImplWin::MBDown() 2816 { 2817 if( IsEnabled() ) 2818 maMBDownHdl.Call( this ); 2819 } 2820 2821 // ----------------------------------------------------------------------- 2822 2823 void ImplWin::MouseButtonDown( const MouseEvent& ) 2824 { 2825 if( IsEnabled() ) 2826 { 2827 // Control::MouseButtonDown( rMEvt ); 2828 MBDown(); 2829 } 2830 } 2831 2832 // ----------------------------------------------------------------------- 2833 2834 void ImplWin::FillLayoutData() const 2835 { 2836 mpControlData->mpLayoutData = new vcl::ControlLayoutData(); 2837 const_cast<ImplWin*>(this)->ImplDraw( true ); 2838 } 2839 2840 // ----------------------------------------------------------------------- 2841 2842 long ImplWin::PreNotify( NotifyEvent& rNEvt ) 2843 { 2844 long nDone = 0; 2845 const MouseEvent* pMouseEvt = NULL; 2846 2847 if( (rNEvt.GetType() == EVENT_MOUSEMOVE) && (pMouseEvt = rNEvt.GetMouseEvent()) != NULL ) 2848 { 2849 if( pMouseEvt->IsEnterWindow() || pMouseEvt->IsLeaveWindow() ) 2850 { 2851 // trigger redraw as mouse over state has changed 2852 if ( IsNativeControlSupported(CTRL_LISTBOX, PART_ENTIRE_CONTROL) 2853 && ! IsNativeControlSupported(CTRL_LISTBOX, PART_BUTTON_DOWN) ) 2854 { 2855 GetParent()->GetWindow( WINDOW_BORDER )->Invalidate( INVALIDATE_NOERASE ); 2856 GetParent()->GetWindow( WINDOW_BORDER )->Update(); 2857 } 2858 } 2859 } 2860 2861 return nDone ? nDone : Control::PreNotify(rNEvt); 2862 } 2863 2864 // ----------------------------------------------------------------------- 2865 2866 void ImplWin::ImplDraw( bool bLayout ) 2867 { 2868 const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings(); 2869 2870 sal_Bool bNativeOK = sal_False; 2871 2872 if( ! bLayout ) 2873 { 2874 ControlState nState = CTRL_STATE_ENABLED; 2875 if ( IsNativeControlSupported(CTRL_LISTBOX, PART_ENTIRE_CONTROL) 2876 && IsNativeControlSupported(CTRL_LISTBOX, HAS_BACKGROUND_TEXTURE) ) 2877 { 2878 // Repaint the (focused) area similarly to 2879 // ImplSmallBorderWindowView::DrawWindow() in 2880 // vcl/source/window/brdwin.cxx 2881 Window *pWin = GetParent(); 2882 2883 ImplControlValue aControlValue; 2884 if ( !pWin->IsEnabled() ) 2885 nState &= ~CTRL_STATE_ENABLED; 2886 if ( pWin->HasFocus() ) 2887 nState |= CTRL_STATE_FOCUSED; 2888 2889 // The listbox is painted over the entire control including the 2890 // border, but ImplWin does not contain the border => correction 2891 // needed. 2892 sal_Int32 nLeft, nTop, nRight, nBottom; 2893 pWin->GetBorder( nLeft, nTop, nRight, nBottom ); 2894 Point aPoint( -nLeft, -nTop ); 2895 Rectangle aCtrlRegion( aPoint - GetPosPixel(), pWin->GetSizePixel() ); 2896 2897 sal_Bool bMouseOver = sal_False; 2898 if( GetParent() ) 2899 { 2900 Window *pChild = GetParent()->GetWindow( WINDOW_FIRSTCHILD ); 2901 while( pChild && (bMouseOver = pChild->IsMouseOver()) == sal_False ) 2902 pChild = pChild->GetWindow( WINDOW_NEXT ); 2903 } 2904 2905 if( bMouseOver ) 2906 nState |= CTRL_STATE_ROLLOVER; 2907 2908 // if parent has no border, then nobody has drawn the background 2909 // since no border window exists. so draw it here. 2910 WinBits nParentStyle = pWin->GetStyle(); 2911 if( ! (nParentStyle & WB_BORDER) || (nParentStyle & WB_NOBORDER) ) 2912 { 2913 Rectangle aParentRect( Point( 0, 0 ), pWin->GetSizePixel() ); 2914 pWin->DrawNativeControl( CTRL_LISTBOX, PART_ENTIRE_CONTROL, aParentRect, 2915 nState, aControlValue, rtl::OUString() ); 2916 } 2917 2918 bNativeOK = DrawNativeControl( CTRL_LISTBOX, PART_ENTIRE_CONTROL, aCtrlRegion, nState, 2919 aControlValue, rtl::OUString() ); 2920 } 2921 2922 if( IsEnabled() ) 2923 { 2924 if( HasFocus() ) 2925 { 2926 SetTextColor( rStyleSettings.GetHighlightTextColor() ); 2927 SetFillColor( rStyleSettings.GetHighlightColor() ); 2928 DrawRect( maFocusRect ); 2929 } 2930 else 2931 { 2932 Color aColor; 2933 if( bNativeOK && (nState & CTRL_STATE_ROLLOVER) ) 2934 aColor = rStyleSettings.GetFieldRolloverTextColor(); 2935 else 2936 aColor = rStyleSettings.GetFieldTextColor(); 2937 if( IsControlForeground() ) 2938 aColor = GetControlForeground(); 2939 SetTextColor( aColor ); 2940 if ( !bNativeOK ) 2941 Erase( maFocusRect ); 2942 } 2943 } 2944 else // Disabled 2945 { 2946 SetTextColor( rStyleSettings.GetDisableColor() ); 2947 if ( !bNativeOK ) 2948 Erase( maFocusRect ); 2949 } 2950 } 2951 2952 if ( IsUserDrawEnabled() ) 2953 { 2954 mbInUserDraw = true; 2955 UserDrawEvent aUDEvt( this, maFocusRect, mnItemPos, 0 ); 2956 maUserDrawHdl.Call( &aUDEvt ); 2957 mbInUserDraw = false; 2958 } 2959 else 2960 { 2961 DrawEntry( sal_True, sal_True, sal_False, bLayout ); 2962 } 2963 } 2964 2965 // ----------------------------------------------------------------------- 2966 2967 void ImplWin::Paint( const Rectangle& ) 2968 { 2969 ImplDraw(); 2970 } 2971 2972 // ----------------------------------------------------------------------- 2973 2974 void ImplWin::DrawEntry( sal_Bool bDrawImage, sal_Bool bDrawText, sal_Bool bDrawTextAtImagePos, bool bLayout ) 2975 { 2976 long nBorder = 1; 2977 Size aOutSz = GetOutputSizePixel(); 2978 2979 sal_Bool bImage = !!maImage; 2980 if( bDrawImage && bImage && !bLayout ) 2981 { 2982 sal_uInt16 nStyle = 0; 2983 Size aImgSz = maImage.GetSizePixel(); 2984 Point aPtImg( nBorder, ( ( aOutSz.Height() - aImgSz.Height() ) / 2 ) ); 2985 const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings(); 2986 2987 // check for HC mode 2988 Image *pImage = &maImage; 2989 2990 if( !!maImageHC ) 2991 { 2992 if( rStyleSettings.GetHighContrastMode() ) 2993 pImage = &maImageHC; 2994 } 2995 2996 if ( !IsZoom() ) 2997 { 2998 DrawImage( aPtImg, *pImage, nStyle ); 2999 } 3000 else 3001 { 3002 aImgSz.Width() = CalcZoom( aImgSz.Width() ); 3003 aImgSz.Height() = CalcZoom( aImgSz.Height() ); 3004 DrawImage( aPtImg, aImgSz, *pImage, nStyle ); 3005 } 3006 3007 const sal_uInt16 nEdgeBlendingPercent(GetEdgeBlending() ? rStyleSettings.GetEdgeBlending() : 0); 3008 3009 if(nEdgeBlendingPercent) 3010 { 3011 const Color& rTopLeft(rStyleSettings.GetEdgeBlendingTopLeftColor()); 3012 const Color& rBottomRight(rStyleSettings.GetEdgeBlendingBottomRightColor()); 3013 const sal_uInt8 nAlpha((nEdgeBlendingPercent * 255) / 100); 3014 const BitmapEx aBlendFrame(createBlendFrame(aImgSz, nAlpha, rTopLeft, rBottomRight)); 3015 3016 if(!aBlendFrame.IsEmpty()) 3017 { 3018 DrawBitmapEx(aPtImg, aBlendFrame); 3019 } 3020 } 3021 } 3022 3023 if( bDrawText && maString.Len() ) 3024 { 3025 sal_uInt16 nTextStyle = TEXT_DRAW_VCENTER; 3026 3027 if ( bDrawImage && bImage && !bLayout ) 3028 nTextStyle |= TEXT_DRAW_LEFT; 3029 else if ( GetStyle() & WB_CENTER ) 3030 nTextStyle |= TEXT_DRAW_CENTER; 3031 else if ( GetStyle() & WB_RIGHT ) 3032 nTextStyle |= TEXT_DRAW_RIGHT; 3033 else 3034 nTextStyle |= TEXT_DRAW_LEFT; 3035 3036 Rectangle aTextRect( Point( nBorder, 0 ), Size( aOutSz.Width()-2*nBorder, aOutSz.Height() ) ); 3037 3038 if ( !bDrawTextAtImagePos && ( bImage || IsUserDrawEnabled() ) ) 3039 { 3040 long nMaxWidth = Max( maImage.GetSizePixel().Width(), maUserItemSize.Width() ); 3041 aTextRect.Left() += nMaxWidth + IMG_TXT_DISTANCE; 3042 } 3043 3044 MetricVector* pVector = bLayout ? &mpControlData->mpLayoutData->m_aUnicodeBoundRects : NULL; 3045 String* pDisplayText = bLayout ? &mpControlData->mpLayoutData->m_aDisplayText : NULL; 3046 DrawText( aTextRect, maString, nTextStyle, pVector, pDisplayText ); 3047 } 3048 3049 if( HasFocus() && !bLayout ) 3050 ShowFocus( maFocusRect ); 3051 } 3052 3053 // ----------------------------------------------------------------------- 3054 3055 void ImplWin::Resize() 3056 { 3057 Control::Resize(); 3058 maFocusRect.SetSize( GetOutputSizePixel() ); 3059 Invalidate(); 3060 } 3061 3062 // ----------------------------------------------------------------------- 3063 3064 void ImplWin::GetFocus() 3065 { 3066 ShowFocus( maFocusRect ); 3067 if( ImplGetSVData()->maNWFData.mbNoFocusRects && 3068 IsNativeWidgetEnabled() && 3069 IsNativeControlSupported( CTRL_LISTBOX, PART_ENTIRE_CONTROL ) ) 3070 { 3071 Window* pWin = GetParent()->GetWindow( WINDOW_BORDER ); 3072 if( ! pWin ) 3073 pWin = GetParent(); 3074 pWin->Invalidate(); 3075 } 3076 else 3077 Invalidate(); 3078 Control::GetFocus(); 3079 } 3080 3081 // ----------------------------------------------------------------------- 3082 3083 void ImplWin::LoseFocus() 3084 { 3085 HideFocus(); 3086 if( ImplGetSVData()->maNWFData.mbNoFocusRects && 3087 IsNativeWidgetEnabled() && 3088 IsNativeControlSupported( CTRL_LISTBOX, PART_ENTIRE_CONTROL ) ) 3089 { 3090 Window* pWin = GetParent()->GetWindow( WINDOW_BORDER ); 3091 if( ! pWin ) 3092 pWin = GetParent(); 3093 pWin->Invalidate(); 3094 } 3095 else 3096 Invalidate(); 3097 Control::LoseFocus(); 3098 } 3099 3100 // ======================================================================= 3101 3102 ImplBtn::ImplBtn( Window* pParent, WinBits nWinStyle ) : 3103 PushButton( pParent, nWinStyle ), 3104 mbDown ( sal_False ) 3105 { 3106 } 3107 3108 // ----------------------------------------------------------------------- 3109 3110 void ImplBtn::MBDown() 3111 { 3112 if( IsEnabled() ) 3113 maMBDownHdl.Call( this ); 3114 } 3115 3116 // ----------------------------------------------------------------------- 3117 3118 void ImplBtn::MouseButtonDown( const MouseEvent& ) 3119 { 3120 //PushButton::MouseButtonDown( rMEvt ); 3121 if( IsEnabled() ) 3122 { 3123 MBDown(); 3124 mbDown = sal_True; 3125 } 3126 } 3127 3128 // ======================================================================= 3129 3130 ImplListBoxFloatingWindow::ImplListBoxFloatingWindow( Window* pParent ) : 3131 FloatingWindow( pParent, WB_BORDER | WB_SYSTEMWINDOW | WB_NOSHADOW ) // no drop shadow for list boxes 3132 { 3133 mpImplLB = NULL; 3134 mnDDLineCount = 0; 3135 mbAutoWidth = sal_False; 3136 3137 mnPopupModeStartSaveSelection = LISTBOX_ENTRY_NOTFOUND; 3138 3139 EnableSaveBackground(); 3140 3141 Window * pBorderWindow = ImplGetBorderWindow(); 3142 if( pBorderWindow ) 3143 { 3144 SetAccessibleRole(accessibility::AccessibleRole::PANEL); 3145 pBorderWindow->SetAccessibleRole(accessibility::AccessibleRole::WINDOW); 3146 } 3147 else 3148 { 3149 SetAccessibleRole(accessibility::AccessibleRole::WINDOW); 3150 } 3151 3152 } 3153 3154 // ----------------------------------------------------------------------- 3155 3156 long ImplListBoxFloatingWindow::PreNotify( NotifyEvent& rNEvt ) 3157 { 3158 if( rNEvt.GetType() == EVENT_LOSEFOCUS ) 3159 { 3160 if( !GetParent()->HasChildPathFocus( sal_True ) ) 3161 EndPopupMode(); 3162 } 3163 3164 return FloatingWindow::PreNotify( rNEvt ); 3165 } 3166 3167 // ----------------------------------------------------------------------- 3168 3169 void ImplListBoxFloatingWindow::SetPosSizePixel( long nX, long nY, long nWidth, long nHeight, sal_uInt16 nFlags ) 3170 { 3171 FloatingWindow::SetPosSizePixel( nX, nY, nWidth, nHeight, nFlags ); 3172 3173 // Fix #60890# ( MBA ): um auch im aufgeklappten Zustand der Listbox die Gr"o\se einfach zu einen 3174 // Aufruf von Resize() "andern zu k"onnen, wird die Position hier ggf. angepa\t 3175 if ( IsReallyVisible() && ( nFlags & WINDOW_POSSIZE_HEIGHT ) ) 3176 { 3177 Point aPos = GetParent()->GetPosPixel(); 3178 aPos = GetParent()->GetParent()->OutputToScreenPixel( aPos ); 3179 3180 if ( nFlags & WINDOW_POSSIZE_X ) 3181 aPos.X() = nX; 3182 3183 if ( nFlags & WINDOW_POSSIZE_Y ) 3184 aPos.Y() = nY; 3185 3186 sal_uInt16 nIndex; 3187 SetPosPixel( ImplCalcPos( this, Rectangle( aPos, GetParent()->GetSizePixel() ), FLOATWIN_POPUPMODE_DOWN, nIndex ) ); 3188 } 3189 3190 // if( !IsReallyVisible() ) 3191 { 3192 // Die ImplListBox erhaelt kein Resize, weil nicht sichtbar. 3193 // Die Fenster muessen aber ein Resize() erhalten, damit die 3194 // Anzahl der sichtbaren Eintraege fuer PgUp/PgDown stimmt. 3195 // Die Anzahl kann auch nicht von List/Combobox berechnet werden, 3196 // weil hierfuer auch die ggf. vorhandene vertikale Scrollbar 3197 // beruecksichtigt werden muss. 3198 mpImplLB->SetSizePixel( GetOutputSizePixel() ); 3199 ((Window*)mpImplLB)->Resize(); 3200 ((Window*)mpImplLB->GetMainWindow())->Resize(); 3201 } 3202 } 3203 3204 // ----------------------------------------------------------------------- 3205 3206 void ImplListBoxFloatingWindow::Resize() 3207 { 3208 mpImplLB->GetMainWindow()->ImplClearLayoutData(); 3209 FloatingWindow::Resize(); 3210 } 3211 3212 // ----------------------------------------------------------------------- 3213 3214 Size ImplListBoxFloatingWindow::CalcFloatSize() 3215 { 3216 Size aFloatSz( maPrefSz ); 3217 3218 sal_Int32 nLeft, nTop, nRight, nBottom; 3219 GetBorder( nLeft, nTop, nRight, nBottom ); 3220 3221 sal_uInt16 nLines = mpImplLB->GetEntryList()->GetEntryCount(); 3222 if ( mnDDLineCount && ( nLines > mnDDLineCount ) ) 3223 nLines = mnDDLineCount; 3224 3225 Size aSz = mpImplLB->CalcSize( nLines ); 3226 long nMaxHeight = aSz.Height() + nTop + nBottom; 3227 3228 if ( mnDDLineCount ) 3229 aFloatSz.Height() = nMaxHeight; 3230 3231 if( mbAutoWidth ) 3232 { 3233 // AutoSize erstmal nur fuer die Breite... 3234 3235 aFloatSz.Width() = aSz.Width() + nLeft + nRight; 3236 aFloatSz.Width() += nRight; // etwas mehr Platz sieht besser aus... 3237 3238 if ( ( aFloatSz.Height() < nMaxHeight ) || ( mnDDLineCount && ( mnDDLineCount < mpImplLB->GetEntryList()->GetEntryCount() ) ) ) 3239 { 3240 // dann wird noch der vertikale Scrollbar benoetigt 3241 long nSBWidth = GetSettings().GetStyleSettings().GetScrollBarSize(); 3242 aFloatSz.Width() += nSBWidth; 3243 } 3244 } 3245 3246 if ( aFloatSz.Height() > nMaxHeight ) 3247 aFloatSz.Height() = nMaxHeight; 3248 3249 // Minimale Hoehe, falls Hoehe nicht auf Float-Hoehe eingestellt wurde. 3250 // Der Parent vom FloatWin muss die DropDown-Combo/Listbox sein. 3251 Size aParentSz = GetParent()->GetSizePixel(); 3252 if( !mnDDLineCount && ( aFloatSz.Height() < aParentSz.Height() ) ) 3253 aFloatSz.Height() = aParentSz.Height(); 3254 3255 // Nicht schmaler als der Parent werden... 3256 if( aFloatSz.Width() < aParentSz.Width() ) 3257 aFloatSz.Width() = aParentSz.Width(); 3258 3259 // Hoehe auf Entries alignen... 3260 long nInnerHeight = aFloatSz.Height() - nTop - nBottom; 3261 long nEntryHeight = mpImplLB->GetEntryHeight(); 3262 if ( nInnerHeight % nEntryHeight ) 3263 { 3264 nInnerHeight /= nEntryHeight; 3265 nInnerHeight++; 3266 nInnerHeight *= nEntryHeight; 3267 aFloatSz.Height() = nInnerHeight + nTop + nBottom; 3268 } 3269 3270 return aFloatSz; 3271 } 3272 3273 // ----------------------------------------------------------------------- 3274 3275 void ImplListBoxFloatingWindow::StartFloat( sal_Bool bStartTracking ) 3276 { 3277 if( !IsInPopupMode() ) 3278 { 3279 Size aFloatSz = CalcFloatSize(); 3280 3281 SetSizePixel( aFloatSz ); 3282 mpImplLB->SetSizePixel( GetOutputSizePixel() ); 3283 3284 sal_uInt16 nPos = mpImplLB->GetEntryList()->GetSelectEntryPos( 0 ); 3285 mnPopupModeStartSaveSelection = nPos; 3286 3287 Size aSz = GetParent()->GetSizePixel(); 3288 Point aPos = GetParent()->GetPosPixel(); 3289 aPos = GetParent()->GetParent()->OutputToScreenPixel( aPos ); 3290 // FIXME: this ugly hack is for Mac/Aqua 3291 // should be replaced by a real mechanism to place the float rectangle 3292 if( ImplGetSVData()->maNWFData.mbNoFocusRects && 3293 GetParent()->IsNativeWidgetEnabled() ) 3294 { 3295 sal_Int32 nLeft = 4, nTop = 4, nRight = 4, nBottom = 4; 3296 aPos.X() += nLeft; 3297 aPos.Y() += nTop; 3298 aSz.Width() -= nLeft + nRight; 3299 aSz.Height() -= nTop + nBottom; 3300 } 3301 Rectangle aRect( aPos, aSz ); 3302 3303 // check if the control's parent is un-mirrored which is the case for form controls in a mirrored UI 3304 // where the document is unmirrored 3305 // because StartPopupMode() expects a rectangle in mirrored coordinates we have to re-mirror 3306 if( GetParent()->GetParent()->ImplIsAntiparallel() ) 3307 GetParent()->GetParent()->ImplReMirror( aRect ); 3308 3309 StartPopupMode( aRect, FLOATWIN_POPUPMODE_DOWN ); 3310 3311 if( nPos != LISTBOX_ENTRY_NOTFOUND ) 3312 mpImplLB->ShowProminentEntry( nPos ); 3313 3314 if( bStartTracking ) 3315 mpImplLB->GetMainWindow()->EnableMouseMoveSelect( sal_True ); 3316 3317 if ( mpImplLB->GetMainWindow()->IsGrabFocusAllowed() ) 3318 mpImplLB->GetMainWindow()->GrabFocus(); 3319 3320 mpImplLB->GetMainWindow()->ImplClearLayoutData(); 3321 } 3322 } 3323