bump product version to 5.0.4.1
[LibreOffice.git] / forms / source / component / Filter.cxx
blobd3246b9062dbd3dcacf71dcd4403fedfed0ef96c
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "Filter.hxx"
21 #include "FormComponent.hxx"
22 #include "frm_resource.hrc"
23 #include "frm_resource.hxx"
24 #include "property.hrc"
25 #include "property.hxx"
26 #include "services.hxx"
28 #include <com/sun/star/awt/VclWindowPeerAttribute.hpp>
29 #include <com/sun/star/awt/XCheckBox.hpp>
30 #include <com/sun/star/awt/XComboBox.hpp>
31 #include <com/sun/star/awt/XListBox.hpp>
32 #include <com/sun/star/awt/XRadioButton.hpp>
33 #include <com/sun/star/awt/XVclWindowPeer.hpp>
34 #include <com/sun/star/beans/NamedValue.hpp>
35 #include <com/sun/star/container/XChild.hpp>
36 #include <com/sun/star/container/XIndexAccess.hpp>
37 #include <com/sun/star/container/XNamed.hpp>
38 #include <com/sun/star/form/FormComponentType.hpp>
39 #include <com/sun/star/sdb/BooleanComparisonMode.hpp>
40 #include <com/sun/star/sdb/ErrorMessageDialog.hpp>
41 #include <com/sun/star/sdb/XColumn.hpp>
42 #include <com/sun/star/sdb/XSQLQueryComposerFactory.hpp>
43 #include <com/sun/star/sdbc/DataType.hpp>
44 #include <com/sun/star/sdbc/XRowSet.hpp>
45 #include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
46 #include <com/sun/star/sdbcx/XTablesSupplier.hpp>
47 #include <com/sun/star/ui/dialogs/XExecutableDialog.hpp>
48 #include <com/sun/star/util/NumberFormatter.hpp>
49 #include <com/sun/star/awt/XItemList.hpp>
51 #include <comphelper/numbers.hxx>
52 #include <comphelper/processfactory.hxx>
53 #include <comphelper/property.hxx>
54 #include <cppuhelper/supportsservice.hxx>
55 #include <connectivity/dbconversion.hxx>
56 #include <connectivity/dbtools.hxx>
57 #include <connectivity/formattedcolumnvalue.hxx>
58 #include <connectivity/predicateinput.hxx>
59 #include <rtl/ustrbuf.hxx>
60 #include <toolkit/helper/vclunohelper.hxx>
61 #include <tools/diagnose_ex.h>
62 #include <unotools/localedatawrapper.hxx>
63 #include <vcl/stdtext.hxx>
64 #include <vcl/svapp.hxx>
65 #include <tools/wintypes.hxx>
68 namespace frm
70 using namespace ::com::sun::star::uno;
71 using namespace ::com::sun::star::awt;
72 using namespace ::com::sun::star::lang;
73 using namespace ::com::sun::star::beans;
74 using namespace ::com::sun::star::sdb;
75 using namespace ::com::sun::star::sdbc;
76 using namespace ::com::sun::star::sdbcx;
77 using namespace ::com::sun::star::util;
78 using namespace ::com::sun::star::form;
79 using namespace ::com::sun::star::container;
80 using namespace ::com::sun::star::ui::dialogs;
82 using namespace ::connectivity;
84 OFilterControl::OFilterControl( const Reference< XComponentContext >& _rxORB )
85 :UnoControl()
86 ,m_aTextListeners( *this )
87 ,m_xContext( _rxORB )
88 #if HAVE_FEATURE_DBCONNECTIVITY
89 ,m_aParser( _rxORB )
90 #endif
91 ,m_nControlClass( FormComponentType::TEXTFIELD )
92 ,m_bFilterList( false )
93 ,m_bMultiLine( false )
94 ,m_bFilterListFilled( false )
99 bool OFilterControl::ensureInitialized( )
101 #if HAVE_FEATURE_DBCONNECTIVITY
102 if ( !m_xField.is() )
104 OSL_FAIL( "OFilterControl::ensureInitialized: improperly initialized: no field!" );
105 return false;
108 if ( !m_xConnection.is() )
110 OSL_FAIL( "OFilterControl::ensureInitialized: improperly initialized: no connection!" );
111 return false;
114 if ( !m_xFormatter.is() )
116 // we can create one from the connection, if it's an SDB connection
118 Reference< XNumberFormatsSupplier > xFormatSupplier = ::dbtools::getNumberFormats( m_xConnection, true, m_xContext );
120 if ( xFormatSupplier.is() )
122 m_xFormatter.set(NumberFormatter::create(m_xContext), UNO_QUERY_THROW );
123 m_xFormatter->attachNumberFormatsSupplier( xFormatSupplier );
126 if ( !m_xFormatter.is() )
128 OSL_FAIL( "OFilterControl::ensureInitialized: no number formatter!" );
129 // no fallback anymore
130 return false;
132 #endif
133 return true;
137 Any SAL_CALL OFilterControl::queryAggregation( const Type & rType ) throw(RuntimeException, std::exception)
139 Any aRet = UnoControl::queryAggregation( rType);
140 if(!aRet.hasValue())
141 aRet = OFilterControl_BASE::queryInterface(rType);
143 return aRet;
147 OUString OFilterControl::GetComponentServiceName()
149 OUString aServiceName;
150 switch (m_nControlClass)
152 case FormComponentType::RADIOBUTTON:
153 aServiceName = "radiobutton";
154 break;
155 case FormComponentType::CHECKBOX:
156 aServiceName = "checkbox";
157 break;
158 case FormComponentType::COMBOBOX:
159 aServiceName = "combobox";
160 break;
161 case FormComponentType::LISTBOX:
162 aServiceName = "listbox";
163 break;
164 default:
165 if (m_bMultiLine)
166 aServiceName = "MultiLineEdit";
167 else
168 aServiceName = "Edit";
170 return aServiceName;
173 // XComponent
175 void OFilterControl::dispose() throw( RuntimeException, std::exception )
177 EventObject aEvt(*this);
178 m_aTextListeners.disposeAndClear( aEvt );
179 UnoControl::dispose();
183 void OFilterControl::createPeer( const Reference< XToolkit > & rxToolkit, const Reference< XWindowPeer > & rParentPeer ) throw(RuntimeException, std::exception)
185 UnoControl::createPeer( rxToolkit, rParentPeer );
189 Reference< XVclWindowPeer > xVclWindow( getPeer(), UNO_QUERY_THROW );
190 switch ( m_nControlClass )
192 case FormComponentType::CHECKBOX:
194 // checkboxes always have a tristate-mode
195 xVclWindow->setProperty( PROPERTY_TRISTATE, makeAny( true ) );
196 xVclWindow->setProperty( PROPERTY_STATE, makeAny( sal_Int32( TRISTATE_INDET ) ) );
198 Reference< XCheckBox > xBox( getPeer(), UNO_QUERY_THROW );
199 xBox->addItemListener( this );
202 break;
204 case FormComponentType::RADIOBUTTON:
206 xVclWindow->setProperty( PROPERTY_STATE, makeAny( sal_Int32( TRISTATE_FALSE ) ) );
208 Reference< XRadioButton > xRadio( getPeer(), UNO_QUERY_THROW );
209 xRadio->addItemListener( this );
211 break;
213 case FormComponentType::LISTBOX:
215 Reference< XListBox > xListBox( getPeer(), UNO_QUERY_THROW );
216 xListBox->addItemListener( this );
218 // no break
220 case FormComponentType::COMBOBOX:
222 xVclWindow->setProperty(PROPERTY_AUTOCOMPLETE, makeAny( true ) );
224 // no break
226 default:
228 Reference< XWindow > xWindow( getPeer(), UNO_QUERY );
229 xWindow->addFocusListener( this );
231 Reference< XTextComponent > xText( getPeer(), UNO_QUERY );
232 if (xText.is())
233 xText->setMaxTextLen(0);
235 break;
238 // filter controls are _never_ readonly
239 Reference< XPropertySet > xModel( getModel(), UNO_QUERY_THROW );
240 Reference< XPropertySetInfo > xModelPSI( xModel->getPropertySetInfo(), UNO_SET_THROW );
241 if ( xModelPSI->hasPropertyByName( PROPERTY_READONLY ) )
242 xVclWindow->setProperty( PROPERTY_READONLY, makeAny( false ) );
244 catch( const Exception& )
246 DBG_UNHANDLED_EXCEPTION();
249 if (m_bFilterList)
250 m_bFilterListFilled = false;
254 void OFilterControl::PrepareWindowDescriptor( WindowDescriptor& rDescr )
256 if (m_bFilterList)
257 rDescr.WindowAttributes |= VclWindowPeerAttribute::DROPDOWN;
261 void OFilterControl::ImplSetPeerProperty( const OUString& rPropName, const Any& rVal )
263 // these properties are ignored
264 if (rPropName == PROPERTY_TEXT ||
265 rPropName == PROPERTY_STATE)
266 return;
268 UnoControl::ImplSetPeerProperty( rPropName, rVal );
271 // XEventListener
273 void SAL_CALL OFilterControl::disposing(const EventObject& Source) throw( RuntimeException, std::exception )
275 UnoControl::disposing(Source);
278 // XItemListener
280 void SAL_CALL OFilterControl::itemStateChanged( const ItemEvent& rEvent ) throw(RuntimeException, std::exception)
282 #if !HAVE_FEATURE_DBCONNECTIVITY
283 (void) rEvent;
284 #else
285 OUStringBuffer aText;
286 switch (m_nControlClass)
288 case FormComponentType::CHECKBOX:
290 if ( ( rEvent.Selected == TRISTATE_TRUE ) || ( rEvent.Selected == TRISTATE_FALSE ) )
292 sal_Int32 nBooleanComparisonMode = ::dbtools::DatabaseMetaData( m_xConnection ).getBooleanComparisonMode();
294 bool bSelected = ( rEvent.Selected == TRISTATE_TRUE );
296 OUString sExpressionMarker( "$expression$" );
297 ::dbtools::getBooleanComparisonPredicate(
298 sExpressionMarker,
299 bSelected,
300 nBooleanComparisonMode,
301 aText
304 OUString sText( aText.makeStringAndClear() );
305 sal_Int32 nMarkerPos( sText.indexOf( sExpressionMarker ) );
306 OSL_ENSURE( nMarkerPos == 0, "OFilterControl::itemStateChanged: unsupported boolean comparison mode!" );
307 // If this assertion fails, then getBoleanComparisonPredicate created a predicate which
308 // does not start with the expression we gave it. The only known case is when
309 // the comparison mode is ACCESS_COMPAT, and the value is TRUE. In this case,
310 // the expression is rather complex.
311 // Well, so this is a known issue - the filter controls (and thus the form based filter)
312 // do not work with boolean MS Access fields.
313 // To fix this, we would probably have to revert here to always return "1" or "0" as normalized
314 // filter, and change our client code to properly translate this (which could be some effort).
315 if ( nMarkerPos == 0 )
316 aText.append( sText.copy( sExpressionMarker.getLength() ) );
317 else
319 // fallback
320 aText.appendAscii( bSelected ? "1" : "0" );
324 break;
326 case FormComponentType::LISTBOX:
330 const Reference< XItemList > xItemList( getModel(), UNO_QUERY_THROW );
331 OUString sItemText( xItemList->getItemText( rEvent.Selected ) );
333 const MapString2String::const_iterator itemPos = m_aDisplayItemToValueItem.find( sItemText );
334 if ( itemPos != m_aDisplayItemToValueItem.end() )
336 sItemText = itemPos->second;
337 if ( !sItemText.isEmpty() )
339 ::dbtools::OPredicateInputController aPredicateInput( m_xContext, m_xConnection, getParseContext() );
340 OUString sErrorMessage;
341 OSL_VERIFY( aPredicateInput.normalizePredicateString( sItemText, m_xField, &sErrorMessage ) );
344 aText.append( sItemText );
346 catch( const Exception& )
348 DBG_UNHANDLED_EXCEPTION();
351 break;
353 case FormComponentType::RADIOBUTTON:
355 if ( rEvent.Selected == TRISTATE_TRUE )
356 aText.append( ::comphelper::getString( Reference< XPropertySet >( getModel(), UNO_QUERY )->getPropertyValue( PROPERTY_REFVALUE ) ) );
358 break;
361 OUString sText( aText.makeStringAndClear() );
362 if ( m_aText.compareTo( sText ) )
364 m_aText = sText;
365 TextEvent aEvt;
366 aEvt.Source = *this;
367 ::cppu::OInterfaceIteratorHelper aIt( m_aTextListeners );
368 while( aIt.hasMoreElements() )
369 static_cast<XTextListener *>(aIt.next())->textChanged( aEvt );
371 #endif
375 void OFilterControl::implInitFilterList()
377 #if HAVE_FEATURE_DBCONNECTIVITY
378 if ( !ensureInitialized( ) )
379 // already asserted in ensureInitialized
380 return;
382 // ensure the cursor and the statement are disposed as soon as we leave
383 ::utl::SharedUNOComponent< XResultSet > xListCursor;
384 ::utl::SharedUNOComponent< XStatement > xStatement;
388 m_bFilterListFilled = true;
390 if ( !m_xField.is() )
391 return;
393 OUString sFieldName;
394 m_xField->getPropertyValue( PROPERTY_NAME ) >>= sFieldName;
396 // here we need a table to which the field belongs to
397 const Reference< XChild > xModelAsChild( getModel(), UNO_QUERY_THROW );
398 const Reference< XRowSet > xForm( xModelAsChild->getParent(), UNO_QUERY_THROW );
399 const Reference< XPropertySet > xFormProps( xForm, UNO_QUERY_THROW );
401 // create a query composer
402 Reference< XColumnsSupplier > xSuppColumns;
403 xFormProps->getPropertyValue("SingleSelectQueryComposer") >>= xSuppColumns;
405 const Reference< XConnection > xConnection( ::dbtools::getConnection( xForm ), UNO_SET_THROW );
406 const Reference< XNameAccess > xFieldNames( xSuppColumns->getColumns(), UNO_SET_THROW );
407 if ( !xFieldNames->hasByName( sFieldName ) )
408 return;
409 OUString sRealFieldName, sTableName;
410 const Reference< XPropertySet > xComposerFieldProps( xFieldNames->getByName( sFieldName ), UNO_QUERY_THROW );
411 xComposerFieldProps->getPropertyValue( PROPERTY_REALNAME ) >>= sRealFieldName;
412 xComposerFieldProps->getPropertyValue( PROPERTY_TABLENAME ) >>= sTableName;
414 // obtain the table of the field
415 const Reference< XTablesSupplier > xSuppTables( xSuppColumns, UNO_QUERY_THROW );
416 const Reference< XNameAccess > xTablesNames( xSuppTables->getTables(), UNO_SET_THROW );
417 const Reference< XNamed > xNamedTable( xTablesNames->getByName( sTableName ), UNO_QUERY_THROW );
418 sTableName = xNamedTable->getName();
420 // create a statement selecting all values for the given field
421 OUStringBuffer aStatement;
423 const Reference< XDatabaseMetaData > xMeta( xConnection->getMetaData(), UNO_SET_THROW );
424 const OUString sQuoteChar = xMeta->getIdentifierQuoteString();
426 aStatement.appendAscii( "SELECT DISTINCT " );
427 aStatement.append( sQuoteChar );
428 aStatement.append( sRealFieldName );
429 aStatement.append( sQuoteChar );
431 // if the field had an alias in our form's statement, give it this alias in the new statement, too
432 if ( !sFieldName.isEmpty() && ( sFieldName != sRealFieldName ) )
434 aStatement.appendAscii(" AS ");
435 aStatement.append( sQuoteChar );
436 aStatement.append( sFieldName );
437 aStatement.append( sQuoteChar );
440 aStatement.appendAscii( " FROM " );
442 OUString sCatalog, sSchema, sTable;
443 ::dbtools::qualifiedNameComponents( xMeta, sTableName, sCatalog, sSchema, sTable, ::dbtools::eInDataManipulation );
444 aStatement.append( ::dbtools::composeTableNameForSelect( xConnection, sCatalog, sSchema, sTable ) );
446 // execute the statement
447 xStatement.reset( xConnection->createStatement() );
448 const OUString sSelectStatement( aStatement.makeStringAndClear( ) );
449 xListCursor.reset( xStatement->executeQuery( sSelectStatement ) );
451 // retrieve the one column which we take the values from
452 const Reference< XColumnsSupplier > xSupplyCols( xListCursor, UNO_QUERY_THROW );
453 const Reference< XIndexAccess > xFields( xSupplyCols->getColumns(), UNO_QUERY_THROW );
454 const Reference< XPropertySet > xDataField( xFields->getByIndex(0), UNO_QUERY_THROW );
456 // ensure the values will be formatted according to the field format
457 const ::dbtools::FormattedColumnValue aFormatter( m_xFormatter, xDataField );
459 ::std::vector< OUString > aProposals;
460 aProposals.reserve(16);
462 while ( xListCursor->next() && ( aProposals.size() < size_t( SHRT_MAX ) ) )
464 const OUString sCurrentValue = aFormatter.getFormattedValue();
465 aProposals.push_back( sCurrentValue );
468 // fill the list items into our peer
469 Sequence< OUString> aStringSeq( aProposals.size() );
470 ::std::copy( aProposals.begin(), aProposals.end(), aStringSeq.getArray() );
472 const Reference< XComboBox > xComboBox( getPeer(), UNO_QUERY_THROW );
473 xComboBox->addItems( aStringSeq, 0 );
475 // set the drop down line count to something reasonable
476 const sal_Int16 nLineCount = ::std::min( sal_Int16( 16 ), sal_Int16( aStringSeq.getLength() ) );
477 xComboBox->setDropDownLineCount( nLineCount );
479 catch( const Exception& )
481 DBG_UNHANDLED_EXCEPTION();
483 #endif
486 // XFocusListener
488 void SAL_CALL OFilterControl::focusGained(const FocusEvent& /*e*/) throw( RuntimeException, std::exception )
490 // should we fill the combobox?
491 if (m_bFilterList && !m_bFilterListFilled)
492 implInitFilterList();
496 void SAL_CALL OFilterControl::focusLost(const FocusEvent& /*e*/) throw( RuntimeException, std::exception )
501 sal_Bool SAL_CALL OFilterControl::commit() throw(RuntimeException, std::exception)
503 #if HAVE_FEATURE_DBCONNECTIVITY
504 if ( !ensureInitialized( ) )
505 // already asserted in ensureInitialized
506 return sal_True;
508 OUString aText;
509 switch (m_nControlClass)
511 case FormComponentType::TEXTFIELD:
512 case FormComponentType::COMBOBOX:
514 Reference< XTextComponent > xText( getPeer(), UNO_QUERY );
515 if (xText.is())
516 aText = xText->getText();
517 } break;
518 default:
519 return sal_True;
521 if (m_aText.compareTo(aText))
523 // check the text with the SQL-Parser
524 OUString aNewText(aText);
525 aNewText = aNewText.trim();
526 if ( !aNewText.isEmpty() )
528 ::dbtools::OPredicateInputController aPredicateInput( m_xContext, m_xConnection, getParseContext() );
529 OUString sErrorMessage;
530 if ( !aPredicateInput.normalizePredicateString( aNewText, m_xField, &sErrorMessage ) )
532 // display the error and outta here
533 SQLContext aError;
534 aError.Message = FRM_RES_STRING( RID_STR_SYNTAXERROR );
535 aError.Details = sErrorMessage;
536 displayException( aError );
537 return sal_False;
541 setText(aNewText);
542 TextEvent aEvt;
543 aEvt.Source = *this;
544 ::cppu::OInterfaceIteratorHelper aIt( m_aTextListeners );
545 while( aIt.hasMoreElements() )
546 static_cast< XTextListener* >( aIt.next() )->textChanged( aEvt );
548 #endif
549 return sal_True;
552 // XTextComponent
554 void SAL_CALL OFilterControl::addTextListener(const Reference< XTextListener > & l) throw(RuntimeException, std::exception)
556 m_aTextListeners.addInterface( l );
560 void SAL_CALL OFilterControl::removeTextListener(const Reference< XTextListener > & l) throw(RuntimeException, std::exception)
562 m_aTextListeners.removeInterface( l );
566 void SAL_CALL OFilterControl::setText( const OUString& aText ) throw(RuntimeException, std::exception)
568 if ( !ensureInitialized( ) )
569 // already asserted in ensureInitialized
570 return;
572 switch (m_nControlClass)
574 case FormComponentType::CHECKBOX:
576 Reference< XVclWindowPeer > xVclWindow( getPeer(), UNO_QUERY );
577 if (xVclWindow.is())
579 Any aValue;
580 if ( aText == "1"
581 || aText.equalsIgnoreAsciiCase("TRUE")
582 || aText.equalsIgnoreAsciiCase("IS TRUE")
585 aValue <<= (sal_Int32)TRISTATE_TRUE;
587 else if ( aText == "0" || aText.equalsIgnoreAsciiCase("FALSE") )
589 aValue <<= (sal_Int32)TRISTATE_FALSE;
591 else
592 aValue <<= (sal_Int32)TRISTATE_INDET;
594 m_aText = aText;
595 xVclWindow->setProperty( PROPERTY_STATE, aValue );
597 } break;
598 case FormComponentType::RADIOBUTTON:
600 Reference< XVclWindowPeer > xVclWindow( getPeer(), UNO_QUERY );
601 if (xVclWindow.is())
603 OUString aRefText = ::comphelper::getString(com::sun::star::uno::Reference< XPropertySet > (getModel(), UNO_QUERY)->getPropertyValue(PROPERTY_REFVALUE));
604 Any aValue;
605 if (aText == aRefText)
606 aValue <<= (sal_Int32)TRISTATE_TRUE;
607 else
608 aValue <<= (sal_Int32)TRISTATE_FALSE;
609 m_aText = aText;
610 xVclWindow->setProperty(PROPERTY_STATE, aValue);
612 } break;
613 case FormComponentType::LISTBOX:
615 Reference< XListBox > xListBox( getPeer(), UNO_QUERY );
616 if (xListBox.is())
618 m_aText = aText;
619 MapString2String::const_iterator itemPos = m_aDisplayItemToValueItem.find( m_aText );
620 if ( itemPos == m_aDisplayItemToValueItem.end() )
622 const bool isQuoted = ( m_aText.getLength() > 1 )
623 && ( m_aText[0] == '\'' )
624 && ( m_aText[ m_aText.getLength() - 1 ] == '\'' );
625 if ( isQuoted )
627 m_aText = m_aText.copy( 1, m_aText.getLength() - 2 );
628 itemPos = m_aDisplayItemToValueItem.find( m_aText );
632 OSL_ENSURE( ( itemPos != m_aDisplayItemToValueItem.end() ) || m_aText.isEmpty(),
633 "OFilterControl::setText: this text is not in my display list!" );
634 if ( itemPos == m_aDisplayItemToValueItem.end() )
635 m_aText.clear();
637 if ( m_aText.isEmpty() )
639 while ( xListBox->getSelectedItemPos() >= 0 )
641 xListBox->selectItemPos( xListBox->getSelectedItemPos(), sal_False );
644 else
646 xListBox->selectItem( m_aText, sal_True );
650 break;
652 default:
654 Reference< XTextComponent > xText( getPeer(), UNO_QUERY );
655 if (xText.is())
657 m_aText = aText;
658 xText->setText(aText);
665 void SAL_CALL OFilterControl::insertText( const ::com::sun::star::awt::Selection& rSel, const OUString& aText ) throw(::com::sun::star::uno::RuntimeException, std::exception)
667 Reference< XTextComponent > xText( getPeer(), UNO_QUERY );
668 if (xText.is())
670 xText->insertText(rSel, aText);
671 m_aText = xText->getText();
676 OUString SAL_CALL OFilterControl::getText() throw(RuntimeException, std::exception)
678 return m_aText;
682 OUString SAL_CALL OFilterControl::getSelectedText() throw(RuntimeException, std::exception)
684 OUString aSelected;
685 Reference< XTextComponent > xText( getPeer(), UNO_QUERY );
686 if (xText.is())
687 aSelected = xText->getSelectedText();
689 return aSelected;
693 void SAL_CALL OFilterControl::setSelection( const ::com::sun::star::awt::Selection& aSelection ) throw(::com::sun::star::uno::RuntimeException, std::exception)
695 Reference< XTextComponent > xText( getPeer(), UNO_QUERY );
696 if (xText.is())
697 xText->setSelection( aSelection );
701 ::com::sun::star::awt::Selection SAL_CALL OFilterControl::getSelection() throw(::com::sun::star::uno::RuntimeException, std::exception)
703 ::com::sun::star::awt::Selection aSel;
704 Reference< XTextComponent > xText( getPeer(), UNO_QUERY );
705 if (xText.is())
706 aSel = xText->getSelection();
707 return aSel;
711 sal_Bool SAL_CALL OFilterControl::isEditable() throw(RuntimeException, std::exception)
713 Reference< XTextComponent > xText( getPeer(), UNO_QUERY );
714 return xText.is() && xText->isEditable();
718 void SAL_CALL OFilterControl::setEditable( sal_Bool bEditable ) throw(RuntimeException, std::exception)
720 Reference< XTextComponent > xText( getPeer(), UNO_QUERY );
721 if (xText.is())
722 xText->setEditable(bEditable);
726 sal_Int16 SAL_CALL OFilterControl::getMaxTextLen() throw(RuntimeException, std::exception)
728 Reference< XTextComponent > xText( getPeer(), UNO_QUERY );
729 return xText.is() ? xText->getMaxTextLen() : 0;
733 void SAL_CALL OFilterControl::setMaxTextLen( sal_Int16 nLength ) throw(RuntimeException, std::exception)
735 Reference< XTextComponent > xText( getPeer(), UNO_QUERY );
736 if (xText.is())
737 xText->setMaxTextLen(nLength);
741 void OFilterControl::displayException( const ::com::sun::star::sdb::SQLContext& _rExcept )
745 Reference< XExecutableDialog > xErrorDialog = ErrorMessageDialog::create( m_xContext, "", m_xMessageParent, makeAny(_rExcept));
746 xErrorDialog->execute();
748 catch( const Exception& )
750 DBG_UNHANDLED_EXCEPTION();
755 void SAL_CALL OFilterControl::initialize( const Sequence< Any >& aArguments ) throw (Exception, RuntimeException, std::exception)
757 const Any* pArguments = aArguments.getConstArray();
758 const Any* pArgumentsEnd = pArguments + aArguments.getLength();
760 PropertyValue aProp;
761 NamedValue aValue;
762 const OUString* pName = NULL;
763 const Any* pValue = NULL;
764 Reference< XPropertySet > xControlModel;
766 if (aArguments.getLength() == 3
767 && (aArguments[0] >>= m_xMessageParent)
768 && (aArguments[1] >>= m_xFormatter)
769 && (aArguments[2] >>= xControlModel))
771 initControlModel(xControlModel);
773 else for ( ; pArguments != pArgumentsEnd; ++pArguments )
775 // we recognize PropertyValues and NamedValues
776 if ( *pArguments >>= aProp )
778 pName = &aProp.Name;
779 pValue = &aProp.Value;
781 else if ( *pArguments >>= aValue )
783 pName = &aValue.Name;
784 pValue = &aValue.Value;
786 else
788 OSL_FAIL( "OFilterControl::initialize: unrecognized argument!" );
789 continue;
792 if ( *pName == "MessageParent" )
794 // the message parent
795 *pValue >>= m_xMessageParent;
796 OSL_ENSURE( m_xMessageParent.is(), "OFilterControl::initialize: invalid MessageParent!" );
798 else if ( *pName == "NumberFormatter" )
800 // the number format. This argument is optional.
801 *pValue >>= m_xFormatter;
802 OSL_ENSURE( m_xFormatter.is(), "OFilterControl::initialize: invalid NumberFormatter!" );
804 else if ( *pName == "ControlModel" )
806 // the control model for which we act as filter control
807 if ( !(*pValue >>= xControlModel ) )
809 OSL_FAIL( "OFilterControl::initialize: invalid control model argument!" );
810 continue;
812 initControlModel(xControlModel);
817 void OFilterControl::initControlModel(Reference< XPropertySet >& xControlModel)
819 #if !HAVE_FEATURE_DBCONNECTIVITY
820 (void) xControlModel;
821 #else
822 if ( !xControlModel.is() )
824 OSL_FAIL( "OFilterControl::initialize: invalid control model argument!" );
825 return;
827 // some properties which are "derived" from the control model we're working for
829 // the field
830 m_xField.clear();
831 OSL_ENSURE( ::comphelper::hasProperty( PROPERTY_BOUNDFIELD, xControlModel ), "OFilterControl::initialize: control model needs a bound field property!" );
832 xControlModel->getPropertyValue( PROPERTY_BOUNDFIELD ) >>= m_xField;
835 // filter list and control class
836 m_bFilterList = ::comphelper::hasProperty( PROPERTY_FILTERPROPOSAL, xControlModel ) && ::comphelper::getBOOL( xControlModel->getPropertyValue( PROPERTY_FILTERPROPOSAL ) );
837 if ( m_bFilterList )
838 m_nControlClass = FormComponentType::COMBOBOX;
839 else
841 sal_Int16 nClassId = ::comphelper::getINT16( xControlModel->getPropertyValue( PROPERTY_CLASSID ) );
842 switch (nClassId)
844 case FormComponentType::CHECKBOX:
845 case FormComponentType::RADIOBUTTON:
846 case FormComponentType::LISTBOX:
847 case FormComponentType::COMBOBOX:
848 m_nControlClass = nClassId;
849 if ( FormComponentType::LISTBOX == nClassId )
851 Sequence< OUString > aDisplayItems;
852 OSL_VERIFY( xControlModel->getPropertyValue( PROPERTY_STRINGITEMLIST ) >>= aDisplayItems );
853 Sequence< OUString > aValueItems;
854 OSL_VERIFY( xControlModel->getPropertyValue( PROPERTY_VALUE_SEQ ) >>= aValueItems );
855 OSL_ENSURE( aDisplayItems.getLength() == aValueItems.getLength(), "OFilterControl::initialize: inconsistent item lists!" );
856 for ( sal_Int32 i=0; i < ::std::min( aDisplayItems.getLength(), aValueItems.getLength() ); ++i )
857 m_aDisplayItemToValueItem[ aDisplayItems[i] ] = aValueItems[i];
859 break;
860 default:
861 m_bMultiLine = ::comphelper::hasProperty( PROPERTY_MULTILINE, xControlModel ) && ::comphelper::getBOOL( xControlModel->getPropertyValue( PROPERTY_MULTILINE ) );
862 m_nControlClass = FormComponentType::TEXTFIELD;
863 break;
868 // the connection meta data for the form which we're working for
869 Reference< XChild > xModel( xControlModel, UNO_QUERY );
870 Reference< XRowSet > xForm;
871 if ( xModel.is() )
872 xForm.set(xModel->getParent(), css::uno::UNO_QUERY);
873 m_xConnection = ::dbtools::getConnection( xForm );
874 OSL_ENSURE( m_xConnection.is(), "OFilterControl::initialize: unable to determine the form's connection!" );
875 #endif
878 OUString SAL_CALL OFilterControl::getImplementationName( ) throw (RuntimeException, std::exception)
880 return getImplementationName_Static();
883 sal_Bool SAL_CALL OFilterControl::supportsService( const OUString& ServiceName ) throw (RuntimeException, std::exception)
885 return cppu::supportsService(this, ServiceName);
888 Sequence< OUString > SAL_CALL OFilterControl::getSupportedServiceNames( ) throw (RuntimeException, std::exception)
890 return getSupportedServiceNames_Static();
893 OUString SAL_CALL OFilterControl::getImplementationName_Static()
895 return OUString( "com.sun.star.comp.forms.OFilterControl" );
898 Sequence< OUString > SAL_CALL OFilterControl::getSupportedServiceNames_Static()
900 Sequence< OUString > aNames( 2 );
901 aNames[ 0 ] = "com.sun.star.form.control.FilterControl";
902 aNames[ 1 ] = "com.sun.star.awt.UnoControl";
903 return aNames;
905 } // namespace frm
907 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface* SAL_CALL
908 com_sun_star_comp_forms_OFilterControl_get_implementation(css::uno::XComponentContext* context,
909 css::uno::Sequence<css::uno::Any> const &)
911 return cppu::acquire(new frm::OFilterControl(context));
914 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */