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