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