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 <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 : #include "sfx2/module.hxx"
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 : String 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 : String 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 += rtl::OUString::valueOf(nConvVal / 100);
75 :
76 0 : if( FUNIT_NONE != eOutUnit )
77 : {
78 0 : sMetric += 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 += rtl::OUString::valueOf(nFract);
86 : }
87 :
88 0 : return sMetric;
89 : }
90 :
91 : // -----------------------------------------------------------------------
92 :
93 18 : 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();
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 externaly.
136 :
137 : One instance exists for each SvxPosSizeStatusBarControl-instance
138 : during it's life time
139 : */
140 :
141 : {
142 : Point aPos; // valid when a position is shown
143 : Size aSize; // valid when a size is shown
144 : String aStr; // valid when a text is shown
145 : sal_Bool bPos; // show position ?
146 : sal_Bool bSize; // set size ?
147 : sal_Bool bTable; // set table index ?
148 : sal_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 = sal_False;
174 0 : pImp->bSize = sal_False;
175 0 : pImp->bTable = sal_False;
176 0 : pImp->bHasMenu = sal_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 : addStatusListener( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( STR_POSITION ))); // SID_ATTR_POSITION
182 0 : addStatusListener( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( STR_TABLECELL ))); // SID_TABLE_CELL
183 0 : addStatusListener( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( STR_FUNC ))); // SID_PSZ_FUNCTION
184 0 : }
185 :
186 : // -----------------------------------------------------------------------
187 :
188 : /* [Description]
189 :
190 : Dtor():
191 : remove the pointer to the implementation class, so that the timer is stopped
192 :
193 : */
194 :
195 0 : SvxPosSizeStatusBarControl::~SvxPosSizeStatusBarControl()
196 : {
197 0 : delete pImp;
198 0 : }
199 :
200 : // -----------------------------------------------------------------------
201 :
202 : /* [Description]
203 :
204 : SID_PSZ_FUNCTION activates the popup menu for Calc:
205 :
206 : Status overview
207 : Depending on the type of the item, a special setting is enabled, the others disabled.
208 :
209 : NULL/Void SfxPointItem SvxSizeItem SfxStringItem
210 : ------------------------------------------------------------------------
211 : Position sal_False FALSE
212 : Size FALSE TRUE FALSE
213 : Text sal_False sal_False TRUE
214 :
215 : */
216 :
217 0 : void SvxPosSizeStatusBarControl::StateChanged( sal_uInt16 nSID, SfxItemState eState,
218 : const SfxPoolItem* pState )
219 : {
220 : // Because the combi-controller, always sets the curent Id as HelpId
221 : // first clean the cached HelpText
222 0 : GetStatusBar().SetHelpText( GetId(), String() );
223 :
224 0 : switch ( nSID )
225 : {
226 0 : case SID_ATTR_POSITION : GetStatusBar().SetHelpId( GetId(), STR_POSITION ); break;
227 0 : case SID_TABLE_CELL: GetStatusBar().SetHelpId( GetId(), STR_TABLECELL ); break;
228 0 : case SID_PSZ_FUNCTION: GetStatusBar().SetHelpId( GetId(), STR_FUNC ); break;
229 0 : default: break;
230 : }
231 :
232 0 : if ( nSID == SID_PSZ_FUNCTION )
233 : {
234 0 : if ( eState == SFX_ITEM_AVAILABLE )
235 : {
236 0 : pImp->bHasMenu = sal_True;
237 0 : if ( pState && pState->ISA(SfxUInt16Item) )
238 0 : pImp->nFunction = ((const SfxUInt16Item*)pState)->GetValue();
239 : }
240 : else
241 0 : pImp->bHasMenu = sal_False;
242 : }
243 0 : else if ( SFX_ITEM_AVAILABLE != eState )
244 : {
245 : // don't switch to empty display before an empty state was
246 : // notified for all display types
247 :
248 0 : if ( nSID == SID_TABLE_CELL )
249 0 : pImp->bTable = sal_False;
250 0 : else if ( nSID == SID_ATTR_POSITION )
251 0 : pImp->bPos = sal_False;
252 0 : else if ( nSID == GetSlotId() ) // controller is registered for SID_ATTR_SIZE
253 0 : pImp->bSize = sal_False;
254 : else
255 : {
256 : SAL_WARN( "svx.stbcrtls","unknown slot id");
257 : }
258 : }
259 0 : else if ( pState->ISA( SfxPointItem ) )
260 : {
261 : // show position
262 0 : pImp->aPos = ( (SfxPointItem*)pState )->GetValue();
263 0 : pImp->bPos = sal_True;
264 0 : pImp->bTable = sal_False;
265 : }
266 0 : else if ( pState->ISA( SvxSizeItem ) )
267 : {
268 : // show size
269 0 : pImp->aSize = ( (SvxSizeItem*)pState )->GetSize();
270 0 : pImp->bSize = sal_True;
271 0 : pImp->bTable = sal_False;
272 : }
273 0 : else if ( pState->ISA( SfxStringItem ) )
274 : {
275 : // show string (table cel or different)
276 0 : pImp->aStr = ( (SfxStringItem*)pState )->GetValue();
277 0 : pImp->bTable = sal_True;
278 0 : pImp->bPos = sal_False;
279 0 : pImp->bSize = sal_False;
280 : }
281 : else
282 : {
283 : SAL_WARN( "svx.stbcrtls", "invalid item type" );
284 0 : pImp->bPos = sal_False;
285 0 : pImp->bSize = sal_False;
286 0 : pImp->bTable = sal_False;
287 : }
288 :
289 0 : if ( GetStatusBar().AreItemsVisible() )
290 0 : GetStatusBar().SetItemData( GetId(), 0 );
291 :
292 : // set only strings as text at the statusBar, so that the Help-Tips
293 : // can work with the text, when it is too long for the statusBar
294 0 : String aText;
295 0 : if ( pImp->bTable )
296 0 : aText = pImp->aStr;
297 0 : GetStatusBar().SetItemText( GetId(), aText );
298 0 : }
299 :
300 : // -----------------------------------------------------------------------
301 :
302 : /* [Description]
303 :
304 : execute popup menu, when the status enables this
305 : */
306 :
307 0 : void SvxPosSizeStatusBarControl::Command( const CommandEvent& rCEvt )
308 : {
309 0 : if ( rCEvt.GetCommand() == COMMAND_CONTEXTMENU && pImp->bHasMenu )
310 : {
311 0 : sal_uInt16 nSelect = pImp->nFunction;
312 0 : if (!nSelect)
313 0 : nSelect = PSZ_FUNC_NONE;
314 0 : FunctionPopup_Impl aMenu( nSelect );
315 0 : if ( aMenu.Execute( &GetStatusBar(), rCEvt.GetMousePosPixel() ) )
316 : {
317 0 : nSelect = aMenu.GetSelected();
318 0 : if (nSelect)
319 : {
320 0 : if (nSelect == PSZ_FUNC_NONE)
321 0 : nSelect = 0;
322 :
323 0 : ::com::sun::star::uno::Any a;
324 0 : SfxUInt16Item aItem( SID_PSZ_FUNCTION, nSelect );
325 :
326 0 : ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue > aArgs( 1 );
327 0 : aArgs[0].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "StatusBarFunc" ));
328 0 : aItem.QueryValue( a );
329 0 : aArgs[0].Value = a;
330 :
331 0 : execute( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".uno:StatusBarFunc" )), aArgs );
332 : // GetBindings().GetDispatcher()->Execute( SID_PSZ_FUNCTION, SFX_CALLMODE_RECORD, &aItem, 0L );
333 : }
334 0 : }
335 : }
336 : else
337 0 : SfxStatusBarControl::Command( rCEvt );
338 0 : }
339 :
340 : // -----------------------------------------------------------------------
341 :
342 : /* [Description]
343 :
344 : Depending on the type to be shown, the value us shown. First the
345 : rectangle is repainted (removed).
346 : */
347 :
348 0 : void SvxPosSizeStatusBarControl::Paint( const UserDrawEvent& rUsrEvt )
349 : {
350 0 : OutputDevice* pDev = rUsrEvt.GetDevice();
351 : DBG_ASSERT( pDev, "no OutputDevice on UserDrawEvent" );
352 0 : const Rectangle& rRect = rUsrEvt.GetRect();
353 0 : StatusBar& rBar = GetStatusBar();
354 0 : Point aItemPos = rBar.GetItemTextPos( GetId() );
355 0 : Color aOldLineColor = pDev->GetLineColor();
356 0 : Color aOldFillColor = pDev->GetFillColor();
357 0 : pDev->SetLineColor();
358 0 : pDev->SetFillColor( pDev->GetBackground().GetColor() );
359 :
360 0 : if ( pImp->bPos || pImp->bSize )
361 : {
362 : // count the position for showing the size
363 : long nSizePosX =
364 0 : rRect.Left() + rRect.GetWidth() / 2 + PAINT_OFFSET;
365 : // draw position
366 0 : Point aPnt = rRect.TopLeft();
367 0 : aPnt.Y() = aItemPos.Y();
368 0 : aPnt.X() += PAINT_OFFSET;
369 0 : pDev->DrawImage( aPnt, pImp->aPosImage );
370 0 : aPnt.X() += pImp->aPosImage.GetSizePixel().Width();
371 0 : aPnt.X() += PAINT_OFFSET;
372 0 : String aStr = GetMetricStr_Impl( pImp->aPos.X());
373 0 : aStr.AppendAscii(" / ");
374 0 : aStr += GetMetricStr_Impl( pImp->aPos.Y());
375 : pDev->DrawRect(
376 0 : Rectangle( aPnt, Point( nSizePosX, rRect.Bottom() ) ) );
377 0 : pDev->DrawText( aPnt, aStr );
378 :
379 : // draw the size, when available
380 0 : aPnt.X() = nSizePosX;
381 :
382 0 : if ( pImp->bSize )
383 : {
384 0 : pDev->DrawImage( aPnt, pImp->aSizeImage );
385 0 : aPnt.X() += pImp->aSizeImage.GetSizePixel().Width();
386 0 : Point aDrwPnt = aPnt;
387 0 : aPnt.X() += PAINT_OFFSET;
388 0 : aStr = GetMetricStr_Impl( pImp->aSize.Width() );
389 0 : aStr.AppendAscii(" x ");
390 0 : aStr += GetMetricStr_Impl( pImp->aSize.Height() );
391 0 : pDev->DrawRect( Rectangle( aDrwPnt, rRect.BottomRight() ) );
392 0 : pDev->DrawText( aPnt, aStr );
393 : }
394 : else
395 0 : pDev->DrawRect( Rectangle( aPnt, rRect.BottomRight() ) );
396 : }
397 0 : else if ( pImp->bTable )
398 : {
399 0 : pDev->DrawRect( rRect );
400 : pDev->DrawText( Point(
401 0 : rRect.Left() + rRect.GetWidth() / 2 - pDev->GetTextWidth( pImp->aStr ) / 2,
402 0 : aItemPos.Y() ), pImp->aStr );
403 : }
404 : else
405 : {
406 : // Empty display if neither size nor table position are available.
407 : // Date/Time are no longer used (#65302#).
408 0 : pDev->DrawRect( rRect );
409 : }
410 :
411 0 : pDev->SetLineColor( aOldLineColor );
412 0 : pDev->SetFillColor( aOldFillColor );
413 0 : }
414 :
415 :
416 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|