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