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