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