diff options
Diffstat (limited to 'sw/source/uibase/docvw/SidebarTxtControl.cxx')
-rw-r--r-- | sw/source/uibase/docvw/SidebarTxtControl.cxx | 473 |
1 files changed, 473 insertions, 0 deletions
diff --git a/sw/source/uibase/docvw/SidebarTxtControl.cxx b/sw/source/uibase/docvw/SidebarTxtControl.cxx new file mode 100644 index 0000000000..281544a7af --- /dev/null +++ b/sw/source/uibase/docvw/SidebarTxtControl.cxx @@ -0,0 +1,473 @@ +/* -*- 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 <config_wasm_strip.h> + +#include "SidebarTxtControl.hxx" + +#include <docsh.hxx> +#include <doc.hxx> + +#include <PostItMgr.hxx> + +#include <cmdid.h> +#include <strings.hrc> + +#include <unotools/securityoptions.hxx> +#include <officecfg/Office/Common.hxx> + +#include <sfx2/viewfrm.hxx> +#include <sfx2/bindings.hxx> +#include <sfx2/dispatch.hxx> +#include <sfx2/sfxhelp.hxx> + +#include <vcl/commandevent.hxx> +#include <vcl/event.hxx> +#include <vcl/ptrstyle.hxx> +#include <vcl/svapp.hxx> +#include <vcl/weld.hxx> +#include <vcl/gradient.hxx> +#include <vcl/settings.hxx> + +#include <editeng/outliner.hxx> +#include <editeng/editeng.hxx> +#include <editeng/editview.hxx> +#include <editeng/flditem.hxx> + +#include <uitool.hxx> +#include <view.hxx> +#include <wrtsh.hxx> +#include <AnnotationWin.hxx> +#include <IDocumentDeviceAccess.hxx> +#include <redline.hxx> +#include <memory> + +namespace sw::sidebarwindows { + +SidebarTextControl::SidebarTextControl(sw::annotation::SwAnnotationWin& rSidebarWin, + SwView& rDocView, + SwPostItMgr& rPostItMgr) + : mrSidebarWin(rSidebarWin) + , mrDocView(rDocView) + , mrPostItMgr(rPostItMgr) + , mbMouseDownGainingFocus(false) +{ +} + +EditView* SidebarTextControl::GetEditView() const +{ + OutlinerView* pOutlinerView = mrSidebarWin.GetOutlinerView(); + if (!pOutlinerView) + return nullptr; + return &pOutlinerView->GetEditView(); +} + +EditEngine* SidebarTextControl::GetEditEngine() const +{ + OutlinerView* pOutlinerView = mrSidebarWin.GetOutlinerView(); + if (!pOutlinerView) + return nullptr; + return pOutlinerView->GetEditView().GetEditEngine(); +} + +void SidebarTextControl::SetDrawingArea(weld::DrawingArea* pDrawingArea) +{ + Size aSize(0, 0); + pDrawingArea->set_size_request(aSize.Width(), aSize.Height()); + + SetOutputSizePixel(aSize); + + weld::CustomWidgetController::SetDrawingArea(pDrawingArea); + + EnableRTL(false); + + const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings(); + Color aBgColor = rStyleSettings.GetWindowColor(); + + OutputDevice& rDevice = pDrawingArea->get_ref_device(); + + rDevice.SetMapMode(MapMode(MapUnit::MapTwip)); + rDevice.SetBackground(aBgColor); + + Size aOutputSize(rDevice.PixelToLogic(aSize)); + + EditView* pEditView = GetEditView(); + pEditView->setEditViewCallbacks(this); + + EditEngine* pEditEngine = GetEditEngine(); + // For tdf#143443 note we want an 'infinite' height initially (which is the + // editengines default). For tdf#144686 it is helpful if the initial width + // is the "SidebarWidth" so the calculated text height is always meaningful + // for layout in the sidebar. + Size aPaperSize(mrPostItMgr.GetSidebarWidth(), pEditEngine->GetPaperSize().Height()); + pEditEngine->SetPaperSize(aPaperSize); + pEditEngine->SetRefDevice(mrDocView.GetWrtShell().getIDocumentDeviceAccess().getReferenceDevice(false)); + + pEditView->SetOutputArea(tools::Rectangle(Point(0, 0), aOutputSize)); + pEditView->SetBackgroundColor(aBgColor); + + pDrawingArea->set_cursor(PointerStyle::Text); + +#if !ENABLE_WASM_STRIP_ACCESSIBILITY + InitAccessible(); +#endif +} + +void SidebarTextControl::SetCursorLogicPosition(const Point& rPosition, bool bPoint, bool bClearMark) +{ + Point aMousePos = EditViewOutputDevice().PixelToLogic(rPosition); + m_xEditView->SetCursorLogicPosition(aMousePos, bPoint, bClearMark); +} + +void SidebarTextControl::GetFocus() +{ + WeldEditView::GetFocus(); + if ( !mrSidebarWin.IsMouseOver() ) + Invalidate(); + mrSidebarWin.SetActiveSidebarWin(); +} + +void SidebarTextControl::LoseFocus() +{ + // write the visible text back into the SwField + mrSidebarWin.UpdateData(); + + WeldEditView::LoseFocus(); + if ( !mrSidebarWin.IsMouseOver() ) + { + Invalidate(); + } + // set false for autoscroll to typing location + mrSidebarWin.LockView(false); +} + +OUString SidebarTextControl::RequestHelp(tools::Rectangle& rHelpRect) +{ + if (EditView* pEditView = GetEditView()) + { + Point aPos = rHelpRect.TopLeft(); + + const OutputDevice& rOutDev = pEditView->GetOutputDevice(); + Point aLogicClick = rOutDev.PixelToLogic(aPos); + const SvxFieldItem* pItem = pEditView->GetField(aLogicClick); + if (pItem) + { + const SvxFieldData* pField = pItem->GetField(); + const SvxURLField* pURL = dynamic_cast<const SvxURLField*>( pField ); + if (pURL) + { + rHelpRect = tools::Rectangle(aPos, Size(50, 10)); + return SfxHelp::GetURLHelpText(pURL->GetURL()); + } + } + } + + TranslateId pResId; + switch( mrSidebarWin.GetLayoutStatus() ) + { + case SwPostItHelper::INSERTED: pResId = STR_REDLINE_INSERT; break; + case SwPostItHelper::DELETED: pResId = STR_REDLINE_DELETE; break; + default: break; + } + + SwContentAtPos aContentAtPos( IsAttrAtPos::Redline ); + if ( pResId && + mrDocView.GetWrtShell().GetContentAtPos( mrSidebarWin.GetAnchorPos(), aContentAtPos ) ) + { + OUString sText = SwResId(pResId) + ": " + + aContentAtPos.aFnd.pRedl->GetAuthorString() + " - " + + GetAppLangDateTimeString( aContentAtPos.aFnd.pRedl->GetTimeStamp() ); + return sText; + } + + return OUString(); +} + +void SidebarTextControl::EditViewScrollStateChange() +{ + mrSidebarWin.SetScrollbar(); +} + +void SidebarTextControl::DrawForPage(OutputDevice* pDev, const Point& rPt) +{ + //Take the control's height, but overwrite the scrollbar area if there was one + OutputDevice& rDevice = GetDrawingArea()->get_ref_device(); + Size aSize(rDevice.PixelToLogic(GetOutputSizePixel())); + + if (OutlinerView* pOutlinerView = mrSidebarWin.GetOutlinerView()) + { + pOutlinerView->GetOutliner()->Draw(*pDev, tools::Rectangle(rPt, aSize)); + } + + if ( mrSidebarWin.GetLayoutStatus()!=SwPostItHelper::DELETED ) + return; + + pDev->Push(vcl::PushFlags::LINECOLOR); + + pDev->SetLineColor(mrSidebarWin.GetChangeColor()); + Point aBottomRight(rPt); + aBottomRight.Move(aSize); + pDev->DrawLine(rPt, aBottomRight); + + Point aTopRight(rPt); + aTopRight.Move(Size(aSize.Width(), 0)); + + Point aBottomLeft(rPt); + aBottomLeft.Move(Size(0, aSize.Height())); + + pDev->DrawLine(aTopRight, aBottomLeft); + + pDev->Pop(); +} + +void SidebarTextControl::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect) +{ + Size aSize = GetOutputSizePixel(); + Point aPos; + + if (!rRenderContext.GetSettings().GetStyleSettings().GetHighContrastMode()) + { + if (mrSidebarWin.IsMouseOverSidebarWin() || HasFocus()) + { + rRenderContext.DrawGradient(tools::Rectangle(aPos, rRenderContext.PixelToLogic(aSize)), + Gradient(css::awt::GradientStyle_LINEAR, mrSidebarWin.ColorDark(), mrSidebarWin.ColorDark())); + } + else + { + rRenderContext.DrawGradient(tools::Rectangle(aPos, rRenderContext.PixelToLogic(aSize)), + Gradient(css::awt::GradientStyle_LINEAR, mrSidebarWin.ColorLight(), mrSidebarWin.ColorDark())); + } + } + + DoPaint(rRenderContext, rRect); + + if (mrSidebarWin.GetLayoutStatus() != SwPostItHelper::DELETED) + return; + + const AntialiasingFlags nFormerAntialiasing( rRenderContext.GetAntialiasing() ); + const bool bIsAntiAliasing = officecfg::Office::Common::Drawinglayer::AntiAliasing::get(); + if ( bIsAntiAliasing ) + rRenderContext.SetAntialiasing(AntialiasingFlags::Enable); + rRenderContext.SetLineColor(mrSidebarWin.GetChangeColor()); + rRenderContext.DrawLine(rRenderContext.PixelToLogic(aPos), + rRenderContext.PixelToLogic(aPos + Point(aSize.Width(), + aSize.Height() * 0.95))); + rRenderContext.DrawLine(rRenderContext.PixelToLogic(aPos + Point(aSize.Width(), + 0)), + rRenderContext.PixelToLogic(aPos + Point(0, + aSize.Height() * 0.95))); + if ( bIsAntiAliasing ) + rRenderContext.SetAntialiasing(nFormerAntialiasing); +} + +void SidebarTextControl::MakeVisible() +{ + //let's make sure we see our note + mrPostItMgr.MakeVisible(&mrSidebarWin); +} + +bool SidebarTextControl::KeyInput( const KeyEvent& rKeyEvt ) +{ + const vcl::KeyCode& rKeyCode = rKeyEvt.GetKeyCode(); + const sal_uInt16 nKey = rKeyCode.GetCode(); + if (nKey == KEY_F12 && getenv("SW_DEBUG")) + { + if (rKeyEvt.GetKeyCode().IsShift()) + { + mrDocView.GetDocShell()->GetDoc()->dumpAsXml(); + return true; + } + } + + bool bDone = false; + + if ( ( rKeyCode.IsMod1() && rKeyCode.IsMod2() ) && + ( (nKey == KEY_PAGEUP) || (nKey == KEY_PAGEDOWN) ) ) + { + mrSidebarWin.SwitchToPostIt(nKey); + bDone = true; + } + else if ( nKey == KEY_ESCAPE || + ( rKeyCode.IsMod1() && + ( nKey == KEY_PAGEUP || + nKey == KEY_PAGEDOWN ) ) ) + { + mrSidebarWin.SwitchToFieldPos(); + bDone = true; + } + else if ( rKeyCode.GetFullCode() == KEY_INSERT ) + { + mrSidebarWin.ToggleInsMode(); + bDone = true; + } + else + { + MakeVisible(); + + tools::Long aOldHeight = mrSidebarWin.GetPostItTextHeight(); + + /// HACK: need to switch off processing of Undo/Redo in Outliner + if ( !( (nKey == KEY_Z || nKey == KEY_Y) && rKeyCode.IsMod1()) ) + { + bool bIsProtected = mrSidebarWin.IsReadOnlyOrProtected(); + if ( !bIsProtected || !EditEngine::DoesKeyChangeText(rKeyEvt) ) + { + EditView* pEditView = GetEditView(); + bDone = pEditView && pEditView->PostKeyEvent(rKeyEvt); + } + else + mrDocView.GetWrtShell().InfoReadOnlyDialog(false); + } + if (bDone) + mrSidebarWin.ResizeIfNecessary( aOldHeight, mrSidebarWin.GetPostItTextHeight() ); + else + { + // write back data first when showing navigator + if ( nKey==KEY_F5 ) + mrSidebarWin.UpdateData(); + bDone = mrDocView.KeyInput(rKeyEvt); + } + } + + mrDocView.GetViewFrame().GetBindings().InvalidateAll(false); + + return bDone; +} + +bool SidebarTextControl::MouseButtonDown(const MouseEvent& rMEvt) +{ + if (EditView* pEditView = GetEditView()) + { + bool bExecuteMod = SvtSecurityOptions::IsOptionSet( SvtSecurityOptions::EOption::CtrlClickHyperlink); + + if ( !bExecuteMod || (rMEvt.GetModifier() == KEY_MOD1)) + { + const OutputDevice& rOutDev = pEditView->GetOutputDevice(); + Point aLogicClick = rOutDev.PixelToLogic(rMEvt.GetPosPixel()); + if (const SvxFieldItem* pItem = pEditView->GetField(aLogicClick)) + { + const SvxFieldData* pField = pItem->GetField(); + const SvxURLField* pURL = dynamic_cast<const SvxURLField*>( pField ); + if ( pURL ) + { + pEditView->MouseButtonDown( rMEvt ); + SwWrtShell &rSh = mrDocView.GetWrtShell(); + const OUString& sURL( pURL->GetURL() ); + const OUString& sTarget( pURL->GetTargetFrame() ); + ::LoadURL(rSh, sURL, LoadUrlFlags::NONE, sTarget); + return true; + } + } + } + } + + mbMouseDownGainingFocus = !HasFocus(); + GrabFocus(); + + bool bRet = WeldEditView::MouseButtonDown(rMEvt); + + mrDocView.GetViewFrame().GetBindings().InvalidateAll(false); + + return bRet; +} + +bool SidebarTextControl::MouseButtonUp(const MouseEvent& rMEvt) +{ + bool bRet = WeldEditView::MouseButtonUp(rMEvt); + + if (mbMouseDownGainingFocus) + { + MakeVisible(); + mbMouseDownGainingFocus = false; + } + + return bRet; +} + +bool SidebarTextControl::MouseMove(const MouseEvent& rMEvt) +{ + if (rMEvt.IsEnterWindow()) + GetDrawingArea()->set_cursor(PointerStyle::Text); + return WeldEditView::MouseMove(rMEvt); +} + +IMPL_LINK( SidebarTextControl, OnlineSpellCallback, SpellCallbackInfo&, rInfo, void ) +{ + if ( rInfo.nCommand == SpellCallbackCommand::STARTSPELLDLG ) + { + mrDocView.GetViewFrame().GetDispatcher()->Execute( FN_SPELL_GRAMMAR_DIALOG, SfxCallMode::ASYNCHRON); + } +} + +bool SidebarTextControl::Command( const CommandEvent& rCEvt ) +{ + EditView* pEditView = GetEditView(); + + if ( rCEvt.GetCommand() == CommandEventId::ContextMenu ) + { + if (IsMouseCaptured()) + ReleaseMouse(); + if ( !mrSidebarWin.IsReadOnlyOrProtected() && + pEditView && + pEditView->IsWrongSpelledWordAtPos( rCEvt.GetMousePosPixel(), true )) + { + Link<SpellCallbackInfo&,void> aLink = LINK(this, SidebarTextControl, OnlineSpellCallback); + pEditView->ExecuteSpellPopup(rCEvt.GetMousePosPixel(), aLink); + } + else + { + Point aPos; + if (rCEvt.IsMouseEvent()) + aPos = rCEvt.GetMousePosPixel(); + else + { + const Size aSize = GetOutputSizePixel(); + aPos = Point( aSize.getWidth()/2, aSize.getHeight()/2 ); + } + SfxDispatcher::ExecutePopup(&mrSidebarWin, &aPos); + } + return true; + } + else if (rCEvt.GetCommand() == CommandEventId::Wheel) + { + // if no scrollbar, or extra keys held scroll the document and consume + // this event, otherwise don't consume and let the event get to the + // surrounding scrolled window + if (!mrSidebarWin.IsScrollbarVisible()) + { + mrDocView.HandleWheelCommands(rCEvt); + return true; + } + else + { + const CommandWheelData* pData = rCEvt.GetWheelData(); + if (pData->IsShift() || pData->IsMod1() || pData->IsMod2()) + { + mrDocView.HandleWheelCommands(rCEvt); + return true; + } + } + } + + return WeldEditView::Command(rCEvt); +} + +} // end of namespace sw::sidebarwindows + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |