xref: /trunk/main/extensions/source/dbpilots/gridwizard.cxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
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 "gridwizard.hxx"
31 #include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
32 #include <com/sun/star/sdbc/DataType.hpp>
33 #include <comphelper/stl_types.hxx>
34 #include <tools/string.hxx>
35 #include <com/sun/star/form/XGridColumnFactory.hpp>
36 #include <com/sun/star/awt/MouseWheelBehavior.hpp>
37 #include <com/sun/star/container/XNameContainer.hpp>
38 #include <tools/debug.hxx>
39 #include "dbptools.hxx"
40 #include "dbpilots.hrc"
41 
42 #define GW_STATE_DATASOURCE_SELECTION   0
43 #define GW_STATE_FIELDSELECTION         1
44 
45 //.........................................................................
46 namespace dbp
47 {
48 //.........................................................................
49 
50     using namespace ::com::sun::star::uno;
51     using namespace ::com::sun::star::lang;
52     using namespace ::com::sun::star::beans;
53     using namespace ::com::sun::star::sdbc;
54     using namespace ::com::sun::star::container;
55     using namespace ::com::sun::star::form;
56     using namespace ::com::sun::star::awt;
57     using namespace ::svt;
58 
59     //=====================================================================
60     //= OGridWizard
61     //=====================================================================
62     //---------------------------------------------------------------------
63     OGridWizard::OGridWizard( Window* _pParent,
64             const Reference< XPropertySet >& _rxObjectModel, const Reference< XMultiServiceFactory >& _rxORB )
65         :OControlWizard(_pParent, ModuleRes(RID_DLG_GRIDWIZARD), _rxObjectModel, _rxORB)
66         ,m_bHadDataSelection(sal_True)
67     {
68         initControlSettings(&m_aSettings);
69 
70         m_pPrevPage->SetHelpId(HID_GRIDWIZARD_PREVIOUS);
71         m_pNextPage->SetHelpId(HID_GRIDWIZARD_NEXT);
72         m_pCancel->SetHelpId(HID_GRIDWIZARD_CANCEL);
73         m_pFinish->SetHelpId(HID_GRIDWIZARD_FINISH);
74 
75         // if we do not need the data source selection page ...
76         if (!needDatasourceSelection())
77         {   // ... skip it!
78             skip(1);
79             m_bHadDataSelection = sal_False;
80         }
81     }
82 
83     //---------------------------------------------------------------------
84     sal_Bool OGridWizard::approveControl(sal_Int16 _nClassId)
85     {
86         if (FormComponentType::GRIDCONTROL != _nClassId)
87             return sal_False;
88 
89         Reference< XGridColumnFactory > xColumnFactory(getContext().xObjectModel, UNO_QUERY);
90         if (!xColumnFactory.is())
91             return sal_False;
92 
93         return sal_True;
94     }
95 
96     //---------------------------------------------------------------------
97     void OGridWizard::implApplySettings()
98     {
99         const OControlWizardContext& rContext = getContext();
100 
101         // the factory for the columns
102         Reference< XGridColumnFactory > xColumnFactory(rContext.xObjectModel, UNO_QUERY);
103         DBG_ASSERT(xColumnFactory.is(), "OGridWizard::implApplySettings: should never have made it 'til here!");
104             // (if we're here, what the hell happened in approveControl??)
105 
106         // the container for the columns
107         Reference< XNameContainer > xColumnContainer(rContext.xObjectModel, UNO_QUERY);
108         DBG_ASSERT(xColumnContainer.is(), "OGridWizard::implApplySettings: no container!");
109 
110         if (!xColumnFactory.is() || !xColumnContainer.is())
111             return;
112 
113         static const ::rtl::OUString s_sDataFieldProperty   = ::rtl::OUString::createFromAscii("DataField");
114         static const ::rtl::OUString s_sLabelProperty       = ::rtl::OUString::createFromAscii("Label");
115         static const ::rtl::OUString s_sWidthProperty       = ::rtl::OUString::createFromAscii("Width");
116         static const ::rtl::OUString s_sMouseWheelBehavior  = ::rtl::OUString::createFromAscii("MouseWheelBehavior");
117         static const ::rtl::OUString s_sEmptyString;
118 
119         // collect "descriptors" for the to-be-created (grid)columns
120         DECLARE_STL_VECTOR( ::rtl::OUString, StringArray );
121         StringArray aColumnServiceNames;    // service names to be used with the XGridColumnFactory
122         StringArray aColumnLabelPostfixes;  // postfixes to append to the column labels
123         StringArray aFormFieldNames;        // data field names
124 
125         aColumnServiceNames.reserve(getSettings().aSelectedFields.getLength());
126         aColumnLabelPostfixes.reserve(getSettings().aSelectedFields.getLength());
127         aFormFieldNames.reserve(getSettings().aSelectedFields.getLength());
128 
129         // loop through the selected field names
130         const ::rtl::OUString* pSelectedFields = getSettings().aSelectedFields.getConstArray();
131         const ::rtl::OUString* pEnd = pSelectedFields + getSettings().aSelectedFields.getLength();
132         for (;pSelectedFields < pEnd; ++pSelectedFields)
133         {
134             // get the information for the selected column
135             sal_Int32 nFieldType = DataType::OTHER;
136             OControlWizardContext::TNameTypeMap::const_iterator aFind = rContext.aTypes.find(*pSelectedFields);
137             if ( aFind != rContext.aTypes.end() )
138                 nFieldType = aFind->second;
139 
140             aFormFieldNames.push_back(*pSelectedFields);
141             switch (nFieldType)
142             {
143                 case DataType::BIT:
144                 case DataType::BOOLEAN:
145                     aColumnServiceNames.push_back(::rtl::OUString::createFromAscii("CheckBox"));
146                     aColumnLabelPostfixes.push_back(s_sEmptyString);
147                     break;
148 
149                 case DataType::TINYINT:
150                 case DataType::SMALLINT:
151                 case DataType::INTEGER:
152                     aColumnServiceNames.push_back(::rtl::OUString::createFromAscii("NumericField"));
153                     aColumnLabelPostfixes.push_back(s_sEmptyString);
154                     break;
155 
156                 case DataType::FLOAT:
157                 case DataType::REAL:
158                 case DataType::DOUBLE:
159                 case DataType::NUMERIC:
160                 case DataType::DECIMAL:
161                     aColumnServiceNames.push_back(::rtl::OUString::createFromAscii("FormattedField"));
162                     aColumnLabelPostfixes.push_back(s_sEmptyString);
163                     break;
164 
165                 case DataType::DATE:
166                     aColumnServiceNames.push_back(::rtl::OUString::createFromAscii("DateField"));
167                     aColumnLabelPostfixes.push_back(s_sEmptyString);
168                     break;
169 
170                 case DataType::TIME:
171                     aColumnServiceNames.push_back(::rtl::OUString::createFromAscii("TimeField"));
172                     aColumnLabelPostfixes.push_back(s_sEmptyString);
173                     break;
174 
175                 case DataType::TIMESTAMP:
176                     aColumnServiceNames.push_back(::rtl::OUString::createFromAscii("DateField"));
177                     aColumnLabelPostfixes.push_back(String(ModuleRes(RID_STR_DATEPOSTFIX)));
178 
179                     aFormFieldNames.push_back(*pSelectedFields);
180                     aColumnServiceNames.push_back(::rtl::OUString::createFromAscii("TimeField"));
181                     aColumnLabelPostfixes.push_back(String(ModuleRes(RID_STR_TIMEPOSTFIX)));
182                     break;
183 
184                 default:
185                     aColumnServiceNames.push_back(::rtl::OUString::createFromAscii("TextField"));
186                     aColumnLabelPostfixes.push_back(s_sEmptyString);
187             }
188         }
189 
190         DBG_ASSERT( aFormFieldNames.size() == aColumnServiceNames.size()
191                 &&  aColumnServiceNames.size() == aColumnLabelPostfixes.size(),
192                 "OGridWizard::implApplySettings: inconsistent descriptor sequences!");
193 
194         // now loop through the descriptions and create the (grid)columns out of th descriptors
195         {
196             Reference< XNameAccess > xExistenceChecker(xColumnContainer.get());
197 
198             ConstStringArrayIterator pColumnServiceName = aColumnServiceNames.begin();
199             ConstStringArrayIterator pColumnLabelPostfix = aColumnLabelPostfixes.begin();
200             ConstStringArrayIterator pFormFieldName = aFormFieldNames.begin();
201             ConstStringArrayIterator pColumnServiceNameEnd = aColumnServiceNames.end();
202 
203             for (;pColumnServiceName < pColumnServiceNameEnd; ++pColumnServiceName, ++pColumnLabelPostfix, ++pFormFieldName)
204             {
205                 // create a (grid)column for the (resultset)column
206                 try
207                 {
208                     Reference< XPropertySet > xColumn( xColumnFactory->createColumn(*pColumnServiceName), UNO_SET_THROW );
209                     Reference< XPropertySetInfo > xColumnPSI( xColumn->getPropertySetInfo(), UNO_SET_THROW );
210 
211                     ::rtl::OUString sColumnName(*pColumnServiceName);
212                     disambiguateName(xExistenceChecker, sColumnName);
213 
214                     // the data field the column should be bound to
215                     xColumn->setPropertyValue(s_sDataFieldProperty, makeAny(*pFormFieldName));
216                     // the label
217                     xColumn->setPropertyValue(s_sLabelProperty, makeAny(::rtl::OUString(*pFormFieldName) += *pColumnLabelPostfix));
218                     // the width (<void/> => column will be auto-sized)
219                     xColumn->setPropertyValue(s_sWidthProperty, Any());
220 
221                     if ( xColumnPSI->hasPropertyByName( s_sMouseWheelBehavior ) )
222                         xColumn->setPropertyValue( s_sMouseWheelBehavior, makeAny( MouseWheelBehavior::SCROLL_DISABLED ) );
223 
224                     // insert the column
225                     xColumnContainer->insertByName(sColumnName, makeAny(xColumn));
226                 }
227                 catch(Exception&)
228                 {
229                     DBG_ERROR(  ::rtl::OString("OGridWizard::implApplySettings: unexpected exception while creating the grid column for field ")
230                             +=  ::rtl::OString(pFormFieldName->getStr(), pFormFieldName->getLength(), gsl_getSystemTextEncoding())
231                             +=  ::rtl::OString("!"));
232                 }
233             }
234         }
235     }
236 
237     //---------------------------------------------------------------------
238     OWizardPage* OGridWizard::createPage(WizardState _nState)
239     {
240         switch (_nState)
241         {
242             case GW_STATE_DATASOURCE_SELECTION:
243                 return new OTableSelectionPage(this);
244             case GW_STATE_FIELDSELECTION:
245                 return new OGridFieldsSelection(this);
246         }
247 
248         return NULL;
249     }
250 
251     //---------------------------------------------------------------------
252     WizardTypes::WizardState OGridWizard::determineNextState( WizardState _nCurrentState ) const
253     {
254         switch (_nCurrentState)
255         {
256             case GW_STATE_DATASOURCE_SELECTION:
257                 return GW_STATE_FIELDSELECTION;
258             case GW_STATE_FIELDSELECTION:
259                 return WZS_INVALID_STATE;
260         }
261 
262         return WZS_INVALID_STATE;
263     }
264 
265     //---------------------------------------------------------------------
266     void OGridWizard::enterState(WizardState _nState)
267     {
268         OControlWizard::enterState(_nState);
269 
270         enableButtons(WZB_PREVIOUS, m_bHadDataSelection ? (GW_STATE_DATASOURCE_SELECTION < _nState) : GW_STATE_FIELDSELECTION < _nState);
271         enableButtons(WZB_NEXT, GW_STATE_FIELDSELECTION != _nState);
272         if (_nState < GW_STATE_FIELDSELECTION)
273             enableButtons(WZB_FINISH, sal_False);
274 
275         if (GW_STATE_FIELDSELECTION == _nState)
276             defaultButton(WZB_FINISH);
277     }
278 
279     //---------------------------------------------------------------------
280     sal_Bool OGridWizard::leaveState(WizardState _nState)
281     {
282         if (!OControlWizard::leaveState(_nState))
283             return sal_False;
284 
285         if (GW_STATE_FIELDSELECTION == _nState)
286             defaultButton(WZB_NEXT);
287 
288         return sal_True;
289     }
290 
291     //---------------------------------------------------------------------
292     sal_Bool OGridWizard::onFinish()
293     {
294         if ( !OControlWizard::onFinish() )
295             return sal_False;
296 
297         implApplySettings();
298 
299         return sal_True;
300     }
301 
302     //=====================================================================
303     //= OGridFieldsSelection
304     //=====================================================================
305     //---------------------------------------------------------------------
306     OGridFieldsSelection::OGridFieldsSelection( OGridWizard* _pParent )
307         :OGridPage(_pParent, ModuleRes(RID_PAGE_GW_FIELDSELECTION))
308         ,m_aFrame               (this, ModuleRes(FL_FRAME))
309         ,m_aExistFieldsLabel    (this, ModuleRes(FT_EXISTING_FIELDS))
310         ,m_aExistFields         (this, ModuleRes(LB_EXISTING_FIELDS))
311         ,m_aSelectOne           (this, ModuleRes(PB_FIELDRIGHT))
312         ,m_aSelectAll           (this, ModuleRes(PB_ALLFIELDSRIGHT))
313         ,m_aDeselectOne         (this, ModuleRes(PB_FIELDLEFT))
314         ,m_aDeselectAll         (this, ModuleRes(PB_ALLFIELDSLEFT))
315         ,m_aSelFieldsLabel      (this, ModuleRes(FT_SELECTED_FIELDS))
316         ,m_aSelFields           (this, ModuleRes(LB_SELECTED_FIELDS))
317     {
318         FreeResource();
319 
320         enableFormDatasourceDisplay();
321 
322         m_aSelectOne.SetClickHdl(LINK(this, OGridFieldsSelection, OnMoveOneEntry));
323         m_aSelectAll.SetClickHdl(LINK(this, OGridFieldsSelection, OnMoveAllEntries));
324         m_aDeselectOne.SetClickHdl(LINK(this, OGridFieldsSelection, OnMoveOneEntry));
325         m_aDeselectAll.SetClickHdl(LINK(this, OGridFieldsSelection, OnMoveAllEntries));
326 
327         m_aExistFields.SetSelectHdl(LINK(this, OGridFieldsSelection, OnEntrySelected));
328         m_aSelFields.SetSelectHdl(LINK(this, OGridFieldsSelection, OnEntrySelected));
329         m_aExistFields.SetDoubleClickHdl(LINK(this, OGridFieldsSelection, OnEntryDoubleClicked));
330         m_aSelFields.SetDoubleClickHdl(LINK(this, OGridFieldsSelection, OnEntryDoubleClicked));
331     }
332 
333     //---------------------------------------------------------------------
334     void OGridFieldsSelection::ActivatePage()
335     {
336         OGridPage::ActivatePage();
337         m_aExistFields.GrabFocus();
338     }
339 
340     //---------------------------------------------------------------------
341     bool OGridFieldsSelection::canAdvance() const
342     {
343         return false;
344             // we're the last page in our wizard
345     }
346 
347     //---------------------------------------------------------------------
348     void OGridFieldsSelection::initializePage()
349     {
350         OGridPage::initializePage();
351 
352         const OControlWizardContext& rContext = getContext();
353         fillListBox(m_aExistFields, rContext.aFieldNames);
354 
355         m_aSelFields.Clear();
356         const OGridSettings& rSettings = getSettings();
357         const ::rtl::OUString* pSelected = rSettings.aSelectedFields.getConstArray();
358         const ::rtl::OUString* pEnd = pSelected + rSettings.aSelectedFields.getLength();
359         for (; pSelected < pEnd; ++pSelected)
360         {
361             m_aSelFields.InsertEntry(*pSelected);
362             m_aExistFields.RemoveEntry(*pSelected);
363         }
364 
365         implCheckButtons();
366     }
367 
368     //---------------------------------------------------------------------
369     sal_Bool OGridFieldsSelection::commitPage( ::svt::WizardTypes::CommitPageReason _eReason )
370     {
371         if (!OGridPage::commitPage(_eReason))
372             return sal_False;
373 
374         OGridSettings& rSettings = getSettings();
375         sal_uInt16 nSelected = m_aSelFields.GetEntryCount();
376 
377         rSettings.aSelectedFields.realloc(nSelected);
378         ::rtl::OUString* pSelected = rSettings.aSelectedFields.getArray();
379 
380         for (sal_uInt16 i=0; i<nSelected; ++i, ++pSelected)
381             *pSelected = m_aSelFields.GetEntry(i);
382 
383         return sal_True;
384     }
385 
386     //---------------------------------------------------------------------
387     void OGridFieldsSelection::implCheckButtons()
388     {
389         m_aSelectOne.Enable(m_aExistFields.GetSelectEntryCount() != 0);
390         m_aSelectAll.Enable(m_aExistFields.GetEntryCount() != 0);
391 
392         m_aDeselectOne.Enable(m_aSelFields.GetSelectEntryCount() != 0);
393         m_aDeselectAll.Enable(m_aSelFields.GetEntryCount() != 0);
394 
395         getDialog()->enableButtons(WZB_FINISH, 0 != m_aSelFields.GetEntryCount());
396     }
397 
398     //---------------------------------------------------------------------
399     IMPL_LINK(OGridFieldsSelection, OnEntryDoubleClicked, ListBox*, _pList)
400     {
401         PushButton* pSimulateButton = &m_aExistFields == _pList ? &m_aSelectOne : &m_aDeselectOne;
402         if (pSimulateButton->IsEnabled())
403             return OnMoveOneEntry( pSimulateButton );
404         else
405             return 1L;
406     }
407 
408     //---------------------------------------------------------------------
409     IMPL_LINK(OGridFieldsSelection, OnEntrySelected, ListBox*, /*NOTINTERESTEDIN*/)
410     {
411         implCheckButtons();
412         return 0L;
413     }
414 
415     //---------------------------------------------------------------------
416     IMPL_LINK(OGridFieldsSelection, OnMoveOneEntry, PushButton*, _pButton)
417     {
418         sal_Bool bMoveRight = (&m_aSelectOne == _pButton);
419         ListBox& rMoveTo = bMoveRight ? m_aSelFields : m_aExistFields;
420 
421         // the index of the selected entry
422         sal_uInt16 nSelected = bMoveRight ? m_aExistFields.GetSelectEntryPos() : m_aSelFields.GetSelectEntryPos();
423         // the (original) relative position of the entry
424         sal_IntPtr nRelativeIndex = reinterpret_cast<sal_IntPtr>(bMoveRight ? m_aExistFields.GetEntryData(nSelected) : m_aSelFields.GetEntryData(nSelected));
425 
426         sal_uInt16 nInsertPos = LISTBOX_APPEND;
427         if (!bMoveRight)
428         {   // need to determine an insert pos which reflects the original
429             nInsertPos = 0;
430             while (nInsertPos < rMoveTo.GetEntryCount())
431             {
432                 if (reinterpret_cast<sal_IntPtr>(rMoveTo.GetEntryData(nInsertPos)) > nRelativeIndex)
433                     break;
434                 ++nInsertPos;
435             }
436         }
437 
438         // the text of the entry to move
439         String sMovingEntry = bMoveRight ? m_aExistFields.GetEntry(nSelected) : m_aSelFields.GetEntry(nSelected);
440 
441         // insert the entry
442         nInsertPos = rMoveTo.InsertEntry(sMovingEntry, nInsertPos);
443         // preserve it's "relative position" entry data
444         rMoveTo.SetEntryData(nInsertPos, reinterpret_cast<void*>(nRelativeIndex));
445 
446         // remove the entry from it's old list
447         if (bMoveRight)
448         {
449             sal_uInt16 nSelectPos = m_aExistFields.GetSelectEntryPos();
450             m_aExistFields.RemoveEntry(nSelected);
451             if ((LISTBOX_ENTRY_NOTFOUND != nSelectPos) && (nSelectPos < m_aExistFields.GetEntryCount()))
452                 m_aExistFields.SelectEntryPos(nSelectPos);
453 
454             m_aExistFields.GrabFocus();
455         }
456         else
457         {
458             sal_uInt16 nSelectPos = m_aSelFields.GetSelectEntryPos();
459             m_aSelFields.RemoveEntry(nSelected);
460             if ((LISTBOX_ENTRY_NOTFOUND != nSelectPos) && (nSelectPos < m_aSelFields.GetEntryCount()))
461                 m_aSelFields.SelectEntryPos(nSelectPos);
462 
463             m_aSelFields.GrabFocus();
464         }
465 
466         implCheckButtons();
467         return 0;
468     }
469 
470     //---------------------------------------------------------------------
471     IMPL_LINK(OGridFieldsSelection, OnMoveAllEntries, PushButton*, _pButton)
472     {
473         sal_Bool bMoveRight = (&m_aSelectAll == _pButton);
474         m_aExistFields.Clear();
475         m_aSelFields.Clear();
476         fillListBox(bMoveRight ? m_aSelFields : m_aExistFields, getContext().aFieldNames);
477 
478         implCheckButtons();
479         return 0;
480     }
481 
482 //.........................................................................
483 }   // namespace dbp
484 //.........................................................................
485 
486