xref: /aoo41x/main/svtools/source/control/roadmap.cxx (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_svtools.hxx"
30 #include <svtools/roadmap.hxx>
31 
32 #ifndef _STRING_HXX
33 #define _STRING_HXX
34 #endif
35 
36 #include <vector>
37 #include <algorithm>
38 #include <vcl/bitmap.hxx>
39 #include <tools/color.hxx>
40 #include <memory>
41 
42 #define ROADMAP_INDENT_X        4
43 #define ROADMAP_INDENT_Y        27
44 #define ROADMAP_ITEM_DISTANCE_Y 6
45 #define RMINCOMPLETE        -1
46 #define NADDITEM            1
47 #define INCOMPLETELABEL     ::String::CreateFromAscii("...")        // TODO: Cast to String
48 
49 //.........................................................................
50 namespace svt
51 {
52 //.........................................................................
53 
54     typedef std::vector< ::rtl::OUString > S_Vector;
55     typedef std::vector< RoadmapItem* > HL_Vector;
56 
57 	//=====================================================================
58 	//= ColorChanger
59 	//=====================================================================
60 	class IDLabel :  public FixedText
61 	{
62 	public:
63 		IDLabel( Window* _pParent, WinBits _nWinStyle = 0 );
64 		~IDLabel( );
65 		virtual void	DataChanged( const DataChangedEvent& rDCEvt );
66 	};
67 
68 	//=====================================================================
69 	//= ColorChanger
70 	//=====================================================================
71 	class ColorChanger
72 	{
73 	protected:
74 		OutputDevice*	m_pDev;
75 
76 	public:
77 		ColorChanger( OutputDevice* _pDev, const Color& _rNewLineColor, const Color& _rNewFillColor )
78 			:m_pDev( _pDev )
79 		{
80 			m_pDev->Push( PUSH_LINECOLOR | PUSH_FILLCOLOR );
81 			m_pDev->SetLineColor( _rNewLineColor );
82 			m_pDev->SetFillColor( _rNewFillColor );
83 		}
84 
85 		~ColorChanger()
86 		{
87 			m_pDev->Pop();
88 		}
89 	};
90 
91 	//=====================================================================
92 	//= RoadmapItem
93 	//=====================================================================
94 	class RoadmapItem : public RoadmapTypes
95 	{
96 	private:
97 		IDLabel*                mpID;
98 		HyperLabel*             mpDescription;
99         const Size              m_aItemPlayground;
100 
101 	public:
102 		RoadmapItem( ORoadmap& _rParent, const Size& _rItemPlayground );
103 		~RoadmapItem( );
104 
105         void					SetID( sal_Int16 _ID );
106         sal_Int16				GetID() const;
107 
108         void					SetIndex( ItemIndex _Index );
109         ItemIndex               GetIndex() const;
110 
111         void					SetLabel( const ::rtl::OUString& _rText );
112         ::rtl::OUString			GetLabel( );
113 
114 		void					Update( ItemIndex _RMIndex, const ::rtl::OUString& _rText );
115 
116         void					SetPosition( RoadmapItem* OldHyperLabel );
117 
118 		void					ToggleBackgroundColor( const Color& _rGBColor );
119         void					SetInteractive( sal_Bool _bInteractive );
120 
121         void					SetClickHdl( const Link& rLink );
122         const Link&				GetClickHdl() const;
123 		void					SetZOrder( RoadmapItem* pRefRoadmapHyperLabel, sal_uInt16 nFlags );
124 		void					Enable( sal_Bool bEnable = sal_True);
125 		sal_Bool					IsEnabled() const;
126 		void					GrabFocus();
127 
128         bool                    Contains( const Window* _pWindow ) const;
129 
130 		HyperLabel*				GetDescriptionHyperLabel() const { return mpDescription; }
131 
132     private:
133         void                    ImplUpdateIndex( const ItemIndex _nIndex );
134         void                    ImplUpdatePosSize();
135 	};
136 
137 	//=====================================================================
138 	//= RoadmapImpl
139 	//=====================================================================
140     class RoadmapImpl : public RoadmapTypes
141 	{
142 	protected:
143         const ORoadmap&     m_rAntiImpl;
144         Link                m_aSelectHdl;
145 		BitmapEx	        m_aPicture;
146         HL_Vector           m_aRoadmapSteps;
147         ItemId              m_iCurItemID;
148         sal_Bool            m_bInteractive;
149         sal_Bool            m_bComplete;
150         Size                m_aItemSizePixel;
151 
152 	public:
153         RoadmapImpl( const ORoadmap& _rAntiImpl )
154             :m_rAntiImpl( _rAntiImpl )
155             ,m_iCurItemID( -1 )
156             ,m_bInteractive( sal_True )
157             ,m_bComplete( sal_True )
158         {
159         }
160 
161         RoadmapItem* InCompleteHyperLabel;
162 
163         void			    addHyperLabel( RoadmapItem*  _rRoadmapStep ) { m_aRoadmapSteps.push_back(_rRoadmapStep); }
164 
165         HL_Vector&	        getHyperLabels() { return m_aRoadmapSteps; }
166 		const HL_Vector&	getHyperLabels() const { return m_aRoadmapSteps; }
167 
168         void                insertHyperLabel( ItemIndex _Index, RoadmapItem* _rRoadmapStep ) { m_aRoadmapSteps.insert( m_aRoadmapSteps.begin() + _Index, _rRoadmapStep ); }
169 
170         ItemIndex           getItemCount() const { return m_aRoadmapSteps.size();}
171 
172         void                setCurItemID( ItemId i ) {m_iCurItemID = i; }
173         ItemId              getCurItemID() const { return m_iCurItemID; }
174 
175         void                setInteractive(const sal_Bool _bInteractive) {m_bInteractive = _bInteractive; }
176         sal_Bool            isInteractive() const { return m_bInteractive; };
177 
178         void                setComplete(const sal_Bool _bComplete) {m_bComplete = _bComplete; }
179         sal_Bool            isComplete() const { return m_bComplete; };
180 
181 		void			    setPicture( const BitmapEx& _rPic ) { m_aPicture = _rPic; }
182 		const BitmapEx&	    getPicture( ) const { return m_aPicture; }
183 
184         void			    setSelectHdl( const Link& _rHdl ) { m_aSelectHdl = _rHdl; }
185 		const Link&	        getSelectHdl( ) const { return m_aSelectHdl; }
186 
187         void                initItemSize();
188         const Size&         getItemSize() const { return m_aItemSizePixel; }
189 
190         void removeHyperLabel( ItemIndex _Index )
191         {
192             if ( ( _Index > -1 ) && ( _Index < getItemCount() ) )
193             {
194                 delete m_aRoadmapSteps[_Index];
195                 m_aRoadmapSteps.erase( m_aRoadmapSteps.begin() + _Index);
196             }
197         }
198 	};
199 
200 
201 	//=====================================================================
202 	//= Roadmap
203 	//=====================================================================
204 	//---------------------------------------------------------------------
205     void RoadmapImpl::initItemSize()
206     {
207         Size aLabelSize( m_rAntiImpl.GetOutputSizePixel() );
208         aLabelSize.Height() = m_rAntiImpl.LogicToPixel( Size( 0, LABELBASEMAPHEIGHT ), MAP_APPFONT ).Height();
209         aLabelSize.Width() -= m_rAntiImpl.LogicToPixel( Size( 2 * ROADMAP_INDENT_X, 0 ), MAP_APPFONT ).Width();
210         m_aItemSizePixel = aLabelSize;
211     }
212 
213 	//=====================================================================
214 	//= Roadmap
215 	//=====================================================================
216 	//---------------------------------------------------------------------
217 	ORoadmap::ORoadmap( Window* _pParent, const ResId& _rId )
218         :Control( _pParent, _rId )
219 		,m_pImpl( new RoadmapImpl( *this ) )
220 	{
221 		implInit();
222 	}
223 
224 	//---------------------------------------------------------------------
225 	ORoadmap::ORoadmap( Window* _pParent, WinBits _nWinStyle )
226 		:Control( _pParent, _nWinStyle )
227 		,m_pImpl( new RoadmapImpl( *this ) )
228 
229     {
230         implInit();
231 	}
232 
233 	//---------------------------------------------------------------------
234 	void ORoadmap::implInit()
235 	{
236 		const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
237 		Color aTextColor = rStyleSettings.GetFieldTextColor();
238         Font aFont = GetFont( );
239 		aFont.SetColor( aTextColor );
240 		aFont.SetWeight( WEIGHT_BOLD );
241         aFont.SetUnderline( UNDERLINE_SINGLE );
242 		SetFont( aFont );
243 		SetBackground( Wallpaper( rStyleSettings.GetFieldColor() ) );
244         m_pImpl->InCompleteHyperLabel = NULL;
245         m_pImpl->setCurItemID(-1 );
246         m_pImpl->setComplete( sal_True );
247 
248         // Roadmap control should be reachable as one unit with a Tab key
249         // the next Tab key should spring out of the control.
250         // To reach it the control itself should get focus and set it
251         // on entries. The entries themself should not be reachable with
252         // the Tab key directly. So each entry should have WB_NOTABSTOP.
253         //
254         // In other words the creator should create the control with the following
255         // flags:
256         // SetStyle( ( GetStyle() | WB_TABSTOP ) & ~WB_DIALOGCONTROL );
257 
258 // TODO: if somebody sets a new font from outside (OutputDevice::SetFont), we would have to react
259 // on this with calculating a new bold font.
260 // Unfortunately, the OutputDevice does not offer a notify mechanism for a changed font.
261 // So settings the font from outside is simply a forbidded scenario at the moment
262         EnableMapMode( sal_False );
263 	}
264 
265 	//---------------------------------------------------------------------
266 	ORoadmap::~ORoadmap( )
267 	{
268         HL_Vector aItemsCopy = m_pImpl->getHyperLabels();
269         m_pImpl->getHyperLabels().clear();
270         for ( HL_Vector::iterator i = aItemsCopy.begin(); i< aItemsCopy.end(); ++i )
271         {
272             delete *i;
273         }
274         if ( ! m_pImpl->isComplete() )
275             delete m_pImpl->InCompleteHyperLabel;
276 		delete m_pImpl;
277         m_pImpl = NULL;
278     }
279 
280 
281     RoadmapTypes::ItemId ORoadmap::GetCurrentRoadmapItemID() const
282     {
283         return m_pImpl->getCurItemID();
284     }
285 
286 
287 	RoadmapItem* ORoadmap::GetPreviousHyperLabel( ItemIndex _Index)
288 	{
289 		RoadmapItem* pOldItem = NULL;
290 		if ( _Index > 0 )
291 			pOldItem = m_pImpl->getHyperLabels().at( _Index - 1 );
292 		return pOldItem;
293 	}
294 
295 
296    	//---------------------------------------------------------------------
297 
298     RoadmapItem* ORoadmap::InsertHyperLabel( ItemIndex _Index, const ::rtl::OUString& _sLabel, ItemId _RMID, sal_Bool _bEnabled)
299     {
300         if ( m_pImpl->getItemCount() == 0 )
301             m_pImpl->initItemSize();
302 
303         RoadmapItem* pItem = NULL;
304         RoadmapItem* pOldItem = GetPreviousHyperLabel( _Index );
305 
306         pItem = new RoadmapItem( *this, m_pImpl->getItemSize() );
307         if ( _RMID != RMINCOMPLETE )
308         {
309             pItem->SetInteractive( m_pImpl->isInteractive() );
310             m_pImpl->insertHyperLabel( _Index, pItem );
311         }
312         else
313         {
314             pItem->SetInteractive( sal_False );
315 		}
316         pItem->SetPosition( pOldItem );
317         pItem->Update( _Index, _sLabel );
318         pItem->SetClickHdl(LINK( this, ORoadmap, ImplClickHdl ) );
319         pItem->SetID( _RMID );
320         pItem->SetIndex( _Index );
321         if (!_bEnabled)
322             pItem->Enable( _bEnabled );
323         return pItem;
324     }
325 
326 	//---------------------------------------------------------------------
327 	void ORoadmap::SetRoadmapBitmap( const BitmapEx& _rBmp, sal_Bool _bInvalidate )
328 	{
329 		m_pImpl->setPicture( _rBmp );
330 		if ( _bInvalidate )
331 			Invalidate( );
332 	}
333 
334 	//---------------------------------------------------------------------
335 	const BitmapEx& ORoadmap::GetRoadmapBitmap( ) const
336 	{
337 		return m_pImpl->getPicture( );
338 	}
339 
340 	//---------------------------------------------------------------------
341     void ORoadmap::SetRoadmapInteractive( sal_Bool _bInteractive )
342     {
343         m_pImpl->setInteractive( _bInteractive );
344 
345         const HL_Vector& rItems = m_pImpl->getHyperLabels();
346         for (   HL_Vector::const_iterator i = rItems.begin();
347                 i < rItems.end();
348                 ++i
349             )
350         {
351             (*i)->SetInteractive( _bInteractive );
352         }
353     }
354 
355 	//---------------------------------------------------------------------
356     sal_Bool ORoadmap::IsRoadmapInteractive()
357     {
358         return m_pImpl->isInteractive();
359     }
360 
361 	//---------------------------------------------------------------------
362     void ORoadmap::SetRoadmapComplete( sal_Bool _bComplete )
363     {
364         sal_Bool bWasComplete = m_pImpl->isComplete();
365         m_pImpl->setComplete( _bComplete );
366         if ( _bComplete )
367         {
368             if ( m_pImpl->InCompleteHyperLabel != NULL)
369             {
370                 delete m_pImpl->InCompleteHyperLabel;
371                 m_pImpl->InCompleteHyperLabel = NULL;
372             }
373         }
374         else if ( bWasComplete )
375             m_pImpl->InCompleteHyperLabel = InsertHyperLabel( m_pImpl->getItemCount(), ::String::CreateFromAscii( "..." ), RMINCOMPLETE );
376     }
377 
378 	//---------------------------------------------------------------------
379     void ORoadmap::UpdatefollowingHyperLabels( ItemIndex _nIndex )
380     {
381         const HL_Vector& rItems = m_pImpl->getHyperLabels();
382         if ( _nIndex < (ItemIndex)rItems.size() )
383         {
384             RoadmapItem* pItem = NULL;
385             for (   HL_Vector::const_iterator i = rItems.begin() + _nIndex;
386                     i< rItems.end();
387                     ++i, ++_nIndex
388                 )
389             {
390                 pItem = *i;
391 
392                 pItem->SetIndex( _nIndex );
393                 pItem->SetPosition( GetPreviousHyperLabel( _nIndex ) );
394             }
395         }
396         if ( ! m_pImpl->isComplete() )
397         {
398 	        RoadmapItem* pOldItem = GetPreviousHyperLabel( m_pImpl->getItemCount() );
399             m_pImpl->InCompleteHyperLabel->SetPosition( pOldItem );
400             m_pImpl->InCompleteHyperLabel->Update( m_pImpl->getItemCount(), ::String::CreateFromAscii("...") );
401         }
402     }
403 
404 	//---------------------------------------------------------------------
405     void ORoadmap::ReplaceRoadmapItem( ItemIndex _Index, const ::rtl::OUString& _RoadmapItem, ItemId _RMID, sal_Bool _bEnabled )
406     {
407         RoadmapItem* pItem = GetByIndex( _Index);
408         if ( pItem != NULL )
409         {
410             pItem->Update( _Index,  _RoadmapItem );
411             pItem->SetID( _RMID );
412             pItem->Enable( _bEnabled );
413         }
414     }
415 
416 	//---------------------------------------------------------------------
417     RoadmapTypes::ItemIndex ORoadmap::GetItemCount() const
418     {
419         return m_pImpl->getItemCount();
420     }
421 
422 	//---------------------------------------------------------------------
423     RoadmapTypes::ItemId ORoadmap::GetItemID( ItemIndex _nIndex ) const
424     {
425         const RoadmapItem* pHyperLabel = GetByIndex( _nIndex );
426         if ( pHyperLabel )
427             return pHyperLabel->GetID();
428         return -1;
429     }
430 
431 	//---------------------------------------------------------------------
432     RoadmapTypes::ItemIndex ORoadmap::GetItemIndex( ItemId _nID ) const
433     {
434         ItemId nLocID = 0;
435         const HL_Vector& rItems = m_pImpl->getHyperLabels();
436         for (   HL_Vector::const_iterator i = rItems.begin();
437                 i < rItems.end();
438                 ++i
439             )
440         {
441             nLocID = (*i)->GetID();
442             if ( nLocID == _nID )
443                 return ItemIndex( i - rItems.begin() );
444         }
445         return -1;
446     }
447 
448 	//---------------------------------------------------------------------
449     void ORoadmap::InsertRoadmapItem( ItemIndex _Index, const ::rtl::OUString& _RoadmapItem, ItemId _nUniqueId, sal_Bool _bEnabled )
450     {
451         InsertHyperLabel( _Index, _RoadmapItem, _nUniqueId, _bEnabled );
452             // Todo: YPos is superfluous, if items are always appended
453         UpdatefollowingHyperLabels( _Index + 1 );
454     }
455 
456 	//---------------------------------------------------------------------
457     void ORoadmap::DeleteRoadmapItem( ItemIndex _Index )
458     {
459         if ( m_pImpl->getItemCount() > 0 && ( _Index > -1)  &&  ( _Index < m_pImpl->getItemCount() ) )
460         {
461             m_pImpl->removeHyperLabel( _Index );
462             UpdatefollowingHyperLabels( _Index );
463         }
464     }
465 
466 	//---------------------------------------------------------------------
467     sal_Bool ORoadmap::IsRoadmapComplete( ) const
468     {
469         return m_pImpl->isComplete();
470     }
471 
472 	//---------------------------------------------------------------------
473     sal_Bool ORoadmap::IsRoadmapItemEnabled( ItemId _nItemId, ItemIndex _nStartIndex  ) const
474     {
475         const RoadmapItem* _pLabelItem = GetByID( _nItemId, _nStartIndex  );
476         return _pLabelItem ? _pLabelItem->IsEnabled() : sal_False;
477     }
478 
479 	//---------------------------------------------------------------------
480     void ORoadmap::EnableRoadmapItem( ItemId _nItemId, sal_Bool _bEnable, ItemIndex _nStartIndex )
481     {
482         RoadmapItem* pItem = GetByID( _nItemId, _nStartIndex );
483         if ( pItem != NULL )
484             pItem->Enable( _bEnable );
485     }
486 
487 	//---------------------------------------------------------------------
488     void ORoadmap::ChangeRoadmapItemLabel( ItemId _nID, const ::rtl::OUString& _sLabel, ItemIndex _nStartIndex )
489     {
490         RoadmapItem* pItem = GetByID( _nID, _nStartIndex );
491         if ( pItem != NULL )
492 		{
493             pItem->Update( pItem->GetIndex(), _sLabel );
494 
495             const HL_Vector& rItems = m_pImpl->getHyperLabels();
496 			for (   HL_Vector::const_iterator i = rItems.begin() + _nStartIndex;
497                     i < rItems.end();
498                     ++i
499                 )
500 			{
501 				(*i)->SetPosition( GetPreviousHyperLabel( i - rItems.begin() ) );
502 			}
503 		}
504     }
505 
506 	//---------------------------------------------------------------------
507 
508     ::rtl::OUString ORoadmap::GetRoadmapItemLabel( ItemId _nID, ItemIndex _nStartIndex )
509     {
510         RoadmapItem* pItem = GetByID( _nID, _nStartIndex );
511         if ( pItem != NULL )
512             return pItem->GetLabel();
513         else
514             return ::rtl::OUString();
515     }
516 
517 	//---------------------------------------------------------------------
518     void ORoadmap::ChangeRoadmapItemID( ItemId _nID, ItemId _NewID, ItemIndex _nStartIndex )
519     {
520         RoadmapItem* pItem = GetByID( _nID, _nStartIndex );
521         if ( pItem != NULL )
522             pItem->SetID( _NewID );
523     }
524 
525 	//---------------------------------------------------------------------
526     RoadmapItem* ORoadmap::GetByID( ItemId _nID, ItemIndex _nStartIndex)
527     {
528         ItemId nLocID = 0;
529         const HL_Vector& rItems = m_pImpl->getHyperLabels();
530         for (   HL_Vector::const_iterator i = rItems.begin() + _nStartIndex;
531                 i < rItems.end();
532                 ++i
533             )
534         {
535             nLocID = (*i)->GetID();
536             if ( nLocID == _nID )
537                 return *i;
538         }
539         return NULL;
540     }
541 
542 	//---------------------------------------------------------------------
543     const RoadmapItem* ORoadmap::GetByID( ItemId _nID, ItemIndex _nStartIndex  ) const
544     {
545         return const_cast< ORoadmap* >( this )->GetByID( _nID, _nStartIndex );
546     }
547 
548 	//---------------------------------------------------------------------
549     RoadmapItem* ORoadmap::GetByIndex( ItemIndex _nItemIndex)
550     {
551         const HL_Vector& rItems = m_pImpl->getHyperLabels();
552         if ( ( _nItemIndex > -1 ) && ( _nItemIndex < (ItemIndex)rItems.size() ) )
553         {
554             return rItems.at( _nItemIndex );
555         }
556         return NULL;
557     }
558 
559     //---------------------------------------------------------------------
560     const RoadmapItem* ORoadmap::GetByIndex( ItemIndex _nItemIndex ) const
561     {
562         return const_cast< ORoadmap* >( this )->GetByIndex( _nItemIndex );
563     }
564 
565 	//---------------------------------------------------------------------
566     RoadmapTypes::ItemId ORoadmap::GetNextAvailableItemId( ItemIndex _nNewIndex )
567     {
568         RoadmapItem* pItem = NULL;
569 
570         ItemIndex searchIndex = ++_nNewIndex;
571         while ( searchIndex < m_pImpl->getItemCount() )
572         {
573             pItem = GetByIndex( searchIndex );
574             if ( pItem->IsEnabled() )
575                 return pItem->GetID( );
576 
577             ++searchIndex;
578         }
579         return -1;
580     }
581 
582 	//---------------------------------------------------------------------
583     RoadmapTypes::ItemId ORoadmap::GetPreviousAvailableItemId( ItemIndex _nNewIndex )
584     {
585         RoadmapItem* pItem = NULL;
586         ItemIndex searchIndex = --_nNewIndex;
587         while ( searchIndex > -1 )
588         {
589             pItem = GetByIndex( searchIndex );
590             if ( pItem->IsEnabled() )
591                 return pItem->GetID( );
592 
593             searchIndex--;
594         }
595         return -1;
596     }
597 
598 	//---------------------------------------------------------------------
599     void ORoadmap::DeselectOldRoadmapItems()
600     {
601         const HL_Vector& rItems = m_pImpl->getHyperLabels();
602         for (   HL_Vector::const_iterator i = rItems.begin();
603                 i < rItems.end();
604                 ++i
605             )
606         {
607             (*i)->ToggleBackgroundColor( COL_TRANSPARENT );
608         }
609     }
610 
611 	//---------------------------------------------------------------------
612     void ORoadmap::SetItemSelectHdl( const Link& _rHdl )
613     {
614         m_pImpl->setSelectHdl( _rHdl );
615     }
616 
617 	//---------------------------------------------------------------------
618     Link ORoadmap::GetItemSelectHdl( ) const
619     {
620         return m_pImpl->getSelectHdl();
621     }
622 
623 	//---------------------------------------------------------------------
624     void ORoadmap::Select()
625     {
626         GetItemSelectHdl().Call( this );
627         CallEventListeners( VCLEVENT_ROADMAP_ITEMSELECTED );
628     }
629 
630     //---------------------------------------------------------------------
631     void ORoadmap::GetFocus()
632 	{
633         RoadmapItem* pCurHyperLabel = GetByID( GetCurrentRoadmapItemID() );
634         if ( pCurHyperLabel != NULL )
635 		    pCurHyperLabel->GrabFocus();
636 	}
637 
638 	//---------------------------------------------------------------------
639     sal_Bool ORoadmap::SelectRoadmapItemByID( ItemId _nNewID )
640     {
641         DeselectOldRoadmapItems();
642         RoadmapItem* pItem = GetByID( _nNewID );
643         if ( pItem != NULL )
644         {
645             if ( pItem->IsEnabled() )
646             {
647 				const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
648                 pItem->ToggleBackgroundColor( rStyleSettings.GetHighlightColor() ); //HighlightColor
649 
650 				pItem->GrabFocus();
651                 m_pImpl->setCurItemID(_nNewID);
652 
653                 Select();
654                 return sal_True;
655             }
656         }
657         return sal_False;
658     }
659 
660 	//---------------------------------------------------------------------
661 	void ORoadmap::Paint( const Rectangle& _rRect )
662 	{
663 		Control::Paint( _rRect );
664 
665 
666 		// draw the bitmap
667 		if ( !!m_pImpl->getPicture() )
668 		{
669 			Size aBitmapSize = m_pImpl->getPicture().GetSizePixel();
670 			Size aMySize = GetOutputSizePixel();
671 
672 			Point aBitmapPos( aMySize.Width() - aBitmapSize.Width(),  aMySize.Height() - aBitmapSize.Height() );
673 
674 			// draw it
675 			DrawBitmapEx( aBitmapPos, m_pImpl->getPicture() );
676 		}
677 
678         //.................................................................
679 		// draw the headline
680         DrawHeadline();
681 	}
682 
683 	//---------------------------------------------------------------------
684     void ORoadmap::DrawHeadline()
685 	{
686 		Point aTextPos = LogicToPixel( Point( ROADMAP_INDENT_X, 8 ), MAP_APPFONT );
687 
688 		Size aOutputSize( GetOutputSizePixel() );
689 
690 		// draw it
691 		DrawText( Rectangle( aTextPos, aOutputSize ), GetText(), TEXT_DRAW_LEFT | TEXT_DRAW_TOP | TEXT_DRAW_MULTILINE | TEXT_DRAW_WORDBREAK );
692         DrawTextLine( aTextPos, aOutputSize.Width(), STRIKEOUT_NONE, UNDERLINE_SINGLE, UNDERLINE_NONE, sal_False );
693 		const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
694         SetLineColor( rStyleSettings.GetFieldTextColor());
695 		SetTextColor(rStyleSettings.GetFieldTextColor());
696 	}
697 
698 	//---------------------------------------------------------------------
699     RoadmapItem* ORoadmap::GetByPointer(Window* pWindow)
700     {
701         const HL_Vector& rItems = m_pImpl->getHyperLabels();
702         for (   HL_Vector::const_iterator i = rItems.begin();
703                 i < rItems.end();
704                 ++i
705             )
706         {
707 			if ( (*i)->Contains( pWindow ) )
708                 return *i;
709         }
710         return NULL;
711     }
712 
713 	//---------------------------------------------------------------------
714     long ORoadmap::PreNotify( NotifyEvent& _rNEvt )
715     {
716         // capture KeyEvents for taskpane cycling
717         if ( _rNEvt.GetType() == EVENT_KEYINPUT )
718         {
719             Window* pWindow = _rNEvt.GetWindow();
720             RoadmapItem* pItem = GetByPointer( pWindow );
721             if ( pItem != NULL )
722             {
723                 sal_Int16 nKeyCode = _rNEvt.GetKeyEvent()->GetKeyCode().GetCode();
724 		        switch( nKeyCode )
725 		        {
726 			        case KEY_UP:
727                         {   // Note: Performancewise this is not optimal, because we search for an ID in the labels
728                             //       and afterwards we search again for a label with the appropriate ID ->
729                             //       unnecessarily we search twice!!!
730                             ItemId nPrevItemID = GetPreviousAvailableItemId( pItem->GetIndex() );
731                             if ( nPrevItemID != -1 )
732                                 return SelectRoadmapItemByID( nPrevItemID );
733                         }
734                         break;
735 			        case KEY_DOWN:
736                         {
737                             ItemId nNextItemID = GetNextAvailableItemId( pItem->GetIndex() );
738                             if ( nNextItemID != -1 )
739                                 return SelectRoadmapItemByID( nNextItemID );
740                         }
741                         break;
742                     case KEY_SPACE:
743                         return SelectRoadmapItemByID( pItem->GetID() );
744                 }
745             }
746         }
747         return Window::PreNotify( _rNEvt );
748     }
749 
750 	//---------------------------------------------------------------------
751   	IMPL_LINK(ORoadmap, ImplClickHdl, HyperLabel*, _CurHyperLabel)
752 	{
753        return SelectRoadmapItemByID( _CurHyperLabel->GetID() );
754     }
755 
756 
757 
758     //---------------------------------------------------------------------
759 	void ORoadmap::DataChanged( const DataChangedEvent& rDCEvt )
760 	{
761 		if ((( rDCEvt.GetType() == DATACHANGED_SETTINGS	)	||
762 			( rDCEvt.GetType() == DATACHANGED_DISPLAY	))	&&
763 			( rDCEvt.GetFlags() & SETTINGS_STYLE		))
764 		{
765 			const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
766 			SetBackground( Wallpaper( rStyleSettings.GetFieldColor() ) );
767 			Color aTextColor = rStyleSettings.GetFieldTextColor();
768 			Font aFont = GetFont();
769 			aFont.SetColor( aTextColor );
770 			SetFont( aFont );
771 			RoadmapTypes::ItemId curItemID = GetCurrentRoadmapItemID();
772 			RoadmapItem* pLabelItem = GetByID( curItemID );
773 			pLabelItem->ToggleBackgroundColor(rStyleSettings.GetHighlightColor());
774 			Invalidate();
775 		}
776 	}
777 
778 
779     //---------------------------------------------------------------------
780     RoadmapItem::RoadmapItem( ORoadmap& _rParent, const Size& _rItemPlayground )
781         :m_aItemPlayground( _rItemPlayground )
782 	{
783 		mpID = new IDLabel( &_rParent, WB_WORDBREAK );
784 		mpID->SetTextColor( mpID->GetSettings().GetStyleSettings().GetFieldTextColor( ) );
785         mpID->Show();
786 		mpDescription = new HyperLabel( &_rParent, WB_NOTABSTOP | WB_WORDBREAK );
787         mpDescription->Show();
788 	}
789 
790     //---------------------------------------------------------------------
791     bool RoadmapItem::Contains( const Window* _pWindow ) const
792     {
793         return ( mpID == _pWindow ) || ( mpDescription == _pWindow );
794     }
795 
796     //---------------------------------------------------------------------
797     void RoadmapItem::GrabFocus()
798 	{
799         if ( mpDescription )
800             mpDescription->GrabFocus();
801 	}
802 
803     //---------------------------------------------------------------------
804 	void RoadmapItem::SetInteractive( sal_Bool _bInteractive )
805 	{
806         if ( mpDescription )
807 		mpDescription->SetInteractive(_bInteractive);
808 	}
809 
810     //---------------------------------------------------------------------
811 	void RoadmapItem::SetID( sal_Int16 _ID )
812 	{
813         if ( mpDescription )
814 		    mpDescription->SetID(_ID);
815 	}
816 
817     //---------------------------------------------------------------------
818 	sal_Int16 RoadmapItem::GetID() const
819 	{
820         return mpDescription ? mpDescription->GetID() : sal_Int16(-1);
821 	}
822 
823     //---------------------------------------------------------------------
824     void RoadmapItem::ImplUpdateIndex( const ItemIndex _nIndex )
825     {
826         if ( mpDescription )
827 		    mpDescription->SetIndex( _nIndex );
828 
829         if ( mpID )
830         {
831             ::rtl::OUString aIDText = ::rtl::OUString::valueOf( (sal_Int32)( _nIndex + 1 ) ) +  ::rtl::OUString::createFromAscii( "." );
832  		    mpID->SetText( aIDText );
833         }
834 
835         // update the geometry of both controls
836         ImplUpdatePosSize();
837     }
838 
839     //---------------------------------------------------------------------
840 	void RoadmapItem::SetIndex( ItemIndex _Index )
841 	{
842         ImplUpdateIndex( _Index );
843 	}
844 
845     //---------------------------------------------------------------------
846     RoadmapTypes::ItemIndex RoadmapItem::GetIndex() const
847 	{
848         return mpDescription ? mpDescription->GetIndex() : ItemIndex(-1);
849 	}
850 
851     //---------------------------------------------------------------------
852 	void RoadmapItem::SetLabel( const ::rtl::OUString& _rText )
853 	{
854         if ( mpDescription )
855 		    mpDescription->SetText(_rText);
856 	}
857 
858     //---------------------------------------------------------------------
859 	::rtl::OUString RoadmapItem::GetLabel( )
860 	{
861         return mpDescription ? mpDescription->GetText() : String();
862 	}
863 
864     //---------------------------------------------------------------------
865 	void RoadmapItem::SetPosition( RoadmapItem* _pOldItem )
866 	{
867 		Point aIDPos;
868 		if ( _pOldItem == NULL )
869 		{
870 			aIDPos = mpID->LogicToPixel( Point( ROADMAP_INDENT_X, ROADMAP_INDENT_Y ), MAP_APPFONT );
871 		}
872 		else
873 		{
874 			Size aOldSize = _pOldItem->GetDescriptionHyperLabel()->GetSizePixel();
875 
876             aIDPos = _pOldItem->mpID->GetPosPixel();
877             aIDPos.Y() += aOldSize.Height();
878             aIDPos.Y() += mpID->GetParent()->LogicToPixel( Size( 0, ROADMAP_ITEM_DISTANCE_Y ) ).Height();
879 		}
880 		mpID->SetPosPixel( aIDPos );
881 
882 		sal_Int32 nDescPos = aIDPos.X() + mpID->GetSizePixel().Width();
883 		mpDescription->SetPosPixel( Point( nDescPos, aIDPos.Y() ) );
884 	}
885 
886     //---------------------------------------------------------------------
887 	void RoadmapItem::SetZOrder( RoadmapItem* pRefRoadmapHyperLabel, sal_uInt16 nFlags )
888 	{
889 		if (pRefRoadmapHyperLabel == NULL)
890 			mpDescription->SetZOrder( NULL, nFlags); //WINDOW_ZORDER_FIRST );
891 		else
892 			mpDescription->SetZOrder( pRefRoadmapHyperLabel->mpDescription, nFlags); //, WINDOW_ZORDER_BEHIND );
893 	}
894 
895     //---------------------------------------------------------------------
896 	void RoadmapItem::Enable( sal_Bool _bEnable)
897 	{
898 		mpID->Enable(_bEnable);
899 		mpDescription->Enable(_bEnable);
900 	}
901 
902     //---------------------------------------------------------------------
903 	sal_Bool RoadmapItem::IsEnabled() const
904 	{
905 		return mpID->IsEnabled();
906 	}
907 
908     //---------------------------------------------------------------------
909 	void RoadmapItem::ToggleBackgroundColor( const Color& _rGBColor )
910 	{
911 		if (_rGBColor == COL_TRANSPARENT)
912 		{
913 			mpID->SetTextColor( mpID->GetSettings().GetStyleSettings().GetFieldTextColor( ) );
914 			mpID->SetControlBackground( COL_TRANSPARENT );
915 		}
916 		else
917 		{
918 			mpID->SetControlBackground( mpID->GetSettings().GetStyleSettings().GetHighlightColor() );
919 			mpID->SetTextColor( mpID->GetSettings().GetStyleSettings().GetHighlightTextColor( ) );
920 		}
921 		mpDescription->ToggleBackgroundColor(_rGBColor);
922 	}
923 
924     //---------------------------------------------------------------------
925     void RoadmapItem::ImplUpdatePosSize()
926     {
927         // calculate widths
928         long nIDWidth = mpID->GetTextWidth( mpID->GetText() );
929 		long nMaxIDWidth = mpID->GetTextWidth( ::rtl::OUString::createFromAscii( "100." ) );
930 		nIDWidth = ::std::min( nIDWidth, nMaxIDWidth );
931 
932         // check how many space the description would need
933         Size aDescriptionSize = mpDescription->CalcMinimumSize( m_aItemPlayground.Width() - nIDWidth );
934 
935         // position and size both controls
936         Size aIDSize( nIDWidth, aDescriptionSize.Height() );
937  		mpID->SetSizePixel( aIDSize );
938 
939         Point aIDPos = mpID->GetPosPixel();
940         mpDescription->SetPosPixel( Point( aIDPos.X() + nIDWidth, aIDPos.Y() ) );
941         mpDescription->SetSizePixel( aDescriptionSize );
942     }
943 
944     //---------------------------------------------------------------------
945 	void RoadmapItem::Update( ItemIndex _RMIndex, const ::rtl::OUString& _rText )
946 	{
947         // update description label
948         mpDescription->SetLabel( _rText );
949 
950         // update the index in both controls, which triggers updating the geometry of both
951         ImplUpdateIndex( _RMIndex );
952 	}
953 
954     //---------------------------------------------------------------------
955 	RoadmapItem::~RoadmapItem( )
956 	{
957         {
958             ::std::auto_ptr<Control> aTemp(mpID);
959 		    mpID = NULL;
960         }
961         {
962             ::std::auto_ptr<Control> aTemp(mpDescription);
963 		    mpDescription = NULL;
964         }
965 	}
966 
967     //---------------------------------------------------------------------
968 	void RoadmapItem::SetClickHdl( const Link& rLink )
969 	{
970         if ( mpDescription )
971 		    mpDescription->SetClickHdl( rLink);
972 	}
973 
974     //---------------------------------------------------------------------
975 	const Link& RoadmapItem::GetClickHdl( ) const
976 	{
977 		return mpDescription->GetClickHdl();
978 	}
979 
980 	//---------------------------------------------------------------------
981     IDLabel::IDLabel( Window* _pParent, WinBits _nWinStyle )
982 		:FixedText( _pParent, _nWinStyle )
983 	{
984 
985 	}
986 
987 	//---------------------------------------------------------------------
988 	IDLabel::~IDLabel( )
989 	{
990 	}
991 
992 	//---------------------------------------------------------------------
993 	void IDLabel::DataChanged( const DataChangedEvent& rDCEvt )
994 	{
995 		const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
996 		FixedText::DataChanged( rDCEvt );
997 		if ((( rDCEvt.GetType() == DATACHANGED_SETTINGS	)	||
998 			( rDCEvt.GetType() == DATACHANGED_DISPLAY	))	&&
999 			( rDCEvt.GetFlags() & SETTINGS_STYLE		))
1000 		{
1001 			const Color& rGBColor = GetControlBackground();
1002 			if (rGBColor == COL_TRANSPARENT)
1003 				SetTextColor( rStyleSettings.GetFieldTextColor( ) );
1004 			else
1005 			{
1006 				SetControlBackground(rStyleSettings.GetHighlightColor());
1007 				SetTextColor( rStyleSettings.GetHighlightTextColor( ) );
1008 			}
1009 			Invalidate();
1010 		}
1011 	}
1012 
1013 
1014 
1015 
1016 //.........................................................................
1017 }	// namespace svt
1018 //.........................................................................
1019