1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 2 /* 3 * This file is part of the LibreOffice project. 4 * 5 * This Source Code Form is subject to the terms of the Mozilla Public 6 * License, v. 2.0. If a copy of the MPL was not distributed with this 7 * file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 * 9 * This file incorporates work covered by the following license notice: 10 * 11 * Licensed to the Apache Software Foundation (ASF) under one or more 12 * contributor license agreements. See the NOTICE file distributed 13 * with this work for additional information regarding copyright 14 * ownership. The ASF licenses this file to you under the Apache 15 * License, Version 2.0 (the "License"); you may not use this file 16 * except in compliance with the License. You may obtain a copy of 17 * the License at http://www.apache.org/licenses/LICENSE-2.0 . 18 */ 19 20 #include <com/sun/star/table/BorderLineStyle.hpp> 21 22 #include <comphelper/lok.hxx> 23 #include <editeng/boxitem.hxx> 24 #include <o3tl/temporary.hxx> 25 #include <sfx2/bindings.hxx> 26 #include <sfx2/request.hxx> 27 #include <sfx2/sfxdlg.hxx> 28 #include <sfx2/sidebar/Sidebar.hxx> 29 #include <sfx2/viewfrm.hxx> 30 #include <svl/ilstitem.hxx> 31 #include <svl/numformat.hxx> 32 #include <svl/zformat.hxx> 33 #include <svl/int64item.hxx> 34 #include <svl/srchitem.hxx> 35 #include <svl/srchdefs.hxx> 36 #include <svl/stritem.hxx> 37 #include <svl/whiter.hxx> 38 #include <svx/numinf.hxx> 39 #include <svx/zoomslideritem.hxx> 40 41 #include <global.hxx> 42 #include <appoptio.hxx> 43 #include <attrib.hxx> 44 #include <cellform.hxx> 45 #include <cellvalue.hxx> 46 #include <compiler.hxx> 47 #include <docsh.hxx> 48 #include <document.hxx> 49 #include <formulacell.hxx> 50 #include <globstr.hrc> 51 #include <inputhdl.hxx> 52 #include <inputwin.hxx> 53 #include <markdata.hxx> 54 #include <patattr.hxx> 55 #include <sc.hrc> 56 #include <scabstdlg.hxx> 57 #include <scitems.hxx> 58 #include <scmod.hxx> 59 #include <scresid.hxx> 60 #include <stlpool.hxx> 61 #include <tabvwsh.hxx> 62 #include <tokenarray.hxx> 63 #include <viewdata.hxx> 64 65 #include <memory> 66 67 using namespace com::sun::star; 68 69 bool ScTabViewShell::GetFunction( OUString& rFuncStr, FormulaError nErrCode ) 70 { 71 sal_uInt32 nFuncs = SC_MOD()->GetAppOptions().GetStatusFunc(); 72 ScViewData& rViewData = GetViewData(); 73 ScMarkData& rMark = rViewData.GetMarkData(); 74 bool bIgnoreError = (rMark.IsMarked() || rMark.IsMultiMarked()); 75 bool bFirst = true; 76 for ( sal_uInt16 nFunc = 0; nFunc < 32; nFunc++ ) 77 { 78 if ( !(nFuncs & (1U << nFunc)) ) 79 continue; 80 ScSubTotalFunc eFunc = static_cast<ScSubTotalFunc>(nFunc); 81 82 if (bIgnoreError && (eFunc == SUBTOTAL_FUNC_CNT || eFunc == SUBTOTAL_FUNC_CNT2)) 83 nErrCode = FormulaError::NONE; 84 85 if (nErrCode != FormulaError::NONE) 86 { 87 rFuncStr = ScGlobal::GetLongErrorString(nErrCode); 88 return true; 89 } 90 91 TranslateId pGlobStrId; 92 switch (eFunc) 93 { 94 case SUBTOTAL_FUNC_AVE: pGlobStrId = STR_FUN_TEXT_AVG; break; 95 case SUBTOTAL_FUNC_CNT: pGlobStrId = STR_FUN_TEXT_COUNT; break; 96 case SUBTOTAL_FUNC_CNT2: pGlobStrId = STR_FUN_TEXT_COUNT2; break; 97 case SUBTOTAL_FUNC_MAX: pGlobStrId = STR_FUN_TEXT_MAX; break; 98 case SUBTOTAL_FUNC_MIN: pGlobStrId = STR_FUN_TEXT_MIN; break; 99 case SUBTOTAL_FUNC_SUM: pGlobStrId = STR_FUN_TEXT_SUM; break; 100 case SUBTOTAL_FUNC_SELECTION_COUNT: pGlobStrId = STR_FUN_TEXT_SELECTION_COUNT; break; 101 102 default: 103 { 104 // added to avoid warnings 105 } 106 } 107 if (pGlobStrId) 108 { 109 ScDocument& rDoc = rViewData.GetDocument(); 110 SCCOL nPosX = rViewData.GetCurX(); 111 SCROW nPosY = rViewData.GetCurY(); 112 SCTAB nTab = rViewData.GetTabNo(); 113 114 OUString aStr = ScResId(pGlobStrId) + ": "; 115 116 ScAddress aCursor( nPosX, nPosY, nTab ); 117 double nVal; 118 if ( rDoc.GetSelectionFunction( eFunc, aCursor, rMark, nVal ) ) 119 { 120 if ( nVal == 0.0 ) 121 aStr += "0"; 122 else 123 { 124 // Number in the standard format, the other on the cursor position 125 SvNumberFormatter* pFormatter = rDoc.GetFormatTable(); 126 sal_uInt32 nNumFmt = 0; 127 if ( eFunc != SUBTOTAL_FUNC_CNT && eFunc != SUBTOTAL_FUNC_CNT2 && eFunc != SUBTOTAL_FUNC_SELECTION_COUNT) 128 { 129 // number format from attributes or formula 130 nNumFmt = rDoc.GetNumberFormat( nPosX, nPosY, nTab ); 131 // If the number format is time (without date) and the 132 // result is not within 24 hours, use a duration 133 // format. Summing date+time doesn't make much sense 134 // otherwise but we also don't want to display duration 135 // for a single date+time value. 136 if (nVal < 0.0 || nVal >= 1.0) 137 { 138 const SvNumberformat* pFormat = pFormatter->GetEntry(nNumFmt); 139 if (pFormat && (pFormat->GetType() == SvNumFormatType::TIME)) 140 nNumFmt = pFormatter->GetTimeFormat( nVal, pFormat->GetLanguage(), true); 141 } 142 } 143 144 OUString aValStr; 145 const Color* pDummy; 146 pFormatter->GetOutputString( nVal, nNumFmt, aValStr, &pDummy ); 147 aStr += aValStr; 148 } 149 } 150 if ( bFirst ) 151 { 152 rFuncStr += aStr; 153 bFirst = false; 154 } 155 else 156 rFuncStr += "; " + aStr; 157 } 158 } 159 160 return !rFuncStr.isEmpty(); 161 } 162 163 // Functions that are disabled, depending on the selection 164 // Default: 165 // SID_DELETE, 166 // SID_DELETE_CONTENTS, 167 // FID_DELETE_CELL 168 // FID_VALIDATION 169 170 void ScTabViewShell::GetState( SfxItemSet& rSet ) 171 { 172 ScViewData& rViewData = GetViewData(); 173 ScDocument& rDoc = rViewData.GetDocument(); 174 ScDocShell* pDocShell = rViewData.GetDocShell(); 175 ScMarkData& rMark = rViewData.GetMarkData(); 176 SCCOL nPosX = rViewData.GetCurX(); 177 SCROW nPosY = rViewData.GetCurY(); 178 SCTAB nTab = rViewData.GetTabNo(); 179 180 SfxViewFrame* pThisFrame = GetViewFrame(); 181 bool bOle = GetViewFrame()->GetFrame().IsInPlace(); 182 183 SCTAB nTabSelCount = rMark.GetSelectCount(); 184 185 SfxWhichIter aIter(rSet); 186 sal_uInt16 nWhich = aIter.FirstWhich(); 187 188 while ( nWhich ) 189 { 190 switch ( nWhich ) 191 { 192 case FID_CHG_COMMENT: 193 { 194 ScDocShell* pDocSh = GetViewData().GetDocShell(); 195 ScAddress aPos( nPosX, nPosY, nTab ); 196 if ( pDocSh->IsReadOnly() || !pDocSh->GetChangeAction(aPos) || pDocSh->IsDocShared() ) 197 rSet.DisableItem( nWhich ); 198 } 199 break; 200 201 case SID_OPENDLG_EDIT_PRINTAREA: 202 case SID_ADD_PRINTAREA: 203 case SID_DEFINE_PRINTAREA: 204 { 205 if ( pDocShell && pDocShell->IsDocShared() ) 206 { 207 rSet.DisableItem( nWhich ); 208 } 209 } 210 break; 211 212 case SID_DELETE_PRINTAREA: 213 if ( pDocShell && pDocShell->IsDocShared() ) 214 { 215 rSet.DisableItem( nWhich ); 216 } 217 else if (rDoc.IsPrintEntireSheet(nTab)) 218 rSet.DisableItem(nWhich); 219 break; 220 221 case SID_STATUS_PAGESTYLE: 222 case SID_HFEDIT: 223 GetViewData().GetDocShell()->GetStatePageStyle( rSet, nTab ); 224 break; 225 226 case SID_SEARCH_ITEM: 227 { 228 SvxSearchItem aItem(ScGlobal::GetSearchItem()); // make a copy. 229 // Search on current selection if a range is marked. 230 aItem.SetSelection(rMark.IsMarked()); 231 rSet.Put(aItem); 232 break; 233 } 234 235 case SID_SEARCH_OPTIONS: 236 { 237 // Anything goes 238 SearchOptionFlags nOptions = SearchOptionFlags::ALL; 239 240 // No replacement if ReadOnly 241 if (GetViewData().GetDocShell()->IsReadOnly()) 242 nOptions &= ~SearchOptionFlags( SearchOptionFlags::REPLACE | SearchOptionFlags::REPLACE_ALL ); 243 rSet.Put( SfxUInt16Item( nWhich, static_cast<sal_uInt16>(nOptions) ) ); 244 } 245 break; 246 247 case SID_CURRENTCELL: 248 { 249 ScAddress aScAddress( GetViewData().GetCurX(), GetViewData().GetCurY(), 0 ); 250 OUString aAddr(aScAddress.Format(ScRefFlags::ADDR_ABS, nullptr, rDoc.GetAddressConvention())); 251 SfxStringItem aPosItem( SID_CURRENTCELL, aAddr ); 252 253 rSet.Put( aPosItem ); 254 } 255 break; 256 257 case SID_CURRENTTAB: 258 // Table for Basic is 1-based 259 rSet.Put( SfxUInt16Item( nWhich, static_cast<sal_uInt16>(GetViewData().GetTabNo()) + 1 ) ); 260 break; 261 262 case SID_CURRENTDOC: 263 rSet.Put( SfxStringItem( nWhich, GetViewData().GetDocShell()->GetTitle() ) ); 264 break; 265 266 case FID_TOGGLEINPUTLINE: 267 { 268 sal_uInt16 nId = ScInputWindowWrapper::GetChildWindowId(); 269 270 if ( pThisFrame->KnowsChildWindow( nId ) ) 271 { 272 SfxChildWindow* pWnd = pThisFrame->GetChildWindow( nId ); 273 rSet.Put( SfxBoolItem( nWhich, pWnd != nullptr ) ); 274 } 275 else 276 rSet.DisableItem( nWhich ); 277 } 278 break; 279 280 case FID_DEL_MANUALBREAKS: 281 if (!rDoc.HasManualBreaks(nTab)) 282 rSet.DisableItem( nWhich ); 283 break; 284 285 case FID_RESET_PRINTZOOM: 286 { 287 // disable if already set to default 288 289 OUString aStyleName = rDoc.GetPageStyle( nTab ); 290 ScStyleSheetPool* pStylePool = rDoc.GetStyleSheetPool(); 291 SfxStyleSheetBase* pStyleSheet = pStylePool->Find( aStyleName, 292 SfxStyleFamily::Page ); 293 OSL_ENSURE( pStyleSheet, "PageStyle not found" ); 294 if ( pStyleSheet ) 295 { 296 SfxItemSet& rStyleSet = pStyleSheet->GetItemSet(); 297 sal_uInt16 nScale = rStyleSet.Get(ATTR_PAGE_SCALE).GetValue(); 298 sal_uInt16 nPages = rStyleSet.Get(ATTR_PAGE_SCALETOPAGES).GetValue(); 299 if ( nScale == 100 && nPages == 0 ) 300 rSet.DisableItem( nWhich ); 301 } 302 } 303 break; 304 305 case SID_ZOOM_IN: 306 { 307 const Fraction& rZoomY = GetViewData().GetZoomY(); 308 tools::Long nZoom = tools::Long(rZoomY * 100); 309 if (nZoom >= tools::Long(MAXZOOM)) 310 rSet.DisableItem(nWhich); 311 } 312 break; 313 case SID_ZOOM_OUT: 314 { 315 const Fraction& rZoomY = GetViewData().GetZoomY(); 316 tools::Long nZoom = tools::Long(rZoomY * 100); 317 if (nZoom <= tools::Long(MINZOOM)) 318 rSet.DisableItem(nWhich); 319 } 320 break; 321 322 case FID_SCALE: 323 case SID_ATTR_ZOOM: 324 if ( bOle ) 325 rSet.DisableItem( nWhich ); 326 else 327 { 328 const Fraction& rOldY = GetViewData().GetZoomY(); 329 sal_uInt16 nZoom = static_cast<sal_uInt16>(tools::Long( rOldY * 100 )); 330 rSet.Put( SvxZoomItem( SvxZoomType::PERCENT, nZoom, nWhich ) ); 331 } 332 break; 333 334 case SID_ATTR_ZOOMSLIDER: 335 { 336 if ( bOle ) 337 rSet.DisableItem( nWhich ); 338 else 339 { 340 const Fraction& rOldY = GetViewData().GetZoomY(); 341 sal_uInt16 nCurrentZoom = static_cast<sal_uInt16>(tools::Long( rOldY * 100 )); 342 343 if( nCurrentZoom ) 344 { 345 SvxZoomSliderItem aZoomSliderItem( nCurrentZoom, MINZOOM, MAXZOOM, SID_ATTR_ZOOMSLIDER ); 346 aZoomSliderItem.AddSnappingPoint( 100 ); 347 rSet.Put( aZoomSliderItem ); 348 } 349 } 350 } 351 break; 352 353 case FID_FUNCTION_BOX: 354 { 355 const bool bBoxOpen = ::sfx2::sidebar::Sidebar::IsPanelVisible(u"ScFunctionsPanel", 356 pThisFrame->GetFrame().GetFrameInterface()); 357 rSet.Put(SfxBoolItem(nWhich, bBoxOpen)); 358 break; 359 } 360 361 case FID_TOGGLESYNTAX: 362 rSet.Put(SfxBoolItem(nWhich, GetViewData().IsSyntaxMode())); 363 break; 364 365 case FID_TOGGLEHEADERS: 366 rSet.Put(SfxBoolItem(nWhich, GetViewData().IsHeaderMode())); 367 break; 368 369 case FID_TOGGLEFORMULA: 370 { 371 const ScViewOptions& rOpts = rViewData.GetOptions(); 372 bool bFormulaMode = rOpts.GetOption( VOPT_FORMULAS ); 373 rSet.Put(SfxBoolItem(nWhich, bFormulaMode )); 374 } 375 break; 376 377 case FID_NORMALVIEWMODE: 378 case FID_PAGEBREAKMODE: 379 // always handle both slots - they exclude each other 380 if ( bOle ) 381 { 382 rSet.DisableItem( FID_NORMALVIEWMODE ); 383 rSet.DisableItem( FID_PAGEBREAKMODE ); 384 } 385 else 386 { 387 rSet.Put(SfxBoolItem(FID_NORMALVIEWMODE, !GetViewData().IsPagebreakMode())); 388 rSet.Put(SfxBoolItem(FID_PAGEBREAKMODE, GetViewData().IsPagebreakMode())); 389 } 390 break; 391 392 case FID_PROTECT_DOC: 393 { 394 if ( pDocShell && pDocShell->IsDocShared() ) 395 { 396 rSet.DisableItem( nWhich ); 397 } 398 else 399 { 400 rSet.Put( SfxBoolItem( nWhich, rDoc.IsDocProtected() ) ); 401 } 402 } 403 break; 404 405 case FID_PROTECT_TABLE: 406 { 407 if ( pDocShell && pDocShell->IsDocShared() ) 408 { 409 rSet.DisableItem( nWhich ); 410 } 411 else 412 { 413 rSet.Put( SfxBoolItem( nWhich, rDoc.IsTabProtected( nTab ) ) ); 414 } 415 } 416 break; 417 418 case SID_AUTO_OUTLINE: 419 { 420 if (rDoc.GetChangeTrack()!=nullptr || GetViewData().IsMultiMarked()) 421 { 422 rSet.DisableItem( nWhich ); 423 } 424 } 425 break; 426 427 case SID_OUTLINE_DELETEALL: 428 { 429 SCTAB nOlTab = GetViewData().GetTabNo(); 430 ScOutlineTable* pOlTable = rDoc.GetOutlineTable( nOlTab ); 431 if (pOlTable == nullptr) 432 rSet.DisableItem( nWhich ); 433 } 434 break; 435 436 case SID_WINDOW_SPLIT: 437 rSet.Put(SfxBoolItem(nWhich, 438 rViewData.GetHSplitMode() == SC_SPLIT_NORMAL || 439 rViewData.GetVSplitMode() == SC_SPLIT_NORMAL )); 440 break; 441 442 case SID_WINDOW_FIX: 443 if(!comphelper::LibreOfficeKit::isActive()) 444 { 445 rSet.Put(SfxBoolItem(nWhich, 446 rViewData.GetHSplitMode() == SC_SPLIT_FIX || 447 rViewData.GetVSplitMode() == SC_SPLIT_FIX )); 448 } 449 else 450 { 451 rSet.Put(SfxBoolItem(nWhich, 452 rViewData.GetLOKSheetFreezeIndex(true) > 0 || 453 rViewData.GetLOKSheetFreezeIndex(false) > 0 )); 454 } 455 break; 456 457 case SID_WINDOW_FIX_COL: 458 case SID_WINDOW_FIX_ROW: 459 { 460 bool bIsCol = (nWhich == SID_WINDOW_FIX_COL); 461 sal_Int32 nFreezeIndex = rViewData.GetLOKSheetFreezeIndex(bIsCol); 462 rSet.Put(SfxInt32Item(nWhich, nFreezeIndex)); 463 } 464 break; 465 466 case FID_CHG_SHOW: 467 { 468 if ( rDoc.GetChangeTrack() == nullptr || ( pDocShell && pDocShell->IsDocShared() ) ) 469 rSet.DisableItem( nWhich ); 470 } 471 break; 472 case FID_CHG_ACCEPT: 473 { 474 if( 475 ( !rDoc.GetChangeTrack() && !pThisFrame->HasChildWindow(FID_CHG_ACCEPT) ) 476 || 477 ( pDocShell && pDocShell->IsDocShared() ) 478 ) 479 { 480 rSet.DisableItem( nWhich); 481 } 482 else 483 { 484 rSet.Put(SfxBoolItem(FID_CHG_ACCEPT, 485 pThisFrame->HasChildWindow(FID_CHG_ACCEPT))); 486 } 487 } 488 break; 489 490 case SID_FORMATPAGE: 491 // in protected tables 492 if ( pDocShell && ( pDocShell->IsReadOnly() || pDocShell->IsDocShared() ) ) 493 rSet.DisableItem( nWhich ); 494 break; 495 496 case SID_PRINTPREVIEW: 497 // Toggle slot needs a State 498 rSet.Put( SfxBoolItem( nWhich, false ) ); 499 break; 500 501 case SID_READONLY_MODE: 502 rSet.Put( SfxBoolItem( nWhich, GetViewData().GetDocShell()->IsReadOnly() ) ); 503 break; 504 505 case FID_TAB_DESELECTALL: 506 if ( nTabSelCount == 1 ) 507 rSet.DisableItem( nWhich ); // enabled only if several sheets are selected 508 break; 509 510 case FID_TOGGLEHIDDENCOLROW: 511 const svtools::ColorConfig& rColorCfg = SC_MOD()->GetColorConfig(); 512 rSet.Put( SfxBoolItem( nWhich, rColorCfg.GetColorValue(svtools::CALCHIDDENROWCOL).bIsVisible) ); 513 break; 514 515 } // switch ( nWitch ) 516 nWhich = aIter.NextWhich(); 517 } // while ( nWitch ) 518 } 519 520 void ScTabViewShell::ExecuteCellFormatDlg(SfxRequest& rReq, const OString &rName) 521 { 522 ScDocument& rDoc = GetViewData().GetDocument(); 523 524 std::shared_ptr<SvxBoxItem> aLineOuter(std::make_shared<SvxBoxItem>(ATTR_BORDER)); 525 std::shared_ptr<SvxBoxInfoItem> aLineInner(std::make_shared<SvxBoxInfoItem>(ATTR_BORDER_INNER)); 526 527 const ScPatternAttr* pOldAttrs = GetSelectionPattern(); 528 529 auto pOldSet = std::make_shared<SfxItemSet>(pOldAttrs->GetItemSet()); 530 531 pOldSet->MergeRange(XATTR_FILLSTYLE, XATTR_FILLCOLOR); 532 533 pOldSet->MergeRange(SID_ATTR_BORDER_STYLES, SID_ATTR_BORDER_DEFAULT_WIDTH); 534 535 // We only allow these border line types. 536 std::vector<sal_Int32> aBorderStyles{ 537 table::BorderLineStyle::SOLID, 538 table::BorderLineStyle::DOTTED, 539 table::BorderLineStyle::DASHED, 540 table::BorderLineStyle::FINE_DASHED, 541 table::BorderLineStyle::DASH_DOT, 542 table::BorderLineStyle::DASH_DOT_DOT, 543 table::BorderLineStyle::DOUBLE_THIN }; 544 545 pOldSet->Put(SfxIntegerListItem(SID_ATTR_BORDER_STYLES, std::move(aBorderStyles))); 546 547 // Set the default border width to 0.75 points. 548 SfxInt64Item aBorderWidthItem(SID_ATTR_BORDER_DEFAULT_WIDTH, 75); 549 pOldSet->Put(aBorderWidthItem); 550 551 // Get border items and put them in the set: 552 GetSelectionFrame( aLineOuter, aLineInner ); 553 554 //Fix border incorrect for RTL fdo#62399 555 if( rDoc.IsLayoutRTL( GetViewData().GetTabNo() ) ) 556 { 557 std::unique_ptr<SvxBoxItem> aNewFrame(aLineOuter->Clone()); 558 std::unique_ptr<SvxBoxInfoItem> aTempInfo(aLineInner->Clone()); 559 560 if ( aLineInner->IsValid(SvxBoxInfoItemValidFlags::LEFT) ) 561 aNewFrame->SetLine( aLineOuter->GetLeft(), SvxBoxItemLine::RIGHT ); 562 if ( aLineInner->IsValid(SvxBoxInfoItemValidFlags::RIGHT) ) 563 aNewFrame->SetLine( aLineOuter->GetRight(), SvxBoxItemLine::LEFT ); 564 565 aLineInner->SetValid( SvxBoxInfoItemValidFlags::LEFT, aTempInfo->IsValid(SvxBoxInfoItemValidFlags::RIGHT)); 566 aLineInner->SetValid( SvxBoxInfoItemValidFlags::RIGHT, aTempInfo->IsValid(SvxBoxInfoItemValidFlags::LEFT)); 567 568 pOldSet->Put( std::move(aNewFrame) ); 569 } 570 else 571 { 572 pOldSet->Put( *aLineOuter ); 573 } 574 575 pOldSet->Put( *aLineInner ); 576 577 // Generate NumberFormat Value from Value and Language and box it. 578 pOldSet->Put( SfxUInt32Item( ATTR_VALUE_FORMAT, 579 pOldAttrs->GetNumberFormat( rDoc.GetFormatTable() ) ) ); 580 581 std::unique_ptr<SvxNumberInfoItem> pNumberInfoItem = MakeNumberInfoItem(rDoc, GetViewData()); 582 pOldSet->MergeRange( SID_ATTR_NUMBERFORMAT_INFO, SID_ATTR_NUMBERFORMAT_INFO ); 583 pOldSet->Put( std::move(pNumberInfoItem) ); 584 585 bInFormatDialog = true; 586 ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create(); 587 588 VclPtr<SfxAbstractTabDialog> pDlg(pFact->CreateScAttrDlg(GetFrameWeld(), pOldSet.get())); 589 590 if (!rName.isEmpty()) 591 pDlg->SetCurPageId(rName); 592 593 auto pRequest = std::make_shared<SfxRequest>(rReq); 594 rReq.Ignore(); // the 'old' request is not relevant any more 595 596 pDlg->StartExecuteAsync([pDlg, pOldSet, pRequest, this](sal_Int32 nResult){ 597 bInFormatDialog = false; 598 599 if ( nResult == RET_OK ) 600 { 601 const SfxItemSet* pOutSet = pDlg->GetOutputItemSet(); 602 if(const SvxNumberInfoItem* pItem = pOutSet->GetItemIfSet(SID_ATTR_NUMBERFORMAT_INFO)) 603 { 604 UpdateNumberFormatter(*pItem); 605 } 606 607 ApplyAttributes(pOutSet, pOldSet.get()); 608 609 pRequest->Done(*pOutSet); 610 } 611 612 pDlg->disposeOnce(); 613 }); 614 } 615 616 bool ScTabViewShell::IsRefInputMode() const 617 { 618 ScModule* pScMod = SC_MOD(); 619 if ( pScMod ) 620 { 621 if( pScMod->IsRefDialogOpen() ) 622 return pScMod->IsFormulaMode(); 623 if( pScMod->IsFormulaMode() ) 624 { 625 ScInputHandler* pHdl = pScMod->GetInputHdl(); 626 if ( pHdl ) 627 { 628 OUString aString = pHdl->GetEditString(); 629 if ( !pHdl->GetSelIsRef() && aString.getLength() > 1 && 630 ( aString[0] == '+' || aString[0] == '-' ) ) 631 { 632 const ScViewData& rViewData = GetViewData(); 633 ScDocument& rDoc = rViewData.GetDocument(); 634 const ScAddress aPos( rViewData.GetCurPos() ); 635 ScCompiler aComp( rDoc, aPos, rDoc.GetGrammar() ); 636 aComp.SetCloseBrackets( false ); 637 std::unique_ptr<ScTokenArray> pArr(aComp.CompileString(aString)); 638 if ( pArr && pArr->MayReferenceFollow() ) 639 { 640 return true; 641 } 642 } 643 else 644 { 645 return true; 646 } 647 } 648 } 649 } 650 651 return false; 652 } 653 654 void ScTabViewShell::ExecuteInputDirect() 655 { 656 if ( !IsRefInputMode() ) 657 { 658 ScModule* pScMod = SC_MOD(); 659 if ( pScMod ) 660 { 661 pScMod->InputEnterHandler(); 662 } 663 } 664 } 665 666 void ScTabViewShell::UpdateInputHandler( bool bForce /* = sal_False */, bool bStopEditing /* = sal_True */ ) 667 { 668 ScInputHandler* pHdl = mpInputHandler ? mpInputHandler.get() : SC_MOD()->GetInputHdl(); 669 670 if ( pHdl ) 671 { 672 OUString aString; 673 const EditTextObject* pObject = nullptr; 674 ScViewData& rViewData = GetViewData(); 675 ScDocument& rDoc = rViewData.GetDocument(); 676 SCCOL nPosX = rViewData.GetCurX(); 677 SCROW nPosY = rViewData.GetCurY(); 678 SCTAB nTab = rViewData.GetTabNo(); 679 SCTAB nStartTab = 0; 680 SCTAB nEndTab = 0; 681 SCCOL nStartCol = 0; 682 SCROW nStartRow = 0; 683 SCCOL nEndCol = 0; 684 SCROW nEndRow = 0; 685 ScAddress aPos = rViewData.GetCurPos(); 686 687 rViewData.GetSimpleArea( nStartCol, nStartRow, nStartTab, 688 nEndCol, nEndRow, nEndTab ); 689 690 PutInOrder( nStartCol, nEndCol ); 691 PutInOrder( nStartRow, nEndRow ); 692 PutInOrder( nStartTab, nEndTab ); 693 694 bool bHideFormula = false; 695 bool bHideAll = false; 696 697 if (rDoc.IsTabProtected(nTab)) 698 { 699 const ScProtectionAttr* pProt = rDoc.GetAttr( nPosX,nPosY,nTab, 700 ATTR_PROTECTION); 701 bHideFormula = pProt->GetHideFormula(); 702 bHideAll = pProt->GetHideCell(); 703 } 704 705 if (!bHideAll) 706 { 707 ScRefCellValue rCell(rDoc, aPos); 708 if (rCell.getType() == CELLTYPE_FORMULA) 709 { 710 if (!bHideFormula) 711 aString = rCell.getFormula()->GetFormula(); 712 } 713 else if (rCell.getType() == CELLTYPE_EDIT) 714 { 715 pObject = rCell.getEditText(); 716 } 717 else 718 { 719 SvNumberFormatter* pFormatter = rDoc.GetFormatTable(); 720 sal_uInt32 nNumFmt = rDoc.GetNumberFormat( aPos ); 721 722 aString = ScCellFormat::GetInputString( rCell, nNumFmt, *pFormatter, rDoc ); 723 if (rCell.getType() == CELLTYPE_STRING) 724 { 725 // Put a ' in front if necessary, so that the string is not 726 // unintentionally interpreted as a number, and to show the 727 // user that it is a string (#35060#). 728 //! also for numberformat "Text"? -> then remove when editing 729 if ( pFormatter->IsNumberFormat(aString, nNumFmt, o3tl::temporary(double())) ) 730 aString = "'" + aString; 731 } 732 } 733 } 734 735 ScInputHdlState aState( ScAddress( nPosX, nPosY, nTab ), 736 ScAddress( nStartCol, nStartRow, nTab ), 737 ScAddress( nEndCol, nEndRow, nTab ), 738 aString, 739 pObject ); 740 741 // if using the view's local input handler, this view can always be set 742 // as current view inside NotifyChange. 743 ScTabViewShell* pSourceSh = mpInputHandler ? this : nullptr; 744 745 pHdl->NotifyChange( &aState, bForce, pSourceSh, bStopEditing ); 746 } 747 748 SfxBindings& rBindings = GetViewFrame()->GetBindings(); 749 rBindings.Invalidate( SID_STATUS_SUM ); // always together with the input row 750 rBindings.Invalidate( SID_ATTR_SIZE ); 751 rBindings.Invalidate( SID_TABLE_CELL ); 752 } 753 754 void ScTabViewShell::UpdateInputHandlerCellAdjust( SvxCellHorJustify eJust ) 755 { 756 if( ScInputHandler* pHdl = mpInputHandler ? mpInputHandler.get() : SC_MOD()->GetInputHdl() ) 757 pHdl->UpdateCellAdjust( eJust ); 758 } 759 760 void ScTabViewShell::ExecuteSave( SfxRequest& rReq ) 761 { 762 // only SID_SAVEDOC / SID_SAVEASDOC 763 bool bCommitChanges = true; 764 const SfxItemSet* pReqArgs = rReq.GetArgs(); 765 const SfxPoolItem* pItem; 766 767 if (pReqArgs && pReqArgs->HasItem(FN_PARAM_1, &pItem)) 768 bCommitChanges = !static_cast<const SfxBoolItem*>(pItem)->GetValue(); 769 770 // Finish entering unless 'DontTerminateEdit' is specified, even if a formula is being processed 771 if (bCommitChanges) 772 { 773 bool bLOKActive = comphelper::LibreOfficeKit::isActive(); 774 775 // Disable error dialog box when about to save in lok mode as 776 // this ultimately invokes SvpSalInstance::DoYield() when we want 777 // to save immediately without committing any erroneous input in possibly 778 // a cell with validation rules. After save is complete the user 779 // can continue editing. 780 SC_MOD()->InputEnterHandler(ScEnterMode::NORMAL, bLOKActive /* bBeforeSavingInLOK */); 781 782 if (bLOKActive) 783 { 784 // Normally this isn't needed, but in Calc when editing a cell formula 785 // and manually saving (without changing cells or hitting enter), while 786 // InputEnterHandler will mark the doc as modified (when it is), because 787 // we will save the doc immediately afterwards, the modified state event 788 // is clobbered. To avoid that, we need to update SID_DOC_MODIFIED so that 789 // a possible state of "true" after "InputEnterHandler" will be sent 790 // as a notification. It is important that the notification goes through 791 // normal process (cache) rather than directly notifying the views. 792 // Otherwise, because there is a previous state of "false" in cache, the 793 // "false" state after saving will be ignored. 794 // This will work only if .uno:ModifiedStatus message will be removed from 795 // the mechanism that keeps in the message queue only last message of 796 // a particular status even if the values are different. 797 GetViewData().GetDocShell()->GetViewBindings()->Update(SID_DOC_MODIFIED); 798 } 799 } 800 801 if ( GetViewData().GetDocShell()->IsDocShared() ) 802 { 803 GetViewData().GetDocShell()->SetDocumentModified(); 804 } 805 806 // otherwise as normal 807 GetViewData().GetDocShell()->ExecuteSlot( rReq ); 808 } 809 810 void ScTabViewShell::GetSaveState( SfxItemSet& rSet ) 811 { 812 SfxShell* pDocSh = GetViewData().GetDocShell(); 813 814 SfxWhichIter aIter(rSet); 815 sal_uInt16 nWhich = aIter.FirstWhich(); 816 while( nWhich ) 817 { 818 if ( nWhich != SID_SAVEDOC || !GetViewData().GetDocShell()->IsDocShared() ) 819 { 820 // get state from DocShell 821 pDocSh->GetSlotState( nWhich, nullptr, &rSet ); 822 } 823 nWhich = aIter.NextWhich(); 824 } 825 } 826 827 void ScTabViewShell::ExecDrawOpt( const SfxRequest& rReq ) 828 { 829 ScViewOptions aViewOptions = GetViewData().GetOptions(); 830 ScGridOptions aGridOptions = aViewOptions.GetGridOptions(); 831 832 SfxBindings& rBindings = GetViewFrame()->GetBindings(); 833 const SfxItemSet* pArgs = rReq.GetArgs(); 834 const SfxPoolItem* pItem; 835 sal_uInt16 nSlotId = rReq.GetSlot(); 836 switch (nSlotId) 837 { 838 case SID_GRID_VISIBLE: 839 if ( pArgs && pArgs->GetItemState(nSlotId,true,&pItem) == SfxItemState::SET ) 840 { 841 aGridOptions.SetGridVisible( static_cast<const SfxBoolItem*>(pItem)->GetValue() ); 842 aViewOptions.SetGridOptions(aGridOptions); 843 rBindings.Invalidate(SID_GRID_VISIBLE); 844 } 845 break; 846 847 case SID_GRID_USE: 848 if ( pArgs && pArgs->GetItemState(nSlotId,true,&pItem) == SfxItemState::SET ) 849 { 850 aGridOptions.SetUseGridSnap( static_cast<const SfxBoolItem*>(pItem)->GetValue() ); 851 aViewOptions.SetGridOptions(aGridOptions); 852 rBindings.Invalidate(SID_GRID_USE); 853 } 854 break; 855 856 case SID_HELPLINES_MOVE: 857 if ( pArgs && pArgs->GetItemState(nSlotId,true,&pItem) == SfxItemState::SET ) 858 { 859 aViewOptions.SetOption( VOPT_HELPLINES, static_cast<const SfxBoolItem*>(pItem)->GetValue() ); 860 rBindings.Invalidate(SID_HELPLINES_MOVE); 861 } 862 break; 863 } 864 865 GetViewData().SetOptions(aViewOptions); 866 } 867 868 void ScTabViewShell::GetDrawOptState( SfxItemSet& rSet ) 869 { 870 SfxBoolItem aBool; 871 872 const ScViewOptions& rViewOptions = GetViewData().GetOptions(); 873 const ScGridOptions& rGridOptions = rViewOptions.GetGridOptions(); 874 875 aBool.SetValue(rGridOptions.GetGridVisible()); 876 aBool.SetWhich( SID_GRID_VISIBLE ); 877 rSet.Put( aBool ); 878 879 aBool.SetValue(rGridOptions.GetUseGridSnap()); 880 aBool.SetWhich( SID_GRID_USE ); 881 rSet.Put( aBool ); 882 883 aBool.SetValue(rViewOptions.GetOption( VOPT_HELPLINES )); 884 aBool.SetWhich( SID_HELPLINES_MOVE ); 885 rSet.Put( aBool ); 886 } 887 888 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ 889
