summaryrefslogtreecommitdiffstats
path: root/sw/source/uibase/docvw/AnnotationWin2.cxx
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-27 16:51:28 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-27 16:51:28 +0000
commit940b4d1848e8c70ab7642901a68594e8016caffc (patch)
treeeb72f344ee6c3d9b80a7ecc079ea79e9fba8676d /sw/source/uibase/docvw/AnnotationWin2.cxx
parentInitial commit. (diff)
downloadlibreoffice-upstream.tar.xz
libreoffice-upstream.zip
Adding upstream version 1:7.0.4.upstream/1%7.0.4upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r--sw/source/uibase/docvw/AnnotationWin2.cxx1624
1 files changed, 1624 insertions, 0 deletions
diff --git a/sw/source/uibase/docvw/AnnotationWin2.cxx b/sw/source/uibase/docvw/AnnotationWin2.cxx
new file mode 100644
index 000000000..9c3539f2e
--- /dev/null
+++ b/sw/source/uibase/docvw/AnnotationWin2.cxx
@@ -0,0 +1,1624 @@
+/* -*- 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 <sal/config.h>
+
+#include <cstddef>
+
+#include "SidebarWinAcc.hxx"
+#include <PostItMgr.hxx>
+#include <AnnotationWin.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <basegfx/range/b2drange.hxx>
+#include "SidebarTxtControl.hxx"
+#include "SidebarScrollBar.hxx"
+#include "AnchorOverlayObject.hxx"
+#include "ShadowOverlayObject.hxx"
+#include "OverlayRanges.hxx"
+
+#include <strings.hrc>
+
+#include <viewopt.hxx>
+#include <cmdid.h>
+
+#include <editeng/fhgtitem.hxx>
+#include <editeng/langitem.hxx>
+#include <editeng/editview.hxx>
+#include <editeng/outliner.hxx>
+#include <editeng/editeng.hxx>
+#include <editeng/eeitem.hxx>
+#include <editeng/outlobj.hxx>
+
+#include <svl/undo.hxx>
+#include <svl/stritem.hxx>
+
+#include <sfx2/viewfrm.hxx>
+#include <sfx2/bindings.hxx>
+#include <sfx2/dispatch.hxx>
+
+#include <vcl/edit.hxx>
+#include <vcl/event.hxx>
+#include <vcl/scrbar.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/menubtn.hxx>
+#include <vcl/settings.hxx>
+#include <vcl/ptrstyle.hxx>
+
+#include <edtwin.hxx>
+#include <view.hxx>
+#include <docsh.hxx>
+#include <wrtsh.hxx>
+#include <doc.hxx>
+#include <swmodule.hxx>
+
+#include <txtannotationfld.hxx>
+#include <ndtxt.hxx>
+
+#include <drawinglayer/processor2d/baseprocessor2d.hxx>
+#include <drawinglayer/processor2d/processorfromoutputdevice.hxx>
+#include <unotools/localedatawrapper.hxx>
+#include <memory>
+#include <comphelper/lok.hxx>
+
+using namespace sw::sidebarwindows;
+
+namespace
+{
+
+/// Translate absolute <-> relative twips: LOK wants absolute coordinates as output and gives absolute coordinates as input.
+void lcl_translateTwips(vcl::Window const & rParent, vcl::Window& rChild, MouseEvent* pMouseEvent)
+{
+ // Set map mode, so that callback payloads will contain absolute coordinates instead of relative ones.
+ Point aOffset(rChild.GetOutOffXPixel() - rParent.GetOutOffXPixel(), rChild.GetOutOffYPixel() - rParent.GetOutOffYPixel());
+ if (!rChild.IsMapModeEnabled())
+ {
+ MapMode aMapMode(rChild.GetMapMode());
+ aMapMode.SetMapUnit(MapUnit::MapTwip);
+ aMapMode.SetScaleX(rParent.GetMapMode().GetScaleX());
+ aMapMode.SetScaleY(rParent.GetMapMode().GetScaleY());
+ rChild.SetMapMode(aMapMode);
+ rChild.EnableMapMode();
+ }
+ aOffset = rChild.PixelToLogic(aOffset);
+ MapMode aMapMode(rChild.GetMapMode());
+ aMapMode.SetOrigin(aOffset);
+ aMapMode.SetMapUnit(rParent.GetMapMode().GetMapUnit());
+ rChild.SetMapMode(aMapMode);
+ rChild.EnableMapMode(false);
+
+ if (pMouseEvent)
+ {
+ // Set event coordinates, so they contain relative coordinates instead of absolute ones.
+ Point aPos = pMouseEvent->GetPosPixel();
+ aPos.Move(-aOffset.getX(), -aOffset.getY());
+ MouseEvent aMouseEvent(aPos, pMouseEvent->GetClicks(), pMouseEvent->GetMode(), pMouseEvent->GetButtons(), pMouseEvent->GetModifier());
+ *pMouseEvent = aMouseEvent;
+ }
+}
+
+/// Decide which one from the children of rParent should get rMouseEvent.
+vcl::Window* lcl_getHitWindow(sw::annotation::SwAnnotationWin& rParent, const MouseEvent& rMouseEvent)
+{
+ vcl::Window* pRet = nullptr;
+
+ rParent.EditWin().Push(PushFlags::MAPMODE);
+ rParent.EditWin().EnableMapMode();
+ for (sal_Int16 i = rParent.GetChildCount() - 1; i >= 0; --i)
+ {
+ vcl::Window* pChild = rParent.GetChild(i);
+
+ Point aPosition(rParent.GetPosPixel());
+ aPosition.Move(pChild->GetPosPixel().getX(), pChild->GetPosPixel().getY());
+ Size aSize(rParent.GetSizePixel());
+ tools::Rectangle aRectangleLogic(rParent.EditWin().PixelToLogic(aPosition), rParent.EditWin().PixelToLogic(aSize));
+ if (aRectangleLogic.IsInside(rMouseEvent.GetPosPixel()))
+ {
+ pRet = pChild;
+ break;
+ }
+ }
+ rParent.EditWin().Pop();
+ return pRet;
+}
+
+}
+
+namespace sw::annotation {
+
+#define METABUTTON_WIDTH 16
+#define METABUTTON_HEIGHT 18
+#define METABUTTON_AREA_WIDTH 30
+#define POSTIT_META_FIELD_HEIGHT sal_Int32(15)
+#define POSTIT_MINIMUMSIZE_WITHOUT_META 50
+
+
+void SwAnnotationWin::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect)
+{
+ Window::Paint(rRenderContext, rRect);
+
+ if (mpMetadataAuthor->IsVisible())
+ {
+ //draw left over space
+ if (Application::GetSettings().GetStyleSettings().GetHighContrastMode())
+ {
+ rRenderContext.SetFillColor(COL_BLACK);
+ }
+ else
+ {
+ rRenderContext.SetFillColor(mColorDark);
+ }
+
+ sal_uInt32 boxHeight = mpMetadataAuthor->GetSizePixel().Height() + mpMetadataDate->GetSizePixel().Height();
+ boxHeight += IsThreadResolved() ? mpMetadataResolved->GetSizePixel().Height() : 0;
+
+ rRenderContext.SetLineColor();
+ tools::Rectangle aRectangle(Point(mpMetadataAuthor->GetPosPixel().X() + mpMetadataAuthor->GetSizePixel().Width(),
+ mpMetadataAuthor->GetPosPixel().Y()),
+ Size(GetMetaButtonAreaWidth(), boxHeight));
+
+ if (comphelper::LibreOfficeKit::isActive())
+ aRectangle = rRect;
+ else
+ aRectangle = PixelToLogic(aRectangle);
+ rRenderContext.DrawRect(aRectangle);
+ }
+}
+
+void SwAnnotationWin::PaintTile(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect)
+{
+ Paint(rRenderContext, rRect);
+
+ for (sal_uInt16 i = 0; i < GetChildCount(); ++i)
+ {
+ vcl::Window* pChild = GetChild(i);
+
+ // No point in showing this button till click on it are not handled.
+ if (pChild == mpMenuButton.get())
+ continue;
+
+ if (!pChild->IsVisible())
+ continue;
+
+ rRenderContext.Push(PushFlags::MAPMODE);
+ Point aOffset(PixelToLogic(pChild->GetPosPixel()));
+ MapMode aMapMode(rRenderContext.GetMapMode());
+ aMapMode.SetOrigin(aMapMode.GetOrigin() + aOffset);
+ rRenderContext.SetMapMode(aMapMode);
+
+ bool bPopChild = false;
+ if (pChild->GetMapMode().GetMapUnit() != rRenderContext.GetMapMode().GetMapUnit())
+ {
+ // This is needed for the scrollbar that has its map unit in pixels.
+ pChild->Push(PushFlags::MAPMODE);
+ bPopChild = true;
+ pChild->EnableMapMode();
+ aMapMode = pChild->GetMapMode();
+ aMapMode.SetMapUnit(rRenderContext.GetMapMode().GetMapUnit());
+ aMapMode.SetScaleX(rRenderContext.GetMapMode().GetScaleX());
+ aMapMode.SetScaleY(rRenderContext.GetMapMode().GetScaleY());
+ pChild->SetMapMode(aMapMode);
+ }
+
+ pChild->Paint(rRenderContext, rRect);
+
+ if (bPopChild)
+ pChild->Pop();
+ rRenderContext.Pop();
+ }
+
+ const drawinglayer::geometry::ViewInformation2D aViewInformation;
+ std::unique_ptr<drawinglayer::processor2d::BaseProcessor2D> pProcessor(drawinglayer::processor2d::createBaseProcessor2DFromOutputDevice(rRenderContext, aViewInformation));
+
+ // drawinglayer sets the map mode to pixels, not needed here.
+ rRenderContext.Pop();
+ // Work in document-global twips.
+ rRenderContext.Pop();
+ if (mpAnchor)
+ pProcessor->process(mpAnchor->getOverlayObjectPrimitive2DSequence());
+ if (mpTextRangeOverlay)
+ pProcessor->process(mpTextRangeOverlay->getOverlayObjectPrimitive2DSequence());
+
+ rRenderContext.Push(PushFlags::NONE);
+ pProcessor.reset();
+ rRenderContext.Push(PushFlags::NONE);
+}
+
+bool SwAnnotationWin::IsHitWindow(const Point& rPointLogic)
+{
+ tools::Rectangle aRectangleLogic(EditWin().PixelToLogic(GetPosPixel()), EditWin().PixelToLogic(GetSizePixel()));
+ return aRectangleLogic.IsInside(rPointLogic);
+}
+
+void SwAnnotationWin::SetCursorLogicPosition(const Point& rPosition, bool bPoint, bool bClearMark)
+{
+ mpSidebarTextControl->Push(PushFlags::MAPMODE);
+ MouseEvent aMouseEvent(rPosition);
+ lcl_translateTwips(EditWin(), *mpSidebarTextControl, &aMouseEvent);
+ Point aPosition(aMouseEvent.GetPosPixel());
+
+ EditView& rEditView = GetOutlinerView()->GetEditView();
+ rEditView.SetCursorLogicPosition(aPosition, bPoint, bClearMark);
+
+ mpSidebarTextControl->Pop();
+}
+
+void SwAnnotationWin::Draw(OutputDevice* pDev, const Point& rPt, DrawFlags nInFlags)
+{
+ Size aSz = pDev->PixelToLogic(GetSizePixel());
+
+ if (mpMetadataAuthor->IsVisible() )
+ {
+ pDev->SetFillColor(mColorDark);
+ pDev->SetLineColor();
+ pDev->DrawRect( tools::Rectangle( rPt, aSz ) );
+ }
+
+ if (mpMetadataAuthor->IsVisible())
+ {
+ vcl::Font aOrigFont(mpMetadataAuthor->GetControlFont());
+ Point aPos(PixelToLogic(mpMetadataAuthor->GetPosPixel()));
+ aPos += rPt;
+ vcl::Font aFont( mpMetadataAuthor->GetSettings().GetStyleSettings().GetFieldFont() );
+ mpMetadataAuthor->SetControlFont( aFont );
+ mpMetadataAuthor->Draw(pDev, aPos, nInFlags);
+ mpMetadataAuthor->SetControlFont( aOrigFont );
+ }
+
+ if (mpMetadataDate->IsVisible())
+ {
+ vcl::Font aOrigFont(mpMetadataDate->GetControlFont());
+ Point aPos(PixelToLogic(mpMetadataDate->GetPosPixel()));
+ aPos += rPt;
+ vcl::Font aFont( mpMetadataDate->GetSettings().GetStyleSettings().GetFieldFont() );
+ mpMetadataDate->SetControlFont( aFont );
+ mpMetadataDate->SetControlFont( aOrigFont );
+ }
+
+ if (mpMetadataResolved->IsVisible())
+ {
+ vcl::Font aOrigFont(mpMetadataResolved->GetControlFont());
+ Point aPos(PixelToLogic(mpMetadataResolved->GetPosPixel()));
+ aPos += rPt;
+ vcl::Font aFont( mpMetadataResolved->GetSettings().GetStyleSettings().GetFieldFont() );
+ mpMetadataResolved->SetControlFont( aFont );
+ mpMetadataResolved->SetControlFont( aOrigFont );
+ }
+
+ Size aOrigSize(mpSidebarTextControl->GetSizePixel());
+ mpSidebarTextControl->SetSizePixel(aSz);
+ mpSidebarTextControl->Draw(pDev, rPt, nInFlags);
+ mpSidebarTextControl->SetSizePixel(aOrigSize);
+
+ const drawinglayer::geometry::ViewInformation2D aNewViewInfos;
+ std::unique_ptr<drawinglayer::processor2d::BaseProcessor2D> pProcessor(
+ drawinglayer::processor2d::createBaseProcessor2DFromOutputDevice(
+ *pDev, aNewViewInfos ));
+
+ if (mpAnchor)
+ pProcessor->process(mpAnchor->getOverlayObjectPrimitive2DSequence());
+ if (mpTextRangeOverlay)
+ pProcessor->process(mpTextRangeOverlay->getOverlayObjectPrimitive2DSequence());
+ pProcessor.reset();
+
+ if (!mpVScrollbar->IsVisible())
+ return;
+
+ vcl::Font aOrigFont(mpMetadataDate->GetControlFont());
+ Color aOrigBg( mpMetadataDate->GetControlBackground() );
+ OUString sOrigText(mpMetadataDate->GetText());
+
+ Point aPos(PixelToLogic(mpMenuButton->GetPosPixel()));
+ aPos += rPt;
+
+ vcl::Font aFont( mpMetadataDate->GetSettings().GetStyleSettings().GetFieldFont() );
+ mpMetadataDate->SetControlFont( aFont );
+ mpMetadataDate->SetControlBackground( Color(0xFFFFFF) );
+ mpMetadataDate->SetText("...");
+ aOrigSize = mpMetadataDate->GetSizePixel();
+ mpMetadataDate->SetSizePixel(mpMenuButton->GetSizePixel());
+ mpMetadataDate->Draw(pDev, aPos, nInFlags);
+ mpMetadataDate->SetSizePixel(aOrigSize);
+
+ mpMetadataDate->SetText(sOrigText);
+ mpMetadataDate->SetControlFont( aOrigFont );
+ mpMetadataDate->SetControlBackground( aOrigBg );
+}
+
+void SwAnnotationWin::KeyInput(const KeyEvent& rKeyEvent)
+{
+ if (mpSidebarTextControl)
+ {
+ mpSidebarTextControl->Push(PushFlags::MAPMODE);
+ lcl_translateTwips(EditWin(), *mpSidebarTextControl, nullptr);
+
+ mpSidebarTextControl->KeyInput(rKeyEvent);
+
+ mpSidebarTextControl->Pop();
+ }
+}
+
+void SwAnnotationWin::MouseMove(const MouseEvent& rMouseEvent)
+{
+ if (vcl::Window* pHit = lcl_getHitWindow(*this, rMouseEvent))
+ {
+ pHit->Push(PushFlags::MAPMODE);
+ MouseEvent aMouseEvent(rMouseEvent);
+ lcl_translateTwips(EditWin(), *pHit, &aMouseEvent);
+
+ pHit->MouseMove(aMouseEvent);
+
+ pHit->Pop();
+ }
+}
+
+void SwAnnotationWin::MouseButtonDown(const MouseEvent& rMouseEvent)
+{
+ if (vcl::Window* pHit = lcl_getHitWindow(*this, rMouseEvent))
+ {
+ pHit->Push(PushFlags::MAPMODE);
+ MouseEvent aMouseEvent(rMouseEvent);
+ lcl_translateTwips(EditWin(), *pHit, &aMouseEvent);
+
+ pHit->MouseButtonDown(aMouseEvent);
+
+ pHit->Pop();
+ }
+}
+
+void SwAnnotationWin::MouseButtonUp(const MouseEvent& rMouseEvent)
+{
+ if (vcl::Window* pHit = lcl_getHitWindow(*this, rMouseEvent))
+ {
+ pHit->Push(PushFlags::MAPMODE);
+ MouseEvent aMouseEvent(rMouseEvent);
+ lcl_translateTwips(EditWin(), *pHit, &aMouseEvent);
+
+ pHit->MouseButtonUp(aMouseEvent);
+
+ pHit->Pop();
+ }
+}
+
+void SwAnnotationWin::SetPosSizePixelRect(long nX, long nY, long nWidth, long nHeight,
+ const SwRect& aAnchorRect, const long aPageBorder)
+{
+ mPosSize = tools::Rectangle(Point(nX,nY),Size(nWidth,nHeight));
+ if (!mAnchorRect.IsEmpty() && mAnchorRect != aAnchorRect)
+ mbAnchorRectChanged = true;
+ mAnchorRect = aAnchorRect;
+ mPageBorder = aPageBorder;
+}
+
+void SwAnnotationWin::SetSize( const Size& rNewSize )
+{
+ mPosSize.SetSize(rNewSize);
+}
+
+void SwAnnotationWin::SetVirtualPosSize( const Point& aPoint, const Size& aSize)
+{
+ mPosSize = tools::Rectangle(aPoint,aSize);
+}
+
+void SwAnnotationWin::TranslateTopPosition(const long aAmount)
+{
+ mPosSize.Move(0,aAmount);
+}
+
+void SwAnnotationWin::ShowAnchorOnly(const Point &aPoint)
+{
+ HideNote();
+ SetPosAndSize();
+ if (mpAnchor)
+ {
+ mpAnchor->SetSixthPosition(basegfx::B2DPoint(aPoint.X(),aPoint.Y()));
+ mpAnchor->SetSeventhPosition(basegfx::B2DPoint(aPoint.X(),aPoint.Y()));
+ mpAnchor->SetAnchorState(AnchorState::All);
+ mpAnchor->setVisible(true);
+ }
+ if (mpShadow)
+ mpShadow->setVisible(false);
+}
+
+SfxItemSet SwAnnotationWin::DefaultItem()
+{
+ SfxItemSet aItem( mrView.GetDocShell()->GetPool() );
+ aItem.Put(SvxFontHeightItem(200,100,EE_CHAR_FONTHEIGHT));
+ return aItem;
+}
+
+void SwAnnotationWin::InitControls()
+{
+ AddEventListener( LINK( this, SwAnnotationWin, WindowEventListener ) );
+
+ // actual window which holds the user text
+ mpSidebarTextControl = VclPtr<SidebarTextControl>::Create( *this,
+ WB_NODIALOGCONTROL,
+ mrView, mrMgr );
+ mpSidebarTextControl->SetPointer(PointerStyle::Text);
+
+ // window controls for author and date
+ mpMetadataAuthor = VclPtr<Edit>::Create( this, 0 );
+ mpMetadataAuthor->SetAccessibleName( SwResId( STR_ACCESS_ANNOTATION_AUTHOR_NAME ) );
+ mpMetadataAuthor->EnableRTL(AllSettings::GetLayoutRTL());
+ mpMetadataAuthor->SetReadOnly();
+ mpMetadataAuthor->AlwaysDisableInput(true);
+ mpMetadataAuthor->SetCallHandlersOnInputDisabled(true);
+ mpMetadataAuthor->AddEventListener( LINK( this, SwAnnotationWin, WindowEventListener ) );
+ // we should leave this setting alone, but for this we need a better layout algo
+ // with variable meta size height
+ {
+ AllSettings aSettings = mpMetadataAuthor->GetSettings();
+ StyleSettings aStyleSettings = aSettings.GetStyleSettings();
+ vcl::Font aFont = aStyleSettings.GetFieldFont();
+ aFont.SetFontHeight(8);
+ aStyleSettings.SetFieldFont(aFont);
+ aSettings.SetStyleSettings(aStyleSettings);
+ mpMetadataAuthor->SetSettings(aSettings);
+ }
+
+ mpMetadataDate = VclPtr<Edit>::Create( this, 0 );
+ mpMetadataDate->SetAccessibleName( SwResId( STR_ACCESS_ANNOTATION_DATE_NAME ) );
+ mpMetadataDate->EnableRTL(AllSettings::GetLayoutRTL());
+ mpMetadataDate->SetReadOnly();
+ mpMetadataDate->AlwaysDisableInput(true);
+ mpMetadataDate->SetCallHandlersOnInputDisabled(true);
+ mpMetadataDate->AddEventListener( LINK( this, SwAnnotationWin, WindowEventListener ) );
+ // we should leave this setting alone, but for this we need a better layout algo
+ // with variable meta size height
+ {
+ AllSettings aSettings = mpMetadataDate->GetSettings();
+ StyleSettings aStyleSettings = aSettings.GetStyleSettings();
+ vcl::Font aFont = aStyleSettings.GetFieldFont();
+ aFont.SetFontHeight(8);
+ aStyleSettings.SetFieldFont(aFont);
+ aSettings.SetStyleSettings(aStyleSettings);
+ mpMetadataDate->SetSettings(aSettings);
+ }
+
+ mpMetadataResolved = VclPtr<Edit>::Create( this, 0 );
+ mpMetadataResolved->SetAccessibleName( SwResId( STR_ACCESS_ANNOTATION_RESOLVED_NAME ) );
+ mpMetadataResolved->EnableRTL(AllSettings::GetLayoutRTL());
+ mpMetadataResolved->SetReadOnly();
+ mpMetadataResolved->AlwaysDisableInput(true);
+ mpMetadataResolved->SetCallHandlersOnInputDisabled(true);
+ mpMetadataResolved->AddEventListener( LINK( this, SwAnnotationWin, WindowEventListener ) );
+ // we should leave this setting alone, but for this we need a better layout algo
+ // with variable meta size height
+ {
+ AllSettings aSettings = mpMetadataResolved->GetSettings();
+ StyleSettings aStyleSettings = aSettings.GetStyleSettings();
+ vcl::Font aFont = aStyleSettings.GetFieldFont();
+ aFont.SetFontHeight(8);
+ aStyleSettings.SetFieldFont(aFont);
+ aSettings.SetStyleSettings(aStyleSettings);
+ mpMetadataResolved->SetSettings(aSettings);
+ mpMetadataResolved->SetText( SwResId( STR_ACCESS_ANNOTATION_RESOLVED_NAME ) );
+ }
+
+ SwDocShell* aShell = mrView.GetDocShell();
+ mpOutliner.reset(new Outliner(&aShell->GetPool(),OutlinerMode::TextObject));
+ aShell->GetDoc()->SetCalcFieldValueHdl( mpOutliner.get() );
+ mpOutliner->SetUpdateMode( true );
+ Rescale();
+
+ mpSidebarTextControl->EnableRTL( false );
+ mpOutlinerView.reset(new OutlinerView ( mpOutliner.get(), mpSidebarTextControl ));
+ mpOutlinerView->SetBackgroundColor(COL_TRANSPARENT);
+ mpOutliner->InsertView(mpOutlinerView.get() );
+ mpOutlinerView->SetOutputArea( PixelToLogic( tools::Rectangle(0,0,1,1) ) );
+
+ mpOutlinerView->SetAttribs(DefaultItem());
+
+ if (comphelper::LibreOfficeKit::isActive())
+ {
+ // If there is a callback already registered, inform the new outliner view about it.
+ mpOutlinerView->RegisterViewShell(&mrView);
+ }
+
+ //create Scrollbars
+ mpVScrollbar = VclPtr<SidebarScrollBar>::Create(*this, WB_3DLOOK |WB_VSCROLL|WB_DRAG, mrView);
+ mpVScrollbar->EnableNativeWidget(false);
+ mpVScrollbar->EnableRTL( false );
+ mpVScrollbar->SetScrollHdl(LINK(this, SwAnnotationWin, ScrollHdl));
+ mpVScrollbar->EnableDrag();
+ mpVScrollbar->AddEventListener( LINK( this, SwAnnotationWin, WindowEventListener ) );
+
+ const SwViewOption* pVOpt = mrView.GetWrtShellPtr()->GetViewOptions();
+ EEControlBits nCntrl = mpOutliner->GetControlWord();
+ // TODO: crash when AUTOCOMPLETE enabled
+ nCntrl |= EEControlBits::MARKFIELDS | EEControlBits::PASTESPECIAL | EEControlBits::AUTOCORRECT | EEControlBits::USECHARATTRIBS; // | EEControlBits::AUTOCOMPLETE;
+ if (SwViewOption::IsFieldShadings())
+ nCntrl |= EEControlBits::MARKFIELDS;
+ else
+ nCntrl &= ~EEControlBits::MARKFIELDS;
+ if (pVOpt->IsOnlineSpell())
+ nCntrl |= EEControlBits::ONLINESPELLING;
+ else
+ nCntrl &= ~EEControlBits::ONLINESPELLING;
+ mpOutliner->SetControlWord(nCntrl);
+
+ std::size_t aIndex = SW_MOD()->InsertRedlineAuthor(GetAuthor());
+ SetColor( SwPostItMgr::GetColorDark(aIndex),
+ SwPostItMgr::GetColorLight(aIndex),
+ SwPostItMgr::GetColorAnchor(aIndex));
+
+ CheckMetaText();
+
+ mpMenuButton = CreateMenuButton();
+
+ SetLanguage(GetLanguage());
+ GetOutlinerView()->StartSpeller();
+ SetPostItText();
+ mpOutliner->CompleteOnlineSpelling();
+
+ mpSidebarTextControl->Show();
+ mpMetadataAuthor->Show();
+ mpMetadataDate->Show();
+ if(IsThreadResolved()) { mpMetadataResolved->Show(); }
+ mpVScrollbar->Show();
+}
+
+void SwAnnotationWin::CheckMetaText()
+{
+ const SvtSysLocale aSysLocale;
+ const LocaleDataWrapper& rLocalData = aSysLocale.GetLocaleData();
+ OUString sMeta = GetAuthor();
+ if (sMeta.isEmpty())
+ {
+ sMeta = SwResId(STR_NOAUTHOR);
+ }
+ else if (sMeta.getLength() > 23)
+ {
+ sMeta = sMeta.copy(0, 20) + "...";
+ }
+ if ( mpMetadataAuthor->GetText() != sMeta )
+ {
+ mpMetadataAuthor->SetText(sMeta);
+ }
+
+ Date aDate = GetDate();
+ if (aDate.IsValidAndGregorian() )
+ {
+ sMeta = rLocalData.getDate(aDate);
+ }
+ else
+ {
+ sMeta = SwResId(STR_NODATE);
+ }
+ if (GetTime().GetTime()!=0)
+ {
+ sMeta += " " + rLocalData.getTime( GetTime(),false );
+ }
+ if ( mpMetadataDate->GetText() != sMeta )
+ {
+ mpMetadataDate->SetText(sMeta);
+ }
+}
+
+void SwAnnotationWin::Rescale()
+{
+ // On Android, this method leads to invoke ImpEditEngine::UpdateViews
+ // which hides the text cursor. Moreover it causes sudden document scroll
+ // when modifying a commented text. Not clear the root cause,
+ // anyway skipping this method fixes the problem, and there should be
+ // no side effect, since the client has disabled annotations rendering.
+ if (comphelper::LibreOfficeKit::isActive() && !comphelper::LibreOfficeKit::isTiledAnnotations())
+ return;
+
+ MapMode aMode = GetParent()->GetMapMode();
+ aMode.SetOrigin( Point() );
+ mpOutliner->SetRefMapMode( aMode );
+ SetMapMode( aMode );
+ mpSidebarTextControl->SetMapMode( aMode );
+ const Fraction& rFraction = mrView.GetWrtShellPtr()->GetOut()->GetMapMode().GetScaleY();
+ if ( mpMetadataAuthor )
+ {
+ vcl::Font aFont( mpMetadataAuthor->GetSettings().GetStyleSettings().GetFieldFont() );
+ sal_Int32 nHeight = long(aFont.GetFontHeight() * rFraction);
+ aFont.SetFontHeight( nHeight );
+ mpMetadataAuthor->SetControlFont( aFont );
+ }
+ if ( mpMetadataDate )
+ {
+ vcl::Font aFont( mpMetadataDate->GetSettings().GetStyleSettings().GetFieldFont() );
+ sal_Int32 nHeight = long(aFont.GetFontHeight() * rFraction);
+ aFont.SetFontHeight( nHeight );
+ mpMetadataDate->SetControlFont( aFont );
+ }
+ if ( mpMetadataResolved )
+ {
+ vcl::Font aFont( mpMetadataResolved->GetSettings().GetStyleSettings().GetFieldFont() );
+ sal_Int32 nHeight = long(aFont.GetFontHeight() * rFraction);
+ aFont.SetFontHeight( nHeight );
+ mpMetadataResolved->SetControlFont( aFont );
+ }
+}
+
+void SwAnnotationWin::SetPosAndSize()
+{
+ bool bChange = false;
+
+ if (GetSizePixel() != mPosSize.GetSize())
+ {
+ bChange = true;
+ SetSizePixel(mPosSize.GetSize());
+
+ if (comphelper::LibreOfficeKit::isActive())
+ {
+ // Position is not yet set at VCL level, but the map mode should
+ // contain the right origin to emit the correct cursor position.
+ mpSidebarTextControl->Push(PushFlags::MAPMODE);
+ Point aOffset(mPosSize.Left(), mPosSize.Top());
+ aOffset = PixelToLogic(aOffset);
+ MapMode aMapMode(mpSidebarTextControl->GetMapMode());
+ aMapMode.SetOrigin(aOffset);
+ mpSidebarTextControl->SetMapMode(aMapMode);
+ mpSidebarTextControl->EnableMapMode(false);
+ }
+
+ DoResize();
+
+ if (comphelper::LibreOfficeKit::isActive())
+ mpSidebarTextControl->Pop();
+ }
+
+ if (GetPosPixel().X() != mPosSize.TopLeft().X() || (std::abs(GetPosPixel().Y() - mPosSize.TopLeft().Y()) > 5) )
+ {
+ bChange = true;
+ SetPosPixel(mPosSize.TopLeft());
+
+ Point aLineStart;
+ Point aLineEnd ;
+ switch ( meSidebarPosition )
+ {
+ case sw::sidebarwindows::SidebarPosition::LEFT:
+ {
+ aLineStart = EditWin().PixelToLogic( Point(GetPosPixel().X()+GetSizePixel().Width(),GetPosPixel().Y()-1) );
+ aLineEnd = EditWin().PixelToLogic( Point(GetPosPixel().X(),GetPosPixel().Y()-1) );
+ }
+ break;
+ case sw::sidebarwindows::SidebarPosition::RIGHT:
+ {
+ aLineStart = EditWin().PixelToLogic( Point(GetPosPixel().X(),GetPosPixel().Y()-1) );
+ aLineEnd = EditWin().PixelToLogic( Point(GetPosPixel().X()+GetSizePixel().Width(),GetPosPixel().Y()-1) );
+ }
+ break;
+ default:
+ OSL_FAIL( "<SwAnnotationWin::SetPosAndSize()> - unexpected position of sidebar" );
+ break;
+ }
+
+ // LOK has map mode disabled, and we still want to perform pixel ->
+ // twips conversion for the size of the line above the note.
+ if (comphelper::LibreOfficeKit::isActive() && !EditWin().IsMapModeEnabled())
+ {
+ EditWin().EnableMapMode();
+ Size aSize(aLineEnd.getX() - aLineStart.getX(), aLineEnd.getY() - aLineStart.getY());
+ aSize = EditWin().PixelToLogic(aSize);
+ aLineEnd = aLineStart;
+ aLineEnd.Move(aSize.getWidth(), aSize.getHeight());
+ EditWin().EnableMapMode(false);
+ }
+
+ if (mpAnchor)
+ {
+ mpAnchor->SetAllPosition( basegfx::B2DPoint( mAnchorRect.Left() , mAnchorRect.Bottom() - 5* 15),
+ basegfx::B2DPoint( mAnchorRect.Left()-5*15 , mAnchorRect.Bottom()+5*15),
+ basegfx::B2DPoint( mAnchorRect.Left()+5*15 , mAnchorRect.Bottom()+5*15),
+ basegfx::B2DPoint( mAnchorRect.Left(), mAnchorRect.Bottom()+2*15),
+ basegfx::B2DPoint( mPageBorder ,mAnchorRect.Bottom()+2*15),
+ basegfx::B2DPoint( aLineStart.X(),aLineStart.Y()),
+ basegfx::B2DPoint( aLineEnd.X(),aLineEnd.Y()));
+ }
+ else
+ {
+ mpAnchor = AnchorOverlayObject::CreateAnchorOverlayObject( mrView,
+ mAnchorRect,
+ mPageBorder,
+ aLineStart,
+ aLineEnd,
+ mColorAnchor );
+ if ( mpAnchor )
+ {
+ mpAnchor->setVisible(true);
+ mpAnchor->SetAnchorState(AnchorState::Tri);
+ if (HasChildPathFocus())
+ {
+ mpAnchor->setLineSolid(true);
+ }
+ }
+ }
+ }
+ else
+ {
+ if ( mpAnchor &&
+ ( mpAnchor->getBasePosition() != basegfx::B2DPoint( mAnchorRect.Left() , mAnchorRect.Bottom()-5*15) ) )
+ {
+ mpAnchor->SetTriPosition( basegfx::B2DPoint( mAnchorRect.Left() , mAnchorRect.Bottom() - 5* 15),
+ basegfx::B2DPoint( mAnchorRect.Left()-5*15 , mAnchorRect.Bottom()+5*15),
+ basegfx::B2DPoint( mAnchorRect.Left()+5*15 , mAnchorRect.Bottom()+5*15),
+ basegfx::B2DPoint( mAnchorRect.Left(), mAnchorRect.Bottom()+2*15),
+ basegfx::B2DPoint( mPageBorder , mAnchorRect.Bottom()+2*15));
+ }
+ }
+
+ if (mpShadow && bChange)
+ {
+ Point aStart = EditWin().PixelToLogic(GetPosPixel()+Point(0,GetSizePixel().Height()));
+ Point aEnd = EditWin().PixelToLogic(GetPosPixel()+Point(GetSizePixel().Width()-1,GetSizePixel().Height()));
+ mpShadow->SetPosition(basegfx::B2DPoint(aStart.X(),aStart.Y()), basegfx::B2DPoint(aEnd.X(),aEnd.Y()));
+ }
+
+ if (mrMgr.ShowNotes())
+ {
+ if (IsFollow() && !HasChildPathFocus())
+ {
+ // #i111964#
+ if ( mpAnchor )
+ {
+ mpAnchor->SetAnchorState(AnchorState::End);
+ }
+ }
+ else
+ {
+ // #i111964#
+ if ( mpAnchor )
+ {
+ mpAnchor->SetAnchorState(AnchorState::All);
+ }
+ SwAnnotationWin* pWin = GetTopReplyNote();
+ // #i111964#
+ if ( pWin != this && pWin->Anchor() )
+ {
+ pWin->Anchor()->SetAnchorState(AnchorState::End);
+ }
+ }
+ }
+
+
+ // text range overlay
+ maAnnotationTextRanges.clear();
+ if ( mrSidebarItem.maLayoutInfo.mnStartNodeIdx != 0
+ && mrSidebarItem.maLayoutInfo.mnStartContent != -1 )
+ {
+ const SwTextAnnotationField* pTextAnnotationField =
+ dynamic_cast< const SwTextAnnotationField* >( mrSidebarItem.GetFormatField().GetTextField() );
+ SwTextNode* pTextNode = pTextAnnotationField ? pTextAnnotationField->GetpTextNode() : nullptr;
+ SwContentNode* pContentNd = nullptr;
+ if (pTextNode)
+ {
+ SwNodes& rNds = pTextNode->GetDoc()->GetNodes();
+ pContentNd = rNds[mrSidebarItem.maLayoutInfo.mnStartNodeIdx]->GetContentNode();
+ }
+ if (pContentNd)
+ {
+ SwPosition aStartPos( *pContentNd, mrSidebarItem.maLayoutInfo.mnStartContent );
+ SwShellCursor* pTmpCursor = nullptr;
+ const bool bTableCursorNeeded = pTextNode->FindTableBoxStartNode() != pContentNd->FindTableBoxStartNode();
+ if ( bTableCursorNeeded )
+ {
+ SwShellTableCursor* pTableCursor = new SwShellTableCursor( mrView.GetWrtShell(), aStartPos );
+ pTableCursor->SetMark();
+ pTableCursor->GetMark()->nNode = *pTextNode;
+ pTableCursor->GetMark()->nContent.Assign( pTextNode, pTextAnnotationField->GetStart()+1 );
+ pTableCursor->NewTableSelection();
+ pTmpCursor = pTableCursor;
+ }
+ else
+ {
+ SwShellCursor* pCursor = new SwShellCursor( mrView.GetWrtShell(), aStartPos );
+ pCursor->SetMark();
+ pCursor->GetMark()->nNode = *pTextNode;
+ pCursor->GetMark()->nContent.Assign( pTextNode, pTextAnnotationField->GetStart()+1 );
+ pTmpCursor = pCursor;
+ }
+ std::unique_ptr<SwShellCursor> pTmpCursorForAnnotationTextRange( pTmpCursor );
+
+ // For annotation text range rectangles to be calculated correctly,
+ // we need the map mode disabled
+ bool bDisableMapMode = comphelper::LibreOfficeKit::isActive() && EditWin().IsMapModeEnabled();
+ if (bDisableMapMode)
+ EditWin().EnableMapMode(false);
+
+ if (mrSidebarItem.maLayoutInfo.mPositionFromCommentAnchor)
+ pTmpCursorForAnnotationTextRange->FillRects();
+
+ if (bDisableMapMode)
+ EditWin().EnableMapMode();
+
+ SwRects* pRects(pTmpCursorForAnnotationTextRange.get());
+ for(const SwRect & rNextRect : *pRects)
+ {
+ const tools::Rectangle aPntRect(rNextRect.SVRect());
+ maAnnotationTextRanges.emplace_back(
+ aPntRect.Left(), aPntRect.Top(),
+ aPntRect.Right() + 1, aPntRect.Bottom() + 1);
+ }
+ }
+ }
+
+ if (mrMgr.ShowNotes() && !maAnnotationTextRanges.empty())
+ {
+ if ( mpTextRangeOverlay != nullptr )
+ {
+ mpTextRangeOverlay->setRanges( maAnnotationTextRanges );
+ if ( mpAnchor != nullptr && mpAnchor->getLineSolid() )
+ {
+ mpTextRangeOverlay->ShowSolidBorder();
+ }
+ else
+ {
+ mpTextRangeOverlay->HideSolidBorder();
+ }
+ }
+ else if (!IsFollow())
+ {
+ // This window is not a reply, then draw its range overlay.
+ mpTextRangeOverlay =
+ sw::overlay::OverlayRanges::CreateOverlayRange(
+ mrView,
+ mColorAnchor,
+ maAnnotationTextRanges,
+ mpAnchor && mpAnchor->getLineSolid() );
+ }
+ }
+ else
+ {
+ mpTextRangeOverlay.reset();
+ }
+}
+
+void SwAnnotationWin::DoResize()
+{
+ long aTextHeight = LogicToPixel( mpOutliner->CalcTextSize()).Height();
+ long aHeight = GetSizePixel().Height();
+ unsigned long aWidth = GetSizePixel().Width();
+
+ aHeight -= GetMetaHeight();
+ mpMetadataAuthor->Show();
+ if(IsThreadResolved()) { mpMetadataResolved->Show(); }
+ mpMetadataDate->Show();
+ mpSidebarTextControl->SetQuickHelpText(OUString());
+ unsigned int numFields = GetNumFields();
+ if (aTextHeight > aHeight)
+ { // we need vertical scrollbars and have to reduce the width
+ aWidth -= GetScrollbarWidth();
+ mpVScrollbar->Show();
+ }
+ else
+ {
+ mpVScrollbar->Hide();
+ }
+
+ {
+ const Size aSizeOfMetadataControls( GetSizePixel().Width() - GetMetaButtonAreaWidth(),
+ GetMetaHeight()/numFields );
+ mpMetadataAuthor->setPosSizePixel( 0,
+ aHeight,
+ aSizeOfMetadataControls.Width(),
+ aSizeOfMetadataControls.Height() );
+ mpMetadataDate->setPosSizePixel( 0,
+ aHeight + aSizeOfMetadataControls.Height(),
+ aSizeOfMetadataControls.Width(),
+ aSizeOfMetadataControls.Height() );
+ if(IsThreadResolved()) {
+ mpMetadataResolved->setPosSizePixel( 0,
+ aHeight + aSizeOfMetadataControls.Height()*2,
+ aSizeOfMetadataControls.Width(),
+ aSizeOfMetadataControls.Height() );
+ }
+ }
+
+ mpOutliner->SetPaperSize( PixelToLogic( Size(aWidth,aHeight) ) ) ;
+ if (!mpVScrollbar->IsVisible())
+ { // if we do not have a scrollbar anymore, we want to see the complete text
+ mpOutlinerView->SetVisArea( PixelToLogic( tools::Rectangle(0,0,aWidth,aHeight) ) );
+ }
+ mpOutlinerView->SetOutputArea( PixelToLogic( tools::Rectangle(0,0,aWidth,aHeight) ) );
+
+ if (!AllSettings::GetLayoutRTL())
+ {
+ mpSidebarTextControl->setPosSizePixel(0, 0, aWidth, aHeight);
+ mpVScrollbar->setPosSizePixel( aWidth, 0, GetScrollbarWidth(), aHeight);
+ }
+ else
+ {
+ mpSidebarTextControl->setPosSizePixel( ( aTextHeight > aHeight ? GetScrollbarWidth() : 0 ), 0,
+ aWidth, aHeight);
+ mpVScrollbar->setPosSizePixel( 0, 0, GetScrollbarWidth(), aHeight);
+ }
+
+ mpVScrollbar->SetVisibleSize( PixelToLogic(Size(0,aHeight)).Height() );
+ mpVScrollbar->SetPageSize( PixelToLogic(Size(0,aHeight)).Height() * 8 / 10 );
+ mpVScrollbar->SetLineSize( mpOutliner->GetTextHeight() / 10 );
+ SetScrollbar();
+ mpVScrollbar->SetRange( Range(0, mpOutliner->GetTextHeight()));
+
+ //calculate rects for meta- button
+ const Fraction& fx( GetMapMode().GetScaleX() );
+ const Fraction& fy( GetMapMode().GetScaleY() );
+
+ const Point aPos( mpMetadataAuthor->GetPosPixel());
+ mpMenuButton->setPosSizePixel( long(aPos.X()+GetSizePixel().Width()-(METABUTTON_WIDTH+10)*fx),
+ long(aPos.Y()+5*fy),
+ long(METABUTTON_WIDTH*fx),
+ long(METABUTTON_HEIGHT*fy) );
+}
+
+void SwAnnotationWin::SetSizePixel( const Size& rNewSize )
+{
+ Window::SetSizePixel(rNewSize);
+
+ if (mpShadow)
+ {
+ Point aStart = EditWin().PixelToLogic(GetPosPixel()+Point(0,GetSizePixel().Height()));
+ Point aEnd = EditWin().PixelToLogic(GetPosPixel()+Point(GetSizePixel().Width()-1,GetSizePixel().Height()));
+ mpShadow->SetPosition(basegfx::B2DPoint(aStart.X(),aStart.Y()), basegfx::B2DPoint(aEnd.X(),aEnd.Y()));
+ }
+}
+
+void SwAnnotationWin::SetScrollbar()
+{
+ mpVScrollbar->SetThumbPos(mpOutlinerView->GetVisArea().Top());
+}
+
+void SwAnnotationWin::ResizeIfNecessary(long aOldHeight, long aNewHeight)
+{
+ if (aOldHeight != aNewHeight)
+ {
+ //check for lower border or next note
+ long aBorder = mrMgr.GetNextBorder();
+ if (aBorder != -1)
+ {
+ if (aNewHeight > GetMinimumSizeWithoutMeta())
+ {
+ long aNewLowerValue = GetPosPixel().Y() + aNewHeight + GetMetaHeight();
+ if (aNewLowerValue < aBorder)
+ SetSizePixel(Size(GetSizePixel().Width(),aNewHeight+GetMetaHeight()));
+ else
+ SetSizePixel(Size(GetSizePixel().Width(),aBorder - GetPosPixel().Y()));
+ DoResize();
+ Invalidate();
+ }
+ else
+ {
+ if (GetSizePixel().Height() != GetMinimumSizeWithoutMeta() + GetMetaHeight())
+ SetSizePixel(Size(GetSizePixel().Width(),GetMinimumSizeWithoutMeta() + GetMetaHeight()));
+ DoResize();
+ Invalidate();
+ }
+ }
+ else
+ {
+ DoResize();
+ Invalidate();
+ }
+ }
+ else
+ {
+ SetScrollbar();
+ }
+}
+
+void SwAnnotationWin::SetColor(Color aColorDark,Color aColorLight, Color aColorAnchor)
+{
+ mColorDark = aColorDark;
+ mColorLight = aColorLight;
+ mColorAnchor = aColorAnchor;
+
+ if ( !Application::GetSettings().GetStyleSettings().GetHighContrastMode() )
+ {
+ {
+ mpMetadataAuthor->SetControlBackground(mColorDark);
+ AllSettings aSettings = mpMetadataAuthor->GetSettings();
+ StyleSettings aStyleSettings = aSettings.GetStyleSettings();
+ aStyleSettings.SetFieldTextColor(aColorAnchor);
+ aSettings.SetStyleSettings(aStyleSettings);
+ mpMetadataAuthor->SetSettings(aSettings);
+ }
+
+ {
+ mpMetadataDate->SetControlBackground(mColorDark);
+ AllSettings aSettings = mpMetadataDate->GetSettings();
+ StyleSettings aStyleSettings = aSettings.GetStyleSettings();
+ aStyleSettings.SetFieldTextColor(aColorAnchor);
+ aSettings.SetStyleSettings(aStyleSettings);
+ mpMetadataDate->SetSettings(aSettings);
+ }
+
+ {
+ mpMetadataResolved->SetControlBackground(mColorDark);
+ AllSettings aSettings = mpMetadataResolved->GetSettings();
+ StyleSettings aStyleSettings = aSettings.GetStyleSettings();
+ aStyleSettings.SetFieldTextColor(aColorAnchor);
+ aSettings.SetStyleSettings(aStyleSettings);
+ mpMetadataResolved->SetSettings(aSettings);
+ }
+
+ AllSettings aSettings2 = mpVScrollbar->GetSettings();
+ StyleSettings aStyleSettings2 = aSettings2.GetStyleSettings();
+ aStyleSettings2.SetButtonTextColor(Color(0,0,0));
+ aStyleSettings2.SetCheckedColor(mColorLight); // background
+ aStyleSettings2.SetShadowColor(mColorAnchor);
+ aStyleSettings2.SetFaceColor(mColorDark);
+ aSettings2.SetStyleSettings(aStyleSettings2);
+ mpVScrollbar->SetSettings(aSettings2);
+ }
+}
+
+void SwAnnotationWin::SetSidebarPosition(sw::sidebarwindows::SidebarPosition eSidebarPosition)
+{
+ meSidebarPosition = eSidebarPosition;
+}
+
+void SwAnnotationWin::SetReadonly(bool bSet)
+{
+ mbReadonly = bSet;
+ GetOutlinerView()->SetReadOnly(bSet);
+}
+
+void SwAnnotationWin::SetLanguage(const SvxLanguageItem& rNewItem)
+{
+ IDocumentUndoRedo& rUndoRedo(
+ mrView.GetDocShell()->GetDoc()->GetIDocumentUndoRedo());
+ const bool bDocUndoEnabled = rUndoRedo.DoesUndo();
+ const bool bOutlinerUndoEnabled = mpOutliner->IsUndoEnabled();
+ const bool bOutlinerModified = mpOutliner->IsModified();
+ const bool bDisableAndRestoreUndoMode = !bDocUndoEnabled && bOutlinerUndoEnabled;
+
+ if (bDisableAndRestoreUndoMode)
+ {
+ // doc undo is disabled, but outliner was enabled, turn outliner undo off
+ // for the duration of this function
+ mpOutliner->EnableUndo(false);
+ }
+
+ Link<LinkParamNone*,void> aLink = mpOutliner->GetModifyHdl();
+ mpOutliner->SetModifyHdl( Link<LinkParamNone*,void>() );
+ ESelection aOld = GetOutlinerView()->GetSelection();
+
+ ESelection aNewSelection( 0, 0, mpOutliner->GetParagraphCount()-1, EE_TEXTPOS_ALL );
+ GetOutlinerView()->SetSelection( aNewSelection );
+ SfxItemSet aEditAttr(GetOutlinerView()->GetAttribs());
+ aEditAttr.Put(rNewItem);
+ GetOutlinerView()->SetAttribs( aEditAttr );
+
+ if (!mpOutliner->IsUndoEnabled() && !bOutlinerModified)
+ {
+ // if undo was disabled (e.g. this is a redo action) and we were
+ // originally 'unmodified' keep it that way
+ mpOutliner->ClearModifyFlag();
+ }
+
+ GetOutlinerView()->SetSelection(aOld);
+ mpOutliner->SetModifyHdl( aLink );
+
+ const SwViewOption* pVOpt = mrView.GetWrtShellPtr()->GetViewOptions();
+ EEControlBits nCntrl = mpOutliner->GetControlWord();
+ // turn off
+ nCntrl &= ~EEControlBits::ONLINESPELLING;
+ mpOutliner->SetControlWord(nCntrl);
+
+ //turn back on
+ if (pVOpt->IsOnlineSpell())
+ nCntrl |= EEControlBits::ONLINESPELLING;
+ else
+ nCntrl &= ~EEControlBits::ONLINESPELLING;
+ mpOutliner->SetControlWord(nCntrl);
+
+ mpOutliner->CompleteOnlineSpelling();
+
+ // restore original mode
+ if (bDisableAndRestoreUndoMode)
+ mpOutliner->EnableUndo(true);
+
+ Invalidate();
+}
+
+void SwAnnotationWin::GetFocus()
+{
+ if (mpSidebarTextControl)
+ mpSidebarTextControl->GrabFocus();
+}
+
+void SwAnnotationWin::LoseFocus()
+{
+}
+
+void SwAnnotationWin::ShowNote()
+{
+ SetPosAndSize();
+ if (!IsVisible())
+ Window::Show();
+ if (mpShadow && !mpShadow->isVisible())
+ mpShadow->setVisible(true);
+ if (mpAnchor && !mpAnchor->isVisible())
+ mpAnchor->setVisible(true);
+
+ // Invalidate.
+ InvalidateControl();
+}
+
+void SwAnnotationWin::HideNote()
+{
+ if (IsVisible())
+ Window::Hide();
+ if (mpAnchor)
+ {
+ if (mrMgr.IsShowAnchor())
+ mpAnchor->SetAnchorState(AnchorState::Tri);
+ else
+ mpAnchor->setVisible(false);
+ }
+ if (mpShadow && mpShadow->isVisible())
+ mpShadow->setVisible(false);
+}
+
+void SwAnnotationWin::InvalidateControl()
+{
+ // Invalidate.
+ mpSidebarTextControl->Push(PushFlags::MAPMODE);
+ lcl_translateTwips(EditWin(), *mpSidebarTextControl, nullptr);
+ mpSidebarTextControl->Invalidate();
+ mpSidebarTextControl->Pop();
+}
+
+void SwAnnotationWin::ActivatePostIt()
+{
+ mrMgr.AssureStdModeAtShell();
+
+ mpOutliner->ClearModifyFlag();
+ mpOutliner->GetUndoManager().Clear();
+
+ CheckMetaText();
+ SetViewState(ViewState::EDIT);
+ GetOutlinerView()->ShowCursor();
+
+ mpOutlinerView->GetEditView().SetInsertMode(mrView.GetWrtShellPtr()->IsInsMode());
+
+ if ( !Application::GetSettings().GetStyleSettings().GetHighContrastMode() )
+ GetOutlinerView()->SetBackgroundColor(mColorDark);
+
+ //tdf#119130 only have the active postit as a dialog control in which pressing
+ //ctrl+tab cycles between text and button so we don't waste time searching
+ //thousands of SwAnnotationWins
+ SetStyle(GetStyle() | WB_DIALOGCONTROL);
+}
+
+void SwAnnotationWin::DeactivatePostIt()
+{
+ //tdf#119130 only have the active postit as a dialog control in which pressing
+ //ctrl+tab cycles between text and button so we don't waste time searching
+ //thousands of SwAnnotationWins
+ SetStyle(GetStyle() & ~WB_DIALOGCONTROL);
+
+ // remove selection, #i87073#
+ if (GetOutlinerView()->GetEditView().HasSelection())
+ {
+ ESelection aSelection = GetOutlinerView()->GetEditView().GetSelection();
+ aSelection.nEndPara = aSelection.nStartPara;
+ aSelection.nEndPos = aSelection.nStartPos;
+ GetOutlinerView()->GetEditView().SetSelection(aSelection);
+ }
+
+ mpOutliner->CompleteOnlineSpelling();
+
+ SetViewState(ViewState::NORMAL);
+ // Make sure this view doesn't emit LOK callbacks during the update, as the
+ // sidebar window's SidebarTextControl doesn't have a valid twip offset
+ // (map mode origin) during that operation.
+ bool bTiledPainting = comphelper::LibreOfficeKit::isTiledPainting();
+ comphelper::LibreOfficeKit::setTiledPainting(true);
+ // write the visible text back into the SwField
+ UpdateData();
+ comphelper::LibreOfficeKit::setTiledPainting(bTiledPainting);
+
+ if ( !Application::GetSettings().GetStyleSettings().GetHighContrastMode() )
+ GetOutlinerView()->SetBackgroundColor(COL_TRANSPARENT);
+
+ if ( !IsProtected() && mpOutliner->GetEditEngine().GetText().isEmpty() )
+ {
+ mnEventId = Application::PostUserEvent( LINK( this, SwAnnotationWin, DeleteHdl), nullptr, true );
+ }
+}
+
+void SwAnnotationWin::ToggleInsMode()
+{
+ if (!mrView.GetWrtShell().IsRedlineOn())
+ {
+ //change outliner
+ mpOutlinerView->GetEditView().SetInsertMode(!mpOutlinerView->GetEditView().IsInsertMode());
+ //change document
+ mrView.GetWrtShell().ToggleInsMode();
+ //update statusbar
+ SfxBindings &rBnd = mrView.GetViewFrame()->GetBindings();
+ rBnd.Invalidate(SID_ATTR_INSERT);
+ rBnd.Update(SID_ATTR_INSERT);
+ }
+}
+
+void SwAnnotationWin::ExecuteCommand(sal_uInt16 nSlot)
+{
+ mrMgr.AssureStdModeAtShell();
+
+ switch (nSlot)
+ {
+ case FN_POSTIT:
+ case FN_REPLY:
+ {
+ // if this note is empty, it will be deleted once losing the focus, so no reply, but only a new note
+ // will be created
+ if (!mpOutliner->GetEditEngine().GetText().isEmpty())
+ {
+ OutlinerParaObject* pPara = new OutlinerParaObject(*GetOutlinerView()->GetEditView().CreateTextObject());
+ mrMgr.RegisterAnswer(pPara);
+ }
+ if (mrMgr.HasActiveSidebarWin())
+ mrMgr.SetActiveSidebarWin(nullptr);
+ SwitchToFieldPos();
+ mrView.GetViewFrame()->GetDispatcher()->Execute(FN_POSTIT);
+ break;
+ }
+ case FN_DELETE_COMMENT:
+ //Delete(); // do not kill the parent of our open popup menu
+ mnEventId = Application::PostUserEvent( LINK( this, SwAnnotationWin, DeleteHdl), nullptr, true );
+ break;
+ case FN_RESOLVE_NOTE:
+ GetTopReplyNote()->ToggleResolved();
+ mrMgr.UpdateResolvedStatus(GetTopReplyNote());
+ DoResize();
+ Invalidate();
+ mrMgr.LayoutPostIts();
+ break;
+ case FN_FORMAT_ALL_NOTES:
+ case FN_DELETE_ALL_NOTES:
+ case FN_HIDE_ALL_NOTES:
+ // not possible as slot as this would require that "this" is the active postit
+ mrView.GetViewFrame()->GetBindings().Execute( nSlot, nullptr, SfxCallMode::ASYNCHRON );
+ break;
+ case FN_DELETE_NOTE_AUTHOR:
+ case FN_HIDE_NOTE_AUTHOR:
+ {
+ // not possible as slot as this would require that "this" is the active postit
+ SfxStringItem aItem( nSlot, GetAuthor() );
+ const SfxPoolItem* aItems[2];
+ aItems[0] = &aItem;
+ aItems[1] = nullptr;
+ mrView.GetViewFrame()->GetBindings().Execute( nSlot, aItems, SfxCallMode::ASYNCHRON );
+ }
+ break;
+ default:
+ mrView.GetViewFrame()->GetBindings().Execute( nSlot );
+ break;
+ }
+}
+
+SwEditWin& SwAnnotationWin::EditWin()
+{
+ return mrView.GetEditWin();
+}
+
+long SwAnnotationWin::GetPostItTextHeight()
+{
+ return mpOutliner ? LogicToPixel(mpOutliner->CalcTextSize()).Height() : 0;
+}
+
+void SwAnnotationWin::SwitchToPostIt(sal_uInt16 aDirection)
+{
+ SwAnnotationWin* pPostIt = mrMgr.GetNextPostIt(aDirection, this);
+ if (pPostIt)
+ pPostIt->GrabFocus();
+}
+
+IMPL_LINK( SwAnnotationWin, WindowEventListener, VclWindowEvent&, rEvent, void )
+{
+ if ( rEvent.GetId() == VclEventId::WindowMouseMove )
+ {
+ MouseEvent* pMouseEvt = static_cast<MouseEvent*>(rEvent.GetData());
+ if ( pMouseEvt->IsEnterWindow() )
+ {
+ mbMouseOver = true;
+ if ( !HasFocus() )
+ {
+ SetViewState(ViewState::VIEW);
+ Invalidate();
+ }
+ }
+ else if ( pMouseEvt->IsLeaveWindow())
+ {
+ mbMouseOver = false;
+ if ( !HasFocus() )
+ {
+ SetViewState(ViewState::NORMAL);
+ Invalidate();
+ }
+ }
+ }
+ else if ( rEvent.GetId() == VclEventId::WindowActivate &&
+ rEvent.GetWindow() == mpSidebarTextControl )
+ {
+ SetActiveSidebarWin();
+ mrMgr.MakeVisible( this );
+ }
+}
+
+bool SwAnnotationWin::SetActiveSidebarWin()
+{
+ if (mrMgr.GetActiveSidebarWin() == this)
+ return false;
+ const bool bLockView = mrView.GetWrtShell().IsViewLocked();
+ mrView.GetWrtShell().LockView( true );
+ mrMgr.SetActiveSidebarWin(this);
+ mrView.GetWrtShell().LockView( bLockView );
+ return true;
+}
+
+void SwAnnotationWin::UnsetActiveSidebarWin()
+{
+ if (mrMgr.GetActiveSidebarWin() != this)
+ return;
+ const bool bLockView = mrView.GetWrtShell().IsViewLocked();
+ mrView.GetWrtShell().LockView( true );
+ mrMgr.SetActiveSidebarWin(nullptr);
+ mrView.GetWrtShell().LockView( bLockView );
+}
+
+IMPL_LINK(SwAnnotationWin, ScrollHdl, ScrollBar*, pScroll, void)
+{
+ long nDiff = GetOutlinerView()->GetEditView().GetVisArea().Top() - pScroll->GetThumbPos();
+ GetOutlinerView()->Scroll( 0, nDiff );
+}
+
+IMPL_LINK_NOARG(SwAnnotationWin, ModifyHdl, LinkParamNone*, void)
+{
+ mrView.GetDocShell()->SetModified();
+}
+
+IMPL_LINK_NOARG(SwAnnotationWin, DeleteHdl, void*, void)
+{
+ mnEventId = nullptr;
+ Delete();
+}
+
+void SwAnnotationWin::ResetAttributes()
+{
+ mpOutlinerView->RemoveAttribsKeepLanguages(true);
+ mpOutliner->RemoveFields();
+ mpOutlinerView->SetAttribs(DefaultItem());
+}
+
+sal_Int32 SwAnnotationWin::GetScrollbarWidth() const
+{
+ return mrView.GetWrtShell().GetViewOptions()->GetZoom() / 10;
+}
+
+sal_Int32 SwAnnotationWin::GetMetaButtonAreaWidth() const
+{
+ const Fraction& f( GetMapMode().GetScaleX() );
+ return long(METABUTTON_AREA_WIDTH * f);
+}
+
+sal_Int32 SwAnnotationWin::GetMetaHeight()
+{
+ const Fraction& f(mrView.GetWrtShellPtr()->GetOut()->GetMapMode().GetScaleY());
+ const int fields = GetNumFields();
+ return long(fields*POSTIT_META_FIELD_HEIGHT*f);
+}
+
+sal_Int32 SwAnnotationWin::GetNumFields()
+{
+ return IsThreadResolved() ? 3 : 2;
+}
+
+sal_Int32 SwAnnotationWin::GetMinimumSizeWithMeta() const
+{
+ return mrMgr.GetMinimumSizeWithMeta();
+}
+
+sal_Int32 SwAnnotationWin::GetMinimumSizeWithoutMeta() const
+{
+ const Fraction& f(mrView.GetWrtShellPtr()->GetOut()->GetMapMode().GetScaleY());
+ return long(POSTIT_MINIMUMSIZE_WITHOUT_META * f);
+}
+
+void SwAnnotationWin::SetSpellChecking()
+{
+ const SwViewOption* pVOpt = mrView.GetWrtShellPtr()->GetViewOptions();
+ EEControlBits nCntrl = mpOutliner->GetControlWord();
+ if (pVOpt->IsOnlineSpell())
+ nCntrl |= EEControlBits::ONLINESPELLING;
+ else
+ nCntrl &= ~EEControlBits::ONLINESPELLING;
+ mpOutliner->SetControlWord(nCntrl);
+
+ mpOutliner->CompleteOnlineSpelling();
+ Invalidate();
+}
+
+void SwAnnotationWin::SetViewState(ViewState bViewState)
+{
+ switch (bViewState)
+ {
+ case ViewState::EDIT:
+ {
+ if (mpAnchor)
+ {
+ mpAnchor->SetAnchorState(AnchorState::All);
+ SwAnnotationWin* pWin = GetTopReplyNote();
+ // #i111964#
+ if ( pWin != this && pWin->Anchor() )
+ {
+ pWin->Anchor()->SetAnchorState(AnchorState::End);
+ }
+ mpAnchor->setLineSolid(true);
+ if ( mpTextRangeOverlay != nullptr )
+ {
+ mpTextRangeOverlay->ShowSolidBorder();
+ }
+ }
+ if (mpShadow)
+ mpShadow->SetShadowState(SS_EDIT);
+ break;
+ }
+ case ViewState::VIEW:
+ {
+ if (mpAnchor)
+ {
+ mpAnchor->setLineSolid(true);
+ if ( mpTextRangeOverlay != nullptr )
+ {
+ mpTextRangeOverlay->ShowSolidBorder();
+ }
+ }
+ if (mpShadow)
+ mpShadow->SetShadowState(SS_VIEW);
+ break;
+ }
+ case ViewState::NORMAL:
+ {
+ if (mpAnchor)
+ {
+ if (IsFollow())
+ {
+ // if there is no visible parent note, we want to see the complete anchor ??
+ //if (IsAnyStackParentVisible())
+ mpAnchor->SetAnchorState(AnchorState::End);
+ SwAnnotationWin* pTopWinSelf = GetTopReplyNote();
+ SwAnnotationWin* pTopWinActive = mrMgr.HasActiveSidebarWin()
+ ? mrMgr.GetActiveSidebarWin()->GetTopReplyNote()
+ : nullptr;
+ // #i111964#
+ if ( ( pTopWinSelf != this ) &&
+ ( pTopWinSelf != pTopWinActive ) &&
+ pTopWinSelf->Anchor() )
+ {
+ if ( pTopWinSelf != mrMgr.GetActiveSidebarWin() )
+ {
+ pTopWinSelf->Anchor()->setLineSolid(false);
+ if ( pTopWinSelf->TextRange() != nullptr )
+ {
+ pTopWinSelf->TextRange()->HideSolidBorder();
+ }
+ }
+ pTopWinSelf->Anchor()->SetAnchorState(AnchorState::All);
+ }
+ }
+ mpAnchor->setLineSolid(false);
+ if ( mpTextRangeOverlay != nullptr )
+ {
+ mpTextRangeOverlay->HideSolidBorder();
+ }
+ }
+ if ( mpShadow )
+ {
+ mpShadow->SetShadowState(SS_NORMAL);
+ }
+ break;
+ }
+ }
+}
+
+SwAnnotationWin* SwAnnotationWin::GetTopReplyNote()
+{
+ SwAnnotationWin* pTopNote = this;
+ SwAnnotationWin* pSidebarWin = IsFollow() ? mrMgr.GetNextPostIt(KEY_PAGEUP, this) : nullptr;
+ while (pSidebarWin)
+ {
+ pTopNote = pSidebarWin;
+ pSidebarWin = pSidebarWin->IsFollow() ? mrMgr.GetNextPostIt(KEY_PAGEUP, pSidebarWin) : nullptr;
+ }
+ return pTopNote;
+}
+
+void SwAnnotationWin::SwitchToFieldPos()
+{
+ if ( mrMgr.GetActiveSidebarWin() == this )
+ mrMgr.SetActiveSidebarWin(nullptr);
+ GotoPos();
+ sal_uInt32 aCount = MoveCaret();
+ if (aCount)
+ mrView.GetDocShell()->GetWrtShell()->SwCursorShell::Right(aCount, 0);
+ GrabFocusToDocument();
+}
+
+void SwAnnotationWin::SetChangeTracking( const SwPostItHelper::SwLayoutStatus aLayoutStatus,
+ const Color& aChangeColor )
+{
+ if ( (mLayoutStatus != aLayoutStatus) ||
+ (mChangeColor != aChangeColor) )
+ {
+ mLayoutStatus = aLayoutStatus;
+ mChangeColor = aChangeColor;
+ Invalidate();
+ }
+}
+
+bool SwAnnotationWin::HasScrollbar() const
+{
+ return mpVScrollbar != nullptr;
+}
+
+bool SwAnnotationWin::IsScrollbarVisible() const
+{
+ return HasScrollbar() && mpVScrollbar->IsVisible();
+}
+
+void SwAnnotationWin::ChangeSidebarItem( SwSidebarItem const & rSidebarItem )
+{
+ const bool bAnchorChanged = mpAnchorFrame != rSidebarItem.maLayoutInfo.mpAnchorFrame;
+ if ( bAnchorChanged )
+ {
+ mrMgr.DisconnectSidebarWinFromFrame( *mpAnchorFrame, *this );
+ }
+
+ mrSidebarItem = rSidebarItem;
+ mpAnchorFrame = mrSidebarItem.maLayoutInfo.mpAnchorFrame;
+
+ if ( GetWindowPeer() )
+ {
+ SidebarWinAccessible* pAcc =
+ static_cast<SidebarWinAccessible*>( GetWindowPeer() );
+ OSL_ENSURE( dynamic_cast<SidebarWinAccessible*>( GetWindowPeer() ),
+ "<SwAnnotationWin::ChangeSidebarItem(..)> - unexpected type of window peer -> crash possible!" );
+ pAcc->ChangeSidebarItem( mrSidebarItem );
+ }
+
+ if ( bAnchorChanged )
+ {
+ mrMgr.ConnectSidebarWinToFrame( *(mrSidebarItem.maLayoutInfo.mpAnchorFrame),
+ mrSidebarItem.GetFormatField(),
+ *this );
+ }
+}
+
+css::uno::Reference< css::accessibility::XAccessible > SwAnnotationWin::CreateAccessible()
+{
+ SidebarWinAccessible* pAcc( new SidebarWinAccessible( *this,
+ mrView.GetWrtShell(),
+ mrSidebarItem ) );
+ css::uno::Reference< css::awt::XWindowPeer > xWinPeer( pAcc );
+ SetWindowPeer( xWinPeer, pAcc );
+
+ css::uno::Reference< css::accessibility::XAccessible > xAcc( xWinPeer, css::uno::UNO_QUERY );
+ return xAcc;
+}
+
+} // eof of namespace sw::sidebarwindows
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */