/* -*- 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 .
*/
/* Search least and greatest position in current cursor ring.
*/ for(SwPaM& rTmpCursor : pSwCursor->GetRingContainer())
{
SwCursor* pTmpCursor = static_cast<SwCursor *>(&rTmpCursor); const SwPosition * pPt = pTmpCursor->GetPoint(),
* pMk = pTmpCursor->GetMark();
if (*pPt < aStartPos)
aStartPos = *pPt;
if (*pPt > aEndPos)
aEndPos = *pPt;
if (*pMk < aStartPos)
aStartPos = *pMk;
if (*pMk > aEndPos)
aEndPos = *pMk;
}
KillPams();
/* @@@ semantic: SwCursor::operator=() is not implemented @@@ */
/* Set cursor to end of selection to ensure IsLastCellInRow works
properly. */
{
SwCursor aTmpCursor( aEndPos, nullptr );
*pSwCursor = aTmpCursor;
}
/* Move the cursor out of the columns to delete and stay in the same row. If the table has only one column the cursor will
stay in the row and the shell will take care of it. */ if (IsLastCellInRow())
{ /* If the cursor is in the last row of the table, first try to move it to the previous cell. If that fails move
it to the next cell. */
if (! pSwCursor->GoPrevCell())
{
SwCursor aTmpCursor( aEndPos, nullptr );
*pSwCursor = aTmpCursor;
pSwCursor->GoNextCell();
}
} else
{ /* If the cursor is not in the last row of the table, first try to move it to the next cell. If that fails move it
to the previous cell. */
void SwFEShell::InsertRow( sal_uInt16 nCnt, bool bBehind )
{ // check if Point/Mark of current cursor are in a table
SwFrame *pFrame = GetCurrFrame(); if( !pFrame || !pFrame->IsInTab() ) return;
// search boxes via the layout
SwSelBoxes aBoxes; bool bSelectAll = StartsWith_() == StartsWith::Table && ExtendedSelectedAll(); if (bSelectAll)
{ // Set the end of the selection to the last paragraph of the last cell of the table.
SwPaM* pPaM = getShellCursor(false);
SwNode* pNode = pPaM->Start()->GetNode().FindTableNode()->EndOfSectionNode(); // pNode is the end node of the table, we want the last node before the end node of the last cell.
pPaM->End()->Assign( pNode->GetIndex() - 2 );
}
GetTableSel( *this, aBoxes, SwTableSearchType::Row );
if ( !aBoxes.empty() )
GetDoc()->InsertRow( aBoxes, nCnt, bBehind, /*bInsertDummy=*/!bAction );
EndAllActionAndCall();
}
void SwFEShell::InsertCol( sal_uInt16 nCnt, bool bBehind )
{ // check if Point/Mark of current cursor are in a table
SwFrame *pFrame = GetCurrFrame(); if( !pFrame || !pFrame->IsInTab() ) return;
// Determines if the current cursor is in the last row of the table. bool SwFEShell::IsLastCellInRow() const
{
SwTabCols aTabCols;
GetTabCols( aTabCols ); bool bResult = false;
if (IsTableRightToLeft()) /* If the table is right-to-left the last row is the most left one. */
bResult = 0 == GetCurTabColNum(); else /* If the table is left-to-right the last row is the most right one. */
bResult = aTabCols.Count() == GetCurTabColNum();
return bResult;
}
bool SwFEShell::DeleteCol()
{ // check if Point/Mark of current cursor are in a table
SwFrame *pFrame = GetCurrFrame(); if( !pFrame || !pFrame->IsInTab() ) returnfalse;
// tracked deletion: remove only textbox content, // and set IsNoTracked table box property to false if ( bRecordChanges )
{
StartUndo(SwUndoId::COL_DELETE);
StartAllAction();
if ( SwWrtShell* pWrtShell = dynamic_cast<SwWrtShell*>(this) )
pWrtShell->SelectTableCol();
// search boxes via the layout
SwSelBoxes aBoxes;
GetTableSel( *this, aBoxes, SwTableSearchType::Col );
// remove cell frames in Hide Changes mode (and table frames, if needed) if ( bRecordAndHideChanges )
{ // remove all frames of the table, and make them again without the deleted ones // TODO remove only the deleted frames
pTableNd->DelFrames();
if ( !pTableNd->GetTable().IsDeleted() )
{
pTableNd->MakeOwnFrames();
}
}
// remove crsr from the deletion area. // Put them behind/on the table; via the // document position they will be put to the old position while( !pFrame->IsCellFrame() )
pFrame = pFrame->GetUpper();
ParkCursorInTab();
// then delete the column
StartUndo(SwUndoId::COL_DELETE);
bRet = GetDoc()->DeleteRowCol(aBoxes, SwDoc::RowColMode::DeleteColumn);
EndUndo(SwUndoId::COL_DELETE);
} else
bRet = false;
bool SwFEShell::DeleteRow(bool bCompleteTable)
{ // check if Point/Mark of current cursor are in a table
SwFrame *pFrame = GetCurrFrame(); if( !pFrame || !pFrame->IsInTab() ) returnfalse;
// tracked deletion: all rows have already had tracked row change in the table selection if ( bRecordChanges && !SwDoc::HasRowNotTracked( *getShellCursor( false ) ) ) returnfalse;
if ( bRecordChanges )
StartUndo(bCompleteTable ? SwUndoId::UI_TABLE_DELETE : SwUndoId::ROW_DELETE);
StartAllAction();
// tracked deletion: remove only textbox content, // and set HasTextChangesOnly table line property to false
SwEditShell* pEditShell = nullptr; if ( bRecordChanges )
{
pEditShell = GetDoc()->GetEditShell();
SvxPrintItem aHasTextChangesOnly(RES_PRINT, false);
GetDoc()->SetRowNotTracked( *getShellCursor( false ), aHasTextChangesOnly );
if ( SwWrtShell* pWrtShell = dynamic_cast<SwWrtShell*>(this) )
pWrtShell->SelectTableRow();
// don't need to remove the row frames in Show Changes mode if ( !bRecordAndHideChanges )
{ if ( pEditShell )
pEditShell->Delete(false);
// Delete cursors from the deletion area. // Then the cursor is: // 1. the following row, if there is another row after this // 2. the preceding row, if there is another row before this // 3. otherwise below the table
{
SwTableNode* pTableNd = pFrame->IsTextFrame()
? static_cast<SwTextFrame*>(pFrame)->GetTextNodeFirst()->FindTableNode()
: static_cast<SwNoTextFrame*>(pFrame)->GetNode()->FindTableNode();
// delete row content in Hide Changes mode if ( pEditShell && bRecordAndHideChanges )
{ // select the row deleted with change tracking cell by cell to handle // the already deleted cells
SwWrtShell* pWrtShell = dynamic_cast<SwWrtShell*>(this); for (SwSelBoxes::size_type nBox = 0; pWrtShell && nBox < aBoxes.size(); ++nBox)
{
pWrtShell->SelectTableRow();
SwCursor* pTableCursor = static_cast<SwCursor*>(GetTableCursor()); auto pStart = aBoxes[nBox]; if ( !pTableCursor )
pTableCursor = GetCursor(true);
if ( pTableCursor )
{ // set start and end of the selection
pTableCursor->DeleteMark();
pTableCursor->GetPoint()->Assign( *pStart->GetSttNd()->EndOfSectionNode() );
pTableCursor->Move( fnMoveBackward, GoInContent );
pWrtShell->UpdateCursor();
}
pEditShell->Delete(false);
}
}
SwNodeOffset nIdx; if( pNextBox ) // put cursor here
nIdx = pNextBox->GetSttIdx() + 1; else// otherwise below the table
nIdx = pTableNd->EndOfSectionIndex() + 1;
// remove row frames in Hide Changes mode (and table frames, if needed) if ( bRecordAndHideChanges )
{ // remove all frames of the table, and make them again without the deleted ones // TODO remove only the deleted frames
pTableNd->DelFrames(); if ( !pTableNd->GetTable().IsDeleted() )
{
pTableNd->MakeOwnFrames();
}
EndAllActionAndCall();
// put cursor
SwPaM* pPam = GetCursor();
pPam->GetPoint()->Assign( *pCNd, 0 );
pPam->SetMark(); // both want something
pPam->DeleteMark(); if ( SwWrtShell* pWrtShell = dynamic_cast<SwWrtShell*>(this) )
{
pWrtShell->UpdateCursor(); // tdf#150578 enable the disabled table toolbar by (zero) cursor moving
pWrtShell->Right( SwCursorSkipMode::Chars, false, 0, false );
}
if (m_pColumnCache->pLastTabFrame != pTab)
{ // if TabFrame was changed, we only shift a little bit // as the width is the same
SwRectFnSet fnRectX(m_pColumnCache->pLastTabFrame); if (fnRectX.GetWidth(m_pColumnCache->pLastTabFrame->getFrameArea()) ==
aRectFnSet.GetWidth(pTab->getFrameArea()) )
{
m_pColumnCache->pLastCols->SetLeftMin( nLeftMin );
// returns the number of rows consecutively selected from top static sal_uInt16 lcl_GetRowNumber( const SwPosition& rPos )
{
Point aTmpPt; const SwContentNode *pNd; const SwContentFrame *pFrame;
// switch on wait-cursor, as we do not know how // much content is affected
TableWait aWait(std::numeric_limits<size_t>::max(), nullptr,
*GetDoc()->GetDocShell());
for (size_t i = 0; i < aBoxes.size(); ++i)
{
SwTableBox *pBox = aBoxes[i]; if ( pBox->GetSttNd() )
{
SwNodeIndex aIdx( *pBox->GetSttNd(), 1 );
SwTextNode* pCNd = aIdx.GetNode().GetTextNode(); if( !pCNd )
pCNd = static_cast<SwTextNode*>(SwNodes::GoNext(&aIdx));
while ( pCNd )
{ if (!pCNd->GetText().isEmpty()) returntrue;
++aIdx;
pCNd = aIdx.GetNode().GetTextNode();
}
}
} returnfalse;
}
void SwFEShell::SetTableStyle(const TableStyleName& rStyleName)
{ // make sure SwDoc has the style
SwTableAutoFormat *pTableFormat = GetDoc()->GetTableStyles().FindAutoFormat(rStyleName); if (!pTableFormat) return;
SwTableNode *pTableNode = const_cast<SwTableNode*>(IsCursorInTable()); if (!pTableNode) return;
// set the name & update
UpdateTableStyleFormatting(pTableNode, false, &rStyleName);
}
bool SwFEShell::ResetTableStyle()
{
SwTableNode *pTableNode = const_cast<SwTableNode*>(IsCursorInTable()); if (!pTableNode) returnfalse;
// AutoFormat for the table/table selection bool SwFEShell::SetTableStyle(const SwTableAutoFormat& rStyle)
{ // make sure SwDoc has the style
GetDoc()->GetTableStyles().AddAutoFormat(rStyle);
SwTableNode *pTableNode = const_cast<SwTableNode*>(IsCursorInTable()); if (!pTableNode) returnfalse;
// set the name & update
TableStyleName aStyleName = rStyle.GetName(); return UpdateTableStyleFormatting(pTableNode, false, &aStyleName);
}
bool SwFEShell::DeleteTableSel()
{ // check if SPoint/Mark of current cursor are in a table
SwFrame *pFrame = GetCurrFrame(); if( !pFrame || !pFrame->IsInTab() ) returnfalse;
// cursor should be removed from deletion area. // Put them behind/on the table; via the document // position they'll be set to the old position while( !pFrame->IsCellFrame() )
pFrame = pFrame->GetUpper();
ParkCursor( *static_cast<SwCellFrame*>(pFrame)->GetTabBox()->GetSttNd() );
// check if SPoint/Mark of current cursor are in a table if (!pFrame || !pFrame->IsInTab()) return 0;
do
{ // JP 26.09.95: why compare with ContentFrame // and not with CellFrame ????
pFrame = pFrame->GetUpper();
} while (pFrame && !pFrame->IsCellFrame());
const SwFrame *pFrame = pLay->ContainsContent(); const SwFrame* pRet = nullptr;
if ( pFrame )
{ do
{ if ( pFrame->IsInTab() )
pFrame = const_cast<SwFrame*>(pFrame)->ImplFindTabFrame();
if (!pFrame) break;
if ( pFrame->IsTabFrame() )
{
Point aPt( rPt ); bool bSearchForFrameInTab = true;
SwTwips nTmpFuzzy = nFuzzy;
if ( !bMouseMoveRowCols )
{ // We ignore nested tables for the enhanced table selection: while ( pFrame->GetUpper()->IsInTab() )
pFrame = pFrame->GetUpper()->FindTabFrame();
// We first check if the given point is 'close' to the left or top // border of the table frame:
OSL_ENSURE( pFrame, "Nested table frame without outer table" );
SwRectFnSet aRectFnSet(pFrame); constbool bRTL = pFrame->IsRightToLeft();
// If we found the point to be 'close' to the left or top border // of the table frame, we adjust the point to be on that border: if ( bCloseToRow && bCloseToCol )
aPt = bRTL ? aTabRect.TopRight() : aRectFnSet.GetPos(aTabRect); elseif ( bCloseToRow )
aRectFnSet.IsVert() ? aPt.setY(nLeft) : aPt.setX(nLeft); elseif ( bCloseToCol )
aRectFnSet.IsVert() ? aPt.setX(nTop) : aPt.setY(nTop);
if ( !bCloseToRow && !bCloseToCol )
bSearchForFrameInTab = false;
// Since the point has been adjusted, we call lcl_FindFrameInTab() // with a fuzzy value of 1:
nTmpFuzzy = 1;
}
} while ( pFrame && pLay->IsAnLower( pFrame ) );
}
if ( pFrame && pFrame->IsInTab() && pLay->IsAnLower( pFrame ) )
{ do
{ // We allow mouse drag of table borders within nested tables, // but disallow hotspot selection of nested tables. if ( bMouseMoveRowCols )
{ // find the next cell frame while ( pFrame && !pFrame->IsCellFrame() )
pFrame = pFrame->GetUpper();
} else
{ // find the most upper cell frame: while ( pFrame &&
( !pFrame->IsCellFrame() ||
!pFrame->GetUpper()->GetUpper()->IsTabFrame() ||
pFrame->GetUpper()->GetUpper()->GetUpper()->IsInTab() ) )
pFrame = pFrame->GetUpper();
}
if ( pFrame ) // Note: this condition should be the same like the while condition!!!
{ // #i32329# Enhanced table selection // used for hotspot selection of tab/cols/rows if ( !bMouseMoveRowCols )
{
assert(pbCol && pbRow && "pbCol or pbRow missing");
if ( bCloseToRow || bCloseToCol )
{
*pbRow = bCloseToRow;
*pbCol = bCloseToCol;
pRet = pFrame; break;
}
} else
{ // used for mouse move of columns/rows const SwTabFrame* pTabFrame = pFrame->FindTabFrame();
SwRect aTabRect = pTabFrame->getFramePrintArea();
aTabRect.Pos() += pTabFrame->getFrameArea().Pos();
const SwCellFrame *pFrame = nullptr; if ( pPage )
{ // We cannot search the box by GetModelPositionForViewPoint or GetContentPos. // This would lead to a performance collapse for documents // with a lot of paragraphs/tables on one page //(BrowseMode!)
// check flys first if ( pPage->GetSortedObjs() )
{ for ( size_t i = 0; !pFrame && i < pPage->GetSortedObjs()->size(); ++i )
{
SwAnchoredObject* pObj = (*pPage->GetSortedObjs())[i]; if ( auto pFlyFrame = pObj->DynCastFlyFrame() )
{
pFrame = lcl_FindFrame( *GetDoc(), pFlyFrame, rPt, nFuzzy, pbRow, pbCol );
}
}
} const SwLayoutFrame *pLay = static_cast<const SwLayoutFrame*>(pPage->Lower()); while ( pLay && !pFrame )
{
pFrame = lcl_FindFrame( *GetDoc(), pLay, rPt, nFuzzy, pbRow, pbCol );
pLay = static_cast<const SwLayoutFrame*>(pLay->GetNext());
}
} return pFrame;
}
/* Helper function*/ /* calculated the distance between Point rC and Line Segment (rA, rB) */ staticdouble lcl_DistancePoint2Segment( const Point& rA, const Point& rB, const Point& rC )
{ double nRet = 0;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.