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