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