/* -*- 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace rptui { #define STD_WIN_SIZE_X 300 #define STD_WIN_SIZE_Y 350 using namespace ::com::sun::star; using namespace uno; using namespace lang; using namespace frame; using namespace beans; using namespace container; using namespace ::comphelper; namespace { bool lcl_shouldEnableHelpSection( const Reference< XComponentContext >& _rxContext ) { ::utl::OConfigurationTreeRoot aConfiguration( ::utl::OConfigurationTreeRoot::createWithComponentContext( _rxContext, "/org.openoffice.Office.ReportDesign/PropertyBrowser/" ) ); bool bEnabled = false; OSL_VERIFY( aConfiguration.getNodeValue( "DirectHelp" ) >>= bEnabled ); return bEnabled; } } // PropBrw PropBrw::PropBrw(const Reference< XComponentContext >& _xORB, vcl::Window* pParent, ODesignView* _pDesignView) : DockingWindow(pParent,WinBits(WB_STDMODELESS|WB_SIZEABLE|WB_3DLOOK)) , m_xContentArea(VclPtr::Create(this)) , m_xORB(_xORB) , m_pDesignView(_pDesignView) , m_pView( nullptr ) , m_bInitialStateChange(true) { Size aPropWinSize(STD_WIN_SIZE_X,STD_WIN_SIZE_Y); SetOutputSizePixel(aPropWinSize); // turn off WB_CLIPCHILDREN otherwise the bg won't extend "under" // transparent children of the widget m_xContentArea->SetControlBackground(m_xContentArea->GetSettings().GetStyleSettings().GetWindowColor()); m_xContentArea->SetBackground(m_xContentArea->GetControlBackground()); m_xContentArea->SetStyle(m_xContentArea->GetStyle() & ~WB_CLIPCHILDREN); m_xContentArea->Show(); try { // create a frame wrapper for myself m_xMeAsFrame = Frame::create( m_xORB ); m_xMeAsFrame->initialize(VCLUnoHelper::GetInterface(m_xContentArea)); m_xMeAsFrame->setName("report property browser"); // change name! } catch (Exception&) { DBG_UNHANDLED_EXCEPTION("reportdesign"); OSL_FAIL("PropBrw::PropBrw: could not create/initialize my frame!"); m_xMeAsFrame.clear(); } if (m_xMeAsFrame.is()) { try { ::cppu::ContextEntry_Init aHandlerContextInfo[] = { ::cppu::ContextEntry_Init( "ContextDocument", Any( m_pDesignView->getController().getModel() )), ::cppu::ContextEntry_Init( "DialogParentWindow", Any( VCLUnoHelper::GetInterface ( this ) )), ::cppu::ContextEntry_Init( "ActiveConnection", Any( m_pDesignView->getController().getConnection() ) ), }; m_xInspectorContext.set( ::cppu::createComponentContext( aHandlerContextInfo, SAL_N_ELEMENTS( aHandlerContextInfo ), m_xORB ) ); // create a property browser controller bool bEnableHelpSection = lcl_shouldEnableHelpSection( m_xORB ); Reference< inspection::XObjectInspectorModel> xInspectorModel( bEnableHelpSection ? report::inspection::DefaultComponentInspectorModel::createWithHelpSection( m_xInspectorContext, 3, 8 ) : report::inspection::DefaultComponentInspectorModel::createDefault( m_xInspectorContext ) ); m_xBrowserController = inspection::ObjectInspector::createWithModel(m_xInspectorContext, xInspectorModel); if ( !m_xBrowserController.is() ) { ShowServiceNotAvailableError(pParent ? pParent->GetFrameWeld() : nullptr, u"com.sun.star.inspection.ObjectInspector", true); } else { m_xBrowserController->attachFrame( Reference(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 xName(m_xInspectorContext,uno::UNO_QUERY); if ( xName.is() ) { const OUString pProps[] = { OUString( "ContextDocument" ) , OUString( "DialogParentWindow" ) , OUString( "ActiveConnection" )}; for (const auto & i : pProps) xName->removeByName(i); } } catch(Exception&) {} ::rptui::notifySystemWindow(this,this,::comphelper::mem_fun(&TaskPaneList::RemoveWindow)); m_pDesignView.clear(); m_xContentArea.disposeAndClear(); DockingWindow::dispose(); } void PropBrw::setCurrentPage(const OUString& _sLastActivePage) { m_sLastActivePage = _sLastActivePage; } void PropBrw::implDetachController() { m_sLastActivePage = getCurrentPage(); implSetNewObject( ); if ( m_xMeAsFrame.is() ) m_xMeAsFrame->setComponent( nullptr, nullptr ); if ( m_xBrowserController.is() ) m_xBrowserController->attachFrame( nullptr ); m_xMeAsFrame.clear(); m_xBrowserController.clear(); } OUString PropBrw::getCurrentPage() const { OUString sCurrentPage; try { if ( m_xBrowserController.is() ) { OSL_VERIFY( m_xBrowserController->getViewData() >>= sCurrentPage ); } if ( sCurrentPage.isEmpty() ) sCurrentPage = m_sLastActivePage; } catch( const Exception& ) { TOOLS_WARN_EXCEPTION( "reportdesign", "PropBrw::getCurrentPage: caught an exception while retrieving the current page!" ); } return sCurrentPage; } bool PropBrw::Close() { m_xLastSection.clear(); // suspend the controller (it is allowed to veto) if ( m_xMeAsFrame.is() ) { try { Reference< XController > xController( m_xMeAsFrame->getController() ); if ( xController.is() && !xController->suspend( true ) ) return false; } catch( const Exception& ) { TOOLS_WARN_EXCEPTION( "reportdesign", "FmPropBrw::Close: caught an exception while asking the controller!" ); } } implDetachController(); m_pDesignView->getController().executeUnChecked(SID_PROPERTYBROWSER_LAST_PAGE,uno::Sequence< beans::PropertyValue>()); return true; } uno::Sequence< Reference > 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; iGetMarkedSdrObj(); ::std::unique_ptr pGroupIterator; if (pCurrent->IsGroupObject()) { pGroupIterator.reset(new SdrObjListIter(pCurrent->GetSubList())); pCurrent = pGroupIterator->IsMore() ? pGroupIterator->Next() : nullptr; } while (pCurrent) { OObjectBase* pObj = dynamic_cast(pCurrent); if ( pObj ) aSets.push_back(CreateComponentPair(pObj)); // next element pCurrent = pGroupIterator && pGroupIterator->IsMore() ? pGroupIterator->Next() : nullptr; } } return uno::Sequence< Reference >(aSets.data(), aSets.size()); } void PropBrw::implSetNewObject( const uno::Sequence< Reference >& _aObjects ) { if ( m_xBrowserController.is() ) { try { m_xBrowserController->inspect(uno::Sequence< Reference >()); m_xBrowserController->inspect(_aObjects); } catch( const Exception& ) { TOOLS_WARN_EXCEPTION( "reportdesign", "FmPropBrw::StateChanged: caught an exception while setting the initial page!" ); } } SetText( GetHeadlineName(_aObjects) ); } OUString PropBrw::GetHeadlineName( const uno::Sequence< Reference >& _aObjects ) { OUString aName; if ( !_aObjects.hasElements() ) { aName = RptResId(RID_STR_BRWTITLE_NO_PROPERTIES); } else if ( _aObjects.getLength() == 1 ) // single selection { aName = RptResId(RID_STR_BRWTITLE_PROPERTIES); uno::Reference< container::XNameContainer > xNameCont(_aObjects[0],uno::UNO_QUERY); Reference< lang::XServiceInfo > xServiceInfo( xNameCont->getByName("ReportComponent"), UNO_QUERY ); if ( xServiceInfo.is() ) { TranslateId pResId; if ( xServiceInfo->supportsService( SERVICE_FIXEDTEXT ) ) { pResId = RID_STR_PROPTITLE_FIXEDTEXT; } else if ( xServiceInfo->supportsService( SERVICE_IMAGECONTROL ) ) { pResId = RID_STR_PROPTITLE_IMAGECONTROL; } else if ( xServiceInfo->supportsService( SERVICE_FORMATTEDFIELD ) ) { pResId = RID_STR_PROPTITLE_FORMATTED; } else if ( xServiceInfo->supportsService( SERVICE_SHAPE ) ) { pResId = RID_STR_PROPTITLE_SHAPE; } else if ( xServiceInfo->supportsService( SERVICE_REPORTDEFINITION ) ) { pResId = RID_STR_PROPTITLE_REPORT; } else if ( xServiceInfo->supportsService( SERVICE_SECTION ) ) { pResId = RID_STR_PROPTITLE_SECTION; } else if ( xServiceInfo->supportsService( SERVICE_FUNCTION ) ) { pResId = RID_STR_PROPTITLE_FUNCTION; } else if ( xServiceInfo->supportsService( SERVICE_GROUP ) ) { pResId = RID_STR_PROPTITLE_GROUP; } else if ( xServiceInfo->supportsService( SERVICE_FIXEDLINE ) ) { pResId = RID_STR_PROPTITLE_FIXEDLINE; } else { OSL_FAIL("Unknown service name!"); aName += RID_STR_CLASS_FORMATTEDFIELD; return aName; } aName += RptResId(pResId); } } else // multiselection { aName = RptResId(RID_STR_BRWTITLE_PROPERTIES) + RptResId(RID_STR_BRWTITLE_MULTISELECT); } return aName; } uno::Reference< uno::XInterface> PropBrw::CreateComponentPair(OObjectBase* _pObj) { _pObj->initializeOle(); return CreateComponentPair(_pObj->getAwtComponent(),_pObj->getReportComponent()); } uno::Reference< uno::XInterface> PropBrw::CreateComponentPair(const uno::Reference< uno::XInterface>& _xFormComponent ,const uno::Reference< uno::XInterface>& _xReportComponent) { uno::Reference< container::XNameContainer > xNameCont = ::comphelper::NameContainer_createInstance(cppu::UnoType::get()); xNameCont->insertByName("FormComponent",uno::Any(_xFormComponent)); xNameCont->insertByName("ReportComponent",uno::Any(_xReportComponent)); xNameCont->insertByName("RowSet",uno::Any(uno::Reference< uno::XInterface>(m_pDesignView->getController().getRowSet()))); return xNameCont; } ::Size PropBrw::getMinimumSize() const { ::Size aSize; Reference< awt::XLayoutConstrains > xLayoutConstrains( m_xBrowserController, UNO_QUERY ); if( xLayoutConstrains.is() ) { awt::Size aMinSize = xLayoutConstrains->getMinimumSize(); aMinSize.Height += 4; aMinSize.Width += 4; aSize.setHeight( aMinSize.Height ); aSize.setWidth( aMinSize.Width ); } return aSize; } void PropBrw::Update( OSectionView* pNewView ) { try { if ( m_pView ) { EndListening( *(m_pView->GetModel()) ); m_pView = nullptr; } // set focus on initialization if ( m_bInitialStateChange ) { // if we're just newly created, we want to have the focus PostUserEvent( LINK( this, PropBrw, OnAsyncGetFocus ), nullptr, true ); m_bInitialStateChange = false; // and additionally, we want to show the page which was active during // our previous incarnation if ( !m_sLastActivePage.isEmpty() && m_xBrowserController.is() ) { try { m_xBrowserController->restoreViewData( Any( m_sLastActivePage ) ); } catch( const Exception& ) { TOOLS_WARN_EXCEPTION( "reportdesign", "FmPropBrw::StateChanged: caught an exception while setting the initial page!" ); } } } if ( !pNewView ) return; else m_pView = pNewView; uno::Sequence< Reference > 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::get() ); xNameCont->insertByName("ReportComponent",uno::Any(xTemp)); xTemp = xNameCont; implSetNewObject( uno::Sequence< uno::Reference< uno::XInterface> >(&xTemp,1) ); } StartListening( *(m_pView->GetModel()) ); } catch ( Exception& ) { TOOLS_WARN_EXCEPTION( "reportdesign", "PropBrw::Update" ); } } void PropBrw::Update( const uno::Reference< uno::XInterface>& _xReportComponent) { if ( m_xLastSection == _xReportComponent ) return; m_xLastSection = _xReportComponent; try { if ( m_pView ) { EndListening( *(m_pView->GetModel()) ); m_pView = nullptr; } uno::Reference< uno::XInterface> xTemp(CreateComponentPair(_xReportComponent,_xReportComponent)); implSetNewObject( uno::Sequence< uno::Reference< uno::XInterface> >(&xTemp,1) ); } catch ( Exception& ) { TOOLS_WARN_EXCEPTION( "reportdesign", "PropBrw::Update: Exception occurred!" ); } } IMPL_LINK_NOARG( PropBrw, OnAsyncGetFocus, void*, void ) { m_xContentArea->GrabFocus(); } void PropBrw::LoseFocus() { DockingWindow::LoseFocus(); if (m_pDesignView) m_pDesignView->getController().InvalidateAll(); } } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */