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 #include "rtl/ustring.hxx"
29 #include "vcl/scrbar.hxx"
30 #include "vcl/fixed.hxx"
31 #include "vcl/dialog.hxx"
32 
33 #include "svtools/extensionlistbox.hxx"
34 #include "svtools/fixedhyper.hxx"
35 #include "cppuhelper/implbase1.hxx"
36 #include "unotools/collatorwrapper.hxx"
37 
38 #include "com/sun/star/lang/Locale.hpp"
39 #include "com/sun/star/lang/XEventListener.hpp"
40 #include "com/sun/star/deployment/XPackage.hpp"
41 
42 #include <boost/shared_ptr.hpp>
43 
44 namespace dp_gui {
45 
46 #define SMALL_ICON_SIZE     16
47 #define TOP_OFFSET           5
48 #define ICON_HEIGHT         42
49 #define ICON_WIDTH          47
50 #define ICON_OFFSET         72
51 #define RIGHT_ICON_OFFSET    5
52 #define SPACE_BETWEEN        3
53 
54 class TheExtensionManager;
55 
56 typedef ::boost::shared_ptr< svt::FixedHyperlink > TFixedHyperlink;
57 
58 //------------------------------------------------------------------------------
59 //                          struct Entry_Impl
60 //------------------------------------------------------------------------------
61 struct Entry_Impl;
62 
63 typedef ::boost::shared_ptr< Entry_Impl > TEntry_Impl;
64 
65 struct Entry_Impl
66 {
67     bool            m_bActive       :1;
68     bool            m_bLocked       :1;
69     bool            m_bHasOptions   :1;
70     bool            m_bUser         :1;
71     bool            m_bShared       :1;
72     bool            m_bNew          :1;
73     bool            m_bChecked      :1;
74     bool            m_bMissingDeps  :1;
75     bool            m_bHasButtons   :1;
76     bool            m_bMissingLic   :1;
77     PackageState    m_eState;
78     String          m_sTitle;
79     String          m_sVersion;
80     String          m_sDescription;
81     String          m_sPublisher;
82     String          m_sPublisherURL;
83     String          m_sErrorText;
84     String          m_sLicenseText;
85     Image           m_aIcon;
86     Image           m_aIconHC;
87     svt::FixedHyperlink *m_pPublisher;
88 
89     ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XPackage> m_xPackage;
90 
91     Entry_Impl( const ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XPackage > &xPackage,
92                 const PackageState eState, const bool bReadOnly );
93    ~Entry_Impl();
94 
95     StringCompare CompareTo( const CollatorWrapper *pCollator, const TEntry_Impl pEntry ) const;
96     void          checkDependencies();
97 };
98 
99 //------------------------------------------------------------------------------
100 //                          class ExtensionBox_Impl
101 //------------------------------------------------------------------------------
102 
103 class ExtensionBox_Impl;
104 
105 //------------------------------------------------------------------------------
106 class ExtensionRemovedListener : public ::cppu::WeakImplHelper1< ::com::sun::star::lang::XEventListener >
107 {
108     ExtensionBox_Impl   *m_pParent;
109 
110 public:
111 
112     ExtensionRemovedListener( ExtensionBox_Impl *pParent ) { m_pParent = pParent; }
113    ~ExtensionRemovedListener();
114 
115     //===================================================================================
116     // XEventListener
117     virtual void SAL_CALL disposing( ::com::sun::star::lang::EventObject const & evt )
118         throw (::com::sun::star::uno::RuntimeException);
119 };
120 
121 //------------------------------------------------------------------------------
122 class ExtensionBox_Impl : public ::svt::IExtensionListBox
123 {
124     bool            m_bHasScrollBar;
125     bool            m_bHasActive;
126     bool            m_bNeedsRecalc;
127     bool            m_bHasNew;
128     bool            m_bInCheckMode;
129     bool            m_bAdjustActive;
130     bool            m_bInDelete;
131     //Must be guarded together with m_vEntries to ensure a valid index at all times.
132     //Use m_entriesMutex as guard.
133     long            m_nActive;
134     long            m_nTopIndex;
135     long            m_nStdHeight;
136     long            m_nActiveHeight;
137     long            m_nExtraHeight;
138     Size            m_aOutputSize;
139     Image           m_aSharedImage;
140     Image           m_aSharedImageHC;
141     Image           m_aLockedImage;
142     Image           m_aLockedImageHC;
143     Image           m_aWarningImage;
144     Image           m_aWarningImageHC;
145     Image           m_aDefaultImage;
146     Image           m_aDefaultImageHC;
147     Link            m_aClickHdl;
148 
149     ScrollBar      *m_pScrollBar;
150 
151     com::sun::star::uno::Reference< ExtensionRemovedListener > m_xRemoveListener;
152 
153     TheExtensionManager      *m_pManager;
154     //This mutex is used for synchronizing access to m_vEntries.
155     //Currently it is used to synchronize adding, removing entries and
156     //functions like getItemName, getItemDescription, etc. to prevent
157     //that m_vEntries is accessed at an invalid index.
158     //ToDo: There are many more places where m_vEntries is read and which may
159     //fail. For example the Paint method is probable called from the main thread
160     //while new entries are added / removed in a separate thread.
161     mutable ::osl::Mutex    m_entriesMutex;
162     std::vector< TEntry_Impl > m_vEntries;
163     std::vector< TEntry_Impl > m_vRemovedEntries;
164 
165 	::com::sun::star::lang::Locale    *m_pLocale;
166 	CollatorWrapper *m_pCollator;
167 
168     void            CalcActiveHeight( const long nPos );
169     long            GetTotalHeight() const;
170     void            SetupScrollBar();
171     void            DrawRow( const Rectangle& rRect, const TEntry_Impl pEntry );
172     bool            HandleTabKey( bool bReverse );
173     bool            HandleCursorKey( sal_uInt16 nKeyCode );
174     bool            FindEntryPos( const TEntry_Impl pEntry, long nStart, long nEnd, long &nFound );
175     bool            isHCMode();
176     void            DeleteRemoved();
177 
178     //-----------------
179     DECL_DLLPRIVATE_LINK( ScrollHdl, ScrollBar * );
180 
181     //Index starts with 1.
182     //Throws an com::sun::star::lang::IllegalArgumentException, when the index is invalid.
183     void checkIndex(sal_Int32 pos) const;
184 
185 
186 public:
187                     ExtensionBox_Impl( Dialog* pParent, TheExtensionManager *pManager );
188                    ~ExtensionBox_Impl();
189 
190     virtual void    MouseButtonDown( const MouseEvent& rMEvt );
191     virtual void    Paint( const Rectangle &rPaintRect );
192     virtual void    Resize();
193     virtual long    Notify( NotifyEvent& rNEvt );
194 
195     const Size      GetMinOutputSizePixel() const;
196     void            SetExtraSize( long nSize ) { m_nExtraHeight = nSize; }
197     TEntry_Impl     GetEntryData( long nPos ) { return m_vEntries[ nPos ]; }
198     long            GetEntryCount() { return (long) m_vEntries.size(); }
199     Rectangle       GetEntryRect( const long nPos ) const;
200     bool            HasActive() { return m_bHasActive; }
201     long            PointToPos( const Point& rPos );
202     void            SetScrollHdl( const Link& rLink );
203     void            DoScroll( long nDelta );
204     void            SetHyperlinkHdl( const Link& rLink ){ m_aClickHdl = rLink; }
205     virtual void    RecalcAll();
206     void            RemoveUnlocked();
207 
208     //-----------------
209     virtual void    selectEntry( const long nPos );
210     long            addEntry( const ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XPackage > &xPackage,
211                               bool bLicenseMissing = false );
212     void            updateEntry( const ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XPackage > &xPackage );
213     void            removeEntry( const ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XPackage > &xPackage );
214 
215     void            prepareChecking();
216     void            checkEntries();
217 
218     TheExtensionManager*    getExtensionManager() const { return m_pManager; }
219 
220     //===================================================================================
221     //These functions are used for automatic testing
222 
223     /** @return  The count of the entries in the list box. */
224     virtual sal_Int32 getItemCount() const;
225 
226     /** @return  The index of the first selected entry in the list box.
227         When nothing is selected, which is the case when getItemCount returns '0',
228         then this function returns EXTENSION_LISTBOX_ENTRY_NOTFOUND */
229     virtual sal_Int32 getSelIndex() const;
230 
231     /** @return  The item name of the entry with the given index
232         The index starts with 0.
233         Throws an com::sun::star::lang::IllegalArgumentException, when the position is invalid. */
234     virtual ::rtl::OUString getItemName( sal_Int32 index ) const;
235 
236     /** @return  The version string of the entry with the given index
237         The index starts with 0.
238         Throws an com::sun::star::lang::IllegalArgumentException, when the position is invalid. */
239     virtual ::rtl::OUString getItemVersion( sal_Int32 index ) const;
240 
241     /** @return  The description string of the entry with the given index
242         The index starts with 0.
243         Throws an com::sun::star::lang::IllegalArgumentException, when the position is invalid. */
244     virtual ::rtl::OUString getItemDescription( sal_Int32 index ) const;
245 
246     /** @return  The publisher string of the entry with the given index
247         The index starts with 0.
248         Throws an com::sun::star::lang::IllegalArgumentException, when the position is invalid. */
249     virtual ::rtl::OUString getItemPublisher( sal_Int32 index ) const;
250 
251     /** @return  The link behind the publisher text of the entry with the given index
252         The index starts with 0.
253         Throws an com::sun::star::lang::IllegalArgumentException, when the position is invalid. */
254     virtual ::rtl::OUString getItemPublisherLink( sal_Int32 index ) const;
255 
256     /** The entry at the given position will be selected
257         Index starts with 0.
258         Throws an com::sun::star::lang::IllegalArgumentException, when the position is invalid. */
259     virtual void select( sal_Int32 pos );
260 
261     /** The first found entry with the given name will be selected
262         When there was no entry found with the name, the selection doesn't change.
263         Please note that there might be more than one entry with the same
264         name, because:
265             1. the name is not unique
266             2. one extension can be installed as user and shared extension.
267     */
268     virtual void select( const ::rtl::OUString & sName );
269 };
270 
271 }
272