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 : 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 :
186 : DECL_LINK(OnEntrySelDesel, NavigatorTree*);
187 : DECL_LINK( OnDropActionTimer, void* );
188 :
189 : virtual void _selectionChanged( const lang::EventObject& aEvent ) throw (uno::RuntimeException) SAL_OVERRIDE;
190 :
191 : // ITraverseReport
192 : virtual void traverseReport(const uno::Reference< report::XReportDefinition>& _xReport) SAL_OVERRIDE;
193 : virtual void traverseReportFunctions(const uno::Reference< report::XFunctions>& _xFunctions) SAL_OVERRIDE;
194 : virtual void traverseReportHeader(const uno::Reference< report::XSection>& _xSection) SAL_OVERRIDE;
195 : virtual void traverseReportFooter(const uno::Reference< report::XSection>& _xSection) SAL_OVERRIDE;
196 : virtual void traversePageHeader(const uno::Reference< report::XSection>& _xSection) SAL_OVERRIDE;
197 : virtual void traversePageFooter(const uno::Reference< report::XSection>& _xSection) SAL_OVERRIDE;
198 :
199 : virtual void traverseGroups(const uno::Reference< report::XGroups>& _xGroups) SAL_OVERRIDE;
200 : virtual void traverseGroup(const uno::Reference< report::XGroup>& _xGroup) SAL_OVERRIDE;
201 : virtual void traverseGroupFunctions(const uno::Reference< report::XFunctions>& _xFunctions) SAL_OVERRIDE;
202 : virtual void traverseGroupHeader(const uno::Reference< report::XSection>& _xSection) SAL_OVERRIDE;
203 : virtual void traverseGroupFooter(const uno::Reference< report::XSection>& _xSection) SAL_OVERRIDE;
204 :
205 : virtual void traverseDetail(const uno::Reference< report::XSection>& _xSection) SAL_OVERRIDE;
206 :
207 : SvTreeListEntry* find(const uno::Reference< uno::XInterface >& _xContent);
208 : void removeEntry(SvTreeListEntry* _pEntry,bool _bRemove = true);
209 :
210 : virtual Size GetOptimalSize() const SAL_OVERRIDE;
211 : private:
212 : using SvTreeListBox::ExecuteDrop;
213 : };
214 :
215 0 : NavigatorTree::NavigatorTree( vcl::Window* pParent,OReportController& _rController )
216 : :SvTreeListBox( pParent, WB_TABSTOP| WB_HASBUTTONS|WB_HASLINES|WB_BORDER|WB_HSCROLL|WB_HASBUTTONSATROOT )
217 : ,comphelper::OSelectionChangeListener(m_aMutex)
218 : ,OPropertyChangeListener(m_aMutex)
219 : ,m_aTimerTriggered(-1,-1)
220 : ,m_aDropActionType( DA_SCROLLUP )
221 : ,m_rController(_rController)
222 : ,m_pMasterReport(NULL)
223 : ,m_pDragedEntry(NULL)
224 0 : ,m_nTimerCounter( DROP_ACTION_TIMER_INITIAL_TICKS )
225 : {
226 0 : set_hexpand(true);
227 0 : set_vexpand(true);
228 :
229 0 : m_pReportListener = new OPropertyChangeMultiplexer(this,m_rController.getReportDefinition().get());
230 0 : m_pReportListener->addProperty(PROPERTY_PAGEHEADERON);
231 0 : m_pReportListener->addProperty(PROPERTY_PAGEFOOTERON);
232 0 : m_pReportListener->addProperty(PROPERTY_REPORTHEADERON);
233 0 : m_pReportListener->addProperty(PROPERTY_REPORTFOOTERON);
234 :
235 0 : m_pSelectionListener = new OSelectionChangeMultiplexer(this,&m_rController);
236 :
237 0 : SetHelpId( HID_REPORT_NAVIGATOR_TREE );
238 :
239 0 : m_aNavigatorImages = ImageList( ModuleRes( RID_SVXIMGLIST_RPTEXPL ) );
240 :
241 : SetNodeBitmaps(
242 : m_aNavigatorImages.GetImage( RID_SVXIMG_COLLAPSEDNODE ),
243 : m_aNavigatorImages.GetImage( RID_SVXIMG_EXPANDEDNODE )
244 0 : );
245 :
246 0 : SetDragDropMode(0xFFFF);
247 0 : EnableInplaceEditing( false );
248 0 : SetSelectionMode(MULTIPLE_SELECTION);
249 0 : Clear();
250 :
251 0 : m_aDropActionTimer.SetTimeoutHdl(LINK(this, NavigatorTree, OnDropActionTimer));
252 0 : SetSelectHdl(LINK(this, NavigatorTree, OnEntrySelDesel));
253 0 : SetDeselectHdl(LINK(this, NavigatorTree, OnEntrySelDesel));
254 0 : }
255 :
256 0 : NavigatorTree::~NavigatorTree()
257 : {
258 0 : SvTreeListEntry* pCurrent = First();
259 0 : while ( pCurrent )
260 : {
261 0 : delete static_cast<UserData*>(pCurrent->GetUserData());
262 0 : pCurrent = Next(pCurrent);
263 : }
264 0 : m_pReportListener->dispose();
265 0 : m_pSelectionListener->dispose();
266 0 : }
267 :
268 0 : void NavigatorTree::Command( const CommandEvent& rEvt )
269 : {
270 0 : bool bHandled = false;
271 0 : switch( rEvt.GetCommand() )
272 : {
273 : case COMMAND_CONTEXTMENU:
274 : {
275 : // die Stelle, an der geklickt wurde
276 0 : SvTreeListEntry* ptClickedOn = NULL;
277 0 : ::Point aWhere;
278 0 : if (rEvt.IsMouseEvent())
279 : {
280 0 : aWhere = rEvt.GetMousePosPixel();
281 0 : ptClickedOn = GetEntry(aWhere);
282 0 : if (ptClickedOn == NULL)
283 0 : break;
284 0 : if ( !IsSelected(ptClickedOn) )
285 : {
286 0 : SelectAll(false);
287 0 : Select(ptClickedOn, true);
288 0 : SetCurEntry(ptClickedOn);
289 : }
290 : }
291 : else
292 : {
293 0 : ptClickedOn = GetCurEntry();
294 0 : if ( !ptClickedOn )
295 0 : break;
296 0 : aWhere = GetEntryPosition(ptClickedOn);
297 : }
298 0 : UserData* pData = static_cast<UserData*>(ptClickedOn->GetUserData());
299 0 : uno::Reference< report::XFunctionsSupplier> xSupplier(pData->getContent(),uno::UNO_QUERY);
300 0 : uno::Reference< report::XFunctions> xFunctions(pData->getContent(),uno::UNO_QUERY);
301 0 : uno::Reference< report::XGroup> xGroup(pData->getContent(),uno::UNO_QUERY);
302 0 : bool bDeleteAllowed = m_rController.isEditable() && (xGroup.is() ||
303 0 : uno::Reference< report::XFunction>(pData->getContent(),uno::UNO_QUERY).is());
304 0 : PopupMenu aContextMenu( ModuleRes( RID_MENU_NAVIGATOR ) );
305 :
306 0 : sal_uInt16 nCount = aContextMenu.GetItemCount();
307 0 : for (sal_uInt16 i = 0; i < nCount; ++i)
308 : {
309 0 : if ( MenuItemType::SEPARATOR != aContextMenu.GetItemType(i))
310 : {
311 0 : sal_uInt16 nId = aContextMenu.GetItemId(i);
312 :
313 0 : aContextMenu.CheckItem(nId,m_rController.isCommandChecked(nId));
314 0 : bool bEnabled = m_rController.isCommandEnabled(nId);
315 0 : if ( nId == SID_RPT_NEW_FUNCTION )
316 0 : aContextMenu.EnableItem(nId,m_rController.isEditable() && (xSupplier.is() || xFunctions.is()) );
317 : // special condition, check for function and group
318 0 : else if ( nId == SID_DELETE )
319 0 : aContextMenu.EnableItem(SID_DELETE,bDeleteAllowed);
320 : else
321 0 : aContextMenu.EnableItem(nId,bEnabled);
322 : }
323 : }
324 0 : sal_uInt16 nId = aContextMenu.Execute(this, aWhere);
325 0 : if ( nId )
326 : {
327 0 : uno::Sequence< beans::PropertyValue> aArgs;
328 0 : if ( nId == SID_RPT_NEW_FUNCTION )
329 : {
330 0 : aArgs.realloc(1);
331 0 : aArgs[0].Value <<= (xFunctions.is() ? xFunctions : xSupplier->getFunctions());
332 : }
333 0 : else if ( nId == SID_DELETE )
334 : {
335 0 : if ( xGroup.is() )
336 0 : nId = SID_GROUP_REMOVE;
337 0 : aArgs.realloc(1);
338 0 : aArgs[0].Name = PROPERTY_GROUP;
339 0 : aArgs[0].Value <<= pData->getContent();
340 : }
341 0 : m_rController.executeUnChecked(nId,aArgs);
342 : }
343 :
344 0 : bHandled = true;
345 0 : } break;
346 : }
347 :
348 0 : if (!bHandled)
349 0 : SvTreeListBox::Command( rEvt );
350 0 : }
351 :
352 0 : sal_Int8 NavigatorTree::AcceptDrop( const AcceptDropEvent& _rEvt )
353 : {
354 0 : sal_Int8 nDropOption = DND_ACTION_NONE;
355 0 : ::Point aDropPos = _rEvt.maPosPixel;
356 0 : if (_rEvt.mbLeaving)
357 : {
358 0 : if (m_aDropActionTimer.IsActive())
359 0 : m_aDropActionTimer.Stop();
360 : }
361 : else
362 : {
363 0 : bool bNeedTrigger = false;
364 : // auf dem ersten Eintrag ?
365 0 : if ((aDropPos.Y() >= 0) && (aDropPos.Y() < GetEntryHeight()))
366 : {
367 0 : m_aDropActionType = DA_SCROLLUP;
368 0 : bNeedTrigger = true;
369 : }
370 0 : else if ((aDropPos.Y() < GetSizePixel().Height()) && (aDropPos.Y() >= GetSizePixel().Height() - GetEntryHeight()))
371 : {
372 0 : m_aDropActionType = DA_SCROLLDOWN;
373 0 : bNeedTrigger = true;
374 : }
375 : else
376 : {
377 0 : SvTreeListEntry* pDropppedOn = GetEntry(aDropPos);
378 0 : if (pDropppedOn && (GetChildCount(pDropppedOn) > 0) && !IsExpanded(pDropppedOn))
379 : {
380 0 : m_aDropActionType = DA_EXPANDNODE;
381 0 : bNeedTrigger = true;
382 : }
383 : }
384 :
385 0 : if (bNeedTrigger && (m_aTimerTriggered != aDropPos))
386 : {
387 : // neu anfangen zu zaehlen
388 0 : m_nTimerCounter = DROP_ACTION_TIMER_INITIAL_TICKS;
389 : // die Pos merken, da ich auch AcceptDrops bekomme, wenn sich die Maus gar nicht bewegt hat
390 0 : m_aTimerTriggered = aDropPos;
391 : // und den Timer los
392 0 : if (!m_aDropActionTimer.IsActive()) // gibt es den Timer schon ?
393 : {
394 0 : m_aDropActionTimer.SetTimeout(DROP_ACTION_TIMER_TICK_BASE);
395 0 : m_aDropActionTimer.Start();
396 : }
397 : }
398 0 : else if (!bNeedTrigger)
399 0 : m_aDropActionTimer.Stop();
400 : }
401 :
402 0 : return nDropOption;
403 : }
404 :
405 0 : sal_Int8 NavigatorTree::ExecuteDrop( const ExecuteDropEvent& /*_rEvt*/ )
406 : {
407 0 : return DND_ACTION_NONE;
408 : }
409 :
410 0 : void NavigatorTree::StartDrag( sal_Int8 /*_nAction*/, const Point& _rPosPixel )
411 : {
412 0 : m_pDragedEntry = GetEntry(_rPosPixel);
413 0 : if ( m_pDragedEntry )
414 : {
415 0 : EndSelection();
416 : }
417 0 : }
418 :
419 0 : IMPL_LINK_NOARG(NavigatorTree, OnDropActionTimer)
420 : {
421 0 : if (--m_nTimerCounter > 0)
422 0 : return 0L;
423 :
424 0 : switch ( m_aDropActionType )
425 : {
426 : case DA_EXPANDNODE:
427 : {
428 0 : SvTreeListEntry* pToExpand = GetEntry(m_aTimerTriggered);
429 0 : if (pToExpand && (GetChildCount(pToExpand) > 0) && !IsExpanded(pToExpand))
430 : // tja, eigentlich muesste ich noch testen, ob die Node nicht schon expandiert ist, aber ich
431 : // habe dazu weder in den Basisklassen noch im Model eine Methode gefunden ...
432 : // aber ich denke, die BK sollte es auch so vertragen
433 0 : Expand(pToExpand);
434 :
435 : // nach dem Expand habe ich im Gegensatz zum Scrollen natuerlich nix mehr zu tun
436 0 : m_aDropActionTimer.Stop();
437 : }
438 0 : break;
439 :
440 : case DA_SCROLLUP :
441 0 : ScrollOutputArea( 1 );
442 0 : m_nTimerCounter = DROP_ACTION_TIMER_SCROLL_TICKS;
443 0 : break;
444 :
445 : case DA_SCROLLDOWN :
446 0 : ScrollOutputArea( -1 );
447 0 : m_nTimerCounter = DROP_ACTION_TIMER_SCROLL_TICKS;
448 0 : break;
449 :
450 : }
451 :
452 0 : return 0L;
453 : }
454 :
455 :
456 0 : IMPL_LINK(NavigatorTree, OnEntrySelDesel, NavigatorTree*, /*pThis*/)
457 : {
458 0 : if ( !m_pSelectionListener->locked() )
459 : {
460 0 : m_pSelectionListener->lock();
461 0 : SvTreeListEntry* pEntry = GetCurEntry();
462 0 : uno::Any aSelection;
463 0 : if ( IsSelected(pEntry) )
464 0 : aSelection <<= static_cast<UserData*>(pEntry->GetUserData())->getContent();
465 0 : m_rController.select(aSelection);
466 0 : m_pSelectionListener->unlock();
467 : }
468 :
469 0 : return 0L;
470 : }
471 :
472 0 : void NavigatorTree::_selectionChanged( const lang::EventObject& aEvent ) throw (uno::RuntimeException)
473 : {
474 0 : m_pSelectionListener->lock();
475 0 : uno::Reference< view::XSelectionSupplier> xSelectionSupplier(aEvent.Source,uno::UNO_QUERY);
476 0 : uno::Any aSec = xSelectionSupplier->getSelection();
477 0 : uno::Sequence< uno::Reference< report::XReportComponent > > aSelection;
478 0 : aSec >>= aSelection;
479 0 : if ( !aSelection.getLength() )
480 : {
481 0 : uno::Reference< uno::XInterface> xSelection(aSec,uno::UNO_QUERY);
482 0 : SvTreeListEntry* pEntry = find(xSelection);
483 0 : if ( pEntry && !IsSelected(pEntry) )
484 : {
485 0 : Select(pEntry, true);
486 0 : SetCurEntry(pEntry);
487 : }
488 0 : else if ( !pEntry )
489 0 : SelectAll(false,false);
490 : }
491 : else
492 : {
493 0 : const uno::Reference< report::XReportComponent >* pIter = aSelection.getConstArray();
494 0 : const uno::Reference< report::XReportComponent >* pEnd = pIter + aSelection.getLength();
495 0 : for (; pIter != pEnd; ++pIter)
496 : {
497 0 : SvTreeListEntry* pEntry = find(*pIter);
498 0 : if ( pEntry && !IsSelected(pEntry) )
499 : {
500 0 : Select(pEntry, true);
501 0 : SetCurEntry(pEntry);
502 : }
503 : }
504 : }
505 0 : m_pSelectionListener->unlock();
506 0 : }
507 :
508 0 : SvTreeListEntry* NavigatorTree::insertEntry(const OUString& _sName,SvTreeListEntry* _pParent,sal_uInt16 _nImageId,sal_uLong _nPosition,UserData* _pData)
509 : {
510 0 : SvTreeListEntry* pEntry = NULL;
511 0 : if ( _nImageId )
512 : {
513 0 : const Image aImage( m_aNavigatorImages.GetImage( _nImageId ) );
514 0 : pEntry = InsertEntry(_sName,aImage,aImage,_pParent,false,_nPosition,_pData);
515 : }
516 : else
517 0 : pEntry = InsertEntry(_sName,_pParent,false,_nPosition,_pData);
518 0 : return pEntry;
519 : }
520 :
521 0 : void NavigatorTree::traverseSection(const uno::Reference< report::XSection>& _xSection,SvTreeListEntry* _pParent,sal_uInt16 _nImageId,sal_uLong _nPosition)
522 : {
523 0 : SvTreeListEntry* pSection = insertEntry(_xSection->getName(),_pParent,_nImageId,_nPosition,new UserData(this,_xSection));
524 0 : const sal_Int32 nCount = _xSection->getCount();
525 0 : for (sal_Int32 i = 0; i < nCount; ++i)
526 : {
527 0 : uno::Reference< report::XReportComponent> xElement(_xSection->getByIndex(i),uno::UNO_QUERY_THROW);
528 : OSL_ENSURE(xElement.is(),"Found report element which is NULL!");
529 0 : insertEntry(lcl_getName(xElement.get()),pSection,lcl_getImageId(xElement),TREELIST_APPEND,new UserData(this,xElement));
530 0 : uno::Reference< report::XReportDefinition> xSubReport(xElement,uno::UNO_QUERY);
531 0 : if ( xSubReport.is() )
532 : {
533 0 : m_pMasterReport = find(_xSection->getReportDefinition());
534 0 : reportdesign::OReportVisitor aSubVisitor(this);
535 0 : aSubVisitor.start(xSubReport);
536 : }
537 0 : }
538 0 : }
539 :
540 0 : void NavigatorTree::traverseFunctions(const uno::Reference< report::XFunctions>& _xFunctions,SvTreeListEntry* _pParent)
541 : {
542 0 : SvTreeListEntry* pFunctions = insertEntry(OUString(ModuleRes(RID_STR_FUNCTIONS)), _pParent, SID_RPT_NEW_FUNCTION, TREELIST_APPEND, new UserData(this,_xFunctions));
543 0 : const sal_Int32 nCount = _xFunctions->getCount();
544 0 : for (sal_Int32 i = 0; i< nCount; ++i)
545 : {
546 0 : uno::Reference< report::XFunction> xElement(_xFunctions->getByIndex(i),uno::UNO_QUERY);
547 0 : insertEntry(xElement->getName(),pFunctions,SID_RPT_NEW_FUNCTION,TREELIST_APPEND,new UserData(this,xElement));
548 0 : }
549 0 : }
550 :
551 0 : SvTreeListEntry* NavigatorTree::find(const uno::Reference< uno::XInterface >& _xContent)
552 : {
553 0 : SvTreeListEntry* pRet = NULL;
554 0 : if ( _xContent.is() )
555 : {
556 0 : SvTreeListEntry* pCurrent = First();
557 0 : while ( pCurrent )
558 : {
559 0 : UserData* pData = static_cast<UserData*>(pCurrent->GetUserData());
560 : OSL_ENSURE(pData,"No UserData set an entry!");
561 0 : if ( pData->getContent() == _xContent )
562 : {
563 0 : pRet = pCurrent;
564 0 : break;
565 : }
566 0 : pCurrent = Next(pCurrent);
567 : }
568 : }
569 0 : return pRet;
570 : }
571 :
572 : // ITraverseReport
573 :
574 0 : void NavigatorTree::traverseReport(const uno::Reference< report::XReportDefinition>& _xReport)
575 : {
576 0 : insertEntry(_xReport->getName(),m_pMasterReport,SID_SELECT_REPORT,TREELIST_APPEND,new UserData(this,_xReport));
577 0 : }
578 :
579 0 : void NavigatorTree::traverseReportFunctions(const uno::Reference< report::XFunctions>& _xFunctions)
580 : {
581 0 : SvTreeListEntry* pReport = find(_xFunctions->getParent());
582 0 : traverseFunctions(_xFunctions,pReport);
583 0 : }
584 :
585 0 : void NavigatorTree::traverseReportHeader(const uno::Reference< report::XSection>& _xSection)
586 : {
587 0 : SvTreeListEntry* pReport = find(_xSection->getReportDefinition());
588 0 : traverseSection(_xSection,pReport,SID_REPORTHEADERFOOTER);
589 0 : }
590 :
591 0 : void NavigatorTree::traverseReportFooter(const uno::Reference< report::XSection>& _xSection)
592 : {
593 0 : SvTreeListEntry* pReport = find(_xSection->getReportDefinition());
594 0 : traverseSection(_xSection,pReport,SID_REPORTHEADERFOOTER);
595 0 : }
596 :
597 0 : void NavigatorTree::traversePageHeader(const uno::Reference< report::XSection>& _xSection)
598 : {
599 0 : SvTreeListEntry* pReport = find(_xSection->getReportDefinition());
600 0 : traverseSection(_xSection,pReport,SID_PAGEHEADERFOOTER);
601 0 : }
602 :
603 0 : void NavigatorTree::traversePageFooter(const uno::Reference< report::XSection>& _xSection)
604 : {
605 0 : SvTreeListEntry* pReport = find(_xSection->getReportDefinition());
606 0 : traverseSection(_xSection,pReport,SID_PAGEHEADERFOOTER);
607 0 : }
608 :
609 0 : void NavigatorTree::traverseGroups(const uno::Reference< report::XGroups>& _xGroups)
610 : {
611 0 : SvTreeListEntry* pReport = find(_xGroups->getReportDefinition());
612 0 : insertEntry(OUString(ModuleRes(RID_STR_GROUPS)), pReport, SID_SORTINGANDGROUPING, TREELIST_APPEND, new UserData(this,_xGroups));
613 0 : }
614 :
615 0 : void NavigatorTree::traverseGroup(const uno::Reference< report::XGroup>& _xGroup)
616 : {
617 0 : uno::Reference< report::XGroups> xGroups(_xGroup->getParent(),uno::UNO_QUERY);
618 0 : SvTreeListEntry* pGroups = find(xGroups);
619 : OSL_ENSURE(pGroups,"No Groups inserted so far. Why!");
620 0 : insertEntry(_xGroup->getExpression(),pGroups,SID_GROUP,rptui::getPositionInIndexAccess(xGroups.get(),_xGroup),new UserData(this,_xGroup));
621 0 : }
622 :
623 0 : void NavigatorTree::traverseGroupFunctions(const uno::Reference< report::XFunctions>& _xFunctions)
624 : {
625 0 : SvTreeListEntry* pGroup = find(_xFunctions->getParent());
626 0 : traverseFunctions(_xFunctions,pGroup);
627 0 : }
628 :
629 0 : void NavigatorTree::traverseGroupHeader(const uno::Reference< report::XSection>& _xSection)
630 : {
631 0 : SvTreeListEntry* pGroup = find(_xSection->getGroup());
632 : OSL_ENSURE(pGroup,"No group found");
633 0 : traverseSection(_xSection,pGroup,SID_GROUPHEADER,1);
634 0 : }
635 :
636 0 : void NavigatorTree::traverseGroupFooter(const uno::Reference< report::XSection>& _xSection)
637 : {
638 0 : SvTreeListEntry* pGroup = find(_xSection->getGroup());
639 : OSL_ENSURE(pGroup,"No group found");
640 0 : traverseSection(_xSection,pGroup,SID_GROUPFOOTER);
641 0 : }
642 :
643 0 : void NavigatorTree::traverseDetail(const uno::Reference< report::XSection>& _xSection)
644 : {
645 0 : uno::Reference< report::XReportDefinition> xReport = _xSection->getReportDefinition();
646 0 : SvTreeListEntry* pParent = find(xReport);
647 0 : traverseSection(_xSection,pParent,SID_ICON_DETAIL);
648 0 : }
649 :
650 0 : void NavigatorTree::_propertyChanged(const beans::PropertyChangeEvent& _rEvent) throw( uno::RuntimeException)
651 : {
652 0 : uno::Reference< report::XReportDefinition> xReport(_rEvent.Source,uno::UNO_QUERY);
653 0 : if ( xReport.is() )
654 : {
655 0 : bool bEnabled = false;
656 0 : _rEvent.NewValue >>= bEnabled;
657 0 : if ( bEnabled )
658 : {
659 0 : SvTreeListEntry* pParent = find(xReport);
660 0 : if ( _rEvent.PropertyName == PROPERTY_REPORTHEADERON )
661 : {
662 0 : sal_uLong nPos = xReport->getReportHeaderOn() ? 2 : 1;
663 0 : traverseSection(xReport->getReportHeader(),pParent,SID_REPORTHEADERFOOTER,nPos);
664 : }
665 0 : else if ( _rEvent.PropertyName == PROPERTY_PAGEHEADERON )
666 : {
667 0 : traverseSection(xReport->getPageHeader(),pParent, SID_PAGEHEADERFOOTER,1);
668 : }
669 0 : else if ( _rEvent.PropertyName == PROPERTY_PAGEFOOTERON )
670 0 : traverseSection(xReport->getPageFooter(),pParent, SID_PAGEHEADERFOOTER);
671 0 : else if ( _rEvent.PropertyName == PROPERTY_REPORTFOOTERON )
672 : {
673 0 : sal_uLong nPos = xReport->getPageFooterOn() ? (GetLevelChildCount(pParent) - 1) : TREELIST_APPEND;
674 0 : traverseSection(xReport->getReportFooter(),pParent,SID_REPORTHEADERFOOTER,nPos);
675 : }
676 : }
677 0 : }
678 0 : }
679 :
680 0 : void NavigatorTree::_elementInserted( const container::ContainerEvent& _rEvent )
681 : {
682 0 : SvTreeListEntry* pEntry = find(_rEvent.Source);
683 0 : uno::Reference<beans::XPropertySet> xProp(_rEvent.Element,uno::UNO_QUERY_THROW);
684 0 : OUString sName;
685 0 : uno::Reference< beans::XPropertySetInfo> xInfo = xProp->getPropertySetInfo();
686 0 : if ( xInfo.is() )
687 : {
688 0 : if ( xInfo->hasPropertyByName(PROPERTY_NAME) )
689 0 : xProp->getPropertyValue(PROPERTY_NAME) >>= sName;
690 0 : else if ( xInfo->hasPropertyByName(PROPERTY_EXPRESSION) )
691 0 : xProp->getPropertyValue(PROPERTY_EXPRESSION) >>= sName;
692 : }
693 0 : uno::Reference< report::XGroup> xGroup(xProp,uno::UNO_QUERY);
694 0 : if ( xGroup.is() )
695 : {
696 0 : reportdesign::OReportVisitor aSubVisitor(this);
697 0 : aSubVisitor.start(xGroup);
698 : }
699 : else
700 : {
701 0 : uno::Reference< report::XReportComponent> xElement(xProp,uno::UNO_QUERY);
702 0 : if ( xProp.is() )
703 0 : sName = lcl_getName(xProp);
704 0 : insertEntry(sName,pEntry,(!xElement.is() ? sal_uInt16(SID_RPT_NEW_FUNCTION) : lcl_getImageId(xElement)),TREELIST_APPEND,new UserData(this,xProp));
705 : }
706 0 : if ( !IsExpanded(pEntry) )
707 0 : Expand(pEntry);
708 0 : }
709 :
710 0 : void NavigatorTree::_elementRemoved( const container::ContainerEvent& _rEvent )
711 : {
712 0 : uno::Reference<beans::XPropertySet> xProp(_rEvent.Element,uno::UNO_QUERY);
713 0 : SvTreeListEntry* pEntry = find(xProp);
714 : OSL_ENSURE(pEntry,"NavigatorTree::_elementRemoved: No Entry found!");
715 :
716 0 : if ( pEntry )
717 : {
718 0 : SvTreeListEntry* pParent = GetParent(pEntry);
719 0 : removeEntry(pEntry);
720 0 : PaintEntry(pParent);
721 0 : }
722 0 : }
723 :
724 0 : void NavigatorTree::_elementReplaced( const container::ContainerEvent& _rEvent )
725 : {
726 0 : uno::Reference<beans::XPropertySet> xProp(_rEvent.ReplacedElement,uno::UNO_QUERY);
727 0 : SvTreeListEntry* pEntry = find(xProp);
728 0 : if ( pEntry )
729 : {
730 0 : UserData* pData = static_cast<UserData*>(pEntry->GetUserData());
731 0 : xProp.set(_rEvent.Element,uno::UNO_QUERY);
732 0 : pData->setContent(xProp);
733 0 : OUString sName;
734 0 : xProp->getPropertyValue(PROPERTY_NAME) >>= sName;
735 0 : SetEntryText(pEntry,sName);
736 0 : }
737 0 : }
738 :
739 0 : void NavigatorTree::_disposing(const lang::EventObject& _rSource)
740 : throw (uno::RuntimeException, std::exception)
741 : {
742 0 : removeEntry(find(_rSource.Source));
743 0 : }
744 :
745 0 : void NavigatorTree::removeEntry(SvTreeListEntry* _pEntry,bool _bRemove)
746 : {
747 0 : if ( _pEntry )
748 : {
749 0 : SvTreeListEntry* pChild = FirstChild(_pEntry);
750 0 : while( pChild )
751 : {
752 0 : removeEntry(pChild,false);
753 0 : pChild = NextSibling(pChild);
754 : }
755 0 : delete static_cast<UserData*>(_pEntry->GetUserData());
756 0 : if ( _bRemove )
757 0 : GetModel()->Remove(_pEntry);
758 : }
759 0 : }
760 :
761 0 : NavigatorTree::UserData::UserData(NavigatorTree* _pTree,const uno::Reference<uno::XInterface>& _xContent)
762 : : OPropertyChangeListener(m_aMutex)
763 : , OContainerListener(m_aMutex)
764 : , m_xContent(_xContent)
765 0 : , m_pTree(_pTree)
766 : {
767 0 : uno::Reference<beans::XPropertySet> xProp(m_xContent,uno::UNO_QUERY);
768 0 : if ( xProp.is() )
769 : {
770 0 : uno::Reference< beans::XPropertySetInfo> xInfo = xProp->getPropertySetInfo();
771 0 : if ( xInfo.is() )
772 : {
773 0 : m_pListener = new ::comphelper::OPropertyChangeMultiplexer(this,xProp);
774 0 : if ( xInfo->hasPropertyByName(PROPERTY_NAME) )
775 0 : m_pListener->addProperty(PROPERTY_NAME);
776 0 : else if ( xInfo->hasPropertyByName(PROPERTY_EXPRESSION) )
777 0 : m_pListener->addProperty(PROPERTY_EXPRESSION);
778 0 : if ( xInfo->hasPropertyByName(PROPERTY_DATAFIELD) )
779 0 : m_pListener->addProperty(PROPERTY_DATAFIELD);
780 0 : if ( xInfo->hasPropertyByName(PROPERTY_LABEL) )
781 0 : m_pListener->addProperty(PROPERTY_LABEL);
782 0 : if ( xInfo->hasPropertyByName(PROPERTY_HEADERON) )
783 0 : m_pListener->addProperty(PROPERTY_HEADERON);
784 0 : if ( xInfo->hasPropertyByName(PROPERTY_FOOTERON) )
785 0 : m_pListener->addProperty(PROPERTY_FOOTERON);
786 0 : }
787 : }
788 0 : uno::Reference< container::XContainer> xContainer(m_xContent,uno::UNO_QUERY);
789 0 : if ( xContainer.is() )
790 : {
791 0 : m_pContainerListener = new ::comphelper::OContainerListenerAdapter(this,xContainer);
792 0 : }
793 0 : }
794 :
795 0 : NavigatorTree::UserData::~UserData()
796 : {
797 0 : if ( m_pContainerListener.is() )
798 0 : m_pContainerListener->dispose();
799 0 : if ( m_pListener.is() )
800 0 : m_pListener->dispose();
801 0 : }
802 :
803 : // OPropertyChangeListener
804 0 : void NavigatorTree::UserData::_propertyChanged(const beans::PropertyChangeEvent& _rEvent) throw( uno::RuntimeException)
805 : {
806 0 : SvTreeListEntry* pEntry = m_pTree->find(_rEvent.Source);
807 : OSL_ENSURE(pEntry,"No entry could be found! Why not!");
808 0 : const bool bFooterOn = (PROPERTY_FOOTERON == _rEvent.PropertyName);
809 : try
810 : {
811 0 : if ( bFooterOn || PROPERTY_HEADERON == _rEvent.PropertyName )
812 : {
813 0 : sal_Int32 nPos = 1;
814 0 : uno::Reference< report::XGroup> xGroup(_rEvent.Source,uno::UNO_QUERY);
815 0 : ::std::mem_fun_t< bool,OGroupHelper> pIsOn = ::std::mem_fun(&OGroupHelper::getHeaderOn);
816 0 : ::std::mem_fun_t< uno::Reference<report::XSection> ,OGroupHelper> pMemFunSection = ::std::mem_fun(&OGroupHelper::getHeader);
817 0 : if ( bFooterOn )
818 : {
819 0 : pIsOn = ::std::mem_fun(&OGroupHelper::getFooterOn);
820 0 : pMemFunSection = ::std::mem_fun(&OGroupHelper::getFooter);
821 0 : nPos = m_pTree->GetChildCount(pEntry) - 1;
822 : }
823 :
824 0 : OGroupHelper aGroupHelper(xGroup);
825 0 : if ( pIsOn(&aGroupHelper) )
826 : {
827 0 : if ( bFooterOn )
828 0 : ++nPos;
829 0 : m_pTree->traverseSection(pMemFunSection(&aGroupHelper),pEntry,bFooterOn ? SID_GROUPFOOTER : SID_GROUPHEADER,nPos);
830 0 : }
831 : }
832 0 : else if ( PROPERTY_EXPRESSION == _rEvent.PropertyName)
833 : {
834 0 : OUString sNewName;
835 0 : _rEvent.NewValue >>= sNewName;
836 0 : m_pTree->SetEntryText(pEntry,sNewName);
837 : }
838 0 : else if ( PROPERTY_DATAFIELD == _rEvent.PropertyName || PROPERTY_LABEL == _rEvent.PropertyName || PROPERTY_NAME == _rEvent.PropertyName )
839 : {
840 0 : uno::Reference<beans::XPropertySet> xProp(_rEvent.Source,uno::UNO_QUERY);
841 0 : m_pTree->SetEntryText(pEntry,lcl_getName(xProp));
842 : }
843 : }
844 0 : catch(const uno::Exception &)
845 : {}
846 0 : }
847 :
848 0 : void NavigatorTree::UserData::_elementInserted( const container::ContainerEvent& _rEvent ) throw(uno::RuntimeException, std::exception)
849 : {
850 0 : m_pTree->_elementInserted( _rEvent );
851 0 : }
852 :
853 0 : void NavigatorTree::UserData::_elementRemoved( const container::ContainerEvent& _rEvent )
854 : throw (uno::RuntimeException, std::exception)
855 : {
856 0 : m_pTree->_elementRemoved( _rEvent );
857 0 : }
858 :
859 0 : void NavigatorTree::UserData::_elementReplaced( const container::ContainerEvent& _rEvent ) throw(uno::RuntimeException, std::exception)
860 : {
861 0 : m_pTree->_elementReplaced( _rEvent );
862 0 : }
863 :
864 0 : void NavigatorTree::UserData::_disposing(const lang::EventObject& _rSource)
865 : throw (uno::RuntimeException, std::exception)
866 : {
867 0 : m_pTree->_disposing( _rSource );
868 0 : }
869 :
870 0 : Size NavigatorTree::GetOptimalSize() const
871 : {
872 0 : return LogicToPixel(Size(100, 70), MAP_APPFONT);
873 : }
874 :
875 : // class ONavigatorImpl
876 0 : class ONavigatorImpl: private boost::noncopyable
877 : {
878 : public:
879 : ONavigatorImpl(OReportController& _rController,ONavigator* _pParent);
880 :
881 : uno::Reference< report::XReportDefinition> m_xReport;
882 : ::rptui::OReportController& m_rController;
883 : ::std::unique_ptr<NavigatorTree> m_pNavigatorTree;
884 : };
885 :
886 0 : ONavigatorImpl::ONavigatorImpl(OReportController& _rController,ONavigator* _pParent)
887 : :m_xReport(_rController.getReportDefinition())
888 : ,m_rController(_rController)
889 0 : ,m_pNavigatorTree(new NavigatorTree(_pParent->get<vcl::Window>("box"),_rController))
890 : {
891 0 : reportdesign::OReportVisitor aVisitor(m_pNavigatorTree.get());
892 0 : aVisitor.start(m_xReport);
893 0 : m_pNavigatorTree->Expand(m_pNavigatorTree->find(m_xReport));
894 0 : lang::EventObject aEvent(m_rController);
895 0 : m_pNavigatorTree->_selectionChanged(aEvent);
896 0 : }
897 :
898 : // class ONavigator
899 0 : ONavigator::ONavigator(vcl::Window* _pParent ,OReportController& _rController)
900 0 : : FloatingWindow( _pParent, "FloatingNavigator", "modules/dbreport/ui/floatingnavigator.ui")
901 : {
902 0 : m_pImpl.reset(new ONavigatorImpl(_rController,this));
903 :
904 0 : m_pImpl->m_pNavigatorTree->Show();
905 0 : m_pImpl->m_pNavigatorTree->GrabFocus();
906 0 : Show();
907 0 : }
908 :
909 0 : void ONavigator::GetFocus()
910 : {
911 0 : Window::GetFocus();
912 0 : if ( m_pImpl->m_pNavigatorTree.get() )
913 0 : m_pImpl->m_pNavigatorTree->GrabFocus();
914 0 : }
915 :
916 6 : } // rptui
917 :
918 :
919 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|