1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include "scitems.hxx"
22 #include <svl/slstitm.hxx>
23 #include <svl/stritem.hxx>
24 #include <svl/whiter.hxx>
25 #include <unotools/moduleoptions.hxx>
26 #include <svtools/cliplistener.hxx>
27 #include <svtools/insdlg.hxx>
28 #include <sot/formats.hxx>
29 #include <svx/hlnkitem.hxx>
30 #include <sfx2/app.hxx>
31 #include <sfx2/bindings.hxx>
32 #include <sfx2/childwin.hxx>
33 #include <sfx2/objface.hxx>
34 #include <sfx2/request.hxx>
35 #include <sfx2/viewfrm.hxx>
36 #include <sfx2/sidebar/EnumContext.hxx>
37 #include <svx/clipfmtitem.hxx>
38 #include <svx/sidebar/ContextChangeEventMultiplexer.hxx>
39 #include <editeng/langitem.hxx>
45 #include "scresid.hxx"
46 #include "tabvwsh.hxx"
48 #include "formulacell.hxx"
50 #include "globstr.hrc"
51 #include "transobj.hxx"
52 #include "drwtrans.hxx"
53 #include "scabstdlg.hxx"
54 #include "dociter.hxx"
56 #include "cliputil.hxx"
57 #include "clipparam.hxx"
58 #include "markdata.hxx"
59 #include <gridwin.hxx>
63 #include "scslots.hxx"
66 SFX_IMPL_INTERFACE(ScCellShell
, ScFormatShell
)
68 void ScCellShell::InitInterface_Impl()
70 GetStaticInterface()->RegisterObjectBar(SFX_OBJECTBAR_OBJECT
| SFX_VISIBILITY_STANDARD
| SFX_VISIBILITY_SERVER
,
71 RID_OBJECTBAR_FORMAT
);
73 GetStaticInterface()->RegisterPopupMenu("cell");
76 ScCellShell::ScCellShell(ScViewData
* pData
) :
78 pImpl( new CellShell_Impl() ),
81 SetHelpId(HID_SCSHELL_CELLSH
);
83 SfxShell::SetContextName(sfx2::sidebar::EnumContext::GetContextName(sfx2::sidebar::EnumContext::Context_Cell
));
86 ScCellShell::~ScCellShell()
88 if ( pImpl
->m_pClipEvtLstnr
)
90 pImpl
->m_pClipEvtLstnr
->AddRemoveListener( GetViewData()->GetActiveWin(), false );
92 // The listener may just now be waiting for the SolarMutex and call the link
93 // afterwards, in spite of RemoveListener. So the link has to be reset, too.
94 pImpl
->m_pClipEvtLstnr
->ClearCallbackLink();
96 pImpl
->m_pClipEvtLstnr
->release();
99 delete pImpl
->m_pLinkedDlg
;
100 delete pImpl
->m_pRequest
;
103 void ScCellShell::GetBlockState( SfxItemSet
& rSet
)
105 ScTabViewShell
* pTabViewShell
= GetViewData()->GetViewShell();
107 ScMarkType eMarkType
= GetViewData()->GetSimpleArea( aMarkRange
);
108 bool bSimpleArea
= (eMarkType
== SC_MARK_SIMPLE
);
109 bool bOnlyNotBecauseOfMatrix
;
110 bool bEditable
= pTabViewShell
->SelectionEditable( &bOnlyNotBecauseOfMatrix
);
111 ScDocument
* pDoc
= GetViewData()->GetDocument();
112 ScDocShell
* pDocShell
= GetViewData()->GetDocShell();
113 ScMarkData
& rMark
= GetViewData()->GetMarkData();
116 nCol1
= aMarkRange
.aStart
.Col();
117 nRow1
= aMarkRange
.aStart
.Row();
118 nCol2
= aMarkRange
.aEnd
.Col();
119 nRow2
= aMarkRange
.aEnd
.Row();
121 SfxWhichIter
aIter(rSet
);
122 sal_uInt16 nWhich
= aIter
.FirstWhich();
125 bool bDisable
= false;
126 bool bNeedEdit
= true; // need selection be editable?
129 case FID_FILL_TO_BOTTOM
: // fill to top / bottom
131 bDisable
= !bSimpleArea
|| (nRow1
== 0 && nRow2
== 0);
132 if (!bDisable
&& GetViewData()->SelectionForbidsPaste())
134 if ( !bDisable
&& bEditable
)
135 { // do not damage matrix
136 bDisable
= pDoc
->HasSelectedBlockMatrixFragment(
137 nCol1
, nRow1
, nCol2
, nRow1
, rMark
); // first row
141 case FID_FILL_TO_TOP
:
143 bDisable
= (!bSimpleArea
) || (nRow1
== MAXROW
&& nRow2
== MAXROW
);
144 if (!bDisable
&& GetViewData()->SelectionForbidsPaste())
146 if ( !bDisable
&& bEditable
)
147 { // do not damage matrix
148 bDisable
= pDoc
->HasSelectedBlockMatrixFragment(
149 nCol1
, nRow2
, nCol2
, nRow2
, rMark
); // last row
153 case FID_FILL_TO_RIGHT
: // fill to left / right
155 bDisable
= !bSimpleArea
|| (nCol1
== 0 && nCol2
== 0);
156 if (!bDisable
&& GetViewData()->SelectionForbidsPaste())
158 if ( !bDisable
&& bEditable
)
159 { // do not damage matrix
160 bDisable
= pDoc
->HasSelectedBlockMatrixFragment(
161 nCol1
, nRow1
, nCol1
, nRow2
, rMark
); // first column
165 case FID_FILL_TO_LEFT
:
167 bDisable
= (!bSimpleArea
) || (nCol1
== MAXCOL
&& nCol2
== MAXCOL
);
168 if (!bDisable
&& GetViewData()->SelectionForbidsPaste())
170 if ( !bDisable
&& bEditable
)
171 { // do not damage matrix
172 bDisable
= pDoc
->HasSelectedBlockMatrixFragment(
173 nCol2
, nRow1
, nCol2
, nRow2
, rMark
); // last column
178 case SID_RANDOM_NUMBER_GENERATOR_DIALOG
:
179 bDisable
= !bSimpleArea
|| GetViewData()->SelectionForbidsPaste();
181 case SID_SAMPLING_DIALOG
:
182 case SID_DESCRIPTIVE_STATISTICS_DIALOG
:
183 case SID_ANALYSIS_OF_VARIANCE_DIALOG
:
184 case SID_CORRELATION_DIALOG
:
185 case SID_COVARIANCE_DIALOG
:
187 bDisable
= !bSimpleArea
;
191 case FID_FILL_SERIES
: // fill block
192 case SID_OPENDLG_TABOP
: // multiple-cell operations, are at least 2 cells marked?
193 if (pDoc
->GetChangeTrack()!=nullptr &&nWhich
==SID_OPENDLG_TABOP
)
196 bDisable
= (!bSimpleArea
) || (nCol1
== nCol2
&& nRow1
== nRow2
);
198 if (!bDisable
&& GetViewData()->SelectionForbidsPaste())
201 if ( !bDisable
&& bEditable
&& nWhich
== FID_FILL_SERIES
)
202 { // do not damage matrix
203 bDisable
= pDoc
->HasSelectedBlockMatrixFragment(
204 nCol1
, nRow1
, nCol2
, nRow1
, rMark
) // first row
205 || pDoc
->HasSelectedBlockMatrixFragment(
206 nCol1
, nRow2
, nCol2
, nRow2
, rMark
) // last row
207 || pDoc
->HasSelectedBlockMatrixFragment(
208 nCol1
, nRow1
, nCol1
, nRow2
, rMark
) // first column
209 || pDoc
->HasSelectedBlockMatrixFragment(
210 nCol2
, nRow1
, nCol2
, nRow2
, rMark
); // last column
213 case FID_FILL_SINGLE_EDIT
:
217 case FID_INS_CELL
: // insert cells, just simple selection
218 bDisable
= (!bSimpleArea
);
222 case SID_PASTE_SPECIAL
:
223 case SID_PASTE_ONLY_VALUE
:
224 case SID_PASTE_ONLY_TEXT
:
225 case SID_PASTE_ONLY_FORMULA
:
226 bDisable
= GetViewData()->SelectionForbidsPaste();
230 case FID_INS_ROWS_BEFORE
: // insert rows
231 case FID_INS_ROWS_AFTER
:
232 case FID_INS_CELLSDOWN
:
233 bDisable
= (!bSimpleArea
) || GetViewData()->SimpleColMarked();
237 case FID_INS_COLUMNS_BEFORE
: // insert columns
238 case FID_INS_COLUMNS_AFTER
:
239 case FID_INS_CELLSRIGHT
:
240 bDisable
= (!bSimpleArea
) || GetViewData()->SimpleRowMarked();
243 case SID_COPY
: // copy
244 // not editable because of matrix only? Do not damage matrix
245 //! is not called, when protected AND matrix, we will have
246 //! to live with this... is caught in Copy-Routine, otherwise
247 //! work is to be done once more
248 if ( !(!bEditable
&& bOnlyNotBecauseOfMatrix
) )
249 bNeedEdit
= false; // allowed when protected/ReadOnly
252 case SID_AUTOFORMAT
: // Autoformat, at least 3x3 selected
253 bDisable
= (!bSimpleArea
)
254 || ((nCol2
- nCol1
) < 2) || ((nRow2
- nRow1
) < 2);
257 case SID_CELL_FORMAT_RESET
:
258 case FID_CELL_FORMAT
:
259 case SID_ENABLE_HYPHENATION
:
260 // not editable because of matrix only? Attribute ok nonetheless
261 if ( !bEditable
&& bOnlyNotBecauseOfMatrix
)
267 if ( pDocShell
&& pDocShell
->IsDocShared() )
274 case SID_TRANSLITERATE_HALFWIDTH
:
275 case SID_TRANSLITERATE_FULLWIDTH
:
276 case SID_TRANSLITERATE_HIRAGANA
:
277 case SID_TRANSLITERATE_KATAGANA
:
278 ScViewUtil::HideDisabledSlot( rSet
, GetViewData()->GetBindings(), nWhich
);
280 case SID_CONVERT_FORMULA_TO_VALUE
:
282 // Check and see if the marked range has at least one formula cell.
283 bDisable
= !pDoc
->HasFormulaCell(aMarkRange
);
287 if (!bDisable
&& bNeedEdit
&& !bEditable
)
291 rSet
.DisableItem(nWhich
);
292 else if (nWhich
== SID_ENABLE_HYPHENATION
)
294 // toggle slots need a bool item
295 rSet
.Put( SfxBoolItem( nWhich
, false ) );
297 nWhich
= aIter
.NextWhich();
301 // functions, disabled depending on cursor position
303 // SID_INSERT_POSTIT, SID_CHARMAP, SID_OPENDLG_FUNCTION
305 void ScCellShell::GetCellState( SfxItemSet
& rSet
)
307 ScDocShell
* pDocShell
= GetViewData()->GetDocShell();
308 ScDocument
& rDoc
= GetViewData()->GetDocShell()->GetDocument();
309 ScAddress
aCursor( GetViewData()->GetCurX(), GetViewData()->GetCurY(),
310 GetViewData()->GetTabNo() );
312 SfxWhichIter
aIter(rSet
);
313 sal_uInt16 nWhich
= aIter
.FirstWhich();
316 bool bDisable
= false;
317 bool bNeedEdit
= true; // need cursor position be editable?
322 CellType eType
= rDoc
.GetCellType( aCursor
);
323 bDisable
= ( eType
!= CELLTYPE_STRING
&& eType
!= CELLTYPE_EDIT
);
326 // test for available languages
327 sal_uInt16 nLang
= ScViewUtil::GetEffLanguage( &rDoc
, aCursor
);
328 bDisable
= !ScModule::HasThesaurusLanguage( nLang
);
332 case SID_OPENDLG_FUNCTION
:
334 ScMarkData aMarkData
= GetViewData()->GetMarkData();
335 aMarkData
.MarkToSimple();
337 aMarkData
.GetMarkArea(aRange
);
338 if(aMarkData
.IsMarked())
340 if (!rDoc
.IsBlockEditable( aCursor
.Tab(), aRange
.aStart
.Col(),aRange
.aStart
.Row(),
341 aRange
.aEnd
.Col(),aRange
.aEnd
.Row() ))
350 case SID_INSERT_POSTIT
:
352 ScAddress
aPos( GetViewData()->GetCurX(), GetViewData()->GetCurY(), GetViewData()->GetTabNo() );
353 if( rDoc
.GetNote(aPos
) )
360 if ( pDocShell
&& pDocShell
->IsDocShared() )
367 case SID_EDIT_POSTIT
:
369 ScAddress
aPos( GetViewData()->GetCurX(), GetViewData()->GetCurY(), GetViewData()->GetTabNo() );
370 if( rDoc
.GetNote(aPos
) )
381 if (!bDisable
&& bNeedEdit
)
382 if (!rDoc
.IsBlockEditable( aCursor
.Tab(), aCursor
.Col(),aCursor
.Row(),
383 aCursor
.Col(),aCursor
.Row() ))
386 rSet
.DisableItem(nWhich
);
387 nWhich
= aIter
.NextWhich();
391 static bool lcl_TestFormat( SvxClipboardFormatItem
& rFormats
, const TransferableDataHelper
& rDataHelper
,
392 SotClipboardFormatId nFormatId
)
394 if ( rDataHelper
.HasFormat( nFormatId
) )
396 // translated format name strings are no longer inserted here,
397 // handled by "paste special" dialog / toolbox controller instead.
398 // Only the object type name has to be set here:
400 if ( nFormatId
== SotClipboardFormatId::EMBED_SOURCE
)
402 TransferableObjectDescriptor aDesc
;
403 if ( ((TransferableDataHelper
&)rDataHelper
).GetTransferableObjectDescriptor(
404 SotClipboardFormatId::OBJECTDESCRIPTOR
, aDesc
) )
405 aStrVal
= aDesc
.maTypeName
;
407 else if ( nFormatId
== SotClipboardFormatId::EMBED_SOURCE_OLE
408 || nFormatId
== SotClipboardFormatId::EMBEDDED_OBJ_OLE
)
411 SvPasteObjectHelper::GetEmbeddedName( rDataHelper
, aStrVal
, aSource
, nFormatId
);
414 if ( !aStrVal
.isEmpty() )
415 rFormats
.AddClipbrdFormat( nFormatId
, aStrVal
);
417 rFormats
.AddClipbrdFormat( nFormatId
);
425 void ScCellShell::GetPossibleClipboardFormats( SvxClipboardFormatItem
& rFormats
)
427 vcl::Window
* pWin
= GetViewData()->GetActiveWin();
428 bool bDraw
= ( ScDrawTransferObj::GetOwnClipboard( pWin
) != nullptr );
430 TransferableDataHelper
aDataHelper( TransferableDataHelper::CreateFromSystemClipboard( pWin
) );
432 lcl_TestFormat( rFormats
, aDataHelper
, SotClipboardFormatId::DRAWING
);
433 lcl_TestFormat( rFormats
, aDataHelper
, SotClipboardFormatId::SVXB
);
434 lcl_TestFormat( rFormats
, aDataHelper
, SotClipboardFormatId::GDIMETAFILE
);
435 lcl_TestFormat( rFormats
, aDataHelper
, SotClipboardFormatId::PNG
);
436 lcl_TestFormat( rFormats
, aDataHelper
, SotClipboardFormatId::BITMAP
);
437 lcl_TestFormat( rFormats
, aDataHelper
, SotClipboardFormatId::EMBED_SOURCE
);
441 lcl_TestFormat( rFormats
, aDataHelper
, SotClipboardFormatId::LINK
);
442 lcl_TestFormat( rFormats
, aDataHelper
, SotClipboardFormatId::STRING
);
443 lcl_TestFormat( rFormats
, aDataHelper
, SotClipboardFormatId::DIF
);
444 lcl_TestFormat( rFormats
, aDataHelper
, SotClipboardFormatId::RTF
);
445 lcl_TestFormat( rFormats
, aDataHelper
, SotClipboardFormatId::HTML
);
446 lcl_TestFormat( rFormats
, aDataHelper
, SotClipboardFormatId::HTML_SIMPLE
);
447 lcl_TestFormat( rFormats
, aDataHelper
, SotClipboardFormatId::BIFF_8
);
448 lcl_TestFormat( rFormats
, aDataHelper
, SotClipboardFormatId::BIFF_5
);
451 if ( !lcl_TestFormat( rFormats
, aDataHelper
, SotClipboardFormatId::EMBED_SOURCE_OLE
) )
452 lcl_TestFormat( rFormats
, aDataHelper
, SotClipboardFormatId::EMBEDDED_OBJ_OLE
);
455 // insert, insert contents
457 static bool lcl_IsCellPastePossible( const TransferableDataHelper
& rData
)
459 bool bPossible
= false;
460 if ( ScTransferObj::GetOwnClipboard( nullptr ) || ScDrawTransferObj::GetOwnClipboard( nullptr ) )
464 if ( rData
.HasFormat( SotClipboardFormatId::PNG
) ||
465 rData
.HasFormat( SotClipboardFormatId::BITMAP
) ||
466 rData
.HasFormat( SotClipboardFormatId::GDIMETAFILE
) ||
467 rData
.HasFormat( SotClipboardFormatId::SVXB
) ||
468 rData
.HasFormat( SotClipboardFormatId::PRIVATE
) ||
469 rData
.HasFormat( SotClipboardFormatId::RTF
) ||
470 rData
.HasFormat( SotClipboardFormatId::EMBED_SOURCE
) ||
471 rData
.HasFormat( SotClipboardFormatId::LINK_SOURCE
) ||
472 rData
.HasFormat( SotClipboardFormatId::EMBED_SOURCE_OLE
) ||
473 rData
.HasFormat( SotClipboardFormatId::LINK_SOURCE_OLE
) ||
474 rData
.HasFormat( SotClipboardFormatId::EMBEDDED_OBJ_OLE
) ||
475 rData
.HasFormat( SotClipboardFormatId::STRING
) ||
476 rData
.HasFormat( SotClipboardFormatId::SYLK
) ||
477 rData
.HasFormat( SotClipboardFormatId::LINK
) ||
478 rData
.HasFormat( SotClipboardFormatId::HTML
) ||
479 rData
.HasFormat( SotClipboardFormatId::HTML_SIMPLE
) ||
480 rData
.HasFormat( SotClipboardFormatId::DIF
) )
488 IMPL_LINK_TYPED( ScCellShell
, ClipboardChanged
, TransferableDataHelper
*, pDataHelper
, void )
490 bPastePossible
= lcl_IsCellPastePossible( *pDataHelper
);
492 SfxBindings
& rBindings
= GetViewData()->GetBindings();
493 rBindings
.Invalidate( SID_PASTE
);
494 rBindings
.Invalidate( SID_PASTE_SPECIAL
);
495 rBindings
.Invalidate( SID_PASTE_ONLY_VALUE
);
496 rBindings
.Invalidate( SID_PASTE_ONLY_TEXT
);
497 rBindings
.Invalidate( SID_PASTE_ONLY_FORMULA
);
498 rBindings
.Invalidate( SID_CLIPBOARD_FORMAT_ITEMS
);
503 bool checkDestRanges(ScViewData
& rViewData
)
506 ScMarkType eMarkType
= rViewData
.GetSimpleArea( aDummy
);
507 if (eMarkType
!= SC_MARK_MULTI
)
509 // Single destination range.
510 if (eMarkType
!= SC_MARK_SIMPLE
&& eMarkType
!= SC_MARK_SIMPLE_FILTERED
)
514 if (rViewData
.SelectionForbidsPaste())
517 // Multiple destination ranges.
519 ScDocument
* pDoc
= rViewData
.GetDocument();
520 vcl::Window
* pWin
= rViewData
.GetActiveWin();
524 ScTransferObj
* pOwnClip
= ScTransferObj::GetOwnClipboard(pWin
);
526 // If it's not a Calc document, we won't be picky.
529 ScDocument
* pClipDoc
= pOwnClip
->GetDocument();
533 ScRange aSrcRange
= pClipDoc
->GetClipParam().getWholeRange();
534 SCROW nRowSize
= aSrcRange
.aEnd
.Row() - aSrcRange
.aStart
.Row() + 1;
535 SCCOL nColSize
= aSrcRange
.aEnd
.Col() - aSrcRange
.aStart
.Col() + 1;
537 ScMarkData aMark
= rViewData
.GetMarkData();
539 aMark
.MarkToSimple();
540 aMark
.FillRangeListWithMarks(&aRanges
, false);
542 return ScClipUtil::CheckDestRanges(pDoc
, nColSize
, nRowSize
, aMark
, aRanges
);
547 void ScCellShell::GetClipState( SfxItemSet
& rSet
)
551 // SID_CLIPBOARD_FORMAT_ITEMS
553 if ( !pImpl
->m_pClipEvtLstnr
)
556 pImpl
->m_pClipEvtLstnr
= new TransferableClipboardListener( LINK( this, ScCellShell
, ClipboardChanged
) );
557 pImpl
->m_pClipEvtLstnr
->acquire();
558 vcl::Window
* pWin
= GetViewData()->GetActiveWin();
559 pImpl
->m_pClipEvtLstnr
->AddRemoveListener( pWin
, true );
562 TransferableDataHelper
aDataHelper( TransferableDataHelper::CreateFromSystemClipboard( pWin
) );
563 bPastePossible
= lcl_IsCellPastePossible( aDataHelper
);
566 bool bDisable
= !bPastePossible
;
568 // cell protection / multiple selection
572 SCCOL nCol
= GetViewData()->GetCurX();
573 SCROW nRow
= GetViewData()->GetCurY();
574 SCTAB nTab
= GetViewData()->GetTabNo();
575 ScDocument
& rDoc
= GetViewData()->GetDocShell()->GetDocument();
576 if (!rDoc
.IsBlockEditable( nTab
, nCol
,nRow
, nCol
,nRow
))
579 if (!bDisable
&& !checkDestRanges(*GetViewData()))
585 rSet
.DisableItem( SID_PASTE
);
586 rSet
.DisableItem( SID_PASTE_SPECIAL
);
587 rSet
.DisableItem( SID_PASTE_ONLY_VALUE
);
588 rSet
.DisableItem( SID_PASTE_ONLY_TEXT
);
589 rSet
.DisableItem( SID_PASTE_ONLY_FORMULA
);
590 rSet
.DisableItem( SID_CLIPBOARD_FORMAT_ITEMS
);
592 else if ( rSet
.GetItemState( SID_CLIPBOARD_FORMAT_ITEMS
) != SfxItemState::UNKNOWN
)
594 SvxClipboardFormatItem
aFormats( SID_CLIPBOARD_FORMAT_ITEMS
);
595 GetPossibleClipboardFormats( aFormats
);
596 rSet
.Put( aFormats
);
600 // only SID_HYPERLINK_GETLINK:
602 void ScCellShell::GetHLinkState( SfxItemSet
& rSet
)
604 // always return an item (or inserting will be disabled)
605 // if the cell at the cursor contains only a link, return that link
607 SvxHyperlinkItem aHLinkItem
;
608 if ( !GetViewData()->GetView()->HasBookmarkAtCursor( &aHLinkItem
) )
610 //! put selected text into item?
613 rSet
.Put(aHLinkItem
);
616 void ScCellShell::GetState(SfxItemSet
&rSet
)
618 ScTabViewShell
* pTabViewShell
= GetViewData()->GetViewShell();
619 ScDocShell
* pDocSh
= GetViewData()->GetDocShell();
620 ScViewData
* pData
= GetViewData();
621 ScDocument
* pDoc
= pData
->GetDocument();
622 ScMarkData
& rMark
= pData
->GetMarkData();
623 SCCOL nPosX
= pData
->GetCurX();
624 SCROW nPosY
= pData
->GetCurY();
625 SCTAB nTab
= pData
->GetTabNo();
627 SCTAB nTabCount
= pDoc
->GetTableCount();
628 SCTAB nTabSelCount
= rMark
.GetSelectCount();
630 SfxWhichIter
aIter(rSet
);
631 sal_uInt16 nWhich
= aIter
.FirstWhich();
636 case SID_DETECTIVE_REFRESH
:
637 if (!pDoc
->HasDetectiveOperations())
638 rSet
.DisableItem( nWhich
);
641 case SID_RANGE_ADDRESS
:
644 if ( pData
->GetSimpleArea( aRange
) == SC_MARK_SIMPLE
)
646 OUString
aStr(aRange
.Format(ScRefFlags::VALID
| ScRefFlags::TAB_3D
,pDoc
));
647 rSet
.Put( SfxStringItem( nWhich
, aStr
) );
652 case SID_RANGE_NOTETEXT
:
654 // always take cursor position, do not use top-left cell of selection
656 if ( const ScPostIt
* pNote
= pDoc
->GetNote(nPosX
, nPosY
, nTab
) )
657 aNoteText
= pNote
->GetText();
658 rSet
.Put( SfxStringItem( nWhich
, aNoteText
) );
663 rSet
.Put( SfxInt32Item( nWhich
, nPosY
+1 ) );
667 rSet
.Put( SfxInt16Item( nWhich
, nPosX
+1 ) );
670 case SID_RANGE_TABLE
:
671 rSet
.Put( SfxInt16Item( nWhich
, nTab
+1 ) );
674 case SID_RANGE_VALUE
:
677 pDoc
->GetValue( nPosX
, nPosY
, nTab
, nValue
);
678 rSet
.Put( ScDoubleItem( nWhich
, nValue
) );
682 case SID_RANGE_FORMULA
:
685 pDoc
->GetFormula( nPosX
, nPosY
, nTab
, aString
);
686 if( aString
.isEmpty() )
688 pDoc
->GetInputString( nPosX
, nPosY
, nTab
, aString
);
690 rSet
.Put( SfxStringItem( nWhich
, aString
) );
694 case SID_RANGE_TEXTVALUE
:
696 OUString aString
= pDoc
->GetString(nPosX
, nPosY
, nTab
);
697 rSet
.Put( SfxStringItem( nWhich
, aString
) );
701 case SID_STATUS_SELMODE
:
703 /* 0: STD Click cancels Sel
704 * 1: ER Click extends selection
705 * 2: ERG Click defines further selection
707 sal_uInt16 nMode
= pTabViewShell
->GetLockedModifiers();
711 case KEY_SHIFT
: nMode
= 1; break;
712 case KEY_MOD1
: nMode
= 2; break; // Control-key
718 rSet
.Put( SfxUInt16Item( nWhich
, nMode
) );
722 case SID_STATUS_DOCPOS
:
724 OUString aStr
= ScGlobal::GetRscString( STR_TABLE_COUNT
);
726 aStr
= aStr
.replaceFirst("%1", OUString::number( nTab
+ 1 ) );
727 aStr
= aStr
.replaceFirst("%2", OUString::number( nTabCount
) );
729 rSet
.Put( SfxStringItem( nWhich
, aStr
) ); }
732 case SID_ROWCOL_SELCOUNT
:
735 GetViewData()->GetSimpleArea( aMarkRange
);
738 nCol1
= aMarkRange
.aStart
.Col();
739 nRow1
= aMarkRange
.aStart
.Row();
740 nCol2
= aMarkRange
.aEnd
.Col();
741 nRow2
= aMarkRange
.aEnd
.Row();
742 if( nCol2
!= nCol1
|| nRow1
!= nRow2
)
744 OUString aStr
= ScGlobal::GetRscString( STR_ROWCOL_SELCOUNT
);
745 aStr
= aStr
.replaceAll( "$1", OUString::number( nRow2
- nRow1
+ 1 ));
746 aStr
= aStr
.replaceAll( "$2", OUString::number( nCol2
- nCol1
+ 1 ));
747 rSet
.Put( SfxStringItem( nWhich
, aStr
) );
751 SCSIZE nSelected
, nTotal
;
752 pDoc
->GetFilterSelCount( nPosX
, nPosY
, nTab
, nSelected
, nTotal
);
755 OUString aStr
= ScGlobal::GetRscString( STR_FILTER_SELCOUNT
);
756 aStr
= aStr
.replaceAll( "$1", OUString::number( nSelected
) );
757 aStr
= aStr
.replaceAll( "$2", OUString::number( nTotal
) );
758 rSet
.Put( SfxStringItem( nWhich
, aStr
) );
764 // calculations etc. with date/time/Fail/position&size together
766 // #i34458# The SfxStringItem belongs only into SID_TABLE_CELL. It no longer has to be
767 // duplicated in SID_ATTR_POSITION or SID_ATTR_SIZE for SvxPosSizeStatusBarControl.
770 // Test, if error under cursor
771 // (not pDoc->GetErrCode, to avoid erasing circular references)
773 // In interpreter may happen via rescheduled Basic
774 if ( pDoc
->IsInInterpreter() )
775 rSet
.Put( SfxStringItem( nWhich
, OUString("...") ) );
778 sal_uInt16 nErrCode
= 0;
779 ScFormulaCell
* pCell
= pDoc
->GetFormulaCell(ScAddress(nPosX
, nPosY
, nTab
));
782 if (!pCell
->IsRunning())
783 nErrCode
= pCell
->GetErrCode();
787 if ( pTabViewShell
->GetFunction( aFuncStr
, nErrCode
) )
788 rSet
.Put( SfxStringItem( nWhich
, aFuncStr
) );
793 case SID_DATA_SELECT
:
794 // HasSelectionData includes column content and validity,
795 // page fields have to be checked separately.
796 if ( !pDoc
->HasSelectionData( nPosX
, nPosY
, nTab
) &&
797 !pTabViewShell
->HasPageFieldDataAtCursor() )
798 rSet
.DisableItem( nWhich
);
804 if ( pTabViewShell
->GetFunction( aFuncStr
) )
805 rSet
.Put( SfxStringItem( nWhich
, aFuncStr
) );
810 if ( pDoc
->GetChangeTrack() || !pTabViewShell
->TestMergeCells() )
811 rSet
.DisableItem( nWhich
);
815 if ( pDoc
->GetChangeTrack() || !pTabViewShell
->TestRemoveMerge() )
816 rSet
.DisableItem( nWhich
);
819 case FID_MERGE_TOGGLE
:
820 if ( pDoc
->GetChangeTrack() )
821 rSet
.DisableItem( nWhich
);
824 bool bCanMerge
= pTabViewShell
->TestMergeCells();
825 bool bCanSplit
= pTabViewShell
->TestRemoveMerge();
826 if( !bCanMerge
&& !bCanSplit
)
827 rSet
.DisableItem( nWhich
);
829 rSet
.Put( SfxBoolItem( nWhich
, bCanSplit
) );
834 if ( nPosY
==0 || (pDoc
->HasRowBreak(nPosY
, nTab
) & BREAK_MANUAL
) )
835 rSet
.DisableItem( nWhich
);
839 if ( nPosX
==0 || (pDoc
->HasColBreak(nPosX
, nTab
) & BREAK_MANUAL
) )
840 rSet
.DisableItem( nWhich
);
844 if ( nPosY
==0 || (pDoc
->HasRowBreak(nPosY
, nTab
) & BREAK_MANUAL
) == 0 )
845 rSet
.DisableItem( nWhich
);
849 if ( nPosX
==0 || (pDoc
->HasColBreak(nPosX
, nTab
) & BREAK_MANUAL
) == 0 )
850 rSet
.DisableItem( nWhich
);
854 if ( nTabSelCount
< 2 )
855 rSet
.DisableItem( nWhich
);
858 case SID_SELECT_SCENARIO
:
860 std::vector
<OUString
> aList
;
863 if ( !pDoc
->IsScenario(nTab
) )
867 SCTAB nScTab
= nTab
+ 1;
868 bool bSheetProtected
= pDoc
->IsTabProtected(nTab
);
870 while ( pDoc
->IsScenario(nScTab
) )
872 pDoc
->GetName( nScTab
, aStr
);
873 aList
.push_back(aStr
);
874 pDoc
->GetScenarioData( nScTab
, aStr
, aDummyCol
, nFlags
);
875 aList
.push_back(aStr
);
876 // Protection is sal_True if both Sheet and Scenario are protected
877 aList
.push_back((bSheetProtected
&& (nFlags
& SC_SCENARIO_PROTECT
)) ? OUString("1") : OUString("0"));
884 sal_uInt16 nDummyFlags
;
885 pDoc
->GetScenarioData( nTab
, aComment
, aDummyCol
, nDummyFlags
);
886 OSL_ENSURE( aList
.empty(), "List not empty!" );
887 aList
.push_back(aComment
);
890 rSet
.Put( SfxStringListItem( nWhich
, &aList
) );
898 case FID_COL_OPT_WIDTH
:
899 case FID_ROW_OPT_HEIGHT
:
900 case FID_DELETE_CELL
:
901 if ( pDoc
->IsTabProtected(nTab
) || pDocSh
->IsReadOnly())
902 rSet
.DisableItem( nWhich
);
905 case SID_OUTLINE_MAKE
:
907 if ( GetViewData()->GetDocument()->GetDPAtCursor( GetViewData()->GetCurX(),
908 GetViewData()->GetCurY(), GetViewData()->GetTabNo() ) )
910 //! test for data pilot operation
912 else if (pDoc
->GetChangeTrack()!=nullptr || GetViewData()->IsMultiMarked())
914 rSet
.DisableItem( nWhich
);
918 case SID_OUTLINE_SHOW
:
919 if ( GetViewData()->GetDocument()->GetDPAtCursor( GetViewData()->GetCurX(),
920 GetViewData()->GetCurY(), GetViewData()->GetTabNo() ) )
922 //! test for data pilot operation
924 else if (!pTabViewShell
->OutlinePossible(false))
925 rSet
.DisableItem( nWhich
);
928 case SID_OUTLINE_HIDE
:
929 if ( GetViewData()->GetDocument()->GetDPAtCursor( GetViewData()->GetCurX(),
930 GetViewData()->GetCurY(), GetViewData()->GetTabNo() ) )
932 //! test for data pilot operation
934 else if (!pTabViewShell
->OutlinePossible(true))
935 rSet
.DisableItem( nWhich
);
938 case SID_OUTLINE_REMOVE
:
940 if ( GetViewData()->GetDocument()->GetDPAtCursor( GetViewData()->GetCurX(),
941 GetViewData()->GetCurY(), GetViewData()->GetTabNo() ) )
943 //! test for data pilot operation
948 pTabViewShell
->TestRemoveOutline( bCol
, bRow
);
949 if ( !bCol
&& !bRow
)
950 rSet
.DisableItem( nWhich
);
957 SfxUInt16Item
aWidthItem( FID_COL_WIDTH
, pDoc
->GetColWidth( nPosX
, nTab
) );
958 rSet
.Put( aWidthItem
);
959 if ( pDocSh
->IsReadOnly())
960 rSet
.DisableItem( nWhich
);
962 //XXX disable if not conclusive
968 SfxUInt16Item
aHeightItem( FID_ROW_HEIGHT
, pDoc
->GetRowHeight( nPosY
, nTab
) );
969 rSet
.Put( aHeightItem
);
970 //XXX disable if not conclusive
971 if ( pDocSh
->IsReadOnly())
972 rSet
.DisableItem( nWhich
);
976 case SID_DETECTIVE_FILLMODE
:
977 rSet
.Put(SfxBoolItem( nWhich
, pTabViewShell
->IsAuditShell() ));
980 case FID_INPUTLINE_STATUS
:
981 OSL_FAIL( "Old update method. Use ScTabViewShell::UpdateInputHandler()." );
984 case SID_SCENARIOS
: // scenarios:
985 if (!(rMark
.IsMarked() || rMark
.IsMultiMarked())) // only, if something selected
986 rSet
.DisableItem( nWhich
);
989 case FID_NOTE_VISIBLE
:
991 const ScPostIt
* pNote
= pDoc
->GetNote(nPosX
, nPosY
, nTab
);
992 if ( pNote
&& pDoc
->IsBlockEditable( nTab
, nPosX
,nPosY
, nPosX
,nPosY
) )
993 rSet
.Put( SfxBoolItem( nWhich
, pNote
->IsCaptionShown() ) );
995 rSet
.DisableItem( nWhich
);
1002 bool bEnable
= false;
1003 bool bSearchForHidden
= nWhich
== FID_SHOW_NOTE
;
1004 if (!rMark
.IsMarked() && !rMark
.IsMultiMarked())
1006 // Check current cell
1007 const ScPostIt
* pNote
= pDoc
->GetNote(nPosX
, nPosY
, nTab
);
1008 if ( pNote
&& pDoc
->IsBlockEditable( nTab
, nPosX
,nPosY
, nPosX
,nPosY
) )
1009 if ( pNote
->IsCaptionShown() != bSearchForHidden
)
1014 // Check selection range
1015 ScRangeListRef aRangesRef
;
1016 pData
->GetMultiArea(aRangesRef
);
1017 ScRangeList aRanges
= *aRangesRef
;
1018 std::vector
<sc::NoteEntry
> aNotes
;
1019 pDoc
->GetNotesInRange(aRanges
, aNotes
);
1020 for(std::vector
<sc::NoteEntry
>::const_iterator itr
= aNotes
.begin(),
1021 itrEnd
= aNotes
.end(); itr
!= itrEnd
; ++itr
)
1023 const ScAddress
& rAdr
= itr
->maPos
;
1024 if( pDoc
->IsBlockEditable( rAdr
.Tab(), rAdr
.Col(), rAdr
.Row(), rAdr
.Col(), rAdr
.Row() ))
1026 if (itr
->mpNote
->IsCaptionShown() != bSearchForHidden
)
1036 rSet
.DisableItem( nWhich
);
1040 case SID_DELETE_NOTE
:
1042 bool bEnable
= false;
1043 if ( rMark
.IsMarked() || rMark
.IsMultiMarked() )
1045 if ( pDoc
->IsSelectionEditable( rMark
) )
1047 // look for at least one note in selection
1048 ScRangeList aRanges
;
1049 rMark
.FillRangeListWithMarks( &aRanges
, false );
1050 bEnable
= pDoc
->ContainsNotesInRange( aRanges
);
1055 bEnable
= pDoc
->IsBlockEditable( nTab
, nPosX
,nPosY
, nPosX
,nPosY
) &&
1056 pDoc
->GetNote(nPosX
, nPosY
, nTab
);
1059 rSet
.DisableItem( nWhich
);
1063 case SID_OPENDLG_CONSOLIDATE
:
1064 case SCITEM_CONSOLIDATEDATA
:
1066 if(pDoc
->GetChangeTrack()!=nullptr)
1067 rSet
.DisableItem( nWhich
);
1071 case SID_CHINESE_CONVERSION
:
1072 case SID_HANGUL_HANJA_CONVERSION
:
1073 ScViewUtil::HideDisabledSlot( rSet
, pData
->GetBindings(), nWhich
);
1078 if ( pDocSh
&& pDocSh
->IsDocShared() )
1079 rSet
.DisableItem( nWhich
);
1083 if ( pData
->GetSimpleArea( aRange
) != SC_MARK_SIMPLE
)
1084 rSet
.DisableItem( nWhich
);
1089 case FID_DEFINE_NAME
:
1090 case FID_INSERT_NAME
:
1092 case SID_DEFINE_COLROWNAMERANGES
:
1094 if ( pDocSh
&& pDocSh
->IsDocShared() )
1096 rSet
.DisableItem( nWhich
);
1101 case SID_SPELL_DIALOG
:
1103 if ( pDoc
&& pData
&& pDoc
->IsTabProtected( pData
->GetTabNo() ) )
1105 bool bVisible
= false;
1106 SfxViewFrame
* pViewFrame
= ( pTabViewShell
? pTabViewShell
->GetViewFrame() : nullptr );
1107 if ( pViewFrame
&& pViewFrame
->HasChildWindow( nWhich
) )
1109 SfxChildWindow
* pChild
= pViewFrame
->GetChildWindow( nWhich
);
1110 vcl::Window
* pWin
= ( pChild
? pChild
->GetWindow() : nullptr );
1111 if ( pWin
&& pWin
->IsVisible() )
1118 rSet
.DisableItem( nWhich
);
1124 } // switch ( nWitch )
1125 nWhich
= aIter
.NextWhich();
1126 } // while ( nWitch )
1129 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */