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