diff options
Diffstat (limited to 'sw/source/uibase/docvw/SidebarTxtControl.cxx')
-rw-r--r-- | sw/source/uibase/docvw/SidebarTxtControl.cxx | 446 |
1 files changed, 446 insertions, 0 deletions
diff --git a/sw/source/uibase/docvw/SidebarTxtControl.cxx b/sw/source/uibase/docvw/SidebarTxtControl.cxx new file mode 100644 index 000000000..65c67d098 --- /dev/null +++ b/sw/source/uibase/docvw/SidebarTxtControl.cxx @@ -0,0 +1,446 @@ +/* -*- 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 "SidebarTxtControl.hxx" + +#include "SidebarTxtControlAcc.hxx" +#include <docsh.hxx> +#include <doc.hxx> + +#include <PostItMgr.hxx> +#include <edtwin.hxx> + +#include <cmdid.h> +#include <strings.hrc> + +#include <unotools/securityoptions.hxx> + +#include <sfx2/viewfrm.hxx> +#include <sfx2/bindings.hxx> +#include <sfx2/dispatch.hxx> +#include <sfx2/sfxhelp.hxx> + +#include <vcl/commandevent.hxx> +#include <vcl/svapp.hxx> +#include <vcl/help.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 <comphelper/lok.hxx> +#include <sfx2/lokhelper.hxx> + +#include <uitool.hxx> +#include <view.hxx> +#include <wrtsh.hxx> +#include <AnnotationWin.hxx> +#include <redline.hxx> +#include <memory> + +namespace sw::sidebarwindows { + +SidebarTextControl::SidebarTextControl( sw::annotation::SwAnnotationWin& rSidebarWin, + WinBits nBits, + SwView& rDocView, + SwPostItMgr& rPostItMgr ) + : Control( &rSidebarWin, nBits ) + , mrSidebarWin( rSidebarWin ) + , mrDocView( rDocView ) + , mrPostItMgr( rPostItMgr ) +{ + AddEventListener( LINK( &mrSidebarWin, sw::annotation::SwAnnotationWin, WindowEventListener ) ); +} + +SidebarTextControl::~SidebarTextControl() +{ + disposeOnce(); +} + +void SidebarTextControl::dispose() +{ + RemoveEventListener( LINK( &mrSidebarWin, sw::annotation::SwAnnotationWin, WindowEventListener ) ); + Control::dispose(); +} + +OutlinerView* SidebarTextControl::GetTextView() const +{ + return mrSidebarWin.GetOutlinerView(); +} + +void SidebarTextControl::GetFocus() +{ + Window::GetFocus(); + if ( !mrSidebarWin.IsMouseOver() ) + { + Invalidate(); + } +} + +void SidebarTextControl::LoseFocus() +{ + // write the visible text back into the SwField + mrSidebarWin.UpdateData(); + + Window::LoseFocus(); + if ( !mrSidebarWin.IsMouseOver() ) + { + Invalidate(); + } +} + +void SidebarTextControl::RequestHelp(const HelpEvent &rEvt) +{ + const char* pResId = nullptr; + switch( mrSidebarWin.GetLayoutStatus() ) + { + case SwPostItHelper::INSERTED: pResId = STR_REDLINE_INSERT; break; + case SwPostItHelper::DELETED: pResId = STR_REDLINE_DELETE; break; + default: pResId = nullptr; + } + + 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() ); + Help::ShowQuickHelp( this,PixelToLogic(tools::Rectangle(rEvt.GetMousePosPixel(),Size(50,10))),sText); + } +} + +void SidebarTextControl::Draw(OutputDevice* pDev, const Point& rPt, DrawFlags) +{ + //Take the control's height, but overwrite the scrollbar area if there was one + Size aSize(PixelToLogic(GetSizePixel())); + + if ( GetTextView() ) + { + GetTextView()->GetOutliner()->Draw(pDev, tools::Rectangle(rPt, aSize)); + } + + if ( mrSidebarWin.GetLayoutStatus()==SwPostItHelper::DELETED ) + { + SetLineColor(mrSidebarWin.GetChangeColor()); + pDev->DrawLine( PixelToLogic( GetPosPixel(), pDev->GetMapMode() ), + PixelToLogic( GetPosPixel() + + Point( GetSizePixel().Width(), + GetSizePixel().Height() ), pDev->GetMapMode() ) ); + pDev->DrawLine( PixelToLogic( GetPosPixel() + + Point( GetSizePixel().Width(),0), pDev->GetMapMode() ), + PixelToLogic( GetPosPixel() + + Point( 0, GetSizePixel().Height() ), pDev->GetMapMode() ) ); + } +} + +void SidebarTextControl::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect) +{ + if (!rRenderContext.GetSettings().GetStyleSettings().GetHighContrastMode()) + { + if (mrSidebarWin.IsMouseOverSidebarWin() || HasFocus()) + { + rRenderContext.DrawGradient(tools::Rectangle(Point(0,0), rRenderContext.PixelToLogic(GetSizePixel())), + Gradient(GradientStyle::Linear, mrSidebarWin.ColorDark(), mrSidebarWin.ColorDark())); + } + else + { + rRenderContext.DrawGradient(tools::Rectangle(Point(0,0), rRenderContext.PixelToLogic(GetSizePixel())), + Gradient(GradientStyle::Linear, mrSidebarWin.ColorLight(), mrSidebarWin.ColorDark())); + } + } + + if (GetTextView()) + { + GetTextView()->Paint(rRect, &rRenderContext); + } + + if (mrSidebarWin.GetLayoutStatus() == SwPostItHelper::DELETED) + { + rRenderContext.SetLineColor(mrSidebarWin.GetChangeColor()); + rRenderContext.DrawLine(rRenderContext.PixelToLogic(GetPosPixel()), + rRenderContext.PixelToLogic(GetPosPixel() + Point(GetSizePixel().Width(), + GetSizePixel().Height()))); + rRenderContext.DrawLine(rRenderContext.PixelToLogic(GetPosPixel() + Point(GetSizePixel().Width(), + 0)), + rRenderContext.PixelToLogic(GetPosPixel() + Point(0, + GetSizePixel().Height()))); + } +} + +void SidebarTextControl::LogicInvalidate(const tools::Rectangle* pRectangle) +{ + tools::Rectangle aRectangle; + + if (!pRectangle) + { + Push(PushFlags::MAPMODE); + EnableMapMode(); + aRectangle = tools::Rectangle(Point(0, 0), PixelToLogic(GetSizePixel())); + Pop(); + } + else + aRectangle = *pRectangle; + + // Convert from relative twips to absolute ones. + vcl::Window& rParent = mrSidebarWin.EditWin(); + Point aOffset(GetOutOffXPixel() - rParent.GetOutOffXPixel(), GetOutOffYPixel() - rParent.GetOutOffYPixel()); + rParent.Push(PushFlags::MAPMODE); + rParent.EnableMapMode(); + aOffset = rParent.PixelToLogic(aOffset); + rParent.Pop(); + aRectangle.Move(aOffset.getX(), aOffset.getY()); + + OString sRectangle = aRectangle.toString(); + SwWrtShell& rWrtShell = mrDocView.GetWrtShell(); + SfxLokHelper::notifyInvalidation(rWrtShell.GetSfxViewShell(), sRectangle); +} + +void SidebarTextControl::KeyInput( const KeyEvent& rKeyEvt ) +{ + if (getenv("SW_DEBUG") && rKeyEvt.GetKeyCode().GetCode() == KEY_F12) + { + if (rKeyEvt.GetKeyCode().IsShift()) + { + mrDocView.GetDocShell()->GetDoc()->dumpAsXml(); + return; + } + } + + const vcl::KeyCode& rKeyCode = rKeyEvt.GetKeyCode(); + sal_uInt16 nKey = rKeyCode.GetCode(); + if ( ( rKeyCode.IsMod1() && rKeyCode.IsMod2() ) && + ( (nKey == KEY_PAGEUP) || (nKey == KEY_PAGEDOWN) ) ) + { + mrSidebarWin.SwitchToPostIt(nKey); + } + else if ( nKey == KEY_ESCAPE || + ( rKeyCode.IsMod1() && + ( nKey == KEY_PAGEUP || + nKey == KEY_PAGEDOWN ) ) ) + { + mrSidebarWin.SwitchToFieldPos(); + } + else if ( rKeyCode.GetFullCode() == KEY_INSERT ) + { + mrSidebarWin.ToggleInsMode(); + } + else + { + // MakeVisible can lose our MapMode, save it. + auto oldMapMode = GetMapMode(); + //let's make sure we see our note + mrPostItMgr.MakeVisible(&mrSidebarWin); + if (comphelper::LibreOfficeKit::isActive()) + SetMapMode(oldMapMode); + + long aOldHeight = mrSidebarWin.GetPostItTextHeight(); + bool bDone = false; + + /// HACK: need to switch off processing of Undo/Redo in Outliner + if ( !( (nKey == KEY_Z || nKey == KEY_Y) && rKeyCode.IsMod1()) ) + { + bool bIsProtected = mrSidebarWin.IsProtected(); + if ( !bIsProtected || !EditEngine::DoesKeyChangeText(rKeyEvt) ) + { + bDone = GetTextView() && GetTextView()->PostKeyEvent( rKeyEvt ); + } + else + { + std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(GetFrameWeld(), "modules/swriter/ui/inforeadonlydialog.ui")); + std::unique_ptr<weld::MessageDialog> xQuery(xBuilder->weld_message_dialog("InfoReadonlyDialog")); + xQuery->run(); + } + } + if (bDone) + mrSidebarWin.ResizeIfNecessary( aOldHeight, mrSidebarWin.GetPostItTextHeight() ); + else + { + // write back data first when showing navigator + if ( nKey==KEY_F5 ) + mrSidebarWin.UpdateData(); + if (!mrDocView.KeyInput(rKeyEvt)) + Window::KeyInput(rKeyEvt); + } + } + + mrDocView.GetViewFrame()->GetBindings().InvalidateAll(false); +} + +void SidebarTextControl::MouseMove( const MouseEvent& rMEvt ) +{ + if ( GetTextView() ) + { + OutlinerView* pOutlinerView( GetTextView() ); + pOutlinerView->MouseMove( rMEvt ); + // mba: why does OutlinerView not handle the modifier setting?! + // this forces the postit to handle *all* pointer types + SetPointer( pOutlinerView->GetPointer( rMEvt.GetPosPixel() ) ); + + const EditView& aEV = pOutlinerView->GetEditView(); + const SvxFieldItem* pItem = aEV.GetFieldUnderMousePointer(); + if ( pItem ) + { + const SvxFieldData* pField = pItem->GetField(); + const SvxURLField* pURL = dynamic_cast<const SvxURLField*>( pField ); + if ( pURL ) + { + OUString sText(SfxHelp::GetURLHelpText(pURL->GetURL())); + Help::ShowQuickHelp( + this, PixelToLogic(tools::Rectangle(GetPosPixel(), Size(50, 10))), sText); + } + } + } +} + +void SidebarTextControl::MouseButtonDown( const MouseEvent& rMEvt ) +{ + if ( GetTextView() ) + { + SvtSecurityOptions aSecOpts; + bool bExecuteMod = aSecOpts.IsOptionSet( SvtSecurityOptions::EOption::CtrlClickHyperlink); + + if ( !bExecuteMod || (rMEvt.GetModifier() == KEY_MOD1)) + { + const EditView& aEV = GetTextView()->GetEditView(); + const SvxFieldItem* pItem = aEV.GetFieldUnderMousePointer(); + if ( pItem ) + { + const SvxFieldData* pField = pItem->GetField(); + const SvxURLField* pURL = dynamic_cast<const SvxURLField*>( pField ); + if ( pURL ) + { + GetTextView()->MouseButtonDown( rMEvt ); + SwWrtShell &rSh = mrDocView.GetWrtShell(); + const OUString& sURL( pURL->GetURL() ); + const OUString& sTarget( pURL->GetTargetFrame() ); + ::LoadURL(rSh, sURL, LoadUrlFlags::NONE, sTarget); + return; + } + } + } + } + + GrabFocus(); + if ( GetTextView() ) + { + GetTextView()->MouseButtonDown( rMEvt ); + } + mrDocView.GetViewFrame()->GetBindings().InvalidateAll(false); +} + +void SidebarTextControl::MouseButtonUp( const MouseEvent& rMEvt ) +{ + if ( GetTextView() ) + GetTextView()->MouseButtonUp( rMEvt ); +} + +IMPL_LINK( SidebarTextControl, OnlineSpellCallback, SpellCallbackInfo&, rInfo, void ) +{ + if ( rInfo.nCommand == SpellCallbackCommand::STARTSPELLDLG ) + { + mrDocView.GetViewFrame()->GetDispatcher()->Execute( FN_SPELL_GRAMMAR_DIALOG, SfxCallMode::ASYNCHRON); + } +} + +void SidebarTextControl::Command( const CommandEvent& rCEvt ) +{ + if ( rCEvt.GetCommand() == CommandEventId::ContextMenu ) + { + if ( !mrSidebarWin.IsProtected() && + GetTextView() && + GetTextView()->IsWrongSpelledWordAtPos( rCEvt.GetMousePosPixel(), true )) + { + Link<SpellCallbackInfo&,void> aLink = LINK(this, SidebarTextControl, OnlineSpellCallback); + GetTextView()->ExecuteSpellPopup(rCEvt.GetMousePosPixel(),&aLink); + } + else + { + Point aPos; + if (rCEvt.IsMouseEvent()) + aPos = rCEvt.GetMousePosPixel(); + else + { + const Size aSize = GetSizePixel(); + aPos = Point( aSize.getWidth()/2, aSize.getHeight()/2 ); + } + SfxDispatcher::ExecutePopup(this, &aPos); + } + } + else + if (rCEvt.GetCommand() == CommandEventId::Wheel) + { + if (mrSidebarWin.IsScrollbarVisible()) + { + const CommandWheelData* pData = rCEvt.GetWheelData(); + if (pData->IsShift() || pData->IsMod1() || pData->IsMod2()) + { + mrDocView.HandleWheelCommands(rCEvt); + } + else + { + HandleScrollCommand( rCEvt, nullptr , mrSidebarWin.Scrollbar()); + } + } + else + { + mrDocView.HandleWheelCommands(rCEvt); + } + } + else + { + if ( GetTextView() ) + GetTextView()->Command( rCEvt ); + else + Window::Command(rCEvt); + } +} + +OUString SidebarTextControl::GetSurroundingText() const +{ + if (GetTextView()) + return GetTextView()->GetSurroundingText(); + return OUString(); +} + +Selection SidebarTextControl::GetSurroundingTextSelection() const +{ + if( GetTextView() ) + return GetTextView()->GetSurroundingTextSelection(); + else + return Selection( 0, 0 ); +} + +css::uno::Reference< css::accessibility::XAccessible > SidebarTextControl::CreateAccessible() +{ + + SidebarTextControlAccessible* pAcc( new SidebarTextControlAccessible( *this ) ); + 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; +} + +} // end of namespace sw::sidebarwindows + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |