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