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/.
10 #include <cppuhelper/implbase.hxx>
11 #include <svtools/toolboxcontroller.hxx>
12 #include <com/sun/star/lang/XServiceInfo.hpp>
13 #include <com/sun/star/document/XDocumentProperties.hpp>
15 #include <com/sun/star/uno/XComponentContext.hpp>
16 #include <com/sun/star/frame/XFrame.hpp>
18 #include <toolkit/helper/vclunohelper.hxx>
19 #include <vcl/InterimItemWindow.hxx>
20 #include <sfx2/classificationhelper.hxx>
21 #include <sfx2/objsh.hxx>
22 #include <sfx2/strings.hrc>
23 #include <sfx2/sfxresid.hxx>
24 #include <vcl/event.hxx>
25 #include <vcl/toolbox.hxx>
26 #include <vcl/svapp.hxx>
27 #include <vcl/vclptr.hxx>
28 #include <vcl/weld.hxx>
30 #include <cppuhelper/supportsservice.hxx>
31 #include <comphelper/propertysequence.hxx>
32 #include <comphelper/dispatchcommand.hxx>
33 #include <comphelper/configurationlistener.hxx>
35 using namespace com::sun::star
;
42 class ClassificationCategoriesController
;
46 using ClassificationPropertyListenerBase
= comphelper::ConfigurationListenerProperty
<OUString
>;
50 /// Listens to configuration changes, so no restart is needed after setting the classification path.
51 class ClassificationPropertyListener
: public ClassificationPropertyListenerBase
53 ClassificationCategoriesController
& m_rController
;
56 ClassificationPropertyListener(const rtl::Reference
<comphelper::ConfigurationListener
>& xListener
, ClassificationCategoriesController
& rController
);
57 void setProperty(const uno::Any
& rProperty
) override
;
62 using ClassificationCategoriesControllerBase
= cppu::ImplInheritanceHelper
<svt::ToolboxController
, lang::XServiceInfo
>;
66 class ClassificationControl
;
68 /// Controller for .uno:ClassificationApply.
69 class ClassificationCategoriesController
: public ClassificationCategoriesControllerBase
71 VclPtr
<ClassificationControl
> m_pClassification
;
72 rtl::Reference
<comphelper::ConfigurationListener
> m_xListener
;
73 ClassificationPropertyListener m_aPropertyListener
;
75 DECL_LINK(SelectHdl
, weld::ComboBox
&, void);
78 explicit ClassificationCategoriesController(const uno::Reference
<uno::XComponentContext
>& rContext
);
81 OUString SAL_CALL
getImplementationName() override
;
82 sal_Bool SAL_CALL
supportsService(const OUString
& rServiceName
) override
;
83 uno::Sequence
<OUString
> SAL_CALL
getSupportedServiceNames() override
;
86 void SAL_CALL
dispose() override
;
89 uno::Reference
<awt::XWindow
> SAL_CALL
createItemWindow(const uno::Reference
<awt::XWindow
>& rParent
) override
;
92 void SAL_CALL
statusChanged(const frame::FeatureStateEvent
& rEvent
) override
;
97 /// Classification control is the parent of all widgets that belongs to ClassificationCategoriesController.
98 class SAL_WARN_UNUSED ClassificationControl final
: public InterimItemWindow
100 std::unique_ptr
<weld::Label
> m_xLabel
;
101 std::unique_ptr
<weld::ComboBox
> m_xCategory
;
103 DECL_LINK(KeyInputHdl
, const KeyEvent
&, bool);
105 void SetOptimalSize();
106 void DataChanged(const DataChangedEvent
& rEvent
) override
;
109 explicit ClassificationControl(vcl::Window
* pParent
);
110 ~ClassificationControl() override
;
111 void dispose() override
;
112 weld::ComboBox
& getCategory()
116 void set_sensitive(bool bSensitive
)
119 m_xContainer
->set_sensitive(bSensitive
);
121 static sfx::ClassificationCreationOrigin
getExistingClassificationOrigin();
122 void toggleInteractivityOnOrigin();
123 void setCategoryStateFromPolicy(const SfxClassificationHelper
& rHelper
);
126 OUString
const & getCategoryType()
128 return SfxClassificationHelper::policyTypeToString(SfxClassificationHelper::getPolicyType());
131 } // end anonymous namespace
133 ClassificationPropertyListener::ClassificationPropertyListener(const rtl::Reference
<comphelper::ConfigurationListener
>& xListener
, ClassificationCategoriesController
& rController
)
134 : ClassificationPropertyListenerBase(xListener
, u
"WritePath"_ustr
)
135 , m_rController(rController
)
139 void ClassificationPropertyListener::setProperty(const uno::Any
& /*rProperty*/)
141 // So that its gets re-filled with entries from the new policy.
142 m_rController
.removeEntries();
145 ClassificationCategoriesController::ClassificationCategoriesController(const uno::Reference
<uno::XComponentContext
>& rContext
)
146 : ClassificationCategoriesControllerBase(rContext
, uno::Reference
<frame::XFrame
>(), u
".uno:ClassificationApply"_ustr
)
147 , m_pClassification(nullptr)
148 , m_xListener(new comphelper::ConfigurationListener(u
"/org.openoffice.Office.Paths/Paths/Classification"_ustr
))
149 , m_aPropertyListener(m_xListener
, *this)
154 OUString
ClassificationCategoriesController::getImplementationName()
156 return u
"com.sun.star.comp.sfx2.ClassificationCategoriesController"_ustr
;
159 sal_Bool
ClassificationCategoriesController::supportsService(const OUString
& rServiceName
)
161 return cppu::supportsService(this, rServiceName
);
164 uno::Sequence
<OUString
> ClassificationCategoriesController::getSupportedServiceNames()
166 return { u
"com.sun.star.frame.ToolbarController"_ustr
};
169 void ClassificationCategoriesController::dispose()
171 SolarMutexGuard aSolarMutexGuard
;
173 svt::ToolboxController::dispose();
174 m_pClassification
.disposeAndClear();
175 m_aPropertyListener
.dispose();
176 m_xListener
->dispose();
179 uno::Reference
<awt::XWindow
> ClassificationCategoriesController::createItemWindow(const uno::Reference
<awt::XWindow
>& rParent
)
181 VclPtr
<vcl::Window
> pParent
= VCLUnoHelper::GetWindow(rParent
);
182 auto pToolbar
= dynamic_cast<ToolBox
*>(pParent
.get());
185 m_pClassification
= VclPtr
<ClassificationControl
>::Create(pToolbar
);
186 m_pClassification
->getCategory().connect_changed(LINK(this, ClassificationCategoriesController
, SelectHdl
));
187 m_pClassification
->Show();
190 return VCLUnoHelper::GetInterface(m_pClassification
);
193 IMPL_LINK(ClassificationCategoriesController
, SelectHdl
, weld::ComboBox
&, rCategory
, void)
195 m_pClassification
->toggleInteractivityOnOrigin();
197 if (ClassificationControl::getExistingClassificationOrigin() == sfx::ClassificationCreationOrigin::MANUAL
)
199 SfxObjectShell
* pObjectShell
= SfxObjectShell::Current();
202 SfxClassificationHelper
aHelper(pObjectShell
->getDocProperties());
203 m_pClassification
->setCategoryStateFromPolicy(aHelper
);
207 OUString aEntry
= rCategory
.get_active_text();
209 const OUString
& aType
= getCategoryType();
210 uno::Sequence
<beans::PropertyValue
> aPropertyValues(comphelper::InitPropertySequence({
211 {"Name", uno::Any(aEntry
)},
212 {"Type", uno::Any(aType
)},
214 comphelper::dispatchCommand(u
".uno:ClassificationApply"_ustr
, aPropertyValues
);
218 void ClassificationCategoriesController::statusChanged(const frame::FeatureStateEvent
& /*rEvent*/)
220 if (!m_pClassification
)
223 SfxObjectShell
* pObjectShell
= SfxObjectShell::Current();
227 SfxClassificationHelper
aHelper(pObjectShell
->getDocProperties());
229 //toggle if the pop-up is enabled/disabled
230 m_pClassification
->toggleInteractivityOnOrigin();
232 // check if classification was set via the advanced dialog
233 if (ClassificationControl::getExistingClassificationOrigin() != sfx::ClassificationCreationOrigin::MANUAL
)
235 weld::ComboBox
& rCategories
= m_pClassification
->getCategory();
236 if (rCategories
.get_count() == 0)
238 std::vector
<OUString
> aNames
= aHelper
.GetBACNames();
239 for (const OUString
& rName
: aNames
)
240 rCategories
.append_text(rName
);
244 // Restore state based on the doc. model.
245 m_pClassification
->setCategoryStateFromPolicy(aHelper
);
249 void ClassificationCategoriesController::removeEntries()
251 m_pClassification
->getCategory().clear();
254 ClassificationControl::ClassificationControl(vcl::Window
* pParent
)
255 : InterimItemWindow(pParent
, u
"sfx/ui/classificationbox.ui"_ustr
, u
"ClassificationBox"_ustr
)
256 , m_xLabel(m_xBuilder
->weld_label(u
"label"_ustr
))
257 , m_xCategory(m_xBuilder
->weld_combo_box(u
"combobox"_ustr
))
259 InitControlBase(m_xCategory
.get());
261 m_xCategory
->connect_key_press(LINK(this, ClassificationControl
, KeyInputHdl
));
263 // WB_NOLABEL means here that the control won't be replaced with a label
264 // when it wouldn't fit the available space.
265 SetStyle(GetStyle() | WB_DIALOGCONTROL
| WB_NOLABEL
);
268 switch (SfxClassificationHelper::getPolicyType())
270 case SfxClassificationPolicyType::IntellectualProperty
:
271 aText
= SfxResId(STR_CLASSIFIED_INTELLECTUAL_PROPERTY
);
273 case SfxClassificationPolicyType::NationalSecurity
:
274 aText
= SfxResId(STR_CLASSIFIED_NATIONAL_SECURITY
);
276 case SfxClassificationPolicyType::ExportControl
:
277 aText
= SfxResId(STR_CLASSIFIED_EXPORT_CONTROL
);
281 m_xLabel
->set_label(aText
);
283 // Same as SvxColorDockingWindow.
284 const Size
aLogicalAttrSize(150, 0);
285 Size
aSize(LogicToPixel(aLogicalAttrSize
, MapMode(MapUnit::MapAppFont
)));
286 m_xCategory
->set_size_request(aSize
.Width() - m_xLabel
->get_preferred_size().Width(), -1);
291 IMPL_LINK(ClassificationControl
, KeyInputHdl
, const KeyEvent
&, rKEvt
, bool)
293 return ChildKeyInput(rKEvt
);
296 ClassificationControl::~ClassificationControl()
301 void ClassificationControl::dispose()
305 InterimItemWindow::dispose();
308 void ClassificationControl::SetOptimalSize()
310 SetSizePixel(get_preferred_size());
313 void ClassificationControl::DataChanged(const DataChangedEvent
& rEvent
)
315 if ((rEvent
.GetType() == DataChangedEventType::SETTINGS
) && (rEvent
.GetFlags() & AllSettingsFlags::STYLE
))
318 toggleInteractivityOnOrigin();
320 InterimItemWindow::DataChanged(rEvent
);
323 sfx::ClassificationCreationOrigin
ClassificationControl::getExistingClassificationOrigin()
325 SfxObjectShell
* pObjectShell
= SfxObjectShell::Current();
327 return sfx::ClassificationCreationOrigin::NONE
;
329 uno::Reference
<document::XDocumentProperties
> xDocumentProperties
= pObjectShell
->getDocProperties();
330 uno::Reference
<beans::XPropertyContainer
> xPropertyContainer
= xDocumentProperties
->getUserDefinedProperties();
332 sfx::ClassificationKeyCreator
aKeyCreator(SfxClassificationHelper::getPolicyType());
333 return sfx::getCreationOriginProperty(xPropertyContainer
, aKeyCreator
);
336 void ClassificationControl::toggleInteractivityOnOrigin()
338 if (getExistingClassificationOrigin() == sfx::ClassificationCreationOrigin::MANUAL
)
340 set_sensitive(false);
348 void ClassificationControl::setCategoryStateFromPolicy(const SfxClassificationHelper
& rHelper
)
350 const OUString
& rCategoryName
= rHelper
.GetBACName(SfxClassificationHelper::getPolicyType());
351 if (!rCategoryName
.isEmpty())
353 getCategory().set_active_text(rCategoryName
);
359 extern "C" SAL_DLLPUBLIC_EXPORT
uno::XInterface
* com_sun_star_sfx2_ClassificationCategoriesController_get_implementation(uno::XComponentContext
* pContext
, const uno::Sequence
<uno::Any
>&)
361 return cppu::acquire(new sfx2::ClassificationCategoriesController(pContext
));
364 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */