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