/* -*- 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 #include #include "SidebarWinAcc.hxx" #include #include #include #include #include "SidebarTxtControl.hxx" #include "SidebarScrollBar.hxx" #include "AnchorOverlayObject.hxx" #include "ShadowOverlayObject.hxx" #include "OverlayRanges.hxx" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include 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 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 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::Create( *this, WB_NODIALOGCONTROL, mrView, mrMgr ); mpSidebarTextControl->SetPointer(PointerStyle::Text); // window controls for author and date mpMetadataAuthor = VclPtr::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::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::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::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( " - 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 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 aLink = mpOutliner->GetModifyHdl(); mpOutliner->SetModifyHdl( Link() ); 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(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( GetWindowPeer() ); OSL_ENSURE( dynamic_cast( GetWindowPeer() ), " - 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: */