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 <svl/intitem.hxx>
36#include <sal/log.hxx>
37
38#include <svx/pszctrl.hxx>
39
40#define PAINT_OFFSET 5
41
42#include <editeng/sizeitem.hxx>
43#include "stbctrls.h"
44
45#include <svx/svxids.hrc>
46#include <bitmaps.hlst>
48
49#include <com/sun/star/beans/PropertyValue.hpp>
50
51/* [Description]
52
53 Function used to create a text representation of
54 a metric value
55
56 nVal is the metric value in the unit eUnit.
57
58 [cross reference]
59
60 <SvxPosSizeStatusBarControl::Paint(const UserDrawEvent&)>
61*/
62
64{
65 // deliver and set the Metric of the application
66 FieldUnit eOutUnit = SfxModule::GetModuleFieldUnit( getFrameInterface() );
67
68 OUString sMetric;
70 sal_Int64 nConvVal = vcl::ConvertValue( nVal * 100, 0, 0, FieldUnit::MM_100TH, eOutUnit );
71
72 if ( nConvVal < 0 && ( nConvVal / 100 == 0 ) )
73 sMetric += "-";
74 sMetric += OUString::number(nConvVal / 100);
75
76 if( FieldUnit::NONE != eOutUnit )
77 {
78 sMetric += OUStringChar(cSep);
79 sal_Int64 nFract = nConvVal % 100;
80
81 if ( nFract < 0 )
82 nFract *= -1;
83 if ( nFract < 10 )
84 sMetric += "0";
85 sMetric += OUString::number(nFract);
86 }
87
88 return sMetric;
89}
90
91
93
94namespace {
95
96class FunctionPopup_Impl
97{
98 std::unique_ptr<weld::Builder> m_xBuilder;
99 std::unique_ptr<weld::Menu> m_xMenu;
100 sal_uInt32 m_nSelected;
101 static sal_uInt16 id_to_function(std::string_view rIdent);
102 static OString function_to_id(sal_uInt16 nFunc);
103public:
104 explicit FunctionPopup_Impl(sal_uInt32 nCheckEncoded);
105 OString Execute(weld::Window* pParent, const tools::Rectangle& rRect)
106 {
107 return m_xMenu->popup_at_rect(pParent, rRect);
108 }
109 sal_uInt32 GetSelected(std::string_view curident) const;
110};
111
112}
113
114sal_uInt16 FunctionPopup_Impl::id_to_function(std::string_view 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
135OString FunctionPopup_Impl::function_to_id(sal_uInt16 nFunc)
136{
137 switch (nFunc)
138 {
139 case PSZ_FUNC_AVG:
140 return "avg";
141 case PSZ_FUNC_COUNT2:
142 return "counta";
143 case PSZ_FUNC_COUNT:
144 return "count";
145 case PSZ_FUNC_MAX:
146 return "max";
147 case PSZ_FUNC_MIN:
148 return "min";
149 case PSZ_FUNC_SUM:
150 return "sum";
152 return "selection";
153 case PSZ_FUNC_NONE:
154 return "none";
155 }
156 return OString();
157}
158
159FunctionPopup_Impl::FunctionPopup_Impl(sal_uInt32 nCheckEncoded)
160 : m_xBuilder(Application::CreateBuilder(nullptr, "svx/ui/functionmenu.ui"))
161 , m_xMenu(m_xBuilder->weld_menu("menu"))
162 , m_nSelected(nCheckEncoded)
163{
164 for ( sal_uInt16 nCheck = 1; nCheck < 32; ++nCheck )
165 if ( nCheckEncoded & (1u << nCheck) )
166 m_xMenu->set_active(function_to_id(nCheck), true);
167}
168
169sal_uInt32 FunctionPopup_Impl::GetSelected(std::string_view curident) const
170{
171 sal_uInt32 nSelected = m_nSelected;
172 sal_uInt16 nCurItemId = id_to_function(curident);
173 if ( nCurItemId == PSZ_FUNC_NONE )
174 nSelected = ( 1 << PSZ_FUNC_NONE );
175 else
176 {
177 nSelected &= (~( 1u << PSZ_FUNC_NONE )); // Clear the "None" bit
178 nSelected ^= ( 1u << nCurItemId ); // Toggle the bit corresponding to nCurItemId
179 if ( !nSelected )
180 nSelected = ( 1u << 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 tools::Rectangle aRect(rCEvt.GetMousePosPixel(), Size(1,1));
360 FunctionPopup_Impl aMenu(nSelect);
361 OString sIdent = aMenu.Execute(pParent, aRect);
362 if (!sIdent.isEmpty())
363 {
364 nSelect = aMenu.GetSelected(sIdent);
365 if (nSelect)
366 {
367 if (nSelect == (1 << PSZ_FUNC_NONE))
368 nSelect = 0;
369
370 css::uno::Any a;
371 SfxUInt32Item aItem( SID_PSZ_FUNCTION, nSelect );
372 aItem.QueryValue( a );
373 css::uno::Sequence< css::beans::PropertyValue > aArgs{ comphelper::makePropertyValue(
374 "StatusBarFunc", a) };
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 tools::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: */
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
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 SetHelpId(sal_uInt16 nItemId, const OString &rHelpId)
void SetItemText(sal_uInt16 nItemId, const OUString &rText, int nCharsWidth=-1)
void SetHelpText(sal_uInt16 nItemId, const OUString &rText)
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:268
virtual ~SvxPosSizeStatusBarControl() override
Definition: pszctrl.cxx:248
SvxPosSizeStatusBarControl(sal_uInt16 nSlotId, sal_uInt16 nId, StatusBar &rStb)
Definition: pszctrl.cxx:221
std::unique_ptr< SvxPosSizeStatusBarControl_Impl > pImpl
Definition: pszctrl.hxx:31
virtual void Command(const CommandEvent &rCEvt) override
Definition: pszctrl.cxx:351
virtual void Paint(const UserDrawEvent &rEvt) override
Definition: pszctrl.cxx:390
SVX_DLLPRIVATE OUString GetMetricStr_Impl(tools::Long nVal) const
Definition: pszctrl.cxx:63
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 Left() const
constexpr tools::Long Bottom() const
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:217
#define STR_TABLECELL
Definition: pszctrl.cxx:218
SFX_IMPL_STATUSBAR_CONTROL(SvxPosSizeStatusBarControl, SvxSizeItem)
#define PAINT_OFFSET
Definition: pszctrl.cxx:40
#define STR_FUNC
Definition: pszctrl.cxx:219
#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