xref: /AOO41X/main/svx/source/form/filtnav.cxx (revision 24c56ab9f1bd1305754aa2f564704f38ff57627e)
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 //========================================================================
OFilterItemExchange()114 OFilterItemExchange::OFilterItemExchange()
115 {
116 }
117 
118 //------------------------------------------------------------------------
AddSupportedFormats()119 void OFilterItemExchange::AddSupportedFormats()
120 {
121     AddFormat(getFormatId());
122 }
123 
124 //------------------------------------------------------------------------
getFormatId()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 //------------------------------------------------------------------------
createExchange() const137 OLocalExchange* OFilterExchangeHelper::createExchange() const
138 {
139     return new OFilterItemExchange;
140 }
141 
142 //========================================================================
143 TYPEINIT0(FmFilterData);
GetImage(BmpColorMode) const144 Image FmFilterData::GetImage( BmpColorMode /*_eMode*/ ) const
145 {
146     return Image();
147 }
148 
149 //========================================================================
150 TYPEINIT1(FmParentData, FmFilterData);
151 //------------------------------------------------------------------------
~FmParentData()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 //------------------------------------------------------------------------
GetImage(BmpColorMode _eMode) const162 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 //------------------------------------------------------------------------
Find(const::sal_Int32 _nFilterComponentIndex) const181 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 //------------------------------------------------------------------------
GetImage(BmpColorMode _eMode) const197 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 //------------------------------------------------------------------------
FmFilterItem(const Reference<XMultiServiceFactory> & _rxFactory,FmFilterItems * pParent,const::rtl::OUString & aFieldName,const::rtl::OUString & aText,const sal_Int32 _nComponentIndex)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 //------------------------------------------------------------------------
GetImage(BmpColorMode _eMode) const228 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();
FmFilterHint(FmFilterData * pData)253     FmFilterHint(FmFilterData* pData):m_pData(pData){}
GetData() const254     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();
FmFilterInsertedHint(FmFilterData * pData,sal_Int32 nRelPos)265     FmFilterInsertedHint(FmFilterData* pData, sal_Int32 nRelPos)
266         :FmFilterHint(pData)
267         ,m_nPos(nRelPos){}
268 
GetPos() const269     sal_Int32 GetPos() const { return m_nPos; }
270 };
271 TYPEINIT1( FmFilterInsertedHint, FmFilterHint );
272 
273 //========================================================================
274 class FmFilterRemovedHint : public FmFilterHint
275 {
276 public:
277     TYPEINFO();
FmFilterRemovedHint(FmFilterData * pData)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();
FmFilterTextChangedHint(FmFilterData * pData)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();
FilterClearingHint()300     FilterClearingHint(){}
301 };
302 TYPEINIT1( FilterClearingHint, SfxHint );
303 
304 //========================================================================
305 class FmFilterCurrentChangedHint : public SfxHint
306 {
307 public:
308     TYPEINFO();
FmFilterCurrentChangedHint()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 //------------------------------------------------------------------------
FmFilterAdapter(FmFilterModel * pModel,const Reference<XIndexAccess> & xControllers)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 //------------------------------------------------------------------------
dispose()351 void FmFilterAdapter::dispose() throw( RuntimeException )
352 {
353     AddOrRemoveListener( m_xControllers, false );
354 }
355 
356 //------------------------------------------------------------------------
AddOrRemoveListener(const Reference<XIndexAccess> & _rxControllers,const bool _bAdd)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 //------------------------------------------------------------------------
setText(sal_Int32 nRowPos,const FmFilterItem * pFilterItem,const::rtl::OUString & rText)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 //------------------------------------------------------------------------
disposing(const EventObject &)400 void SAL_CALL FmFilterAdapter::disposing(const EventObject& /*e*/) throw( RuntimeException )
401 {
402 }
403 
404 //------------------------------------------------------------------------
405 namespace
406 {
lcl_getLabelName_nothrow(const Reference<XControl> & _rxControl)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 
lcl_getBoundField_nothrow(const Reference<XControl> & _rxControl)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 //------------------------------------------------------------------------
predicateExpressionChanged(const FilterEvent & _Event)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 //------------------------------------------------------------------------
disjunctiveTermRemoved(const FilterEvent & _Event)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 //------------------------------------------------------------------------
disjunctiveTermAdded(const FilterEvent & _Event)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 //------------------------------------------------------------------------
FmFilterModel(const Reference<XMultiServiceFactory> & _rxFactory)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 //------------------------------------------------------------------------
~FmFilterModel()569 FmFilterModel::~FmFilterModel()
570 {
571     Clear();
572 }
573 
574 //------------------------------------------------------------------------
Clear()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 //------------------------------------------------------------------------
Update(const Reference<XIndexAccess> & xControllers,const Reference<XFormController> & xCurrent)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 //------------------------------------------------------------------------
Update(const Reference<XIndexAccess> & xControllers,FmParentData * pParent)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 //------------------------------------------------------------------------
Find(const::std::vector<FmFilterData * > & rItems,const Reference<XFormController> & xController) const703 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 //------------------------------------------------------------------------
Find(const::std::vector<FmFilterData * > & rItems,const Reference<XForm> & xForm) const725 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 //------------------------------------------------------------------------
SetCurrentController(const Reference<XFormController> & xCurrent)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 //------------------------------------------------------------------------
AppendFilterItems(FmFormItem & _rFormItem)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 //------------------------------------------------------------------------
Insert(const::std::vector<FmFilterData * >::iterator & rPos,FmFilterData * pData)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 //------------------------------------------------------------------------
Remove(FmFilterData * pData)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 //------------------------------------------------------------------------
Remove(const::std::vector<FmFilterData * >::iterator & rPos)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 //------------------------------------------------------------------------
ValidateText(FmFilterItem * pItem,UniString & rText,UniString & rErrorMsg) const892 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 //------------------------------------------------------------------------
Append(FmFilterItems * pItems,FmFilterItem * pFilterItem)937 void FmFilterModel::Append(FmFilterItems* pItems, FmFilterItem* pFilterItem)
938 {
939     Insert(pItems->GetChildren().end(), pFilterItem);
940 }
941 
942 //------------------------------------------------------------------------
SetTextForItem(FmFilterItem * pItem,const::rtl::OUString & rText)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.isEmpty() )
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 //------------------------------------------------------------------------
SetCurrentItems(FmFilterItems * pCurrent)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 //------------------------------------------------------------------------
EnsureEmptyFilterRows(FmParentData & _rItem)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:
FmFilterItemsString(SvLBoxEntry * pEntry,sal_uInt16 nFlags,const XubString & rStr)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 //------------------------------------------------------------------------
Paint(const Point & rPos,SvLBox & rDev,sal_uInt16,SvLBoxEntry * pEntry)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 //------------------------------------------------------------------------
InitViewData(SvLBox * pView,SvLBoxEntry * pEntry,SvViewDataItem * pViewData)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:
FmFilterString(SvLBoxEntry * pEntry,sal_uInt16 nFlags,const XubString & rStr,const UniString & aName)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 //------------------------------------------------------------------------
InitViewData(SvLBox * pView,SvLBoxEntry * pEntry,SvViewDataItem * pViewData)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 //------------------------------------------------------------------------
Paint(const Point & rPos,SvLBox & rDev,sal_uInt16,SvLBoxEntry *)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 //========================================================================
FmFilterNavigator(Window * pParent)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 //------------------------------------------------------------------------
~FmFilterNavigator()1200 FmFilterNavigator::~FmFilterNavigator()
1201 {
1202     EndListening( *m_pModel );
1203     delete m_pModel;
1204 }
1205 
1206 //------------------------------------------------------------------------
Clear()1207 void FmFilterNavigator::Clear()
1208 {
1209     m_pModel->Clear();
1210 }
1211 
1212 //------------------------------------------------------------------------
UpdateContent(const Reference<XIndexAccess> & xControllers,const Reference<XFormController> & xCurrent)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 //------------------------------------------------------------------------
EditingEntry(SvLBoxEntry * pEntry,Selection & rSelection)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 //------------------------------------------------------------------------
EditedEntry(SvLBoxEntry * pEntry,const XubString & rNewText)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 //------------------------------------------------------------------------
IMPL_LINK(FmFilterNavigator,OnRemove,SvLBoxEntry *,pEntry)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 //------------------------------------------------------------------------
IMPL_LINK(FmFilterNavigator,OnDropActionTimer,void *,EMPTYARG)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 //------------------------------------------------------------------------
AcceptDrop(const AcceptDropEvent & rEvt)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 {
getTargetItems(SvLBoxEntry * _pTarget)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 //------------------------------------------------------------------------
ExecuteDrop(const ExecuteDropEvent & rEvt)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 //------------------------------------------------------------------------
InitEntry(SvLBoxEntry * pEntry,const XubString & rStr,const Image & rImg1,const Image & rImg2,SvLBoxButtonKind eButtonKind)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 //------------------------------------------------------------------------
Select(SvLBoxEntry * pEntry,sal_Bool bSelect)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 //------------------------------------------------------------------------
Notify(SfxBroadcaster &,const SfxHint & rHint)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 //------------------------------------------------------------------------
FindEntry(const FmFilterData * pItem) const1563 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 //------------------------------------------------------------------------
Insert(FmFilterData * pItem,sal_Int32 nPos)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 //------------------------------------------------------------------------
Remove(FmFilterData * pItem)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 // -----------------------------------------------------------------------------
getSelectedFilterItems(::std::vector<FmFilterItem * > & _rItemList)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 // -----------------------------------------------------------------------------
insertFilterItem(const::std::vector<FmFilterItem * > & _rFilterList,FmFilterItems * _pTargetItems,sal_Bool _bCopy)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 //------------------------------------------------------------------------------
StartDrag(sal_Int8,const Point &)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 //------------------------------------------------------------------------------
Command(const CommandEvent & rEvt)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 // -----------------------------------------------------------------------------
getNextEntry(SvLBoxEntry * _pStartWith)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 // -----------------------------------------------------------------------------
getPrevEntry(SvLBoxEntry * _pStartWith)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 //------------------------------------------------------------------------
KeyInput(const KeyEvent & rKEvt)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 //------------------------------------------------------------------------------
DeleteSelection()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 //========================================================================
FmFilterNavigatorWin(SfxBindings * _pBindings,SfxChildWindow * _pMgr,Window * _pParent)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 //------------------------------------------------------------------------
~FmFilterNavigatorWin()1949 FmFilterNavigatorWin::~FmFilterNavigatorWin()
1950 {
1951     delete m_pNavigator;
1952 }
1953 
1954 //-----------------------------------------------------------------------
UpdateContent(FmFormShell * pFormShell)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 //-----------------------------------------------------------------------
StateChanged(sal_uInt16 nSID,SfxItemState eState,const SfxPoolItem * pState)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 //-----------------------------------------------------------------------
Close()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 //-----------------------------------------------------------------------
FillInfo(SfxChildWinInfo & rInfo) const2008 void FmFilterNavigatorWin::FillInfo( SfxChildWinInfo& rInfo ) const
2009 {
2010     SfxDockingWindow::FillInfo( rInfo );
2011     rInfo.bVisible = sal_False;
2012 }
2013 
2014 //-----------------------------------------------------------------------
CalcDockingSize(SfxChildAlignment eAlign)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 //-----------------------------------------------------------------------
CheckAlignment(SfxChildAlignment eActAlign,SfxChildAlignment eAlign)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 //------------------------------------------------------------------------
Resize()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 // -----------------------------------------------------------------------------
GetFocus()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 //========================================================================
SFX_IMPL_DOCKINGWINDOW(FmFilterNavigatorWinMgr,SID_FM_FILTER_NAVIGATOR)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