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