1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <config_wasm_strip.h>
22 #include "SidebarTxtControl.hxx"
27 #include <PostItMgr.hxx>
30 #include <strings.hrc>
32 #include <unotools/securityoptions.hxx>
33 #include <officecfg/Office/Common.hxx>
35 #include <sfx2/viewfrm.hxx>
36 #include <sfx2/bindings.hxx>
37 #include <sfx2/dispatch.hxx>
38 #include <sfx2/sfxhelp.hxx>
40 #include <vcl/commandevent.hxx>
41 #include <vcl/event.hxx>
42 #include <vcl/ptrstyle.hxx>
43 #include <vcl/svapp.hxx>
44 #include <vcl/weld.hxx>
45 #include <vcl/gradient.hxx>
46 #include <vcl/settings.hxx>
48 #include <editeng/outliner.hxx>
49 #include <editeng/editeng.hxx>
50 #include <editeng/editview.hxx>
51 #include <editeng/flditem.hxx>
56 #include <AnnotationWin.hxx>
57 #include <IDocumentDeviceAccess.hxx>
58 #include <redline.hxx>
61 namespace sw::sidebarwindows
{
63 SidebarTextControl::SidebarTextControl(sw::annotation::SwAnnotationWin
& rSidebarWin
,
65 SwPostItMgr
& rPostItMgr
)
66 : mrSidebarWin(rSidebarWin
)
68 , mrPostItMgr(rPostItMgr
)
69 , mbMouseDownGainingFocus(false)
73 EditView
* SidebarTextControl::GetEditView() const
75 OutlinerView
* pOutlinerView
= mrSidebarWin
.GetOutlinerView();
78 return &pOutlinerView
->GetEditView();
81 EditEngine
* SidebarTextControl::GetEditEngine() const
83 OutlinerView
* pOutlinerView
= mrSidebarWin
.GetOutlinerView();
86 return pOutlinerView
->GetEditView().GetEditEngine();
89 void SidebarTextControl::SetDrawingArea(weld::DrawingArea
* pDrawingArea
)
92 pDrawingArea
->set_size_request(aSize
.Width(), aSize
.Height());
94 SetOutputSizePixel(aSize
);
96 weld::CustomWidgetController::SetDrawingArea(pDrawingArea
);
100 const StyleSettings
& rStyleSettings
= Application::GetSettings().GetStyleSettings();
101 Color aBgColor
= rStyleSettings
.GetWindowColor();
103 OutputDevice
& rDevice
= pDrawingArea
->get_ref_device();
105 rDevice
.SetMapMode(MapMode(MapUnit::MapTwip
));
106 rDevice
.SetBackground(aBgColor
);
108 Size
aOutputSize(rDevice
.PixelToLogic(aSize
));
110 EditView
* pEditView
= GetEditView();
111 pEditView
->setEditViewCallbacks(this);
113 EditEngine
* pEditEngine
= GetEditEngine();
114 // For tdf#143443 note we want an 'infinite' height initially (which is the
115 // editengines default). For tdf#144686 it is helpful if the initial width
116 // is the "SidebarWidth" so the calculated text height is always meaningful
117 // for layout in the sidebar.
118 Size
aPaperSize(mrPostItMgr
.GetSidebarWidth(), pEditEngine
->GetPaperSize().Height());
119 pEditEngine
->SetPaperSize(aPaperSize
);
120 pEditEngine
->SetRefDevice(mrDocView
.GetWrtShell().getIDocumentDeviceAccess().getReferenceDevice(false));
122 pEditView
->SetOutputArea(tools::Rectangle(Point(0, 0), aOutputSize
));
123 pEditView
->SetBackgroundColor(aBgColor
);
125 pDrawingArea
->set_cursor(PointerStyle::Text
);
127 #if !ENABLE_WASM_STRIP_ACCESSIBILITY
132 void SidebarTextControl::SetCursorLogicPosition(const Point
& rPosition
, bool bPoint
, bool bClearMark
)
134 Point aMousePos
= EditViewOutputDevice().PixelToLogic(rPosition
);
135 m_xEditView
->SetCursorLogicPosition(aMousePos
, bPoint
, bClearMark
);
138 void SidebarTextControl::GetFocus()
140 WeldEditView::GetFocus();
141 if ( !mrSidebarWin
.IsMouseOver() )
143 mrSidebarWin
.SetActiveSidebarWin();
146 void SidebarTextControl::LoseFocus()
148 // write the visible text back into the SwField
149 mrSidebarWin
.UpdateData();
151 WeldEditView::LoseFocus();
152 if ( !mrSidebarWin
.IsMouseOver() )
156 // set false for autoscroll to typing location
157 mrSidebarWin
.LockView(false);
160 OUString
SidebarTextControl::RequestHelp(tools::Rectangle
& rHelpRect
)
162 if (EditView
* pEditView
= GetEditView())
164 Point aPos
= rHelpRect
.TopLeft();
166 const OutputDevice
& rOutDev
= pEditView
->GetOutputDevice();
167 Point aLogicClick
= rOutDev
.PixelToLogic(aPos
);
168 const SvxFieldItem
* pItem
= pEditView
->GetField(aLogicClick
);
171 const SvxFieldData
* pField
= pItem
->GetField();
172 const SvxURLField
* pURL
= dynamic_cast<const SvxURLField
*>( pField
);
175 rHelpRect
= tools::Rectangle(aPos
, Size(50, 10));
176 return SfxHelp::GetURLHelpText(pURL
->GetURL());
182 switch( mrSidebarWin
.GetLayoutStatus() )
184 case SwPostItHelper::INSERTED
: pResId
= STR_REDLINE_INSERT
; break;
185 case SwPostItHelper::DELETED
: pResId
= STR_REDLINE_DELETE
; break;
189 SwContentAtPos
aContentAtPos( IsAttrAtPos::Redline
);
191 mrDocView
.GetWrtShell().GetContentAtPos( mrSidebarWin
.GetAnchorPos(), aContentAtPos
) )
193 OUString sText
= SwResId(pResId
) + ": " +
194 aContentAtPos
.aFnd
.pRedl
->GetAuthorString() + " - " +
195 GetAppLangDateTimeString( aContentAtPos
.aFnd
.pRedl
->GetTimeStamp() );
202 void SidebarTextControl::EditViewScrollStateChange()
204 mrSidebarWin
.SetScrollbar();
207 void SidebarTextControl::DrawForPage(OutputDevice
* pDev
, const Point
& rPt
)
209 //Take the control's height, but overwrite the scrollbar area if there was one
210 OutputDevice
& rDevice
= GetDrawingArea()->get_ref_device();
211 Size
aSize(rDevice
.PixelToLogic(GetOutputSizePixel()));
213 if (OutlinerView
* pOutlinerView
= mrSidebarWin
.GetOutlinerView())
215 pOutlinerView
->GetOutliner()->Draw(*pDev
, tools::Rectangle(rPt
, aSize
));
218 if ( mrSidebarWin
.GetLayoutStatus()!=SwPostItHelper::DELETED
)
221 pDev
->Push(vcl::PushFlags::LINECOLOR
);
223 pDev
->SetLineColor(mrSidebarWin
.GetChangeColor());
224 Point
aBottomRight(rPt
);
225 aBottomRight
.Move(aSize
);
226 pDev
->DrawLine(rPt
, aBottomRight
);
228 Point
aTopRight(rPt
);
229 aTopRight
.Move(Size(aSize
.Width(), 0));
231 Point
aBottomLeft(rPt
);
232 aBottomLeft
.Move(Size(0, aSize
.Height()));
234 pDev
->DrawLine(aTopRight
, aBottomLeft
);
239 void SidebarTextControl::Paint(vcl::RenderContext
& rRenderContext
, const tools::Rectangle
& rRect
)
241 Size aSize
= GetOutputSizePixel();
244 if (!rRenderContext
.GetSettings().GetStyleSettings().GetHighContrastMode())
246 if (mrSidebarWin
.IsMouseOverSidebarWin() || HasFocus())
248 rRenderContext
.DrawGradient(tools::Rectangle(aPos
, rRenderContext
.PixelToLogic(aSize
)),
249 Gradient(css::awt::GradientStyle_LINEAR
, mrSidebarWin
.ColorDark(), mrSidebarWin
.ColorDark()));
253 rRenderContext
.DrawGradient(tools::Rectangle(aPos
, rRenderContext
.PixelToLogic(aSize
)),
254 Gradient(css::awt::GradientStyle_LINEAR
, mrSidebarWin
.ColorLight(), mrSidebarWin
.ColorDark()));
258 DoPaint(rRenderContext
, rRect
);
260 if (mrSidebarWin
.GetLayoutStatus() != SwPostItHelper::DELETED
)
263 const AntialiasingFlags
nFormerAntialiasing( rRenderContext
.GetAntialiasing() );
264 const bool bIsAntiAliasing
= officecfg::Office::Common::Drawinglayer::AntiAliasing::get();
265 if ( bIsAntiAliasing
)
266 rRenderContext
.SetAntialiasing(AntialiasingFlags::Enable
);
267 rRenderContext
.SetLineColor(mrSidebarWin
.GetChangeColor());
268 rRenderContext
.DrawLine(rRenderContext
.PixelToLogic(aPos
),
269 rRenderContext
.PixelToLogic(aPos
+ Point(aSize
.Width(),
270 aSize
.Height() * 0.95)));
271 rRenderContext
.DrawLine(rRenderContext
.PixelToLogic(aPos
+ Point(aSize
.Width(),
273 rRenderContext
.PixelToLogic(aPos
+ Point(0,
274 aSize
.Height() * 0.95)));
275 if ( bIsAntiAliasing
)
276 rRenderContext
.SetAntialiasing(nFormerAntialiasing
);
279 void SidebarTextControl::MakeVisible()
281 //let's make sure we see our note
282 mrPostItMgr
.MakeVisible(&mrSidebarWin
);
285 bool SidebarTextControl::KeyInput( const KeyEvent
& rKeyEvt
)
287 if (getenv("SW_DEBUG") && rKeyEvt
.GetKeyCode().GetCode() == KEY_F12
)
289 if (rKeyEvt
.GetKeyCode().IsShift())
291 mrDocView
.GetDocShell()->GetDoc()->dumpAsXml();
298 const vcl::KeyCode
& rKeyCode
= rKeyEvt
.GetKeyCode();
299 sal_uInt16 nKey
= rKeyCode
.GetCode();
300 if ( ( rKeyCode
.IsMod1() && rKeyCode
.IsMod2() ) &&
301 ( (nKey
== KEY_PAGEUP
) || (nKey
== KEY_PAGEDOWN
) ) )
303 mrSidebarWin
.SwitchToPostIt(nKey
);
306 else if ( nKey
== KEY_ESCAPE
||
307 ( rKeyCode
.IsMod1() &&
308 ( nKey
== KEY_PAGEUP
||
309 nKey
== KEY_PAGEDOWN
) ) )
311 mrSidebarWin
.SwitchToFieldPos();
314 else if ( rKeyCode
.GetFullCode() == KEY_INSERT
)
316 mrSidebarWin
.ToggleInsMode();
323 tools::Long aOldHeight
= mrSidebarWin
.GetPostItTextHeight();
325 /// HACK: need to switch off processing of Undo/Redo in Outliner
326 if ( !( (nKey
== KEY_Z
|| nKey
== KEY_Y
) && rKeyCode
.IsMod1()) )
328 bool bIsProtected
= mrSidebarWin
.IsReadOnlyOrProtected();
329 if ( !bIsProtected
|| !EditEngine::DoesKeyChangeText(rKeyEvt
) )
331 EditView
* pEditView
= GetEditView();
332 bDone
= pEditView
&& pEditView
->PostKeyEvent(rKeyEvt
);
335 mrDocView
.GetWrtShell().InfoReadOnlyDialog(false);
338 mrSidebarWin
.ResizeIfNecessary( aOldHeight
, mrSidebarWin
.GetPostItTextHeight() );
341 // write back data first when showing navigator
343 mrSidebarWin
.UpdateData();
344 bDone
= mrDocView
.KeyInput(rKeyEvt
);
348 mrDocView
.GetViewFrame().GetBindings().InvalidateAll(false);
353 bool SidebarTextControl::MouseButtonDown(const MouseEvent
& rMEvt
)
355 if (EditView
* pEditView
= GetEditView())
357 bool bExecuteMod
= SvtSecurityOptions::IsOptionSet( SvtSecurityOptions::EOption::CtrlClickHyperlink
);
359 if ( !bExecuteMod
|| (rMEvt
.GetModifier() == KEY_MOD1
))
361 const OutputDevice
& rOutDev
= pEditView
->GetOutputDevice();
362 Point aLogicClick
= rOutDev
.PixelToLogic(rMEvt
.GetPosPixel());
363 if (const SvxFieldItem
* pItem
= pEditView
->GetField(aLogicClick
))
365 const SvxFieldData
* pField
= pItem
->GetField();
366 const SvxURLField
* pURL
= dynamic_cast<const SvxURLField
*>( pField
);
369 pEditView
->MouseButtonDown( rMEvt
);
370 SwWrtShell
&rSh
= mrDocView
.GetWrtShell();
371 const OUString
& sURL( pURL
->GetURL() );
372 const OUString
& sTarget( pURL
->GetTargetFrame() );
373 ::LoadURL(rSh
, sURL
, LoadUrlFlags::NONE
, sTarget
);
380 mbMouseDownGainingFocus
= !HasFocus();
383 bool bRet
= WeldEditView::MouseButtonDown(rMEvt
);
385 mrDocView
.GetViewFrame().GetBindings().InvalidateAll(false);
390 bool SidebarTextControl::MouseButtonUp(const MouseEvent
& rMEvt
)
392 bool bRet
= WeldEditView::MouseButtonUp(rMEvt
);
394 if (mbMouseDownGainingFocus
)
397 mbMouseDownGainingFocus
= false;
403 bool SidebarTextControl::MouseMove(const MouseEvent
& rMEvt
)
405 if (rMEvt
.IsEnterWindow())
406 GetDrawingArea()->set_cursor(PointerStyle::Text
);
407 return WeldEditView::MouseMove(rMEvt
);
410 IMPL_LINK( SidebarTextControl
, OnlineSpellCallback
, SpellCallbackInfo
&, rInfo
, void )
412 if ( rInfo
.nCommand
== SpellCallbackCommand::STARTSPELLDLG
)
414 mrDocView
.GetViewFrame().GetDispatcher()->Execute( FN_SPELL_GRAMMAR_DIALOG
, SfxCallMode::ASYNCHRON
);
418 bool SidebarTextControl::Command( const CommandEvent
& rCEvt
)
420 EditView
* pEditView
= GetEditView();
422 if ( rCEvt
.GetCommand() == CommandEventId::ContextMenu
)
424 if (IsMouseCaptured())
426 if ( !mrSidebarWin
.IsReadOnlyOrProtected() &&
428 pEditView
->IsWrongSpelledWordAtPos( rCEvt
.GetMousePosPixel(), true ))
430 Link
<SpellCallbackInfo
&,void> aLink
= LINK(this, SidebarTextControl
, OnlineSpellCallback
);
431 pEditView
->ExecuteSpellPopup(rCEvt
.GetMousePosPixel(), aLink
);
436 if (rCEvt
.IsMouseEvent())
437 aPos
= rCEvt
.GetMousePosPixel();
440 const Size aSize
= GetOutputSizePixel();
441 aPos
= Point( aSize
.getWidth()/2, aSize
.getHeight()/2 );
443 SfxDispatcher::ExecutePopup(&mrSidebarWin
, &aPos
);
447 else if (rCEvt
.GetCommand() == CommandEventId::Wheel
)
449 // if no scrollbar, or extra keys held scroll the document and consume
450 // this event, otherwise don't consume and let the event get to the
451 // surrounding scrolled window
452 if (!mrSidebarWin
.IsScrollbarVisible())
454 mrDocView
.HandleWheelCommands(rCEvt
);
459 const CommandWheelData
* pData
= rCEvt
.GetWheelData();
460 if (pData
->IsShift() || pData
->IsMod1() || pData
->IsMod2())
462 mrDocView
.HandleWheelCommands(rCEvt
);
468 return WeldEditView::Command(rCEvt
);
471 } // end of namespace sw::sidebarwindows
473 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */