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_extensions.hxx"
30 #include "taborder.hxx"
31 #ifndef EXTENSIONS_SOURCE_PROPCTRLR_TABORDER_HRC
32 #include "taborder.hrc"
33 #endif
34 
35 #ifndef _EXTENSIONS_PROPCTRLR_MODULEPRC_HXX_
36 #include "modulepcr.hxx"
37 #endif
38 #ifndef _EXTENSIONS_FORMCTRLR_PROPRESID_HRC_
39 #include "formresid.hrc"
40 #endif
41 #include "formstrings.hxx"
42 #include <comphelper/types.hxx>
43 #include <comphelper/property.hxx>
44 #include <cppuhelper/implbase1.hxx>
45 #include <com/sun/star/form/FormComponentType.hpp>
46 #include <com/sun/star/awt/XTabController.hpp>
47 #include <vcl/scrbar.hxx>
48 
49 //............................................................................
50 namespace pcr
51 {
52 //............................................................................
53 
54     using namespace ::com::sun::star::uno;
55     using namespace ::com::sun::star::awt;
56     using namespace ::com::sun::star::lang;
57     using namespace ::com::sun::star::form;
58     using namespace ::com::sun::star::beans;
59     using namespace ::com::sun::star::datatransfer;
60 
61     //========================================================================
62     //= OSimpleTabModel
63     //========================================================================
64     class OSimpleTabModel : public ::cppu::WeakImplHelper1< XTabControllerModel>
65     {
66         Sequence< Reference< XControlModel > > m_aModels;
67 
68     public:
69         OSimpleTabModel( const Sequence< Reference< XControlModel > >& _rModels )
70             :m_aModels( _rModels )
71         {
72         }
73 
74         // XTabControllerModel
75         virtual void SAL_CALL setControlModels(const Sequence< Reference< XControlModel > >& rModels) throw( RuntimeException ) {m_aModels = rModels;}
76         virtual Sequence< Reference< XControlModel > > SAL_CALL getControlModels(void) throw( RuntimeException ) {return m_aModels;}
77         virtual void SAL_CALL setGroup(const Sequence< Reference< XControlModel > >& /*Group*/, const ::rtl::OUString& /*GroupName*/) throw( RuntimeException ) {}
78         virtual sal_Int32 SAL_CALL getGroupCount(void) throw( RuntimeException ) {return 0;}
79         virtual void SAL_CALL getGroup(sal_Int32 /*nGroup*/, Sequence< Reference< XControlModel > >& /*Group*/, ::rtl::OUString& /*Name*/) throw( RuntimeException ) {}
80         virtual void SAL_CALL getGroupByName(const ::rtl::OUString& /*Name*/, Sequence< Reference< XControlModel > >& /*Group*/) throw( RuntimeException ) {}
81         virtual sal_Bool SAL_CALL getGroupControl(void) throw( RuntimeException ){return sal_False;} ;
82         virtual void SAL_CALL setGroupControl(sal_Bool /*GroupControl*/) throw( RuntimeException ){};
83     };
84 
85     //========================================================================
86     //= TabOrderDialog
87     //========================================================================
88     DBG_NAME(TabOrderDialog)
89     //------------------------------------------------------------------------
90     TabOrderDialog::TabOrderDialog( Window* _pParent, const Reference< XTabControllerModel >& _rxTabModel,
91                     const Reference< XControlContainer >& _rxControlCont, const Reference< XMultiServiceFactory >& _rxORB )
92         :ModalDialog( _pParent, PcrRes( RID_DLG_TABORDER ) )
93         ,m_xModel( _rxTabModel )
94         ,m_xControlContainer( _rxControlCont )
95         ,m_xORB( _rxORB )
96         ,aFT_Controls( this, PcrRes( FT_CONTROLS ) )
97         ,aLB_Controls( this, PcrRes( CTRL_TREE ) )
98         ,aPB_OK( this, PcrRes( PB_OK ) )
99         ,aPB_CANCEL( this, PcrRes( PB_CANCEL ) )
100         ,aPB_HELP( this, PcrRes( PB_HELP ) )
101         ,aPB_MoveUp( this, PcrRes( PB_MOVE_UP ) )
102         ,aPB_MoveDown( this, PcrRes( PB_MOVE_DOWN ) )
103         ,aPB_AutoOrder( this, PcrRes( PB_AUTO_ORDER ) )
104         ,pImageList( NULL )
105     {
106         DBG_CTOR(TabOrderDialog,NULL);
107 
108         aPB_MoveUp.SetClickHdl( LINK( this, TabOrderDialog, MoveUpClickHdl ) );
109         aPB_MoveDown.SetClickHdl( LINK( this, TabOrderDialog, MoveDownClickHdl ) );
110         aPB_AutoOrder.SetClickHdl( LINK( this, TabOrderDialog, AutoOrderClickHdl ) );
111         aPB_OK.SetClickHdl( LINK( this, TabOrderDialog, OKClickHdl ) );
112         aPB_OK.Disable();
113 
114         sal_Bool bIsHighContrast = GetSettings().GetStyleSettings().GetHighContrastMode();
115         pImageList = new ImageList( PcrRes( bIsHighContrast ? RID_IL_FORMEXPLORER_HC : RID_IL_FORMEXPLORER ) );
116 
117 
118         if ( m_xModel.is() )
119             m_xTempModel = new OSimpleTabModel( m_xModel->getControlModels() );
120 
121         if ( m_xTempModel.is() && m_xControlContainer.is() )
122             FillList();
123 
124         if ( aLB_Controls.GetEntryCount() < 2 )
125         {
126             aPB_MoveUp.Disable();
127             aPB_MoveDown.Disable();
128             aPB_AutoOrder.Disable();
129         }
130 
131         FreeResource();
132     }
133 
134     //------------------------------------------------------------------------
135     void TabOrderDialog::SetModified()
136     {
137         aPB_OK.Enable();
138     }
139 
140     //------------------------------------------------------------------------
141     TabOrderDialog::~TabOrderDialog()
142     {
143         aLB_Controls.Hide();
144         //  delete pLB_Controls;
145         delete pImageList;
146 
147         DBG_DTOR(TabOrderDialog,NULL);
148     }
149 
150     //------------------------------------------------------------------------
151     Image TabOrderDialog::GetImage( const Reference< XPropertySet >& _rxSet ) const
152     {
153         sal_uInt16 nImageId = RID_SVXIMG_CONTROL;
154         // TODO: classify controls also in Basic propbrw
155         if ( _rxSet.is() && ::comphelper::hasProperty( PROPERTY_CLASSID, _rxSet ) )
156         {
157             switch( ::comphelper::getINT16( _rxSet->getPropertyValue( PROPERTY_CLASSID ) ) )
158             {
159             case FormComponentType::COMMANDBUTTON:  nImageId = RID_SVXIMG_BUTTON; break;
160             case FormComponentType::FIXEDTEXT:      nImageId = RID_SVXIMG_FIXEDTEXT; break;
161             case FormComponentType::TEXTFIELD:      nImageId = RID_SVXIMG_EDIT; break;
162             case FormComponentType::RADIOBUTTON:    nImageId = RID_SVXIMG_RADIOBUTTON; break;
163             case FormComponentType::CHECKBOX:       nImageId = RID_SVXIMG_CHECKBOX; break;
164             case FormComponentType::LISTBOX:        nImageId = RID_SVXIMG_LISTBOX; break;
165             case FormComponentType::COMBOBOX:       nImageId = RID_SVXIMG_COMBOBOX; break;
166             case FormComponentType::GROUPBOX:       nImageId = RID_SVXIMG_GROUPBOX; break;
167             case FormComponentType::IMAGEBUTTON:    nImageId = RID_SVXIMG_IMAGEBUTTON; break;
168             case FormComponentType::FILECONTROL:    nImageId = RID_SVXIMG_FILECONTROL; break;
169             case FormComponentType::HIDDENCONTROL:  nImageId = RID_SVXIMG_HIDDEN; break;
170             case FormComponentType::DATEFIELD:      nImageId = RID_SVXIMG_DATEFIELD; break;
171             case FormComponentType::TIMEFIELD:      nImageId = RID_SVXIMG_TIMEFIELD; break;
172             case FormComponentType::NUMERICFIELD:   nImageId = RID_SVXIMG_NUMERICFIELD; break;
173             case FormComponentType::CURRENCYFIELD:  nImageId = RID_SVXIMG_CURRENCYFIELD; break;
174             case FormComponentType::PATTERNFIELD:   nImageId = RID_SVXIMG_PATTERNFIELD; break;
175             case FormComponentType::IMAGECONTROL:   nImageId = RID_SVXIMG_IMAGECONTROL; break;
176             case FormComponentType::GRIDCONTROL:    nImageId = RID_SVXIMG_GRID; break;
177             case FormComponentType::SCROLLBAR:      nImageId = RID_SVXIMG_SCROLLBAR; break;
178             case FormComponentType::SPINBUTTON:     nImageId = RID_SVXIMG_SPINBUTTON; break;
179             case FormComponentType::NAVIGATIONBAR:  nImageId = RID_SVXIMG_NAVIGATIONBAR; break;
180             default:
181                 DBG_ERROR( "TabOrderDialog::GetImage: unknown control type" );
182             }
183         }
184 
185         return pImageList->GetImage( nImageId );
186     }
187 
188     //------------------------------------------------------------------------
189     void TabOrderDialog::FillList()
190     {
191         DBG_ASSERT( m_xTempModel.is() && m_xControlContainer.is(), "TabOrderDialog::FillList: invalid call!" );
192         if ( !m_xTempModel.is() || !m_xControlContainer.is() )
193             return;
194 
195         aLB_Controls.Clear();
196 
197         try
198         {
199             Sequence< Reference< XControlModel > > aControlModels( m_xTempModel->getControlModels() );
200             const Reference< XControlModel >* pControlModels = aControlModels.getConstArray();
201 
202             ::rtl::OUString aName;
203             Image aImage;
204 
205             for ( sal_Int32 i=0; i < aControlModels.getLength(); ++i, ++pControlModels )
206             {
207                 Reference< XPropertySet > xControl( *pControlModels, UNO_QUERY );
208                 Reference< XPropertySetInfo > xPI;
209                 if ( xControl.is() )
210                     xPI = xControl->getPropertySetInfo();
211 
212                 if ( xPI.is() )
213                 {
214                     if ( xPI->hasPropertyByName( PROPERTY_TABSTOP ) )
215                     {
216                         aName = ::comphelper::getString( xControl->getPropertyValue( PROPERTY_NAME ) );
217                             // TODO: do Basic controls have a name?
218                         aImage = GetImage( xControl );
219                         aLB_Controls.InsertEntry( aName, aImage, aImage, 0, sal_False, LIST_APPEND, xControl.get() );
220                     }
221                 }
222                 else
223                 {
224                     // no property set -> no tab order
225                     DBG_ERROR( "TabOrderDialog::FillList: invalid control encountered!" );
226                     aLB_Controls.Clear();
227                     break;
228                 }
229             }
230         }
231         catch( const Exception& )
232         {
233         	DBG_ERROR( "TabOrderDialog::FillList: caught an exception!" );
234         }
235 
236         // select first entry
237         SvLBoxEntry* pFirstEntry = aLB_Controls.GetEntry( 0 );
238         if ( pFirstEntry )
239             aLB_Controls.Select( pFirstEntry );
240     }
241 
242     //------------------------------------------------------------------------
243     IMPL_LINK( TabOrderDialog, MoveUpClickHdl, Button*, /*pButton*/ )
244     {
245         aLB_Controls.MoveSelection( -1 );
246         return 0;
247     }
248 
249     //------------------------------------------------------------------------
250     IMPL_LINK( TabOrderDialog, MoveDownClickHdl, Button*, /*pButton*/ )
251     {
252         aLB_Controls.MoveSelection( 1 );
253         return 0;
254     }
255 
256     //------------------------------------------------------------------------
257     IMPL_LINK( TabOrderDialog, AutoOrderClickHdl, Button*, /*pButton*/ )
258     {
259         try
260         {
261             Reference< XTabController > xTabController;
262             if ( m_xORB.is() )
263                 xTabController = xTabController.query( m_xORB->createInstance( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.form.FormController" ) ) ) );
264             DBG_ASSERT( xTabController.is(), "TabOrderDialog::AutoOrderClickHdl: could not instantiate a tab controller!" );
265             if ( !xTabController.is() )
266                 return 0;
267 
268             xTabController->setModel( m_xTempModel );
269             xTabController->setContainer( m_xControlContainer );
270             xTabController->autoTabOrder();
271 
272             SetModified();
273             FillList();
274 
275             ::comphelper::disposeComponent( xTabController );
276         }
277         catch( const Exception& )
278         {
279             OSL_ENSURE( sal_False, "TabOrderDialog::AutoOrderClickHdl: caught an exception!" );
280         }
281 
282         return 0;
283     }
284 
285     //------------------------------------------------------------------------
286     IMPL_LINK( TabOrderDialog, OKClickHdl, Button*, /*pButton*/ )
287     {
288         sal_uLong nEntryCount = aLB_Controls.GetEntryCount();
289         Sequence< Reference< XControlModel > > aSortedControlModelSeq( nEntryCount );
290         Sequence< Reference< XControlModel > > aControlModels( m_xTempModel->getControlModels());
291         Reference< XControlModel > * pSortedControlModels = aSortedControlModelSeq.getArray();
292         const Reference< XControlModel > * pControlModels = aControlModels.getConstArray();
293 
294         for (sal_uLong i=0; i < nEntryCount; i++)
295         {
296             SvLBoxEntry* pEntry = aLB_Controls.GetEntry(i);
297 
298             for( sal_Int32 j=0; j<aControlModels.getLength(); j++ )
299             {
300                 Reference< XPropertySet >  xSet(pControlModels[j], UNO_QUERY);
301                 if ((XPropertySet*)xSet.get() == ((XPropertySet*)pEntry->GetUserData()))
302                 {
303                     pSortedControlModels[i] = pControlModels[j];
304                     break;
305                 }
306             }
307         }
308 
309         // TODO: UNO action (to bracket all the single actions which are being created)
310 //        pDrawModel->BegUndo(PcrRes(RID_STR_UNDO_TABORDER));
311         m_xModel->setControlModels( aSortedControlModelSeq );
312 //        pDrawModel->EndUndo();
313 
314         EndDialog( sal_True );
315         return 0;
316     }
317 
318     //========================================================================
319     //= TabOrderListBox
320     //========================================================================
321     DBG_NAME(TabOrderListBox);
322     //------------------------------------------------------------------------
323     TabOrderListBox::TabOrderListBox( Window* pParent, const ResId& rResId  )
324         :SvTreeListBox( pParent, rResId  )
325     {
326         DBG_CTOR(TabOrderListBox,NULL);
327         SetDragDropMode(0xFFFF/*SV_DRAGDROP_CTRL_MOVE*/);
328             // Hmm. The flag alone is not enough, so to be on the safe side ...
329 
330         SetSelectionMode( MULTIPLE_SELECTION );
331     }
332 
333     //------------------------------------------------------------------------
334     TabOrderListBox::~TabOrderListBox()
335     {
336         DBG_DTOR(TabOrderListBox,NULL);
337     }
338 
339     //------------------------------------------------------------------------
340     void TabOrderListBox::ModelHasMoved( SvListEntry* _pSource )
341     {
342         SvTreeListBox::ModelHasMoved( _pSource );
343 
344         ((TabOrderDialog*)Window::GetParent())->SetModified();
345     }
346 
347     //------------------------------------------------------------------------
348     void TabOrderListBox::MoveSelection( long nRelPos )
349     {
350         UniString aSelEntryPrevText,aSelEntryNextText;
351         Image  aImage;
352         for (long i=0; i<labs(nRelPos); i++)
353         {
354             ((TabOrderDialog*)Window::GetParent())->SetModified();
355 
356             //////////////////////////////////////////////////////////////////////
357             // move entries
358             if( nRelPos < 0 )
359             {
360                 SvLBoxEntry* pFirstSelected = FirstSelected();
361                 if( !pFirstSelected ) return;
362                 sal_uLong nFirstSelPos = GetModel()->GetAbsPos( pFirstSelected );
363                 if( nFirstSelPos == 0 ) return;
364 
365                 SvLBoxEntry* pSelEntry = pFirstSelected;
366                 while( pSelEntry )
367                 {
368                     sal_uLong nSelEntryPos = GetModel()->GetAbsPos( pSelEntry );
369                     SvLBoxEntry* pSelEntryPrev = GetEntry( nSelEntryPos-1 );
370                     aSelEntryPrevText = GetEntryText( pSelEntryPrev );
371                     aImage = GetExpandedEntryBmp(pSelEntryPrev);
372                     void*  pData = pSelEntryPrev->GetUserData();
373 
374                     GetModel()->Remove( pSelEntryPrev );
375                     InsertEntry( aSelEntryPrevText, aImage, aImage, 0, sal_False, nSelEntryPos, pData );
376 
377                     pSelEntry = NextSelected( pSelEntry );
378                 }
379             }
380 
381             else if( nRelPos > 0 )
382             {
383                 SvLBoxEntry* pLastSelected = LastSelected();
384                 if( !pLastSelected ) return;
385                 sal_uLong nLastSelPos = GetModel()->GetAbsPos( pLastSelected );
386 
387                 if( (nLastSelPos + nRelPos - i) > (GetEntryCount()-1) ) return;
388 
389 #if OSL_DEBUG_LEVEL > 0
390                 sal_uLong nSelCount = GetSelectionCount();
391                 (void)nSelCount;
392 #endif
393 
394 
395                 SvLBoxEntry* pSelEntry = pLastSelected;
396                 while( pSelEntry )
397                 {
398                     sal_uLong nSelEntryPos = GetModel()->GetAbsPos( pSelEntry );
399                     SvLBoxEntry* pSelEntryNext = GetEntry( nSelEntryPos+1 );
400                     void* pData = pSelEntryNext->GetUserData();
401 
402                     aSelEntryNextText = GetEntryText( pSelEntryNext );
403                     aImage = GetExpandedEntryBmp(pSelEntryNext);
404 
405                     GetModel()->Remove( pSelEntryNext );
406                     InsertEntry( aSelEntryNextText, aImage, aImage, 0, sal_False, nSelEntryPos, pData );
407 
408                     pSelEntry = PrevSelected( pSelEntry );
409                 }
410                 long nThumbPos      = GetVScroll()->GetThumbPos();
411                 long nVisibleSize   = GetVScroll()->GetVisibleSize();
412                 long nFirstVisible = GetModel()->GetAbsPos( FirstVisible());
413 
414                 if ( ( nThumbPos + nVisibleSize + 1 ) < (long)( nLastSelPos + 3 ) )
415                     GetVScroll()->DoScrollAction(SCROLL_LINEDOWN);
416                 else if((nThumbPos+nVisibleSize+1) >= (nFirstVisible))
417                     GetVScroll()->DoScrollAction(SCROLL_LINEUP);
418             }
419         }
420     }
421 
422 //............................................................................
423 }  // namespace pcr
424 //............................................................................
425