diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:06:44 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:06:44 +0000 |
commit | ed5640d8b587fbcfed7dd7967f3de04b37a76f26 (patch) | |
tree | 7a5f7c6c9d02226d7471cb3cc8fbbf631b415303 /reportdesign/source/ui/report | |
parent | Initial commit. (diff) | |
download | libreoffice-ed5640d8b587fbcfed7dd7967f3de04b37a76f26.tar.xz libreoffice-ed5640d8b587fbcfed7dd7967f3de04b37a76f26.zip |
Adding upstream version 4:7.4.7.upstream/4%7.4.7upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'reportdesign/source/ui/report')
17 files changed, 11742 insertions, 0 deletions
diff --git a/reportdesign/source/ui/report/DesignView.cxx b/reportdesign/source/ui/report/DesignView.cxx new file mode 100644 index 000000000..ab213479b --- /dev/null +++ b/reportdesign/source/ui/report/DesignView.cxx @@ -0,0 +1,686 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * 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 . + */ + +#include <DesignView.hxx> +#include <ReportController.hxx> +#include <svtools/acceleratorexecute.hxx> +#include <unotools/viewoptions.hxx> +#include <RptDef.hxx> +#include <UITools.hxx> +#include <RptObject.hxx> +#include <propbrw.hxx> +#include <helpids.h> +#include <SectionView.hxx> +#include <ReportSection.hxx> +#include <rptui_slotid.hrc> +#include <AddField.hxx> +#include <ScrollHelper.hxx> +#include <Navigator.hxx> +#include <SectionWindow.hxx> + +#include <vcl/settings.hxx> +#include <vcl/svapp.hxx> + +#include <algorithm> + +namespace rptui +{ +using namespace ::dbaui; +using namespace ::utl; +using namespace ::com::sun::star; +using namespace uno; +using namespace lang; +using namespace beans; +using namespace container; + +#define START_SIZE_TASKPANE 30 +#define COLSET_ID 1 +#define REPORT_ID 2 +#define TASKPANE_ID 3 + +namespace { + +class OTaskWindow : public vcl::Window +{ + VclPtr<PropBrw> m_pPropWin; +public: + explicit OTaskWindow(vcl::Window* _pParent) : Window(_pParent),m_pPropWin(nullptr){} + virtual ~OTaskWindow() override { disposeOnce(); } + virtual void dispose() override { m_pPropWin.clear(); vcl::Window::dispose(); } + + void setPropertyBrowser(PropBrw* _pPropWin) + { + m_pPropWin = _pPropWin; + } + + virtual void Resize() override + { + const Size aSize = GetOutputSizePixel(); + if ( m_pPropWin && aSize.Height() && aSize.Width() ) + m_pPropWin->SetSizePixel(aSize); + } +}; + +} + + + +ODesignView::ODesignView( vcl::Window* pParent, + const Reference< XComponentContext >& _rxOrb, + OReportController& _rController) : + ODataView( pParent, _rController, _rxOrb, WB_DIALOGCONTROL ) + ,m_aSplitWin(VclPtr<SplitWindow>::Create(this)) + ,m_rReportController( _rController ) + ,m_aScrollWindow(VclPtr<rptui::OScrollWindowHelper>::Create(this)) + ,m_pPropWin(nullptr) + ,m_pCurrentView(nullptr) + ,m_aMarkIdle("reportdesign ODesignView Mark Idle") + ,m_eMode( DlgEdMode::Select ) + ,m_eActObj( SdrObjKind::NONE ) + ,m_aGridSizeCoarse( 1000, 1000 ) // #i93595# 100TH_MM changed to grid using coarse 1 cm grid + ,m_aGridSizeFine( 250, 250 ) // and a 0,25 cm subdivision for better visualisation + ,m_bDeleted( false ) +{ + SetHelpId(UID_RPT_RPT_APP_VIEW); + ImplInitSettings(); + + SetMapMode( MapMode( MapUnit::Map100thMM ) ); + + // now create the task pane on the right side :-) + m_pTaskPane = VclPtr<OTaskWindow>::Create(this); + + m_aSplitWin->InsertItem( COLSET_ID,100,SPLITWINDOW_APPEND, 0, SplitWindowItemFlags::PercentSize | SplitWindowItemFlags::ColSet ); + m_aSplitWin->InsertItem( REPORT_ID, m_aScrollWindow.get(), 100, SPLITWINDOW_APPEND, COLSET_ID, SplitWindowItemFlags::PercentSize); + + // set up splitter + m_aSplitWin->SetSplitHdl(LINK(this, ODesignView,SplitHdl)); + m_aSplitWin->SetAlign(WindowAlign::Left); + m_aSplitWin->Show(); + + m_aMarkIdle.SetInvokeHandler( LINK( this, ODesignView, MarkTimeout ) ); +} + + +ODesignView::~ODesignView() +{ + disposeOnce(); +} + +void ODesignView::dispose() +{ + m_bDeleted = true; + Hide(); + m_aScrollWindow->Hide(); + m_aMarkIdle.Stop(); + if ( m_pPropWin ) + { + notifySystemWindow(this,m_pPropWin,::comphelper::mem_fun(&TaskPaneList::RemoveWindow)); + m_pPropWin.disposeAndClear(); + } + if ( m_xAddField ) + { + SvtViewOptions aDlgOpt( EViewType::Window, UID_RPT_RPT_APP_VIEW ); + aDlgOpt.SetWindowState(OStringToOUString(m_xAddField->getDialog()->get_window_state(WindowStateMask::All), RTL_TEXTENCODING_ASCII_US)); + + if (m_xAddField->getDialog()->get_visible()) + m_xAddField->response(RET_CANCEL); + + m_xAddField.reset(); + } + if ( m_xReportExplorer ) + { + SvtViewOptions aDlgOpt(EViewType::Window, OStringToOUString(m_xReportExplorer->get_help_id(), RTL_TEXTENCODING_UTF8)); + aDlgOpt.SetWindowState(OStringToOUString(m_xReportExplorer->getDialog()->get_window_state(WindowStateMask::All), RTL_TEXTENCODING_ASCII_US)); + + if (m_xReportExplorer->getDialog()->get_visible()) + m_xReportExplorer->response(RET_CANCEL); + + m_xReportExplorer.reset(); + } + + m_pTaskPane.disposeAndClear(); + m_aScrollWindow.disposeAndClear(); + m_aSplitWin.disposeAndClear(); + dbaui::ODataView::dispose(); +} + +void ODesignView::initialize() +{ + SetMapMode( MapMode( MapUnit::Map100thMM ) ); + m_aScrollWindow->initialize(); + m_aScrollWindow->Show(); +} + +void ODesignView::DataChanged( const DataChangedEvent& rDCEvt ) +{ + ODataView::DataChanged( rDCEvt ); + + if ( (rDCEvt.GetType() == DataChangedEventType::SETTINGS) && + (rDCEvt.GetFlags() & AllSettingsFlags::STYLE) ) + { + ImplInitSettings(); + Invalidate(); + } +} + +bool ODesignView::PreNotify( NotifyEvent& rNEvt ) +{ + bool bRet = ODataView::PreNotify(rNEvt); // 1 := has to be handled here + switch(rNEvt.GetType()) + { + case MouseNotifyEvent::KEYINPUT: + { + if ( m_pPropWin && m_pPropWin->HasChildPathFocus() ) + return false; + if (m_xAddField && m_xAddField->getDialog()->has_toplevel_focus()) + return false; + if ( m_xReportExplorer && m_xReportExplorer->getDialog()->has_toplevel_focus()) + return false; + const KeyEvent* pKeyEvent = rNEvt.GetKeyEvent(); + if ( handleKeyEvent(*pKeyEvent) ) + bRet = true; + else if ( bRet && m_pAccel ) + { + const vcl::KeyCode& rCode = pKeyEvent->GetKeyCode(); + util::URL aUrl; + aUrl.Complete = m_pAccel->findCommand(svt::AcceleratorExecute::st_VCLKey2AWTKey(rCode)); + if ( aUrl.Complete.isEmpty() || !m_xController->isCommandEnabled( aUrl.Complete ) ) + bRet = false; + } + break; + } + default: + break; + } + + return bRet; +} + +void ODesignView::resizeDocumentView(tools::Rectangle& _rPlayground) +{ + if ( !_rPlayground.IsEmpty() ) + { + const Size aPlaygroundSize( _rPlayground.GetSize() ); + + // calc the split pos, and forward it to the controller + sal_Int32 nSplitPos = getController().getSplitPos(); + if ( 0 != aPlaygroundSize.Width() ) + { + if ( ( -1 == nSplitPos ) + || ( nSplitPos >= aPlaygroundSize.Width() ) + ) + { + tools::Long nMinWidth = static_cast<tools::Long>(0.1*aPlaygroundSize.Width()); + if ( m_pPropWin && m_pPropWin->IsVisible() ) + nMinWidth = m_pPropWin->GetMinOutputSizePixel().Width(); + nSplitPos = static_cast<sal_Int32>(_rPlayground.Right() - nMinWidth); + getController().setSplitPos(nSplitPos); + } + } + + if ( m_aSplitWin->IsItemValid(TASKPANE_ID) ) + { + // normalize the split pos + const tools::Long nSplitterWidth = StyleSettings::GetSplitSize(); + Point aTaskPanePos(nSplitPos + nSplitterWidth, _rPlayground.Top()); + if (m_pTaskPane && m_pTaskPane->IsVisible() && m_pPropWin) + { + aTaskPanePos.setX( aPlaygroundSize.Width() - m_pTaskPane->GetSizePixel().Width() ); + sal_Int32 nMinWidth = m_pPropWin->getMinimumSize().Width(); + if ( nMinWidth > (aPlaygroundSize.Width() - aTaskPanePos.X()) ) + { + aTaskPanePos.setX( aPlaygroundSize.Width() - nMinWidth ); + } + nSplitPos = aTaskPanePos.X() - nSplitterWidth; + getController().setSplitPos(nSplitPos); + + const tools::Long nTaskPaneSize = static_cast<tools::Long>((aPlaygroundSize.Width() - aTaskPanePos.X())*100/aPlaygroundSize.Width()); + if ( m_aSplitWin->GetItemSize( TASKPANE_ID ) != nTaskPaneSize ) + { + m_aSplitWin->SetItemSize( REPORT_ID, 99 - nTaskPaneSize ); + m_aSplitWin->SetItemSize( TASKPANE_ID, nTaskPaneSize ); + } + } + } + // set the size of the report window + m_aSplitWin->SetPosSizePixel( _rPlayground.TopLeft(),aPlaygroundSize ); + } + // just for completeness: there is no space left, we occupied it all ... + _rPlayground.SetPos( _rPlayground.BottomRight() ); + _rPlayground.SetSize( Size( 0, 0 ) ); + +} + +IMPL_LINK_NOARG(ODesignView, MarkTimeout, Timer *, void) +{ + if ( m_pPropWin && m_pPropWin->IsVisible() ) + { + m_pPropWin->Update(m_pCurrentView); + uno::Reference<beans::XPropertySet> xProp(m_xReportComponent,uno::UNO_QUERY); + if ( xProp.is() ) + { + m_pPropWin->Update(xProp); + static_cast<OTaskWindow*>(m_pTaskPane.get())->Resize(); + } + Resize(); + } +} + + +void ODesignView::SetMode( DlgEdMode _eNewMode ) +{ + m_eMode = _eNewMode; + if ( m_eMode == DlgEdMode::Select ) + m_eActObj = SdrObjKind::NONE; + + m_aScrollWindow->SetMode(_eNewMode); +} + +void ODesignView::SetInsertObj( SdrObjKind eObj,const OUString& _sShapeType ) +{ + m_eActObj = eObj; + m_aScrollWindow->SetInsertObj( eObj,_sShapeType ); +} + +OUString const & ODesignView::GetInsertObjString() const +{ + return m_aScrollWindow->GetInsertObjString(); +} + + +void ODesignView::Cut() +{ + Copy(); + Delete(); +} + + +void ODesignView::Copy() +{ + m_aScrollWindow->Copy(); +} + + +void ODesignView::Paste() +{ + m_aScrollWindow->Paste(); +} + +void ODesignView::Delete() +{ + m_aScrollWindow->Delete(); +} + +bool ODesignView::HasSelection() const +{ + return m_aScrollWindow->HasSelection(); +} + + +bool ODesignView::IsPasteAllowed() const +{ + return m_aScrollWindow->IsPasteAllowed(); +} + + +void ODesignView::UpdatePropertyBrowserDelayed(OSectionView& _rView) +{ + if ( m_pCurrentView != &_rView ) + { + if ( m_pCurrentView ) + m_aScrollWindow->setMarked(m_pCurrentView,false); + m_pCurrentView = &_rView; + m_aScrollWindow->setMarked(m_pCurrentView, true); + m_xReportComponent.clear(); + DlgEdHint aHint( RPTUI_HINT_SELECTIONCHANGED ); + Broadcast( aHint ); + } + m_aMarkIdle.Start(); +} + + +void ODesignView::toggleGrid(bool _bGridVisible) +{ + m_aScrollWindow->toggleGrid(_bGridVisible); +} + +sal_uInt16 ODesignView::getSectionCount() const +{ + return m_aScrollWindow->getSectionCount(); +} + +void ODesignView::showRuler(bool _bShow) +{ + m_aScrollWindow->showRuler(_bShow); +} + +void ODesignView::removeSection(sal_uInt16 _nPosition) +{ + m_aScrollWindow->removeSection(_nPosition); +} + +void ODesignView::addSection(const uno::Reference< report::XSection >& _xSection,const OUString& _sColorEntry,sal_uInt16 _nPosition) +{ + m_aScrollWindow->addSection(_xSection,_sColorEntry,_nPosition); +} + +void ODesignView::GetFocus() +{ + Window::GetFocus(); + + if ( !m_bDeleted ) + { + OSectionWindow* pSectionWindow = m_aScrollWindow->getMarkedSection(); + if ( pSectionWindow ) + pSectionWindow->GrabFocus(); + } +} + +void ODesignView::ImplInitSettings() +{ + SetBackground( Wallpaper( Application::GetSettings().GetStyleSettings().GetFaceColor() )); + GetOutDev()->SetFillColor( Application::GetSettings().GetStyleSettings().GetFaceColor() ); + SetTextFillColor( Application::GetSettings().GetStyleSettings().GetFaceColor() ); +} + +IMPL_LINK_NOARG( ODesignView, SplitHdl, SplitWindow*, void ) +{ + const Size aOutputSize = GetOutputSizePixel(); + const tools::Long nTest = aOutputSize.Width() * m_aSplitWin->GetItemSize(TASKPANE_ID) / 100; + tools::Long nMinWidth = static_cast<tools::Long>(0.1*aOutputSize.Width()); + if ( m_pPropWin && m_pPropWin->IsVisible() ) + nMinWidth = m_pPropWin->GetMinOutputSizePixel().Width(); + + if ( (aOutputSize.Width() - nTest) >= nMinWidth && nTest > m_aScrollWindow->getMaxMarkerWidth() ) + { + getController().setSplitPos(nTest); + } +} + +void ODesignView::SelectAll(const SdrObjKind _nObjectType) +{ + m_aScrollWindow->SelectAll(_nObjectType); +} + +void ODesignView::unmarkAllObjects() +{ + m_aScrollWindow->unmarkAllObjects(); +} + +void ODesignView::togglePropertyBrowser(bool _bToggleOn) +{ + if ( !m_pPropWin && _bToggleOn ) + { + m_pPropWin = VclPtr<PropBrw>::Create(getController().getORB(), m_pTaskPane,this); + m_pPropWin->Invalidate(); + static_cast<OTaskWindow*>(m_pTaskPane.get())->setPropertyBrowser(m_pPropWin); + notifySystemWindow(this,m_pPropWin,::comphelper::mem_fun(&TaskPaneList::AddWindow)); + } + if ( !(m_pPropWin && _bToggleOn != m_pPropWin->IsVisible()) ) + return; + + if ( !m_pCurrentView && !m_xReportComponent.is() ) + m_xReportComponent = getController().getReportDefinition(); + + const bool bWillBeVisible = _bToggleOn; + m_pPropWin->Show(bWillBeVisible); + m_pTaskPane->Show(bWillBeVisible); + m_pTaskPane->Invalidate(); + + if ( bWillBeVisible ) + m_aSplitWin->InsertItem( TASKPANE_ID, m_pTaskPane,START_SIZE_TASKPANE, SPLITWINDOW_APPEND, COLSET_ID, SplitWindowItemFlags::PercentSize); + else + m_aSplitWin->RemoveItem(TASKPANE_ID); + + if ( bWillBeVisible ) + m_aMarkIdle.Start(); +} + +void ODesignView::showProperties(const uno::Reference< uno::XInterface>& _xReportComponent) +{ + if ( m_xReportComponent != _xReportComponent ) + { + m_xReportComponent = _xReportComponent; + if ( m_pCurrentView ) + m_aScrollWindow->setMarked(m_pCurrentView,false); + m_pCurrentView = nullptr; + m_aMarkIdle.Start(); + } +} + +bool ODesignView::isReportExplorerVisible() const +{ + return m_xReportExplorer && m_xReportExplorer->getDialog()->get_visible(); +} + +void ODesignView::toggleReportExplorer() +{ + if ( !m_xReportExplorer ) + { + OReportController& rReportController = getController(); + m_xReportExplorer = std::make_shared<ONavigator>(GetFrameWeld(), rReportController); + SvtViewOptions aDlgOpt(EViewType::Window, OStringToOUString(m_xReportExplorer->get_help_id(), RTL_TEXTENCODING_UTF8)); + if ( aDlgOpt.Exists() ) + m_xReportExplorer->getDialog()->set_window_state(OUStringToOString(aDlgOpt.GetWindowState(), RTL_TEXTENCODING_ASCII_US)); + } + + if (!m_xReportExplorer->getDialog()->get_visible()) + weld::DialogController::runAsync(m_xReportExplorer, [this](sal_Int32 /*nResult*/) { m_xReportExplorer.reset(); }); + else + m_xReportExplorer->response(RET_CANCEL); +} + +bool ODesignView::isAddFieldVisible() const +{ + return m_xAddField && m_xAddField->getDialog()->get_visible(); +} + +void ODesignView::toggleAddField() +{ + if (!m_xAddField) + { + uno::Reference< report::XReportDefinition > xReport(m_xReportComponent,uno::UNO_QUERY); + uno::Reference< report::XReportComponent > xReportComponent(m_xReportComponent,uno::UNO_QUERY); + OReportController& rReportController = getController(); + if ( !m_pCurrentView && !xReport.is() ) + { + if ( xReportComponent.is() ) + xReport = xReportComponent->getSection()->getReportDefinition(); + else + xReport = rReportController.getReportDefinition().get(); + } + else if ( m_pCurrentView ) + { + uno::Reference< report::XSection > xSection = m_pCurrentView->getReportSection()->getSection(); + xReport = xSection->getReportDefinition(); + } + uno::Reference < beans::XPropertySet > xSet(rReportController.getRowSet(),uno::UNO_QUERY); + m_xAddField = std::make_shared<OAddFieldWindow>(GetFrameWeld(), xSet); + m_xAddField->SetCreateHdl(LINK( &rReportController, OReportController, OnCreateHdl ) ); + SvtViewOptions aDlgOpt( EViewType::Window, UID_RPT_RPT_APP_VIEW ); + if ( aDlgOpt.Exists() ) + m_xAddField->getDialog()->set_window_state(OUStringToOString(aDlgOpt.GetWindowState(), RTL_TEXTENCODING_ASCII_US)); + m_xAddField->Update(); + } + if (!m_xAddField->getDialog()->get_visible()) + weld::DialogController::runAsync(m_xAddField, [this](sal_Int32 /*nResult*/) { m_xAddField.reset(); }); + else + m_xAddField->response(RET_CANCEL); +} + +uno::Reference< report::XSection > ODesignView::getCurrentSection() const +{ + uno::Reference< report::XSection > xSection; + if ( m_pCurrentView ) + xSection = m_pCurrentView->getReportSection()->getSection(); + + return xSection; +} + +uno::Reference< report::XReportComponent > ODesignView::getCurrentControlModel() const +{ + uno::Reference< report::XReportComponent > xModel; + if ( m_pCurrentView ) + { + xModel = m_pCurrentView->getReportSection()->getCurrentControlModel(); + } + return xModel; +} + +OSectionWindow* ODesignView::getMarkedSection(NearSectionAccess nsa) const +{ + return m_aScrollWindow->getMarkedSection(nsa); +} + +OSectionWindow* ODesignView::getSectionWindow(const css::uno::Reference< css::report::XSection>& _xSection) const +{ + return m_aScrollWindow->getSectionWindow(_xSection); +} + +void ODesignView::markSection(const sal_uInt16 _nPos) +{ + m_aScrollWindow->markSection(_nPos); +} + +void ODesignView::fillCollapsedSections(::std::vector<sal_uInt16>& _rCollapsedPositions) const +{ + m_aScrollWindow->fillCollapsedSections(_rCollapsedPositions); +} + +void ODesignView::collapseSections(const uno::Sequence< beans::PropertyValue>& _aCollapsedSections) +{ + m_aScrollWindow->collapseSections(_aCollapsedSections); +} + +OUString ODesignView::getCurrentPage() const +{ + return m_pPropWin ? m_pPropWin->getCurrentPage() : OUString(); +} + +void ODesignView::setCurrentPage(const OUString& _sLastActivePage) +{ + if ( m_pPropWin ) + m_pPropWin->setCurrentPage(_sLastActivePage); +} + +void ODesignView::alignMarkedObjects(ControlModification _nControlModification,bool _bAlignAtSection) +{ + m_aScrollWindow->alignMarkedObjects(_nControlModification, _bAlignAtSection); +} + +bool ODesignView::handleKeyEvent(const KeyEvent& _rEvent) +{ + if ( m_pPropWin && m_pPropWin->HasChildPathFocus() ) + return false; + if (m_xAddField && m_xAddField->getDialog()->has_toplevel_focus()) + return false; + if (m_xReportExplorer && m_xReportExplorer->getDialog()->has_toplevel_focus()) + return false; + return m_aScrollWindow->handleKeyEvent(_rEvent); +} + +void ODesignView::setMarked(const uno::Reference< report::XSection>& _xSection,bool _bMark) +{ + m_aScrollWindow->setMarked(_xSection,_bMark); + if ( _bMark ) + UpdatePropertyBrowserDelayed(getMarkedSection()->getReportSection().getSectionView()); + else + m_pCurrentView = nullptr; +} + +void ODesignView::setMarked(const uno::Sequence< uno::Reference< report::XReportComponent> >& _aShapes,bool _bMark) +{ + m_aScrollWindow->setMarked(_aShapes,_bMark); + if ( _aShapes.hasElements() && _bMark ) + showProperties(_aShapes[0]); + else + m_xReportComponent.clear(); +} + +void ODesignView::MouseButtonDown( const MouseEvent& rMEvt ) +{ + if ( rMEvt.IsLeft() ) + { + const uno::Sequence< beans::PropertyValue> aArgs; + getController().executeChecked(SID_SELECT_REPORT,aArgs); + } + ODataView::MouseButtonDown(rMEvt); +} + +uno::Any ODesignView::getCurrentlyShownProperty() const +{ + uno::Any aRet; + OSectionWindow* pSectionWindow = getMarkedSection(); + if ( pSectionWindow ) + { + ::std::vector< uno::Reference< uno::XInterface > > aSelection; + pSectionWindow->getReportSection().fillControlModelSelection(aSelection); + if ( !aSelection.empty() ) + { + uno::Sequence< uno::Reference< report::XReportComponent > > aSeq(aSelection.size()); + std::transform( + aSelection.begin(), aSelection.end(), aSeq.getArray(), + [](const auto& rxInterface) + { return uno::Reference<report::XReportComponent>(rxInterface, uno::UNO_QUERY); }); + aRet <<= aSeq; + } + } + return aRet; +} + +void ODesignView::fillControlModelSelection(::std::vector< uno::Reference< uno::XInterface > >& _rSelection) const +{ + m_aScrollWindow->fillControlModelSelection(_rSelection); +} + +void ODesignView::setGridSnap(bool bOn) +{ + m_aScrollWindow->setGridSnap(bOn); + +} + +void ODesignView::setDragStripes(bool bOn) +{ + m_aScrollWindow->setDragStripes(bOn); +} + +bool ODesignView::isHandleEvent() const +{ + return m_pPropWin && m_pPropWin->HasChildPathFocus(); +} + +sal_uInt32 ODesignView::getMarkedObjectCount() const +{ + return m_aScrollWindow->getMarkedObjectCount(); +} + +void ODesignView::zoom(const Fraction& _aZoom) +{ + m_aScrollWindow->zoom(_aZoom); +} + +sal_uInt16 ODesignView::getZoomFactor(SvxZoomType _eType) const +{ + return m_aScrollWindow->getZoomFactor(_eType); +} + +} // rptui + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/reportdesign/source/ui/report/EndMarker.cxx b/reportdesign/source/ui/report/EndMarker.cxx new file mode 100644 index 000000000..fdd28f4db --- /dev/null +++ b/reportdesign/source/ui/report/EndMarker.cxx @@ -0,0 +1,99 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * 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 . + */ +#include <EndMarker.hxx> +#include <ColorChanger.hxx> +#include <SectionWindow.hxx> + +#include <vcl/settings.hxx> +#include <vcl/svapp.hxx> +#include <vcl/gradient.hxx> +#include <vcl/lineinfo.hxx> +#include <vcl/event.hxx> + + +#define CORNER_SPACE 5 + +namespace rptui +{ + +OEndMarker::OEndMarker(vcl::Window* _pParent ,const OUString& _sColorEntry) + : OColorListener(_pParent, _sColorEntry) +{ + ImplInitSettings(); +} + +OEndMarker::~OEndMarker() +{ +} + +void OEndMarker::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& /*rRect*/) +{ + Fraction aCornerSpace(tools::Long(CORNER_SPACE)); + aCornerSpace *= rRenderContext.GetMapMode().GetScaleX(); + const tools::Long nCornerSpace = tools::Long(aCornerSpace); + + Size aSize = GetSizePixel(); + aSize.AdjustWidth(nCornerSpace ); + tools::Rectangle aWholeRect(Point(-nCornerSpace,0),aSize); + tools::PolyPolygon aPoly; + aPoly.Insert( tools::Polygon(aWholeRect,nCornerSpace,nCornerSpace)); + + Color aStartColor(m_nColor); + aStartColor.IncreaseLuminance(10); + sal_uInt16 nHue = 0; + sal_uInt16 nSat = 0; + sal_uInt16 nBri = 0; + aStartColor.RGBtoHSB(nHue, nSat, nBri); + nSat += 40; + Color aEndColor(Color::HSBtoRGB(nHue, nSat, nBri)); + Gradient aGradient(GradientStyle::Linear, aStartColor, aEndColor); + aGradient.SetSteps(static_cast<sal_uInt16>(aSize.Height())); + + rRenderContext.DrawGradient(PixelToLogic(aPoly), aGradient); + if (m_bMarked) + { + tools::Rectangle aRect(Point(-nCornerSpace, nCornerSpace), + Size(aSize.Width() - nCornerSpace, + aSize.Height() - nCornerSpace - nCornerSpace)); + ColorChanger aColors(GetOutDev(), COL_WHITE, COL_WHITE); + rRenderContext.DrawPolyLine( tools::Polygon(PixelToLogic(aRect)), LineInfo(LineStyle::Solid, 2)); + } +} + +void OEndMarker::ImplInitSettings() +{ + EnableChildTransparentMode(); + SetParentClipMode( ParentClipMode::NoClip ); + SetPaintTransparent( true ); + + SetBackground( Wallpaper( svtools::ColorConfig().GetColorValue(::svtools::APPBACKGROUND).nColor) ); + GetOutDev()->SetFillColor( Application::GetSettings().GetStyleSettings().GetShadowColor() ); +} + +void OEndMarker::MouseButtonDown( const MouseEvent& rMEvt ) +{ + if ( !rMEvt.IsLeft() && !rMEvt.IsRight()) + return; + static_cast<OSectionWindow*>(GetParent())->showProperties(); +} + +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/reportdesign/source/ui/report/FixedTextColor.cxx b/reportdesign/source/ui/report/FixedTextColor.cxx new file mode 100644 index 000000000..b0dd3c496 --- /dev/null +++ b/reportdesign/source/ui/report/FixedTextColor.cxx @@ -0,0 +1,193 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * 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 . + */ + + +#include <FixedTextColor.hxx> +#include <com/sun/star/report/XFixedText.hpp> +#include <com/sun/star/awt/XVclWindowPeer.hpp> + +#include <RptObject.hxx> +#include <RptModel.hxx> +#include <RptPage.hxx> +#include <ReportSection.hxx> +#include <ReportController.hxx> +#include <strings.hxx> + +#include <tools/color.hxx> + +// DBG_UNHANDLED_EXCEPTION +#include <tools/diagnose_ex.h> + +#include <vcl/svapp.hxx> +#include <vcl/settings.hxx> + +namespace rptui +{ + using namespace ::com::sun::star; + + + FixedTextColor::FixedTextColor(const OReportController& _aController) + :m_rReportController(_aController) + { + } + + + FixedTextColor::~FixedTextColor() + { + } + + + void FixedTextColor::notifyPropertyChange( const beans::PropertyChangeEvent& _rEvent ) + { + uno::Reference< report::XFixedText > xFixedText( _rEvent.Source, uno::UNO_QUERY ); + if ( ! xFixedText.is() ) + { + return; + } + + try + { + uno::Reference< lang::XComponent > xComponent( xFixedText, uno::UNO_QUERY_THROW ); + handle(xComponent); + } + catch (uno::Exception const&) + { + DBG_UNHANDLED_EXCEPTION("reportdesign"); + } + } + + + void FixedTextColor::setPropertyTextColor(const uno::Reference< awt::XVclWindowPeer >& _xVclWindowPeer, Color _nTextColor) + { + _xVclWindowPeer->setProperty(PROPERTY_TEXTCOLOR, uno::Any(_nTextColor)); + } + + + void FixedTextColor::notifyElementInserted( const uno::Reference< uno::XInterface >& _rxElement ) + { + handle(_rxElement); + } + + + void FixedTextColor::handle( const uno::Reference< uno::XInterface >& _rxElement ) + { + uno::Reference< report::XFixedText > xFixedText( _rxElement, uno::UNO_QUERY ); + if ( ! xFixedText.is() ) + { + return; + } + + try + { + bool bIsDark = false; + const Color nBackColor( ColorTransparency, xFixedText->getControlBackground() ); + if (nBackColor == COL_TRANSPARENT) + { + uno::Reference <report::XSection> xSection(xFixedText->getParent(), uno::UNO_QUERY_THROW); + + bool bSectionBackColorIsTransparent = xSection->getBackTransparent(); + if (bSectionBackColorIsTransparent) + { + // Label Transparent, Section Transparent set LabelTextColor + const StyleSettings& aStyleSettings = Application::GetSettings().GetStyleSettings(); + Color aWindowColor = aStyleSettings.GetWindowColor(); + bIsDark = aWindowColor.IsDark(); + } + else + { + css::util::Color aColor2 = xSection->getBackColor(); + Color aBackColor(ColorTransparency, aColor2); + bIsDark = aBackColor.IsDark(); + } + } + else + { + Color aLabelBackColor(nBackColor); + bIsDark = aLabelBackColor.IsDark(); + } + + uno::Reference<awt::XVclWindowPeer> xVclWindowPeer = getVclWindowPeer(xFixedText); + if (bIsDark) + { + const StyleSettings& aStyleSettings = Application::GetSettings().GetStyleSettings(); + Color aLabelTextColor = aStyleSettings.GetLabelTextColor(); + setPropertyTextColor(xVclWindowPeer, aLabelTextColor); + } + else + { + util::Color aLabelColor = xFixedText->getCharColor(); + setPropertyTextColor(xVclWindowPeer, ::Color(ColorTransparency, aLabelColor)); + } + + } + catch( const uno::Exception& ) + { + DBG_UNHANDLED_EXCEPTION("reportdesign"); + } + } + + + // XPropertyChangeListener + uno::Reference<awt::XControl> FixedTextColor::getXControl(const uno::Reference< report::XFixedText >& _xFixedText) + { + + uno::Reference<awt::XControl> xControl; + OReportController *pController = const_cast<OReportController *>(&m_rReportController); + + std::shared_ptr<OReportModel> pModel = pController->getSdrModel(); + + uno::Reference<report::XSection> xSection(_xFixedText->getSection()); + if ( xSection.is() ) + { + OReportPage *pPage = pModel->getPage(xSection); + const size_t nIndex = pPage->getIndexOf(_xFixedText); + if (nIndex < pPage->GetObjCount() ) + { + SdrObject *pObject = pPage->GetObj(nIndex); + OUnoObject* pUnoObj = dynamic_cast<OUnoObject*>(pObject); + if ( pUnoObj ) // this doesn't need to be done for shapes + { + OSectionWindow* pSectionWindow = pController->getSectionWindow(xSection); + if (pSectionWindow != nullptr) + { + OReportSection& aOutputDevice = pSectionWindow->getReportSection(); // OutputDevice + OSectionView& aSdrView = aOutputDevice.getSectionView(); // SdrView + xControl = pUnoObj->GetUnoControl(aSdrView, *aOutputDevice.GetOutDev()); + } + } + } + } + return xControl; + } + + + uno::Reference<awt::XVclWindowPeer> FixedTextColor::getVclWindowPeer(const uno::Reference< report::XFixedText >& _xComponent) + { + uno::Reference<awt::XVclWindowPeer> xVclWindowPeer; + uno::Reference<awt::XControl> xControl = getXControl(_xComponent); + + xVclWindowPeer.set( xControl->getPeer(), uno::UNO_QUERY); + + return xVclWindowPeer; + } + + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/reportdesign/source/ui/report/FormattedFieldBeautifier.cxx b/reportdesign/source/ui/report/FormattedFieldBeautifier.cxx new file mode 100644 index 000000000..d4fec971e --- /dev/null +++ b/reportdesign/source/ui/report/FormattedFieldBeautifier.cxx @@ -0,0 +1,177 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * 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 . + */ + + +#include <FormattedFieldBeautifier.hxx> + +#include <com/sun/star/report/XFormattedField.hpp> +#include <com/sun/star/awt/XVclWindowPeer.hpp> + +#include <RptObject.hxx> +#include <RptModel.hxx> +#include <RptPage.hxx> +#include <ReportSection.hxx> +#include <ReportController.hxx> +#include <strings.hxx> +#include <reportformula.hxx> + +#include <svtools/extcolorcfg.hxx> + +// DBG_UNHANDLED_EXCEPTION +#include <tools/diagnose_ex.h> + +namespace rptui +{ + using namespace ::com::sun::star; + + + FormattedFieldBeautifier::FormattedFieldBeautifier(const OReportController& _aController) + :m_rReportController(_aController) + ,m_nTextColor(COL_AUTO) + { + } + + + Color FormattedFieldBeautifier::getTextColor() + { + if (m_nTextColor == COL_AUTO) + { + svtools::ExtendedColorConfig aConfig; + m_nTextColor = aConfig.GetColorValue(CFG_REPORTDESIGNER, DBTEXTBOXBOUNDCONTENT).getColor(); + } + return m_nTextColor; + } + + + FormattedFieldBeautifier::~FormattedFieldBeautifier() + { + } + + + void FormattedFieldBeautifier::setPlaceholderText( const uno::Reference< uno::XInterface >& _rxComponent ) + { + try + { + uno::Reference< report::XFormattedField > xControlModel( _rxComponent, uno::UNO_QUERY ); + if ( xControlModel.is() ) + { + OUString sDataField = xControlModel->getDataField(); + + if ( !sDataField.isEmpty() ) + { + ReportFormula aFormula( sDataField ); + bool bSet = true; + if ( aFormula.getType() == ReportFormula::Field ) + { + const OUString& sColumnName = aFormula.getFieldName(); + OUString sLabel = m_rReportController.getColumnLabel_throw(sColumnName); + if ( !sLabel.isEmpty() ) + { + sDataField = "=" + sLabel; + bSet = false; + } + } + if ( bSet ) + sDataField = aFormula.getEqualUndecoratedContent(); + } + + setPlaceholderText( getVclWindowPeer( xControlModel ), sDataField ); + } + } + catch (const uno::Exception &) + { + DBG_UNHANDLED_EXCEPTION("reportdesign"); + } + } + + + void FormattedFieldBeautifier::setPlaceholderText( const uno::Reference< awt::XVclWindowPeer >& _xVclWindowPeer, const OUString& _rText ) + { + OSL_ENSURE( _xVclWindowPeer.is(), "FormattedFieldBeautifier::setPlaceholderText: invalid peer!" ); + if ( !_xVclWindowPeer.is() ) + throw uno::RuntimeException(); + + // the actual text + _xVclWindowPeer->setProperty(PROPERTY_TEXT, uno::Any(_rText)); + // the text color + _xVclWindowPeer->setProperty(PROPERTY_TEXTCOLOR, uno::Any(getTextColor())); + // font->italic + uno::Any aFontDescriptor = _xVclWindowPeer->getProperty(PROPERTY_FONTDESCRIPTOR); + awt::FontDescriptor aFontDescriptorStructure; + aFontDescriptor >>= aFontDescriptorStructure; + aFontDescriptorStructure.Slant = css::awt::FontSlant_ITALIC; + _xVclWindowPeer->setProperty(PROPERTY_FONTDESCRIPTOR, uno::Any(aFontDescriptorStructure)); + } + + + void FormattedFieldBeautifier::notifyPropertyChange( const beans::PropertyChangeEvent& _rEvent ) + { + if ( _rEvent.PropertyName != "DataField" ) + // not interested in + return; + + setPlaceholderText( _rEvent.Source ); + } + + + void FormattedFieldBeautifier::handle( const uno::Reference< uno::XInterface >& _rxElement ) + { + setPlaceholderText( _rxElement ); + } + + + void FormattedFieldBeautifier::notifyElementInserted( const uno::Reference< uno::XInterface >& _rxElement ) + { + handle( _rxElement ); + } + + + uno::Reference<awt::XVclWindowPeer> FormattedFieldBeautifier::getVclWindowPeer(const uno::Reference< report::XReportComponent >& _xComponent) + { + uno::Reference<awt::XVclWindowPeer> xVclWindowPeer; + + std::shared_ptr<OReportModel> pModel = m_rReportController.getSdrModel(); + + uno::Reference<report::XSection> xSection(_xComponent->getSection()); + if ( xSection.is() ) + { + OReportPage *pPage = pModel->getPage(xSection); + const size_t nIndex = pPage->getIndexOf(_xComponent); + if (nIndex < pPage->GetObjCount() ) + { + SdrObject *pObject = pPage->GetObj(nIndex); + OUnoObject* pUnoObj = dynamic_cast<OUnoObject*>(pObject); + if ( pUnoObj ) // this doesn't need to be done for shapes + { + OSectionWindow* pSectionWindow = m_rReportController.getSectionWindow(xSection); + if (pSectionWindow != nullptr) + { + OReportSection& aOutputDevice = pSectionWindow->getReportSection(); // OutputDevice + OSectionView& aSdrView = aOutputDevice.getSectionView(); // SdrView + uno::Reference<awt::XControl> xControl = pUnoObj->GetUnoControl(aSdrView, *aOutputDevice.GetOutDev()); + xVclWindowPeer.set( xControl->getPeer(), uno::UNO_QUERY); + } + } + } + } + return xVclWindowPeer; + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/reportdesign/source/ui/report/ReportController.cxx b/reportdesign/source/ui/report/ReportController.cxx new file mode 100644 index 000000000..82edfba92 --- /dev/null +++ b/reportdesign/source/ui/report/ReportController.cxx @@ -0,0 +1,4365 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * 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 . + */ + +#include <ReportController.hxx> +#include <ReportDefinition.hxx> +#include <CondFormat.hxx> +#include <UITools.hxx> +#include <AddField.hxx> +#include <toolkit/helper/vclunohelper.hxx> +#include <DateTime.hxx> + +#include <sfx2/filedlghelper.hxx> +#include <tools/diagnose_ex.h> +#include <rptui_slotid.hrc> +#include <reportformula.hxx> + +#include <comphelper/documentconstants.hxx> +#include <unotools/mediadescriptor.hxx> +#include <comphelper/propertysequence.hxx> +#include <comphelper/propertyvalue.hxx> +#include <comphelper/sequenceashashmap.hxx> +#include <comphelper/types.hxx> + +#include <connectivity/dbtools.hxx> +#include <com/sun/star/style/XStyle.hpp> +#include <com/sun/star/style/ParagraphAdjust.hpp> +#include <com/sun/star/util/NumberFormatter.hpp> +#include <com/sun/star/ui/dialogs/XFilePicker3.hpp> +#include <com/sun/star/ui/dialogs/XFilePickerControlAccess.hpp> +#include <com/sun/star/ui/dialogs/TemplateDescription.hpp> +#include <com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.hpp> +#include <com/sun/star/frame/FrameSearchFlag.hpp> +#include <com/sun/star/container/XChild.hpp> +#include <com/sun/star/report/XImageControl.hpp> +#include <com/sun/star/report/XFixedLine.hpp> +#include <com/sun/star/report/Function.hpp> +#include <com/sun/star/awt/FontDescriptor.hpp> +#include <com/sun/star/sdb/XParametersSupplier.hpp> +#include <com/sun/star/sdb/CommandType.hpp> +#include <com/sun/star/sdbcx/XTablesSupplier.hpp> +#include <com/sun/star/embed/EmbedMapUnits.hpp> +#include <com/sun/star/awt/FontWeight.hpp> +#include <com/sun/star/awt/FontUnderline.hpp> +#include <com/sun/star/awt/FontSlant.hpp> +#include <com/sun/star/frame/Desktop.hpp> +#include <com/sun/star/frame/status/FontHeight.hpp> +#include <com/sun/star/report/ReportEngine.hpp> +#include <com/sun/star/report/XFormattedField.hpp> +#include <com/sun/star/sdb/SQLContext.hpp> +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/document/XUndoManagerSupplier.hpp> + +#include <vcl/svapp.hxx> + +#include <i18nutil/paper.hxx> +#include <svx/fmview.hxx> +#include <editeng/memberids.h> +#include <svx/svxids.hrc> +#include <svx/svdobj.hxx> +#include <svx/unomid.hxx> +#include <svx/dataaccessdescriptor.hxx> +#include <svx/xfillit0.hxx> +#include <svx/xflclit.hxx> +#include <svx/xflgrit.hxx> +#include <svx/xflhtit.hxx> +#include <svx/xbtmpit.hxx> +#include <svx/xflftrit.hxx> +#include <svx/xsflclit.hxx> +#include <svx/xflbckit.hxx> +#include <svx/xflbmpit.hxx> +#include <svx/xflbmsli.hxx> +#include <svx/xflbmsxy.hxx> +#include <svx/xflbmtit.hxx> +#include <svx/xflboxy.hxx> +#include <svx/xflbstit.hxx> +#include <svx/xflbtoxy.hxx> +#include <svx/xfltrit.hxx> +#include <svx/xgrscit.hxx> +#include <editeng/svxenum.hxx> +#include <svx/pageitem.hxx> +#include <editeng/lrspitem.hxx> +#include <editeng/ulspitem.hxx> +#include <editeng/sizeitem.hxx> +#include <sfx2/zoomitem.hxx> +#include <svx/zoomslideritem.hxx> +#include <editeng/brushitem.hxx> +#include <svx/flagsdef.hxx> +#include <svx/svdpagv.hxx> +#include <svx/svxdlg.hxx> + +#include <core_resource.hxx> +#include <DesignView.hxx> +#include <RptObject.hxx> +#include <RptUndo.hxx> +#include <strings.hxx> +#include <RptDef.hxx> +#include <ReportSection.hxx> +#include <SectionView.hxx> +#include <UndoActions.hxx> +#include <dlgpage.hxx> +#include <strings.hrc> + +#include <svl/itempool.hxx> +#include <svl/itemset.hxx> +#include <svtools/cliplistener.hxx> +#include <unotools/syslocale.hxx> +#include <unotools/viewoptions.hxx> +#include <unotools/localedatawrapper.hxx> + +#include <osl/mutex.hxx> +#include <PropertyForward.hxx> +#include <SectionWindow.hxx> + +#include <toolkit/helper/convert.hxx> +#include <GroupsSorting.hxx> +#include <PageNumber.hxx> +#include <UndoEnv.hxx> + +#include <memory> +#include <string_view> + +#include <cppuhelper/exc_hlp.hxx> +#include <unotools/confignode.hxx> + +#include <ReportControllerObserver.hxx> + +#define MAX_ROWS_FOR_PREVIEW 20 + +#define RPTUI_ID_LRSPACE TypedWhichId<SvxLRSpaceItem>(XATTR_FILL_FIRST - 8) +#define RPTUI_ID_ULSPACE TypedWhichId<SvxULSpaceItem>(XATTR_FILL_FIRST - 7) +#define RPTUI_ID_PAGE TypedWhichId<SvxPageItem>(XATTR_FILL_FIRST - 6) +#define RPTUI_ID_SIZE TypedWhichId<SvxSizeItem>(XATTR_FILL_FIRST - 5) +#define RPTUI_ID_PAGE_MODE XATTR_FILL_FIRST - 4 +#define RPTUI_ID_START XATTR_FILL_FIRST - 3 +#define RPTUI_ID_END XATTR_FILL_FIRST - 2 +#define RPTUI_ID_BRUSH TypedWhichId<SvxBrushItem>(XATTR_FILL_FIRST - 1) +/// Note that we deliberately overlap an existing item id, so that we can have contiguous item ids for +/// the static defaults. +#define RPTUI_ID_METRIC XATTR_FILL_LAST + +using namespace ::com::sun::star; +using namespace uno; +using namespace io; +using namespace beans; +using namespace frame; +using namespace util; +using namespace lang; +using namespace container; +using namespace sdbcx; +using namespace sdbc; +using namespace sdb; +using namespace ui; +using namespace ui::dialogs; +using namespace ::dbtools; +using namespace ::rptui; +using namespace ::dbaui; +using namespace ::comphelper; +using namespace ::cppu; + + +namespace +{ + void lcl_setFontWPU_nothrow(const uno::Reference< report::XReportControlFormat>& _xReportControlFormat,const sal_Int32 _nId) + { + if ( !_xReportControlFormat.is() ) + return; + + try + { + awt::FontDescriptor aFontDescriptor = _xReportControlFormat->getFontDescriptor(); + switch(_nId) + { + case SID_ATTR_CHAR_WEIGHT: + aFontDescriptor.Weight = (awt::FontWeight::NORMAL + awt::FontWeight::BOLD) - aFontDescriptor.Weight; + break; + case SID_ATTR_CHAR_POSTURE: + aFontDescriptor.Slant = static_cast<awt::FontSlant>(static_cast<sal_Int16>(awt::FontSlant_ITALIC) - static_cast<sal_Int16>(aFontDescriptor.Slant)); + break; + case SID_ATTR_CHAR_UNDERLINE: + aFontDescriptor.Underline = awt::FontUnderline::SINGLE - aFontDescriptor.Underline; + break; + default: + OSL_FAIL("Illegal value in default!"); + break; + } + + _xReportControlFormat->setFontDescriptor(aFontDescriptor); + } + catch(const beans::UnknownPropertyException&) + { + } + } +} + + +static void lcl_getReportControlFormat(const Sequence< PropertyValue >& aArgs, + ODesignView* _pView, + uno::Reference< awt::XWindow>& _xWindow, + ::std::vector< uno::Reference< uno::XInterface > >& _rControlsFormats) +{ + uno::Reference< report::XReportControlFormat> xReportControlFormat; + if ( aArgs.hasElements() ) + { + SequenceAsHashMap aMap(aArgs); + xReportControlFormat = aMap.getUnpackedValueOrDefault(REPORTCONTROLFORMAT,uno::Reference< report::XReportControlFormat>()); + _xWindow = aMap.getUnpackedValueOrDefault(CURRENT_WINDOW,uno::Reference< awt::XWindow>()); + } + + if ( !xReportControlFormat.is() ) + { + _pView->fillControlModelSelection(_rControlsFormats); + } + else + { + uno::Reference<uno::XInterface> xInterface(xReportControlFormat); + _rControlsFormats.push_back(xInterface); + } + + if ( !_xWindow.is() ) + _xWindow = VCLUnoHelper::GetInterface(_pView); +} + +OUString SAL_CALL OReportController::getImplementationName() +{ + return "com.sun.star.report.comp.ReportDesign"; +} + +Sequence< OUString> SAL_CALL OReportController::getSupportedServiceNames() +{ + return { "com.sun.star.sdb.ReportDesign" }; +} + +#define PROPERTY_ID_ZOOMVALUE 1 + + +OReportController::OReportController(Reference< XComponentContext > const & xContext) + :OReportController_BASE(xContext) + ,OPropertyStateContainer(OGenericUnoController_Base::rBHelper) + ,m_aSelectionListeners( getMutex() ) + ,m_sMode("normal") + ,m_nSplitPos(-1) + ,m_nPageNum(-1) + ,m_nSelectionCount(0) + ,m_nAspect(0) + ,m_nZoomValue(100) + ,m_eZoomType(SvxZoomType::PERCENT) + ,m_bShowRuler(true) + ,m_bGridVisible(true) + ,m_bGridUse(true) + ,m_bShowProperties(true) + ,m_bHelplinesMove(true) + ,m_bChartEnabled(false) + ,m_bChartEnabledAsked(false) + ,m_bInGeneratePreview(false) +{ + // new Observer + m_pReportControllerObserver = new OXReportControllerObserver(*this); + registerProperty("ZoomValue", PROPERTY_ID_ZOOMVALUE, + beans::PropertyAttribute::BOUND | beans::PropertyAttribute::TRANSIENT, + &m_nZoomValue, ::cppu::UnoType<sal_Int16>::get()); + +} + +OReportController::~OReportController() +{ +} + +IMPLEMENT_FORWARD_XTYPEPROVIDER2(OReportController,OReportController_BASE,OReportController_Listener) +IMPLEMENT_FORWARD_XINTERFACE2(OReportController,OReportController_BASE,OReportController_Listener) + +void OReportController::disposing() +{ + + if ( m_pClipboardNotifier.is() ) + { + m_pClipboardNotifier->ClearCallbackLink(); + m_pClipboardNotifier->RemoveListener( getView() ); + m_pClipboardNotifier.clear(); + } + if ( m_xGroupsFloater ) + { + SvtViewOptions aDlgOpt(EViewType::Window, OStringToOUString(m_xGroupsFloater->get_help_id(), RTL_TEXTENCODING_UTF8)); + aDlgOpt.SetWindowState(OStringToOUString(m_xGroupsFloater->getDialog()->get_window_state(WindowStateMask::All), RTL_TEXTENCODING_ASCII_US)); + if (m_xGroupsFloater->getDialog()->get_visible()) + m_xGroupsFloater->response(RET_CANCEL); + m_xGroupsFloater.reset(); + } + + try + { + m_xHoldAlive.clear(); + m_xColumns.clear(); + ::comphelper::disposeComponent( m_xRowSet ); + ::comphelper::disposeComponent( m_xRowSetMediator ); + ::comphelper::disposeComponent( m_xFormatter ); + } + catch(const uno::Exception&) + { + TOOLS_WARN_EXCEPTION( "reportdesign", "Exception caught while disposing row sets."); + } + m_xRowSet.clear(); + m_xRowSetMediator.clear(); + + if ( m_xReportDefinition.is() ) + { + try + { + OSectionWindow* pSectionWindow = nullptr; + if ( getDesignView() ) + pSectionWindow = getDesignView()->getMarkedSection(); + if ( pSectionWindow ) + pSectionWindow->getReportSection().deactivateOle(); + clearUndoManager(); + if ( m_aReportModel ) + listen(false); + m_pReportControllerObserver->Clear(); + m_pReportControllerObserver.clear(); + } + catch(const uno::Exception&) + { + DBG_UNHANDLED_EXCEPTION("reportdesign"); + } + } + + { + EventObject aDisposingEvent( *this ); + m_aSelectionListeners.disposeAndClear( aDisposingEvent ); + } + + OReportController_BASE::disposing(); + + + try + { + m_xReportDefinition.clear(); + m_aReportModel.reset(); + m_xFrameLoader.clear(); + m_xReportEngine.clear(); + } + catch(const uno::Exception&) + { + } + if ( getDesignView() ) + EndListening( *getDesignView() ); + clearView(); +} + +FeatureState OReportController::GetState(sal_uInt16 _nId) const +{ + FeatureState aReturn; + // (disabled automatically) + aReturn.bEnabled = false; + // check this first + if ( !getView() ) + return aReturn; + + switch (_nId) + { + case SID_RPT_TEXTDOCUMENT: + aReturn.bEnabled = isEditable(); + aReturn.bChecked = (m_xReportDefinition.is() && m_xReportDefinition->getMimeType() == MIMETYPE_OASIS_OPENDOCUMENT_TEXT_ASCII); + break; + case SID_RPT_SPREADSHEET: + aReturn.bEnabled = isEditable(); + aReturn.bChecked = (m_xReportDefinition.is() && m_xReportDefinition->getMimeType() == MIMETYPE_OASIS_OPENDOCUMENT_SPREADSHEET_ASCII); + break; + case SID_REPORTHEADER_WITHOUT_UNDO: + case SID_REPORTFOOTER_WITHOUT_UNDO: + case SID_REPORTHEADERFOOTER: + { + aReturn.bEnabled = isEditable(); + OUString sText = RptResId((m_xReportDefinition.is() && m_xReportDefinition->getReportHeaderOn()) ? RID_STR_REPORTHEADERFOOTER_DELETE : RID_STR_REPORTHEADERFOOTER_INSERT); + aReturn.sTitle = sText; + } + break; + case SID_PAGEHEADER_WITHOUT_UNDO: + case SID_PAGEFOOTER_WITHOUT_UNDO: + case SID_PAGEHEADERFOOTER: + { + aReturn.bEnabled = isEditable(); + OUString sText = RptResId((m_xReportDefinition.is() && m_xReportDefinition->getPageHeaderOn()) ? RID_STR_PAGEHEADERFOOTER_DELETE : RID_STR_PAGEHEADERFOOTER_INSERT); + aReturn.sTitle = sText; + } + break; + case SID_GROUP_APPEND: + case SID_GROUP_REMOVE: + case SID_GROUPHEADER_WITHOUT_UNDO: + case SID_GROUPHEADER: + case SID_GROUPFOOTER_WITHOUT_UNDO: + case SID_GROUPFOOTER: + aReturn.bEnabled = isEditable(); + break; + case SID_ADD_CONTROL_PAIR: + aReturn.bEnabled = isEditable(); + break; + case SID_REDO: + case SID_UNDO: + { + size_t ( SfxUndoManager::*retrieveCount )( bool const ) const = + ( _nId == SID_UNDO ) ? &SfxUndoManager::GetUndoActionCount : &SfxUndoManager::GetRedoActionCount; + + SfxUndoManager& rUndoManager( getUndoManager() ); + aReturn.bEnabled = ( rUndoManager.*retrieveCount )( SfxUndoManager::TopLevel ) > 0; + if ( aReturn.bEnabled ) + { + // TODO: add "Undo/Redo: prefix" + OUString ( SfxUndoManager::*retrieveComment )( size_t, bool const ) const = + ( _nId == SID_UNDO ) ? &SfxUndoManager::GetUndoActionComment : &SfxUndoManager::GetRedoActionComment; + aReturn.sTitle = (rUndoManager.*retrieveComment)( 0, SfxUndoManager::TopLevel ); + } + } + break; + case SID_GETUNDOSTRINGS: + case SID_GETREDOSTRINGS: + { + size_t ( SfxUndoManager::*retrieveCount )( bool const ) const = + ( _nId == SID_GETUNDOSTRINGS ) ? &SfxUndoManager::GetUndoActionCount : &SfxUndoManager::GetRedoActionCount; + + OUString ( SfxUndoManager::*retrieveComment )( size_t, bool const ) const = + ( _nId == SID_GETUNDOSTRINGS ) ? &SfxUndoManager::GetUndoActionComment : &SfxUndoManager::GetRedoActionComment; + + SfxUndoManager& rUndoManager( getUndoManager() ); + size_t nCount(( rUndoManager.*retrieveCount )( SfxUndoManager::TopLevel )); + Sequence<OUString> aSeq(nCount); + auto aSeqRange = asNonConstRange(aSeq); + for (size_t n = 0; n < nCount; ++n) + aSeqRange[n] = (rUndoManager.*retrieveComment)( n, SfxUndoManager::TopLevel ); + aReturn.aValue <<= aSeq; + aReturn.bEnabled = true; + } + break; + case SID_OBJECT_RESIZING: + case SID_OBJECT_SMALLESTWIDTH: + case SID_OBJECT_SMALLESTHEIGHT: + case SID_OBJECT_GREATESTWIDTH: + case SID_OBJECT_GREATESTHEIGHT: + aReturn.bEnabled = isEditable() && getDesignView()->HasSelection(); + if ( aReturn.bEnabled ) + aReturn.bEnabled = m_nSelectionCount > 1; + break; + + case SID_DISTRIBUTE_HLEFT: + case SID_DISTRIBUTE_HCENTER: + case SID_DISTRIBUTE_HDISTANCE: + case SID_DISTRIBUTE_HRIGHT: + case SID_DISTRIBUTE_VTOP: + case SID_DISTRIBUTE_VCENTER: + case SID_DISTRIBUTE_VDISTANCE: + case SID_DISTRIBUTE_VBOTTOM: + aReturn.bEnabled = isEditable() && getDesignView()->HasSelection(); + if ( aReturn.bEnabled ) + { + OSectionView* pSectionView = getCurrentSectionView(); + aReturn.bEnabled = pSectionView && pSectionView->GetMarkedObjectCount() > 2; + } + break; + case SID_ARRANGEMENU: + case SID_FRAME_DOWN: + case SID_FRAME_UP: + case SID_FRAME_TO_TOP: + case SID_FRAME_TO_BOTTOM: + case SID_OBJECT_HEAVEN: + case SID_OBJECT_HELL: + aReturn.bEnabled = isEditable() && getDesignView()->HasSelection(); + if ( aReturn.bEnabled ) + { + OSectionView* pSectionView = getCurrentSectionView(); + aReturn.bEnabled = pSectionView && pSectionView->OnlyShapesMarked(); + if ( aReturn.bEnabled ) + { + if ( SID_OBJECT_HEAVEN == _nId ) + aReturn.bEnabled = pSectionView->GetLayerIdOfMarkedObjects() != RPT_LAYER_FRONT; + else if ( SID_OBJECT_HELL == _nId ) + aReturn.bEnabled = pSectionView->GetLayerIdOfMarkedObjects() != RPT_LAYER_BACK; + } + } + break; + + case SID_SECTION_SHRINK: + case SID_SECTION_SHRINK_TOP: + case SID_SECTION_SHRINK_BOTTOM: + { + sal_Int32 nCount = 0; + uno::Reference<report::XSection> xSection = getDesignView()->getCurrentSection(); + if ( xSection.is() ) + { + nCount = xSection->getCount(); + } + aReturn.bEnabled = isEditable() && nCount > 0; + } + break; + case SID_OBJECT_ALIGN: + case SID_OBJECT_ALIGN_LEFT: + case SID_OBJECT_ALIGN_CENTER: + case SID_OBJECT_ALIGN_RIGHT: + case SID_OBJECT_ALIGN_UP: + case SID_OBJECT_ALIGN_MIDDLE: + case SID_OBJECT_ALIGN_DOWN: + case SID_SECTION_ALIGN: + case SID_SECTION_ALIGN_LEFT: + case SID_SECTION_ALIGN_CENTER: + case SID_SECTION_ALIGN_RIGHT: + case SID_SECTION_ALIGN_UP: + case SID_SECTION_ALIGN_MIDDLE: + case SID_SECTION_ALIGN_DOWN: + aReturn.bEnabled = isEditable() && getDesignView()->HasSelection(); + break; + case SID_CUT: + aReturn.bEnabled = isEditable() && getDesignView()->HasSelection() && !getDesignView()->isHandleEvent(); + break; + case SID_COPY: + aReturn.bEnabled = getDesignView()->HasSelection() && !getDesignView()->isHandleEvent(); + break; + case SID_PASTE: + aReturn.bEnabled = isEditable() && !getDesignView()->isHandleEvent() && getDesignView()->IsPasteAllowed(); + break; + case SID_SELECTALL: + aReturn.bEnabled = !getDesignView()->isHandleEvent(); + break; + case SID_SELECTALL_IN_SECTION: + aReturn.bEnabled = !getDesignView()->isHandleEvent(); + if ( aReturn.bEnabled ) + aReturn.bEnabled = getCurrentSectionView() != nullptr; + break; + case SID_ESCAPE: + aReturn.bEnabled = getDesignView()->GetMode() == DlgEdMode::Insert; + break; + case SID_TERMINATE_INPLACEACTIVATION: + aReturn.bEnabled = true; + break; + case SID_SELECT_ALL_EDITS: + case SID_SELECT_ALL_LABELS: + aReturn.bEnabled = true; + break; + case SID_RPT_NEW_FUNCTION: + aReturn.bEnabled = isEditable(); + break; + case SID_COLLAPSE_SECTION: + case SID_EXPAND_SECTION: + case SID_NEXT_MARK: + case SID_PREV_MARK: + aReturn.bEnabled = isEditable() && !getDesignView()->isHandleEvent(); + break; + case SID_SELECT: + case SID_SELECT_REPORT: + aReturn.bEnabled = true; + break; + case SID_EXECUTE_REPORT: + aReturn.bEnabled = isConnected() && m_xReportDefinition.is(); + break; + case SID_DELETE: + aReturn.bEnabled = isEditable() && getDesignView()->HasSelection() && !getDesignView()->isHandleEvent(); + if ( aReturn.bEnabled ) + { + OSectionWindow* pSectionWindow = getDesignView()->getMarkedSection(); + if ( pSectionWindow ) + aReturn.bEnabled = !pSectionWindow->getReportSection().isUiActive(); + } + { + OUString sText = RptResId(RID_STR_DELETE); + aReturn.sTitle = sText; + } + break; + case SID_GRID_VISIBLE: + aReturn.bEnabled = isEditable(); + aReturn.bChecked = m_bGridVisible; + break; + case SID_GRID_USE: + aReturn.bEnabled = isEditable(); + aReturn.bChecked = m_bGridUse; + break; + case SID_HELPLINES_MOVE: + aReturn.bEnabled = isEditable(); + aReturn.bChecked = m_bHelplinesMove; + break; + case SID_RULER: + aReturn.bEnabled = isEditable(); + aReturn.bChecked = m_bShowRuler; + break; + case SID_OBJECT_SELECT: + aReturn.bEnabled = true; + aReturn.bChecked = getDesignView()->GetMode() == DlgEdMode::Select; + break; + case SID_INSERT_DIAGRAM: + aReturn.bEnabled = isEditable(); + aReturn.bInvisible = !m_bChartEnabled; + aReturn.bChecked = getDesignView()->GetInsertObj() == SdrObjKind::OLE2; + break; + case SID_FM_FIXEDTEXT: + aReturn.bEnabled = isEditable(); + aReturn.bChecked = getDesignView()->GetInsertObj() == SdrObjKind::ReportDesignFixedText; + break; + case SID_INSERT_HFIXEDLINE: + aReturn.bEnabled = isEditable(); + aReturn.bChecked = getDesignView()->GetInsertObj() == SdrObjKind::ReportDesignHorizontalFixedLine; + break; + case SID_INSERT_VFIXEDLINE: + aReturn.bEnabled = isEditable(); + aReturn.bChecked = getDesignView()->GetInsertObj() == SdrObjKind::ReportDesignVerticalFixedLine; + break; + case SID_FM_EDIT: + aReturn.bEnabled = isEditable(); + aReturn.bChecked = getDesignView()->GetInsertObj() == SdrObjKind::ReportDesignFormattedField; + break; + case SID_FM_IMAGECONTROL: + aReturn.bEnabled = isEditable(); + aReturn.bChecked = getDesignView()->GetInsertObj() == SdrObjKind::ReportDesignImageControl; + break; + case SID_DRAWTBX_CS_BASIC: + case SID_DRAWTBX_CS_BASIC1: + case SID_DRAWTBX_CS_BASIC2: + case SID_DRAWTBX_CS_BASIC3: + case SID_DRAWTBX_CS_BASIC4: + case SID_DRAWTBX_CS_BASIC5: + case SID_DRAWTBX_CS_BASIC6: + case SID_DRAWTBX_CS_BASIC7: + case SID_DRAWTBX_CS_BASIC8: + case SID_DRAWTBX_CS_BASIC9: + case SID_DRAWTBX_CS_BASIC10: + case SID_DRAWTBX_CS_BASIC11: + case SID_DRAWTBX_CS_BASIC12: + case SID_DRAWTBX_CS_BASIC13: + case SID_DRAWTBX_CS_BASIC14: + case SID_DRAWTBX_CS_BASIC15: + case SID_DRAWTBX_CS_BASIC16: + case SID_DRAWTBX_CS_BASIC17: + case SID_DRAWTBX_CS_BASIC18: + case SID_DRAWTBX_CS_BASIC19: + case SID_DRAWTBX_CS_BASIC20: + case SID_DRAWTBX_CS_BASIC21: + case SID_DRAWTBX_CS_BASIC22: + impl_fillCustomShapeState_nothrow("diamond",aReturn); + break; + case SID_DRAWTBX_CS_SYMBOL: + case SID_DRAWTBX_CS_SYMBOL1: + case SID_DRAWTBX_CS_SYMBOL2: + case SID_DRAWTBX_CS_SYMBOL3: + case SID_DRAWTBX_CS_SYMBOL4: + case SID_DRAWTBX_CS_SYMBOL5: + case SID_DRAWTBX_CS_SYMBOL6: + case SID_DRAWTBX_CS_SYMBOL7: + case SID_DRAWTBX_CS_SYMBOL8: + case SID_DRAWTBX_CS_SYMBOL9: + case SID_DRAWTBX_CS_SYMBOL10: + case SID_DRAWTBX_CS_SYMBOL11: + case SID_DRAWTBX_CS_SYMBOL12: + case SID_DRAWTBX_CS_SYMBOL13: + case SID_DRAWTBX_CS_SYMBOL14: + case SID_DRAWTBX_CS_SYMBOL15: + case SID_DRAWTBX_CS_SYMBOL16: + case SID_DRAWTBX_CS_SYMBOL17: + case SID_DRAWTBX_CS_SYMBOL18: + impl_fillCustomShapeState_nothrow("smiley",aReturn); + break; + case SID_DRAWTBX_CS_ARROW: + case SID_DRAWTBX_CS_ARROW1: + case SID_DRAWTBX_CS_ARROW2: + case SID_DRAWTBX_CS_ARROW3: + case SID_DRAWTBX_CS_ARROW4: + case SID_DRAWTBX_CS_ARROW5: + case SID_DRAWTBX_CS_ARROW6: + case SID_DRAWTBX_CS_ARROW7: + case SID_DRAWTBX_CS_ARROW8: + case SID_DRAWTBX_CS_ARROW9: + case SID_DRAWTBX_CS_ARROW10: + case SID_DRAWTBX_CS_ARROW11: + case SID_DRAWTBX_CS_ARROW12: + case SID_DRAWTBX_CS_ARROW13: + case SID_DRAWTBX_CS_ARROW14: + case SID_DRAWTBX_CS_ARROW15: + case SID_DRAWTBX_CS_ARROW16: + case SID_DRAWTBX_CS_ARROW17: + case SID_DRAWTBX_CS_ARROW18: + case SID_DRAWTBX_CS_ARROW19: + case SID_DRAWTBX_CS_ARROW20: + case SID_DRAWTBX_CS_ARROW21: + case SID_DRAWTBX_CS_ARROW22: + case SID_DRAWTBX_CS_ARROW23: + case SID_DRAWTBX_CS_ARROW24: + case SID_DRAWTBX_CS_ARROW25: + case SID_DRAWTBX_CS_ARROW26: + impl_fillCustomShapeState_nothrow("left-right-arrow",aReturn); + break; + case SID_DRAWTBX_CS_STAR: + case SID_DRAWTBX_CS_STAR1: + case SID_DRAWTBX_CS_STAR2: + case SID_DRAWTBX_CS_STAR3: + case SID_DRAWTBX_CS_STAR4: + case SID_DRAWTBX_CS_STAR5: + case SID_DRAWTBX_CS_STAR6: + case SID_DRAWTBX_CS_STAR7: + case SID_DRAWTBX_CS_STAR8: + case SID_DRAWTBX_CS_STAR9: + case SID_DRAWTBX_CS_STAR10: + case SID_DRAWTBX_CS_STAR11: + case SID_DRAWTBX_CS_STAR12: + impl_fillCustomShapeState_nothrow("star5",aReturn); + break; + case SID_DRAWTBX_CS_FLOWCHART: + case SID_DRAWTBX_CS_FLOWCHART1: + case SID_DRAWTBX_CS_FLOWCHART2: + case SID_DRAWTBX_CS_FLOWCHART3: + case SID_DRAWTBX_CS_FLOWCHART4: + case SID_DRAWTBX_CS_FLOWCHART5: + case SID_DRAWTBX_CS_FLOWCHART6: + case SID_DRAWTBX_CS_FLOWCHART7: + case SID_DRAWTBX_CS_FLOWCHART8: + case SID_DRAWTBX_CS_FLOWCHART9: + case SID_DRAWTBX_CS_FLOWCHART10: + case SID_DRAWTBX_CS_FLOWCHART11: + case SID_DRAWTBX_CS_FLOWCHART12: + case SID_DRAWTBX_CS_FLOWCHART13: + case SID_DRAWTBX_CS_FLOWCHART14: + case SID_DRAWTBX_CS_FLOWCHART15: + case SID_DRAWTBX_CS_FLOWCHART16: + case SID_DRAWTBX_CS_FLOWCHART17: + case SID_DRAWTBX_CS_FLOWCHART18: + case SID_DRAWTBX_CS_FLOWCHART19: + case SID_DRAWTBX_CS_FLOWCHART20: + case SID_DRAWTBX_CS_FLOWCHART21: + case SID_DRAWTBX_CS_FLOWCHART22: + case SID_DRAWTBX_CS_FLOWCHART23: + case SID_DRAWTBX_CS_FLOWCHART24: + case SID_DRAWTBX_CS_FLOWCHART25: + case SID_DRAWTBX_CS_FLOWCHART26: + case SID_DRAWTBX_CS_FLOWCHART27: + case SID_DRAWTBX_CS_FLOWCHART28: + impl_fillCustomShapeState_nothrow("flowchart-internal-storage",aReturn); + break; + case SID_DRAWTBX_CS_CALLOUT: + case SID_DRAWTBX_CS_CALLOUT1: + case SID_DRAWTBX_CS_CALLOUT2: + case SID_DRAWTBX_CS_CALLOUT3: + case SID_DRAWTBX_CS_CALLOUT4: + case SID_DRAWTBX_CS_CALLOUT5: + case SID_DRAWTBX_CS_CALLOUT6: + case SID_DRAWTBX_CS_CALLOUT7: + impl_fillCustomShapeState_nothrow("round-rectangular-callout",aReturn); + break; + case SID_RPT_SHOWREPORTEXPLORER: + aReturn.bEnabled = m_xReportDefinition.is(); + aReturn.bChecked = getDesignView() && getDesignView()->isReportExplorerVisible(); + break; + case SID_FM_ADD_FIELD: + aReturn.bEnabled = isConnected() && isEditable() && m_xReportDefinition.is() + && !m_xReportDefinition->getCommand().isEmpty(); + aReturn.bChecked = getDesignView() && getDesignView()->isAddFieldVisible(); + break; + case SID_SHOW_PROPERTYBROWSER: + aReturn.bEnabled = true; + aReturn.bChecked = m_bShowProperties; + break; + case SID_PROPERTYBROWSER_LAST_PAGE: + aReturn.bEnabled = true; + aReturn.aValue <<= m_sLastActivePage; + break; + case SID_SPLIT_POSITION: + aReturn.bEnabled = true; + aReturn.aValue <<= getSplitPos(); + break; + case SID_SAVEDOC: + case SID_SAVEASDOC: + case SID_SAVEACOPY: + aReturn.bEnabled = isConnected() && isEditable(); + break; + case SID_EDITDOC: + aReturn.bChecked = isEditable(); + break; + case SID_PAGEDIALOG: + aReturn.bEnabled = isEditable(); + break; + case SID_BACKGROUND_COLOR: + impl_fillState_nothrow(PROPERTY_CONTROLBACKGROUND,aReturn); + break; + case SID_ATTR_CHAR_COLOR_BACKGROUND: + aReturn.bEnabled = isEditable(); + { + uno::Reference<report::XSection> xSection = getDesignView()->getCurrentSection(); + if ( xSection.is() ) + try + { + aReturn.aValue <<= xSection->getBackColor(); + const uno::Reference< report::XReportControlModel> xControlModel(getDesignView()->getCurrentControlModel(),uno::UNO_QUERY); + aReturn.bEnabled = !xControlModel.is(); + } + catch(const beans::UnknownPropertyException&) + { + } + else + aReturn.bEnabled = false; + } + break; + case SID_SORTINGANDGROUPING: + aReturn.bEnabled = true; + aReturn.bChecked = m_xGroupsFloater && m_xGroupsFloater->getDialog()->get_visible(); + break; + case SID_ATTR_CHAR_WEIGHT: + case SID_ATTR_CHAR_POSTURE: + case SID_ATTR_CHAR_UNDERLINE: + impl_fillState_nothrow(PROPERTY_FONTDESCRIPTOR,aReturn); + if ( aReturn.bEnabled ) + { + awt::FontDescriptor aFontDescriptor; + aReturn.aValue >>= aFontDescriptor; + aReturn.aValue.clear(); + + switch(_nId) + { + case SID_ATTR_CHAR_WEIGHT: + aReturn.bChecked = awt::FontWeight::BOLD == aFontDescriptor.Weight; + break; + case SID_ATTR_CHAR_POSTURE: + aReturn.bChecked = awt::FontSlant_ITALIC == aFontDescriptor.Slant; + break; + case SID_ATTR_CHAR_UNDERLINE: + aReturn.bChecked = awt::FontUnderline::SINGLE == aFontDescriptor.Underline; + break; + default: + ; + } + } + break; + case SID_ATTR_CHAR_COLOR: + case SID_ATTR_CHAR_COLOR2: + impl_fillState_nothrow(PROPERTY_CHARCOLOR,aReturn); + break; + case SID_ATTR_CHAR_FONT: + impl_fillState_nothrow(PROPERTY_FONTDESCRIPTOR,aReturn); + break; + case SID_ATTR_CHAR_FONTHEIGHT: + impl_fillState_nothrow(PROPERTY_CHARHEIGHT,aReturn); + if ( aReturn.aValue.hasValue() ) + { + frame::status::FontHeight aFontHeight; + aReturn.aValue >>= aFontHeight.Height; + aReturn.aValue <<= aFontHeight; // another type is needed here, so + } + break; + case SID_ATTR_PARA_ADJUST_LEFT: + case SID_ATTR_PARA_ADJUST_CENTER: + case SID_ATTR_PARA_ADJUST_RIGHT: + case SID_ATTR_PARA_ADJUST_BLOCK: + impl_fillState_nothrow(PROPERTY_PARAADJUST,aReturn); + if ( aReturn.bEnabled ) + { + ::sal_Int16 nParaAdjust = 0; + if ( aReturn.aValue >>= nParaAdjust ) + { + switch(static_cast<style::ParagraphAdjust>(nParaAdjust)) + { + case style::ParagraphAdjust_LEFT: + aReturn.bChecked = _nId == SID_ATTR_PARA_ADJUST_LEFT; + break; + case style::ParagraphAdjust_RIGHT: + aReturn.bChecked = _nId == SID_ATTR_PARA_ADJUST_RIGHT; + break; + case style::ParagraphAdjust_BLOCK: + case style::ParagraphAdjust_STRETCH: + aReturn.bChecked = _nId == SID_ATTR_PARA_ADJUST_BLOCK; + break; + case style::ParagraphAdjust_CENTER: + aReturn.bChecked = _nId == SID_ATTR_PARA_ADJUST_CENTER; + break; + default: break; + } + } + aReturn.aValue.clear(); + } + break; + + case SID_INSERT_GRAPHIC: + aReturn.bEnabled = m_xReportDefinition.is() && isEditable() && getDesignView()->getCurrentSection().is(); + break; + case SID_CHAR_DLG: + case SID_SETCONTROLDEFAULTS: + aReturn.bEnabled = m_xReportDefinition.is() && isEditable(); + if ( aReturn.bEnabled ) + { + ::std::vector< uno::Reference< uno::XInterface > > aSelection; + getDesignView()->fillControlModelSelection(aSelection); + aReturn.bEnabled = !aSelection.empty() + && std::all_of(aSelection.begin(), aSelection.end(), [](const uno::Reference<uno::XInterface>& rxInterface) { + return !uno::Reference<report::XFixedLine>(rxInterface, uno::UNO_QUERY).is() + && !uno::Reference<report::XImageControl>(rxInterface, uno::UNO_QUERY).is() + && uno::Reference<report::XReportControlFormat>(rxInterface, uno::UNO_QUERY).is(); }); + } + break; + case SID_CONDITIONALFORMATTING: + { + const uno::Reference< report::XFormattedField> xFormattedField(getDesignView()->getCurrentControlModel(),uno::UNO_QUERY); + aReturn.bEnabled = xFormattedField.is(); + } + break; + case SID_INSERT_FLD_PGNUMBER: + case SID_DATETIME: + aReturn.bEnabled = m_xReportDefinition.is() && isEditable() && getDesignView()->getCurrentSection().is(); + break; + case SID_EXPORTDOC: + case SID_EXPORTDOCASPDF: + aReturn.bEnabled = m_xReportDefinition.is(); + break; + case SID_PRINTPREVIEW: + aReturn.bEnabled = false; + break; + case SID_ATTR_ZOOM: + aReturn.bEnabled = true; + { + SvxZoomItem aZoom(m_eZoomType,m_nZoomValue); + aZoom.SetValueSet(SvxZoomEnableFlags::N50|SvxZoomEnableFlags::N75|SvxZoomEnableFlags::N100|SvxZoomEnableFlags::N200); + aZoom.QueryValue(aReturn.aValue); + } + break; + case SID_ATTR_ZOOMSLIDER: + aReturn.bEnabled = true; + { + SvxZoomSliderItem aZoomSlider(m_nZoomValue,20,400); + aZoomSlider.AddSnappingPoint(50); + aZoomSlider.AddSnappingPoint(75); + aZoomSlider.AddSnappingPoint(100); + aZoomSlider.AddSnappingPoint(200); + aZoomSlider.QueryValue(aReturn.aValue); + } + break; + default: + aReturn = OReportController_BASE::GetState(_nId); + } + return aReturn; +} + + +namespace +{ + /** extracts a background color from a dispatched SID_BACKGROUND_COLOR call + + The dispatch might originate from either the toolbar, or the conditional + formatting dialog. In both cases, argument formats are different. + */ + util::Color lcl_extractBackgroundColor( const Sequence< PropertyValue >& _rDispatchArgs ) + { + util::Color aColor( COL_TRANSPARENT ); + if ( _rDispatchArgs.getLength() == 1 ) + { + OSL_VERIFY( _rDispatchArgs[0].Value >>= aColor ); + } + else + { + SequenceAsHashMap aMap( _rDispatchArgs ); + aColor = aMap.getUnpackedValueOrDefault( PROPERTY_FONTCOLOR, aColor ); + } + return aColor; + } +} + + +void OReportController::Execute(sal_uInt16 _nId, const Sequence< PropertyValue >& aArgs) +{ + SolarMutexGuard aSolarGuard; + ::osl::MutexGuard aGuard( getMutex() ); + + bool bForceBroadcast = false; + switch(_nId) + { + case SID_RPT_TEXTDOCUMENT: + if ( m_xReportDefinition.is() ) + m_xReportDefinition->setMimeType( MIMETYPE_OASIS_OPENDOCUMENT_TEXT_ASCII ); + break; + case SID_RPT_SPREADSHEET: + if (m_xReportDefinition.is() ) + m_xReportDefinition->setMimeType( MIMETYPE_OASIS_OPENDOCUMENT_SPREADSHEET_ASCII ); + break; + case SID_REPORTHEADER_WITHOUT_UNDO: + case SID_REPORTFOOTER_WITHOUT_UNDO: + case SID_REPORTHEADERFOOTER: + switchReportSection(_nId); + break; + case SID_PAGEHEADER_WITHOUT_UNDO: + case SID_PAGEFOOTER_WITHOUT_UNDO: + case SID_PAGEHEADERFOOTER: + switchPageSection(_nId); + break; + case SID_GROUP_APPEND: + case SID_GROUP_REMOVE: + modifyGroup(_nId == SID_GROUP_APPEND,aArgs); + break; + case SID_GROUPHEADER_WITHOUT_UNDO: + case SID_GROUPHEADER: + createGroupSection(SID_GROUPHEADER == _nId,true,aArgs); + break; + case SID_GROUPFOOTER_WITHOUT_UNDO: + case SID_GROUPFOOTER: + createGroupSection(SID_GROUPFOOTER == _nId,false,aArgs); + break; + case SID_ADD_CONTROL_PAIR: + addPairControls(aArgs); + break; + case SID_REDO: + case SID_UNDO: + { + const OXUndoEnvironment::OUndoMode aLock( m_aReportModel->GetUndoEnv() ); + bool ( SfxUndoManager::*doXDo )() = + ( _nId == SID_UNDO ) ? &SfxUndoManager::Undo : &SfxUndoManager::Redo; + SfxUndoManager& rUndoManager( getUndoManager() ); + + sal_Int16 nCount(1); + if (aArgs.hasElements() && aArgs[0].Name != "KeyModifier") + aArgs[0].Value >>= nCount; + while (nCount--) + (rUndoManager.*doXDo)(); + InvalidateAll(); + if (m_xGroupsFloater && m_xGroupsFloater->getDialog()->get_visible()) + m_xGroupsFloater->UpdateData(); + } + break; + case SID_CUT: + executeMethodWithUndo(RID_STR_UNDO_REMOVE_SELECTION,::std::mem_fn(&ODesignView::Cut)); + break; + case SID_COPY: + getDesignView()->Copy(); + break; + case SID_PASTE: + executeMethodWithUndo(RID_STR_UNDO_PASTE,::std::mem_fn(&ODesignView::Paste)); + break; + + case SID_FRAME_TO_TOP: + case SID_FRAME_DOWN: + case SID_FRAME_UP: + case SID_FRAME_TO_BOTTOM: + case SID_OBJECT_HEAVEN: + case SID_OBJECT_HELL: + changeZOrder(_nId); + break; + case SID_DISTRIBUTE_HLEFT: + case SID_DISTRIBUTE_HCENTER: + case SID_DISTRIBUTE_HDISTANCE: + case SID_DISTRIBUTE_HRIGHT: + case SID_DISTRIBUTE_VTOP: + case SID_DISTRIBUTE_VCENTER: + case SID_DISTRIBUTE_VDISTANCE: + case SID_DISTRIBUTE_VBOTTOM: + { + OSectionView* pSectionView = getCurrentSectionView(); + if ( pSectionView ) + pSectionView->DistributeMarkedObjects(_nId); + } + break; + case SID_OBJECT_SMALLESTWIDTH: + alignControlsWithUndo(RID_STR_UNDO_ALIGNMENT,ControlModification::WIDTH_SMALLEST); + break; + case SID_OBJECT_SMALLESTHEIGHT: + alignControlsWithUndo(RID_STR_UNDO_ALIGNMENT,ControlModification::HEIGHT_SMALLEST); + break; + case SID_OBJECT_GREATESTWIDTH: + alignControlsWithUndo(RID_STR_UNDO_ALIGNMENT,ControlModification::WIDTH_GREATEST); + break; + case SID_OBJECT_GREATESTHEIGHT: + alignControlsWithUndo(RID_STR_UNDO_ALIGNMENT,ControlModification::HEIGHT_GREATEST); + break; + case SID_SECTION_ALIGN_LEFT: + case SID_OBJECT_ALIGN_LEFT: + alignControlsWithUndo(RID_STR_UNDO_ALIGNMENT,ControlModification::LEFT,SID_SECTION_ALIGN_LEFT == _nId); + break; + case SID_SECTION_ALIGN_CENTER: + case SID_OBJECT_ALIGN_CENTER: + alignControlsWithUndo(RID_STR_UNDO_ALIGNMENT,ControlModification::CENTER_HORIZONTAL,SID_SECTION_ALIGN_CENTER == _nId); + break; + case SID_SECTION_ALIGN_RIGHT: + case SID_OBJECT_ALIGN_RIGHT: + alignControlsWithUndo(RID_STR_UNDO_ALIGNMENT,ControlModification::RIGHT,SID_SECTION_ALIGN_RIGHT == _nId); + break; + case SID_SECTION_ALIGN_UP: + case SID_OBJECT_ALIGN_UP: + alignControlsWithUndo(RID_STR_UNDO_ALIGNMENT,ControlModification::TOP,SID_SECTION_ALIGN_UP == _nId); + break; + case SID_SECTION_ALIGN_MIDDLE: + case SID_OBJECT_ALIGN_MIDDLE: + alignControlsWithUndo(RID_STR_UNDO_ALIGNMENT,ControlModification::CENTER_VERTICAL,SID_SECTION_ALIGN_MIDDLE == _nId); + break; + case SID_SECTION_ALIGN_DOWN: + case SID_OBJECT_ALIGN_DOWN: + alignControlsWithUndo(RID_STR_UNDO_ALIGNMENT,ControlModification::BOTTOM,SID_SECTION_ALIGN_DOWN == _nId); + break; + + case SID_SECTION_SHRINK_BOTTOM: + case SID_SECTION_SHRINK_TOP: + case SID_SECTION_SHRINK: + { + uno::Reference<report::XSection> xSection = getDesignView()->getCurrentSection(); + shrinkSection(RID_STR_UNDO_SHRINK, xSection, _nId); + } + break; + + case SID_SELECTALL: + getDesignView()->SelectAll(SdrObjKind::NONE); + break; + case SID_SELECTALL_IN_SECTION: + { + OSectionView* pSectionView = getCurrentSectionView(); + if ( pSectionView ) + pSectionView->MarkAll(); + } + break; + case SID_ESCAPE: + getDesignView()->SetMode(DlgEdMode::Select); + InvalidateFeature( SID_OBJECT_SELECT ); + break; + case SID_SELECT_ALL_EDITS: + getDesignView()->SelectAll(SdrObjKind::ReportDesignFormattedField); + break; + case SID_SELECT_ALL_LABELS: + getDesignView()->SelectAll(SdrObjKind::ReportDesignFixedText); + break; + case SID_TERMINATE_INPLACEACTIVATION: + { + OSectionWindow* pSection = getDesignView()->getMarkedSection(); + if ( pSection ) + pSection->getReportSection().deactivateOle(); + } + break; + case SID_SELECT: + if ( aArgs.getLength() == 1 ) + select(aArgs[0].Value); + break; + case SID_SELECT_REPORT: + select(uno::Any(m_xReportDefinition)); + break; + case SID_EXECUTE_REPORT: + getView()->PostUserEvent(LINK(this, OReportController,OnExecuteReport)); + break; + case SID_RPT_NEW_FUNCTION: + createNewFunction(aArgs[0].Value); + break; + case SID_COLLAPSE_SECTION: + collapseSection(true); + break; + case SID_EXPAND_SECTION: + collapseSection(false); + break; + case SID_NEXT_MARK: + markSection(true); + break; + case SID_PREV_MARK: + markSection(false); + break; + case SID_DELETE: + if ( aArgs.getLength() == 1 ) + { + uno::Reference< report::XFunction> xFunction; + aArgs[0].Value >>= xFunction; + if ( xFunction.is() ) + { + uno::Reference< report::XFunctions> xFunctions(xFunction->getParent(),uno::UNO_QUERY_THROW); + sal_Int32 nIndex = getPositionInIndexAccess(xFunctions, xFunction); + const OUString sUndoAction = RptResId(RID_STR_UNDO_REMOVE_FUNCTION); + UndoContext aUndoContext( getUndoManager(), sUndoAction ); + xFunctions->removeByIndex(nIndex); + select(uno::Any(xFunctions->getParent())); + InvalidateFeature( SID_UNDO ); + } + } + else + executeMethodWithUndo(RID_STR_UNDO_REMOVE_SELECTION,::std::mem_fn(&ODesignView::Delete)); + break; + case SID_GRID_USE: + m_bGridUse = !m_bGridUse; + getDesignView()->setGridSnap(m_bGridUse); + break; + case SID_HELPLINES_MOVE: + m_bHelplinesMove = !m_bHelplinesMove; + getDesignView()->setDragStripes(m_bHelplinesMove); + break; + case SID_GRID_VISIBLE: + m_bGridVisible = !m_bGridVisible; + getDesignView()->toggleGrid(m_bGridVisible); + break; + case SID_RULER: + m_bShowRuler = !m_bShowRuler; + getDesignView()->showRuler(m_bShowRuler); + break; + case SID_OBJECT_SELECT: + getDesignView()->SetMode(DlgEdMode::Select); + InvalidateAll(); + break; + case SID_INSERT_DIAGRAM: + getDesignView()->SetMode( DlgEdMode::Insert ); + getDesignView()->SetInsertObj( SdrObjKind::OLE2); + createDefaultControl(aArgs); + InvalidateAll(); + break; + case SID_FM_FIXEDTEXT: + getDesignView()->SetMode( DlgEdMode::Insert ); + getDesignView()->SetInsertObj( SdrObjKind::ReportDesignFixedText ); + createDefaultControl(aArgs); + InvalidateAll(); + break; + case SID_INSERT_HFIXEDLINE: + getDesignView()->SetMode( DlgEdMode::Insert ); + getDesignView()->SetInsertObj( SdrObjKind::ReportDesignHorizontalFixedLine ); + createDefaultControl(aArgs); + InvalidateAll(); + break; + case SID_INSERT_VFIXEDLINE: + getDesignView()->SetMode( DlgEdMode::Insert ); + getDesignView()->SetInsertObj( SdrObjKind::ReportDesignVerticalFixedLine ); + createDefaultControl(aArgs); + InvalidateAll(); + break; + case SID_FM_EDIT: + getDesignView()->SetMode( DlgEdMode::Insert ); + getDesignView()->SetInsertObj( SdrObjKind::ReportDesignFormattedField ); + createDefaultControl(aArgs); + InvalidateAll(); + break; + case SID_FM_IMAGECONTROL: + getDesignView()->SetMode( DlgEdMode::Insert ); + getDesignView()->SetInsertObj( SdrObjKind::ReportDesignImageControl ); + createDefaultControl(aArgs); + InvalidateAll(); + break; + case SID_DRAWTBX_CS_BASIC: + case SID_DRAWTBX_CS_BASIC1: + case SID_DRAWTBX_CS_BASIC2: + case SID_DRAWTBX_CS_BASIC3: + case SID_DRAWTBX_CS_BASIC4: + case SID_DRAWTBX_CS_BASIC5: + case SID_DRAWTBX_CS_BASIC6: + case SID_DRAWTBX_CS_BASIC7: + case SID_DRAWTBX_CS_BASIC8: + case SID_DRAWTBX_CS_BASIC9: + case SID_DRAWTBX_CS_BASIC10: + case SID_DRAWTBX_CS_BASIC11: + case SID_DRAWTBX_CS_BASIC12: + case SID_DRAWTBX_CS_BASIC13: + case SID_DRAWTBX_CS_BASIC14: + case SID_DRAWTBX_CS_BASIC15: + case SID_DRAWTBX_CS_BASIC16: + case SID_DRAWTBX_CS_BASIC17: + case SID_DRAWTBX_CS_BASIC18: + case SID_DRAWTBX_CS_BASIC19: + case SID_DRAWTBX_CS_BASIC20: + case SID_DRAWTBX_CS_BASIC21: + case SID_DRAWTBX_CS_BASIC22: + case SID_DRAWTBX_CS_SYMBOL1: + case SID_DRAWTBX_CS_SYMBOL2: + case SID_DRAWTBX_CS_SYMBOL3: + case SID_DRAWTBX_CS_SYMBOL4: + case SID_DRAWTBX_CS_SYMBOL5: + case SID_DRAWTBX_CS_SYMBOL6: + case SID_DRAWTBX_CS_SYMBOL7: + case SID_DRAWTBX_CS_SYMBOL8: + case SID_DRAWTBX_CS_SYMBOL9: + case SID_DRAWTBX_CS_SYMBOL10: + case SID_DRAWTBX_CS_SYMBOL11: + case SID_DRAWTBX_CS_SYMBOL12: + case SID_DRAWTBX_CS_SYMBOL13: + case SID_DRAWTBX_CS_SYMBOL14: + case SID_DRAWTBX_CS_SYMBOL15: + case SID_DRAWTBX_CS_SYMBOL16: + case SID_DRAWTBX_CS_SYMBOL17: + case SID_DRAWTBX_CS_SYMBOL18: + case SID_DRAWTBX_CS_ARROW1: + case SID_DRAWTBX_CS_ARROW2: + case SID_DRAWTBX_CS_ARROW3: + case SID_DRAWTBX_CS_ARROW4: + case SID_DRAWTBX_CS_ARROW5: + case SID_DRAWTBX_CS_ARROW6: + case SID_DRAWTBX_CS_ARROW7: + case SID_DRAWTBX_CS_ARROW8: + case SID_DRAWTBX_CS_ARROW9: + case SID_DRAWTBX_CS_ARROW10: + case SID_DRAWTBX_CS_ARROW11: + case SID_DRAWTBX_CS_ARROW12: + case SID_DRAWTBX_CS_ARROW13: + case SID_DRAWTBX_CS_ARROW14: + case SID_DRAWTBX_CS_ARROW15: + case SID_DRAWTBX_CS_ARROW16: + case SID_DRAWTBX_CS_ARROW17: + case SID_DRAWTBX_CS_ARROW18: + case SID_DRAWTBX_CS_ARROW19: + case SID_DRAWTBX_CS_ARROW20: + case SID_DRAWTBX_CS_ARROW21: + case SID_DRAWTBX_CS_ARROW22: + case SID_DRAWTBX_CS_ARROW23: + case SID_DRAWTBX_CS_ARROW24: + case SID_DRAWTBX_CS_ARROW25: + case SID_DRAWTBX_CS_ARROW26: + case SID_DRAWTBX_CS_STAR1: + case SID_DRAWTBX_CS_STAR2: + case SID_DRAWTBX_CS_STAR3: + case SID_DRAWTBX_CS_STAR4: + case SID_DRAWTBX_CS_STAR5: + case SID_DRAWTBX_CS_STAR6: + case SID_DRAWTBX_CS_STAR7: + case SID_DRAWTBX_CS_STAR8: + case SID_DRAWTBX_CS_STAR9: + case SID_DRAWTBX_CS_STAR10: + case SID_DRAWTBX_CS_STAR11: + case SID_DRAWTBX_CS_STAR12: + case SID_DRAWTBX_CS_FLOWCHART1: + case SID_DRAWTBX_CS_FLOWCHART2: + case SID_DRAWTBX_CS_FLOWCHART3: + case SID_DRAWTBX_CS_FLOWCHART4: + case SID_DRAWTBX_CS_FLOWCHART5: + case SID_DRAWTBX_CS_FLOWCHART6: + case SID_DRAWTBX_CS_FLOWCHART7: + case SID_DRAWTBX_CS_FLOWCHART8: + case SID_DRAWTBX_CS_FLOWCHART9: + case SID_DRAWTBX_CS_FLOWCHART10: + case SID_DRAWTBX_CS_FLOWCHART11: + case SID_DRAWTBX_CS_FLOWCHART12: + case SID_DRAWTBX_CS_FLOWCHART13: + case SID_DRAWTBX_CS_FLOWCHART14: + case SID_DRAWTBX_CS_FLOWCHART15: + case SID_DRAWTBX_CS_FLOWCHART16: + case SID_DRAWTBX_CS_FLOWCHART17: + case SID_DRAWTBX_CS_FLOWCHART18: + case SID_DRAWTBX_CS_FLOWCHART19: + case SID_DRAWTBX_CS_FLOWCHART20: + case SID_DRAWTBX_CS_FLOWCHART21: + case SID_DRAWTBX_CS_FLOWCHART22: + case SID_DRAWTBX_CS_FLOWCHART23: + case SID_DRAWTBX_CS_FLOWCHART24: + case SID_DRAWTBX_CS_FLOWCHART25: + case SID_DRAWTBX_CS_FLOWCHART26: + case SID_DRAWTBX_CS_FLOWCHART27: + case SID_DRAWTBX_CS_FLOWCHART28: + case SID_DRAWTBX_CS_CALLOUT1: + case SID_DRAWTBX_CS_CALLOUT2: + case SID_DRAWTBX_CS_CALLOUT3: + case SID_DRAWTBX_CS_CALLOUT4: + case SID_DRAWTBX_CS_CALLOUT5: + case SID_DRAWTBX_CS_CALLOUT6: + case SID_DRAWTBX_CS_CALLOUT7: + case SID_DRAWTBX_CS_SYMBOL: + case SID_DRAWTBX_CS_ARROW: + case SID_DRAWTBX_CS_FLOWCHART: + case SID_DRAWTBX_CS_CALLOUT: + case SID_DRAWTBX_CS_STAR: + getDesignView()->SetMode( DlgEdMode::Insert ); + { + URL aUrl = getURLForId(_nId); + sal_Int32 nIndex = 1; + std::u16string_view sType = o3tl::getToken(aUrl.Complete, 0,'.',nIndex); + if ( nIndex == -1 || sType.empty() ) + { + switch(_nId) + { + case SID_DRAWTBX_CS_SYMBOL: + sType = u"smiley"; + break; + case SID_DRAWTBX_CS_ARROW: + sType = u"left-right-arrow"; + break; + case SID_DRAWTBX_CS_FLOWCHART: + sType = u"flowchart-internal-storage"; + break; + case SID_DRAWTBX_CS_CALLOUT: + sType = u"round-rectangular-callout"; + break; + case SID_DRAWTBX_CS_STAR: + sType = u"star5"; + break; + default: + sType = u"diamond"; + } + } + else + sType = o3tl::getToken(aUrl.Complete, 0,'.',nIndex); + + getDesignView()->SetInsertObj( SdrObjKind::CustomShape, OUString(sType)); + createDefaultControl(aArgs); + } + InvalidateAll(); + break; + case SID_RPT_SHOWREPORTEXPLORER: + if ( isUiVisible() ) + getDesignView()->toggleReportExplorer(); + break; + case SID_FM_ADD_FIELD: + if ( isUiVisible() ) + getDesignView()->toggleAddField(); + break; + case SID_SHOW_PROPERTYBROWSER: + if ( m_bShowProperties ) + m_sLastActivePage = getDesignView()->getCurrentPage(); + else + getDesignView()->setCurrentPage(m_sLastActivePage); + + if ( isUiVisible() ) + { + m_bShowProperties = !m_bShowProperties; + if ( aArgs.getLength() == 1 ) + aArgs[0].Value >>= m_bShowProperties; + + getDesignView()->togglePropertyBrowser(m_bShowProperties); + } + break; + case SID_PROPERTYBROWSER_LAST_PAGE: // nothing to do + m_sLastActivePage = getDesignView()->getCurrentPage(); + break; + case SID_SPLIT_POSITION: + getDesignView()->Resize(); + break; + case SID_PAGEDIALOG: + case SID_ATTR_CHAR_COLOR_BACKGROUND: + { + uno::Reference<report::XSection> xSection; + if (aArgs.getLength() == 1 ) + aArgs[0].Value >>= xSection; + else if (_nId == SID_ATTR_CHAR_COLOR_BACKGROUND) + xSection.set(getDesignView()->getMarkedSection()->getReportSection().getSection()); + openPageDialog(xSection); + bForceBroadcast = true; + } + break; + case SID_SORTINGANDGROUPING: + openSortingAndGroupingDialog(); + break; + case SID_BACKGROUND_COLOR: + { + const util::Color aColor( lcl_extractBackgroundColor( aArgs ) ); + if ( !impl_setPropertyAtControls_throw(RID_STR_UNDO_CHANGEFONT,PROPERTY_CONTROLBACKGROUND,uno::Any(aColor),aArgs) ) + { + uno::Reference< report::XSection > xSection = getDesignView()->getCurrentSection(); + if ( xSection.is() ) + { + xSection->setBackColor( aColor ); + } + } + bForceBroadcast = true; + } + break; + case SID_ATTR_CHAR_WEIGHT: + case SID_ATTR_CHAR_POSTURE: + case SID_ATTR_CHAR_UNDERLINE: + { + uno::Reference< awt::XWindow> xWindow; + ::std::vector< uno::Reference< uno::XInterface > > aControlsFormats; + lcl_getReportControlFormat( aArgs, getDesignView(), xWindow, aControlsFormats ); + + const OUString sUndoAction(RptResId(RID_STR_UNDO_CHANGEFONT)); + UndoContext aUndoContext( getUndoManager(), sUndoAction ); + + for (const auto& rxControlFormat : aControlsFormats) + { + uno::Reference< report::XReportControlFormat> xReportControlFormat(rxControlFormat,uno::UNO_QUERY); + lcl_setFontWPU_nothrow(xReportControlFormat,_nId); + } + } + break; + case SID_ATTR_CHAR_COLOR: + case SID_ATTR_CHAR_COLOR2: + case SID_ATTR_CHAR_COLOR_EXT: + { + const SequenceAsHashMap aMap(aArgs); + const util::Color aColor = aMap.getUnpackedValueOrDefault(PROPERTY_FONTCOLOR,util::Color()); + impl_setPropertyAtControls_throw(RID_STR_UNDO_CHANGEFONT,PROPERTY_CHARCOLOR,uno::Any(aColor),aArgs); + bForceBroadcast = true; + } + break; + case SID_ATTR_CHAR_FONT: + if ( aArgs.getLength() == 1 ) + { + awt::FontDescriptor aFont; + if ( aArgs[0].Value >>= aFont ) + { + impl_setPropertyAtControls_throw(RID_STR_UNDO_CHANGEFONT,PROPERTY_CHARFONTNAME,uno::Any(aFont.Name),aArgs); + } + } + break; + case SID_ATTR_CHAR_FONTHEIGHT: + if ( aArgs.getLength() == 1 ) + { + float fSelVal = 0.0; + if ( aArgs[0].Value >>= fSelVal ) + impl_setPropertyAtControls_throw(RID_STR_UNDO_CHANGEFONT,PROPERTY_CHARHEIGHT,aArgs[0].Value,aArgs); + } + break; + case SID_ATTR_PARA_ADJUST_LEFT: + case SID_ATTR_PARA_ADJUST_CENTER: + case SID_ATTR_PARA_ADJUST_RIGHT: + case SID_ATTR_PARA_ADJUST_BLOCK: + { + style::ParagraphAdjust eParagraphAdjust = style::ParagraphAdjust_LEFT; + switch(_nId) + { + case SID_ATTR_PARA_ADJUST_LEFT: + eParagraphAdjust = style::ParagraphAdjust_LEFT; + break; + case SID_ATTR_PARA_ADJUST_CENTER: + eParagraphAdjust = style::ParagraphAdjust_CENTER; + break; + case SID_ATTR_PARA_ADJUST_RIGHT: + eParagraphAdjust = style::ParagraphAdjust_RIGHT; + break; + case SID_ATTR_PARA_ADJUST_BLOCK: + eParagraphAdjust = style::ParagraphAdjust_BLOCK; + break; + } + impl_setPropertyAtControls_throw(RID_STR_UNDO_ALIGNMENT,PROPERTY_PARAADJUST,uno::Any(static_cast<sal_Int16>(eParagraphAdjust)),aArgs); + + InvalidateFeature(SID_ATTR_PARA_ADJUST_LEFT); + InvalidateFeature(SID_ATTR_PARA_ADJUST_CENTER); + InvalidateFeature(SID_ATTR_PARA_ADJUST_RIGHT); + InvalidateFeature(SID_ATTR_PARA_ADJUST_BLOCK); + } + break; + case SID_CHAR_DLG: + { + uno::Sequence< beans::NamedValue > aSettings; + uno::Reference< awt::XWindow> xWindow; + ::std::vector< uno::Reference< uno::XInterface > > aControlsFormats; + lcl_getReportControlFormat( aArgs, getDesignView(), xWindow, aControlsFormats ); + + if ( !aControlsFormats.empty() ) + { + const OUString sUndoAction( RptResId( RID_STR_UNDO_CHANGEFONT ) ); + UndoContext aUndoContext( getUndoManager(), sUndoAction ); + + for (const auto& rxControlFormat : aControlsFormats) + { + uno::Reference< report::XReportControlFormat > xFormat( rxControlFormat, uno::UNO_QUERY ); + if ( !xFormat.is() ) + continue; + + if ( !aSettings.hasElements() ) + { + ::rptui::openCharDialog( xFormat, xWindow, aSettings ); + if ( !aSettings.hasElements() ) + break; + } + + applyCharacterSettings( xFormat, aSettings ); + } + + InvalidateAll(); + } + } + break; + case SID_INSERT_GRAPHIC: + insertGraphic(); + break; + case SID_SETCONTROLDEFAULTS: + break; + case SID_CONDITIONALFORMATTING: + { + uno::Reference< report::XFormattedField> xFormattedField(getDesignView()->getCurrentControlModel(),uno::UNO_QUERY); + if ( xFormattedField.is() ) + { + ConditionalFormattingDialog aDlg(getFrameWeld(), xFormattedField, *this); + aDlg.run(); + } + } + break; + case SID_DATETIME: + if ( m_xReportDefinition.is() ) + { + if ( !aArgs.hasElements() ) + { + ODateTimeDialog aDlg(getFrameWeld(), getDesignView()->getCurrentSection(), this); + aDlg.run(); + } + else + createDateTime(aArgs); + } + break; + case SID_INSERT_FLD_PGNUMBER: + if ( m_xReportDefinition.is() ) + { + if ( !aArgs.hasElements() ) + { + OPageNumberDialog aDlg(getFrameWeld(), m_xReportDefinition, this); + aDlg.run(); + } + else + createPageNumber(aArgs); + } + break; + case SID_EXPORTDOC: + case SID_EXPORTDOCASPDF: + case SID_PRINTPREVIEW: + break; + case SID_EDITDOC: + if(isEditable()) + { // the state should be changed to not editable + setModified(false); // and we are not modified yet + } + setEditable(!isEditable()); + InvalidateAll(); + return; + case SID_GROUP: + break; + case SID_ATTR_ZOOM: + if ( !aArgs.hasElements() ) + { + openZoomDialog(); + } + else if ( aArgs.getLength() == 1 && aArgs[0].Name == "Zoom" ) + { + SvxZoomItem aZoomItem; + aZoomItem.PutValue(aArgs[0].Value, 0); + m_nZoomValue = aZoomItem.GetValue(); + m_eZoomType = aZoomItem.GetType(); + impl_zoom_nothrow(); + } + break; + case SID_ATTR_ZOOMSLIDER: + if ( aArgs.getLength() == 1 && aArgs[0].Name == "ZoomSlider" ) + { + SvxZoomSliderItem aZoomSlider; + aZoomSlider.PutValue(aArgs[0].Value, 0); + m_nZoomValue = aZoomSlider.GetValue(); + m_eZoomType = SvxZoomType::PERCENT; + impl_zoom_nothrow(); + } + break; + default: + OReportController_BASE::Execute(_nId,aArgs); + } + InvalidateFeature(_nId,Reference< XStatusListener >(),bForceBroadcast); +} + +void OReportController::impl_initialize( ) +{ + OReportController_BASE::impl_initialize(); + + const ::comphelper::NamedValueCollection& rArguments( getInitParams() ); + + rArguments.get_ensureType( PROPERTY_REPORTNAME, m_sName ); + if ( m_sName.isEmpty() ) + rArguments.get_ensureType( "DocumentTitle", m_sName ); + + try + { + if ( m_xReportDefinition.is() ) + { + getView()->initialize(); // show the windows and fill with our information + + m_aReportModel = reportdesign::OReportDefinition::getSdrModel(m_xReportDefinition); + if ( !m_aReportModel ) + throw RuntimeException(); + m_aReportModel->attachController( *this ); + + clearUndoManager(); + UndoSuppressor aSuppressUndo( getUndoManager() ); + + setMode(::comphelper::NamedValueCollection::getOrDefault(getModel()->getArgs(), u"Mode", OUString("normal"))); + + listen(true); + setEditable( !m_aReportModel->IsReadOnly() ); + m_xFormatter.set(util::NumberFormatter::create(m_xContext), UNO_QUERY_THROW); + m_xFormatter->attachNumberFormatsSupplier(Reference< XNumberFormatsSupplier>(m_xReportDefinition,uno::UNO_QUERY)); + + utl::MediaDescriptor aDescriptor( m_xReportDefinition->getArgs() ); + OUString sHierarchicalDocumentName = aDescriptor.getUnpackedValueOrDefault("HierarchicalDocumentName",OUString()); + + if ( sHierarchicalDocumentName.isEmpty() && getConnection().is() ) + { + uno::Reference<sdbcx::XTablesSupplier> xTablesSup(getConnection(),uno::UNO_QUERY_THROW); + uno::Reference<container::XNameAccess> xTables = xTablesSup->getTables(); + const uno::Sequence< OUString > aNames( xTables->getElementNames() ); + + if ( aNames.hasElements() ) + { + m_xReportDefinition->setCommand(aNames[0]); + m_xReportDefinition->setCommandType(sdb::CommandType::TABLE); + } + } + + m_aVisualAreaSize = m_xReportDefinition->getVisualAreaSize(0); + + } + + // check if chart is supported by the engine + checkChartEnabled(); + // restore the view data + getDesignView()->toggleGrid(m_bGridVisible); + getDesignView()->showRuler(m_bShowRuler); + getDesignView()->togglePropertyBrowser(m_bShowProperties); + getDesignView()->setCurrentPage(m_sLastActivePage); + getDesignView()->unmarkAllObjects(); + + if ( m_nPageNum != -1 ) + { + if ( m_nPageNum < m_aReportModel->GetPageCount() ) + { + const OReportPage* pPage = dynamic_cast<OReportPage*>(m_aReportModel->GetPage(static_cast<sal_uInt16>(m_nPageNum))); + if ( pPage ) + { + executeUnChecked(SID_SELECT,{ comphelper::makePropertyValue("", pPage->getSection() ) }); + } + } + else + m_nPageNum = -1; + } + getDesignView()->collapseSections(m_aCollapsedSections); + impl_zoom_nothrow(); + getDesignView()->Resize(); + getDesignView()->Invalidate(); + InvalidateAll(); + + if ( m_bShowProperties && m_nPageNum == -1 ) + { + m_sLastActivePage = "Data"; + getDesignView()->setCurrentPage(m_sLastActivePage); + executeUnChecked(SID_SELECT_REPORT,{}); + } + + setModified(false); // and we are not modified yet + } + catch(const SQLException&) + { + DBG_UNHANDLED_EXCEPTION("reportdesign"); + } +} + +IMPL_LINK( OReportController, OnCreateHdl, OAddFieldWindow& ,_rAddFieldDlg, void) +{ + weld::WaitObject aObj(getFrameWeld()); + uno::Sequence< beans::PropertyValue > aArgs = _rAddFieldDlg.getSelectedFieldDescriptors(); + // we use this way to create undo actions + if ( aArgs.hasElements() ) + { + executeChecked(SID_ADD_CONTROL_PAIR,aArgs); + } +} + +bool OReportController::Construct(vcl::Window* pParent) +{ + VclPtrInstance<ODesignView> pMyOwnView( pParent, m_xContext, *this ); + StartListening( *pMyOwnView ); + setView( pMyOwnView ); + + // now that we have a view we can create the clipboard listener + m_aSystemClipboard = TransferableDataHelper::CreateFromSystemClipboard( getView() ); + m_aSystemClipboard.StartClipboardListening( ); + m_pClipboardNotifier = new TransferableClipboardListener( LINK( this, OReportController, OnClipboardChanged ) ); + m_pClipboardNotifier->AddListener( getView() ); + + OReportController_BASE::Construct(pParent); + return true; +} + +sal_Bool SAL_CALL OReportController::suspend(sal_Bool /*_bSuspend*/) +{ + if ( getBroadcastHelper().bInDispose || getBroadcastHelper().bDisposed ) + return true; + + SolarMutexGuard aSolarGuard; + ::osl::MutexGuard aGuard( getMutex() ); + + if ( getView() && getView()->IsInModalMode() ) + return false; + + // this suspend will be handled in the DBAccess interceptor implementation + return true; +} + +void OReportController::describeSupportedFeatures() +{ + DBSubComponentController::describeSupportedFeatures(); + + implDescribeSupportedFeature( ".uno:TextDocument", SID_RPT_TEXTDOCUMENT, CommandGroup::APPLICATION ); + implDescribeSupportedFeature( ".uno:Spreadsheet", SID_RPT_SPREADSHEET, CommandGroup::APPLICATION ); + + implDescribeSupportedFeature( ".uno:Redo", SID_REDO, CommandGroup::EDIT ); + implDescribeSupportedFeature( ".uno:Undo", SID_UNDO, CommandGroup::EDIT ); + implDescribeSupportedFeature( ".uno:SelectAll", SID_SELECTALL, CommandGroup::EDIT ); + implDescribeSupportedFeature( ".uno:SelectAllInSection", SID_SELECTALL_IN_SECTION, CommandGroup::EDIT ); + implDescribeSupportedFeature( ".uno:Delete", SID_DELETE, CommandGroup::EDIT ); + implDescribeSupportedFeature( ".uno:SelectReport", SID_SELECT_REPORT, CommandGroup::EDIT ); + implDescribeSupportedFeature( ".uno:ExecuteReport", SID_EXECUTE_REPORT, CommandGroup::EDIT ); + + implDescribeSupportedFeature( ".uno:GridVisible", SID_GRID_VISIBLE, CommandGroup::VIEW ); + implDescribeSupportedFeature( ".uno:GridUse", SID_GRID_USE, CommandGroup::VIEW ); + implDescribeSupportedFeature( ".uno:HelplinesMove", SID_HELPLINES_MOVE, CommandGroup::VIEW ); + implDescribeSupportedFeature( ".uno:ShowRuler", SID_RULER, CommandGroup::VIEW ); + implDescribeSupportedFeature( ".uno:AddField", SID_FM_ADD_FIELD, CommandGroup::VIEW ); + implDescribeSupportedFeature( ".uno:ReportNavigator", SID_RPT_SHOWREPORTEXPLORER, CommandGroup::VIEW ); + implDescribeSupportedFeature( ".uno:ControlProperties", SID_SHOW_PROPERTYBROWSER, CommandGroup::VIEW ); + implDescribeSupportedFeature( ".uno:DbSortingAndGrouping", SID_SORTINGANDGROUPING, CommandGroup::VIEW ); + implDescribeSupportedFeature( ".uno:PageHeaderFooter", SID_PAGEHEADERFOOTER, CommandGroup::VIEW ); + implDescribeSupportedFeature( ".uno:ReportHeaderFooter", SID_REPORTHEADERFOOTER, CommandGroup::VIEW ); + implDescribeSupportedFeature( ".uno:ZoomSlider", SID_ATTR_ZOOMSLIDER ); + implDescribeSupportedFeature( ".uno:Zoom", SID_ATTR_ZOOM, CommandGroup::VIEW ); + + implDescribeSupportedFeature( ".uno:ConditionalFormatting", SID_CONDITIONALFORMATTING, CommandGroup::FORMAT ); + implDescribeSupportedFeature( ".uno:PageDialog", SID_PAGEDIALOG, CommandGroup::FORMAT ); + implDescribeSupportedFeature( ".uno:ResetAttributes", SID_SETCONTROLDEFAULTS, CommandGroup::FORMAT ); + + implDescribeSupportedFeature( ".uno:Bold", SID_ATTR_CHAR_WEIGHT, CommandGroup::FORMAT ); + implDescribeSupportedFeature( ".uno:Italic", SID_ATTR_CHAR_POSTURE, CommandGroup::FORMAT ); + implDescribeSupportedFeature( ".uno:Underline", SID_ATTR_CHAR_UNDERLINE, CommandGroup::FORMAT ); + implDescribeSupportedFeature( ".uno:DBBackgroundColor", SID_ATTR_CHAR_COLOR_BACKGROUND, CommandGroup::FORMAT ); + implDescribeSupportedFeature( ".uno:BackgroundColor", SID_BACKGROUND_COLOR, CommandGroup::FORMAT ); + implDescribeSupportedFeature( ".uno:CharColorExt", SID_ATTR_CHAR_COLOR_EXT); + implDescribeSupportedFeature( ".uno:Color", SID_ATTR_CHAR_COLOR); + implDescribeSupportedFeature( ".uno:FontColor", SID_ATTR_CHAR_COLOR2, CommandGroup::FORMAT ); + implDescribeSupportedFeature( ".uno:FontDialog", SID_CHAR_DLG, CommandGroup::FORMAT ); + implDescribeSupportedFeature( ".uno:LeftPara", SID_ATTR_PARA_ADJUST_LEFT, CommandGroup::FORMAT ); + implDescribeSupportedFeature( ".uno:CenterPara", SID_ATTR_PARA_ADJUST_CENTER, CommandGroup::FORMAT ); + implDescribeSupportedFeature( ".uno:RightPara", SID_ATTR_PARA_ADJUST_RIGHT, CommandGroup::FORMAT ); + implDescribeSupportedFeature( ".uno:JustifyPara", SID_ATTR_PARA_ADJUST_BLOCK, CommandGroup::FORMAT ); + + implDescribeSupportedFeature( ".uno:FontHeight", SID_ATTR_CHAR_FONTHEIGHT, CommandGroup::FORMAT ); + implDescribeSupportedFeature( ".uno:CharFontName", SID_ATTR_CHAR_FONT, CommandGroup::FORMAT ); + + implDescribeSupportedFeature( ".uno:ArrangeMenu", SID_ARRANGEMENU, CommandGroup::FORMAT ); + implDescribeSupportedFeature( ".uno:BringToFront", SID_FRAME_TO_TOP, CommandGroup::FORMAT ); + implDescribeSupportedFeature( ".uno:ObjectBackOne", SID_FRAME_DOWN, CommandGroup::FORMAT ); + implDescribeSupportedFeature( ".uno:ObjectForwardOne", SID_FRAME_UP, CommandGroup::FORMAT ); + implDescribeSupportedFeature( ".uno:SendToBack", SID_FRAME_TO_BOTTOM, CommandGroup::FORMAT ); + implDescribeSupportedFeature( ".uno:SetObjectToForeground", SID_OBJECT_HEAVEN, CommandGroup::FORMAT ); + implDescribeSupportedFeature( ".uno:SetObjectToBackground", SID_OBJECT_HELL, CommandGroup::FORMAT ); + + implDescribeSupportedFeature( ".uno:ObjectAlign", SID_OBJECT_ALIGN, CommandGroup::FORMAT ); + implDescribeSupportedFeature( ".uno:ObjectAlignLeft", SID_OBJECT_ALIGN_LEFT, CommandGroup::FORMAT ); + implDescribeSupportedFeature( ".uno:AlignCenter", SID_OBJECT_ALIGN_CENTER, CommandGroup::FORMAT ); + implDescribeSupportedFeature( ".uno:ObjectAlignRight", SID_OBJECT_ALIGN_RIGHT, CommandGroup::FORMAT ); + implDescribeSupportedFeature( ".uno:AlignUp", SID_OBJECT_ALIGN_UP, CommandGroup::FORMAT ); + implDescribeSupportedFeature( ".uno:AlignMiddle", SID_OBJECT_ALIGN_MIDDLE, CommandGroup::FORMAT ); + implDescribeSupportedFeature( ".uno:AlignDown", SID_OBJECT_ALIGN_DOWN, CommandGroup::FORMAT ); + + implDescribeSupportedFeature( ".uno:SectionAlign", SID_SECTION_ALIGN ); + implDescribeSupportedFeature( ".uno:SectionAlignLeft", SID_SECTION_ALIGN_LEFT, CommandGroup::FORMAT ); + implDescribeSupportedFeature( ".uno:SectionAlignCenter", SID_SECTION_ALIGN_CENTER, CommandGroup::FORMAT ); + implDescribeSupportedFeature( ".uno:SectionAlignRight", SID_SECTION_ALIGN_RIGHT, CommandGroup::FORMAT ); + implDescribeSupportedFeature( ".uno:SectionAlignTop", SID_SECTION_ALIGN_UP, CommandGroup::FORMAT ); + implDescribeSupportedFeature( ".uno:SectionAlignMiddle", SID_SECTION_ALIGN_MIDDLE, CommandGroup::FORMAT ); + implDescribeSupportedFeature( ".uno:SectionAlignBottom", SID_SECTION_ALIGN_DOWN, CommandGroup::FORMAT ); + implDescribeSupportedFeature( ".uno:SectionShrink", SID_SECTION_SHRINK, CommandGroup::FORMAT ); + implDescribeSupportedFeature( ".uno:SectionShrinkTop", SID_SECTION_SHRINK_TOP, CommandGroup::FORMAT ); + implDescribeSupportedFeature( ".uno:SectionShrinkBottom", SID_SECTION_SHRINK_BOTTOM, CommandGroup::FORMAT ); + + implDescribeSupportedFeature( ".uno:ObjectResize", SID_OBJECT_RESIZING, CommandGroup::FORMAT ); + implDescribeSupportedFeature( ".uno:SmallestWidth", SID_OBJECT_SMALLESTWIDTH, CommandGroup::FORMAT ); + implDescribeSupportedFeature( ".uno:SmallestHeight", SID_OBJECT_SMALLESTHEIGHT, CommandGroup::FORMAT ); + implDescribeSupportedFeature( ".uno:GreatestWidth", SID_OBJECT_GREATESTWIDTH, CommandGroup::FORMAT ); + implDescribeSupportedFeature( ".uno:GreatestHeight", SID_OBJECT_GREATESTHEIGHT, CommandGroup::FORMAT ); + + implDescribeSupportedFeature( ".uno:DistributeSelection", SID_DISTRIBUTE_DLG, CommandGroup::FORMAT ); + implDescribeSupportedFeature( ".uno:DistributeHorzLeft", SID_DISTRIBUTE_HLEFT, CommandGroup::FORMAT ); + implDescribeSupportedFeature( ".uno:DistributeHorzCenter", SID_DISTRIBUTE_HCENTER, CommandGroup::FORMAT ); + implDescribeSupportedFeature( ".uno:DistributeHorzDistance", SID_DISTRIBUTE_HDISTANCE, CommandGroup::FORMAT ); + implDescribeSupportedFeature( ".uno:DistributeHorzRight", SID_DISTRIBUTE_HRIGHT, CommandGroup::FORMAT ); + implDescribeSupportedFeature( ".uno:DistributeVertTop", SID_DISTRIBUTE_VTOP, CommandGroup::FORMAT ); + implDescribeSupportedFeature( ".uno:DistributeVertCenter", SID_DISTRIBUTE_VCENTER, CommandGroup::FORMAT ); + implDescribeSupportedFeature( ".uno:DistributeVertDistance", SID_DISTRIBUTE_VDISTANCE, CommandGroup::FORMAT ); + implDescribeSupportedFeature( ".uno:DistributeVertBottom", SID_DISTRIBUTE_VBOTTOM, CommandGroup::FORMAT ); + + implDescribeSupportedFeature( ".uno:ExportTo", SID_EXPORTDOC, CommandGroup::APPLICATION ); + implDescribeSupportedFeature( ".uno:ExportToPDF", SID_EXPORTDOCASPDF, CommandGroup::APPLICATION ); + implDescribeSupportedFeature( ".uno:PrintPreview", SID_PRINTPREVIEW, CommandGroup::APPLICATION ); + + implDescribeSupportedFeature( ".uno:NewDoc", SID_NEWDOC, CommandGroup::DOCUMENT ); + implDescribeSupportedFeature( ".uno:Save", SID_SAVEDOC, CommandGroup::DOCUMENT ); + implDescribeSupportedFeature( ".uno:SaveAs", SID_SAVEASDOC, CommandGroup::DOCUMENT ); + implDescribeSupportedFeature( ".uno:SaveACopy", SID_SAVEACOPY, CommandGroup::DOCUMENT ); + + implDescribeSupportedFeature( ".uno:InsertPageNumberField", SID_INSERT_FLD_PGNUMBER, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:InsertDateTimeField", SID_DATETIME, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:InsertObjectChart", SID_INSERT_DIAGRAM, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:InsertGraphic", SID_INSERT_GRAPHIC, CommandGroup::INSERT ); + // controls + implDescribeSupportedFeature( ".uno:SelectObject", SID_OBJECT_SELECT, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:Label", SID_FM_FIXEDTEXT, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:Edit", SID_FM_EDIT, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:ImageControl", SID_FM_IMAGECONTROL, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:HFixedLine", SID_INSERT_HFIXEDLINE, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:VFixedLine", SID_INSERT_VFIXEDLINE, CommandGroup::INSERT ); + + // shapes + implDescribeSupportedFeature( ".uno:BasicShapes", SID_DRAWTBX_CS_BASIC, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:BasicShapes.rectangle", SID_DRAWTBX_CS_BASIC1, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:BasicShapes.round-rectangle",SID_DRAWTBX_CS_BASIC2, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:BasicShapes.quadrat", SID_DRAWTBX_CS_BASIC3, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:BasicShapes.round-quadrat", SID_DRAWTBX_CS_BASIC4, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:BasicShapes.circle", SID_DRAWTBX_CS_BASIC5, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:BasicShapes.ellipse", SID_DRAWTBX_CS_BASIC6, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:BasicShapes.circle-pie", SID_DRAWTBX_CS_BASIC7, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:BasicShapes.isosceles-triangle",SID_DRAWTBX_CS_BASIC8, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:BasicShapes.right-triangle",SID_DRAWTBX_CS_BASIC9, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:BasicShapes.trapezoid", SID_DRAWTBX_CS_BASIC10, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:BasicShapes.diamond", SID_DRAWTBX_CS_BASIC11, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:BasicShapes.parallelogram", SID_DRAWTBX_CS_BASIC12, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:BasicShapes.pentagon", SID_DRAWTBX_CS_BASIC13, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:BasicShapes.hexagon", SID_DRAWTBX_CS_BASIC14, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:BasicShapes.octagon", SID_DRAWTBX_CS_BASIC15, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:BasicShapes.cross", SID_DRAWTBX_CS_BASIC16, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:BasicShapes.ring", SID_DRAWTBX_CS_BASIC17, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:BasicShapes.block-arc", SID_DRAWTBX_CS_BASIC18, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:BasicShapes.can", SID_DRAWTBX_CS_BASIC19, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:BasicShapes.cube", SID_DRAWTBX_CS_BASIC20, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:BasicShapes.paper", SID_DRAWTBX_CS_BASIC21, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:BasicShapes.frame", SID_DRAWTBX_CS_BASIC22, CommandGroup::INSERT ); + + implDescribeSupportedFeature( ".uno:SymbolShapes", SID_DRAWTBX_CS_SYMBOL, CommandGroup::INSERT ); + + implDescribeSupportedFeature( ".uno:SymbolShapes.smiley" , SID_DRAWTBX_CS_SYMBOL1, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:SymbolShapes.sun" , SID_DRAWTBX_CS_SYMBOL2, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:SymbolShapes.moon" , SID_DRAWTBX_CS_SYMBOL3, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:SymbolShapes.lightning" , SID_DRAWTBX_CS_SYMBOL4, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:SymbolShapes.heart" , SID_DRAWTBX_CS_SYMBOL5, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:SymbolShapes.flower" , SID_DRAWTBX_CS_SYMBOL6, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:SymbolShapes.cloud" , SID_DRAWTBX_CS_SYMBOL7, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:SymbolShapes.forbidden" , SID_DRAWTBX_CS_SYMBOL8, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:SymbolShapes.puzzle" , SID_DRAWTBX_CS_SYMBOL9, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:SymbolShapes.bracket-pair" ,SID_DRAWTBX_CS_SYMBOL10, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:SymbolShapes.left-bracket" ,SID_DRAWTBX_CS_SYMBOL11, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:SymbolShapes.right-bracket",SID_DRAWTBX_CS_SYMBOL12, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:SymbolShapes.brace-pair" , SID_DRAWTBX_CS_SYMBOL13, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:SymbolShapes.left-brace" , SID_DRAWTBX_CS_SYMBOL14, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:SymbolShapes.right-brace" , SID_DRAWTBX_CS_SYMBOL15, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:SymbolShapes.quad-bevel" , SID_DRAWTBX_CS_SYMBOL16, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:SymbolShapes.octagon-bevel",SID_DRAWTBX_CS_SYMBOL17, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:SymbolShapes.diamond-bevel",SID_DRAWTBX_CS_SYMBOL18, CommandGroup::INSERT ); + + implDescribeSupportedFeature( ".uno:ArrowShapes.left-arrow" , SID_DRAWTBX_CS_ARROW1, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:ArrowShapes.right-arrow" , SID_DRAWTBX_CS_ARROW2, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:ArrowShapes.up-arrow" , SID_DRAWTBX_CS_ARROW3, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:ArrowShapes.down-arrow" , SID_DRAWTBX_CS_ARROW4, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:ArrowShapes.left-right-arrow" , SID_DRAWTBX_CS_ARROW5, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:ArrowShapes.up-down-arrow" , SID_DRAWTBX_CS_ARROW6, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:ArrowShapes.up-right-arrow" , SID_DRAWTBX_CS_ARROW7, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:ArrowShapes.up-right-down-arrow" , SID_DRAWTBX_CS_ARROW8, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:ArrowShapes.quad-arrow" , SID_DRAWTBX_CS_ARROW9, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:ArrowShapes.corner-right-arrow" , SID_DRAWTBX_CS_ARROW10, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:ArrowShapes.split-arrow" , SID_DRAWTBX_CS_ARROW11, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:ArrowShapes.striped-right-arrow" , SID_DRAWTBX_CS_ARROW12, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:ArrowShapes.notched-right-arrow" , SID_DRAWTBX_CS_ARROW13, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:ArrowShapes.pentagon-right" , SID_DRAWTBX_CS_ARROW14, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:ArrowShapes.chevron" , SID_DRAWTBX_CS_ARROW15, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:ArrowShapes.right-arrow-callout" , SID_DRAWTBX_CS_ARROW16, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:ArrowShapes.left-arrow-callout" , SID_DRAWTBX_CS_ARROW17, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:ArrowShapes.up-arrow-callout" , SID_DRAWTBX_CS_ARROW18, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:ArrowShapes.down-arrow-callout" , SID_DRAWTBX_CS_ARROW19, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:ArrowShapes.left-right-arrow-callout",SID_DRAWTBX_CS_ARROW20, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:ArrowShapes.up-down-arrow-callout" ,SID_DRAWTBX_CS_ARROW21, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:ArrowShapes.up-right-arrow-callout",SID_DRAWTBX_CS_ARROW22, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:ArrowShapes.quad-arrow-callout" , SID_DRAWTBX_CS_ARROW23, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:ArrowShapes.circular-arrow" , SID_DRAWTBX_CS_ARROW24, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:ArrowShapes.split-round-arrow" , SID_DRAWTBX_CS_ARROW25, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:ArrowShapes.s-sharped-arrow" , SID_DRAWTBX_CS_ARROW26, CommandGroup::INSERT ); + + implDescribeSupportedFeature( ".uno:StarShapes.bang" , SID_DRAWTBX_CS_STAR1, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:StarShapes.star4" , SID_DRAWTBX_CS_STAR2, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:StarShapes.star5" , SID_DRAWTBX_CS_STAR3, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:StarShapes.star6" , SID_DRAWTBX_CS_STAR4, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:StarShapes.star8" , SID_DRAWTBX_CS_STAR5, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:StarShapes.star12" , SID_DRAWTBX_CS_STAR6, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:StarShapes.star24" , SID_DRAWTBX_CS_STAR7, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:StarShapes.concave-star6" , SID_DRAWTBX_CS_STAR8, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:StarShapes.vertical-scroll" , SID_DRAWTBX_CS_STAR9, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:StarShapes.horizontal-scroll" , SID_DRAWTBX_CS_STAR10, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:StarShapes.signet" , SID_DRAWTBX_CS_STAR11, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:StarShapes.doorplate" , SID_DRAWTBX_CS_STAR12, CommandGroup::INSERT ); + + implDescribeSupportedFeature( ".uno:FlowChartShapes.flowchart-process" , SID_DRAWTBX_CS_FLOWCHART1, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:FlowChartShapes.flowchart-alternate-process" , SID_DRAWTBX_CS_FLOWCHART2, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:FlowChartShapes.flowchart-decision" , SID_DRAWTBX_CS_FLOWCHART3, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:FlowChartShapes.flowchart-data" , SID_DRAWTBX_CS_FLOWCHART4, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:FlowChartShapes.flowchart-predefined-process" , SID_DRAWTBX_CS_FLOWCHART5, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:FlowChartShapes.flowchart-internal-storage" , SID_DRAWTBX_CS_FLOWCHART6, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:FlowChartShapes.flowchart-document" , SID_DRAWTBX_CS_FLOWCHART7, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:FlowChartShapes.flowchart-multidocument" , SID_DRAWTBX_CS_FLOWCHART8, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:FlowChartShapes.flowchart-terminator" , SID_DRAWTBX_CS_FLOWCHART9, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:FlowChartShapes.flowchart-preparation" , SID_DRAWTBX_CS_FLOWCHART10, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:FlowChartShapes.flowchart-manual-input" , SID_DRAWTBX_CS_FLOWCHART11, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:FlowChartShapes.flowchart-manual-operation" , SID_DRAWTBX_CS_FLOWCHART12, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:FlowChartShapes.flowchart-connector" , SID_DRAWTBX_CS_FLOWCHART13, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:FlowChartShapes.flowchart-off-page-connector" , SID_DRAWTBX_CS_FLOWCHART14, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:FlowChartShapes.flowchart-card" , SID_DRAWTBX_CS_FLOWCHART15, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:FlowChartShapes.flowchart-punched-tape" , SID_DRAWTBX_CS_FLOWCHART16, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:FlowChartShapes.flowchart-summing-junction" , SID_DRAWTBX_CS_FLOWCHART17, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:FlowChartShapes.flowchart-or" , SID_DRAWTBX_CS_FLOWCHART18, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:FlowChartShapes.flowchart-collate" , SID_DRAWTBX_CS_FLOWCHART19, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:FlowChartShapes.flowchart-sort" , SID_DRAWTBX_CS_FLOWCHART20, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:FlowChartShapes.flowchart-extract" , SID_DRAWTBX_CS_FLOWCHART21, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:FlowChartShapes.flowchart-merge" , SID_DRAWTBX_CS_FLOWCHART22, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:FlowChartShapes.flowchart-stored-data" , SID_DRAWTBX_CS_FLOWCHART23, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:FlowChartShapes.flowchart-delay" , SID_DRAWTBX_CS_FLOWCHART24, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:FlowChartShapes.flowchart-sequential-access" , SID_DRAWTBX_CS_FLOWCHART25, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:FlowChartShapes.flowchart-magnetic-disk" , SID_DRAWTBX_CS_FLOWCHART26, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:FlowChartShapes.flowchart-direct-access-storage",SID_DRAWTBX_CS_FLOWCHART27, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:FlowChartShapes.flowchart-display" , SID_DRAWTBX_CS_FLOWCHART28, CommandGroup::INSERT ); + + implDescribeSupportedFeature( ".uno:CalloutShapes.rectangular-callout" , SID_DRAWTBX_CS_CALLOUT1, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:CalloutShapes.round-rectangular-callout" , SID_DRAWTBX_CS_CALLOUT2, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:CalloutShapes.round-callout" , SID_DRAWTBX_CS_CALLOUT3, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:CalloutShapes.cloud-callout" , SID_DRAWTBX_CS_CALLOUT4, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:CalloutShapes.line-callout-1" , SID_DRAWTBX_CS_CALLOUT5, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:CalloutShapes.line-callout-2" , SID_DRAWTBX_CS_CALLOUT6, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:CalloutShapes.line-callout-3" , SID_DRAWTBX_CS_CALLOUT7, CommandGroup::INSERT ); + + implDescribeSupportedFeature( ".uno:ArrowShapes", SID_DRAWTBX_CS_ARROW, CommandGroup::INSERT ); + + implDescribeSupportedFeature( ".uno:FlowChartShapes", SID_DRAWTBX_CS_FLOWCHART, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:CalloutShapes", SID_DRAWTBX_CS_CALLOUT, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:StarShapes", SID_DRAWTBX_CS_STAR, CommandGroup::INSERT ); + + + // keys + implDescribeSupportedFeature( ".uno:Escape", SID_ESCAPE); + + // internal one + implDescribeSupportedFeature( ".uno:RPT_RPTHEADER_UNDO", SID_REPORTHEADER_WITHOUT_UNDO); + implDescribeSupportedFeature( ".uno:RPT_RPTFOOTER_UNDO", SID_REPORTFOOTER_WITHOUT_UNDO); + implDescribeSupportedFeature( ".uno:RPT_PGHEADER_UNDO", SID_PAGEHEADER_WITHOUT_UNDO); + implDescribeSupportedFeature( ".uno:RPT_PGFOOTER_UNDO", SID_PAGEFOOTER_WITHOUT_UNDO); + implDescribeSupportedFeature( ".uno:SID_GROUPHEADER", SID_GROUPHEADER); + implDescribeSupportedFeature( ".uno:SID_GROUPHEADER_WITHOUT_UNDO", SID_GROUPHEADER_WITHOUT_UNDO); + implDescribeSupportedFeature( ".uno:SID_GROUPFOOTER", SID_GROUPFOOTER); + implDescribeSupportedFeature( ".uno:SID_GROUPFOOTER_WITHOUT_UNDO", SID_GROUPFOOTER_WITHOUT_UNDO); + implDescribeSupportedFeature( ".uno:SID_GROUP_REMOVE", SID_GROUP_REMOVE); + implDescribeSupportedFeature( ".uno:SID_GROUP_APPEND", SID_GROUP_APPEND); + implDescribeSupportedFeature( ".uno:SID_ADD_CONTROL_PAIR", SID_ADD_CONTROL_PAIR); + implDescribeSupportedFeature( ".uno:SplitPosition", SID_SPLIT_POSITION); + implDescribeSupportedFeature( ".uno:LastPropertyBrowserPage", SID_PROPERTYBROWSER_LAST_PAGE); + implDescribeSupportedFeature( ".uno:Select", SID_SELECT); + implDescribeSupportedFeature( ".uno:InsertFunction", SID_RPT_NEW_FUNCTION); + implDescribeSupportedFeature( ".uno:NextMark", SID_NEXT_MARK); + implDescribeSupportedFeature( ".uno:PrevMark", SID_PREV_MARK); + implDescribeSupportedFeature( ".uno:TerminateInplaceActivation", SID_TERMINATE_INPLACEACTIVATION); + implDescribeSupportedFeature( ".uno:SelectAllLabels", SID_SELECT_ALL_LABELS); + implDescribeSupportedFeature( ".uno:SelectAllEdits", SID_SELECT_ALL_EDITS); + implDescribeSupportedFeature( ".uno:CollapseSection", SID_COLLAPSE_SECTION); + implDescribeSupportedFeature( ".uno:ExpandSection", SID_EXPAND_SECTION); + implDescribeSupportedFeature( ".uno:GetUndoStrings", SID_GETUNDOSTRINGS); + implDescribeSupportedFeature( ".uno:GetRedoStrings", SID_GETREDOSTRINGS); +} + +void OReportController::impl_onModifyChanged() +{ + try + { + if ( m_xReportDefinition.is() ) + m_xReportDefinition->setModified( impl_isModified() ); + DBSubComponentController::impl_onModifyChanged(); + } + catch(const uno::Exception&) + { + DBG_UNHANDLED_EXCEPTION("reportdesign"); + } +} + +void OReportController::onLoadedMenu(const Reference< frame::XLayoutManager >& _xLayoutManager) +{ + if ( !_xLayoutManager.is() ) + return; + + static const std::u16string_view s_sMenu[] = { + u"private:resource/statusbar/statusbar" + ,u"private:resource/toolbar/reportcontrols" + ,u"private:resource/toolbar/drawbar" + ,u"private:resource/toolbar/Formatting" + ,u"private:resource/toolbar/alignmentbar" + ,u"private:resource/toolbar/sectionalignmentbar" + ,u"private:resource/toolbar/resizebar" + ,u"private:resource/toolbar/sectionshrinkbar" + }; + for (const auto & i : s_sMenu) + { + _xLayoutManager->createElement( OUString(i) ); + _xLayoutManager->requestElement( OUString(i) ); + } +} + +void OReportController::notifyGroupSections(const ContainerEvent& _rEvent,bool _bShow) +{ + uno::Reference< report::XGroup> xGroup(_rEvent.Element,uno::UNO_QUERY); + if ( !xGroup.is() ) + return; + + SolarMutexGuard aSolarGuard; + ::osl::MutexGuard aGuard( getMutex() ); + sal_Int32 nGroupPos = 0; + _rEvent.Accessor >>= nGroupPos; + + if ( _bShow ) + { + xGroup->addPropertyChangeListener(PROPERTY_HEADERON, static_cast<XPropertyChangeListener*>(this)); + xGroup->addPropertyChangeListener(PROPERTY_FOOTERON, static_cast<XPropertyChangeListener*>(this)); + } + else + { + xGroup->removePropertyChangeListener(PROPERTY_HEADERON, static_cast<XPropertyChangeListener*>(this)); + xGroup->removePropertyChangeListener(PROPERTY_FOOTERON, static_cast<XPropertyChangeListener*>(this)); + } + + if ( xGroup->getHeaderOn() ) + { + groupChange(xGroup,PROPERTY_HEADERON,nGroupPos,_bShow); + if (_bShow) + { + m_pReportControllerObserver->AddSection(xGroup->getHeader()); + } + else + { + m_pReportControllerObserver->RemoveSection(xGroup->getHeader()); + } + } + if ( xGroup->getFooterOn() ) + { + groupChange(xGroup,PROPERTY_FOOTERON,nGroupPos,_bShow); + if (_bShow) + { + m_pReportControllerObserver->AddSection(xGroup->getFooter()); + } + else + { + m_pReportControllerObserver->RemoveSection(xGroup->getFooter()); + } + } +} + +// ::container::XContainerListener +void SAL_CALL OReportController::elementInserted( const ContainerEvent& _rEvent ) +{ + notifyGroupSections(_rEvent,true); +} + +void SAL_CALL OReportController::elementRemoved( const ContainerEvent& _rEvent ) +{ + notifyGroupSections(_rEvent,false); +} + +void SAL_CALL OReportController::elementReplaced( const ContainerEvent& /*_rEvent*/ ) +{ + SolarMutexGuard aSolarGuard; + ::osl::MutexGuard aGuard( getMutex() ); + OSL_FAIL("Not yet implemented!"); +} + +void SAL_CALL OReportController::propertyChange( const beans::PropertyChangeEvent& evt ) +{ + SolarMutexGuard aSolarGuard; + ::osl::MutexGuard aGuard( getMutex() ); + try + { + bool bShow = false; + evt.NewValue >>= bShow; + if ( evt.Source == m_xReportDefinition ) + { + if ( evt.PropertyName == PROPERTY_REPORTHEADERON ) + { + const sal_uInt16 nPosition = m_xReportDefinition->getPageHeaderOn() ? 1 : 0; + if ( bShow ) + { + getDesignView()->addSection(m_xReportDefinition->getReportHeader(),DBREPORTHEADER,nPosition); + m_pReportControllerObserver->AddSection(m_xReportDefinition->getReportHeader()); + } + else + { + getDesignView()->removeSection(nPosition); + } + } + else if ( evt.PropertyName == PROPERTY_REPORTFOOTERON ) + { + sal_uInt16 nPosition = getDesignView()->getSectionCount(); + if ( m_xReportDefinition->getPageFooterOn() ) + --nPosition; + if ( bShow ) + { + getDesignView()->addSection(m_xReportDefinition->getReportFooter(),DBREPORTFOOTER,nPosition); + m_pReportControllerObserver->AddSection(m_xReportDefinition->getReportFooter()); + } + else + { + getDesignView()->removeSection(nPosition - 1); + } + } + else if ( evt.PropertyName == PROPERTY_PAGEHEADERON ) + { + if ( bShow ) + { + getDesignView()->addSection(m_xReportDefinition->getPageHeader(),DBPAGEHEADER,0); + m_pReportControllerObserver->AddSection(m_xReportDefinition->getPageHeader()); + } + else + { + getDesignView()->removeSection(sal_uInt16(0)); + } + } + else if ( evt.PropertyName == PROPERTY_PAGEFOOTERON ) + { + if ( bShow ) + { + getDesignView()->addSection(m_xReportDefinition->getPageFooter(),DBPAGEFOOTER); + m_pReportControllerObserver->AddSection(m_xReportDefinition->getPageFooter()); + } + else + { + getDesignView()->removeSection(getDesignView()->getSectionCount() - 1); + } + } + else if ( evt.PropertyName == PROPERTY_COMMAND + || evt.PropertyName == PROPERTY_COMMANDTYPE + || evt.PropertyName == PROPERTY_ESCAPEPROCESSING + || evt.PropertyName == PROPERTY_FILTER + ) + { + m_xColumns.clear(); + m_xHoldAlive.clear(); + InvalidateFeature(SID_FM_ADD_FIELD); + if ( !getDesignView()->isAddFieldVisible() && isUiVisible() ) + getDesignView()->toggleAddField(); + } + /// TODO: check what we need to notify here TitleHelper + /*else if ( evt.PropertyName.equals( PROPERTY_CAPTION ) ) + updateTitle();*/ + } + else + { + uno::Reference< report::XGroup> xGroup(evt.Source,uno::UNO_QUERY); + if ( xGroup.is() ) + { + sal_Int32 nGroupPos = getGroupPosition(xGroup); + + groupChange(xGroup,evt.PropertyName,nGroupPos,bShow); + } + } + } + catch(const uno::Exception&) + { + DBG_UNHANDLED_EXCEPTION("reportdesign"); + } +} + + +void SAL_CALL OReportController::disposing( const lang::EventObject& Source ) +{ + // simply disambiguate + OReportController_BASE::disposing(Source); +} + + +static sal_uInt16 lcl_getNonVisibleGroupsBefore( const uno::Reference< report::XGroups>& _xGroups + ,sal_Int32 _nGroupPos + ,::std::function<bool(OGroupHelper *)> const & _pGroupMemberFunction) +{ + uno::Reference< report::XGroup> xGroup; + sal_uInt16 nNonVisibleGroups = 0; + sal_Int32 nCount = _xGroups->getCount(); + for( sal_Int32 i = 0; i < _nGroupPos && i < nCount; ++i) + { + xGroup.set(_xGroups->getByIndex(i),uno::UNO_QUERY); + OSL_ENSURE(xGroup.is(),"Group is NULL! -> GPF"); + OGroupHelper aGroupHelper(xGroup); + if ( !_pGroupMemberFunction(&aGroupHelper) ) + ++nNonVisibleGroups; + } + return nNonVisibleGroups; +} + +void OReportController::groupChange( const uno::Reference< report::XGroup>& _xGroup,std::u16string_view _sPropName,sal_Int32 _nGroupPos,bool _bShow) +{ + ::std::function<bool(OGroupHelper *)> pMemFun = ::std::mem_fn(&OGroupHelper::getHeaderOn); + ::std::function<uno::Reference<report::XSection>(OGroupHelper *)> pMemFunSection = ::std::mem_fn(&OGroupHelper::getHeader); + OUString sColor(DBGROUPHEADER); + sal_uInt16 nPosition = 0; + bool bHandle = false; + if ( _sPropName == PROPERTY_HEADERON ) + { + nPosition = m_xReportDefinition->getPageHeaderOn() ? (m_xReportDefinition->getReportHeaderOn() ? 2 : 1) : (m_xReportDefinition->getReportHeaderOn() ? 1 : 0); + nPosition += (static_cast<sal_uInt16>(_nGroupPos) - lcl_getNonVisibleGroupsBefore(m_xReportDefinition->getGroups(),_nGroupPos,pMemFun)); + bHandle = true; + } + else if ( _sPropName == PROPERTY_FOOTERON ) + { + pMemFun = ::std::mem_fn(&OGroupHelper::getFooterOn); + pMemFunSection = ::std::mem_fn(&OGroupHelper::getFooter); + nPosition = getDesignView()->getSectionCount(); + + if ( m_xReportDefinition->getPageFooterOn() ) + --nPosition; + if ( m_xReportDefinition->getReportFooterOn() ) + --nPosition; + sColor = DBGROUPFOOTER; + nPosition -= (static_cast<sal_uInt16>(_nGroupPos) - lcl_getNonVisibleGroupsBefore(m_xReportDefinition->getGroups(),_nGroupPos,pMemFun)); + if ( !_bShow ) + --nPosition; + bHandle = true; + } + if ( bHandle ) + { + if ( _bShow ) + { + OGroupHelper aGroupHelper(_xGroup); + getDesignView()->addSection(pMemFunSection(&aGroupHelper),sColor,nPosition); + } + else + { + getDesignView()->removeSection(nPosition); + } + } +} + +IMPL_LINK_NOARG(OReportController, OnClipboardChanged, TransferableDataHelper*, void) +{ + OnInvalidateClipboard(); +} + +void OReportController::OnInvalidateClipboard() +{ + InvalidateFeature(SID_CUT); + InvalidateFeature(SID_COPY); + InvalidateFeature(SID_PASTE); +} + +void OReportController::openPageDialog(const uno::Reference<report::XSection>& _xSection) +{ + if ( !m_xReportDefinition.is() ) + return; + + // UNO->ItemSet + static SfxItemInfo aItemInfos[] = + { + { SID_ATTR_LRSPACE, true }, + { SID_ATTR_ULSPACE, true }, + { SID_ATTR_PAGE, true }, + { SID_ATTR_PAGE_SIZE, true }, + { SID_ENUM_PAGE_MODE, true }, + { SID_PAPER_START, true }, + { SID_PAPER_END, true }, + { SID_ATTR_BRUSH, true }, + { 0, true }, // XATTR_FILLSTYLE + { 0, true }, // XATTR_FILLCOLOR + { 0, true }, // XATTR_FILLGRADIENT + { 0, true }, // XATTR_FILLHATCH + { 0, true }, // XATTR_FILLBITMAP + { 0, true }, // XATTR_FILLTRANSPARENCE + { 0, true }, // XATTR_GRADIENTSTEPCOUNT + { 0, true }, // XATTR_FILLBMP_TILE + { 0, true }, // XATTR_FILLBMP_POS + { 0, true }, // XATTR_FILLBMP_SIZEX + { 0, true }, // XATTR_FILLBMP_SIZEY + { 0, true }, // XATTR_FILLFLOATTRANSPARENCE + { 0, true }, // XATTR_SECONDARYFILLCOLOR + { 0, true }, // XATTR_FILLBMP_SIZELOG + { 0, true }, // XATTR_FILLBMP_TILEOFFSETX + { 0, true }, // XATTR_FILLBMP_TILEOFFSETY + { 0, true }, // XATTR_FILLBMP_STRETCH + { 0, true }, // XATTR_FILLBMP_POSOFFSETX + { 0, true }, // XATTR_FILLBMP_POSOFFSETY + { 0, true }, // XATTR_FILLBACKGROUND + { SID_ATTR_METRIC, true } + }; + + MeasurementSystem eSystem = SvtSysLocale().GetLocaleData().getMeasurementSystemEnum(); + FieldUnit eUserMetric = MeasurementSystem::Metric == eSystem ? FieldUnit::CM : FieldUnit::INCH; + static const WhichRangesContainer pRanges(svl::Items< + RPTUI_ID_LRSPACE, XATTR_FILL_LAST, + SID_ATTR_METRIC,SID_ATTR_METRIC + >); + rtl::Reference<SfxItemPool> pPool( new SfxItemPool("ReportPageProperties", RPTUI_ID_LRSPACE, RPTUI_ID_METRIC, aItemInfos ) ); + + const Graphic aNullGraphic; + const ::Color aNullLineCol(COL_DEFAULT_SHAPE_STROKE); // #i121448# Use defined default color + const ::Color aNullFillCol(COL_DEFAULT_SHAPE_FILLING); // #i121448# Use defined default color + const XGradient aNullGrad(COL_BLACK, COL_WHITE); + const XHatch aNullHatch(aNullLineCol); + + std::vector<SfxPoolItem*> pDefaults + { + new SvxLRSpaceItem(RPTUI_ID_LRSPACE), + new SvxULSpaceItem(RPTUI_ID_ULSPACE), + new SvxPageItem(RPTUI_ID_PAGE), + new SvxSizeItem(RPTUI_ID_SIZE), + new SfxUInt16Item(RPTUI_ID_PAGE_MODE,SVX_PAGE_MODE_STANDARD), + new SfxUInt16Item(RPTUI_ID_START,PAPER_A4), + new SfxUInt16Item(RPTUI_ID_END,PAPER_E), + new SvxBrushItem(RPTUI_ID_BRUSH), + new XFillStyleItem, + new XFillColorItem("", aNullFillCol), + new XFillGradientItem(aNullGrad), + new XFillHatchItem(aNullHatch), + new XFillBitmapItem(aNullGraphic), + new XFillTransparenceItem, + new XGradientStepCountItem, + new XFillBmpTileItem, + new XFillBmpPosItem, + new XFillBmpSizeXItem, + new XFillBmpSizeYItem, + new XFillFloatTransparenceItem(aNullGrad, false), + new XSecondaryFillColorItem("", aNullFillCol), + new XFillBmpSizeLogItem, + new XFillBmpTileOffsetXItem, + new XFillBmpTileOffsetYItem, + new XFillBmpStretchItem, + new XFillBmpPosOffsetXItem, + new XFillBmpPosOffsetYItem, + new XFillBackgroundItem, + new SfxUInt16Item(RPTUI_ID_METRIC,static_cast<sal_uInt16>(eUserMetric)) + }; + + pPool->SetDefaults(&pDefaults); + + + pPool->SetDefaultMetric( MapUnit::Map100thMM ); // ripped, don't understand why + pPool->FreezeIdRanges(); // the same + + try + { + SfxItemSet aDescriptor(*pPool, pRanges); + // fill it + if ( _xSection.is() ) + aDescriptor.Put(SvxBrushItem(::Color(ColorTransparency, _xSection->getBackColor()),RPTUI_ID_BRUSH)); + else + { + aDescriptor.Put(SvxSizeItem(RPTUI_ID_SIZE,VCLSize(getStyleProperty<awt::Size>(m_xReportDefinition,PROPERTY_PAPERSIZE)))); + aDescriptor.Put(SvxLRSpaceItem(getStyleProperty<sal_Int32>(m_xReportDefinition,PROPERTY_LEFTMARGIN) + ,getStyleProperty<sal_Int32>(m_xReportDefinition,PROPERTY_RIGHTMARGIN),0,0,RPTUI_ID_LRSPACE)); + aDescriptor.Put(SvxULSpaceItem(static_cast<sal_uInt16>(getStyleProperty<sal_Int32>(m_xReportDefinition,PROPERTY_TOPMARGIN)) + ,static_cast<sal_uInt16>(getStyleProperty<sal_Int32>(m_xReportDefinition,PROPERTY_BOTTOMMARGIN)),RPTUI_ID_ULSPACE)); + aDescriptor.Put(SfxUInt16Item(SID_ATTR_METRIC,static_cast<sal_uInt16>(eUserMetric))); + + uno::Reference< style::XStyle> xPageStyle(getUsedStyle(m_xReportDefinition)); + if ( xPageStyle.is() ) + { + SvxPageItem aPageItem(RPTUI_ID_PAGE); + aPageItem.SetDescName(xPageStyle->getName()); + uno::Reference<beans::XPropertySet> xProp(xPageStyle,uno::UNO_QUERY_THROW); + aPageItem.PutValue(xProp->getPropertyValue(PROPERTY_PAGESTYLELAYOUT),MID_PAGE_LAYOUT); + aPageItem.SetLandscape(getStyleProperty<bool>(m_xReportDefinition,PROPERTY_ISLANDSCAPE)); + aPageItem.SetNumType(static_cast<SvxNumType>(getStyleProperty<sal_Int16>(m_xReportDefinition,PROPERTY_NUMBERINGTYPE))); + aDescriptor.Put(aPageItem); + aDescriptor.Put(SvxBrushItem(::Color(ColorTransparency, getStyleProperty<sal_Int32>(m_xReportDefinition,PROPERTY_BACKCOLOR)),RPTUI_ID_BRUSH)); + } + } + + { // want the dialog to be destroyed before our set + ORptPageDialog aDlg( + getFrameWeld(), &aDescriptor,_xSection.is() + ? OUString("BackgroundDialog") + : OUString("PageDialog")); + if (aDlg.run() == RET_OK) + { + + // ItemSet->UNO + // UNO-properties + const SfxItemSet* pSet = aDlg.GetOutputItemSet(); + if ( _xSection.is() ) + { + if ( const SvxBrushItem* pBrushItem = pSet->GetItemIfSet( RPTUI_ID_BRUSH )) + _xSection->setBackColor(sal_Int32(pBrushItem->GetColor())); + } + else + { + uno::Reference< beans::XPropertySet> xProp(getUsedStyle(m_xReportDefinition),uno::UNO_QUERY_THROW); + const OUString sUndoAction(RptResId(RID_STR_UNDO_CHANGEPAGE)); + UndoContext aUndoContext( getUndoManager(), sUndoAction ); + if ( const SvxSizeItem* pSizeItem = pSet->GetItemIfSet( RPTUI_ID_SIZE )) + { + uno::Any aValue; + pSizeItem->QueryValue(aValue); + xProp->setPropertyValue(PROPERTY_PAPERSIZE,aValue); + resetZoomType(); + } + + if ( const SvxLRSpaceItem* pSpaceItem = pSet->GetItemIfSet( RPTUI_ID_LRSPACE )) + { + Any aValue; + pSpaceItem->QueryValue(aValue,MID_L_MARGIN); + xProp->setPropertyValue(PROPERTY_LEFTMARGIN,aValue); + pSpaceItem->QueryValue(aValue,MID_R_MARGIN); + xProp->setPropertyValue(PROPERTY_RIGHTMARGIN,aValue); + } + if ( const SvxULSpaceItem* pSpaceItem = pSet->GetItemIfSet( RPTUI_ID_ULSPACE )) + { + xProp->setPropertyValue(PROPERTY_TOPMARGIN,uno::Any(pSpaceItem->GetUpper())); + xProp->setPropertyValue(PROPERTY_BOTTOMMARGIN,uno::Any(pSpaceItem->GetLower())); + } + if ( const SvxPageItem* pPageItem = pSet->GetItemIfSet( RPTUI_ID_PAGE )) + { + xProp->setPropertyValue(PROPERTY_ISLANDSCAPE,uno::Any(pPageItem->IsLandscape())); + xProp->setPropertyValue(PROPERTY_NUMBERINGTYPE,uno::Any(static_cast<sal_Int16>(pPageItem->GetNumType()))); + uno::Any aValue; + pPageItem->QueryValue(aValue,MID_PAGE_LAYOUT); + xProp->setPropertyValue(PROPERTY_PAGESTYLELAYOUT,aValue); + resetZoomType(); + } + if ( const SvxBrushItem* pBrushItem = pSet->GetItemIfSet( RPTUI_ID_BRUSH )) + { + ::Color aBackColor = pBrushItem->GetColor(); + xProp->setPropertyValue(PROPERTY_BACKTRANSPARENT,uno::Any(aBackColor == COL_TRANSPARENT)); + xProp->setPropertyValue(PROPERTY_BACKCOLOR,uno::Any(aBackColor)); + } + } + } + } + } + catch(const Exception&) + { + DBG_UNHANDLED_EXCEPTION("reportdesign"); + } + pPool.clear(); + + for (SfxPoolItem* pDefault : pDefaults) + delete pDefault; + +} + + +sal_Bool SAL_CALL OReportController::attachModel(const uno::Reference< frame::XModel > & xModel) +{ + ::osl::MutexGuard aGuard( getMutex() ); + + uno::Reference< report::XReportDefinition > xReportDefinition( xModel, UNO_QUERY ); + if ( !xReportDefinition.is() ) + return false; + + uno::Reference< document::XUndoManagerSupplier > xTestSuppUndo( xModel, UNO_QUERY ); + if ( !xTestSuppUndo.is() ) + return false; + + m_xReportDefinition = xReportDefinition; + return true; +} + + +void OReportController::openSortingAndGroupingDialog() +{ + if ( !m_xReportDefinition.is() ) + return; + if (!m_xGroupsFloater) + { + m_xGroupsFloater = std::make_shared<OGroupsSortingDialog>(getFrameWeld(), !isEditable(), this); + SvtViewOptions aDlgOpt(EViewType::Window, OStringToOUString(m_xGroupsFloater->get_help_id(), RTL_TEXTENCODING_UTF8)); + if ( aDlgOpt.Exists() ) + m_xGroupsFloater->getDialog()->set_window_state(OUStringToOString(aDlgOpt.GetWindowState(), RTL_TEXTENCODING_ASCII_US)); + } + if (isUiVisible()) + { + if (!m_xGroupsFloater->getDialog()->get_visible()) + weld::DialogController::runAsync(m_xGroupsFloater, [this](sal_Int32 /*nResult*/) { m_xGroupsFloater.reset(); }); + else + m_xGroupsFloater->response(RET_CANCEL); + } +} + +sal_Int32 OReportController::getGroupPosition(const uno::Reference< report::XGroup >& _xGroup) +{ + return rptui::getPositionInIndexAccess(m_xReportDefinition->getGroups(),_xGroup); +} + + +void OReportController::Notify(SfxBroadcaster & /* _rBc */, SfxHint const & _rHint) +{ + const DlgEdHint* pDlgEdHint = dynamic_cast<const DlgEdHint*>(&_rHint); + if (!(pDlgEdHint && pDlgEdHint->GetKind() == RPTUI_HINT_SELECTIONCHANGED)) + return; + + const sal_Int32 nSelectionCount = getDesignView()->getMarkedObjectCount(); + if ( m_nSelectionCount != nSelectionCount ) + { + m_nSelectionCount = nSelectionCount; + InvalidateAll(); + } + lang::EventObject aEvent(*this); + m_aSelectionListeners.forEach( + [&aEvent] (uno::Reference<view::XSelectionChangeListener> const& xListener) { + return xListener->selectionChanged(aEvent); + }); +} + +void OReportController::executeMethodWithUndo(TranslateId pUndoStrId,const ::std::function<void(ODesignView *)>& _pMemfun) +{ + const OUString sUndoAction = RptResId(pUndoStrId); + UndoContext aUndoContext( getUndoManager(), sUndoAction ); + _pMemfun( getDesignView() ); + InvalidateFeature( SID_UNDO ); +} + +void OReportController::alignControlsWithUndo(TranslateId pUndoStrId, ControlModification _nControlModification, bool _bAlignAtSection) +{ + const OUString sUndoAction = RptResId(pUndoStrId); + UndoContext aUndoContext( getUndoManager(), sUndoAction ); + getDesignView()->alignMarkedObjects(_nControlModification,_bAlignAtSection); + InvalidateFeature( SID_UNDO ); +} + +void OReportController::shrinkSectionBottom(const uno::Reference<report::XSection>& _xSection) +{ + const sal_Int32 nElements = _xSection->getCount(); + if (nElements == 0) + { + // there are no elements + return; + } + const sal_Int32 nSectionHeight = _xSection->getHeight(); + sal_Int32 nMaxPositionY = 0; + uno::Reference< report::XReportComponent> xReportComponent; + + // for every component get its Y-position and compare it to the current Y-position + for (int i=0;i<nElements;i++) + { + xReportComponent.set(_xSection->getByIndex(i), uno::UNO_QUERY); + const sal_Int32 nReportComponentPositionY = xReportComponent->getPositionY(); + const sal_Int32 nReportComponentHeight = xReportComponent->getHeight(); + const sal_Int32 nReportComponentPositionYAndHeight = nReportComponentPositionY + nReportComponentHeight; + nMaxPositionY = std::max(nReportComponentPositionYAndHeight, nMaxPositionY); + } + // now we know the minimal Y-Position and maximal Y-Position + + if (nMaxPositionY > (nSectionHeight - 7) ) // Magic Number, we use a little bit less heights for right positioning + { + // the lowest position is already 0 + return; + } + _xSection->setHeight(nMaxPositionY); +} + +void OReportController::shrinkSectionTop(const uno::Reference<report::XSection>& _xSection) +{ + const sal_Int32 nElements = _xSection->getCount(); + if (nElements == 0) + { + // there are no elements + return; + } + + const sal_Int32 nSectionHeight = _xSection->getHeight(); + sal_Int32 nMinPositionY = nSectionHeight; + uno::Reference< report::XReportComponent> xReportComponent; + + // for every component get its Y-position and compare it to the current Y-position + for (int i=0;i<nElements;i++) + { + xReportComponent.set(_xSection->getByIndex(i), uno::UNO_QUERY); + const sal_Int32 nReportComponentPositionY = xReportComponent->getPositionY(); + nMinPositionY = std::min(nReportComponentPositionY, nMinPositionY); + } + // now we know the minimal Y-Position and maximal Y-Position + if (nMinPositionY == 0) + { + // the lowest position is already 0 + return; + } + for (int i=0;i<nElements;i++) + { + xReportComponent.set(_xSection->getByIndex(i), uno::UNO_QUERY); + const sal_Int32 nReportComponentPositionY = xReportComponent->getPositionY(); + const sal_Int32 nNewPositionY = nReportComponentPositionY - nMinPositionY; + xReportComponent->setPositionY(nNewPositionY); + } + const sal_Int32 nNewSectionHeight = nSectionHeight - nMinPositionY; + _xSection->setHeight(nNewSectionHeight); +} + +void OReportController::shrinkSection(TranslateId pUndoStrId, const uno::Reference<report::XSection>& _xSection, sal_Int32 _nSid) +{ + if ( _xSection.is() ) + { + const OUString sUndoAction = RptResId(pUndoStrId); + UndoContext aUndoContext( getUndoManager(), sUndoAction ); + + if (_nSid == SID_SECTION_SHRINK) + { + shrinkSectionTop(_xSection); + shrinkSectionBottom(_xSection); + } + else if (_nSid == SID_SECTION_SHRINK_TOP) + { + shrinkSectionTop(_xSection); + } + else if (_nSid == SID_SECTION_SHRINK_BOTTOM) + { + shrinkSectionBottom(_xSection); + } + } + + InvalidateFeature( SID_UNDO ); +} + + +uno::Any SAL_CALL OReportController::getViewData() +{ + ::osl::MutexGuard aGuard( getMutex() ); + + const sal_Int32 nCommandIDs[] = + { + SID_GRID_VISIBLE, + SID_GRID_USE, + SID_HELPLINES_MOVE, + SID_RULER, + SID_SHOW_PROPERTYBROWSER, + SID_PROPERTYBROWSER_LAST_PAGE, + SID_SPLIT_POSITION + }; + + ::comphelper::NamedValueCollection aCommandProperties; + for (sal_Int32 nCommandID : nCommandIDs) + { + const FeatureState aFeatureState = GetState( nCommandID ); + + OUString sCommandURL( getURLForId( nCommandID ).Main ); + OSL_ENSURE( sCommandURL.startsWith( ".uno:" ), "OReportController::getViewData: illegal command URL!" ); + sCommandURL = sCommandURL.copy( 5 ); + + Any aCommandState; + if ( !!aFeatureState.bChecked ) + aCommandState <<= *aFeatureState.bChecked; + else if ( aFeatureState.aValue.hasValue() ) + aCommandState = aFeatureState.aValue; + + aCommandProperties.put( sCommandURL, aCommandState ); + } + + ::comphelper::NamedValueCollection aViewData; + aViewData.put( "CommandProperties", aCommandProperties.getPropertyValues() ); + + if ( getDesignView() ) + { + ::std::vector<sal_uInt16> aCollapsedPositions; + getDesignView()->fillCollapsedSections(aCollapsedPositions); + if ( !aCollapsedPositions.empty() ) + { + uno::Sequence<beans::PropertyValue> aCollapsedSections(aCollapsedPositions.size()); + beans::PropertyValue* pCollapsedIter = aCollapsedSections.getArray(); + sal_Int32 i = 1; + for (const auto& rPos : aCollapsedPositions) + { + pCollapsedIter->Name = PROPERTY_SECTION + OUString::number(i); + pCollapsedIter->Value <<= static_cast<sal_Int32>(rPos); + ++pCollapsedIter; + ++i; + } + + aViewData.put( "CollapsedSections", aCollapsedSections ); + } + + OSectionWindow* pSectionWindow = getDesignView()->getMarkedSection(); + if ( pSectionWindow ) + { + aViewData.put( "MarkedSection", static_cast<sal_Int32>(pSectionWindow->getReportSection().getPage()->GetPageNum()) ); + } + } + + aViewData.put( "ZoomFactor", m_nZoomValue ); + return uno::Any( aViewData.getPropertyValues() ); +} + +void SAL_CALL OReportController::restoreViewData(const uno::Any& i_data) +{ + ::osl::MutexGuard aGuard( getMutex() ); + + try + { + const ::comphelper::NamedValueCollection aViewData( i_data ); + + m_aCollapsedSections = aViewData.getOrDefault( "CollapsedSections", m_aCollapsedSections ); + m_nPageNum = aViewData.getOrDefault( "MarkedSection", m_nPageNum ); + m_nZoomValue = aViewData.getOrDefault( "ZoomFactor", m_nZoomValue ); + // TODO: setting those 3 members is not enough - in theory, restoreViewData can be called when the + // view is fully alive, so we need to reflect those 3 values in the view. + // (At the moment, the method is called only during construction phase) + + + ::comphelper::NamedValueCollection aCommandProperties( aViewData.get( "CommandProperties" ) ); + const ::std::vector< OUString > aCommandNames( aCommandProperties.getNames() ); + + for ( const auto& rCommandName : aCommandNames ) + { + const Any& rCommandValue = aCommandProperties.get( rCommandName ); + if ( !rCommandValue.hasValue() ) + continue; + + if ( getView() ) + { + util::URL aCommand; + aCommand.Complete = ".uno:" + rCommandName; + + executeUnChecked( aCommand, { comphelper::makePropertyValue("Value", rCommandValue) } ); + } + else + { + if ( rCommandName == "ShowRuler" ) + OSL_VERIFY( rCommandValue >>= m_bShowRuler ); + else if ( rCommandName == "HelplinesMove" ) + OSL_VERIFY( rCommandValue >>= m_bHelplinesMove ); + else if ( rCommandName == "GridVisible" ) + OSL_VERIFY( rCommandValue >>= m_bGridVisible ); + else if ( rCommandName == "GridUse" ) + OSL_VERIFY( rCommandValue >>= m_bGridUse ); + else if ( rCommandName == "ControlProperties" ) + OSL_VERIFY( rCommandValue >>= m_bShowProperties ); + else if ( rCommandName == "LastPropertyBrowserPage" ) + OSL_VERIFY( rCommandValue >>= m_sLastActivePage ); + else if ( rCommandName == "SplitPosition" ) + OSL_VERIFY( rCommandValue >>= m_nSplitPos ); + } + } + } + catch(const IllegalArgumentException&) + { + DBG_UNHANDLED_EXCEPTION("reportdesign"); + } +} + +Reference<XFrame> OReportController::getXFrame() +{ + if ( !m_xFrameLoader.is() ) + { + m_xFrameLoader.set( frame::Desktop::create(m_xContext) ); + } + const sal_Int32 nFrameSearchFlag = frame::FrameSearchFlag::TASKS | frame::FrameSearchFlag::CREATE; + Reference<XFrame> xFrame = m_xFrameLoader->findFrame("_blank",nFrameSearchFlag); + return xFrame; +} + + +uno::Reference<frame::XModel> OReportController::executeReport() +{ + OSL_ENSURE(m_xReportDefinition.is(),"Where is my report?"); + + uno::Reference<frame::XModel> xModel; + if ( m_xReportDefinition.is() ) + { + TranslateId pErrorId = RID_ERR_NO_COMMAND; + bool bEnabled = !m_xReportDefinition->getCommand().isEmpty(); + if ( bEnabled ) + { + bEnabled = false; + const sal_uInt16 nCount = m_aReportModel->GetPageCount(); + sal_uInt16 i = 0; + for (; i < nCount && !bEnabled ; ++i) + { + const SdrPage* pPage = m_aReportModel->GetPage(i); + bEnabled = pPage->GetObjCount() != 0; + } + if ( !bEnabled ) + pErrorId = RID_ERR_NO_OBJECTS; + } + + dbtools::SQLExceptionInfo aInfo; + if ( !bEnabled ) + { + sdb::SQLContext aFirstMessage; + OUString sInfo = RptResId( pErrorId ); + aFirstMessage.Message = sInfo; + aInfo = aFirstMessage; + if ( isEditable() ) + { + sal_uInt16 nCommand = 0; + if (pErrorId != RID_ERR_NO_COMMAND) + { + if ( !m_bShowProperties ) + executeUnChecked(SID_SHOW_PROPERTYBROWSER, {}); + + m_sLastActivePage = "Data"; + getDesignView()->setCurrentPage(m_sLastActivePage); + nCommand = SID_SELECT_REPORT; + } + else if ( getDesignView() && !getDesignView()->isAddFieldVisible() ) + { + nCommand = SID_FM_ADD_FIELD; + } + if ( nCommand ) + { + executeUnChecked(nCommand, {}); + } + } + } + else + { + m_bInGeneratePreview = true; + try + { + weld::WaitObject aWait(getFrameWeld()); // cursor + if ( !m_xReportEngine.is() ) + m_xReportEngine.set( report::ReportEngine::create(m_xContext) ); + m_xReportEngine->setReportDefinition(m_xReportDefinition); + m_xReportEngine->setActiveConnection(getConnection()); + Reference<XFrame> xFrame = getXFrame(); + xModel = m_xReportEngine->createDocumentAlive(xFrame); + } + catch(const sdbc::SQLException&) + { // SQLExceptions and derived exceptions must not be translated + aInfo = ::cppu::getCaughtException(); + } + catch(const uno::Exception& e) + { + uno::Any aCaughtException( ::cppu::getCaughtException() ); + + // our first message says: we caught an exception + sdb::SQLContext aFirstMessage; + OUString sInfo(RptResId(RID_STR_CAUGHT_FOREIGN_EXCEPTION)); + sInfo = sInfo.replaceAll("$type$", aCaughtException.getValueTypeName()); + aFirstMessage.Message = sInfo; + + // our second message: the message of the exception we caught + sdbc::SQLException aSecondMessage; + aSecondMessage.Message = e.Message; + aSecondMessage.Context = e.Context; + + // maybe our third message: the message which is wrapped in the exception we caught + sdbc::SQLException aThirdMessage; + lang::WrappedTargetException aWrapped; + if ( aCaughtException >>= aWrapped ) + { + aThirdMessage.Message = aWrapped.Message; + aThirdMessage.Context = aWrapped.Context; + } + + if ( !aThirdMessage.Message.isEmpty() ) + aSecondMessage.NextException <<= aThirdMessage; + aFirstMessage.NextException <<= aSecondMessage; + + aInfo = aFirstMessage; + } + if (aInfo.isValid()) + { + const OUString suSQLContext = RptResId( RID_STR_COULD_NOT_CREATE_REPORT ); + aInfo.prepend(suSQLContext); + } + m_bInGeneratePreview = false; + } + + if (aInfo.isValid()) + { + showError(aInfo); + } + } + return xModel; +} + +uno::Reference< frame::XModel > SAL_CALL OReportController::getModel() +{ + return m_xReportDefinition; +} + +uno::Reference< sdbc::XRowSet > const & OReportController::getRowSet() +{ + OSL_PRECOND( m_xReportDefinition.is(), "OReportController::getRowSet: no report definition?!" ); + + if ( m_xRowSet.is() || !m_xReportDefinition.is() ) + return m_xRowSet; + + try + { + uno::Reference< sdbc::XRowSet > xRowSet( + getORB()->getServiceManager()->createInstanceWithContext("com.sun.star.sdb.RowSet", getORB()), + uno::UNO_QUERY ); + uno::Reference< beans::XPropertySet> xRowSetProp( xRowSet, uno::UNO_QUERY_THROW ); + + xRowSetProp->setPropertyValue( PROPERTY_ACTIVECONNECTION, uno::Any( getConnection() ) ); + xRowSetProp->setPropertyValue( PROPERTY_APPLYFILTER, uno::Any( true ) ); + + auto aNoConverter = std::make_shared<AnyConverter>(); + TPropertyNamePair aPropertyMediation; + aPropertyMediation.emplace( PROPERTY_COMMAND, TPropertyConverter(PROPERTY_COMMAND,aNoConverter) ); + aPropertyMediation.emplace( PROPERTY_COMMANDTYPE, TPropertyConverter(PROPERTY_COMMANDTYPE,aNoConverter) ); + aPropertyMediation.emplace( PROPERTY_ESCAPEPROCESSING, TPropertyConverter(PROPERTY_ESCAPEPROCESSING,aNoConverter) ); + aPropertyMediation.emplace( PROPERTY_FILTER, TPropertyConverter(PROPERTY_FILTER,aNoConverter) ); + + m_xRowSetMediator = new OPropertyMediator( m_xReportDefinition, xRowSetProp, std::move(aPropertyMediation) ); + m_xRowSet = xRowSet; + } + catch(const uno::Exception&) + { + DBG_UNHANDLED_EXCEPTION("reportdesign"); + } + + return m_xRowSet; +} + +void OReportController::insertGraphic() +{ + const OUString sTitle(RptResId(RID_STR_IMPORT_GRAPHIC)); + // build some arguments for the upcoming dialog + try + { + uno::Reference< report::XSection> xSection = getDesignView()->getCurrentSection(); + ::sfx2::FileDialogHelper aDialog(ui::dialogs::TemplateDescription::FILEOPEN_LINK_PREVIEW, FileDialogFlags::Graphic, getFrameWeld()); + aDialog.SetContext(sfx2::FileDialogHelper::ReportInsertImage); + aDialog.SetTitle( sTitle ); + + uno::Reference< ui::dialogs::XFilePickerControlAccess > xController(aDialog.GetFilePicker(), UNO_QUERY_THROW); + xController->setValue(ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_PREVIEW, 0, css::uno::Any(true)); + xController->enableControl(ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_LINK, false/*sal_True*/); + xController->setValue( ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_LINK, 0, css::uno::Any(true) ); + + if ( ERRCODE_NONE == aDialog.Execute() ) + { + bool bLink = true; + xController->getValue( ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_LINK, 0) >>= bLink; + uno::Sequence<beans::PropertyValue> aArgs( comphelper::InitPropertySequence({ + { PROPERTY_IMAGEURL, Any(aDialog.GetPath()) }, + { PROPERTY_PRESERVEIRI, Any(bLink) } + })); + createControl(aArgs,xSection,OUString(),SdrObjKind::ReportDesignImageControl); + } + } + catch(const Exception&) + { + DBG_UNHANDLED_EXCEPTION("reportdesign"); + } +} + + +sal_Bool SAL_CALL OReportController::select( const Any& aSelection ) +{ + ::osl::MutexGuard aGuard( getMutex() ); + if ( !getDesignView() ) + return true; + + getDesignView()->unmarkAllObjects(); + getDesignView()->SetMode(DlgEdMode::Select); + + uno::Sequence< uno::Reference<report::XReportComponent> > aElements; + if ( aSelection >>= aElements ) + { + if ( aElements.hasElements() ) + getDesignView()->showProperties(uno::Reference<uno::XInterface>(aElements[0],uno::UNO_QUERY)); + getDesignView()->setMarked(aElements, true); + } + else + { + uno::Reference<uno::XInterface> xObject(aSelection,uno::UNO_QUERY); + uno::Reference<report::XReportComponent> xProp(xObject,uno::UNO_QUERY); + if ( xProp.is() ) + { + getDesignView()->showProperties(xObject); + aElements = { xProp }; + getDesignView()->setMarked(aElements, true); + } + else + { + uno::Reference<report::XSection> xSection(aSelection,uno::UNO_QUERY); + if ( !xSection.is() && xObject.is() ) + getDesignView()->showProperties(xObject); + getDesignView()->setMarked(xSection,xSection.is()); + } + } + InvalidateAll(); + return true; +} + +Any SAL_CALL OReportController::getSelection( ) +{ + ::osl::MutexGuard aGuard( getMutex() ); + Any aRet; + if ( getDesignView() ) + { + aRet = getDesignView()->getCurrentlyShownProperty(); + if ( !aRet.hasValue() ) + aRet <<= getDesignView()->getCurrentSection(); + } + return aRet; +} + +void SAL_CALL OReportController::addSelectionChangeListener( const Reference< view::XSelectionChangeListener >& Listener ) +{ + m_aSelectionListeners.addInterface( Listener ); +} + +void SAL_CALL OReportController::removeSelectionChangeListener( const Reference< view::XSelectionChangeListener >& Listener ) +{ + m_aSelectionListeners.removeInterface( Listener ); +} + +void OReportController::createNewFunction(const uno::Any& _aValue) +{ + uno::Reference< container::XIndexContainer> xFunctions(_aValue,uno::UNO_QUERY_THROW); + const OUString sNewName = RptResId(RID_STR_FUNCTION); + uno::Reference< report::XFunction> xFunction(report::Function::create(m_xContext)); + xFunction->setName(sNewName); + // the call below will also create an undo action -> listener + xFunctions->insertByIndex(xFunctions->getCount(),uno::Any(xFunction)); +} + +IMPL_LINK_NOARG( OReportController, OnExecuteReport, void*, void ) +{ + executeReport(); +} + +void OReportController::createControl(const Sequence< PropertyValue >& _aArgs,const uno::Reference< report::XSection>& _xSection,const OUString& _sFunction,SdrObjKind _nObjectId) +{ + SequenceAsHashMap aMap(_aArgs); + getDesignView()->setMarked(_xSection, true); + OSectionWindow* pSectionWindow = getDesignView()->getMarkedSection(); + if ( !pSectionWindow ) + return; + + OSL_ENSURE(pSectionWindow->getReportSection().getSection() == _xSection,"Invalid section after marking the correct one."); + + sal_Int32 nLeftMargin = getStyleProperty<sal_Int32>(m_xReportDefinition,PROPERTY_LEFTMARGIN); + const sal_Int32 nRightMargin = getStyleProperty<sal_Int32>(m_xReportDefinition,PROPERTY_RIGHTMARGIN); + const sal_Int32 nPaperWidth = getStyleProperty<awt::Size>(m_xReportDefinition,PROPERTY_PAPERSIZE).Width - nRightMargin; + awt::Point aPos = aMap.getUnpackedValueOrDefault(PROPERTY_POSITION,awt::Point(nLeftMargin,0)); + if ( aPos.X < nLeftMargin ) + aPos.X = nLeftMargin; + + SdrObject* pNewControl = nullptr; + uno::Reference< report::XReportComponent> xShapeProp; + if ( _nObjectId == SdrObjKind::CustomShape ) + { + pNewControl = SdrObjFactory::MakeNewObject( + *m_aReportModel, + SdrInventor::ReportDesign, + _nObjectId); + xShapeProp.set(pNewControl->getUnoShape(),uno::UNO_QUERY); + OUString sCustomShapeType = getDesignView()->GetInsertObjString(); + if ( sCustomShapeType.isEmpty() ) + sCustomShapeType = "diamond"; + OReportSection::createDefault(sCustomShapeType,pNewControl); + pNewControl->SetLogicRect(tools::Rectangle(3000,500,6000,3500)); // switch height and width + } + else if ( _nObjectId == SdrObjKind::OLE2 || SdrObjKind::ReportDesignSubReport == _nObjectId ) + { + pNewControl = SdrObjFactory::MakeNewObject( + *m_aReportModel, + SdrInventor::ReportDesign, + _nObjectId); + + pNewControl->SetLogicRect(tools::Rectangle(3000,500,8000,5500)); // switch height and width + xShapeProp.set(pNewControl->getUnoShape(),uno::UNO_QUERY_THROW); + OOle2Obj* pObj = dynamic_cast<OOle2Obj*>(pNewControl); + if ( pObj && !pObj->IsEmpty() ) + { + pObj->initializeChart(getModel()); + } + } + else + { + std::unique_ptr<SdrUnoObj, SdrObjectFreeOp> pLabel; + std::unique_ptr<SdrUnoObj, SdrObjectFreeOp> pControl; + + FmFormView::createControlLabelPair( + getDesignView()->GetOutDev(), + nLeftMargin, + 0, + nullptr, + nullptr, + _nObjectId, + SdrInventor::ReportDesign, + SdrObjKind::ReportDesignFixedText, + + // tdf#118963 Need a SdrModel for SdrObject creation. Dereferencing + // m_aReportModel seems pretty safe, it's done in other places, initialized + // in impl_initialize and throws a RuntimeException if not existing. + *m_aReportModel, + + pLabel, + pControl); + + pLabel.reset(); + + pNewControl = pControl.release(); + OUnoObject* pObj = dynamic_cast<OUnoObject*>(pNewControl); + assert(pObj); + if(pObj) + { + uno::Reference<beans::XPropertySet> xUnoProp(pObj->GetUnoControlModel(),uno::UNO_QUERY); + xShapeProp.set(pObj->getUnoShape(),uno::UNO_QUERY); + uno::Reference<beans::XPropertySetInfo> xShapeInfo = xShapeProp->getPropertySetInfo(); + uno::Reference<beans::XPropertySetInfo> xInfo = xUnoProp->getPropertySetInfo(); + + const OUString sProps[] = { OUString(PROPERTY_NAME) + ,OUString(PROPERTY_FONTDESCRIPTOR) + ,OUString(PROPERTY_FONTDESCRIPTORASIAN) + ,OUString(PROPERTY_FONTDESCRIPTORCOMPLEX) + ,OUString(PROPERTY_ORIENTATION) + ,OUString(PROPERTY_BORDER) + ,OUString(PROPERTY_FORMATSSUPPLIER) + ,OUString(PROPERTY_BACKGROUNDCOLOR) + }; + for(const auto & sProp : sProps) + { + if ( xInfo->hasPropertyByName(sProp) && xShapeInfo->hasPropertyByName(sProp) ) + xUnoProp->setPropertyValue(sProp,xShapeProp->getPropertyValue(sProp)); + } + + if ( xInfo->hasPropertyByName(PROPERTY_BORDER) && xShapeInfo->hasPropertyByName(PROPERTY_CONTROLBORDER) ) + xUnoProp->setPropertyValue(PROPERTY_BORDER,xShapeProp->getPropertyValue(PROPERTY_CONTROLBORDER)); + + + if ( xInfo->hasPropertyByName(PROPERTY_DATAFIELD) && !_sFunction.isEmpty() ) + { + ReportFormula aFunctionFormula( ReportFormula::Expression, _sFunction ); + xUnoProp->setPropertyValue( PROPERTY_DATAFIELD, uno::Any( aFunctionFormula.getCompleteFormula() ) ); + } + + sal_Int32 nFormatKey = aMap.getUnpackedValueOrDefault(PROPERTY_FORMATKEY,sal_Int32(0)); + if ( nFormatKey && xInfo->hasPropertyByName(PROPERTY_FORMATKEY) ) + xUnoProp->setPropertyValue( PROPERTY_FORMATKEY, uno::Any( nFormatKey ) ); + + OUString sUrl = aMap.getUnpackedValueOrDefault(PROPERTY_IMAGEURL,OUString()); + if ( !sUrl.isEmpty() && xInfo->hasPropertyByName(PROPERTY_IMAGEURL) ) + xUnoProp->setPropertyValue( PROPERTY_IMAGEURL, uno::Any( sUrl ) ); + + pObj->CreateMediator(true); + + if ( _nObjectId == SdrObjKind::ReportDesignFixedText ) // special case for fixed text + xUnoProp->setPropertyValue(PROPERTY_LABEL,uno::Any(OUnoObject::GetDefaultName(pObj))); + else if ( _nObjectId == SdrObjKind::ReportDesignVerticalFixedLine ) + { + awt::Size aOlSize = xShapeProp->getSize(); + xShapeProp->setSize(awt::Size(aOlSize.Height,aOlSize.Width)); // switch height and width + } + } + } + + const sal_Int32 nShapeWidth = aMap.getUnpackedValueOrDefault(PROPERTY_WIDTH,xShapeProp->getWidth()); + if ( nShapeWidth != xShapeProp->getWidth() ) + xShapeProp->setWidth( nShapeWidth ); + + const bool bChangedPos = (aPos.X + nShapeWidth) > nPaperWidth; + if ( bChangedPos ) + aPos.X = nPaperWidth - nShapeWidth; + xShapeProp->setPosition(aPos); + + correctOverlapping(pNewControl,pSectionWindow->getReportSection()); +} + +void OReportController::createDateTime(const Sequence< PropertyValue >& _aArgs) +{ + getDesignView()->unmarkAllObjects(); + + const OUString sUndoAction(RptResId(RID_STR_UNDO_INSERT_CONTROL)); + UndoContext aUndoContext( getUndoManager(), sUndoAction ); + + SequenceAsHashMap aMap(_aArgs); + aMap.createItemIfMissing(PROPERTY_FORMATKEY,aMap.getUnpackedValueOrDefault(PROPERTY_FORMATKEYDATE,sal_Int32(0))); + + uno::Reference< report::XSection> xSection = aMap.getUnpackedValueOrDefault(PROPERTY_SECTION,uno::Reference< report::XSection>()); + OUString sFunction; + + bool bDate = aMap.getUnpackedValueOrDefault(PROPERTY_DATE_STATE, false); + if ( bDate ) + { + sFunction = "TODAY()"; + createControl(aMap.getAsConstPropertyValueList(),xSection,sFunction); + } + bool bTime = aMap.getUnpackedValueOrDefault(PROPERTY_TIME_STATE, false); + if ( bTime ) + { + sFunction = "TIMEVALUE(NOW())"; + aMap[PROPERTY_FORMATKEY] <<= aMap.getUnpackedValueOrDefault(PROPERTY_FORMATKEYTIME,sal_Int32(0)); + createControl(aMap.getAsConstPropertyValueList(),xSection,sFunction); + } +} + +void OReportController::createPageNumber(const Sequence< PropertyValue >& _aArgs) +{ + getDesignView()->unmarkAllObjects(); + + const OUString sUndoAction(RptResId(RID_STR_UNDO_INSERT_CONTROL)); + UndoContext aUndoContext( getUndoManager(), sUndoAction ); + + if ( !m_xReportDefinition->getPageHeaderOn() ) + { + uno::Sequence< beans::PropertyValue > aArgs; + executeChecked(SID_PAGEHEADERFOOTER,aArgs); + } + + SequenceAsHashMap aMap(_aArgs); + bool bStateOfPage = aMap.getUnpackedValueOrDefault(PROPERTY_STATE, false); + + OUString sFunction( RptResId(STR_RPT_PN_PAGE) ); + sFunction = sFunction.replaceFirst("#PAGENUMBER#", "PageNumber()"); + + if ( bStateOfPage ) + { + sFunction += RptResId(STR_RPT_PN_PAGE_OF); + sFunction = sFunction.replaceFirst("#PAGECOUNT#", "PageCount()"); + } + + bool bInPageHeader = aMap.getUnpackedValueOrDefault(PROPERTY_PAGEHEADERON, true); + createControl(_aArgs,bInPageHeader ? m_xReportDefinition->getPageHeader() : m_xReportDefinition->getPageFooter(),sFunction); +} + + +void OReportController::addPairControls(const Sequence< PropertyValue >& aArgs) +{ + getDesignView()->unmarkAllObjects(); + + // the FormatKey determines which field is required + OSectionWindow* pSectionWindow[2]; + pSectionWindow[0] = getDesignView()->getMarkedSection(); + + if ( !pSectionWindow[0] ) + { + select(uno::Any(m_xReportDefinition->getDetail())); + pSectionWindow[0] = getDesignView()->getMarkedSection(); + if ( !pSectionWindow[0] ) + return; + } + + uno::Reference<report::XSection> xCurrentSection = getDesignView()->getCurrentSection(); + UndoContext aUndoContext(getUndoManager(), RptResId(RID_STR_UNDO_INSERT_CONTROL)); + + try + { + bool bHandleOnlyOne = false; + for(const PropertyValue& rArg : aArgs) + { + if (bHandleOnlyOne) + break; + Sequence< PropertyValue > aValue; + if ( !(rArg.Value >>= aValue) ) + { // the sequence has only one element which already contains the descriptor + bHandleOnlyOne = true; + aValue = aArgs; + } + svx::ODataAccessDescriptor aDescriptor(aValue); + SequenceAsHashMap aMap(aValue); + uno::Reference<report::XSection> xSection = aMap.getUnpackedValueOrDefault("Section",xCurrentSection); + uno::Reference<report::XReportDefinition> xReportDefinition = xSection->getReportDefinition(); + + getDesignView()->setMarked(xSection, true); + pSectionWindow[0] = getDesignView()->getMarkedSection(); + + sal_Int32 nLeftMargin = getStyleProperty<sal_Int32>(m_xReportDefinition,PROPERTY_LEFTMARGIN); + awt::Point aPos = aMap.getUnpackedValueOrDefault(PROPERTY_POSITION,awt::Point(nLeftMargin,0)); + if ( aPos.X < nLeftMargin ) + aPos.X = nLeftMargin; + + // LLA: new feature, add the Label in dependency of the given DND_ACTION one section up, normal or one section down + sal_Int8 nDNDAction = aMap.getUnpackedValueOrDefault("DNDAction", sal_Int8(0)); + pSectionWindow[1] = pSectionWindow[0]; + bool bLabelAboveTextField = nDNDAction == DND_ACTION_COPY; + if ( bLabelAboveTextField || nDNDAction == DND_ACTION_LINK ) + { + // Add the Label one Section up + pSectionWindow[1] = getDesignView()->getMarkedSection(bLabelAboveTextField ? PREVIOUS : POST); + if (!pSectionWindow[1]) + { + // maybe out of bounds + pSectionWindow[1] = pSectionWindow[0]; + } + } + // clear all selections + getDesignView()->unmarkAllObjects(); + + uno::Reference< beans::XPropertySet > xField( aDescriptor[ svx::DataAccessDescriptorProperty::ColumnObject ], uno::UNO_QUERY ); + uno::Reference< lang::XComponent > xHoldAlive; + if ( !xField.is() ) + { + OUString sCommand; + OUString sColumnName; + sal_Int32 nCommandType( -1 ); + OSL_VERIFY( aDescriptor[ svx::DataAccessDescriptorProperty::Command ] >>= sCommand ); + OSL_VERIFY( aDescriptor[ svx::DataAccessDescriptorProperty::ColumnName ] >>= sColumnName ); + OSL_VERIFY( aDescriptor[ svx::DataAccessDescriptorProperty::CommandType ] >>= nCommandType ); + + uno::Reference< container::XNameAccess > xColumns; + uno::Reference< sdbc::XConnection > xConnection( getConnection() ); + if ( !sCommand.isEmpty() && nCommandType != -1 && !sColumnName.isEmpty() && xConnection.is() ) + { + if ( xReportDefinition->getCommand().isEmpty() ) + { + xReportDefinition->setCommand(sCommand); + xReportDefinition->setCommandType(nCommandType); + } + + xColumns = dbtools::getFieldsByCommandDescriptor(xConnection,nCommandType,sCommand,xHoldAlive); + if ( xColumns.is() && xColumns->hasByName(sColumnName) ) + xField.set( xColumns->getByName( sColumnName ), uno::UNO_QUERY ); + } + + if ( !xField.is() ) + { + #if OSL_DEBUG_LEVEL > 0 + try + { + uno::Reference< beans::XPropertySet > xRowSetProps( getRowSet(), UNO_QUERY_THROW ); + OUString sRowSetCommand; + sal_Int32 nRowSetCommandType( -1 ); + OSL_VERIFY( xRowSetProps->getPropertyValue( PROPERTY_COMMAND ) >>= sRowSetCommand ); + OSL_VERIFY( xRowSetProps->getPropertyValue( PROPERTY_COMMANDTYPE ) >>= nRowSetCommandType ); + OSL_ENSURE( ( sRowSetCommand == sCommand ) && ( nCommandType == nRowSetCommandType ), + "OReportController::addPairControls: this only works for a data source which equals our current settings!" ); + // if this asserts, then either our row set and our report definition are not in sync, or somebody + // requested the creation of a control/pair for another data source than what our report + // definition is bound to - which is not supported for the parameters case, since we + // can retrieve parameters from the RowSet only. + } + catch(const Exception&) + { + DBG_UNHANDLED_EXCEPTION("reportdesign"); + } + #endif + + // no column name - perhaps a parameter name? + uno::Reference< sdb::XParametersSupplier > xSuppParam( getRowSet(), uno::UNO_QUERY_THROW ); + uno::Reference< container::XIndexAccess > xParams( xSuppParam->getParameters(), uno::UNO_SET_THROW ); + sal_Int32 nParamCount( xParams->getCount() ); + for ( sal_Int32 i=0; i<nParamCount; ++i) + { + uno::Reference< beans::XPropertySet > xParamCol( xParams->getByIndex(i), uno::UNO_QUERY_THROW ); + OUString sParamName; + OSL_VERIFY( xParamCol->getPropertyValue("Name") >>= sParamName ); + if ( sParamName == sColumnName ) + { + xField = xParamCol; + break; + } + } + } + } + if ( !xField.is() ) + continue; + + SdrObjKind nOBJID = SdrObjKind::NONE; + sal_Int32 nDataType = sdbc::DataType::BINARY; + xField->getPropertyValue(PROPERTY_TYPE) >>= nDataType; + switch ( nDataType ) + { + case sdbc::DataType::BINARY: + case sdbc::DataType::VARBINARY: + case sdbc::DataType::LONGVARBINARY: + nOBJID = SdrObjKind::ReportDesignImageControl; + break; + default: + nOBJID = SdrObjKind::ReportDesignFormattedField; + break; + } + + if ( nOBJID == SdrObjKind::NONE ) + continue; + + Reference< util::XNumberFormatsSupplier > xSupplier = getReportNumberFormatter()->getNumberFormatsSupplier(); + if ( !xSupplier.is() ) + continue; + + Reference< XNumberFormats > xNumberFormats(xSupplier->getNumberFormats()); + std::unique_ptr<SdrUnoObj, SdrObjectFreeOp> pControl[2]; + const sal_Int32 nRightMargin = getStyleProperty<sal_Int32>(m_xReportDefinition,PROPERTY_RIGHTMARGIN); + const sal_Int32 nPaperWidth = getStyleProperty<awt::Size>(m_xReportDefinition,PROPERTY_PAPERSIZE).Width - nRightMargin; + OSectionView* pSectionViews[2]; + pSectionViews[0] = &pSectionWindow[1]->getReportSection().getSectionView(); + pSectionViews[1] = &pSectionWindow[0]->getReportSection().getSectionView(); + + // find this in svx + FmFormView::createControlLabelPair( + getDesignView()->GetOutDev(), + nLeftMargin, + 0, + xField, + xNumberFormats, + nOBJID, + SdrInventor::ReportDesign, + SdrObjKind::ReportDesignFixedText, + + // tdf#118963 Need a SdrModel for SdrObject creation. Dereferencing + // m_aReportModel seems pretty safe, it's done in other places, initialized + // in impl_initialize and throws a RuntimeException if not existing. + *m_aReportModel, + + pControl[0], + pControl[1]); + + if ( pControl[0] && pControl[1] ) + { + SdrPageView* pPgViews[2]; + pPgViews[0] = pSectionViews[0]->GetSdrPageView(); + pPgViews[1] = pSectionViews[1]->GetSdrPageView(); + if ( pPgViews[0] && pPgViews[1] ) + { + OUString sDefaultName; + size_t i = 0; + OUnoObject* pObjs[2]; + for(i = 0; i < SAL_N_ELEMENTS(pControl); ++i) + { + pObjs[i] = dynamic_cast<OUnoObject*>(pControl[i].get()); + assert(pObjs[i]); + uno::Reference<beans::XPropertySet> xUnoProp(pObjs[i]->GetUnoControlModel(),uno::UNO_QUERY_THROW); + uno::Reference< report::XReportComponent> xShapeProp(pObjs[i]->getUnoShape(),uno::UNO_QUERY_THROW); + xUnoProp->setPropertyValue(PROPERTY_NAME,xShapeProp->getPropertyValue(PROPERTY_NAME)); + + uno::Reference<beans::XPropertySetInfo> xShapeInfo = xShapeProp->getPropertySetInfo(); + uno::Reference<beans::XPropertySetInfo> xInfo = xUnoProp->getPropertySetInfo(); + const OUString sProps[] = { OUString(PROPERTY_FONTDESCRIPTOR) + ,OUString(PROPERTY_FONTDESCRIPTORASIAN) + ,OUString(PROPERTY_FONTDESCRIPTORCOMPLEX) + ,OUString(PROPERTY_BORDER) + ,OUString(PROPERTY_BACKGROUNDCOLOR) + }; + for(const auto & sProp : sProps) + { + if ( xInfo->hasPropertyByName(sProp) && xShapeInfo->hasPropertyByName(sProp) ) + xUnoProp->setPropertyValue(sProp,xShapeProp->getPropertyValue(sProp)); + } + if ( xInfo->hasPropertyByName(PROPERTY_DATAFIELD) ) + { + OUString sName; + xUnoProp->getPropertyValue(PROPERTY_DATAFIELD) >>= sName; + sDefaultName = sName; + xUnoProp->setPropertyValue(PROPERTY_NAME,uno::Any(sDefaultName)); + + ReportFormula aFormula( ReportFormula::Field, sName ); + xUnoProp->setPropertyValue( PROPERTY_DATAFIELD, uno::Any( aFormula.getCompleteFormula() ) ); + } + + if ( xInfo->hasPropertyByName(PROPERTY_BORDER) && xShapeInfo->hasPropertyByName(PROPERTY_CONTROLBORDER) ) + xUnoProp->setPropertyValue(PROPERTY_BORDER,xShapeProp->getPropertyValue(PROPERTY_CONTROLBORDER)); + + pObjs[i]->CreateMediator(true); + + const sal_Int32 nShapeWidth = xShapeProp->getWidth(); + const bool bChangedPos = (aPos.X + nShapeWidth) > nPaperWidth; + if ( bChangedPos ) + aPos.X = nPaperWidth - nShapeWidth; + xShapeProp->setPosition(aPos); + if ( bChangedPos ) + aPos.Y += xShapeProp->getHeight(); + aPos.X += nShapeWidth; + } + OUString sLabel; + if ( xField->getPropertySetInfo()->hasPropertyByName(PROPERTY_LABEL) ) + xField->getPropertyValue(PROPERTY_LABEL) >>= sLabel; + + if (pSectionViews[0] != pSectionViews[1] && + nOBJID == SdrObjKind::ReportDesignFormattedField) // we want this nice feature only at FORMATTEDFIELD + { + uno::Reference< report::XReportComponent> xShapePropLabel(pObjs[0]->getUnoShape(),uno::UNO_QUERY_THROW); + uno::Reference< report::XReportComponent> xShapePropTextField(pObjs[1]->getUnoShape(),uno::UNO_QUERY_THROW); + if ( !sLabel.isEmpty() ) + xShapePropTextField->setName(sLabel); + awt::Point aPosLabel = xShapePropLabel->getPosition(); + awt::Point aPosTextField = xShapePropTextField->getPosition(); + aPosTextField.X = aPosLabel.X; + xShapePropTextField->setPosition(aPosTextField); + if (bLabelAboveTextField) + { + // move the label down near the splitter + const uno::Reference<report::XSection> xLabelSection = pSectionWindow[1]->getReportSection().getSection(); + aPosLabel.Y = xLabelSection->getHeight() - xShapePropLabel->getHeight(); + } + else + { + // move the label up to the splitter + aPosLabel.Y = 0; + } + xShapePropLabel->setPosition(aPosLabel); + } + OUnoObject* pObj = dynamic_cast<OUnoObject*>(pControl[0].get()); + assert(pObj); + uno::Reference< report::XFixedText> xShapeProp(pObj->getUnoShape(),uno::UNO_QUERY_THROW); + xShapeProp->setName(xShapeProp->getName() + sDefaultName ); + + for(i = 0; i < SAL_N_ELEMENTS(pControl); ++i) // insert controls + { + correctOverlapping(pControl[i].get(), pSectionWindow[1-i]->getReportSection()); + } + + if (!bLabelAboveTextField ) + { + if ( pSectionViews[0] == pSectionViews[1] ) + { + tools::Rectangle aLabel = getRectangleFromControl(pControl[0].get()); + tools::Rectangle aTextfield = getRectangleFromControl(pControl[1].get()); + + // create a Union of the given Label and Textfield + tools::Rectangle aLabelAndTextfield( aLabel ); + aLabelAndTextfield.Union(aTextfield); + + // check if there exists other fields and if yes, move down + bool bOverlapping = true; + bool bHasToMove = false; + while ( bOverlapping ) + { + const SdrObject* pOverlappedObj = isOver(aLabelAndTextfield, *pSectionWindow[0]->getReportSection().getPage(), *pSectionViews[0], true, pControl, 2); + bOverlapping = pOverlappedObj != nullptr; + if ( bOverlapping ) + { + const tools::Rectangle& aLogicRect = pOverlappedObj->GetLogicRect(); + aLabelAndTextfield.Move(0,aLogicRect.Top() + aLogicRect.getHeight() - aLabelAndTextfield.Top()); + bHasToMove = true; + } + } + + if (bHasToMove) + { + // There was a move down, we need to move the Label and the Textfield down + aLabel.Move(0, aLabelAndTextfield.Top() - aLabel.Top()); + aTextfield.Move(0, aLabelAndTextfield.Top() - aTextfield.Top()); + + uno::Reference< report::XReportComponent> xLabel(pControl[0]->getUnoShape(),uno::UNO_QUERY_THROW); + xLabel->setPositionY(aLabel.Top()); + + uno::Reference< report::XReportComponent> xTextfield(pControl[1]->getUnoShape(),uno::UNO_QUERY_THROW); + xTextfield->setPositionY(aTextfield.Top()); + } + } + } + } + // not sure where the ownership of these passes too... + pControl[0].release(); + pControl[1].release(); + } + } + } + catch(const Exception&) + { + DBG_UNHANDLED_EXCEPTION("reportdesign"); + } +} + + +OSectionView* OReportController::getCurrentSectionView() const +{ + OSectionView* pSectionView = nullptr; + OSectionWindow* pSectionWindow = getDesignView()->getMarkedSection(); + if ( pSectionWindow ) + pSectionView = &pSectionWindow->getReportSection().getSectionView(); + return pSectionView; +} + +void OReportController::changeZOrder(sal_Int32 _nId) +{ + OSectionView* pSectionView = getCurrentSectionView(); + if ( !pSectionView ) + return; + + switch(_nId) + { + case SID_FRAME_TO_BOTTOM: + pSectionView->PutMarkedToBtm(); + break; + case SID_FRAME_TO_TOP: + pSectionView->PutMarkedToTop(); + break; + case SID_FRAME_DOWN: + pSectionView->MovMarkedToBtm(); + break; + case SID_FRAME_UP: + pSectionView->MovMarkedToTop(); + break; + + case SID_OBJECT_HEAVEN: + pSectionView->SetMarkedToLayer( RPT_LAYER_FRONT ); + break; + case SID_OBJECT_HELL: + pSectionView->SetMarkedToLayer( RPT_LAYER_BACK ); + break; + } +} + +void OReportController::listen(const bool _bAdd) +{ + const OUString aProps [] = { OUString(PROPERTY_REPORTHEADERON),OUString(PROPERTY_REPORTFOOTERON) + ,OUString(PROPERTY_PAGEHEADERON),OUString(PROPERTY_PAGEFOOTERON) + ,OUString(PROPERTY_COMMAND), OUString(PROPERTY_COMMANDTYPE),OUString(PROPERTY_CAPTION) + }; + + void (SAL_CALL XPropertySet::*pPropertyListenerAction)( const OUString&, const uno::Reference< XPropertyChangeListener >& ) = + _bAdd ? &XPropertySet::addPropertyChangeListener : &XPropertySet::removePropertyChangeListener; + + for (const auto & aProp : aProps) + (m_xReportDefinition.get()->*pPropertyListenerAction)( aProp, static_cast< XPropertyChangeListener* >( this ) ); + + OXUndoEnvironment& rUndoEnv = m_aReportModel->GetUndoEnv(); + uno::Reference< XPropertyChangeListener > xUndo = &rUndoEnv; + const uno::Sequence< beans::Property> aSeq = m_xReportDefinition->getPropertySetInfo()->getProperties(); + const OUString* pPropsBegin = &aProps[0]; + const OUString* pPropsEnd = pPropsBegin + SAL_N_ELEMENTS(aProps) - 3; + for(const beans::Property& rProp : aSeq) + { + if ( ::std::find(pPropsBegin,pPropsEnd,rProp.Name) == pPropsEnd ) + (m_xReportDefinition.get()->*pPropertyListenerAction)( rProp.Name, xUndo ); + } + + // Add Listeners to UndoEnvironment + void (OXUndoEnvironment::*pElementUndoFunction)( const uno::Reference< uno::XInterface >& ) = + _bAdd ? &OXUndoEnvironment::AddElement : &OXUndoEnvironment::RemoveElement; + + (rUndoEnv.*pElementUndoFunction)( m_xReportDefinition->getStyleFamilies() ); + (rUndoEnv.*pElementUndoFunction)( m_xReportDefinition->getFunctions() ); + + // Add Listeners to ReportControllerObserver + OXReportControllerObserver& rObserver = *m_pReportControllerObserver; + + if ( m_xReportDefinition->getPageHeaderOn() && _bAdd ) + { + getDesignView()->addSection(m_xReportDefinition->getPageHeader(),DBPAGEHEADER); + rObserver.AddSection(m_xReportDefinition->getPageHeader()); + } + if ( m_xReportDefinition->getReportHeaderOn() && _bAdd ) + { + getDesignView()->addSection(m_xReportDefinition->getReportHeader(),DBREPORTHEADER); + rObserver.AddSection(m_xReportDefinition->getReportHeader()); + } + + uno::Reference< report::XGroups > xGroups = m_xReportDefinition->getGroups(); + const sal_Int32 nCount = xGroups->getCount(); + _bAdd ? xGroups->addContainerListener(&rUndoEnv) : xGroups->removeContainerListener(&rUndoEnv); + _bAdd ? xGroups->addContainerListener(&rObserver) : xGroups->removeContainerListener(&rObserver); + + for (sal_Int32 i=0;i<nCount ; ++i) + { + uno::Reference< report::XGroup > xGroup(xGroups->getByIndex(i),uno::UNO_QUERY); + (xGroup.get()->*pPropertyListenerAction)( OUString(PROPERTY_HEADERON), static_cast< XPropertyChangeListener* >( this ) ); + (xGroup.get()->*pPropertyListenerAction)( OUString(PROPERTY_FOOTERON), static_cast< XPropertyChangeListener* >( this ) ); + + (rUndoEnv.*pElementUndoFunction)( xGroup ); + (rUndoEnv.*pElementUndoFunction)( xGroup->getFunctions() ); + if ( xGroup->getHeaderOn() && _bAdd ) + { + getDesignView()->addSection(xGroup->getHeader(),DBGROUPHEADER); + rObserver.AddSection(xGroup->getHeader()); + } + } + + if ( _bAdd ) + { + getDesignView()->addSection(m_xReportDefinition->getDetail(),DBDETAIL); + rObserver.AddSection(m_xReportDefinition->getDetail()); + + for (sal_Int32 i=nCount;i > 0 ; --i) + { + uno::Reference< report::XGroup > xGroup(xGroups->getByIndex(i-1),uno::UNO_QUERY); + if ( xGroup->getFooterOn() ) + { + getDesignView()->addSection(xGroup->getFooter(),DBGROUPFOOTER); + rObserver.AddSection(xGroup->getFooter()); + } + } + if ( m_xReportDefinition->getReportFooterOn() ) + { + getDesignView()->addSection(m_xReportDefinition->getReportFooter(),DBREPORTFOOTER); + rObserver.AddSection(m_xReportDefinition->getReportFooter()); + } + if ( m_xReportDefinition->getPageFooterOn()) + { + getDesignView()->addSection(m_xReportDefinition->getPageFooter(),DBPAGEFOOTER); + rObserver.AddSection(m_xReportDefinition->getPageFooter()); + } + + xGroups->addContainerListener(static_cast<XContainerListener*>(this)); + m_xReportDefinition->addModifyListener(static_cast<XModifyListener*>(this)); + } + else /* ! _bAdd */ + { + rObserver.RemoveSection(m_xReportDefinition->getDetail()); + xGroups->removeContainerListener(static_cast<XContainerListener*>(this)); + m_xReportDefinition->removeModifyListener(static_cast<XModifyListener*>(this)); + m_aReportModel->detachController(); + } +} + +void OReportController::switchReportSection(const sal_Int16 _nId) +{ + OSL_ENSURE(_nId == SID_REPORTHEADER_WITHOUT_UNDO || _nId == SID_REPORTFOOTER_WITHOUT_UNDO || _nId == SID_REPORTHEADERFOOTER ,"Illegal id given!"); + + if ( !m_xReportDefinition.is() ) + return; + + const OXUndoEnvironment::OUndoEnvLock aLock( m_aReportModel->GetUndoEnv() ); + const bool bSwitchOn = !m_xReportDefinition->getReportHeaderOn(); + + std::unique_ptr< UndoContext > pUndoContext; + if ( SID_REPORTHEADERFOOTER == _nId ) + { + const OUString sUndoAction(RptResId(bSwitchOn ? RID_STR_UNDO_ADD_REPORTHEADERFOOTER : RID_STR_UNDO_REMOVE_REPORTHEADERFOOTER)); + pUndoContext.reset( new UndoContext( getUndoManager(), sUndoAction ) ); + + addUndoAction(std::make_unique<OReportSectionUndo>(*m_aReportModel,SID_REPORTHEADER_WITHOUT_UNDO + ,::std::mem_fn(&OReportHelper::getReportHeader) + ,m_xReportDefinition + ,bSwitchOn ? Inserted : Removed + )); + + addUndoAction(std::make_unique<OReportSectionUndo>(*m_aReportModel,SID_REPORTFOOTER_WITHOUT_UNDO + ,::std::mem_fn(&OReportHelper::getReportFooter) + ,m_xReportDefinition + ,bSwitchOn ? Inserted : Removed + )); + } + + switch( _nId ) + { + case SID_REPORTHEADER_WITHOUT_UNDO: + m_xReportDefinition->setReportHeaderOn( bSwitchOn ); + break; + case SID_REPORTFOOTER_WITHOUT_UNDO: + m_xReportDefinition->setReportFooterOn( !m_xReportDefinition->getReportFooterOn() ); + break; + case SID_REPORTHEADERFOOTER: + m_xReportDefinition->setReportHeaderOn( bSwitchOn ); + m_xReportDefinition->setReportFooterOn( bSwitchOn ); + break; + } + + if ( SID_REPORTHEADERFOOTER == _nId ) + pUndoContext.reset(); + getView()->Resize(); +} + +void OReportController::switchPageSection(const sal_Int16 _nId) +{ + OSL_ENSURE(_nId == SID_PAGEHEADERFOOTER || _nId == SID_PAGEHEADER_WITHOUT_UNDO || _nId == SID_PAGEFOOTER_WITHOUT_UNDO ,"Illegal id given!"); + if ( !m_xReportDefinition.is() ) + return; + + const OXUndoEnvironment::OUndoEnvLock aLock( m_aReportModel->GetUndoEnv() ); + const bool bSwitchOn = !m_xReportDefinition->getPageHeaderOn(); + + std::unique_ptr< UndoContext > pUndoContext; + if ( SID_PAGEHEADERFOOTER == _nId ) + { + const OUString sUndoAction(RptResId(bSwitchOn ? RID_STR_UNDO_ADD_REPORTHEADERFOOTER : RID_STR_UNDO_REMOVE_REPORTHEADERFOOTER)); + pUndoContext.reset( new UndoContext( getUndoManager(), sUndoAction ) ); + + addUndoAction(std::make_unique<OReportSectionUndo>(*m_aReportModel + ,SID_PAGEHEADER_WITHOUT_UNDO + ,::std::mem_fn(&OReportHelper::getPageHeader) + ,m_xReportDefinition + ,bSwitchOn ? Inserted : Removed + )); + + addUndoAction(std::make_unique<OReportSectionUndo>(*m_aReportModel + ,SID_PAGEFOOTER_WITHOUT_UNDO + ,::std::mem_fn(&OReportHelper::getPageFooter) + ,m_xReportDefinition + ,bSwitchOn ? Inserted : Removed + )); + } + switch( _nId ) + { + case SID_PAGEHEADER_WITHOUT_UNDO: + m_xReportDefinition->setPageHeaderOn( bSwitchOn ); + break; + case SID_PAGEFOOTER_WITHOUT_UNDO: + m_xReportDefinition->setPageFooterOn( !m_xReportDefinition->getPageFooterOn() ); + break; + case SID_PAGEHEADERFOOTER: + m_xReportDefinition->setPageHeaderOn( bSwitchOn ); + m_xReportDefinition->setPageFooterOn( bSwitchOn ); + break; + } + if ( SID_PAGEHEADERFOOTER == _nId ) + pUndoContext.reset(); + getView()->Resize(); +} + +void OReportController::modifyGroup(const bool _bAppend, const Sequence< PropertyValue >& _aArgs) +{ + if ( !m_xReportDefinition.is() ) + return; + + try + { + const SequenceAsHashMap aMap( _aArgs ); + uno::Reference< report::XGroup > xGroup = aMap.getUnpackedValueOrDefault( PROPERTY_GROUP, uno::Reference< report::XGroup >() ); + if ( !xGroup.is() ) + return; + + OXUndoEnvironment& rUndoEnv = m_aReportModel->GetUndoEnv(); + uno::Reference< report::XGroups > xGroups = m_xReportDefinition->getGroups(); + if ( _bAppend ) + { + const sal_Int32 nPos = aMap.getUnpackedValueOrDefault( PROPERTY_POSITIONY, xGroups->getCount() ); + xGroups->insertByIndex( nPos, uno::Any( xGroup ) ); + rUndoEnv.AddElement( xGroup->getFunctions() ); + } + + addUndoAction( std::make_unique<OGroupUndo>( + *m_aReportModel, + _bAppend ? RID_STR_UNDO_APPEND_GROUP : RID_STR_UNDO_REMOVE_GROUP, + _bAppend ? Inserted : Removed, + xGroup, + m_xReportDefinition + ) ); + + if ( !_bAppend ) + { + rUndoEnv.RemoveElement( xGroup->getFunctions() ); + const sal_Int32 nPos = getGroupPosition( xGroup ); + const OXUndoEnvironment::OUndoEnvLock aLock( m_aReportModel->GetUndoEnv() ); + xGroups->removeByIndex( nPos ); + } + } + catch(const Exception&) + { + DBG_UNHANDLED_EXCEPTION("reportdesign"); + } +} + + +void OReportController::createGroupSection(const bool _bUndo,const bool _bHeader, const Sequence< PropertyValue >& _aArgs) +{ + if ( !m_xReportDefinition.is() ) + return; + + const SequenceAsHashMap aMap(_aArgs); + const bool bSwitchOn = aMap.getUnpackedValueOrDefault(_bHeader ? OUString(PROPERTY_HEADERON) : OUString(PROPERTY_FOOTERON), false); + uno::Reference< report::XGroup> xGroup = aMap.getUnpackedValueOrDefault(PROPERTY_GROUP,uno::Reference< report::XGroup>()); + if ( !xGroup.is() ) + return; + + const OXUndoEnvironment::OUndoEnvLock aLock(m_aReportModel->GetUndoEnv()); + if ( _bUndo ) + addUndoAction(std::make_unique<OGroupSectionUndo>(*m_aReportModel + ,_bHeader ? SID_GROUPHEADER_WITHOUT_UNDO : SID_GROUPFOOTER_WITHOUT_UNDO + ,_bHeader ? ::std::mem_fn(&OGroupHelper::getHeader) : ::std::mem_fn(&OGroupHelper::getFooter) + ,xGroup + ,bSwitchOn ? Inserted : Removed + , ( _bHeader ? + (bSwitchOn ? RID_STR_UNDO_ADD_GROUP_HEADER : RID_STR_UNDO_REMOVE_GROUP_HEADER) + :(bSwitchOn ? RID_STR_UNDO_ADD_GROUP_FOOTER : RID_STR_UNDO_REMOVE_GROUP_FOOTER) + ) + )); + + if ( _bHeader ) + xGroup->setHeaderOn( bSwitchOn ); + else + xGroup->setFooterOn( bSwitchOn ); +} + +void OReportController::collapseSection(const bool _bCollapse) +{ + OSectionWindow *pSection = getDesignView()->getMarkedSection(); + if ( pSection ) + { + pSection->setCollapsed(_bCollapse); + } +} + +void OReportController::markSection(const bool _bNext) +{ + OSectionWindow *pSection = getDesignView()->getMarkedSection(); + if ( pSection ) + { + OSectionWindow *pPrevSection = getDesignView()->getMarkedSection(_bNext ? POST : PREVIOUS); + if ( pPrevSection != pSection && pPrevSection ) + select(uno::Any(pPrevSection->getReportSection().getSection())); + else + select(uno::Any(m_xReportDefinition)); + } + else + { + getDesignView()->markSection(_bNext ? 0 : getDesignView()->getSectionCount() - 1); + pSection = getDesignView()->getMarkedSection(); + if ( pSection ) + select(uno::Any(pSection->getReportSection().getSection())); + } +} + +void OReportController::createDefaultControl(const uno::Sequence< beans::PropertyValue>& _aArgs) +{ + uno::Reference< report::XSection > xSection = getDesignView()->getCurrentSection(); + if ( !xSection.is() ) + xSection = m_xReportDefinition->getDetail(); + + if ( !xSection.is() ) + return; + + const beans::PropertyValue* pIter = _aArgs.getConstArray(); + const beans::PropertyValue* pEnd = pIter + _aArgs.getLength(); + const beans::PropertyValue* pKeyModifier = ::std::find_if(pIter, pEnd, + [] (const beans::PropertyValue& x) -> bool { + return x.Name == "KeyModifier"; + }); + sal_Int16 nKeyModifier = 0; + if ( pKeyModifier == pEnd || ((pKeyModifier->Value >>= nKeyModifier) && nKeyModifier == KEY_MOD1) ) + { + Sequence< PropertyValue > aCreateArgs; + getDesignView()->unmarkAllObjects(); + createControl(aCreateArgs,xSection,OUString(),getDesignView()->GetInsertObj()); + } +} + + +void OReportController::checkChartEnabled() +{ + if ( m_bChartEnabledAsked ) + return; + + m_bChartEnabledAsked = true; + + try + { + ::utl::OConfigurationTreeRoot aConfiguration( + ::utl::OConfigurationTreeRoot::createWithComponentContext( m_xContext, "/org.openoffice.Office.ReportDesign" ) ); + + bool bChartEnabled = false; + static const OUStringLiteral sPropertyName( u"UserData/Chart" ); + if ( aConfiguration.hasByHierarchicalName(sPropertyName) ) + aConfiguration.getNodeValue( sPropertyName ) >>= bChartEnabled; + m_bChartEnabled = bChartEnabled; + } + catch(const Exception&) + { + } +} + + +// css.frame.XTitle +OUString SAL_CALL OReportController::getTitle() +{ + SolarMutexGuard aSolarGuard; + ::osl::MutexGuard aGuard( getMutex() ); + + uno::Reference< frame::XTitle> xTitle(m_xReportDefinition,uno::UNO_QUERY_THROW); + + return xTitle->getTitle (); +} + +void OReportController::getPropertyDefaultByHandle( sal_Int32 /*_nHandle*/, Any& _rDefault ) const +{ + _rDefault <<= sal_Int16(100); +} + +// comphelper::OPropertyArrayUsageHelper +::cppu::IPropertyArrayHelper* OReportController::createArrayHelper( ) const +{ + Sequence< Property > aProps; + describeProperties(aProps); + return new ::cppu::OPropertyArrayHelper(aProps); +} + + +// cppu::OPropertySetHelper +::cppu::IPropertyArrayHelper& SAL_CALL OReportController::getInfoHelper() +{ + return *::comphelper::OPropertyArrayUsageHelper<OReportController_BASE>::getArrayHelper(); +} + +void SAL_CALL OReportController::setFastPropertyValue_NoBroadcast(sal_Int32 _nHandle,const Any& _aValue) +{ + if ( _nHandle == PROPERTY_ID_ZOOMVALUE ) + { + _aValue >>= m_nZoomValue; + impl_zoom_nothrow(); + } +} +void SAL_CALL OReportController::setMode( const OUString& aMode ) +{ + ::osl::MutexGuard aGuard( getMutex() ); + m_sMode = aMode; +} +OUString SAL_CALL OReportController::getMode( ) +{ + ::osl::MutexGuard aGuard( getMutex() ); + return m_sMode; +} +css::uno::Sequence< OUString > SAL_CALL OReportController::getSupportedModes( ) +{ + return uno::Sequence< OUString> { OUString("remote"), OUString("normal") }; +} +sal_Bool SAL_CALL OReportController::supportsMode( const OUString& aMode ) +{ + uno::Sequence< OUString> aModes = getSupportedModes(); + return comphelper::findValue(aModes, aMode) != -1; +} + +bool OReportController::isUiVisible() const +{ + return m_sMode != "remote"; +} + +void OReportController::impl_fillState_nothrow(const OUString& _sProperty,dbaui::FeatureState& _rState) const +{ + _rState.bEnabled = isEditable(); + if ( !_rState.bEnabled ) + return; + + ::std::vector< uno::Reference< uno::XInterface > > aSelection; + getDesignView()->fillControlModelSelection(aSelection); + _rState.bEnabled = !aSelection.empty(); + if ( !_rState.bEnabled ) + return; + + uno::Any aTemp; + ::std::vector< uno::Reference< uno::XInterface > >::const_iterator aIter = aSelection.begin(); + for(; aIter != aSelection.end() && _rState.bEnabled ;++aIter) + { + uno::Reference< beans::XPropertySet> xProp(*aIter,uno::UNO_QUERY); + try + { + uno::Any aTemp2 = xProp->getPropertyValue(_sProperty); + if ( aIter == aSelection.begin() ) + { + aTemp = aTemp2; + } + else if ( aTemp != aTemp2 ) + break; + } + catch(const beans::UnknownPropertyException&) + { + _rState.bEnabled = false; + } + } + if ( aIter == aSelection.end() ) + _rState.aValue = aTemp; +} + +void OReportController::impl_zoom_nothrow() +{ + Fraction aZoom(m_nZoomValue,100); + setZoomFactor( aZoom, *getDesignView() ); + getDesignView()->zoom(aZoom); + InvalidateFeature(SID_ATTR_ZOOM,Reference< XStatusListener >(), true); + InvalidateFeature(SID_ATTR_ZOOMSLIDER,Reference< XStatusListener >(), true); +} + +bool OReportController::isFormatCommandEnabled(sal_uInt16 _nCommand,const uno::Reference< report::XReportControlFormat>& _xReportControlFormat) +{ + bool bRet = false; + if ( _xReportControlFormat.is() && !uno::Reference< report::XFixedLine>(_xReportControlFormat,uno::UNO_QUERY).is() ) // this command is really often called so we need a short cut here + { + try + { + const awt::FontDescriptor aFontDescriptor = _xReportControlFormat->getFontDescriptor(); + + switch(_nCommand) + { + case SID_ATTR_CHAR_WEIGHT: + bRet = awt::FontWeight::BOLD == aFontDescriptor.Weight; + break; + case SID_ATTR_CHAR_POSTURE: + bRet = awt::FontSlant_ITALIC == aFontDescriptor.Slant; + break; + case SID_ATTR_CHAR_UNDERLINE: + bRet = awt::FontUnderline::SINGLE == aFontDescriptor.Underline; + break; + default: + ; + } + } + catch(const uno::Exception&) + { + } + } + return bRet; +} + +bool OReportController::impl_setPropertyAtControls_throw(TranslateId pUndoResId,const OUString& _sProperty,const uno::Any& _aValue,const Sequence< PropertyValue >& _aArgs) +{ + ::std::vector< uno::Reference< uno::XInterface > > aSelection; + uno::Reference< awt::XWindow> xWindow; + lcl_getReportControlFormat( _aArgs, getDesignView(), xWindow, aSelection ); + + const OUString sUndoAction = RptResId( pUndoResId ); + UndoContext aUndoContext( getUndoManager(), sUndoAction ); + + for (const auto& rxInterface : aSelection) + { + const uno::Reference< beans::XPropertySet > xControlModel(rxInterface,uno::UNO_QUERY); + if ( xControlModel.is() ) + // tdf#117795: some elements may have not some property + // eg class "OFixedLine" doesn't have property "CharFontName" + // so in this case, instead of crashing when selecting all and changing font + // just display a warning + try + { + xControlModel->setPropertyValue(_sProperty,_aValue); + } + catch(const UnknownPropertyException&) + { + TOOLS_WARN_EXCEPTION("reportdesign", ""); + } + } + + return !aSelection.empty(); +} + +void OReportController::impl_fillCustomShapeState_nothrow(const char* _pCustomShapeType,dbaui::FeatureState& _rState) const +{ + _rState.bEnabled = isEditable(); + _rState.bChecked = getDesignView()->GetInsertObj() == SdrObjKind::CustomShape && getDesignView()->GetInsertObjString().equalsAscii(_pCustomShapeType); +} + + +OSectionWindow* OReportController::getSectionWindow(const css::uno::Reference< css::report::XSection>& _xSection) const +{ + if ( getDesignView() ) + { + return getDesignView()->getSectionWindow(_xSection); + } + + // throw NullPointerException? + return nullptr; +} + + +void OReportController::openZoomDialog() +{ + SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create(); + + static SfxItemInfo aItemInfos[] = + { + { SID_ATTR_ZOOM, true } + }; + std::vector<SfxPoolItem*> pDefaults + { + new SvxZoomItem() + }; + rtl::Reference<SfxItemPool> pPool( new SfxItemPool("ZoomProperties", SID_ATTR_ZOOM,SID_ATTR_ZOOM, aItemInfos, &pDefaults) ); + pPool->SetDefaultMetric( MapUnit::Map100thMM ); // ripped, don't understand why + pPool->FreezeIdRanges(); // the same + try + { + SfxItemSetFixed<SID_ATTR_ZOOM,SID_ATTR_ZOOM> aDescriptor(*pPool); + // fill it + SvxZoomItem aZoomItem( m_eZoomType, m_nZoomValue, SID_ATTR_ZOOM ); + aZoomItem.SetValueSet(SvxZoomEnableFlags::N100|SvxZoomEnableFlags::WHOLEPAGE|SvxZoomEnableFlags::PAGEWIDTH); + aDescriptor.Put(aZoomItem); + + ScopedVclPtr<AbstractSvxZoomDialog> pDlg(pFact->CreateSvxZoomDialog(nullptr, aDescriptor)); + pDlg->SetLimits( 20, 400 ); + bool bCancel = ( RET_CANCEL == pDlg->Execute() ); + + if ( !bCancel ) + { + const SvxZoomItem& rZoomItem = pDlg->GetOutputItemSet()->Get( SID_ATTR_ZOOM ); + m_eZoomType = rZoomItem.GetType(); + m_nZoomValue = rZoomItem.GetValue(); + if ( m_eZoomType != SvxZoomType::PERCENT ) + m_nZoomValue = getDesignView()->getZoomFactor( m_eZoomType ); + + impl_zoom_nothrow(); + } + } + catch(const uno::Exception&) + { + DBG_UNHANDLED_EXCEPTION("reportdesign"); + } + pPool.clear(); + + for (SfxPoolItem* pDefault : pDefaults) + delete pDefault; +} + + +// XVisualObject +void SAL_CALL OReportController::setVisualAreaSize( ::sal_Int64 _nAspect, const awt::Size& _aSize ) +{ + ::osl::MutexGuard aGuard( getMutex() ); + bool bChanged = + (m_aVisualAreaSize.Width != _aSize.Width || + m_aVisualAreaSize.Height != _aSize.Height); + m_aVisualAreaSize = _aSize; + if( bChanged ) + setModified( true ); + m_nAspect = _nAspect; +} + +awt::Size SAL_CALL OReportController::getVisualAreaSize( ::sal_Int64 /*nAspect*/ ) +{ + ::osl::MutexGuard aGuard( getMutex() ); + return m_aVisualAreaSize; +} + +embed::VisualRepresentation SAL_CALL OReportController::getPreferredVisualRepresentation( ::sal_Int64 _nAspect ) +{ + SolarMutexGuard aSolarGuard; + ::osl::MutexGuard aGuard( getMutex() ); + embed::VisualRepresentation aResult; + if ( !m_bInGeneratePreview ) + { + m_bInGeneratePreview = true; + try + { + if ( !m_xReportEngine.is() ) + m_xReportEngine.set( report::ReportEngine::create(m_xContext) ); + const sal_Int32 nOldMaxRows = m_xReportEngine->getMaxRows(); + m_xReportEngine->setMaxRows(MAX_ROWS_FOR_PREVIEW); + m_xReportEngine->setReportDefinition(m_xReportDefinition); + m_xReportEngine->setActiveConnection(getConnection()); + try + { + Reference<embed::XVisualObject> xTransfer(m_xReportEngine->createDocumentModel(),UNO_QUERY); + if ( xTransfer.is() ) + { + xTransfer->setVisualAreaSize(m_nAspect,m_aVisualAreaSize); + aResult = xTransfer->getPreferredVisualRepresentation( _nAspect ); + } + } + catch(const uno::Exception&) + { + } + m_xReportEngine->setMaxRows(nOldMaxRows); + } + catch(const uno::Exception&) + { + } + m_bInGeneratePreview = false; + } + return aResult; +} + +::sal_Int32 SAL_CALL OReportController::getMapUnit( ::sal_Int64 /*nAspect*/ ) +{ + return embed::EmbedMapUnits::ONE_100TH_MM; +} + +uno::Reference< container::XNameAccess > const & OReportController::getColumns() const +{ + if ( !m_xColumns.is() && m_xReportDefinition.is() && !m_xReportDefinition->getCommand().isEmpty() ) + { + m_xColumns = dbtools::getFieldsByCommandDescriptor(getConnection(),m_xReportDefinition->getCommandType(),m_xReportDefinition->getCommand(),m_xHoldAlive); + } + return m_xColumns; +} + +OUString OReportController::getColumnLabel_throw(const OUString& i_sColumnName) const +{ + OUString sLabel; + uno::Reference< container::XNameAccess > xColumns = getColumns(); + if ( xColumns.is() && xColumns->hasByName(i_sColumnName) ) + { + uno::Reference< beans::XPropertySet> xColumn(xColumns->getByName(i_sColumnName),uno::UNO_QUERY_THROW); + if ( xColumn->getPropertySetInfo()->hasPropertyByName(PROPERTY_LABEL) ) + xColumn->getPropertyValue(PROPERTY_LABEL) >>= sLabel; + } + return sLabel; +} + + +SfxUndoManager& OReportController::getUndoManager() const +{ + DBG_TESTSOLARMUTEX(); + // this is expected to be called during UI actions, so the SM is assumed to be locked + + std::shared_ptr< OReportModel > pReportModel( getSdrModel() ); + ENSURE_OR_THROW( !!pReportModel, "no access to our model" ); + + SfxUndoManager* pUndoManager( pReportModel->GetSdrUndoManager() ); + ENSURE_OR_THROW( pUndoManager != nullptr, "no access to our model's UndoManager" ); + + return *pUndoManager; +} + + +void OReportController::clearUndoManager() const +{ + getUndoManager().Clear(); +} + + +void OReportController::addUndoAction( std::unique_ptr<SfxUndoAction> i_pAction ) +{ + getUndoManager().AddUndoAction( std::move(i_pAction) ); + + InvalidateFeature( SID_UNDO ); + InvalidateFeature( SID_REDO ); +} + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface* +reportdesign_OReportController_get_implementation( + css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const&) +{ + return cppu::acquire(new OReportController(context)); +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/reportdesign/source/ui/report/ReportControllerObserver.cxx b/reportdesign/source/ui/report/ReportControllerObserver.cxx new file mode 100644 index 000000000..514624388 --- /dev/null +++ b/reportdesign/source/ui/report/ReportControllerObserver.cxx @@ -0,0 +1,342 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * 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 . + */ + +#include <sal/config.h> + +#include <map> + +#include <ReportControllerObserver.hxx> +#include <ReportController.hxx> +#include <osl/mutex.hxx> +#include <vcl/svapp.hxx> +#include <vcl/settings.hxx> + +#include <FormattedFieldBeautifier.hxx> + +// DBG_UNHANDLED_EXCEPTION +#include <tools/diagnose_ex.h> + +namespace rptui +{ + + using namespace ::com::sun::star; + +typedef std::map<OUString, bool> AllProperties; +typedef std::map<uno::Reference< beans::XPropertySet >, AllProperties> PropertySetInfoCache; + +class OXReportControllerObserverImpl +{ +public: + ::std::vector< uno::Reference< container::XChild> > m_aSections; + ::osl::Mutex m_aMutex; + oslInterlockedCount m_nLocks; + + explicit OXReportControllerObserverImpl(); + OXReportControllerObserverImpl(const OXReportControllerObserverImpl&) = delete; + OXReportControllerObserverImpl& operator=(const OXReportControllerObserverImpl&) = delete; +}; + + + OXReportControllerObserverImpl::OXReportControllerObserverImpl() + :m_nLocks(0) + { + } + + + OXReportControllerObserver::OXReportControllerObserver(const OReportController& _rController) + :m_pImpl(new OXReportControllerObserverImpl ) + ,m_aFormattedFieldBeautifier(_rController) + ,m_aFixedTextColor(_rController) + { + + Application::AddEventListener(LINK( this, OXReportControllerObserver, SettingsChanged ) ); + } + + OXReportControllerObserver::~OXReportControllerObserver() + { + Application::RemoveEventListener(LINK( this, OXReportControllerObserver, SettingsChanged ) ); + } + + + IMPL_LINK(OXReportControllerObserver, SettingsChanged, VclSimpleEvent&, _rEvt, void) + { + VclEventId nEvent = _rEvt.GetId(); + + if (nEvent != VclEventId::ApplicationDataChanged ) + return; + + DataChangedEvent* pData = static_cast<DataChangedEvent*>(static_cast<VclWindowEvent&>(_rEvt).GetData()); + if ( !(pData && ((( pData->GetType() == DataChangedEventType::SETTINGS ) || + ( pData->GetType() == DataChangedEventType::DISPLAY )) && + ( pData->GetFlags() & AllSettingsFlags::STYLE )))) + return; + + OEnvLock aLock(*this); + + // send all Section Objects a 'tingle' + // maybe they need a change in format, color, etc + for (const uno::Reference<container::XChild>& xChild : m_pImpl->m_aSections) + { + if (xChild.is()) + { + uno::Reference<report::XSection> xSection(xChild, uno::UNO_QUERY); + if (xSection.is()) + { + const sal_Int32 nCount = xSection->getCount(); + for (sal_Int32 i = 0; i < nCount; ++i) + { + const uno::Any aObj = xSection->getByIndex(i); + uno::Reference < report::XReportComponent > xReportComponent(aObj, uno::UNO_QUERY); + if (xReportComponent.is()) + { + m_aFormattedFieldBeautifier.handle(xReportComponent); + m_aFixedTextColor.handle(xReportComponent); + } + } + } + } + } + } + + // XEventListener + void SAL_CALL OXReportControllerObserver::disposing(const lang::EventObject& e) + { + // check if it's an object we have cached information about + uno::Reference< beans::XPropertySet > xSourceSet(e.Source, uno::UNO_QUERY); + if ( xSourceSet.is() ) + { + uno::Reference< report::XSection> xSection(xSourceSet,uno::UNO_QUERY); + if ( xSection.is() ) + RemoveSection(xSection); + else + RemoveElement(xSourceSet); + } + } + + void OXReportControllerObserver::Clear() + { + OEnvLock aLock(*this); + m_pImpl->m_aSections.clear(); + } + + // XPropertyChangeListener + void SAL_CALL OXReportControllerObserver::propertyChange(const beans::PropertyChangeEvent& _rEvent) + { + osl::MutexGuard aGuard( m_pImpl->m_aMutex ); + + if ( m_pImpl->m_nLocks != 0 ) + return; + + m_aFormattedFieldBeautifier.notifyPropertyChange(_rEvent); + m_aFixedTextColor.notifyPropertyChange(_rEvent); + } + + +void OXReportControllerObserver::Lock() +{ + OSL_ENSURE(m_refCount,"Illegal call to dead object!"); + osl_atomic_increment( &m_pImpl->m_nLocks ); +} + +void OXReportControllerObserver::UnLock() +{ + OSL_ENSURE(m_refCount,"Illegal call to dead object!"); + + osl_atomic_decrement( &m_pImpl->m_nLocks ); +} + +void OXReportControllerObserver::AddSection(const uno::Reference< report::XSection > & _xSection) +{ + OEnvLock aLock(*this); + try + { + uno::Reference<container::XChild> xChild = _xSection; + m_pImpl->m_aSections.push_back(xChild); + uno::Reference< uno::XInterface > xInt(_xSection); + AddElement(xInt); + } + catch(const uno::Exception&) + { + DBG_UNHANDLED_EXCEPTION("reportdesign"); + } +} + + +void OXReportControllerObserver::RemoveSection(const uno::Reference< report::XSection > & _xSection) +{ + OEnvLock aLock(*this); + try + { + uno::Reference<container::XChild> xChild(_xSection); + m_pImpl->m_aSections.erase(::std::remove(m_pImpl->m_aSections.begin(),m_pImpl->m_aSections.end(), + xChild), m_pImpl->m_aSections.end()); + uno::Reference< uno::XInterface > xInt(_xSection); + RemoveElement(xInt); + } + catch(uno::Exception&) + { + DBG_UNHANDLED_EXCEPTION("reportdesign"); + } +} + + +void OXReportControllerObserver::switchListening( const uno::Reference< container::XIndexAccess >& _rxContainer, bool _bStartListening ) +{ + OSL_PRECOND( _rxContainer.is(), "OXReportControllerObserver::switchListening: invalid container!" ); + if ( !_rxContainer.is() ) + return; + + try + { + // also handle all children of this element + uno::Reference< uno::XInterface > xInterface; + sal_Int32 nCount = _rxContainer->getCount(); + for(sal_Int32 i = 0;i != nCount;++i) + { + xInterface.set(_rxContainer->getByIndex( i ),uno::UNO_QUERY); + if ( _bStartListening ) + AddElement( xInterface ); + else + RemoveElement( xInterface ); + } + + // be notified of any changes in the container elements + uno::Reference< container::XContainer > xSimpleContainer( _rxContainer, uno::UNO_QUERY ); + if ( xSimpleContainer.is() ) + { + if ( _bStartListening ) + xSimpleContainer->addContainerListener( this ); + else + xSimpleContainer->removeContainerListener( this ); + } + } + catch( const uno::Exception& ) + { + DBG_UNHANDLED_EXCEPTION("reportdesign"); + } +} + + +void OXReportControllerObserver::switchListening( const uno::Reference< uno::XInterface >& _rxObject, bool _bStartListening ) +{ + OSL_PRECOND( _rxObject.is(), "OXReportControllerObserver::switchListening: how should I listen at a NULL object?" ); + + try + { + uno::Reference< beans::XPropertySet > xProps( _rxObject, uno::UNO_QUERY ); + if ( xProps.is() ) + { + if ( _bStartListening ) + xProps->addPropertyChangeListener( OUString(), this ); + else + xProps->removePropertyChangeListener( OUString(), this ); + } + + uno::Reference< util::XModifyBroadcaster > xBroadcaster( _rxObject, uno::UNO_QUERY ); + if ( xBroadcaster.is() ) + { + if ( _bStartListening ) + xBroadcaster->addModifyListener( this ); + else + xBroadcaster->removeModifyListener( this ); + } + } + catch( const uno::Exception& ) + { + DBG_UNHANDLED_EXCEPTION("reportdesign"); + } +} + + +void SAL_CALL OXReportControllerObserver::modified( const lang::EventObject& /*aEvent*/ ) +{ +} + + +void OXReportControllerObserver::AddElement(const uno::Reference< uno::XInterface >& _rxElement ) +{ + m_aFormattedFieldBeautifier.notifyElementInserted(_rxElement); + m_aFixedTextColor.notifyElementInserted(_rxElement); + + // if it's a container, start listening at all elements + uno::Reference< container::XIndexAccess > xContainer( _rxElement, uno::UNO_QUERY ); + if ( xContainer.is() ) + switchListening( xContainer, true ); + + switchListening( _rxElement, true ); +} + + +void OXReportControllerObserver::RemoveElement(const uno::Reference< uno::XInterface >& _rxElement) +{ + switchListening( _rxElement, false ); + + uno::Reference< container::XIndexAccess > xContainer( _rxElement, uno::UNO_QUERY ); + if ( xContainer.is() ) + switchListening( xContainer, false ); +} + + +// XContainerListener + +void SAL_CALL OXReportControllerObserver::elementInserted(const container::ContainerEvent& evt) +{ + SolarMutexGuard aSolarGuard; + ::osl::MutexGuard aGuard( m_pImpl->m_aMutex ); + + // new listener object + uno::Reference< uno::XInterface > xIface( evt.Element, uno::UNO_QUERY ); + if ( xIface.is() ) + { + AddElement(xIface); + } +} + + +void SAL_CALL OXReportControllerObserver::elementReplaced(const container::ContainerEvent& evt) +{ + SolarMutexGuard aSolarGuard; + ::osl::MutexGuard aGuard( m_pImpl->m_aMutex ); + + uno::Reference< uno::XInterface > xIface(evt.ReplacedElement,uno::UNO_QUERY); + OSL_ENSURE(xIface.is(), "OXReportControllerObserver::elementReplaced: invalid container notification!"); + RemoveElement(xIface); + + xIface.set(evt.Element,uno::UNO_QUERY); + AddElement(xIface); +} + + +void SAL_CALL OXReportControllerObserver::elementRemoved(const container::ContainerEvent& evt) +{ + SolarMutexGuard aSolarGuard; + ::osl::MutexGuard aGuard( m_pImpl->m_aMutex ); + + uno::Reference< uno::XInterface > xIface( evt.Element, uno::UNO_QUERY ); + if ( xIface.is() ) + { + RemoveElement(xIface); + } +} + + +} // namespace rptui + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/reportdesign/source/ui/report/ReportSection.cxx b/reportdesign/source/ui/report/ReportSection.cxx new file mode 100644 index 000000000..95d063c1d --- /dev/null +++ b/reportdesign/source/ui/report/ReportSection.cxx @@ -0,0 +1,805 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * 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 . + */ +#include <memory> +#include <ReportSection.hxx> +#include <ReportWindow.hxx> +#include <DesignView.hxx> +#include <strings.hxx> +#include <RptObject.hxx> +#include <RptModel.hxx> +#include <SectionView.hxx> +#include <RptPage.hxx> +#include <ReportController.hxx> +#include <UITools.hxx> +#include <ViewsWindow.hxx> + +#include <svx/svdpagv.hxx> +#include <editeng/adjustitem.hxx> +#include <editeng/eeitem.hxx> +#include <svx/sdrpaintwindow.hxx> +#include <svx/gallery.hxx> +#include <svx/svxids.hrc> +#include <svx/svditer.hxx> +#include <svx/dbaexchange.hxx> +#include <svx/sdtagitm.hxx> + +#include <com/sun/star/awt/PopupMenuDirection.hpp> +#include <com/sun/star/frame/XPopupMenuController.hpp> +#include <comphelper/propertyvalue.hxx> +#include <toolkit/helper/convert.hxx> +#include <tools/diagnose_ex.h> +#include <RptDef.hxx> +#include <SectionWindow.hxx> +#include <helpids.h> +#include <dlgedclip.hxx> +#include <rptui_slotid.hrc> + +#include <vcl/commandevent.hxx> +#include <o3tl/safeint.hxx> + +#include <svl/itempool.hxx> +#include <svtools/extcolorcfg.hxx> + + +namespace rptui +{ + +using namespace ::com::sun::star; + + +static Color lcl_getOverlappedControlColor(/*const uno::Reference <lang::XMultiServiceFactory> _rxFactory*/) +{ + svtools::ExtendedColorConfig aConfig; + return aConfig.GetColorValue(CFG_REPORTDESIGNER, DBOVERLAPPEDCONTROL).getColor(); +} + +OReportSection::OReportSection(OSectionWindow* _pParent,const uno::Reference< report::XSection >& _xSection) + : Window(_pParent,WB_DIALOGCONTROL) + , ::comphelper::OPropertyChangeListener(m_aMutex) + , DropTargetHelper(this) + , m_pPage(nullptr) + , m_pView(nullptr) + , m_pParent(_pParent) + , m_xSection(_xSection) + , m_nPaintEntranceCount(0) + , m_eMode(DlgEdMode::Select) +{ + //EnableChildTransparentMode(); + SetHelpId(HID_REPORTSECTION); + SetMapMode(MapMode(MapUnit::Map100thMM)); + SetParentClipMode(ParentClipMode::Clip); + EnableChildTransparentMode( false ); + SetPaintTransparent( false ); + + try + { + fill(); + } + catch(uno::Exception&) + { + TOOLS_WARN_EXCEPTION( "reportdesign", ""); + } + + m_pFunc.reset(new DlgEdFuncSelect( this )); + m_pFunc->setOverlappedControlColor(lcl_getOverlappedControlColor() ); +} + +OReportSection::~OReportSection() +{ + disposeOnce(); +} + +void OReportSection::dispose() +{ + m_pPage = nullptr; + if ( m_pMulti.is() ) + m_pMulti->dispose(); + m_pMulti.clear(); + + if ( m_pReportListener.is() ) + m_pReportListener->dispose(); + m_pReportListener.clear(); + m_pFunc.reset(); + + { + if ( m_pView ) + m_pView->EndListening( *m_pModel ); + delete m_pView; + m_pView = nullptr; + } + m_pParent.clear(); + vcl::Window::dispose(); +} + +void OReportSection::Paint( vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect ) +{ + Window::Paint(rRenderContext, rRect); + + if ( !(m_pView && m_nPaintEntranceCount == 0)) + return; + + ++m_nPaintEntranceCount; + // repaint, get PageView and prepare Region + SdrPageView* pPgView = m_pView->GetSdrPageView(); + const vcl::Region aPaintRectRegion(rRect); + + // #i74769# + SdrPaintWindow* pTargetPaintWindow = nullptr; + + // mark repaint start + if (pPgView) + { + pTargetPaintWindow = pPgView->GetView().BeginDrawLayers(GetOutDev(), aPaintRectRegion); + OSL_ENSURE(pTargetPaintWindow, "BeginDrawLayers: Got no SdrPaintWindow (!)"); + // draw background self using wallpaper + OutputDevice& rTargetOutDev = pTargetPaintWindow->GetTargetOutputDevice(); + rTargetOutDev.DrawWallpaper(rRect, Wallpaper(pPgView->GetApplicationDocumentColor())); + + // do paint (unbuffered) and mark repaint end + pPgView->DrawLayer(RPT_LAYER_FRONT, &rRenderContext); + pPgView->GetView().EndDrawLayers(*pTargetPaintWindow, true); + } + + m_pView->CompleteRedraw(&rRenderContext, aPaintRectRegion); + --m_nPaintEntranceCount; +} + +void OReportSection::fill() +{ + if ( !m_xSection.is() ) + return; + + m_pMulti = new comphelper::OPropertyChangeMultiplexer(this,m_xSection); + m_pMulti->addProperty(PROPERTY_BACKCOLOR); + + m_pReportListener = addStyleListener(m_xSection->getReportDefinition(),this); + + m_pModel = m_pParent->getViewsWindow()->getView()->getReportView()->getController().getSdrModel(); + m_pPage = m_pModel->getPage(m_xSection); + + m_pView = new OSectionView( + *m_pModel, + this, + m_pParent->getViewsWindow()->getView()); + + // #i93597# tell SdrPage that only left and right page border is defined + // instead of the full rectangle definition + m_pPage->setPageBorderOnlyLeftRight(true); + + // without the following call, no grid is painted + m_pView->ShowSdrPage( m_pPage ); + + m_pView->SetMoveSnapOnlyTopLeft( true ); + ODesignView* pDesignView = m_pParent->getViewsWindow()->getView()->getReportView(); + + // #i93595# Adapted grid to a more coarse grid and subdivisions for better visualisation. This + // is only for visualisation and has nothing to do with the actual snap + const Size aGridSizeCoarse(pDesignView->getGridSizeCoarse()); + const Size aGridSizeFine(pDesignView->getGridSizeFine()); + m_pView->SetGridCoarse(aGridSizeCoarse); + m_pView->SetGridFine(aGridSizeFine); + + // #i93595# set snap grid width to snap to all existing subdivisions + const Fraction aX(aGridSizeFine.Width()); + const Fraction aY(aGridSizeFine.Height()); + m_pView->SetSnapGridWidth(aX, aY); + + m_pView->SetGridSnap( true ); + m_pView->SetGridFront( false ); + m_pView->SetDragStripes( true ); + m_pView->SetPageVisible(); + sal_Int32 nColor = m_xSection->getBackColor(); + if ( nColor == static_cast<sal_Int32>(COL_TRANSPARENT) ) + nColor = getStyleProperty<sal_Int32>(m_xSection->getReportDefinition(),PROPERTY_BACKCOLOR); + m_pView->SetApplicationDocumentColor(Color(ColorTransparency, nColor)); + + uno::Reference<report::XReportDefinition> xReportDefinition = m_xSection->getReportDefinition(); + const sal_Int32 nLeftMargin = getStyleProperty<sal_Int32>(xReportDefinition,PROPERTY_LEFTMARGIN); + const sal_Int32 nRightMargin = getStyleProperty<sal_Int32>(xReportDefinition,PROPERTY_RIGHTMARGIN); + m_pPage->SetLeftBorder(nLeftMargin); + m_pPage->SetRightBorder(nRightMargin); + +// LLA: TODO +// m_pPage->SetUpperBorder(-10000); + + m_pView->SetDesignMode(); + + m_pPage->SetSize( Size( getStyleProperty<awt::Size>(xReportDefinition,PROPERTY_PAPERSIZE).Width,5*m_xSection->getHeight()) ); + const Size aPageSize = m_pPage->GetSize(); + m_pView->SetWorkArea( tools::Rectangle( Point( nLeftMargin, 0), Size(aPageSize.Width() - nLeftMargin - nRightMargin,aPageSize.Height()) ) ); +} + +void OReportSection::Paste(const uno::Sequence< beans::NamedValue >& _aAllreadyCopiedObjects,bool _bForce) +{ + OSL_ENSURE(m_xSection.is(),"Why is the section here NULL!"); + if ( !(m_xSection.is() && _aAllreadyCopiedObjects.hasElements()) ) + return; + + // stop all drawing actions + m_pView->BrkAction(); + + // unmark all objects + m_pView->UnmarkAll(); + const OUString sSectionName = m_xSection->getName(); + for(const beans::NamedValue& rObject : _aAllreadyCopiedObjects) + { + if ( _bForce || rObject.Name == sSectionName) + { + try + { + uno::Sequence< uno::Reference<report::XReportComponent> > aCopies; + rObject.Value >>= aCopies; + for (const uno::Reference<report::XReportComponent>& rCopy : std::as_const(aCopies)) + { + SdrObject* pObject = SdrObject::getSdrObjectFromXShape( rCopy ); + if ( pObject ) + { + // Clone to target SdrModel + SdrObject* pNewObj(pObject->CloneSdrObject(*m_pModel)); + m_pPage->InsertObject(pNewObj, SAL_MAX_SIZE); + tools::Rectangle aRet(VCLPoint(rCopy->getPosition()),VCLSize(rCopy->getSize())); + aRet.setHeight(aRet.getHeight() + 1); + aRet.setWidth(aRet.getWidth() + 1); + bool bOverlapping = true; + while ( bOverlapping ) + { + bOverlapping = isOver(aRet,*m_pPage,*m_pView,true,pNewObj) != nullptr; + if ( bOverlapping ) + { + aRet.Move(0,aRet.getHeight()+1); + pNewObj->SetLogicRect(aRet); + } + } + m_pView->AddUndo( m_pView->GetModel()->GetSdrUndoFactory().CreateUndoNewObject( *pNewObj ) ); + m_pView->MarkObj( pNewObj, m_pView->GetSdrPageView() ); + if ( m_xSection.is() && (o3tl::make_unsigned(aRet.getHeight() + aRet.Top()) > m_xSection->getHeight()) ) + m_xSection->setHeight(aRet.getHeight() + aRet.Top()); + } + } + } + catch(uno::Exception&) + { + TOOLS_WARN_EXCEPTION( "reportdesign", "Exception caught while pasting a new object!"); + } + if ( !_bForce ) + break; + } + } +} + +void OReportSection::Delete() +{ + if( !m_pView->AreObjectsMarked() ) + return; + + m_pView->BrkAction(); + m_pView->DeleteMarked(); +} + +void OReportSection::SetMode( DlgEdMode eNewMode ) +{ + if ( eNewMode == m_eMode ) + return; + + if ( eNewMode == DlgEdMode::Insert ) + { + m_pFunc.reset(new DlgEdFuncInsert( this )); + } + else + { + m_pFunc.reset(new DlgEdFuncSelect( this )); + } + m_pFunc->setOverlappedControlColor(lcl_getOverlappedControlColor( ) ); + m_pModel->SetReadOnly(false); + m_eMode = eNewMode; +} + +void OReportSection::Copy(uno::Sequence< beans::NamedValue >& _rAllreadyCopiedObjects) +{ + Copy(_rAllreadyCopiedObjects,false); +} + +void OReportSection::Copy(uno::Sequence< beans::NamedValue >& _rAllreadyCopiedObjects,bool _bEraseAnddNoClone) +{ + OSL_ENSURE(m_xSection.is(),"Why is the section here NULL!"); + if( !m_pView->AreObjectsMarked() || !m_xSection.is() ) + return; + + // insert control models of marked objects into clipboard dialog model + const SdrMarkList& rMarkedList = m_pView->GetMarkedObjectList(); + const size_t nMark = rMarkedList.GetMarkCount(); + + ::std::vector< uno::Reference<report::XReportComponent> > aCopies; + aCopies.reserve(nMark); + + SdrUndoFactory& rUndo = m_pView->GetModel()->GetSdrUndoFactory(); + + for( size_t i = nMark; i > 0; ) + { + --i; + SdrObject* pSdrObject = rMarkedList.GetMark(i)->GetMarkedSdrObj(); + OObjectBase* pObj = dynamic_cast<OObjectBase*>(pSdrObject); + if ( pObj ) + { + try + { + SdrObject* pNewObj(pSdrObject->CloneSdrObject(pSdrObject->getSdrModelFromSdrObject())); + aCopies.emplace_back(pNewObj->getUnoShape(),uno::UNO_QUERY); + if ( _bEraseAnddNoClone ) + { + m_pView->AddUndo( rUndo.CreateUndoDeleteObject( *pSdrObject ) ); + m_pPage->RemoveObject(pSdrObject->GetOrdNum()); + } + + } + catch(uno::Exception&) + { + OSL_FAIL("Can't copy report elements!"); + } + } + } + + if ( !aCopies.empty() ) + { + ::std::reverse(aCopies.begin(),aCopies.end()); + const sal_Int32 nLength = _rAllreadyCopiedObjects.getLength(); + _rAllreadyCopiedObjects.realloc( nLength + 1); + beans::NamedValue* pNewValue = _rAllreadyCopiedObjects.getArray() + nLength; + pNewValue->Name = m_xSection->getName(); + pNewValue->Value <<= uno::Sequence< uno::Reference<report::XReportComponent> >(&(*aCopies.begin()),aCopies.size()); + } +} + +void OReportSection::MouseButtonDown( const MouseEvent& rMEvt ) +{ + m_pParent->getViewsWindow()->getView()->setMarked(m_pView, true); // mark the section in which is clicked + m_pFunc->MouseButtonDown( rMEvt ); + Window::MouseButtonDown(rMEvt); +} + +void OReportSection::MouseButtonUp( const MouseEvent& rMEvt ) +{ + if ( !m_pFunc->MouseButtonUp( rMEvt ) ) + m_pParent->getViewsWindow()->getView()->getReportView()->getController().executeUnChecked(SID_OBJECT_SELECT,uno::Sequence< beans::PropertyValue>()); +} + + +void OReportSection::MouseMove( const MouseEvent& rMEvt ) +{ + m_pFunc->MouseMove( rMEvt ); + +} + +void OReportSection::SetGridVisible(bool _bVisible) +{ + m_pView->SetGridVisible( _bVisible ); +} + +void OReportSection::SelectAll(const SdrObjKind _nObjectType) +{ + if ( !m_pView ) + return; + + if ( _nObjectType == SdrObjKind::NONE ) + m_pView->MarkAllObj(); + else + { + m_pView->UnmarkAll(); + SdrObjListIter aIter(m_pPage,SdrIterMode::DeepNoGroups); + SdrObject* pObjIter = nullptr; + while( (pObjIter = aIter.Next()) != nullptr ) + { + if ( pObjIter->GetObjIdentifier() == _nObjectType ) + m_pView->MarkObj( pObjIter, m_pView->GetSdrPageView() ); + } + } +} + +void OReportSection::Command( const CommandEvent& _rCEvt ) +{ + Window::Command(_rCEvt); + if (_rCEvt.GetCommand() != CommandEventId::ContextMenu) + return; + + OReportController& rController = m_pParent->getViewsWindow()->getView()->getReportView()->getController(); + uno::Reference<frame::XFrame> xFrame = rController.getFrame(); + css::uno::Sequence<css::uno::Any> aArgs { + css::uno::Any(comphelper::makePropertyValue("Value", OUString("report"))), + css::uno::Any(comphelper::makePropertyValue("Frame", xFrame)), + css::uno::Any(comphelper::makePropertyValue("IsContextMenu", true)) + }; + + css::uno::Reference<css::uno::XComponentContext> xContext(rController.getORB()); + css::uno::Reference<css::frame::XPopupMenuController> xMenuController( + xContext->getServiceManager()->createInstanceWithArgumentsAndContext( + "com.sun.star.comp.framework.ResourceMenuController", aArgs, xContext), css::uno::UNO_QUERY); + + if (!xMenuController.is()) + return; + + css::uno::Reference<css::awt::XPopupMenu> xPopupMenu( + xContext->getServiceManager()->createInstanceWithContext( + "com.sun.star.awt.PopupMenu", xContext), css::uno::UNO_QUERY); + + if (!xPopupMenu.is()) + return; + + xMenuController->setPopupMenu(xPopupMenu); + + Point aPos = _rCEvt.GetMousePosPixel(); + m_pView->EndAction(); + + xPopupMenu->execute(GetComponentInterface(), + css::awt::Rectangle(aPos.X(), aPos.Y(), 1, 1), + css::awt::PopupMenuDirection::EXECUTE_DOWN); + + css::uno::Reference<css::lang::XComponent> xComponent(xMenuController, css::uno::UNO_QUERY); + xComponent->dispose(); +} + +void OReportSection::_propertyChanged(const beans::PropertyChangeEvent& _rEvent) +{ + if ( !m_xSection.is() ) + return; + + if ( _rEvent.Source == m_xSection || PROPERTY_BACKCOLOR == _rEvent.PropertyName ) + { + sal_Int32 nColor = m_xSection->getBackColor(); + if ( nColor == static_cast<sal_Int32>(COL_TRANSPARENT) ) + nColor = getStyleProperty<sal_Int32>(m_xSection->getReportDefinition(),PROPERTY_BACKCOLOR); + m_pView->SetApplicationDocumentColor(Color(ColorTransparency, nColor)); + Invalidate(InvalidateFlags::NoChildren|InvalidateFlags::NoErase); + } + else + { + uno::Reference<report::XReportDefinition> xReportDefinition = m_xSection->getReportDefinition(); + const sal_Int32 nLeftMargin = getStyleProperty<sal_Int32>(xReportDefinition,PROPERTY_LEFTMARGIN); + const sal_Int32 nRightMargin = getStyleProperty<sal_Int32>(xReportDefinition,PROPERTY_RIGHTMARGIN); + const sal_Int32 nPaperWidth = getStyleProperty<awt::Size>(xReportDefinition,PROPERTY_PAPERSIZE).Width; + + if ( _rEvent.PropertyName == PROPERTY_LEFTMARGIN ) + { + m_pPage->SetLeftBorder(nLeftMargin); + } + else if ( _rEvent.PropertyName == PROPERTY_RIGHTMARGIN ) + { + m_pPage->SetRightBorder(nRightMargin); + } + const Size aOldPageSize = m_pPage->GetSize(); + sal_Int32 nNewHeight = 5*m_xSection->getHeight(); + if ( aOldPageSize.Height() != nNewHeight || nPaperWidth != aOldPageSize.Width() ) + { + m_pPage->SetSize( Size( nPaperWidth,nNewHeight) ); + const Size aPageSize = m_pPage->GetSize(); + m_pView->SetWorkArea( tools::Rectangle( Point( nLeftMargin, 0), Size(aPageSize.Width() - nLeftMargin - nRightMargin,aPageSize.Height()) ) ); + } + impl_adjustObjectSizePosition(nPaperWidth,nLeftMargin,nRightMargin); + m_pParent->Invalidate(InvalidateFlags::Update | InvalidateFlags::Transparent); + } +} +void OReportSection::impl_adjustObjectSizePosition(sal_Int32 i_nPaperWidth,sal_Int32 i_nLeftMargin,sal_Int32 i_nRightMargin) +{ + try + { + sal_Int32 nRightBorder = i_nPaperWidth - i_nRightMargin; + const sal_Int32 nCount = m_xSection->getCount(); + for (sal_Int32 i = 0; i < nCount; ++i) + { + uno::Reference< report::XReportComponent> xReportComponent(m_xSection->getByIndex(i),uno::UNO_QUERY_THROW); + awt::Point aPos = xReportComponent->getPosition(); + awt::Size aSize = xReportComponent->getSize(); + SdrObject* pObject = SdrObject::getSdrObjectFromXShape( xReportComponent ); + if ( pObject ) + { + bool bChanged = false; + + OObjectBase& rBase = dynamic_cast<OObjectBase&>(*pObject); + rBase.EndListening(); + if ( aPos.X < i_nLeftMargin ) + { + aPos.X = i_nLeftMargin; + bChanged = true; + } + if ( (aPos.X + aSize.Width) > nRightBorder ) + { + aPos.X = nRightBorder - aSize.Width; + if ( aPos.X < i_nLeftMargin ) + { + aSize.Width += aPos.X - i_nLeftMargin; + aPos.X = i_nLeftMargin; + // add listener around + rBase.StartListening(); + xReportComponent->setSize(aSize); + rBase.EndListening(); + } + bChanged = true; + } + if ( aPos.Y < 0 ) + aPos.Y = 0; + if ( bChanged ) + { + xReportComponent->setPosition(aPos); + correctOverlapping(pObject,*this,false); + tools::Rectangle aRet(VCLPoint(xReportComponent->getPosition()),VCLSize(xReportComponent->getSize())); + aRet.setHeight(aRet.getHeight() + 1); + aRet.setWidth(aRet.getWidth() + 1); + if ( m_xSection.is() && (o3tl::make_unsigned(aRet.getHeight() + aRet.Top()) > m_xSection->getHeight()) ) + m_xSection->setHeight(aRet.getHeight() + aRet.Top()); + + pObject->RecalcBoundRect(); + } + rBase.StartListening(); + } + } + } + catch(const uno::Exception &) + { + TOOLS_WARN_EXCEPTION( "reportdesign", "OReportSection::impl_adjustObjectSizePosition()"); + } +} + +bool OReportSection::handleKeyEvent(const KeyEvent& _rEvent) +{ + return m_pFunc && m_pFunc->handleKeyEvent(_rEvent); +} + +void OReportSection::deactivateOle() +{ + if (m_pFunc) + m_pFunc->deactivateOle(true); +} + +void OReportSection::createDefault(const OUString& _sType) +{ + SdrObject* pObj = m_pView->GetCreateObj(); + if ( !pObj ) + return; + createDefault(_sType,pObj); +} + +void OReportSection::createDefault(const OUString& _sType,SdrObject* _pObj) +{ + bool bAttributesAppliedFromGallery = false; + + if ( GalleryExplorer::GetSdrObjCount( GALLERY_THEME_POWERPOINT ) ) + { + std::vector< OUString > aObjList; + if ( GalleryExplorer::FillObjListTitle( GALLERY_THEME_POWERPOINT, aObjList ) ) + { + auto aIter = std::find_if(aObjList.begin(), aObjList.end(), + [&_sType](const OUString& rObj) { return rObj.equalsIgnoreAsciiCase(_sType); }); + if (aIter != aObjList.end()) + { + auto i = static_cast<sal_uInt32>(std::distance(aObjList.begin(), aIter)); + OReportModel aReportModel(nullptr); + SfxItemPool& rPool = aReportModel.GetItemPool(); + rPool.FreezeIdRanges(); + if ( GalleryExplorer::GetSdrObj( GALLERY_THEME_POWERPOINT, i, &aReportModel ) ) + { + const SdrObject* pSourceObj = aReportModel.GetPage( 0 )->GetObj( 0 ); + if( pSourceObj ) + { + const SfxItemSet& rSource = pSourceObj->GetMergedItemSet(); + SfxItemSetFixed< + // Ranges from SdrAttrObj: + SDRATTR_START, SDRATTR_SHADOW_LAST, + SDRATTR_MISC_FIRST, SDRATTR_MISC_LAST, + SDRATTR_TEXTDIRECTION, + SDRATTR_TEXTDIRECTION, + // Graphic attributes, 3D properties, + // CustomShape properties: + SDRATTR_GRAF_FIRST, + SDRATTR_CUSTOMSHAPE_LAST, + // Range from SdrTextObj: + EE_ITEMS_START, EE_ITEMS_END> + aDest( _pObj->getSdrModelFromSdrObject().GetItemPool() ); + aDest.Set( rSource ); + _pObj->SetMergedItemSet( aDest ); + Degree100 nAngle = pSourceObj->GetRotateAngle(); + if ( nAngle ) + _pObj->NbcRotate( _pObj->GetSnapRect().Center(), nAngle ); + bAttributesAppliedFromGallery = true; + } + } + } + } + } + if ( !bAttributesAppliedFromGallery ) + { + _pObj->SetMergedItem( SvxAdjustItem( SvxAdjust::Center, EE_PARA_JUST) ); + _pObj->SetMergedItem( SdrTextVertAdjustItem( SDRTEXTVERTADJUST_CENTER ) ); + _pObj->SetMergedItem( SdrTextHorzAdjustItem( SDRTEXTHORZADJUST_BLOCK ) ); + _pObj->SetMergedItem( makeSdrTextAutoGrowHeightItem( false ) ); + static_cast<SdrObjCustomShape*>(_pObj)->MergeDefaultAttributes( &_sType ); + } +} + +uno::Reference< report::XReportComponent > OReportSection::getCurrentControlModel() const +{ + uno::Reference< report::XReportComponent > xModel; + if ( m_pView ) + { + const SdrMarkList& rMarkList = m_pView->GetMarkedObjectList(); + + if ( rMarkList.GetMarkCount() == 1 ) + { + SdrObject* pDlgEdObj = rMarkList.GetMark(0)->GetMarkedSdrObj(); + OObjectBase* pObj = dynamic_cast<OObjectBase*>(pDlgEdObj); + if ( pObj ) + xModel = pObj->getReportComponent().get(); + } + } + return xModel; +} + +void OReportSection::fillControlModelSelection(::std::vector< uno::Reference< uno::XInterface > >& _rSelection) const +{ + if ( !m_pView ) + return; + + const SdrMarkList& rMarkList = m_pView->GetMarkedObjectList(); + const size_t nMarkCount = rMarkList.GetMarkCount(); + + for (size_t i=0; i < nMarkCount; ++i) + { + const SdrObject* pDlgEdObj = rMarkList.GetMark(i)->GetMarkedSdrObj(); + const OObjectBase* pObj = dynamic_cast<const OObjectBase*>(pDlgEdObj); + if ( pObj ) + { + uno::Reference<uno::XInterface> xInterface(pObj->getReportComponent()); + _rSelection.push_back(xInterface); + } + } +} + +sal_Int8 OReportSection::AcceptDrop( const AcceptDropEvent& _rEvt ) +{ + ::Point aDropPos(_rEvt.maPosPixel); + const MouseEvent aMouseEvt(aDropPos); + if ( m_pFunc->isOverlapping(aMouseEvt) ) + return DND_ACTION_NONE; + + if ( _rEvt.mnAction == DND_ACTION_COPY || + _rEvt.mnAction == DND_ACTION_LINK + ) + { + if (!m_pParent) return DND_ACTION_NONE; + sal_uInt16 nCurrentPosition = m_pParent->getViewsWindow()->getPosition(m_pParent); + if (_rEvt.mnAction == DND_ACTION_COPY ) + { + // we must assure, we can't drop in the top section + if (nCurrentPosition < 1) + { + return DND_ACTION_NONE; + } + return DND_ACTION_LINK; + } + if (_rEvt.mnAction == DND_ACTION_LINK) + { + // we must assure, we can't drop in the bottom section + if (m_pParent->getViewsWindow()->getSectionCount() > (nCurrentPosition + 1) ) + { + return DND_ACTION_COPY; + } + return DND_ACTION_NONE; + } + } + else + { + const DataFlavorExVector& rFlavors = GetDataFlavorExVector(); + if ( svx::OMultiColumnTransferable::canExtractDescriptor(rFlavors) + || svx::OColumnTransferable::canExtractColumnDescriptor(rFlavors, ColumnTransferFormatFlags::FIELD_DESCRIPTOR | ColumnTransferFormatFlags::CONTROL_EXCHANGE | ColumnTransferFormatFlags::COLUMN_DESCRIPTOR) ) + return _rEvt.mnAction; + + const sal_Int8 nDropOption = ( OReportExchange::canExtract(rFlavors) ) ? DND_ACTION_COPYMOVE : DND_ACTION_NONE; + + return nDropOption; + } + return DND_ACTION_NONE; +} + + +sal_Int8 OReportSection::ExecuteDrop( const ExecuteDropEvent& _rEvt ) +{ + ::Point aDropPos(PixelToLogic(_rEvt.maPosPixel)); + const MouseEvent aMouseEvt(aDropPos); + if ( m_pFunc->isOverlapping(aMouseEvt) ) + return DND_ACTION_NONE; + + sal_Int8 nDropOption = DND_ACTION_NONE; + const TransferableDataHelper aDropped(_rEvt.maDropEvent.Transferable); + const DataFlavorExVector& rFlavors = aDropped.GetDataFlavorExVector(); + bool bMultipleFormat = svx::OMultiColumnTransferable::canExtractDescriptor(rFlavors); + if ( OReportExchange::canExtract(rFlavors) ) + { + OReportExchange::TSectionElements aCopies = OReportExchange::extractCopies(aDropped); + Paste(aCopies,true); + nDropOption = DND_ACTION_COPYMOVE; + m_pParent->getViewsWindow()->BrkAction(); + m_pParent->getViewsWindow()->unmarkAllObjects(m_pView); + } + else if ( bMultipleFormat + || svx::OColumnTransferable::canExtractColumnDescriptor(rFlavors, ColumnTransferFormatFlags::FIELD_DESCRIPTOR | ColumnTransferFormatFlags::CONTROL_EXCHANGE | ColumnTransferFormatFlags::COLUMN_DESCRIPTOR) ) + { + m_pParent->getViewsWindow()->getView()->setMarked(m_pView, true); + m_pView->UnmarkAll(); + const tools::Rectangle& rRect = m_pView->GetWorkArea(); + if ( aDropPos.X() < rRect.Left() ) + aDropPos.setX( rRect.Left() ); + else if ( aDropPos.X() > rRect.Right() ) + aDropPos.setX( rRect.Right() ); + + if ( aDropPos.Y() > rRect.Bottom() ) + aDropPos.setY( rRect.Bottom() ); + + uno::Sequence<beans::PropertyValue> aValues; + if ( !bMultipleFormat ) + { + svx::ODataAccessDescriptor aDescriptor = svx::OColumnTransferable::extractColumnDescriptor(aDropped); + + aValues.realloc(1); + aValues.getArray()[0].Value <<= aDescriptor.createPropertyValueSequence(); + } + else + aValues = svx::OMultiColumnTransferable::extractDescriptor(aDropped); + + for(beans::PropertyValue & propVal : asNonConstRange(aValues)) + { + uno::Sequence<beans::PropertyValue> aCurrent; + propVal.Value >>= aCurrent; + sal_Int32 nLength = aCurrent.getLength(); + if ( nLength ) + { + aCurrent.realloc(nLength + 3); + auto pCurrent = aCurrent.getArray(); + pCurrent[nLength].Name = PROPERTY_POSITION; + pCurrent[nLength++].Value <<= AWTPoint(aDropPos); + // give also the DND Action (Shift|Ctrl) Key to really say what we want + pCurrent[nLength].Name = "DNDAction"; + pCurrent[nLength++].Value <<= _rEvt.mnAction; + + pCurrent[nLength].Name = "Section"; + pCurrent[nLength++].Value <<= getSection(); + propVal.Value <<= aCurrent; + } + } + + // we use this way to create undo actions + OReportController& rController = m_pParent->getViewsWindow()->getView()->getReportView()->getController(); + rController.executeChecked(SID_ADD_CONTROL_PAIR,aValues); + nDropOption = DND_ACTION_COPY; + } + return nDropOption; +} + +void OReportSection::stopScrollTimer() +{ + m_pFunc->stopScrollTimer(); +} + +bool OReportSection::isUiActive() const +{ + return m_pFunc->isUiActive(); +} + + +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/reportdesign/source/ui/report/ReportWindow.cxx b/reportdesign/source/ui/report/ReportWindow.cxx new file mode 100644 index 000000000..8da0855f6 --- /dev/null +++ b/reportdesign/source/ui/report/ReportWindow.cxx @@ -0,0 +1,433 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * 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 . + */ +#include <ReportWindow.hxx> +#include <ReportSection.hxx> +#include <SectionView.hxx> +#include <ViewsWindow.hxx> +#include <DesignView.hxx> +#include <UITools.hxx> + +#include <unotools/syslocale.hxx> +#include <unotools/localedatawrapper.hxx> + +#include <vcl/settings.hxx> + +#include <RptDef.hxx> +#include <strings.hxx> +#include <ReportController.hxx> +#include <ScrollHelper.hxx> + +#include <helpids.h> +#include <dlgedfac.hxx> + + +#define SECTION_OFFSET 3 +namespace rptui +{ +using namespace ::com::sun::star; +using namespace ::comphelper; + + + +OReportWindow::OReportWindow(OScrollWindowHelper* _pParent,ODesignView* _pView) +: Window(_pParent,WB_DIALOGCONTROL) +, ::comphelper::OPropertyChangeListener(m_aMutex) +,m_aHRuler(VclPtr<Ruler>::Create(this)) +,m_pView(_pView) +,m_pParent(_pParent) +,m_aViewsWindow(VclPtr<rptui::OViewsWindow>::Create(this)) +,m_pObjFac( new DlgEdFactory() ) +{ + SetHelpId(UID_RPT_REPORTWINDOW); + SetMapMode( MapMode( MapUnit::Map100thMM ) ); + + m_aViewsWindow->Show(); + + m_aHRuler->Show(); + m_aHRuler->Activate(); + m_aHRuler->SetPagePos(); + m_aHRuler->SetBorders(); + m_aHRuler->SetIndents(); + m_aHRuler->SetMargin1(); + m_aHRuler->SetMargin2(); + const MeasurementSystem eSystem = SvtSysLocale().GetLocaleData().getMeasurementSystemEnum(); + m_aHRuler->SetUnit(MeasurementSystem::Metric == eSystem ? FieldUnit::CM : FieldUnit::INCH); + + ImplInitSettings(); + m_pReportListener = addStyleListener(_pView->getController().getReportDefinition(),this); +} + +OReportWindow::~OReportWindow() +{ + disposeOnce(); +} + +void OReportWindow::dispose() +{ + if ( m_pReportListener.is() ) + m_pReportListener->dispose(); + m_aHRuler.disposeAndClear(); + m_aViewsWindow.disposeAndClear(); + m_pView.clear(); + m_pParent.clear(); + vcl::Window::dispose(); +} + +void OReportWindow::SetInsertObj( SdrObjKind eObj,const OUString& _sShapeType ) +{ + m_aViewsWindow->SetInsertObj( eObj,_sShapeType); +} + +OUString const & OReportWindow::GetInsertObjString() const +{ + return m_aViewsWindow->GetInsertObjString(); +} + +void OReportWindow::SetMode( DlgEdMode eNewMode ) +{ + m_aViewsWindow->SetMode(eNewMode); +} + +void OReportWindow::removeSection(sal_uInt16 _nPosition) +{ + m_aViewsWindow->removeSection(_nPosition); + m_pParent->setTotalSize(GetTotalWidth(),GetTotalHeight()); + m_aViewsWindow->Invalidate(InvalidateFlags::Transparent); +} + +void OReportWindow::addSection(const uno::Reference< report::XSection >& _xSection,const OUString& _sColorEntry,sal_uInt16 _nPosition) +{ + if ( !_xSection.is() ) + return; + + m_aViewsWindow->addSection(_xSection,_sColorEntry,_nPosition); + + m_pParent->setTotalSize(GetTotalWidth(),GetTotalHeight()); +} + +void OReportWindow::toggleGrid(bool _bVisible) +{ + m_aViewsWindow->toggleGrid(_bVisible); +} + +void OReportWindow::showRuler(bool _bShow) +{ + m_aHRuler->Show(_bShow); + + m_aViewsWindow->showRuler(_bShow); +} + +sal_Int32 OReportWindow::getMaxMarkerWidth() const +{ + Fraction aStartWidth(tools::Long(REPORT_STARTMARKER_WIDTH)); + aStartWidth *= m_aViewsWindow->GetMapMode().GetScaleX(); + return sal_Int32(static_cast<tools::Long>(aStartWidth)); +} + +sal_Int32 OReportWindow::GetTotalWidth() const +{ + sal_Int32 nWidth = 0; + if ( !m_aViewsWindow->empty() ) + { + Fraction aStartWidth(tools::Long(REPORT_ENDMARKER_WIDTH + REPORT_STARTMARKER_WIDTH )); + const Fraction aZoom(m_pView->getController().getZoomValue(),100); + aStartWidth *= aZoom; + sal_Int32 nPaperWidth = getStyleProperty<awt::Size>(m_pView->getController().getReportDefinition(),PROPERTY_PAPERSIZE).Width; + nPaperWidth = tools::Long(nPaperWidth * aZoom); + const Size aPageSize = LogicToPixel(Size(nPaperWidth,0)); + nWidth = aPageSize.Width() + tools::Long(aStartWidth); + } + return nWidth; +} + +void OReportWindow::Resize() +{ + Window::Resize(); + if ( m_aViewsWindow->empty() ) + return; + + const Size aTotalOutputSize = GetOutputSizePixel(); + Fraction aStartWidth(tools::Long(REPORT_STARTMARKER_WIDTH)*m_pView->getController().getZoomValue(),100); + + const Point aOffset = LogicToPixel(Point(SECTION_OFFSET, 0), MapMode(MapUnit::MapAppFont)); + Point aStartPoint(static_cast<tools::Long>(aStartWidth) + aOffset.X(),0); + uno::Reference<report::XReportDefinition> xReportDefinition = getReportView()->getController().getReportDefinition(); + const sal_Int32 nPaperWidth = getStyleProperty<awt::Size>(xReportDefinition,PROPERTY_PAPERSIZE).Width; + sal_Int32 nLeftMargin = getStyleProperty<sal_Int32>(xReportDefinition,PROPERTY_LEFTMARGIN); + sal_Int32 nRightMargin = getStyleProperty<sal_Int32>(xReportDefinition,PROPERTY_RIGHTMARGIN); + Size aPageSize = m_aViewsWindow->LogicToPixel(Size(nPaperWidth ,0)); + nLeftMargin = m_aViewsWindow->LogicToPixel(Size(nLeftMargin,0)).Width(); + nRightMargin = m_aViewsWindow->LogicToPixel(Size(nRightMargin,0)).Width(); + + aPageSize.setHeight( m_aHRuler->GetSizePixel().Height() ); + + const tools::Long nTermp(m_aViewsWindow->getTotalHeight() + aPageSize.Height()); + tools::Long nSectionsHeight = ::std::max<tools::Long>(nTermp,aTotalOutputSize.Height()); + + m_aHRuler->SetPosSizePixel(aStartPoint,aPageSize); + m_aHRuler->SetNullOffset(nLeftMargin); + m_aHRuler->SetMargin1(0); + m_aHRuler->SetMargin2(aPageSize.Width() - nLeftMargin - nRightMargin); + + aStartPoint.AdjustY(aPageSize.Height() ); + nSectionsHeight -= aStartPoint.Y(); + + aStartPoint.setX( aOffset.X() ); + + m_aViewsWindow->SetPosSizePixel(aStartPoint,Size(aTotalOutputSize.Width(),nSectionsHeight)); +} + +Point OReportWindow::getThumbPos() const +{ + return m_pParent->getThumbPos(); +} + +void OReportWindow::ImplInitSettings() +{ + SetBackground( ); +} + +void OReportWindow::DataChanged( const DataChangedEvent& rDCEvt ) +{ + Window::DataChanged( rDCEvt ); + + if ( (rDCEvt.GetType() == DataChangedEventType::SETTINGS) && + (rDCEvt.GetFlags() & AllSettingsFlags::STYLE) ) + { + ImplInitSettings(); + Invalidate(); + } +} + +sal_Int32 OReportWindow::GetTotalHeight() const +{ + return m_aViewsWindow->getTotalHeight(); +} + +void OReportWindow::ScrollChildren(const Point& _aThumbPos) +{ + MapMode aMap = m_aHRuler->GetMapMode(); + Point aOrg( aMap.GetOrigin() ); + if ( aOrg.X() != (-_aThumbPos.X()) ) + { + aMap.SetOrigin( Point(- _aThumbPos.X(), aOrg.Y())); + m_aHRuler->SetMapMode( aMap ); + m_aHRuler->Scroll(-(aOrg.X() + _aThumbPos.X()),0); + } + + m_aViewsWindow->scrollChildren(_aThumbPos); +} + +sal_uInt16 OReportWindow::getSectionCount() const +{ + return m_aViewsWindow->getSectionCount(); +} + +void OReportWindow::notifySizeChanged() +{ + m_pParent->setTotalSize(GetTotalWidth(),GetTotalHeight()); +} + +bool OReportWindow::HasSelection() const +{ + return m_aViewsWindow->HasSelection(); +} + +void OReportWindow::Delete() +{ + + m_aViewsWindow->Delete(); +} + +void OReportWindow::Copy() +{ + + m_aViewsWindow->Copy(); +} + +void OReportWindow::Paste() +{ + + m_aViewsWindow->Paste(); +} + +bool OReportWindow::IsPasteAllowed() const +{ + return m_aViewsWindow->IsPasteAllowed(); +} + +void OReportWindow::SelectAll(const SdrObjKind _nObjectType) +{ + + m_aViewsWindow->SelectAll(_nObjectType); +} + +void OReportWindow::unmarkAllObjects() +{ + + m_aViewsWindow->unmarkAllObjects(nullptr); +} + +void OReportWindow::showProperties(const uno::Reference< report::XSection>& _xReportComponent) +{ + OSectionWindow* pSectionWindow = m_aViewsWindow->getSectionWindow( _xReportComponent ); + m_pView->UpdatePropertyBrowserDelayed(pSectionWindow->getReportSection().getSectionView()); +} + +bool OReportWindow::handleKeyEvent(const KeyEvent& _rEvent) +{ + return m_aViewsWindow->handleKeyEvent(_rEvent); +} + +void OReportWindow::setMarked(OSectionView const * _pSectionView, bool _bMark) +{ + if ( _pSectionView ) + m_aViewsWindow->setMarked(_pSectionView,_bMark); +} + +void OReportWindow::setMarked(const uno::Reference< report::XSection>& _xSection, bool _bMark) +{ + + m_aViewsWindow->setMarked(_xSection,_bMark); +} + +void OReportWindow::setMarked(const uno::Sequence< uno::Reference< report::XReportComponent> >& _xShape, bool _bMark) +{ + + m_aViewsWindow->setMarked(_xShape,_bMark); +} + +OSectionWindow* OReportWindow::getMarkedSection(NearSectionAccess nsa) const +{ + return m_aViewsWindow->getMarkedSection(nsa); +} + +OSectionWindow* OReportWindow::getSectionWindow(const css::uno::Reference< css::report::XSection>& _xSection) const +{ + return m_aViewsWindow->getSectionWindow(_xSection); +} + +void OReportWindow::markSection(const sal_uInt16 _nPos) +{ + + m_aViewsWindow->markSection(_nPos); +} + +void OReportWindow::fillCollapsedSections(::std::vector<sal_uInt16>& _rCollapsedPositions) const +{ + + m_aViewsWindow->fillCollapsedSections(_rCollapsedPositions); +} + +void OReportWindow::collapseSections(const uno::Sequence< css::beans::PropertyValue>& _aCollapsedSections) +{ + + m_aViewsWindow->collapseSections(_aCollapsedSections); +} + +void OReportWindow::alignMarkedObjects(ControlModification _nControlModification, bool _bAlignAtSection) +{ + m_aViewsWindow->alignMarkedObjects(_nControlModification, _bAlignAtSection); +} + +void OReportWindow::setGridSnap(bool bOn) +{ + + m_aViewsWindow->setGridSnap(bOn); +} + +void OReportWindow::setDragStripes(bool bOn) +{ + m_aViewsWindow->setDragStripes(bOn); +} + +sal_uInt32 OReportWindow::getMarkedObjectCount() const +{ + return m_aViewsWindow->getMarkedObjectCount(); +} + +void OReportWindow::zoom(const Fraction& _aZoom) +{ + m_aHRuler->SetZoom(_aZoom); + m_aHRuler->Invalidate(); + + m_aViewsWindow->zoom(_aZoom); + + notifySizeChanged(); + const Point aNewThumbPos( m_pParent->getThumbPos() ); + + ScrollChildren( aNewThumbPos ); + Resize(); + + Invalidate(InvalidateFlags::NoErase | InvalidateFlags::NoChildren | InvalidateFlags::Transparent); +} + +void OReportWindow::fillControlModelSelection(::std::vector< uno::Reference< uno::XInterface > >& _rSelection) const +{ + m_aViewsWindow->fillControlModelSelection(_rSelection); +} + +sal_Int32 OReportWindow::impl_getRealPixelWidth() const +{ + const sal_Int32 nPaperWidth = getStyleProperty<awt::Size>(m_pView->getController().getReportDefinition(),PROPERTY_PAPERSIZE).Width; + MapMode aMap( MapUnit::Map100thMM ); + const Size aPageSize = LogicToPixel(Size(nPaperWidth,0),aMap); + return aPageSize.Width() + REPORT_ENDMARKER_WIDTH + REPORT_STARTMARKER_WIDTH + SECTION_OFFSET; +} + +sal_uInt16 OReportWindow::getZoomFactor(SvxZoomType _eType) const +{ + sal_uInt16 nZoom(100); + const Size aSize( GetSizePixel() ); + switch( _eType) + { + case SvxZoomType::PERCENT: + nZoom = m_pView->getController().getZoomValue(); + break; + case SvxZoomType::OPTIMAL: + break; + case SvxZoomType::WHOLEPAGE: + { + nZoom = static_cast<sal_uInt16>(static_cast<tools::Long>(Fraction(aSize.Width()*100,impl_getRealPixelWidth()))); + MapMode aMap( MapUnit::Map100thMM ); + const Size aHeight = m_aViewsWindow->LogicToPixel(m_aViewsWindow->PixelToLogic(Size(0,GetTotalHeight() + m_aHRuler->GetSizePixel().Height())),aMap); + nZoom = ::std::min(nZoom,static_cast<sal_uInt16>(static_cast<tools::Long>(Fraction(aSize.Height()*100,aHeight.Height())))); + } + break; + case SvxZoomType::PAGEWIDTH: + nZoom = static_cast<sal_uInt16>(static_cast<tools::Long>(Fraction(aSize.Width()*100,impl_getRealPixelWidth()))); + break; + default: + break; + } + + return nZoom; +} + +void OReportWindow::_propertyChanged(const beans::PropertyChangeEvent&) +{ + Resize(); + m_aViewsWindow->Resize(); + Invalidate(InvalidateFlags::Transparent); +} + +} //rptui + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/reportdesign/source/ui/report/ScrollHelper.cxx b/reportdesign/source/ui/report/ScrollHelper.cxx new file mode 100644 index 000000000..bf5f261cf --- /dev/null +++ b/reportdesign/source/ui/report/ScrollHelper.cxx @@ -0,0 +1,412 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * 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 . + */ +#include <ScrollHelper.hxx> +#include <DesignView.hxx> +#include <ReportController.hxx> +#include <ReportWindow.hxx> +#include <UITools.hxx> +#include <com/sun/star/accessibility/AccessibleRole.hpp> + +#include <vcl/commandevent.hxx> +#include <vcl/settings.hxx> +#include <vcl/svapp.hxx> + +namespace rptui +{ +#define SECTION_OFFSET 3 +#define SCR_LINE_SIZE 10 +using namespace ::com::sun::star; + + +static void lcl_setScrollBar(sal_Int32 _nNewValue,const Point& _aPos,const Size& _aSize,ScrollBar& _rScrollBar) +{ + _rScrollBar.SetPosSizePixel(_aPos,_aSize); + _rScrollBar.SetPageSize( _nNewValue ); + _rScrollBar.SetVisibleSize( _nNewValue ); +} + + +OScrollWindowHelper::OScrollWindowHelper( ODesignView* _pDesignView) + : OScrollWindowHelper_BASE( _pDesignView,WB_DIALOGCONTROL) + ,OPropertyChangeListener(m_aMutex) + ,m_aHScroll( VclPtr<ScrollBar>::Create(this, WB_HSCROLL|WB_REPEAT|WB_DRAG) ) + ,m_aVScroll( VclPtr<ScrollBar>::Create(this, WB_VSCROLL|WB_REPEAT|WB_DRAG) ) + ,m_aCornerWin( VclPtr<ScrollBarBox>::Create(this) ) + ,m_pParent(_pDesignView) + ,m_aReportWindow(VclPtr<rptui::OReportWindow>::Create(this,m_pParent)) +{ + SetMapMode( MapMode( MapUnit::Map100thMM ) ); + + impl_initScrollBar( *m_aHScroll ); + impl_initScrollBar( *m_aVScroll ); + + m_aReportWindow->SetMapMode( MapMode( MapUnit::Map100thMM ) ); + m_aReportWindow->Show(); + + // normally we should be SCROLL_PANE + SetAccessibleRole(css::accessibility::AccessibleRole::SCROLL_PANE); + ImplInitSettings(); +} + + +OScrollWindowHelper::~OScrollWindowHelper() +{ + disposeOnce(); +} + +void OScrollWindowHelper::dispose() +{ + if ( m_pReportDefinitionMultiPlexer.is() ) + m_pReportDefinitionMultiPlexer->dispose(); + + m_aHScroll.disposeAndClear(); + m_aVScroll.disposeAndClear(); + m_aCornerWin.disposeAndClear(); + m_aReportWindow.disposeAndClear(); + m_pParent.clear(); + OScrollWindowHelper_BASE::dispose(); +} + + +void OScrollWindowHelper::impl_initScrollBar( ScrollBar& _rScrollBar ) const +{ + AllSettings aSettings( _rScrollBar.GetSettings() ); + StyleSettings aStyle( aSettings.GetStyleSettings() ); + aStyle.SetDragFullOptions( aStyle.GetDragFullOptions() | DragFullOptions::Scroll ); // live scrolling + aSettings.SetStyleSettings( aStyle ); + _rScrollBar.SetSettings( aSettings ); + + _rScrollBar.SetScrollHdl( LINK( const_cast<OScrollWindowHelper*>(this), OScrollWindowHelper, ScrollHdl ) ); + _rScrollBar.SetLineSize( SCR_LINE_SIZE ); +} + + +void OScrollWindowHelper::initialize() +{ + uno::Reference<report::XReportDefinition> xReportDefinition = m_pParent->getController().getReportDefinition(); + m_pReportDefinitionMultiPlexer = addStyleListener(xReportDefinition,this); +} + +void OScrollWindowHelper::setTotalSize(sal_Int32 _nWidth ,sal_Int32 _nHeight) +{ + m_aTotalPixelSize.setWidth( _nWidth ); + m_aTotalPixelSize.setHeight( _nHeight ); + + // now set the ranges without start marker + Fraction aStartWidth(REPORT_STARTMARKER_WIDTH * m_pParent->getController().getZoomValue(),100); + tools::Long nWidth = tools::Long(_nWidth - static_cast<double>(aStartWidth)); + m_aHScroll->SetRangeMax( nWidth ); + m_aVScroll->SetRangeMax( m_aTotalPixelSize.Height() ); + + Resize(); +} + +Size OScrollWindowHelper::ResizeScrollBars() +{ + // get the new output-size in pixel + Size aOutPixSz = GetOutputSizePixel(); + if ( aOutPixSz.IsEmpty() ) + return aOutPixSz; + + aOutPixSz.AdjustHeight( -(m_aReportWindow->getRulerHeight()) ); + // determine the size of the output-area and if we need scrollbars + const tools::Long nScrSize = GetSettings().GetStyleSettings().GetScrollBarSize(); + bool bVVisible = false; // by default no vertical-ScrollBar + bool bHVisible = false; // by default no horizontal-ScrollBar + bool bChanged; // determines if a visiblility was changed + do + { + bChanged = false; + + // does we need a vertical ScrollBar + if ( aOutPixSz.Width() < m_aTotalPixelSize.Width() && !bHVisible ) + { + bHVisible = true; + aOutPixSz.AdjustHeight( -nScrSize ); + bChanged = true; + } + + // does we need a horizontal ScrollBar + if ( aOutPixSz.Height() < m_aTotalPixelSize.Height() && !bVVisible ) + { + bVVisible = true; + aOutPixSz.AdjustWidth( -nScrSize ); + bChanged = true; + } + + } + while ( bChanged ); // until no visibility has changed + + aOutPixSz.AdjustHeight(m_aReportWindow->getRulerHeight() ); + + // show or hide scrollbars + m_aVScroll->Show( bVVisible ); + m_aHScroll->Show( bHVisible ); + + // disable painting in the corner between the scrollbars + if ( bVVisible && bHVisible ) + { + m_aCornerWin->SetPosSizePixel(Point(aOutPixSz.Width(), aOutPixSz.Height()), Size(nScrSize, nScrSize) ); + m_aCornerWin->Show(); + } + else + m_aCornerWin->Hide(); + + const Point aOffset = LogicToPixel(Point(SECTION_OFFSET, SECTION_OFFSET), MapMode(MapUnit::MapAppFont)); + // resize scrollbars and set their ranges + { + Fraction aStartWidth(tools::Long(REPORT_STARTMARKER_WIDTH*m_pParent->getController().getZoomValue()),100); + const sal_Int32 nNewWidth = aOutPixSz.Width() - aOffset.X() - static_cast<tools::Long>(aStartWidth); + lcl_setScrollBar(nNewWidth,Point( static_cast<tools::Long>(aStartWidth) + aOffset.X(), aOutPixSz.Height() ), Size( nNewWidth, nScrSize ), *m_aHScroll); + } + { + const sal_Int32 nNewHeight = aOutPixSz.Height() - m_aReportWindow->getRulerHeight(); + lcl_setScrollBar(nNewHeight,Point( aOutPixSz.Width(), m_aReportWindow->getRulerHeight() ), Size( nScrSize,nNewHeight), *m_aVScroll); + } + + return aOutPixSz; +} + +void OScrollWindowHelper::Resize() +{ + OScrollWindowHelper_BASE::Resize(); + const Size aTotalOutputSize = ResizeScrollBars(); + + m_aReportWindow->SetPosSizePixel(Point( 0, 0 ),aTotalOutputSize); +} + +IMPL_LINK( OScrollWindowHelper, ScrollHdl, ScrollBar*, /*pScroll*/, void ) +{ + m_aReportWindow->ScrollChildren( getThumbPos() ); +} + +void OScrollWindowHelper::addSection(const uno::Reference< report::XSection >& _xSection + ,const OUString& _sColorEntry + ,sal_uInt16 _nPosition) +{ + m_aReportWindow->addSection(_xSection,_sColorEntry,_nPosition); +} + +void OScrollWindowHelper::removeSection(sal_uInt16 _nPosition) +{ + m_aReportWindow->removeSection(_nPosition); +} + +void OScrollWindowHelper::toggleGrid(bool _bVisible) +{ + m_aReportWindow->toggleGrid(_bVisible); +} + +sal_uInt16 OScrollWindowHelper::getSectionCount() const +{ + return m_aReportWindow->getSectionCount(); +} + +void OScrollWindowHelper::SetInsertObj(SdrObjKind eObj, const OUString& _sShapeType) +{ + m_aReportWindow->SetInsertObj(eObj,_sShapeType); +} + +OUString const & OScrollWindowHelper::GetInsertObjString() const +{ + return m_aReportWindow->GetInsertObjString(); +} + +void OScrollWindowHelper::SetMode( DlgEdMode _eNewMode ) +{ + m_aReportWindow->SetMode(_eNewMode); +} + +bool OScrollWindowHelper::HasSelection() const +{ + return m_aReportWindow->HasSelection(); +} + +void OScrollWindowHelper::Delete() +{ + m_aReportWindow->Delete(); +} + +void OScrollWindowHelper::Copy() +{ + m_aReportWindow->Copy(); +} + +void OScrollWindowHelper::Paste() +{ + m_aReportWindow->Paste(); +} + +bool OScrollWindowHelper::IsPasteAllowed() const +{ + return m_aReportWindow->IsPasteAllowed(); +} + +void OScrollWindowHelper::SelectAll(const SdrObjKind _nObjectType) +{ + m_aReportWindow->SelectAll(_nObjectType); +} + +void OScrollWindowHelper::unmarkAllObjects() +{ + m_aReportWindow->unmarkAllObjects(); +} + +sal_Int32 OScrollWindowHelper::getMaxMarkerWidth() const +{ + return m_aReportWindow->getMaxMarkerWidth(); +} + +void OScrollWindowHelper::showRuler(bool _bShow) +{ + m_aReportWindow->showRuler(_bShow); +} + +bool OScrollWindowHelper::handleKeyEvent(const KeyEvent& _rEvent) +{ + return m_aReportWindow->handleKeyEvent(_rEvent); +} + +void OScrollWindowHelper::setMarked(OSectionView const * _pSectionView, bool _bMark) +{ + m_aReportWindow->setMarked(_pSectionView,_bMark); +} + +void OScrollWindowHelper::setMarked(const uno::Reference< report::XSection>& _xSection, bool _bMark) +{ + m_aReportWindow->setMarked(_xSection,_bMark); +} + +void OScrollWindowHelper::setMarked(const uno::Sequence< uno::Reference< report::XReportComponent> >& _xShape, bool _bMark) +{ + m_aReportWindow->setMarked(_xShape,_bMark); +} + +OSectionWindow* OScrollWindowHelper::getMarkedSection(NearSectionAccess nsa) const +{ + return m_aReportWindow->getMarkedSection(nsa); +} + +OSectionWindow* OScrollWindowHelper::getSectionWindow(const css::uno::Reference< css::report::XSection>& _xSection) const +{ + return m_aReportWindow->getSectionWindow(_xSection); +} + +void OScrollWindowHelper::markSection(const sal_uInt16 _nPos) +{ + m_aReportWindow->markSection(_nPos); +} + +void OScrollWindowHelper::fillCollapsedSections(::std::vector<sal_uInt16>& _rCollapsedPositions) const +{ + m_aReportWindow->fillCollapsedSections(_rCollapsedPositions); +} + +void OScrollWindowHelper::collapseSections(const uno::Sequence< css::beans::PropertyValue>& _aCollapsedSections) +{ + m_aReportWindow->collapseSections(_aCollapsedSections); +} + +bool OScrollWindowHelper::EventNotify( NotifyEvent& rNEvt ) +{ + const CommandEvent* pCommandEvent = rNEvt.GetCommandEvent(); + if ( pCommandEvent && + ((pCommandEvent->GetCommand() == CommandEventId::Wheel) || + (pCommandEvent->GetCommand() == CommandEventId::StartAutoScroll) || + (pCommandEvent->GetCommand() == CommandEventId::AutoScroll)) ) + { + ScrollBar* pHScrBar = nullptr; + ScrollBar* pVScrBar = nullptr; + if ( m_aHScroll->IsVisible() ) + pHScrBar = m_aHScroll.get(); + + if ( m_aVScroll->IsVisible() ) + pVScrBar = m_aVScroll.get(); + + if ( HandleScrollCommand( *pCommandEvent, pHScrBar, pVScrBar ) ) + return true; + } + return OScrollWindowHelper_BASE::EventNotify(rNEvt); +} + +void OScrollWindowHelper::alignMarkedObjects(ControlModification _nControlModification, bool _bAlignAtSection) +{ + m_aReportWindow->alignMarkedObjects(_nControlModification, _bAlignAtSection); +} + +void OScrollWindowHelper::ImplInitSettings() +{ + SetBackground( Wallpaper( Application::GetSettings().GetStyleSettings().GetFaceColor() )); + GetOutDev()->SetFillColor( Application::GetSettings().GetStyleSettings().GetFaceColor() ); + SetTextFillColor( Application::GetSettings().GetStyleSettings().GetFaceColor() ); +} + +void OScrollWindowHelper::DataChanged( const DataChangedEvent& rDCEvt ) +{ + Window::DataChanged( rDCEvt ); + + if ( (rDCEvt.GetType() == DataChangedEventType::SETTINGS) && + (rDCEvt.GetFlags() & AllSettingsFlags::STYLE) ) + { + ImplInitSettings(); + Invalidate(); + } +} + +void OScrollWindowHelper::_propertyChanged(const beans::PropertyChangeEvent& /*_rEvent*/) +{ + m_aReportWindow->notifySizeChanged(); +} + +void OScrollWindowHelper::setGridSnap(bool bOn) +{ + m_aReportWindow->setGridSnap(bOn); +} + +void OScrollWindowHelper::setDragStripes(bool bOn) +{ + m_aReportWindow->setDragStripes(bOn); +} + +sal_uInt32 OScrollWindowHelper::getMarkedObjectCount() const +{ + return m_aReportWindow->getMarkedObjectCount(); +} + +void OScrollWindowHelper::zoom(const Fraction& _aZoom) +{ + m_aReportWindow->zoom(_aZoom); + Resize(); + Invalidate(InvalidateFlags::NoChildren|InvalidateFlags::Transparent); +} + +void OScrollWindowHelper::fillControlModelSelection(::std::vector< uno::Reference< uno::XInterface > >& _rSelection) const +{ + m_aReportWindow->fillControlModelSelection(_rSelection); +} + +sal_uInt16 OScrollWindowHelper::getZoomFactor(SvxZoomType _eType) const +{ + return m_aReportWindow->getZoomFactor(_eType); +} + +} // rptui + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/reportdesign/source/ui/report/SectionView.cxx b/reportdesign/source/ui/report/SectionView.cxx new file mode 100644 index 000000000..f0da7c2e1 --- /dev/null +++ b/reportdesign/source/ui/report/SectionView.cxx @@ -0,0 +1,250 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * 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 . + */ +#include <SectionView.hxx> +#include <DesignView.hxx> +#include <RptPage.hxx> +#include <RptObject.hxx> +#include <RptDef.hxx> +#include <svx/svddrgmt.hxx> +#include <ReportSection.hxx> +#include <ReportWindow.hxx> +#include <strings.hxx> +#include <tools/diagnose_ex.h> + +namespace rptui +{ + using namespace ::com::sun::star; + +OSectionView::OSectionView( + SdrModel& rSdrModel, + OReportSection* _pSectionWindow, + OReportWindow* pEditor) +: SdrView(rSdrModel, _pSectionWindow->GetOutDev()) + ,m_pReportWindow( pEditor ) + ,m_pSectionWindow(_pSectionWindow) +{ + // SetPagePaintingAllowed(false); + SetBufferedOutputAllowed(true); + SetBufferedOverlayAllowed(true); + SetPageBorderVisible(false); + SetBordVisible(); + SetQuickTextEditMode(false); +} + + +OSectionView::~OSectionView() +{ +} + + +void OSectionView::MarkListHasChanged() +{ + SdrView::MarkListHasChanged(); + + if ( m_pReportWindow && m_pSectionWindow && !m_pSectionWindow->getPage()->getSpecialMode() ) + { + DlgEdHint aHint( RPTUI_HINT_SELECTIONCHANGED ); + m_pReportWindow->getReportView()->Broadcast( aHint ); + m_pReportWindow->getReportView()->UpdatePropertyBrowserDelayed(*this); + } +} + + +void OSectionView::MakeVisible( const tools::Rectangle& rRect, vcl::Window& rWin ) +{ + // visible area + MapMode aMap( rWin.GetMapMode() ); + const Point aOrg( aMap.GetOrigin() ); + const Size aVisSize( rWin.GetOutDev()->GetOutputSize() ); + const tools::Rectangle aVisRect( Point(-aOrg.X(),-aOrg.Y()), aVisSize ); + + // check, if rectangle is inside visible area + if ( !aVisRect.Contains( rRect ) ) + { + // calculate scroll distance; the rectangle must be inside the visible area + sal_Int32 nScrollX = 0, nScrollY = 0; + + const sal_Int32 nVisLeft = aVisRect.Left(); + const sal_Int32 nVisRight = aVisRect.Right(); + const sal_Int32 nVisTop = aVisRect.Top(); + const sal_Int32 nVisBottom = aVisRect.Bottom(); + + // don't scroll beyond the page size + Size aPageSize = m_pSectionWindow->getPage()->GetSize(); + const sal_Int32 nPageWidth = aPageSize.Width(); + const sal_Int32 nPageHeight = aPageSize.Height(); + + if ( nVisRight + nScrollX > nPageWidth ) + nScrollX = nPageWidth - nVisRight; + + if ( nVisLeft + nScrollX < 0 ) + nScrollX = -nVisLeft; + + if ( nVisBottom + nScrollY > nPageHeight ) + nScrollY = nPageHeight - nVisBottom; + + if ( nVisTop + nScrollY < 0 ) + nScrollY = -nVisTop; + + // scroll window + rWin.PaintImmediately(); + rWin.Scroll( -nScrollX, -nScrollY ); + aMap.SetOrigin( Point( aOrg.X() - nScrollX, aOrg.Y() - nScrollY ) ); + rWin.SetMapMode( aMap ); + rWin.Invalidate(); + + if ( m_pReportWindow ) + { + const DlgEdHint aHint( RPTUI_HINT_WINDOWSCROLLED ); + m_pReportWindow->getReportView()->Broadcast( aHint ); + } + } + else + { + rWin.Invalidate(InvalidateFlags::NoErase); + } +} + +void OSectionView::Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) +{ + SdrView::Notify(rBC,rHint); + if (rHint.GetId() != SfxHintId::ThisIsAnSdrHint) + return; + const SdrHint* pSdrHint = static_cast<const SdrHint*>(&rHint); + const SdrObject* pObj = pSdrHint->GetObject(); + const SdrHintKind eKind = pSdrHint->GetKind(); + // check for change of selected object + if(SdrHintKind::ObjectChange == eKind && pObj && IsObjMarked(pObj)) + AdjustMarkHdl(); + else if ( eKind == SdrHintKind::ObjectRemoved ) + ObjectRemovedInAliveMode(pObj); +} + + +void OSectionView::ObjectRemovedInAliveMode( const SdrObject* _pObject ) +{ + const SdrMarkList& rMarkedList = GetMarkedObjectList(); + const size_t nMark = rMarkedList.GetMarkCount(); + + for( size_t i = 0; i < nMark; ++i ) + { + SdrObject* pSdrObj = rMarkedList.GetMark(i)->GetMarkedSdrObj(); + if (_pObject == pSdrObj) + { + SdrPageView* pPgView = GetSdrPageView(); + BrkAction(); + MarkObj( pSdrObj, pPgView, true ); + break; + } + } +} + + +void OSectionView::SetMarkedToLayer( SdrLayerID _nLayerNo ) +{ + if (!AreObjectsMarked()) + return; + + // #i11702# use SdrUndoObjectLayerChange for undo + // STR_UNDO_SELATTR is "Attributes" - should use a different text later + BegUndo( ); + + const SdrMarkList& rMark = GetMarkedObjectList(); + const size_t nCount = rMark.GetMarkCount(); + for (size_t i = 0; i<nCount; ++i) + { + SdrObject* pObj = rMark.GetMark(i)->GetMarkedSdrObj(); + if ( dynamic_cast< const OCustomShape *>( pObj ) != nullptr ) + { + AddUndo( std::make_unique<SdrUndoObjectLayerChange>( *pObj, pObj->GetLayer(), _nLayerNo) ); + pObj->SetLayer( _nLayerNo ); + OObjectBase& rBaseObj = dynamic_cast<OObjectBase&>(*pObj); + try + { + rBaseObj.getReportComponent()->setPropertyValue(PROPERTY_OPAQUE,uno::Any(_nLayerNo == RPT_LAYER_FRONT)); + } + catch(const uno::Exception&) + { + DBG_UNHANDLED_EXCEPTION("reportdesign"); + } + } + } + + EndUndo(); + + // check mark list now instead of later in a timer + CheckMarked(); + MarkListHasChanged(); +} + +bool OSectionView::OnlyShapesMarked() const +{ + const SdrMarkList& rMark = GetMarkedObjectList(); + const size_t nCount = rMark.GetMarkCount(); + if ( !nCount ) + return false; + for (size_t i = 0; i<nCount; ++i) + { + SdrObject* pObj = rMark.GetMark(i)->GetMarkedSdrObj(); + if ( dynamic_cast< const OCustomShape *>( pObj ) == nullptr ) + { + return false; + } + } + return true; +} + +bool OSectionView::IsDragResize() const +{ + const SdrDragMethod* pDragMethod = GetDragMethod(); + if (pDragMethod) + { + bool bMoveOnly = pDragMethod->getMoveOnly(); + if (!bMoveOnly) + { + // current marked components will be resized + return true; + } + } + return false; +} + + +SdrLayerID OSectionView::GetLayerIdOfMarkedObjects() const +{ + SdrLayerID nRet = SDRLAYER_NOTFOUND; + const SdrMarkList &rMrkList = GetMarkedObjectList(); + for ( size_t i = 0; i < rMrkList.GetMarkCount(); ++i ) + { + const SdrObject *pObj = rMrkList.GetMark( i )->GetMarkedSdrObj(); + if ( nRet == SDRLAYER_NOTFOUND ) + nRet = pObj->GetLayer(); + else if ( nRet != pObj->GetLayer() ) + { + break; + } + } + return nRet; +} + + +} // rptui + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/reportdesign/source/ui/report/SectionWindow.cxx b/reportdesign/source/ui/report/SectionWindow.cxx new file mode 100644 index 000000000..60d5235f8 --- /dev/null +++ b/reportdesign/source/ui/report/SectionWindow.cxx @@ -0,0 +1,391 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * 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 . + */ +#include <SectionWindow.hxx> +#include <ReportWindow.hxx> +#include <UITools.hxx> +#include <ReportController.hxx> +#include <ReportSection.hxx> +#include <DesignView.hxx> +#include <strings.hxx> +#include <core_resource.hxx> +#include <strings.hrc> +#include <StartMarker.hxx> +#include <EndMarker.hxx> +#include <ViewsWindow.hxx> + +#include <functional> +#include <algorithm> +#include <vcl/svapp.hxx> +#include <vcl/settings.hxx> + +namespace rptui +{ +using namespace ::com::sun::star; +using namespace ::comphelper; + +OSectionWindow::OSectionWindow( OViewsWindow* _pParent,const uno::Reference< report::XSection >& _xSection,const OUString& _sColorEntry) +: Window( _pParent,WB_DIALOGCONTROL) +,OPropertyChangeListener(m_aMutex) +,m_pParent(_pParent) +,m_aStartMarker( VclPtr<rptui::OStartMarker>::Create(this,_sColorEntry)) +,m_aReportSection( VclPtr<rptui::OReportSection>::Create(this,_xSection)) +,m_aSplitter(VclPtr<Splitter>::Create(this)) +,m_aEndMarker( VclPtr<rptui::OEndMarker>::Create(this,_sColorEntry)) +{ + const MapMode& rMapMode = _pParent->GetMapMode(); + SetMapMode( rMapMode ); + ImplInitSettings(); + // TRY + m_aSplitter->SetMapMode( MapMode( MapUnit::Map100thMM ) ); + m_aSplitter->SetStartSplitHdl(LINK(this, OSectionWindow,StartSplitHdl)); + m_aSplitter->SetSplitHdl(LINK(this, OSectionWindow,SplitHdl)); + m_aSplitter->SetEndSplitHdl(LINK(this, OSectionWindow,EndSplitHdl)); + m_aSplitter->SetBackground( Wallpaper( Application::GetSettings().GetStyleSettings().GetFaceColor() )); + m_aSplitter->SetSplitPosPixel(m_aSplitter->LogicToPixel(Size(0,_xSection->getHeight())).Height()); + + + m_aStartMarker->setCollapsedHdl(LINK(this,OSectionWindow,Collapsed)); + + m_aStartMarker->zoom(rMapMode.GetScaleX()); + setZoomFactor(rMapMode.GetScaleX(), *m_aReportSection); + setZoomFactor(rMapMode.GetScaleX(), *m_aSplitter); + setZoomFactor(rMapMode.GetScaleX(), *m_aEndMarker); + + m_aSplitter->Show(); + m_aStartMarker->Show(); + m_aReportSection->Show(); + m_aEndMarker->Show(); + Show(); + + m_pSectionMulti = new OPropertyChangeMultiplexer(this,_xSection); + m_pSectionMulti->addProperty(PROPERTY_NAME); + m_pSectionMulti->addProperty(PROPERTY_HEIGHT); + + beans::PropertyChangeEvent aEvent; + aEvent.Source = _xSection; + aEvent.PropertyName = PROPERTY_NAME; + uno::Reference< report::XGroup > xGroup(_xSection->getGroup()); + if ( xGroup.is() ) + { + m_pGroupMulti = new OPropertyChangeMultiplexer(this,xGroup); + m_pGroupMulti->addProperty(PROPERTY_EXPRESSION); + aEvent.Source = xGroup; + aEvent.PropertyName = PROPERTY_EXPRESSION; + } + + _propertyChanged(aEvent); +} + +OSectionWindow::~OSectionWindow() +{ + disposeOnce(); +} + +void OSectionWindow::dispose() +{ + try + { + if ( m_pSectionMulti.is() ) + m_pSectionMulti->dispose(); + m_pSectionMulti.clear(); + if ( m_pGroupMulti.is() ) + m_pGroupMulti->dispose(); + m_pGroupMulti.clear(); + } + catch (uno::Exception&) + { + } + m_aStartMarker.disposeAndClear(); + m_aReportSection.disposeAndClear(); + m_aSplitter.disposeAndClear(); + m_aEndMarker.disposeAndClear(); + m_pParent.clear(); + vcl::Window::dispose(); +} + +void OSectionWindow::_propertyChanged(const beans::PropertyChangeEvent& _rEvent) +{ + SolarMutexGuard g; + const uno::Reference< report::XSection > xSection(_rEvent.Source,uno::UNO_QUERY); + if ( xSection.is() ) + { + if ( _rEvent.PropertyName == PROPERTY_HEIGHT ) + { + m_pParent->getView()->SetUpdateMode(false); + //Resize(); + m_pParent->getView()->notifySizeChanged(); + m_pParent->resize(*this); + m_pParent->getView()->SetUpdateMode(true); + // getViewsWindow()->getView()->getReportView()->getController().resetZoomType(); + } + else if ( _rEvent.PropertyName == PROPERTY_NAME && !xSection->getGroup().is() ) + { + uno::Reference< report::XReportDefinition > xReport = xSection->getReportDefinition(); + if ( setReportSectionTitle(xReport,RID_STR_REPORT_HEADER,::std::mem_fn(&OReportHelper::getReportHeader),::std::mem_fn(&OReportHelper::getReportHeaderOn)) + || setReportSectionTitle(xReport,RID_STR_REPORT_FOOTER,::std::mem_fn(&OReportHelper::getReportFooter),::std::mem_fn(&OReportHelper::getReportFooterOn)) + || setReportSectionTitle(xReport,RID_STR_PAGE_HEADER,::std::mem_fn(&OReportHelper::getPageHeader),::std::mem_fn(&OReportHelper::getPageHeaderOn)) + || setReportSectionTitle(xReport,RID_STR_PAGE_FOOTER,::std::mem_fn(&OReportHelper::getPageFooter),::std::mem_fn(&OReportHelper::getPageFooterOn)) ) + { + m_aStartMarker->Invalidate(InvalidateFlags::NoErase); + } + else + { + OUString sTitle = RptResId(RID_STR_DETAIL); + m_aStartMarker->setTitle(sTitle); + m_aStartMarker->Invalidate(InvalidateFlags::Children); + } + } + } + else if ( _rEvent.PropertyName == PROPERTY_EXPRESSION ) + { + uno::Reference< report::XGroup > xGroup(_rEvent.Source,uno::UNO_QUERY); + if ( xGroup.is() && !setGroupSectionTitle(xGroup,RID_STR_HEADER,::std::mem_fn(&OGroupHelper::getHeader),::std::mem_fn(&OGroupHelper::getHeaderOn))) + { + setGroupSectionTitle(xGroup,RID_STR_FOOTER,::std::mem_fn(&OGroupHelper::getFooter),::std::mem_fn(&OGroupHelper::getFooterOn)); + } + } +} + +bool OSectionWindow::setReportSectionTitle( + const uno::Reference<report::XReportDefinition>& _xReport, TranslateId pResId, + const ::std::function<uno::Reference<report::XSection>(OReportHelper*)>& _pGetSection, + const ::std::function<bool(OReportHelper*)>& _pIsSectionOn) +{ + OReportHelper aReportHelper(_xReport); + const bool bRet = _pIsSectionOn(&aReportHelper) && _pGetSection(&aReportHelper) == m_aReportSection->getSection(); + if ( bRet ) + { + OUString sTitle = RptResId(pResId); + m_aStartMarker->setTitle(sTitle); + m_aStartMarker->Invalidate(InvalidateFlags::Children); + } + return bRet; +} + +bool OSectionWindow::setGroupSectionTitle( + const uno::Reference<report::XGroup>& _xGroup, TranslateId pResId, + const ::std::function<uno::Reference<report::XSection>(OGroupHelper*)>& _pGetSection, + const ::std::function<bool(OGroupHelper*)>& _pIsSectionOn) +{ + OGroupHelper aGroupHelper(_xGroup); + const bool bRet = _pIsSectionOn(&aGroupHelper) && _pGetSection(&aGroupHelper) == m_aReportSection->getSection() ; + if ( bRet ) + { + OUString sExpression = _xGroup->getExpression(); + OUString sLabel = getViewsWindow()->getView()->getReportView()->getController().getColumnLabel_throw(sExpression); + if ( !sLabel.isEmpty() ) + { + sExpression = sLabel; + } + + OUString sTitle(RptResId(pResId)); + sTitle = sTitle.replaceFirst("#", sExpression); + m_aStartMarker->setTitle( sTitle ); + m_aStartMarker->Invalidate(InvalidateFlags::Children); + } + return bRet; +} + +void OSectionWindow::ImplInitSettings() +{ + EnableChildTransparentMode(); + SetParentClipMode( ParentClipMode::NoClip ); + SetPaintTransparent( true ); + SetBackground( ); +} + +void OSectionWindow::DataChanged( const DataChangedEvent& rDCEvt ) +{ + Window::DataChanged( rDCEvt ); + + if ( (rDCEvt.GetType() == DataChangedEventType::SETTINGS) && + (rDCEvt.GetFlags() & AllSettingsFlags::STYLE) ) + { + ImplInitSettings(); + Invalidate(); + } +} + +void OSectionWindow::Resize() +{ + Window::Resize(); + + Size aOutputSize = GetOutputSizePixel(); + tools::Long nEndWidth = tools::Long(REPORT_ENDMARKER_WIDTH * GetMapMode().GetScaleX()); + + const Point aThumbPos = m_pParent->getView()->getThumbPos(); + aOutputSize.AdjustWidth( -(aThumbPos.X()) ); + aOutputSize.AdjustHeight( -m_aSplitter->GetSizePixel().Height() ); + + if ( m_aStartMarker->isCollapsed() ) + { + Point aPos(0,0); + m_aStartMarker->SetPosSizePixel(aPos,aOutputSize); + } + else + { + const bool bShowEndMarker = m_pParent->getView()->GetTotalWidth() <= (aThumbPos.X() + aOutputSize.Width() ); + + tools::Long nStartWidth = tools::Long(REPORT_STARTMARKER_WIDTH * GetMapMode().GetScaleX()); + + // set start marker + m_aStartMarker->SetPosSizePixel(Point(0,0),Size(nStartWidth,aOutputSize.Height())); + + // set report section + const uno::Reference< report::XSection> xSection = m_aReportSection->getSection(); + Size aSectionSize = LogicToPixel( Size( 0,xSection->getHeight() ) ); + Point aReportPos(nStartWidth,0); + aSectionSize.setWidth( aOutputSize.Width() - nStartWidth ); + if ( bShowEndMarker ) + aSectionSize.AdjustWidth( -nEndWidth ); + + m_aReportSection->SetPosSizePixel(aReportPos,aSectionSize); + + // set splitter + aReportPos.AdjustY(aSectionSize.Height() ); + m_aSplitter->SetPosSizePixel(aReportPos,Size(aSectionSize.Width(),m_aSplitter->GetSizePixel().Height())); + aSectionSize.setHeight( static_cast<tools::Long>(1000 * static_cast<double>(GetMapMode().GetScaleY())) ); + m_aSplitter->SetDragRectPixel( tools::Rectangle(Point(nStartWidth,0),aSectionSize)); + + // set end marker + aReportPos.AdjustX(aSectionSize.Width() ); + aReportPos.setY( 0 ); + m_aEndMarker->Show(bShowEndMarker); + m_aEndMarker->SetPosSizePixel(aReportPos,Size(nEndWidth,aOutputSize.Height())); + } +} + +void OSectionWindow::setCollapsed(bool _bCollapsed) +{ + if ( m_aStartMarker->isCollapsed() != _bCollapsed ) + { + m_aStartMarker->setCollapsed(_bCollapsed); + } +} + +void OSectionWindow::showProperties() +{ + m_pParent->getView()->showProperties( m_aReportSection->getSection() ); +} + +void OSectionWindow::setMarked(bool _bMark) +{ + m_aStartMarker->setMarked(_bMark); + m_aEndMarker->setMarked(_bMark); +} + +IMPL_LINK( OSectionWindow, Collapsed, OColorListener&, _rMarker, void ) +{ + bool bShow = !_rMarker.isCollapsed(); + m_aReportSection->Show(bShow); + m_aEndMarker->Show(bShow); + m_aSplitter->Show(bShow); + + m_pParent->resize(*this); +} + +void OSectionWindow::zoom(const Fraction& _aZoom) +{ + setZoomFactor(_aZoom,*this); + m_aStartMarker->zoom(_aZoom); + + setZoomFactor(_aZoom, *m_aReportSection); + setZoomFactor(_aZoom, *m_aSplitter); + setZoomFactor(_aZoom, *m_aEndMarker); + Invalidate(); +} + +IMPL_LINK_NOARG( OSectionWindow, StartSplitHdl, Splitter*, void) +{ + const OUString sUndoAction( RptResId( RID_STR_UNDO_CHANGE_SIZE ) ); + getViewsWindow()->getView()->getReportView()->getController().getUndoManager().EnterListAction( sUndoAction, OUString(), 0, ViewShellId(-1) ); +} + +IMPL_LINK_NOARG( OSectionWindow, EndSplitHdl, Splitter*, void ) +{ + getViewsWindow()->getView()->getReportView()->getController().getUndoManager().LeaveListAction(); +} + +IMPL_LINK( OSectionWindow, SplitHdl, Splitter*, _pSplitter, void ) +{ + if ( !getViewsWindow()->getView()->getReportView()->getController().isEditable() ) + { + return; + } + + sal_Int32 nSplitPos = _pSplitter->GetSplitPosPixel(); + + const uno::Reference< report::XSection> xSection = m_aReportSection->getSection(); + nSplitPos = m_aSplitter->PixelToLogic(Size(0,nSplitPos)).Height(); + + const sal_Int32 nCount = xSection->getCount(); + for (sal_Int32 i = 0; i < nCount; ++i) + { + uno::Reference<report::XReportComponent> xReportComponent(xSection->getByIndex(i),uno::UNO_QUERY); + if ( xReportComponent.is() ) + { + nSplitPos = ::std::max(nSplitPos,xReportComponent->getPositionY() + xReportComponent->getHeight()); + } + } + + if ( nSplitPos < 0 ) + nSplitPos = 0; + + xSection->setHeight(nSplitPos); + m_aSplitter->SetSplitPosPixel(m_aSplitter->LogicToPixel(Size(0,nSplitPos)).Height()); +} + +static void lcl_scroll(vcl::Window& _rWindow,const Point& _aDelta) +{ + _rWindow.Scroll(-_aDelta.X(),-_aDelta.Y()); + _rWindow.Invalidate(InvalidateFlags::Transparent); +} + +static void lcl_setOrigin(vcl::Window& _rWindow,tools::Long _nX, tools::Long _nY) +{ + MapMode aMap = _rWindow.GetMapMode(); + aMap.SetOrigin( Point(- _nX, - _nY)); + _rWindow.SetMapMode( aMap ); +} + +void OSectionWindow::scrollChildren(tools::Long _nX) +{ + const Point aDelta( _nX,0 ); + + MapMode aMapMode( m_aReportSection->GetMapMode() ); + const Point aOld = aMapMode.GetOrigin(); + lcl_setOrigin(*m_aReportSection, aDelta.X(), 0); + + aMapMode = m_aReportSection->GetMapMode(); + const Point aNew = aMapMode.GetOrigin(); + const Point aDiff = aOld - aNew; + { + lcl_scroll(*m_aReportSection, aDiff); + } + + lcl_scroll(*m_aEndMarker, m_aEndMarker->PixelToLogic(Point(_nX,0))); + + lcl_setOrigin(*m_aSplitter,_nX, 0); + lcl_scroll(*m_aSplitter,aDiff); +} + +} // rptui + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/reportdesign/source/ui/report/StartMarker.cxx b/reportdesign/source/ui/report/StartMarker.cxx new file mode 100644 index 000000000..3d05f2910 --- /dev/null +++ b/reportdesign/source/ui/report/StartMarker.cxx @@ -0,0 +1,304 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * 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 . + */ +#include <StartMarker.hxx> +#include <UITools.hxx> +#include <vcl/image.hxx> +#include <vcl/svapp.hxx> +#include <bitmaps.hlst> +#include <ColorChanger.hxx> +#include <ReportDefines.hxx> +#include <SectionWindow.hxx> +#include <vcl/event.hxx> +#include <vcl/help.hxx> +#include <vcl/gradient.hxx> +#include <vcl/lineinfo.hxx> +#include <vcl/settings.hxx> + +#include <unotools/syslocale.hxx> +#include <unotools/localedatawrapper.hxx> + +#define CORNER_SPACE 5 + + +namespace rptui +{ + + +Image* OStartMarker::s_pDefCollapsed = nullptr; +Image* OStartMarker::s_pDefExpanded = nullptr; +oslInterlockedCount OStartMarker::s_nImageRefCount = 0; + + +OStartMarker::OStartMarker(OSectionWindow* _pParent,const OUString& _sColorEntry) + : OColorListener(_pParent,_sColorEntry) + , m_aVRuler(VclPtr<Ruler>::Create(this,WB_VERT)) + , m_pParent(_pParent) + , m_bShowRuler(true) +{ + osl_atomic_increment(&s_nImageRefCount); + initDefaultNodeImages(); + ImplInitSettings(); + m_aVRuler->Show(); + m_aVRuler->Activate(); + m_aVRuler->SetPagePos(); + m_aVRuler->SetBorders(); + m_aVRuler->SetIndents(); + m_aVRuler->SetMargin1(); + m_aVRuler->SetMargin2(); + const MeasurementSystem eSystem = SvtSysLocale().GetLocaleData().getMeasurementSystemEnum(); + m_aVRuler->SetUnit(MeasurementSystem::Metric == eSystem ? FieldUnit::CM : FieldUnit::INCH); + EnableChildTransparentMode(); + SetParentClipMode( ParentClipMode::NoClip ); + SetPaintTransparent( true ); +} + +OStartMarker::~OStartMarker() +{ + disposeOnce(); +} + +void OStartMarker::dispose() +{ + if ( osl_atomic_decrement(&s_nImageRefCount) == 0 ) + { + delete s_pDefCollapsed; + s_pDefCollapsed = nullptr; + delete s_pDefExpanded; + s_pDefExpanded = nullptr; + } + m_aVRuler.disposeAndClear(); + m_pParent.clear(); + OColorListener::dispose(); +} + +sal_Int32 OStartMarker::getMinHeight() const +{ + Fraction aExtraWidth(tools::Long(2 * REPORT_EXTRA_SPACE)); + aExtraWidth *= GetMapMode().GetScaleX(); + return LogicToPixel(Size(0, GetTextHeight())).Height() + tools::Long(aExtraWidth); +} + +void OStartMarker::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& /*rRect*/) +{ + rRenderContext.Push(vcl::PushFlags::TEXTCOLOR); + + Size aSize(GetOutputSizePixel()); + const tools::Long nCornerWidth = tools::Long(CORNER_SPACE * double(GetMapMode().GetScaleX())); + + if (isCollapsed()) + { + rRenderContext.SetClipRegion(); + } + else + { + const tools::Long nVRulerWidth = m_aVRuler->GetSizePixel().Width(); + tools::Long nSize = aSize.Width() - nVRulerWidth; + aSize.AdjustWidth(nCornerWidth ); + rRenderContext.SetClipRegion(vcl::Region(rRenderContext.PixelToLogic(tools::Rectangle(Point(), + Size(nSize, aSize.Height()))))); + } + + tools::Rectangle aWholeRect(Point(), aSize); + { + const ColorChanger aColors(&rRenderContext, m_nTextBoundaries, m_nColor); + tools::PolyPolygon aPoly; + aPoly.Insert( tools::Polygon(aWholeRect,nCornerWidth,nCornerWidth)); + + Color aStartColor(m_nColor); + aStartColor.IncreaseLuminance(10); + sal_uInt16 nHue = 0; + sal_uInt16 nSat = 0; + sal_uInt16 nBri = 0; + aStartColor.RGBtoHSB(nHue, nSat, nBri); + nSat += 40; + Color aEndColor(Color::HSBtoRGB(nHue, nSat, nBri)); + Gradient aGradient(GradientStyle::Linear,aStartColor,aEndColor); + aGradient.SetSteps(static_cast<sal_uInt16>(aSize.Height())); + + rRenderContext.DrawGradient(PixelToLogic(aPoly) ,aGradient); + } + + rRenderContext.Push(vcl::PushFlags::MAPMODE); + rRenderContext.SetMapMode(); + + rRenderContext.DrawImage(m_aImageRect.TopLeft(), m_aImageRect.GetSize(), m_aImage); + + const Color aColor(m_nColor); + Color aTextColor = GetTextColor(); + if (aColor.GetLuminance() < 128) + aTextColor = COL_WHITE; + rRenderContext.SetTextColor(aTextColor); + + rRenderContext.DrawText(m_aTextRect, m_aText, DrawTextFlags::MultiLine | DrawTextFlags::WordBreakHyphenation); + + rRenderContext.Pop(); + + if (m_bMarked) + { + const tools::Long nCornerHeight = tools::Long(CORNER_SPACE * double(GetMapMode().GetScaleY())); + tools::Rectangle aRect(Point(nCornerWidth, nCornerHeight), + Size(aSize.Width() - nCornerWidth - nCornerWidth, + aSize.Height() - nCornerHeight - nCornerHeight)); + ColorChanger aColors(&rRenderContext, COL_WHITE, COL_WHITE); + rRenderContext.DrawPolyLine( tools::Polygon(rRenderContext.PixelToLogic(aRect)), + LineInfo(LineStyle::Solid, 2)); + } + + rRenderContext.Pop(); +} + +void OStartMarker::MouseButtonUp( const MouseEvent& rMEvt ) +{ + if ( !rMEvt.IsLeft() ) + return; + + Point aPos( rMEvt.GetPosPixel()); + + const Size aOutputSize = GetOutputSizePixel(); + if( aPos.X() > aOutputSize.Width() || aPos.Y() > aOutputSize.Height() ) + return; + if ( rMEvt.GetClicks() == 2 || m_aImageRect.Contains( aPos ) ) + { + m_bCollapsed = !m_bCollapsed; + + changeImage(); + + m_aVRuler->Show(!m_bCollapsed && m_bShowRuler); + m_aCollapsedLink.Call(*this); + } + + m_pParent->showProperties(); +} + +void OStartMarker::changeImage() +{ + m_aImage = m_bCollapsed ? *s_pDefCollapsed : *s_pDefExpanded; +} + +void OStartMarker::initDefaultNodeImages() +{ + if ( !s_pDefCollapsed ) + { + s_pDefCollapsed = new Image(StockImage::Yes, RID_BMP_TREENODE_COLLAPSED); + s_pDefExpanded = new Image(StockImage::Yes, RID_BMP_TREENODE_EXPANDED); + } + + m_aImage = m_bCollapsed ? *s_pDefCollapsed : *s_pDefExpanded; +} + +void OStartMarker::ApplySettings(vcl::RenderContext& rRenderContext) +{ + rRenderContext.SetBackground(); + rRenderContext.SetFillColor(Application::GetSettings().GetStyleSettings().GetDialogColor()); +} + +void OStartMarker::ImplInitSettings() +{ + ApplySettings(*GetOutDev()); +} + +void OStartMarker::Resize() +{ + const Size aOutputSize( GetOutputSizePixel() ); + const tools::Long nOutputWidth = aOutputSize.Width(); + const tools::Long nOutputHeight = aOutputSize.Height(); + + const tools::Long nVRulerWidth = m_aVRuler->GetSizePixel().Width(); + const Point aRulerPos(nOutputWidth - nVRulerWidth,0); + m_aVRuler->SetPosSizePixel(aRulerPos,Size(nVRulerWidth,nOutputHeight)); + + Size aImageSize = m_aImage.GetSizePixel(); + const MapMode& rMapMode = GetMapMode(); + aImageSize.setWidth( tools::Long(aImageSize.Width() * static_cast<double>(rMapMode.GetScaleX())) ); + aImageSize.setHeight( tools::Long(aImageSize.Height() * static_cast<double>(rMapMode.GetScaleY())) ); + + tools::Long nExtraWidth = tools::Long(REPORT_EXTRA_SPACE * rMapMode.GetScaleX()); + + Point aPos(aImageSize.Width() + (nExtraWidth * 2), nExtraWidth); + const tools::Long nHeight = ::std::max<sal_Int32>(nOutputHeight - 2*aPos.Y(),LogicToPixel(Size(0, GetTextHeight())).Height()); + m_aTextRect = tools::Rectangle(aPos, Size(aRulerPos.X() - aPos.X(),nHeight)); + + aPos.setX( nExtraWidth ); + aPos.AdjustY(static_cast<sal_Int32>((LogicToPixel(Size(0, GetTextHeight())).Height() - aImageSize.Height()) * 0.5) ) ; + m_aImageRect = tools::Rectangle(aPos, aImageSize); + + OColorListener::Resize(); +} + +void OStartMarker::setTitle(const OUString& rTitle) +{ + if (m_aText != rTitle) + { + m_aText = rTitle; + Invalidate(); + } +} + +void OStartMarker::Notify(SfxBroadcaster & rBc, SfxHint const & rHint) +{ + OColorListener::Notify(rBc, rHint); + if (rHint.GetId() == SfxHintId::ColorsChanged) + { + Invalidate(InvalidateFlags::Children); + } +} + +void OStartMarker::showRuler(bool _bShow) +{ + m_bShowRuler = _bShow; + m_aVRuler->Show(!m_bCollapsed && m_bShowRuler); +} + +void OStartMarker::RequestHelp( const HelpEvent& rHEvt ) +{ + if (m_aText.isEmpty()) + return; + + // show help + tools::Rectangle aItemRect(rHEvt.GetMousePosPixel(),Size(GetSizePixel().Width(),getMinHeight())); + Point aPt = OutputToScreenPixel( aItemRect.TopLeft() ); + aItemRect.SetLeft( aPt.X() ); + aItemRect.SetTop( aPt.Y() ); + aPt = OutputToScreenPixel( aItemRect.BottomRight() ); + aItemRect.SetRight( aPt.X() ); + aItemRect.SetBottom( aPt.Y() ); + if( rHEvt.GetMode() == HelpEventMode::BALLOON ) + Help::ShowBalloon( this, aItemRect.Center(), aItemRect, m_aText); + else + Help::ShowQuickHelp( this, aItemRect, m_aText ); +} + +void OStartMarker::setCollapsed(bool _bCollapsed) +{ + OColorListener::setCollapsed(_bCollapsed); + showRuler(_bCollapsed); + changeImage(); +} + +void OStartMarker::zoom(const Fraction& _aZoom) +{ + setZoomFactor(_aZoom, *this); + m_aVRuler->SetZoom(_aZoom); + Resize(); + Invalidate(); +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/reportdesign/source/ui/report/ViewsWindow.cxx b/reportdesign/source/ui/report/ViewsWindow.cxx new file mode 100644 index 000000000..b5ce7a48f --- /dev/null +++ b/reportdesign/source/ui/report/ViewsWindow.cxx @@ -0,0 +1,1673 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * 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 . + */ + +#include <ViewsWindow.hxx> +#include <ScrollHelper.hxx> +#include <UndoActions.hxx> +#include <ReportWindow.hxx> +#include <DesignView.hxx> +#include <svtools/colorcfg.hxx> +#include <ReportController.hxx> +#include <UITools.hxx> +#include <RptDef.hxx> +#include <strings.hrc> +#include <SectionView.hxx> +#include <ReportSection.hxx> +#include <strings.hxx> +#include <rptui_slotid.hrc> +#include <dlgedclip.hxx> +#include <RptObject.hxx> +#include <EndMarker.hxx> +#include <sal/log.hxx> +#include <vcl/svapp.hxx> +#include <vcl/settings.hxx> +#include <core_resource.hxx> +#include <svx/svdundo.hxx> +#include <toolkit/helper/convert.hxx> +#include <algorithm> +#include <cstdlib> +#include <numeric> + +namespace rptui +{ +#define DEFAUL_MOVE_SIZE 100 + +using namespace ::com::sun::star; +using namespace ::comphelper; + +static bool lcl_getNewRectSize(const tools::Rectangle& _aObjRect,tools::Long& _nXMov, tools::Long& _nYMov,SdrObject const * _pObj,SdrView const * _pView, ControlModification _nControlModification) +{ + bool bMoveAllowed = _nXMov != 0 || _nYMov != 0; + if ( bMoveAllowed ) + { + tools::Rectangle aNewRect = _aObjRect; + SdrObject* pOverlappedObj = nullptr; + do + { + aNewRect = _aObjRect; + switch(_nControlModification) + { + case ControlModification::HEIGHT_GREATEST: + case ControlModification::WIDTH_GREATEST: + aNewRect.setWidth(_nXMov); + aNewRect.setHeight(_nYMov); + break; + default: + aNewRect.Move(_nXMov,_nYMov); + break; + } + if (dynamic_cast<OUnoObject const *>(_pObj) != nullptr || dynamic_cast<OOle2Obj const *>(_pObj) != nullptr) + { + pOverlappedObj = isOver(aNewRect,*_pObj->getSdrPageFromSdrObject(),*_pView,true,_pObj); + if ( pOverlappedObj && _pObj != pOverlappedObj ) + { + tools::Rectangle aOverlappingRect = pOverlappedObj->GetSnapRect(); + sal_Int32 nXTemp = _nXMov; + sal_Int32 nYTemp = _nYMov; + switch(_nControlModification) + { + case ControlModification::LEFT: + nXTemp += aOverlappingRect.Right() - aNewRect.Left(); + bMoveAllowed = _nXMov != nXTemp; + break; + case ControlModification::RIGHT: + nXTemp += aOverlappingRect.Left() - aNewRect.Right(); + bMoveAllowed = _nXMov != nXTemp; + break; + case ControlModification::TOP: + nYTemp += aOverlappingRect.Bottom() - aNewRect.Top(); + bMoveAllowed = _nYMov != nYTemp; + break; + case ControlModification::BOTTOM: + nYTemp += aOverlappingRect.Top() - aNewRect.Bottom(); + bMoveAllowed = _nYMov != nYTemp; + break; + case ControlModification::CENTER_HORIZONTAL: + if ( _aObjRect.Left() < aOverlappingRect.Left() ) + nXTemp += aOverlappingRect.Left() - aNewRect.Left() - aNewRect.getWidth(); + else + nXTemp += aOverlappingRect.Right() - aNewRect.Left(); + bMoveAllowed = _nXMov != nXTemp; + break; + case ControlModification::CENTER_VERTICAL: + if ( _aObjRect.Top() < aOverlappingRect.Top() ) + nYTemp += aOverlappingRect.Top() - aNewRect.Top() - aNewRect.getHeight(); + else + nYTemp += aOverlappingRect.Bottom() - aNewRect.Top(); + bMoveAllowed = _nYMov != nYTemp; + break; + case ControlModification::HEIGHT_GREATEST: + case ControlModification::WIDTH_GREATEST: + { + tools::Rectangle aIntersectionRect = aNewRect.GetIntersection(aOverlappingRect); + if ( !aIntersectionRect.IsEmpty() ) + { + if ( _nControlModification == ControlModification::WIDTH_GREATEST ) + { + if ( aNewRect.Left() < aIntersectionRect.Left() ) + { + aNewRect.SetRight( aIntersectionRect.Left() ); + } + else if ( aNewRect.Left() < aIntersectionRect.Right() ) + { + aNewRect.SetLeft( aIntersectionRect.Right() ); + } + } + else if ( _nControlModification == ControlModification::HEIGHT_GREATEST ) + { + if ( aNewRect.Top() < aIntersectionRect.Top() ) + { + aNewRect.SetBottom( aIntersectionRect.Top() ); + } + else if ( aNewRect.Top() < aIntersectionRect.Bottom() ) + { + aNewRect.SetTop( aIntersectionRect.Bottom() ); + } + } + nYTemp = aNewRect.getHeight(); + bMoveAllowed = _nYMov != nYTemp; + nXTemp = aNewRect.getWidth(); + bMoveAllowed = bMoveAllowed && _nXMov != nXTemp; + } + } + break; + default: + break; + } + + _nXMov = nXTemp; + _nYMov = nYTemp; + } + else + pOverlappedObj = nullptr; + } + } + while ( pOverlappedObj && bMoveAllowed ); + } + return bMoveAllowed; +} + +OViewsWindow::OViewsWindow( OReportWindow* _pReportWindow) + : Window( _pReportWindow,WB_DIALOGCONTROL) + , m_pParent(_pReportWindow) + , m_bInUnmark(false) +{ + SetPaintTransparent(true); + SetMapMode(MapMode(MapUnit::Map100thMM)); + m_aColorConfig.AddListener(this); + ImplInitSettings(); +} + +OViewsWindow::~OViewsWindow() +{ + disposeOnce(); +} + +void OViewsWindow::dispose() +{ + m_aColorConfig.RemoveListener(this); + for (auto& rxSection : m_aSections) + rxSection.disposeAndClear(); + m_aSections.clear(); + m_pParent.clear(); + vcl::Window::dispose(); +} + +void OViewsWindow::impl_resizeSectionWindow(OSectionWindow& _rSectionWindow,Point& _rStartPoint,bool _bSet) +{ + const uno::Reference< report::XSection> xSection = _rSectionWindow.getReportSection().getSection(); + + Size aSectionSize = _rSectionWindow.LogicToPixel( Size( 0,xSection->getHeight() ) ); + aSectionSize.setWidth( getView()->GetTotalWidth() ); + + const sal_Int32 nMinHeight = _rSectionWindow.getStartMarker().getMinHeight(); + if ( _rSectionWindow.getStartMarker().isCollapsed() || nMinHeight > aSectionSize.Height() ) + { + aSectionSize.setHeight( nMinHeight ); + } + aSectionSize.AdjustHeight(static_cast<tools::Long>(StyleSettings::GetSplitSize() * static_cast<double>(_rSectionWindow.GetMapMode().GetScaleY())) ); + + if ( _bSet ) + _rSectionWindow.SetPosSizePixel(_rStartPoint,aSectionSize); + + _rStartPoint.AdjustY(aSectionSize.Height() ); +} + + +void OViewsWindow::resize(const OSectionWindow& _rSectionWindow) +{ + bool bSet = false; + Point aStartPoint; + for (VclPtr<OSectionWindow> const & pSectionWindow : m_aSections) + { + if ( pSectionWindow == &_rSectionWindow ) + { + aStartPoint = pSectionWindow->GetPosPixel(); + bSet = true; + } + + if ( bSet ) + { + impl_resizeSectionWindow(*pSectionWindow,aStartPoint,bSet); + static const InvalidateFlags nIn = InvalidateFlags::Update | InvalidateFlags::Transparent; + pSectionWindow->getStartMarker().Invalidate( nIn ); // InvalidateFlags::NoErase |InvalidateFlags::NoChildren| InvalidateFlags::Transparent + pSectionWindow->getEndMarker().Invalidate( nIn ); + } + } + m_pParent->notifySizeChanged(); +} + +void OViewsWindow::Resize() +{ + Window::Resize(); + if ( !m_aSections.empty() ) + { + const Point aOffset(m_pParent->getThumbPos()); + Point aStartPoint(0,-aOffset.Y()); + for (VclPtr<OSectionWindow> const & pSectionWindow : m_aSections) + { + impl_resizeSectionWindow(*pSectionWindow,aStartPoint,true); + } + } +} + +void OViewsWindow::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect) +{ + Window::Paint(rRenderContext, rRect); + + rRenderContext.SetBackground(); + rRenderContext.SetFillColor(Application::GetSettings().GetStyleSettings().GetDialogColor()); + rRenderContext.SetTextFillColor(Application::GetSettings().GetStyleSettings().GetDialogColor()); + + Size aOut(GetOutputSizePixel()); + tools::Long nStartWidth = tools::Long(REPORT_STARTMARKER_WIDTH * rRenderContext.GetMapMode().GetScaleX()); + + aOut.AdjustWidth( -nStartWidth ); + aOut = rRenderContext.PixelToLogic(aOut); + + tools::Rectangle aRect(rRenderContext.PixelToLogic(Point(nStartWidth,0)), aOut); + Wallpaper aWall(m_aColorConfig.GetColorValue(::svtools::APPBACKGROUND).nColor); + rRenderContext.DrawWallpaper(aRect, aWall); +} + +void OViewsWindow::ImplInitSettings() +{ + EnableChildTransparentMode(); +} + +void OViewsWindow::DataChanged( const DataChangedEvent& rDCEvt ) +{ + Window::DataChanged( rDCEvt ); + + if ( (rDCEvt.GetType() == DataChangedEventType::SETTINGS) && + (rDCEvt.GetFlags() & AllSettingsFlags::STYLE) ) + { + ImplInitSettings(); + Invalidate(); + } +} + +void OViewsWindow::addSection(const uno::Reference< report::XSection >& _xSection,const OUString& _sColorEntry,sal_uInt16 _nPosition) +{ + VclPtrInstance<OSectionWindow> pSectionWindow(this,_xSection,_sColorEntry); + m_aSections.insert(getIteratorAtPos(_nPosition) , TSectionsMap::value_type(pSectionWindow)); + m_pParent->setMarked(&pSectionWindow->getReportSection().getSectionView(),m_aSections.size() == 1); + Resize(); +} + +void OViewsWindow::removeSection(sal_uInt16 _nPosition) +{ + if ( _nPosition < m_aSections.size() ) + { + TSectionsMap::iterator aPos = getIteratorAtPos(_nPosition); + TSectionsMap::const_iterator aNew = getIteratorAtPos(_nPosition == 0 ? _nPosition+1: _nPosition - 1); + + m_pParent->getReportView()->UpdatePropertyBrowserDelayed((*aNew)->getReportSection().getSectionView()); + + aPos->disposeAndClear(); + m_aSections.erase(aPos); + Resize(); + } +} + +void OViewsWindow::toggleGrid(bool _bVisible) +{ + ::std::for_each(m_aSections.begin(),m_aSections.end(), + [_bVisible] (const TSectionsMap::value_type& sectionPtr) { + sectionPtr->getReportSection().SetGridVisible(_bVisible); + }); + ::std::for_each(m_aSections.begin(),m_aSections.end(), + [] (const TSectionsMap::value_type& sectionPtr) { + sectionPtr->getReportSection().Window::Invalidate(InvalidateFlags::NoErase); + }); +} + +sal_Int32 OViewsWindow::getTotalHeight() const +{ + return std::accumulate(m_aSections.begin(), m_aSections.end(), sal_Int32(0), + [](const sal_Int32 nHeight, const VclPtr<OSectionWindow>& rxSection) { return nHeight + rxSection->GetSizePixel().Height(); }); +} + +sal_uInt16 OViewsWindow::getSectionCount() const +{ + return static_cast<sal_uInt16>(m_aSections.size()); +} + +void OViewsWindow::SetInsertObj( SdrObjKind eObj,const OUString& _sShapeType ) +{ + for (const auto& rxSection : m_aSections) + rxSection->getReportSection().getSectionView().SetCurrentObj( eObj, SdrInventor::ReportDesign ); + + m_sShapeType = _sShapeType; +} + + +void OViewsWindow::SetMode( DlgEdMode eNewMode ) +{ + ::std::for_each(m_aSections.begin(),m_aSections.end(), + [&eNewMode] (const TSectionsMap::value_type& sectionPtr) { + sectionPtr->getReportSection().SetMode(eNewMode); + }); +} + +bool OViewsWindow::HasSelection() const +{ + return std::any_of(m_aSections.begin(), m_aSections.end(), + [](const VclPtr<OSectionWindow>& rxSection) { return rxSection->getReportSection().getSectionView().AreObjectsMarked(); }); +} + +void OViewsWindow::Delete() +{ + m_bInUnmark = true; + ::std::for_each(m_aSections.begin(),m_aSections.end(), + [] (const TSectionsMap::value_type& sectionPtr) { + sectionPtr->getReportSection().Delete(); + }); + m_bInUnmark = false; +} + +void OViewsWindow::Copy() +{ + uno::Sequence< beans::NamedValue > aAllreadyCopiedObjects; + ::std::for_each(m_aSections.begin(),m_aSections.end(), + [&aAllreadyCopiedObjects] (const TSectionsMap::value_type& sectionPtr) { + sectionPtr->getReportSection().Copy(aAllreadyCopiedObjects); + }); + + rtl::Reference<OReportExchange> pCopy = new OReportExchange(aAllreadyCopiedObjects); + pCopy->CopyToClipboard(this); +} + +void OViewsWindow::Paste() +{ + TransferableDataHelper aTransferData(TransferableDataHelper::CreateFromSystemClipboard(this)); + OReportExchange::TSectionElements aCopies = OReportExchange::extractCopies(aTransferData); + if ( aCopies.getLength() > 1 ) + ::std::for_each(m_aSections.begin(),m_aSections.end(), + [&aCopies] (const TSectionsMap::value_type& sectionPtr) { + sectionPtr->getReportSection().Paste(aCopies); + }); + else + { + OSectionWindow* pMarkedSection = getMarkedSection(); + if ( pMarkedSection ) + pMarkedSection->getReportSection().Paste(aCopies,true); + } +} + +OSectionWindow* OViewsWindow::getSectionWindow(const uno::Reference< report::XSection>& _xSection) const +{ + OSL_ENSURE(_xSection.is(),"Section is NULL!"); + + OSectionWindow* pSectionWindow = nullptr; + for (VclPtr<OSectionWindow> const & p : m_aSections) + { + if (p->getReportSection().getSection() == _xSection) + { + pSectionWindow = p.get(); + break; + } + } + + return pSectionWindow; +} + + +OSectionWindow* OViewsWindow::getMarkedSection(NearSectionAccess nsa) const +{ + OSectionWindow* pRet = nullptr; + TSectionsMap::const_iterator aIter = m_aSections.begin(); + TSectionsMap::const_iterator aEnd = m_aSections.end(); + sal_uInt32 nCurrentPosition = 0; + for (; aIter != aEnd ; ++aIter) + { + if ( (*aIter)->getStartMarker().isMarked() ) + { + if (nsa == CURRENT) + { + pRet = aIter->get(); + break; + } + else if ( nsa == PREVIOUS ) + { + if (nCurrentPosition > 0) + { + pRet = (--aIter)->get(); + if (pRet == nullptr) + { + pRet = m_aSections.begin()->get(); + } + } + else + { + // if we are out of bounds return the first one + pRet = m_aSections.begin()->get(); + } + break; + } + else if ( nsa == POST ) + { + sal_uInt32 nSize = m_aSections.size(); + if ((nCurrentPosition + 1) < nSize) + { + pRet = (++aIter)->get(); + if (pRet == nullptr) + { + pRet = (--aEnd)->get(); + } + } + else + { + // if we are out of bounds return the last one + pRet = (--aEnd)->get(); + } + break; + } + } + ++nCurrentPosition; + } + + return pRet; +} + +void OViewsWindow::markSection(const sal_uInt16 _nPos) +{ + if ( _nPos < m_aSections.size() ) + m_pParent->setMarked(m_aSections[_nPos]->getReportSection().getSection(),true); +} + +bool OViewsWindow::IsPasteAllowed() const +{ + TransferableDataHelper aTransferData( TransferableDataHelper::CreateFromSystemClipboard( const_cast< OViewsWindow* >( this ) ) ); + return aTransferData.HasFormat(OReportExchange::getDescriptorFormatId()); +} + +void OViewsWindow::SelectAll(const SdrObjKind _nObjectType) +{ + m_bInUnmark = true; + ::std::for_each(m_aSections.begin(),m_aSections.end(), + [&_nObjectType] (const TSectionsMap::value_type& sectionPtr) { + sectionPtr->getReportSection().SelectAll(_nObjectType); + }); + m_bInUnmark = false; +} + +void OViewsWindow::unmarkAllObjects(OSectionView const * _pSectionView) +{ + if ( m_bInUnmark ) + return; + + m_bInUnmark = true; + for (const auto& rxSection : m_aSections) + { + if ( &rxSection->getReportSection().getSectionView() != _pSectionView ) + { + rxSection->getReportSection().deactivateOle(); + rxSection->getReportSection().getSectionView().UnmarkAllObj(); + } + } + m_bInUnmark = false; +} + +void OViewsWindow::ConfigurationChanged( utl::ConfigurationBroadcaster*, ConfigurationHints) +{ + ImplInitSettings(); + Invalidate(); +} + +void OViewsWindow::MouseButtonDown( const MouseEvent& rMEvt ) +{ + if ( rMEvt.IsLeft() ) + { + GrabFocus(); + const uno::Sequence< beans::PropertyValue> aArgs; + getView()->getReportView()->getController().executeChecked(SID_SELECT_REPORT,aArgs); + } + Window::MouseButtonDown(rMEvt); +} + +void OViewsWindow::showRuler(bool _bShow) +{ + ::std::for_each(m_aSections.begin(),m_aSections.end(), + [_bShow] (const TSectionsMap::value_type& sectionPtr) { + sectionPtr->getStartMarker().showRuler(_bShow); + }); + ::std::for_each(m_aSections.begin(),m_aSections.end(), + [] (const TSectionsMap::value_type& sectionPtr) { + sectionPtr->getStartMarker().Window::Invalidate(InvalidateFlags::NoErase); + }); +} + +void OViewsWindow::MouseButtonUp( const MouseEvent& rMEvt ) +{ + if ( !rMEvt.IsLeft() ) + return; + + auto aIter = std::find_if(m_aSections.begin(), m_aSections.end(), + [](const VclPtr<OSectionWindow>& rxSection) { return rxSection->getReportSection().getSectionView().AreObjectsMarked(); }); + if (aIter != m_aSections.end()) + { + (*aIter)->getReportSection().MouseButtonUp(rMEvt); + } + + // remove special insert mode + for (const auto& rxSection : m_aSections) + { + rxSection->getReportSection().getPage()->resetSpecialMode(); + } +} + +bool OViewsWindow::handleKeyEvent(const KeyEvent& _rEvent) +{ + bool bRet = false; + for (const auto& rxSection : m_aSections) + { + if ( rxSection->getStartMarker().isMarked() ) + { + bRet = rxSection->getReportSection().handleKeyEvent(_rEvent); + } + } + return bRet; +} + +OViewsWindow::TSectionsMap::iterator OViewsWindow::getIteratorAtPos(sal_uInt16 _nPos) +{ + TSectionsMap::iterator aRet = m_aSections.end(); + if ( _nPos < m_aSections.size() ) + aRet = m_aSections.begin() + _nPos; + return aRet; +} + +void OViewsWindow::setMarked(OSectionView const * _pSectionView, bool _bMark) +{ + OSL_ENSURE(_pSectionView != nullptr,"SectionView is NULL!"); + if ( _pSectionView ) + setMarked(_pSectionView->getReportSection()->getSection(),_bMark); +} + +void OViewsWindow::setMarked(const uno::Reference< report::XSection>& _xSection, bool _bMark) +{ + for (const auto& rxSection : m_aSections) + { + if ( rxSection->getReportSection().getSection() != _xSection ) + { + rxSection->setMarked(false); + } + else if ( rxSection->getStartMarker().isMarked() != _bMark ) + { + rxSection->setMarked(_bMark); + } + } +} + +void OViewsWindow::setMarked(const uno::Sequence< uno::Reference< report::XReportComponent> >& _aShapes, bool _bMark) +{ + bool bFirst = true; + for(const uno::Reference< report::XReportComponent>& rShape : _aShapes) + { + const uno::Reference< report::XSection> xSection = rShape->getSection(); + if ( xSection.is() ) + { + if ( bFirst ) + { + bFirst = false; + m_pParent->setMarked(xSection,_bMark); + } + OSectionWindow* pSectionWindow = getSectionWindow(xSection); + if ( pSectionWindow ) + { + SdrObject* pObject = SdrObject::getSdrObjectFromXShape( rShape ); + OSL_ENSURE( pObject, "OViewsWindow::setMarked: no SdrObject for the shape!" ); + if ( pObject ) + pSectionWindow->getReportSection().getSectionView().MarkObj( pObject, pSectionWindow->getReportSection().getSectionView().GetSdrPageView(), !_bMark ); + } + } + } +} + +void OViewsWindow::collectRectangles(TRectangleMap& _rSortRectangles) +{ + for (const auto& rxSection : m_aSections) + { + OSectionView& rView = rxSection->getReportSection().getSectionView(); + if ( rView.AreObjectsMarked() ) + { + rView.SortMarkedObjects(); + const size_t nCount = rView.GetMarkedObjectCount(); + for (size_t i=0; i < nCount; ++i) + { + const SdrMark* pM = rView.GetSdrMarkByIndex(i); + SdrObject* pObj = pM->GetMarkedSdrObj(); + tools::Rectangle aObjRect(pObj->GetSnapRect()); + _rSortRectangles.emplace(aObjRect,TRectangleMap::mapped_type(pObj,&rView)); + } + } + } +} + +void OViewsWindow::collectBoundResizeRect(const TRectangleMap& _rSortRectangles, ControlModification _nControlModification,bool _bAlignAtSection, tools::Rectangle& _rBound, tools::Rectangle& _rResize) +{ + bool bOnlyOnce = false; + for (const auto& [aObjRect, rObjViewPair] : _rSortRectangles) + { + if ( _rResize.IsEmpty() ) + _rResize = aObjRect; + switch(_nControlModification) + { + case ControlModification::WIDTH_SMALLEST: + if ( _rResize.getWidth() > aObjRect.getWidth() ) + _rResize = aObjRect; + break; + case ControlModification::HEIGHT_SMALLEST: + if ( _rResize.getHeight() > aObjRect.getHeight() ) + _rResize = aObjRect; + break; + case ControlModification::WIDTH_GREATEST: + if ( _rResize.getWidth() < aObjRect.getWidth() ) + _rResize = aObjRect; + break; + case ControlModification::HEIGHT_GREATEST: + if ( _rResize.getHeight() < aObjRect.getHeight() ) + _rResize = aObjRect; + break; + default: break; + } + + SdrObjTransformInfoRec aInfo; + const SdrObject* pObj = rObjViewPair.first; + pObj->TakeObjInfo(aInfo); + bool bHasFixed = !aInfo.bMoveAllowed || pObj->IsMoveProtect(); + if ( bHasFixed ) + _rBound.Union(aObjRect); + else + { + if ( _bAlignAtSection || _rSortRectangles.size() == 1 ) + { // align single object at the page + if ( ! bOnlyOnce ) + { + bOnlyOnce = true; + OReportSection* pReportSection = rObjViewPair.second->getReportSection(); + const uno::Reference< report::XSection>& xSection = pReportSection->getSection(); + try + { + uno::Reference<report::XReportDefinition> xReportDefinition = xSection->getReportDefinition(); + _rBound.Union(tools::Rectangle(getStyleProperty<sal_Int32>(xReportDefinition,PROPERTY_LEFTMARGIN),0, + getStyleProperty<awt::Size>(xReportDefinition,PROPERTY_PAPERSIZE).Width - getStyleProperty<sal_Int32>(xReportDefinition,PROPERTY_RIGHTMARGIN), + xSection->getHeight())); + } + catch(const uno::Exception &){} + } + } + else + { + _rBound.Union(rObjViewPair.second->GetMarkedObjRect()); + } + } + } +} + +void OViewsWindow::alignMarkedObjects(ControlModification _nControlModification, bool _bAlignAtSection) +{ + if ( _nControlModification == ControlModification::NONE ) + return; + + Point aRefPoint; + RectangleLess::CompareMode eCompareMode = RectangleLess::POS_LEFT; + switch (_nControlModification) + { + case ControlModification::TOP : eCompareMode = RectangleLess::POS_UPPER; break; + case ControlModification::BOTTOM: eCompareMode = RectangleLess::POS_DOWN; break; + case ControlModification::LEFT : eCompareMode = RectangleLess::POS_LEFT; break; + case ControlModification::RIGHT : eCompareMode = RectangleLess::POS_RIGHT; break; + case ControlModification::CENTER_HORIZONTAL : + case ControlModification::CENTER_VERTICAL : + { + eCompareMode = (ControlModification::CENTER_VERTICAL == _nControlModification) ? RectangleLess::POS_CENTER_VERTICAL : RectangleLess::POS_CENTER_HORIZONTAL; + uno::Reference<report::XSection> xSection = (*m_aSections.begin())->getReportSection().getSection(); + uno::Reference<report::XReportDefinition> xReportDefinition = xSection->getReportDefinition(); + aRefPoint = tools::Rectangle(getStyleProperty<sal_Int32>(xReportDefinition,PROPERTY_LEFTMARGIN),0, + getStyleProperty<awt::Size>(xReportDefinition,PROPERTY_PAPERSIZE).Width - getStyleProperty<sal_Int32>(xReportDefinition,PROPERTY_RIGHTMARGIN), + xSection->getHeight()).Center(); + } + break; + default: break; + } + RectangleLess aCompare(eCompareMode,aRefPoint); + TRectangleMap aSortRectangles(aCompare); + collectRectangles(aSortRectangles); + + tools::Rectangle aBound; + tools::Rectangle aResize; + collectBoundResizeRect(aSortRectangles,_nControlModification,_bAlignAtSection,aBound,aResize); + + bool bMove = true; + + auto aGetFun = ::std::mem_fn(&tools::Rectangle::Bottom); + auto aSetFun = ::std::mem_fn(&tools::Rectangle::SetBottom); + auto aRefFun = ::std::mem_fn(&tools::Rectangle::Top); + TRectangleMap::const_iterator aRectIter = aSortRectangles.begin(); + TRectangleMap::const_iterator aRectEnd = aSortRectangles.end(); + for (;aRectIter != aRectEnd ; ++aRectIter) + { + tools::Rectangle aObjRect = aRectIter->first; + SdrObject* pObj = aRectIter->second.first; + SdrView* pView = aRectIter->second.second; + Point aCenter(aBound.Center()); + SdrObjTransformInfoRec aInfo; + pObj->TakeObjInfo(aInfo); + if (aInfo.bMoveAllowed && !pObj->IsMoveProtect()) + { + tools::Long nXMov = 0; + tools::Long nYMov = 0; + tools::Long* pValue = &nXMov; + switch(_nControlModification) + { + case ControlModification::TOP : + aGetFun = ::std::mem_fn(&tools::Rectangle::Top); + aSetFun = ::std::mem_fn(&tools::Rectangle::SetTop); + aRefFun = ::std::mem_fn(&tools::Rectangle::Bottom); + pValue = &nYMov; + break; + case ControlModification::BOTTOM: + // defaults are already set + pValue = &nYMov; + break; + case ControlModification::CENTER_VERTICAL: + nYMov = aCenter.Y() - aObjRect.Center().Y(); + pValue = &nYMov; + bMove = false; + break; + case ControlModification::RIGHT : + aGetFun = ::std::mem_fn(&tools::Rectangle::Right); + aSetFun = ::std::mem_fn(&tools::Rectangle::SetRight); + aRefFun = ::std::mem_fn(&tools::Rectangle::Left); + break; + case ControlModification::CENTER_HORIZONTAL: + nXMov = aCenter.X() - aObjRect.Center().X(); + bMove = false; + break; + case ControlModification::LEFT : + aGetFun = ::std::mem_fn(&tools::Rectangle::Left); + aSetFun = ::std::mem_fn(&tools::Rectangle::SetLeft); + aRefFun = ::std::mem_fn(&tools::Rectangle::Right); + break; + default: + bMove = false; + break; + } + if ( bMove ) + { + tools::Rectangle aTest = aObjRect; + aSetFun(&aTest, aGetFun(&aBound)); + TRectangleMap::const_iterator aInterSectRectIter = aSortRectangles.begin(); + for (; aInterSectRectIter != aRectIter; ++aInterSectRectIter) + { + if ( pView == aInterSectRectIter->second.second && (dynamic_cast<OUnoObject*>(aInterSectRectIter->second.first) || dynamic_cast<OOle2Obj*>(aInterSectRectIter->second.first))) + { + SdrObject* pPreviousObj = aInterSectRectIter->second.first; + tools::Rectangle aIntersectRect = aTest.GetIntersection( pPreviousObj->GetSnapRect()); + if ( !aIntersectRect.IsEmpty() && (aIntersectRect.Left() != aIntersectRect.Right() && aIntersectRect.Top() != aIntersectRect.Bottom() ) ) + { + *pValue = aRefFun(&aIntersectRect) - aGetFun(&aObjRect); + break; + } + } + } + if ( aInterSectRectIter == aRectIter ) + *pValue = aGetFun(&aBound) - aGetFun(&aObjRect); + } + + if ( lcl_getNewRectSize(aObjRect,nXMov,nYMov,pObj,pView,_nControlModification) ) + { + const Size aSize(nXMov,nYMov); + pView->AddUndo(pView->GetModel()->GetSdrUndoFactory().CreateUndoMoveObject(*pObj,aSize)); + pObj->Move(aSize); + aObjRect = pObj->GetSnapRect(); + } + + // resizing control + if ( !aResize.IsEmpty() && aObjRect != aResize ) + { + nXMov = aResize.getWidth(); + nYMov = aResize.getHeight(); + switch(_nControlModification) + { + case ControlModification::WIDTH_GREATEST: + case ControlModification::HEIGHT_GREATEST: + if ( _nControlModification == ControlModification::HEIGHT_GREATEST ) + nXMov = aObjRect.getWidth(); + else if ( _nControlModification == ControlModification::WIDTH_GREATEST ) + nYMov = aObjRect.getHeight(); + lcl_getNewRectSize(aObjRect,nXMov,nYMov,pObj,pView,_nControlModification); + [[fallthrough]]; + case ControlModification::WIDTH_SMALLEST: + case ControlModification::HEIGHT_SMALLEST: + pView->AddUndo( pView->GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pObj)); + { + OObjectBase* pObjBase = dynamic_cast<OObjectBase*>(pObj); + OSL_ENSURE(pObjBase,"Where comes this object from?"); + if ( pObjBase ) + { + if ( _nControlModification == ControlModification::WIDTH_SMALLEST || _nControlModification == ControlModification::WIDTH_GREATEST ) + pObjBase->getReportComponent()->setSize(awt::Size(nXMov,aObjRect.getHeight())); + else if ( _nControlModification == ControlModification::HEIGHT_GREATEST || _nControlModification == ControlModification::HEIGHT_SMALLEST ) + pObjBase->getReportComponent()->setSize(awt::Size(aObjRect.getWidth(),nYMov)); + } + } + break; + default: + break; + } + } + } + pView->AdjustMarkHdl(); + } +} + +void OViewsWindow::createDefault() +{ + OSectionWindow* pMarkedSection = getMarkedSection(); + if ( pMarkedSection ) + pMarkedSection->getReportSection().createDefault(m_sShapeType); +} + +void OViewsWindow::setGridSnap(bool bOn) +{ + for (const auto& rxSection : m_aSections) + { + rxSection->getReportSection().getSectionView().SetGridSnap(bOn); + rxSection->getReportSection().Invalidate(); + } +} + +void OViewsWindow::setDragStripes(bool bOn) +{ + for (const auto& rxSection : m_aSections) + rxSection->getReportSection().getSectionView().SetDragStripes(bOn); +} + +sal_uInt16 OViewsWindow::getPosition(const OSectionWindow* _pSectionWindow) const +{ + auto aIter = std::find_if(m_aSections.begin(), m_aSections.end(), + [&_pSectionWindow](const VclPtr<OSectionWindow>& rxSection) { return _pSectionWindow == rxSection.get(); }); + return static_cast<sal_uInt16>(std::distance(m_aSections.begin(), aIter)); +} + +OSectionWindow* OViewsWindow::getSectionWindow(const sal_uInt16 _nPos) const +{ + OSectionWindow* aReturn = nullptr; + + if ( _nPos < m_aSections.size() ) + aReturn = m_aSections[_nPos].get(); + + return aReturn; +} + +namespace +{ + enum SectionViewAction + { + eEndDragObj, + eEndAction, + eForceToAnotherPage, + eBreakAction + }; + class ApplySectionViewAction + { + private: + SectionViewAction m_eAction; + + public: + explicit ApplySectionViewAction() + : m_eAction(eEndDragObj) + { + } + + explicit ApplySectionViewAction(SectionViewAction _eAction) + : m_eAction(_eAction) + { + } + + void operator() ( const OViewsWindow::TSectionsMap::value_type& _rhs ) + { + OSectionView& rView( _rhs->getReportSection().getSectionView() ); + switch ( m_eAction ) + { + case eEndDragObj: + rView.EndDragObj(); + break; + case eEndAction: + if ( rView.IsAction() ) + rView.EndAction ( ); + break; + case eForceToAnotherPage: + rView.ForceMarkedToAnotherPage(); + break; + case eBreakAction: + if ( rView.IsAction() ) + rView.BrkAction ( ); + break; + // default: + + } + } + }; +} + +void OViewsWindow::BrkAction() +{ + EndDragObj_removeInvisibleObjects(); + ::std::for_each( m_aSections.begin(), m_aSections.end(), ApplySectionViewAction(eBreakAction) ); +} + +void OViewsWindow::BegDragObj_createInvisibleObjectAtPosition(const tools::Rectangle& _aRect, const OSectionView& _rSection) +{ + Point aNewPos(0,0); + + for (const auto& rxSection : m_aSections) + { + OReportSection& rReportSection = rxSection->getReportSection(); + rReportSection.getPage()->setSpecialMode(); + OSectionView& rView = rReportSection.getSectionView(); + + if ( &rView != &_rSection ) + { + SdrObject *pNewObj = new SdrUnoObj( + rView.getSdrModelFromSdrView(), + "com.sun.star.form.component.FixedText"); + + pNewObj->SetLogicRect(_aRect); + pNewObj->Move(Size(0, aNewPos.Y())); + bool bChanged = rView.GetModel()->IsChanged(); + rReportSection.getPage()->InsertObject(pNewObj); + rView.GetModel()->SetChanged(bChanged); + m_aBegDragTempList.push_back(pNewObj); + + rView.MarkObj( pNewObj, rView.GetSdrPageView() ); + } + const tools::Long nSectionHeight = rReportSection.PixelToLogic(rReportSection.GetOutputSizePixel()).Height(); + aNewPos.AdjustY( -nSectionHeight ); + } +} + +void OViewsWindow::BegDragObj(const Point& _aPnt, SdrHdl* _pHdl,const OSectionView* _pSection) +{ + SAL_INFO( + "reportdesign", "Clickpoint X:" << _aPnt.X() << " Y:" << _aPnt.Y()); + + m_aBegDragTempList.clear(); + + // Calculate the absolute clickpoint in the views + Point aAbsolutePnt = _aPnt; + for (const auto& rxSection : m_aSections) + { + OReportSection& rReportSection = rxSection->getReportSection(); + OSectionView* pView = &rReportSection.getSectionView(); + if (pView == _pSection) + break; + const tools::Long nSectionHeight = rReportSection.PixelToLogic(rReportSection.GetOutputSizePixel()).Height(); + aAbsolutePnt.AdjustY(nSectionHeight ); + } + m_aDragDelta = Point(SAL_MAX_INT32, SAL_MAX_INT32); + SAL_INFO( + "reportdesign", + "Absolute X:" << aAbsolutePnt.X() << " Y:" << aAbsolutePnt.Y()); + + // Create drag lines over all viewable Views + // Therefore we need to identify the marked objects + // and create temporary objects on all other views at the same position + // relative to its occurrence. + + int nViewCount = 0; + Point aNewObjPos(0,0); + Point aLeftTop(SAL_MAX_INT32, SAL_MAX_INT32); + for (const auto& rxSection : m_aSections) + { + OReportSection& rReportSection = rxSection->getReportSection(); + + OSectionView& rView = rReportSection.getSectionView(); + + if ( rView.AreObjectsMarked() ) + { + const size_t nCount = rView.GetMarkedObjectCount(); + for (size_t i=0; i < nCount; ++i) + { + const SdrMark* pM = rView.GetSdrMarkByIndex(i); + SdrObject* pObj = pM->GetMarkedSdrObj(); + if (::std::find(m_aBegDragTempList.begin(),m_aBegDragTempList.end(),pObj) == m_aBegDragTempList.end()) + { + tools::Rectangle aRect( pObj->GetCurrentBoundRect() ); + aRect.Move(0, aNewObjPos.Y()); + + aLeftTop.setX( ::std::min( aRect.Left(), aLeftTop.X() ) ); + aLeftTop.setY( ::std::min( aRect.Top(), aLeftTop.Y() ) ); + + SAL_INFO( + "reportdesign", + "createInvisible X:" << aRect.Left() << " Y:" + << aRect.Top() << " on View #" << nViewCount); + + BegDragObj_createInvisibleObjectAtPosition(aRect, rView); + } + } + } + ++nViewCount; + tools::Rectangle aClipRect = rView.GetWorkArea(); + aClipRect.SetTop( -aNewObjPos.Y() ); + rView.SetWorkArea( aClipRect ); + + const tools::Long nSectionHeight = rReportSection.PixelToLogic(rReportSection.GetOutputSizePixel()).Height(); + aNewObjPos.AdjustY(nSectionHeight ); + } + + const sal_Int32 nDeltaX = std::abs(aLeftTop.X() - aAbsolutePnt.X()); + const sal_Int32 nDeltaY = std::abs(aLeftTop.Y() - aAbsolutePnt.Y()); + m_aDragDelta.setX( nDeltaX ); + m_aDragDelta.setY( nDeltaY ); + + Point aNewPos = aAbsolutePnt; + + const short nDrgLog = static_cast<short>(PixelToLogic(Size(3,0)).Width()); + nViewCount = 0; + for (const auto& rxSection : m_aSections) + { + OReportSection& rReportSection = rxSection->getReportSection(); + + SdrHdl* pHdl = _pHdl; + if ( pHdl ) + { + if ( &rReportSection.getSectionView() != _pSection ) + { + const SdrHdlList& rHdlList = rReportSection.getSectionView().GetHdlList(); + pHdl = rHdlList.GetHdl(_pHdl->GetKind()); + } + } + SAL_INFO( + "reportdesign", + "X:" << aNewPos.X() << " Y:" << aNewPos.Y() << " on View#" + << nViewCount++); + rReportSection.getSectionView().BegDragObj(aNewPos, nullptr, pHdl, nDrgLog); + + const tools::Long nSectionHeight = rReportSection.PixelToLogic(rReportSection.GetOutputSizePixel()).Height(); + aNewPos.AdjustY( -nSectionHeight ); + } +} + + +void OViewsWindow::ForceMarkedToAnotherPage() +{ + ::std::for_each( m_aSections.begin(), m_aSections.end(), ApplySectionViewAction(eForceToAnotherPage ) ); +} + +void OViewsWindow::BegMarkObj(const Point& _aPnt,const OSectionView* _pSection) +{ + bool bAdd = true; + Point aNewPos = _aPnt; + + tools::Long nLastSectionHeight = 0; + for (const auto& rxSection : m_aSections) + { + OReportSection& rReportSection = rxSection->getReportSection(); + if ( &rReportSection.getSectionView() == _pSection ) + { + bAdd = false; + aNewPos = _aPnt; // 2,2 + } + else if ( bAdd ) + { + const tools::Long nSectionHeight = rReportSection.PixelToLogic(rReportSection.GetOutputSizePixel()).Height(); + aNewPos.AdjustY(nSectionHeight ); + } + else + { + aNewPos.AdjustY( -nLastSectionHeight ); + } + rReportSection.getSectionView().BegMarkObj ( aNewPos ); + nLastSectionHeight = rReportSection.PixelToLogic(rReportSection.GetOutputSizePixel()).Height(); + } +} + +OSectionView* OViewsWindow::getSectionRelativeToPosition(const OSectionView* _pSection,Point& _rPnt) +{ + OSectionView* pSection = nullptr; + TSectionsMap::const_iterator aIter = m_aSections.begin(); + const TSectionsMap::const_iterator aEnd = m_aSections.end(); + aIter = std::find_if(aIter, aEnd, [&_pSection](const VclPtr<OSectionWindow>& rxSection) { + return &rxSection->getReportSection().getSectionView() == _pSection; }); + sal_Int32 nCount = static_cast<sal_Int32>(std::distance(m_aSections.cbegin(), aIter)); + OSL_ENSURE(aIter != aEnd,"This can never happen!"); + if ( _rPnt.Y() < 0 ) + { + if ( nCount ) + --aIter; + for (; nCount && (_rPnt.Y() < 0); --nCount) + { + OReportSection& rReportSection = (*aIter)->getReportSection(); + const sal_Int32 nHeight = rReportSection.PixelToLogic(rReportSection.GetOutputSizePixel()).Height(); + _rPnt.AdjustY(nHeight ); + if ( (nCount -1) > 0 && (_rPnt.Y() < 0) ) + --aIter; + } + if ( nCount == 0 ) + pSection = &(*m_aSections.begin())->getReportSection().getSectionView(); + else + pSection = &(*aIter)->getReportSection().getSectionView(); + } + else + { + for (; aIter != aEnd; ++aIter) + { + OReportSection& rReportSection = (*aIter)->getReportSection(); + const tools::Long nHeight = rReportSection.PixelToLogic(rReportSection.GetOutputSizePixel()).Height(); + if ( (_rPnt.Y() - nHeight) < 0 ) + break; + _rPnt.AdjustY( -nHeight ); + } + if ( aIter != aEnd ) + pSection = &(*aIter)->getReportSection().getSectionView(); + else + pSection = &(*(aEnd-1))->getReportSection().getSectionView(); + } + + return pSection; +} + +void OViewsWindow::EndDragObj_removeInvisibleObjects() +{ + for (const auto& rxSection : m_aSections) + { + OReportSection& rReportSection = rxSection->getReportSection(); + rReportSection.getPage()->resetSpecialMode(); + } +} + +void OViewsWindow::EndDragObj(bool _bControlKeyPressed, const OSectionView* _pSection, const Point& _aPnt) +{ + const OUString sUndoAction = RptResId(RID_STR_UNDO_CHANGEPOSITION); + const UndoContext aUndoContext( getView()->getReportView()->getController().getUndoManager(), sUndoAction ); + + Point aNewPos = _aPnt; + OSectionView* pInSection = getSectionRelativeToPosition(_pSection, aNewPos); + if (!_bControlKeyPressed && + _pSection && !_pSection->IsDragResize() && /* Not in resize mode */ + _pSection != pInSection) + { + EndDragObj_removeInvisibleObjects(); + + // we need to manipulate the current clickpoint, we subtract the old delta from BeginDrag + aNewPos -= m_aDragDelta; + + uno::Sequence< beans::NamedValue > aAllreadyCopiedObjects; + for (const auto& rxSection : m_aSections) + { + OReportSection& rReportSection = rxSection->getReportSection(); + if ( pInSection != &rReportSection.getSectionView() ) + { + rReportSection.getSectionView().BrkAction(); + rReportSection.Copy(aAllreadyCopiedObjects,true); + } + else + pInSection->EndDragObj(); + } + + if ( aAllreadyCopiedObjects.hasElements() ) + { + try + { + uno::Reference<report::XReportDefinition> xReportDefinition = getView()->getReportView()->getController().getReportDefinition(); + const sal_Int32 nLeftMargin = getStyleProperty<sal_Int32>(xReportDefinition,PROPERTY_LEFTMARGIN); + const sal_Int32 nRightMargin = getStyleProperty<sal_Int32>(xReportDefinition,PROPERTY_RIGHTMARGIN); + const sal_Int32 nPaperWidth = getStyleProperty<awt::Size>(xReportDefinition,PROPERTY_PAPERSIZE).Width; + + if ( aNewPos.X() < nLeftMargin ) + aNewPos.setX( nLeftMargin ); + if ( aNewPos.Y() < 0 ) + aNewPos.setY( 0 ); + + Point aPrevious; + for (beans::NamedValue const & namedVal : std::as_const(aAllreadyCopiedObjects)) + { + uno::Sequence< uno::Reference<report::XReportComponent> > aClones; + namedVal.Value >>= aClones; + uno::Reference<report::XReportComponent>* pColIter = aClones.getArray(); + const uno::Reference<report::XReportComponent>* pColEnd = pColIter + aClones.getLength(); + + // move the cloned Components to new positions + for (; pColIter != pColEnd; ++pColIter) + { + uno::Reference< report::XReportComponent> xRC(*pColIter); + aPrevious = VCLPoint(xRC->getPosition()); + awt::Size aSize = xRC->getSize(); + + if ( aNewPos.X() < nLeftMargin ) + { + aNewPos.setX( nLeftMargin ); + } + else if ( (aNewPos.X() + aSize.Width) > (nPaperWidth - nRightMargin) ) + { + aNewPos.setX( nPaperWidth - nRightMargin - aSize.Width ); + } + if ( aNewPos.Y() < 0 ) + { + aNewPos.setY( 0 ); + } + if ( aNewPos.X() < 0 ) + { + aSize.Width += aNewPos.X(); + aNewPos.setX( 0 ); + xRC->setSize(aSize); + } + xRC->setPosition(AWTPoint(aNewPos)); + if ( (pColIter+1) != pColEnd ) + { + // bring aNewPos to the position of the next object + uno::Reference< report::XReportComponent> xRCNext = *(pColIter + 1); + Point aNextPosition = VCLPoint(xRCNext->getPosition()); + aNewPos += aNextPosition - aPrevious; + } + } + } + } + catch(uno::Exception&) + { + } + pInSection->getReportSection()->Paste(aAllreadyCopiedObjects,true); + } + } + else + { + ::std::for_each( m_aSections.begin(), m_aSections.end(), ApplySectionViewAction() ); + EndDragObj_removeInvisibleObjects(); + } + m_aDragDelta = Point(SAL_MAX_INT32, SAL_MAX_INT32); +} + +void OViewsWindow::EndAction() +{ + ::std::for_each( m_aSections.begin(), m_aSections.end(), ApplySectionViewAction(eEndAction) ); +} + +void OViewsWindow::MovAction(const Point& _aPnt,const OSectionView* _pSection, bool _bControlKeySet) +{ + Point aRealMousePos = _aPnt; + Point aCurrentSectionPos; + SAL_INFO( + "reportdesign", + "X:" << aRealMousePos.X() << " Y:" << aRealMousePos.Y()); + + Point aHdlPos; + SdrHdl* pHdl = _pSection->GetDragHdl(); + if ( pHdl ) + { + aHdlPos = pHdl->GetPos(); + } + + for (const auto& rxSection : m_aSections) + { + OReportSection& rReportSection = rxSection->getReportSection(); + if ( &rReportSection.getSectionView() == _pSection ) + break; + const tools::Long nSectionHeight = rxSection->PixelToLogic(rReportSection.GetOutputSizePixel()).Height(); + aCurrentSectionPos.AdjustY(nSectionHeight ); + } + aRealMousePos += aCurrentSectionPos; + + // If control key is pressed the work area is limited to the section with the current selection. + Point aPosForWorkArea(0,0); + for (const auto& rxSection : m_aSections) + { + OReportSection& rReportSection = rxSection->getReportSection(); + OSectionView& rView = rReportSection.getSectionView(); + const tools::Long nSectionHeight = rxSection->PixelToLogic(rxSection->GetOutputSizePixel()).Height(); + + if (_bControlKeySet) + { + tools::Rectangle aClipRect = rView.GetWorkArea(); + aClipRect.SetTop( aCurrentSectionPos.Y() - aPosForWorkArea.Y() ); + aClipRect.SetBottom( aClipRect.Top() + nSectionHeight ); + rView.SetWorkArea( aClipRect ); + } + else + { + tools::Rectangle aClipRect = rView.GetWorkArea(); + aClipRect.SetTop( -aPosForWorkArea.Y() ); + rView.SetWorkArea( aClipRect ); + } + aPosForWorkArea.AdjustY(nSectionHeight ); + } + + + for (const auto& rxSection : m_aSections) + { + OReportSection& rReportSection = rxSection->getReportSection(); + SdrHdl* pCurrentHdl = rReportSection.getSectionView().GetDragHdl(); + if ( pCurrentHdl && aRealMousePos.Y() > 0 ) + aRealMousePos = _aPnt + pCurrentHdl->GetPos() - aHdlPos; + rReportSection.getSectionView().MovAction ( aRealMousePos ); + const tools::Long nSectionHeight = rxSection->PixelToLogic(rxSection->GetOutputSizePixel()).Height(); + aRealMousePos.AdjustY( -nSectionHeight ); + } +} + +bool OViewsWindow::IsAction() const +{ + return std::any_of(m_aSections.begin(), m_aSections.end(), + [](const VclPtr<OSectionWindow>& rxSection) { return rxSection->getReportSection().getSectionView().IsAction(); }); +} + +bool OViewsWindow::IsDragObj() const +{ + return std::any_of(m_aSections.begin(), m_aSections.end(), + [](const VclPtr<OSectionWindow>& rxSection) { return rxSection->getReportSection().getSectionView().IsAction(); }); +} + +sal_uInt32 OViewsWindow::getMarkedObjectCount() const +{ + return std::accumulate(m_aSections.begin(), m_aSections.end(), sal_uInt32(0), + [](const sal_uInt32 nCount, const VclPtr<OSectionWindow>& rxSection) { + return nCount + static_cast<sal_uInt32>(rxSection->getReportSection().getSectionView().GetMarkedObjectCount()); }); +} + +void OViewsWindow::handleKey(const vcl::KeyCode& _rCode) +{ + const sal_uInt16 nCode = _rCode.GetCode(); + if ( _rCode.IsMod1() ) + { + // scroll page + OScrollWindowHelper* pScrollWindow = getView()->getScrollWindow(); + ScrollBar& rScrollBar = ( nCode == KEY_LEFT || nCode == KEY_RIGHT ) ? pScrollWindow->GetHScroll() : pScrollWindow->GetVScroll(); + if ( rScrollBar.IsVisible() ) + rScrollBar.DoScrollAction(( nCode == KEY_RIGHT || nCode == KEY_UP ) ? ScrollType::LineUp : ScrollType::LineDown ); + return; + } + + for (const auto& rxSection : m_aSections) + { + OReportSection& rReportSection = rxSection->getReportSection(); + tools::Long nX = 0; + tools::Long nY = 0; + + if ( nCode == KEY_UP ) + nY = -1; + else if ( nCode == KEY_DOWN ) + nY = 1; + else if ( nCode == KEY_LEFT ) + nX = -1; + else if ( nCode == KEY_RIGHT ) + nX = 1; + + if ( rReportSection.getSectionView().AreObjectsMarked() ) + { + if ( _rCode.IsMod2() ) + { + // move in 1 pixel distance + const Size aPixelSize = rReportSection.PixelToLogic( Size( 1, 1 ) ); + nX *= aPixelSize.Width(); + nY *= aPixelSize.Height(); + } + else + { + // move in 1 mm distance + nX *= DEFAUL_MOVE_SIZE; + nY *= DEFAUL_MOVE_SIZE; + } + + OSectionView& rView = rReportSection.getSectionView(); + const SdrHdlList& rHdlList = rView.GetHdlList(); + SdrHdl* pHdl = rHdlList.GetFocusHdl(); + + if ( pHdl == nullptr ) + { + // no handle selected + if ( rView.IsMoveAllowed() ) + { + // restrict movement to work area + tools::Rectangle rWorkArea = rView.GetWorkArea(); + rWorkArea.AdjustRight( 1 ); + + if ( !rWorkArea.IsEmpty() ) + { + if ( rWorkArea.Top() < 0 ) + rWorkArea.SetTop( 0 ); + tools::Rectangle aMarkRect( rView.GetMarkedObjRect() ); + aMarkRect.Move( nX, nY ); + + if ( !rWorkArea.Contains( aMarkRect ) ) + { + if ( aMarkRect.Left() < rWorkArea.Left() ) + nX += rWorkArea.Left() - aMarkRect.Left(); + + if ( aMarkRect.Right() > rWorkArea.Right() ) + nX -= aMarkRect.Right() - rWorkArea.Right(); + + if ( aMarkRect.Top() < rWorkArea.Top() ) + nY += rWorkArea.Top() - aMarkRect.Top(); + + if ( aMarkRect.Bottom() > rWorkArea.Bottom() ) + nY -= aMarkRect.Bottom() - rWorkArea.Bottom(); + } + bool bCheck = false; + const SdrMarkList& rMarkList = rView.GetMarkedObjectList(); + for (size_t i = 0; !bCheck && i < rMarkList.GetMarkCount(); ++i ) + { + SdrMark* pMark = rMarkList.GetMark(i); + bCheck = dynamic_cast<OUnoObject*>(pMark->GetMarkedSdrObj()) != nullptr|| dynamic_cast<OOle2Obj*>(pMark->GetMarkedSdrObj()); + } + + + if ( bCheck ) + { + SdrObject* pOverlapped = isOver(aMarkRect,*rReportSection.getPage(),rView); + if ( pOverlapped ) + { + do + { + tools::Rectangle aOver = pOverlapped->GetLastBoundRect(); + Point aPos; + if ( nCode == KEY_UP ) + { + aPos.setX( aMarkRect.Left() ); + aPos.setY( aOver.Top() - aMarkRect.getHeight() ); + nY += (aPos.Y() - aMarkRect.Top()); + } + else if ( nCode == KEY_DOWN ) + { + aPos.setX( aMarkRect.Left() ); + aPos.setY( aOver.Bottom() ); + nY += (aPos.Y() - aMarkRect.Top()); + } + else if ( nCode == KEY_LEFT ) + { + aPos.setX( aOver.Left() - aMarkRect.getWidth() ); + aPos.setY( aMarkRect.Top() ); + nX += (aPos.X() - aMarkRect.Left()); + } + else if ( nCode == KEY_RIGHT ) + { + aPos.setX( aOver.Right() ); + aPos.setY( aMarkRect.Top() ); + nX += (aPos.X() - aMarkRect.Left()); + } + + aMarkRect.SetPos(aPos); + if ( !rWorkArea.Contains( aMarkRect ) ) + { + break; + } + pOverlapped = isOver(aMarkRect,*rReportSection.getPage(),rView); + } + while(pOverlapped != nullptr); + if (pOverlapped != nullptr) + break; + } + } + } + + if ( nX != 0 || nY != 0 ) + { + rView.MoveAllMarked( Size( nX, nY ) ); + rView.MakeVisible( rView.GetAllMarkedRect(), rReportSection); + } + } + } + else // pHdl != nullptr + { + // move the handle + if (nX || nY) + { + const Point aStartPoint( pHdl->GetPos() ); + const Point aEndPoint( pHdl->GetPos() + Point( nX, nY ) ); + const SdrDragStat& rDragStat = rView.GetDragStat(); + + // start dragging + rView.BegDragObj( aStartPoint, nullptr, pHdl, 0 ); + + if ( rView.IsDragObj() ) + { + const bool bWasNoSnap = rDragStat.IsNoSnap(); + const bool bWasSnapEnabled = rView.IsSnapEnabled(); + + // switch snapping off + if ( !bWasNoSnap ) + const_cast<SdrDragStat&>(rDragStat).SetNoSnap(); + if ( bWasSnapEnabled ) + rView.SetSnapEnabled( false ); + + tools::Rectangle aNewRect; + bool bCheck = false; + const SdrMarkList& rMarkList = rView.GetMarkedObjectList(); + for (size_t i = 0; !bCheck && i < rMarkList.GetMarkCount(); ++i ) + { + SdrMark* pMark = rMarkList.GetMark(i); + bCheck = dynamic_cast<OUnoObject*>(pMark->GetMarkedSdrObj()) != nullptr || dynamic_cast<OOle2Obj*>(pMark->GetMarkedSdrObj()) != nullptr; + if ( bCheck ) + aNewRect.Union(pMark->GetMarkedSdrObj()->GetLastBoundRect()); + } + + switch(pHdl->GetKind()) + { + case SdrHdlKind::Left: + case SdrHdlKind::UpperLeft: + case SdrHdlKind::LowerLeft: + case SdrHdlKind::Upper: + aNewRect.AdjustLeft(nX ); + aNewRect.AdjustTop(nY ); + break; + case SdrHdlKind::UpperRight: + case SdrHdlKind::Right: + case SdrHdlKind::LowerRight: + case SdrHdlKind::Lower: + aNewRect.setWidth(aNewRect.getWidth() + nX); + aNewRect.setHeight(aNewRect.getHeight() + nY); + break; + default: + break; + } + if ( !(bCheck && isOver(aNewRect,*rReportSection.getPage(),rView)) ) + rView.MovAction(aEndPoint); + rView.EndDragObj(); + + // restore snap + if ( !bWasNoSnap ) + const_cast<SdrDragStat&>(rDragStat).SetNoSnap( bWasNoSnap ); + if ( bWasSnapEnabled ) + rView.SetSnapEnabled( bWasSnapEnabled ); + } + + // make moved handle visible + const tools::Rectangle aVisRect( aEndPoint - Point( DEFAUL_MOVE_SIZE, DEFAUL_MOVE_SIZE ), Size( 200, 200 ) ); + rView.MakeVisible( aVisRect, rReportSection); + } + } + rView.AdjustMarkHdl(); + } + } +} + +void OViewsWindow::stopScrollTimer() +{ + ::std::for_each(m_aSections.begin(),m_aSections.end(), + [] (const TSectionsMap::value_type& sectionPtr) { + sectionPtr->getReportSection().stopScrollTimer(); + }); +} + +void OViewsWindow::fillCollapsedSections(::std::vector<sal_uInt16>& _rCollapsedPositions) const +{ + sal_uInt16 i = 0; + for (const auto& rxSection : m_aSections) + { + if ( rxSection->getStartMarker().isCollapsed() ) + _rCollapsedPositions.push_back(i); + ++i; + } +} + +void OViewsWindow::collapseSections(const uno::Sequence< beans::PropertyValue>& _aCollapsedSections) +{ + for (const beans::PropertyValue& rSection : _aCollapsedSections) + { + sal_uInt16 nPos = sal_uInt16(-1); + if ( (rSection.Value >>= nPos) && nPos < m_aSections.size() ) + { + m_aSections[nPos]->setCollapsed(true); + } + } +} + +void OViewsWindow::zoom(const Fraction& _aZoom) +{ + const MapMode& aMapMode = GetMapMode(); + + Fraction aStartWidth(tools::Long(REPORT_STARTMARKER_WIDTH)); + if ( _aZoom < aMapMode.GetScaleX() ) + aStartWidth *= aMapMode.GetScaleX(); + else + aStartWidth *= _aZoom; + + setZoomFactor(_aZoom,*this); + + for (const auto& rxSection : m_aSections) + { + rxSection->zoom(_aZoom); + } + + Resize(); + + Size aOut = GetOutputSizePixel(); + aOut.setWidth( tools::Long(aStartWidth) ); + aOut = PixelToLogic(aOut); + + tools::Rectangle aRect(PixelToLogic(Point(0,0)),aOut); + Invalidate(aRect, InvalidateFlags::NoChildren); +} + +void OViewsWindow::scrollChildren(const Point& _aThumbPos) +{ + const Point aPos(PixelToLogic(_aThumbPos)); + { + MapMode aMapMode = GetMapMode(); + const Point aOld = aMapMode.GetOrigin(); + aMapMode.SetOrigin(m_pParent->GetMapMode().GetOrigin()); + + const Point aPosY(m_pParent->PixelToLogic(_aThumbPos,aMapMode)); + + aMapMode.SetOrigin( Point(aOld.X() , - aPosY.Y())); + SetMapMode( aMapMode ); + Scroll(0, -( aOld.Y() + aPosY.Y()),ScrollFlags::Children); + } + + for (const auto& rxSection : m_aSections) + { + rxSection->scrollChildren(aPos.X()); + } +} + +void OViewsWindow::fillControlModelSelection(::std::vector< uno::Reference< uno::XInterface > >& _rSelection) const +{ + for (const auto& rxSection : m_aSections) + { + rxSection->getReportSection().fillControlModelSelection(_rSelection); + } +} + +} // rptui + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/reportdesign/source/ui/report/dlgedclip.cxx b/reportdesign/source/ui/report/dlgedclip.cxx new file mode 100644 index 000000000..1f36563fe --- /dev/null +++ b/reportdesign/source/ui/report/dlgedclip.cxx @@ -0,0 +1,91 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * 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 . + */ +#include <dlgedclip.hxx> +#include <osl/diagnose.h> +#include <sot/exchange.hxx> + +namespace rptui +{ + +using namespace ::com::sun::star; + + +// OReportExchange + + +OReportExchange::OReportExchange(const TSectionElements& _rCopyElements ) +: m_aCopyElements(_rCopyElements) +{ +} + +SotClipboardFormatId OReportExchange::getDescriptorFormatId() +{ + static SotClipboardFormatId s_nFormat = static_cast<SotClipboardFormatId>(-1); + if (static_cast<SotClipboardFormatId>(-1) == s_nFormat) + { + s_nFormat = SotExchange::RegisterFormatName("application/x-openoffice;windows_formatname=\"report.ReportObjectsTransfer\""); + OSL_ENSURE(static_cast<SotClipboardFormatId>(-1) != s_nFormat, "OReportExchange::getDescriptorFormatId: bad exchange id!"); + } + return s_nFormat; +} + +void OReportExchange::AddSupportedFormats() +{ + AddFormat(getDescriptorFormatId()); +} + +bool OReportExchange::GetData( const datatransfer::DataFlavor& _rFlavor, const OUString& /*rDestDoc*/ ) +{ + const SotClipboardFormatId nFormatId = SotExchange::GetFormat(_rFlavor); + return (nFormatId == getDescriptorFormatId()) && SetAny( uno::Any(m_aCopyElements) ); +} + +bool OReportExchange::canExtract(const DataFlavorExVector& _rFlavor) +{ + return IsFormatSupported(_rFlavor,getDescriptorFormatId()); +} + +OReportExchange::TSectionElements OReportExchange::extractCopies(const TransferableDataHelper& _rData) +{ + SotClipboardFormatId nKnownFormatId = getDescriptorFormatId(); + if ( _rData.HasFormat( nKnownFormatId ) ) + { + // extract the any from the transferable + datatransfer::DataFlavor aFlavor; + bool bSuccess = + SotExchange::GetFormatDataFlavor(nKnownFormatId, aFlavor); + OSL_ENSURE(bSuccess, "OReportExchange::extractCopies: invalid data format (no flavor)!"); + + uno::Any aDescriptor = _rData.GetAny(aFlavor, OUString()); + + TSectionElements aCopies; + bSuccess = aDescriptor >>= aCopies; + OSL_ENSURE(bSuccess, "OReportExchange::extractCopies: invalid clipboard format!"); + + // build the real descriptor + return aCopies; + } + + return TSectionElements(); +} + +} // rptui + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/reportdesign/source/ui/report/dlgedfac.cxx b/reportdesign/source/ui/report/dlgedfac.cxx new file mode 100644 index 000000000..7429d5517 --- /dev/null +++ b/reportdesign/source/ui/report/dlgedfac.cxx @@ -0,0 +1,99 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * 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 . + */ +#include <dlgedfac.hxx> +#include <strings.hxx> +#include <RptObject.hxx> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <osl/diagnose.h> + +namespace rptui +{ +using namespace ::com::sun::star; + + +DlgEdFactory::DlgEdFactory() +{ + SdrObjFactory::InsertMakeObjectHdl( LINK(this, DlgEdFactory, MakeObject) ); +} + + +DlgEdFactory::~DlgEdFactory() COVERITY_NOEXCEPT_FALSE +{ + SdrObjFactory::RemoveMakeObjectHdl( LINK(this, DlgEdFactory, MakeObject) ); +} + + +IMPL_STATIC_LINK( + DlgEdFactory, MakeObject, SdrObjCreatorParams, aParams, SdrObject* ) +{ + SdrObject* pNewObj = nullptr; + + if ( aParams.nInventor == SdrInventor::ReportDesign ) + { + switch( aParams.nObjIdentifier ) + { + case SdrObjKind::ReportDesignFixedText: + pNewObj = new OUnoObject(aParams.rSdrModel, SERVICE_FIXEDTEXT + ,OUString("com.sun.star.form.component.FixedText") + ,SdrObjKind::ReportDesignFixedText); + break; + case SdrObjKind::ReportDesignImageControl: + pNewObj = new OUnoObject(aParams.rSdrModel, SERVICE_IMAGECONTROL + ,OUString("com.sun.star.form.component.DatabaseImageControl") + ,SdrObjKind::ReportDesignImageControl); + break; + case SdrObjKind::ReportDesignFormattedField: + pNewObj = new OUnoObject(aParams.rSdrModel, SERVICE_FORMATTEDFIELD + ,OUString("com.sun.star.form.component.FormattedField") + ,SdrObjKind::ReportDesignFormattedField); + break; + case SdrObjKind::ReportDesignVerticalFixedLine: + case SdrObjKind::ReportDesignHorizontalFixedLine: + { + OUnoObject* pObj = new OUnoObject(aParams.rSdrModel, SERVICE_FIXEDLINE + ,OUString("com.sun.star.awt.UnoControlFixedLineModel") + ,aParams.nObjIdentifier); + pNewObj = pObj; + if ( aParams.nObjIdentifier == SdrObjKind::ReportDesignHorizontalFixedLine ) + { + uno::Reference<beans::XPropertySet> xProp = pObj->getAwtComponent(); + xProp->setPropertyValue( PROPERTY_ORIENTATION, uno::Any(sal_Int32(0)) ); + } + } + break; + case SdrObjKind::CustomShape: + pNewObj = new OCustomShape(aParams.rSdrModel, SERVICE_SHAPE); + break; + case SdrObjKind::ReportDesignSubReport: + pNewObj = new OOle2Obj(aParams.rSdrModel, SERVICE_REPORTDEFINITION, SdrObjKind::ReportDesignSubReport); + break; + case SdrObjKind::OLE2: + pNewObj = new OOle2Obj(aParams.rSdrModel, "com.sun.star.chart2.ChartDocument", SdrObjKind::OLE2); + break; + default: + OSL_FAIL("Unknown object id"); + break; + } + } + return pNewObj; +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/reportdesign/source/ui/report/dlgedfunc.cxx b/reportdesign/source/ui/report/dlgedfunc.cxx new file mode 100644 index 000000000..8a84093cd --- /dev/null +++ b/reportdesign/source/ui/report/dlgedfunc.cxx @@ -0,0 +1,894 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * 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 . + */ +#include <vcl/scrbar.hxx> +#include <vcl/seleng.hxx> +#include <vcl/ptrstyle.hxx> +#include <com/sun/star/embed/EmbedStates.hpp> +#include <com/sun/star/embed/XEmbeddedObject.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> + +#include <svx/svdview.hxx> +#include <svx/svdpagv.hxx> +#include <svx/svdetc.hxx> +#include <svx/svddrgmt.hxx> +#include <svx/svdoashp.hxx> +#include <svx/svxids.hrc> +#include <svx/svditer.hxx> + +#include <toolkit/helper/vclunohelper.hxx> + +#include <dlgedfunc.hxx> +#include <ReportSection.hxx> +#include <DesignView.hxx> +#include <ReportController.hxx> +#include <SectionView.hxx> +#include <ViewsWindow.hxx> +#include <ReportWindow.hxx> +#include <RptObject.hxx> +#include <ScrollHelper.hxx> +#include <UITools.hxx> + +#include <strings.hxx> +#include <UndoEnv.hxx> +#include <RptModel.hxx> +#include <comphelper/propertysequence.hxx> +#include <tools/diagnose_ex.h> + +#define DEFAUL_MOVE_SIZE 100 +namespace rptui +{ +using namespace ::com::sun::star; + + +IMPL_LINK_NOARG( DlgEdFunc, ScrollTimeout, Timer *, void ) +{ + ForceScroll( m_pParent->PixelToLogic( m_pParent->GetPointerPosPixel() ) ); +} + + +void DlgEdFunc::ForceScroll( const Point& rPos ) +{ + aScrollTimer.Stop(); + + OReportWindow* pReportWindow = m_pParent->getSectionWindow()->getViewsWindow()->getView(); + OScrollWindowHelper* pScrollWindow = pReportWindow->getScrollWindow(); + + Size aOut = pReportWindow->GetOutputSizePixel(); + Fraction aStartWidth(tools::Long(REPORT_STARTMARKER_WIDTH)); + aStartWidth *= m_pParent->GetMapMode().GetScaleX(); + + aOut.AdjustWidth( -static_cast<tools::Long>(aStartWidth) ); + aOut.setHeight( m_pParent->GetOutputSizePixel().Height() ); + + Point aPos = pScrollWindow->getThumbPos(); + aPos.setX( aPos.X() * 0.5 ); + aPos.setY( aPos.Y() * 0.5 ); + tools::Rectangle aOutRect( aPos, aOut ); + aOutRect = m_pParent->PixelToLogic( aOutRect ); + tools::Rectangle aWorkArea(Point(), pScrollWindow->getTotalSize()); + aWorkArea.AdjustRight( -static_cast<tools::Long>(aStartWidth) ); + aWorkArea = pScrollWindow->PixelToLogic( aWorkArea ); + if( !aOutRect.Contains( rPos ) && aWorkArea.Contains( rPos ) ) + { + ScrollBar& rHScroll = pScrollWindow->GetHScroll(); + ScrollBar& rVScroll = pScrollWindow->GetVScroll(); + ScrollType eH = ScrollType::LineDown,eV = ScrollType::LineDown; + if( rPos.X() < aOutRect.Left() ) + eH = ScrollType::LineUp; + else if( rPos.X() <= aOutRect.Right() ) + eH = ScrollType::DontKnow; + + if( rPos.Y() < aOutRect.Top() ) + eV = ScrollType::LineUp; + else if( rPos.Y() <= aOutRect.Bottom() ) + eV = ScrollType::DontKnow; + + rHScroll.DoScrollAction(eH); + rVScroll.DoScrollAction(eV); + } + + aScrollTimer.Start(); +} + +DlgEdFunc::DlgEdFunc( OReportSection* _pParent ) + : m_pParent(_pParent) + , m_rView(_pParent->getSectionView()) + , aScrollTimer("reportdesign DlgEdFunc aScrollTimer") + , m_pOverlappingObj(nullptr) + , m_nOverlappedControlColor(0) + , m_nOldColor(0) + , m_bSelectionMode(false) + , m_bUiActive(false) + , m_bShowPropertyBrowser(false) +{ + aScrollTimer.SetInvokeHandler( LINK( this, DlgEdFunc, ScrollTimeout ) ); + m_rView.SetActualWin( m_pParent->GetOutDev() ); + aScrollTimer.SetTimeout( SELENG_AUTOREPEAT_INTERVAL ); +} + +void DlgEdFunc::setOverlappedControlColor(Color _nColor) +{ + m_nOverlappedControlColor = _nColor; +} + +static Color lcl_setColorOfObject(const uno::Reference< uno::XInterface >& _xObj, Color _nColorTRGB) +{ + Color nBackColor; + try + { + uno::Reference<report::XReportComponent> xComponent(_xObj, uno::UNO_QUERY_THROW); + uno::Reference< beans::XPropertySet > xProp(xComponent, uno::UNO_QUERY_THROW); + uno::Any aAny = xProp->getPropertyValue(PROPERTY_CONTROLBACKGROUND); + if (aAny.hasValue()) + { + aAny >>= nBackColor; + // try to set background color at the ReportComponent + uno::Any aBlackColorAny(_nColorTRGB); + xProp->setPropertyValue(PROPERTY_CONTROLBACKGROUND, aBlackColorAny); + } + } + catch(uno::Exception&) + { + } + return nBackColor; +} + +DlgEdFunc::~DlgEdFunc() +{ + unColorizeOverlappedObj(); + aScrollTimer.Stop(); +} + + +bool DlgEdFunc::MouseButtonDown( const MouseEvent& rMEvt ) +{ + m_aMDPos = m_pParent->PixelToLogic( rMEvt.GetPosPixel() ); + m_pParent->GrabFocus(); + bool bHandled = false; + if ( rMEvt.IsLeft() ) + { + if ( rMEvt.GetClicks() > 1 ) + { + // show property browser + uno::Sequence<beans::PropertyValue> aArgs( comphelper::InitPropertySequence({ + { "ShowProperties", uno::Any(true) } + })); + m_pParent->getSectionWindow()->getViewsWindow()->getView()->getReportView()->getController().executeUnChecked(SID_SHOW_PROPERTYBROWSER,aArgs); + m_pParent->getSectionWindow()->getViewsWindow()->getView()->getReportView()->UpdatePropertyBrowserDelayed(m_rView); + // TODO character in shapes + // SdrViewEvent aVEvt; + // m_rView.PickAnything(rMEvt, SdrMouseEventKind::BUTTONDOWN, aVEvt); + // if ( aVEvt.mpRootObj && aVEvt.pRootObj->ISA(SdrTextObj) ) + // SetInEditMode(static_cast<SdrTextObj *>(aVEvt.mpRootObj),rMEvt, sal_False); + bHandled = true; + } + else + { + SdrHdl* pHdl = m_rView.PickHandle(m_aMDPos); + + // if selected object was hit, drag object + if ( pHdl!=nullptr || m_rView.IsMarkedHit(m_aMDPos) ) + { + bHandled = true; + m_pParent->CaptureMouse(); + m_pParent->getSectionWindow()->getViewsWindow()->BegDragObj(m_aMDPos, pHdl,&m_rView); + } + } + } + else if ( rMEvt.IsRight() && !rMEvt.IsLeft() && rMEvt.GetClicks() == 1 ) // mark object when context menu was selected + { + SdrPageView* pPV = m_rView.GetSdrPageView(); + SdrViewEvent aVEvt; + if ( m_rView.PickAnything(rMEvt, SdrMouseEventKind::BUTTONDOWN, aVEvt) != SdrHitKind::MarkedObject && !rMEvt.IsShift() ) + m_pParent->getSectionWindow()->getViewsWindow()->unmarkAllObjects(nullptr); + if ( aVEvt.mpRootObj ) + m_rView.MarkObj(aVEvt.mpRootObj, pPV); + else + m_pParent->getSectionWindow()->getViewsWindow()->unmarkAllObjects(nullptr); + + bHandled = true; + } + else if( !rMEvt.IsLeft() ) + bHandled = true; + if ( !bHandled ) + m_pParent->CaptureMouse(); + return bHandled; +} + + +bool DlgEdFunc::MouseButtonUp( const MouseEvent& /*rMEvt*/ ) +{ + m_pParent->getSectionWindow()->getViewsWindow()->stopScrollTimer(); + return false; +} + +void DlgEdFunc::checkTwoClicks(const MouseEvent& rMEvt) +{ + deactivateOle(); + + const sal_uInt16 nClicks = rMEvt.GetClicks(); + if ( !(nClicks == 2 && rMEvt.IsLeft()) ) + return; + + if ( m_rView.AreObjectsMarked() ) + { + const SdrMarkList& rMarkList = m_rView.GetMarkedObjectList(); + if (rMarkList.GetMarkCount() == 1) + { + const SdrMark* pMark = rMarkList.GetMark(0); + SdrObject* pObj = pMark->GetMarkedSdrObj(); + activateOle(pObj); + } + } +} + +void DlgEdFunc::stopScrollTimer() +{ + unColorizeOverlappedObj(); + aScrollTimer.Stop(); + if ( m_pParent->IsMouseCaptured() ) + m_pParent->ReleaseMouse(); +} + + +bool DlgEdFunc::MouseMove( const MouseEvent& /*rMEvt*/ ) +{ + return false; +} + +bool DlgEdFunc::handleKeyEvent(const KeyEvent& _rEvent) +{ + bool bReturn = false; + + if ( !m_bUiActive ) + { + const vcl::KeyCode& rCode = _rEvent.GetKeyCode(); + sal_uInt16 nCode = rCode.GetCode(); + + switch ( nCode ) + { + case KEY_ESCAPE: + { + if ( m_pParent->getSectionWindow()->getViewsWindow()->IsAction() ) + { + m_pParent->getSectionWindow()->getViewsWindow()->BrkAction(); + bReturn = true; + } + else if ( m_rView.IsTextEdit() ) + { + m_rView.SdrEndTextEdit(); + bReturn = true; + } + else if ( m_rView.AreObjectsMarked() ) + { + const SdrHdlList& rHdlList = m_rView.GetHdlList(); + SdrHdl* pHdl = rHdlList.GetFocusHdl(); + if ( pHdl ) + const_cast<SdrHdlList&>(rHdlList).ResetFocusHdl(); + else + m_pParent->getSectionWindow()->getViewsWindow()->unmarkAllObjects(nullptr); + + deactivateOle(true); + bReturn = false; + } + else + { + deactivateOle(true); + } + } + break; + case KEY_TAB: + { + if ( !rCode.IsMod1() && !rCode.IsMod2() ) + { + // mark next object + if ( !m_rView.MarkNextObj( !rCode.IsShift() ) ) + { + // if no next object, mark first/last + m_rView.UnmarkAllObj(); + m_rView.MarkNextObj( !rCode.IsShift() ); + } + + if ( m_rView.AreObjectsMarked() ) + m_rView.MakeVisible( m_rView.GetAllMarkedRect(), *m_pParent); + + bReturn = true; + } + else if ( rCode.IsMod1() && rCode.IsMod2()) + { + // selected handle + const SdrHdlList& rHdlList = m_rView.GetHdlList(); + const_cast<SdrHdlList&>(rHdlList).TravelFocusHdl( !rCode.IsShift() ); + + // guarantee visibility of focused handle + SdrHdl* pHdl = rHdlList.GetFocusHdl(); + if ( pHdl ) + { + Point aHdlPosition( pHdl->GetPos() ); + tools::Rectangle aVisRect( aHdlPosition - Point( DEFAUL_MOVE_SIZE, DEFAUL_MOVE_SIZE ), Size( 200, 200 ) ); + m_rView.MakeVisible( aVisRect, *m_pParent); + } + + bReturn = true; + } + } + break; + case KEY_UP: + case KEY_DOWN: + case KEY_LEFT: + case KEY_RIGHT: + { + m_pParent->getSectionWindow()->getViewsWindow()->handleKey(rCode); + bReturn = true; + } + break; + case KEY_RETURN: + if ( !rCode.IsMod1() ) + { + const SdrMarkList& rMarkList = m_rView.GetMarkedObjectList(); + if ( rMarkList.GetMarkCount() == 1 ) + { + SdrObject* pObj = rMarkList.GetMark( 0 )->GetMarkedSdrObj(); + activateOle(pObj); + } + } + break; + case KEY_DELETE: + if ( !rCode.IsMod1() && !rCode.IsMod2() ) + { + bReturn = true; + break; + } + [[fallthrough]]; + default: + { + bReturn = m_rView.KeyInput(_rEvent, m_pParent); + } + break; + } + } + + if ( bReturn && m_pParent->IsMouseCaptured() ) + m_pParent->ReleaseMouse(); + + return bReturn; +} + +void DlgEdFunc::activateOle(SdrObject* _pObj) +{ + if ( !_pObj ) + return; + + const SdrObjKind nSdrObjKind = _pObj->GetObjIdentifier(); + + // OLE: activate + + if (nSdrObjKind != SdrObjKind::OLE2) + return; + + SdrOle2Obj* pOleObj = dynamic_cast<SdrOle2Obj*>(_pObj); + if (!(pOleObj && pOleObj->GetObjRef().is())) + return; + + if (m_rView.IsTextEdit()) + { + m_rView.SdrEndTextEdit(); + } + + pOleObj->AddOwnLightClient(); + pOleObj->SetWindow(VCLUnoHelper::GetInterface(m_pParent)); + try + { + pOleObj->GetObjRef()->changeState( embed::EmbedStates::UI_ACTIVE ); + m_bUiActive = true; + OReportController& rController = m_pParent->getSectionWindow()->getViewsWindow()->getView()->getReportView()->getController(); + m_bShowPropertyBrowser = rController.isCommandChecked(SID_SHOW_PROPERTYBROWSER); + if ( m_bShowPropertyBrowser ) + rController.executeChecked(SID_SHOW_PROPERTYBROWSER,uno::Sequence< beans::PropertyValue >()); + } + catch( uno::Exception& ) + { + DBG_UNHANDLED_EXCEPTION("reportdesign"); + } +} + +void DlgEdFunc::deactivateOle(bool _bSelect) +{ + OLEObjCache& rObjCache = GetSdrGlobalData().GetOLEObjCache(); + OReportController& rController = m_pParent->getSectionWindow()->getViewsWindow()->getView()->getReportView()->getController(); + const size_t nCount = rObjCache.size(); + for(size_t i = 0 ; i < nCount;++i) + { + SdrOle2Obj* pObj = rObjCache[i]; + if ( m_pParent->getPage() == pObj->getSdrPageFromSdrObject() ) + { + uno::Reference< embed::XEmbeddedObject > xObj = pObj->GetObjRef(); + if ( xObj.is() && xObj->getCurrentState() == embed::EmbedStates::UI_ACTIVE ) + { + xObj->changeState( embed::EmbedStates::RUNNING ); + m_bUiActive = false; + if ( m_bShowPropertyBrowser ) + { + rController.executeChecked(SID_SHOW_PROPERTYBROWSER,uno::Sequence< beans::PropertyValue >()); + } + + if ( _bSelect ) + { + SdrPageView* pPV = m_rView.GetSdrPageView(); + m_rView.MarkObj(pObj, pPV); + } + } + } + } +} + +void DlgEdFunc::colorizeOverlappedObject(SdrObject* _pOverlappedObj) +{ + OObjectBase* pObj = dynamic_cast<OObjectBase*>(_pOverlappedObj); + if ( !pObj ) + return; + + const uno::Reference<report::XReportComponent>& xComponent = pObj->getReportComponent(); + if (xComponent.is() && xComponent != m_xOverlappingObj) + { + OReportModel& rRptModel(static_cast< OReportModel& >(_pOverlappedObj->getSdrModelFromSdrObject())); + OXUndoEnvironment::OUndoEnvLock aLock(rRptModel.GetUndoEnv()); + + // uncolorize an old object, if there is one + unColorizeOverlappedObj(); + + m_nOldColor = lcl_setColorOfObject(xComponent, m_nOverlappedControlColor); + m_xOverlappingObj = xComponent; + m_pOverlappingObj = _pOverlappedObj; + } +} + +void DlgEdFunc::unColorizeOverlappedObj() +{ + // uncolorize an old object, if there is one + if (m_xOverlappingObj.is()) + { + OReportModel& rRptModel(static_cast< OReportModel& >(m_pOverlappingObj->getSdrModelFromSdrObject())); + OXUndoEnvironment::OUndoEnvLock aLock(rRptModel.GetUndoEnv()); + + lcl_setColorOfObject(m_xOverlappingObj, m_nOldColor); + m_xOverlappingObj = nullptr; + m_pOverlappingObj = nullptr; + } +} + +bool DlgEdFunc::isOverlapping(const MouseEvent& rMEvt) +{ + SdrViewEvent aVEvt; + bool bOverlapping = m_rView.PickAnything(rMEvt, SdrMouseEventKind::BUTTONUP, aVEvt) != SdrHitKind::NONE; + if (bOverlapping && aVEvt.mpObj) + { + colorizeOverlappedObject(aVEvt.mpObj); + } + else + { + unColorizeOverlappedObj(); + } + + return bOverlapping; +} + +void DlgEdFunc::checkMovementAllowed(const MouseEvent& rMEvt) +{ + if ( m_pParent->getSectionWindow()->getViewsWindow()->IsDragObj() ) + { + if ( isRectangleHit(rMEvt) ) + { + // there is another component under use, break action + m_pParent->getSectionWindow()->getViewsWindow()->BrkAction(); + } + // object was dragged + Point aPnt( m_pParent->PixelToLogic( rMEvt.GetPosPixel() ) ); + if (m_bSelectionMode) + { + m_pParent->getSectionWindow()->getViewsWindow()->EndAction(); + } + else + { + bool bControlKeyPressed = rMEvt.IsMod1(); + // Don't allow points smaller 0 + if (bControlKeyPressed && (aPnt.Y() < 0)) + { + aPnt.setY( 0 ); + } + if (m_rView.IsDragResize()) + { + // we resize the object don't resize to above sections + if ( aPnt.Y() < 0 ) + { + aPnt.setY( 0 ); + } + } + m_pParent->getSectionWindow()->getViewsWindow()->EndDragObj( bControlKeyPressed, &m_rView, aPnt ); + } + m_pParent->getSectionWindow()->getViewsWindow()->ForceMarkedToAnotherPage(); + m_pParent->Invalidate(InvalidateFlags::Children); + } + else + m_pParent->getSectionWindow()->getViewsWindow()->EndAction(); +} + +bool DlgEdFunc::isOnlyCustomShapeMarked() const +{ + bool bReturn = true; + const SdrMarkList& rMarkList = m_rView.GetMarkedObjectList(); + for (size_t i = 0; i < rMarkList.GetMarkCount(); ++i ) + { + SdrMark* pMark = rMarkList.GetMark(i); + SdrObject* pObj = pMark->GetMarkedSdrObj(); + if (pObj->GetObjIdentifier() != SdrObjKind::CustomShape) + { + // we found an object in the marked objects, which is not a custom shape. + bReturn = false; + break; + } + } + return bReturn; +} + +bool DlgEdFunc::isRectangleHit(const MouseEvent& rMEvt) +{ + if (isOnlyCustomShapeMarked()) + { + return false; + } + + SdrViewEvent aVEvt; + const SdrHitKind eHit = m_rView.PickAnything(rMEvt, SdrMouseEventKind::MOVE, aVEvt); + bool bIsSetPoint = (eHit == SdrHitKind::UnmarkedObject); + if ( !bIsSetPoint ) + { + // no drag rect, we have to check every single select rect + const SdrDragStat& rDragStat = m_rView.GetDragStat(); + if (rDragStat.GetDragMethod() != nullptr) + { + SdrObjListIter aIter(m_pParent->getPage(),SdrIterMode::DeepNoGroups); + // loop through all marked objects and check if there new rect overlapps an old one. + for (;;) + { + SdrObject* pObjIter = aIter.Next(); + if( !pObjIter || bIsSetPoint) + break; + if ( m_rView.IsObjMarked(pObjIter) + && (dynamic_cast<OUnoObject*>(pObjIter) != nullptr || dynamic_cast<OOle2Obj*>(pObjIter) != nullptr) ) + { + tools::Rectangle aNewRect = pObjIter->GetLastBoundRect(); + tools::Long nDx = rDragStat.IsHorFixed() ? 0 : rDragStat.GetDX(); + tools::Long nDy = rDragStat.IsVerFixed() ? 0 : rDragStat.GetDY(); + if ( (nDx + aNewRect.Left()) < 0 ) + nDx = -aNewRect.Left(); + if ( (nDy + aNewRect.Top()) < 0 ) + nDy = -aNewRect.Top(); + + if ( rDragStat.GetDragMethod()->getMoveOnly() ) + aNewRect.Move(nDx,nDy); + else + ::ResizeRect(aNewRect,rDragStat.GetRef1(),rDragStat.GetXFact(),rDragStat.GetYFact()); + + + SdrObject* pObjOverlapped = isOver(aNewRect,*m_pParent->getPage(),m_rView,false,pObjIter, ISOVER_IGNORE_CUSTOMSHAPES); + bIsSetPoint = pObjOverlapped != nullptr; + if (pObjOverlapped && !m_bSelectionMode) + { + colorizeOverlappedObject(pObjOverlapped); + } + } + } + } + } + else if (aVEvt.mpObj && (aVEvt.mpObj->GetObjIdentifier() != SdrObjKind::CustomShape) && !m_bSelectionMode) + { + colorizeOverlappedObject(aVEvt.mpObj); + } + else + bIsSetPoint = false; + return bIsSetPoint; +} + +bool DlgEdFunc::setMovementPointer(const MouseEvent& rMEvt) +{ + bool bIsSetPoint = isRectangleHit(rMEvt); + if ( bIsSetPoint ) + m_pParent->SetPointer( PointerStyle::NotAllowed ); + else + { + bool bCtrlKey = rMEvt.IsMod1(); + if (bCtrlKey) + { + m_pParent->SetPointer( PointerStyle::MoveDataLink ); + bIsSetPoint = true; + } + } + return bIsSetPoint; +} + + +DlgEdFuncInsert::DlgEdFuncInsert( OReportSection* _pParent ) : + DlgEdFunc( _pParent ) +{ + m_rView.SetCreateMode(); +} + + +DlgEdFuncInsert::~DlgEdFuncInsert() +{ + m_rView.SetEditMode(); +} + + +bool DlgEdFuncInsert::MouseButtonDown( const MouseEvent& rMEvt ) +{ + if ( DlgEdFunc::MouseButtonDown(rMEvt) ) + return true; + + SdrViewEvent aVEvt; + SdrObjKind nId = m_rView.GetCurrentObjIdentifier(); + + const SdrHitKind eHit = m_rView.PickAnything(rMEvt, SdrMouseEventKind::BUTTONDOWN, aVEvt); + + if (eHit == SdrHitKind::UnmarkedObject && nId != SdrObjKind::CustomShape) + { + // there is an object under the mouse cursor, but not a customshape + m_pParent->getSectionWindow()->getViewsWindow()->BrkAction(); + return false; + } + + // if no action, create object + if (!m_pParent->getSectionWindow()->getViewsWindow()->IsAction()) + { + deactivateOle(true); + if ( m_pParent->getSectionWindow()->getViewsWindow()->HasSelection() ) + m_pParent->getSectionWindow()->getViewsWindow()->unmarkAllObjects(&m_rView); + m_rView.BegCreateObj(m_aMDPos); + m_pParent->getSectionWindow()->getViewsWindow()->createDefault(); + } + + return true; +} + + +bool DlgEdFuncInsert::MouseButtonUp( const MouseEvent& rMEvt ) +{ + if ( DlgEdFunc::MouseButtonUp( rMEvt ) ) + return true; + + const Point aPos( m_pParent->PixelToLogic( rMEvt.GetPosPixel() ) ); + const sal_uInt16 nHitLog = sal_uInt16 ( m_pParent->PixelToLogic(Size(3,0)).Width() ); + + bool bReturn = true; + // object creation active? + if ( m_rView.IsCreateObj() ) + { + if ( isOver(m_rView.GetCreateObj(),*m_pParent->getPage(),m_rView) ) + { + m_pParent->getSectionWindow()->getViewsWindow()->BrkAction(); + // BrkAction disables the create mode + m_rView.SetCreateMode(); + return true; + } + + m_rView.EndCreateObj(SdrCreateCmd::ForceEnd); + + if ( !m_rView.AreObjectsMarked() ) + { + m_rView.MarkObj(aPos, nHitLog); + } + + bReturn = m_rView.AreObjectsMarked(); + if ( bReturn ) + { + OReportController& rController = m_pParent->getSectionWindow()->getViewsWindow()->getView()->getReportView()->getController(); + const SdrMarkList& rMarkList = m_rView.GetMarkedObjectList(); + for (size_t i = 0; i < rMarkList.GetMarkCount(); ++i ) + { + SdrMark* pMark = rMarkList.GetMark(i); + OOle2Obj* pObj = dynamic_cast<OOle2Obj*>(pMark->GetMarkedSdrObj()); + if ( pObj && !pObj->IsEmpty() ) + { + pObj->initializeChart(rController.getModel()); + } + } + } + } + else + checkMovementAllowed(rMEvt); + + if ( !m_rView.AreObjectsMarked() && + std::abs(m_aMDPos.X() - aPos.X()) < nHitLog && + std::abs(m_aMDPos.Y() - aPos.Y()) < nHitLog && + !rMEvt.IsShift() && !rMEvt.IsMod2() ) + { + SdrPageView* pPV = m_rView.GetSdrPageView(); + SdrViewEvent aVEvt; + m_rView.PickAnything(rMEvt, SdrMouseEventKind::BUTTONDOWN, aVEvt); + m_rView.MarkObj(aVEvt.mpRootObj, pPV); + } + checkTwoClicks(rMEvt); + m_pParent->getSectionWindow()->getViewsWindow()->getView()->getReportView()->UpdatePropertyBrowserDelayed(m_rView); + return bReturn; +} + + +bool DlgEdFuncInsert::MouseMove( const MouseEvent& rMEvt ) +{ + if ( DlgEdFunc::MouseMove(rMEvt ) ) + return true; + Point aPos( m_pParent->PixelToLogic( rMEvt.GetPosPixel() ) ); + + if ( m_rView.IsCreateObj() ) + { + m_rView.SetOrtho(SdrObjCustomShape::doConstructOrthogonal(m_rView.getReportSection()->getSectionWindow()->getViewsWindow()->getShapeType()) ? !rMEvt.IsShift() : rMEvt.IsShift()); + m_rView.SetAngleSnapEnabled(rMEvt.IsShift()); + } + + bool bIsSetPoint = false; + if ( m_rView.IsAction() ) + { + if ( m_rView.IsDragResize() ) + { + // we resize the object don't resize to above sections + if ( aPos.Y() < 0 ) + { + aPos.setY( 0 ); + } + } + bIsSetPoint = setMovementPointer(rMEvt); + ForceScroll(aPos); + m_pParent->getSectionWindow()->getViewsWindow()->MovAction(aPos,&m_rView, false); + } + + if ( !bIsSetPoint ) + m_pParent->SetPointer( m_rView.GetPreferredPointer( aPos, m_pParent->GetOutDev()) ); + + return true; +} + + +DlgEdFuncSelect::DlgEdFuncSelect( OReportSection* _pParent ) : + DlgEdFunc( _pParent ) +{ +} + + +DlgEdFuncSelect::~DlgEdFuncSelect() +{ +} + + +bool DlgEdFuncSelect::MouseButtonDown( const MouseEvent& rMEvt ) +{ + m_bSelectionMode = false; + if ( DlgEdFunc::MouseButtonDown(rMEvt) ) + return true; + + SdrViewEvent aVEvt; + const SdrHitKind eHit = m_rView.PickAnything(rMEvt, SdrMouseEventKind::BUTTONDOWN, aVEvt); + if( eHit == SdrHitKind::UnmarkedObject ) + { + // if not multi selection, unmark all + if ( !rMEvt.IsShift() ) + m_pParent->getSectionWindow()->getViewsWindow()->unmarkAllObjects(nullptr); + + if ( m_rView.MarkObj(m_aMDPos) && rMEvt.IsLeft() ) + { + // drag object + m_pParent->getSectionWindow()->getViewsWindow()->BegDragObj(m_aMDPos, m_rView.PickHandle(m_aMDPos), &m_rView); + } + else + { + // select object + m_pParent->getSectionWindow()->getViewsWindow()->BegMarkObj(m_aMDPos,&m_rView); + } + } + else + { + if( !rMEvt.IsShift() ) + m_pParent->getSectionWindow()->getViewsWindow()->unmarkAllObjects(nullptr); + + if ( rMEvt.GetClicks() == 1 ) + { + m_bSelectionMode = true; + m_pParent->getSectionWindow()->getViewsWindow()->BegMarkObj( m_aMDPos ,&m_rView); + } + else + { + m_rView.SdrBeginTextEdit( aVEvt.mpRootObj,m_rView.GetSdrPageView(),m_pParent ); + } + } + + return true; +} + + +bool DlgEdFuncSelect::MouseButtonUp( const MouseEvent& rMEvt ) +{ + if ( DlgEdFunc::MouseButtonUp( rMEvt ) ) + return true; + + // get view from parent + const Point aPnt( m_pParent->PixelToLogic( rMEvt.GetPosPixel() ) ); + + if ( rMEvt.IsLeft() ) // left mousebutton pressed + checkMovementAllowed(rMEvt); + + m_pParent->getSectionWindow()->getViewsWindow()->EndAction(); + checkTwoClicks(rMEvt); + + m_pParent->SetPointer( m_rView.GetPreferredPointer( aPnt, m_pParent->GetOutDev() ) ); + + if ( !m_bUiActive ) + m_pParent->getSectionWindow()->getViewsWindow()->getView()->getReportView()->UpdatePropertyBrowserDelayed(m_rView); + m_bSelectionMode = false; + return true; +} + + +bool DlgEdFuncSelect::MouseMove( const MouseEvent& rMEvt ) +{ + if ( DlgEdFunc::MouseMove(rMEvt ) ) + return true; + + Point aPnt( m_pParent->PixelToLogic( rMEvt.GetPosPixel() ) ); + bool bIsSetPoint = false; + + if ( m_rView.IsAction() ) // Drag Mode + { + bIsSetPoint = setMovementPointer(rMEvt); + ForceScroll(aPnt); + if (m_rView.GetDragMethod()==nullptr) + { + // create a selection + m_pParent->getSectionWindow()->getViewsWindow()->MovAction(aPnt, &m_rView, false); + } + else + { + if ( m_rView.IsDragResize() ) + { + // we resize the object don't resize to above sections + if ( aPnt.Y() < 0 ) + { + aPnt.setY( 0 ); + } + } + // drag or resize an object + bool bControlKey = rMEvt.IsMod1(); + m_pParent->getSectionWindow()->getViewsWindow()->MovAction(aPnt, &m_rView, bControlKey); + } + } + + if ( !bIsSetPoint ) + { + m_pParent->SetPointer( m_rView.GetPreferredPointer( aPnt, m_pParent->GetOutDev() ) ); + + // restore color + unColorizeOverlappedObj(); + } + + return true; +} + + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/reportdesign/source/ui/report/propbrw.cxx b/reportdesign/source/ui/report/propbrw.cxx new file mode 100644 index 000000000..4254dcf3e --- /dev/null +++ b/reportdesign/source/ui/report/propbrw.cxx @@ -0,0 +1,528 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * 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 . + */ +#include <memory> +#include <propbrw.hxx> +#include <RptObject.hxx> +#include <ReportController.hxx> +#include <cppuhelper/component_context.hxx> +#include <strings.hrc> +#include <rptui_slotid.hrc> +#include <tools/diagnose_ex.h> +#include <com/sun/star/awt/XLayoutConstrains.hpp> +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/frame/Frame.hpp> +#include <com/sun/star/inspection/ObjectInspector.hpp> +#include <com/sun/star/inspection/DefaultHelpProvider.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/report/inspection/DefaultComponentInspectorModel.hpp> +#include <vcl/stdtext.hxx> +#include <vcl/weld.hxx> +#include <svx/svditer.hxx> + +#include <toolkit/helper/vclunohelper.hxx> +#include <comphelper/namecontainer.hxx> +#include <comphelper/types.hxx> +#include <comphelper/sequence.hxx> +#include <core_resource.hxx> +#include <SectionView.hxx> +#include <ReportSection.hxx> +#include <strings.hxx> +#include <DesignView.hxx> +#include <ViewsWindow.hxx> +#include <UITools.hxx> +#include <unotools/confignode.hxx> + +namespace rptui +{ +#define STD_WIN_SIZE_X 300 +#define STD_WIN_SIZE_Y 350 + +using namespace ::com::sun::star; +using namespace uno; +using namespace lang; +using namespace frame; +using namespace beans; +using namespace container; +using namespace ::comphelper; + + +namespace +{ + bool lcl_shouldEnableHelpSection( const Reference< XComponentContext >& _rxContext ) + { + ::utl::OConfigurationTreeRoot aConfiguration( + ::utl::OConfigurationTreeRoot::createWithComponentContext( + _rxContext, "/org.openoffice.Office.ReportDesign/PropertyBrowser/" ) ); + + bool bEnabled = false; + OSL_VERIFY( aConfiguration.getNodeValue( "DirectHelp" ) >>= bEnabled ); + return bEnabled; + } +} + + +// PropBrw + + +PropBrw::PropBrw(const Reference< XComponentContext >& _xORB, vcl::Window* pParent, ODesignView* _pDesignView) + : DockingWindow(pParent,WinBits(WB_STDMODELESS|WB_SIZEABLE|WB_3DLOOK)) + , m_xContentArea(VclPtr<VclVBox>::Create(this)) + , m_xORB(_xORB) + , m_pDesignView(_pDesignView) + , m_pView( nullptr ) + , m_bInitialStateChange(true) +{ + + Size aPropWinSize(STD_WIN_SIZE_X,STD_WIN_SIZE_Y); + SetOutputSizePixel(aPropWinSize); + + // turn off WB_CLIPCHILDREN otherwise the bg won't extend "under" + // transparent children of the widget + m_xContentArea->SetControlBackground(m_xContentArea->GetSettings().GetStyleSettings().GetWindowColor()); + m_xContentArea->SetBackground(m_xContentArea->GetControlBackground()); + m_xContentArea->SetStyle(m_xContentArea->GetStyle() & ~WB_CLIPCHILDREN); + m_xContentArea->Show(); + + try + { + // create a frame wrapper for myself + m_xMeAsFrame = Frame::create( m_xORB ); + m_xMeAsFrame->initialize(VCLUnoHelper::GetInterface(m_xContentArea)); + m_xMeAsFrame->setName("report property browser"); // change name! + } + catch (Exception&) + { + DBG_UNHANDLED_EXCEPTION("reportdesign"); + OSL_FAIL("PropBrw::PropBrw: could not create/initialize my frame!"); + m_xMeAsFrame.clear(); + } + + if (m_xMeAsFrame.is()) + { + try + { + ::cppu::ContextEntry_Init aHandlerContextInfo[] = + { + ::cppu::ContextEntry_Init( "ContextDocument", Any( m_pDesignView->getController().getModel() )), + ::cppu::ContextEntry_Init( "DialogParentWindow", Any( VCLUnoHelper::GetInterface ( this ) )), + ::cppu::ContextEntry_Init( "ActiveConnection", Any( m_pDesignView->getController().getConnection() ) ), + }; + m_xInspectorContext.set( + ::cppu::createComponentContext( aHandlerContextInfo, SAL_N_ELEMENTS( aHandlerContextInfo ), + m_xORB ) ); + // create a property browser controller + bool bEnableHelpSection = lcl_shouldEnableHelpSection( m_xORB ); + Reference< inspection::XObjectInspectorModel> xInspectorModel( bEnableHelpSection + ? report::inspection::DefaultComponentInspectorModel::createWithHelpSection( m_xInspectorContext, 3, 8 ) + : report::inspection::DefaultComponentInspectorModel::createDefault( m_xInspectorContext ) ); + + m_xBrowserController = inspection::ObjectInspector::createWithModel(m_xInspectorContext, xInspectorModel); + if ( !m_xBrowserController.is() ) + { + ShowServiceNotAvailableError(pParent ? pParent->GetFrameWeld() : nullptr, u"com.sun.star.inspection.ObjectInspector", true); + } + else + { + m_xBrowserController->attachFrame( Reference<XFrame>(m_xMeAsFrame, UNO_QUERY_THROW)); + if ( bEnableHelpSection ) + { + uno::Reference< inspection::XObjectInspector > xInspector( m_xBrowserController, uno::UNO_SET_THROW ); + uno::Reference< inspection::XObjectInspectorUI > xInspectorUI( xInspector->getInspectorUI() ); + inspection::DefaultHelpProvider::create( m_xInspectorContext, xInspectorUI ); + } + } + } + catch (Exception&) + { + DBG_UNHANDLED_EXCEPTION("reportdesign"); + OSL_FAIL("PropBrw::PropBrw: could not create/initialize the browser controller!"); + try + { + ::comphelper::disposeComponent(m_xBrowserController); + } + catch(Exception&) { } + m_xBrowserController.clear(); + } + } + + VclContainer::setLayoutAllocation(*m_xContentArea, Point(0, 0), aPropWinSize); + m_xContentArea->Show(); + + ::rptui::notifySystemWindow(pParent,this,::comphelper::mem_fun(&TaskPaneList::AddWindow)); +} + + +PropBrw::~PropBrw() +{ + disposeOnce(); +} + +void PropBrw::dispose() +{ + if (m_xBrowserController.is()) + implDetachController(); + + try + { + uno::Reference<container::XNameContainer> xName(m_xInspectorContext,uno::UNO_QUERY); + if ( xName.is() ) + { + const OUString pProps[] = { OUString( "ContextDocument" ) + , OUString( "DialogParentWindow" ) + , OUString( "ActiveConnection" )}; + for (const auto & i : pProps) + xName->removeByName(i); + } + } + catch(Exception&) + {} + + ::rptui::notifySystemWindow(this,this,::comphelper::mem_fun(&TaskPaneList::RemoveWindow)); + m_pDesignView.clear(); + m_xContentArea.disposeAndClear(); + DockingWindow::dispose(); +} + +void PropBrw::setCurrentPage(const OUString& _sLastActivePage) +{ + m_sLastActivePage = _sLastActivePage; +} + + +void PropBrw::implDetachController() +{ + m_sLastActivePage = getCurrentPage(); + implSetNewObject( ); + + if ( m_xMeAsFrame.is() ) + m_xMeAsFrame->setComponent( nullptr, nullptr ); + + if ( m_xBrowserController.is() ) + m_xBrowserController->attachFrame( nullptr ); + + m_xMeAsFrame.clear(); + m_xBrowserController.clear(); +} + +OUString PropBrw::getCurrentPage() const +{ + OUString sCurrentPage; + try + { + if ( m_xBrowserController.is() ) + { + OSL_VERIFY( m_xBrowserController->getViewData() >>= sCurrentPage ); + } + + if ( sCurrentPage.isEmpty() ) + sCurrentPage = m_sLastActivePage; + } + catch( const Exception& ) + { + TOOLS_WARN_EXCEPTION( "reportdesign", "PropBrw::getCurrentPage: caught an exception while retrieving the current page!" ); + } + return sCurrentPage; +} + +bool PropBrw::Close() +{ + m_xLastSection.clear(); + // suspend the controller (it is allowed to veto) + if ( m_xMeAsFrame.is() ) + { + try + { + Reference< XController > xController( m_xMeAsFrame->getController() ); + if ( xController.is() && !xController->suspend( true ) ) + return false; + } + catch( const Exception& ) + { + TOOLS_WARN_EXCEPTION( "reportdesign", "FmPropBrw::Close: caught an exception while asking the controller!" ); + } + } + implDetachController(); + + m_pDesignView->getController().executeUnChecked(SID_PROPERTYBROWSER_LAST_PAGE,uno::Sequence< beans::PropertyValue>()); + + return true; +} + +uno::Sequence< Reference<uno::XInterface> > PropBrw::CreateCompPropSet(const SdrMarkList& _rMarkList) +{ + const size_t nMarkCount = _rMarkList.GetMarkCount(); + ::std::vector< uno::Reference< uno::XInterface> > aSets; + aSets.reserve(nMarkCount); + + for(size_t i=0; i<nMarkCount; ++i) + { + SdrObject* pCurrent = _rMarkList.GetMark(i)->GetMarkedSdrObj(); + + ::std::unique_ptr<SdrObjListIter> pGroupIterator; + if (pCurrent->IsGroupObject()) + { + pGroupIterator.reset(new SdrObjListIter(pCurrent->GetSubList())); + pCurrent = pGroupIterator->IsMore() ? pGroupIterator->Next() : nullptr; + } + + while (pCurrent) + { + OObjectBase* pObj = dynamic_cast<OObjectBase*>(pCurrent); + if ( pObj ) + aSets.push_back(CreateComponentPair(pObj)); + + // next element + pCurrent = pGroupIterator && pGroupIterator->IsMore() ? pGroupIterator->Next() : nullptr; + } + } + return uno::Sequence< Reference<uno::XInterface> >(aSets.data(), aSets.size()); +} + +void PropBrw::implSetNewObject( const uno::Sequence< Reference<uno::XInterface> >& _aObjects ) +{ + if ( m_xBrowserController.is() ) + { + try + { + m_xBrowserController->inspect(uno::Sequence< Reference<uno::XInterface> >()); + m_xBrowserController->inspect(_aObjects); + } + catch( const Exception& ) + { + TOOLS_WARN_EXCEPTION( "reportdesign", "FmPropBrw::StateChanged: caught an exception while setting the initial page!" ); + } + } + SetText( GetHeadlineName(_aObjects) ); +} + + +OUString PropBrw::GetHeadlineName( const uno::Sequence< Reference<uno::XInterface> >& _aObjects ) +{ + OUString aName; + if ( !_aObjects.hasElements() ) + { + aName = RptResId(RID_STR_BRWTITLE_NO_PROPERTIES); + } + else if ( _aObjects.getLength() == 1 ) // single selection + { + aName = RptResId(RID_STR_BRWTITLE_PROPERTIES); + + uno::Reference< container::XNameContainer > xNameCont(_aObjects[0],uno::UNO_QUERY); + Reference< lang::XServiceInfo > xServiceInfo( xNameCont->getByName("ReportComponent"), UNO_QUERY ); + if ( xServiceInfo.is() ) + { + TranslateId pResId; + if ( xServiceInfo->supportsService( SERVICE_FIXEDTEXT ) ) + { + pResId = RID_STR_PROPTITLE_FIXEDTEXT; + } + else if ( xServiceInfo->supportsService( SERVICE_IMAGECONTROL ) ) + { + pResId = RID_STR_PROPTITLE_IMAGECONTROL; + } + else if ( xServiceInfo->supportsService( SERVICE_FORMATTEDFIELD ) ) + { + pResId = RID_STR_PROPTITLE_FORMATTED; + } + else if ( xServiceInfo->supportsService( SERVICE_SHAPE ) ) + { + pResId = RID_STR_PROPTITLE_SHAPE; + } + else if ( xServiceInfo->supportsService( SERVICE_REPORTDEFINITION ) ) + { + pResId = RID_STR_PROPTITLE_REPORT; + } + else if ( xServiceInfo->supportsService( SERVICE_SECTION ) ) + { + pResId = RID_STR_PROPTITLE_SECTION; + } + else if ( xServiceInfo->supportsService( SERVICE_FUNCTION ) ) + { + pResId = RID_STR_PROPTITLE_FUNCTION; + } + else if ( xServiceInfo->supportsService( SERVICE_GROUP ) ) + { + pResId = RID_STR_PROPTITLE_GROUP; + } + else if ( xServiceInfo->supportsService( SERVICE_FIXEDLINE ) ) + { + pResId = RID_STR_PROPTITLE_FIXEDLINE; + } + else + { + OSL_FAIL("Unknown service name!"); + aName += RID_STR_CLASS_FORMATTEDFIELD; + return aName; + } + + aName += RptResId(pResId); + } + } + else // multiselection + { + aName = RptResId(RID_STR_BRWTITLE_PROPERTIES) + + RptResId(RID_STR_BRWTITLE_MULTISELECT); + } + + return aName; +} + +uno::Reference< uno::XInterface> PropBrw::CreateComponentPair(OObjectBase* _pObj) +{ + _pObj->initializeOle(); + return CreateComponentPair(_pObj->getAwtComponent(),_pObj->getReportComponent()); +} + +uno::Reference< uno::XInterface> PropBrw::CreateComponentPair(const uno::Reference< uno::XInterface>& _xFormComponent + ,const uno::Reference< uno::XInterface>& _xReportComponent) +{ + uno::Reference< container::XNameContainer > xNameCont = ::comphelper::NameContainer_createInstance(cppu::UnoType<XInterface>::get()); + xNameCont->insertByName("FormComponent",uno::Any(_xFormComponent)); + xNameCont->insertByName("ReportComponent",uno::Any(_xReportComponent)); + xNameCont->insertByName("RowSet",uno::Any(uno::Reference< uno::XInterface>(m_pDesignView->getController().getRowSet()))); + + return xNameCont; +} + +::Size PropBrw::getMinimumSize() const +{ + ::Size aSize; + Reference< awt::XLayoutConstrains > xLayoutConstrains( m_xBrowserController, UNO_QUERY ); + if( xLayoutConstrains.is() ) + { + awt::Size aMinSize = xLayoutConstrains->getMinimumSize(); + aMinSize.Height += 4; + aMinSize.Width += 4; + aSize.setHeight( aMinSize.Height ); + aSize.setWidth( aMinSize.Width ); + } + return aSize; +} + +void PropBrw::Update( OSectionView* pNewView ) +{ + try + { + if ( m_pView ) + { + EndListening( *(m_pView->GetModel()) ); + m_pView = nullptr; + } + + // set focus on initialization + if ( m_bInitialStateChange ) + { + // if we're just newly created, we want to have the focus + PostUserEvent( LINK( this, PropBrw, OnAsyncGetFocus ), nullptr, true ); + m_bInitialStateChange = false; + // and additionally, we want to show the page which was active during + // our previous incarnation + if ( !m_sLastActivePage.isEmpty() && m_xBrowserController.is() ) + { + try + { + m_xBrowserController->restoreViewData( Any( m_sLastActivePage ) ); + } + catch( const Exception& ) + { + TOOLS_WARN_EXCEPTION( "reportdesign", "FmPropBrw::StateChanged: caught an exception while setting the initial page!" ); + } + } + } + + if ( !pNewView ) + return; + else + m_pView = pNewView; + + uno::Sequence< Reference<uno::XInterface> > aMarkedObjects; + OViewsWindow* pViews = m_pView->getReportSection()->getSectionWindow()->getViewsWindow(); + const sal_uInt16 nSectionCount = pViews->getSectionCount(); + for (sal_uInt16 i = 0; i < nSectionCount; ++i) + { + OSectionWindow* pSectionWindow = pViews->getSectionWindow(i); + if ( pSectionWindow ) + { + const SdrMarkList& rMarkList = pSectionWindow->getReportSection().getSectionView().GetMarkedObjectList(); + aMarkedObjects = ::comphelper::concatSequences(aMarkedObjects,CreateCompPropSet( rMarkList )); + } + } + + if ( aMarkedObjects.hasElements() ) // multiple selection + { + m_xLastSection.clear(); + implSetNewObject( aMarkedObjects ); + } + else if ( m_xLastSection != m_pView->getReportSection()->getSection() ) + { + uno::Reference< uno::XInterface> xTemp(m_pView->getReportSection()->getSection()); + m_xLastSection = xTemp; + uno::Reference< container::XNameContainer > xNameCont = ::comphelper::NameContainer_createInstance(cppu::UnoType<XInterface>::get() ); + xNameCont->insertByName("ReportComponent",uno::Any(xTemp)); + xTemp = xNameCont; + + implSetNewObject( uno::Sequence< uno::Reference< uno::XInterface> >(&xTemp,1) ); + } + + StartListening( *(m_pView->GetModel()) ); + } + catch ( Exception& ) + { + TOOLS_WARN_EXCEPTION( "reportdesign", "PropBrw::Update" ); + } +} + +void PropBrw::Update( const uno::Reference< uno::XInterface>& _xReportComponent) +{ + if ( m_xLastSection == _xReportComponent ) + return; + + m_xLastSection = _xReportComponent; + try + { + if ( m_pView ) + { + EndListening( *(m_pView->GetModel()) ); + m_pView = nullptr; + } + + uno::Reference< uno::XInterface> xTemp(CreateComponentPair(_xReportComponent,_xReportComponent)); + implSetNewObject( uno::Sequence< uno::Reference< uno::XInterface> >(&xTemp,1) ); + } + catch ( Exception& ) + { + TOOLS_WARN_EXCEPTION( "reportdesign", "PropBrw::Update: Exception occurred!" ); + } +} + +IMPL_LINK_NOARG( PropBrw, OnAsyncGetFocus, void*, void ) +{ + m_xContentArea->GrabFocus(); +} + +void PropBrw::LoseFocus() +{ + DockingWindow::LoseFocus(); + if (m_pDesignView) + m_pDesignView->getController().InvalidateAll(); +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |