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