diff options
author | Tomaž Vajngerl <tomaz.vajngerl@collabora.co.uk> | 2019-08-26 20:07:12 +0900 |
---|---|---|
committer | Tomaž Vajngerl <quikee@gmail.com> | 2019-08-30 03:58:03 +0200 |
commit | 0285492a45e9cc19c26e14dcdf297bcc491da4d2 (patch) | |
tree | 99be93079240d29990b59b7f50c30777d67e4efa /svx | |
parent | 5735a2ce6941264e90f6b0593c54f661291d4987 (diff) |
tdf#126959 impress table border resize handle support
This adds support to edit the resize handles for the impress.
It includes:
- sending the positions of handles when table object is
selected or changed
- a implementaton of SID_TABLE_CHANGE_CURRENT_BORDER_POSITION
to perform the changing of the border positions of a table
Change-Id: I6f60822c5cd9afc3be5c48ea7b775f1860bfa5a7
Reviewed-on: https://gerrit.libreoffice.org/78201
Tested-by: Jenkins
Reviewed-by: Tomaž Vajngerl <quikee@gmail.com>
Diffstat (limited to 'svx')
-rw-r--r-- | svx/source/inc/tablemodel.hxx | 3 | ||||
-rw-r--r-- | svx/source/svdraw/svdmrkv.cxx | 68 | ||||
-rw-r--r-- | svx/source/table/svdotable.cxx | 122 | ||||
-rw-r--r-- | svx/source/table/tablecontroller.cxx | 73 | ||||
-rw-r--r-- | svx/source/table/tablelayouter.cxx | 31 | ||||
-rw-r--r-- | svx/source/table/tablelayouter.hxx | 18 | ||||
-rw-r--r-- | svx/source/table/tablemodel.cxx | 8 | ||||
-rw-r--r-- | svx/source/table/tablerow.cxx | 5 | ||||
-rw-r--r-- | svx/source/table/tablerow.hxx | 2 |
9 files changed, 275 insertions, 55 deletions
diff --git a/svx/source/inc/tablemodel.hxx b/svx/source/inc/tablemodel.hxx index 78aabc51f692..0dba1c058866 100644 --- a/svx/source/inc/tablemodel.hxx +++ b/svx/source/inc/tablemodel.hxx @@ -85,6 +85,9 @@ public: /// Get the width of all columns in this table. std::vector<sal_Int32> getColumnWidths(); + /// Get the height of all rows in this table. + std::vector<sal_Int32> getRowHeights(); + void dumpAsXml(xmlTextWriterPtr pWriter) const; // ICellRange diff --git a/svx/source/svdraw/svdmrkv.cxx b/svx/source/svdraw/svdmrkv.cxx index e49a00817582..4acee37ada36 100644 --- a/svx/source/svdraw/svdmrkv.cxx +++ b/svx/source/svdraw/svdmrkv.cxx @@ -24,6 +24,7 @@ #include <svx/svdview.hxx> #include <svx/svdpagv.hxx> #include <svx/svdpage.hxx> +#include <svx/svdotable.hxx> #include "svddrgm1.hxx" #ifdef DBG_UTIL @@ -46,6 +47,7 @@ #include <svx/svdovirt.hxx> #include <sdr/overlay/overlayrollingrectangle.hxx> #include <svx/sdr/overlay/overlaymanager.hxx> +#include <svx/sdr/table/tablecontroller.hxx> #include <svx/sdr/contact/viewcontact.hxx> #include <svx/sdrpaintwindow.hxx> #include <svx/sdrpagewindow.hxx> @@ -739,7 +741,7 @@ void SdrMarkView::SetMarkHandles(SfxViewShell* pOtherShell) } SfxViewShell* pViewShell = GetSfxViewShell(); - + bool bIsInTextEditMode = false; // check if text edit or ole is active and handles need to be suppressed. This may be the case // when a single object is selected // Using a strict return statement is okay here; no handles means *no* handles. @@ -755,18 +757,12 @@ void SdrMarkView::SetMarkHandles(SfxViewShell* pOtherShell) { const SdrTextObj* pSdrTextObj = dynamic_cast< const SdrTextObj* >(mpMarkedObj); - if(pSdrTextObj && pSdrTextObj->IsInEditMode()) + if (pSdrTextObj && pSdrTextObj->IsInEditMode()) { if (bTiledRendering) - { - // Suppress handles -> empty graphic selection. - if (pViewShell) - { - pViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_GRAPHIC_SELECTION, "EMPTY"); - SfxLokHelper::notifyOtherViews(pViewShell, LOK_CALLBACK_GRAPHIC_VIEW_SELECTION, "selection", "EMPTY"); - } - } - return; + bIsInTextEditMode = true; + else + return; } } @@ -777,21 +773,6 @@ void SdrMarkView::SetMarkHandles(SfxViewShell* pOtherShell) { return; } - - if (bTiledRendering && mpMarkedObj->GetObjIdentifier() == OBJ_TABLE) - { - rtl::Reference<sdr::SelectionController> xController = static_cast<SdrView*>(this)->getSelectionController(); - if (xController.is() && xController->hasSelectedCells()) - { - // The table shape has selected cells, which provide text selection already -> no graphic selection. - if (pViewShell) - { - pViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_GRAPHIC_SELECTION, "EMPTY"); - SfxLokHelper::notifyOtherViews(pViewShell, LOK_CALLBACK_GRAPHIC_VIEW_SELECTION, "selection", "EMPTY"); - } - return; - } - } } tools::Rectangle aRect(GetMarkedObjRect()); @@ -839,7 +820,22 @@ void SdrMarkView::SetMarkHandles(SfxViewShell* pOtherShell) { OString sSelectionText; + boost::property_tree::ptree aTableJsonTree; + bool bTableSelection = false; + bool bCellsAreSelected = false; + + if (mpMarkedObj && mpMarkedObj->GetObjIdentifier() == OBJ_TABLE) + { + auto* pTableObject = dynamic_cast<sdr::table::SdrTableObj*>(mpMarkedObj); + bTableSelection = pTableObject->createTableEdgesJson(aTableJsonTree); + rtl::Reference<sdr::SelectionController> xController = static_cast<SdrView*>(this)->getSelectionController(); + if (xController.is() && xController->hasSelectedCells()) + { + // The table shape has selected cells, which provide text selection already -> no graphic selection. + bCellsAreSelected = true; + } + } if (GetMarkedObjectCount()) { SdrMark* pM = GetSdrMarkByIndex(0); @@ -996,9 +992,27 @@ void SdrMarkView::SetMarkHandles(SfxViewShell* pOtherShell) } } - if (sSelectionText.isEmpty()) + if (sSelectionText.isEmpty() || bCellsAreSelected || bIsInTextEditMode) sSelectionText = "EMPTY"; + if (bTableSelection) + { + boost::property_tree::ptree aTableRectangle; + aTableRectangle.put("x", aSelection.Left()); + aTableRectangle.put("y", aSelection.Top()); + aTableRectangle.put("width", aSelection.GetWidth()); + aTableRectangle.put("height", aSelection.GetHeight()); + aTableJsonTree.push_back(std::make_pair("rectangle", aTableRectangle)); + + std::stringstream aStream; + boost::property_tree::write_json(aStream, aTableJsonTree); + pViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_TABLE_SELECTED, aStream.str().c_str()); + } + else + { + pViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_TABLE_SELECTED, "{}"); + } + if (pOtherShell) { // Another shell wants to know about our existing diff --git a/svx/source/table/svdotable.cxx b/svx/source/table/svdotable.cxx index 42f97ef7eb4d..c197b715bee6 100644 --- a/svx/source/table/svdotable.cxx +++ b/svx/source/table/svdotable.cxx @@ -1556,6 +1556,16 @@ sal_Int32 SdrTableObj::getColumnCount() const return mpImpl.is() ? mpImpl->getColumnCount() : 0; } +sal_Int32 SdrTableObj::getRowCount() const +{ + return mpImpl.is() ? mpImpl->getRowCount() : 0; +} + +void SdrTableObj::changeEdge(bool bHorizontal, int nEdge, sal_Int32 nOffset) +{ + if (mpImpl.is()) + mpImpl->DragEdge(bHorizontal, nEdge, nOffset); +} void SdrTableObj::setActiveCell( const CellPos& rPos ) { @@ -2073,41 +2083,29 @@ void SdrTableObj::AddToHdlList(SdrHdlList& rHdlList) const const sal_Int32 nColCount = mpImpl->getColumnCount(); // first add row handles - std::vector< TableEdgeHdl* > aRowEdges( nRowCount + 1 ); - - for( sal_Int32 nRow = 0; nRow <= nRowCount; nRow++ ) + std::vector<TableEdgeHdl*> aRowEdges(nRowCount + 1); + for (auto const & rEdge : mpImpl->mpLayouter->getHorizontalEdges()) { - sal_Int32 nEdgeMin, nEdgeMax; - const sal_Int32 nEdge = mpImpl->mpLayouter->getHorizontalEdge( nRow, &nEdgeMin, &nEdgeMax ); - nEdgeMin -= nEdge; - nEdgeMax -= nEdge; - - Point aPoint( maRect.TopLeft() ); - aPoint.AdjustY(nEdge ); + Point aPoint(maRect.TopLeft()); + aPoint.AdjustY(rEdge.nPosition); - std::unique_ptr<TableEdgeHdl> pHdl(new TableEdgeHdl(aPoint,true,nEdgeMin,nEdgeMax,nColCount+1)); - pHdl->SetPointNum( nRow ); - aRowEdges[nRow] = pHdl.get(); - rHdlList.AddHdl( std::move(pHdl) ); + std::unique_ptr<TableEdgeHdl> pHdl(new TableEdgeHdl(aPoint, true, rEdge.nMin, rEdge.nMax, nColCount + 1)); + pHdl->SetPointNum(rEdge.nIndex); + aRowEdges[rEdge.nIndex] = pHdl.get(); + rHdlList.AddHdl(std::move(pHdl)); } // second add column handles - std::vector< TableEdgeHdl* > aColEdges( nColCount + 1 ); - - for( sal_Int32 nCol = 0; nCol <= nColCount; nCol++ ) + std::vector<TableEdgeHdl*> aColEdges(nColCount + 1); + for (auto const & rEdge : mpImpl->mpLayouter->getVerticalEdges()) { - sal_Int32 nEdgeMin, nEdgeMax; - const sal_Int32 nEdge = mpImpl->mpLayouter->getVerticalEdge( nCol, &nEdgeMin, &nEdgeMax ); - nEdgeMin -= nEdge; - nEdgeMax -= nEdge; + Point aPoint(maRect.TopLeft()); + aPoint.AdjustX(rEdge.nPosition); - Point aPoint( maRect.TopLeft() ); - aPoint.AdjustX(nEdge ); - - std::unique_ptr<TableEdgeHdl> pHdl(new TableEdgeHdl(aPoint,false,nEdgeMin,nEdgeMax, nRowCount+1)); - pHdl->SetPointNum( nCol ); - aColEdges[nCol] = pHdl.get(); - rHdlList.AddHdl( std::move(pHdl) ); + std::unique_ptr<TableEdgeHdl> pHdl(new TableEdgeHdl(aPoint, false, rEdge.nMin, rEdge.nMax, nRowCount + 1)); + pHdl->SetPointNum(rEdge.nIndex); + aColEdges[rEdge.nIndex] = pHdl.get(); + rHdlList.AddHdl(std::move(pHdl)); } // now add visible edges to row and column handles @@ -2452,6 +2450,74 @@ void SdrTableObj::dumpAsXml(xmlTextWriterPtr pWriter) const xmlTextWriterEndElement(pWriter); } +bool SdrTableObj::createTableEdgesJson(boost::property_tree::ptree & rJsonRoot) +{ + if (!mpImpl.is() || !mpImpl->mxTable.is()) + return false; + + tools::Rectangle aRect = GetCurrentBoundRect(); + boost::property_tree::ptree aTableColumns; + { + aTableColumns.put("tableOffset", convertMm100ToTwip(aRect.Left())); + + boost::property_tree::ptree aEntries; + auto const & aEdges = mpImpl->mpLayouter->getVerticalEdges(); + for (auto & rEdge : aEdges) + { + if (rEdge.nIndex == 0) + { + aTableColumns.put("left", convertMm100ToTwip(rEdge.nPosition)); + } + else if (rEdge.nIndex == sal_Int32(aEdges.size() - 1)) + { + aTableColumns.put("right", convertMm100ToTwip(rEdge.nPosition)); + } + else + { + boost::property_tree::ptree aEntry; + aEntry.put("position", convertMm100ToTwip(rEdge.nPosition)); + aEntry.put("min", convertMm100ToTwip(rEdge.nPosition + rEdge.nMin)); + aEntry.put("max", convertMm100ToTwip(rEdge.nPosition + rEdge.nMax)); + aEntry.put("hidden", false); + aEntries.push_back(std::make_pair("", aEntry)); + } + } + aTableColumns.push_back(std::make_pair("entries", aEntries)); + } + rJsonRoot.add_child("columns", aTableColumns); + + boost::property_tree::ptree aTableRows; + { + aTableRows.put("tableOffset", convertMm100ToTwip(aRect.Top())); + + boost::property_tree::ptree aEntries; + auto const & aEdges = mpImpl->mpLayouter->getHorizontalEdges(); + for (auto & rEdge : aEdges) + { + if (rEdge.nIndex == 0) + { + aTableRows.put("left", convertMm100ToTwip(rEdge.nPosition)); + } + else if (rEdge.nIndex == sal_Int32(aEdges.size() - 1)) + { + aTableRows.put("right", convertMm100ToTwip(rEdge.nPosition)); + } + else + { + boost::property_tree::ptree aEntry; + aEntry.put("position", convertMm100ToTwip(rEdge.nPosition)); + aEntry.put("min", convertMm100ToTwip(rEdge.nPosition + rEdge.nMin)); + aEntry.put("max", convertMm100ToTwip(rEdge.nPosition + rEdge.nMax)); + aEntry.put("hidden", false); + aEntries.push_back(std::make_pair("", aEntry)); + } + } + aTableRows.push_back(std::make_pair("entries", aEntries)); + } + rJsonRoot.add_child("rows", aTableRows); + return true; +} + } } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/table/tablecontroller.cxx b/svx/source/table/tablecontroller.cxx index 5296797e0954..fd81047b4901 100644 --- a/svx/source/table/tablecontroller.cxx +++ b/svx/source/table/tablecontroller.cxx @@ -75,6 +75,7 @@ #include <cppuhelper/implbase.hxx> #include <comphelper/lok.hxx> #include <sfx2/viewsh.hxx> +#include <sfx2/lokhelper.hxx> #include <editeng/editview.hxx> using ::editeng::SvxBorderLine; @@ -1050,6 +1051,9 @@ void SvxTableController::Execute( SfxRequest& rReq ) case SID_TABLE_STYLE_SETTINGS: SetTableStyleSettings( rReq.GetArgs() ); break; + case SID_TABLE_CHANGE_CURRENT_BORDER_POSITION: + changeTableEdge(rReq); + break; } } @@ -1466,6 +1470,71 @@ bool SvxTableController::SetStyleSheet( SfxStyleSheet* pStyleSheet, bool bDontRe return false; } +void SvxTableController::changeTableEdge(const SfxRequest& rReq) +{ + if (!checkTableObject()) + return; + + const auto* pType = rReq.GetArg<SfxStringItem>(SID_TABLE_BORDER_TYPE); + const auto* pIndex = rReq.GetArg<SfxUInt16Item>(SID_TABLE_BORDER_INDEX); + const auto* pOffset = rReq.GetArg<SfxInt32Item>(SID_TABLE_BORDER_OFFSET); + + if (pType && pIndex && pOffset) + { + const OUString sType = pType->GetValue(); + const sal_uInt16 nIndex = pIndex->GetValue(); + const sal_Int32 nOffset = convertTwipToMm100(pOffset->GetValue()); + + SdrTableObj& rTableObj(*mxTableObj.get()); + + sal_Int32 nEdgeIndex = -1; + bool bHorizontal = sType.startsWith("row"); + + if (sType == "column-left" || sType == "row-left") + { + nEdgeIndex = 0; + } + else if (sType == "column-right") + { + // Number of edges = number of columns + 1 + nEdgeIndex = rTableObj.getColumnCount(); + } + else if (sType == "row-right") + { + // Number of edges = number of rows + 1 + nEdgeIndex = rTableObj.getRowCount(); + } + else if (sType == "column-middle" || sType == "row-middle") + { + nEdgeIndex = nIndex + 1; + } + + if (nEdgeIndex >= 0) + { + TableModelNotifyGuard aGuard(mxTable.get()); + SdrModel& rModel(rTableObj.getSdrModelFromSdrObject()); + const bool bUndo(rModel.IsUndoEnabled()); + if (bUndo) + { + auto pUndoObject = rModel.GetSdrUndoFactory().CreateUndoGeoObject(rTableObj); + rModel.BegUndo(pUndoObject->GetComment()); + rModel.AddUndo(std::move(pUndoObject)); + + auto* pGeoUndo = static_cast<SdrUndoGeoObj*>(pUndoObject.get()); + if (pGeoUndo) + pGeoUndo->SetSkipChangeLayout(true); + } + tools::Rectangle aBoundRect; + if (rTableObj.GetUserCall()) + aBoundRect = rTableObj.GetLastBoundRect(); + rTableObj.changeEdge(bHorizontal, nEdgeIndex, nOffset); + rTableObj.SetChanged(); + rTableObj.SendUserCall(SdrUserCallType::Resize, aBoundRect); + if (bUndo) + rModel.EndUndo(); + } + } +} // internals @@ -2230,6 +2299,9 @@ void SvxTableController::updateSelectionOverlay() { pViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_CELL_SELECTION_AREA, aSelection.toString().getStr()); pViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_TEXT_SELECTION, aSelection.toString().getStr()); + OString sSelection("EMPTY"); + pViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_GRAPHIC_SELECTION, sSelection.getStr()); + SfxLokHelper::notifyOtherViews(pViewShell, LOK_CALLBACK_GRAPHIC_VIEW_SELECTION, "selection", sSelection); } } } @@ -2248,6 +2320,7 @@ void SvxTableController::destroySelectionOverlay() // Clear the LOK text selection so far provided by this table. if(SfxViewShell* pViewShell = SfxViewShell::Current()) { + pViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_CELL_SELECTION_AREA, "EMPTY"); pViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_TEXT_SELECTION_START, "EMPTY"); pViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_TEXT_SELECTION_END, "EMPTY"); pViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_TEXT_SELECTION, "EMPTY"); diff --git a/svx/source/table/tablelayouter.cxx b/svx/source/table/tablelayouter.cxx index 6d19cba01820..11ac8da225d8 100644 --- a/svx/source/table/tablelayouter.cxx +++ b/svx/source/table/tablelayouter.cxx @@ -251,6 +251,37 @@ SvxBorderLine* TableLayouter::getBorderLine( sal_Int32 nEdgeX, sal_Int32 nEdgeY, return pLine; } +std::vector<EdgeInfo> TableLayouter::getHorizontalEdges() +{ + std::vector<EdgeInfo> aReturn; + sal_Int32 nRowSize = sal_Int32(maRows.size()); + for (sal_Int32 i = 0; i <= nRowSize; i++) + { + sal_Int32 nEdgeMin = 0; + sal_Int32 nEdgeMax = 0; + sal_Int32 nEdge = getHorizontalEdge(i, &nEdgeMin, &nEdgeMax); + nEdgeMin -= nEdge; + nEdgeMax -= nEdge; + aReturn.emplace_back(i, nEdge, nEdgeMin, nEdgeMax); + } + return aReturn; +} + +std::vector<EdgeInfo> TableLayouter::getVerticalEdges() +{ + std::vector<EdgeInfo> aReturn; + sal_Int32 nColumnSize = sal_Int32(maColumns.size()); + for (sal_Int32 i = 0; i <= nColumnSize; i++) + { + sal_Int32 nEdgeMin = 0; + sal_Int32 nEdgeMax = 0; + sal_Int32 nEdge = getVerticalEdge(i, &nEdgeMin, &nEdgeMax); + nEdgeMin -= nEdge; + nEdgeMax -= nEdge; + aReturn.emplace_back(i, nEdge, nEdgeMin, nEdgeMax); + } + return aReturn; +} sal_Int32 TableLayouter::getHorizontalEdge( int nEdgeY, sal_Int32* pnMin /*= 0*/, sal_Int32* pnMax /*= 0*/ ) { diff --git a/svx/source/table/tablelayouter.hxx b/svx/source/table/tablelayouter.hxx index 11e43ae7fe43..ba402b262ea0 100644 --- a/svx/source/table/tablelayouter.hxx +++ b/svx/source/table/tablelayouter.hxx @@ -51,6 +51,20 @@ typedef std::vector< BorderLineVector > BorderLineMap; // TableModel +struct EdgeInfo final +{ + sal_Int32 nIndex; + sal_Int32 nPosition; + sal_Int32 nMin; + sal_Int32 nMax; + + EdgeInfo(sal_Int32 nInIndex, sal_Int32 nInPosition, sal_Int32 nInMin, sal_Int32 nInMax) + : nIndex(nInIndex) + , nPosition(nInPosition) + , nMin(nInMin) + , nMax(nInMax) + {} +}; class TableLayouter final { @@ -92,9 +106,13 @@ public: void updateCells( ::tools::Rectangle const & rRectangle ); + std::vector<EdgeInfo> getHorizontalEdges(); sal_Int32 getHorizontalEdge( int nEdgeY, sal_Int32* pnMin, sal_Int32* pnMax ); + + std::vector<EdgeInfo> getVerticalEdges(); sal_Int32 getVerticalEdge( int nEdgeX , sal_Int32* pnMin, sal_Int32* pnMax); + void DistributeColumns( ::tools::Rectangle& rArea, sal_Int32 nFirstCol, sal_Int32 nLastCol, diff --git a/svx/source/table/tablemodel.cxx b/svx/source/table/tablemodel.cxx index 23101debcb07..d1de143dc898 100644 --- a/svx/source/table/tablemodel.cxx +++ b/svx/source/table/tablemodel.cxx @@ -303,6 +303,14 @@ sal_Int32 SAL_CALL TableModel::getRowCount() return getRowCountImpl(); } +std::vector<sal_Int32> TableModel::getRowHeights() +{ + std::vector<sal_Int32> aRet; + for (const TableRowRef& xRow : maRows) + aRet.push_back(xRow->getHeight()); + return aRet; +} + sal_Int32 SAL_CALL TableModel::getColumnCount() { diff --git a/svx/source/table/tablerow.cxx b/svx/source/table/tablerow.cxx index f7ca4d8d40d0..5623007e69a8 100644 --- a/svx/source/table/tablerow.cxx +++ b/svx/source/table/tablerow.cxx @@ -153,6 +153,11 @@ const TableModelRef& TableRow::getModel() const return mxTableModel; } +sal_Int32 TableRow::getHeight() const +{ + return mnHeight; +} + // XCellRange diff --git a/svx/source/table/tablerow.hxx b/svx/source/table/tablerow.hxx index 5c14452831b1..c45957962208 100644 --- a/svx/source/table/tablerow.hxx +++ b/svx/source/table/tablerow.hxx @@ -50,6 +50,8 @@ public: void removeColumns( sal_Int32 nIndex, sal_Int32 nCount ); /// Reference to the table model containing this row. const TableModelRef& getModel() const; + /// Get the height of this row. + sal_Int32 getHeight() const; // XCellRange virtual css::uno::Reference< css::table::XCell > SAL_CALL getCellByPosition( sal_Int32 nColumn, sal_Int32 nRow ) override; |