/* -*- 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 #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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace { /// Translate absolute <-> relative twips: LOK wants absolute coordinates as output and gives absolute coordinates as input. void lcl_translateTwips(vcl::Window& 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(MAP_TWIP); 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::sidebarwindows::SwSidebarWin& 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()); 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 { namespace sidebarwindows { #define METABUTTON_WIDTH 16 #define METABUTTON_HEIGHT 18 #define METABUTTON_AREA_WIDTH 30 #define POSTIT_META_HEIGHT (sal_Int32) 30 #define POSTIT_MINIMUMSIZE_WITHOUT_META 50 SwSidebarWin::SwSidebarWin(SwEditWin& rEditWin, WinBits nBits, SwPostItMgr& aMgr, SwPostItBits aBits, SwSidebarItem& rSidebarItem) : Window(&rEditWin, nBits) , mrMgr(aMgr) , mrView(rEditWin.GetView()) , nFlags(aBits) , mnEventId(nullptr) , mpOutlinerView(nullptr) , mpOutliner(nullptr) , mpSidebarTextControl(nullptr) , mpVScrollbar(nullptr) , mpMetadataAuthor(nullptr) , mpMetadataDate(nullptr) , mpMenuButton(nullptr) , mpAnchor(nullptr) , mpShadow(nullptr) , mpTextRangeOverlay(nullptr) , mColorAnchor() , mColorDark() , mColorLight() , mChangeColor() , meSidebarPosition(sw::sidebarwindows::SidebarPosition::NONE) , mPosSize() , mAnchorRect() , mPageBorder(0) , mbMouseOver(false) , mLayoutStatus(SwPostItHelper::INVISIBLE) , mbReadonly(false) , mbIsFollow(false) , mrSidebarItem(rSidebarItem) , mpAnchorFrm(rSidebarItem.maLayoutInfo.mpAnchorFrm) { mpShadow = ShadowOverlayObject::CreateShadowOverlayObject( mrView ); if ( mpShadow ) { mpShadow->setVisible(false); } mrMgr.ConnectSidebarWinToFrm( *(mrSidebarItem.maLayoutInfo.mpAnchorFrm), mrSidebarItem.GetFormatField(), *this ); } SwSidebarWin::~SwSidebarWin() { disposeOnce(); } void SwSidebarWin::dispose() { if (IsDisposed()) return; mrMgr.DisconnectSidebarWinFromFrm( *(mrSidebarItem.maLayoutInfo.mpAnchorFrm), *this ); Disable(); if ( mpSidebarTextControl ) { if ( mpOutlinerView ) { mpOutlinerView->SetWindow( nullptr ); } } mpSidebarTextControl.disposeAndClear(); if ( mpOutlinerView ) { delete mpOutlinerView; mpOutlinerView = nullptr; } if (mpOutliner) { delete mpOutliner; mpOutliner = nullptr; } if (mpMetadataAuthor) { mpMetadataAuthor->RemoveEventListener( LINK( this, SwSidebarWin, WindowEventListener ) ); } mpMetadataAuthor.disposeAndClear(); if (mpMetadataDate) { mpMetadataDate->RemoveEventListener( LINK( this, SwSidebarWin, WindowEventListener ) ); } mpMetadataDate.disposeAndClear(); if (mpVScrollbar) { mpVScrollbar->RemoveEventListener( LINK( this, SwSidebarWin, WindowEventListener ) ); } mpVScrollbar.disposeAndClear(); RemoveEventListener( LINK( this, SwSidebarWin, WindowEventListener ) ); AnchorOverlayObject::DestroyAnchorOverlayObject( mpAnchor ); mpAnchor = nullptr; ShadowOverlayObject::DestroyShadowOverlayObject( mpShadow ); mpShadow = nullptr; delete mpTextRangeOverlay; mpTextRangeOverlay = nullptr; mpMenuButton.disposeAndClear(); if (mnEventId) Application::RemoveUserEvent( mnEventId ); vcl::Window::dispose(); } void SwSidebarWin::Paint(vcl::RenderContext& rRenderContext, const 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); } rRenderContext.SetLineColor(); Rectangle aRectangle(Point(mpMetadataAuthor->GetPosPixel().X() + mpMetadataAuthor->GetSizePixel().Width(), mpMetadataAuthor->GetPosPixel().Y()), Size(GetMetaButtonAreaWidth(), mpMetadataAuthor->GetSizePixel().Height() + mpMetadataDate->GetSizePixel().Height())); if (comphelper::LibreOfficeKit::isActive()) aRectangle = rRect; else aRectangle = PixelToLogic(aRectangle); rRenderContext.DrawRect(aRectangle); } } void SwSidebarWin::PaintTile(vcl::RenderContext& rRenderContext, const 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 SwSidebarWin::IsHitWindow(const Point& rPointLogic) { Rectangle aRectangleLogic(EditWin().PixelToLogic(GetPosPixel()), EditWin().PixelToLogic(GetSizePixel())); return aRectangleLogic.IsInside(rPointLogic); } void SwSidebarWin::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 SwSidebarWin::Draw(OutputDevice* pDev, const Point& rPt, const Size& rSz, DrawFlags nInFlags) { if (mpMetadataAuthor->IsVisible() ) { pDev->SetFillColor(mColorDark); pDev->SetLineColor(); pDev->DrawRect( Rectangle( rPt, rSz ) ); } if (mpMetadataAuthor->IsVisible()) { vcl::Font aOrigFont(mpMetadataAuthor->GetControlFont()); Size aSize(PixelToLogic(mpMetadataAuthor->GetSizePixel())); Point aPos(PixelToLogic(mpMetadataAuthor->GetPosPixel())); aPos += rPt; vcl::Font aFont( mpMetadataAuthor->GetSettings().GetStyleSettings().GetFieldFont() ); mpMetadataAuthor->SetControlFont( aFont ); mpMetadataAuthor->Draw(pDev, aPos, aSize, nInFlags); mpMetadataAuthor->SetControlFont( aOrigFont ); } if (mpMetadataDate->IsVisible()) { vcl::Font aOrigFont(mpMetadataDate->GetControlFont()); Size aSize(PixelToLogic(mpMetadataDate->GetSizePixel())); Point aPos(PixelToLogic(mpMetadataDate->GetPosPixel())); aPos += rPt; vcl::Font aFont( mpMetadataDate->GetSettings().GetStyleSettings().GetFieldFont() ); mpMetadataDate->SetControlFont( aFont ); mpMetadataDate->Draw(pDev, aPos, aSize, nInFlags); mpMetadataDate->SetControlFont( aOrigFont ); } mpSidebarTextControl->Draw(pDev, rPt, rSz, nInFlags); 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()) { vcl::Font aOrigFont(mpMetadataDate->GetControlFont()); Color aOrigBg( mpMetadataDate->GetControlBackground() ); OUString sOrigText(mpMetadataDate->GetText()); Size aSize(PixelToLogic(mpMenuButton->GetSizePixel())); Point aPos(PixelToLogic(mpMenuButton->GetPosPixel())); aPos += rPt; vcl::Font aFont( mpMetadataDate->GetSettings().GetStyleSettings().GetFieldFont() ); mpMetadataDate->SetControlFont( aFont ); mpMetadataDate->SetControlBackground( 0xFFFFFF ); mpMetadataDate->SetText("..."); mpMetadataDate->Draw(pDev, aPos, aSize, nInFlags); mpMetadataDate->SetText(sOrigText); mpMetadataDate->SetControlFont( aOrigFont ); mpMetadataDate->SetControlBackground( aOrigBg ); } } void SwSidebarWin::KeyInput(const KeyEvent& rKeyEvent) { if (mpSidebarTextControl) { mpSidebarTextControl->Push(PushFlags::MAPMODE); lcl_translateTwips(EditWin(), *mpSidebarTextControl, nullptr); mpSidebarTextControl->KeyInput(rKeyEvent); mpSidebarTextControl->Pop(); } } void SwSidebarWin::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 SwSidebarWin::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 SwSidebarWin::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 SwSidebarWin::SetPosSizePixelRect(long nX, long nY, long nWidth, long nHeight, const SwRect& aAnchorRect, const long aPageBorder) { mPosSize = Rectangle(Point(nX,nY),Size(nWidth,nHeight)); mAnchorRect = aAnchorRect; mPageBorder = aPageBorder; } void SwSidebarWin::SetSize( const Size& rNewSize ) { mPosSize.SetSize(rNewSize); } void SwSidebarWin::SetVirtualPosSize( const Point& aPoint, const Size& aSize) { mPosSize = Rectangle(aPoint,aSize); } void SwSidebarWin::TranslateTopPosition(const long aAmount) { mPosSize.Move(0,aAmount); } void SwSidebarWin::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(AS_ALL); mpAnchor->setVisible(true); } if (mpShadow) mpShadow->setVisible(false); } SfxItemSet SwSidebarWin::DefaultItem() { SfxItemSet aItem( mrView.GetDocShell()->GetPool() ); aItem.Put(SvxFontHeightItem(200,100,EE_CHAR_FONTHEIGHT)); return aItem; } void SwSidebarWin::InitControls() { AddEventListener( LINK( this, SwSidebarWin, WindowEventListener ) ); // actual window which holds the user text mpSidebarTextControl = VclPtr::Create( *this, WB_NODIALOGCONTROL, mrView, mrMgr ); mpSidebarTextControl->SetPointer(Pointer(PointerStyle::Text)); // window controls for author and date mpMetadataAuthor = VclPtr::Create( this, 0 ); mpMetadataAuthor->SetAccessibleName( SW_RES( STR_ACCESS_ANNOTATION_AUTHOR_NAME ) ); mpMetadataAuthor->EnableRTL(AllSettings::GetLayoutRTL()); mpMetadataAuthor->SetReadOnly(); mpMetadataAuthor->AlwaysDisableInput(true); mpMetadataAuthor->SetCallHandlersOnInputDisabled(true); mpMetadataAuthor->AddEventListener( LINK( this, SwSidebarWin, 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.SetHeight(8); aStyleSettings.SetFieldFont(aFont); aSettings.SetStyleSettings(aStyleSettings); mpMetadataAuthor->SetSettings(aSettings); } mpMetadataDate = VclPtr::Create( this, 0 ); mpMetadataDate->SetAccessibleName( SW_RES( STR_ACCESS_ANNOTATION_DATE_NAME ) ); mpMetadataDate->EnableRTL(AllSettings::GetLayoutRTL()); mpMetadataDate->SetReadOnly(); mpMetadataDate->AlwaysDisableInput(true); mpMetadataDate->SetCallHandlersOnInputDisabled(true); mpMetadataDate->AddEventListener( LINK( this, SwSidebarWin, 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.SetHeight(8); aStyleSettings.SetFieldFont(aFont); aSettings.SetStyleSettings(aStyleSettings); mpMetadataDate->SetSettings(aSettings); } SwDocShell* aShell = mrView.GetDocShell(); mpOutliner = new Outliner(&aShell->GetPool(),OUTLINERMODE_TEXTOBJECT); aShell->GetDoc()->SetCalcFieldValueHdl( mpOutliner ); mpOutliner->SetUpdateMode( true ); Rescale(); mpSidebarTextControl->EnableRTL( false ); mpOutlinerView = new OutlinerView ( mpOutliner, mpSidebarTextControl ); mpOutlinerView->SetBackgroundColor(COL_TRANSPARENT); mpOutliner->InsertView(mpOutlinerView ); mpOutlinerView->SetOutputArea( PixelToLogic( 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. SwDrawModel* pDrawModel = mrView.GetWrtShellPtr()->getIDocumentDrawModelAccess().GetDrawModel(); LibreOfficeKitCallback pCallback = nullptr; void* pData = nullptr; pDrawModel->getLibreOfficeKitCallback(pCallback, pData); mpOutlinerView->setTiledRendering(mrView.GetWrtShellPtr()->isTiledRendering()); mpOutlinerView->registerLibreOfficeKitCallback(pCallback, pData); } //create Scrollbars mpVScrollbar = VclPtr::Create(*this, WB_3DLOOK |WB_VSCROLL|WB_DRAG, mrView); mpVScrollbar->EnableNativeWidget(false); mpVScrollbar->EnableRTL( false ); mpVScrollbar->SetScrollHdl(LINK(this, SwSidebarWin, ScrollHdl)); mpVScrollbar->EnableDrag(); mpVScrollbar->AddEventListener( LINK( this, SwSidebarWin, 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); sal_uInt16 aIndex = SW_MOD()->InsertRedlineAuthor(GetAuthor()); SetColor( SwPostItMgr::GetColorDark(aIndex), SwPostItMgr::GetColorLight(aIndex), SwPostItMgr::GetColorAnchor(aIndex)); CheckMetaText(); mpMenuButton = CreateMenuButton(); SetLanguage(GetLanguage()); GetOutlinerView()->StartSpeller(); SetPostItText(); Engine()->CompleteOnlineSpelling(); mpSidebarTextControl->Show(); mpMetadataAuthor->Show(); mpMetadataDate->Show(); mpVScrollbar->Show(); } void SwSidebarWin::CheckMetaText() { const SvtSysLocale aSysLocale; const LocaleDataWrapper& rLocalData = aSysLocale.GetLocaleData(); OUString sMeta = GetAuthor(); if (sMeta.isEmpty()) { sMeta = SW_RESSTR(STR_NOAUTHOR); } else if (sMeta.getLength() > 23) { sMeta = sMeta.copy(0, 20) + "..."; } if ( mpMetadataAuthor->GetText() != sMeta ) { mpMetadataAuthor->SetText(sMeta); } Date aSysDate( Date::SYSTEM ); Date aDate = GetDate(); if (aDate==aSysDate) { sMeta = SW_RESSTR(STR_POSTIT_TODAY); } else if (aDate == Date(aSysDate-1)) { sMeta = SW_RESSTR(STR_POSTIT_YESTERDAY); } else if (aDate.IsValidAndGregorian() ) { sMeta = rLocalData.getDate(aDate); } else { sMeta = SW_RESSTR(STR_NODATE); } if (GetTime()!=0) { sMeta += " " + rLocalData.getTime( GetTime(),false ); } if ( mpMetadataDate->GetText() != sMeta ) { mpMetadataDate->SetText(sMeta); } } void SwSidebarWin::Rescale() { 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 = aFont.GetHeight(); nHeight = nHeight * rFraction.GetNumerator() / rFraction.GetDenominator(); aFont.SetHeight( nHeight ); mpMetadataAuthor->SetControlFont( aFont ); } if ( mpMetadataDate ) { vcl::Font aFont( mpMetadataDate->GetSettings().GetStyleSettings().GetFieldFont() ); sal_Int32 nHeight = aFont.GetHeight(); nHeight = nHeight * rFraction.GetNumerator() / rFraction.GetDenominator(); aFont.SetHeight( nHeight ); mpMetadataDate->SetControlFont( aFont ); } } void SwSidebarWin::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 (!IsPreview()) { 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())); mpAnchor->SetHeight(mAnchorRect.Height()); } else { mpAnchor = AnchorOverlayObject::CreateAnchorOverlayObject( mrView, mAnchorRect, mPageBorder, aLineStart, aLineEnd, mColorAnchor ); if ( mpAnchor ) { mpAnchor->SetHeight(mAnchorRect.Height()); mpAnchor->setVisible(true); mpAnchor->SetAnchorState(AS_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 (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(AS_END); } } else { // #i111964# if ( mpAnchor ) { mpAnchor->SetAnchorState(AS_ALL); } SwSidebarWin* pWin = GetTopReplyNote(); // #i111964# if ( pWin && pWin->Anchor() ) { pWin->Anchor()->SetAnchorState(AS_END); } } } // text range overlay if ( mrMgr.ShowNotes() && mrSidebarItem.maLayoutInfo.mnStartNodeIdx != 0 && mrSidebarItem.maLayoutInfo.mnStartContent != -1 ) { std::vector< basegfx::B2DRange > aAnnotationTextRanges; { const SwTextAnnotationField* pTextAnnotationField = dynamic_cast< const SwTextAnnotationField* >( mrSidebarItem.GetFormatField().GetTextField() ); if ( pTextAnnotationField != nullptr && pTextAnnotationField->GetpTextNode() != nullptr ) { SwTextNode* pTextNode = pTextAnnotationField->GetpTextNode(); SwNodes& rNds = pTextNode->GetDoc()->GetNodes(); SwContentNode* const pContentNd = rNds[mrSidebarItem.maLayoutInfo.mnStartNodeIdx]->GetContentNode(); SwPosition aStartPos( *pContentNd, mrSidebarItem.maLayoutInfo.mnStartContent ); SwShellCrsr* pTmpCrsr = nullptr; const bool bTableCrsrNeeded = pTextNode->FindTableBoxStartNode() != pContentNd->FindTableBoxStartNode(); if ( bTableCrsrNeeded ) { SwShellTableCrsr* pTableCrsr = new SwShellTableCrsr( DocView().GetWrtShell(), aStartPos ); pTableCrsr->SetMark(); pTableCrsr->GetMark()->nNode = *pTextNode; pTableCrsr->GetMark()->nContent.Assign( pTextNode, pTextAnnotationField->GetStart()+1 ); pTableCrsr->NewTableSelection(); pTmpCrsr = pTableCrsr; } else { SwShellCrsr* pCrsr = new SwShellCrsr( DocView().GetWrtShell(), aStartPos ); pCrsr->SetMark(); pCrsr->GetMark()->nNode = *pTextNode; pCrsr->GetMark()->nContent.Assign( pTextNode, pTextAnnotationField->GetStart()+1 ); pTmpCrsr = pCrsr; } std::unique_ptr pTmpCrsrForAnnotationTextRange( pTmpCrsr ); pTmpCrsrForAnnotationTextRange->FillRects(); SwRects* pRects(pTmpCrsrForAnnotationTextRange.get()); for( size_t a(0); a < pRects->size(); ++a ) { const SwRect aNextRect((*pRects)[a]); const Rectangle aPntRect(aNextRect.SVRect()); aAnnotationTextRanges.push_back(basegfx::B2DRange( aPntRect.Left(), aPntRect.Top(), aPntRect.Right() + 1, aPntRect.Bottom() + 1)); } } } if ( mpTextRangeOverlay != nullptr ) { mpTextRangeOverlay->setRanges( aAnnotationTextRanges ); 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( DocView(), mColorAnchor, aAnnotationTextRanges, mpAnchor && mpAnchor->getLineSolid() ); } } else { delete mpTextRangeOverlay; mpTextRangeOverlay = nullptr; } } void SwSidebarWin::DoResize() { long aTextHeight = LogicToPixel( mpOutliner->CalcTextSize()).Height(); long aHeight = GetSizePixel().Height(); unsigned long aWidth = GetSizePixel().Width(); aHeight -= GetMetaHeight(); mpMetadataAuthor->Show(); mpMetadataDate->Show(); mpSidebarTextControl->SetQuickHelpText(OUString()); if ((aTextHeight > aHeight) && !IsPreview()) { // we need vertical scrollbars and have to reduce the width aWidth -= GetScrollbarWidth(); mpVScrollbar->Show(); } else { mpVScrollbar->Hide(); } { const Size aSizeOfMetadataControls( GetSizePixel().Width() - GetMetaButtonAreaWidth(), GetMetaHeight()/2 ); mpMetadataAuthor->setPosSizePixel( 0, aHeight, aSizeOfMetadataControls.Width(), aSizeOfMetadataControls.Height() ); mpMetadataDate->setPosSizePixel( 0, aHeight + aSizeOfMetadataControls.Height(), 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( Rectangle(0,0,aWidth,aHeight) ) ); } mpOutlinerView->SetOutputArea( PixelToLogic( 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) && !IsPreview() ? 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()); Rectangle aRectMetaButton; if (IsPreview()) { aRectMetaButton = PixelToLogic( Rectangle( Point( aPos.X()+GetSizePixel().Width()-(METABUTTON_WIDTH*4+10)*fx.GetNumerator()/fx.GetDenominator(), aPos.Y()+5*fy.GetNumerator()/fy.GetDenominator() ), Size( METABUTTON_WIDTH*4*fx.GetNumerator()/fx.GetDenominator(), METABUTTON_HEIGHT*fy.GetNumerator()/fy.GetDenominator() ) ) ); } else { aRectMetaButton = PixelToLogic( Rectangle( Point( aPos.X()+GetSizePixel().Width()-(METABUTTON_WIDTH+10)*fx.GetNumerator()/fx.GetDenominator(), aPos.Y()+5*fy.GetNumerator()/fy.GetDenominator() ), Size( METABUTTON_WIDTH*fx.GetNumerator()/fx.GetDenominator(), METABUTTON_HEIGHT*fy.GetNumerator()/fy.GetDenominator() ) ) ); } { const Rectangle aRectMetaButtonPixel( LogicToPixel( aRectMetaButton ) ); mpMenuButton->setPosSizePixel( aRectMetaButtonPixel.Left(), aRectMetaButtonPixel.Top(), aRectMetaButtonPixel.GetWidth(), aRectMetaButtonPixel.GetHeight() ); } } void SwSidebarWin::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 SwSidebarWin::SetScrollbar() { mpVScrollbar->SetThumbPos(mpOutlinerView->GetVisArea().Top()); } void SwSidebarWin::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 SwSidebarWin::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); } 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 SwSidebarWin::SetSidebarPosition(sw::sidebarwindows::SidebarPosition eSidebarPosition) { meSidebarPosition = eSidebarPosition; } void SwSidebarWin::SetReadonly(bool bSet) { mbReadonly = bSet; GetOutlinerView()->SetReadOnly(bSet); } void SwSidebarWin::SetLanguage(const SvxLanguageItem& rNewItem) { Link pLink = Engine()->GetModifyHdl(); Engine()->SetModifyHdl( Link() ); ESelection aOld = GetOutlinerView()->GetSelection(); ESelection aNewSelection( 0, 0, Engine()->GetParagraphCount()-1, EE_TEXTPOS_ALL ); GetOutlinerView()->SetSelection( aNewSelection ); SfxItemSet aEditAttr(GetOutlinerView()->GetAttribs()); aEditAttr.Put(rNewItem); GetOutlinerView()->SetAttribs( aEditAttr ); GetOutlinerView()->SetSelection(aOld); Engine()->SetModifyHdl( pLink ); const SwViewOption* pVOpt = mrView.GetWrtShellPtr()->GetViewOptions(); EEControlBits nCntrl = Engine()->GetControlWord(); // turn off nCntrl &= ~EEControlBits::ONLINESPELLING; Engine()->SetControlWord(nCntrl); //turn back on if (pVOpt->IsOnlineSpell()) nCntrl |= EEControlBits::ONLINESPELLING; else nCntrl &= ~EEControlBits::ONLINESPELLING; Engine()->SetControlWord(nCntrl); Engine()->CompleteOnlineSpelling(); Invalidate(); } void SwSidebarWin::DataChanged( const DataChangedEvent& aEvent) { Window::DataChanged( aEvent ); } void SwSidebarWin::GetFocus() { if (mpSidebarTextControl) mpSidebarTextControl->GrabFocus(); } void SwSidebarWin::LoseFocus() { } void SwSidebarWin::ShowNote() { SetPosAndSize(); if (!IsVisible()) Window::Show(); if (mpShadow && !mpShadow->isVisible()) mpShadow->setVisible(true); if (mpAnchor && !mpAnchor->isVisible()) mpAnchor->setVisible(true); } void SwSidebarWin::HideNote() { if (IsVisible()) Window::Hide(); if (mpAnchor) { if (mrMgr.IsShowAnchor()) mpAnchor->SetAnchorState(AS_TRI); else mpAnchor->setVisible(false); } if (mpShadow && mpShadow->isVisible()) mpShadow->setVisible(false); } void SwSidebarWin::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); } void SwSidebarWin::DeactivatePostIt() { // 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); // write the visible text back into the SwField UpdateData(); if ( !Application::GetSettings().GetStyleSettings().GetHighContrastMode() ) GetOutlinerView()->SetBackgroundColor(COL_TRANSPARENT); if ( !IsProtected() && Engine()->GetEditEngine().GetText().isEmpty() ) { mnEventId = Application::PostUserEvent( LINK( this, SwSidebarWin, DeleteHdl), nullptr, true ); } } void SwSidebarWin::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 SwSidebarWin::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 (!Engine()->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, SwSidebarWin, DeleteHdl), nullptr, true ); 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, 0, 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, 0, SfxCallMode::ASYNCHRON ); } break; default: mrView.GetViewFrame()->GetBindings().Execute( nSlot ); break; } } SwEditWin& SwSidebarWin::EditWin() { return mrView.GetEditWin(); } long SwSidebarWin::GetPostItTextHeight() { return mpOutliner ? LogicToPixel(mpOutliner->CalcTextSize()).Height() : 0; } void SwSidebarWin::SwitchToPostIt(sal_uInt16 aDirection) { SwSidebarWin* pPostIt = mrMgr.GetNextPostIt(aDirection, this); if (pPostIt) pPostIt->GrabFocus(); } IMPL_LINK_TYPED( SwSidebarWin, WindowEventListener, VclWindowEvent&, rEvent, void ) { if ( rEvent.GetId() == VCLEVENT_WINDOW_MOUSEMOVE ) { MouseEvent* pMouseEvt = static_cast(rEvent.GetData()); if ( pMouseEvt->IsEnterWindow() ) { mbMouseOver = true; if ( !HasFocus() ) { SetViewState(ViewState::VIEW); Invalidate(); } } else if ( pMouseEvt->IsLeaveWindow()) { if (!IsPreview()) { mbMouseOver = false; if ( !HasFocus() ) { SetViewState(ViewState::NORMAL); Invalidate(); } } } } else if ( rEvent.GetId() == VCLEVENT_WINDOW_ACTIVATE && rEvent.GetWindow() == mpSidebarTextControl ) { const bool bLockView = mrView.GetWrtShell().IsViewLocked(); mrView.GetWrtShell().LockView( true ); if ( !IsPreview() ) { mrMgr.SetActiveSidebarWin( this ); } mrView.GetWrtShell().LockView( bLockView ); mrMgr.MakeVisible( this ); } } void SwSidebarWin::Delete() { if ( mrMgr.GetActiveSidebarWin() == this) { mrMgr.SetActiveSidebarWin(nullptr); // if the note is empty, the previous line will send a delete event, but we are already there if (mnEventId) { Application::RemoveUserEvent( mnEventId ); mnEventId = nullptr; } } } IMPL_LINK_TYPED(SwSidebarWin, ScrollHdl, ScrollBar*, pScroll, void) { long nDiff = GetOutlinerView()->GetEditView().GetVisArea().Top() - pScroll->GetThumbPos(); GetOutlinerView()->Scroll( 0, nDiff ); } IMPL_LINK_NOARG_TYPED(SwSidebarWin, ModifyHdl, LinkParamNone*, void) { mrView.GetDocShell()->SetModified(); } IMPL_LINK_NOARG_TYPED(SwSidebarWin, DeleteHdl, void*, void) { mnEventId = nullptr; Delete(); } void SwSidebarWin::ResetAttributes() { mpOutlinerView->RemoveAttribsKeepLanguages(true); mpOutliner->RemoveFields(true); mpOutlinerView->SetAttribs(DefaultItem()); } sal_Int32 SwSidebarWin::GetScrollbarWidth() { return mrView.GetWrtShell().GetViewOptions()->GetZoom() / 10; } sal_Int32 SwSidebarWin::GetMetaButtonAreaWidth() { const Fraction& f( GetMapMode().GetScaleX() ); if (IsPreview()) return 3 * METABUTTON_AREA_WIDTH * f.GetNumerator() / f.GetDenominator(); else return METABUTTON_AREA_WIDTH * f.GetNumerator() / f.GetDenominator(); } sal_Int32 SwSidebarWin::GetMetaHeight() { const Fraction& f(mrView.GetWrtShellPtr()->GetOut()->GetMapMode().GetScaleY()); return POSTIT_META_HEIGHT * f.GetNumerator() / f.GetDenominator(); } sal_Int32 SwSidebarWin::GetMinimumSizeWithMeta() { return mrMgr.GetMinimumSizeWithMeta(); } sal_Int32 SwSidebarWin::GetMinimumSizeWithoutMeta() { const Fraction& f(mrView.GetWrtShellPtr()->GetOut()->GetMapMode().GetScaleY()); return POSTIT_MINIMUMSIZE_WITHOUT_META * f.GetNumerator() / f.GetDenominator(); } void SwSidebarWin::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 SwSidebarWin::SetViewState(ViewState bViewState) { switch (bViewState) { case ViewState::EDIT: { if (mpAnchor) { mpAnchor->SetAnchorState(AS_ALL); SwSidebarWin* pWin = GetTopReplyNote(); // #i111964# if ( pWin && pWin->Anchor() ) { pWin->Anchor()->SetAnchorState(AS_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(AS_END); SwSidebarWin* pTopWinSelf = GetTopReplyNote(); SwSidebarWin* pTopWinActive = mrMgr.HasActiveSidebarWin() ? mrMgr.GetActiveSidebarWin()->GetTopReplyNote() : nullptr; // #i111964# if ( pTopWinSelf && ( pTopWinSelf != pTopWinActive ) && pTopWinSelf->Anchor() ) { if ( pTopWinSelf != mrMgr.GetActiveSidebarWin() ) { pTopWinSelf->Anchor()->setLineSolid(false); if ( pTopWinSelf->TextRange() != nullptr ) { pTopWinSelf->TextRange()->HideSolidBorder(); } } pTopWinSelf->Anchor()->SetAnchorState(AS_ALL); } } mpAnchor->setLineSolid(false); if ( mpTextRangeOverlay != nullptr ) { mpTextRangeOverlay->HideSolidBorder(); } } if ( mpShadow ) { mpShadow->SetShadowState(SS_NORMAL); } break; } } } SwSidebarWin* SwSidebarWin::GetTopReplyNote() { SwSidebarWin* pTopNote = nullptr; SwSidebarWin* pSidebarWin = IsFollow() ? mrMgr.GetNextPostIt(KEY_PAGEUP, this) : nullptr; while (pSidebarWin) { pTopNote = pSidebarWin; pSidebarWin = pSidebarWin->IsFollow() ? mrMgr.GetNextPostIt(KEY_PAGEUP, pSidebarWin) : nullptr; } return pTopNote; } void SwSidebarWin::SwitchToFieldPos() { if ( mrMgr.GetActiveSidebarWin() == this ) mrMgr.SetActiveSidebarWin(nullptr); GotoPos(); sal_uInt32 aCount = MoveCaret(); if (aCount) mrView.GetDocShell()->GetWrtShell()->SwCrsrShell::Right(aCount, 0); GrabFocusToDocument(); } SvxLanguageItem SwSidebarWin::GetLanguage() { return SvxLanguageItem(SwLangHelper::GetLanguage(mrView.GetWrtShell(),RES_CHRATR_LANGUAGE),RES_CHRATR_LANGUAGE); } void SwSidebarWin::SetChangeTracking( const SwPostItHelper::SwLayoutStatus aLayoutStatus, const Color& aChangeColor ) { if ( (mLayoutStatus != aLayoutStatus) || (mChangeColor != aChangeColor) ) { mLayoutStatus = aLayoutStatus; mChangeColor = aChangeColor; Invalidate(); } } bool SwSidebarWin::HasScrollbar() const { return mpVScrollbar != nullptr; } bool SwSidebarWin::IsScrollbarVisible() const { return HasScrollbar() && mpVScrollbar->IsVisible(); } void SwSidebarWin::ChangeSidebarItem( SwSidebarItem& rSidebarItem ) { const bool bAnchorChanged = mpAnchorFrm != rSidebarItem.maLayoutInfo.mpAnchorFrm; if ( bAnchorChanged ) { mrMgr.DisconnectSidebarWinFromFrm( *(mpAnchorFrm), *this ); } mrSidebarItem = rSidebarItem; mpAnchorFrm = mrSidebarItem.maLayoutInfo.mpAnchorFrm; 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.ConnectSidebarWinToFrm( *(mrSidebarItem.maLayoutInfo.mpAnchorFrm), mrSidebarItem.GetFormatField(), *this ); } } css::uno::Reference< css::accessibility::XAccessible > SwSidebarWin::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: */