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