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/window.hxx>
31 #include <vcl/settings.hxx>
33 #include <svtools/ctrltool.hxx>
34 #include <svtools/ctrlbox.hxx>
38 
39 #include <memory>
40 
43 #include <boost/property_tree/ptree.hpp>
44 
45 using namespace ::com::sun::star;
46 
47 namespace {
48 
49 class SvxFontSizeBox_Impl;
50 class FontHeightToolBoxControl : public svt::ToolboxController,
51  public lang::XServiceInfo
52 {
53  public:
54  explicit FontHeightToolBoxControl(
55  const css::uno::Reference< css::uno::XComponentContext >& rServiceManager );
56 
57  // XInterface
58  virtual css::uno::Any SAL_CALL queryInterface( const css::uno::Type& aType ) override;
59  virtual void SAL_CALL acquire() throw () override;
60  virtual void SAL_CALL release() throw () override;
61 
62  // XServiceInfo
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;
66 
67  // XComponent
68  virtual void SAL_CALL dispose() override;
69 
70  // XStatusListener
71  virtual void SAL_CALL statusChanged( const css::frame::FeatureStateEvent& Event ) override;
72 
73  // XToolbarController
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;
79 
80  void dispatchCommand( const css::uno::Sequence< css::beans::PropertyValue >& rArgs );
81  using svt::ToolboxController::dispatchCommand;
82 
83  private:
84  VclPtr<SvxFontSizeBox_Impl> m_pBox;
85  css::awt::FontDescriptor m_aCurrentFont;
86 };
87 
88 class SvxFontSizeBox_Impl final : public InterimItemWindow
89 {
90 public:
91  SvxFontSizeBox_Impl( vcl::Window* pParent,
92  const uno::Reference< frame::XFrame >& _xFrame,
93  FontHeightToolBoxControl& rCtrl );
94 
95  virtual void dispose() override;
96  virtual ~SvxFontSizeBox_Impl() override;
97  void statusChanged_Impl( long nHeight, bool bErase );
98  void UpdateFont( const css::awt::FontDescriptor& rCurrentFont );
99  void SetOptimalSize();
100 
101  virtual void DataChanged( const DataChangedEvent& rDCEvt ) override;
102  virtual void GetFocus() override;
103 
104  void Enable() {m_xWidget->set_sensitive(true); InterimItemWindow::Enable();}
105  void Disable() {m_xWidget->set_sensitive(false); InterimItemWindow::Disable();}
106 
107 private:
108  FontHeightToolBoxControl& m_rCtrl;
109  OUString m_aCurText;
110  bool m_bRelease;
111  uno::Reference< frame::XFrame > m_xFrame;
112  std::unique_ptr<FontSizeBox> m_xWidget;
113 
114  void ReleaseFocus_Impl();
115 
116  void Select();
117 
118  DECL_LINK(SelectHdl, weld::ComboBox&, void);
119  DECL_LINK(KeyInputHdl, const KeyEvent&, bool);
120  DECL_LINK(ActivateHdl, weld::ComboBox&, bool);
121  DECL_LINK(FocusOutHdl, weld::Widget&, void);
122  DECL_LINK(DumpAsPropertyTreeHdl, boost::property_tree::ptree&, void);
123 };
124 
125 SvxFontSizeBox_Impl::SvxFontSizeBox_Impl(
126  vcl::Window* _pParent,
127  const uno::Reference< frame::XFrame >& _xFrame,
128  FontHeightToolBoxControl& _rCtrl ) :
129 
130  InterimItemWindow(_pParent, "svx/ui/fontsizebox.ui", "FontSizeBox"),
131 
132  m_rCtrl ( _rCtrl ),
133  m_bRelease ( true ),
134  m_xFrame ( _xFrame ),
135  m_xWidget(new FontSizeBox(m_xBuilder->weld_combo_box("fontsizecombobox")))
136 {
137  m_xWidget->set_value(0);
138  m_xWidget->set_entry_text("");
139  m_xWidget->disable_entry_completion();
140 
141  m_xWidget->connect_changed(LINK(this, SvxFontSizeBox_Impl, SelectHdl));
142  m_xWidget->connect_key_press(LINK(this, SvxFontSizeBox_Impl, KeyInputHdl));
143  m_xWidget->connect_entry_activate(LINK(this, SvxFontSizeBox_Impl, ActivateHdl));
144  m_xWidget->connect_focus_out(LINK(this, SvxFontSizeBox_Impl, FocusOutHdl));
145  m_xWidget->connect_get_property_tree(LINK(this, SvxFontSizeBox_Impl, DumpAsPropertyTreeHdl));
146 }
147 
148 void SvxFontSizeBox_Impl::dispose()
149 {
150  m_xWidget.reset();
152 }
153 
154 SvxFontSizeBox_Impl::~SvxFontSizeBox_Impl()
155 {
156  disposeOnce();
157 }
158 
159 void SvxFontSizeBox_Impl::GetFocus()
160 {
161  if (m_xWidget)
162  m_xWidget->grab_focus();
164 }
165 
166 void SvxFontSizeBox_Impl::ReleaseFocus_Impl()
167 {
168  if ( !m_bRelease )
169  {
170  m_bRelease = true;
171  return;
172  }
173 
174  if ( m_xFrame.is() && m_xFrame->getContainerWindow().is() )
175  m_xFrame->getContainerWindow()->setFocus();
176 }
177 
178 IMPL_LINK(SvxFontSizeBox_Impl, SelectHdl, weld::ComboBox&, rCombo, void)
179 {
180  if (rCombo.changed_by_direct_pick()) // only when picked from the list
181  Select();
182 }
183 
184 IMPL_LINK_NOARG(SvxFontSizeBox_Impl, ActivateHdl, weld::ComboBox&, bool)
185 {
186  Select();
187  return true;
188 }
189 
190 void SvxFontSizeBox_Impl::Select()
191 {
192  sal_Int64 nSelVal = m_xWidget->get_value();
193  float fSelVal = float( nSelVal ) / 10;
194 
195  uno::Sequence< beans::PropertyValue > aArgs( 1 );
196  aArgs[0].Name = "FontHeight.Height";
197  aArgs[0].Value <<= fSelVal;
198 
199  /* #i33380# DR 2004-09-03 Moved the following line above the Dispatch() call.
200  This instance may be deleted in the meantime (i.e. when a dialog is opened
201  while in Dispatch()), accessing members will crash in this case. */
202  ReleaseFocus_Impl();
203 
204  m_rCtrl.dispatchCommand( aArgs );
205 }
206 
207 void SvxFontSizeBox_Impl::statusChanged_Impl( long nPoint, bool bErase )
208 {
209  if ( !bErase )
210  {
211  // convert the metric
212  long nVal = nPoint;
213 
214  // changed => set new value
215  if (m_xWidget->get_value() != nVal)
216  m_xWidget->set_value(nVal);
217  }
218  else
219  {
220  // delete value in the display
221  m_xWidget->set_value(-1L);
222  m_xWidget->set_entry_text("");
223  }
224  m_aCurText = m_xWidget->get_active_text();
225 }
226 
227 void SvxFontSizeBox_Impl::UpdateFont( const css::awt::FontDescriptor& rCurrentFont )
228 {
229  // filling up the sizes list
230  auto nOldVal = m_xWidget->get_value(); // memorize old value
231  const FontList* _pFontList = nullptr;
232  std::unique_ptr<FontList> aHold( new FontList( this ));
233  _pFontList = aHold.get();
234 
235  if ( !rCurrentFont.Name.isEmpty() )
236  {
237  FontMetric _aFontMetric;
238  _aFontMetric.SetFamilyName( rCurrentFont.Name );
239  _aFontMetric.SetStyleName( rCurrentFont.StyleName );
240  _aFontMetric.SetFontHeight( rCurrentFont.Height );
241  m_xWidget->Fill(&_aFontMetric, _pFontList);
242  }
243  else
244  {
245  m_xWidget->Fill(nullptr, _pFontList);
246  }
247  m_xWidget->set_value(nOldVal); // restore old value
248  m_aCurText = m_xWidget->get_active_text(); // memorize to reset at ESC
249 }
250 
251 IMPL_LINK(SvxFontSizeBox_Impl, KeyInputHdl, const KeyEvent&, rKEvt, bool)
252 {
253  bool bHandled = false;
254 
255  sal_uInt16 nCode = rKEvt.GetKeyCode().GetCode();
256 
257  switch (nCode)
258  {
259  case KEY_TAB:
260  m_bRelease = false;
261  Select();
262  break;
263 
264  case KEY_ESCAPE:
265  m_xWidget->set_entry_text(m_aCurText);
266  if ( typeid( *GetParent() ) != typeid( sfx2::sidebar::SidebarToolBox ) )
267  ReleaseFocus_Impl();
268  bHandled = true;
269  break;
270  }
271 
272  return bHandled || ChildKeyInput(rKEvt);
273 }
274 
275 IMPL_LINK_NOARG(SvxFontSizeBox_Impl, FocusOutHdl, weld::Widget&, void)
276 {
277  if (!m_xWidget->has_focus()) // a combobox can be comprised of different subwidget so double-check if none of those has focus
278  m_xWidget->set_entry_text(m_aCurText);
279 }
280 
281 void SvxFontSizeBox_Impl::SetOptimalSize()
282 {
283  SetSizePixel(get_preferred_size());
284 }
285 
286 void SvxFontSizeBox_Impl::DataChanged( const DataChangedEvent& rDCEvt )
287 {
288  if ( (rDCEvt.GetType() == DataChangedEventType::SETTINGS) &&
289  (rDCEvt.GetFlags() & AllSettingsFlags::STYLE) )
290  {
291  SetOptimalSize();
292  }
293 }
294 
295 IMPL_LINK(SvxFontSizeBox_Impl, DumpAsPropertyTreeHdl, boost::property_tree::ptree&, rTree, void)
296 {
297  boost::property_tree::ptree aEntries;
298 
299  for (int i = 0, nCount = m_xWidget->get_count(); i < nCount; ++i)
300  {
301  boost::property_tree::ptree aEntry;
302  aEntry.put("", m_xWidget->get_text(i));
303  aEntries.push_back(std::make_pair("", aEntry));
304  }
305 
306  rTree.add_child("entries", aEntries);
307 
308  boost::property_tree::ptree aSelected;
309 
310  int nActive = m_xWidget->get_active();
311  if (nActive != -1)
312  {
313  boost::property_tree::ptree aEntry;
314  aEntry.put("", nActive);
315  aSelected.push_back(std::make_pair("", aEntry));
316  }
317 
318  rTree.put("selectedCount", nActive == -1 ? 0 : 1);
319  rTree.add_child("selectedEntries", aSelected);
320 
321  rTree.put("command", ".uno:FontHeight");
322 }
323 
324 FontHeightToolBoxControl::FontHeightToolBoxControl( const uno::Reference< uno::XComponentContext >& rxContext )
325  : svt::ToolboxController( rxContext,
326  uno::Reference< frame::XFrame >(),
327  ".uno:FontHeight" ),
328  m_pBox( nullptr )
329 {
330  addStatusListener( ".uno:CharFontName");
331 }
332 
333 // XInterface
334 css::uno::Any SAL_CALL FontHeightToolBoxControl::queryInterface( const css::uno::Type& aType )
335 {
336  uno::Any a = ToolboxController::queryInterface( aType );
337  if ( a.hasValue() )
338  return a;
339 
340  return ::cppu::queryInterface( aType, static_cast< lang::XServiceInfo* >( this ));
341 }
342 
343 void SAL_CALL FontHeightToolBoxControl::acquire() throw ()
344 {
345  ToolboxController::acquire();
346 }
347 
348 void SAL_CALL FontHeightToolBoxControl::release() throw ()
349 {
350  ToolboxController::release();
351 }
352 
353 // XServiceInfo
354 sal_Bool SAL_CALL FontHeightToolBoxControl::supportsService( const OUString& ServiceName )
355 {
356  return cppu::supportsService(this, ServiceName);
357 }
358 
359 OUString SAL_CALL FontHeightToolBoxControl::getImplementationName()
360 {
361  return "com.sun.star.svx.FontHeightToolBoxController";
362 }
363 
364 uno::Sequence< OUString > SAL_CALL FontHeightToolBoxControl::getSupportedServiceNames( )
365 {
366  return { "com.sun.star.frame.ToolbarController" };
367 }
368 
369 // XComponent
370 void SAL_CALL FontHeightToolBoxControl::dispose()
371 {
373 
374  SolarMutexGuard aSolarMutexGuard;
375  m_pBox.disposeAndClear();
376 }
377 
378 // XStatusListener
379 void SAL_CALL FontHeightToolBoxControl::statusChanged(
380  const frame::FeatureStateEvent& rEvent )
381 {
382  if ( m_pBox )
383  {
384  SolarMutexGuard aSolarMutexGuard;
385  if ( rEvent.FeatureURL.Path == "FontHeight" )
386  {
387  ToolBox* pToolBox = nullptr;
388  sal_uInt16 nId = 0;
389  if ( !getToolboxId( nId, &pToolBox ) )
390  return;
391 
392  if ( rEvent.IsEnabled )
393  {
394  m_pBox->Enable();
395  frame::status::FontHeight aFontHeight;
396  if ( rEvent.State >>= aFontHeight )
397  m_pBox->statusChanged_Impl( long( 10. * aFontHeight.Height ), false );
398  else
399  m_pBox->statusChanged_Impl( long( -1 ), true );
400  }
401  else
402  {
403  m_pBox->Disable();
404  m_pBox->statusChanged_Impl( long( -1 ), true );
405  }
406 
407  pToolBox->EnableItem( nId, rEvent.IsEnabled );
408  }
409  else if ( rEvent.FeatureURL.Path == "CharFontName" )
410  {
411  if ( rEvent.State >>= m_aCurrentFont )
412  m_pBox->UpdateFont( m_aCurrentFont );
413  }
414  }
415 }
416 
417 // XToolbarController
418 void SAL_CALL FontHeightToolBoxControl::execute( sal_Int16 /*KeyModifier*/ )
419 {
420 }
421 
422 void SAL_CALL FontHeightToolBoxControl::click()
423 {
424 }
425 
426 void SAL_CALL FontHeightToolBoxControl::doubleClick()
427 {
428 }
429 
430 uno::Reference< awt::XWindow > SAL_CALL FontHeightToolBoxControl::createPopupWindow()
431 {
432  return uno::Reference< awt::XWindow >();
433 }
434 
435 uno::Reference< awt::XWindow > SAL_CALL FontHeightToolBoxControl::createItemWindow(
436  const uno::Reference< awt::XWindow >& xParent )
437 {
438  uno::Reference< awt::XWindow > xItemWindow;
439 
440  VclPtr<vcl::Window> pParent = VCLUnoHelper::GetWindow( xParent );
441  if ( pParent )
442  {
443  SolarMutexGuard aSolarMutexGuard;
444  m_pBox = VclPtr<SvxFontSizeBox_Impl>::Create( pParent, m_xFrame, *this );
445  //Get the box to fill itself with all its sizes
446  m_pBox->UpdateFont(m_aCurrentFont);
447  //Make it size itself to its optimal size re above sizes
448  m_pBox->SetOptimalSize();
449  xItemWindow = VCLUnoHelper::GetInterface( m_pBox );
450  }
451 
452  return xItemWindow;
453 }
454 
455 void FontHeightToolBoxControl::dispatchCommand(
456  const uno::Sequence< beans::PropertyValue >& rArgs )
457 {
458  uno::Reference< frame::XDispatchProvider > xDispatchProvider( m_xFrame, uno::UNO_QUERY );
459  if ( xDispatchProvider.is() )
460  {
461  util::URL aURL;
462  uno::Reference< frame::XDispatch > xDispatch;
463  uno::Reference< util::XURLTransformer > xURLTransformer = getURLTransformer();
464 
465  aURL.Complete = ".uno:FontHeight";
466  xURLTransformer->parseStrict( aURL );
467  xDispatch = xDispatchProvider->queryDispatch( aURL, OUString(), 0 );
468  if ( xDispatch.is() )
469  xDispatch->dispatch( aURL, rArgs );
470  }
471 }
472 
473 }
474 
475 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
477  css::uno::XComponentContext *rxContext,
478  css::uno::Sequence<css::uno::Any> const &)
479 {
480  return cppu::acquire(new FontHeightToolBoxControl(rxContext));
481 }
482 
483 /* 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
DataChangedEventType GetType() const
IMPL_LINK_NOARG(MaskData, ExecHdl, weld::Button &, void)
Definition: _bmpmask.cxx:300
SAL_DLLPUBLIC_EXPORT css::uno::XInterface * com_sun_star_svx_FontHeightToolBoxController_get_implementation(css::uno::XComponentContext *rxContext, css::uno::Sequence< css::uno::Any > const &)
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 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
ScXMLEditAttributeMap::Entry const aEntries[]
static css::uno::Reference< css::awt::XWindow > GetInterface(vcl::Window *pWindow)
constexpr sal_uInt16 KEY_TAB