xref: /trunk/main/svtools/source/control/roadmap.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
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