1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_svx.hxx"
26
27 // include ---------------------------------------------------------------
28
29 #include <limits.h>
30 #include <tools/shl.hxx>
31 #include <vcl/status.hxx>
32 #include <vcl/menu.hxx>
33 #include <vcl/image.hxx>
34 #include <svl/stritem.hxx>
35 #include <svl/ptitem.hxx>
36 #include <svl/itempool.hxx>
37 #include <sfx2/app.hxx>
38 #include <sfx2/module.hxx>
39 #include <sfx2/dispatch.hxx>
40 #include <sfx2/objsh.hxx>
41 #include <svl/intitem.hxx>
42
43 #include "svx/pszctrl.hxx"
44
45 #define PAINT_OFFSET 5
46
47 #include <editeng/sizeitem.hxx>
48 #include <svx/dialmgr.hxx>
49 #include "svx/dlgutil.hxx"
50 #include "stbctrls.h"
51 #include "sfx2/module.hxx"
52
53 #include <svx/dialogs.hrc>
54 #include <unotools/localedatawrapper.hxx>
55 #ifndef _UNOTOOLS_PROCESSFACTORY_HXX
56 #include <comphelper/processfactory.hxx>
57 #endif
58
59 // -----------------------------------------------------------------------
60
61 /* [Beschreibung]
62
63 Funktion, mit der ein metrischer Wert in textueller Darstellung
64 umgewandelt wird.
65
66 nVal ist hier der metrische Wert in der Einheit eUnit.
67
68 [Querverweise]
69
70 <SvxPosSizeStatusBarControl::Paint(const UserDrawEvent&)>
71 */
72
GetMetricStr_Impl(long nVal)73 String SvxPosSizeStatusBarControl::GetMetricStr_Impl( long nVal )
74 {
75 // Applikations-Metrik besorgen und setzen
76 FieldUnit eOutUnit = SfxModule::GetModuleFieldUnit( getFrameInterface() );
77 FieldUnit eInUnit = FUNIT_100TH_MM;
78
79 String sMetric;
80 const sal_Unicode cSep = Application::GetSettings().GetLocaleDataWrapper().getNumDecimalSep().GetChar(0);
81 sal_Int64 nConvVal = MetricField::ConvertValue( nVal * 100, 0L, 0, eInUnit, eOutUnit );
82
83 if ( nConvVal < 0 && ( nConvVal / 100 == 0 ) )
84 sMetric += '-';
85 sMetric += String::CreateFromInt64( nConvVal / 100 );
86
87 if( FUNIT_NONE != eOutUnit )
88 {
89 sMetric += cSep;
90 sal_Int64 nFract = nConvVal % 100;
91
92 if ( nFract < 0 )
93 nFract *= -1;
94 if ( nFract < 10 )
95 sMetric += '0';
96 sMetric += String::CreateFromInt64( nFract );
97 }
98
99 return sMetric;
100 }
101
102 // -----------------------------------------------------------------------
103
104 SFX_IMPL_STATUSBAR_CONTROL(SvxPosSizeStatusBarControl, SvxSizeItem);
105
106 // class FunctionPopup_Impl ----------------------------------------------
107
108 class FunctionPopup_Impl : public PopupMenu
109 {
110 public:
111 FunctionPopup_Impl( sal_uInt16 nCheck );
112
GetSelected() const113 sal_uInt16 GetSelected() const { return nSelected; }
114
115 private:
116 sal_uInt16 nSelected;
117
118 virtual void Select();
119 };
120
121 // -----------------------------------------------------------------------
122
FunctionPopup_Impl(sal_uInt16 nCheck)123 FunctionPopup_Impl::FunctionPopup_Impl( sal_uInt16 nCheck ) :
124 PopupMenu( ResId( RID_SVXMNU_PSZ_FUNC, DIALOG_MGR() ) ),
125 nSelected( 0 )
126 {
127 if (nCheck)
128 CheckItem( nCheck );
129 }
130
131 // -----------------------------------------------------------------------
132
Select()133 void FunctionPopup_Impl::Select()
134 {
135 nSelected = GetCurItemId();
136 }
137
138 // struct SvxPosSizeStatusBarControl_Impl --------------------------------
139
140 struct SvxPosSizeStatusBarControl_Impl
141
142 /* [Beschreibung]
143
144 Diese Implementations-Struktur der Klasse SvxPosSizeStatusBarControl
145 dient der Entkopplung von "Anderungen vom exportierten Interface sowie
146 der Verringerung von extern sichtbaren Symbolen.
147
148 Eine Instanz exisitiert pro SvxPosSizeStatusBarControl-Instanz
149 f"ur deren Laufzeit.
150 */
151
152 {
153 Point aPos; // g"ultig, wenn eine Position angezeigt wird
154 Size aSize; // g"ultig, wenn eine Gr"o/se angezeigt wird
155 String aStr; // g"ultig, wenn ein Text angezeigt wird
156 sal_Bool bPos; // show position
157 sal_Bool bSize; // Gr"o/se anzeigen?
158 sal_Bool bTable; // Tabellenindex anzeigen?
159 sal_Bool bHasMenu; // StarCalc Popup-Menue anzeigen?
160 sal_uInt16 nFunction; // selektierte StarCalc Funktion
161 Image aPosImage; // Image f"ur die Positionsanzeige
162 Image aSizeImage; // Image f"ur die Gr"o/senanzeige
163 };
164
165 // class SvxPosSizeStatusBarControl ------------------------------------------
166
167 /* [Beschreibung]
168
169 Ctor():
170 Anlegen einer Impl-Klassen-Instanz, Default die Zeitanzeige enablen,
171 Images fu"r die Position und Gro"sse laden.
172 */
173
174 #define STR_POSITION ".uno:Position"
175 #define STR_TABLECELL ".uno:StateTableCell"
176 #define STR_FUNC ".uno:StatusBarFunc"
177
SvxPosSizeStatusBarControl(sal_uInt16 _nSlotId,sal_uInt16 _nId,StatusBar & rStb)178 SvxPosSizeStatusBarControl::SvxPosSizeStatusBarControl( sal_uInt16 _nSlotId,
179 sal_uInt16 _nId,
180 StatusBar& rStb ) :
181 SfxStatusBarControl( _nSlotId, _nId, rStb ),
182 pImp( new SvxPosSizeStatusBarControl_Impl )
183 {
184 pImp->bPos = sal_False;
185 pImp->bSize = sal_False;
186 pImp->bTable = sal_False;
187 pImp->bHasMenu = sal_False;
188 pImp->nFunction = 0;
189 sal_Bool bHC = GetStatusBar().GetSettings().GetStyleSettings().GetHighContrastMode();
190 pImp->aPosImage = Image( SVX_RES( bHC ? RID_SVXBMP_POSITION_H : RID_SVXBMP_POSITION ) );
191 pImp->aSizeImage = Image( SVX_RES( bHC ? RID_SVXBMP_SIZE_H : RID_SVXBMP_SIZE ) );
192
193 addStatusListener( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( STR_POSITION ))); // SID_ATTR_POSITION
194 addStatusListener( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( STR_TABLECELL ))); // SID_TABLE_CELL
195 addStatusListener( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( STR_FUNC ))); // SID_PSZ_FUNCTION
196 }
197
198 // -----------------------------------------------------------------------
199
200 /* [Beschreibung]
201
202 Dtor():
203 Pointer auf die Impl-Klasse lo"schen, damit der Timer gestoppt wird.
204 */
205
~SvxPosSizeStatusBarControl()206 SvxPosSizeStatusBarControl::~SvxPosSizeStatusBarControl()
207 {
208 delete pImp;
209 }
210
211 // -----------------------------------------------------------------------
212
213 /* [Beschreibung]
214
215 SID_PSZ_FUNCTION aktiviert das Popup-Menue fuer Calc, ansonsten:
216
217 Statusbenachrichtigung;
218 Je nach Item-Typ wird eine bestimmte Anzeige enabled, die anderen disabled.
219
220 NULL/Void SfxPointItem SvxSizeItem SfxStringItem
221 ------------------------------------------------------------------------
222 Zeit sal_True sal_False sal_False FALSE
223 Position sal_False FALSE
224 Gro"sse FALSE TRUE FALSE
225 Text sal_False sal_False TRUE
226
227 Ein anderes Item bewirkt einen Assert, die Zeitanzeige wird enabled.
228 */
229
StateChanged(sal_uInt16 nSID,SfxItemState eState,const SfxPoolItem * pState)230 void SvxPosSizeStatusBarControl::StateChanged( sal_uInt16 nSID, SfxItemState eState,
231 const SfxPoolItem* pState )
232 {
233 // da Kombi-Controller, immer die aktuelle Id als HelpId setzen
234 // gecachten HelpText vorher l"oschen
235 GetStatusBar().SetHelpText( GetId(), String() );
236
237 switch ( nSID )
238 {
239 case SID_ATTR_POSITION : GetStatusBar().SetHelpId( GetId(), STR_POSITION ); break;
240 case SID_TABLE_CELL: GetStatusBar().SetHelpId( GetId(), STR_TABLECELL ); break;
241 case SID_PSZ_FUNCTION: GetStatusBar().SetHelpId( GetId(), STR_FUNC ); break;
242 default: break;
243 }
244
245 if ( nSID == SID_PSZ_FUNCTION )
246 {
247 if ( eState == SFX_ITEM_AVAILABLE )
248 {
249 pImp->bHasMenu = sal_True;
250 if ( pState && pState->ISA(SfxUInt16Item) )
251 pImp->nFunction = ((const SfxUInt16Item*)pState)->GetValue();
252 }
253 else
254 pImp->bHasMenu = sal_False;
255 }
256 else if ( SFX_ITEM_AVAILABLE != eState )
257 {
258 // #i34458# don't switch to empty display before an empty state was
259 // notified for all display types
260
261 if ( nSID == SID_TABLE_CELL )
262 pImp->bTable = sal_False;
263 else if ( nSID == SID_ATTR_POSITION )
264 pImp->bPos = sal_False;
265 else if ( nSID == GetSlotId() ) // controller is registered for SID_ATTR_SIZE
266 pImp->bSize = sal_False;
267 else
268 {
269 DBG_ERRORFILE("unknown slot id");
270 }
271 }
272 else if ( pState->ISA( SfxPointItem ) )
273 {
274 // Position anzeigen
275 pImp->aPos = ( (SfxPointItem*)pState )->GetValue();
276 pImp->bPos = sal_True;
277 pImp->bTable = sal_False;
278 }
279 else if ( pState->ISA( SvxSizeItem ) )
280 {
281 // Groesse anzeigen
282 pImp->aSize = ( (SvxSizeItem*)pState )->GetSize();
283 pImp->bSize = sal_True;
284 pImp->bTable = sal_False;
285 }
286 else if ( pState->ISA( SfxStringItem ) )
287 {
288 // String anzeigen (Tabellen-Zelle oder anderes)
289 pImp->aStr = ( (SfxStringItem*)pState )->GetValue();
290 pImp->bTable = sal_True;
291 pImp->bPos = sal_False;
292 pImp->bSize = sal_False;
293 }
294 else
295 {
296 DBG_ERRORFILE( "invalid item type" );
297 // trotzdem Datum und Zeit anzeigen
298 pImp->bPos = sal_False;
299 pImp->bSize = sal_False;
300 pImp->bTable = sal_False;
301 }
302
303 if ( GetStatusBar().AreItemsVisible() )
304 GetStatusBar().SetItemData( GetId(), 0 );
305
306 // nur Strings auch als Text an der StatusBar setzen, damit Tip-Hilfe
307 // funktioniert, wenn der Text zu lang ist.
308 String aText;
309 if ( pImp->bTable )
310 aText = pImp->aStr;
311 GetStatusBar().SetItemText( GetId(), aText );
312 }
313
314 // -----------------------------------------------------------------------
315
316 /* [Beschreibung]
317
318 Popup-Menue ausfuehren, wenn per Status enabled
319 */
320
Command(const CommandEvent & rCEvt)321 void SvxPosSizeStatusBarControl::Command( const CommandEvent& rCEvt )
322 {
323 if ( rCEvt.GetCommand() == COMMAND_CONTEXTMENU && pImp->bHasMenu )
324 {
325 sal_uInt16 nSelect = pImp->nFunction;
326 if (!nSelect)
327 nSelect = PSZ_FUNC_NONE;
328 FunctionPopup_Impl aMenu( nSelect );
329 if ( aMenu.Execute( &GetStatusBar(), rCEvt.GetMousePosPixel() ) )
330 {
331 nSelect = aMenu.GetSelected();
332 if (nSelect)
333 {
334 if (nSelect == PSZ_FUNC_NONE)
335 nSelect = 0;
336
337 ::com::sun::star::uno::Any a;
338 SfxUInt16Item aItem( SID_PSZ_FUNCTION, nSelect );
339
340 ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue > aArgs( 1 );
341 aArgs[0].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "StatusBarFunc" ));
342 aItem.QueryValue( a );
343 aArgs[0].Value = a;
344
345 execute( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".uno:StatusBarFunc" )), aArgs );
346 // GetBindings().GetDispatcher()->Execute( SID_PSZ_FUNCTION, SFX_CALLMODE_RECORD, &aItem, 0L );
347 }
348 }
349 }
350 else
351 SfxStatusBarControl::Command( rCEvt );
352 }
353
354 // -----------------------------------------------------------------------
355
356 /* [Beschreibung]
357
358 Je nach enableden Anzeigentyp, wird der Wert angezeigt. Vorher wird
359 das Rectangle u"bermalt (gelo"scht).
360 */
361
Paint(const UserDrawEvent & rUsrEvt)362 void SvxPosSizeStatusBarControl::Paint( const UserDrawEvent& rUsrEvt )
363 {
364 OutputDevice* pDev = rUsrEvt.GetDevice();
365 DBG_ASSERT( pDev, "no OutputDevice on UserDrawEvent" );
366 const Rectangle& rRect = rUsrEvt.GetRect();
367 StatusBar& rBar = GetStatusBar();
368 Point aItemPos = rBar.GetItemTextPos( GetId() );
369 Color aOldLineColor = pDev->GetLineColor();
370 Color aOldFillColor = pDev->GetFillColor();
371 pDev->SetLineColor();
372 pDev->SetFillColor( pDev->GetBackground().GetColor() );
373
374 if ( pImp->bPos || pImp->bSize )
375 {
376 // Position fuer Size-Anzeige berechnen
377 long nSizePosX =
378 rRect.Left() + rRect.GetWidth() / 2 + PAINT_OFFSET;
379 // Position zeichnen
380 Point aPnt = rRect.TopLeft();
381 aPnt.Y() = aItemPos.Y();
382 aPnt.X() += PAINT_OFFSET;
383 pDev->DrawImage( aPnt, pImp->aPosImage );
384 aPnt.X() += pImp->aPosImage.GetSizePixel().Width();
385 aPnt.X() += PAINT_OFFSET;
386 String aStr = GetMetricStr_Impl( pImp->aPos.X());
387 aStr.AppendAscii(" / ");
388 aStr += GetMetricStr_Impl( pImp->aPos.Y());
389 pDev->DrawRect(
390 Rectangle( aPnt, Point( nSizePosX, rRect.Bottom() ) ) );
391 pDev->DrawText( aPnt, aStr );
392
393 // falls verf"ugbar, Gr"osse zeichnen
394 aPnt.X() = nSizePosX;
395
396 if ( pImp->bSize )
397 {
398 pDev->DrawImage( aPnt, pImp->aSizeImage );
399 aPnt.X() += pImp->aSizeImage.GetSizePixel().Width();
400 Point aDrwPnt = aPnt;
401 aPnt.X() += PAINT_OFFSET;
402 aStr = GetMetricStr_Impl( pImp->aSize.Width() );
403 aStr.AppendAscii(" x ");
404 aStr += GetMetricStr_Impl( pImp->aSize.Height() );
405 pDev->DrawRect( Rectangle( aDrwPnt, rRect.BottomRight() ) );
406 pDev->DrawText( aPnt, aStr );
407 }
408 else
409 pDev->DrawRect( Rectangle( aPnt, rRect.BottomRight() ) );
410 }
411 else if ( pImp->bTable )
412 {
413 pDev->DrawRect( rRect );
414 pDev->DrawText( Point(
415 rRect.Left() + rRect.GetWidth() / 2 - pDev->GetTextWidth( pImp->aStr ) / 2,
416 aItemPos.Y() ), pImp->aStr );
417 }
418 else
419 {
420 // Empty display if neither size nor table position are available.
421 // Date/Time are no longer used (#65302#).
422 pDev->DrawRect( rRect );
423 }
424
425 pDev->SetLineColor( aOldLineColor );
426 pDev->SetFillColor( aOldFillColor );
427 }
428
429 // -----------------------------------------------------------------------
430
GetDefItemWidth(const StatusBar & rStb)431 sal_uIntPtr SvxPosSizeStatusBarControl::GetDefItemWidth(const StatusBar& rStb)
432 {
433 Image aTmpPosImage( ResId( RID_SVXBMP_POSITION, DIALOG_MGR() ) );
434 Image aTmpSizeImage( ResId( RID_SVXBMP_SIZE, DIALOG_MGR() ) );
435
436 sal_uIntPtr nWidth=PAINT_OFFSET+aTmpPosImage.GetSizePixel().Width();
437 nWidth+=PAINT_OFFSET+aTmpSizeImage.GetSizePixel().Width();
438 nWidth+=2*(PAINT_OFFSET+rStb.GetTextWidth(String::CreateFromAscii("XXXX,XX / XXXX,XX")));
439
440 return nWidth;
441 }
442
443
444