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_sc.hxx" 30 31 32 33 // INCLUDE --------------------------------------------------------------- 34 #define _ZFORLIST_DECLARE_TABLE 35 #include "scitems.hxx" 36 #include <svl/smplhint.hxx> 37 #include <svl/zforlist.hxx> 38 #include <svx/numfmtsh.hxx> 39 #include <svx/numinf.hxx> 40 #include <svx/svxids.hrc> 41 #include <sfx2/dispatch.hxx> 42 #include <sfx2/objsh.hxx> 43 44 #include "tabvwsh.hxx" 45 #include "sc.hrc" 46 #include "global.hxx" 47 #include "docsh.hxx" 48 #include "document.hxx" 49 #include "cell.hxx" 50 #include "globstr.hrc" 51 #include "scmod.hxx" 52 #include "uiitems.hxx" 53 #include "editsh.hxx" 54 #include "hints.hxx" 55 56 57 //================================================================== 58 59 void __EXPORT ScTabViewShell::Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) 60 { 61 if (rHint.ISA(SfxSimpleHint)) // ohne Parameter 62 { 63 sal_uLong nSlot = ((SfxSimpleHint&)rHint).GetId(); 64 switch ( nSlot ) 65 { 66 case FID_DATACHANGED: 67 UpdateFormulas(); 68 break; 69 70 case FID_REFMODECHANGED: 71 { 72 sal_Bool bRefMode = SC_MOD()->IsFormulaMode(); 73 if (!bRefMode) 74 StopRefMode(); 75 else 76 { 77 GetSelEngine()->Reset(); 78 GetFunctionSet()->SetAnchorFlag(sal_True); 79 // AnchorFlag, damit gleich mit Control angehaengt werden kann 80 } 81 } 82 break; 83 84 case FID_KILLEDITVIEW: 85 case FID_KILLEDITVIEW_NOPAINT: 86 StopEditShell(); 87 KillEditView( nSlot == FID_KILLEDITVIEW_NOPAINT ); 88 break; 89 90 case SFX_HINT_DOCCHANGED: 91 { 92 ScDocument* pDoc = GetViewData()->GetDocument(); 93 if (!pDoc->HasTable( GetViewData()->GetTabNo() )) 94 { 95 SetTabNo(0); 96 } 97 } 98 break; 99 100 case SC_HINT_DRWLAYER_NEW: 101 MakeDrawView(); 102 break; 103 104 case SC_HINT_DOC_SAVED: 105 { 106 // beim "Save as" kann ein vorher schreibgeschuetztes Dokument 107 // bearbeitbar werden, deshalb die Layer-Locks neu (#39884#) 108 // (Invalidate etc. passiert schon vom Sfx her) 109 // #42091# bei SID_EDITDOC kommt kein SFX_HINT_TITLECHANGED, darum 110 // der eigene Hint aus DoSaveCompleted 111 //! was ist mit SFX_HINT_SAVECOMPLETED ? 112 113 UpdateLayerLocks(); 114 115 // #54891# Design-Modus bei jedem Speichern anzupassen, waere zuviel 116 // (beim Speichern unter gleichem Namen soll er unveraendert bleiben) 117 // Darum nur bei SFX_HINT_MODECHANGED (vom ViewFrame) 118 } 119 break; 120 121 case SFX_HINT_MODECHANGED: 122 // #54891#/#58510# Da man sich nicht mehr darauf verlassen kann, woher 123 // dieser Hint kommt, den Design-Modus immer dann umschalten, wenn der 124 // ReadOnly-Status sich wirklich geaendert hat: 125 126 if ( GetViewData()->GetSfxDocShell()->IsReadOnly() != bReadOnly ) 127 { 128 bReadOnly = GetViewData()->GetSfxDocShell()->IsReadOnly(); 129 130 SfxBoolItem aItem( SID_FM_DESIGN_MODE, !bReadOnly); 131 GetViewData()->GetDispatcher().Execute( SID_FM_DESIGN_MODE, SFX_CALLMODE_ASYNCHRON, 132 &aItem, 0L ); 133 134 UpdateInputContext(); 135 } 136 break; 137 138 case SC_HINT_SHOWRANGEFINDER: 139 PaintRangeFinder(); 140 break; 141 142 case SC_HINT_FORCESETTAB: 143 SetTabNo( GetViewData()->GetTabNo(), sal_True ); 144 break; 145 146 default: 147 break; 148 } 149 } 150 else if (rHint.ISA(ScPaintHint)) // neu zeichnen 151 { 152 ScPaintHint* pHint = (ScPaintHint*) &rHint; 153 sal_uInt16 nParts = pHint->GetParts(); 154 SCTAB nTab = GetViewData()->GetTabNo(); 155 if (pHint->GetStartTab() <= nTab && pHint->GetEndTab() >= nTab) 156 { 157 if (nParts & PAINT_EXTRAS) // zuerst, falls Tabelle weg ist !!! 158 if (PaintExtras()) 159 nParts = PAINT_ALL; 160 161 // if the current sheet has pending row height updates (sheet links refreshed), 162 // execute them before invalidating the window 163 GetViewData()->GetDocShell()->UpdatePendingRowHeights( GetViewData()->GetTabNo() ); 164 165 if (nParts & PAINT_SIZE) 166 RepeatResize(); //! InvalidateBorder ??? 167 if (nParts & PAINT_GRID) 168 PaintArea( pHint->GetStartCol(), pHint->GetStartRow(), 169 pHint->GetEndCol(), pHint->GetEndRow() ); 170 if (nParts & PAINT_MARKS) 171 PaintArea( pHint->GetStartCol(), pHint->GetStartRow(), 172 pHint->GetEndCol(), pHint->GetEndRow(), SC_UPDATE_MARKS ); 173 if (nParts & PAINT_LEFT) 174 PaintLeftArea( pHint->GetStartRow(), pHint->GetEndRow() ); 175 if (nParts & PAINT_TOP) 176 PaintTopArea( pHint->GetStartCol(), pHint->GetEndCol() ); 177 if (nParts & PAINT_INVERT) 178 InvertBlockMark( pHint->GetStartCol(), pHint->GetStartRow(), 179 pHint->GetEndCol(), pHint->GetEndRow() ); 180 181 // #i84689# call UpdateAllOverlays here instead of in ScTabView::PaintArea 182 if (nParts & ( PAINT_LEFT | PAINT_TOP )) // only if widths or heights changed 183 UpdateAllOverlays(); 184 185 HideNoteMarker(); 186 } 187 } 188 else if (rHint.ISA(ScEditViewHint)) // Edit-View anlegen 189 { 190 // ScEditViewHint kommt nur an aktiver View an 191 192 ScEditViewHint* pHint = (ScEditViewHint*) &rHint; 193 SCTAB nTab = GetViewData()->GetTabNo(); 194 if ( pHint->GetTab() == nTab ) 195 { 196 SCCOL nCol = pHint->GetCol(); 197 SCROW nRow = pHint->GetRow(); 198 { 199 HideNoteMarker(); 200 201 MakeEditView( pHint->GetEngine(), nCol, nRow ); 202 203 StopEditShell(); // sollte nicht gesetzt sein 204 205 ScSplitPos eActive = GetViewData()->GetActivePart(); 206 if ( GetViewData()->HasEditView(eActive) ) 207 { 208 // MakeEditView geht schief, wenn der Cursor ausserhalb des 209 // Bildschirms steht. GetEditView gibt dann eine nicht aktive 210 // View zurueck, darum die Abfrage HasEditView. 211 212 EditView* pView = GetViewData()->GetEditView(eActive); // ist nicht 0 213 214 SetEditShell(pView ,sal_True); 215 } 216 } 217 } 218 } 219 else if (rHint.ISA(ScTablesHint)) // Tabelle eingefuegt / geloescht 220 { 221 // aktuelle Tabelle zuerst holen (kann bei DeleteTab an ViewData geaendert werden) 222 SCTAB nActiveTab = GetViewData()->GetTabNo(); 223 224 const ScTablesHint& rTabHint = (const ScTablesHint&)rHint; 225 SCTAB nTab1 = rTabHint.GetTab1(); 226 SCTAB nTab2 = rTabHint.GetTab2(); 227 sal_uInt16 nId = rTabHint.GetId(); 228 switch (nId) 229 { 230 case SC_TAB_INSERTED: 231 GetViewData()->InsertTab( nTab1 ); 232 break; 233 case SC_TAB_DELETED: 234 GetViewData()->DeleteTab( nTab1 ); 235 break; 236 case SC_TAB_MOVED: 237 GetViewData()->MoveTab( nTab1, nTab2 ); 238 break; 239 case SC_TAB_COPIED: 240 GetViewData()->CopyTab( nTab1, nTab2 ); 241 break; 242 case SC_TAB_HIDDEN: 243 break; 244 default: 245 DBG_ERROR("unbekannter ScTablesHint"); 246 } 247 248 // hier keine Abfrage auf IsActive() mehr, weil die Aktion von Basic ausgehen 249 // kann und dann auch die aktive View umgeschaltet werden muss. 250 251 SCTAB nNewTab = nActiveTab; 252 bool bStayOnActiveTab = true; 253 switch (nId) 254 { 255 case SC_TAB_INSERTED: 256 if ( nTab1 <= nNewTab ) // vorher eingefuegt 257 ++nNewTab; 258 break; 259 case SC_TAB_DELETED: 260 if ( nTab1 < nNewTab ) // vorher geloescht 261 --nNewTab; 262 else if ( nTab1 == nNewTab ) // aktuelle geloescht 263 bStayOnActiveTab = false; 264 break; 265 case SC_TAB_MOVED: 266 if ( nNewTab == nTab1 ) // verschobene Tabelle 267 nNewTab = nTab2; 268 else if ( nTab1 < nTab2 ) // nach hinten verschoben 269 { 270 if ( nNewTab > nTab1 && nNewTab <= nTab2 ) // nachrueckender Bereich 271 --nNewTab; 272 } 273 else // nach vorne verschoben 274 { 275 if ( nNewTab >= nTab2 && nNewTab < nTab1 ) // nachrueckender Bereich 276 ++nNewTab; 277 } 278 break; 279 case SC_TAB_COPIED: 280 if ( nNewTab >= nTab2 ) // vorher eingefuegt 281 ++nNewTab; 282 break; 283 case SC_TAB_HIDDEN: 284 if ( nTab1 == nNewTab ) // aktuelle ausgeblendet 285 bStayOnActiveTab = false; 286 break; 287 } 288 289 ScDocument* pDoc = GetViewData()->GetDocument(); 290 if ( nNewTab >= pDoc->GetTableCount() ) 291 nNewTab = pDoc->GetTableCount() - 1; 292 293 sal_Bool bForce = !bStayOnActiveTab; 294 SetTabNo( nNewTab, bForce, sal_False, bStayOnActiveTab ); 295 } 296 else if (rHint.ISA(ScIndexHint)) 297 { 298 const ScIndexHint& rIndexHint = (const ScIndexHint&)rHint; 299 sal_uInt16 nId = rIndexHint.GetId(); 300 sal_uInt16 nIndex = rIndexHint.GetIndex(); 301 switch (nId) 302 { 303 case SC_HINT_SHOWRANGEFINDER: 304 PaintRangeFinder( nIndex ); 305 break; 306 } 307 } 308 309 SfxViewShell::Notify( rBC, rHint ); 310 } 311 312 //------------------------------------------------------------------ 313 314 void ScTabViewShell::MakeNumberInfoItem( ScDocument* pDoc, 315 ScViewData* pViewData, 316 SvxNumberInfoItem** ppItem ) 317 { 318 //------------------------------ 319 // NumberInfo-Item konstruieren: 320 //------------------------------ 321 ScBaseCell* pCell = NULL; 322 SvxNumberValueType eValType = SVX_VALUE_TYPE_UNDEFINED; 323 double nCellValue = 0; 324 String aCellString; 325 326 pDoc->GetCell( pViewData->GetCurX(), 327 pViewData->GetCurY(), 328 pViewData->GetTabNo(), 329 pCell ); 330 331 if ( pCell ) 332 { 333 switch ( pCell->GetCellType() ) 334 { 335 case CELLTYPE_VALUE: 336 { 337 nCellValue = ((ScValueCell*)pCell)->GetValue(); 338 eValType = SVX_VALUE_TYPE_NUMBER; 339 aCellString.Erase(); 340 } 341 break; 342 343 case CELLTYPE_STRING: 344 { 345 ((ScStringCell*)pCell)->GetString( aCellString ); 346 eValType = SVX_VALUE_TYPE_STRING; 347 } 348 break; 349 350 case CELLTYPE_FORMULA: 351 { 352 if ( ((ScFormulaCell*)pCell)->IsValue() ) 353 { 354 nCellValue = ((ScFormulaCell*)pCell)->GetValue(); 355 eValType = SVX_VALUE_TYPE_NUMBER; 356 } 357 else 358 { 359 nCellValue = 0; 360 eValType = SVX_VALUE_TYPE_UNDEFINED; 361 } 362 aCellString.Erase(); 363 } 364 break; 365 366 default: 367 nCellValue = 0; 368 eValType = SVX_VALUE_TYPE_UNDEFINED; 369 aCellString.Erase(); 370 } 371 } 372 else // Zelle noch leer (== nicht erzeugt) 373 { 374 nCellValue = 0; 375 eValType = SVX_VALUE_TYPE_UNDEFINED; 376 aCellString.Erase(); 377 } 378 379 switch ( eValType ) 380 { 381 case SVX_VALUE_TYPE_STRING: 382 *ppItem = new SvxNumberInfoItem( 383 pDoc->GetFormatTable(), 384 aCellString, 385 SID_ATTR_NUMBERFORMAT_INFO ); 386 break; 387 388 case SVX_VALUE_TYPE_NUMBER: 389 *ppItem = new SvxNumberInfoItem( 390 pDoc->GetFormatTable(), 391 nCellValue, 392 SID_ATTR_NUMBERFORMAT_INFO ); 393 break; 394 395 case SVX_VALUE_TYPE_UNDEFINED: 396 default: 397 *ppItem = new SvxNumberInfoItem( 398 pDoc->GetFormatTable(), 399 (const sal_uInt16) 400 SID_ATTR_NUMBERFORMAT_INFO ); 401 } 402 } 403 404 //------------------------------------------------------------------ 405 406 void ScTabViewShell::UpdateNumberFormatter( 407 ScDocument* pDoc, 408 const SvxNumberInfoItem& rInfoItem ) 409 { 410 const sal_uInt32 nDelCount = rInfoItem.GetDelCount(); 411 412 if ( nDelCount > 0 ) 413 { 414 const sal_uInt32* pDelArr = rInfoItem.GetDelArray(); 415 416 for ( sal_uInt16 i=0; i<nDelCount; i++ ) 417 rInfoItem.GetNumberFormatter()->DeleteEntry( pDelArr[i] ); 418 } 419 420 // sollte besser UpdateNumberFormats() heissen ? 421 pDoc->DeleteNumberFormat( rInfoItem.GetDelArray(), 422 rInfoItem.GetDelCount() ); 423 } 424 425 426 427 428 429 430