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>
14 #include <com/sun/star/uno/XComponentContext.hpp>
15 #include <com/sun/star/frame/XFrame.hpp>
17 #include <vcl/vclptr.hxx>
18 #include <vcl/lstbox.hxx>
19 #include <vcl/svapp.hxx>
20 #include <toolkit/helper/vclunohelper.hxx>
21 #include <vcl/toolbox.hxx>
22 #include <vcl/fixed.hxx>
23 #include <sfx2/viewfrm.hxx>
24 #include <sfx2/classificationhelper.hxx>
25 #include <sfx2/strings.hrc>
26 #include <sfx2/sfxresid.hxx>
27 #include <cppuhelper/supportsservice.hxx>
28 #include <comphelper/propertysequence.hxx>
29 #include <comphelper/dispatchcommand.hxx>
30 #include <comphelper/configurationlistener.hxx>
32 using namespace com::sun::star
;
37 class ClassificationCategoriesController
;
38 using ClassificationPropertyListenerBase
= comphelper::ConfigurationListenerProperty
<OUString
>;
40 /// Listens to configuration changes, so no restart is needed after setting the classification path.
41 class ClassificationPropertyListener
: public ClassificationPropertyListenerBase
43 ClassificationCategoriesController
& m_rController
;
46 ClassificationPropertyListener(const rtl::Reference
<comphelper::ConfigurationListener
>& xListener
, ClassificationCategoriesController
& rController
);
47 void setProperty(const uno::Any
& rProperty
) override
;
50 using ClassificationCategoriesControllerBase
= cppu::ImplInheritanceHelper
<svt::ToolboxController
, lang::XServiceInfo
>;
52 class ClassificationControl
;
54 /// Controller for .uno:ClassificationApply.
55 class ClassificationCategoriesController
: public ClassificationCategoriesControllerBase
57 VclPtr
<ClassificationControl
> m_pClassification
;
58 rtl::Reference
<comphelper::ConfigurationListener
> m_xListener
;
59 ClassificationPropertyListener m_aPropertyListener
;
61 DECL_LINK(SelectHdl
, ListBox
&, void);
64 explicit ClassificationCategoriesController(const uno::Reference
<uno::XComponentContext
>& rContext
);
67 OUString SAL_CALL
getImplementationName() override
;
68 sal_Bool SAL_CALL
supportsService(const OUString
& rServiceName
) override
;
69 uno::Sequence
<OUString
> SAL_CALL
getSupportedServiceNames() override
;
72 void SAL_CALL
dispose() override
;
75 uno::Reference
<awt::XWindow
> SAL_CALL
createItemWindow(const uno::Reference
<awt::XWindow
>& rParent
) override
;
78 void SAL_CALL
statusChanged(const frame::FeatureStateEvent
& rEvent
) override
;
83 /// Classification control is the parent of all widgets that belongs to ClassificationCategoriesController.
84 class SAL_WARN_UNUSED ClassificationControl
: public vcl::Window
86 VclPtr
<FixedText
> m_pLabel
;
87 VclPtr
<ListBox
> m_pCategory
;
88 void SetOptimalSize();
89 void DataChanged(const DataChangedEvent
& rEvent
) override
;
92 explicit ClassificationControl(vcl::Window
* pParent
);
93 ~ClassificationControl() override
;
94 void dispose() override
;
95 void Resize() override
;
96 const VclPtr
<ListBox
>& getCategory()
100 sfx::ClassificationCreationOrigin
getExistingClassificationOrigin();
101 void toggleInteractivityOnOrigin();
102 void setCategoryStateFromPolicy(SfxClassificationHelper
& rHelper
);
108 OUString
const & getCategoryType()
110 return SfxClassificationHelper::policyTypeToString(SfxClassificationHelper::getPolicyType());
113 } // end anonymous namespace
115 ClassificationPropertyListener::ClassificationPropertyListener(const rtl::Reference
<comphelper::ConfigurationListener
>& xListener
, ClassificationCategoriesController
& rController
)
116 : ClassificationPropertyListenerBase(xListener
, "WritePath")
117 , m_rController(rController
)
121 void ClassificationPropertyListener::setProperty(const uno::Any
& /*rProperty*/)
123 // So that its gets re-filled with entries from the new policy.
124 m_rController
.removeEntries();
127 ClassificationCategoriesController::ClassificationCategoriesController(const uno::Reference
<uno::XComponentContext
>& rContext
)
128 : ClassificationCategoriesControllerBase(rContext
, uno::Reference
<frame::XFrame
>(), OUString(".uno:ClassificationApply"))
129 , m_pClassification(nullptr)
130 , m_xListener(new comphelper::ConfigurationListener("/org.openoffice.Office.Paths/Paths/Classification"))
131 , m_aPropertyListener(m_xListener
, *this)
136 OUString
ClassificationCategoriesController::getImplementationName()
138 return OUString("com.sun.star.comp.sfx2.ClassificationCategoriesController");
141 sal_Bool
ClassificationCategoriesController::supportsService(const OUString
& rServiceName
)
143 return cppu::supportsService(this, rServiceName
);
146 uno::Sequence
<OUString
> ClassificationCategoriesController::getSupportedServiceNames()
148 return { "com.sun.star.frame.ToolbarController" };
151 void ClassificationCategoriesController::dispose()
153 SolarMutexGuard aSolarMutexGuard
;
155 svt::ToolboxController::dispose();
156 m_pClassification
.disposeAndClear();
157 m_aPropertyListener
.dispose();
158 m_xListener
->dispose();
161 uno::Reference
<awt::XWindow
> ClassificationCategoriesController::createItemWindow(const uno::Reference
<awt::XWindow
>& rParent
)
163 VclPtr
<vcl::Window
> pParent
= VCLUnoHelper::GetWindow(rParent
);
164 auto pToolbar
= dynamic_cast<ToolBox
*>(pParent
.get());
167 m_pClassification
= VclPtr
<ClassificationControl
>::Create(pToolbar
);
168 m_pClassification
->getCategory()->SetSelectHdl(LINK(this, ClassificationCategoriesController
, SelectHdl
));
171 return VCLUnoHelper::GetInterface(m_pClassification
);
174 IMPL_LINK(ClassificationCategoriesController
, SelectHdl
, ListBox
&, rCategory
, void)
176 m_pClassification
->toggleInteractivityOnOrigin();
178 if (m_pClassification
->getExistingClassificationOrigin() == sfx::ClassificationCreationOrigin::MANUAL
)
180 SfxObjectShell
* pObjectShell
= SfxObjectShell::Current();
183 SfxClassificationHelper
aHelper(pObjectShell
->getDocProperties());
184 m_pClassification
->setCategoryStateFromPolicy(aHelper
);
188 OUString aEntry
= rCategory
.GetSelectedEntry();
190 OUString aType
= getCategoryType();
191 uno::Sequence
<beans::PropertyValue
> aPropertyValues(comphelper::InitPropertySequence({
192 {"Name", uno::makeAny(aEntry
)},
193 {"Type", uno::makeAny(aType
)},
195 comphelper::dispatchCommand(".uno:ClassificationApply", aPropertyValues
);
199 void ClassificationCategoriesController::statusChanged(const frame::FeatureStateEvent
& /*rEvent*/)
201 if (!m_pClassification
)
204 SfxObjectShell
* pObjectShell
= SfxObjectShell::Current();
208 SfxClassificationHelper
aHelper(pObjectShell
->getDocProperties());
210 //toggle if the pop-up is enabled/disabled
211 m_pClassification
->toggleInteractivityOnOrigin();
213 // check if classification was set via the advanced dialog
214 if (m_pClassification
->getExistingClassificationOrigin() != sfx::ClassificationCreationOrigin::MANUAL
)
216 VclPtr
<ListBox
> pCategories
= m_pClassification
->getCategory();
217 if (pCategories
->GetEntryCount() == 0)
219 std::vector
<OUString
> aNames
= aHelper
.GetBACNames();
220 for (const OUString
& rName
: aNames
)
221 pCategories
->InsertEntry(rName
);
222 // Normally VclBuilder::makeObject() does this.
223 pCategories
->EnableAutoSize(true);
227 // Restore state based on the doc. model.
228 m_pClassification
->setCategoryStateFromPolicy(aHelper
);
232 void ClassificationCategoriesController::removeEntries()
234 m_pClassification
->getCategory()->Clear();
237 // WB_NOLABEL means here that the control won't be replaced with a label
238 // when it wouldn't fit the available space.
239 ClassificationControl::ClassificationControl(vcl::Window
* pParent
)
240 : Window(pParent
, WB_DIALOGCONTROL
| WB_NOLABEL
)
242 m_pLabel
= VclPtr
<FixedText
>::Create(this, WB_CENTER
);
243 m_pCategory
= VclPtr
<ListBox
>::Create(this, WB_CLIPCHILDREN
|WB_LEFT
|WB_VCENTER
|WB_3DLOOK
|WB_DROPDOWN
|WB_SIMPLEMODE
);
246 switch (SfxClassificationHelper::getPolicyType())
248 case SfxClassificationPolicyType::IntellectualProperty
:
249 aText
= SfxResId(STR_CLASSIFIED_INTELLECTUAL_PROPERTY
);
251 case SfxClassificationPolicyType::NationalSecurity
:
252 aText
= SfxResId(STR_CLASSIFIED_NATIONAL_SECURITY
);
254 case SfxClassificationPolicyType::ExportControl
:
255 aText
= SfxResId(STR_CLASSIFIED_EXPORT_CONTROL
);
258 Size
aTextSize(m_pLabel
->GetTextWidth(aText
), m_pLabel
->GetTextHeight());
261 aTextSize
.AdjustWidth(12 );
262 m_pLabel
->SetText(aText
);
263 m_pLabel
->SetSizePixel(aTextSize
);
271 ClassificationControl::~ClassificationControl()
276 void ClassificationControl::dispose()
278 m_pLabel
.disposeAndClear();
279 m_pCategory
.disposeAndClear();
280 vcl::Window::dispose();
283 void ClassificationControl::Resize()
285 // Give the label what it wants, and the remaining size to the listbox.
286 Size
aSize(GetOutputSizePixel());
288 long nWLabel
= m_pLabel
->GetOutputSizePixel().Width();
289 long nW
= aSize
.Width();
290 long nH
= aSize
.Height();
292 long nPrefHeight
= m_pLabel
->get_preferred_size().Height();
293 long nOffset
= (nH
- nPrefHeight
) / 2;
294 m_pLabel
->SetPosSizePixel(Point(0, nOffset
), Size(nWLabel
, nPrefHeight
));
296 nPrefHeight
= m_pCategory
->get_preferred_size().Height();
297 nOffset
= (nH
- nPrefHeight
) / 2;
298 m_pCategory
->SetPosSizePixel(Point(0 + nWLabel
, nOffset
), Size(nW
- nWLabel
, nPrefHeight
));
301 void ClassificationControl::SetOptimalSize()
303 // Same as SvxColorDockingWindow.
304 const Size
aLogicalAttrSize(150, 0);
305 Size
aSize(LogicToPixel(aLogicalAttrSize
, MapMode(MapUnit::MapAppFont
)));
307 Point aPosition
= m_pCategory
->GetPosPixel();
309 aSize
.setHeight( std::max(aSize
.Height(), m_pLabel
->get_preferred_size().Height()) );
310 aSize
.setHeight( std::max(aSize
.Height(), m_pCategory
->get_preferred_size().Height()) );
312 aSize
.setWidth( aPosition
.X() + aSize
.Width() );
317 void ClassificationControl::DataChanged(const DataChangedEvent
& rEvent
)
319 if ((rEvent
.GetType() == DataChangedEventType::SETTINGS
) && (rEvent
.GetFlags() & AllSettingsFlags::STYLE
))
322 toggleInteractivityOnOrigin();
324 Window::DataChanged(rEvent
);
327 sfx::ClassificationCreationOrigin
ClassificationControl::getExistingClassificationOrigin()
329 SfxObjectShell
* pObjectShell
= SfxObjectShell::Current();
331 return sfx::ClassificationCreationOrigin::NONE
;
333 uno::Reference
<document::XDocumentProperties
> xDocumentProperties
= pObjectShell
->getDocProperties();
334 uno::Reference
<beans::XPropertyContainer
> xPropertyContainer
= xDocumentProperties
->getUserDefinedProperties();
336 sfx::ClassificationKeyCreator
aKeyCreator(SfxClassificationHelper::getPolicyType());
337 return sfx::getCreationOriginProperty(xPropertyContainer
, aKeyCreator
);
340 void ClassificationControl::toggleInteractivityOnOrigin()
342 if (getExistingClassificationOrigin() == sfx::ClassificationCreationOrigin::MANUAL
)
352 void ClassificationControl::setCategoryStateFromPolicy(SfxClassificationHelper
& rHelper
)
354 const OUString
& rCategoryName
= rHelper
.GetBACName(SfxClassificationHelper::getPolicyType());
355 if (!rCategoryName
.isEmpty())
357 getCategory()->SelectEntry(rCategoryName
);
363 extern "C" SAL_DLLPUBLIC_EXPORT
uno::XInterface
* com_sun_star_sfx2_ClassificationCategoriesController_get_implementation(uno::XComponentContext
* pContext
, const uno::Sequence
<uno::Any
>&)
365 return cppu::acquire(new sfx2::ClassificationCategoriesController(pContext
));
368 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */