bump product version to 7.2.5.1
[LibreOffice.git] / svx / source / stbctrls / pszctrl.cxx
blobe3539a5e7c5b0ae7420be5860fa6956ffd5c6810
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <vcl/commandevent.hxx>
21 #include <vcl/event.hxx>
22 #include <vcl/fieldvalues.hxx>
23 #include <vcl/status.hxx>
24 #include <vcl/image.hxx>
25 #include <vcl/settings.hxx>
26 #include <vcl/svapp.hxx>
27 #include <vcl/weld.hxx>
28 #include <vcl/weldutils.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>
35 #include <svx/pszctrl.hxx>
37 #define PAINT_OFFSET 5
39 #include <editeng/sizeitem.hxx>
40 #include "stbctrls.h"
42 #include <svx/svxids.hrc>
43 #include <bitmaps.hlst>
44 #include <unotools/localedatawrapper.hxx>
46 #include <com/sun/star/beans/PropertyValue.hpp>
48 /* [Description]
50 Function used to create a text representation of
51 a metric value
53 nVal is the metric value in the unit eUnit.
55 [cross reference]
57 <SvxPosSizeStatusBarControl::Paint(const UserDrawEvent&)>
60 OUString SvxPosSizeStatusBarControl::GetMetricStr_Impl( tools::Long nVal )
62 // deliver and set the Metric of the application
63 FieldUnit eOutUnit = SfxModule::GetModuleFieldUnit( getFrameInterface() );
65 OUString sMetric;
66 const sal_Unicode cSep = Application::GetSettings().GetLocaleDataWrapper().getNumDecimalSep()[0];
67 sal_Int64 nConvVal = vcl::ConvertValue( nVal * 100, 0, 0, FieldUnit::MM_100TH, eOutUnit );
69 if ( nConvVal < 0 && ( nConvVal / 100 == 0 ) )
70 sMetric += "-";
71 sMetric += OUString::number(nConvVal / 100);
73 if( FieldUnit::NONE != eOutUnit )
75 sMetric += OUStringChar(cSep);
76 sal_Int64 nFract = nConvVal % 100;
78 if ( nFract < 0 )
79 nFract *= -1;
80 if ( nFract < 10 )
81 sMetric += "0";
82 sMetric += OUString::number(nFract);
85 return sMetric;
89 SFX_IMPL_STATUSBAR_CONTROL(SvxPosSizeStatusBarControl, SvxSizeItem);
91 namespace {
93 class FunctionPopup_Impl
95 std::unique_ptr<weld::Builder> m_xBuilder;
96 std::unique_ptr<weld::Menu> m_xMenu;
97 sal_uInt32 m_nSelected;
98 static sal_uInt16 id_to_function(std::string_view rIdent);
99 static OString function_to_id(sal_uInt16 nFunc);
100 public:
101 explicit FunctionPopup_Impl(sal_uInt32 nCheckEncoded);
102 OString Execute(weld::Window* pParent, const tools::Rectangle& rRect)
104 return m_xMenu->popup_at_rect(pParent, rRect);
106 sal_uInt32 GetSelected(std::string_view curident) const;
111 sal_uInt16 FunctionPopup_Impl::id_to_function(std::string_view rIdent)
113 if (rIdent == "avg")
114 return PSZ_FUNC_AVG;
115 else if (rIdent == "counta")
116 return PSZ_FUNC_COUNT2;
117 else if (rIdent == "count")
118 return PSZ_FUNC_COUNT;
119 else if (rIdent == "max")
120 return PSZ_FUNC_MAX;
121 else if (rIdent == "min")
122 return PSZ_FUNC_MIN;
123 else if (rIdent == "sum")
124 return PSZ_FUNC_SUM;
125 else if (rIdent == "selection")
126 return PSZ_FUNC_SELECTION_COUNT;
127 else if (rIdent == "none")
128 return PSZ_FUNC_NONE;
129 return 0;
132 OString FunctionPopup_Impl::function_to_id(sal_uInt16 nFunc)
134 switch (nFunc)
136 case PSZ_FUNC_AVG:
137 return "avg";
138 case PSZ_FUNC_COUNT2:
139 return "counta";
140 case PSZ_FUNC_COUNT:
141 return "count";
142 case PSZ_FUNC_MAX:
143 return "max";
144 case PSZ_FUNC_MIN:
145 return "min";
146 case PSZ_FUNC_SUM:
147 return "sum";
148 case PSZ_FUNC_SELECTION_COUNT:
149 return "selection";
150 case PSZ_FUNC_NONE:
151 return "none";
153 return OString();
156 FunctionPopup_Impl::FunctionPopup_Impl(sal_uInt32 nCheckEncoded)
157 : m_xBuilder(Application::CreateBuilder(nullptr, "svx/ui/functionmenu.ui"))
158 , m_xMenu(m_xBuilder->weld_menu("menu"))
159 , m_nSelected(nCheckEncoded)
161 for ( sal_uInt16 nCheck = 1; nCheck < 32; ++nCheck )
162 if ( nCheckEncoded & (1 << nCheck) )
163 m_xMenu->set_active(function_to_id(nCheck), true);
166 sal_uInt32 FunctionPopup_Impl::GetSelected(std::string_view curident) const
168 sal_uInt32 nSelected = m_nSelected;
169 sal_uInt16 nCurItemId = id_to_function(curident);
170 if ( nCurItemId == PSZ_FUNC_NONE )
171 nSelected = ( 1 << PSZ_FUNC_NONE );
172 else
174 nSelected &= (~( 1 << PSZ_FUNC_NONE )); // Clear the "None" bit
175 nSelected ^= ( 1 << nCurItemId ); // Toggle the bit corresponding to nCurItemId
176 if ( !nSelected )
177 nSelected = ( 1 << PSZ_FUNC_NONE );
179 return nSelected;
182 struct SvxPosSizeStatusBarControl_Impl
184 /* [Description]
186 This implementation-structure of the class SvxPosSizeStatusBarControl
187 is done for the un-linking of the changes of the exported interface such as
188 the toning down of symbols that are visible externally.
190 One instance exists for each SvxPosSizeStatusBarControl-instance
191 during its life time
195 Point aPos; // valid when a position is shown
196 Size aSize; // valid when a size is shown
197 OUString aStr; // valid when a text is shown
198 bool bPos; // show position ?
199 bool bSize; // set size ?
200 bool bTable; // set table index ?
201 bool bHasMenu; // set StarCalc popup menu ?
202 sal_uInt32 nFunctionSet; // the selected StarCalc functions encoded in 32 bits
203 Image aPosImage; // Image to show the position
204 Image aSizeImage; // Image to show the size
207 /* [Description]
209 Ctor():
210 Create an instance of the implementation class,
211 load the images for the position and size
214 #define STR_POSITION ".uno:Position"
215 #define STR_TABLECELL ".uno:StateTableCell"
216 #define STR_FUNC ".uno:StatusBarFunc"
218 SvxPosSizeStatusBarControl::SvxPosSizeStatusBarControl( sal_uInt16 _nSlotId,
219 sal_uInt16 _nId,
220 StatusBar& rStb ) :
221 SfxStatusBarControl( _nSlotId, _nId, rStb ),
222 pImpl( new SvxPosSizeStatusBarControl_Impl )
224 pImpl->bPos = false;
225 pImpl->bSize = false;
226 pImpl->bTable = false;
227 pImpl->bHasMenu = false;
228 pImpl->nFunctionSet = 0;
229 pImpl->aPosImage = Image(StockImage::Yes, RID_SVXBMP_POSITION);
230 pImpl->aSizeImage = Image(StockImage::Yes, RID_SVXBMP_SIZE);
232 addStatusListener( STR_POSITION); // SID_ATTR_POSITION
233 addStatusListener( STR_TABLECELL); // SID_TABLE_CELL
234 addStatusListener( STR_FUNC); // SID_PSZ_FUNCTION
235 ImplUpdateItemText();
238 /* [Description]
240 Dtor():
241 remove the pointer to the implementation class, so that the timer is stopped
245 SvxPosSizeStatusBarControl::~SvxPosSizeStatusBarControl()
250 /* [Description]
252 SID_PSZ_FUNCTION activates the popup menu for Calc:
254 Status overview
255 Depending on the type of the item, a special setting is enabled, the others disabled.
257 NULL/Void SfxPointItem SvxSizeItem SfxStringItem
258 ------------------------------------------------------------------------
259 Position sal_False FALSE
260 Size FALSE TRUE FALSE
261 Text sal_False sal_False TRUE
265 void SvxPosSizeStatusBarControl::StateChanged( sal_uInt16 nSID, SfxItemState eState,
266 const SfxPoolItem* pState )
268 // Because the combi-controller, always sets the current Id as HelpId
269 // first clean the cached HelpText
270 GetStatusBar().SetHelpText( GetId(), "" );
272 switch ( nSID )
274 case SID_ATTR_POSITION : GetStatusBar().SetHelpId( GetId(), STR_POSITION ); break;
275 case SID_TABLE_CELL: GetStatusBar().SetHelpId( GetId(), STR_TABLECELL ); break;
276 case SID_PSZ_FUNCTION: GetStatusBar().SetHelpId( GetId(), STR_FUNC ); break;
277 default: break;
280 if ( nSID == SID_PSZ_FUNCTION )
282 if ( eState == SfxItemState::DEFAULT )
284 pImpl->bHasMenu = true;
285 if ( auto pUInt32Item = dynamic_cast< const SfxUInt32Item* >(pState) )
286 pImpl->nFunctionSet = pUInt32Item->GetValue();
288 else
289 pImpl->bHasMenu = false;
291 else if ( SfxItemState::DEFAULT != eState )
293 // don't switch to empty display before an empty state was
294 // notified for all display types
296 if ( nSID == SID_TABLE_CELL )
297 pImpl->bTable = false;
298 else if ( nSID == SID_ATTR_POSITION )
299 pImpl->bPos = false;
300 else if ( nSID == GetSlotId() ) // controller is registered for SID_ATTR_SIZE
301 pImpl->bSize = false;
302 else
304 SAL_WARN( "svx.stbcrtls","unknown slot id");
307 else if ( auto pPointItem = dynamic_cast<const SfxPointItem*>( pState) )
309 // show position
310 pImpl->aPos = pPointItem->GetValue();
311 pImpl->bPos = true;
312 pImpl->bTable = false;
314 else if ( auto pSizeItem = dynamic_cast<const SvxSizeItem*>( pState) )
316 // show size
317 pImpl->aSize = pSizeItem->GetSize();
318 pImpl->bSize = true;
319 pImpl->bTable = false;
321 else if ( auto pStringItem = dynamic_cast<const SfxStringItem*>( pState) )
323 // show string (table cel or different)
324 pImpl->aStr = pStringItem->GetValue();
325 pImpl->bTable = true;
326 pImpl->bPos = false;
327 pImpl->bSize = false;
329 else
331 SAL_WARN( "svx.stbcrtls", "invalid item type" );
332 pImpl->bPos = false;
333 pImpl->bSize = false;
334 pImpl->bTable = false;
337 GetStatusBar().SetItemData( GetId(), nullptr );
339 ImplUpdateItemText();
343 /* [Description]
345 execute popup menu, when the status enables this
348 void SvxPosSizeStatusBarControl::Command( const CommandEvent& rCEvt )
350 if ( rCEvt.GetCommand() == CommandEventId::ContextMenu && pImpl->bHasMenu )
352 sal_uInt32 nSelect = pImpl->nFunctionSet;
353 if (!nSelect)
354 nSelect = ( 1 << PSZ_FUNC_NONE );
355 tools::Rectangle aRect(rCEvt.GetMousePosPixel(), Size(1,1));
356 weld::Window* pParent = weld::GetPopupParent(GetStatusBar(), aRect);
357 FunctionPopup_Impl aMenu(nSelect);
358 OString sIdent = aMenu.Execute(pParent, aRect);
359 if (!sIdent.isEmpty())
361 nSelect = aMenu.GetSelected(sIdent);
362 if (nSelect)
364 if (nSelect == (1 << PSZ_FUNC_NONE))
365 nSelect = 0;
367 css::uno::Any a;
368 SfxUInt32Item aItem( SID_PSZ_FUNCTION, nSelect );
370 css::uno::Sequence< css::beans::PropertyValue > aArgs( 1 );
371 aArgs[0].Name = "StatusBarFunc";
372 aItem.QueryValue( a );
373 aArgs[0].Value = a;
375 execute( ".uno:StatusBarFunc", aArgs );
379 else
380 SfxStatusBarControl::Command( rCEvt );
384 /* [Description]
386 Depending on the type to be shown, the value us shown. First the
387 rectangle is repainted (removed).
390 void SvxPosSizeStatusBarControl::Paint( const UserDrawEvent& rUsrEvt )
392 vcl::RenderContext* pDev = rUsrEvt.GetRenderContext();
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() );
402 if ( pImpl->bPos || pImpl->bSize )
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);
423 // draw the size, when available
424 aPnt.setX( nSizePosX );
426 if ( pImpl->bSize )
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);
441 else
442 pDev->DrawRect( tools::Rectangle( aPnt, rRect.BottomRight() ) );
444 else if ( pImpl->bTable )
446 pDev->DrawRect( rRect );
447 pDev->DrawText( Point(
448 rRect.Left() + rRect.GetWidth() / 2 - pDev->GetTextWidth( pImpl->aStr ) / 2,
449 aItemPos.Y() ), pImpl->aStr );
451 else
453 // Empty display if neither size nor table position are available.
454 // Date/Time are no longer used (#65302#).
455 pDev->DrawRect( rRect );
458 pDev->SetLineColor( aOldLineColor );
459 pDev->SetFillColor( aOldFillColor );
462 void SvxPosSizeStatusBarControl::ImplUpdateItemText()
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 )
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 )
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
481 else if ( pImpl->bTable )
482 aText = pImpl->aStr;
484 GetStatusBar().SetItemText( GetId(), aText, nCharsWidth );
486 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */