xref: /AOO41X/main/svtools/source/control/roadmap.cxx (revision 1be7247669264f94ebf8f1f55ee11acf6d8c0226)
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:
ColorChanger(OutputDevice * _pDev,const Color & _rNewLineColor,const Color & _rNewFillColor)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 
~ColorChanger()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 
GetDescriptionHyperLabel() const126         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:
RoadmapImpl(const ORoadmap & _rAntiImpl)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 
addHyperLabel(RoadmapItem * _rRoadmapStep)159         void                addHyperLabel( RoadmapItem*  _rRoadmapStep ) { m_aRoadmapSteps.push_back(_rRoadmapStep); }
160 
getHyperLabels()161         HL_Vector&          getHyperLabels() { return m_aRoadmapSteps; }
getHyperLabels() const162         const HL_Vector&    getHyperLabels() const { return m_aRoadmapSteps; }
163 
insertHyperLabel(ItemIndex _Index,RoadmapItem * _rRoadmapStep)164         void                insertHyperLabel( ItemIndex _Index, RoadmapItem* _rRoadmapStep ) { m_aRoadmapSteps.insert( m_aRoadmapSteps.begin() + _Index, _rRoadmapStep ); }
165 
getItemCount() const166         ItemIndex           getItemCount() const { return m_aRoadmapSteps.size();}
167 
setCurItemID(ItemId i)168         void                setCurItemID( ItemId i ) {m_iCurItemID = i; }
getCurItemID() const169         ItemId              getCurItemID() const { return m_iCurItemID; }
170 
setInteractive(const sal_Bool _bInteractive)171         void                setInteractive(const sal_Bool _bInteractive) {m_bInteractive = _bInteractive; }
isInteractive() const172         sal_Bool            isInteractive() const { return m_bInteractive; };
173 
setComplete(const sal_Bool _bComplete)174         void                setComplete(const sal_Bool _bComplete) {m_bComplete = _bComplete; }
isComplete() const175         sal_Bool            isComplete() const { return m_bComplete; };
176 
setPicture(const BitmapEx & _rPic)177         void                setPicture( const BitmapEx& _rPic ) { m_aPicture = _rPic; }
getPicture() const178         const BitmapEx&     getPicture( ) const { return m_aPicture; }
179 
setSelectHdl(const Link & _rHdl)180         void                setSelectHdl( const Link& _rHdl ) { m_aSelectHdl = _rHdl; }
getSelectHdl() const181         const Link&         getSelectHdl( ) const { return m_aSelectHdl; }
182 
183         void                initItemSize();
getItemSize() const184         const Size&         getItemSize() const { return m_aItemSizePixel; }
185 
removeHyperLabel(ItemIndex _Index)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     //---------------------------------------------------------------------
initItemSize()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     //---------------------------------------------------------------------
ORoadmap(Window * _pParent,const ResId & _rId)213     ORoadmap::ORoadmap( Window* _pParent, const ResId& _rId )
214         :Control( _pParent, _rId )
215         ,m_pImpl( new RoadmapImpl( *this ) )
216     {
217         implInit();
218     }
219 
220     //---------------------------------------------------------------------
ORoadmap(Window * _pParent,WinBits _nWinStyle)221     ORoadmap::ORoadmap( Window* _pParent, WinBits _nWinStyle )
222         :Control( _pParent, _nWinStyle )
223         ,m_pImpl( new RoadmapImpl( *this ) )
224 
225     {
226         implInit();
227     }
228 
229     //---------------------------------------------------------------------
implInit()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     //---------------------------------------------------------------------
~ORoadmap()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 
GetCurrentRoadmapItemID() const277     RoadmapTypes::ItemId ORoadmap::GetCurrentRoadmapItemID() const
278     {
279         return m_pImpl->getCurItemID();
280     }
281 
282 
GetPreviousHyperLabel(ItemIndex _Index)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 
InsertHyperLabel(ItemIndex _Index,const::rtl::OUString & _sLabel,ItemId _RMID,sal_Bool _bEnabled)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     //---------------------------------------------------------------------
SetRoadmapBitmap(const BitmapEx & _rBmp,sal_Bool _bInvalidate)323     void ORoadmap::SetRoadmapBitmap( const BitmapEx& _rBmp, sal_Bool _bInvalidate )
324     {
325         m_pImpl->setPicture( _rBmp );
326         if ( _bInvalidate )
327             Invalidate( );
328     }
329 
330     //---------------------------------------------------------------------
GetRoadmapBitmap() const331     const BitmapEx& ORoadmap::GetRoadmapBitmap( ) const
332     {
333         return m_pImpl->getPicture( );
334     }
335 
336     //---------------------------------------------------------------------
SetRoadmapInteractive(sal_Bool _bInteractive)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     //---------------------------------------------------------------------
IsRoadmapInteractive()352     sal_Bool ORoadmap::IsRoadmapInteractive()
353     {
354         return m_pImpl->isInteractive();
355     }
356 
357     //---------------------------------------------------------------------
SetRoadmapComplete(sal_Bool _bComplete)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     //---------------------------------------------------------------------
UpdatefollowingHyperLabels(ItemIndex _nIndex)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     //---------------------------------------------------------------------
ReplaceRoadmapItem(ItemIndex _Index,const::rtl::OUString & _RoadmapItem,ItemId _RMID,sal_Bool _bEnabled)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     //---------------------------------------------------------------------
GetItemCount() const413     RoadmapTypes::ItemIndex ORoadmap::GetItemCount() const
414     {
415         return m_pImpl->getItemCount();
416     }
417 
418     //---------------------------------------------------------------------
GetItemID(ItemIndex _nIndex) const419     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     //---------------------------------------------------------------------
GetItemIndex(ItemId _nID) const428     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     //---------------------------------------------------------------------
InsertRoadmapItem(ItemIndex _Index,const::rtl::OUString & _RoadmapItem,ItemId _nUniqueId,sal_Bool _bEnabled)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     //---------------------------------------------------------------------
DeleteRoadmapItem(ItemIndex _Index)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     //---------------------------------------------------------------------
IsRoadmapComplete() const463     sal_Bool ORoadmap::IsRoadmapComplete( ) const
464     {
465         return m_pImpl->isComplete();
466     }
467 
468     //---------------------------------------------------------------------
IsRoadmapItemEnabled(ItemId _nItemId,ItemIndex _nStartIndex) const469     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     //---------------------------------------------------------------------
EnableRoadmapItem(ItemId _nItemId,sal_Bool _bEnable,ItemIndex _nStartIndex)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     //---------------------------------------------------------------------
ChangeRoadmapItemLabel(ItemId _nID,const::rtl::OUString & _sLabel,ItemIndex _nStartIndex)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 
GetRoadmapItemLabel(ItemId _nID,ItemIndex _nStartIndex)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     //---------------------------------------------------------------------
ChangeRoadmapItemID(ItemId _nID,ItemId _NewID,ItemIndex _nStartIndex)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     //---------------------------------------------------------------------
GetByID(ItemId _nID,ItemIndex _nStartIndex)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     //---------------------------------------------------------------------
GetByID(ItemId _nID,ItemIndex _nStartIndex) const539     const RoadmapItem* ORoadmap::GetByID( ItemId _nID, ItemIndex _nStartIndex  ) const
540     {
541         return const_cast< ORoadmap* >( this )->GetByID( _nID, _nStartIndex );
542     }
543 
544     //---------------------------------------------------------------------
GetByIndex(ItemIndex _nItemIndex)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     //---------------------------------------------------------------------
GetByIndex(ItemIndex _nItemIndex) const556     const RoadmapItem* ORoadmap::GetByIndex( ItemIndex _nItemIndex ) const
557     {
558         return const_cast< ORoadmap* >( this )->GetByIndex( _nItemIndex );
559     }
560 
561     //---------------------------------------------------------------------
GetNextAvailableItemId(ItemIndex _nNewIndex)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     //---------------------------------------------------------------------
GetPreviousAvailableItemId(ItemIndex _nNewIndex)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     //---------------------------------------------------------------------
DeselectOldRoadmapItems()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     //---------------------------------------------------------------------
SetItemSelectHdl(const Link & _rHdl)608     void ORoadmap::SetItemSelectHdl( const Link& _rHdl )
609     {
610         m_pImpl->setSelectHdl( _rHdl );
611     }
612 
613     //---------------------------------------------------------------------
GetItemSelectHdl() const614     Link ORoadmap::GetItemSelectHdl( ) const
615     {
616         return m_pImpl->getSelectHdl();
617     }
618 
619     //---------------------------------------------------------------------
Select()620     void ORoadmap::Select()
621     {
622         GetItemSelectHdl().Call( this );
623         CallEventListeners( VCLEVENT_ROADMAP_ITEMSELECTED );
624     }
625 
626     //---------------------------------------------------------------------
GetFocus()627     void ORoadmap::GetFocus()
628     {
629         RoadmapItem* pCurHyperLabel = GetByID( GetCurrentRoadmapItemID() );
630         if ( pCurHyperLabel != NULL )
631             pCurHyperLabel->GrabFocus();
632     }
633 
634     //---------------------------------------------------------------------
SelectRoadmapItemByID(ItemId _nNewID)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     //---------------------------------------------------------------------
Paint(const Rectangle & _rRect)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     //---------------------------------------------------------------------
DrawHeadline()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     //---------------------------------------------------------------------
GetByPointer(Window * pWindow)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     //---------------------------------------------------------------------
PreNotify(NotifyEvent & _rNEvt)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     //---------------------------------------------------------------------
IMPL_LINK(ORoadmap,ImplClickHdl,HyperLabel *,_CurHyperLabel)747     IMPL_LINK(ORoadmap, ImplClickHdl, HyperLabel*, _CurHyperLabel)
748     {
749        return SelectRoadmapItemByID( _CurHyperLabel->GetID() );
750     }
751 
752 
753 
754     //---------------------------------------------------------------------
DataChanged(const DataChangedEvent & rDCEvt)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             if ( pLabelItem != NULL )
770                 pLabelItem->ToggleBackgroundColor(rStyleSettings.GetHighlightColor());
771             Invalidate();
772         }
773     }
774 
775 
776     //---------------------------------------------------------------------
RoadmapItem(ORoadmap & _rParent,const Size & _rItemPlayground)777     RoadmapItem::RoadmapItem( ORoadmap& _rParent, const Size& _rItemPlayground )
778         :m_aItemPlayground( _rItemPlayground )
779     {
780         mpID = new IDLabel( &_rParent, WB_WORDBREAK );
781         mpID->SetTextColor( mpID->GetSettings().GetStyleSettings().GetFieldTextColor( ) );
782         mpID->Show();
783         mpDescription = new HyperLabel( &_rParent, WB_NOTABSTOP | WB_WORDBREAK );
784         mpDescription->Show();
785     }
786 
787     //---------------------------------------------------------------------
Contains(const Window * _pWindow) const788     bool RoadmapItem::Contains( const Window* _pWindow ) const
789     {
790         return ( mpID == _pWindow ) || ( mpDescription == _pWindow );
791     }
792 
793     //---------------------------------------------------------------------
GrabFocus()794     void RoadmapItem::GrabFocus()
795     {
796         if ( mpDescription )
797             mpDescription->GrabFocus();
798     }
799 
800     //---------------------------------------------------------------------
SetInteractive(sal_Bool _bInteractive)801     void RoadmapItem::SetInteractive( sal_Bool _bInteractive )
802     {
803         if ( mpDescription )
804         mpDescription->SetInteractive(_bInteractive);
805     }
806 
807     //---------------------------------------------------------------------
SetID(sal_Int16 _ID)808     void RoadmapItem::SetID( sal_Int16 _ID )
809     {
810         if ( mpDescription )
811             mpDescription->SetID(_ID);
812     }
813 
814     //---------------------------------------------------------------------
GetID() const815     sal_Int16 RoadmapItem::GetID() const
816     {
817         return mpDescription ? mpDescription->GetID() : sal_Int16(-1);
818     }
819 
820     //---------------------------------------------------------------------
ImplUpdateIndex(const ItemIndex _nIndex)821     void RoadmapItem::ImplUpdateIndex( const ItemIndex _nIndex )
822     {
823         if ( mpDescription )
824             mpDescription->SetIndex( _nIndex );
825 
826         if ( mpID )
827         {
828             ::rtl::OUString aIDText = ::rtl::OUString::valueOf( (sal_Int32)( _nIndex + 1 ) ) +  ::rtl::OUString::createFromAscii( "." );
829             mpID->SetText( aIDText );
830         }
831 
832         // update the geometry of both controls
833         ImplUpdatePosSize();
834     }
835 
836     //---------------------------------------------------------------------
SetIndex(ItemIndex _Index)837     void RoadmapItem::SetIndex( ItemIndex _Index )
838     {
839         ImplUpdateIndex( _Index );
840     }
841 
842     //---------------------------------------------------------------------
GetIndex() const843     RoadmapTypes::ItemIndex RoadmapItem::GetIndex() const
844     {
845         return mpDescription ? mpDescription->GetIndex() : ItemIndex(-1);
846     }
847 
848     //---------------------------------------------------------------------
SetLabel(const::rtl::OUString & _rText)849     void RoadmapItem::SetLabel( const ::rtl::OUString& _rText )
850     {
851         if ( mpDescription )
852             mpDescription->SetText(_rText);
853     }
854 
855     //---------------------------------------------------------------------
GetLabel()856     ::rtl::OUString RoadmapItem::GetLabel( )
857     {
858         return mpDescription ? mpDescription->GetText() : String();
859     }
860 
861     //---------------------------------------------------------------------
SetPosition(RoadmapItem * _pOldItem)862     void RoadmapItem::SetPosition( RoadmapItem* _pOldItem )
863     {
864         Point aIDPos;
865         if ( _pOldItem == NULL )
866         {
867             aIDPos = mpID->LogicToPixel( Point( ROADMAP_INDENT_X, ROADMAP_INDENT_Y ), MAP_APPFONT );
868         }
869         else
870         {
871             Size aOldSize = _pOldItem->GetDescriptionHyperLabel()->GetSizePixel();
872 
873             aIDPos = _pOldItem->mpID->GetPosPixel();
874             aIDPos.Y() += aOldSize.Height();
875             aIDPos.Y() += mpID->GetParent()->LogicToPixel( Size( 0, ROADMAP_ITEM_DISTANCE_Y ) ).Height();
876         }
877         mpID->SetPosPixel( aIDPos );
878 
879         sal_Int32 nDescPos = aIDPos.X() + mpID->GetSizePixel().Width();
880         mpDescription->SetPosPixel( Point( nDescPos, aIDPos.Y() ) );
881     }
882 
883     //---------------------------------------------------------------------
SetZOrder(RoadmapItem * pRefRoadmapHyperLabel,sal_uInt16 nFlags)884     void RoadmapItem::SetZOrder( RoadmapItem* pRefRoadmapHyperLabel, sal_uInt16 nFlags )
885     {
886         if (pRefRoadmapHyperLabel == NULL)
887             mpDescription->SetZOrder( NULL, nFlags); //WINDOW_ZORDER_FIRST );
888         else
889             mpDescription->SetZOrder( pRefRoadmapHyperLabel->mpDescription, nFlags); //, WINDOW_ZORDER_BEHIND );
890     }
891 
892     //---------------------------------------------------------------------
Enable(sal_Bool _bEnable)893     void RoadmapItem::Enable( sal_Bool _bEnable)
894     {
895         mpID->Enable(_bEnable);
896         mpDescription->Enable(_bEnable);
897     }
898 
899     //---------------------------------------------------------------------
IsEnabled() const900     sal_Bool RoadmapItem::IsEnabled() const
901     {
902         return mpID->IsEnabled();
903     }
904 
905     //---------------------------------------------------------------------
ToggleBackgroundColor(const Color & _rGBColor)906     void RoadmapItem::ToggleBackgroundColor( const Color& _rGBColor )
907     {
908         if (_rGBColor == COL_TRANSPARENT)
909         {
910             mpID->SetTextColor( mpID->GetSettings().GetStyleSettings().GetFieldTextColor( ) );
911             mpID->SetControlBackground( COL_TRANSPARENT );
912         }
913         else
914         {
915             mpID->SetControlBackground( mpID->GetSettings().GetStyleSettings().GetHighlightColor() );
916             mpID->SetTextColor( mpID->GetSettings().GetStyleSettings().GetHighlightTextColor( ) );
917         }
918         mpDescription->ToggleBackgroundColor(_rGBColor);
919     }
920 
921     //---------------------------------------------------------------------
ImplUpdatePosSize()922     void RoadmapItem::ImplUpdatePosSize()
923     {
924         // calculate widths
925         long nIDWidth = mpID->GetTextWidth( mpID->GetText() );
926         long nMaxIDWidth = mpID->GetTextWidth( ::rtl::OUString::createFromAscii( "100." ) );
927         nIDWidth = ::std::min( nIDWidth, nMaxIDWidth );
928 
929         // check how many space the description would need
930         Size aDescriptionSize = mpDescription->CalcMinimumSize( m_aItemPlayground.Width() - nIDWidth );
931 
932         // position and size both controls
933         Size aIDSize( nIDWidth, aDescriptionSize.Height() );
934         mpID->SetSizePixel( aIDSize );
935 
936         Point aIDPos = mpID->GetPosPixel();
937         mpDescription->SetPosPixel( Point( aIDPos.X() + nIDWidth, aIDPos.Y() ) );
938         mpDescription->SetSizePixel( aDescriptionSize );
939     }
940 
941     //---------------------------------------------------------------------
Update(ItemIndex _RMIndex,const::rtl::OUString & _rText)942     void RoadmapItem::Update( ItemIndex _RMIndex, const ::rtl::OUString& _rText )
943     {
944         // update description label
945         mpDescription->SetLabel( _rText );
946 
947         // update the index in both controls, which triggers updating the geometry of both
948         ImplUpdateIndex( _RMIndex );
949     }
950 
951     //---------------------------------------------------------------------
~RoadmapItem()952     RoadmapItem::~RoadmapItem( )
953     {
954         {
955             ::std::auto_ptr<Control> aTemp(mpID);
956             mpID = NULL;
957         }
958         {
959             ::std::auto_ptr<Control> aTemp(mpDescription);
960             mpDescription = NULL;
961         }
962     }
963 
964     //---------------------------------------------------------------------
SetClickHdl(const Link & rLink)965     void RoadmapItem::SetClickHdl( const Link& rLink )
966     {
967         if ( mpDescription )
968             mpDescription->SetClickHdl( rLink);
969     }
970 
971     //---------------------------------------------------------------------
GetClickHdl() const972     const Link& RoadmapItem::GetClickHdl( ) const
973     {
974         return mpDescription->GetClickHdl();
975     }
976 
977     //---------------------------------------------------------------------
IDLabel(Window * _pParent,WinBits _nWinStyle)978     IDLabel::IDLabel( Window* _pParent, WinBits _nWinStyle )
979         :FixedText( _pParent, _nWinStyle )
980     {
981 
982     }
983 
984     //---------------------------------------------------------------------
~IDLabel()985     IDLabel::~IDLabel( )
986     {
987     }
988 
989     //---------------------------------------------------------------------
DataChanged(const DataChangedEvent & rDCEvt)990     void IDLabel::DataChanged( const DataChangedEvent& rDCEvt )
991     {
992         const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
993         FixedText::DataChanged( rDCEvt );
994         if ((( rDCEvt.GetType() == DATACHANGED_SETTINGS )   ||
995             ( rDCEvt.GetType() == DATACHANGED_DISPLAY   ))  &&
996             ( rDCEvt.GetFlags() & SETTINGS_STYLE        ))
997         {
998             const Color& rGBColor = GetControlBackground();
999             if (rGBColor == COL_TRANSPARENT)
1000                 SetTextColor( rStyleSettings.GetFieldTextColor( ) );
1001             else
1002             {
1003                 SetControlBackground(rStyleSettings.GetHighlightColor());
1004                 SetTextColor( rStyleSettings.GetHighlightTextColor( ) );
1005             }
1006             Invalidate();
1007         }
1008     }
1009 
1010 
1011 
1012 
1013 //.........................................................................
1014 }   // namespace svt
1015 //.........................................................................
1016