diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 16:51:28 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 16:51:28 +0000 |
commit | 940b4d1848e8c70ab7642901a68594e8016caffc (patch) | |
tree | eb72f344ee6c3d9b80a7ecc079ea79e9fba8676d /reportdesign/source/ui | |
parent | Initial commit. (diff) | |
download | libreoffice-upstream.tar.xz libreoffice-upstream.zip |
Adding upstream version 1:7.0.4.upstream/1%7.0.4upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
80 files changed, 26446 insertions, 0 deletions
diff --git a/reportdesign/source/ui/dlg/AddField.cxx b/reportdesign/source/ui/dlg/AddField.cxx new file mode 100644 index 000000000..790c0d700 --- /dev/null +++ b/reportdesign/source/ui/dlg/AddField.cxx @@ -0,0 +1,352 @@ +/* -*- 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 <AddField.hxx> +#include <UITools.hxx> +#include <com/sun/star/sdb/CommandType.hpp> +#include <com/sun/star/sdb/XDocumentDataSource.hpp> + +#include <vcl/svapp.hxx> + +#include <tools/diagnose_ex.h> + +#include <connectivity/dbtools.hxx> +#include <core_resource.hxx> +#include <helpids.h> +#include <strings.hrc> +#include <strings.hxx> + +#include <comphelper/sequence.hxx> + +namespace rptui +{ + +using namespace ::com::sun::star; +using namespace sdbc; +using namespace sdb; +using namespace uno; +using namespace datatransfer; +using namespace beans; +using namespace lang; +using namespace container; +using namespace ::svx; + +IMPL_LINK(OAddFieldWindow, DragBeginHdl, bool&, rUnsetDragIcon, bool) +{ + rUnsetDragIcon = false; + if (m_xListBox->get_selected_index() == -1) + { + // no drag without a field + return true; + } + + m_xHelper->setDescriptors(getSelectedFieldDescriptors()); + return false; +} + +OAddFieldWindow::OAddFieldWindow(weld::Window* pParent, const uno::Reference< beans::XPropertySet >& xRowSet) + : GenericDialogController(pParent, "modules/dbreport/ui/floatingfield.ui", "FloatingField") + , ::comphelper::OPropertyChangeListener(m_aMutex) + , ::comphelper::OContainerListener(m_aMutex) + , m_xRowSet(xRowSet) + , m_xActions(m_xBuilder->weld_toolbar("toolbox")) + , m_xListBox(m_xBuilder->weld_tree_view("treeview")) + , m_xHelpText(m_xBuilder->weld_label("helptext")) + , m_nCommandType(0) + , m_bEscapeProcessing(false) +{ + m_xListBox->set_help_id(HID_RPT_FIELD_SEL); + m_xListBox->set_selection_mode(SelectionMode::Multiple); + m_xHelper.set(new svx::OMultiColumnTransferable); + rtl::Reference<TransferDataContainer> xHelper(m_xHelper.get()); + m_xListBox->enable_drag_source(xHelper, DND_ACTION_COPYMOVE | DND_ACTION_LINK); + m_xListBox->connect_drag_begin(LINK(this, OAddFieldWindow, DragBeginHdl)); + + m_xDialog->connect_toplevel_focus_changed(LINK(this, OAddFieldWindow, FocusChangeHdl)); + + m_xDialog->set_help_id(HID_RPT_FIELD_SEL_WIN); + + m_xActions->connect_clicked(LINK(this, OAddFieldWindow, OnSortAction)); + m_xActions->set_item_active("up", true); + m_xListBox->make_sorted(); + m_xActions->set_item_sensitive("insert", false); + + m_xListBox->connect_row_activated(LINK( this, OAddFieldWindow, OnDoubleClickHdl ) ); + m_xListBox->connect_changed(LINK( this, OAddFieldWindow, OnSelectHdl ) ); + m_xListBox->set_size_request(m_xListBox->get_approximate_digit_width() * 45, m_xListBox->get_height_rows(8)); + + if (!m_xRowSet.is()) + return; + + try + { + // be notified when the settings of report definition change + m_pChangeListener = new ::comphelper::OPropertyChangeMultiplexer( this, m_xRowSet ); + m_pChangeListener->addProperty( PROPERTY_COMMAND ); + m_pChangeListener->addProperty( PROPERTY_COMMANDTYPE ); + m_pChangeListener->addProperty( PROPERTY_ESCAPEPROCESSING ); + m_pChangeListener->addProperty( PROPERTY_FILTER ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION("reportdesign"); + } +} + +OAddFieldWindow::~OAddFieldWindow() +{ + m_aListBoxData.clear(); + if (m_pChangeListener.is()) + m_pChangeListener->dispose(); + if ( m_pContainerListener.is() ) + m_pContainerListener->dispose(); +} + +IMPL_LINK_NOARG(OAddFieldWindow, FocusChangeHdl, weld::Widget&, void) +{ + if (m_xDialog->has_toplevel_focus()) + m_xListBox->grab_focus(); +} + +uno::Sequence< beans::PropertyValue > OAddFieldWindow::getSelectedFieldDescriptors() +{ + std::vector<beans::PropertyValue> aArgs; + + m_xListBox->selected_foreach([this, &aArgs](weld::TreeIter& rEntry){ + // build a descriptor for the currently selected field + svx::ODataAccessDescriptor aDescriptor; + fillDescriptor(rEntry, aDescriptor); + aArgs.push_back(beans::PropertyValue()); + aArgs.back().Value <<= aDescriptor.createPropertyValueSequence(); + + return false; + }); + + return comphelper::containerToSequence(aArgs); +} + +void OAddFieldWindow::_propertyChanged( const beans::PropertyChangeEvent& _evt ) +{ + OSL_ENSURE( _evt.Source == m_xRowSet, "OAddFieldWindow::_propertyChanged: where did this come from?" ); + Update(); +} + +void OAddFieldWindow::addToList(const uno::Sequence< OUString >& rEntries) +{ + for (const OUString& rEntry : rEntries) + { + m_aListBoxData.emplace_back(new ColumnInfo(rEntry)); + OUString sId(OUString::number(reinterpret_cast<sal_Int64>(m_aListBoxData.back().get()))); + m_xListBox->append(sId, rEntry); + } +} + +void OAddFieldWindow::addToList(const uno::Reference< container::XNameAccess>& i_xColumns) +{ + const uno::Sequence< OUString > aEntries = i_xColumns->getElementNames(); + for ( const OUString& rEntry : aEntries ) + { + uno::Reference< beans::XPropertySet> xColumn(i_xColumns->getByName(rEntry),UNO_QUERY_THROW); + OUString sLabel; + if ( xColumn->getPropertySetInfo()->hasPropertyByName(PROPERTY_LABEL) ) + xColumn->getPropertyValue(PROPERTY_LABEL) >>= sLabel; + m_aListBoxData.emplace_back(new ColumnInfo(rEntry, sLabel)); + OUString sId(OUString::number(reinterpret_cast<sal_Int64>(m_aListBoxData.back().get()))); + if ( !sLabel.isEmpty() ) + m_xListBox->append(sId, sLabel); + else + m_xListBox->append(sId, rEntry); + } +} + +void OAddFieldWindow::Update() +{ + SolarMutexGuard aSolarGuard; + + if ( m_pContainerListener.is() ) + m_pContainerListener->dispose(); + m_pContainerListener = nullptr; + m_xColumns.clear(); + + try + { + // ListBox loeschen + m_xListBox->clear(); + m_aListBoxData.clear(); + const OString aIds[] = { "up", "down" }; + for (size_t j = 0; j< SAL_N_ELEMENTS(aIds); ++j) + m_xActions->set_item_sensitive(aIds[j], false); + + OUString aTitle(RptResId(RID_STR_FIELDSELECTION)); + m_xDialog->set_title(aTitle); + if ( m_xRowSet.is() ) + { + OUString sCommand( m_aCommandName ); + sal_Int32 nCommandType( m_nCommandType ); + bool bEscapeProcessing( m_bEscapeProcessing ); + OUString sFilter( m_sFilter ); + + OSL_VERIFY( m_xRowSet->getPropertyValue( PROPERTY_COMMAND ) >>= sCommand ); + OSL_VERIFY( m_xRowSet->getPropertyValue( PROPERTY_COMMANDTYPE ) >>= nCommandType ); + OSL_VERIFY( m_xRowSet->getPropertyValue( PROPERTY_ESCAPEPROCESSING ) >>= bEscapeProcessing ); + OSL_VERIFY( m_xRowSet->getPropertyValue( PROPERTY_FILTER ) >>= sFilter ); + + m_aCommandName = sCommand; + m_nCommandType = nCommandType; + m_bEscapeProcessing = bEscapeProcessing; + m_sFilter = sFilter; + + // add the columns to the list + uno::Reference< sdbc::XConnection> xCon = getConnection(); + if ( xCon.is() && !m_aCommandName.isEmpty() ) + m_xColumns = dbtools::getFieldsByCommandDescriptor( xCon, GetCommandType(), GetCommand(), m_xHoldAlive ); + if ( m_xColumns.is() ) + { + addToList(m_xColumns); + uno::Reference< container::XContainer> xContainer(m_xColumns,uno::UNO_QUERY); + if ( xContainer.is() ) + m_pContainerListener = new ::comphelper::OContainerListenerAdapter(this,xContainer); + } + + // add the parameter columns to the list + uno::Reference< css::sdbc::XRowSet > xRowSet(m_xRowSet,uno::UNO_QUERY); + Sequence< OUString > aParamNames( getParameterNames( xRowSet ) ); + addToList(aParamNames); + + // set title + aTitle += " " + m_aCommandName; + m_xDialog->set_title(aTitle); + if ( !m_aCommandName.isEmpty() ) + { + for (size_t i = 0; i < SAL_N_ELEMENTS(aIds); ++i) + m_xActions->set_item_sensitive(aIds[i], true); + } + OnSelectHdl(*m_xListBox); + } + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION("reportdesign"); + } +} + +uno::Reference< sdbc::XConnection> OAddFieldWindow::getConnection() const +{ + return uno::Reference< sdbc::XConnection>(m_xRowSet->getPropertyValue( PROPERTY_ACTIVECONNECTION ),uno::UNO_QUERY); +} + +void OAddFieldWindow::fillDescriptor(const weld::TreeIter& rSelected, svx::ODataAccessDescriptor& rDescriptor) +{ + if (!m_xColumns.is()) + return; + + uno::Reference<container::XChild> xChild(getConnection(),uno::UNO_QUERY); + if ( xChild.is( ) ) + { + uno::Reference<sdb::XDocumentDataSource> xDocument( xChild->getParent(), uno::UNO_QUERY ); + if ( xDocument.is() ) + { + uno::Reference<frame::XModel> xModel(xDocument->getDatabaseDocument(),uno::UNO_QUERY); + if ( xModel.is() ) + rDescriptor[ DataAccessDescriptorProperty::DatabaseLocation ] <<= xModel->getURL(); + } + } + + rDescriptor[ svx::DataAccessDescriptorProperty::Command ] <<= GetCommand(); + rDescriptor[ svx::DataAccessDescriptorProperty::CommandType ] <<= GetCommandType(); + rDescriptor[ svx::DataAccessDescriptorProperty::EscapeProcessing ] <<= m_bEscapeProcessing; + rDescriptor[ svx::DataAccessDescriptorProperty::Connection ] <<= getConnection(); + + ColumnInfo* pInfo = reinterpret_cast<ColumnInfo*>(m_xListBox->get_id(rSelected).toInt64()); + rDescriptor[ svx::DataAccessDescriptorProperty::ColumnName ] <<= pInfo->sColumnName; + if ( m_xColumns->hasByName( pInfo->sColumnName ) ) + rDescriptor[ svx::DataAccessDescriptorProperty::ColumnObject ] = m_xColumns->getByName(pInfo->sColumnName); +} + +void OAddFieldWindow::_elementInserted( const container::ContainerEvent& _rEvent ) +{ + OUString sName; + if ( !((_rEvent.Accessor >>= sName) && m_xColumns->hasByName(sName)) ) + return; + + uno::Reference< beans::XPropertySet> xColumn(m_xColumns->getByName(sName),UNO_QUERY_THROW); + OUString sLabel; + if ( xColumn->getPropertySetInfo()->hasPropertyByName(PROPERTY_LABEL) ) + xColumn->getPropertyValue(PROPERTY_LABEL) >>= sLabel; + m_aListBoxData.emplace_back(new ColumnInfo(sName, sLabel)); + OUString sId(OUString::number(reinterpret_cast<sal_Int64>(m_aListBoxData.back().get()))); + if (!sLabel.isEmpty()) + m_xListBox->append(sId, sLabel); + else + m_xListBox->append(sId, sName); +} + +void OAddFieldWindow::_elementRemoved( const container::ContainerEvent& /*_rEvent*/ ) +{ + m_xListBox->clear(); + m_aListBoxData.clear(); + if ( m_xColumns.is() ) + addToList(m_xColumns); +} + +void OAddFieldWindow::_elementReplaced( const container::ContainerEvent& /*_rEvent*/ ) +{ +} + +IMPL_LINK_NOARG( OAddFieldWindow, OnSelectHdl, weld::TreeView&, void ) +{ + m_xActions->set_item_sensitive("insert", m_xListBox->get_selected_index() != -1); +} + +IMPL_LINK_NOARG( OAddFieldWindow, OnDoubleClickHdl, weld::TreeView&, bool ) +{ + m_aCreateLink.Call(*this); + return true; +} + +IMPL_LINK(OAddFieldWindow, OnSortAction, const OString&, rCurItem, void) +{ + if (rCurItem == "insert") + { + OnDoubleClickHdl(*m_xListBox); + return; + } + + const OString aIds[] = { "up", "down" }; + + if (rCurItem == "delete") + { + for (size_t j = 0; j< SAL_N_ELEMENTS(aIds); ++j) + m_xActions->set_item_active(aIds[j], false); + + m_xListBox->make_unsorted(); + Update(); + return; + } + + for (size_t j = 0; j< SAL_N_ELEMENTS(aIds); ++j) + m_xActions->set_item_active(aIds[j], rCurItem == aIds[j]); + + m_xListBox->make_sorted(); + if (m_xActions->get_item_active("down")) + m_xListBox->set_sort_order(false); +} + +} // namespace rptui + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/reportdesign/source/ui/dlg/CondFormat.cxx b/reportdesign/source/ui/dlg/CondFormat.cxx new file mode 100644 index 000000000..f869ca0f5 --- /dev/null +++ b/reportdesign/source/ui/dlg/CondFormat.cxx @@ -0,0 +1,453 @@ +/* -*- 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 <CondFormat.hxx> + +#include <strings.hxx> +#include <strings.hrc> +#include <core_resource.hxx> +#include <ReportController.hxx> +#include "Condition.hxx" + +#include <com/sun/star/lang/IllegalArgumentException.hpp> +#include <o3tl/safeint.hxx> +#include <toolkit/helper/vclunohelper.hxx> + +#include <tools/diagnose_ex.h> + +#include <comphelper/property.hxx> + +#include <algorithm> +#include <UndoActions.hxx> + + +namespace rptui +{ + + + using ::com::sun::star::uno::Reference; + using ::com::sun::star::uno::UNO_QUERY_THROW; + using ::com::sun::star::uno::UNO_QUERY; + using ::com::sun::star::uno::Exception; + using ::com::sun::star::lang::IllegalArgumentException; + using ::com::sun::star::uno::Sequence; + using ::com::sun::star::beans::PropertyValue; + using ::com::sun::star::uno::Any; + + using namespace ::com::sun::star::report; + + void ConditionalFormattingDialog::impl_setPrefHeight(bool bFirst) + { + if (!m_bConstructed && !bFirst) + return; + + //allow dialog to resize itself + size_t nCount = impl_getConditionCount(); + if (!nCount) + return; + + auto nHeight = m_aConditions[0]->get_preferred_size().Height(); + size_t nVisibleConditions = ::std::min(nCount, MAX_CONDITIONS); + nHeight *= nVisibleConditions; + nHeight += 2; + if (nHeight != m_xScrollWindow->get_size_request().Height()) + { + m_xScrollWindow->set_size_request(-1, nHeight); + if (!bFirst) + m_xDialog->resize_to_request(); + } + } + + ConditionalFormattingDialog::ConditionalFormattingDialog( + weld::Window* _pParent, const Reference< XReportControlModel >& _rxFormatConditions, ::rptui::OReportController& _rController) + : GenericDialogController(_pParent, "modules/dbreport/ui/condformatdialog.ui", "CondFormat") + , m_rController(_rController) + , m_xFormatConditions(_rxFormatConditions) + , m_bConstructed(false) + , m_xScrollWindow(m_xBuilder->weld_scrolled_window("scrolledwindow")) + , m_xConditionPlayground(m_xBuilder->weld_box("condPlaygroundDrawingarea")) + { + OSL_ENSURE( m_xFormatConditions.is(), "ConditionalFormattingDialog::ConditionalFormattingDialog: ReportControlModel is NULL -> Prepare for GPF!" ); + + m_xCopy.set( m_xFormatConditions->createClone(), UNO_QUERY_THROW ); + + m_xScrollWindow->connect_vadjustment_changed(LINK(this, ConditionalFormattingDialog, OnScroll)); + + impl_initializeConditions(); + + impl_setPrefHeight(true); + + m_bConstructed = true; + } + + ConditionalFormattingDialog::~ConditionalFormattingDialog() + { + } + + void ConditionalFormattingDialog::impl_updateConditionIndicies() + { + sal_Int32 nIndex = 0; + for (const auto& rxCondition : m_aConditions) + { + rxCondition->setConditionIndex( nIndex, impl_getConditionCount() ); + m_xConditionPlayground->reorder_child(rxCondition->get_widget(), nIndex); + ++nIndex; + } + } + + void ConditionalFormattingDialog::impl_conditionCountChanged() + { + if ( m_aConditions.empty() ) + impl_addCondition_nothrow( 0 ); + + impl_setPrefHeight(false); + + impl_updateConditionIndicies(); + impl_layoutAll(); + } + + void ConditionalFormattingDialog::addCondition( size_t _nAddAfterIndex ) + { + OSL_PRECOND( _nAddAfterIndex < impl_getConditionCount(), "ConditionalFormattingDialog::addCondition: illegal condition index!" ); + impl_addCondition_nothrow( _nAddAfterIndex + 1 ); + } + + + void ConditionalFormattingDialog::deleteCondition( size_t _nCondIndex ) + { + impl_deleteCondition_nothrow( _nCondIndex ); + } + + + void ConditionalFormattingDialog::impl_addCondition_nothrow( size_t _nNewCondIndex ) + { + try + { + if ( _nNewCondIndex > o3tl::make_unsigned(m_xCopy->getCount()) ) + throw IllegalArgumentException(); + + Reference< XFormatCondition > xCond = m_xCopy->createFormatCondition(); + ::comphelper::copyProperties(m_xCopy.get(),xCond.get()); + m_xCopy->insertByIndex( _nNewCondIndex, makeAny( xCond ) ); + auto xCon = std::make_unique<Condition>(m_xConditionPlayground.get(), m_xDialog.get(), *this, m_rController); + xCon->setCondition(xCond); + m_xConditionPlayground->reorder_child(xCon->get_widget(), _nNewCondIndex); + m_aConditions.insert(m_aConditions.begin() + _nNewCondIndex, std::move(xCon)); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION("reportdesign"); + } + + impl_conditionCountChanged(); + + impl_ensureConditionVisible( _nNewCondIndex ); + } + + void ConditionalFormattingDialog::impl_focusCondition( size_t _nCondIndex ) + { + OSL_PRECOND( _nCondIndex < impl_getConditionCount(), + "ConditionalFormattingDialog::impl_focusCondition: illegal index!" ); + + impl_ensureConditionVisible( _nCondIndex ); + m_aConditions[ _nCondIndex ]->grab_focus(); + } + + void ConditionalFormattingDialog::impl_deleteCondition_nothrow( size_t _nCondIndex ) + { + OSL_PRECOND( _nCondIndex < impl_getConditionCount(), + "ConditionalFormattingDialog::impl_deleteCondition_nothrow: illegal index!" ); + + bool bLastCondition = ( impl_getConditionCount() == 1 ); + + bool bSetNewFocus = false; + size_t nNewFocusIndex( _nCondIndex ); + try + { + if ( !bLastCondition ) + m_xCopy->removeByIndex( _nCondIndex ); + + Conditions::iterator pos = m_aConditions.begin() + _nCondIndex; + if ( bLastCondition ) + { + Reference< XFormatCondition > xFormatCondition( m_xCopy->getByIndex( 0 ), UNO_QUERY_THROW ); + xFormatCondition->setFormula( OUString() ); + (*pos)->setCondition( xFormatCondition ); + } + else + { + bSetNewFocus = (*pos)->has_focus(); + + auto xMovedCondition = std::move(*pos); + m_aConditions.erase(pos); + m_xConditionPlayground->move(xMovedCondition->get_widget(), nullptr); + } + + if ( bSetNewFocus ) + { + if ( nNewFocusIndex >= impl_getConditionCount() ) + nNewFocusIndex = impl_getConditionCount() - 1; + } + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION("reportdesign"); + } + + impl_conditionCountChanged(); + if ( bSetNewFocus ) + impl_focusCondition( nNewFocusIndex ); + } + + + void ConditionalFormattingDialog::impl_moveCondition_nothrow( size_t _nCondIndex, bool _bMoveUp ) + { + size_t nOldConditionIndex( _nCondIndex ); + size_t nNewConditionIndex( _bMoveUp ? _nCondIndex - 1 : _nCondIndex + 1 ); + + // do this in two steps, so we don't become inconsistent if any of the UNO actions fails + Any aMovedCondition; + std::unique_ptr<Condition> xMovedCondition; + try + { + aMovedCondition = m_xCopy->getByIndex( static_cast<sal_Int32>(nOldConditionIndex) ); + m_xCopy->removeByIndex( static_cast<sal_Int32>(nOldConditionIndex) ); + + Conditions::iterator aRemovePos( m_aConditions.begin() + nOldConditionIndex ); + xMovedCondition = std::move(*aRemovePos); + m_aConditions.erase( aRemovePos ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION("reportdesign"); + return; + } + + try + { + m_xCopy->insertByIndex( static_cast<sal_Int32>(nNewConditionIndex), aMovedCondition ); + m_aConditions.insert(m_aConditions.begin() + nNewConditionIndex, std::move(xMovedCondition)); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION("reportdesign"); + } + + // at least the two swapped conditions need to know their new index + impl_updateConditionIndicies(); + + // ensure the moved condition is visible + impl_ensureConditionVisible( nNewConditionIndex ); + } + + IMPL_LINK_NOARG(ConditionalFormattingDialog, OnScroll, weld::ScrolledWindow&, void) + { + size_t nFirstCondIndex( impl_getFirstVisibleConditionIndex() ); + size_t nFocusCondIndex = impl_getFocusedConditionIndex( nFirstCondIndex ); + + if ( nFocusCondIndex < nFirstCondIndex ) + impl_focusCondition( nFirstCondIndex ); + else if ( nFocusCondIndex >= nFirstCondIndex + MAX_CONDITIONS ) + impl_focusCondition( nFirstCondIndex + MAX_CONDITIONS - 1 ); + } + + void ConditionalFormattingDialog::impl_layoutAll() + { + // scrollbar visibility + if ( m_aConditions.size() <= MAX_CONDITIONS ) + // normalize the position, so it can, in all situations, be used as top index + m_xScrollWindow->vadjustment_set_value(0); + } + + void ConditionalFormattingDialog::impl_initializeConditions() + { + try + { + sal_Int32 nCount = m_xCopy->getCount(); + for ( sal_Int32 i = 0; i < nCount ; ++i ) + { + auto xCon = std::make_unique<Condition>(m_xConditionPlayground.get(), m_xDialog.get(), *this, m_rController); + Reference< XFormatCondition > xCond( m_xCopy->getByIndex(i), UNO_QUERY ); + m_xConditionPlayground->reorder_child(xCon->get_widget(), i); + xCon->setCondition(xCond); + xCon->updateToolbar(xCond.get()); + m_aConditions.push_back(std::move(xCon)); + } + } + catch(Exception&) + { + OSL_FAIL("Can not access format condition!"); + } + + impl_conditionCountChanged(); + } + + void ConditionalFormattingDialog::applyCommand(size_t _nCondIndex, sal_uInt16 _nCommandId, const ::Color& rColor) + { + OSL_PRECOND( _nCommandId, "ConditionalFormattingDialog::applyCommand: illegal command id!" ); + try + { + Reference< XReportControlFormat > xReportControlFormat( m_xCopy->getByIndex( _nCondIndex ), UNO_QUERY_THROW ); + + Sequence< PropertyValue > aArgs(3); + + aArgs[0].Name = REPORTCONTROLFORMAT; + aArgs[0].Value <<= xReportControlFormat; + + aArgs[1].Name = CURRENT_WINDOW; + aArgs[1].Value <<= m_xDialog->GetXWindow(); + + aArgs[2].Name = PROPERTY_FONTCOLOR; + aArgs[2].Value <<= rColor; + + // we use this way to create undo actions + m_rController.executeUnChecked(_nCommandId,aArgs); + m_aConditions[ _nCondIndex ]->updateToolbar(xReportControlFormat); + } + catch( Exception& ) + { + DBG_UNHANDLED_EXCEPTION("reportdesign"); + } + } + + + void ConditionalFormattingDialog::moveConditionUp( size_t _nCondIndex ) + { + OSL_PRECOND( _nCondIndex > 0, "ConditionalFormattingDialog::moveConditionUp: cannot move up the first condition!" ); + if ( _nCondIndex > 0 ) + impl_moveCondition_nothrow( _nCondIndex, true ); + } + + + void ConditionalFormattingDialog::moveConditionDown( size_t _nCondIndex ) + { + OSL_PRECOND( _nCondIndex < impl_getConditionCount(), "ConditionalFormattingDialog::moveConditionDown: cannot move down the last condition!" ); + if ( _nCondIndex < impl_getConditionCount() ) + impl_moveCondition_nothrow( _nCondIndex, false ); + } + + OUString ConditionalFormattingDialog::getDataField() const + { + OUString sDataField; + try + { + sDataField = m_xFormatConditions->getDataField(); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION("reportdesign"); + } + return sDataField; + } + + short ConditionalFormattingDialog::run() + { + short nRet = GenericDialogController::run(); + if (nRet == RET_OK) + { + const OUString sUndoAction( RptResId( RID_STR_UNDO_CONDITIONAL_FORMATTING ) ); + const UndoContext aUndoContext( m_rController.getUndoManager(), sUndoAction ); + try + { + sal_Int32 j(0), i(0); + for ( Conditions::const_iterator cond = m_aConditions.begin(); + cond != m_aConditions.end(); + ++cond, ++i + ) + { + Reference< XFormatCondition > xCond( m_xCopy->getByIndex(i), UNO_QUERY_THROW ); + (*cond)->fillFormatCondition( xCond ); + + if ( (*cond)->isEmpty() ) + continue; + + Reference< XFormatCondition > xNewCond; + bool bAppend = j >= m_xFormatConditions->getCount(); + if ( bAppend ) + { + xNewCond = m_xFormatConditions->createFormatCondition(); + m_xFormatConditions->insertByIndex( i, makeAny( xNewCond ) ); + } + else + xNewCond.set( m_xFormatConditions->getByIndex(j), UNO_QUERY ); + ++j; + + ::comphelper::copyProperties(xCond.get(),xNewCond.get()); + } + + for ( sal_Int32 k = m_xFormatConditions->getCount()-1; k >= j; --k ) + m_xFormatConditions->removeByIndex(k); + + ::comphelper::copyProperties( m_xCopy.get(), m_xFormatConditions.get() ); + } + catch ( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION("reportdesign"); + nRet = RET_NO; + } + } + return nRet; + } + + size_t ConditionalFormattingDialog::impl_getFirstVisibleConditionIndex() const + { + auto nHeight = m_aConditions[0]->get_preferred_size().Height(); + return m_xScrollWindow->vadjustment_get_value() / nHeight; + } + + size_t ConditionalFormattingDialog::impl_getLastVisibleConditionIndex() const + { + return ::std::min( impl_getFirstVisibleConditionIndex() + MAX_CONDITIONS, impl_getConditionCount() ) - 1; + } + + size_t ConditionalFormattingDialog::impl_getFocusedConditionIndex( sal_Int32 _nFallBackIfNone ) const + { + auto cond = std::find_if(m_aConditions.begin(), m_aConditions.end(), + [](const std::unique_ptr<Condition>& rxCondition) { return rxCondition->has_focus(); }); + if (cond != m_aConditions.end()) + return static_cast<size_t>(std::distance(m_aConditions.begin(), cond)); + return _nFallBackIfNone; + } + + void ConditionalFormattingDialog::impl_scrollTo( size_t nTopCondIndex ) + { + OSL_PRECOND( nTopCondIndex + MAX_CONDITIONS <= impl_getConditionCount(), + "ConditionalFormattingDialog::impl_scrollTo: illegal index!" ); + + auto nHeight = m_aConditions[0]->get_preferred_size().Height(); + m_xScrollWindow->vadjustment_set_value(nTopCondIndex * nHeight); + OnScroll(*m_xScrollWindow); + } + + void ConditionalFormattingDialog::impl_ensureConditionVisible( size_t _nCondIndex ) + { + OSL_PRECOND( _nCondIndex < impl_getConditionCount(), + "ConditionalFormattingDialog::impl_ensureConditionVisible: illegal index!" ); + + if ( _nCondIndex < impl_getFirstVisibleConditionIndex() ) + impl_scrollTo( _nCondIndex ); + else if ( _nCondIndex > impl_getLastVisibleConditionIndex() ) + impl_scrollTo( _nCondIndex - MAX_CONDITIONS + 1 ); + } + + +} // rptui + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/reportdesign/source/ui/dlg/Condition.cxx b/reportdesign/source/ui/dlg/Condition.cxx new file mode 100644 index 000000000..9f7b8bbd5 --- /dev/null +++ b/reportdesign/source/ui/dlg/Condition.cxx @@ -0,0 +1,379 @@ +/* -*- 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 "Condition.hxx" +#include <UITools.hxx> +#include <CondFormat.hxx> +#include <core_resource.hxx> +#include <strings.hrc> +#include <ReportController.hxx> +#include <reportformula.hxx> + +#include <svx/PaletteManager.hxx> +#include <svx/svxids.hrc> +#include <toolkit/helper/vclunohelper.hxx> +#include <vcl/svapp.hxx> +#include <vcl/settings.hxx> + +#include <tools/diagnose_ex.h> + +namespace rptui +{ +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; + +ConditionField::ConditionField(Condition* pParent, std::unique_ptr<weld::Entry> xSubEdit, + std::unique_ptr<weld::Button> xFormula) + : m_pParent(pParent) + , m_xSubEdit(std::move(xSubEdit)) + , m_xFormula(std::move(xFormula)) +{ + m_xFormula->set_label("..."); + m_xFormula->connect_clicked( LINK( this, ConditionField, OnFormula ) ); +} + +IMPL_LINK_NOARG(ConditionField, OnFormula, weld::Button&, void) +{ + OUString sFormula(m_xSubEdit->get_text()); + const sal_Int32 nLen = sFormula.getLength(); + if ( nLen ) + { + ReportFormula aFormula( sFormula ); + sFormula = aFormula.getCompleteFormula(); + } + uno::Reference< awt::XWindow> xInspectorWindow = m_pParent->GetXWindow(); + uno::Reference< beans::XPropertySet> xProp(m_pParent->getController().getRowSet(),uno::UNO_QUERY); + if ( rptui::openDialogFormula_nothrow( sFormula, m_pParent->getController().getContext(),xInspectorWindow,xProp ) ) + { + ReportFormula aFormula( sFormula ); + m_xSubEdit->set_text(aFormula.getUndecoratedContent()); + } +} + +ConditionColorWrapper::ConditionColorWrapper(Condition* pControl, sal_uInt16 nSlotId) + : mpControl(pControl) + , mnSlotId(nSlotId) +{ +} + +void ConditionColorWrapper::operator()(const OUString& /*rCommand*/, const NamedColor& rNamedColor) +{ + mpControl->ApplyCommand(mnSlotId, rNamedColor); +} + +// = Condition +Condition::Condition(weld::Container* pParent, weld::Window* pDialog, IConditionalFormatAction& _rAction, ::rptui::OReportController& _rController) + : m_xPaletteManager(std::make_shared<PaletteManager>()) + , m_aBackColorWrapper(this, SID_BACKGROUND_COLOR) + , m_aForeColorWrapper(this, SID_ATTR_CHAR_COLOR2) + , m_rController(_rController) + , m_rAction(_rAction) + , m_nCondIndex(0) + , m_pDialog(pDialog) + , m_xBuilder(Application::CreateBuilder(pParent, "modules/dbreport/ui/conditionwin.ui")) + , m_xContainer(m_xBuilder->weld_container("ConditionWin")) + , m_xHeader(m_xBuilder->weld_label("headerLabel")) + , m_xConditionType(m_xBuilder->weld_combo_box("typeCombobox")) + , m_xOperationList(m_xBuilder->weld_combo_box("opCombobox")) + , m_xOperandGlue(m_xBuilder->weld_label("andLabel")) + , m_xActions(m_xBuilder->weld_toolbar("formatToolbox")) + , m_xPreview(new weld::CustomWeld(*m_xBuilder, "previewDrawingarea", m_aPreview)) + , m_xMoveUp(m_xBuilder->weld_button("upButton")) + , m_xMoveDown(m_xBuilder->weld_button("downButton")) + , m_xAddCondition(m_xBuilder->weld_button("addButton")) + , m_xRemoveCondition(m_xBuilder->weld_button("removeButton")) +{ + m_xCondLHS.reset(new ConditionField(this, m_xBuilder->weld_entry("lhsEntry"), m_xBuilder->weld_button("lhsButton"))); + m_xCondRHS.reset(new ConditionField(this, m_xBuilder->weld_entry("rhsEntry"), m_xBuilder->weld_button("rhsButton"))); + + m_xCondLHS->grab_focus(); + + m_xConditionType->connect_changed( LINK( this, Condition, OnTypeSelected ) ); + + m_xOperationList->connect_changed( LINK( this, Condition, OnOperationSelected ) ); + + m_xActions->connect_clicked(LINK(this, Condition, OnFormatAction)); + + m_xMoveUp->connect_clicked( LINK( this, Condition, OnConditionAction ) ); + m_xMoveDown->connect_clicked( LINK( this, Condition, OnConditionAction ) ); + m_xAddCondition->connect_clicked( LINK( this, Condition, OnConditionAction ) ); + m_xRemoveCondition->connect_clicked( LINK( this, Condition, OnConditionAction ) ); + + m_xConditionType->set_active(0); + m_xOperationList->set_active(0); + + SetBackgroundDropdownClick(); + SetForegroundDropdownClick(); + + m_xContainer->show(); + + ConditionalExpressionFactory::getKnownConditionalExpressions( m_aConditionalExpressions ); +} + +sal_uInt16 Condition::mapToolbarItemToSlotId(const OString& rItemId) +{ + if (rItemId == "bold") + return SID_ATTR_CHAR_WEIGHT; + if (rItemId == "italic") + return SID_ATTR_CHAR_POSTURE; + if (rItemId == "underline") + return SID_ATTR_CHAR_UNDERLINE; + if (rItemId == "background") + return SID_BACKGROUND_COLOR; + if (rItemId == "foreground") + return SID_ATTR_CHAR_COLOR2; + if (rItemId == "fontdialog") + return SID_CHAR_DLG; + return 0; +} + +Condition::~Condition() +{ +} + +void Condition::SetBackgroundDropdownClick() +{ + m_xBackColorFloat.reset(new ColorWindow( + OUString() /*m_aCommandURL*/, + m_xPaletteManager, + m_aColorStatus, + SID_BACKGROUND_COLOR, + nullptr, + m_pDialog, + MenuOrToolMenuButton(m_xActions.get(), "background"), + m_aBackColorWrapper)); + + m_xActions->set_item_popover("background", m_xBackColorFloat->getTopLevel()); +} + +void Condition::SetForegroundDropdownClick() +{ + m_xForeColorFloat.reset(new ColorWindow( + OUString() /*m_aCommandURL*/, + m_xPaletteManager, + m_aColorStatus, + SID_ATTR_CHAR_COLOR2, + nullptr, + m_pDialog, + MenuOrToolMenuButton(m_xActions.get(), "foreground"), + m_aForeColorWrapper)); + + m_xActions->set_item_popover("foreground", m_xForeColorFloat->getTopLevel()); +} + + +IMPL_LINK(Condition, OnFormatAction, const OString&, rIdent, void) +{ + ApplyCommand(mapToolbarItemToSlotId(rIdent), + NamedColor(COL_AUTO, "#" + COL_AUTO.AsRGBHexString())); +} + +IMPL_LINK(Condition, OnConditionAction, weld::Button&, rClickedButton, void) +{ + if ( &rClickedButton == m_xMoveUp.get() ) + m_rAction.moveConditionUp( getConditionIndex() ); + else if ( &rClickedButton == m_xMoveDown.get() ) + m_rAction.moveConditionDown( getConditionIndex() ); + else if ( &rClickedButton == m_xAddCondition.get() ) + m_rAction.addCondition( getConditionIndex() ); + else if ( &rClickedButton == m_xRemoveCondition.get() ) + m_rAction.deleteCondition( getConditionIndex() ); +} + +void Condition::ApplyCommand( sal_uInt16 _nCommandId, const NamedColor& rNamedColor ) +{ + m_rAction.applyCommand( m_nCondIndex, _nCommandId, rNamedColor.first ); +} + +IMPL_LINK_NOARG( Condition, OnTypeSelected, weld::ComboBox&, void ) +{ + impl_layoutOperands(); +} + +IMPL_LINK_NOARG( Condition, OnOperationSelected, weld::ComboBox&, void ) +{ + impl_layoutOperands(); +} + +void Condition::impl_layoutOperands() +{ + const ConditionType eType( impl_getCurrentConditionType() ); + const ComparisonOperation eOperation( impl_getCurrentComparisonOperation() ); + + const bool bIsExpression = ( eType == eExpression ); + const bool bHaveRHS = + ( ( eType == eFieldValueComparison ) + && ( ( eOperation == eBetween ) + || ( eOperation == eNotBetween ) + ) + ); + + // the "condition type" list box + m_xOperationList->set_visible( !bIsExpression ); + m_xOperandGlue->set_visible( bHaveRHS ); + m_xCondRHS->set_visible( bHaveRHS ); +} + +void Condition::impl_setCondition( const OUString& _rConditionFormula ) +{ + // determine the condition's type and comparison operation + ConditionType eType( eFieldValueComparison ); + ComparisonOperation eOperation( eBetween ); + + // LHS and RHS, matched below + OUString sLHS, sRHS; + + if ( !_rConditionFormula.isEmpty() ) + { + // the unprefixed expression which forms the condition + ReportFormula aFormula( _rConditionFormula ); + OSL_ENSURE( aFormula.getType() == ReportFormula::Expression, "Condition::setCondition: illegal formula!" ); + OUString sExpression; + if ( aFormula.getType() == ReportFormula::Expression ) + sExpression = aFormula.getExpression(); + // as fallback, if the below matching does not succeed, assume + // the whole expression is the LHS + eType = eExpression; + sLHS = sExpression; + + // the data field (or expression) to which our control is bound + const ReportFormula aFieldContentFormula( m_rAction.getDataField() ); + const OUString sUnprefixedFieldContent( aFieldContentFormula.getBracketedFieldOrExpression() ); + + // check whether one of the Field Value Expression Factories recognizes the expression + for (const auto& [rOperation, rxConditionalExpression] : m_aConditionalExpressions) + { + if ( rxConditionalExpression->matchExpression( sExpression, sUnprefixedFieldContent, sLHS, sRHS ) ) + { + eType = eFieldValueComparison; + eOperation = rOperation; + break; + } + } + } + + // update UI + m_xConditionType->set_active(static_cast<sal_uInt16>(eType)); + m_xOperationList->set_active(static_cast<sal_uInt16>(eOperation)); + m_xCondLHS->set_text( sLHS ); + m_xCondRHS->set_text( sRHS ); + + // re-layout + impl_layoutOperands(); +} + + +void Condition::setCondition( const uno::Reference< report::XFormatCondition >& _rxCondition ) +{ + OSL_PRECOND( _rxCondition.is(), "Condition::setCondition: empty condition object!" ); + if ( !_rxCondition.is() ) + return; + + OUString sConditionFormula; + try + { + if ( _rxCondition.is() ) + sConditionFormula = _rxCondition->getFormula(); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION("reportdesign"); + } + impl_setCondition( sConditionFormula ); + updateToolbar( _rxCondition.get() ); +} + + +void Condition::updateToolbar(const uno::Reference< report::XReportControlFormat >& _xReportControlFormat) +{ + OString aItems[] = { "bold", "italic", "underline", "fontdialog" }; + + OSL_ENSURE(_xReportControlFormat.is(),"XReportControlFormat is NULL!"); + if ( !_xReportControlFormat.is() ) + return; + + for (size_t j = 0; j < SAL_N_ELEMENTS(aItems); ++j) + { + m_xActions->set_item_active(aItems[j], OReportController::isFormatCommandEnabled(mapToolbarItemToSlotId(aItems[j]), + _xReportControlFormat)); + } + + try + { + vcl::Font aBaseFont( Application::GetDefaultDevice()->GetSettings().GetStyleSettings().GetAppFont() ); + SvxFont aFont( VCLUnoHelper::CreateFont( _xReportControlFormat->getFontDescriptor(), aBaseFont ) ); + aFont.SetFontHeight(OutputDevice::LogicToLogic(Size(0, aFont.GetFontHeight()), MapMode(MapUnit::MapPoint), MapMode(MapUnit::MapTwip)).Height()); + aFont.SetEmphasisMark( static_cast< FontEmphasisMark >( _xReportControlFormat->getControlTextEmphasis() ) ); + aFont.SetRelief( static_cast< FontRelief >( _xReportControlFormat->getCharRelief() ) ); + aFont.SetColor( Color(_xReportControlFormat->getCharColor()) ); + m_aPreview.SetFont( aFont, aFont, aFont ); + m_aPreview.SetBackColor( Color(_xReportControlFormat->getControlBackground()) ); + m_aPreview.SetTextLineColor( Color( _xReportControlFormat->getCharUnderlineColor() ) ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION("reportdesign"); + } +} + +void Condition::fillFormatCondition(const uno::Reference< report::XFormatCondition >& _xCondition) +{ + const ConditionType eType( impl_getCurrentConditionType() ); + const ComparisonOperation eOperation( impl_getCurrentComparisonOperation() ); + + const OUString sLHS( m_xCondLHS->get_text() ); + const OUString sRHS( m_xCondRHS->get_text() ); + + OUString sUndecoratedFormula( sLHS ); + + if ( eType == eFieldValueComparison ) + { + ReportFormula aFieldContentFormula( m_rAction.getDataField() ); + OUString sUnprefixedFieldContent( aFieldContentFormula.getBracketedFieldOrExpression() ); + + PConditionalExpression pFactory( m_aConditionalExpressions[ eOperation ] ); + sUndecoratedFormula = pFactory->assembleExpression( sUnprefixedFieldContent, sLHS, sRHS ); + } + + ReportFormula aFormula( ReportFormula::Expression, sUndecoratedFormula ); + _xCondition->setFormula( aFormula.getCompleteFormula() ); +} + +void Condition::setConditionIndex( size_t _nCondIndex, size_t _nCondCount ) +{ + m_nCondIndex = _nCondIndex; + OUString sHeader( RptResId( STR_NUMBERED_CONDITION ) ); + sHeader = sHeader.replaceFirst( "$number$", OUString::number( _nCondIndex + 1) ); + m_xHeader->set_label( sHeader ); + + m_xMoveUp->set_sensitive(_nCondIndex > 0); + OSL_PRECOND( _nCondCount > 0, "Condition::setConditionIndex: having no conditions at all is nonsense!" ); + m_xMoveDown->set_sensitive(_nCondIndex < _nCondCount - 1); +} + +bool Condition::isEmpty() const +{ + return m_xCondLHS->get_text().isEmpty(); +} + +} // rptui + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/reportdesign/source/ui/dlg/Condition.hxx b/reportdesign/source/ui/dlg/Condition.hxx new file mode 100644 index 000000000..641c1a2bf --- /dev/null +++ b/reportdesign/source/ui/dlg/Condition.hxx @@ -0,0 +1,182 @@ +/* -*- 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 . + */ + +#ifndef INCLUDED_REPORTDESIGN_SOURCE_UI_DLG_CONDITION_HXX +#define INCLUDED_REPORTDESIGN_SOURCE_UI_DLG_CONDITION_HXX + +#include <conditionalexpression.hxx> + +#include <com/sun/star/report/XFormatCondition.hpp> + +#include <svx/colorwindow.hxx> +#include <svx/fntctrl.hxx> + +#include <vcl/customweld.hxx> +#include <vcl/weld.hxx> + +#include <memory> + +namespace rptui +{ + class OColorPopup; + class OReportController; + class IConditionalFormatAction; + class Condition; + + class ConditionField + { + Condition* m_pParent; + std::unique_ptr<weld::Entry> m_xSubEdit; + std::unique_ptr<weld::Button> m_xFormula; + + DECL_LINK(OnFormula, weld::Button&, void); + public: + ConditionField(Condition* pParent, std::unique_ptr<weld::Entry> xSubEdit, std::unique_ptr<weld::Button> xFormula); + void grab_focus() { m_xSubEdit->grab_focus(); } + void set_visible(bool bShow) { m_xSubEdit->set_visible(bShow); m_xFormula->set_visible(bShow); } + void set_text(const OUString& rText) { m_xSubEdit->set_text(rText); } + OUString get_text() const { return m_xSubEdit->get_text(); } + }; + + class ConditionColorWrapper + { + public: + ConditionColorWrapper(Condition* pControl, sal_uInt16 nSlotId); + void operator()(const OUString& rCommand, const NamedColor& rColor); + private: + Condition* mpControl; + sal_uInt16 mnSlotId; + }; + + //= Condition + + class Condition + { + std::shared_ptr<PaletteManager> m_xPaletteManager; + ColorStatus m_aColorStatus; + ConditionColorWrapper m_aBackColorWrapper; + ConditionColorWrapper m_aForeColorWrapper; + + ::rptui::OReportController& m_rController; + IConditionalFormatAction& m_rAction; + + size_t m_nCondIndex; + + ConditionalExpressions m_aConditionalExpressions; + + SvxFontPrevWindow m_aPreview; + weld::Window* m_pDialog; + std::unique_ptr<weld::Builder> m_xBuilder; + std::unique_ptr<weld::Container> m_xContainer; + std::unique_ptr<weld::Label> m_xHeader; + std::unique_ptr<weld::ComboBox> m_xConditionType; + std::unique_ptr<weld::ComboBox> m_xOperationList; + std::unique_ptr<ConditionField> m_xCondLHS; + std::unique_ptr<weld::Label> m_xOperandGlue; + std::unique_ptr<ConditionField> m_xCondRHS; + std::unique_ptr<weld::Toolbar> m_xActions; + std::unique_ptr<weld::CustomWeld> m_xPreview; + std::unique_ptr<weld::Button> m_xMoveUp; + std::unique_ptr<weld::Button> m_xMoveDown; + std::unique_ptr<weld::Button> m_xAddCondition; + std::unique_ptr<weld::Button> m_xRemoveCondition; + std::unique_ptr<ColorWindow> m_xBackColorFloat; + std::unique_ptr<ColorWindow> m_xForeColorFloat; + + void SetBackgroundDropdownClick(); + void SetForegroundDropdownClick(); + + DECL_LINK( OnFormatAction, const OString&, void ); + DECL_LINK( OnConditionAction, weld::Button&, void ); + + public: + Condition(weld::Container* pParent, weld::Window* pDialog, IConditionalFormatAction& rAction, ::rptui::OReportController& rController); + ~Condition(); + + /** sets the props at the control + @param _xCondition the source + */ + void setCondition(const css::uno::Reference< css::report::XFormatCondition >& _xCondition); + + /** fills from the control + _xCondition the destination + */ + void fillFormatCondition(const css::uno::Reference< css::report::XFormatCondition >& _xCondition); + + /** updates the toolbar + _xCondition the destination + */ + void updateToolbar(const css::uno::Reference< css::report::XReportControlFormat >& _xCondition); + + /// tells the condition its new index within the dialog's condition array + void setConditionIndex( size_t _nCondIndex, size_t _nCondCount ); + + /// returns the condition's index within the dialog's condition array + size_t getConditionIndex() const { return m_nCondIndex; } + + /** determines whether the condition is actually empty + */ + bool isEmpty() const; + + /** forward to the parent class + */ + void ApplyCommand( sal_uInt16 _nCommandId, const NamedColor& rNamedColor ); + + ::rptui::OReportController& getController() const { return m_rController; } + + static sal_uInt16 mapToolbarItemToSlotId(const OString& rItemId); + + css::uno::Reference<css::awt::XWindow> GetXWindow() const { return m_pDialog->GetXWindow(); } + + void grab_focus() { m_xContainer->grab_focus(); } + bool has_focus() const { return m_xContainer->has_focus(); } + Size get_preferred_size() const { return m_xContainer->get_preferred_size(); } + weld::Widget* get_widget() const { return m_xContainer.get(); } + + private: + void impl_layoutOperands(); + + inline ConditionType + impl_getCurrentConditionType() const; + + inline ComparisonOperation + impl_getCurrentComparisonOperation() const; + + void impl_setCondition( const OUString& _rConditionFormula ); + + private: + DECL_LINK( OnTypeSelected, weld::ComboBox&, void ); + DECL_LINK( OnOperationSelected, weld::ComboBox&, void ); + }; + + inline ConditionType Condition::impl_getCurrentConditionType() const + { + return sal::static_int_cast<ConditionType>(m_xConditionType->get_active()); + } + + inline ComparisonOperation Condition::impl_getCurrentComparisonOperation() const + { + return sal::static_int_cast<ComparisonOperation>(m_xOperationList->get_active()); + } + +} // namespace rptui + +#endif // INCLUDED_REPORTDESIGN_SOURCE_UI_DLG_CONDITION_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/reportdesign/source/ui/dlg/DateTime.cxx b/reportdesign/source/ui/dlg/DateTime.cxx new file mode 100644 index 000000000..9e5a91bbe --- /dev/null +++ b/reportdesign/source/ui/dlg/DateTime.cxx @@ -0,0 +1,207 @@ +/* -*- 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 <DateTime.hxx> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <rptui_slotid.hrc> +#include <connectivity/dbconversion.hxx> +#include <unotools/syslocale.hxx> +#include <i18nlangtag/languagetag.hxx> +#include <vcl/svapp.hxx> +#include <strings.hxx> +#include <ReportController.hxx> +#include <com/sun/star/util/NumberFormat.hpp> +#include <com/sun/star/util/XNumberFormatPreviewer.hpp> +#include <algorithm> + +namespace rptui +{ +using namespace ::com::sun::star; +using namespace ::comphelper; + + + +ODateTimeDialog::ODateTimeDialog(weld::Window* _pParent, const uno::Reference< report::XSection >& _xHoldAlive, + OReportController* _pController) + : GenericDialogController(_pParent, "modules/dbreport/ui/datetimedialog.ui", "DateTimeDialog") + + , m_pController(_pController) + , m_xHoldAlive(_xHoldAlive) + , m_xDate(m_xBuilder->weld_check_button("date")) + , m_xFTDateFormat(m_xBuilder->weld_label("datelistbox_label")) + , m_xDateListBox(m_xBuilder->weld_combo_box("datelistbox")) + , m_xTime(m_xBuilder->weld_check_button("time")) + , m_xFTTimeFormat(m_xBuilder->weld_label("timelistbox_label")) + , m_xTimeListBox(m_xBuilder->weld_combo_box("timelistbox")) + , m_xPB_OK(m_xBuilder->weld_button("ok")) +{ + try + { + SvtSysLocale aSysLocale; + m_nLocale = aSysLocale.GetLanguageTag().getLocale(); + // Fill listbox with all well known date types + InsertEntry(util::NumberFormat::DATE); + InsertEntry(util::NumberFormat::TIME); + } + catch (const uno::Exception&) + { + } + + m_xDateListBox->set_active(0); + m_xTimeListBox->set_active(0); + + weld::CheckButton* aCheckBoxes[] = { m_xDate.get(), m_xTime.get() }; + for (weld::CheckButton* pCheckBox : aCheckBoxes) + pCheckBox->connect_toggled(LINK(this,ODateTimeDialog,CBClickHdl)); + CBClickHdl(*m_xTime); +} + +void ODateTimeDialog::InsertEntry(sal_Int16 _nNumberFormatId) +{ + const bool bTime = util::NumberFormat::TIME == _nNumberFormatId; + weld::ComboBox* pListBox = m_xDateListBox.get(); + if (bTime) + pListBox = m_xTimeListBox.get(); + + const uno::Reference< util::XNumberFormatter> xNumberFormatter = m_pController->getReportNumberFormatter(); + const uno::Reference< util::XNumberFormats> xFormats = xNumberFormatter->getNumberFormatsSupplier()->getNumberFormats(); + const uno::Sequence<sal_Int32> aFormatKeys = xFormats->queryKeys(_nNumberFormatId,m_nLocale,true); + for (const sal_Int32 nFormatKey : aFormatKeys) + { + pListBox->append(OUString::number(nFormatKey), getFormatStringByKey(nFormatKey,xFormats,bTime)); + } +} + +short ODateTimeDialog::run() +{ + short nRet = GenericDialogController::run(); + if (nRet == RET_OK && (m_xDate->get_active() || m_xTime->get_active())) + { + try + { + sal_Int32 nLength = 0; + uno::Sequence<beans::PropertyValue> aValues( 6 ); + aValues[nLength].Name = PROPERTY_SECTION; + aValues[nLength++].Value <<= m_xHoldAlive; + + aValues[nLength].Name = PROPERTY_TIME_STATE; + aValues[nLength++].Value <<= m_xTime->get_active(); + + aValues[nLength].Name = PROPERTY_DATE_STATE; + aValues[nLength++].Value <<= m_xDate->get_active(); + + aValues[nLength].Name = PROPERTY_FORMATKEYDATE; + aValues[nLength++].Value <<= getFormatKey(true); + + aValues[nLength].Name = PROPERTY_FORMATKEYTIME; + aValues[nLength++].Value <<= getFormatKey(false); + + OutputDevice* pDefDev = Application::GetDefaultDevice(); + sal_Int32 nWidth = 0; + if ( m_xDate->get_active() ) + { + OUString sDateFormat = m_xDateListBox->get_active_text(); + nWidth = OutputDevice::LogicToLogic(pDefDev->PixelToLogic(Size(pDefDev->GetCtrlTextWidth(sDateFormat),0)).Width(), + pDefDev->GetMapMode().GetMapUnit(),MapUnit::Map100thMM); + } + if ( m_xTime->get_active() ) + { + OUString sDateFormat = m_xTimeListBox->get_active_text(); + nWidth = ::std::max<sal_Int32>(OutputDevice::LogicToLogic(pDefDev->PixelToLogic(Size(pDefDev->GetCtrlTextWidth(sDateFormat),0)).Width(), + pDefDev->GetMapMode().GetMapUnit(),MapUnit::Map100thMM),nWidth); + } + + if ( nWidth > 4000 ) + { + aValues[nLength].Name = PROPERTY_WIDTH; + aValues[nLength++].Value <<= nWidth; + } + + m_pController->executeChecked(SID_DATETIME,aValues); + } + catch (const uno::Exception&) + { + nRet = RET_NO; + } + } + return nRet; +} + +OUString ODateTimeDialog::getFormatStringByKey(::sal_Int32 _nNumberFormatKey,const uno::Reference< util::XNumberFormats>& _xFormats,bool _bTime) +{ + uno::Reference< beans::XPropertySet> xFormSet = _xFormats->getByKey(_nNumberFormatKey); + OSL_ENSURE(xFormSet.is(),"XPropertySet is null!"); + OUString sFormat; + xFormSet->getPropertyValue("FormatString") >>= sFormat; + + double nValue = 0; + if ( _bTime ) + { + tools::Time aCurrentTime( tools::Time::SYSTEM ); + nValue = ::dbtools::DBTypeConversion::toDouble(::dbtools::DBTypeConversion::toTime(aCurrentTime.GetTime())); + } + else + { + Date aCurrentDate( Date::SYSTEM ); + static css::util::Date STANDARD_DB_DATE(30,12,1899); + nValue = ::dbtools::DBTypeConversion::toDouble(::dbtools::DBTypeConversion::toDate(aCurrentDate.GetDate()),STANDARD_DB_DATE); + } + + uno::Reference< util::XNumberFormatPreviewer> xPreviewer(m_pController->getReportNumberFormatter(),uno::UNO_QUERY); + OSL_ENSURE(xPreviewer.is(),"XNumberFormatPreviewer is null!"); + return xPreviewer->convertNumberToPreviewString(sFormat,nValue,m_nLocale,true); +} + +IMPL_LINK_NOARG(ODateTimeDialog, CBClickHdl, weld::ToggleButton&, void) +{ + const bool bDate = m_xDate->get_active(); + m_xFTDateFormat->set_sensitive(bDate); + m_xDateListBox->set_sensitive(bDate); + + const bool bTime = m_xTime->get_active(); + m_xFTTimeFormat->set_sensitive(bTime); + m_xTimeListBox->set_sensitive(bTime); + + if (!bDate && !bTime) + { + m_xPB_OK->set_sensitive(false); + } + else + { + m_xPB_OK->set_sensitive(true); + } +} + +sal_Int32 ODateTimeDialog::getFormatKey(bool _bDate) const +{ + sal_Int32 nFormatKey; + if ( _bDate ) + { + nFormatKey = m_xDateListBox->get_active_id().toInt32(); + } + else + { + nFormatKey = m_xTimeListBox->get_active_id().toInt32(); + } + return nFormatKey; +} + +} // rptui + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/reportdesign/source/ui/dlg/Formula.cxx b/reportdesign/source/ui/dlg/Formula.cxx new file mode 100644 index 000000000..3bdcb2e5b --- /dev/null +++ b/reportdesign/source/ui/dlg/Formula.cxx @@ -0,0 +1,274 @@ +/* -*- 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 <unotools/viewoptions.hxx> +#include <formula/formdata.hxx> +#include <formula/funcutl.hxx> +#include <formula/tokenarray.hxx> +#include <formula/FormulaCompiler.hxx> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/beans/PropertyValue.hpp> + +#include <memory> + +#include <Formula.hxx> +#include <AddField.hxx> +#include <helpids.h> + + +namespace rptui +{ + using namespace formula; + using namespace ::com::sun::star; + + +// initialization / shared functions for the dialog + + +FormulaDialog::FormulaDialog(weld::Window* pParent + , const uno::Reference<lang::XMultiServiceFactory>& _xServiceFactory + , const std::shared_ptr< IFunctionManager >& _pFunctionMgr + , const OUString& _sFormula + , const css::uno::Reference < css::beans::XPropertySet >& _xRowSet + , svl::SharedStringPool& rStrPool ) + : FormulaModalDialog( pParent, _pFunctionMgr.get(),this) + ,m_aFunctionManager(_pFunctionMgr) + ,m_xFormulaData(new FormEditData()) + ,m_xRowSet(_xRowSet) + ,m_pEdit(nullptr) + ,m_sFormula("=") + ,m_nStart(0) + ,m_nEnd(1) + ,mrStringPool(rStrPool) +{ + if ( !_sFormula.isEmpty() ) + { + if ( _sFormula[0] != '=' ) + m_sFormula += _sFormula; + else + m_sFormula = _sFormula; + } + m_xParser.set(_xServiceFactory->createInstance("org.libreoffice.report.pentaho.SOFormulaParser"),uno::UNO_QUERY); + if ( m_xParser.is() ) + m_xOpCodeMapper = m_xParser->getFormulaOpCodeMapper(); + fill(); +} + +void FormulaDialog::notifyChange() +{ +} + +void FormulaDialog::fill() +{ + SetMeText(m_sFormula); + Update(m_sFormula); + CheckMatrix(m_sFormula); + Update(); +} + +FormulaDialog::~FormulaDialog() +{ + if ( m_xAddField ) + { + SvtViewOptions aDlgOpt( EViewType::Window, HID_RPT_FIELD_SEL_WIN ); + aDlgOpt.SetWindowState(OStringToOUString(m_xAddField->getDialog()->get_window_state(WindowStateMask::X | WindowStateMask::Y | WindowStateMask::State | WindowStateMask::Minimized), RTL_TEXTENCODING_ASCII_US)); + + if (m_xAddField->getDialog()->get_visible()) + m_xAddField->response(RET_CANCEL); + + m_xAddField.reset(); + } + + StoreFormEditData(m_xFormulaData.get()); + m_pEdit = nullptr; +} + +// functions for right side + +bool FormulaDialog::calculateValue( const OUString& rStrExp, OUString& rStrResult, bool /*bMatrixFormula*/ ) +{ + rStrResult = rStrExp; + return false; +} + +std::shared_ptr<formula::FormulaCompiler> FormulaDialog::getCompiler() const +{ + return nullptr; +} + +std::unique_ptr<formula::FormulaCompiler> FormulaDialog::createCompiler( formula::FormulaTokenArray& rArray ) const +{ + return std::unique_ptr<formula::FormulaCompiler>(new FormulaCompiler(rArray)); +} + +void FormulaDialog::doClose(bool _bOk) +{ + response(_bOk ? RET_OK : RET_CANCEL); +} + +void FormulaDialog::insertEntryToLRUList(const IFunctionDescription* /*_pDesc*/) +{ +} +void FormulaDialog::showReference(const OUString& /*_sFormula*/) +{ +} +void FormulaDialog::dispatch(bool /*_bOK*/, bool /*_bMatrixChecked*/) +{ +} +void FormulaDialog::setDispatcherLock( bool /*bLock*/ ) +{ +} +void FormulaDialog::deleteFormData() +{ +} +void FormulaDialog::clear() +{ +} +void FormulaDialog::switchBack() +{ +} +FormEditData* FormulaDialog::getFormEditData() const +{ + return m_xFormulaData.get(); +} +void FormulaDialog::setCurrentFormula(const OUString& _sReplacement) +{ + const sal_Int32 nOldLen = m_nEnd - m_nStart; + const sal_Int32 nNewLen = _sReplacement.getLength(); + if (nOldLen) + m_sFormula = m_sFormula.replaceAt( m_nStart, nOldLen, "" ); + if (nNewLen) + m_sFormula = m_sFormula.replaceAt( m_nStart, 0, _sReplacement ); + m_nEnd = m_nStart + nNewLen; +} +void FormulaDialog::setSelection(sal_Int32 _nStart, sal_Int32 _nEnd) +{ + if ( _nStart <= _nEnd ) + { + m_nStart = _nStart; + m_nEnd = _nEnd; + } + else + { + m_nEnd = _nStart; + m_nStart = _nEnd; + } +} +void FormulaDialog::getSelection(sal_Int32& _nStart, sal_Int32& _nEnd) const +{ + _nStart = m_nStart; + _nEnd = m_nEnd; +} +OUString FormulaDialog::getCurrentFormula() const +{ + return m_sFormula; +} +IFunctionManager* FormulaDialog::getFunctionManager() +{ + return m_aFunctionManager.get(); +} + +void FormulaDialog::ShowReference(const OUString& /*_sRef*/) +{ +} + +void FormulaDialog::HideReference( bool /*bDoneRefMode*/) +{ +} + +void FormulaDialog::ReleaseFocus( RefEdit* /*pEdit*/) +{ +} + +void FormulaDialog::ToggleCollapsed( RefEdit* _pEdit, RefButton* _pButton) +{ + ::std::pair<RefButton*,RefEdit*> aPair = RefInputStartBefore( _pEdit, _pButton ); + m_pEdit = aPair.second; + if ( m_pEdit ) + m_pEdit->GetWidget()->hide(); + if ( aPair.first ) + aPair.first->GetWidget()->hide(); + + if (!m_xAddField) + { + m_xAddField = std::make_shared<OAddFieldWindow>(m_xDialog.get(), m_xRowSet); + m_xAddField->SetCreateHdl(LINK( this, FormulaDialog, OnClickHdl ) ); + SvtViewOptions aDlgOpt( EViewType::Window, HID_RPT_FIELD_SEL_WIN ); + if ( aDlgOpt.Exists() ) + { + m_xAddField->getDialog()->set_window_state(OUStringToOString(aDlgOpt.GetWindowState(), RTL_TEXTENCODING_ASCII_US)); + + } + + m_xAddField->Update(); + } + RefInputStartAfter(); + + if (!m_xAddField->getDialog()->get_visible()) + weld::DialogController::runAsync(m_xAddField, [this](sal_Int32 /*nResult*/) { m_xAddField.reset(); }); +} + +IMPL_LINK( FormulaDialog, OnClickHdl, OAddFieldWindow& ,_rAddFieldDlg, void) +{ + const uno::Sequence< beans::PropertyValue > aArgs = _rAddFieldDlg.getSelectedFieldDescriptors(); + // we use this way to create undo actions + if ( m_pEdit && aArgs.getLength() == 1) + { + uno::Sequence< beans::PropertyValue > aValue; + aArgs[0].Value >>= aValue; + svx::ODataAccessDescriptor aDescriptor(aValue); + OUString sName; + aDescriptor[ svx::DataAccessDescriptorProperty::ColumnName ] >>= sName; + if ( !sName.isEmpty() ) + { + sName = "[" + sName + "]"; + m_pEdit->SetText(sName); + } + } + m_pEdit = nullptr; + if (_rAddFieldDlg.getDialog()->get_visible()) + _rAddFieldDlg.response(RET_CANCEL); + RefInputDoneAfter(); +} + +uno::Reference< sheet::XFormulaParser> FormulaDialog::getFormulaParser() const +{ + return m_xParser.get(); +} + +uno::Reference< sheet::XFormulaOpCodeMapper> FormulaDialog::getFormulaOpCodeMapper() const +{ + return m_xOpCodeMapper; +} + +table::CellAddress FormulaDialog::getReferencePosition() const +{ + return table::CellAddress(); +} + +::std::unique_ptr<formula::FormulaTokenArray> FormulaDialog::convertToTokenArray(const uno::Sequence< sheet::FormulaToken >& _aTokenList) +{ + ::std::unique_ptr<formula::FormulaTokenArray> pArray(new FormulaTokenArray()); + pArray->Fill(_aTokenList, mrStringPool, nullptr); + return pArray; +} + +} // rptui + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/reportdesign/source/ui/dlg/GroupExchange.cxx b/reportdesign/source/ui/dlg/GroupExchange.cxx new file mode 100644 index 000000000..44e9fa0a3 --- /dev/null +++ b/reportdesign/source/ui/dlg/GroupExchange.cxx @@ -0,0 +1,68 @@ +/* -*- 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 "GroupExchange.hxx" +#include <sot/formats.hxx> +#include <osl/diagnose.h> + +namespace rptui +{ + using namespace ::com::sun::star; + using namespace ::com::sun::star::uno; + + SotClipboardFormatId OGroupExchange::getReportGroupId() + { + static SotClipboardFormatId s_nReportFormat = static_cast<SotClipboardFormatId>(-1); + if ( static_cast<SotClipboardFormatId>(-1) == s_nReportFormat ) + { + s_nReportFormat = SotExchange::RegisterFormatName("application/x-openoffice;windows_formatname=\"reportdesign.GroupFormat\""); + OSL_ENSURE(static_cast<SotClipboardFormatId>(-1) != s_nReportFormat, "Bad exchange id!"); + } + return s_nReportFormat; + } + OGroupExchange::OGroupExchange(const uno::Sequence< uno::Any >& _aGroupRow) + : m_aGroupRow(_aGroupRow) + { + } + + void OGroupExchange::AddSupportedFormats() + { + if ( m_aGroupRow.hasElements() ) + { + AddFormat(OGroupExchange::getReportGroupId()); + } + } + + bool OGroupExchange::GetData( const css::datatransfer::DataFlavor& rFlavor, const OUString& /*rDestDoc*/ ) + { + SotClipboardFormatId nFormat = SotExchange::GetFormat(rFlavor); + if(nFormat == OGroupExchange::getReportGroupId() ) + { + return SetAny(uno::makeAny(m_aGroupRow)); + } + return false; + } + + void OGroupExchange::ObjectReleased() + { + m_aGroupRow.realloc(0); + } + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/reportdesign/source/ui/dlg/GroupExchange.hxx b/reportdesign/source/ui/dlg/GroupExchange.hxx new file mode 100644 index 000000000..6154e75ae --- /dev/null +++ b/reportdesign/source/ui/dlg/GroupExchange.hxx @@ -0,0 +1,43 @@ +/* -*- 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 . + */ +#ifndef INCLUDED_REPORTDESIGN_SOURCE_UI_DLG_GROUPEXCHANGE_HXX +#define INCLUDED_REPORTDESIGN_SOURCE_UI_DLG_GROUPEXCHANGE_HXX + +#include <vcl/transfer.hxx> + +namespace rptui +{ + /** clipboard class for group rows in the groups and sorting dialog + */ + class OGroupExchange : public TransferableHelper + { + css::uno::Sequence< css::uno::Any> m_aGroupRow; + public: + explicit OGroupExchange(const css::uno::Sequence< css::uno::Any>& _aGroupRow); + + static SotClipboardFormatId getReportGroupId(); + protected: + virtual void AddSupportedFormats() override; + virtual bool GetData( const css::datatransfer::DataFlavor& rFlavor, const OUString& rDestDoc ) override; + virtual void ObjectReleased() override; + }; +} +#endif // INCLUDED_REPORTDESIGN_SOURCE_UI_DLG_GROUPEXCHANGE_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/reportdesign/source/ui/dlg/GroupsSorting.cxx b/reportdesign/source/ui/dlg/GroupsSorting.cxx new file mode 100644 index 000000000..8cb3a6534 --- /dev/null +++ b/reportdesign/source/ui/dlg/GroupsSorting.cxx @@ -0,0 +1,1182 @@ +/* -*- 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 <GroupsSorting.hxx> +#include <svtools/editbrowsebox.hxx> +#include <toolkit/helper/vclunohelper.hxx> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/container/XContainerListener.hpp> +#include <com/sun/star/report/GroupOn.hpp> +#include <com/sun/star/sdbc/DataType.hpp> + +#include <strings.hrc> +#include <rptui_slotid.hrc> +#include <core_resource.hxx> +#include <helpids.h> +#include "GroupExchange.hxx" +#include <UITools.hxx> +#include <UndoActions.hxx> +#include <strings.hxx> +#include <ReportController.hxx> +#include <ColumnInfo.hxx> + +#include <cppuhelper/implbase.hxx> +#include <vcl/commandevent.hxx> +#include <vcl/svapp.hxx> + +#include <algorithm> + +#define HANDLE_ID 0 +#define FIELD_EXPRESSION 1 +#define GROUPS_START_LEN 5 +#define NO_GROUP -1 + +namespace rptui +{ +using namespace ::com::sun::star; +using namespace svt; +using namespace ::comphelper; + + static void lcl_addToList_throw( weld::ComboBox& _rListBox, ::std::vector<ColumnInfo>& o_aColumnList,const uno::Reference< container::XNameAccess>& i_xColumns ) + { + const uno::Sequence< OUString > aEntries = i_xColumns->getElementNames(); + for ( const OUString& rEntry : aEntries ) + { + uno::Reference< beans::XPropertySet> xColumn(i_xColumns->getByName(rEntry),uno::UNO_QUERY_THROW); + OUString sLabel; + if ( xColumn->getPropertySetInfo()->hasPropertyByName(PROPERTY_LABEL) ) + xColumn->getPropertyValue(PROPERTY_LABEL) >>= sLabel; + o_aColumnList.emplace_back(rEntry,sLabel ); + if ( !sLabel.isEmpty() ) + _rListBox.append_text( sLabel ); + else + _rListBox.append_text( rEntry ); + } + } + +/** + * Separated out from OFieldExpressionControl to prevent collision of ref-counted base classes + */ +class OFieldExpressionControl; + +namespace { + +class OFieldExpressionControlContainerListener : public ::cppu::WeakImplHelper< container::XContainerListener > +{ + VclPtr<OFieldExpressionControl> mpParent; +public: + explicit OFieldExpressionControlContainerListener(OFieldExpressionControl* pParent) : mpParent(pParent) {} + + // XEventListener + virtual void SAL_CALL disposing(const css::lang::EventObject& Source) override; + // XContainerListener + virtual void SAL_CALL elementInserted(const css::container::ContainerEvent& rEvent) override; + virtual void SAL_CALL elementReplaced(const css::container::ContainerEvent& rEvent) override; + virtual void SAL_CALL elementRemoved(const css::container::ContainerEvent& rEvent) override; +}; + +} + +class OFieldExpressionControl : public ::svt::EditBrowseBox +{ + ::osl::Mutex m_aMutex; + ::std::vector<sal_Int32> m_aGroupPositions; + ::std::vector<ColumnInfo> m_aColumnInfo; + VclPtr< ::svt::ComboBoxControl> m_pComboCell; + sal_Int32 m_nDataPos; + sal_Int32 m_nCurrentPos; + ImplSVEvent * m_nDeleteEvent; + OGroupsSortingDialog* m_pParent; + bool m_bIgnoreEvent; + rtl::Reference<OFieldExpressionControlContainerListener> aContainerListener; + +public: + OFieldExpressionControl(OGroupsSortingDialog* pParentDialog, const css::uno::Reference<css::awt::XWindow> &rParent); + virtual ~OFieldExpressionControl() override; + virtual void dispose() override; + + // XContainerListener + /// @throws css::uno::RuntimeException + void elementInserted(const css::container::ContainerEvent& rEvent); + /// @throws css::uno::RuntimeException + void elementRemoved(const css::container::ContainerEvent& rEvent); + + virtual Size GetOptimalSize() const override; + + void fillColumns(const uno::Reference< container::XNameAccess>& _xColumns); + void lateInit(); + bool IsDeleteAllowed( ) const; + void DeleteRows(); + + sal_Int32 getGroupPosition(sal_Int32 _nRow) const { return _nRow != BROWSER_ENDOFSELECTION ? m_aGroupPositions[_nRow] : sal_Int32(NO_GROUP); } + + /** returns the sequence with the selected groups + */ + uno::Sequence<uno::Any> fillSelectedGroups(); + + /** move groups given by _aGroups + */ + void moveGroups(const uno::Sequence<uno::Any>& _aGroups,sal_Int32 _nRow,bool _bSelect = true); + + virtual bool CursorMoving(long nNewRow, sal_uInt16 nNewCol) override; + using ::svt::EditBrowseBox::GetRowCount; +protected: + virtual bool IsTabAllowed(bool bForward) const override; + + virtual void InitController( ::svt::CellControllerRef& rController, long nRow, sal_uInt16 nCol ) override; + virtual ::svt::CellController* GetController( long nRow, sal_uInt16 nCol ) override; + virtual void PaintCell( OutputDevice& rDev, const tools::Rectangle& rRect, sal_uInt16 nColId ) const override; + virtual bool SeekRow( long nRow ) override; + virtual bool SaveModified() override; + virtual OUString GetCellText( long nRow, sal_uInt16 nColId ) const override; + virtual RowStatus GetRowStatus(long nRow) const override; + + virtual void KeyInput(const KeyEvent& rEvt) override; + virtual void Command( const CommandEvent& rEvt ) override; + + // D&D + virtual void StartDrag( sal_Int8 nAction, const Point& rPosPixel ) override; + virtual sal_Int8 AcceptDrop( const BrowserAcceptDropEvent& rEvt ) override; + virtual sal_Int8 ExecuteDrop( const BrowserExecuteDropEvent& rEvt ) override; + + using BrowseBox::AcceptDrop; + using BrowseBox::ExecuteDrop; + +private: + + DECL_LINK( CBChangeHdl, weld::ComboBox&, void); + +public: + DECL_LINK( DelayedDelete, void*, void ); + +}; + + +void OFieldExpressionControlContainerListener::disposing(const css::lang::EventObject& ) +{} + +void OFieldExpressionControlContainerListener::elementInserted(const css::container::ContainerEvent& rEvent) +{ mpParent->elementInserted(rEvent); } + +void OFieldExpressionControlContainerListener::elementReplaced(const css::container::ContainerEvent& ) +{} + +void OFieldExpressionControlContainerListener::elementRemoved(const css::container::ContainerEvent& rEvent) +{ mpParent->elementRemoved(rEvent); } + +OFieldExpressionControl::OFieldExpressionControl(OGroupsSortingDialog* pParentDialog, const css::uno::Reference<css::awt::XWindow> &rParent) + :EditBrowseBox( VCLUnoHelper::GetWindow(rParent), EditBrowseBoxFlags::NONE, WB_TABSTOP, + BrowserMode::COLUMNSELECTION | BrowserMode::MULTISELECTION | BrowserMode::AUTOSIZE_LASTCOL | + BrowserMode::KEEPHIGHLIGHT | BrowserMode::HLINES | BrowserMode::VLINES) + ,m_aGroupPositions(GROUPS_START_LEN,-1) + ,m_pComboCell(nullptr) + ,m_nDataPos(-1) + ,m_nCurrentPos(-1) + ,m_nDeleteEvent(nullptr) + ,m_pParent(pParentDialog) + ,m_bIgnoreEvent(false) + ,aContainerListener(new OFieldExpressionControlContainerListener(this)) +{ + SetBorderStyle(WindowBorderStyle::MONO); +} + +OFieldExpressionControl::~OFieldExpressionControl() +{ + disposeOnce(); +} + +void OFieldExpressionControl::dispose() +{ + uno::Reference< report::XGroups > xGroups = m_pParent->getGroups(); + xGroups->removeContainerListener(aContainerListener.get()); + + // delete events from queue + if( m_nDeleteEvent ) + Application::RemoveUserEvent( m_nDeleteEvent ); + + m_pComboCell.disposeAndClear(); + m_pParent = nullptr; + ::svt::EditBrowseBox::dispose(); +} + +uno::Sequence<uno::Any> OFieldExpressionControl::fillSelectedGroups() +{ + uno::Sequence<uno::Any> aList; + ::std::vector<uno::Any> vClipboardList; + vClipboardList.reserve(GetSelectRowCount()); + + uno::Reference<report::XGroups> xGroups = m_pParent->getGroups(); + sal_Int32 nCount = xGroups->getCount(); + if ( nCount >= 1 ) + { + for( long nIndex=FirstSelectedRow(); nIndex != SFX_ENDOFSELECTION; nIndex=NextSelectedRow() ) + { + try + { + if ( m_aGroupPositions[nIndex] != NO_GROUP ) + { + uno::Reference< report::XGroup> xOrgGroup(xGroups->getByIndex(m_aGroupPositions[nIndex]),uno::UNO_QUERY); + /*uno::Reference< report::XGroup> xCopy = xGroups->createGroup(); + ::comphelper::copyProperties(xOrgGroup.get(),xCopy.get());*/ + vClipboardList.push_back( uno::makeAny(xOrgGroup) ); + } + } + catch(uno::Exception&) + { + OSL_FAIL("Can not access group!"); + } + } + if ( !vClipboardList.empty() ) + aList = uno::Sequence< uno::Any >(vClipboardList.data(), vClipboardList.size()); + } + return aList; +} + +void OFieldExpressionControl::StartDrag( sal_Int8 /*_nAction*/ , const Point& /*_rPosPixel*/ ) +{ + if ( m_pParent && !m_pParent->isReadOnly( ) ) + { + uno::Sequence<uno::Any> aClipboardList = fillSelectedGroups(); + + if( aClipboardList.hasElements() ) + { + rtl::Reference<OGroupExchange> pData = new OGroupExchange(aClipboardList); + pData->StartDrag(this, DND_ACTION_MOVE ); + } + } +} + +sal_Int8 OFieldExpressionControl::AcceptDrop( const BrowserAcceptDropEvent& rEvt ) +{ + sal_Int8 nAction = DND_ACTION_NONE; + if ( IsEditing() ) + { + weld::ComboBox& rComboBox = m_pComboCell->get_widget(); + sal_Int32 nPos = rComboBox.get_active(); + if (nPos != -1 || !rComboBox.get_active_text().isEmpty()) + SaveModified(); + DeactivateCell(); + } + if ( IsDropFormatSupported( OGroupExchange::getReportGroupId() ) && m_pParent->getGroups()->getCount() > 1 && rEvt.GetWindow() == &GetDataWindow() ) + { + nAction = DND_ACTION_MOVE; + } + return nAction; +} + +sal_Int8 OFieldExpressionControl::ExecuteDrop( const BrowserExecuteDropEvent& rEvt ) +{ + sal_Int8 nAction = DND_ACTION_NONE; + if ( IsDropFormatSupported( OGroupExchange::getReportGroupId() ) ) + { + sal_Int32 nRow = GetRowAtYPosPixel(rEvt.maPosPixel.Y(), false); + SetNoSelection(); + + TransferableDataHelper aDropped( rEvt.maDropEvent.Transferable ); + uno::Any aDrop = aDropped.GetAny(OGroupExchange::getReportGroupId(), OUString()); + uno::Sequence< uno::Any > aGroups; + aDrop >>= aGroups; + if ( aGroups.hasElements() ) + { + moveGroups(aGroups,nRow); + nAction = DND_ACTION_MOVE; + } + } + return nAction; +} + +void OFieldExpressionControl::moveGroups(const uno::Sequence<uno::Any>& _aGroups,sal_Int32 _nRow,bool _bSelect) +{ + if ( !_aGroups.hasElements() ) + return; + + m_bIgnoreEvent = true; + { + sal_Int32 nRow = _nRow; + const OUString sUndoAction(RptResId(RID_STR_UNDO_MOVE_GROUP)); + const UndoContext aUndoContext( m_pParent->m_pController->getUndoManager(), sUndoAction ); + + uno::Reference< report::XGroups> xGroups = m_pParent->getGroups(); + for(const uno::Any& rGroup : _aGroups) + { + uno::Reference< report::XGroup> xGroup(rGroup,uno::UNO_QUERY); + if ( xGroup.is() ) + { + uno::Sequence< beans::PropertyValue > aArgs(1); + aArgs[0].Name = PROPERTY_GROUP; + aArgs[0].Value <<= xGroup; + // we use this way to create undo actions + m_pParent->m_pController->executeChecked(SID_GROUP_REMOVE,aArgs); + aArgs.realloc(2); + if ( nRow > xGroups->getCount() ) + nRow = xGroups->getCount(); + if ( _bSelect ) + SelectRow(nRow); + aArgs[1].Name = PROPERTY_POSITIONY; + aArgs[1].Value <<= nRow; + m_pParent->m_pController->executeChecked(SID_GROUP_APPEND,aArgs); + ++nRow; + } + } + } + m_bIgnoreEvent = false; + Invalidate(); +} + +void OFieldExpressionControl::fillColumns(const uno::Reference< container::XNameAccess>& _xColumns) +{ + weld::ComboBox& rComboBox = m_pComboCell->get_widget(); + rComboBox.clear(); + if ( _xColumns.is() ) + lcl_addToList_throw(rComboBox, m_aColumnInfo, _xColumns); +} + +void OFieldExpressionControl::lateInit() +{ + uno::Reference< report::XGroups > xGroups = m_pParent->getGroups(); + sal_Int32 nGroupsCount = xGroups->getCount(); + m_aGroupPositions.resize(::std::max<sal_Int32>(nGroupsCount,sal_Int32(GROUPS_START_LEN)),NO_GROUP); + ::std::vector<sal_Int32>::iterator aIter = m_aGroupPositions.begin(); + for (sal_Int32 i = 0; i < nGroupsCount; ++i,++aIter) + *aIter = i; + + if ( ColCount() == 0 ) + { + vcl::Font aFont( GetDataWindow().GetFont() ); + aFont.SetWeight( WEIGHT_NORMAL ); + GetDataWindow().SetFont( aFont ); + + // Set font of the headline to light + aFont = GetFont(); + aFont.SetWeight( WEIGHT_LIGHT ); + SetFont(aFont); + + InsertHandleColumn(static_cast<sal_uInt16>(GetTextWidth(OUString('0')) * 4)/*, sal_True */); + InsertDataColumn( FIELD_EXPRESSION, RptResId(STR_RPT_EXPRESSION), 100); + + m_pComboCell = VclPtr<ComboBoxControl>::Create( &GetDataWindow() ); + weld::ComboBox& rComboBox = m_pComboCell->get_widget(); + rComboBox.connect_changed(LINK(this,OFieldExpressionControl,CBChangeHdl)); + m_pComboCell->SetHelpId(HID_RPT_FIELDEXPRESSION); + + rComboBox.connect_focus_in(LINK(m_pParent, OGroupsSortingDialog, OnControlFocusGot)); + + + // set browse mode + BrowserMode nMode(BrowserMode::COLUMNSELECTION | BrowserMode::MULTISELECTION | BrowserMode::KEEPHIGHLIGHT | + BrowserMode::HLINES | BrowserMode::VLINES | BrowserMode::AUTOSIZE_LASTCOL | BrowserMode::AUTO_VSCROLL | BrowserMode::AUTO_HSCROLL); + if( m_pParent->isReadOnly() ) + nMode |= BrowserMode::HIDECURSOR; + SetMode(nMode); + xGroups->addContainerListener(aContainerListener.get()); + } + else + // not the first call + RowRemoved(0, GetRowCount()); + + RowInserted(0, m_aGroupPositions.size()); +} + +IMPL_LINK_NOARG( OFieldExpressionControl, CBChangeHdl, weld::ComboBox&, void ) +{ + SaveModified(); +} + +bool OFieldExpressionControl::IsTabAllowed(bool /*bForward*/) const +{ + return false; +} + +bool OFieldExpressionControl::SaveModified() +{ + sal_Int32 nRow = GetCurRow(); + if ( nRow != BROWSER_ENDOFSELECTION ) + { + try + { + bool bAppend = false; + uno::Reference< report::XGroup> xGroup; + if ( m_aGroupPositions[nRow] == NO_GROUP ) + { + bAppend = true; + OUString sUndoAction(RptResId(RID_STR_UNDO_APPEND_GROUP)); + m_pParent->m_pController->getUndoManager().EnterListAction( sUndoAction, OUString(), 0, ViewShellId(-1) ); + xGroup = m_pParent->getGroups()->createGroup(); + xGroup->setHeaderOn(true); + + uno::Sequence< beans::PropertyValue > aArgs(2); + aArgs[0].Name = PROPERTY_GROUP; + aArgs[0].Value <<= xGroup; + // find position where to insert the new group + sal_Int32 nGroupPos = 0; + ::std::vector<sal_Int32>::iterator aIter = m_aGroupPositions.begin(); + ::std::vector<sal_Int32>::const_iterator aEnd = m_aGroupPositions.begin() + nRow; + for(;aIter != aEnd;++aIter) + if ( *aIter != NO_GROUP ) + nGroupPos = *aIter + 1; + aArgs[1].Name = PROPERTY_POSITIONY; + aArgs[1].Value <<= nGroupPos; + m_bIgnoreEvent = true; + m_pParent->m_pController->executeChecked(SID_GROUP_APPEND,aArgs); + m_bIgnoreEvent = false; + OSL_ENSURE(*aIter == NO_GROUP ,"Illegal iterator!"); + *aIter++ = nGroupPos; + + aEnd = m_aGroupPositions.end(); + for(;aIter != aEnd;++aIter) + if ( *aIter != NO_GROUP ) + ++*aIter; + } + else + xGroup = m_pParent->getGroup(m_aGroupPositions[nRow]); + if ( xGroup.is() ) + { + weld::ComboBox& rComboBox = m_pComboCell->get_widget(); + sal_Int32 nPos = rComboBox.get_active(); + OUString sExpression; + if (nPos == -1) + sExpression = rComboBox.get_active_text(); + else + { + sExpression = m_aColumnInfo[nPos].sColumnName; + } + xGroup->setExpression( sExpression ); + + ::rptui::adjustSectionName(xGroup,nPos); + + if ( bAppend ) + m_pParent->m_pController->getUndoManager().LeaveListAction(); + } + + if ( Controller().is() ) + Controller()->ClearModified(); + if ( GetRowCount() == m_pParent->getGroups()->getCount() ) + { + RowInserted( GetRowCount()-1); + m_aGroupPositions.push_back(NO_GROUP); + } + + GoToRow(nRow); + m_pParent->DisplayData(nRow); + } + catch(uno::Exception&) + { + OSL_FAIL("OFieldExpressionControl::SaveModified: Exception caught!"); + } + } + + return true; +} + +OUString OFieldExpressionControl::GetCellText( long nRow, sal_uInt16 /*nColId*/ ) const +{ + OUString sText; + if ( nRow != BROWSER_ENDOFSELECTION && m_aGroupPositions[nRow] != NO_GROUP ) + { + try + { + uno::Reference< report::XGroup> xGroup = m_pParent->getGroup(m_aGroupPositions[nRow]); + OUString sExpression = xGroup->getExpression(); + + auto aIter = std::find_if(m_aColumnInfo.begin(), m_aColumnInfo.end(), + [&sExpression](const ColumnInfo& rColumnInfo) { return rColumnInfo.sColumnName == sExpression; }); + if (aIter != m_aColumnInfo.end() && !aIter->sLabel.isEmpty()) + sExpression = aIter->sLabel; + sText = sExpression; + } + catch (const uno::Exception&) + { + OSL_FAIL("Exception caught while getting expression value from the group"); + } + } + return sText; +} + +void OFieldExpressionControl::InitController( CellControllerRef& /*rController*/, long nRow, sal_uInt16 nColumnId ) +{ + weld::ComboBox& rComboBox = m_pComboCell->get_widget(); + rComboBox.set_entry_text(GetCellText(nRow, nColumnId)); +} + +bool OFieldExpressionControl::CursorMoving(long nNewRow, sal_uInt16 nNewCol) +{ + + if (!EditBrowseBox::CursorMoving(nNewRow, nNewCol)) + return false; + m_nDataPos = nNewRow; + long nOldDataPos = GetCurRow(); + InvalidateStatusCell( m_nDataPos ); + InvalidateStatusCell( nOldDataPos ); + + m_pParent->SaveData( nOldDataPos ); + m_pParent->DisplayData( m_nDataPos ); + return true; +} + +CellController* OFieldExpressionControl::GetController( long /*nRow*/, sal_uInt16 /*nColumnId*/ ) +{ + ComboBoxCellController* pCellController = new ComboBoxCellController( m_pComboCell ); + pCellController->GetComboBox().set_entry_editable(m_pParent->m_pController->isEditable()); + return pCellController; +} + +bool OFieldExpressionControl::SeekRow( long _nRow ) +{ + // the basis class needs the call, because that's how the class knows which line will be painted + EditBrowseBox::SeekRow(_nRow); + m_nCurrentPos = _nRow; + return true; +} + +void OFieldExpressionControl::PaintCell( OutputDevice& rDev, const tools::Rectangle& rRect, sal_uInt16 nColumnId ) const +{ + OUString aText =GetCellText( m_nCurrentPos, nColumnId ); + + Point aPos( rRect.TopLeft() ); + Size aTextSize( GetDataWindow().GetTextWidth( aText ), GetDataWindow().GetTextHeight() ); + + if( aPos.X() < rRect.Left() || aPos.X() + aTextSize.Width() > rRect.Right() || + aPos.Y() < rRect.Top() || aPos.Y() + aTextSize.Height() > rRect.Bottom() ) + rDev.SetClipRegion(vcl::Region(rRect)); + + rDev.DrawText( aPos, aText ); + + if( rDev.IsClipRegion() ) + rDev.SetClipRegion(); +} + +EditBrowseBox::RowStatus OFieldExpressionControl::GetRowStatus(long nRow) const +{ + if (nRow >= 0 && nRow == m_nDataPos) + return EditBrowseBox::CURRENT; + if ( nRow != BROWSER_ENDOFSELECTION && nRow < static_cast<long>(m_aGroupPositions.size()) && m_aGroupPositions[nRow] != NO_GROUP ) + { + try + { + uno::Reference< report::XGroup> xGroup = m_pParent->getGroup(m_aGroupPositions[nRow]); + return (xGroup->getHeaderOn() || xGroup->getFooterOn())? EditBrowseBox::HEADERFOOTER : EditBrowseBox::CLEAN; + } + catch(uno::Exception&) + { + OSL_FAIL("Exception caught while try to get a group!"); + } + } + return EditBrowseBox::CLEAN; +} + +// XContainerListener + +void OFieldExpressionControl::elementInserted(const container::ContainerEvent& evt) +{ + if ( m_bIgnoreEvent ) + return; + SolarMutexGuard aSolarGuard; + ::osl::MutexGuard aGuard( m_aMutex ); + sal_Int32 nGroupPos = 0; + if ( !(evt.Accessor >>= nGroupPos) ) + return; + + if ( nGroupPos >= GetRowCount() ) + { + sal_Int32 nAddedRows = nGroupPos - GetRowCount(); + RowInserted(nAddedRows); + for (sal_Int32 i = 0; i < nAddedRows; ++i) + m_aGroupPositions.push_back(NO_GROUP); + m_aGroupPositions[nGroupPos] = nGroupPos; + } + else + { + ::std::vector<sal_Int32>::iterator aFind = m_aGroupPositions.begin()+ nGroupPos; + if ( aFind == m_aGroupPositions.end() ) + aFind = ::std::find(m_aGroupPositions.begin(),m_aGroupPositions.end(),NO_GROUP); + + if ( aFind != m_aGroupPositions.end() ) + { + if ( *aFind != NO_GROUP ) + aFind = m_aGroupPositions.insert(aFind,nGroupPos); + else + *aFind = nGroupPos; + + ::std::vector<sal_Int32>::const_iterator aEnd = m_aGroupPositions.end(); + for(++aFind;aFind != aEnd;++aFind) + if ( *aFind != NO_GROUP ) + ++*aFind; + } + } + Invalidate(); +} + +void OFieldExpressionControl::elementRemoved(const container::ContainerEvent& evt) +{ + SolarMutexGuard aSolarGuard; + ::osl::MutexGuard aGuard( m_aMutex ); + + if ( m_bIgnoreEvent ) + return; + + sal_Int32 nGroupPos = 0; + if ( !(evt.Accessor >>= nGroupPos) ) + return; + + std::vector<sal_Int32>::iterator aEnd = m_aGroupPositions.end(); + std::vector<sal_Int32>::iterator aFind = std::find(m_aGroupPositions.begin(), aEnd, nGroupPos); + if (aFind != aEnd) + { + *aFind = NO_GROUP; + for(++aFind;aFind != aEnd;++aFind) + if ( *aFind != NO_GROUP ) + --*aFind; + Invalidate(); + } +} + +bool OFieldExpressionControl::IsDeleteAllowed( ) const +{ + return !m_pParent->isReadOnly() && GetSelectRowCount() > 0; +} + +void OFieldExpressionControl::KeyInput( const KeyEvent& rEvt ) +{ + if (IsDeleteAllowed()) + { + if (rEvt.GetKeyCode().GetCode() == KEY_DELETE && // Delete rows + !rEvt.GetKeyCode().IsShift() && + !rEvt.GetKeyCode().IsMod1()) + { + DeleteRows(); + return; + } + } + EditBrowseBox::KeyInput(rEvt); +} + +void OFieldExpressionControl::Command(const CommandEvent& rEvt) +{ + switch (rEvt.GetCommand()) + { + case CommandEventId::ContextMenu: + { + if (!rEvt.IsMouseEvent()) + { + EditBrowseBox::Command(rEvt); + return; + } + + sal_uInt16 nColId = GetColumnId(GetColumnAtXPosPixel(rEvt.GetMousePosPixel().X())); + + if ( nColId == HANDLE_ID ) + { + bool bEnable = false; + long nIndex = FirstSelectedRow(); + while( nIndex != SFX_ENDOFSELECTION && !bEnable ) + { + if ( m_aGroupPositions[nIndex] != NO_GROUP ) + bEnable = true; + nIndex = NextSelectedRow(); + } + VclBuilder aBuilder(nullptr, VclBuilderContainer::getUIRootDir(), "modules/dbreport/ui/groupsortmenu.ui", ""); + VclPtr<PopupMenu> aContextMenu(aBuilder.get_menu("menu")); + aContextMenu->EnableItem(aContextMenu->GetItemId("delete"), IsDeleteAllowed() && bEnable); + if (aContextMenu->Execute(this, rEvt.GetMousePosPixel())) + { + if( m_nDeleteEvent ) + Application::RemoveUserEvent( m_nDeleteEvent ); + m_nDeleteEvent = Application::PostUserEvent( LINK(this, OFieldExpressionControl, DelayedDelete), nullptr, true ); + } + } + [[fallthrough]]; + } + default: + EditBrowseBox::Command(rEvt); + } + +} + +void OFieldExpressionControl::DeleteRows() +{ + + bool bIsEditing = IsEditing(); + if (bIsEditing) + { + DeactivateCell(); + } + long nIndex = FirstSelectedRow(); + if (nIndex == SFX_ENDOFSELECTION) + { + nIndex = GetCurRow(); + } + bool bFirstTime = true; + + long nOldDataPos = nIndex; + uno::Sequence< beans::PropertyValue > aArgs(1); + aArgs[0].Name = PROPERTY_GROUP; + m_bIgnoreEvent = true; + while( nIndex >= 0 ) + { + if ( m_aGroupPositions[nIndex] != NO_GROUP ) + { + if ( bFirstTime ) + { + bFirstTime = false; + OUString sUndoAction(RptResId(RID_STR_UNDO_REMOVE_SELECTION)); + m_pParent->m_pController->getUndoManager().EnterListAction( sUndoAction, OUString(), 0, ViewShellId(-1) ); + } + + sal_Int32 nGroupPos = m_aGroupPositions[nIndex]; + uno::Reference< report::XGroup> xGroup = m_pParent->getGroup(nGroupPos); + aArgs[0].Value <<= xGroup; + // we use this way to create undo actions + m_pParent->m_pController->executeChecked(SID_GROUP_REMOVE,aArgs); + + std::vector<sal_Int32>::iterator aEnd = m_aGroupPositions.end(); + std::vector<sal_Int32>::iterator aFind = std::find(m_aGroupPositions.begin(), aEnd, nGroupPos); + if (aFind != aEnd) + { + *aFind = NO_GROUP; + for(++aFind;aFind != aEnd;++aFind) + if ( *aFind != NO_GROUP ) + --*aFind; + } + } + nIndex = NextSelectedRow(); + } + + if ( !bFirstTime ) + m_pParent->m_pController->getUndoManager().LeaveListAction(); + + m_nDataPos = GetCurRow(); + InvalidateStatusCell( nOldDataPos ); + InvalidateStatusCell( m_nDataPos ); + ActivateCell(); + m_pParent->DisplayData( m_nDataPos ); + m_bIgnoreEvent = false; + Invalidate(); +} + +IMPL_LINK_NOARG( OFieldExpressionControl, DelayedDelete, void*, void ) +{ + m_nDeleteEvent = nullptr; + DeleteRows(); +} + +Size OFieldExpressionControl::GetOptimalSize() const +{ + return LogicToPixel(Size(106, 75), MapMode(MapUnit::MapAppFont)); +} + +OGroupsSortingDialog::OGroupsSortingDialog(weld::Window* pParent, bool bReadOnly, + OReportController* pController) + : GenericDialogController(pParent, "modules/dbreport/ui/floatingsort.ui", "FloatingSort") + , OPropertyChangeListener(m_aMutex) + , m_pController(pController) + , m_xGroups(m_pController->getReportDefinition()->getGroups()) + , m_bReadOnly(bReadOnly) + , m_xToolBox(m_xBuilder->weld_toolbar("toolbox")) + , m_xProperties(m_xBuilder->weld_widget("properties")) + , m_xOrderLst(m_xBuilder->weld_combo_box("sorting")) + , m_xHeaderLst(m_xBuilder->weld_combo_box("header")) + , m_xFooterLst(m_xBuilder->weld_combo_box("footer")) + , m_xGroupOnLst(m_xBuilder->weld_combo_box("group")) + , m_xGroupIntervalEd(m_xBuilder->weld_spin_button("interval")) + , m_xKeepTogetherLst(m_xBuilder->weld_combo_box("keep")) + , m_xHelpWindow(m_xBuilder->weld_label("helptext")) + , m_xBox(m_xBuilder->weld_container("box")) + , m_xTableCtrlParent(m_xBox->CreateChildFrame()) + , m_xFieldExpression(VclPtr<OFieldExpressionControl>::Create(this, m_xTableCtrlParent)) +{ + m_xHelpWindow->set_size_request(-1, m_xHelpWindow->get_text_height() * 4); + m_xFieldExpression->set_hexpand(true); + m_xFieldExpression->set_vexpand(true); + + weld::Widget* pControlsLst[] = { m_xHeaderLst.get(), m_xFooterLst.get(), m_xGroupOnLst.get(), + m_xKeepTogetherLst.get(), m_xOrderLst.get(), m_xGroupIntervalEd.get() }; + for (weld::Widget* i : pControlsLst) + { + i->connect_focus_in(LINK(this, OGroupsSortingDialog, OnWidgetFocusGot)); + i->show(); + } + + m_xGroupIntervalEd->connect_focus_out(LINK(this, OGroupsSortingDialog, OnWidgetFocusLost)); + + for (size_t i = 0; i < SAL_N_ELEMENTS(pControlsLst) - 1; ++i) + dynamic_cast<weld::ComboBox&>(*pControlsLst[i]).connect_changed(LINK(this,OGroupsSortingDialog,LBChangeHdl)); + + m_pReportListener = new OPropertyChangeMultiplexer(this,m_pController->getReportDefinition().get()); + m_pReportListener->addProperty(PROPERTY_COMMAND); + m_pReportListener->addProperty(PROPERTY_COMMANDTYPE); + + m_xFieldExpression->lateInit(); + fillColumns(); + Size aPrefSize = m_xFieldExpression->GetOptimalSize(); + m_xBox->set_size_request(aPrefSize.Width(), aPrefSize.Height()); + m_xFieldExpression->Show(); + + m_xToolBox->connect_clicked(LINK(this, OGroupsSortingDialog, OnFormatAction)); + + checkButtons(0); +} + +OGroupsSortingDialog::~OGroupsSortingDialog() +{ + m_pReportListener->dispose(); + if ( m_pCurrentGroupListener.is() ) + m_pCurrentGroupListener->dispose(); + m_xFieldExpression.disposeAndClear(); + m_xTableCtrlParent->dispose(); + m_xTableCtrlParent.clear(); +} + +void OGroupsSortingDialog::UpdateData( ) +{ + m_xFieldExpression->Invalidate(); + long nCurRow = m_xFieldExpression->GetCurRow(); + m_xFieldExpression->DeactivateCell(); + m_xFieldExpression->ActivateCell(nCurRow, m_xFieldExpression->GetCurColumnId()); + DisplayData(nCurRow); +} + +void OGroupsSortingDialog::DisplayData( sal_Int32 _nRow ) +{ + const sal_Int32 nGroupPos = m_xFieldExpression->getGroupPosition(_nRow); + const bool bEmpty = nGroupPos == NO_GROUP; + m_xProperties->set_sensitive(!bEmpty); + + checkButtons(_nRow); + + if ( m_pCurrentGroupListener.is() ) + m_pCurrentGroupListener->dispose(); + m_pCurrentGroupListener = nullptr; + if (!bEmpty) + { + uno::Reference< report::XGroup> xGroup = getGroup(nGroupPos); + + m_pCurrentGroupListener = new OPropertyChangeMultiplexer(this,xGroup.get()); + m_pCurrentGroupListener->addProperty(PROPERTY_HEADERON); + m_pCurrentGroupListener->addProperty(PROPERTY_FOOTERON); + + displayGroup(xGroup); + } +} + +void OGroupsSortingDialog::SaveData( sal_Int32 _nRow) +{ + sal_Int32 nGroupPos = m_xFieldExpression->getGroupPosition(_nRow); + if ( nGroupPos == NO_GROUP ) + return; + + uno::Reference< report::XGroup> xGroup = getGroup(nGroupPos); + if (m_xHeaderLst->get_value_changed_from_saved()) + xGroup->setHeaderOn( m_xHeaderLst->get_active() == 0 ); + if (m_xFooterLst->get_value_changed_from_saved()) + xGroup->setFooterOn( m_xFooterLst->get_active() == 0 ); + if (m_xKeepTogetherLst->get_value_changed_from_saved()) + xGroup->setKeepTogether( m_xKeepTogetherLst->get_active() ); + if (m_xGroupOnLst->get_value_changed_from_saved()) + { + auto nGroupOn = m_xGroupOnLst->get_active_id().toInt32(); + xGroup->setGroupOn( nGroupOn ); + } + if (m_xGroupIntervalEd->get_value_changed_from_saved()) + { + xGroup->setGroupInterval(m_xGroupIntervalEd->get_value()); + m_xGroupIntervalEd->save_value(); + } + if ( m_xOrderLst->get_value_changed_from_saved() ) + xGroup->setSortAscending( m_xOrderLst->get_active() == 0 ); + + weld::ComboBox* pControls[] = { m_xHeaderLst.get(), m_xFooterLst.get(), m_xGroupOnLst.get(), + m_xKeepTogetherLst.get(), m_xOrderLst.get() }; + for (weld::ComboBox* pControl : pControls) + pControl->save_value(); +} + +sal_Int32 OGroupsSortingDialog::getColumnDataType(const OUString& _sColumnName) +{ + sal_Int32 nDataType = sdbc::DataType::VARCHAR; + try + { + if ( !m_xColumns.is() ) + fillColumns(); + if ( m_xColumns.is() && m_xColumns->hasByName(_sColumnName) ) + { + uno::Reference< beans::XPropertySet> xColumn(m_xColumns->getByName(_sColumnName),uno::UNO_QUERY); + if ( xColumn.is() ) + xColumn->getPropertyValue(PROPERTY_TYPE) >>= nDataType; + } + } + catch(uno::Exception&) + { + OSL_FAIL("Exception caught while getting the type of a column"); + } + + return nDataType; +} + +IMPL_LINK_NOARG(OGroupsSortingDialog, OnControlFocusGot, weld::Widget&, void ) +{ + m_xHelpWindow->set_label(RptResId(STR_RPT_HELP_FIELD)); +} + +IMPL_LINK(OGroupsSortingDialog, OnWidgetFocusGot, weld::Widget&, rControl, void ) +{ + const std::pair<weld::Widget*, const char*> pControls[] = { + { m_xHeaderLst.get(), STR_RPT_HELP_HEADER }, + { m_xFooterLst.get(), STR_RPT_HELP_FOOTER }, + { m_xGroupOnLst.get(), STR_RPT_HELP_GROUPON }, + { m_xGroupIntervalEd.get(), STR_RPT_HELP_INTERVAL }, + { m_xKeepTogetherLst.get(), STR_RPT_HELP_KEEP }, + { m_xOrderLst.get(), STR_RPT_HELP_SORT } + }; + for (size_t i = 0; i < SAL_N_ELEMENTS(pControls); ++i) + { + if (&rControl == pControls[i].first) + { + weld::ComboBox* pListBox = dynamic_cast<weld::ComboBox*>( &rControl ); + if ( pListBox ) + pListBox->save_value(); + weld::SpinButton* pNumericField = dynamic_cast<weld::SpinButton*>(&rControl); + if ( pNumericField ) + pNumericField->save_value(); + //shows the text given by the id in the multiline edit + m_xHelpWindow->set_label(RptResId(pControls[i].second)); + break; + } + } +} + +IMPL_LINK_NOARG(OGroupsSortingDialog, OnWidgetFocusLost, weld::Widget&, void) +{ + if (m_xFieldExpression) + { + if (m_xGroupIntervalEd->get_value_changed_from_saved()) + SaveData(m_xFieldExpression->GetCurRow()); + } +} + +IMPL_LINK(OGroupsSortingDialog, OnFormatAction, const OString&, rCommand, void) +{ + if ( !m_xFieldExpression ) + return; + + long nIndex = m_xFieldExpression->GetCurrRow(); + sal_Int32 nGroupPos = m_xFieldExpression->getGroupPosition(nIndex); + uno::Sequence<uno::Any> aClipboardList; + if ( nIndex >= 0 && nGroupPos != NO_GROUP ) + { + aClipboardList.realloc(1); + aClipboardList[0] = m_xGroups->getByIndex(nGroupPos); + } + if (rCommand == "up") + { + --nIndex; + } + if (rCommand == "down") + { + ++nIndex; + } + if (rCommand == "delete") + { + Application::PostUserEvent(LINK(m_xFieldExpression, OFieldExpressionControl, DelayedDelete)); + } + else + { + if ( nIndex >= 0 && aClipboardList.hasElements() ) + { + m_xFieldExpression->SetNoSelection(); + m_xFieldExpression->moveGroups(aClipboardList,nIndex,false); + m_xFieldExpression->DeactivateCell(); + m_xFieldExpression->GoToRow(nIndex); + m_xFieldExpression->ActivateCell(nIndex, m_xFieldExpression->GetCurColumnId()); + DisplayData(nIndex); + } + } +} + +IMPL_LINK( OGroupsSortingDialog, LBChangeHdl, weld::ComboBox&, rListBox, void ) +{ + if ( !rListBox.get_value_changed_from_saved() ) + return; + + sal_Int32 nRow = m_xFieldExpression->GetCurRow(); + sal_Int32 nGroupPos = m_xFieldExpression->getGroupPosition(nRow); + if (&rListBox != m_xHeaderLst.get() && &rListBox != m_xFooterLst.get()) + { + if ( rListBox.get_value_changed_from_saved() ) + SaveData(nRow); + if ( &rListBox == m_xGroupOnLst.get() ) + m_xGroupIntervalEd->set_sensitive(rListBox.get_active() != 0); + } + else if ( nGroupPos != NO_GROUP ) + { + uno::Reference< report::XGroup> xGroup = getGroup(nGroupPos); + uno::Sequence< beans::PropertyValue > aArgs(2); + aArgs[1].Name = PROPERTY_GROUP; + aArgs[1].Value <<= xGroup; + + if ( m_xHeaderLst.get() == &rListBox ) + aArgs[0].Name = PROPERTY_HEADERON; + else + aArgs[0].Name = PROPERTY_FOOTERON; + + aArgs[0].Value <<= rListBox.get_active() == 0; + m_pController->executeChecked(m_xHeaderLst.get() == &rListBox ? SID_GROUPHEADER : SID_GROUPFOOTER, aArgs); + m_xFieldExpression->InvalidateHandleColumn(); + } +} + +void OGroupsSortingDialog::_propertyChanged(const beans::PropertyChangeEvent& _rEvent) +{ + uno::Reference< report::XGroup > xGroup(_rEvent.Source,uno::UNO_QUERY); + if ( xGroup.is() ) + displayGroup(xGroup); + else + fillColumns(); +} + +void OGroupsSortingDialog::fillColumns() +{ + m_xColumns = m_pController->getColumns(); + m_xFieldExpression->fillColumns(m_xColumns); +} + +void OGroupsSortingDialog::displayGroup(const uno::Reference<report::XGroup>& _xGroup) +{ + m_xHeaderLst->set_active(_xGroup->getHeaderOn() ? 0 : 1 ); + m_xFooterLst->set_active(_xGroup->getFooterOn() ? 0 : 1 ); + sal_Int32 nDataType = getColumnDataType(_xGroup->getExpression()); + + // first clear whole group on list + while (m_xGroupOnLst->get_count() > 1 ) + { + m_xGroupOnLst->remove(1); + } + + switch(nDataType) + { + case sdbc::DataType::LONGVARCHAR: + case sdbc::DataType::VARCHAR: + case sdbc::DataType::CHAR: + m_xGroupOnLst->append(OUString::number(report::GroupOn::PREFIX_CHARACTERS), RptResId(STR_RPT_PREFIXCHARS)); + break; + case sdbc::DataType::DATE: + case sdbc::DataType::TIME: + case sdbc::DataType::TIMESTAMP: + { + const char* aIds[] = { STR_RPT_YEAR, STR_RPT_QUARTER,STR_RPT_MONTH,STR_RPT_WEEK,STR_RPT_DAY,STR_RPT_HOUR,STR_RPT_MINUTE }; + for (size_t i = 0; i < SAL_N_ELEMENTS(aIds); ++i) + { + m_xGroupOnLst->append(OUString::number(i+2), RptResId(aIds[i])); + } + } + break; + default: + m_xGroupOnLst->append(OUString::number(report::GroupOn::INTERVAL), RptResId(STR_RPT_INTERVAL)); + break; + } + sal_Int32 nPos = 0; + switch(_xGroup->getGroupOn()) + { + case report::GroupOn::DEFAULT: + nPos = 0; + break; + case report::GroupOn::PREFIX_CHARACTERS: + nPos = 1; + break; + case report::GroupOn::YEAR: + nPos = 1; + break; + case report::GroupOn::QUARTAL: + nPos = 2; + break; + case report::GroupOn::MONTH: + nPos = 3; + break; + case report::GroupOn::WEEK: + nPos = 4; + break; + case report::GroupOn::DAY: + nPos = 5; + break; + case report::GroupOn::HOUR: + nPos = 6; + break; + case report::GroupOn::MINUTE: + nPos = 7; + break; + case report::GroupOn::INTERVAL: + nPos = 1; + break; + default: + nPos = 0; + } + m_xGroupOnLst->set_active(nPos); + m_xGroupIntervalEd->set_value(_xGroup->getGroupInterval()); + m_xGroupIntervalEd->save_value(); + m_xGroupIntervalEd->set_sensitive( nPos != 0 ); + m_xKeepTogetherLst->set_active(_xGroup->getKeepTogether()); + m_xOrderLst->set_active(_xGroup->getSortAscending() ? 0 : 1); + + weld::ComboBox* pControls[] = { m_xHeaderLst.get(), m_xFooterLst.get(), m_xGroupOnLst.get(), + m_xKeepTogetherLst.get(), m_xOrderLst.get() }; + for (weld::ComboBox* pControl : pControls) + pControl->save_value(); + + bool bReadOnly = !m_pController->isEditable(); + for (weld::ComboBox* pControl : pControls) + pControl->set_sensitive(!bReadOnly); + m_xGroupIntervalEd->set_editable(!bReadOnly); +} + +void OGroupsSortingDialog::checkButtons(sal_Int32 _nRow) +{ + sal_Int32 nGroupCount = m_xGroups->getCount(); + sal_Int32 nRowCount = m_xFieldExpression->GetRowCount(); + bool bEnabled = nGroupCount > 1; + + if (bEnabled && _nRow > 0 ) + { + m_xToolBox->set_item_sensitive("up", true); + } + else + { + m_xToolBox->set_item_sensitive("up", false); + } + if (bEnabled && _nRow < (nRowCount - 1) ) + { + m_xToolBox->set_item_sensitive("down", true); + } + else + { + m_xToolBox->set_item_sensitive("down", false); + } + + sal_Int32 nGroupPos = m_xFieldExpression->getGroupPosition(_nRow); + if ( nGroupPos != NO_GROUP ) + { + bool bEnableDelete = nGroupCount > 0; + m_xToolBox->set_item_sensitive("delete", bEnableDelete); + } + else + { + m_xToolBox->set_item_sensitive("delete", false); + } +} + +} // rptui + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/reportdesign/source/ui/dlg/Navigator.cxx b/reportdesign/source/ui/dlg/Navigator.cxx new file mode 100644 index 000000000..d8f1323ac --- /dev/null +++ b/reportdesign/source/ui/dlg/Navigator.cxx @@ -0,0 +1,837 @@ +/* -*- 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 <Navigator.hxx> + +#include <strings.hxx> +#include <bitmaps.hlst> +#include <ReportController.hxx> +#include <UITools.hxx> +#include <reportformula.hxx> +#include <com/sun/star/report/XReportDefinition.hpp> +#include <com/sun/star/report/XFixedText.hpp> +#include <com/sun/star/report/XFixedLine.hpp> +#include <com/sun/star/report/XFormattedField.hpp> +#include <com/sun/star/report/XImageControl.hpp> +#include <com/sun/star/report/XShape.hpp> +#include <helpids.h> +#include <strings.hrc> +#include <rptui_slotid.hrc> +#include <comphelper/propmultiplex.hxx> +#include <comphelper/containermultiplexer.hxx> +#include <cppuhelper/basemutex.hxx> +#include <comphelper/SelectionMultiplex.hxx> +#include <vcl/svapp.hxx> +#include <vcl/weld.hxx> +#include <vcl/commandevent.hxx> +#include <ReportVisitor.hxx> +#include <core_resource.hxx> +#include <rtl/ref.hxx> +#include <svx/svxids.hrc> + +#include <memory> + +namespace rptui +{ +using namespace ::com::sun::star; +using namespace utl; +using namespace ::comphelper; + +static OUString lcl_getImageId(const uno::Reference< report::XReportComponent>& _xElement) +{ + OUString sId; + uno::Reference< report::XFixedLine> xFixedLine(_xElement,uno::UNO_QUERY); + if ( uno::Reference< report::XFixedText>(_xElement,uno::UNO_QUERY).is() ) + sId = RID_SVXBMP_FM_FIXEDTEXT; + else if ( xFixedLine.is() ) + sId = xFixedLine->getOrientation() ? OUStringLiteral(RID_SVXBMP_INSERT_VFIXEDLINE) : OUStringLiteral(RID_SVXBMP_INSERT_HFIXEDLINE); + else if ( uno::Reference< report::XFormattedField>(_xElement,uno::UNO_QUERY).is() ) + sId = RID_SVXBMP_FM_EDIT; + else if ( uno::Reference< report::XImageControl>(_xElement,uno::UNO_QUERY).is() ) + sId = RID_SVXBMP_FM_IMAGECONTROL; + else if ( uno::Reference< report::XShape>(_xElement,uno::UNO_QUERY).is() ) + sId = RID_SVXBMP_DRAWTBX_CS_BASIC; + return sId; +} + +static OUString lcl_getName(const uno::Reference< beans::XPropertySet>& _xElement) +{ + OSL_ENSURE(_xElement.is(),"Found report element which is NULL!"); + OUString sTempName; + _xElement->getPropertyValue(PROPERTY_NAME) >>= sTempName; + OUStringBuffer sName = sTempName; + uno::Reference< report::XFixedText> xFixedText(_xElement,uno::UNO_QUERY); + uno::Reference< report::XReportControlModel> xReportModel(_xElement,uno::UNO_QUERY); + if ( xFixedText.is() ) + { + sName.append(" : "); + sName.append(xFixedText->getLabel()); + } + else if ( xReportModel.is() && _xElement->getPropertySetInfo()->hasPropertyByName(PROPERTY_DATAFIELD) ) + { + ReportFormula aFormula( xReportModel->getDataField() ); + if ( aFormula.isValid() ) + { + sName.append(" : "); + sName.append( aFormula.getUndecoratedContent() ); + } + } + return sName.makeStringAndClear(); +} + +namespace { + +class NavigatorTree : public ::cppu::BaseMutex + , public reportdesign::ITraverseReport + , public comphelper::OSelectionChangeListener + , public ::comphelper::OPropertyChangeListener +{ + class UserData; + friend class UserData; + class UserData : public ::cppu::BaseMutex + ,public ::comphelper::OPropertyChangeListener + ,public ::comphelper::OContainerListener + { + uno::Reference< uno::XInterface > m_xContent; + ::rtl::Reference< comphelper::OPropertyChangeMultiplexer> m_pListener; + ::rtl::Reference< comphelper::OContainerListenerAdapter> m_pContainerListener; + NavigatorTree* m_pTree; + public: + UserData(NavigatorTree* pTree, const uno::Reference<uno::XInterface>& xContent); + virtual ~UserData() override; + + const uno::Reference< uno::XInterface >& getContent() const { return m_xContent; } + void setContent(const uno::Reference< uno::XInterface >& _xContent) { m_xContent = _xContent; } + + protected: + // OPropertyChangeListener + virtual void _propertyChanged(const beans::PropertyChangeEvent& _rEvent) override; + + // OContainerListener + virtual void _elementInserted( const container::ContainerEvent& _rEvent ) override; + virtual void _elementRemoved( const container::ContainerEvent& Event ) override; + virtual void _elementReplaced( const container::ContainerEvent& _rEvent ) override; + virtual void _disposing(const lang::EventObject& _rSource) override; + }; + + std::unique_ptr<weld::TreeView> m_xTreeView; + OReportController& m_rController; + std::unique_ptr<weld::TreeIter> m_xMasterReport; + ::rtl::Reference< comphelper::OPropertyChangeMultiplexer> m_pReportListener; + ::rtl::Reference< comphelper::OSelectionChangeMultiplexer> m_pSelectionListener; + + void insertEntry(const OUString& rName, weld::TreeIter* pParent, const OUString& rImageId, int nPosition, UserData* pData, weld::TreeIter& rRet); + + void traverseSection(const uno::Reference<report::XSection>& xSection, weld::TreeIter* pParent, const OUString& rImageId, int nPosition = -1); + void traverseFunctions(const uno::Reference< report::XFunctions>& xFunctions, weld::TreeIter* pParent); + +protected: + // OSelectionChangeListener + virtual void _disposing(const lang::EventObject& _rSource) override; + + // OPropertyChangeListener + virtual void _propertyChanged(const beans::PropertyChangeEvent& _rEvent) override; + + // OContainerListener Helper + void _elementInserted( const container::ContainerEvent& _rEvent ); + void _elementRemoved( const container::ContainerEvent& Event ); + void _elementReplaced( const container::ContainerEvent& _rEvent ); + +public: + NavigatorTree(std::unique_ptr<weld::TreeView>, OReportController& rController); + virtual ~NavigatorTree() override; + + DECL_LINK(OnEntrySelDesel, weld::TreeView&, void); + DECL_LINK(CommandHdl, const CommandEvent&, bool); + + virtual void _selectionChanged( const lang::EventObject& aEvent ) override; + + // ITraverseReport + virtual void traverseReport(const uno::Reference< report::XReportDefinition>& xReport) override; + virtual void traverseReportFunctions(const uno::Reference< report::XFunctions>& xFunctions) override; + virtual void traverseReportHeader(const uno::Reference< report::XSection>& xSection) override; + virtual void traverseReportFooter(const uno::Reference< report::XSection>& xSection) override; + virtual void traversePageHeader(const uno::Reference< report::XSection>& xSection) override; + virtual void traversePageFooter(const uno::Reference< report::XSection>& xSection) override; + + virtual void traverseGroups(const uno::Reference< report::XGroups>& xGroups) override; + virtual void traverseGroup(const uno::Reference< report::XGroup>& xGroup) override; + virtual void traverseGroupFunctions(const uno::Reference< report::XFunctions>& xFunctions) override; + virtual void traverseGroupHeader(const uno::Reference< report::XSection>& xSection) override; + virtual void traverseGroupFooter(const uno::Reference< report::XSection>& xSection) override; + + virtual void traverseDetail(const uno::Reference< report::XSection>& xSection) override; + + bool find(const uno::Reference<uno::XInterface>& xContent, weld::TreeIter& rIter); + void removeEntry(weld::TreeIter& rEntry, bool bRemove = true); + + void grab_focus() { m_xTreeView->grab_focus(); } + + void set_text(const weld::TreeIter& rIter, const OUString& rStr) + { + m_xTreeView->set_text(rIter, rStr); + } + + void expand_row(const weld::TreeIter& rIter) + { + m_xTreeView->expand_row(rIter); + } + + std::unique_ptr<weld::TreeIter> make_iterator() const + { + return m_xTreeView->make_iterator(); + } + + int iter_n_children(const weld::TreeIter& rIter) const + { + return m_xTreeView->iter_n_children(rIter); + } +}; + +} + +NavigatorTree::NavigatorTree(std::unique_ptr<weld::TreeView> xTreeView, OReportController& rController) + : comphelper::OSelectionChangeListener() + , OPropertyChangeListener(m_aMutex) + , m_xTreeView(std::move(xTreeView)) + , m_rController(rController) +{ + m_xTreeView->set_size_request(m_xTreeView->get_approximate_digit_width() * 25, m_xTreeView->get_height_rows(18)); + + m_pReportListener = new OPropertyChangeMultiplexer(this,m_rController.getReportDefinition().get()); + m_pReportListener->addProperty(PROPERTY_PAGEHEADERON); + m_pReportListener->addProperty(PROPERTY_PAGEFOOTERON); + m_pReportListener->addProperty(PROPERTY_REPORTHEADERON); + m_pReportListener->addProperty(PROPERTY_REPORTFOOTERON); + + m_pSelectionListener = new OSelectionChangeMultiplexer(this,&m_rController); + + m_xTreeView->set_help_id(HID_REPORT_NAVIGATOR_TREE); + + m_xTreeView->set_selection_mode(SelectionMode::Multiple); + + m_xTreeView->connect_changed(LINK(this, NavigatorTree, OnEntrySelDesel)); + m_xTreeView->connect_popup_menu(LINK(this, NavigatorTree, CommandHdl)); +} + +NavigatorTree::~NavigatorTree() +{ + m_xTreeView->all_foreach([this](weld::TreeIter& rIter) { + UserData* pData = reinterpret_cast<UserData*>(m_xTreeView->get_id(rIter).toInt64()); + delete pData; + return false; + }); + m_pReportListener->dispose(); +} + +namespace +{ + sal_uInt16 mapIdent(const OString& rIdent) + { + if (rIdent == "sorting") + return SID_SORTINGANDGROUPING; + else if (rIdent == "page") + return SID_PAGEHEADERFOOTER; + else if (rIdent == "report") + return SID_REPORTHEADERFOOTER; + else if (rIdent == "function") + return SID_RPT_NEW_FUNCTION; + else if (rIdent == "properties") + return SID_SHOW_PROPERTYBROWSER; + else if (rIdent == "delete") + return SID_DELETE; + return 0; + } +} + +IMPL_LINK(NavigatorTree, CommandHdl, const CommandEvent&, rEvt, bool) +{ + bool bHandled = false; + switch( rEvt.GetCommand()) + { + case CommandEventId::ContextMenu: + { + UserData* pData = reinterpret_cast<UserData*>(m_xTreeView->get_selected_id().toInt64()); + if (!pData) + break; + + uno::Reference< report::XFunctionsSupplier> xSupplier(pData->getContent(),uno::UNO_QUERY); + uno::Reference< report::XFunctions> xFunctions(pData->getContent(),uno::UNO_QUERY); + uno::Reference< report::XGroup> xGroup(pData->getContent(),uno::UNO_QUERY); + bool bDeleteAllowed = m_rController.isEditable() && (xGroup.is() || + uno::Reference< report::XFunction>(pData->getContent(),uno::UNO_QUERY).is()); + + std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(m_xTreeView.get(), "modules/dbreport/ui/navigatormenu.ui")); + std::unique_ptr<weld::Menu> xContextMenu(xBuilder->weld_menu("menu")); + + const OString aIds[] = { "sorting", "page", "report", "function", "properties", "delete" }; + for (size_t i = 0; i < SAL_N_ELEMENTS(aIds); ++i) + { + sal_uInt16 nSId = mapIdent(aIds[i]); + + if (aIds[i] == "page" || aIds[i] == "report" || aIds[i] == "properties") + xContextMenu->set_active(aIds[i], m_rController.isCommandChecked(nSId)); + bool bEnabled = m_rController.isCommandEnabled(nSId); + if (nSId == SID_RPT_NEW_FUNCTION) + xContextMenu->set_sensitive(aIds[i], m_rController.isEditable() && (xSupplier.is() || xFunctions.is())); + // special condition, check for function and group + else if (nSId == SID_DELETE) + xContextMenu->set_sensitive(aIds[i], bDeleteAllowed); + else + xContextMenu->set_sensitive(aIds[i], bEnabled); + } + + // the point that was clicked on + ::Point aWhere(rEvt.GetMousePosPixel()); + OString sCurItemIdent = xContextMenu->popup_at_rect(m_xTreeView.get(), tools::Rectangle(aWhere, Size(1,1))); + if (!sCurItemIdent.isEmpty()) + { + sal_uInt16 nId = mapIdent(sCurItemIdent); + uno::Sequence< beans::PropertyValue> aArgs; + if ( nId == SID_RPT_NEW_FUNCTION ) + { + aArgs.realloc(1); + aArgs[0].Value <<= (xFunctions.is() ? xFunctions : xSupplier->getFunctions()); + } + else if ( nId == SID_DELETE ) + { + if ( xGroup.is() ) + nId = SID_GROUP_REMOVE; + aArgs.realloc(1); + aArgs[0].Name = PROPERTY_GROUP; + aArgs[0].Value <<= pData->getContent(); + } + m_rController.executeUnChecked(nId,aArgs); + } + + bHandled = true; + } + break; + default: break; + } + + return bHandled; +} + +IMPL_LINK_NOARG(NavigatorTree, OnEntrySelDesel, weld::TreeView&, void) +{ + if ( !m_pSelectionListener->locked() ) + { + m_pSelectionListener->lock(); + std::unique_ptr<weld::TreeIter> xEntry = m_xTreeView->make_iterator(); + bool bEntry = m_xTreeView->get_cursor(xEntry.get()); + uno::Any aSelection; + if (bEntry && m_xTreeView->is_selected(*xEntry)) + aSelection <<= reinterpret_cast<UserData*>(m_xTreeView->get_id(*xEntry).toInt64())->getContent(); + m_rController.select(aSelection); + m_pSelectionListener->unlock(); + } +} + +void NavigatorTree::_selectionChanged( const lang::EventObject& aEvent ) +{ + m_pSelectionListener->lock(); + uno::Reference< view::XSelectionSupplier> xSelectionSupplier(aEvent.Source,uno::UNO_QUERY); + uno::Any aSec = xSelectionSupplier->getSelection(); + uno::Sequence< uno::Reference< report::XReportComponent > > aSelection; + aSec >>= aSelection; + std::unique_ptr<weld::TreeIter> xEntry = m_xTreeView->make_iterator(); + if ( !aSelection.hasElements() ) + { + uno::Reference< uno::XInterface> xSelection(aSec,uno::UNO_QUERY); + bool bEntry = find(xSelection, *xEntry); + if (bEntry && !m_xTreeView->is_selected(*xEntry)) + { + m_xTreeView->select(*xEntry); + m_xTreeView->set_cursor(*xEntry); + } + else if (!bEntry) + m_xTreeView->unselect_all(); + } + else + { + for (const uno::Reference<report::XReportComponent>& rElem : std::as_const(aSelection)) + { + bool bEntry = find(rElem, *xEntry); + if (bEntry && !m_xTreeView->is_selected(*xEntry)) + { + m_xTreeView->select(*xEntry); + m_xTreeView->set_cursor(*xEntry); + } + } + } + m_pSelectionListener->unlock(); +} + +void NavigatorTree::insertEntry(const OUString& rName, weld::TreeIter* pParent, const OUString& rImageId, + int nPosition, UserData* pData, weld::TreeIter& rRet) +{ + OUString sId = pData ? OUString::number(reinterpret_cast<sal_Int64>(pData)) : OUString(); + m_xTreeView->insert(pParent, nPosition, &rName, &sId, nullptr, nullptr, nullptr, false, &rRet); + if (!rImageId.isEmpty()) + m_xTreeView->set_image(rRet, rImageId); +} + +void NavigatorTree::traverseSection(const uno::Reference<report::XSection>& xSection, weld::TreeIter* pParent, const OUString& rImageId, int nPosition) +{ + std::unique_ptr<weld::TreeIter> xSectionIter = m_xTreeView->make_iterator(); + std::unique_ptr<weld::TreeIter> xScratch = m_xTreeView->make_iterator(); + insertEntry(xSection->getName(), pParent, rImageId, nPosition, new UserData(this, xSection), *xSectionIter); + const sal_Int32 nCount = xSection->getCount(); + for (sal_Int32 i = 0; i < nCount; ++i) + { + uno::Reference< report::XReportComponent> xElement(xSection->getByIndex(i), uno::UNO_QUERY_THROW); + insertEntry(lcl_getName(xElement.get()), xSectionIter.get(), lcl_getImageId(xElement), -1, new UserData(this, xElement), *xScratch); + uno::Reference< report::XReportDefinition> xSubReport(xElement,uno::UNO_QUERY); + if ( xSubReport.is() ) + { + bool bMasterReport = find(xSection->getReportDefinition(), *xScratch); + if (!bMasterReport) + m_xMasterReport.reset(); + else + m_xMasterReport = m_xTreeView->make_iterator(xScratch.get()); + reportdesign::OReportVisitor aSubVisitor(this); + aSubVisitor.start(xSubReport); + } + } +} + +void NavigatorTree::traverseFunctions(const uno::Reference< report::XFunctions>& xFunctions, weld::TreeIter* pParent) +{ + std::unique_ptr<weld::TreeIter> xFunctionIter = m_xTreeView->make_iterator(); + std::unique_ptr<weld::TreeIter> xScratch = m_xTreeView->make_iterator(); + insertEntry(RptResId(RID_STR_FUNCTIONS), pParent, RID_SVXBMP_RPT_NEW_FUNCTION, -1, new UserData(this, xFunctions), *xFunctionIter); + const sal_Int32 nCount = xFunctions->getCount(); + for (sal_Int32 i = 0; i< nCount; ++i) + { + uno::Reference< report::XFunction> xElement(xFunctions->getByIndex(i),uno::UNO_QUERY); + insertEntry(xElement->getName(), xFunctionIter.get(), RID_SVXBMP_RPT_NEW_FUNCTION, -1, new UserData(this,xElement), *xScratch); + } +} + +bool NavigatorTree::find(const uno::Reference<uno::XInterface>& xContent, weld::TreeIter& rRet) +{ + bool bRet = false; + if (xContent.is()) + { + m_xTreeView->all_foreach([this, &xContent, &bRet, &rRet](weld::TreeIter& rIter) { + UserData* pData = reinterpret_cast<UserData*>(m_xTreeView->get_id(rIter).toInt64()); + if (pData->getContent() == xContent) + { + m_xTreeView->copy_iterator(rIter, rRet); + bRet = true; + return true; + } + return false; + }); + } + return bRet; +} + +// ITraverseReport + +void NavigatorTree::traverseReport(const uno::Reference< report::XReportDefinition>& xReport) +{ + std::unique_ptr<weld::TreeIter> xScratch = m_xTreeView->make_iterator(); + insertEntry(xReport->getName(), m_xMasterReport.get(), RID_SVXBMP_SELECT_REPORT,-1, new UserData(this, xReport), *xScratch); +} + +void NavigatorTree::traverseReportFunctions(const uno::Reference< report::XFunctions>& xFunctions) +{ + std::unique_ptr<weld::TreeIter> xReport = m_xTreeView->make_iterator(); + bool bReport = find(xFunctions->getParent(), *xReport); + if (!bReport) + xReport.reset(); + traverseFunctions(xFunctions, xReport.get()); +} + +void NavigatorTree::traverseReportHeader(const uno::Reference< report::XSection>& xSection) +{ + std::unique_ptr<weld::TreeIter> xReport = m_xTreeView->make_iterator(); + bool bReport = find(xSection->getReportDefinition(), *xReport); + if (!bReport) + xReport.reset(); + traverseSection(xSection, xReport.get(), RID_SVXBMP_REPORTHEADERFOOTER); +} + +void NavigatorTree::traverseReportFooter(const uno::Reference< report::XSection>& xSection) +{ + std::unique_ptr<weld::TreeIter> xReport = m_xTreeView->make_iterator(); + bool bReport = find(xSection->getReportDefinition(), *xReport); + if (!bReport) + xReport.reset(); + traverseSection(xSection, xReport.get(), RID_SVXBMP_REPORTHEADERFOOTER); +} + +void NavigatorTree::traversePageHeader(const uno::Reference< report::XSection>& xSection) +{ + std::unique_ptr<weld::TreeIter> xReport = m_xTreeView->make_iterator(); + bool bReport = find(xSection->getReportDefinition(), *xReport); + if (!bReport) + xReport.reset(); + traverseSection(xSection, xReport.get(), RID_SVXBMP_PAGEHEADERFOOTER); +} + +void NavigatorTree::traversePageFooter(const uno::Reference< report::XSection>& xSection) +{ + std::unique_ptr<weld::TreeIter> xReport = m_xTreeView->make_iterator(); + bool bReport = find(xSection->getReportDefinition(), *xReport); + if (!bReport) + xReport.reset(); + traverseSection(xSection, xReport.get(), RID_SVXBMP_PAGEHEADERFOOTER); +} + +void NavigatorTree::traverseGroups(const uno::Reference< report::XGroups>& xGroups) +{ + std::unique_ptr<weld::TreeIter> xReport = m_xTreeView->make_iterator(); + bool bReport = find(xGroups->getReportDefinition(), *xReport); + if (!bReport) + xReport.reset(); + std::unique_ptr<weld::TreeIter> xScratch = m_xTreeView->make_iterator(); + insertEntry(RptResId(RID_STR_GROUPS), xReport.get(), RID_SVXBMP_SORTINGANDGROUPING, -1, new UserData(this, xGroups), *xScratch); +} + +void NavigatorTree::traverseGroup(const uno::Reference< report::XGroup>& xGroup) +{ + uno::Reference< report::XGroups> xGroups(xGroup->getParent(),uno::UNO_QUERY); + std::unique_ptr<weld::TreeIter> xGroupsIter = m_xTreeView->make_iterator(); + bool bGroups = find(xGroups, *xGroupsIter); + OSL_ENSURE(bGroups, "No Groups inserted so far. Why!"); + if (!bGroups) + xGroupsIter.reset(); + std::unique_ptr<weld::TreeIter> xScratch = m_xTreeView->make_iterator(); + insertEntry(xGroup->getExpression(), xGroupsIter.get(), RID_SVXBMP_GROUP, rptui::getPositionInIndexAccess(xGroups.get(),xGroup), new UserData(this,xGroup), *xScratch); +} + +void NavigatorTree::traverseGroupFunctions(const uno::Reference< report::XFunctions>& xFunctions) +{ + std::unique_ptr<weld::TreeIter> xReport = m_xTreeView->make_iterator(); + bool bReport = find(xFunctions->getParent(), *xReport); + if (!bReport) + xReport.reset(); + traverseFunctions(xFunctions, xReport.get()); +} + +void NavigatorTree::traverseGroupHeader(const uno::Reference< report::XSection>& xSection) +{ + std::unique_ptr<weld::TreeIter> xReport = m_xTreeView->make_iterator(); + bool bReport = find(xSection->getGroup(), *xReport); + OSL_ENSURE(bReport, "No group found"); + if (!bReport) + xReport.reset(); + traverseSection(xSection, xReport.get(), RID_SVXBMP_GROUPHEADER, 1); +} + +void NavigatorTree::traverseGroupFooter(const uno::Reference< report::XSection>& xSection) +{ + std::unique_ptr<weld::TreeIter> xReport = m_xTreeView->make_iterator(); + bool bReport = find(xSection->getGroup(), *xReport); + OSL_ENSURE(bReport, "No group found"); + if (!bReport) + xReport.reset(); + traverseSection(xSection, xReport.get(), RID_SVXBMP_GROUPFOOTER); +} + +void NavigatorTree::traverseDetail(const uno::Reference< report::XSection>& xSection) +{ + uno::Reference< report::XReportDefinition> xReport = xSection->getReportDefinition(); + std::unique_ptr<weld::TreeIter> xParent = m_xTreeView->make_iterator(); + bool bParent = find(xReport, *xParent); + if (!bParent) + xParent.reset(); + traverseSection(xSection, xParent.get(), RID_SVXBMP_ICON_DETAIL); +} + +void NavigatorTree::_propertyChanged(const beans::PropertyChangeEvent& _rEvent) +{ + uno::Reference< report::XReportDefinition> xReport(_rEvent.Source,uno::UNO_QUERY); + if ( !xReport.is() ) + return; + + bool bEnabled = false; + _rEvent.NewValue >>= bEnabled; + if ( !bEnabled ) + return; + + std::unique_ptr<weld::TreeIter> xParent = m_xTreeView->make_iterator(); + bool bParent = find(xReport, *xParent); + if (!bParent) + xParent.reset(); + if ( _rEvent.PropertyName == PROPERTY_REPORTHEADERON ) + { + sal_uLong nPos = xReport->getReportHeaderOn() ? 2 : 1; + traverseSection(xReport->getReportHeader(),xParent.get(),RID_SVXBMP_REPORTHEADERFOOTER,nPos); + } + else if ( _rEvent.PropertyName == PROPERTY_PAGEHEADERON ) + { + traverseSection(xReport->getPageHeader(),xParent.get(), RID_SVXBMP_PAGEHEADERFOOTER,1); + } + else if ( _rEvent.PropertyName == PROPERTY_PAGEFOOTERON ) + traverseSection(xReport->getPageFooter(),xParent.get(), RID_SVXBMP_PAGEHEADERFOOTER); + else if ( _rEvent.PropertyName == PROPERTY_REPORTFOOTERON ) + { + int nPos = -1; + if (xReport->getPageFooterOn() && xParent) + nPos = m_xTreeView->iter_n_children(*xParent) - 1; + traverseSection(xReport->getReportFooter(),xParent.get(),RID_SVXBMP_REPORTHEADERFOOTER,nPos); + } +} + +void NavigatorTree::_elementInserted( const container::ContainerEvent& _rEvent ) +{ + std::unique_ptr<weld::TreeIter> xEntry = m_xTreeView->make_iterator(); + bool bEntry = find(_rEvent.Source, *xEntry); + if (!bEntry) + xEntry.reset(); + uno::Reference<beans::XPropertySet> xProp(_rEvent.Element,uno::UNO_QUERY_THROW); + OUString sName; + uno::Reference< beans::XPropertySetInfo> xInfo = xProp->getPropertySetInfo(); + if ( xInfo.is() ) + { + if ( xInfo->hasPropertyByName(PROPERTY_NAME) ) + xProp->getPropertyValue(PROPERTY_NAME) >>= sName; + else if ( xInfo->hasPropertyByName(PROPERTY_EXPRESSION) ) + xProp->getPropertyValue(PROPERTY_EXPRESSION) >>= sName; + } + uno::Reference< report::XGroup> xGroup(xProp,uno::UNO_QUERY); + if ( xGroup.is() ) + { + reportdesign::OReportVisitor aSubVisitor(this); + aSubVisitor.start(xGroup); + } + else + { + uno::Reference< report::XReportComponent> xElement(xProp,uno::UNO_QUERY); + if ( xProp.is() ) + sName = lcl_getName(xProp); + std::unique_ptr<weld::TreeIter> xScratch = m_xTreeView->make_iterator(); + insertEntry(sName, xEntry.get(), (!xElement.is() ? OUString(RID_SVXBMP_RPT_NEW_FUNCTION) : lcl_getImageId(xElement)), + -1, new UserData(this,xProp), *xScratch); + } + if (bEntry && !m_xTreeView->get_row_expanded(*xEntry)) + m_xTreeView->expand_row(*xEntry); +} + +void NavigatorTree::_elementRemoved( const container::ContainerEvent& _rEvent ) +{ + uno::Reference<beans::XPropertySet> xProp(_rEvent.Element,uno::UNO_QUERY); + std::unique_ptr<weld::TreeIter> xEntry = m_xTreeView->make_iterator(); + bool bEntry = find(xProp, *xEntry); + OSL_ENSURE(bEntry,"NavigatorTree::_elementRemoved: No Entry found!"); + + if (bEntry) + { + removeEntry(*xEntry); + } +} + +void NavigatorTree::_elementReplaced( const container::ContainerEvent& _rEvent ) +{ + uno::Reference<beans::XPropertySet> xProp(_rEvent.ReplacedElement,uno::UNO_QUERY); + std::unique_ptr<weld::TreeIter> xEntry = m_xTreeView->make_iterator(); + bool bEntry = find(xProp, *xEntry); + if (bEntry) + { + UserData* pData = reinterpret_cast<UserData*>(m_xTreeView->get_id(*xEntry).toInt64()); + xProp.set(_rEvent.Element,uno::UNO_QUERY); + pData->setContent(xProp); + OUString sName; + xProp->getPropertyValue(PROPERTY_NAME) >>= sName; + m_xTreeView->set_text(*xEntry, sName); + } +} + +void NavigatorTree::_disposing(const lang::EventObject& _rSource) +{ + std::unique_ptr<weld::TreeIter> xEntry = m_xTreeView->make_iterator(); + if (find(_rSource.Source, *xEntry)) + removeEntry(*xEntry); +} + +void NavigatorTree::removeEntry(weld::TreeIter& rEntry, bool bRemove) +{ + std::unique_ptr<weld::TreeIter> xChild = m_xTreeView->make_iterator(&rEntry); + bool bChild = m_xTreeView->iter_children(*xChild); + while (bChild) + { + removeEntry(*xChild, false); + bChild = m_xTreeView->iter_next_sibling(*xChild); + } + delete reinterpret_cast<UserData*>(m_xTreeView->get_id(rEntry).toInt64()); + if (bRemove) + m_xTreeView->remove(rEntry); +} + +NavigatorTree::UserData::UserData(NavigatorTree* pTree,const uno::Reference<uno::XInterface>& xContent) + : OPropertyChangeListener(m_aMutex) + , OContainerListener(m_aMutex) + , m_xContent(xContent) + , m_pTree(pTree) +{ + uno::Reference<beans::XPropertySet> xProp(m_xContent,uno::UNO_QUERY); + if ( xProp.is() ) + { + uno::Reference< beans::XPropertySetInfo> xInfo = xProp->getPropertySetInfo(); + if ( xInfo.is() ) + { + m_pListener = new ::comphelper::OPropertyChangeMultiplexer(this,xProp); + if ( xInfo->hasPropertyByName(PROPERTY_NAME) ) + m_pListener->addProperty(PROPERTY_NAME); + else if ( xInfo->hasPropertyByName(PROPERTY_EXPRESSION) ) + m_pListener->addProperty(PROPERTY_EXPRESSION); + if ( xInfo->hasPropertyByName(PROPERTY_DATAFIELD) ) + m_pListener->addProperty(PROPERTY_DATAFIELD); + if ( xInfo->hasPropertyByName(PROPERTY_LABEL) ) + m_pListener->addProperty(PROPERTY_LABEL); + if ( xInfo->hasPropertyByName(PROPERTY_HEADERON) ) + m_pListener->addProperty(PROPERTY_HEADERON); + if ( xInfo->hasPropertyByName(PROPERTY_FOOTERON) ) + m_pListener->addProperty(PROPERTY_FOOTERON); + } + } + uno::Reference< container::XContainer> xContainer(m_xContent,uno::UNO_QUERY); + if ( xContainer.is() ) + { + m_pContainerListener = new ::comphelper::OContainerListenerAdapter(this,xContainer); + } +} + +NavigatorTree::UserData::~UserData() +{ + if ( m_pContainerListener.is() ) + m_pContainerListener->dispose(); + if ( m_pListener.is() ) + m_pListener->dispose(); +} + +// OPropertyChangeListener +void NavigatorTree::UserData::_propertyChanged(const beans::PropertyChangeEvent& _rEvent) +{ + std::unique_ptr<weld::TreeIter> xEntry = m_pTree->make_iterator(); + bool bEntry = m_pTree->find(_rEvent.Source, *xEntry); + OSL_ENSURE(bEntry,"No entry could be found! Why not!"); + if (!bEntry) + return; + const bool bFooterOn = (PROPERTY_FOOTERON == _rEvent.PropertyName); + try + { + if ( bFooterOn || PROPERTY_HEADERON == _rEvent.PropertyName ) + { + sal_Int32 nPos = 1; + uno::Reference< report::XGroup> xGroup(_rEvent.Source,uno::UNO_QUERY); + ::std::function<bool(OGroupHelper *)> pIsOn = ::std::mem_fn(&OGroupHelper::getHeaderOn); + ::std::function<uno::Reference<report::XSection>(OGroupHelper *)> pMemFunSection = ::std::mem_fn(&OGroupHelper::getHeader); + if ( bFooterOn ) + { + pIsOn = ::std::mem_fn(&OGroupHelper::getFooterOn); + pMemFunSection = ::std::mem_fn(&OGroupHelper::getFooter); + nPos = m_pTree->iter_n_children(*xEntry) - 1; + } + + OGroupHelper aGroupHelper(xGroup); + if ( pIsOn(&aGroupHelper) ) + { + if ( bFooterOn ) + ++nPos; + m_pTree->traverseSection(pMemFunSection(&aGroupHelper),xEntry.get(),bFooterOn ? OUString(RID_SVXBMP_GROUPFOOTER) : OUString(RID_SVXBMP_GROUPHEADER),nPos); + } + } + else if ( PROPERTY_EXPRESSION == _rEvent.PropertyName) + { + OUString sNewName; + _rEvent.NewValue >>= sNewName; + m_pTree->set_text(*xEntry, sNewName); + } + else if ( PROPERTY_DATAFIELD == _rEvent.PropertyName || PROPERTY_LABEL == _rEvent.PropertyName || PROPERTY_NAME == _rEvent.PropertyName ) + { + uno::Reference<beans::XPropertySet> xProp(_rEvent.Source,uno::UNO_QUERY); + m_pTree->set_text(*xEntry, lcl_getName(xProp)); + } + } + catch(const uno::Exception &) + {} +} + +void NavigatorTree::UserData::_elementInserted( const container::ContainerEvent& _rEvent ) +{ + m_pTree->_elementInserted( _rEvent ); +} + +void NavigatorTree::UserData::_elementRemoved( const container::ContainerEvent& _rEvent ) +{ + m_pTree->_elementRemoved( _rEvent ); +} + +void NavigatorTree::UserData::_elementReplaced( const container::ContainerEvent& _rEvent ) +{ + m_pTree->_elementReplaced( _rEvent ); +} + +void NavigatorTree::UserData::_disposing(const lang::EventObject& _rSource) +{ + m_pTree->_disposing( _rSource ); +} + +class ONavigatorImpl +{ +public: + ONavigatorImpl(OReportController& rController, weld::Builder& rBuilder); + ONavigatorImpl(const ONavigatorImpl&) = delete; + ONavigatorImpl& operator=(const ONavigatorImpl&) = delete; + + uno::Reference< report::XReportDefinition> m_xReport; + std::unique_ptr<NavigatorTree> m_xNavigatorTree; +}; + +ONavigatorImpl::ONavigatorImpl(OReportController& rController, weld::Builder& rBuilder) + : m_xReport(rController.getReportDefinition()) + , m_xNavigatorTree(std::make_unique<NavigatorTree>(rBuilder.weld_tree_view("treeview"), rController)) +{ + reportdesign::OReportVisitor aVisitor(m_xNavigatorTree.get()); + aVisitor.start(m_xReport); + std::unique_ptr<weld::TreeIter> xScratch = m_xNavigatorTree->make_iterator(); + if (m_xNavigatorTree->find(m_xReport, *xScratch)) + m_xNavigatorTree->expand_row(*xScratch); + lang::EventObject aEvent(rController); + m_xNavigatorTree->_selectionChanged(aEvent); +} + +ONavigator::ONavigator(weld::Window* pParent, OReportController& rController) + : GenericDialogController(pParent, "modules/dbreport/ui/floatingnavigator.ui", "FloatingNavigator") +{ + m_pImpl.reset(new ONavigatorImpl(rController, *m_xBuilder)); + m_pImpl->m_xNavigatorTree->grab_focus(); + + m_xDialog->connect_toplevel_focus_changed(LINK(this, ONavigator, FocusChangeHdl)); +} + +ONavigator::~ONavigator() +{ +} + +IMPL_LINK_NOARG(ONavigator, FocusChangeHdl, weld::Widget&, void) +{ + if (m_xDialog->has_toplevel_focus()) + m_pImpl->m_xNavigatorTree->grab_focus(); +} + +} // rptui + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/reportdesign/source/ui/dlg/PageNumber.cxx b/reportdesign/source/ui/dlg/PageNumber.cxx new file mode 100644 index 000000000..2d18077ab --- /dev/null +++ b/reportdesign/source/ui/dlg/PageNumber.cxx @@ -0,0 +1,105 @@ +/* -*- 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 <PageNumber.hxx> +#include <rptui_slotid.hrc> +#include <RptDef.hxx> + +#include <strings.hxx> +#include <ReportController.hxx> +#include <comphelper/propertysequence.hxx> + +namespace rptui +{ +using namespace ::com::sun::star; +using namespace ::comphelper; + + + +OPageNumberDialog::OPageNumberDialog(weld::Window* pParent, + const uno::Reference< report::XReportDefinition >& _xHoldAlive, + OReportController* _pController) + : GenericDialogController(pParent, "modules/dbreport/ui/pagenumberdialog.ui", "PageNumberDialog") + , m_pController(_pController) + , m_xHoldAlive(_xHoldAlive) + , m_xPageN(m_xBuilder->weld_radio_button("pagen")) + , m_xPageNofM(m_xBuilder->weld_radio_button("pagenofm")) + , m_xTopPage(m_xBuilder->weld_radio_button("toppage")) + , m_xBottomPage(m_xBuilder->weld_radio_button("bottompage")) + , m_xAlignmentLst(m_xBuilder->weld_combo_box("alignment")) + , m_xShowNumberOnFirstPage(m_xBuilder->weld_check_button("shownumberonfirstpage")) +{ + m_xShowNumberOnFirstPage->hide(); +} + +OPageNumberDialog::~OPageNumberDialog() +{ +} + +short OPageNumberDialog::run() +{ + short nRet = GenericDialogController::run(); + if (nRet == RET_OK) + { + try + { + sal_Int32 nControlMaxSize = 3000; + sal_Int32 nPosX = 0; + sal_Int32 nPos2X = 0; + awt::Size aRptSize = getStyleProperty<awt::Size>(m_xHoldAlive,PROPERTY_PAPERSIZE); + switch (m_xAlignmentLst->get_active()) + { + case 0: // left + nPosX = getStyleProperty<sal_Int32>(m_xHoldAlive,PROPERTY_LEFTMARGIN); + break; + case 1: // middle + nPosX = getStyleProperty<sal_Int32>(m_xHoldAlive,PROPERTY_LEFTMARGIN) + (aRptSize.Width - getStyleProperty<sal_Int32>(m_xHoldAlive,PROPERTY_LEFTMARGIN) - getStyleProperty<sal_Int32>(m_xHoldAlive,PROPERTY_RIGHTMARGIN) - nControlMaxSize) / 2; + break; + case 2: // right + nPosX = (aRptSize.Width - getStyleProperty<sal_Int32>(m_xHoldAlive,PROPERTY_RIGHTMARGIN) - nControlMaxSize); + break; + case 3: // inner + case 4: // outer + nPosX = getStyleProperty<sal_Int32>(m_xHoldAlive,PROPERTY_LEFTMARGIN); + nPos2X = (aRptSize.Width - getStyleProperty<sal_Int32>(m_xHoldAlive,PROPERTY_RIGHTMARGIN) - nControlMaxSize); + break; + default: + break; + } + if (m_xAlignmentLst->get_active() > 2) + nPosX = nPos2X; + + uno::Sequence<beans::PropertyValue> aValues( comphelper::InitPropertySequence({ + { PROPERTY_POSITION, uno::Any(awt::Point(nPosX,0)) }, + { PROPERTY_PAGEHEADERON, uno::Any(m_xTopPage->get_active()) }, + { PROPERTY_STATE, uno::Any(m_xPageNofM->get_active()) } + })); + + m_pController->executeChecked(SID_INSERT_FLD_PGNUMBER,aValues); + } + catch(uno::Exception&) + { + } + } + return nRet; +} + +} // rptui + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/reportdesign/source/ui/dlg/dlgpage.cxx b/reportdesign/source/ui/dlg/dlgpage.cxx new file mode 100644 index 000000000..1cc0b4db7 --- /dev/null +++ b/reportdesign/source/ui/dlg/dlgpage.cxx @@ -0,0 +1,79 @@ +/* -*- 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 <svx/dialogs.hrc> +#include <sfx2/sfxdlg.hxx> +#include <dlgpage.hxx> +#include <svl/cjkoptions.hxx> +#include <osl/diagnose.h> + +namespace rptui +{ +/************************************************************************* +|* +|* constructor of the tab dialogs: Add the page to the dialog +|* +\************************************************************************/ + +ORptPageDialog::ORptPageDialog(weld::Window* pParent, const SfxItemSet* pAttr, const OUString &rDialog) + : SfxTabDialogController(pParent, "modules/dbreport/ui/" + + rDialog.toAsciiLowerCase() + ".ui", rDialog.toUtf8(), pAttr) +{ + SfxAbstractDialogFactory* pFact = SfxAbstractDialogFactory::Create(); + + if (rDialog == "BackgroundDialog") + { + AddTabPage("background", pFact->GetTabPageCreatorFunc( RID_SVXPAGE_BKG ), nullptr ); + } + else if (rDialog == "PageDialog") + { + AddTabPage("page", pFact->GetTabPageCreatorFunc( RID_SVXPAGE_PAGE ), nullptr ); + AddTabPage("background", pFact->GetTabPageCreatorFunc( RID_SVXPAGE_BKG ), nullptr ); + } + else if (rDialog == "CharDialog") + { + AddTabPage("font", pFact->GetTabPageCreatorFunc( RID_SVXPAGE_CHAR_NAME ), nullptr ); + AddTabPage("fonteffects", pFact->GetTabPageCreatorFunc( RID_SVXPAGE_CHAR_EFFECTS ), nullptr ); + AddTabPage("position", pFact->GetTabPageCreatorFunc( RID_SVXPAGE_CHAR_POSITION ), nullptr ); + AddTabPage("asianlayout", pFact->GetTabPageCreatorFunc( RID_SVXPAGE_CHAR_TWOLINES ), nullptr ); + AddTabPage("background", pFact->GetTabPageCreatorFunc( RID_SVXPAGE_BKG ), nullptr ); + AddTabPage("alignment", pFact->GetTabPageCreatorFunc( RID_SVXPAGE_ALIGNMENT ), nullptr ); + } + else + OSL_FAIL("Unknown page id"); + + SvtCJKOptions aCJKOptions; + if ( !aCJKOptions.IsDoubleLinesEnabled() ) + RemoveTabPage("asianlayout"); +} + +void ORptPageDialog::PageCreated(const OString& rId, SfxTabPage &rPage) +{ + SfxAllItemSet aSet(*(GetInputSetImpl()->GetPool())); + if (rId == "background") + { + rPage.PageCreated(aSet); + } +} + +} // namespace rptui + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/reportdesign/source/ui/inc/AddField.hxx b/reportdesign/source/ui/inc/AddField.hxx new file mode 100644 index 000000000..db255fd4f --- /dev/null +++ b/reportdesign/source/ui/inc/AddField.hxx @@ -0,0 +1,116 @@ +/* -*- 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 . + */ + +#ifndef INCLUDED_REPORTDESIGN_SOURCE_UI_INC_ADDFIELD_HXX +#define INCLUDED_REPORTDESIGN_SOURCE_UI_INC_ADDFIELD_HXX + +#include <com/sun/star/lang/XComponent.hpp> +#include <com/sun/star/container/XNameAccess.hpp> +#include <com/sun/star/sdbc/XConnection.hpp> +#include <comphelper/propmultiplex.hxx> +#include <comphelper/containermultiplexer.hxx> + +#include <svx/dataaccessdescriptor.hxx> +#include <svx/dbaexchange.hxx> +#include <cppuhelper/basemutex.hxx> + +#include <vcl/weld.hxx> + +#include <rtl/ref.hxx> + +#include "ColumnInfo.hxx" + +namespace rptui +{ + +class OAddFieldWindow; + +class OAddFieldWindow : public weld::GenericDialogController + , public ::cppu::BaseMutex + , public ::comphelper::OPropertyChangeListener + , public ::comphelper::OContainerListener +{ + css::uno::Reference< css::lang::XComponent> m_xHoldAlive; + css::uno::Reference< css::container::XNameAccess> m_xColumns; + css::uno::Reference< css::beans::XPropertySet > m_xRowSet; + + std::unique_ptr<weld::Toolbar> m_xActions; + std::unique_ptr<weld::TreeView> m_xListBox; + std::unique_ptr<weld::Label> m_xHelpText; + + Link<OAddFieldWindow&,void> m_aCreateLink; + OUString m_aCommandName; + OUString m_sFilter; + sal_Int32 m_nCommandType; + bool m_bEscapeProcessing; + ::rtl::Reference< comphelper::OPropertyChangeMultiplexer> m_pChangeListener; + ::rtl::Reference< comphelper::OContainerListenerAdapter> m_pContainerListener; + ::rtl::Reference< svx::OMultiColumnTransferable > m_xHelper; + + std::vector<std::unique_ptr<ColumnInfo>> m_aListBoxData; + + DECL_LINK( OnDoubleClickHdl, weld::TreeView&, bool ); + DECL_LINK( OnSelectHdl, weld::TreeView&, void ); + DECL_LINK( DragBeginHdl, bool&, bool ); + DECL_LINK( OnSortAction, const OString&, void ); + DECL_LINK( FocusChangeHdl, weld::Widget&, void ); + + void addToList(const css::uno::Sequence<OUString>& rEntries); + void addToList(const css::uno::Reference<css::container::XNameAccess>& i_xColumns); + + OAddFieldWindow(const OAddFieldWindow&) = delete; + void operator =(const OAddFieldWindow&) = delete; +public: + OAddFieldWindow(weld::Window* pParent, + const css::uno::Reference< css::beans::XPropertySet >& xRowSet); + + virtual ~OAddFieldWindow() override; + + const OUString& GetCommand() const { return m_aCommandName; } + sal_Int32 GetCommandType() const { return m_nCommandType; } + void SetCreateHdl(const Link<OAddFieldWindow&,void>& _aCreateLink) { m_aCreateLink = _aCreateLink; } + + css::uno::Reference< css::sdbc::XConnection> getConnection() const; + + css::uno::Sequence< css::beans::PropertyValue > getSelectedFieldDescriptors(); + + /// Updates the current field list + void Update(); + + /** fills the descriptor with the column name, column object, command and command type + * + * \param rSelected the currently selected + * \param rDescriptor the descriptor will be filled + */ + void fillDescriptor(const weld::TreeIter& rSelected, svx::ODataAccessDescriptor& rDescriptor); + +private: + // FmXChangeListener + virtual void _propertyChanged(const css::beans::PropertyChangeEvent& evt) override; + // OContainerListener + virtual void _elementInserted( const css::container::ContainerEvent& _rEvent ) override; + virtual void _elementRemoved( const css::container::ContainerEvent& _rEvent ) override; + virtual void _elementReplaced( const css::container::ContainerEvent& _rEvent ) override; +}; + +} // rptui + +#endif // INCLUDED_REPORTDESIGN_SOURCE_UI_INC_ADDFIELD_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/reportdesign/source/ui/inc/ColorChanger.hxx b/reportdesign/source/ui/inc/ColorChanger.hxx new file mode 100644 index 000000000..bbed0a0c1 --- /dev/null +++ b/reportdesign/source/ui/inc/ColorChanger.hxx @@ -0,0 +1,50 @@ +/* -*- 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 . + */ +#ifndef INCLUDED_REPORTDESIGN_SOURCE_UI_INC_COLORCHANGER_HXX +#define INCLUDED_REPORTDESIGN_SOURCE_UI_INC_COLORCHANGER_HXX + +#include <vcl/outdev.hxx> + +namespace rptui +{ + + //= ColorChanger + + class ColorChanger final + { + VclPtr<OutputDevice> m_pDev; + + public: + ColorChanger( OutputDevice* _pDev, const Color& _rNewLineColor, const Color& _rNewFillColor ) + :m_pDev( _pDev ) + { + m_pDev->Push( PushFlags::LINECOLOR | PushFlags::FILLCOLOR ); + m_pDev->SetLineColor( _rNewLineColor ); + m_pDev->SetFillColor( _rNewFillColor ); + } + + ~ColorChanger() + { + m_pDev->Pop(); + } + }; +} +#endif // INCLUDED_REPORTDESIGN_SOURCE_UI_INC_COLORCHANGER_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/reportdesign/source/ui/inc/ColorListener.hxx b/reportdesign/source/ui/inc/ColorListener.hxx new file mode 100644 index 000000000..0f8a89aca --- /dev/null +++ b/reportdesign/source/ui/inc/ColorListener.hxx @@ -0,0 +1,75 @@ +/* -*- 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 . + */ +#ifndef INCLUDED_REPORTDESIGN_SOURCE_UI_INC_COLORLISTENER_HXX +#define INCLUDED_REPORTDESIGN_SOURCE_UI_INC_COLORLISTENER_HXX + +#include <vcl/window.hxx> +#include <svtools/colorcfg.hxx> +#include <svtools/extcolorcfg.hxx> +#include <tools/link.hxx> + +namespace rptui +{ + class OColorListener : public vcl::Window, public SfxListener + { + OColorListener(const OColorListener&) = delete; + void operator =(const OColorListener&) = delete; + protected: + Link<OColorListener&,void> m_aCollapsedLink; + svtools::ColorConfig m_aColorConfig; + svtools::ExtendedColorConfig m_aExtendedColorConfig; + OUString m_sColorEntry; + Color m_nColor; + Color m_nTextBoundaries; + bool m_bCollapsed; + bool m_bMarked; + + virtual void ImplInitSettings() = 0; + protected: + virtual void DataChanged( const DataChangedEvent& rDCEvt ) override; + public: + OColorListener(vcl::Window* _pParent,const OUString& _sColorEntry); + virtual ~OColorListener() override; + virtual void dispose() override; + + // SfxListener + virtual void Notify(SfxBroadcaster & rBc, SfxHint const & rHint) override; + + /** set the marker as marked or not marked + @param _bMark set the new state of the marker + */ + void setMarked(bool _bMark); + + /** returns if the section is marked + */ + bool isMarked() const { return m_bMarked; } + + void setCollapsedHdl(const Link<OColorListener&,void>& _aLink ){ m_aCollapsedLink = _aLink; } + bool isCollapsed() const { return m_bCollapsed; } + + /** collapse or expand + * + * \param _bCollapsed + */ + virtual void setCollapsed(bool _bCollapsed); + }; +} +#endif // INCLUDED_REPORTDESIGN_SOURCE_UI_INC_COLORLISTENER_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/reportdesign/source/ui/inc/ColumnInfo.hxx b/reportdesign/source/ui/inc/ColumnInfo.hxx new file mode 100644 index 000000000..65062f9dc --- /dev/null +++ b/reportdesign/source/ui/inc/ColumnInfo.hxx @@ -0,0 +1,45 @@ +/* -*- 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 . + */ +#ifndef INCLUDED_REPORTDESIGN_SOURCE_UI_INC_COLUMNINFO_HXX +#define INCLUDED_REPORTDESIGN_SOURCE_UI_INC_COLUMNINFO_HXX + +#include <rtl/ustring.hxx> + +namespace rptui +{ + struct ColumnInfo + { + OUString sColumnName; + OUString sLabel; + ColumnInfo(const OUString& i_sColumnName,const OUString& i_sLabel) + : sColumnName(i_sColumnName) + , sLabel(i_sLabel) + { + } + ColumnInfo(const OUString& i_sColumnName) + : sColumnName(i_sColumnName) + { + } + }; + +} // namespace rptui + +#endif // INCLUDED_REPORTDESIGN_SOURCE_UI_INC_COLUMNINFO_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/reportdesign/source/ui/inc/CondFormat.hxx b/reportdesign/source/ui/inc/CondFormat.hxx new file mode 100644 index 000000000..9b648be10 --- /dev/null +++ b/reportdesign/source/ui/inc/CondFormat.hxx @@ -0,0 +1,152 @@ +/* -*- 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 . + */ + +#ifndef INCLUDED_REPORTDESIGN_SOURCE_UI_INC_CONDFORMAT_HXX +#define INCLUDED_REPORTDESIGN_SOURCE_UI_INC_CONDFORMAT_HXX + +#include <com/sun/star/report/XReportControlModel.hpp> +#include <vcl/weld.hxx> +#include <vector> + +namespace rptui +{ + + + constexpr size_t MAX_CONDITIONS = 3; + + class OReportController; + class Condition; + + + //= IConditionalFormatAction + + class SAL_NO_VTABLE IConditionalFormatAction + { + public: + virtual void addCondition( size_t _nAddAfterIndex ) = 0; + virtual void deleteCondition( size_t _nCondIndex ) = 0; + virtual void applyCommand( size_t _nCondIndex, sal_uInt16 _nCommandId, const ::Color& rColor ) = 0; + virtual void moveConditionUp( size_t _nCondIndex ) = 0; + virtual void moveConditionDown( size_t _nCondIndex ) = 0; + virtual OUString getDataField() const = 0; + + protected: + ~IConditionalFormatAction() {} + }; + + /************************************************************************* + |* + |* Conditional formatting dialog + |* + \************************************************************************/ + class ConditionalFormattingDialog : public weld::GenericDialogController + , public IConditionalFormatAction + { + typedef ::std::vector< std::unique_ptr<Condition> > Conditions; + + ::rptui::OReportController& m_rController; + css::uno::Reference< css::report::XReportControlModel > + m_xFormatConditions; + css::uno::Reference< css::report::XReportControlModel > + m_xCopy; + + bool m_bConstructed; + + std::unique_ptr<weld::ScrolledWindow> m_xScrollWindow; + std::unique_ptr<weld::Box> m_xConditionPlayground; + Conditions m_aConditions; + + public: + ConditionalFormattingDialog( + weld::Window* pParent, + const css::uno::Reference< css::report::XReportControlModel>& _xHoldAlive, + ::rptui::OReportController& _rController + ); + virtual ~ConditionalFormattingDialog() override; + // Dialog overridables + virtual short run() override; + + // IConditionalFormatAction overridables + virtual void addCondition( size_t _nAddAfterIndex ) override; + virtual void deleteCondition( size_t _nCondIndex ) override; + virtual void applyCommand( size_t _nCondIndex, sal_uInt16 _nCommandId, const ::Color& rColor ) override; + virtual void moveConditionUp( size_t _nCondIndex ) override; + virtual void moveConditionDown( size_t _nCondIndex ) override; + virtual OUString getDataField() const override; + + private: + DECL_LINK(OnScroll, weld::ScrolledWindow&, void); + + private: + /// returns the current number of conditions + size_t impl_getConditionCount() const { return m_aConditions.size(); } + + /** adds a condition + @param _nNewCondIndex + the index of the to-be-inserted condition + */ + void impl_addCondition_nothrow( size_t _nNewCondIndex ); + + /// deletes the condition with the given index + void impl_deleteCondition_nothrow( size_t _nCondIndex ); + + /// moves the condition with the given index one position + void impl_moveCondition_nothrow( size_t _nCondIndex, bool _bMoveUp ); + + /// does the dialog layouting + void impl_layoutAll(); + + /// called when the number of conditions has changed in any way + void impl_conditionCountChanged(); + + /// initializes the conditions from m_xCopy + void impl_initializeConditions(); + + /// tells all our Condition instances their new index + void impl_updateConditionIndicies(); + + /// returns the number of the condition which has the (child path) focus + size_t impl_getFocusedConditionIndex( sal_Int32 _nFallBackIfNone ) const; + + /// returns the index of the first visible condition + size_t impl_getFirstVisibleConditionIndex() const; + + /// returns the index of the last visible condition + size_t impl_getLastVisibleConditionIndex() const; + + /// focuses the condition with the given index, making it visible if necessary + void impl_focusCondition( size_t _nCondIndex ); + + /// scrolls the condition with the given index to the top position + void impl_scrollTo( size_t _nTopCondIndex ); + + /// ensures the condition with the given index is visible + void impl_ensureConditionVisible( size_t _nCondIndex ); + + /// set the preferred height of the action_area + void impl_setPrefHeight(bool bFirst); + }; + + +} // namespace rptui + + +#endif // INCLUDED_REPORTDESIGN_SOURCE_UI_INC_CONDFORMAT_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/reportdesign/source/ui/inc/DataProviderHandler.hxx b/reportdesign/source/ui/inc/DataProviderHandler.hxx new file mode 100644 index 000000000..657f900b7 --- /dev/null +++ b/reportdesign/source/ui/inc/DataProviderHandler.hxx @@ -0,0 +1,122 @@ +/* -*- 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 . + */ + +#ifndef INCLUDED_REPORTDESIGN_SOURCE_UI_INC_DATAPROVIDERHANDLER_HXX +#define INCLUDED_REPORTDESIGN_SOURCE_UI_INC_DATAPROVIDERHANDLER_HXX + +#include <sal/config.h> + +#include <cppuhelper/compbase.hxx> +#include <cppuhelper/basemutex.hxx> + +#include <com/sun/star/uno/XComponentContext.hpp> +#include <com/sun/star/inspection/XPropertyHandler.hpp> +#include <com/sun/star/chart2/XChartDocument.hpp> +#include <com/sun/star/chart2/data/XDatabaseDataProvider.hpp> +#include <com/sun/star/report/XReportComponent.hpp> +#include <com/sun/star/script/XTypeConverter.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> + + +namespace rptui +{ + + + class OPropertyInfoService; + + typedef ::cppu::WeakComponentImplHelper< css::inspection::XPropertyHandler + , css::lang::XServiceInfo> DataProviderHandler_Base; + + class DataProviderHandler: + private ::cppu::BaseMutex, + public DataProviderHandler_Base + { + public: + // XServiceInfo - static versions + /// @throws css::uno::RuntimeException + static OUString getImplementationName_Static( ); + /// @throws css::uno::RuntimeException + static css::uno::Sequence< OUString > getSupportedServiceNames_static( ); + static css::uno::Reference< css::uno::XInterface > + create(const css::uno::Reference< css::uno::XComponentContext >&); + + explicit DataProviderHandler(css::uno::Reference< css::uno::XComponentContext > const & context); + private: + + // XServiceInfo + virtual OUString SAL_CALL getImplementationName( ) override; + virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override; + virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override; + + // css::lang::XComponent: + virtual void SAL_CALL addEventListener(const css::uno::Reference< css::lang::XEventListener > & xListener) override; + virtual void SAL_CALL removeEventListener(const css::uno::Reference< css::lang::XEventListener > & aListener) override; + + // css::inspection::XPropertyHandler: + virtual void SAL_CALL inspect(const css::uno::Reference< css::uno::XInterface > & Component) override; + virtual css::uno::Any SAL_CALL getPropertyValue(const OUString & PropertyName) override; + virtual void SAL_CALL setPropertyValue(const OUString & PropertyName, const css::uno::Any & Value) override; + virtual css::beans::PropertyState SAL_CALL getPropertyState(const OUString & PropertyName) override; + virtual css::inspection::LineDescriptor SAL_CALL describePropertyLine(const OUString& PropertyName, const css::uno::Reference< css::inspection::XPropertyControlFactory >& ControlFactory ) override; + virtual css::uno::Any SAL_CALL convertToPropertyValue(const OUString & PropertyName, const css::uno::Any & ControlValue) override; + virtual css::uno::Any SAL_CALL convertToControlValue(const OUString & PropertyName, const css::uno::Any & PropertyValue, const css::uno::Type & ControlValueType) override; + virtual void SAL_CALL addPropertyChangeListener(const css::uno::Reference< css::beans::XPropertyChangeListener > & Listener) override; + virtual void SAL_CALL removePropertyChangeListener(const css::uno::Reference< css::beans::XPropertyChangeListener > & _rxListener) override; + virtual css::uno::Sequence< css::beans::Property > SAL_CALL getSupportedProperties() override; + virtual css::uno::Sequence< OUString > SAL_CALL getSupersededProperties() override; + virtual css::uno::Sequence< OUString > SAL_CALL getActuatingProperties() override; + virtual sal_Bool SAL_CALL isComposable(const OUString & PropertyName) override; + virtual css::inspection::InteractiveSelectionResult SAL_CALL onInteractivePropertySelection(const OUString & PropertyName, sal_Bool Primary, css::uno::Any & out_Data, const css::uno::Reference< css::inspection::XObjectInspectorUI > & InspectorUI) override; + virtual void SAL_CALL actuatingPropertyChanged(const OUString & ActuatingPropertyName, const css::uno::Any & NewValue, const css::uno::Any & OldValue, const css::uno::Reference< css::inspection::XObjectInspectorUI > & InspectorUI, sal_Bool FirstTimeInit) override; + virtual sal_Bool SAL_CALL suspend(sal_Bool Suspend) override; + + protected: + virtual ~DataProviderHandler() override {} + private: + DataProviderHandler(DataProviderHandler const &) = delete; + void operator =(DataProviderHandler const &) = delete; + + + bool impl_dialogLinkedFields_nothrow( ::osl::ClearableMutexGuard& _rClearBeforeDialog ) const; + bool impl_dialogChartType_nothrow( ::osl::ClearableMutexGuard& _rClearBeforeDialog ) const; + void impl_updateChartTitle_throw(const css::uno::Any& _aValue); + + // override WeakComponentImplHelperBase::disposing() + // This function is called upon disposing the component, + // if your component needs special work when it becomes + // disposed, do it here. + virtual void SAL_CALL disposing() override; + + css::uno::Reference< css::uno::XComponentContext > m_xContext; + css::uno::Reference< css::inspection::XPropertyHandler > m_xFormComponentHandler; /// delegatee + css::uno::Reference< css::chart2::data::XDatabaseDataProvider> m_xDataProvider; /// inspectee + css::uno::Reference< css::uno::XInterface > m_xFormComponent; /// inspectee + css::uno::Reference< css::report::XReportComponent > m_xReportComponent; /// inspectee + css::uno::Reference< css::chart2::XChartDocument> m_xChartModel; + css::uno::Reference< css::beans::XPropertyChangeListener > m_xMasterDetails; + /// type converter, needed on various occasions + css::uno::Reference< css::script::XTypeConverter > m_xTypeConverter; + }; + +} // namespace rptui + + +#endif // INCLUDED_REPORTDESIGN_SOURCE_UI_INC_DATAPROVIDERHANDLER_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/reportdesign/source/ui/inc/DateTime.hxx b/reportdesign/source/ui/inc/DateTime.hxx new file mode 100644 index 000000000..0906c7906 --- /dev/null +++ b/reportdesign/source/ui/inc/DateTime.hxx @@ -0,0 +1,81 @@ +/* -*- 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 . + */ +#ifndef INCLUDED_REPORTDESIGN_SOURCE_UI_INC_DATETIME_HXX +#define INCLUDED_REPORTDESIGN_SOURCE_UI_INC_DATETIME_HXX + +#include <vcl/weld.hxx> +#include <com/sun/star/report/XSection.hpp> +#include <com/sun/star/util/XNumberFormats.hpp> +#include <com/sun/star/lang/Locale.hpp> + +namespace rptui +{ +class OReportController; +/************************************************************************* +|* +|* Groups and Sorting dialog +|* +\************************************************************************/ +class ODateTimeDialog : public weld::GenericDialogController +{ + ::rptui::OReportController* m_pController; + css::uno::Reference< css::report::XSection> + m_xHoldAlive; + css::lang::Locale m_nLocale; + + std::unique_ptr<weld::CheckButton> m_xDate; + std::unique_ptr<weld::Label> m_xFTDateFormat; + std::unique_ptr<weld::ComboBox> m_xDateListBox; + std::unique_ptr<weld::CheckButton> m_xTime; + std::unique_ptr<weld::Label> m_xFTTimeFormat; + std::unique_ptr<weld::ComboBox> m_xTimeListBox; + std::unique_ptr<weld::Button> m_xPB_OK; + + /** returns the format string + * + * \param _nNumberFormatKey the number format key + * \param _xFormats + * \param _bTime + * \return + */ + OUString getFormatStringByKey(::sal_Int32 _nNumberFormatKey,const css::uno::Reference< css::util::XNumberFormats>& _xFormats,bool _bTime); + + /** returns the number format key + @param _nNumberFormatIndex the number format index @see css::i18n::NumberFormatIndex + */ + sal_Int32 getFormatKey(bool _bDate) const; + + DECL_LINK(CBClickHdl, weld::ToggleButton&, void); + ODateTimeDialog(const ODateTimeDialog&) = delete; + void operator =(const ODateTimeDialog&) = delete; + + // fill methods + void InsertEntry(sal_Int16 _nNumberFormatId); +public: + ODateTimeDialog(weld::Window* pParent, + const css::uno::Reference< css::report::XSection>& _xHoldAlive, + ::rptui::OReportController* _pController); + virtual short run() override; +}; + +} // namespace rptui + +#endif // INCLUDED_REPORTDESIGN_SOURCE_UI_INC_DATETIME_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/reportdesign/source/ui/inc/DefaultInspection.hxx b/reportdesign/source/ui/inc/DefaultInspection.hxx new file mode 100644 index 000000000..e740112e5 --- /dev/null +++ b/reportdesign/source/ui/inc/DefaultInspection.hxx @@ -0,0 +1,97 @@ +/* -*- 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 . + */ +#ifndef INCLUDED_REPORTDESIGN_SOURCE_UI_INC_DEFAULTINSPECTION_HXX +#define INCLUDED_REPORTDESIGN_SOURCE_UI_INC_DEFAULTINSPECTION_HXX + +#include <com/sun/star/inspection/XObjectInspectorModel.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> +#include <com/sun/star/lang/XInitialization.hpp> +#include <cppuhelper/implbase3.hxx> + + +namespace rptui +{ + + class OPropertyInfoService; + + //= DefaultComponentInspectorModel + + typedef ::cppu::WeakAggImplHelper3 < css::inspection::XObjectInspectorModel + , css::lang::XServiceInfo + , css::lang::XInitialization + > DefaultComponentInspectorModel_Base; + class DefaultComponentInspectorModel final : public DefaultComponentInspectorModel_Base + { + private: + ::osl::Mutex m_aMutex; + css::uno::Reference< css::uno::XComponentContext > m_xContext; + css::uno::Reference< css::inspection::XObjectInspectorModel > m_xComponent; /// delegatee + bool m_bConstructed; + bool m_bHasHelpSection; + bool m_bIsReadOnly; + sal_Int32 m_nMinHelpTextLines; + sal_Int32 m_nMaxHelpTextLines; + + DefaultComponentInspectorModel(const DefaultComponentInspectorModel&) = delete; + DefaultComponentInspectorModel& operator=(const DefaultComponentInspectorModel&) = delete; + + virtual ~DefaultComponentInspectorModel() override; + + // XServiceInfo + virtual OUString SAL_CALL getImplementationName( ) override; + virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override; + virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override; + + // XObjectInspectorModel + virtual css::uno::Sequence< css::uno::Any > SAL_CALL getHandlerFactories() override; + virtual sal_Bool SAL_CALL getHasHelpSection() override; + virtual ::sal_Int32 SAL_CALL getMinHelpTextLines() override; + virtual ::sal_Int32 SAL_CALL getMaxHelpTextLines() override; + virtual sal_Bool SAL_CALL getIsReadOnly() override; + virtual void SAL_CALL setIsReadOnly( sal_Bool _isreadonly ) override; + + virtual css::uno::Sequence< css::inspection::PropertyCategoryDescriptor > SAL_CALL describeCategories( ) override; + virtual ::sal_Int32 SAL_CALL getPropertyOrderIndex( const OUString& PropertyName ) override; + + // XInitialization + virtual void SAL_CALL initialize( const css::uno::Sequence< css::uno::Any >& aArguments ) override; + + // Service constructors + void createWithHelpSection( sal_Int32 _nMinHelpTextLines, sal_Int32 _nMaxHelpTextLines ); + + public: + // XServiceInfo - static versions + /// @throws css::uno::RuntimeException + static OUString getImplementationName_Static( ); + /// @throws css::uno::RuntimeException + static css::uno::Sequence< OUString > getSupportedServiceNames_static( ); + static css::uno::Reference< css::uno::XInterface > + create(const css::uno::Reference< css::uno::XComponentContext >&); + + DefaultComponentInspectorModel( const css::uno::Reference< css::uno::XComponentContext >& _rxContext); + }; + + +} // namespace rptui + + +#endif // INCLUDED_REPORTDESIGN_SOURCE_UI_INC_DEFAULTINSPECTION_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/reportdesign/source/ui/inc/DesignView.hxx b/reportdesign/source/ui/inc/DesignView.hxx new file mode 100644 index 000000000..60ee506da --- /dev/null +++ b/reportdesign/source/ui/inc/DesignView.hxx @@ -0,0 +1,257 @@ +/* -*- 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 . + */ +#ifndef INCLUDED_REPORTDESIGN_SOURCE_UI_INC_DESIGNVIEW_HXX +#define INCLUDED_REPORTDESIGN_SOURCE_UI_INC_DESIGNVIEW_HXX + +#include <dbaccess/dataview.hxx> +#include <com/sun/star/report/XSection.hpp> +#include <com/sun/star/report/XReportComponent.hpp> +#include <tools/link.hxx> +#include <tools/gen.hxx> +#include <vcl/timer.hxx> +#include <vcl/idle.hxx> +#include <svl/SfxBroadcaster.hxx> +#include "ReportDefines.hxx" +#include <vcl/splitwin.hxx> +#include "MarkedSection.hxx" +#include "ScrollHelper.hxx" + +class KeyEvent; +class MouseEvent; +class Timer; +namespace vcl { class Window; } + +namespace rptui +{ + class OSectionView; + class OReportController; + class PropBrw; + class OAddFieldWindow; + class ONavigator; + + + class ODesignView : public dbaui::ODataView, public SfxBroadcaster, public IMarkedSection + { + private: + VclPtr<SplitWindow> m_aSplitWin; + + css::uno::Reference< css::uno::XInterface> m_xReportComponent; + OReportController& m_rReportController; + VclPtr<OScrollWindowHelper> m_aScrollWindow; + VclPtr<vcl::Window> m_pTaskPane; + VclPtr<PropBrw> m_pPropWin; + std::shared_ptr<OAddFieldWindow> m_xAddField; + OSectionView* m_pCurrentView; + std::shared_ptr<ONavigator> m_xReportExplorer; + Idle m_aMarkIdle; + DlgEdMode m_eMode; + sal_uInt16 m_eActObj; + Size m_aGridSizeCoarse; + Size m_aGridSizeFine; + bool m_bDeleted; + + + DECL_LINK(MarkTimeout, Timer *, void); + DECL_LINK( SplitHdl, SplitWindow*, void ); + + void ImplInitSettings(); + + ODesignView(ODesignView const &) = delete; + void operator =(ODesignView const &) = delete; + protected: + // return the Rectangle where I can paint myself + virtual void resizeDocumentView(tools::Rectangle& rRect) override; + // return the Rectangle where I can paint myself + virtual void DataChanged( const DataChangedEvent& rDCEvt ) override; + + public: + ODesignView(vcl::Window* pParent, + const css::uno::Reference< css::uno::XComponentContext >&, + OReportController& _rController); + virtual ~ODesignView() override; + virtual void dispose() override; + + // Window overrides + virtual void MouseButtonDown( const MouseEvent& rMEvt ) override; + virtual bool PreNotify( NotifyEvent& rNEvt ) override; + virtual void GetFocus() override; + + virtual void initialize() override; + + OReportController& getController() const { return m_rReportController; } + + void SetMode( DlgEdMode m_eMode ); + void SetInsertObj( sal_uInt16 eObj,const OUString& _sShapeType = OUString()); + sal_uInt16 GetInsertObj() const { return m_eActObj;} + OUString const & GetInsertObjString() const; + DlgEdMode GetMode() const { return m_eMode; } + + /** cuts the current selection in this section + */ + void Cut(); + + /** copies the current selection in this section + */ + void Copy(); + + /** returns if paste is allowed + * + * \return <TRUE/> if paste is allowed + */ + bool IsPasteAllowed() const; + + /** paste a new control in this section + */ + void Paste(); + + /** Deletes the current selection in this section + * + */ + void Delete(); + + /** align all marked objects in all sections + */ + void alignMarkedObjects(ControlModification _nControlModification, bool _bAlignAtSection); + + /** All objects will be marked. + */ + void SelectAll(const sal_uInt16 _nObjectType); + + /// checks if a selection exists + bool HasSelection() const; + + void UpdatePropertyBrowserDelayed(OSectionView& _rView); + + sal_uInt16 getSectionCount() const; + + /** removes the section at the given position. + * + * \param _nPosition Zero based. + */ + void removeSection(sal_uInt16 _nPosition); + + /** adds a new section at position _nPosition. + If the section is <NULL/> nothing happens. + If the position is grater than the current elements, the section will be appended. + */ + void addSection(const css::uno::Reference< css::report::XSection >& _xSection + ,const OUString& _sColorEntry + ,sal_uInt16 _nPosition = USHRT_MAX); + + const Size& getGridSizeCoarse() const { return m_aGridSizeCoarse; } + const Size& getGridSizeFine() const { return m_aGridSizeFine; } + void setGridSnap(bool bOn); + void setDragStripes(bool bOn); + /** turns the grid on or off + * + * \param _bGridVisible + */ + void toggleGrid(bool _bGridVisible); + + void togglePropertyBrowser(bool _bToggleOn); + + bool isAddFieldVisible() const; + void toggleAddField(); + + bool isReportExplorerVisible() const; + void toggleReportExplorer(); + + /** shows or hides the ruler. + */ + void showRuler(bool _bShow); + + /** unmark all objects on the views. + */ + void unmarkAllObjects(); + + /** triggers the property browser with the section + @param _xReportComponent the report component + */ + void showProperties( const css::uno::Reference< css::uno::XInterface>& _xReportComponent); + css::uno::Any getCurrentlyShownProperty() const; + + /** returns the current section or the detail section if no section was selected previously + */ + css::uno::Reference< css::report::XSection > getCurrentSection() const; + + /** returns the current control report model or <NULL/> + */ + css::uno::Reference< css::report::XReportComponent > getCurrentControlModel() const; + + // IMarkedSection + OSectionWindow* getMarkedSection(NearSectionAccess nsa = CURRENT) const override; + OSectionWindow* getSectionWindow(const css::uno::Reference< css::report::XSection>& _xSection) const; + virtual void markSection(const sal_uInt16 _nPos) override; + + /** fills the positions of all collapsed sections. + * + * \param _rCollapsedPositions Out parameter which holds afterwards all positions of the collapsed sections. + */ + void fillCollapsedSections(::std::vector<sal_uInt16>& _rCollapsedPositions) const; + + /** collapse all sections given by their position + * + * \param _aCollapsedSections The position of the sections which should be collapsed. + */ + void collapseSections(const css::uno::Sequence< css::beans::PropertyValue>& _aCollapsedSections); + + OUString getCurrentPage() const; + void setCurrentPage(const OUString& _sLastActivePage); + + /** checks if the keycode is known by the child windows + @param _rCode the keycode + @return <TRUE/> if the keycode is handled otherwise <FALSE/> + */ + bool handleKeyEvent(const KeyEvent& _rEvent); + + /** set the section as marked or not marked + @param _pSectionView the section where to set the marked flag + @param _bMark the marked flag + */ + void setMarked(const css::uno::Reference< css::report::XSection>& _xSection,bool _bMark); + void setMarked(const css::uno::Sequence< css::uno::Reference< css::report::XReportComponent> >& _xShape,bool _bMark); + + /** returns if the view handles the event by itself + * + * \return <FALSE/> is the event is not handled by the view otherwise <TRUE/> + */ + bool isHandleEvent() const; + + sal_uInt32 getMarkedObjectCount() const; + + /** zoom the ruler and view windows + */ + void zoom(const Fraction& _aZoom); + + /** fills the vector with all selected control models + /param _rSelection The vector will be filled and will not be cleared before. + */ + void fillControlModelSelection(::std::vector< css::uno::Reference< css::uno::XInterface > >& _rSelection) const; + + /** calculates the zoom factor. + @param _eType which kind of zoom is needed + */ + sal_uInt16 getZoomFactor(SvxZoomType _eType) const; + }; + +} //rptui + +#endif // INCLUDED_REPORTDESIGN_SOURCE_UI_INC_DESIGNVIEW_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/reportdesign/source/ui/inc/EndMarker.hxx b/reportdesign/source/ui/inc/EndMarker.hxx new file mode 100644 index 000000000..a48eb8106 --- /dev/null +++ b/reportdesign/source/ui/inc/EndMarker.hxx @@ -0,0 +1,46 @@ +/* -*- 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 . + */ +#ifndef INCLUDED_REPORTDESIGN_SOURCE_UI_INC_ENDMARKER_HXX +#define INCLUDED_REPORTDESIGN_SOURCE_UI_INC_ENDMARKER_HXX + +#include "ColorListener.hxx" + +namespace rptui +{ + /** \class OEndMarker + * \brief Defines the right side of a graphical section. + */ + class OEndMarker : public OColorListener + { + OEndMarker(OEndMarker const &) = delete; + void operator =(OEndMarker const &) = delete; + protected: + virtual void ImplInitSettings() override; + public: + OEndMarker(vcl::Window* _pParent,const OUString& _sColorEntry); + virtual ~OEndMarker() override; + + // windows + virtual void Paint( vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect ) override; + virtual void MouseButtonDown( const MouseEvent& rMEvt ) override; + }; +} +#endif // INCLUDED_REPORTDESIGN_SOURCE_UI_INC_ENDMARKER_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/reportdesign/source/ui/inc/FixedTextColor.hxx b/reportdesign/source/ui/inc/FixedTextColor.hxx new file mode 100644 index 000000000..fa76a52df --- /dev/null +++ b/reportdesign/source/ui/inc/FixedTextColor.hxx @@ -0,0 +1,61 @@ +/* -*- 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 . + */ + +#ifndef INCLUDED_REPORTDESIGN_SOURCE_UI_INC_FIXEDTEXTCOLOR_HXX +#define INCLUDED_REPORTDESIGN_SOURCE_UI_INC_FIXEDTEXTCOLOR_HXX + +#include <com/sun/star/beans/PropertyChangeEvent.hpp> +#include <com/sun/star/awt/XVclWindowPeer.hpp> +#include <com/sun/star/awt/XControl.hpp> +#include <com/sun/star/report/XFixedText.hpp> +#include <tools/color.hxx> + +#include "IReportControllerObserver.hxx" + +namespace rptui +{ + class OReportController; + + class FixedTextColor : public IReportControllerObserver + { + const OReportController& m_rReportController; + + /// @throws css::uno::RuntimeException + css::uno::Reference< css::awt::XVclWindowPeer > getVclWindowPeer(const css::uno::Reference< css::report::XFixedText >& _xComponent); + /// @throws css::uno::RuntimeException + css::uno::Reference< css::awt::XControl > getXControl(const css::uno::Reference< css::report::XFixedText >& _xFixedText); + + static void setPropertyTextColor(const css::uno::Reference< css::awt::XVclWindowPeer >& _xVclWindowPeer, Color _nFormatKey); + + public: + FixedTextColor(const OReportController & _aObserver); + virtual ~FixedTextColor() override; + + void notifyPropertyChange( const css::beans::PropertyChangeEvent& _rEvent ) override; + void notifyElementInserted( const css::uno::Reference< css::uno::XInterface >& _rxElement ) override; + void handle( const css::uno::Reference< css::uno::XInterface >& _rxElement ) override; + + }; + +} // namespace rptui + + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/reportdesign/source/ui/inc/FormattedFieldBeautifier.hxx b/reportdesign/source/ui/inc/FormattedFieldBeautifier.hxx new file mode 100644 index 000000000..455dfd396 --- /dev/null +++ b/reportdesign/source/ui/inc/FormattedFieldBeautifier.hxx @@ -0,0 +1,61 @@ +/* -*- 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 . + */ + +#ifndef INCLUDED_REPORTDESIGN_SOURCE_UI_INC_FORMATTEDFIELDBEAUTIFIER_HXX +#define INCLUDED_REPORTDESIGN_SOURCE_UI_INC_FORMATTEDFIELDBEAUTIFIER_HXX + +#include <com/sun/star/beans/PropertyChangeEvent.hpp> +#include <com/sun/star/awt/XVclWindowPeer.hpp> +#include <com/sun/star/report/XReportComponent.hpp> +#include <tools/color.hxx> + +#include "IReportControllerObserver.hxx" + +namespace rptui +{ + class OReportController; + + class FormattedFieldBeautifier : public IReportControllerObserver + { + const OReportController& m_rReportController; + Color m_nTextColor; + + /// @throws css::uno::RuntimeException + css::uno::Reference< css::awt::XVclWindowPeer > getVclWindowPeer(const css::uno::Reference< css::report::XReportComponent >& _xComponent); + + void setPlaceholderText( const css::uno::Reference< css::uno::XInterface >& _rxComponent ); + void setPlaceholderText( const css::uno::Reference< css::awt::XVclWindowPeer >& _xVclWindowPeer, const OUString& _rText ); + + Color getTextColor(); + + public: + FormattedFieldBeautifier(const OReportController & _aObserver); + virtual ~FormattedFieldBeautifier() override; + + void notifyPropertyChange( const css::beans::PropertyChangeEvent& _rEvent ) override; + void notifyElementInserted( const css::uno::Reference< css::uno::XInterface >& _rxElement ) override; + void handle( const css::uno::Reference< css::uno::XInterface >& _rxElement ) override; + }; + +} // namespace rptui + + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/reportdesign/source/ui/inc/Formula.hxx b/reportdesign/source/ui/inc/Formula.hxx new file mode 100644 index 000000000..8ec93075b --- /dev/null +++ b/reportdesign/source/ui/inc/Formula.hxx @@ -0,0 +1,112 @@ +/* -*- 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 . + */ + +#ifndef INCLUDED_REPORTDESIGN_SOURCE_UI_INC_FORMULA_HXX +#define INCLUDED_REPORTDESIGN_SOURCE_UI_INC_FORMULA_HXX + +#include <formula/formula.hxx> +#include <formula/IControlReferenceHandler.hxx> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/report/meta/XFormulaParser.hpp> +#include <memory> + +namespace com::sun::star::lang { + class XMultiServiceFactory; +} + +namespace svl { + +class SharedStringPool; + +} + +namespace rptui +{ + +class OAddFieldWindow; + + +class FormulaDialog : public formula::FormulaModalDialog, + public formula::IControlReferenceHandler +{ + std::shared_ptr<formula::IFunctionManager> m_aFunctionManager; + std::unique_ptr<formula::FormEditData> m_xFormulaData; + std::shared_ptr<OAddFieldWindow> m_xAddField; + css::uno::Reference < css::beans::XPropertySet > m_xRowSet; + css::uno::Reference< css::report::meta::XFormulaParser> m_xParser; + css::uno::Reference< css::sheet::XFormulaOpCodeMapper> m_xOpCodeMapper; + formula::RefEdit* m_pEdit; + OUString m_sFormula; + sal_Int32 m_nStart; + sal_Int32 m_nEnd; + + svl::SharedStringPool& mrStringPool; + + DECL_LINK( OnClickHdl, OAddFieldWindow&, void ); +public: + FormulaDialog( weld::Window* pParent + , const css::uno::Reference< css::lang::XMultiServiceFactory>& _xServiceFactory + , const std::shared_ptr< formula::IFunctionManager >& _pFunctionMgr + , const OUString& _sFormula + , const css::uno::Reference < css::beans::XPropertySet >& _xRowSet + , svl::SharedStringPool& rStrPool ); + + virtual ~FormulaDialog() override; + + // IFormulaEditorHelper + virtual void notifyChange() override; + virtual void fill() override; + virtual bool calculateValue(const OUString& _sExpression, OUString& _rResult, bool bMatrixFormula) override; + virtual std::shared_ptr<formula::FormulaCompiler> getCompiler() const override; + virtual std::unique_ptr<formula::FormulaCompiler> createCompiler( formula::FormulaTokenArray& rArray ) const override; + virtual void doClose(bool _bOk) override; + virtual void insertEntryToLRUList(const formula::IFunctionDescription* pDesc) override; + virtual void showReference(const OUString& _sFormula) override; + virtual void dispatch(bool _bOK, bool _bMatrixChecked) override; + virtual void setDispatcherLock( bool bLock ) override; + virtual void deleteFormData() override; + virtual void clear() override; + virtual void switchBack() override; + virtual formula::FormEditData* getFormEditData() const override; + virtual void setCurrentFormula(const OUString& _sReplacement) override; + virtual void setSelection(sal_Int32 _nStart, sal_Int32 _nEnd) override; + virtual void getSelection(sal_Int32& _nStart, sal_Int32& _nEnd) const override; + virtual OUString getCurrentFormula() const override; + + virtual formula::IFunctionManager* getFunctionManager() override; + virtual css::uno::Reference< css::sheet::XFormulaParser> getFormulaParser() const override; + virtual css::uno::Reference< css::sheet::XFormulaOpCodeMapper> getFormulaOpCodeMapper() const override; + virtual css::table::CellAddress getReferencePosition() const override; + + virtual ::std::unique_ptr<formula::FormulaTokenArray> convertToTokenArray(const css::uno::Sequence< css::sheet::FormulaToken >& _aTokenList) override; + + // IControlReferenceHandler + virtual void ShowReference(const OUString& _sRef) override; + virtual void HideReference( bool bDoneRefMode = true ) override; + virtual void ReleaseFocus( formula::RefEdit* pEdit ) override; + virtual void ToggleCollapsed( formula::RefEdit* pEdit, formula::RefButton* pButton ) override; +}; + + +} // rptui + + +#endif // INCLUDED_REPORTDESIGN_SOURCE_UI_INC_FORMULA_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/reportdesign/source/ui/inc/FunctionHelper.hxx b/reportdesign/source/ui/inc/FunctionHelper.hxx new file mode 100644 index 000000000..8eea9632b --- /dev/null +++ b/reportdesign/source/ui/inc/FunctionHelper.hxx @@ -0,0 +1,105 @@ +/* -*- 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 . + */ + +#ifndef INCLUDED_REPORTDESIGN_SOURCE_UI_INC_FUNCTIONHELPER_HXX +#define INCLUDED_REPORTDESIGN_SOURCE_UI_INC_FUNCTIONHELPER_HXX + +#include <formula/IFunctionDescription.hxx> +#include <com/sun/star/report/meta/XFunctionManager.hpp> +#include <com/sun/star/report/meta/XFunctionCategory.hpp> +#include <com/sun/star/report/meta/XFunctionDescription.hpp> +#include <map> +#include <memory> +#include <vector> + +namespace rptui +{ + +class FunctionCategory; +class FunctionDescription; + +class FunctionManager : public formula::IFunctionManager +{ + typedef std::map< OUString, std::shared_ptr< FunctionDescription > > TFunctionsMap; + typedef std::map< OUString, std::shared_ptr< FunctionCategory > > TCategoriesMap; + css::uno::Reference< css::report::meta::XFunctionManager> m_xMgr; + mutable TCategoriesMap m_aCategories; + mutable ::std::vector< TCategoriesMap::iterator > m_aCategoryIndex; + mutable TFunctionsMap m_aFunctions; +public: + FunctionManager(const css::uno::Reference< css::report::meta::XFunctionManager>& _xMgr); + virtual ~FunctionManager(); + virtual sal_uInt32 getCount() const override; + virtual const formula::IFunctionCategory* getCategory(sal_uInt32 nPos) const override; + virtual void fillLastRecentlyUsedFunctions(::std::vector< const formula::IFunctionDescription*>& _rLastRUFunctions) const override; + virtual sal_Unicode getSingleToken(const EToken _eToken) const override; + + std::shared_ptr< FunctionDescription > get(const css::uno::Reference< css::report::meta::XFunctionDescription>& _xFunctionDescription) const; +}; + +class FunctionDescription : public formula::IFunctionDescription +{ + css::uno::Sequence< css::sheet::FunctionArgument > m_aParameter; + css::uno::Reference< css::report::meta::XFunctionDescription> m_xFunctionDescription; + const formula::IFunctionCategory* m_pFunctionCategory; +public: + FunctionDescription(const formula::IFunctionCategory* _pFunctionCategory,const css::uno::Reference< css::report::meta::XFunctionDescription>& _xFunctionDescription); + virtual ~FunctionDescription(){} + + virtual OUString getFunctionName() const override ; + virtual const formula::IFunctionCategory* getCategory() const override ; + virtual OUString getDescription() const override ; + virtual sal_Int32 getSuppressedArgumentCount() const override ; + virtual OUString getFormula(const ::std::vector< OUString >& _aArguments) const override ; + virtual void fillVisibleArgumentMapping(::std::vector<sal_uInt16>& _rArguments) const override ; + virtual void initArgumentInfo() const override; + virtual OUString getSignature() const override ; + virtual OString getHelpId() const override ; + virtual bool isHidden() const override; + virtual sal_uInt32 getParameterCount() const override ; + virtual sal_uInt32 getVarArgsStart() const override; + virtual sal_uInt32 getVarArgsLimit() const override; + virtual OUString getParameterName(sal_uInt32 _nPos) const override ; + virtual OUString getParameterDescription(sal_uInt32 _nPos) const override ; + virtual bool isParameterOptional(sal_uInt32 _nPos) const override ; +}; + +class FunctionCategory : public formula::IFunctionCategory +{ + mutable ::std::vector< std::shared_ptr< FunctionDescription > > m_aFunctions; + css::uno::Reference< css::report::meta::XFunctionCategory> m_xCategory; + sal_uInt32 m_nFunctionCount; + sal_uInt32 m_nNumber; + const FunctionManager* m_pFunctionManager; +public: + FunctionCategory(const FunctionManager* _pFMgr,sal_uInt32 _nPos,const css::uno::Reference< css::report::meta::XFunctionCategory>& _xCategory); + virtual ~FunctionCategory() {} + + virtual sal_uInt32 getCount() const override; + virtual const formula::IFunctionDescription* getFunction(sal_uInt32 _nPos) const override; + virtual sal_uInt32 getNumber() const override; + virtual OUString getName() const override; +}; + +} // rptui + + +#endif // INCLUDED_REPORTDESIGN_SOURCE_UI_INC_FUNCTIONHELPER_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/reportdesign/source/ui/inc/GeometryHandler.hxx b/reportdesign/source/ui/inc/GeometryHandler.hxx new file mode 100644 index 000000000..d4520e210 --- /dev/null +++ b/reportdesign/source/ui/inc/GeometryHandler.hxx @@ -0,0 +1,315 @@ +/* -*- 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 . + */ + +#ifndef INCLUDED_REPORTDESIGN_SOURCE_UI_INC_GEOMETRYHANDLER_HXX +#define INCLUDED_REPORTDESIGN_SOURCE_UI_INC_GEOMETRYHANDLER_HXX + +#include <sal/config.h> +#include <com/sun/star/uno/XComponentContext.hpp> +#include <cppuhelper/compbase.hxx> +#include <cppuhelper/basemutex.hxx> +#include <com/sun/star/awt/Point.hpp> +#include <com/sun/star/awt/Size.hpp> +#include <com/sun/star/inspection/XPropertyHandler.hpp> +#include <com/sun/star/script/XTypeConverter.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/report/XFunctionsSupplier.hpp> +#include <com/sun/star/beans/XPropertyChangeListener.hpp> +#include <com/sun/star/sdbc/XRowSet.hpp> +#include <map> +#include <memory> +#include <comphelper/stl_types.hxx> +#include <comphelper/listenernotification.hxx> + + +namespace rptui +{ + + + struct DefaultFunction + { + css::beans::Optional< OUString> m_sInitialFormula; + OUString m_sName; + OUString m_sSearchString; + OUString m_sFormula; + bool m_bPreEvaluated; + + const OUString& getName() const { return m_sName; } + } ; + + class OPropertyInfoService; + typedef ::std::pair< css::uno::Reference< css::report::XFunction>, css::uno::Reference< css::report::XFunctionsSupplier> > TFunctionPair; + typedef ::std::multimap< OUString,TFunctionPair, ::comphelper::UStringMixLess > TFunctions; + typedef ::comphelper::OSimpleListenerContainer < css::beans::XPropertyChangeListener + , css::beans::PropertyChangeEvent + > PropertyChangeListeners; + typedef ::cppu::WeakComponentImplHelper< css::inspection::XPropertyHandler + , css::beans::XPropertyChangeListener + , css::lang::XServiceInfo> GeometryHandler_Base; + + class GeometryHandler: + private ::cppu::BaseMutex, + public GeometryHandler_Base + { + /** sets the counter function at the data field. + * If the counter function doesn't exist it will be created. + */ + void impl_setCounterFunction_throw(); + + /** executes a dialog for choosing a filter criterion for a database report + @param _out_rSelectedClause + the filter or order clause as chosen by the user + @precond + we're really inspecting a database form (well, a RowSet at least) + @return + <TRUE/> if and only if the user successfully chose a clause + */ + bool impl_dialogFilter_nothrow( OUString& _out_rSelectedClause, ::osl::ClearableMutexGuard& _rClearBeforeDialog ) const; + + /** returns the data field type depending on the data field of the report control + * + * \param _sDataField if the data field is not empty it will be used as data field, otherwise the data field will be used. + * \return the data field type + */ + sal_uInt32 impl_getDataFieldType_throw(const OUString& _sDataField = OUString()) const; + + css::uno::Any getConstantValue(bool bToControlValue,const char** pResId,const css::uno::Any& _aValue,const OUString& _sConstantName,const OUString & PropertyName ); + css::beans::Property getProperty(const OUString & PropertyName); + static void implCreateListLikeControl( + const css::uno::Reference< css::inspection::XPropertyControlFactory >& _rxControlFactory + ,css::inspection::LineDescriptor & out_Descriptor + ,const char** pResId + ,bool _bReadOnlyControl + ,bool _bTrueIfListBoxFalseIfComboBox + ); + static void implCreateListLikeControl( + const css::uno::Reference< css::inspection::XPropertyControlFactory >& _rxControlFactory + ,css::inspection::LineDescriptor & out_Descriptor + ,const ::std::vector< OUString>& _aEntries + ,bool _bReadOnlyControl + ,bool _bTrueIfListBoxFalseIfComboBox + ); + void checkPosAndSize( const css::awt::Point& _aNewPos, + const css::awt::Size& _aSize); + + OUString impl_convertToFormula( const css::uno::Any& _rControlValue ); + + void impl_initFieldList_nothrow( css::uno::Sequence< OUString >& _rFieldNames ) const; + + /** Creates the function defined by the function template + * + * \param _sFunctionName the function name + * \param _sDataField the data field + * \param _aFunction the function template + */ + void impl_createFunction(const OUString& _sFunctionName,const OUString& _sDataField,const DefaultFunction& _aFunction); + + /** check whether the given function name is a counter function. + * + * \param _sQuotedFunctionName the quoted function name to check + * \param Out_sScope the scope of the function + * \return When true it is a counter functions otherwise false. + */ + bool impl_isCounterFunction_throw(const OUString& _sQuotedFunctionName,OUString& Out_sScope) const; + + /** clear the own properties like function and scope and send a notification + * + * \param _aGuard + * \param _sOldFunctionName + * \param _sOldScope + * \param _nOldDataFieldType + */ + void resetOwnProperties(::osl::ResettableMutexGuard& _aGuard,const OUString& _sOldFunctionName,const OUString& _sOldScope,const sal_uInt32 _nOldDataFieldType); + + /** checks whether the name is a field or a parameter + * + * \param _sName the name to check + * \return true when it is a field or parameter otherwise false + */ + bool impl_isDataField(const OUString& _sName) const; + + /**return all formula in a semicolon separated list + * + * \param _rList the localized function names + */ + void impl_fillFormulaList_nothrow(::std::vector< OUString >& _out_rList) const; + + /** return all group names in a semicolon separated list starting with the group where this control is contained in. + * + * \param _rList fills the list with all scope names. + */ + void impl_fillScopeList_nothrow(::std::vector< OUString >& _out_rList) const; + + /** return all supported output formats of the report definition + * + * \param _rList fills the list with all mime types + */ + void impl_fillMimeTypes_nothrow(::std::vector< OUString >& _out_rList) const; + + /** return the one supported output formats of the report definition + * + * \param _sMimetype the mimetype + */ + OUString impl_ConvertMimeTypeToUI_nothrow(const OUString& _sMimetype) const; + + /** return the MimeType for the given UI Name + * + * \param _sUIName the doc ui name + */ + OUString impl_ConvertUIToMimeType_nothrow(const OUString& _sUIName) const; + + /** get the functions supplier for the set scope, default is the surrounding group. + * + * \param _rsNamePostfix the name postfix which can be used when the scope as name part is needed + * \return the function supplier + */ + css::uno::Reference< css::report::XFunctionsSupplier> fillScope_throw(OUString& _rsNamePostfix); + + /** checks if the given function is a default function we know. + * + * \param _sQuotedFunction the quoted function name + * \param Out_rDataField the data field which is used in the function + * \param _xFunctionsSupplier the function supplier to search or empty if not used + * \param _bSet If set to sal_True than the m_sDefaultFunction and m_sScope vars will be set if successful. + * \return sal_True with known otherwise sal_False + */ + bool isDefaultFunction(const OUString& _sQuotedFunction + ,OUString& Out_rDataField + ,const css::uno::Reference< css::report::XFunctionsSupplier>& _xFunctionsSupplier = css::uno::Reference< css::report::XFunctionsSupplier>() + ,bool _bSet = false) const; + + /** checks if the given function is a default function we know. + * + * \param _xFunction + * \param _rDataField + * \param _rsDefaultFunctionName + * \return + */ + bool impl_isDefaultFunction_nothrow( const css::uno::Reference< css::report::XFunction>& _xFunction + ,OUString& _rDataField + ,OUString& _rsDefaultFunctionName) const; + + /** fills the member m_aDefaultFunctions + * + */ + void loadDefaultFunctions(); + + /** creates a default function of the _sFunction for the data field _sDataField + * The new function will only be created if it didn't exist. + * + * \param _aGuard Will be cleared, when a new function was created. + * \param _sFunction The name of the function. + * \param _sDataField The name of the data field. + */ + void createDefaultFunction(::osl::ResettableMutexGuard& _aGuard ,const OUString& _sFunction,const OUString& _sDataField); + + void removeFunction(); + + class OBlocker + { + bool& m_bIn; + public: + OBlocker(bool& _bIn) : m_bIn(_bIn){ m_bIn = true; } + ~OBlocker() { m_bIn = false; } + }; + + + // XEventListener + virtual void SAL_CALL disposing(const css::lang::EventObject& Source) override; + // XPropertyChangeListener + virtual void SAL_CALL propertyChange(const css::beans::PropertyChangeEvent& evt) override; + + public: + // XServiceInfo - static versions + /// @throws css::uno::RuntimeException + static OUString getImplementationName_Static( ); + /// @throws css::uno::RuntimeException + static css::uno::Sequence< OUString > getSupportedServiceNames_static( ); + static css::uno::Reference< css::uno::XInterface > + create(const css::uno::Reference< css::uno::XComponentContext >&); + + public: + explicit GeometryHandler(css::uno::Reference< css::uno::XComponentContext > const & context); + + // XServiceInfo + virtual OUString SAL_CALL getImplementationName( ) override; + virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override; + virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override; + + // css::lang::XComponent: + virtual void SAL_CALL addEventListener(const css::uno::Reference< css::lang::XEventListener > & xListener) override; + virtual void SAL_CALL removeEventListener(const css::uno::Reference< css::lang::XEventListener > & aListener) override; + + // css::inspection::XPropertyHandler: + virtual void SAL_CALL inspect(const css::uno::Reference< css::uno::XInterface > & Component) override; + virtual css::uno::Any SAL_CALL getPropertyValue(const OUString & PropertyName) override; + virtual void SAL_CALL setPropertyValue(const OUString & PropertyName, const css::uno::Any & Value) override; + virtual css::beans::PropertyState SAL_CALL getPropertyState(const OUString & PropertyName) override; + virtual css::inspection::LineDescriptor SAL_CALL describePropertyLine(const OUString& PropertyName, const css::uno::Reference< css::inspection::XPropertyControlFactory >& ControlFactory ) override; + virtual css::uno::Any SAL_CALL convertToPropertyValue(const OUString & PropertyName, const css::uno::Any & ControlValue) override; + virtual css::uno::Any SAL_CALL convertToControlValue(const OUString & PropertyName, const css::uno::Any & PropertyValue, const css::uno::Type & ControlValueType) override; + virtual void SAL_CALL addPropertyChangeListener(const css::uno::Reference< css::beans::XPropertyChangeListener > & Listener) override; + virtual void SAL_CALL removePropertyChangeListener(const css::uno::Reference< css::beans::XPropertyChangeListener > & _rxListener) override; + virtual css::uno::Sequence< css::beans::Property > SAL_CALL getSupportedProperties() override; + virtual css::uno::Sequence< OUString > SAL_CALL getSupersededProperties() override; + virtual css::uno::Sequence< OUString > SAL_CALL getActuatingProperties() override; + virtual sal_Bool SAL_CALL isComposable(const OUString & PropertyName) override; + virtual css::inspection::InteractiveSelectionResult SAL_CALL onInteractivePropertySelection(const OUString & PropertyName, sal_Bool Primary, css::uno::Any & out_Data, const css::uno::Reference< css::inspection::XObjectInspectorUI > & InspectorUI) override; + virtual void SAL_CALL actuatingPropertyChanged(const OUString & ActuatingPropertyName, const css::uno::Any & NewValue, const css::uno::Any & OldValue, const css::uno::Reference< css::inspection::XObjectInspectorUI > & InspectorUI, sal_Bool FirstTimeInit) override; + virtual sal_Bool SAL_CALL suspend(sal_Bool Suspend) override; + + protected: + virtual ~GeometryHandler() override; + private: + GeometryHandler(GeometryHandler const &) = delete; + void operator =(GeometryHandler const &) = delete; + + // override WeakComponentImplHelperBase::disposing() + // This function is called upon disposing the component, + // if your component needs special work when it becomes + // disposed, do it here. + virtual void SAL_CALL disposing() override; + + PropertyChangeListeners m_aPropertyListeners; + css::uno::Sequence< OUString > m_aFieldNames; + css::uno::Sequence< OUString > m_aParamNames; + TFunctions m_aFunctionNames; + ::std::vector< DefaultFunction > m_aDefaultFunctions; + DefaultFunction m_aCounterFunction; + css::uno::Reference< css::uno::XComponentContext > m_xContext; + mutable css::uno::Reference< css::report::XFunction> m_xFunction; + css::uno::Reference< css::inspection::XPropertyHandler > m_xFormComponentHandler; /// delegatee + css::uno::Reference< css::beans::XPropertySet > m_xReportComponent; /// inspectee + mutable css::uno::Reference< css::sdbc::XRowSet > m_xRowSet; + /// type converter, needed on various occasions + css::uno::Reference< css::script::XTypeConverter > m_xTypeConverter; + mutable OUString m_sDefaultFunction; + mutable OUString m_sScope; + sal_uInt32 m_nDataFieldType; + mutable bool m_bNewFunction; + bool m_bIn; + }; + +} // namespace rptui + + +#endif // RPT_GeometryHandler_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/reportdesign/source/ui/inc/GroupsSorting.hxx b/reportdesign/source/ui/inc/GroupsSorting.hxx new file mode 100644 index 000000000..cd038e616 --- /dev/null +++ b/reportdesign/source/ui/inc/GroupsSorting.hxx @@ -0,0 +1,146 @@ +/* -*- 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 . + */ +#ifndef INCLUDED_REPORTDESIGN_SOURCE_UI_INC_GROUPSSORTING_HXX +#define INCLUDED_REPORTDESIGN_SOURCE_UI_INC_GROUPSSORTING_HXX + +#include <com/sun/star/report/XGroups.hpp> +#include <com/sun/star/report/XGroup.hpp> +#include <com/sun/star/container/XNameAccess.hpp> +#include <comphelper/propmultiplex.hxx> +#include <cppuhelper/basemutex.hxx> +#include <rtl/ref.hxx> +#include <vcl/weld.hxx> +#include <osl/diagnose.h> + +class Control; + +namespace comphelper +{ + class OPropertyChangeMultiplexer; +} +namespace rptui +{ +class OFieldExpressionControl; +class OReportController; +/************************************************************************* +|* +|* Groups and Sorting dialog +|* +\************************************************************************/ + +class OGroupsSortingDialog : public weld::GenericDialogController + , public ::cppu::BaseMutex + , public ::comphelper::OPropertyChangeListener +{ + friend class OFieldExpressionControl; + + ::rptui::OReportController* m_pController; + ::rtl::Reference< comphelper::OPropertyChangeMultiplexer> m_pCurrentGroupListener; + ::rtl::Reference< comphelper::OPropertyChangeMultiplexer> m_pReportListener; + css::uno::Reference< css::report::XGroups> m_xGroups; + css::uno::Reference< css::container::XNameAccess > m_xColumns; + bool m_bReadOnly; + + std::unique_ptr<weld::Toolbar> m_xToolBox; + std::unique_ptr<weld::Widget> m_xProperties; + std::unique_ptr<weld::ComboBox> m_xOrderLst; + std::unique_ptr<weld::ComboBox> m_xHeaderLst; + std::unique_ptr<weld::ComboBox> m_xFooterLst; + std::unique_ptr<weld::ComboBox> m_xGroupOnLst; + std::unique_ptr<weld::SpinButton> m_xGroupIntervalEd; + std::unique_ptr<weld::ComboBox> m_xKeepTogetherLst; + std::unique_ptr<weld::Label> m_xHelpWindow; + std::unique_ptr<weld::Container> m_xBox; + css::uno::Reference<css::awt::XWindow> m_xTableCtrlParent; + VclPtr<OFieldExpressionControl> m_xFieldExpression; + +private: + DECL_LINK( OnWidgetFocusLost, weld::Widget&, void ); + DECL_LINK( OnWidgetFocusGot, weld::Widget&, void ); + + DECL_LINK( OnControlFocusGot, weld::Widget&, void ); + + DECL_LINK( LBChangeHdl, weld::ComboBox&, void ); + DECL_LINK( OnFormatAction, const OString&, void ); + + /** returns the groups + @return the groups which now have to check which one changes + */ + css::uno::Reference< css::report::XGroups>& getGroups() { return m_xGroups; } + + css::uno::Reference< css::report::XGroup> getGroup(sal_Int32 _nPos) + { + OSL_ENSURE(_nPos >= 0 && _nPos < m_xGroups->getCount(),"Invalid count!"); + return css::uno::Reference< css::report::XGroup>(m_xGroups->getByIndex(_nPos),css::uno::UNO_QUERY); + } + + /** updates the listboxes with the new group properties + @param _nRow the new group pos + */ + void DisplayData( sal_Int32 _nRow ); + + /** saves the values from the listboxes into the group at position _nRow + @param _nRow the group pos to store in + */ + void SaveData( sal_Int32 _nRow ); + + /** returns <TRUE/> when the dialog should be read only + */ + bool isReadOnly( ) const { return m_bReadOnly;} + + /** returns the data type for the given column name + @param _sColumnName + */ + sal_Int32 getColumnDataType(const OUString& _sColumnName); + + /** display the group props + @param _xGroup the group to display + */ + void displayGroup(const css::uno::Reference< css::report::XGroup>& _xGroup); + + /** enables or disables the up and down button + @param _nRow the row which will be active + */ + void checkButtons(sal_Int32 _nRow); + + /** clears the m_xColumns member and reset the fields + * + */ + void fillColumns(); + OGroupsSortingDialog(OGroupsSortingDialog const &) = delete; + void operator =(OGroupsSortingDialog const &) = delete; +protected: + // OPropertyChangeListener + virtual void _propertyChanged(const css::beans::PropertyChangeEvent& _rEvent) override; +public: + OGroupsSortingDialog(weld::Window* pParent, + bool _bReadOnly, + ::rptui::OReportController* _pController); + virtual ~OGroupsSortingDialog() override; + + /* updates the current view + */ + void UpdateData( ); +}; + +} // namespace rptui + +#endif // INCLUDED_REPORTDESIGN_SOURCE_UI_INC_GROUPSSORTING_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/reportdesign/source/ui/inc/IReportControllerObserver.hxx b/reportdesign/source/ui/inc/IReportControllerObserver.hxx new file mode 100644 index 000000000..3d9f7e75c --- /dev/null +++ b/reportdesign/source/ui/inc/IReportControllerObserver.hxx @@ -0,0 +1,45 @@ +/* -*- 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 . + */ + +#ifndef INCLUDED_REPORTDESIGN_SOURCE_UI_INC_IREPORTCONTROLLEROBSERVER_HXX +#define INCLUDED_REPORTDESIGN_SOURCE_UI_INC_IREPORTCONTROLLEROBSERVER_HXX + +#include <com/sun/star/beans/PropertyChangeEvent.hpp> + +namespace rptui +{ + /* abstract */ class IReportControllerObserver + { + protected: + // IReportControllerObserver(){} + virtual ~IReportControllerObserver() {} + + public: + + virtual void notifyPropertyChange( const css::beans::PropertyChangeEvent& _rEvent ) = 0; + virtual void notifyElementInserted( const css::uno::Reference< css::uno::XInterface >& _rxElement ) = 0; + virtual void handle( const css::uno::Reference< css::uno::XInterface >& _rxElement ) = 0; + }; + +} // namespace rptui + +#endif + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/reportdesign/source/ui/inc/MarkedSection.hxx b/reportdesign/source/ui/inc/MarkedSection.hxx new file mode 100644 index 000000000..2d97645c4 --- /dev/null +++ b/reportdesign/source/ui/inc/MarkedSection.hxx @@ -0,0 +1,57 @@ +/* -*- 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 . + */ + +#ifndef INCLUDED_REPORTDESIGN_SOURCE_UI_INC_MARKEDSECTION_HXX +#define INCLUDED_REPORTDESIGN_SOURCE_UI_INC_MARKEDSECTION_HXX + +#include <sal/types.h> + +namespace rptui +{ + class OSectionWindow; + + enum NearSectionAccess + { + CURRENT = 0, + PREVIOUS = -1, + POST = 1 + }; + + class IMarkedSection + { + public: + /** returns the section which is currently marked. + */ + virtual OSectionWindow* getMarkedSection(NearSectionAccess nsa = CURRENT) const =0; + + /** mark the section on the given position . + * + * \param _nPos the position is zero based. + */ + virtual void markSection(const sal_uInt16 _nPos) = 0; + + protected: + ~IMarkedSection() {} + }; + +} // rptui + +#endif // INCLUDED_REPORTDESIGN_SOURCE_UI_INC_MARKEDSECTION_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/reportdesign/source/ui/inc/Navigator.hxx b/reportdesign/source/ui/inc/Navigator.hxx new file mode 100644 index 000000000..5c28d2401 --- /dev/null +++ b/reportdesign/source/ui/inc/Navigator.hxx @@ -0,0 +1,45 @@ +/* -*- 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 . + */ +#ifndef INCLUDED_REPORTDESIGN_SOURCE_UI_INC_NAVIGATOR_HXX +#define INCLUDED_REPORTDESIGN_SOURCE_UI_INC_NAVIGATOR_HXX + +#include <vcl/weld.hxx> +#include <memory> +namespace rptui +{ + class OReportController; + class ONavigatorImpl; + class ONavigator : public weld::GenericDialogController + { + ::std::unique_ptr<ONavigatorImpl> m_pImpl; + ONavigator(const ONavigator&) = delete; + void operator =(const ONavigator&) = delete; + + DECL_LINK(FocusChangeHdl, weld::Widget&, void); + + public: + ONavigator(weld::Window* pParent, OReportController& rController); + ~ONavigator(); + }; + +} // namespace rptui + +#endif // INCLUDED_REPORTDESIGN_SOURCE_UI_INC_NAVIGATOR_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/reportdesign/source/ui/inc/PageNumber.hxx b/reportdesign/source/ui/inc/PageNumber.hxx new file mode 100644 index 000000000..eefa10c8b --- /dev/null +++ b/reportdesign/source/ui/inc/PageNumber.hxx @@ -0,0 +1,59 @@ +/* -*- 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 . + */ +#ifndef INCLUDED_REPORTDESIGN_SOURCE_UI_INC_PAGENUMBER_HXX +#define INCLUDED_REPORTDESIGN_SOURCE_UI_INC_PAGENUMBER_HXX + +#include <vcl/weld.hxx> +#include <com/sun/star/report/XReportDefinition.hpp> + +namespace rptui +{ +class OReportController; +/************************************************************************* +|* +|* Groups and Sorting dialog +|* +\************************************************************************/ +class OPageNumberDialog : public weld::GenericDialogController +{ + ::rptui::OReportController* m_pController; + css::uno::Reference< css::report::XReportDefinition> + m_xHoldAlive; + std::unique_ptr<weld::RadioButton> m_xPageN; + std::unique_ptr<weld::RadioButton> m_xPageNofM; + std::unique_ptr<weld::RadioButton> m_xTopPage; + std::unique_ptr<weld::RadioButton> m_xBottomPage; + std::unique_ptr<weld::ComboBox> m_xAlignmentLst; + std::unique_ptr<weld::CheckButton> m_xShowNumberOnFirstPage; + + OPageNumberDialog(const OPageNumberDialog&) = delete; + void operator =(const OPageNumberDialog&) = delete; +public: + OPageNumberDialog(weld::Window* pParent, + const css::uno::Reference< css::report::XReportDefinition>& _xHoldAlive, + ::rptui::OReportController* _pController); + virtual ~OPageNumberDialog() override; + virtual short run() override; +}; + +} // namespace rptui + +#endif // INCLUDED_REPORTDESIGN_SOURCE_UI_INC_PAGENUMBER_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/reportdesign/source/ui/inc/ReportComponentHandler.hxx b/reportdesign/source/ui/inc/ReportComponentHandler.hxx new file mode 100644 index 000000000..3a329c58d --- /dev/null +++ b/reportdesign/source/ui/inc/ReportComponentHandler.hxx @@ -0,0 +1,106 @@ +/* -*- 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 . + */ + +#ifndef INCLUDED_REPORTDESIGN_SOURCE_UI_INC_REPORTCOMPONENTHANDLER_HXX +#define INCLUDED_REPORTDESIGN_SOURCE_UI_INC_REPORTCOMPONENTHANDLER_HXX + +#include <sal/config.h> +#include <com/sun/star/uno/XComponentContext.hpp> +#include <cppuhelper/compbase.hxx> +#include <cppuhelper/basemutex.hxx> +#include <com/sun/star/inspection/XPropertyHandler.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> + + +namespace rptui +{ + + + class OPropertyInfoService; + + typedef ::cppu::WeakComponentImplHelper< css::inspection::XPropertyHandler + , css::lang::XServiceInfo> ReportComponentHandler_Base; + + class ReportComponentHandler: + private ::cppu::BaseMutex, + public ReportComponentHandler_Base + { + public: + // XServiceInfo - static versions + /// @throws css::uno::RuntimeException + static OUString getImplementationName_Static( ); + /// @throws css::uno::RuntimeException + static css::uno::Sequence< OUString > getSupportedServiceNames_static( ); + static css::uno::Reference< css::uno::XInterface > + create(const css::uno::Reference< css::uno::XComponentContext >&); + + public: + explicit ReportComponentHandler(css::uno::Reference< css::uno::XComponentContext > const & context); + + // XServiceInfo + virtual OUString SAL_CALL getImplementationName( ) override; + virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override; + virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override; + + // css::lang::XComponent: + virtual void SAL_CALL addEventListener(const css::uno::Reference< css::lang::XEventListener > & xListener) override; + virtual void SAL_CALL removeEventListener(const css::uno::Reference< css::lang::XEventListener > & aListener) override; + + // css::inspection::XPropertyHandler: + virtual void SAL_CALL inspect(const css::uno::Reference< css::uno::XInterface > & Component) override; + virtual css::uno::Any SAL_CALL getPropertyValue(const OUString & PropertyName) override; + virtual void SAL_CALL setPropertyValue(const OUString & PropertyName, const css::uno::Any & Value) override; + virtual css::beans::PropertyState SAL_CALL getPropertyState(const OUString & PropertyName) override; + virtual css::inspection::LineDescriptor SAL_CALL describePropertyLine(const OUString& PropertyName, const css::uno::Reference< css::inspection::XPropertyControlFactory >& ControlFactory ) override; + virtual css::uno::Any SAL_CALL convertToPropertyValue(const OUString & PropertyName, const css::uno::Any & ControlValue) override; + virtual css::uno::Any SAL_CALL convertToControlValue(const OUString & PropertyName, const css::uno::Any & PropertyValue, const css::uno::Type & ControlValueType) override; + virtual void SAL_CALL addPropertyChangeListener(const css::uno::Reference< css::beans::XPropertyChangeListener > & Listener) override; + virtual void SAL_CALL removePropertyChangeListener(const css::uno::Reference< css::beans::XPropertyChangeListener > & _rxListener) override; + virtual css::uno::Sequence< css::beans::Property > SAL_CALL getSupportedProperties() override; + virtual css::uno::Sequence< OUString > SAL_CALL getSupersededProperties() override; + virtual css::uno::Sequence< OUString > SAL_CALL getActuatingProperties() override; + virtual sal_Bool SAL_CALL isComposable(const OUString & PropertyName) override; + virtual css::inspection::InteractiveSelectionResult SAL_CALL onInteractivePropertySelection(const OUString & PropertyName, sal_Bool Primary, css::uno::Any & out_Data, const css::uno::Reference< css::inspection::XObjectInspectorUI > & InspectorUI) override; + virtual void SAL_CALL actuatingPropertyChanged(const OUString & ActuatingPropertyName, const css::uno::Any & NewValue, const css::uno::Any & OldValue, const css::uno::Reference< css::inspection::XObjectInspectorUI > & InspectorUI, sal_Bool FirstTimeInit) override; + virtual sal_Bool SAL_CALL suspend(sal_Bool Suspend) override; + + protected: + virtual ~ReportComponentHandler() override {} + private: + ReportComponentHandler(ReportComponentHandler const &) = delete; + void operator =(ReportComponentHandler const &) = delete; + + + // override WeakComponentImplHelperBase::disposing() + // This function is called upon disposing the component, + // if your component needs special work when it becomes + // disposed, do it here. + virtual void SAL_CALL disposing() override; + + css::uno::Reference< css::uno::XComponentContext > m_xContext; + css::uno::Reference< css::inspection::XPropertyHandler > m_xFormComponentHandler; /// delegatee + css::uno::Reference< css::uno::XInterface > m_xFormComponent; /// inspectee + }; + +} // namespace rptui + + +#endif // INCLUDED_REPORTDESIGN_SOURCE_UI_INC_REPORTCOMPONENTHANDLER_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/reportdesign/source/ui/inc/ReportController.hxx b/reportdesign/source/ui/inc/ReportController.hxx new file mode 100644 index 000000000..a6fc9f155 --- /dev/null +++ b/reportdesign/source/ui/inc/ReportController.hxx @@ -0,0 +1,457 @@ +/* -*- 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 . + */ +#ifndef INCLUDED_REPORTDESIGN_SOURCE_UI_INC_REPORTCONTROLLER_HXX +#define INCLUDED_REPORTDESIGN_SOURCE_UI_INC_REPORTCONTROLLER_HXX + +#include "DesignView.hxx" +#include "ReportControllerObserver.hxx" +#include <RptDef.hxx> + +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/beans/XPropertyChangeListener.hpp> +#include <com/sun/star/embed/XVisualObject.hpp> +#include <com/sun/star/frame/XDesktop2.hpp> +#include <com/sun/star/frame/XFrame.hpp> +#include <com/sun/star/report/XReportDefinition.hpp> +#include <com/sun/star/report/XReportEngine.hpp> +#include <com/sun/star/report/XSection.hpp> +#include <com/sun/star/sdbc/XRowSet.hpp> +#include <com/sun/star/uno/Sequence.hxx> +#include <com/sun/star/uno/XComponentContext.hpp> +#include <com/sun/star/util/XModeSelector.hpp> +#include <com/sun/star/util/XNumberFormatter.hpp> +#include <com/sun/star/view/XSelectionSupplier.hpp> + +#include <comphelper/proparrhlp.hxx> +#include <comphelper/propertystatecontainer.hxx> +#include <comphelper/uno3.hxx> +#include <cppuhelper/implbase5.hxx> +#include <comphelper/interfacecontainer2.hxx> +#include <dbaccess/dbsubcomponentcontroller.hxx> +#include <svl/lstner.hxx> +#include <vcl/transfer.hxx> +#include <sfx2/zoomitem.hxx> + +#include <functional> +#include <memory> + +class TransferableClipboardListener; +class VclWindowEvent; +class SfxUndoManager; +namespace rptui +{ + class OGroupsSortingDialog; + class OReportModel; + class OSectionView; + class OAddFieldWindow; + class OSectionWindow; + + typedef ::dbaui::DBSubComponentController OReportController_BASE; + typedef ::cppu::ImplHelper5 < css::container::XContainerListener + , css::beans::XPropertyChangeListener + , css::view::XSelectionSupplier + , css::util::XModeSelector + , css::embed::XVisualObject + > OReportController_Listener; + + class OReportController : public OReportController_BASE + ,public OReportController_Listener + ,public SfxListener + ,public ::comphelper::OPropertyStateContainer + ,public ::comphelper::OPropertyArrayUsageHelper < OReportController_BASE > + { + private: + ::comphelper::OInterfaceContainerHelper2 + m_aSelectionListeners; + css::uno::Sequence< css::beans::PropertyValue> + m_aCollapsedSections; + TransferableDataHelper m_aSystemClipboard; // content of the clipboard + rtl::Reference<TransferableClipboardListener> + m_pClipboardNotifier; /// notifier for changes in the clipboard + std::shared_ptr<OGroupsSortingDialog> m_xGroupsFloater; + + rtl::Reference<OXReportControllerObserver> m_pReportControllerObserver; + + ODesignView* getDesignView() const { return static_cast< ODesignView* >( getView() ); } + + css::uno::Reference< css::report::XReportDefinition > m_xReportDefinition; + css::uno::Reference< css::report::XReportEngine > m_xReportEngine; + css::uno::Reference< css::frame::XDesktop2 > m_xFrameLoader; + css::uno::Reference< css::sdbc::XRowSet > m_xRowSet; + css::uno::Reference< css::beans::XPropertyChangeListener > m_xRowSetMediator; + css::uno::Reference< css::util::XNumberFormatter > m_xFormatter; // a number formatter working with the report's NumberFormatsSupplier + mutable css::uno::Reference< css::lang::XComponent > m_xHoldAlive; + mutable css::uno::Reference< css::container::XNameAccess > m_xColumns; + css::awt::Size m_aVisualAreaSize; + + std::shared_ptr<rptui::OReportModel> + m_aReportModel; + OUString m_sName; /// name for the report definition + OUString m_sLastActivePage; /// last active property browser page + OUString m_sMode; /// the current mode of the controller + sal_Int32 m_nSplitPos; /// the position of the splitter + sal_Int32 m_nPageNum; /// the page number from the restoreView call + sal_Int32 m_nSelectionCount; + ::sal_Int64 m_nAspect; + sal_Int16 m_nZoomValue; + SvxZoomType m_eZoomType; + bool m_bShowRuler; + bool m_bGridVisible; + bool m_bGridUse; + bool m_bShowProperties; + bool m_bHelplinesMove; + bool m_bChartEnabled; + bool m_bChartEnabledAsked; + bool m_bInGeneratePreview; + + /** creates a formatted field in the given section with the given formula as data field + * + * \param _aArgs + * \param _xSection the section where to create the formatted field + * \param _sFunction the function which will be set at the data field. + */ + void createControl(const css::uno::Sequence< css::beans::PropertyValue >& _aArgs,const css::uno::Reference< css::report::XSection>& _xSection,const OUString& _sFunction ,sal_uInt16 _nObjectId = OBJ_DLG_FORMATTEDFIELD); + /** switch the report header/footer sectionon off with undo or without depending on the given id. + * + * \param _nId Can either be SID_REPORTHEADER_WITHOUT_UNDO or SID_REPORTFOOTER_WITHOUT_UNDO or SID_REPORTHEADERFOOTER. + */ + void switchReportSection(const sal_Int16 _nId); + + /** switch the report header/footer sectionon off with undo or without depending on the given id. + * + * \param _nId Can either be SID_PAGEHEADER_WITHOUT_UNDO or SID_PAGEFOOTER_WITHOUT_UNDO or SID_PAGEHEADERFOOTER. + */ + void switchPageSection(const sal_Int16 _nId); + + /** append a new group or remove it with undo. + * + * \param _bAppend + * \param _aArgs The args which contains an element named PROPERTY_GROUP of type report::XGroup. + */ + void modifyGroup(const bool _bAppend, const css::uno::Sequence< css::beans::PropertyValue >& _aArgs); + + /** creates a group section. + * + * \param _bUndo true when undo action should be created + * \param _bHeader true when it is a header otherwise it is a footer + * \param _aArgs The args which contains an element named PROPERTY_GROUP of type report::XGroup. + */ + void createGroupSection(const bool _bUndo,const bool _bHeader,const css::uno::Sequence< css::beans::PropertyValue >&_aArgs); + + /** add or remove me as listener at the report definition + * + * \param _bAdd + */ + void listen(const bool _bAdd); + + /** opens the common page dialog + */ + void openPageDialog(const css::uno::Reference< css::report::XSection>& _xSection); + + /** opens or hides the sorting and grouping dialog + */ + void openSortingAndGroupingDialog(); + + /** opens the zoom dialog + */ + void openZoomDialog(); + + /** returns the position of the group inside the groups collection + */ + sal_Int32 getGroupPosition(const css::uno::Reference< css::report::XGroup >& _xGroup); + + /** calls propertyChanged when the header or footer is really turned on. + @param _rEvent the group + @param _bShow when <TRUE/> the header and footer will be shown otherwise not + */ + void notifyGroupSections(const css::container::ContainerEvent& _rEvent + ,bool _bShow); + + /** change the sections for a group + @param _sPropName the header or footer + @param _xGroup the group + @param _nGroupPos the position of the group inside the groups collection or the previous index when it was removed + @param _bShow when <TRUE/> the header and footer will be shown otherwise not + */ + void groupChange( const css::uno::Reference< css::report::XGroup>& _xGroup + ,const OUString& _sPropName + ,sal_Int32 _nGroupPos + ,bool _bShow); + + void executeMethodWithUndo(const char* pUndoStrId,const ::std::function<void(ODesignView *)>& _pMemfun); + void alignControlsWithUndo(const char* pUndoStrId, ControlModification _nControlModification, bool _bAlignAtSection = false); + + css::uno::Reference< css::frame::XFrame > getXFrame(); + + /** shrink a section + @param pUndoStrId the string id of the string which is shown in undo menu + @param _nShrinkId ID of what you would like to shrink. + */ + static void shrinkSectionBottom(const css::uno::Reference< css::report::XSection >& _xSection); + static void shrinkSectionTop(const css::uno::Reference< css::report::XSection >& _xSection); + + public: + void shrinkSection(const char* pUndoStrId, const css::uno::Reference< css::report::XSection >& _xSection, sal_Int32 _nShrinkId); + + /** opens the file open dialog to allow the user to select an image which will be + * bound to a newly created image button. + */ + void insertGraphic(); + + /** creates a new function in the given value context + * + * \param _aValue contains a XNameContainer + */ + void createNewFunction(const css::uno::Any& _aValue); + + /** inserts a label - field pair into the current selected section + * + * \param aArgs + */ + void addPairControls(const css::uno::Sequence< css::beans::PropertyValue >& aArgs); + + /** inserts a label - field combination to show the page number and/or page count + * + * \param _aArgs + */ + void createPageNumber(const css::uno::Sequence< css::beans::PropertyValue >& _aArgs); + + /** creates a formatted field with TODAY() function and if set also a NOW() function + * + * \param _aArgs + */ + void createDateTime(const css::uno::Sequence< css::beans::PropertyValue >& _aArgs); + + /** gets the current section (SdrView) + * + * \return the currently selected section or <NULL/> if no one is selected + */ + OSectionView* getCurrentSectionView() const; + + /**change the ZOrder of a current select object. + * + * \param _nId The command ID about what to do. + */ + void changeZOrder(sal_Int32 _nId); + + /** marks the next or previous section, when the first/last section was already selected then the report will be selected. + * + * \param _bNext + */ + void markSection(const bool _bNext); + + /** collapse or expand the currently selected section. + * + * \param _bCollapse collapse if sal_True otherwise expand + */ + void collapseSection(const bool _bCollapse); + + /** fills the member that chart is enabled or not + * + */ + void checkChartEnabled(); + + /** set the zoom factor at the design view + */ + void impl_zoom_nothrow(); + + virtual void impl_onModifyChanged() override; + + virtual void onLoadedMenu( const css::uno::Reference< css::frame::XLayoutManager >& _xLayoutManager ) override; + virtual void impl_initialize( ) override; + bool isUiVisible() const; + + /** creates a new default control for the currently set type when the modifier KEY_MOD1 was pressed + * \param _aArgs must contain a propertyvalue with name "KeyModifier" and value KEY_MOD1 when control should be created. + */ + void createDefaultControl(const css::uno::Sequence< css::beans::PropertyValue>& _aArgs); + + /** fills the state for the feature request. + @param _sProperty the property which should be filled in the value + @param _rState the state to fill + */ + void impl_fillState_nothrow(const OUString& _sProperty,dbaui::FeatureState& _rState) const; + void impl_fillCustomShapeState_nothrow(const char* _pCustomShapeType,dbaui::FeatureState& _rState) const; + + /** set the property at all selected controls. + @return <TRUE/> when the selection is not empty + */ + bool impl_setPropertyAtControls_throw(const char* pUndoResId + ,const OUString& _sProperty + ,const css::uno::Any& _aValue + ,const css::uno::Sequence< css::beans::PropertyValue >& _aArgs); + + void OnInvalidateClipboard(); + DECL_LINK( OnClipboardChanged, TransferableDataHelper*, void ); + DECL_LINK( OnExecuteReport, void*, void ); + // all the features which should be handled by this class + virtual void describeSupportedFeatures() override; + // state of a feature. 'feature' may be the handle of a css::util::URL somebody requested a dispatch interface for OR a toolbar slot. + virtual dbaui::FeatureState GetState(sal_uInt16 nId) const override; + // execute a feature + virtual void Execute(sal_uInt16 nId, const css::uno::Sequence< css::beans::PropertyValue>& aArgs) override; + + virtual void getPropertyDefaultByHandle( sal_Int32 _nHandle, css::uno::Any& _rDefault ) const override; + virtual void SAL_CALL setFastPropertyValue_NoBroadcast(sal_Int32 nHandle,const css::uno::Any& rValue) override; + + private: + virtual ~OReportController() override; + + public: + explicit OReportController(css::uno::Reference< css::uno::XComponentContext > const & the_context); + OReportController(const OReportController&) = delete; + OReportController& operator=(const OReportController&) = delete; + + DECL_LINK( OnCreateHdl, OAddFieldWindow&, void); + + DECLARE_XINTERFACE( ) + DECLARE_XTYPEPROVIDER( ) + + // SfxListener + virtual void Notify(SfxBroadcaster & rBc, SfxHint const & rHint) override; + + /** returns <TRUE/> when the command is enabled + @param _nCommand the command id + @param _xControlFormat the report control format + */ + static bool isFormatCommandEnabled(sal_uInt16 _nCommand + ,const css::uno::Reference< css::report::XReportControlFormat>& _xControlFormat); + + virtual bool Construct(vcl::Window* pParent) override; + // XEventListener + virtual void SAL_CALL disposing( const css::lang::EventObject& Source ) override; + + // css::frame::XController + virtual sal_Bool SAL_CALL suspend(sal_Bool bSuspend) override; + + // css::lang::XComponent + virtual void SAL_CALL disposing() override; + + // XServiceInfo + virtual OUString SAL_CALL getImplementationName() override; + virtual css::uno::Sequence< OUString> SAL_CALL getSupportedServiceNames() override; + // need by registration + /// @throws css::uno::RuntimeException + static OUString getImplementationName_Static(); + /// @throws css::uno::RuntimeException + static css::uno::Sequence< OUString > getSupportedServiceNames_Static(); + static css::uno::Reference< css::uno::XInterface > + create(css::uno::Reference< css::uno::XComponentContext > const & xContext); + + // css::container::XContainerListener + virtual void SAL_CALL elementInserted(const css::container::ContainerEvent& Event) override; + virtual void SAL_CALL elementRemoved(const css::container::ContainerEvent& Event) override; + virtual void SAL_CALL elementReplaced(const css::container::ContainerEvent& Event) override; + + // XPropertyChangeListener + virtual void SAL_CALL propertyChange( const css::beans::PropertyChangeEvent& evt ) override; + + // XSelectionSupplier + virtual sal_Bool SAL_CALL select( const css::uno::Any& xSelection ) override; + virtual css::uno::Any SAL_CALL getSelection( ) override; + virtual void SAL_CALL addSelectionChangeListener( const css::uno::Reference< css::view::XSelectionChangeListener >& xListener ) override; + virtual void SAL_CALL removeSelectionChangeListener( const css::uno::Reference< css::view::XSelectionChangeListener >& xListener ) override; + + // css::frame::XController + virtual sal_Bool SAL_CALL attachModel(const css::uno::Reference< css::frame::XModel > & xModel) override; + virtual css::uno::Any SAL_CALL getViewData() override; + virtual void SAL_CALL restoreViewData(const css::uno::Any& Data) override; + + /** gives access to the report definition + * \return the report definition object, may be <NULL/> + */ + const css::uno::Reference< css::report::XReportDefinition>& getReportDefinition() const { return m_xReportDefinition; } + + // css::frame::XController + virtual css::uno::Reference< css::frame::XModel > SAL_CALL getModel() override; + + // XTitle + virtual OUString SAL_CALL getTitle( ) override; + + // XModeSelector + virtual void SAL_CALL setMode( const OUString& aMode ) override ; + virtual OUString SAL_CALL getMode( ) override ; + virtual css::uno::Sequence< OUString > SAL_CALL getSupportedModes( ) override ; + virtual sal_Bool SAL_CALL supportsMode( const OUString& aMode ) override ; + + // XVisualObject + virtual void SAL_CALL setVisualAreaSize( ::sal_Int64 nAspect, const css::awt::Size& aSize ) override; + virtual css::awt::Size SAL_CALL getVisualAreaSize( ::sal_Int64 nAspect ) override; + virtual css::embed::VisualRepresentation SAL_CALL getPreferredVisualRepresentation( ::sal_Int64 nAspect ) override; + virtual ::sal_Int32 SAL_CALL getMapUnit( ::sal_Int64 nAspect ) override; + + + /** returns the current position of the splitter + * + * \return + */ + sal_Int32 getSplitPos() const { return m_nSplitPos;} + void setSplitPos(sal_Int32 _nSplitPos) { m_nSplitPos = _nSplitPos;} + + /** creates a new report from the report definition. + * + * \return The model or <NULL/> if the model could not be created. + */ + css::uno::Reference< css::frame::XModel> executeReport(); + + /** returns the RowSet which reflects the current settings of the report definition + + The caller is allowed to hold a reference to the RowSet - it is kept alive as long + as the controller lives, and it's settings will follow the report definition's settings. + */ + css::uno::Reference< css::sdbc::XRowSet > const & getRowSet(); + + /** returns the number formatter + */ + const css::uno::Reference< css::util::XNumberFormatter >& getReportNumberFormatter() const { return m_xFormatter;} + + /** return the SdrModel of the real model + * + * \return + */ + const std::shared_ptr<rptui::OReportModel>& getSdrModel() const { return m_aReportModel;} + + const css::uno::Reference< css::uno::XComponentContext >& getContext() const { return m_xContext; } + sal_Int16 getZoomValue() const { return m_nZoomValue; } + void resetZoomType() { m_eZoomType = SvxZoomType::PERCENT; } + + // css::beans::XPropertySet + virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo( ) override + { + return ::cppu::OPropertySetHelper::createPropertySetInfo(getInfoHelper()); + } + // comphelper::OPropertyArrayUsageHelper + virtual ::cppu::IPropertyArrayHelper* createArrayHelper( ) const override; + + // cppu::OPropertySetHelper + virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper() override; + + OSectionWindow* getSectionWindow(const css::uno::Reference< css::report::XSection>& _xSection) const; + + css::uno::Reference< css::container::XNameAccess > const & getColumns() const; + OUString getColumnLabel_throw(const OUString& i_sColumnName) const; + + SfxUndoManager& getUndoManager() const; + void clearUndoManager() const; + void addUndoAction( std::unique_ptr<SfxUndoAction> i_pAction ); + }; +} +#endif // INCLUDED_REPORTDESIGN_SOURCE_UI_INC_REPORTCONTROLLER_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/reportdesign/source/ui/inc/ReportControllerObserver.hxx b/reportdesign/source/ui/inc/ReportControllerObserver.hxx new file mode 100644 index 000000000..ec6be058b --- /dev/null +++ b/reportdesign/source/ui/inc/ReportControllerObserver.hxx @@ -0,0 +1,109 @@ +/* -*- 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 . + */ +#ifndef INCLUDED_REPORTDESIGN_SOURCE_UI_INC_REPORTCONTROLLEROBSERVER_HXX +#define INCLUDED_REPORTDESIGN_SOURCE_UI_INC_REPORTCONTROLLEROBSERVER_HXX + +#include <com/sun/star/beans/XPropertyChangeListener.hpp> +#include <com/sun/star/beans/PropertyChangeEvent.hpp> +#include <cppuhelper/implbase.hxx> + +#include <memory> + +#include <vcl/vclevent.hxx> +#include <tools/link.hxx> + +#include "FormattedFieldBeautifier.hxx" +#include "FixedTextColor.hxx" + +namespace rptui +{ + class OReportController; + class OXReportControllerObserverImpl; + + + class OXReportControllerObserver + : public ::cppu::WeakImplHelper< css::beans::XPropertyChangeListener + , css::container::XContainerListener + , css::util::XModifyListener + > + { + + const ::std::unique_ptr<OXReportControllerObserverImpl> m_pImpl; + + FormattedFieldBeautifier m_aFormattedFieldBeautifier; + FixedTextColor m_aFixedTextColor; + + // do not allow copy + OXReportControllerObserver(const OXReportControllerObserver&) = delete; + OXReportControllerObserver& operator=(const OXReportControllerObserver&) = delete; + virtual ~OXReportControllerObserver() override; // UNO Object must have private destructor! + public: + OXReportControllerObserver(const OReportController& _rController); + + // XPropertyChangeListener + virtual void SAL_CALL propertyChange(const css::beans::PropertyChangeEvent& evt) override; + + // XEventListener + virtual void SAL_CALL disposing(const css::lang::EventObject& Source) override; + + // XContainerListener + virtual void SAL_CALL elementInserted(const css::container::ContainerEvent& rEvent) override; + virtual void SAL_CALL elementReplaced(const css::container::ContainerEvent& rEvent) override; + virtual void SAL_CALL elementRemoved(const css::container::ContainerEvent& rEvent) override; + + // XModifyListener + virtual void SAL_CALL modified( const css::lang::EventObject& aEvent ) override; + + + void AddElement(const css::uno::Reference< css::uno::XInterface>& Element); + void RemoveElement(const css::uno::Reference< css::uno::XInterface>& Element); + + void AddSection( const css::uno::Reference< css::report::XSection>& _xSection); + void RemoveSection( const css::uno::Reference< css::report::XSection>& _xSection ); + + /** + Create an object ob OUndoEnvLock locks the undo possibility + As long as in the OUndoEnvLock scope, no undo is possible for manipulated object. + */ + class OEnvLock + { + OXReportControllerObserver& m_rObserver; + public: + OEnvLock(OXReportControllerObserver& _rObserver): m_rObserver(_rObserver){m_rObserver.Lock();} + ~OEnvLock(){ m_rObserver.UnLock(); } + }; + + void Lock(); + void UnLock(); + + void Clear(); + private: + + void switchListening( const css::uno::Reference< css::container::XIndexAccess >& _rxContainer, bool _bStartListening ); + void switchListening( const css::uno::Reference< css::uno::XInterface >& _rxObject, bool _bStartListening ); + + DECL_LINK(SettingsChanged, VclSimpleEvent&, void ); + }; + +} // namespace rptui + +#endif // INCLUDED_REPORTDESIGN_SOURCE_UI_INC_REPORTCONTROLLEROBSERVER_HXX + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/reportdesign/source/ui/inc/ReportDefines.hxx b/reportdesign/source/ui/inc/ReportDefines.hxx new file mode 100644 index 000000000..c56e20841 --- /dev/null +++ b/reportdesign/source/ui/inc/ReportDefines.hxx @@ -0,0 +1,33 @@ +/* -*- 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 . + */ +#ifndef INCLUDED_REPORTDESIGN_SOURCE_UI_INC_REPORTDEFINES_HXX +#define INCLUDED_REPORTDESIGN_SOURCE_UI_INC_REPORTDEFINES_HXX + +namespace rptui +{ + enum class DlgEdMode { Insert, Select }; + +#define REPORT_STARTMARKER_WIDTH 120 +#define REPORT_ENDMARKER_WIDTH 10 +#define REPORT_EXTRA_SPACE 10 + +} +#endif // INCLUDED_REPORTDESIGN_SOURCE_UI_INC_REPORTDEFINES_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/reportdesign/source/ui/inc/ReportSection.hxx b/reportdesign/source/ui/inc/ReportSection.hxx new file mode 100644 index 000000000..ad334f194 --- /dev/null +++ b/reportdesign/source/ui/inc/ReportSection.hxx @@ -0,0 +1,164 @@ +/* -*- 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 . + */ +#ifndef INCLUDED_REPORTDESIGN_SOURCE_UI_INC_REPORTSECTION_HXX +#define INCLUDED_REPORTDESIGN_SOURCE_UI_INC_REPORTSECTION_HXX + +#include <vcl/window.hxx> +#include <RptPage.hxx> +#include <com/sun/star/beans/NamedValue.hpp> +#include <comphelper/propmultiplex.hxx> +#include <cppuhelper/basemutex.hxx> +#include "ReportDefines.hxx" +#include "dlgedfunc.hxx" +#include <vcl/transfer.hxx> +#include <rtl/ref.hxx> +#include <memory> + +namespace rptui +{ + class OReportModel; + class OReportPage; + class OSectionView; + class OSectionWindow; + + class OReportSection : public vcl::Window + , public ::cppu::BaseMutex + , public ::comphelper::OPropertyChangeListener + , public DropTargetHelper + { + OReportPage* m_pPage; + OSectionView* m_pView; + VclPtr<OSectionWindow> m_pParent; + ::std::unique_ptr<DlgEdFunc> m_pFunc; + std::shared_ptr<OReportModel> m_pModel; + ::rtl::Reference< comphelper::OPropertyChangeMultiplexer> m_pMulti; + ::rtl::Reference< comphelper::OPropertyChangeMultiplexer> m_pReportListener; + css::uno::Reference< css::report::XSection > m_xSection; + sal_Int32 m_nPaintEntranceCount; + + DlgEdMode m_eMode; + + /** fills the section with all control from the report section + */ + void fill(); + /** checks all objects if they fit in the new paper width. + */ + void impl_adjustObjectSizePosition(sal_Int32 i_nPaperWidth,sal_Int32 i_nLeftMargin,sal_Int32 i_nRightMargin); + + OReportSection(OReportSection const &) = delete; + void operator =(OReportSection const &) = delete; + protected: + // DropTargetHelper overridables + virtual sal_Int8 AcceptDrop( const AcceptDropEvent& _rEvt ) override; + virtual sal_Int8 ExecuteDrop( const ExecuteDropEvent& _rEvt ) override; + + // window overrides + virtual void Paint( vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect ) override; + virtual void MouseMove( const MouseEvent& rMEvt ) override; + virtual void Command( const CommandEvent& rCEvt ) override; + + // OPropertyChangeListener + virtual void _propertyChanged(const css::beans::PropertyChangeEvent& _rEvent) override; + public: + OReportSection(OSectionWindow* _pParent,const css::uno::Reference< css::report::XSection >& _xSection); + virtual ~OReportSection() override; + virtual void dispose() override; + + // window overrides + virtual void MouseButtonDown( const MouseEvent& rMEvt ) override; + virtual void MouseButtonUp( const MouseEvent& rMEvt ) override; + + /** copies the current selection in this section + @param _rAllreadyCopiedObjects This is an out/in put param which contains all already copied objects. + */ + void Copy(css::uno::Sequence< css::beans::NamedValue >& _rAllreadyCopiedObjects); + + void Copy(css::uno::Sequence< css::beans::NamedValue >& _rAllreadyCopiedObjects,bool _bEraseAnddNoClone); + + /** paste a new control in this section + @param _aAllreadyCopiedObjects objects to paste into the section. Only objects are pasted where the name is equal to the section name. + @param _bForce If set to <TRUE/> than the objects will be copied into this section. The name is not compared in this case. + */ + void Paste(const css::uno::Sequence< css::beans::NamedValue >& _aAllreadyCopiedObjects,bool _bForce = false); + + /** Deletes the current selection in this section + * + */ + void Delete(); + + /** All objects will be marked. + */ + void SelectAll(const sal_uInt16 _nObjectType); + + /** makes the grid visible + * + * \param _bVisible when <TRUE/> the grid is made visible + */ + void SetGridVisible(bool _bVisible); + + OSectionWindow* getSectionWindow() const { return m_pParent; } + OSectionView& getSectionView() const { return *m_pView; } + OReportPage* getPage() const { return m_pPage; } + const css::uno::Reference< css::report::XSection >& getSection() const { return m_xSection; } + + void SetMode( DlgEdMode m_eMode ); + + /** checks if the keycode is known by the child windows + @param _rCode the keycode + @return <TRUE/> if the keycode is handled otherwise <FALSE/> + */ + bool handleKeyEvent(const KeyEvent& _rEvent); + + /** returns the current control report model or <NULL/> + */ + css::uno::Reference< css::report::XReportComponent > getCurrentControlModel() const; + + /** fills the vector with all selected control models + /param _rSelection The vector will be filled and will not be cleared before. + */ + void fillControlModelSelection(::std::vector< css::uno::Reference< css::uno::XInterface > >& _rSelection) const; + + /** creates a default object (custom shape) + * + * @param _sType + */ + void createDefault(const OUString& _sType); + + /** creates a new default custom shape + * + * \param _sType + * \param _pObj + */ + static void createDefault(const OUString& _sType,SdrObject* _pObj); + void stopScrollTimer(); + + /** deactivate the current active ole object if any + */ + void deactivateOle(); + + /** returns true when an ole object is currently active + */ + bool isUiActive() const; + }; + +} //rptui + +#endif // INCLUDED_REPORTDESIGN_SOURCE_UI_INC_REPORTSECTION_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/reportdesign/source/ui/inc/ReportWindow.hxx b/reportdesign/source/ui/inc/ReportWindow.hxx new file mode 100644 index 000000000..d794a33f1 --- /dev/null +++ b/reportdesign/source/ui/inc/ReportWindow.hxx @@ -0,0 +1,221 @@ +/* -*- 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 . + */ +#ifndef INCLUDED_REPORTDESIGN_SOURCE_UI_INC_REPORTWINDOW_HXX +#define INCLUDED_REPORTDESIGN_SOURCE_UI_INC_REPORTWINDOW_HXX + +#include <com/sun/star/report/XSection.hpp> +#include "ReportDefines.hxx" +#include <o3tl/deleter.hxx> +#include <svtools/ruler.hxx> +#include <sfx2/zoomitem.hxx> + +#include <memory> +#include <vector> +#include <comphelper/propmultiplex.hxx> + +#include "MarkedSection.hxx" +#include "ViewsWindow.hxx" + +namespace rptui +{ + class ODesignView; + class OScrollWindowHelper; + class OSectionView; + class DlgEdFactory; + + class OReportWindow : public vcl::Window + , public IMarkedSection + , public ::cppu::BaseMutex + , public ::comphelper::OPropertyChangeListener + { + VclPtr<Ruler> m_aHRuler; + VclPtr<ODesignView> m_pView; + VclPtr<OScrollWindowHelper> m_pParent; + VclPtr<OViewsWindow> m_aViewsWindow; + rtl::Reference< comphelper::OPropertyChangeMultiplexer> m_pReportListener; + std::unique_ptr<DlgEdFactory, o3tl::default_delete<DlgEdFactory>> m_pObjFac; + + void ImplInitSettings(); + + sal_Int32 GetTotalHeight() const; + sal_Int32 impl_getRealPixelWidth() const; + + OReportWindow(OReportWindow const &) = delete; + void operator =(OReportWindow const &) = delete; + protected: + virtual void DataChanged( const DataChangedEvent& rDCEvt ) override; + // OPropertyChangeListener + virtual void _propertyChanged(const css::beans::PropertyChangeEvent& _rEvent) override; + public: + OReportWindow(OScrollWindowHelper* _pParent,ODesignView* _pView); + virtual ~OReportWindow() override; + virtual void dispose() override; + + // Window overrides + virtual void Resize() override; + + ODesignView* getReportView() const { return m_pView; } + OScrollWindowHelper* getScrollWindow() const { return m_pParent; } + + void SetMode( DlgEdMode m_eMode ); + void SetInsertObj( sal_uInt16 eObj, const OUString& _sShapeType); + OUString const & GetInsertObjString() const; + void setGridSnap(bool bOn); + void setDragStripes(bool bOn); + + /** copies the current selection in this section + */ + void Copy(); + + /** returns if paste is allowed + * + * \return <TRUE/> if paste is allowed + */ + bool IsPasteAllowed() const; + + /** paste a new control in this section + */ + void Paste(); + + /** Deletes the current selection in this section + * + */ + void Delete(); + + /** All objects will be marked. + */ + void SelectAll(const sal_uInt16 _nObjectType); + + /** returns <TRUE/> when an object is marked + */ + bool HasSelection() const; + + Point getThumbPos() const; + + /** removes the section at the given position. + * + * \param _nPosition Zero based. + */ + void removeSection(sal_uInt16 _nPosition); + + /** adds a new section at position _nPosition. + If the section is <NULL/> nothing happens. + If the position is grater than the current elements, the section will be appended. + */ + void addSection(const css::uno::Reference< css::report::XSection >& _xSection + ,const OUString& _sColorEntry + ,sal_uInt16 _nPosition); + + sal_uInt16 getSectionCount() const; + + /** turns the grid on or off + * + * \param _bVisible + */ + void toggleGrid(bool _bVisible); + + + /** shows the ruler + */ + void showRuler(bool _bShow); + + sal_Int32 getRulerHeight() const { return m_aHRuler->GetSizePixel().Height(); } + + /** returns the total width of the first section + */ + sal_Int32 GetTotalWidth() const; + + /** calculate the max width of the markers + * The end marker will not be used for calculation. + * + * \return the max width + */ + sal_Int32 getMaxMarkerWidth() const; + + void ScrollChildren(const Point& _aThumbPos); + + void notifySizeChanged(); + + /** unmark all objects on the views without the given one. + */ + void unmarkAllObjects(); + + /** triggers the property browser with the report component or section + @param _xReportComponent + */ + void showProperties( const css::uno::Reference< css::report::XSection>& _xReportComponent); + + /** checks if the keycode is known by the child windows + @param _rCode the keycode + @return <TRUE/> if the keycode is handled otherwise <FALSE/> + */ + bool handleKeyEvent(const KeyEvent& _rEvent); + + /** the section as marked or not marked + @param _pSectionView the section where to set the marked flag + @param _bMark the marked flag + */ + void setMarked(OSectionView const * _pSectionView, bool _bMark); + void setMarked(const css::uno::Reference< css::report::XSection>& _xSection, bool _bMark); + void setMarked(const css::uno::Sequence< css::uno::Reference< css::report::XReportComponent> >& _xShape, bool _bMark); + + // IMarkedSection + OSectionWindow* getMarkedSection(NearSectionAccess nsa = CURRENT) const override; + OSectionWindow* getSectionWindow(const css::uno::Reference< css::report::XSection>& _xSection) const; + virtual void markSection(const sal_uInt16 _nPos) override; + + + /** fills the positions of all collapsed sections. + * + * \param _rCollapsedPositions Out parameter which holds afterwards all positions of the collapsed sections. + */ + void fillCollapsedSections(::std::vector<sal_uInt16>& _rCollapsedPositions) const; + + /** collapse all sections given by their position + * + * \param _aCollapsedSections The position of the sections which should be collapsed. + */ + void collapseSections(const css::uno::Sequence< css::beans::PropertyValue>& _aCollapsedSections); + + /** align all marked objects in all sections + */ + void alignMarkedObjects(ControlModification _nControlModification, bool _bAlignAtSection); + + sal_uInt32 getMarkedObjectCount() const; + + /** zoom the ruler and view windows + */ + void zoom(const Fraction& _aZoom); + + /** fills the vector with all selected control models + /param _rSelection The vector will be filled and will not be cleared before. + */ + void fillControlModelSelection(::std::vector< css::uno::Reference< css::uno::XInterface > >& _rSelection) const; + + /** calculates the zoom factor. + @param _eType which kind of zoom is needed + */ + sal_uInt16 getZoomFactor(SvxZoomType _eType) const; + }; + +} //rptui + +#endif // INCLUDED_REPORTDESIGN_SOURCE_UI_INC_REPORTWINDOW_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/reportdesign/source/ui/inc/RptUndo.hxx b/reportdesign/source/ui/inc/RptUndo.hxx new file mode 100644 index 000000000..9f0b6c1aa --- /dev/null +++ b/reportdesign/source/ui/inc/RptUndo.hxx @@ -0,0 +1,135 @@ +/* -*- 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 . + */ +#ifndef INCLUDED_REPORTDESIGN_SOURCE_UI_INC_RPTUNDO_HXX +#define INCLUDED_REPORTDESIGN_SOURCE_UI_INC_RPTUNDO_HXX + +#include <RptModel.hxx> +#include <UndoActions.hxx> +#include <functional> + +namespace com::sun::star { + namespace drawing { + class XShape; + } +} + +namespace rptui +{ + /** \class OSectionUndo + * Undo class for section add and remove. + */ + class OSectionUndo : public OCommentUndoAction + { + OSectionUndo(const OSectionUndo&) = delete; + void operator =(const OSectionUndo&) = delete; + protected: + ::std::vector< css::uno::Reference< css::drawing::XShape> > + m_aControls; + ::std::vector< ::std::pair< OUString ,css::uno::Any> > + m_aValues; + Action m_eAction; + sal_uInt16 m_nSlot; + bool m_bInserted; + + virtual void implReInsert( ) = 0; + virtual void implReRemove( ) = 0; + + void collectControls(const css::uno::Reference< css::report::XSection >& _xSection); + public: + OSectionUndo( OReportModel& rMod + ,sal_uInt16 _nSlot + ,Action _eAction + ,const char* pCommentID); + virtual ~OSectionUndo() override; + + virtual void Undo() override; + virtual void Redo() override; + }; + + /** Undo action for the group header, footer, page header, footer + */ + class OReportSectionUndo : public OSectionUndo + { + OReportHelper m_aReportHelper; + ::std::function<css::uno::Reference< css::report::XSection >(OReportHelper *)> m_pMemberFunction; + + void implReInsert( ) override; + void implReRemove( ) override; + OReportSectionUndo(const OReportSectionUndo&) = delete; + void operator =(const OReportSectionUndo&) = delete; + public: + //OReportSectionUndo( const css::uno::Reference< css::report::XSection >& _xSection + OReportSectionUndo( OReportModel& rMod + ,sal_uInt16 _nSlot + ,::std::function<css::uno::Reference< css::report::XSection >(OReportHelper *)> _pMemberFunction + ,const css::uno::Reference< css::report::XReportDefinition >& _xReport + ,Action _eAction); + virtual ~OReportSectionUndo() override; + }; + + /** Undo action for the group header, footer + */ + class OGroupSectionUndo : public OSectionUndo + { + OGroupHelper m_aGroupHelper; + ::std::function<css::uno::Reference< css::report::XSection >(OGroupHelper *)> m_pMemberFunction; + + mutable OUString m_sName; + + void implReInsert( ) override; + void implReRemove( ) override; + OGroupSectionUndo(const OGroupSectionUndo&) = delete; + void operator =(const OGroupSectionUndo&) = delete; + public: + //OGroupSectionUndo( const css::uno::Reference< css::report::XSection >& _xSection + OGroupSectionUndo( OReportModel& rMod + ,sal_uInt16 _nSlot + ,::std::function<css::uno::Reference< css::report::XSection >(OGroupHelper *)> _pMemberFunction + ,const css::uno::Reference< css::report::XGroup >& _xGroup + ,Action _eAction + ,const char* pCommentID); + + virtual OUString GetComment() const override; + }; + + /** /class OGroupUndo + * \brief Undo action for removing a group object. + */ + class OGroupUndo : public OCommentUndoAction + { + css::uno::Reference< css::report::XGroup> m_xGroup; ///<! the group for the undo redo action + css::uno::Reference< css::report::XReportDefinition > m_xReportDefinition; ///<! the parent report definition + Action m_eAction; ///<! the current action + sal_Int32 m_nLastPosition; ///<! the last position of the group + + void implReInsert( ); + void implReRemove( ); + public: + OGroupUndo(OReportModel& rMod + ,const char* pCommentID + ,Action _eAction + ,const css::uno::Reference< css::report::XGroup>& _xGroup + ,const css::uno::Reference< css::report::XReportDefinition >& _xReportDefinition); + virtual void Undo() override; + virtual void Redo() override; + }; +} +#endif // INCLUDED_REPORTDESIGN_SOURCE_UI_INC_RPTUNDO_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/reportdesign/source/ui/inc/ScrollHelper.hxx b/reportdesign/source/ui/inc/ScrollHelper.hxx new file mode 100644 index 000000000..c166e1f75 --- /dev/null +++ b/reportdesign/source/ui/inc/ScrollHelper.hxx @@ -0,0 +1,210 @@ +/* -*- 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 . + */ +#ifndef INCLUDED_REPORTDESIGN_SOURCE_UI_INC_SCROLLHELPER_HXX +#define INCLUDED_REPORTDESIGN_SOURCE_UI_INC_SCROLLHELPER_HXX + +#include <vcl/scrbar.hxx> +#include <com/sun/star/report/XSection.hpp> +#include <comphelper/propmultiplex.hxx> +#include "ReportDefines.hxx" +#include <cppuhelper/basemutex.hxx> +#include <rtl/ref.hxx> +#include "MarkedSection.hxx" +#include "ReportWindow.hxx" + +namespace rptui +{ + class ODesignView; + class OReportWindow; + class OSectionView; + + /** This class defines the scrollable area of the report design. It includes + the h-ruler and the sections, and end marker. Not the start marker. + */ + typedef vcl::Window OScrollWindowHelper_BASE; + class OScrollWindowHelper : public ::cppu::BaseMutex + , public OScrollWindowHelper_BASE/*TabPage*/ + , public ::comphelper::OPropertyChangeListener + , public IMarkedSection + { + private: + VclPtr<ScrollBar> m_aHScroll; + VclPtr<ScrollBar> m_aVScroll; + VclPtr<ScrollBarBox> m_aCornerWin; // window in the bottom right corner + Size m_aTotalPixelSize; + VclPtr<ODesignView> m_pParent; + VclPtr<OReportWindow> m_aReportWindow; + ::rtl::Reference<comphelper::OPropertyChangeMultiplexer > + m_pReportDefinitionMultiPlexer; // listener for property changes + + DECL_LINK( ScrollHdl, ScrollBar*, void); + Size ResizeScrollBars(); + void ImplInitSettings(); + void impl_initScrollBar( ScrollBar& _rScrollBar ) const; + + OScrollWindowHelper(OScrollWindowHelper const &) = delete; + void operator =(OScrollWindowHelper const &) = delete; + protected: + virtual void DataChanged( const DataChangedEvent& rDCEvt ) override; + // window + virtual void Resize() override; + virtual bool EventNotify( NotifyEvent& rNEvt ) override; + // OPropertyChangeListener + virtual void _propertyChanged(const css::beans::PropertyChangeEvent& _rEvent) override; + public: + OScrollWindowHelper( ODesignView* _pReportDesignView); + virtual ~OScrollWindowHelper() override; + virtual void dispose() override; + + /** late ctor + */ + void initialize(); + + Point getThumbPos() const { return Point(m_aHScroll->GetThumbPos(),m_aVScroll->GetThumbPos())/*m_aScrollOffset*/; } + void setTotalSize(sal_Int32 _nWidth, sal_Int32 _nHeight); + const Size& getTotalSize() const { return m_aTotalPixelSize; } + ScrollBar& GetHScroll() { return *m_aHScroll; } + ScrollBar& GetVScroll() { return *m_aVScroll; } + + // forwards + void SetMode( DlgEdMode _eMode ); + void SetInsertObj( sal_uInt16 eObj,const OUString& _sShapeType); + OUString const & GetInsertObjString() const; + void setGridSnap(bool bOn); + void setDragStripes(bool bOn); + /** copies the current selection in this section + */ + void Copy(); + + /** returns if paste is allowed + * + * \return <TRUE/> if paste is allowed + */ + bool IsPasteAllowed() const; + + /** paste a new control in this section + */ + void Paste(); + + /** Deletes the current selection in this section + * + */ + void Delete(); + + /** All objects will be marked. + */ + void SelectAll(const sal_uInt16 _nObjectType); + + /** returns <TRUE/> when an object is marked + */ + bool HasSelection() const; + + /** removes the section at the given position. + * + * \param _nPosition Zero based. + */ + void removeSection(sal_uInt16 _nPosition); + + /** adds a new section at position _nPosition. + If the section is <NULL/> nothing happens. + If the position is grater than the current elements, the section will be appended. + */ + void addSection(const css::uno::Reference< css::report::XSection >& _xSection + ,const OUString& _sColorEntry + ,sal_uInt16 _nPosition); + + sal_uInt16 getSectionCount() const; + + /** turns the grid on or off + * + * \param _bVisible + */ + void toggleGrid(bool _bVisible); + + /** unmark all objects on the views. + */ + void unmarkAllObjects(); + + /** shows or hides the ruler. + */ + void showRuler(bool _bShow); + + /** calculate the max width of the markers + * + * The end marker will not be used for calculation. + * \return the max width + */ + sal_Int32 getMaxMarkerWidth() const; + + /** checks if the keycode is known by the child windows + @param _rCode the keycode + @return <TRUE/> if the keycode is handled otherwise <FALSE/> + */ + bool handleKeyEvent(const KeyEvent& _rEvent); + + /** the section as marked or not marked + @param _pSectionView the section where to set the marked flag + @param _bMark the marked flag + */ + void setMarked(OSectionView const * _pSectionView, bool _bMark); + void setMarked(const css::uno::Reference< css::report::XSection>& _xSection, bool _bMark); + void setMarked(const css::uno::Sequence< css::uno::Reference< css::report::XReportComponent> >& _xShape, bool _bMark); + + // IMarkedSection + OSectionWindow* getMarkedSection(NearSectionAccess nsa = CURRENT) const override; + OSectionWindow* getSectionWindow(const css::uno::Reference< css::report::XSection>& _xSection) const; + virtual void markSection(const sal_uInt16 _nPos) override; + + + /** fills the positions of all collapsed sections. + * + * \param _rCollapsedPositions Out parameter which holds afterwards all positions of the collapsed sections. + */ + void fillCollapsedSections(::std::vector<sal_uInt16>& _rCollapsedPositions) const; + + /** collapse all sections given by their position + * + * \param _aCollapsedSections The position of the sections which should be collapsed. + */ + void collapseSections(const css::uno::Sequence< css::beans::PropertyValue>& _aCollapsedSections); + + /** align all marked objects in all sections + */ + void alignMarkedObjects(ControlModification _nControlModification, bool _bAlignAtSection); + + sal_uInt32 getMarkedObjectCount() const; + + /** zoom the ruler and view windows + */ + void zoom(const Fraction& _aZoom); + + /** fills the vector with all selected control models + /param _rSelection The vector will be filled and will not be cleared before. + */ + void fillControlModelSelection(::std::vector< css::uno::Reference< css::uno::XInterface > >& _rSelection) const; + + /** calculates the zoom factor. + @param _eType which kind of zoom is needed + */ + sal_uInt16 getZoomFactor(SvxZoomType _eType) const; + }; +} +#endif // INCLUDED_REPORTDESIGN_SOURCE_UI_INC_SCROLLHELPER_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/reportdesign/source/ui/inc/SectionView.hxx b/reportdesign/source/ui/inc/SectionView.hxx new file mode 100644 index 000000000..df3cbc7b0 --- /dev/null +++ b/reportdesign/source/ui/inc/SectionView.hxx @@ -0,0 +1,74 @@ +/* -*- 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 . + */ + +#ifndef INCLUDED_REPORTDESIGN_SOURCE_UI_INC_SECTIONVIEW_HXX +#define INCLUDED_REPORTDESIGN_SOURCE_UI_INC_SECTIONVIEW_HXX + + +#include <svx/svdview.hxx> +namespace rptui +{ +class OReportWindow; +class OReportSection; + + +// OSectionView + + +class OSectionView : public SdrView +{ +private: + VclPtr<OReportWindow> m_pReportWindow; + VclPtr<OReportSection> m_pSectionWindow; + + void ObjectRemovedInAliveMode( const SdrObject* pObject ); + OSectionView(const OSectionView&) = delete; + void operator =(const OSectionView&) = delete; +public: + + OSectionView( + SdrModel& rSdrModel, + OReportSection* _pSectionWindow, + OReportWindow* pEditor); + + virtual ~OSectionView() override; + + virtual void Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) override; + virtual void MarkListHasChanged() override; + virtual void MakeVisible( const tools::Rectangle& rRect, vcl::Window& rWin ) override; + + OReportSection* getReportSection() const { return m_pSectionWindow; } + + // switch the marked objects to the given layer. + void SetMarkedToLayer( SdrLayerID nLayerNo ); + + // return true when only shapes are marked, otherwise false. + bool OnlyShapesMarked() const; + + /* returns the common layer id of the marked objects, otherwise -1 will be returned. + */ + SdrLayerID GetLayerIdOfMarkedObjects() const; + + // returns true if objects at Drag & Drop is resize not move + bool IsDragResize() const; +}; +} +#endif // INCLUDED_REPORTDESIGN_SOURCE_UI_INC_SECTIONVIEW_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/reportdesign/source/ui/inc/SectionWindow.hxx b/reportdesign/source/ui/inc/SectionWindow.hxx new file mode 100644 index 000000000..2ef3e8b17 --- /dev/null +++ b/reportdesign/source/ui/inc/SectionWindow.hxx @@ -0,0 +1,132 @@ +/* -*- 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 . + */ +#ifndef INCLUDED_REPORTDESIGN_SOURCE_UI_INC_SECTIONWINDOW_HXX +#define INCLUDED_REPORTDESIGN_SOURCE_UI_INC_SECTIONWINDOW_HXX + +#include <com/sun/star/report/XSection.hpp> +#include <vcl/window.hxx> +#include <vcl/split.hxx> +#include <comphelper/propmultiplex.hxx> +#include <cppuhelper/basemutex.hxx> + +#include <UndoActions.hxx> +#include "StartMarker.hxx" +#include "EndMarker.hxx" +#include "ReportSection.hxx" + +namespace comphelper +{ + class OPropertyChangeMultiplexer; +} +namespace rptui +{ + class OViewsWindow; + class OSectionWindow : public vcl::Window + , public ::cppu::BaseMutex + , public ::comphelper::OPropertyChangeListener + { + VclPtr<OViewsWindow> m_pParent; + VclPtr<OStartMarker> m_aStartMarker; + VclPtr<OReportSection> m_aReportSection; + VclPtr<Splitter> m_aSplitter; + VclPtr<OEndMarker> m_aEndMarker; + + ::rtl::Reference< comphelper::OPropertyChangeMultiplexer> m_pSectionMulti; + ::rtl::Reference< comphelper::OPropertyChangeMultiplexer> m_pGroupMulti; + + OSectionWindow(OSectionWindow const &) = delete; + void operator =(OSectionWindow const &) = delete; + + /** set the title of the group header or footer + * + * \param _xGroup + * \param _nResId + * \param _pGetSection + * \param _pIsSectionOn + * @return sal_True when title was set otherwise FALSE + */ + bool setGroupSectionTitle( + const css::uno::Reference<css::report::XGroup>& _xGroup, const char* pResId, + const ::std::function<css::uno::Reference<css::report::XSection>(OGroupHelper*)>& + _pGetSection, + const ::std::function<bool(OGroupHelper*)>& _pIsSectionOn); + + /** set the title of the (report/page) header or footer + * + * \param _xGroup + * \param _nResId + * \param _pGetSection + * \param _pIsSectionOn + * @return sal_True when title was set otherwise FALSE + */ + bool setReportSectionTitle( + const css::uno::Reference<css::report::XReportDefinition>& _xReport, const char* pResId, + const ::std::function<css::uno::Reference<css::report::XSection>(OReportHelper*)>& + _pGetSection, + const ::std::function<bool(OReportHelper*)>& _pIsSectionOn); + void ImplInitSettings(); + + DECL_LINK(Collapsed, OColorListener&, void); + DECL_LINK(StartSplitHdl, Splitter*, void); + DECL_LINK(SplitHdl, Splitter*, void); + DECL_LINK(EndSplitHdl, Splitter*, void); + + + virtual void DataChanged( const DataChangedEvent& rDCEvt ) override; + // Window overrides + virtual void Resize() override; + + protected: + virtual void _propertyChanged(const css::beans::PropertyChangeEvent& _rEvent) override; + public: + OSectionWindow( OViewsWindow* _pParent + ,const css::uno::Reference< css::report::XSection >& _xSection + ,const OUString& _sColorEntry); + virtual ~OSectionWindow() override; + virtual void dispose() override; + + OStartMarker& getStartMarker() { return *m_aStartMarker; } + OReportSection& getReportSection() { return *m_aReportSection; } + OEndMarker& getEndMarker() { return *m_aEndMarker; } + OViewsWindow* getViewsWindow() { return m_pParent; } + + void setCollapsed(bool _bCollapsed); + + /** triggers the property browser with the section + @param _pStartMarker + */ + void showProperties(); + + /** set the marker as marked or not marked + @param _bMark set the new state of the marker + */ + void setMarked(bool _bMark); + + /** zoom the ruler and view windows + */ + void zoom(const Fraction& _aZoom); + + void scrollChildren(long _nThumbPosX); + }; + +} // rptui + +#endif // INCLUDED_REPORTDESIGN_SOURCE_UI_INC_SECTIONWINDOW_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/reportdesign/source/ui/inc/StartMarker.hxx b/reportdesign/source/ui/inc/StartMarker.hxx new file mode 100644 index 000000000..296255303 --- /dev/null +++ b/reportdesign/source/ui/inc/StartMarker.hxx @@ -0,0 +1,82 @@ +/* -*- 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 . + */ +#ifndef INCLUDED_REPORTDESIGN_SOURCE_UI_INC_STARTMARKER_HXX +#define INCLUDED_REPORTDESIGN_SOURCE_UI_INC_STARTMARKER_HXX + +#include <osl/interlck.h> +#include <svtools/ruler.hxx> +#include "ColorListener.hxx" +#include <vcl/fixed.hxx> + + +namespace rptui +{ + class OSectionWindow; + class OStartMarker : public OColorListener + { + + VclPtr<Ruler> m_aVRuler; + VclPtr<FixedText> m_aText; + VclPtr<FixedImage> m_aImage; + VclPtr<OSectionWindow> m_pParent; + static Image* s_pDefCollapsed; + static Image* s_pDefExpanded; + static oslInterlockedCount s_nImageRefCount; /// When 0 all static images will be destroyed + + bool m_bShowRuler; + + void changeImage(); + void initDefaultNodeImages(); + void setColor(); + + virtual void ImplInitSettings() override; + virtual void ApplySettings(vcl::RenderContext& rRenderContext) override; + + OStartMarker(OStartMarker const &) = delete; + void operator =(OStartMarker const &) = delete; + public: + OStartMarker(OSectionWindow* _pParent,const OUString& _sColorEntry); + virtual ~OStartMarker() override; + virtual void dispose() override; + + // SfxListener + virtual void Notify(SfxBroadcaster & rBc, SfxHint const & rHint) override; + // Window overrides + virtual void Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect) override; + virtual void MouseButtonUp(const MouseEvent& rMEvt) override; + virtual void Resize() override; + virtual void RequestHelp(const HelpEvent& rHEvt) override; + + void setTitle(const OUString& _sTitle); + sal_Int32 getMinHeight() const; + + /** shows or hides the ruler. + */ + void showRuler(bool _bShow); + + virtual void setCollapsed(bool _bCollapsed) override; + + /** zoom the ruler and view windows + */ + void zoom(const Fraction& _aZoom); + }; +} +#endif // INCLUDED_REPORTDESIGN_SOURCE_UI_INC_STARTMARKER_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/reportdesign/source/ui/inc/UITools.hxx b/reportdesign/source/ui/inc/UITools.hxx new file mode 100644 index 000000000..13aafb14f --- /dev/null +++ b/reportdesign/source/ui/inc/UITools.hxx @@ -0,0 +1,181 @@ +/* -*- 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 . + */ +#ifndef INCLUDED_REPORTDESIGN_SOURCE_UI_INC_UITOOLS_HXX +#define INCLUDED_REPORTDESIGN_SOURCE_UI_INC_UITOOLS_HXX + +#include <com/sun/star/report/XGroup.hpp> +#include <com/sun/star/report/XReportControlFormat.hpp> +#include <com/sun/star/report/XShape.hpp> +#include <com/sun/star/awt/XWindow.hpp> +#include <com/sun/star/beans/NamedValue.hpp> +#include <com/sun/star/container/XIndexAccess.hpp> +#include <com/sun/star/sdbc/XRowSet.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> +#include "ReportSection.hxx" +#include <rtl/ref.hxx> +#include <vcl/taskpanelist.hxx> +#include <comphelper/stl_types.hxx> + +class SdrPage; +class SdrObject; +class SdrUnoObj; +class SdrView; +namespace tools { class Rectangle; } +namespace comphelper +{ + class OPropertyChangeMultiplexer; + class OPropertyChangeListener; +} +namespace rptui +{ + /** returns the position of the object inside the index container + @param _xReportDefinition the report definition to get the groups + @param _xGroup the group to search + @return returns the position of the group in the list, otherwise -1 + */ + template<typename T> sal_Int32 getPositionInIndexAccess( + const css::uno::Reference< css::container::XIndexAccess >& _xCollection + ,const css::uno::Reference< T >& _xSearch) + { + sal_Int32 nCount = _xCollection->getCount(); + sal_Int32 i = (nCount == 0) ? -1 : 0; + for (;i<nCount ; ++i) + { + css::uno::Reference< T > xObject(_xCollection->getByIndex(i),css::uno::UNO_QUERY); + if ( xObject == _xSearch ) + break; + } + return i; + } + + /** set the name of the header and footer of the group by the expression appended by the localized name of the section + @param _xGroup the group where the header/footer name is set by the expression of the group + */ + void adjustSectionName(const css::uno::Reference< css::report::XGroup >& _xGroup,sal_Int32 _nPos); + + /** add a listener for the properties size, left margin, right margin to the page style + * + * \param _xReportDefinition + * \param _pListener + * \return + */ + ::rtl::Reference< comphelper::OPropertyChangeMultiplexer> addStyleListener( const css::uno::Reference< css::report::XReportDefinition >& _xReportDefinition + ,::comphelper::OPropertyChangeListener* _pListener); + + /** opens the common character font dialog + */ + bool openCharDialog( + const css::uno::Reference< css::report::XReportControlFormat>& _xReportControlFormat, + const css::uno::Reference< css::awt::XWindow>& _xWindow, + css::uno::Sequence< css::beans::NamedValue >& _out_rNewValues + ); + + /** opens the area dialog for shapes + */ + bool openAreaDialog( + const css::uno::Reference< css::report::XShape >& _xShape + ,const css::uno::Reference< css::awt::XWindow>& _xWindow + ); + + /** opens the formula dialog + @param _out_rFormula + the formula chosen by the user + @precond + we're really inspecting a database report (well, a RowSet at least) + @return + <TRUE/> if and only if the user successfully chose a clause + */ + bool openDialogFormula_nothrow( OUString& _in_out_rFormula + , const css::uno::Reference< css::uno::XComponentContext >& _xContext + , const css::uno::Reference< css::awt::XWindow>& _xWindow + , const css::uno::Reference < css::beans::XPropertySet >& _xRowSet + ); + + /** applies the character settings previously obtained via openCharDialog + */ + void applyCharacterSettings( + const css::uno::Reference< css::report::XReportControlFormat >& _rxReportControlFormat, + const css::uno::Sequence< css::beans::NamedValue >& _rSettings + ); + + /** notifySystemWindow adds or remove the given window _pToRegister at the Systemwindow found when search _pWindow. + @param pWindow + The window which is used to search for the SystemWindow. + @param pToRegister + The window which should be added or removed on the TaskPaneList. + @param rMemFunc + The member function which should be called at the SystemWindow when found. + Possible values are: + ::comphelper::mem_fun(&TaskPaneList::AddWindow) + ::comphelper::mem_fun(&TaskPaneList::RemoveWindow) + */ + void notifySystemWindow(vcl::Window const * pWindow, vcl::Window* pToRegister, const ::comphelper::mem_fun1_t<TaskPaneList, vcl::Window*>& rMemFunc); + + + const sal_Int16 ISOVER_IGNORE_CUSTOMSHAPES = 1; + + /** checks whether the given rectangle overlapps another OUnoObject object in that view. + * + * \param _rRect + * \param _rPage + * \param _bAllObjects if <TRUE/> all objects are taken into account, otherwise only not marked ones + * \return the object which is overlapped, otherwise <NULL/> + */ + SdrObject* isOver(const tools::Rectangle& _rRect,SdrPage const & _rPage,SdrView const & _rView,bool _bAllObjects = false,SdrObject const * _pIgnore = nullptr, sal_Int16 _nIgnoreType=0); + + SdrObject* isOver(const tools::Rectangle& _rRect,SdrPage const & _rPage,SdrView const & _rView,bool _bAllObjects, std::unique_ptr<SdrUnoObj, SdrObjectFreeOp> _pIgnoreList[], int _nIgnoreListLength); + + /** checks whether the given OUnoObject object rectangle overlapps another object in that view. + * + * \param _pObj + * \param _rPage + * \param _rView + * \return the object which is overlapped, otherwise <NULL/>. If the given object is not of type OUnoObject <NULL/> will be returned. + */ + SdrObject* isOver(SdrObject const * _pObj,SdrPage const & _rPage,SdrView const & _rView); + + /** retrieves the names of the parameters of the command which the given RowSet is bound to + */ + css::uno::Sequence< OUString > + getParameterNames( const css::uno::Reference< css::sdbc::XRowSet >& _rxRowSet ); + + /** ensures that no control overlaps the given one. + * + * \param pControl the control which should place in the section without overlapping + * \param _pReportSection the section + * \param _bInsert sal_True when the control should be inserted, otherwise not. + */ + void correctOverlapping(SdrObject* pControl,OReportSection const & _aReportSection,bool _bInsert = true); + + /** returns a Rectangle of a given SdrObject + * + * \param pControl the SdrObject + */ + + tools::Rectangle getRectangleFromControl(SdrObject* pControl); + + /** sets the map mode at the window + @param _aZoom the zoom scale + @param _rWindow where to set the map mode + */ + void setZoomFactor(const Fraction& _aZoom, vcl::Window& _rWindow); +} +#endif // INCLUDED_REPORTDESIGN_SOURCE_UI_INC_UITOOLS_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/reportdesign/source/ui/inc/ViewsWindow.hxx b/reportdesign/source/ui/inc/ViewsWindow.hxx new file mode 100644 index 000000000..e03ff6364 --- /dev/null +++ b/reportdesign/source/ui/inc/ViewsWindow.hxx @@ -0,0 +1,294 @@ +/* -*- 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 . + */ +#ifndef INCLUDED_REPORTDESIGN_SOURCE_UI_INC_VIEWSWINDOW_HXX +#define INCLUDED_REPORTDESIGN_SOURCE_UI_INC_VIEWSWINDOW_HXX + +#include <com/sun/star/report/XSection.hpp> +#include <vcl/window.hxx> +#include <svtools/colorcfg.hxx> +#include "ReportDefines.hxx" +#include "SectionView.hxx" +#include <unotools/options.hxx> +#include <vector> + +#include "MarkedSection.hxx" +#include "SectionWindow.hxx" + +class SdrHdl; + +namespace rptui +{ + class OReportWindow; + class OReportSection; + class OSectionView; + enum class ControlModification; + + struct RectangleLess + { + enum CompareMode { POS_LEFT,POS_RIGHT,POS_UPPER,POS_DOWN,POS_CENTER_HORIZONTAL,POS_CENTER_VERTICAL }; + CompareMode m_eCompareMode; + Point m_aRefPoint; + RectangleLess(CompareMode _eCompareMode,const Point& _rRefPoint ) : m_eCompareMode(_eCompareMode),m_aRefPoint(_rRefPoint){} + bool operator() (const tools::Rectangle& lhs, const tools::Rectangle& rhs) const + { + switch(m_eCompareMode) + { + case POS_LEFT: + return lhs.Left() < rhs.Left(); + case POS_RIGHT: + return lhs.Right() >= rhs.Right(); + case POS_UPPER: + return lhs.Top() < rhs.Top(); + case POS_DOWN: + return lhs.Bottom() >= rhs.Bottom(); + case POS_CENTER_HORIZONTAL: + return std::abs(m_aRefPoint.X() - lhs.Center().X()) < std::abs(m_aRefPoint.X() - rhs.Center().X()); + case POS_CENTER_VERTICAL: + return std::abs(lhs.Center().Y() - m_aRefPoint.Y()) < std::abs(rhs.Center().Y() - m_aRefPoint.Y()); + } + return false; + } + }; + + class OViewsWindow : public vcl::Window + , public utl::ConfigurationListener + , public IMarkedSection + { + typedef ::std::multimap<tools::Rectangle,::std::pair<SdrObject*,OSectionView*>,RectangleLess> TRectangleMap; + public: + typedef ::std::vector< VclPtr<OSectionWindow> > TSectionsMap; + + private: + TSectionsMap m_aSections; + svtools::ColorConfig m_aColorConfig; + VclPtr<OReportWindow> m_pParent; + OUString m_sShapeType; + bool m_bInUnmark; + + void ImplInitSettings(); + /** returns the iterator at pos _nPos or the end() + */ + TSectionsMap::iterator getIteratorAtPos(sal_uInt16 _nPos); + void collectRectangles(TRectangleMap& _rMap); + static void collectBoundResizeRect(const TRectangleMap& _rSortRectangles, ControlModification _nControlModification,bool _bAlignAtSection,tools::Rectangle& _rBound,tools::Rectangle& _rResize); + void impl_resizeSectionWindow(OSectionWindow& _rSectionWindow,Point& _rStartPoint,bool _bSet); + + OViewsWindow(OViewsWindow const &) = delete; + void operator =(OViewsWindow const &) = delete; + protected: + virtual void DataChanged( const DataChangedEvent& rDCEvt ) override; + // Window overrides + virtual void MouseButtonDown( const MouseEvent& rMEvt ) override; + virtual void MouseButtonUp( const MouseEvent& rMEvt ) override; + + virtual void Paint( vcl::RenderContext& /*rRenderContext*/, const tools::Rectangle& rRect ) override; + virtual void ConfigurationChanged( utl::ConfigurationBroadcaster*, ConfigurationHints ) override; + public: + OViewsWindow( + OReportWindow* _pReportWindow); + virtual ~OViewsWindow() override; + virtual void dispose() override; + + // Window overrides + virtual void Resize() override; + + void resize(const OSectionWindow& _rSectionWindow); + + OReportWindow* getView() const { return m_pParent; } + + /** removes the section at the given position. + * + * \param _nPosition Zero based. + */ + void removeSection(sal_uInt16 _nPosition); + + /** adds a new section at position _nPosition. + If the section is <NULL/> nothing happens. + If the position is grater than the current elements, the section will be appended. + */ + void addSection(const css::uno::Reference< css::report::XSection >& _xSection + ,const OUString& _sColorEntry + ,sal_uInt16 _nPosition); + + sal_uInt16 getSectionCount() const; + /** return the section at the given position + * + * \param _nPos + * \return the section at this pos or an empty section + */ + OSectionWindow* getSectionWindow(const sal_uInt16 _nPos) const; + + /** turns the grid on or off + * + * \param _bVisible + */ + void toggleGrid(bool _bVisible); + void setGridSnap(bool bOn); + void setDragStripes(bool bOn); + + /** returns the total accumulated height of all sections until _pSection is reached + */ + sal_Int32 getTotalHeight() const; + + bool empty() const { return m_aSections.empty(); } + void SetMode( DlgEdMode m_eMode ); + void SetInsertObj( sal_uInt16 eObj,const OUString& _sShapeType); + const OUString& GetInsertObjString() const { return m_sShapeType;} + /** copies the current selection in this section + */ + void Copy(); + + /** returns if paste is allowed + * + * \return <TRUE/> if paste is allowed + */ + bool IsPasteAllowed() const; + + /** paste a new control in this section + */ + void Paste(); + + /** Deletes the current selection in this section + * + */ + void Delete(); + + /** All objects will be marked. + */ + void SelectAll(const sal_uInt16 _nObjectType); + + /** returns <TRUE/> when an object is marked + */ + bool HasSelection() const; + + /** unmark all objects on the views without the given one. + * + * @param _pSectionView The view where the objects should not be unmarked. + */ + void unmarkAllObjects(OSectionView const * _pSectionView); + + /** returns the report section window for the given xsection + @param _xSection the section + */ + OSectionWindow* getSectionWindow(const css::uno::Reference< css::report::XSection>& _xSection) const; + + /** checks if the keycode is known by the child windows + @param _rCode the keycode + @return <TRUE/> if the keycode is handled otherwise <FALSE/> + */ + bool handleKeyEvent(const KeyEvent& _rEvent); + + /** the section as marked or not marked + @param _pSectionView the section where to set the marked flag + @param _bMark the marked flag + */ + void setMarked(OSectionView const * _pSectionView, bool _bMark); + void setMarked(const css::uno::Reference< css::report::XSection>& _xSection, bool _bMark); + void setMarked(const css::uno::Sequence< css::uno::Reference< css::report::XReportComponent> >& _xShape, bool _bMark); + + // IMarkedSection + OSectionWindow* getMarkedSection(NearSectionAccess nsa = CURRENT) const override; + virtual void markSection(const sal_uInt16 _nPos) override; + + /** align all marked objects in all sections + */ + void alignMarkedObjects(ControlModification _nControlModification, bool _bAlignAtSection); + + /** creates a default object + * + */ + void createDefault(); + + /** shows or hides the ruler. + */ + void showRuler(bool _bShow); + + /** returns the currently set shape type. + * + * \return \member m_sShapeType + */ + const OUString& getShapeType() const { return m_sShapeType; } + + /** returns the current position in the list + */ + sal_uInt16 getPosition(const OSectionWindow* _pSectionWindow) const; + + /** calls on every section BrkAction + * + */ + void BrkAction(); + void BegMarkObj(const Point& _aPnt,const OSectionView* _pSection); + + private: + void BegDragObj_createInvisibleObjectAtPosition(const tools::Rectangle& _aRect, const OSectionView& _rSection); + void EndDragObj_removeInvisibleObjects(); + Point m_aDragDelta; + ::std::vector<SdrObject*> m_aBegDragTempList; + public: + void BegDragObj(const Point& _aPnt, SdrHdl* _pHdl,const OSectionView* _pSection); + void EndDragObj(bool _bDragIntoNewSection,const OSectionView* _pSection,const Point& _aPnt); + + void EndAction(); + void ForceMarkedToAnotherPage(); + bool IsAction() const; + bool IsDragObj() const; + void handleKey(const vcl::KeyCode& _rCode); + void stopScrollTimer(); + + /** return the section at the given point which is relative to the given section + * + * \param _pSection the section which is used as reference point + * \param _rPnt the point, it will be changed that it is inside the section which will be returned + * \return the section + */ + OSectionView* getSectionRelativeToPosition(const OSectionView* _pSection,Point& _rPnt); + + void MovAction(const Point& rPnt,const OSectionView* _pSection, bool _bControlKeySet); + + sal_uInt32 getMarkedObjectCount() const; + + /** fills the positions of all collapsed sections. + * + * \param _rCollapsedPositions Out parameter which holds afterwards all positions of the collapsed sections. + */ + void fillCollapsedSections(::std::vector<sal_uInt16>& _rCollapsedPositions) const; + + /** collapse all sections given by their position + * + * \param _aCollapsedSections The position of the sections which should be collapsed. + */ + void collapseSections(const css::uno::Sequence< css::beans::PropertyValue>& _aCollapsedSections); + + /** zoom the ruler and view windows + */ + void zoom(const Fraction& _aZoom); + + void scrollChildren(const Point& _aThumbPos); + + /** fills the vector with all selected control models + /param _rSelection The vector will be filled and will not be cleared before. + */ + void fillControlModelSelection(::std::vector< css::uno::Reference< css::uno::XInterface > >& _rSelection) const; + }; + +} // rptui + +#endif // INCLUDED_REPORTDESIGN_SOURCE_UI_INC_VIEWSWINDOW_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/reportdesign/source/ui/inc/dlgedclip.hxx b/reportdesign/source/ui/inc/dlgedclip.hxx new file mode 100644 index 000000000..54a0baab3 --- /dev/null +++ b/reportdesign/source/ui/inc/dlgedclip.hxx @@ -0,0 +1,80 @@ +/* -*- 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 . + */ + +#ifndef INCLUDED_REPORTDESIGN_SOURCE_UI_INC_DLGEDCLIP_HXX +#define INCLUDED_REPORTDESIGN_SOURCE_UI_INC_DLGEDCLIP_HXX + +#include <vcl/transfer.hxx> +#include <com/sun/star/beans/NamedValue.hpp> + +namespace rptui +{ + +// OReportExchange + +/** \class OReportExchange + * \brief defines a clipboard format for copying selection elements. + * \ingroup reportdesign_source_ui_report + * + * + */ +class OReportExchange : public TransferableHelper +{ +public: + typedef css::uno::Sequence< css::beans::NamedValue > TSectionElements; + + /** Constructs a new exchange object with section elements + * + * \param _rCopyElements the elements to copy. Each section is one entry. The value must be a sequence of elements. + * \return + */ + OReportExchange( const TSectionElements& _rCopyElements); + + /** checks whether or not a descriptor can be extracted from the data flavor vector given + * + * \param _rFlavors + available flavors + * \return + */ + static bool canExtract(const DataFlavorExVector& _rFlavors); + + /** extract the section elements + * + * \param _rData the clipboard data + * \return the copied elements + */ + static TSectionElements extractCopies(const TransferableDataHelper& _rData); + + /** returns the format id. + * + * \return the registered format id + */ + static SotClipboardFormatId getDescriptorFormatId(); + +protected: + // TransferableHelper overridables + virtual void AddSupportedFormats() override; + virtual bool GetData( const css::datatransfer::DataFlavor& rFlavor, const OUString& rDestDoc ) override; +private: + TSectionElements m_aCopyElements; +}; +} +#endif // INCLUDED_REPORTDESIGN_SOURCE_UI_INC_DLGEDCLIP_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/reportdesign/source/ui/inc/dlgedfac.hxx b/reportdesign/source/ui/inc/dlgedfac.hxx new file mode 100644 index 000000000..f35d65757 --- /dev/null +++ b/reportdesign/source/ui/inc/dlgedfac.hxx @@ -0,0 +1,43 @@ +/* -*- 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 . + */ + +#ifndef INCLUDED_REPORTDESIGN_SOURCE_UI_INC_DLGEDFAC_HXX +#define INCLUDED_REPORTDESIGN_SOURCE_UI_INC_DLGEDFAC_HXX + + +#include <svx/svdobj.hxx> +#include <tools/link.hxx> + +namespace rptui +{ + +// DlgEdFactory + +class DlgEdFactory +{ +public: + DlgEdFactory(); + ~DlgEdFactory() COVERITY_NOEXCEPT_FALSE; + + DECL_STATIC_LINK( DlgEdFactory, MakeObject, SdrObjCreatorParams, SdrObject* ); +}; +} +#endif // INCLUDED_REPORTDESIGN_SOURCE_UI_INC_DLGEDFAC_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/reportdesign/source/ui/inc/dlgedfunc.hxx b/reportdesign/source/ui/inc/dlgedfunc.hxx new file mode 100644 index 000000000..804b814ee --- /dev/null +++ b/reportdesign/source/ui/inc/dlgedfunc.hxx @@ -0,0 +1,155 @@ +/* -*- 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 . + */ +#ifndef INCLUDED_REPORTDESIGN_SOURCE_UI_INC_DLGEDFUNC_HXX +#define INCLUDED_REPORTDESIGN_SOURCE_UI_INC_DLGEDFUNC_HXX + +#include <tools/gen.hxx> +#include <vcl/event.hxx> +#include <vcl/timer.hxx> +#include <com/sun/star/uno/XInterface.hpp> + +class Timer; +class MouseEvent; +class Point; +class SdrTextObj; +class SdrObject; +namespace rptui +{ + +class OReportSection; +class OSectionView; + + +// DlgEdFunc + + +class DlgEdFunc /* : public LinkHdl */ +{ + DlgEdFunc(const DlgEdFunc&) = delete; + void operator =(const DlgEdFunc&) = delete; +protected: + VclPtr<OReportSection> m_pParent; + OSectionView& m_rView; + Timer aScrollTimer; + Point m_aMDPos; + css::uno::Reference<css::uno::XInterface> m_xOverlappingObj; + SdrObject * m_pOverlappingObj; + Color m_nOverlappedControlColor; + Color m_nOldColor; + bool m_bSelectionMode; + bool m_bUiActive; + bool m_bShowPropertyBrowser; + + DECL_LINK( ScrollTimeout, Timer *, void ); + void ForceScroll( const Point& rPos ); + /** checks that no other object is overlapped. + * + * \param rMEvt + */ + void checkMovementAllowed(const MouseEvent& rMEvt); + + /** sets the correct mouse pointer when moving an object + * + * \param rMEvt + * \return <TRUE/> when the pointer was already set. + */ + bool setMovementPointer(const MouseEvent& rMEvt); + + bool isRectangleHit(const MouseEvent& rMEvt); + /** + returns true, as long as only customshapes in the marked list, + custom shapes can drop every where + */ + bool isOnlyCustomShapeMarked() const; + + /** activate object if it is of type OBJ_OLE2 + */ + void activateOle(SdrObject* _pObj); + + void checkTwoCklicks(const MouseEvent& rMEvt); + +public: + DlgEdFunc( OReportSection* pParent ); + virtual ~DlgEdFunc(); + + virtual bool MouseButtonDown( const MouseEvent& rMEvt ); + virtual bool MouseButtonUp( const MouseEvent& rMEvt ); + virtual bool MouseMove( const MouseEvent& rMEvt ); + + /** checks if the keycode is known by the child windows + @param _rCode the keycode + @return <TRUE/> if the keycode is handled otherwise <FALSE/> + */ + bool handleKeyEvent(const KeyEvent& _rEvent); + + /** returns <TRUE/> if the mouse event is over an existing object + * + * \param rMEvt + * \return <TRUE/> if overlapping, otherwise <FALSE/> + */ + bool isOverlapping(const MouseEvent& rMEvt); + void setOverlappedControlColor(Color _nColor); + void stopScrollTimer(); + + /** deactivate all ole object + */ + void deactivateOle(bool _bSelect = false); + + bool isUiActive() const { return m_bUiActive; } +protected: + void colorizeOverlappedObject(SdrObject* _pOverlappedObj); + void unColorizeOverlappedObj(); + + +}; + + +// DlgEdFuncInsert + + +class DlgEdFuncInsert : public DlgEdFunc +{ +public: + DlgEdFuncInsert( OReportSection* pParent ); + virtual ~DlgEdFuncInsert() override; + + virtual bool MouseButtonDown( const MouseEvent& rMEvt ) override; + virtual bool MouseButtonUp( const MouseEvent& rMEvt ) override; + virtual bool MouseMove( const MouseEvent& rMEvt ) override; +}; + + +// DlgEdFuncSelect + + +class DlgEdFuncSelect : public DlgEdFunc +{ +public: + DlgEdFuncSelect( OReportSection* pParent ); + virtual ~DlgEdFuncSelect() override; + + virtual bool MouseButtonDown( const MouseEvent& rMEvt ) override; + virtual bool MouseButtonUp( const MouseEvent& rMEvt ) override; + virtual bool MouseMove( const MouseEvent& rMEvt ) override; +}; + +} +#endif // INCLUDED_REPORTDESIGN_SOURCE_UI_INC_DLGEDFUNC_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/reportdesign/source/ui/inc/dlgpage.hxx b/reportdesign/source/ui/inc/dlgpage.hxx new file mode 100644 index 000000000..5bebf0958 --- /dev/null +++ b/reportdesign/source/ui/inc/dlgpage.hxx @@ -0,0 +1,47 @@ +/* -*- 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 . + */ +#ifndef INCLUDED_REPORTDESIGN_SOURCE_UI_INC_DLGPAGE_HXX +#define INCLUDED_REPORTDESIGN_SOURCE_UI_INC_DLGPAGE_HXX + +#include <sfx2/tabdlg.hxx> + +namespace rptui +{ +/************************************************************************* +|* +|* Page setup tab dialog +|* +\************************************************************************/ +class ORptPageDialog : public SfxTabDialogController +{ +private: + ORptPageDialog(const ORptPageDialog&) = delete; + void operator =(const ORptPageDialog&) = delete; + +public: + + ORptPageDialog(weld::Window* pParent, const SfxItemSet* pAttr, const OUString &rDialog); + virtual void PageCreated(const OString& rId, SfxTabPage &rPage) override; +}; + +} // namespace rptui + +#endif // INCLUDED_REPORTDESIGN_SOURCE_UI_INC_DLGPAGE_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/reportdesign/source/ui/inc/metadata.hxx b/reportdesign/source/ui/inc/metadata.hxx new file mode 100644 index 000000000..63281076d --- /dev/null +++ b/reportdesign/source/ui/inc/metadata.hxx @@ -0,0 +1,146 @@ +/* -*- 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 . + */ +#ifndef INCLUDED_REPORTDESIGN_SOURCE_UI_INC_METADATA_HXX +#define INCLUDED_REPORTDESIGN_SOURCE_UI_INC_METADATA_HXX + +#include <com/sun/star/beans/Property.hpp> +#include <com/sun/star/inspection/XPropertyHandler.hpp> +#include <o3tl/typed_flags_set.hxx> +#include <vector> + + //= UI flags (for all browsable properties) +enum class PropUIFlags { + NONE = 0x0001, // no special flag + Composeable = 0x0002, // the property is "composeable", i.e. an intersection of property + // sets should expose it, if all elements do + DataProperty = 0x0004 // the property is to appear on the "Data" page +}; +namespace o3tl { + template<> struct typed_flags<PropUIFlags> : is_typed_flags<PropUIFlags, 0x0007> {}; +} + + +namespace rptui +{ + + + struct OPropertyInfoImpl; + + + //= OPropertyInfoService + + class OPropertyInfoService final + { + public: + // IPropertyInfoService + static sal_Int32 getPropertyId(const OUString& _rName); + static OUString getPropertyTranslation(sal_Int32 _nId); + static OString getPropertyHelpId(sal_Int32 _nId); + static PropUIFlags getPropertyUIFlags(sal_Int32 _nId); + static void getExcludeProperties(::std::vector< css::beans::Property >& _rExcludeProperties,const css::uno::Reference< css::inspection::XPropertyHandler >& _xFormComponentHandler); + + static bool isComposable( + const OUString& _rPropertyName, + const css::uno::Reference< css::inspection::XPropertyHandler >& _xFormComponentHandler + ); + + private: + static const OPropertyInfoImpl* getPropertyInfo(); + + static const OPropertyInfoImpl* getPropertyInfo(const OUString& _rName); + static const OPropertyInfoImpl* getPropertyInfo(sal_Int32 _nId); + + OPropertyInfoService(const OPropertyInfoService&) = delete; + void operator =(const OPropertyInfoService&) = delete; + OPropertyInfoService() = delete; + + static sal_uInt16 s_nCount; + static OPropertyInfoImpl* s_pPropertyInfos; + // TODO: a real structure which allows quick access by name as well as by id + }; + + + //= HelpIdUrl + + /// small helper to translate help ids into help urls + class HelpIdUrl + { + public: + static OUString getHelpURL( const OString& _sHelpId ); + }; + + + //= property ids (for all browsable properties) + //= The ID is used for the view order in the property browser. + + + #define PROPERTY_ID_FORCENEWPAGE 1 + #define PROPERTY_ID_NEWROWORCOL 2 + #define PROPERTY_ID_KEEPTOGETHER 3 + #define PROPERTY_ID_CANGROW 4 + #define PROPERTY_ID_CANSHRINK 5 + #define PROPERTY_ID_REPEATSECTION 6 + #define PROPERTY_ID_PRESERVEIRI 7 + #define PROPERTY_ID_VISIBLE 8 + #define PROPERTY_ID_GROUPKEEPTOGETHER 9 + #define PROPERTY_ID_PAGEHEADEROPTION 10 + #define PROPERTY_ID_PAGEFOOTEROPTION 11 + #define PROPERTY_ID_POSITIONX 12 + #define PROPERTY_ID_POSITIONY 13 + #define PROPERTY_ID_WIDTH 14 + #define PROPERTY_ID_HEIGHT 15 + #define PROPERTY_ID_AUTOGROW 16 + #define PROPERTY_ID_FORMULA 17 + #define PROPERTY_ID_CONDITIONALPRINTEXPRESSION 18 + #define PROPERTY_ID_PRINTREPEATEDVALUES 19 + #define PROPERTY_ID_PRINTWHENGROUPCHANGE 20 + #define PROPERTY_ID_INITIALFORMULA 21 + #define PROPERTY_ID_STARTNEWCOLUMN 22 + #define PROPERTY_ID_TYPE 23 + #define PROPERTY_ID_DATAFIELD 24 + #define PROPERTY_ID_CHARFONTNAME 25 + #define PROPERTY_ID_DEEPTRAVERSING 26 + #define PROPERTY_ID_PREEVALUATED 27 + + #define PROPERTY_ID_BACKTRANSPARENT 28 + #define PROPERTY_ID_CONTROLBACKGROUNDTRANSPARENT 29 + #define PROPERTY_ID_BACKCOLOR 30 + #define PROPERTY_ID_CONTROLBACKGROUND 31 + + #define PROPERTY_ID_FORMULALIST 32 + #define PROPERTY_ID_SCOPE 33 + #define PROPERTY_ID_RESETPAGENUMBER 34 + #define PROPERTY_ID_CHARTTYPE 35 + #define PROPERTY_ID_MASTERFIELDS 36 + #define PROPERTY_ID_DETAILFIELDS 37 + #define PROPERTY_ID_PREVIEW_COUNT 38 + #define PROPERTY_ID_AREA 39 + #define PROPERTY_ID_MIMETYPE 40 + + #define PROPERTY_ID_FONT 41 + #define PROPERTY_ID_PARAADJUST 42 + #define PROPERTY_ID_VERTICALALIGN 43 + + +} // namespace rptui + + +#endif // INCLUDED_REPORTDESIGN_SOURCE_UI_INC_METADATA_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/reportdesign/source/ui/inc/propbrw.hxx b/reportdesign/source/ui/inc/propbrw.hxx new file mode 100644 index 000000000..5b697df05 --- /dev/null +++ b/reportdesign/source/ui/inc/propbrw.hxx @@ -0,0 +1,103 @@ +/* -*- 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 . + */ + +#ifndef INCLUDED_REPORTDESIGN_SOURCE_UI_INC_PROPBRW_HXX +#define INCLUDED_REPORTDESIGN_SOURCE_UI_INC_PROPBRW_HXX + +#include <com/sun/star/frame/XFrame2.hpp> +#include <com/sun/star/inspection/XObjectInspector.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> +#include <svl/SfxBroadcaster.hxx> +#include <svl/lstner.hxx> +#include <vcl/dockwin.hxx> +#include <vcl/layout.hxx> +#include <svx/svdmark.hxx> + +namespace rptui +{ + +class OSectionView; +class ODesignView; +class OObjectBase; + +// PropBrw + + +class PropBrw final : public DockingWindow , public SfxListener, public SfxBroadcaster +{ + VclPtr<VclVBox> m_xContentArea; + + css::uno::Reference< css::uno::XComponentContext > + m_xInspectorContext; + css::uno::Reference< css::uno::XComponentContext > + m_xORB; + css::uno::Reference< css::frame::XFrame2 > + m_xMeAsFrame; + css::uno::Reference< css::inspection::XObjectInspector > + m_xBrowserController; + css::uno::Reference< css::uno::XInterface> + m_xLastSection; /// is the previously displayed section + OUString m_sLastActivePage; + VclPtr<ODesignView> m_pDesignView; + OSectionView* m_pView; + bool m_bInitialStateChange; + + PropBrw(PropBrw const &) = delete; + void operator =(PropBrw const &) = delete; + + virtual bool Close() override; + + css::uno::Sequence< css::uno::Reference< css::uno::XInterface> > + CreateCompPropSet(const SdrMarkList& rMarkList); + + void implSetNewObject( + const css::uno::Sequence< css::uno::Reference< css::uno::XInterface> >& _aObjects = css::uno::Sequence< css::uno::Reference< css::uno::XInterface> >()); + + static OUString GetHeadlineName( + const css::uno::Sequence< css::uno::Reference< css::uno::XInterface> >& _aObjects); + + void implDetachController(); + css::uno::Reference< css::uno::XInterface> CreateComponentPair(OObjectBase* _pObj); + css::uno::Reference< css::uno::XInterface> CreateComponentPair( + const css::uno::Reference< css::uno::XInterface>& _xFormComponent + ,const css::uno::Reference< css::uno::XInterface>& _xReportComponent); + DECL_LINK( OnAsyncGetFocus, void*, void ); + +public: + PropBrw(const css::uno::Reference< css::uno::XComponentContext >& _xORB + ,Window* pParent + ,ODesignView* _pDesignView); + virtual ~PropBrw() override; + virtual void dispose() override; + + virtual void LoseFocus() override; + + void Update( OSectionView* m_pView ); + void Update( const css::uno::Reference< css::uno::XInterface>& _xReportComponent); + OUString getCurrentPage() const; + void setCurrentPage(const OUString& _sLastActivePage); + + ::Size getMinimumSize() const; +}; + +} // rptui + +#endif // INCLUDED_REPORTDESIGN_SOURCE_UI_INC_PROPBRW_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/reportdesign/source/ui/inc/statusbarcontroller.hxx b/reportdesign/source/ui/inc/statusbarcontroller.hxx new file mode 100644 index 000000000..be539ec25 --- /dev/null +++ b/reportdesign/source/ui/inc/statusbarcontroller.hxx @@ -0,0 +1,84 @@ +/* -*- 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 . + */ +#ifndef INCLUDED_REPORTDESIGN_SOURCE_UI_INC_STATUSBARCONTROLLER_HXX +#define INCLUDED_REPORTDESIGN_SOURCE_UI_INC_STATUSBARCONTROLLER_HXX + +#include <svtools/statusbarcontroller.hxx> +#include <comphelper/uno3.hxx> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <cppuhelper/implbase1.hxx> + +class SfxStatusBarControl; +namespace rptui +{ + typedef ::cppu::ImplHelper1 < css::lang::XServiceInfo> OStatusbarController_BASE; + class OStatusbarController : public ::svt::StatusbarController, + public OStatusbarController_BASE + { + css::uno::Reference< css::frame::XStatusbarController > m_rController; + sal_uInt16 m_nSlotId; + sal_uInt16 m_nId; + public: + OStatusbarController(const css::uno::Reference< css::uno::XComponentContext >& _rxORB); + + /// @throws css::uno::RuntimeException + static OUString getImplementationName_Static(); + /// @throws css::uno::RuntimeException + static css::uno::Sequence< OUString > getSupportedServiceNames_Static(); + static css::uno::Reference< css::uno::XInterface > + create(css::uno::Reference< css::uno::XComponentContext > const & xContext); + + private: + void SAL_CALL dispose() override; + // XInterface + DECLARE_XINTERFACE( ) + // XServiceInfo + virtual OUString SAL_CALL getImplementationName() override; + virtual css::uno::Sequence< OUString> SAL_CALL getSupportedServiceNames() override; + // need by registration + + virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override; + + // XInitialization + virtual void SAL_CALL initialize( const css::uno::Sequence< css::uno::Any >& aArguments ) override; + + // XUpdatable + virtual void SAL_CALL update() override; + + // XStatusListener + virtual void SAL_CALL statusChanged( const css::frame::FeatureStateEvent& Event ) override; + + // XStatusbarController + virtual sal_Bool SAL_CALL mouseButtonDown( const css::awt::MouseEvent& aMouseEvent ) override; + virtual sal_Bool SAL_CALL mouseMove( const css::awt::MouseEvent& aMouseEvent ) override; + virtual sal_Bool SAL_CALL mouseButtonUp( const css::awt::MouseEvent& aMouseEvent ) override; + virtual void SAL_CALL command( const css::awt::Point& aPos, + ::sal_Int32 nCommand, + sal_Bool bMouseEvent, + const css::uno::Any& aData ) override; + virtual void SAL_CALL paint( const css::uno::Reference< css::awt::XGraphics >& xGraphics, + const css::awt::Rectangle& rOutputRectangle, + ::sal_Int32 nStyle ) override; + virtual void SAL_CALL click( const css::awt::Point& aPos ) override; + virtual void SAL_CALL doubleClick( const css::awt::Point& aPos ) override; + }; +} +#endif // DBAUI_STATUSBARCONTROLLER_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/reportdesign/source/ui/inspection/DataProviderHandler.cxx b/reportdesign/source/ui/inspection/DataProviderHandler.cxx new file mode 100644 index 000000000..a41703aaf --- /dev/null +++ b/reportdesign/source/ui/inspection/DataProviderHandler.cxx @@ -0,0 +1,516 @@ +/* -*- 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 <DataProviderHandler.hxx> +#include <comphelper/namedvaluecollection.hxx> +#include <comphelper/sequence.hxx> +#include <comphelper/types.hxx> +#include <comphelper/propertysequence.hxx> +#include <cppuhelper/supportsservice.hxx> +#include <strings.hxx> +#include <com/sun/star/form/inspection/FormComponentPropertyHandler.hpp> +#include <com/sun/star/inspection/PropertyControlType.hpp> +#include <com/sun/star/inspection/PropertyLineElement.hpp> +#include <com/sun/star/lang/NullPointerException.hpp> +#include <com/sun/star/chart/ChartDataRowSource.hpp> +#include <com/sun/star/chart2/FormattedString.hpp> +#include <com/sun/star/chart2/XTitled.hpp> +#include <com/sun/star/chart2/XTitle.hpp> +#include <com/sun/star/chart2/data/XDataReceiver.hpp> +#include <com/sun/star/ui/dialogs/XExecutableDialog.hpp> +#include <com/sun/star/report/XReportDefinition.hpp> +#include <com/sun/star/script/Converter.hpp> +#include <com/sun/star/container/XNameContainer.hpp> +#include <metadata.hxx> +#include <osl/mutex.hxx> +#include <core_resource.hxx> +#include <helpids.h> +#include <strings.hrc> +#include <PropertyForward.hxx> + +namespace rptui +{ + +using namespace ::com::sun::star; + +DataProviderHandler::DataProviderHandler(uno::Reference< uno::XComponentContext > const & context) + :DataProviderHandler_Base(m_aMutex) + ,m_xContext(context) +{ + try + { + m_xFormComponentHandler = form::inspection::FormComponentPropertyHandler::create(m_xContext); + m_xTypeConverter = script::Converter::create(m_xContext); + + }catch(const uno::Exception &) + { + } +} + +OUString SAL_CALL DataProviderHandler::getImplementationName( ) +{ + return getImplementationName_Static(); +} + +sal_Bool SAL_CALL DataProviderHandler::supportsService( const OUString& ServiceName ) +{ + return cppu::supportsService(this, ServiceName); +} + +uno::Sequence< OUString > SAL_CALL DataProviderHandler::getSupportedServiceNames( ) +{ + return getSupportedServiceNames_static(); +} + +OUString DataProviderHandler::getImplementationName_Static( ) +{ + return "com.sun.star.comp.report.DataProviderHandler"; +} + +uno::Sequence< OUString > DataProviderHandler::getSupportedServiceNames_static( ) +{ + uno::Sequence< OUString > aSupported { "com.sun.star.report.inspection.DataProviderHandler" }; + return aSupported; +} + +uno::Reference< uno::XInterface > DataProviderHandler::create( const uno::Reference< uno::XComponentContext >& _rxContext ) +{ + return *(new DataProviderHandler( _rxContext )); +} +// override WeakComponentImplHelperBase::disposing() +// This function is called upon disposing the component, +// if your component needs special work when it becomes +// disposed, do it here. +void SAL_CALL DataProviderHandler::disposing() +{ + ::comphelper::disposeComponent(m_xFormComponentHandler); + ::comphelper::disposeComponent( m_xMasterDetails ); + ::comphelper::disposeComponent(m_xTypeConverter); +} +void SAL_CALL DataProviderHandler::addEventListener(const uno::Reference< lang::XEventListener > & xListener) +{ + m_xFormComponentHandler->addEventListener(xListener); +} + +void SAL_CALL DataProviderHandler::removeEventListener(const uno::Reference< lang::XEventListener > & aListener) +{ + m_xFormComponentHandler->removeEventListener(aListener); +} + +// inspection::XPropertyHandler: + +/********************************************************************************/ +void SAL_CALL DataProviderHandler::inspect(const uno::Reference< uno::XInterface > & Component) +{ + try + { + uno::Reference< container::XNameContainer > xNameCont(Component,uno::UNO_QUERY); + const OUString sFormComponent("FormComponent"); + if ( xNameCont->hasByName(sFormComponent) ) + { + uno::Reference<beans::XPropertySet> xProp(xNameCont->getByName(sFormComponent),uno::UNO_QUERY); + const OUString sModel("Model"); + if ( xProp.is() && xProp->getPropertySetInfo()->hasPropertyByName(sModel) ) + { + m_xChartModel.set(xProp->getPropertyValue(sModel),uno::UNO_QUERY); + if ( m_xChartModel.is() ) + m_xFormComponent = m_xChartModel->getDataProvider(); + } + } + m_xDataProvider.set(m_xFormComponent,uno::UNO_QUERY); + m_xReportComponent.set( xNameCont->getByName("ReportComponent"), uno::UNO_QUERY ); + if ( m_xDataProvider.is() ) + { + auto aNoConverter = std::make_shared<AnyConverter>(); + TPropertyNamePair aPropertyMediation; + aPropertyMediation.emplace( PROPERTY_MASTERFIELDS, TPropertyConverter(PROPERTY_MASTERFIELDS,aNoConverter) ); + aPropertyMediation.emplace( PROPERTY_DETAILFIELDS, TPropertyConverter(PROPERTY_DETAILFIELDS,aNoConverter) ); + + m_xMasterDetails = new OPropertyMediator( m_xDataProvider.get(), m_xReportComponent.get(), aPropertyMediation,true ); + } + } + catch(const uno::Exception &) + { + throw lang::NullPointerException(); + } + if ( m_xFormComponent.is() ) + { + m_xFormComponentHandler->inspect(m_xFormComponent); + } +} + +uno::Any SAL_CALL DataProviderHandler::getPropertyValue(const OUString & PropertyName) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + uno::Any aPropertyValue; + const sal_Int32 nId = OPropertyInfoService::getPropertyId(PropertyName); + switch(nId) + { + case PROPERTY_ID_CHARTTYPE: + // TODO: We need a possibility to get the UI of the selected chart type + // LEM: this business of ignoring ChartType seems very fishy! + //if( m_xChartModel.is() ) + //{ + // uno::Reference< chart2::XDiagram > xDiagram( m_xChartModel->getFirstDiagram() ); + // if( xDiagram.is() ) + // { + // OUString sChartTypes; + // uno::Reference< chart2::XCoordinateSystemContainer > xCooSysCnt( xDiagram, uno::UNO_QUERY_THROW ); + // const uno::Sequence< uno::Reference< chart2::XCoordinateSystem > > aCooSysSeq( xCooSysCnt->getCoordinateSystems()); + // const uno::Reference< chart2::XCoordinateSystem >* pIter = aCooSysSeq.getConstArray(); + // const uno::Reference< chart2::XCoordinateSystem >* pEnd = pIter + aCooSysSeq.getLength(); + // for(;pIter != pEnd;++pIter) + // { + // const uno::Reference< chart2::XChartTypeContainer > xCTCnt( *pIter, uno::UNO_QUERY_THROW ); + // const uno::Sequence< uno::Reference< chart2::XChartType > > aCTSeq( xCTCnt->getChartTypes()); + // const uno::Reference< chart2::XChartType >* pChartTypeIter = aCTSeq.getConstArray(); + // const uno::Reference< chart2::XChartType >* pChartTypeEnd = pChartTypeIter + aCTSeq.getLength(); + // for(;pChartTypeIter != pChartTypeEnd;++pChartTypeIter) + // { + // sChartTypes += (*pChartTypeIter)->getChartType(); + // sChartTypes += ";"; + // } + // } + // aPropertyValue;// <<= sChartTypes; + // } + //} + break; + case PROPERTY_ID_PREVIEW_COUNT: + aPropertyValue <<= m_xDataProvider->getRowLimit(); + break; + default: + aPropertyValue = m_xFormComponentHandler->getPropertyValue( PropertyName ); + break; + } + return aPropertyValue; +} + +void SAL_CALL DataProviderHandler::setPropertyValue(const OUString & PropertyName, const uno::Any & Value) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + const sal_Int32 nId = OPropertyInfoService::getPropertyId(PropertyName); + switch(nId) + { + case PROPERTY_ID_CHARTTYPE: + break; + case PROPERTY_ID_PREVIEW_COUNT: + m_xDataProvider->setPropertyValue(PropertyName,Value); + break; + default: + m_xFormComponentHandler->setPropertyValue(PropertyName, Value); + break; + } +} + +void DataProviderHandler::impl_updateChartTitle_throw(const uno::Any& _aValue) +{ + uno::Reference<chart2::XTitled> xTitled(m_xChartModel,uno::UNO_QUERY); + if ( !xTitled.is() ) + return; + + uno::Reference<chart2::XTitle> xTitle = xTitled->getTitleObject(); + if ( !xTitle.is() ) + { + xTitle.set(m_xContext->getServiceManager()->createInstanceWithContext("com.sun.star.chart2.Title",m_xContext),uno::UNO_QUERY); + xTitled->setTitleObject(xTitle); + } + if ( xTitle.is() ) + { + uno::Reference< chart2::XFormattedString2> xFormatted = chart2::FormattedString::create(m_xContext); + OUString sStr; + _aValue >>= sStr; + xFormatted->setString(sStr); + uno::Sequence< uno::Reference< chart2::XFormattedString> > aArgs(1); + aArgs[0] = xFormatted; + xTitle->setText(aArgs); + } +} + +beans::PropertyState SAL_CALL DataProviderHandler::getPropertyState(const OUString & PropertyName) +{ + return m_xFormComponentHandler->getPropertyState(PropertyName); +} + +inspection::LineDescriptor SAL_CALL DataProviderHandler::describePropertyLine(const OUString & PropertyName, const uno::Reference< inspection::XPropertyControlFactory > & _xControlFactory) +{ + inspection::LineDescriptor aOut; + const sal_Int32 nId = OPropertyInfoService::getPropertyId(PropertyName); + switch(nId) + { + case PROPERTY_ID_CHARTTYPE: + aOut.PrimaryButtonId = UID_RPT_PROP_CHARTTYPE_DLG; + aOut.Control = _xControlFactory->createPropertyControl(inspection::PropertyControlType::TextField , true); + aOut.HasPrimaryButton = true; + break; + case PROPERTY_ID_PREVIEW_COUNT: + aOut.Control = _xControlFactory->createPropertyControl(inspection::PropertyControlType::NumericField , false); + break; + case PROPERTY_ID_MASTERFIELDS: + case PROPERTY_ID_DETAILFIELDS: + aOut.Control = _xControlFactory->createPropertyControl(inspection::PropertyControlType::StringListField , false); + aOut.PrimaryButtonId = UID_RPT_PROP_DLG_LINKFIELDS; + aOut.HasPrimaryButton = true; + break; + default: + aOut = m_xFormComponentHandler->describePropertyLine(PropertyName, _xControlFactory); + } + if ( nId != -1 ) + { + aOut.Category = (OPropertyInfoService::getPropertyUIFlags(nId ) & PropUIFlags::DataProperty) ? + OUStringLiteral("Data") + : + OUStringLiteral("General"); + aOut.HelpURL = HelpIdUrl::getHelpURL( OPropertyInfoService::getPropertyHelpId( nId ) ); + aOut.DisplayName = OPropertyInfoService::getPropertyTranslation(nId); + } + return aOut; +} + +uno::Any SAL_CALL DataProviderHandler::convertToPropertyValue(const OUString & _rPropertyValue, const uno::Any & _rControlValue) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + uno::Any aPropertyValue( _rControlValue ); + const sal_Int32 nId = OPropertyInfoService::getPropertyId(_rPropertyValue); + switch(nId) + { + case PROPERTY_ID_CHARTTYPE: + break; + case PROPERTY_ID_PREVIEW_COUNT: + try + { + aPropertyValue = m_xTypeConverter->convertTo( _rControlValue, ::cppu::UnoType<sal_Int32>::get()); + } + catch( const uno::Exception& ) + { + OSL_FAIL( "DataProviderHandler::convertToPropertyValue: caught an exception while converting via TypeConverter!" ); + } + break; + case PROPERTY_ID_MASTERFIELDS: + case PROPERTY_ID_DETAILFIELDS: + break; + default: + aPropertyValue = m_xFormComponentHandler->convertToPropertyValue(_rPropertyValue, _rControlValue); + } + return aPropertyValue; +} + +uno::Any SAL_CALL DataProviderHandler::convertToControlValue(const OUString & _rPropertyName, const uno::Any & _rPropertyValue, const uno::Type & ControlValueType) +{ + uno::Any aControlValue( _rPropertyValue ); + if ( !aControlValue.hasValue() ) + // NULL is converted to NULL + return aControlValue; + + ::osl::MutexGuard aGuard( m_aMutex ); + const sal_Int32 nId = OPropertyInfoService::getPropertyId(_rPropertyName); + switch(nId) + { + case PROPERTY_ID_CHARTTYPE: + break; + case PROPERTY_ID_MASTERFIELDS: + case PROPERTY_ID_DETAILFIELDS: + case PROPERTY_ID_PREVIEW_COUNT: + try + { + aControlValue = m_xTypeConverter->convertTo( _rPropertyValue, ControlValueType); + } + catch( const uno::Exception& ) + { + OSL_FAIL( "GeometryHandler::convertToPropertyValue: caught an exception while converting via TypeConverter!" ); + } + break; + default: + aControlValue = m_xFormComponentHandler->convertToControlValue(_rPropertyName, _rPropertyValue, ControlValueType); + } + return aControlValue; +} + +void SAL_CALL DataProviderHandler::addPropertyChangeListener(const uno::Reference< beans::XPropertyChangeListener > & Listener) +{ + m_xFormComponentHandler->addPropertyChangeListener(Listener); +} + +void SAL_CALL DataProviderHandler::removePropertyChangeListener(const uno::Reference< beans::XPropertyChangeListener > & _rxListener) +{ + m_xFormComponentHandler->removePropertyChangeListener(_rxListener); +} + +uno::Sequence< beans::Property > SAL_CALL DataProviderHandler::getSupportedProperties() +{ + ::std::vector< beans::Property > aNewProps; + if( m_xChartModel.is() ) + { + rptui::OPropertyInfoService::getExcludeProperties( aNewProps, m_xFormComponentHandler ); + beans::Property aValue; + static const OUStringLiteral s_pProperties[] = + { + PROPERTY_CHARTTYPE + ,PROPERTY_MASTERFIELDS + ,PROPERTY_DETAILFIELDS + ,PROPERTY_PREVIEW_COUNT + }; + + for (const auto & rName : s_pProperties) + { + aValue.Name = rName; + aNewProps.push_back(aValue); + } + } + return uno::Sequence< beans::Property >(aNewProps.data(), aNewProps.size()); +} + +uno::Sequence< OUString > SAL_CALL DataProviderHandler::getSupersededProperties() +{ + uno::Sequence< OUString > aRet { PROPERTY_TITLE }; // have a look at OPropertyInfoService::getExcludeProperties + return aRet; +} + +uno::Sequence< OUString > SAL_CALL DataProviderHandler::getActuatingProperties() +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + uno::Sequence< OUString > aSeq { PROPERTY_TITLE }; + return ::comphelper::concatSequences(m_xFormComponentHandler->getActuatingProperties(),aSeq); +} + +sal_Bool SAL_CALL DataProviderHandler::isComposable( const OUString& _rPropertyName ) +{ + return OPropertyInfoService::isComposable( _rPropertyName, m_xFormComponentHandler ); +} + +inspection::InteractiveSelectionResult SAL_CALL DataProviderHandler::onInteractivePropertySelection(const OUString & PropertyName, sal_Bool Primary, uno::Any & out_Data, const uno::Reference< inspection::XObjectInspectorUI > & _rxInspectorUI) +{ + if ( !_rxInspectorUI.is() ) + throw lang::NullPointerException(); + + inspection::InteractiveSelectionResult eResult = inspection::InteractiveSelectionResult_Cancelled; + ::osl::ClearableMutexGuard aGuard( m_aMutex ); + + const sal_Int32 nId = OPropertyInfoService::getPropertyId(PropertyName); + switch(nId) + { + case PROPERTY_ID_CHARTTYPE: + if ( impl_dialogChartType_nothrow(aGuard) ) + eResult = inspection::InteractiveSelectionResult_ObtainedValue; + break; + case PROPERTY_ID_MASTERFIELDS: + case PROPERTY_ID_DETAILFIELDS: + if ( impl_dialogLinkedFields_nothrow( aGuard ) ) + eResult = inspection::InteractiveSelectionResult_Success; + break; + default: + eResult = m_xFormComponentHandler->onInteractivePropertySelection(PropertyName, Primary, out_Data, _rxInspectorUI); + } + + return eResult; +} + +void SAL_CALL DataProviderHandler::actuatingPropertyChanged(const OUString & ActuatingPropertyName, const uno::Any & NewValue, const uno::Any & OldValue, const uno::Reference< inspection::XObjectInspectorUI > & InspectorUI, sal_Bool FirstTimeInit) +{ + osl::MutexGuard aGuard( m_aMutex ); + + if ( ActuatingPropertyName == PROPERTY_COMMAND ) + { + if ( NewValue != OldValue ) + { + uno::Reference< report::XReportDefinition> xReport = m_xReportComponent->getSection()->getReportDefinition(); + bool bDoEnableMasterDetailFields = xReport.is() && !xReport->getCommand().isEmpty() && !m_xDataProvider->getCommand().isEmpty(); + InspectorUI->enablePropertyUIElements( PROPERTY_DETAILFIELDS, inspection::PropertyLineElement::PrimaryButton, bDoEnableMasterDetailFields ); + InspectorUI->enablePropertyUIElements( PROPERTY_MASTERFIELDS, inspection::PropertyLineElement::PrimaryButton, bDoEnableMasterDetailFields ); + + bool bModified = xReport->isModified(); + // this fills the chart again + ::comphelper::NamedValueCollection aArgs; + aArgs.put( "CellRangeRepresentation", uno::makeAny( OUString( "all" ) ) ); + aArgs.put( "HasCategories", uno::makeAny( true ) ); + aArgs.put( "FirstCellAsLabel", uno::makeAny( true ) ); + aArgs.put( "DataRowSource", uno::makeAny( chart::ChartDataRowSource_COLUMNS ) ); + uno::Reference< chart2::data::XDataReceiver > xReceiver(m_xChartModel,uno::UNO_QUERY_THROW); + xReceiver->setArguments( aArgs.getPropertyValues() ); + if ( !bModified ) + xReport->setModified(false); + } + m_xFormComponentHandler->actuatingPropertyChanged(ActuatingPropertyName, NewValue, OldValue, InspectorUI, FirstTimeInit); + } + else if ( ActuatingPropertyName == PROPERTY_TITLE ) + { + if ( NewValue != OldValue ) + impl_updateChartTitle_throw(NewValue); + } + else + { + const sal_Int32 nId = OPropertyInfoService::getPropertyId(ActuatingPropertyName); + switch(nId) + { + + case PROPERTY_ID_MASTERFIELDS: + break; + case PROPERTY_ID_DETAILFIELDS: + break; + default: + m_xFormComponentHandler->actuatingPropertyChanged(ActuatingPropertyName, NewValue, OldValue, InspectorUI, FirstTimeInit); + } + } +} + +sal_Bool SAL_CALL DataProviderHandler::suspend(sal_Bool Suspend) +{ + return m_xFormComponentHandler->suspend(Suspend); +} +bool DataProviderHandler::impl_dialogLinkedFields_nothrow( ::osl::ClearableMutexGuard& _rClearBeforeDialog ) const +{ + uno::Sequence<uno::Any> aSeq(comphelper::InitAnyPropertySequence( + { + {"ParentWindow", m_xContext->getValueByName("DialogParentWindow")}, + {"Detail", uno::Any(m_xDataProvider)}, + {"Master", uno::Any(m_xReportComponent->getSection()->getReportDefinition())}, + {"Explanation", uno::Any(RptResId(RID_STR_EXPLANATION))}, + {"DetailLabel", uno::Any(RptResId(RID_STR_DETAILLABEL))}, + {"MasterLabel", uno::Any(RptResId(RID_STR_MASTERLABEL))}, + })); + + uno::Reference< ui::dialogs::XExecutableDialog > xDialog( + m_xContext->getServiceManager()->createInstanceWithArgumentsAndContext( + "org.openoffice.comp.form.ui.MasterDetailLinkDialog", aSeq, m_xContext), + uno::UNO_QUERY); + + _rClearBeforeDialog.clear(); + return ( xDialog->execute() != 0 ); +} + +bool DataProviderHandler::impl_dialogChartType_nothrow( ::osl::ClearableMutexGuard& _rClearBeforeDialog ) const +{ + uno::Sequence<uno::Any> aSeq(comphelper::InitAnyPropertySequence( + { + {"ParentWindow", m_xContext->getValueByName("DialogParentWindow")}, + {"ChartModel", uno::Any(m_xChartModel)} + })); + + uno::Reference< ui::dialogs::XExecutableDialog > xDialog( + m_xContext->getServiceManager()->createInstanceWithArgumentsAndContext( + "com.sun.star.comp.chart2.ChartTypeDialog", aSeq, m_xContext), + uno::UNO_QUERY); + + _rClearBeforeDialog.clear(); + return ( xDialog->execute() != 0 ); +} + +} // namespace rptui + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/reportdesign/source/ui/inspection/DefaultInspection.cxx b/reportdesign/source/ui/inspection/DefaultInspection.cxx new file mode 100644 index 000000000..e7346e4c3 --- /dev/null +++ b/reportdesign/source/ui/inspection/DefaultInspection.cxx @@ -0,0 +1,225 @@ +/* -*- 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 <DefaultInspection.hxx> +#include <com/sun/star/ucb/AlreadyInitializedException.hpp> +#include <com/sun/star/lang/IllegalArgumentException.hpp> +#include <strings.hrc> +#include <core_resource.hxx> +#include <helpids.h> +#include <cppuhelper/supportsservice.hxx> +#include <tools/debug.hxx> +#include <metadata.hxx> +#include <tools/urlobj.hxx> + + +namespace rptui +{ + OUString HelpIdUrl::getHelpURL( const OString& sHelpId ) + { + OUString aTmp( OStringToOUString(sHelpId, RTL_TEXTENCODING_UTF8) ); + DBG_ASSERT( INetURLObject( aTmp ).GetProtocol() == INetProtocol::NotValid, "Wrong HelpId!" ); + return INET_HID_SCHEME + aTmp; + } + + using namespace com::sun::star::uno; + using namespace com::sun::star; + using com::sun::star::inspection::PropertyCategoryDescriptor; + + + //= DefaultComponentInspectorModel + + + DefaultComponentInspectorModel::DefaultComponentInspectorModel( const Reference< XComponentContext >& _rxContext) + :m_xContext( _rxContext ) + ,m_bConstructed( false ) + ,m_bHasHelpSection( false ) + ,m_bIsReadOnly(false) + ,m_nMinHelpTextLines( 3 ) + ,m_nMaxHelpTextLines( 8 ) + { + } + + DefaultComponentInspectorModel::~DefaultComponentInspectorModel() + { + } + + OUString SAL_CALL DefaultComponentInspectorModel::getImplementationName( ) + { + return getImplementationName_Static(); + } + + sal_Bool SAL_CALL DefaultComponentInspectorModel::supportsService( const OUString& ServiceName ) + { + return cppu::supportsService(this, ServiceName); + } + + Sequence< OUString > SAL_CALL DefaultComponentInspectorModel::getSupportedServiceNames( ) + { + return getSupportedServiceNames_static(); + } + + OUString DefaultComponentInspectorModel::getImplementationName_Static( ) + { + return "com.sun.star.comp.report.DefaultComponentInspectorModel"; + } + + Sequence< OUString > DefaultComponentInspectorModel::getSupportedServiceNames_static( ) + { + Sequence< OUString > aSupported { "com.sun.star.report.inspection.DefaultComponentInspectorModel" }; + return aSupported; + } + + Reference< XInterface > DefaultComponentInspectorModel::create( const Reference< XComponentContext >& _rxContext ) + { + return *(new DefaultComponentInspectorModel( _rxContext )); + } + + + Sequence< Any > SAL_CALL DefaultComponentInspectorModel::getHandlerFactories() + { + // service names for all our handlers + return Sequence<Any> { + Any(OUString( "com.sun.star.report.inspection.ReportComponentHandler")), + Any(OUString( "com.sun.star.form.inspection.EditPropertyHandler")), + Any(OUString( "com.sun.star.report.inspection.DataProviderHandler")), + Any(OUString( "com.sun.star.report.inspection.GeometryHandler")) + }; + } + + sal_Bool SAL_CALL DefaultComponentInspectorModel::getHasHelpSection() + { + ::osl::MutexGuard aGuard(m_aMutex); + return m_bHasHelpSection; + } + + + ::sal_Int32 SAL_CALL DefaultComponentInspectorModel::getMinHelpTextLines() + { + ::osl::MutexGuard aGuard(m_aMutex); + return m_nMinHelpTextLines; + } + + sal_Bool SAL_CALL DefaultComponentInspectorModel::getIsReadOnly() + { + ::osl::MutexGuard aGuard(m_aMutex); + return m_bIsReadOnly; + } + + void SAL_CALL DefaultComponentInspectorModel::setIsReadOnly( sal_Bool _isreadonly ) + { + ::osl::MutexGuard aGuard(m_aMutex); + m_bIsReadOnly = _isreadonly; + } + + + ::sal_Int32 SAL_CALL DefaultComponentInspectorModel::getMaxHelpTextLines() + { + ::osl::MutexGuard aGuard(m_aMutex); + return m_nMaxHelpTextLines; + } + + void SAL_CALL DefaultComponentInspectorModel::initialize( const Sequence< Any >& _arguments ) + { + ::osl::MutexGuard aGuard(m_aMutex); + if ( m_bConstructed ) + throw ucb::AlreadyInitializedException(); + + if ( !_arguments.hasElements() ) + { // constructor: "createDefault()" + m_bConstructed = true; + return; + } + + sal_Int32 nMinHelpTextLines( 0 ), nMaxHelpTextLines( 0 ); + if ( _arguments.getLength() == 2 ) + { // constructor: "createWithHelpSection( long, long )" + if ( !( _arguments[0] >>= nMinHelpTextLines ) || !( _arguments[1] >>= nMaxHelpTextLines ) ) + throw lang::IllegalArgumentException( OUString(), *this, 0 ); + createWithHelpSection( nMinHelpTextLines, nMaxHelpTextLines ); + return; + } + + throw lang::IllegalArgumentException( OUString(), *this, 0 ); + } + + + void DefaultComponentInspectorModel::createWithHelpSection( sal_Int32 _nMinHelpTextLines, sal_Int32 _nMaxHelpTextLines ) + { + if ( ( _nMinHelpTextLines <= 0 ) || ( _nMaxHelpTextLines <= 0 ) || ( _nMinHelpTextLines > _nMaxHelpTextLines ) ) + throw lang::IllegalArgumentException( OUString(), *this, 0 ); + + m_bHasHelpSection = true; + m_nMinHelpTextLines = _nMinHelpTextLines; + m_nMaxHelpTextLines = _nMaxHelpTextLines; + m_bConstructed = true; + } + + Sequence< PropertyCategoryDescriptor > SAL_CALL DefaultComponentInspectorModel::describeCategories( ) + { + ::osl::MutexGuard aGuard( m_aMutex ); + + const struct + { + const char* programmaticName; + const char* uiNameResId; + OString helpId; + } aCategories[] = { + { "General", RID_STR_PROPPAGE_DEFAULT, HID_RPT_PROPDLG_TAB_GENERAL }, + { "Data", RID_STR_PROPPAGE_DATA, HID_RPT_PROPDLG_TAB_DATA }, + }; + + const size_t nCategories = SAL_N_ELEMENTS( aCategories ); + Sequence< PropertyCategoryDescriptor > aReturn( nCategories ); + PropertyCategoryDescriptor* pReturn = aReturn.getArray(); + for ( size_t i=0; i<nCategories; ++i, ++pReturn ) + { + pReturn->ProgrammaticName = OUString::createFromAscii( aCategories[i].programmaticName ); + pReturn->UIName = RptResId( aCategories[i].uiNameResId ); + pReturn->HelpURL = HelpIdUrl::getHelpURL( aCategories[i].helpId ); + } + + return aReturn; + } + + + ::sal_Int32 SAL_CALL DefaultComponentInspectorModel::getPropertyOrderIndex( const OUString& _rPropertyName ) + { + ::osl::MutexGuard aGuard(m_aMutex); + const sal_Int32 nPropertyId( OPropertyInfoService::getPropertyId( _rPropertyName ) ); + if ( nPropertyId != -1 ) + return nPropertyId; + + if ( !m_xComponent.is() ) + try + { + m_xComponent.set(m_xContext->getServiceManager()->createInstanceWithContext("com.sun.star.form.inspection.DefaultFormComponentInspectorModel",m_xContext),UNO_QUERY_THROW); + } + catch(const Exception &) + { + return 0; + } + + return m_xComponent->getPropertyOrderIndex(_rPropertyName); + } + + +} // namespace rptui + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/reportdesign/source/ui/inspection/GeometryHandler.cxx b/reportdesign/source/ui/inspection/GeometryHandler.cxx new file mode 100644 index 000000000..d5b9748e2 --- /dev/null +++ b/reportdesign/source/ui/inspection/GeometryHandler.cxx @@ -0,0 +1,2220 @@ +/* -*- 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 <iterator> +#include <map> + +#include <GeometryHandler.hxx> + +#include <comphelper/sequence.hxx> +#include <comphelper/types.hxx> +#include <comphelper/property.hxx> +#include <comphelper/mimeconfighelper.hxx> +#include <cppuhelper/supportsservice.hxx> + +#include <strings.hxx> +#include <reportformula.hxx> + +#include <i18nutil/searchopt.hxx> +#include <unotools/textsearch.hxx> +#include <unotools/localedatawrapper.hxx> + +#include <toolkit/helper/vclunohelper.hxx> +#include <unotools/syslocale.hxx> +#include <tools/diagnose_ex.h> +#include <tools/resary.hxx> +#include <com/sun/star/lang/NullPointerException.hpp> +#include <com/sun/star/form/inspection/FormComponentPropertyHandler.hpp> +#include <com/sun/star/inspection/StringRepresentation.hpp> +#include <com/sun/star/inspection/PropertyControlType.hpp> +#include <com/sun/star/inspection/XStringListControl.hpp> +#include <com/sun/star/report/Function.hpp> +#include <com/sun/star/report/XReportDefinition.hpp> +#include <com/sun/star/report/XShape.hpp> +#include <com/sun/star/report/XSection.hpp> +#include <com/sun/star/report/XFixedLine.hpp> +#include <com/sun/star/script/Converter.hpp> +#include <com/sun/star/sdb/XSingleSelectQueryComposer.hpp> +#include <com/sun/star/sdb/CommandType.hpp> +#include <com/sun/star/sdb/FilterDialog.hpp> +#include <com/sun/star/sdb/SQLContext.hpp> +#include <com/sun/star/sdbc/XConnection.hpp> +#include <com/sun/star/util/SearchAlgorithms2.hpp> +#include <com/sun/star/util/MeasureUnit.hpp> +#include <com/sun/star/ui/dialogs/XExecutableDialog.hpp> +#include <com/sun/star/container/XNameContainer.hpp> +#include <com/sun/star/inspection/XNumericControl.hpp> +#include <com/sun/star/style/ParagraphAdjust.hpp> + +#include <tools/fldunit.hxx> +#include <vcl/svapp.hxx> +#include <vcl/weld.hxx> + +#include <core_resource.hxx> +#include <stringarray.hrc> +#include <strings.hrc> +#include <RptDef.hxx> +#include <UITools.hxx> + +#include <connectivity/dbexception.hxx> +#include <connectivity/dbtools.hxx> + +#include <metadata.hxx> +#include <sfx2/docfilt.hxx> + +#include <helpids.h> +#include <toolkit/helper/convert.hxx> +#include <o3tl/functional.hxx> +#include <o3tl/safeint.hxx> + +#define DATA_OR_FORMULA 0 +#define FUNCTION 1 +#define COUNTER 2 +#define USER_DEF_FUNCTION 3 +#define UNDEF_DATA 4 + + +namespace rptui +{ + +using namespace ::com::sun::star; + +namespace{ + +OUString lcl_getQuotedFunctionName(const OUString& _sFunction) +{ + return "[" + _sFunction + "]"; +} + +OUString lcl_getQuotedFunctionName(const uno::Reference< report::XFunction>& _xFunction) +{ + return lcl_getQuotedFunctionName(_xFunction->getName()); +} + +void lcl_collectFunctionNames(const uno::Reference< report::XFunctions>& _xFunctions,TFunctions& _rFunctionNames) +{ + uno::Reference< report::XFunctionsSupplier> xParent(_xFunctions->getParent(),uno::UNO_QUERY_THROW); + const sal_Int32 nCount = _xFunctions->getCount(); + for (sal_Int32 i = 0; i < nCount ; ++i) + { + uno::Reference< report::XFunction > xFunction(_xFunctions->getByIndex(i),uno::UNO_QUERY_THROW); + _rFunctionNames.emplace( lcl_getQuotedFunctionName(xFunction),TFunctionPair(xFunction,xParent) ); + } +} + +void lcl_collectFunctionNames(const uno::Reference< report::XSection>& _xSection,TFunctions& _rFunctionNames) +{ + const uno::Reference< report::XReportDefinition> xReportDefinition = _xSection->getReportDefinition(); + const uno::Reference< report::XGroups> xGroups = xReportDefinition->getGroups(); + sal_Int32 nPos = -1; + uno::Reference< report::XGroup> xGroup = _xSection->getGroup(); + if ( xGroup.is() ) + nPos = getPositionInIndexAccess(xGroups.get(),xGroup); + else if ( _xSection == xReportDefinition->getDetail() ) + nPos = xGroups->getCount()-1; + + for (sal_Int32 i = 0 ; i <= nPos ; ++i) + { + xGroup.set(xGroups->getByIndex(i),uno::UNO_QUERY_THROW); + lcl_collectFunctionNames(xGroup->getFunctions(),_rFunctionNames); + } + lcl_collectFunctionNames(xReportDefinition->getFunctions(),_rFunctionNames); +} + +void lcl_convertFormulaTo(const uno::Any& _aPropertyValue,uno::Any& _rControlValue) +{ + OUString sName; + _aPropertyValue >>= sName; + const sal_Int32 nLen = sName.getLength(); + if ( nLen ) + { + ReportFormula aFormula( sName ); + _rControlValue <<= aFormula.getUndecoratedContent(); + } +} + +// return value rounded to the nearest multiple of base +// if equidistant of two multiples, round up (for positive numbers) +// T is assumed to be an integer type +template <typename T, T base> T lcl_round(T value) +{ + OSL_ENSURE(value >= 0, "lcl_round: positive numbers only please"); + const T threshold = (base % 2 == 0) ? (base/2) : (base/2 + 1); + const T rest = value % base; + if ( rest >= threshold ) + return value + (base - rest); + else + return value - rest; +} + +} // anonymous namespace + +bool GeometryHandler::impl_isDataField(const OUString& _sName) const +{ + bool bIsField = ( ::std::find( m_aFieldNames.begin(), m_aFieldNames.end(), _sName ) != m_aFieldNames.end() ); + + if ( !bIsField ) + { + bIsField = ( ::std::find( m_aParamNames.begin(), m_aParamNames.end(), _sName ) != m_aParamNames.end() ); + } + return bIsField; +} + +OUString GeometryHandler::impl_convertToFormula( const uno::Any& _rControlValue ) +{ + OUString sName; + _rControlValue >>= sName; + + if ( sName.isEmpty() ) + return sName; + + ReportFormula aParser( sName ); + if ( aParser.isValid() ) + return sName; + + return ReportFormula(impl_isDataField(sName) ? ReportFormula::Field : ReportFormula::Expression, sName).getCompleteFormula(); +} + +GeometryHandler::GeometryHandler(uno::Reference< uno::XComponentContext > const & context) + : GeometryHandler_Base(m_aMutex) + , m_aPropertyListeners(m_aMutex) + , m_xContext(context) + , m_nDataFieldType(0) + , m_bNewFunction(false) + , m_bIn(false) +{ + try + { + m_xFormComponentHandler = form::inspection::FormComponentPropertyHandler::create(m_xContext); + m_xTypeConverter = script::Converter::create(context); + loadDefaultFunctions(); + } + catch(const uno::Exception&) + { + } +} + +GeometryHandler::~GeometryHandler() +{ +} + +OUString SAL_CALL GeometryHandler::getImplementationName( ) +{ + return getImplementationName_Static(); +} + +sal_Bool SAL_CALL GeometryHandler::supportsService( const OUString& ServiceName ) +{ + return cppu::supportsService(this, ServiceName); +} + +uno::Sequence< OUString > SAL_CALL GeometryHandler::getSupportedServiceNames( ) +{ + return getSupportedServiceNames_static(); +} + +OUString GeometryHandler::getImplementationName_Static( ) +{ + return "com.sun.star.comp.report.GeometryHandler"; +} + +uno::Sequence< OUString > GeometryHandler::getSupportedServiceNames_static( ) +{ + uno::Sequence< OUString > aSupported { "com.sun.star.report.inspection.GeometryHandler" }; + return aSupported; +} + +uno::Reference< uno::XInterface > GeometryHandler::create( const uno::Reference< uno::XComponentContext >& _rxContext ) +{ + return *(new GeometryHandler( _rxContext )); +} +// override WeakComponentImplHelperBase::disposing() +// This function is called upon disposing the component, +// if your component needs special work when it becomes +// disposed, do it here. +void SAL_CALL GeometryHandler::disposing() +{ + try + { + ::comphelper::disposeComponent(m_xFormComponentHandler); + ::comphelper::disposeComponent(m_xTypeConverter); + if ( m_xReportComponent.is() && m_xReportComponent->getPropertySetInfo()->hasPropertyByName(PROPERTY_DATAFIELD) ) + m_xReportComponent->removePropertyChangeListener(PROPERTY_DATAFIELD,static_cast< beans::XPropertyChangeListener* >( this )); + + m_xReportComponent.clear(); + m_xRowSet.clear(); + m_aPropertyListeners.clear(); + } + catch(uno::Exception&) + {} +} +void SAL_CALL GeometryHandler::addEventListener(const uno::Reference< lang::XEventListener > & xListener) +{ + m_xFormComponentHandler->addEventListener(xListener); +} + +void SAL_CALL GeometryHandler::removeEventListener(const uno::Reference< lang::XEventListener > & aListener) +{ + m_xFormComponentHandler->removeEventListener(aListener); +} + +// inspection::XPropertyHandler: + +/********************************************************************************/ +void SAL_CALL GeometryHandler::inspect( const uno::Reference< uno::XInterface > & _rxInspectee ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + m_sScope.clear(); + m_sDefaultFunction.clear(); + m_bNewFunction = false; + m_nDataFieldType = 0; + m_xFunction.clear(); + m_aFunctionNames.clear(); + try + { + if ( m_xReportComponent.is() && m_xReportComponent->getPropertySetInfo()->hasPropertyByName(PROPERTY_DATAFIELD) ) + m_xReportComponent->removePropertyChangeListener(PROPERTY_DATAFIELD,static_cast< beans::XPropertyChangeListener* >( this )); + + const uno::Reference< container::XNameContainer > xObjectAsContainer( _rxInspectee, uno::UNO_QUERY ); + m_xReportComponent.set( xObjectAsContainer->getByName("ReportComponent"), uno::UNO_QUERY ); + + const OUString sRowSet("RowSet"); + if ( xObjectAsContainer->hasByName( sRowSet ) ) + { + const uno::Any aRowSet( xObjectAsContainer->getByName(sRowSet) ); + aRowSet >>= m_xRowSet; + // forward the rowset to our delegator handler + uno::Reference< beans::XPropertySet > xProp( m_xFormComponentHandler,uno::UNO_QUERY ); + xProp->setPropertyValue( sRowSet, aRowSet ); + + m_aParamNames = getParameterNames( m_xRowSet ); + impl_initFieldList_nothrow(m_aFieldNames); + if ( m_xReportComponent->getPropertySetInfo()->hasPropertyByName(PROPERTY_DATAFIELD) ) + m_xReportComponent->addPropertyChangeListener(PROPERTY_DATAFIELD,static_cast< beans::XPropertyChangeListener* >( this )); + } + + const uno::Reference< report::XReportComponent> xReportComponent( m_xReportComponent, uno::UNO_QUERY); + uno::Reference< report::XSection> xSection( m_xReportComponent, uno::UNO_QUERY ); + if ( !xSection.is() && xReportComponent.is() ) + xSection = xReportComponent->getSection(); + if ( xSection.is() ) + lcl_collectFunctionNames( xSection, m_aFunctionNames ); + } + catch(const uno::Exception &) + { + throw lang::NullPointerException(); + } + m_xFormComponentHandler->inspect(m_xReportComponent); +} + +uno::Any SAL_CALL GeometryHandler::getPropertyValue(const OUString & PropertyName) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + uno::Any aPropertyValue; + const sal_Int32 nId = OPropertyInfoService::getPropertyId(PropertyName); + switch(nId) + { + case PROPERTY_ID_CONDITIONALPRINTEXPRESSION: + case PROPERTY_ID_INITIALFORMULA: + case PROPERTY_ID_FORMULA: + case PROPERTY_ID_DATAFIELD: + aPropertyValue = m_xReportComponent->getPropertyValue( PropertyName ); + lcl_convertFormulaTo(aPropertyValue,aPropertyValue); + if ( PROPERTY_ID_DATAFIELD == nId ) + { + OUString sDataField; + aPropertyValue >>= sDataField; + switch(m_nDataFieldType) + { + case DATA_OR_FORMULA: + break; + case FUNCTION: + if ( isDefaultFunction(sDataField,sDataField) ) + aPropertyValue <<= sDataField; + else if ( sDataField.isEmpty() ) + aPropertyValue = uno::Any(); + break; + case COUNTER: + case USER_DEF_FUNCTION: + aPropertyValue = uno::Any(); + break; + } + + } + break; + case PROPERTY_ID_TYPE: + { + const sal_uInt32 nOldDataFieldType = m_nDataFieldType; + m_nDataFieldType = impl_getDataFieldType_throw(); + if ( UNDEF_DATA == m_nDataFieldType ) + m_nDataFieldType = nOldDataFieldType; + aPropertyValue <<= m_nDataFieldType; + } + break; + case PROPERTY_ID_FORMULALIST: + case PROPERTY_ID_SCOPE: + { + uno::Any aDataField = m_xReportComponent->getPropertyValue( PROPERTY_DATAFIELD ); + lcl_convertFormulaTo(aDataField,aDataField); + OUString sDataField; + aDataField >>= sDataField; + switch(m_nDataFieldType) + { + case DATA_OR_FORMULA: + break; + case FUNCTION: + if ( isDefaultFunction(sDataField,sDataField,uno::Reference< report::XFunctionsSupplier>(),true) ) + aPropertyValue <<= (PROPERTY_ID_FORMULALIST == nId ? m_sDefaultFunction : m_sScope); + break; + case USER_DEF_FUNCTION: + if ( !sDataField.isEmpty() && PROPERTY_ID_FORMULALIST == nId ) + aPropertyValue = aDataField; + break; + case COUNTER: + if ( PROPERTY_ID_SCOPE == nId && impl_isCounterFunction_throw(sDataField,m_sScope) ) + aPropertyValue <<= m_sScope; + break; + } + + } + break; + case PROPERTY_ID_BACKCOLOR: + case PROPERTY_ID_CONTROLBACKGROUND: + { + aPropertyValue = m_xReportComponent->getPropertyValue( PropertyName ); + Color nColor = COL_TRANSPARENT; + if ( (aPropertyValue >>= nColor) && COL_TRANSPARENT == nColor ) + aPropertyValue.clear(); + } + break; + case PROPERTY_ID_MIMETYPE: + { + OUString sValue; + m_xReportComponent->getPropertyValue( PropertyName ) >>= sValue; + aPropertyValue <<= impl_ConvertMimeTypeToUI_nothrow(sValue); + } + break; + default: + aPropertyValue = m_xReportComponent->getPropertyValue( PropertyName ); + break; + } + return aPropertyValue; +} + +void SAL_CALL GeometryHandler::setPropertyValue(const OUString & PropertyName, const uno::Any & Value) +{ + ::osl::ResettableMutexGuard aGuard( m_aMutex ); + uno::Any aNewValue = Value; + const sal_Int32 nId = OPropertyInfoService::getPropertyId(PropertyName); + bool bHandled = false; + switch(nId) + { + case PROPERTY_ID_INITIALFORMULA: + case PROPERTY_ID_FORMULA: + break; + case PROPERTY_ID_DATAFIELD: + { + OBlocker aBlocker(m_bIn); + m_xReportComponent->setPropertyValue(PropertyName, aNewValue); + bHandled = true; + const OUString sOldFunctionName = m_sDefaultFunction; + const OUString sOldScope = m_sScope; + + uno::Any aPropertyValue; + lcl_convertFormulaTo(Value,aPropertyValue); + OUString sDataField; + aPropertyValue >>= sDataField; + + m_sScope.clear(); + m_sDefaultFunction.clear(); + m_xFunction.clear(); + const sal_uInt32 nOldDataFieldType = m_nDataFieldType; + if ( !sDataField.isEmpty() ) + { + if ( isDefaultFunction(sDataField,sDataField,uno::Reference< report::XFunctionsSupplier>(),true) ) + m_nDataFieldType = FUNCTION; + else if ( m_aFunctionNames.find(sDataField) != m_aFunctionNames.end() ) + m_nDataFieldType = USER_DEF_FUNCTION; + } + + resetOwnProperties(aGuard,sOldFunctionName,sOldScope,nOldDataFieldType); + } + break; + case PROPERTY_ID_TYPE: + { + bHandled = true; + Value >>= m_nDataFieldType; + + const OUString sOldFunctionName = m_sDefaultFunction; + const OUString sOldScope = m_sScope; + m_sDefaultFunction.clear(); + m_sScope.clear(); + + if ( m_nDataFieldType == COUNTER ) + { + impl_setCounterFunction_throw(); + } + else + { + if ( m_bNewFunction ) + removeFunction(); + m_xFunction.clear(); + OBlocker aBlocker(m_bIn); + m_xReportComponent->setPropertyValue(PROPERTY_DATAFIELD,uno::makeAny(OUString())); + } + resetOwnProperties(aGuard,sOldFunctionName,sOldScope,m_nDataFieldType); + } + break; + case PROPERTY_ID_FORMULALIST: + { + bHandled = true; + OUString sFunction; + if ( !(Value >>= sFunction) || sFunction.isEmpty() ) + { + if ( m_nDataFieldType == FUNCTION ) + { + m_sDefaultFunction.clear(); + if ( m_bNewFunction ) + removeFunction(); + m_xFunction.clear(); + + beans::PropertyChangeEvent aEvent; + aEvent.PropertyName = PROPERTY_SCOPE; + aEvent.OldValue <<= m_sScope; + m_sScope.clear(); + aEvent.NewValue <<= m_sScope; + aGuard.clear(); + m_aPropertyListeners.notify( aEvent, &beans::XPropertyChangeListener::propertyChange ); + } + else if ( m_nDataFieldType == USER_DEF_FUNCTION ) + { + OBlocker aBlocker(m_bIn); + m_xReportComponent->setPropertyValue(PROPERTY_DATAFIELD,uno::makeAny(OUString())); + } + } + else if ( m_nDataFieldType == USER_DEF_FUNCTION ) + { + OUString sDataField; + OBlocker aBlocker(m_bIn); + const sal_uInt32 nNewDataType = impl_getDataFieldType_throw(sFunction); + if ( nNewDataType != UNDEF_DATA && nNewDataType != m_nDataFieldType ) + { + const OUString sOldFunctionName = m_sDefaultFunction; + const OUString sOldScope = m_sScope; + m_sScope.clear(); + m_sDefaultFunction.clear(); + m_xFunction.clear(); + if ( nNewDataType == COUNTER ) + impl_isCounterFunction_throw(sFunction,m_sScope); + else + { + OUString sNamePostfix; + const uno::Reference< report::XFunctionsSupplier> xFunctionsSupplier = fillScope_throw(sNamePostfix); + isDefaultFunction(sFunction,sDataField,xFunctionsSupplier,true); + } + const sal_uInt32 nOldDataFieldType = m_nDataFieldType; + m_nDataFieldType = nNewDataType; + m_xReportComponent->setPropertyValue(PROPERTY_DATAFIELD,uno::makeAny(impl_convertToFormula( uno::makeAny(sFunction)))); + resetOwnProperties(aGuard,sOldFunctionName,sOldScope,nOldDataFieldType); + } + else + m_xReportComponent->setPropertyValue(PROPERTY_DATAFIELD,uno::makeAny(impl_convertToFormula( uno::makeAny(sFunction)))); + } + else if ( m_nDataFieldType == FUNCTION ) + { + uno::Any aPropertyValue = m_xReportComponent->getPropertyValue(PROPERTY_DATAFIELD); + lcl_convertFormulaTo(aPropertyValue,aPropertyValue); + OUString sDataField; + aPropertyValue >>= sDataField; + if ( m_nDataFieldType == FUNCTION && (!isDefaultFunction(sDataField,sDataField) || m_sDefaultFunction != sFunction) ) + { + if ( m_bNewFunction ) + removeFunction(); + // function currently does not exist + createDefaultFunction(aGuard,sFunction,sDataField); + m_sDefaultFunction = sFunction; + } + } + } + + break; + case PROPERTY_ID_SCOPE: + if ( !(Value >>= m_sScope) ) + m_sScope.clear(); + else + { + if ( m_bNewFunction ) + removeFunction(); + if ( m_nDataFieldType == COUNTER ) + impl_setCounterFunction_throw(); + else + { + OSL_ENSURE(m_xFunction.is(),"Where is my function gone!"); + + OUString sNamePostfix; + const uno::Reference< report::XFunctionsSupplier> xFunctionsSupplier = fillScope_throw(sNamePostfix); + + OUString sQuotedFunctionName(lcl_getQuotedFunctionName(m_xFunction)); + if ( isDefaultFunction(sQuotedFunctionName,sQuotedFunctionName,xFunctionsSupplier,true) ) + m_bNewFunction = false; + else + { + OUString sDefaultFunctionName; + OUString sDataField; + OSL_VERIFY( impl_isDefaultFunction_nothrow(m_xFunction,sDataField,sDefaultFunctionName) ); + m_sDefaultFunction = sDefaultFunctionName; + createDefaultFunction(aGuard,m_sDefaultFunction,sDataField); + } + } + } + bHandled = true; + break; + case PROPERTY_ID_POSITIONX: + case PROPERTY_ID_POSITIONY: + case PROPERTY_ID_HEIGHT: + case PROPERTY_ID_WIDTH: + { + const uno::Reference< report::XReportComponent> xSourceReportComponent(m_xReportComponent,uno::UNO_QUERY); + if ( xSourceReportComponent.is() ) // check only report components + { + sal_Int32 nNewValue = 0; + Value >>= nNewValue; + OSL_ENSURE(nNewValue >= 0, "A position/dimension should not be negative!"); + nNewValue = lcl_round<sal_Int32, 10>(nNewValue); + awt::Point aAwtPoint = xSourceReportComponent->getPosition(); + awt::Size aAwtSize = xSourceReportComponent->getSize(); + if ( nId == PROPERTY_ID_POSITIONX ) + aAwtPoint.X = nNewValue; + else if ( nId == PROPERTY_ID_POSITIONY ) + aAwtPoint.Y = nNewValue; + else if ( nId == PROPERTY_ID_HEIGHT ) + aAwtSize.Height = nNewValue; + else if ( nId == PROPERTY_ID_WIDTH ) + aAwtSize.Width = nNewValue; + + checkPosAndSize(aAwtPoint,aAwtSize); + } + } + break; + case PROPERTY_ID_FONT: + { + const uno::Reference< report::XReportControlFormat > xReportControlFormat( m_xReportComponent,uno::UNO_QUERY_THROW ); + uno::Sequence< beans::NamedValue > aFontSettings; + OSL_VERIFY( Value >>= aFontSettings ); + applyCharacterSettings( xReportControlFormat, aFontSettings ); + bHandled = true; + } + break; + case PROPERTY_ID_MIMETYPE: + { + OUString sValue; + Value >>= sValue; + aNewValue <<= impl_ConvertUIToMimeType_nothrow(sValue); + } + break; + default: + break; + } + + if ( !bHandled ) + m_xReportComponent->setPropertyValue(PropertyName, aNewValue); +} + + +beans::PropertyState SAL_CALL GeometryHandler::getPropertyState(const OUString & PropertyName) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + return m_xFormComponentHandler->getPropertyState(PropertyName); +} + +void GeometryHandler::implCreateListLikeControl( + const uno::Reference< inspection::XPropertyControlFactory >& _rxControlFactory + ,inspection::LineDescriptor & out_Descriptor + ,const char** pResId + ,bool _bReadOnlyControl + ,bool _bTrueIfListBoxFalseIfComboBox + ) +{ + std::vector<OUString> aList; + for (const char** pItem = pResId; *pItem; ++pItem) + aList.push_back(RptResId(*pItem)); + implCreateListLikeControl(_rxControlFactory, out_Descriptor, aList, _bReadOnlyControl, _bTrueIfListBoxFalseIfComboBox); +} + +void GeometryHandler::implCreateListLikeControl( + const uno::Reference< inspection::XPropertyControlFactory >& _rxControlFactory + ,inspection::LineDescriptor & out_Descriptor + ,const ::std::vector< OUString>& _aEntries + ,bool _bReadOnlyControl + ,bool _bTrueIfListBoxFalseIfComboBox + ) +{ + const uno::Reference< inspection::XStringListControl > xListControl( + _rxControlFactory->createPropertyControl( + _bTrueIfListBoxFalseIfComboBox ? inspection::PropertyControlType::ListBox : inspection::PropertyControlType::ComboBox, _bReadOnlyControl + ), + uno::UNO_QUERY_THROW + ); + + out_Descriptor.Control = xListControl.get(); + for (auto const& it : _aEntries) + { + xListControl->appendListEntry(it); + } +} + + +inspection::LineDescriptor SAL_CALL GeometryHandler::describePropertyLine(const OUString & PropertyName, const uno::Reference< inspection::XPropertyControlFactory > & _xControlFactory) +{ + inspection::LineDescriptor aOut; + const sal_Int32 nId = OPropertyInfoService::getPropertyId(PropertyName); + switch(nId) + { + case PROPERTY_ID_FORCENEWPAGE: + case PROPERTY_ID_NEWROWORCOL: + implCreateListLikeControl(_xControlFactory,aOut,RID_STR_FORCENEWPAGE_CONST,false,true); + break; + case PROPERTY_ID_GROUPKEEPTOGETHER: + implCreateListLikeControl(_xControlFactory,aOut,RID_STR_GROUPKEEPTOGETHER_CONST,false,true); + break; + case PROPERTY_ID_PAGEHEADEROPTION: + case PROPERTY_ID_PAGEFOOTEROPTION: + implCreateListLikeControl(_xControlFactory,aOut,RID_STR_REPORTPRINTOPTION_CONST,false,true); + break; + case PROPERTY_ID_FORMULALIST: + { + ::std::vector< OUString > aList; + impl_fillFormulaList_nothrow(aList); + implCreateListLikeControl(_xControlFactory,aOut,aList,false,true); + } + break; + case PROPERTY_ID_SCOPE: + { + ::std::vector< OUString > aList; + impl_fillScopeList_nothrow(aList); + implCreateListLikeControl(_xControlFactory,aOut,aList,false,true); + } + break; + case PROPERTY_ID_MIMETYPE: + { + ::std::vector< OUString > aList; + impl_fillMimeTypes_nothrow(aList); + implCreateListLikeControl(_xControlFactory,aOut,aList,false,true); + } + break; + case PROPERTY_ID_TYPE: + implCreateListLikeControl(_xControlFactory,aOut,RID_STR_TYPE_CONST,false,true); + break; + case PROPERTY_ID_VISIBLE: + case PROPERTY_ID_CANGROW: + case PROPERTY_ID_CANSHRINK: + case PROPERTY_ID_REPEATSECTION: + case PROPERTY_ID_PRINTREPEATEDVALUES: + case PROPERTY_ID_STARTNEWCOLUMN: + case PROPERTY_ID_RESETPAGENUMBER: + case PROPERTY_ID_PRINTWHENGROUPCHANGE: + case PROPERTY_ID_KEEPTOGETHER: + case PROPERTY_ID_DEEPTRAVERSING: + case PROPERTY_ID_PREEVALUATED: + case PROPERTY_ID_PRESERVEIRI: + case PROPERTY_ID_BACKTRANSPARENT: + case PROPERTY_ID_CONTROLBACKGROUNDTRANSPARENT: + { + const char** pResId = RID_STR_BOOL; + if ( PROPERTY_ID_KEEPTOGETHER == nId && uno::Reference< report::XGroup>(m_xReportComponent,uno::UNO_QUERY).is()) + pResId = RID_STR_KEEPTOGETHER_CONST; + implCreateListLikeControl(_xControlFactory,aOut,pResId,false,true); + } + break; + case PROPERTY_ID_INITIALFORMULA: + case PROPERTY_ID_FORMULA: + aOut.PrimaryButtonId = UID_RPT_PROP_FORMULA; + aOut.HasPrimaryButton = true; + aOut.Control = _xControlFactory->createPropertyControl(inspection::PropertyControlType::MultiLineTextField , false); + break; + case PROPERTY_ID_CONDITIONALPRINTEXPRESSION: + aOut.PrimaryButtonId = UID_RPT_PROP_FORMULA; + aOut.HasPrimaryButton = true; + aOut.Control = _xControlFactory->createPropertyControl(inspection::PropertyControlType::MultiLineTextField , false); + break; + case PROPERTY_ID_DATAFIELD: + { + uno::Reference< inspection::XStringListControl > xListControl( + _xControlFactory->createPropertyControl( + m_nDataFieldType == DATA_OR_FORMULA ? inspection::PropertyControlType::ComboBox : inspection::PropertyControlType::ListBox, false + ), + uno::UNO_QUERY_THROW + ); + + if ( m_nDataFieldType == DATA_OR_FORMULA ) + { + aOut.PrimaryButtonId = UID_RPT_PROP_FORMULA; + aOut.HasPrimaryButton = true; + } + + aOut.Control = xListControl.get(); + if ( m_nDataFieldType == USER_DEF_FUNCTION ) + { + // add function names + ::std::for_each(m_aFunctionNames.begin(), m_aFunctionNames.end(), + [&xListControl] (const TFunctions::value_type& func) { + xListControl->appendListEntry(func.first); + }); + } + else + { + for (auto const& it : std::as_const(m_aFieldNames)) + { + xListControl->appendListEntry(it); + } + for (auto const& it : std::as_const(m_aParamNames)) + { + xListControl->appendListEntry(it); + } + } + } + break; + case PROPERTY_ID_BACKCOLOR: + case PROPERTY_ID_CONTROLBACKGROUND: + aOut.Control = _xControlFactory->createPropertyControl( inspection::PropertyControlType::ColorListBox, false ); + break; + case PROPERTY_ID_FONT: + aOut.PrimaryButtonId = UID_RPT_RPT_PROP_DLG_FONT_TYPE; + aOut.Control = _xControlFactory->createPropertyControl( inspection::PropertyControlType::TextField, true ); + aOut.HasPrimaryButton = true; + break; + case PROPERTY_ID_AREA: + aOut.PrimaryButtonId = UID_RPT_RPT_PROP_DLG_AREA; + aOut.Control = _xControlFactory->createPropertyControl( inspection::PropertyControlType::TextField, true ); + aOut.HasPrimaryButton = true; + break; + case PROPERTY_ID_VERTICALALIGN: + implCreateListLikeControl(_xControlFactory,aOut,RID_STR_VERTICAL_ALIGN_CONST,false,true); + break; + case PROPERTY_ID_PARAADJUST: + implCreateListLikeControl(_xControlFactory,aOut,RID_STR_PARAADJUST_CONST,false,true); + break; + default: + { + aOut = m_xFormComponentHandler->describePropertyLine(PropertyName, _xControlFactory); + } + } + + if ( nId != -1 ) + { + aOut.Category = (OPropertyInfoService::getPropertyUIFlags(nId ) & PropUIFlags::DataProperty) ? + OUStringLiteral("Data") + : + OUStringLiteral("General"); + aOut.HelpURL = HelpIdUrl::getHelpURL( OPropertyInfoService::getPropertyHelpId( nId ) ); + aOut.DisplayName = OPropertyInfoService::getPropertyTranslation(nId); + } + + if ( ( nId == PROPERTY_ID_POSITIONX ) + || ( nId == PROPERTY_ID_POSITIONY ) + || ( nId == PROPERTY_ID_WIDTH ) + || ( nId == PROPERTY_ID_HEIGHT ) + ) + { + const MeasurementSystem eSystem = SvtSysLocale().GetLocaleData().getMeasurementSystemEnum(); + const sal_Int16 nDisplayUnit = VCLUnoHelper::ConvertToMeasurementUnit( MeasurementSystem::Metric == eSystem ? FieldUnit::CM : FieldUnit::INCH, 1 ); + uno::Reference< inspection::XNumericControl > xNumericControl(aOut.Control,uno::UNO_QUERY); + xNumericControl->setDecimalDigits( 2 ); + xNumericControl->setValueUnit( util::MeasureUnit::MM_100TH ); + uno::Reference< drawing::XShapeDescriptor> xShapeDesc(m_xReportComponent,uno::UNO_QUERY); + bool bSetMin = !xShapeDesc.is() || xShapeDesc->getShapeType() != "com.sun.star.drawing.CustomShape"; + if ( bSetMin ) + xNumericControl->setMinValue(beans::Optional<double>(true,0.0)); + if ( nDisplayUnit != -1 ) + xNumericControl->setDisplayUnit( nDisplayUnit ); + uno::Reference< report::XReportComponent> xComp(m_xReportComponent,uno::UNO_QUERY); + if ( xComp.is() && xComp->getSection().is() ) + { + uno::Reference< report::XReportDefinition > xReport = xComp->getSection()->getReportDefinition(); + OSL_ENSURE(xReport.is(),"Why is the report definition NULL!"); + if ( xReport.is() ) + { + const awt::Size aSize = getStyleProperty<awt::Size>(xReport,PROPERTY_PAPERSIZE); + const sal_Int32 nLeftMargin = getStyleProperty<sal_Int32>(xReport,PROPERTY_LEFTMARGIN); + const sal_Int32 nRightMargin = getStyleProperty<sal_Int32>(xReport,PROPERTY_RIGHTMARGIN); + switch(nId) + { + case PROPERTY_ID_POSITIONX: + case PROPERTY_ID_WIDTH: + if ( bSetMin ) + xNumericControl->setMinValue(beans::Optional<double>(true,0.0)); + xNumericControl->setMaxValue(beans::Optional<double>(true,double(aSize.Width - nLeftMargin - nRightMargin))); + if ( PROPERTY_ID_WIDTH == nId ) + { + uno::Reference<report::XFixedLine> xFixedLine(m_xReportComponent,uno::UNO_QUERY); + if ( xFixedLine.is() && xFixedLine->getOrientation() == 1 ) // vertical + xNumericControl->setMinValue(beans::Optional<double>(true,0.08 )); + } + break; + default: + break; + } + } + } + else if ( PROPERTY_ID_HEIGHT == nId ) + { + const uno::Reference< report::XSection> xSection(m_xReportComponent,uno::UNO_QUERY); + if ( xSection.is() ) + { + sal_Int32 nHeight = 0; + const sal_Int32 nCount = xSection->getCount(); + for (sal_Int32 i = 0; i < nCount; ++i) + { + uno::Reference<drawing::XShape> xShape(xSection->getByIndex(i),uno::UNO_QUERY); + nHeight = ::std::max<sal_Int32>(nHeight,xShape->getPosition().Y + xShape->getSize().Height); + } + xNumericControl->setMinValue(beans::Optional<double>(true,nHeight )); + } + } + } + return aOut; +} + +beans::Property GeometryHandler::getProperty(const OUString & PropertyName) +{ + uno::Sequence< beans::Property > aProps = getSupportedProperties(); + const beans::Property* pIter = aProps.getConstArray(); + const beans::Property* pEnd = pIter + aProps.getLength(); + const beans::Property* pFind = ::std::find_if(pIter, pEnd, + [&PropertyName] (const beans::Property& x) -> bool { + return x.Name == PropertyName; + }); + if ( pFind == pEnd ) + return beans::Property(); + return *pFind; +} +uno::Any GeometryHandler::getConstantValue(bool _bToControlValue,const char** pResId,const uno::Any& _aValue,const OUString& _sConstantName,const OUString & PropertyName ) +{ + std::vector<OUString> aList; + for (const char** pItem = pResId; *pItem; ++pItem) + aList.push_back(RptResId(*pItem)); + uno::Sequence< OUString > aSeq(aList.size()); + for (size_t i = 0; i < aList.size(); ++i) + aSeq[i] = aList[i]; + + uno::Reference< inspection::XStringRepresentation > xConversionHelper = inspection::StringRepresentation::createConstant( m_xContext,m_xTypeConverter,_sConstantName,aSeq); + if ( _bToControlValue ) + { + return uno::makeAny( xConversionHelper->convertToControlValue( _aValue ) ); + } + else + { + OUString sControlValue; + _aValue >>= sControlValue; + const beans::Property aProp = getProperty(PropertyName); + return xConversionHelper->convertToPropertyValue( sControlValue, aProp.Type ); + } +} + +uno::Any SAL_CALL GeometryHandler::convertToPropertyValue(const OUString & PropertyName, const uno::Any & _rControlValue) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + uno::Any aPropertyValue( _rControlValue ); + const sal_Int32 nId = OPropertyInfoService::getPropertyId(PropertyName); + switch(nId) + { + case PROPERTY_ID_FORCENEWPAGE: + case PROPERTY_ID_NEWROWORCOL: + aPropertyValue = getConstantValue(false,RID_STR_FORCENEWPAGE_CONST,_rControlValue,"com.sun.star.report.ForceNewPage",PropertyName); + break; + case PROPERTY_ID_GROUPKEEPTOGETHER: + aPropertyValue = getConstantValue(false,RID_STR_GROUPKEEPTOGETHER_CONST,_rControlValue,"com.sun.star.report.GroupKeepTogether",PropertyName); + break; + case PROPERTY_ID_PAGEHEADEROPTION: + case PROPERTY_ID_PAGEFOOTEROPTION: + aPropertyValue = getConstantValue(false,RID_STR_REPORTPRINTOPTION_CONST,_rControlValue,"com.sun.star.report.ReportPrintOption",PropertyName); + break; + case PROPERTY_ID_BACKCOLOR: + case PROPERTY_ID_CONTROLBACKGROUND: + if ( !_rControlValue.hasValue() ) + { + aPropertyValue <<= COL_TRANSPARENT; + break; + } + [[fallthrough]]; + + case PROPERTY_ID_KEEPTOGETHER: + if ( uno::Reference< report::XGroup>(m_xReportComponent,uno::UNO_QUERY).is()) + { + aPropertyValue = getConstantValue(false,RID_STR_KEEPTOGETHER_CONST,_rControlValue,"com.sun.star.report.KeepTogether",PropertyName); + break; + } + [[fallthrough]]; + + case PROPERTY_ID_VISIBLE: + case PROPERTY_ID_CANGROW: + case PROPERTY_ID_CANSHRINK: + case PROPERTY_ID_REPEATSECTION: + case PROPERTY_ID_PRINTREPEATEDVALUES: + case PROPERTY_ID_STARTNEWCOLUMN: + case PROPERTY_ID_RESETPAGENUMBER: + case PROPERTY_ID_PRINTWHENGROUPCHANGE: + case PROPERTY_ID_DEEPTRAVERSING: + case PROPERTY_ID_PREEVALUATED: + case PROPERTY_ID_PRESERVEIRI: + case PROPERTY_ID_BACKTRANSPARENT: + case PROPERTY_ID_CONTROLBACKGROUNDTRANSPARENT: + { + if ( aPropertyValue.hasValue() ) + { + const beans::Property aProp = getProperty(PropertyName); + if ( aPropertyValue.getValueType().equals( aProp.Type ) ) + // nothing to do, type is already as desired + return aPropertyValue; + + if ( _rControlValue.getValueType().getTypeClass() == uno::TypeClass_STRING ) + { + OUString sControlValue; + _rControlValue >>= sControlValue; + + const uno::Reference< inspection::XStringRepresentation > xConversionHelper = inspection::StringRepresentation::create( m_xContext,m_xTypeConverter ); + aPropertyValue = xConversionHelper->convertToPropertyValue( sControlValue, aProp.Type ); + } + else + { + try + { + aPropertyValue = m_xTypeConverter->convertTo( _rControlValue, aProp.Type ); + } + catch( const uno::Exception& ) + { + OSL_FAIL( "GeometryHandler::convertToPropertyValue: caught an exception while converting via TypeConverter!" ); + } + } + } + + break; + } + case PROPERTY_ID_CONDITIONALPRINTEXPRESSION: + case PROPERTY_ID_INITIALFORMULA: + case PROPERTY_ID_FORMULA: + return uno::makeAny( impl_convertToFormula( _rControlValue ) ); + case PROPERTY_ID_DATAFIELD: + { + OUString sDataField; + _rControlValue >>= sDataField; + if ( isDefaultFunction(sDataField,sDataField) ) + { + OSL_ENSURE(m_xFunction.is(),"No function set!"); + aPropertyValue <<= impl_convertToFormula( uno::makeAny(lcl_getQuotedFunctionName(m_xFunction)) ); + } + else + aPropertyValue <<= impl_convertToFormula( _rControlValue ); + } + break; + case PROPERTY_ID_POSITIONX: + { + aPropertyValue = m_xFormComponentHandler->convertToPropertyValue(PropertyName, _rControlValue); + sal_Int32 nPosX = 0; + aPropertyValue >>= nPosX; + const uno::Reference< report::XReportComponent> xSourceReportComponent(m_xReportComponent,uno::UNO_QUERY); + if ( xSourceReportComponent->getSection().is() ) + nPosX += getStyleProperty<sal_Int32>(xSourceReportComponent->getSection()->getReportDefinition(),PROPERTY_LEFTMARGIN); + aPropertyValue <<= nPosX; + } + break; + case PROPERTY_ID_FONT: + aPropertyValue = m_xFormComponentHandler->convertToPropertyValue(PROPERTY_FONT, _rControlValue); + break; + case PROPERTY_ID_SCOPE: + case PROPERTY_ID_FORMULALIST: + case PROPERTY_ID_AREA: + aPropertyValue = _rControlValue; + break; + case PROPERTY_ID_TYPE: + { + OUString sValue; + _rControlValue >>= sValue; + + sal_uInt32 nFound(RESARRAY_INDEX_NOTFOUND); + sal_uInt32 i = 0; + for (const char** pItem = RID_STR_TYPE_CONST; *pItem; ++pItem) + { + if (sValue == RptResId(*pItem)) + { + nFound = i; + break; + } + ++i; + } + if (nFound != RESARRAY_INDEX_NOTFOUND) + aPropertyValue <<= nFound; + } + break; + case PROPERTY_ID_MIMETYPE: + aPropertyValue = _rControlValue; + break; + case PROPERTY_ID_VERTICALALIGN: + { + OUString sValue; + _rControlValue >>= sValue; + + sal_uInt32 nFound(RESARRAY_INDEX_NOTFOUND); + sal_uInt32 i = 0; + for (const char** pItem = RID_STR_VERTICAL_ALIGN_CONST; *pItem; ++pItem) + { + if (sValue == RptResId(*pItem)) + { + nFound = i; + break; + } + ++i; + } + if (nFound != RESARRAY_INDEX_NOTFOUND) + aPropertyValue <<= static_cast<style::VerticalAlignment>(nFound); + } + break; + case PROPERTY_ID_PARAADJUST: + { + OUString sValue; + _rControlValue >>= sValue; + + sal_uInt32 nFound(RESARRAY_INDEX_NOTFOUND); + sal_uInt32 i = 0; + for (const char** pItem = RID_STR_PARAADJUST_CONST; *pItem; ++pItem) + { + if (sValue == RptResId(*pItem)) + { + nFound = i; + break; + } + ++i; + } + + if (nFound != RESARRAY_INDEX_NOTFOUND) + aPropertyValue <<= static_cast<sal_Int16>(nFound); + } + break; + default: + return m_xFormComponentHandler->convertToPropertyValue(PropertyName, _rControlValue); + } + return aPropertyValue; +} + +uno::Any SAL_CALL GeometryHandler::convertToControlValue(const OUString & PropertyName, const uno::Any & _rPropertyValue, const uno::Type & _rControlValueType) +{ + uno::Any aControlValue( _rPropertyValue ); + if ( !aControlValue.hasValue() ) + // NULL is converted to NULL + return aControlValue; + + uno::Any aPropertyValue(_rPropertyValue); + + ::osl::MutexGuard aGuard( m_aMutex ); + const sal_Int32 nId = OPropertyInfoService::getPropertyId(PropertyName); + switch(nId) + { + case PROPERTY_ID_AREA: + break; + case PROPERTY_ID_FORCENEWPAGE: + case PROPERTY_ID_NEWROWORCOL: + aControlValue = getConstantValue(true,RID_STR_FORCENEWPAGE_CONST,aPropertyValue,"com.sun.star.report.ForceNewPage",PropertyName); + break; + case PROPERTY_ID_GROUPKEEPTOGETHER: + aControlValue = getConstantValue(true,RID_STR_GROUPKEEPTOGETHER_CONST,aPropertyValue,"com.sun.star.report.GroupKeepTogether",PropertyName); + break; + case PROPERTY_ID_PAGEHEADEROPTION: + case PROPERTY_ID_PAGEFOOTEROPTION: + aControlValue = getConstantValue(true,RID_STR_REPORTPRINTOPTION_CONST,aPropertyValue,"com.sun.star.report.ReportPrintOption",PropertyName); + break; + case PROPERTY_ID_KEEPTOGETHER: + if ( uno::Reference< report::XGroup>(m_xReportComponent,uno::UNO_QUERY).is()) + { + aControlValue = getConstantValue(true,RID_STR_KEEPTOGETHER_CONST,aPropertyValue,"com.sun.star.report.KeepTogether",PropertyName); + break; + } + [[fallthrough]]; + case PROPERTY_ID_VISIBLE: + case PROPERTY_ID_CANGROW: + case PROPERTY_ID_CANSHRINK: + case PROPERTY_ID_REPEATSECTION: + case PROPERTY_ID_PRINTREPEATEDVALUES: + case PROPERTY_ID_STARTNEWCOLUMN: + case PROPERTY_ID_RESETPAGENUMBER: + case PROPERTY_ID_PRINTWHENGROUPCHANGE: + case PROPERTY_ID_DEEPTRAVERSING: + case PROPERTY_ID_PREEVALUATED: + case PROPERTY_ID_PRESERVEIRI: + case PROPERTY_ID_BACKTRANSPARENT: + case PROPERTY_ID_CONTROLBACKGROUNDTRANSPARENT: + { + if ( _rControlValueType.getTypeClass() == uno::TypeClass_STRING ) + { + const uno::Reference< inspection::XStringRepresentation > xConversionHelper = inspection::StringRepresentation::create( m_xContext,m_xTypeConverter ); + aControlValue <<= xConversionHelper->convertToControlValue( aPropertyValue ); + } + else + { + try + { + aControlValue = m_xTypeConverter->convertTo( aPropertyValue, _rControlValueType ); + } + catch( const uno::Exception& ) + { + OSL_FAIL( "GeometryHandler::convertToControlValue: caught an exception while converting via TypeConverter!" ); + } + } + break; + } + case PROPERTY_ID_CONDITIONALPRINTEXPRESSION: + case PROPERTY_ID_INITIALFORMULA: + case PROPERTY_ID_FORMULA: + lcl_convertFormulaTo(aPropertyValue,aControlValue); + break; + case PROPERTY_ID_DATAFIELD: + { + OUString sValue; + aControlValue >>= sValue; + if ( isDefaultFunction(sValue,sValue) ) + aControlValue <<= sValue; + else + lcl_convertFormulaTo(aPropertyValue,aControlValue); + } + break; + case PROPERTY_ID_FONT: + aControlValue = m_xFormComponentHandler->convertToControlValue(PROPERTY_FONT, aPropertyValue, _rControlValueType); + break; + case PROPERTY_ID_POSITIONX: + { + sal_Int32 nPosX = 0; + aPropertyValue >>= nPosX; + const uno::Reference< report::XReportComponent> xSourceReportComponent(m_xReportComponent,uno::UNO_QUERY); + if ( xSourceReportComponent->getSection().is() ) + nPosX -= getStyleProperty<sal_Int32>(xSourceReportComponent->getSection()->getReportDefinition(),PROPERTY_LEFTMARGIN); + aPropertyValue <<= nPosX; + aControlValue = m_xFormComponentHandler->convertToControlValue(PropertyName, aPropertyValue, _rControlValueType); + } + break; + case PROPERTY_ID_FORMULALIST: + aControlValue <<= m_sDefaultFunction; + break; + case PROPERTY_ID_SCOPE: + aControlValue <<= m_sScope; + break; + case PROPERTY_ID_MIMETYPE: + aControlValue = aPropertyValue; + break; + case PROPERTY_ID_TYPE: + { + if (m_nDataFieldType < SAL_N_ELEMENTS(RID_STR_TYPE_CONST) - 1) + aControlValue <<= RptResId(RID_STR_TYPE_CONST[m_nDataFieldType]); + } + break; + case PROPERTY_ID_VERTICALALIGN: + { + style::VerticalAlignment nParagraphVertAlign = style::VerticalAlignment_TOP; + aPropertyValue >>= nParagraphVertAlign; + if (sal_uInt32(nParagraphVertAlign) < SAL_N_ELEMENTS(RID_STR_VERTICAL_ALIGN_CONST) - 1) + aControlValue <<= RptResId(RID_STR_VERTICAL_ALIGN_CONST[static_cast<sal_uInt32>(nParagraphVertAlign)]); + } + break; + case PROPERTY_ID_PARAADJUST: + { + sal_Int16 nParagraphAdjust = sal_Int16(style::ParagraphAdjust_LEFT); + aPropertyValue >>= nParagraphAdjust; + if (o3tl::make_unsigned(nParagraphAdjust) < SAL_N_ELEMENTS(RID_STR_PARAADJUST_CONST) - 1) + aControlValue <<= RptResId(RID_STR_PARAADJUST_CONST[nParagraphAdjust]); + } + break; + case PROPERTY_ID_BACKCOLOR: + case PROPERTY_ID_CONTROLBACKGROUND: + { + Color nColor = COL_TRANSPARENT; + if ( (aPropertyValue >>= nColor) && COL_TRANSPARENT == nColor ) + aPropertyValue.clear(); + } + [[fallthrough]]; + default: + aControlValue = m_xFormComponentHandler->convertToControlValue(PropertyName, aPropertyValue, _rControlValueType); + } + return aControlValue; +} +void SAL_CALL GeometryHandler::addPropertyChangeListener(const uno::Reference< beans::XPropertyChangeListener > & _rxListener) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + m_aPropertyListeners.addListener( _rxListener ); + m_xFormComponentHandler->addPropertyChangeListener(_rxListener); +} + +void SAL_CALL GeometryHandler::removePropertyChangeListener(const uno::Reference< beans::XPropertyChangeListener > & _rxListener) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + m_aPropertyListeners.removeListener( _rxListener ); + m_xFormComponentHandler->removePropertyChangeListener(_rxListener); +} + + +uno::Sequence< beans::Property > SAL_CALL GeometryHandler::getSupportedProperties() +{ + ::std::vector< beans::Property > aNewProps; + aNewProps.reserve(20); // only a guess + rptui::OPropertyInfoService::getExcludeProperties( aNewProps, m_xFormComponentHandler ); + + const OUString pIncludeProperties[] = + { + OUString(PROPERTY_FORCENEWPAGE) + ,OUString(PROPERTY_KEEPTOGETHER) + ,OUString(PROPERTY_CANGROW) + ,OUString(PROPERTY_CANSHRINK) + ,OUString(PROPERTY_REPEATSECTION) + ,OUString(PROPERTY_PRINTREPEATEDVALUES) + ,OUString(PROPERTY_CONDITIONALPRINTEXPRESSION) + ,OUString(PROPERTY_STARTNEWCOLUMN) + ,OUString(PROPERTY_RESETPAGENUMBER) + ,OUString(PROPERTY_PRINTWHENGROUPCHANGE) + ,OUString(PROPERTY_VISIBLE) + ,OUString(PROPERTY_PAGEHEADEROPTION) + ,OUString(PROPERTY_PAGEFOOTEROPTION) + ,OUString("ControlLabel") + ,OUString(PROPERTY_POSITIONX) + ,OUString(PROPERTY_POSITIONY) + ,OUString(PROPERTY_WIDTH) + ,OUString(PROPERTY_HEIGHT) + ,OUString(PROPERTY_AUTOGROW) + ,OUString(PROPERTY_PREEVALUATED) + ,OUString(PROPERTY_DEEPTRAVERSING) + ,OUString(PROPERTY_FORMULA) + ,OUString(PROPERTY_INITIALFORMULA) + ,OUString(PROPERTY_PRESERVEIRI) + ,OUString(PROPERTY_DATAFIELD) + ,OUString(PROPERTY_FONT) + ,OUString(PROPERTY_BACKCOLOR) + ,OUString(PROPERTY_BACKTRANSPARENT) + ,OUString(PROPERTY_CONTROLBACKGROUND) + ,OUString(PROPERTY_CONTROLBACKGROUNDTRANSPARENT) + ,OUString(PROPERTY_LABEL) + ,OUString(PROPERTY_MIMETYPE) + ,OUString(PROPERTY_VERTICALALIGN) + ,OUString(PROPERTY_PARAADJUST) + }; + const uno::Reference < beans::XPropertySetInfo > xInfo = m_xReportComponent->getPropertySetInfo(); + const uno::Sequence< beans::Property> aSeq = xInfo->getProperties(); + for (const auto & rIncludeProp : pIncludeProperties) + { + const beans::Property* pFind = ::std::find_if(aSeq.begin(), aSeq.end(), + [&rIncludeProp] (const beans::Property& x) -> bool { + return x.Name == rIncludeProp; + }); + if ( pFind != aSeq.end() ) + { + // special case for controls which contain a data field + if ( PROPERTY_DATAFIELD == rIncludeProp ) + { + beans::Property aValue; + aValue.Name = PROPERTY_FORMULALIST; + aNewProps.push_back(aValue); + aValue.Name = PROPERTY_SCOPE; + aNewProps.push_back(aValue); + aValue.Name = PROPERTY_TYPE; + aNewProps.push_back(aValue); + } + aNewProps.push_back(*pFind); + } + } + + // special property for shapes +// if ( uno::Reference< report::XShape>(m_xReportComponent,uno::UNO_QUERY).is() ) +// { +// beans::Property aValue; +// aValue.Name = PROPERTY_AREA; +// aNewProps.push_back(aValue); +// } + // re-enable when the remaining issues of #i88727# are fixed + + return uno::Sequence< beans::Property > (&(*aNewProps.begin()),aNewProps.size()); +} + +uno::Sequence< OUString > SAL_CALL GeometryHandler::getSupersededProperties() +{ + uno::Sequence< OUString > aRet; + const uno::Reference<report::XReportDefinition> xReport(m_xReportComponent,uno::UNO_QUERY); + if ( xReport.is() && !uno::Reference< report::XSection>(xReport->getParent(),uno::UNO_QUERY).is() ) + { + aRet.realloc(5); + OUString* pIter = aRet.getArray(); + *pIter++ = PROPERTY_POSITIONX; + *pIter++ = PROPERTY_POSITIONY; + *pIter++ = PROPERTY_WIDTH; + *pIter++ = PROPERTY_HEIGHT; + *pIter++ = PROPERTY_DATAFIELD; + } + return aRet; +} + +uno::Sequence< OUString > SAL_CALL GeometryHandler::getActuatingProperties() +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + uno::Sequence< OUString > aSeq(5); + aSeq[0] = PROPERTY_BACKTRANSPARENT; + aSeq[1] = PROPERTY_CONTROLBACKGROUNDTRANSPARENT; + aSeq[2] = PROPERTY_FORMULALIST; + aSeq[3] = PROPERTY_TYPE; + aSeq[4] = PROPERTY_DATAFIELD; + + return ::comphelper::concatSequences(m_xFormComponentHandler->getActuatingProperties(),aSeq); +} + +sal_Bool SAL_CALL GeometryHandler::isComposable(const OUString & _rPropertyName) +{ + return OPropertyInfoService::isComposable( _rPropertyName, m_xFormComponentHandler ); +} + +inspection::InteractiveSelectionResult SAL_CALL GeometryHandler::onInteractivePropertySelection(const OUString & PropertyName, sal_Bool Primary, uno::Any & _rData, const uno::Reference< inspection::XObjectInspectorUI > & _rxInspectorUI) +{ + if ( !_rxInspectorUI.is() ) + throw lang::NullPointerException(); + if (PropertyName == PROPERTY_FILTER) + { + ::osl::ClearableMutexGuard aGuard( m_aMutex ); + + inspection::InteractiveSelectionResult eResult = inspection::InteractiveSelectionResult_Cancelled; + OUString sClause; + if ( impl_dialogFilter_nothrow( sClause, aGuard ) ) + { + _rData <<= sClause; + eResult = inspection::InteractiveSelectionResult_ObtainedValue; + } + return eResult; + } + else if (PropertyName == PROPERTY_FONT) + { + ::osl::ClearableMutexGuard aGuard( m_aMutex ); + + inspection::InteractiveSelectionResult eResult = inspection::InteractiveSelectionResult_Cancelled; + const uno::Reference< awt::XWindow> xInspectorWindow(m_xContext->getValueByName("DialogParentWindow") ,uno::UNO_QUERY); + const uno::Reference< report::XReportControlFormat> xReportControlFormat(m_xReportComponent,uno::UNO_QUERY); + aGuard.clear(); + + uno::Sequence< beans::NamedValue > aFontSettings; + if ( rptui::openCharDialog( xReportControlFormat, xInspectorWindow, aFontSettings ) ) + { + _rData <<= aFontSettings; + eResult = inspection::InteractiveSelectionResult_ObtainedValue; + } + return eResult; + } + else if ( PropertyName == PROPERTY_FORMULA + || PropertyName == PROPERTY_INITIALFORMULA + || PropertyName == PROPERTY_DATAFIELD + || PropertyName == PROPERTY_CONDITIONALPRINTEXPRESSION) + { + ::osl::ClearableMutexGuard aGuard( m_aMutex ); + + + OUString sFormula; + m_xReportComponent->getPropertyValue(PropertyName) >>= sFormula; + const uno::Reference< awt::XWindow> xInspectorWindow(m_xContext->getValueByName("DialogParentWindow") ,uno::UNO_QUERY); + uno::Reference< uno::XComponentContext > xContext = m_xContext; + uno::Reference< beans::XPropertySet > xRowSet( m_xRowSet,uno::UNO_QUERY); + aGuard.clear(); + + inspection::InteractiveSelectionResult eResult = inspection::InteractiveSelectionResult_Cancelled; + if ( rptui::openDialogFormula_nothrow( sFormula, xContext,xInspectorWindow,xRowSet ) ) + { + _rData <<= sFormula; + eResult = inspection::InteractiveSelectionResult_ObtainedValue; + } + return eResult; + } + else if (PropertyName == PROPERTY_AREA) + { + ::osl::ClearableMutexGuard aGuard( m_aMutex ); + + inspection::InteractiveSelectionResult eResult = inspection::InteractiveSelectionResult_Cancelled; + const uno::Reference< awt::XWindow> xInspectorWindow(m_xContext->getValueByName("DialogParentWindow") ,uno::UNO_QUERY); + const uno::Reference< report::XShape> xShape(m_xReportComponent,uno::UNO_QUERY); + aGuard.clear(); + + if ( rptui::openAreaDialog( xShape, xInspectorWindow) ) + { + eResult = inspection::InteractiveSelectionResult_ObtainedValue; + beans::PropertyChangeEvent aScopeEvent; + aScopeEvent.PropertyName = PROPERTY_FILLCOLOR; + aScopeEvent.NewValue = xShape->getPropertyValue(PROPERTY_FILLCOLOR); + m_aPropertyListeners.notify( aScopeEvent, &beans::XPropertyChangeListener::propertyChange ); + } + return eResult; + } + + + return m_xFormComponentHandler->onInteractivePropertySelection(PropertyName, Primary, _rData, _rxInspectorUI); +} + +void SAL_CALL GeometryHandler::actuatingPropertyChanged(const OUString & ActuatingPropertyName, const uno::Any & NewValue, const uno::Any & OldValue, const uno::Reference< inspection::XObjectInspectorUI > & _rxInspectorUI, sal_Bool _bFirstTimeInit) +{ + if ( !_rxInspectorUI.is() ) + throw lang::NullPointerException(); + + ::osl::MutexGuard aGuard( m_aMutex ); + const sal_Int32 nId = OPropertyInfoService::getPropertyId(ActuatingPropertyName); + switch(nId) + { + case PROPERTY_ID_TYPE: + { + sal_uInt32 nNewVal = 0; + NewValue >>= nNewVal; + switch(nNewVal) + { + case DATA_OR_FORMULA: + _rxInspectorUI->rebuildPropertyUI(PROPERTY_DATAFIELD); + _rxInspectorUI->enablePropertyUI(PROPERTY_DATAFIELD,true); + _rxInspectorUI->enablePropertyUI(PROPERTY_FORMULALIST,false); + _rxInspectorUI->enablePropertyUI(PROPERTY_SCOPE,false); + OSL_ENSURE(m_sDefaultFunction.isEmpty(),"Why is the m_sDefaultFunction set?"); + OSL_ENSURE(m_sScope.isEmpty(),"Why is the m_sScope set?"); + break; + case FUNCTION: + _rxInspectorUI->rebuildPropertyUI(PROPERTY_DATAFIELD); + _rxInspectorUI->rebuildPropertyUI(PROPERTY_FORMULALIST); + _rxInspectorUI->enablePropertyUI(PROPERTY_DATAFIELD,true); + _rxInspectorUI->enablePropertyUI(PROPERTY_FORMULALIST,!m_sDefaultFunction.isEmpty()); + _rxInspectorUI->enablePropertyUI(PROPERTY_SCOPE,!m_sScope.isEmpty()); + break; + case USER_DEF_FUNCTION: + _rxInspectorUI->enablePropertyUI(PROPERTY_DATAFIELD,false); + _rxInspectorUI->enablePropertyUI(PROPERTY_FORMULALIST,true); + _rxInspectorUI->rebuildPropertyUI(PROPERTY_FORMULALIST); + _rxInspectorUI->enablePropertyUI(PROPERTY_SCOPE,false); + break; + case COUNTER: + _rxInspectorUI->enablePropertyUI(PROPERTY_DATAFIELD,false); + _rxInspectorUI->enablePropertyUI(PROPERTY_FORMULALIST,false); + _rxInspectorUI->enablePropertyUI(PROPERTY_SCOPE,true); + break; + } + } + break; + case PROPERTY_ID_DATAFIELD: + { + bool bEnable = (m_nDataFieldType != DATA_OR_FORMULA && m_nDataFieldType != COUNTER ); + if ( bEnable ) + { + OUString sValue; + m_xReportComponent->getPropertyValue( PROPERTY_DATAFIELD ) >>= sValue; + bEnable = !sValue.isEmpty(); + } + _rxInspectorUI->enablePropertyUI(PROPERTY_FORMULALIST,bEnable); + if ( bEnable ) + { + _rxInspectorUI->rebuildPropertyUI(PROPERTY_DATAFIELD); + _rxInspectorUI->rebuildPropertyUI(PROPERTY_FORMULALIST); + } + m_xFormComponentHandler->actuatingPropertyChanged(ActuatingPropertyName, NewValue, OldValue, _rxInspectorUI, _bFirstTimeInit); + } + break; + case PROPERTY_ID_FORMULALIST: + { + _rxInspectorUI->enablePropertyUI(PROPERTY_SCOPE,m_nDataFieldType == FUNCTION || m_nDataFieldType == COUNTER); + } + break; + case PROPERTY_ID_BACKTRANSPARENT: + case PROPERTY_ID_CONTROLBACKGROUNDTRANSPARENT: + { + bool bValue = false; + NewValue >>= bValue; + bValue = !bValue; + _rxInspectorUI->enablePropertyUI(PROPERTY_BACKCOLOR,bValue); + _rxInspectorUI->enablePropertyUI(PROPERTY_CONTROLBACKGROUND,bValue); + } + break; + default: + m_xFormComponentHandler->actuatingPropertyChanged(ActuatingPropertyName, NewValue, OldValue, _rxInspectorUI, _bFirstTimeInit); + break; + } +} + +sal_Bool SAL_CALL GeometryHandler::suspend(sal_Bool Suspend) +{ + return m_xFormComponentHandler->suspend(Suspend); +} + +bool GeometryHandler::impl_dialogFilter_nothrow( OUString& _out_rSelectedClause, ::osl::ClearableMutexGuard& _rClearBeforeDialog ) const +{ + _out_rSelectedClause.clear(); + bool bSuccess = false; + ::dbtools::SQLExceptionInfo aErrorInfo; + uno::Reference< awt::XWindow > xInspectorWindow; + uno::Reference< lang::XMultiComponentFactory > xFactory; + try + { + xFactory = m_xContext->getServiceManager(); + xInspectorWindow.set(m_xContext->getValueByName("DialogParentWindow") ,uno::UNO_QUERY); + uno::Reference<sdbc::XConnection> xCon(m_xContext->getValueByName("ActiveConnection") ,uno::UNO_QUERY); + if ( !xCon.is() ) + return false; + + uno::Reference< beans::XPropertySet> xRowSetProp(m_xRowSet,uno::UNO_QUERY); + if ( !m_xRowSet.is() ) + { + m_xRowSet.set(xFactory->createInstanceWithContext("com.sun.star.sdb.RowSet",m_xContext),uno::UNO_QUERY); + xRowSetProp.set(m_xRowSet,uno::UNO_QUERY); + xRowSetProp->setPropertyValue(PROPERTY_ACTIVECONNECTION,uno::makeAny(xCon)); + ::comphelper::copyProperties(m_xReportComponent,xRowSetProp); + } + + // get a composer for the statement which the form is currently based on + uno::Reference< sdb::XSingleSelectQueryComposer > xComposer( ::dbtools::getCurrentSettingsComposer( xRowSetProp, m_xContext, nullptr ) ); + OSL_ENSURE( xComposer.is(), "GeometryHandler::impl_dialogFilter_nothrow: could not obtain a composer!" ); + if ( !xComposer.is() ) + return false; + + // create the dialog + uno::Reference< ui::dialogs::XExecutableDialog > xDialog = sdb::FilterDialog::createWithQuery(m_xContext, xComposer, m_xRowSet, xInspectorWindow); + + const OUString sPropertyUIName(RptResId(RID_STR_FILTER)); + // initialize the dialog + xDialog->setTitle( sPropertyUIName ); + + _rClearBeforeDialog.clear(); + bSuccess = ( xDialog->execute() != 0 ); + if ( bSuccess ) + _out_rSelectedClause = xComposer->getFilter(); + } + catch (const sdb::SQLContext& e) { aErrorInfo = e; } + catch (const sdbc::SQLWarning& e) { aErrorInfo = e; } + catch (const sdbc::SQLException& e) { aErrorInfo = e; } + catch( const uno::Exception& ) + { + TOOLS_WARN_EXCEPTION( "reportdesign", "GeometryHandler::impl_dialogFilter_nothrow" ); + } + + if ( aErrorInfo.isValid() ) + ::dbtools::showError( aErrorInfo, xInspectorWindow, m_xContext ); + + return bSuccess; +} + +void GeometryHandler::checkPosAndSize( const awt::Point& _aNewPos, + const awt::Size& _aSize) +{ + const uno::Reference< report::XReportComponent> xSourceReportComponent(m_xReportComponent,uno::UNO_QUERY); + const uno::Reference< report::XSection> xSection(xSourceReportComponent->getParent(),uno::UNO_QUERY); + if ( !xSection.is() || uno::Reference< report::XShape>(xSourceReportComponent,uno::UNO_QUERY).is() ) // shapes can overlap. + return; + + ::Point aPos(VCLPoint(_aNewPos)); + if ( aPos.X() < 0 || aPos.Y() < 0 ) // TODO: have to check size with pos aka || (aPos.X() + aAwtSize.Width) > m_xSection->getReportDefinition()-> + throw beans::PropertyVetoException(RptResId(RID_STR_ILLEGAL_POSITION),xSourceReportComponent); + + ::tools::Rectangle aSourceRect(aPos,VCLSize(_aSize)); + + const sal_Int32 nCount = xSection->getCount(); + for (sal_Int32 i = 0; i < nCount ; ++i) + { + const uno::Reference< report::XReportComponent> xReportComponent(xSection->getByIndex(i),uno::UNO_QUERY); + if ( xReportComponent.is() && xReportComponent != xSourceReportComponent ) + { + const ::tools::Rectangle aBoundRect(VCLPoint(xReportComponent->getPosition()),VCLSize(xReportComponent->getSize())); + const ::tools::Rectangle aRect = aSourceRect.GetIntersection(aBoundRect); + if ( !aRect.IsEmpty() && (aRect.Left() != aRect.Right() && aRect.Top() != aRect.Bottom() ) ) + throw beans::PropertyVetoException(RptResId( RID_STR_OVERLAP_OTHER_CONTROL),xSourceReportComponent); + } + } +} + +void GeometryHandler::impl_fillFormulaList_nothrow(::std::vector< OUString >& out_rList) const +{ + if ( m_nDataFieldType == FUNCTION ) + { + for (auto const& it : m_aDefaultFunctions) + { + out_rList.push_back(it.getName()); + } + } + else if ( m_nDataFieldType == USER_DEF_FUNCTION ) + ::std::transform( m_aFunctionNames.begin(), + m_aFunctionNames.end(), + ::std::back_inserter(out_rList), + ::o3tl::select1st< TFunctions::value_type >() ); +} + +OUString GeometryHandler::impl_ConvertUIToMimeType_nothrow(const OUString& _sUIName) const +{ + ::std::vector< OUString > aList; + impl_fillMimeTypes_nothrow(aList); + OUString sRet; + ::std::vector< OUString >::const_iterator aFind = ::std::find(aList.begin(),aList.end(),_sUIName); + if ( aFind != aList.end() ) + { + const std::size_t nPos = aFind - aList.begin(); + const uno::Reference< report::XReportDefinition> xReportDefinition(m_xReportComponent,uno::UNO_QUERY); + if ( xReportDefinition.is() ) + { + const uno::Sequence< OUString > aMimeTypes( xReportDefinition->getAvailableMimeTypes() ); + sRet = aMimeTypes[nPos]; + } + } + return sRet; +} + +OUString GeometryHandler::impl_ConvertMimeTypeToUI_nothrow(const OUString& _sMimetype) const +{ + ::comphelper::MimeConfigurationHelper aMimeHelper(m_xContext); + OUString sRet; + std::shared_ptr<const SfxFilter> pFilter = SfxFilter::GetDefaultFilter( aMimeHelper.GetDocServiceNameFromMediaType(_sMimetype) ); + if ( pFilter ) + sRet = pFilter->GetUIName(); + if ( sRet.isEmpty() ) + sRet = _sMimetype; + return sRet; +} + +void GeometryHandler::impl_fillMimeTypes_nothrow(::std::vector< OUString >& _out_rList) const +{ + try + { + const uno::Reference< report::XReportDefinition> xReportDefinition(m_xReportComponent,uno::UNO_QUERY); + if ( xReportDefinition.is() ) + { + const uno::Sequence< OUString > aMimeTypes( xReportDefinition->getAvailableMimeTypes() ); + for(const OUString& rMimeType : aMimeTypes) + { + const OUString sDocName( impl_ConvertMimeTypeToUI_nothrow(rMimeType) ); + if ( !sDocName.isEmpty() ) + _out_rList.push_back(sDocName); + } + } + } + catch(uno::Exception&) + { + OSL_FAIL("Exception caught!"); + } +} + +void GeometryHandler::impl_fillScopeList_nothrow(::std::vector< OUString >& _out_rList) const +{ + try + { + const uno::Reference< report::XReportComponent> xSourceReportComponent(m_xReportComponent,uno::UNO_QUERY_THROW); + const uno::Reference< report::XSection> xSection(xSourceReportComponent->getParent(),uno::UNO_QUERY_THROW); + + const uno::Reference< report::XReportDefinition> xReportDefinition = xSection->getReportDefinition(); + const uno::Reference< report::XGroups> xGroups = xReportDefinition->getGroups(); + sal_Int32 nPos = -1; + uno::Reference< report::XGroup> xGroup = xSection->getGroup(); + if ( xGroup.is() ) + nPos = getPositionInIndexAccess(xGroups.get(),xGroup); + else if ( xSection == xReportDefinition->getDetail() ) + nPos = xGroups->getCount()-1; + + const OUString sGroup = RptResId(RID_STR_SCOPE_GROUP); + for (sal_Int32 i = 0 ; i <= nPos ; ++i) + { + xGroup.set(xGroups->getByIndex(i),uno::UNO_QUERY_THROW); + OUString sGroupName = sGroup.replaceFirst("%1",xGroup->getExpression()); + _out_rList.push_back(sGroupName); + } + _out_rList.push_back(xReportDefinition->getName()); + } + catch(uno::Exception&) + { + OSL_FAIL("Exception caught!"); + } +} + +uno::Reference< report::XFunctionsSupplier> GeometryHandler::fillScope_throw(OUString& _rsNamePostfix) +{ + uno::Reference< report::XFunctionsSupplier> xReturn; + + const uno::Reference< report::XReportComponent> xSourceReportComponent(m_xReportComponent,uno::UNO_QUERY_THROW); + const uno::Reference< report::XSection> xSection(xSourceReportComponent->getParent(),uno::UNO_QUERY_THROW); + const uno::Reference< report::XReportDefinition> xReportDefinition = xSection->getReportDefinition(); + if ( m_sScope.isEmpty() ) + { + const uno::Reference< report::XGroup> xGroup = xSection->getGroup(); + if ( xGroup.is() ) + { + OUString sGroupName = RptResId(RID_STR_SCOPE_GROUP); + _rsNamePostfix = xGroup->getExpression(); + m_sScope = sGroupName.replaceFirst("%1",_rsNamePostfix); + xReturn = xGroup.get(); + } + else if ( xSection == xReportDefinition->getDetail() ) + { + const uno::Reference< report::XGroups> xGroups = xReportDefinition->getGroups(); + const sal_Int32 nCount = xGroups->getCount(); + if ( nCount ) + { + const uno::Reference< report::XGroup> xGroup2(xGroups->getByIndex(nCount - 1),uno::UNO_QUERY_THROW); + OUString sGroupName = RptResId(RID_STR_SCOPE_GROUP); + _rsNamePostfix = xGroup2->getExpression(); + m_sScope = sGroupName.replaceFirst("%1",_rsNamePostfix); + xReturn = xGroup2.get(); + } + } + if ( m_sScope.isEmpty() ) + { + xReturn = xReportDefinition.get(); + _rsNamePostfix = m_sScope = xReportDefinition->getName(); + } + } + else if ( m_sScope == xReportDefinition->getName() ) + { + xReturn = xReportDefinition.get(); + _rsNamePostfix = m_sScope; + } + else + { + uno::Reference< report::XGroups> xGroups = xReportDefinition->getGroups(); + const sal_Int32 nCount = xGroups->getCount(); + + for (sal_Int32 i = 0 ; i < nCount; ++i) + { + const uno::Reference< report::XGroup> xGroup(xGroups->getByIndex(i),uno::UNO_QUERY_THROW); + OUString sGroupName = RptResId(RID_STR_SCOPE_GROUP); + if ( m_sScope == sGroupName.replaceFirst("%1",xGroup->getExpression()) ) + { + _rsNamePostfix = xGroup->getExpression(); + xReturn = xGroup.get(); + break; + } + } + + } + OSL_ENSURE(xReturn.is(),"Why don't we have a functionssupplier here!"); + + return xReturn; +} + +bool GeometryHandler::isDefaultFunction( const OUString& _sQuotedFunction + ,OUString& _rDataField + ,const uno::Reference< report::XFunctionsSupplier>& _xFunctionsSupplier + ,bool _bSet) const +{ + bool bDefaultFunction = false; + try + { + const uno::Reference< report::XReportComponent> xSourceReportComponent(m_xReportComponent,uno::UNO_QUERY_THROW); + const uno::Reference< report::XSection> xSection(xSourceReportComponent->getParent(),uno::UNO_QUERY_THROW); + const uno::Reference< report::XReportDefinition> xReportDefinition = xSection->getReportDefinition(); + + ::std::pair<TFunctions::const_iterator,TFunctions::const_iterator> aFind = m_aFunctionNames.equal_range(_sQuotedFunction); + while ( aFind.first != aFind.second ) + { + if ( !_xFunctionsSupplier.is() || _xFunctionsSupplier == aFind.first->second.second ) + { + const beans::Optional< OUString> aInitalFormula = aFind.first->second.first->getInitialFormula(); + if ( aInitalFormula.IsPresent ) + { + OUString sDefaultFunctionName; + bDefaultFunction = impl_isDefaultFunction_nothrow(aFind.first->second.first,_rDataField,sDefaultFunctionName); + if ( bDefaultFunction ) + { + m_xFunction = aFind.first->second.first; + if ( _bSet ) + { + m_sDefaultFunction = sDefaultFunctionName; + uno::Reference< report::XGroup> xGroup(aFind.first->second.second,uno::UNO_QUERY); + if ( xGroup.is() ) + { + OUString sGroupName = RptResId(RID_STR_SCOPE_GROUP); + m_sScope = sGroupName.replaceFirst("%1",xGroup->getExpression()); + } + else + m_sScope = xReportDefinition->getName(); + } + } + break; + } + } + ++(aFind.first); + } + } + catch(uno::Exception&) + { + OSL_FAIL("Exception caught!"); + } + return bDefaultFunction; +} + +bool GeometryHandler::impl_isDefaultFunction_nothrow( const uno::Reference< report::XFunction>& _xFunction + ,OUString& _rDataField + ,OUString& _rsDefaultFunctionName) const +{ + bool bDefaultFunction = false; + try + { + const OUString sFormula( _xFunction->getFormula() ); + i18nutil::SearchOptions2 aSearchOptions; + aSearchOptions.AlgorithmType2 = util::SearchAlgorithms2::REGEXP; + aSearchOptions.searchFlag = 0x00000100; + auto aIter = std::find_if(m_aDefaultFunctions.begin(), m_aDefaultFunctions.end(), + [&aSearchOptions, &sFormula](const DefaultFunction& rDefaultFunction) { + aSearchOptions.searchString = rDefaultFunction.m_sSearchString; + utl::TextSearch aTextSearch( aSearchOptions); + sal_Int32 start = 0; + sal_Int32 end = sFormula.getLength(); + return aTextSearch.SearchForward(sFormula, &start, &end) && start == 0 && end == sFormula.getLength(); + }); + if (aIter != m_aDefaultFunctions.end()) // default function found + { + sal_Int32 start = 0; + sal_Int32 end = sFormula.getLength(); + aSearchOptions.searchString = "\\[[:alpha:]+([:space:]*[:alnum:]*)*\\]"; + utl::TextSearch aDataSearch( aSearchOptions); + (void)aDataSearch.SearchForward(sFormula, &start, &end); + ++start; + _rDataField = sFormula.copy(start,end-start-1); + _rsDefaultFunctionName = aIter->m_sName; + bDefaultFunction = true; + } + } + catch(uno::Exception&) + { + OSL_FAIL("Exception caught!"); + } + return bDefaultFunction; +} + +void GeometryHandler::loadDefaultFunctions() +{ + if ( !m_aDefaultFunctions.empty() ) + return; + + m_aCounterFunction.m_bPreEvaluated = false; + m_aCounterFunction.m_sName = RptResId(RID_STR_F_COUNTER); + m_aCounterFunction.m_sFormula = "rpt:[%FunctionName] + 1"; + m_aCounterFunction.m_sSearchString = "rpt:\\[[:alpha:]+([:space:]*[:alnum:]*)*\\][:space:]*\\+[:space:]*[:digit:]*"; + m_aCounterFunction.m_sInitialFormula.IsPresent = true; + m_aCounterFunction.m_sInitialFormula.Value = "rpt:1"; + + DefaultFunction aDefault; + + aDefault.m_bPreEvaluated = true; + + aDefault.m_sName = RptResId(RID_STR_F_ACCUMULATION); + aDefault.m_sFormula = "rpt:[%Column] + [%FunctionName]"; + aDefault.m_sSearchString = "rpt:\\[[:alpha:]+([:space:]*[:alnum:]*)*\\][:space:]*\\+[:space:]*\\[[:alpha:]+([:space:]*[:alnum:]*)*\\]"; + aDefault.m_sInitialFormula.IsPresent = true; + aDefault.m_sInitialFormula.Value = "rpt:[%Column]"; + m_aDefaultFunctions.push_back(aDefault); + + aDefault.m_sName = RptResId(RID_STR_F_MINIMUM); + aDefault.m_sFormula = "rpt:IF([%Column] < [%FunctionName];[%Column];[%FunctionName])"; + aDefault.m_sSearchString = "rpt:IF\\((\\[[:alpha:]+([:space:]*[:alnum:]*)*\\])[:space:]*<[:space:]*(\\[[:alpha:]+([:space:]*[:alnum:]*)*\\]);[:space:]*\\1[:space:]*;[:space:]*\\3[:space:]*\\)"; + aDefault.m_sInitialFormula.IsPresent = true; + aDefault.m_sInitialFormula.Value = "rpt:[%Column]"; + m_aDefaultFunctions.push_back(aDefault); + + aDefault.m_sName = RptResId(RID_STR_F_MAXIMUM); + aDefault.m_sFormula = "rpt:IF([%Column] > [%FunctionName];[%Column];[%FunctionName])"; + aDefault.m_sSearchString = "rpt:IF\\((\\[[:alpha:]+([:space:]*[:alnum:]*)*\\])[:space:]*>[:space:]*(\\[[:alpha:]+([:space:]*[:alnum:]*)*\\]);[:space:]*\\1[:space:]*;[:space:]*\\3[:space:]*\\)"; + aDefault.m_sInitialFormula.IsPresent = true; + aDefault.m_sInitialFormula.Value = "rpt:[%Column]"; + m_aDefaultFunctions.push_back(aDefault); +} + +void GeometryHandler::createDefaultFunction(::osl::ResettableMutexGuard& _aGuard ,const OUString& _sFunction,const OUString& _sDataField) +{ + try + { + OUString sNamePostfix; + const uno::Reference< report::XFunctionsSupplier> xFunctionsSupplier = fillScope_throw(sNamePostfix); + + auto aIter = std::find_if(m_aDefaultFunctions.begin(), m_aDefaultFunctions.end(), + [&_sFunction](const DefaultFunction& rDefaultFunction) { return rDefaultFunction.m_sName == _sFunction; }); + if (aIter != m_aDefaultFunctions.end()) + { + const OUString sFunctionName( _sFunction + _sDataField + sNamePostfix); + const OUString sQuotedFunctionName(lcl_getQuotedFunctionName(sFunctionName)); + + beans::PropertyChangeEvent aEvent; + aEvent.PropertyName = PROPERTY_SCOPE; + aEvent.OldValue <<= m_sScope; + + ::std::pair<TFunctions::const_iterator,TFunctions::const_iterator> aFind = m_aFunctionNames.equal_range(sQuotedFunctionName); + while ( aFind.first != aFind.second ) + { + if ( xFunctionsSupplier == aFind.first->second.second ) + { + m_xFunction = aFind.first->second.first; + OUString sTemp; + isDefaultFunction(sQuotedFunctionName,sTemp,uno::Reference< report::XFunctionsSupplier>(),true); // implicitly sets the m_sScope + break; + } + ++(aFind.first); + } + if ( aFind.first == aFind.second ) + impl_createFunction(sFunctionName,_sDataField,*aIter); + + OBlocker aBlocker(m_bIn); + m_xReportComponent->setPropertyValue(PROPERTY_DATAFIELD,uno::makeAny( impl_convertToFormula( uno::makeAny(sQuotedFunctionName) ))); + aEvent.NewValue <<= m_sScope; + _aGuard.clear(); + m_aPropertyListeners.notify( aEvent, &beans::XPropertyChangeListener::propertyChange ); + } + } + catch(uno::Exception&) + { + OSL_FAIL("Exception caught!"); + } +} + +void GeometryHandler::removeFunction() +{ + if ( !m_xFunction.is() ) + return; + + const OUString sQuotedFunctionName(lcl_getQuotedFunctionName(m_xFunction)); + ::std::pair<TFunctions::iterator,TFunctions::iterator> aFind = m_aFunctionNames.equal_range(sQuotedFunctionName); + while ( aFind.first != aFind.second ) + { + if ( aFind.first->second.first == m_xFunction ) + { + uno::Reference< report::XFunctions> xFunctions = aFind.first->second.second->getFunctions(); + xFunctions->removeByIndex(xFunctions->getCount() - 1 ); /// TODO: insert new method in XFunctions: removeFunction(xfunction) + m_aFunctionNames.erase(aFind.first); + m_bNewFunction = false; + break; + } + ++(aFind.first); + } +} + +void GeometryHandler::resetOwnProperties(::osl::ResettableMutexGuard& _aGuard,const OUString& _sOldFunctionName,const OUString& _sOldScope,const sal_uInt32 _nOldDataFieldType) +{ + const OUString sNewFunction = m_sDefaultFunction; + const OUString sNewScope = m_sScope; + const sal_uInt32 nNewDataFieldType = m_nDataFieldType; + _aGuard.clear(); + if ( _nOldDataFieldType != nNewDataFieldType ) + { + beans::PropertyChangeEvent aScopeEvent; + aScopeEvent.PropertyName = PROPERTY_TYPE; + aScopeEvent.OldValue <<= _nOldDataFieldType; + aScopeEvent.NewValue <<= nNewDataFieldType; + m_aPropertyListeners.notify( aScopeEvent, &beans::XPropertyChangeListener::propertyChange ); + } + if ( _sOldFunctionName != sNewFunction ) + { + beans::PropertyChangeEvent aFormulaEvent; + aFormulaEvent.PropertyName = PROPERTY_FORMULALIST; + aFormulaEvent.OldValue <<= _sOldFunctionName; + aFormulaEvent.NewValue <<= sNewFunction; + + m_aPropertyListeners.notify( aFormulaEvent, &beans::XPropertyChangeListener::propertyChange ); + } + if ( _sOldScope != sNewScope ) + { + beans::PropertyChangeEvent aScopeEvent; + aScopeEvent.PropertyName = PROPERTY_SCOPE; + aScopeEvent.OldValue <<= _sOldScope; + aScopeEvent.NewValue <<= sNewScope; + m_aPropertyListeners.notify( aScopeEvent, &beans::XPropertyChangeListener::propertyChange ); + } + + _aGuard.reset(); +} + +void GeometryHandler::impl_initFieldList_nothrow( uno::Sequence< OUString >& _rFieldNames ) const +{ + _rFieldNames.realloc(0); + try + { + uno::Reference< awt::XWindow> xInspectorWindow(m_xContext->getValueByName("DialogParentWindow") ,uno::UNO_QUERY); + weld::WaitObject aWaitCursor(Application::GetFrameWeld(xInspectorWindow)); + + // get the form of the control we're inspecting + uno::Reference< beans::XPropertySet > xFormSet( m_xRowSet, uno::UNO_QUERY ); + if ( !xFormSet.is() ) + return; + + OUString sObjectName; + OSL_VERIFY( xFormSet->getPropertyValue( PROPERTY_COMMAND ) >>= sObjectName ); + // when there is no command we don't need to ask for columns + uno::Reference<sdbc::XConnection> xCon(m_xContext->getValueByName("ActiveConnection") ,uno::UNO_QUERY); + if ( !sObjectName.isEmpty() && xCon.is() ) + { + sal_Int32 nObjectType = sdb::CommandType::COMMAND; + OSL_VERIFY( xFormSet->getPropertyValue( PROPERTY_COMMANDTYPE ) >>= nObjectType ); + + _rFieldNames = ::dbtools::getFieldNamesByCommandDescriptor( xCon, nObjectType, sObjectName ); + } + } + catch (uno::Exception&) + { + TOOLS_WARN_EXCEPTION( "reportdesign", "GeometryHandler::impl_initFieldList_nothrow" ); + } +} + +bool GeometryHandler::impl_isCounterFunction_throw(const OUString& _sQuotedFunctionName,OUString& Out_sScope) const +{ + ::std::pair<TFunctions::const_iterator,TFunctions::const_iterator> aFind = m_aFunctionNames.equal_range(_sQuotedFunctionName); + while ( aFind.first != aFind.second ) + { + const beans::Optional< OUString> aInitalFormula = aFind.first->second.first->getInitialFormula(); + if ( aInitalFormula.IsPresent ) + { + const OUString sFormula( aFind.first->second.first->getFormula() ); + i18nutil::SearchOptions2 aSearchOptions; + aSearchOptions.AlgorithmType2 = util::SearchAlgorithms2::REGEXP; + aSearchOptions.searchFlag = 0x00000100; + aSearchOptions.searchString = m_aCounterFunction.m_sSearchString; + utl::TextSearch aTextSearch( aSearchOptions); + sal_Int32 start = 0; + sal_Int32 end = sFormula.getLength(); + if ( aTextSearch.SearchForward(sFormula,&start,&end) && start == 0 && end == sFormula.getLength()) // counter function found + { + const uno::Reference< report::XGroup > xGroup(aFind.first->second.second,uno::UNO_QUERY); + if ( xGroup.is() ) + { + OUString sGroupName = RptResId(RID_STR_SCOPE_GROUP); + Out_sScope = sGroupName.replaceFirst("%1",xGroup->getExpression()); + } + else + Out_sScope = uno::Reference< report::XReportDefinition >(aFind.first->second.second,uno::UNO_QUERY_THROW)->getName(); + break; + } + } + ++(aFind.first); + } + return aFind.first != aFind.second; +} + +void GeometryHandler::impl_createFunction(const OUString& _sFunctionName,const OUString& _sDataField,const DefaultFunction& _aFunction) +{ + if ( m_bNewFunction ) + removeFunction(); + + const OUString sQuotedFunctionName(lcl_getQuotedFunctionName(_sFunctionName)); + m_xFunction.set(report::Function::create(m_xContext)); + m_xFunction->setName( _sFunctionName ); + + const OUString sPlaceHolder1("%Column"); + const OUString sPlaceHolder2("%FunctionName"); + OUString sFormula(_aFunction.m_sFormula); + sFormula = sFormula.replaceAll(sPlaceHolder1,_sDataField); + sFormula = sFormula.replaceAll(sPlaceHolder2,_sFunctionName); + + m_xFunction->setFormula(sFormula); + m_xFunction->setPreEvaluated(_aFunction.m_bPreEvaluated); + m_xFunction->setDeepTraversing(false); + if ( _aFunction.m_sInitialFormula.IsPresent ) + { + beans::Optional< OUString> aInitialFormula = _aFunction.m_sInitialFormula; + OUString sInitialFormula = aInitialFormula.Value; + sInitialFormula = sInitialFormula.replaceAll(sPlaceHolder1,_sDataField); + sInitialFormula = sInitialFormula.replaceAll(sPlaceHolder2,_sFunctionName); + aInitialFormula.Value = sInitialFormula; + m_xFunction->setInitialFormula( aInitialFormula ); + } + OUString sNamePostfix; + const uno::Reference< report::XFunctionsSupplier> xFunctionsSupplier = fillScope_throw(sNamePostfix); + const uno::Reference< container::XIndexContainer> xFunctions(xFunctionsSupplier->getFunctions(),uno::UNO_QUERY_THROW); + xFunctions->insertByIndex(xFunctions->getCount(),uno::makeAny(m_xFunction)); + m_aFunctionNames.emplace(sQuotedFunctionName,TFunctionPair(m_xFunction,xFunctionsSupplier)); + m_bNewFunction = true; +} + +void GeometryHandler::impl_setCounterFunction_throw() +{ + OUString sNamePostfix; + fillScope_throw(sNamePostfix); + OUString sFunctionName = m_aCounterFunction.m_sName + sNamePostfix; + const OUString sQuotedFunctionName = lcl_getQuotedFunctionName(sFunctionName); + OUString sScope; + if ( !(!sFunctionName.isEmpty() && m_aFunctionNames.find(sQuotedFunctionName) != m_aFunctionNames.end() && impl_isCounterFunction_throw(sQuotedFunctionName,sScope)) ) + impl_createFunction(sFunctionName,OUString(),m_aCounterFunction); + + OBlocker aBlocker(m_bIn); + m_xReportComponent->setPropertyValue(PROPERTY_DATAFIELD,uno::makeAny(impl_convertToFormula( uno::makeAny(sQuotedFunctionName)))); +} + +sal_uInt32 GeometryHandler::impl_getDataFieldType_throw(const OUString& _sDataField) const +{ + sal_uInt32 nDataFieldType = UNDEF_DATA; + OUString sDataField; + if ( !_sDataField.isEmpty() ) + sDataField = _sDataField; + else + { + uno::Any aDataField( m_xReportComponent->getPropertyValue( PROPERTY_DATAFIELD ) ); + lcl_convertFormulaTo(aDataField,aDataField); + aDataField >>= sDataField; + } + + if ( !sDataField.isEmpty() ) + { + if ( impl_isDataField(sDataField) ) + nDataFieldType = DATA_OR_FORMULA; + else if ( isDefaultFunction(sDataField,sDataField) ) + nDataFieldType = FUNCTION; + else if ( m_aFunctionNames.find(sDataField) != m_aFunctionNames.end() ) + { + nDataFieldType = USER_DEF_FUNCTION; + OUString sScope; + if ( impl_isCounterFunction_throw(sDataField,sScope) ) + nDataFieldType = COUNTER; + } + else + nDataFieldType = DATA_OR_FORMULA; + } + return nDataFieldType; +} + +// XEventListener +void SAL_CALL GeometryHandler::disposing(const lang::EventObject& ) +{ +} +// XPropertyChangeListener +void SAL_CALL GeometryHandler::propertyChange(const beans::PropertyChangeEvent& /*evt*/) +{ + ::osl::ResettableMutexGuard aGuard( m_aMutex ); + if ( m_bIn ) + return; + + const sal_uInt32 nOldDataFieldType = m_nDataFieldType; + const OUString sOldFunctionName = m_sDefaultFunction; + const OUString sOldScope = m_sScope; + m_sDefaultFunction.clear(); + m_sScope.clear(); + m_nDataFieldType = impl_getDataFieldType_throw(); + if ( UNDEF_DATA == m_nDataFieldType ) + m_nDataFieldType = nOldDataFieldType; + uno::Any aDataField = m_xReportComponent->getPropertyValue( PROPERTY_DATAFIELD ); + lcl_convertFormulaTo(aDataField,aDataField); + OUString sDataField; + aDataField >>= sDataField; + switch(m_nDataFieldType) + { + case FUNCTION: + isDefaultFunction(sDataField,sDataField,uno::Reference< report::XFunctionsSupplier>(),true); + break; + case COUNTER: + impl_isCounterFunction_throw(sDataField,m_sScope); + break; + default: + ; + } + + resetOwnProperties(aGuard,sOldFunctionName,sOldScope,nOldDataFieldType); +} + +} // namespace rptui + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/reportdesign/source/ui/inspection/ReportComponentHandler.cxx b/reportdesign/source/ui/inspection/ReportComponentHandler.cxx new file mode 100644 index 000000000..ece8e8d23 --- /dev/null +++ b/reportdesign/source/ui/inspection/ReportComponentHandler.cxx @@ -0,0 +1,206 @@ +/* -*- 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 <ReportComponentHandler.hxx> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/lang/NullPointerException.hpp> +#include <comphelper/types.hxx> +#include <cppuhelper/supportsservice.hxx> +#include <com/sun/star/form/inspection/FormComponentPropertyHandler.hpp> +#include <com/sun/star/container/XNameContainer.hpp> +#include <metadata.hxx> + + +namespace rptui +{ + +using namespace ::com::sun::star; + +ReportComponentHandler::ReportComponentHandler(uno::Reference< uno::XComponentContext > const & context) + :ReportComponentHandler_Base(m_aMutex) + ,m_xContext(context) +{ + try + { + m_xFormComponentHandler = form::inspection::FormComponentPropertyHandler::create(m_xContext); + + }catch(const uno::Exception &) + { + } +} + +OUString SAL_CALL ReportComponentHandler::getImplementationName( ) +{ + return getImplementationName_Static(); +} + +sal_Bool SAL_CALL ReportComponentHandler::supportsService( const OUString& ServiceName ) +{ + return cppu::supportsService(this, ServiceName); +} + +uno::Sequence< OUString > SAL_CALL ReportComponentHandler::getSupportedServiceNames( ) +{ + return getSupportedServiceNames_static(); +} + +OUString ReportComponentHandler::getImplementationName_Static( ) +{ + return "com.sun.star.comp.report.ReportComponentHandler"; +} + +uno::Sequence< OUString > ReportComponentHandler::getSupportedServiceNames_static( ) +{ + uno::Sequence< OUString > aSupported { "com.sun.star.report.inspection.ReportComponentHandler" }; + return aSupported; +} + +uno::Reference< uno::XInterface > ReportComponentHandler::create( const uno::Reference< uno::XComponentContext >& _rxContext ) +{ + return *(new ReportComponentHandler( _rxContext )); +} +// override WeakComponentImplHelperBase::disposing() +// This function is called upon disposing the component, +// if your component needs special work when it becomes +// disposed, do it here. +void SAL_CALL ReportComponentHandler::disposing() +{ + ::comphelper::disposeComponent(m_xFormComponentHandler); +} +void SAL_CALL ReportComponentHandler::addEventListener(const uno::Reference< lang::XEventListener > & xListener) +{ + m_xFormComponentHandler->addEventListener(xListener); +} + +void SAL_CALL ReportComponentHandler::removeEventListener(const uno::Reference< lang::XEventListener > & aListener) +{ + m_xFormComponentHandler->removeEventListener(aListener); +} + +// inspection::XPropertyHandler: + +/********************************************************************************/ +void SAL_CALL ReportComponentHandler::inspect(const uno::Reference< uno::XInterface > & Component) +{ + try + { + uno::Reference< container::XNameContainer > xNameCont(Component,uno::UNO_QUERY); + const OUString sFormComponent("FormComponent"); + if ( xNameCont->hasByName(sFormComponent) ) + xNameCont->getByName(sFormComponent) >>= m_xFormComponent; + const OUString sRowSet("RowSet"); + if ( xNameCont->hasByName(sRowSet) ) + { + uno::Reference<beans::XPropertySet> xProp(m_xFormComponentHandler,uno::UNO_QUERY); + xProp->setPropertyValue(sRowSet,xNameCont->getByName(sRowSet)); + } + } + catch(const uno::Exception &) + { + throw lang::NullPointerException(); + } + if ( m_xFormComponent.is() ) + { + m_xFormComponentHandler->inspect(m_xFormComponent); + } +} + +uno::Any SAL_CALL ReportComponentHandler::getPropertyValue(const OUString & PropertyName) +{ + return m_xFormComponentHandler->getPropertyValue(PropertyName); +} + +void SAL_CALL ReportComponentHandler::setPropertyValue(const OUString & PropertyName, const uno::Any & Value) +{ + m_xFormComponentHandler->setPropertyValue(PropertyName, Value); +} + +beans::PropertyState SAL_CALL ReportComponentHandler::getPropertyState(const OUString & PropertyName) +{ + return m_xFormComponentHandler->getPropertyState(PropertyName); +} + +inspection::LineDescriptor SAL_CALL ReportComponentHandler::describePropertyLine(const OUString & PropertyName, const uno::Reference< inspection::XPropertyControlFactory > & ControlFactory) +{ + return m_xFormComponentHandler->describePropertyLine(PropertyName, ControlFactory); +} + +uno::Any SAL_CALL ReportComponentHandler::convertToPropertyValue(const OUString & PropertyName, const uno::Any & ControlValue) +{ + return m_xFormComponentHandler->convertToPropertyValue(PropertyName, ControlValue); +} + +uno::Any SAL_CALL ReportComponentHandler::convertToControlValue(const OUString & PropertyName, const uno::Any & PropertyValue, const uno::Type & ControlValueType) +{ + return m_xFormComponentHandler->convertToControlValue(PropertyName, PropertyValue, ControlValueType); +} + +void SAL_CALL ReportComponentHandler::addPropertyChangeListener(const uno::Reference< beans::XPropertyChangeListener > & Listener) +{ + m_xFormComponentHandler->addPropertyChangeListener(Listener); +} + +void SAL_CALL ReportComponentHandler::removePropertyChangeListener(const uno::Reference< beans::XPropertyChangeListener > & _rxListener) +{ + m_xFormComponentHandler->removePropertyChangeListener(_rxListener); +} + +uno::Sequence< beans::Property > SAL_CALL ReportComponentHandler::getSupportedProperties() +{ + ::std::vector< beans::Property > aNewProps; + rptui::OPropertyInfoService::getExcludeProperties( aNewProps, m_xFormComponentHandler ); + + return uno::Sequence< beans::Property >(aNewProps.data(), aNewProps.size()); +} + +uno::Sequence< OUString > SAL_CALL ReportComponentHandler::getSupersededProperties() +{ + uno::Sequence< OUString > aRet; + return aRet; +} + +uno::Sequence< OUString > SAL_CALL ReportComponentHandler::getActuatingProperties() +{ + return m_xFormComponentHandler->getActuatingProperties(); +} + +sal_Bool SAL_CALL ReportComponentHandler::isComposable( const OUString& _rPropertyName ) +{ + return OPropertyInfoService::isComposable( _rPropertyName, m_xFormComponentHandler ); +} + +inspection::InteractiveSelectionResult SAL_CALL ReportComponentHandler::onInteractivePropertySelection(const OUString & PropertyName, sal_Bool Primary, uno::Any & out_Data, const uno::Reference< inspection::XObjectInspectorUI > & InspectorUI) +{ + return m_xFormComponentHandler->onInteractivePropertySelection(PropertyName, Primary, out_Data, InspectorUI); +} + +void SAL_CALL ReportComponentHandler::actuatingPropertyChanged(const OUString & ActuatingPropertyName, const uno::Any & NewValue, const uno::Any & OldValue, const uno::Reference< inspection::XObjectInspectorUI > & InspectorUI, sal_Bool FirstTimeInit) +{ + m_xFormComponentHandler->actuatingPropertyChanged(ActuatingPropertyName, NewValue, OldValue, InspectorUI, FirstTimeInit); +} + +sal_Bool SAL_CALL ReportComponentHandler::suspend(sal_Bool Suspend) +{ + return m_xFormComponentHandler->suspend(Suspend); +} + + +} // namespace rptui + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/reportdesign/source/ui/inspection/metadata.cxx b/reportdesign/source/ui/inspection/metadata.cxx new file mode 100644 index 000000000..f652fa4a4 --- /dev/null +++ b/reportdesign/source/ui/inspection/metadata.cxx @@ -0,0 +1,305 @@ +/* -*- 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 <metadata.hxx> +#include <com/sun/star/inspection/XPropertyHandler.hpp> +#include <core_resource.hxx> +#include <helpids.h> +#include <strings.hrc> +#include <strings.hxx> + +#include <algorithm> + + +namespace rptui +{ + + + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star; + + + //= OPropertyInfoImpl + + struct OPropertyInfoImpl + { + OUString sName; + OUString sTranslation; + OString sHelpId; + sal_Int32 nId; + PropUIFlags nUIFlags; + + OPropertyInfoImpl( + const OUString& rName, + sal_Int32 _nId, + const OUString& aTranslation, + const OString& _sHelpId, + PropUIFlags _nUIFlags); + }; + + + OPropertyInfoImpl::OPropertyInfoImpl(const OUString& _rName, sal_Int32 _nId, + const OUString& aString, const OString& sHid, PropUIFlags _nUIFlags) + :sName(_rName) + ,sTranslation(aString) + ,sHelpId(sHid) + ,nId(_nId) + ,nUIFlags(_nUIFlags) + { + } + + namespace { + + // compare PropertyInfo + struct PropertyInfoLessByName + { + bool operator()( const OPropertyInfoImpl& _lhs, const OPropertyInfoImpl& _rhs ) + { + return _lhs.sName < _rhs.sName; + } + }; + + } + + //= OPropertyInfoService + +#define DEF_INFO( ident, uinameres, helpid, flags ) \ + OPropertyInfoImpl( PROPERTY_##ident, PROPERTY_ID_##ident, \ + RptResId( RID_STR_##uinameres ), HID_RPT_PROP_##helpid, flags ) + +#define DEF_INFO_1( ident, uinameres, helpid, flag1 ) \ + DEF_INFO( ident, uinameres, helpid, PropUIFlags::flag1 ) + +#define DEF_INFO_2( ident, uinameres, helpid, flag1, flag2 ) \ + DEF_INFO( ident, uinameres, helpid, PropUIFlags::flag1 | PropUIFlags::flag2 ) + + sal_uInt16 OPropertyInfoService::s_nCount = 0; + OPropertyInfoImpl* OPropertyInfoService::s_pPropertyInfos = nullptr; + + const OPropertyInfoImpl* OPropertyInfoService::getPropertyInfo() + { + if ( s_pPropertyInfos ) + return s_pPropertyInfos; + + static OPropertyInfoImpl aPropertyInfos[] = + { + /* + DEF_INFO_?( propname and id, resource id, help id, flags ), + */ + DEF_INFO_1( FORCENEWPAGE, FORCENEWPAGE, FORCENEWPAGE, Composeable ) + ,DEF_INFO_1( NEWROWORCOL, NEWROWORCOL, NEWROWORCOL, Composeable ) + ,DEF_INFO_1( KEEPTOGETHER, KEEPTOGETHER, KEEPTOGETHER, Composeable ) + ,DEF_INFO_1( CANGROW, CANGROW, CANGROW, Composeable ) + ,DEF_INFO_1( CANSHRINK, CANSHRINK, CANSHRINK, Composeable ) + ,DEF_INFO_1( REPEATSECTION, REPEATSECTION, REPEATSECTION, Composeable ) + ,DEF_INFO_1( PRINTREPEATEDVALUES, PRINTREPEATEDVALUES, PRINTREPEATEDVALUES, Composeable ) + ,DEF_INFO_1( CONDITIONALPRINTEXPRESSION, CONDITIONALPRINTEXPRESSION, CONDITIONALPRINTEXPRESSION, Composeable ) + ,DEF_INFO_1( STARTNEWCOLUMN, STARTNEWCOLUMN, STARTNEWCOLUMN, Composeable ) + ,DEF_INFO_1( RESETPAGENUMBER, RESETPAGENUMBER, RESETPAGENUMBER, Composeable ) + ,DEF_INFO_1( PRINTWHENGROUPCHANGE, PRINTWHENGROUPCHANGE, PRINTWHENGROUPCHANGE, Composeable ) + ,DEF_INFO_1( VISIBLE, VISIBLE, VISIBLE, Composeable ) + ,DEF_INFO_1( GROUPKEEPTOGETHER, GROUPKEEPTOGETHER, GROUPKEEPTOGETHER, Composeable ) + ,DEF_INFO_1( PAGEHEADEROPTION, PAGEHEADEROPTION, PAGEHEADEROPTION, Composeable ) + ,DEF_INFO_1( PAGEFOOTEROPTION, PAGEFOOTEROPTION, PAGEFOOTEROPTION, Composeable ) + ,DEF_INFO_1( POSITIONX, POSITIONX, RPT_POSITIONX, Composeable ) + ,DEF_INFO_1( POSITIONY, POSITIONY, RPT_POSITIONY, Composeable ) + ,DEF_INFO_1( WIDTH, WIDTH, RPT_WIDTH, Composeable ) + ,DEF_INFO_1( HEIGHT, HEIGHT, RPT_HEIGHT, Composeable ) + ,DEF_INFO_1( AUTOGROW, AUTOGROW, RPT_AUTOGROW, Composeable ) + ,DEF_INFO_1( FONT, FONT, RPT_FONT, Composeable ) + ,DEF_INFO_1( PREEVALUATED, PREEVALUATED, PREEVALUATED, Composeable ) + ,DEF_INFO_1( DEEPTRAVERSING, DEEPTRAVERSING, DEEPTRAVERSING, Composeable ) + ,DEF_INFO_1( FORMULA, FORMULA, FORMULA, Composeable ) + ,DEF_INFO_1( INITIALFORMULA, INITIALFORMULA, INITIALFORMULA, Composeable ) + ,DEF_INFO_2( TYPE, TYPE, TYPE, Composeable,DataProperty ) + ,DEF_INFO_2( DATAFIELD, DATAFIELD, DATAFIELD, Composeable,DataProperty ) + ,DEF_INFO_2( FORMULALIST, FORMULALIST, FORMULALIST, Composeable,DataProperty ) + ,DEF_INFO_2( SCOPE, SCOPE, SCOPE, Composeable,DataProperty ) + ,DEF_INFO_1( PRESERVEIRI, PRESERVEIRI, PRESERVEIRI, Composeable ) + ,DEF_INFO_1( BACKCOLOR, BACKCOLOR, BACKCOLOR, Composeable ) + ,DEF_INFO_1( CONTROLBACKGROUND, BACKCOLOR, BACKCOLOR, Composeable ) + ,DEF_INFO_1( BACKTRANSPARENT, BACKTRANSPARENT, BACKTRANSPARENT, Composeable ) + ,DEF_INFO_1( CONTROLBACKGROUNDTRANSPARENT, CONTROLBACKGROUNDTRANSPARENT, + CONTROLBACKGROUNDTRANSPARENT, Composeable ) + ,DEF_INFO_1( CHARTTYPE, CHARTTYPE, CHARTTYPE, Composeable ) + ,DEF_INFO_1( PREVIEW_COUNT, PREVIEW_COUNT, PREVIEW_COUNT, Composeable ) + ,DEF_INFO_2( MASTERFIELDS, MASTERFIELDS, MASTERFIELDS, Composeable,DataProperty ) + ,DEF_INFO_2( DETAILFIELDS, DETAILFIELDS, DETAILFIELDS, Composeable,DataProperty) + ,DEF_INFO_1( AREA, AREA, AREA, Composeable ) + ,DEF_INFO_2( MIMETYPE, MIMETYPE, MIMETYPE, Composeable,DataProperty ) + ,DEF_INFO_1( PARAADJUST, PARAADJUST, PARAADJUST, Composeable ) + ,DEF_INFO_1( VERTICALALIGN, VERTICALALIGN, VERTICALALIGN, Composeable ) + }; + + s_pPropertyInfos = aPropertyInfos; + s_nCount = SAL_N_ELEMENTS(aPropertyInfos); + ::std::sort( aPropertyInfos, aPropertyInfos + SAL_N_ELEMENTS(aPropertyInfos), PropertyInfoLessByName() ); + + return s_pPropertyInfos; + } + + + sal_Int32 OPropertyInfoService::getPropertyId(const OUString& _rName) + { + const OPropertyInfoImpl* pInfo = getPropertyInfo(_rName); + return pInfo ? pInfo->nId : -1; + } + + + OUString OPropertyInfoService::getPropertyTranslation(sal_Int32 _nId) + { + const OPropertyInfoImpl* pInfo = getPropertyInfo(_nId); + return pInfo ? pInfo->sTranslation : OUString(); + } + + + OString OPropertyInfoService::getPropertyHelpId(sal_Int32 _nId) + { + const OPropertyInfoImpl* pInfo = getPropertyInfo(_nId); + return pInfo ? pInfo->sHelpId : OString(); + } + + + PropUIFlags OPropertyInfoService::getPropertyUIFlags(sal_Int32 _nId) + { + const OPropertyInfoImpl* pInfo = getPropertyInfo(_nId); + return pInfo ? pInfo->nUIFlags : PropUIFlags::NONE; + } + + + const OPropertyInfoImpl* OPropertyInfoService::getPropertyInfo(const OUString& _rName) + { + // initialization + if(!s_pPropertyInfos) + getPropertyInfo(); + OPropertyInfoImpl aSearch(_rName, 0, OUString(), "", PropUIFlags::NONE); + + const OPropertyInfoImpl* pPropInfo = ::std::lower_bound( + s_pPropertyInfos, s_pPropertyInfos + s_nCount, aSearch, PropertyInfoLessByName() ); + + if ( ( pPropInfo < s_pPropertyInfos + s_nCount ) && pPropInfo->sName == _rName ) + return pPropInfo; + + return nullptr; + } + + + const OPropertyInfoImpl* OPropertyInfoService::getPropertyInfo(sal_Int32 _nId) + { + // initialization + if(!s_pPropertyInfos) + getPropertyInfo(); + + // TODO: a real structure which allows quick access by name as well as by id + for (sal_uInt16 i = 0; i < s_nCount; i++) + if (s_pPropertyInfos[i].nId == _nId) + return &s_pPropertyInfos[i]; + + return nullptr; + } + + + bool OPropertyInfoService::isComposable( const OUString& _rPropertyName, const css::uno::Reference< css::inspection::XPropertyHandler >& _rxFormComponentHandler ) + { + sal_Int32 nId = getPropertyId( _rPropertyName ); + if ( nId != -1 ) + { + PropUIFlags nFlags = getPropertyUIFlags( nId ); + return bool( nFlags & PropUIFlags::Composeable ); + } + + return _rxFormComponentHandler->isComposable( _rPropertyName ); + } + + + void OPropertyInfoService::getExcludeProperties(::std::vector< beans::Property >& _rExcludeProperties,const css::uno::Reference< css::inspection::XPropertyHandler >& _xFormComponentHandler) + { + const uno::Sequence< beans::Property > aProps = _xFormComponentHandler->getSupportedProperties(); + static const OUStringLiteral pExcludeProperties[] = + { + "Enabled", + "Printable", + "WordBreak", + "MultiLine", + "Tag", + "HelpText", + "HelpURL", + "MaxTextLen", + "ReadOnly", + "Tabstop", + "TabIndex", + "ValueMin", + "ValueMax", + "Spin", + "SpinValue", + "SpinValueMin", + "SpinValueMax", + "DefaultSpinValue", + "SpinIncrement", + "Repeat", + "RepeatDelay", + "ControlLabel", /// TODO: has to be checked + "LabelControl", + "Title", // comment this out if you want to have title feature for charts + PROPERTY_MAXTEXTLEN, + PROPERTY_EFFECTIVEDEFAULT, + PROPERTY_EFFECTIVEMAX, + PROPERTY_EFFECTIVEMIN, + "HideInactiveSelection", + "SubmitAction", + "InputRequired", + "VerticalAlign", + PROPERTY_ALIGN, + PROPERTY_EMPTY_IS_NULL, + PROPERTY_FILTERPROPOSAL + ,PROPERTY_POSITIONX + ,PROPERTY_POSITIONY + ,PROPERTY_WIDTH + ,PROPERTY_HEIGHT + ,PROPERTY_AUTOGROW + ,PROPERTY_FONT + ,PROPERTY_LABEL + ,PROPERTY_LINECOLOR + ,PROPERTY_BORDER + ,PROPERTY_BORDERCOLOR + ,PROPERTY_BACKTRANSPARENT + ,PROPERTY_CONTROLBACKGROUND + ,PROPERTY_BACKGROUNDCOLOR + ,PROPERTY_CONTROLBACKGROUNDTRANSPARENT + ,PROPERTY_FORMULALIST + ,PROPERTY_SCOPE + ,PROPERTY_TYPE + ,PROPERTY_DATASOURCENAME + ,PROPERTY_VERTICALALIGN + }; + + for (beans::Property const & prop : aProps) + { + size_t nPos = 0; + for (; nPos < SAL_N_ELEMENTS(pExcludeProperties) && pExcludeProperties[nPos] != prop.Name; ++nPos ) + ; + if ( nPos == SAL_N_ELEMENTS(pExcludeProperties) ) + _rExcludeProperties.push_back(prop); + } + } + + +} // namespace pcr + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/reportdesign/source/ui/misc/ColorListener.cxx b/reportdesign/source/ui/misc/ColorListener.cxx new file mode 100644 index 000000000..48fa67902 --- /dev/null +++ b/reportdesign/source/ui/misc/ColorListener.cxx @@ -0,0 +1,96 @@ +/* -*- 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 <ColorListener.hxx> +#include <svl/hint.hxx> +#include <vcl/settings.hxx> +#include <vcl/event.hxx> + +#include <strings.hxx> + + +namespace rptui +{ + +OColorListener::OColorListener(vcl::Window* _pParent ,const OUString& _sColorEntry) +: Window(_pParent) +,m_sColorEntry(_sColorEntry) +,m_nColor(COL_LIGHTBLUE) +,m_bCollapsed(false) +,m_bMarked(false) +{ + StartListening(m_aExtendedColorConfig); + m_nColor = m_aExtendedColorConfig.GetColorValue(CFG_REPORTDESIGNER,m_sColorEntry).getColor(); + m_nTextBoundaries = m_aColorConfig.GetColorValue(::svtools::DOCBOUNDARIES).nColor; +} + +OColorListener::~OColorListener() +{ + disposeOnce(); +} + +void OColorListener::dispose() +{ + EndListening(m_aExtendedColorConfig); + vcl::Window::dispose(); +} + +void OColorListener::Notify(SfxBroadcaster & /*rBc*/, SfxHint const & rHint) +{ + if (rHint.GetId() == SfxHintId::ColorsChanged) + { + m_nColor = m_aExtendedColorConfig.GetColorValue(CFG_REPORTDESIGNER,m_sColorEntry).getColor(); + m_nTextBoundaries = m_aColorConfig.GetColorValue(::svtools::DOCBOUNDARIES).nColor; + Invalidate(InvalidateFlags::NoChildren|InvalidateFlags::NoErase); + } +} + +void OColorListener::DataChanged( const DataChangedEvent& rDCEvt ) +{ + Window::DataChanged( rDCEvt ); + + if ( (rDCEvt.GetType() == DataChangedEventType::SETTINGS) && + (rDCEvt.GetFlags() & AllSettingsFlags::STYLE) ) + { + ImplInitSettings(); + Invalidate(); + } +} + +void OColorListener::setCollapsed(bool _bCollapsed) +{ + if ( m_bCollapsed != _bCollapsed ) + { + m_bCollapsed = _bCollapsed; + m_aCollapsedLink.Call(*this); + } +} + +void OColorListener::setMarked(bool _bMark) +{ + if ( m_bMarked != _bMark) + { + m_bMarked = _bMark; + Invalidate(InvalidateFlags::NoChildren|InvalidateFlags::NoErase); + } +} + +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/reportdesign/source/ui/misc/FunctionHelper.cxx b/reportdesign/source/ui/misc/FunctionHelper.cxx new file mode 100644 index 000000000..c9cfbbd4b --- /dev/null +++ b/reportdesign/source/ui/misc/FunctionHelper.cxx @@ -0,0 +1,268 @@ +/* -*- 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 <FunctionHelper.hxx> + +#include <o3tl/safeint.hxx> +#include <osl/diagnose.h> +#include <formula/funcvarargs.h> + + +namespace rptui +{ + + using namespace ::com::sun::star; + +FunctionManager::FunctionManager(const uno::Reference< report::meta::XFunctionManager>& _xMgr) +: m_xMgr(_xMgr) +{ +} +FunctionManager::~FunctionManager() +{ +} +sal_Unicode FunctionManager::getSingleToken(const formula::IFunctionManager::EToken _eToken) const +{ + switch(_eToken) + { + case eOk: + return '('; + case eClose: + return ')'; + case eSep: + return ';'; + case eArrayOpen: + return '{'; + case eArrayClose: + return '}'; + } + return 0; +} + +sal_uInt32 FunctionManager::getCount() const +{ + return m_xMgr->getCount(); +} + +const formula::IFunctionCategory* FunctionManager::getCategory(sal_uInt32 _nPos) const +{ + if ( _nPos >= m_aCategoryIndex.size() ) + { + uno::Reference< report::meta::XFunctionCategory> xCategory = m_xMgr->getCategory(_nPos); + auto pCategory = std::make_shared<FunctionCategory>(this,_nPos + 1,xCategory); + m_aCategoryIndex.push_back( m_aCategories.emplace(xCategory->getName(),pCategory).first ); + } + return m_aCategoryIndex[_nPos]->second.get(); +} + +void FunctionManager::fillLastRecentlyUsedFunctions(::std::vector< const formula::IFunctionDescription*>& /*_rLastRUFunctions*/) const +{ +} + +std::shared_ptr< FunctionDescription > FunctionManager::get(const uno::Reference< report::meta::XFunctionDescription>& _xFunctionDescription) const +{ + std::shared_ptr< FunctionDescription > pDesc; + if ( _xFunctionDescription.is() ) + { + const OUString sFunctionName = _xFunctionDescription->getName(); + TFunctionsMap::const_iterator aFunctionFind = m_aFunctions.find(sFunctionName); + if ( aFunctionFind == m_aFunctions.end() ) + { + const uno::Reference< report::meta::XFunctionCategory> xCategory = _xFunctionDescription->getCategory(); + const OUString sCategoryName = xCategory->getName(); + TCategoriesMap::iterator aCategoryFind = m_aCategories.find(sCategoryName); + if ( aCategoryFind == m_aCategories.end() ) + { + aCategoryFind = m_aCategories.emplace(sCategoryName,std::make_shared< FunctionCategory > (this,xCategory->getNumber() + 1,xCategory)).first; + m_aCategoryIndex.push_back( aCategoryFind ); + } + aFunctionFind = m_aFunctions.emplace(sFunctionName,std::make_shared<FunctionDescription>(aCategoryFind->second.get(),_xFunctionDescription)).first; + } + pDesc = aFunctionFind->second; + } + return pDesc; +} + +FunctionCategory::FunctionCategory(const FunctionManager* _pFMgr,sal_uInt32 _nPos,const uno::Reference< report::meta::XFunctionCategory>& _xCategory) +: m_xCategory(_xCategory) +,m_nFunctionCount(_xCategory->getCount()) +, m_nNumber(_nPos) +,m_pFunctionManager(_pFMgr) +{ +} + +sal_uInt32 FunctionCategory::getCount() const +{ + return m_nFunctionCount; +} + +const formula::IFunctionDescription* FunctionCategory::getFunction(sal_uInt32 _nPos) const +{ + if ( _nPos >= m_aFunctions.size() && _nPos < m_nFunctionCount ) + { + uno::Reference< report::meta::XFunctionDescription> xFunctionDescription = m_xCategory->getFunction(_nPos); + std::shared_ptr< FunctionDescription > pFunction = m_pFunctionManager->get(xFunctionDescription); + m_aFunctions.push_back( pFunction ); + } + return m_aFunctions[_nPos].get(); +} + +sal_uInt32 FunctionCategory::getNumber() const +{ + return m_nNumber; +} + +OUString FunctionCategory::getName() const +{ + return m_xCategory->getName(); +} + +FunctionDescription::FunctionDescription(const formula::IFunctionCategory* _pFunctionCategory,const uno::Reference< report::meta::XFunctionDescription>& _xFunctionDescription) +: m_xFunctionDescription(_xFunctionDescription) +, m_pFunctionCategory(_pFunctionCategory) +{ + m_aParameter = m_xFunctionDescription->getArguments(); +} +OUString FunctionDescription::getFunctionName() const +{ + return m_xFunctionDescription->getName(); +} + +const formula::IFunctionCategory* FunctionDescription::getCategory() const +{ + return m_pFunctionCategory; +} + +OUString FunctionDescription::getDescription() const +{ + return m_xFunctionDescription->getDescription(); +} + +sal_Int32 FunctionDescription::getSuppressedArgumentCount() const +{ + return m_aParameter.getLength(); +} + +OUString FunctionDescription::getFormula(const ::std::vector< OUString >& _aArguments) const +{ + OUString sFormula; + try + { + sFormula = m_xFunctionDescription->createFormula(uno::Sequence< OUString >(_aArguments.data(), _aArguments.size())); + } + catch(const uno::Exception&) + { + OSL_FAIL("Exception caught!"); + } + return sFormula; +} + +void FunctionDescription::fillVisibleArgumentMapping(::std::vector<sal_uInt16>& _rArguments) const +{ + const sal_Int32 nCount = m_aParameter.getLength(); + for(sal_Int32 i = 0;i < nCount; ++i) + { + _rArguments.push_back(i); + } +} + +void FunctionDescription::initArgumentInfo() const +{ +} + +OUString FunctionDescription::getSignature() const +{ + return m_xFunctionDescription->getSignature(); +} + +OString FunctionDescription::getHelpId() const +{ + return OString(); +} + +bool FunctionDescription::isHidden() const +{ + return false; +} + +sal_uInt32 FunctionDescription::getParameterCount() const +{ + return m_aParameter.getLength(); +} + +sal_uInt32 FunctionDescription::getVarArgsStart() const +{ + /* XXX there are no variable number of arguments, are there? Nevertheless + * consider the varargs handling of the Function Wizard and return a value + * within the bounds of parameters. */ + // Don't use defines/constants that could change in future, parameter count + // could be part of an implicit stable API. + // offapi/com/sun/star/report/meta/XFunctionDescription.idl doesn't tell. + const sal_uInt32 nVarArgs30 = 30; // ugly hard coded old VAR_ARGS of formula::ParaWin + const sal_uInt32 nPairedVarArgs60 = 60; // ugly hard coded old PAIRED_VAR_ARGS of formula::ParaWin + const sal_uInt32 nVarArgs255 = 255; // ugly hard coded new VAR_ARGS of formula::ParaWin + const sal_uInt32 nPairedVarArgs510 = 510; // ugly hard coded new PAIRED_VAR_ARGS of formula::ParaWin + sal_uInt32 nLen = m_aParameter.getLength(); + // If the value of VAR_ARGS changes then adapt *and* maintain implicit API + // stability, ie. old code using the old VAR_ARGS and PAIRED_VAR_ARGS + // values must still be handled. It is *not* sufficient to simply change + // the values here. + static_assert(nVarArgs255 == VAR_ARGS && nPairedVarArgs510 == PAIRED_VAR_ARGS, + "VAR_ARGS or PAIRED_VAR_ARGS has unexpected value"); + if (nLen >= nPairedVarArgs510) + nLen -= nPairedVarArgs510; + else if (nLen >= nVarArgs255) + nLen -= nVarArgs255; + else if (nLen >= nPairedVarArgs60) + nLen -= nPairedVarArgs60; + else if (nLen >= nVarArgs30) + nLen -= nVarArgs30; + return nLen ? nLen - 1 : 0; +} + +sal_uInt32 FunctionDescription::getVarArgsLimit() const +{ + return 0; +} + +OUString FunctionDescription::getParameterName(sal_uInt32 _nPos) const +{ + if ( _nPos < o3tl::make_unsigned(m_aParameter.getLength()) ) + return m_aParameter[_nPos].Name; + return OUString(); +} + +OUString FunctionDescription::getParameterDescription(sal_uInt32 _nPos) const +{ + if ( _nPos < o3tl::make_unsigned(m_aParameter.getLength()) ) + return m_aParameter[_nPos].Description; + return OUString(); +} + +bool FunctionDescription::isParameterOptional(sal_uInt32 _nPos) const +{ + if ( _nPos < o3tl::make_unsigned(m_aParameter.getLength()) ) + return m_aParameter[_nPos].IsOptional; + return false; +} + + +} // rptui + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/reportdesign/source/ui/misc/RptUndo.cxx b/reportdesign/source/ui/misc/RptUndo.cxx new file mode 100644 index 000000000..5ac23ff0c --- /dev/null +++ b/reportdesign/source/ui/misc/RptUndo.cxx @@ -0,0 +1,386 @@ +/* -*- 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 <RptUndo.hxx> +#include <strings.hxx> +#include <rptui_slotid.hrc> +#include <UITools.hxx> +#include <UndoEnv.hxx> + +#include <dbaccess/IController.hxx> +#include <com/sun/star/report/XSection.hpp> +#include <com/sun/star/beans/PropertyAttribute.hpp> + +#include <com/sun/star/awt/Point.hpp> +#include <com/sun/star/awt/Size.hpp> +#include <comphelper/types.hxx> +#include <svx/unoshape.hxx> +#include <utility> +#include <tools/diagnose_ex.h> + +#include <functional> + +namespace rptui +{ + using namespace ::com::sun::star; + using namespace uno; + using namespace lang; + using namespace beans; + using namespace awt; + using namespace util; + using namespace container; + using namespace report; + + +namespace +{ + void lcl_collectElements(const uno::Reference< report::XSection >& _xSection,::std::vector< uno::Reference< drawing::XShape> >& _rControls) + { + if ( _xSection.is() ) + { + sal_Int32 nCount = _xSection->getCount(); + _rControls.reserve(nCount); + while ( nCount ) + { + uno::Reference< drawing::XShape> xShape(_xSection->getByIndex(nCount-1),uno::UNO_QUERY); + _rControls.push_back(xShape); + _xSection->remove(xShape); + --nCount; + } + } + } + + void lcl_insertElements(const uno::Reference< report::XSection >& _xSection,const ::std::vector< uno::Reference< drawing::XShape> >& _aControls) + { + if ( !_xSection.is() ) + return; + + ::std::vector< uno::Reference< drawing::XShape> >::const_reverse_iterator aIter = _aControls.rbegin(); + ::std::vector< uno::Reference< drawing::XShape> >::const_reverse_iterator aEnd = _aControls.rend(); + for (; aIter != aEnd; ++aIter) + { + try + { + const awt::Point aPos = (*aIter)->getPosition(); + const awt::Size aSize = (*aIter)->getSize(); + _xSection->add(*aIter); + (*aIter)->setPosition( aPos ); + (*aIter)->setSize( aSize ); + } + catch(const uno::Exception&) + { + OSL_FAIL("lcl_insertElements:Exception caught!"); + } + } + } + + void lcl_setValues(const uno::Reference< report::XSection >& _xSection,const ::std::vector< ::std::pair< OUString ,uno::Any> >& _aValues) + { + if ( !_xSection.is() ) + return; + + for (const auto& [rPropName, rValue] : _aValues) + { + try + { + _xSection->setPropertyValue(rPropName, rValue); + } + catch(const uno::Exception&) + { + OSL_FAIL("lcl_setValues:Exception caught!"); + } + } + } +} + + +OSectionUndo::OSectionUndo(OReportModel& _rMod + ,sal_uInt16 _nSlot + ,Action _eAction + ,const char* pCommentID) +: OCommentUndoAction(_rMod,pCommentID) +,m_eAction(_eAction) +,m_nSlot(_nSlot) +,m_bInserted(false) +{ +} + +OSectionUndo::~OSectionUndo() +{ + if ( m_bInserted ) + return; + + OXUndoEnvironment& rEnv = static_cast< OReportModel& >( rMod ).GetUndoEnv(); + for (uno::Reference<drawing::XShape>& xShape : m_aControls) + { + rEnv.RemoveElement(xShape); + +#if OSL_DEBUG_LEVEL > 0 + SvxShape* pShape = comphelper::getUnoTunnelImplementation<SvxShape>( xShape ); + SdrObject* pObject = pShape ? pShape->GetSdrObject() : nullptr; + OSL_ENSURE( pShape && pShape->HasSdrObjectOwnership() && pObject && !pObject->IsInserted(), + "OSectionUndo::~OSectionUndo: inconsistency in the shape/object ownership!" ); +#endif + try + { + comphelper::disposeComponent(xShape); + } + catch(const uno::Exception &) + { + OSL_FAIL("Exception caught!"); + } + } +} + +void OSectionUndo::collectControls(const uno::Reference< report::XSection >& _xSection) +{ + m_aControls.clear(); + try + { + // copy all properties for restoring + uno::Reference< beans::XPropertySetInfo> xInfo = _xSection->getPropertySetInfo(); + const uno::Sequence< beans::Property> aSeq = xInfo->getProperties(); + for(const beans::Property& rProp : aSeq) + { + if ( 0 == (rProp.Attributes & beans::PropertyAttribute::READONLY) ) + m_aValues.emplace_back(rProp.Name,_xSection->getPropertyValue(rProp.Name)); + } + lcl_collectElements(_xSection,m_aControls); + } + catch(uno::Exception&) + { + } +} + +void OSectionUndo::Undo() +{ + try + { + switch ( m_eAction ) + { + case Inserted: + implReRemove(); + break; + + case Removed: + implReInsert(); + break; + } + } + catch( const Exception& ) + { + TOOLS_WARN_EXCEPTION( "reportdesign", "OSectionUndo::Undo" ); + } +} + +void OSectionUndo::Redo() +{ + try + { + switch ( m_eAction ) + { + case Inserted: + implReInsert(); + break; + + case Removed: + implReRemove(); + break; + } + } + catch( const Exception& ) + { + TOOLS_WARN_EXCEPTION( "reportdesign", "OSectionUndo::Redo" ); + } +} + +OReportSectionUndo::OReportSectionUndo( + OReportModel& _rMod, sal_uInt16 _nSlot, + ::std::function<uno::Reference<report::XSection>(OReportHelper*)> _pMemberFunction, + const uno::Reference<report::XReportDefinition>& _xReport, Action _eAction) + : OSectionUndo(_rMod, _nSlot, _eAction, nullptr) + , m_aReportHelper(_xReport) + , m_pMemberFunction(std::move(_pMemberFunction)) +{ + if( m_eAction == Removed ) + collectControls(m_pMemberFunction(&m_aReportHelper)); +} + +OReportSectionUndo::~OReportSectionUndo() +{ +} + +void OReportSectionUndo::implReInsert( ) +{ + const uno::Sequence< beans::PropertyValue > aArgs; + m_pController->executeChecked(m_nSlot,aArgs); + uno::Reference< report::XSection > xSection = m_pMemberFunction(&m_aReportHelper); + lcl_insertElements(xSection,m_aControls); + lcl_setValues(xSection,m_aValues); + m_bInserted = true; +} + +void OReportSectionUndo::implReRemove( ) +{ + if( m_eAction == Removed ) + collectControls(m_pMemberFunction(&m_aReportHelper)); + const uno::Sequence< beans::PropertyValue > aArgs; + m_pController->executeChecked(m_nSlot,aArgs); + m_bInserted = false; +} + +OGroupSectionUndo::OGroupSectionUndo( + OReportModel& _rMod, sal_uInt16 _nSlot, + ::std::function<uno::Reference<report::XSection>(OGroupHelper*)> _pMemberFunction, + const uno::Reference<report::XGroup>& _xGroup, Action _eAction, const char* pCommentID) + : OSectionUndo(_rMod, _nSlot, _eAction, pCommentID) + , m_aGroupHelper(_xGroup) + , m_pMemberFunction(std::move(_pMemberFunction)) +{ + if( m_eAction == Removed ) + { + uno::Reference< report::XSection > xSection = m_pMemberFunction(&m_aGroupHelper); + if ( xSection.is() ) + m_sName = xSection->getName(); + collectControls(xSection); + } +} + +OUString OGroupSectionUndo::GetComment() const +{ + if ( m_sName.isEmpty() ) + { + try + { + uno::Reference< report::XSection > xSection = const_cast<OGroupSectionUndo*>(this)->m_pMemberFunction(&const_cast<OGroupSectionUndo*>(this)->m_aGroupHelper); + + if ( xSection.is() ) + m_sName = xSection->getName(); + } + catch (const uno::Exception&) + { + } + } + return m_strComment + m_sName; +} + +void OGroupSectionUndo::implReInsert( ) +{ + uno::Sequence< beans::PropertyValue > aArgs(2); + + aArgs[0].Name = SID_GROUPHEADER_WITHOUT_UNDO == m_nSlot? OUStringLiteral(PROPERTY_HEADERON) : OUStringLiteral(PROPERTY_FOOTERON); + aArgs[0].Value <<= true; + aArgs[1].Name = PROPERTY_GROUP; + aArgs[1].Value <<= m_aGroupHelper.getGroup(); + m_pController->executeChecked(m_nSlot,aArgs); + + uno::Reference< report::XSection > xSection = m_pMemberFunction(&m_aGroupHelper); + lcl_insertElements(xSection,m_aControls); + lcl_setValues(xSection,m_aValues); + m_bInserted = true; +} + +void OGroupSectionUndo::implReRemove( ) +{ + if( m_eAction == Removed ) + collectControls(m_pMemberFunction(&m_aGroupHelper)); + + uno::Sequence< beans::PropertyValue > aArgs(2); + + aArgs[0].Name = SID_GROUPHEADER_WITHOUT_UNDO == m_nSlot? OUStringLiteral(PROPERTY_HEADERON) : OUStringLiteral(PROPERTY_FOOTERON); + aArgs[0].Value <<= false; + aArgs[1].Name = PROPERTY_GROUP; + aArgs[1].Value <<= m_aGroupHelper.getGroup(); + + m_pController->executeChecked(m_nSlot,aArgs); + m_bInserted = false; +} + + +OGroupUndo::OGroupUndo(OReportModel& _rMod + ,const char* pCommentID + ,Action _eAction + ,const uno::Reference< report::XGroup>& _xGroup + ,const uno::Reference< report::XReportDefinition >& _xReportDefinition) +: OCommentUndoAction(_rMod,pCommentID) +,m_xGroup(_xGroup) +,m_xReportDefinition(_xReportDefinition) +,m_eAction(_eAction) +{ + m_nLastPosition = getPositionInIndexAccess(m_xReportDefinition->getGroups().get(),m_xGroup); +} + +void OGroupUndo::implReInsert( ) +{ + try + { + m_xReportDefinition->getGroups()->insertByIndex(m_nLastPosition,uno::makeAny(m_xGroup)); + } + catch(uno::Exception&) + { + OSL_FAIL("Exception caught while undoing remove group"); + } +} + +void OGroupUndo::implReRemove( ) +{ + try + { + m_xReportDefinition->getGroups()->removeByIndex(m_nLastPosition); + } + catch(uno::Exception&) + { + OSL_FAIL("Exception caught while redoing remove group"); + } +} + +void OGroupUndo::Undo() +{ + switch ( m_eAction ) + { + case Inserted: + implReRemove(); + break; + + case Removed: + implReInsert(); + break; + } + +} + +void OGroupUndo::Redo() +{ + switch ( m_eAction ) + { + case Inserted: + implReInsert(); + break; + + case Removed: + implReRemove(); + break; + } +} + + +} // rptui + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/reportdesign/source/ui/misc/UITools.cxx b/reportdesign/source/ui/misc/UITools.cxx new file mode 100644 index 000000000..940250a6f --- /dev/null +++ b/reportdesign/source/ui/misc/UITools.cxx @@ -0,0 +1,1116 @@ +/* -*- 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 <toolkit/helper/convert.hxx> +#include <toolkit/helper/vclunohelper.hxx> +#include <SectionView.hxx> +#include <UITools.hxx> +#include <Formula.hxx> +#include <FunctionHelper.hxx> +#include <reportformula.hxx> + +#include <tools/diagnose_ex.h> + +#include <vcl/settings.hxx> +#include <vcl/syswin.hxx> +#include <vcl/svapp.hxx> +#include <vcl/unohelp.hxx> +#include <vcl/window.hxx> + +#include <com/sun/star/lang/NullPointerException.hpp> +#include <com/sun/star/beans/NamedValue.hpp> +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <svx/svdpool.hxx> + +#include <editeng/charscaleitem.hxx> +#include <editeng/brushitem.hxx> +#include <editeng/fontitem.hxx> +#include <editeng/emphasismarkitem.hxx> +#include <editeng/postitem.hxx> +#include <editeng/udlnitem.hxx> +#include <editeng/crossedoutitem.hxx> +#include <editeng/contouritem.hxx> +#include <editeng/langitem.hxx> +#include <editeng/wghtitem.hxx> +#include <editeng/fhgtitem.hxx> +#include <editeng/shdditem.hxx> +#include <editeng/escapementitem.hxx> +#include <editeng/wrlmitem.hxx> +#include <editeng/cmapitem.hxx> +#include <editeng/kernitem.hxx> +#include <editeng/blinkitem.hxx> +#include <editeng/flstitem.hxx> +#include <editeng/autokernitem.hxx> +#include <editeng/colritem.hxx> +#include <editeng/justifyitem.hxx> +#include <svx/drawitem.hxx> +#include <editeng/twolinesitem.hxx> +#include <editeng/charreliefitem.hxx> +#include <editeng/charrotateitem.hxx> +#include <editeng/charhiddenitem.hxx> +#include <editeng/memberids.h> +#include <svx/xgrscit.hxx> +#include <svx/svditer.hxx> +#include <svx/xtable.hxx> +#include <svx/svdview.hxx> +#include <svx/svdpage.hxx> +#include <svx/svxdlg.hxx> +#include <svx/unoprov.hxx> +#include <svx/svxids.hrc> + +#include <unotools/charclass.hxx> +#include <svtools/ctrltool.hxx> +#include <svl/itempool.hxx> +#include <svl/itemset.hxx> +#include <svl/sharedstringpool.hxx> + +#include <comphelper/propmultiplex.hxx> +#include <comphelper/namedvaluecollection.hxx> + +#include <connectivity/dbexception.hxx> +#include <connectivity/dbtools.hxx> + +#include <com/sun/star/style/VerticalAlignment.hpp> +#include <com/sun/star/report/XShape.hpp> +#include <com/sun/star/sdb/XParametersSupplier.hpp> +#include <com/sun/star/sdb/SQLContext.hpp> +#include <i18nlangtag/languagetag.hxx> +#include <dlgpage.hxx> +#include <strings.hxx> +#include <core_resource.hxx> +#include <RptObject.hxx> +#include <RptDef.hxx> +#include <strings.hrc> +#include <ReportDefinition.hxx> +#include <RptModel.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/xbtmpit.hxx> +#include <svx/xfillit0.hxx> +#include <svx/xfltrit.hxx> +#include <svx/xflclit.hxx> +#include <svx/xflgrit.hxx> +#include <svx/xflhtit.hxx> +#include <svx/xflftrit.hxx> +#include <svx/xsflclit.hxx> + +#define ITEMID_FONT XATTR_FILL_LAST + 1 +#define ITEMID_FONTHEIGHT XATTR_FILL_LAST + 2 +#define ITEMID_LANGUAGE XATTR_FILL_LAST + 3 + +#define ITEMID_POSTURE XATTR_FILL_LAST + 4 +#define ITEMID_WEIGHT XATTR_FILL_LAST + 5 +#define ITEMID_SHADOWED XATTR_FILL_LAST + 6 +#define ITEMID_WORDLINEMODE XATTR_FILL_LAST + 7 +#define ITEMID_CONTOUR XATTR_FILL_LAST + 8 +#define ITEMID_CROSSEDOUT XATTR_FILL_LAST + 9 +#define ITEMID_UNDERLINE XATTR_FILL_LAST + 10 + +#define ITEMID_COLOR XATTR_FILL_LAST + 11 +#define ITEMID_KERNING XATTR_FILL_LAST + 12 +#define ITEMID_CASEMAP XATTR_FILL_LAST + 13 + +#define ITEMID_ESCAPEMENT XATTR_FILL_LAST + 14 +#define ITEMID_FONTLIST XATTR_FILL_LAST + 15 +#define ITEMID_AUTOKERN XATTR_FILL_LAST + 16 +#define ITEMID_COLOR_TABLE XATTR_FILL_LAST + 17 +#define ITEMID_BLINK XATTR_FILL_LAST + 18 +#define ITEMID_EMPHASISMARK XATTR_FILL_LAST + 19 +#define ITEMID_TWOLINES XATTR_FILL_LAST + 20 +#define ITEMID_CHARROTATE XATTR_FILL_LAST + 21 +#define ITEMID_CHARSCALE_W XATTR_FILL_LAST + 22 +#define ITEMID_CHARRELIEF XATTR_FILL_LAST + 23 +#define ITEMID_CHARHIDDEN XATTR_FILL_LAST + 24 +#define ITEMID_BRUSH XATTR_FILL_LAST + 25 +#define ITEMID_HORJUSTIFY XATTR_FILL_LAST + 26 +#define ITEMID_VERJUSTIFY XATTR_FILL_LAST + 27 +#define ITEMID_FONT_ASIAN XATTR_FILL_LAST + 28 +#define ITEMID_FONTHEIGHT_ASIAN XATTR_FILL_LAST + 29 +#define ITEMID_LANGUAGE_ASIAN XATTR_FILL_LAST + 30 +#define ITEMID_POSTURE_ASIAN XATTR_FILL_LAST + 31 +#define ITEMID_WEIGHT_ASIAN XATTR_FILL_LAST + 32 +#define ITEMID_FONT_COMPLEX XATTR_FILL_LAST + 33 +#define ITEMID_FONTHEIGHT_COMPLEX XATTR_FILL_LAST + 34 +#define ITEMID_LANGUAGE_COMPLEX XATTR_FILL_LAST + 35 +#define ITEMID_POSTURE_COMPLEX XATTR_FILL_LAST + 36 +#define ITEMID_WEIGHT_COMPLEX XATTR_FILL_LAST + 37 + +#define WESTERN 0 +#define ASIAN 1 +#define COMPLEX 2 + +namespace rptui +{ +using namespace ::com::sun::star; +using namespace formula; + +void adjustSectionName(const uno::Reference< report::XGroup >& _xGroup,sal_Int32 _nPos) +{ + OSL_ENSURE(_xGroup.is(),"Group is NULL -> GPF"); + if ( _xGroup->getHeaderOn() && _xGroup->getHeader()->getName().isEmpty() ) + { + OUString sName = RptResId(RID_STR_GROUPHEADER) + OUString::number(_nPos); + _xGroup->getHeader()->setName(sName); + } + + if ( _xGroup->getFooterOn() && _xGroup->getFooter()->getName().isEmpty() ) + { + OUString sName = RptResId(RID_STR_GROUPFOOTER) + OUString::number(_nPos); + _xGroup->getFooter()->setName(sName); + } +} + +::rtl::Reference< comphelper::OPropertyChangeMultiplexer> addStyleListener(const uno::Reference< report::XReportDefinition >& _xReportDefinition,::comphelper::OPropertyChangeListener* _pListener) +{ + ::rtl::Reference< comphelper::OPropertyChangeMultiplexer> pRet; + if ( _xReportDefinition.is() ) + { + uno::Reference<beans::XPropertySet> xPageStyle(getUsedStyle(_xReportDefinition),uno::UNO_QUERY); + if ( xPageStyle.is() ) + { + pRet = new comphelper::OPropertyChangeMultiplexer(_pListener,xPageStyle); + pRet->addProperty(PROPERTY_LEFTMARGIN); + pRet->addProperty(PROPERTY_RIGHTMARGIN); + pRet->addProperty(PROPERTY_PAPERSIZE); + pRet->addProperty(PROPERTY_BACKCOLOR); + } + } + return pRet; +} + + +namespace +{ + + vcl::Font lcl_getReportControlFont( const uno::Reference<report::XReportControlFormat >& _rxReportControlFormat, awt::FontDescriptor& _out_rControlFont ,sal_uInt16 _nWichFont) + { + if ( !_rxReportControlFormat.is() ) + throw uno::RuntimeException(); + + switch(_nWichFont) + { + case WESTERN: + _out_rControlFont = _rxReportControlFormat->getFontDescriptor(); + break; + case ASIAN: + _out_rControlFont = _rxReportControlFormat->getFontDescriptorAsian(); + break; + case COMPLEX: + _out_rControlFont = _rxReportControlFormat->getFontDescriptorComplex(); + break; + + } + + vcl::Font aDefaultFont = Application::GetDefaultDevice()->GetSettings().GetStyleSettings().GetAppFont(); + return VCLUnoHelper::CreateFont( _out_rControlFont, aDefaultFont ); + } + + + vcl::Font lcl_getReportControlFont( const uno::Reference<report::XReportControlFormat >& _rxReportControlFormat,sal_uInt16 _nWhich ) + { + awt::FontDescriptor aAwtFont; + return lcl_getReportControlFont( _rxReportControlFormat, aAwtFont, _nWhich ); + } + + vcl::Font lcl_setFont(const uno::Reference<report::XReportControlFormat >& _rxReportControlFormat, + SfxItemSet& _rItemSet,sal_uInt16 _nWhich,sal_uInt16 _nFont, sal_uInt16 _nFontHeight,sal_uInt16 _nLanguage,sal_uInt16 _nPosture, sal_uInt16 _nWeight) + { + // fill it + awt::FontDescriptor aControlFont; + const vcl::Font aFont( lcl_getReportControlFont( _rxReportControlFormat, aControlFont,_nWhich ) ); + + SvxFontItem aFontItem(_nFont); + aFontItem.PutValue( uno::makeAny( aControlFont ), 0 ); + _rItemSet.Put(aFontItem); + + _rItemSet.Put(SvxFontHeightItem(OutputDevice::LogicToLogic(Size(0, aFont.GetFontHeight()), MapMode(MapUnit::MapPoint), MapMode(MapUnit::MapTwip)).Height(), 100, _nFontHeight)); + lang::Locale aLocale; + switch(_nWhich) + { + default: + aLocale = _rxReportControlFormat->getCharLocale(); + break; + case ASIAN: + aLocale = _rxReportControlFormat->getCharLocaleAsian(); + break; + case COMPLEX: + aLocale = _rxReportControlFormat->getCharLocaleComplex(); + break; + } + + _rItemSet.Put(SvxLanguageItem(LanguageTag(aLocale).makeFallback().getLanguageType(),_nLanguage)); + + _rItemSet.Put(SvxPostureItem(aFont.GetItalic(),_nPosture)); + _rItemSet.Put(SvxWeightItem(aFont.GetWeight(),_nWeight)); + return aFont; + } + + void lcl_fillShapeToItems( const uno::Reference<report::XShape >& _xShape,SfxItemSet& _rItemSet ) + { + uno::Reference< beans::XPropertySetInfo> xInfo = _xShape->getPropertySetInfo(); + SvxUnoPropertyMapProvider aMap; + const SfxItemPropertyMap& rPropertyMap = aMap.GetPropertySet(SVXMAP_CUSTOMSHAPE, SdrObject::GetGlobalDrawObjectItemPool())->getPropertyMap(); + PropertyEntryVector_t aPropVector = rPropertyMap.getPropertyEntries(); + for (const auto& rProp : aPropVector) + { + if ( xInfo->hasPropertyByName(rProp.sName) ) + { + const SfxPoolItem* pItem = _rItemSet.GetItem(rProp.nWID); + if ( pItem ) + { + ::std::unique_ptr<SfxPoolItem> pClone(pItem->CloneSetWhich(rProp.nWID)); + pClone->PutValue(_xShape->getPropertyValue(rProp.sName), rProp.nMemberId); + _rItemSet.Put(std::move(pClone)); + } + } + } + } + + void lcl_fillItemsToShape( const uno::Reference<report::XShape >& _xShape,const SfxItemSet& _rItemSet ) + { + const uno::Reference< beans::XPropertySetInfo> xInfo = _xShape->getPropertySetInfo(); + SvxUnoPropertyMapProvider aMap; + const SfxItemPropertyMap& rPropertyMap = aMap.GetPropertySet(SVXMAP_CUSTOMSHAPE, SdrObject::GetGlobalDrawObjectItemPool())->getPropertyMap(); + PropertyEntryVector_t aPropVector = rPropertyMap.getPropertyEntries(); + for (const auto& rProp : aPropVector) + { + if ( SfxItemState::SET == _rItemSet.GetItemState(rProp.nWID) && xInfo->hasPropertyByName(rProp.sName) ) + { + if ( ( rProp.nFlags & beans::PropertyAttribute::READONLY ) != beans::PropertyAttribute::READONLY ) + { + const SfxPoolItem* pItem = _rItemSet.GetItem(rProp.nWID); + if ( pItem ) + { + uno::Any aValue; + pItem->QueryValue(aValue,rProp.nMemberId); + try + { + _xShape->setPropertyValue(rProp.sName, aValue); + } + catch(uno::Exception&) + { // shapes have a bug so we ignore this one. + } + } + } + } + } + } + + void lcl_CharPropertiesToItems( const uno::Reference<report::XReportControlFormat >& _rxReportControlFormat, + SfxItemSet& _rItemSet ) + { + if ( !_rxReportControlFormat.is() ) + throw lang::NullPointerException(); + + uno::Reference< beans::XPropertySet > xSet(_rxReportControlFormat,uno::UNO_QUERY_THROW); + + // fill it + const vcl::Font aFont( lcl_setFont(_rxReportControlFormat, _rItemSet,WESTERN,ITEMID_FONT,ITEMID_FONTHEIGHT,ITEMID_LANGUAGE,ITEMID_POSTURE,ITEMID_WEIGHT ) ); + + _rItemSet.Put(SvxShadowedItem(_rxReportControlFormat->getCharShadowed(),ITEMID_SHADOWED)); + _rItemSet.Put(SvxWordLineModeItem(aFont.IsWordLineMode(),ITEMID_WORDLINEMODE)); + _rItemSet.Put(SvxContourItem(_rxReportControlFormat->getCharContoured(),ITEMID_CONTOUR)); + _rItemSet.Put(SvxAutoKernItem(_rxReportControlFormat->getCharAutoKerning(),ITEMID_AUTOKERN)); + _rItemSet.Put(SvxCrossedOutItem(aFont.GetStrikeout(),ITEMID_CROSSEDOUT)); + _rItemSet.Put(SvxCaseMapItem(static_cast<SvxCaseMap>(_rxReportControlFormat->getCharCaseMap()),ITEMID_CASEMAP)); + + _rItemSet.Put(SvxEscapementItem(_rxReportControlFormat->getCharEscapement(),_rxReportControlFormat->getCharEscapementHeight(),ITEMID_ESCAPEMENT)); + _rItemSet.Put(SvxBlinkItem(_rxReportControlFormat->getCharFlash(),ITEMID_BLINK)); + _rItemSet.Put(SvxCharHiddenItem(_rxReportControlFormat->getCharHidden(),ITEMID_CHARHIDDEN)); + _rItemSet.Put(SvxTwoLinesItem(_rxReportControlFormat->getCharCombineIsOn(),_rxReportControlFormat->getCharCombinePrefix().toChar(),_rxReportControlFormat->getCharCombineSuffix().toChar(),ITEMID_TWOLINES)); + SvxUnderlineItem aUnderLineItem(aFont.GetUnderline(),ITEMID_UNDERLINE); + aUnderLineItem.SetColor(Color(_rxReportControlFormat->getCharUnderlineColor())); + _rItemSet.Put(aUnderLineItem); + _rItemSet.Put(SvxKerningItem(_rxReportControlFormat->getCharKerning(),ITEMID_KERNING)); + _rItemSet.Put(SvxEmphasisMarkItem(static_cast<FontEmphasisMark>(_rxReportControlFormat->getCharEmphasis()),ITEMID_EMPHASISMARK)); + _rItemSet.Put(SvxCharReliefItem(static_cast<FontRelief>(_rxReportControlFormat->getCharRelief()),ITEMID_CHARRELIEF)); + _rItemSet.Put(SvxColorItem(::Color(_rxReportControlFormat->getCharColor()),ITEMID_COLOR)); + _rItemSet.Put(SvxCharRotateItem(_rxReportControlFormat->getCharRotation(),false,ITEMID_CHARROTATE)); + _rItemSet.Put(SvxCharScaleWidthItem(_rxReportControlFormat->getCharScaleWidth(),ITEMID_CHARSCALE_W)); + + SvxHorJustifyItem aHorJustifyItem(ITEMID_HORJUSTIFY); + aHorJustifyItem.PutValue(xSet->getPropertyValue(PROPERTY_PARAADJUST),MID_HORJUST_ADJUST); + _rItemSet.Put(aHorJustifyItem); + SvxVerJustifyItem aVerJustifyItem(ITEMID_VERJUSTIFY); + aVerJustifyItem.PutValue(xSet->getPropertyValue(PROPERTY_VERTICALALIGN),MID_HORJUST_ADJUST); + _rItemSet.Put(aVerJustifyItem); + + uno::Reference< report::XShape> xShape(_rxReportControlFormat,uno::UNO_QUERY); + if ( !xShape.is() ) + _rItemSet.Put(SvxBrushItem(::Color(_rxReportControlFormat->getControlBackground()),ITEMID_BRUSH)); + + lcl_setFont(_rxReportControlFormat, _rItemSet,ASIAN,ITEMID_FONT_ASIAN,ITEMID_FONTHEIGHT_ASIAN,ITEMID_LANGUAGE_ASIAN,ITEMID_POSTURE_ASIAN,ITEMID_WEIGHT_ASIAN ); + lcl_setFont(_rxReportControlFormat, _rItemSet,COMPLEX,ITEMID_FONT_COMPLEX,ITEMID_FONTHEIGHT_COMPLEX,ITEMID_LANGUAGE_COMPLEX,ITEMID_POSTURE_COMPLEX,ITEMID_WEIGHT_COMPLEX ); + } + + + void lcl_pushBack( uno::Sequence< beans::NamedValue >& _out_rProperties, const OUString& _sName, const uno::Any& _rValue ) + { + sal_Int32 nLen( _out_rProperties.getLength() ); + _out_rProperties.realloc( nLen + 1 ); + _out_rProperties[ nLen ] = beans::NamedValue( _sName, _rValue ); + } + + + void lcl_initAwtFont( const vcl::Font& _rOriginalFont, const SfxItemSet& _rItemSet, awt::FontDescriptor& _out_rAwtFont, + sal_uInt16 _nFont, sal_uInt16 _nFontHeight,sal_uInt16 _nPosture, sal_uInt16 _nWeight) + { + vcl::Font aNewFont( _rOriginalFont ); + const SfxPoolItem* pItem( nullptr ); + if ( SfxItemState::SET == _rItemSet.GetItemState( _nFont,true,&pItem) && dynamic_cast< const SvxFontItem *>( pItem ) != nullptr) + { + const SvxFontItem* pFontItem = static_cast<const SvxFontItem*>(pItem); + aNewFont.SetFamilyName(pFontItem->GetFamilyName()); + aNewFont.SetStyleName(pFontItem->GetStyleName()); + aNewFont.SetFamily(pFontItem->GetFamily()); + aNewFont.SetPitch(pFontItem->GetPitch()); + aNewFont.SetCharSet(pFontItem->GetCharSet()); + } + if ( SfxItemState::SET == _rItemSet.GetItemState( _nFontHeight,true,&pItem) && dynamic_cast< const SvxFontHeightItem *>( pItem ) != nullptr) + { + const SvxFontHeightItem* pFontItem = static_cast<const SvxFontHeightItem*>(pItem); + aNewFont.SetFontHeight(OutputDevice::LogicToLogic(Size(0, pFontItem->GetHeight()), MapMode(MapUnit::MapTwip), MapMode(MapUnit::MapPoint)).Height()); + } + if ( SfxItemState::SET == _rItemSet.GetItemState( _nPosture,true,&pItem) && dynamic_cast< const SvxPostureItem *>( pItem ) != nullptr) + { + const SvxPostureItem* pFontItem = static_cast<const SvxPostureItem*>(pItem); + aNewFont.SetItalic(pFontItem->GetPosture()); + } + if ( SfxItemState::SET == _rItemSet.GetItemState( _nWeight,true,&pItem) && dynamic_cast< const SvxWeightItem *>( pItem ) != nullptr) + { + const SvxWeightItem* pFontItem = static_cast<const SvxWeightItem*>(pItem); + aNewFont.SetWeight(pFontItem->GetWeight()); + } + if ( SfxItemState::SET == _rItemSet.GetItemState( ITEMID_WORDLINEMODE,true,&pItem) && dynamic_cast< const SvxWordLineModeItem *>( pItem ) != nullptr) + { + const SvxWordLineModeItem* pFontItem = static_cast<const SvxWordLineModeItem*>(pItem); + aNewFont.SetWordLineMode(pFontItem->GetValue()); + } + if ( SfxItemState::SET == _rItemSet.GetItemState( ITEMID_CROSSEDOUT,true,&pItem) && dynamic_cast< const SvxCrossedOutItem *>( pItem ) != nullptr) + { + const SvxCrossedOutItem* pFontItem = static_cast<const SvxCrossedOutItem*>(pItem); + aNewFont.SetStrikeout(pFontItem->GetStrikeout()); + } + + if ( SfxItemState::SET == _rItemSet.GetItemState( ITEMID_CHARROTATE,true,&pItem) && dynamic_cast< const SvxCharRotateItem *>( pItem ) != nullptr) + { + const SvxCharRotateItem* pRotateItem = static_cast<const SvxCharRotateItem*>(pItem); + aNewFont.SetOrientation(pRotateItem->GetValue()); + } + if ( SfxItemState::SET == _rItemSet.GetItemState( ITEMID_CHARSCALE_W,true,&pItem) && dynamic_cast< const SvxCharScaleWidthItem *>( pItem ) != nullptr) + { + const SvxCharScaleWidthItem* pCharItem = static_cast<const SvxCharScaleWidthItem*>(pItem); + aNewFont.SetWidthType(vcl::unohelper::ConvertFontWidth(pCharItem->GetValue())); + } + if ( SfxItemState::SET == _rItemSet.GetItemState( ITEMID_UNDERLINE,true,&pItem) && dynamic_cast< const SvxUnderlineItem *>( pItem ) != nullptr) + { + const SvxUnderlineItem* pFontItem = static_cast<const SvxUnderlineItem*>(pItem); + aNewFont.SetUnderline(pFontItem->GetLineStyle()); + } + if ( SfxItemState::SET == _rItemSet.GetItemState( ITEMID_COLOR,true,&pItem) && dynamic_cast< const SvxColorItem *>( pItem ) != nullptr) + { + const SvxColorItem* pFontItem = static_cast<const SvxColorItem*>(pItem); + aNewFont.SetColor(pFontItem->GetValue()); + } + + _out_rAwtFont = VCLUnoHelper::CreateFontDescriptor( aNewFont ); + } + + + void lcl_itemsToCharProperties( const vcl::Font& _rOriginalControlFont,const vcl::Font& _rOriginalControlFontAsian,const vcl::Font& _rOriginalControlFontComplex, const SfxItemSet& _rItemSet, uno::Sequence< beans::NamedValue >& _out_rProperties ) + { + const SfxPoolItem* pItem( nullptr ); + + // create an AWT font + awt::FontDescriptor aAwtFont; + lcl_initAwtFont( _rOriginalControlFont, _rItemSet, aAwtFont,ITEMID_FONT,ITEMID_FONTHEIGHT,ITEMID_POSTURE, ITEMID_WEIGHT); + lcl_pushBack( _out_rProperties, "Font", uno::makeAny( aAwtFont ) ); + lcl_initAwtFont( _rOriginalControlFontAsian, _rItemSet, aAwtFont,ITEMID_FONT_ASIAN,ITEMID_FONTHEIGHT_ASIAN,ITEMID_POSTURE_ASIAN, ITEMID_WEIGHT_ASIAN); + lcl_pushBack( _out_rProperties, "FontAsian", uno::makeAny( aAwtFont ) ); + lcl_initAwtFont( _rOriginalControlFontComplex, _rItemSet, aAwtFont,ITEMID_FONT_COMPLEX,ITEMID_FONTHEIGHT_COMPLEX,ITEMID_POSTURE_COMPLEX, ITEMID_WEIGHT_COMPLEX); + lcl_pushBack( _out_rProperties, "FontComplex", uno::makeAny( aAwtFont ) ); + + // properties which cannot be represented in an AWT font need to be preserved directly + if ( SfxItemState::SET == _rItemSet.GetItemState( ITEMID_SHADOWED,true,&pItem) && dynamic_cast< const SvxShadowedItem *>( pItem ) != nullptr) + { + const SvxShadowedItem* pFontItem = static_cast<const SvxShadowedItem*>(pItem); + lcl_pushBack( _out_rProperties, PROPERTY_CHARSHADOWED, uno::makeAny( pFontItem->GetValue() ) ); + } + if ( SfxItemState::SET == _rItemSet.GetItemState( ITEMID_CONTOUR,true,&pItem) && dynamic_cast< const SvxContourItem *>( pItem ) != nullptr) + { + const SvxContourItem* pFontItem = static_cast<const SvxContourItem*>(pItem); + lcl_pushBack( _out_rProperties, PROPERTY_CHARCONTOURED, uno::makeAny( pFontItem->GetValue() ) ); + } + if ( SfxItemState::SET == _rItemSet.GetItemState( ITEMID_UNDERLINE,true,&pItem) && dynamic_cast< const SvxUnderlineItem *>( pItem ) != nullptr) + { + const SvxUnderlineItem* pFontItem = static_cast<const SvxUnderlineItem*>(pItem); + lcl_pushBack( _out_rProperties, PROPERTY_CHARUNDERLINECOLOR, uno::makeAny( pFontItem->GetColor() ) ); + } + if ( SfxItemState::SET == _rItemSet.GetItemState( ITEMID_HORJUSTIFY,true,&pItem) && dynamic_cast< const SvxHorJustifyItem *>( pItem ) != nullptr) + { + const SvxHorJustifyItem* pJustifyItem = static_cast<const SvxHorJustifyItem*>(pItem); + uno::Any aValue; + pJustifyItem->QueryValue(aValue,MID_HORJUST_ADJUST); + lcl_pushBack( _out_rProperties, PROPERTY_PARAADJUST, aValue ); + } + if ( SfxItemState::SET == _rItemSet.GetItemState( ITEMID_VERJUSTIFY,true,&pItem) && dynamic_cast< const SvxVerJustifyItem *>( pItem ) != nullptr) + { + const SvxVerJustifyItem* pJustifyItem = static_cast<const SvxVerJustifyItem*>(pItem); + uno::Any aValue; + pJustifyItem->QueryValue(aValue,MID_HORJUST_ADJUST); + lcl_pushBack( _out_rProperties, PROPERTY_VERTICALALIGN, aValue ); + } + if ( SfxItemState::SET == _rItemSet.GetItemState( ITEMID_CHARRELIEF,true,&pItem) && dynamic_cast< const SvxCharReliefItem *>( pItem ) != nullptr) + { + const SvxCharReliefItem* pFontItem = static_cast<const SvxCharReliefItem*>(pItem); + lcl_pushBack( _out_rProperties, PROPERTY_CHARRELIEF, uno::makeAny( static_cast< sal_Int16 >( pFontItem->GetEnumValue() ) ) ); + } + if ( SfxItemState::SET == _rItemSet.GetItemState( ITEMID_CHARHIDDEN,true,&pItem) && dynamic_cast< const SvxCharHiddenItem *>( pItem ) != nullptr) + { + const SvxCharHiddenItem* pFontItem = static_cast<const SvxCharHiddenItem*>(pItem); + lcl_pushBack( _out_rProperties, PROPERTY_CHARHIDDEN, uno::makeAny( pFontItem->GetValue() ) ); + } + if ( SfxItemState::SET == _rItemSet.GetItemState( ITEMID_AUTOKERN,true,&pItem) && dynamic_cast< const SvxAutoKernItem *>( pItem ) != nullptr) + { + const SvxAutoKernItem* pFontItem = static_cast<const SvxAutoKernItem*>(pItem); + lcl_pushBack( _out_rProperties, PROPERTY_CHARAUTOKERNING, uno::makeAny( pFontItem->GetValue() ) ); + } + if ( SfxItemState::SET == _rItemSet.GetItemState( ITEMID_BRUSH,true,&pItem) && dynamic_cast< const SvxBrushItem *>( pItem ) != nullptr) + { + const SvxBrushItem* pFontItem = static_cast<const SvxBrushItem*>(pItem); + lcl_pushBack( _out_rProperties, PROPERTY_CONTROLBACKGROUND, uno::makeAny( pFontItem->GetColor() ) ); + } + if ( SfxItemState::SET == _rItemSet.GetItemState( ITEMID_BLINK,true,&pItem) && dynamic_cast< const SvxBlinkItem *>( pItem ) != nullptr) + { + const SvxBlinkItem* pFontItem = static_cast<const SvxBlinkItem*>(pItem); + lcl_pushBack( _out_rProperties, PROPERTY_CHARFLASH, uno::makeAny( pFontItem->GetValue() ) ); + } + if ( SfxItemState::SET == _rItemSet.GetItemState( ITEMID_EMPHASISMARK,true,&pItem) && dynamic_cast< const SvxEmphasisMarkItem *>( pItem ) != nullptr) + { + const SvxEmphasisMarkItem* pFontItem = static_cast<const SvxEmphasisMarkItem*>(pItem); + lcl_pushBack( _out_rProperties, PROPERTY_CHAREMPHASIS, uno::makeAny( static_cast< sal_Int16 >( pFontItem->GetEmphasisMark() ) ) ); + } + if ( SfxItemState::SET == _rItemSet.GetItemState( ITEMID_TWOLINES,true,&pItem) && dynamic_cast< const SvxTwoLinesItem *>( pItem ) != nullptr) + { + const SvxTwoLinesItem* pFontItem = static_cast<const SvxTwoLinesItem*>(pItem); + lcl_pushBack( _out_rProperties, PROPERTY_CHARCOMBINEISON, uno::makeAny( pFontItem->GetValue() ) ); + lcl_pushBack( _out_rProperties, PROPERTY_CHARCOMBINEPREFIX, uno::makeAny( OUString( pFontItem->GetStartBracket() ) ) ); + lcl_pushBack( _out_rProperties, PROPERTY_CHARCOMBINESUFFIX, uno::makeAny( OUString( pFontItem->GetEndBracket() ) ) ); + } + if ( SfxItemState::SET == _rItemSet.GetItemState( ITEMID_COLOR,true,&pItem) && dynamic_cast< const SvxColorItem *>( pItem ) != nullptr) + { + const SvxColorItem* pFontItem = static_cast<const SvxColorItem*>(pItem); + lcl_pushBack( _out_rProperties, PROPERTY_CHARCOLOR, uno::makeAny( pFontItem->GetValue() ) ); + } + if ( SfxItemState::SET == _rItemSet.GetItemState( ITEMID_KERNING,true,&pItem) && dynamic_cast< const SvxKerningItem *>( pItem ) != nullptr) + { + const SvxKerningItem* pFontItem = static_cast<const SvxKerningItem*>(pItem); + lcl_pushBack( _out_rProperties, PROPERTY_CHARKERNING, uno::makeAny( pFontItem->GetValue() ) ); + } + if ( SfxItemState::SET == _rItemSet.GetItemState( ITEMID_CASEMAP,true,&pItem) && dynamic_cast< const SvxCaseMapItem *>( pItem ) != nullptr) + { + const SvxCaseMapItem* pFontItem = static_cast<const SvxCaseMapItem*>(pItem); + lcl_pushBack( _out_rProperties, PROPERTY_CHARCASEMAP, uno::makeAny( pFontItem->GetEnumValue() ) ); + } + struct Items { + sal_uInt16 nWhich; + OUString sPropertyName; + }; + const Items pItems[] = { {ITEMID_LANGUAGE,OUString(PROPERTY_CHARLOCALE)} + ,{ITEMID_LANGUAGE_ASIAN,OUString(PROPERTY_CHARLOCALEASIAN)} + ,{ITEMID_LANGUAGE_COMPLEX,OUString(PROPERTY_CHARLOCALECOMPLEX)} + }; + for(const auto & k : pItems) + { + if ( SfxItemState::SET == _rItemSet.GetItemState( k.nWhich,true,&pItem) && dynamic_cast< const SvxLanguageItem *>( pItem ) != nullptr) + { + const SvxLanguageItem* pFontItem = static_cast<const SvxLanguageItem*>(pItem); + lang::Locale aCharLocale( LanguageTag( pFontItem->GetLanguage()).getLocale()); + lcl_pushBack( _out_rProperties, k.sPropertyName, uno::makeAny( aCharLocale ) ); + } + } + if ( SfxItemState::SET == _rItemSet.GetItemState( ITEMID_ESCAPEMENT,true,&pItem) && dynamic_cast< const SvxEscapementItem *>( pItem ) != nullptr) + { + const SvxEscapementItem* pFontItem = static_cast<const SvxEscapementItem*>(pItem); + lcl_pushBack( _out_rProperties, PROPERTY_CHARESCAPEMENT, uno::makeAny( pFontItem->GetEsc() ) ); + lcl_pushBack( _out_rProperties, PROPERTY_CHARESCAPEMENTHEIGHT, uno::makeAny(static_cast<sal_Int8>(pFontItem->GetProportionalHeight())) ); + } + } + + + template< class ATTRIBUTE_TYPE > + void lcl_applyFontAttribute( const ::comphelper::NamedValueCollection& _rAttrValues, const char* _pAttributeName, + const uno::Reference<report::XReportControlFormat >& _rxReportControlFormat, + void (SAL_CALL report::XReportControlFormat::*pSetter)( ATTRIBUTE_TYPE ) ) + { + ATTRIBUTE_TYPE aAttributeValue = ATTRIBUTE_TYPE(); + if ( _rAttrValues.get_ensureType( _pAttributeName, aAttributeValue ) ) + (_rxReportControlFormat.get()->*pSetter)( aAttributeValue ); + } + + + void lcl_applyFontAttribute( const ::comphelper::NamedValueCollection& _rAttrValues, const char* _pAttributeName, + const uno::Reference<report::XReportControlFormat >& _rxReportControlFormat, + void (SAL_CALL report::XReportControlFormat::*pSetter)( const OUString& ) ) + { + OUString aAttributeValue; + if ( _rAttrValues.get_ensureType( _pAttributeName, aAttributeValue ) ) + (_rxReportControlFormat.get()->*pSetter)( aAttributeValue ); + } + + + void lcl_applyFontAttribute( const ::comphelper::NamedValueCollection& _rAttrValues, const char* _pAttributeName, + const uno::Reference<report::XReportControlFormat >& _rxReportControlFormat, + void (SAL_CALL report::XReportControlFormat::*pSetter)( const lang::Locale& ) ) + { + lang::Locale aAttributeValue; + if ( _rAttrValues.get_ensureType( _pAttributeName, aAttributeValue ) ) + (_rxReportControlFormat.get()->*pSetter)( aAttributeValue ); + } +} + + +bool openCharDialog( const uno::Reference<report::XReportControlFormat >& _rxReportControlFormat, + const uno::Reference< awt::XWindow>& _rxParentWindow, uno::Sequence< beans::NamedValue >& _out_rNewValues ) +{ + OSL_PRECOND( _rxReportControlFormat.is() && _rxParentWindow.is(), "openCharDialog: invalid parameters!" ); + if ( !_rxReportControlFormat.is() || !_rxParentWindow.is() ) + return false; + + _out_rNewValues = uno::Sequence< beans::NamedValue >(); + + + // UNO->ItemSet + static SfxItemInfo aItemInfos[] = + { + { XATTR_FILLSTYLE, true }, + { XATTR_FILLCOLOR, true }, + { XATTR_FILLGRADIENT, true }, + { XATTR_FILLHATCH, true }, + { XATTR_FILLBITMAP, true }, + { XATTR_FILLTRANSPARENCE, true }, + { XATTR_GRADIENTSTEPCOUNT, true }, + { XATTR_FILLBMP_TILE, true }, + { XATTR_FILLBMP_POS, true }, + { XATTR_FILLBMP_SIZEX, true }, + { XATTR_FILLBMP_SIZEY, true }, + { XATTR_FILLFLOATTRANSPARENCE, true }, + { XATTR_SECONDARYFILLCOLOR, true }, + { XATTR_FILLBMP_SIZELOG, true }, + { XATTR_FILLBMP_TILEOFFSETX, true }, + { XATTR_FILLBMP_TILEOFFSETY, true }, + { XATTR_FILLBMP_STRETCH, true }, + { XATTR_FILLBMP_POSOFFSETX, true }, + { XATTR_FILLBMP_POSOFFSETY, true }, + { XATTR_FILLBACKGROUND, true }, + + { SID_ATTR_CHAR_FONT, true }, + { SID_ATTR_CHAR_FONTHEIGHT, true }, + { SID_ATTR_CHAR_LANGUAGE, true }, + { SID_ATTR_CHAR_POSTURE, true }, + { SID_ATTR_CHAR_WEIGHT, true }, + { SID_ATTR_CHAR_SHADOWED, true }, + { SID_ATTR_CHAR_WORDLINEMODE, true }, + { SID_ATTR_CHAR_CONTOUR, true }, + { SID_ATTR_CHAR_STRIKEOUT, true }, + { SID_ATTR_CHAR_UNDERLINE, true }, + { SID_ATTR_CHAR_COLOR, true }, + { SID_ATTR_CHAR_KERNING, true }, + { SID_ATTR_CHAR_CASEMAP, true }, + { SID_ATTR_CHAR_ESCAPEMENT, true }, + { SID_ATTR_CHAR_FONTLIST, true }, + { SID_ATTR_CHAR_AUTOKERN, true }, + { SID_COLOR_TABLE, true }, + { SID_ATTR_FLASH, true }, + { SID_ATTR_CHAR_EMPHASISMARK, true }, + { SID_ATTR_CHAR_TWO_LINES, true }, + { SID_ATTR_CHAR_ROTATED, true }, + { SID_ATTR_CHAR_SCALEWIDTH, true }, + { SID_ATTR_CHAR_RELIEF, true }, + { SID_ATTR_CHAR_HIDDEN, true }, + { SID_ATTR_BRUSH, true }, + { SID_ATTR_ALIGN_HOR_JUSTIFY, true }, + { SID_ATTR_ALIGN_VER_JUSTIFY, true }, + + // Asian + { SID_ATTR_CHAR_CJK_FONT, true }, + { SID_ATTR_CHAR_CJK_FONTHEIGHT, true }, + { SID_ATTR_CHAR_CJK_LANGUAGE, true }, + { SID_ATTR_CHAR_CJK_POSTURE, true }, + { SID_ATTR_CHAR_CJK_WEIGHT, true }, + // Complex + { SID_ATTR_CHAR_CTL_FONT, true }, + { SID_ATTR_CHAR_CTL_FONTHEIGHT, true }, + { SID_ATTR_CHAR_CTL_LANGUAGE, true }, + { SID_ATTR_CHAR_CTL_POSTURE, true }, + { SID_ATTR_CHAR_CTL_WEIGHT, true } + }; + ::std::unique_ptr<FontList> pFontList(new FontList(Application::GetDefaultDevice())); + XColorListRef pColorList( XColorList::CreateStdColorList() ); + 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 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 SvxFontItem(ITEMID_FONT), + new SvxFontHeightItem(240,100,ITEMID_FONTHEIGHT), + new SvxLanguageItem(LANGUAGE_GERMAN,ITEMID_LANGUAGE), + new SvxPostureItem(ITALIC_NONE,ITEMID_POSTURE), + new SvxWeightItem(WEIGHT_NORMAL,ITEMID_WEIGHT), + + new SvxShadowedItem(false,ITEMID_SHADOWED), + new SvxWordLineModeItem(false,ITEMID_WORDLINEMODE), + new SvxContourItem(false,ITEMID_CONTOUR), + new SvxCrossedOutItem(STRIKEOUT_NONE,ITEMID_CROSSEDOUT), + new SvxUnderlineItem(LINESTYLE_NONE,ITEMID_UNDERLINE), + + new SvxColorItem(ITEMID_COLOR), + new SvxKerningItem(0,ITEMID_KERNING), + new SvxCaseMapItem(SvxCaseMap::NotMapped,ITEMID_CASEMAP), + new SvxEscapementItem(ITEMID_ESCAPEMENT), + new SvxFontListItem(pFontList.get(),ITEMID_FONTLIST), + new SvxAutoKernItem(false,ITEMID_AUTOKERN), + new SvxColorListItem(pColorList.get(),ITEMID_COLOR_TABLE), + new SvxBlinkItem(false,ITEMID_BLINK), + new SvxEmphasisMarkItem(FontEmphasisMark::NONE,ITEMID_EMPHASISMARK), + new SvxTwoLinesItem(true,0,0,ITEMID_TWOLINES), + new SvxCharRotateItem(0,false,ITEMID_CHARROTATE), + new SvxCharScaleWidthItem(100,ITEMID_CHARSCALE_W), + new SvxCharReliefItem(FontRelief::NONE,ITEMID_CHARRELIEF), + new SvxCharHiddenItem(false,ITEMID_CHARHIDDEN), + new SvxBrushItem(ITEMID_BRUSH), + new SvxHorJustifyItem(ITEMID_HORJUSTIFY), + new SvxVerJustifyItem(ITEMID_VERJUSTIFY), +// Asian + new SvxFontItem(ITEMID_FONT_ASIAN), + new SvxFontHeightItem(240,100,ITEMID_FONTHEIGHT_ASIAN), + new SvxLanguageItem(LANGUAGE_GERMAN,ITEMID_LANGUAGE_ASIAN), + new SvxPostureItem(ITALIC_NONE,ITEMID_POSTURE_ASIAN), + new SvxWeightItem(WEIGHT_NORMAL,ITEMID_WEIGHT_ASIAN), +// Complex + new SvxFontItem(ITEMID_FONT_COMPLEX), + new SvxFontHeightItem(240,100,ITEMID_FONTHEIGHT_COMPLEX), + new SvxLanguageItem(LANGUAGE_GERMAN,ITEMID_LANGUAGE_COMPLEX), + new SvxPostureItem(ITALIC_NONE,ITEMID_POSTURE_COMPLEX), + new SvxWeightItem(WEIGHT_NORMAL,ITEMID_WEIGHT_COMPLEX) + + }; + + OSL_ASSERT( pDefaults.size() == SAL_N_ELEMENTS(aItemInfos) ); + + static const sal_uInt16 pRanges[] = + { + XATTR_FILL_FIRST, ITEMID_WEIGHT_COMPLEX, + 0 + }; + + SfxItemPool* pPool( new SfxItemPool("ReportCharProperties", XATTR_FILL_FIRST,ITEMID_WEIGHT_COMPLEX, aItemInfos, &pDefaults) ); + // not needed for font height pPool->SetDefaultMetric( MapUnit::Map100thMM ); // ripped, don't understand why + pPool->FreezeIdRanges(); // the same + bool bSuccess = false; + try + { + ::std::unique_ptr<SfxItemSet> pDescriptor( new SfxItemSet( *pPool, pRanges ) ); + lcl_CharPropertiesToItems( _rxReportControlFormat, *pDescriptor ); + + { // want the dialog to be destroyed before our set + ORptPageDialog aDlg(Application::GetFrameWeld(_rxParentWindow), pDescriptor.get(), "CharDialog"); + uno::Reference< report::XShape > xShape( _rxReportControlFormat, uno::UNO_QUERY ); + if ( xShape.is() ) + aDlg.RemoveTabPage("background"); + bSuccess = aDlg.run() == RET_OK; + if ( bSuccess ) + { + lcl_itemsToCharProperties( lcl_getReportControlFont( _rxReportControlFormat,WESTERN ), + lcl_getReportControlFont( _rxReportControlFormat,ASIAN ), + lcl_getReportControlFont( _rxReportControlFormat,COMPLEX ), *aDlg.GetOutputItemSet(), _out_rNewValues ); + } + } + } + catch(uno::Exception&) + { + DBG_UNHANDLED_EXCEPTION("reportdesign"); + } + + SfxItemPool::Free(pPool); + for (SfxPoolItem* pDefault : pDefaults) + delete pDefault; + + return bSuccess; +} + +bool openAreaDialog( const uno::Reference<report::XShape >& _xShape,const uno::Reference< awt::XWindow>& _rxParentWindow ) +{ + OSL_PRECOND( _xShape.is() && _rxParentWindow.is(), "openAreaDialog: invalid parameters!" ); + if ( !_xShape.is() || !_rxParentWindow.is() ) + return false; + + std::shared_ptr<rptui::OReportModel> pModel = ::reportdesign::OReportDefinition::getSdrModel(_xShape->getSection()->getReportDefinition()); + + weld::Window* pParent = Application::GetFrameWeld(_rxParentWindow); + + bool bSuccess = false; + try + { + SfxItemPool& rItemPool = pModel->GetItemPool(); + ::std::unique_ptr<SfxItemSet> pDescriptor( new SfxItemSet( rItemPool, {{rItemPool.GetFirstWhich(),rItemPool.GetLastWhich()}} ) ); + lcl_fillShapeToItems(_xShape,*pDescriptor); + + { // want the dialog to be destroyed before our set + SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create(); + ScopedVclPtr<AbstractSvxAreaTabDialog> pDialog(pFact->CreateSvxAreaTabDialog(pParent, pDescriptor.get(), pModel.get(), true)); + if ( RET_OK == pDialog->Execute() ) + { + bSuccess = true; + lcl_fillItemsToShape(_xShape,*pDialog->GetOutputItemSet()); + } + } + } + catch(uno::Exception&) + { + DBG_UNHANDLED_EXCEPTION("reportdesign"); + } + + return bSuccess; +} + + +void applyCharacterSettings( const uno::Reference< report::XReportControlFormat >& _rxReportControlFormat, const uno::Sequence< beans::NamedValue >& _rSettings ) +{ + ::comphelper::NamedValueCollection aSettings( _rSettings ); + + try + { + awt::FontDescriptor aAwtFont; + if ( aSettings.get( "Font" ) >>= aAwtFont ) + { + OUString sTemp = aAwtFont.Name; + aAwtFont.Name.clear(); // hack to + _rxReportControlFormat->setFontDescriptor( aAwtFont ); + _rxReportControlFormat->setCharFontName( sTemp ); + } + if ( aSettings.get( "FontAsian" ) >>= aAwtFont ) + { + OUString sTemp = aAwtFont.Name; + aAwtFont.Name.clear(); // hack to + _rxReportControlFormat->setFontDescriptorAsian( aAwtFont ); + _rxReportControlFormat->setCharFontNameAsian( sTemp ); + } + if ( aSettings.get( "FontComplex" ) >>= aAwtFont ) + { + OUString sTemp = aAwtFont.Name; + aAwtFont.Name.clear(); // hack to + _rxReportControlFormat->setFontDescriptorComplex( aAwtFont ); + _rxReportControlFormat->setCharFontNameComplex( sTemp ); + } + + lcl_applyFontAttribute( aSettings, PROPERTY_CHARSHADOWED, _rxReportControlFormat, &report::XReportControlFormat::setCharShadowed ); + lcl_applyFontAttribute( aSettings, PROPERTY_CHARCONTOURED, _rxReportControlFormat, &report::XReportControlFormat::setCharContoured ); + lcl_applyFontAttribute( aSettings, PROPERTY_CHARUNDERLINECOLOR, _rxReportControlFormat, &report::XReportControlFormat::setCharUnderlineColor ); + lcl_applyFontAttribute( aSettings, PROPERTY_PARAADJUST, _rxReportControlFormat, &report::XReportControlFormat::setParaAdjust ); + lcl_applyFontAttribute( aSettings, PROPERTY_VERTICALALIGN, _rxReportControlFormat, &report::XReportControlFormat::setVerticalAlign ); + lcl_applyFontAttribute( aSettings, PROPERTY_CHARRELIEF, _rxReportControlFormat, &report::XReportControlFormat::setCharRelief ); + lcl_applyFontAttribute( aSettings, PROPERTY_CHARHIDDEN, _rxReportControlFormat, &report::XReportControlFormat::setCharHidden ); + lcl_applyFontAttribute( aSettings, PROPERTY_CHARAUTOKERNING, _rxReportControlFormat, &report::XReportControlFormat::setCharAutoKerning ); + lcl_applyFontAttribute( aSettings, PROPERTY_CONTROLBACKGROUND, _rxReportControlFormat, &report::XReportControlFormat::setControlBackground ); + lcl_applyFontAttribute( aSettings, PROPERTY_CHARFLASH, _rxReportControlFormat, &report::XReportControlFormat::setCharFlash ); + lcl_applyFontAttribute( aSettings, PROPERTY_CHAREMPHASIS, _rxReportControlFormat, &report::XReportControlFormat::setCharEmphasis ); + lcl_applyFontAttribute( aSettings, PROPERTY_CHARCOMBINEISON, _rxReportControlFormat, &report::XReportControlFormat::setCharCombineIsOn ); + lcl_applyFontAttribute( aSettings, PROPERTY_CHARCOMBINEPREFIX, _rxReportControlFormat, &report::XReportControlFormat::setCharCombinePrefix ); + lcl_applyFontAttribute( aSettings, PROPERTY_CHARCOMBINESUFFIX, _rxReportControlFormat, &report::XReportControlFormat::setCharCombineSuffix ); + lcl_applyFontAttribute( aSettings, PROPERTY_CHARCOLOR, _rxReportControlFormat, &report::XReportControlFormat::setCharColor ); + lcl_applyFontAttribute( aSettings, PROPERTY_CHARKERNING, _rxReportControlFormat, &report::XReportControlFormat::setCharKerning ); + lcl_applyFontAttribute( aSettings, PROPERTY_CHARCASEMAP, _rxReportControlFormat, &report::XReportControlFormat::setCharCaseMap ); + lcl_applyFontAttribute( aSettings, PROPERTY_CHARLOCALE, _rxReportControlFormat, &report::XReportControlFormat::setCharLocale ); + lcl_applyFontAttribute( aSettings, PROPERTY_CHARESCAPEMENT, _rxReportControlFormat, &report::XReportControlFormat::setCharEscapement ); + lcl_applyFontAttribute( aSettings, PROPERTY_CHARESCAPEMENTHEIGHT, _rxReportControlFormat, &report::XReportControlFormat::setCharEscapementHeight ); + lcl_applyFontAttribute( aSettings, PROPERTY_CHARLOCALEASIAN, _rxReportControlFormat, &report::XReportControlFormat::setCharLocaleAsian ); + lcl_applyFontAttribute( aSettings, PROPERTY_CHARLOCALECOMPLEX, _rxReportControlFormat, &report::XReportControlFormat::setCharLocaleComplex ); + } + catch( const uno::Exception& ) + { + DBG_UNHANDLED_EXCEPTION("reportdesign"); + } +} + +void notifySystemWindow(vcl::Window const * _pWindow, vcl::Window* _pToRegister, const ::comphelper::mem_fun1_t<TaskPaneList,vcl::Window*>& rMemFunc) +{ + OSL_ENSURE(_pWindow,"Window can not be null!"); + SystemWindow* pSystemWindow = _pWindow ? _pWindow->GetSystemWindow() : nullptr; + if ( pSystemWindow ) + { + rMemFunc( pSystemWindow->GetTaskPaneList(), _pToRegister ); + } +} + +SdrObject* isOver(const tools::Rectangle& _rRect, SdrPage const & _rPage, SdrView const & _rView, bool _bAllObjects, SdrObject const * _pIgnore, sal_Int16 _nIgnoreType) +{ + SdrObject* pOverlappedObj = nullptr; + SdrObjListIter aIter(&_rPage,SdrIterMode::DeepNoGroups); + + while( !pOverlappedObj ) + { + SdrObject* pObjIter = aIter.Next(); + if( !pObjIter ) + break; + if ( _pIgnore != pObjIter + && (_bAllObjects || !_rView.IsObjMarked(pObjIter)) + && (dynamic_cast<OUnoObject*>(pObjIter) != nullptr || dynamic_cast<OOle2Obj*>(pObjIter) != nullptr)) + { + if (_nIgnoreType == ISOVER_IGNORE_CUSTOMSHAPES && pObjIter->GetObjIdentifier() == OBJ_CUSTOMSHAPE) + { + continue; + } + + if (dynamic_cast<OUnoObject*>(pObjIter) != nullptr || dynamic_cast<OOle2Obj*>(pObjIter) != nullptr) + { + tools::Rectangle aRect = _rRect.GetIntersection(pObjIter->GetLastBoundRect()); + if ( !aRect.IsEmpty() && (aRect.Left() != aRect.Right() && aRect.Top() != aRect.Bottom() ) ) + pOverlappedObj = pObjIter; + } + } + } + return pOverlappedObj; +} + +static bool checkArrayForOccurrence(SdrObject const * _pObjToCheck, std::unique_ptr<SdrUnoObj, SdrObjectFreeOp> _pIgnore[], int _nListLength) +{ + for(int i=0;i<_nListLength;i++) + { + SdrObject *pIgnore = _pIgnore[i].get(); + if (pIgnore == _pObjToCheck) + { + return true; + } + } + return false; +} + +SdrObject* isOver(const tools::Rectangle& _rRect,SdrPage const & _rPage,SdrView const & _rView,bool _bAllObjects, std::unique_ptr<SdrUnoObj, SdrObjectFreeOp> _pIgnoreList[], int _nIgnoreListLength) +{ + SdrObject* pOverlappedObj = nullptr; + SdrObjListIter aIter(&_rPage,SdrIterMode::DeepNoGroups); + + while( !pOverlappedObj ) + { + SdrObject* pObjIter = aIter.Next(); + if( !pObjIter ) + break; + if (checkArrayForOccurrence(pObjIter, _pIgnoreList, _nIgnoreListLength)) + { + continue; + } + + if ( (_bAllObjects || !_rView.IsObjMarked(pObjIter)) + && (dynamic_cast<OUnoObject*>(pObjIter) != nullptr || dynamic_cast<OOle2Obj*>(pObjIter) != nullptr) ) + { + tools::Rectangle aRect = _rRect.GetIntersection(pObjIter->GetLastBoundRect()); + if ( !aRect.IsEmpty() && (aRect.Left() != aRect.Right() && aRect.Top() != aRect.Bottom() ) ) + pOverlappedObj = pObjIter; + } + } + return pOverlappedObj; +} + + +SdrObject* isOver(SdrObject const * _pObj,SdrPage const & _rPage,SdrView const & _rView) +{ + SdrObject* pOverlappedObj = nullptr; + if (dynamic_cast<OUnoObject const *>(_pObj) != nullptr || dynamic_cast<OOle2Obj const *>(_pObj) != nullptr) // this doesn't need to be done for shapes + { + tools::Rectangle aRect = _pObj->GetCurrentBoundRect(); + pOverlappedObj = isOver(aRect,_rPage,_rView,false/*_bUnMarkedObjects*/,_pObj); + } + return pOverlappedObj; +} + + +uno::Sequence< OUString > getParameterNames( const uno::Reference< sdbc::XRowSet >& _rxRowSet ) +{ + uno::Sequence< OUString > aNames; + + try + { + uno::Reference< sdb::XParametersSupplier > xSuppParams( _rxRowSet, uno::UNO_QUERY_THROW ); + uno::Reference< container::XIndexAccess > xParams( xSuppParams->getParameters() ); + if ( xParams.is() ) + { + sal_Int32 count( xParams->getCount() ); + aNames.realloc( count ); + + uno::Reference< beans::XPropertySet > xParam; + OUString sParamName; + for ( sal_Int32 i=0; i<count; ++i ) + { + xParam.set( xParams->getByIndex(i), uno::UNO_QUERY_THROW ); + OSL_VERIFY( xParam->getPropertyValue( PROPERTY_NAME ) >>= sParamName ); + aNames[i] = sParamName; + } + } + } + catch( const uno::Exception& ) + { + DBG_UNHANDLED_EXCEPTION("reportdesign"); + } + + return aNames; +} + +tools::Rectangle getRectangleFromControl(SdrObject* _pControl) +{ + if (_pControl) + { + uno::Reference< report::XReportComponent > xComponent( _pControl->getUnoShape(), uno::UNO_QUERY); + if (xComponent.is()) + { + tools::Rectangle aRect(VCLPoint(xComponent->getPosition()),VCLSize(xComponent->getSize())); + aRect.setHeight(aRect.getHeight() + 1); + aRect.setWidth(aRect.getWidth() + 1); + return aRect; + } + } + return tools::Rectangle(); +} + +// check overlapping +void correctOverlapping(SdrObject* _pControl,OReportSection const & _aReportSection,bool _bInsert) +{ + OSectionView& rSectionView = _aReportSection.getSectionView(); + uno::Reference< report::XReportComponent> xComponent(_pControl->getUnoShape(),uno::UNO_QUERY); + tools::Rectangle aRect = getRectangleFromControl(_pControl); + + bool bOverlapping = true; + while ( bOverlapping ) + { + SdrObject* pOverlappedObj = isOver(aRect,*_aReportSection.getPage(),rSectionView,true, _pControl); + bOverlapping = pOverlappedObj != nullptr; + if ( bOverlapping ) + { + const tools::Rectangle& aLogicRect = pOverlappedObj->GetLogicRect(); + aRect.Move(0,aLogicRect.Top() + aLogicRect.getHeight() - aRect.Top()); + xComponent->setPositionY(aRect.Top()); + } + } + if (_bInsert) // now insert objects + rSectionView.InsertObjectAtView(_pControl,*rSectionView.GetSdrPageView(), SdrInsertFlags::ADDMARK); +} + +void setZoomFactor(const Fraction& _aZoom, vcl::Window& _rWindow) +{ + MapMode aMapMode( _rWindow.GetMapMode() ); + aMapMode.SetScaleX(_aZoom); + aMapMode.SetScaleY(_aZoom); + _rWindow.SetMapMode(aMapMode); +} + +bool openDialogFormula_nothrow( OUString& _in_out_rFormula + , const css::uno::Reference< css::uno::XComponentContext >& _xContext + , const uno::Reference< awt::XWindow>& _xInspectorWindow + , const css::uno::Reference < css::beans::XPropertySet >& _xRowSet + ) +{ + OSL_PRECOND( _xInspectorWindow.is(), "openDialogFormula_nothrow: invalid parameters!" ); + if ( !_xInspectorWindow.is() ) + return false; + bool bSuccess = false; + ::dbtools::SQLExceptionInfo aErrorInfo; + uno::Reference< awt::XWindow > xInspectorWindow; + uno::Reference< lang::XMultiComponentFactory > xFactory; + uno::Reference<lang::XMultiServiceFactory> xServiceFactory; + try + { + xFactory = _xContext->getServiceManager(); + xServiceFactory.set(xFactory,uno::UNO_QUERY); + + uno::Reference< report::meta::XFunctionManager> xMgr(xFactory->createInstanceWithContext("org.libreoffice.report.pentaho.SOFunctionManager",_xContext),uno::UNO_QUERY); + if ( xMgr.is() ) + { + auto pFormulaManager = std::make_shared<FunctionManager>(xMgr); + ReportFormula aFormula( _in_out_rFormula ); + + LanguageTag aLangTag(LANGUAGE_SYSTEM); + CharClass aCC(_xContext, aLangTag); + svl::SharedStringPool aStringPool(aCC); + + FormulaDialog aDlg( + Application::GetFrameWeld(_xInspectorWindow), xServiceFactory, pFormulaManager, + aFormula.getUndecoratedContent(), _xRowSet, aStringPool); + + bSuccess = aDlg.run() == RET_OK; + if ( bSuccess ) + { + OUString sFormula = aDlg.getCurrentFormula(); + if ( sFormula[0] == '=' ) + _in_out_rFormula = "rpt:" + sFormula.copy(1); + else + _in_out_rFormula = "rpt:" + sFormula; + } + } + } + catch (const sdb::SQLContext& e) { aErrorInfo = e; } + catch (const sdbc::SQLWarning& e) { aErrorInfo = e; } + catch (const sdbc::SQLException& e) { aErrorInfo = e; } + catch( const uno::Exception& ) + { + TOOLS_WARN_EXCEPTION( "reportdesign", "GeometryHandler::impl_dialogFilter_nothrow" ); + } + + if ( aErrorInfo.isValid() ) + ::dbtools::showError( aErrorInfo, xInspectorWindow, _xContext ); + + return bSuccess; +} + +} // namespace rptui + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/reportdesign/source/ui/misc/rptuiservices.cxx b/reportdesign/source/ui/misc/rptuiservices.cxx new file mode 100644 index 000000000..622d45add --- /dev/null +++ b/reportdesign/source/ui/misc/rptuiservices.cxx @@ -0,0 +1,64 @@ +/* -*- 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 <cppuhelper/factory.hxx> +#include <cppuhelper/implementationentry.hxx> +#include <ReportController.hxx> +#include <statusbarcontroller.hxx> +#include <DefaultInspection.hxx> +#include <ReportComponentHandler.hxx> +#include <GeometryHandler.hxx> +#include <DataProviderHandler.hxx> + +/********************************************************************************************/ + +using namespace ::rptui; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::registry; + + +// registry functions +namespace +{ + +cppu::ImplementationEntry const entries[] = { + { &OReportController::create, &OReportController::getImplementationName_Static, &OReportController::getSupportedServiceNames_Static, + &cppu::createSingleComponentFactory, nullptr, 0 }, + { &OStatusbarController::create, &OStatusbarController::getImplementationName_Static, &OStatusbarController::getSupportedServiceNames_Static, + &cppu::createSingleComponentFactory, nullptr, 0 }, + { &DefaultComponentInspectorModel::create, &DefaultComponentInspectorModel::getImplementationName_Static, &DefaultComponentInspectorModel::getSupportedServiceNames_static, + &cppu::createSingleComponentFactory, nullptr, 0 }, + { &ReportComponentHandler::create, &ReportComponentHandler::getImplementationName_Static, &ReportComponentHandler::getSupportedServiceNames_static, + &cppu::createSingleComponentFactory, nullptr, 0 }, + { &GeometryHandler::create, &GeometryHandler::getImplementationName_Static, &GeometryHandler::getSupportedServiceNames_static, + &cppu::createSingleComponentFactory, nullptr, 0 }, + { &DataProviderHandler::create, &DataProviderHandler::getImplementationName_Static, &DataProviderHandler::getSupportedServiceNames_static, + &cppu::createSingleComponentFactory, nullptr, 0 }, + { nullptr, nullptr, nullptr, nullptr, nullptr, 0 } +}; +} + +extern "C" SAL_DLLPUBLIC_EXPORT void * rptui_component_getFactory( + char const * implName, void * serviceManager, void * registryKey) +{ + return cppu::component_getFactoryHelper( + implName, serviceManager, registryKey, entries); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/reportdesign/source/ui/misc/statusbarcontroller.cxx b/reportdesign/source/ui/misc/statusbarcontroller.cxx new file mode 100644 index 000000000..bae4a793a --- /dev/null +++ b/reportdesign/source/ui/misc/statusbarcontroller.cxx @@ -0,0 +1,230 @@ +/* -*- 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 <statusbarcontroller.hxx> + +#include <cppuhelper/supportsservice.hxx> +#include <comphelper/types.hxx> +#include <svx/zoomsliderctrl.hxx> +#include <svx/zoomctrl.hxx> +#include <svx/svxids.hrc> +#include <sfx2/zoomitem.hxx> +#include <svx/zoomslideritem.hxx> + +#include <vcl/svapp.hxx> +#include <vcl/status.hxx> +#include <osl/mutex.hxx> +#include <toolkit/helper/vclunohelper.hxx> +#include <com/sun/star/awt/XWindow.hpp> +#include <com/sun/star/beans/PropertyValue.hpp> + +namespace rptui +{ + using namespace svt; + using namespace com::sun::star::uno; + using namespace com::sun::star::beans; + using namespace com::sun::star::lang; + using namespace ::com::sun::star::frame; + using namespace ::com::sun::star::util; + +OUString SAL_CALL OStatusbarController::getImplementationName() +{ + return getImplementationName_Static(); +} + +OUString OStatusbarController::getImplementationName_Static() +{ + return "com.sun.star.report.comp.StatusbarController"; +} + +Sequence< OUString> OStatusbarController::getSupportedServiceNames_Static() +{ + Sequence<OUString> aSupported { "com.sun.star.frame.StatusbarController" }; + return aSupported; +} + +sal_Bool SAL_CALL OStatusbarController::supportsService( const OUString& ServiceName ) +{ + return cppu::supportsService(this, ServiceName); +} + +Sequence< OUString> SAL_CALL OStatusbarController::getSupportedServiceNames() +{ + return getSupportedServiceNames_Static(); +} + +Reference< XInterface > OStatusbarController::create(Reference< XComponentContext > const & xContext) +{ + return *(new OStatusbarController(xContext)); +} +IMPLEMENT_FORWARD_XINTERFACE2(OStatusbarController, ::svt::StatusbarController,OStatusbarController_BASE) + +OStatusbarController::OStatusbarController(const Reference< XComponentContext >& rxContext) +: ::svt::StatusbarController(rxContext, Reference< XFrame >(), OUString(), 0) +,m_nSlotId(0) +,m_nId(1) +{ +} + +void SAL_CALL OStatusbarController::initialize( const Sequence< Any >& _rArguments ) +{ + StatusbarController::initialize(_rArguments); + SolarMutexGuard aSolarMutexGuard; + ::osl::MutexGuard aGuard(m_aMutex); + + VclPtr< StatusBar > pStatusBar = static_cast<StatusBar*>(VCLUnoHelper::GetWindow(m_xParentWindow).get()); + if ( !pStatusBar ) + return; + + const sal_uInt16 nCount = pStatusBar->GetItemCount(); + for (sal_uInt16 nPos = 0; nPos < nCount; ++nPos) + { + const sal_uInt16 nItemId = pStatusBar->GetItemId(nPos); + if ( pStatusBar->GetItemCommand(nItemId) == m_aCommandURL ) + { + m_nId = nItemId; + break; + } + } + + SfxStatusBarControl *pController = nullptr; + if ( m_aCommandURL == ".uno:ZoomSlider" ) + { + m_nSlotId = SID_ATTR_ZOOMSLIDER; + pController = new SvxZoomSliderControl(m_nSlotId,m_nId,*pStatusBar); + } + else if ( m_aCommandURL == ".uno:Zoom" ) + { + m_nSlotId = SID_ATTR_ZOOM; + pController = new SvxZoomStatusBarControl(m_nSlotId,m_nId,*pStatusBar); + } + + if ( pController ) + { + m_rController.set( pController ); + if ( m_rController.is() ) + { + m_rController->initialize(_rArguments); + m_rController->update(); + } + } + + addStatusListener(m_aCommandURL); + update(); +} +// XStatusListener +void SAL_CALL OStatusbarController::statusChanged( const FeatureStateEvent& _aEvent) +{ + SolarMutexGuard aSolarGuard; + ::osl::MutexGuard aGuard(m_aMutex); + + if ( !m_rController.is() ) + return; + + if ( m_aCommandURL == ".uno:ZoomSlider" ) + { + Sequence< PropertyValue > aSeq; + if ( (_aEvent.State >>= aSeq) && aSeq.getLength() == 2 ) + { + SvxZoomSliderItem aZoomSlider(100,20,400); + aZoomSlider.PutValue(_aEvent.State, 0); + static_cast<SvxZoomSliderControl*>(m_rController.get())->StateChanged(m_nSlotId,SfxItemState::DEFAULT,&aZoomSlider); + } + } + else if ( m_aCommandURL == ".uno:Zoom" ) + { + Sequence< PropertyValue > aSeq; + if ( (_aEvent.State >>= aSeq) && aSeq.getLength() == 3 ) + { + SvxZoomItem aZoom; + aZoom.PutValue(_aEvent.State, 0 ); + static_cast<SvxZoomStatusBarControl*>(m_rController.get())->StateChanged(m_nSlotId,SfxItemState::DEFAULT,&aZoom); + } + } +} + +// XStatusbarController +sal_Bool SAL_CALL OStatusbarController::mouseButtonDown(const css::awt::MouseEvent& _aEvent) +{ + return m_rController.is() && m_rController->mouseButtonDown(_aEvent); +} + +sal_Bool SAL_CALL OStatusbarController::mouseMove( const css::awt::MouseEvent& _aEvent) +{ + return m_rController.is() && m_rController->mouseMove(_aEvent); +} + +sal_Bool SAL_CALL OStatusbarController::mouseButtonUp( const css::awt::MouseEvent& _aEvent) +{ + return m_rController.is() && m_rController->mouseButtonUp(_aEvent); +} + +void SAL_CALL OStatusbarController::command( + const css::awt::Point& aPos, + ::sal_Int32 nCommand, + sal_Bool bMouseEvent, + const css::uno::Any& aData ) +{ + if ( m_rController.is() ) + m_rController->command( aPos, nCommand, bMouseEvent, aData ); +} + +void SAL_CALL OStatusbarController::paint( + const css::uno::Reference< css::awt::XGraphics >& xGraphics, + const css::awt::Rectangle& rOutputRectangle, + ::sal_Int32 nStyle ) +{ + if ( m_rController.is() ) + m_rController->paint( xGraphics, rOutputRectangle, nStyle ); +} + +void SAL_CALL OStatusbarController::click( + const css::awt::Point& aPos ) +{ + if ( m_rController.is() ) + m_rController->click( aPos ); +} + +void SAL_CALL OStatusbarController::doubleClick( + const css::awt::Point& aPos ) +{ + if ( m_rController.is() ) + m_rController->doubleClick( aPos ); +} + +void SAL_CALL OStatusbarController::update() +{ + ::svt::StatusbarController::update(); + if ( m_rController.is() ) + m_rController->update(); +} + +// XComponent +void SAL_CALL OStatusbarController::dispose() +{ + if ( m_rController.is() ) + ::comphelper::disposeComponent( m_rController ); + + svt::StatusbarController::dispose(); +} + +} // rptui + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/reportdesign/source/ui/report/DesignView.cxx b/reportdesign/source/ui/report/DesignView.cxx new file mode 100644 index 000000000..6332f8b49 --- /dev/null +++ b/reportdesign/source/ui/report/DesignView.cxx @@ -0,0 +1,685 @@ +/* -*- 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> + +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_eMode( DlgEdMode::Select ) + ,m_eActObj( OBJ_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() ) + ) + { + long nMinWidth = static_cast<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 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 long nTaskPaneSize = static_cast<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 = OBJ_NONE; + + m_aScrollWindow->SetMode(_eNewMode); +} + +void ODesignView::SetInsertObj( sal_uInt16 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() )); + SetFillColor( Application::GetSettings().GetStyleSettings().GetFaceColor() ); + SetTextFillColor( Application::GetSettings().GetStyleSettings().GetFaceColor() ); +} + +IMPL_LINK_NOARG( ODesignView, SplitHdl, SplitWindow*, void ) +{ + const Size aOutputSize = GetOutputSizePixel(); + const long nTest = aOutputSize.Width() * m_aSplitWin->GetItemSize(TASKPANE_ID) / 100; + long nMinWidth = static_cast<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 sal_uInt16 _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()); + sal_Int32 i = 0; + for(const auto& rxInterface : aSelection) + { + aSeq[i].set(rxInterface,uno::UNO_QUERY); + ++i; + } + 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..4dd537fae --- /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(long(CORNER_SPACE)); + aCornerSpace *= rRenderContext.GetMapMode().GetScaleX(); + const long nCornerSpace = 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(this, 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) ); + 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..92894cfcb --- /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::makeAny(_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( 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(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(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.get()); + 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); + } + } + } + } + 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..6ebc21915 --- /dev/null +++ b/reportdesign/source/ui/report/FormattedFieldBeautifier.cxx @@ -0,0 +1,179 @@ +/* -*- 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(0xffffffff) + { + } + + + Color FormattedFieldBeautifier::getTextColor() + { + if (m_nTextColor == Color(0xffffffff)) + { + 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 ) + { + OUString sDataField; + + try + { + uno::Reference< report::XFormattedField > xControlModel( _rxComponent, uno::UNO_QUERY ); + if ( xControlModel.is() ) + { + 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.get() ), 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::makeAny(_rText)); + // the text color + _xVclWindowPeer->setProperty(PROPERTY_TEXTCOLOR, uno::makeAny(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::makeAny(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); + 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..3bf9e9e07 --- /dev/null +++ b/reportdesign/source/ui/report/ReportController.cxx @@ -0,0 +1,4367 @@ +/* -*- 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/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 <cppuhelper/exc_hlp.hxx> +#include <unotools/confignode.hxx> + +#include <ReportControllerObserver.hxx> + +#define MAX_ROWS_FOR_PREVIEW 20 + +#define RPTUI_ID_LRSPACE XATTR_FILL_FIRST - 8 +#define RPTUI_ID_ULSPACE XATTR_FILL_FIRST - 7 +#define RPTUI_ID_PAGE XATTR_FILL_FIRST - 6 +#define RPTUI_ID_SIZE 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 XATTR_FILL_FIRST - 1 +#define RPTUI_ID_METRIC XATTR_FILL_LAST + 1 + +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 getImplementationName_Static(); +} + + +OUString OReportController::getImplementationName_Static() +{ + return "com.sun.star.report.comp.ReportDesign"; +} + +Sequence< OUString> OReportController::getSupportedServiceNames_Static() +{ + Sequence<OUString> aSupported { "com.sun.star.sdb.ReportDesign" }; + return aSupported; +} + +Sequence< OUString> SAL_CALL OReportController::getSupportedServiceNames() +{ + return getSupportedServiceNames_Static(); +} + +Reference< XInterface > OReportController::create(Reference< XComponentContext > const & xContext) +{ + return *(new OReportController(xContext)); +} + +#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&) + { + OSL_FAIL("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); + for (size_t n = 0; n < nCount; ++n) + aSeq[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_DISTRIBUTION: + 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() == OBJ_OLE2; + break; + case SID_FM_FIXEDTEXT: + aReturn.bEnabled = isEditable(); + aReturn.bChecked = getDesignView()->GetInsertObj() == OBJ_DLG_FIXEDTEXT; + break; + case SID_INSERT_HFIXEDLINE: + aReturn.bEnabled = isEditable(); + aReturn.bChecked = getDesignView()->GetInsertObj() == OBJ_DLG_HFIXEDLINE; + break; + case SID_INSERT_VFIXEDLINE: + aReturn.bEnabled = isEditable(); + aReturn.bChecked = getDesignView()->GetInsertObj() == OBJ_DLG_VFIXEDLINE; + break; + case SID_FM_EDIT: + aReturn.bEnabled = isEditable(); + aReturn.bChecked = getDesignView()->GetInsertObj() == OBJ_DLG_FORMATTEDFIELD; + break; + case SID_FM_IMAGECONTROL: + aReturn.bEnabled = isEditable(); + aReturn.bChecked = getDesignView()->GetInsertObj() == OBJ_DLG_IMAGECONTROL; + 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_DISTRIBUTION: + { + OSectionView* pSectionView = getCurrentSectionView(); + if ( pSectionView ) + pSectionView->DistributeMarkedObjects(getFrameWeld()); + } + 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(OBJ_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(OBJ_DLG_FORMATTEDFIELD); + break; + case SID_SELECT_ALL_LABELS: + getDesignView()->SelectAll(OBJ_DLG_FIXEDTEXT); + 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::makeAny(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.get(),xFunction); + const OUString sUndoAction = RptResId(RID_STR_UNDO_REMOVE_FUNCTION); + UndoContext aUndoContext( getUndoManager(), sUndoAction ); + xFunctions->removeByIndex(nIndex); + select(uno::makeAny(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( OBJ_OLE2); + createDefaultControl(aArgs); + InvalidateAll(); + break; + case SID_FM_FIXEDTEXT: + getDesignView()->SetMode( DlgEdMode::Insert ); + getDesignView()->SetInsertObj( OBJ_DLG_FIXEDTEXT ); + createDefaultControl(aArgs); + InvalidateAll(); + break; + case SID_INSERT_HFIXEDLINE: + getDesignView()->SetMode( DlgEdMode::Insert ); + getDesignView()->SetInsertObj( OBJ_DLG_HFIXEDLINE ); + createDefaultControl(aArgs); + InvalidateAll(); + break; + case SID_INSERT_VFIXEDLINE: + getDesignView()->SetMode( DlgEdMode::Insert ); + getDesignView()->SetInsertObj( OBJ_DLG_VFIXEDLINE ); + createDefaultControl(aArgs); + InvalidateAll(); + break; + case SID_FM_EDIT: + getDesignView()->SetMode( DlgEdMode::Insert ); + getDesignView()->SetInsertObj( OBJ_DLG_FORMATTEDFIELD ); + createDefaultControl(aArgs); + InvalidateAll(); + break; + case SID_FM_IMAGECONTROL: + getDesignView()->SetMode( DlgEdMode::Insert ); + getDesignView()->SetInsertObj( OBJ_DLG_IMAGECONTROL ); + 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; + OUString sType = aUrl.Complete.getToken(0,'.',nIndex); + if ( nIndex == -1 || sType.isEmpty() ) + { + switch(_nId) + { + case SID_DRAWTBX_CS_SYMBOL: + sType = "smiley"; + break; + case SID_DRAWTBX_CS_ARROW: + sType = "left-right-arrow"; + break; + case SID_DRAWTBX_CS_FLOWCHART: + sType = "flowchart-internal-storage"; + break; + case SID_DRAWTBX_CS_CALLOUT: + sType = "round-rectangular-callout"; + break; + case SID_DRAWTBX_CS_STAR: + sType = "star5"; + break; + default: + sType = "diamond"; + } + } + else + sType = aUrl.Complete.getToken(0,'.',nIndex); + + getDesignView()->SetInsertObj( OBJ_CUSTOMSHAPE ,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::makeAny(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::makeAny(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::makeAny(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::makeAny(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.get(), *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() ); + + ::comphelper::NamedValueCollection aArgs(getModel()->getArgs()); + setMode(aArgs.getOrDefault("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 ) + { + uno::Sequence< beans::PropertyValue> aArgs(1); + aArgs[0].Value <<= pPage->getSection(); + executeUnChecked(SID_SELECT,aArgs); + } + } + 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); + uno::Sequence< beans::PropertyValue> aArgs; + executeUnChecked(SID_SELECT_REPORT,aArgs); + } + + 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:Distribution", SID_DISTRIBUTION, 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 OUStringLiteral s_sMenu[] = { + "private:resource/statusbar/statusbar" + ,"private:resource/toolbar/reportcontrols" + ,"private:resource/toolbar/drawbar" + ,"private:resource/toolbar/Formatting" + ,"private:resource/toolbar/alignmentbar" + ,"private:resource/toolbar/sectionalignmentbar" + ,"private:resource/toolbar/resizebar" + ,"private:resource/toolbar/sectionshrinkbar" + }; + for (const auto & i : s_sMenu) + { + _xLayoutManager->createElement( i ); + _xLayoutManager->requestElement( 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_getNonVisbleGroupsBefore( 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,const OUString& _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_getNonVisbleGroupsBefore(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_getNonVisbleGroupsBefore(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 }, + { XATTR_FILLSTYLE, true }, + { XATTR_FILLCOLOR, true }, + { XATTR_FILLGRADIENT, true }, + { XATTR_FILLHATCH, true }, + { XATTR_FILLBITMAP, true }, + { XATTR_FILLTRANSPARENCE, true }, + { XATTR_GRADIENTSTEPCOUNT, true }, + { XATTR_FILLBMP_TILE, true }, + { XATTR_FILLBMP_POS, true }, + { XATTR_FILLBMP_SIZEX, true }, + { XATTR_FILLBMP_SIZEY, true }, + { XATTR_FILLFLOATTRANSPARENCE, true }, + { XATTR_SECONDARYFILLCOLOR, true }, + { XATTR_FILLBMP_SIZELOG, true }, + { XATTR_FILLBMP_TILEOFFSETX, true }, + { XATTR_FILLBMP_TILEOFFSETY, true }, + { XATTR_FILLBMP_STRETCH, true }, + { XATTR_FILLBMP_POSOFFSETX, true }, + { XATTR_FILLBMP_POSOFFSETY, true }, + { XATTR_FILLBACKGROUND, true }, + { SID_ATTR_METRIC, true } + }; + + MeasurementSystem eSystem = SvtSysLocale().GetLocaleData().getMeasurementSystemEnum(); + FieldUnit eUserMetric = MeasurementSystem::Metric == eSystem ? FieldUnit::CM : FieldUnit::INCH; + static const sal_uInt16 pRanges[] = + { + RPTUI_ID_LRSPACE, XATTR_FILL_LAST, + SID_ATTR_METRIC,SID_ATTR_METRIC, + 0 + }; + 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 + { + ::std::unique_ptr<SfxItemSet> pDescriptor(new SfxItemSet(*pPool, pRanges)); + // fill it + if ( _xSection.is() ) + pDescriptor->Put(SvxBrushItem(::Color(_xSection->getBackColor()),RPTUI_ID_BRUSH)); + else + { + pDescriptor->Put(SvxSizeItem(RPTUI_ID_SIZE,VCLSize(getStyleProperty<awt::Size>(m_xReportDefinition,PROPERTY_PAPERSIZE)))); + pDescriptor->Put(SvxLRSpaceItem(getStyleProperty<sal_Int32>(m_xReportDefinition,PROPERTY_LEFTMARGIN) + ,getStyleProperty<sal_Int32>(m_xReportDefinition,PROPERTY_RIGHTMARGIN),0,0,RPTUI_ID_LRSPACE)); + pDescriptor->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)); + pDescriptor->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))); + pDescriptor->Put(aPageItem); + pDescriptor->Put(SvxBrushItem(::Color(getStyleProperty<sal_Int32>(m_xReportDefinition,PROPERTY_BACKCOLOR)),RPTUI_ID_BRUSH)); + } + } + + { // want the dialog to be destroyed before our set + ORptPageDialog aDlg( + getFrameWeld(), pDescriptor.get(),_xSection.is() + ? OUString("BackgroundDialog") + : OUString("PageDialog")); + if (aDlg.run() == RET_OK) + { + + // ItemSet->UNO + // UNO-properties + const SfxItemSet* pSet = aDlg.GetOutputItemSet(); + if ( _xSection.is() ) + { + const SfxPoolItem* pItem; + if ( SfxItemState::SET == pSet->GetItemState( RPTUI_ID_BRUSH,true,&pItem)) + _xSection->setBackColor(sal_Int32(static_cast<const SvxBrushItem*>(pItem)->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 ); + const SfxPoolItem* pItem = nullptr; + if ( SfxItemState::SET == pSet->GetItemState( RPTUI_ID_SIZE,true,&pItem)) + { + uno::Any aValue; + static_cast<const SvxSizeItem*>(pItem)->QueryValue(aValue); + xProp->setPropertyValue(PROPERTY_PAPERSIZE,aValue); + resetZoomType(); + } + + if ( SfxItemState::SET == pSet->GetItemState( RPTUI_ID_LRSPACE,true,&pItem)) + { + Any aValue; + static_cast<const SvxLRSpaceItem*>(pItem)->QueryValue(aValue,MID_L_MARGIN); + xProp->setPropertyValue(PROPERTY_LEFTMARGIN,aValue); + static_cast<const SvxLRSpaceItem*>(pItem)->QueryValue(aValue,MID_R_MARGIN); + xProp->setPropertyValue(PROPERTY_RIGHTMARGIN,aValue); + } + if ( SfxItemState::SET == pSet->GetItemState( RPTUI_ID_ULSPACE,true,&pItem)) + { + xProp->setPropertyValue(PROPERTY_TOPMARGIN,uno::makeAny(static_cast<const SvxULSpaceItem*>(pItem)->GetUpper())); + xProp->setPropertyValue(PROPERTY_BOTTOMMARGIN,uno::makeAny(static_cast<const SvxULSpaceItem*>(pItem)->GetLower())); + } + if ( SfxItemState::SET == pSet->GetItemState( RPTUI_ID_PAGE,true,&pItem)) + { + const SvxPageItem* pPageItem = static_cast<const SvxPageItem*>(pItem); + xProp->setPropertyValue(PROPERTY_ISLANDSCAPE,uno::makeAny(pPageItem->IsLandscape())); + xProp->setPropertyValue(PROPERTY_NUMBERINGTYPE,uno::makeAny(static_cast<sal_Int16>(pPageItem->GetNumType()))); + uno::Any aValue; + pPageItem->QueryValue(aValue,MID_PAGE_LAYOUT); + xProp->setPropertyValue(PROPERTY_PAGESTYLELAYOUT,aValue); + resetZoomType(); + } + if ( SfxItemState::SET == pSet->GetItemState( RPTUI_ID_BRUSH,true,&pItem)) + { + ::Color aBackColor = static_cast<const SvxBrushItem*>(pItem)->GetColor(); + xProp->setPropertyValue(PROPERTY_BACKTRANSPARENT,uno::makeAny(aBackColor == COL_TRANSPARENT)); + xProp->setPropertyValue(PROPERTY_BACKCOLOR,uno::makeAny(aBackColor)); + } + } + } + } + } + catch(const Exception&) + { + DBG_UNHANDLED_EXCEPTION("reportdesign"); + } + SfxItemPool::Free(pPool); + + 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().get(),_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<view::XSelectionChangeListener>( + [&aEvent] (uno::Reference<view::XSelectionChangeListener> const& xListener) { + return xListener->selectionChanged(aEvent); + }); +} + +void OReportController::executeMethodWithUndo(const char* pUndoStrId,const ::std::function<void(ODesignView *)>& _pMemfun) +{ + const OUString sUndoAction = RptResId(pUndoStrId); + UndoContext aUndoContext( getUndoManager(), sUndoAction ); + _pMemfun( getDesignView() ); + InvalidateFeature( SID_UNDO ); +} + +void OReportController::alignControlsWithUndo(const char* 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(const char* 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::makeAny( 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; + + Sequence< PropertyValue > aCommandArgs(1); + aCommandArgs[0].Name = "Value"; + aCommandArgs[0].Value = rCommandValue; + + executeUnChecked( aCommand, aCommandArgs ); + } + 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; + const OUString sTarget("_blank"); + Reference<XFrame> xFrame = m_xFrameLoader->findFrame(sTarget,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() ) + { + const char* 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 (!strcmp(pErrorId, RID_ERR_NO_COMMAND)) + { + if ( !m_bShowProperties ) + executeUnChecked(SID_SHOW_PROPERTYBROWSER,uno::Sequence< beans::PropertyValue>()); + + m_sLastActivePage = "Data"; + getDesignView()->setCurrentPage(m_sLastActivePage); + nCommand = SID_SELECT_REPORT; + } + else if ( getDesignView() && !getDesignView()->isAddFieldVisible() ) + { + nCommand = SID_FM_ADD_FIELD; + } + if ( nCommand ) + { + uno::Sequence< beans::PropertyValue> aArgs; + executeUnChecked(nCommand,aArgs); + } + } + } + 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.get(); +} + +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::makeAny( getConnection() ) ); + xRowSetProp->setPropertyValue( PROPERTY_APPLYFILTER, uno::makeAny( 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.get(), xRowSetProp, 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.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(),OBJ_DLG_IMAGECONTROL); + } + } + catch(const Exception&) + { + DBG_UNHANDLED_EXCEPTION("reportdesign"); + } +} + + +sal_Bool SAL_CALL OReportController::select( const Any& aSelection ) +{ + ::osl::MutexGuard aGuard( getMutex() ); + if ( getDesignView() ) + { + 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.realloc(1); + aElements[0] = 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::makeAny(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,sal_uInt16 _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 == OBJ_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 == OBJ_OLE2 || OBJ_DLG_SUBREPORT == _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(), + nLeftMargin, + 0, + nullptr, + nullptr, + _nObjectId, + SdrInventor::ReportDesign, + OBJ_DLG_FIXEDTEXT, + + // 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::makeAny( aFunctionFormula.getCompleteFormula() ) ); + } + + sal_Int32 nFormatKey = aMap.getUnpackedValueOrDefault(PROPERTY_FORMATKEY,sal_Int32(0)); + if ( nFormatKey && xInfo->hasPropertyByName(PROPERTY_FORMATKEY) ) + xUnoProp->setPropertyValue( PROPERTY_FORMATKEY, uno::makeAny( nFormatKey ) ); + + OUString sUrl = aMap.getUnpackedValueOrDefault(PROPERTY_IMAGEURL,OUString()); + if ( !sUrl.isEmpty() && xInfo->hasPropertyByName(PROPERTY_IMAGEURL) ) + xUnoProp->setPropertyValue( PROPERTY_IMAGEURL, uno::makeAny( sUrl ) ); + + pObj->CreateMediator(true); + + if ( _nObjectId == OBJ_DLG_FIXEDTEXT ) // special case for fixed text + xUnoProp->setPropertyValue(PROPERTY_LABEL,uno::makeAny(OUnoObject::GetDefaultName(pObj))); + else if ( _nObjectId == OBJ_DLG_VFIXEDLINE ) + { + 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::makeAny(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; + + sal_uInt16 nOBJID = 0; + 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 = OBJ_DLG_IMAGECONTROL; + break; + default: + nOBJID = OBJ_DLG_FORMATTEDFIELD; + break; + } + + if ( !nOBJID ) + 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(), + nLeftMargin, + 0, + xField, + xNumberFormats, + nOBJID, + SdrInventor::ReportDesign, + OBJ_DLG_FIXEDTEXT, + + // 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::makeAny(sDefaultName)); + + ReportFormula aFormula( ReportFormula::Field, sName ); + xUnoProp->setPropertyValue( PROPERTY_DATAFIELD, uno::makeAny( 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 == OBJ_DLG_FORMATTEDFIELD) // 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::makeAny( 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::makeAny(pPrevSection->getReportSection().getSection())); + else + select(uno::makeAny(m_xReportDefinition)); + } + else + { + getDesignView()->markSection(_bNext ? 0 : getDesignView()->getSectionCount() - 1); + pSection = getDesignView()->getMarkedSection(); + if ( pSection ) + select(uno::makeAny(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 OUString sKeyModifier("KeyModifier"); + const beans::PropertyValue* pIter = _aArgs.getConstArray(); + const beans::PropertyValue* pEnd = pIter + _aArgs.getLength(); + const beans::PropertyValue* pKeyModifier = ::std::find_if(pIter, pEnd, + [&sKeyModifier] (const beans::PropertyValue& x) -> bool { + return x.Name == sKeyModifier; + }); + 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; + const OUString sConfigName( "/org.openoffice.Office.ReportDesign" ); + const OUString sPropertyName( "UserData/Chart" ); + + try + { + ::utl::OConfigurationTreeRoot aConfiguration( + ::utl::OConfigurationTreeRoot::createWithComponentContext( m_xContext, sConfigName ) ); + + bool bChartEnabled = false; + 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(const char* 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() == OBJ_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() + }; + static const sal_uInt16 pRanges[] = + { + SID_ATTR_ZOOM,SID_ATTR_ZOOM, + 0 + }; + 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 + { + ::std::unique_ptr<SfxItemSet> pDescriptor(new SfxItemSet(*pPool, pRanges)); + // fill it + SvxZoomItem aZoomItem( m_eZoomType, m_nZoomValue, SID_ATTR_ZOOM ); + aZoomItem.SetValueSet(SvxZoomEnableFlags::N100|SvxZoomEnableFlags::WHOLEPAGE|SvxZoomEnableFlags::PAGEWIDTH); + pDescriptor->Put(aZoomItem); + + ScopedVclPtr<AbstractSvxZoomDialog> pDlg(pFact->CreateSvxZoomDialog(nullptr, *pDescriptor)); + 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"); + } + SfxItemPool::Free(pPool); + + 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 ); +} +/* 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..79afb9c04 --- /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.get(); + 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.get()); + 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..9eb402e84 --- /dev/null +++ b/reportdesign/source/ui/report/ReportSection.cxx @@ -0,0 +1,799 @@ +/* -*- 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 <svx/sdrpaintwindow.hxx> +#include <svx/unoshape.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/frame/XPopupMenuController.hpp> +#include <comphelper/propertyvalue.hxx> +#include <toolkit/awt/vclxmenu.hxx> +#include <toolkit/helper/convert.hxx> +#include <RptDef.hxx> +#include <SectionWindow.hxx> +#include <helpids.h> +#include <dlgedclip.hxx> +#include <rptui_slotid.hrc> + +#include <vcl/commandevent.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&) + { + OSL_FAIL("Exception caught!"); + } + + 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(this, 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.get()); + 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(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)) + { + SvxShape* pShape = comphelper::getUnoTunnelImplementation<SvxShape>( rCopy ); + SdrObject* pObject = pShape ? pShape->GetSdrObject() : nullptr; + 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&) + { + OSL_FAIL("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 sal_uInt16 _nObjectType) +{ + if ( !m_pView ) + return; + + if ( _nObjectType == OBJ_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::makeAny(comphelper::makePropertyValue("Value", OUString("report"))), + css::uno::makeAny(comphelper::makePropertyValue("Frame", xFrame)), + css::uno::makeAny(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; + + rtl::Reference<VCLXPopupMenu> xPopupMenu(new VCLXPopupMenu); + xMenuController->setPopupMenu(xPopupMenu.get()); + + Point aPos = _rCEvt.GetMousePosPixel(); + m_pView->EndAction(); + static_cast<PopupMenu*>(xPopupMenu->GetMenu())->Execute(this, aPos); + + 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(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(); + SvxShape* pShape = comphelper::getUnoTunnelImplementation<SvxShape>( xReportComponent ); + SdrObject* pObject = pShape ? pShape->GetSdrObject() : nullptr; + 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 &) + { + OSL_FAIL("Exception caught: 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(); + SfxItemSet aDest( + _pObj->getSdrModelFromSdrObject().GetItemPool(), + svl::Items< + // 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.Set( rSource ); + _pObj->SetMergedItemSet( aDest ); + sal_Int32 nAngle = pSourceObj->GetRotateAngle(); + if ( nAngle ) + { + double a = nAngle * F_PI18000; + _pObj->NbcRotate( _pObj->GetSnapRect().Center(), nAngle, sin( a ), cos( a ) ); + } + 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[0].Value <<= aDescriptor.createPropertyValueSequence(); + } + else + aValues = svx::OMultiColumnTransferable::extractDescriptor(aDropped); + + for(beans::PropertyValue & propVal : aValues) + { + uno::Sequence<beans::PropertyValue> aCurrent; + propVal.Value >>= aCurrent; + sal_Int32 nLength = aCurrent.getLength(); + if ( nLength ) + { + aCurrent.realloc(nLength + 3); + aCurrent[nLength].Name = PROPERTY_POSITION; + aCurrent[nLength++].Value <<= AWTPoint(aDropPos); + // give also the DND Action (Shift|Ctrl) Key to really say what we want + aCurrent[nLength].Name = "DNDAction"; + aCurrent[nLength++].Value <<= _rEvt.mnAction; + + aCurrent[nLength].Name = "Section"; + aCurrent[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..b0b619701 --- /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( sal_uInt16 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(long(REPORT_STARTMARKER_WIDTH)); + aStartWidth *= m_aViewsWindow->GetMapMode().GetScaleX(); + return sal_Int32(static_cast<long>(aStartWidth)); +} + +sal_Int32 OReportWindow::GetTotalWidth() const +{ + sal_Int32 nWidth = 0; + if ( !m_aViewsWindow->empty() ) + { + Fraction aStartWidth(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 = long(nPaperWidth * aZoom); + const Size aPageSize = LogicToPixel(Size(nPaperWidth,0)); + nWidth = aPageSize.Width() + long(aStartWidth); + } + return nWidth; +} + +void OReportWindow::Resize() +{ + Window::Resize(); + if ( m_aViewsWindow->empty() ) + return; + + const Size aTotalOutputSize = GetOutputSizePixel(); + Fraction aStartWidth(long(REPORT_STARTMARKER_WIDTH)*m_pView->getController().getZoomValue(),100); + + const Point aOffset = LogicToPixel(Point(SECTION_OFFSET, 0), MapMode(MapUnit::MapAppFont)); + Point aStartPoint(static_cast<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 long nTermp(m_aViewsWindow->getTotalHeight() + aPageSize.Height()); + long nSectionsHeight = ::std::max<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 sal_uInt16 _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<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<long>(Fraction(aSize.Height()*100,aHeight.Height())))); + } + break; + case SvxZoomType::PAGEWIDTH: + nZoom = static_cast<sal_uInt16>(static_cast<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..0f64f0ac1 --- /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); + long nWidth = 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 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(long(REPORT_STARTMARKER_WIDTH*m_pParent->getController().getZoomValue()),100); + const sal_Int32 nNewWidth = aOutPixSz.Width() - aOffset.X() - static_cast<long>(aStartWidth); + lcl_setScrollBar(nNewWidth,Point( static_cast<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( sal_uInt16 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 sal_uInt16 _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() )); + 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..3b5694c99 --- /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) + ,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.GetOutputSize() ); + const tools::Rectangle aVisRect( Point(-aOrg.X(),-aOrg.Y()), aVisSize ); + + // check, if rectangle is inside visible area + if ( !aVisRect.IsInside( 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::makeAny(_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..627490e62 --- /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.get()); + 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.get()); + 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, const char* 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, const char* 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(); + long nEndWidth = 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() ); + + long nStartWidth = 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<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().get() ); +} + +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,long _nX, long _nY) +{ + MapMode aMap = _rWindow.GetMapMode(); + aMap.SetOrigin( Point(- _nX, - _nY)); + _rWindow.SetMapMode( aMap ); +} + +void OSectionWindow::scrollChildren(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..2d9eda114 --- /dev/null +++ b/reportdesign/source/ui/report/StartMarker.cxx @@ -0,0 +1,308 @@ +/* -*- 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 <helpids.h> +#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_aText(VclPtr<FixedText>::Create(this,WB_HYPHENATION)) +,m_aImage(VclPtr<FixedImage>::Create(this,WB_LEFT|WB_TOP|WB_SCALE)) +,m_pParent(_pParent) +,m_bShowRuler(true) +{ + osl_atomic_increment(&s_nImageRefCount); + initDefaultNodeImages(); + ImplInitSettings(); + m_aText->SetHelpId(HID_RPT_START_TITLE); + m_aText->SetPaintTransparent(true); + m_aImage->SetHelpId(HID_RPT_START_IMAGE); + m_aText->Show(); + m_aImage->Show(); + 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 ) + { + DELETEZ(s_pDefCollapsed); + DELETEZ(s_pDefExpanded); + } + m_aVRuler.disposeAndClear(); + m_aText.disposeAndClear(); + m_aImage.disposeAndClear(); + m_pParent.clear(); + OColorListener::dispose(); +} + +sal_Int32 OStartMarker::getMinHeight() const +{ + Fraction aExtraWidth(long(2 * REPORT_EXTRA_SPACE)); + aExtraWidth *= GetMapMode().GetScaleX(); + return LogicToPixel(Size(0, m_aText->GetTextHeight())).Height() + long(aExtraWidth); +} + +void OStartMarker::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& /*rRect*/) +{ + Size aSize(GetOutputSizePixel()); + const long nCornerWidth = long(CORNER_SPACE * double(GetMapMode().GetScaleX())); + + if (isCollapsed()) + { + rRenderContext.SetClipRegion(); + } + else + { + const long nVRulerWidth = m_aVRuler->GetSizePixel().Width(); + 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); + } + if (m_bMarked) + { + const long nCornerHeight = 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)); + } +} + +void OStartMarker::setColor() +{ + const Color aColor(m_nColor); + Color aTextColor = GetTextColor(); + if ( aColor.GetLuminance() < 128 ) + aTextColor = COL_WHITE; + m_aText->SetTextColor(aTextColor); + m_aText->SetLineColor(m_nColor); +} + +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; + tools::Rectangle aRect(m_aImage->GetPosPixel(),m_aImage->GetSizePixel()); + if ( rMEvt.GetClicks() == 2 || aRect.IsInside( aPos ) ) + { + m_bCollapsed = !m_bCollapsed; + + changeImage(); + + m_aVRuler->Show(!m_bCollapsed && m_bShowRuler); + m_aCollapsedLink.Call(*this); + } + + m_pParent->showProperties(); +} + +void OStartMarker::changeImage() +{ + Image* pImage = m_bCollapsed ? s_pDefCollapsed : s_pDefExpanded; + m_aImage->SetImage(*pImage); +} + +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); + } + + Image* pImage = m_bCollapsed ? s_pDefCollapsed : s_pDefExpanded; + m_aImage->SetImage(*pImage); + m_aImage->SetMouseTransparent(true); + m_aImage->SetBackground(); + m_aText->SetBackground(); + m_aText->SetMouseTransparent(true); +} + +void OStartMarker::ApplySettings(vcl::RenderContext& rRenderContext) +{ + rRenderContext.SetBackground(); + rRenderContext.SetFillColor(Application::GetSettings().GetStyleSettings().GetDialogColor()); + setColor(); +} + +void OStartMarker::ImplInitSettings() +{ + ApplySettings(*this); +} + +void OStartMarker::Resize() +{ + const Size aOutputSize( GetOutputSizePixel() ); + const long nOutputWidth = aOutputSize.Width(); + const long nOutputHeight = aOutputSize.Height(); + + const long nVRulerWidth = m_aVRuler->GetSizePixel().Width(); + const Point aRulerPos(nOutputWidth - nVRulerWidth,0); + m_aVRuler->SetPosSizePixel(aRulerPos,Size(nVRulerWidth,nOutputHeight)); + + Size aImageSize = m_aImage->GetImage().GetSizePixel(); + const MapMode& rMapMode = GetMapMode(); + aImageSize.setWidth( long(aImageSize.Width() * static_cast<double>(rMapMode.GetScaleX())) ); + aImageSize.setHeight( long(aImageSize.Height() * static_cast<double>(rMapMode.GetScaleY())) ); + + long nExtraWidth = long(REPORT_EXTRA_SPACE * rMapMode.GetScaleX()); + + Point aPos(aImageSize.Width() + (nExtraWidth * 2), nExtraWidth); + const long nHeight = ::std::max<sal_Int32>(nOutputHeight - 2*aPos.Y(),LogicToPixel(Size(0,m_aText->GetTextHeight())).Height()); + m_aText->SetPosSizePixel(aPos,Size(aRulerPos.X() - aPos.X(),nHeight)); + + aPos.setX( nExtraWidth ); + aPos.AdjustY(static_cast<sal_Int32>((LogicToPixel(Size(0,m_aText->GetTextHeight())).Height() - aImageSize.Height()) * 0.5) ) ; + m_aImage->SetPosSizePixel(aPos,aImageSize); +} + +void OStartMarker::setTitle(const OUString& _sTitle) +{ + m_aText->SetText(_sTitle); +} + +void OStartMarker::Notify(SfxBroadcaster & rBc, SfxHint const & rHint) +{ + OColorListener::Notify(rBc, rHint); + if (rHint.GetId() == SfxHintId::ColorsChanged) + { + setColor(); + 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->GetText().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->GetText()); + else + Help::ShowQuickHelp( this, aItemRect, m_aText->GetText() ); +} + +void OStartMarker::setCollapsed(bool _bCollapsed) +{ + OColorListener::setCollapsed(_bCollapsed); + showRuler(_bCollapsed); + changeImage(); +} + +void OStartMarker::zoom(const Fraction& _aZoom) +{ + setZoomFactor(_aZoom,*this); + m_aVRuler->SetZoom(_aZoom); + setZoomFactor(_aZoom, *m_aText); + 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..51204671b --- /dev/null +++ b/reportdesign/source/ui/report/ViewsWindow.cxx @@ -0,0 +1,1675 @@ +/* -*- 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 <svx/unoshape.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,long& _nXMov, 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<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()); + long nStartWidth = 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( sal_uInt16 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 sal_uInt16 _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 ) + { + SvxShape* pShape = comphelper::getUnoTunnelImplementation<SvxShape>( rShape ); + SdrObject* pObject = pShape ? pShape->GetSdrObject() : nullptr; + 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()) + { + long nXMov = 0; + long nYMov = 0; + 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 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 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 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 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; + + 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 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 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 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 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 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(); + long nX = 0; + 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.IsInside( 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.IsInside( 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(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( 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..a0db6c64b --- /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 <RptDef.hxx> +#include <com/sun/star/beans/XPropertySet.hpp> + +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 OBJ_DLG_FIXEDTEXT: + pNewObj = new OUnoObject(aParams.rSdrModel, SERVICE_FIXEDTEXT + ,OUString("com.sun.star.form.component.FixedText") + ,OBJ_DLG_FIXEDTEXT); + break; + case OBJ_DLG_IMAGECONTROL: + pNewObj = new OUnoObject(aParams.rSdrModel, SERVICE_IMAGECONTROL + ,OUString("com.sun.star.form.component.DatabaseImageControl") + ,OBJ_DLG_IMAGECONTROL); + break; + case OBJ_DLG_FORMATTEDFIELD: + pNewObj = new OUnoObject(aParams.rSdrModel, SERVICE_FORMATTEDFIELD + ,OUString("com.sun.star.form.component.FormattedField") + ,OBJ_DLG_FORMATTEDFIELD); + break; + case OBJ_DLG_VFIXEDLINE: + case OBJ_DLG_HFIXEDLINE: + { + OUnoObject* pObj = new OUnoObject(aParams.rSdrModel, SERVICE_FIXEDLINE + ,OUString("com.sun.star.awt.UnoControlFixedLineModel") + ,aParams.nObjIdentifier); + pNewObj = pObj; + if ( aParams.nObjIdentifier == OBJ_DLG_HFIXEDLINE ) + { + uno::Reference<beans::XPropertySet> xProp = pObj->getAwtComponent(); + xProp->setPropertyValue( PROPERTY_ORIENTATION, uno::makeAny(sal_Int32(0)) ); + } + } + break; + case OBJ_CUSTOMSHAPE: + pNewObj = new OCustomShape(aParams.rSdrModel, SERVICE_SHAPE); + break; + case OBJ_DLG_SUBREPORT: + pNewObj = new OOle2Obj(aParams.rSdrModel, SERVICE_REPORTDEFINITION, OBJ_DLG_SUBREPORT); + break; + case OBJ_OLE2: + pNewObj = new OOle2Obj(aParams.rSdrModel, "com.sun.star.chart2.ChartDocument", OBJ_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..1753205cd --- /dev/null +++ b/reportdesign/source/ui/report/dlgedfunc.cxx @@ -0,0 +1,893 @@ +/* -*- 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(long(REPORT_STARTMARKER_WIDTH)); + aStartWidth *= m_pParent->GetMapMode().GetScaleX(); + + aOut.AdjustWidth( -static_cast<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<long>(aStartWidth) ); + aWorkArea = pScrollWindow->PixelToLogic( aWorkArea ); + if( !aOutRect.IsInside( rPos ) && aWorkArea.IsInside( 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()) + , 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); + 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 = uno::makeAny(_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.pRootObj && aVEvt.pRootObj->ISA(SdrTextObj) ) + // SetInEditMode(static_cast<SdrTextObj *>(aVEvt.pRootObj),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.pRootObj ) + m_rView.MarkObj(aVEvt.pRootObj, 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::checkTwoCklicks(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 sal_uInt16 nSdrObjKind = _pObj->GetObjIdentifier(); + + // OLE: activate + + if (nSdrObjKind != OBJ_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 sal_uLong nCount = rObjCache.size(); + for(sal_uLong 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.pObj) + { + colorizeOverlappedObject(aVEvt.pObj); + } + 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() != OBJ_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(); + long nDx = rDragStat.IsHorFixed() ? 0 : rDragStat.GetDX(); + 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.pObj && (aVEvt.pObj->GetObjIdentifier() != OBJ_CUSTOMSHAPE) && !m_bSelectionMode) + { + colorizeOverlappedObject(aVEvt.pObj); + } + 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; + sal_Int16 nId = m_rView.GetCurrentObjIdentifier(); + + const SdrHitKind eHit = m_rView.PickAnything(rMEvt, SdrMouseEventKind::BUTTONDOWN, aVEvt); + + if (eHit == SdrHitKind::UnmarkedObject && nId != OBJ_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.pRootObj, pPV); + } + checkTwoCklicks(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) ); + + 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.pRootObj,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(); + checkTwoCklicks(rMEvt); + + m_pParent->SetPointer( m_rView.GetPreferredPointer( aPnt, m_pParent) ); + + 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) ); + + // 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..edc4e78e6 --- /dev/null +++ b/reportdesign/source/ui/report/propbrw.cxx @@ -0,0 +1,534 @@ +/* -*- 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|WB_ROLLABLE)) + , 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", makeAny( m_pDesignView->getController().getModel() )), + ::cppu::ContextEntry_Init( "DialogParentWindow", makeAny( VCLUnoHelper::GetInterface ( this ) )), + ::cppu::ContextEntry_Init( "ActiveConnection", makeAny( 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() ) + { + const OUString sServiceName( "com.sun.star.inspection.ObjectInspector" ); + ShowServiceNotAvailableError(pParent ? pParent->GetFrameWeld() : nullptr, sServiceName, 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& ) + { + OSL_FAIL( "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& ) + { + OSL_FAIL( "FmPropBrw::Close: caught an exception while asking the controller!" ); + } + } + implDetachController(); + + if( IsRollUp() ) + RollDown(); + + 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& ) + { + OSL_FAIL( "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() ) + { + const char* 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::makeAny(_xFormComponent)); + xNameCont->insertByName("ReportComponent",uno::makeAny(_xReportComponent)); + xNameCont->insertByName("RowSet",uno::makeAny(uno::Reference< uno::XInterface>(m_pDesignView->getController().getRowSet()))); + + return xNameCont.get(); +} + +::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( makeAny( m_sLastActivePage ) ); + } + catch( const Exception& ) + { + OSL_FAIL( "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::makeAny(xTemp)); + xTemp = xNameCont; + + implSetNewObject( uno::Sequence< uno::Reference< uno::XInterface> >(&xTemp,1) ); + } + + StartListening( *(m_pView->GetModel()) ); + } + catch ( Exception& ) + { + OSL_FAIL( "PropBrw::Update: Exception occurred!" ); + } +} + +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& ) + { + OSL_FAIL( "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: */ |