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