blob: c68aa7021b9f6a261672a74cf1987eb259b4c595 [file] [log] [blame]
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
#include "precompiled_reportdesign.hxx"
#include "Navigator.hxx"
#include "uistrings.hrc"
#include "ReportController.hxx"
#include "UITools.hxx"
#include "RptUndo.hxx"
#include "reportformula.hxx"
#include <com/sun/star/container/XContainerListener.hpp>
#include <com/sun/star/report/XReportDefinition.hpp>
#include <com/sun/star/report/XFixedText.hpp>
#include <com/sun/star/report/XFixedLine.hpp>
#include <com/sun/star/report/XFormattedField.hpp>
#include <com/sun/star/report/XImageControl.hpp>
#include <com/sun/star/report/XShape.hpp>
#include <svx/globlmn.hrc>
#include <svx/svxids.hrc>
#include "helpids.hrc"
#include "RptResId.hrc"
#include "rptui_slotid.hrc"
#include <tools/debug.hxx>
#include <comphelper/propmultiplex.hxx>
#include <comphelper/containermultiplexer.hxx>
#include <comphelper/types.hxx>
#include "cppuhelper/basemutex.hxx"
#include "comphelper/SelectionMultiplex.hxx"
#include <svtools/svtreebx.hxx>
#include <svl/solar.hrc>
#include "ReportVisitor.hxx"
#include "ModuleHelper.hxx"
#include <rtl/ref.hxx>
#include <boost/bind.hpp>
#include <memory>
#include <algorithm>
#define RID_SVXIMG_COLLAPSEDNODE (RID_FORMS_START + 2)
#define RID_SVXIMG_EXPANDEDNODE (RID_FORMS_START + 3)
#define DROP_ACTION_TIMER_INITIAL_TICKS 10
#define DROP_ACTION_TIMER_SCROLL_TICKS 3
#define DROP_ACTION_TIMER_TICK_BASE 10
namespace rptui
{
using namespace ::com::sun::star;
using namespace utl;
using namespace ::comphelper;
sal_uInt16 lcl_getImageId(const uno::Reference< report::XReportComponent>& _xElement)
{
sal_uInt16 nId = 0;
uno::Reference< report::XFixedLine> xFixedLine(_xElement,uno::UNO_QUERY);
if ( uno::Reference< report::XFixedText>(_xElement,uno::UNO_QUERY).is() )
nId = SID_FM_FIXEDTEXT;
else if ( xFixedLine.is() )
nId = xFixedLine->getOrientation() ? SID_INSERT_VFIXEDLINE : SID_INSERT_HFIXEDLINE;
else if ( uno::Reference< report::XFormattedField>(_xElement,uno::UNO_QUERY).is() )
nId = SID_FM_EDIT;
else if ( uno::Reference< report::XImageControl>(_xElement,uno::UNO_QUERY).is() )
nId = SID_FM_IMAGECONTROL;
else if ( uno::Reference< report::XShape>(_xElement,uno::UNO_QUERY).is() )
nId = SID_DRAWTBX_CS_BASIC;
return nId;
}
// -----------------------------------------------------------------------------
::rtl::OUString lcl_getName(const uno::Reference< beans::XPropertySet>& _xElement)
{
OSL_ENSURE(_xElement.is(),"Found report element which is NULL!");
::rtl::OUString sTempName;
_xElement->getPropertyValue(PROPERTY_NAME) >>= sTempName;
::rtl::OUStringBuffer sName = sTempName;
uno::Reference< report::XFixedText> xFixedText(_xElement,uno::UNO_QUERY);
uno::Reference< report::XReportControlModel> xReportModel(_xElement,uno::UNO_QUERY);
if ( xFixedText.is() )
{
sName.append(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" : ")));
sName.append(xFixedText->getLabel());
}
else if ( xReportModel.is() && _xElement->getPropertySetInfo()->hasPropertyByName(PROPERTY_DATAFIELD) )
{
ReportFormula aFormula( xReportModel->getDataField() );
if ( aFormula.isValid() )
{
sName.append(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" : ")));
sName.append( aFormula.getUndecoratedContent() );
}
}
return sName.makeStringAndClear();
}
// -----------------------------------------------------------------------------
class NavigatorTree : public ::cppu::BaseMutex
, public SvTreeListBox
, public reportdesign::ITraverseReport
, public comphelper::OSelectionChangeListener
, public ::comphelper::OPropertyChangeListener
{
class UserData;
friend class UserData;
class UserData : public ::cppu::BaseMutex
,public ::comphelper::OPropertyChangeListener
,public ::comphelper::OContainerListener
{
uno::Reference< uno::XInterface > m_xContent;
::rtl::Reference< comphelper::OPropertyChangeMultiplexer> m_pListener;
::rtl::Reference< comphelper::OContainerListenerAdapter> m_pContainerListener;
NavigatorTree* m_pTree;
public:
UserData(NavigatorTree* _pTree,const uno::Reference<uno::XInterface>& _xContent);
~UserData();
inline uno::Reference< uno::XInterface > getContent() const { return m_xContent; }
inline void setContent(const uno::Reference< uno::XInterface >& _xContent) { m_xContent = _xContent; }
protected:
// OPropertyChangeListener
virtual void _propertyChanged(const beans::PropertyChangeEvent& _rEvent) throw( uno::RuntimeException);
// OContainerListener
virtual void _elementInserted( const container::ContainerEvent& _rEvent ) throw(uno::RuntimeException);
virtual void _elementRemoved( const container::ContainerEvent& _Event ) throw(uno::RuntimeException);
virtual void _elementReplaced( const container::ContainerEvent& _rEvent ) throw(uno::RuntimeException);
virtual void _disposing(const lang::EventObject& _rSource) throw( uno::RuntimeException);
};
enum DROP_ACTION { DA_SCROLLUP, DA_SCROLLDOWN, DA_EXPANDNODE };
AutoTimer m_aDropActionTimer;
Timer m_aSynchronizeTimer;
ImageList m_aNavigatorImages;
ImageList m_aNavigatorImagesHC;
Point m_aTimerTriggered; // die Position, an der der DropTimer angeschaltet wurde
DROP_ACTION m_aDropActionType;
OReportController& m_rController;
SvLBoxEntry* m_pMasterReport;
SvLBoxEntry* m_pDragedEntry;
::rtl::Reference< comphelper::OPropertyChangeMultiplexer> m_pReportListener;
::rtl::Reference< comphelper::OSelectionChangeMultiplexer> m_pSelectionListener;
unsigned short m_nTimerCounter;
SvLBoxEntry* insertEntry(const ::rtl::OUString& _sName,SvLBoxEntry* _pParent,sal_uInt16 _nImageId,sal_uLong _nPosition,UserData* _pData);
void traverseSection(const uno::Reference< report::XSection>& _xSection,SvLBoxEntry* _pParent,sal_uInt16 _nImageId,sal_uLong _nPosition = LIST_APPEND);
void traverseFunctions(const uno::Reference< report::XFunctions>& _xFunctions,SvLBoxEntry* _pParent);
NavigatorTree(const NavigatorTree&);
void operator =(const NavigatorTree&);
protected:
virtual void Command( const CommandEvent& rEvt );
// DragSourceHelper overridables
virtual void StartDrag( sal_Int8 nAction, const Point& rPosPixel );
// DropTargetHelper overridables
virtual sal_Int8 AcceptDrop( const AcceptDropEvent& _rEvt );
virtual sal_Int8 ExecuteDrop( const ExecuteDropEvent& _rEvt );
// OSelectionChangeListener
virtual void _disposing(const lang::EventObject& _rSource) throw( uno::RuntimeException);
// OPropertyChangeListener
virtual void _propertyChanged(const beans::PropertyChangeEvent& _rEvent) throw( uno::RuntimeException);
// OContainerListener Helper
void _elementInserted( const container::ContainerEvent& _rEvent );
void _elementRemoved( const container::ContainerEvent& _Event );
void _elementReplaced( const container::ContainerEvent& _rEvent );
public:
NavigatorTree(Window* pParent,OReportController& _rController );
virtual ~NavigatorTree();
DECL_LINK(OnEntrySelDesel, NavigatorTree*);
DECL_LINK( OnDropActionTimer, void* );
virtual void _selectionChanged( const lang::EventObject& aEvent ) throw (uno::RuntimeException);
// ITraverseReport
virtual void traverseReport(const uno::Reference< report::XReportDefinition>& _xReport);
virtual void traverseReportFunctions(const uno::Reference< report::XFunctions>& _xFunctions);
virtual void traverseReportHeader(const uno::Reference< report::XSection>& _xSection);
virtual void traverseReportFooter(const uno::Reference< report::XSection>& _xSection);
virtual void traversePageHeader(const uno::Reference< report::XSection>& _xSection);
virtual void traversePageFooter(const uno::Reference< report::XSection>& _xSection);
virtual void traverseGroups(const uno::Reference< report::XGroups>& _xGroups);
virtual void traverseGroup(const uno::Reference< report::XGroup>& _xGroup);
virtual void traverseGroupFunctions(const uno::Reference< report::XFunctions>& _xFunctions);
virtual void traverseGroupHeader(const uno::Reference< report::XSection>& _xSection);
virtual void traverseGroupFooter(const uno::Reference< report::XSection>& _xSection);
virtual void traverseDetail(const uno::Reference< report::XSection>& _xSection);
SvLBoxEntry* find(const uno::Reference< uno::XInterface >& _xContent);
void removeEntry(SvLBoxEntry* _pEntry,bool _bRemove = true);
private:
using SvTreeListBox::ExecuteDrop;
};
DBG_NAME(rpt_NavigatorTree)
// -----------------------------------------------------------------------------
NavigatorTree::NavigatorTree( Window* pParent,OReportController& _rController )
:SvTreeListBox( pParent, WB_TABSTOP| WB_HASBUTTONS|WB_HASLINES|WB_BORDER|WB_HSCROLL|WB_HASBUTTONSATROOT )
,comphelper::OSelectionChangeListener(m_aMutex)
,OPropertyChangeListener(m_aMutex)
,m_aTimerTriggered(-1,-1)
,m_aDropActionType( DA_SCROLLUP )
,m_rController(_rController)
,m_pMasterReport(NULL)
,m_pDragedEntry(NULL)
,m_nTimerCounter( DROP_ACTION_TIMER_INITIAL_TICKS )
{
DBG_CTOR(rpt_NavigatorTree,NULL);
m_pReportListener = new OPropertyChangeMultiplexer(this,m_rController.getReportDefinition().get());
m_pReportListener->addProperty(PROPERTY_PAGEHEADERON);
m_pReportListener->addProperty(PROPERTY_PAGEFOOTERON);
m_pReportListener->addProperty(PROPERTY_REPORTHEADERON);
m_pReportListener->addProperty(PROPERTY_REPORTFOOTERON);
m_pSelectionListener = new OSelectionChangeMultiplexer(this,&m_rController);
SetHelpId( HID_REPORT_NAVIGATOR_TREE );
m_aNavigatorImages = ImageList( ModuleRes( RID_SVXIMGLIST_RPTEXPL ) );
m_aNavigatorImagesHC = ImageList( ModuleRes( RID_SVXIMGLIST_RPTEXPL_HC ) );
SetNodeBitmaps(
m_aNavigatorImages.GetImage( RID_SVXIMG_COLLAPSEDNODE ),
m_aNavigatorImages.GetImage( RID_SVXIMG_EXPANDEDNODE ),
BMP_COLOR_NORMAL
);
SetNodeBitmaps(
m_aNavigatorImagesHC.GetImage( RID_SVXIMG_COLLAPSEDNODE ),
m_aNavigatorImagesHC.GetImage( RID_SVXIMG_EXPANDEDNODE ),
BMP_COLOR_HIGHCONTRAST
);
SetDragDropMode(0xFFFF);
EnableInplaceEditing( sal_False );
SetSelectionMode(MULTIPLE_SELECTION);
Clear();
m_aDropActionTimer.SetTimeoutHdl(LINK(this, NavigatorTree, OnDropActionTimer));
SetSelectHdl(LINK(this, NavigatorTree, OnEntrySelDesel));
SetDeselectHdl(LINK(this, NavigatorTree, OnEntrySelDesel));
}
// -----------------------------------------------------------------------------
NavigatorTree::~NavigatorTree()
{
SvLBoxEntry* pCurrent = First();
while ( pCurrent )
{
delete static_cast<UserData*>(pCurrent->GetUserData());
pCurrent = Next(pCurrent);
}
m_pReportListener->dispose();
m_pSelectionListener->dispose();
DBG_DTOR(rpt_NavigatorTree,NULL);
}
//------------------------------------------------------------------------------
void NavigatorTree::Command( const CommandEvent& rEvt )
{
sal_Bool bHandled = sal_False;
switch( rEvt.GetCommand() )
{
case COMMAND_CONTEXTMENU:
{
// die Stelle, an der geklickt wurde
SvLBoxEntry* ptClickedOn = NULL;
::Point aWhere;
if (rEvt.IsMouseEvent())
{
aWhere = rEvt.GetMousePosPixel();
ptClickedOn = GetEntry(aWhere);
if (ptClickedOn == NULL)
break;
if ( !IsSelected(ptClickedOn) )
{
SelectAll(sal_False);
Select(ptClickedOn, sal_True);
SetCurEntry(ptClickedOn);
}
}
else
{
ptClickedOn = GetCurEntry();
if ( !ptClickedOn )
break;
aWhere = GetEntryPosition(ptClickedOn);
}
UserData* pData = static_cast<UserData*>(ptClickedOn->GetUserData());
uno::Reference< report::XFunctionsSupplier> xSupplier(pData->getContent(),uno::UNO_QUERY);
uno::Reference< report::XFunctions> xFunctions(pData->getContent(),uno::UNO_QUERY);
uno::Reference< report::XGroup> xGroup(pData->getContent(),uno::UNO_QUERY);
sal_Bool bDeleteAllowed = m_rController.isEditable() && (xGroup.is() ||
uno::Reference< report::XFunction>(pData->getContent(),uno::UNO_QUERY).is());
PopupMenu aContextMenu( ModuleRes( RID_MENU_NAVIGATOR ) );
sal_uInt16 nCount = aContextMenu.GetItemCount();
for (sal_uInt16 i = 0; i < nCount; ++i)
{
if ( MENUITEM_SEPARATOR != aContextMenu.GetItemType(i))
{
sal_uInt16 nId = aContextMenu.GetItemId(i);
aContextMenu.CheckItem(nId,m_rController.isCommandChecked(nId));
sal_Bool bEnabled = m_rController.isCommandEnabled(nId);
if ( nId == SID_RPT_NEW_FUNCTION )
aContextMenu.EnableItem(nId,m_rController.isEditable() && (xSupplier.is() || xFunctions.is()) );
// special condition, check for function and group
else if ( nId == SID_DELETE )
aContextMenu.EnableItem(SID_DELETE,bDeleteAllowed);
else
aContextMenu.EnableItem(nId,bEnabled);
}
} // for (sal_uInt16 i = 0; i < nCount; ++i)
sal_uInt16 nId = aContextMenu.Execute(this, aWhere);
if ( nId )
{
uno::Sequence< beans::PropertyValue> aArgs;
if ( nId == SID_RPT_NEW_FUNCTION )
{
aArgs.realloc(1);
aArgs[0].Value <<= (xFunctions.is() ? xFunctions : xSupplier->getFunctions());
}
else if ( nId == SID_DELETE )
{
if ( xGroup.is() )
nId = SID_GROUP_REMOVE;
aArgs.realloc(1);
aArgs[0].Name = PROPERTY_GROUP;
aArgs[0].Value <<= pData->getContent();
}
m_rController.executeUnChecked(nId,aArgs);
}
bHandled = sal_True;
} break;
}
if (!bHandled)
SvTreeListBox::Command( rEvt );
}
// -----------------------------------------------------------------------------
sal_Int8 NavigatorTree::AcceptDrop( const AcceptDropEvent& _rEvt )
{
sal_Int8 nDropOption = DND_ACTION_NONE;
::Point aDropPos = _rEvt.maPosPixel;
if (_rEvt.mbLeaving)
{
if (m_aDropActionTimer.IsActive())
m_aDropActionTimer.Stop();
}
else
{
bool bNeedTrigger = false;
// auf dem ersten Eintrag ?
if ((aDropPos.Y() >= 0) && (aDropPos.Y() < GetEntryHeight()))
{
m_aDropActionType = DA_SCROLLUP;
bNeedTrigger = true;
}
else if ((aDropPos.Y() < GetSizePixel().Height()) && (aDropPos.Y() >= GetSizePixel().Height() - GetEntryHeight()))
{
m_aDropActionType = DA_SCROLLDOWN;
bNeedTrigger = true;
}
else
{
SvLBoxEntry* pDropppedOn = GetEntry(aDropPos);
if (pDropppedOn && (GetChildCount(pDropppedOn) > 0) && !IsExpanded(pDropppedOn))
{
m_aDropActionType = DA_EXPANDNODE;
bNeedTrigger = true;
}
}
if (bNeedTrigger && (m_aTimerTriggered != aDropPos))
{
// neu anfangen zu zaehlen
m_nTimerCounter = DROP_ACTION_TIMER_INITIAL_TICKS;
// die Pos merken, da ich auch AcceptDrops bekomme, wenn sich die Maus gar nicht bewegt hat
m_aTimerTriggered = aDropPos;
// und den Timer los
if (!m_aDropActionTimer.IsActive()) // gibt es den Timer schon ?
{
m_aDropActionTimer.SetTimeout(DROP_ACTION_TIMER_TICK_BASE);
m_aDropActionTimer.Start();
}
}
else if (!bNeedTrigger)
m_aDropActionTimer.Stop();
}
return nDropOption;
}
// -------------------------------------------------------------------------
sal_Int8 NavigatorTree::ExecuteDrop( const ExecuteDropEvent& /*_rEvt*/ )
{
// _rEvt.mnAction;
return DND_ACTION_NONE;
}
// -------------------------------------------------------------------------
void NavigatorTree::StartDrag( sal_Int8 /*_nAction*/, const Point& _rPosPixel )
{
m_pDragedEntry = GetEntry(_rPosPixel);
if ( m_pDragedEntry )
{
EndSelection();
}
}
//------------------------------------------------------------------------
IMPL_LINK( NavigatorTree, OnDropActionTimer, void*, EMPTYARG )
{
if (--m_nTimerCounter > 0)
return 0L;
switch ( m_aDropActionType )
{
case DA_EXPANDNODE:
{
SvLBoxEntry* pToExpand = GetEntry(m_aTimerTriggered);
if (pToExpand && (GetChildCount(pToExpand) > 0) && !IsExpanded(pToExpand))
// tja, eigentlich muesste ich noch testen, ob die Node nicht schon expandiert ist, aber ich
// habe dazu weder in den Basisklassen noch im Model eine Methode gefunden ...
// aber ich denke, die BK sollte es auch so vertragen
Expand(pToExpand);
// nach dem Expand habe ich im Gegensatz zum Scrollen natuerlich nix mehr zu tun
m_aDropActionTimer.Stop();
}
break;
case DA_SCROLLUP :
ScrollOutputArea( 1 );
m_nTimerCounter = DROP_ACTION_TIMER_SCROLL_TICKS;
break;
case DA_SCROLLDOWN :
ScrollOutputArea( -1 );
m_nTimerCounter = DROP_ACTION_TIMER_SCROLL_TICKS;
break;
}
return 0L;
}
// -----------------------------------------------------------------------------
IMPL_LINK(NavigatorTree, OnEntrySelDesel, NavigatorTree*, /*pThis*/)
{
if ( !m_pSelectionListener->locked() )
{
m_pSelectionListener->lock();
SvLBoxEntry* pEntry = GetCurEntry();
uno::Any aSelection;
if ( IsSelected(pEntry) )
aSelection <<= static_cast<UserData*>(pEntry->GetUserData())->getContent();
m_rController.select(aSelection);
m_pSelectionListener->unlock();
}
return 0L;
}
// -----------------------------------------------------------------------------
void NavigatorTree::_selectionChanged( const lang::EventObject& aEvent ) throw (uno::RuntimeException)
{
m_pSelectionListener->lock();
uno::Reference< view::XSelectionSupplier> xSelectionSupplier(aEvent.Source,uno::UNO_QUERY);
uno::Any aSec = xSelectionSupplier->getSelection();
uno::Sequence< uno::Reference< report::XReportComponent > > aSelection;
aSec >>= aSelection;
if ( !aSelection.getLength() )
{
uno::Reference< uno::XInterface> xSelection(aSec,uno::UNO_QUERY);
SvLBoxEntry* pEntry = find(xSelection);
if ( pEntry && !IsSelected(pEntry) )
{
Select(pEntry, sal_True);
SetCurEntry(pEntry);
}
else if ( !pEntry )
SelectAll(sal_False,sal_False);
}
else
{
const uno::Reference< report::XReportComponent >* pIter = aSelection.getConstArray();
const uno::Reference< report::XReportComponent >* pEnd = pIter + aSelection.getLength();
for (; pIter != pEnd; ++pIter)
{
SvLBoxEntry* pEntry = find(*pIter);
if ( pEntry && !IsSelected(pEntry) )
{
Select(pEntry, sal_True);
SetCurEntry(pEntry);
}
}
}
m_pSelectionListener->unlock();
}
// -----------------------------------------------------------------------------
SvLBoxEntry* NavigatorTree::insertEntry(const ::rtl::OUString& _sName,SvLBoxEntry* _pParent,sal_uInt16 _nImageId,sal_uLong _nPosition,UserData* _pData)
{
SvLBoxEntry* pEntry = NULL;
if ( _nImageId )
{
const Image aImage( m_aNavigatorImages.GetImage( _nImageId ) );
pEntry = InsertEntry(_sName,aImage,aImage,_pParent,sal_False,_nPosition,_pData);
if ( pEntry )
{
const Image aImageHC( m_aNavigatorImagesHC.GetImage( _nImageId ) );
SetExpandedEntryBmp( pEntry, aImageHC, BMP_COLOR_HIGHCONTRAST );
SetCollapsedEntryBmp( pEntry, aImageHC, BMP_COLOR_HIGHCONTRAST );
}
}
else
pEntry = InsertEntry(_sName,_pParent,sal_False,_nPosition,_pData);
return pEntry;
}
// -----------------------------------------------------------------------------
void NavigatorTree::traverseSection(const uno::Reference< report::XSection>& _xSection,SvLBoxEntry* _pParent,sal_uInt16 _nImageId,sal_uLong _nPosition)
{
SvLBoxEntry* pSection = insertEntry(_xSection->getName(),_pParent,_nImageId,_nPosition,new UserData(this,_xSection));
const sal_Int32 nCount = _xSection->getCount();
for (sal_Int32 i = 0; i < nCount; ++i)
{
uno::Reference< report::XReportComponent> xElement(_xSection->getByIndex(i),uno::UNO_QUERY_THROW);
OSL_ENSURE(xElement.is(),"Found report element which is NULL!");
insertEntry(lcl_getName(xElement.get()),pSection,lcl_getImageId(xElement),LIST_APPEND,new UserData(this,xElement));
uno::Reference< report::XReportDefinition> xSubReport(xElement,uno::UNO_QUERY);
if ( xSubReport.is() )
{
m_pMasterReport = find(_xSection->getReportDefinition());
reportdesign::OReportVisitor aSubVisitor(this);
aSubVisitor.start(xSubReport);
}
}
}
// -----------------------------------------------------------------------------
void NavigatorTree::traverseFunctions(const uno::Reference< report::XFunctions>& _xFunctions,SvLBoxEntry* _pParent)
{
SvLBoxEntry* pFunctions = insertEntry(String(ModuleRes(RID_STR_FUNCTIONS)),_pParent,SID_RPT_NEW_FUNCTION,LIST_APPEND,new UserData(this,_xFunctions));
const sal_Int32 nCount = _xFunctions->getCount();
for (sal_Int32 i = 0; i< nCount; ++i)
{
uno::Reference< report::XFunction> xElement(_xFunctions->getByIndex(i),uno::UNO_QUERY);
insertEntry(xElement->getName(),pFunctions,SID_RPT_NEW_FUNCTION,LIST_APPEND,new UserData(this,xElement));
}
}
// -----------------------------------------------------------------------------
SvLBoxEntry* NavigatorTree::find(const uno::Reference< uno::XInterface >& _xContent)
{
SvLBoxEntry* pRet = NULL;
if ( _xContent.is() )
{
SvLBoxEntry* pCurrent = First();
while ( pCurrent )
{
UserData* pData = static_cast<UserData*>(pCurrent->GetUserData());
OSL_ENSURE(pData,"No UserData set an entry!");
if ( pData->getContent() == _xContent )
{
pRet = pCurrent;
break;
}
pCurrent = Next(pCurrent);
}
}
return pRet;
}
// -----------------------------------------------------------------------------
// ITraverseReport
// -----------------------------------------------------------------------------
void NavigatorTree::traverseReport(const uno::Reference< report::XReportDefinition>& _xReport)
{
insertEntry(_xReport->getName(),m_pMasterReport,SID_SELECT_REPORT,LIST_APPEND,new UserData(this,_xReport));
}
// -----------------------------------------------------------------------------
void NavigatorTree::traverseReportFunctions(const uno::Reference< report::XFunctions>& _xFunctions)
{
SvLBoxEntry* pReport = find(_xFunctions->getParent());
traverseFunctions(_xFunctions,pReport);
}
// -----------------------------------------------------------------------------
void NavigatorTree::traverseReportHeader(const uno::Reference< report::XSection>& _xSection)
{
SvLBoxEntry* pReport = find(_xSection->getReportDefinition());
traverseSection(_xSection,pReport,SID_REPORTHEADERFOOTER);
}
// -----------------------------------------------------------------------------
void NavigatorTree::traverseReportFooter(const uno::Reference< report::XSection>& _xSection)
{
SvLBoxEntry* pReport = find(_xSection->getReportDefinition());
traverseSection(_xSection,pReport,SID_REPORTHEADERFOOTER);
}
// -----------------------------------------------------------------------------
void NavigatorTree::traversePageHeader(const uno::Reference< report::XSection>& _xSection)
{
SvLBoxEntry* pReport = find(_xSection->getReportDefinition());
traverseSection(_xSection,pReport,SID_PAGEHEADERFOOTER);
}
// -----------------------------------------------------------------------------
void NavigatorTree::traversePageFooter(const uno::Reference< report::XSection>& _xSection)
{
SvLBoxEntry* pReport = find(_xSection->getReportDefinition());
traverseSection(_xSection,pReport,SID_PAGEHEADERFOOTER);
}
// -----------------------------------------------------------------------------
void NavigatorTree::traverseGroups(const uno::Reference< report::XGroups>& _xGroups)
{
SvLBoxEntry* pReport = find(_xGroups->getReportDefinition());
insertEntry(String(ModuleRes(RID_STR_GROUPS)),pReport,SID_SORTINGANDGROUPING,LIST_APPEND,new UserData(this,_xGroups));
}
// -----------------------------------------------------------------------------
void NavigatorTree::traverseGroup(const uno::Reference< report::XGroup>& _xGroup)
{
uno::Reference< report::XGroups> xGroups(_xGroup->getParent(),uno::UNO_QUERY);
SvLBoxEntry* pGroups = find(xGroups);
OSL_ENSURE(pGroups,"No Groups inserted so far. Why!");
insertEntry(_xGroup->getExpression(),pGroups,SID_GROUP,rptui::getPositionInIndexAccess(xGroups.get(),_xGroup),new UserData(this,_xGroup));
}
// -----------------------------------------------------------------------------
void NavigatorTree::traverseGroupFunctions(const uno::Reference< report::XFunctions>& _xFunctions)
{
SvLBoxEntry* pGroup = find(_xFunctions->getParent());
traverseFunctions(_xFunctions,pGroup);
}
// -----------------------------------------------------------------------------
void NavigatorTree::traverseGroupHeader(const uno::Reference< report::XSection>& _xSection)
{
SvLBoxEntry* pGroup = find(_xSection->getGroup());
OSL_ENSURE(pGroup,"No group found");
traverseSection(_xSection,pGroup,SID_GROUPHEADER,1);
}
// -----------------------------------------------------------------------------
void NavigatorTree::traverseGroupFooter(const uno::Reference< report::XSection>& _xSection)
{
SvLBoxEntry* pGroup = find(_xSection->getGroup());
OSL_ENSURE(pGroup,"No group found");
traverseSection(_xSection,pGroup,SID_GROUPFOOTER);
}
// -----------------------------------------------------------------------------
void NavigatorTree::traverseDetail(const uno::Reference< report::XSection>& _xSection)
{
uno::Reference< report::XReportDefinition> xReport = _xSection->getReportDefinition();
SvLBoxEntry* pParent = find(xReport);
traverseSection(_xSection,pParent,SID_ICON_DETAIL);
}
// -----------------------------------------------------------------------------
void NavigatorTree::_propertyChanged(const beans::PropertyChangeEvent& _rEvent) throw( uno::RuntimeException)
{
uno::Reference< report::XReportDefinition> xReport(_rEvent.Source,uno::UNO_QUERY);
if ( xReport.is() )
{
sal_Bool bEnabled = sal_False;
_rEvent.NewValue >>= bEnabled;
if ( bEnabled )
{
SvLBoxEntry* pParent = find(xReport);
if ( _rEvent.PropertyName == PROPERTY_REPORTHEADERON )
{
sal_uLong nPos = xReport->getReportHeaderOn() ? 2 : 1;
traverseSection(xReport->getReportHeader(),pParent,SID_REPORTHEADERFOOTER,nPos);
}
else if ( _rEvent.PropertyName == PROPERTY_PAGEHEADERON )
{
traverseSection(xReport->getPageHeader(),pParent, SID_PAGEHEADERFOOTER,1);
}
else if ( _rEvent.PropertyName == PROPERTY_PAGEFOOTERON )
traverseSection(xReport->getPageFooter(),pParent, SID_PAGEHEADERFOOTER);
else if ( _rEvent.PropertyName == PROPERTY_REPORTFOOTERON )
{
sal_uLong nPos = xReport->getPageFooterOn() ? (GetLevelChildCount(pParent) - 1) : LIST_APPEND;
traverseSection(xReport->getReportFooter(),pParent,SID_REPORTHEADERFOOTER,nPos);
}
}
}
}
// -----------------------------------------------------------------------------
void NavigatorTree::_elementInserted( const container::ContainerEvent& _rEvent )
{
SvLBoxEntry* pEntry = find(_rEvent.Source);
uno::Reference<beans::XPropertySet> xProp(_rEvent.Element,uno::UNO_QUERY_THROW);
::rtl::OUString sName;
uno::Reference< beans::XPropertySetInfo> xInfo = xProp->getPropertySetInfo();
if ( xInfo.is() )
{
if ( xInfo->hasPropertyByName(PROPERTY_NAME) )
xProp->getPropertyValue(PROPERTY_NAME) >>= sName;
else if ( xInfo->hasPropertyByName(PROPERTY_EXPRESSION) )
xProp->getPropertyValue(PROPERTY_EXPRESSION) >>= sName;
}
uno::Reference< report::XGroup> xGroup(xProp,uno::UNO_QUERY);
if ( xGroup.is() )
{
reportdesign::OReportVisitor aSubVisitor(this);
aSubVisitor.start(xGroup);
}
else
{
uno::Reference< report::XReportComponent> xElement(xProp,uno::UNO_QUERY);
if ( xProp.is() )
sName = lcl_getName(xProp);
insertEntry(sName,pEntry,(!xElement.is() ? sal_uInt16(SID_RPT_NEW_FUNCTION) : lcl_getImageId(xElement)),LIST_APPEND,new UserData(this,xProp));
}
if ( !IsExpanded(pEntry) )
Expand(pEntry);
}
// -----------------------------------------------------------------------------
void NavigatorTree::_elementRemoved( const container::ContainerEvent& _rEvent )
{
uno::Reference<beans::XPropertySet> xProp(_rEvent.Element,uno::UNO_QUERY);
SvLBoxEntry* pEntry = find(xProp);
OSL_ENSURE(pEntry,"NavigatorTree::_elementRemoved: No Entry found!");
if ( pEntry )
{
SvLBoxEntry* pParent = GetParent(pEntry);
removeEntry(pEntry);
PaintEntry(pParent);
}
}
// -----------------------------------------------------------------------------
void NavigatorTree::_elementReplaced( const container::ContainerEvent& _rEvent )
{
uno::Reference<beans::XPropertySet> xProp(_rEvent.ReplacedElement,uno::UNO_QUERY);
SvLBoxEntry* pEntry = find(xProp);
if ( pEntry )
{
UserData* pData = static_cast<UserData*>(pEntry->GetUserData());
xProp.set(_rEvent.Element,uno::UNO_QUERY);
pData->setContent(xProp);
::rtl::OUString sName;
xProp->getPropertyValue(PROPERTY_NAME) >>= sName;
SetEntryText(pEntry,sName);
}
}
// -----------------------------------------------------------------------------
void NavigatorTree::_disposing(const lang::EventObject& _rSource)throw( uno::RuntimeException)
{
removeEntry(find(_rSource.Source));
}
// -----------------------------------------------------------------------------
void NavigatorTree::removeEntry(SvLBoxEntry* _pEntry,bool _bRemove)
{
if ( _pEntry )
{
SvLBoxEntry* pChild = FirstChild(_pEntry);
while( pChild )
{
removeEntry(pChild,false);
pChild = NextSibling(pChild);
}
delete static_cast<UserData*>(_pEntry->GetUserData());
if ( _bRemove )
GetModel()->Remove(_pEntry);
}
}
DBG_NAME(rpt_NavigatorTree_UserData)
// -----------------------------------------------------------------------------
NavigatorTree::UserData::UserData(NavigatorTree* _pTree,const uno::Reference<uno::XInterface>& _xContent)
: OPropertyChangeListener(m_aMutex)
, OContainerListener(m_aMutex)
, m_xContent(_xContent)
, m_pTree(_pTree)
{
DBG_CTOR(rpt_NavigatorTree_UserData,NULL);
uno::Reference<beans::XPropertySet> xProp(m_xContent,uno::UNO_QUERY);
if ( xProp.is() )
{
uno::Reference< beans::XPropertySetInfo> xInfo = xProp->getPropertySetInfo();
if ( xInfo.is() )
{
m_pListener = new ::comphelper::OPropertyChangeMultiplexer(this,xProp);
if ( xInfo->hasPropertyByName(PROPERTY_NAME) )
m_pListener->addProperty(PROPERTY_NAME);
else if ( xInfo->hasPropertyByName(PROPERTY_EXPRESSION) )
m_pListener->addProperty(PROPERTY_EXPRESSION);
if ( xInfo->hasPropertyByName(PROPERTY_DATAFIELD) )
m_pListener->addProperty(PROPERTY_DATAFIELD);
if ( xInfo->hasPropertyByName(PROPERTY_LABEL) )
m_pListener->addProperty(PROPERTY_LABEL);
if ( xInfo->hasPropertyByName(PROPERTY_HEADERON) )
m_pListener->addProperty(PROPERTY_HEADERON);
if ( xInfo->hasPropertyByName(PROPERTY_FOOTERON) )
m_pListener->addProperty(PROPERTY_FOOTERON);
}
}
uno::Reference< container::XContainer> xContainer(m_xContent,uno::UNO_QUERY);
if ( xContainer.is() )
{
m_pContainerListener = new ::comphelper::OContainerListenerAdapter(this,xContainer);
}
}
// -----------------------------------------------------------------------------
NavigatorTree::UserData::~UserData()
{
DBG_DTOR(rpt_NavigatorTree_UserData,NULL);
if ( m_pContainerListener.is() )
m_pContainerListener->dispose();
if ( m_pListener.is() )
m_pListener->dispose();
}
// -----------------------------------------------------------------------------
// OPropertyChangeListener
void NavigatorTree::UserData::_propertyChanged(const beans::PropertyChangeEvent& _rEvent) throw( uno::RuntimeException)
{
SvLBoxEntry* pEntry = m_pTree->find(_rEvent.Source);
OSL_ENSURE(pEntry,"No entry could be found! Why not!");
const bool bFooterOn = (PROPERTY_FOOTERON == _rEvent.PropertyName);
try
{
if ( bFooterOn || PROPERTY_HEADERON == _rEvent.PropertyName )
{
sal_Int32 nPos = 1;
uno::Reference< report::XGroup> xGroup(_rEvent.Source,uno::UNO_QUERY);
::std::mem_fun_t< sal_Bool,OGroupHelper> pIsOn = ::std::mem_fun(&OGroupHelper::getHeaderOn);
::std::mem_fun_t< uno::Reference<report::XSection> ,OGroupHelper> pMemFunSection = ::std::mem_fun(&OGroupHelper::getHeader);
if ( bFooterOn )
{
pIsOn = ::std::mem_fun(&OGroupHelper::getFooterOn);
pMemFunSection = ::std::mem_fun(&OGroupHelper::getFooter);
nPos = m_pTree->GetChildCount(pEntry) - 1;
}
OGroupHelper aGroupHelper(xGroup);
if ( pIsOn(&aGroupHelper) )
{
if ( bFooterOn )
++nPos;
m_pTree->traverseSection(pMemFunSection(&aGroupHelper),pEntry,bFooterOn ? SID_GROUPFOOTER : SID_GROUPHEADER,nPos);
}
//else
// m_pTree->removeEntry(m_pTree->GetEntry(pEntry,nPos));
}
else if ( PROPERTY_EXPRESSION == _rEvent.PropertyName)
{
::rtl::OUString sNewName;
_rEvent.NewValue >>= sNewName;
m_pTree->SetEntryText(pEntry,sNewName);
}
else if ( PROPERTY_DATAFIELD == _rEvent.PropertyName || PROPERTY_LABEL == _rEvent.PropertyName || PROPERTY_NAME == _rEvent.PropertyName )
{
uno::Reference<beans::XPropertySet> xProp(_rEvent.Source,uno::UNO_QUERY);
m_pTree->SetEntryText(pEntry,lcl_getName(xProp));
}
}
catch(uno::Exception)
{}
}
// -----------------------------------------------------------------------------
void NavigatorTree::UserData::_elementInserted( const container::ContainerEvent& _rEvent ) throw(uno::RuntimeException)
{
m_pTree->_elementInserted( _rEvent );
}
// -----------------------------------------------------------------------------
void NavigatorTree::UserData::_elementRemoved( const container::ContainerEvent& _rEvent ) throw(uno::RuntimeException)
{
m_pTree->_elementRemoved( _rEvent );
}
// -----------------------------------------------------------------------------
void NavigatorTree::UserData::_elementReplaced( const container::ContainerEvent& _rEvent ) throw(uno::RuntimeException)
{
m_pTree->_elementReplaced( _rEvent );
}
// -----------------------------------------------------------------------------
void NavigatorTree::UserData::_disposing(const lang::EventObject& _rSource) throw( uno::RuntimeException)
{
m_pTree->_disposing( _rSource );
}
// -----------------------------------------------------------------------------
// class ONavigatorImpl
// -----------------------------------------------------------------------------
class ONavigatorImpl
{
ONavigatorImpl(const ONavigatorImpl&);
void operator =(const ONavigatorImpl&);
public:
ONavigatorImpl(OReportController& _rController,ONavigator* _pParent);
virtual ~ONavigatorImpl();
uno::Reference< report::XReportDefinition> m_xReport;
::rptui::OReportController& m_rController;
::std::auto_ptr<NavigatorTree> m_pNavigatorTree;
};
ONavigatorImpl::ONavigatorImpl(OReportController& _rController,ONavigator* _pParent)
:m_xReport(_rController.getReportDefinition())
,m_rController(_rController)
,m_pNavigatorTree(new NavigatorTree(_pParent,_rController))
{
reportdesign::OReportVisitor aVisitor(m_pNavigatorTree.get());
aVisitor.start(m_xReport);
m_pNavigatorTree->Expand(m_pNavigatorTree->find(m_xReport));
lang::EventObject aEvent(m_rController);
m_pNavigatorTree->_selectionChanged(aEvent);
}
//------------------------------------------------------------------------
ONavigatorImpl::~ONavigatorImpl()
{
}
// -----------------------------------------------------------------------------
DBG_NAME( rpt_ONavigator )
const long STD_WIN_SIZE_X = 210;
const long STD_WIN_SIZE_Y = 280;
const long LISTBOX_BORDER = 2;
//========================================================================
// class ONavigator
//========================================================================
ONavigator::ONavigator( Window* _pParent
,OReportController& _rController)
: FloatingWindow( _pParent, ModuleRes(RID_NAVIGATOR) )
{
DBG_CTOR( rpt_ONavigator,NULL);
m_pImpl.reset(new ONavigatorImpl(_rController,this));
//Size aSpace = LogicToPixel( Size( 7, 120), MAP_APPFONT );
//Size aOutSize(nMaxTextWidth + m_aHeader.GetSizePixel().Width() + 3*aSpace.Width(),aSpace.Height());
//SetMinOutputSizePixel(aOutSize);
//SetOutputSizePixel(aOutSize);
FreeResource();
m_pImpl->m_pNavigatorTree->Show();
m_pImpl->m_pNavigatorTree->GrabFocus();
SetSizePixel(Size(STD_WIN_SIZE_X,STD_WIN_SIZE_Y));
Show();
}
// -----------------------------------------------------------------------------
//------------------------------------------------------------------------
ONavigator::~ONavigator()
{
DBG_DTOR( rpt_ONavigator,NULL);
}
//------------------------------------------------------------------------------
void ONavigator::Resize()
{
FloatingWindow::Resize();
Point aPos(GetPosPixel());
Size aSize( GetOutputSizePixel() );
//////////////////////////////////////////////////////////////////////
// Groesse der form::ListBox anpassen
Point aLBPos( LISTBOX_BORDER, LISTBOX_BORDER );
Size aLBSize( aSize );
aLBSize.Width() -= (2*LISTBOX_BORDER);
aLBSize.Height() -= (2*LISTBOX_BORDER);
m_pImpl->m_pNavigatorTree->SetPosSizePixel( aLBPos, aLBSize );
}
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
void ONavigator::GetFocus()
{
Window::GetFocus();
if ( m_pImpl->m_pNavigatorTree.get() )
m_pImpl->m_pNavigatorTree->GrabFocus();
}
// =============================================================================
} // rptui
// =============================================================================