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