Version 5.2.6.1, tag libreoffice-5.2.6.1
[LibreOffice.git] / sc / source / ui / view / cellsh.cxx
blobf8bcb6f6e4ceff180ee3bb8ca2929b65ac87fed1
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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>
41 #include "cellsh.hxx"
42 #include "sc.hrc"
43 #include "docsh.hxx"
44 #include "attrib.hxx"
45 #include "scresid.hxx"
46 #include "tabvwsh.hxx"
47 #include "impex.hxx"
48 #include "formulacell.hxx"
49 #include "scmod.hxx"
50 #include "globstr.hrc"
51 #include "transobj.hxx"
52 #include "drwtrans.hxx"
53 #include "scabstdlg.hxx"
54 #include "dociter.hxx"
55 #include "postit.hxx"
56 #include "cliputil.hxx"
57 #include "clipparam.hxx"
58 #include "markdata.hxx"
59 #include <gridwin.hxx>
61 #define ScCellShell
62 #define CellMovement
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) :
77 ScFormatShell(pData),
78 pImpl( new CellShell_Impl() ),
79 bPastePossible(false)
81 SetHelpId(HID_SCSHELL_CELLSH);
82 SetName("Cell");
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();
106 ScRange aMarkRange;
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();
114 SCCOL nCol1, nCol2;
115 SCROW nRow1, nRow2;
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();
123 while ( nWhich )
125 bool bDisable = false;
126 bool bNeedEdit = true; // need selection be editable?
127 switch ( nWhich )
129 case FID_FILL_TO_BOTTOM: // fill to top / bottom
131 bDisable = !bSimpleArea || (nRow1 == 0 && nRow2 == 0);
132 if (!bDisable && GetViewData()->SelectionForbidsPaste())
133 bDisable = true;
134 if ( !bDisable && bEditable )
135 { // do not damage matrix
136 bDisable = pDoc->HasSelectedBlockMatrixFragment(
137 nCol1, nRow1, nCol2, nRow1, rMark ); // first row
140 break;
141 case FID_FILL_TO_TOP:
143 bDisable = (!bSimpleArea) || (nRow1 == MAXROW && nRow2 == MAXROW);
144 if (!bDisable && GetViewData()->SelectionForbidsPaste())
145 bDisable = true;
146 if ( !bDisable && bEditable )
147 { // do not damage matrix
148 bDisable = pDoc->HasSelectedBlockMatrixFragment(
149 nCol1, nRow2, nCol2, nRow2, rMark ); // last row
152 break;
153 case FID_FILL_TO_RIGHT: // fill to left / right
155 bDisable = !bSimpleArea || (nCol1 == 0 && nCol2 == 0);
156 if (!bDisable && GetViewData()->SelectionForbidsPaste())
157 bDisable = true;
158 if ( !bDisable && bEditable )
159 { // do not damage matrix
160 bDisable = pDoc->HasSelectedBlockMatrixFragment(
161 nCol1, nRow1, nCol1, nRow2, rMark ); // first column
164 break;
165 case FID_FILL_TO_LEFT:
167 bDisable = (!bSimpleArea) || (nCol1 == MAXCOL && nCol2 == MAXCOL);
168 if (!bDisable && GetViewData()->SelectionForbidsPaste())
169 bDisable = true;
170 if ( !bDisable && bEditable )
171 { // do not damage matrix
172 bDisable = pDoc->HasSelectedBlockMatrixFragment(
173 nCol2, nRow1, nCol2, nRow2, rMark ); // last column
176 break;
178 case SID_RANDOM_NUMBER_GENERATOR_DIALOG:
179 bDisable = !bSimpleArea || GetViewData()->SelectionForbidsPaste();
180 break;
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;
189 break;
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)
194 bDisable = true;
195 else
196 bDisable = (!bSimpleArea) || (nCol1 == nCol2 && nRow1 == nRow2);
198 if (!bDisable && GetViewData()->SelectionForbidsPaste())
199 bDisable = true;
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
212 break;
213 case FID_FILL_SINGLE_EDIT:
214 bDisable = false;
215 break;
216 case SID_CUT: // cut
217 case FID_INS_CELL: // insert cells, just simple selection
218 bDisable = (!bSimpleArea);
219 break;
221 case SID_PASTE:
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();
227 break;
229 case FID_INS_ROW:
230 case FID_INS_ROWS_BEFORE: // insert rows
231 case FID_INS_ROWS_AFTER:
232 case FID_INS_CELLSDOWN:
233 bDisable = (!bSimpleArea) || GetViewData()->SimpleColMarked();
234 break;
236 case FID_INS_COLUMN:
237 case FID_INS_COLUMNS_BEFORE: // insert columns
238 case FID_INS_COLUMNS_AFTER:
239 case FID_INS_CELLSRIGHT:
240 bDisable = (!bSimpleArea) || GetViewData()->SimpleRowMarked();
241 break;
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
250 break;
252 case SID_AUTOFORMAT: // Autoformat, at least 3x3 selected
253 bDisable = (!bSimpleArea)
254 || ((nCol2 - nCol1) < 2) || ((nRow2 - nRow1) < 2);
255 break;
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 )
262 bNeedEdit = false;
263 break;
265 case FID_VALIDATION:
267 if ( pDocShell && pDocShell->IsDocShared() )
269 bDisable = true;
272 break;
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 );
279 break;
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);
285 break;
287 if (!bDisable && bNeedEdit && !bEditable)
288 bDisable = true;
290 if (bDisable)
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
302 // Default:
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();
314 while ( nWhich )
316 bool bDisable = false;
317 bool bNeedEdit = true; // need cursor position be editable?
318 switch ( nWhich )
320 case SID_THESAURUS:
322 CellType eType = rDoc.GetCellType( aCursor );
323 bDisable = ( eType != CELLTYPE_STRING && eType != CELLTYPE_EDIT);
324 if (!bDisable)
326 // test for available languages
327 sal_uInt16 nLang = ScViewUtil::GetEffLanguage( &rDoc, aCursor );
328 bDisable = !ScModule::HasThesaurusLanguage( nLang );
331 break;
332 case SID_OPENDLG_FUNCTION:
334 ScMarkData aMarkData = GetViewData()->GetMarkData();
335 aMarkData.MarkToSimple();
336 ScRange aRange;
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() ))
343 bDisable = true;
345 bNeedEdit=false;
349 break;
350 case SID_INSERT_POSTIT:
352 ScAddress aPos( GetViewData()->GetCurX(), GetViewData()->GetCurY(), GetViewData()->GetTabNo() );
353 if( rDoc.GetNote(aPos) )
355 bDisable = true;
357 else
359 bDisable = false;
360 if ( pDocShell && pDocShell->IsDocShared() )
362 bDisable = true;
366 break;
367 case SID_EDIT_POSTIT:
369 ScAddress aPos( GetViewData()->GetCurX(), GetViewData()->GetCurY(), GetViewData()->GetTabNo() );
370 if( rDoc.GetNote(aPos) )
372 bDisable = false;
374 else
376 bDisable = true;
379 break;
381 if (!bDisable && bNeedEdit)
382 if (!rDoc.IsBlockEditable( aCursor.Tab(), aCursor.Col(),aCursor.Row(),
383 aCursor.Col(),aCursor.Row() ))
384 bDisable = true;
385 if (bDisable)
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:
399 OUString aStrVal;
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 )
410 OUString aSource;
411 SvPasteObjectHelper::GetEmbeddedName( rDataHelper, aStrVal, aSource, nFormatId );
414 if ( !aStrVal.isEmpty() )
415 rFormats.AddClipbrdFormat( nFormatId, aStrVal );
416 else
417 rFormats.AddClipbrdFormat( nFormatId );
419 return true;
422 return false;
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 );
439 if ( !bDraw )
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 ) )
461 bPossible = true;
462 else
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 ) )
482 bPossible = true;
485 return bPossible;
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 );
501 namespace {
503 bool checkDestRanges(ScViewData& rViewData)
505 ScRange aDummy;
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)
511 return false;
514 if (rViewData.SelectionForbidsPaste())
515 return false;
517 // Multiple destination ranges.
519 ScDocument* pDoc = rViewData.GetDocument();
520 vcl::Window* pWin = rViewData.GetActiveWin();
521 if (!pWin)
522 return false;
524 ScTransferObj* pOwnClip = ScTransferObj::GetOwnClipboard(pWin);
525 if (!pOwnClip)
526 // If it's not a Calc document, we won't be picky.
527 return true;
529 ScDocument* pClipDoc = pOwnClip->GetDocument();
530 if (!pClipDoc)
531 return false;
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();
538 ScRangeList aRanges;
539 aMark.MarkToSimple();
540 aMark.FillRangeListWithMarks(&aRanges, false);
542 return ScClipUtil::CheckDestRanges(pDoc, nColSize, nRowSize, aMark, aRanges);
547 void ScCellShell::GetClipState( SfxItemSet& rSet )
549 // SID_PASTE
550 // SID_PASTE_SPECIAL
551 // SID_CLIPBOARD_FORMAT_ITEMS
553 if ( !pImpl->m_pClipEvtLstnr )
555 // create listener
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 );
561 // get initial state
562 TransferableDataHelper aDataHelper( TransferableDataHelper::CreateFromSystemClipboard( pWin ) );
563 bPastePossible = lcl_IsCellPastePossible( aDataHelper );
566 bool bDisable = !bPastePossible;
568 // cell protection / multiple selection
570 if (!bDisable)
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 ))
577 bDisable = true;
579 if (!bDisable && !checkDestRanges(*GetViewData()))
580 bDisable = true;
583 if (bDisable)
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();
632 while ( nWhich )
634 switch ( nWhich )
636 case SID_DETECTIVE_REFRESH:
637 if (!pDoc->HasDetectiveOperations())
638 rSet.DisableItem( nWhich );
639 break;
641 case SID_RANGE_ADDRESS:
643 ScRange aRange;
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 ) );
650 break;
652 case SID_RANGE_NOTETEXT:
654 // always take cursor position, do not use top-left cell of selection
655 OUString aNoteText;
656 if ( const ScPostIt* pNote = pDoc->GetNote(nPosX, nPosY, nTab) )
657 aNoteText = pNote->GetText();
658 rSet.Put( SfxStringItem( nWhich, aNoteText ) );
660 break;
662 case SID_RANGE_ROW:
663 rSet.Put( SfxInt32Item( nWhich, nPosY+1 ) );
664 break;
666 case SID_RANGE_COL:
667 rSet.Put( SfxInt16Item( nWhich, nPosX+1 ) );
668 break;
670 case SID_RANGE_TABLE:
671 rSet.Put( SfxInt16Item( nWhich, nTab+1 ) );
672 break;
674 case SID_RANGE_VALUE:
676 double nValue;
677 pDoc->GetValue( nPosX, nPosY, nTab, nValue );
678 rSet.Put( ScDoubleItem( nWhich, nValue ) );
680 break;
682 case SID_RANGE_FORMULA:
684 OUString aString;
685 pDoc->GetFormula( nPosX, nPosY, nTab, aString );
686 if( aString.isEmpty() )
688 pDoc->GetInputString( nPosX, nPosY, nTab, aString );
690 rSet.Put( SfxStringItem( nWhich, aString ) );
692 break;
694 case SID_RANGE_TEXTVALUE:
696 OUString aString = pDoc->GetString(nPosX, nPosY, nTab);
697 rSet.Put( SfxStringItem( nWhich, aString ) );
699 break;
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();
709 switch ( nMode )
711 case KEY_SHIFT: nMode = 1; break;
712 case KEY_MOD1: nMode = 2; break; // Control-key
713 case 0:
714 default:
715 nMode = 0;
718 rSet.Put( SfxUInt16Item( nWhich, nMode ) );
720 break;
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 ) ); }
730 break;
732 case SID_ROWCOL_SELCOUNT:
734 ScRange aMarkRange;
735 GetViewData()->GetSimpleArea( aMarkRange );
736 SCCOL nCol1, nCol2;
737 SCROW nRow1, nRow2;
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 ) );
749 else
751 SCSIZE nSelected, nTotal;
752 pDoc->GetFilterSelCount( nPosX, nPosY, nTab, nSelected, nTotal );
753 if( 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 ) );
762 break;
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.
768 case SID_TABLE_CELL:
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("...") ) );
776 else
778 sal_uInt16 nErrCode = 0;
779 ScFormulaCell* pCell = pDoc->GetFormulaCell(ScAddress(nPosX, nPosY, nTab));
780 if (pCell)
782 if (!pCell->IsRunning())
783 nErrCode = pCell->GetErrCode();
786 OUString aFuncStr;
787 if ( pTabViewShell->GetFunction( aFuncStr, nErrCode ) )
788 rSet.Put( SfxStringItem( nWhich, aFuncStr ) );
791 break;
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 );
799 break;
801 case SID_STATUS_SUM:
803 OUString aFuncStr;
804 if ( pTabViewShell->GetFunction( aFuncStr ) )
805 rSet.Put( SfxStringItem( nWhich, aFuncStr ) );
807 break;
809 case FID_MERGE_ON:
810 if ( pDoc->GetChangeTrack() || !pTabViewShell->TestMergeCells() )
811 rSet.DisableItem( nWhich );
812 break;
814 case FID_MERGE_OFF:
815 if ( pDoc->GetChangeTrack() || !pTabViewShell->TestRemoveMerge() )
816 rSet.DisableItem( nWhich );
817 break;
819 case FID_MERGE_TOGGLE:
820 if ( pDoc->GetChangeTrack() )
821 rSet.DisableItem( nWhich );
822 else
824 bool bCanMerge = pTabViewShell->TestMergeCells();
825 bool bCanSplit = pTabViewShell->TestRemoveMerge();
826 if( !bCanMerge && !bCanSplit )
827 rSet.DisableItem( nWhich );
828 else
829 rSet.Put( SfxBoolItem( nWhich, bCanSplit ) );
831 break;
833 case FID_INS_ROWBRK:
834 if ( nPosY==0 || (pDoc->HasRowBreak(nPosY, nTab) & BREAK_MANUAL) )
835 rSet.DisableItem( nWhich );
836 break;
838 case FID_INS_COLBRK:
839 if ( nPosX==0 || (pDoc->HasColBreak(nPosX, nTab) & BREAK_MANUAL) )
840 rSet.DisableItem( nWhich );
841 break;
843 case FID_DEL_ROWBRK:
844 if ( nPosY==0 || (pDoc->HasRowBreak(nPosY, nTab) & BREAK_MANUAL) == 0 )
845 rSet.DisableItem( nWhich );
846 break;
848 case FID_DEL_COLBRK:
849 if ( nPosX==0 || (pDoc->HasColBreak(nPosX, nTab) & BREAK_MANUAL) == 0 )
850 rSet.DisableItem( nWhich );
851 break;
853 case FID_FILL_TAB:
854 if ( nTabSelCount < 2 )
855 rSet.DisableItem( nWhich );
856 break;
858 case SID_SELECT_SCENARIO:
860 std::vector<OUString> aList;
861 Color aDummyCol;
863 if ( !pDoc->IsScenario(nTab) )
865 OUString aStr;
866 sal_uInt16 nFlags;
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"));
878 ++nScTab;
881 else
883 OUString aComment;
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 ) );
892 break;
894 case FID_ROW_HIDE:
895 case FID_ROW_SHOW:
896 case FID_COL_HIDE:
897 case FID_COL_SHOW:
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 );
903 break;
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 );
917 break;
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 );
926 break;
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 );
936 break;
938 case SID_OUTLINE_REMOVE:
940 if ( GetViewData()->GetDocument()->GetDPAtCursor( GetViewData()->GetCurX(),
941 GetViewData()->GetCurY(), GetViewData()->GetTabNo() ) )
943 //! test for data pilot operation
945 else
947 bool bCol, bRow;
948 pTabViewShell->TestRemoveOutline( bCol, bRow );
949 if ( !bCol && !bRow )
950 rSet.DisableItem( nWhich );
953 break;
955 case FID_COL_WIDTH:
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
964 break;
966 case FID_ROW_HEIGHT:
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 );
974 break;
976 case SID_DETECTIVE_FILLMODE:
977 rSet.Put(SfxBoolItem( nWhich, pTabViewShell->IsAuditShell() ));
978 break;
980 case FID_INPUTLINE_STATUS:
981 OSL_FAIL( "Old update method. Use ScTabViewShell::UpdateInputHandler()." );
982 break;
984 case SID_SCENARIOS: // scenarios:
985 if (!(rMark.IsMarked() || rMark.IsMultiMarked())) // only, if something selected
986 rSet.DisableItem( nWhich );
987 break;
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() ) );
994 else
995 rSet.DisableItem( nWhich );
997 break;
999 case FID_HIDE_NOTE:
1000 case FID_SHOW_NOTE:
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)
1010 bEnable = true;
1012 else
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)
1028 bEnable = true;
1029 break;
1035 if ( !bEnable )
1036 rSet.DisableItem( nWhich );
1038 break;
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 );
1053 else
1055 bEnable = pDoc->IsBlockEditable( nTab, nPosX,nPosY, nPosX,nPosY ) &&
1056 pDoc->GetNote(nPosX, nPosY, nTab);
1058 if ( !bEnable )
1059 rSet.DisableItem( nWhich );
1061 break;
1063 case SID_OPENDLG_CONSOLIDATE:
1064 case SCITEM_CONSOLIDATEDATA:
1066 if(pDoc->GetChangeTrack()!=nullptr)
1067 rSet.DisableItem( nWhich);
1069 break;
1071 case SID_CHINESE_CONVERSION:
1072 case SID_HANGUL_HANJA_CONVERSION:
1073 ScViewUtil::HideDisabledSlot( rSet, pData->GetBindings(), nWhich );
1074 break;
1076 case FID_USE_NAME:
1078 if ( pDocSh && pDocSh->IsDocShared() )
1079 rSet.DisableItem( nWhich );
1080 else
1082 ScRange aRange;
1083 if ( pData->GetSimpleArea( aRange ) != SC_MARK_SIMPLE )
1084 rSet.DisableItem( nWhich );
1087 break;
1089 case FID_DEFINE_NAME:
1090 case FID_INSERT_NAME:
1091 case FID_ADD_NAME:
1092 case SID_DEFINE_COLROWNAMERANGES:
1094 if ( pDocSh && pDocSh->IsDocShared() )
1096 rSet.DisableItem( nWhich );
1099 break;
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() )
1113 bVisible = true;
1116 if ( !bVisible )
1118 rSet.DisableItem( nWhich );
1122 break;
1124 } // switch ( nWitch )
1125 nWhich = aIter.NextWhich();
1126 } // while ( nWitch )
1129 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */