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