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 <sal/config.h>
21
23#include <vcl/commandevent.hxx>
24#include <vcl/event.hxx>
25#include <vcl/fieldvalues.hxx>
26#include <vcl/status.hxx>
27#include <vcl/image.hxx>
28#include <vcl/settings.hxx>
29#include <vcl/svapp.hxx>
30#include <vcl/weld.hxx>
31#include <vcl/weldutils.hxx>
32#include <svl/stritem.hxx>
33#include <svl/ptitem.hxx>
34#include <sfx2/module.hxx>
35#include <svx/dialmgr.hxx>
36#include <svx/statusitem.hxx>
37#include <svx/strings.hrc>
38#include <svl/intitem.hxx>
39#include <sal/log.hxx>
40
41#include <svx/pszctrl.hxx>
42
43#define PAINT_OFFSET 5
44
45#include <editeng/sizeitem.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 = vcl::ConvertValue( nVal * 100, 0, 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
97namespace {
98
99class FunctionPopup_Impl
100{
101 std::unique_ptr<weld::Builder> m_xBuilder;
102 std::unique_ptr<weld::Menu> m_xMenu;
103 sal_uInt32 m_nSelected;
104 static sal_uInt16 id_to_function(std::u16string_view rIdent);
105 static OUString function_to_id(sal_uInt16 nFunc);
106public:
107 explicit FunctionPopup_Impl(sal_uInt32 nCheckEncoded);
108 OUString Execute(weld::Window* pParent, const tools::Rectangle& rRect)
109 {
110 return m_xMenu->popup_at_rect(pParent, rRect);
111 }
112 sal_uInt32 GetSelected(std::u16string_view curident) const;
113};
114
115}
116
117sal_uInt16 FunctionPopup_Impl::id_to_function(std::u16string_view rIdent)
118{
119 if (rIdent == u"avg")
120 return PSZ_FUNC_AVG;
121 else if (rIdent == u"counta")
122 return PSZ_FUNC_COUNT2;
123 else if (rIdent == u"count")
124 return PSZ_FUNC_COUNT;
125 else if (rIdent == u"max")
126 return PSZ_FUNC_MAX;
127 else if (rIdent == u"min")
128 return PSZ_FUNC_MIN;
129 else if (rIdent == u"sum")
130 return PSZ_FUNC_SUM;
131 else if (rIdent == u"selection")
133 else if (rIdent == u"none")
134 return PSZ_FUNC_NONE;
135 return 0;
136}
137
138OUString FunctionPopup_Impl::function_to_id(sal_uInt16 nFunc)
139{
140 switch (nFunc)
141 {
142 case PSZ_FUNC_AVG:
143 return "avg";
144 case PSZ_FUNC_COUNT2:
145 return "counta";
146 case PSZ_FUNC_COUNT:
147 return "count";
148 case PSZ_FUNC_MAX:
149 return "max";
150 case PSZ_FUNC_MIN:
151 return "min";
152 case PSZ_FUNC_SUM:
153 return "sum";
155 return "selection";
156 case PSZ_FUNC_NONE:
157 return "none";
158 }
159 return {};
160}
161
162FunctionPopup_Impl::FunctionPopup_Impl(sal_uInt32 nCheckEncoded)
163 : m_xBuilder(Application::CreateBuilder(nullptr, "svx/ui/functionmenu.ui"))
164 , m_xMenu(m_xBuilder->weld_menu("menu"))
165 , m_nSelected(nCheckEncoded)
166{
167 for ( sal_uInt16 nCheck = 1; nCheck < 32; ++nCheck )
168 if ( nCheckEncoded & (1u << nCheck) )
169 m_xMenu->set_active(function_to_id(nCheck), true);
170}
171
172sal_uInt32 FunctionPopup_Impl::GetSelected(std::u16string_view curident) const
173{
174 sal_uInt32 nSelected = m_nSelected;
175 sal_uInt16 nCurItemId = id_to_function(curident);
176 if ( nCurItemId == PSZ_FUNC_NONE )
177 nSelected = ( 1 << PSZ_FUNC_NONE );
178 else
179 {
180 nSelected &= (~( 1u << PSZ_FUNC_NONE )); // Clear the "None" bit
181 nSelected ^= ( 1u << nCurItemId ); // Toggle the bit corresponding to nCurItemId
182 if ( !nSelected )
183 nSelected = ( 1u << PSZ_FUNC_NONE );
184 }
185 return nSelected;
186}
187
189
190/* [Description]
191
192 This implementation-structure of the class SvxPosSizeStatusBarControl
193 is done for the un-linking of the changes of the exported interface such as
194 the toning down of symbols that are visible externally.
195
196 One instance exists for each SvxPosSizeStatusBarControl-instance
197 during its life time
198*/
199
200{
201 Point aPos; // valid when a position is shown
202 Size aSize; // valid when a size is shown
203 OUString aStr; // valid when a text is shown
204 bool bPos; // show position ?
205 bool bSize; // set size ?
206 bool bTable; // set table index ?
207 bool bHasMenu; // set StarCalc popup menu ?
208 sal_uInt32 nFunctionSet; // the selected StarCalc functions encoded in 32 bits
209 Image aPosImage; // Image to show the position
210 Image aSizeImage; // Image to show the size
211};
212
213/* [Description]
214
215 Ctor():
216 Create an instance of the implementation class,
217 load the images for the position and size
218*/
219
220#define STR_POSITION ".uno:Position"
221#define STR_TABLECELL ".uno:StateTableCell"
222#define STR_FUNC ".uno:StatusBarFunc"
223
225 sal_uInt16 _nId,
226 StatusBar& rStb ) :
227 SfxStatusBarControl( _nSlotId, _nId, rStb ),
229{
230 pImpl->bPos = false;
231 pImpl->bSize = false;
232 pImpl->bTable = false;
233 pImpl->bHasMenu = false;
234 pImpl->nFunctionSet = 0;
235 pImpl->aPosImage = Image(StockImage::Yes, RID_SVXBMP_POSITION);
236 pImpl->aSizeImage = Image(StockImage::Yes, RID_SVXBMP_SIZE);
237
238 addStatusListener( STR_POSITION); // SID_ATTR_POSITION
239 addStatusListener( STR_TABLECELL); // SID_TABLE_CELL
240 addStatusListener( STR_FUNC); // SID_PSZ_FUNCTION
242}
243
244/* [Description]
245
246 Dtor():
247 remove the pointer to the implementation class, so that the timer is stopped
248
249*/
250
252{
253}
254
255
256/* [Description]
257
258 SID_PSZ_FUNCTION activates the popup menu for Calc:
259
260 Status overview
261 Depending on the type of the item, a special setting is enabled, the others disabled.
262
263 NULL/Void SfxPointItem SvxSizeItem SfxStringItem
264 ------------------------------------------------------------------------
265 Position sal_False FALSE
266 Size FALSE TRUE FALSE
267 Text sal_False sal_False TRUE
268
269*/
270
272 const SfxPoolItem* pState )
273{
274 // Because the combi-controller, always sets the current Id as HelpId
275 // first clean the cached HelpText
276 GetStatusBar().SetHelpText( GetId(), "" );
277
278 switch ( nSID )
279 {
280 case SID_ATTR_POSITION : GetStatusBar().SetHelpId( GetId(), STR_POSITION ); break;
281 case SID_TABLE_CELL: GetStatusBar().SetHelpId( GetId(), STR_TABLECELL ); break;
282 case SID_PSZ_FUNCTION: GetStatusBar().SetHelpId( GetId(), STR_FUNC ); break;
283 default: break;
284 }
285
286 if ( nSID == SID_PSZ_FUNCTION )
287 {
288 if ( eState == SfxItemState::DEFAULT )
289 {
290 pImpl->bHasMenu = true;
291 if ( auto pUInt32Item = dynamic_cast< const SfxUInt32Item* >(pState) )
292 pImpl->nFunctionSet = pUInt32Item->GetValue();
293 }
294 else
295 pImpl->bHasMenu = false;
296 }
297 else if ( SfxItemState::DEFAULT != eState )
298 {
299 // don't switch to empty display before an empty state was
300 // notified for all display types
301
302 if ( nSID == SID_TABLE_CELL )
303 pImpl->bTable = false;
304 else if ( nSID == SID_ATTR_POSITION )
305 pImpl->bPos = false;
306 else if ( nSID == GetSlotId() ) // controller is registered for SID_ATTR_SIZE
307 pImpl->bSize = false;
308 else
309 {
310 SAL_WARN( "svx.stbcrtls","unknown slot id");
311 }
312 }
313 else if ( auto pPointItem = dynamic_cast<const SfxPointItem*>( pState) )
314 {
315 // show position
316 pImpl->aPos = pPointItem->GetValue();
317 pImpl->bPos = true;
318 pImpl->bTable = false;
319 }
320 else if ( auto pSizeItem = dynamic_cast<const SvxSizeItem*>( pState) )
321 {
322 // show size
323 pImpl->aSize = pSizeItem->GetSize();
324 pImpl->bSize = true;
325 pImpl->bTable = false;
326 }
327 else if ( auto pStatusItem = dynamic_cast<const SvxStatusItem*>( pState) )
328 {
329 // show string (table cell or different)
330 pImpl->aStr = pStatusItem->GetValue();
331 pImpl->bTable = true;
332 pImpl->bPos = false;
333 pImpl->bSize = false;
334 if (!pImpl->aStr.isEmpty())
335 {
336 OUString sTip;
337 switch (pStatusItem->GetCategory())
338 {
340 sTip = SvxResId(RID_SVXSTR_TABLECELL_HINT);
341 break;
343 sTip = SvxResId(RID_SVXSTR_SECTION_HINT);
344 break;
346 sTip = SvxResId(RID_SVXSTR_TOC_HINT);
347 break;
349 sTip = SvxResId(RID_SVXSTR_NUMBERING_HINT);
350 break;
352 sTip = SvxResId(RID_SVXSTR_LIST_STYLE_HINT);
353 break;
355 sTip = SvxResId(RID_SVXSTR_FORMULA_HINT);
356 break;
358 sTip = SvxResId(RID_SVXSTR_ROW_COLUMN_HINT);
359 break;
361 break;
362 }
364 }
365 }
366 else if ( auto pStringItem = dynamic_cast<const SfxStringItem*>( pState) )
367 {
368 SAL_WARN( "svx.stbcrtls", "this should be a SvxStatusItem not a SfxStringItem" );
369 // show string (table cell or different)
370 pImpl->aStr = pStringItem->GetValue();
371 pImpl->bTable = true;
372 pImpl->bPos = false;
373 pImpl->bSize = false;
374 }
375 else
376 {
377 SAL_WARN( "svx.stbcrtls", "invalid item type" );
378 pImpl->bPos = false;
379 pImpl->bSize = false;
380 pImpl->bTable = false;
381 }
382
383 GetStatusBar().SetItemData( GetId(), nullptr );
384
386}
387
388
389/* [Description]
390
391 execute popup menu, when the status enables this
392*/
393
395{
396 if ( rCEvt.GetCommand() == CommandEventId::ContextMenu && pImpl->bHasMenu )
397 {
398 sal_uInt32 nSelect = pImpl->nFunctionSet;
399 if (!nSelect)
400 nSelect = ( 1 << PSZ_FUNC_NONE );
401 tools::Rectangle aRect(rCEvt.GetMousePosPixel(), Size(1,1));
403 FunctionPopup_Impl aMenu(nSelect);
404 OUString sIdent = aMenu.Execute(pParent, aRect);
405 if (!sIdent.isEmpty())
406 {
407 nSelect = aMenu.GetSelected(sIdent);
408 if (nSelect)
409 {
410 if (nSelect == (1 << PSZ_FUNC_NONE))
411 nSelect = 0;
412
413 css::uno::Any a;
414 SfxUInt32Item aItem( SID_PSZ_FUNCTION, nSelect );
415 aItem.QueryValue( a );
416 css::uno::Sequence< css::beans::PropertyValue > aArgs{ comphelper::makePropertyValue(
417 "StatusBarFunc", a) };
418 execute( ".uno:StatusBarFunc", aArgs );
419 }
420 }
421 }
422 else
424}
425
426
427/* [Description]
428
429 Depending on the type to be shown, the value us shown. First the
430 rectangle is repainted (removed).
431*/
432
434{
435 vcl::RenderContext* pDev = rUsrEvt.GetRenderContext();
436
437 const tools::Rectangle& rRect = rUsrEvt.GetRect();
438 StatusBar& rBar = GetStatusBar();
439 Point aItemPos = rBar.GetItemTextPos( GetId() );
440 Color aOldLineColor = pDev->GetLineColor();
441 Color aOldFillColor = pDev->GetFillColor();
442 pDev->SetLineColor();
443 pDev->SetFillColor( pDev->GetBackground().GetColor() );
444
445 if ( pImpl->bPos || pImpl->bSize )
446 {
447 // count the position for showing the size
448 tools::Long nSizePosX =
449 rRect.Left() + rRect.GetWidth() / 2 + PAINT_OFFSET;
450 // draw position
451 Point aPnt = rRect.TopLeft();
452 aPnt.AdjustX(PAINT_OFFSET );
453 // vertically centered
454 const tools::Long nSizePosY =
455 (rRect.GetHeight() - pImpl->aPosImage.GetSizePixel().Height()) / 2;
456 aPnt.AdjustY( nSizePosY );
457
458 pDev->DrawImage( aPnt, pImpl->aPosImage );
459 aPnt.AdjustX(pImpl->aPosImage.GetSizePixel().Width() );
460 aPnt.AdjustX(PAINT_OFFSET );
461 OUString aStr = GetMetricStr_Impl( pImpl->aPos.X()) + " / " +
462 GetMetricStr_Impl( pImpl->aPos.Y());
463 tools::Rectangle aRect(aPnt, Point(nSizePosX, rRect.Bottom()));
464 pDev->DrawRect(aRect);
465 vcl::Region aOrigRegion(pDev->GetClipRegion());
466 pDev->SetClipRegion(vcl::Region(aRect));
467 pDev->DrawText(aPnt, aStr);
468 pDev->SetClipRegion(aOrigRegion);
469
470 // draw the size, when available
471 aPnt.setX( nSizePosX );
472
473 if ( pImpl->bSize )
474 {
475 pDev->DrawImage( aPnt, pImpl->aSizeImage );
476 aPnt.AdjustX(pImpl->aSizeImage.GetSizePixel().Width() );
477 Point aDrwPnt = aPnt;
478 aPnt.AdjustX(PAINT_OFFSET );
479 aStr = GetMetricStr_Impl( pImpl->aSize.Width() ) + " x " +
480 GetMetricStr_Impl( pImpl->aSize.Height() );
481 aRect = tools::Rectangle(aDrwPnt, rRect.BottomRight());
482 pDev->DrawRect(aRect);
483 aOrigRegion = pDev->GetClipRegion();
484 pDev->SetClipRegion(vcl::Region(aRect));
485 pDev->DrawText(aPnt, aStr);
486 pDev->SetClipRegion(aOrigRegion);
487 }
488 else
489 pDev->DrawRect( tools::Rectangle( aPnt, rRect.BottomRight() ) );
490 }
491 else if ( pImpl->bTable )
492 {
493 pDev->DrawRect( rRect );
494 pDev->DrawText( Point(
495 rRect.Left() + rRect.GetWidth() / 2 - pDev->GetTextWidth( pImpl->aStr ) / 2,
496 aItemPos.Y() ), pImpl->aStr );
497 }
498 else
499 {
500 // Empty display if neither size nor table position are available.
501 // Date/Time are no longer used (#65302#).
502 pDev->DrawRect( rRect );
503 }
504
505 pDev->SetLineColor( aOldLineColor );
506 pDev->SetFillColor( aOldFillColor );
507}
508
510{
511 // set only strings as text at the statusBar, so that the Help-Tips
512 // can work with the text, when it is too long for the statusBar
513 OUString aText;
514 int nCharsWidth = -1;
515 if ( pImpl->bPos || pImpl->bSize )
516 {
517 aText = GetMetricStr_Impl( pImpl->aPos.X()) + " / " +
518 GetMetricStr_Impl( pImpl->aPos.Y());
519 // widest X/Y string looks like "-999,99"
520 nCharsWidth = 1 + 6 + 3 + 6; // icon + x + slash + y
521 if ( pImpl->bSize )
522 {
523 aText += " " + GetMetricStr_Impl( pImpl->aSize.Width() ) + " x " +
524 GetMetricStr_Impl( pImpl->aSize.Height() );
525 nCharsWidth += 1 + 1 + 4 + 3 + 4; // icon + space + w + x + h
526 }
527 }
528 else if ( pImpl->bTable )
529 aText = pImpl->aStr;
530
531 GetStatusBar().SetItemText( GetId(), aText, nCharsWidth );
532}
533/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
const LocaleDataWrapper & GetLocaleDataWrapper() const
static const AllSettings & GetSettings()
virtual bool QueryValue(css::uno::Any &rVal, sal_uInt8 nMemberId=0) const override
CommandEventId GetCommand() const
const Point & GetMousePosPixel() const
const OUString & getNumDecimalSep() const
vcl::Region GetClipRegion() const
void DrawRect(const tools::Rectangle &rRect)
const Wallpaper & GetBackground() const
void SetLineColor()
tools::Long GetTextWidth(const OUString &rStr, sal_Int32 nIndex=0, sal_Int32 nLen=-1, vcl::text::TextLayoutCache const *=nullptr, SalLayoutGlyphs const *const pLayoutCache=nullptr) const
void SetClipRegion()
void DrawImage(const Point &rPos, const Image &rImage, DrawImageFlags nStyle=DrawImageFlags::NONE)
void SetFillColor()
const Color & GetLineColor() const
void DrawText(const Point &rStartPt, const OUString &rStr, sal_Int32 nIndex=0, sal_Int32 nLen=-1, std::vector< tools::Rectangle > *pVector=nullptr, OUString *pDisplayText=nullptr, const SalLayoutGlyphs *pLayoutCache=nullptr)
const Color & GetFillColor() const
constexpr tools::Long Y() const
void setX(tools::Long nX)
tools::Long AdjustY(tools::Long nVertMove)
tools::Long AdjustX(tools::Long nHorzMove)
static FieldUnit GetModuleFieldUnit(css::uno::Reference< css::frame::XFrame > const &i_frame)
StatusBar & GetStatusBar() const
virtual void Command(const CommandEvent &rCEvt)
sal_uInt16 GetId() const
sal_uInt16 GetSlotId() const
void SetItemText(sal_uInt16 nItemId, const OUString &rText, int nCharsWidth=-1)
void SetHelpText(sal_uInt16 nItemId, const OUString &rText)
void SetQuickHelpText(sal_uInt16 nItemId, const OUString &rText)
void SetHelpId(sal_uInt16 nItemId, const OUString &rHelpId)
void SetItemData(sal_uInt16 nItemId, void *pNewData)
Point GetItemTextPos(sal_uInt16 nItemId) const
virtual void StateChangedAtStatusBarControl(sal_uInt16 nSID, SfxItemState eState, const SfxPoolItem *pState) override
Definition: pszctrl.cxx:271
virtual ~SvxPosSizeStatusBarControl() override
Definition: pszctrl.cxx:251
SvxPosSizeStatusBarControl(sal_uInt16 nSlotId, sal_uInt16 nId, StatusBar &rStb)
Definition: pszctrl.cxx:224
std::unique_ptr< SvxPosSizeStatusBarControl_Impl > pImpl
Definition: pszctrl.hxx:31
virtual void Command(const CommandEvent &rCEvt) override
Definition: pszctrl.cxx:394
virtual void Paint(const UserDrawEvent &rEvt) override
Definition: pszctrl.cxx:433
SVX_DLLPRIVATE OUString GetMetricStr_Impl(tools::Long nVal) const
Definition: pszctrl.cxx:66
vcl::RenderContext * GetRenderContext() const
const tools::Rectangle & GetRect() const
const Color & GetColor() const
constexpr tools::Long GetWidth() const
constexpr Point TopLeft() const
constexpr Point BottomRight() const
constexpr tools::Long GetHeight() const
constexpr tools::Long Left() const
constexpr tools::Long Bottom() const
OUString SvxResId(TranslateId aId)
Definition: dialmgr.cxx:24
FieldUnit
uno_Any a
#define SAL_WARN(area, stream)
aStr
css::beans::PropertyValue makePropertyValue(const OUString &rName, T &&rValue)
long Long
sal_Int64 ConvertValue(sal_Int64 nValue, sal_Int64 mnBaseValue, sal_uInt16 nDecDigits, FieldUnit eInUnit, FieldUnit eOutUnit)
weld::Window * GetPopupParent(vcl::Window &rOutWin, tools::Rectangle &rRect)
SfxItemState
#define STR_POSITION
Definition: pszctrl.cxx:220
#define STR_TABLECELL
Definition: pszctrl.cxx:221
SFX_IMPL_STATUSBAR_CONTROL(SvxPosSizeStatusBarControl, SvxSizeItem)
#define PAINT_OFFSET
Definition: pszctrl.cxx:43
#define STR_FUNC
Definition: pszctrl.cxx:222
#define PSZ_FUNC_MIN
Definition: stbctrls.h:28
#define PSZ_FUNC_SUM
Definition: stbctrls.h:29
#define PSZ_FUNC_MAX
Definition: stbctrls.h:27
#define PSZ_FUNC_COUNT
Definition: stbctrls.h:26
#define PSZ_FUNC_AVG
Definition: stbctrls.h:24
#define PSZ_FUNC_COUNT2
Definition: stbctrls.h:25
#define PSZ_FUNC_NONE
Definition: stbctrls.h:31
#define PSZ_FUNC_SELECTION_COUNT
Definition: stbctrls.h:30
sal_uInt16 sal_Unicode