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 <com/sun/star/frame/XFrame.hpp>
21 #include <com/sun/star/frame/status/FontHeight.hpp>
22 #include <com/sun/star/frame/XDispatchProvider.hpp>
23 #include <com/sun/star/beans/PropertyValue.hpp>
24 #include <com/sun/star/lang/XServiceInfo.hpp>
25 #include <com/sun/star/util/XURLTransformer.hpp>
27 #include <comphelper/propertyvalue.hxx>
28 #include <rtl/math.hxx>
30 #include <vcl/event.hxx>
31 #include <vcl/svapp.hxx>
32 #include <vcl/weldutils.hxx>
33 #include <vcl/window.hxx>
34 #include <vcl/settings.hxx>
35 #include <toolkit/helper/vclunohelper.hxx>
36 #include <svtools/ctrltool.hxx>
37 #include <svtools/ctrlbox.hxx>
38 #include <svtools/toolboxcontroller.hxx>
39 #include <tools/json_writer.hxx>
40 #include <vcl/toolbox.hxx>
41 #include <cppuhelper/queryinterface.hxx>
42 #include <cppuhelper/supportsservice.hxx>
46 #include <vcl/InterimItemWindow.hxx>
48 using namespace ::com::sun::star
;
52 class SvxFontSizeBox_Base
;
53 class SvxFontSizeBox_Impl
;
55 typedef cppu::ImplInheritanceHelper
< ::svt::ToolboxController
, lang::XServiceInfo
> FontHeightToolBoxControl_Base
;
56 class FontHeightToolBoxControl
: public FontHeightToolBoxControl_Base
59 explicit FontHeightToolBoxControl(
60 const css::uno::Reference
< css::uno::XComponentContext
>& rServiceManager
);
63 virtual OUString SAL_CALL
getImplementationName() override
;
64 virtual sal_Bool SAL_CALL
supportsService( const OUString
& ServiceName
) override
;
65 virtual css::uno::Sequence
< OUString
> SAL_CALL
getSupportedServiceNames() override
;
68 virtual void SAL_CALL
dispose() override
;
71 virtual void SAL_CALL
statusChanged( const css::frame::FeatureStateEvent
& Event
) override
;
74 virtual void SAL_CALL
execute( sal_Int16 KeyModifier
) override
;
75 virtual void SAL_CALL
click() override
;
76 virtual void SAL_CALL
doubleClick() override
;
77 virtual css::uno::Reference
< css::awt::XWindow
> SAL_CALL
createPopupWindow() override
;
78 virtual css::uno::Reference
< css::awt::XWindow
> SAL_CALL
createItemWindow( const css::uno::Reference
< css::awt::XWindow
>& Parent
) override
;
80 void dispatchCommand( const css::uno::Sequence
< css::beans::PropertyValue
>& rArgs
);
81 using svt::ToolboxController::dispatchCommand
;
84 VclPtr
<SvxFontSizeBox_Impl
> m_xVclBox
;
85 std::unique_ptr
<SvxFontSizeBox_Base
> m_xWeldBox
;
86 SvxFontSizeBox_Base
* m_pBox
;
89 class SvxFontSizeBox_Base
92 SvxFontSizeBox_Base(std::unique_ptr
<weld::ComboBox
> xWidget
,
93 uno::Reference
< frame::XFrame
> _xFrame
,
94 FontHeightToolBoxControl
& rCtrl
);
96 virtual ~SvxFontSizeBox_Base()
100 virtual void set_sensitive(bool bSensitive
)
102 m_xWidget
->set_sensitive(bSensitive
);
105 void statusChanged_Impl(tools::Long nHeight
, bool bErase
);
109 FontHeightToolBoxControl
& m_rCtrl
;
112 uno::Reference
<frame::XFrame
> m_xFrame
;
113 std::unique_ptr
<FontSizeBox
> m_xWidget
;
115 void ReleaseFocus_Impl();
118 virtual bool DoKeyInput(const KeyEvent
& rKEvt
);
120 DECL_LINK(SelectHdl
, weld::ComboBox
&, void);
121 DECL_LINK(KeyInputHdl
, const KeyEvent
&, bool);
122 DECL_LINK(ActivateHdl
, weld::ComboBox
&, bool);
123 DECL_LINK(FocusOutHdl
, weld::Widget
&, void);
124 DECL_LINK(DumpAsPropertyTreeHdl
, tools::JsonWriter
&, void);
127 class SvxFontSizeBox_Impl final
: public InterimItemWindow
128 , public SvxFontSizeBox_Base
131 SvxFontSizeBox_Impl(vcl::Window
* pParent
,
132 const uno::Reference
< frame::XFrame
>& _xFrame
,
133 FontHeightToolBoxControl
& rCtrl
);
135 virtual void dispose() override
138 InterimItemWindow::dispose();
141 virtual void GetFocus() override
144 m_xWidget
->grab_focus();
145 InterimItemWindow::GetFocus();
148 virtual ~SvxFontSizeBox_Impl() override
153 void SetOptimalSize();
155 virtual void DataChanged(const DataChangedEvent
& rDCEvt
) override
;
157 virtual void set_sensitive(bool bSensitive
) override
159 m_xWidget
->set_sensitive(bSensitive
);
161 InterimItemWindow::Enable();
163 InterimItemWindow::Disable();
167 virtual bool DoKeyInput(const KeyEvent
& rKEvt
) override
;
170 SvxFontSizeBox_Base::SvxFontSizeBox_Base(std::unique_ptr
<weld::ComboBox
> xWidget
,
171 uno::Reference
<frame::XFrame
> xFrame
,
172 FontHeightToolBoxControl
& rCtrl
)
175 , m_xFrame(std::move(xFrame
))
176 , m_xWidget(new FontSizeBox(std::move(xWidget
)))
178 m_xWidget
->set_value(0);
179 m_xWidget
->set_active_or_entry_text("");
180 m_xWidget
->disable_entry_completion();
182 m_xWidget
->connect_changed(LINK(this, SvxFontSizeBox_Base
, SelectHdl
));
183 m_xWidget
->connect_key_press(LINK(this, SvxFontSizeBox_Base
, KeyInputHdl
));
184 m_xWidget
->connect_entry_activate(LINK(this, SvxFontSizeBox_Base
, ActivateHdl
));
185 m_xWidget
->connect_focus_out(LINK(this, SvxFontSizeBox_Base
, FocusOutHdl
));
186 m_xWidget
->connect_get_property_tree(LINK(this, SvxFontSizeBox_Base
, DumpAsPropertyTreeHdl
));
189 void SvxFontSizeBox_Base::ReleaseFocus_Impl()
197 if ( m_xFrame
.is() && m_xFrame
->getContainerWindow().is() )
198 m_xFrame
->getContainerWindow()->setFocus();
201 IMPL_LINK(SvxFontSizeBox_Base
, SelectHdl
, weld::ComboBox
&, rCombo
, void)
203 if (rCombo
.changed_by_direct_pick()) // only when picked from the list
207 IMPL_LINK_NOARG(SvxFontSizeBox_Base
, ActivateHdl
, weld::ComboBox
&, bool)
213 void SvxFontSizeBox_Base::Select()
215 sal_Int64 nSelVal
= m_xWidget
->get_value();
216 float fSelVal
= float( nSelVal
) / 10;
218 uno::Sequence
< beans::PropertyValue
> aArgs
{ comphelper::makePropertyValue("FontHeight.Height",
221 /* #i33380# DR 2004-09-03 Moved the following line above the Dispatch() call.
222 This instance may be deleted in the meantime (i.e. when a dialog is opened
223 while in Dispatch()), accessing members will crash in this case. */
226 m_rCtrl
.dispatchCommand( aArgs
);
229 void SvxFontSizeBox_Base::statusChanged_Impl( tools::Long nPoint
, bool bErase
)
233 // convert the metric
234 tools::Long nVal
= nPoint
;
236 // changed => set new value
237 if (m_xWidget
->get_value() != nVal
)
238 m_xWidget
->set_value(nVal
);
242 // delete value in the display
243 m_xWidget
->set_value(-1L);
244 m_xWidget
->set_active_or_entry_text("");
246 m_aCurText
= m_xWidget
->get_active_text();
249 void SvxFontSizeBox_Base::UpdateFont()
251 // filling up the sizes list
252 auto nOldVal
= m_xWidget
->get_value(); // memorize old value
253 FontList
aFontList(Application::GetDefaultDevice());
255 m_xWidget
->Fill(&aFontList
);
257 m_xWidget
->set_value(nOldVal
); // restore old value
258 m_aCurText
= m_xWidget
->get_active_text(); // memorize to reset at ESC
261 IMPL_LINK(SvxFontSizeBox_Base
, KeyInputHdl
, const KeyEvent
&, rKEvt
, bool)
263 return DoKeyInput(rKEvt
);
266 bool SvxFontSizeBox_Base::DoKeyInput(const KeyEvent
& rKEvt
)
268 bool bHandled
= false;
270 sal_uInt16 nCode
= rKEvt
.GetKeyCode().GetCode();
280 m_xWidget
->set_active_or_entry_text(m_aCurText
);
281 if (!m_rCtrl
.IsInSidebar())
292 bool SvxFontSizeBox_Impl::DoKeyInput(const KeyEvent
& rKEvt
)
294 return SvxFontSizeBox_Base::DoKeyInput(rKEvt
) || ChildKeyInput(rKEvt
);
297 IMPL_LINK_NOARG(SvxFontSizeBox_Base
, FocusOutHdl
, weld::Widget
&, void)
299 if (!m_xWidget
->has_focus()) // a combobox can be comprised of different subwidget so double-check if none of those has focus
300 m_xWidget
->set_active_or_entry_text(m_aCurText
);
303 void SvxFontSizeBox_Impl::SetOptimalSize()
305 SetSizePixel(get_preferred_size());
308 SvxFontSizeBox_Impl::SvxFontSizeBox_Impl(vcl::Window
* pParent
,
309 const uno::Reference
<frame::XFrame
>& rFrame
,
310 FontHeightToolBoxControl
& rCtrl
)
311 : InterimItemWindow(pParent
, "svx/ui/fontsizebox.ui", "FontSizeBox")
312 , SvxFontSizeBox_Base(m_xBuilder
->weld_combo_box("fontsizecombobox"), rFrame
, rCtrl
)
316 void SvxFontSizeBox_Impl::DataChanged( const DataChangedEvent
& rDCEvt
)
318 if ( (rDCEvt
.GetType() == DataChangedEventType::SETTINGS
) &&
319 (rDCEvt
.GetFlags() & AllSettingsFlags::STYLE
) )
325 IMPL_LINK(SvxFontSizeBox_Base
, DumpAsPropertyTreeHdl
, tools::JsonWriter
&, rJsonWriter
, void)
328 auto entriesNode
= rJsonWriter
.startNode("entries");
329 for (int i
= 0, nCount
= m_xWidget
->get_count(); i
< nCount
; ++i
)
331 auto entryNode
= rJsonWriter
.startNode("");
332 rJsonWriter
.put("", m_xWidget
->get_text(i
));
336 int nActive
= m_xWidget
->get_active();
337 rJsonWriter
.put("selectedCount", static_cast<sal_Int32
>(nActive
== -1 ? 0 : 1));
339 auto selectedNode
= rJsonWriter
.startNode("selectedEntries");
342 auto node
= rJsonWriter
.startNode("");
343 rJsonWriter
.put("", static_cast<sal_Int32
>(nActive
));
347 rJsonWriter
.put("command", ".uno:FontHeight");
350 FontHeightToolBoxControl::FontHeightToolBoxControl( const uno::Reference
< uno::XComponentContext
>& rxContext
)
351 : FontHeightToolBoxControl_Base( rxContext
,
352 uno::Reference
< frame::XFrame
>(),
356 addStatusListener( ".uno:CharFontName");
360 sal_Bool SAL_CALL
FontHeightToolBoxControl::supportsService( const OUString
& ServiceName
)
362 return cppu::supportsService(this, ServiceName
);
365 OUString SAL_CALL
FontHeightToolBoxControl::getImplementationName()
367 return "com.sun.star.svx.FontHeightToolBoxController";
370 uno::Sequence
< OUString
> SAL_CALL
FontHeightToolBoxControl::getSupportedServiceNames( )
372 return { "com.sun.star.frame.ToolbarController" };
376 void SAL_CALL
FontHeightToolBoxControl::dispose()
378 svt::ToolboxController::dispose();
380 SolarMutexGuard aSolarMutexGuard
;
381 m_xVclBox
.disposeAndClear();
387 void SAL_CALL
FontHeightToolBoxControl::statusChanged(
388 const frame::FeatureStateEvent
& rEvent
)
393 SolarMutexGuard aSolarMutexGuard
;
394 if (rEvent
.FeatureURL
.Path
== "FontHeight")
396 if ( rEvent
.IsEnabled
)
398 m_pBox
->set_sensitive(true);
399 frame::status::FontHeight aFontHeight
;
400 if ( rEvent
.State
>>= aFontHeight
)
402 // tdf#83090 - correctly round the height of the font
403 aFontHeight
.Height
= rtl::math::round(10. * aFontHeight
.Height
);
404 m_pBox
->statusChanged_Impl(tools::Long(aFontHeight
.Height
), false);
407 m_pBox
->statusChanged_Impl( tools::Long( -1 ), true );
411 m_pBox
->set_sensitive(false);
412 m_pBox
->statusChanged_Impl( tools::Long( -1 ), true );
416 m_pToolbar
->set_item_sensitive(m_aCommandURL
, rEvent
.IsEnabled
);
419 ToolBox
* pToolBox
= nullptr;
421 if (getToolboxId(nId
, &pToolBox
))
422 pToolBox
->EnableItem(nId
, rEvent
.IsEnabled
);
425 else if ( rEvent
.FeatureURL
.Path
== "CharFontName" )
427 m_pBox
->UpdateFont();
431 // XToolbarController
432 void SAL_CALL
FontHeightToolBoxControl::execute( sal_Int16
/*KeyModifier*/ )
436 void SAL_CALL
FontHeightToolBoxControl::click()
440 void SAL_CALL
FontHeightToolBoxControl::doubleClick()
444 uno::Reference
< awt::XWindow
> SAL_CALL
FontHeightToolBoxControl::createPopupWindow()
446 return uno::Reference
< awt::XWindow
>();
449 uno::Reference
< awt::XWindow
> SAL_CALL
FontHeightToolBoxControl::createItemWindow(
450 const uno::Reference
< awt::XWindow
>& xParent
)
452 uno::Reference
< awt::XWindow
> xItemWindow
;
456 SolarMutexGuard aSolarMutexGuard
;
458 std::unique_ptr
<weld::ComboBox
> xWidget(m_pBuilder
->weld_combo_box("fontsizecombobox"));
460 xItemWindow
= css::uno::Reference
<css::awt::XWindow
>(new weld::TransportAsXWindow(xWidget
.get()));
462 m_xWeldBox
.reset(new SvxFontSizeBox_Base(std::move(xWidget
), m_xFrame
, *this));
463 m_pBox
= m_xWeldBox
.get();
464 //Get the box to fill itself with all its sizes
465 m_pBox
->UpdateFont();
469 VclPtr
<vcl::Window
> pParent
= VCLUnoHelper::GetWindow( xParent
);
472 SolarMutexGuard aSolarMutexGuard
;
473 m_xVclBox
= VclPtr
<SvxFontSizeBox_Impl
>::Create( pParent
, m_xFrame
, *this );
474 m_pBox
= m_xVclBox
.get();
475 //Get the box to fill itself with all its sizes
476 m_pBox
->UpdateFont();
477 //Make it size itself to its optimal size re above sizes
478 m_xVclBox
->SetOptimalSize();
479 xItemWindow
= VCLUnoHelper::GetInterface(m_xVclBox
);
486 void FontHeightToolBoxControl::dispatchCommand(
487 const uno::Sequence
< beans::PropertyValue
>& rArgs
)
489 uno::Reference
< frame::XDispatchProvider
> xDispatchProvider( m_xFrame
, uno::UNO_QUERY
);
490 if ( xDispatchProvider
.is() )
493 uno::Reference
< frame::XDispatch
> xDispatch
;
494 uno::Reference
< util::XURLTransformer
> xURLTransformer
= getURLTransformer();
496 aURL
.Complete
= ".uno:FontHeight";
497 xURLTransformer
->parseStrict( aURL
);
498 xDispatch
= xDispatchProvider
->queryDispatch( aURL
, OUString(), 0 );
499 if ( xDispatch
.is() )
500 xDispatch
->dispatch( aURL
, rArgs
);
506 extern "C" SAL_DLLPUBLIC_EXPORT
css::uno::XInterface
*
507 com_sun_star_svx_FontHeightToolBoxController_get_implementation(
508 css::uno::XComponentContext
*rxContext
,
509 css::uno::Sequence
<css::uno::Any
> const &)
511 return cppu::acquire(new FontHeightToolBoxControl(rxContext
));
514 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */