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