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