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