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 #define _SVX_PSZCTRL_CXX 43 44 #include "svx/pszctrl.hxx" 45 46 #define PAINT_OFFSET 5 47 48 #include <editeng/sizeitem.hxx> 49 #include <svx/dialmgr.hxx> 50 #include "svx/dlgutil.hxx" 51 #include "stbctrls.h" 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 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 113 sal_uInt16 GetSelected() const { return nSelected; } 114 115 private: 116 sal_uInt16 nSelected; 117 118 virtual void Select(); 119 }; 120 121 // ----------------------------------------------------------------------- 122 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 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 Änderungen vom exportierten Interface sowie 146 der Verringerung von extern sichtbaren Symbolen. 147 148 Eine Instanz existiert pro SvxPosSizeStatusBarControl-Instanz 149 für deren Laufzeit. 150 */ 151 152 { 153 Point aPos; // gültig, wenn eine Position angezeigt wird 154 Size aSize; // gültig, wenn eine Größe angezeigt wird 155 String aStr; // gültig, wenn ein Text angezeigt wird 156 sal_Bool bPos; // show position? 157 sal_Bool bSize; // show size? 158 sal_Bool bTable; // Tabellenindex anzeigen? 159 sal_Bool bHasMenu; // Calc Popup-Menü anzeigen? 160 sal_uInt16 nFunction; // selektierte Calc Funktion 161 Image aPosImage; // Image für die Positionsanzeige 162 Image aSizeImage; // Image für die Größenanzeige 163 }; 164 165 // class SvxPosSizeStatusBarControl ------------------------------------------ 166 167 /* [Beschreibung] 168 169 Ctor(): 170 Anlegen einer Impl-Klassen-Instanz, Default die Zeitanzeige enablen, 171 Images für die Position und Größe laden. 172 */ 173 174 #define STR_POSITION ".uno:Position" 175 #define STR_TABLECELL ".uno:StateTableCell" 176 #define STR_FUNC ".uno:StatusBarFunc" 177 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 pImp->aPosImage = Image( ResId( RID_SVXBMP_POSITION, DIALOG_MGR() ) ); 190 pImp->aSizeImage = Image( ResId( RID_SVXBMP_SIZE, DIALOG_MGR() ) ); 191 192 addStatusListener( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( STR_POSITION ))); // SID_ATTR_POSITION 193 addStatusListener( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( STR_TABLECELL ))); // SID_TABLE_CELL 194 addStatusListener( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( STR_FUNC ))); // SID_PSZ_FUNCTION 195 } 196 197 // ----------------------------------------------------------------------- 198 199 /* [Beschreibung] 200 201 Dtor(): 202 Pointer auf die Impl-Klasse löschen, damit der Timer gestoppt wird. 203 */ 204 205 SvxPosSizeStatusBarControl::~SvxPosSizeStatusBarControl() 206 { 207 delete pImp; 208 } 209 210 // ----------------------------------------------------------------------- 211 212 /* [Beschreibung] 213 214 SID_PSZ_FUNCTION aktiviert das Popup-Menü für Calc, ansonsten: 215 216 Statusbenachrichtigung; 217 Je nach Item-Typ wird eine bestimmte Anzeige enabled, die anderen disabled. 218 219 NULL/Void SfxPointItem SvxSizeItem SfxStringItem 220 ------------------------------------------------------------------------ 221 Zeit sal_True sal_False sal_False FALSE 222 Position sal_False FALSE 223 Größe FALSE TRUE FALSE 224 Text sal_False sal_False TRUE 225 226 Ein anderes Item bewirkt einen Assert, die Zeitanzeige wird enabled. 227 */ 228 229 void SvxPosSizeStatusBarControl::StateChanged( sal_uInt16 nSID, SfxItemState eState, 230 const SfxPoolItem* pState ) 231 { 232 // da Kombi-Controller, immer die aktuelle Id als HelpId setzen 233 // gecachten HelpText vorher löschen 234 GetStatusBar().SetHelpText( GetId(), String() ); 235 236 switch ( nSID ) 237 { 238 case SID_ATTR_POSITION : GetStatusBar().SetHelpId( GetId(), STR_POSITION ); break; 239 case SID_TABLE_CELL: GetStatusBar().SetHelpId( GetId(), STR_TABLECELL ); break; 240 case SID_PSZ_FUNCTION: GetStatusBar().SetHelpId( GetId(), STR_FUNC ); break; 241 default: break; 242 } 243 244 if ( nSID == SID_PSZ_FUNCTION ) 245 { 246 if ( eState == SFX_ITEM_AVAILABLE ) 247 { 248 pImp->bHasMenu = sal_True; 249 if ( pState && pState->ISA(SfxUInt16Item) ) 250 pImp->nFunction = ((const SfxUInt16Item*)pState)->GetValue(); 251 } 252 else 253 pImp->bHasMenu = sal_False; 254 } 255 else if ( SFX_ITEM_AVAILABLE != eState ) 256 { 257 // #i34458# don't switch to empty display before an empty state was 258 // notified for all display types 259 260 if ( nSID == SID_TABLE_CELL ) 261 pImp->bTable = sal_False; 262 else if ( nSID == SID_ATTR_POSITION ) 263 pImp->bPos = sal_False; 264 else if ( nSID == GetSlotId() ) // controller is registered for SID_ATTR_SIZE 265 pImp->bSize = sal_False; 266 else 267 { 268 DBG_ERRORFILE("unknown slot id"); 269 } 270 } 271 else if ( pState->ISA( SfxPointItem ) ) 272 { 273 // Position anzeigen 274 pImp->aPos = ( (SfxPointItem*)pState )->GetValue(); 275 pImp->bPos = sal_True; 276 pImp->bTable = sal_False; 277 } 278 else if ( pState->ISA( SvxSizeItem ) ) 279 { 280 // Größe anzeigen 281 pImp->aSize = ( (SvxSizeItem*)pState )->GetSize(); 282 pImp->bSize = sal_True; 283 pImp->bTable = sal_False; 284 } 285 else if ( pState->ISA( SfxStringItem ) ) 286 { 287 // String anzeigen (Tabellen-Zelle oder anderes) 288 pImp->aStr = ( (SfxStringItem*)pState )->GetValue(); 289 pImp->bTable = sal_True; 290 pImp->bPos = sal_False; 291 pImp->bSize = sal_False; 292 } 293 else 294 { 295 DBG_ERRORFILE( "invalid item type" ); 296 // trotzdem Datum und Zeit anzeigen 297 pImp->bPos = sal_False; 298 pImp->bSize = sal_False; 299 pImp->bTable = sal_False; 300 } 301 302 if ( GetStatusBar().AreItemsVisible() ) 303 GetStatusBar().SetItemData( GetId(), 0 ); 304 305 // nur Strings auch als Text an der StatusBar setzen, damit Tip-Hilfe 306 // funktioniert, wenn der Text zu lang ist. 307 String aText; 308 if ( pImp->bTable ) 309 aText = pImp->aStr; 310 GetStatusBar().SetItemText( GetId(), aText ); 311 } 312 313 // ----------------------------------------------------------------------- 314 315 /* [Beschreibung] 316 317 Popup-Menü ausführen, wenn per Status enabled 318 */ 319 320 void SvxPosSizeStatusBarControl::Command( const CommandEvent& rCEvt ) 321 { 322 if ( rCEvt.GetCommand() == COMMAND_CONTEXTMENU && pImp->bHasMenu ) 323 { 324 sal_uInt16 nSelect = pImp->nFunction; 325 if (!nSelect) 326 nSelect = PSZ_FUNC_NONE; 327 FunctionPopup_Impl aMenu( nSelect ); 328 if ( aMenu.Execute( &GetStatusBar(), rCEvt.GetMousePosPixel() ) ) 329 { 330 nSelect = aMenu.GetSelected(); 331 if (nSelect) 332 { 333 if (nSelect == PSZ_FUNC_NONE) 334 nSelect = 0; 335 336 ::com::sun::star::uno::Any a; 337 SfxUInt16Item aItem( SID_PSZ_FUNCTION, nSelect ); 338 339 ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue > aArgs( 1 ); 340 aArgs[0].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "StatusBarFunc" )); 341 aItem.QueryValue( a ); 342 aArgs[0].Value = a; 343 344 execute( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".uno:StatusBarFunc" )), aArgs ); 345 // GetBindings().GetDispatcher()->Execute( SID_PSZ_FUNCTION, SFX_CALLMODE_RECORD, &aItem, 0L ); 346 } 347 } 348 } 349 else 350 SfxStatusBarControl::Command( rCEvt ); 351 } 352 353 // ----------------------------------------------------------------------- 354 355 /* [Beschreibung] 356 357 Je nach enableden Anzeigentyp, wird der Wert angezeigt. Vorher wird 358 das Rectangle übermalt (gelöscht). 359 */ 360 361 void SvxPosSizeStatusBarControl::Paint( const UserDrawEvent& rUsrEvt ) 362 { 363 OutputDevice* pDev = rUsrEvt.GetDevice(); 364 DBG_ASSERT( pDev, "no OutputDevice on UserDrawEvent" ); 365 const Rectangle& rRect = rUsrEvt.GetRect(); 366 StatusBar& rBar = GetStatusBar(); 367 Point aItemPos = rBar.GetItemTextPos( GetId() ); 368 Color aOldLineColor = pDev->GetLineColor(); 369 Color aOldFillColor = pDev->GetFillColor(); 370 pDev->SetLineColor(); 371 pDev->SetFillColor( pDev->GetBackground().GetColor() ); 372 373 if ( pImp->bPos || pImp->bSize ) 374 { 375 // Position für Size-Anzeige berechnen 376 long nSizePosX = 377 rRect.Left() + rRect.GetWidth() / 2 + PAINT_OFFSET; 378 // Position zeichnen 379 Point aPnt = rRect.TopLeft(); 380 aPnt.Y() = aItemPos.Y(); 381 aPnt.X() += PAINT_OFFSET; 382 pDev->DrawImage( aPnt, pImp->aPosImage ); 383 aPnt.X() += pImp->aPosImage.GetSizePixel().Width(); 384 aPnt.X() += PAINT_OFFSET; 385 String aStr = GetMetricStr_Impl( pImp->aPos.X()); 386 aStr.AppendAscii(" / "); 387 aStr += GetMetricStr_Impl( pImp->aPos.Y()); 388 pDev->DrawRect( 389 Rectangle( aPnt, Point( nSizePosX, rRect.Bottom() ) ) ); 390 pDev->DrawText( aPnt, aStr ); 391 392 // falls verfügbar, Größe zeichnen 393 aPnt.X() = nSizePosX; 394 395 if ( pImp->bSize ) 396 { 397 pDev->DrawImage( aPnt, pImp->aSizeImage ); 398 aPnt.X() += pImp->aSizeImage.GetSizePixel().Width(); 399 Point aDrwPnt = aPnt; 400 aPnt.X() += PAINT_OFFSET; 401 aStr = GetMetricStr_Impl( pImp->aSize.Width() ); 402 aStr.AppendAscii(" x "); 403 aStr += GetMetricStr_Impl( pImp->aSize.Height() ); 404 pDev->DrawRect( Rectangle( aDrwPnt, rRect.BottomRight() ) ); 405 pDev->DrawText( aPnt, aStr ); 406 } 407 else 408 pDev->DrawRect( Rectangle( aPnt, rRect.BottomRight() ) ); 409 } 410 else if ( pImp->bTable ) 411 { 412 pDev->DrawRect( rRect ); 413 pDev->DrawText( Point( 414 rRect.Left() + rRect.GetWidth() / 2 - pDev->GetTextWidth( pImp->aStr ) / 2, 415 aItemPos.Y() ), pImp->aStr ); 416 } 417 else 418 { 419 // Empty display if neither size nor table position are available. 420 // Date/Time are no longer used (#65302#). 421 pDev->DrawRect( rRect ); 422 } 423 424 pDev->SetLineColor( aOldLineColor ); 425 pDev->SetFillColor( aOldFillColor ); 426 } 427 428 // ----------------------------------------------------------------------- 429 430 sal_uIntPtr SvxPosSizeStatusBarControl::GetDefItemWidth(const StatusBar& rStb) 431 { 432 Image aTmpPosImage( ResId( RID_SVXBMP_POSITION, DIALOG_MGR() ) ); 433 Image aTmpSizeImage( ResId( RID_SVXBMP_SIZE, DIALOG_MGR() ) ); 434 435 sal_uIntPtr nWidth=PAINT_OFFSET+aTmpPosImage.GetSizePixel().Width(); 436 nWidth+=PAINT_OFFSET+aTmpSizeImage.GetSizePixel().Width(); 437 nWidth+=2*(PAINT_OFFSET+rStb.GetTextWidth(String::CreateFromAscii("XXXX,XX / XXXX,XX"))); 438 439 return nWidth; 440 } 441 442 /* vim: set noet sw=4 ts=4: */ 443