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 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