Line data Source code
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/status.hxx>
22 : #include <vcl/menu.hxx>
23 : #include <vcl/image.hxx>
24 : #include <vcl/settings.hxx>
25 : #include <svl/stritem.hxx>
26 : #include <svl/ptitem.hxx>
27 : #include <svl/itempool.hxx>
28 : #include <sfx2/app.hxx>
29 : #include <sfx2/module.hxx>
30 : #include <sfx2/dispatch.hxx>
31 : #include <sfx2/objsh.hxx>
32 : #include <svl/intitem.hxx>
33 :
34 : #include "svx/pszctrl.hxx"
35 :
36 : #define PAINT_OFFSET 5
37 :
38 : #include <editeng/sizeitem.hxx>
39 : #include <svx/dialmgr.hxx>
40 : #include "svx/dlgutil.hxx"
41 : #include "stbctrls.h"
42 :
43 : #include <svx/dialogs.hrc>
44 : #include <unotools/localedatawrapper.hxx>
45 : #include <comphelper/processfactory.hxx>
46 :
47 :
48 :
49 : /* [Description]
50 :
51 : Function used to create a text representation of
52 : a metric value
53 :
54 : nVal is the metric value in the unit eUnit.
55 :
56 : [cross reference]
57 :
58 : <SvxPosSizeStatusBarControl::Paint(const UserDrawEvent&)>
59 : */
60 :
61 972 : OUString SvxPosSizeStatusBarControl::GetMetricStr_Impl( long nVal )
62 : {
63 : // deliver and set the Metric of the application
64 972 : FieldUnit eOutUnit = SfxModule::GetModuleFieldUnit( getFrameInterface() );
65 972 : FieldUnit eInUnit = FUNIT_100TH_MM;
66 :
67 972 : OUString sMetric;
68 972 : const sal_Unicode cSep = Application::GetSettings().GetLocaleDataWrapper().getNumDecimalSep()[0];
69 972 : sal_Int64 nConvVal = MetricField::ConvertValue( nVal * 100, 0L, 0, eInUnit, eOutUnit );
70 :
71 972 : if ( nConvVal < 0 && ( nConvVal / 100 == 0 ) )
72 341 : sMetric += "-";
73 972 : sMetric += OUString::number(nConvVal / 100);
74 :
75 972 : if( FUNIT_NONE != eOutUnit )
76 : {
77 972 : sMetric += OUString(cSep);
78 972 : sal_Int64 nFract = nConvVal % 100;
79 :
80 972 : if ( nFract < 0 )
81 458 : nFract *= -1;
82 972 : if ( nFract < 10 )
83 514 : sMetric += "0";
84 972 : sMetric += OUString::number(nFract);
85 : }
86 :
87 972 : return sMetric;
88 : }
89 :
90 :
91 :
92 703 : SFX_IMPL_STATUSBAR_CONTROL(SvxPosSizeStatusBarControl, SvxSizeItem);
93 :
94 0 : class FunctionPopup_Impl : public PopupMenu
95 : {
96 : public:
97 : explicit FunctionPopup_Impl( sal_uInt16 nCheck );
98 :
99 0 : sal_uInt16 GetSelected() const { return nSelected; }
100 :
101 : private:
102 : sal_uInt16 nSelected;
103 :
104 : virtual void Select() SAL_OVERRIDE;
105 : };
106 :
107 :
108 :
109 0 : FunctionPopup_Impl::FunctionPopup_Impl( sal_uInt16 nCheck ) :
110 0 : PopupMenu( ResId( RID_SVXMNU_PSZ_FUNC, DIALOG_MGR() ) ),
111 0 : nSelected( 0 )
112 : {
113 0 : if (nCheck)
114 0 : CheckItem( nCheck );
115 0 : }
116 :
117 :
118 :
119 0 : void FunctionPopup_Impl::Select()
120 : {
121 0 : nSelected = GetCurItemId();
122 0 : }
123 :
124 1142 : struct SvxPosSizeStatusBarControl_Impl
125 :
126 : /* [Description]
127 :
128 : This implementation-structure of the class SvxPosSizeStatusBarControl
129 : is done for the un-linking of the changes of the exported interface such as
130 : the toning down of symbols that are visible externally.
131 :
132 : One instance exists for each SvxPosSizeStatusBarControl-instance
133 : during its life time
134 : */
135 :
136 : {
137 : Point aPos; // valid when a position is shown
138 : Size aSize; // valid when a size is shown
139 : OUString aStr; // valid when a text is shown
140 : bool bPos; // show position ?
141 : bool bSize; // set size ?
142 : bool bTable; // set table index ?
143 : bool bHasMenu; // set StarCalc popup menu ?
144 : sal_uInt16 nFunction; // the selected StarCalc function
145 : Image aPosImage; // Image to show the position
146 : Image aSizeImage; // Image to show the size
147 : };
148 :
149 : /* [Description]
150 :
151 : Ctor():
152 : Create an instance of the implementation class,
153 : load the images for the position and size
154 : */
155 :
156 : #define STR_POSITION ".uno:Position"
157 : #define STR_TABLECELL ".uno:StateTableCell"
158 : #define STR_FUNC ".uno:StatusBarFunc"
159 :
160 571 : SvxPosSizeStatusBarControl::SvxPosSizeStatusBarControl( sal_uInt16 _nSlotId,
161 : sal_uInt16 _nId,
162 : StatusBar& rStb ) :
163 : SfxStatusBarControl( _nSlotId, _nId, rStb ),
164 571 : pImp( new SvxPosSizeStatusBarControl_Impl )
165 : {
166 571 : pImp->bPos = false;
167 571 : pImp->bSize = false;
168 571 : pImp->bTable = false;
169 571 : pImp->bHasMenu = false;
170 571 : pImp->nFunction = 0;
171 571 : pImp->aPosImage = Image( ResId( RID_SVXBMP_POSITION, DIALOG_MGR() ) );
172 571 : pImp->aSizeImage = Image( ResId( RID_SVXBMP_SIZE, DIALOG_MGR() ) );
173 :
174 571 : if ( rStb.GetDPIScaleFactor() > 1)
175 : {
176 0 : BitmapEx b = pImp->aPosImage.GetBitmapEx();
177 0 : b.Scale(rStb.GetDPIScaleFactor(), rStb.GetDPIScaleFactor(), BmpScaleFlag::Fast);
178 0 : pImp->aPosImage = Image(b);
179 :
180 0 : b = pImp->aSizeImage.GetBitmapEx();
181 0 : b.Scale(rStb.GetDPIScaleFactor(), rStb.GetDPIScaleFactor(), BmpScaleFlag::Fast);
182 0 : pImp->aSizeImage = Image(b);
183 : }
184 :
185 571 : addStatusListener( OUString( STR_POSITION )); // SID_ATTR_POSITION
186 571 : addStatusListener( OUString( STR_TABLECELL )); // SID_TABLE_CELL
187 571 : addStatusListener( OUString( STR_FUNC )); // SID_PSZ_FUNCTION
188 571 : }
189 :
190 :
191 :
192 : /* [Description]
193 :
194 : Dtor():
195 : remove the pointer to the implementation class, so that the timer is stopped
196 :
197 : */
198 :
199 1713 : SvxPosSizeStatusBarControl::~SvxPosSizeStatusBarControl()
200 : {
201 571 : delete pImp;
202 1142 : }
203 :
204 :
205 :
206 : /* [Description]
207 :
208 : SID_PSZ_FUNCTION activates the popup menu for Calc:
209 :
210 : Status overview
211 : Depending on the type of the item, a special setting is enabled, the others disabled.
212 :
213 : NULL/Void SfxPointItem SvxSizeItem SfxStringItem
214 : ------------------------------------------------------------------------
215 : Position sal_False FALSE
216 : Size FALSE TRUE FALSE
217 : Text sal_False sal_False TRUE
218 :
219 : */
220 :
221 2839 : void SvxPosSizeStatusBarControl::StateChanged( sal_uInt16 nSID, SfxItemState eState,
222 : const SfxPoolItem* pState )
223 : {
224 : // Because the combi-controller, always sets the current Id as HelpId
225 : // first clean the cached HelpText
226 2839 : GetStatusBar().SetHelpText( GetId(), "" );
227 :
228 2839 : switch ( nSID )
229 : {
230 917 : case SID_ATTR_POSITION : GetStatusBar().SetHelpId( GetId(), STR_POSITION ); break;
231 809 : case SID_TABLE_CELL: GetStatusBar().SetHelpId( GetId(), STR_TABLECELL ); break;
232 198 : case SID_PSZ_FUNCTION: GetStatusBar().SetHelpId( GetId(), STR_FUNC ); break;
233 915 : default: break;
234 : }
235 :
236 2839 : if ( nSID == SID_PSZ_FUNCTION )
237 : {
238 198 : if ( eState == SfxItemState::DEFAULT )
239 : {
240 37 : pImp->bHasMenu = true;
241 37 : if ( pState && pState->ISA(SfxUInt16Item) )
242 37 : pImp->nFunction = static_cast<const SfxUInt16Item*>(pState)->GetValue();
243 : }
244 : else
245 161 : pImp->bHasMenu = false;
246 : }
247 2641 : else if ( SfxItemState::DEFAULT != eState )
248 : {
249 : // don't switch to empty display before an empty state was
250 : // notified for all display types
251 :
252 2238 : if ( nSID == SID_TABLE_CELL )
253 622 : pImp->bTable = false;
254 1616 : else if ( nSID == SID_ATTR_POSITION )
255 808 : pImp->bPos = false;
256 808 : else if ( nSID == GetSlotId() ) // controller is registered for SID_ATTR_SIZE
257 808 : pImp->bSize = false;
258 : else
259 : {
260 : SAL_WARN( "svx.stbcrtls","unknown slot id");
261 : }
262 : }
263 403 : else if ( pState->ISA( SfxPointItem ) )
264 : {
265 : // show position
266 109 : pImp->aPos = static_cast<const SfxPointItem*>(pState)->GetValue();
267 109 : pImp->bPos = true;
268 109 : pImp->bTable = false;
269 : }
270 294 : else if ( pState->ISA( SvxSizeItem ) )
271 : {
272 : // show size
273 107 : pImp->aSize = static_cast<const SvxSizeItem*>(pState)->GetSize();
274 107 : pImp->bSize = true;
275 107 : pImp->bTable = false;
276 : }
277 187 : else if ( pState->ISA( SfxStringItem ) )
278 : {
279 : // show string (table cel or different)
280 187 : pImp->aStr = static_cast<const SfxStringItem*>(pState)->GetValue();
281 187 : pImp->bTable = true;
282 187 : pImp->bPos = false;
283 187 : pImp->bSize = false;
284 : }
285 : else
286 : {
287 : SAL_WARN( "svx.stbcrtls", "invalid item type" );
288 0 : pImp->bPos = false;
289 0 : pImp->bSize = false;
290 0 : pImp->bTable = false;
291 : }
292 :
293 2839 : if ( GetStatusBar().AreItemsVisible() )
294 2839 : GetStatusBar().SetItemData( GetId(), 0 );
295 :
296 : // set only strings as text at the statusBar, so that the Help-Tips
297 : // can work with the text, when it is too long for the statusBar
298 2839 : OUString aText;
299 2839 : if ( pImp->bTable )
300 434 : aText = pImp->aStr;
301 2839 : GetStatusBar().SetItemText( GetId(), aText );
302 2839 : }
303 :
304 :
305 :
306 : /* [Description]
307 :
308 : execute popup menu, when the status enables this
309 : */
310 :
311 0 : void SvxPosSizeStatusBarControl::Command( const CommandEvent& rCEvt )
312 : {
313 0 : if ( rCEvt.GetCommand() == CommandEventId::ContextMenu && pImp->bHasMenu )
314 : {
315 0 : sal_uInt16 nSelect = pImp->nFunction;
316 0 : if (!nSelect)
317 0 : nSelect = PSZ_FUNC_NONE;
318 0 : FunctionPopup_Impl aMenu( nSelect );
319 0 : if ( aMenu.Execute( &GetStatusBar(), rCEvt.GetMousePosPixel() ) )
320 : {
321 0 : nSelect = aMenu.GetSelected();
322 0 : if (nSelect)
323 : {
324 0 : if (nSelect == PSZ_FUNC_NONE)
325 0 : nSelect = 0;
326 :
327 0 : ::com::sun::star::uno::Any a;
328 0 : SfxUInt16Item aItem( SID_PSZ_FUNCTION, nSelect );
329 :
330 0 : ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue > aArgs( 1 );
331 0 : aArgs[0].Name = "StatusBarFunc";
332 0 : aItem.QueryValue( a );
333 0 : aArgs[0].Value = a;
334 :
335 0 : execute( OUString( ".uno:StatusBarFunc" ), aArgs );
336 : // GetBindings().GetDispatcher()->Execute( SID_PSZ_FUNCTION, SfxCallMode::RECORD, &aItem, 0L );
337 : }
338 0 : }
339 : }
340 : else
341 0 : SfxStatusBarControl::Command( rCEvt );
342 0 : }
343 :
344 :
345 :
346 : /* [Description]
347 :
348 : Depending on the type to be shown, the value us shown. First the
349 : rectangle is repainted (removed).
350 : */
351 :
352 4063 : void SvxPosSizeStatusBarControl::Paint( const UserDrawEvent& rUsrEvt )
353 : {
354 4063 : OutputDevice* pDev = rUsrEvt.GetDevice();
355 : assert(pDev && "no OutputDevice on UserDrawEvent");
356 4063 : const Rectangle& rRect = rUsrEvt.GetRect();
357 4063 : StatusBar& rBar = GetStatusBar();
358 4063 : Point aItemPos = rBar.GetItemTextPos( GetId() );
359 4063 : Color aOldLineColor = pDev->GetLineColor();
360 4063 : Color aOldFillColor = pDev->GetFillColor();
361 4063 : pDev->SetLineColor();
362 4063 : pDev->SetFillColor( pDev->GetBackground().GetColor() );
363 :
364 4063 : if ( pImp->bPos || pImp->bSize )
365 : {
366 : // count the position for showing the size
367 : long nSizePosX =
368 243 : rRect.Left() + rRect.GetWidth() / 2 + PAINT_OFFSET;
369 : // draw position
370 243 : Point aPnt = rRect.TopLeft();
371 243 : aPnt.Y() = aItemPos.Y();
372 243 : aPnt.X() += PAINT_OFFSET;
373 243 : pDev->DrawImage( aPnt, pImp->aPosImage );
374 243 : aPnt.X() += pImp->aPosImage.GetSizePixel().Width();
375 243 : aPnt.X() += PAINT_OFFSET;
376 243 : OUString aStr = GetMetricStr_Impl( pImp->aPos.X());
377 243 : aStr += " / ";
378 243 : aStr += GetMetricStr_Impl( pImp->aPos.Y());
379 : pDev->DrawRect(
380 243 : Rectangle( aPnt, Point( nSizePosX, rRect.Bottom() ) ) );
381 243 : pDev->DrawText( aPnt, aStr );
382 :
383 : // draw the size, when available
384 243 : aPnt.X() = nSizePosX;
385 :
386 243 : if ( pImp->bSize )
387 : {
388 243 : pDev->DrawImage( aPnt, pImp->aSizeImage );
389 243 : aPnt.X() += pImp->aSizeImage.GetSizePixel().Width();
390 243 : Point aDrwPnt = aPnt;
391 243 : aPnt.X() += PAINT_OFFSET;
392 243 : aStr = GetMetricStr_Impl( pImp->aSize.Width() );
393 243 : aStr += " x ";
394 243 : aStr += GetMetricStr_Impl( pImp->aSize.Height() );
395 243 : pDev->DrawRect( Rectangle( aDrwPnt, rRect.BottomRight() ) );
396 243 : pDev->DrawText( aPnt, aStr );
397 : }
398 : else
399 0 : pDev->DrawRect( Rectangle( aPnt, rRect.BottomRight() ) );
400 : }
401 3820 : else if ( pImp->bTable )
402 : {
403 578 : pDev->DrawRect( rRect );
404 : pDev->DrawText( Point(
405 578 : rRect.Left() + rRect.GetWidth() / 2 - pDev->GetTextWidth( pImp->aStr ) / 2,
406 1156 : aItemPos.Y() ), pImp->aStr );
407 : }
408 : else
409 : {
410 : // Empty display if neither size nor table position are available.
411 : // Date/Time are no longer used (#65302#).
412 3242 : pDev->DrawRect( rRect );
413 : }
414 :
415 4063 : pDev->SetLineColor( aOldLineColor );
416 4063 : pDev->SetFillColor( aOldFillColor );
417 4453 : }
418 :
419 :
420 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|