LOCRDT editeng,sw: yrs peer cursors for editengine
The cursors are represented as integers in yrs as a first step, which isn't ideal. Surprisingly EditView doesn't really have functions to correct the cursor, only ImpEditEngine::UpdateSelections() for the case when nodes are deleted, apparently there's only one active EditView at a time typically so it wasn't needed? Typically the active EditView's cursor is assigned from a return value of ImpEditEngine. Add some new functions to correct peer cursors and call them all over ImpEditEngine; unfortunately UpdateSelectionsDelete() isn't easy to get working on EditView's actual EditSelection cursor so leave that for the future... To fix EE paint of non-active comment, add SwAnnotationWin::Paint() To get things to paint with "gen", it's enough to invalidate the SwAnnotationWin, but for gtk3 a queue_draw() must be called, else it's only painted when clicking on the window. Cursors are painted in color in SidebarTextControl::Paint() Change-Id: Id8696238290405554ece1b9961676972a559b58e Reviewed-on: https://gerrit.libreoffice.org/c/core/+/181679 Tested-by: Jenkins Reviewed-by: Michael Stahl <michael.stahl@allotropia.de>
This commit is contained in:
@@ -134,6 +134,8 @@ public:
|
||||
void YrsWriteEEState();
|
||||
void YrsReadEEState(YTransaction *, ImpEditEngine & rIEE);
|
||||
void YrsApplyEEDelta(YTransaction *, YTextEvent const* pEvent, ImpEditEngine & rIEE);
|
||||
::std::optional<EditSelection> YrsReadEECursor(::std::pair<int64_t, int64_t> point,
|
||||
::std::optional<::std::pair<int64_t, int64_t>> oMark);
|
||||
void YrsSetStyle(sal_Int32 nPara, ::std::u16string_view rStyle);
|
||||
void YrsSetParaAttr(sal_Int32 nPara, SfxPoolItem const& rItem);
|
||||
OString GetYrsCommentId() const;
|
||||
|
||||
@@ -2712,75 +2712,105 @@ void EditDoc::YrsReadEEState(YTransaction *const pTxn, ImpEditEngine & rIEE)
|
||||
rIEE.RemoveParagraph(nodes); // remove pre-existing one from InitDoc()
|
||||
}
|
||||
|
||||
static void YrsAdjustCursors(ImpEditEngine & rIEE, EditDoc & rDoc,
|
||||
sal_Int32 const node, sal_Int32 const pos, ContentNode *const pNewNode, sal_Int32 const delta)
|
||||
::std::optional<EditSelection> EditDoc::YrsReadEECursor(
|
||||
::std::pair<int64_t, int64_t> const i_point,
|
||||
::std::optional<::std::pair<int64_t, int64_t>> const i_oMark)
|
||||
{
|
||||
for (EditView *const pView : rIEE.GetEditViews())
|
||||
// TODO should not use ints here?
|
||||
::std::optional<EditPaM> oMark;
|
||||
if (i_oMark)
|
||||
{
|
||||
bool bSet{false};
|
||||
EditSelection sel{pView->getImpl().GetEditSelection()};
|
||||
ContentNode const*const pNode{rDoc.GetObject(node)};
|
||||
if (sel.Min().GetNode() == pNode
|
||||
&& pos <= sel.Min().GetIndex())
|
||||
// yvalidate(i_oMark->first < Count());
|
||||
if (Count() <= i_oMark->first)
|
||||
{
|
||||
sel.Min().SetNode(pNewNode);
|
||||
sel.Min().SetIndex(sel.Min().GetIndex() + delta);
|
||||
bSet = true;
|
||||
return {};
|
||||
}
|
||||
if (sel.Max().GetNode() == pNode
|
||||
&& pos <= sel.Max().GetIndex())
|
||||
ContentNode & rNode{*GetObject(i_oMark->first)};
|
||||
// yvalidate(i_oMark->second <= o3tl::make_unsigned(rNode.Len()));
|
||||
if (o3tl::make_unsigned(rNode.Len()) < i_oMark->second)
|
||||
{
|
||||
sel.Max().SetNode(pNewNode);
|
||||
sel.Max().SetIndex(sel.Max().GetIndex() + delta);
|
||||
bSet = true;
|
||||
}
|
||||
if (bSet)
|
||||
{
|
||||
pView->getImpl().SetEditSelection(sel);
|
||||
return {};
|
||||
}
|
||||
oMark.emplace(&rNode, static_cast<sal_Int32>(i_oMark->second));
|
||||
}
|
||||
|
||||
// the problem with using ints here is that multiple local edits may
|
||||
// occur before the peer sends the updated cursor for the first edit,
|
||||
// and then its position may be invalid; work around this here by
|
||||
// ignoring obviously invalid cursors.
|
||||
// yvalidate(i_point.first < Count());
|
||||
if (Count() <= i_point.first)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
ContentNode & rNode{*GetObject(i_point.first)};
|
||||
// yvalidate(i_point.second <= o3tl::make_unsigned(rNode.Len()));
|
||||
if (o3tl::make_unsigned(rNode.Len()) < i_point.second)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
EditPaM point{&rNode, static_cast<sal_Int32>(i_point.second)};
|
||||
|
||||
return EditSelection{point, oMark ? *oMark : point};
|
||||
}
|
||||
|
||||
// TODO test this
|
||||
static bool UpdatePosDelete(EditDoc & rDoc, EditPaM & rPos, ESelection const& rDeleted)
|
||||
{
|
||||
auto const nPosNode{rDoc.GetPos(rPos.GetNode())};
|
||||
if (rDeleted.start.nPara == nPosNode)
|
||||
{
|
||||
if (rDeleted.start.nIndex < rPos.GetIndex())
|
||||
{
|
||||
if (rDeleted.start.nPara == rDeleted.end.nPara && rDeleted.end.nIndex < rPos.GetIndex())
|
||||
{
|
||||
rPos.SetIndex(rPos.GetIndex() - (rDeleted.end.nIndex - rDeleted.start.nIndex));
|
||||
}
|
||||
else
|
||||
{
|
||||
rPos.SetIndex(rDeleted.start.nIndex);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (rDeleted.start.nPara < nPosNode && nPosNode <= rDeleted.end.nPara)
|
||||
{
|
||||
if (nPosNode == rDeleted.end.nPara && rDeleted.end.nIndex < rPos.GetIndex())
|
||||
{
|
||||
rPos.SetIndex(rPos.GetIndex() - (rDeleted.end.nIndex - rDeleted.start.nIndex));
|
||||
}
|
||||
else
|
||||
{
|
||||
rPos.SetIndex(rDeleted.start.nIndex);
|
||||
}
|
||||
rPos.SetNode(rDoc.GetObject(rDeleted.start.nPara));
|
||||
return true;
|
||||
}
|
||||
#if 0
|
||||
else if (rDeleted.end.nPara < nPosNode)
|
||||
{
|
||||
rPos.SetNode(rDoc.GetObject(nPosNode - (rDeleted.end.nPara - rDeleted.start.nPara)));
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
// TODO this is now sort of duplicated as UpdateSelectionsDelete, but
|
||||
// consolidating that would probably require replacing EditSelection with
|
||||
// ESelection in EditView
|
||||
static void YrsAdjustCursorsDel(ImpEditEngine & rIEE, EditDoc & rDoc,
|
||||
sal_Int32 const startNode, sal_Int32 const startPos,
|
||||
sal_Int32 const endNode, sal_Int32 const endPos)
|
||||
{
|
||||
ESelection const deleted{startNode, startPos, endNode, endPos};
|
||||
for (EditView *const pView : rIEE.GetEditViews())
|
||||
{
|
||||
bool bSet{false};
|
||||
EditSelection sel{pView->getImpl().GetEditSelection()};
|
||||
ContentNode *const pStartNode{rDoc.GetObject(startNode)};
|
||||
ContentNode const*const pEndNode{rDoc.GetObject(endNode)};
|
||||
if ((sel.Min().GetNode() == pStartNode && startPos < sel.Min().GetIndex())
|
||||
|| (startNode < rDoc.GetPos(sel.Min().GetNode()) && rDoc.GetPos(sel.Min().GetNode()) < endNode)
|
||||
|| (sel.Min().GetNode() == pEndNode && sel.Min().GetIndex() < endPos))
|
||||
{
|
||||
sel.Min().SetNode(pStartNode);
|
||||
sel.Min().SetIndex(startPos);
|
||||
bSet = true;
|
||||
}
|
||||
else if (sel.Min().GetNode() == pEndNode)
|
||||
{
|
||||
sel.Min().SetNode(pStartNode);
|
||||
sel.Min().SetIndex(startPos + sel.Min().GetIndex() - endPos);
|
||||
bSet = true;
|
||||
}
|
||||
if ((sel.Max().GetNode() == pStartNode && startPos < sel.Max().GetIndex())
|
||||
|| (startNode < rDoc.GetPos(sel.Max().GetNode()) && rDoc.GetPos(sel.Max().GetNode()) < endNode)
|
||||
|| (sel.Max().GetNode() == pEndNode && sel.Max().GetIndex() < endPos))
|
||||
{
|
||||
sel.Max().SetNode(pStartNode);
|
||||
sel.Max().SetIndex(startPos);
|
||||
bSet = true;
|
||||
}
|
||||
else if (sel.Max().GetNode() == pEndNode)
|
||||
{
|
||||
sel.Max().SetNode(pStartNode);
|
||||
sel.Max().SetIndex(startPos + sel.Max().GetIndex() - endPos);
|
||||
bSet = true;
|
||||
}
|
||||
if (bSet)
|
||||
bool isChanged{false};
|
||||
isChanged |= UpdatePosDelete(rDoc, sel.Min(), deleted);
|
||||
isChanged |= UpdatePosDelete(rDoc, sel.Max(), deleted);
|
||||
if (isChanged)
|
||||
{
|
||||
pView->getImpl().SetEditSelection(sel);
|
||||
}
|
||||
@@ -2832,7 +2862,6 @@ void EditDoc::YrsApplyEEDelta(YTransaction *const /*pTxn*/, YTextEvent const*con
|
||||
{ return {rEntry.key, rEntry.value}; };
|
||||
EditPaM const pam{maContents[node].get(), pos};
|
||||
YrsImplInsertFeature<YDeltaAttr>(rIEE, pam, pChange[i].attributes, pChange[i].attributes_len, GetAttr);
|
||||
YrsAdjustCursors(rIEE, *this, node, pos, maContents[node].get(), 1);
|
||||
++pos;
|
||||
break;
|
||||
}
|
||||
@@ -2845,9 +2874,8 @@ void EditDoc::YrsApplyEEDelta(YTransaction *const /*pTxn*/, YTextEvent const*con
|
||||
EditSelection const sel{EditPaM{maContents[node].get(), pos}};
|
||||
rIEE.InsertText(sel, str.copy(index, iPara));
|
||||
}
|
||||
EditPaM const newPos{rIEE.SplitContent(node, pos + iPara)};
|
||||
rIEE.SplitContent(node, pos + iPara);
|
||||
rIEE.SetStyleSheet(node, pStyle);
|
||||
YrsAdjustCursors(rIEE, *this, node, pos, const_cast<ContentNode*>(newPos.GetNode()), -pos);
|
||||
index = iPara + 1;
|
||||
pos = 0;
|
||||
++node;
|
||||
@@ -2868,7 +2896,6 @@ void EditDoc::YrsApplyEEDelta(YTransaction *const /*pTxn*/, YTextEvent const*con
|
||||
{
|
||||
EditSelection const sel{EditPaM{maContents[node].get(), pos}};
|
||||
rIEE.InsertText(sel, str.copy(index, str.getLength() - index));
|
||||
YrsAdjustCursors(rIEE, *this, node, pos, maContents[node].get(), str.getLength() - index);
|
||||
pos += str.getLength() - index;
|
||||
}
|
||||
break;
|
||||
@@ -2936,6 +2963,8 @@ void EditDoc::YrsApplyEEDelta(YTransaction *const /*pTxn*/, YTextEvent const*con
|
||||
if (pChange[i].tag == Y_EVENT_CHANGE_DELETE)
|
||||
{
|
||||
YrsAdjustCursorsDel(rIEE, *this, nodeStart, posStart, node, pos);
|
||||
ESelection const deleted{rIEE.CreateESel(*oSel)};
|
||||
rIEE.UpdateSelectionsDelete(deleted);
|
||||
rIEE.DeleteSelected(*oSel);
|
||||
node = nodeStart;
|
||||
pos = posStart;
|
||||
|
||||
@@ -347,6 +347,51 @@ void EditView::GetSelectionRectangles(std::vector<tools::Rectangle>& rLogicRects
|
||||
return getImpl().GetSelectionRectangles(getImpl().GetEditSelection(), rLogicRects);
|
||||
}
|
||||
|
||||
#if defined(YRS)
|
||||
void EditView::YrsGetSelectionRectangles(
|
||||
::std::vector<::std::pair<OUString, ::std::vector<tools::Rectangle>>>& rLogicRects) const
|
||||
{
|
||||
for (auto const& it : getImpl().m_PeerCursors)
|
||||
{
|
||||
rLogicRects.push_back({it.second.first, {}});
|
||||
EditSelection const sel{getEditEngine().getImpl().CreateSel(it.second.second)};
|
||||
if (sel.HasRange())
|
||||
{
|
||||
getImpl().GetSelectionRectangles(sel, rLogicRects.back().second);
|
||||
}
|
||||
else
|
||||
{
|
||||
ParaPortion const& rParaPortion{getEditEngine().GetParaPortions().getRef(it.second.second.start.nPara)};
|
||||
auto const oCursor{getImpl().ImplGetCursorRectAndMaybeScroll(sel.Min(), rParaPortion, false)};
|
||||
if (oCursor)
|
||||
{
|
||||
auto const rect{std::get<0>(*oCursor)};
|
||||
rLogicRects.back().second.push_back(rect);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EditView::YrsApplyEECursor(OString const& rPeerId, OUString const& rAuthor,
|
||||
::std::pair<int64_t, int64_t> const point,
|
||||
::std::optional<::std::pair<int64_t, int64_t>> const oMark)
|
||||
{
|
||||
::std::optional<EditSelection> const oSel{getEditEngine().GetEditDoc().YrsReadEECursor(point, oMark)};
|
||||
if (!oSel)
|
||||
{
|
||||
SAL_DEBUG("YRS ignoring invalid cursor position");
|
||||
return;
|
||||
}
|
||||
ESelection const esel{getEditEngine().getImpl().CreateESel(*oSel)};
|
||||
getImpl().m_PeerCursors[rPeerId] = {rAuthor, esel};
|
||||
}
|
||||
|
||||
bool EditView::YrsDelEECursor(OString const& rId)
|
||||
{
|
||||
return getImpl().m_PeerCursors.erase(rId) != 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
Point EditView::CalculateTextPaintStartPosition() const
|
||||
{
|
||||
return getImpEditEngine().CalculateTextPaintStartPosition(getImpl());
|
||||
|
||||
@@ -287,6 +287,13 @@ private:
|
||||
EESelectionMode meSelectionMode;
|
||||
EditSelection maEditSelection;
|
||||
EEAnchorMode meAnchorMode;
|
||||
#if defined(YRS)
|
||||
public:
|
||||
/// when SwAnnotationWin::UpdateData() is called, the EE is cleared
|
||||
/// and recreated, so use ESelection not EditSelection to survive this!
|
||||
::std::unordered_map<OString, ::std::pair<OUString, ESelection>> m_PeerCursors;
|
||||
private:
|
||||
#endif
|
||||
|
||||
/// mechanism to change from the classic refresh mode that simply
|
||||
// invalidates the area where text was changed. When set, the invalidate
|
||||
@@ -702,7 +709,7 @@ private:
|
||||
|
||||
void ImpBreakLine(ParaPortion& rParaPortion, EditLine& rLine, TextPortion const * pPortion, sal_Int32 nPortionStart, tools::Long nRemainingWidth, bool bCanHyphenate);
|
||||
void ImpAdjustBlocks(ParaPortion& rParaPortion, EditLine& rLine, tools::Long nRemainingSpace );
|
||||
EditPaM ImpConnectParagraphs( ContentNode* pLeft, ContentNode* pRight, bool bBackward = false );
|
||||
EditPaM ImpConnectParagraphs(ContentNode* pLeft, ContentNode* pRight, bool bBackward = false, bool isUpdateCursors = true);
|
||||
EditPaM ImpDeleteSelection(const EditSelection& rCurSel);
|
||||
EditPaM ImpInsertParaBreak( EditPaM& rPaM, bool bKeepEndingAttribs = true );
|
||||
EditPaM ImpInsertParaBreak( const EditSelection& rEditSelection );
|
||||
@@ -1013,6 +1020,8 @@ public:
|
||||
|
||||
bool UpdateSelection(EditSelection &);
|
||||
void UpdateSelections();
|
||||
void UpdateSelectionsDelete(ESelection const& rDeleted);
|
||||
void UpdateSelectionsInsert(ESelection const& rInserted);
|
||||
|
||||
void EnableUndo( bool bEnable );
|
||||
bool IsUndoEnabled() const { return mbUndoEnabled; }
|
||||
|
||||
@@ -474,6 +474,7 @@ bool ImpEditEngine::Command( const CommandEvent& rCEvt, EditView* pView )
|
||||
FormatAndLayout( pView );
|
||||
}
|
||||
|
||||
UpdateSelections(); // other views
|
||||
EditSelection aNewSel( EditPaM( mpIMEInfos->aPos.GetNode(), mpIMEInfos->aPos.GetIndex()+pData->GetCursorPos() ) );
|
||||
pView->SetSelection( CreateESel( aNewSel ) );
|
||||
pView->SetInsertMode( !pData->IsCursorOverwrite() );
|
||||
@@ -2212,7 +2213,8 @@ EditSelection ImpEditEngine::ImpMoveParagraphs( Range aOldPositions, sal_Int32 n
|
||||
}
|
||||
|
||||
|
||||
EditPaM ImpEditEngine::ImpConnectParagraphs( ContentNode* pLeft, ContentNode* pRight, bool bBackward )
|
||||
EditPaM ImpEditEngine::ImpConnectParagraphs(ContentNode* pLeft, ContentNode* pRight,
|
||||
bool bBackward, bool const isUpdateCursors)
|
||||
{
|
||||
OSL_ENSURE( pLeft != pRight, "Join together the same paragraph ?" );
|
||||
OSL_ENSURE(maEditDoc.GetPos(pLeft) != EE_PARA_MAX, "Inserted node not found (1)");
|
||||
@@ -2230,6 +2232,7 @@ EditPaM ImpEditEngine::ImpConnectParagraphs( ContentNode* pLeft, ContentNode* pR
|
||||
|
||||
sal_Int32 nParagraphTobeDeleted = maEditDoc.GetPos( pRight );
|
||||
maDeletedNodes.push_back(std::make_unique<DeletedNodeInfo>( pRight, nParagraphTobeDeleted ));
|
||||
ESelection const deleted{nParagraphTobeDeleted - 1, pLeft->Len(), nParagraphTobeDeleted, 0};
|
||||
|
||||
GetEditEnginePtr()->ParagraphConnected( maEditDoc.GetPos( pLeft ), maEditDoc.GetPos( pRight ) );
|
||||
|
||||
@@ -2297,6 +2300,11 @@ EditPaM ImpEditEngine::ImpConnectParagraphs( ContentNode* pLeft, ContentNode* pR
|
||||
}
|
||||
}
|
||||
|
||||
if (isUpdateCursors)
|
||||
{
|
||||
UpdateSelectionsDelete(deleted);
|
||||
}
|
||||
|
||||
TextModified();
|
||||
|
||||
return aPaM;
|
||||
@@ -2398,6 +2406,7 @@ EditPaM ImpEditEngine::ImpDeleteSelection(const EditSelection& rCurSel)
|
||||
if ( !rCurSel.HasRange() )
|
||||
return rCurSel.Min();
|
||||
|
||||
ESelection const deleted{CreateESel(rCurSel)};
|
||||
EditSelection aCurSel(rCurSel);
|
||||
aCurSel.Adjust( maEditDoc );
|
||||
EditPaM aStartPaM(aCurSel.Min());
|
||||
@@ -2440,7 +2449,7 @@ EditPaM ImpEditEngine::ImpDeleteSelection(const EditSelection& rCurSel)
|
||||
assert(pPortion);
|
||||
pPortion->MarkSelectionInvalid( 0 );
|
||||
// Join together...
|
||||
aStartPaM = ImpConnectParagraphs( aStartPaM.GetNode(), aEndPaM.GetNode() );
|
||||
aStartPaM = ImpConnectParagraphs(aStartPaM.GetNode(), aEndPaM.GetNode(), false, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2450,6 +2459,7 @@ EditPaM ImpEditEngine::ImpDeleteSelection(const EditSelection& rCurSel)
|
||||
pPortion->MarkInvalid( aEndPaM.GetIndex(), aStartPaM.GetIndex() - aEndPaM.GetIndex() );
|
||||
}
|
||||
|
||||
UpdateSelectionsDelete(deleted);
|
||||
UpdateSelections();
|
||||
TextModified();
|
||||
return aStartPaM;
|
||||
@@ -2467,8 +2477,13 @@ void ImpEditEngine::RemoveParagraph( sal_Int32 nPara )
|
||||
if ( pNode && pPortion )
|
||||
{
|
||||
// No Undo encapsulation needed.
|
||||
auto const len{pNode->Len()};
|
||||
ImpRemoveParagraph(nPara);
|
||||
InvalidateFromParagraph(nPara);
|
||||
ESelection const deleted{nPara == 0 ? nPara : nPara - 1,
|
||||
nPara == 0 ? 0 : maEditDoc.GetObject(nPara-1)->Len(),
|
||||
nPara, len};
|
||||
UpdateSelectionsDelete(deleted);
|
||||
UpdateSelections();
|
||||
if (IsUpdateLayout())
|
||||
FormatAndLayout();
|
||||
@@ -2830,6 +2845,10 @@ EditPaM ImpEditEngine::ImpInsertText(const EditSelection& aCurSel, const OUStrin
|
||||
|
||||
UndoActionEnd();
|
||||
|
||||
ESelection inserted{CreateEPaM(aCurPaM)};
|
||||
inserted.end = CreateEPaM(aPaM);
|
||||
UpdateSelectionsInsert(inserted);
|
||||
|
||||
TextModified();
|
||||
return aPaM;
|
||||
}
|
||||
@@ -2876,6 +2895,10 @@ EditPaM ImpEditEngine::ImpInsertFeature(const EditSelection& rCurSel, const SfxP
|
||||
assert(pPortion);
|
||||
pPortion->MarkInvalid( aPaM.GetIndex()-1, 1 );
|
||||
|
||||
ESelection inserted{CreateEPaM(rCurSel.Min())};
|
||||
inserted.end = CreateEPaM(aPaM);
|
||||
UpdateSelectionsInsert(inserted);
|
||||
|
||||
TextModified();
|
||||
|
||||
return aPaM;
|
||||
@@ -2955,6 +2978,10 @@ EditPaM ImpEditEngine::ImpInsertParaBreak( EditPaM& rPaM, bool bKeepEndingAttrib
|
||||
if( nullptr != rPaM.GetNode() )
|
||||
rPaM.GetNode()->checkAndDeleteEmptyAttribs(); // if empty Attributes have emerged.
|
||||
|
||||
ESelection inserted{CreateEPaM(rPaM)};
|
||||
inserted.end = CreateEPaM(aPaM);
|
||||
UpdateSelectionsInsert(inserted);
|
||||
|
||||
TextModified();
|
||||
return aPaM;
|
||||
}
|
||||
@@ -3805,10 +3832,150 @@ void ImpEditEngine::UpdateSelections()
|
||||
{
|
||||
pView->getImpl().SetEditSelection(aCurSel);
|
||||
}
|
||||
#if defined(YRS)
|
||||
for (auto & it : pView->getImpl().m_PeerCursors)
|
||||
{
|
||||
EditSelection sel(CreateSel(it.second.second));
|
||||
if (UpdateSelection(sel))
|
||||
{
|
||||
assert(false); // should have called Insert/Delete?
|
||||
it.second.second = CreateESel(sel);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
maDeletedNodes.clear();
|
||||
}
|
||||
|
||||
#if defined(YRS)
|
||||
static bool UpdatePosDelete(EPaM & rPos, ESelection const& rDeleted)
|
||||
{
|
||||
// correct towards start: RemoveParagraph(Count()) can't work otherwise
|
||||
assert(rDeleted.IsAdjusted());
|
||||
if (rDeleted.start.nPara == rPos.nPara)
|
||||
{
|
||||
if (rDeleted.start.nIndex < rPos.nIndex)
|
||||
{
|
||||
if (rDeleted.start.nPara == rDeleted.end.nPara && rDeleted.end.nIndex < rPos.nIndex)
|
||||
{
|
||||
rPos.nIndex -= (rDeleted.end.nIndex - rDeleted.start.nIndex);
|
||||
}
|
||||
else
|
||||
{
|
||||
rPos.nIndex = rDeleted.start.nIndex;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (rDeleted.start.nPara < rPos.nPara && rPos.nPara <= rDeleted.end.nPara)
|
||||
{
|
||||
if (rPos.nPara == rDeleted.end.nPara && rDeleted.end.nIndex < rPos.nIndex)
|
||||
{
|
||||
rPos.nIndex -= rDeleted.end.nIndex - rDeleted.start.nIndex;
|
||||
}
|
||||
else
|
||||
{
|
||||
rPos.nIndex = rDeleted.start.nIndex;
|
||||
}
|
||||
rPos.nPara = rDeleted.start.nPara;
|
||||
return true;
|
||||
}
|
||||
else if (rDeleted.end.nPara < rPos.nPara)
|
||||
{
|
||||
rPos.nPara -= rDeleted.end.nPara - rDeleted.start.nPara;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
static bool UpdatePosInsert(EPaM & rPos, ESelection const& rInserted)
|
||||
{
|
||||
assert(rInserted.IsAdjusted());
|
||||
if (rInserted.start.nPara == rPos.nPara)
|
||||
{
|
||||
if (rInserted.start.nIndex <= rPos.nIndex)
|
||||
{
|
||||
rPos.nPara = rInserted.end.nPara;
|
||||
rPos.nIndex = rInserted.end.nIndex + (rPos.nIndex - rInserted.start.nIndex);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (rInserted.start.nPara < rPos.nPara && rInserted.start.nPara != rInserted.end.nPara)
|
||||
{
|
||||
rPos.nPara += rInserted.end.nPara - rInserted.start.nPara;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void ImpEditEngine::UpdateSelectionsDelete(ESelection const& rDeleted)
|
||||
{
|
||||
ESelection deleted(rDeleted);
|
||||
deleted.Adjust();
|
||||
for (EditView *const pView : maEditViews)
|
||||
{
|
||||
// FIXME fails because CreateESel needs the deleted nodes! but if it's
|
||||
// called before deleting the nodes, it will assign wrong nodes...
|
||||
// perhaps the cursors could be stored as ESelection in the first
|
||||
// place, but that would require reviewing all code that inserts or
|
||||
// deletes nodes if it does the update in the correct place...
|
||||
#if 0
|
||||
EditSelection const sel{pView->getImpl().GetEditSelection()};
|
||||
ESelection esel{CreateESel(sel)};
|
||||
bool isChanged{false};
|
||||
isChanged |= UpdatePosDelete(esel.start, deleted);
|
||||
isChanged |= UpdatePosDelete(esel.end, deleted);
|
||||
if (isChanged)
|
||||
{
|
||||
pView->getImpl().SetEditSelection(CreateSel(esel));
|
||||
}
|
||||
#else
|
||||
(void)pView;
|
||||
(void)deleted;
|
||||
#endif
|
||||
#if defined(YRS)
|
||||
for (auto & it : pView->getImpl().m_PeerCursors)
|
||||
{
|
||||
UpdatePosDelete(it.second.second.start, deleted);
|
||||
UpdatePosDelete(it.second.second.end, deleted);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void ImpEditEngine::UpdateSelectionsInsert(ESelection const& rInserted)
|
||||
{
|
||||
for (EditView *const pView : maEditViews)
|
||||
{
|
||||
EditSelection const sel{pView->getImpl().GetEditSelection()};
|
||||
ESelection esel{CreateESel(sel)};
|
||||
// nodes have been inserted, but CreateESel counts them: adjust for this!
|
||||
if (rInserted.start.nPara < esel.start.nPara)
|
||||
{
|
||||
esel.start.nPara -= rInserted.end.nPara - rInserted.start.nPara;
|
||||
}
|
||||
if (rInserted.start.nPara < esel.end.nPara)
|
||||
{
|
||||
esel.end.nPara -= rInserted.end.nPara - rInserted.start.nPara;
|
||||
}
|
||||
bool isChanged{false};
|
||||
isChanged |= UpdatePosInsert(esel.start, rInserted);
|
||||
isChanged |= UpdatePosInsert(esel.end, rInserted);
|
||||
if (isChanged)
|
||||
{
|
||||
pView->getImpl().SetEditSelection(CreateSel(esel));
|
||||
}
|
||||
#if defined(YRS)
|
||||
for (auto & it : pView->getImpl().m_PeerCursors)
|
||||
{
|
||||
UpdatePosInsert(it.second.second.start, rInserted);
|
||||
UpdatePosInsert(it.second.second.end, rInserted);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
EditSelection ImpEditEngine::ConvertSelection(
|
||||
sal_Int32 nStartPara, sal_Int32 nStartPos, sal_Int32 nEndPara, sal_Int32 nEndPos )
|
||||
{
|
||||
|
||||
@@ -3240,11 +3240,15 @@ short ImpEditEngine::ReplaceTextOnly(
|
||||
|
||||
DBG_ASSERT( (nCurrentPos+1) < pNode->Len(), "TransliterateText - String smaller than expected!" );
|
||||
GetEditDoc().RemoveChars( EditPaM( pNode, nCurrentPos+1 ), -nDiff);
|
||||
ESelection const deleted{maEditDoc.GetPos(pNode), nCurrentPos+1, maEditDoc.GetPos(pNode), nCurrentPos-nDiff};
|
||||
UpdateSelectionsDelete(deleted);
|
||||
}
|
||||
else
|
||||
{
|
||||
DBG_ASSERT( nDiff == 1, "TransliterateText - Diff other than expected! But should work..." );
|
||||
GetEditDoc().InsertText( EditPaM( pNode, nCurrentPos ), OUStringChar(rNewText[n]) );
|
||||
ESelection const inserted{maEditDoc.GetPos(pNode), nCurrentPos, maEditDoc.GetPos(pNode), nCurrentPos+nDiff};
|
||||
UpdateSelectionsInsert(inserted);
|
||||
|
||||
}
|
||||
nDiffs = sal::static_int_cast< short >(nDiffs + nDiff);
|
||||
|
||||
@@ -41,6 +41,7 @@
|
||||
class IYrsTransactionSupplier;
|
||||
typedef struct TransactionInner YTransaction;
|
||||
typedef struct YTextEvent YTextEvent;
|
||||
typedef struct Branch Branch;
|
||||
#endif
|
||||
|
||||
class EditTextObject;
|
||||
@@ -416,6 +417,12 @@ public:
|
||||
void YrsReadEEState(YTransaction *);
|
||||
void YrsApplyEEDelta(YTransaction *, YTextEvent const* pEvent);
|
||||
OString GetYrsCommentId() const;
|
||||
void YrsApplyEECursor(OString const& rPeerId, OUString const& rAuthor,
|
||||
::std::pair<int64_t, int64_t> point,
|
||||
::std::optional<::std::pair<int64_t, int64_t>> oMark);
|
||||
bool YrsDelEECursor(OString const& rPeerId);
|
||||
void YrsGetSelectionRectangles(
|
||||
::std::vector<::std::pair<OUString, ::std::vector<tools::Rectangle>>>& rLogicRects) const;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
@@ -206,7 +206,6 @@ void WeldEditView::PaintSelection(vcl::RenderContext& rRenderContext, tools::Rec
|
||||
aLogicRanges.emplace_back(nLeft, nTop, nRight, nBottom);
|
||||
}
|
||||
|
||||
// get the system's highlight color
|
||||
sdr::overlay::OverlaySelection aCursorOverlay(sdr::overlay::OverlayType::Transparent, color,
|
||||
std::move(aLogicRanges), true);
|
||||
|
||||
@@ -248,6 +247,7 @@ void WeldEditView::DoPaint(vcl::RenderContext& rRenderContext, const tools::Rect
|
||||
std::vector<tools::Rectangle> aLogicRects;
|
||||
pEditView->GetSelectionRectangles(aLogicRects);
|
||||
|
||||
// get the system's highlight color
|
||||
const Color aHighlight(SvtOptionsDrawinglayer::getHilightColor());
|
||||
PaintSelection(rRenderContext, rRect, aLogicRects, aHighlight);
|
||||
|
||||
|
||||
@@ -211,11 +211,14 @@ class SAL_DLLPUBLIC_RTTI SwAnnotationWin final : public InterimItemWindow
|
||||
bool IsRootNote() const;
|
||||
void SetAsRoot();
|
||||
|
||||
void queue_draw();
|
||||
|
||||
private:
|
||||
|
||||
virtual void LoseFocus() override;
|
||||
virtual void GetFocus() override;
|
||||
|
||||
virtual void Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect) override;
|
||||
void SetSizePixel( const Size& rNewSize ) override;
|
||||
|
||||
DECL_DLLPRIVATE_LINK(ModifyHdl, LinkParamNone*, void);
|
||||
|
||||
@@ -630,6 +630,7 @@ struct ObserveCursorState : public ObserveState
|
||||
{
|
||||
struct Update {
|
||||
OString const peerId;
|
||||
::std::optional<OString> const oCommentId;
|
||||
::std::optional<OUString> const oAuthor;
|
||||
::std::pair<int64_t, int64_t> const point;
|
||||
::std::optional<::std::pair<int64_t, int64_t>> const oMark;
|
||||
@@ -641,8 +642,25 @@ void YrsCursorUpdates(ObserveCursorState & rState)
|
||||
{
|
||||
for (auto const& it : rState.CursorUpdates)
|
||||
{
|
||||
#if defined(LOPLUGIN_BLOCK_BLOCK)
|
||||
#endif
|
||||
if (it.oCommentId)
|
||||
{
|
||||
auto const it2{rState.rYrsSupplier.GetComments().find(*it.oCommentId)};
|
||||
yvalidate(it2 != rState.rYrsSupplier.GetComments().end());
|
||||
SwAnnotationWin & rWin{*it2->second.front()->mpPostIt};
|
||||
// note: rState.pTxn is invalid at this point!
|
||||
rWin.GetOutlinerView()->GetEditView().YrsApplyEECursor(it.peerId, *it.oAuthor, it.point, it.oMark);
|
||||
if ((rWin.GetStyle() & WB_DIALOGCONTROL) == 0)
|
||||
{
|
||||
// note: Invalidate does work with gen but does not with gtk3
|
||||
//rWin.Invalidate(); // not active window, force paint
|
||||
rWin.queue_draw();
|
||||
}
|
||||
else
|
||||
{ // apparently this repaints active window
|
||||
rWin.GetOutlinerView()->GetEditView().Invalidate();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
::std::optional<SwPosition> oMark;
|
||||
if (it.oMark)
|
||||
@@ -678,8 +696,43 @@ void YrsCursorUpdates(ObserveCursorState & rState)
|
||||
}
|
||||
}
|
||||
|
||||
void YrsInvalidateEECursors(ObserveState const& rState,
|
||||
OString const& rPeerId, OString const*const pCommentId)
|
||||
{
|
||||
for (auto const& it : rState.rYrsSupplier.GetComments())
|
||||
{
|
||||
if (pCommentId == nullptr || *pCommentId != it.first)
|
||||
{
|
||||
SwAnnotationWin & rWin{*it.second.front()->mpPostIt};
|
||||
if (rWin.GetOutlinerView()->GetEditView().YrsDelEECursor(rPeerId))
|
||||
{
|
||||
rWin.queue_draw(); // repaint
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void YrsInvalidateSwCursors(ObserveState const& rState,
|
||||
OString const& rPeerId, OUString const& rAuthor, bool const isAdd)
|
||||
{
|
||||
for (SwViewShell & rShell : rState.rDoc.getIDocumentLayoutAccess().GetCurrentViewShell()->GetRingContainer())
|
||||
{
|
||||
if (auto const pShell{dynamic_cast<SwCursorShell *>(&rShell)})
|
||||
{
|
||||
if (isAdd)
|
||||
{
|
||||
pShell->YrsAddCursor(rPeerId, {}, {}, rAuthor);
|
||||
}
|
||||
else
|
||||
{
|
||||
pShell->YrsSetCursor(rPeerId, {}, {});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void YrsReadCursor(ObserveCursorState & rState, OString const& rPeerId,
|
||||
YOutput const& rCursor, ::std::optional<OUString> const oAuthor)
|
||||
YOutput const& rCursor, OUString const& rAuthor, bool const isAdd)
|
||||
{
|
||||
switch (rCursor.tag)
|
||||
{
|
||||
@@ -689,10 +742,32 @@ void YrsReadCursor(ObserveCursorState & rState, OString const& rPeerId,
|
||||
auto const len{yarray_len(pArray)};
|
||||
if (len == 3 || len == 5)
|
||||
{
|
||||
// TODO cursor in EE
|
||||
::std::unique_ptr<YOutput, YOutputDeleter> const pComment{yarray_get(pArray, rState.pTxn, 0)};
|
||||
yvalidate(pComment->tag == Y_JSON_STR && pComment->len < SAL_MAX_INT32);
|
||||
OString const commentId{pComment->value.str, static_cast<sal_Int32>(pComment->len)};
|
||||
YrsInvalidateEECursors(rState, rPeerId, &commentId);
|
||||
YrsInvalidateSwCursors(rState, rPeerId, rAuthor, false);
|
||||
::std::optional<::std::pair<int64_t, int64_t>> oMark;
|
||||
if (len == 5)
|
||||
{
|
||||
::std::unique_ptr<YOutput, YOutputDeleter> const pNode{
|
||||
yarray_get(pArray, rState.pTxn, 3)};
|
||||
yvalidate(pNode->tag == Y_JSON_INT);
|
||||
::std::unique_ptr<YOutput, YOutputDeleter> const pContent{
|
||||
yarray_get(pArray, rState.pTxn, 4)};
|
||||
yvalidate(pContent->tag == Y_JSON_INT);
|
||||
oMark.emplace(pNode->value.integer, pContent->value.integer);
|
||||
}
|
||||
::std::unique_ptr<YOutput, YOutputDeleter> const pNode{yarray_get(pArray, rState.pTxn, 1)};
|
||||
yvalidate(pNode->tag == Y_JSON_INT);
|
||||
::std::unique_ptr<YOutput, YOutputDeleter> const pContent{yarray_get(pArray, rState.pTxn, 2)};
|
||||
yvalidate(pContent->tag == Y_JSON_INT);
|
||||
::std::pair<int64_t, int64_t> const pos{pNode->value.integer, pContent->value.integer};
|
||||
rState.CursorUpdates.emplace_back(rPeerId, ::std::optional<OString>{commentId}, ::std::optional<OUString>{rAuthor}, pos, oMark);
|
||||
}
|
||||
else if (len == 2 || len == 4)
|
||||
{
|
||||
YrsInvalidateEECursors(rState, rPeerId, nullptr);
|
||||
// the only reason this stuff has a hope of working with
|
||||
// integers is that the SwNodes is read-only
|
||||
::std::optional<::std::pair<int64_t, int64_t>> oMark;
|
||||
@@ -710,27 +785,17 @@ void YrsReadCursor(ObserveCursorState & rState, OString const& rPeerId,
|
||||
::std::unique_ptr<YOutput, YOutputDeleter> const pContent{yarray_get(pArray, rState.pTxn, 1)};
|
||||
yvalidate(pContent->tag == Y_JSON_INT);
|
||||
::std::pair<int64_t, int64_t> const pos{pNode->value.integer, pContent->value.integer};
|
||||
rState.CursorUpdates.emplace_back(rPeerId, oAuthor, pos, oMark);
|
||||
rState.CursorUpdates.emplace_back(rPeerId, ::std::optional<OString>{},
|
||||
isAdd ? ::std::optional<OUString>{rAuthor} : ::std::optional<OUString>{},
|
||||
pos, oMark);
|
||||
}
|
||||
else
|
||||
yvalidate(false);
|
||||
break;
|
||||
}
|
||||
case Y_JSON_NULL:
|
||||
for (SwViewShell & rShell : rState.rDoc.getIDocumentLayoutAccess().GetCurrentViewShell()->GetRingContainer())
|
||||
{
|
||||
if (auto const pShell{dynamic_cast<SwCursorShell *>(&rShell)})
|
||||
{
|
||||
if (oAuthor)
|
||||
{
|
||||
pShell->YrsAddCursor(rPeerId, {}, {}, *oAuthor);
|
||||
}
|
||||
else
|
||||
{
|
||||
pShell->YrsSetCursor(rPeerId, {}, {});
|
||||
}
|
||||
}
|
||||
}
|
||||
YrsInvalidateEECursors(rState, rPeerId, nullptr);
|
||||
YrsInvalidateSwCursors(rState, rPeerId, rAuthor, isAdd);
|
||||
break;
|
||||
default:
|
||||
yvalidate(false);
|
||||
@@ -783,7 +848,7 @@ extern "C" void observe_cursors(void *const pState, uint32_t count, YEvent const
|
||||
static_cast<sal_Int32>(pAuthor->len), RTL_TEXTENCODING_UTF8};
|
||||
::std::unique_ptr<YOutput, YOutputDeleter> const pCursor{
|
||||
yarray_get(pArray, rState.pTxn, 1)};
|
||||
YrsReadCursor(rState, peerId, *pCursor, {author});
|
||||
YrsReadCursor(rState, peerId, *pCursor, author, true);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@@ -830,7 +895,10 @@ extern "C" void observe_cursors(void *const pState, uint32_t count, YEvent const
|
||||
yvalidate(pChange[1].len == 1);
|
||||
yvalidate(pChange[2].tag == Y_EVENT_CHANGE_ADD);
|
||||
yvalidate(pChange[2].len == 1);
|
||||
YrsReadCursor(rState, peerId, pChange[2].values[0], {});
|
||||
Branch const*const pArray{yarray_event_target(pEvent)};
|
||||
::std::unique_ptr<YOutput, YOutputDeleter> const pAuthor{yarray_get(pArray, rState.pTxn, 0)};
|
||||
OUString const author{pAuthor->value.str, static_cast<sal_Int32>(pAuthor->len), RTL_TEXTENCODING_UTF8};
|
||||
YrsReadCursor(rState, peerId, pChange[2].values[0], author, false);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@@ -1168,12 +1236,12 @@ void DocumentStateManager::YrsRemoveComment(SwPosition const& rPos, OString cons
|
||||
void DocumentStateManager::YrsNotifyCursorUpdate()
|
||||
{
|
||||
SwWrtShell *const pShell{dynamic_cast<SwWrtShell*>(m_rDoc.getIDocumentLayoutAccess().GetCurrentViewShell())};
|
||||
if (!m_pYrsSupplier || !pShell->GetView().GetPostItMgr())
|
||||
YTransaction *const pTxn{m_pYrsSupplier ? m_pYrsSupplier->GetWriteTransaction() : nullptr};
|
||||
if (!pTxn || !pShell->GetView().GetPostItMgr())
|
||||
{
|
||||
return;
|
||||
}
|
||||
SAL_DEBUG("YRS NotifyCursorUpdate");
|
||||
YTransaction *const pTxn{m_pYrsSupplier->GetWriteTransaction()};
|
||||
YDoc *const pYDoc{m_pYrsSupplier->GetYDoc()};
|
||||
auto const id{ydoc_id(pYDoc)};
|
||||
::std::unique_ptr<YOutput, YOutputDeleter> pEntry{ymap_get(m_pYrsSupplier->m_pCursors, pTxn, OString::number(id).getStr())};
|
||||
@@ -1464,7 +1532,6 @@ void DocumentStateManager::SetModified()
|
||||
|
||||
#if defined(YRS)
|
||||
SAL_DEBUG("YRS SetModified");
|
||||
// FIXME: this is called only on LoseFocus! not while editing comment
|
||||
YrsCommitModified();
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -937,6 +937,22 @@ void SwAnnotationWin::LoseFocus()
|
||||
{
|
||||
}
|
||||
|
||||
void SwAnnotationWin::queue_draw()
|
||||
{
|
||||
if (mxSidebarTextControlWin)
|
||||
{
|
||||
mxSidebarTextControlWin->queue_draw();
|
||||
}
|
||||
}
|
||||
|
||||
void SwAnnotationWin::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect)
|
||||
{
|
||||
if (mxSidebarTextControl)
|
||||
{
|
||||
mxSidebarTextControl->Paint(rRenderContext, rRect);
|
||||
}
|
||||
}
|
||||
|
||||
void SwAnnotationWin::ShowNote()
|
||||
{
|
||||
SetPosAndSize();
|
||||
|
||||
@@ -57,6 +57,7 @@
|
||||
#include <IDocumentDeviceAccess.hxx>
|
||||
#if defined(YRS)
|
||||
#include <IDocumentState.hxx>
|
||||
#include <swmodule.hxx>
|
||||
#endif
|
||||
#include <redline.hxx>
|
||||
#include <memory>
|
||||
@@ -205,9 +206,18 @@ OUString SidebarTextControl::RequestHelp(tools::Rectangle& rHelpRect)
|
||||
#if defined(YRS)
|
||||
void SidebarTextControl::EditViewInvalidate(const tools::Rectangle& rRect)
|
||||
{
|
||||
SAL_DEBUG("YRS EditViewInvalidate");
|
||||
mrDocView.GetDocShell()->GetDoc()->getIDocumentState().YrsNotifyCursorUpdate();
|
||||
mrDocView.GetDocShell()->GetDoc()->getIDocumentState().YrsCommitModified();
|
||||
return WeldEditView::EditViewInvalidate(rRect);
|
||||
}
|
||||
|
||||
void SidebarTextControl::EditViewSelectionChange()
|
||||
{
|
||||
SAL_DEBUG("YRS EditViewSelectionChange");
|
||||
mrDocView.GetDocShell()->GetDoc()->getIDocumentState().YrsNotifyCursorUpdate();
|
||||
return WeldEditView::EditViewSelectionChange();
|
||||
}
|
||||
#endif
|
||||
|
||||
void SidebarTextControl::EditViewScrollStateChange()
|
||||
@@ -268,6 +278,25 @@ void SidebarTextControl::Paint(vcl::RenderContext& rRenderContext, const tools::
|
||||
|
||||
DoPaint(rRenderContext, rRect);
|
||||
|
||||
#if defined(YRS)
|
||||
if (EditView *const pEditView{GetEditView()})
|
||||
{
|
||||
rRenderContext.Push(vcl::PushFlags::ALL);
|
||||
rRenderContext.SetClipRegion();
|
||||
|
||||
::std::vector<::std::pair<OUString, ::std::vector<tools::Rectangle>>> rects;
|
||||
pEditView->YrsGetSelectionRectangles(rects);
|
||||
for (auto const& it : rects)
|
||||
{
|
||||
::std::size_t const authorId{SwModule::get()->InsertRedlineAuthor(it.first)};
|
||||
Color const color{SwPostItMgr::GetColorAnchor(authorId)};
|
||||
PaintSelection(rRenderContext, rRect, it.second, color);
|
||||
}
|
||||
|
||||
rRenderContext.Pop();
|
||||
}
|
||||
#endif
|
||||
|
||||
if (mrSidebarWin.GetLayoutStatus() != SwPostItHelper::DELETED)
|
||||
return;
|
||||
|
||||
|
||||
@@ -40,8 +40,6 @@ class SidebarTextControl : public WeldEditView
|
||||
void MakeVisible();
|
||||
|
||||
protected:
|
||||
virtual void Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect) override;
|
||||
|
||||
virtual bool Command(const CommandEvent& rCEvt) override;
|
||||
virtual void GetFocus() override;
|
||||
virtual void LoseFocus() override;
|
||||
@@ -53,12 +51,15 @@ class SidebarTextControl : public WeldEditView
|
||||
SwView& rDocView,
|
||||
SwPostItMgr& rPostItMgr);
|
||||
|
||||
virtual void Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect) override;
|
||||
|
||||
virtual EditView* GetEditView() const override;
|
||||
|
||||
virtual EditEngine* GetEditEngine() const override;
|
||||
|
||||
#if defined(YRS)
|
||||
virtual void EditViewInvalidate(const tools::Rectangle& rRect) override;
|
||||
virtual void EditViewSelectionChange() override;
|
||||
#endif
|
||||
virtual void EditViewScrollStateChange() override;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user