/* -*- 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 "ElementSelector.hxx" #include "macros.hxx" #include "ObjectNameProvider.hxx" #include "ObjectHierarchy.hxx" #include "servicenames.hxx" #include #include "DrawViewWrapper.hxx" #include "ResId.hxx" #include "Strings.hrc" #include "ObjectIdentifier.hxx" #include #include #include #include #include #include #include #include namespace chart { using namespace com::sun::star; using namespace com::sun::star::uno; using ::com::sun::star::uno::Any; using ::com::sun::star::uno::Reference; using ::com::sun::star::uno::Sequence; namespace { static const char lcl_aServiceName[] = "com.sun.star.comp.chart.ElementSelectorToolbarController"; } SelectorListBox::SelectorListBox( vcl::Window* pParent, WinBits nStyle ) : ListBox( pParent, nStyle ) , m_bReleaseFocus( true ) { } void lcl_addObjectsToList( const ObjectHierarchy& rHierarchy, const ObjectIdentifier & rParent, std::vector< ListBoxEntryData >& rEntries , const sal_Int32 nHierarchyDepth, const Reference< chart2::XChartDocument >& xChartDoc ) { ObjectHierarchy::tChildContainer aChildren( rHierarchy.getChildren(rParent) ); ObjectHierarchy::tChildContainer::const_iterator aIt( aChildren.begin()); while( aIt != aChildren.end() ) { ObjectIdentifier aOID = *aIt; OUString aCID = aOID.getObjectCID(); ListBoxEntryData aEntry; aEntry.OID = aOID; aEntry.UIName += ObjectNameProvider::getNameForCID( aCID, xChartDoc ); aEntry.nHierarchyDepth = nHierarchyDepth; rEntries.push_back(aEntry); lcl_addObjectsToList( rHierarchy, aOID, rEntries, nHierarchyDepth+1, xChartDoc ); ++aIt; } } void SelectorListBox::SetChartController( const Reference< frame::XController >& xChartController ) { m_xChartController = xChartController; } void SelectorListBox::UpdateChartElementsListAndSelection() { Clear(); m_aEntries.clear(); Reference< frame::XController > xChartController( m_xChartController ); if( xChartController.is() ) { Reference< view::XSelectionSupplier > xSelectionSupplier( xChartController, uno::UNO_QUERY); ObjectIdentifier aSelectedOID; OUString aSelectedCID; if( xSelectionSupplier.is() ) { aSelectedOID = ObjectIdentifier( xSelectionSupplier->getSelection() ); aSelectedCID = aSelectedOID.getObjectCID(); } Reference< chart2::XChartDocument > xChartDoc( xChartController->getModel(), uno::UNO_QUERY ); ObjectType eType( aSelectedOID.getObjectType() ); bool bAddSelectionToList = false; if ( eType == OBJECTTYPE_DATA_POINT || eType == OBJECTTYPE_DATA_LABEL || eType == OBJECTTYPE_SHAPE ) bAddSelectionToList = true; Reference< uno::XInterface > xChartView; Reference< lang::XMultiServiceFactory > xFact( xChartController->getModel(), uno::UNO_QUERY ); if( xFact.is() ) xChartView = xFact->createInstance( CHART_VIEW_SERVICE_NAME ); ExplicitValueProvider* pExplicitValueProvider = nullptr; //ExplicitValueProvider::getExplicitValueProvider(xChartView); this creates all visible data points, that's too much ObjectHierarchy aHierarchy( xChartDoc, pExplicitValueProvider, true /*bFlattenDiagram*/, true /*bOrderingForElementSelector*/ ); lcl_addObjectsToList( aHierarchy, ::chart::ObjectHierarchy::getRootNodeOID(), m_aEntries, 0, xChartDoc ); std::vector< ListBoxEntryData >::iterator aIt( m_aEntries.begin() ); if( bAddSelectionToList ) { if ( aSelectedOID.isAutoGeneratedObject() ) { OUString aSeriesCID = ObjectIdentifier::createClassifiedIdentifierForParticle( ObjectIdentifier::getSeriesParticleFromCID( aSelectedCID ) ); for( aIt = m_aEntries.begin(); aIt != m_aEntries.end(); ++aIt ) { if( aIt->OID.getObjectCID().match( aSeriesCID ) ) { ListBoxEntryData aEntry; aEntry.UIName = ObjectNameProvider::getNameForCID( aSelectedCID, xChartDoc ); aEntry.OID = aSelectedOID; ++aIt; if( aIt != m_aEntries.end() ) m_aEntries.insert(aIt, aEntry); else m_aEntries.push_back( aEntry ); break; } } } else if ( aSelectedOID.isAdditionalShape() ) { ListBoxEntryData aEntry; SdrObject* pSelectedObj = DrawViewWrapper::getSdrObject( aSelectedOID.getAdditionalShape() ); OUString aName = pSelectedObj ? pSelectedObj->GetName() : OUString(); aEntry.UIName = ( aName.isEmpty() ? SCH_RESSTR( STR_OBJECT_SHAPE ) : aName ); aEntry.OID = aSelectedOID; m_aEntries.push_back( aEntry ); } } sal_uInt16 nEntryPosToSelect = 0; bool bSelectionFound = false; aIt = m_aEntries.begin(); for( sal_uInt16 nN=0; aIt != m_aEntries.end(); ++aIt, ++nN ) { InsertEntry( aIt->UIName ); if ( !bSelectionFound && aSelectedOID == aIt->OID ) { nEntryPosToSelect = nN; bSelectionFound = true; } } if( bSelectionFound ) SelectEntryPos(nEntryPosToSelect); sal_Int32 nEntryCount = GetEntryCount(); if( nEntryCount > 100 ) nEntryCount = 100; SetDropDownLineCount( nEntryCount ); } SaveValue(); //remind current selection pos } void SelectorListBox::ReleaseFocus_Impl() { if ( !m_bReleaseFocus ) { m_bReleaseFocus = true; return; } Reference< frame::XController > xController( m_xChartController ); Reference< frame::XFrame > xFrame( xController->getFrame() ); if ( xFrame.is() && xFrame->getContainerWindow().is() ) xFrame->getContainerWindow()->setFocus(); } void SelectorListBox::Select() { ListBox::Select(); if ( !IsTravelSelect() ) { const sal_Int32 nPos = GetSelectEntryPos(); if( static_cast(nPos) < m_aEntries.size() ) { ObjectIdentifier aOID = m_aEntries[nPos].OID; Reference< view::XSelectionSupplier > xSelectionSupplier( m_xChartController.get(), uno::UNO_QUERY ); if( xSelectionSupplier.is() ) xSelectionSupplier->select( aOID.getAny() ); } ReleaseFocus_Impl(); } } bool SelectorListBox::Notify( NotifyEvent& rNEvt ) { bool bHandled = false; if ( rNEvt.GetType() == MouseNotifyEvent::KEYINPUT ) { sal_uInt16 nCode = rNEvt.GetKeyEvent()->GetKeyCode().GetCode(); switch ( nCode ) { case KEY_RETURN: case KEY_TAB: { if ( KEY_TAB == nCode ) m_bReleaseFocus = false; else bHandled = true; Select(); break; } case KEY_ESCAPE: SelectEntryPos( GetSavedValue() ); //restore saved selection ReleaseFocus_Impl(); break; } } else if ( MouseNotifyEvent::LOSEFOCUS == rNEvt.GetType() ) { if ( !HasFocus() ) SelectEntryPos( GetSavedValue() ); } return bHandled || ListBox::Notify( rNEvt ); } Reference< css::accessibility::XAccessible > SelectorListBox::CreateAccessible() { UpdateChartElementsListAndSelection(); return ListBox::CreateAccessible(); } // implement XServiceInfo methods basing upon getSupportedServiceNames_Static OUString SAL_CALL ElementSelectorToolbarController::getImplementationName() throw( css::uno::RuntimeException, std::exception ) { return getImplementationName_Static(); } OUString ElementSelectorToolbarController::getImplementationName_Static() { return OUString(lcl_aServiceName); } sal_Bool SAL_CALL ElementSelectorToolbarController::supportsService( const OUString& rServiceName ) throw( css::uno::RuntimeException, std::exception ) { return cppu::supportsService(this, rServiceName); } css::uno::Sequence< OUString > SAL_CALL ElementSelectorToolbarController::getSupportedServiceNames() throw( css::uno::RuntimeException, std::exception ) { return getSupportedServiceNames_Static(); } Sequence< OUString > ElementSelectorToolbarController::getSupportedServiceNames_Static() { return { "com.sun.star.frame.ToolbarController" }; } ElementSelectorToolbarController::ElementSelectorToolbarController() { } ElementSelectorToolbarController::~ElementSelectorToolbarController() { } // XInterface Any SAL_CALL ElementSelectorToolbarController::queryInterface( const Type& _rType ) throw (RuntimeException, std::exception) { Any aReturn = ToolboxController::queryInterface(_rType); if (!aReturn.hasValue()) aReturn = ElementSelectorToolbarController_BASE::queryInterface(_rType); return aReturn; } void SAL_CALL ElementSelectorToolbarController::acquire() throw () { ToolboxController::acquire(); } void SAL_CALL ElementSelectorToolbarController::release() throw () { ToolboxController::release(); } void SAL_CALL ElementSelectorToolbarController::statusChanged( const frame::FeatureStateEvent& rEvent ) throw ( RuntimeException, std::exception ) { if( m_apSelectorListBox.get() ) { SolarMutexGuard aSolarMutexGuard; if ( rEvent.FeatureURL.Path == "ChartElementSelector" ) { Reference< frame::XController > xChartController; rEvent.State >>= xChartController; m_apSelectorListBox->SetChartController( xChartController ); m_apSelectorListBox->UpdateChartElementsListAndSelection(); } } } uno::Reference< awt::XWindow > SAL_CALL ElementSelectorToolbarController::createItemWindow( const uno::Reference< awt::XWindow >& xParent ) throw (uno::RuntimeException, std::exception) { uno::Reference< awt::XWindow > xItemWindow; if( !m_apSelectorListBox.get() ) { vcl::Window* pParent = VCLUnoHelper::GetWindow( xParent ); if( pParent ) { m_apSelectorListBox.reset( VclPtr::Create( pParent, WB_DROPDOWN|WB_AUTOHSCROLL|WB_BORDER ) ); ::Size aLogicalSize( 95, 160 ); ::Size aPixelSize = m_apSelectorListBox->LogicToPixel( aLogicalSize, MapUnit::MapAppFont ); m_apSelectorListBox->SetSizePixel( aPixelSize ); m_apSelectorListBox->SetDropDownLineCount( 5 ); } } if( m_apSelectorListBox.get() ) xItemWindow = VCLUnoHelper::GetInterface( m_apSelectorListBox.get() ); return xItemWindow; } } // chart2 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * SAL_CALL com_sun_star_comp_chart_ElementSelectorToolbarController_get_implementation(css::uno::XComponentContext *, css::uno::Sequence const &) { return cppu::acquire(new chart::ElementSelectorToolbarController ); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */