Bump version to 6.4-15
[LibreOffice.git] / svx / source / stbctrls / pszctrl.cxx
blobc79a778459a253259cdf337a1ae6d501e682be69
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 <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>
40 #include <svx/pszctrl.hxx>
42 #define PAINT_OFFSET 5
44 #include <editeng/sizeitem.hxx>
45 #include <svx/dlgutil.hxx>
46 #include "stbctrls.h"
48 #include <svx/svxids.hrc>
49 #include <bitmaps.hlst>
50 #include <unotools/localedatawrapper.hxx>
52 #include <com/sun/star/beans/PropertyValue.hpp>
54 /* [Description]
56 Function used to create a text representation of
57 a metric value
59 nVal is the metric value in the unit eUnit.
61 [cross reference]
63 <SvxPosSizeStatusBarControl::Paint(const UserDrawEvent&)>
66 OUString SvxPosSizeStatusBarControl::GetMetricStr_Impl( long nVal )
68 // deliver and set the Metric of the application
69 FieldUnit eOutUnit = SfxModule::GetModuleFieldUnit( getFrameInterface() );
71 OUString sMetric;
72 const sal_Unicode cSep = Application::GetSettings().GetLocaleDataWrapper().getNumDecimalSep()[0];
73 sal_Int64 nConvVal = MetricField::ConvertValue( nVal * 100, 0L, 0, FieldUnit::MM_100TH, eOutUnit );
75 if ( nConvVal < 0 && ( nConvVal / 100 == 0 ) )
76 sMetric += "-";
77 sMetric += OUString::number(nConvVal / 100);
79 if( FieldUnit::NONE != eOutUnit )
81 sMetric += OUStringChar(cSep);
82 sal_Int64 nFract = nConvVal % 100;
84 if ( nFract < 0 )
85 nFract *= -1;
86 if ( nFract < 10 )
87 sMetric += "0";
88 sMetric += OUString::number(nFract);
91 return sMetric;
95 SFX_IMPL_STATUSBAR_CONTROL(SvxPosSizeStatusBarControl, SvxSizeItem);
97 class FunctionPopup_Impl
99 VclBuilder m_aBuilder;
100 VclPtr<PopupMenu> m_xMenu;
101 sal_uInt32 const m_nSelected;
102 static sal_uInt16 id_to_function(const OString& rIdent);
103 sal_uInt16 function_to_id(sal_uInt16 nFunc) const;
104 public:
105 explicit FunctionPopup_Impl( sal_uInt32 nCheckEncoded );
106 sal_uInt16 Execute(vcl::Window* pWindow, const Point& rPopupPos) { return m_xMenu->Execute(pWindow, rPopupPos); }
107 sal_uInt32 GetSelected() const;
110 sal_uInt16 FunctionPopup_Impl::id_to_function(const OString& rIdent)
112 if (rIdent == "avg")
113 return PSZ_FUNC_AVG;
114 else if (rIdent == "counta")
115 return PSZ_FUNC_COUNT2;
116 else if (rIdent == "count")
117 return PSZ_FUNC_COUNT;
118 else if (rIdent == "max")
119 return PSZ_FUNC_MAX;
120 else if (rIdent == "min")
121 return PSZ_FUNC_MIN;
122 else if (rIdent == "sum")
123 return PSZ_FUNC_SUM;
124 else if (rIdent == "selection")
125 return PSZ_FUNC_SELECTION_COUNT;
126 else if (rIdent == "none")
127 return PSZ_FUNC_NONE;
128 return 0;
131 sal_uInt16 FunctionPopup_Impl::function_to_id(sal_uInt16 nFunc) const
133 switch (nFunc)
135 case PSZ_FUNC_AVG:
136 return m_xMenu->GetItemId("avg");
137 case PSZ_FUNC_COUNT2:
138 return m_xMenu->GetItemId("counta");
139 case PSZ_FUNC_COUNT:
140 return m_xMenu->GetItemId("count");
141 case PSZ_FUNC_MAX:
142 return m_xMenu->GetItemId("max");
143 case PSZ_FUNC_MIN:
144 return m_xMenu->GetItemId("min");
145 case PSZ_FUNC_SUM:
146 return m_xMenu->GetItemId("sum");
147 case PSZ_FUNC_SELECTION_COUNT:
148 return m_xMenu->GetItemId("selection");
149 case PSZ_FUNC_NONE:
150 return m_xMenu->GetItemId("none");
152 return 0;
155 FunctionPopup_Impl::FunctionPopup_Impl(sal_uInt32 nCheckEncoded)
156 : m_aBuilder(nullptr, VclBuilderContainer::getUIRootDir(), "svx/ui/functionmenu.ui", "")
157 , m_xMenu(m_aBuilder.get_menu("menu"))
158 , m_nSelected(nCheckEncoded)
160 for ( sal_uInt16 nCheck = 1; nCheck < 32; ++nCheck )
161 if ( nCheckEncoded & (1 << nCheck) )
162 m_xMenu->CheckItem(function_to_id(nCheck));
165 sal_uInt32 FunctionPopup_Impl::GetSelected() const
167 sal_uInt32 nSelected = m_nSelected;
168 sal_uInt16 nCurItemId = id_to_function(m_xMenu->GetCurItemIdent());
169 if ( nCurItemId == PSZ_FUNC_NONE )
170 nSelected = ( 1 << PSZ_FUNC_NONE );
171 else
173 nSelected &= (~( 1 << PSZ_FUNC_NONE )); // Clear the "None" bit
174 nSelected ^= ( 1 << nCurItemId ); // Toggle the bit corresponding to nCurItemId
175 if ( !nSelected )
176 nSelected = ( 1 << PSZ_FUNC_NONE );
178 return nSelected;
181 struct SvxPosSizeStatusBarControl_Impl
183 /* [Description]
185 This implementation-structure of the class SvxPosSizeStatusBarControl
186 is done for the un-linking of the changes of the exported interface such as
187 the toning down of symbols that are visible externally.
189 One instance exists for each SvxPosSizeStatusBarControl-instance
190 during its life time
194 Point aPos; // valid when a position is shown
195 Size aSize; // valid when a size is shown
196 OUString aStr; // valid when a text is shown
197 bool bPos; // show position ?
198 bool bSize; // set size ?
199 bool bTable; // set table index ?
200 bool bHasMenu; // set StarCalc popup menu ?
201 sal_uInt32 nFunctionSet; // the selected StarCalc functions encoded in 32 bits
202 Image aPosImage; // Image to show the position
203 Image aSizeImage; // Image to show the size
206 /* [Description]
208 Ctor():
209 Create an instance of the implementation class,
210 load the images for the position and size
213 #define STR_POSITION ".uno:Position"
214 #define STR_TABLECELL ".uno:StateTableCell"
215 #define STR_FUNC ".uno:StatusBarFunc"
217 SvxPosSizeStatusBarControl::SvxPosSizeStatusBarControl( sal_uInt16 _nSlotId,
218 sal_uInt16 _nId,
219 StatusBar& rStb ) :
220 SfxStatusBarControl( _nSlotId, _nId, rStb ),
221 pImpl( new SvxPosSizeStatusBarControl_Impl )
223 pImpl->bPos = false;
224 pImpl->bSize = false;
225 pImpl->bTable = false;
226 pImpl->bHasMenu = false;
227 pImpl->nFunctionSet = 0;
228 pImpl->aPosImage = Image(StockImage::Yes, RID_SVXBMP_POSITION);
229 pImpl->aSizeImage = Image(StockImage::Yes, RID_SVXBMP_SIZE);
231 addStatusListener( STR_POSITION); // SID_ATTR_POSITION
232 addStatusListener( STR_TABLECELL); // SID_TABLE_CELL
233 addStatusListener( STR_FUNC); // SID_PSZ_FUNCTION
234 ImplUpdateItemText();
237 /* [Description]
239 Dtor():
240 remove the pointer to the implementation class, so that the timer is stopped
244 SvxPosSizeStatusBarControl::~SvxPosSizeStatusBarControl()
249 /* [Description]
251 SID_PSZ_FUNCTION activates the popup menu for Calc:
253 Status overview
254 Depending on the type of the item, a special setting is enabled, the others disabled.
256 NULL/Void SfxPointItem SvxSizeItem SfxStringItem
257 ------------------------------------------------------------------------
258 Position sal_False FALSE
259 Size FALSE TRUE FALSE
260 Text sal_False sal_False TRUE
264 void SvxPosSizeStatusBarControl::StateChanged( sal_uInt16 nSID, SfxItemState eState,
265 const SfxPoolItem* pState )
267 // Because the combi-controller, always sets the current Id as HelpId
268 // first clean the cached HelpText
269 GetStatusBar().SetHelpText( GetId(), "" );
271 switch ( nSID )
273 case SID_ATTR_POSITION : GetStatusBar().SetHelpId( GetId(), STR_POSITION ); break;
274 case SID_TABLE_CELL: GetStatusBar().SetHelpId( GetId(), STR_TABLECELL ); break;
275 case SID_PSZ_FUNCTION: GetStatusBar().SetHelpId( GetId(), STR_FUNC ); break;
276 default: break;
279 if ( nSID == SID_PSZ_FUNCTION )
281 if ( eState == SfxItemState::DEFAULT )
283 pImpl->bHasMenu = true;
284 if ( auto pUInt32Item = dynamic_cast< const SfxUInt32Item* >(pState) )
285 pImpl->nFunctionSet = pUInt32Item->GetValue();
287 else
288 pImpl->bHasMenu = false;
290 else if ( SfxItemState::DEFAULT != eState )
292 // don't switch to empty display before an empty state was
293 // notified for all display types
295 if ( nSID == SID_TABLE_CELL )
296 pImpl->bTable = false;
297 else if ( nSID == SID_ATTR_POSITION )
298 pImpl->bPos = false;
299 else if ( nSID == GetSlotId() ) // controller is registered for SID_ATTR_SIZE
300 pImpl->bSize = false;
301 else
303 SAL_WARN( "svx.stbcrtls","unknown slot id");
306 else if ( auto pPointItem = dynamic_cast<const SfxPointItem*>( pState) )
308 // show position
309 pImpl->aPos = pPointItem->GetValue();
310 pImpl->bPos = true;
311 pImpl->bTable = false;
313 else if ( auto pSizeItem = dynamic_cast<const SvxSizeItem*>( pState) )
315 // show size
316 pImpl->aSize = pSizeItem->GetSize();
317 pImpl->bSize = true;
318 pImpl->bTable = false;
320 else if ( auto pStringItem = dynamic_cast<const SfxStringItem*>( pState) )
322 // show string (table cel or different)
323 pImpl->aStr = pStringItem->GetValue();
324 pImpl->bTable = true;
325 pImpl->bPos = false;
326 pImpl->bSize = false;
328 else
330 SAL_WARN( "svx.stbcrtls", "invalid item type" );
331 pImpl->bPos = false;
332 pImpl->bSize = false;
333 pImpl->bTable = false;
336 GetStatusBar().SetItemData( GetId(), nullptr );
338 ImplUpdateItemText();
342 /* [Description]
344 execute popup menu, when the status enables this
347 void SvxPosSizeStatusBarControl::Command( const CommandEvent& rCEvt )
349 if ( rCEvt.GetCommand() == CommandEventId::ContextMenu && pImpl->bHasMenu )
351 sal_uInt32 nSelect = pImpl->nFunctionSet;
352 if (!nSelect)
353 nSelect = ( 1 << PSZ_FUNC_NONE );
354 FunctionPopup_Impl aMenu(nSelect);
355 if (aMenu.Execute(&GetStatusBar(), rCEvt.GetMousePosPixel()))
357 nSelect = aMenu.GetSelected();
358 if (nSelect)
360 if (nSelect == (1 << PSZ_FUNC_NONE))
361 nSelect = 0;
363 css::uno::Any a;
364 SfxUInt32Item aItem( SID_PSZ_FUNCTION, nSelect );
366 css::uno::Sequence< css::beans::PropertyValue > aArgs( 1 );
367 aArgs[0].Name = "StatusBarFunc";
368 aItem.QueryValue( a );
369 aArgs[0].Value = a;
371 execute( ".uno:StatusBarFunc", aArgs );
375 else
376 SfxStatusBarControl::Command( rCEvt );
380 /* [Description]
382 Depending on the type to be shown, the value us shown. First the
383 rectangle is repainted (removed).
386 void SvxPosSizeStatusBarControl::Paint( const UserDrawEvent& rUsrEvt )
388 vcl::RenderContext* pDev = rUsrEvt.GetRenderContext();
390 const tools::Rectangle& rRect = rUsrEvt.GetRect();
391 StatusBar& rBar = GetStatusBar();
392 Point aItemPos = rBar.GetItemTextPos( GetId() );
393 Color aOldLineColor = pDev->GetLineColor();
394 Color aOldFillColor = pDev->GetFillColor();
395 pDev->SetLineColor();
396 pDev->SetFillColor( pDev->GetBackground().GetColor() );
398 if ( pImpl->bPos || pImpl->bSize )
400 // count the position for showing the size
401 long nSizePosX =
402 rRect.Left() + rRect.GetWidth() / 2 + PAINT_OFFSET;
403 // draw position
404 Point aPnt = rRect.TopLeft();
405 aPnt.setY( aItemPos.Y() );
406 aPnt.AdjustX(PAINT_OFFSET );
407 pDev->DrawImage( aPnt, pImpl->aPosImage );
408 aPnt.AdjustX(pImpl->aPosImage.GetSizePixel().Width() );
409 aPnt.AdjustX(PAINT_OFFSET );
410 OUString aStr = GetMetricStr_Impl( pImpl->aPos.X()) + " / " +
411 GetMetricStr_Impl( pImpl->aPos.Y());
412 tools::Rectangle aRect(aPnt, Point(nSizePosX, rRect.Bottom()));
413 pDev->DrawRect(aRect);
414 vcl::Region aOrigRegion(pDev->GetClipRegion());
415 pDev->SetClipRegion(vcl::Region(aRect));
416 pDev->DrawText(aPnt, aStr);
417 pDev->SetClipRegion(aOrigRegion);
419 // draw the size, when available
420 aPnt.setX( nSizePosX );
422 if ( pImpl->bSize )
424 pDev->DrawImage( aPnt, pImpl->aSizeImage );
425 aPnt.AdjustX(pImpl->aSizeImage.GetSizePixel().Width() );
426 Point aDrwPnt = aPnt;
427 aPnt.AdjustX(PAINT_OFFSET );
428 aStr = GetMetricStr_Impl( pImpl->aSize.Width() ) + " x " +
429 GetMetricStr_Impl( pImpl->aSize.Height() );
430 aRect = tools::Rectangle(aDrwPnt, rRect.BottomRight());
431 pDev->DrawRect(aRect);
432 aOrigRegion = pDev->GetClipRegion();
433 pDev->SetClipRegion(vcl::Region(aRect));
434 pDev->DrawText(aPnt, aStr);
435 pDev->SetClipRegion(aOrigRegion);
437 else
438 pDev->DrawRect( tools::Rectangle( aPnt, rRect.BottomRight() ) );
440 else if ( pImpl->bTable )
442 pDev->DrawRect( rRect );
443 pDev->DrawText( Point(
444 rRect.Left() + rRect.GetWidth() / 2 - pDev->GetTextWidth( pImpl->aStr ) / 2,
445 aItemPos.Y() ), pImpl->aStr );
447 else
449 // Empty display if neither size nor table position are available.
450 // Date/Time are no longer used (#65302#).
451 pDev->DrawRect( rRect );
454 pDev->SetLineColor( aOldLineColor );
455 pDev->SetFillColor( aOldFillColor );
458 void SvxPosSizeStatusBarControl::ImplUpdateItemText()
460 // set only strings as text at the statusBar, so that the Help-Tips
461 // can work with the text, when it is too long for the statusBar
462 OUString aText;
463 int nCharsWidth = -1;
464 if ( pImpl->bPos || pImpl->bSize )
466 aText = GetMetricStr_Impl( pImpl->aPos.X()) + " / " +
467 GetMetricStr_Impl( pImpl->aPos.Y());
468 // widest X/Y string looks like "-999,99"
469 nCharsWidth = 1 + 6 + 3 + 6; // icon + x + slash + y
470 if ( pImpl->bSize )
472 aText += " " + GetMetricStr_Impl( pImpl->aSize.Width() ) + " x " +
473 GetMetricStr_Impl( pImpl->aSize.Height() );
474 nCharsWidth += 1 + 1 + 4 + 3 + 4; // icon + space + w + x + h
477 else if ( pImpl->bTable )
478 aText = pImpl->aStr;
480 GetStatusBar().SetItemText( GetId(), aText, nCharsWidth );
482 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */