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