LibreOffice Module svx (master) 1
tbunocontroller.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
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>
26
28#include <rtl/math.hxx>
29#include <utility>
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>
36#include <svtools/ctrltool.hxx>
37#include <svtools/ctrlbox.hxx>
39#include <tools/json_writer.hxx>
40#include <vcl/toolbox.hxx>
43
44#include <memory>
45
47
48using namespace ::com::sun::star;
49
50namespace {
51
52class SvxFontSizeBox_Base;
53class SvxFontSizeBox_Impl;
54
55class FontHeightToolBoxControl : public svt::ToolboxController,
56 public lang::XServiceInfo
57{
58 public:
59 explicit FontHeightToolBoxControl(
60 const css::uno::Reference< css::uno::XComponentContext >& rServiceManager );
61
62 // XInterface
63 virtual css::uno::Any SAL_CALL queryInterface( const css::uno::Type& aType ) override;
64 virtual void SAL_CALL acquire() noexcept override;
65 virtual void SAL_CALL release() noexcept override;
66
67 // XServiceInfo
68 virtual OUString SAL_CALL getImplementationName() override;
69 virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
70 virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
71
72 // XComponent
73 virtual void SAL_CALL dispose() override;
74
75 // XStatusListener
76 virtual void SAL_CALL statusChanged( const css::frame::FeatureStateEvent& Event ) override;
77
78 // XToolbarController
79 virtual void SAL_CALL execute( sal_Int16 KeyModifier ) override;
80 virtual void SAL_CALL click() override;
81 virtual void SAL_CALL doubleClick() override;
82 virtual css::uno::Reference< css::awt::XWindow > SAL_CALL createPopupWindow() override;
83 virtual css::uno::Reference< css::awt::XWindow > SAL_CALL createItemWindow( const css::uno::Reference< css::awt::XWindow >& Parent ) override;
84
85 void dispatchCommand( const css::uno::Sequence< css::beans::PropertyValue >& rArgs );
86 using svt::ToolboxController::dispatchCommand;
87
88 private:
89 VclPtr<SvxFontSizeBox_Impl> m_xVclBox;
90 std::unique_ptr<SvxFontSizeBox_Base> m_xWeldBox;
91 SvxFontSizeBox_Base* m_pBox;
92};
93
94class SvxFontSizeBox_Base
95{
96public:
97 SvxFontSizeBox_Base(std::unique_ptr<weld::ComboBox> xWidget,
98 uno::Reference< frame::XFrame > _xFrame,
99 FontHeightToolBoxControl& rCtrl);
100
101 virtual ~SvxFontSizeBox_Base()
102 {
103 }
104
105 virtual void set_sensitive(bool bSensitive)
106 {
107 m_xWidget->set_sensitive(bSensitive);
108 }
109
110 void statusChanged_Impl(tools::Long nHeight, bool bErase);
111 void UpdateFont();
112
113protected:
114 FontHeightToolBoxControl& m_rCtrl;
115 OUString m_aCurText;
116 bool m_bRelease;
117 uno::Reference<frame::XFrame> m_xFrame;
118 std::unique_ptr<FontSizeBox> m_xWidget;
119
120 void ReleaseFocus_Impl();
121 void Select();
122
123 virtual bool DoKeyInput(const KeyEvent& rKEvt);
124
125 DECL_LINK(SelectHdl, weld::ComboBox&, void);
126 DECL_LINK(KeyInputHdl, const KeyEvent&, bool);
127 DECL_LINK(ActivateHdl, weld::ComboBox&, bool);
128 DECL_LINK(FocusOutHdl, weld::Widget&, void);
129 DECL_LINK(DumpAsPropertyTreeHdl, tools::JsonWriter&, void);
130};
131
132class SvxFontSizeBox_Impl final : public InterimItemWindow
133 , public SvxFontSizeBox_Base
134{
135public:
136 SvxFontSizeBox_Impl(vcl::Window* pParent,
137 const uno::Reference< frame::XFrame >& _xFrame,
138 FontHeightToolBoxControl& rCtrl);
139
140 virtual void dispose() override
141 {
142 m_xWidget.reset();
144 }
145
146 virtual void GetFocus() override
147 {
148 if (m_xWidget)
149 m_xWidget->grab_focus();
151 }
152
153 virtual ~SvxFontSizeBox_Impl() override
154 {
155 disposeOnce();
156 }
157
158 void SetOptimalSize();
159
160 virtual void DataChanged(const DataChangedEvent& rDCEvt) override;
161
162 virtual void set_sensitive(bool bSensitive) override
163 {
164 m_xWidget->set_sensitive(bSensitive);
165 if (bSensitive)
167 else
169 }
170
171private:
172 virtual bool DoKeyInput(const KeyEvent& rKEvt) override;
173};
174
175SvxFontSizeBox_Base::SvxFontSizeBox_Base(std::unique_ptr<weld::ComboBox> xWidget,
176 uno::Reference<frame::XFrame> xFrame,
177 FontHeightToolBoxControl& rCtrl)
178 : m_rCtrl(rCtrl)
179 , m_bRelease(true)
180 , m_xFrame(std::move(xFrame))
181 , m_xWidget(new FontSizeBox(std::move(xWidget)))
182{
183 m_xWidget->set_value(0);
184 m_xWidget->set_active_or_entry_text("");
185 m_xWidget->disable_entry_completion();
186
187 m_xWidget->connect_changed(LINK(this, SvxFontSizeBox_Base, SelectHdl));
188 m_xWidget->connect_key_press(LINK(this, SvxFontSizeBox_Base, KeyInputHdl));
189 m_xWidget->connect_entry_activate(LINK(this, SvxFontSizeBox_Base, ActivateHdl));
190 m_xWidget->connect_focus_out(LINK(this, SvxFontSizeBox_Base, FocusOutHdl));
191 m_xWidget->connect_get_property_tree(LINK(this, SvxFontSizeBox_Base, DumpAsPropertyTreeHdl));
192}
193
194void SvxFontSizeBox_Base::ReleaseFocus_Impl()
195{
196 if ( !m_bRelease )
197 {
198 m_bRelease = true;
199 return;
200 }
201
202 if ( m_xFrame.is() && m_xFrame->getContainerWindow().is() )
203 m_xFrame->getContainerWindow()->setFocus();
204}
205
206IMPL_LINK(SvxFontSizeBox_Base, SelectHdl, weld::ComboBox&, rCombo, void)
207{
208 if (rCombo.changed_by_direct_pick()) // only when picked from the list
209 Select();
210}
211
212IMPL_LINK_NOARG(SvxFontSizeBox_Base, ActivateHdl, weld::ComboBox&, bool)
213{
214 Select();
215 return true;
216}
217
218void SvxFontSizeBox_Base::Select()
219{
220 sal_Int64 nSelVal = m_xWidget->get_value();
221 float fSelVal = float( nSelVal ) / 10;
222
223 uno::Sequence< beans::PropertyValue > aArgs{ comphelper::makePropertyValue("FontHeight.Height",
224 fSelVal) };
225
226 /* #i33380# DR 2004-09-03 Moved the following line above the Dispatch() call.
227 This instance may be deleted in the meantime (i.e. when a dialog is opened
228 while in Dispatch()), accessing members will crash in this case. */
229 ReleaseFocus_Impl();
230
231 m_rCtrl.dispatchCommand( aArgs );
232}
233
234void SvxFontSizeBox_Base::statusChanged_Impl( tools::Long nPoint, bool bErase )
235{
236 if ( !bErase )
237 {
238 // convert the metric
239 tools::Long nVal = nPoint;
240
241 // changed => set new value
242 if (m_xWidget->get_value() != nVal)
243 m_xWidget->set_value(nVal);
244 }
245 else
246 {
247 // delete value in the display
248 m_xWidget->set_value(-1L);
249 m_xWidget->set_active_or_entry_text("");
250 }
251 m_aCurText = m_xWidget->get_active_text();
252}
253
254void SvxFontSizeBox_Base::UpdateFont()
255{
256 // filling up the sizes list
257 auto nOldVal = m_xWidget->get_value(); // memorize old value
259
260 m_xWidget->Fill(&aFontList);
261
262 m_xWidget->set_value(nOldVal); // restore old value
263 m_aCurText = m_xWidget->get_active_text(); // memorize to reset at ESC
264}
265
266IMPL_LINK(SvxFontSizeBox_Base, KeyInputHdl, const KeyEvent&, rKEvt, bool)
267{
268 return DoKeyInput(rKEvt);
269}
270
271bool SvxFontSizeBox_Base::DoKeyInput(const KeyEvent& rKEvt)
272{
273 bool bHandled = false;
274
275 sal_uInt16 nCode = rKEvt.GetKeyCode().GetCode();
276
277 switch (nCode)
278 {
279 case KEY_TAB:
280 m_bRelease = false;
281 Select();
282 break;
283
284 case KEY_ESCAPE:
285 m_xWidget->set_active_or_entry_text(m_aCurText);
286 if (!m_rCtrl.IsInSidebar())
287 {
288 ReleaseFocus_Impl();
289 bHandled = true;
290 }
291 break;
292 }
293
294 return bHandled;
295}
296
297bool SvxFontSizeBox_Impl::DoKeyInput(const KeyEvent& rKEvt)
298{
299 return SvxFontSizeBox_Base::DoKeyInput(rKEvt) || ChildKeyInput(rKEvt);
300}
301
302IMPL_LINK_NOARG(SvxFontSizeBox_Base, FocusOutHdl, weld::Widget&, void)
303{
304 if (!m_xWidget->has_focus()) // a combobox can be comprised of different subwidget so double-check if none of those has focus
305 m_xWidget->set_active_or_entry_text(m_aCurText);
306}
307
308void SvxFontSizeBox_Impl::SetOptimalSize()
309{
310 SetSizePixel(get_preferred_size());
311}
312
313SvxFontSizeBox_Impl::SvxFontSizeBox_Impl(vcl::Window* pParent,
314 const uno::Reference<frame::XFrame>& rFrame,
315 FontHeightToolBoxControl& rCtrl)
316 : InterimItemWindow(pParent, "svx/ui/fontsizebox.ui", "FontSizeBox")
317 , SvxFontSizeBox_Base(m_xBuilder->weld_combo_box("fontsizecombobox"), rFrame, rCtrl)
318{
319}
320
321void SvxFontSizeBox_Impl::DataChanged( const DataChangedEvent& rDCEvt )
322{
323 if ( (rDCEvt.GetType() == DataChangedEventType::SETTINGS) &&
324 (rDCEvt.GetFlags() & AllSettingsFlags::STYLE) )
325 {
326 SetOptimalSize();
327 }
328}
329
330IMPL_LINK(SvxFontSizeBox_Base, DumpAsPropertyTreeHdl, tools::JsonWriter&, rJsonWriter, void)
331{
332 {
333 auto entriesNode = rJsonWriter.startNode("entries");
334 for (int i = 0, nCount = m_xWidget->get_count(); i < nCount; ++i)
335 {
336 auto entryNode = rJsonWriter.startNode("");
337 rJsonWriter.put("", m_xWidget->get_text(i));
338 }
339 }
340
341 int nActive = m_xWidget->get_active();
342 rJsonWriter.put("selectedCount", static_cast<sal_Int32>(nActive == -1 ? 0 : 1));
343 {
344 auto selectedNode = rJsonWriter.startNode("selectedEntries");
345 if (nActive != -1)
346 {
347 auto node = rJsonWriter.startNode("");
348 rJsonWriter.put("", static_cast<sal_Int32>(nActive));
349 }
350 }
351
352 rJsonWriter.put("command", ".uno:FontHeight");
353}
354
355FontHeightToolBoxControl::FontHeightToolBoxControl( const uno::Reference< uno::XComponentContext >& rxContext )
356 : svt::ToolboxController( rxContext,
357 uno::Reference< frame::XFrame >(),
358 ".uno:FontHeight" ),
359 m_pBox( nullptr )
360{
361 addStatusListener( ".uno:CharFontName");
362}
363
364// XInterface
365css::uno::Any SAL_CALL FontHeightToolBoxControl::queryInterface( const css::uno::Type& aType )
366{
367 uno::Any a = ToolboxController::queryInterface( aType );
368 if ( a.hasValue() )
369 return a;
370
371 return ::cppu::queryInterface( aType, static_cast< lang::XServiceInfo* >( this ));
372}
373
374void SAL_CALL FontHeightToolBoxControl::acquire() noexcept
375{
376 ToolboxController::acquire();
377}
378
379void SAL_CALL FontHeightToolBoxControl::release() noexcept
380{
381 ToolboxController::release();
382}
383
384// XServiceInfo
385sal_Bool SAL_CALL FontHeightToolBoxControl::supportsService( const OUString& ServiceName )
386{
387 return cppu::supportsService(this, ServiceName);
388}
389
390OUString SAL_CALL FontHeightToolBoxControl::getImplementationName()
391{
392 return "com.sun.star.svx.FontHeightToolBoxController";
393}
394
395uno::Sequence< OUString > SAL_CALL FontHeightToolBoxControl::getSupportedServiceNames( )
396{
397 return { "com.sun.star.frame.ToolbarController" };
398}
399
400// XComponent
401void SAL_CALL FontHeightToolBoxControl::dispose()
402{
404
405 SolarMutexGuard aSolarMutexGuard;
406 m_xVclBox.disposeAndClear();
407 m_xWeldBox.reset();
408 m_pBox = nullptr;
409}
410
411// XStatusListener
412void SAL_CALL FontHeightToolBoxControl::statusChanged(
413 const frame::FeatureStateEvent& rEvent )
414{
415 if ( !m_pBox )
416 return;
417
418 SolarMutexGuard aSolarMutexGuard;
419 if (rEvent.FeatureURL.Path == "FontHeight")
420 {
421 if ( rEvent.IsEnabled )
422 {
423 m_pBox->set_sensitive(true);
424 frame::status::FontHeight aFontHeight;
425 if ( rEvent.State >>= aFontHeight )
426 {
427 // tdf#83090 - correctly round the height of the font
428 aFontHeight.Height = rtl::math::round(10. * aFontHeight.Height);
429 m_pBox->statusChanged_Impl(tools::Long(aFontHeight.Height), false);
430 }
431 else
432 m_pBox->statusChanged_Impl( tools::Long( -1 ), true );
433 }
434 else
435 {
436 m_pBox->set_sensitive(false);
437 m_pBox->statusChanged_Impl( tools::Long( -1 ), true );
438 }
439
440 if (m_pToolbar)
441 m_pToolbar->set_item_sensitive(m_aCommandURL.toUtf8(), rEvent.IsEnabled);
442 else
443 {
444 ToolBox* pToolBox = nullptr;
446 if (getToolboxId(nId, &pToolBox))
447 pToolBox->EnableItem(nId, rEvent.IsEnabled);
448 }
449 }
450 else if ( rEvent.FeatureURL.Path == "CharFontName" )
451 {
452 m_pBox->UpdateFont();
453 }
454}
455
456// XToolbarController
457void SAL_CALL FontHeightToolBoxControl::execute( sal_Int16 /*KeyModifier*/ )
458{
459}
460
461void SAL_CALL FontHeightToolBoxControl::click()
462{
463}
464
465void SAL_CALL FontHeightToolBoxControl::doubleClick()
466{
467}
468
469uno::Reference< awt::XWindow > SAL_CALL FontHeightToolBoxControl::createPopupWindow()
470{
471 return uno::Reference< awt::XWindow >();
472}
473
474uno::Reference< awt::XWindow > SAL_CALL FontHeightToolBoxControl::createItemWindow(
475 const uno::Reference< awt::XWindow >& xParent )
476{
477 uno::Reference< awt::XWindow > xItemWindow;
478
479 if (m_pBuilder)
480 {
481 SolarMutexGuard aSolarMutexGuard;
482
483 std::unique_ptr<weld::ComboBox> xWidget(m_pBuilder->weld_combo_box("fontsizecombobox"));
484
485 xItemWindow = css::uno::Reference<css::awt::XWindow>(new weld::TransportAsXWindow(xWidget.get()));
486
487 m_xWeldBox.reset(new SvxFontSizeBox_Base(std::move(xWidget), m_xFrame, *this));
488 m_pBox = m_xWeldBox.get();
489 //Get the box to fill itself with all its sizes
490 m_pBox->UpdateFont();
491 }
492 else
493 {
494 VclPtr<vcl::Window> pParent = VCLUnoHelper::GetWindow( xParent );
495 if ( pParent )
496 {
497 SolarMutexGuard aSolarMutexGuard;
498 m_xVclBox = VclPtr<SvxFontSizeBox_Impl>::Create( pParent, m_xFrame, *this );
499 m_pBox = m_xVclBox.get();
500 //Get the box to fill itself with all its sizes
501 m_pBox->UpdateFont();
502 //Make it size itself to its optimal size re above sizes
503 m_xVclBox->SetOptimalSize();
504 xItemWindow = VCLUnoHelper::GetInterface(m_xVclBox);
505 }
506 }
507
508 return xItemWindow;
509}
510
511void FontHeightToolBoxControl::dispatchCommand(
512 const uno::Sequence< beans::PropertyValue >& rArgs )
513{
514 uno::Reference< frame::XDispatchProvider > xDispatchProvider( m_xFrame, uno::UNO_QUERY );
515 if ( xDispatchProvider.is() )
516 {
517 util::URL aURL;
518 uno::Reference< frame::XDispatch > xDispatch;
519 uno::Reference< util::XURLTransformer > xURLTransformer = getURLTransformer();
520
521 aURL.Complete = ".uno:FontHeight";
522 xURLTransformer->parseStrict( aURL );
523 xDispatch = xDispatchProvider->queryDispatch( aURL, OUString(), 0 );
524 if ( xDispatch.is() )
525 xDispatch->dispatch( aURL, rArgs );
526 }
527}
528
529}
530
531extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
533 css::uno::XComponentContext *rxContext,
534 css::uno::Sequence<css::uno::Any> const &)
535{
536 return cppu::acquire(new FontHeightToolBoxControl(rxContext));
537}
538
539/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
std::unique_ptr< weld::Image > m_xWidget
IMPL_LINK(MaskData, PipetteHdl, const OString &, rId, void)
Definition: _bmpmask.cxx:192
IMPL_LINK_NOARG(MaskData, ExecHdl, weld::Button &, void)
Definition: _bmpmask.cxx:300
css::uno::Reference< css::lang::XComponent > m_xFrame
static OutputDevice * GetDefaultDevice()
DataChangedEventType GetType() const
AllSettingsFlags GetFlags() const
virtual void dispose() override
virtual void GetFocus() override
const vcl::KeyCode & GetKeyCode() const
void EnableItem(ToolBoxItemId nItemId, bool bEnable=true)
static css::uno::Reference< css::awt::XWindow > GetInterface(vcl::Window *pWindow)
static vcl::Window * GetWindow(const css::uno::Reference< css::awt::XWindow > &rxWindow)
static VclPtr< reference_type > Create(Arg &&... arg)
virtual void SAL_CALL dispose() override
virtual css::uno::Any SAL_CALL queryInterface(const css::uno::Type &aType) override
virtual void SAL_CALL acquire() noexcept override
sal_uInt16 GetCode() const
void Disable(bool bChild=true)
void Enable(bool bEnable=true, bool bChild=true)
virtual std::unique_ptr< ComboBox > weld_combo_box(const OString &id)=0
Reference< XDispatch > xDispatch
URL aURL
DECL_LINK(CheckNameHdl, SvxNameDialog &, bool)
uno_Any a
constexpr sal_uInt16 KEY_ESCAPE
constexpr sal_uInt16 KEY_TAB
sal_uInt16 nCode
css::beans::PropertyValue makePropertyValue(const OUString &rName, T &&rValue)
bool CPPUHELPER_DLLPUBLIC supportsService(css::lang::XServiceInfo *implementation, rtl::OUString const &name)
Reference
void dispose()
long Long
sal_Int16 nId
Reference< XFrame > xFrame
SAL_DLLPUBLIC_EXPORT css::uno::XInterface * com_sun_star_svx_FontHeightToolBoxController_get_implementation(css::uno::XComponentContext *rxContext, css::uno::Sequence< css::uno::Any > const &)
weld::Builder * m_pBuilder
unsigned char sal_Bool