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/rc.h" 28 #include "tools/debug.hxx" 29 30 31 #include "vcl/decoview.hxx" 32 #include "vcl/event.hxx" 33 #include "vcl/scrbar.hxx" 34 #include "vcl/button.hxx" 35 #include "vcl/edit.hxx" 36 #include "vcl/lstbox.hxx" 37 #include "vcl/combobox.hxx" 38 39 #include "svdata.hxx" 40 #include "controldata.hxx" 41 #include "subedit.hxx" 42 #include "ilstbox.hxx" 43 #include "dndevdis.hxx" 44 45 #include <com/sun/star/datatransfer/dnd/XDropTarget.hpp> 46 47 // ======================================================================= 48 49 ListBox::ListBox( WindowType nType ) : Control( nType ) 50 { 51 ImplInitListBoxData(); 52 } 53 54 // ----------------------------------------------------------------------- 55 56 ListBox::ListBox( Window* pParent, WinBits nStyle ) : Control( WINDOW_LISTBOX ) 57 { 58 ImplInitListBoxData(); 59 ImplInit( pParent, nStyle ); 60 } 61 62 // ----------------------------------------------------------------------- 63 64 ListBox::ListBox( Window* pParent, const ResId& rResId ) : 65 Control( WINDOW_LISTBOX ) 66 { 67 ImplInitListBoxData(); 68 rResId.SetRT( RSC_LISTBOX ); 69 WinBits nStyle = ImplInitRes( rResId ); 70 ImplInit( pParent, nStyle ); 71 ImplLoadRes( rResId ); 72 73 if ( !(nStyle & WB_HIDE ) ) 74 Show(); 75 } 76 77 // ----------------------------------------------------------------------- 78 79 ListBox::~ListBox() 80 { 81 //#109201# 82 ImplCallEventListeners( VCLEVENT_OBJECT_DYING ); 83 84 delete mpImplLB; 85 86 // Beim zerstoeren des FloatWins macht TH ein GrabFocus auf den Parent, 87 // also diese ListBox => PreNotify()... 88 mpImplLB = NULL; 89 90 delete mpFloatWin; 91 delete mpImplWin; 92 delete mpBtn; 93 } 94 95 // ----------------------------------------------------------------------- 96 97 void ListBox::ImplInitListBoxData() 98 { 99 mpFloatWin = NULL; 100 mpImplWin = NULL; 101 mpBtn = NULL; 102 mnDDHeight = 0; 103 mnSaveValue = LISTBOX_ENTRY_NOTFOUND; 104 mnLineCount = 0; 105 mbDDAutoSize = true; 106 mbEdgeBlending = false; 107 } 108 109 // ----------------------------------------------------------------------- 110 111 void ListBox::ImplInit( Window* pParent, WinBits nStyle ) 112 { 113 nStyle = ImplInitStyle( nStyle ); 114 if ( !(nStyle & WB_NOBORDER) && ( nStyle & WB_DROPDOWN ) ) 115 nStyle |= WB_BORDER; 116 117 Control::ImplInit( pParent, nStyle, NULL ); 118 SetBackground(); 119 120 ::com::sun::star::uno::Reference< ::com::sun::star::datatransfer::dnd::XDropTargetListener> xDrop = new DNDEventDispatcher(this); 121 122 if( nStyle & WB_DROPDOWN ) 123 { 124 sal_Int32 nLeft, nTop, nRight, nBottom; 125 GetBorder( nLeft, nTop, nRight, nBottom ); 126 mnDDHeight = (sal_uInt16)(GetTextHeight() + nTop + nBottom + 4); 127 128 if( IsNativeWidgetEnabled() && 129 IsNativeControlSupported( CTRL_LISTBOX, PART_ENTIRE_CONTROL ) ) 130 { 131 ImplControlValue aControlValue; 132 Rectangle aCtrlRegion( Point( 0, 0 ), Size( 20, mnDDHeight ) ); 133 Rectangle aBoundingRgn( aCtrlRegion ); 134 Rectangle aContentRgn( aCtrlRegion ); 135 if( GetNativeControlRegion( CTRL_LISTBOX, PART_ENTIRE_CONTROL, aCtrlRegion, 136 CTRL_STATE_ENABLED, aControlValue, rtl::OUString(), 137 aBoundingRgn, aContentRgn ) ) 138 { 139 sal_Int32 nHeight = aBoundingRgn.GetHeight(); 140 if( nHeight > mnDDHeight ) 141 mnDDHeight = static_cast<sal_uInt16>(nHeight); 142 } 143 } 144 145 mpFloatWin = new ImplListBoxFloatingWindow( this ); 146 mpFloatWin->SetAutoWidth( sal_True ); 147 mpFloatWin->SetPopupModeEndHdl( LINK( this, ListBox, ImplPopupModeEndHdl ) ); 148 mpFloatWin->GetDropTarget()->addDropTargetListener(xDrop); 149 150 mpImplWin = new ImplWin( this, (nStyle & (WB_LEFT|WB_RIGHT|WB_CENTER))|WB_NOBORDER ); 151 mpImplWin->SetMBDownHdl( LINK( this, ListBox, ImplClickBtnHdl ) ); 152 mpImplWin->SetUserDrawHdl( LINK( this, ListBox, ImplUserDrawHdl ) ); 153 mpImplWin->Show(); 154 mpImplWin->GetDropTarget()->addDropTargetListener(xDrop); 155 mpImplWin->SetEdgeBlending(GetEdgeBlending()); 156 157 mpBtn = new ImplBtn( this, WB_NOLIGHTBORDER | WB_RECTSTYLE ); 158 ImplInitDropDownButton( mpBtn ); 159 mpBtn->SetMBDownHdl( LINK( this, ListBox, ImplClickBtnHdl ) ); 160 mpBtn->Show(); 161 mpBtn->GetDropTarget()->addDropTargetListener(xDrop); 162 } 163 164 Window* pLBParent = this; 165 if ( mpFloatWin ) 166 pLBParent = mpFloatWin; 167 mpImplLB = new ImplListBox( pLBParent, nStyle&(~WB_BORDER) ); 168 mpImplLB->SetSelectHdl( LINK( this, ListBox, ImplSelectHdl ) ); 169 mpImplLB->SetScrollHdl( LINK( this, ListBox, ImplScrollHdl ) ); 170 mpImplLB->SetCancelHdl( LINK( this, ListBox, ImplCancelHdl ) ); 171 mpImplLB->SetDoubleClickHdl( LINK( this, ListBox, ImplDoubleClickHdl ) ); 172 mpImplLB->SetUserDrawHdl( LINK( this, ListBox, ImplUserDrawHdl ) ); 173 mpImplLB->SetPosPixel( Point() ); 174 mpImplLB->SetEdgeBlending(GetEdgeBlending()); 175 mpImplLB->Show(); 176 177 mpImplLB->GetDropTarget()->addDropTargetListener(xDrop); 178 mpImplLB->SetDropTraget(xDrop); 179 180 if ( mpFloatWin ) 181 { 182 mpFloatWin->SetImplListBox( mpImplLB ); 183 mpImplLB->SetSelectionChangedHdl( LINK( this, ListBox, ImplSelectionChangedHdl ) ); 184 } 185 else 186 mpImplLB->GetMainWindow()->AllowGrabFocus( sal_True ); 187 188 SetCompoundControl( sal_True ); 189 } 190 191 // ----------------------------------------------------------------------- 192 193 WinBits ListBox::ImplInitStyle( WinBits nStyle ) 194 { 195 if ( !(nStyle & WB_NOTABSTOP) ) 196 nStyle |= WB_TABSTOP; 197 if ( !(nStyle & WB_NOGROUP) ) 198 nStyle |= WB_GROUP; 199 return nStyle; 200 } 201 202 // ----------------------------------------------------------------------- 203 204 void ListBox::ImplLoadRes( const ResId& rResId ) 205 { 206 Control::ImplLoadRes( rResId ); 207 208 sal_uInt16 nSelPos = ReadShortRes(); 209 sal_uInt16 nNumber = sal::static_int_cast<sal_uInt16>(ReadLongRes()); 210 211 for( sal_uInt16 i = 0; i < nNumber; i++ ) 212 { 213 sal_uInt16 nPos = InsertEntry( ReadStringRes(), LISTBOX_APPEND ); 214 215 long nId = ReadLongRes(); 216 if( nId ) 217 SetEntryData( nPos, (void *)nId ); // ID als UserData 218 } 219 220 if( nSelPos < nNumber ) 221 SelectEntryPos( nSelPos ); 222 } 223 224 // ----------------------------------------------------------------------- 225 226 IMPL_LINK( ListBox, ImplSelectHdl, void*, EMPTYARG ) 227 { 228 sal_Bool bPopup = IsInDropDown(); 229 if( IsDropDownBox() ) 230 { 231 if( !mpImplLB->IsTravelSelect() ) 232 { 233 mpFloatWin->EndPopupMode(); 234 mpImplWin->GrabFocus(); 235 } 236 237 mpImplWin->SetItemPos( GetSelectEntryPos() ); 238 mpImplWin->SetString( GetSelectEntry() ); 239 if( mpImplLB->GetEntryList()->HasImages() ) 240 { 241 Image aImage = mpImplLB->GetEntryList()->GetEntryImage( GetSelectEntryPos() ); 242 mpImplWin->SetImage( aImage ); 243 } 244 mpImplWin->Invalidate(); 245 } 246 247 if ( ( !IsTravelSelect() || mpImplLB->IsSelectionChanged() ) || ( bPopup && !IsMultiSelectionEnabled() ) ) 248 Select(); 249 250 return 1; 251 } 252 253 // ----------------------------------------------------------------------- 254 255 IMPL_LINK( ListBox, ImplScrollHdl, void*, EMPTYARG ) 256 { 257 ImplCallEventListeners( VCLEVENT_LISTBOX_SCROLLED ); 258 return 1; 259 } 260 261 // ----------------------------------------------------------------------- 262 263 IMPL_LINK( ListBox, ImplCancelHdl, void*, EMPTYARG ) 264 { 265 if( IsInDropDown() ) 266 mpFloatWin->EndPopupMode(); 267 268 return 1; 269 } 270 271 // ----------------------------------------------------------------------- 272 273 IMPL_LINK( ListBox, ImplSelectionChangedHdl, void*, n ) 274 { 275 if ( !mpImplLB->IsTrackingSelect() ) 276 { 277 sal_uInt16 nChanged = (sal_uInt16)(sal_uLong)n; 278 const ImplEntryList* pEntryList = mpImplLB->GetEntryList(); 279 if ( pEntryList->IsEntryPosSelected( nChanged ) ) 280 { 281 // Sollte mal ein ImplPaintEntry werden... 282 if ( nChanged < pEntryList->GetMRUCount() ) 283 nChanged = pEntryList->FindEntry( pEntryList->GetEntryText( nChanged ) ); 284 mpImplWin->SetItemPos( nChanged ); 285 mpImplWin->SetString( mpImplLB->GetEntryList()->GetEntryText( nChanged ) ); 286 if( mpImplLB->GetEntryList()->HasImages() ) 287 { 288 Image aImage = mpImplLB->GetEntryList()->GetEntryImage( nChanged ); 289 mpImplWin->SetImage( aImage ); 290 } 291 } 292 else 293 { 294 mpImplWin->SetItemPos( LISTBOX_ENTRY_NOTFOUND ); 295 mpImplWin->SetString( ImplGetSVEmptyStr() ); 296 Image aImage; 297 mpImplWin->SetImage( aImage ); 298 } 299 mpImplWin->Invalidate(); 300 } 301 return 1; 302 } 303 304 // ----------------------------------------------------------------------- 305 306 IMPL_LINK( ListBox, ImplDoubleClickHdl, void*, EMPTYARG ) 307 { 308 DoubleClick(); 309 return 1; 310 } 311 312 // ----------------------------------------------------------------------- 313 314 IMPL_LINK( ListBox, ImplClickBtnHdl, void*, EMPTYARG ) 315 { 316 if( !mpFloatWin->IsInPopupMode() ) 317 { 318 ImplCallEventListeners( VCLEVENT_DROPDOWN_PRE_OPEN ); 319 mpImplWin->GrabFocus(); 320 mpBtn->SetPressed( sal_True ); 321 mpFloatWin->StartFloat( sal_True ); 322 ImplCallEventListeners( VCLEVENT_DROPDOWN_OPEN ); 323 324 ImplClearLayoutData(); 325 if( mpImplLB ) 326 mpImplLB->GetMainWindow()->ImplClearLayoutData(); 327 if( mpImplWin ) 328 mpImplWin->ImplClearLayoutData(); 329 } 330 331 return 0; 332 } 333 334 // ----------------------------------------------------------------------- 335 336 IMPL_LINK( ListBox, ImplPopupModeEndHdl, void*, EMPTYARG ) 337 { 338 if( mpFloatWin->IsPopupModeCanceled() ) 339 { 340 if ( ( mpFloatWin->GetPopupModeStartSaveSelection() != LISTBOX_ENTRY_NOTFOUND ) 341 && !IsEntryPosSelected( mpFloatWin->GetPopupModeStartSaveSelection() ) ) 342 { 343 mpImplLB->SelectEntry( mpFloatWin->GetPopupModeStartSaveSelection(), sal_True ); 344 sal_Bool bTravelSelect = mpImplLB->IsTravelSelect(); 345 mpImplLB->SetTravelSelect( sal_True ); 346 347 ImplDelData aCheckDelete; 348 ImplAddDel( &aCheckDelete ); 349 Select(); 350 if ( aCheckDelete.IsDelete() ) 351 return 0; 352 ImplRemoveDel( &aCheckDelete ); 353 354 mpImplLB->SetTravelSelect( bTravelSelect ); 355 } 356 } 357 358 ImplClearLayoutData(); 359 if( mpImplLB ) 360 mpImplLB->GetMainWindow()->ImplClearLayoutData(); 361 if( mpImplWin ) 362 mpImplWin->ImplClearLayoutData(); 363 364 mpBtn->SetPressed( sal_False ); 365 ImplCallEventListeners( VCLEVENT_DROPDOWN_CLOSE ); 366 return 0; 367 } 368 369 // ----------------------------------------------------------------------- 370 371 void ListBox::ToggleDropDown() 372 { 373 if( IsDropDownBox() ) 374 { 375 if( mpFloatWin->IsInPopupMode() ) 376 mpFloatWin->EndPopupMode(); 377 else 378 { 379 ImplCallEventListeners( VCLEVENT_DROPDOWN_PRE_OPEN ); 380 mpImplWin->GrabFocus(); 381 mpBtn->SetPressed( sal_True ); 382 mpFloatWin->StartFloat( sal_True ); 383 ImplCallEventListeners( VCLEVENT_DROPDOWN_OPEN ); 384 } 385 } 386 } 387 388 // ----------------------------------------------------------------------- 389 390 void ListBox::Draw( OutputDevice* pDev, const Point& rPos, const Size& rSize, sal_uLong nFlags ) 391 { 392 mpImplLB->GetMainWindow()->ImplInitSettings( sal_True, sal_True, sal_True ); 393 394 Point aPos = pDev->LogicToPixel( rPos ); 395 Size aSize = pDev->LogicToPixel( rSize ); 396 Font aFont = mpImplLB->GetMainWindow()->GetDrawPixelFont( pDev ); 397 OutDevType eOutDevType = pDev->GetOutDevType(); 398 399 pDev->Push(); 400 pDev->SetMapMode(); 401 pDev->SetFont( aFont ); 402 pDev->SetTextFillColor(); 403 404 // Border/Background 405 pDev->SetLineColor(); 406 pDev->SetFillColor(); 407 sal_Bool bBorder = !(nFlags & WINDOW_DRAW_NOBORDER ) && (GetStyle() & WB_BORDER); 408 sal_Bool bBackground = !(nFlags & WINDOW_DRAW_NOBACKGROUND) && IsControlBackground(); 409 if ( bBorder || bBackground ) 410 { 411 Rectangle aRect( aPos, aSize ); 412 if ( bBorder ) 413 { 414 ImplDrawFrame( pDev, aRect ); 415 } 416 if ( bBackground ) 417 { 418 pDev->SetFillColor( GetControlBackground() ); 419 pDev->DrawRect( aRect ); 420 } 421 } 422 423 // Inhalt 424 if ( ( nFlags & WINDOW_DRAW_MONO ) || ( eOutDevType == OUTDEV_PRINTER ) ) 425 { 426 pDev->SetTextColor( Color( COL_BLACK ) ); 427 } 428 else 429 { 430 if ( !(nFlags & WINDOW_DRAW_NODISABLE ) && !IsEnabled() ) 431 { 432 const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings(); 433 pDev->SetTextColor( rStyleSettings.GetDisableColor() ); 434 } 435 else 436 { 437 pDev->SetTextColor( GetTextColor() ); 438 } 439 } 440 441 long nOnePixel = GetDrawPixel( pDev, 1 ); 442 sal_uInt16 nTextStyle = TEXT_DRAW_VCENTER; 443 Rectangle aTextRect( aPos, aSize ); 444 445 if ( GetStyle() & WB_CENTER ) 446 nTextStyle |= TEXT_DRAW_CENTER; 447 else if ( GetStyle() & WB_RIGHT ) 448 nTextStyle |= TEXT_DRAW_RIGHT; 449 else 450 nTextStyle |= TEXT_DRAW_LEFT; 451 452 aTextRect.Left() += 3*nOnePixel; 453 aTextRect.Right() -= 3*nOnePixel; 454 455 if ( IsDropDownBox() ) 456 { 457 XubString aText = GetSelectEntry(); 458 long nTextHeight = pDev->GetTextHeight(); 459 long nTextWidth = pDev->GetTextWidth( aText ); 460 long nOffX = 3*nOnePixel; 461 long nOffY = (aSize.Height()-nTextHeight) / 2; 462 463 // Clipping? 464 if ( (nOffY < 0) || 465 ((nOffY+nTextHeight) > aSize.Height()) || 466 ((nOffX+nTextWidth) > aSize.Width()) ) 467 { 468 Rectangle aClip( aPos, aSize ); 469 if ( nTextHeight > aSize.Height() ) 470 aClip.Bottom() += nTextHeight-aSize.Height()+1; // Damit HP-Drucker nicht 'weg-optimieren' 471 pDev->IntersectClipRegion( aClip ); 472 } 473 474 pDev->DrawText( aTextRect, aText, nTextStyle ); 475 } 476 else 477 { 478 long nTextHeight = pDev->GetTextHeight(); 479 sal_uInt16 nLines = (sal_uInt16)(aSize.Height() / nTextHeight); 480 Rectangle aClip( aPos, aSize ); 481 482 pDev->IntersectClipRegion( aClip ); 483 484 if ( !nLines ) 485 nLines = 1; 486 487 for ( sal_uInt16 n = 0; n < nLines; n++ ) 488 { 489 sal_uInt16 nEntry = n+mpImplLB->GetTopEntry(); 490 sal_Bool bSelected = mpImplLB->GetEntryList()->IsEntryPosSelected( nEntry ); 491 if ( bSelected ) 492 { 493 pDev->SetFillColor( COL_BLACK ); 494 pDev->DrawRect( Rectangle( Point( aPos.X(), aPos.Y() + n*nTextHeight ), 495 Point( aPos.X() + aSize.Width(), aPos.Y() + (n+1)*nTextHeight + 2*nOnePixel ) ) ); 496 pDev->SetFillColor(); 497 pDev->SetTextColor( COL_WHITE ); 498 } 499 500 aTextRect.Top() = aPos.Y() + n*nTextHeight; 501 aTextRect.Bottom() = aTextRect.Top() + nTextHeight; 502 503 pDev->DrawText( aTextRect, mpImplLB->GetEntryList()->GetEntryText( nEntry ), nTextStyle ); 504 505 if ( bSelected ) 506 pDev->SetTextColor( COL_BLACK ); 507 } 508 } 509 510 pDev->Pop(); 511 } 512 513 // ----------------------------------------------------------------------- 514 515 void ListBox::GetFocus() 516 { 517 if ( mpImplLB ) 518 { 519 if( IsDropDownBox() ) 520 mpImplWin->GrabFocus(); 521 else 522 mpImplLB->GrabFocus(); 523 } 524 525 Control::GetFocus(); 526 } 527 528 // ----------------------------------------------------------------------- 529 530 Window* ListBox::GetPreferredKeyInputWindow() 531 { 532 if ( mpImplLB ) 533 { 534 if( IsDropDownBox() ) 535 return mpImplWin->GetPreferredKeyInputWindow(); 536 else 537 return mpImplLB->GetPreferredKeyInputWindow(); 538 } 539 540 return Control::GetPreferredKeyInputWindow(); 541 } 542 543 // ----------------------------------------------------------------------- 544 545 void ListBox::LoseFocus() 546 { 547 if( IsDropDownBox() ) 548 mpImplWin->HideFocus(); 549 else 550 mpImplLB->HideFocus(); 551 552 Control::LoseFocus(); 553 } 554 555 // ----------------------------------------------------------------------- 556 557 void ListBox::DataChanged( const DataChangedEvent& rDCEvt ) 558 { 559 Control::DataChanged( rDCEvt ); 560 561 if ( (rDCEvt.GetType() == DATACHANGED_FONTS) || 562 (rDCEvt.GetType() == DATACHANGED_FONTSUBSTITUTION) || 563 ((rDCEvt.GetType() == DATACHANGED_SETTINGS) && 564 (rDCEvt.GetFlags() & SETTINGS_STYLE)) ) 565 { 566 SetBackground(); // due to a hack in Window::UpdateSettings the background must be reset 567 // otherwise it will overpaint NWF drawn listboxes 568 Resize(); 569 mpImplLB->Resize(); // Wird nicht durch ListBox::Resize() gerufen, wenn sich die ImplLB nicht aendert. 570 571 if ( mpImplWin ) 572 { 573 mpImplWin->SetSettings( GetSettings() ); // Falls noch nicht eingestellt... 574 ImplInitFieldSettings( mpImplWin, sal_True, sal_True, sal_True ); 575 576 mpBtn->SetSettings( GetSettings() ); 577 ImplInitDropDownButton( mpBtn ); 578 } 579 580 581 if ( IsDropDownBox() ) 582 Invalidate(); 583 } 584 } 585 586 // ----------------------------------------------------------------------- 587 588 void ListBox::EnableAutoSize( bool bAuto ) 589 { 590 mbDDAutoSize = bAuto; 591 if ( mpFloatWin ) 592 { 593 if ( bAuto && !mpFloatWin->GetDropDownLineCount() ) 594 { 595 // use GetListBoxMaximumLineCount here; before, was on fixed number of five 596 AdaptDropDownLineCountToMaximum(); 597 } 598 else if ( !bAuto ) 599 { 600 mpFloatWin->SetDropDownLineCount( 0 ); 601 } 602 } 603 } 604 605 // ----------------------------------------------------------------------- 606 607 void ListBox::EnableDDAutoWidth( sal_Bool b ) 608 { 609 if ( mpFloatWin ) 610 mpFloatWin->SetAutoWidth( b ); 611 } 612 613 // ----------------------------------------------------------------------- 614 615 sal_Bool ListBox::IsDDAutoWidthEnabled() const 616 { 617 return mpFloatWin ? mpFloatWin->IsAutoWidth() : sal_False; 618 } 619 620 // ----------------------------------------------------------------------- 621 622 void ListBox::SetDropDownLineCount( sal_uInt16 nLines ) 623 { 624 mnLineCount = nLines; 625 if ( mpFloatWin ) 626 mpFloatWin->SetDropDownLineCount( mnLineCount ); 627 } 628 629 // ----------------------------------------------------------------------- 630 631 void ListBox::AdaptDropDownLineCountToMaximum() 632 { 633 // adapt to maximum allowed number 634 SetDropDownLineCount(std::min(GetEntryCount(), GetSettings().GetStyleSettings().GetListBoxMaximumLineCount())); 635 } 636 637 // ----------------------------------------------------------------------- 638 639 sal_uInt16 ListBox::GetDropDownLineCount() const 640 { 641 if ( mpFloatWin ) 642 return mpFloatWin->GetDropDownLineCount(); 643 return mnLineCount; 644 } 645 646 // ----------------------------------------------------------------------- 647 648 void ListBox::SetPosSizePixel( long nX, long nY, long nWidth, long nHeight, sal_uInt16 nFlags ) 649 { 650 if( IsDropDownBox() && ( nFlags & WINDOW_POSSIZE_SIZE ) ) 651 { 652 Size aPrefSz = mpFloatWin->GetPrefSize(); 653 if ( ( nFlags & WINDOW_POSSIZE_HEIGHT ) && ( nHeight >= 2*mnDDHeight ) ) 654 aPrefSz.Height() = nHeight-mnDDHeight; 655 if ( nFlags & WINDOW_POSSIZE_WIDTH ) 656 aPrefSz.Width() = nWidth; 657 mpFloatWin->SetPrefSize( aPrefSz ); 658 659 if ( IsAutoSizeEnabled() && ! (nFlags & WINDOW_POSSIZE_DROPDOWN) ) 660 nHeight = mnDDHeight; 661 } 662 663 Control::SetPosSizePixel( nX, nY, nWidth, nHeight, nFlags ); 664 } 665 666 // ----------------------------------------------------------------------- 667 668 void ListBox::Resize() 669 { 670 Size aOutSz = GetOutputSizePixel(); 671 if( IsDropDownBox() ) 672 { 673 // initialize the dropdown button size with the standard scrollbar width 674 long nSBWidth = GetSettings().GetStyleSettings().GetScrollBarSize(); 675 long nTop = 0; 676 long nBottom = aOutSz.Height(); 677 678 // note: in case of no border, pBorder will actually be this 679 Window *pBorder = GetWindow( WINDOW_BORDER ); 680 ImplControlValue aControlValue; 681 Point aPoint; 682 Rectangle aContent, aBound; 683 684 // use the full extent of the control 685 Rectangle aArea( aPoint, pBorder->GetOutputSizePixel() ); 686 687 if ( GetNativeControlRegion( CTRL_LISTBOX, PART_BUTTON_DOWN, 688 aArea, 0, aControlValue, rtl::OUString(), aBound, aContent) ) 689 { 690 // convert back from border space to local coordinates 691 aPoint = pBorder->ScreenToOutputPixel( OutputToScreenPixel( aPoint ) ); 692 aContent.Move( -aPoint.X(), -aPoint.Y() ); 693 694 // use the themes drop down size for the button 695 aOutSz.Width() = aContent.Left(); 696 mpBtn->SetPosSizePixel( aContent.Left(), nTop, aContent.Right(), (nBottom-nTop) ); 697 698 // adjust the size of the edit field 699 if ( GetNativeControlRegion( CTRL_LISTBOX, PART_SUB_EDIT, 700 aArea, 0, aControlValue, rtl::OUString(), aBound, aContent) ) 701 { 702 // convert back from border space to local coordinates 703 aContent.Move( -aPoint.X(), -aPoint.Y() ); 704 705 // use the themes drop down size 706 if( ! (GetStyle() & WB_BORDER) && ImplGetSVData()->maNWFData.mbNoFocusRects ) 707 { 708 // no border but focus ring behavior -> we have a problem; the 709 // native rect relies on the border to draw the focus 710 // let's do the best we can and center vertically, so it doesn't look 711 // completely wrong. 712 Size aSz( GetOutputSizePixel() ); 713 long nDiff = aContent.Top() - (aSz.Height() - aContent.GetHeight())/2; 714 aContent.Top() -= nDiff; 715 aContent.Bottom() -= nDiff; 716 } 717 mpImplWin->SetPosSizePixel( aContent.TopLeft(), aContent.GetSize() ); 718 } 719 else 720 mpImplWin->SetSizePixel( aOutSz ); 721 } 722 else 723 { 724 nSBWidth = CalcZoom( nSBWidth ); 725 mpImplWin->SetPosSizePixel( 0, 0, aOutSz.Width() - nSBWidth, aOutSz.Height() ); 726 mpBtn->SetPosSizePixel( aOutSz.Width() - nSBWidth, 0, nSBWidth, aOutSz.Height() ); 727 } 728 } 729 else 730 { 731 mpImplLB->SetSizePixel( aOutSz ); 732 } 733 734 // FloatingWindow-Groesse auch im unsichtbare Zustand auf Stand halten, 735 // weil KEY_PGUP/DOWN ausgewertet wird... 736 if ( mpFloatWin ) 737 mpFloatWin->SetSizePixel( mpFloatWin->CalcFloatSize() ); 738 739 Control::Resize(); 740 } 741 742 // ----------------------------------------------------------------------- 743 744 void ListBox::FillLayoutData() const 745 { 746 mpControlData->mpLayoutData = new vcl::ControlLayoutData(); 747 const Control* pMainWin = mpImplLB->GetMainWindow(); 748 if( mpFloatWin ) 749 { 750 // dropdown mode 751 AppendLayoutData( *mpImplWin ); 752 mpImplWin->SetLayoutDataParent( this ); 753 if( mpFloatWin->IsReallyVisible() ) 754 { 755 AppendLayoutData( *pMainWin ); 756 pMainWin->SetLayoutDataParent( this ); 757 } 758 } 759 else 760 { 761 AppendLayoutData( *pMainWin ); 762 pMainWin->SetLayoutDataParent( this ); 763 } 764 } 765 766 // ----------------------------------------------------------------------- 767 768 long ListBox::GetIndexForPoint( const Point& rPoint, sal_uInt16& rPos ) const 769 { 770 if( !HasLayoutData() ) 771 FillLayoutData(); 772 773 // check whether rPoint fits at all 774 long nIndex = Control::GetIndexForPoint( rPoint ); 775 if( nIndex != -1 ) 776 { 777 // point must be either in main list window 778 // or in impl window (dropdown case) 779 ImplListBoxWindow* pMain = mpImplLB->GetMainWindow(); 780 781 // convert coordinates to ImplListBoxWindow pixel coordinate space 782 Point aConvPoint = LogicToPixel( rPoint ); 783 aConvPoint = OutputToAbsoluteScreenPixel( aConvPoint ); 784 aConvPoint = pMain->AbsoluteScreenToOutputPixel( aConvPoint ); 785 aConvPoint = pMain->PixelToLogic( aConvPoint ); 786 787 // try to find entry 788 sal_uInt16 nEntry = pMain->GetEntryPosForPoint( aConvPoint ); 789 if( nEntry == LISTBOX_ENTRY_NOTFOUND ) 790 { 791 // not found, maybe dropdown case 792 if( mpImplWin && mpImplWin->IsReallyVisible() ) 793 { 794 // convert to impl window pixel coordinates 795 aConvPoint = LogicToPixel( rPoint ); 796 aConvPoint = OutputToAbsoluteScreenPixel( aConvPoint ); 797 aConvPoint = mpImplWin->AbsoluteScreenToOutputPixel( aConvPoint ); 798 799 // check whether converted point is inside impl window 800 Size aImplWinSize = mpImplWin->GetOutputSizePixel(); 801 if( aConvPoint.X() >= 0 && aConvPoint.Y() >= 0 && aConvPoint.X() < aImplWinSize.Width() && aConvPoint.Y() < aImplWinSize.Height() ) 802 { 803 // inside the impl window, the position is the current item pos 804 rPos = mpImplWin->GetItemPos(); 805 } 806 else 807 nIndex = -1; 808 } 809 else 810 nIndex = -1; 811 } 812 else 813 rPos = nEntry; 814 815 DBG_ASSERT( nIndex != -1, "found index for point, but relative index failed" ); 816 } 817 818 // get line relative index 819 if( nIndex != -1 ) 820 nIndex = ToRelativeLineIndex( nIndex ); 821 822 return nIndex; 823 } 824 825 // ----------------------------------------------------------------------- 826 827 void ListBox::StateChanged( StateChangedType nType ) 828 { 829 if( nType == STATE_CHANGE_READONLY ) 830 { 831 if( mpImplWin ) 832 mpImplWin->Enable( !IsReadOnly() ); 833 if( mpBtn ) 834 mpBtn->Enable( !IsReadOnly() ); 835 } 836 else if( nType == STATE_CHANGE_ENABLE ) 837 { 838 mpImplLB->Enable( IsEnabled() ); 839 if( mpImplWin ) 840 { 841 mpImplWin->Enable( IsEnabled() ); 842 if ( IsNativeControlSupported(CTRL_LISTBOX, PART_ENTIRE_CONTROL) 843 && ! IsNativeControlSupported(CTRL_LISTBOX, PART_BUTTON_DOWN) ) 844 { 845 GetWindow( WINDOW_BORDER )->Invalidate( INVALIDATE_NOERASE ); 846 } 847 else 848 mpImplWin->Invalidate(); 849 } 850 if( mpBtn ) 851 mpBtn->Enable( IsEnabled() ); 852 } 853 else if( nType == STATE_CHANGE_UPDATEMODE ) 854 { 855 mpImplLB->SetUpdateMode( IsUpdateMode() ); 856 } 857 else if ( nType == STATE_CHANGE_ZOOM ) 858 { 859 mpImplLB->SetZoom( GetZoom() ); 860 if ( mpImplWin ) 861 { 862 mpImplWin->SetZoom( GetZoom() ); 863 mpImplWin->SetFont( mpImplLB->GetMainWindow()->GetFont() ); 864 mpImplWin->Invalidate(); 865 } 866 Resize(); 867 } 868 else if ( nType == STATE_CHANGE_CONTROLFONT ) 869 { 870 mpImplLB->SetControlFont( GetControlFont() ); 871 if ( mpImplWin ) 872 { 873 mpImplWin->SetControlFont( GetControlFont() ); 874 mpImplWin->SetFont( mpImplLB->GetMainWindow()->GetFont() ); 875 mpImplWin->Invalidate(); 876 } 877 Resize(); 878 } 879 else if ( nType == STATE_CHANGE_CONTROLFOREGROUND ) 880 { 881 mpImplLB->SetControlForeground( GetControlForeground() ); 882 if ( mpImplWin ) 883 { 884 mpImplWin->SetControlForeground( GetControlForeground() ); 885 mpImplWin->SetTextColor( GetControlForeground() ); 886 mpImplWin->SetFont( mpImplLB->GetMainWindow()->GetFont() ); 887 mpImplWin->Invalidate(); 888 } 889 } 890 else if ( nType == STATE_CHANGE_CONTROLBACKGROUND ) 891 { 892 mpImplLB->SetControlBackground( GetControlBackground() ); 893 if ( mpImplWin ) 894 { 895 if ( mpImplWin->IsNativeControlSupported(CTRL_LISTBOX, PART_ENTIRE_CONTROL) ) 896 { 897 // Transparent background 898 mpImplWin->SetBackground(); 899 mpImplWin->SetControlBackground(); 900 } 901 else 902 { 903 mpImplWin->SetBackground( mpImplLB->GetMainWindow()->GetControlBackground() ); 904 mpImplWin->SetControlBackground( mpImplLB->GetMainWindow()->GetControlBackground() ); 905 } 906 mpImplWin->SetFont( mpImplLB->GetMainWindow()->GetFont() ); 907 mpImplWin->Invalidate(); 908 } 909 } 910 else if ( nType == STATE_CHANGE_STYLE ) 911 { 912 SetStyle( ImplInitStyle( GetStyle() ) ); 913 mpImplLB->GetMainWindow()->EnableSort( ( GetStyle() & WB_SORT ) ? sal_True : sal_False ); 914 sal_Bool bSimpleMode = ( GetStyle() & WB_SIMPLEMODE ) ? sal_True : sal_False; 915 mpImplLB->SetMultiSelectionSimpleMode( bSimpleMode ); 916 } 917 else if( nType == STATE_CHANGE_MIRRORING ) 918 { 919 if( mpBtn ) 920 { 921 mpBtn->EnableRTL( IsRTLEnabled() ); 922 ImplInitDropDownButton( mpBtn ); 923 } 924 mpImplLB->EnableRTL( IsRTLEnabled() ); 925 if( mpImplWin ) 926 mpImplWin->EnableRTL( IsRTLEnabled() ); 927 Resize(); 928 } 929 930 Control::StateChanged( nType ); 931 } 932 933 // ----------------------------------------------------------------------- 934 935 long ListBox::PreNotify( NotifyEvent& rNEvt ) 936 { 937 long nDone = 0; 938 if ( mpImplLB ) 939 { 940 if( ( rNEvt.GetType() == EVENT_KEYINPUT ) && ( rNEvt.GetWindow() == mpImplWin ) ) 941 { 942 KeyEvent aKeyEvt = *rNEvt.GetKeyEvent(); 943 switch( aKeyEvt.GetKeyCode().GetCode() ) 944 { 945 case KEY_DOWN: 946 { 947 if( mpFloatWin && !mpFloatWin->IsInPopupMode() && 948 aKeyEvt.GetKeyCode().IsMod2() ) 949 { 950 ImplCallEventListeners( VCLEVENT_DROPDOWN_PRE_OPEN ); 951 mpBtn->SetPressed( sal_True ); 952 mpFloatWin->StartFloat( sal_False ); 953 ImplCallEventListeners( VCLEVENT_DROPDOWN_OPEN ); 954 nDone = 1; 955 } 956 else 957 { 958 nDone = mpImplLB->ProcessKeyInput( aKeyEvt ); 959 } 960 } 961 break; 962 case KEY_UP: 963 { 964 if( mpFloatWin && mpFloatWin->IsInPopupMode() && 965 aKeyEvt.GetKeyCode().IsMod2() ) 966 { 967 mpFloatWin->EndPopupMode(); 968 nDone = 1; 969 } 970 else 971 { 972 nDone = mpImplLB->ProcessKeyInput( aKeyEvt ); 973 } 974 } 975 break; 976 case KEY_RETURN: 977 { 978 if( IsInDropDown() ) 979 { 980 mpImplLB->ProcessKeyInput( aKeyEvt ); 981 nDone = 1; 982 } 983 } 984 break; 985 986 default: 987 { 988 nDone = mpImplLB->ProcessKeyInput( aKeyEvt ); 989 } 990 } 991 } 992 else if ( rNEvt.GetType() == EVENT_LOSEFOCUS ) 993 { 994 if ( IsInDropDown() && !HasChildPathFocus( sal_True ) ) 995 mpFloatWin->EndPopupMode(); 996 } 997 else if ( (rNEvt.GetType() == EVENT_COMMAND) && 998 (rNEvt.GetCommandEvent()->GetCommand() == COMMAND_WHEEL) && 999 (rNEvt.GetWindow() == mpImplWin) ) 1000 { 1001 sal_uInt16 nWheelBehavior( GetSettings().GetMouseSettings().GetWheelBehavior() ); 1002 if ( ( nWheelBehavior == MOUSE_WHEEL_ALWAYS ) 1003 || ( ( nWheelBehavior == MOUSE_WHEEL_FOCUS_ONLY ) 1004 && HasChildPathFocus() 1005 ) 1006 ) 1007 { 1008 nDone = mpImplLB->HandleWheelAsCursorTravel( *rNEvt.GetCommandEvent() ); 1009 } 1010 else 1011 { 1012 nDone = 0; // don't eat this event, let the default handling happen (i.e. scroll the context) 1013 } 1014 } 1015 } 1016 1017 return nDone ? nDone : Control::PreNotify( rNEvt ); 1018 } 1019 1020 // ----------------------------------------------------------------------- 1021 1022 void ListBox::Select() 1023 { 1024 ImplCallEventListenersAndHandler( VCLEVENT_LISTBOX_SELECT, maSelectHdl, this ); 1025 } 1026 1027 // ----------------------------------------------------------------------- 1028 1029 void ListBox::DoubleClick() 1030 { 1031 ImplCallEventListenersAndHandler( VCLEVENT_LISTBOX_DOUBLECLICK, maDoubleClickHdl, this ); 1032 } 1033 1034 // ----------------------------------------------------------------------- 1035 1036 void ListBox::Clear() 1037 { 1038 mpImplLB->Clear(); 1039 if( IsDropDownBox() ) 1040 { 1041 mpImplWin->SetItemPos( LISTBOX_ENTRY_NOTFOUND ); 1042 mpImplWin->SetString( ImplGetSVEmptyStr() ); 1043 Image aImage; 1044 mpImplWin->SetImage( aImage ); 1045 mpImplWin->Invalidate(); 1046 } 1047 CallEventListeners( VCLEVENT_LISTBOX_ITEMREMOVED, (void*) sal_IntPtr(-1) ); 1048 } 1049 1050 // ----------------------------------------------------------------------- 1051 1052 void ListBox::SetNoSelection() 1053 { 1054 mpImplLB->SetNoSelection(); 1055 if( IsDropDownBox() ) 1056 { 1057 mpImplWin->SetItemPos( LISTBOX_ENTRY_NOTFOUND ); 1058 mpImplWin->SetString( ImplGetSVEmptyStr() ); 1059 Image aImage; 1060 mpImplWin->SetImage( aImage ); 1061 mpImplWin->Invalidate(); 1062 } 1063 } 1064 1065 // ----------------------------------------------------------------------- 1066 1067 sal_uInt16 ListBox::InsertEntry( const XubString& rStr, sal_uInt16 nPos ) 1068 { 1069 sal_uInt16 nRealPos = mpImplLB->InsertEntry( nPos + mpImplLB->GetEntryList()->GetMRUCount(), rStr ); 1070 nRealPos = sal::static_int_cast<sal_uInt16>(nRealPos - mpImplLB->GetEntryList()->GetMRUCount()); 1071 CallEventListeners( VCLEVENT_LISTBOX_ITEMADDED, (void*) sal_IntPtr(nRealPos) ); 1072 return nRealPos; 1073 } 1074 1075 // ----------------------------------------------------------------------- 1076 1077 sal_uInt16 ListBox::InsertEntry( const Image& rImage, sal_uInt16 nPos ) 1078 { 1079 sal_uInt16 nRealPos = mpImplLB->InsertEntry( nPos + mpImplLB->GetEntryList()->GetMRUCount(), rImage ); 1080 nRealPos = sal::static_int_cast<sal_uInt16>(nRealPos - mpImplLB->GetEntryList()->GetMRUCount()); 1081 CallEventListeners( VCLEVENT_LISTBOX_ITEMADDED, (void*) sal_IntPtr(nRealPos) ); 1082 return nRealPos; 1083 } 1084 1085 // ----------------------------------------------------------------------- 1086 1087 sal_uInt16 ListBox::InsertEntry( const XubString& rStr, const Image& rImage, sal_uInt16 nPos ) 1088 { 1089 sal_uInt16 nRealPos = mpImplLB->InsertEntry( nPos + mpImplLB->GetEntryList()->GetMRUCount(), rStr, rImage ); 1090 nRealPos = sal::static_int_cast<sal_uInt16>(nRealPos - mpImplLB->GetEntryList()->GetMRUCount()); 1091 CallEventListeners( VCLEVENT_LISTBOX_ITEMADDED, (void*) sal_IntPtr(nRealPos) ); 1092 return nRealPos; 1093 } 1094 1095 // ----------------------------------------------------------------------- 1096 1097 void ListBox::RemoveEntry( const XubString& rStr ) 1098 { 1099 RemoveEntry( GetEntryPos( rStr ) ); 1100 } 1101 1102 // ----------------------------------------------------------------------- 1103 1104 void ListBox::RemoveEntry( sal_uInt16 nPos ) 1105 { 1106 mpImplLB->RemoveEntry( nPos + mpImplLB->GetEntryList()->GetMRUCount() ); 1107 CallEventListeners( VCLEVENT_LISTBOX_ITEMREMOVED, (void*) sal_IntPtr(nPos) ); 1108 } 1109 1110 // ----------------------------------------------------------------------- 1111 1112 Image ListBox::GetEntryImage( sal_uInt16 nPos ) const 1113 { 1114 if ( mpImplLB->GetEntryList()->HasEntryImage( nPos ) ) 1115 return mpImplLB->GetEntryList()->GetEntryImage( nPos ); 1116 return Image(); 1117 } 1118 1119 // ----------------------------------------------------------------------- 1120 1121 sal_uInt16 ListBox::GetEntryPos( const XubString& rStr ) const 1122 { 1123 sal_uInt16 nPos = mpImplLB->GetEntryList()->FindEntry( rStr ); 1124 if ( nPos != LISTBOX_ENTRY_NOTFOUND ) 1125 nPos = sal::static_int_cast<sal_uInt16>(nPos - mpImplLB->GetEntryList()->GetMRUCount()); 1126 return nPos; 1127 } 1128 1129 // ----------------------------------------------------------------------- 1130 1131 sal_uInt16 ListBox::GetEntryPos( const void* pData ) const 1132 { 1133 sal_uInt16 nPos = mpImplLB->GetEntryList()->FindEntry( pData ); 1134 if ( nPos != LISTBOX_ENTRY_NOTFOUND ) 1135 nPos = sal::static_int_cast<sal_uInt16>(nPos - mpImplLB->GetEntryList()->GetMRUCount()); 1136 return nPos; 1137 } 1138 1139 // ----------------------------------------------------------------------- 1140 1141 XubString ListBox::GetEntry( sal_uInt16 nPos ) const 1142 { 1143 return mpImplLB->GetEntryList()->GetEntryText( nPos + mpImplLB->GetEntryList()->GetMRUCount() ); 1144 } 1145 1146 // ----------------------------------------------------------------------- 1147 1148 sal_uInt16 ListBox::GetEntryCount() const 1149 { 1150 return mpImplLB->GetEntryList()->GetEntryCount() - mpImplLB->GetEntryList()->GetMRUCount(); 1151 } 1152 1153 // ----------------------------------------------------------------------- 1154 1155 XubString ListBox::GetSelectEntry( sal_uInt16 nIndex ) const 1156 { 1157 return GetEntry( GetSelectEntryPos( nIndex ) ); 1158 } 1159 1160 // ----------------------------------------------------------------------- 1161 1162 sal_uInt16 ListBox::GetSelectEntryCount() const 1163 { 1164 return mpImplLB->GetEntryList()->GetSelectEntryCount(); 1165 } 1166 1167 // ----------------------------------------------------------------------- 1168 1169 sal_uInt16 ListBox::GetSelectEntryPos( sal_uInt16 nIndex ) const 1170 { 1171 sal_uInt16 nPos = mpImplLB->GetEntryList()->GetSelectEntryPos( nIndex ); 1172 if ( nPos != LISTBOX_ENTRY_NOTFOUND ) 1173 { 1174 if ( nPos < mpImplLB->GetEntryList()->GetMRUCount() ) 1175 nPos = mpImplLB->GetEntryList()->FindEntry( mpImplLB->GetEntryList()->GetEntryText( nPos ) ); 1176 nPos = sal::static_int_cast<sal_uInt16>(nPos - mpImplLB->GetEntryList()->GetMRUCount()); 1177 } 1178 return nPos; 1179 } 1180 1181 // ----------------------------------------------------------------------- 1182 1183 sal_Bool ListBox::IsEntrySelected( const XubString& rStr ) const 1184 { 1185 return IsEntryPosSelected( GetEntryPos( rStr ) ); 1186 } 1187 1188 // ----------------------------------------------------------------------- 1189 1190 sal_Bool ListBox::IsEntryPosSelected( sal_uInt16 nPos ) const 1191 { 1192 return mpImplLB->GetEntryList()->IsEntryPosSelected( nPos + mpImplLB->GetEntryList()->GetMRUCount() ); 1193 } 1194 1195 // ----------------------------------------------------------------------- 1196 1197 void ListBox::SelectEntry( const XubString& rStr, sal_Bool bSelect ) 1198 { 1199 SelectEntryPos( GetEntryPos( rStr ), bSelect ); 1200 } 1201 1202 // ----------------------------------------------------------------------- 1203 1204 void ListBox::SelectEntryPos( sal_uInt16 nPos, sal_Bool bSelect ) 1205 { 1206 if ( nPos < mpImplLB->GetEntryList()->GetEntryCount() ) 1207 mpImplLB->SelectEntry( nPos + mpImplLB->GetEntryList()->GetMRUCount(), bSelect ); 1208 } 1209 1210 // ----------------------------------------------------------------------- 1211 1212 void ListBox::SetEntryData( sal_uInt16 nPos, void* pNewData ) 1213 { 1214 mpImplLB->SetEntryData( nPos + mpImplLB->GetEntryList()->GetMRUCount(), pNewData ); 1215 } 1216 1217 // ----------------------------------------------------------------------- 1218 1219 void* ListBox::GetEntryData( sal_uInt16 nPos ) const 1220 { 1221 return mpImplLB->GetEntryList()->GetEntryData( nPos + mpImplLB->GetEntryList()->GetMRUCount() ); 1222 } 1223 1224 // ----------------------------------------------------------------------- 1225 1226 void ListBox::SetEntryFlags( sal_uInt16 nPos, long nFlags ) 1227 { 1228 mpImplLB->SetEntryFlags( nPos + mpImplLB->GetEntryList()->GetMRUCount(), nFlags ); 1229 } 1230 1231 // ----------------------------------------------------------------------- 1232 1233 long ListBox::GetEntryFlags( sal_uInt16 nPos ) const 1234 { 1235 return mpImplLB->GetEntryList()->GetEntryFlags( nPos + mpImplLB->GetEntryList()->GetMRUCount() ); 1236 } 1237 1238 // ----------------------------------------------------------------------- 1239 1240 void ListBox::SetTopEntry( sal_uInt16 nPos ) 1241 { 1242 mpImplLB->SetTopEntry( nPos + mpImplLB->GetEntryList()->GetMRUCount() ); 1243 } 1244 1245 // ----------------------------------------------------------------------- 1246 1247 void ListBox::ShowProminentEntry( sal_uInt16 nPos ) 1248 { 1249 mpImplLB->ShowProminentEntry( nPos + mpImplLB->GetEntryList()->GetMRUCount() ); 1250 } 1251 1252 // ----------------------------------------------------------------------- 1253 1254 sal_uInt16 ListBox::GetTopEntry() const 1255 { 1256 sal_uInt16 nPos = GetEntryCount() ? mpImplLB->GetTopEntry() : LISTBOX_ENTRY_NOTFOUND; 1257 if ( nPos < mpImplLB->GetEntryList()->GetMRUCount() ) 1258 nPos = 0; 1259 return nPos; 1260 } 1261 1262 // ----------------------------------------------------------------------- 1263 1264 void ListBox::SetProminentEntryType( ProminentEntry eType ) 1265 { 1266 mpImplLB->SetProminentEntryType( eType ); 1267 } 1268 1269 // ----------------------------------------------------------------------- 1270 1271 ProminentEntry ListBox::GetProminentEntryType() const 1272 { 1273 return mpImplLB->GetProminentEntryType(); 1274 } 1275 1276 // ----------------------------------------------------------------------- 1277 1278 sal_Bool ListBox::IsTravelSelect() const 1279 { 1280 return mpImplLB->IsTravelSelect(); 1281 } 1282 1283 // ----------------------------------------------------------------------- 1284 1285 sal_Bool ListBox::IsInDropDown() const 1286 { 1287 return mpFloatWin && mpFloatWin->IsInPopupMode(); 1288 } 1289 1290 // ----------------------------------------------------------------------- 1291 1292 long ListBox::CalcWindowSizePixel( sal_uInt16 nLines ) const 1293 { 1294 return mpImplLB->GetEntryHeight() * nLines; 1295 } 1296 1297 Rectangle ListBox::GetBoundingRectangle( sal_uInt16 nItem ) const 1298 { 1299 Rectangle aRect = mpImplLB->GetMainWindow()->GetBoundingRectangle( nItem ); 1300 Rectangle aOffset = mpImplLB->GetMainWindow()->GetWindowExtentsRelative( (Window*)this ); 1301 aRect.Move( aOffset.TopLeft().X(), aOffset.TopLeft().Y() ); 1302 return aRect; 1303 } 1304 1305 // ----------------------------------------------------------------------- 1306 1307 void ListBox::EnableMultiSelection( sal_Bool bMulti ) 1308 { 1309 EnableMultiSelection( bMulti, sal_False ); 1310 } 1311 1312 void ListBox::EnableMultiSelection( sal_Bool bMulti, sal_Bool bStackSelection ) 1313 { 1314 mpImplLB->EnableMultiSelection( bMulti, bStackSelection ); 1315 1316 // WB_SIMPLEMODE: 1317 // Die MultiListBox verh�lt sich wie eine normale ListBox. 1318 // Die Mehrfachselektion kann nur �ber entsprechende Zusatztasten erfolgen. 1319 1320 sal_Bool bSimpleMode = ( GetStyle() & WB_SIMPLEMODE ) ? sal_True : sal_False; 1321 mpImplLB->SetMultiSelectionSimpleMode( bSimpleMode ); 1322 1323 // ohne Focus ist das Traveln in einer MultiSelection nicht zu sehen: 1324 if ( mpFloatWin ) 1325 mpImplLB->GetMainWindow()->AllowGrabFocus( bMulti ); 1326 } 1327 1328 // ----------------------------------------------------------------------- 1329 1330 sal_Bool ListBox::IsMultiSelectionEnabled() const 1331 { 1332 return mpImplLB->IsMultiSelectionEnabled(); 1333 } 1334 1335 // ----------------------------------------------------------------------- 1336 1337 Size ListBox::CalcMinimumSize() const 1338 { 1339 Size aSz; 1340 if ( !IsDropDownBox() ) 1341 aSz = mpImplLB->CalcSize (mnLineCount ? mnLineCount : mpImplLB->GetEntryList()->GetEntryCount()); 1342 else 1343 { 1344 aSz.Height() = mpImplLB->CalcSize( 1 ).Height(); 1345 aSz.Height() += 4; // add a space between entry and border 1346 // size to maxmimum entry width and add a little breathing space 1347 aSz.Width() = mpImplLB->GetMaxEntryWidth() + 4; 1348 // do not create ultrathin ListBoxes, it doesn't look good 1349 if( aSz.Width() < GetSettings().GetStyleSettings().GetScrollBarSize() ) 1350 aSz.Width() = GetSettings().GetStyleSettings().GetScrollBarSize(); 1351 1352 // try native borders; scrollbar size may not be a good indicator 1353 // see how large the edit area inside is to estimate what is needed for the dropdown 1354 ImplControlValue aControlValue; 1355 Point aPoint; 1356 Rectangle aContent, aBound; 1357 Size aTestSize( 100, 20 ); 1358 Rectangle aArea( aPoint, aTestSize ); 1359 if( const_cast<ListBox*>(this)->GetNativeControlRegion( 1360 CTRL_LISTBOX, PART_SUB_EDIT, aArea, 0, aControlValue, rtl::OUString(), aBound, aContent) ) 1361 { 1362 // use the themes drop down size 1363 aSz.Width() += aTestSize.Width() - aContent.GetWidth(); 1364 } 1365 else 1366 aSz.Width() += GetSettings().GetStyleSettings().GetScrollBarSize(); 1367 } 1368 1369 aSz = CalcWindowSize( aSz ); 1370 1371 if ( IsDropDownBox() ) // check minimum height of dropdown box 1372 { 1373 ImplControlValue aControlValue; 1374 Rectangle aRect( Point( 0, 0 ), aSz ); 1375 Rectangle aContent, aBound; 1376 if( const_cast<ListBox*>(this)->GetNativeControlRegion( 1377 CTRL_LISTBOX, PART_ENTIRE_CONTROL, aRect, 0, aControlValue, rtl::OUString(), aBound, aContent) ) 1378 { 1379 if( aBound.GetHeight() > aSz.Height() ) 1380 aSz.Height() = aBound.GetHeight(); 1381 } 1382 } 1383 1384 return aSz; 1385 } 1386 1387 // ----------------------------------------------------------------------- 1388 1389 Size ListBox::GetOptimalSize(WindowSizeType eType) const 1390 { 1391 switch (eType) { 1392 case WINDOWSIZE_MINIMUM: 1393 return CalcMinimumSize(); 1394 default: 1395 return Control::GetOptimalSize( eType ); 1396 } 1397 } 1398 1399 // ----------------------------------------------------------------------- 1400 1401 Size ListBox::CalcAdjustedSize( const Size& rPrefSize ) const 1402 { 1403 Size aSz = rPrefSize; 1404 sal_Int32 nLeft, nTop, nRight, nBottom; 1405 ((Window*)this)->GetBorder( nLeft, nTop, nRight, nBottom ); 1406 aSz.Height() -= nTop+nBottom; 1407 if ( !IsDropDownBox() ) 1408 { 1409 long nEntryHeight = CalcSize( 1, 1 ).Height(); 1410 long nLines = aSz.Height() / nEntryHeight; 1411 if ( nLines < 1 ) 1412 nLines = 1; 1413 aSz.Height() = nLines * nEntryHeight; 1414 } 1415 else 1416 { 1417 aSz.Height() = mnDDHeight; 1418 } 1419 aSz.Height() += nTop+nBottom; 1420 1421 aSz = CalcWindowSize( aSz ); 1422 return aSz; 1423 } 1424 1425 // ----------------------------------------------------------------------- 1426 1427 Size ListBox::CalcSize( sal_uInt16 nColumns, sal_uInt16 nLines ) const 1428 { 1429 // ggf. werden ScrollBars eingeblendet 1430 Size aMinSz = CalcMinimumSize(); 1431 // aMinSz = ImplCalcOutSz( aMinSz ); 1432 1433 Size aSz; 1434 1435 // Hoehe 1436 if ( nLines ) 1437 { 1438 if ( !IsDropDownBox() ) 1439 aSz.Height() = mpImplLB->CalcSize( nLines ).Height(); 1440 else 1441 aSz.Height() = mnDDHeight; 1442 } 1443 else 1444 aSz.Height() = aMinSz.Height(); 1445 1446 // Breite 1447 if ( nColumns ) 1448 aSz.Width() = nColumns * GetTextWidth( XubString( 'X' ) ); 1449 else 1450 aSz.Width() = aMinSz.Width(); 1451 1452 if ( IsDropDownBox() ) 1453 aSz.Width() += GetSettings().GetStyleSettings().GetScrollBarSize(); 1454 1455 if ( !IsDropDownBox() ) 1456 { 1457 if ( aSz.Width() < aMinSz.Width() ) 1458 aSz.Height() += GetSettings().GetStyleSettings().GetScrollBarSize(); 1459 if ( aSz.Height() < aMinSz.Height() ) 1460 aSz.Width() += GetSettings().GetStyleSettings().GetScrollBarSize(); 1461 } 1462 1463 aSz = CalcWindowSize( aSz ); 1464 return aSz; 1465 } 1466 1467 // ----------------------------------------------------------------------- 1468 1469 void ListBox::GetMaxVisColumnsAndLines( sal_uInt16& rnCols, sal_uInt16& rnLines ) const 1470 { 1471 long nCharWidth = GetTextWidth( UniString( 'x' ) ); 1472 if ( !IsDropDownBox() ) 1473 { 1474 Size aOutSz = mpImplLB->GetMainWindow()->GetOutputSizePixel(); 1475 rnCols = (sal_uInt16) (aOutSz.Width()/nCharWidth); 1476 rnLines = (sal_uInt16) (aOutSz.Height()/mpImplLB->GetEntryHeight()); 1477 } 1478 else 1479 { 1480 Size aOutSz = mpImplWin->GetOutputSizePixel(); 1481 rnCols = (sal_uInt16) (aOutSz.Width()/nCharWidth); 1482 rnLines = 1; 1483 } 1484 } 1485 1486 // ----------------------------------------------------------------------- 1487 1488 IMPL_LINK( ListBox, ImplUserDrawHdl, UserDrawEvent*, pEvent ) 1489 { 1490 UserDraw( *pEvent ); 1491 return 1; 1492 } 1493 1494 // ----------------------------------------------------------------------- 1495 1496 void ListBox::UserDraw( const UserDrawEvent& ) 1497 { 1498 } 1499 1500 // ----------------------------------------------------------------------- 1501 1502 void ListBox::DrawEntry( const UserDrawEvent& rEvt, sal_Bool bDrawImage, sal_Bool bDrawText, sal_Bool bDrawTextAtImagePos ) 1503 { 1504 if ( rEvt.GetDevice() == mpImplLB->GetMainWindow() ) 1505 mpImplLB->GetMainWindow()->DrawEntry( rEvt.GetItemId(), bDrawImage, bDrawText, bDrawTextAtImagePos ); 1506 else if ( rEvt.GetDevice() == mpImplWin ) 1507 mpImplWin->DrawEntry( bDrawImage, bDrawText, bDrawTextAtImagePos ); 1508 } 1509 1510 // ----------------------------------------------------------------------- 1511 1512 void ListBox::SetUserItemSize( const Size& rSz ) 1513 { 1514 mpImplLB->GetMainWindow()->SetUserItemSize( rSz ); 1515 if ( mpImplWin ) 1516 mpImplWin->SetUserItemSize( rSz ); 1517 } 1518 1519 // ----------------------------------------------------------------------- 1520 1521 const Size& ListBox::GetUserItemSize() const 1522 { 1523 return mpImplLB->GetMainWindow()->GetUserItemSize(); 1524 } 1525 1526 // ----------------------------------------------------------------------- 1527 1528 void ListBox::EnableUserDraw( sal_Bool bUserDraw ) 1529 { 1530 mpImplLB->GetMainWindow()->EnableUserDraw( bUserDraw ); 1531 if ( mpImplWin ) 1532 mpImplWin->EnableUserDraw( bUserDraw ); 1533 } 1534 1535 // ----------------------------------------------------------------------- 1536 1537 sal_Bool ListBox::IsUserDrawEnabled() const 1538 { 1539 return mpImplLB->GetMainWindow()->IsUserDrawEnabled(); 1540 } 1541 1542 // ----------------------------------------------------------------------- 1543 1544 void ListBox::SetReadOnly( sal_Bool bReadOnly ) 1545 { 1546 if ( mpImplLB->IsReadOnly() != bReadOnly ) 1547 { 1548 mpImplLB->SetReadOnly( bReadOnly ); 1549 StateChanged( STATE_CHANGE_READONLY ); 1550 } 1551 } 1552 1553 // ----------------------------------------------------------------------- 1554 1555 sal_Bool ListBox::IsReadOnly() const 1556 { 1557 return mpImplLB->IsReadOnly(); 1558 } 1559 1560 // ----------------------------------------------------------------------- 1561 1562 void ListBox::SetSeparatorPos( sal_uInt16 n ) 1563 { 1564 mpImplLB->SetSeparatorPos( n ); 1565 } 1566 1567 // ----------------------------------------------------------------------- 1568 1569 void ListBox::SetSeparatorPos() 1570 { 1571 mpImplLB->SetSeparatorPos( LISTBOX_ENTRY_NOTFOUND ); 1572 } 1573 1574 // ----------------------------------------------------------------------- 1575 1576 sal_uInt16 ListBox::GetSeparatorPos() const 1577 { 1578 return mpImplLB->GetSeparatorPos(); 1579 } 1580 1581 // ----------------------------------------------------------------------- 1582 1583 void ListBox::SetMRUEntries( const XubString& rEntries, xub_Unicode cSep ) 1584 { 1585 mpImplLB->SetMRUEntries( rEntries, cSep ); 1586 } 1587 1588 // ----------------------------------------------------------------------- 1589 1590 XubString ListBox::GetMRUEntries( xub_Unicode cSep ) const 1591 { 1592 return mpImplLB->GetMRUEntries( cSep ); 1593 } 1594 1595 // ----------------------------------------------------------------------- 1596 1597 void ListBox::SetMaxMRUCount( sal_uInt16 n ) 1598 { 1599 mpImplLB->SetMaxMRUCount( n ); 1600 } 1601 1602 // ----------------------------------------------------------------------- 1603 1604 sal_uInt16 ListBox::GetMaxMRUCount() const 1605 { 1606 return mpImplLB->GetMaxMRUCount(); 1607 } 1608 1609 // ----------------------------------------------------------------------- 1610 1611 sal_uInt16 ListBox::GetDisplayLineCount() const 1612 { 1613 return mpImplLB->GetDisplayLineCount(); 1614 } 1615 1616 // ----------------------------------------------------------------------- 1617 1618 // pb: #106948# explicit mirroring for calc 1619 1620 void ListBox::EnableMirroring() 1621 { 1622 mpImplLB->EnableMirroring(); 1623 } 1624 1625 // ----------------------------------------------------------------------- 1626 1627 Rectangle ListBox::GetDropDownPosSizePixel() const 1628 { 1629 return mpFloatWin ? mpFloatWin->GetWindowExtentsRelative( const_cast<ListBox*>(this) ) : Rectangle(); 1630 } 1631 1632 // ----------------------------------------------------------------------- 1633 1634 const Wallpaper& ListBox::GetDisplayBackground() const 1635 { 1636 // !!! recursion does not occur because the ImplListBox is default 1637 // initialized to a nontransparent color in Window::ImplInitData 1638 return mpImplLB->GetDisplayBackground(); 1639 } 1640 1641 // ----------------------------------------------------------------------- 1642 1643 void ListBox::SetEdgeBlending(bool bNew) 1644 { 1645 if(mbEdgeBlending != bNew) 1646 { 1647 mbEdgeBlending = bNew; 1648 1649 if(IsDropDownBox()) 1650 { 1651 mpImplWin->Invalidate(); 1652 } 1653 else 1654 { 1655 mpImplLB->Invalidate(); 1656 } 1657 1658 if(mpImplWin) 1659 { 1660 mpImplWin->SetEdgeBlending(GetEdgeBlending()); 1661 } 1662 1663 if(mpImplLB) 1664 { 1665 mpImplLB->SetEdgeBlending(GetEdgeBlending()); 1666 } 1667 1668 Invalidate(); 1669 } 1670 } 1671 1672 // ======================================================================= 1673 MultiListBox::MultiListBox( Window* pParent, WinBits nStyle ) : 1674 ListBox( WINDOW_MULTILISTBOX ) 1675 { 1676 ImplInit( pParent, nStyle ); 1677 EnableMultiSelection( sal_True ); 1678 } 1679 1680 // ----------------------------------------------------------------------- 1681 1682 MultiListBox::MultiListBox( Window* pParent, const ResId& rResId ) : 1683 ListBox( WINDOW_MULTILISTBOX ) 1684 { 1685 rResId.SetRT( RSC_MULTILISTBOX ); 1686 WinBits nStyle = ImplInitRes( rResId ); 1687 ImplInit( pParent, nStyle ); 1688 ImplLoadRes( rResId ); 1689 1690 if ( !(nStyle & WB_HIDE ) ) 1691 Show(); 1692 EnableMultiSelection( sal_True ); 1693 } 1694 1695