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