1709 lines
56 KiB
C++
1709 lines
56 KiB
C++
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
/*
|
|
* This file is part of the LibreOffice project.
|
|
*
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
*
|
|
* This file incorporates work covered by the following license notice:
|
|
*
|
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
* contributor license agreements. See the NOTICE file distributed
|
|
* with this work for additional information regarding copyright
|
|
* ownership. The ASF licenses this file to you under the Apache
|
|
* License, Version 2.0 (the "License"); you may not use this file
|
|
* except in compliance with the License. You may obtain a copy of
|
|
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
|
|
*/
|
|
|
|
#include <scitems.hxx>
|
|
#include <vcl/svapp.hxx>
|
|
#include <vcl/weld.hxx>
|
|
#include <sfx2/bindings.hxx>
|
|
#include <osl/diagnose.h>
|
|
|
|
#include <attrib.hxx>
|
|
#include <pagedata.hxx>
|
|
#include <tabview.hxx>
|
|
#include <tabvwsh.hxx>
|
|
#include <printfun.hxx>
|
|
#include <stlpool.hxx>
|
|
#include <docsh.hxx>
|
|
#include <gridwin.hxx>
|
|
#include <sc.hrc>
|
|
#include <viewutil.hxx>
|
|
#include <colrowba.hxx>
|
|
#include <globstr.hrc>
|
|
#include <scresid.hxx>
|
|
#include <scmod.hxx>
|
|
#include <table.hxx>
|
|
#include <tabprotection.hxx>
|
|
#include <markdata.hxx>
|
|
#include <inputopt.hxx>
|
|
#include <comphelper/lok.hxx>
|
|
|
|
namespace {
|
|
|
|
bool isCellQualified(const ScDocument* pDoc, SCCOL nCol, SCROW nRow, SCTAB nTab, bool bSelectLocked, bool bSelectUnlocked)
|
|
{
|
|
bool bCellProtected = pDoc->HasAttrib(
|
|
nCol, nRow, nTab, nCol, nRow, nTab, HasAttrFlags::Protected);
|
|
|
|
if (bCellProtected && !bSelectLocked)
|
|
return false;
|
|
|
|
if (!bCellProtected && !bSelectUnlocked)
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
bool areCellsQualified(const ScDocument* pDoc, SCCOL nColStart, SCROW nRowStart, SCCOL nColEnd,
|
|
SCROW nRowEnd, SCTAB nTab, bool bSelectLocked, bool bSelectUnlocked)
|
|
{
|
|
PutInOrder(nColStart, nColEnd);
|
|
PutInOrder(nRowStart, nRowEnd);
|
|
for (SCCOL col = nColStart; col <= nColEnd; ++col)
|
|
for (SCROW row = nRowStart; row <= nRowEnd; ++row)
|
|
if (!isCellQualified(pDoc, col, row, nTab, bSelectLocked, bSelectUnlocked))
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
void moveCursorByProtRule(
|
|
SCCOL& rCol, SCROW& rRow, SCCOL nMovX, SCROW nMovY, SCTAB nTab, const ScDocument* pDoc)
|
|
{
|
|
bool bSelectLocked = true;
|
|
bool bSelectUnlocked = true;
|
|
const ScTableProtection* pTabProtection = pDoc->GetTabProtection(nTab);
|
|
if (pTabProtection && pTabProtection->isProtected())
|
|
{
|
|
bSelectLocked = pTabProtection->isOptionEnabled(ScTableProtection::SELECT_LOCKED_CELLS);
|
|
bSelectUnlocked = pTabProtection->isOptionEnabled(ScTableProtection::SELECT_UNLOCKED_CELLS);
|
|
}
|
|
|
|
if (nMovX > 0)
|
|
{
|
|
for (SCCOL i = 0; i < nMovX && rCol < pDoc->MaxCol(); ++i)
|
|
{
|
|
SCCOL nNewUnhiddenCol = rCol + 1;
|
|
SCCOL nEndCol = 0;
|
|
while(pDoc->ColHidden(nNewUnhiddenCol, nTab, nullptr, &nEndCol))
|
|
{
|
|
if(nNewUnhiddenCol >= pDoc->MaxCol())
|
|
return;
|
|
|
|
i += nEndCol - nNewUnhiddenCol + 1;
|
|
nNewUnhiddenCol = nEndCol +1;
|
|
}
|
|
|
|
if (!isCellQualified(pDoc, nNewUnhiddenCol, rRow, nTab, bSelectLocked, bSelectUnlocked))
|
|
break;
|
|
rCol = nNewUnhiddenCol;
|
|
}
|
|
}
|
|
else if (nMovX < 0)
|
|
{
|
|
for (SCCOL i = 0; i > nMovX && rCol > 0; --i)
|
|
{
|
|
SCCOL nNewUnhiddenCol = rCol - 1;
|
|
SCCOL nStartCol = 0;
|
|
while(pDoc->ColHidden(nNewUnhiddenCol, nTab, &nStartCol))
|
|
{
|
|
if(nNewUnhiddenCol <= 0)
|
|
return;
|
|
|
|
i -= nNewUnhiddenCol - nStartCol + 1;
|
|
nNewUnhiddenCol = nStartCol - 1;
|
|
}
|
|
|
|
if (!isCellQualified(pDoc, nNewUnhiddenCol, rRow, nTab, bSelectLocked, bSelectUnlocked))
|
|
break;
|
|
rCol = nNewUnhiddenCol;
|
|
}
|
|
}
|
|
|
|
if (nMovY > 0)
|
|
{
|
|
for (SCROW i = 0; i < nMovY && rRow < pDoc->MaxRow(); ++i)
|
|
{
|
|
SCROW nNewUnhiddenRow = rRow + 1;
|
|
SCROW nEndRow = 0;
|
|
while(pDoc->RowHidden(nNewUnhiddenRow, nTab, nullptr, &nEndRow))
|
|
{
|
|
if(nNewUnhiddenRow >= pDoc->MaxRow())
|
|
return;
|
|
|
|
i += nEndRow - nNewUnhiddenRow + 1;
|
|
nNewUnhiddenRow = nEndRow + 1;
|
|
}
|
|
|
|
if (!isCellQualified(pDoc, rCol, nNewUnhiddenRow, nTab, bSelectLocked, bSelectUnlocked))
|
|
break;
|
|
rRow = nNewUnhiddenRow;
|
|
}
|
|
}
|
|
else if (nMovY < 0)
|
|
{
|
|
for (SCROW i = 0; i > nMovY && rRow > 0; --i)
|
|
{
|
|
SCROW nNewUnhiddenRow = rRow - 1;
|
|
SCROW nStartRow = 0;
|
|
while(pDoc->RowHidden(nNewUnhiddenRow, nTab, &nStartRow))
|
|
{
|
|
if(nNewUnhiddenRow <= 0)
|
|
return;
|
|
|
|
i -= nNewUnhiddenRow - nStartRow + 1;
|
|
nNewUnhiddenRow = nStartRow - 1;
|
|
}
|
|
|
|
if (!isCellQualified(pDoc, rCol, nNewUnhiddenRow, nTab, bSelectLocked, bSelectUnlocked))
|
|
break;
|
|
rRow = nNewUnhiddenRow;
|
|
}
|
|
}
|
|
}
|
|
|
|
bool checkBoundary(const ScDocument* pDoc, SCCOL& rCol, SCROW& rRow)
|
|
{
|
|
bool bGood = true;
|
|
if (rCol < 0)
|
|
{
|
|
rCol = 0;
|
|
bGood = false;
|
|
}
|
|
else if (rCol > pDoc->MaxCol())
|
|
{
|
|
rCol = pDoc->MaxCol();
|
|
bGood = false;
|
|
}
|
|
|
|
if (rRow < 0)
|
|
{
|
|
rRow = 0;
|
|
bGood = false;
|
|
}
|
|
else if (rRow > pDoc->MaxRow())
|
|
{
|
|
rRow = pDoc->MaxRow();
|
|
bGood = false;
|
|
}
|
|
return bGood;
|
|
}
|
|
|
|
void moveRefByCell(SCCOL& rNewX, SCROW& rNewY,
|
|
SCCOL nMovX, SCROW nMovY, SCTAB nRefTab,
|
|
const ScDocument& rDoc)
|
|
{
|
|
SCCOL nOldX = rNewX;
|
|
SCROW nOldY = rNewY;
|
|
bool bSelectLocked = true;
|
|
bool bSelectUnlocked = true;
|
|
const ScTableProtection* pTabProtection = rDoc.GetTabProtection(nRefTab);
|
|
if (pTabProtection && pTabProtection->isProtected())
|
|
{
|
|
bSelectLocked = pTabProtection->isOptionEnabled(ScTableProtection::SELECT_LOCKED_CELLS);
|
|
bSelectUnlocked = pTabProtection->isOptionEnabled(ScTableProtection::SELECT_UNLOCKED_CELLS);
|
|
}
|
|
|
|
moveCursorByProtRule(rNewX, rNewY, nMovX, nMovY, nRefTab, &rDoc);
|
|
checkBoundary(&rDoc, rNewX, rNewY);
|
|
|
|
if (nMovX)
|
|
{
|
|
SCCOL nTempX = rNewX;
|
|
while (rDoc.IsHorOverlapped(nTempX, rNewY, nRefTab))
|
|
{
|
|
nTempX = (nMovX > 0) ? nTempX + 1 : nTempX - 1;
|
|
if (!checkBoundary(&rDoc, nTempX, rNewY))
|
|
break;
|
|
}
|
|
if (isCellQualified(&rDoc, nTempX, rNewY, nRefTab, bSelectLocked, bSelectUnlocked))
|
|
rNewX = nTempX;
|
|
|
|
if (nMovX < 0 && rNewX > 0)
|
|
{
|
|
const ScMergeAttr* pMergeAttr = rDoc.GetAttr(rNewX, rNewY, nRefTab, ATTR_MERGE);
|
|
if (pMergeAttr && pMergeAttr->IsMerged() &&
|
|
nOldX >= rNewX &&
|
|
nOldX <= rNewX + pMergeAttr->GetRowMerge() - 1)
|
|
rNewX = rNewX - 1;
|
|
}
|
|
}
|
|
|
|
if (nMovY)
|
|
{
|
|
SCROW nTempY = rNewY;
|
|
while (rDoc.IsVerOverlapped(rNewX, nTempY, nRefTab))
|
|
{
|
|
nTempY = (nMovY > 0) ? nTempY + 1 : nTempY - 1;
|
|
if (!checkBoundary(&rDoc, rNewX, nTempY))
|
|
break;
|
|
}
|
|
if (isCellQualified(&rDoc, rNewX, nTempY, nRefTab, bSelectLocked, bSelectUnlocked))
|
|
rNewY = nTempY;
|
|
|
|
if (nMovY < 0 && rNewY > 0)
|
|
{
|
|
const ScMergeAttr* pMergeAttr = rDoc.GetAttr(rNewX, rNewY, nRefTab, ATTR_MERGE);
|
|
if (pMergeAttr && pMergeAttr->IsMerged() &&
|
|
nOldY >= rNewY &&
|
|
nOldY <= rNewY + pMergeAttr->GetRowMerge() - 1)
|
|
rNewY = rNewY - 1;
|
|
}
|
|
}
|
|
|
|
rDoc.SkipOverlapped(rNewX, rNewY, nRefTab);
|
|
}
|
|
|
|
void moveCursorByMergedCell(SCCOL& rCol, SCROW& rRow, SCCOL nMovX, SCROW nMovY, SCCOL nStartX,
|
|
SCROW nStartY, SCTAB nTab, const ScDocument* pDoc)
|
|
{
|
|
const ScTableProtection* pTabProtection = pDoc->GetTabProtection(nTab);
|
|
bool bSelectLocked = true;
|
|
bool bSelectUnlocked = true;
|
|
if (pTabProtection && pTabProtection->isProtected())
|
|
{
|
|
bSelectLocked = pTabProtection->isOptionEnabled(ScTableProtection::SELECT_LOCKED_CELLS);
|
|
bSelectUnlocked = pTabProtection->isOptionEnabled(ScTableProtection::SELECT_UNLOCKED_CELLS);
|
|
}
|
|
|
|
if (nMovX > 0)
|
|
{
|
|
SCROW rowStart = std::min(rRow, nStartY);
|
|
SCROW rowEnd = std::max(rRow, nStartY);
|
|
|
|
for (SCROW i = rowStart; i <= rowEnd && rCol < nStartX;)
|
|
{
|
|
SCCOL tmpCol = rCol;
|
|
while (tmpCol < pDoc->MaxCol() && pDoc->IsHorOverlapped(tmpCol, i, nTab))
|
|
++tmpCol;
|
|
if (tmpCol != rCol)
|
|
{
|
|
i = rowStart;
|
|
if (tmpCol > nStartX)
|
|
--tmpCol;
|
|
if (!areCellsQualified(pDoc, rCol + 1, rowStart, tmpCol, rowEnd, nTab,
|
|
bSelectLocked, bSelectUnlocked))
|
|
break;
|
|
rCol = tmpCol;
|
|
}
|
|
else
|
|
++i;
|
|
}
|
|
}
|
|
else if (nMovX < 0)
|
|
{
|
|
SCROW rowStart = std::min(rRow, nStartY);
|
|
SCROW rowEnd = std::max(rRow, nStartY);
|
|
|
|
for (SCROW i = rowStart; i <= rowEnd && rCol > nStartX;)
|
|
{
|
|
SCCOL tmpCol = rCol;
|
|
while (tmpCol >= 0 && pDoc->IsHorOverlapped(tmpCol + 1, i, nTab))
|
|
--tmpCol;
|
|
if (tmpCol != rCol)
|
|
{
|
|
i = rowStart;
|
|
if (tmpCol < nStartX)
|
|
++tmpCol;
|
|
if (!areCellsQualified(pDoc, rCol - 1, rowStart, tmpCol, rowEnd, nTab,
|
|
bSelectLocked, bSelectUnlocked))
|
|
break;
|
|
rCol = tmpCol;
|
|
}
|
|
else
|
|
++i;
|
|
}
|
|
}
|
|
|
|
if (nMovY > 0)
|
|
{
|
|
SCCOL colStart = std::min(rCol, nStartX);
|
|
SCCOL colEnd = std::max(rCol, nStartX);
|
|
|
|
for (SCCOL i = colStart; i <= colEnd && rRow < nStartY;)
|
|
{
|
|
SCROW tmpRow = rRow;
|
|
while (tmpRow < pDoc->MaxRow() && pDoc->IsVerOverlapped(i, tmpRow, nTab))
|
|
++tmpRow;
|
|
if (tmpRow != rRow)
|
|
{
|
|
i = colStart;
|
|
if (tmpRow > nStartY)
|
|
--tmpRow;
|
|
if (!areCellsQualified(pDoc, colStart, rRow + 1, colEnd, tmpRow, nTab,
|
|
bSelectLocked, bSelectUnlocked))
|
|
break;
|
|
rRow = tmpRow;
|
|
}
|
|
else
|
|
++i;
|
|
}
|
|
}
|
|
else if (nMovY < 0)
|
|
{
|
|
SCCOL colStart = std::min(rCol, nStartX);
|
|
SCCOL colEnd = std::max(rCol, nStartX);
|
|
|
|
for (SCCOL i = colStart; i <= colEnd && rRow > nStartY;)
|
|
{
|
|
SCROW tmpRow = rRow;
|
|
while (tmpRow >= 0 && pDoc->IsVerOverlapped(i, tmpRow + 1, nTab))
|
|
--tmpRow;
|
|
if (tmpRow != rRow)
|
|
{
|
|
i = colStart;
|
|
if (tmpRow < nStartY)
|
|
++tmpRow;
|
|
if (!areCellsQualified(pDoc, colStart, rRow - 1, colEnd, tmpRow, nTab,
|
|
bSelectLocked, bSelectUnlocked))
|
|
break;
|
|
rRow = tmpRow;
|
|
}
|
|
else
|
|
++i;
|
|
}
|
|
}
|
|
}
|
|
|
|
void moveCursorToProperSide(SCCOL& rCol, SCROW& rRow, SCCOL nMovX, SCROW nMovY, SCCOL nStartX,
|
|
SCROW nStartY, SCTAB nTab, const ScDocument* pDoc)
|
|
{
|
|
SCCOL tmpCol = rCol;
|
|
SCROW tmpRow = rRow;
|
|
|
|
if (nMovX > 0 && nStartX < pDoc->MaxCol() && rCol < nStartX)
|
|
{
|
|
SCROW rowStart = std::min(rRow, nStartY);
|
|
SCROW rowEnd = std::max(rRow, nStartY);
|
|
for (SCROW i = rowStart; i <= rowEnd && tmpCol < nStartX;)
|
|
{
|
|
if (pDoc->IsHorOverlapped(tmpCol + 1, i, nTab))
|
|
{
|
|
do
|
|
{
|
|
++tmpCol;
|
|
} while (pDoc->IsHorOverlapped(tmpCol + 1, i, nTab));
|
|
i = rowStart;
|
|
}
|
|
else
|
|
++i;
|
|
}
|
|
if (tmpCol < nStartX)
|
|
tmpCol = rCol;
|
|
}
|
|
else if (nMovX < 0 && nStartX > 0 && rCol > nStartX)
|
|
{
|
|
SCROW rowStart = std::min(rRow, nStartY);
|
|
SCROW rowEnd = std::max(rRow, nStartY);
|
|
for (SCROW i = rowStart; i <= rowEnd && tmpCol > nStartX;)
|
|
{
|
|
if (pDoc->IsHorOverlapped(tmpCol, i, nTab))
|
|
{
|
|
do
|
|
{
|
|
--tmpCol;
|
|
} while (pDoc->IsHorOverlapped(tmpCol, i, nTab));
|
|
i = rowStart;
|
|
}
|
|
else
|
|
++i;
|
|
}
|
|
if (tmpCol > nStartX)
|
|
tmpCol = rCol;
|
|
}
|
|
|
|
if (nMovY > 0 && nStartY < pDoc->MaxRow() && rRow < nStartY)
|
|
{
|
|
SCCOL colStart = std::min(rCol, nStartX);
|
|
SCCOL colEnd = std::max(rCol, nStartX);
|
|
for (SCCOL i = colStart; i <= colEnd && tmpRow < nStartY;)
|
|
{
|
|
if (pDoc->IsVerOverlapped(i, tmpRow + 1, nTab))
|
|
{
|
|
do
|
|
{
|
|
++tmpRow;
|
|
} while (pDoc->IsVerOverlapped(i, tmpRow + 1, nTab));
|
|
i = colStart;
|
|
}
|
|
else
|
|
++i;
|
|
}
|
|
if (tmpRow < nStartY)
|
|
tmpRow = rRow;
|
|
}
|
|
else if (nMovY < 0 && nStartY > 0 && rRow > nStartY)
|
|
{
|
|
SCCOL colStart = std::min(rCol, nStartX);
|
|
SCCOL colEnd = std::max(rCol, nStartX);
|
|
for (SCCOL i = colStart; i <= colEnd && tmpRow > nStartY;)
|
|
{
|
|
if (pDoc->IsVerOverlapped(i, tmpRow, nTab))
|
|
{
|
|
do
|
|
{
|
|
--tmpRow;
|
|
} while (pDoc->IsVerOverlapped(i, tmpRow, nTab));
|
|
i = colStart;
|
|
}
|
|
else
|
|
++i;
|
|
}
|
|
if (tmpRow > nStartY)
|
|
tmpRow = rRow;
|
|
}
|
|
|
|
if (tmpCol != rCol)
|
|
rCol = tmpCol;
|
|
if (tmpRow != rRow)
|
|
rRow = tmpRow;
|
|
}
|
|
}
|
|
|
|
void ScTabView::PaintMarks(SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow )
|
|
{
|
|
auto& rDoc = aViewData.GetDocument();
|
|
if (!rDoc.ValidCol(nStartCol)) nStartCol = rDoc.MaxCol();
|
|
if (!rDoc.ValidRow(nStartRow)) nStartRow = rDoc.MaxRow();
|
|
if (!rDoc.ValidCol(nEndCol)) nEndCol = rDoc.MaxCol();
|
|
if (!rDoc.ValidRow(nEndRow)) nEndRow = rDoc.MaxRow();
|
|
|
|
bool bLeft = (nStartCol==0 && nEndCol==rDoc.MaxCol());
|
|
bool bTop = (nStartRow==0 && nEndRow==rDoc.MaxRow());
|
|
|
|
if (bLeft)
|
|
PaintLeftArea( nStartRow, nEndRow );
|
|
if (bTop)
|
|
PaintTopArea( nStartCol, nEndCol );
|
|
|
|
aViewData.GetDocument().ExtendMerge( nStartCol, nStartRow, nEndCol, nEndRow,
|
|
aViewData.GetTabNo() );
|
|
PaintArea( nStartCol, nStartRow, nEndCol, nEndRow, ScUpdateMode::Marks );
|
|
}
|
|
|
|
bool ScTabView::IsMarking( SCCOL nCol, SCROW nRow, SCTAB nTab ) const
|
|
{
|
|
return IsBlockMode()
|
|
&& nBlockStartX == nCol
|
|
&& nBlockStartY == nRow
|
|
&& nBlockStartZ == nTab;
|
|
}
|
|
|
|
void ScTabView::InitOwnBlockMode( const ScRange& rMarkRange )
|
|
{
|
|
if (IsBlockMode())
|
|
return;
|
|
|
|
// when there is no (old) selection anymore, delete anchor in SelectionEngine:
|
|
ScMarkData& rMark = aViewData.GetMarkData();
|
|
if (!rMark.IsMarked() && !rMark.IsMultiMarked())
|
|
GetSelEngine()->CursorPosChanging( false, false );
|
|
|
|
meBlockMode = Own;
|
|
nBlockStartX = rMarkRange.aStart.Col();
|
|
nBlockStartY = rMarkRange.aStart.Row();
|
|
nBlockStartZ = rMarkRange.aStart.Tab();
|
|
nBlockEndX = rMarkRange.aEnd.Col();
|
|
nBlockEndY = rMarkRange.aEnd.Row();
|
|
nBlockEndZ = rMarkRange.aEnd.Tab();
|
|
|
|
SelectionChanged(); // status is checked with mark set
|
|
}
|
|
|
|
void ScTabView::InitBlockModeHighlight( SCCOL nCurX, SCROW nCurY, SCTAB nCurZ,
|
|
bool bCols, bool bRows )
|
|
{
|
|
if (meHighlightBlockMode != None)
|
|
return;
|
|
|
|
auto& rDoc = aViewData.GetDocument();
|
|
if (!rDoc.ValidCol(nCurX)) nCurX = rDoc.MaxCol();
|
|
if (!rDoc.ValidRow(nCurY)) nCurY = rDoc.MaxRow();
|
|
|
|
ScMarkData& rMark = aViewData.GetHighlightData();
|
|
meHighlightBlockMode = Normal;
|
|
|
|
SCROW nStartY = nCurY;
|
|
SCCOL nStartX = nCurX;
|
|
SCROW nEndY = nCurY;
|
|
SCCOL nEndX = nCurX;
|
|
|
|
if (bCols)
|
|
{
|
|
nStartY = 0;
|
|
nEndY = rDoc.MaxRow();
|
|
}
|
|
|
|
if (bRows)
|
|
{
|
|
nStartX = 0;
|
|
nEndX = rDoc.MaxCol();
|
|
}
|
|
|
|
rMark.SetMarkArea( ScRange( nStartX, nStartY, nCurZ, nEndX, nEndY, nCurZ ) );
|
|
UpdateHighlightOverlay();
|
|
}
|
|
|
|
void ScTabView::InitBlockMode( SCCOL nCurX, SCROW nCurY, SCTAB nCurZ,
|
|
bool bTestNeg, bool bCols, bool bRows, bool bForceNeg )
|
|
{
|
|
if (IsBlockMode())
|
|
return;
|
|
|
|
auto& rDoc = aViewData.GetDocument();
|
|
if (!rDoc.ValidCol(nCurX)) nCurX = rDoc.MaxCol();
|
|
if (!rDoc.ValidRow(nCurY)) nCurY = rDoc.MaxRow();
|
|
|
|
ScMarkData& rMark = aViewData.GetMarkData();
|
|
SCTAB nTab = aViewData.GetTabNo();
|
|
|
|
// unmark part?
|
|
if (bForceNeg)
|
|
bBlockNeg = true;
|
|
else if (bTestNeg)
|
|
{
|
|
if ( bCols )
|
|
bBlockNeg = rMark.IsColumnMarked( nCurX );
|
|
else if ( bRows )
|
|
bBlockNeg = rMark.IsRowMarked( nCurY );
|
|
else
|
|
bBlockNeg = rMark.IsCellMarked( nCurX, nCurY );
|
|
}
|
|
else
|
|
bBlockNeg = false;
|
|
rMark.SetMarkNegative(bBlockNeg);
|
|
|
|
meBlockMode = Normal;
|
|
bBlockCols = bCols;
|
|
bBlockRows = bRows;
|
|
nBlockStartX = nBlockStartXOrig = nCurX;
|
|
nBlockStartY = nBlockStartYOrig = nCurY;
|
|
nBlockStartZ = nCurZ;
|
|
nBlockEndX = nOldCurX = nBlockStartX;
|
|
nBlockEndY = nOldCurY = nBlockStartY;
|
|
nBlockEndZ = nBlockStartZ;
|
|
|
|
if (bBlockCols)
|
|
{
|
|
nBlockStartY = nBlockStartYOrig = 0;
|
|
nBlockEndY = rDoc.MaxRow();
|
|
}
|
|
|
|
if (bBlockRows)
|
|
{
|
|
nBlockStartX = nBlockStartXOrig = 0;
|
|
nBlockEndX = rDoc.MaxCol();
|
|
}
|
|
|
|
rMark.SetMarkArea( ScRange( nBlockStartX,nBlockStartY, nTab, nBlockEndX,nBlockEndY, nTab ) );
|
|
|
|
UpdateSelectionOverlay();
|
|
}
|
|
|
|
void ScTabView::DoneBlockModeHighlight( bool bContinue )
|
|
{
|
|
if (meHighlightBlockMode == None)
|
|
return;
|
|
|
|
ScMarkData& rMark = aViewData.GetHighlightData();
|
|
bool bFlag = rMark.GetMarkingFlag();
|
|
rMark.SetMarking(false);
|
|
|
|
if (bContinue)
|
|
rMark.MarkToMulti();
|
|
else
|
|
{
|
|
SCTAB nTab = aViewData.GetTabNo();
|
|
ScDocument& rDoc = aViewData.GetDocument();
|
|
if ( rDoc.HasTable(nTab) )
|
|
rMark.ResetMark();
|
|
}
|
|
meHighlightBlockMode = None;
|
|
|
|
rMark.SetMarking(bFlag);
|
|
if (bContinue)
|
|
rMark.SetMarking(false);
|
|
}
|
|
|
|
void ScTabView::DoneBlockMode( bool bContinue )
|
|
{
|
|
// When switching between sheet and header SelectionEngine DeselectAll may be called,
|
|
// because the other engine does not have any anchor.
|
|
// bMoveIsShift prevents the selection to be canceled.
|
|
|
|
if (!IsBlockMode() || bMoveIsShift)
|
|
return;
|
|
|
|
ScMarkData& rMark = aViewData.GetMarkData();
|
|
bool bFlag = rMark.GetMarkingFlag();
|
|
rMark.SetMarking(false);
|
|
|
|
if (bBlockNeg && !bContinue)
|
|
rMark.MarkToMulti();
|
|
|
|
if (bContinue)
|
|
rMark.MarkToMulti();
|
|
else
|
|
{
|
|
// the sheet may be invalid at this point because DoneBlockMode from SetTabNo is
|
|
// called (for example, when the current sheet is closed from another View)
|
|
SCTAB nTab = aViewData.GetTabNo();
|
|
ScDocument& rDoc = aViewData.GetDocument();
|
|
if ( rDoc.HasTable(nTab) )
|
|
PaintBlock( true ); // true -> delete block
|
|
else
|
|
rMark.ResetMark();
|
|
}
|
|
meBlockMode = None;
|
|
|
|
rMark.SetMarking(bFlag);
|
|
rMark.SetMarkNegative(false);
|
|
}
|
|
|
|
bool ScTabView::IsBlockMode() const
|
|
{
|
|
return meBlockMode != None;
|
|
}
|
|
|
|
void ScTabView::MarkCursor( SCCOL nCurX, SCROW nCurY, SCTAB nCurZ,
|
|
bool bCols, bool bRows, bool bCellSelection )
|
|
{
|
|
ScDocument& rDocument = aViewData.GetDocument();
|
|
if (!rDocument.ValidCol(nCurX)) nCurX = rDocument.MaxCol();
|
|
if (!rDocument.ValidRow(nCurY)) nCurY = rDocument.MaxRow();
|
|
|
|
if (!IsBlockMode())
|
|
{
|
|
OSL_FAIL( "MarkCursor not in BlockMode" );
|
|
InitBlockMode( nCurX, nCurY, nCurZ, false, bCols, bRows );
|
|
}
|
|
|
|
if (bCols)
|
|
nCurY = rDocument.MaxRow();
|
|
if (bRows)
|
|
nCurX = rDocument.MaxCol();
|
|
|
|
ScMarkData& rMark = aViewData.GetMarkData();
|
|
OSL_ENSURE(rMark.IsMarked() || rMark.IsMultiMarked(), "MarkCursor, !IsMarked()");
|
|
const ScRange& aMarkRange = rMark.GetMarkArea();
|
|
if (( aMarkRange.aStart.Col() != nBlockStartX && aMarkRange.aEnd.Col() != nBlockStartX ) ||
|
|
( aMarkRange.aStart.Row() != nBlockStartY && aMarkRange.aEnd.Row() != nBlockStartY ) ||
|
|
( meBlockMode == Own ))
|
|
{
|
|
// Mark has been changed
|
|
// (Eg MarkToSimple if by negative everything was erased, except for a rectangle)
|
|
// or after InitOwnBlockMode is further marked with shift-
|
|
bool bOldShift = bMoveIsShift;
|
|
bMoveIsShift = false; // really move
|
|
DoneBlockMode(); //! Set variables directly? (-> no flicker)
|
|
bMoveIsShift = bOldShift;
|
|
|
|
InitBlockMode( aMarkRange.aStart.Col(), aMarkRange.aStart.Row(),
|
|
nBlockStartZ, rMark.IsMarkNegative(), bCols, bRows );
|
|
}
|
|
|
|
if ( nCurX != nOldCurX || nCurY != nOldCurY )
|
|
{
|
|
// Current cursor has moved
|
|
|
|
SCTAB nTab = nCurZ;
|
|
|
|
if ( bCellSelection )
|
|
{
|
|
// Expand selection area accordingly when the current selection cuts
|
|
// through a merged cell.
|
|
ScRange cellSel(nBlockStartXOrig, nBlockStartYOrig, nTab, nCurX, nCurY, nTab);
|
|
cellSel.PutInOrder();
|
|
ScRange oldSel;
|
|
do
|
|
{
|
|
oldSel = cellSel;
|
|
rDocument.ExtendOverlapped(cellSel);
|
|
rDocument.ExtendMerge(cellSel);
|
|
} while (oldSel != cellSel);
|
|
|
|
// Preserve the directionality of the selection
|
|
if (nCurX >= nBlockStartXOrig)
|
|
{
|
|
nBlockStartX = cellSel.aStart.Col();
|
|
nBlockEndX = cellSel.aEnd.Col();
|
|
}
|
|
else
|
|
{
|
|
nBlockStartX = cellSel.aEnd.Col();
|
|
nBlockEndX = cellSel.aStart.Col();
|
|
}
|
|
if (nCurY >= nBlockStartYOrig)
|
|
{
|
|
nBlockStartY = cellSel.aStart.Row();
|
|
nBlockEndY = cellSel.aEnd.Row();
|
|
}
|
|
else
|
|
{
|
|
nBlockStartY = cellSel.aEnd.Row();
|
|
nBlockEndY = cellSel.aStart.Row();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
nBlockEndX = nCurX;
|
|
nBlockEndY = nCurY;
|
|
}
|
|
|
|
// Set new selection area
|
|
rMark.SetMarkArea( ScRange( nBlockStartX, nBlockStartY, nTab, nBlockEndX, nBlockEndY, nTab ) );
|
|
|
|
UpdateSelectionOverlay();
|
|
SelectionChanged();
|
|
|
|
nOldCurX = nBlockEndX;
|
|
nOldCurY = nBlockEndY;
|
|
|
|
aViewData.GetViewShell()->UpdateInputHandler();
|
|
}
|
|
|
|
if ( !bCols && !bRows )
|
|
aHdrFunc.SetAnchorFlag( false );
|
|
}
|
|
|
|
void ScTabView::GetPageMoveEndPosition(SCCOL nMovX, SCROW nMovY, SCCOL& rPageX, SCROW& rPageY)
|
|
{
|
|
SCCOL nCurX;
|
|
SCROW nCurY;
|
|
if (aViewData.IsRefMode())
|
|
{
|
|
nCurX = aViewData.GetRefEndX();
|
|
nCurY = aViewData.GetRefEndY();
|
|
}
|
|
else if (IsBlockMode())
|
|
{
|
|
// block end position.
|
|
nCurX = nBlockEndX;
|
|
nCurY = nBlockEndY;
|
|
}
|
|
else
|
|
{
|
|
// cursor position
|
|
nCurX = aViewData.GetCurX();
|
|
nCurY = aViewData.GetCurY();
|
|
}
|
|
|
|
ScSplitPos eWhich = aViewData.GetActivePart();
|
|
ScHSplitPos eWhichX = WhichH( eWhich );
|
|
ScVSplitPos eWhichY = WhichV( eWhich );
|
|
|
|
sal_uInt16 nScrSizeY = SC_SIZE_NONE;
|
|
if (comphelper::LibreOfficeKit::isActive() && aViewData.GetPageUpDownOffset() > 0) {
|
|
nScrSizeY = ScViewData::ToPixel( aViewData.GetPageUpDownOffset(), aViewData.GetPPTX() );
|
|
}
|
|
|
|
SCCOL nPageX;
|
|
SCROW nPageY;
|
|
if (nMovX >= 0)
|
|
nPageX = aViewData.CellsAtX( nCurX, 1, eWhichX ) * nMovX;
|
|
else
|
|
nPageX = aViewData.CellsAtX( nCurX, -1, eWhichX ) * nMovX;
|
|
|
|
if (nMovY >= 0)
|
|
nPageY = aViewData.CellsAtY( nCurY, 1, eWhichY, nScrSizeY ) * nMovY;
|
|
else
|
|
nPageY = aViewData.CellsAtY( nCurY, -1, eWhichY, nScrSizeY ) * nMovY;
|
|
|
|
if (nMovX != 0 && nPageX == 0) nPageX = (nMovX>0) ? 1 : -1;
|
|
if (nMovY != 0 && nPageY == 0) nPageY = (nMovY>0) ? 1 : -1;
|
|
|
|
rPageX = nPageX;
|
|
rPageY = nPageY;
|
|
}
|
|
|
|
void ScTabView::GetAreaMoveEndPosition(SCCOL nMovX, SCROW nMovY, ScFollowMode eMode,
|
|
SCCOL& rAreaX, SCROW& rAreaY, ScFollowMode& rMode,
|
|
bool bInteractiveByUser)
|
|
{
|
|
SCCOL nNewX = -1;
|
|
SCROW nNewY = -1;
|
|
|
|
// current cursor position.
|
|
SCCOL nCurX = aViewData.GetCurX();
|
|
SCROW nCurY = aViewData.GetCurY();
|
|
|
|
ScModule* pScModule = ScModule::get();
|
|
bool bLegacyCellSelection = pScModule->GetInputOptions().GetLegacyCellSelection();
|
|
bool bIncrementallyExpandToDocLimits(false);
|
|
|
|
if (aViewData.IsRefMode())
|
|
{
|
|
nNewX = aViewData.GetRefEndX();
|
|
nNewY = aViewData.GetRefEndY();
|
|
nCurX = aViewData.GetRefStartX();
|
|
nCurY = aViewData.GetRefStartY();
|
|
}
|
|
else if (IsBlockMode())
|
|
{
|
|
// block end position.
|
|
nNewX = nBlockEndX;
|
|
nNewY = nBlockEndY;
|
|
}
|
|
else
|
|
{
|
|
nNewX = nCurX;
|
|
nNewY = nCurY;
|
|
// cool#6931 on ctrl+[right/down] don't immediately leap to the far limits of the document when no more data,
|
|
// instead jump a generous block of emptiness. Limit to direct interaction by user and the simple
|
|
// case.
|
|
bIncrementallyExpandToDocLimits = bInteractiveByUser && (nMovX == 1 || nMovY == 1) &&
|
|
!bLegacyCellSelection && comphelper::LibreOfficeKit::isActive();
|
|
}
|
|
|
|
ScDocument& rDoc = aViewData.GetDocument();
|
|
SCTAB nTab = aViewData.GetTabNo();
|
|
|
|
// FindAreaPos knows only -1 or 1 as direction
|
|
SCCOL nVirtualX = bLegacyCellSelection ? nNewX : nCurX;
|
|
SCROW nVirtualY = bLegacyCellSelection ? nNewY : nCurY;
|
|
|
|
SCCOLROW i;
|
|
if ( nMovX > 0 )
|
|
for ( i=0; i<nMovX; i++ )
|
|
rDoc.FindAreaPos( nNewX, nVirtualY, nTab, SC_MOVE_RIGHT );
|
|
if ( nMovX < 0 )
|
|
for ( i=0; i<-nMovX; i++ )
|
|
rDoc.FindAreaPos( nNewX, nVirtualY, nTab, SC_MOVE_LEFT );
|
|
if ( nMovY > 0 )
|
|
for ( i=0; i<nMovY; i++ )
|
|
rDoc.FindAreaPos( nVirtualX, nNewY, nTab, SC_MOVE_DOWN );
|
|
if ( nMovY < 0 )
|
|
for ( i=0; i<-nMovY; i++ )
|
|
rDoc.FindAreaPos( nVirtualX, nNewY, nTab, SC_MOVE_UP );
|
|
|
|
if (eMode==SC_FOLLOW_JUMP) // bottom right do not show too much grey
|
|
{
|
|
if (nMovX != 0 && nNewX == rDoc.MaxCol())
|
|
{
|
|
eMode = SC_FOLLOW_LINE;
|
|
if (bIncrementallyExpandToDocLimits)
|
|
{
|
|
if (const ScTable* pTab = rDoc.FetchTable(nTab))
|
|
{
|
|
if (!pTab->HasData(nNewX, nCurY))
|
|
{
|
|
SCCOL nLastUsedCol(0);
|
|
SCROW nLastUsedRow(0);
|
|
rDoc.GetPrintArea(nTab, nLastUsedCol, nLastUsedRow);
|
|
SCCOL nJumpFrom = std::max(nCurX, nLastUsedCol);
|
|
nNewX = ((nJumpFrom / 13) + 2) * 13 - 1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (nMovY != 0 && nNewY == rDoc.MaxRow())
|
|
{
|
|
eMode = SC_FOLLOW_LINE;
|
|
if (bIncrementallyExpandToDocLimits)
|
|
{
|
|
if (const ScTable* pTab = rDoc.FetchTable(nTab))
|
|
{
|
|
if (!pTab->HasData(nCurX, nNewY))
|
|
{
|
|
SCCOL nLastUsedCol(0);
|
|
SCROW nLastUsedRow(0);
|
|
rDoc.GetPrintArea(nTab, nLastUsedCol, nLastUsedRow);
|
|
SCROW nJumpFrom = std::max(nCurY, nLastUsedRow);
|
|
nNewY = ((nJumpFrom / 500) + 2) * 500 - 1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (aViewData.IsRefMode())
|
|
{
|
|
rAreaX = nNewX - aViewData.GetRefEndX();
|
|
rAreaY = nNewY - aViewData.GetRefEndY();
|
|
}
|
|
else if (IsBlockMode())
|
|
{
|
|
rAreaX = nNewX - nBlockEndX;
|
|
rAreaY = nNewY - nBlockEndY;
|
|
}
|
|
else
|
|
{
|
|
rAreaX = nNewX - nCurX;
|
|
rAreaY = nNewY - nCurY;
|
|
}
|
|
rMode = eMode;
|
|
}
|
|
|
|
void ScTabView::SkipCursorHorizontal(SCCOL& rCurX, SCROW& rCurY, SCCOL nOldX, SCCOL nMovX)
|
|
{
|
|
ScDocument& rDoc = aViewData.GetDocument();
|
|
SCTAB nTab = aViewData.GetTabNo();
|
|
|
|
bool bSkipProtected = false, bSkipUnprotected = false;
|
|
const ScTableProtection* pProtect = rDoc.GetTabProtection(nTab);
|
|
if (pProtect && pProtect->isProtected())
|
|
{
|
|
bSkipProtected = !pProtect->isOptionEnabled(ScTableProtection::SELECT_LOCKED_CELLS);
|
|
bSkipUnprotected = !pProtect->isOptionEnabled(ScTableProtection::SELECT_UNLOCKED_CELLS);
|
|
}
|
|
|
|
bool bSkipCell = false;
|
|
bool bHFlip = false;
|
|
// If a number of last columns are hidden, search up to and including the first of them,
|
|
// because after it nothing changes.
|
|
SCCOL nMaxCol;
|
|
if(rDoc.ColHidden(rDoc.MaxCol(), nTab, &nMaxCol))
|
|
++nMaxCol;
|
|
else
|
|
nMaxCol = rDoc.MaxCol();
|
|
// Search also at least up to and including the first unallocated column (all unallocated columns
|
|
// share a set of attrs).
|
|
nMaxCol = std::max( nMaxCol, std::min<SCCOL>( rDoc.GetAllocatedColumnsCount(nTab) + 1, rDoc.MaxCol()));
|
|
do
|
|
{
|
|
bSkipCell = rDoc.ColHidden(rCurX, nTab) || rDoc.IsHorOverlapped(rCurX, rCurY, nTab);
|
|
if (bSkipProtected && !bSkipCell)
|
|
bSkipCell = rDoc.HasAttrib(rCurX, rCurY, nTab, rCurX, rCurY, nTab, HasAttrFlags::Protected);
|
|
if (bSkipUnprotected && !bSkipCell)
|
|
bSkipCell = !rDoc.HasAttrib(rCurX, rCurY, nTab, rCurX, rCurY, nTab, HasAttrFlags::Protected);
|
|
|
|
if (bSkipCell)
|
|
{
|
|
if (rCurX <= 0 || rCurX >= nMaxCol)
|
|
{
|
|
if (bHFlip)
|
|
{
|
|
rCurX = nOldX;
|
|
bSkipCell = false;
|
|
}
|
|
else
|
|
{
|
|
nMovX = -nMovX;
|
|
if (nMovX > 0)
|
|
++rCurX;
|
|
else
|
|
--rCurX;
|
|
bHFlip = true;
|
|
}
|
|
}
|
|
else
|
|
if (nMovX > 0)
|
|
++rCurX;
|
|
else
|
|
--rCurX;
|
|
}
|
|
}
|
|
while (bSkipCell);
|
|
|
|
if (rDoc.IsVerOverlapped(rCurX, rCurY, nTab))
|
|
{
|
|
aViewData.SetOldCursor(rCurX, rCurY);
|
|
while (rDoc.IsVerOverlapped(rCurX, rCurY, nTab))
|
|
--rCurY;
|
|
}
|
|
}
|
|
|
|
void ScTabView::SkipCursorVertical(SCCOL& rCurX, SCROW& rCurY, SCROW nOldY, SCROW nMovY)
|
|
{
|
|
ScDocument& rDoc = aViewData.GetDocument();
|
|
SCTAB nTab = aViewData.GetTabNo();
|
|
|
|
bool bSkipProtected = false, bSkipUnprotected = false;
|
|
const ScTableProtection* pProtect = rDoc.GetTabProtection(nTab);
|
|
if (pProtect && pProtect->isProtected())
|
|
{
|
|
bSkipProtected = !pProtect->isOptionEnabled(ScTableProtection::SELECT_LOCKED_CELLS);
|
|
bSkipUnprotected = !pProtect->isOptionEnabled(ScTableProtection::SELECT_UNLOCKED_CELLS);
|
|
}
|
|
|
|
bool bSkipCell = false;
|
|
bool bVFlip = false;
|
|
// Avoid repeated calls to RowHidden(), IsVerOverlapped() and HasAttrib().
|
|
SCROW nFirstSameHiddenRow = -1;
|
|
SCROW nLastSameHiddenRow = -1;
|
|
bool bRowHidden = false;
|
|
SCROW nFirstSameIsVerOverlapped = -1;
|
|
SCROW nLastSameIsVerOverlapped = -1;
|
|
bool bIsVerOverlapped = false;
|
|
SCROW nFirstSameHasAttribRow = -1;
|
|
SCROW nLastSameHasAttribRow = -1;
|
|
bool bHasAttribProtected = false;
|
|
do
|
|
{
|
|
if( rCurY < nFirstSameHiddenRow || rCurY > nLastSameHiddenRow )
|
|
bRowHidden = rDoc.RowHidden(rCurY, nTab, &nFirstSameHiddenRow, &nLastSameHiddenRow);
|
|
bSkipCell = bRowHidden;
|
|
if( !bSkipCell )
|
|
{
|
|
if( rCurY < nFirstSameIsVerOverlapped || rCurY > nLastSameIsVerOverlapped )
|
|
bIsVerOverlapped = rDoc.IsVerOverlapped(rCurX, rCurY, nTab, &nFirstSameIsVerOverlapped, &nLastSameIsVerOverlapped);
|
|
bSkipCell = bIsVerOverlapped;
|
|
}
|
|
if (bSkipProtected && !bSkipCell)
|
|
{
|
|
if( rCurY < nFirstSameHasAttribRow || rCurY > nLastSameHasAttribRow )
|
|
bHasAttribProtected = rDoc.HasAttrib(rCurX, rCurY, nTab, HasAttrFlags::Protected,
|
|
&nFirstSameHasAttribRow, &nLastSameHasAttribRow);
|
|
bSkipCell = bHasAttribProtected;
|
|
}
|
|
if (bSkipUnprotected && !bSkipCell)
|
|
{
|
|
if( rCurY < nFirstSameHasAttribRow || rCurY > nLastSameHasAttribRow )
|
|
bHasAttribProtected = rDoc.HasAttrib(rCurX, rCurY, nTab, HasAttrFlags::Protected,
|
|
&nFirstSameHasAttribRow, &nLastSameHasAttribRow);
|
|
bSkipCell = !bHasAttribProtected;
|
|
}
|
|
|
|
if (bSkipCell)
|
|
{
|
|
if (rCurY <= 0 || rCurY >= rDoc.MaxRow())
|
|
{
|
|
if (bVFlip)
|
|
{
|
|
rCurY = nOldY;
|
|
bSkipCell = false;
|
|
}
|
|
else
|
|
{
|
|
nMovY = -nMovY;
|
|
if (nMovY > 0)
|
|
++rCurY;
|
|
else
|
|
--rCurY;
|
|
bVFlip = true;
|
|
}
|
|
}
|
|
else
|
|
if (nMovY > 0)
|
|
++rCurY;
|
|
else
|
|
--rCurY;
|
|
}
|
|
}
|
|
while (bSkipCell);
|
|
|
|
if (rDoc.IsHorOverlapped(rCurX, rCurY, nTab))
|
|
{
|
|
aViewData.SetOldCursor(rCurX, rCurY);
|
|
while (rDoc.IsHorOverlapped(rCurX, rCurY, nTab))
|
|
--rCurX;
|
|
}
|
|
}
|
|
|
|
void ScTabView::ExpandBlock(SCCOL nMovX, SCROW nMovY, ScFollowMode eMode)
|
|
{
|
|
if (!nMovX && !nMovY)
|
|
// Nothing to do. Bail out.
|
|
return;
|
|
|
|
ScTabViewShell* pViewShell = aViewData.GetViewShell();
|
|
bool bRefInputMode = pViewShell && pViewShell->IsRefInputMode();
|
|
if (bRefInputMode && !aViewData.IsRefMode())
|
|
// initialize formula reference mode if it hasn't already.
|
|
InitRefMode(aViewData.GetCurX(), aViewData.GetCurY(), aViewData.GetTabNo(), SC_REFTYPE_REF);
|
|
|
|
ScDocument& rDoc = aViewData.GetDocument();
|
|
|
|
if (aViewData.IsRefMode())
|
|
{
|
|
// formula reference mode
|
|
|
|
SCCOL nNewX = aViewData.GetRefEndX();
|
|
SCROW nNewY = aViewData.GetRefEndY();
|
|
SCTAB nRefTab = aViewData.GetRefEndZ();
|
|
|
|
moveRefByCell(nNewX, nNewY, nMovX, nMovY, nRefTab, rDoc);
|
|
|
|
UpdateRef(nNewX, nNewY, nRefTab);
|
|
SCCOL nTargetCol = nNewX;
|
|
SCROW nTargetRow = nNewY;
|
|
if (((aViewData.GetRefStartX() == 0) || (aViewData.GetRefStartY() == 0)) &&
|
|
((nNewX != rDoc.MaxCol()) || (nNewY != rDoc.MaxRow())))
|
|
{
|
|
// Row selection
|
|
if ((aViewData.GetRefStartX() == 0) && (nNewX == rDoc.MaxCol()))
|
|
nTargetCol = aViewData.GetCurX();
|
|
// Column selection
|
|
if ((aViewData.GetRefStartY() == 0) && (nNewY == rDoc.MaxRow()))
|
|
nTargetRow = aViewData.GetCurY();
|
|
}
|
|
AlignToCursor(nTargetCol, nTargetRow, eMode);
|
|
}
|
|
else
|
|
{
|
|
// normal selection mode
|
|
|
|
SCTAB nTab = aViewData.GetTabNo();
|
|
SCCOL nOrigX = aViewData.GetCurX();
|
|
SCROW nOrigY = aViewData.GetCurY();
|
|
|
|
// Note that the origin position *never* moves during selection.
|
|
|
|
if (!IsBlockMode())
|
|
{
|
|
InitBlockMode(nOrigX, nOrigY, nTab, true);
|
|
const ScMergeAttr* pMergeAttr = rDoc.GetAttr(nOrigX, nOrigY, nTab, ATTR_MERGE);
|
|
if (pMergeAttr && pMergeAttr->IsMerged())
|
|
{
|
|
nBlockEndX = nOrigX + pMergeAttr->GetColMerge() - 1;
|
|
nBlockEndY = nOrigY + pMergeAttr->GetRowMerge() - 1;
|
|
}
|
|
}
|
|
|
|
moveCursorToProperSide(nBlockEndX, nBlockEndY, nMovX, nMovY, nBlockStartX, nBlockStartY,
|
|
nTab, &rDoc);
|
|
moveCursorByProtRule(nBlockEndX, nBlockEndY, nMovX, nMovY, nTab, &rDoc);
|
|
checkBoundary(&rDoc, nBlockEndX, nBlockEndY);
|
|
moveCursorByMergedCell(nBlockEndX, nBlockEndY, nMovX, nMovY, nBlockStartX, nBlockStartY,
|
|
nTab, &rDoc);
|
|
checkBoundary(&rDoc, nBlockEndX, nBlockEndY);
|
|
|
|
MarkCursor(nBlockEndX, nBlockEndY, nTab, false, false, true);
|
|
|
|
// Check if the entire row(s) or column(s) are selected.
|
|
ScSplitPos eActive = aViewData.GetActivePart();
|
|
bool bRowSelected = (nBlockStartX == 0 && nBlockEndX == rDoc.MaxCol());
|
|
bool bColSelected = (nBlockStartY == 0 && nBlockEndY == rDoc.MaxRow());
|
|
SCCOL nAlignX = bRowSelected ? aViewData.GetPosX(WhichH(eActive)) : nBlockEndX;
|
|
SCROW nAlignY = bColSelected ? aViewData.GetPosY(WhichV(eActive)) : nBlockEndY;
|
|
AlignToCursor(nAlignX, nAlignY, eMode);
|
|
|
|
SelectionChanged();
|
|
}
|
|
}
|
|
|
|
void ScTabView::ExpandBlockPage(SCCOL nMovX, SCROW nMovY)
|
|
{
|
|
SCCOL nPageX;
|
|
SCROW nPageY;
|
|
GetPageMoveEndPosition(nMovX, nMovY, nPageX, nPageY);
|
|
ExpandBlock(nPageX, nPageY, SC_FOLLOW_FIX);
|
|
}
|
|
|
|
void ScTabView::ExpandBlockArea(SCCOL nMovX, SCROW nMovY)
|
|
{
|
|
SCCOL nAreaX;
|
|
SCROW nAreaY;
|
|
ScFollowMode eMode;
|
|
GetAreaMoveEndPosition(nMovX, nMovY, SC_FOLLOW_JUMP, nAreaX, nAreaY, eMode);
|
|
ExpandBlock(nAreaX, nAreaY, eMode);
|
|
}
|
|
|
|
void ScTabView::UpdateCopySourceOverlay()
|
|
{
|
|
for (VclPtr<ScGridWindow> & pWin : pGridWin)
|
|
if (pWin && pWin->IsVisible())
|
|
pWin->UpdateCopySourceOverlay();
|
|
}
|
|
|
|
void ScTabView::UpdateSelectionOverlay()
|
|
{
|
|
for (VclPtr<ScGridWindow> & pWin : pGridWin)
|
|
if ( pWin && pWin->IsVisible() )
|
|
pWin->UpdateSelectionOverlay();
|
|
}
|
|
|
|
void ScTabView::UpdateHighlightOverlay()
|
|
{
|
|
for (VclPtr<ScGridWindow> & pWin : pGridWin)
|
|
if ( pWin && pWin->IsVisible() )
|
|
pWin->UpdateHighlightOverlay();
|
|
}
|
|
|
|
void ScTabView::UpdateShrinkOverlay()
|
|
{
|
|
for (VclPtr<ScGridWindow> & pWin : pGridWin)
|
|
if ( pWin && pWin->IsVisible() )
|
|
pWin->UpdateShrinkOverlay();
|
|
}
|
|
|
|
void ScTabView::UpdateAllOverlays()
|
|
{
|
|
for (VclPtr<ScGridWindow> & pWin : pGridWin)
|
|
if ( pWin && pWin->IsVisible() )
|
|
pWin->UpdateAllOverlays();
|
|
}
|
|
|
|
//!
|
|
//! divide PaintBlock into two methods: RepaintBlock and RemoveBlock or similar
|
|
//!
|
|
|
|
void ScTabView::PaintBlock( bool bReset )
|
|
{
|
|
ScMarkData& rMark = aViewData.GetMarkData();
|
|
SCTAB nTab = aViewData.GetTabNo();
|
|
bool bMulti = rMark.IsMultiMarked();
|
|
if (!(rMark.IsMarked() || bMulti))
|
|
return;
|
|
|
|
ScRange aMarkRange;
|
|
HideAllCursors();
|
|
if (bMulti)
|
|
{
|
|
bool bFlag = rMark.GetMarkingFlag();
|
|
rMark.SetMarking(false);
|
|
rMark.MarkToMulti();
|
|
aMarkRange = rMark.GetMultiMarkArea();
|
|
rMark.MarkToSimple();
|
|
rMark.SetMarking(bFlag);
|
|
}
|
|
else
|
|
aMarkRange = rMark.GetMarkArea();
|
|
|
|
nBlockStartX = aMarkRange.aStart.Col();
|
|
nBlockStartY = aMarkRange.aStart.Row();
|
|
nBlockStartZ = aMarkRange.aStart.Tab();
|
|
nBlockEndX = aMarkRange.aEnd.Col();
|
|
nBlockEndY = aMarkRange.aEnd.Row();
|
|
nBlockEndZ = aMarkRange.aEnd.Tab();
|
|
|
|
bool bDidReset = false;
|
|
|
|
if ( nTab>=nBlockStartZ && nTab<=nBlockEndZ )
|
|
{
|
|
if ( bReset )
|
|
{
|
|
// Inverting when deleting only on active View
|
|
if ( aViewData.IsActive() )
|
|
{
|
|
rMark.ResetMark();
|
|
UpdateSelectionOverlay();
|
|
bDidReset = true;
|
|
}
|
|
}
|
|
else
|
|
PaintMarks( nBlockStartX, nBlockStartY, nBlockEndX, nBlockEndY );
|
|
}
|
|
|
|
if ( bReset && !bDidReset )
|
|
rMark.ResetMark();
|
|
|
|
ShowAllCursors();
|
|
}
|
|
|
|
void ScTabView::SelectAll( bool bContinue )
|
|
{
|
|
ScDocument& rDoc = aViewData.GetDocument();
|
|
ScMarkData& rMark = aViewData.GetMarkData();
|
|
SCTAB nTab = aViewData.GetTabNo();
|
|
|
|
if (rMark.IsMarked())
|
|
{
|
|
if ( rMark.GetMarkArea() == ScRange( 0,0,nTab, rDoc.MaxCol(),rDoc.MaxRow(),nTab ) )
|
|
return;
|
|
}
|
|
|
|
DoneBlockMode( bContinue );
|
|
InitBlockMode( 0,0,nTab );
|
|
MarkCursor( rDoc.MaxCol(),rDoc.MaxRow(),nTab );
|
|
|
|
SelectionChanged();
|
|
}
|
|
|
|
void ScTabView::SelectAllTables()
|
|
{
|
|
ScDocument& rDoc = aViewData.GetDocument();
|
|
ScMarkData& rMark = aViewData.GetMarkData();
|
|
SCTAB nCount = rDoc.GetTableCount();
|
|
|
|
if (nCount>1)
|
|
{
|
|
for (SCTAB i=0; i<nCount; i++)
|
|
rMark.SelectTable( i, true );
|
|
|
|
aViewData.GetDocShell()->PostPaintExtras();
|
|
SfxBindings& rBind = aViewData.GetBindings();
|
|
rBind.Invalidate( FID_FILL_TAB );
|
|
rBind.Invalidate( FID_TAB_DESELECTALL );
|
|
}
|
|
}
|
|
|
|
void ScTabView::DeselectAllTables()
|
|
{
|
|
ScDocument& rDoc = aViewData.GetDocument();
|
|
ScMarkData& rMark = aViewData.GetMarkData();
|
|
SCTAB nTab = aViewData.GetTabNo();
|
|
SCTAB nCount = rDoc.GetTableCount();
|
|
|
|
for (SCTAB i=0; i<nCount; i++)
|
|
rMark.SelectTable( i, ( i == nTab ) );
|
|
|
|
aViewData.GetDocShell()->PostPaintExtras();
|
|
SfxBindings& rBind = aViewData.GetBindings();
|
|
rBind.Invalidate( FID_FILL_TAB );
|
|
rBind.Invalidate( FID_TAB_DESELECTALL );
|
|
}
|
|
|
|
static bool lcl_FitsInWindow( double fScaleX, double fScaleY, sal_uInt16 nZoom,
|
|
tools::Long nWindowX, tools::Long nWindowY, const ScDocument* pDoc, SCTAB nTab,
|
|
SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow,
|
|
SCCOL nFixPosX, SCROW nFixPosY )
|
|
{
|
|
double fZoomFactor = static_cast<double>(Fraction(nZoom,100));
|
|
fScaleX *= fZoomFactor;
|
|
fScaleY *= fZoomFactor;
|
|
|
|
tools::Long nBlockX = 0;
|
|
SCCOL nCol;
|
|
for (nCol=0; nCol<nFixPosX; nCol++)
|
|
{
|
|
// for frozen panes, add both parts
|
|
sal_uInt16 nColTwips = pDoc->GetColWidth( nCol, nTab );
|
|
if (nColTwips)
|
|
{
|
|
nBlockX += static_cast<tools::Long>(nColTwips * fScaleX);
|
|
if (nBlockX > nWindowX)
|
|
return false;
|
|
}
|
|
}
|
|
for (nCol=nStartCol; nCol<=nEndCol; nCol++)
|
|
{
|
|
sal_uInt16 nColTwips = pDoc->GetColWidth( nCol, nTab );
|
|
if (nColTwips)
|
|
{
|
|
nBlockX += static_cast<tools::Long>(nColTwips * fScaleX);
|
|
if (nBlockX > nWindowX)
|
|
return false;
|
|
}
|
|
}
|
|
|
|
tools::Long nBlockY = 0;
|
|
for (SCROW nRow = 0; nRow <= nFixPosY-1; ++nRow)
|
|
{
|
|
if (pDoc->RowHidden(nRow, nTab))
|
|
continue;
|
|
|
|
// for frozen panes, add both parts
|
|
sal_uInt16 nRowTwips = pDoc->GetRowHeight(nRow, nTab);
|
|
if (nRowTwips)
|
|
{
|
|
nBlockY += static_cast<tools::Long>(nRowTwips * fScaleY);
|
|
if (nBlockY > nWindowY)
|
|
return false;
|
|
}
|
|
}
|
|
for (SCROW nRow = nStartRow; nRow <= nEndRow; ++nRow)
|
|
{
|
|
sal_uInt16 nRowTwips = pDoc->GetRowHeight(nRow, nTab);
|
|
if (nRowTwips)
|
|
{
|
|
nBlockY += static_cast<tools::Long>(nRowTwips * fScaleY);
|
|
if (nBlockY > nWindowY)
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
sal_uInt16 ScTabView::CalcZoom( SvxZoomType eType, sal_uInt16 nOldZoom )
|
|
{
|
|
sal_uInt16 nZoom = 100;
|
|
|
|
switch ( eType )
|
|
{
|
|
case SvxZoomType::PERCENT: // rZoom is no particular percent value
|
|
nZoom = nOldZoom;
|
|
break;
|
|
|
|
case SvxZoomType::OPTIMAL: // nZoom corresponds to the optimal size
|
|
{
|
|
ScMarkData& rMark = aViewData.GetMarkData();
|
|
ScDocument& rDoc = aViewData.GetDocument();
|
|
|
|
if (!rMark.IsMarked() && !rMark.IsMultiMarked())
|
|
nZoom = 100; // nothing selected
|
|
else
|
|
{
|
|
SCTAB nTab = aViewData.GetTabNo();
|
|
ScRange aMarkRange;
|
|
if ( aViewData.GetSimpleArea( aMarkRange ) != SC_MARK_SIMPLE )
|
|
aMarkRange = rMark.GetMultiMarkArea();
|
|
|
|
SCCOL nStartCol = aMarkRange.aStart.Col();
|
|
SCROW nStartRow = aMarkRange.aStart.Row();
|
|
SCTAB nStartTab = aMarkRange.aStart.Tab();
|
|
SCCOL nEndCol = aMarkRange.aEnd.Col();
|
|
SCROW nEndRow = aMarkRange.aEnd.Row();
|
|
SCTAB nEndTab = aMarkRange.aEnd.Tab();
|
|
|
|
if ( nTab < nStartTab && nTab > nEndTab )
|
|
nTab = nStartTab;
|
|
|
|
ScSplitPos eUsedPart = aViewData.GetActivePart();
|
|
|
|
SCCOL nFixPosX = 0;
|
|
SCROW nFixPosY = 0;
|
|
if ( aViewData.GetHSplitMode() == SC_SPLIT_FIX )
|
|
{
|
|
// use right part
|
|
eUsedPart = (WhichV(eUsedPart)==SC_SPLIT_TOP) ? SC_SPLIT_TOPRIGHT : SC_SPLIT_BOTTOMRIGHT;
|
|
nFixPosX = aViewData.GetFixPosX();
|
|
if ( nStartCol < nFixPosX )
|
|
nStartCol = nFixPosX;
|
|
}
|
|
if ( aViewData.GetVSplitMode() == SC_SPLIT_FIX )
|
|
{
|
|
// use bottom part
|
|
eUsedPart = (WhichH(eUsedPart)==SC_SPLIT_LEFT) ? SC_SPLIT_BOTTOMLEFT : SC_SPLIT_BOTTOMRIGHT;
|
|
nFixPosY = aViewData.GetFixPosY();
|
|
if ( nStartRow < nFixPosY )
|
|
nStartRow = nFixPosY;
|
|
}
|
|
|
|
if (pGridWin[eUsedPart])
|
|
{
|
|
// Because scale is rounded to pixels, the only reliable way to find
|
|
// the right scale is to check if a zoom fits
|
|
|
|
Size aWinSize = pGridWin[eUsedPart]->GetOutputSizePixel();
|
|
|
|
// for frozen panes, use sum of both parts for calculation
|
|
|
|
if ( nFixPosX != 0 )
|
|
aWinSize.AdjustWidth(GetGridWidth( SC_SPLIT_LEFT ) );
|
|
if ( nFixPosY != 0 )
|
|
aWinSize.AdjustHeight(GetGridHeight( SC_SPLIT_TOP ) );
|
|
|
|
ScDocShell* pDocSh = aViewData.GetDocShell();
|
|
double nPPTX = ScGlobal::nScreenPPTX / pDocSh->GetOutputFactor();
|
|
double nPPTY = ScGlobal::nScreenPPTY;
|
|
|
|
sal_uInt16 nMin = MINZOOM;
|
|
sal_uInt16 nMax = MAXZOOM;
|
|
while ( nMax > nMin )
|
|
{
|
|
sal_uInt16 nTest = (nMin+nMax+1)/2;
|
|
if ( lcl_FitsInWindow(
|
|
nPPTX, nPPTY, nTest, aWinSize.Width(), aWinSize.Height(),
|
|
&rDoc, nTab, nStartCol, nStartRow, nEndCol, nEndRow,
|
|
nFixPosX, nFixPosY ) )
|
|
nMin = nTest;
|
|
else
|
|
nMax = nTest-1;
|
|
}
|
|
OSL_ENSURE( nMin == nMax, "Nesting is wrong" );
|
|
nZoom = nMin;
|
|
|
|
if ( nZoom != nOldZoom )
|
|
{
|
|
// scroll to block only in active split part
|
|
// (the part for which the size was calculated)
|
|
|
|
if ( nStartCol <= nEndCol )
|
|
aViewData.SetPosX( WhichH(eUsedPart), nStartCol );
|
|
if ( nStartRow <= nEndRow )
|
|
aViewData.SetPosY( WhichV(eUsedPart), nStartRow );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case SvxZoomType::WHOLEPAGE: // nZoom corresponds to the whole page or
|
|
case SvxZoomType::PAGEWIDTH: // nZoom corresponds to the page width
|
|
{
|
|
SCTAB nCurTab = aViewData.GetTabNo();
|
|
ScDocument& rDoc = aViewData.GetDocument();
|
|
ScStyleSheetPool* pStylePool = rDoc.GetStyleSheetPool();
|
|
SfxStyleSheetBase* pStyleSheet =
|
|
pStylePool->Find( rDoc.GetPageStyle( nCurTab ),
|
|
SfxStyleFamily::Page );
|
|
|
|
OSL_ENSURE( pStyleSheet, "PageStyle not found :-/" );
|
|
|
|
if ( pStyleSheet )
|
|
{
|
|
ScPrintFunc aPrintFunc( aViewData.GetDocShell(),
|
|
aViewData.GetViewShell()->GetPrinter(true),
|
|
nCurTab );
|
|
|
|
Size aPageSize = aPrintFunc.GetDataSize();
|
|
|
|
// use the size of the largest GridWin for normal split,
|
|
// or both combined for frozen panes, with the (document) size
|
|
// of the frozen part added to the page size
|
|
// (with frozen panes, the size of the individual parts
|
|
// depends on the scale that is to be calculated)
|
|
|
|
if (!pGridWin[SC_SPLIT_BOTTOMLEFT])
|
|
return nZoom;
|
|
|
|
Size aWinSize = pGridWin[SC_SPLIT_BOTTOMLEFT]->GetOutputSizePixel();
|
|
ScSplitMode eHMode = aViewData.GetHSplitMode();
|
|
if ( eHMode != SC_SPLIT_NONE && pGridWin[SC_SPLIT_BOTTOMRIGHT] )
|
|
{
|
|
tools::Long nOtherWidth = pGridWin[SC_SPLIT_BOTTOMRIGHT]->
|
|
GetOutputSizePixel().Width();
|
|
if ( eHMode == SC_SPLIT_FIX )
|
|
{
|
|
aWinSize.AdjustWidth(nOtherWidth );
|
|
for ( SCCOL nCol = aViewData.GetPosX(SC_SPLIT_LEFT);
|
|
nCol < aViewData.GetFixPosX(); nCol++ )
|
|
aPageSize.AdjustWidth(rDoc.GetColWidth( nCol, nCurTab ) );
|
|
}
|
|
else if ( nOtherWidth > aWinSize.Width() )
|
|
aWinSize.setWidth( nOtherWidth );
|
|
}
|
|
ScSplitMode eVMode = aViewData.GetVSplitMode();
|
|
if ( eVMode != SC_SPLIT_NONE && pGridWin[SC_SPLIT_TOPLEFT] )
|
|
{
|
|
tools::Long nOtherHeight = pGridWin[SC_SPLIT_TOPLEFT]->
|
|
GetOutputSizePixel().Height();
|
|
if ( eVMode == SC_SPLIT_FIX )
|
|
{
|
|
aWinSize.AdjustHeight(nOtherHeight );
|
|
aPageSize.AdjustHeight(rDoc.GetRowHeight(
|
|
aViewData.GetPosY(SC_SPLIT_TOP),
|
|
aViewData.GetFixPosY()-1, nCurTab) );
|
|
}
|
|
else if ( nOtherHeight > aWinSize.Height() )
|
|
aWinSize.setHeight( nOtherHeight );
|
|
}
|
|
|
|
double nPPTX = ScGlobal::nScreenPPTX / aViewData.GetDocShell()->GetOutputFactor();
|
|
double nPPTY = ScGlobal::nScreenPPTY;
|
|
|
|
tools::Long nZoomX = static_cast<tools::Long>( aWinSize.Width() * 100 /
|
|
( aPageSize.Width() * nPPTX ) );
|
|
tools::Long nZoomY = static_cast<tools::Long>( aWinSize.Height() * 100 /
|
|
( aPageSize.Height() * nPPTY ) );
|
|
|
|
if (nZoomX > 0)
|
|
nZoom = static_cast<sal_uInt16>(nZoomX);
|
|
|
|
if (eType == SvxZoomType::WHOLEPAGE && nZoomY > 0 && nZoomY < nZoom)
|
|
nZoom = static_cast<sal_uInt16>(nZoomY);
|
|
}
|
|
}
|
|
break;
|
|
|
|
default:
|
|
OSL_FAIL("Unknown Zoom-Revision");
|
|
}
|
|
|
|
return nZoom;
|
|
}
|
|
|
|
// is called for instance when the view window is shifted:
|
|
|
|
void ScTabView::StopMarking()
|
|
{
|
|
ScSplitPos eActive = aViewData.GetActivePart();
|
|
if (pGridWin[eActive])
|
|
pGridWin[eActive]->StopMarking();
|
|
|
|
ScHSplitPos eH = WhichH(eActive);
|
|
if (pColBar[eH])
|
|
pColBar[eH]->StopMarking();
|
|
|
|
ScVSplitPos eV = WhichV(eActive);
|
|
if (pRowBar[eV])
|
|
pRowBar[eV]->StopMarking();
|
|
}
|
|
|
|
void ScTabView::HideNoteMarker()
|
|
{
|
|
for (VclPtr<ScGridWindow> & pWin : pGridWin)
|
|
if (pWin && pWin->IsVisible())
|
|
pWin->HideNoteMarker();
|
|
}
|
|
|
|
void ScTabView::MakeDrawLayer()
|
|
{
|
|
if (pDrawView)
|
|
return;
|
|
|
|
aViewData.GetDocShell()->MakeDrawLayer();
|
|
|
|
// pDrawView is set per Notify
|
|
OSL_ENSURE(pDrawView,"ScTabView::MakeDrawLayer does not work");
|
|
|
|
for(VclPtr<ScGridWindow> & pWin : pGridWin)
|
|
{
|
|
if(pWin)
|
|
{
|
|
pWin->DrawLayerCreated();
|
|
}
|
|
}
|
|
}
|
|
|
|
IMPL_STATIC_LINK_NOARG(ScTabView, InstallLOKNotifierHdl, void*, vcl::ILibreOfficeKitNotifier*)
|
|
{
|
|
return GetpApp();
|
|
}
|
|
|
|
void ScTabView::ErrorMessage(TranslateId pGlobStrId)
|
|
{
|
|
if (ScModule::get()->IsInExecuteDrop())
|
|
{
|
|
// #i28468# don't show error message when called from Drag&Drop, silently abort instead
|
|
return;
|
|
}
|
|
|
|
StopMarking(); // if called by Focus from MouseButtonDown
|
|
|
|
weld::Window* pParent = aViewData.GetDialogParent();
|
|
weld::WaitObject aWaitOff( pParent );
|
|
bool bFocus = pParent && pParent->has_focus();
|
|
|
|
if (pGlobStrId && pGlobStrId == STR_PROTECTIONERR)
|
|
{
|
|
if (aViewData.GetDocShell()->IsReadOnly())
|
|
{
|
|
pGlobStrId = STR_READONLYERR;
|
|
}
|
|
}
|
|
|
|
m_xMessageBox.reset(Application::CreateMessageDialog(pParent,
|
|
VclMessageType::Info, VclButtonsType::Ok,
|
|
ScResId(pGlobStrId)));
|
|
|
|
if (comphelper::LibreOfficeKit::isActive())
|
|
m_xMessageBox->SetInstallLOKNotifierHdl(LINK(this, ScTabView, InstallLOKNotifierHdl));
|
|
|
|
weld::Window* pGrabOnClose = bFocus ? pParent : nullptr;
|
|
m_xMessageBox->runAsync(m_xMessageBox, [this, pGrabOnClose](sal_Int32 /*nResult*/) {
|
|
m_xMessageBox.reset();
|
|
if (pGrabOnClose)
|
|
pGrabOnClose->grab_focus();
|
|
});
|
|
}
|
|
|
|
void ScTabView::UpdatePageBreakData( bool bForcePaint )
|
|
{
|
|
std::unique_ptr<ScPageBreakData> pNewData;
|
|
|
|
if (aViewData.IsPagebreakMode())
|
|
{
|
|
ScDocShell* pDocSh = aViewData.GetDocShell();
|
|
ScDocument& rDoc = pDocSh->GetDocument();
|
|
SCTAB nTab = aViewData.GetTabNo();
|
|
|
|
sal_uInt16 nCount = rDoc.GetPrintRangeCount(nTab);
|
|
if (!nCount)
|
|
nCount = 1;
|
|
pNewData.reset( new ScPageBreakData(nCount) );
|
|
|
|
ScPrintFunc aPrintFunc( pDocSh, pDocSh->GetPrinter(), nTab, 0,0,nullptr, nullptr, pNewData.get() );
|
|
// ScPrintFunc fills the PageBreakData in ctor
|
|
if ( nCount > 1 )
|
|
{
|
|
aPrintFunc.ResetBreaks(nTab);
|
|
pNewData->AddPages();
|
|
}
|
|
|
|
// print area changed?
|
|
if ( bForcePaint || ( pPageBreakData && !( *pPageBreakData == *pNewData ) ) )
|
|
PaintGrid();
|
|
}
|
|
|
|
pPageBreakData = std::move(pNewData);
|
|
}
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|