1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 "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>
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
62 using namespace ::com::sun::star
;
64 using namespace ::comphelper
;
66 sal_uInt16
lcl_getImageId(const uno::Reference
< report::XReportComponent
>& _xElement
)
69 uno::Reference
< report::XFixedLine
> xFixedLine(_xElement
,uno::UNO_QUERY
);
70 if ( uno::Reference
< report::XFixedText
>(_xElement
,uno::UNO_QUERY
).is() )
71 nId
= SID_FM_FIXEDTEXT
;
72 else if ( xFixedLine
.is() )
73 nId
= xFixedLine
->getOrientation() ? SID_INSERT_VFIXEDLINE
: SID_INSERT_HFIXEDLINE
;
74 else if ( uno::Reference
< report::XFormattedField
>(_xElement
,uno::UNO_QUERY
).is() )
76 else if ( uno::Reference
< report::XImageControl
>(_xElement
,uno::UNO_QUERY
).is() )
77 nId
= SID_FM_IMAGECONTROL
;
78 else if ( uno::Reference
< report::XShape
>(_xElement
,uno::UNO_QUERY
).is() )
79 nId
= SID_DRAWTBX_CS_BASIC
;
83 OUString
lcl_getName(const uno::Reference
< beans::XPropertySet
>& _xElement
)
85 OSL_ENSURE(_xElement
.is(),"Found report element which is NULL!");
87 _xElement
->getPropertyValue(PROPERTY_NAME
) >>= sTempName
;
88 OUStringBuffer sName
= sTempName
;
89 uno::Reference
< report::XFixedText
> xFixedText(_xElement
,uno::UNO_QUERY
);
90 uno::Reference
< report::XReportControlModel
> xReportModel(_xElement
,uno::UNO_QUERY
);
91 if ( xFixedText
.is() )
94 sName
.append(xFixedText
->getLabel());
96 else if ( xReportModel
.is() && _xElement
->getPropertySetInfo()->hasPropertyByName(PROPERTY_DATAFIELD
) )
98 ReportFormula
aFormula( xReportModel
->getDataField() );
99 if ( aFormula
.isValid() )
102 sName
.append( aFormula
.getUndecoratedContent() );
105 return sName
.makeStringAndClear();
109 class NavigatorTree
: public ::cppu::BaseMutex
110 , public SvTreeListBox
111 , public reportdesign::ITraverseReport
112 , public comphelper::OSelectionChangeListener
113 , public ::comphelper::OPropertyChangeListener
116 friend class UserData
;
117 class UserData
: public ::cppu::BaseMutex
118 ,public ::comphelper::OPropertyChangeListener
119 ,public ::comphelper::OContainerListener
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
;
126 UserData(NavigatorTree
* _pTree
,const uno::Reference
<uno::XInterface
>& _xContent
);
129 inline uno::Reference
< uno::XInterface
> getContent() const { return m_xContent
; }
130 inline void setContent(const uno::Reference
< uno::XInterface
>& _xContent
) { m_xContent
= _xContent
; }
133 // OPropertyChangeListener
134 virtual void _propertyChanged(const beans::PropertyChangeEvent
& _rEvent
) throw( uno::RuntimeException
) SAL_OVERRIDE
;
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
;
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
;
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
);
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
;
170 // OSelectionChangeListener
171 virtual void _disposing(const lang::EventObject
& _rSource
)
172 throw (uno::RuntimeException
, std::exception
) SAL_OVERRIDE
;
174 // OPropertyChangeListener
175 virtual void _propertyChanged(const beans::PropertyChangeEvent
& _rEvent
) throw( uno::RuntimeException
) SAL_OVERRIDE
;
177 // OContainerListener Helper
178 void _elementInserted( const container::ContainerEvent
& _rEvent
);
179 void _elementRemoved( const container::ContainerEvent
& _Event
);
180 void _elementReplaced( const container::ContainerEvent
& _rEvent
);
183 NavigatorTree(vcl::Window
* pParent
,OReportController
& _rController
);
184 virtual ~NavigatorTree();
185 virtual void dispose() SAL_OVERRIDE
;
187 DECL_LINK(OnEntrySelDesel
, NavigatorTree
*);
188 DECL_LINK_TYPED( OnDropActionTimer
, Timer
*, void );
190 virtual void _selectionChanged( const lang::EventObject
& aEvent
) throw (uno::RuntimeException
) SAL_OVERRIDE
;
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
;
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
;
206 virtual void traverseDetail(const uno::Reference
< report::XSection
>& _xSection
) SAL_OVERRIDE
;
208 SvTreeListEntry
* find(const uno::Reference
< uno::XInterface
>& _xContent
);
209 void removeEntry(SvTreeListEntry
* _pEntry
,bool _bRemove
= true);
211 virtual Size
GetOptimalSize() const SAL_OVERRIDE
;
213 using SvTreeListBox::ExecuteDrop
;
216 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 ,m_nTimerCounter( DROP_ACTION_TIMER_INITIAL_TICKS
)
230 m_pReportListener
= new OPropertyChangeMultiplexer(this,m_rController
.getReportDefinition().get());
231 m_pReportListener
->addProperty(PROPERTY_PAGEHEADERON
);
232 m_pReportListener
->addProperty(PROPERTY_PAGEFOOTERON
);
233 m_pReportListener
->addProperty(PROPERTY_REPORTHEADERON
);
234 m_pReportListener
->addProperty(PROPERTY_REPORTFOOTERON
);
236 m_pSelectionListener
= new OSelectionChangeMultiplexer(this,&m_rController
);
238 SetHelpId( HID_REPORT_NAVIGATOR_TREE
);
240 m_aNavigatorImages
= ImageList( ModuleRes( RID_SVXIMGLIST_RPTEXPL
) );
243 m_aNavigatorImages
.GetImage( RID_SVXIMG_COLLAPSEDNODE
),
244 m_aNavigatorImages
.GetImage( RID_SVXIMG_EXPANDEDNODE
)
247 SetDragDropMode(DragDropMode::ALL
);
248 EnableInplaceEditing( false );
249 SetSelectionMode(MULTIPLE_SELECTION
);
252 m_aDropActionTimer
.SetTimeoutHdl(LINK(this, NavigatorTree
, OnDropActionTimer
));
253 SetSelectHdl(LINK(this, NavigatorTree
, OnEntrySelDesel
));
254 SetDeselectHdl(LINK(this, NavigatorTree
, OnEntrySelDesel
));
257 NavigatorTree::~NavigatorTree()
262 void NavigatorTree::dispose()
264 SvTreeListEntry
* pCurrent
= First();
267 delete static_cast<UserData
*>(pCurrent
->GetUserData());
268 pCurrent
= Next(pCurrent
);
270 m_pReportListener
->dispose();
271 m_pSelectionListener
->dispose();
272 SvTreeListBox::dispose();
275 void NavigatorTree::Command( const CommandEvent
& rEvt
)
277 bool bHandled
= false;
278 switch( rEvt
.GetCommand())
280 case CommandEventId::ContextMenu
:
282 // die Stelle, an der geklickt wurde
283 SvTreeListEntry
* ptClickedOn
= NULL
;
285 if (rEvt
.IsMouseEvent())
287 aWhere
= rEvt
.GetMousePosPixel();
288 ptClickedOn
= GetEntry(aWhere
);
289 if (ptClickedOn
== NULL
)
291 if ( !IsSelected(ptClickedOn
) )
294 Select(ptClickedOn
, true);
295 SetCurEntry(ptClickedOn
);
300 ptClickedOn
= GetCurEntry();
303 aWhere
= GetEntryPosition(ptClickedOn
);
305 UserData
* pData
= static_cast<UserData
*>(ptClickedOn
->GetUserData());
306 uno::Reference
< report::XFunctionsSupplier
> xSupplier(pData
->getContent(),uno::UNO_QUERY
);
307 uno::Reference
< report::XFunctions
> xFunctions(pData
->getContent(),uno::UNO_QUERY
);
308 uno::Reference
< report::XGroup
> xGroup(pData
->getContent(),uno::UNO_QUERY
);
309 bool bDeleteAllowed
= m_rController
.isEditable() && (xGroup
.is() ||
310 uno::Reference
< report::XFunction
>(pData
->getContent(),uno::UNO_QUERY
).is());
311 PopupMenu
aContextMenu( ModuleRes( RID_MENU_NAVIGATOR
) );
313 sal_uInt16 nCount
= aContextMenu
.GetItemCount();
314 for (sal_uInt16 i
= 0; i
< nCount
; ++i
)
316 if ( MenuItemType::SEPARATOR
!= aContextMenu
.GetItemType(i
))
318 sal_uInt16 nId
= aContextMenu
.GetItemId(i
);
320 aContextMenu
.CheckItem(nId
,m_rController
.isCommandChecked(nId
));
321 bool bEnabled
= m_rController
.isCommandEnabled(nId
);
322 if ( nId
== SID_RPT_NEW_FUNCTION
)
323 aContextMenu
.EnableItem(nId
,m_rController
.isEditable() && (xSupplier
.is() || xFunctions
.is()) );
324 // special condition, check for function and group
325 else if ( nId
== SID_DELETE
)
326 aContextMenu
.EnableItem(SID_DELETE
,bDeleteAllowed
);
328 aContextMenu
.EnableItem(nId
,bEnabled
);
331 sal_uInt16 nId
= aContextMenu
.Execute(this, aWhere
);
334 uno::Sequence
< beans::PropertyValue
> aArgs
;
335 if ( nId
== SID_RPT_NEW_FUNCTION
)
338 aArgs
[0].Value
<<= (xFunctions
.is() ? xFunctions
: xSupplier
->getFunctions());
340 else if ( nId
== SID_DELETE
)
343 nId
= SID_GROUP_REMOVE
;
345 aArgs
[0].Name
= PROPERTY_GROUP
;
346 aArgs
[0].Value
<<= pData
->getContent();
348 m_rController
.executeUnChecked(nId
,aArgs
);
358 SvTreeListBox::Command( rEvt
);
361 sal_Int8
NavigatorTree::AcceptDrop( const AcceptDropEvent
& _rEvt
)
363 sal_Int8 nDropOption
= DND_ACTION_NONE
;
364 ::Point aDropPos
= _rEvt
.maPosPixel
;
367 if (m_aDropActionTimer
.IsActive())
368 m_aDropActionTimer
.Stop();
372 bool bNeedTrigger
= false;
373 // auf dem ersten Eintrag ?
374 if ((aDropPos
.Y() >= 0) && (aDropPos
.Y() < GetEntryHeight()))
376 m_aDropActionType
= DA_SCROLLUP
;
379 else if ((aDropPos
.Y() < GetSizePixel().Height()) && (aDropPos
.Y() >= GetSizePixel().Height() - GetEntryHeight()))
381 m_aDropActionType
= DA_SCROLLDOWN
;
386 SvTreeListEntry
* pDropppedOn
= GetEntry(aDropPos
);
387 if (pDropppedOn
&& (GetChildCount(pDropppedOn
) > 0) && !IsExpanded(pDropppedOn
))
389 m_aDropActionType
= DA_EXPANDNODE
;
394 if (bNeedTrigger
&& (m_aTimerTriggered
!= aDropPos
))
396 // neu anfangen zu zaehlen
397 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 m_aTimerTriggered
= aDropPos
;
401 if (!m_aDropActionTimer
.IsActive()) // gibt es den Timer schon ?
403 m_aDropActionTimer
.SetTimeout(DROP_ACTION_TIMER_TICK_BASE
);
404 m_aDropActionTimer
.Start();
407 else if (!bNeedTrigger
)
408 m_aDropActionTimer
.Stop();
414 sal_Int8
NavigatorTree::ExecuteDrop( const ExecuteDropEvent
& /*_rEvt*/ )
416 return DND_ACTION_NONE
;
419 void NavigatorTree::StartDrag( sal_Int8
/*_nAction*/, const Point
& _rPosPixel
)
421 m_pDragedEntry
= GetEntry(_rPosPixel
);
422 if ( m_pDragedEntry
)
428 IMPL_LINK_NOARG_TYPED(NavigatorTree
, OnDropActionTimer
, Timer
*, void)
430 if (--m_nTimerCounter
> 0)
433 switch ( m_aDropActionType
)
437 SvTreeListEntry
* pToExpand
= GetEntry(m_aTimerTriggered
);
438 if (pToExpand
&& (GetChildCount(pToExpand
) > 0) && !IsExpanded(pToExpand
))
440 m_aDropActionTimer
.Stop();
445 ScrollOutputArea( 1 );
446 m_nTimerCounter
= DROP_ACTION_TIMER_SCROLL_TICKS
;
450 ScrollOutputArea( -1 );
451 m_nTimerCounter
= DROP_ACTION_TIMER_SCROLL_TICKS
;
458 IMPL_LINK(NavigatorTree
, OnEntrySelDesel
, NavigatorTree
*, /*pThis*/)
460 if ( !m_pSelectionListener
->locked() )
462 m_pSelectionListener
->lock();
463 SvTreeListEntry
* pEntry
= GetCurEntry();
465 if ( IsSelected(pEntry
) )
466 aSelection
<<= static_cast<UserData
*>(pEntry
->GetUserData())->getContent();
467 m_rController
.select(aSelection
);
468 m_pSelectionListener
->unlock();
474 void NavigatorTree::_selectionChanged( const lang::EventObject
& aEvent
) throw (uno::RuntimeException
)
476 m_pSelectionListener
->lock();
477 uno::Reference
< view::XSelectionSupplier
> xSelectionSupplier(aEvent
.Source
,uno::UNO_QUERY
);
478 uno::Any aSec
= xSelectionSupplier
->getSelection();
479 uno::Sequence
< uno::Reference
< report::XReportComponent
> > aSelection
;
481 if ( !aSelection
.getLength() )
483 uno::Reference
< uno::XInterface
> xSelection(aSec
,uno::UNO_QUERY
);
484 SvTreeListEntry
* pEntry
= find(xSelection
);
485 if ( pEntry
&& !IsSelected(pEntry
) )
487 Select(pEntry
, true);
491 SelectAll(false,false);
495 const uno::Reference
< report::XReportComponent
>* pIter
= aSelection
.getConstArray();
496 const uno::Reference
< report::XReportComponent
>* pEnd
= pIter
+ aSelection
.getLength();
497 for (; pIter
!= pEnd
; ++pIter
)
499 SvTreeListEntry
* pEntry
= find(*pIter
);
500 if ( pEntry
&& !IsSelected(pEntry
) )
502 Select(pEntry
, true);
507 m_pSelectionListener
->unlock();
510 SvTreeListEntry
* NavigatorTree::insertEntry(const OUString
& _sName
,SvTreeListEntry
* _pParent
,sal_uInt16 _nImageId
,sal_uLong _nPosition
,UserData
* _pData
)
512 SvTreeListEntry
* pEntry
= NULL
;
515 const Image
aImage( m_aNavigatorImages
.GetImage( _nImageId
) );
516 pEntry
= InsertEntry(_sName
,aImage
,aImage
,_pParent
,false,_nPosition
,_pData
);
519 pEntry
= InsertEntry(_sName
,_pParent
,false,_nPosition
,_pData
);
523 void NavigatorTree::traverseSection(const uno::Reference
< report::XSection
>& _xSection
,SvTreeListEntry
* _pParent
,sal_uInt16 _nImageId
,sal_uLong _nPosition
)
525 SvTreeListEntry
* pSection
= insertEntry(_xSection
->getName(),_pParent
,_nImageId
,_nPosition
,new UserData(this,_xSection
));
526 const sal_Int32 nCount
= _xSection
->getCount();
527 for (sal_Int32 i
= 0; i
< nCount
; ++i
)
529 uno::Reference
< report::XReportComponent
> xElement(_xSection
->getByIndex(i
),uno::UNO_QUERY_THROW
);
530 OSL_ENSURE(xElement
.is(),"Found report element which is NULL!");
531 insertEntry(lcl_getName(xElement
.get()),pSection
,lcl_getImageId(xElement
),TREELIST_APPEND
,new UserData(this,xElement
));
532 uno::Reference
< report::XReportDefinition
> xSubReport(xElement
,uno::UNO_QUERY
);
533 if ( xSubReport
.is() )
535 m_pMasterReport
= find(_xSection
->getReportDefinition());
536 reportdesign::OReportVisitor
aSubVisitor(this);
537 aSubVisitor
.start(xSubReport
);
542 void NavigatorTree::traverseFunctions(const uno::Reference
< report::XFunctions
>& _xFunctions
,SvTreeListEntry
* _pParent
)
544 SvTreeListEntry
* pFunctions
= insertEntry(OUString(ModuleRes(RID_STR_FUNCTIONS
)), _pParent
, SID_RPT_NEW_FUNCTION
, TREELIST_APPEND
, new UserData(this,_xFunctions
));
545 const sal_Int32 nCount
= _xFunctions
->getCount();
546 for (sal_Int32 i
= 0; i
< nCount
; ++i
)
548 uno::Reference
< report::XFunction
> xElement(_xFunctions
->getByIndex(i
),uno::UNO_QUERY
);
549 insertEntry(xElement
->getName(),pFunctions
,SID_RPT_NEW_FUNCTION
,TREELIST_APPEND
,new UserData(this,xElement
));
553 SvTreeListEntry
* NavigatorTree::find(const uno::Reference
< uno::XInterface
>& _xContent
)
555 SvTreeListEntry
* pRet
= NULL
;
556 if ( _xContent
.is() )
558 SvTreeListEntry
* pCurrent
= First();
561 UserData
* pData
= static_cast<UserData
*>(pCurrent
->GetUserData());
562 OSL_ENSURE(pData
,"No UserData set an entry!");
563 if ( pData
->getContent() == _xContent
)
568 pCurrent
= Next(pCurrent
);
576 void NavigatorTree::traverseReport(const uno::Reference
< report::XReportDefinition
>& _xReport
)
578 insertEntry(_xReport
->getName(),m_pMasterReport
,SID_SELECT_REPORT
,TREELIST_APPEND
,new UserData(this,_xReport
));
581 void NavigatorTree::traverseReportFunctions(const uno::Reference
< report::XFunctions
>& _xFunctions
)
583 SvTreeListEntry
* pReport
= find(_xFunctions
->getParent());
584 traverseFunctions(_xFunctions
,pReport
);
587 void NavigatorTree::traverseReportHeader(const uno::Reference
< report::XSection
>& _xSection
)
589 SvTreeListEntry
* pReport
= find(_xSection
->getReportDefinition());
590 traverseSection(_xSection
,pReport
,SID_REPORTHEADERFOOTER
);
593 void NavigatorTree::traverseReportFooter(const uno::Reference
< report::XSection
>& _xSection
)
595 SvTreeListEntry
* pReport
= find(_xSection
->getReportDefinition());
596 traverseSection(_xSection
,pReport
,SID_REPORTHEADERFOOTER
);
599 void NavigatorTree::traversePageHeader(const uno::Reference
< report::XSection
>& _xSection
)
601 SvTreeListEntry
* pReport
= find(_xSection
->getReportDefinition());
602 traverseSection(_xSection
,pReport
,SID_PAGEHEADERFOOTER
);
605 void NavigatorTree::traversePageFooter(const uno::Reference
< report::XSection
>& _xSection
)
607 SvTreeListEntry
* pReport
= find(_xSection
->getReportDefinition());
608 traverseSection(_xSection
,pReport
,SID_PAGEHEADERFOOTER
);
611 void NavigatorTree::traverseGroups(const uno::Reference
< report::XGroups
>& _xGroups
)
613 SvTreeListEntry
* pReport
= find(_xGroups
->getReportDefinition());
614 insertEntry(OUString(ModuleRes(RID_STR_GROUPS
)), pReport
, SID_SORTINGANDGROUPING
, TREELIST_APPEND
, new UserData(this,_xGroups
));
617 void NavigatorTree::traverseGroup(const uno::Reference
< report::XGroup
>& _xGroup
)
619 uno::Reference
< report::XGroups
> xGroups(_xGroup
->getParent(),uno::UNO_QUERY
);
620 SvTreeListEntry
* pGroups
= find(xGroups
);
621 OSL_ENSURE(pGroups
,"No Groups inserted so far. Why!");
622 insertEntry(_xGroup
->getExpression(),pGroups
,SID_GROUP
,rptui::getPositionInIndexAccess(xGroups
.get(),_xGroup
),new UserData(this,_xGroup
));
625 void NavigatorTree::traverseGroupFunctions(const uno::Reference
< report::XFunctions
>& _xFunctions
)
627 SvTreeListEntry
* pGroup
= find(_xFunctions
->getParent());
628 traverseFunctions(_xFunctions
,pGroup
);
631 void NavigatorTree::traverseGroupHeader(const uno::Reference
< report::XSection
>& _xSection
)
633 SvTreeListEntry
* pGroup
= find(_xSection
->getGroup());
634 OSL_ENSURE(pGroup
,"No group found");
635 traverseSection(_xSection
,pGroup
,SID_GROUPHEADER
,1);
638 void NavigatorTree::traverseGroupFooter(const uno::Reference
< report::XSection
>& _xSection
)
640 SvTreeListEntry
* pGroup
= find(_xSection
->getGroup());
641 OSL_ENSURE(pGroup
,"No group found");
642 traverseSection(_xSection
,pGroup
,SID_GROUPFOOTER
);
645 void NavigatorTree::traverseDetail(const uno::Reference
< report::XSection
>& _xSection
)
647 uno::Reference
< report::XReportDefinition
> xReport
= _xSection
->getReportDefinition();
648 SvTreeListEntry
* pParent
= find(xReport
);
649 traverseSection(_xSection
,pParent
,SID_ICON_DETAIL
);
652 void NavigatorTree::_propertyChanged(const beans::PropertyChangeEvent
& _rEvent
) throw( uno::RuntimeException
)
654 uno::Reference
< report::XReportDefinition
> xReport(_rEvent
.Source
,uno::UNO_QUERY
);
657 bool bEnabled
= false;
658 _rEvent
.NewValue
>>= bEnabled
;
661 SvTreeListEntry
* pParent
= find(xReport
);
662 if ( _rEvent
.PropertyName
== PROPERTY_REPORTHEADERON
)
664 sal_uLong nPos
= xReport
->getReportHeaderOn() ? 2 : 1;
665 traverseSection(xReport
->getReportHeader(),pParent
,SID_REPORTHEADERFOOTER
,nPos
);
667 else if ( _rEvent
.PropertyName
== PROPERTY_PAGEHEADERON
)
669 traverseSection(xReport
->getPageHeader(),pParent
, SID_PAGEHEADERFOOTER
,1);
671 else if ( _rEvent
.PropertyName
== PROPERTY_PAGEFOOTERON
)
672 traverseSection(xReport
->getPageFooter(),pParent
, SID_PAGEHEADERFOOTER
);
673 else if ( _rEvent
.PropertyName
== PROPERTY_REPORTFOOTERON
)
675 sal_uLong nPos
= xReport
->getPageFooterOn() ? (GetLevelChildCount(pParent
) - 1) : TREELIST_APPEND
;
676 traverseSection(xReport
->getReportFooter(),pParent
,SID_REPORTHEADERFOOTER
,nPos
);
682 void NavigatorTree::_elementInserted( const container::ContainerEvent
& _rEvent
)
684 SvTreeListEntry
* pEntry
= find(_rEvent
.Source
);
685 uno::Reference
<beans::XPropertySet
> xProp(_rEvent
.Element
,uno::UNO_QUERY_THROW
);
687 uno::Reference
< beans::XPropertySetInfo
> xInfo
= xProp
->getPropertySetInfo();
690 if ( xInfo
->hasPropertyByName(PROPERTY_NAME
) )
691 xProp
->getPropertyValue(PROPERTY_NAME
) >>= sName
;
692 else if ( xInfo
->hasPropertyByName(PROPERTY_EXPRESSION
) )
693 xProp
->getPropertyValue(PROPERTY_EXPRESSION
) >>= sName
;
695 uno::Reference
< report::XGroup
> xGroup(xProp
,uno::UNO_QUERY
);
698 reportdesign::OReportVisitor
aSubVisitor(this);
699 aSubVisitor
.start(xGroup
);
703 uno::Reference
< report::XReportComponent
> xElement(xProp
,uno::UNO_QUERY
);
705 sName
= lcl_getName(xProp
);
706 insertEntry(sName
,pEntry
,(!xElement
.is() ? sal_uInt16(SID_RPT_NEW_FUNCTION
) : lcl_getImageId(xElement
)),TREELIST_APPEND
,new UserData(this,xProp
));
708 if ( !IsExpanded(pEntry
) )
712 void NavigatorTree::_elementRemoved( const container::ContainerEvent
& _rEvent
)
714 uno::Reference
<beans::XPropertySet
> xProp(_rEvent
.Element
,uno::UNO_QUERY
);
715 SvTreeListEntry
* pEntry
= find(xProp
);
716 OSL_ENSURE(pEntry
,"NavigatorTree::_elementRemoved: No Entry found!");
725 void NavigatorTree::_elementReplaced( const container::ContainerEvent
& _rEvent
)
727 uno::Reference
<beans::XPropertySet
> xProp(_rEvent
.ReplacedElement
,uno::UNO_QUERY
);
728 SvTreeListEntry
* pEntry
= find(xProp
);
731 UserData
* pData
= static_cast<UserData
*>(pEntry
->GetUserData());
732 xProp
.set(_rEvent
.Element
,uno::UNO_QUERY
);
733 pData
->setContent(xProp
);
735 xProp
->getPropertyValue(PROPERTY_NAME
) >>= sName
;
736 SetEntryText(pEntry
,sName
);
740 void NavigatorTree::_disposing(const lang::EventObject
& _rSource
)
741 throw (uno::RuntimeException
, std::exception
)
743 removeEntry(find(_rSource
.Source
));
746 void NavigatorTree::removeEntry(SvTreeListEntry
* _pEntry
,bool _bRemove
)
750 SvTreeListEntry
* pChild
= FirstChild(_pEntry
);
753 removeEntry(pChild
,false);
754 pChild
= NextSibling(pChild
);
756 delete static_cast<UserData
*>(_pEntry
->GetUserData());
758 GetModel()->Remove(_pEntry
);
762 NavigatorTree::UserData::UserData(NavigatorTree
* _pTree
,const uno::Reference
<uno::XInterface
>& _xContent
)
763 : OPropertyChangeListener(m_aMutex
)
764 , OContainerListener(m_aMutex
)
765 , m_xContent(_xContent
)
768 uno::Reference
<beans::XPropertySet
> xProp(m_xContent
,uno::UNO_QUERY
);
771 uno::Reference
< beans::XPropertySetInfo
> xInfo
= xProp
->getPropertySetInfo();
774 m_pListener
= new ::comphelper::OPropertyChangeMultiplexer(this,xProp
);
775 if ( xInfo
->hasPropertyByName(PROPERTY_NAME
) )
776 m_pListener
->addProperty(PROPERTY_NAME
);
777 else if ( xInfo
->hasPropertyByName(PROPERTY_EXPRESSION
) )
778 m_pListener
->addProperty(PROPERTY_EXPRESSION
);
779 if ( xInfo
->hasPropertyByName(PROPERTY_DATAFIELD
) )
780 m_pListener
->addProperty(PROPERTY_DATAFIELD
);
781 if ( xInfo
->hasPropertyByName(PROPERTY_LABEL
) )
782 m_pListener
->addProperty(PROPERTY_LABEL
);
783 if ( xInfo
->hasPropertyByName(PROPERTY_HEADERON
) )
784 m_pListener
->addProperty(PROPERTY_HEADERON
);
785 if ( xInfo
->hasPropertyByName(PROPERTY_FOOTERON
) )
786 m_pListener
->addProperty(PROPERTY_FOOTERON
);
789 uno::Reference
< container::XContainer
> xContainer(m_xContent
,uno::UNO_QUERY
);
790 if ( xContainer
.is() )
792 m_pContainerListener
= new ::comphelper::OContainerListenerAdapter(this,xContainer
);
796 NavigatorTree::UserData::~UserData()
798 if ( m_pContainerListener
.is() )
799 m_pContainerListener
->dispose();
800 if ( m_pListener
.is() )
801 m_pListener
->dispose();
804 // OPropertyChangeListener
805 void NavigatorTree::UserData::_propertyChanged(const beans::PropertyChangeEvent
& _rEvent
) throw( uno::RuntimeException
)
807 SvTreeListEntry
* pEntry
= m_pTree
->find(_rEvent
.Source
);
808 OSL_ENSURE(pEntry
,"No entry could be found! Why not!");
809 const bool bFooterOn
= (PROPERTY_FOOTERON
== _rEvent
.PropertyName
);
812 if ( bFooterOn
|| PROPERTY_HEADERON
== _rEvent
.PropertyName
)
815 uno::Reference
< report::XGroup
> xGroup(_rEvent
.Source
,uno::UNO_QUERY
);
816 ::std::mem_fun_t
< bool,OGroupHelper
> pIsOn
= ::std::mem_fun(&OGroupHelper::getHeaderOn
);
817 ::std::mem_fun_t
< uno::Reference
<report::XSection
> ,OGroupHelper
> pMemFunSection
= ::std::mem_fun(&OGroupHelper::getHeader
);
820 pIsOn
= ::std::mem_fun(&OGroupHelper::getFooterOn
);
821 pMemFunSection
= ::std::mem_fun(&OGroupHelper::getFooter
);
822 nPos
= m_pTree
->GetChildCount(pEntry
) - 1;
825 OGroupHelper
aGroupHelper(xGroup
);
826 if ( pIsOn(&aGroupHelper
) )
830 m_pTree
->traverseSection(pMemFunSection(&aGroupHelper
),pEntry
,bFooterOn
? SID_GROUPFOOTER
: SID_GROUPHEADER
,nPos
);
833 else if ( PROPERTY_EXPRESSION
== _rEvent
.PropertyName
)
836 _rEvent
.NewValue
>>= sNewName
;
837 m_pTree
->SetEntryText(pEntry
,sNewName
);
839 else if ( PROPERTY_DATAFIELD
== _rEvent
.PropertyName
|| PROPERTY_LABEL
== _rEvent
.PropertyName
|| PROPERTY_NAME
== _rEvent
.PropertyName
)
841 uno::Reference
<beans::XPropertySet
> xProp(_rEvent
.Source
,uno::UNO_QUERY
);
842 m_pTree
->SetEntryText(pEntry
,lcl_getName(xProp
));
845 catch(const uno::Exception
&)
849 void NavigatorTree::UserData::_elementInserted( const container::ContainerEvent
& _rEvent
) throw(uno::RuntimeException
, std::exception
)
851 m_pTree
->_elementInserted( _rEvent
);
854 void NavigatorTree::UserData::_elementRemoved( const container::ContainerEvent
& _rEvent
)
855 throw (uno::RuntimeException
, std::exception
)
857 m_pTree
->_elementRemoved( _rEvent
);
860 void NavigatorTree::UserData::_elementReplaced( const container::ContainerEvent
& _rEvent
) throw(uno::RuntimeException
, std::exception
)
862 m_pTree
->_elementReplaced( _rEvent
);
865 void NavigatorTree::UserData::_disposing(const lang::EventObject
& _rSource
)
866 throw (uno::RuntimeException
, std::exception
)
868 m_pTree
->_disposing( _rSource
);
871 Size
NavigatorTree::GetOptimalSize() const
873 return LogicToPixel(Size(100, 70), MAP_APPFONT
);
876 // class ONavigatorImpl
877 class ONavigatorImpl
: private boost::noncopyable
880 ONavigatorImpl(OReportController
& _rController
,ONavigator
* _pParent
);
882 uno::Reference
< report::XReportDefinition
> m_xReport
;
883 ::rptui::OReportController
& m_rController
;
884 VclPtr
<NavigatorTree
> m_pNavigatorTree
;
887 ONavigatorImpl::ONavigatorImpl(OReportController
& _rController
,ONavigator
* _pParent
)
888 :m_xReport(_rController
.getReportDefinition())
889 ,m_rController(_rController
)
890 ,m_pNavigatorTree(VclPtr
<NavigatorTree
>::Create(_pParent
->get
<vcl::Window
>("box"),_rController
))
892 reportdesign::OReportVisitor
aVisitor(m_pNavigatorTree
.get());
893 aVisitor
.start(m_xReport
);
894 m_pNavigatorTree
->Expand(m_pNavigatorTree
->find(m_xReport
));
895 lang::EventObject
aEvent(m_rController
);
896 m_pNavigatorTree
->_selectionChanged(aEvent
);
900 ONavigator::ONavigator(vcl::Window
* _pParent
,OReportController
& _rController
)
901 : FloatingWindow( _pParent
, "FloatingNavigator", "modules/dbreport/ui/floatingnavigator.ui")
903 m_pImpl
.reset(new ONavigatorImpl(_rController
,this));
905 m_pImpl
->m_pNavigatorTree
->Show();
906 m_pImpl
->m_pNavigatorTree
->GrabFocus();
910 void ONavigator::GetFocus()
913 if ( m_pImpl
->m_pNavigatorTree
.get() )
914 m_pImpl
->m_pNavigatorTree
->GrabFocus();
920 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */