1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "ElementSelector.hxx"
21 #include <ObjectNameProvider.hxx>
22 #include <ObjectHierarchy.hxx>
23 #include <servicenames.hxx>
24 #include <DrawViewWrapper.hxx>
26 #include <strings.hrc>
27 #include <ObjectIdentifier.hxx>
28 #include <ChartController.hxx>
29 #include <ChartModel.hxx>
31 #include <cppuhelper/supportsservice.hxx>
32 #include <o3tl/safeint.hxx>
33 #include <toolkit/helper/vclunohelper.hxx>
34 #include <vcl/svapp.hxx>
36 namespace chart
{ class ExplicitValueProvider
; }
41 using namespace com::sun::star
;
42 using namespace com::sun::star::uno
;
43 using ::com::sun::star::uno::Any
;
44 using ::com::sun::star::uno::Reference
;
45 using ::com::sun::star::uno::Sequence
;
49 constexpr OUStringLiteral lcl_aServiceName
50 = u
"com.sun.star.comp.chart.ElementSelectorToolbarController";
53 SelectorListBox::SelectorListBox(vcl::Window
* pParent
)
54 : InterimItemWindow(pParent
, u
"modules/schart/ui/combobox.ui"_ustr
, u
"ComboBox"_ustr
)
55 , m_xWidget(m_xBuilder
->weld_combo_box(u
"combobox"_ustr
))
56 , m_bReleaseFocus(true)
58 InitControlBase(m_xWidget
.get());
60 m_xWidget
->connect_key_press(LINK(this, SelectorListBox
, KeyInputHdl
));
61 m_xWidget
->connect_changed(LINK(this, SelectorListBox
, SelectHdl
));
62 m_xWidget
->connect_focus_out(LINK(this, SelectorListBox
, FocusOutHdl
));
64 ::Size
aLogicalSize(75, 0);
65 ::Size aPixelSize
= LogicToPixel(aLogicalSize
, MapMode(MapUnit::MapAppFont
));
66 m_xWidget
->set_size_request(aPixelSize
.Width(), -1);
67 SetSizePixel(m_xContainer
->get_preferred_size());
70 void SelectorListBox::dispose()
73 InterimItemWindow::dispose();
76 SelectorListBox::~SelectorListBox()
81 static void lcl_addObjectsToList( const ObjectHierarchy
& rHierarchy
, const ObjectIdentifier
& rParent
, std::vector
< ListBoxEntryData
>& rEntries
82 , const sal_Int32 nHierarchyDepth
, const rtl::Reference
<::chart::ChartModel
>& xChartDoc
)
84 ObjectHierarchy::tChildContainer
aChildren( rHierarchy
.getChildren(rParent
) );
85 for (auto const& child
: aChildren
)
87 ListBoxEntryData aEntry
;
89 aEntry
.UIName
= ObjectNameProvider::getNameForCID( child
.getObjectCID(), xChartDoc
);
90 aEntry
.nHierarchyDepth
= nHierarchyDepth
;
91 rEntries
.push_back(aEntry
);
92 lcl_addObjectsToList( rHierarchy
, child
, rEntries
, nHierarchyDepth
+1, xChartDoc
);
96 void SelectorListBox::SetChartController( const rtl::Reference
< ::chart::ChartController
>& xChartController
)
98 m_xChartController
= xChartController
.get();
101 void SelectorListBox::UpdateChartElementsListAndSelection()
106 rtl::Reference
< ::chart::ChartController
> xChartController
= m_xChartController
.get();
107 if( xChartController
.is() )
109 ObjectIdentifier
aSelectedOID( xChartController
->getSelection() );
110 const OUString
& aSelectedCID
= aSelectedOID
.getObjectCID();
112 rtl::Reference
<::chart::ChartModel
> xChartDoc
= xChartController
->getChartModel();
113 ObjectType
eType( aSelectedOID
.getObjectType() );
114 bool bAddSelectionToList
= false;
115 if ( eType
== OBJECTTYPE_DATA_POINT
|| eType
== OBJECTTYPE_DATA_LABEL
|| eType
== OBJECTTYPE_SHAPE
)
116 bAddSelectionToList
= true;
118 Reference
< uno::XInterface
> xChartView
;
119 rtl::Reference
< ChartModel
> xFact
= xChartController
->getChartModel();
121 xChartView
= xFact
->createInstance( CHART_VIEW_SERVICE_NAME
);
122 ExplicitValueProvider
* pExplicitValueProvider
= nullptr; //ExplicitValueProvider::getExplicitValueProvider(xChartView); this creates all visible data points, that's too much
123 ObjectHierarchy
aHierarchy( xChartDoc
, pExplicitValueProvider
, true /*bFlattenDiagram*/, true /*bOrderingForElementSelector*/ );
124 lcl_addObjectsToList( aHierarchy
, ::chart::ObjectHierarchy::getRootNodeOID(), m_aEntries
, 0, xChartDoc
);
126 if( bAddSelectionToList
)
128 if ( aSelectedOID
.isAutoGeneratedObject() )
130 OUString aSeriesCID
= ObjectIdentifier::createClassifiedIdentifierForParticle( ObjectIdentifier::getSeriesParticleFromCID( aSelectedCID
) );
131 std::vector
< ListBoxEntryData
>::iterator aIt
= std::find_if(m_aEntries
.begin(), m_aEntries
.end(),
132 [&aSeriesCID
](const ListBoxEntryData
& rEntry
) { return rEntry
.OID
.getObjectCID().match(aSeriesCID
); });
133 if (aIt
!= m_aEntries
.end())
135 ListBoxEntryData aEntry
;
136 aEntry
.UIName
= ObjectNameProvider::getNameForCID( aSelectedCID
, xChartDoc
);
137 aEntry
.OID
= aSelectedOID
;
139 if( aIt
!= m_aEntries
.end() )
140 m_aEntries
.insert(aIt
, aEntry
);
142 m_aEntries
.push_back( aEntry
);
145 else if ( aSelectedOID
.isAdditionalShape() )
147 ListBoxEntryData aEntry
;
148 SdrObject
* pSelectedObj
= DrawViewWrapper::getSdrObject( aSelectedOID
.getAdditionalShape() );
149 OUString aName
= pSelectedObj
? pSelectedObj
->GetName() : OUString();
150 aEntry
.UIName
= ( aName
.isEmpty() ? SchResId( STR_OBJECT_SHAPE
) : aName
);
151 aEntry
.OID
= aSelectedOID
;
152 m_aEntries
.push_back( aEntry
);
157 sal_uInt16 nEntryPosToSelect
= 0; bool bSelectionFound
= false;
159 for (auto const& entry
: m_aEntries
)
161 // tdf#152087 strip any newlines from the entry
162 m_xWidget
->append_text(entry
.UIName
.replaceAll("\n", " "));
163 if ( !bSelectionFound
&& aSelectedOID
== entry
.OID
)
165 nEntryPosToSelect
= nN
;
166 bSelectionFound
= true;
172 if( bSelectionFound
)
173 m_xWidget
->set_active(nEntryPosToSelect
);
175 m_xWidget
->save_value(); //remind current selection pos
178 void SelectorListBox::ReleaseFocus_Impl()
180 if ( !m_bReleaseFocus
)
182 m_bReleaseFocus
= true;
186 rtl::Reference
< ::chart::ChartController
> xController
= m_xChartController
.get();
187 Reference
< frame::XFrame
> xFrame( xController
->getFrame() );
188 if ( xFrame
.is() && xFrame
->getContainerWindow().is() )
189 xFrame
->getContainerWindow()->setFocus();
192 IMPL_LINK(SelectorListBox
, SelectHdl
, weld::ComboBox
&, rComboBox
, void)
194 if (rComboBox
.changed_by_direct_pick())
196 const sal_Int32 nPos
= rComboBox
.get_active();
197 if (o3tl::make_unsigned(nPos
) < m_aEntries
.size())
199 ObjectIdentifier aOID
= m_aEntries
[nPos
].OID
;
200 rtl::Reference
< ::chart::ChartController
> xController
= m_xChartController
.get();
201 if( xController
.is() )
202 xController
->select( aOID
.getAny() );
208 IMPL_LINK(SelectorListBox
, KeyInputHdl
, const KeyEvent
&, rKEvt
, bool)
210 bool bHandled
= false;
212 sal_uInt16 nCode
= rKEvt
.GetKeyCode().GetCode();
219 if ( nCode
== KEY_TAB
)
220 m_bReleaseFocus
= false;
223 SelectHdl(*m_xWidget
);
228 m_xWidget
->set_active_text(m_xWidget
->get_saved_value()); //restore saved selection
233 return bHandled
|| ChildKeyInput(rKEvt
);
236 IMPL_LINK_NOARG(SelectorListBox
, FocusOutHdl
, weld::Widget
&, void)
238 if (m_xWidget
&& !m_xWidget
->has_focus()) // comboboxes can be comprised of multiple widgets, ensure all have lost focus
239 m_xWidget
->set_active_text(m_xWidget
->get_saved_value());
242 OUString SAL_CALL
ElementSelectorToolbarController::getImplementationName()
244 return lcl_aServiceName
;
247 sal_Bool SAL_CALL
ElementSelectorToolbarController::supportsService( const OUString
& rServiceName
)
249 return cppu::supportsService(this, rServiceName
);
252 css::uno::Sequence
< OUString
> SAL_CALL
ElementSelectorToolbarController::getSupportedServiceNames()
254 return { u
"com.sun.star.frame.ToolbarController"_ustr
};
256 ElementSelectorToolbarController::ElementSelectorToolbarController()
259 ElementSelectorToolbarController::~ElementSelectorToolbarController()
263 Any SAL_CALL
ElementSelectorToolbarController::queryInterface( const Type
& _rType
)
265 Any aReturn
= ToolboxController::queryInterface(_rType
);
266 if (!aReturn
.hasValue())
267 aReturn
= ElementSelectorToolbarController_BASE::queryInterface(_rType
);
270 void SAL_CALL
ElementSelectorToolbarController::acquire() noexcept
272 ToolboxController::acquire();
274 void SAL_CALL
ElementSelectorToolbarController::release() noexcept
276 ToolboxController::release();
278 void SAL_CALL
ElementSelectorToolbarController::statusChanged( const frame::FeatureStateEvent
& rEvent
)
280 if( m_apSelectorListBox
)
282 SolarMutexGuard aSolarMutexGuard
;
283 if ( rEvent
.FeatureURL
.Path
== "ChartElementSelector" )
285 Reference
< frame::XController
> xChartController
;
286 rEvent
.State
>>= xChartController
;
287 ::chart::ChartController
* pController
= dynamic_cast<::chart::ChartController
*>(xChartController
.get());
288 assert(!xChartController
|| pController
);
289 m_apSelectorListBox
->SetChartController( pController
);
290 m_apSelectorListBox
->UpdateChartElementsListAndSelection();
294 uno::Reference
< awt::XWindow
> SAL_CALL
ElementSelectorToolbarController::createItemWindow( const uno::Reference
< awt::XWindow
>& xParent
)
296 uno::Reference
< awt::XWindow
> xItemWindow
;
297 if( !m_apSelectorListBox
)
299 VclPtr
<vcl::Window
> pParent
= VCLUnoHelper::GetWindow( xParent
);
302 m_apSelectorListBox
.reset(VclPtr
<SelectorListBox
>::Create(pParent
));
305 if( m_apSelectorListBox
)
306 xItemWindow
= VCLUnoHelper::GetInterface( m_apSelectorListBox
.get() );
312 extern "C" SAL_DLLPUBLIC_EXPORT
css::uno::XInterface
*
313 com_sun_star_comp_chart_ElementSelectorToolbarController_get_implementation(css::uno::XComponentContext
*,
314 css::uno::Sequence
<css::uno::Any
> const &)
316 return cppu::acquire(new chart::ElementSelectorToolbarController
);
319 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */