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