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/awt/FontDescriptor.hpp>
21 #include <com/sun/star/frame/XFrame.hpp>
22 #include <com/sun/star/frame/status/FontHeight.hpp>
23 #include <com/sun/star/frame/XDispatchProvider.hpp>
24 #include <com/sun/star/beans/PropertyValue.hpp>
25 #include <com/sun/star/lang/XServiceInfo.hpp>
26 #include <com/sun/star/util/XURLTransformer.hpp>
27 
28 #include <vcl/event.hxx>
29 #include <vcl/svapp.hxx>
30 #include <vcl/weldutils.hxx>
31 #include <vcl/window.hxx>
32 #include <vcl/settings.hxx>
34 #include <svtools/ctrltool.hxx>
35 #include <svtools/ctrlbox.hxx>
37 #include <tools/json_writer.hxx>
40 
41 #include <memory>
42 
45 
46 using namespace ::com::sun::star;
47 
48 namespace {
49 
50 class SvxFontSizeBox_Base;
51 class SvxFontSizeBox_Impl;
52 
53 class FontHeightToolBoxControl : public svt::ToolboxController,
54  public lang::XServiceInfo
55 {
56  public:
57  explicit FontHeightToolBoxControl(
58  const css::uno::Reference< css::uno::XComponentContext >& rServiceManager );
59 
60  // XInterface
61  virtual css::uno::Any SAL_CALL queryInterface( const css::uno::Type& aType ) override;
62  virtual void SAL_CALL acquire() throw () override;
63  virtual void SAL_CALL release() throw () override;
64 
65  // XServiceInfo
66  virtual OUString SAL_CALL getImplementationName() override;
67  virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
68  virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
69 
70  // XComponent
71  virtual void SAL_CALL dispose() override;
72 
73  // XStatusListener
74  virtual void SAL_CALL statusChanged( const css::frame::FeatureStateEvent& Event ) override;
75 
76  // XToolbarController
77  virtual void SAL_CALL execute( sal_Int16 KeyModifier ) override;
78  virtual void SAL_CALL click() override;
79  virtual void SAL_CALL doubleClick() override;
80  virtual css::uno::Reference< css::awt::XWindow > SAL_CALL createPopupWindow() override;
81  virtual css::uno::Reference< css::awt::XWindow > SAL_CALL createItemWindow( const css::uno::Reference< css::awt::XWindow >& Parent ) override;
82 
83  void dispatchCommand( const css::uno::Sequence< css::beans::PropertyValue >& rArgs );
84  using svt::ToolboxController::dispatchCommand;
85 
86  private:
87  VclPtr<SvxFontSizeBox_Impl> m_xVclBox;
88  std::unique_ptr<SvxFontSizeBox_Base> m_xWeldBox;
89  SvxFontSizeBox_Base* m_pBox;
90  css::awt::FontDescriptor m_aCurrentFont;
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(long nHeight, bool bErase);
110  void UpdateFont(const css::awt::FontDescriptor& rCurrentFont);
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( 1 );
223  aArgs[0].Name = "FontHeight.Height";
224  aArgs[0].Value <<= 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 
234 void SvxFontSizeBox_Base::statusChanged_Impl( long nPoint, bool bErase )
235 {
236  if ( !bErase )
237  {
238  // convert the metric
239  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 
254 void SvxFontSizeBox_Base::UpdateFont(const css::awt::FontDescriptor& rCurrentFont)
255 {
256  // filling up the sizes list
257  auto nOldVal = m_xWidget->get_value(); // memorize old value
258  std::unique_ptr<FontList> xFontList(new FontList(Application::GetDefaultDevice()));
259 
260  if (!rCurrentFont.Name.isEmpty())
261  {
262  FontMetric aFontMetric;
263  aFontMetric.SetFamilyName(rCurrentFont.Name);
264  aFontMetric.SetStyleName(rCurrentFont.StyleName);
265  aFontMetric.SetFontHeight(rCurrentFont.Height);
266  m_xWidget->Fill(&aFontMetric, xFontList.get());
267  }
268  else
269  {
270  m_xWidget->Fill(nullptr, xFontList.get());
271  }
272  m_xWidget->set_value(nOldVal); // restore old value
273  m_aCurText = m_xWidget->get_active_text(); // memorize to reset at ESC
274 }
275 
276 IMPL_LINK(SvxFontSizeBox_Base, KeyInputHdl, const KeyEvent&, rKEvt, bool)
277 {
278  return DoKeyInput(rKEvt);
279 }
280 
281 bool SvxFontSizeBox_Base::DoKeyInput(const KeyEvent& rKEvt)
282 {
283  bool bHandled = false;
284 
285  sal_uInt16 nCode = rKEvt.GetKeyCode().GetCode();
286 
287  switch (nCode)
288  {
289  case KEY_TAB:
290  m_bRelease = false;
291  Select();
292  break;
293 
294  case KEY_ESCAPE:
295  m_xWidget->set_active_or_entry_text(m_aCurText);
296  if (!m_rCtrl.IsInSidebar())
297  {
298  ReleaseFocus_Impl();
299  bHandled = true;
300  }
301  break;
302  }
303 
304  return bHandled;
305 }
306 
307 bool SvxFontSizeBox_Impl::DoKeyInput(const KeyEvent& rKEvt)
308 {
309  return SvxFontSizeBox_Base::DoKeyInput(rKEvt) || ChildKeyInput(rKEvt);
310 }
311 
312 IMPL_LINK_NOARG(SvxFontSizeBox_Base, FocusOutHdl, weld::Widget&, void)
313 {
314  if (!m_xWidget->has_focus()) // a combobox can be comprised of different subwidget so double-check if none of those has focus
315  m_xWidget->set_active_or_entry_text(m_aCurText);
316 }
317 
318 void SvxFontSizeBox_Impl::SetOptimalSize()
319 {
320  SetSizePixel(get_preferred_size());
321 }
322 
323 SvxFontSizeBox_Impl::SvxFontSizeBox_Impl(vcl::Window* pParent,
324  const uno::Reference<frame::XFrame>& rFrame,
325  FontHeightToolBoxControl& rCtrl)
326  : InterimItemWindow(pParent, "svx/ui/fontsizebox.ui", "FontSizeBox")
327  , SvxFontSizeBox_Base(m_xBuilder->weld_combo_box("fontsizecombobox"), rFrame, rCtrl)
328 {
329 }
330 
331 void SvxFontSizeBox_Impl::DataChanged( const DataChangedEvent& rDCEvt )
332 {
333  if ( (rDCEvt.GetType() == DataChangedEventType::SETTINGS) &&
334  (rDCEvt.GetFlags() & AllSettingsFlags::STYLE) )
335  {
336  SetOptimalSize();
337  }
338 }
339 
340 IMPL_LINK(SvxFontSizeBox_Base, DumpAsPropertyTreeHdl, tools::JsonWriter&, rJsonWriter, void)
341 {
342  {
343  auto entriesNode = rJsonWriter.startNode("entries");
344  for (int i = 0, nCount = m_xWidget->get_count(); i < nCount; ++i)
345  {
346  auto entryNode = rJsonWriter.startNode("");
347  rJsonWriter.put("", m_xWidget->get_text(i));
348  }
349  }
350 
351  int nActive = m_xWidget->get_active();
352  rJsonWriter.put("selectedCount", static_cast<sal_Int32>(nActive == -1 ? 0 : 1));
353  {
354  auto selectedNode = rJsonWriter.startNode("selectedEntries");
355  if (nActive != -1)
356  {
357  auto node = rJsonWriter.startNode("");
358  rJsonWriter.put("", static_cast<sal_Int32>(nActive));
359  }
360  }
361 
362  rJsonWriter.put("command", ".uno:FontHeight");
363 }
364 
365 FontHeightToolBoxControl::FontHeightToolBoxControl( const uno::Reference< uno::XComponentContext >& rxContext )
366  : svt::ToolboxController( rxContext,
367  uno::Reference< frame::XFrame >(),
368  ".uno:FontHeight" ),
369  m_pBox( nullptr )
370 {
371  addStatusListener( ".uno:CharFontName");
372 }
373 
374 // XInterface
375 css::uno::Any SAL_CALL FontHeightToolBoxControl::queryInterface( const css::uno::Type& aType )
376 {
377  uno::Any a = ToolboxController::queryInterface( aType );
378  if ( a.hasValue() )
379  return a;
380 
381  return ::cppu::queryInterface( aType, static_cast< lang::XServiceInfo* >( this ));
382 }
383 
384 void SAL_CALL FontHeightToolBoxControl::acquire() throw ()
385 {
386  ToolboxController::acquire();
387 }
388 
389 void SAL_CALL FontHeightToolBoxControl::release() throw ()
390 {
391  ToolboxController::release();
392 }
393 
394 // XServiceInfo
395 sal_Bool SAL_CALL FontHeightToolBoxControl::supportsService( const OUString& ServiceName )
396 {
397  return cppu::supportsService(this, ServiceName);
398 }
399 
400 OUString SAL_CALL FontHeightToolBoxControl::getImplementationName()
401 {
402  return "com.sun.star.svx.FontHeightToolBoxController";
403 }
404 
405 uno::Sequence< OUString > SAL_CALL FontHeightToolBoxControl::getSupportedServiceNames( )
406 {
407  return { "com.sun.star.frame.ToolbarController" };
408 }
409 
410 // XComponent
411 void SAL_CALL FontHeightToolBoxControl::dispose()
412 {
414 
415  SolarMutexGuard aSolarMutexGuard;
416  m_xVclBox.disposeAndClear();
417  m_xWeldBox.reset();
418  m_pBox = nullptr;
419 }
420 
421 // XStatusListener
422 void SAL_CALL FontHeightToolBoxControl::statusChanged(
423  const frame::FeatureStateEvent& rEvent )
424 {
425  if ( m_pBox )
426  {
427  SolarMutexGuard aSolarMutexGuard;
428  if (rEvent.FeatureURL.Path == "FontHeight")
429  {
430  if ( rEvent.IsEnabled )
431  {
432  m_pBox->set_sensitive(true);
433  frame::status::FontHeight aFontHeight;
434  if ( rEvent.State >>= aFontHeight )
435  m_pBox->statusChanged_Impl( long( 10. * aFontHeight.Height ), false );
436  else
437  m_pBox->statusChanged_Impl( long( -1 ), true );
438  }
439  else
440  {
441  m_pBox->set_sensitive(false);
442  m_pBox->statusChanged_Impl( long( -1 ), true );
443  }
444 
445  if (m_pToolbar)
446  m_pToolbar->set_item_sensitive(m_aCommandURL.toUtf8(), rEvent.IsEnabled);
447  else
448  {
449  ToolBox* pToolBox = nullptr;
450  sal_uInt16 nId = 0;
451  if (getToolboxId(nId, &pToolBox))
452  pToolBox->EnableItem(nId, rEvent.IsEnabled);
453  }
454  }
455  else if ( rEvent.FeatureURL.Path == "CharFontName" )
456  {
457  if ( rEvent.State >>= m_aCurrentFont )
458  m_pBox->UpdateFont( m_aCurrentFont );
459  }
460  }
461 }
462 
463 // XToolbarController
464 void SAL_CALL FontHeightToolBoxControl::execute( sal_Int16 /*KeyModifier*/ )
465 {
466 }
467 
468 void SAL_CALL FontHeightToolBoxControl::click()
469 {
470 }
471 
472 void SAL_CALL FontHeightToolBoxControl::doubleClick()
473 {
474 }
475 
476 uno::Reference< awt::XWindow > SAL_CALL FontHeightToolBoxControl::createPopupWindow()
477 {
478  return uno::Reference< awt::XWindow >();
479 }
480 
481 uno::Reference< awt::XWindow > SAL_CALL FontHeightToolBoxControl::createItemWindow(
482  const uno::Reference< awt::XWindow >& xParent )
483 {
484  uno::Reference< awt::XWindow > xItemWindow;
485 
486  if (m_pBuilder)
487  {
488  SolarMutexGuard aSolarMutexGuard;
489 
490  std::unique_ptr<weld::ComboBox> xWidget(m_pBuilder->weld_combo_box("fontsizecombobox"));
491 
492  xItemWindow = css::uno::Reference<css::awt::XWindow>(new weld::TransportAsXWindow(xWidget.get()));
493 
494  m_xWeldBox.reset(new SvxFontSizeBox_Base(std::move(xWidget), m_xFrame, *this));
495  m_pBox = m_xWeldBox.get();
496  //Get the box to fill itself with all its sizes
497  m_pBox->UpdateFont(m_aCurrentFont);
498  }
499  else
500  {
501  VclPtr<vcl::Window> pParent = VCLUnoHelper::GetWindow( xParent );
502  if ( pParent )
503  {
504  SolarMutexGuard aSolarMutexGuard;
505  m_xVclBox = VclPtr<SvxFontSizeBox_Impl>::Create( pParent, m_xFrame, *this );
506  m_pBox = m_xVclBox.get();
507  //Get the box to fill itself with all its sizes
508  m_pBox->UpdateFont(m_aCurrentFont);
509  //Make it size itself to its optimal size re above sizes
510  m_xVclBox->SetOptimalSize();
511  xItemWindow = VCLUnoHelper::GetInterface(m_xVclBox);
512  }
513  }
514 
515  return xItemWindow;
516 }
517 
518 void FontHeightToolBoxControl::dispatchCommand(
519  const uno::Sequence< beans::PropertyValue >& rArgs )
520 {
521  uno::Reference< frame::XDispatchProvider > xDispatchProvider( m_xFrame, uno::UNO_QUERY );
522  if ( xDispatchProvider.is() )
523  {
524  util::URL aURL;
525  uno::Reference< frame::XDispatch > xDispatch;
526  uno::Reference< util::XURLTransformer > xURLTransformer = getURLTransformer();
527 
528  aURL.Complete = ".uno:FontHeight";
529  xURLTransformer->parseStrict( aURL );
530  xDispatch = xDispatchProvider->queryDispatch( aURL, OUString(), 0 );
531  if ( xDispatch.is() )
532  xDispatch->dispatch( aURL, rArgs );
533  }
534 }
535 
536 }
537 
538 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
540  css::uno::XComponentContext *rxContext,
541  css::uno::Sequence<css::uno::Any> const &)
542 {
543  return cppu::acquire(new FontHeightToolBoxControl(rxContext));
544 }
545 
546 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
URL aURL
bool hasValue()
virtual void SAL_CALL dispose() override
IMPL_LINK(MaskData, PipetteHdl, const OString &, rId, void)
Definition: _bmpmask.cxx:192
static VclPtr< vcl::Window > GetWindow(const css::uno::Reference< css::awt::XWindow > &rxWindow)
css::uno::Reference< css::lang::XComponent > m_xFrame
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
virtual void SAL_CALL acquire() override
int nCount
virtual void GetFocus() override
AllSettingsFlags GetFlags() const
bool CPPUHELPER_DLLPUBLIC supportsService(css::lang::XServiceInfo *implementation, rtl::OUString const &name)
void EnableItem(sal_uInt16 nItemId, bool bEnable=true)
sal_uInt16 nCode
void SetFamilyName(const OUString &rFamilyName)
int i
uno_Any a
unsigned char sal_Bool
void Disable(bool bChild=true)
const vcl::KeyCode & GetKeyCode() const
void SetStyleName(const OUString &rStyleName)
Reference< XDispatch > xDispatch
constexpr sal_uInt16 KEY_ESCAPE
virtual void dispose() override
static VclPtr< reference_type > Create(Arg &&...arg)
void SetFontHeight(long nHeight)
css::uno::Reference< css::frame::XFrame > m_xFrame
void dispose()
static css::uno::Reference< css::awt::XWindow > GetInterface(vcl::Window *pWindow)
constexpr sal_uInt16 KEY_TAB