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 0 : OUString SvxPosSizeStatusBarControl::GetMetricStr_Impl( long nVal )
63 : {
64 : // deliver and set the Metric of the application
65 0 : FieldUnit eOutUnit = SfxModule::GetModuleFieldUnit( getFrameInterface() );
66 0 : FieldUnit eInUnit = FUNIT_100TH_MM;
67 :
68 0 : OUString sMetric;
69 0 : const sal_Unicode cSep = Application::GetSettings().GetLocaleDataWrapper().getNumDecimalSep()[0];
70 0 : sal_Int64 nConvVal = MetricField::ConvertValue( nVal * 100, 0L, 0, eInUnit, eOutUnit );
71 :
72 0 : if ( nConvVal < 0 && ( nConvVal / 100 == 0 ) )
73 0 : sMetric += "-";
74 0 : sMetric += OUString::number(nConvVal / 100);
75 :
76 0 : if( FUNIT_NONE != eOutUnit )
77 : {
78 0 : sMetric += OUString(cSep);
79 0 : sal_Int64 nFract = nConvVal % 100;
80 :
81 0 : if ( nFract < 0 )
82 0 : nFract *= -1;
83 0 : if ( nFract < 10 )
84 0 : sMetric += "0";
85 0 : sMetric += OUString::number(nFract);
86 : }
87 :
88 0 : return sMetric;
89 : }
90 :
91 :
92 :
93 0 : 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 0 : 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 0 : SvxPosSizeStatusBarControl::SvxPosSizeStatusBarControl( sal_uInt16 _nSlotId,
168 : sal_uInt16 _nId,
169 : StatusBar& rStb ) :
170 : SfxStatusBarControl( _nSlotId, _nId, rStb ),
171 0 : pImp( new SvxPosSizeStatusBarControl_Impl )
172 : {
173 0 : pImp->bPos = false;
174 0 : pImp->bSize = false;
175 0 : pImp->bTable = false;
176 0 : pImp->bHasMenu = false;
177 0 : pImp->nFunction = 0;
178 0 : pImp->aPosImage = Image( ResId( RID_SVXBMP_POSITION, DIALOG_MGR() ) );
179 0 : pImp->aSizeImage = Image( ResId( RID_SVXBMP_SIZE, DIALOG_MGR() ) );
180 :
181 0 : 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 0 : addStatusListener( OUString( STR_POSITION )); // SID_ATTR_POSITION
193 0 : addStatusListener( OUString( STR_TABLECELL )); // SID_TABLE_CELL
194 0 : addStatusListener( OUString( STR_FUNC )); // SID_PSZ_FUNCTION
195 0 : }
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 0 : SvxPosSizeStatusBarControl::~SvxPosSizeStatusBarControl()
207 : {
208 0 : delete pImp;
209 0 : }
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 0 : 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 0 : GetStatusBar().SetHelpText( GetId(), "" );
234 :
235 0 : switch ( nSID )
236 : {
237 0 : case SID_ATTR_POSITION : GetStatusBar().SetHelpId( GetId(), STR_POSITION ); break;
238 0 : case SID_TABLE_CELL: GetStatusBar().SetHelpId( GetId(), STR_TABLECELL ); break;
239 0 : case SID_PSZ_FUNCTION: GetStatusBar().SetHelpId( GetId(), STR_FUNC ); break;
240 0 : default: break;
241 : }
242 :
243 0 : if ( nSID == SID_PSZ_FUNCTION )
244 : {
245 0 : if ( eState == SFX_ITEM_AVAILABLE )
246 : {
247 0 : pImp->bHasMenu = true;
248 0 : if ( pState && pState->ISA(SfxUInt16Item) )
249 0 : pImp->nFunction = ((const SfxUInt16Item*)pState)->GetValue();
250 : }
251 : else
252 0 : pImp->bHasMenu = false;
253 : }
254 0 : 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 0 : if ( nSID == SID_TABLE_CELL )
260 0 : pImp->bTable = false;
261 0 : else if ( nSID == SID_ATTR_POSITION )
262 0 : pImp->bPos = false;
263 0 : else if ( nSID == GetSlotId() ) // controller is registered for SID_ATTR_SIZE
264 0 : pImp->bSize = false;
265 : else
266 : {
267 : SAL_WARN( "svx.stbcrtls","unknown slot id");
268 : }
269 : }
270 0 : else if ( pState->ISA( SfxPointItem ) )
271 : {
272 : // show position
273 0 : pImp->aPos = ( (SfxPointItem*)pState )->GetValue();
274 0 : pImp->bPos = true;
275 0 : pImp->bTable = false;
276 : }
277 0 : else if ( pState->ISA( SvxSizeItem ) )
278 : {
279 : // show size
280 0 : pImp->aSize = ( (SvxSizeItem*)pState )->GetSize();
281 0 : pImp->bSize = true;
282 0 : pImp->bTable = false;
283 : }
284 0 : else if ( pState->ISA( SfxStringItem ) )
285 : {
286 : // show string (table cel or different)
287 0 : pImp->aStr = ( (SfxStringItem*)pState )->GetValue();
288 0 : pImp->bTable = true;
289 0 : pImp->bPos = false;
290 0 : 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 0 : if ( GetStatusBar().AreItemsVisible() )
301 0 : 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 0 : OUString aText;
306 0 : if ( pImp->bTable )
307 0 : aText = pImp->aStr;
308 0 : GetStatusBar().SetItemText( GetId(), aText );
309 0 : }
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 0 : void SvxPosSizeStatusBarControl::Paint( const UserDrawEvent& rUsrEvt )
360 : {
361 0 : OutputDevice* pDev = rUsrEvt.GetDevice();
362 : DBG_ASSERT( pDev, "no OutputDevice on UserDrawEvent" );
363 0 : const Rectangle& rRect = rUsrEvt.GetRect();
364 0 : StatusBar& rBar = GetStatusBar();
365 0 : Point aItemPos = rBar.GetItemTextPos( GetId() );
366 0 : Color aOldLineColor = pDev->GetLineColor();
367 0 : Color aOldFillColor = pDev->GetFillColor();
368 0 : pDev->SetLineColor();
369 0 : pDev->SetFillColor( pDev->GetBackground().GetColor() );
370 :
371 0 : if ( pImp->bPos || pImp->bSize )
372 : {
373 : // count the position for showing the size
374 : long nSizePosX =
375 0 : rRect.Left() + rRect.GetWidth() / 2 + PAINT_OFFSET;
376 : // draw position
377 0 : Point aPnt = rRect.TopLeft();
378 0 : aPnt.Y() = aItemPos.Y();
379 0 : aPnt.X() += PAINT_OFFSET;
380 0 : pDev->DrawImage( aPnt, pImp->aPosImage );
381 0 : aPnt.X() += pImp->aPosImage.GetSizePixel().Width();
382 0 : aPnt.X() += PAINT_OFFSET;
383 0 : OUString aStr = GetMetricStr_Impl( pImp->aPos.X());
384 0 : aStr += " / ";
385 0 : aStr += GetMetricStr_Impl( pImp->aPos.Y());
386 : pDev->DrawRect(
387 0 : Rectangle( aPnt, Point( nSizePosX, rRect.Bottom() ) ) );
388 0 : pDev->DrawText( aPnt, aStr );
389 :
390 : // draw the size, when available
391 0 : aPnt.X() = nSizePosX;
392 :
393 0 : if ( pImp->bSize )
394 : {
395 0 : pDev->DrawImage( aPnt, pImp->aSizeImage );
396 0 : aPnt.X() += pImp->aSizeImage.GetSizePixel().Width();
397 0 : Point aDrwPnt = aPnt;
398 0 : aPnt.X() += PAINT_OFFSET;
399 0 : aStr = GetMetricStr_Impl( pImp->aSize.Width() );
400 0 : aStr += " x ";
401 0 : aStr += GetMetricStr_Impl( pImp->aSize.Height() );
402 0 : pDev->DrawRect( Rectangle( aDrwPnt, rRect.BottomRight() ) );
403 0 : pDev->DrawText( aPnt, aStr );
404 : }
405 : else
406 0 : pDev->DrawRect( Rectangle( aPnt, rRect.BottomRight() ) );
407 : }
408 0 : else if ( pImp->bTable )
409 : {
410 0 : pDev->DrawRect( rRect );
411 : pDev->DrawText( Point(
412 0 : rRect.Left() + rRect.GetWidth() / 2 - pDev->GetTextWidth( pImp->aStr ) / 2,
413 0 : 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 0 : pDev->DrawRect( rRect );
420 : }
421 :
422 0 : pDev->SetLineColor( aOldLineColor );
423 0 : pDev->SetFillColor( aOldFillColor );
424 0 : }
425 :
426 :
427 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|