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