xref: /trunk/main/svx/source/form/filtnav.cxx (revision f6e50924)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_svx.hxx"
26 
27 
28 #include "filtnav.hxx"
29 #include "fmexch.hxx"
30 #include "fmhelp.hrc"
31 #include "fmitems.hxx"
32 #include "fmprop.hrc"
33 #include "svx/fmresids.hrc"
34 #include "gridcell.hxx"
35 
36 /** === begin UNO includes === **/
37 #include <com/sun/star/form/runtime/XFormController.hpp>
38 #include <com/sun/star/lang/XUnoTunnel.hpp>
39 #include <com/sun/star/util/XNumberFormatter.hpp>
40 /** === end UNO includes === **/
41 
42 #include <comphelper/processfactory.hxx>
43 #include <svx/fmtools.hxx>
44 #include <comphelper/property.hxx>
45 #include <comphelper/sequence.hxx>
46 #include <comphelper/uno3.hxx>
47 #include <connectivity/dbtools.hxx>
48 #include <cppuhelper/implbase1.hxx>
49 #include <fmservs.hxx>
50 #include <fmshimp.hxx>
51 #include <rtl/logfile.hxx>
52 #include <sfx2/dispatch.hxx>
53 #include <sfx2/objitem.hxx>
54 #include <sfx2/objsh.hxx>
55 #include <sfx2/request.hxx>
56 #include <svx/dialmgr.hxx>
57 #include <svx/fmshell.hxx>
58 #include <svx/svxids.hrc>
59 #include <tools/shl.hxx>
60 #include <vcl/wrkwin.hxx>
61 
62 #include <functional>
63 
64 #define SYNC_DELAY						200
65 #define DROP_ACTION_TIMER_INITIAL_TICKS 	10
66 	// solange dauert es, bis das Scrollen anspringt
67 #define DROP_ACTION_TIMER_SCROLL_TICKS		3
68 	// in diesen Intervallen wird jeweils eine Zeile gescrollt
69 #define DROP_ACTION_TIMER_TICK_BASE 		10
70 	// das ist die Basis, mit der beide Angaben multipliziert werden (in ms)
71 
72 using namespace ::svxform;
73 using namespace ::connectivity::simple;
74 using namespace ::connectivity;
75 
76 
77 //........................................................................
78 namespace svxform
79 {
80 //........................................................................
81 
82     /** === begin UNO using === **/
83     using ::com::sun::star::uno::Reference;
84     using ::com::sun::star::lang::XMultiServiceFactory;
85     using ::com::sun::star::awt::TextEvent;
86     using ::com::sun::star::container::XIndexAccess;
87     using ::com::sun::star::uno::UNO_QUERY;
88     using ::com::sun::star::beans::XPropertySet;
89     using ::com::sun::star::form::runtime::XFormController;
90     using ::com::sun::star::form::runtime::XFilterController;
91     using ::com::sun::star::form::runtime::XFilterControllerListener;
92     using ::com::sun::star::form::runtime::FilterEvent;
93     using ::com::sun::star::lang::EventObject;
94     using ::com::sun::star::uno::RuntimeException;
95     using ::com::sun::star::form::XForm;
96     using ::com::sun::star::container::XChild;
97     using ::com::sun::star::awt::XControl;
98     using ::com::sun::star::sdbc::XConnection;
99     using ::com::sun::star::util::XNumberFormatsSupplier;
100     using ::com::sun::star::beans::XPropertySet;
101     using ::com::sun::star::util::XNumberFormatter;
102     using ::com::sun::star::sdbc::XRowSet;
103     using ::com::sun::star::lang::Locale;
104     using ::com::sun::star::sdb::SQLContext;
105     using ::com::sun::star::uno::XInterface;
106     using ::com::sun::star::uno::UNO_QUERY_THROW;
107     using ::com::sun::star::uno::UNO_SET_THROW;
108     using ::com::sun::star::uno::Exception;
109     using ::com::sun::star::awt::XTextComponent;
110     using ::com::sun::star::uno::Sequence;
111     /** === end UNO using === **/
112 
113 //========================================================================
114 OFilterItemExchange::OFilterItemExchange()
115 {
116 }
117 
118 //------------------------------------------------------------------------
119 void OFilterItemExchange::AddSupportedFormats()
120 {
121 	AddFormat(getFormatId());
122 }
123 
124 //------------------------------------------------------------------------
125 sal_uInt32 OFilterItemExchange::getFormatId()
126 {
127 	static sal_uInt32 s_nFormat = (sal_uInt32)-1;
128 	if ((sal_uInt32)-1 == s_nFormat)
129 	{
130 		s_nFormat = SotExchange::RegisterFormatName(String::CreateFromAscii("application/x-openoffice;windows_formatname=\"form.FilterControlExchange\""));
131 		DBG_ASSERT((sal_uInt32)-1 != s_nFormat, "OFilterExchangeHelper::getFormatId: bad exchange id!");
132 	}
133 	return s_nFormat;
134 }
135 
136 //------------------------------------------------------------------------
137 OLocalExchange* OFilterExchangeHelper::createExchange() const
138 {
139 	return new OFilterItemExchange;
140 }
141 
142 //========================================================================
143 TYPEINIT0(FmFilterData);
144 Image FmFilterData::GetImage( BmpColorMode /*_eMode*/ ) const
145 {
146 	return Image();
147 }
148 
149 //========================================================================
150 TYPEINIT1(FmParentData, FmFilterData);
151 //------------------------------------------------------------------------
152 FmParentData::~FmParentData()
153 {
154 	for (::std::vector<FmFilterData*>::const_iterator i = m_aChildren.begin();
155 		 i != m_aChildren.end(); i++)
156 		delete (*i);
157 }
158 
159 //========================================================================
160 TYPEINIT1(FmFormItem, FmParentData);
161 //------------------------------------------------------------------------
162 Image FmFormItem::GetImage( BmpColorMode _eMode ) const
163 {
164 	static Image aImage;
165 	static Image aImage_HC;
166 
167 	if (!aImage)
168 	{
169 		ImageList aNavigatorImages( SVX_RES( RID_SVXIMGLIST_FMEXPL ) );
170 		ImageList aNavigatorImages_HC( SVX_RES( RID_SVXIMGLIST_FMEXPL_HC ) );
171 
172 		aImage = aNavigatorImages.GetImage( RID_SVXIMG_FORM );
173 		aImage_HC = aNavigatorImages_HC.GetImage( RID_SVXIMG_FORM );
174 	}
175 	return ( BMP_COLOR_HIGHCONTRAST == _eMode ) ? aImage_HC : aImage;
176 }
177 
178 //========================================================================
179 TYPEINIT1(FmFilterItems, FmParentData);
180 //------------------------------------------------------------------------
181 FmFilterItem* FmFilterItems::Find( const ::sal_Int32 _nFilterComponentIndex ) const
182 {
183 	for (   ::std::vector< FmFilterData* >::const_iterator i = m_aChildren.begin();
184 		    i != m_aChildren.end();
185             ++i
186         )
187 	{
188 		FmFilterItem* pCondition = PTR_CAST( FmFilterItem, *i );
189         DBG_ASSERT( pCondition, "FmFilterItems::Find: Wrong element in container!" );
190 		if ( _nFilterComponentIndex == pCondition->GetComponentIndex() )
191 			return pCondition;
192 	}
193 	return NULL;
194 }
195 
196 //------------------------------------------------------------------------
197 Image FmFilterItems::GetImage( BmpColorMode _eMode ) const
198 {
199 	static Image aImage;
200 	static Image aImage_HC;
201 
202 	if (!aImage)
203 	{
204 		ImageList aNavigatorImages( SVX_RES( RID_SVXIMGLIST_FMEXPL ) );
205 		ImageList aNavigatorImages_HC( SVX_RES( RID_SVXIMGLIST_FMEXPL_HC ) );
206 
207 		aImage = aNavigatorImages.GetImage( RID_SVXIMG_FILTER );
208 		aImage_HC = aNavigatorImages_HC.GetImage( RID_SVXIMG_FILTER );
209 	}
210 	return ( BMP_COLOR_HIGHCONTRAST == _eMode ) ? aImage_HC : aImage;
211 }
212 
213 //========================================================================
214 TYPEINIT1(FmFilterItem, FmFilterData);
215 //------------------------------------------------------------------------
216 FmFilterItem::FmFilterItem( const Reference< XMultiServiceFactory >& _rxFactory,
217 						    FmFilterItems* pParent,
218 					        const ::rtl::OUString& aFieldName,
219 					        const ::rtl::OUString& aText,
220 					        const sal_Int32 _nComponentIndex )
221 		  :FmFilterData(_rxFactory,pParent, aText)
222 		  ,m_aFieldName(aFieldName)
223 		  ,m_nComponentIndex( _nComponentIndex )
224 {
225 }
226 
227 //------------------------------------------------------------------------
228 Image FmFilterItem::GetImage( BmpColorMode _eMode ) const
229 {
230 	static Image aImage;
231 	static Image aImage_HC;
232 
233 	if (!aImage)
234 	{
235 		ImageList aNavigatorImages( SVX_RES( RID_SVXIMGLIST_FMEXPL ) );
236 		ImageList aNavigatorImages_HC( SVX_RES( RID_SVXIMGLIST_FMEXPL_HC ) );
237 
238 		aImage = aNavigatorImages.GetImage( RID_SVXIMG_FIELD );
239 		aImage_HC = aNavigatorImages_HC.GetImage( RID_SVXIMG_FIELD );
240 	}
241 	return ( BMP_COLOR_HIGHCONTRAST == _eMode ) ? aImage_HC : aImage;
242 }
243 
244 //========================================================================
245 // Hints for communicatition between model and view
246 //========================================================================
247 class FmFilterHint : public SfxHint
248 {
249 	FmFilterData*	m_pData;
250 
251 public:
252 	TYPEINFO();
253 	FmFilterHint(FmFilterData* pData):m_pData(pData){}
254 	FmFilterData* GetData() const { return m_pData; }
255 };
256 TYPEINIT1( FmFilterHint, SfxHint );
257 
258 //========================================================================
259 class FmFilterInsertedHint : public FmFilterHint
260 {
261 	sal_Int32 m_nPos;	// Position relative to the parent of the data
262 
263 public:
264 	TYPEINFO();
265 	FmFilterInsertedHint(FmFilterData* pData, sal_Int32 nRelPos)
266 		:FmFilterHint(pData)
267 		,m_nPos(nRelPos){}
268 
269 	sal_Int32 GetPos() const { return m_nPos; }
270 };
271 TYPEINIT1( FmFilterInsertedHint, FmFilterHint );
272 
273 //========================================================================
274 class FmFilterRemovedHint : public FmFilterHint
275 {
276 public:
277 	TYPEINFO();
278 	FmFilterRemovedHint(FmFilterData* pData)
279 		:FmFilterHint(pData){}
280 
281 };
282 TYPEINIT1( FmFilterRemovedHint, FmFilterHint );
283 
284 //========================================================================
285 class FmFilterTextChangedHint : public FmFilterHint
286 {
287 public:
288 	TYPEINFO();
289 	FmFilterTextChangedHint(FmFilterData* pData)
290 		:FmFilterHint(pData){}
291 
292 };
293 TYPEINIT1( FmFilterTextChangedHint, FmFilterHint );
294 
295 //========================================================================
296 class FilterClearingHint : public SfxHint
297 {
298 public:
299 	TYPEINFO();
300 	FilterClearingHint(){}
301 };
302 TYPEINIT1( FilterClearingHint, SfxHint );
303 
304 //========================================================================
305 class FmFilterCurrentChangedHint : public SfxHint
306 {
307 public:
308 	TYPEINFO();
309 	FmFilterCurrentChangedHint(){}
310 };
311 TYPEINIT1( FmFilterCurrentChangedHint, SfxHint );
312 
313 //========================================================================
314 // class FmFilterAdapter, Listener an den FilterControls
315 //========================================================================
316 class FmFilterAdapter : public ::cppu::WeakImplHelper1< XFilterControllerListener >
317 {
318 	FmFilterModel*			    m_pModel;
319     Reference< XIndexAccess >   m_xControllers;
320 
321 public:
322 	FmFilterAdapter(FmFilterModel* pModel, const Reference< XIndexAccess >& xControllers);
323 
324 // XEventListener
325 	virtual void SAL_CALL disposing(const EventObject& Source) throw( RuntimeException );
326 
327 // XFilterControllerListener
328     virtual void SAL_CALL predicateExpressionChanged( const FilterEvent& _Event ) throw (RuntimeException);
329     virtual void SAL_CALL disjunctiveTermRemoved( const FilterEvent& _Event ) throw (RuntimeException);
330     virtual void SAL_CALL disjunctiveTermAdded( const FilterEvent& _Event ) throw (RuntimeException);
331 
332 // helpers
333 	void dispose() throw( RuntimeException );
334 
335 	void AddOrRemoveListener( const Reference< XIndexAccess >& _rxControllers, const bool _bAdd );
336 
337 	void setText(sal_Int32 nPos,
338 		const FmFilterItem* pFilterItem,
339 		const ::rtl::OUString& rText);
340 };
341 
342 //------------------------------------------------------------------------
343 FmFilterAdapter::FmFilterAdapter(FmFilterModel* pModel, const Reference< XIndexAccess >& xControllers)
344     :m_pModel( pModel )
345     ,m_xControllers( xControllers )
346 {
347     AddOrRemoveListener( m_xControllers, true );
348 }
349 
350 //------------------------------------------------------------------------
351 void FmFilterAdapter::dispose() throw( RuntimeException )
352 {
353     AddOrRemoveListener( m_xControllers, false );
354 }
355 
356 //------------------------------------------------------------------------
357 void FmFilterAdapter::AddOrRemoveListener( const Reference< XIndexAccess >& _rxControllers, const bool _bAdd )
358 {
359 	for (sal_Int32 i = 0, nLen = _rxControllers->getCount(); i < nLen; ++i)
360 	{
361 		Reference< XIndexAccess > xElement( _rxControllers->getByIndex(i), UNO_QUERY );
362 
363 		// step down
364 		AddOrRemoveListener( xElement, _bAdd );
365 
366         // handle this particular controller
367         Reference< XFilterController > xController( xElement, UNO_QUERY );
368         OSL_ENSURE( xController.is(), "FmFilterAdapter::InsertElements: no XFilterController, cannot sync data!" );
369         if ( xController.is() )
370         {
371             if ( _bAdd )
372                 xController->addFilterControllerListener( this );
373             else
374                 xController->removeFilterControllerListener( this );
375         }
376 	}
377 }
378 
379 //------------------------------------------------------------------------
380 void FmFilterAdapter::setText(sal_Int32 nRowPos,
381 							  const FmFilterItem* pFilterItem,
382 							  const ::rtl::OUString& rText)
383 {
384 	FmFormItem* pFormItem = PTR_CAST( FmFormItem, pFilterItem->GetParent()->GetParent() );
385 
386     try
387     {
388         Reference< XFilterController > xController( pFormItem->GetController(), UNO_QUERY_THROW );
389         xController->setPredicateExpression( pFilterItem->GetComponentIndex(), nRowPos, rText );
390     }
391     catch( const Exception& )
392     {
393     	DBG_UNHANDLED_EXCEPTION();
394     }
395 }
396 
397 
398 // XEventListener
399 //------------------------------------------------------------------------
400 void SAL_CALL FmFilterAdapter::disposing(const EventObject& /*e*/) throw( RuntimeException )
401 {
402 }
403 
404 //------------------------------------------------------------------------
405 namespace
406 {
407     ::rtl::OUString lcl_getLabelName_nothrow( const Reference< XControl >& _rxControl )
408     {
409         ::rtl::OUString sLabelName;
410         try
411         {
412             Reference< XControl > xControl( _rxControl, UNO_SET_THROW );
413             Reference< XPropertySet > xModel( xControl->getModel(), UNO_QUERY_THROW );
414             sLabelName = getLabelName( xModel );
415         }
416         catch( const Exception& )
417         {
418         	DBG_UNHANDLED_EXCEPTION();
419         }
420         return sLabelName;
421     }
422 
423     Reference< XPropertySet > lcl_getBoundField_nothrow( const Reference< XControl >& _rxControl )
424     {
425         Reference< XPropertySet > xField;
426         try
427         {
428             Reference< XControl > xControl( _rxControl, UNO_SET_THROW );
429             Reference< XPropertySet > xModelProps( xControl->getModel(), UNO_QUERY_THROW );
430             xField.set( xModelProps->getPropertyValue( FM_PROP_BOUNDFIELD ), UNO_QUERY_THROW );
431         }
432         catch( const Exception& )
433         {
434         	DBG_UNHANDLED_EXCEPTION();
435         }
436         return xField;
437     }
438 }
439 
440 // XFilterControllerListener
441 //------------------------------------------------------------------------
442 void FmFilterAdapter::predicateExpressionChanged( const FilterEvent& _Event ) throw( RuntimeException )
443 {
444     ::vos::OGuard aGuard( Application::GetSolarMutex() );
445 
446     if ( !m_pModel )
447         return;
448 
449     // the controller which sent the event
450     Reference< XFormController > xController( _Event.Source, UNO_QUERY_THROW );
451     Reference< XFilterController > xFilterController( _Event.Source, UNO_QUERY_THROW );
452     Reference< XForm > xForm( xController->getModel(), UNO_QUERY_THROW );
453 
454     FmFormItem* pFormItem = m_pModel->Find( m_pModel->m_aChildren, xForm );
455     OSL_ENSURE( pFormItem, "FmFilterAdapter::predicateExpressionChanged: don't know this form!" );
456     if ( !pFormItem )
457         return;
458 
459     const sal_Int32 nActiveTerm( xFilterController->getActiveTerm() );
460 
461 	FmFilterItems* pFilter = PTR_CAST( FmFilterItems, pFormItem->GetChildren()[ nActiveTerm ] );
462 	FmFilterItem* pFilterItem = pFilter->Find( _Event.FilterComponent );
463 	if ( pFilterItem )
464 	{
465 		if ( _Event.PredicateExpression.getLength())
466 		{
467 			pFilterItem->SetText( _Event.PredicateExpression );
468 			// UI benachrichtigen
469 			FmFilterTextChangedHint aChangeHint(pFilterItem);
470 			m_pModel->Broadcast( aChangeHint );
471 		}
472 		else
473 		{
474 			// no text anymore so remove the condition
475 			m_pModel->Remove(pFilterItem);
476 		}
477 	}
478 	else
479 	{
480 		// searching the component by field name
481 		::rtl::OUString aFieldName( lcl_getLabelName_nothrow( xFilterController->getFilterComponent( _Event.FilterComponent ) ) );
482 
483 		pFilterItem = new FmFilterItem( m_pModel->getORB(), pFilter, aFieldName, _Event.PredicateExpression, _Event.FilterComponent );
484 		m_pModel->Insert(pFilter->GetChildren().end(), pFilterItem);
485 	}
486 
487     // ensure there's one empty term in the filter, just in case the active term was previously empty
488     m_pModel->EnsureEmptyFilterRows( *pFormItem );
489 }
490 
491 //------------------------------------------------------------------------
492 void SAL_CALL FmFilterAdapter::disjunctiveTermRemoved( const FilterEvent& _Event ) throw (RuntimeException)
493 {
494     ::vos::OGuard aGuard( Application::GetSolarMutex() );
495 
496     Reference< XFormController > xController( _Event.Source, UNO_QUERY_THROW );
497     Reference< XFilterController > xFilterController( _Event.Source, UNO_QUERY_THROW );
498     Reference< XForm > xForm( xController->getModel(), UNO_QUERY_THROW );
499 
500     FmFormItem* pFormItem = m_pModel->Find( m_pModel->m_aChildren, xForm );
501     OSL_ENSURE( pFormItem, "FmFilterAdapter::disjunctiveTermRemoved: don't know this form!" );
502     if ( !pFormItem )
503         return;
504 
505 	::std::vector< FmFilterData* >& rTermItems = pFormItem->GetChildren();
506     const bool bValidIndex = ( _Event.DisjunctiveTerm >= 0 ) && ( (size_t)_Event.DisjunctiveTerm < rTermItems.size() );
507     OSL_ENSURE( bValidIndex, "FmFilterAdapter::disjunctiveTermRemoved: invalid term index!" );
508     if ( !bValidIndex )
509         return;
510 
511     // if the first term was removed, then the to-be first term needs its text updated
512     if ( _Event.DisjunctiveTerm == 0 )
513     {
514         rTermItems[1]->SetText( String( SVX_RES( RID_STR_FILTER_FILTER_FOR ) ) );
515         FmFilterTextChangedHint aChangeHint( rTermItems[1] );
516         m_pModel->Broadcast( aChangeHint );
517     }
518 
519     // finally remove the entry from the model
520     m_pModel->Remove( rTermItems.begin() + _Event.DisjunctiveTerm );
521 
522     // ensure there's one empty term in the filter, just in case the currently removed one was the last empty one
523     m_pModel->EnsureEmptyFilterRows( *pFormItem );
524 }
525 
526 //------------------------------------------------------------------------
527 void SAL_CALL FmFilterAdapter::disjunctiveTermAdded( const FilterEvent& _Event ) throw (RuntimeException)
528 {
529     ::vos::OGuard aGuard( Application::GetSolarMutex() );
530 
531     Reference< XFormController > xController( _Event.Source, UNO_QUERY_THROW );
532     Reference< XFilterController > xFilterController( _Event.Source, UNO_QUERY_THROW );
533     Reference< XForm > xForm( xController->getModel(), UNO_QUERY_THROW );
534 
535     FmFormItem* pFormItem = m_pModel->Find( m_pModel->m_aChildren, xForm );
536     OSL_ENSURE( pFormItem, "FmFilterAdapter::disjunctiveTermAdded: don't know this form!" );
537     if ( !pFormItem )
538         return;
539 
540     const sal_Int32 nInsertPos = _Event.DisjunctiveTerm;
541     bool bValidIndex = ( nInsertPos >= 0 ) && ( (size_t)nInsertPos <= pFormItem->GetChildren().size() );
542     if ( !bValidIndex )
543     {
544         OSL_ENSURE( false, "FmFilterAdapter::disjunctiveTermAdded: invalid index!" );
545         return;
546     }
547 
548     const ::std::vector< FmFilterData* >::iterator insertPos = pFormItem->GetChildren().begin() + nInsertPos;
549 
550     FmFilterItems* pFilterItems = new FmFilterItems( m_pModel->getORB(), pFormItem, String( SVX_RES( RID_STR_FILTER_FILTER_OR ) ) );
551     m_pModel->Insert( insertPos, pFilterItems );
552 }
553 
554 //========================================================================
555 // class FmFilterModel
556 //========================================================================
557 TYPEINIT1(FmFilterModel, FmParentData);
558 //------------------------------------------------------------------------
559 FmFilterModel::FmFilterModel(const Reference< XMultiServiceFactory >& _rxFactory)
560 			  :FmParentData(_rxFactory,NULL, ::rtl::OUString())
561 			  ,OSQLParserClient(_rxFactory)
562 			  ,m_xORB(_rxFactory)
563 			  ,m_pAdapter(NULL)
564 			  ,m_pCurrentItems(NULL)
565 {
566 }
567 
568 //------------------------------------------------------------------------
569 FmFilterModel::~FmFilterModel()
570 {
571 	Clear();
572 }
573 
574 //------------------------------------------------------------------------
575 void FmFilterModel::Clear()
576 {
577 	// notify
578 	FilterClearingHint aClearedHint;
579 	Broadcast( aClearedHint );
580 
581 	// loose endings
582 	if (m_pAdapter)
583 	{
584 		m_pAdapter->dispose();
585 		m_pAdapter->release();
586 		m_pAdapter= NULL;
587 	}
588 
589 	m_pCurrentItems  = NULL;
590 	m_xController	 = NULL;
591 	m_xControllers	 = NULL;
592 
593 	for (::std::vector<FmFilterData*>::const_iterator i = m_aChildren.begin();
594 		 i != m_aChildren.end(); i++)
595 		delete (*i);
596 
597 	m_aChildren.clear();
598 }
599 
600 //------------------------------------------------------------------------
601 void FmFilterModel::Update(const Reference< XIndexAccess > & xControllers, const Reference< XFormController > & xCurrent)
602 {
603 	if ( xCurrent == m_xController )
604 		return;
605 
606 	if (!xControllers.is())
607 	{
608 		Clear();
609 		return;
610 	}
611 
612 	// there is only a new current controller
613 	if ( m_xControllers != xControllers )
614 	{
615 		Clear();
616 
617 		m_xControllers = xControllers;
618 		Update(m_xControllers, this);
619 
620 		DBG_ASSERT(xCurrent.is(), "FmFilterModel::Update(...) no current controller");
621 
622 		// Listening for TextChanges
623 		m_pAdapter = new FmFilterAdapter(this, xControllers);
624 		m_pAdapter->acquire();
625 
626 		SetCurrentController(xCurrent);
627 		EnsureEmptyFilterRows( *this );
628 	}
629 	else
630 		SetCurrentController(xCurrent);
631 }
632 
633 //------------------------------------------------------------------------
634 void FmFilterModel::Update(const Reference< XIndexAccess > & xControllers, FmParentData* pParent)
635 {
636     try
637     {
638         sal_Int32 nCount = xControllers->getCount();
639         for ( sal_Int32 i = 0; i < nCount; ++i )
640         {
641             Reference< XFormController > xController( xControllers->getByIndex(i), UNO_QUERY_THROW );
642 
643             Reference< XPropertySet > xFormProperties( xController->getModel(), UNO_QUERY_THROW );
644             ::rtl::OUString aName;
645             OSL_VERIFY( xFormProperties->getPropertyValue( FM_PROP_NAME ) >>= aName );
646 
647             // Insert a new item for the form
648             FmFormItem* pFormItem = new FmFormItem( m_xORB, pParent, xController, aName );
649             Insert( pParent->GetChildren().end(), pFormItem );
650 
651             Reference< XFilterController > xFilterController( pFormItem->GetFilterController(), UNO_SET_THROW );
652 
653             // insert the existing filters for the form
654             String aTitle( SVX_RES( RID_STR_FILTER_FILTER_FOR ) );
655 
656             Sequence< Sequence< ::rtl::OUString > > aExpressions = xFilterController->getPredicateExpressions();
657             for (   const Sequence< ::rtl::OUString >* pConjunctionTerm = aExpressions.getConstArray();
658                     pConjunctionTerm != aExpressions.getConstArray() + aExpressions.getLength();
659                     ++pConjunctionTerm
660                 )
661             {
662                 // we always display one row, even if there's no term to be displayed
663                 FmFilterItems* pFilterItems = new FmFilterItems( m_xORB, pFormItem, aTitle );
664                 Insert( pFormItem->GetChildren().end(), pFilterItems );
665 
666                 const Sequence< ::rtl::OUString >& rDisjunction( *pConjunctionTerm );
667                 for (   const ::rtl::OUString* pDisjunctiveTerm = rDisjunction.getConstArray();
668                         pDisjunctiveTerm != rDisjunction.getConstArray() + rDisjunction.getLength();
669                         ++pDisjunctiveTerm
670                     )
671                 {
672                     if ( pDisjunctiveTerm->getLength() == 0 )
673                         // no condition for this particular component in this particular conjunction term
674                         continue;
675 
676                     const sal_Int32 nComponentIndex = pDisjunctiveTerm - rDisjunction.getConstArray();
677 
678                     // determine the display name of the control
679                     const Reference< XControl > xFilterControl( xFilterController->getFilterComponent( nComponentIndex ) );
680                     const ::rtl::OUString sDisplayName( lcl_getLabelName_nothrow( xFilterControl ) );
681 
682                     // insert a new entry
683                     FmFilterItem* pANDCondition = new FmFilterItem( m_xORB, pFilterItems, sDisplayName, *pDisjunctiveTerm, nComponentIndex );
684                     Insert( pFilterItems->GetChildren().end(), pANDCondition );
685                 }
686 
687                 // title for the next conditions
688                 aTitle = SVX_RES( RID_STR_FILTER_FILTER_OR );
689             }
690 
691             // now add dependent controllers
692             Reference< XIndexAccess > xControllerAsIndex( xController, UNO_QUERY );
693             Update( xControllerAsIndex, pFormItem );
694         }
695     }
696     catch( const Exception& )
697     {
698     	DBG_UNHANDLED_EXCEPTION();
699     }
700 }
701 
702 //------------------------------------------------------------------------
703 FmFormItem* FmFilterModel::Find(const ::std::vector<FmFilterData*>& rItems, const Reference< XFormController > & xController) const
704 {
705 	for (::std::vector<FmFilterData*>::const_iterator i = rItems.begin();
706 		 i != rItems.end(); i++)
707 	{
708 		FmFormItem* pForm = PTR_CAST(FmFormItem,*i);
709 		if (pForm)
710 		{
711 			if ( xController == pForm->GetController() )
712 				return pForm;
713 			else
714 			{
715 				pForm = Find(pForm->GetChildren(), xController);
716 				if (pForm)
717 					return pForm;
718 			}
719 		}
720 	}
721 	return NULL;
722 }
723 
724 //------------------------------------------------------------------------
725 FmFormItem* FmFilterModel::Find(const ::std::vector<FmFilterData*>& rItems, const Reference< XForm >& xForm) const
726 {
727 	for (::std::vector<FmFilterData*>::const_iterator i = rItems.begin();
728 		 i != rItems.end(); i++)
729 	{
730 		FmFormItem* pForm = PTR_CAST(FmFormItem,*i);
731 		if (pForm)
732 		{
733 			if (xForm == pForm->GetController()->getModel())
734 				return pForm;
735 			else
736 			{
737 				pForm = Find(pForm->GetChildren(), xForm);
738 				if (pForm)
739 					return pForm;
740 			}
741 		}
742 	}
743 	return NULL;
744 }
745 
746 //------------------------------------------------------------------------
747 void FmFilterModel::SetCurrentController(const Reference< XFormController > & xCurrent)
748 {
749 	if ( xCurrent == m_xController )
750 		return;
751 
752 	m_xController = xCurrent;
753 
754     FmFormItem* pItem = Find( m_aChildren, xCurrent );
755     if ( !pItem )
756         return;
757 
758     try
759     {
760         Reference< XFilterController > xFilterController( m_xController, UNO_QUERY_THROW );
761         const sal_Int32 nActiveTerm( xFilterController->getActiveTerm() );
762 	    if ( pItem->GetChildren().size() > (size_t)nActiveTerm )
763         {
764 		    SetCurrentItems( static_cast< FmFilterItems* >( pItem->GetChildren()[ nActiveTerm ] ) );
765         }
766     }
767     catch( const Exception& )
768     {
769     	DBG_UNHANDLED_EXCEPTION();
770     }
771 }
772 
773 //------------------------------------------------------------------------
774 void FmFilterModel::AppendFilterItems( FmFormItem& _rFormItem )
775 {
776 	// insert the condition behind the last filter items
777 	::std::vector<FmFilterData*>::reverse_iterator iter;
778     for (   iter = _rFormItem.GetChildren().rbegin();
779 		    iter != _rFormItem.GetChildren().rend();
780             ++iter
781         )
782 	{
783 		if ((*iter)->ISA(FmFilterItems))
784 			break;
785 	}
786 
787     sal_Int32 nInsertPos = iter.base() - _rFormItem.GetChildren().begin();
788 	// delegate this to the FilterController, it will notify us, which will let us update our model
789     try
790     {
791         Reference< XFilterController > xFilterController( _rFormItem.GetFilterController(), UNO_SET_THROW );
792         if ( nInsertPos >= xFilterController->getDisjunctiveTerms() )
793             xFilterController->appendEmptyDisjunctiveTerm();
794     }
795     catch( const Exception& )
796     {
797     	DBG_UNHANDLED_EXCEPTION();
798     }
799 }
800 
801 //------------------------------------------------------------------------
802 void FmFilterModel::Insert(const ::std::vector<FmFilterData*>::iterator& rPos, FmFilterData* pData)
803 {
804 	::std::vector<FmFilterData*>& rItems = pData->GetParent()->GetChildren();
805 	sal_Int32 nPos = rPos == rItems.end() ? LIST_APPEND : rPos - rItems.begin();
806 	rItems.insert(rPos, pData);
807 
808 	// UI benachrichtigen
809 	FmFilterInsertedHint aInsertedHint(pData, nPos);
810 	Broadcast( aInsertedHint );
811 }
812 
813 //------------------------------------------------------------------------
814 void FmFilterModel::Remove(FmFilterData* pData)
815 {
816 	FmParentData* pParent = pData->GetParent();
817 	::std::vector<FmFilterData*>& rItems = pParent->GetChildren();
818 
819 	// erase the item from the model
820 	::std::vector<FmFilterData*>::iterator i = ::std::find(rItems.begin(), rItems.end(), pData);
821 	DBG_ASSERT(i != rItems.end(), "FmFilterModel::Remove(): unknown Item");
822 	// position within the parent
823 	sal_Int32 nPos = i - rItems.begin();
824 	if (pData->ISA(FmFilterItems))
825 	{
826 		FmFormItem* pFormItem = (FmFormItem*)pParent;
827 
828         try
829         {
830             Reference< XFilterController > xFilterController( pFormItem->GetFilterController(), UNO_SET_THROW );
831 
832             bool bEmptyLastTerm = ( ( nPos == 0 ) && xFilterController->getDisjunctiveTerms() == 1 );
833             if ( bEmptyLastTerm )
834             {
835 			    // remove all children (by setting an empty predicate expression)
836 			    ::std::vector< FmFilterData* >& rChildren = ((FmFilterItems*)pData)->GetChildren();
837 			    while ( !rChildren.empty() )
838 			    {
839                     ::std::vector< FmFilterData* >::iterator removePos = rChildren.end() - 1;
840 				    FmFilterItem* pFilterItem = PTR_CAST( FmFilterItem, *removePos );
841 				    m_pAdapter->setText( nPos, pFilterItem, ::rtl::OUString() );
842 				    Remove( removePos );
843                 }
844             }
845             else
846             {
847                 xFilterController->removeDisjunctiveTerm( nPos );
848             }
849         }
850         catch( const Exception& )
851         {
852     	    DBG_UNHANDLED_EXCEPTION();
853         }
854 	}
855 	else // FormItems can not be deleted
856 	{
857 		FmFilterItem* pFilterItem = PTR_CAST(FmFilterItem, pData);
858 
859 		// if its the last condition remove the parent
860 		if (rItems.size() == 1)
861 			Remove(pFilterItem->GetParent());
862 		else
863 		{
864 			// find the position of the father within his father
865 			::std::vector<FmFilterData*>& rParentParentItems = pData->GetParent()->GetParent()->GetChildren();
866 			::std::vector<FmFilterData*>::iterator j = ::std::find(rParentParentItems.begin(), rParentParentItems.end(), pFilterItem->GetParent());
867 			DBG_ASSERT(j != rParentParentItems.end(), "FmFilterModel::Remove(): unknown Item");
868 			sal_Int32 nParentPos = j - rParentParentItems.begin();
869 
870 			// EmptyText removes the filter
871 			m_pAdapter->setText(nParentPos, pFilterItem, ::rtl::OUString());
872 			Remove( i );
873 		}
874 	}
875 }
876 
877 //------------------------------------------------------------------------
878 void FmFilterModel::Remove( const ::std::vector<FmFilterData*>::iterator& rPos )
879 {
880     // remove from parent's child list
881     FmFilterData* pData = *rPos;
882     pData->GetParent()->GetChildren().erase( rPos );
883 
884 	// notify the view, this will remove the actual SvLBoxEntry
885 	FmFilterRemovedHint aRemoveHint( pData );
886 	Broadcast( aRemoveHint );
887 
888 	delete pData;
889 }
890 
891 //------------------------------------------------------------------------
892 sal_Bool FmFilterModel::ValidateText(FmFilterItem* pItem, UniString& rText, UniString& rErrorMsg) const
893 {
894 	FmFormItem* pFormItem = PTR_CAST( FmFormItem, pItem->GetParent()->GetParent() );
895     try
896     {
897         Reference< XFormController > xFormController( pFormItem->GetController() );
898         // obtain the connection of the form belonging to the controller
899         OStaticDataAccessTools aStaticTools;
900         Reference< XRowSet > xRowSet( xFormController->getModel(), UNO_QUERY_THROW );
901         Reference< XConnection > xConnection( aStaticTools.getRowSetConnection( xRowSet ) );
902 
903         // obtain a number formatter for this connection
904         // TODO: shouldn't this be cached?
905         Reference< XNumberFormatsSupplier > xFormatSupplier = aStaticTools.getNumberFormats( xConnection, sal_True );
906         Reference< XNumberFormatter > xFormatter( m_xORB->createInstance( FM_NUMBER_FORMATTER ), UNO_QUERY );
907         xFormatter->attachNumberFormatsSupplier( xFormatSupplier );
908 
909         // get the field (database column) which the item is responsible for
910         Reference< XFilterController > xFilterController( xFormController, UNO_QUERY_THROW );
911         Reference< XPropertySet > xField( lcl_getBoundField_nothrow( xFilterController->getFilterComponent( pItem->GetComponentIndex() ) ), UNO_SET_THROW );
912 
913         // parse the given text as filter predicate
914         ::rtl::OUString aErr, aTxt( rText );
915         ::rtl::Reference< ISQLParseNode > xParseNode = predicateTree( aErr, aTxt, xFormatter, xField );
916         rErrorMsg = aErr;
917         rText = aTxt;
918         if ( xParseNode.is() )
919         {
920 	        ::rtl::OUString aPreparedText;
921 	        Locale aAppLocale = Application::GetSettings().GetUILocale();
922 	        xParseNode->parseNodeToPredicateStr(
923                 aPreparedText, xConnection, xFormatter, xField, aAppLocale, '.', getParseContext() );
924 	        rText = aPreparedText;
925 	        return sal_True;
926         }
927     }
928     catch( const Exception& )
929     {
930     	DBG_UNHANDLED_EXCEPTION();
931     }
932 
933     return sal_False;
934 }
935 
936 //------------------------------------------------------------------------
937 void FmFilterModel::Append(FmFilterItems* pItems, FmFilterItem* pFilterItem)
938 {
939 	Insert(pItems->GetChildren().end(), pFilterItem);
940 }
941 
942 //------------------------------------------------------------------------
943 void FmFilterModel::SetTextForItem(FmFilterItem* pItem, const ::rtl::OUString& rText)
944 {
945 	::std::vector<FmFilterData*>& rItems = pItem->GetParent()->GetParent()->GetChildren();
946 	::std::vector<FmFilterData*>::iterator i = ::std::find(rItems.begin(), rItems.end(), pItem->GetParent());
947 	sal_Int32 nParentPos = i - rItems.begin();
948 
949 	m_pAdapter->setText(nParentPos, pItem, rText);
950 
951 	if (!rText)
952 		Remove(pItem);
953 	else
954 	{
955 		// Change the text
956 		pItem->SetText(rText);
957 		FmFilterTextChangedHint aChangeHint(pItem);
958 		Broadcast( aChangeHint );
959 	}
960 }
961 
962 //------------------------------------------------------------------------
963 void FmFilterModel::SetCurrentItems(FmFilterItems* pCurrent)
964 {
965 	if (m_pCurrentItems == pCurrent)
966 		return;
967 
968 	// search for the condition
969 	if (pCurrent)
970 	{
971 		FmFormItem* pFormItem = (FmFormItem*)pCurrent->GetParent();
972 		::std::vector<FmFilterData*>& rItems = pFormItem->GetChildren();
973 		::std::vector<FmFilterData*>::const_iterator i = ::std::find(rItems.begin(), rItems.end(), pCurrent);
974 
975 		if (i != rItems.end())
976 		{
977 			// determine the filter position
978 			sal_Int32 nPos = i - rItems.begin();
979             try
980             {
981                 Reference< XFilterController > xFilterController( pFormItem->GetFilterController(), UNO_SET_THROW );
982 			    xFilterController->setActiveTerm( nPos );
983             }
984             catch( const Exception& )
985             {
986             	DBG_UNHANDLED_EXCEPTION();
987             }
988 
989 			if ( m_xController != pFormItem->GetController() )
990 				// calls SetCurrentItems again
991 				SetCurrentController( pFormItem->GetController() );
992 			else
993 				m_pCurrentItems = pCurrent;
994 		}
995 		else
996 			m_pCurrentItems = NULL;
997 	}
998 	else
999 		m_pCurrentItems = NULL;
1000 
1001 
1002 	// UI benachrichtigen
1003 	FmFilterCurrentChangedHint aHint;
1004 	Broadcast( aHint );
1005 }
1006 
1007 //------------------------------------------------------------------------
1008 void FmFilterModel::EnsureEmptyFilterRows( FmParentData& _rItem )
1009 {
1010 	// checks whether for each form there's one free level for input
1011 	::std::vector< FmFilterData* >& rChildren = _rItem.GetChildren();
1012 	sal_Bool bAppendLevel = _rItem.ISA( FmFormItem );
1013 
1014 	for (   ::std::vector<FmFilterData*>::iterator i = rChildren.begin();
1015 		    i != rChildren.end();
1016             ++i
1017         )
1018 	{
1019 		FmFilterItems* pItems = PTR_CAST(FmFilterItems, *i);
1020 		if ( pItems && pItems->GetChildren().empty() )
1021 		{
1022 			bAppendLevel = sal_False;
1023 			break;
1024 		}
1025 
1026 		FmFormItem* pFormItem = PTR_CAST(FmFormItem, *i);
1027 		if (pFormItem)
1028 		{
1029 			EnsureEmptyFilterRows( *pFormItem );
1030 			continue;
1031 		}
1032 	}
1033 
1034 	if ( bAppendLevel )
1035     {
1036         FmFormItem* pFormItem = PTR_CAST( FmFormItem, &_rItem );
1037         OSL_ENSURE( pFormItem, "FmFilterModel::EnsureEmptyFilterRows: no FmFormItem, but a FmFilterItems child?" );
1038         if ( pFormItem )
1039 		    AppendFilterItems( *pFormItem );
1040     }
1041 }
1042 
1043 //========================================================================
1044 // class FmFilterItemsString
1045 //========================================================================
1046 class FmFilterItemsString : public SvLBoxString
1047 {
1048 public:
1049 	FmFilterItemsString( SvLBoxEntry* pEntry, sal_uInt16 nFlags,	const XubString& rStr )
1050 		:SvLBoxString(pEntry,nFlags,rStr){}
1051 
1052 	virtual void Paint(const Point& rPos, SvLBox& rDev, sal_uInt16 nFlags, SvLBoxEntry* pEntry);
1053 	virtual void InitViewData( SvLBox* pView,SvLBoxEntry* pEntry, SvViewDataItem* pViewData);
1054 };
1055 
1056 const int nxDBmp = 12;
1057 //------------------------------------------------------------------------
1058 void FmFilterItemsString::Paint(const Point& rPos, SvLBox& rDev, sal_uInt16 /*nFlags*/, SvLBoxEntry* pEntry )
1059 {
1060 	FmFilterItems* pRow = (FmFilterItems*)pEntry->GetUserData();
1061 	FmFormItem* pForm = (FmFormItem*)pRow->GetParent();
1062 
1063     // current filter is significant painted
1064     const bool bIsCurrentFilter = pForm->GetChildren()[ pForm->GetFilterController()->getActiveTerm() ] == pRow;
1065 	if ( bIsCurrentFilter )
1066     {
1067         rDev.Push( PUSH_LINECOLOR );
1068 
1069 		rDev.SetLineColor( rDev.GetTextColor() );
1070 
1071 		Rectangle aRect( rPos, GetSize( &rDev, pEntry ) );
1072 		Point aFirst( rPos.X(), aRect.Bottom() - 6 );
1073 		Point aSecond(aFirst .X() + 2, aFirst.Y() + 3 );
1074 
1075 		rDev.DrawLine( aFirst, aSecond );
1076 
1077 		aFirst = aSecond;
1078 		aFirst.X() += 1;
1079 		aSecond.X() += 6;
1080 		aSecond.Y() -= 5;
1081 
1082 		rDev.DrawLine( aFirst, aSecond );
1083 
1084         rDev.Pop();
1085 	}
1086 
1087 	rDev.DrawText( Point(rPos.X() + nxDBmp, rPos.Y()), GetText() );
1088 }
1089 
1090 //------------------------------------------------------------------------
1091 void FmFilterItemsString::InitViewData( SvLBox* pView,SvLBoxEntry* pEntry, SvViewDataItem* pViewData)
1092 {
1093 	if( !pViewData )
1094 		pViewData = pView->GetViewDataItem( pEntry, this );
1095 
1096 	Size aSize(pView->GetTextWidth(GetText()), pView->GetTextHeight());
1097 	aSize.Width() += nxDBmp;
1098 	pViewData->aSize = aSize;
1099 }
1100 
1101 //========================================================================
1102 // class FmFilterString
1103 //========================================================================
1104 class FmFilterString : public SvLBoxString
1105 {
1106 	UniString m_aName;
1107 
1108 public:
1109 	FmFilterString( SvLBoxEntry* pEntry, sal_uInt16 nFlags, const XubString& rStr, const UniString& aName)
1110 		:SvLBoxString(pEntry,nFlags,rStr)
1111 		,m_aName(aName)
1112 	{
1113 		m_aName.AppendAscii(": ");
1114 	}
1115 
1116 	virtual void Paint(const Point& rPos, SvLBox& rDev, sal_uInt16 nFlags, SvLBoxEntry* pEntry);
1117 	virtual void InitViewData( SvLBox* pView,SvLBoxEntry* pEntry, SvViewDataItem* pViewData);
1118 };
1119 
1120 const int nxD = 4;
1121 
1122 //------------------------------------------------------------------------
1123 void FmFilterString::InitViewData( SvLBox* pView,SvLBoxEntry* pEntry, SvViewDataItem* pViewData)
1124 {
1125 	if( !pViewData )
1126 		pViewData = pView->GetViewDataItem( pEntry, this );
1127 
1128 	Font aOldFont( pView->GetFont());
1129 	Font aFont( aOldFont );
1130 	aFont.SetWeight(WEIGHT_BOLD);
1131 	pView->SetFont( aFont );
1132 
1133 	Size aSize(pView->GetTextWidth(m_aName), pView->GetTextHeight());
1134 	pView->SetFont( aOldFont );
1135 	aSize.Width() += pView->GetTextWidth(GetText()) + nxD;
1136 	pViewData->aSize = aSize;
1137 }
1138 
1139 //------------------------------------------------------------------------
1140 void FmFilterString::Paint(const Point& rPos, SvLBox& rDev, sal_uInt16 /*nFlags*/, SvLBoxEntry* /*pEntry*/ )
1141 {
1142 	Font aOldFont( rDev.GetFont());
1143 	Font aFont( aOldFont );
1144 	aFont.SetWeight(WEIGHT_BOLD);
1145 	rDev.SetFont( aFont );
1146 
1147 	Point aPos(rPos);
1148 	rDev.DrawText( aPos, m_aName );
1149 
1150 	// position for the second text
1151 	aPos.X() += rDev.GetTextWidth(m_aName) + nxD;
1152 	rDev.SetFont( aOldFont );
1153 	rDev.DrawText( aPos, GetText() );
1154 }
1155 
1156 //========================================================================
1157 // class FmFilterNavigator
1158 //========================================================================
1159 FmFilterNavigator::FmFilterNavigator( Window* pParent )
1160 				  :SvTreeListBox( pParent, WB_HASBUTTONS|WB_HASLINES|WB_BORDER|WB_HASBUTTONSATROOT )
1161                   ,m_pModel( NULL )
1162 				  ,m_pEditingCurrently( NULL )
1163 				  ,m_aControlExchange( this )
1164                   ,m_aTimerCounter( 0 )
1165                   ,m_aDropActionType( DA_SCROLLUP )
1166 {
1167 	SetHelpId( HID_FILTER_NAVIGATOR );
1168 
1169 	{
1170 		{
1171 			ImageList aNavigatorImages( SVX_RES( RID_SVXIMGLIST_FMEXPL ) );
1172 			SetNodeBitmaps(
1173 				aNavigatorImages.GetImage( RID_SVXIMG_COLLAPSEDNODE ),
1174 				aNavigatorImages.GetImage( RID_SVXIMG_EXPANDEDNODE ),
1175 				BMP_COLOR_NORMAL
1176 			);
1177 		}
1178 		{
1179 			ImageList aNavigatorImages( SVX_RES( RID_SVXIMGLIST_FMEXPL_HC ) );
1180 			SetNodeBitmaps(
1181 				aNavigatorImages.GetImage( RID_SVXIMG_COLLAPSEDNODE ),
1182 				aNavigatorImages.GetImage( RID_SVXIMG_EXPANDEDNODE ),
1183 				BMP_COLOR_HIGHCONTRAST
1184 			);
1185 		}
1186 	}
1187 
1188 	m_pModel = new FmFilterModel(comphelper::getProcessServiceFactory());
1189 	StartListening( *m_pModel );
1190 
1191 	EnableInplaceEditing( sal_True );
1192 	SetSelectionMode(MULTIPLE_SELECTION);
1193 
1194 	SetDragDropMode(0xFFFF);
1195 
1196 	m_aDropActionTimer.SetTimeoutHdl(LINK(this, FmFilterNavigator, OnDropActionTimer));
1197 }
1198 
1199 //------------------------------------------------------------------------
1200 FmFilterNavigator::~FmFilterNavigator()
1201 {
1202 	EndListening( *m_pModel );
1203 	delete m_pModel;
1204 }
1205 
1206 //------------------------------------------------------------------------
1207 void FmFilterNavigator::Clear()
1208 {
1209 	m_pModel->Clear();
1210 }
1211 
1212 //------------------------------------------------------------------------
1213 void FmFilterNavigator::UpdateContent(const Reference< XIndexAccess > & xControllers, const Reference< XFormController > & xCurrent)
1214 {
1215 	if (xCurrent == m_pModel->GetCurrentController())
1216 		return;
1217 
1218 	m_pModel->Update(xControllers, xCurrent);
1219 
1220 	// expand the filters for the current controller
1221 	SvLBoxEntry* pEntry = FindEntry(m_pModel->GetCurrentForm());
1222 	if (pEntry && !IsExpanded(pEntry))
1223 	{
1224 		SelectAll(sal_False);
1225 
1226 		if (!IsExpanded(pEntry))
1227 			Expand(pEntry);
1228 
1229 		pEntry = FindEntry(m_pModel->GetCurrentItems());
1230 		if (pEntry)
1231 		{
1232 			if (!IsExpanded(pEntry))
1233 				Expand(pEntry);
1234 			Select(pEntry, sal_True);
1235 		}
1236 	}
1237 }
1238 
1239 //------------------------------------------------------------------------
1240 sal_Bool FmFilterNavigator::EditingEntry( SvLBoxEntry* pEntry, Selection& rSelection )
1241 {
1242 	m_pEditingCurrently = pEntry;
1243 	if (!SvTreeListBox::EditingEntry( pEntry, rSelection ))
1244 		return sal_False;
1245 
1246 	return pEntry && ((FmFilterData*)pEntry->GetUserData())->ISA(FmFilterItem);
1247 }
1248 
1249 //------------------------------------------------------------------------
1250 sal_Bool FmFilterNavigator::EditedEntry( SvLBoxEntry* pEntry, const XubString& rNewText )
1251 {
1252 	DBG_ASSERT(pEntry == m_pEditingCurrently, "FmFilterNavigator::EditedEntry: suspicious entry!");
1253 	m_pEditingCurrently = NULL;
1254 
1255 	if (EditingCanceled())
1256 		return sal_True;
1257 
1258 	DBG_ASSERT(((FmFilterData*)pEntry->GetUserData())->ISA(FmFilterItem),
1259 					"FmFilterNavigator::EditedEntry() wrong entry");
1260 
1261 	UniString aText(rNewText);
1262 	aText.EraseTrailingChars();
1263 	aText.EraseLeadingChars();
1264 	if (aText.Len() == 0)
1265 	{
1266 		// deleting the entry asynchron
1267 		sal_uLong nEvent;
1268 		PostUserEvent(nEvent, LINK(this, FmFilterNavigator, OnRemove), pEntry);
1269 	}
1270 	else
1271 	{
1272 		UniString aErrorMsg;
1273 
1274 		if (m_pModel->ValidateText((FmFilterItem*)pEntry->GetUserData(), aText, aErrorMsg))
1275 		{
1276 			GrabFocus();
1277 			// this will set the text at the FmFilterItem, as well as update any filter controls
1278 			// which are connected to this particular entry
1279 			m_pModel->SetTextForItem( static_cast< FmFilterItem* >( pEntry->GetUserData() ), aText );
1280 
1281 			SetCursor( pEntry, sal_True );
1282 			SetEntryText( pEntry, aText );
1283 		}
1284 		else
1285 		{
1286 			// display the error and return sal_False
1287 			SQLContext aError;
1288 			aError.Message = String(SVX_RES(RID_STR_SYNTAXERROR));
1289 			aError.Details = aErrorMsg;
1290 			displayException(aError, this);
1291 
1292 			return sal_False;
1293 		}
1294 	}
1295 	return sal_True;
1296 }
1297 
1298 //------------------------------------------------------------------------
1299 IMPL_LINK( FmFilterNavigator, OnRemove, SvLBoxEntry*, pEntry )
1300 {
1301 	// now remove the entry
1302 	m_pModel->Remove((FmFilterData*) pEntry->GetUserData());
1303 	return 0L;
1304 }
1305 
1306 //------------------------------------------------------------------------
1307 IMPL_LINK( FmFilterNavigator, OnDropActionTimer, void*, EMPTYARG )
1308 {
1309 	if (--m_aTimerCounter > 0)
1310 		return 0L;
1311 
1312 	switch (m_aDropActionType)
1313 	{
1314 		case DA_SCROLLUP :
1315 			ScrollOutputArea(1);
1316 	        m_aTimerCounter = DROP_ACTION_TIMER_SCROLL_TICKS;
1317 			break;
1318 		case DA_SCROLLDOWN :
1319 			ScrollOutputArea(-1);
1320 	        m_aTimerCounter = DROP_ACTION_TIMER_SCROLL_TICKS;
1321 			break;
1322         case DA_EXPANDNODE:
1323 	    {
1324 		    SvLBoxEntry* pToExpand = GetEntry(m_aTimerTriggered);
1325 		    if (pToExpand && (GetChildCount(pToExpand) > 0) &&	!IsExpanded(pToExpand))
1326 			    // tja, eigentlich muesste ich noch testen, ob die Node nicht schon expandiert ist, aber ich
1327 			    // habe dazu weder in den Basisklassen noch im Model eine Methode gefunden ...
1328 			    // aber ich denke, die BK sollte es auch so vertragen
1329 			    Expand(pToExpand);
1330 
1331 		    // nach dem Expand habe ich im Gegensatz zum Scrollen natuerlich nix mehr zu tun
1332 		    m_aDropActionTimer.Stop();
1333 	    }
1334         break;
1335 	}
1336 	return 0L;
1337 }
1338 
1339 
1340 //------------------------------------------------------------------------
1341 sal_Int8 FmFilterNavigator::AcceptDrop( const AcceptDropEvent& rEvt )
1342 {
1343 	Point aDropPos = rEvt.maPosPixel;
1344 
1345 	// kuemmern wir uns erst mal um moeglich DropActions (Scrollen und Aufklappen)
1346 	if (rEvt.mbLeaving)
1347 	{
1348 		if (m_aDropActionTimer.IsActive())
1349 			m_aDropActionTimer.Stop();
1350 	}
1351 	else
1352 	{
1353 		sal_Bool bNeedTrigger = sal_False;
1354 		// auf dem ersten Eintrag ?
1355 		if ((aDropPos.Y() >= 0) && (aDropPos.Y() < GetEntryHeight()))
1356 		{
1357 			m_aDropActionType = DA_SCROLLUP;
1358 			bNeedTrigger = sal_True;
1359 		}
1360 		else
1361 		{
1362 			// auf dem letzten (bzw. in dem Bereich, den ein Eintrag einnehmen wuerde, wenn er unten genau buendig
1363 			// abschliessen wuerde) ?
1364 			if ((aDropPos.Y() < GetSizePixel().Height()) && (aDropPos.Y() >= GetSizePixel().Height() - GetEntryHeight()))
1365 			{
1366 				m_aDropActionType = DA_SCROLLDOWN;
1367 				bNeedTrigger = sal_True;
1368 			}
1369 			else
1370 			{	// is it an entry whith children, and not yet expanded?
1371 				SvLBoxEntry* pDropppedOn = GetEntry(aDropPos);
1372 				if (pDropppedOn && (GetChildCount(pDropppedOn) > 0) && !IsExpanded(pDropppedOn))
1373 				{
1374 					// -> aufklappen
1375 					m_aDropActionType = DA_EXPANDNODE;
1376 					bNeedTrigger = sal_True;
1377 				}
1378 			}
1379 		}
1380 		if (bNeedTrigger && (m_aTimerTriggered != aDropPos))
1381 		{
1382 			// neu anfangen zu zaehlen
1383 			m_aTimerCounter = DROP_ACTION_TIMER_INITIAL_TICKS;
1384 			// die Pos merken, da ich auch QueryDrops bekomme, wenn sich die Maus gar nicht bewegt hat
1385 			m_aTimerTriggered = aDropPos;
1386 			// und den Timer los
1387 			if (!m_aDropActionTimer.IsActive()) // gibt es den Timer schon ?
1388 			{
1389 				m_aDropActionTimer.SetTimeout(DROP_ACTION_TIMER_TICK_BASE);
1390 				m_aDropActionTimer.Start();
1391 			}
1392 		}
1393 		else if (!bNeedTrigger)
1394 			m_aDropActionTimer.Stop();
1395 	}
1396 
1397 
1398 	// Hat das Object das richtige Format?
1399 	if (!m_aControlExchange.isDragSource())
1400 		return DND_ACTION_NONE;
1401 
1402 	if (!m_aControlExchange->hasFormat(GetDataFlavorExVector()))
1403 		return DND_ACTION_NONE;
1404 
1405 	// do we conain the formitem?
1406 	if (!FindEntry(m_aControlExchange->getFormItem()))
1407 		return DND_ACTION_NONE;
1408 
1409 	SvLBoxEntry* pDropTarget = GetEntry(aDropPos);
1410 	if (!pDropTarget)
1411 		return DND_ACTION_NONE;
1412 
1413 	FmFilterData* pData = (FmFilterData*)pDropTarget->GetUserData();
1414 	FmFormItem* pForm = NULL;
1415 	if (pData->ISA(FmFilterItem))
1416 	{
1417 		pForm = PTR_CAST(FmFormItem,pData->GetParent()->GetParent());
1418 		if (pForm != m_aControlExchange->getFormItem())
1419 			return DND_ACTION_NONE;
1420 	}
1421 	else if (pData->ISA(FmFilterItems))
1422 	{
1423 		pForm = PTR_CAST(FmFormItem,pData->GetParent());
1424 		if (pForm != m_aControlExchange->getFormItem())
1425 			return DND_ACTION_NONE;
1426 	}
1427 	else
1428 		return DND_ACTION_NONE;
1429 
1430 	return rEvt.mnAction;
1431 }
1432 // -----------------------------------------------------------------------------
1433 namespace
1434 {
1435 	FmFilterItems* getTargetItems(SvLBoxEntry* _pTarget)
1436 	{
1437 		FmFilterData*	pData = static_cast<FmFilterData*>(_pTarget->GetUserData());
1438 		FmFilterItems*	pTargetItems = pData->ISA(FmFilterItems)
1439 										?
1440 										PTR_CAST(FmFilterItems,pData)
1441 										:
1442 									PTR_CAST(FmFilterItems,pData->GetParent());
1443 		return pTargetItems;
1444 	}
1445 }
1446 //------------------------------------------------------------------------
1447 sal_Int8 FmFilterNavigator::ExecuteDrop( const ExecuteDropEvent& rEvt )
1448 {
1449 	// ware schlecht, wenn nach dem Droppen noch gescrollt wird ...
1450 	if (m_aDropActionTimer.IsActive())
1451 		m_aDropActionTimer.Stop();
1452 
1453 	// Format-Ueberpruefung
1454 	if (!m_aControlExchange.isDragSource())
1455 		return DND_ACTION_NONE;
1456 
1457 	// das Ziel des Drop sowie einige Daten darueber
1458 	Point aDropPos = rEvt.maPosPixel;
1459 	SvLBoxEntry* pDropTarget = GetEntry( aDropPos );
1460 	if (!pDropTarget)
1461 		return DND_ACTION_NONE;
1462 
1463 	// search the container where to add the items
1464 	FmFilterItems*	pTargetItems = getTargetItems(pDropTarget);
1465 	SelectAll(sal_False);
1466 	SvLBoxEntry* pEntry = FindEntry(pTargetItems);
1467 	Select(pEntry, sal_True);
1468 	SetCurEntry(pEntry);
1469 
1470 	insertFilterItem(m_aControlExchange->getDraggedEntries(),pTargetItems,DND_ACTION_COPY == rEvt.mnAction);
1471 
1472 	return sal_True;
1473 }
1474 
1475 //------------------------------------------------------------------------
1476 void FmFilterNavigator::InitEntry(SvLBoxEntry* pEntry,
1477 								  const XubString& rStr,
1478 								  const Image& rImg1,
1479 								  const Image& rImg2,
1480                                                                   SvLBoxButtonKind eButtonKind)
1481 {
1482 	SvTreeListBox::InitEntry( pEntry, rStr, rImg1, rImg2, eButtonKind );
1483 	SvLBoxString* pString = NULL;
1484 
1485 	if (((FmFilterData*)pEntry->GetUserData())->ISA(FmFilterItem))
1486 		pString = new FmFilterString(pEntry, 0, rStr, ((FmFilterItem*)pEntry->GetUserData())->GetFieldName());
1487 	else if (((FmFilterData*)pEntry->GetUserData())->ISA(FmFilterItems))
1488 		pString = new FmFilterItemsString(pEntry, 0, rStr );
1489 
1490 	if (pString)
1491 		pEntry->ReplaceItem( pString, 1 );
1492 }
1493 
1494 //------------------------------------------------------------------------
1495 sal_Bool FmFilterNavigator::Select( SvLBoxEntry* pEntry, sal_Bool bSelect )
1496 {
1497 	if (bSelect == IsSelected(pEntry))	// das passiert manchmal, ich glaube, die Basisklasse geht zu sehr auf Nummer sicher ;)
1498 		return sal_True;
1499 
1500 	if (SvTreeListBox::Select(pEntry, bSelect))
1501 	{
1502 		if (bSelect)
1503 		{
1504 			FmFormItem* pFormItem = NULL;
1505 			if (((FmFilterData*)pEntry->GetUserData())->ISA(FmFilterItem))
1506 				pFormItem = (FmFormItem*)((FmFilterItem*)pEntry->GetUserData())->GetParent()->GetParent();
1507 			else if (((FmFilterData*)pEntry->GetUserData())->ISA(FmFilterItems))
1508 				pFormItem = (FmFormItem*)((FmFilterItem*)pEntry->GetUserData())->GetParent()->GetParent();
1509 			else if (((FmFilterData*)pEntry->GetUserData())->ISA(FmFormItem))
1510 				pFormItem = (FmFormItem*)pEntry->GetUserData();
1511 
1512 			if (pFormItem)
1513 			{
1514 				// will the controller be exchanged?
1515 				if (((FmFilterData*)pEntry->GetUserData())->ISA(FmFilterItem))
1516 					m_pModel->SetCurrentItems((FmFilterItems*)((FmFilterItem*)pEntry->GetUserData())->GetParent());
1517 				else if (((FmFilterData*)pEntry->GetUserData())->ISA(FmFilterItems))
1518 					m_pModel->SetCurrentItems((FmFilterItems*)pEntry->GetUserData());
1519 				else if (((FmFilterData*)pEntry->GetUserData())->ISA(FmFormItem))
1520 					m_pModel->SetCurrentController(((FmFormItem*)pEntry->GetUserData())->GetController());
1521 			}
1522 		}
1523 		return sal_True;
1524 	}
1525 	else
1526 		return sal_False;
1527 }
1528 
1529 //------------------------------------------------------------------------
1530 void FmFilterNavigator::Notify( SfxBroadcaster& /*rBC*/, const SfxHint& rHint )
1531 {
1532 	if (rHint.ISA(FmFilterInsertedHint))
1533 	{
1534 		FmFilterInsertedHint* pHint = (FmFilterInsertedHint*)&rHint;
1535 		Insert(pHint->GetData(), pHint->GetPos());
1536 	}
1537 	else if( rHint.ISA(FilterClearingHint) )
1538 	{
1539 		SvTreeListBox::Clear();
1540 	}
1541 	else if( rHint.ISA(FmFilterRemovedHint) )
1542 	{
1543 		FmFilterRemovedHint* pHint = (FmFilterRemovedHint*)&rHint;
1544 		Remove(pHint->GetData());
1545 	}
1546 	else if( rHint.ISA(FmFilterTextChangedHint) )
1547 	{
1548 		FmFilterTextChangedHint* pHint = (FmFilterTextChangedHint*)&rHint;
1549 		SvLBoxEntry* pEntry = FindEntry(pHint->GetData());
1550 		if (pEntry)
1551 			SetEntryText( pEntry, pHint->GetData()->GetText());
1552 	}
1553 	else if( rHint.ISA(FmFilterCurrentChangedHint) )
1554 	{
1555 		// invalidate the entries
1556 		for (SvLBoxEntry* pEntry = First(); pEntry != NULL;
1557 			 pEntry = Next(pEntry))
1558 			GetModel()->InvalidateEntry( pEntry );
1559 	}
1560 }
1561 
1562 //------------------------------------------------------------------------
1563 SvLBoxEntry* FmFilterNavigator::FindEntry(const FmFilterData* pItem) const
1564 {
1565 	SvLBoxEntry* pEntry = NULL;
1566 	if (pItem)
1567 	{
1568 		for (pEntry = First(); pEntry != NULL; pEntry = Next( pEntry ))
1569 		{
1570 			FmFilterData* pEntryItem = (FmFilterData*)pEntry->GetUserData();
1571 			if (pEntryItem == pItem)
1572 				break;
1573 		}
1574 	}
1575 	return pEntry;
1576 }
1577 
1578 //------------------------------------------------------------------------
1579 void FmFilterNavigator::Insert(FmFilterData* pItem, sal_Int32 nPos)
1580 {
1581 	const FmParentData* pParent = pItem->GetParent() ? pItem->GetParent() : GetFilterModel();
1582 
1583 	// insert the item
1584 	SvLBoxEntry* pParentEntry = FindEntry( pParent );
1585 	SvLBoxEntry* pNewEntry = InsertEntry(pItem->GetText(), pItem->GetImage(), pItem->GetImage(), pParentEntry, sal_False, nPos, pItem );
1586 	if ( pNewEntry )
1587 	{
1588 		SetExpandedEntryBmp( pNewEntry, pItem->GetImage( BMP_COLOR_HIGHCONTRAST ), BMP_COLOR_HIGHCONTRAST );
1589 		SetCollapsedEntryBmp( pNewEntry, pItem->GetImage( BMP_COLOR_HIGHCONTRAST ), BMP_COLOR_HIGHCONTRAST );
1590 	}
1591     if ( pParentEntry )
1592         Expand( pParentEntry );
1593 }
1594 
1595 //------------------------------------------------------------------------
1596 void FmFilterNavigator::Remove(FmFilterData* pItem)
1597 {
1598 	// der Entry zu den Daten
1599 	SvLBoxEntry* pEntry = FindEntry(pItem);
1600 
1601 	if (pEntry == m_pEditingCurrently)
1602 		// cancel editing
1603 		EndEditing(sal_True);
1604 
1605 	if (pEntry)
1606 		GetModel()->Remove( pEntry );
1607 }
1608 // -----------------------------------------------------------------------------
1609 FmFormItem* FmFilterNavigator::getSelectedFilterItems(::std::vector<FmFilterItem*>& _rItemList)
1610 {
1611 	// be sure that the data is only used within only one form!
1612 	FmFormItem* pFirstItem = NULL;
1613 
1614 	sal_Bool bHandled = sal_True;
1615 	sal_Bool bFoundSomething = sal_False;
1616 	for (SvLBoxEntry* pEntry = FirstSelected();
1617 		 bHandled && pEntry != NULL;
1618 		 pEntry = NextSelected(pEntry))
1619 	{
1620 		FmFilterItem* pFilter = PTR_CAST(FmFilterItem, (FmFilterData*)pEntry->GetUserData());
1621 		if (pFilter)
1622 		{
1623 			FmFormItem* pForm = PTR_CAST(FmFormItem,pFilter->GetParent()->GetParent());
1624 			if (!pForm)
1625 				bHandled = sal_False;
1626 			else if (!pFirstItem)
1627 				pFirstItem = pForm;
1628 			else if (pFirstItem != pForm)
1629 				bHandled = sal_False;
1630 
1631 			if (bHandled)
1632 			{
1633 				_rItemList.push_back(pFilter);
1634 				bFoundSomething = sal_True;
1635 			}
1636 		}
1637 	}
1638 	if ( !bHandled || !bFoundSomething )
1639 		pFirstItem = NULL;
1640 	return pFirstItem;
1641 }
1642 // -----------------------------------------------------------------------------
1643 void FmFilterNavigator::insertFilterItem(const ::std::vector<FmFilterItem*>& _rFilterList,FmFilterItems* _pTargetItems,sal_Bool _bCopy)
1644 {
1645 	::std::vector<FmFilterItem*>::const_iterator aEnd = _rFilterList.end();
1646 	for (   ::std::vector< FmFilterItem* >::const_iterator i = _rFilterList.begin();
1647             i != aEnd;
1648             ++i
1649         )
1650 	{
1651         FmFilterItem* pLookupItem( *i );
1652 		if ( pLookupItem->GetParent() == _pTargetItems )
1653 			continue;
1654 
1655 		FmFilterItem* pFilterItem = _pTargetItems->Find( pLookupItem->GetComponentIndex() );
1656 		String aText = pLookupItem->GetText();
1657 		if ( !pFilterItem )
1658 		{
1659 			pFilterItem = new FmFilterItem( m_pModel->getORB(), _pTargetItems, pLookupItem->GetFieldName(), aText, pLookupItem->GetComponentIndex() );
1660 			m_pModel->Append( _pTargetItems, pFilterItem );
1661 		}
1662 
1663 		if ( !_bCopy )
1664 			m_pModel->Remove( pLookupItem );
1665 
1666 		// now set the text for the new dragged item
1667 		m_pModel->SetTextForItem( pFilterItem, aText );
1668 	}
1669 
1670 	m_pModel->EnsureEmptyFilterRows( *_pTargetItems->GetParent() );
1671 }
1672 
1673 //------------------------------------------------------------------------------
1674 void FmFilterNavigator::StartDrag( sal_Int8 /*_nAction*/, const Point& /*_rPosPixel*/ )
1675 {
1676 	EndSelection();
1677 
1678 	// be sure that the data is only used within a only one form!
1679 	m_aControlExchange.prepareDrag();
1680 
1681 	::std::vector<FmFilterItem*> aItemList;
1682 	if ( FmFormItem* pFirstItem = getSelectedFilterItems(aItemList) )
1683 	{
1684 		m_aControlExchange->setDraggedEntries(aItemList);
1685 		m_aControlExchange->setFormItem(pFirstItem);
1686 		m_aControlExchange.startDrag( DND_ACTION_COPYMOVE );
1687 	}
1688 }
1689 
1690 //------------------------------------------------------------------------------
1691 void FmFilterNavigator::Command( const CommandEvent& rEvt )
1692 {
1693 	sal_Bool bHandled = sal_False;
1694 	switch (rEvt.GetCommand())
1695 	{
1696 		case COMMAND_CONTEXTMENU:
1697 		{
1698 			// die Stelle, an der geklickt wurde
1699 			Point aWhere;
1700 			SvLBoxEntry* pClicked = NULL;
1701 			if (rEvt.IsMouseEvent())
1702 			{
1703 				aWhere = rEvt.GetMousePosPixel();
1704 				pClicked = GetEntry(aWhere);
1705 				if (pClicked == NULL)
1706 					break;
1707 
1708 				if (!IsSelected(pClicked))
1709 				{
1710 					SelectAll(sal_False);
1711 					Select(pClicked, sal_True);
1712 					SetCurEntry(pClicked);
1713 				}
1714 			}
1715 			else
1716 			{
1717 				pClicked = GetCurEntry();
1718 				if (!pClicked)
1719 					break;
1720 				aWhere = GetEntryPosition( pClicked );
1721 			}
1722 
1723 			::std::vector<FmFilterData*> aSelectList;
1724 			for (SvLBoxEntry* pEntry = FirstSelected();
1725 				 pEntry != NULL;
1726 				 pEntry = NextSelected(pEntry))
1727 			{
1728 				// don't delete forms
1729 				FmFormItem* pForm = PTR_CAST(FmFormItem, (FmFilterData*)pEntry->GetUserData());
1730 				if (!pForm)
1731 					aSelectList.push_back((FmFilterData*)pEntry->GetUserData());
1732 			}
1733 			if (aSelectList.size() == 1)
1734 			{
1735 				// don't delete the only empty row of a form
1736 				FmFilterItems* pFilterItems = PTR_CAST(FmFilterItems, aSelectList[0]);
1737 				if (pFilterItems && pFilterItems->GetChildren().empty()
1738 					&& pFilterItems->GetParent()->GetChildren().size() == 1)
1739 					aSelectList.clear();
1740 			}
1741 
1742 			PopupMenu aContextMenu(SVX_RES(RID_FM_FILTER_MENU));
1743 
1744 			// every condition could be deleted except the first one if its the only one
1745 			aContextMenu.EnableItem( SID_FM_DELETE, !aSelectList.empty() );
1746 
1747 			//
1748 			sal_Bool bEdit = PTR_CAST(FmFilterItem, (FmFilterData*)pClicked->GetUserData()) != NULL &&
1749 				IsSelected(pClicked) && GetSelectionCount() == 1;
1750 
1751 			aContextMenu.EnableItem( SID_FM_FILTER_EDIT,
1752 				bEdit );
1753 			aContextMenu.EnableItem( SID_FM_FILTER_IS_NULL,
1754 				bEdit );
1755 			aContextMenu.EnableItem( SID_FM_FILTER_IS_NOT_NULL,
1756 				bEdit );
1757 
1758 			aContextMenu.RemoveDisabledEntries(sal_True, sal_True);
1759 			sal_uInt16 nSlotId = aContextMenu.Execute( this, aWhere );
1760 			switch( nSlotId )
1761 			{
1762 				case SID_FM_FILTER_EDIT:
1763 				{
1764 					EditEntry( pClicked );
1765 				}	break;
1766 				case SID_FM_FILTER_IS_NULL:
1767 				case SID_FM_FILTER_IS_NOT_NULL:
1768 				{
1769 					UniString aErrorMsg;
1770 					UniString aText;
1771 					if (nSlotId == SID_FM_FILTER_IS_NULL)
1772 						aText.AssignAscii("IS NULL");
1773 					else
1774 						aText.AssignAscii("IS NOT NULL");
1775 
1776 					m_pModel->ValidateText((FmFilterItem*)pClicked->GetUserData(),
1777 											aText, aErrorMsg);
1778 					m_pModel->SetTextForItem((FmFilterItem*)pClicked->GetUserData(), aText);
1779 				}	break;
1780 				case SID_FM_DELETE:
1781 				{
1782 					DeleteSelection();
1783 				}	break;
1784 			}
1785 			bHandled = sal_True;
1786 		} break;
1787 	}
1788 
1789 	if (!bHandled)
1790 		SvTreeListBox::Command( rEvt );
1791 }
1792 // -----------------------------------------------------------------------------
1793 SvLBoxEntry* FmFilterNavigator::getNextEntry(SvLBoxEntry* _pStartWith)
1794 {
1795 	SvLBoxEntry* pEntry = _pStartWith ? _pStartWith : LastSelected();
1796 	pEntry = Next(pEntry);
1797 	// we need the next filter entry
1798 	while( pEntry && GetChildCount( pEntry ) == 0 && pEntry != Last() )
1799 		pEntry = Next(pEntry);
1800 	return pEntry;
1801 }
1802 // -----------------------------------------------------------------------------
1803 SvLBoxEntry* FmFilterNavigator::getPrevEntry(SvLBoxEntry* _pStartWith)
1804 {
1805 	SvLBoxEntry* pEntry = _pStartWith ? _pStartWith : FirstSelected();
1806 	pEntry = Prev(pEntry);
1807 	// check if the previous entry is a filter, if so get the next prev
1808 	if ( pEntry && GetChildCount( pEntry ) != 0 )
1809 	{
1810 		pEntry = Prev(pEntry);
1811 		// if the entry is still no leaf return
1812 		if ( pEntry && GetChildCount( pEntry ) != 0 )
1813 			pEntry = NULL;
1814 	}
1815 	return pEntry;
1816 }
1817 //------------------------------------------------------------------------
1818 void FmFilterNavigator::KeyInput(const KeyEvent& rKEvt)
1819 {
1820 	const KeyCode&  rKeyCode = rKEvt.GetKeyCode();
1821 
1822     switch ( rKeyCode.GetCode() )
1823     {
1824     case KEY_UP:
1825     case KEY_DOWN:
1826     {
1827         if ( !rKeyCode.IsMod1() || !rKeyCode.IsMod2() || rKeyCode.IsShift() )
1828             break;
1829 
1830         ::std::vector<FmFilterItem*> aItemList;
1831 		if ( !getSelectedFilterItems( aItemList ) )
1832             break;
1833 
1834 		::std::mem_fun1_t<SvLBoxEntry*,FmFilterNavigator,SvLBoxEntry*> getter = ::std::mem_fun(&FmFilterNavigator::getNextEntry);
1835 		if ( rKeyCode.GetCode() == KEY_UP )
1836 			getter = ::std::mem_fun(&FmFilterNavigator::getPrevEntry);
1837 
1838 		SvLBoxEntry* pTarget = getter( this, NULL );
1839 		if ( !pTarget )
1840             break;
1841 
1842         FmFilterItems* pTargetItems = getTargetItems( pTarget );
1843 		if ( !pTargetItems )
1844             break;
1845 
1846         ::std::vector<FmFilterItem*>::const_iterator aEnd = aItemList.end();
1847 		sal_Bool bNextTargetItem = sal_True;
1848 		while ( bNextTargetItem )
1849 		{
1850 			::std::vector<FmFilterItem*>::const_iterator i = aItemList.begin();
1851 			for (; i != aEnd; ++i)
1852 			{
1853 				if ( (*i)->GetParent() == pTargetItems )
1854 				{
1855 					pTarget = getter(this,pTarget);
1856 					if ( !pTarget )
1857 						return;
1858 					pTargetItems = getTargetItems( pTarget );
1859 					break;
1860 				}
1861 				else
1862 				{
1863 					FmFilterItem* pFilterItem = pTargetItems->Find( (*i)->GetComponentIndex() );
1864 					// we found the text component so jump above
1865 					if ( pFilterItem )
1866 					{
1867 						pTarget = getter( this, pTarget );
1868 						if ( !pTarget )
1869 							return;
1870 
1871                         pTargetItems = getTargetItems( pTarget );
1872 						break;
1873 					}
1874 				}
1875 			}
1876 			bNextTargetItem = i != aEnd && pTargetItems;
1877 		}
1878 
1879 		if ( pTargetItems )
1880 		{
1881 			insertFilterItem( aItemList, pTargetItems );
1882 			return;
1883 		}
1884     }
1885     break;
1886 
1887     case KEY_DELETE:
1888     {
1889         if ( rKeyCode.GetModifier() )
1890             break;
1891 
1892         if ( !IsSelected( First() ) || GetEntryCount() > 1 )
1893 			DeleteSelection();
1894 		return;
1895     }
1896     }
1897 
1898     SvTreeListBox::KeyInput(rKEvt);
1899 }
1900 
1901 //------------------------------------------------------------------------------
1902 void FmFilterNavigator::DeleteSelection()
1903 {
1904 	// to avoid the deletion of an entry twice (e.g. deletion of a parent and afterward
1905 	// the deletion of it's child, i have to shrink the selecton list
1906 	::std::vector<SvLBoxEntry*> aEntryList;
1907 	for (SvLBoxEntry* pEntry = FirstSelected();
1908 		 pEntry != NULL;
1909 		 pEntry = NextSelected(pEntry))
1910 	{
1911 		FmFilterItem* pFilterItem = PTR_CAST(FmFilterItem, (FmFilterData*)pEntry->GetUserData());
1912 		if (pFilterItem && IsSelected(GetParent(pEntry)))
1913 			continue;
1914 
1915 		FmFormItem* pForm = PTR_CAST(FmFormItem, (FmFilterData*)pEntry->GetUserData());
1916 		if (!pForm)
1917 			aEntryList.push_back(pEntry);
1918 	}
1919 
1920 	// Remove the selection
1921 	SelectAll(sal_False);
1922 
1923 	for (::std::vector<SvLBoxEntry*>::reverse_iterator i = aEntryList.rbegin();
1924 		// link problems with operator ==
1925 		i.base() != aEntryList.rend().base(); i++)
1926 	{
1927 		m_pModel->Remove((FmFilterData*)(*i)->GetUserData());
1928 	}
1929 }
1930 // -----------------------------------------------------------------------------
1931 
1932 //========================================================================
1933 // class FmFilterNavigatorWin
1934 //========================================================================
1935 FmFilterNavigatorWin::FmFilterNavigatorWin( SfxBindings* _pBindings, SfxChildWindow* _pMgr,
1936 							  Window* _pParent )
1937 					 :SfxDockingWindow( _pBindings, _pMgr, _pParent, WinBits(WB_STDMODELESS|WB_SIZEABLE|WB_ROLLABLE|WB_3DLOOK|WB_DOCKABLE) )
1938 					 ,SfxControllerItem( SID_FM_FILTER_NAVIGATOR_CONTROL, *_pBindings )
1939 {
1940 	SetHelpId( HID_FILTER_NAVIGATOR_WIN );
1941 
1942 	m_pNavigator = new FmFilterNavigator( this );
1943 	m_pNavigator->Show();
1944 	SetText( SVX_RES(RID_STR_FILTER_NAVIGATOR) );
1945 	SfxDockingWindow::SetFloatingSize( Size(200,200) );
1946 }
1947 
1948 //------------------------------------------------------------------------
1949 FmFilterNavigatorWin::~FmFilterNavigatorWin()
1950 {
1951 	delete m_pNavigator;
1952 }
1953 
1954 //-----------------------------------------------------------------------
1955 void FmFilterNavigatorWin::UpdateContent(FmFormShell* pFormShell)
1956 {
1957 	if (!pFormShell)
1958 		m_pNavigator->UpdateContent( NULL, NULL );
1959 	else
1960 	{
1961 		Reference< XFormController >  xController(pFormShell->GetImpl()->getActiveInternalController());
1962 		Reference< XIndexAccess >	xContainer;
1963 		if (xController.is())
1964 		{
1965 			Reference< XChild >  xChild(xController, UNO_QUERY);
1966 			for (Reference< XInterface >  xParent(xChild->getParent());
1967 				 xParent.is();
1968 				 xParent = xChild.is() ? xChild->getParent() : Reference< XInterface > ())
1969 			{
1970 				xContainer = Reference< XIndexAccess > (xParent, UNO_QUERY);
1971 				xChild = Reference< XChild > (xParent, UNO_QUERY);
1972 			}
1973 		}
1974 		m_pNavigator->UpdateContent(xContainer, xController);
1975 	}
1976 }
1977 
1978 //-----------------------------------------------------------------------
1979 void FmFilterNavigatorWin::StateChanged( sal_uInt16 nSID, SfxItemState eState, const SfxPoolItem* pState )
1980 {
1981 	if( !pState  || SID_FM_FILTER_NAVIGATOR_CONTROL != nSID )
1982 		return;
1983 
1984 	if( eState >= SFX_ITEM_AVAILABLE )
1985 	{
1986 		FmFormShell* pShell = PTR_CAST( FmFormShell,((SfxObjectItem*)pState)->GetShell() );
1987 		UpdateContent( pShell );
1988 	}
1989 	else
1990 		UpdateContent( NULL );
1991 }
1992 
1993 //-----------------------------------------------------------------------
1994 sal_Bool FmFilterNavigatorWin::Close()
1995 {
1996 	if ( m_pNavigator && m_pNavigator->IsEditingActive() )
1997 		m_pNavigator->EndEditing();
1998 
1999 	if ( m_pNavigator && m_pNavigator->IsEditingActive() )
2000 		// the EndEditing was vetoed (perhaps of an syntax error or such)
2001 		return sal_False;
2002 
2003 	UpdateContent( NULL );
2004 	return SfxDockingWindow::Close();
2005 }
2006 
2007 //-----------------------------------------------------------------------
2008 void FmFilterNavigatorWin::FillInfo( SfxChildWinInfo& rInfo ) const
2009 {
2010 	SfxDockingWindow::FillInfo( rInfo );
2011 	rInfo.bVisible = sal_False;
2012 }
2013 
2014 //-----------------------------------------------------------------------
2015 Size FmFilterNavigatorWin::CalcDockingSize( SfxChildAlignment eAlign )
2016 {
2017 	if ( ( eAlign == SFX_ALIGN_TOP ) || ( eAlign == SFX_ALIGN_BOTTOM ) )
2018 		return Size();
2019 
2020     return SfxDockingWindow::CalcDockingSize( eAlign );
2021 }
2022 
2023 //-----------------------------------------------------------------------
2024 SfxChildAlignment FmFilterNavigatorWin::CheckAlignment( SfxChildAlignment eActAlign, SfxChildAlignment eAlign )
2025 {
2026 	switch (eAlign)
2027 	{
2028 		case SFX_ALIGN_LEFT:
2029 		case SFX_ALIGN_RIGHT:
2030 		case SFX_ALIGN_NOALIGNMENT:
2031 			return (eAlign);
2032         default:
2033             break;
2034 	}
2035 
2036 	return (eActAlign);
2037 }
2038 
2039 //------------------------------------------------------------------------
2040 void FmFilterNavigatorWin::Resize()
2041 {
2042 	SfxDockingWindow::Resize();
2043 
2044 	Size aLogOutputSize = PixelToLogic( GetOutputSizePixel(), MAP_APPFONT );
2045 	Size aLogExplSize = aLogOutputSize;
2046 	aLogExplSize.Width() -= 6;
2047 	aLogExplSize.Height() -= 6;
2048 
2049 	Point aExplPos = LogicToPixel( Point(3,3), MAP_APPFONT );
2050 	Size aExplSize = LogicToPixel( aLogExplSize, MAP_APPFONT );
2051 
2052 	m_pNavigator->SetPosSizePixel( aExplPos, aExplSize );
2053 }
2054 // -----------------------------------------------------------------------------
2055 void FmFilterNavigatorWin::GetFocus()
2056 {
2057 	// oj #97405#
2058 	if ( m_pNavigator )
2059 		m_pNavigator->GrabFocus();
2060 }
2061 // -----------------------------------------------------------------------------
2062 
2063 
2064 //========================================================================
2065 // class FmFilterNavigatorWinMgr
2066 //========================================================================
2067 SFX_IMPL_DOCKINGWINDOW( FmFilterNavigatorWinMgr, SID_FM_FILTER_NAVIGATOR )
2068 
2069 //-----------------------------------------------------------------------
2070 FmFilterNavigatorWinMgr::FmFilterNavigatorWinMgr( Window *_pParent, sal_uInt16 _nId,
2071 									SfxBindings *_pBindings, SfxChildWinInfo* _pInfo )
2072 				 :SfxChildWindow( _pParent, _nId )
2073 {
2074 	pWindow = new FmFilterNavigatorWin( _pBindings, this, _pParent );
2075 	eChildAlignment = SFX_ALIGN_NOALIGNMENT;
2076 	((SfxDockingWindow*)pWindow)->Initialize( _pInfo );
2077 }
2078 
2079 //........................................................................
2080 }	// namespace svxform
2081 //........................................................................
2082