LibreOffice Module svx (master)  1
pszctrl.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 <vcl/builder.hxx>
21 #include <vcl/commandevent.hxx>
22 #include <vcl/event.hxx>
23 #include <vcl/fieldvalues.hxx>
24 #include <vcl/status.hxx>
25 #include <vcl/menu.hxx>
26 #include <vcl/image.hxx>
27 #include <vcl/settings.hxx>
28 #include <vcl/svapp.hxx>
29 #include <svl/stritem.hxx>
30 #include <svl/ptitem.hxx>
31 #include <sfx2/module.hxx>
32 #include <svl/intitem.hxx>
33 #include <sal/log.hxx>
34 
35 #include <svx/pszctrl.hxx>
36 
37 #define PAINT_OFFSET 5
38 
39 #include <editeng/sizeitem.hxx>
40 #include "stbctrls.h"
41 
42 #include <svx/svxids.hrc>
43 #include <bitmaps.hlst>
45 
46 #include <com/sun/star/beans/PropertyValue.hpp>
47 
48 /* [Description]
49 
50  Function used to create a text representation of
51  a metric value
52 
53  nVal is the metric value in the unit eUnit.
54 
55  [cross reference]
56 
57  <SvxPosSizeStatusBarControl::Paint(const UserDrawEvent&)>
58 */
59 
61 {
62  // deliver and set the Metric of the application
63  FieldUnit eOutUnit = SfxModule::GetModuleFieldUnit( getFrameInterface() );
64 
65  OUString sMetric;
67  sal_Int64 nConvVal = vcl::ConvertValue( nVal * 100, 0, 0, FieldUnit::MM_100TH, eOutUnit );
68 
69  if ( nConvVal < 0 && ( nConvVal / 100 == 0 ) )
70  sMetric += "-";
71  sMetric += OUString::number(nConvVal / 100);
72 
73  if( FieldUnit::NONE != eOutUnit )
74  {
75  sMetric += OUStringChar(cSep);
76  sal_Int64 nFract = nConvVal % 100;
77 
78  if ( nFract < 0 )
79  nFract *= -1;
80  if ( nFract < 10 )
81  sMetric += "0";
82  sMetric += OUString::number(nFract);
83  }
84 
85  return sMetric;
86 }
87 
88 
90 
91 namespace {
92 
93 class FunctionPopup_Impl
94 {
95  VclBuilder m_aBuilder;
96  VclPtr<PopupMenu> m_xMenu;
97  sal_uInt32 m_nSelected;
98  static sal_uInt16 id_to_function(const OString& rIdent);
99  sal_uInt16 function_to_id(sal_uInt16 nFunc) const;
100 public:
101  explicit FunctionPopup_Impl( sal_uInt32 nCheckEncoded );
102  sal_uInt16 Execute(vcl::Window* pWindow, const Point& rPopupPos) { return m_xMenu->Execute(pWindow, rPopupPos); }
103  sal_uInt32 GetSelected() const;
104 };
105 
106 }
107 
108 sal_uInt16 FunctionPopup_Impl::id_to_function(const OString& rIdent)
109 {
110  if (rIdent == "avg")
111  return PSZ_FUNC_AVG;
112  else if (rIdent == "counta")
113  return PSZ_FUNC_COUNT2;
114  else if (rIdent == "count")
115  return PSZ_FUNC_COUNT;
116  else if (rIdent == "max")
117  return PSZ_FUNC_MAX;
118  else if (rIdent == "min")
119  return PSZ_FUNC_MIN;
120  else if (rIdent == "sum")
121  return PSZ_FUNC_SUM;
122  else if (rIdent == "selection")
124  else if (rIdent == "none")
125  return PSZ_FUNC_NONE;
126  return 0;
127 }
128 
129 sal_uInt16 FunctionPopup_Impl::function_to_id(sal_uInt16 nFunc) const
130 {
131  switch (nFunc)
132  {
133  case PSZ_FUNC_AVG:
134  return m_xMenu->GetItemId("avg");
135  case PSZ_FUNC_COUNT2:
136  return m_xMenu->GetItemId("counta");
137  case PSZ_FUNC_COUNT:
138  return m_xMenu->GetItemId("count");
139  case PSZ_FUNC_MAX:
140  return m_xMenu->GetItemId("max");
141  case PSZ_FUNC_MIN:
142  return m_xMenu->GetItemId("min");
143  case PSZ_FUNC_SUM:
144  return m_xMenu->GetItemId("sum");
146  return m_xMenu->GetItemId("selection");
147  case PSZ_FUNC_NONE:
148  return m_xMenu->GetItemId("none");
149  }
150  return 0;
151 }
152 
153 FunctionPopup_Impl::FunctionPopup_Impl(sal_uInt32 nCheckEncoded)
154  : m_aBuilder(nullptr, AllSettings::GetUIRootDir(), "svx/ui/functionmenu.ui", "")
155  , m_xMenu(m_aBuilder.get_menu("menu"))
156  , m_nSelected(nCheckEncoded)
157 {
158  for ( sal_uInt16 nCheck = 1; nCheck < 32; ++nCheck )
159  if ( nCheckEncoded & (1 << nCheck) )
160  m_xMenu->CheckItem(function_to_id(nCheck));
161 }
162 
163 sal_uInt32 FunctionPopup_Impl::GetSelected() const
164 {
165  sal_uInt32 nSelected = m_nSelected;
166  sal_uInt16 nCurItemId = id_to_function(m_xMenu->GetCurItemIdent());
167  if ( nCurItemId == PSZ_FUNC_NONE )
168  nSelected = ( 1 << PSZ_FUNC_NONE );
169  else
170  {
171  nSelected &= (~( 1 << PSZ_FUNC_NONE )); // Clear the "None" bit
172  nSelected ^= ( 1 << nCurItemId ); // Toggle the bit corresponding to nCurItemId
173  if ( !nSelected )
174  nSelected = ( 1 << PSZ_FUNC_NONE );
175  }
176  return nSelected;
177 }
178 
180 
181 /* [Description]
182 
183  This implementation-structure of the class SvxPosSizeStatusBarControl
184  is done for the un-linking of the changes of the exported interface such as
185  the toning down of symbols that are visible externally.
186 
187  One instance exists for each SvxPosSizeStatusBarControl-instance
188  during its life time
189 */
190 
191 {
192  Point aPos; // valid when a position is shown
193  Size aSize; // valid when a size is shown
194  OUString aStr; // valid when a text is shown
195  bool bPos; // show position ?
196  bool bSize; // set size ?
197  bool bTable; // set table index ?
198  bool bHasMenu; // set StarCalc popup menu ?
199  sal_uInt32 nFunctionSet; // the selected StarCalc functions encoded in 32 bits
200  Image aPosImage; // Image to show the position
201  Image aSizeImage; // Image to show the size
202 };
203 
204 /* [Description]
205 
206  Ctor():
207  Create an instance of the implementation class,
208  load the images for the position and size
209 */
210 
211 #define STR_POSITION ".uno:Position"
212 #define STR_TABLECELL ".uno:StateTableCell"
213 #define STR_FUNC ".uno:StatusBarFunc"
214 
216  sal_uInt16 _nId,
217  StatusBar& rStb ) :
218  SfxStatusBarControl( _nSlotId, _nId, rStb ),
220 {
221  pImpl->bPos = false;
222  pImpl->bSize = false;
223  pImpl->bTable = false;
224  pImpl->bHasMenu = false;
225  pImpl->nFunctionSet = 0;
226  pImpl->aPosImage = Image(StockImage::Yes, RID_SVXBMP_POSITION);
227  pImpl->aSizeImage = Image(StockImage::Yes, RID_SVXBMP_SIZE);
228 
229  addStatusListener( STR_POSITION); // SID_ATTR_POSITION
230  addStatusListener( STR_TABLECELL); // SID_TABLE_CELL
231  addStatusListener( STR_FUNC); // SID_PSZ_FUNCTION
233 }
234 
235 /* [Description]
236 
237  Dtor():
238  remove the pointer to the implementation class, so that the timer is stopped
239 
240 */
241 
243 {
244 }
245 
246 
247 /* [Description]
248 
249  SID_PSZ_FUNCTION activates the popup menu for Calc:
250 
251  Status overview
252  Depending on the type of the item, a special setting is enabled, the others disabled.
253 
254  NULL/Void SfxPointItem SvxSizeItem SfxStringItem
255  ------------------------------------------------------------------------
256  Position sal_False FALSE
257  Size FALSE TRUE FALSE
258  Text sal_False sal_False TRUE
259 
260 */
261 
263  const SfxPoolItem* pState )
264 {
265  // Because the combi-controller, always sets the current Id as HelpId
266  // first clean the cached HelpText
267  GetStatusBar().SetHelpText( GetId(), "" );
268 
269  switch ( nSID )
270  {
271  case SID_ATTR_POSITION : GetStatusBar().SetHelpId( GetId(), STR_POSITION ); break;
272  case SID_TABLE_CELL: GetStatusBar().SetHelpId( GetId(), STR_TABLECELL ); break;
273  case SID_PSZ_FUNCTION: GetStatusBar().SetHelpId( GetId(), STR_FUNC ); break;
274  default: break;
275  }
276 
277  if ( nSID == SID_PSZ_FUNCTION )
278  {
279  if ( eState == SfxItemState::DEFAULT )
280  {
281  pImpl->bHasMenu = true;
282  if ( auto pUInt32Item = dynamic_cast< const SfxUInt32Item* >(pState) )
283  pImpl->nFunctionSet = pUInt32Item->GetValue();
284  }
285  else
286  pImpl->bHasMenu = false;
287  }
288  else if ( SfxItemState::DEFAULT != eState )
289  {
290  // don't switch to empty display before an empty state was
291  // notified for all display types
292 
293  if ( nSID == SID_TABLE_CELL )
294  pImpl->bTable = false;
295  else if ( nSID == SID_ATTR_POSITION )
296  pImpl->bPos = false;
297  else if ( nSID == GetSlotId() ) // controller is registered for SID_ATTR_SIZE
298  pImpl->bSize = false;
299  else
300  {
301  SAL_WARN( "svx.stbcrtls","unknown slot id");
302  }
303  }
304  else if ( auto pPointItem = dynamic_cast<const SfxPointItem*>( pState) )
305  {
306  // show position
307  pImpl->aPos = pPointItem->GetValue();
308  pImpl->bPos = true;
309  pImpl->bTable = false;
310  }
311  else if ( auto pSizeItem = dynamic_cast<const SvxSizeItem*>( pState) )
312  {
313  // show size
314  pImpl->aSize = pSizeItem->GetSize();
315  pImpl->bSize = true;
316  pImpl->bTable = false;
317  }
318  else if ( auto pStringItem = dynamic_cast<const SfxStringItem*>( pState) )
319  {
320  // show string (table cel or different)
321  pImpl->aStr = pStringItem->GetValue();
322  pImpl->bTable = true;
323  pImpl->bPos = false;
324  pImpl->bSize = false;
325  }
326  else
327  {
328  SAL_WARN( "svx.stbcrtls", "invalid item type" );
329  pImpl->bPos = false;
330  pImpl->bSize = false;
331  pImpl->bTable = false;
332  }
333 
334  GetStatusBar().SetItemData( GetId(), nullptr );
335 
337 }
338 
339 
340 /* [Description]
341 
342  execute popup menu, when the status enables this
343 */
344 
346 {
347  if ( rCEvt.GetCommand() == CommandEventId::ContextMenu && pImpl->bHasMenu )
348  {
349  sal_uInt32 nSelect = pImpl->nFunctionSet;
350  if (!nSelect)
351  nSelect = ( 1 << PSZ_FUNC_NONE );
352  FunctionPopup_Impl aMenu(nSelect);
353  if (aMenu.Execute(&GetStatusBar(), rCEvt.GetMousePosPixel()))
354  {
355  nSelect = aMenu.GetSelected();
356  if (nSelect)
357  {
358  if (nSelect == (1 << PSZ_FUNC_NONE))
359  nSelect = 0;
360 
361  css::uno::Any a;
362  SfxUInt32Item aItem( SID_PSZ_FUNCTION, nSelect );
363 
364  css::uno::Sequence< css::beans::PropertyValue > aArgs( 1 );
365  aArgs[0].Name = "StatusBarFunc";
366  aItem.QueryValue( a );
367  aArgs[0].Value = a;
368 
369  execute( ".uno:StatusBarFunc", aArgs );
370  }
371  }
372  }
373  else
375 }
376 
377 
378 /* [Description]
379 
380  Depending on the type to be shown, the value us shown. First the
381  rectangle is repainted (removed).
382 */
383 
385 {
386  vcl::RenderContext* pDev = rUsrEvt.GetRenderContext();
387 
388  const tools::Rectangle& rRect = rUsrEvt.GetRect();
389  StatusBar& rBar = GetStatusBar();
390  Point aItemPos = rBar.GetItemTextPos( GetId() );
391  Color aOldLineColor = pDev->GetLineColor();
392  Color aOldFillColor = pDev->GetFillColor();
393  pDev->SetLineColor();
394  pDev->SetFillColor( pDev->GetBackground().GetColor() );
395 
396  if ( pImpl->bPos || pImpl->bSize )
397  {
398  // count the position for showing the size
399  long nSizePosX =
400  rRect.Left() + rRect.GetWidth() / 2 + PAINT_OFFSET;
401  // draw position
402  Point aPnt = rRect.TopLeft();
403  aPnt.setY( aItemPos.Y() );
404  aPnt.AdjustX(PAINT_OFFSET );
405  pDev->DrawImage( aPnt, pImpl->aPosImage );
406  aPnt.AdjustX(pImpl->aPosImage.GetSizePixel().Width() );
407  aPnt.AdjustX(PAINT_OFFSET );
408  OUString aStr = GetMetricStr_Impl( pImpl->aPos.X()) + " / " +
409  GetMetricStr_Impl( pImpl->aPos.Y());
410  tools::Rectangle aRect(aPnt, Point(nSizePosX, rRect.Bottom()));
411  pDev->DrawRect(aRect);
412  vcl::Region aOrigRegion(pDev->GetClipRegion());
413  pDev->SetClipRegion(vcl::Region(aRect));
414  pDev->DrawText(aPnt, aStr);
415  pDev->SetClipRegion(aOrigRegion);
416 
417  // draw the size, when available
418  aPnt.setX( nSizePosX );
419 
420  if ( pImpl->bSize )
421  {
422  pDev->DrawImage( aPnt, pImpl->aSizeImage );
423  aPnt.AdjustX(pImpl->aSizeImage.GetSizePixel().Width() );
424  Point aDrwPnt = aPnt;
425  aPnt.AdjustX(PAINT_OFFSET );
426  aStr = GetMetricStr_Impl( pImpl->aSize.Width() ) + " x " +
427  GetMetricStr_Impl( pImpl->aSize.Height() );
428  aRect = tools::Rectangle(aDrwPnt, rRect.BottomRight());
429  pDev->DrawRect(aRect);
430  aOrigRegion = pDev->GetClipRegion();
431  pDev->SetClipRegion(vcl::Region(aRect));
432  pDev->DrawText(aPnt, aStr);
433  pDev->SetClipRegion(aOrigRegion);
434  }
435  else
436  pDev->DrawRect( tools::Rectangle( aPnt, rRect.BottomRight() ) );
437  }
438  else if ( pImpl->bTable )
439  {
440  pDev->DrawRect( rRect );
441  pDev->DrawText( Point(
442  rRect.Left() + rRect.GetWidth() / 2 - pDev->GetTextWidth( pImpl->aStr ) / 2,
443  aItemPos.Y() ), pImpl->aStr );
444  }
445  else
446  {
447  // Empty display if neither size nor table position are available.
448  // Date/Time are no longer used (#65302#).
449  pDev->DrawRect( rRect );
450  }
451 
452  pDev->SetLineColor( aOldLineColor );
453  pDev->SetFillColor( aOldFillColor );
454 }
455 
457 {
458  // set only strings as text at the statusBar, so that the Help-Tips
459  // can work with the text, when it is too long for the statusBar
460  OUString aText;
461  int nCharsWidth = -1;
462  if ( pImpl->bPos || pImpl->bSize )
463  {
464  aText = GetMetricStr_Impl( pImpl->aPos.X()) + " / " +
465  GetMetricStr_Impl( pImpl->aPos.Y());
466  // widest X/Y string looks like "-999,99"
467  nCharsWidth = 1 + 6 + 3 + 6; // icon + x + slash + y
468  if ( pImpl->bSize )
469  {
470  aText += " " + GetMetricStr_Impl( pImpl->aSize.Width() ) + " x " +
471  GetMetricStr_Impl( pImpl->aSize.Height() );
472  nCharsWidth += 1 + 1 + 4 + 3 + 4; // icon + space + w + x + h
473  }
474  }
475  else if ( pImpl->bTable )
476  aText = pImpl->aStr;
477 
478  GetStatusBar().SetItemText( GetId(), aText, nCharsWidth );
479 }
480 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Point TopLeft() const
void SetClipRegion()
vcl::Region GetClipRegion() const
void DrawText(const Point &rStartPt, const OUString &rStr, sal_Int32 nIndex=0, sal_Int32 nLen=-1, MetricVector *pVector=nullptr, OUString *pDisplayText=nullptr, const SalLayoutGlyphs *pLayoutCache=nullptr)
long GetWidth() const
const Wallpaper & GetBackground() const
FieldUnit
const LocaleDataWrapper & GetLocaleDataWrapper() const
sal_uInt16 GetSlotId() const
void DrawImage(const Point &rPos, const Image &rImage, DrawImageFlags nStyle=DrawImageFlags::NONE)
const tools::Rectangle & GetRect() const
#define PAINT_OFFSET
Definition: pszctrl.cxx:37
static const AllSettings & GetSettings()
#define PSZ_FUNC_COUNT
Definition: stbctrls.h:26
void SetItemText(sal_uInt16 nItemId, const OUString &rText, int nCharsWidth=-1)
sal_uInt16 Execute(vcl::Window *pWindow, const Point &rPopupPos)
virtual ~SvxPosSizeStatusBarControl() override
Definition: pszctrl.cxx:242
virtual void StateChanged(sal_uInt16 nSID, SfxItemState eState, const SfxPoolItem *pState) override
Definition: pszctrl.cxx:262
void SetHelpText(sal_uInt16 nItemId, const OUString &rText)
sal_uInt16 sal_Unicode
#define PSZ_FUNC_COUNT2
Definition: stbctrls.h:25
void SetItemData(sal_uInt16 nItemId, void *pNewData)
void DrawRect(const tools::Rectangle &rRect)
Point GetItemTextPos(sal_uInt16 nItemId) const
sal_uInt16 GetId() const
Point BottomRight() const
static FieldUnit GetModuleFieldUnit(css::uno::Reference< css::frame::XFrame > const &i_frame)
const OUString & getNumDecimalSep() const
void SetLineColor()
#define PSZ_FUNC_AVG
Definition: stbctrls.h:24
vcl::RenderContext * GetRenderContext() const
#define PSZ_FUNC_MAX
Definition: stbctrls.h:27
uno_Any a
virtual bool QueryValue(css::uno::Any &rVal, sal_uInt8 nMemberId=0) const override
#define STR_POSITION
Definition: pszctrl.cxx:211
#define PSZ_FUNC_SELECTION_COUNT
Definition: stbctrls.h:30
const Color & GetColor() const
void SetFillColor()
const Color & GetLineColor() const
CommandEventId GetCommand() const
long Bottom() const
#define PSZ_FUNC_SUM
Definition: stbctrls.h:29
#define STR_TABLECELL
Definition: pszctrl.cxx:212
const Point & GetMousePosPixel() const
SfxItemState
SVX_DLLPRIVATE OUString GetMetricStr_Impl(long nVal)
Definition: pszctrl.cxx:60
SFX_IMPL_STATUSBAR_CONTROL(SvxPosSizeStatusBarControl, SvxSizeItem)
virtual void Command(const CommandEvent &rCEvt)
StatusBar & GetStatusBar() const
void SetHelpId(sal_uInt16 nItemId, const OString &rHelpId)
long Left() const
long GetTextWidth(const OUString &rStr, sal_Int32 nIndex=0, sal_Int32 nLen=-1, vcl::TextLayoutCache const *=nullptr, SalLayoutGlyphs const *const pLayoutCache=nullptr) const
#define PSZ_FUNC_NONE
Definition: stbctrls.h:31
sal_Int64 ConvertValue(sal_Int64 nValue, sal_Int64 mnBaseValue, sal_uInt16 nDecDigits, FieldUnit eInUnit, FieldUnit eOutUnit)
#define SAL_WARN(area, stream)
virtual void Command(const CommandEvent &rCEvt) override
Definition: pszctrl.cxx:345
SvxPosSizeStatusBarControl(sal_uInt16 nSlotId, sal_uInt16 nId, StatusBar &rStb)
Definition: pszctrl.cxx:215
aStr
std::unique_ptr< SvxPosSizeStatusBarControl_Impl > pImpl
Definition: pszctrl.hxx:31
#define STR_FUNC
Definition: pszctrl.cxx:213
const Color & GetFillColor() const
virtual void Paint(const UserDrawEvent &rEvt) override
Definition: pszctrl.cxx:384
#define PSZ_FUNC_MIN
Definition: stbctrls.h:28