bump product version to 6.3.0.0.beta1
[LibreOffice.git] / reportdesign / source / ui / dlg / Navigator.cxx
blob6dd851e5bd0cdc02b1acfb5823fb2d9ce3728faf
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <Navigator.hxx>
22 #include <strings.hxx>
23 #include <bitmaps.hlst>
24 #include <ReportController.hxx>
25 #include <UITools.hxx>
26 #include <RptUndo.hxx>
27 #include <reportformula.hxx>
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.h>
36 #include <strings.hrc>
37 #include <rptui_slotid.hrc>
38 #include <comphelper/propmultiplex.hxx>
39 #include <comphelper/containermultiplexer.hxx>
40 #include <cppuhelper/basemutex.hxx>
41 #include <comphelper/SelectionMultiplex.hxx>
42 #include <vcl/treelistbox.hxx>
43 #include <vcl/treelistentry.hxx>
44 #include <vcl/commandevent.hxx>
45 #include <svl/solar.hrc>
46 #include <ReportVisitor.hxx>
47 #include <core_resource.hxx>
48 #include <rtl/ref.hxx>
50 #include <memory>
51 #include <algorithm>
53 #define DROP_ACTION_TIMER_INITIAL_TICKS 10
54 #define DROP_ACTION_TIMER_SCROLL_TICKS 3
55 #define DROP_ACTION_TIMER_TICK_BASE 10
57 namespace rptui
59 using namespace ::com::sun::star;
60 using namespace utl;
61 using namespace ::comphelper;
63 static OUString lcl_getImageId(const uno::Reference< report::XReportComponent>& _xElement)
65 OUString sId;
66 uno::Reference< report::XFixedLine> xFixedLine(_xElement,uno::UNO_QUERY);
67 if ( uno::Reference< report::XFixedText>(_xElement,uno::UNO_QUERY).is() )
68 sId = RID_SVXBMP_FM_FIXEDTEXT;
69 else if ( xFixedLine.is() )
70 sId = xFixedLine->getOrientation() ? OUStringLiteral(RID_SVXBMP_INSERT_VFIXEDLINE) : OUStringLiteral(RID_SVXBMP_INSERT_HFIXEDLINE);
71 else if ( uno::Reference< report::XFormattedField>(_xElement,uno::UNO_QUERY).is() )
72 sId = RID_SVXBMP_FM_EDIT;
73 else if ( uno::Reference< report::XImageControl>(_xElement,uno::UNO_QUERY).is() )
74 sId = RID_SVXBMP_FM_IMAGECONTROL;
75 else if ( uno::Reference< report::XShape>(_xElement,uno::UNO_QUERY).is() )
76 sId = RID_SVXBMP_DRAWTBX_CS_BASIC;
77 return sId;
80 static OUString lcl_getName(const uno::Reference< beans::XPropertySet>& _xElement)
82 OSL_ENSURE(_xElement.is(),"Found report element which is NULL!");
83 OUString sTempName;
84 _xElement->getPropertyValue(PROPERTY_NAME) >>= sTempName;
85 OUStringBuffer sName = sTempName;
86 uno::Reference< report::XFixedText> xFixedText(_xElement,uno::UNO_QUERY);
87 uno::Reference< report::XReportControlModel> xReportModel(_xElement,uno::UNO_QUERY);
88 if ( xFixedText.is() )
90 sName.append(" : ");
91 sName.append(xFixedText->getLabel());
93 else if ( xReportModel.is() && _xElement->getPropertySetInfo()->hasPropertyByName(PROPERTY_DATAFIELD) )
95 ReportFormula aFormula( xReportModel->getDataField() );
96 if ( aFormula.isValid() )
98 sName.append(" : ");
99 sName.append( aFormula.getUndecoratedContent() );
102 return sName.makeStringAndClear();
106 class NavigatorTree : public ::cppu::BaseMutex
107 , public SvTreeListBox
108 , public reportdesign::ITraverseReport
109 , public comphelper::OSelectionChangeListener
110 , public ::comphelper::OPropertyChangeListener
112 class UserData;
113 friend class UserData;
114 class UserData : public ::cppu::BaseMutex
115 ,public ::comphelper::OPropertyChangeListener
116 ,public ::comphelper::OContainerListener
118 uno::Reference< uno::XInterface > m_xContent;
119 ::rtl::Reference< comphelper::OPropertyChangeMultiplexer> m_pListener;
120 ::rtl::Reference< comphelper::OContainerListenerAdapter> m_pContainerListener;
121 VclPtr<NavigatorTree> m_pTree;
122 public:
123 UserData(NavigatorTree* _pTree,const uno::Reference<uno::XInterface>& _xContent);
124 virtual ~UserData() override;
126 const uno::Reference< uno::XInterface >& getContent() const { return m_xContent; }
127 void setContent(const uno::Reference< uno::XInterface >& _xContent) { m_xContent = _xContent; }
129 protected:
130 // OPropertyChangeListener
131 virtual void _propertyChanged(const beans::PropertyChangeEvent& _rEvent) override;
133 // OContainerListener
134 virtual void _elementInserted( const container::ContainerEvent& _rEvent ) override;
135 virtual void _elementRemoved( const container::ContainerEvent& Event ) override;
136 virtual void _elementReplaced( const container::ContainerEvent& _rEvent ) override;
137 virtual void _disposing(const lang::EventObject& _rSource) override;
140 enum DROP_ACTION { DA_SCROLLUP, DA_SCROLLDOWN, DA_EXPANDNODE };
141 AutoTimer m_aDropActionTimer;
142 Point m_aTimerTriggered; // position at which the DropTimer started
143 DROP_ACTION m_aDropActionType;
144 OReportController& m_rController;
145 SvTreeListEntry* m_pMasterReport;
146 SvTreeListEntry* m_pDragedEntry;
147 ::rtl::Reference< comphelper::OPropertyChangeMultiplexer> m_pReportListener;
148 ::rtl::Reference< comphelper::OSelectionChangeMultiplexer> m_pSelectionListener;
149 unsigned short m_nTimerCounter;
151 SvTreeListEntry* insertEntry(const OUString& _sName,SvTreeListEntry* _pParent, const OUString& rImageId, sal_uLong _nPosition,UserData* _pData);
152 void traverseSection(const uno::Reference< report::XSection>& _xSection,SvTreeListEntry* _pParent, const OUString& rImageId, sal_uLong _nPosition = TREELIST_APPEND);
153 void traverseFunctions(const uno::Reference< report::XFunctions>& _xFunctions,SvTreeListEntry* _pParent);
155 protected:
156 virtual void Command( const CommandEvent& rEvt ) override;
157 // DragSourceHelper overridables
158 virtual void StartDrag( sal_Int8 nAction, const Point& rPosPixel ) override;
159 // DropTargetHelper overridables
160 virtual sal_Int8 AcceptDrop( const AcceptDropEvent& _rEvt ) override;
161 virtual sal_Int8 ExecuteDrop( const ExecuteDropEvent& _rEvt ) override;
163 // OSelectionChangeListener
164 virtual void _disposing(const lang::EventObject& _rSource) override;
166 // OPropertyChangeListener
167 virtual void _propertyChanged(const beans::PropertyChangeEvent& _rEvent) override;
169 // OContainerListener Helper
170 void _elementInserted( const container::ContainerEvent& _rEvent );
171 void _elementRemoved( const container::ContainerEvent& Event );
172 void _elementReplaced( const container::ContainerEvent& _rEvent );
174 public:
175 NavigatorTree(vcl::Window* pParent,OReportController& _rController );
176 virtual ~NavigatorTree() override;
177 virtual void dispose() override;
179 DECL_LINK(OnEntrySelDesel, SvTreeListBox*, void);
180 DECL_LINK( OnDropActionTimer, Timer*, void );
182 virtual void _selectionChanged( const lang::EventObject& aEvent ) override;
184 // ITraverseReport
185 virtual void traverseReport(const uno::Reference< report::XReportDefinition>& _xReport) override;
186 virtual void traverseReportFunctions(const uno::Reference< report::XFunctions>& _xFunctions) override;
187 virtual void traverseReportHeader(const uno::Reference< report::XSection>& _xSection) override;
188 virtual void traverseReportFooter(const uno::Reference< report::XSection>& _xSection) override;
189 virtual void traversePageHeader(const uno::Reference< report::XSection>& _xSection) override;
190 virtual void traversePageFooter(const uno::Reference< report::XSection>& _xSection) override;
192 virtual void traverseGroups(const uno::Reference< report::XGroups>& _xGroups) override;
193 virtual void traverseGroup(const uno::Reference< report::XGroup>& _xGroup) override;
194 virtual void traverseGroupFunctions(const uno::Reference< report::XFunctions>& _xFunctions) override;
195 virtual void traverseGroupHeader(const uno::Reference< report::XSection>& _xSection) override;
196 virtual void traverseGroupFooter(const uno::Reference< report::XSection>& _xSection) override;
198 virtual void traverseDetail(const uno::Reference< report::XSection>& _xSection) override;
200 SvTreeListEntry* find(const uno::Reference< uno::XInterface >& _xContent);
201 void removeEntry(SvTreeListEntry* _pEntry,bool _bRemove = true);
203 virtual Size GetOptimalSize() const override;
204 private:
205 using SvTreeListBox::ExecuteDrop;
208 NavigatorTree::NavigatorTree( vcl::Window* pParent,OReportController& _rController )
209 :SvTreeListBox( pParent, WB_TABSTOP| WB_HASBUTTONS|WB_HASLINES|WB_BORDER|WB_HSCROLL|WB_HASBUTTONSATROOT )
210 ,comphelper::OSelectionChangeListener()
211 ,OPropertyChangeListener(m_aMutex)
212 ,m_aTimerTriggered(-1,-1)
213 ,m_aDropActionType( DA_SCROLLUP )
214 ,m_rController(_rController)
215 ,m_pMasterReport(nullptr)
216 ,m_pDragedEntry(nullptr)
217 ,m_nTimerCounter( DROP_ACTION_TIMER_INITIAL_TICKS )
219 set_hexpand(true);
220 set_vexpand(true);
222 m_pReportListener = new OPropertyChangeMultiplexer(this,m_rController.getReportDefinition().get());
223 m_pReportListener->addProperty(PROPERTY_PAGEHEADERON);
224 m_pReportListener->addProperty(PROPERTY_PAGEFOOTERON);
225 m_pReportListener->addProperty(PROPERTY_REPORTHEADERON);
226 m_pReportListener->addProperty(PROPERTY_REPORTFOOTERON);
228 m_pSelectionListener = new OSelectionChangeMultiplexer(this,&m_rController);
230 SetHelpId( HID_REPORT_NAVIGATOR_TREE );
232 SetNodeBitmaps(
233 Image(StockImage::Yes, RID_SVXBMP_COLLAPSEDNODE),
234 Image(StockImage::Yes, RID_SVXBMP_EXPANDEDNODE)
237 SetDragDropMode(DragDropMode::ALL);
238 EnableInplaceEditing( false );
239 SetSelectionMode(SelectionMode::Multiple);
240 Clear();
242 m_aDropActionTimer.SetInvokeHandler(LINK(this, NavigatorTree, OnDropActionTimer));
243 SetSelectHdl(LINK(this, NavigatorTree, OnEntrySelDesel));
244 SetDeselectHdl(LINK(this, NavigatorTree, OnEntrySelDesel));
247 NavigatorTree::~NavigatorTree()
249 disposeOnce();
252 void NavigatorTree::dispose()
254 SvTreeListEntry* pCurrent = First();
255 while ( pCurrent )
257 delete static_cast<UserData*>(pCurrent->GetUserData());
258 pCurrent = Next(pCurrent);
260 m_pReportListener->dispose();
261 SvTreeListBox::dispose();
264 namespace
266 sal_uInt16 mapIdent(const OString& rIdent)
268 if (rIdent == "sorting")
269 return SID_SORTINGANDGROUPING;
270 else if (rIdent == "page")
271 return SID_PAGEHEADERFOOTER;
272 else if (rIdent == "report")
273 return SID_REPORTHEADERFOOTER;
274 else if (rIdent == "function")
275 return SID_RPT_NEW_FUNCTION;
276 else if (rIdent == "properties")
277 return SID_SHOW_PROPERTYBROWSER;
278 else if (rIdent == "delete")
279 return SID_DELETE;
280 return 0;
284 void NavigatorTree::Command( const CommandEvent& rEvt )
286 bool bHandled = false;
287 switch( rEvt.GetCommand())
289 case CommandEventId::ContextMenu:
291 // the point that was clicked on
292 SvTreeListEntry* ptClickedOn = nullptr;
293 ::Point aWhere;
294 if (rEvt.IsMouseEvent())
296 aWhere = rEvt.GetMousePosPixel();
297 ptClickedOn = GetEntry(aWhere);
298 if (ptClickedOn == nullptr)
299 break;
300 if ( !IsSelected(ptClickedOn) )
302 SelectAll(false);
303 Select(ptClickedOn);
304 SetCurEntry(ptClickedOn);
307 else
309 ptClickedOn = GetCurEntry();
310 if ( !ptClickedOn )
311 break;
312 aWhere = GetEntryPosition(ptClickedOn);
314 UserData* pData = static_cast<UserData*>(ptClickedOn->GetUserData());
315 uno::Reference< report::XFunctionsSupplier> xSupplier(pData->getContent(),uno::UNO_QUERY);
316 uno::Reference< report::XFunctions> xFunctions(pData->getContent(),uno::UNO_QUERY);
317 uno::Reference< report::XGroup> xGroup(pData->getContent(),uno::UNO_QUERY);
318 bool bDeleteAllowed = m_rController.isEditable() && (xGroup.is() ||
319 uno::Reference< report::XFunction>(pData->getContent(),uno::UNO_QUERY).is());
321 VclBuilder aBuilder(nullptr, VclBuilderContainer::getUIRootDir(), "modules/dbreport/ui/navigatormenu.ui", "");
322 VclPtr<PopupMenu> aContextMenu(aBuilder.get_menu("menu"));
324 sal_uInt16 nCount = aContextMenu->GetItemCount();
325 for (sal_uInt16 i = 0; i < nCount; ++i)
327 if ( MenuItemType::SEPARATOR != aContextMenu->GetItemType(i))
329 sal_uInt16 nMId = aContextMenu->GetItemId(i);
330 sal_uInt16 nSId = mapIdent(aContextMenu->GetItemIdent(nMId));
332 aContextMenu->CheckItem(nMId, m_rController.isCommandChecked(nSId));
333 bool bEnabled = m_rController.isCommandEnabled(nSId);
334 if (nSId == SID_RPT_NEW_FUNCTION)
335 aContextMenu->EnableItem(nMId, m_rController.isEditable() && (xSupplier.is() || xFunctions.is()));
336 // special condition, check for function and group
337 else if (nSId == SID_DELETE)
338 aContextMenu->EnableItem(nMId, bDeleteAllowed);
339 else
340 aContextMenu->EnableItem(nMId, bEnabled);
344 if (aContextMenu->Execute(this, aWhere))
346 sal_uInt16 nId = mapIdent(aContextMenu->GetCurItemIdent());
347 uno::Sequence< beans::PropertyValue> aArgs;
348 if ( nId == SID_RPT_NEW_FUNCTION )
350 aArgs.realloc(1);
351 aArgs[0].Value <<= (xFunctions.is() ? xFunctions : xSupplier->getFunctions());
353 else if ( nId == SID_DELETE )
355 if ( xGroup.is() )
356 nId = SID_GROUP_REMOVE;
357 aArgs.realloc(1);
358 aArgs[0].Name = PROPERTY_GROUP;
359 aArgs[0].Value <<= pData->getContent();
361 m_rController.executeUnChecked(nId,aArgs);
364 bHandled = true;
366 break;
367 default: break;
370 if (!bHandled)
371 SvTreeListBox::Command( rEvt );
374 sal_Int8 NavigatorTree::AcceptDrop( const AcceptDropEvent& _rEvt )
376 ::Point aDropPos = _rEvt.maPosPixel;
377 if (_rEvt.mbLeaving)
379 if (m_aDropActionTimer.IsActive())
380 m_aDropActionTimer.Stop();
382 else
384 bool bNeedTrigger = false;
385 // At the first record?
386 if ((aDropPos.Y() >= 0) && (aDropPos.Y() < GetEntryHeight()))
388 m_aDropActionType = DA_SCROLLUP;
389 bNeedTrigger = true;
391 else if ((aDropPos.Y() < GetSizePixel().Height()) && (aDropPos.Y() >= GetSizePixel().Height() - GetEntryHeight()))
393 m_aDropActionType = DA_SCROLLDOWN;
394 bNeedTrigger = true;
396 else
398 SvTreeListEntry* pDroppedOn = GetEntry(aDropPos);
399 if (pDroppedOn && (GetChildCount(pDroppedOn) > 0) && !IsExpanded(pDroppedOn))
401 m_aDropActionType = DA_EXPANDNODE;
402 bNeedTrigger = true;
406 if (bNeedTrigger && (m_aTimerTriggered != aDropPos))
408 // again start counting
409 m_nTimerCounter = DROP_ACTION_TIMER_INITIAL_TICKS;
410 // remember the position, because I also get AcceptDrops, if the mouse does not move
411 m_aTimerTriggered = aDropPos;
412 // start Timer
413 if (!m_aDropActionTimer.IsActive()) // Does the Timer already exists?
415 m_aDropActionTimer.SetTimeout(DROP_ACTION_TIMER_TICK_BASE);
416 m_aDropActionTimer.Start();
419 else if (!bNeedTrigger)
420 m_aDropActionTimer.Stop();
423 return DND_ACTION_NONE;
426 sal_Int8 NavigatorTree::ExecuteDrop( const ExecuteDropEvent& /*_rEvt*/ )
428 return DND_ACTION_NONE;
431 void NavigatorTree::StartDrag( sal_Int8 /*_nAction*/, const Point& _rPosPixel )
433 m_pDragedEntry = GetEntry(_rPosPixel);
434 if ( m_pDragedEntry )
436 EndSelection();
440 IMPL_LINK_NOARG(NavigatorTree, OnDropActionTimer, Timer *, void)
442 if (--m_nTimerCounter > 0)
443 return;
445 switch ( m_aDropActionType )
447 case DA_EXPANDNODE:
449 SvTreeListEntry* pToExpand = GetEntry(m_aTimerTriggered);
450 if (pToExpand && (GetChildCount(pToExpand) > 0) && !IsExpanded(pToExpand))
451 Expand(pToExpand);
452 m_aDropActionTimer.Stop();
454 break;
456 case DA_SCROLLUP :
457 ScrollOutputArea( 1 );
458 m_nTimerCounter = DROP_ACTION_TIMER_SCROLL_TICKS;
459 break;
461 case DA_SCROLLDOWN :
462 ScrollOutputArea( -1 );
463 m_nTimerCounter = DROP_ACTION_TIMER_SCROLL_TICKS;
464 break;
470 IMPL_LINK_NOARG(NavigatorTree, OnEntrySelDesel, SvTreeListBox*, void)
472 if ( !m_pSelectionListener->locked() )
474 m_pSelectionListener->lock();
475 SvTreeListEntry* pEntry = GetCurEntry();
476 uno::Any aSelection;
477 if ( IsSelected(pEntry) )
478 aSelection <<= static_cast<UserData*>(pEntry->GetUserData())->getContent();
479 m_rController.select(aSelection);
480 m_pSelectionListener->unlock();
484 void NavigatorTree::_selectionChanged( const lang::EventObject& aEvent )
486 m_pSelectionListener->lock();
487 uno::Reference< view::XSelectionSupplier> xSelectionSupplier(aEvent.Source,uno::UNO_QUERY);
488 uno::Any aSec = xSelectionSupplier->getSelection();
489 uno::Sequence< uno::Reference< report::XReportComponent > > aSelection;
490 aSec >>= aSelection;
491 if ( !aSelection.hasElements() )
493 uno::Reference< uno::XInterface> xSelection(aSec,uno::UNO_QUERY);
494 SvTreeListEntry* pEntry = find(xSelection);
495 if ( pEntry && !IsSelected(pEntry) )
497 Select(pEntry);
498 SetCurEntry(pEntry);
500 else if ( !pEntry )
501 SelectAll(false,false);
503 else
505 const uno::Reference< report::XReportComponent >* pIter = aSelection.getConstArray();
506 const uno::Reference< report::XReportComponent >* pEnd = pIter + aSelection.getLength();
507 for (; pIter != pEnd; ++pIter)
509 SvTreeListEntry* pEntry = find(*pIter);
510 if ( pEntry && !IsSelected(pEntry) )
512 Select(pEntry);
513 SetCurEntry(pEntry);
517 m_pSelectionListener->unlock();
520 SvTreeListEntry* NavigatorTree::insertEntry(const OUString& _sName,SvTreeListEntry* _pParent, const OUString& rImageId, sal_uLong _nPosition,UserData* _pData)
522 SvTreeListEntry* pEntry = nullptr;
523 if (!rImageId.isEmpty())
525 const Image aImage(StockImage::Yes, rImageId);
526 pEntry = InsertEntry(_sName,aImage,aImage,_pParent,false,_nPosition,_pData);
528 else
529 pEntry = InsertEntry(_sName,_pParent,false,_nPosition,_pData);
530 return pEntry;
533 void NavigatorTree::traverseSection(const uno::Reference< report::XSection>& _xSection,SvTreeListEntry* _pParent, const OUString& rImageId, sal_uLong _nPosition)
535 SvTreeListEntry* pSection = insertEntry(_xSection->getName(),_pParent, rImageId, _nPosition,new UserData(this,_xSection));
536 const sal_Int32 nCount = _xSection->getCount();
537 for (sal_Int32 i = 0; i < nCount; ++i)
539 uno::Reference< report::XReportComponent> xElement(_xSection->getByIndex(i),uno::UNO_QUERY_THROW);
540 insertEntry(lcl_getName(xElement.get()),pSection,lcl_getImageId(xElement),TREELIST_APPEND,new UserData(this,xElement));
541 uno::Reference< report::XReportDefinition> xSubReport(xElement,uno::UNO_QUERY);
542 if ( xSubReport.is() )
544 m_pMasterReport = find(_xSection->getReportDefinition());
545 reportdesign::OReportVisitor aSubVisitor(this);
546 aSubVisitor.start(xSubReport);
551 void NavigatorTree::traverseFunctions(const uno::Reference< report::XFunctions>& _xFunctions,SvTreeListEntry* _pParent)
553 SvTreeListEntry* pFunctions = insertEntry(RptResId(RID_STR_FUNCTIONS), _pParent, RID_SVXBMP_RPT_NEW_FUNCTION, TREELIST_APPEND, new UserData(this,_xFunctions));
554 const sal_Int32 nCount = _xFunctions->getCount();
555 for (sal_Int32 i = 0; i< nCount; ++i)
557 uno::Reference< report::XFunction> xElement(_xFunctions->getByIndex(i),uno::UNO_QUERY);
558 insertEntry(xElement->getName(),pFunctions,RID_SVXBMP_RPT_NEW_FUNCTION,TREELIST_APPEND,new UserData(this,xElement));
562 SvTreeListEntry* NavigatorTree::find(const uno::Reference< uno::XInterface >& _xContent)
564 SvTreeListEntry* pRet = nullptr;
565 if ( _xContent.is() )
567 SvTreeListEntry* pCurrent = First();
568 while ( pCurrent )
570 UserData* pData = static_cast<UserData*>(pCurrent->GetUserData());
571 OSL_ENSURE(pData,"No UserData set an entry!");
572 if ( pData->getContent() == _xContent )
574 pRet = pCurrent;
575 break;
577 pCurrent = Next(pCurrent);
580 return pRet;
583 // ITraverseReport
585 void NavigatorTree::traverseReport(const uno::Reference< report::XReportDefinition>& _xReport)
587 insertEntry(_xReport->getName(),m_pMasterReport,RID_SVXBMP_SELECT_REPORT,TREELIST_APPEND,new UserData(this,_xReport));
590 void NavigatorTree::traverseReportFunctions(const uno::Reference< report::XFunctions>& _xFunctions)
592 SvTreeListEntry* pReport = find(_xFunctions->getParent());
593 traverseFunctions(_xFunctions,pReport);
596 void NavigatorTree::traverseReportHeader(const uno::Reference< report::XSection>& _xSection)
598 SvTreeListEntry* pReport = find(_xSection->getReportDefinition());
599 traverseSection(_xSection,pReport,RID_SVXBMP_REPORTHEADERFOOTER);
602 void NavigatorTree::traverseReportFooter(const uno::Reference< report::XSection>& _xSection)
604 SvTreeListEntry* pReport = find(_xSection->getReportDefinition());
605 traverseSection(_xSection,pReport,RID_SVXBMP_REPORTHEADERFOOTER);
608 void NavigatorTree::traversePageHeader(const uno::Reference< report::XSection>& _xSection)
610 SvTreeListEntry* pReport = find(_xSection->getReportDefinition());
611 traverseSection(_xSection,pReport,RID_SVXBMP_PAGEHEADERFOOTER);
614 void NavigatorTree::traversePageFooter(const uno::Reference< report::XSection>& _xSection)
616 SvTreeListEntry* pReport = find(_xSection->getReportDefinition());
617 traverseSection(_xSection,pReport,RID_SVXBMP_PAGEHEADERFOOTER);
620 void NavigatorTree::traverseGroups(const uno::Reference< report::XGroups>& _xGroups)
622 SvTreeListEntry* pReport = find(_xGroups->getReportDefinition());
623 insertEntry(RptResId(RID_STR_GROUPS), pReport, RID_SVXBMP_SORTINGANDGROUPING, TREELIST_APPEND, new UserData(this,_xGroups));
626 void NavigatorTree::traverseGroup(const uno::Reference< report::XGroup>& _xGroup)
628 uno::Reference< report::XGroups> xGroups(_xGroup->getParent(),uno::UNO_QUERY);
629 SvTreeListEntry* pGroups = find(xGroups);
630 OSL_ENSURE(pGroups,"No Groups inserted so far. Why!");
631 insertEntry(_xGroup->getExpression(),pGroups,RID_SVXBMP_GROUP,rptui::getPositionInIndexAccess(xGroups.get(),_xGroup),new UserData(this,_xGroup));
634 void NavigatorTree::traverseGroupFunctions(const uno::Reference< report::XFunctions>& _xFunctions)
636 SvTreeListEntry* pGroup = find(_xFunctions->getParent());
637 traverseFunctions(_xFunctions,pGroup);
640 void NavigatorTree::traverseGroupHeader(const uno::Reference< report::XSection>& _xSection)
642 SvTreeListEntry* pGroup = find(_xSection->getGroup());
643 OSL_ENSURE(pGroup,"No group found");
644 traverseSection(_xSection,pGroup,RID_SVXBMP_GROUPHEADER,1);
647 void NavigatorTree::traverseGroupFooter(const uno::Reference< report::XSection>& _xSection)
649 SvTreeListEntry* pGroup = find(_xSection->getGroup());
650 OSL_ENSURE(pGroup,"No group found");
651 traverseSection(_xSection,pGroup,RID_SVXBMP_GROUPFOOTER);
654 void NavigatorTree::traverseDetail(const uno::Reference< report::XSection>& _xSection)
656 uno::Reference< report::XReportDefinition> xReport = _xSection->getReportDefinition();
657 SvTreeListEntry* pParent = find(xReport);
658 traverseSection(_xSection,pParent,RID_SVXBMP_ICON_DETAIL);
661 void NavigatorTree::_propertyChanged(const beans::PropertyChangeEvent& _rEvent)
663 uno::Reference< report::XReportDefinition> xReport(_rEvent.Source,uno::UNO_QUERY);
664 if ( xReport.is() )
666 bool bEnabled = false;
667 _rEvent.NewValue >>= bEnabled;
668 if ( bEnabled )
670 SvTreeListEntry* pParent = find(xReport);
671 if ( _rEvent.PropertyName == PROPERTY_REPORTHEADERON )
673 sal_uLong nPos = xReport->getReportHeaderOn() ? 2 : 1;
674 traverseSection(xReport->getReportHeader(),pParent,RID_SVXBMP_REPORTHEADERFOOTER,nPos);
676 else if ( _rEvent.PropertyName == PROPERTY_PAGEHEADERON )
678 traverseSection(xReport->getPageHeader(),pParent, RID_SVXBMP_PAGEHEADERFOOTER,1);
680 else if ( _rEvent.PropertyName == PROPERTY_PAGEFOOTERON )
681 traverseSection(xReport->getPageFooter(),pParent, RID_SVXBMP_PAGEHEADERFOOTER);
682 else if ( _rEvent.PropertyName == PROPERTY_REPORTFOOTERON )
684 sal_uLong nPos = xReport->getPageFooterOn() ? (GetLevelChildCount(pParent) - 1) : TREELIST_APPEND;
685 traverseSection(xReport->getReportFooter(),pParent,RID_SVXBMP_REPORTHEADERFOOTER,nPos);
691 void NavigatorTree::_elementInserted( const container::ContainerEvent& _rEvent )
693 SvTreeListEntry* pEntry = find(_rEvent.Source);
694 uno::Reference<beans::XPropertySet> xProp(_rEvent.Element,uno::UNO_QUERY_THROW);
695 OUString sName;
696 uno::Reference< beans::XPropertySetInfo> xInfo = xProp->getPropertySetInfo();
697 if ( xInfo.is() )
699 if ( xInfo->hasPropertyByName(PROPERTY_NAME) )
700 xProp->getPropertyValue(PROPERTY_NAME) >>= sName;
701 else if ( xInfo->hasPropertyByName(PROPERTY_EXPRESSION) )
702 xProp->getPropertyValue(PROPERTY_EXPRESSION) >>= sName;
704 uno::Reference< report::XGroup> xGroup(xProp,uno::UNO_QUERY);
705 if ( xGroup.is() )
707 reportdesign::OReportVisitor aSubVisitor(this);
708 aSubVisitor.start(xGroup);
710 else
712 uno::Reference< report::XReportComponent> xElement(xProp,uno::UNO_QUERY);
713 if ( xProp.is() )
714 sName = lcl_getName(xProp);
715 insertEntry(sName,pEntry,(!xElement.is() ? OUString(RID_SVXBMP_RPT_NEW_FUNCTION) : lcl_getImageId(xElement)),TREELIST_APPEND,new UserData(this,xProp));
717 if ( !IsExpanded(pEntry) )
718 Expand(pEntry);
721 void NavigatorTree::_elementRemoved( const container::ContainerEvent& _rEvent )
723 uno::Reference<beans::XPropertySet> xProp(_rEvent.Element,uno::UNO_QUERY);
724 SvTreeListEntry* pEntry = find(xProp);
725 OSL_ENSURE(pEntry,"NavigatorTree::_elementRemoved: No Entry found!");
727 if (pEntry)
729 removeEntry(pEntry);
730 Invalidate();
734 void NavigatorTree::_elementReplaced( const container::ContainerEvent& _rEvent )
736 uno::Reference<beans::XPropertySet> xProp(_rEvent.ReplacedElement,uno::UNO_QUERY);
737 SvTreeListEntry* pEntry = find(xProp);
738 if ( pEntry )
740 UserData* pData = static_cast<UserData*>(pEntry->GetUserData());
741 xProp.set(_rEvent.Element,uno::UNO_QUERY);
742 pData->setContent(xProp);
743 OUString sName;
744 xProp->getPropertyValue(PROPERTY_NAME) >>= sName;
745 SetEntryText(pEntry,sName);
749 void NavigatorTree::_disposing(const lang::EventObject& _rSource)
751 removeEntry(find(_rSource.Source));
754 void NavigatorTree::removeEntry(SvTreeListEntry* _pEntry,bool _bRemove)
756 if ( _pEntry )
758 SvTreeListEntry* pChild = FirstChild(_pEntry);
759 while( pChild )
761 removeEntry(pChild,false);
762 pChild = pChild->NextSibling();
764 delete static_cast<UserData*>(_pEntry->GetUserData());
765 if ( _bRemove )
766 GetModel()->Remove(_pEntry);
770 NavigatorTree::UserData::UserData(NavigatorTree* _pTree,const uno::Reference<uno::XInterface>& _xContent)
771 : OPropertyChangeListener(m_aMutex)
772 , OContainerListener(m_aMutex)
773 , m_xContent(_xContent)
774 , m_pTree(_pTree)
776 uno::Reference<beans::XPropertySet> xProp(m_xContent,uno::UNO_QUERY);
777 if ( xProp.is() )
779 uno::Reference< beans::XPropertySetInfo> xInfo = xProp->getPropertySetInfo();
780 if ( xInfo.is() )
782 m_pListener = new ::comphelper::OPropertyChangeMultiplexer(this,xProp);
783 if ( xInfo->hasPropertyByName(PROPERTY_NAME) )
784 m_pListener->addProperty(PROPERTY_NAME);
785 else if ( xInfo->hasPropertyByName(PROPERTY_EXPRESSION) )
786 m_pListener->addProperty(PROPERTY_EXPRESSION);
787 if ( xInfo->hasPropertyByName(PROPERTY_DATAFIELD) )
788 m_pListener->addProperty(PROPERTY_DATAFIELD);
789 if ( xInfo->hasPropertyByName(PROPERTY_LABEL) )
790 m_pListener->addProperty(PROPERTY_LABEL);
791 if ( xInfo->hasPropertyByName(PROPERTY_HEADERON) )
792 m_pListener->addProperty(PROPERTY_HEADERON);
793 if ( xInfo->hasPropertyByName(PROPERTY_FOOTERON) )
794 m_pListener->addProperty(PROPERTY_FOOTERON);
797 uno::Reference< container::XContainer> xContainer(m_xContent,uno::UNO_QUERY);
798 if ( xContainer.is() )
800 m_pContainerListener = new ::comphelper::OContainerListenerAdapter(this,xContainer);
804 NavigatorTree::UserData::~UserData()
806 if ( m_pContainerListener.is() )
807 m_pContainerListener->dispose();
808 if ( m_pListener.is() )
809 m_pListener->dispose();
812 // OPropertyChangeListener
813 void NavigatorTree::UserData::_propertyChanged(const beans::PropertyChangeEvent& _rEvent)
815 SvTreeListEntry* pEntry = m_pTree->find(_rEvent.Source);
816 OSL_ENSURE(pEntry,"No entry could be found! Why not!");
817 const bool bFooterOn = (PROPERTY_FOOTERON == _rEvent.PropertyName);
820 if ( bFooterOn || PROPERTY_HEADERON == _rEvent.PropertyName )
822 sal_Int32 nPos = 1;
823 uno::Reference< report::XGroup> xGroup(_rEvent.Source,uno::UNO_QUERY);
824 ::std::function<bool(OGroupHelper *)> pIsOn = ::std::mem_fn(&OGroupHelper::getHeaderOn);
825 ::std::function<uno::Reference<report::XSection>(OGroupHelper *)> pMemFunSection = ::std::mem_fn(&OGroupHelper::getHeader);
826 if ( bFooterOn )
828 pIsOn = ::std::mem_fn(&OGroupHelper::getFooterOn);
829 pMemFunSection = ::std::mem_fn(&OGroupHelper::getFooter);
830 nPos = m_pTree->GetChildCount(pEntry) - 1;
833 OGroupHelper aGroupHelper(xGroup);
834 if ( pIsOn(&aGroupHelper) )
836 if ( bFooterOn )
837 ++nPos;
838 m_pTree->traverseSection(pMemFunSection(&aGroupHelper),pEntry,bFooterOn ? OUString(RID_SVXBMP_GROUPFOOTER) : OUString(RID_SVXBMP_GROUPHEADER),nPos);
841 else if ( PROPERTY_EXPRESSION == _rEvent.PropertyName)
843 OUString sNewName;
844 _rEvent.NewValue >>= sNewName;
845 m_pTree->SetEntryText(pEntry,sNewName);
847 else if ( PROPERTY_DATAFIELD == _rEvent.PropertyName || PROPERTY_LABEL == _rEvent.PropertyName || PROPERTY_NAME == _rEvent.PropertyName )
849 uno::Reference<beans::XPropertySet> xProp(_rEvent.Source,uno::UNO_QUERY);
850 m_pTree->SetEntryText(pEntry,lcl_getName(xProp));
853 catch(const uno::Exception &)
857 void NavigatorTree::UserData::_elementInserted( const container::ContainerEvent& _rEvent )
859 m_pTree->_elementInserted( _rEvent );
862 void NavigatorTree::UserData::_elementRemoved( const container::ContainerEvent& _rEvent )
864 m_pTree->_elementRemoved( _rEvent );
867 void NavigatorTree::UserData::_elementReplaced( const container::ContainerEvent& _rEvent )
869 m_pTree->_elementReplaced( _rEvent );
872 void NavigatorTree::UserData::_disposing(const lang::EventObject& _rSource)
874 m_pTree->_disposing( _rSource );
877 Size NavigatorTree::GetOptimalSize() const
879 return LogicToPixel(Size(100, 70), MapMode(MapUnit::MapAppFont));
882 // class ONavigatorImpl
883 class ONavigatorImpl
885 public:
886 ONavigatorImpl(OReportController& _rController,ONavigator* _pParent);
887 ONavigatorImpl(const ONavigatorImpl&) = delete;
888 ONavigatorImpl& operator=(const ONavigatorImpl&) = delete;
890 uno::Reference< report::XReportDefinition> m_xReport;
891 ::rptui::OReportController& m_rController;
892 VclPtr<NavigatorTree> m_pNavigatorTree;
895 ONavigatorImpl::ONavigatorImpl(OReportController& _rController,ONavigator* _pParent)
896 :m_xReport(_rController.getReportDefinition())
897 ,m_rController(_rController)
898 ,m_pNavigatorTree(VclPtr<NavigatorTree>::Create(_pParent->get<vcl::Window>("box"),_rController))
900 reportdesign::OReportVisitor aVisitor(m_pNavigatorTree.get());
901 aVisitor.start(m_xReport);
902 m_pNavigatorTree->Expand(m_pNavigatorTree->find(m_xReport));
903 lang::EventObject aEvent(m_rController);
904 m_pNavigatorTree->_selectionChanged(aEvent);
907 // class ONavigator
908 ONavigator::ONavigator(vcl::Window* _pParent ,OReportController& _rController)
909 : FloatingWindow( _pParent, "FloatingNavigator", "modules/dbreport/ui/floatingnavigator.ui")
911 m_pImpl.reset(new ONavigatorImpl(_rController,this));
913 m_pImpl->m_pNavigatorTree->Show();
914 m_pImpl->m_pNavigatorTree->GrabFocus();
915 Show();
918 void ONavigator::GetFocus()
920 Window::GetFocus();
921 if ( m_pImpl->m_pNavigatorTree.get() )
922 m_pImpl->m_pNavigatorTree->GrabFocus();
925 void ONavigator::dispose()
927 m_pImpl->m_pNavigatorTree.disposeAndClear();
928 FloatingWindow::dispose();
931 } // rptui
934 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */