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 with 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