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