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 "Navigator.hxx"
21 :
22 : #include "uistrings.hrc"
23 : #include "ReportController.hxx"
24 : #include "UITools.hxx"
25 : #include "RptUndo.hxx"
26 : #include "reportformula.hxx"
27 : #include <boost/noncopyable.hpp>
28 : #include <com/sun/star/container/XContainerListener.hpp>
29 : #include <com/sun/star/report/XReportDefinition.hpp>
30 : #include <com/sun/star/report/XFixedText.hpp>
31 : #include <com/sun/star/report/XFixedLine.hpp>
32 : #include <com/sun/star/report/XFormattedField.hpp>
33 : #include <com/sun/star/report/XImageControl.hpp>
34 : #include <com/sun/star/report/XShape.hpp>
35 : #include "helpids.hrc"
36 : #include "RptResId.hrc"
37 : #include "rptui_slotid.hrc"
38 : #include <tools/debug.hxx>
39 : #include <comphelper/propmultiplex.hxx>
40 : #include <comphelper/containermultiplexer.hxx>
41 : #include <comphelper/types.hxx>
42 : #include <cppuhelper/basemutex.hxx>
43 : #include <comphelper/SelectionMultiplex.hxx>
44 : #include <svtools/treelistbox.hxx>
45 : #include <svtools/treelistentry.hxx>
46 : #include <svl/solar.hrc>
47 : #include "ReportVisitor.hxx"
48 : #include "ModuleHelper.hxx"
49 : #include <rtl/ref.hxx>
50 :
51 : #include <memory>
52 : #include <algorithm>
53 :
54 : #define RID_SVXIMG_COLLAPSEDNODE (RID_FORMS_START + 2)
55 : #define RID_SVXIMG_EXPANDEDNODE (RID_FORMS_START + 3)
56 : #define DROP_ACTION_TIMER_INITIAL_TICKS 10
57 : #define DROP_ACTION_TIMER_SCROLL_TICKS 3
58 : #define DROP_ACTION_TIMER_TICK_BASE 10
59 :
60 : namespace rptui
61 : {
62 : using namespace ::com::sun::star;
63 : using namespace utl;
64 : using namespace ::comphelper;
65 :
66 0 : sal_uInt16 lcl_getImageId(const uno::Reference< report::XReportComponent>& _xElement)
67 : {
68 0 : sal_uInt16 nId = 0;
69 0 : uno::Reference< report::XFixedLine> xFixedLine(_xElement,uno::UNO_QUERY);
70 0 : if ( uno::Reference< report::XFixedText>(_xElement,uno::UNO_QUERY).is() )
71 0 : nId = SID_FM_FIXEDTEXT;
72 0 : else if ( xFixedLine.is() )
73 0 : nId = xFixedLine->getOrientation() ? SID_INSERT_VFIXEDLINE : SID_INSERT_HFIXEDLINE;
74 0 : else if ( uno::Reference< report::XFormattedField>(_xElement,uno::UNO_QUERY).is() )
75 0 : nId = SID_FM_EDIT;
76 0 : else if ( uno::Reference< report::XImageControl>(_xElement,uno::UNO_QUERY).is() )
77 0 : nId = SID_FM_IMAGECONTROL;
78 0 : else if ( uno::Reference< report::XShape>(_xElement,uno::UNO_QUERY).is() )
79 0 : nId = SID_DRAWTBX_CS_BASIC;
80 0 : return nId;
81 : }
82 :
83 0 : OUString lcl_getName(const uno::Reference< beans::XPropertySet>& _xElement)
84 : {
85 : OSL_ENSURE(_xElement.is(),"Found report element which is NULL!");
86 0 : OUString sTempName;
87 0 : _xElement->getPropertyValue(PROPERTY_NAME) >>= sTempName;
88 0 : OUStringBuffer sName = sTempName;
89 0 : uno::Reference< report::XFixedText> xFixedText(_xElement,uno::UNO_QUERY);
90 0 : uno::Reference< report::XReportControlModel> xReportModel(_xElement,uno::UNO_QUERY);
91 0 : if ( xFixedText.is() )
92 : {
93 0 : sName.append(" : ");
94 0 : sName.append(xFixedText->getLabel());
95 : }
96 0 : else if ( xReportModel.is() && _xElement->getPropertySetInfo()->hasPropertyByName(PROPERTY_DATAFIELD) )
97 : {
98 0 : ReportFormula aFormula( xReportModel->getDataField() );
99 0 : if ( aFormula.isValid() )
100 : {
101 0 : sName.append(" : ");
102 0 : sName.append( aFormula.getUndecoratedContent() );
103 0 : }
104 : }
105 0 : return sName.makeStringAndClear();
106 : }
107 :
108 :
109 : class NavigatorTree : public ::cppu::BaseMutex
110 : , public SvTreeListBox
111 : , public reportdesign::ITraverseReport
112 : , public comphelper::OSelectionChangeListener
113 : , public ::comphelper::OPropertyChangeListener
114 : {
115 : class UserData;
116 : friend class UserData;
117 : class UserData : public ::cppu::BaseMutex
118 : ,public ::comphelper::OPropertyChangeListener
119 : ,public ::comphelper::OContainerListener
120 : {
121 : uno::Reference< uno::XInterface > m_xContent;
122 : ::rtl::Reference< comphelper::OPropertyChangeMultiplexer> m_pListener;
123 : ::rtl::Reference< comphelper::OContainerListenerAdapter> m_pContainerListener;
124 : VclPtr<NavigatorTree> m_pTree;
125 : public:
126 : UserData(NavigatorTree* _pTree,const uno::Reference<uno::XInterface>& _xContent);
127 : virtual ~UserData();
128 :
129 0 : inline uno::Reference< uno::XInterface > getContent() const { return m_xContent; }
130 0 : inline void setContent(const uno::Reference< uno::XInterface >& _xContent) { m_xContent = _xContent; }
131 :
132 : protected:
133 : // OPropertyChangeListener
134 : virtual void _propertyChanged(const beans::PropertyChangeEvent& _rEvent) throw( uno::RuntimeException) SAL_OVERRIDE;
135 :
136 : // OContainerListener
137 : virtual void _elementInserted( const container::ContainerEvent& _rEvent ) throw(uno::RuntimeException, std::exception) SAL_OVERRIDE;
138 : virtual void _elementRemoved( const container::ContainerEvent& _Event )
139 : throw (uno::RuntimeException, std::exception) SAL_OVERRIDE;
140 : virtual void _elementReplaced( const container::ContainerEvent& _rEvent ) throw(uno::RuntimeException, std::exception) SAL_OVERRIDE;
141 : virtual void _disposing(const lang::EventObject& _rSource)
142 : throw (uno::RuntimeException, std::exception) SAL_OVERRIDE;
143 : };
144 :
145 : enum DROP_ACTION { DA_SCROLLUP, DA_SCROLLDOWN, DA_EXPANDNODE };
146 : AutoTimer m_aDropActionTimer;
147 : Timer m_aSynchronizeTimer;
148 : ImageList m_aNavigatorImages;
149 : Point m_aTimerTriggered; // die Position, an der der DropTimer angeschaltet wurde
150 : DROP_ACTION m_aDropActionType;
151 : OReportController& m_rController;
152 : SvTreeListEntry* m_pMasterReport;
153 : SvTreeListEntry* m_pDragedEntry;
154 : ::rtl::Reference< comphelper::OPropertyChangeMultiplexer> m_pReportListener;
155 : ::rtl::Reference< comphelper::OSelectionChangeMultiplexer> m_pSelectionListener;
156 : unsigned short m_nTimerCounter;
157 :
158 : SvTreeListEntry* insertEntry(const OUString& _sName,SvTreeListEntry* _pParent,sal_uInt16 _nImageId,sal_uLong _nPosition,UserData* _pData);
159 : void traverseSection(const uno::Reference< report::XSection>& _xSection,SvTreeListEntry* _pParent,sal_uInt16 _nImageId,sal_uLong _nPosition = TREELIST_APPEND);
160 : void traverseFunctions(const uno::Reference< report::XFunctions>& _xFunctions,SvTreeListEntry* _pParent);
161 :
162 : protected:
163 : virtual void Command( const CommandEvent& rEvt ) SAL_OVERRIDE;
164 : // DragSourceHelper overridables
165 : virtual void StartDrag( sal_Int8 nAction, const Point& rPosPixel ) SAL_OVERRIDE;
166 : // DropTargetHelper overridables
167 : virtual sal_Int8 AcceptDrop( const AcceptDropEvent& _rEvt ) SAL_OVERRIDE;
168 : virtual sal_Int8 ExecuteDrop( const ExecuteDropEvent& _rEvt ) SAL_OVERRIDE;
169 :
170 : // OSelectionChangeListener
171 : virtual void _disposing(const lang::EventObject& _rSource)
172 : throw (uno::RuntimeException, std::exception) SAL_OVERRIDE;
173 :
174 : // OPropertyChangeListener
175 : virtual void _propertyChanged(const beans::PropertyChangeEvent& _rEvent) throw( uno::RuntimeException) SAL_OVERRIDE;
176 :
177 : // OContainerListener Helper
178 : void _elementInserted( const container::ContainerEvent& _rEvent );
179 : void _elementRemoved( const container::ContainerEvent& _Event );
180 : void _elementReplaced( const container::ContainerEvent& _rEvent );
181 :
182 : public:
183 : NavigatorTree(vcl::Window* pParent,OReportController& _rController );
184 : virtual ~NavigatorTree();
185 : virtual void dispose() SAL_OVERRIDE;
186 :
187 : DECL_LINK(OnEntrySelDesel, NavigatorTree*);
188 : DECL_LINK_TYPED( OnDropActionTimer, Timer*, void );
189 :
190 : virtual void _selectionChanged( const lang::EventObject& aEvent ) throw (uno::RuntimeException) SAL_OVERRIDE;
191 :
192 : // ITraverseReport
193 : virtual void traverseReport(const uno::Reference< report::XReportDefinition>& _xReport) SAL_OVERRIDE;
194 : virtual void traverseReportFunctions(const uno::Reference< report::XFunctions>& _xFunctions) SAL_OVERRIDE;
195 : virtual void traverseReportHeader(const uno::Reference< report::XSection>& _xSection) SAL_OVERRIDE;
196 : virtual void traverseReportFooter(const uno::Reference< report::XSection>& _xSection) SAL_OVERRIDE;
197 : virtual void traversePageHeader(const uno::Reference< report::XSection>& _xSection) SAL_OVERRIDE;
198 : virtual void traversePageFooter(const uno::Reference< report::XSection>& _xSection) SAL_OVERRIDE;
199 :
200 : virtual void traverseGroups(const uno::Reference< report::XGroups>& _xGroups) SAL_OVERRIDE;
201 : virtual void traverseGroup(const uno::Reference< report::XGroup>& _xGroup) SAL_OVERRIDE;
202 : virtual void traverseGroupFunctions(const uno::Reference< report::XFunctions>& _xFunctions) SAL_OVERRIDE;
203 : virtual void traverseGroupHeader(const uno::Reference< report::XSection>& _xSection) SAL_OVERRIDE;
204 : virtual void traverseGroupFooter(const uno::Reference< report::XSection>& _xSection) SAL_OVERRIDE;
205 :
206 : virtual void traverseDetail(const uno::Reference< report::XSection>& _xSection) SAL_OVERRIDE;
207 :
208 : SvTreeListEntry* find(const uno::Reference< uno::XInterface >& _xContent);
209 : void removeEntry(SvTreeListEntry* _pEntry,bool _bRemove = true);
210 :
211 : virtual Size GetOptimalSize() const SAL_OVERRIDE;
212 : private:
213 : using SvTreeListBox::ExecuteDrop;
214 : };
215 :
216 0 : NavigatorTree::NavigatorTree( vcl::Window* pParent,OReportController& _rController )
217 : :SvTreeListBox( pParent, WB_TABSTOP| WB_HASBUTTONS|WB_HASLINES|WB_BORDER|WB_HSCROLL|WB_HASBUTTONSATROOT )
218 : ,comphelper::OSelectionChangeListener(m_aMutex)
219 : ,OPropertyChangeListener(m_aMutex)
220 : ,m_aTimerTriggered(-1,-1)
221 : ,m_aDropActionType( DA_SCROLLUP )
222 : ,m_rController(_rController)
223 : ,m_pMasterReport(NULL)
224 : ,m_pDragedEntry(NULL)
225 0 : ,m_nTimerCounter( DROP_ACTION_TIMER_INITIAL_TICKS )
226 : {
227 0 : set_hexpand(true);
228 0 : set_vexpand(true);
229 :
230 0 : m_pReportListener = new OPropertyChangeMultiplexer(this,m_rController.getReportDefinition().get());
231 0 : m_pReportListener->addProperty(PROPERTY_PAGEHEADERON);
232 0 : m_pReportListener->addProperty(PROPERTY_PAGEFOOTERON);
233 0 : m_pReportListener->addProperty(PROPERTY_REPORTHEADERON);
234 0 : m_pReportListener->addProperty(PROPERTY_REPORTFOOTERON);
235 :
236 0 : m_pSelectionListener = new OSelectionChangeMultiplexer(this,&m_rController);
237 :
238 0 : SetHelpId( HID_REPORT_NAVIGATOR_TREE );
239 :
240 0 : m_aNavigatorImages = ImageList( ModuleRes( RID_SVXIMGLIST_RPTEXPL ) );
241 :
242 : SetNodeBitmaps(
243 : m_aNavigatorImages.GetImage( RID_SVXIMG_COLLAPSEDNODE ),
244 : m_aNavigatorImages.GetImage( RID_SVXIMG_EXPANDEDNODE )
245 0 : );
246 :
247 0 : SetDragDropMode(DragDropMode::ALL);
248 0 : EnableInplaceEditing( false );
249 0 : SetSelectionMode(MULTIPLE_SELECTION);
250 0 : Clear();
251 :
252 0 : m_aDropActionTimer.SetTimeoutHdl(LINK(this, NavigatorTree, OnDropActionTimer));
253 0 : SetSelectHdl(LINK(this, NavigatorTree, OnEntrySelDesel));
254 0 : SetDeselectHdl(LINK(this, NavigatorTree, OnEntrySelDesel));
255 0 : }
256 :
257 0 : NavigatorTree::~NavigatorTree()
258 : {
259 0 : disposeOnce();
260 0 : }
261 :
262 0 : void NavigatorTree::dispose()
263 : {
264 0 : SvTreeListEntry* pCurrent = First();
265 0 : while ( pCurrent )
266 : {
267 0 : delete static_cast<UserData*>(pCurrent->GetUserData());
268 0 : pCurrent = Next(pCurrent);
269 : }
270 0 : m_pReportListener->dispose();
271 0 : m_pSelectionListener->dispose();
272 0 : SvTreeListBox::dispose();
273 0 : }
274 :
275 0 : void NavigatorTree::Command( const CommandEvent& rEvt )
276 : {
277 0 : bool bHandled = false;
278 0 : switch( rEvt.GetCommand())
279 : {
280 : case CommandEventId::ContextMenu:
281 : {
282 : // die Stelle, an der geklickt wurde
283 0 : SvTreeListEntry* ptClickedOn = NULL;
284 0 : ::Point aWhere;
285 0 : if (rEvt.IsMouseEvent())
286 : {
287 0 : aWhere = rEvt.GetMousePosPixel();
288 0 : ptClickedOn = GetEntry(aWhere);
289 0 : if (ptClickedOn == NULL)
290 0 : break;
291 0 : if ( !IsSelected(ptClickedOn) )
292 : {
293 0 : SelectAll(false);
294 0 : Select(ptClickedOn, true);
295 0 : SetCurEntry(ptClickedOn);
296 : }
297 : }
298 : else
299 : {
300 0 : ptClickedOn = GetCurEntry();
301 0 : if ( !ptClickedOn )
302 0 : break;
303 0 : aWhere = GetEntryPosition(ptClickedOn);
304 : }
305 0 : UserData* pData = static_cast<UserData*>(ptClickedOn->GetUserData());
306 0 : uno::Reference< report::XFunctionsSupplier> xSupplier(pData->getContent(),uno::UNO_QUERY);
307 0 : uno::Reference< report::XFunctions> xFunctions(pData->getContent(),uno::UNO_QUERY);
308 0 : uno::Reference< report::XGroup> xGroup(pData->getContent(),uno::UNO_QUERY);
309 0 : bool bDeleteAllowed = m_rController.isEditable() && (xGroup.is() ||
310 0 : uno::Reference< report::XFunction>(pData->getContent(),uno::UNO_QUERY).is());
311 0 : PopupMenu aContextMenu( ModuleRes( RID_MENU_NAVIGATOR ) );
312 :
313 0 : sal_uInt16 nCount = aContextMenu.GetItemCount();
314 0 : for (sal_uInt16 i = 0; i < nCount; ++i)
315 : {
316 0 : if ( MenuItemType::SEPARATOR != aContextMenu.GetItemType(i))
317 : {
318 0 : sal_uInt16 nId = aContextMenu.GetItemId(i);
319 :
320 0 : aContextMenu.CheckItem(nId,m_rController.isCommandChecked(nId));
321 0 : bool bEnabled = m_rController.isCommandEnabled(nId);
322 0 : if ( nId == SID_RPT_NEW_FUNCTION )
323 0 : aContextMenu.EnableItem(nId,m_rController.isEditable() && (xSupplier.is() || xFunctions.is()) );
324 : // special condition, check for function and group
325 0 : else if ( nId == SID_DELETE )
326 0 : aContextMenu.EnableItem(SID_DELETE,bDeleteAllowed);
327 : else
328 0 : aContextMenu.EnableItem(nId,bEnabled);
329 : }
330 : }
331 0 : sal_uInt16 nId = aContextMenu.Execute(this, aWhere);
332 0 : if ( nId )
333 : {
334 0 : uno::Sequence< beans::PropertyValue> aArgs;
335 0 : if ( nId == SID_RPT_NEW_FUNCTION )
336 : {
337 0 : aArgs.realloc(1);
338 0 : aArgs[0].Value <<= (xFunctions.is() ? xFunctions : xSupplier->getFunctions());
339 : }
340 0 : else if ( nId == SID_DELETE )
341 : {
342 0 : if ( xGroup.is() )
343 0 : nId = SID_GROUP_REMOVE;
344 0 : aArgs.realloc(1);
345 0 : aArgs[0].Name = PROPERTY_GROUP;
346 0 : aArgs[0].Value <<= pData->getContent();
347 : }
348 0 : m_rController.executeUnChecked(nId,aArgs);
349 : }
350 :
351 0 : bHandled = true;
352 : }
353 0 : break;
354 0 : default: break;
355 : }
356 :
357 0 : if (!bHandled)
358 0 : SvTreeListBox::Command( rEvt );
359 0 : }
360 :
361 0 : sal_Int8 NavigatorTree::AcceptDrop( const AcceptDropEvent& _rEvt )
362 : {
363 0 : sal_Int8 nDropOption = DND_ACTION_NONE;
364 0 : ::Point aDropPos = _rEvt.maPosPixel;
365 0 : if (_rEvt.mbLeaving)
366 : {
367 0 : if (m_aDropActionTimer.IsActive())
368 0 : m_aDropActionTimer.Stop();
369 : }
370 : else
371 : {
372 0 : bool bNeedTrigger = false;
373 : // auf dem ersten Eintrag ?
374 0 : if ((aDropPos.Y() >= 0) && (aDropPos.Y() < GetEntryHeight()))
375 : {
376 0 : m_aDropActionType = DA_SCROLLUP;
377 0 : bNeedTrigger = true;
378 : }
379 0 : else if ((aDropPos.Y() < GetSizePixel().Height()) && (aDropPos.Y() >= GetSizePixel().Height() - GetEntryHeight()))
380 : {
381 0 : m_aDropActionType = DA_SCROLLDOWN;
382 0 : bNeedTrigger = true;
383 : }
384 : else
385 : {
386 0 : SvTreeListEntry* pDropppedOn = GetEntry(aDropPos);
387 0 : if (pDropppedOn && (GetChildCount(pDropppedOn) > 0) && !IsExpanded(pDropppedOn))
388 : {
389 0 : m_aDropActionType = DA_EXPANDNODE;
390 0 : bNeedTrigger = true;
391 : }
392 : }
393 :
394 0 : if (bNeedTrigger && (m_aTimerTriggered != aDropPos))
395 : {
396 : // neu anfangen zu zaehlen
397 0 : m_nTimerCounter = DROP_ACTION_TIMER_INITIAL_TICKS;
398 : // die Pos merken, da ich auch AcceptDrops bekomme, wenn sich die Maus gar nicht bewegt hat
399 0 : m_aTimerTriggered = aDropPos;
400 : // und den Timer los
401 0 : if (!m_aDropActionTimer.IsActive()) // gibt es den Timer schon ?
402 : {
403 0 : m_aDropActionTimer.SetTimeout(DROP_ACTION_TIMER_TICK_BASE);
404 0 : m_aDropActionTimer.Start();
405 : }
406 : }
407 0 : else if (!bNeedTrigger)
408 0 : m_aDropActionTimer.Stop();
409 : }
410 :
411 0 : return nDropOption;
412 : }
413 :
414 0 : sal_Int8 NavigatorTree::ExecuteDrop( const ExecuteDropEvent& /*_rEvt*/ )
415 : {
416 0 : return DND_ACTION_NONE;
417 : }
418 :
419 0 : void NavigatorTree::StartDrag( sal_Int8 /*_nAction*/, const Point& _rPosPixel )
420 : {
421 0 : m_pDragedEntry = GetEntry(_rPosPixel);
422 0 : if ( m_pDragedEntry )
423 : {
424 0 : EndSelection();
425 : }
426 0 : }
427 :
428 0 : IMPL_LINK_NOARG_TYPED(NavigatorTree, OnDropActionTimer, Timer *, void)
429 : {
430 0 : if (--m_nTimerCounter > 0)
431 0 : return;
432 :
433 0 : switch ( m_aDropActionType )
434 : {
435 : case DA_EXPANDNODE:
436 : {
437 0 : SvTreeListEntry* pToExpand = GetEntry(m_aTimerTriggered);
438 0 : if (pToExpand && (GetChildCount(pToExpand) > 0) && !IsExpanded(pToExpand))
439 0 : Expand(pToExpand);
440 0 : m_aDropActionTimer.Stop();
441 : }
442 0 : break;
443 :
444 : case DA_SCROLLUP :
445 0 : ScrollOutputArea( 1 );
446 0 : m_nTimerCounter = DROP_ACTION_TIMER_SCROLL_TICKS;
447 0 : break;
448 :
449 : case DA_SCROLLDOWN :
450 0 : ScrollOutputArea( -1 );
451 0 : m_nTimerCounter = DROP_ACTION_TIMER_SCROLL_TICKS;
452 0 : break;
453 :
454 : }
455 : }
456 :
457 :
458 0 : IMPL_LINK(NavigatorTree, OnEntrySelDesel, NavigatorTree*, /*pThis*/)
459 : {
460 0 : if ( !m_pSelectionListener->locked() )
461 : {
462 0 : m_pSelectionListener->lock();
463 0 : SvTreeListEntry* pEntry = GetCurEntry();
464 0 : uno::Any aSelection;
465 0 : if ( IsSelected(pEntry) )
466 0 : aSelection <<= static_cast<UserData*>(pEntry->GetUserData())->getContent();
467 0 : m_rController.select(aSelection);
468 0 : m_pSelectionListener->unlock();
469 : }
470 :
471 0 : return 0L;
472 : }
473 :
474 0 : void NavigatorTree::_selectionChanged( const lang::EventObject& aEvent ) throw (uno::RuntimeException)
475 : {
476 0 : m_pSelectionListener->lock();
477 0 : uno::Reference< view::XSelectionSupplier> xSelectionSupplier(aEvent.Source,uno::UNO_QUERY);
478 0 : uno::Any aSec = xSelectionSupplier->getSelection();
479 0 : uno::Sequence< uno::Reference< report::XReportComponent > > aSelection;
480 0 : aSec >>= aSelection;
481 0 : if ( !aSelection.getLength() )
482 : {
483 0 : uno::Reference< uno::XInterface> xSelection(aSec,uno::UNO_QUERY);
484 0 : SvTreeListEntry* pEntry = find(xSelection);
485 0 : if ( pEntry && !IsSelected(pEntry) )
486 : {
487 0 : Select(pEntry, true);
488 0 : SetCurEntry(pEntry);
489 : }
490 0 : else if ( !pEntry )
491 0 : SelectAll(false,false);
492 : }
493 : else
494 : {
495 0 : const uno::Reference< report::XReportComponent >* pIter = aSelection.getConstArray();
496 0 : const uno::Reference< report::XReportComponent >* pEnd = pIter + aSelection.getLength();
497 0 : for (; pIter != pEnd; ++pIter)
498 : {
499 0 : SvTreeListEntry* pEntry = find(*pIter);
500 0 : if ( pEntry && !IsSelected(pEntry) )
501 : {
502 0 : Select(pEntry, true);
503 0 : SetCurEntry(pEntry);
504 : }
505 : }
506 : }
507 0 : m_pSelectionListener->unlock();
508 0 : }
509 :
510 0 : SvTreeListEntry* NavigatorTree::insertEntry(const OUString& _sName,SvTreeListEntry* _pParent,sal_uInt16 _nImageId,sal_uLong _nPosition,UserData* _pData)
511 : {
512 0 : SvTreeListEntry* pEntry = NULL;
513 0 : if ( _nImageId )
514 : {
515 0 : const Image aImage( m_aNavigatorImages.GetImage( _nImageId ) );
516 0 : pEntry = InsertEntry(_sName,aImage,aImage,_pParent,false,_nPosition,_pData);
517 : }
518 : else
519 0 : pEntry = InsertEntry(_sName,_pParent,false,_nPosition,_pData);
520 0 : return pEntry;
521 : }
522 :
523 0 : void NavigatorTree::traverseSection(const uno::Reference< report::XSection>& _xSection,SvTreeListEntry* _pParent,sal_uInt16 _nImageId,sal_uLong _nPosition)
524 : {
525 0 : SvTreeListEntry* pSection = insertEntry(_xSection->getName(),_pParent,_nImageId,_nPosition,new UserData(this,_xSection));
526 0 : const sal_Int32 nCount = _xSection->getCount();
527 0 : for (sal_Int32 i = 0; i < nCount; ++i)
528 : {
529 0 : uno::Reference< report::XReportComponent> xElement(_xSection->getByIndex(i),uno::UNO_QUERY_THROW);
530 : OSL_ENSURE(xElement.is(),"Found report element which is NULL!");
531 0 : insertEntry(lcl_getName(xElement.get()),pSection,lcl_getImageId(xElement),TREELIST_APPEND,new UserData(this,xElement));
532 0 : uno::Reference< report::XReportDefinition> xSubReport(xElement,uno::UNO_QUERY);
533 0 : if ( xSubReport.is() )
534 : {
535 0 : m_pMasterReport = find(_xSection->getReportDefinition());
536 0 : reportdesign::OReportVisitor aSubVisitor(this);
537 0 : aSubVisitor.start(xSubReport);
538 : }
539 0 : }
540 0 : }
541 :
542 0 : void NavigatorTree::traverseFunctions(const uno::Reference< report::XFunctions>& _xFunctions,SvTreeListEntry* _pParent)
543 : {
544 0 : SvTreeListEntry* pFunctions = insertEntry(OUString(ModuleRes(RID_STR_FUNCTIONS)), _pParent, SID_RPT_NEW_FUNCTION, TREELIST_APPEND, new UserData(this,_xFunctions));
545 0 : const sal_Int32 nCount = _xFunctions->getCount();
546 0 : for (sal_Int32 i = 0; i< nCount; ++i)
547 : {
548 0 : uno::Reference< report::XFunction> xElement(_xFunctions->getByIndex(i),uno::UNO_QUERY);
549 0 : insertEntry(xElement->getName(),pFunctions,SID_RPT_NEW_FUNCTION,TREELIST_APPEND,new UserData(this,xElement));
550 0 : }
551 0 : }
552 :
553 0 : SvTreeListEntry* NavigatorTree::find(const uno::Reference< uno::XInterface >& _xContent)
554 : {
555 0 : SvTreeListEntry* pRet = NULL;
556 0 : if ( _xContent.is() )
557 : {
558 0 : SvTreeListEntry* pCurrent = First();
559 0 : while ( pCurrent )
560 : {
561 0 : UserData* pData = static_cast<UserData*>(pCurrent->GetUserData());
562 : OSL_ENSURE(pData,"No UserData set an entry!");
563 0 : if ( pData->getContent() == _xContent )
564 : {
565 0 : pRet = pCurrent;
566 0 : break;
567 : }
568 0 : pCurrent = Next(pCurrent);
569 : }
570 : }
571 0 : return pRet;
572 : }
573 :
574 : // ITraverseReport
575 :
576 0 : void NavigatorTree::traverseReport(const uno::Reference< report::XReportDefinition>& _xReport)
577 : {
578 0 : insertEntry(_xReport->getName(),m_pMasterReport,SID_SELECT_REPORT,TREELIST_APPEND,new UserData(this,_xReport));
579 0 : }
580 :
581 0 : void NavigatorTree::traverseReportFunctions(const uno::Reference< report::XFunctions>& _xFunctions)
582 : {
583 0 : SvTreeListEntry* pReport = find(_xFunctions->getParent());
584 0 : traverseFunctions(_xFunctions,pReport);
585 0 : }
586 :
587 0 : void NavigatorTree::traverseReportHeader(const uno::Reference< report::XSection>& _xSection)
588 : {
589 0 : SvTreeListEntry* pReport = find(_xSection->getReportDefinition());
590 0 : traverseSection(_xSection,pReport,SID_REPORTHEADERFOOTER);
591 0 : }
592 :
593 0 : void NavigatorTree::traverseReportFooter(const uno::Reference< report::XSection>& _xSection)
594 : {
595 0 : SvTreeListEntry* pReport = find(_xSection->getReportDefinition());
596 0 : traverseSection(_xSection,pReport,SID_REPORTHEADERFOOTER);
597 0 : }
598 :
599 0 : void NavigatorTree::traversePageHeader(const uno::Reference< report::XSection>& _xSection)
600 : {
601 0 : SvTreeListEntry* pReport = find(_xSection->getReportDefinition());
602 0 : traverseSection(_xSection,pReport,SID_PAGEHEADERFOOTER);
603 0 : }
604 :
605 0 : void NavigatorTree::traversePageFooter(const uno::Reference< report::XSection>& _xSection)
606 : {
607 0 : SvTreeListEntry* pReport = find(_xSection->getReportDefinition());
608 0 : traverseSection(_xSection,pReport,SID_PAGEHEADERFOOTER);
609 0 : }
610 :
611 0 : void NavigatorTree::traverseGroups(const uno::Reference< report::XGroups>& _xGroups)
612 : {
613 0 : SvTreeListEntry* pReport = find(_xGroups->getReportDefinition());
614 0 : insertEntry(OUString(ModuleRes(RID_STR_GROUPS)), pReport, SID_SORTINGANDGROUPING, TREELIST_APPEND, new UserData(this,_xGroups));
615 0 : }
616 :
617 0 : void NavigatorTree::traverseGroup(const uno::Reference< report::XGroup>& _xGroup)
618 : {
619 0 : uno::Reference< report::XGroups> xGroups(_xGroup->getParent(),uno::UNO_QUERY);
620 0 : SvTreeListEntry* pGroups = find(xGroups);
621 : OSL_ENSURE(pGroups,"No Groups inserted so far. Why!");
622 0 : insertEntry(_xGroup->getExpression(),pGroups,SID_GROUP,rptui::getPositionInIndexAccess(xGroups.get(),_xGroup),new UserData(this,_xGroup));
623 0 : }
624 :
625 0 : void NavigatorTree::traverseGroupFunctions(const uno::Reference< report::XFunctions>& _xFunctions)
626 : {
627 0 : SvTreeListEntry* pGroup = find(_xFunctions->getParent());
628 0 : traverseFunctions(_xFunctions,pGroup);
629 0 : }
630 :
631 0 : void NavigatorTree::traverseGroupHeader(const uno::Reference< report::XSection>& _xSection)
632 : {
633 0 : SvTreeListEntry* pGroup = find(_xSection->getGroup());
634 : OSL_ENSURE(pGroup,"No group found");
635 0 : traverseSection(_xSection,pGroup,SID_GROUPHEADER,1);
636 0 : }
637 :
638 0 : void NavigatorTree::traverseGroupFooter(const uno::Reference< report::XSection>& _xSection)
639 : {
640 0 : SvTreeListEntry* pGroup = find(_xSection->getGroup());
641 : OSL_ENSURE(pGroup,"No group found");
642 0 : traverseSection(_xSection,pGroup,SID_GROUPFOOTER);
643 0 : }
644 :
645 0 : void NavigatorTree::traverseDetail(const uno::Reference< report::XSection>& _xSection)
646 : {
647 0 : uno::Reference< report::XReportDefinition> xReport = _xSection->getReportDefinition();
648 0 : SvTreeListEntry* pParent = find(xReport);
649 0 : traverseSection(_xSection,pParent,SID_ICON_DETAIL);
650 0 : }
651 :
652 0 : void NavigatorTree::_propertyChanged(const beans::PropertyChangeEvent& _rEvent) throw( uno::RuntimeException)
653 : {
654 0 : uno::Reference< report::XReportDefinition> xReport(_rEvent.Source,uno::UNO_QUERY);
655 0 : if ( xReport.is() )
656 : {
657 0 : bool bEnabled = false;
658 0 : _rEvent.NewValue >>= bEnabled;
659 0 : if ( bEnabled )
660 : {
661 0 : SvTreeListEntry* pParent = find(xReport);
662 0 : if ( _rEvent.PropertyName == PROPERTY_REPORTHEADERON )
663 : {
664 0 : sal_uLong nPos = xReport->getReportHeaderOn() ? 2 : 1;
665 0 : traverseSection(xReport->getReportHeader(),pParent,SID_REPORTHEADERFOOTER,nPos);
666 : }
667 0 : else if ( _rEvent.PropertyName == PROPERTY_PAGEHEADERON )
668 : {
669 0 : traverseSection(xReport->getPageHeader(),pParent, SID_PAGEHEADERFOOTER,1);
670 : }
671 0 : else if ( _rEvent.PropertyName == PROPERTY_PAGEFOOTERON )
672 0 : traverseSection(xReport->getPageFooter(),pParent, SID_PAGEHEADERFOOTER);
673 0 : else if ( _rEvent.PropertyName == PROPERTY_REPORTFOOTERON )
674 : {
675 0 : sal_uLong nPos = xReport->getPageFooterOn() ? (GetLevelChildCount(pParent) - 1) : TREELIST_APPEND;
676 0 : traverseSection(xReport->getReportFooter(),pParent,SID_REPORTHEADERFOOTER,nPos);
677 : }
678 : }
679 0 : }
680 0 : }
681 :
682 0 : void NavigatorTree::_elementInserted( const container::ContainerEvent& _rEvent )
683 : {
684 0 : SvTreeListEntry* pEntry = find(_rEvent.Source);
685 0 : uno::Reference<beans::XPropertySet> xProp(_rEvent.Element,uno::UNO_QUERY_THROW);
686 0 : OUString sName;
687 0 : uno::Reference< beans::XPropertySetInfo> xInfo = xProp->getPropertySetInfo();
688 0 : if ( xInfo.is() )
689 : {
690 0 : if ( xInfo->hasPropertyByName(PROPERTY_NAME) )
691 0 : xProp->getPropertyValue(PROPERTY_NAME) >>= sName;
692 0 : else if ( xInfo->hasPropertyByName(PROPERTY_EXPRESSION) )
693 0 : xProp->getPropertyValue(PROPERTY_EXPRESSION) >>= sName;
694 : }
695 0 : uno::Reference< report::XGroup> xGroup(xProp,uno::UNO_QUERY);
696 0 : if ( xGroup.is() )
697 : {
698 0 : reportdesign::OReportVisitor aSubVisitor(this);
699 0 : aSubVisitor.start(xGroup);
700 : }
701 : else
702 : {
703 0 : uno::Reference< report::XReportComponent> xElement(xProp,uno::UNO_QUERY);
704 0 : if ( xProp.is() )
705 0 : sName = lcl_getName(xProp);
706 0 : insertEntry(sName,pEntry,(!xElement.is() ? sal_uInt16(SID_RPT_NEW_FUNCTION) : lcl_getImageId(xElement)),TREELIST_APPEND,new UserData(this,xProp));
707 : }
708 0 : if ( !IsExpanded(pEntry) )
709 0 : Expand(pEntry);
710 0 : }
711 :
712 0 : void NavigatorTree::_elementRemoved( const container::ContainerEvent& _rEvent )
713 : {
714 0 : uno::Reference<beans::XPropertySet> xProp(_rEvent.Element,uno::UNO_QUERY);
715 0 : SvTreeListEntry* pEntry = find(xProp);
716 : OSL_ENSURE(pEntry,"NavigatorTree::_elementRemoved: No Entry found!");
717 :
718 0 : if (pEntry)
719 : {
720 0 : removeEntry(pEntry);
721 0 : Invalidate();
722 0 : }
723 0 : }
724 :
725 0 : void NavigatorTree::_elementReplaced( const container::ContainerEvent& _rEvent )
726 : {
727 0 : uno::Reference<beans::XPropertySet> xProp(_rEvent.ReplacedElement,uno::UNO_QUERY);
728 0 : SvTreeListEntry* pEntry = find(xProp);
729 0 : if ( pEntry )
730 : {
731 0 : UserData* pData = static_cast<UserData*>(pEntry->GetUserData());
732 0 : xProp.set(_rEvent.Element,uno::UNO_QUERY);
733 0 : pData->setContent(xProp);
734 0 : OUString sName;
735 0 : xProp->getPropertyValue(PROPERTY_NAME) >>= sName;
736 0 : SetEntryText(pEntry,sName);
737 0 : }
738 0 : }
739 :
740 0 : void NavigatorTree::_disposing(const lang::EventObject& _rSource)
741 : throw (uno::RuntimeException, std::exception)
742 : {
743 0 : removeEntry(find(_rSource.Source));
744 0 : }
745 :
746 0 : void NavigatorTree::removeEntry(SvTreeListEntry* _pEntry,bool _bRemove)
747 : {
748 0 : if ( _pEntry )
749 : {
750 0 : SvTreeListEntry* pChild = FirstChild(_pEntry);
751 0 : while( pChild )
752 : {
753 0 : removeEntry(pChild,false);
754 0 : pChild = NextSibling(pChild);
755 : }
756 0 : delete static_cast<UserData*>(_pEntry->GetUserData());
757 0 : if ( _bRemove )
758 0 : GetModel()->Remove(_pEntry);
759 : }
760 0 : }
761 :
762 0 : NavigatorTree::UserData::UserData(NavigatorTree* _pTree,const uno::Reference<uno::XInterface>& _xContent)
763 : : OPropertyChangeListener(m_aMutex)
764 : , OContainerListener(m_aMutex)
765 : , m_xContent(_xContent)
766 0 : , m_pTree(_pTree)
767 : {
768 0 : uno::Reference<beans::XPropertySet> xProp(m_xContent,uno::UNO_QUERY);
769 0 : if ( xProp.is() )
770 : {
771 0 : uno::Reference< beans::XPropertySetInfo> xInfo = xProp->getPropertySetInfo();
772 0 : if ( xInfo.is() )
773 : {
774 0 : m_pListener = new ::comphelper::OPropertyChangeMultiplexer(this,xProp);
775 0 : if ( xInfo->hasPropertyByName(PROPERTY_NAME) )
776 0 : m_pListener->addProperty(PROPERTY_NAME);
777 0 : else if ( xInfo->hasPropertyByName(PROPERTY_EXPRESSION) )
778 0 : m_pListener->addProperty(PROPERTY_EXPRESSION);
779 0 : if ( xInfo->hasPropertyByName(PROPERTY_DATAFIELD) )
780 0 : m_pListener->addProperty(PROPERTY_DATAFIELD);
781 0 : if ( xInfo->hasPropertyByName(PROPERTY_LABEL) )
782 0 : m_pListener->addProperty(PROPERTY_LABEL);
783 0 : if ( xInfo->hasPropertyByName(PROPERTY_HEADERON) )
784 0 : m_pListener->addProperty(PROPERTY_HEADERON);
785 0 : if ( xInfo->hasPropertyByName(PROPERTY_FOOTERON) )
786 0 : m_pListener->addProperty(PROPERTY_FOOTERON);
787 0 : }
788 : }
789 0 : uno::Reference< container::XContainer> xContainer(m_xContent,uno::UNO_QUERY);
790 0 : if ( xContainer.is() )
791 : {
792 0 : m_pContainerListener = new ::comphelper::OContainerListenerAdapter(this,xContainer);
793 0 : }
794 0 : }
795 :
796 0 : NavigatorTree::UserData::~UserData()
797 : {
798 0 : if ( m_pContainerListener.is() )
799 0 : m_pContainerListener->dispose();
800 0 : if ( m_pListener.is() )
801 0 : m_pListener->dispose();
802 0 : }
803 :
804 : // OPropertyChangeListener
805 0 : void NavigatorTree::UserData::_propertyChanged(const beans::PropertyChangeEvent& _rEvent) throw( uno::RuntimeException)
806 : {
807 0 : SvTreeListEntry* pEntry = m_pTree->find(_rEvent.Source);
808 : OSL_ENSURE(pEntry,"No entry could be found! Why not!");
809 0 : const bool bFooterOn = (PROPERTY_FOOTERON == _rEvent.PropertyName);
810 : try
811 : {
812 0 : if ( bFooterOn || PROPERTY_HEADERON == _rEvent.PropertyName )
813 : {
814 0 : sal_Int32 nPos = 1;
815 0 : uno::Reference< report::XGroup> xGroup(_rEvent.Source,uno::UNO_QUERY);
816 0 : ::std::mem_fun_t< bool,OGroupHelper> pIsOn = ::std::mem_fun(&OGroupHelper::getHeaderOn);
817 0 : ::std::mem_fun_t< uno::Reference<report::XSection> ,OGroupHelper> pMemFunSection = ::std::mem_fun(&OGroupHelper::getHeader);
818 0 : if ( bFooterOn )
819 : {
820 0 : pIsOn = ::std::mem_fun(&OGroupHelper::getFooterOn);
821 0 : pMemFunSection = ::std::mem_fun(&OGroupHelper::getFooter);
822 0 : nPos = m_pTree->GetChildCount(pEntry) - 1;
823 : }
824 :
825 0 : OGroupHelper aGroupHelper(xGroup);
826 0 : if ( pIsOn(&aGroupHelper) )
827 : {
828 0 : if ( bFooterOn )
829 0 : ++nPos;
830 0 : m_pTree->traverseSection(pMemFunSection(&aGroupHelper),pEntry,bFooterOn ? SID_GROUPFOOTER : SID_GROUPHEADER,nPos);
831 0 : }
832 : }
833 0 : else if ( PROPERTY_EXPRESSION == _rEvent.PropertyName)
834 : {
835 0 : OUString sNewName;
836 0 : _rEvent.NewValue >>= sNewName;
837 0 : m_pTree->SetEntryText(pEntry,sNewName);
838 : }
839 0 : else if ( PROPERTY_DATAFIELD == _rEvent.PropertyName || PROPERTY_LABEL == _rEvent.PropertyName || PROPERTY_NAME == _rEvent.PropertyName )
840 : {
841 0 : uno::Reference<beans::XPropertySet> xProp(_rEvent.Source,uno::UNO_QUERY);
842 0 : m_pTree->SetEntryText(pEntry,lcl_getName(xProp));
843 : }
844 : }
845 0 : catch(const uno::Exception &)
846 : {}
847 0 : }
848 :
849 0 : void NavigatorTree::UserData::_elementInserted( const container::ContainerEvent& _rEvent ) throw(uno::RuntimeException, std::exception)
850 : {
851 0 : m_pTree->_elementInserted( _rEvent );
852 0 : }
853 :
854 0 : void NavigatorTree::UserData::_elementRemoved( const container::ContainerEvent& _rEvent )
855 : throw (uno::RuntimeException, std::exception)
856 : {
857 0 : m_pTree->_elementRemoved( _rEvent );
858 0 : }
859 :
860 0 : void NavigatorTree::UserData::_elementReplaced( const container::ContainerEvent& _rEvent ) throw(uno::RuntimeException, std::exception)
861 : {
862 0 : m_pTree->_elementReplaced( _rEvent );
863 0 : }
864 :
865 0 : void NavigatorTree::UserData::_disposing(const lang::EventObject& _rSource)
866 : throw (uno::RuntimeException, std::exception)
867 : {
868 0 : m_pTree->_disposing( _rSource );
869 0 : }
870 :
871 0 : Size NavigatorTree::GetOptimalSize() const
872 : {
873 0 : return LogicToPixel(Size(100, 70), MAP_APPFONT);
874 : }
875 :
876 : // class ONavigatorImpl
877 0 : class ONavigatorImpl: private boost::noncopyable
878 : {
879 : public:
880 : ONavigatorImpl(OReportController& _rController,ONavigator* _pParent);
881 :
882 : uno::Reference< report::XReportDefinition> m_xReport;
883 : ::rptui::OReportController& m_rController;
884 : VclPtr<NavigatorTree> m_pNavigatorTree;
885 : };
886 :
887 0 : ONavigatorImpl::ONavigatorImpl(OReportController& _rController,ONavigator* _pParent)
888 : :m_xReport(_rController.getReportDefinition())
889 : ,m_rController(_rController)
890 0 : ,m_pNavigatorTree(VclPtr<NavigatorTree>::Create(_pParent->get<vcl::Window>("box"),_rController))
891 : {
892 0 : reportdesign::OReportVisitor aVisitor(m_pNavigatorTree.get());
893 0 : aVisitor.start(m_xReport);
894 0 : m_pNavigatorTree->Expand(m_pNavigatorTree->find(m_xReport));
895 0 : lang::EventObject aEvent(m_rController);
896 0 : m_pNavigatorTree->_selectionChanged(aEvent);
897 0 : }
898 :
899 : // class ONavigator
900 0 : ONavigator::ONavigator(vcl::Window* _pParent ,OReportController& _rController)
901 0 : : FloatingWindow( _pParent, "FloatingNavigator", "modules/dbreport/ui/floatingnavigator.ui")
902 : {
903 0 : m_pImpl.reset(new ONavigatorImpl(_rController,this));
904 :
905 0 : m_pImpl->m_pNavigatorTree->Show();
906 0 : m_pImpl->m_pNavigatorTree->GrabFocus();
907 0 : Show();
908 0 : }
909 :
910 0 : void ONavigator::GetFocus()
911 : {
912 0 : Window::GetFocus();
913 0 : if ( m_pImpl->m_pNavigatorTree.get() )
914 0 : m_pImpl->m_pNavigatorTree->GrabFocus();
915 0 : }
916 :
917 3 : } // rptui
918 :
919 :
920 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|