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