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_svtools.hxx" 26 27 #include <limits.h> 28 #include <tools/debug.hxx> 29 #include <vcl/wall.hxx> 30 #include <vcl/help.hxx> 31 #include <vcl/decoview.hxx> 32 #include <vcl/svapp.hxx> 33 #include <tools/poly.hxx> 34 #include <vcl/lineinfo.hxx> 35 #include <vcl/i18nhelp.hxx> 36 #include <vcl/mnemonic.hxx> 37 #include <vcl/controllayout.hxx> 38 39 #include <svtools/ivctrl.hxx> 40 #include "imivctl.hxx" 41 #include <svtools/svmedit.hxx> 42 43 #include <algorithm> 44 #include <memory> 45 46 #define DD_SCROLL_PIXEL 24 47 #define IMPICNVIEW_ACC_RETURN 1 48 #define IMPICNVIEW_ACC_ESCAPE 2 49 50 #define DRAWTEXT_FLAGS_ICON \ 51 ( TEXT_DRAW_CENTER | TEXT_DRAW_TOP | TEXT_DRAW_ENDELLIPSIS | \ 52 TEXT_DRAW_CLIP | TEXT_DRAW_MULTILINE | TEXT_DRAW_WORDBREAK | TEXT_DRAW_MNEMONIC ) 53 54 #define DRAWTEXT_FLAGS_SMALLICON (TEXT_DRAW_LEFT|TEXT_DRAW_ENDELLIPSIS|TEXT_DRAW_CLIP) 55 56 #define EVENTID_SHOW_CURSOR ((void*)1) 57 #define EVENTID_ADJUST_SCROLLBARS ((void*)2) 58 59 struct SvxIconChoiceCtrlEntry_Impl 60 { 61 SvxIconChoiceCtrlEntry* _pEntry; 62 Point _aPos; 63 SvxIconChoiceCtrlEntry_Impl( SvxIconChoiceCtrlEntry* pEntry, const Rectangle& rBoundRect ) 64 : _pEntry( pEntry), _aPos( rBoundRect.TopLeft()) {} 65 }; 66 67 static sal_Bool bEndScrollInvalidate = sal_True; 68 69 // ---------------------------------------------------------------------------------------------- 70 71 class IcnViewEdit_Impl : public MultiLineEdit 72 { 73 Link aCallBackHdl; 74 Accelerator aAccReturn; 75 Accelerator aAccEscape; 76 Timer aTimer; 77 sal_Bool bCanceled; 78 sal_Bool bAlreadyInCallback; 79 sal_Bool bGrabFocus; 80 81 void CallCallBackHdl_Impl(); 82 DECL_LINK( Timeout_Impl, Timer * ); 83 DECL_LINK( ReturnHdl_Impl, Accelerator * ); 84 DECL_LINK( EscapeHdl_Impl, Accelerator * ); 85 86 public: 87 88 IcnViewEdit_Impl( 89 SvtIconChoiceCtrl* pParent, 90 const Point& rPos, 91 const Size& rSize, 92 const XubString& rData, 93 const Link& rNotifyEditEnd ); 94 95 ~IcnViewEdit_Impl(); 96 virtual void KeyInput( const KeyEvent& rKEvt ); 97 virtual long PreNotify( NotifyEvent& rNEvt ); 98 sal_Bool EditingCanceled() const { return bCanceled; } 99 void StopEditing( sal_Bool bCancel = sal_False ); 100 sal_Bool IsGrabFocus() const { return bGrabFocus; } 101 }; 102 103 // ---------------------------------------------------------------------------------------------- 104 105 // ---------------------------------------------------------------------------------------------- 106 107 SvxIconChoiceCtrl_Impl::SvxIconChoiceCtrl_Impl( SvtIconChoiceCtrl* pCurView, 108 WinBits nWinStyle ) : 109 aEntries( this ), 110 aVerSBar( pCurView, WB_DRAG | WB_VSCROLL ), 111 aHorSBar( pCurView, WB_DRAG | WB_HSCROLL ), 112 aScrBarBox( pCurView ), 113 aImageSize( 32, 32 ), 114 pColumns( 0 ) 115 { 116 bChooseWithCursor=sal_False; 117 pEntryPaintDev = 0; 118 pCurEditedEntry = 0; 119 pCurHighlightFrame = 0; 120 pEdit = 0; 121 pAnchor = 0; 122 pDraggedSelection = 0; 123 pPrevDropTarget = 0; 124 pHdlEntry = 0; 125 pHead = NULL; 126 pCursor = NULL; 127 bUpdateMode = sal_True; 128 bEntryEditingEnabled = sal_False; 129 bInDragDrop = sal_False; 130 bHighlightFramePressed = sal_False; 131 eSelectionMode = MULTIPLE_SELECTION; 132 pView = pCurView; 133 pZOrderList = new List; //SvPtrarr; 134 ePositionMode = IcnViewPositionModeFree; 135 SetStyle( nWinStyle ); 136 nFlags = 0; 137 nUserEventAdjustScrBars = 0; 138 nUserEventShowCursor = 0; 139 nMaxVirtWidth = DEFAULT_MAX_VIRT_WIDTH; 140 nMaxVirtHeight = DEFAULT_MAX_VIRT_HEIGHT; 141 pDDRefEntry = 0; 142 pDDDev = 0; 143 pDDBufDev = 0; 144 pDDTempDev = 0; 145 eTextMode = IcnShowTextShort; 146 pImpCursor = new IcnCursor_Impl( this ); 147 pGridMap = new IcnGridMap_Impl( this ); 148 149 aVerSBar.SetScrollHdl( LINK( this, SvxIconChoiceCtrl_Impl, ScrollUpDownHdl ) ); 150 aHorSBar.SetScrollHdl( LINK( this, SvxIconChoiceCtrl_Impl, ScrollLeftRightHdl ) ); 151 Link aEndScrollHdl( LINK( this, SvxIconChoiceCtrl_Impl, EndScrollHdl ) ); 152 aVerSBar.SetEndScrollHdl( aEndScrollHdl ); 153 aHorSBar.SetEndScrollHdl( aEndScrollHdl ); 154 155 nHorSBarHeight = aHorSBar.GetSizePixel().Height(); 156 nVerSBarWidth = aVerSBar.GetSizePixel().Width(); 157 158 aEditTimer.SetTimeout( 800 ); 159 aEditTimer.SetTimeoutHdl(LINK(this,SvxIconChoiceCtrl_Impl,EditTimeoutHdl)); 160 aAutoArrangeTimer.SetTimeout( 100 ); 161 aAutoArrangeTimer.SetTimeoutHdl(LINK(this,SvxIconChoiceCtrl_Impl,AutoArrangeHdl)); 162 aCallSelectHdlTimer.SetTimeout( 500 ); 163 aCallSelectHdlTimer.SetTimeoutHdl( LINK(this,SvxIconChoiceCtrl_Impl,CallSelectHdlHdl)); 164 165 aDocRectChangedTimer.SetTimeout( 50 ); 166 aDocRectChangedTimer.SetTimeoutHdl(LINK(this,SvxIconChoiceCtrl_Impl,DocRectChangedHdl)); 167 aVisRectChangedTimer.SetTimeout( 50 ); 168 aVisRectChangedTimer.SetTimeoutHdl(LINK(this,SvxIconChoiceCtrl_Impl,VisRectChangedHdl)); 169 170 Clear( sal_True ); 171 172 SetGrid( Size(100, 70) ); 173 } 174 175 SvxIconChoiceCtrl_Impl::~SvxIconChoiceCtrl_Impl() 176 { 177 pCurEditedEntry = 0; 178 DELETEZ(pEdit); 179 Clear(); 180 StopEditTimer(); 181 CancelUserEvents(); 182 delete pZOrderList; 183 delete pImpCursor; 184 delete pGridMap; 185 delete pDDDev; 186 delete pDDBufDev; 187 delete pDDTempDev; 188 delete pDraggedSelection; 189 delete pEntryPaintDev; 190 ClearSelectedRectList(); 191 ClearColumnList(); 192 } 193 194 void SvxIconChoiceCtrl_Impl::Clear( sal_Bool bInCtor ) 195 { 196 StopEntryEditing( sal_True ); 197 nSelectionCount = 0; 198 DELETEZ(pDraggedSelection); 199 bInDragDrop = sal_False; 200 pCurHighlightFrame = 0; 201 StopEditTimer(); 202 CancelUserEvents(); 203 ShowCursor( sal_False ); 204 bBoundRectsDirty = sal_False; 205 nMaxBoundHeight = 0; 206 207 nFlags &= ~(F_PAINTED | F_MOVED_ENTRIES); 208 pCursor = 0; 209 if( !bInCtor ) 210 { 211 pImpCursor->Clear(); 212 pGridMap->Clear(); 213 aVirtOutputSize.Width() = 0; 214 aVirtOutputSize.Height() = 0; 215 Size aSize( pView->GetOutputSizePixel() ); 216 nMaxVirtWidth = aSize.Width() - nVerSBarWidth; 217 if( nMaxVirtWidth <= 0 ) 218 nMaxVirtWidth = DEFAULT_MAX_VIRT_WIDTH; 219 nMaxVirtHeight = aSize.Height() - nHorSBarHeight; 220 if( nMaxVirtHeight <= 0 ) 221 nMaxVirtHeight = DEFAULT_MAX_VIRT_HEIGHT; 222 pZOrderList->Clear(); //Remove(0,pZOrderList->Count()); 223 SetOrigin( Point() ); 224 if( bUpdateMode ) 225 pView->Invalidate(INVALIDATE_NOCHILDREN); 226 } 227 AdjustScrollBars(); 228 sal_uLong nCount = aEntries.Count(); 229 for( sal_uLong nCur = 0; nCur < nCount; nCur++ ) 230 { 231 SvxIconChoiceCtrlEntry* pCur = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( nCur ); 232 delete pCur; 233 } 234 aEntries.Clear(); 235 DocRectChanged(); 236 VisRectChanged(); 237 } 238 239 void SvxIconChoiceCtrl_Impl::SetStyle( WinBits nWinStyle ) 240 { 241 nWinBits = nWinStyle; 242 nCurTextDrawFlags = DRAWTEXT_FLAGS_ICON; 243 if( nWinBits & (WB_SMALLICON | WB_DETAILS) ) 244 nCurTextDrawFlags = DRAWTEXT_FLAGS_SMALLICON; 245 if( nWinBits & WB_NOSELECTION ) 246 eSelectionMode = NO_SELECTION; 247 if( !(nWinStyle & (WB_ALIGN_TOP | WB_ALIGN_LEFT))) 248 nWinBits |= WB_ALIGN_LEFT; 249 if( (nWinStyle & WB_DETAILS)) 250 { 251 if( !pColumns ) 252 SetColumn( 0, SvxIconChoiceCtrlColumnInfo( 0, 100, IcnViewAlignLeft )); 253 } 254 } 255 256 IMPL_LINK( SvxIconChoiceCtrl_Impl, ScrollUpDownHdl, ScrollBar*, pScrollBar ) 257 { 258 StopEntryEditing( sal_True ); 259 // Pfeil hoch: delta=-1; Pfeil runter: delta=+1 260 Scroll( 0, pScrollBar->GetDelta(), sal_True ); 261 bEndScrollInvalidate = sal_True; 262 return 0; 263 } 264 265 IMPL_LINK( SvxIconChoiceCtrl_Impl, ScrollLeftRightHdl, ScrollBar*, pScrollBar ) 266 { 267 StopEntryEditing( sal_True ); 268 // Pfeil links: delta=-1; Pfeil rechts: delta=+1 269 Scroll( pScrollBar->GetDelta(), 0, sal_True ); 270 bEndScrollInvalidate = sal_True; 271 return 0; 272 } 273 274 IMPL_LINK( SvxIconChoiceCtrl_Impl, EndScrollHdl, void*, EMPTYARG ) 275 { 276 if( pView->HasBackground() && !pView->GetBackground().IsScrollable() && 277 bEndScrollInvalidate ) 278 { 279 pView->Invalidate(INVALIDATE_NOCHILDREN); 280 } 281 return 0; 282 } 283 284 void SvxIconChoiceCtrl_Impl::FontModified() 285 { 286 StopEditTimer(); 287 DELETEZ(pDDDev); 288 DELETEZ(pDDBufDev); 289 DELETEZ(pDDTempDev); 290 DELETEZ(pEntryPaintDev); 291 SetDefaultTextSize(); 292 ShowCursor( sal_False ); 293 ShowCursor( sal_True ); 294 } 295 296 void SvxIconChoiceCtrl_Impl::InsertEntry( SvxIconChoiceCtrlEntry* pEntry, sal_uLong nPos, 297 const Point* pPos ) 298 { 299 StopEditTimer(); 300 aEntries.Insert( pEntry, nPos ); 301 if( (nFlags & F_ENTRYLISTPOS_VALID) && nPos >= aEntries.Count() - 1 ) 302 pEntry->nPos = aEntries.Count() - 1; 303 else 304 nFlags &= ~F_ENTRYLISTPOS_VALID; 305 306 pZOrderList->Insert( (void*)pEntry, LIST_APPEND ); //pZOrderList->Count() ); 307 pImpCursor->Clear(); 308 // pGridMap->Clear(); 309 if( pPos ) 310 { 311 Size aSize( CalcBoundingSize( pEntry ) ); 312 SetBoundingRect_Impl( pEntry, *pPos, aSize ); 313 SetEntryPos( pEntry, *pPos, sal_False, sal_True, sal_True /*keep grid map*/ ); 314 pEntry->nFlags |= ICNVIEW_FLAG_POS_MOVED; 315 SetEntriesMoved( sal_True ); 316 } 317 else 318 { 319 // wenn der UpdateMode sal_True ist, wollen wir nicht pauschal alle 320 // BoundRects auf 'zu ueberpruefen' setzen, sondern nur das des 321 // neuen Eintrags. Deshalb kein InvalidateBoundingRect aufrufen! 322 pEntry->aRect.Right() = LONG_MAX; 323 if( bUpdateMode ) 324 { 325 FindBoundingRect( pEntry ); 326 Rectangle aOutputArea( GetOutputRect() ); 327 pGridMap->OccupyGrids( pEntry ); 328 if( !aOutputArea.IsOver( pEntry->aRect ) ) 329 return; // ist nicht sichtbar 330 pView->Invalidate( pEntry->aRect ); 331 } 332 else 333 InvalidateBoundingRect( pEntry->aRect ); 334 } 335 } 336 337 void SvxIconChoiceCtrl_Impl::CreateAutoMnemonics( MnemonicGenerator* _pGenerator ) 338 { 339 ::std::auto_ptr< MnemonicGenerator > pAutoDeleteOwnGenerator; 340 if ( !_pGenerator ) 341 { 342 _pGenerator = new MnemonicGenerator; 343 pAutoDeleteOwnGenerator.reset( _pGenerator ); 344 } 345 346 sal_uLong nEntryCount = GetEntryCount(); 347 sal_uLong i; 348 349 // insert texts in generator 350 for( i = 0; i < nEntryCount; ++i ) 351 { 352 DBG_ASSERT( GetEntry( i ), "-SvxIconChoiceCtrl_Impl::CreateAutoMnemonics(): more expected than provided!" ); 353 354 _pGenerator->RegisterMnemonic( GetEntry( i )->GetText() ); 355 } 356 357 // exchange texts with generated mnemonics 358 for( i = 0; i < nEntryCount; ++i ) 359 { 360 SvxIconChoiceCtrlEntry* pEntry = GetEntry( i ); 361 String aTxt = pEntry->GetText(); 362 363 if( _pGenerator->CreateMnemonic( aTxt ) ) 364 pEntry->SetText( aTxt ); 365 } 366 } 367 368 Rectangle SvxIconChoiceCtrl_Impl::GetOutputRect() const 369 { 370 Point aOrigin( pView->GetMapMode().GetOrigin() ); 371 aOrigin *= -1; 372 return Rectangle( aOrigin, aOutputSize ); 373 } 374 375 void SvxIconChoiceCtrl_Impl::SetListPositions() 376 { 377 if( nFlags & F_ENTRYLISTPOS_VALID ) 378 return; 379 380 sal_uLong nCount = aEntries.Count(); 381 for( sal_uLong nCur = 0; nCur < nCount; nCur++ ) 382 { 383 SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( nCur ); 384 pEntry->nPos = nCur; 385 } 386 nFlags |= F_ENTRYLISTPOS_VALID; 387 } 388 389 void SvxIconChoiceCtrl_Impl::RemoveEntry( SvxIconChoiceCtrlEntry* pEntry ) 390 { 391 sal_Bool bSyncSingleSelection; 392 // bei Single-Selection wird die Selektion beim Umsetzen des Cursors 393 // mitgefuehrt. Das soll aber nur erfolgen, wenn ueberhaupt ein 394 // Eintrag selektiert ist. 395 if( GetSelectionCount() ) 396 bSyncSingleSelection = sal_True; 397 else 398 bSyncSingleSelection = sal_False; 399 400 if( pEntry == pCurHighlightFrame ) 401 pCurHighlightFrame = 0; 402 403 if( bInDragDrop ) 404 { 405 DELETEZ(pDraggedSelection); 406 bInDragDrop = sal_False; 407 } 408 409 if( pEntry->IsSelected() ) 410 CallSelectHandler( 0 ); 411 412 if( aEntries.Count() == 1 && aEntries.GetObject(0) == pEntry ) 413 { 414 Clear(); 415 return; 416 } 417 418 StopEditTimer(); 419 if( pEntry == pAnchor ) 420 pAnchor = 0; 421 if( pEntry->IsSelected() ) 422 nSelectionCount--; 423 sal_Bool bEntryBoundValid = IsBoundingRectValid( pEntry->aRect ); 424 if( bEntryBoundValid ) 425 pView->Invalidate( pEntry->aRect ); 426 427 sal_Bool bSetNewCursor = sal_False; 428 SvxIconChoiceCtrlEntry* pNewCursor = NULL; 429 430 if( pEntry == pCursor ) 431 { 432 bSetNewCursor = sal_True; 433 pNewCursor = FindNewCursor(); 434 ShowCursor( sal_False ); 435 pCursor = 0; 436 } 437 438 sal_Bool bCurEntryPosValid = (nFlags & F_ENTRYLISTPOS_VALID) ? sal_True : sal_False; 439 if( bCurEntryPosValid && aEntries.GetObject(aEntries.Count()-1) != pEntry ) 440 nFlags &= ~F_ENTRYLISTPOS_VALID; 441 sal_uLong nPos = pZOrderList->GetPos( (void*)pEntry ); 442 pZOrderList->Remove( nPos ); 443 if( bCurEntryPosValid ) 444 { 445 DBG_ASSERT(aEntries.GetObject(pEntry->nPos)==pEntry,"RemoveEntry: Wrong nPos in entry"); 446 aEntries.Remove( pEntry->nPos ); 447 } 448 else 449 aEntries.Remove( pEntry ); 450 pImpCursor->Clear(); 451 pGridMap->Clear(); 452 delete pEntry; 453 if( IsAutoArrange() && aEntries.Count() ) 454 aAutoArrangeTimer.Start(); 455 if( bSetNewCursor ) 456 { 457 // Fokusrechteck asynchron einblenden, um das Loeschen einer 458 // Multiselektion zu beschleunigen. 459 SetCursor( pNewCursor, bSyncSingleSelection, sal_True ); 460 } 461 } 462 463 void SvxIconChoiceCtrl_Impl::SelectEntry( SvxIconChoiceCtrlEntry* pEntry, sal_Bool bSelect, 464 sal_Bool bCallHdl, sal_Bool bAdd, sal_Bool bSyncPaint ) 465 { 466 if( eSelectionMode == NO_SELECTION ) 467 return; 468 469 if( !bAdd ) 470 { 471 if ( 0 == ( nFlags & F_CLEARING_SELECTION ) ) 472 { 473 nFlags |= F_CLEARING_SELECTION; 474 DeselectAllBut( pEntry, sal_True ); 475 nFlags &= ~F_CLEARING_SELECTION; 476 } 477 } 478 if( pEntry->IsSelected() != bSelect ) 479 { 480 pHdlEntry = pEntry; 481 sal_uInt16 nEntryFlags = pEntry->GetFlags(); 482 if( bSelect ) 483 { 484 nEntryFlags |= ICNVIEW_FLAG_SELECTED; 485 pEntry->AssignFlags( nEntryFlags ); 486 nSelectionCount++; 487 if( bCallHdl ) 488 CallSelectHandler( pEntry ); 489 } 490 else 491 { 492 nEntryFlags &= ~( ICNVIEW_FLAG_SELECTED); 493 pEntry->AssignFlags( nEntryFlags ); 494 nSelectionCount--; 495 if( bCallHdl ) 496 CallSelectHandler( 0 ); 497 } 498 EntrySelected( pEntry, bSelect, bSyncPaint ); 499 } 500 } 501 502 void SvxIconChoiceCtrl_Impl::EntrySelected( SvxIconChoiceCtrlEntry* pEntry, sal_Bool bSelect, 503 sal_Bool bSyncPaint ) 504 { 505 // bei SingleSelection dafuer sorgen, dass der Cursor immer 506 // auf dem (einzigen) selektierten Eintrag steht. Aber nur, 507 // wenn es bereits einen Cursor gibt 508 if( bSelect && pCursor && 509 eSelectionMode == SINGLE_SELECTION && 510 pEntry != pCursor ) 511 { 512 SetCursor( pEntry ); 513 //DBG_ASSERT(pView->GetSelectionCount()==1,"selection count?") 514 } 515 516 // beim Aufziehen nicht, da sonst die Schleife in SelectRect 517 // nicht richtig funktioniert! 518 if( !(nFlags & F_SELECTING_RECT) ) 519 ToTop( pEntry ); 520 if( bUpdateMode ) 521 { 522 if( pEntry == pCursor ) 523 ShowCursor( sal_False ); 524 if( pView->IsTracking() && (bSelect || !pView->HasBackground()) ) // beim Tracken immer synchron 525 PaintEntry( pEntry ); 526 else if( bSyncPaint ) // synchron & mit virtuellem OutDev! 527 PaintEntryVirtOutDev( pEntry ); 528 else 529 { 530 pView->Invalidate( CalcFocusRect( pEntry ) ); 531 } 532 if( pEntry == pCursor ) 533 ShowCursor( sal_True ); 534 } // if( bUpdateMode ) 535 536 // --> OD 2009-05-27 #i101012# 537 // emit vcl event LISTBOX_SELECT only in case that the given entry is selected. 538 if ( bSelect ) 539 { 540 CallEventListeners( VCLEVENT_LISTBOX_SELECT, pEntry ); 541 } 542 // <-- 543 } 544 545 void SvxIconChoiceCtrl_Impl::ResetVirtSize() 546 { 547 StopEditTimer(); 548 aVirtOutputSize.Width() = 0; 549 aVirtOutputSize.Height() = 0; 550 sal_Bool bLockedEntryFound = sal_False; 551 const sal_uLong nCount = aEntries.Count(); 552 for( sal_uLong nCur = 0; nCur < nCount; nCur++ ) 553 { 554 SvxIconChoiceCtrlEntry* pCur = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( nCur ); 555 pCur->ClearFlags( ICNVIEW_FLAG_POS_MOVED ); 556 if( pCur->IsPosLocked() ) 557 { 558 // VirtSize u.a. anpassen 559 if( !IsBoundingRectValid( pCur->aRect ) ) 560 FindBoundingRect( pCur ); 561 else 562 AdjustVirtSize( pCur->aRect ); 563 bLockedEntryFound = sal_True; 564 } 565 else 566 InvalidateBoundingRect( pCur->aRect ); 567 } 568 569 if( !(nWinBits & (WB_NOVSCROLL | WB_NOHSCROLL)) ) 570 { 571 Size aRealOutputSize( pView->GetOutputSizePixel() ); 572 if( aVirtOutputSize.Width() < aRealOutputSize.Width() || 573 aVirtOutputSize.Height() < aRealOutputSize.Height() ) 574 { 575 sal_uLong nGridCount = IcnGridMap_Impl::GetGridCount( 576 aRealOutputSize, (sal_uInt16)nGridDX, (sal_uInt16)nGridDY ); 577 if( nGridCount < nCount ) 578 { 579 if( nWinBits & WB_ALIGN_TOP ) 580 nMaxVirtWidth = aRealOutputSize.Width() - nVerSBarWidth; 581 else // WB_ALIGN_LEFT 582 nMaxVirtHeight = aRealOutputSize.Height() - nHorSBarHeight; 583 } 584 } 585 } 586 587 pImpCursor->Clear(); 588 pGridMap->Clear(); 589 VisRectChanged(); 590 } 591 592 void SvxIconChoiceCtrl_Impl::AdjustVirtSize( const Rectangle& rRect ) 593 { 594 long nHeightOffs = 0; 595 long nWidthOffs = 0; 596 597 if( aVirtOutputSize.Width() < (rRect.Right()+LROFFS_WINBORDER) ) 598 nWidthOffs = (rRect.Right()+LROFFS_WINBORDER) - aVirtOutputSize.Width(); 599 600 if( aVirtOutputSize.Height() < (rRect.Bottom()+TBOFFS_WINBORDER) ) 601 nHeightOffs = (rRect.Bottom()+TBOFFS_WINBORDER) - aVirtOutputSize.Height(); 602 603 if( nWidthOffs || nHeightOffs ) 604 { 605 Range aRange; 606 aVirtOutputSize.Width() += nWidthOffs; 607 aRange.Max() = aVirtOutputSize.Width(); 608 aHorSBar.SetRange( aRange ); 609 610 aVirtOutputSize.Height() += nHeightOffs; 611 aRange.Max() = aVirtOutputSize.Height(); 612 aVerSBar.SetRange( aRange ); 613 614 pImpCursor->Clear(); 615 pGridMap->OutputSizeChanged(); 616 AdjustScrollBars(); 617 DocRectChanged(); 618 } 619 } 620 621 void SvxIconChoiceCtrl_Impl::InitPredecessors() 622 { 623 DBG_ASSERT(!pHead,"SvxIconChoiceCtrl_Impl::InitPredecessors() >> Already initialized"); 624 sal_uLong nCount = aEntries.Count(); 625 if( nCount ) 626 { 627 SvxIconChoiceCtrlEntry* pPrev = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( 0 ); 628 for( sal_uLong nCur = 1; nCur <= nCount; nCur++ ) 629 { 630 pPrev->ClearFlags( ICNVIEW_FLAG_POS_LOCKED | ICNVIEW_FLAG_POS_MOVED | 631 ICNVIEW_FLAG_PRED_SET); 632 633 SvxIconChoiceCtrlEntry* pNext; 634 if( nCur == nCount ) 635 pNext = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( 0 ); 636 else 637 pNext = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( nCur ); 638 pPrev->pflink = pNext; 639 pNext->pblink = pPrev; 640 pPrev = pNext; 641 } 642 pHead = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( 0 ); 643 } 644 else 645 pHead = 0; 646 nFlags &= ~F_MOVED_ENTRIES; 647 } 648 649 void SvxIconChoiceCtrl_Impl::ClearPredecessors() 650 { 651 if( pHead ) 652 { 653 sal_uLong nCount = aEntries.Count(); 654 for( sal_uLong nCur = 0; nCur < nCount; nCur++ ) 655 { 656 SvxIconChoiceCtrlEntry* pCur = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( nCur ); 657 pCur->pflink = 0; 658 pCur->pblink = 0; 659 pCur->ClearFlags( ICNVIEW_FLAG_PRED_SET ); 660 } 661 pHead = 0; 662 } 663 } 664 665 void SvxIconChoiceCtrl_Impl::Arrange( sal_Bool bKeepPredecessors, long nSetMaxVirtWidth, long nSetMaxVirtHeight ) 666 { 667 if ( nSetMaxVirtWidth != 0 ) 668 nMaxVirtWidth = nSetMaxVirtWidth; 669 else 670 nMaxVirtWidth = aOutputSize.Width(); 671 672 if ( nSetMaxVirtHeight != 0 ) 673 nMaxVirtHeight = nSetMaxVirtHeight; 674 else 675 nMaxVirtHeight = aOutputSize.Height(); 676 677 ImpArrange( bKeepPredecessors ); 678 } 679 680 void SvxIconChoiceCtrl_Impl::ImpArrange( sal_Bool bKeepPredecessors ) 681 { 682 static Point aEmptyPoint; 683 684 sal_Bool bOldUpdate = bUpdateMode; 685 Rectangle aCurOutputArea( GetOutputRect() ); 686 if( (nWinBits & WB_SMART_ARRANGE) && aCurOutputArea.TopLeft() != aEmptyPoint ) 687 bUpdateMode = sal_False; 688 aAutoArrangeTimer.Stop(); 689 nFlags &= ~F_MOVED_ENTRIES; 690 nFlags |= F_ARRANGING; 691 StopEditTimer(); 692 ShowCursor( sal_False ); 693 ResetVirtSize(); 694 if( !bKeepPredecessors ) 695 ClearPredecessors(); 696 bBoundRectsDirty = sal_False; 697 SetOrigin( Point() ); 698 VisRectChanged(); 699 RecalcAllBoundingRectsSmart(); 700 // in der Detailsview muss das Invalidieren intelligenter erfolgen 701 //if( !(nWinBits & WB_DETAILS )) 702 pView->Invalidate( INVALIDATE_NOCHILDREN ); 703 nFlags &= ~F_ARRANGING; 704 if( (nWinBits & WB_SMART_ARRANGE) && aCurOutputArea.TopLeft() != aEmptyPoint ) 705 { 706 MakeVisible( aCurOutputArea ); 707 SetUpdateMode( bOldUpdate ); 708 } 709 ShowCursor( sal_True ); 710 } 711 712 void SvxIconChoiceCtrl_Impl::Paint( const Rectangle& rRect ) 713 { 714 bEndScrollInvalidate = sal_False; 715 716 #if defined(OV_DRAWGRID) 717 Color aOldColor ( pView->GetLineColor() ); 718 Color aColor( COL_BLACK ); 719 pView->SetLineColor( aColor ); 720 Point aOffs( pView->GetMapMode().GetOrigin()); 721 Size aXSize( pView->GetOutputSizePixel() ); 722 723 { 724 Point aStart( LROFFS_WINBORDER, 0 ); 725 Point aEnd( LROFFS_WINBORDER, aXSize.Height()); 726 aStart -= aOffs; 727 aEnd -= aOffs; 728 pView->DrawLine( aStart, aEnd ); 729 } 730 { 731 Point aStart( 0, TBOFFS_WINBORDER ); 732 Point aEnd( aXSize.Width(), TBOFFS_WINBORDER ); 733 aStart -= aOffs; 734 aEnd -= aOffs; 735 pView->DrawLine( aStart, aEnd ); 736 } 737 738 for( long nDX = nGridDX; nDX <= aXSize.Width(); nDX += nGridDX ) 739 { 740 Point aStart( nDX+LROFFS_WINBORDER, 0 ); 741 Point aEnd( nDX+LROFFS_WINBORDER, aXSize.Height()); 742 aStart -= aOffs; 743 aEnd -= aOffs; 744 pView->DrawLine( aStart, aEnd ); 745 } 746 for( long nDY = nGridDY; nDY <= aXSize.Height(); nDY += nGridDY ) 747 { 748 Point aStart( 0, nDY+TBOFFS_WINBORDER ); 749 Point aEnd( aXSize.Width(), nDY+TBOFFS_WINBORDER ); 750 aStart -= aOffs; 751 aEnd -= aOffs; 752 pView->DrawLine( aStart, aEnd ); 753 } 754 pView->SetLineColor( aOldColor ); 755 #endif 756 nFlags |= F_PAINTED; 757 758 if( !aEntries.Count() ) 759 return; 760 if( !pCursor ) 761 { 762 // set cursor to item with focus-flag 763 sal_Bool bfound = sal_False; 764 for ( sal_uLong i = 0; i < pView->GetEntryCount() && !bfound; i++) 765 { 766 SvxIconChoiceCtrlEntry* pEntry = pView->GetEntry ( i ); 767 if( pEntry->IsFocused() ) 768 { 769 pCursor = pEntry; 770 bfound=sal_True; 771 } 772 } 773 774 if( !bfound ) 775 pCursor = (SvxIconChoiceCtrlEntry*)aEntries.First(); 776 } 777 778 // Show Focus at Init-Time 779 if ( pView->HasFocus() ) 780 GetFocus(); 781 782 sal_uLong nCount = pZOrderList->Count(); 783 if( !nCount ) 784 return; 785 786 sal_Bool bResetClipRegion = sal_False; 787 if( !pView->IsClipRegion() ) 788 { 789 Rectangle aOutputArea( GetOutputRect() ); 790 bResetClipRegion = sal_True; 791 pView->SetClipRegion( aOutputArea ); 792 } 793 794 const sal_uInt16 nListInitSize = aEntries.Count() > USHRT_MAX ? 795 USHRT_MAX : (sal_uInt16)aEntries.Count(); 796 List* pNewZOrderList = new List( nListInitSize ); 797 List* pPaintedEntries = new List( nListInitSize ); 798 799 sal_uLong nPos = 0; 800 while( nCount ) 801 { 802 SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)(pZOrderList->GetObject(nPos )); 803 const Rectangle& rBoundRect = GetEntryBoundRect( pEntry ); 804 if( rRect.IsOver( rBoundRect ) ) 805 { 806 PaintEntry( pEntry, rBoundRect.TopLeft(), pView, sal_True ); 807 // Eintraege, die neu gezeichnet werden, auf Top setzen 808 pPaintedEntries->Insert( pEntry, LIST_APPEND ); 809 } 810 else 811 pNewZOrderList->Insert( pEntry, LIST_APPEND ); 812 813 nCount--; 814 nPos++; 815 } 816 delete pZOrderList; 817 pZOrderList = pNewZOrderList; 818 nCount = pPaintedEntries->Count(); 819 if( nCount ) 820 { 821 for( sal_uLong nCur = 0; nCur < nCount; nCur++ ) 822 pZOrderList->Insert( pPaintedEntries->GetObject(nCur), LIST_APPEND); 823 } 824 delete pPaintedEntries; 825 826 if( bResetClipRegion ) 827 pView->SetClipRegion(); 828 } 829 830 void SvxIconChoiceCtrl_Impl::RepaintEntries( sal_uInt16 nEntryFlagsMask ) 831 { 832 const sal_uLong nCount = pZOrderList->Count(); 833 if( !nCount ) 834 return; 835 836 sal_Bool bResetClipRegion = sal_False; 837 Rectangle aOutRect( GetOutputRect() ); 838 if( !pView->IsClipRegion() ) 839 { 840 bResetClipRegion = sal_True; 841 pView->SetClipRegion( aOutRect ); 842 } 843 for( sal_uLong nCur = 0; nCur < nCount; nCur++ ) 844 { 845 SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)(pZOrderList->GetObject(nCur)); 846 if( pEntry->GetFlags() & nEntryFlagsMask ) 847 { 848 const Rectangle& rBoundRect = GetEntryBoundRect( pEntry ); 849 if( aOutRect.IsOver( rBoundRect ) ) 850 PaintEntry( pEntry, rBoundRect.TopLeft() ); 851 } 852 } 853 if( bResetClipRegion ) 854 pView->SetClipRegion(); 855 } 856 857 858 void SvxIconChoiceCtrl_Impl::InitScrollBarBox() 859 { 860 aScrBarBox.SetSizePixel( Size(nVerSBarWidth-1, nHorSBarHeight-1) ); 861 Size aSize( pView->GetOutputSizePixel() ); 862 aScrBarBox.SetPosPixel( Point(aSize.Width()-nVerSBarWidth+1, aSize.Height()-nHorSBarHeight+1)); 863 } 864 865 IcnViewFieldType SvxIconChoiceCtrl_Impl::GetItem( SvxIconChoiceCtrlEntry* pEntry, 866 const Point& rAbsPos ) 867 { 868 Rectangle aRect( CalcTextRect( pEntry ) ); 869 if( aRect.IsInside( rAbsPos ) ) 870 return IcnViewFieldTypeText; 871 872 aRect = CalcBmpRect( pEntry ); 873 if( aRect.IsInside( rAbsPos ) ) 874 return IcnViewFieldTypeImage; 875 876 return IcnViewFieldTypeDontknow; 877 } 878 879 sal_Bool SvxIconChoiceCtrl_Impl::MouseButtonDown( const MouseEvent& rMEvt) 880 { 881 sal_Bool bHandled = sal_True; 882 bHighlightFramePressed = sal_False; 883 StopEditTimer(); 884 sal_Bool bGotFocus = (sal_Bool)(!pView->HasFocus() && !(nWinBits & WB_NOPOINTERFOCUS)); 885 if( !(nWinBits & WB_NOPOINTERFOCUS) ) 886 pView->GrabFocus(); 887 888 Point aDocPos( rMEvt.GetPosPixel() ); 889 if(aDocPos.X()>=aOutputSize.Width() || aDocPos.Y()>=aOutputSize.Height()) 890 return sal_False; 891 ToDocPos( aDocPos ); 892 SvxIconChoiceCtrlEntry* pEntry = GetEntry( aDocPos, sal_True ); 893 if( pEntry ) 894 MakeEntryVisible( pEntry, sal_False ); 895 896 if( rMEvt.IsShift() && eSelectionMode != SINGLE_SELECTION ) 897 { 898 if( pEntry ) 899 SetCursor_Impl( pCursor, pEntry, rMEvt.IsMod1(), rMEvt.IsShift(), sal_True); 900 return sal_True; 901 } 902 903 if( pAnchor && (rMEvt.IsShift() || rMEvt.IsMod1())) // Tastaturselektion? 904 { 905 DBG_ASSERT(eSelectionMode != SINGLE_SELECTION,"Invalid selection mode"); 906 if( rMEvt.IsMod1() ) 907 nFlags |= F_ADD_MODE; 908 909 if( rMEvt.IsShift() ) 910 { 911 Rectangle aRect( GetEntryBoundRect( pAnchor )); 912 if( pEntry ) 913 aRect.Union( GetEntryBoundRect( pEntry ) ); 914 else 915 { 916 Rectangle aTempRect( aDocPos, Size(1,1)); 917 aRect.Union( aTempRect ); 918 } 919 aCurSelectionRect = aRect; 920 SelectRect( aRect, (nFlags & F_ADD_MODE)!=0, &aSelectedRectList ); 921 } 922 else if( rMEvt.IsMod1() ) 923 { 924 AddSelectedRect( aCurSelectionRect ); 925 pAnchor = 0; 926 aCurSelectionRect.SetPos( aDocPos ); 927 } 928 929 if( !pEntry && !(nWinBits & WB_NODRAGSELECTION)) 930 pView->StartTracking( STARTTRACK_SCROLLREPEAT ); 931 return sal_True; 932 } 933 else 934 { 935 if( !pEntry ) 936 { 937 if( eSelectionMode == MULTIPLE_SELECTION ) 938 { 939 if( !rMEvt.IsMod1() ) // Ctrl 940 { 941 if( !bGotFocus ) 942 { 943 SetNoSelection(); 944 ClearSelectedRectList(); 945 } 946 } 947 else 948 nFlags |= F_ADD_MODE; 949 aCurSelectionRect.SetPos( aDocPos ); 950 pView->StartTracking( STARTTRACK_SCROLLREPEAT ); 951 } 952 else 953 bHandled = sal_False; 954 return bHandled; 955 } 956 } 957 sal_Bool bSelected = pEntry->IsSelected(); 958 sal_Bool bEditingEnabled = IsEntryEditingEnabled(); 959 960 if( rMEvt.GetClicks() == 2 ) 961 { 962 DeselectAllBut( pEntry ); 963 SelectEntry( pEntry, sal_True, sal_True, sal_False, sal_True ); 964 pHdlEntry = pEntry; 965 pView->ClickIcon(); 966 } 967 else 968 { 969 // Inplace-Editing ? 970 if( rMEvt.IsMod2() ) // Alt? 971 { 972 if( bEntryEditingEnabled && pEntry && 973 pEntry->IsSelected()) 974 { 975 if( pView->EditingEntry( pEntry )) 976 EditEntry( pEntry ); 977 } 978 } 979 else if( eSelectionMode == SINGLE_SELECTION ) 980 { 981 DeselectAllBut( pEntry ); 982 SetCursor( pEntry ); 983 if( bEditingEnabled && bSelected && !rMEvt.GetModifier() && 984 rMEvt.IsLeft() && IsTextHit( pEntry, aDocPos ) ) 985 { 986 nFlags |= F_START_EDITTIMER_IN_MOUSEUP; 987 } 988 } 989 else if( eSelectionMode == NO_SELECTION ) 990 { 991 if( rMEvt.IsLeft() && (nWinBits & WB_HIGHLIGHTFRAME) ) 992 { 993 pCurHighlightFrame = 0; // Neues painten des Frames erzwingen 994 bHighlightFramePressed = sal_True; 995 SetEntryHighlightFrame( pEntry, sal_True ); 996 } 997 } 998 else 999 { 1000 if( !rMEvt.GetModifier() && rMEvt.IsLeft() ) 1001 { 1002 if( !bSelected ) 1003 { 1004 DeselectAllBut( pEntry, sal_True /* Synchron painten */ ); 1005 SetCursor( pEntry ); 1006 SelectEntry( pEntry, sal_True, sal_True, sal_False, sal_True ); 1007 } 1008 else 1009 { 1010 // erst im Up deselektieren, falls Move per D&D! 1011 nFlags |= F_DOWN_DESELECT; 1012 if( bEditingEnabled && IsTextHit( pEntry, aDocPos ) && 1013 rMEvt.IsLeft()) 1014 { 1015 nFlags |= F_START_EDITTIMER_IN_MOUSEUP; 1016 } 1017 } 1018 } 1019 else if( rMEvt.IsMod1() ) 1020 nFlags |= F_DOWN_CTRL; 1021 } 1022 } 1023 return bHandled; 1024 } 1025 1026 sal_Bool SvxIconChoiceCtrl_Impl::MouseButtonUp( const MouseEvent& rMEvt ) 1027 { 1028 sal_Bool bHandled = sal_False; 1029 if( rMEvt.IsRight() && (nFlags & (F_DOWN_CTRL | F_DOWN_DESELECT) )) 1030 { 1031 nFlags &= ~(F_DOWN_CTRL | F_DOWN_DESELECT); 1032 bHandled = sal_True; 1033 } 1034 1035 Point aDocPos( rMEvt.GetPosPixel() ); 1036 ToDocPos( aDocPos ); 1037 SvxIconChoiceCtrlEntry* pDocEntry = GetEntry( aDocPos ); 1038 if( pDocEntry ) 1039 { 1040 if( nFlags & F_DOWN_CTRL ) 1041 { 1042 // Ctrl & MultiSelection 1043 ToggleSelection( pDocEntry ); 1044 SetCursor( pDocEntry ); 1045 bHandled = sal_True; 1046 } 1047 else if( nFlags & F_DOWN_DESELECT ) 1048 { 1049 DeselectAllBut( pDocEntry ); 1050 SetCursor( pDocEntry ); 1051 SelectEntry( pDocEntry, sal_True, sal_True, sal_False, sal_True ); 1052 bHandled = sal_True; 1053 } 1054 } 1055 1056 nFlags &= ~(F_DOWN_CTRL | F_DOWN_DESELECT); 1057 if( nFlags & F_START_EDITTIMER_IN_MOUSEUP ) 1058 { 1059 bHandled = sal_True; 1060 StartEditTimer(); 1061 nFlags &= ~F_START_EDITTIMER_IN_MOUSEUP; 1062 } 1063 1064 if((nWinBits & WB_HIGHLIGHTFRAME) && bHighlightFramePressed && pCurHighlightFrame) 1065 { 1066 bHandled = sal_True; 1067 SvxIconChoiceCtrlEntry* pEntry = pCurHighlightFrame; 1068 pCurHighlightFrame = 0; // Neues painten des Frames erzwingen 1069 bHighlightFramePressed = sal_False; 1070 SetEntryHighlightFrame( pEntry, sal_True ); 1071 #if 0 1072 CallSelectHandler( pCurHighlightFrame ); 1073 #else 1074 pHdlEntry = pCurHighlightFrame; 1075 pView->ClickIcon(); 1076 1077 // set focus on Icon 1078 SvxIconChoiceCtrlEntry* pOldCursor = pCursor; 1079 SetCursor_Impl( pOldCursor, pHdlEntry, sal_False, sal_False, sal_True ); 1080 #endif 1081 pHdlEntry = 0; 1082 } 1083 return bHandled; 1084 } 1085 1086 sal_Bool SvxIconChoiceCtrl_Impl::MouseMove( const MouseEvent& rMEvt ) 1087 { 1088 const Point aDocPos( pView->PixelToLogic(rMEvt.GetPosPixel()) ); 1089 1090 if( pView->IsTracking() ) 1091 return sal_False; 1092 else if( nWinBits & WB_HIGHLIGHTFRAME ) 1093 { 1094 SvxIconChoiceCtrlEntry* pEntry = GetEntry( aDocPos, sal_True ); 1095 SetEntryHighlightFrame( pEntry ); 1096 } 1097 else 1098 return sal_False; 1099 return sal_True; 1100 } 1101 1102 void SvxIconChoiceCtrl_Impl::Tracking( const TrackingEvent& rTEvt ) 1103 { 1104 if ( rTEvt.IsTrackingEnded() ) 1105 { 1106 // Das Rechteck darf nicht "justified" sein, da seine 1107 // TopLeft-Position u.U. zur Berechnung eines Ankers 1108 // benutzt wird. 1109 AddSelectedRect( aCurSelectionRect ); 1110 pView->HideTracking(); 1111 nFlags &= ~(F_ADD_MODE); 1112 if( rTEvt.IsTrackingCanceled() ) 1113 SetNoSelection(); 1114 } 1115 else 1116 { 1117 Point aPosPixel = rTEvt.GetMouseEvent().GetPosPixel(); 1118 Point aDocPos( aPosPixel ); 1119 ToDocPos( aDocPos ); 1120 1121 long nScrollDX, nScrollDY; 1122 1123 CalcScrollOffsets( aPosPixel, nScrollDX, nScrollDY, sal_False ); 1124 if( nScrollDX || nScrollDY ) 1125 { 1126 pView->HideTracking(); 1127 pView->Scroll( nScrollDX, nScrollDY ); 1128 } 1129 Rectangle aRect( aCurSelectionRect.TopLeft(), aDocPos ); 1130 if( aRect != aCurSelectionRect ) 1131 { 1132 pView->HideTracking(); 1133 sal_Bool bAdd = (nFlags & F_ADD_MODE) ? sal_True : sal_False; 1134 SelectRect( aRect, bAdd, &aSelectedRectList ); 1135 } 1136 pView->ShowTracking( aRect, SHOWTRACK_SMALL | SHOWTRACK_CLIP ); 1137 } 1138 } 1139 1140 void SvxIconChoiceCtrl_Impl::SetCursor_Impl( SvxIconChoiceCtrlEntry* pOldCursor, 1141 SvxIconChoiceCtrlEntry* pNewCursor, sal_Bool bMod1, sal_Bool bShift, sal_Bool bPaintSync ) 1142 { 1143 if( pNewCursor ) 1144 { 1145 SvxIconChoiceCtrlEntry* pFilterEntry = 0; 1146 sal_Bool bDeselectAll = sal_False; 1147 if( eSelectionMode != SINGLE_SELECTION ) 1148 { 1149 if( !bMod1 && !bShift ) 1150 bDeselectAll = sal_True; 1151 else if( bShift && !bMod1 && !pAnchor ) 1152 { 1153 bDeselectAll = sal_True; 1154 pFilterEntry = pOldCursor; 1155 } 1156 } 1157 if( bDeselectAll ) 1158 DeselectAllBut( pFilterEntry, bPaintSync ); 1159 ShowCursor( sal_False ); 1160 MakeEntryVisible( pNewCursor ); 1161 SetCursor( pNewCursor ); 1162 if( bMod1 && !bShift ) 1163 { 1164 if( pAnchor ) 1165 { 1166 AddSelectedRect( pAnchor, pOldCursor ); 1167 pAnchor = 0; 1168 } 1169 } 1170 else if( bShift ) 1171 { 1172 if( !pAnchor ) 1173 pAnchor = pOldCursor; 1174 if ( nWinBits & WB_ALIGN_LEFT ) 1175 SelectRange( pAnchor, pNewCursor, (nFlags & F_ADD_MODE)!=0 ); 1176 else 1177 SelectRect(pAnchor,pNewCursor,(nFlags & F_ADD_MODE)!=0,&aSelectedRectList); 1178 } 1179 else 1180 { 1181 SelectEntry( pCursor, sal_True, sal_True, sal_False, bPaintSync ); 1182 aCurSelectionRect = GetEntryBoundRect( pCursor ); 1183 CallEventListeners( VCLEVENT_LISTBOX_SELECT, pCursor ); 1184 } 1185 } 1186 } 1187 1188 sal_Bool SvxIconChoiceCtrl_Impl::KeyInput( const KeyEvent& rKEvt ) 1189 { 1190 StopEditTimer(); 1191 1192 sal_Bool bMod2 = rKEvt.GetKeyCode().IsMod2(); 1193 sal_Unicode cChar = rKEvt.GetCharCode(); 1194 sal_uLong nPos = (sal_uLong)-1; 1195 if ( bMod2 && cChar && IsMnemonicChar( cChar, nPos ) ) 1196 { 1197 // shortcut is clicked 1198 SvxIconChoiceCtrlEntry* pNewCursor = GetEntry( nPos ); 1199 SvxIconChoiceCtrlEntry* pOldCursor = pCursor; 1200 if ( pNewCursor != pOldCursor ) 1201 SetCursor_Impl( pOldCursor, pNewCursor, sal_False, sal_False, sal_False ); 1202 return sal_True; 1203 } 1204 1205 if ( bMod2 ) 1206 // no actions with <ALT> 1207 return sal_False; 1208 1209 sal_Bool bKeyUsed = sal_True; 1210 sal_Bool bMod1 = rKEvt.GetKeyCode().IsMod1(); 1211 sal_Bool bShift = rKEvt.GetKeyCode().IsShift(); 1212 1213 if( eSelectionMode == SINGLE_SELECTION || eSelectionMode == NO_SELECTION) 1214 { 1215 bShift = sal_False; 1216 bMod1 = sal_False; 1217 } 1218 1219 if( bMod1 ) 1220 nFlags |= F_ADD_MODE; 1221 sal_Bool bDeselectAll = sal_False; 1222 if( eSelectionMode != SINGLE_SELECTION ) 1223 { 1224 if( !bMod1 && !bShift ) 1225 bDeselectAll = sal_True; 1226 if( bShift && !bMod1 && !pAnchor ) 1227 bDeselectAll = sal_True; 1228 } 1229 1230 SvxIconChoiceCtrlEntry* pNewCursor; 1231 SvxIconChoiceCtrlEntry* pOldCursor = pCursor; 1232 1233 sal_uInt16 nCode = rKEvt.GetKeyCode().GetCode(); 1234 switch( nCode ) 1235 { 1236 case KEY_UP: 1237 case KEY_PAGEUP: 1238 if( pCursor ) 1239 { 1240 MakeEntryVisible( pCursor ); 1241 if( nCode == KEY_UP ) 1242 pNewCursor = pImpCursor->GoUpDown(pCursor,sal_False); 1243 else 1244 pNewCursor = pImpCursor->GoPageUpDown(pCursor,sal_False); 1245 SetCursor_Impl( pOldCursor, pNewCursor, bMod1, bShift, sal_True ); 1246 if( !pNewCursor ) 1247 { 1248 Rectangle aRect( GetEntryBoundRect( pCursor ) ); 1249 if( aRect.Top()) 1250 { 1251 aRect.Bottom() -= aRect.Top(); 1252 aRect.Top() = 0; 1253 MakeVisible( aRect ); 1254 } 1255 } 1256 1257 if ( bChooseWithCursor && pNewCursor != NULL ) 1258 { 1259 pHdlEntry = pNewCursor;//GetCurEntry(); 1260 pCurHighlightFrame = pHdlEntry; 1261 pView->ClickIcon(); 1262 pCurHighlightFrame = NULL; 1263 } 1264 } 1265 break; 1266 1267 case KEY_DOWN: 1268 case KEY_PAGEDOWN: 1269 if( pCursor ) 1270 { 1271 if( nCode == KEY_DOWN ) 1272 pNewCursor=pImpCursor->GoUpDown( pCursor,sal_True ); 1273 else 1274 pNewCursor=pImpCursor->GoPageUpDown( pCursor,sal_True ); 1275 SetCursor_Impl( pOldCursor, pNewCursor, bMod1, bShift, sal_True ); 1276 1277 if ( bChooseWithCursor && pNewCursor != NULL) 1278 { 1279 pHdlEntry = pNewCursor;//GetCurEntry(); 1280 pCurHighlightFrame = pHdlEntry; 1281 pView->ClickIcon(); 1282 pCurHighlightFrame = NULL; 1283 } 1284 } 1285 break; 1286 1287 case KEY_RIGHT: 1288 if( pCursor ) 1289 { 1290 pNewCursor=pImpCursor->GoLeftRight(pCursor,sal_True ); 1291 SetCursor_Impl( pOldCursor, pNewCursor, bMod1, bShift, sal_True ); 1292 } 1293 break; 1294 1295 case KEY_LEFT: 1296 if( pCursor ) 1297 { 1298 MakeEntryVisible( pCursor ); 1299 pNewCursor = pImpCursor->GoLeftRight(pCursor,sal_False ); 1300 SetCursor_Impl( pOldCursor, pNewCursor, bMod1, bShift, sal_True ); 1301 if( !pNewCursor ) 1302 { 1303 Rectangle aRect( GetEntryBoundRect(pCursor)); 1304 if( aRect.Left() ) 1305 { 1306 aRect.Right() -= aRect.Left(); 1307 aRect.Left() = 0; 1308 MakeVisible( aRect ); 1309 } 1310 } 1311 } 1312 break; 1313 1314 // wird vom VCL-Tracking gesteuert 1315 #if 0 1316 case KEY_ESCAPE: 1317 if( pView->IsTracking() ) 1318 { 1319 HideSelectionRect(); 1320 //SelectAll( sal_False ); 1321 SetNoSelection(); 1322 ClearSelectedRectList(); 1323 nFlags &= ~F_TRACKING; 1324 } 1325 else 1326 bKeyUsed = sal_False; 1327 break; 1328 #endif 1329 1330 1331 case KEY_F2: 1332 if( !bMod1 && !bShift ) 1333 EditTimeoutHdl( 0 ); 1334 else 1335 bKeyUsed = sal_False; 1336 break; 1337 1338 case KEY_F8: 1339 if( rKEvt.GetKeyCode().IsShift() ) 1340 { 1341 if( nFlags & F_ADD_MODE ) 1342 nFlags &= (~F_ADD_MODE); 1343 else 1344 nFlags |= F_ADD_MODE; 1345 } 1346 else 1347 bKeyUsed = sal_False; 1348 break; 1349 1350 case KEY_SPACE: 1351 if( pCursor && eSelectionMode != SINGLE_SELECTION ) 1352 { 1353 if( !bMod1 ) 1354 { 1355 //SelectAll( sal_False ); 1356 SetNoSelection(); 1357 ClearSelectedRectList(); 1358 1359 // click Icon with spacebar 1360 SetEntryHighlightFrame( GetCurEntry(), sal_True ); 1361 pView->ClickIcon(); 1362 pHdlEntry = pCurHighlightFrame; 1363 pCurHighlightFrame=0; 1364 } 1365 else 1366 ToggleSelection( pCursor ); 1367 } 1368 break; 1369 1370 #ifdef DBG_UTIL 1371 case KEY_F10: 1372 if( rKEvt.GetKeyCode().IsShift() ) 1373 { 1374 if( pCursor ) 1375 pView->SetEntryTextMode( IcnShowTextFull, pCursor ); 1376 } 1377 if( rKEvt.GetKeyCode().IsMod1() ) 1378 { 1379 if( pCursor ) 1380 pView->SetEntryTextMode( IcnShowTextShort, pCursor ); 1381 } 1382 break; 1383 #endif 1384 1385 case KEY_ADD: 1386 case KEY_DIVIDE : 1387 case KEY_A: 1388 if( bMod1 && (eSelectionMode != SINGLE_SELECTION)) 1389 SelectAll( sal_True ); 1390 else 1391 bKeyUsed = sal_False; 1392 break; 1393 1394 case KEY_SUBTRACT: 1395 case KEY_COMMA : 1396 if( bMod1 ) 1397 SetNoSelection(); 1398 else 1399 bKeyUsed = sal_False; 1400 break; 1401 1402 case KEY_RETURN: 1403 if( bMod1 ) 1404 { 1405 if( pCursor && bEntryEditingEnabled ) 1406 /*pView->*/EditEntry( pCursor ); 1407 } 1408 else 1409 bKeyUsed = sal_False; 1410 break; 1411 1412 case KEY_END: 1413 if( pCursor ) 1414 { 1415 pNewCursor = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( aEntries.Count() - 1 ); 1416 SetCursor_Impl( pOldCursor, pNewCursor, bMod1, bShift, sal_True ); 1417 } 1418 break; 1419 1420 case KEY_HOME: 1421 if( pCursor ) 1422 { 1423 pNewCursor = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( 0 ); 1424 SetCursor_Impl( pOldCursor, pNewCursor, bMod1, bShift, sal_True ); 1425 } 1426 break; 1427 1428 default: 1429 bKeyUsed = sal_False; 1430 1431 } 1432 return bKeyUsed; 1433 } 1434 1435 // Berechnet TopLeft der Scrollbars (nicht ihre Groessen!) 1436 void SvxIconChoiceCtrl_Impl::PositionScrollBars( long nRealWidth, long nRealHeight ) 1437 { 1438 // hor scrollbar 1439 Point aPos( 0, nRealHeight ); 1440 aPos.Y() -= nHorSBarHeight; 1441 1442 if( aHorSBar.GetPosPixel() != aPos ) 1443 aHorSBar.SetPosPixel( aPos ); 1444 1445 // ver scrollbar 1446 aPos.X() = nRealWidth; aPos.Y() = 0; 1447 aPos.X() -= nVerSBarWidth; 1448 aPos.X()++; 1449 aPos.Y()--; 1450 1451 if( aVerSBar.GetPosPixel() != aPos ) 1452 aVerSBar.SetPosPixel( aPos ); 1453 } 1454 1455 void SvxIconChoiceCtrl_Impl::AdjustScrollBars( sal_Bool ) 1456 { 1457 Rectangle aOldOutRect( GetOutputRect() ); 1458 long nVirtHeight = aVirtOutputSize.Height(); 1459 long nVirtWidth = aVirtOutputSize.Width(); 1460 1461 Size aOSize( pView->Control::GetOutputSizePixel() ); 1462 long nRealHeight = aOSize.Height(); 1463 long nRealWidth = aOSize.Width(); 1464 1465 PositionScrollBars( nRealWidth, nRealHeight ); 1466 1467 const MapMode& rMapMode = pView->GetMapMode(); 1468 Point aOrigin( rMapMode.GetOrigin() ); 1469 1470 long nVisibleWidth; 1471 if( nRealWidth > nVirtWidth ) 1472 nVisibleWidth = nVirtWidth + aOrigin.X(); 1473 else 1474 nVisibleWidth = nRealWidth; 1475 1476 long nVisibleHeight; 1477 if( nRealHeight > nVirtHeight ) 1478 nVisibleHeight = nVirtHeight + aOrigin.Y(); 1479 else 1480 nVisibleHeight = nRealHeight; 1481 1482 sal_Bool bVerSBar = ( nWinBits & WB_VSCROLL ) != 0; 1483 sal_Bool bHorSBar = ( nWinBits & WB_HSCROLL ) != 0; 1484 sal_Bool bNoVerSBar = ( nWinBits & WB_NOVSCROLL ) != 0; 1485 sal_Bool bNoHorSBar = ( nWinBits & WB_NOHSCROLL ) != 0; 1486 1487 sal_uInt16 nResult = 0; 1488 if( nVirtHeight ) 1489 { 1490 // activate ver scrollbar ? 1491 if( !bNoVerSBar && (bVerSBar || ( nVirtHeight > nVisibleHeight)) ) 1492 { 1493 nResult = 0x0001; 1494 nRealWidth -= nVerSBarWidth; 1495 1496 if( nRealWidth > nVirtWidth ) 1497 nVisibleWidth = nVirtWidth + aOrigin.X(); 1498 else 1499 nVisibleWidth = nRealWidth; 1500 1501 nFlags |= F_HOR_SBARSIZE_WITH_VBAR; 1502 } 1503 // activate hor scrollbar ? 1504 if( !bNoHorSBar && (bHorSBar || (nVirtWidth > nVisibleWidth)) ) 1505 { 1506 nResult |= 0x0002; 1507 nRealHeight -= nHorSBarHeight; 1508 1509 if( nRealHeight > nVirtHeight ) 1510 nVisibleHeight = nVirtHeight + aOrigin.Y(); 1511 else 1512 nVisibleHeight = nRealHeight; 1513 1514 // brauchen wir jetzt doch eine senkrechte Scrollbar ? 1515 if( !(nResult & 0x0001) && // nur wenn nicht schon da 1516 ( !bNoVerSBar && ((nVirtHeight > nVisibleHeight) || bVerSBar)) ) 1517 { 1518 nResult = 3; // beide sind an 1519 nRealWidth -= nVerSBarWidth; 1520 1521 if( nRealWidth > nVirtWidth ) 1522 nVisibleWidth = nVirtWidth + aOrigin.X(); 1523 else 1524 nVisibleWidth = nRealWidth; 1525 1526 nFlags |= F_VER_SBARSIZE_WITH_HBAR; 1527 } 1528 } 1529 } 1530 1531 // size ver scrollbar 1532 long nThumb = aVerSBar.GetThumbPos(); 1533 Size aSize( nVerSBarWidth, nRealHeight ); 1534 aSize.Height() += 2; 1535 if( aSize != aVerSBar.GetSizePixel() ) 1536 aVerSBar.SetSizePixel( aSize ); 1537 aVerSBar.SetVisibleSize( nVisibleHeight ); 1538 aVerSBar.SetPageSize( GetScrollBarPageSize( nVisibleHeight )); 1539 1540 if( nResult & 0x0001 ) 1541 { 1542 aVerSBar.SetThumbPos( nThumb ); 1543 aVerSBar.Show(); 1544 } 1545 else 1546 { 1547 aVerSBar.SetThumbPos( 0 ); 1548 aVerSBar.Hide(); 1549 } 1550 1551 // size hor scrollbar 1552 nThumb = aHorSBar.GetThumbPos(); 1553 aSize.Width() = nRealWidth; 1554 aSize.Height() = nHorSBarHeight; 1555 aSize.Width()++; 1556 if( nResult & 0x0001 ) // vertikale Scrollbar ? 1557 { 1558 aSize.Width()++; 1559 nRealWidth++; 1560 } 1561 if( aSize != aHorSBar.GetSizePixel() ) 1562 aHorSBar.SetSizePixel( aSize ); 1563 aHorSBar.SetVisibleSize( nVisibleWidth ); 1564 aHorSBar.SetPageSize( GetScrollBarPageSize(nVisibleWidth )); 1565 if( nResult & 0x0002 ) 1566 { 1567 aHorSBar.SetThumbPos( nThumb ); 1568 aHorSBar.Show(); 1569 } 1570 else 1571 { 1572 aHorSBar.SetThumbPos( 0 ); 1573 aHorSBar.Hide(); 1574 } 1575 1576 aOutputSize.Width() = nRealWidth; 1577 if( nResult & 0x0002 ) // hor scrollbar ? 1578 nRealHeight++; // weil unterer Rand geclippt wird 1579 aOutputSize.Height() = nRealHeight; 1580 1581 Rectangle aNewOutRect( GetOutputRect() ); 1582 if( aNewOutRect != aOldOutRect && pView->HasBackground() ) 1583 { 1584 Wallpaper aPaper( pView->GetBackground() ); 1585 aPaper.SetRect( aNewOutRect ); 1586 pView->SetBackground( aPaper ); 1587 } 1588 1589 if( (nResult & (0x0001|0x0002)) == (0x0001|0x0002) ) 1590 aScrBarBox.Show(); 1591 else 1592 aScrBarBox.Hide(); 1593 } 1594 1595 void SvxIconChoiceCtrl_Impl::Resize() 1596 { 1597 StopEditTimer(); 1598 InitScrollBarBox(); 1599 aOutputSize = pView->GetOutputSizePixel(); 1600 pImpCursor->Clear(); 1601 pGridMap->OutputSizeChanged(); 1602 1603 const Size& rSize = pView->Control::GetOutputSizePixel(); 1604 PositionScrollBars( rSize.Width(), rSize.Height() ); 1605 // Die ScrollBars werden asynchron ein/ausgeblendet, damit abgeleitete 1606 // Klassen im Resize ein Arrange durchfuehren koennen, ohne dass 1607 // die ScrollBars aufblitzen 1608 // Wenn schon ein Event unterwegs ist, dann braucht kein neues verschickt werden, 1609 // zumindest, solange es nur einen EventTypen gibt 1610 if ( ! nUserEventAdjustScrBars ) 1611 nUserEventAdjustScrBars = 1612 Application::PostUserEvent( LINK( this, SvxIconChoiceCtrl_Impl, UserEventHdl), 1613 EVENTID_ADJUST_SCROLLBARS); 1614 1615 if( pView->HasBackground() && !pView->GetBackground().IsScrollable() ) 1616 { 1617 Rectangle aRect( GetOutputRect()); 1618 Wallpaper aPaper( pView->GetBackground() ); 1619 aPaper.SetRect( aRect ); 1620 pView->SetBackground( aPaper ); 1621 } 1622 VisRectChanged(); 1623 } 1624 1625 sal_Bool SvxIconChoiceCtrl_Impl::CheckHorScrollBar() 1626 { 1627 if( !pZOrderList || !aHorSBar.IsVisible() ) 1628 return sal_False; 1629 const MapMode& rMapMode = pView->GetMapMode(); 1630 Point aOrigin( rMapMode.GetOrigin() ); 1631 if(!( nWinBits & WB_HSCROLL) && !aOrigin.X() ) 1632 { 1633 long nWidth = aOutputSize.Width(); 1634 const sal_uLong nCount = pZOrderList->Count(); 1635 long nMostRight = 0; 1636 for( sal_uLong nCur = 0; nCur < nCount; nCur++ ) 1637 { 1638 SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)pZOrderList->GetObject(nCur); 1639 long nRight = GetEntryBoundRect(pEntry).Right(); 1640 if( nRight > nWidth ) 1641 return sal_False; 1642 if( nRight > nMostRight ) 1643 nMostRight = nRight; 1644 } 1645 aHorSBar.Hide(); 1646 aOutputSize.Height() += nHorSBarHeight; 1647 aVirtOutputSize.Width() = nMostRight; 1648 aHorSBar.SetThumbPos( 0 ); 1649 Range aRange; 1650 aRange.Max() = nMostRight - 1; 1651 aHorSBar.SetRange( aRange ); 1652 if( aVerSBar.IsVisible() ) 1653 { 1654 Size aSize( aVerSBar.GetSizePixel()); 1655 aSize.Height() += nHorSBarHeight; 1656 aVerSBar.SetSizePixel( aSize ); 1657 } 1658 return sal_True; 1659 } 1660 return sal_False; 1661 } 1662 1663 sal_Bool SvxIconChoiceCtrl_Impl::CheckVerScrollBar() 1664 { 1665 if( !pZOrderList || !aVerSBar.IsVisible() ) 1666 return sal_False; 1667 const MapMode& rMapMode = pView->GetMapMode(); 1668 Point aOrigin( rMapMode.GetOrigin() ); 1669 if(!( nWinBits & WB_VSCROLL) && !aOrigin.Y() ) 1670 { 1671 long nDeepest = 0; 1672 long nHeight = aOutputSize.Height(); 1673 const sal_uLong nCount = pZOrderList->Count(); 1674 for( sal_uLong nCur = 0; nCur < nCount; nCur++ ) 1675 { 1676 SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)pZOrderList->GetObject(nCur); 1677 long nBottom = GetEntryBoundRect(pEntry).Bottom(); 1678 if( nBottom > nHeight ) 1679 return sal_False; 1680 if( nBottom > nDeepest ) 1681 nDeepest = nBottom; 1682 } 1683 aVerSBar.Hide(); 1684 aOutputSize.Width() += nVerSBarWidth; 1685 aVirtOutputSize.Height() = nDeepest; 1686 aVerSBar.SetThumbPos( 0 ); 1687 Range aRange; 1688 aRange.Max() = nDeepest - 1; 1689 aVerSBar.SetRange( aRange ); 1690 if( aHorSBar.IsVisible() ) 1691 { 1692 Size aSize( aHorSBar.GetSizePixel()); 1693 aSize.Width() += nVerSBarWidth; 1694 aHorSBar.SetSizePixel( aSize ); 1695 } 1696 return sal_True; 1697 } 1698 return sal_False; 1699 } 1700 1701 1702 // blendet Scrollbars aus, wenn sie nicht mehr benoetigt werden 1703 void SvxIconChoiceCtrl_Impl::CheckScrollBars() 1704 { 1705 CheckVerScrollBar(); 1706 if( CheckHorScrollBar() ) 1707 CheckVerScrollBar(); 1708 if( aVerSBar.IsVisible() && aHorSBar.IsVisible() ) 1709 aScrBarBox.Show(); 1710 else 1711 aScrBarBox.Hide(); 1712 } 1713 1714 1715 void SvxIconChoiceCtrl_Impl::GetFocus() 1716 { 1717 RepaintEntries( ICNVIEW_FLAG_SELECTED ); 1718 if( pCursor ) 1719 { 1720 pCursor->SetFlags( ICNVIEW_FLAG_FOCUSED ); 1721 ShowCursor( sal_True ); 1722 } 1723 } 1724 1725 void SvxIconChoiceCtrl_Impl::LoseFocus() 1726 { 1727 StopEditTimer(); 1728 if( pCursor ) 1729 pCursor->ClearFlags( ICNVIEW_FLAG_FOCUSED ); 1730 ShowCursor( sal_False ); 1731 1732 // HideFocus (); 1733 // pView->Invalidate ( aFocus.aRect ); 1734 1735 RepaintEntries( ICNVIEW_FLAG_SELECTED ); 1736 } 1737 1738 void SvxIconChoiceCtrl_Impl::SetUpdateMode( sal_Bool bUpdate ) 1739 { 1740 if( bUpdate != bUpdateMode ) 1741 { 1742 bUpdateMode = bUpdate; 1743 if( bUpdate ) 1744 { 1745 AdjustScrollBars(); 1746 pImpCursor->Clear(); 1747 pGridMap->Clear(); 1748 pView->Invalidate(INVALIDATE_NOCHILDREN); 1749 } 1750 } 1751 } 1752 1753 void SvxIconChoiceCtrl_Impl::PaintEntry( SvxIconChoiceCtrlEntry* pEntry, sal_Bool bIsBackgroundPainted ) 1754 { 1755 Point aPos( GetEntryPos( pEntry ) ); 1756 PaintEntry( pEntry, aPos, 0, bIsBackgroundPainted ); 1757 } 1758 1759 // Prios der Emphasis: bDropTarget => bCursored => bSelected 1760 void SvxIconChoiceCtrl_Impl::PaintEmphasis( 1761 const Rectangle& rTextRect, const Rectangle& rImageRect, 1762 sal_Bool bSelected, sal_Bool bDropTarget, sal_Bool bCursored, OutputDevice* pOut, 1763 sal_Bool bIsBackgroundPainted ) 1764 { 1765 static Color aTransparent( COL_TRANSPARENT ); 1766 1767 if( !pOut ) 1768 pOut = pView; 1769 1770 #ifdef OV_CHECK_EMPH_RECTS 1771 { 1772 Color aXOld( pOut->GetFillColor() ); 1773 pOut->SetFillColor( Color( COL_GREEN )); 1774 pOut->DrawRect( rTextRect ); 1775 pOut->DrawRect( rImageRect ); 1776 pOut->SetFillColor( aXOld ); 1777 } 1778 #endif 1779 1780 const StyleSettings& rSettings = pOut->GetSettings().GetStyleSettings(); 1781 Color aOldFillColor( pOut->GetFillColor() ); 1782 1783 sal_Bool bSolidTextRect = sal_False; 1784 sal_Bool bSolidImageRect = sal_False; 1785 1786 if( bDropTarget && ( eSelectionMode != NO_SELECTION ) ) 1787 { 1788 pOut->SetFillColor( rSettings.GetHighlightColor() ); 1789 bSolidTextRect = sal_True; 1790 bSolidImageRect = sal_True; 1791 } 1792 else 1793 { 1794 if ( !bSelected || bCursored ) 1795 { 1796 if( !pView->HasFontFillColor() ) 1797 pOut->SetFillColor( pOut->GetBackground().GetColor() ); 1798 else 1799 { 1800 const Color& rFillColor = pView->GetFont().GetFillColor(); 1801 pOut->SetFillColor( rFillColor ); 1802 if( rFillColor != aTransparent ) 1803 bSolidTextRect = sal_True; 1804 } 1805 } 1806 } 1807 1808 // Textrechteck zeichnen 1809 if( !bSolidTextRect ) 1810 { 1811 if( !bIsBackgroundPainted ) 1812 pOut->Erase( rTextRect ); 1813 } 1814 else 1815 { 1816 Color aOldLineColor; 1817 if( bCursored ) 1818 { 1819 aOldLineColor = pOut->GetLineColor(); 1820 pOut->SetLineColor( Color( COL_GRAY ) ); 1821 } 1822 pOut->DrawRect( rTextRect ); 1823 if( bCursored ) 1824 pOut->SetLineColor( aOldLineColor ); 1825 } 1826 1827 // Bildrechteck zeichnen 1828 if( !bSolidImageRect ) 1829 { 1830 if( !bIsBackgroundPainted ) 1831 pOut->Erase( rImageRect ); 1832 } 1833 // die Emphasis des Images muss von der abgeleiteten Klasse gezeichnet werden 1834 // (in der virtuellen Funktion DrawEntryImage) 1835 // else 1836 // pOut->DrawRect( rImageRect ); 1837 1838 pOut->SetFillColor( aOldFillColor ); 1839 } 1840 1841 1842 void SvxIconChoiceCtrl_Impl::PaintItem( const Rectangle& rRect, 1843 IcnViewFieldType eItem, SvxIconChoiceCtrlEntry* pEntry, sal_uInt16 nPaintFlags, 1844 OutputDevice* pOut, const String* pStr, ::vcl::ControlLayoutData* _pLayoutData ) 1845 { 1846 if( eItem == IcnViewFieldTypeText ) 1847 { 1848 String aText; 1849 if( !pStr ) 1850 aText = pView->GetEntryText( pEntry, sal_False ); 1851 else 1852 aText = *pStr; 1853 1854 if ( _pLayoutData ) 1855 { 1856 pOut->DrawText( rRect, aText, nCurTextDrawFlags, 1857 &_pLayoutData->m_aUnicodeBoundRects, &_pLayoutData->m_aDisplayText ); 1858 } 1859 else 1860 { 1861 Color aOldFontColor = pOut->GetTextColor(); 1862 if ( pView->AutoFontColor() ) 1863 { 1864 Color aBkgColor( pOut->GetBackground().GetColor() ); 1865 Color aFontColor; 1866 sal_uInt16 nColor = ( aBkgColor.GetRed() + aBkgColor.GetGreen() + aBkgColor.GetBlue() ) / 3; 1867 if ( nColor > 127 ) 1868 aFontColor.SetColor ( COL_BLACK ); 1869 else 1870 aFontColor.SetColor( COL_WHITE ); 1871 pOut->SetTextColor( aFontColor ); 1872 } 1873 1874 pOut->DrawText( rRect, aText, nCurTextDrawFlags ); 1875 1876 if ( pView->AutoFontColor() ) 1877 pOut->SetTextColor( aOldFontColor ); 1878 1879 if( pEntry->IsFocused() ) 1880 { 1881 Rectangle aRect ( CalcFocusRect( (SvxIconChoiceCtrlEntry*)pEntry ) ); 1882 /*pView->*/ShowFocus( aRect ); 1883 DrawFocusRect( pOut ); 1884 } 1885 } 1886 } 1887 else 1888 { 1889 Point aPos( rRect.TopLeft() ); 1890 if( nPaintFlags & PAINTFLAG_HOR_CENTERED ) 1891 aPos.X() += (rRect.GetWidth() - aImageSize.Width() ) / 2; 1892 if( nPaintFlags & PAINTFLAG_VER_CENTERED ) 1893 aPos.Y() += (rRect.GetHeight() - aImageSize.Height() ) / 2; 1894 pView->DrawEntryImage( pEntry, aPos, *pOut ); 1895 } 1896 } 1897 1898 void SvxIconChoiceCtrl_Impl::PaintEntryVirtOutDev( SvxIconChoiceCtrlEntry* pEntry ) 1899 { 1900 #ifdef OV_NO_VIRT_OUTDEV 1901 PaintEntry( pEntry ); 1902 #else 1903 if( !pEntryPaintDev ) 1904 { 1905 pEntryPaintDev = new VirtualDevice( *pView ); 1906 pEntryPaintDev->SetFont( pView->GetFont() ); 1907 pEntryPaintDev->SetLineColor(); 1908 //pEntryPaintDev->SetBackground( pView->GetBackground() ); 1909 } 1910 const Rectangle& rRect = GetEntryBoundRect( pEntry ); 1911 Rectangle aOutRect( GetOutputRect() ); 1912 if( !rRect.IsOver( aOutRect ) ) 1913 return; 1914 Wallpaper aPaper( pView->GetBackground() ); 1915 Rectangle aRect( aPaper.GetRect() ); 1916 1917 // Rechteck verschieben, so dass das Boundrect des Entries im 1918 // VirtOut-Dev bei 0,0 liegt. 1919 aRect.Move( -rRect.Left(), -rRect.Top() ); 1920 aPaper.SetRect( aRect ); 1921 pEntryPaintDev->SetBackground( aPaper ); 1922 pEntryPaintDev->SetFont( pView->GetFont() ); 1923 Rectangle aPix ( pEntryPaintDev->LogicToPixel(aRect) ); 1924 1925 1926 Size aSize( rRect.GetSize() ); 1927 pEntryPaintDev->SetOutputSizePixel( aSize ); 1928 pEntryPaintDev->DrawOutDev( 1929 Point(), aSize, rRect.TopLeft(), aSize, *pView ); 1930 1931 PaintEntry( pEntry, Point(), pEntryPaintDev ); 1932 1933 pView->DrawOutDev( 1934 rRect.TopLeft(), 1935 aSize, 1936 Point(), 1937 aSize, 1938 *pEntryPaintDev ); 1939 #endif 1940 } 1941 1942 1943 void SvxIconChoiceCtrl_Impl::PaintEntry( SvxIconChoiceCtrlEntry* pEntry, const Point& rPos, 1944 OutputDevice* pOut, sal_Bool bIsBackgroundPainted ) 1945 { 1946 if( !pOut ) 1947 pOut = pView; 1948 1949 sal_Bool bSelected = sal_False; 1950 1951 if( eSelectionMode != NO_SELECTION ) 1952 bSelected = pEntry->IsSelected(); 1953 1954 sal_Bool bCursored = pEntry->IsCursored(); 1955 sal_Bool bDropTarget = pEntry->IsDropTarget(); 1956 sal_Bool bNoEmphasis = pEntry->IsBlockingEmphasis(); 1957 1958 Font aTempFont( pOut->GetFont() ); 1959 1960 // AutoFontColor 1961 /* 1962 if ( pView->AutoFontColor() ) 1963 { 1964 aTempFont.SetColor ( aFontColor ); 1965 } 1966 */ 1967 1968 String aEntryText( pView->GetEntryText( pEntry, sal_False ) ); 1969 Rectangle aTextRect( CalcTextRect(pEntry,&rPos,sal_False,&aEntryText)); 1970 Rectangle aBmpRect( CalcBmpRect(pEntry, &rPos ) ); 1971 1972 sal_Bool bShowSelection = 1973 ( ( ( bSelected && !bCursored ) 1974 || bDropTarget 1975 ) 1976 && !bNoEmphasis 1977 && ( eSelectionMode != NO_SELECTION ) 1978 ); 1979 sal_Bool bActiveSelection = ( 0 != ( nWinBits & WB_NOHIDESELECTION ) ) || pView->HasFocus(); 1980 1981 if ( bShowSelection ) 1982 { 1983 const StyleSettings& rSettings = pOut->GetSettings().GetStyleSettings(); 1984 Font aNewFont( aTempFont ); 1985 1986 // bei hart attributierter Font-Fuellcolor muessen wir diese 1987 // hart auf die Highlight-Color setzen 1988 if( pView->HasFontFillColor() ) 1989 { 1990 if( (nWinBits & WB_NOHIDESELECTION) || pView->HasFocus() ) 1991 aNewFont.SetFillColor( rSettings.GetHighlightColor() ); 1992 else 1993 aNewFont.SetFillColor( rSettings.GetDeactiveColor() ); 1994 } 1995 1996 Color aWinCol = rSettings.GetWindowTextColor(); 1997 if ( !bActiveSelection && rSettings.GetFaceColor().IsBright() == aWinCol.IsBright() ) 1998 aNewFont.SetColor( rSettings.GetWindowTextColor() ); 1999 else 2000 aNewFont.SetColor( rSettings.GetHighlightTextColor() ); 2001 2002 pOut->SetFont( aNewFont ); 2003 2004 pOut->SetFillColor( pOut->GetBackground().GetColor() ); 2005 pOut->DrawRect( CalcFocusRect( pEntry ) ); 2006 pOut->SetFillColor( ); 2007 } 2008 2009 sal_Bool bResetClipRegion = sal_False; 2010 if( !pView->IsClipRegion() && (aVerSBar.IsVisible() || aHorSBar.IsVisible()) ) 2011 { 2012 Rectangle aOutputArea( GetOutputRect() ); 2013 if( aOutputArea.IsOver(aTextRect) || aOutputArea.IsOver(aBmpRect) ) 2014 { 2015 pView->SetClipRegion( aOutputArea ); 2016 bResetClipRegion = sal_True; 2017 } 2018 } 2019 2020 #ifdef OV_DRAWBOUNDRECT 2021 { 2022 Color aXOldColor = pOut->GetLineColor(); 2023 pOut->SetLineColor( Color( COL_LIGHTRED ) ); 2024 Rectangle aXRect( pEntry->aRect ); 2025 aXRect.SetPos( rPos ); 2026 pOut->DrawRect( aXRect ); 2027 pOut->SetLineColor( aXOldColor ); 2028 } 2029 #endif 2030 2031 sal_Bool bLargeIconMode = WB_ICON == ( nWinBits & (VIEWMODE_MASK) ); 2032 sal_uInt16 nBmpPaintFlags = PAINTFLAG_VER_CENTERED; 2033 if ( bLargeIconMode ) 2034 nBmpPaintFlags |= PAINTFLAG_HOR_CENTERED; 2035 sal_uInt16 nTextPaintFlags = bLargeIconMode ? PAINTFLAG_HOR_CENTERED : PAINTFLAG_VER_CENTERED; 2036 2037 if( !bNoEmphasis ) 2038 PaintEmphasis(aTextRect,aBmpRect,bSelected,bDropTarget,bCursored,pOut,bIsBackgroundPainted); 2039 2040 if ( bShowSelection ) 2041 pView->DrawSelectionBackground( CalcFocusRect( pEntry ), 2042 bActiveSelection ? 1 : 2 /* highlight */, sal_False /* check */, sal_True /* border */, sal_False /* ext border only */ ); 2043 2044 PaintItem( aBmpRect, IcnViewFieldTypeImage, pEntry, nBmpPaintFlags, pOut ); 2045 2046 PaintItem( aTextRect, IcnViewFieldTypeText, pEntry, 2047 nTextPaintFlags, pOut ); 2048 2049 // Highlight-Frame zeichnen 2050 if( pEntry == pCurHighlightFrame && !bNoEmphasis ) 2051 DrawHighlightFrame( pOut, CalcFocusRect( pEntry ), sal_False ); 2052 2053 pOut->SetFont( aTempFont ); 2054 if( bResetClipRegion ) 2055 pView->SetClipRegion(); 2056 } 2057 2058 void SvxIconChoiceCtrl_Impl::SetEntryPos( SvxIconChoiceCtrlEntry* pEntry, const Point& rPos, 2059 sal_Bool bAdjustAtGrid, sal_Bool bCheckScrollBars, sal_Bool bKeepGridMap ) 2060 { 2061 ShowCursor( sal_False ); 2062 Rectangle aBoundRect( GetEntryBoundRect( pEntry )); 2063 pView->Invalidate( aBoundRect ); 2064 ToTop( pEntry ); 2065 if( !IsAutoArrange() ) 2066 { 2067 sal_Bool bAdjustVirtSize = sal_False; 2068 if( rPos != aBoundRect.TopLeft() ) 2069 { 2070 Point aGridOffs( 2071 pEntry->aGridRect.TopLeft() - pEntry->aRect.TopLeft() ); 2072 pImpCursor->Clear(); 2073 if( !bKeepGridMap ) 2074 pGridMap->Clear(); 2075 aBoundRect.SetPos( rPos ); 2076 pEntry->aRect = aBoundRect; 2077 pEntry->aGridRect.SetPos( rPos + aGridOffs ); 2078 bAdjustVirtSize = sal_True; 2079 } 2080 if( bAdjustAtGrid ) 2081 { 2082 if( bAdjustVirtSize ) 2083 { 2084 // Durch das Ausrichten des (ggf. gerade neu positionierten) Eintrags, 2085 // kann er wieder komplett 2086 // in den sichtbaren Bereich rutschen, so dass u.U. doch keine Scrollbar 2087 // eingeblendet werden muss. Um deshalb ein 'Aufblitzen' der 2088 // Scrollbar(s) zu vermeiden, wird zum Aufplustern der virtuellen 2089 // Ausgabegroesse bereits das ausgerichtete Boundrect des 2090 // Eintrags genommen. Die virtuelle Groesse muss angepasst werden, 2091 // da AdjustEntryAtGrid von ihr abhaengt. 2092 const Rectangle& rBoundRect = GetEntryBoundRect( pEntry ); 2093 Rectangle aCenterRect( CalcBmpRect( pEntry, 0 )); 2094 Point aNewPos( AdjustAtGrid( aCenterRect, rBoundRect ) ); 2095 Rectangle aNewBoundRect( aNewPos, pEntry->aRect.GetSize()); 2096 AdjustVirtSize( aNewBoundRect ); 2097 bAdjustVirtSize = sal_False; 2098 } 2099 AdjustEntryAtGrid( pEntry ); 2100 ToTop( pEntry ); 2101 } 2102 if( bAdjustVirtSize ) 2103 AdjustVirtSize( pEntry->aRect ); 2104 2105 if( bCheckScrollBars && bUpdateMode ) 2106 CheckScrollBars(); 2107 2108 pView->Invalidate( pEntry->aRect ); 2109 pGridMap->OccupyGrids( pEntry ); 2110 } 2111 else 2112 { 2113 SvxIconChoiceCtrlEntry* pPrev = FindEntryPredecessor( pEntry, rPos ); 2114 SetEntryPredecessor( pEntry, pPrev ); 2115 aAutoArrangeTimer.Start(); 2116 } 2117 ShowCursor( sal_True ); 2118 } 2119 2120 void SvxIconChoiceCtrl_Impl::SetNoSelection() 2121 { 2122 // rekursive Aufrufe ueber SelectEntry abblocken 2123 if( !(nFlags & F_CLEARING_SELECTION )) 2124 { 2125 nFlags |= F_CLEARING_SELECTION; 2126 DeselectAllBut( 0, sal_True ); 2127 nFlags &= ~F_CLEARING_SELECTION; 2128 } 2129 } 2130 2131 SvxIconChoiceCtrlEntry* SvxIconChoiceCtrl_Impl::GetEntry( const Point& rDocPos, sal_Bool bHit ) 2132 { 2133 CheckBoundingRects(); 2134 // Z-Order-Liste vom Ende her absuchen 2135 sal_uLong nCount = pZOrderList->Count(); 2136 while( nCount ) 2137 { 2138 nCount--; 2139 SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)(pZOrderList->GetObject(nCount)); 2140 if( pEntry->aRect.IsInside( rDocPos ) ) 2141 { 2142 if( bHit ) 2143 { 2144 Rectangle aRect = CalcBmpRect( pEntry ); 2145 aRect.Top() -= 3; 2146 aRect.Bottom() += 3; 2147 aRect.Left() -= 3; 2148 aRect.Right() += 3; 2149 if( aRect.IsInside( rDocPos ) ) 2150 return pEntry; 2151 aRect = CalcTextRect( pEntry ); 2152 if( aRect.IsInside( rDocPos ) ) 2153 return pEntry; 2154 } 2155 else 2156 return pEntry; 2157 } 2158 } 2159 return 0; 2160 } 2161 2162 SvxIconChoiceCtrlEntry* SvxIconChoiceCtrl_Impl::GetNextEntry( const Point& rDocPos, SvxIconChoiceCtrlEntry* pCurEntry ) 2163 { 2164 CheckBoundingRects(); 2165 SvxIconChoiceCtrlEntry* pTarget = 0; 2166 const sal_uLong nStartPos = pZOrderList->GetPos( (void*)pCurEntry ); 2167 if( nStartPos != LIST_ENTRY_NOTFOUND ) 2168 { 2169 const sal_uLong nCount = pZOrderList->Count(); 2170 for( sal_uLong nCur = nStartPos+1; nCur < nCount; nCur++ ) 2171 { 2172 SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)(pZOrderList->GetObject(nCur)); 2173 if( pEntry->aRect.IsInside( rDocPos ) ) 2174 { 2175 pTarget = pEntry; 2176 break; 2177 } 2178 } 2179 } 2180 return pTarget; 2181 } 2182 2183 SvxIconChoiceCtrlEntry* SvxIconChoiceCtrl_Impl::GetPrevEntry( const Point& rDocPos, SvxIconChoiceCtrlEntry* pCurEntry ) 2184 { 2185 CheckBoundingRects(); 2186 SvxIconChoiceCtrlEntry* pTarget = 0; 2187 sal_uLong nStartPos = pZOrderList->GetPos( (void*)pCurEntry ); 2188 if( nStartPos != LIST_ENTRY_NOTFOUND && nStartPos != 0 ) 2189 { 2190 nStartPos--; 2191 do 2192 { 2193 SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)(pZOrderList->GetObject(nStartPos)); 2194 if( pEntry->aRect.IsInside( rDocPos ) ) 2195 { 2196 pTarget = pEntry; 2197 break; 2198 } 2199 } while( nStartPos > 0 ); 2200 } 2201 return pTarget; 2202 } 2203 2204 Point SvxIconChoiceCtrl_Impl::GetEntryPos( SvxIconChoiceCtrlEntry* pEntry ) 2205 { 2206 return pEntry->aRect.TopLeft(); 2207 } 2208 2209 void SvxIconChoiceCtrl_Impl::MakeEntryVisible( SvxIconChoiceCtrlEntry* pEntry, sal_Bool bBound ) 2210 { 2211 if ( bBound ) 2212 { 2213 const Rectangle& rRect = GetEntryBoundRect( pEntry ); 2214 MakeVisible( rRect ); 2215 } 2216 else 2217 { 2218 Rectangle aRect = CalcBmpRect( pEntry ); 2219 aRect.Union( CalcTextRect( pEntry ) ); 2220 aRect.Top() += TBOFFS_BOUND; 2221 aRect.Bottom() += TBOFFS_BOUND; 2222 aRect.Left() += LROFFS_BOUND; 2223 aRect.Right() += LROFFS_BOUND; 2224 MakeVisible( aRect ); 2225 } 2226 } 2227 2228 const Rectangle& SvxIconChoiceCtrl_Impl::GetEntryBoundRect( SvxIconChoiceCtrlEntry* pEntry ) 2229 { 2230 if( !IsBoundingRectValid( pEntry->aRect )) 2231 FindBoundingRect( pEntry ); 2232 return pEntry->aRect; 2233 } 2234 2235 Rectangle SvxIconChoiceCtrl_Impl::CalcBmpRect( SvxIconChoiceCtrlEntry* pEntry, const Point* pPos ) 2236 { 2237 Rectangle aBound = GetEntryBoundRect( pEntry ); 2238 if( pPos ) 2239 aBound.SetPos( *pPos ); 2240 Point aPos( aBound.TopLeft() ); 2241 2242 switch( nWinBits & (VIEWMODE_MASK) ) 2243 { 2244 case WB_ICON: 2245 { 2246 aPos.X() += ( aBound.GetWidth() - aImageSize.Width() ) / 2; 2247 return Rectangle( aPos, aImageSize ); 2248 } 2249 2250 case WB_SMALLICON: 2251 case WB_DETAILS: 2252 aPos.Y() += ( aBound.GetHeight() - aImageSize.Height() ) / 2; 2253 //todo: hor. Abstand zum BoundRect? 2254 return Rectangle( aPos, aImageSize ); 2255 2256 default: 2257 DBG_ERROR("IconView: Viewmode not set"); 2258 return aBound; 2259 } 2260 } 2261 2262 Rectangle SvxIconChoiceCtrl_Impl::CalcTextRect( SvxIconChoiceCtrlEntry* pEntry, 2263 const Point* pEntryPos, sal_Bool bEdit, const String* pStr ) 2264 { 2265 String aEntryText; 2266 if( !pStr ) 2267 aEntryText = pView->GetEntryText( pEntry, bEdit ); 2268 else 2269 aEntryText = *pStr; 2270 2271 const Rectangle aMaxTextRect( CalcMaxTextRect( pEntry ) ); 2272 Rectangle aBound( GetEntryBoundRect( pEntry ) ); 2273 if( pEntryPos ) 2274 aBound.SetPos( *pEntryPos ); 2275 2276 Rectangle aTextRect( aMaxTextRect ); 2277 if( !bEdit ) 2278 aTextRect = pView->GetTextRect( aTextRect, aEntryText, nCurTextDrawFlags ); 2279 2280 Size aTextSize( aTextRect.GetSize() ); 2281 2282 Point aPos( aBound.TopLeft() ); 2283 long nBoundWidth = aBound.GetWidth(); 2284 long nBoundHeight = aBound.GetHeight(); 2285 2286 switch( nWinBits & (VIEWMODE_MASK) ) 2287 { 2288 case WB_ICON: 2289 aPos.Y() += aImageSize.Height(); 2290 aPos.Y() += VER_DIST_BMP_STRING; 2291 // beim Editieren etwas mehr Platz 2292 if( bEdit ) 2293 { 2294 // 20% rauf 2295 long nMinWidth = (( (aImageSize.Width()*10) / 100 ) * 2 ) + 2296 aImageSize.Width(); 2297 if( nMinWidth > nBoundWidth ) 2298 nMinWidth = nBoundWidth; 2299 2300 if( aTextSize.Width() < nMinWidth ) 2301 aTextSize.Width() = nMinWidth; 2302 2303 // beim Editieren ist Ueberlappung nach unten erlaubt 2304 Size aOptSize = aMaxTextRect.GetSize(); 2305 if( aOptSize.Height() > aTextSize.Height() ) 2306 aTextSize.Height() = aOptSize.Height(); 2307 } 2308 aPos.X() += (nBoundWidth - aTextSize.Width()) / 2; 2309 break; 2310 2311 case WB_SMALLICON: 2312 case WB_DETAILS: 2313 aPos.X() += aImageSize.Width(); 2314 aPos.X() += HOR_DIST_BMP_STRING; 2315 aPos.Y() += (nBoundHeight - aTextSize.Height()) / 2; 2316 break; 2317 } 2318 return Rectangle( aPos, aTextSize ); 2319 } 2320 2321 2322 long SvxIconChoiceCtrl_Impl::CalcBoundingWidth( SvxIconChoiceCtrlEntry* pEntry ) const 2323 { 2324 long nStringWidth = GetItemSize( pEntry, IcnViewFieldTypeText ).Width(); 2325 // nStringWidth += 2*LROFFS_TEXT; 2326 long nWidth = 0; 2327 2328 switch( nWinBits & (VIEWMODE_MASK) ) 2329 { 2330 case WB_ICON: 2331 nWidth = Max( nStringWidth, aImageSize.Width() ); 2332 break; 2333 2334 case WB_SMALLICON: 2335 case WB_DETAILS: 2336 nWidth = aImageSize.Width(); 2337 nWidth += HOR_DIST_BMP_STRING; 2338 nWidth += nStringWidth; 2339 break; 2340 } 2341 return nWidth; 2342 } 2343 2344 long SvxIconChoiceCtrl_Impl::CalcBoundingHeight( SvxIconChoiceCtrlEntry* pEntry ) const 2345 { 2346 long nStringHeight = GetItemSize( pEntry, IcnViewFieldTypeText).Height(); 2347 long nHeight = 0; 2348 2349 switch( nWinBits & (VIEWMODE_MASK) ) 2350 { 2351 case WB_ICON: 2352 nHeight = aImageSize.Height(); 2353 nHeight += VER_DIST_BMP_STRING; 2354 nHeight += nStringHeight; 2355 break; 2356 2357 case WB_SMALLICON: 2358 case WB_DETAILS: 2359 nHeight = Max( aImageSize.Height(), nStringHeight ); 2360 break; 2361 } 2362 if( nHeight > nMaxBoundHeight ) 2363 { 2364 ((SvxIconChoiceCtrl_Impl*)this)->nMaxBoundHeight = nHeight; 2365 ((SvxIconChoiceCtrl_Impl*)this)->aHorSBar.SetLineSize( GetScrollBarLineSize() ); 2366 ((SvxIconChoiceCtrl_Impl*)this)->aVerSBar.SetLineSize( GetScrollBarLineSize() ); 2367 } 2368 return nHeight; 2369 } 2370 2371 Size SvxIconChoiceCtrl_Impl::CalcBoundingSize( SvxIconChoiceCtrlEntry* pEntry ) const 2372 { 2373 return Size( CalcBoundingWidth( pEntry ), 2374 CalcBoundingHeight( pEntry ) ); 2375 } 2376 2377 void SvxIconChoiceCtrl_Impl::RecalcAllBoundingRects() 2378 { 2379 nMaxBoundHeight = 0; 2380 pZOrderList->Clear(); 2381 sal_uLong nCount = aEntries.Count(); 2382 sal_uLong nCur; 2383 SvxIconChoiceCtrlEntry* pEntry; 2384 2385 if( !IsAutoArrange() || !pHead ) 2386 { 2387 for( nCur = 0; nCur < nCount; nCur++ ) 2388 { 2389 pEntry = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( nCur ); 2390 FindBoundingRect( pEntry ); 2391 pZOrderList->Insert( pEntry, LIST_APPEND ); 2392 } 2393 } 2394 else 2395 { 2396 nCur = 0; 2397 pEntry = pHead; 2398 while( nCur != nCount ) 2399 { 2400 DBG_ASSERT(pEntry->pflink&&pEntry->pblink,"SvxIconChoiceCtrl_Impl::RecalcAllBoundingRect > Bad link(s)"); 2401 FindBoundingRect( pEntry ); 2402 pZOrderList->Insert( pEntry, pZOrderList->Count() ); 2403 pEntry = pEntry->pflink; 2404 nCur++; 2405 } 2406 } 2407 bBoundRectsDirty = sal_False; 2408 AdjustScrollBars(); 2409 } 2410 2411 void SvxIconChoiceCtrl_Impl::RecalcAllBoundingRectsSmart() 2412 { 2413 nMaxBoundHeight = 0; 2414 pZOrderList->Clear(); 2415 sal_uLong nCur; 2416 SvxIconChoiceCtrlEntry* pEntry; 2417 const sal_uLong nCount = aEntries.Count(); 2418 2419 if( !IsAutoArrange() || !pHead ) 2420 { 2421 for( nCur = 0; nCur < nCount; nCur++ ) 2422 { 2423 pEntry = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( nCur ); 2424 if( IsBoundingRectValid( pEntry->aRect )) 2425 { 2426 Size aBoundSize( pEntry->aRect.GetSize() ); 2427 if( aBoundSize.Height() > nMaxBoundHeight ) 2428 nMaxBoundHeight = aBoundSize.Height(); 2429 } 2430 else 2431 FindBoundingRect( pEntry ); 2432 pZOrderList->Insert( pEntry, LIST_APPEND ); 2433 } 2434 } 2435 else 2436 { 2437 nCur = 0; 2438 pEntry = pHead; 2439 while( nCur != nCount ) 2440 { 2441 DBG_ASSERT(pEntry->pflink&&pEntry->pblink,"SvxIconChoiceCtrl_Impl::RecalcAllBoundingRect > Bad link(s)"); 2442 if( IsBoundingRectValid( pEntry->aRect )) 2443 { 2444 Size aBoundSize( pEntry->aRect.GetSize() ); 2445 if( aBoundSize.Height() > nMaxBoundHeight ) 2446 nMaxBoundHeight = aBoundSize.Height(); 2447 } 2448 else 2449 FindBoundingRect( pEntry ); 2450 pZOrderList->Insert( pEntry, LIST_APPEND ); 2451 pEntry = pEntry->pflink; 2452 nCur++; 2453 } 2454 } 2455 AdjustScrollBars(); 2456 } 2457 2458 void SvxIconChoiceCtrl_Impl::UpdateBoundingRects() 2459 { 2460 const sal_uLong nCount = aEntries.Count(); 2461 for( sal_uLong nCur = 0; nCur < nCount; nCur++ ) 2462 { 2463 SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( nCur ); 2464 GetEntryBoundRect( pEntry ); 2465 } 2466 } 2467 2468 void SvxIconChoiceCtrl_Impl::FindBoundingRect( SvxIconChoiceCtrlEntry* pEntry ) 2469 { 2470 DBG_ASSERT(!pEntry->IsPosLocked(),"Locked entry pos in FindBoundingRect"); 2471 if( pEntry->IsPosLocked() && IsBoundingRectValid( pEntry->aRect) ) 2472 { 2473 AdjustVirtSize( pEntry->aRect ); 2474 return; 2475 } 2476 Size aSize( CalcBoundingSize( pEntry ) ); 2477 Point aPos(pGridMap->GetGridRect(pGridMap->GetUnoccupiedGrid(sal_True)).TopLeft()); 2478 SetBoundingRect_Impl( pEntry, aPos, aSize ); 2479 } 2480 2481 void SvxIconChoiceCtrl_Impl::SetBoundingRect_Impl( SvxIconChoiceCtrlEntry* pEntry, const Point& rPos, 2482 const Size& /*rBoundingSize*/ ) 2483 { 2484 Rectangle aGridRect( rPos, Size(nGridDX, nGridDY) ); 2485 pEntry->aGridRect = aGridRect; 2486 Center( pEntry ); 2487 AdjustVirtSize( pEntry->aRect ); 2488 pGridMap->OccupyGrids( pEntry ); 2489 } 2490 2491 2492 void SvxIconChoiceCtrl_Impl::SetCursor( SvxIconChoiceCtrlEntry* pEntry, sal_Bool bSyncSingleSelection, 2493 sal_Bool bShowFocusAsync ) 2494 { 2495 if( pEntry == pCursor ) 2496 { 2497 if( pCursor && eSelectionMode == SINGLE_SELECTION && bSyncSingleSelection && 2498 !pCursor->IsSelected() ) 2499 SelectEntry( pCursor, sal_True, sal_True ); 2500 return; 2501 } 2502 ShowCursor( sal_False ); 2503 SvxIconChoiceCtrlEntry* pOldCursor = pCursor; 2504 pCursor = pEntry; 2505 if( pOldCursor ) 2506 { 2507 pOldCursor->ClearFlags( ICNVIEW_FLAG_FOCUSED ); 2508 if( eSelectionMode == SINGLE_SELECTION && bSyncSingleSelection ) 2509 SelectEntry( pOldCursor, sal_False, sal_True ); // alten Cursor deselektieren 2510 } 2511 if( pCursor ) 2512 { 2513 ToTop( pCursor ); 2514 pCursor->SetFlags( ICNVIEW_FLAG_FOCUSED ); 2515 if( eSelectionMode == SINGLE_SELECTION && bSyncSingleSelection ) 2516 SelectEntry( pCursor, sal_True, sal_True ); 2517 if( !bShowFocusAsync ) 2518 ShowCursor( sal_True ); 2519 else 2520 { 2521 if( !nUserEventShowCursor ) 2522 nUserEventShowCursor = 2523 Application::PostUserEvent( LINK( this, SvxIconChoiceCtrl_Impl, UserEventHdl), 2524 EVENTID_SHOW_CURSOR ); 2525 } 2526 } 2527 } 2528 2529 2530 void SvxIconChoiceCtrl_Impl::ShowCursor( sal_Bool bShow ) 2531 { 2532 if( !pCursor || !bShow || !pView->HasFocus() ) 2533 { 2534 pView->HideFocus(); 2535 return; 2536 } 2537 Rectangle aRect ( CalcFocusRect( pCursor ) ); 2538 /*pView->*/ShowFocus( aRect ); 2539 } 2540 2541 2542 void SvxIconChoiceCtrl_Impl::HideDDIcon() 2543 { 2544 pView->Update(); 2545 ImpHideDDIcon(); 2546 pDDBufDev = pDDDev; 2547 pDDDev = 0; 2548 } 2549 2550 void SvxIconChoiceCtrl_Impl::ImpHideDDIcon() 2551 { 2552 if( pDDDev ) 2553 { 2554 Size aSize( pDDDev->GetOutputSizePixel() ); 2555 // pView restaurieren 2556 pView->DrawOutDev( aDDLastRectPos, aSize, Point(), aSize, *pDDDev ); 2557 } 2558 } 2559 2560 2561 void SvxIconChoiceCtrl_Impl::ShowDDIcon( SvxIconChoiceCtrlEntry* pRefEntry, const Point& rPosPix ) 2562 { 2563 pView->Update(); 2564 if( pRefEntry != pDDRefEntry ) 2565 { 2566 DELETEZ(pDDDev); 2567 DELETEZ(pDDBufDev); 2568 } 2569 sal_Bool bSelected = pRefEntry->IsSelected(); 2570 pRefEntry->ClearFlags( ICNVIEW_FLAG_SELECTED ); 2571 if( !pDDDev ) 2572 { 2573 if( pDDBufDev ) 2574 { 2575 // nicht bei jedem Move ein Device anlegen, da dies besonders 2576 // auf Remote-Clients zu langsam ist 2577 pDDDev = pDDBufDev; 2578 pDDBufDev = 0; 2579 } 2580 else 2581 { 2582 pDDDev = new VirtualDevice( *pView ); 2583 pDDDev->SetFont( pView->GetFont() ); 2584 } 2585 } 2586 else 2587 { 2588 ImpHideDDIcon(); 2589 } 2590 const Rectangle& rRect = GetEntryBoundRect( pRefEntry ); 2591 pDDDev->SetOutputSizePixel( rRect.GetSize() ); 2592 2593 Point aPos( rPosPix ); 2594 ToDocPos( aPos ); 2595 2596 Size aSize( pDDDev->GetOutputSizePixel() ); 2597 pDDRefEntry = pRefEntry; 2598 aDDLastEntryPos = aPos; 2599 aDDLastRectPos = aPos; 2600 2601 // Hintergrund sichern 2602 pDDDev->DrawOutDev( Point(), aSize, aPos, aSize, *pView ); 2603 // Icon in pView malen 2604 pRefEntry->SetFlags( ICNVIEW_FLAG_BLOCK_EMPHASIS ); 2605 PaintEntry( pRefEntry, aPos ); 2606 pRefEntry->ClearFlags( ICNVIEW_FLAG_BLOCK_EMPHASIS ); 2607 if( bSelected ) 2608 pRefEntry->SetFlags( ICNVIEW_FLAG_SELECTED ); 2609 } 2610 2611 void SvxIconChoiceCtrl_Impl::HideShowDDIcon( SvxIconChoiceCtrlEntry* pRefEntry, const Point& rPosPix ) 2612 { 2613 /* In Notfaellen folgenden flackernden Code aktivieren: 2614 2615 HideDDIcon(); 2616 ShowDDIcon( pRefEntry, rPosPix ); 2617 return; 2618 */ 2619 if( !pDDDev ) 2620 { 2621 ShowDDIcon( pRefEntry, rPosPix ); 2622 return; 2623 } 2624 2625 if( pRefEntry != pDDRefEntry ) 2626 { 2627 HideDDIcon(); 2628 ShowDDIcon( pRefEntry, rPosPix ); 2629 return; 2630 } 2631 2632 Point aEmptyPoint; 2633 2634 Point aCurEntryPos( rPosPix ); 2635 ToDocPos( aCurEntryPos ); 2636 2637 const Rectangle& rRect = GetEntryBoundRect( pRefEntry ); 2638 Size aEntrySize( rRect.GetSize() ); 2639 Rectangle aPrevEntryRect( aDDLastEntryPos, aEntrySize ); 2640 Rectangle aCurEntryRect( aCurEntryPos, aEntrySize ); 2641 2642 if( !aPrevEntryRect.IsOver( aCurEntryRect ) ) 2643 { 2644 HideDDIcon(); 2645 ShowDDIcon( pRefEntry, rPosPix ); 2646 return; 2647 } 2648 2649 // Ueberlappung des neuen und alten D&D-Pointers! 2650 2651 Rectangle aFullRect( aPrevEntryRect.Union( aCurEntryRect ) ); 2652 if( !pDDTempDev ) 2653 { 2654 pDDTempDev = new VirtualDevice( *pView ); 2655 pDDTempDev->SetFont( pView->GetFont() ); 2656 } 2657 2658 Size aFullSize( aFullRect.GetSize() ); 2659 Point aFullPos( aFullRect.TopLeft() ); 2660 2661 pDDTempDev->SetOutputSizePixel( aFullSize ); 2662 2663 // Hintergrund (mit dem alten D&D-Pointer!) sichern 2664 pDDTempDev->DrawOutDev( aEmptyPoint, aFullSize, aFullPos, aFullSize, *pView ); 2665 // den alten Buffer in den neuen Buffer pasten 2666 aDDLastRectPos = aDDLastRectPos - aFullPos; 2667 2668 pDDTempDev->DrawOutDev( 2669 aDDLastRectPos, 2670 pDDDev->GetOutputSizePixel(), 2671 aEmptyPoint, 2672 pDDDev->GetOutputSizePixel(), 2673 *pDDDev ); 2674 2675 // Swap 2676 VirtualDevice* pTemp = pDDDev; 2677 pDDDev = pDDTempDev; 2678 pDDTempDev = pTemp; 2679 2680 // in den restaurierten Hintergrund den neuen D&D-Pointer zeichnen 2681 pDDTempDev->SetOutputSizePixel( pDDDev->GetOutputSizePixel() ); 2682 pDDTempDev->DrawOutDev( 2683 aEmptyPoint, aFullSize, aEmptyPoint, aFullSize, *pDDDev ); 2684 Point aRelPos = aCurEntryPos - aFullPos; 2685 pRefEntry->SetFlags( ICNVIEW_FLAG_BLOCK_EMPHASIS ); 2686 PaintEntry( pRefEntry, aRelPos, pDDTempDev ); 2687 pRefEntry->ClearFlags( ICNVIEW_FLAG_BLOCK_EMPHASIS ); 2688 2689 aDDLastRectPos = aFullPos; 2690 aDDLastEntryPos = aCurEntryPos; 2691 2692 pView->DrawOutDev( 2693 aDDLastRectPos, 2694 pDDDev->GetOutputSizePixel(), 2695 aEmptyPoint, 2696 pDDDev->GetOutputSizePixel(), 2697 *pDDTempDev ); 2698 } 2699 2700 void SvxIconChoiceCtrl_Impl::InvalidateBoundingRect( SvxIconChoiceCtrlEntry* pEntry ) 2701 { 2702 InvalidateBoundingRect( pEntry->aRect ); 2703 } 2704 2705 2706 sal_Bool SvxIconChoiceCtrl_Impl::HandleScrollCommand( const CommandEvent& rCmd ) 2707 { 2708 Rectangle aDocRect( GetDocumentRect() ); 2709 Rectangle aVisRect( GetVisibleRect() ); 2710 if( aVisRect.IsInside( aDocRect )) 2711 return sal_False; 2712 Size aDocSize( aDocRect.GetSize() ); 2713 Size aVisSize( aVisRect.GetSize() ); 2714 sal_Bool bHor = aDocSize.Width() > aVisSize.Width(); 2715 sal_Bool bVer = aDocSize.Height() > aVisSize.Height(); 2716 2717 long nScrollDX = 0, nScrollDY = 0; 2718 2719 switch( rCmd.GetCommand() ) 2720 { 2721 case COMMAND_STARTAUTOSCROLL: 2722 { 2723 pView->EndTracking(); 2724 sal_uInt16 nScrollFlags = 0; 2725 if( bHor ) 2726 nScrollFlags |= AUTOSCROLL_HORZ; 2727 if( bVer ) 2728 nScrollFlags |= AUTOSCROLL_VERT; 2729 if( nScrollFlags ) 2730 { 2731 pView->StartAutoScroll( nScrollFlags ); 2732 return sal_True; 2733 } 2734 } 2735 break; 2736 2737 case COMMAND_WHEEL: 2738 { 2739 const CommandWheelData* pData = rCmd.GetWheelData(); 2740 if( pData && (COMMAND_WHEEL_SCROLL == pData->GetMode()) && !pData->IsHorz() ) 2741 { 2742 sal_uLong nScrollLines = pData->GetScrollLines(); 2743 if( nScrollLines == COMMAND_WHEEL_PAGESCROLL ) 2744 { 2745 nScrollDY = GetScrollBarPageSize( aVisSize.Width() ); 2746 if( pData->GetDelta() < 0 ) 2747 nScrollDY *= -1; 2748 } 2749 else 2750 { 2751 nScrollDY = pData->GetNotchDelta() * (long)nScrollLines; 2752 nScrollDY *= GetScrollBarLineSize(); 2753 } 2754 } 2755 } 2756 break; 2757 2758 case COMMAND_AUTOSCROLL: 2759 { 2760 const CommandScrollData* pData = rCmd.GetAutoScrollData(); 2761 if( pData ) 2762 { 2763 nScrollDX = pData->GetDeltaX() * GetScrollBarLineSize(); 2764 nScrollDY = pData->GetDeltaY() * GetScrollBarLineSize(); 2765 } 2766 } 2767 break; 2768 } 2769 2770 if( nScrollDX || nScrollDY ) 2771 { 2772 aVisRect.Top() -= nScrollDY; 2773 aVisRect.Bottom() -= nScrollDY; 2774 aVisRect.Left() -= nScrollDX; 2775 aVisRect.Right() -= nScrollDX; 2776 MakeVisible( aVisRect ); 2777 return sal_True; 2778 } 2779 return sal_False; 2780 } 2781 2782 2783 void SvxIconChoiceCtrl_Impl::Command( const CommandEvent& rCEvt ) 2784 { 2785 // Rollmaus-Event? 2786 if( (rCEvt.GetCommand() == COMMAND_WHEEL) || 2787 (rCEvt.GetCommand() == COMMAND_STARTAUTOSCROLL) || 2788 (rCEvt.GetCommand() == COMMAND_AUTOSCROLL) ) 2789 { 2790 #if 1 2791 if( HandleScrollCommand( rCEvt ) ) 2792 return; 2793 #else 2794 ScrollBar* pHor = aHorSBar.IsVisible() ? &aHorSBar : 0; 2795 ScrollBar* pVer = aVerSBar.IsVisible() ? &aVerSBar : 0; 2796 if( pView->HandleScrollCommand( rCEvt, pHor, pVer ) ) 2797 return; 2798 #endif 2799 } 2800 } 2801 2802 void SvxIconChoiceCtrl_Impl::ToTop( SvxIconChoiceCtrlEntry* pEntry ) 2803 { 2804 if( pZOrderList->GetObject( pZOrderList->Count() - 1 ) != pEntry ) 2805 { 2806 sal_uLong nPos = pZOrderList->GetPos( (void*)pEntry ); 2807 pZOrderList->Remove( nPos ); 2808 pZOrderList->Insert( pEntry, LIST_APPEND ); 2809 } 2810 } 2811 2812 void SvxIconChoiceCtrl_Impl::ClipAtVirtOutRect( Rectangle& rRect ) const 2813 { 2814 if( rRect.Bottom() >= aVirtOutputSize.Height() ) 2815 rRect.Bottom() = aVirtOutputSize.Height() - 1; 2816 if( rRect.Right() >= aVirtOutputSize.Width() ) 2817 rRect.Right() = aVirtOutputSize.Width() - 1; 2818 if( rRect.Top() < 0 ) 2819 rRect.Top() = 0; 2820 if( rRect.Left() < 0 ) 2821 rRect.Left() = 0; 2822 } 2823 2824 // rRect: Bereich des Dokumentes (in Dokumentkoordinaten), der 2825 // sichtbar gemacht werden soll. 2826 // bScrBar == sal_True: Das Rect wurde aufgrund eines ScrollBar-Events berechnet 2827 2828 void SvxIconChoiceCtrl_Impl::MakeVisible( const Rectangle& rRect, sal_Bool bScrBar, 2829 sal_Bool bCallRectChangedHdl ) 2830 { 2831 Rectangle aVirtRect( rRect ); 2832 ClipAtVirtOutRect( aVirtRect ); 2833 Point aOrigin( pView->GetMapMode().GetOrigin() ); 2834 // in Dokumentkoordinate umwandeln 2835 aOrigin *= -1; 2836 Rectangle aOutputArea( GetOutputRect() ); 2837 if( aOutputArea.IsInside( aVirtRect ) ) 2838 return; // ist schon sichtbar 2839 2840 long nDy; 2841 if( aVirtRect.Top() < aOutputArea.Top() ) 2842 { 2843 // nach oben scrollen (nDy < 0) 2844 nDy = aVirtRect.Top() - aOutputArea.Top(); 2845 } 2846 else if( aVirtRect.Bottom() > aOutputArea.Bottom() ) 2847 { 2848 // nach unten scrollen (nDy > 0) 2849 nDy = aVirtRect.Bottom() - aOutputArea.Bottom(); 2850 } 2851 else 2852 nDy = 0; 2853 2854 long nDx; 2855 if( aVirtRect.Left() < aOutputArea.Left() ) 2856 { 2857 // nach links scrollen (nDx < 0) 2858 nDx = aVirtRect.Left() - aOutputArea.Left(); 2859 } 2860 else if( aVirtRect.Right() > aOutputArea.Right() ) 2861 { 2862 // nach rechts scrollen (nDx > 0) 2863 nDx = aVirtRect.Right() - aOutputArea.Right(); 2864 } 2865 else 2866 nDx = 0; 2867 2868 aOrigin.X() += nDx; 2869 aOrigin.Y() += nDy; 2870 aOutputArea.SetPos( aOrigin ); 2871 if( GetUpdateMode() ) 2872 { 2873 HideDDIcon(); 2874 pView->Update(); 2875 ShowCursor( sal_False ); 2876 } 2877 2878 // Origin fuer SV invertieren (damit wir in 2879 // Dokumentkoordinaten scrollen/painten koennen) 2880 aOrigin *= -1; 2881 SetOrigin( aOrigin ); 2882 2883 sal_Bool bScrollable = pView->GetBackground().IsScrollable(); 2884 if( pView->HasBackground() && !bScrollable ) 2885 { 2886 Rectangle aRect( GetOutputRect()); 2887 Wallpaper aPaper( pView->GetBackground() ); 2888 aPaper.SetRect( aRect ); 2889 pView->SetBackground( aPaper ); 2890 } 2891 2892 if( bScrollable && GetUpdateMode() ) 2893 { 2894 // in umgekehrte Richtung scrollen! 2895 pView->Control::Scroll( -nDx, -nDy, aOutputArea, 2896 SCROLL_NOCHILDREN | SCROLL_USECLIPREGION | SCROLL_CLIP ); 2897 } 2898 else 2899 pView->Invalidate(INVALIDATE_NOCHILDREN); 2900 2901 if( aHorSBar.IsVisible() || aVerSBar.IsVisible() ) 2902 { 2903 if( !bScrBar ) 2904 { 2905 aOrigin *= -1; 2906 // Thumbs korrigieren 2907 if(aHorSBar.IsVisible() && aHorSBar.GetThumbPos() != aOrigin.X()) 2908 aHorSBar.SetThumbPos( aOrigin.X() ); 2909 if(aVerSBar.IsVisible() && aVerSBar.GetThumbPos() != aOrigin.Y()) 2910 aVerSBar.SetThumbPos( aOrigin.Y() ); 2911 } 2912 } 2913 2914 if( GetUpdateMode() ) 2915 ShowCursor( sal_True ); 2916 2917 // pruefen, ob ScrollBars noch benoetigt werden 2918 CheckScrollBars(); 2919 if( bScrollable && GetUpdateMode() ) 2920 pView->Update(); 2921 2922 // kann der angeforderte Bereich nicht komplett sichtbar gemacht werden, 2923 // wird auf jeden Fall der Vis-Rect-Changed-Handler gerufen. Eintreten kann der 2924 // Fall z.B. wenn nur wenige Pixel des unteren Randes nicht sichtbar sind, 2925 // eine ScrollBar aber eine groessere Line-Size eingestellt hat. 2926 if( bCallRectChangedHdl || GetOutputRect() != rRect ) 2927 VisRectChanged(); 2928 } 2929 2930 2931 SvxIconChoiceCtrlEntry* SvxIconChoiceCtrl_Impl::FindNewCursor() 2932 { 2933 SvxIconChoiceCtrlEntry* pNewCursor; 2934 if( pCursor ) 2935 { 2936 pNewCursor = pImpCursor->GoLeftRight( pCursor, sal_False ); 2937 if( !pNewCursor ) 2938 { 2939 pNewCursor = pImpCursor->GoLeftRight( pCursor, sal_True ); 2940 if( !pNewCursor ) 2941 { 2942 pNewCursor = pImpCursor->GoUpDown( pCursor, sal_False ); 2943 if( !pNewCursor ) 2944 pNewCursor = pImpCursor->GoUpDown( pCursor, sal_True ); 2945 } 2946 } 2947 } 2948 else 2949 pNewCursor = (SvxIconChoiceCtrlEntry*)aEntries.First(); 2950 DBG_ASSERT(!pNewCursor|| (pCursor&&pCursor!=pNewCursor),"FindNewCursor failed"); 2951 return pNewCursor; 2952 } 2953 2954 sal_uLong SvxIconChoiceCtrl_Impl::GetSelectionCount() const 2955 { 2956 if( (nWinBits & WB_HIGHLIGHTFRAME) && pCurHighlightFrame ) 2957 return 1; 2958 return nSelectionCount; 2959 } 2960 2961 void SvxIconChoiceCtrl_Impl::ToggleSelection( SvxIconChoiceCtrlEntry* pEntry ) 2962 { 2963 sal_Bool bSel; 2964 if( pEntry->IsSelected() ) 2965 bSel = sal_False; 2966 else 2967 bSel = sal_True; 2968 SelectEntry( pEntry, bSel, sal_True, sal_True ); 2969 } 2970 2971 void SvxIconChoiceCtrl_Impl::DeselectAllBut( SvxIconChoiceCtrlEntry* pThisEntryNot, 2972 sal_Bool bPaintSync ) 2973 { 2974 ClearSelectedRectList(); 2975 // 2976 // !!!!!!! Todo: Evtl. Z-Orderlist abarbeiten !!!!!!! 2977 // 2978 sal_uLong nCount = aEntries.Count(); 2979 for( sal_uLong nCur = 0; nCur < nCount; nCur++ ) 2980 { 2981 SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( nCur ); 2982 if( pEntry != pThisEntryNot && pEntry->IsSelected() ) 2983 SelectEntry( pEntry, sal_False, sal_True, sal_True, bPaintSync ); 2984 } 2985 pAnchor = 0; 2986 nFlags &= (~F_ADD_MODE); 2987 } 2988 2989 Size SvxIconChoiceCtrl_Impl::GetMinGrid() const 2990 { 2991 Size aMinSize( aImageSize ); 2992 aMinSize.Width() += 2 * LROFFS_BOUND; 2993 aMinSize.Height() += TBOFFS_BOUND; // PB: einmal Offset reicht (FileDlg) 2994 String aStrDummy( RTL_CONSTASCII_USTRINGPARAM( "XXX" ) ); 2995 Size aTextSize( pView->GetTextWidth( aStrDummy ), pView->GetTextHeight() ); 2996 if( nWinBits & WB_ICON ) 2997 { 2998 aMinSize.Height() += VER_DIST_BMP_STRING; 2999 aMinSize.Height() += aTextSize.Height(); 3000 } 3001 else 3002 { 3003 aMinSize.Width() += HOR_DIST_BMP_STRING; 3004 aMinSize.Width() += aTextSize.Width(); 3005 } 3006 return aMinSize; 3007 } 3008 3009 void SvxIconChoiceCtrl_Impl::SetGrid( const Size& rSize ) 3010 { 3011 Size aSize( rSize ); 3012 Size aMinSize( GetMinGrid() ); 3013 if( aSize.Width() < aMinSize.Width() ) 3014 aSize.Width() = aMinSize.Width(); 3015 if( aSize.Height() < aMinSize.Height() ) 3016 aSize.Height() = aMinSize.Height(); 3017 3018 nGridDX = aSize.Width(); 3019 // HACK(Detail-Modus ist noch nicht vollstaendig implementiert!) 3020 // dieses Workaround bringts mit einer Spalte zum Fliegen 3021 if( nWinBits & WB_DETAILS ) 3022 { 3023 const SvxIconChoiceCtrlColumnInfo* pCol = GetColumn( 0 ); 3024 if( pCol ) 3025 ((SvxIconChoiceCtrlColumnInfo*)pCol)->SetWidth( nGridDX ); 3026 } 3027 nGridDY = aSize.Height(); 3028 SetDefaultTextSize(); 3029 } 3030 3031 // berechnet die maximale Groesse, die das Textrechteck innerhalb des 3032 // umschliessenden Rechtecks einnehmen kann. Im Modus WB_ICON und 3033 // IcnShowTextFull wird Bottom auf LONG_MAX gesetzt 3034 3035 Rectangle SvxIconChoiceCtrl_Impl::CalcMaxTextRect( const SvxIconChoiceCtrlEntry* pEntry ) const 3036 { 3037 Rectangle aBoundRect; 3038 // keine Endlosrekursion! deshalb das Bound-Rect hier nicht berechnen 3039 if( IsBoundingRectValid( pEntry->aRect ) ) 3040 aBoundRect = pEntry->aRect; 3041 else 3042 aBoundRect = pEntry->aGridRect; 3043 3044 Rectangle aBmpRect( ((SvxIconChoiceCtrl_Impl*)this)->CalcBmpRect( 3045 (SvxIconChoiceCtrlEntry*)pEntry ) ); 3046 if( nWinBits & WB_ICON ) 3047 { 3048 aBoundRect.Top() = aBmpRect.Bottom(); 3049 aBoundRect.Top() += VER_DIST_BMP_STRING; 3050 if( aBoundRect.Top() > aBoundRect.Bottom()) 3051 aBoundRect.Top() = aBoundRect.Bottom(); 3052 aBoundRect.Left() += LROFFS_BOUND; 3053 aBoundRect.Left()++; 3054 aBoundRect.Right() -= LROFFS_BOUND; 3055 aBoundRect.Right()--; 3056 if( aBoundRect.Left() > aBoundRect.Right()) 3057 aBoundRect.Left() = aBoundRect.Right(); 3058 if( GetEntryTextModeSmart( pEntry ) == IcnShowTextFull ) 3059 aBoundRect.Bottom() = LONG_MAX; 3060 } 3061 else 3062 { 3063 aBoundRect.Left() = aBmpRect.Right(); 3064 aBoundRect.Left() += HOR_DIST_BMP_STRING; 3065 aBoundRect.Right() -= LROFFS_BOUND; 3066 if( aBoundRect.Left() > aBoundRect.Right() ) 3067 aBoundRect.Left() = aBoundRect.Right(); 3068 long nHeight = aBoundRect.GetSize().Height(); 3069 nHeight = nHeight - aDefaultTextSize.Height(); 3070 nHeight /= 2; 3071 aBoundRect.Top() += nHeight; 3072 aBoundRect.Bottom() -= nHeight; 3073 } 3074 return aBoundRect; 3075 } 3076 3077 void SvxIconChoiceCtrl_Impl::SetDefaultTextSize() 3078 { 3079 long nDY = nGridDY; 3080 nDY -= aImageSize.Height(); 3081 nDY -= VER_DIST_BMP_STRING; 3082 nDY -= 2*TBOFFS_BOUND; 3083 if( nDY <= 0 ) 3084 nDY = 2; 3085 3086 long nDX = nGridDX; 3087 nDX -= 2*LROFFS_BOUND; 3088 nDX -= 2; 3089 if( nDX <= 0 ) 3090 nDX = 2; 3091 3092 String aStrDummy( RTL_CONSTASCII_USTRINGPARAM( "X" ) ); 3093 long nHeight = pView->GetTextHeight(); 3094 if( nDY < nHeight ) 3095 nDY = nHeight; 3096 aDefaultTextSize = Size( nDX, nDY ); 3097 } 3098 3099 3100 void SvxIconChoiceCtrl_Impl::Center( SvxIconChoiceCtrlEntry* pEntry ) const 3101 { 3102 pEntry->aRect = pEntry->aGridRect; 3103 Size aSize( CalcBoundingSize( pEntry ) ); 3104 if( nWinBits & WB_ICON ) 3105 { 3106 // horizontal zentrieren 3107 long nBorder = pEntry->aGridRect.GetWidth() - aSize.Width(); 3108 pEntry->aRect.Left() += nBorder / 2; 3109 pEntry->aRect.Right() -= nBorder / 2; 3110 } 3111 // vertikal zentrieren 3112 pEntry->aRect.Bottom() = pEntry->aRect.Top() + aSize.Height(); 3113 } 3114 3115 3116 // Die Deltas entsprechen Offsets, um die die View auf dem Doc verschoben wird 3117 // links, hoch: Offsets < 0 3118 // rechts, runter: Offsets > 0 3119 void SvxIconChoiceCtrl_Impl::Scroll( long nDeltaX, long nDeltaY, sal_Bool bScrollBar ) 3120 { 3121 const MapMode& rMapMode = pView->GetMapMode(); 3122 Point aOrigin( rMapMode.GetOrigin() ); 3123 // in Dokumentkoordinate umwandeln 3124 aOrigin *= -1; 3125 aOrigin.Y() += nDeltaY; 3126 aOrigin.X() += nDeltaX; 3127 Rectangle aRect( aOrigin, aOutputSize ); 3128 MakeVisible( aRect, bScrollBar ); 3129 } 3130 3131 3132 const Size& SvxIconChoiceCtrl_Impl::GetItemSize( SvxIconChoiceCtrlEntry*, 3133 IcnViewFieldType eItem ) const 3134 { 3135 if( eItem == IcnViewFieldTypeText ) 3136 return aDefaultTextSize; 3137 return aImageSize; 3138 } 3139 3140 Rectangle SvxIconChoiceCtrl_Impl::CalcFocusRect( SvxIconChoiceCtrlEntry* pEntry ) 3141 { 3142 Rectangle aBmpRect( CalcBmpRect( pEntry ) ); 3143 Rectangle aTextRect( CalcTextRect( pEntry ) ); 3144 Rectangle aBoundRect( GetEntryBoundRect( pEntry ) ); 3145 Rectangle aFocusRect( aBoundRect.Left(), aBmpRect.Top() - 1, 3146 aBoundRect.Right() - 4, aTextRect.Bottom() + 1 ); 3147 // Das Fokusrechteck soll nicht den Text beruehren 3148 if( aFocusRect.Left() - 1 >= pEntry->aRect.Left() ) 3149 aFocusRect.Left()--; 3150 if( aFocusRect.Right() + 1 <= pEntry->aRect.Right() ) 3151 aFocusRect.Right()++; 3152 3153 return aFocusRect; 3154 } 3155 3156 // Der 'Hot Spot' sind die inneren 50% der Rechteckflaeche 3157 static Rectangle GetHotSpot( const Rectangle& rRect ) 3158 { 3159 Rectangle aResult( rRect ); 3160 aResult.Justify(); 3161 Size aSize( rRect.GetSize() ); 3162 long nDelta = aSize.Width() / 4; 3163 aResult.Left() += nDelta; 3164 aResult.Right() -= nDelta; 3165 nDelta = aSize.Height() / 4; 3166 aResult.Top() += nDelta; 3167 aResult.Bottom() -= nDelta; 3168 return aResult; 3169 } 3170 3171 void SvxIconChoiceCtrl_Impl::SelectRect( SvxIconChoiceCtrlEntry* pEntry1, SvxIconChoiceCtrlEntry* pEntry2, 3172 sal_Bool bAdd, SvPtrarr* pOtherRects ) 3173 { 3174 DBG_ASSERT(pEntry1 && pEntry2,"SelectEntry: Invalid Entry-Ptr"); 3175 Rectangle aRect( GetEntryBoundRect( pEntry1 ) ); 3176 aRect.Union( GetEntryBoundRect( pEntry2 ) ); 3177 SelectRect( aRect, bAdd, pOtherRects ); 3178 } 3179 3180 void SvxIconChoiceCtrl_Impl::SelectRect( const Rectangle& rRect, sal_Bool bAdd, 3181 SvPtrarr* pOtherRects ) 3182 { 3183 aCurSelectionRect = rRect; 3184 if( !pZOrderList || !pZOrderList->Count() ) 3185 return; 3186 3187 // Flag setzen, damit im Select kein ToTop gerufen wird 3188 sal_Bool bAlreadySelectingRect = nFlags & F_SELECTING_RECT ? sal_True : sal_False; 3189 nFlags |= F_SELECTING_RECT; 3190 3191 CheckBoundingRects(); 3192 pView->Update(); 3193 const sal_uLong nCount = pZOrderList->Count(); 3194 3195 Rectangle aRect( rRect ); 3196 aRect.Justify(); 3197 sal_Bool bCalcOverlap = (bAdd && pOtherRects && pOtherRects->Count()) ? sal_True : sal_False; 3198 3199 sal_Bool bResetClipRegion = sal_False; 3200 if( !pView->IsClipRegion() ) 3201 { 3202 bResetClipRegion = sal_True; 3203 pView->SetClipRegion( GetOutputRect() ); 3204 } 3205 3206 for( sal_uLong nPos = 0; nPos < nCount; nPos++ ) 3207 { 3208 SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)(pZOrderList->GetObject(nPos )); 3209 3210 if( !IsBoundingRectValid( pEntry->aRect )) 3211 FindBoundingRect( pEntry ); 3212 Rectangle aBoundRect( GetHotSpot( pEntry->aRect ) ); 3213 sal_Bool bSelected = pEntry->IsSelected(); 3214 3215 sal_Bool bOverlaps; 3216 if( bCalcOverlap ) 3217 bOverlaps = IsOver( pOtherRects, aBoundRect ); 3218 else 3219 bOverlaps = sal_False; 3220 sal_Bool bOver = aRect.IsOver( aBoundRect ); 3221 3222 if( bOver && !bOverlaps ) 3223 { 3224 // Ist im neuen Selektionsrechteck und in keinem alten 3225 // => selektieren 3226 if( !bSelected ) 3227 SelectEntry( pEntry, sal_True, sal_True, sal_True ); 3228 } 3229 else if( !bAdd ) 3230 { 3231 // ist ausserhalb des Selektionsrechtecks 3232 // => Selektion entfernen 3233 if( bSelected ) 3234 SelectEntry( pEntry, sal_False, sal_True, sal_True ); 3235 } 3236 else if( bAdd && bOverlaps ) 3237 { 3238 // Der Eintrag befindet sich in einem alten (=>Aufspannen 3239 // mehrerer Rechtecke mit Ctrl!) Selektionsrechteck 3240 3241 // Hier ist noch ein Bug! Der Selektionsstatus eines Eintrags 3242 // in einem vorherigen Rechteck, muss restauriert werden, wenn 3243 // er vom aktuellen Selektionsrechteck beruehrt wurde, jetzt aber 3244 // nicht mehr in ihm liegt. Ich gehe hier der Einfachheit halber 3245 // pauschal davon aus, dass die Eintraege in den alten Rechtecken 3246 // alle selektiert sind. Ebenso ist es falsch, die Schnittmenge 3247 // nur zu deselektieren. 3248 // Loesungsmoeglichkeit: Snapshot der Selektion vor dem Auf- 3249 // spannen des Rechtecks merken 3250 if( aBoundRect.IsOver( rRect)) 3251 { 3252 // Schnittmenge zwischen alten Rects & aktuellem Rect desel. 3253 if( bSelected ) 3254 SelectEntry( pEntry, sal_False, sal_True, sal_True ); 3255 } 3256 else 3257 { 3258 // Eintrag eines alten Rects selektieren 3259 if( !bSelected ) 3260 SelectEntry( pEntry, sal_True, sal_True, sal_True ); 3261 } 3262 } 3263 else if( !bOver && bSelected ) 3264 { 3265 // Der Eintrag liegt voellig ausserhalb und wird deshalb desel. 3266 SelectEntry( pEntry, sal_False, sal_True, sal_True ); 3267 } 3268 } 3269 3270 if( !bAlreadySelectingRect ) 3271 nFlags &= ~F_SELECTING_RECT; 3272 3273 pView->Update(); 3274 if( bResetClipRegion ) 3275 pView->SetClipRegion(); 3276 } 3277 3278 void SvxIconChoiceCtrl_Impl::SelectRange( 3279 SvxIconChoiceCtrlEntry* pStart, 3280 SvxIconChoiceCtrlEntry* pEnd, 3281 sal_Bool bAdd ) 3282 { 3283 sal_uLong nFront = GetEntryListPos( pStart ); 3284 sal_uLong nBack = GetEntryListPos( pEnd ); 3285 sal_uLong nFirst = std::min( nFront, nBack ); 3286 sal_uLong nLast = std::max( nFront, nBack ); 3287 sal_uLong i; 3288 SvxIconChoiceCtrlEntry* pEntry; 3289 3290 if ( ! bAdd ) 3291 { 3292 // deselect everything before the first entry if not in 3293 // adding mode 3294 for ( i=0; i<nFirst; i++ ) 3295 { 3296 pEntry = GetEntry( i ); 3297 if( pEntry->IsSelected() ) 3298 SelectEntry( pEntry, sal_False, sal_True, sal_True, sal_True ); 3299 } 3300 } 3301 3302 // select everything between nFirst and nLast 3303 for ( i=nFirst; i<=nLast; i++ ) 3304 { 3305 pEntry = GetEntry( i ); 3306 if( ! pEntry->IsSelected() ) 3307 SelectEntry( pEntry, sal_True, sal_True, sal_True, sal_True ); 3308 } 3309 3310 if ( ! bAdd ) 3311 { 3312 // deselect everything behind the last entry if not in 3313 // adding mode 3314 sal_uLong nEnd = GetEntryCount(); 3315 for ( ; i<nEnd; i++ ) 3316 { 3317 pEntry = GetEntry( i ); 3318 if( pEntry->IsSelected() ) 3319 SelectEntry( pEntry, sal_False, sal_True, sal_True, sal_True ); 3320 } 3321 } 3322 } 3323 3324 sal_Bool SvxIconChoiceCtrl_Impl::IsOver( SvPtrarr* pRectList, const Rectangle& rBoundRect ) const 3325 { 3326 const sal_uInt16 nCount = pRectList->Count(); 3327 for( sal_uInt16 nCur = 0; nCur < nCount; nCur++ ) 3328 { 3329 Rectangle* pRect = (Rectangle*)pRectList->GetObject( nCur ); 3330 if( rBoundRect.IsOver( *pRect )) 3331 return sal_True; 3332 } 3333 return sal_False; 3334 } 3335 3336 void SvxIconChoiceCtrl_Impl::AddSelectedRect( SvxIconChoiceCtrlEntry* pEntry1, 3337 SvxIconChoiceCtrlEntry* pEntry2 ) 3338 { 3339 DBG_ASSERT(pEntry1 && pEntry2,"SelectEntry: Invalid Entry-Ptr"); 3340 Rectangle aRect( GetEntryBoundRect( pEntry1 ) ); 3341 aRect.Union( GetEntryBoundRect( pEntry2 ) ); 3342 AddSelectedRect( aRect ); 3343 } 3344 3345 void SvxIconChoiceCtrl_Impl::AddSelectedRect( const Rectangle& rRect ) 3346 { 3347 Rectangle* pRect = new Rectangle( rRect ); 3348 pRect->Justify(); 3349 aSelectedRectList.Insert( (void*)pRect, aSelectedRectList.Count() ); 3350 } 3351 3352 void SvxIconChoiceCtrl_Impl::ClearSelectedRectList() 3353 { 3354 const sal_uInt16 nCount = aSelectedRectList.Count(); 3355 for( sal_uInt16 nCur = 0; nCur < nCount; nCur++ ) 3356 { 3357 Rectangle* pRect = (Rectangle*)aSelectedRectList.GetObject( nCur ); 3358 delete pRect; 3359 } 3360 aSelectedRectList.Remove( 0, aSelectedRectList.Count() ); 3361 } 3362 3363 void SvxIconChoiceCtrl_Impl::CalcScrollOffsets( const Point& rPosPixel, 3364 long& rX, long& rY, sal_Bool isInDragDrop, sal_uInt16 nBorderWidth) 3365 { 3366 // Scrolling der View, falls sich der Mauszeiger im Grenzbereich des 3367 // Fensters befindet 3368 long nPixelToScrollX = 0; 3369 long nPixelToScrollY = 0; 3370 Size aWndSize = aOutputSize; 3371 3372 nBorderWidth = (sal_uInt16)(Min( (long)(aWndSize.Height()-1), (long)nBorderWidth )); 3373 nBorderWidth = (sal_uInt16)(Min( (long)(aWndSize.Width()-1), (long)nBorderWidth )); 3374 3375 if ( rPosPixel.X() < nBorderWidth ) 3376 { 3377 if( isInDragDrop ) 3378 nPixelToScrollX = -DD_SCROLL_PIXEL; 3379 else 3380 nPixelToScrollX = rPosPixel.X()- nBorderWidth; 3381 } 3382 else if ( rPosPixel.X() > aWndSize.Width() - nBorderWidth ) 3383 { 3384 if( isInDragDrop ) 3385 nPixelToScrollX = DD_SCROLL_PIXEL; 3386 else 3387 nPixelToScrollX = rPosPixel.X() - (aWndSize.Width() - nBorderWidth); 3388 } 3389 if ( rPosPixel.Y() < nBorderWidth ) 3390 { 3391 if( isInDragDrop ) 3392 nPixelToScrollY = -DD_SCROLL_PIXEL; 3393 else 3394 nPixelToScrollY = rPosPixel.Y() - nBorderWidth; 3395 } 3396 else if ( rPosPixel.Y() > aWndSize.Height() - nBorderWidth ) 3397 { 3398 if( isInDragDrop ) 3399 nPixelToScrollY = DD_SCROLL_PIXEL; 3400 else 3401 nPixelToScrollY = rPosPixel.Y() - (aWndSize.Height() - nBorderWidth); 3402 } 3403 3404 rX = nPixelToScrollX; 3405 rY = nPixelToScrollY; 3406 } 3407 3408 IMPL_LINK(SvxIconChoiceCtrl_Impl, AutoArrangeHdl, void*, EMPTYARG ) 3409 { 3410 aAutoArrangeTimer.Stop(); 3411 Arrange( IsAutoArrange() ); 3412 return 0; 3413 } 3414 3415 IMPL_LINK(SvxIconChoiceCtrl_Impl, VisRectChangedHdl, void*, EMPTYARG ) 3416 { 3417 aVisRectChangedTimer.Stop(); 3418 pView->VisibleRectChanged(); 3419 return 0; 3420 } 3421 3422 IMPL_LINK(SvxIconChoiceCtrl_Impl, DocRectChangedHdl, void*, EMPTYARG ) 3423 { 3424 aDocRectChangedTimer.Stop(); 3425 pView->DocumentRectChanged(); 3426 return 0; 3427 } 3428 3429 void SvxIconChoiceCtrl_Impl::PrepareCommandEvent( const CommandEvent& rCEvt ) 3430 { 3431 StopEditTimer(); 3432 SvxIconChoiceCtrlEntry* pEntry = pView->GetEntry( rCEvt.GetMousePosPixel() ); 3433 if( (nFlags & F_DOWN_CTRL) && pEntry && !pEntry->IsSelected() ) 3434 SelectEntry( pEntry, sal_True, sal_True ); 3435 nFlags &= ~(F_DOWN_CTRL | F_DOWN_DESELECT); 3436 } 3437 3438 sal_Bool SvxIconChoiceCtrl_Impl::IsTextHit( SvxIconChoiceCtrlEntry* pEntry, const Point& rDocPos ) 3439 { 3440 Rectangle aRect( CalcTextRect( pEntry )); 3441 if( aRect.IsInside( rDocPos ) ) 3442 return sal_True; 3443 return sal_False; 3444 } 3445 3446 IMPL_LINK(SvxIconChoiceCtrl_Impl, EditTimeoutHdl, Timer*, EMPTYARG ) 3447 { 3448 SvxIconChoiceCtrlEntry* pEntry = GetCurEntry(); 3449 if( bEntryEditingEnabled && pEntry && 3450 pEntry->IsSelected()) 3451 { 3452 if( pView->EditingEntry( pEntry )) 3453 EditEntry( pEntry ); 3454 } 3455 return 0; 3456 } 3457 3458 3459 // 3460 // Funktionen zum Ausrichten der Eintraege am Grid 3461 // 3462 3463 // pStart == 0: Alle Eintraege werden ausgerichtet 3464 // sonst: Alle Eintraege der Zeile ab einschliesslich pStart werden ausgerichtet 3465 void SvxIconChoiceCtrl_Impl::AdjustEntryAtGrid( SvxIconChoiceCtrlEntry* pStart ) 3466 { 3467 SvPtrarr aLists; 3468 pImpCursor->CreateGridAjustData( aLists, pStart ); 3469 const sal_uInt16 nCount = aLists.Count(); 3470 for( sal_uInt16 nCur = 0; nCur < nCount; nCur++ ) 3471 AdjustAtGrid( *(SvPtrarr*)aLists[ nCur ], pStart ); 3472 IcnCursor_Impl::DestroyGridAdjustData( aLists ); 3473 CheckScrollBars(); 3474 } 3475 3476 // Richtet eine Zeile aus, erweitert ggf. die Breite; Bricht die Zeile nicht um 3477 void SvxIconChoiceCtrl_Impl::AdjustAtGrid( const SvPtrarr& rRow, SvxIconChoiceCtrlEntry* pStart ) 3478 { 3479 if( !rRow.Count() ) 3480 return; 3481 3482 sal_Bool bGo; 3483 if( !pStart ) 3484 bGo = sal_True; 3485 else 3486 bGo = sal_False; 3487 3488 long nCurRight = 0; 3489 for( sal_uInt16 nCur = 0; nCur < rRow.Count(); nCur++ ) 3490 { 3491 SvxIconChoiceCtrlEntry* pCur = (SvxIconChoiceCtrlEntry*)rRow[ nCur ]; 3492 if( !bGo && pCur == pStart ) 3493 bGo = sal_True; 3494 3495 //SvIcnVwDataEntry* pViewData = ICNVIEWDATA(pCur); 3496 // Massgebend (fuer unser Auge) ist die Bitmap, da sonst 3497 // durch lange Texte der Eintrag stark springen kann 3498 const Rectangle& rBoundRect = GetEntryBoundRect( pCur ); 3499 Rectangle aCenterRect( CalcBmpRect( pCur, 0 )); 3500 if( bGo && !pCur->IsPosLocked() ) 3501 { 3502 long nWidth = aCenterRect.GetSize().Width(); 3503 Point aNewPos( AdjustAtGrid( aCenterRect, rBoundRect ) ); 3504 while( aNewPos.X() < nCurRight ) 3505 aNewPos.X() += nGridDX; 3506 if( aNewPos != rBoundRect.TopLeft() ) 3507 { 3508 SetEntryPos( pCur, aNewPos ); 3509 pCur->SetFlags( ICNVIEW_FLAG_POS_MOVED ); 3510 nFlags |= F_MOVED_ENTRIES; 3511 } 3512 nCurRight = aNewPos.X() + nWidth; 3513 } 3514 else 3515 { 3516 nCurRight = rBoundRect.Right(); 3517 } 3518 } 3519 } 3520 3521 // Richtet Rect am Grid aus, garantiert jedoch nicht, dass die 3522 // neue Pos. frei ist. Die Pos. kann fuer SetEntryPos verwendet werden. 3523 // Das CenterRect beschreibt den Teil des BoundRects, der fuer 3524 // die Berechnung des Ziel-Rechtecks verwendet wird. 3525 Point SvxIconChoiceCtrl_Impl::AdjustAtGrid( const Rectangle& rCenterRect, 3526 const Rectangle& rBoundRect ) const 3527 { 3528 Point aPos( rCenterRect.TopLeft() ); 3529 Size aSize( rCenterRect.GetSize() ); 3530 3531 aPos.X() -= LROFFS_WINBORDER; 3532 aPos.Y() -= TBOFFS_WINBORDER; 3533 3534 // align (ref ist mitte des rects) 3535 short nGridX = (short)((aPos.X()+(aSize.Width()/2)) / nGridDX); 3536 short nGridY = (short)((aPos.Y()+(aSize.Height()/2)) / nGridDY); 3537 aPos.X() = nGridX * nGridDX; 3538 aPos.Y() = nGridY * nGridDY; 3539 // hor. center 3540 aPos.X() += (nGridDX - rBoundRect.GetSize().Width() ) / 2; 3541 3542 aPos.X() += LROFFS_WINBORDER; 3543 aPos.Y() += TBOFFS_WINBORDER; 3544 3545 return aPos; 3546 } 3547 3548 void SvxIconChoiceCtrl_Impl::SetEntryTextMode( SvxIconChoiceCtrlTextMode eMode, SvxIconChoiceCtrlEntry* pEntry ) 3549 { 3550 if( !pEntry ) 3551 { 3552 if( eTextMode != eMode ) 3553 { 3554 if( eTextMode == IcnShowTextDontKnow ) 3555 eTextMode = IcnShowTextShort; 3556 eTextMode = eMode; 3557 Arrange( sal_True ); 3558 } 3559 } 3560 else 3561 { 3562 if( pEntry->eTextMode != eMode ) 3563 { 3564 pEntry->eTextMode = eMode; 3565 InvalidateEntry( pEntry ); 3566 pView->Invalidate( GetEntryBoundRect( pEntry ) ); 3567 AdjustVirtSize( pEntry->aRect ); 3568 } 3569 } 3570 } 3571 3572 SvxIconChoiceCtrlTextMode SvxIconChoiceCtrl_Impl::GetTextMode( const SvxIconChoiceCtrlEntry* pEntry ) const 3573 { 3574 if( !pEntry ) 3575 return eTextMode; 3576 return pEntry->GetTextMode(); 3577 } 3578 3579 SvxIconChoiceCtrlTextMode SvxIconChoiceCtrl_Impl::GetEntryTextModeSmart( const SvxIconChoiceCtrlEntry* pEntry ) const 3580 { 3581 DBG_ASSERT(pEntry,"GetEntryTextModeSmart: Entry not set"); 3582 SvxIconChoiceCtrlTextMode eMode = pEntry->GetTextMode(); 3583 if( eMode == IcnShowTextDontKnow ) 3584 return eTextMode; 3585 return eMode; 3586 } 3587 3588 void SvxIconChoiceCtrl_Impl::ShowEntryFocusRect( const SvxIconChoiceCtrlEntry* pEntry ) 3589 { 3590 if( !pEntry ) 3591 { 3592 pView->HideFocus(); 3593 } 3594 else 3595 { 3596 Rectangle aRect ( CalcFocusRect( (SvxIconChoiceCtrlEntry*)pEntry ) ); 3597 /*pView->*/ShowFocus( aRect ); 3598 } 3599 } 3600 3601 //////////////////////////////////////////////////////////////////////////////////////////////// 3602 // 3603 // Draw my own focusrect, because the focusrect of the outputdevice has got the inverted color 3604 // of the background. But what will we see, if the the backgroundcolor is gray ? - We will see 3605 // a gray focusrect on a gray background !!! 3606 // 3607 void SvxIconChoiceCtrl_Impl::ShowFocus ( Rectangle& rRect ) 3608 { 3609 Color aBkgColor ( pView->GetBackground().GetColor() ); 3610 Color aPenColor; 3611 sal_uInt16 nColor = ( aBkgColor.GetRed() + aBkgColor.GetGreen() + aBkgColor.GetBlue() ) / 3; 3612 if ( nColor > 128 ) 3613 aPenColor.SetColor ( COL_BLACK ); 3614 else 3615 aPenColor.SetColor( COL_WHITE ); 3616 3617 aFocus.bOn = sal_True; 3618 aFocus.aPenColor = aPenColor; 3619 aFocus.aRect = rRect; 3620 } 3621 3622 void SvxIconChoiceCtrl_Impl::HideFocus () 3623 { 3624 aFocus.bOn = sal_False; 3625 } 3626 3627 void SvxIconChoiceCtrl_Impl::DrawFocusRect ( OutputDevice* pOut ) 3628 { 3629 pOut->SetLineColor( aFocus.aPenColor ); 3630 pOut->SetFillColor(); 3631 Polygon aPolygon ( aFocus.aRect ); 3632 3633 LineInfo aLineInfo ( LINE_DASH ); 3634 3635 aLineInfo.SetDashLen ( 1 ); 3636 3637 aLineInfo.SetDotLen ( 1L ); 3638 aLineInfo.SetDistance ( 1L ); 3639 aLineInfo.SetDotCount ( 1 ); 3640 3641 pOut->DrawPolyLine ( aPolygon, aLineInfo ); 3642 } 3643 3644 sal_Bool SvxIconChoiceCtrl_Impl::IsMnemonicChar( sal_Unicode cChar, sal_uLong& rPos ) const 3645 { 3646 sal_Bool bRet = sal_False; 3647 const vcl::I18nHelper& rI18nHelper = Application::GetSettings().GetUILocaleI18nHelper(); 3648 sal_uLong nEntryCount = GetEntryCount(); 3649 for ( sal_uLong i = 0; i < nEntryCount; ++i ) 3650 { 3651 if ( rI18nHelper.MatchMnemonic( GetEntry( i )->GetText(), cChar ) ) 3652 { 3653 bRet = sal_True; 3654 rPos = i; 3655 break; 3656 } 3657 } 3658 3659 return bRet; 3660 } 3661 3662 // 3663 //////////////////////////////////////////////////////////////////////////////////////////////// 3664 3665 IMPL_LINK(SvxIconChoiceCtrl_Impl, UserEventHdl, void*, nId ) 3666 { 3667 if( nId == EVENTID_ADJUST_SCROLLBARS ) 3668 { 3669 nUserEventAdjustScrBars = 0; 3670 AdjustScrollBars(); 3671 } 3672 else if( nId == EVENTID_SHOW_CURSOR ) 3673 { 3674 nUserEventShowCursor = 0; 3675 ShowCursor( sal_True ); 3676 } 3677 return 0; 3678 } 3679 3680 void SvxIconChoiceCtrl_Impl::CancelUserEvents() 3681 { 3682 if( nUserEventAdjustScrBars ) 3683 { 3684 Application::RemoveUserEvent( nUserEventAdjustScrBars ); 3685 nUserEventAdjustScrBars = 0; 3686 } 3687 if( nUserEventShowCursor ) 3688 { 3689 Application::RemoveUserEvent( nUserEventShowCursor ); 3690 nUserEventShowCursor = 0; 3691 } 3692 } 3693 3694 void SvxIconChoiceCtrl_Impl::InvalidateEntry( SvxIconChoiceCtrlEntry* pEntry ) 3695 { 3696 if( pEntry == pCursor ) 3697 ShowCursor( sal_False ); 3698 pView->Invalidate( pEntry->aRect ); 3699 Center( pEntry ); 3700 pView->Invalidate( pEntry->aRect ); 3701 if( pEntry == pCursor ) 3702 ShowCursor( sal_True ); 3703 } 3704 3705 void SvxIconChoiceCtrl_Impl::EditEntry( SvxIconChoiceCtrlEntry* pEntry ) 3706 { 3707 DBG_ASSERT(pEntry,"EditEntry: Entry not set"); 3708 if( !pEntry ) 3709 return; 3710 3711 StopEntryEditing( sal_True ); 3712 DELETEZ(pEdit); 3713 SetNoSelection(); 3714 3715 pCurEditedEntry = pEntry; 3716 String aEntryText( pView->GetEntryText( pEntry, sal_True ) ); 3717 Rectangle aRect( CalcTextRect( pEntry, 0, sal_True, &aEntryText ) ); 3718 MakeVisible( aRect ); 3719 Point aPos( aRect.TopLeft() ); 3720 aPos = pView->GetPixelPos( aPos ); 3721 aRect.SetPos( aPos ); 3722 pView->HideFocus(); 3723 pEdit = new IcnViewEdit_Impl( 3724 pView, 3725 aRect.TopLeft(), 3726 aRect.GetSize(), 3727 aEntryText, 3728 LINK( this, SvxIconChoiceCtrl_Impl, TextEditEndedHdl ) ); 3729 } 3730 3731 IMPL_LINK( SvxIconChoiceCtrl_Impl, TextEditEndedHdl, IcnViewEdit_Impl*, EMPTYARG ) 3732 { 3733 DBG_ASSERT(pEdit,"TextEditEnded: pEdit not set"); 3734 if( !pEdit ) 3735 { 3736 pCurEditedEntry = 0; 3737 return 0; 3738 } 3739 DBG_ASSERT(pCurEditedEntry,"TextEditEnded: pCurEditedEntry not set"); 3740 3741 if( !pCurEditedEntry ) 3742 { 3743 pEdit->Hide(); 3744 if( pEdit->IsGrabFocus() ) 3745 pView->GrabFocus(); 3746 return 0; 3747 } 3748 3749 String aText; 3750 if ( !pEdit->EditingCanceled() ) 3751 aText = pEdit->GetText(); 3752 else 3753 aText = pEdit->GetSavedValue(); 3754 3755 if( pView->EditedEntry( pCurEditedEntry, aText, pEdit->EditingCanceled() ) ) 3756 InvalidateEntry( pCurEditedEntry ); 3757 if( !GetSelectionCount() ) 3758 SelectEntry( pCurEditedEntry, sal_True ); 3759 3760 pEdit->Hide(); 3761 if( pEdit->IsGrabFocus() ) 3762 pView->GrabFocus(); 3763 // Das Edit kann nicht hier geloescht werden, weil es noch in einem 3764 // Handler steht. Es wird im Dtor oder im naechsten EditEntry geloescht. 3765 pCurEditedEntry = 0; 3766 return 0; 3767 } 3768 3769 void SvxIconChoiceCtrl_Impl::StopEntryEditing( sal_Bool bCancel ) 3770 { 3771 if( pEdit ) 3772 pEdit->StopEditing( bCancel ); 3773 } 3774 3775 void SvxIconChoiceCtrl_Impl::LockEntryPos( SvxIconChoiceCtrlEntry* pEntry, sal_Bool bLock ) 3776 { 3777 if( bLock ) 3778 pEntry->SetFlags( ICNVIEW_FLAG_POS_LOCKED ); 3779 else 3780 pEntry->ClearFlags( ICNVIEW_FLAG_POS_LOCKED ); 3781 } 3782 3783 SvxIconChoiceCtrlEntry* SvxIconChoiceCtrl_Impl::GetFirstSelectedEntry( sal_uLong& rPos ) const 3784 { 3785 if( !GetSelectionCount() ) 3786 return 0; 3787 3788 if( (nWinBits & WB_HIGHLIGHTFRAME) && (eSelectionMode == NO_SELECTION) ) 3789 { 3790 rPos = pView->GetEntryListPos( pCurHighlightFrame ); 3791 return pCurHighlightFrame; 3792 } 3793 3794 sal_uLong nCount = aEntries.Count(); 3795 if( !pHead ) 3796 { 3797 for( sal_uLong nCur = 0; nCur < nCount; nCur++ ) 3798 { 3799 SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( nCur ); 3800 if( pEntry->IsSelected() ) 3801 { 3802 rPos = nCur; 3803 return pEntry; 3804 } 3805 } 3806 } 3807 else 3808 { 3809 SvxIconChoiceCtrlEntry* pEntry = pHead; 3810 while( nCount-- ) 3811 { 3812 if( pEntry->IsSelected() ) 3813 { 3814 rPos = GetEntryListPos( pEntry ); 3815 return pEntry; 3816 } 3817 pEntry = pEntry->pflink; 3818 if( nCount && pEntry == pHead ) 3819 { 3820 DBG_ERROR("SvxIconChoiceCtrl_Impl::GetFirstSelectedEntry > Endlosschleife!"); 3821 return 0; 3822 } 3823 } 3824 } 3825 return 0; 3826 } 3827 3828 // kein Round Robin! 3829 SvxIconChoiceCtrlEntry* SvxIconChoiceCtrl_Impl::GetNextSelectedEntry( sal_uLong& rStartPos ) const 3830 { 3831 sal_uLong nCount = aEntries.Count(); 3832 if( rStartPos > nCount || !GetSelectionCount() ) 3833 return 0; 3834 if( !pHead ) 3835 { 3836 for( sal_uLong nCur = rStartPos+1; nCur < nCount; nCur++ ) 3837 { 3838 SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( nCur ); 3839 if( pEntry->IsSelected() ) 3840 { 3841 rStartPos = nCur; 3842 return pEntry; 3843 } 3844 } 3845 } 3846 else 3847 { 3848 SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( rStartPos ); 3849 pEntry = pEntry->pflink; 3850 while( pEntry != pHead ) 3851 { 3852 if( pEntry->IsSelected() ) 3853 { 3854 rStartPos = GetEntryListPos( pEntry ); 3855 return pEntry; 3856 } 3857 pEntry = pEntry->pflink; 3858 } 3859 } 3860 3861 rStartPos = 0xffffffff; 3862 return 0; 3863 } 3864 3865 void SvxIconChoiceCtrl_Impl::SelectAll( sal_Bool bSelect, sal_Bool bPaint ) 3866 { 3867 bPaint = sal_True; 3868 3869 sal_uLong nCount = aEntries.Count(); 3870 for( sal_uLong nCur = 0; nCur < nCount && (bSelect || GetSelectionCount() ); nCur++ ) 3871 { 3872 SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( nCur ); 3873 SelectEntry( pEntry, bSelect, sal_True, sal_True, bPaint ); 3874 } 3875 nFlags &= (~F_ADD_MODE); 3876 pAnchor = 0; 3877 } 3878 3879 void SvxIconChoiceCtrl_Impl::SaveSelection( List** ppList ) 3880 { 3881 if( !*ppList ) 3882 *ppList = new List; 3883 sal_uLong nPos; 3884 SvxIconChoiceCtrlEntry* pEntry = GetFirstSelectedEntry( nPos ); 3885 while( pEntry && GetSelectionCount() != (*ppList)->Count() ) 3886 { 3887 (*ppList)->Insert( pEntry, LIST_APPEND ); 3888 pEntry = GetNextSelectedEntry( nPos ); 3889 } 3890 } 3891 3892 IcnViewEdit_Impl::IcnViewEdit_Impl( SvtIconChoiceCtrl* pParent, const Point& rPos, 3893 const Size& rSize, const XubString& rData, const Link& rNotifyEditEnd ) : 3894 MultiLineEdit( pParent, (pParent->GetStyle() & WB_ICON) ? WB_CENTER : WB_LEFT), 3895 aCallBackHdl( rNotifyEditEnd ), 3896 bCanceled( sal_False ), 3897 bAlreadyInCallback( sal_False ), 3898 bGrabFocus( sal_False ) 3899 { 3900 Font aFont( pParent->GetPointFont() ); 3901 aFont.SetTransparent( sal_False ); 3902 SetControlFont( aFont ); 3903 if( !pParent->HasFontFillColor() ) 3904 { 3905 Color aColor( pParent->GetBackground().GetColor() ); 3906 SetControlBackground( aColor ); 3907 } 3908 else 3909 SetControlBackground( aFont.GetFillColor() ); 3910 SetControlForeground( aFont.GetColor() ); 3911 SetPosPixel( rPos ); 3912 SetSizePixel( CalcAdjustedSize(rSize) ); 3913 SetText( rData ); 3914 SaveValue(); 3915 3916 aAccReturn.InsertItem( IMPICNVIEW_ACC_RETURN, KeyCode(KEY_RETURN) ); 3917 aAccEscape.InsertItem( IMPICNVIEW_ACC_ESCAPE, KeyCode(KEY_ESCAPE) ); 3918 3919 aAccReturn.SetActivateHdl( LINK( this, IcnViewEdit_Impl, ReturnHdl_Impl) ); 3920 aAccEscape.SetActivateHdl( LINK( this, IcnViewEdit_Impl, EscapeHdl_Impl) ); 3921 GetpApp()->InsertAccel( &aAccReturn);//, ACCEL_ALWAYS ); 3922 GetpApp()->InsertAccel( &aAccEscape);//, ACCEL_ALWAYS ); 3923 Show(); 3924 GrabFocus(); 3925 } 3926 3927 IcnViewEdit_Impl::~IcnViewEdit_Impl() 3928 { 3929 if( !bAlreadyInCallback ) 3930 { 3931 GetpApp()->RemoveAccel( &aAccReturn ); 3932 GetpApp()->RemoveAccel( &aAccEscape ); 3933 } 3934 } 3935 3936 void IcnViewEdit_Impl::CallCallBackHdl_Impl() 3937 { 3938 aTimer.Stop(); 3939 if ( !bAlreadyInCallback ) 3940 { 3941 bAlreadyInCallback = sal_True; 3942 GetpApp()->RemoveAccel( &aAccReturn ); 3943 GetpApp()->RemoveAccel( &aAccEscape ); 3944 Hide(); 3945 aCallBackHdl.Call( this ); 3946 } 3947 } 3948 3949 IMPL_LINK( IcnViewEdit_Impl, Timeout_Impl, Timer*, EMPTYARG ) 3950 { 3951 CallCallBackHdl_Impl(); 3952 return 0; 3953 } 3954 3955 IMPL_LINK( IcnViewEdit_Impl, ReturnHdl_Impl, Accelerator*, EMPTYARG ) 3956 { 3957 bCanceled = sal_False; 3958 bGrabFocus = sal_True; 3959 CallCallBackHdl_Impl(); 3960 return 1; 3961 } 3962 3963 IMPL_LINK( IcnViewEdit_Impl, EscapeHdl_Impl, Accelerator*, EMPTYARG ) 3964 { 3965 bCanceled = sal_True; 3966 bGrabFocus = sal_True; 3967 CallCallBackHdl_Impl(); 3968 return 1; 3969 } 3970 3971 void IcnViewEdit_Impl::KeyInput( const KeyEvent& rKEvt ) 3972 { 3973 KeyCode aCode = rKEvt.GetKeyCode(); 3974 sal_uInt16 nCode = aCode.GetCode(); 3975 3976 switch ( nCode ) 3977 { 3978 case KEY_ESCAPE: 3979 bCanceled = sal_True; 3980 bGrabFocus = sal_True; 3981 CallCallBackHdl_Impl(); 3982 break; 3983 3984 case KEY_RETURN: 3985 bCanceled = sal_False; 3986 bGrabFocus = sal_True; 3987 CallCallBackHdl_Impl(); 3988 break; 3989 3990 default: 3991 MultiLineEdit::KeyInput( rKEvt ); 3992 } 3993 } 3994 3995 long IcnViewEdit_Impl::PreNotify( NotifyEvent& rNEvt ) 3996 { 3997 if( rNEvt.GetType() == EVENT_LOSEFOCUS ) 3998 { 3999 if ( !bAlreadyInCallback && 4000 ((!Application::GetFocusWindow()) || !IsChild(Application::GetFocusWindow()))) 4001 { 4002 bCanceled = sal_False; 4003 aTimer.SetTimeout(10); 4004 aTimer.SetTimeoutHdl(LINK(this,IcnViewEdit_Impl,Timeout_Impl)); 4005 aTimer.Start(); 4006 } 4007 } 4008 return 0; 4009 } 4010 4011 void IcnViewEdit_Impl::StopEditing( sal_Bool bCancel ) 4012 { 4013 if ( !bAlreadyInCallback ) 4014 { 4015 bCanceled = bCancel; 4016 CallCallBackHdl_Impl(); 4017 } 4018 } 4019 4020 sal_uLong SvxIconChoiceCtrl_Impl::GetEntryListPos( SvxIconChoiceCtrlEntry* pEntry ) const 4021 { 4022 if( !(nFlags & F_ENTRYLISTPOS_VALID )) 4023 ((SvxIconChoiceCtrl_Impl*)this)->SetListPositions(); 4024 return pEntry->nPos; 4025 } 4026 4027 void SvxIconChoiceCtrl_Impl::SetEntryListPos( SvxIconChoiceCtrlEntry* pListEntry, sal_uLong nNewPos ) 4028 { 4029 sal_uLong nCurPos = GetEntryListPos( pListEntry ); 4030 if( nCurPos == nNewPos ) 4031 return; 4032 aEntries.List::Remove( nCurPos ); 4033 aEntries.List::Insert( (void*)pListEntry, nNewPos ); 4034 // Eintragspositionen anpassen 4035 sal_uLong nStart, nEnd; 4036 if( nNewPos < nCurPos ) 4037 { 4038 nStart = nNewPos; 4039 nEnd = nCurPos; 4040 } 4041 else 4042 { 4043 nStart = nCurPos; 4044 nEnd = nNewPos; 4045 } 4046 for( ; nStart <= nEnd; nStart++ ) 4047 { 4048 SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( nStart ); 4049 pEntry->nPos = nStart; 4050 } 4051 } 4052 4053 void SvxIconChoiceCtrl_Impl::SetEntryFlags( SvxIconChoiceCtrlEntry* pEntry, sal_uInt16 nEntryFlags ) 4054 { 4055 pEntry->nFlags = nEntryFlags; 4056 if( nEntryFlags & ICNVIEW_FLAG_POS_MOVED ) 4057 nFlags |= F_MOVED_ENTRIES; 4058 } 4059 4060 SvxIconChoiceCtrlEntry* SvxIconChoiceCtrl_Impl::GoLeftRight( SvxIconChoiceCtrlEntry* pStart, sal_Bool bRight ) 4061 { 4062 return pImpCursor->GoLeftRight( pStart, bRight ); 4063 } 4064 4065 SvxIconChoiceCtrlEntry* SvxIconChoiceCtrl_Impl::GoUpDown( SvxIconChoiceCtrlEntry* pStart, sal_Bool bDown ) 4066 { 4067 return pImpCursor->GoUpDown( pStart, bDown ); 4068 } 4069 4070 void SvxIconChoiceCtrl_Impl::InitSettings() 4071 { 4072 const StyleSettings& rStyleSettings = pView->GetSettings().GetStyleSettings(); 4073 4074 if( !pView->HasFont() ) 4075 { 4076 // Unit aus den Settings ist Point 4077 Font aFont( rStyleSettings.GetFieldFont() ); 4078 //const Font& rFont = pView->GetFont(); 4079 //if( pView->HasFontTextColor() ) 4080 aFont.SetColor( rStyleSettings.GetWindowTextColor() ); 4081 //if( pView->HasFontFillColor() ) 4082 //aFont.SetFillColor( rFont.GetFillColor() ); 4083 pView->SetPointFont( aFont ); 4084 SetDefaultTextSize(); 4085 } 4086 4087 //if( !pView->HasFontTextColor() ) 4088 pView->SetTextColor( rStyleSettings.GetFieldTextColor() ); 4089 //if( !pView->HasFontFillColor() ) 4090 pView->SetTextFillColor(); 4091 4092 //if( !pView->HasBackground() ) 4093 pView->SetBackground( rStyleSettings.GetFieldColor()); 4094 4095 long nScrBarSize = rStyleSettings.GetScrollBarSize(); 4096 if( nScrBarSize != nHorSBarHeight || nScrBarSize != nVerSBarWidth ) 4097 { 4098 nHorSBarHeight = nScrBarSize; 4099 Size aSize( aHorSBar.GetSizePixel() ); 4100 aSize.Height() = nScrBarSize; 4101 aHorSBar.Hide(); 4102 aHorSBar.SetSizePixel( aSize ); 4103 4104 nVerSBarWidth = nScrBarSize; 4105 aSize = aVerSBar.GetSizePixel(); 4106 aSize.Width() = nScrBarSize; 4107 aVerSBar.Hide(); 4108 aVerSBar.SetSizePixel( aSize ); 4109 4110 Size aOSize( pView->Control::GetOutputSizePixel() ); 4111 PositionScrollBars( aOSize.Width(), aOSize.Height() ); 4112 AdjustScrollBars(); 4113 } 4114 } 4115 4116 EntryList_Impl::EntryList_Impl( SvxIconChoiceCtrl_Impl* pOwner, sal_uInt16 _nInitSize , sal_uInt16 _nReSize ) : 4117 List( _nInitSize, _nReSize ), 4118 _pOwner( pOwner ) 4119 { 4120 _pOwner->pHead = 0; 4121 } 4122 4123 EntryList_Impl::EntryList_Impl( SvxIconChoiceCtrl_Impl* pOwner, sal_uInt16 _nBlockSize, sal_uInt16 _nInitSize, sal_uInt16 _nReSize ) : 4124 List( _nBlockSize, _nInitSize, _nReSize ), 4125 _pOwner( pOwner ) 4126 { 4127 _pOwner->pHead = 0; 4128 } 4129 4130 EntryList_Impl::~EntryList_Impl() 4131 { 4132 _pOwner->pHead = 0; 4133 } 4134 4135 void EntryList_Impl::Clear() 4136 { 4137 _pOwner->pHead = 0; 4138 List::Clear(); 4139 } 4140 4141 void EntryList_Impl::Insert( SvxIconChoiceCtrlEntry* pEntry, sal_uLong nPos ) 4142 { 4143 List::Insert( pEntry, nPos ); 4144 if( _pOwner->pHead ) 4145 pEntry->SetBacklink( _pOwner->pHead->pblink ); 4146 } 4147 4148 SvxIconChoiceCtrlEntry* EntryList_Impl::Remove( sal_uLong nPos ) 4149 { 4150 SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)List::Remove( nPos ); 4151 DBG_ASSERT(pEntry,"EntryList_Impl::Remove > Entry not found"); 4152 Removed_Impl( pEntry ); 4153 return pEntry; 4154 } 4155 4156 void EntryList_Impl::Remove( SvxIconChoiceCtrlEntry* pEntry ) 4157 { 4158 List::Remove( (void*)pEntry ); 4159 Removed_Impl( pEntry ); 4160 } 4161 4162 void EntryList_Impl::Removed_Impl( SvxIconChoiceCtrlEntry* pEntry ) 4163 { 4164 if( _pOwner->pHead ) 4165 { 4166 if( _pOwner->pHead == pEntry ) 4167 { 4168 if( _pOwner->pHead != pEntry->pflink ) 4169 _pOwner->pHead = pEntry->pflink; 4170 else 4171 { 4172 DBG_ASSERT(!Count(),"EntryList_Impl::Remove > Invalid predecessor" ); 4173 _pOwner->pHead = 0; 4174 } 4175 } 4176 pEntry->Unlink(); 4177 } 4178 } 4179 4180 void SvxIconChoiceCtrl_Impl::SetPositionMode( SvxIconChoiceCtrlPositionMode eMode ) 4181 { 4182 sal_uLong nCur; 4183 4184 if( eMode == ePositionMode ) 4185 return; 4186 4187 SvxIconChoiceCtrlPositionMode eOldMode = ePositionMode; 4188 ePositionMode = eMode; 4189 sal_uLong nCount = aEntries.Count(); 4190 4191 if( eOldMode == IcnViewPositionModeAutoArrange ) 4192 { 4193 // positionieren wir verschobene Eintraege 'hart' gibts noch Probleme 4194 // mit ungewollten Ueberlappungen, da diese Eintrage im Arrange 4195 // nicht beruecksichtigt werden. 4196 #if 1 4197 if( aEntries.Count() ) 4198 aAutoArrangeTimer.Start(); 4199 #else 4200 if( pHead ) 4201 { 4202 // verschobene Eintraege 'hart' auf ihre Position setzen 4203 nCur = nCount; 4204 SvxIconChoiceCtrlEntry* pEntry = pHead; 4205 while( nCur ) 4206 { 4207 SvxIconChoiceCtrlEntry* pPred; 4208 if( GetEntryPredecessor( pEntry, &pPred )) 4209 SetEntryFlags( pEntry, ICNVIEW_FLAG_POS_MOVED ); 4210 pEntry = pEntry->pflink; 4211 nCur--; 4212 } 4213 ClearPredecessors(); 4214 } 4215 #endif 4216 return; 4217 } 4218 4219 if( ePositionMode == IcnViewPositionModeAutoArrange ) 4220 { 4221 List aMovedEntries; 4222 for( nCur = 0; nCur < nCount; nCur++ ) 4223 { 4224 SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( nCur ); 4225 if( pEntry->GetFlags() & (ICNVIEW_FLAG_POS_LOCKED | ICNVIEW_FLAG_POS_MOVED)) 4226 { 4227 SvxIconChoiceCtrlEntry_Impl* pE = new SvxIconChoiceCtrlEntry_Impl( 4228 pEntry, GetEntryBoundRect( pEntry )); 4229 aMovedEntries.Insert( pE, LIST_APPEND ); 4230 } 4231 } 4232 nCount = aMovedEntries.Count(); 4233 for( nCur = 0; nCur < nCount; nCur++ ) 4234 { 4235 SvxIconChoiceCtrlEntry_Impl* pE = (SvxIconChoiceCtrlEntry_Impl*)aMovedEntries.GetObject(nCur); 4236 SetEntryPos( pE->_pEntry, pE->_aPos ); 4237 } 4238 for( nCur = 0; nCur < nCount; nCur++ ) 4239 delete (SvxIconChoiceCtrlEntry_Impl*)aMovedEntries.GetObject( nCur ); 4240 if( aEntries.Count() ) 4241 aAutoArrangeTimer.Start(); 4242 } 4243 else if( ePositionMode == IcnViewPositionModeAutoAdjust ) 4244 { 4245 AdjustEntryAtGrid( 0 ); 4246 } 4247 } 4248 4249 void SvxIconChoiceCtrl_Impl::SetEntryPredecessor( SvxIconChoiceCtrlEntry* pEntry, 4250 SvxIconChoiceCtrlEntry* pPredecessor ) 4251 { 4252 if( !IsAutoArrange() ) 4253 return; 4254 4255 if( pEntry == pPredecessor ) 4256 return; 4257 4258 sal_uLong nPos1 = GetEntryListPos( pEntry ); 4259 if( !pHead ) 4260 { 4261 if( pPredecessor ) 4262 { 4263 sal_uLong nPos2 = GetEntryListPos( pPredecessor ); 4264 if( nPos1 == (nPos2 + 1) ) 4265 return; // ist schon Vorgaenger 4266 } 4267 else if( !nPos1 ) 4268 return; 4269 } 4270 4271 if( !pHead ) 4272 InitPredecessors(); 4273 4274 if( !pPredecessor && pHead == pEntry ) 4275 return; // ist schon der Erste 4276 4277 sal_Bool bSetHead = sal_False; 4278 if( !pPredecessor ) 4279 { 4280 bSetHead = sal_True; 4281 pPredecessor = pHead->pblink; 4282 } 4283 if( pEntry == pHead ) 4284 { 4285 pHead = pHead->pflink; 4286 bSetHead = sal_False; 4287 } 4288 if( pEntry != pPredecessor ) 4289 { 4290 pEntry->Unlink(); 4291 pEntry->SetBacklink( pPredecessor ); 4292 } 4293 if( bSetHead ) 4294 pHead = pEntry; 4295 pEntry->SetFlags( ICNVIEW_FLAG_PRED_SET ); 4296 aAutoArrangeTimer.Start(); 4297 } 4298 4299 sal_Bool SvxIconChoiceCtrl_Impl::GetEntryPredecessor( SvxIconChoiceCtrlEntry* pEntry, 4300 SvxIconChoiceCtrlEntry** ppPredecessor ) 4301 { 4302 *ppPredecessor = 0; 4303 if( !pHead ) 4304 return sal_False; 4305 DBG_ASSERT(pEntry->pblink,"GetEntryPredecessor: Backward link not set"); 4306 DBG_ASSERT(pEntry->pflink,"GetEntryPredecessor: Forward link not set"); 4307 4308 if( pEntry == pHead ) 4309 { 4310 SvxIconChoiceCtrlEntry* pFirst = (SvxIconChoiceCtrlEntry*)aEntries.GetObject(0); 4311 if( pFirst != pEntry ) 4312 return sal_True; 4313 return sal_False; 4314 } 4315 *ppPredecessor = pEntry->pblink; 4316 if( !(pEntry->nFlags & ICNVIEW_FLAG_PRED_SET) && 4317 (GetEntryListPos( *ppPredecessor ) + 1) == GetEntryListPos( pEntry )) 4318 return sal_False; 4319 return sal_True; 4320 } 4321 4322 SvxIconChoiceCtrlEntry* SvxIconChoiceCtrl_Impl::FindEntryPredecessor( SvxIconChoiceCtrlEntry* pEntry, 4323 const Point& rPosTopLeft ) 4324 { 4325 Point aPos( rPosTopLeft ); //TopLeft 4326 Rectangle aCenterRect( CalcBmpRect( pEntry, &aPos )); 4327 Point aNewPos( aCenterRect.Center() ); 4328 sal_uLong nGrid = GetPredecessorGrid( aNewPos ); 4329 sal_uLong nCount = aEntries.Count(); 4330 if( nGrid == ULONG_MAX ) 4331 return 0; 4332 if( nGrid >= nCount ) 4333 nGrid = nCount - 1; 4334 if( !pHead ) 4335 return (SvxIconChoiceCtrlEntry*)aEntries.GetObject( nGrid ); 4336 4337 SvxIconChoiceCtrlEntry* pCur = pHead; // Grid 0 4338 // todo: Liste von hinten aufrollen wenn nGrid > nCount/2 4339 for( sal_uLong nCur = 0; nCur < nGrid; nCur++ ) 4340 pCur = pCur->pflink; 4341 4342 return pCur; 4343 } 4344 4345 sal_uLong SvxIconChoiceCtrl_Impl::GetPredecessorGrid( const Point& rPos) const 4346 { 4347 Point aPos( rPos ); 4348 aPos.X() -= LROFFS_WINBORDER; 4349 aPos.Y() -= TBOFFS_WINBORDER; 4350 sal_uInt16 nMaxCol = (sal_uInt16)(aVirtOutputSize.Width() / nGridDX); 4351 if( nMaxCol ) 4352 nMaxCol--; 4353 sal_uInt16 nGridX = (sal_uInt16)(aPos.X() / nGridDX); 4354 if( nGridX > nMaxCol ) 4355 nGridX = nMaxCol; 4356 sal_uInt16 nGridY = (sal_uInt16)(aPos.Y() / nGridDY); 4357 sal_uInt16 nGridsX = (sal_uInt16)(aOutputSize.Width() / nGridDX); 4358 sal_uLong nGrid = (nGridY * nGridsX) + nGridX; 4359 long nMiddle = (nGridX * nGridDX) + (nGridDX / 2); 4360 if( rPos.X() < nMiddle ) 4361 { 4362 if( !nGrid ) 4363 nGrid = ULONG_MAX; 4364 else 4365 nGrid--; 4366 } 4367 return nGrid; 4368 } 4369 4370 void SvxIconChoiceCtrl_Impl::Flush() 4371 { 4372 if( aAutoArrangeTimer.IsActive() ) 4373 { 4374 AutoArrangeHdl( 0 ); 4375 } 4376 } 4377 4378 sal_Bool SvxIconChoiceCtrl_Impl::RequestHelp( const HelpEvent& rHEvt ) 4379 { 4380 if ( !(rHEvt.GetMode() & HELPMODE_QUICK ) ) 4381 return sal_False; 4382 4383 Point aPos( pView->ScreenToOutputPixel(rHEvt.GetMousePosPixel() ) ); 4384 aPos -= pView->GetMapMode().GetOrigin(); 4385 SvxIconChoiceCtrlEntry* pEntry = GetEntry( aPos, sal_True ); 4386 4387 if ( !pEntry ) 4388 return sal_False; 4389 4390 String sQuickHelpText = pEntry->GetQuickHelpText(); 4391 String aEntryText( pView->GetEntryText( pEntry, sal_False ) ); 4392 Rectangle aTextRect( CalcTextRect( pEntry, 0, sal_False, &aEntryText ) ); 4393 if ( ( !aTextRect.IsInside( aPos ) || !aEntryText.Len() ) && !sQuickHelpText.Len() ) 4394 return sal_False; 4395 4396 Rectangle aOptTextRect( aTextRect ); 4397 aOptTextRect.Bottom() = LONG_MAX; 4398 sal_uInt16 nNewFlags = nCurTextDrawFlags; 4399 nNewFlags &= ~( TEXT_DRAW_CLIP | TEXT_DRAW_ENDELLIPSIS ); 4400 aOptTextRect = pView->GetTextRect( aOptTextRect, aEntryText, nNewFlags ); 4401 if ( aOptTextRect != aTextRect || sQuickHelpText.Len() > 0 ) 4402 { 4403 //aTextRect.Right() = aTextRect.Left() + aRealSize.Width() + 4; 4404 Point aPt( aOptTextRect.TopLeft() ); 4405 aPt += pView->GetMapMode().GetOrigin(); 4406 aPt = pView->OutputToScreenPixel( aPt ); 4407 // Border der Tiphilfe abziehen 4408 aPt.Y() -= 1; 4409 aPt.X() -= 3; 4410 aOptTextRect.SetPos( aPt ); 4411 String sHelpText; 4412 if ( sQuickHelpText.Len() > 0 ) 4413 sHelpText = sQuickHelpText; 4414 else 4415 sHelpText = aEntryText; 4416 Help::ShowQuickHelp( (Window*)pView, aOptTextRect, sHelpText, QUICKHELP_LEFT | QUICKHELP_VCENTER ); 4417 } 4418 4419 return sal_True; 4420 } 4421 4422 void SvxIconChoiceCtrl_Impl::ClearColumnList() 4423 { 4424 if( !pColumns ) 4425 return; 4426 4427 const sal_uInt16 nCount = pColumns->Count(); 4428 for( sal_uInt16 nCur = 0; nCur < nCount; nCur++ ) 4429 { 4430 SvxIconChoiceCtrlColumnInfo* pInfo = (SvxIconChoiceCtrlColumnInfo*) 4431 pColumns->GetObject( nCur ); 4432 delete pInfo; 4433 } 4434 DELETEZ(pColumns); 4435 } 4436 4437 void SvxIconChoiceCtrl_Impl::SetColumn( sal_uInt16 nIndex, const SvxIconChoiceCtrlColumnInfo& rInfo) 4438 { 4439 if( !pColumns ) 4440 pColumns = new SvPtrarr; 4441 while( pColumns->Count() < nIndex + 1 ) 4442 pColumns->Insert( (void*)0, pColumns->Count() ); 4443 4444 SvxIconChoiceCtrlColumnInfo* pInfo = 4445 (SvxIconChoiceCtrlColumnInfo*)pColumns->GetObject(nIndex); 4446 if( !pInfo ) 4447 { 4448 pInfo = new SvxIconChoiceCtrlColumnInfo( rInfo ); 4449 pColumns->Insert( (void*)pInfo, nIndex ); 4450 } 4451 else 4452 { 4453 delete pInfo; 4454 pInfo = new SvxIconChoiceCtrlColumnInfo( rInfo ); 4455 pColumns->Replace( pInfo, nIndex ); 4456 } 4457 4458 // HACK(Detail-Modus ist noch nicht vollstaendig implementiert!) 4459 // dieses Workaround bringts mit einer Spalte zum Fliegen 4460 if( !nIndex && (nWinBits & WB_DETAILS) ) 4461 nGridDX = pInfo->GetWidth(); 4462 4463 if( GetUpdateMode() ) 4464 Arrange( IsAutoArrange() ); 4465 } 4466 4467 const SvxIconChoiceCtrlColumnInfo* SvxIconChoiceCtrl_Impl::GetColumn( sal_uInt16 nIndex ) const 4468 { 4469 if( !pColumns || nIndex >= pColumns->Count() ) 4470 return 0; 4471 return (const SvxIconChoiceCtrlColumnInfo*)pColumns->GetObject( nIndex ); 4472 } 4473 4474 const SvxIconChoiceCtrlColumnInfo* SvxIconChoiceCtrl_Impl::GetItemColumn( sal_uInt16 nSubItem, 4475 long& rLeft ) const 4476 { 4477 rLeft = 0; 4478 if( !pColumns ) 4479 return 0; 4480 const sal_uInt16 nCount = pColumns->Count(); 4481 const SvxIconChoiceCtrlColumnInfo* pCol = 0; 4482 for( sal_uInt16 nCur = 0; nCur < nCount; nCur++ ) 4483 { 4484 pCol = (const SvxIconChoiceCtrlColumnInfo*)pColumns->GetObject( nCur ); 4485 if( !pCol || pCol->GetSubItem() == nSubItem ) 4486 return pCol; 4487 rLeft += pCol->GetWidth(); 4488 } 4489 return pCol; 4490 } 4491 4492 void SvxIconChoiceCtrl_Impl::DrawHighlightFrame( 4493 OutputDevice* pOut, const Rectangle& rBmpRect, sal_Bool bHide ) 4494 { 4495 Rectangle aBmpRect( rBmpRect ); 4496 long nBorder = 2; 4497 if( aImageSize.Width() < 32 ) 4498 nBorder = 1; 4499 aBmpRect.Right() += nBorder; 4500 aBmpRect.Left() -= nBorder; 4501 aBmpRect.Bottom() += nBorder; 4502 aBmpRect.Top() -= nBorder; 4503 4504 if ( bHide ) 4505 pView->Invalidate( aBmpRect ); 4506 else 4507 { 4508 DecorationView aDecoView( pOut ); 4509 sal_uInt16 nDecoFlags; 4510 if ( bHighlightFramePressed ) 4511 nDecoFlags = FRAME_HIGHLIGHT_TESTBACKGROUND | FRAME_HIGHLIGHT_IN; 4512 else 4513 nDecoFlags = FRAME_HIGHLIGHT_TESTBACKGROUND | FRAME_HIGHLIGHT_OUT; 4514 aDecoView.DrawHighlightFrame( aBmpRect, nDecoFlags ); 4515 } 4516 } 4517 4518 void SvxIconChoiceCtrl_Impl::SetEntryHighlightFrame( SvxIconChoiceCtrlEntry* pEntry, 4519 sal_Bool bKeepHighlightFlags ) 4520 { 4521 if( pEntry == pCurHighlightFrame ) 4522 return; 4523 4524 if( !bKeepHighlightFlags ) 4525 bHighlightFramePressed = sal_False; 4526 4527 HideEntryHighlightFrame(); 4528 pCurHighlightFrame = pEntry; 4529 if( pEntry ) 4530 { 4531 Rectangle aBmpRect( CalcFocusRect(pEntry) ); 4532 DrawHighlightFrame( pView, aBmpRect, sal_False ); 4533 } 4534 } 4535 4536 void SvxIconChoiceCtrl_Impl::HideEntryHighlightFrame() 4537 { 4538 if( !pCurHighlightFrame ) 4539 return; 4540 4541 SvxIconChoiceCtrlEntry* pEntry = pCurHighlightFrame; 4542 pCurHighlightFrame = 0; 4543 Rectangle aBmpRect( CalcFocusRect(pEntry) ); 4544 DrawHighlightFrame( pView, aBmpRect, sal_True ); 4545 } 4546 4547 void SvxIconChoiceCtrl_Impl::CallSelectHandler( SvxIconChoiceCtrlEntry* ) 4548 { 4549 // Bei aktiviertem Single-Click-Modus sollte der Selektionshandler 4550 // synchron gerufen werden, weil die Selektion automatisch 4551 // weggenommen wird, wenn der Mauszeiger nicht mehr das Objekt 4552 // beruehrt. Es kann sonst zu fehlenden Select-Aufrufen kommen, 4553 // wenn das Objekt aus einer Mausbewegung heraus selektiert wird, 4554 // weil beim Ausloesen des Timers der Mauszeiger das Objekt u.U. 4555 // schon verlassen hat. 4556 // Fuer spezielle Faelle (=>SfxFileDialog!) koennen synchrone 4557 // Aufrufe auch per WB_NOASYNCSELECTHDL erzwungen werden. 4558 if( nWinBits & (WB_NOASYNCSELECTHDL | WB_HIGHLIGHTFRAME) ) 4559 { 4560 pHdlEntry = 0; 4561 pView->ClickIcon(); 4562 //pView->Select(); 4563 } 4564 else 4565 aCallSelectHdlTimer.Start(); 4566 } 4567 4568 IMPL_LINK( SvxIconChoiceCtrl_Impl, CallSelectHdlHdl, void*, EMPTYARG ) 4569 { 4570 pHdlEntry = 0; 4571 pView->ClickIcon(); 4572 //pView->Select(); 4573 return 0; 4574 } 4575 4576 Point SvxIconChoiceCtrl_Impl::GetPopupMenuPosPixel() const 4577 { 4578 Point aResult; 4579 if( !GetSelectionCount() ) 4580 return aResult; 4581 4582 SvxIconChoiceCtrlEntry* pEntry = GetCurEntry(); 4583 if( !pEntry || !pEntry->IsSelected() ) 4584 { 4585 sal_uLong nNext; 4586 pEntry = GetFirstSelectedEntry( nNext ); 4587 } 4588 if( pEntry ) 4589 { 4590 Rectangle aRect( ((SvxIconChoiceCtrl_Impl*)this)->CalcBmpRect( pEntry ) ); 4591 aResult = aRect.Center(); 4592 aResult = pView->GetPixelPos( aResult ); 4593 } 4594 return aResult; 4595 } 4596 4597 void SvxIconChoiceCtrl_Impl::SetOrigin( const Point& rPos, sal_Bool bDoNotUpdateWallpaper ) 4598 { 4599 MapMode aMapMode( pView->GetMapMode() ); 4600 aMapMode.SetOrigin( rPos ); 4601 pView->SetMapMode( aMapMode ); 4602 if( !bDoNotUpdateWallpaper ) 4603 { 4604 sal_Bool bScrollable = pView->GetBackground().IsScrollable(); 4605 if( pView->HasBackground() && !bScrollable ) 4606 { 4607 Rectangle aRect( GetOutputRect()); 4608 Wallpaper aPaper( pView->GetBackground() ); 4609 aPaper.SetRect( aRect ); 4610 pView->SetBackground( aPaper ); 4611 } 4612 } 4613 } 4614 4615 sal_uLong SvxIconChoiceCtrl_Impl::GetGridCount( const Size& rSize, sal_Bool bCheckScrBars, 4616 sal_Bool bSmartScrBar ) const 4617 { 4618 Size aSize( rSize ); 4619 if( bCheckScrBars && aHorSBar.IsVisible() ) 4620 aSize.Height() -= nHorSBarHeight; 4621 else if( bSmartScrBar && (nWinBits & WB_ALIGN_LEFT) ) 4622 aSize.Height() -= nHorSBarHeight; 4623 4624 if( bCheckScrBars && aVerSBar.IsVisible() ) 4625 aSize.Width() -= nVerSBarWidth; 4626 else if( bSmartScrBar && (nWinBits & WB_ALIGN_TOP) ) 4627 aSize.Width() -= nVerSBarWidth; 4628 4629 if( aSize.Width() < 0 ) 4630 aSize.Width() = 0; 4631 if( aSize.Height() < 0 ) 4632 aSize.Height() = 0; 4633 4634 return IcnGridMap_Impl::GetGridCount( aSize, (sal_uInt16)nGridDX, (sal_uInt16)nGridDY ); 4635 } 4636 4637 sal_Bool SvxIconChoiceCtrl_Impl::HandleShortCutKey( const KeyEvent& rKEvt ) 4638 { 4639 StopEditTimer(); 4640 4641 sal_Bool bRet = sal_False; 4642 4643 DBG_ASSERT( rKEvt.GetKeyCode().IsMod2(), "*SvxIconChoiceCtrl_Impl::HandleShortCutKey(): no <ALT> pressed!?" ); 4644 4645 sal_Unicode cChar = rKEvt.GetCharCode(); 4646 sal_uLong nPos = (sal_uLong)-1; 4647 4648 if( cChar && IsMnemonicChar( cChar, nPos ) ) 4649 { 4650 // shortcut is clicked 4651 SvxIconChoiceCtrlEntry* pNewCursor = GetEntry( nPos ); 4652 SvxIconChoiceCtrlEntry* pOldCursor = pCursor; 4653 if( pNewCursor != pOldCursor ) 4654 { 4655 SetCursor_Impl( pOldCursor, pNewCursor, sal_False, sal_False, sal_False ); 4656 4657 if( pNewCursor != NULL ) 4658 { 4659 pHdlEntry = pNewCursor; 4660 pCurHighlightFrame = pHdlEntry; 4661 pView->ClickIcon(); 4662 pCurHighlightFrame = NULL; 4663 } 4664 } 4665 bRet = sal_True; 4666 } 4667 4668 return bRet; 4669 } 4670 4671 // ----------------------------------------------------------------------- 4672 4673 void SvxIconChoiceCtrl_Impl::CallEventListeners( sal_uLong nEvent, void* pData ) 4674 { 4675 pView->CallImplEventListeners( nEvent, pData ); 4676 } 4677 4678 4679