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_forms.hxx"
26
27
28 #include "Filter.hxx"
29 #include "FormComponent.hxx"
30 #include "frm_module.hxx"
31 #include "frm_resource.hrc"
32 #include "frm_resource.hxx"
33 #include "property.hrc"
34 #include "property.hxx"
35
36 /** === begin UNO includes === **/
37 #include <com/sun/star/awt/VclWindowPeerAttribute.hpp>
38 #include <com/sun/star/awt/XCheckBox.hpp>
39 #include <com/sun/star/awt/XComboBox.hpp>
40 #include <com/sun/star/awt/XListBox.hpp>
41 #include <com/sun/star/awt/XRadioButton.hpp>
42 #include <com/sun/star/awt/XVclWindowPeer.hpp>
43 #include <com/sun/star/beans/NamedValue.hpp>
44 #include <com/sun/star/container/XChild.hpp>
45 #include <com/sun/star/container/XIndexAccess.hpp>
46 #include <com/sun/star/container/XNamed.hpp>
47 #include <com/sun/star/form/FormComponentType.hpp>
48 #include <com/sun/star/sdb/BooleanComparisonMode.hpp>
49 #include <com/sun/star/sdb/XColumn.hpp>
50 #include <com/sun/star/sdb/XSQLQueryComposerFactory.hpp>
51 #include <com/sun/star/sdbc/DataType.hpp>
52 #include <com/sun/star/sdbc/XRowSet.hpp>
53 #include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
54 #include <com/sun/star/sdbcx/XTablesSupplier.hpp>
55 #include <com/sun/star/ui/dialogs/XExecutableDialog.hpp>
56 #include <com/sun/star/awt/XItemList.hpp>
57 /** === end UNO includes === **/
58
59 #include <comphelper/numbers.hxx>
60 #include <comphelper/property.hxx>
61 #include <connectivity/dbconversion.hxx>
62 #include <connectivity/dbtools.hxx>
63 #include <connectivity/formattedcolumnvalue.hxx>
64 #include <connectivity/predicateinput.hxx>
65 #include <rtl/ustrbuf.hxx>
66 #include <toolkit/helper/vclunohelper.hxx>
67 #include <tools/diagnose_ex.h>
68 #include <unotools/localedatawrapper.hxx>
69 #include <vcl/stdtext.hxx>
70 #include <vcl/svapp.hxx>
71 #include <tools/wintypes.hxx>
72
73 //--------------------------------------------------------------------------
createRegistryInfo_OFilterControl()74 extern "C" void SAL_CALL createRegistryInfo_OFilterControl()
75 {
76 static ::frm::OMultiInstanceAutoRegistration< ::frm::OFilterControl > aAutoRegistration;
77 }
78
79 //.........................................................................
80 namespace frm
81 {
82 //.........................................................................
83
84 using namespace ::com::sun::star::uno;
85 using namespace ::com::sun::star::awt;
86 using namespace ::com::sun::star::lang;
87 using namespace ::com::sun::star::beans;
88 using namespace ::com::sun::star::sdb;
89 using namespace ::com::sun::star::sdbc;
90 using namespace ::com::sun::star::sdbcx;
91 using namespace ::com::sun::star::util;
92 using namespace ::com::sun::star::form;
93 using namespace ::com::sun::star::container;
94 using namespace ::com::sun::star::ui::dialogs;
95
96 using namespace ::connectivity;
97
98 //=====================================================================
99 // OFilterControl
100 //=====================================================================
101 //---------------------------------------------------------------------
OFilterControl(const Reference<XMultiServiceFactory> & _rxORB)102 OFilterControl::OFilterControl( const Reference< XMultiServiceFactory >& _rxORB )
103 :UnoControl( _rxORB )
104 ,m_aTextListeners( *this )
105 ,m_aParser( _rxORB )
106 ,m_nControlClass( FormComponentType::TEXTFIELD )
107 ,m_bFilterList( sal_False )
108 ,m_bMultiLine( sal_False )
109 ,m_bFilterListFilled( sal_False )
110 {
111 }
112
113 //---------------------------------------------------------------------
ensureInitialized()114 sal_Bool OFilterControl::ensureInitialized( )
115 {
116 if ( !m_xField.is() )
117 {
118 OSL_ENSURE( sal_False, "OFilterControl::ensureInitialized: improperly initialized: no field!" );
119 return sal_False;
120 }
121
122 if ( !m_xConnection.is() )
123 {
124 OSL_ENSURE( sal_False, "OFilterControl::ensureInitialized: improperly initialized: no connection!" );
125 return sal_False;
126 }
127
128 if ( !m_xFormatter.is() )
129 {
130 // we can create one from the connection, if it's an SDB connection
131 Reference< XNumberFormatsSupplier > xFormatSupplier = ::dbtools::getNumberFormats( m_xConnection, sal_True, maContext.getLegacyServiceFactory() );
132
133 if ( xFormatSupplier.is() )
134 {
135 maContext.createComponent( "com.sun.star.util.NumberFormatter", m_xFormatter );
136 if ( m_xFormatter.is() )
137 m_xFormatter->attachNumberFormatsSupplier( xFormatSupplier );
138 }
139 }
140 if ( !m_xFormatter.is() )
141 {
142 OSL_ENSURE( sal_False, "OFilterControl::ensureInitialized: no number formatter!" );
143 // no fallback anymore
144 return sal_False;
145 }
146
147 return sal_True;
148 }
149
150 //---------------------------------------------------------------------
queryAggregation(const Type & rType)151 Any SAL_CALL OFilterControl::queryAggregation( const Type & rType ) throw(RuntimeException)
152 {
153 Any aRet = UnoControl::queryAggregation( rType);
154 if(!aRet.hasValue())
155 aRet = OFilterControl_BASE::queryInterface(rType);
156
157 return aRet;
158 }
159
160 //------------------------------------------------------------------
GetComponentServiceName()161 ::rtl::OUString OFilterControl::GetComponentServiceName()
162 {
163 ::rtl::OUString aServiceName;
164 switch (m_nControlClass)
165 {
166 case FormComponentType::RADIOBUTTON:
167 aServiceName = ::rtl::OUString::createFromAscii("radiobutton");
168 break;
169 case FormComponentType::CHECKBOX:
170 aServiceName = ::rtl::OUString::createFromAscii("checkbox");
171 break;
172 case FormComponentType::COMBOBOX:
173 aServiceName = ::rtl::OUString::createFromAscii("combobox");
174 break;
175 case FormComponentType::LISTBOX:
176 aServiceName = ::rtl::OUString::createFromAscii("listbox");
177 break;
178 default:
179 if (m_bMultiLine)
180 aServiceName = ::rtl::OUString::createFromAscii("MultiLineEdit");
181 else
182 aServiceName = ::rtl::OUString::createFromAscii("Edit");
183 }
184 return aServiceName;
185 }
186
187 // XComponent
188 //---------------------------------------------------------------------
dispose()189 void OFilterControl::dispose() throw( RuntimeException )
190 {
191 EventObject aEvt(*this);
192 m_aTextListeners.disposeAndClear( aEvt );
193 UnoControl::dispose();
194 }
195
196 //---------------------------------------------------------------------
createPeer(const Reference<XToolkit> & rxToolkit,const Reference<XWindowPeer> & rParentPeer)197 void OFilterControl::createPeer( const Reference< XToolkit > & rxToolkit, const Reference< XWindowPeer > & rParentPeer ) throw(RuntimeException)
198 {
199 UnoControl::createPeer( rxToolkit, rParentPeer );
200
201 try
202 {
203 Reference< XVclWindowPeer > xVclWindow( getPeer(), UNO_QUERY_THROW );
204 switch ( m_nControlClass )
205 {
206 case FormComponentType::CHECKBOX:
207 {
208 // checkboxes always have a tristate-mode
209 xVclWindow->setProperty( PROPERTY_TRISTATE, makeAny( sal_Bool( sal_True ) ) );
210 xVclWindow->setProperty( PROPERTY_STATE, makeAny( sal_Int32( STATE_DONTKNOW ) ) );
211
212 Reference< XCheckBox > xBox( getPeer(), UNO_QUERY_THROW );
213 xBox->addItemListener( this );
214
215 }
216 break;
217
218 case FormComponentType::RADIOBUTTON:
219 {
220 xVclWindow->setProperty( PROPERTY_STATE, makeAny( sal_Int32( STATE_NOCHECK ) ) );
221
222 Reference< XRadioButton > xRadio( getPeer(), UNO_QUERY_THROW );
223 xRadio->addItemListener( this );
224 }
225 break;
226
227 case FormComponentType::LISTBOX:
228 {
229 Reference< XListBox > xListBox( getPeer(), UNO_QUERY_THROW );
230 xListBox->addItemListener( this );
231 }
232 // no break
233
234 case FormComponentType::COMBOBOX:
235 {
236 xVclWindow->setProperty(PROPERTY_AUTOCOMPLETE, makeAny( sal_Bool( sal_True ) ) );
237 }
238 // no break
239
240 default:
241 {
242 Reference< XWindow > xWindow( getPeer(), UNO_QUERY );
243 xWindow->addFocusListener( this );
244
245 Reference< XTextComponent > xText( getPeer(), UNO_QUERY );
246 if (xText.is())
247 xText->setMaxTextLen(0);
248 }
249 break;
250 }
251
252 OControl::initFormControlPeer( getPeer() );
253
254 // filter controls are _never_ readonly
255 // #107013# - 2002-02-03 - fs@openoffice.org
256 Reference< XPropertySet > xModel( getModel(), UNO_QUERY_THROW );
257 Reference< XPropertySetInfo > xModelPSI( xModel->getPropertySetInfo(), UNO_SET_THROW );
258 if ( xModelPSI->hasPropertyByName( PROPERTY_READONLY ) )
259 xVclWindow->setProperty( PROPERTY_READONLY, makeAny( sal_Bool( sal_False ) ) );
260 }
261 catch( const Exception& )
262 {
263 DBG_UNHANDLED_EXCEPTION();
264 }
265
266 if (m_bFilterList)
267 m_bFilterListFilled = sal_False;
268 }
269
270 //---------------------------------------------------------------------
PrepareWindowDescriptor(WindowDescriptor & rDescr)271 void OFilterControl::PrepareWindowDescriptor( WindowDescriptor& rDescr )
272 {
273 if (m_bFilterList)
274 rDescr.WindowAttributes |= VclWindowPeerAttribute::DROPDOWN;
275 }
276
277 //---------------------------------------------------------------------
ImplSetPeerProperty(const::rtl::OUString & rPropName,const Any & rVal)278 void OFilterControl::ImplSetPeerProperty( const ::rtl::OUString& rPropName, const Any& rVal )
279 {
280 // these properties are ignored
281 if (rPropName == PROPERTY_TEXT ||
282 rPropName == PROPERTY_STATE)
283 return;
284
285 UnoControl::ImplSetPeerProperty( rPropName, rVal );
286 }
287
288 // XEventListener
289 //---------------------------------------------------------------------
disposing(const EventObject & Source)290 void SAL_CALL OFilterControl::disposing(const EventObject& Source) throw( RuntimeException )
291 {
292 UnoControl::disposing(Source);
293 }
294
295 // XItemListener
296 //---------------------------------------------------------------------
itemStateChanged(const ItemEvent & rEvent)297 void SAL_CALL OFilterControl::itemStateChanged( const ItemEvent& rEvent ) throw(RuntimeException)
298 {
299 ::rtl::OUStringBuffer aText;
300 switch (m_nControlClass)
301 {
302 case FormComponentType::CHECKBOX:
303 {
304 if ( ( rEvent.Selected == STATE_CHECK ) || ( rEvent.Selected == STATE_NOCHECK ) )
305 {
306 sal_Int32 nBooleanComparisonMode = ::dbtools::DatabaseMetaData( m_xConnection ).getBooleanComparisonMode();
307
308 bool bSelected = ( rEvent.Selected == STATE_CHECK );
309
310 ::rtl::OUString sExpressionMarker( RTL_CONSTASCII_USTRINGPARAM( "$expression$" ) );
311 ::dbtools::getBoleanComparisonPredicate(
312 sExpressionMarker,
313 bSelected,
314 nBooleanComparisonMode,
315 aText
316 );
317
318 ::rtl::OUString sText( aText.makeStringAndClear() );
319 sal_Int32 nMarkerPos( sText.indexOf( sExpressionMarker ) );
320 OSL_ENSURE( nMarkerPos == 0, "OFilterControl::itemStateChanged: unsupported boolean comparison mode!" );
321 // If this assertion fails, then getBoleanComparisonPredicate created a predicate which
322 // does not start with the expression we gave it. The only known case is when
323 // the comparison mode is ACCESS_COMPAT, and the value is TRUE. In this case,
324 // the expression is rather complex.
325 // Well, so this is a known issue - the filter controls (and thus the form based filter)
326 // do not work with boolean MS Access fields.
327 // To fix this, we would probably have to revert here to always return "1" or "0" as normalized
328 // filter, and change our client code to properly translate this (which could be some effort).
329 if ( nMarkerPos == 0 )
330 aText.append( sText.copy( sExpressionMarker.getLength() ) );
331 else
332 {
333 // fallback
334 aText.appendAscii( bSelected ? "1" : "0" );
335 }
336 }
337 }
338 break;
339
340 case FormComponentType::LISTBOX:
341 {
342 try
343 {
344 const Reference< XItemList > xItemList( getModel(), UNO_QUERY_THROW );
345 ::rtl::OUString sItemText( xItemList->getItemText( rEvent.Selected ) );
346
347 const MapString2String::const_iterator itemPos = m_aDisplayItemToValueItem.find( sItemText );
348 if ( itemPos != m_aDisplayItemToValueItem.end() )
349 {
350 sItemText = itemPos->second;
351 if ( sItemText.getLength() )
352 {
353 ::dbtools::OPredicateInputController aPredicateInput( maContext.getLegacyServiceFactory(), m_xConnection, getParseContext() );
354 ::rtl::OUString sErrorMessage;
355 OSL_VERIFY( aPredicateInput.normalizePredicateString( sItemText, m_xField, &sErrorMessage ) );
356 }
357 }
358 aText.append( sItemText );
359 }
360 catch( const Exception& )
361 {
362 DBG_UNHANDLED_EXCEPTION();
363 }
364 }
365 break;
366
367 case FormComponentType::RADIOBUTTON:
368 {
369 if ( rEvent.Selected == STATE_CHECK )
370 aText.append( ::comphelper::getString( Reference< XPropertySet >( getModel(), UNO_QUERY )->getPropertyValue( PROPERTY_REFVALUE ) ) );
371 }
372 break;
373 }
374
375 ::rtl::OUString sText( aText.makeStringAndClear() );
376 if ( m_aText.compareTo( sText ) )
377 {
378 m_aText = sText;
379 TextEvent aEvt;
380 aEvt.Source = *this;
381 ::cppu::OInterfaceIteratorHelper aIt( m_aTextListeners );
382 while( aIt.hasMoreElements() )
383 ((XTextListener *)aIt.next())->textChanged( aEvt );
384 }
385 }
386
387 //---------------------------------------------------------------------
implInitFilterList()388 void OFilterControl::implInitFilterList()
389 {
390 if ( !ensureInitialized( ) )
391 // already asserted in ensureInitialized
392 return;
393
394 // ensure the cursor and the statement are disposed as soon as we leave
395 ::utl::SharedUNOComponent< XResultSet > xListCursor;
396 ::utl::SharedUNOComponent< XStatement > xStatement;
397
398 try
399 {
400 m_bFilterListFilled = sal_True;
401
402 if ( !m_xField.is() )
403 return;
404
405 ::rtl::OUString sFieldName;
406 m_xField->getPropertyValue( PROPERTY_NAME ) >>= sFieldName;
407
408 // here we need a table to which the field belongs to
409 const Reference< XChild > xModelAsChild( getModel(), UNO_QUERY_THROW );
410 const Reference< XRowSet > xForm( xModelAsChild->getParent(), UNO_QUERY_THROW );
411 const Reference< XPropertySet > xFormProps( xForm, UNO_QUERY_THROW );
412
413 // create a query composer
414 Reference< XColumnsSupplier > xSuppColumns;
415 xFormProps->getPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("SingleSelectQueryComposer"))) >>= xSuppColumns;
416
417 const Reference< XConnection > xConnection( ::dbtools::getConnection( xForm ), UNO_SET_THROW );
418 const Reference< XNameAccess > xFieldNames( xSuppColumns->getColumns(), UNO_SET_THROW );
419 if ( !xFieldNames->hasByName( sFieldName ) )
420 return;
421 ::rtl::OUString sRealFieldName, sTableName;
422 const Reference< XPropertySet > xComposerFieldProps( xFieldNames->getByName( sFieldName ), UNO_QUERY_THROW );
423 xComposerFieldProps->getPropertyValue( PROPERTY_REALNAME ) >>= sRealFieldName;
424 xComposerFieldProps->getPropertyValue( PROPERTY_TABLENAME ) >>= sTableName;
425
426 // obtain the table of the field
427 const Reference< XTablesSupplier > xSuppTables( xSuppColumns, UNO_QUERY_THROW );
428 const Reference< XNameAccess > xTablesNames( xSuppTables->getTables(), UNO_SET_THROW );
429 const Reference< XNamed > xNamedTable( xTablesNames->getByName( sTableName ), UNO_QUERY_THROW );
430 sTableName = xNamedTable->getName();
431
432 // create a statement selecting all values for the given field
433 ::rtl::OUStringBuffer aStatement;
434
435 const Reference< XDatabaseMetaData > xMeta( xConnection->getMetaData(), UNO_SET_THROW );
436 const ::rtl::OUString sQuoteChar = xMeta->getIdentifierQuoteString();
437
438 aStatement.appendAscii( "SELECT DISTINCT " );
439 aStatement.append( sQuoteChar );
440 aStatement.append( sRealFieldName );
441 aStatement.append( sQuoteChar );
442
443 // if the field had an alias in our form's statement, give it this alias in the new statement, too
444 if ( sFieldName.getLength() && ( sFieldName != sRealFieldName ) )
445 {
446 aStatement.appendAscii(" AS ");
447 aStatement.append( sQuoteChar );
448 aStatement.append( sFieldName );
449 aStatement.append( sQuoteChar );
450 }
451
452 aStatement.appendAscii( " FROM " );
453
454 ::rtl::OUString sCatalog, sSchema, sTable;
455 ::dbtools::qualifiedNameComponents( xMeta, sTableName, sCatalog, sSchema, sTable, ::dbtools::eInDataManipulation );
456 aStatement.append( ::dbtools::composeTableNameForSelect( xConnection, sCatalog, sSchema, sTable ) );
457
458 // execute the statement
459 xStatement.reset( xConnection->createStatement() );
460 const ::rtl::OUString sSelectStatement( aStatement.makeStringAndClear( ) );
461 xListCursor.reset( xStatement->executeQuery( sSelectStatement ) );
462
463 // retrieve the one column which we take the values from
464 const Reference< XColumnsSupplier > xSupplyCols( xListCursor, UNO_QUERY_THROW );
465 const Reference< XIndexAccess > xFields( xSupplyCols->getColumns(), UNO_QUERY_THROW );
466 const Reference< XPropertySet > xDataField( xFields->getByIndex(0), UNO_QUERY_THROW );
467
468 // ensure the values will be formatted according to the field format
469 const ::dbtools::FormattedColumnValue aFormatter( m_xFormatter, xDataField );
470
471 ::std::vector< ::rtl::OUString > aProposals;
472 aProposals.reserve(16);
473
474 while ( xListCursor->next() && ( aProposals.size() < size_t( SHRT_MAX ) ) )
475 {
476 const ::rtl::OUString sCurrentValue = aFormatter.getFormattedValue();
477 aProposals.push_back( sCurrentValue );
478 }
479
480 // fill the list items into our peer
481 Sequence< ::rtl::OUString> aStringSeq( aProposals.size() );
482 ::std::copy( aProposals.begin(), aProposals.end(), aStringSeq.getArray() );
483
484 const Reference< XComboBox > xComboBox( getPeer(), UNO_QUERY_THROW );
485 xComboBox->addItems( aStringSeq, 0 );
486
487 // set the drop down line count to something reasonable
488 const sal_Int16 nLineCount = ::std::min( sal_Int16( 16 ), sal_Int16( aStringSeq.getLength() ) );
489 xComboBox->setDropDownLineCount( nLineCount );
490 }
491 catch( const Exception& )
492 {
493 DBG_UNHANDLED_EXCEPTION();
494 }
495 }
496
497 // XFocusListener
498 //---------------------------------------------------------------------
focusGained(const FocusEvent &)499 void SAL_CALL OFilterControl::focusGained(const FocusEvent& /*e*/) throw( RuntimeException )
500 {
501 // should we fill the combobox?
502 if (m_bFilterList && !m_bFilterListFilled)
503 implInitFilterList();
504 }
505
506 //---------------------------------------------------------------------
focusLost(const FocusEvent &)507 void SAL_CALL OFilterControl::focusLost(const FocusEvent& /*e*/) throw( RuntimeException )
508 {
509 }
510
511 //---------------------------------------------------------------------
commit()512 sal_Bool SAL_CALL OFilterControl::commit() throw(RuntimeException)
513 {
514 if ( !ensureInitialized( ) )
515 // already asserted in ensureInitialized
516 return sal_True;
517
518 ::rtl::OUString aText;
519 switch (m_nControlClass)
520 {
521 case FormComponentType::TEXTFIELD:
522 case FormComponentType::COMBOBOX:
523 {
524 Reference< XTextComponent > xText( getPeer(), UNO_QUERY );
525 if (xText.is())
526 aText = xText->getText();
527 } break;
528 default:
529 return sal_True;
530 }
531 if (m_aText.compareTo(aText))
532 {
533 // check the text with the SQL-Parser
534 ::rtl::OUString aNewText(aText);
535 aNewText.trim();
536 if ( aNewText.getLength() )
537 {
538 ::dbtools::OPredicateInputController aPredicateInput( maContext.getLegacyServiceFactory(), m_xConnection, getParseContext() );
539 ::rtl::OUString sErrorMessage;
540 if ( !aPredicateInput.normalizePredicateString( aNewText, m_xField, &sErrorMessage ) )
541 {
542 // display the error and outta here
543 SQLContext aError;
544 aError.Message = String( FRM_RES_STRING( RID_STR_SYNTAXERROR ) );
545 aError.Details = sErrorMessage;
546 displayException( aError );
547 return sal_False;
548 }
549 }
550
551 setText(aNewText);
552 TextEvent aEvt;
553 aEvt.Source = *this;
554 ::cppu::OInterfaceIteratorHelper aIt( m_aTextListeners );
555 while( aIt.hasMoreElements() )
556 static_cast< XTextListener* >( aIt.next() )->textChanged( aEvt );
557 }
558 return sal_True;
559 }
560
561 // XTextComponent
562 //---------------------------------------------------------------------
addTextListener(const Reference<XTextListener> & l)563 void SAL_CALL OFilterControl::addTextListener(const Reference< XTextListener > & l) throw(RuntimeException)
564 {
565 m_aTextListeners.addInterface( l );
566 }
567
568 //---------------------------------------------------------------------
removeTextListener(const Reference<XTextListener> & l)569 void SAL_CALL OFilterControl::removeTextListener(const Reference< XTextListener > & l) throw(RuntimeException)
570 {
571 m_aTextListeners.removeInterface( l );
572 }
573
574 //---------------------------------------------------------------------
setText(const::rtl::OUString & aText)575 void SAL_CALL OFilterControl::setText( const ::rtl::OUString& aText ) throw(RuntimeException)
576 {
577 if ( !ensureInitialized( ) )
578 // already asserted in ensureInitialized
579 return;
580
581 switch (m_nControlClass)
582 {
583 case FormComponentType::CHECKBOX:
584 {
585 Reference< XVclWindowPeer > xVclWindow( getPeer(), UNO_QUERY );
586 if (xVclWindow.is())
587 {
588 Any aValue;
589 if ( aText.equalsAscii( "1" )
590 || aText.equalsIgnoreAsciiCaseAscii( "TRUE" )
591 || aText.equalsIgnoreAsciiCaseAscii( "IS TRUE" )
592 )
593 {
594 aValue <<= (sal_Int32)STATE_CHECK;
595 }
596 else if ( aText.equalsAscii( "0" )
597 || aText.equalsIgnoreAsciiCaseAscii( "FALSE" )
598 )
599 {
600 aValue <<= (sal_Int32)STATE_NOCHECK;
601 }
602 else
603 aValue <<= (sal_Int32)STATE_DONTKNOW;
604
605 m_aText = aText;
606 xVclWindow->setProperty( PROPERTY_STATE, aValue );
607 }
608 } break;
609 case FormComponentType::RADIOBUTTON:
610 {
611 Reference< XVclWindowPeer > xVclWindow( getPeer(), UNO_QUERY );
612 if (xVclWindow.is())
613 {
614 ::rtl::OUString aRefText = ::comphelper::getString(com::sun::star::uno::Reference< XPropertySet > (getModel(), UNO_QUERY)->getPropertyValue(PROPERTY_REFVALUE));
615 Any aValue;
616 if (aText == aRefText)
617 aValue <<= (sal_Int32)STATE_CHECK;
618 else
619 aValue <<= (sal_Int32)STATE_NOCHECK;
620 m_aText = aText;
621 xVclWindow->setProperty(PROPERTY_STATE, aValue);
622 }
623 } break;
624 case FormComponentType::LISTBOX:
625 {
626 Reference< XListBox > xListBox( getPeer(), UNO_QUERY );
627 if (xListBox.is())
628 {
629 m_aText = aText;
630 MapString2String::const_iterator itemPos = m_aDisplayItemToValueItem.find( m_aText );
631 if ( itemPos == m_aDisplayItemToValueItem.end() )
632 {
633 const bool isQuoted = ( m_aText.getLength() > 1 )
634 && ( m_aText[0] == '\'' )
635 && ( m_aText[ m_aText.getLength() - 1 ] == '\'' );
636 if ( isQuoted )
637 {
638 m_aText = m_aText.copy( 1, m_aText.getLength() - 2 );
639 itemPos = m_aDisplayItemToValueItem.find( m_aText );
640 }
641 }
642
643 OSL_ENSURE( ( itemPos != m_aDisplayItemToValueItem.end() ) || ( m_aText.getLength() == 0 ),
644 "OFilterControl::setText: this text is not in my display list!" );
645 if ( itemPos == m_aDisplayItemToValueItem.end() )
646 m_aText = ::rtl::OUString();
647
648 if ( m_aText.getLength() == 0)
649 {
650 while ( xListBox->getSelectedItemPos() >= 0 )
651 {
652 xListBox->selectItemPos( xListBox->getSelectedItemPos(), sal_False );
653 }
654 }
655 else
656 {
657 xListBox->selectItem( m_aText, sal_True );
658 }
659 }
660 }
661 break;
662
663 default:
664 {
665 Reference< XTextComponent > xText( getPeer(), UNO_QUERY );
666 if (xText.is())
667 {
668 m_aText = aText;
669 xText->setText(aText);
670 }
671 }
672 }
673 }
674
675 //---------------------------------------------------------------------
insertText(const::com::sun::star::awt::Selection & rSel,const::rtl::OUString & aText)676 void SAL_CALL OFilterControl::insertText( const ::com::sun::star::awt::Selection& rSel, const ::rtl::OUString& aText ) throw(::com::sun::star::uno::RuntimeException)
677 {
678 Reference< XTextComponent > xText( getPeer(), UNO_QUERY );
679 if (xText.is())
680 {
681 xText->insertText(rSel, aText);
682 m_aText = xText->getText();
683 }
684 }
685
686 //---------------------------------------------------------------------
getText()687 ::rtl::OUString SAL_CALL OFilterControl::getText() throw(RuntimeException)
688 {
689 return m_aText;
690 }
691
692 //---------------------------------------------------------------------
getSelectedText(void)693 ::rtl::OUString SAL_CALL OFilterControl::getSelectedText( void ) throw(RuntimeException)
694 {
695 ::rtl::OUString aSelected;
696 Reference< XTextComponent > xText( getPeer(), UNO_QUERY );
697 if (xText.is())
698 aSelected = xText->getSelectedText();
699
700 return aSelected;
701 }
702
703 //---------------------------------------------------------------------
setSelection(const::com::sun::star::awt::Selection & aSelection)704 void SAL_CALL OFilterControl::setSelection( const ::com::sun::star::awt::Selection& aSelection ) throw(::com::sun::star::uno::RuntimeException)
705 {
706 Reference< XTextComponent > xText( getPeer(), UNO_QUERY );
707 if (xText.is())
708 xText->setSelection( aSelection );
709 }
710
711 //---------------------------------------------------------------------
getSelection(void)712 ::com::sun::star::awt::Selection SAL_CALL OFilterControl::getSelection( void ) throw(::com::sun::star::uno::RuntimeException)
713 {
714 ::com::sun::star::awt::Selection aSel;
715 Reference< XTextComponent > xText( getPeer(), UNO_QUERY );
716 if (xText.is())
717 aSel = xText->getSelection();
718 return aSel;
719 }
720
721 //---------------------------------------------------------------------
isEditable(void)722 sal_Bool SAL_CALL OFilterControl::isEditable( void ) throw(RuntimeException)
723 {
724 Reference< XTextComponent > xText( getPeer(), UNO_QUERY );
725 return xText.is() && xText->isEditable();
726 }
727
728 //---------------------------------------------------------------------
setEditable(sal_Bool bEditable)729 void SAL_CALL OFilterControl::setEditable( sal_Bool bEditable ) throw(RuntimeException)
730 {
731 Reference< XTextComponent > xText( getPeer(), UNO_QUERY );
732 if (xText.is())
733 xText->setEditable(bEditable);
734 }
735
736 //---------------------------------------------------------------------
getMaxTextLen()737 sal_Int16 SAL_CALL OFilterControl::getMaxTextLen() throw(RuntimeException)
738 {
739 Reference< XTextComponent > xText( getPeer(), UNO_QUERY );
740 return xText.is() ? xText->getMaxTextLen() : 0;
741 }
742
743 //---------------------------------------------------------------------
setMaxTextLen(sal_Int16 nLength)744 void SAL_CALL OFilterControl::setMaxTextLen( sal_Int16 nLength ) throw(RuntimeException)
745 {
746 Reference< XTextComponent > xText( getPeer(), UNO_QUERY );
747 if (xText.is())
748 xText->setMaxTextLen(nLength);
749 }
750
751 //---------------------------------------------------------------------
displayException(const::com::sun::star::sdb::SQLContext & _rExcept)752 void OFilterControl::displayException( const ::com::sun::star::sdb::SQLContext& _rExcept )
753 {
754 try
755 {
756 Sequence< Any > aArgs(2);
757 aArgs[0] <<= PropertyValue(::rtl::OUString::createFromAscii("SQLException"), 0, makeAny( _rExcept ), PropertyState_DIRECT_VALUE);
758 aArgs[1] <<= PropertyValue(::rtl::OUString::createFromAscii("ParentWindow"), 0, makeAny( m_xMessageParent ), PropertyState_DIRECT_VALUE);
759
760 static ::rtl::OUString s_sDialogServiceName = ::rtl::OUString::createFromAscii( "com.sun.star.sdb.ErrorMessageDialog" );
761
762 Reference< XExecutableDialog > xErrorDialog( maContext.createComponentWithArguments( s_sDialogServiceName, aArgs ), UNO_QUERY );
763 if ( xErrorDialog.is() )
764 xErrorDialog->execute();
765 else
766 {
767 Window* pMessageParent = VCLUnoHelper::GetWindow( m_xMessageParent );
768 ShowServiceNotAvailableError( pMessageParent, s_sDialogServiceName, sal_True );
769 }
770 }
771 catch( const Exception& )
772 {
773 DBG_UNHANDLED_EXCEPTION();
774 }
775 }
776
777 //---------------------------------------------------------------------
initialize(const Sequence<Any> & aArguments)778 void SAL_CALL OFilterControl::initialize( const Sequence< Any >& aArguments ) throw (Exception, RuntimeException)
779 {
780 const Any* pArguments = aArguments.getConstArray();
781 const Any* pArgumentsEnd = pArguments + aArguments.getLength();
782
783 PropertyValue aProp;
784 NamedValue aValue;
785 const ::rtl::OUString* pName = NULL;
786 const Any* pValue = NULL;
787
788 for ( ; pArguments != pArgumentsEnd; ++pArguments )
789 {
790 // we recognize PropertyValues and NamedValues
791 if ( *pArguments >>= aProp )
792 {
793 pName = &aProp.Name;
794 pValue = &aProp.Value;
795 }
796 else if ( *pArguments >>= aValue )
797 {
798 pName = &aValue.Name;
799 pValue = &aValue.Value;
800 }
801 else
802 {
803 DBG_ERROR( "OFilterControl::initialize: unrecognized argument!" );
804 continue;
805 }
806
807 if ( 0 == pName->compareToAscii( "MessageParent" ) )
808 {
809 // the message parent
810 *pValue >>= m_xMessageParent;
811 OSL_ENSURE( m_xMessageParent.is(), "OFilterControl::initialize: invalid MessageParent!" );
812 }
813 else if ( 0 == pName->compareToAscii( "NumberFormatter" ) )
814 {
815 // the number format. This argument is optional.
816 *pValue >>= m_xFormatter;
817 OSL_ENSURE( m_xFormatter.is(), "OFilterControl::initialize: invalid NumberFormatter!" );
818 }
819 else if ( 0 == pName->compareToAscii( "ControlModel" ) )
820 {
821 // the control model for which we act as filter control
822 Reference< XPropertySet > xControlModel;
823 if ( !(*pValue >>= xControlModel ) || !xControlModel.is() )
824 {
825 OSL_ENSURE( sal_False, "OFilterControl::initialize: invalid control model argument!" );
826 continue;
827 }
828
829 // some properties which are "derived" from the control model we're working for
830 // ...................................................
831 // the field
832 m_xField.clear();
833 OSL_ENSURE( ::comphelper::hasProperty( PROPERTY_BOUNDFIELD, xControlModel ), "OFilterControl::initialize: control model needs a bound field property!" );
834 xControlModel->getPropertyValue( PROPERTY_BOUNDFIELD ) >>= m_xField;
835
836 // ...................................................
837 // filter list and control class
838 m_bFilterList = ::comphelper::hasProperty( PROPERTY_FILTERPROPOSAL, xControlModel ) && ::comphelper::getBOOL( xControlModel->getPropertyValue( PROPERTY_FILTERPROPOSAL ) );
839 if ( m_bFilterList )
840 m_nControlClass = FormComponentType::COMBOBOX;
841 else
842 {
843 sal_Int16 nClassId = ::comphelper::getINT16( xControlModel->getPropertyValue( PROPERTY_CLASSID ) );
844 switch (nClassId)
845 {
846 case FormComponentType::CHECKBOX:
847 case FormComponentType::RADIOBUTTON:
848 case FormComponentType::LISTBOX:
849 case FormComponentType::COMBOBOX:
850 m_nControlClass = nClassId;
851 if ( FormComponentType::LISTBOX == nClassId )
852 {
853 Sequence< ::rtl::OUString > aDisplayItems;
854 OSL_VERIFY( xControlModel->getPropertyValue( PROPERTY_STRINGITEMLIST ) >>= aDisplayItems );
855 Sequence< ::rtl::OUString > aValueItems;
856 OSL_VERIFY( xControlModel->getPropertyValue( PROPERTY_VALUE_SEQ ) >>= aValueItems );
857 OSL_ENSURE( aDisplayItems.getLength() == aValueItems.getLength(), "OFilterControl::initialize: inconsistent item lists!" );
858 for ( sal_Int32 i=0; i < ::std::min( aDisplayItems.getLength(), aValueItems.getLength() ); ++i )
859 m_aDisplayItemToValueItem[ aDisplayItems[i] ] = aValueItems[i];
860 }
861 break;
862 default:
863 m_bMultiLine = ::comphelper::hasProperty( PROPERTY_MULTILINE, xControlModel ) && ::comphelper::getBOOL( xControlModel->getPropertyValue( PROPERTY_MULTILINE ) );
864 m_nControlClass = FormComponentType::TEXTFIELD;
865 break;
866 }
867 }
868
869 // ...................................................
870 // the connection meta data for the form which we're working for
871 Reference< XChild > xModel( xControlModel, UNO_QUERY );
872 Reference< XRowSet > xForm;
873 if ( xModel.is() )
874 xForm = xForm.query( xModel->getParent() );
875 m_xConnection = ::dbtools::getConnection( xForm );
876 OSL_ENSURE( m_xConnection.is(), "OFilterControl::initialize: unable to determine the form's connection!" );
877 }
878 }
879 }
880
881 //---------------------------------------------------------------------
getImplementationName()882 ::rtl::OUString SAL_CALL OFilterControl::getImplementationName( ) throw (RuntimeException)
883 {
884 return getImplementationName_Static();
885 }
886
887 //---------------------------------------------------------------------
supportsService(const::rtl::OUString & ServiceName)888 sal_Bool SAL_CALL OFilterControl::supportsService( const ::rtl::OUString& ServiceName ) throw (RuntimeException)
889 {
890 Sequence< ::rtl::OUString > aSupported( getSupportedServiceNames() );
891 const ::rtl::OUString* pArray = aSupported.getConstArray();
892 for( sal_Int32 i = 0; i < aSupported.getLength(); ++i, ++pArray )
893 if( pArray->equals( ServiceName ) )
894 return sal_True;
895 return sal_False;
896 }
897
898 //---------------------------------------------------------------------
getSupportedServiceNames()899 Sequence< ::rtl::OUString > SAL_CALL OFilterControl::getSupportedServiceNames( ) throw (RuntimeException)
900 {
901 return getSupportedServiceNames_Static();
902 }
903
904 //---------------------------------------------------------------------
getImplementationName_Static()905 ::rtl::OUString SAL_CALL OFilterControl::getImplementationName_Static()
906 {
907 return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.forms.OFilterControl" ) );
908 }
909
910 //---------------------------------------------------------------------
getSupportedServiceNames_Static()911 Sequence< ::rtl::OUString > SAL_CALL OFilterControl::getSupportedServiceNames_Static()
912 {
913 Sequence< ::rtl::OUString > aNames( 2 );
914 aNames[ 0 ] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.form.control.FilterControl" ) );
915 aNames[ 1 ] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.awt.UnoControl" ) );
916 return aNames;
917 }
918
919 //---------------------------------------------------------------------
Create(const Reference<XMultiServiceFactory> & _rxFactory)920 Reference< XInterface > SAL_CALL OFilterControl::Create( const Reference< XMultiServiceFactory >& _rxFactory )
921 {
922 return static_cast< XServiceInfo* >( new OFilterControl( _rxFactory ) );
923 }
924
925 //.........................................................................
926 } // namespace frm
927 //.........................................................................
928