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