LibreOffice Module sw (master)  1
SidebarTxtControl.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
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/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
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 .
18  */
19 
20 #include "SidebarTxtControl.hxx"
21 
22 #include <docsh.hxx>
23 #include <doc.hxx>
24 
25 #include <PostItMgr.hxx>
26 #include <edtwin.hxx>
27 
28 #include <cmdid.h>
29 #include <strings.hrc>
30 
32 #include <officecfg/Office/Common.hxx>
33 
34 #include <sfx2/viewfrm.hxx>
35 #include <sfx2/bindings.hxx>
36 #include <sfx2/dispatch.hxx>
37 #include <sfx2/sfxhelp.hxx>
38 
39 #include <vcl/commandevent.hxx>
40 #include <vcl/svapp.hxx>
41 #include <vcl/help.hxx>
42 #include <vcl/weld.hxx>
43 #include <vcl/gradient.hxx>
44 #include <vcl/settings.hxx>
45 
46 #include <editeng/outliner.hxx>
47 #include <editeng/editeng.hxx>
48 #include <editeng/editview.hxx>
49 #include <editeng/flditem.hxx>
50 #include <comphelper/lok.hxx>
51 #include <sfx2/lokhelper.hxx>
52 
53 #include <uitool.hxx>
54 #include <view.hxx>
55 #include <wrtsh.hxx>
56 #include <AnnotationWin.hxx>
57 #include <redline.hxx>
58 #include <memory>
59 
60 namespace sw::sidebarwindows {
61 
63  SwView& rDocView,
64  SwPostItMgr& rPostItMgr)
65  : mrSidebarWin(rSidebarWin)
66  , mrDocView(rDocView)
67  , mrPostItMgr(rPostItMgr)
68  , mbMouseDownGainingFocus(false)
69 {
70 }
71 
73 {
74  OutlinerView* pOutlinerView = mrSidebarWin.GetOutlinerView();
75  if (!pOutlinerView)
76  return nullptr;
77  return &pOutlinerView->GetEditView();
78 }
79 
81 {
82  OutlinerView* pOutlinerView = mrSidebarWin.GetOutlinerView();
83  if (!pOutlinerView)
84  return nullptr;
85  return pOutlinerView->GetEditView().GetEditEngine();
86 }
87 
89 {
90  Size aSize(0, 0);
91  pDrawingArea->set_size_request(aSize.Width(), aSize.Height());
92 
93  SetOutputSizePixel(aSize);
94 
96 
97  EnableRTL(false);
98 
99  const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
100  Color aBgColor = rStyleSettings.GetWindowColor();
101 
102  OutputDevice& rDevice = pDrawingArea->get_ref_device();
103 
104  rDevice.SetMapMode(MapMode(MapUnit::MapTwip));
105  rDevice.SetBackground(aBgColor);
106 
107  Size aOutputSize(rDevice.PixelToLogic(aSize));
108  aSize = aOutputSize;
109  aSize.setHeight(aSize.Height());
110 
111  EditView* pEditView = GetEditView();
112  pEditView->setEditViewCallbacks(this);
113 
114  EditEngine* pEditEngine = GetEditEngine();
115  pEditEngine->SetPaperSize(aSize);
116  pEditEngine->SetRefDevice(&rDevice);
117 
118  pEditView->SetOutputArea(tools::Rectangle(Point(0, 0), aOutputSize));
119  pEditView->SetBackgroundColor(aBgColor);
120 
121  pDrawingArea->set_cursor(PointerStyle::Text);
122 
123  InitAccessible();
124 }
125 
126 void SidebarTextControl::SetCursorLogicPosition(const Point& rPosition, bool bPoint, bool bClearMark)
127 {
128  Point aMousePos = EditViewOutputDevice().PixelToLogic(rPosition);
129  m_xEditView->SetCursorLogicPosition(aMousePos, bPoint, bClearMark);
130 }
131 
133 {
135  if ( !mrSidebarWin.IsMouseOver() )
136  Invalidate();
138 }
139 
141 {
142  // write the visible text back into the SwField
144 
146  if ( !mrSidebarWin.IsMouseOver() )
147  {
148  Invalidate();
149  }
150 }
151 
153 {
154  if (EditView* pEditView = GetEditView())
155  {
156  Point aPos = rHelpRect.TopLeft();
157 
158  const OutputDevice& rOutDev = pEditView->GetOutputDevice();
159  Point aLogicClick = rOutDev.PixelToLogic(aPos);
160  const SvxFieldItem* pItem = pEditView->GetField(aLogicClick);
161  if (pItem)
162  {
163  const SvxFieldData* pField = pItem->GetField();
164  const SvxURLField* pURL = dynamic_cast<const SvxURLField*>( pField );
165  if (pURL)
166  {
167  rHelpRect = tools::Rectangle(aPos, Size(50, 10));
168  return SfxHelp::GetURLHelpText(pURL->GetURL());
169  }
170  }
171  }
172 
173  const char* pResId = nullptr;
174  switch( mrSidebarWin.GetLayoutStatus() )
175  {
176  case SwPostItHelper::INSERTED: pResId = STR_REDLINE_INSERT; break;
177  case SwPostItHelper::DELETED: pResId = STR_REDLINE_DELETE; break;
178  default: pResId = nullptr;
179  }
180 
181  SwContentAtPos aContentAtPos( IsAttrAtPos::Redline );
182  if ( pResId &&
184  {
185  OUString sText = SwResId(pResId) + ": " +
186  aContentAtPos.aFnd.pRedl->GetAuthorString() + " - " +
187  GetAppLangDateTimeString( aContentAtPos.aFnd.pRedl->GetTimeStamp() );
188  return sText;
189  }
190 
191  return OUString();
192 }
193 
195 {
197 }
198 
199 void SidebarTextControl::DrawForPage(OutputDevice* pDev, const Point& rPt)
200 {
201  //Take the control's height, but overwrite the scrollbar area if there was one
202  OutputDevice& rDevice = GetDrawingArea()->get_ref_device();
203  Size aSize(rDevice.PixelToLogic(GetOutputSizePixel()));
204 
205  if (OutlinerView* pOutlinerView = mrSidebarWin.GetOutlinerView())
206  {
207  pOutlinerView->GetOutliner()->Draw(*pDev, tools::Rectangle(rPt, aSize));
208  }
209 
211  return;
212 
213  pDev->Push(PushFlags::LINECOLOR);
214 
216  Point aBottomRight(rPt);
217  aBottomRight.Move(aSize);
218  pDev->DrawLine(rPt, aBottomRight);
219 
220  Point aTopRight(rPt);
221  aTopRight.Move(Size(aSize.Width(), 0));
222 
223  Point aBottomLeft(rPt);
224  aBottomLeft.Move(Size(0, aSize.Height()));
225 
226  pDev->DrawLine(aTopRight, aBottomLeft);
227 
228  pDev->Pop();
229 }
230 
232 {
233  Size aSize = GetOutputSizePixel();
234  Point aPos;
235 
236  if (!rRenderContext.GetSettings().GetStyleSettings().GetHighContrastMode())
237  {
238  if (mrSidebarWin.IsMouseOverSidebarWin() || HasFocus())
239  {
240  rRenderContext.DrawGradient(tools::Rectangle(aPos, rRenderContext.PixelToLogic(aSize)),
241  Gradient(GradientStyle::Linear, mrSidebarWin.ColorDark(), mrSidebarWin.ColorDark()));
242  }
243  else
244  {
245  rRenderContext.DrawGradient(tools::Rectangle(aPos, rRenderContext.PixelToLogic(aSize)),
246  Gradient(GradientStyle::Linear, mrSidebarWin.ColorLight(), mrSidebarWin.ColorDark()));
247  }
248  }
249 
250  DoPaint(rRenderContext, rRect);
251 
253  {
254  const AntialiasingFlags nFormerAntialiasing( rRenderContext.GetAntialiasing() );
255  const bool bIsAntiAliasing = officecfg::Office::Common::Drawinglayer::AntiAliasing::get();
256  if ( bIsAntiAliasing )
257  rRenderContext.SetAntialiasing(AntialiasingFlags::Enable);
258  rRenderContext.SetLineColor(mrSidebarWin.GetChangeColor());
259  rRenderContext.DrawLine(rRenderContext.PixelToLogic(aPos),
260  rRenderContext.PixelToLogic(aPos + Point(aSize.Width(),
261  aSize.Height() * 0.95)));
262  rRenderContext.DrawLine(rRenderContext.PixelToLogic(aPos + Point(aSize.Width(),
263  0)),
264  rRenderContext.PixelToLogic(aPos + Point(0,
265  aSize.Height() * 0.95)));
266  if ( bIsAntiAliasing )
267  rRenderContext.SetAntialiasing(nFormerAntialiasing);
268  }
269 }
270 
272 {
273  //let's make sure we see our note
275 }
276 
278 {
279  if (getenv("SW_DEBUG") && rKeyEvt.GetKeyCode().GetCode() == KEY_F12)
280  {
281  if (rKeyEvt.GetKeyCode().IsShift())
282  {
284  return true;
285  }
286  }
287 
288  bool bDone = false;
289 
290  const vcl::KeyCode& rKeyCode = rKeyEvt.GetKeyCode();
291  sal_uInt16 nKey = rKeyCode.GetCode();
292  if ( ( rKeyCode.IsMod1() && rKeyCode.IsMod2() ) &&
293  ( (nKey == KEY_PAGEUP) || (nKey == KEY_PAGEDOWN) ) )
294  {
296  bDone = true;
297  }
298  else if ( nKey == KEY_ESCAPE ||
299  ( rKeyCode.IsMod1() &&
300  ( nKey == KEY_PAGEUP ||
301  nKey == KEY_PAGEDOWN ) ) )
302  {
304  bDone = true;
305  }
306  else if ( rKeyCode.GetFullCode() == KEY_INSERT )
307  {
309  bDone = true;
310  }
311  else
312  {
313  MakeVisible();
314 
316 
318  if ( !( (nKey == KEY_Z || nKey == KEY_Y) && rKeyCode.IsMod1()) )
319  {
320  bool bIsProtected = mrSidebarWin.IsProtected();
321  if ( !bIsProtected || !EditEngine::DoesKeyChangeText(rKeyEvt) )
322  {
323  EditView* pEditView = GetEditView();
324  bDone = pEditView && pEditView->PostKeyEvent(rKeyEvt);
325  }
326  else
327  {
328  std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(GetDrawingArea(), "modules/swriter/ui/inforeadonlydialog.ui"));
329  std::unique_ptr<weld::MessageDialog> xQuery(xBuilder->weld_message_dialog("InfoReadonlyDialog"));
330  xQuery->run();
331  }
332  }
333  if (bDone)
335  else
336  {
337  // write back data first when showing navigator
338  if ( nKey==KEY_F5 )
340  bDone = mrDocView.KeyInput(rKeyEvt);
341  }
342  }
343 
345 
346  return bDone;
347 }
348 
350 {
351  if (EditView* pEditView = GetEditView())
352  {
353  SvtSecurityOptions aSecOpts;
354  bool bExecuteMod = aSecOpts.IsOptionSet( SvtSecurityOptions::EOption::CtrlClickHyperlink);
355 
356  if ( !bExecuteMod || (rMEvt.GetModifier() == KEY_MOD1))
357  {
358  const OutputDevice& rOutDev = pEditView->GetOutputDevice();
359  Point aLogicClick = rOutDev.PixelToLogic(rMEvt.GetPosPixel());
360  if (const SvxFieldItem* pItem = pEditView->GetField(aLogicClick))
361  {
362  const SvxFieldData* pField = pItem->GetField();
363  const SvxURLField* pURL = dynamic_cast<const SvxURLField*>( pField );
364  if ( pURL )
365  {
366  pEditView->MouseButtonDown( rMEvt );
368  const OUString& sURL( pURL->GetURL() );
369  const OUString& sTarget( pURL->GetTargetFrame() );
370  ::LoadURL(rSh, sURL, LoadUrlFlags::NONE, sTarget);
371  return true;
372  }
373  }
374  }
375  }
376 
377  mbMouseDownGainingFocus = !HasFocus();
378  GrabFocus();
379 
380  bool bRet = WeldEditView::MouseButtonDown(rMEvt);
381 
383 
384  return bRet;
385 }
386 
388 {
389  bool bRet = WeldEditView::MouseButtonUp(rMEvt);
390 
392  {
393  MakeVisible();
394  mbMouseDownGainingFocus = false;
395  }
396 
397  return bRet;
398 }
399 
400 IMPL_LINK( SidebarTextControl, OnlineSpellCallback, SpellCallbackInfo&, rInfo, void )
401 {
402  if ( rInfo.nCommand == SpellCallbackCommand::STARTSPELLDLG )
403  {
404  mrDocView.GetViewFrame()->GetDispatcher()->Execute( FN_SPELL_GRAMMAR_DIALOG, SfxCallMode::ASYNCHRON);
405  }
406 }
407 
409 {
410  EditView* pEditView = GetEditView();
411 
412  if ( rCEvt.GetCommand() == CommandEventId::ContextMenu )
413  {
414  if (IsMouseCaptured())
415  ReleaseMouse();
416  if ( !mrSidebarWin.IsProtected() &&
417  pEditView &&
418  pEditView->IsWrongSpelledWordAtPos( rCEvt.GetMousePosPixel(), true ))
419  {
420  Link<SpellCallbackInfo&,void> aLink = LINK(this, SidebarTextControl, OnlineSpellCallback);
421  pEditView->ExecuteSpellPopup(rCEvt.GetMousePosPixel(), aLink);
422  }
423  else
424  {
425  Point aPos;
426  if (rCEvt.IsMouseEvent())
427  aPos = rCEvt.GetMousePosPixel();
428  else
429  {
430  const Size aSize = GetOutputSizePixel();
431  aPos = Point( aSize.getWidth()/2, aSize.getHeight()/2 );
432  }
434  }
435  return true;
436  }
437  else if (rCEvt.GetCommand() == CommandEventId::Wheel)
438  {
439  // if no scrollbar, or extra keys held scroll the document and consume
440  // this event, otherwise don't consume and let the event get to the
441  // surrounding scrolled window
443  {
445  return true;
446  }
447  else
448  {
449  const CommandWheelData* pData = rCEvt.GetWheelData();
450  if (pData->IsShift() || pData->IsMod1() || pData->IsMod2())
451  {
453  return true;
454  }
455  }
456  }
457 
458  return WeldEditView::Command(rCEvt);
459 }
460 
461 } // end of namespace sw::sidebarwindows
462 
463 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
bool IsOptionSet(EOption eOption) const
css::uno::Reference< css::linguistic2::XProofreadingIterator > get(css::uno::Reference< css::uno::XComponentContext > const &context)
SfxViewFrame * GetViewFrame() const
void setEditViewCallbacks(EditViewCallbacks *pEditViewCallbacks)
void ExecuteSpellPopup(const Point &rPosPixel, const Link< SpellCallbackInfo &, void > &rCallBack)
bool IsMod1() const
void SetAntialiasing(AntialiasingFlags nMode)
constexpr sal_uInt16 KEY_MOD1
AntialiasingFlags
OUString const & GetAuthorString(sal_uInt16 nPos=0) const
Definition: docredln.cxx:1800
SwPostItHelper::SwLayoutStatus GetLayoutStatus() const
std::unique_ptr< ContentProperties > pData
SidebarTextControl(sw::annotation::SwAnnotationWin &rSidebarWin, SwView &rDocView, SwPostItMgr &rPostItMgr)
long Long
const StyleSettings & GetStyleSettings() const
static const AllSettings & GetSettings()
constexpr sal_uInt16 KEY_F5
IMPL_LINK(SidebarTextControl, OnlineSpellCallback, SpellCallbackInfo &, rInfo, void)
void InitAccessible()
static weld::Builder * CreateBuilder(weld::Widget *pParent, const OUString &rUIFile, bool bMobile=false)
bool IsShift() const
sal_uInt16 GetCode() const
const CommandWheelData * GetWheelData() const
void DoPaint(vcl::RenderContext &rRenderContext, const tools::Rectangle &rRect)
OUString GetAppLangDateTimeString(const DateTime &)
Definition: uitool.cxx:873
const OUString & GetTargetFrame() const
constexpr sal_uInt16 KEY_Y
void SetMapMode()
AntialiasingFlags GetAntialiasing() const
void ExecutePopup(const OUString &rResName, vcl::Window *pWin=nullptr, const Point *pPos=nullptr)
SwWrtShell & GetWrtShell() const
Definition: view.hxx:413
Used by the UI to modify the document model.
Definition: wrtsh.hxx:93
constexpr tools::Long Width() const
void LoadURL(SwViewShell &rVSh, const OUString &rURL, LoadUrlFlags nFilter, const OUString &rTargetFrameName)
Definition: wrtsh2.cxx:498
void SetBackground()
virtual EditView * GetEditView() const override
void SetCursorLogicPosition(const Point &rPosition, bool bPoint, bool bClearMark)
bool IsMouseEvent() const
const DateTime & GetTimeStamp(sal_uInt16 nPos=0) const
Definition: docredln.cxx:1805
constexpr sal_uInt16 KEY_PAGEUP
bool GetHighContrastMode() const
union SwContentAtPos::@24 aFnd
virtual bool MouseButtonUp(const MouseEvent &rMEvt) override
constexpr tools::Long getHeight() const
virtual OutputDevice & get_ref_device()=0
void DrawLine(const Point &rStartPt, const Point &rEndPt)
virtual void Paint(vcl::RenderContext &rRenderContext, const tools::Rectangle &rRect) override
EditView & GetEditView() const
SwDoc * GetDoc()
returns Doc. But be careful!
Definition: docsh.hxx:203
static bool DoesKeyChangeText(const KeyEvent &rKeyEvent)
void SetLineColor()
virtual void set_cursor(PointerStyle ePointerStyle)=0
virtual bool Command(const CommandEvent &rCEvt) override
virtual OUString RequestHelp(tools::Rectangle &rRect) override
void SetDrawingArea(weld::DrawingArea *pDrawingArea) override
void dumpAsXml(xmlTextWriterPtr=nullptr) const
Dumps the entire nodes structure to the given destination (file nodes.xml in the current directory by...
Definition: docfmt.cxx:1937
bool IsMod2() const
EditEngine * GetEditEngine() const
SfxBindings & GetBindings()
void SetRefDevice(OutputDevice *pRefDef)
const Color & GetChangeColor() const
void MakeVisible(const sw::annotation::SwAnnotationWin *pPostIt)
Definition: PostItMgr.cxx:1069
CommandEventId GetCommand() const
constexpr sal_uInt16 KEY_PAGEDOWN
std::unique_ptr< EditView > m_xEditView
virtual void GetFocus() override
void SwitchToPostIt(sal_uInt16 aDirection)
const AllSettings & GetSettings() const
virtual bool MouseButtonDown(const MouseEvent &rMEvt) override
sal_uInt16 GetModifier() const
void ResizeIfNecessary(tools::Long aOldHeight, tools::Long aNewHeight)
SwDocShell * GetDocShell()
Definition: view.cxx:1122
virtual bool MouseButtonUp(const MouseEvent &rMEvt) override
constexpr Point TopLeft() const
const OUString & GetURL() const
const Point & GetMousePosPixel() const
SAL_WARN_UNUSED_RESULT Point PixelToLogic(const Point &rDevicePt) const
virtual bool KeyInput(const KeyEvent &rKeyEvt) override
void SetPaperSize(const Size &rSize)
const vcl::KeyCode & GetKeyCode() const
bool PostKeyEvent(const KeyEvent &rKeyEvent, vcl::Window const *pFrameWin=nullptr)
virtual bool MouseButtonDown(const MouseEvent &rMEvt) override
bool IsShift() const
bool IsMouseOver() const
#define FN_SPELL_GRAMMAR_DIALOG
Definition: cmdid.h:602
constexpr tools::Long Height() const
constexpr sal_uInt16 KEY_ESCAPE
constexpr sal_uInt16 KEY_F12
bool IsMod1() const
virtual void SetDrawingArea(weld::DrawingArea *pDrawingArea)
const Color & GetWindowColor() const
bool IsWrongSpelledWordAtPos(const Point &rPosPixel, bool bMarkIfWrong=false)
const Point & GetPosPixel() const
sal_uInt16 GetFullCode() const
const SwRangeRedline * pRedl
Definition: crsrsh.hxx:97
void SetOutputArea(const tools::Rectangle &rRect)
void setHeight(tools::Long nHeight)
virtual bool KeyInput(const KeyEvent &rKeyEvent)
constexpr sal_uInt16 KEY_Z
void InvalidateAll(bool bWithMsg)
virtual void LoseFocus() override
bool HandleWheelCommands(const CommandEvent &)
Definition: viewport.cxx:1200
constexpr tools::Long getWidth() const
bool GetContentAtPos(const Point &rPt, SwContentAtPos &rContentAtPos, bool bSetCursor=false, SwRect *pFieldRect=nullptr)
Definition: crstrvl.cxx:1255
virtual bool Command(const CommandEvent &rCEvt) override
constexpr sal_uInt16 KEY_INSERT
void SetBackgroundColor(const Color &rColor)
virtual OutputDevice & EditViewOutputDevice() const override
OUString SwResId(std::string_view aId)
Definition: swmodule.cxx:165
virtual void set_size_request(int nWidth, int nHeight)=0
static OUString GetURLHelpText(std::u16string_view)
void Push(PushFlags nFlags=PushFlags::ALL)
virtual void EditViewScrollStateChange() override
void DrawGradient(const tools::Rectangle &rRect, const Gradient &rGradient)
sw::annotation::SwAnnotationWin & mrSidebarWin
virtual EditEngine * GetEditEngine() const override
void DrawForPage(OutputDevice *pDev, const Point &rPos)
Definition: view.hxx:144
const SvxFieldData * GetField() const
bool IsMod2() const