blob: 93fdb1c69b705d1fe8c5005d923b67b235689641 [file] [log] [blame]
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_forms.hxx"
#include "Filter.hxx"
#include "FormComponent.hxx"
#include "frm_module.hxx"
#include "frm_resource.hrc"
#include "frm_resource.hxx"
#include "property.hrc"
#include "property.hxx"
/** === begin UNO includes === **/
#include <com/sun/star/awt/VclWindowPeerAttribute.hpp>
#include <com/sun/star/awt/XCheckBox.hpp>
#include <com/sun/star/awt/XComboBox.hpp>
#include <com/sun/star/awt/XListBox.hpp>
#include <com/sun/star/awt/XRadioButton.hpp>
#include <com/sun/star/awt/XVclWindowPeer.hpp>
#include <com/sun/star/beans/NamedValue.hpp>
#include <com/sun/star/container/XChild.hpp>
#include <com/sun/star/container/XIndexAccess.hpp>
#include <com/sun/star/container/XNamed.hpp>
#include <com/sun/star/form/FormComponentType.hpp>
#include <com/sun/star/sdb/BooleanComparisonMode.hpp>
#include <com/sun/star/sdb/XColumn.hpp>
#include <com/sun/star/sdb/XSQLQueryComposerFactory.hpp>
#include <com/sun/star/sdbc/DataType.hpp>
#include <com/sun/star/sdbc/XRowSet.hpp>
#include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
#include <com/sun/star/sdbcx/XTablesSupplier.hpp>
#include <com/sun/star/ui/dialogs/XExecutableDialog.hpp>
#include <com/sun/star/awt/XItemList.hpp>
/** === end UNO includes === **/
#include <comphelper/numbers.hxx>
#include <comphelper/property.hxx>
#include <connectivity/dbconversion.hxx>
#include <connectivity/dbtools.hxx>
#include <connectivity/formattedcolumnvalue.hxx>
#include <connectivity/predicateinput.hxx>
#include <rtl/ustrbuf.hxx>
#include <toolkit/helper/vclunohelper.hxx>
#include <tools/diagnose_ex.h>
#include <unotools/localedatawrapper.hxx>
#include <vcl/stdtext.hxx>
#include <vcl/svapp.hxx>
#include <tools/wintypes.hxx>
//--------------------------------------------------------------------------
extern "C" void SAL_CALL createRegistryInfo_OFilterControl()
{
static ::frm::OMultiInstanceAutoRegistration< ::frm::OFilterControl > aAutoRegistration;
}
//.........................................................................
namespace frm
{
//.........................................................................
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::awt;
using namespace ::com::sun::star::lang;
using namespace ::com::sun::star::beans;
using namespace ::com::sun::star::sdb;
using namespace ::com::sun::star::sdbc;
using namespace ::com::sun::star::sdbcx;
using namespace ::com::sun::star::util;
using namespace ::com::sun::star::form;
using namespace ::com::sun::star::container;
using namespace ::com::sun::star::ui::dialogs;
using namespace ::connectivity;
//=====================================================================
// OFilterControl
//=====================================================================
//---------------------------------------------------------------------
OFilterControl::OFilterControl( const Reference< XMultiServiceFactory >& _rxORB )
:UnoControl( _rxORB )
,m_aTextListeners( *this )
,m_aParser( _rxORB )
,m_nControlClass( FormComponentType::TEXTFIELD )
,m_bFilterList( sal_False )
,m_bMultiLine( sal_False )
,m_bFilterListFilled( sal_False )
{
}
//---------------------------------------------------------------------
sal_Bool OFilterControl::ensureInitialized( )
{
if ( !m_xField.is() )
{
OSL_ENSURE( sal_False, "OFilterControl::ensureInitialized: improperly initialized: no field!" );
return sal_False;
}
if ( !m_xConnection.is() )
{
OSL_ENSURE( sal_False, "OFilterControl::ensureInitialized: improperly initialized: no connection!" );
return sal_False;
}
if ( !m_xFormatter.is() )
{
// we can create one from the connection, if it's an SDB connection
Reference< XNumberFormatsSupplier > xFormatSupplier = ::dbtools::getNumberFormats( m_xConnection, sal_True, maContext.getLegacyServiceFactory() );
if ( xFormatSupplier.is() )
{
maContext.createComponent( "com.sun.star.util.NumberFormatter", m_xFormatter );
if ( m_xFormatter.is() )
m_xFormatter->attachNumberFormatsSupplier( xFormatSupplier );
}
}
if ( !m_xFormatter.is() )
{
OSL_ENSURE( sal_False, "OFilterControl::ensureInitialized: no number formatter!" );
// no fallback anymore
return sal_False;
}
return sal_True;
}
//---------------------------------------------------------------------
Any SAL_CALL OFilterControl::queryAggregation( const Type & rType ) throw(RuntimeException)
{
Any aRet = UnoControl::queryAggregation( rType);
if(!aRet.hasValue())
aRet = OFilterControl_BASE::queryInterface(rType);
return aRet;
}
//------------------------------------------------------------------
::rtl::OUString OFilterControl::GetComponentServiceName()
{
::rtl::OUString aServiceName;
switch (m_nControlClass)
{
case FormComponentType::RADIOBUTTON:
aServiceName = ::rtl::OUString::createFromAscii("radiobutton");
break;
case FormComponentType::CHECKBOX:
aServiceName = ::rtl::OUString::createFromAscii("checkbox");
break;
case FormComponentType::COMBOBOX:
aServiceName = ::rtl::OUString::createFromAscii("combobox");
break;
case FormComponentType::LISTBOX:
aServiceName = ::rtl::OUString::createFromAscii("listbox");
break;
default:
if (m_bMultiLine)
aServiceName = ::rtl::OUString::createFromAscii("MultiLineEdit");
else
aServiceName = ::rtl::OUString::createFromAscii("Edit");
}
return aServiceName;
}
// XComponent
//---------------------------------------------------------------------
void OFilterControl::dispose() throw( RuntimeException )
{
EventObject aEvt(*this);
m_aTextListeners.disposeAndClear( aEvt );
UnoControl::dispose();
}
//---------------------------------------------------------------------
void OFilterControl::createPeer( const Reference< XToolkit > & rxToolkit, const Reference< XWindowPeer > & rParentPeer ) throw(RuntimeException)
{
UnoControl::createPeer( rxToolkit, rParentPeer );
try
{
Reference< XVclWindowPeer > xVclWindow( getPeer(), UNO_QUERY_THROW );
switch ( m_nControlClass )
{
case FormComponentType::CHECKBOX:
{
// checkboxes always have a tristate-mode
xVclWindow->setProperty( PROPERTY_TRISTATE, makeAny( sal_Bool( sal_True ) ) );
xVclWindow->setProperty( PROPERTY_STATE, makeAny( sal_Int32( STATE_DONTKNOW ) ) );
Reference< XCheckBox > xBox( getPeer(), UNO_QUERY_THROW );
xBox->addItemListener( this );
}
break;
case FormComponentType::RADIOBUTTON:
{
xVclWindow->setProperty( PROPERTY_STATE, makeAny( sal_Int32( STATE_NOCHECK ) ) );
Reference< XRadioButton > xRadio( getPeer(), UNO_QUERY_THROW );
xRadio->addItemListener( this );
}
break;
case FormComponentType::LISTBOX:
{
Reference< XListBox > xListBox( getPeer(), UNO_QUERY_THROW );
xListBox->addItemListener( this );
}
// no break
case FormComponentType::COMBOBOX:
{
xVclWindow->setProperty(PROPERTY_AUTOCOMPLETE, makeAny( sal_Bool( sal_True ) ) );
}
// no break
default:
{
Reference< XWindow > xWindow( getPeer(), UNO_QUERY );
xWindow->addFocusListener( this );
Reference< XTextComponent > xText( getPeer(), UNO_QUERY );
if (xText.is())
xText->setMaxTextLen(0);
}
break;
}
OControl::initFormControlPeer( getPeer() );
// filter controls are _never_ readonly
// #107013# - 2002-02-03 - fs@openoffice.org
Reference< XPropertySet > xModel( getModel(), UNO_QUERY_THROW );
Reference< XPropertySetInfo > xModelPSI( xModel->getPropertySetInfo(), UNO_SET_THROW );
if ( xModelPSI->hasPropertyByName( PROPERTY_READONLY ) )
xVclWindow->setProperty( PROPERTY_READONLY, makeAny( sal_Bool( sal_False ) ) );
}
catch( const Exception& )
{
DBG_UNHANDLED_EXCEPTION();
}
if (m_bFilterList)
m_bFilterListFilled = sal_False;
}
//---------------------------------------------------------------------
void OFilterControl::PrepareWindowDescriptor( WindowDescriptor& rDescr )
{
if (m_bFilterList)
rDescr.WindowAttributes |= VclWindowPeerAttribute::DROPDOWN;
}
//---------------------------------------------------------------------
void OFilterControl::ImplSetPeerProperty( const ::rtl::OUString& rPropName, const Any& rVal )
{
// these properties are ignored
if (rPropName == PROPERTY_TEXT ||
rPropName == PROPERTY_STATE)
return;
UnoControl::ImplSetPeerProperty( rPropName, rVal );
}
// XEventListener
//---------------------------------------------------------------------
void SAL_CALL OFilterControl::disposing(const EventObject& Source) throw( RuntimeException )
{
UnoControl::disposing(Source);
}
// XItemListener
//---------------------------------------------------------------------
void SAL_CALL OFilterControl::itemStateChanged( const ItemEvent& rEvent ) throw(RuntimeException)
{
::rtl::OUStringBuffer aText;
switch (m_nControlClass)
{
case FormComponentType::CHECKBOX:
{
if ( ( rEvent.Selected == STATE_CHECK ) || ( rEvent.Selected == STATE_NOCHECK ) )
{
sal_Int32 nBooleanComparisonMode = ::dbtools::DatabaseMetaData( m_xConnection ).getBooleanComparisonMode();
bool bSelected = ( rEvent.Selected == STATE_CHECK );
::rtl::OUString sExpressionMarker( RTL_CONSTASCII_USTRINGPARAM( "$expression$" ) );
::dbtools::getBoleanComparisonPredicate(
sExpressionMarker,
bSelected,
nBooleanComparisonMode,
aText
);
::rtl::OUString sText( aText.makeStringAndClear() );
sal_Int32 nMarkerPos( sText.indexOf( sExpressionMarker ) );
OSL_ENSURE( nMarkerPos == 0, "OFilterControl::itemStateChanged: unsupported boolean comparison mode!" );
// If this assertion fails, then getBoleanComparisonPredicate created a predicate which
// does not start with the expression we gave it. The only known case is when
// the comparison mode is ACCESS_COMPAT, and the value is TRUE. In this case,
// the expression is rather complex.
// Well, so this is a known issue - the filter controls (and thus the form based filter)
// do not work with boolean MS Access fields.
// To fix this, we would probably have to revert here to always return "1" or "0" as normalized
// filter, and change our client code to properly translate this (which could be some effort).
if ( nMarkerPos == 0 )
aText.append( sText.copy( sExpressionMarker.getLength() ) );
else
{
// fallback
aText.appendAscii( bSelected ? "1" : "0" );
}
}
}
break;
case FormComponentType::LISTBOX:
{
try
{
const Reference< XItemList > xItemList( getModel(), UNO_QUERY_THROW );
::rtl::OUString sItemText( xItemList->getItemText( rEvent.Selected ) );
const MapString2String::const_iterator itemPos = m_aDisplayItemToValueItem.find( sItemText );
if ( itemPos != m_aDisplayItemToValueItem.end() )
{
sItemText = itemPos->second;
if ( sItemText.getLength() )
{
::dbtools::OPredicateInputController aPredicateInput( maContext.getLegacyServiceFactory(), m_xConnection, getParseContext() );
::rtl::OUString sErrorMessage;
OSL_VERIFY( aPredicateInput.normalizePredicateString( sItemText, m_xField, &sErrorMessage ) );
}
}
aText.append( sItemText );
}
catch( const Exception& )
{
DBG_UNHANDLED_EXCEPTION();
}
}
break;
case FormComponentType::RADIOBUTTON:
{
if ( rEvent.Selected == STATE_CHECK )
aText.append( ::comphelper::getString( Reference< XPropertySet >( getModel(), UNO_QUERY )->getPropertyValue( PROPERTY_REFVALUE ) ) );
}
break;
}
::rtl::OUString sText( aText.makeStringAndClear() );
if ( m_aText.compareTo( sText ) )
{
m_aText = sText;
TextEvent aEvt;
aEvt.Source = *this;
::cppu::OInterfaceIteratorHelper aIt( m_aTextListeners );
while( aIt.hasMoreElements() )
((XTextListener *)aIt.next())->textChanged( aEvt );
}
}
//---------------------------------------------------------------------
void OFilterControl::implInitFilterList()
{
if ( !ensureInitialized( ) )
// already asserted in ensureInitialized
return;
// ensure the cursor and the statement are disposed as soon as we leave
::utl::SharedUNOComponent< XResultSet > xListCursor;
::utl::SharedUNOComponent< XStatement > xStatement;
try
{
m_bFilterListFilled = sal_True;
if ( !m_xField.is() )
return;
::rtl::OUString sFieldName;
m_xField->getPropertyValue( PROPERTY_NAME ) >>= sFieldName;
// here we need a table to which the field belongs to
const Reference< XChild > xModelAsChild( getModel(), UNO_QUERY_THROW );
const Reference< XRowSet > xForm( xModelAsChild->getParent(), UNO_QUERY_THROW );
const Reference< XPropertySet > xFormProps( xForm, UNO_QUERY_THROW );
// create a query composer
Reference< XColumnsSupplier > xSuppColumns;
xFormProps->getPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("SingleSelectQueryComposer"))) >>= xSuppColumns;
const Reference< XConnection > xConnection( ::dbtools::getConnection( xForm ), UNO_SET_THROW );
const Reference< XNameAccess > xFieldNames( xSuppColumns->getColumns(), UNO_SET_THROW );
if ( !xFieldNames->hasByName( sFieldName ) )
return;
::rtl::OUString sRealFieldName, sTableName;
const Reference< XPropertySet > xComposerFieldProps( xFieldNames->getByName( sFieldName ), UNO_QUERY_THROW );
xComposerFieldProps->getPropertyValue( PROPERTY_REALNAME ) >>= sRealFieldName;
xComposerFieldProps->getPropertyValue( PROPERTY_TABLENAME ) >>= sTableName;
// obtain the table of the field
const Reference< XTablesSupplier > xSuppTables( xSuppColumns, UNO_QUERY_THROW );
const Reference< XNameAccess > xTablesNames( xSuppTables->getTables(), UNO_SET_THROW );
const Reference< XNamed > xNamedTable( xTablesNames->getByName( sTableName ), UNO_QUERY_THROW );
sTableName = xNamedTable->getName();
// create a statement selecting all values for the given field
::rtl::OUStringBuffer aStatement;
const Reference< XDatabaseMetaData > xMeta( xConnection->getMetaData(), UNO_SET_THROW );
const ::rtl::OUString sQuoteChar = xMeta->getIdentifierQuoteString();
aStatement.appendAscii( "SELECT DISTINCT " );
aStatement.append( sQuoteChar );
aStatement.append( sRealFieldName );
aStatement.append( sQuoteChar );
// if the field had an alias in our form's statement, give it this alias in the new statement, too
if ( sFieldName.getLength() && ( sFieldName != sRealFieldName ) )
{
aStatement.appendAscii(" AS ");
aStatement.append( sQuoteChar );
aStatement.append( sFieldName );
aStatement.append( sQuoteChar );
}
aStatement.appendAscii( " FROM " );
::rtl::OUString sCatalog, sSchema, sTable;
::dbtools::qualifiedNameComponents( xMeta, sTableName, sCatalog, sSchema, sTable, ::dbtools::eInDataManipulation );
aStatement.append( ::dbtools::composeTableNameForSelect( xConnection, sCatalog, sSchema, sTable ) );
// execute the statement
xStatement.reset( xConnection->createStatement() );
const ::rtl::OUString sSelectStatement( aStatement.makeStringAndClear( ) );
xListCursor.reset( xStatement->executeQuery( sSelectStatement ) );
// retrieve the one column which we take the values from
const Reference< XColumnsSupplier > xSupplyCols( xListCursor, UNO_QUERY_THROW );
const Reference< XIndexAccess > xFields( xSupplyCols->getColumns(), UNO_QUERY_THROW );
const Reference< XPropertySet > xDataField( xFields->getByIndex(0), UNO_QUERY_THROW );
// ensure the values will be formatted according to the field format
const ::dbtools::FormattedColumnValue aFormatter( m_xFormatter, xDataField );
::std::vector< ::rtl::OUString > aProposals;
aProposals.reserve(16);
while ( xListCursor->next() && ( aProposals.size() < size_t( SHRT_MAX ) ) )
{
const ::rtl::OUString sCurrentValue = aFormatter.getFormattedValue();
aProposals.push_back( sCurrentValue );
}
// fill the list items into our peer
Sequence< ::rtl::OUString> aStringSeq( aProposals.size() );
::std::copy( aProposals.begin(), aProposals.end(), aStringSeq.getArray() );
const Reference< XComboBox > xComboBox( getPeer(), UNO_QUERY_THROW );
xComboBox->addItems( aStringSeq, 0 );
// set the drop down line count to something reasonable
const sal_Int16 nLineCount = ::std::min( sal_Int16( 16 ), sal_Int16( aStringSeq.getLength() ) );
xComboBox->setDropDownLineCount( nLineCount );
}
catch( const Exception& )
{
DBG_UNHANDLED_EXCEPTION();
}
}
// XFocusListener
//---------------------------------------------------------------------
void SAL_CALL OFilterControl::focusGained(const FocusEvent& /*e*/) throw( RuntimeException )
{
// should we fill the combobox?
if (m_bFilterList && !m_bFilterListFilled)
implInitFilterList();
}
//---------------------------------------------------------------------
void SAL_CALL OFilterControl::focusLost(const FocusEvent& /*e*/) throw( RuntimeException )
{
}
//---------------------------------------------------------------------
sal_Bool SAL_CALL OFilterControl::commit() throw(RuntimeException)
{
if ( !ensureInitialized( ) )
// already asserted in ensureInitialized
return sal_True;
::rtl::OUString aText;
switch (m_nControlClass)
{
case FormComponentType::TEXTFIELD:
case FormComponentType::COMBOBOX:
{
Reference< XTextComponent > xText( getPeer(), UNO_QUERY );
if (xText.is())
aText = xText->getText();
} break;
default:
return sal_True;
}
if (m_aText.compareTo(aText))
{
// check the text with the SQL-Parser
::rtl::OUString aNewText(aText);
aNewText.trim();
if ( aNewText.getLength() )
{
::dbtools::OPredicateInputController aPredicateInput( maContext.getLegacyServiceFactory(), m_xConnection, getParseContext() );
::rtl::OUString sErrorMessage;
if ( !aPredicateInput.normalizePredicateString( aNewText, m_xField, &sErrorMessage ) )
{
// display the error and outta here
SQLContext aError;
aError.Message = String( FRM_RES_STRING( RID_STR_SYNTAXERROR ) );
aError.Details = sErrorMessage;
displayException( aError );
return sal_False;
}
}
setText(aNewText);
TextEvent aEvt;
aEvt.Source = *this;
::cppu::OInterfaceIteratorHelper aIt( m_aTextListeners );
while( aIt.hasMoreElements() )
static_cast< XTextListener* >( aIt.next() )->textChanged( aEvt );
}
return sal_True;
}
// XTextComponent
//---------------------------------------------------------------------
void SAL_CALL OFilterControl::addTextListener(const Reference< XTextListener > & l) throw(RuntimeException)
{
m_aTextListeners.addInterface( l );
}
//---------------------------------------------------------------------
void SAL_CALL OFilterControl::removeTextListener(const Reference< XTextListener > & l) throw(RuntimeException)
{
m_aTextListeners.removeInterface( l );
}
//---------------------------------------------------------------------
void SAL_CALL OFilterControl::setText( const ::rtl::OUString& aText ) throw(RuntimeException)
{
if ( !ensureInitialized( ) )
// already asserted in ensureInitialized
return;
switch (m_nControlClass)
{
case FormComponentType::CHECKBOX:
{
Reference< XVclWindowPeer > xVclWindow( getPeer(), UNO_QUERY );
if (xVclWindow.is())
{
Any aValue;
if ( aText.equalsAscii( "1" )
|| aText.equalsIgnoreAsciiCaseAscii( "TRUE" )
|| aText.equalsIgnoreAsciiCaseAscii( "IS TRUE" )
)
{
aValue <<= (sal_Int32)STATE_CHECK;
}
else if ( aText.equalsAscii( "0" )
|| aText.equalsIgnoreAsciiCaseAscii( "FALSE" )
)
{
aValue <<= (sal_Int32)STATE_NOCHECK;
}
else
aValue <<= (sal_Int32)STATE_DONTKNOW;
m_aText = aText;
xVclWindow->setProperty( PROPERTY_STATE, aValue );
}
} break;
case FormComponentType::RADIOBUTTON:
{
Reference< XVclWindowPeer > xVclWindow( getPeer(), UNO_QUERY );
if (xVclWindow.is())
{
::rtl::OUString aRefText = ::comphelper::getString(com::sun::star::uno::Reference< XPropertySet > (getModel(), UNO_QUERY)->getPropertyValue(PROPERTY_REFVALUE));
Any aValue;
if (aText == aRefText)
aValue <<= (sal_Int32)STATE_CHECK;
else
aValue <<= (sal_Int32)STATE_NOCHECK;
m_aText = aText;
xVclWindow->setProperty(PROPERTY_STATE, aValue);
}
} break;
case FormComponentType::LISTBOX:
{
Reference< XListBox > xListBox( getPeer(), UNO_QUERY );
if (xListBox.is())
{
m_aText = aText;
MapString2String::const_iterator itemPos = m_aDisplayItemToValueItem.find( m_aText );
if ( itemPos == m_aDisplayItemToValueItem.end() )
{
const bool isQuoted = ( m_aText.getLength() > 1 )
&& ( m_aText[0] == '\'' )
&& ( m_aText[ m_aText.getLength() - 1 ] == '\'' );
if ( isQuoted )
{
m_aText = m_aText.copy( 1, m_aText.getLength() - 2 );
itemPos = m_aDisplayItemToValueItem.find( m_aText );
}
}
OSL_ENSURE( ( itemPos != m_aDisplayItemToValueItem.end() ) || ( m_aText.getLength() == 0 ),
"OFilterControl::setText: this text is not in my display list!" );
if ( itemPos == m_aDisplayItemToValueItem.end() )
m_aText = ::rtl::OUString();
if ( m_aText.getLength() == 0)
{
while ( xListBox->getSelectedItemPos() >= 0 )
{
xListBox->selectItemPos( xListBox->getSelectedItemPos(), sal_False );
}
}
else
{
xListBox->selectItem( m_aText, sal_True );
}
}
}
break;
default:
{
Reference< XTextComponent > xText( getPeer(), UNO_QUERY );
if (xText.is())
{
m_aText = aText;
xText->setText(aText);
}
}
}
}
//---------------------------------------------------------------------
void SAL_CALL OFilterControl::insertText( const ::com::sun::star::awt::Selection& rSel, const ::rtl::OUString& aText ) throw(::com::sun::star::uno::RuntimeException)
{
Reference< XTextComponent > xText( getPeer(), UNO_QUERY );
if (xText.is())
{
xText->insertText(rSel, aText);
m_aText = xText->getText();
}
}
//---------------------------------------------------------------------
::rtl::OUString SAL_CALL OFilterControl::getText() throw(RuntimeException)
{
return m_aText;
}
//---------------------------------------------------------------------
::rtl::OUString SAL_CALL OFilterControl::getSelectedText( void ) throw(RuntimeException)
{
::rtl::OUString aSelected;
Reference< XTextComponent > xText( getPeer(), UNO_QUERY );
if (xText.is())
aSelected = xText->getSelectedText();
return aSelected;
}
//---------------------------------------------------------------------
void SAL_CALL OFilterControl::setSelection( const ::com::sun::star::awt::Selection& aSelection ) throw(::com::sun::star::uno::RuntimeException)
{
Reference< XTextComponent > xText( getPeer(), UNO_QUERY );
if (xText.is())
xText->setSelection( aSelection );
}
//---------------------------------------------------------------------
::com::sun::star::awt::Selection SAL_CALL OFilterControl::getSelection( void ) throw(::com::sun::star::uno::RuntimeException)
{
::com::sun::star::awt::Selection aSel;
Reference< XTextComponent > xText( getPeer(), UNO_QUERY );
if (xText.is())
aSel = xText->getSelection();
return aSel;
}
//---------------------------------------------------------------------
sal_Bool SAL_CALL OFilterControl::isEditable( void ) throw(RuntimeException)
{
Reference< XTextComponent > xText( getPeer(), UNO_QUERY );
return xText.is() && xText->isEditable();
}
//---------------------------------------------------------------------
void SAL_CALL OFilterControl::setEditable( sal_Bool bEditable ) throw(RuntimeException)
{
Reference< XTextComponent > xText( getPeer(), UNO_QUERY );
if (xText.is())
xText->setEditable(bEditable);
}
//---------------------------------------------------------------------
sal_Int16 SAL_CALL OFilterControl::getMaxTextLen() throw(RuntimeException)
{
Reference< XTextComponent > xText( getPeer(), UNO_QUERY );
return xText.is() ? xText->getMaxTextLen() : 0;
}
//---------------------------------------------------------------------
void SAL_CALL OFilterControl::setMaxTextLen( sal_Int16 nLength ) throw(RuntimeException)
{
Reference< XTextComponent > xText( getPeer(), UNO_QUERY );
if (xText.is())
xText->setMaxTextLen(nLength);
}
//---------------------------------------------------------------------
void OFilterControl::displayException( const ::com::sun::star::sdb::SQLContext& _rExcept )
{
try
{
Sequence< Any > aArgs(2);
aArgs[0] <<= PropertyValue(::rtl::OUString::createFromAscii("SQLException"), 0, makeAny( _rExcept ), PropertyState_DIRECT_VALUE);
aArgs[1] <<= PropertyValue(::rtl::OUString::createFromAscii("ParentWindow"), 0, makeAny( m_xMessageParent ), PropertyState_DIRECT_VALUE);
static ::rtl::OUString s_sDialogServiceName = ::rtl::OUString::createFromAscii( "com.sun.star.sdb.ErrorMessageDialog" );
Reference< XExecutableDialog > xErrorDialog( maContext.createComponentWithArguments( s_sDialogServiceName, aArgs ), UNO_QUERY );
if ( xErrorDialog.is() )
xErrorDialog->execute();
else
{
Window* pMessageParent = VCLUnoHelper::GetWindow( m_xMessageParent );
ShowServiceNotAvailableError( pMessageParent, s_sDialogServiceName, sal_True );
}
}
catch( const Exception& )
{
DBG_UNHANDLED_EXCEPTION();
}
}
//---------------------------------------------------------------------
void SAL_CALL OFilterControl::initialize( const Sequence< Any >& aArguments ) throw (Exception, RuntimeException)
{
const Any* pArguments = aArguments.getConstArray();
const Any* pArgumentsEnd = pArguments + aArguments.getLength();
PropertyValue aProp;
NamedValue aValue;
const ::rtl::OUString* pName = NULL;
const Any* pValue = NULL;
for ( ; pArguments != pArgumentsEnd; ++pArguments )
{
// we recognize PropertyValues and NamedValues
if ( *pArguments >>= aProp )
{
pName = &aProp.Name;
pValue = &aProp.Value;
}
else if ( *pArguments >>= aValue )
{
pName = &aValue.Name;
pValue = &aValue.Value;
}
else
{
DBG_ERROR( "OFilterControl::initialize: unrecognized argument!" );
continue;
}
if ( 0 == pName->compareToAscii( "MessageParent" ) )
{
// the message parent
*pValue >>= m_xMessageParent;
OSL_ENSURE( m_xMessageParent.is(), "OFilterControl::initialize: invalid MessageParent!" );
}
else if ( 0 == pName->compareToAscii( "NumberFormatter" ) )
{
// the number format. This argument is optional.
*pValue >>= m_xFormatter;
OSL_ENSURE( m_xFormatter.is(), "OFilterControl::initialize: invalid NumberFormatter!" );
}
else if ( 0 == pName->compareToAscii( "ControlModel" ) )
{
// the control model for which we act as filter control
Reference< XPropertySet > xControlModel;
if ( !(*pValue >>= xControlModel ) || !xControlModel.is() )
{
OSL_ENSURE( sal_False, "OFilterControl::initialize: invalid control model argument!" );
continue;
}
// some properties which are "derived" from the control model we're working for
// ...................................................
// the field
m_xField.clear();
OSL_ENSURE( ::comphelper::hasProperty( PROPERTY_BOUNDFIELD, xControlModel ), "OFilterControl::initialize: control model needs a bound field property!" );
xControlModel->getPropertyValue( PROPERTY_BOUNDFIELD ) >>= m_xField;
// ...................................................
// filter list and control class
m_bFilterList = ::comphelper::hasProperty( PROPERTY_FILTERPROPOSAL, xControlModel ) && ::comphelper::getBOOL( xControlModel->getPropertyValue( PROPERTY_FILTERPROPOSAL ) );
if ( m_bFilterList )
m_nControlClass = FormComponentType::COMBOBOX;
else
{
sal_Int16 nClassId = ::comphelper::getINT16( xControlModel->getPropertyValue( PROPERTY_CLASSID ) );
switch (nClassId)
{
case FormComponentType::CHECKBOX:
case FormComponentType::RADIOBUTTON:
case FormComponentType::LISTBOX:
case FormComponentType::COMBOBOX:
m_nControlClass = nClassId;
if ( FormComponentType::LISTBOX == nClassId )
{
Sequence< ::rtl::OUString > aDisplayItems;
OSL_VERIFY( xControlModel->getPropertyValue( PROPERTY_STRINGITEMLIST ) >>= aDisplayItems );
Sequence< ::rtl::OUString > aValueItems;
OSL_VERIFY( xControlModel->getPropertyValue( PROPERTY_VALUE_SEQ ) >>= aValueItems );
OSL_ENSURE( aDisplayItems.getLength() == aValueItems.getLength(), "OFilterControl::initialize: inconsistent item lists!" );
for ( sal_Int32 i=0; i < ::std::min( aDisplayItems.getLength(), aValueItems.getLength() ); ++i )
m_aDisplayItemToValueItem[ aDisplayItems[i] ] = aValueItems[i];
}
break;
default:
m_bMultiLine = ::comphelper::hasProperty( PROPERTY_MULTILINE, xControlModel ) && ::comphelper::getBOOL( xControlModel->getPropertyValue( PROPERTY_MULTILINE ) );
m_nControlClass = FormComponentType::TEXTFIELD;
break;
}
}
// ...................................................
// the connection meta data for the form which we're working for
Reference< XChild > xModel( xControlModel, UNO_QUERY );
Reference< XRowSet > xForm;
if ( xModel.is() )
xForm = xForm.query( xModel->getParent() );
m_xConnection = ::dbtools::getConnection( xForm );
OSL_ENSURE( m_xConnection.is(), "OFilterControl::initialize: unable to determine the form's connection!" );
}
}
}
//---------------------------------------------------------------------
::rtl::OUString SAL_CALL OFilterControl::getImplementationName( ) throw (RuntimeException)
{
return getImplementationName_Static();
}
//---------------------------------------------------------------------
sal_Bool SAL_CALL OFilterControl::supportsService( const ::rtl::OUString& ServiceName ) throw (RuntimeException)
{
Sequence< ::rtl::OUString > aSupported( getSupportedServiceNames() );
const ::rtl::OUString* pArray = aSupported.getConstArray();
for( sal_Int32 i = 0; i < aSupported.getLength(); ++i, ++pArray )
if( pArray->equals( ServiceName ) )
return sal_True;
return sal_False;
}
//---------------------------------------------------------------------
Sequence< ::rtl::OUString > SAL_CALL OFilterControl::getSupportedServiceNames( ) throw (RuntimeException)
{
return getSupportedServiceNames_Static();
}
//---------------------------------------------------------------------
::rtl::OUString SAL_CALL OFilterControl::getImplementationName_Static()
{
return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.forms.OFilterControl" ) );
}
//---------------------------------------------------------------------
Sequence< ::rtl::OUString > SAL_CALL OFilterControl::getSupportedServiceNames_Static()
{
Sequence< ::rtl::OUString > aNames( 2 );
aNames[ 0 ] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.form.control.FilterControl" ) );
aNames[ 1 ] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.awt.UnoControl" ) );
return aNames;
}
//---------------------------------------------------------------------
Reference< XInterface > SAL_CALL OFilterControl::Create( const Reference< XMultiServiceFactory >& _rxFactory )
{
return static_cast< XServiceInfo* >( new OFilterControl( _rxFactory ) );
}
//.........................................................................
} // namespace frm
//.........................................................................