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 } 1184 } 1185 } 1186 1187 sal_Bool SvxIconChoiceCtrl_Impl::KeyInput( const KeyEvent& rKEvt ) 1188 { 1189 StopEditTimer(); 1190 1191 sal_Bool bMod2 = rKEvt.GetKeyCode().IsMod2(); 1192 sal_Unicode cChar = rKEvt.GetCharCode(); 1193 sal_uLong nPos = (sal_uLong)-1; 1194 if ( bMod2 && cChar && IsMnemonicChar( cChar, nPos ) ) 1195 { 1196 // shortcut is clicked 1197 SvxIconChoiceCtrlEntry* pNewCursor = GetEntry( nPos ); 1198 SvxIconChoiceCtrlEntry* pOldCursor = pCursor; 1199 if ( pNewCursor != pOldCursor ) 1200 SetCursor_Impl( pOldCursor, pNewCursor, sal_False, sal_False, sal_False ); 1201 return sal_True; 1202 } 1203 1204 if ( bMod2 ) 1205 // no actions with <ALT> 1206 return sal_False; 1207 1208 sal_Bool bKeyUsed = sal_True; 1209 sal_Bool bMod1 = rKEvt.GetKeyCode().IsMod1(); 1210 sal_Bool bShift = rKEvt.GetKeyCode().IsShift(); 1211 1212 if( eSelectionMode == SINGLE_SELECTION || eSelectionMode == NO_SELECTION) 1213 { 1214 bShift = sal_False; 1215 bMod1 = sal_False; 1216 } 1217 1218 if( bMod1 ) 1219 nFlags |= F_ADD_MODE; 1220 sal_Bool bDeselectAll = sal_False; 1221 if( eSelectionMode != SINGLE_SELECTION ) 1222 { 1223 if( !bMod1 && !bShift ) 1224 bDeselectAll = sal_True; 1225 if( bShift && !bMod1 && !pAnchor ) 1226 bDeselectAll = sal_True; 1227 } 1228 1229 SvxIconChoiceCtrlEntry* pNewCursor; 1230 SvxIconChoiceCtrlEntry* pOldCursor = pCursor; 1231 1232 sal_uInt16 nCode = rKEvt.GetKeyCode().GetCode(); 1233 switch( nCode ) 1234 { 1235 case KEY_UP: 1236 case KEY_PAGEUP: 1237 if( pCursor ) 1238 { 1239 MakeEntryVisible( pCursor ); 1240 if( nCode == KEY_UP ) 1241 pNewCursor = pImpCursor->GoUpDown(pCursor,sal_False); 1242 else 1243 pNewCursor = pImpCursor->GoPageUpDown(pCursor,sal_False); 1244 SetCursor_Impl( pOldCursor, pNewCursor, bMod1, bShift, sal_True ); 1245 if( !pNewCursor ) 1246 { 1247 Rectangle aRect( GetEntryBoundRect( pCursor ) ); 1248 if( aRect.Top()) 1249 { 1250 aRect.Bottom() -= aRect.Top(); 1251 aRect.Top() = 0; 1252 MakeVisible( aRect ); 1253 } 1254 } 1255 1256 if ( bChooseWithCursor && pNewCursor != NULL ) 1257 { 1258 pHdlEntry = pNewCursor;//GetCurEntry(); 1259 pCurHighlightFrame = pHdlEntry; 1260 pView->ClickIcon(); 1261 pCurHighlightFrame = NULL; 1262 } 1263 } 1264 break; 1265 1266 case KEY_DOWN: 1267 case KEY_PAGEDOWN: 1268 if( pCursor ) 1269 { 1270 if( nCode == KEY_DOWN ) 1271 pNewCursor=pImpCursor->GoUpDown( pCursor,sal_True ); 1272 else 1273 pNewCursor=pImpCursor->GoPageUpDown( pCursor,sal_True ); 1274 SetCursor_Impl( pOldCursor, pNewCursor, bMod1, bShift, sal_True ); 1275 1276 if ( bChooseWithCursor && pNewCursor != NULL) 1277 { 1278 pHdlEntry = pNewCursor;//GetCurEntry(); 1279 pCurHighlightFrame = pHdlEntry; 1280 pView->ClickIcon(); 1281 pCurHighlightFrame = NULL; 1282 } 1283 } 1284 break; 1285 1286 case KEY_RIGHT: 1287 if( pCursor ) 1288 { 1289 pNewCursor=pImpCursor->GoLeftRight(pCursor,sal_True ); 1290 SetCursor_Impl( pOldCursor, pNewCursor, bMod1, bShift, sal_True ); 1291 } 1292 break; 1293 1294 case KEY_LEFT: 1295 if( pCursor ) 1296 { 1297 MakeEntryVisible( pCursor ); 1298 pNewCursor = pImpCursor->GoLeftRight(pCursor,sal_False ); 1299 SetCursor_Impl( pOldCursor, pNewCursor, bMod1, bShift, sal_True ); 1300 if( !pNewCursor ) 1301 { 1302 Rectangle aRect( GetEntryBoundRect(pCursor)); 1303 if( aRect.Left() ) 1304 { 1305 aRect.Right() -= aRect.Left(); 1306 aRect.Left() = 0; 1307 MakeVisible( aRect ); 1308 } 1309 } 1310 } 1311 break; 1312 1313 // wird vom VCL-Tracking gesteuert 1314 #if 0 1315 case KEY_ESCAPE: 1316 if( pView->IsTracking() ) 1317 { 1318 HideSelectionRect(); 1319 //SelectAll( sal_False ); 1320 SetNoSelection(); 1321 ClearSelectedRectList(); 1322 nFlags &= ~F_TRACKING; 1323 } 1324 else 1325 bKeyUsed = sal_False; 1326 break; 1327 #endif 1328 1329 1330 case KEY_F2: 1331 if( !bMod1 && !bShift ) 1332 EditTimeoutHdl( 0 ); 1333 else 1334 bKeyUsed = sal_False; 1335 break; 1336 1337 case KEY_F8: 1338 if( rKEvt.GetKeyCode().IsShift() ) 1339 { 1340 if( nFlags & F_ADD_MODE ) 1341 nFlags &= (~F_ADD_MODE); 1342 else 1343 nFlags |= F_ADD_MODE; 1344 } 1345 else 1346 bKeyUsed = sal_False; 1347 break; 1348 1349 case KEY_SPACE: 1350 if( pCursor && eSelectionMode != SINGLE_SELECTION ) 1351 { 1352 if( !bMod1 ) 1353 { 1354 //SelectAll( sal_False ); 1355 SetNoSelection(); 1356 ClearSelectedRectList(); 1357 1358 // click Icon with spacebar 1359 SetEntryHighlightFrame( GetCurEntry(), sal_True ); 1360 pView->ClickIcon(); 1361 pHdlEntry = pCurHighlightFrame; 1362 pCurHighlightFrame=0; 1363 } 1364 else 1365 ToggleSelection( pCursor ); 1366 } 1367 break; 1368 1369 #ifdef DBG_UTIL 1370 case KEY_F10: 1371 if( rKEvt.GetKeyCode().IsShift() ) 1372 { 1373 if( pCursor ) 1374 pView->SetEntryTextMode( IcnShowTextFull, pCursor ); 1375 } 1376 if( rKEvt.GetKeyCode().IsMod1() ) 1377 { 1378 if( pCursor ) 1379 pView->SetEntryTextMode( IcnShowTextShort, pCursor ); 1380 } 1381 break; 1382 #endif 1383 1384 case KEY_ADD: 1385 case KEY_DIVIDE : 1386 case KEY_A: 1387 if( bMod1 && (eSelectionMode != SINGLE_SELECTION)) 1388 SelectAll( sal_True ); 1389 else 1390 bKeyUsed = sal_False; 1391 break; 1392 1393 case KEY_SUBTRACT: 1394 case KEY_COMMA : 1395 if( bMod1 ) 1396 SetNoSelection(); 1397 else 1398 bKeyUsed = sal_False; 1399 break; 1400 1401 case KEY_RETURN: 1402 if( bMod1 ) 1403 { 1404 if( pCursor && bEntryEditingEnabled ) 1405 /*pView->*/EditEntry( pCursor ); 1406 } 1407 else 1408 bKeyUsed = sal_False; 1409 break; 1410 1411 case KEY_END: 1412 if( pCursor ) 1413 { 1414 pNewCursor = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( aEntries.Count() - 1 ); 1415 SetCursor_Impl( pOldCursor, pNewCursor, bMod1, bShift, sal_True ); 1416 } 1417 break; 1418 1419 case KEY_HOME: 1420 if( pCursor ) 1421 { 1422 pNewCursor = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( 0 ); 1423 SetCursor_Impl( pOldCursor, pNewCursor, bMod1, bShift, sal_True ); 1424 } 1425 break; 1426 1427 default: 1428 bKeyUsed = sal_False; 1429 1430 } 1431 return bKeyUsed; 1432 } 1433 1434 // Berechnet TopLeft der Scrollbars (nicht ihre Groessen!) 1435 void SvxIconChoiceCtrl_Impl::PositionScrollBars( long nRealWidth, long nRealHeight ) 1436 { 1437 // hor scrollbar 1438 Point aPos( 0, nRealHeight ); 1439 aPos.Y() -= nHorSBarHeight; 1440 1441 if( aHorSBar.GetPosPixel() != aPos ) 1442 aHorSBar.SetPosPixel( aPos ); 1443 1444 // ver scrollbar 1445 aPos.X() = nRealWidth; aPos.Y() = 0; 1446 aPos.X() -= nVerSBarWidth; 1447 aPos.X()++; 1448 aPos.Y()--; 1449 1450 if( aVerSBar.GetPosPixel() != aPos ) 1451 aVerSBar.SetPosPixel( aPos ); 1452 } 1453 1454 void SvxIconChoiceCtrl_Impl::AdjustScrollBars( sal_Bool ) 1455 { 1456 Rectangle aOldOutRect( GetOutputRect() ); 1457 long nVirtHeight = aVirtOutputSize.Height(); 1458 long nVirtWidth = aVirtOutputSize.Width(); 1459 1460 Size aOSize( pView->Control::GetOutputSizePixel() ); 1461 long nRealHeight = aOSize.Height(); 1462 long nRealWidth = aOSize.Width(); 1463 1464 PositionScrollBars( nRealWidth, nRealHeight ); 1465 1466 const MapMode& rMapMode = pView->GetMapMode(); 1467 Point aOrigin( rMapMode.GetOrigin() ); 1468 1469 long nVisibleWidth; 1470 if( nRealWidth > nVirtWidth ) 1471 nVisibleWidth = nVirtWidth + aOrigin.X(); 1472 else 1473 nVisibleWidth = nRealWidth; 1474 1475 long nVisibleHeight; 1476 if( nRealHeight > nVirtHeight ) 1477 nVisibleHeight = nVirtHeight + aOrigin.Y(); 1478 else 1479 nVisibleHeight = nRealHeight; 1480 1481 sal_Bool bVerSBar = ( nWinBits & WB_VSCROLL ) != 0; 1482 sal_Bool bHorSBar = ( nWinBits & WB_HSCROLL ) != 0; 1483 sal_Bool bNoVerSBar = ( nWinBits & WB_NOVSCROLL ) != 0; 1484 sal_Bool bNoHorSBar = ( nWinBits & WB_NOHSCROLL ) != 0; 1485 1486 sal_uInt16 nResult = 0; 1487 if( nVirtHeight ) 1488 { 1489 // activate ver scrollbar ? 1490 if( !bNoVerSBar && (bVerSBar || ( nVirtHeight > nVisibleHeight)) ) 1491 { 1492 nResult = 0x0001; 1493 nRealWidth -= nVerSBarWidth; 1494 1495 if( nRealWidth > nVirtWidth ) 1496 nVisibleWidth = nVirtWidth + aOrigin.X(); 1497 else 1498 nVisibleWidth = nRealWidth; 1499 1500 nFlags |= F_HOR_SBARSIZE_WITH_VBAR; 1501 } 1502 // activate hor scrollbar ? 1503 if( !bNoHorSBar && (bHorSBar || (nVirtWidth > nVisibleWidth)) ) 1504 { 1505 nResult |= 0x0002; 1506 nRealHeight -= nHorSBarHeight; 1507 1508 if( nRealHeight > nVirtHeight ) 1509 nVisibleHeight = nVirtHeight + aOrigin.Y(); 1510 else 1511 nVisibleHeight = nRealHeight; 1512 1513 // brauchen wir jetzt doch eine senkrechte Scrollbar ? 1514 if( !(nResult & 0x0001) && // nur wenn nicht schon da 1515 ( !bNoVerSBar && ((nVirtHeight > nVisibleHeight) || bVerSBar)) ) 1516 { 1517 nResult = 3; // beide sind an 1518 nRealWidth -= nVerSBarWidth; 1519 1520 if( nRealWidth > nVirtWidth ) 1521 nVisibleWidth = nVirtWidth + aOrigin.X(); 1522 else 1523 nVisibleWidth = nRealWidth; 1524 1525 nFlags |= F_VER_SBARSIZE_WITH_HBAR; 1526 } 1527 } 1528 } 1529 1530 // size ver scrollbar 1531 long nThumb = aVerSBar.GetThumbPos(); 1532 Size aSize( nVerSBarWidth, nRealHeight ); 1533 aSize.Height() += 2; 1534 if( aSize != aVerSBar.GetSizePixel() ) 1535 aVerSBar.SetSizePixel( aSize ); 1536 aVerSBar.SetVisibleSize( nVisibleHeight ); 1537 aVerSBar.SetPageSize( GetScrollBarPageSize( nVisibleHeight )); 1538 1539 if( nResult & 0x0001 ) 1540 { 1541 aVerSBar.SetThumbPos( nThumb ); 1542 aVerSBar.Show(); 1543 } 1544 else 1545 { 1546 aVerSBar.SetThumbPos( 0 ); 1547 aVerSBar.Hide(); 1548 } 1549 1550 // size hor scrollbar 1551 nThumb = aHorSBar.GetThumbPos(); 1552 aSize.Width() = nRealWidth; 1553 aSize.Height() = nHorSBarHeight; 1554 aSize.Width()++; 1555 if( nResult & 0x0001 ) // vertikale Scrollbar ? 1556 { 1557 aSize.Width()++; 1558 nRealWidth++; 1559 } 1560 if( aSize != aHorSBar.GetSizePixel() ) 1561 aHorSBar.SetSizePixel( aSize ); 1562 aHorSBar.SetVisibleSize( nVisibleWidth ); 1563 aHorSBar.SetPageSize( GetScrollBarPageSize(nVisibleWidth )); 1564 if( nResult & 0x0002 ) 1565 { 1566 aHorSBar.SetThumbPos( nThumb ); 1567 aHorSBar.Show(); 1568 } 1569 else 1570 { 1571 aHorSBar.SetThumbPos( 0 ); 1572 aHorSBar.Hide(); 1573 } 1574 1575 aOutputSize.Width() = nRealWidth; 1576 if( nResult & 0x0002 ) // hor scrollbar ? 1577 nRealHeight++; // weil unterer Rand geclippt wird 1578 aOutputSize.Height() = nRealHeight; 1579 1580 Rectangle aNewOutRect( GetOutputRect() ); 1581 if( aNewOutRect != aOldOutRect && pView->HasBackground() ) 1582 { 1583 Wallpaper aPaper( pView->GetBackground() ); 1584 aPaper.SetRect( aNewOutRect ); 1585 pView->SetBackground( aPaper ); 1586 } 1587 1588 if( (nResult & (0x0001|0x0002)) == (0x0001|0x0002) ) 1589 aScrBarBox.Show(); 1590 else 1591 aScrBarBox.Hide(); 1592 } 1593 1594 void SvxIconChoiceCtrl_Impl::Resize() 1595 { 1596 StopEditTimer(); 1597 InitScrollBarBox(); 1598 aOutputSize = pView->GetOutputSizePixel(); 1599 pImpCursor->Clear(); 1600 pGridMap->OutputSizeChanged(); 1601 1602 const Size& rSize = pView->Control::GetOutputSizePixel(); 1603 PositionScrollBars( rSize.Width(), rSize.Height() ); 1604 // Die ScrollBars werden asynchron ein/ausgeblendet, damit abgeleitete 1605 // Klassen im Resize ein Arrange durchfuehren koennen, ohne dass 1606 // die ScrollBars aufblitzen 1607 // Wenn schon ein Event unterwegs ist, dann braucht kein neues verschickt werden, 1608 // zumindest, solange es nur einen EventTypen gibt 1609 if ( ! nUserEventAdjustScrBars ) 1610 nUserEventAdjustScrBars = 1611 Application::PostUserEvent( LINK( this, SvxIconChoiceCtrl_Impl, UserEventHdl), 1612 EVENTID_ADJUST_SCROLLBARS); 1613 1614 if( pView->HasBackground() && !pView->GetBackground().IsScrollable() ) 1615 { 1616 Rectangle aRect( GetOutputRect()); 1617 Wallpaper aPaper( pView->GetBackground() ); 1618 aPaper.SetRect( aRect ); 1619 pView->SetBackground( aPaper ); 1620 } 1621 VisRectChanged(); 1622 } 1623 1624 sal_Bool SvxIconChoiceCtrl_Impl::CheckHorScrollBar() 1625 { 1626 if( !pZOrderList || !aHorSBar.IsVisible() ) 1627 return sal_False; 1628 const MapMode& rMapMode = pView->GetMapMode(); 1629 Point aOrigin( rMapMode.GetOrigin() ); 1630 if(!( nWinBits & WB_HSCROLL) && !aOrigin.X() ) 1631 { 1632 long nWidth = aOutputSize.Width(); 1633 const sal_uLong nCount = pZOrderList->Count(); 1634 long nMostRight = 0; 1635 for( sal_uLong nCur = 0; nCur < nCount; nCur++ ) 1636 { 1637 SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)pZOrderList->GetObject(nCur); 1638 long nRight = GetEntryBoundRect(pEntry).Right(); 1639 if( nRight > nWidth ) 1640 return sal_False; 1641 if( nRight > nMostRight ) 1642 nMostRight = nRight; 1643 } 1644 aHorSBar.Hide(); 1645 aOutputSize.Height() += nHorSBarHeight; 1646 aVirtOutputSize.Width() = nMostRight; 1647 aHorSBar.SetThumbPos( 0 ); 1648 Range aRange; 1649 aRange.Max() = nMostRight - 1; 1650 aHorSBar.SetRange( aRange ); 1651 if( aVerSBar.IsVisible() ) 1652 { 1653 Size aSize( aVerSBar.GetSizePixel()); 1654 aSize.Height() += nHorSBarHeight; 1655 aVerSBar.SetSizePixel( aSize ); 1656 } 1657 return sal_True; 1658 } 1659 return sal_False; 1660 } 1661 1662 sal_Bool SvxIconChoiceCtrl_Impl::CheckVerScrollBar() 1663 { 1664 if( !pZOrderList || !aVerSBar.IsVisible() ) 1665 return sal_False; 1666 const MapMode& rMapMode = pView->GetMapMode(); 1667 Point aOrigin( rMapMode.GetOrigin() ); 1668 if(!( nWinBits & WB_VSCROLL) && !aOrigin.Y() ) 1669 { 1670 long nDeepest = 0; 1671 long nHeight = aOutputSize.Height(); 1672 const sal_uLong nCount = pZOrderList->Count(); 1673 for( sal_uLong nCur = 0; nCur < nCount; nCur++ ) 1674 { 1675 SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)pZOrderList->GetObject(nCur); 1676 long nBottom = GetEntryBoundRect(pEntry).Bottom(); 1677 if( nBottom > nHeight ) 1678 return sal_False; 1679 if( nBottom > nDeepest ) 1680 nDeepest = nBottom; 1681 } 1682 aVerSBar.Hide(); 1683 aOutputSize.Width() += nVerSBarWidth; 1684 aVirtOutputSize.Height() = nDeepest; 1685 aVerSBar.SetThumbPos( 0 ); 1686 Range aRange; 1687 aRange.Max() = nDeepest - 1; 1688 aVerSBar.SetRange( aRange ); 1689 if( aHorSBar.IsVisible() ) 1690 { 1691 Size aSize( aHorSBar.GetSizePixel()); 1692 aSize.Width() += nVerSBarWidth; 1693 aHorSBar.SetSizePixel( aSize ); 1694 } 1695 return sal_True; 1696 } 1697 return sal_False; 1698 } 1699 1700 1701 // blendet Scrollbars aus, wenn sie nicht mehr benoetigt werden 1702 void SvxIconChoiceCtrl_Impl::CheckScrollBars() 1703 { 1704 CheckVerScrollBar(); 1705 if( CheckHorScrollBar() ) 1706 CheckVerScrollBar(); 1707 if( aVerSBar.IsVisible() && aHorSBar.IsVisible() ) 1708 aScrBarBox.Show(); 1709 else 1710 aScrBarBox.Hide(); 1711 } 1712 1713 1714 void SvxIconChoiceCtrl_Impl::GetFocus() 1715 { 1716 RepaintEntries( ICNVIEW_FLAG_SELECTED ); 1717 if( pCursor ) 1718 { 1719 pCursor->SetFlags( ICNVIEW_FLAG_FOCUSED ); 1720 ShowCursor( sal_True ); 1721 } 1722 } 1723 1724 void SvxIconChoiceCtrl_Impl::LoseFocus() 1725 { 1726 StopEditTimer(); 1727 if( pCursor ) 1728 pCursor->ClearFlags( ICNVIEW_FLAG_FOCUSED ); 1729 ShowCursor( sal_False ); 1730 1731 // HideFocus (); 1732 // pView->Invalidate ( aFocus.aRect ); 1733 1734 RepaintEntries( ICNVIEW_FLAG_SELECTED ); 1735 } 1736 1737 void SvxIconChoiceCtrl_Impl::SetUpdateMode( sal_Bool bUpdate ) 1738 { 1739 if( bUpdate != bUpdateMode ) 1740 { 1741 bUpdateMode = bUpdate; 1742 if( bUpdate ) 1743 { 1744 AdjustScrollBars(); 1745 pImpCursor->Clear(); 1746 pGridMap->Clear(); 1747 pView->Invalidate(INVALIDATE_NOCHILDREN); 1748 } 1749 } 1750 } 1751 1752 void SvxIconChoiceCtrl_Impl::PaintEntry( SvxIconChoiceCtrlEntry* pEntry, sal_Bool bIsBackgroundPainted ) 1753 { 1754 Point aPos( GetEntryPos( pEntry ) ); 1755 PaintEntry( pEntry, aPos, 0, bIsBackgroundPainted ); 1756 } 1757 1758 // Prios der Emphasis: bDropTarget => bCursored => bSelected 1759 void SvxIconChoiceCtrl_Impl::PaintEmphasis( 1760 const Rectangle& rTextRect, const Rectangle& rImageRect, 1761 sal_Bool bSelected, sal_Bool bDropTarget, sal_Bool bCursored, OutputDevice* pOut, 1762 sal_Bool bIsBackgroundPainted ) 1763 { 1764 static Color aTransparent( COL_TRANSPARENT ); 1765 1766 if( !pOut ) 1767 pOut = pView; 1768 1769 #ifdef OV_CHECK_EMPH_RECTS 1770 { 1771 Color aXOld( pOut->GetFillColor() ); 1772 pOut->SetFillColor( Color( COL_GREEN )); 1773 pOut->DrawRect( rTextRect ); 1774 pOut->DrawRect( rImageRect ); 1775 pOut->SetFillColor( aXOld ); 1776 } 1777 #endif 1778 1779 const StyleSettings& rSettings = pOut->GetSettings().GetStyleSettings(); 1780 Color aOldFillColor( pOut->GetFillColor() ); 1781 1782 sal_Bool bSolidTextRect = sal_False; 1783 sal_Bool bSolidImageRect = sal_False; 1784 1785 if( bDropTarget && ( eSelectionMode != NO_SELECTION ) ) 1786 { 1787 pOut->SetFillColor( rSettings.GetHighlightColor() ); 1788 bSolidTextRect = sal_True; 1789 bSolidImageRect = sal_True; 1790 } 1791 else 1792 { 1793 if ( !bSelected || bCursored ) 1794 { 1795 if( !pView->HasFontFillColor() ) 1796 pOut->SetFillColor( pOut->GetBackground().GetColor() ); 1797 else 1798 { 1799 const Color& rFillColor = pView->GetFont().GetFillColor(); 1800 pOut->SetFillColor( rFillColor ); 1801 if( rFillColor != aTransparent ) 1802 bSolidTextRect = sal_True; 1803 } 1804 } 1805 } 1806 1807 // Textrechteck zeichnen 1808 if( !bSolidTextRect ) 1809 { 1810 if( !bIsBackgroundPainted ) 1811 pOut->Erase( rTextRect ); 1812 } 1813 else 1814 { 1815 Color aOldLineColor; 1816 if( bCursored ) 1817 { 1818 aOldLineColor = pOut->GetLineColor(); 1819 pOut->SetLineColor( Color( COL_GRAY ) ); 1820 } 1821 pOut->DrawRect( rTextRect ); 1822 if( bCursored ) 1823 pOut->SetLineColor( aOldLineColor ); 1824 } 1825 1826 // Bildrechteck zeichnen 1827 if( !bSolidImageRect ) 1828 { 1829 if( !bIsBackgroundPainted ) 1830 pOut->Erase( rImageRect ); 1831 } 1832 // die Emphasis des Images muss von der abgeleiteten Klasse gezeichnet werden 1833 // (in der virtuellen Funktion DrawEntryImage) 1834 // else 1835 // pOut->DrawRect( rImageRect ); 1836 1837 pOut->SetFillColor( aOldFillColor ); 1838 } 1839 1840 1841 void SvxIconChoiceCtrl_Impl::PaintItem( const Rectangle& rRect, 1842 IcnViewFieldType eItem, SvxIconChoiceCtrlEntry* pEntry, sal_uInt16 nPaintFlags, 1843 OutputDevice* pOut, const String* pStr, ::vcl::ControlLayoutData* _pLayoutData ) 1844 { 1845 if( eItem == IcnViewFieldTypeText ) 1846 { 1847 String aText; 1848 if( !pStr ) 1849 aText = pView->GetEntryText( pEntry, sal_False ); 1850 else 1851 aText = *pStr; 1852 1853 if ( _pLayoutData ) 1854 { 1855 pOut->DrawText( rRect, aText, nCurTextDrawFlags, 1856 &_pLayoutData->m_aUnicodeBoundRects, &_pLayoutData->m_aDisplayText ); 1857 } 1858 else 1859 { 1860 Color aOldFontColor = pOut->GetTextColor(); 1861 if ( pView->AutoFontColor() ) 1862 { 1863 Color aBkgColor( pOut->GetBackground().GetColor() ); 1864 Color aFontColor; 1865 sal_uInt16 nColor = ( aBkgColor.GetRed() + aBkgColor.GetGreen() + aBkgColor.GetBlue() ) / 3; 1866 if ( nColor > 127 ) 1867 aFontColor.SetColor ( COL_BLACK ); 1868 else 1869 aFontColor.SetColor( COL_WHITE ); 1870 pOut->SetTextColor( aFontColor ); 1871 } 1872 1873 pOut->DrawText( rRect, aText, nCurTextDrawFlags ); 1874 1875 if ( pView->AutoFontColor() ) 1876 pOut->SetTextColor( aOldFontColor ); 1877 1878 if( pEntry->IsFocused() ) 1879 { 1880 Rectangle aRect ( CalcFocusRect( (SvxIconChoiceCtrlEntry*)pEntry ) ); 1881 /*pView->*/ShowFocus( aRect ); 1882 DrawFocusRect( pOut ); 1883 } 1884 } 1885 } 1886 else 1887 { 1888 Point aPos( rRect.TopLeft() ); 1889 if( nPaintFlags & PAINTFLAG_HOR_CENTERED ) 1890 aPos.X() += (rRect.GetWidth() - aImageSize.Width() ) / 2; 1891 if( nPaintFlags & PAINTFLAG_VER_CENTERED ) 1892 aPos.Y() += (rRect.GetHeight() - aImageSize.Height() ) / 2; 1893 pView->DrawEntryImage( pEntry, aPos, *pOut ); 1894 } 1895 } 1896 1897 void SvxIconChoiceCtrl_Impl::PaintEntryVirtOutDev( SvxIconChoiceCtrlEntry* pEntry ) 1898 { 1899 #ifdef OV_NO_VIRT_OUTDEV 1900 PaintEntry( pEntry ); 1901 #else 1902 if( !pEntryPaintDev ) 1903 { 1904 pEntryPaintDev = new VirtualDevice( *pView ); 1905 pEntryPaintDev->SetFont( pView->GetFont() ); 1906 pEntryPaintDev->SetLineColor(); 1907 //pEntryPaintDev->SetBackground( pView->GetBackground() ); 1908 } 1909 const Rectangle& rRect = GetEntryBoundRect( pEntry ); 1910 Rectangle aOutRect( GetOutputRect() ); 1911 if( !rRect.IsOver( aOutRect ) ) 1912 return; 1913 Wallpaper aPaper( pView->GetBackground() ); 1914 Rectangle aRect( aPaper.GetRect() ); 1915 1916 // Rechteck verschieben, so dass das Boundrect des Entries im 1917 // VirtOut-Dev bei 0,0 liegt. 1918 aRect.Move( -rRect.Left(), -rRect.Top() ); 1919 aPaper.SetRect( aRect ); 1920 pEntryPaintDev->SetBackground( aPaper ); 1921 pEntryPaintDev->SetFont( pView->GetFont() ); 1922 Rectangle aPix ( pEntryPaintDev->LogicToPixel(aRect) ); 1923 1924 1925 Size aSize( rRect.GetSize() ); 1926 pEntryPaintDev->SetOutputSizePixel( aSize ); 1927 pEntryPaintDev->DrawOutDev( 1928 Point(), aSize, rRect.TopLeft(), aSize, *pView ); 1929 1930 PaintEntry( pEntry, Point(), pEntryPaintDev ); 1931 1932 pView->DrawOutDev( 1933 rRect.TopLeft(), 1934 aSize, 1935 Point(), 1936 aSize, 1937 *pEntryPaintDev ); 1938 #endif 1939 } 1940 1941 1942 void SvxIconChoiceCtrl_Impl::PaintEntry( SvxIconChoiceCtrlEntry* pEntry, const Point& rPos, 1943 OutputDevice* pOut, sal_Bool bIsBackgroundPainted ) 1944 { 1945 if( !pOut ) 1946 pOut = pView; 1947 1948 sal_Bool bSelected = sal_False; 1949 1950 if( eSelectionMode != NO_SELECTION ) 1951 bSelected = pEntry->IsSelected(); 1952 1953 sal_Bool bCursored = pEntry->IsCursored(); 1954 sal_Bool bDropTarget = pEntry->IsDropTarget(); 1955 sal_Bool bNoEmphasis = pEntry->IsBlockingEmphasis(); 1956 1957 Font aTempFont( pOut->GetFont() ); 1958 1959 // AutoFontColor 1960 /* 1961 if ( pView->AutoFontColor() ) 1962 { 1963 aTempFont.SetColor ( aFontColor ); 1964 } 1965 */ 1966 1967 String aEntryText( pView->GetEntryText( pEntry, sal_False ) ); 1968 Rectangle aTextRect( CalcTextRect(pEntry,&rPos,sal_False,&aEntryText)); 1969 Rectangle aBmpRect( CalcBmpRect(pEntry, &rPos ) ); 1970 1971 sal_Bool bShowSelection = 1972 ( ( ( bSelected && !bCursored ) 1973 || bDropTarget 1974 ) 1975 && !bNoEmphasis 1976 && ( eSelectionMode != NO_SELECTION ) 1977 ); 1978 sal_Bool bActiveSelection = ( 0 != ( nWinBits & WB_NOHIDESELECTION ) ) || pView->HasFocus(); 1979 1980 if ( bShowSelection ) 1981 { 1982 const StyleSettings& rSettings = pOut->GetSettings().GetStyleSettings(); 1983 Font aNewFont( aTempFont ); 1984 1985 // bei hart attributierter Font-Fuellcolor muessen wir diese 1986 // hart auf die Highlight-Color setzen 1987 if( pView->HasFontFillColor() ) 1988 { 1989 if( (nWinBits & WB_NOHIDESELECTION) || pView->HasFocus() ) 1990 aNewFont.SetFillColor( rSettings.GetHighlightColor() ); 1991 else 1992 aNewFont.SetFillColor( rSettings.GetDeactiveColor() ); 1993 } 1994 1995 Color aWinCol = rSettings.GetWindowTextColor(); 1996 if ( !bActiveSelection && rSettings.GetFaceColor().IsBright() == aWinCol.IsBright() ) 1997 aNewFont.SetColor( rSettings.GetWindowTextColor() ); 1998 else 1999 aNewFont.SetColor( rSettings.GetHighlightTextColor() ); 2000 2001 pOut->SetFont( aNewFont ); 2002 2003 pOut->SetFillColor( pOut->GetBackground().GetColor() ); 2004 pOut->DrawRect( CalcFocusRect( pEntry ) ); 2005 pOut->SetFillColor( ); 2006 } 2007 2008 sal_Bool bResetClipRegion = sal_False; 2009 if( !pView->IsClipRegion() && (aVerSBar.IsVisible() || aHorSBar.IsVisible()) ) 2010 { 2011 Rectangle aOutputArea( GetOutputRect() ); 2012 if( aOutputArea.IsOver(aTextRect) || aOutputArea.IsOver(aBmpRect) ) 2013 { 2014 pView->SetClipRegion( aOutputArea ); 2015 bResetClipRegion = sal_True; 2016 } 2017 } 2018 2019 #ifdef OV_DRAWBOUNDRECT 2020 { 2021 Color aXOldColor = pOut->GetLineColor(); 2022 pOut->SetLineColor( Color( COL_LIGHTRED ) ); 2023 Rectangle aXRect( pEntry->aRect ); 2024 aXRect.SetPos( rPos ); 2025 pOut->DrawRect( aXRect ); 2026 pOut->SetLineColor( aXOldColor ); 2027 } 2028 #endif 2029 2030 sal_Bool bLargeIconMode = WB_ICON == ( nWinBits & (VIEWMODE_MASK) ); 2031 sal_uInt16 nBmpPaintFlags = PAINTFLAG_VER_CENTERED; 2032 if ( bLargeIconMode ) 2033 nBmpPaintFlags |= PAINTFLAG_HOR_CENTERED; 2034 sal_uInt16 nTextPaintFlags = bLargeIconMode ? PAINTFLAG_HOR_CENTERED : PAINTFLAG_VER_CENTERED; 2035 2036 if( !bNoEmphasis ) 2037 PaintEmphasis(aTextRect,aBmpRect,bSelected,bDropTarget,bCursored,pOut,bIsBackgroundPainted); 2038 2039 if ( bShowSelection ) 2040 pView->DrawSelectionBackground( CalcFocusRect( pEntry ), 2041 bActiveSelection ? 1 : 2 /* highlight */, sal_False /* check */, sal_True /* border */, sal_False /* ext border only */ ); 2042 2043 PaintItem( aBmpRect, IcnViewFieldTypeImage, pEntry, nBmpPaintFlags, pOut ); 2044 2045 PaintItem( aTextRect, IcnViewFieldTypeText, pEntry, 2046 nTextPaintFlags, pOut ); 2047 2048 // Highlight-Frame zeichnen 2049 if( pEntry == pCurHighlightFrame && !bNoEmphasis ) 2050 DrawHighlightFrame( pOut, CalcFocusRect( pEntry ), sal_False ); 2051 2052 pOut->SetFont( aTempFont ); 2053 if( bResetClipRegion ) 2054 pView->SetClipRegion(); 2055 } 2056 2057 void SvxIconChoiceCtrl_Impl::SetEntryPos( SvxIconChoiceCtrlEntry* pEntry, const Point& rPos, 2058 sal_Bool bAdjustAtGrid, sal_Bool bCheckScrollBars, sal_Bool bKeepGridMap ) 2059 { 2060 ShowCursor( sal_False ); 2061 Rectangle aBoundRect( GetEntryBoundRect( pEntry )); 2062 pView->Invalidate( aBoundRect ); 2063 ToTop( pEntry ); 2064 if( !IsAutoArrange() ) 2065 { 2066 sal_Bool bAdjustVirtSize = sal_False; 2067 if( rPos != aBoundRect.TopLeft() ) 2068 { 2069 Point aGridOffs( 2070 pEntry->aGridRect.TopLeft() - pEntry->aRect.TopLeft() ); 2071 pImpCursor->Clear(); 2072 if( !bKeepGridMap ) 2073 pGridMap->Clear(); 2074 aBoundRect.SetPos( rPos ); 2075 pEntry->aRect = aBoundRect; 2076 pEntry->aGridRect.SetPos( rPos + aGridOffs ); 2077 bAdjustVirtSize = sal_True; 2078 } 2079 if( bAdjustAtGrid ) 2080 { 2081 if( bAdjustVirtSize ) 2082 { 2083 // Durch das Ausrichten des (ggf. gerade neu positionierten) Eintrags, 2084 // kann er wieder komplett 2085 // in den sichtbaren Bereich rutschen, so dass u.U. doch keine Scrollbar 2086 // eingeblendet werden muss. Um deshalb ein 'Aufblitzen' der 2087 // Scrollbar(s) zu vermeiden, wird zum Aufplustern der virtuellen 2088 // Ausgabegroesse bereits das ausgerichtete Boundrect des 2089 // Eintrags genommen. Die virtuelle Groesse muss angepasst werden, 2090 // da AdjustEntryAtGrid von ihr abhaengt. 2091 const Rectangle& rBoundRect = GetEntryBoundRect( pEntry ); 2092 Rectangle aCenterRect( CalcBmpRect( pEntry, 0 )); 2093 Point aNewPos( AdjustAtGrid( aCenterRect, rBoundRect ) ); 2094 Rectangle aNewBoundRect( aNewPos, pEntry->aRect.GetSize()); 2095 AdjustVirtSize( aNewBoundRect ); 2096 bAdjustVirtSize = sal_False; 2097 } 2098 AdjustEntryAtGrid( pEntry ); 2099 ToTop( pEntry ); 2100 } 2101 if( bAdjustVirtSize ) 2102 AdjustVirtSize( pEntry->aRect ); 2103 2104 if( bCheckScrollBars && bUpdateMode ) 2105 CheckScrollBars(); 2106 2107 pView->Invalidate( pEntry->aRect ); 2108 pGridMap->OccupyGrids( pEntry ); 2109 } 2110 else 2111 { 2112 SvxIconChoiceCtrlEntry* pPrev = FindEntryPredecessor( pEntry, rPos ); 2113 SetEntryPredecessor( pEntry, pPrev ); 2114 aAutoArrangeTimer.Start(); 2115 } 2116 ShowCursor( sal_True ); 2117 } 2118 2119 void SvxIconChoiceCtrl_Impl::SetNoSelection() 2120 { 2121 // rekursive Aufrufe ueber SelectEntry abblocken 2122 if( !(nFlags & F_CLEARING_SELECTION )) 2123 { 2124 nFlags |= F_CLEARING_SELECTION; 2125 DeselectAllBut( 0, sal_True ); 2126 nFlags &= ~F_CLEARING_SELECTION; 2127 } 2128 } 2129 2130 SvxIconChoiceCtrlEntry* SvxIconChoiceCtrl_Impl::GetEntry( const Point& rDocPos, sal_Bool bHit ) 2131 { 2132 CheckBoundingRects(); 2133 // Z-Order-Liste vom Ende her absuchen 2134 sal_uLong nCount = pZOrderList->Count(); 2135 while( nCount ) 2136 { 2137 nCount--; 2138 SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)(pZOrderList->GetObject(nCount)); 2139 if( pEntry->aRect.IsInside( rDocPos ) ) 2140 { 2141 if( bHit ) 2142 { 2143 Rectangle aRect = CalcBmpRect( pEntry ); 2144 aRect.Top() -= 3; 2145 aRect.Bottom() += 3; 2146 aRect.Left() -= 3; 2147 aRect.Right() += 3; 2148 if( aRect.IsInside( rDocPos ) ) 2149 return pEntry; 2150 aRect = CalcTextRect( pEntry ); 2151 if( aRect.IsInside( rDocPos ) ) 2152 return pEntry; 2153 } 2154 else 2155 return pEntry; 2156 } 2157 } 2158 return 0; 2159 } 2160 2161 SvxIconChoiceCtrlEntry* SvxIconChoiceCtrl_Impl::GetNextEntry( const Point& rDocPos, SvxIconChoiceCtrlEntry* pCurEntry ) 2162 { 2163 CheckBoundingRects(); 2164 SvxIconChoiceCtrlEntry* pTarget = 0; 2165 const sal_uLong nStartPos = pZOrderList->GetPos( (void*)pCurEntry ); 2166 if( nStartPos != LIST_ENTRY_NOTFOUND ) 2167 { 2168 const sal_uLong nCount = pZOrderList->Count(); 2169 for( sal_uLong nCur = nStartPos+1; nCur < nCount; nCur++ ) 2170 { 2171 SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)(pZOrderList->GetObject(nCur)); 2172 if( pEntry->aRect.IsInside( rDocPos ) ) 2173 { 2174 pTarget = pEntry; 2175 break; 2176 } 2177 } 2178 } 2179 return pTarget; 2180 } 2181 2182 SvxIconChoiceCtrlEntry* SvxIconChoiceCtrl_Impl::GetPrevEntry( const Point& rDocPos, SvxIconChoiceCtrlEntry* pCurEntry ) 2183 { 2184 CheckBoundingRects(); 2185 SvxIconChoiceCtrlEntry* pTarget = 0; 2186 sal_uLong nStartPos = pZOrderList->GetPos( (void*)pCurEntry ); 2187 if( nStartPos != LIST_ENTRY_NOTFOUND && nStartPos != 0 ) 2188 { 2189 nStartPos--; 2190 do 2191 { 2192 SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)(pZOrderList->GetObject(nStartPos)); 2193 if( pEntry->aRect.IsInside( rDocPos ) ) 2194 { 2195 pTarget = pEntry; 2196 break; 2197 } 2198 } while( nStartPos > 0 ); 2199 } 2200 return pTarget; 2201 } 2202 2203 Point SvxIconChoiceCtrl_Impl::GetEntryPos( SvxIconChoiceCtrlEntry* pEntry ) 2204 { 2205 return pEntry->aRect.TopLeft(); 2206 } 2207 2208 void SvxIconChoiceCtrl_Impl::MakeEntryVisible( SvxIconChoiceCtrlEntry* pEntry, sal_Bool bBound ) 2209 { 2210 if ( bBound ) 2211 { 2212 const Rectangle& rRect = GetEntryBoundRect( pEntry ); 2213 MakeVisible( rRect ); 2214 } 2215 else 2216 { 2217 Rectangle aRect = CalcBmpRect( pEntry ); 2218 aRect.Union( CalcTextRect( pEntry ) ); 2219 aRect.Top() += TBOFFS_BOUND; 2220 aRect.Bottom() += TBOFFS_BOUND; 2221 aRect.Left() += LROFFS_BOUND; 2222 aRect.Right() += LROFFS_BOUND; 2223 MakeVisible( aRect ); 2224 } 2225 } 2226 2227 const Rectangle& SvxIconChoiceCtrl_Impl::GetEntryBoundRect( SvxIconChoiceCtrlEntry* pEntry ) 2228 { 2229 if( !IsBoundingRectValid( pEntry->aRect )) 2230 FindBoundingRect( pEntry ); 2231 return pEntry->aRect; 2232 } 2233 2234 Rectangle SvxIconChoiceCtrl_Impl::CalcBmpRect( SvxIconChoiceCtrlEntry* pEntry, const Point* pPos ) 2235 { 2236 Rectangle aBound = GetEntryBoundRect( pEntry ); 2237 if( pPos ) 2238 aBound.SetPos( *pPos ); 2239 Point aPos( aBound.TopLeft() ); 2240 2241 switch( nWinBits & (VIEWMODE_MASK) ) 2242 { 2243 case WB_ICON: 2244 { 2245 aPos.X() += ( aBound.GetWidth() - aImageSize.Width() ) / 2; 2246 return Rectangle( aPos, aImageSize ); 2247 } 2248 2249 case WB_SMALLICON: 2250 case WB_DETAILS: 2251 aPos.Y() += ( aBound.GetHeight() - aImageSize.Height() ) / 2; 2252 //todo: hor. Abstand zum BoundRect? 2253 return Rectangle( aPos, aImageSize ); 2254 2255 default: 2256 DBG_ERROR("IconView: Viewmode not set"); 2257 return aBound; 2258 } 2259 } 2260 2261 Rectangle SvxIconChoiceCtrl_Impl::CalcTextRect( SvxIconChoiceCtrlEntry* pEntry, 2262 const Point* pEntryPos, sal_Bool bEdit, const String* pStr ) 2263 { 2264 String aEntryText; 2265 if( !pStr ) 2266 aEntryText = pView->GetEntryText( pEntry, bEdit ); 2267 else 2268 aEntryText = *pStr; 2269 2270 const Rectangle aMaxTextRect( CalcMaxTextRect( pEntry ) ); 2271 Rectangle aBound( GetEntryBoundRect( pEntry ) ); 2272 if( pEntryPos ) 2273 aBound.SetPos( *pEntryPos ); 2274 2275 Rectangle aTextRect( aMaxTextRect ); 2276 if( !bEdit ) 2277 aTextRect = pView->GetTextRect( aTextRect, aEntryText, nCurTextDrawFlags ); 2278 2279 Size aTextSize( aTextRect.GetSize() ); 2280 2281 Point aPos( aBound.TopLeft() ); 2282 long nBoundWidth = aBound.GetWidth(); 2283 long nBoundHeight = aBound.GetHeight(); 2284 2285 switch( nWinBits & (VIEWMODE_MASK) ) 2286 { 2287 case WB_ICON: 2288 aPos.Y() += aImageSize.Height(); 2289 aPos.Y() += VER_DIST_BMP_STRING; 2290 // beim Editieren etwas mehr Platz 2291 if( bEdit ) 2292 { 2293 // 20% rauf 2294 long nMinWidth = (( (aImageSize.Width()*10) / 100 ) * 2 ) + 2295 aImageSize.Width(); 2296 if( nMinWidth > nBoundWidth ) 2297 nMinWidth = nBoundWidth; 2298 2299 if( aTextSize.Width() < nMinWidth ) 2300 aTextSize.Width() = nMinWidth; 2301 2302 // beim Editieren ist Ueberlappung nach unten erlaubt 2303 Size aOptSize = aMaxTextRect.GetSize(); 2304 if( aOptSize.Height() > aTextSize.Height() ) 2305 aTextSize.Height() = aOptSize.Height(); 2306 } 2307 aPos.X() += (nBoundWidth - aTextSize.Width()) / 2; 2308 break; 2309 2310 case WB_SMALLICON: 2311 case WB_DETAILS: 2312 aPos.X() += aImageSize.Width(); 2313 aPos.X() += HOR_DIST_BMP_STRING; 2314 aPos.Y() += (nBoundHeight - aTextSize.Height()) / 2; 2315 break; 2316 } 2317 return Rectangle( aPos, aTextSize ); 2318 } 2319 2320 2321 long SvxIconChoiceCtrl_Impl::CalcBoundingWidth( SvxIconChoiceCtrlEntry* pEntry ) const 2322 { 2323 long nStringWidth = GetItemSize( pEntry, IcnViewFieldTypeText ).Width(); 2324 // nStringWidth += 2*LROFFS_TEXT; 2325 long nWidth = 0; 2326 2327 switch( nWinBits & (VIEWMODE_MASK) ) 2328 { 2329 case WB_ICON: 2330 nWidth = Max( nStringWidth, aImageSize.Width() ); 2331 break; 2332 2333 case WB_SMALLICON: 2334 case WB_DETAILS: 2335 nWidth = aImageSize.Width(); 2336 nWidth += HOR_DIST_BMP_STRING; 2337 nWidth += nStringWidth; 2338 break; 2339 } 2340 return nWidth; 2341 } 2342 2343 long SvxIconChoiceCtrl_Impl::CalcBoundingHeight( SvxIconChoiceCtrlEntry* pEntry ) const 2344 { 2345 long nStringHeight = GetItemSize( pEntry, IcnViewFieldTypeText).Height(); 2346 long nHeight = 0; 2347 2348 switch( nWinBits & (VIEWMODE_MASK) ) 2349 { 2350 case WB_ICON: 2351 nHeight = aImageSize.Height(); 2352 nHeight += VER_DIST_BMP_STRING; 2353 nHeight += nStringHeight; 2354 break; 2355 2356 case WB_SMALLICON: 2357 case WB_DETAILS: 2358 nHeight = Max( aImageSize.Height(), nStringHeight ); 2359 break; 2360 } 2361 if( nHeight > nMaxBoundHeight ) 2362 { 2363 ((SvxIconChoiceCtrl_Impl*)this)->nMaxBoundHeight = nHeight; 2364 ((SvxIconChoiceCtrl_Impl*)this)->aHorSBar.SetLineSize( GetScrollBarLineSize() ); 2365 ((SvxIconChoiceCtrl_Impl*)this)->aVerSBar.SetLineSize( GetScrollBarLineSize() ); 2366 } 2367 return nHeight; 2368 } 2369 2370 Size SvxIconChoiceCtrl_Impl::CalcBoundingSize( SvxIconChoiceCtrlEntry* pEntry ) const 2371 { 2372 return Size( CalcBoundingWidth( pEntry ), 2373 CalcBoundingHeight( pEntry ) ); 2374 } 2375 2376 void SvxIconChoiceCtrl_Impl::RecalcAllBoundingRects() 2377 { 2378 nMaxBoundHeight = 0; 2379 pZOrderList->Clear(); 2380 sal_uLong nCount = aEntries.Count(); 2381 sal_uLong nCur; 2382 SvxIconChoiceCtrlEntry* pEntry; 2383 2384 if( !IsAutoArrange() || !pHead ) 2385 { 2386 for( nCur = 0; nCur < nCount; nCur++ ) 2387 { 2388 pEntry = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( nCur ); 2389 FindBoundingRect( pEntry ); 2390 pZOrderList->Insert( pEntry, LIST_APPEND ); 2391 } 2392 } 2393 else 2394 { 2395 nCur = 0; 2396 pEntry = pHead; 2397 while( nCur != nCount ) 2398 { 2399 DBG_ASSERT(pEntry->pflink&&pEntry->pblink,"SvxIconChoiceCtrl_Impl::RecalcAllBoundingRect > Bad link(s)"); 2400 FindBoundingRect( pEntry ); 2401 pZOrderList->Insert( pEntry, pZOrderList->Count() ); 2402 pEntry = pEntry->pflink; 2403 nCur++; 2404 } 2405 } 2406 bBoundRectsDirty = sal_False; 2407 AdjustScrollBars(); 2408 } 2409 2410 void SvxIconChoiceCtrl_Impl::RecalcAllBoundingRectsSmart() 2411 { 2412 nMaxBoundHeight = 0; 2413 pZOrderList->Clear(); 2414 sal_uLong nCur; 2415 SvxIconChoiceCtrlEntry* pEntry; 2416 const sal_uLong nCount = aEntries.Count(); 2417 2418 if( !IsAutoArrange() || !pHead ) 2419 { 2420 for( nCur = 0; nCur < nCount; nCur++ ) 2421 { 2422 pEntry = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( nCur ); 2423 if( IsBoundingRectValid( pEntry->aRect )) 2424 { 2425 Size aBoundSize( pEntry->aRect.GetSize() ); 2426 if( aBoundSize.Height() > nMaxBoundHeight ) 2427 nMaxBoundHeight = aBoundSize.Height(); 2428 } 2429 else 2430 FindBoundingRect( pEntry ); 2431 pZOrderList->Insert( pEntry, LIST_APPEND ); 2432 } 2433 } 2434 else 2435 { 2436 nCur = 0; 2437 pEntry = pHead; 2438 while( nCur != nCount ) 2439 { 2440 DBG_ASSERT(pEntry->pflink&&pEntry->pblink,"SvxIconChoiceCtrl_Impl::RecalcAllBoundingRect > Bad link(s)"); 2441 if( IsBoundingRectValid( pEntry->aRect )) 2442 { 2443 Size aBoundSize( pEntry->aRect.GetSize() ); 2444 if( aBoundSize.Height() > nMaxBoundHeight ) 2445 nMaxBoundHeight = aBoundSize.Height(); 2446 } 2447 else 2448 FindBoundingRect( pEntry ); 2449 pZOrderList->Insert( pEntry, LIST_APPEND ); 2450 pEntry = pEntry->pflink; 2451 nCur++; 2452 } 2453 } 2454 AdjustScrollBars(); 2455 } 2456 2457 void SvxIconChoiceCtrl_Impl::UpdateBoundingRects() 2458 { 2459 const sal_uLong nCount = aEntries.Count(); 2460 for( sal_uLong nCur = 0; nCur < nCount; nCur++ ) 2461 { 2462 SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( nCur ); 2463 GetEntryBoundRect( pEntry ); 2464 } 2465 } 2466 2467 void SvxIconChoiceCtrl_Impl::FindBoundingRect( SvxIconChoiceCtrlEntry* pEntry ) 2468 { 2469 DBG_ASSERT(!pEntry->IsPosLocked(),"Locked entry pos in FindBoundingRect"); 2470 if( pEntry->IsPosLocked() && IsBoundingRectValid( pEntry->aRect) ) 2471 { 2472 AdjustVirtSize( pEntry->aRect ); 2473 return; 2474 } 2475 Size aSize( CalcBoundingSize( pEntry ) ); 2476 Point aPos(pGridMap->GetGridRect(pGridMap->GetUnoccupiedGrid(sal_True)).TopLeft()); 2477 SetBoundingRect_Impl( pEntry, aPos, aSize ); 2478 } 2479 2480 void SvxIconChoiceCtrl_Impl::SetBoundingRect_Impl( SvxIconChoiceCtrlEntry* pEntry, const Point& rPos, 2481 const Size& /*rBoundingSize*/ ) 2482 { 2483 Rectangle aGridRect( rPos, Size(nGridDX, nGridDY) ); 2484 pEntry->aGridRect = aGridRect; 2485 Center( pEntry ); 2486 AdjustVirtSize( pEntry->aRect ); 2487 pGridMap->OccupyGrids( pEntry ); 2488 } 2489 2490 2491 void SvxIconChoiceCtrl_Impl::SetCursor( SvxIconChoiceCtrlEntry* pEntry, sal_Bool bSyncSingleSelection, 2492 sal_Bool bShowFocusAsync ) 2493 { 2494 if( pEntry == pCursor ) 2495 { 2496 if( pCursor && eSelectionMode == SINGLE_SELECTION && bSyncSingleSelection && 2497 !pCursor->IsSelected() ) 2498 SelectEntry( pCursor, sal_True, sal_True ); 2499 return; 2500 } 2501 ShowCursor( sal_False ); 2502 SvxIconChoiceCtrlEntry* pOldCursor = pCursor; 2503 pCursor = pEntry; 2504 if( pOldCursor ) 2505 { 2506 pOldCursor->ClearFlags( ICNVIEW_FLAG_FOCUSED ); 2507 if( eSelectionMode == SINGLE_SELECTION && bSyncSingleSelection ) 2508 SelectEntry( pOldCursor, sal_False, sal_True ); // alten Cursor deselektieren 2509 } 2510 if( pCursor ) 2511 { 2512 ToTop( pCursor ); 2513 pCursor->SetFlags( ICNVIEW_FLAG_FOCUSED ); 2514 if( eSelectionMode == SINGLE_SELECTION && bSyncSingleSelection ) 2515 SelectEntry( pCursor, sal_True, sal_True ); 2516 if( !bShowFocusAsync ) 2517 ShowCursor( sal_True ); 2518 else 2519 { 2520 if( !nUserEventShowCursor ) 2521 nUserEventShowCursor = 2522 Application::PostUserEvent( LINK( this, SvxIconChoiceCtrl_Impl, UserEventHdl), 2523 EVENTID_SHOW_CURSOR ); 2524 } 2525 } 2526 } 2527 2528 2529 void SvxIconChoiceCtrl_Impl::ShowCursor( sal_Bool bShow ) 2530 { 2531 if( !pCursor || !bShow || !pView->HasFocus() ) 2532 { 2533 pView->HideFocus(); 2534 return; 2535 } 2536 Rectangle aRect ( CalcFocusRect( pCursor ) ); 2537 /*pView->*/ShowFocus( aRect ); 2538 } 2539 2540 2541 void SvxIconChoiceCtrl_Impl::HideDDIcon() 2542 { 2543 pView->Update(); 2544 ImpHideDDIcon(); 2545 pDDBufDev = pDDDev; 2546 pDDDev = 0; 2547 } 2548 2549 void SvxIconChoiceCtrl_Impl::ImpHideDDIcon() 2550 { 2551 if( pDDDev ) 2552 { 2553 Size aSize( pDDDev->GetOutputSizePixel() ); 2554 // pView restaurieren 2555 pView->DrawOutDev( aDDLastRectPos, aSize, Point(), aSize, *pDDDev ); 2556 } 2557 } 2558 2559 2560 void SvxIconChoiceCtrl_Impl::ShowDDIcon( SvxIconChoiceCtrlEntry* pRefEntry, const Point& rPosPix ) 2561 { 2562 pView->Update(); 2563 if( pRefEntry != pDDRefEntry ) 2564 { 2565 DELETEZ(pDDDev); 2566 DELETEZ(pDDBufDev); 2567 } 2568 sal_Bool bSelected = pRefEntry->IsSelected(); 2569 pRefEntry->ClearFlags( ICNVIEW_FLAG_SELECTED ); 2570 if( !pDDDev ) 2571 { 2572 if( pDDBufDev ) 2573 { 2574 // nicht bei jedem Move ein Device anlegen, da dies besonders 2575 // auf Remote-Clients zu langsam ist 2576 pDDDev = pDDBufDev; 2577 pDDBufDev = 0; 2578 } 2579 else 2580 { 2581 pDDDev = new VirtualDevice( *pView ); 2582 pDDDev->SetFont( pView->GetFont() ); 2583 } 2584 } 2585 else 2586 { 2587 ImpHideDDIcon(); 2588 } 2589 const Rectangle& rRect = GetEntryBoundRect( pRefEntry ); 2590 pDDDev->SetOutputSizePixel( rRect.GetSize() ); 2591 2592 Point aPos( rPosPix ); 2593 ToDocPos( aPos ); 2594 2595 Size aSize( pDDDev->GetOutputSizePixel() ); 2596 pDDRefEntry = pRefEntry; 2597 aDDLastEntryPos = aPos; 2598 aDDLastRectPos = aPos; 2599 2600 // Hintergrund sichern 2601 pDDDev->DrawOutDev( Point(), aSize, aPos, aSize, *pView ); 2602 // Icon in pView malen 2603 pRefEntry->SetFlags( ICNVIEW_FLAG_BLOCK_EMPHASIS ); 2604 PaintEntry( pRefEntry, aPos ); 2605 pRefEntry->ClearFlags( ICNVIEW_FLAG_BLOCK_EMPHASIS ); 2606 if( bSelected ) 2607 pRefEntry->SetFlags( ICNVIEW_FLAG_SELECTED ); 2608 } 2609 2610 void SvxIconChoiceCtrl_Impl::HideShowDDIcon( SvxIconChoiceCtrlEntry* pRefEntry, const Point& rPosPix ) 2611 { 2612 /* In Notfaellen folgenden flackernden Code aktivieren: 2613 2614 HideDDIcon(); 2615 ShowDDIcon( pRefEntry, rPosPix ); 2616 return; 2617 */ 2618 if( !pDDDev ) 2619 { 2620 ShowDDIcon( pRefEntry, rPosPix ); 2621 return; 2622 } 2623 2624 if( pRefEntry != pDDRefEntry ) 2625 { 2626 HideDDIcon(); 2627 ShowDDIcon( pRefEntry, rPosPix ); 2628 return; 2629 } 2630 2631 Point aEmptyPoint; 2632 2633 Point aCurEntryPos( rPosPix ); 2634 ToDocPos( aCurEntryPos ); 2635 2636 const Rectangle& rRect = GetEntryBoundRect( pRefEntry ); 2637 Size aEntrySize( rRect.GetSize() ); 2638 Rectangle aPrevEntryRect( aDDLastEntryPos, aEntrySize ); 2639 Rectangle aCurEntryRect( aCurEntryPos, aEntrySize ); 2640 2641 if( !aPrevEntryRect.IsOver( aCurEntryRect ) ) 2642 { 2643 HideDDIcon(); 2644 ShowDDIcon( pRefEntry, rPosPix ); 2645 return; 2646 } 2647 2648 // Ueberlappung des neuen und alten D&D-Pointers! 2649 2650 Rectangle aFullRect( aPrevEntryRect.Union( aCurEntryRect ) ); 2651 if( !pDDTempDev ) 2652 { 2653 pDDTempDev = new VirtualDevice( *pView ); 2654 pDDTempDev->SetFont( pView->GetFont() ); 2655 } 2656 2657 Size aFullSize( aFullRect.GetSize() ); 2658 Point aFullPos( aFullRect.TopLeft() ); 2659 2660 pDDTempDev->SetOutputSizePixel( aFullSize ); 2661 2662 // Hintergrund (mit dem alten D&D-Pointer!) sichern 2663 pDDTempDev->DrawOutDev( aEmptyPoint, aFullSize, aFullPos, aFullSize, *pView ); 2664 // den alten Buffer in den neuen Buffer pasten 2665 aDDLastRectPos = aDDLastRectPos - aFullPos; 2666 2667 pDDTempDev->DrawOutDev( 2668 aDDLastRectPos, 2669 pDDDev->GetOutputSizePixel(), 2670 aEmptyPoint, 2671 pDDDev->GetOutputSizePixel(), 2672 *pDDDev ); 2673 2674 // Swap 2675 VirtualDevice* pTemp = pDDDev; 2676 pDDDev = pDDTempDev; 2677 pDDTempDev = pTemp; 2678 2679 // in den restaurierten Hintergrund den neuen D&D-Pointer zeichnen 2680 pDDTempDev->SetOutputSizePixel( pDDDev->GetOutputSizePixel() ); 2681 pDDTempDev->DrawOutDev( 2682 aEmptyPoint, aFullSize, aEmptyPoint, aFullSize, *pDDDev ); 2683 Point aRelPos = aCurEntryPos - aFullPos; 2684 pRefEntry->SetFlags( ICNVIEW_FLAG_BLOCK_EMPHASIS ); 2685 PaintEntry( pRefEntry, aRelPos, pDDTempDev ); 2686 pRefEntry->ClearFlags( ICNVIEW_FLAG_BLOCK_EMPHASIS ); 2687 2688 aDDLastRectPos = aFullPos; 2689 aDDLastEntryPos = aCurEntryPos; 2690 2691 pView->DrawOutDev( 2692 aDDLastRectPos, 2693 pDDDev->GetOutputSizePixel(), 2694 aEmptyPoint, 2695 pDDDev->GetOutputSizePixel(), 2696 *pDDTempDev ); 2697 } 2698 2699 void SvxIconChoiceCtrl_Impl::InvalidateBoundingRect( SvxIconChoiceCtrlEntry* pEntry ) 2700 { 2701 InvalidateBoundingRect( pEntry->aRect ); 2702 } 2703 2704 2705 sal_Bool SvxIconChoiceCtrl_Impl::HandleScrollCommand( const CommandEvent& rCmd ) 2706 { 2707 Rectangle aDocRect( GetDocumentRect() ); 2708 Rectangle aVisRect( GetVisibleRect() ); 2709 if( aVisRect.IsInside( aDocRect )) 2710 return sal_False; 2711 Size aDocSize( aDocRect.GetSize() ); 2712 Size aVisSize( aVisRect.GetSize() ); 2713 sal_Bool bHor = aDocSize.Width() > aVisSize.Width(); 2714 sal_Bool bVer = aDocSize.Height() > aVisSize.Height(); 2715 2716 long nScrollDX = 0, nScrollDY = 0; 2717 2718 switch( rCmd.GetCommand() ) 2719 { 2720 case COMMAND_STARTAUTOSCROLL: 2721 { 2722 pView->EndTracking(); 2723 sal_uInt16 nScrollFlags = 0; 2724 if( bHor ) 2725 nScrollFlags |= AUTOSCROLL_HORZ; 2726 if( bVer ) 2727 nScrollFlags |= AUTOSCROLL_VERT; 2728 if( nScrollFlags ) 2729 { 2730 pView->StartAutoScroll( nScrollFlags ); 2731 return sal_True; 2732 } 2733 } 2734 break; 2735 2736 case COMMAND_WHEEL: 2737 { 2738 const CommandWheelData* pData = rCmd.GetWheelData(); 2739 if( pData && (COMMAND_WHEEL_SCROLL == pData->GetMode()) && !pData->IsHorz() ) 2740 { 2741 sal_uLong nScrollLines = pData->GetScrollLines(); 2742 if( nScrollLines == COMMAND_WHEEL_PAGESCROLL ) 2743 { 2744 nScrollDY = GetScrollBarPageSize( aVisSize.Width() ); 2745 if( pData->GetDelta() < 0 ) 2746 nScrollDY *= -1; 2747 } 2748 else 2749 { 2750 nScrollDY = pData->GetNotchDelta() * (long)nScrollLines; 2751 nScrollDY *= GetScrollBarLineSize(); 2752 } 2753 } 2754 } 2755 break; 2756 2757 case COMMAND_AUTOSCROLL: 2758 { 2759 const CommandScrollData* pData = rCmd.GetAutoScrollData(); 2760 if( pData ) 2761 { 2762 nScrollDX = pData->GetDeltaX() * GetScrollBarLineSize(); 2763 nScrollDY = pData->GetDeltaY() * GetScrollBarLineSize(); 2764 } 2765 } 2766 break; 2767 } 2768 2769 if( nScrollDX || nScrollDY ) 2770 { 2771 aVisRect.Top() -= nScrollDY; 2772 aVisRect.Bottom() -= nScrollDY; 2773 aVisRect.Left() -= nScrollDX; 2774 aVisRect.Right() -= nScrollDX; 2775 MakeVisible( aVisRect ); 2776 return sal_True; 2777 } 2778 return sal_False; 2779 } 2780 2781 2782 void SvxIconChoiceCtrl_Impl::Command( const CommandEvent& rCEvt ) 2783 { 2784 // Rollmaus-Event? 2785 if( (rCEvt.GetCommand() == COMMAND_WHEEL) || 2786 (rCEvt.GetCommand() == COMMAND_STARTAUTOSCROLL) || 2787 (rCEvt.GetCommand() == COMMAND_AUTOSCROLL) ) 2788 { 2789 #if 1 2790 if( HandleScrollCommand( rCEvt ) ) 2791 return; 2792 #else 2793 ScrollBar* pHor = aHorSBar.IsVisible() ? &aHorSBar : 0; 2794 ScrollBar* pVer = aVerSBar.IsVisible() ? &aVerSBar : 0; 2795 if( pView->HandleScrollCommand( rCEvt, pHor, pVer ) ) 2796 return; 2797 #endif 2798 } 2799 } 2800 2801 void SvxIconChoiceCtrl_Impl::ToTop( SvxIconChoiceCtrlEntry* pEntry ) 2802 { 2803 if( pZOrderList->GetObject( pZOrderList->Count() - 1 ) != pEntry ) 2804 { 2805 sal_uLong nPos = pZOrderList->GetPos( (void*)pEntry ); 2806 pZOrderList->Remove( nPos ); 2807 pZOrderList->Insert( pEntry, LIST_APPEND ); 2808 } 2809 } 2810 2811 void SvxIconChoiceCtrl_Impl::ClipAtVirtOutRect( Rectangle& rRect ) const 2812 { 2813 if( rRect.Bottom() >= aVirtOutputSize.Height() ) 2814 rRect.Bottom() = aVirtOutputSize.Height() - 1; 2815 if( rRect.Right() >= aVirtOutputSize.Width() ) 2816 rRect.Right() = aVirtOutputSize.Width() - 1; 2817 if( rRect.Top() < 0 ) 2818 rRect.Top() = 0; 2819 if( rRect.Left() < 0 ) 2820 rRect.Left() = 0; 2821 } 2822 2823 // rRect: Bereich des Dokumentes (in Dokumentkoordinaten), der 2824 // sichtbar gemacht werden soll. 2825 // bScrBar == sal_True: Das Rect wurde aufgrund eines ScrollBar-Events berechnet 2826 2827 void SvxIconChoiceCtrl_Impl::MakeVisible( const Rectangle& rRect, sal_Bool bScrBar, 2828 sal_Bool bCallRectChangedHdl ) 2829 { 2830 Rectangle aVirtRect( rRect ); 2831 ClipAtVirtOutRect( aVirtRect ); 2832 Point aOrigin( pView->GetMapMode().GetOrigin() ); 2833 // in Dokumentkoordinate umwandeln 2834 aOrigin *= -1; 2835 Rectangle aOutputArea( GetOutputRect() ); 2836 if( aOutputArea.IsInside( aVirtRect ) ) 2837 return; // ist schon sichtbar 2838 2839 long nDy; 2840 if( aVirtRect.Top() < aOutputArea.Top() ) 2841 { 2842 // nach oben scrollen (nDy < 0) 2843 nDy = aVirtRect.Top() - aOutputArea.Top(); 2844 } 2845 else if( aVirtRect.Bottom() > aOutputArea.Bottom() ) 2846 { 2847 // nach unten scrollen (nDy > 0) 2848 nDy = aVirtRect.Bottom() - aOutputArea.Bottom(); 2849 } 2850 else 2851 nDy = 0; 2852 2853 long nDx; 2854 if( aVirtRect.Left() < aOutputArea.Left() ) 2855 { 2856 // nach links scrollen (nDx < 0) 2857 nDx = aVirtRect.Left() - aOutputArea.Left(); 2858 } 2859 else if( aVirtRect.Right() > aOutputArea.Right() ) 2860 { 2861 // nach rechts scrollen (nDx > 0) 2862 nDx = aVirtRect.Right() - aOutputArea.Right(); 2863 } 2864 else 2865 nDx = 0; 2866 2867 aOrigin.X() += nDx; 2868 aOrigin.Y() += nDy; 2869 aOutputArea.SetPos( aOrigin ); 2870 if( GetUpdateMode() ) 2871 { 2872 HideDDIcon(); 2873 pView->Update(); 2874 ShowCursor( sal_False ); 2875 } 2876 2877 // Origin fuer SV invertieren (damit wir in 2878 // Dokumentkoordinaten scrollen/painten koennen) 2879 aOrigin *= -1; 2880 SetOrigin( aOrigin ); 2881 2882 sal_Bool bScrollable = pView->GetBackground().IsScrollable(); 2883 if( pView->HasBackground() && !bScrollable ) 2884 { 2885 Rectangle aRect( GetOutputRect()); 2886 Wallpaper aPaper( pView->GetBackground() ); 2887 aPaper.SetRect( aRect ); 2888 pView->SetBackground( aPaper ); 2889 } 2890 2891 if( bScrollable && GetUpdateMode() ) 2892 { 2893 // in umgekehrte Richtung scrollen! 2894 pView->Control::Scroll( -nDx, -nDy, aOutputArea, 2895 SCROLL_NOCHILDREN | SCROLL_USECLIPREGION | SCROLL_CLIP ); 2896 } 2897 else 2898 pView->Invalidate(INVALIDATE_NOCHILDREN); 2899 2900 if( aHorSBar.IsVisible() || aVerSBar.IsVisible() ) 2901 { 2902 if( !bScrBar ) 2903 { 2904 aOrigin *= -1; 2905 // Thumbs korrigieren 2906 if(aHorSBar.IsVisible() && aHorSBar.GetThumbPos() != aOrigin.X()) 2907 aHorSBar.SetThumbPos( aOrigin.X() ); 2908 if(aVerSBar.IsVisible() && aVerSBar.GetThumbPos() != aOrigin.Y()) 2909 aVerSBar.SetThumbPos( aOrigin.Y() ); 2910 } 2911 } 2912 2913 if( GetUpdateMode() ) 2914 ShowCursor( sal_True ); 2915 2916 // pruefen, ob ScrollBars noch benoetigt werden 2917 CheckScrollBars(); 2918 if( bScrollable && GetUpdateMode() ) 2919 pView->Update(); 2920 2921 // kann der angeforderte Bereich nicht komplett sichtbar gemacht werden, 2922 // wird auf jeden Fall der Vis-Rect-Changed-Handler gerufen. Eintreten kann der 2923 // Fall z.B. wenn nur wenige Pixel des unteren Randes nicht sichtbar sind, 2924 // eine ScrollBar aber eine groessere Line-Size eingestellt hat. 2925 if( bCallRectChangedHdl || GetOutputRect() != rRect ) 2926 VisRectChanged(); 2927 } 2928 2929 2930 SvxIconChoiceCtrlEntry* SvxIconChoiceCtrl_Impl::FindNewCursor() 2931 { 2932 SvxIconChoiceCtrlEntry* pNewCursor; 2933 if( pCursor ) 2934 { 2935 pNewCursor = pImpCursor->GoLeftRight( pCursor, sal_False ); 2936 if( !pNewCursor ) 2937 { 2938 pNewCursor = pImpCursor->GoLeftRight( pCursor, sal_True ); 2939 if( !pNewCursor ) 2940 { 2941 pNewCursor = pImpCursor->GoUpDown( pCursor, sal_False ); 2942 if( !pNewCursor ) 2943 pNewCursor = pImpCursor->GoUpDown( pCursor, sal_True ); 2944 } 2945 } 2946 } 2947 else 2948 pNewCursor = (SvxIconChoiceCtrlEntry*)aEntries.First(); 2949 DBG_ASSERT(!pNewCursor|| (pCursor&&pCursor!=pNewCursor),"FindNewCursor failed"); 2950 return pNewCursor; 2951 } 2952 2953 sal_uLong SvxIconChoiceCtrl_Impl::GetSelectionCount() const 2954 { 2955 if( (nWinBits & WB_HIGHLIGHTFRAME) && pCurHighlightFrame ) 2956 return 1; 2957 return nSelectionCount; 2958 } 2959 2960 void SvxIconChoiceCtrl_Impl::ToggleSelection( SvxIconChoiceCtrlEntry* pEntry ) 2961 { 2962 sal_Bool bSel; 2963 if( pEntry->IsSelected() ) 2964 bSel = sal_False; 2965 else 2966 bSel = sal_True; 2967 SelectEntry( pEntry, bSel, sal_True, sal_True ); 2968 } 2969 2970 void SvxIconChoiceCtrl_Impl::DeselectAllBut( SvxIconChoiceCtrlEntry* pThisEntryNot, 2971 sal_Bool bPaintSync ) 2972 { 2973 ClearSelectedRectList(); 2974 // 2975 // !!!!!!! Todo: Evtl. Z-Orderlist abarbeiten !!!!!!! 2976 // 2977 sal_uLong nCount = aEntries.Count(); 2978 for( sal_uLong nCur = 0; nCur < nCount; nCur++ ) 2979 { 2980 SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( nCur ); 2981 if( pEntry != pThisEntryNot && pEntry->IsSelected() ) 2982 SelectEntry( pEntry, sal_False, sal_True, sal_True, bPaintSync ); 2983 } 2984 pAnchor = 0; 2985 nFlags &= (~F_ADD_MODE); 2986 } 2987 2988 Size SvxIconChoiceCtrl_Impl::GetMinGrid() const 2989 { 2990 Size aMinSize( aImageSize ); 2991 aMinSize.Width() += 2 * LROFFS_BOUND; 2992 aMinSize.Height() += TBOFFS_BOUND; // PB: einmal Offset reicht (FileDlg) 2993 String aStrDummy( RTL_CONSTASCII_USTRINGPARAM( "XXX" ) ); 2994 Size aTextSize( pView->GetTextWidth( aStrDummy ), pView->GetTextHeight() ); 2995 if( nWinBits & WB_ICON ) 2996 { 2997 aMinSize.Height() += VER_DIST_BMP_STRING; 2998 aMinSize.Height() += aTextSize.Height(); 2999 } 3000 else 3001 { 3002 aMinSize.Width() += HOR_DIST_BMP_STRING; 3003 aMinSize.Width() += aTextSize.Width(); 3004 } 3005 return aMinSize; 3006 } 3007 3008 void SvxIconChoiceCtrl_Impl::SetGrid( const Size& rSize ) 3009 { 3010 Size aSize( rSize ); 3011 Size aMinSize( GetMinGrid() ); 3012 if( aSize.Width() < aMinSize.Width() ) 3013 aSize.Width() = aMinSize.Width(); 3014 if( aSize.Height() < aMinSize.Height() ) 3015 aSize.Height() = aMinSize.Height(); 3016 3017 nGridDX = aSize.Width(); 3018 // HACK(Detail-Modus ist noch nicht vollstaendig implementiert!) 3019 // dieses Workaround bringts mit einer Spalte zum Fliegen 3020 if( nWinBits & WB_DETAILS ) 3021 { 3022 const SvxIconChoiceCtrlColumnInfo* pCol = GetColumn( 0 ); 3023 if( pCol ) 3024 ((SvxIconChoiceCtrlColumnInfo*)pCol)->SetWidth( nGridDX ); 3025 } 3026 nGridDY = aSize.Height(); 3027 SetDefaultTextSize(); 3028 } 3029 3030 // berechnet die maximale Groesse, die das Textrechteck innerhalb des 3031 // umschliessenden Rechtecks einnehmen kann. Im Modus WB_ICON und 3032 // IcnShowTextFull wird Bottom auf LONG_MAX gesetzt 3033 3034 Rectangle SvxIconChoiceCtrl_Impl::CalcMaxTextRect( const SvxIconChoiceCtrlEntry* pEntry ) const 3035 { 3036 Rectangle aBoundRect; 3037 // keine Endlosrekursion! deshalb das Bound-Rect hier nicht berechnen 3038 if( IsBoundingRectValid( pEntry->aRect ) ) 3039 aBoundRect = pEntry->aRect; 3040 else 3041 aBoundRect = pEntry->aGridRect; 3042 3043 Rectangle aBmpRect( ((SvxIconChoiceCtrl_Impl*)this)->CalcBmpRect( 3044 (SvxIconChoiceCtrlEntry*)pEntry ) ); 3045 if( nWinBits & WB_ICON ) 3046 { 3047 aBoundRect.Top() = aBmpRect.Bottom(); 3048 aBoundRect.Top() += VER_DIST_BMP_STRING; 3049 if( aBoundRect.Top() > aBoundRect.Bottom()) 3050 aBoundRect.Top() = aBoundRect.Bottom(); 3051 aBoundRect.Left() += LROFFS_BOUND; 3052 aBoundRect.Left()++; 3053 aBoundRect.Right() -= LROFFS_BOUND; 3054 aBoundRect.Right()--; 3055 if( aBoundRect.Left() > aBoundRect.Right()) 3056 aBoundRect.Left() = aBoundRect.Right(); 3057 if( GetEntryTextModeSmart( pEntry ) == IcnShowTextFull ) 3058 aBoundRect.Bottom() = LONG_MAX; 3059 } 3060 else 3061 { 3062 aBoundRect.Left() = aBmpRect.Right(); 3063 aBoundRect.Left() += HOR_DIST_BMP_STRING; 3064 aBoundRect.Right() -= LROFFS_BOUND; 3065 if( aBoundRect.Left() > aBoundRect.Right() ) 3066 aBoundRect.Left() = aBoundRect.Right(); 3067 long nHeight = aBoundRect.GetSize().Height(); 3068 nHeight = nHeight - aDefaultTextSize.Height(); 3069 nHeight /= 2; 3070 aBoundRect.Top() += nHeight; 3071 aBoundRect.Bottom() -= nHeight; 3072 } 3073 return aBoundRect; 3074 } 3075 3076 void SvxIconChoiceCtrl_Impl::SetDefaultTextSize() 3077 { 3078 long nDY = nGridDY; 3079 nDY -= aImageSize.Height(); 3080 nDY -= VER_DIST_BMP_STRING; 3081 nDY -= 2*TBOFFS_BOUND; 3082 if( nDY <= 0 ) 3083 nDY = 2; 3084 3085 long nDX = nGridDX; 3086 nDX -= 2*LROFFS_BOUND; 3087 nDX -= 2; 3088 if( nDX <= 0 ) 3089 nDX = 2; 3090 3091 String aStrDummy( RTL_CONSTASCII_USTRINGPARAM( "X" ) ); 3092 long nHeight = pView->GetTextHeight(); 3093 if( nDY < nHeight ) 3094 nDY = nHeight; 3095 aDefaultTextSize = Size( nDX, nDY ); 3096 } 3097 3098 3099 void SvxIconChoiceCtrl_Impl::Center( SvxIconChoiceCtrlEntry* pEntry ) const 3100 { 3101 pEntry->aRect = pEntry->aGridRect; 3102 Size aSize( CalcBoundingSize( pEntry ) ); 3103 if( nWinBits & WB_ICON ) 3104 { 3105 // horizontal zentrieren 3106 long nBorder = pEntry->aGridRect.GetWidth() - aSize.Width(); 3107 pEntry->aRect.Left() += nBorder / 2; 3108 pEntry->aRect.Right() -= nBorder / 2; 3109 } 3110 // vertikal zentrieren 3111 pEntry->aRect.Bottom() = pEntry->aRect.Top() + aSize.Height(); 3112 } 3113 3114 3115 // Die Deltas entsprechen Offsets, um die die View auf dem Doc verschoben wird 3116 // links, hoch: Offsets < 0 3117 // rechts, runter: Offsets > 0 3118 void SvxIconChoiceCtrl_Impl::Scroll( long nDeltaX, long nDeltaY, sal_Bool bScrollBar ) 3119 { 3120 const MapMode& rMapMode = pView->GetMapMode(); 3121 Point aOrigin( rMapMode.GetOrigin() ); 3122 // in Dokumentkoordinate umwandeln 3123 aOrigin *= -1; 3124 aOrigin.Y() += nDeltaY; 3125 aOrigin.X() += nDeltaX; 3126 Rectangle aRect( aOrigin, aOutputSize ); 3127 MakeVisible( aRect, bScrollBar ); 3128 } 3129 3130 3131 const Size& SvxIconChoiceCtrl_Impl::GetItemSize( SvxIconChoiceCtrlEntry*, 3132 IcnViewFieldType eItem ) const 3133 { 3134 if( eItem == IcnViewFieldTypeText ) 3135 return aDefaultTextSize; 3136 return aImageSize; 3137 } 3138 3139 Rectangle SvxIconChoiceCtrl_Impl::CalcFocusRect( SvxIconChoiceCtrlEntry* pEntry ) 3140 { 3141 Rectangle aBmpRect( CalcBmpRect( pEntry ) ); 3142 Rectangle aTextRect( CalcTextRect( pEntry ) ); 3143 Rectangle aBoundRect( GetEntryBoundRect( pEntry ) ); 3144 Rectangle aFocusRect( aBoundRect.Left(), aBmpRect.Top() - 1, 3145 aBoundRect.Right() - 4, aTextRect.Bottom() + 1 ); 3146 // Das Fokusrechteck soll nicht den Text beruehren 3147 if( aFocusRect.Left() - 1 >= pEntry->aRect.Left() ) 3148 aFocusRect.Left()--; 3149 if( aFocusRect.Right() + 1 <= pEntry->aRect.Right() ) 3150 aFocusRect.Right()++; 3151 3152 return aFocusRect; 3153 } 3154 3155 // Der 'Hot Spot' sind die inneren 50% der Rechteckflaeche 3156 static Rectangle GetHotSpot( const Rectangle& rRect ) 3157 { 3158 Rectangle aResult( rRect ); 3159 aResult.Justify(); 3160 Size aSize( rRect.GetSize() ); 3161 long nDelta = aSize.Width() / 4; 3162 aResult.Left() += nDelta; 3163 aResult.Right() -= nDelta; 3164 nDelta = aSize.Height() / 4; 3165 aResult.Top() += nDelta; 3166 aResult.Bottom() -= nDelta; 3167 return aResult; 3168 } 3169 3170 void SvxIconChoiceCtrl_Impl::SelectRect( SvxIconChoiceCtrlEntry* pEntry1, SvxIconChoiceCtrlEntry* pEntry2, 3171 sal_Bool bAdd, SvPtrarr* pOtherRects ) 3172 { 3173 DBG_ASSERT(pEntry1 && pEntry2,"SelectEntry: Invalid Entry-Ptr"); 3174 Rectangle aRect( GetEntryBoundRect( pEntry1 ) ); 3175 aRect.Union( GetEntryBoundRect( pEntry2 ) ); 3176 SelectRect( aRect, bAdd, pOtherRects ); 3177 } 3178 3179 void SvxIconChoiceCtrl_Impl::SelectRect( const Rectangle& rRect, sal_Bool bAdd, 3180 SvPtrarr* pOtherRects ) 3181 { 3182 aCurSelectionRect = rRect; 3183 if( !pZOrderList || !pZOrderList->Count() ) 3184 return; 3185 3186 // Flag setzen, damit im Select kein ToTop gerufen wird 3187 sal_Bool bAlreadySelectingRect = nFlags & F_SELECTING_RECT ? sal_True : sal_False; 3188 nFlags |= F_SELECTING_RECT; 3189 3190 CheckBoundingRects(); 3191 pView->Update(); 3192 const sal_uLong nCount = pZOrderList->Count(); 3193 3194 Rectangle aRect( rRect ); 3195 aRect.Justify(); 3196 sal_Bool bCalcOverlap = (bAdd && pOtherRects && pOtherRects->Count()) ? sal_True : sal_False; 3197 3198 sal_Bool bResetClipRegion = sal_False; 3199 if( !pView->IsClipRegion() ) 3200 { 3201 bResetClipRegion = sal_True; 3202 pView->SetClipRegion( GetOutputRect() ); 3203 } 3204 3205 for( sal_uLong nPos = 0; nPos < nCount; nPos++ ) 3206 { 3207 SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)(pZOrderList->GetObject(nPos )); 3208 3209 if( !IsBoundingRectValid( pEntry->aRect )) 3210 FindBoundingRect( pEntry ); 3211 Rectangle aBoundRect( GetHotSpot( pEntry->aRect ) ); 3212 sal_Bool bSelected = pEntry->IsSelected(); 3213 3214 sal_Bool bOverlaps; 3215 if( bCalcOverlap ) 3216 bOverlaps = IsOver( pOtherRects, aBoundRect ); 3217 else 3218 bOverlaps = sal_False; 3219 sal_Bool bOver = aRect.IsOver( aBoundRect ); 3220 3221 if( bOver && !bOverlaps ) 3222 { 3223 // Ist im neuen Selektionsrechteck und in keinem alten 3224 // => selektieren 3225 if( !bSelected ) 3226 SelectEntry( pEntry, sal_True, sal_True, sal_True ); 3227 } 3228 else if( !bAdd ) 3229 { 3230 // ist ausserhalb des Selektionsrechtecks 3231 // => Selektion entfernen 3232 if( bSelected ) 3233 SelectEntry( pEntry, sal_False, sal_True, sal_True ); 3234 } 3235 else if( bAdd && bOverlaps ) 3236 { 3237 // Der Eintrag befindet sich in einem alten (=>Aufspannen 3238 // mehrerer Rechtecke mit Ctrl!) Selektionsrechteck 3239 3240 // Hier ist noch ein Bug! Der Selektionsstatus eines Eintrags 3241 // in einem vorherigen Rechteck, muss restauriert werden, wenn 3242 // er vom aktuellen Selektionsrechteck beruehrt wurde, jetzt aber 3243 // nicht mehr in ihm liegt. Ich gehe hier der Einfachheit halber 3244 // pauschal davon aus, dass die Eintraege in den alten Rechtecken 3245 // alle selektiert sind. Ebenso ist es falsch, die Schnittmenge 3246 // nur zu deselektieren. 3247 // Loesungsmoeglichkeit: Snapshot der Selektion vor dem Auf- 3248 // spannen des Rechtecks merken 3249 if( aBoundRect.IsOver( rRect)) 3250 { 3251 // Schnittmenge zwischen alten Rects & aktuellem Rect desel. 3252 if( bSelected ) 3253 SelectEntry( pEntry, sal_False, sal_True, sal_True ); 3254 } 3255 else 3256 { 3257 // Eintrag eines alten Rects selektieren 3258 if( !bSelected ) 3259 SelectEntry( pEntry, sal_True, sal_True, sal_True ); 3260 } 3261 } 3262 else if( !bOver && bSelected ) 3263 { 3264 // Der Eintrag liegt voellig ausserhalb und wird deshalb desel. 3265 SelectEntry( pEntry, sal_False, sal_True, sal_True ); 3266 } 3267 } 3268 3269 if( !bAlreadySelectingRect ) 3270 nFlags &= ~F_SELECTING_RECT; 3271 3272 pView->Update(); 3273 if( bResetClipRegion ) 3274 pView->SetClipRegion(); 3275 } 3276 3277 void SvxIconChoiceCtrl_Impl::SelectRange( 3278 SvxIconChoiceCtrlEntry* pStart, 3279 SvxIconChoiceCtrlEntry* pEnd, 3280 sal_Bool bAdd ) 3281 { 3282 sal_uLong nFront = GetEntryListPos( pStart ); 3283 sal_uLong nBack = GetEntryListPos( pEnd ); 3284 sal_uLong nFirst = std::min( nFront, nBack ); 3285 sal_uLong nLast = std::max( nFront, nBack ); 3286 sal_uLong i; 3287 SvxIconChoiceCtrlEntry* pEntry; 3288 3289 if ( ! bAdd ) 3290 { 3291 // deselect everything before the first entry if not in 3292 // adding mode 3293 for ( i=0; i<nFirst; i++ ) 3294 { 3295 pEntry = GetEntry( i ); 3296 if( pEntry->IsSelected() ) 3297 SelectEntry( pEntry, sal_False, sal_True, sal_True, sal_True ); 3298 } 3299 } 3300 3301 // select everything between nFirst and nLast 3302 for ( i=nFirst; i<=nLast; i++ ) 3303 { 3304 pEntry = GetEntry( i ); 3305 if( ! pEntry->IsSelected() ) 3306 SelectEntry( pEntry, sal_True, sal_True, sal_True, sal_True ); 3307 } 3308 3309 if ( ! bAdd ) 3310 { 3311 // deselect everything behind the last entry if not in 3312 // adding mode 3313 sal_uLong nEnd = GetEntryCount(); 3314 for ( ; i<nEnd; i++ ) 3315 { 3316 pEntry = GetEntry( i ); 3317 if( pEntry->IsSelected() ) 3318 SelectEntry( pEntry, sal_False, sal_True, sal_True, sal_True ); 3319 } 3320 } 3321 } 3322 3323 sal_Bool SvxIconChoiceCtrl_Impl::IsOver( SvPtrarr* pRectList, const Rectangle& rBoundRect ) const 3324 { 3325 const sal_uInt16 nCount = pRectList->Count(); 3326 for( sal_uInt16 nCur = 0; nCur < nCount; nCur++ ) 3327 { 3328 Rectangle* pRect = (Rectangle*)pRectList->GetObject( nCur ); 3329 if( rBoundRect.IsOver( *pRect )) 3330 return sal_True; 3331 } 3332 return sal_False; 3333 } 3334 3335 void SvxIconChoiceCtrl_Impl::AddSelectedRect( SvxIconChoiceCtrlEntry* pEntry1, 3336 SvxIconChoiceCtrlEntry* pEntry2 ) 3337 { 3338 DBG_ASSERT(pEntry1 && pEntry2,"SelectEntry: Invalid Entry-Ptr"); 3339 Rectangle aRect( GetEntryBoundRect( pEntry1 ) ); 3340 aRect.Union( GetEntryBoundRect( pEntry2 ) ); 3341 AddSelectedRect( aRect ); 3342 } 3343 3344 void SvxIconChoiceCtrl_Impl::AddSelectedRect( const Rectangle& rRect ) 3345 { 3346 Rectangle* pRect = new Rectangle( rRect ); 3347 pRect->Justify(); 3348 aSelectedRectList.Insert( (void*)pRect, aSelectedRectList.Count() ); 3349 } 3350 3351 void SvxIconChoiceCtrl_Impl::ClearSelectedRectList() 3352 { 3353 const sal_uInt16 nCount = aSelectedRectList.Count(); 3354 for( sal_uInt16 nCur = 0; nCur < nCount; nCur++ ) 3355 { 3356 Rectangle* pRect = (Rectangle*)aSelectedRectList.GetObject( nCur ); 3357 delete pRect; 3358 } 3359 aSelectedRectList.Remove( 0, aSelectedRectList.Count() ); 3360 } 3361 3362 void SvxIconChoiceCtrl_Impl::CalcScrollOffsets( const Point& rPosPixel, 3363 long& rX, long& rY, sal_Bool isInDragDrop, sal_uInt16 nBorderWidth) 3364 { 3365 // Scrolling der View, falls sich der Mauszeiger im Grenzbereich des 3366 // Fensters befindet 3367 long nPixelToScrollX = 0; 3368 long nPixelToScrollY = 0; 3369 Size aWndSize = aOutputSize; 3370 3371 nBorderWidth = (sal_uInt16)(Min( (long)(aWndSize.Height()-1), (long)nBorderWidth )); 3372 nBorderWidth = (sal_uInt16)(Min( (long)(aWndSize.Width()-1), (long)nBorderWidth )); 3373 3374 if ( rPosPixel.X() < nBorderWidth ) 3375 { 3376 if( isInDragDrop ) 3377 nPixelToScrollX = -DD_SCROLL_PIXEL; 3378 else 3379 nPixelToScrollX = rPosPixel.X()- nBorderWidth; 3380 } 3381 else if ( rPosPixel.X() > aWndSize.Width() - nBorderWidth ) 3382 { 3383 if( isInDragDrop ) 3384 nPixelToScrollX = DD_SCROLL_PIXEL; 3385 else 3386 nPixelToScrollX = rPosPixel.X() - (aWndSize.Width() - nBorderWidth); 3387 } 3388 if ( rPosPixel.Y() < nBorderWidth ) 3389 { 3390 if( isInDragDrop ) 3391 nPixelToScrollY = -DD_SCROLL_PIXEL; 3392 else 3393 nPixelToScrollY = rPosPixel.Y() - nBorderWidth; 3394 } 3395 else if ( rPosPixel.Y() > aWndSize.Height() - nBorderWidth ) 3396 { 3397 if( isInDragDrop ) 3398 nPixelToScrollY = DD_SCROLL_PIXEL; 3399 else 3400 nPixelToScrollY = rPosPixel.Y() - (aWndSize.Height() - nBorderWidth); 3401 } 3402 3403 rX = nPixelToScrollX; 3404 rY = nPixelToScrollY; 3405 } 3406 3407 IMPL_LINK(SvxIconChoiceCtrl_Impl, AutoArrangeHdl, void*, EMPTYARG ) 3408 { 3409 aAutoArrangeTimer.Stop(); 3410 Arrange( IsAutoArrange() ); 3411 return 0; 3412 } 3413 3414 IMPL_LINK(SvxIconChoiceCtrl_Impl, VisRectChangedHdl, void*, EMPTYARG ) 3415 { 3416 aVisRectChangedTimer.Stop(); 3417 pView->VisibleRectChanged(); 3418 return 0; 3419 } 3420 3421 IMPL_LINK(SvxIconChoiceCtrl_Impl, DocRectChangedHdl, void*, EMPTYARG ) 3422 { 3423 aDocRectChangedTimer.Stop(); 3424 pView->DocumentRectChanged(); 3425 return 0; 3426 } 3427 3428 void SvxIconChoiceCtrl_Impl::PrepareCommandEvent( const CommandEvent& rCEvt ) 3429 { 3430 StopEditTimer(); 3431 SvxIconChoiceCtrlEntry* pEntry = pView->GetEntry( rCEvt.GetMousePosPixel() ); 3432 if( (nFlags & F_DOWN_CTRL) && pEntry && !pEntry->IsSelected() ) 3433 SelectEntry( pEntry, sal_True, sal_True ); 3434 nFlags &= ~(F_DOWN_CTRL | F_DOWN_DESELECT); 3435 } 3436 3437 sal_Bool SvxIconChoiceCtrl_Impl::IsTextHit( SvxIconChoiceCtrlEntry* pEntry, const Point& rDocPos ) 3438 { 3439 Rectangle aRect( CalcTextRect( pEntry )); 3440 if( aRect.IsInside( rDocPos ) ) 3441 return sal_True; 3442 return sal_False; 3443 } 3444 3445 IMPL_LINK(SvxIconChoiceCtrl_Impl, EditTimeoutHdl, Timer*, EMPTYARG ) 3446 { 3447 SvxIconChoiceCtrlEntry* pEntry = GetCurEntry(); 3448 if( bEntryEditingEnabled && pEntry && 3449 pEntry->IsSelected()) 3450 { 3451 if( pView->EditingEntry( pEntry )) 3452 EditEntry( pEntry ); 3453 } 3454 return 0; 3455 } 3456 3457 3458 // 3459 // Funktionen zum Ausrichten der Eintraege am Grid 3460 // 3461 3462 // pStart == 0: Alle Eintraege werden ausgerichtet 3463 // sonst: Alle Eintraege der Zeile ab einschliesslich pStart werden ausgerichtet 3464 void SvxIconChoiceCtrl_Impl::AdjustEntryAtGrid( SvxIconChoiceCtrlEntry* pStart ) 3465 { 3466 SvPtrarr aLists; 3467 pImpCursor->CreateGridAjustData( aLists, pStart ); 3468 const sal_uInt16 nCount = aLists.Count(); 3469 for( sal_uInt16 nCur = 0; nCur < nCount; nCur++ ) 3470 AdjustAtGrid( *(SvPtrarr*)aLists[ nCur ], pStart ); 3471 IcnCursor_Impl::DestroyGridAdjustData( aLists ); 3472 CheckScrollBars(); 3473 } 3474 3475 // Richtet eine Zeile aus, erweitert ggf. die Breite; Bricht die Zeile nicht um 3476 void SvxIconChoiceCtrl_Impl::AdjustAtGrid( const SvPtrarr& rRow, SvxIconChoiceCtrlEntry* pStart ) 3477 { 3478 if( !rRow.Count() ) 3479 return; 3480 3481 sal_Bool bGo; 3482 if( !pStart ) 3483 bGo = sal_True; 3484 else 3485 bGo = sal_False; 3486 3487 long nCurRight = 0; 3488 for( sal_uInt16 nCur = 0; nCur < rRow.Count(); nCur++ ) 3489 { 3490 SvxIconChoiceCtrlEntry* pCur = (SvxIconChoiceCtrlEntry*)rRow[ nCur ]; 3491 if( !bGo && pCur == pStart ) 3492 bGo = sal_True; 3493 3494 //SvIcnVwDataEntry* pViewData = ICNVIEWDATA(pCur); 3495 // Massgebend (fuer unser Auge) ist die Bitmap, da sonst 3496 // durch lange Texte der Eintrag stark springen kann 3497 const Rectangle& rBoundRect = GetEntryBoundRect( pCur ); 3498 Rectangle aCenterRect( CalcBmpRect( pCur, 0 )); 3499 if( bGo && !pCur->IsPosLocked() ) 3500 { 3501 long nWidth = aCenterRect.GetSize().Width(); 3502 Point aNewPos( AdjustAtGrid( aCenterRect, rBoundRect ) ); 3503 while( aNewPos.X() < nCurRight ) 3504 aNewPos.X() += nGridDX; 3505 if( aNewPos != rBoundRect.TopLeft() ) 3506 { 3507 SetEntryPos( pCur, aNewPos ); 3508 pCur->SetFlags( ICNVIEW_FLAG_POS_MOVED ); 3509 nFlags |= F_MOVED_ENTRIES; 3510 } 3511 nCurRight = aNewPos.X() + nWidth; 3512 } 3513 else 3514 { 3515 nCurRight = rBoundRect.Right(); 3516 } 3517 } 3518 } 3519 3520 // Richtet Rect am Grid aus, garantiert jedoch nicht, dass die 3521 // neue Pos. frei ist. Die Pos. kann fuer SetEntryPos verwendet werden. 3522 // Das CenterRect beschreibt den Teil des BoundRects, der fuer 3523 // die Berechnung des Ziel-Rechtecks verwendet wird. 3524 Point SvxIconChoiceCtrl_Impl::AdjustAtGrid( const Rectangle& rCenterRect, 3525 const Rectangle& rBoundRect ) const 3526 { 3527 Point aPos( rCenterRect.TopLeft() ); 3528 Size aSize( rCenterRect.GetSize() ); 3529 3530 aPos.X() -= LROFFS_WINBORDER; 3531 aPos.Y() -= TBOFFS_WINBORDER; 3532 3533 // align (ref ist mitte des rects) 3534 short nGridX = (short)((aPos.X()+(aSize.Width()/2)) / nGridDX); 3535 short nGridY = (short)((aPos.Y()+(aSize.Height()/2)) / nGridDY); 3536 aPos.X() = nGridX * nGridDX; 3537 aPos.Y() = nGridY * nGridDY; 3538 // hor. center 3539 aPos.X() += (nGridDX - rBoundRect.GetSize().Width() ) / 2; 3540 3541 aPos.X() += LROFFS_WINBORDER; 3542 aPos.Y() += TBOFFS_WINBORDER; 3543 3544 return aPos; 3545 } 3546 3547 void SvxIconChoiceCtrl_Impl::SetEntryTextMode( SvxIconChoiceCtrlTextMode eMode, SvxIconChoiceCtrlEntry* pEntry ) 3548 { 3549 if( !pEntry ) 3550 { 3551 if( eTextMode != eMode ) 3552 { 3553 if( eTextMode == IcnShowTextDontKnow ) 3554 eTextMode = IcnShowTextShort; 3555 eTextMode = eMode; 3556 Arrange( sal_True ); 3557 } 3558 } 3559 else 3560 { 3561 if( pEntry->eTextMode != eMode ) 3562 { 3563 pEntry->eTextMode = eMode; 3564 InvalidateEntry( pEntry ); 3565 pView->Invalidate( GetEntryBoundRect( pEntry ) ); 3566 AdjustVirtSize( pEntry->aRect ); 3567 } 3568 } 3569 } 3570 3571 SvxIconChoiceCtrlTextMode SvxIconChoiceCtrl_Impl::GetTextMode( const SvxIconChoiceCtrlEntry* pEntry ) const 3572 { 3573 if( !pEntry ) 3574 return eTextMode; 3575 return pEntry->GetTextMode(); 3576 } 3577 3578 SvxIconChoiceCtrlTextMode SvxIconChoiceCtrl_Impl::GetEntryTextModeSmart( const SvxIconChoiceCtrlEntry* pEntry ) const 3579 { 3580 DBG_ASSERT(pEntry,"GetEntryTextModeSmart: Entry not set"); 3581 SvxIconChoiceCtrlTextMode eMode = pEntry->GetTextMode(); 3582 if( eMode == IcnShowTextDontKnow ) 3583 return eTextMode; 3584 return eMode; 3585 } 3586 3587 void SvxIconChoiceCtrl_Impl::ShowEntryFocusRect( const SvxIconChoiceCtrlEntry* pEntry ) 3588 { 3589 if( !pEntry ) 3590 { 3591 pView->HideFocus(); 3592 } 3593 else 3594 { 3595 Rectangle aRect ( CalcFocusRect( (SvxIconChoiceCtrlEntry*)pEntry ) ); 3596 /*pView->*/ShowFocus( aRect ); 3597 } 3598 } 3599 3600 //////////////////////////////////////////////////////////////////////////////////////////////// 3601 // 3602 // Draw my own focusrect, because the focusrect of the outputdevice has got the inverted color 3603 // of the background. But what will we see, if the the backgroundcolor is gray ? - We will see 3604 // a gray focusrect on a gray background !!! 3605 // 3606 void SvxIconChoiceCtrl_Impl::ShowFocus ( Rectangle& rRect ) 3607 { 3608 Color aBkgColor ( pView->GetBackground().GetColor() ); 3609 Color aPenColor; 3610 sal_uInt16 nColor = ( aBkgColor.GetRed() + aBkgColor.GetGreen() + aBkgColor.GetBlue() ) / 3; 3611 if ( nColor > 128 ) 3612 aPenColor.SetColor ( COL_BLACK ); 3613 else 3614 aPenColor.SetColor( COL_WHITE ); 3615 3616 aFocus.bOn = sal_True; 3617 aFocus.aPenColor = aPenColor; 3618 aFocus.aRect = rRect; 3619 } 3620 3621 void SvxIconChoiceCtrl_Impl::HideFocus () 3622 { 3623 aFocus.bOn = sal_False; 3624 } 3625 3626 void SvxIconChoiceCtrl_Impl::DrawFocusRect ( OutputDevice* pOut ) 3627 { 3628 pOut->SetLineColor( aFocus.aPenColor ); 3629 pOut->SetFillColor(); 3630 Polygon aPolygon ( aFocus.aRect ); 3631 3632 LineInfo aLineInfo ( LINE_DASH ); 3633 3634 aLineInfo.SetDashLen ( 1 ); 3635 3636 aLineInfo.SetDotLen ( 1L ); 3637 aLineInfo.SetDistance ( 1L ); 3638 aLineInfo.SetDotCount ( 1 ); 3639 3640 pOut->DrawPolyLine ( aPolygon, aLineInfo ); 3641 } 3642 3643 sal_Bool SvxIconChoiceCtrl_Impl::IsMnemonicChar( sal_Unicode cChar, sal_uLong& rPos ) const 3644 { 3645 sal_Bool bRet = sal_False; 3646 const vcl::I18nHelper& rI18nHelper = Application::GetSettings().GetUILocaleI18nHelper(); 3647 sal_uLong nEntryCount = GetEntryCount(); 3648 for ( sal_uLong i = 0; i < nEntryCount; ++i ) 3649 { 3650 if ( rI18nHelper.MatchMnemonic( GetEntry( i )->GetText(), cChar ) ) 3651 { 3652 bRet = sal_True; 3653 rPos = i; 3654 break; 3655 } 3656 } 3657 3658 return bRet; 3659 } 3660 3661 // 3662 //////////////////////////////////////////////////////////////////////////////////////////////// 3663 3664 IMPL_LINK(SvxIconChoiceCtrl_Impl, UserEventHdl, void*, nId ) 3665 { 3666 if( nId == EVENTID_ADJUST_SCROLLBARS ) 3667 { 3668 nUserEventAdjustScrBars = 0; 3669 AdjustScrollBars(); 3670 } 3671 else if( nId == EVENTID_SHOW_CURSOR ) 3672 { 3673 nUserEventShowCursor = 0; 3674 ShowCursor( sal_True ); 3675 } 3676 return 0; 3677 } 3678 3679 void SvxIconChoiceCtrl_Impl::CancelUserEvents() 3680 { 3681 if( nUserEventAdjustScrBars ) 3682 { 3683 Application::RemoveUserEvent( nUserEventAdjustScrBars ); 3684 nUserEventAdjustScrBars = 0; 3685 } 3686 if( nUserEventShowCursor ) 3687 { 3688 Application::RemoveUserEvent( nUserEventShowCursor ); 3689 nUserEventShowCursor = 0; 3690 } 3691 } 3692 3693 void SvxIconChoiceCtrl_Impl::InvalidateEntry( SvxIconChoiceCtrlEntry* pEntry ) 3694 { 3695 if( pEntry == pCursor ) 3696 ShowCursor( sal_False ); 3697 pView->Invalidate( pEntry->aRect ); 3698 Center( pEntry ); 3699 pView->Invalidate( pEntry->aRect ); 3700 if( pEntry == pCursor ) 3701 ShowCursor( sal_True ); 3702 } 3703 3704 void SvxIconChoiceCtrl_Impl::EditEntry( SvxIconChoiceCtrlEntry* pEntry ) 3705 { 3706 DBG_ASSERT(pEntry,"EditEntry: Entry not set"); 3707 if( !pEntry ) 3708 return; 3709 3710 StopEntryEditing( sal_True ); 3711 DELETEZ(pEdit); 3712 SetNoSelection(); 3713 3714 pCurEditedEntry = pEntry; 3715 String aEntryText( pView->GetEntryText( pEntry, sal_True ) ); 3716 Rectangle aRect( CalcTextRect( pEntry, 0, sal_True, &aEntryText ) ); 3717 MakeVisible( aRect ); 3718 Point aPos( aRect.TopLeft() ); 3719 aPos = pView->GetPixelPos( aPos ); 3720 aRect.SetPos( aPos ); 3721 pView->HideFocus(); 3722 pEdit = new IcnViewEdit_Impl( 3723 pView, 3724 aRect.TopLeft(), 3725 aRect.GetSize(), 3726 aEntryText, 3727 LINK( this, SvxIconChoiceCtrl_Impl, TextEditEndedHdl ) ); 3728 } 3729 3730 IMPL_LINK( SvxIconChoiceCtrl_Impl, TextEditEndedHdl, IcnViewEdit_Impl*, EMPTYARG ) 3731 { 3732 DBG_ASSERT(pEdit,"TextEditEnded: pEdit not set"); 3733 if( !pEdit ) 3734 { 3735 pCurEditedEntry = 0; 3736 return 0; 3737 } 3738 DBG_ASSERT(pCurEditedEntry,"TextEditEnded: pCurEditedEntry not set"); 3739 3740 if( !pCurEditedEntry ) 3741 { 3742 pEdit->Hide(); 3743 if( pEdit->IsGrabFocus() ) 3744 pView->GrabFocus(); 3745 return 0; 3746 } 3747 3748 String aText; 3749 if ( !pEdit->EditingCanceled() ) 3750 aText = pEdit->GetText(); 3751 else 3752 aText = pEdit->GetSavedValue(); 3753 3754 if( pView->EditedEntry( pCurEditedEntry, aText, pEdit->EditingCanceled() ) ) 3755 InvalidateEntry( pCurEditedEntry ); 3756 if( !GetSelectionCount() ) 3757 SelectEntry( pCurEditedEntry, sal_True ); 3758 3759 pEdit->Hide(); 3760 if( pEdit->IsGrabFocus() ) 3761 pView->GrabFocus(); 3762 // Das Edit kann nicht hier geloescht werden, weil es noch in einem 3763 // Handler steht. Es wird im Dtor oder im naechsten EditEntry geloescht. 3764 pCurEditedEntry = 0; 3765 return 0; 3766 } 3767 3768 void SvxIconChoiceCtrl_Impl::StopEntryEditing( sal_Bool bCancel ) 3769 { 3770 if( pEdit ) 3771 pEdit->StopEditing( bCancel ); 3772 } 3773 3774 void SvxIconChoiceCtrl_Impl::LockEntryPos( SvxIconChoiceCtrlEntry* pEntry, sal_Bool bLock ) 3775 { 3776 if( bLock ) 3777 pEntry->SetFlags( ICNVIEW_FLAG_POS_LOCKED ); 3778 else 3779 pEntry->ClearFlags( ICNVIEW_FLAG_POS_LOCKED ); 3780 } 3781 3782 SvxIconChoiceCtrlEntry* SvxIconChoiceCtrl_Impl::GetFirstSelectedEntry( sal_uLong& rPos ) const 3783 { 3784 if( !GetSelectionCount() ) 3785 return 0; 3786 3787 if( (nWinBits & WB_HIGHLIGHTFRAME) && (eSelectionMode == NO_SELECTION) ) 3788 { 3789 rPos = pView->GetEntryListPos( pCurHighlightFrame ); 3790 return pCurHighlightFrame; 3791 } 3792 3793 sal_uLong nCount = aEntries.Count(); 3794 if( !pHead ) 3795 { 3796 for( sal_uLong nCur = 0; nCur < nCount; nCur++ ) 3797 { 3798 SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( nCur ); 3799 if( pEntry->IsSelected() ) 3800 { 3801 rPos = nCur; 3802 return pEntry; 3803 } 3804 } 3805 } 3806 else 3807 { 3808 SvxIconChoiceCtrlEntry* pEntry = pHead; 3809 while( nCount-- ) 3810 { 3811 if( pEntry->IsSelected() ) 3812 { 3813 rPos = GetEntryListPos( pEntry ); 3814 return pEntry; 3815 } 3816 pEntry = pEntry->pflink; 3817 if( nCount && pEntry == pHead ) 3818 { 3819 DBG_ERROR("SvxIconChoiceCtrl_Impl::GetFirstSelectedEntry > Endlosschleife!"); 3820 return 0; 3821 } 3822 } 3823 } 3824 return 0; 3825 } 3826 3827 // kein Round Robin! 3828 SvxIconChoiceCtrlEntry* SvxIconChoiceCtrl_Impl::GetNextSelectedEntry( sal_uLong& rStartPos ) const 3829 { 3830 sal_uLong nCount = aEntries.Count(); 3831 if( rStartPos > nCount || !GetSelectionCount() ) 3832 return 0; 3833 if( !pHead ) 3834 { 3835 for( sal_uLong nCur = rStartPos+1; nCur < nCount; nCur++ ) 3836 { 3837 SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( nCur ); 3838 if( pEntry->IsSelected() ) 3839 { 3840 rStartPos = nCur; 3841 return pEntry; 3842 } 3843 } 3844 } 3845 else 3846 { 3847 SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( rStartPos ); 3848 pEntry = pEntry->pflink; 3849 while( pEntry != pHead ) 3850 { 3851 if( pEntry->IsSelected() ) 3852 { 3853 rStartPos = GetEntryListPos( pEntry ); 3854 return pEntry; 3855 } 3856 pEntry = pEntry->pflink; 3857 } 3858 } 3859 3860 rStartPos = 0xffffffff; 3861 return 0; 3862 } 3863 3864 void SvxIconChoiceCtrl_Impl::SelectAll( sal_Bool bSelect, sal_Bool bPaint ) 3865 { 3866 bPaint = sal_True; 3867 3868 sal_uLong nCount = aEntries.Count(); 3869 for( sal_uLong nCur = 0; nCur < nCount && (bSelect || GetSelectionCount() ); nCur++ ) 3870 { 3871 SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( nCur ); 3872 SelectEntry( pEntry, bSelect, sal_True, sal_True, bPaint ); 3873 } 3874 nFlags &= (~F_ADD_MODE); 3875 pAnchor = 0; 3876 } 3877 3878 void SvxIconChoiceCtrl_Impl::SaveSelection( List** ppList ) 3879 { 3880 if( !*ppList ) 3881 *ppList = new List; 3882 sal_uLong nPos; 3883 SvxIconChoiceCtrlEntry* pEntry = GetFirstSelectedEntry( nPos ); 3884 while( pEntry && GetSelectionCount() != (*ppList)->Count() ) 3885 { 3886 (*ppList)->Insert( pEntry, LIST_APPEND ); 3887 pEntry = GetNextSelectedEntry( nPos ); 3888 } 3889 } 3890 3891 IcnViewEdit_Impl::IcnViewEdit_Impl( SvtIconChoiceCtrl* pParent, const Point& rPos, 3892 const Size& rSize, const XubString& rData, const Link& rNotifyEditEnd ) : 3893 MultiLineEdit( pParent, (pParent->GetStyle() & WB_ICON) ? WB_CENTER : WB_LEFT), 3894 aCallBackHdl( rNotifyEditEnd ), 3895 bCanceled( sal_False ), 3896 bAlreadyInCallback( sal_False ), 3897 bGrabFocus( sal_False ) 3898 { 3899 Font aFont( pParent->GetPointFont() ); 3900 aFont.SetTransparent( sal_False ); 3901 SetControlFont( aFont ); 3902 if( !pParent->HasFontFillColor() ) 3903 { 3904 Color aColor( pParent->GetBackground().GetColor() ); 3905 SetControlBackground( aColor ); 3906 } 3907 else 3908 SetControlBackground( aFont.GetFillColor() ); 3909 SetControlForeground( aFont.GetColor() ); 3910 SetPosPixel( rPos ); 3911 SetSizePixel( CalcAdjustedSize(rSize) ); 3912 SetText( rData ); 3913 SaveValue(); 3914 3915 aAccReturn.InsertItem( IMPICNVIEW_ACC_RETURN, KeyCode(KEY_RETURN) ); 3916 aAccEscape.InsertItem( IMPICNVIEW_ACC_ESCAPE, KeyCode(KEY_ESCAPE) ); 3917 3918 aAccReturn.SetActivateHdl( LINK( this, IcnViewEdit_Impl, ReturnHdl_Impl) ); 3919 aAccEscape.SetActivateHdl( LINK( this, IcnViewEdit_Impl, EscapeHdl_Impl) ); 3920 GetpApp()->InsertAccel( &aAccReturn);//, ACCEL_ALWAYS ); 3921 GetpApp()->InsertAccel( &aAccEscape);//, ACCEL_ALWAYS ); 3922 Show(); 3923 GrabFocus(); 3924 } 3925 3926 IcnViewEdit_Impl::~IcnViewEdit_Impl() 3927 { 3928 if( !bAlreadyInCallback ) 3929 { 3930 GetpApp()->RemoveAccel( &aAccReturn ); 3931 GetpApp()->RemoveAccel( &aAccEscape ); 3932 } 3933 } 3934 3935 void IcnViewEdit_Impl::CallCallBackHdl_Impl() 3936 { 3937 aTimer.Stop(); 3938 if ( !bAlreadyInCallback ) 3939 { 3940 bAlreadyInCallback = sal_True; 3941 GetpApp()->RemoveAccel( &aAccReturn ); 3942 GetpApp()->RemoveAccel( &aAccEscape ); 3943 Hide(); 3944 aCallBackHdl.Call( this ); 3945 } 3946 } 3947 3948 IMPL_LINK( IcnViewEdit_Impl, Timeout_Impl, Timer*, EMPTYARG ) 3949 { 3950 CallCallBackHdl_Impl(); 3951 return 0; 3952 } 3953 3954 IMPL_LINK( IcnViewEdit_Impl, ReturnHdl_Impl, Accelerator*, EMPTYARG ) 3955 { 3956 bCanceled = sal_False; 3957 bGrabFocus = sal_True; 3958 CallCallBackHdl_Impl(); 3959 return 1; 3960 } 3961 3962 IMPL_LINK( IcnViewEdit_Impl, EscapeHdl_Impl, Accelerator*, EMPTYARG ) 3963 { 3964 bCanceled = sal_True; 3965 bGrabFocus = sal_True; 3966 CallCallBackHdl_Impl(); 3967 return 1; 3968 } 3969 3970 void IcnViewEdit_Impl::KeyInput( const KeyEvent& rKEvt ) 3971 { 3972 KeyCode aCode = rKEvt.GetKeyCode(); 3973 sal_uInt16 nCode = aCode.GetCode(); 3974 3975 switch ( nCode ) 3976 { 3977 case KEY_ESCAPE: 3978 bCanceled = sal_True; 3979 bGrabFocus = sal_True; 3980 CallCallBackHdl_Impl(); 3981 break; 3982 3983 case KEY_RETURN: 3984 bCanceled = sal_False; 3985 bGrabFocus = sal_True; 3986 CallCallBackHdl_Impl(); 3987 break; 3988 3989 default: 3990 MultiLineEdit::KeyInput( rKEvt ); 3991 } 3992 } 3993 3994 long IcnViewEdit_Impl::PreNotify( NotifyEvent& rNEvt ) 3995 { 3996 if( rNEvt.GetType() == EVENT_LOSEFOCUS ) 3997 { 3998 if ( !bAlreadyInCallback && 3999 ((!Application::GetFocusWindow()) || !IsChild(Application::GetFocusWindow()))) 4000 { 4001 bCanceled = sal_False; 4002 aTimer.SetTimeout(10); 4003 aTimer.SetTimeoutHdl(LINK(this,IcnViewEdit_Impl,Timeout_Impl)); 4004 aTimer.Start(); 4005 } 4006 } 4007 return 0; 4008 } 4009 4010 void IcnViewEdit_Impl::StopEditing( sal_Bool bCancel ) 4011 { 4012 if ( !bAlreadyInCallback ) 4013 { 4014 bCanceled = bCancel; 4015 CallCallBackHdl_Impl(); 4016 } 4017 } 4018 4019 sal_uLong SvxIconChoiceCtrl_Impl::GetEntryListPos( SvxIconChoiceCtrlEntry* pEntry ) const 4020 { 4021 if( !(nFlags & F_ENTRYLISTPOS_VALID )) 4022 ((SvxIconChoiceCtrl_Impl*)this)->SetListPositions(); 4023 return pEntry->nPos; 4024 } 4025 4026 void SvxIconChoiceCtrl_Impl::SetEntryListPos( SvxIconChoiceCtrlEntry* pListEntry, sal_uLong nNewPos ) 4027 { 4028 sal_uLong nCurPos = GetEntryListPos( pListEntry ); 4029 if( nCurPos == nNewPos ) 4030 return; 4031 aEntries.List::Remove( nCurPos ); 4032 aEntries.List::Insert( (void*)pListEntry, nNewPos ); 4033 // Eintragspositionen anpassen 4034 sal_uLong nStart, nEnd; 4035 if( nNewPos < nCurPos ) 4036 { 4037 nStart = nNewPos; 4038 nEnd = nCurPos; 4039 } 4040 else 4041 { 4042 nStart = nCurPos; 4043 nEnd = nNewPos; 4044 } 4045 for( ; nStart <= nEnd; nStart++ ) 4046 { 4047 SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( nStart ); 4048 pEntry->nPos = nStart; 4049 } 4050 } 4051 4052 void SvxIconChoiceCtrl_Impl::SetEntryFlags( SvxIconChoiceCtrlEntry* pEntry, sal_uInt16 nEntryFlags ) 4053 { 4054 pEntry->nFlags = nEntryFlags; 4055 if( nEntryFlags & ICNVIEW_FLAG_POS_MOVED ) 4056 nFlags |= F_MOVED_ENTRIES; 4057 } 4058 4059 SvxIconChoiceCtrlEntry* SvxIconChoiceCtrl_Impl::GoLeftRight( SvxIconChoiceCtrlEntry* pStart, sal_Bool bRight ) 4060 { 4061 return pImpCursor->GoLeftRight( pStart, bRight ); 4062 } 4063 4064 SvxIconChoiceCtrlEntry* SvxIconChoiceCtrl_Impl::GoUpDown( SvxIconChoiceCtrlEntry* pStart, sal_Bool bDown ) 4065 { 4066 return pImpCursor->GoUpDown( pStart, bDown ); 4067 } 4068 4069 void SvxIconChoiceCtrl_Impl::InitSettings() 4070 { 4071 const StyleSettings& rStyleSettings = pView->GetSettings().GetStyleSettings(); 4072 4073 if( !pView->HasFont() ) 4074 { 4075 // Unit aus den Settings ist Point 4076 Font aFont( rStyleSettings.GetFieldFont() ); 4077 //const Font& rFont = pView->GetFont(); 4078 //if( pView->HasFontTextColor() ) 4079 aFont.SetColor( rStyleSettings.GetWindowTextColor() ); 4080 //if( pView->HasFontFillColor() ) 4081 //aFont.SetFillColor( rFont.GetFillColor() ); 4082 pView->SetPointFont( aFont ); 4083 SetDefaultTextSize(); 4084 } 4085 4086 //if( !pView->HasFontTextColor() ) 4087 pView->SetTextColor( rStyleSettings.GetFieldTextColor() ); 4088 //if( !pView->HasFontFillColor() ) 4089 pView->SetTextFillColor(); 4090 4091 //if( !pView->HasBackground() ) 4092 pView->SetBackground( rStyleSettings.GetFieldColor()); 4093 4094 long nScrBarSize = rStyleSettings.GetScrollBarSize(); 4095 if( nScrBarSize != nHorSBarHeight || nScrBarSize != nVerSBarWidth ) 4096 { 4097 nHorSBarHeight = nScrBarSize; 4098 Size aSize( aHorSBar.GetSizePixel() ); 4099 aSize.Height() = nScrBarSize; 4100 aHorSBar.Hide(); 4101 aHorSBar.SetSizePixel( aSize ); 4102 4103 nVerSBarWidth = nScrBarSize; 4104 aSize = aVerSBar.GetSizePixel(); 4105 aSize.Width() = nScrBarSize; 4106 aVerSBar.Hide(); 4107 aVerSBar.SetSizePixel( aSize ); 4108 4109 Size aOSize( pView->Control::GetOutputSizePixel() ); 4110 PositionScrollBars( aOSize.Width(), aOSize.Height() ); 4111 AdjustScrollBars(); 4112 } 4113 } 4114 4115 EntryList_Impl::EntryList_Impl( SvxIconChoiceCtrl_Impl* pOwner, sal_uInt16 _nInitSize , sal_uInt16 _nReSize ) : 4116 List( _nInitSize, _nReSize ), 4117 _pOwner( pOwner ) 4118 { 4119 _pOwner->pHead = 0; 4120 } 4121 4122 EntryList_Impl::EntryList_Impl( SvxIconChoiceCtrl_Impl* pOwner, sal_uInt16 _nBlockSize, sal_uInt16 _nInitSize, sal_uInt16 _nReSize ) : 4123 List( _nBlockSize, _nInitSize, _nReSize ), 4124 _pOwner( pOwner ) 4125 { 4126 _pOwner->pHead = 0; 4127 } 4128 4129 EntryList_Impl::~EntryList_Impl() 4130 { 4131 _pOwner->pHead = 0; 4132 } 4133 4134 void EntryList_Impl::Clear() 4135 { 4136 _pOwner->pHead = 0; 4137 List::Clear(); 4138 } 4139 4140 void EntryList_Impl::Insert( SvxIconChoiceCtrlEntry* pEntry, sal_uLong nPos ) 4141 { 4142 List::Insert( pEntry, nPos ); 4143 if( _pOwner->pHead ) 4144 pEntry->SetBacklink( _pOwner->pHead->pblink ); 4145 } 4146 4147 SvxIconChoiceCtrlEntry* EntryList_Impl::Remove( sal_uLong nPos ) 4148 { 4149 SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)List::Remove( nPos ); 4150 DBG_ASSERT(pEntry,"EntryList_Impl::Remove > Entry not found"); 4151 Removed_Impl( pEntry ); 4152 return pEntry; 4153 } 4154 4155 void EntryList_Impl::Remove( SvxIconChoiceCtrlEntry* pEntry ) 4156 { 4157 List::Remove( (void*)pEntry ); 4158 Removed_Impl( pEntry ); 4159 } 4160 4161 void EntryList_Impl::Removed_Impl( SvxIconChoiceCtrlEntry* pEntry ) 4162 { 4163 if( _pOwner->pHead ) 4164 { 4165 if( _pOwner->pHead == pEntry ) 4166 { 4167 if( _pOwner->pHead != pEntry->pflink ) 4168 _pOwner->pHead = pEntry->pflink; 4169 else 4170 { 4171 DBG_ASSERT(!Count(),"EntryList_Impl::Remove > Invalid predecessor" ); 4172 _pOwner->pHead = 0; 4173 } 4174 } 4175 pEntry->Unlink(); 4176 } 4177 } 4178 4179 void SvxIconChoiceCtrl_Impl::SetPositionMode( SvxIconChoiceCtrlPositionMode eMode ) 4180 { 4181 sal_uLong nCur; 4182 4183 if( eMode == ePositionMode ) 4184 return; 4185 4186 SvxIconChoiceCtrlPositionMode eOldMode = ePositionMode; 4187 ePositionMode = eMode; 4188 sal_uLong nCount = aEntries.Count(); 4189 4190 if( eOldMode == IcnViewPositionModeAutoArrange ) 4191 { 4192 // positionieren wir verschobene Eintraege 'hart' gibts noch Probleme 4193 // mit ungewollten Ueberlappungen, da diese Eintrage im Arrange 4194 // nicht beruecksichtigt werden. 4195 #if 1 4196 if( aEntries.Count() ) 4197 aAutoArrangeTimer.Start(); 4198 #else 4199 if( pHead ) 4200 { 4201 // verschobene Eintraege 'hart' auf ihre Position setzen 4202 nCur = nCount; 4203 SvxIconChoiceCtrlEntry* pEntry = pHead; 4204 while( nCur ) 4205 { 4206 SvxIconChoiceCtrlEntry* pPred; 4207 if( GetEntryPredecessor( pEntry, &pPred )) 4208 SetEntryFlags( pEntry, ICNVIEW_FLAG_POS_MOVED ); 4209 pEntry = pEntry->pflink; 4210 nCur--; 4211 } 4212 ClearPredecessors(); 4213 } 4214 #endif 4215 return; 4216 } 4217 4218 if( ePositionMode == IcnViewPositionModeAutoArrange ) 4219 { 4220 List aMovedEntries; 4221 for( nCur = 0; nCur < nCount; nCur++ ) 4222 { 4223 SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( nCur ); 4224 if( pEntry->GetFlags() & (ICNVIEW_FLAG_POS_LOCKED | ICNVIEW_FLAG_POS_MOVED)) 4225 { 4226 SvxIconChoiceCtrlEntry_Impl* pE = new SvxIconChoiceCtrlEntry_Impl( 4227 pEntry, GetEntryBoundRect( pEntry )); 4228 aMovedEntries.Insert( pE, LIST_APPEND ); 4229 } 4230 } 4231 nCount = aMovedEntries.Count(); 4232 for( nCur = 0; nCur < nCount; nCur++ ) 4233 { 4234 SvxIconChoiceCtrlEntry_Impl* pE = (SvxIconChoiceCtrlEntry_Impl*)aMovedEntries.GetObject(nCur); 4235 SetEntryPos( pE->_pEntry, pE->_aPos ); 4236 } 4237 for( nCur = 0; nCur < nCount; nCur++ ) 4238 delete (SvxIconChoiceCtrlEntry_Impl*)aMovedEntries.GetObject( nCur ); 4239 if( aEntries.Count() ) 4240 aAutoArrangeTimer.Start(); 4241 } 4242 else if( ePositionMode == IcnViewPositionModeAutoAdjust ) 4243 { 4244 AdjustEntryAtGrid( 0 ); 4245 } 4246 } 4247 4248 void SvxIconChoiceCtrl_Impl::SetEntryPredecessor( SvxIconChoiceCtrlEntry* pEntry, 4249 SvxIconChoiceCtrlEntry* pPredecessor ) 4250 { 4251 if( !IsAutoArrange() ) 4252 return; 4253 4254 if( pEntry == pPredecessor ) 4255 return; 4256 4257 sal_uLong nPos1 = GetEntryListPos( pEntry ); 4258 if( !pHead ) 4259 { 4260 if( pPredecessor ) 4261 { 4262 sal_uLong nPos2 = GetEntryListPos( pPredecessor ); 4263 if( nPos1 == (nPos2 + 1) ) 4264 return; // ist schon Vorgaenger 4265 } 4266 else if( !nPos1 ) 4267 return; 4268 } 4269 4270 if( !pHead ) 4271 InitPredecessors(); 4272 4273 if( !pPredecessor && pHead == pEntry ) 4274 return; // ist schon der Erste 4275 4276 sal_Bool bSetHead = sal_False; 4277 if( !pPredecessor ) 4278 { 4279 bSetHead = sal_True; 4280 pPredecessor = pHead->pblink; 4281 } 4282 if( pEntry == pHead ) 4283 { 4284 pHead = pHead->pflink; 4285 bSetHead = sal_False; 4286 } 4287 if( pEntry != pPredecessor ) 4288 { 4289 pEntry->Unlink(); 4290 pEntry->SetBacklink( pPredecessor ); 4291 } 4292 if( bSetHead ) 4293 pHead = pEntry; 4294 pEntry->SetFlags( ICNVIEW_FLAG_PRED_SET ); 4295 aAutoArrangeTimer.Start(); 4296 } 4297 4298 sal_Bool SvxIconChoiceCtrl_Impl::GetEntryPredecessor( SvxIconChoiceCtrlEntry* pEntry, 4299 SvxIconChoiceCtrlEntry** ppPredecessor ) 4300 { 4301 *ppPredecessor = 0; 4302 if( !pHead ) 4303 return sal_False; 4304 DBG_ASSERT(pEntry->pblink,"GetEntryPredecessor: Backward link not set"); 4305 DBG_ASSERT(pEntry->pflink,"GetEntryPredecessor: Forward link not set"); 4306 4307 if( pEntry == pHead ) 4308 { 4309 SvxIconChoiceCtrlEntry* pFirst = (SvxIconChoiceCtrlEntry*)aEntries.GetObject(0); 4310 if( pFirst != pEntry ) 4311 return sal_True; 4312 return sal_False; 4313 } 4314 *ppPredecessor = pEntry->pblink; 4315 if( !(pEntry->nFlags & ICNVIEW_FLAG_PRED_SET) && 4316 (GetEntryListPos( *ppPredecessor ) + 1) == GetEntryListPos( pEntry )) 4317 return sal_False; 4318 return sal_True; 4319 } 4320 4321 SvxIconChoiceCtrlEntry* SvxIconChoiceCtrl_Impl::FindEntryPredecessor( SvxIconChoiceCtrlEntry* pEntry, 4322 const Point& rPosTopLeft ) 4323 { 4324 Point aPos( rPosTopLeft ); //TopLeft 4325 Rectangle aCenterRect( CalcBmpRect( pEntry, &aPos )); 4326 Point aNewPos( aCenterRect.Center() ); 4327 sal_uLong nGrid = GetPredecessorGrid( aNewPos ); 4328 sal_uLong nCount = aEntries.Count(); 4329 if( nGrid == ULONG_MAX ) 4330 return 0; 4331 if( nGrid >= nCount ) 4332 nGrid = nCount - 1; 4333 if( !pHead ) 4334 return (SvxIconChoiceCtrlEntry*)aEntries.GetObject( nGrid ); 4335 4336 SvxIconChoiceCtrlEntry* pCur = pHead; // Grid 0 4337 // todo: Liste von hinten aufrollen wenn nGrid > nCount/2 4338 for( sal_uLong nCur = 0; nCur < nGrid; nCur++ ) 4339 pCur = pCur->pflink; 4340 4341 return pCur; 4342 } 4343 4344 sal_uLong SvxIconChoiceCtrl_Impl::GetPredecessorGrid( const Point& rPos) const 4345 { 4346 Point aPos( rPos ); 4347 aPos.X() -= LROFFS_WINBORDER; 4348 aPos.Y() -= TBOFFS_WINBORDER; 4349 sal_uInt16 nMaxCol = (sal_uInt16)(aVirtOutputSize.Width() / nGridDX); 4350 if( nMaxCol ) 4351 nMaxCol--; 4352 sal_uInt16 nGridX = (sal_uInt16)(aPos.X() / nGridDX); 4353 if( nGridX > nMaxCol ) 4354 nGridX = nMaxCol; 4355 sal_uInt16 nGridY = (sal_uInt16)(aPos.Y() / nGridDY); 4356 sal_uInt16 nGridsX = (sal_uInt16)(aOutputSize.Width() / nGridDX); 4357 sal_uLong nGrid = (nGridY * nGridsX) + nGridX; 4358 long nMiddle = (nGridX * nGridDX) + (nGridDX / 2); 4359 if( rPos.X() < nMiddle ) 4360 { 4361 if( !nGrid ) 4362 nGrid = ULONG_MAX; 4363 else 4364 nGrid--; 4365 } 4366 return nGrid; 4367 } 4368 4369 void SvxIconChoiceCtrl_Impl::Flush() 4370 { 4371 if( aAutoArrangeTimer.IsActive() ) 4372 { 4373 AutoArrangeHdl( 0 ); 4374 } 4375 } 4376 4377 sal_Bool SvxIconChoiceCtrl_Impl::RequestHelp( const HelpEvent& rHEvt ) 4378 { 4379 if ( !(rHEvt.GetMode() & HELPMODE_QUICK ) ) 4380 return sal_False; 4381 4382 Point aPos( pView->ScreenToOutputPixel(rHEvt.GetMousePosPixel() ) ); 4383 aPos -= pView->GetMapMode().GetOrigin(); 4384 SvxIconChoiceCtrlEntry* pEntry = GetEntry( aPos, sal_True ); 4385 4386 if ( !pEntry ) 4387 return sal_False; 4388 4389 String sQuickHelpText = pEntry->GetQuickHelpText(); 4390 String aEntryText( pView->GetEntryText( pEntry, sal_False ) ); 4391 Rectangle aTextRect( CalcTextRect( pEntry, 0, sal_False, &aEntryText ) ); 4392 if ( ( !aTextRect.IsInside( aPos ) || !aEntryText.Len() ) && !sQuickHelpText.Len() ) 4393 return sal_False; 4394 4395 Rectangle aOptTextRect( aTextRect ); 4396 aOptTextRect.Bottom() = LONG_MAX; 4397 sal_uInt16 nNewFlags = nCurTextDrawFlags; 4398 nNewFlags &= ~( TEXT_DRAW_CLIP | TEXT_DRAW_ENDELLIPSIS ); 4399 aOptTextRect = pView->GetTextRect( aOptTextRect, aEntryText, nNewFlags ); 4400 if ( aOptTextRect != aTextRect || sQuickHelpText.Len() > 0 ) 4401 { 4402 //aTextRect.Right() = aTextRect.Left() + aRealSize.Width() + 4; 4403 Point aPt( aOptTextRect.TopLeft() ); 4404 aPt += pView->GetMapMode().GetOrigin(); 4405 aPt = pView->OutputToScreenPixel( aPt ); 4406 // Border der Tiphilfe abziehen 4407 aPt.Y() -= 1; 4408 aPt.X() -= 3; 4409 aOptTextRect.SetPos( aPt ); 4410 String sHelpText; 4411 if ( sQuickHelpText.Len() > 0 ) 4412 sHelpText = sQuickHelpText; 4413 else 4414 sHelpText = aEntryText; 4415 Help::ShowQuickHelp( (Window*)pView, aOptTextRect, sHelpText, QUICKHELP_LEFT | QUICKHELP_VCENTER ); 4416 } 4417 4418 return sal_True; 4419 } 4420 4421 void SvxIconChoiceCtrl_Impl::ClearColumnList() 4422 { 4423 if( !pColumns ) 4424 return; 4425 4426 const sal_uInt16 nCount = pColumns->Count(); 4427 for( sal_uInt16 nCur = 0; nCur < nCount; nCur++ ) 4428 { 4429 SvxIconChoiceCtrlColumnInfo* pInfo = (SvxIconChoiceCtrlColumnInfo*) 4430 pColumns->GetObject( nCur ); 4431 delete pInfo; 4432 } 4433 DELETEZ(pColumns); 4434 } 4435 4436 void SvxIconChoiceCtrl_Impl::SetColumn( sal_uInt16 nIndex, const SvxIconChoiceCtrlColumnInfo& rInfo) 4437 { 4438 if( !pColumns ) 4439 pColumns = new SvPtrarr; 4440 while( pColumns->Count() < nIndex + 1 ) 4441 pColumns->Insert( (void*)0, pColumns->Count() ); 4442 4443 SvxIconChoiceCtrlColumnInfo* pInfo = 4444 (SvxIconChoiceCtrlColumnInfo*)pColumns->GetObject(nIndex); 4445 if( !pInfo ) 4446 { 4447 pInfo = new SvxIconChoiceCtrlColumnInfo( rInfo ); 4448 pColumns->Insert( (void*)pInfo, nIndex ); 4449 } 4450 else 4451 { 4452 delete pInfo; 4453 pInfo = new SvxIconChoiceCtrlColumnInfo( rInfo ); 4454 pColumns->Replace( pInfo, nIndex ); 4455 } 4456 4457 // HACK(Detail-Modus ist noch nicht vollstaendig implementiert!) 4458 // dieses Workaround bringts mit einer Spalte zum Fliegen 4459 if( !nIndex && (nWinBits & WB_DETAILS) ) 4460 nGridDX = pInfo->GetWidth(); 4461 4462 if( GetUpdateMode() ) 4463 Arrange( IsAutoArrange() ); 4464 } 4465 4466 const SvxIconChoiceCtrlColumnInfo* SvxIconChoiceCtrl_Impl::GetColumn( sal_uInt16 nIndex ) const 4467 { 4468 if( !pColumns || nIndex >= pColumns->Count() ) 4469 return 0; 4470 return (const SvxIconChoiceCtrlColumnInfo*)pColumns->GetObject( nIndex ); 4471 } 4472 4473 const SvxIconChoiceCtrlColumnInfo* SvxIconChoiceCtrl_Impl::GetItemColumn( sal_uInt16 nSubItem, 4474 long& rLeft ) const 4475 { 4476 rLeft = 0; 4477 if( !pColumns ) 4478 return 0; 4479 const sal_uInt16 nCount = pColumns->Count(); 4480 const SvxIconChoiceCtrlColumnInfo* pCol = 0; 4481 for( sal_uInt16 nCur = 0; nCur < nCount; nCur++ ) 4482 { 4483 pCol = (const SvxIconChoiceCtrlColumnInfo*)pColumns->GetObject( nCur ); 4484 if( !pCol || pCol->GetSubItem() == nSubItem ) 4485 return pCol; 4486 rLeft += pCol->GetWidth(); 4487 } 4488 return pCol; 4489 } 4490 4491 void SvxIconChoiceCtrl_Impl::DrawHighlightFrame( 4492 OutputDevice* pOut, const Rectangle& rBmpRect, sal_Bool bHide ) 4493 { 4494 Rectangle aBmpRect( rBmpRect ); 4495 long nBorder = 2; 4496 if( aImageSize.Width() < 32 ) 4497 nBorder = 1; 4498 aBmpRect.Right() += nBorder; 4499 aBmpRect.Left() -= nBorder; 4500 aBmpRect.Bottom() += nBorder; 4501 aBmpRect.Top() -= nBorder; 4502 4503 if ( bHide ) 4504 pView->Invalidate( aBmpRect ); 4505 else 4506 { 4507 DecorationView aDecoView( pOut ); 4508 sal_uInt16 nDecoFlags; 4509 if ( bHighlightFramePressed ) 4510 nDecoFlags = FRAME_HIGHLIGHT_TESTBACKGROUND | FRAME_HIGHLIGHT_IN; 4511 else 4512 nDecoFlags = FRAME_HIGHLIGHT_TESTBACKGROUND | FRAME_HIGHLIGHT_OUT; 4513 aDecoView.DrawHighlightFrame( aBmpRect, nDecoFlags ); 4514 } 4515 } 4516 4517 void SvxIconChoiceCtrl_Impl::SetEntryHighlightFrame( SvxIconChoiceCtrlEntry* pEntry, 4518 sal_Bool bKeepHighlightFlags ) 4519 { 4520 if( pEntry == pCurHighlightFrame ) 4521 return; 4522 4523 if( !bKeepHighlightFlags ) 4524 bHighlightFramePressed = sal_False; 4525 4526 HideEntryHighlightFrame(); 4527 pCurHighlightFrame = pEntry; 4528 if( pEntry ) 4529 { 4530 Rectangle aBmpRect( CalcFocusRect(pEntry) ); 4531 DrawHighlightFrame( pView, aBmpRect, sal_False ); 4532 } 4533 } 4534 4535 void SvxIconChoiceCtrl_Impl::HideEntryHighlightFrame() 4536 { 4537 if( !pCurHighlightFrame ) 4538 return; 4539 4540 SvxIconChoiceCtrlEntry* pEntry = pCurHighlightFrame; 4541 pCurHighlightFrame = 0; 4542 Rectangle aBmpRect( CalcFocusRect(pEntry) ); 4543 DrawHighlightFrame( pView, aBmpRect, sal_True ); 4544 } 4545 4546 void SvxIconChoiceCtrl_Impl::CallSelectHandler( SvxIconChoiceCtrlEntry* ) 4547 { 4548 // Bei aktiviertem Single-Click-Modus sollte der Selektionshandler 4549 // synchron gerufen werden, weil die Selektion automatisch 4550 // weggenommen wird, wenn der Mauszeiger nicht mehr das Objekt 4551 // beruehrt. Es kann sonst zu fehlenden Select-Aufrufen kommen, 4552 // wenn das Objekt aus einer Mausbewegung heraus selektiert wird, 4553 // weil beim Ausloesen des Timers der Mauszeiger das Objekt u.U. 4554 // schon verlassen hat. 4555 // Fuer spezielle Faelle (=>SfxFileDialog!) koennen synchrone 4556 // Aufrufe auch per WB_NOASYNCSELECTHDL erzwungen werden. 4557 if( nWinBits & (WB_NOASYNCSELECTHDL | WB_HIGHLIGHTFRAME) ) 4558 { 4559 pHdlEntry = 0; 4560 pView->ClickIcon(); 4561 //pView->Select(); 4562 } 4563 else 4564 aCallSelectHdlTimer.Start(); 4565 } 4566 4567 IMPL_LINK( SvxIconChoiceCtrl_Impl, CallSelectHdlHdl, void*, EMPTYARG ) 4568 { 4569 pHdlEntry = 0; 4570 pView->ClickIcon(); 4571 //pView->Select(); 4572 return 0; 4573 } 4574 4575 Point SvxIconChoiceCtrl_Impl::GetPopupMenuPosPixel() const 4576 { 4577 Point aResult; 4578 if( !GetSelectionCount() ) 4579 return aResult; 4580 4581 SvxIconChoiceCtrlEntry* pEntry = GetCurEntry(); 4582 if( !pEntry || !pEntry->IsSelected() ) 4583 { 4584 sal_uLong nNext; 4585 pEntry = GetFirstSelectedEntry( nNext ); 4586 } 4587 if( pEntry ) 4588 { 4589 Rectangle aRect( ((SvxIconChoiceCtrl_Impl*)this)->CalcBmpRect( pEntry ) ); 4590 aResult = aRect.Center(); 4591 aResult = pView->GetPixelPos( aResult ); 4592 } 4593 return aResult; 4594 } 4595 4596 void SvxIconChoiceCtrl_Impl::SetOrigin( const Point& rPos, sal_Bool bDoNotUpdateWallpaper ) 4597 { 4598 MapMode aMapMode( pView->GetMapMode() ); 4599 aMapMode.SetOrigin( rPos ); 4600 pView->SetMapMode( aMapMode ); 4601 if( !bDoNotUpdateWallpaper ) 4602 { 4603 sal_Bool bScrollable = pView->GetBackground().IsScrollable(); 4604 if( pView->HasBackground() && !bScrollable ) 4605 { 4606 Rectangle aRect( GetOutputRect()); 4607 Wallpaper aPaper( pView->GetBackground() ); 4608 aPaper.SetRect( aRect ); 4609 pView->SetBackground( aPaper ); 4610 } 4611 } 4612 } 4613 4614 sal_uLong SvxIconChoiceCtrl_Impl::GetGridCount( const Size& rSize, sal_Bool bCheckScrBars, 4615 sal_Bool bSmartScrBar ) const 4616 { 4617 Size aSize( rSize ); 4618 if( bCheckScrBars && aHorSBar.IsVisible() ) 4619 aSize.Height() -= nHorSBarHeight; 4620 else if( bSmartScrBar && (nWinBits & WB_ALIGN_LEFT) ) 4621 aSize.Height() -= nHorSBarHeight; 4622 4623 if( bCheckScrBars && aVerSBar.IsVisible() ) 4624 aSize.Width() -= nVerSBarWidth; 4625 else if( bSmartScrBar && (nWinBits & WB_ALIGN_TOP) ) 4626 aSize.Width() -= nVerSBarWidth; 4627 4628 if( aSize.Width() < 0 ) 4629 aSize.Width() = 0; 4630 if( aSize.Height() < 0 ) 4631 aSize.Height() = 0; 4632 4633 return IcnGridMap_Impl::GetGridCount( aSize, (sal_uInt16)nGridDX, (sal_uInt16)nGridDY ); 4634 } 4635 4636 sal_Bool SvxIconChoiceCtrl_Impl::HandleShortCutKey( const KeyEvent& rKEvt ) 4637 { 4638 StopEditTimer(); 4639 4640 sal_Bool bRet = sal_False; 4641 4642 DBG_ASSERT( rKEvt.GetKeyCode().IsMod2(), "*SvxIconChoiceCtrl_Impl::HandleShortCutKey(): no <ALT> pressed!?" ); 4643 4644 sal_Unicode cChar = rKEvt.GetCharCode(); 4645 sal_uLong nPos = (sal_uLong)-1; 4646 4647 if( cChar && IsMnemonicChar( cChar, nPos ) ) 4648 { 4649 // shortcut is clicked 4650 SvxIconChoiceCtrlEntry* pNewCursor = GetEntry( nPos ); 4651 SvxIconChoiceCtrlEntry* pOldCursor = pCursor; 4652 if( pNewCursor != pOldCursor ) 4653 { 4654 SetCursor_Impl( pOldCursor, pNewCursor, sal_False, sal_False, sal_False ); 4655 4656 if( pNewCursor != NULL ) 4657 { 4658 pHdlEntry = pNewCursor; 4659 pCurHighlightFrame = pHdlEntry; 4660 pView->ClickIcon(); 4661 pCurHighlightFrame = NULL; 4662 } 4663 } 4664 bRet = sal_True; 4665 } 4666 4667 return bRet; 4668 } 4669 4670 // ----------------------------------------------------------------------- 4671 4672 void SvxIconChoiceCtrl_Impl::CallEventListeners( sal_uLong nEvent, void* pData ) 4673 { 4674 pView->CallImplEventListeners( nEvent, pData ); 4675 } 4676 4677 4678