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  // For tdf#143443 note we want an 'infinite' height initially (which is the
116  // editengines default). For tdf#144686 it is helpful if the initial width
117  // is the "SidebarWidth" so the calculated text height is always meaningful
118  // for layout in the sidebar.
119  Size aPaperSize(mrPostItMgr.GetSidebarWidth(), pEditEngine->GetPaperSize().Height());
120  pEditEngine->SetPaperSize(aPaperSize);
121  pEditEngine->SetRefDevice(&rDevice);
122 
123  pEditView->SetOutputArea(tools::Rectangle(Point(0, 0), aOutputSize));
124  pEditView->SetBackgroundColor(aBgColor);
125 
126  pDrawingArea->set_cursor(PointerStyle::Text);
127 
128  InitAccessible();
129 }
130 
131 void SidebarTextControl::SetCursorLogicPosition(const Point& rPosition, bool bPoint, bool bClearMark)
132 {
133  Point aMousePos = EditViewOutputDevice().PixelToLogic(rPosition);
134  m_xEditView->SetCursorLogicPosition(aMousePos, bPoint, bClearMark);
135 }
136 
138 {
140  if ( !mrSidebarWin.IsMouseOver() )
141  Invalidate();
143 }
144 
146 {
147  // write the visible text back into the SwField
149 
151  if ( !mrSidebarWin.IsMouseOver() )
152  {
153  Invalidate();
154  }
155  // set false for autoscroll to typing location
156  mrSidebarWin.LockView(false);
157 }
158 
160 {
161  if (EditView* pEditView = GetEditView())
162  {
163  Point aPos = rHelpRect.TopLeft();
164 
165  const OutputDevice& rOutDev = pEditView->GetOutputDevice();
166  Point aLogicClick = rOutDev.PixelToLogic(aPos);
167  const SvxFieldItem* pItem = pEditView->GetField(aLogicClick);
168  if (pItem)
169  {
170  const SvxFieldData* pField = pItem->GetField();
171  const SvxURLField* pURL = dynamic_cast<const SvxURLField*>( pField );
172  if (pURL)
173  {
174  rHelpRect = tools::Rectangle(aPos, Size(50, 10));
175  return SfxHelp::GetURLHelpText(pURL->GetURL());
176  }
177  }
178  }
179 
180  TranslateId pResId;
181  switch( mrSidebarWin.GetLayoutStatus() )
182  {
183  case SwPostItHelper::INSERTED: pResId = STR_REDLINE_INSERT; break;
184  case SwPostItHelper::DELETED: pResId = STR_REDLINE_DELETE; break;
185  default: break;
186  }
187 
188  SwContentAtPos aContentAtPos( IsAttrAtPos::Redline );
189  if ( pResId &&
191  {
192  OUString sText = SwResId(pResId) + ": " +
193  aContentAtPos.aFnd.pRedl->GetAuthorString() + " - " +
194  GetAppLangDateTimeString( aContentAtPos.aFnd.pRedl->GetTimeStamp() );
195  return sText;
196  }
197 
198  return OUString();
199 }
200 
202 {
204 }
205 
206 void SidebarTextControl::DrawForPage(OutputDevice* pDev, const Point& rPt)
207 {
208  //Take the control's height, but overwrite the scrollbar area if there was one
209  OutputDevice& rDevice = GetDrawingArea()->get_ref_device();
210  Size aSize(rDevice.PixelToLogic(GetOutputSizePixel()));
211 
212  if (OutlinerView* pOutlinerView = mrSidebarWin.GetOutlinerView())
213  {
214  pOutlinerView->GetOutliner()->Draw(*pDev, tools::Rectangle(rPt, aSize));
215  }
216 
218  return;
219 
221 
223  Point aBottomRight(rPt);
224  aBottomRight.Move(aSize);
225  pDev->DrawLine(rPt, aBottomRight);
226 
227  Point aTopRight(rPt);
228  aTopRight.Move(Size(aSize.Width(), 0));
229 
230  Point aBottomLeft(rPt);
231  aBottomLeft.Move(Size(0, aSize.Height()));
232 
233  pDev->DrawLine(aTopRight, aBottomLeft);
234 
235  pDev->Pop();
236 }
237 
239 {
240  Size aSize = GetOutputSizePixel();
241  Point aPos;
242 
243  if (!rRenderContext.GetSettings().GetStyleSettings().GetHighContrastMode())
244  {
245  if (mrSidebarWin.IsMouseOverSidebarWin() || HasFocus())
246  {
247  rRenderContext.DrawGradient(tools::Rectangle(aPos, rRenderContext.PixelToLogic(aSize)),
248  Gradient(GradientStyle::Linear, mrSidebarWin.ColorDark(), mrSidebarWin.ColorDark()));
249  }
250  else
251  {
252  rRenderContext.DrawGradient(tools::Rectangle(aPos, rRenderContext.PixelToLogic(aSize)),
253  Gradient(GradientStyle::Linear, mrSidebarWin.ColorLight(), mrSidebarWin.ColorDark()));
254  }
255  }
256 
257  DoPaint(rRenderContext, rRect);
258 
260  return;
261 
262  const AntialiasingFlags nFormerAntialiasing( rRenderContext.GetAntialiasing() );
263  const bool bIsAntiAliasing = officecfg::Office::Common::Drawinglayer::AntiAliasing::get();
264  if ( bIsAntiAliasing )
265  rRenderContext.SetAntialiasing(AntialiasingFlags::Enable);
266  rRenderContext.SetLineColor(mrSidebarWin.GetChangeColor());
267  rRenderContext.DrawLine(rRenderContext.PixelToLogic(aPos),
268  rRenderContext.PixelToLogic(aPos + Point(aSize.Width(),
269  aSize.Height() * 0.95)));
270  rRenderContext.DrawLine(rRenderContext.PixelToLogic(aPos + Point(aSize.Width(),
271  0)),
272  rRenderContext.PixelToLogic(aPos + Point(0,
273  aSize.Height() * 0.95)));
274  if ( bIsAntiAliasing )
275  rRenderContext.SetAntialiasing(nFormerAntialiasing);
276 }
277 
279 {
280  //let's make sure we see our note
282 }
283 
285 {
286  if (getenv("SW_DEBUG") && rKeyEvt.GetKeyCode().GetCode() == KEY_F12)
287  {
288  if (rKeyEvt.GetKeyCode().IsShift())
289  {
291  return true;
292  }
293  }
294 
295  bool bDone = false;
296 
297  const vcl::KeyCode& rKeyCode = rKeyEvt.GetKeyCode();
298  sal_uInt16 nKey = rKeyCode.GetCode();
299  if ( ( rKeyCode.IsMod1() && rKeyCode.IsMod2() ) &&
300  ( (nKey == KEY_PAGEUP) || (nKey == KEY_PAGEDOWN) ) )
301  {
303  bDone = true;
304  }
305  else if ( nKey == KEY_ESCAPE ||
306  ( rKeyCode.IsMod1() &&
307  ( nKey == KEY_PAGEUP ||
308  nKey == KEY_PAGEDOWN ) ) )
309  {
311  bDone = true;
312  }
313  else if ( rKeyCode.GetFullCode() == KEY_INSERT )
314  {
316  bDone = true;
317  }
318  else
319  {
320  MakeVisible();
321 
323 
325  if ( !( (nKey == KEY_Z || nKey == KEY_Y) && rKeyCode.IsMod1()) )
326  {
327  bool bIsProtected = mrSidebarWin.IsProtected();
328  if ( !bIsProtected || !EditEngine::DoesKeyChangeText(rKeyEvt) )
329  {
330  EditView* pEditView = GetEditView();
331  bDone = pEditView && pEditView->PostKeyEvent(rKeyEvt);
332  }
333  else
334  {
335  std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(GetDrawingArea(), "modules/swriter/ui/inforeadonlydialog.ui"));
336  std::unique_ptr<weld::MessageDialog> xQuery(xBuilder->weld_message_dialog("InfoReadonlyDialog"));
337  xQuery->run();
338  }
339  }
340  if (bDone)
342  else
343  {
344  // write back data first when showing navigator
345  if ( nKey==KEY_F5 )
347  bDone = mrDocView.KeyInput(rKeyEvt);
348  }
349  }
350 
352 
353  return bDone;
354 }
355 
357 {
358  if (EditView* pEditView = GetEditView())
359  {
361 
362  if ( !bExecuteMod || (rMEvt.GetModifier() == KEY_MOD1))
363  {
364  const OutputDevice& rOutDev = pEditView->GetOutputDevice();
365  Point aLogicClick = rOutDev.PixelToLogic(rMEvt.GetPosPixel());
366  if (const SvxFieldItem* pItem = pEditView->GetField(aLogicClick))
367  {
368  const SvxFieldData* pField = pItem->GetField();
369  const SvxURLField* pURL = dynamic_cast<const SvxURLField*>( pField );
370  if ( pURL )
371  {
372  pEditView->MouseButtonDown( rMEvt );
374  const OUString& sURL( pURL->GetURL() );
375  const OUString& sTarget( pURL->GetTargetFrame() );
376  ::LoadURL(rSh, sURL, LoadUrlFlags::NONE, sTarget);
377  return true;
378  }
379  }
380  }
381  }
382 
383  mbMouseDownGainingFocus = !HasFocus();
384  GrabFocus();
385 
386  bool bRet = WeldEditView::MouseButtonDown(rMEvt);
387 
389 
390  return bRet;
391 }
392 
394 {
395  bool bRet = WeldEditView::MouseButtonUp(rMEvt);
396 
398  {
399  MakeVisible();
400  mbMouseDownGainingFocus = false;
401  }
402 
403  return bRet;
404 }
405 
406 IMPL_LINK( SidebarTextControl, OnlineSpellCallback, SpellCallbackInfo&, rInfo, void )
407 {
408  if ( rInfo.nCommand == SpellCallbackCommand::STARTSPELLDLG )
409  {
410  mrDocView.GetViewFrame()->GetDispatcher()->Execute( FN_SPELL_GRAMMAR_DIALOG, SfxCallMode::ASYNCHRON);
411  }
412 }
413 
415 {
416  EditView* pEditView = GetEditView();
417 
418  if ( rCEvt.GetCommand() == CommandEventId::ContextMenu )
419  {
420  if (IsMouseCaptured())
421  ReleaseMouse();
422  if ( !mrSidebarWin.IsProtected() &&
423  pEditView &&
424  pEditView->IsWrongSpelledWordAtPos( rCEvt.GetMousePosPixel(), true ))
425  {
426  Link<SpellCallbackInfo&,void> aLink = LINK(this, SidebarTextControl, OnlineSpellCallback);
427  pEditView->ExecuteSpellPopup(rCEvt.GetMousePosPixel(), aLink);
428  }
429  else
430  {
431  Point aPos;
432  if (rCEvt.IsMouseEvent())
433  aPos = rCEvt.GetMousePosPixel();
434  else
435  {
436  const Size aSize = GetOutputSizePixel();
437  aPos = Point( aSize.getWidth()/2, aSize.getHeight()/2 );
438  }
440  }
441  return true;
442  }
443  else if (rCEvt.GetCommand() == CommandEventId::Wheel)
444  {
445  // if no scrollbar, or extra keys held scroll the document and consume
446  // this event, otherwise don't consume and let the event get to the
447  // surrounding scrolled window
449  {
451  return true;
452  }
453  else
454  {
455  const CommandWheelData* pData = rCEvt.GetWheelData();
456  if (pData->IsShift() || pData->IsMod1() || pData->IsMod2())
457  {
459  return true;
460  }
461  }
462  }
463 
464  return WeldEditView::Command(rCEvt);
465 }
466 
467 } // end of namespace sw::sidebarwindows
468 
469 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
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 IsOptionSet(EOption eOption)
bool IsMod1() const
void SetAntialiasing(AntialiasingFlags nMode)
constexpr sal_uInt16 KEY_MOD1
AntialiasingFlags
OUString const & GetAuthorString(sal_uInt16 nPos=0) const
Definition: docredln.cxx:1918
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()
void Push(vcl::PushFlags nFlags=vcl::PushFlags::ALL)
constexpr sal_uInt16 KEY_F5
IMPL_LINK(SidebarTextControl, OnlineSpellCallback, SpellCallbackInfo &, rInfo, void)
void InitAccessible()
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:870
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
OUString SwResId(TranslateId aId)
Definition: swmodule.cxx:165
constexpr tools::Long Width() const
void LoadURL(SwViewShell &rVSh, const OUString &rURL, LoadUrlFlags nFilter, const OUString &rTargetFrameName)
Definition: wrtsh2.cxx:504
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:1923
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:204
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:1950
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:1074
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
tools::ULong GetSidebarWidth(bool bPx=false) const
Definition: PostItMgr.cxx:2107
void ResizeIfNecessary(tools::Long aOldHeight, tools::Long aNewHeight)
SwDocShell * GetDocShell()
Definition: view.cxx:1132
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:603
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:98
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
const Size & GetPaperSize() const
bool GetContentAtPos(const Point &rPt, SwContentAtPos &rContentAtPos, bool bSetCursor=false, SwRect *pFieldRect=nullptr)
Definition: crstrvl.cxx:1276
virtual bool Command(const CommandEvent &rCEvt) override
constexpr sal_uInt16 KEY_INSERT
void SetBackgroundColor(const Color &rColor)
virtual OutputDevice & EditViewOutputDevice() const override
virtual void set_size_request(int nWidth, int nHeight)=0
static OUString GetURLHelpText(std::u16string_view)
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
static std::unique_ptr< weld::Builder > CreateBuilder(weld::Widget *pParent, const OUString &rUIFile, bool bMobile=false, sal_uInt64 nLOKWindowId=0)
const SvxFieldData * GetField() const
bool IsMod2() const