LibreOffice Module sw (master)  1
AnnotationWin2.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 <config_wasm_strip.h>
21 
22 #include <sal/config.h>
23 
24 #include <cstddef>
25 
26 #include "SidebarWinAcc.hxx"
27 #include <PostItMgr.hxx>
28 #include <AnnotationWin.hxx>
29 #include <IDocumentUndoRedo.hxx>
31 #include "SidebarTxtControl.hxx"
32 #include "AnchorOverlayObject.hxx"
33 #include "ShadowOverlayObject.hxx"
34 #include "OverlayRanges.hxx"
35 
36 #include <strings.hrc>
37 
38 #include <viewopt.hxx>
39 #include <cmdid.h>
40 
41 #include <editeng/fhgtitem.hxx>
42 #include <editeng/langitem.hxx>
43 #include <editeng/editview.hxx>
44 #include <editeng/outliner.hxx>
45 #include <editeng/editeng.hxx>
46 #include <editeng/eeitem.hxx>
47 #include <editeng/outlobj.hxx>
48 
49 #include <svl/undo.hxx>
50 #include <svl/stritem.hxx>
51 
52 #include <sfx2/viewfrm.hxx>
53 #include <sfx2/bindings.hxx>
54 #include <sfx2/dispatch.hxx>
55 
56 #include <vcl/decoview.hxx>
57 #include <vcl/event.hxx>
58 #include <vcl/gradient.hxx>
59 #include <vcl/svapp.hxx>
60 #include <vcl/settings.hxx>
61 #include <vcl/ptrstyle.hxx>
62 #include <vcl/uitest/logger.hxx>
64 
65 #include <edtwin.hxx>
66 #include <view.hxx>
67 #include <docsh.hxx>
68 #include <wrtsh.hxx>
69 #include <doc.hxx>
70 #include <swmodule.hxx>
71 
72 #include <SwRewriter.hxx>
73 #include <txtannotationfld.hxx>
74 #include <ndtxt.hxx>
75 
78 #include <osl/diagnose.h>
80 #include <unotools/syslocale.hxx>
81 #include <memory>
82 #include <comphelper/lok.hxx>
83 
84 using namespace sw::sidebarwindows;
85 
86 namespace
87 {
88 
89 void collectUIInformation( const OUString& aevent , const OUString& aID )
90 {
91  EventDescription aDescription;
92  aDescription.aID = aID;
93  aDescription.aParameters = {{"" , ""}};
94  aDescription.aAction = aevent;
95  aDescription.aParent = "MainWindow";
96  aDescription.aKeyWord = "SwEditWinUIObject";
97  UITestLogger::getInstance().logEvent(aDescription);
98 }
99 
100 }
101 
102 namespace sw::annotation {
103 
104 #define METABUTTON_WIDTH 16
105 #define METABUTTON_HEIGHT 18
106 #define POSTIT_MINIMUMSIZE_WITHOUT_META 50
107 
108 void SwAnnotationWin::PaintTile(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect)
109 {
110  bool bMenuButtonVisible = mxMenuButton->get_visible();
111  // No point in showing this button till click on it are not handled.
112  if (bMenuButtonVisible)
113  mxMenuButton->hide();
114 
115  // draw left over space
116  if (Application::GetSettings().GetStyleSettings().GetHighContrastMode())
117  rRenderContext.SetFillColor(COL_BLACK);
118  else
119  rRenderContext.SetFillColor(mColorDark);
120  rRenderContext.SetLineColor();
121  rRenderContext.DrawRect(rRect);
122 
123  m_xContainer->draw(rRenderContext, rRect.TopLeft(), GetSizePixel());
124 
125  const drawinglayer::geometry::ViewInformation2D aViewInformation;
126  std::unique_ptr<drawinglayer::processor2d::BaseProcessor2D> pProcessor(drawinglayer::processor2d::createBaseProcessor2DFromOutputDevice(rRenderContext, aViewInformation));
127 
128  // drawinglayer sets the map mode to pixels, not needed here.
129  rRenderContext.Pop();
130  // Work in document-global twips.
131  rRenderContext.Pop();
132  if (mpAnchor)
133  pProcessor->process(mpAnchor->getOverlayObjectPrimitive2DSequence());
134  if (mpTextRangeOverlay)
135  pProcessor->process(mpTextRangeOverlay->getOverlayObjectPrimitive2DSequence());
136 
137  rRenderContext.Push(vcl::PushFlags::NONE);
138  pProcessor.reset();
139  rRenderContext.Push(vcl::PushFlags::NONE);
140 
141  if (bMenuButtonVisible)
142  mxMenuButton->show();
143 }
144 
145 bool SwAnnotationWin::IsHitWindow(const Point& rPointLogic)
146 {
147  tools::Rectangle aRectangleLogic(EditWin().PixelToLogic(GetPosPixel()), EditWin().PixelToLogic(GetSizePixel()));
148  return aRectangleLogic.Contains(rPointLogic);
149 }
150 
151 void SwAnnotationWin::SetCursorLogicPosition(const Point& rPosition, bool bPoint, bool bClearMark)
152 {
153  mxSidebarTextControl->SetCursorLogicPosition(rPosition, bPoint, bClearMark);
154 }
155 
156 void SwAnnotationWin::DrawForPage(OutputDevice* pDev, const Point& rPt)
157 {
158  // tdf#143511 unclip SysObj so get_extents_relative_to of children
159  // of the SysObj can provide meaningful results
160  UnclipVisibleSysObj();
161 
162  pDev->Push();
163 
164  pDev->SetFillColor(mColorDark);
165  pDev->SetLineColor();
166 
167  pDev->SetTextColor(mColorAnchor);
168  vcl::Font aFont = maLabelFont;
169  aFont.SetFontHeight(aFont.GetFontHeight() * 20);
170  pDev->SetFont(aFont);
171 
172  Size aSz = PixelToLogic(GetSizePixel());
173 
174  pDev->DrawRect(tools::Rectangle(rPt, aSz));
175 
176  if (mxMetadataAuthor->get_visible())
177  {
178  int x, y, width, height;
179  mxMetadataAuthor->get_extents_relative_to(*m_xContainer, x, y, width, height);
180  Point aPos(rPt + PixelToLogic(Point(x, y)));
181  Size aSize(PixelToLogic(Size(width, height)));
182 
184  pDev->IntersectClipRegion(tools::Rectangle(aPos, aSize));
185  pDev->DrawText(aPos, mxMetadataAuthor->get_label());
186  pDev->Pop();
187  }
188 
189  if (mxMetadataDate->get_visible())
190  {
191  int x, y, width, height;
192  mxMetadataDate->get_extents_relative_to(*m_xContainer, x, y, width, height);
193  Point aPos(rPt + PixelToLogic(Point(x, y)));
194  Size aSize(PixelToLogic(Size(width, height)));
195 
197  pDev->IntersectClipRegion(tools::Rectangle(aPos, aSize));
198  pDev->DrawText(aPos, mxMetadataDate->get_label());
199  pDev->Pop();
200  }
201 
202  if (mxMetadataResolved->get_visible())
203  {
204  int x, y, width, height;
205  mxMetadataResolved->get_extents_relative_to(*m_xContainer, x, y, width, height);
206  Point aPos(rPt + PixelToLogic(Point(x, y)));
207  Size aSize(PixelToLogic(Size(width, height)));
208 
210  pDev->IntersectClipRegion(tools::Rectangle(aPos, aSize));
211  pDev->DrawText(aPos, mxMetadataResolved->get_label());
212  pDev->Pop();
213  }
214 
215  mxSidebarTextControl->DrawForPage(pDev, rPt);
216 
217  const drawinglayer::geometry::ViewInformation2D aNewViewInfos;
218  std::unique_ptr<drawinglayer::processor2d::BaseProcessor2D> pProcessor(
220  *pDev, aNewViewInfos ));
221 
222  if (mpAnchor)
223  pProcessor->process(mpAnchor->getOverlayObjectPrimitive2DSequence());
224  if (mpTextRangeOverlay)
225  pProcessor->process(mpTextRangeOverlay->getOverlayObjectPrimitive2DSequence());
226  pProcessor.reset();
227 
228  if (mxVScrollbar->get_vpolicy() != VclPolicyType::NEVER)
229  {
230  // if there is a scrollbar shown, draw "..." to indicate the comment isn't
231  // completely shown
232  int x, y, width, height;
233  mxMenuButton->get_extents_relative_to(*m_xContainer, x, y, width, height);
234  Point aPos(rPt + PixelToLogic(Point(x, y)));
235  pDev->DrawText(aPos, "...");
236  }
237 
238  pDev->Pop();
239 }
240 
241 void SwAnnotationWin::SetPosSizePixelRect(tools::Long nX, tools::Long nY, tools::Long nWidth, tools::Long nHeight,
242  const SwRect& aAnchorRect, const tools::Long aPageBorder)
243 {
244  mPosSize = tools::Rectangle(Point(nX,nY),Size(nWidth,nHeight));
245  if (!mAnchorRect.IsEmpty() && mAnchorRect != aAnchorRect)
246  mbAnchorRectChanged = true;
247  mAnchorRect = aAnchorRect;
248  mPageBorder = aPageBorder;
249 }
250 
251 void SwAnnotationWin::SetSize( const Size& rNewSize )
252 {
253  mPosSize.SetSize(rNewSize);
254 }
255 
256 void SwAnnotationWin::SetVirtualPosSize( const Point& aPoint, const Size& aSize)
257 {
258  mPosSize = tools::Rectangle(aPoint,aSize);
259 }
260 
261 void SwAnnotationWin::TranslateTopPosition(const tools::Long aAmount)
262 {
263  mPosSize.Move(0,aAmount);
264 }
265 
266 void SwAnnotationWin::ShowAnchorOnly(const Point &aPoint)
267 {
268  HideNote();
269  SetPosAndSize();
270  if (mpAnchor)
271  {
272  mpAnchor->SetSixthPosition(basegfx::B2DPoint(aPoint.X(),aPoint.Y()));
273  mpAnchor->SetSeventhPosition(basegfx::B2DPoint(aPoint.X(),aPoint.Y()));
274  mpAnchor->SetAnchorState(AnchorState::All);
275  mpAnchor->setVisible(true);
276  }
277  if (mpShadow)
278  mpShadow->setVisible(false);
279 }
280 
281 SfxItemSet SwAnnotationWin::DefaultItem()
282 {
283  SfxItemSet aItem( mrView.GetDocShell()->GetPool() );
284  aItem.Put(SvxFontHeightItem(200,100,EE_CHAR_FONTHEIGHT));
285  return aItem;
286 }
287 
288 void SwAnnotationWin::InitControls()
289 {
290  // window controls for author and date
291  mxMetadataAuthor = m_xBuilder->weld_label("author");
292  mxMetadataAuthor->set_accessible_name( SwResId( STR_ACCESS_ANNOTATION_AUTHOR_NAME ) );
293  mxMetadataAuthor->set_direction(AllSettings::GetLayoutRTL());
294 
296  maLabelFont.SetFontHeight(8);
297 
298  // we should leave this setting alone, but for this we need a better layout algo
299  // with variable meta size height
300  mxMetadataAuthor->set_font(maLabelFont);
301 
302  mxMetadataDate = m_xBuilder->weld_label("date");
303  mxMetadataDate->set_accessible_name( SwResId( STR_ACCESS_ANNOTATION_DATE_NAME ) );
304  mxMetadataDate->set_direction(AllSettings::GetLayoutRTL());
305  mxMetadataDate->connect_mouse_move(LINK(this, SwAnnotationWin, MouseMoveHdl));
306 
307  // we should leave this setting alone, but for this we need a better layout algo
308  // with variable meta size height
309  mxMetadataDate->set_font(maLabelFont);
310 
311  mxMetadataResolved = m_xBuilder->weld_label("resolved");
312  mxMetadataResolved->set_accessible_name( SwResId( STR_ACCESS_ANNOTATION_RESOLVED_NAME ) );
313  mxMetadataResolved->set_direction(AllSettings::GetLayoutRTL());
314  mxMetadataResolved->connect_mouse_move(LINK(this, SwAnnotationWin, MouseMoveHdl));
315 
316  // we should leave this setting alone, but for this we need a better layout algo
317  // with variable meta size height
318  mxMetadataResolved->set_font(maLabelFont);
319  mxMetadataResolved->set_label(SwResId(STR_ACCESS_ANNOTATION_RESOLVED_NAME));
320 
321  SwDocShell* aShell = mrView.GetDocShell();
322  mpOutliner.reset(new Outliner(&aShell->GetPool(),OutlinerMode::TextObject));
323  aShell->GetDoc()->SetCalcFieldValueHdl( mpOutliner.get() );
324  mpOutliner->SetUpdateLayout( true );
325 
326  mpOutlinerView.reset(new OutlinerView(mpOutliner.get(), nullptr));
327  mpOutliner->InsertView(mpOutlinerView.get());
328 
329  //create Scrollbars
330  mxVScrollbar = m_xBuilder->weld_scrolled_window("scrolledwindow", true);
331 
332  mxMenuButton = m_xBuilder->weld_menu_button("menubutton");
333  mxMenuButton->set_size_request(METABUTTON_WIDTH, METABUTTON_HEIGHT);
334 
335  // actual window which holds the user text
336  mxSidebarTextControl.reset(new SidebarTextControl(*this, mrView, mrMgr));
337  mxSidebarTextControlWin.reset(new weld::CustomWeld(*m_xBuilder, "editview", *mxSidebarTextControl));
338  mxSidebarTextControl->SetPointer(PointerStyle::Text);
339 
340  Rescale();
341 
342  mpOutlinerView->SetBackgroundColor(COL_TRANSPARENT);
343  mpOutlinerView->SetOutputArea( PixelToLogic( tools::Rectangle(0,0,1,1) ) );
344 
345  mpOutlinerView->SetAttribs(DefaultItem());
346 
347  mxVScrollbar->set_direction(false);
348  mxVScrollbar->connect_vadjustment_changed(LINK(this, SwAnnotationWin, ScrollHdl));
349  mxVScrollbar->connect_mouse_move(LINK(this, SwAnnotationWin, MouseMoveHdl));
350 
351  const SwViewOption* pVOpt = mrView.GetWrtShellPtr()->GetViewOptions();
352  EEControlBits nCntrl = mpOutliner->GetControlWord();
353  // TODO: crash when AUTOCOMPLETE enabled
354  nCntrl |= EEControlBits::MARKFIELDS | EEControlBits::PASTESPECIAL | EEControlBits::AUTOCORRECT | EEControlBits::USECHARATTRIBS; // | EEControlBits::AUTOCOMPLETE;
356  nCntrl |= EEControlBits::MARKFIELDS;
357  else
358  nCntrl &= ~EEControlBits::MARKFIELDS;
359  if (pVOpt->IsOnlineSpell())
360  nCntrl |= EEControlBits::ONLINESPELLING;
361  else
362  nCntrl &= ~EEControlBits::ONLINESPELLING;
363  mpOutliner->SetControlWord(nCntrl);
364 
365  std::size_t aIndex = SW_MOD()->InsertRedlineAuthor(GetAuthor());
366  SetColor( SwPostItMgr::GetColorDark(aIndex),
369 
370  CheckMetaText();
371 
372  // expand %1 "Author"
373  OUString aText = mxMenuButton->get_item_label("deleteby");
374  SwRewriter aRewriter;
375  aRewriter.AddRule(UndoArg1, GetAuthor());
376  aText = aRewriter.Apply(aText);
377  mxMenuButton->set_item_label("deleteby", aText);
378 
379  mxMenuButton->set_accessible_name(SwResId(STR_ACCESS_ANNOTATION_BUTTON_NAME));
380  mxMenuButton->set_accessible_description(SwResId(STR_ACCESS_ANNOTATION_BUTTON_DESC));
381  mxMenuButton->set_tooltip_text(SwResId(STR_ACCESS_ANNOTATION_BUTTON_DESC));
382 
383  mxMenuButton->connect_toggled(LINK(this, SwAnnotationWin, ToggleHdl));
384  mxMenuButton->connect_selected(LINK(this, SwAnnotationWin, SelectHdl));
385  mxMenuButton->connect_key_press(LINK(this, SwAnnotationWin, KeyInputHdl));
386  mxMenuButton->connect_mouse_move(LINK(this, SwAnnotationWin, MouseMoveHdl));
387 
389  GetOutlinerView()->StartSpeller(mxSidebarTextControl->GetDrawingArea());
390  SetPostItText();
391  mpOutliner->CompleteOnlineSpelling();
392 
393  mxSidebarTextControl->Show();
394  mxMetadataAuthor->show();
395  mxMetadataDate->show();
396  mxMetadataResolved->set_visible(IsResolved());
397  mxVScrollbar->set_vpolicy(VclPolicyType::ALWAYS);
398 }
399 
400 void SwAnnotationWin::CheckMetaText()
401 {
402  const SvtSysLocale aSysLocale;
403  const LocaleDataWrapper& rLocalData = aSysLocale.GetLocaleData();
404  OUString sMeta = GetAuthor();
405  if (sMeta.isEmpty())
406  {
407  sMeta = SwResId(STR_NOAUTHOR);
408  }
409  else if (sMeta.getLength() > 23)
410  {
411  sMeta = OUString::Concat(sMeta.subView(0, 20)) + "...";
412  }
413  if ( mxMetadataAuthor->get_label() != sMeta )
414  {
415  mxMetadataAuthor->set_label(sMeta);
416  }
417 
418  Date aDate = GetDate();
419  if (aDate.IsValidAndGregorian() )
420  {
421  sMeta = rLocalData.getDate(aDate);
422  }
423  else
424  {
425  sMeta = SwResId(STR_NODATE);
426  }
427  if (GetTime().GetTime()!=0)
428  {
429  sMeta += " " + rLocalData.getTime( GetTime(),false );
430  }
431  if ( mxMetadataDate->get_label() != sMeta )
432  {
433  mxMetadataDate->set_label(sMeta);
434  }
435 
436  std::size_t aIndex = SW_MOD()->InsertRedlineAuthor(GetAuthor());
437  SetColor( SwPostItMgr::GetColorDark(aIndex),
440 }
441 
442 static Color ColorFromAlphaColor(const sal_uInt8 aTransparency, const Color& aFront, const Color& aBack)
443 {
444  return Color(sal_uInt8(aFront.GetRed() * aTransparency / 255.0 + aBack.GetRed() * (1 - aTransparency / 255.0)),
445  sal_uInt8(aFront.GetGreen() * aTransparency / 255.0 + aBack.GetGreen() * (1 - aTransparency / 255.0)),
446  sal_uInt8(aFront.GetBlue() * aTransparency / 255.0 + aBack.GetBlue() * (1 - aTransparency / 255.0)));
447 }
448 
449 void SwAnnotationWin::SetMenuButtonColors()
450 {
451  if (!mxMenuButton)
452  return;
453 
454  mxMenuButton->set_background(mColorDark);
455 
456  const Fraction& rFraction = mrView.GetWrtShellPtr()->GetOut()->GetMapMode().GetScaleY();
457 
459  Size aSize(tools::Long(METABUTTON_WIDTH * rFraction),
460  tools::Long(METABUTTON_HEIGHT * rFraction));
461  tools::Rectangle aRect(Point(0, 0), aSize);
462  xVirDev->SetOutputSizePixel(aSize);
463 
464  Gradient aGradient(GradientStyle::Linear,
465  ColorFromAlphaColor(15, mColorAnchor, mColorDark),
466  ColorFromAlphaColor(80, mColorAnchor, mColorDark));
467  xVirDev->DrawGradient(aRect, aGradient);
468 
469  //draw rect around button
470  xVirDev->SetFillColor();
471  xVirDev->SetLineColor(ColorFromAlphaColor(90, mColorAnchor, mColorDark));
472  xVirDev->DrawRect(aRect);
473 
474  tools::Rectangle aSymbolRect(aRect);
475  // 25% distance to the left and right button border
476  const tools::Long nBorderDistanceLeftAndRight = ((aSymbolRect.GetWidth() * 250) + 500) / 1000;
477  aSymbolRect.AdjustLeft(nBorderDistanceLeftAndRight );
478  aSymbolRect.AdjustRight( -nBorderDistanceLeftAndRight );
479  // 40% distance to the top button border
480  const tools::Long nBorderDistanceTop = ((aSymbolRect.GetHeight() * 400) + 500) / 1000;
481  aSymbolRect.AdjustTop(nBorderDistanceTop );
482  // 15% distance to the bottom button border
483  const tools::Long nBorderDistanceBottom = ((aSymbolRect.GetHeight() * 150) + 500) / 1000;
484  aSymbolRect.AdjustBottom( -nBorderDistanceBottom );
485  DecorationView aDecoView(xVirDev.get());
486  aDecoView.DrawSymbol(aSymbolRect, SymbolType::SPIN_DOWN, GetTextColor(),
487  DrawSymbolFlags::NONE);
488  mxMenuButton->set_image(xVirDev);
489  mxMenuButton->set_size_request(aSize.Width() + 4, aSize.Height() + 4);
490 }
491 
492 void SwAnnotationWin::Rescale()
493 {
494  // On Android, this method leads to invoke ImpEditEngine::UpdateViews
495  // which hides the text cursor. Moreover it causes sudden document scroll
496  // when modifying a commented text. Not clear the root cause,
497  // anyway skipping this method fixes the problem, and there should be
498  // no side effect, since the client has disabled annotations rendering.
500  return;
501 
502  MapMode aMode = GetParent()->GetMapMode();
503  aMode.SetOrigin( Point() );
504  mpOutliner->SetRefMapMode( aMode );
505  SetMapMode( aMode );
506  mxSidebarTextControl->SetMapMode( aMode );
507  const Fraction& rFraction = mrView.GetWrtShellPtr()->GetOut()->GetMapMode().GetScaleY();
508 
509  vcl::Font aFont = maLabelFont;
510  sal_Int32 nHeight = tools::Long(aFont.GetFontHeight() * rFraction);
511  aFont.SetFontHeight( nHeight );
512 
513  if (mxMetadataAuthor)
514  mxMetadataAuthor->set_font(aFont);
515  if (mxMetadataDate)
516  mxMetadataDate->set_font(aFont);
517  if (mxMetadataResolved)
518  mxMetadataResolved->set_font(aFont);
519  SetMenuButtonColors();
520  if (mxVScrollbar)
521  mxVScrollbar->set_scroll_thickness(GetPrefScrollbarWidth());
522 }
523 
524 void SwAnnotationWin::SetPosAndSize()
525 {
526  bool bChange = false;
527 
528  if (GetSizePixel() != mPosSize.GetSize())
529  {
530  bChange = true;
531  SetSizePixel(mPosSize.GetSize());
532 
533  DoResize();
534  }
535 
536  if (GetPosPixel().X() != mPosSize.Left() || (std::abs(GetPosPixel().Y() - mPosSize.Top()) > 5) )
537  {
538  bChange = true;
539  SetPosPixel(mPosSize.TopLeft());
540 
541  Point aLineStart;
542  Point aLineEnd ;
543  switch ( meSidebarPosition )
544  {
546  {
547  aLineStart = EditWin().PixelToLogic( Point(GetPosPixel().X()+GetSizePixel().Width(),GetPosPixel().Y()-1) );
548  aLineEnd = EditWin().PixelToLogic( Point(GetPosPixel().X(),GetPosPixel().Y()-1) );
549  }
550  break;
552  {
553  aLineStart = EditWin().PixelToLogic( Point(GetPosPixel().X(),GetPosPixel().Y()-1) );
554  aLineEnd = EditWin().PixelToLogic( Point(GetPosPixel().X()+GetSizePixel().Width(),GetPosPixel().Y()-1) );
555  }
556  break;
557  default:
558  OSL_FAIL( "<SwAnnotationWin::SetPosAndSize()> - unexpected position of sidebar" );
559  break;
560  }
561 
562  // LOK has map mode disabled, and we still want to perform pixel ->
563  // twips conversion for the size of the line above the note.
564  if (comphelper::LibreOfficeKit::isActive() && !EditWin().IsMapModeEnabled())
565  {
566  EditWin().EnableMapMode();
567  Size aSize(aLineEnd.getX() - aLineStart.getX(), aLineEnd.getY() - aLineStart.getY());
568  aSize = EditWin().PixelToLogic(aSize);
569  aLineEnd = aLineStart;
570  aLineEnd.Move(aSize.getWidth(), aSize.getHeight());
571  EditWin().EnableMapMode(false);
572  }
573 
574  if (mpAnchor)
575  {
576  mpAnchor->SetAllPosition( basegfx::B2DPoint( mAnchorRect.Left() , mAnchorRect.Bottom() - 5* 15),
577  basegfx::B2DPoint( mAnchorRect.Left()-5*15 , mAnchorRect.Bottom()+5*15),
578  basegfx::B2DPoint( mAnchorRect.Left()+5*15 , mAnchorRect.Bottom()+5*15),
579  basegfx::B2DPoint( mAnchorRect.Left(), mAnchorRect.Bottom()+2*15),
580  basegfx::B2DPoint( mPageBorder ,mAnchorRect.Bottom()+2*15),
581  basegfx::B2DPoint( aLineStart.X(),aLineStart.Y()),
582  basegfx::B2DPoint( aLineEnd.X(),aLineEnd.Y()));
583  }
584  else
585  {
587  mAnchorRect,
588  mPageBorder,
589  aLineStart,
590  aLineEnd,
591  mColorAnchor );
592  if ( mpAnchor )
593  {
594  mpAnchor->setVisible(true);
595  mpAnchor->SetAnchorState(AnchorState::Tri);
596  if (HasChildPathFocus())
597  {
598  mpAnchor->setLineSolid(true);
599  }
600  }
601  }
602  }
603  else
604  {
605  if ( mpAnchor &&
606  ( mpAnchor->getBasePosition() != basegfx::B2DPoint( mAnchorRect.Left() , mAnchorRect.Bottom()-5*15) ) )
607  {
608  mpAnchor->SetTriPosition( basegfx::B2DPoint( mAnchorRect.Left() , mAnchorRect.Bottom() - 5* 15),
609  basegfx::B2DPoint( mAnchorRect.Left()-5*15 , mAnchorRect.Bottom()+5*15),
610  basegfx::B2DPoint( mAnchorRect.Left()+5*15 , mAnchorRect.Bottom()+5*15),
611  basegfx::B2DPoint( mAnchorRect.Left(), mAnchorRect.Bottom()+2*15),
612  basegfx::B2DPoint( mPageBorder , mAnchorRect.Bottom()+2*15));
613  }
614  }
615 
616  if (mpShadow && bChange)
617  {
618  Point aStart = EditWin().PixelToLogic(GetPosPixel()+Point(0,GetSizePixel().Height()));
619  Point aEnd = EditWin().PixelToLogic(GetPosPixel()+Point(GetSizePixel().Width()-1,GetSizePixel().Height()));
620  mpShadow->SetPosition(basegfx::B2DPoint(aStart.X(),aStart.Y()), basegfx::B2DPoint(aEnd.X(),aEnd.Y()));
621  }
622 
623  if (mrMgr.ShowNotes())
624  {
625  if (IsFollow() && !HasChildPathFocus())
626  {
627  // #i111964#
628  if ( mpAnchor )
629  {
630  mpAnchor->SetAnchorState(AnchorState::End);
631  }
632  }
633  else
634  {
635  // #i111964#
636  if ( mpAnchor )
637  {
638  mpAnchor->SetAnchorState(AnchorState::All);
639  }
640  SwAnnotationWin* pWin = GetTopReplyNote();
641  // #i111964#
642  if ( pWin != this && pWin->Anchor() )
643  {
645  }
646  }
647  }
648 
649 
650  // text range overlay
651  maAnnotationTextRanges.clear();
652  if ( mrSidebarItem.maLayoutInfo.mnStartNodeIdx != SwNodeOffset(0)
653  && mrSidebarItem.maLayoutInfo.mnStartContent != -1 )
654  {
655  const SwTextAnnotationField* pTextAnnotationField =
656  dynamic_cast< const SwTextAnnotationField* >( mrSidebarItem.GetFormatField().GetTextField() );
657  SwTextNode* pTextNode = pTextAnnotationField ? pTextAnnotationField->GetpTextNode() : nullptr;
658  SwContentNode* pContentNd = nullptr;
659  if (pTextNode)
660  {
661  SwNodes& rNds = pTextNode->GetDoc().GetNodes();
662  pContentNd = rNds[mrSidebarItem.maLayoutInfo.mnStartNodeIdx]->GetContentNode();
663  }
664  if (pContentNd)
665  {
666  SwPosition aStartPos( *pContentNd, mrSidebarItem.maLayoutInfo.mnStartContent );
667  SwShellCursor* pTmpCursor = nullptr;
668  const bool bTableCursorNeeded = pTextNode->FindTableBoxStartNode() != pContentNd->FindTableBoxStartNode();
669  if ( bTableCursorNeeded )
670  {
671  SwShellTableCursor* pTableCursor = new SwShellTableCursor( mrView.GetWrtShell(), aStartPos );
672  pTableCursor->SetMark();
673  pTableCursor->GetMark()->nNode = *pTextNode;
674  pTableCursor->GetMark()->nContent.Assign( pTextNode, pTextAnnotationField->GetStart()+1 );
675  pTableCursor->NewTableSelection();
676  pTmpCursor = pTableCursor;
677  }
678  else
679  {
680  SwShellCursor* pCursor = new SwShellCursor( mrView.GetWrtShell(), aStartPos );
681  pCursor->SetMark();
682  pCursor->GetMark()->nNode = *pTextNode;
683  pCursor->GetMark()->nContent.Assign( pTextNode, pTextAnnotationField->GetStart()+1 );
684  pTmpCursor = pCursor;
685  }
686  std::unique_ptr<SwShellCursor> pTmpCursorForAnnotationTextRange( pTmpCursor );
687 
688  // For annotation text range rectangles to be calculated correctly,
689  // we need the map mode disabled
690  bool bDisableMapMode = comphelper::LibreOfficeKit::isActive() && EditWin().IsMapModeEnabled();
691  if (bDisableMapMode)
692  EditWin().EnableMapMode(false);
693 
694  if (mrSidebarItem.maLayoutInfo.mPositionFromCommentAnchor)
695  pTmpCursorForAnnotationTextRange->FillRects();
696 
697  if (bDisableMapMode)
698  EditWin().EnableMapMode();
699 
700  SwRects* pRects(pTmpCursorForAnnotationTextRange.get());
701  for(const SwRect & rNextRect : *pRects)
702  {
703  const tools::Rectangle aPntRect(rNextRect.SVRect());
704  maAnnotationTextRanges.emplace_back(
705  aPntRect.Left(), aPntRect.Top(),
706  aPntRect.Right() + 1, aPntRect.Bottom() + 1);
707  }
708  }
709  }
710 
711  if (mrMgr.ShowNotes() && !maAnnotationTextRanges.empty())
712  {
713  if ( mpTextRangeOverlay != nullptr )
714  {
715  mpTextRangeOverlay->setRanges( std::vector(maAnnotationTextRanges) );
716  if ( mpAnchor != nullptr && mpAnchor->getLineSolid() )
717  {
718  mpTextRangeOverlay->ShowSolidBorder();
719  }
720  else
721  {
722  mpTextRangeOverlay->HideSolidBorder();
723  }
724  }
725  else if (!IsFollow())
726  {
727  // This window is not a reply, then draw its range overlay.
728  mpTextRangeOverlay =
730  mrView,
731  mColorAnchor,
732  std::vector(maAnnotationTextRanges),
733  mpAnchor && mpAnchor->getLineSolid() );
734  }
735  }
736  else
737  {
738  mpTextRangeOverlay.reset();
739  }
740 }
741 
742 void SwAnnotationWin::DoResize()
743 {
744  tools::Long aHeight = GetSizePixel().Height();
745  tools::ULong aWidth = GetSizePixel().Width();
746 
747  aHeight -= GetMetaHeight();
748 
749  mpOutliner->SetPaperSize( PixelToLogic( Size(aWidth, aHeight) ) ) ;
750  tools::Long aTextHeight = LogicToPixel( mpOutliner->CalcTextSize()).Height();
751 
752  mxMetadataAuthor->show();
753  if(IsResolved()) { mxMetadataResolved->show(); }
754  mxMetadataDate->show();
755 
756  if (aTextHeight > aHeight)
757  {
758  const int nThickness = mxVScrollbar->get_scroll_thickness();
759  if (nThickness)
760  {
761  // we need vertical scrollbars and have to reduce the width
762  aWidth -= nThickness;
763  mpOutliner->SetPaperSize(PixelToLogic(Size(aWidth, aHeight)));
764  }
765  mxVScrollbar->set_vpolicy(VclPolicyType::ALWAYS);
766  }
767  else
768  {
769  mxVScrollbar->set_vpolicy(VclPolicyType::NEVER);
770  }
771 
772  tools::Rectangle aOutputArea = PixelToLogic(tools::Rectangle(0, 0, aWidth, aHeight));
773  if (mxVScrollbar->get_vpolicy() == VclPolicyType::NEVER)
774  {
775  // if we do not have a scrollbar anymore, we want to see the complete text
776  mpOutlinerView->SetVisArea(aOutputArea);
777  }
778  mpOutlinerView->SetOutputArea(aOutputArea);
779  mpOutlinerView->ShowCursor(true, true);
780 
781  // Don't leave an empty area at the bottom if we can move the text down.
782  tools::Long nMaxVisAreaTop = mpOutliner->GetTextHeight() - aOutputArea.GetHeight();
783  if (mpOutlinerView->GetVisArea().Top() > nMaxVisAreaTop)
784  {
785  GetOutlinerView()->Scroll(0, mpOutlinerView->GetVisArea().Top() - nMaxVisAreaTop);
786  }
787 
788  int nUpper = mpOutliner->GetTextHeight();
789  int nCurrentDocPos = mpOutlinerView->GetVisArea().Top();
790  int nStepIncrement = mpOutliner->GetTextHeight() / 10;
791  int nPageIncrement = PixelToLogic(Size(0,aHeight)).Height() * 8 / 10;
792  int nPageSize = PixelToLogic(Size(0,aHeight)).Height();
793 
794  /* limit the page size to below nUpper because gtk's gtk_scrolled_window_start_deceleration has
795  effectively...
796 
797  lower = gtk_adjustment_get_lower
798  upper = gtk_adjustment_get_upper - gtk_adjustment_get_page_size
799 
800  and requires that upper > lower or the deceleration animation never ends
801  */
802  nPageSize = std::min(nPageSize, nUpper);
803 
804  mxVScrollbar->vadjustment_configure(nCurrentDocPos, 0, nUpper,
805  nStepIncrement, nPageIncrement, nPageSize);
806 }
807 
808 void SwAnnotationWin::SetSizePixel( const Size& rNewSize )
809 {
811  return;
812 
814 
815  if (mpShadow)
816  {
817  Point aStart = EditWin().PixelToLogic(GetPosPixel()+Point(0,GetSizePixel().Height()));
818  Point aEnd = EditWin().PixelToLogic(GetPosPixel()+Point(GetSizePixel().Width()-1,GetSizePixel().Height()));
819  mpShadow->SetPosition(basegfx::B2DPoint(aStart.X(),aStart.Y()), basegfx::B2DPoint(aEnd.X(),aEnd.Y()));
820  }
821 }
822 
823 void SwAnnotationWin::SetScrollbar()
824 {
825  mxVScrollbar->vadjustment_set_value(mpOutlinerView->GetVisArea().Top());
826 }
827 
828 void SwAnnotationWin::ResizeIfNecessary(tools::Long aOldHeight, tools::Long aNewHeight)
829 {
830  if (aOldHeight != aNewHeight)
831  {
832  //check for lower border or next note
833  tools::Long aBorder = mrMgr.GetNextBorder();
834  if (aBorder != -1)
835  {
836  if (aNewHeight > GetMinimumSizeWithoutMeta())
837  {
838  tools::Long aNewLowerValue = GetPosPixel().Y() + aNewHeight + GetMetaHeight();
839  if (aNewLowerValue < aBorder)
840  SetSizePixel(Size(GetSizePixel().Width(),aNewHeight+GetMetaHeight()));
841  else
842  SetSizePixel(Size(GetSizePixel().Width(),aBorder - GetPosPixel().Y()));
843  DoResize();
844  Invalidate();
845  }
846  else
847  {
848  if (GetSizePixel().Height() != GetMinimumSizeWithoutMeta() + GetMetaHeight())
849  SetSizePixel(Size(GetSizePixel().Width(),GetMinimumSizeWithoutMeta() + GetMetaHeight()));
850  DoResize();
851  Invalidate();
852  }
853  }
854  else
855  {
856  DoResize();
857  Invalidate();
858  }
859  }
860  else
861  {
862  SetScrollbar();
863  }
864 }
865 
866 void SwAnnotationWin::SetColor(Color aColorDark,Color aColorLight, Color aColorAnchor)
867 {
868  mColorDark = aColorDark;
869  mColorLight = aColorLight;
870  mColorAnchor = aColorAnchor;
871 
872  if ( Application::GetSettings().GetStyleSettings().GetHighContrastMode() )
873  return;
874 
875  m_xContainer->set_background(mColorDark);
876  SetMenuButtonColors();
877 
878  mxMetadataAuthor->set_font_color(aColorAnchor);
879 
880  mxMetadataDate->set_font_color(aColorAnchor);
881 
882  mxMetadataResolved->set_font_color(aColorAnchor);
883 
884  mxVScrollbar->customize_scrollbars(mColorLight,
885  mColorAnchor,
886  mColorDark);
887 }
888 
889 void SwAnnotationWin::SetSidebarPosition(sw::sidebarwindows::SidebarPosition eSidebarPosition)
890 {
891  meSidebarPosition = eSidebarPosition;
892 }
893 
894 void SwAnnotationWin::SetReadonly(bool bSet)
895 {
896  mbReadonly = bSet;
897  GetOutlinerView()->SetReadOnly(bSet);
898 }
899 
901 {
902  IDocumentUndoRedo& rUndoRedo(
903  mrView.GetDocShell()->GetDoc()->GetIDocumentUndoRedo());
904  const bool bDocUndoEnabled = rUndoRedo.DoesUndo();
905  const bool bOutlinerUndoEnabled = mpOutliner->IsUndoEnabled();
906  const bool bOutlinerModified = mpOutliner->IsModified();
907  const bool bDisableAndRestoreUndoMode = !bDocUndoEnabled && bOutlinerUndoEnabled;
908 
909  if (bDisableAndRestoreUndoMode)
910  {
911  // doc undo is disabled, but outliner was enabled, turn outliner undo off
912  // for the duration of this function
913  mpOutliner->EnableUndo(false);
914  }
915 
916  Link<LinkParamNone*,void> aLink = mpOutliner->GetModifyHdl();
917  mpOutliner->SetModifyHdl( Link<LinkParamNone*,void>() );
918  ESelection aOld = GetOutlinerView()->GetSelection();
919 
920  ESelection aNewSelection( 0, 0, mpOutliner->GetParagraphCount()-1, EE_TEXTPOS_ALL );
921  GetOutlinerView()->SetSelection( aNewSelection );
922  SfxItemSet aEditAttr(GetOutlinerView()->GetAttribs());
923  aEditAttr.Put(rNewItem);
924  GetOutlinerView()->SetAttribs( aEditAttr );
925 
926  if (!mpOutliner->IsUndoEnabled() && !bOutlinerModified)
927  {
928  // if undo was disabled (e.g. this is a redo action) and we were
929  // originally 'unmodified' keep it that way
930  mpOutliner->ClearModifyFlag();
931  }
932 
933  GetOutlinerView()->SetSelection(aOld);
934  mpOutliner->SetModifyHdl( aLink );
935 
936  const SwViewOption* pVOpt = mrView.GetWrtShellPtr()->GetViewOptions();
937  EEControlBits nCntrl = mpOutliner->GetControlWord();
938  // turn off
939  nCntrl &= ~EEControlBits::ONLINESPELLING;
940  mpOutliner->SetControlWord(nCntrl);
941 
942  //turn back on
943  if (pVOpt->IsOnlineSpell())
944  nCntrl |= EEControlBits::ONLINESPELLING;
945  else
946  nCntrl &= ~EEControlBits::ONLINESPELLING;
947  mpOutliner->SetControlWord(nCntrl);
948 
949  mpOutliner->CompleteOnlineSpelling();
950 
951  // restore original mode
952  if (bDisableAndRestoreUndoMode)
953  mpOutliner->EnableUndo(true);
954 
955  Invalidate();
956 }
957 
958 void SwAnnotationWin::GetFocus()
959 {
960  if (mxSidebarTextControl)
961  mxSidebarTextControl->GrabFocus();
962 }
963 
964 void SwAnnotationWin::LoseFocus()
965 {
966 }
967 
968 void SwAnnotationWin::ShowNote()
969 {
970  SetPosAndSize();
971  if (!IsVisible())
972  Window::Show();
973  if (mpShadow && !mpShadow->isVisible())
974  mpShadow->setVisible(true);
975  if (mpAnchor && !mpAnchor->isVisible())
976  mpAnchor->setVisible(true);
977  if (mpTextRangeOverlay && !mpTextRangeOverlay->isVisible())
978  mpTextRangeOverlay->setVisible(true);
979 
980  collectUIInformation("SHOW",get_id());
981 }
982 
983 void SwAnnotationWin::HideNote()
984 {
985  if (IsVisible())
986  Window::Hide();
987  if (mpAnchor)
988  {
989  if (mrMgr.IsShowAnchor())
990  mpAnchor->SetAnchorState(AnchorState::Tri);
991  else
992  mpAnchor->setVisible(false);
993  }
994  if (mpShadow && mpShadow->isVisible())
995  mpShadow->setVisible(false);
996  if (mpTextRangeOverlay && mpTextRangeOverlay->isVisible())
997  mpTextRangeOverlay->setVisible(false);
998  collectUIInformation("HIDE",get_id());
999 }
1000 
1001 void SwAnnotationWin::ActivatePostIt()
1002 {
1003  mrMgr.AssureStdModeAtShell();
1004 
1005  mpOutliner->ClearModifyFlag();
1006  mpOutliner->GetUndoManager().Clear();
1007 
1008  CheckMetaText();
1009  SetViewState(ViewState::EDIT);
1010 
1011  // prevent autoscroll to the old cursor location
1012  // when cursor out of visible area
1013  GetOutlinerView()->ShowCursor(false);
1014 
1015  mpOutlinerView->GetEditView().SetInsertMode(mrView.GetWrtShellPtr()->IsInsMode());
1016 
1018  GetOutlinerView()->SetBackgroundColor(mColorDark);
1019 
1020  //tdf#119130 only have the active postit as a dialog control in which pressing
1021  //ctrl+tab cycles between text and button so we don't waste time searching
1022  //thousands of SwAnnotationWins
1023  SetStyle(GetStyle() | WB_DIALOGCONTROL);
1024 }
1025 
1026 void SwAnnotationWin::DeactivatePostIt()
1027 {
1028  //tdf#119130 only have the active postit as a dialog control in which pressing
1029  //ctrl+tab cycles between text and button so we don't waste time searching
1030  //thousands of SwAnnotationWins
1031  SetStyle(GetStyle() & ~WB_DIALOGCONTROL);
1032 
1033  // remove selection, #i87073#
1034  if (GetOutlinerView()->GetEditView().HasSelection())
1035  {
1036  ESelection aSelection = GetOutlinerView()->GetEditView().GetSelection();
1037  aSelection.nEndPara = aSelection.nStartPara;
1038  aSelection.nEndPos = aSelection.nStartPos;
1039  GetOutlinerView()->GetEditView().SetSelection(aSelection);
1040  }
1041 
1042  mpOutliner->CompleteOnlineSpelling();
1043 
1044  SetViewState(ViewState::NORMAL);
1045  // Make sure this view doesn't emit LOK callbacks during the update, as the
1046  // sidebar window's SidebarTextControl doesn't have a valid twip offset
1047  // (map mode origin) during that operation.
1048  bool bTiledPainting = comphelper::LibreOfficeKit::isTiledPainting();
1050  // write the visible text back into the SwField
1051  UpdateData();
1053 
1054  if ( !Application::GetSettings().GetStyleSettings().GetHighContrastMode() )
1055  GetOutlinerView()->SetBackgroundColor(COL_TRANSPARENT);
1056 
1057  if (!mnDeleteEventId && !IsProtected() && mpOutliner->GetEditEngine().GetText().isEmpty())
1058  {
1059  mnDeleteEventId = Application::PostUserEvent( LINK( this, SwAnnotationWin, DeleteHdl), nullptr, true );
1060  }
1061 }
1062 
1063 void SwAnnotationWin::ToggleInsMode()
1064 {
1065  if (!mrView.GetWrtShell().IsRedlineOn())
1066  {
1067  //change outliner
1068  mpOutlinerView->GetEditView().SetInsertMode(!mpOutlinerView->GetEditView().IsInsertMode());
1069  //change document
1070  mrView.GetWrtShell().ToggleInsMode();
1071  //update statusbar
1072  SfxBindings &rBnd = mrView.GetViewFrame()->GetBindings();
1073  rBnd.Invalidate(SID_ATTR_INSERT);
1074  rBnd.Update(SID_ATTR_INSERT);
1075  }
1076 }
1077 
1078 void SwAnnotationWin::ExecuteCommand(sal_uInt16 nSlot)
1079 {
1080  mrMgr.AssureStdModeAtShell();
1081 
1082  switch (nSlot)
1083  {
1084  case FN_POSTIT:
1085  case FN_REPLY:
1086  {
1087  // if this note is empty, it will be deleted once losing the focus, so no reply, but only a new note
1088  // will be created
1089  if (!mpOutliner->GetEditEngine().GetText().isEmpty())
1090  {
1091  OutlinerParaObject aPara(GetOutlinerView()->GetEditView().CreateTextObject());
1092  mrMgr.RegisterAnswer(&aPara);
1093  }
1094  if (mrMgr.HasActiveSidebarWin())
1095  mrMgr.SetActiveSidebarWin(nullptr);
1096  SwitchToFieldPos();
1097  mrView.GetViewFrame()->GetDispatcher()->Execute(FN_POSTIT);
1098  break;
1099  }
1100  case FN_DELETE_COMMENT:
1101  //Delete(); // do not kill the parent of our open popup menu
1102  mnDeleteEventId = Application::PostUserEvent( LINK( this, SwAnnotationWin, DeleteHdl), nullptr, true );
1103  break;
1105  DeleteThread();
1106  break;
1107  case FN_RESOLVE_NOTE:
1108  ToggleResolved();
1109  DoResize();
1110  Invalidate();
1111  mrMgr.LayoutPostIts();
1112  break;
1114  GetTopReplyNote()->SetResolved(!IsThreadResolved());
1115  mrMgr.UpdateResolvedStatus(GetTopReplyNote());
1116  DoResize();
1117  Invalidate();
1118  mrMgr.LayoutPostIts();
1119  break;
1120  case FN_FORMAT_ALL_NOTES:
1121  case FN_DELETE_ALL_NOTES:
1122  case FN_HIDE_ALL_NOTES:
1123  // not possible as slot as this would require that "this" is the active postit
1124  mrView.GetViewFrame()->GetBindings().Execute( nSlot, nullptr, SfxCallMode::ASYNCHRON );
1125  break;
1126  case FN_DELETE_NOTE_AUTHOR:
1127  case FN_HIDE_NOTE_AUTHOR:
1128  {
1129  // not possible as slot as this would require that "this" is the active postit
1130  SfxStringItem aItem( nSlot, GetAuthor() );
1131  const SfxPoolItem* aItems[2];
1132  aItems[0] = &aItem;
1133  aItems[1] = nullptr;
1134  mrView.GetViewFrame()->GetBindings().Execute( nSlot, aItems, SfxCallMode::ASYNCHRON );
1135  }
1136  break;
1137  default:
1138  mrView.GetViewFrame()->GetBindings().Execute( nSlot );
1139  break;
1140  }
1141 }
1142 
1143 SwEditWin& SwAnnotationWin::EditWin()
1144 {
1145  return mrView.GetEditWin();
1146 }
1147 
1148 tools::Long SwAnnotationWin::GetPostItTextHeight()
1149 {
1150  return mpOutliner ? LogicToPixel(mpOutliner->CalcTextSize()).Height() : 0;
1151 }
1152 
1153 void SwAnnotationWin::SwitchToPostIt(sal_uInt16 aDirection)
1154 {
1155  SwAnnotationWin* pPostIt = mrMgr.GetNextPostIt(aDirection, this);
1156  if (pPostIt)
1157  pPostIt->GrabFocus();
1158 }
1159 
1160 IMPL_LINK(SwAnnotationWin, MouseMoveHdl, const MouseEvent&, rMEvt, bool)
1161 {
1162  if (rMEvt.IsEnterWindow())
1163  {
1164  mbMouseOver = true;
1165  if ( !HasFocus() )
1166  {
1167  SetViewState(ViewState::VIEW);
1168  Invalidate();
1169  }
1170  }
1171  else if (rMEvt.IsLeaveWindow())
1172  {
1173  mbMouseOver = false;
1174  if ( !HasFocus() )
1175  {
1176  SetViewState(ViewState::NORMAL);
1177  Invalidate();
1178  }
1179  }
1180  return false;
1181 }
1182 
1183 bool SwAnnotationWin::SetActiveSidebarWin()
1184 {
1185  if (mrMgr.GetActiveSidebarWin() == this)
1186  return false;
1187  mrView.GetWrtShell().LockView( true );
1188  mrMgr.SetActiveSidebarWin(this);
1189  mrView.GetWrtShell().LockView( true );
1190 
1191  return true;
1192 }
1193 
1194 void SwAnnotationWin::UnsetActiveSidebarWin()
1195 {
1196  if (mrMgr.GetActiveSidebarWin() != this)
1197  return;
1198  mrView.GetWrtShell().LockView( true );
1199  mrMgr.SetActiveSidebarWin(nullptr);
1200  mrView.GetWrtShell().LockView( false );
1201 }
1202 
1203 void SwAnnotationWin::LockView(bool bLock)
1204 {
1205  mrView.GetWrtShell().LockView( bLock );
1206 }
1207 
1208 IMPL_LINK(SwAnnotationWin, ScrollHdl, weld::ScrolledWindow&, rScrolledWindow, void)
1209 {
1210  tools::Long nDiff = GetOutlinerView()->GetEditView().GetVisArea().Top() - rScrolledWindow.vadjustment_get_value();
1211  GetOutlinerView()->Scroll( 0, nDiff );
1212 }
1213 
1215 {
1216  mrView.GetDocShell()->SetModified();
1217 }
1218 
1219 IMPL_LINK_NOARG(SwAnnotationWin, DeleteHdl, void*, void)
1220 {
1221  mnDeleteEventId = nullptr;
1222  Delete();
1223 }
1224 
1225 void SwAnnotationWin::ResetAttributes()
1226 {
1227  mpOutlinerView->RemoveAttribsKeepLanguages(true);
1228  mpOutliner->RemoveFields();
1229  mpOutlinerView->SetAttribs(DefaultItem());
1230 }
1231 
1232 int SwAnnotationWin::GetPrefScrollbarWidth() const
1233 {
1234  const Fraction& f(mrView.GetWrtShellPtr()->GetOut()->GetMapMode().GetScaleY());
1235  return tools::Long(Application::GetSettings().GetStyleSettings().GetScrollBarSize() * f);
1236 }
1237 
1238 sal_Int32 SwAnnotationWin::GetMetaHeight() const
1239 {
1240  const int fields = GetNumFields();
1241 
1242  sal_Int32 nRequiredHeight = 0;
1243  weld::Label* aLabels[3] = { mxMetadataAuthor.get(), mxMetadataDate.get(), mxMetadataResolved.get() };
1244  for (int i = 0; i < fields; ++i)
1245  nRequiredHeight += aLabels[i]->get_preferred_size().Height();
1246 
1247  return nRequiredHeight;
1248 }
1249 
1250 sal_Int32 SwAnnotationWin::GetNumFields() const
1251 {
1252  return IsResolved() ? 3 : 2;
1253 }
1254 
1255 sal_Int32 SwAnnotationWin::GetMinimumSizeWithMeta() const
1256 {
1257  return mrMgr.GetMinimumSizeWithMeta();
1258 }
1259 
1260 sal_Int32 SwAnnotationWin::GetMinimumSizeWithoutMeta() const
1261 {
1262  const Fraction& f(mrView.GetWrtShellPtr()->GetOut()->GetMapMode().GetScaleY());
1264 }
1265 
1266 void SwAnnotationWin::SetSpellChecking()
1267 {
1268  const SwViewOption* pVOpt = mrView.GetWrtShellPtr()->GetViewOptions();
1269  EEControlBits nCntrl = mpOutliner->GetControlWord();
1270  if (pVOpt->IsOnlineSpell())
1271  nCntrl |= EEControlBits::ONLINESPELLING;
1272  else
1273  nCntrl &= ~EEControlBits::ONLINESPELLING;
1274  mpOutliner->SetControlWord(nCntrl);
1275 
1276  mpOutliner->CompleteOnlineSpelling();
1277  Invalidate();
1278 }
1279 
1280 void SwAnnotationWin::SetViewState(ViewState bViewState)
1281 {
1282  switch (bViewState)
1283  {
1284  case ViewState::EDIT:
1285  {
1286  if (mpAnchor)
1287  {
1288  mpAnchor->SetAnchorState(AnchorState::All);
1289  SwAnnotationWin* pWin = GetTopReplyNote();
1290  // #i111964#
1291  if ( pWin != this && pWin->Anchor() )
1292  {
1294  }
1295  mpAnchor->setLineSolid(true);
1296  if ( mpTextRangeOverlay != nullptr )
1297  {
1298  mpTextRangeOverlay->ShowSolidBorder();
1299  }
1300  }
1301  if (mpShadow)
1302  mpShadow->SetShadowState(SS_EDIT);
1303  break;
1304  }
1305  case ViewState::VIEW:
1306  {
1307  if (mpAnchor)
1308  {
1309  mpAnchor->setLineSolid(true);
1310  if ( mpTextRangeOverlay != nullptr )
1311  {
1312  mpTextRangeOverlay->ShowSolidBorder();
1313  }
1314  }
1315  if (mpShadow)
1316  mpShadow->SetShadowState(SS_VIEW);
1317  break;
1318  }
1319  case ViewState::NORMAL:
1320  {
1321  if (mpAnchor)
1322  {
1323  if (IsFollow())
1324  {
1325  // if there is no visible parent note, we want to see the complete anchor ??
1326  //if (IsAnyStackParentVisible())
1327  mpAnchor->SetAnchorState(AnchorState::End);
1328  SwAnnotationWin* pTopWinSelf = GetTopReplyNote();
1329  SwAnnotationWin* pTopWinActive = mrMgr.HasActiveSidebarWin()
1330  ? mrMgr.GetActiveSidebarWin()->GetTopReplyNote()
1331  : nullptr;
1332  // #i111964#
1333  if ( ( pTopWinSelf != this ) &&
1334  ( pTopWinSelf != pTopWinActive ) &&
1335  pTopWinSelf->Anchor() )
1336  {
1337  if ( pTopWinSelf != mrMgr.GetActiveSidebarWin() )
1338  {
1339  pTopWinSelf->Anchor()->setLineSolid(false);
1340  if ( pTopWinSelf->TextRange() != nullptr )
1341  {
1342  pTopWinSelf->TextRange()->HideSolidBorder();
1343  }
1344  }
1345  pTopWinSelf->Anchor()->SetAnchorState(AnchorState::All);
1346  }
1347  }
1348  mpAnchor->setLineSolid(false);
1349  if ( mpTextRangeOverlay != nullptr )
1350  {
1351  mpTextRangeOverlay->HideSolidBorder();
1352  }
1353  }
1354  if ( mpShadow )
1355  {
1356  mpShadow->SetShadowState(SS_NORMAL);
1357  }
1358  break;
1359  }
1360  }
1361 }
1362 
1363 SwAnnotationWin* SwAnnotationWin::GetTopReplyNote()
1364 {
1365  SwAnnotationWin* pTopNote = this;
1366  SwAnnotationWin* pSidebarWin = IsFollow() ? mrMgr.GetNextPostIt(KEY_PAGEUP, this) : nullptr;
1367  while (pSidebarWin)
1368  {
1369  pTopNote = pSidebarWin;
1370  pSidebarWin = pSidebarWin->IsFollow() ? mrMgr.GetNextPostIt(KEY_PAGEUP, pSidebarWin) : nullptr;
1371  }
1372  return pTopNote;
1373 }
1374 
1375 void SwAnnotationWin::SwitchToFieldPos()
1376 {
1377  if ( mrMgr.GetActiveSidebarWin() == this )
1378  mrMgr.SetActiveSidebarWin(nullptr);
1379  GotoPos();
1380  sal_uInt32 aCount = MoveCaret();
1381  if (aCount)
1382  mrView.GetDocShell()->GetWrtShell()->SwCursorShell::Right(aCount, 0);
1383  GrabFocusToDocument();
1384  collectUIInformation("LEAVE",get_id());
1385 }
1386 
1387 void SwAnnotationWin::SetChangeTracking( const SwPostItHelper::SwLayoutStatus aLayoutStatus,
1388  const Color& aChangeColor )
1389 {
1390  if ( (mLayoutStatus != aLayoutStatus) ||
1391  (mChangeColor != aChangeColor) )
1392  {
1393  mLayoutStatus = aLayoutStatus;
1394  mChangeColor = aChangeColor;
1395  Invalidate();
1396  }
1397 }
1398 
1399 bool SwAnnotationWin::HasScrollbar() const
1400 {
1401  return static_cast<bool>(mxVScrollbar);
1402 }
1403 
1404 bool SwAnnotationWin::IsScrollbarVisible() const
1405 {
1406  return HasScrollbar() && mxVScrollbar->get_vpolicy() == VclPolicyType::ALWAYS;
1407 }
1408 
1409 void SwAnnotationWin::ChangeSidebarItem( SwSidebarItem const & rSidebarItem )
1410 {
1411 #if !ENABLE_WASM_STRIP_ACCESSIBILITY
1412  const bool bAnchorChanged = mpAnchorFrame != rSidebarItem.maLayoutInfo.mpAnchorFrame;
1413  if ( bAnchorChanged )
1414  {
1415  mrMgr.DisconnectSidebarWinFromFrame( *mpAnchorFrame, *this );
1416  }
1417 #endif
1418 
1419  mrSidebarItem = rSidebarItem;
1420  mpAnchorFrame = mrSidebarItem.maLayoutInfo.mpAnchorFrame;
1421 
1422 #if !ENABLE_WASM_STRIP_ACCESSIBILITY
1423  if (mxSidebarWinAccessible)
1424  mxSidebarWinAccessible->ChangeSidebarItem( mrSidebarItem );
1425 
1426  if ( bAnchorChanged )
1427  {
1428  mrMgr.ConnectSidebarWinToFrame( *(mrSidebarItem.maLayoutInfo.mpAnchorFrame),
1429  mrSidebarItem.GetFormatField(),
1430  *this );
1431  }
1432 #endif
1433 }
1434 
1435 css::uno::Reference< css::accessibility::XAccessible > SwAnnotationWin::CreateAccessible()
1436 {
1437 #if !ENABLE_WASM_STRIP_ACCESSIBILITY
1438  // This is rather dodgy code. Normally in CreateAccessible, if we want a custom
1439  // object, we return a custom object, but we do no override the default toolkit
1440  // window peer.
1441  if (!mxSidebarWinAccessible)
1442  mxSidebarWinAccessible = new SidebarWinAccessible( *this,
1443  mrView.GetWrtShell(),
1444  mrSidebarItem );
1445 #endif
1446  return mxSidebarWinAccessible;
1447 }
1448 
1449 } // eof of namespace sw::sidebarwindows
1450 
1451 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
#define FN_HIDE_ALL_NOTES
Definition: cmdid.h:767
SwNodeOffset min(const SwNodeOffset &a, const SwNodeOffset &b)
Definition: nodeoffset.hxx:35
sal_Int32 nStartPara
Marks a position in the document model.
Definition: pam.hxx:36
sal_uInt8 GetRed() const
const SwFrame * mpAnchorFrame
tools::Long AdjustRight(tools::Long nHorzMoveDelta)
SwNodeIndex nNode
Definition: pam.hxx:38
bool Contains(const Point &rPOINT) const
::sw::overlay::OverlayRanges * TextRange()
long Long
constexpr::Color COL_TRANSPARENT(ColorTransparency, 0xFF, 0xFF, 0xFF, 0xFF)
const StyleSettings & GetStyleSettings() const
static const AllSettings & GetSettings()
void Push(vcl::PushFlags nFlags=vcl::PushFlags::ALL)
Color GetTextColor(Color const &rColor, DrawModeFlags nDrawMode, StyleSettings const &rStyleSettings)
const SwPosition * GetMark() const
Definition: pam.hxx:210
LanguageType GetLanguage(SfxItemSet const &aSet, sal_uInt16 nLangWhichId)
Definition: langhelper.cxx:390
virtual void SetMark() override
Unless this is called, the getter method of Mark will return Point.
Definition: viscrs.cxx:868
Any GetTime(const OUString &val)
IMPL_LINK(SidebarTextControl, OnlineSpellCallback, SpellCallbackInfo &, rInfo, void)
virtual void SetSizePixel(const Size &rNewSize)
void SetCalcFieldValueHdl(Outliner *pOutliner)
In the Outliner, set a link to the method for field display in edit objects.
Definition: docdraw.cxx:540
static ImplSVEvent * PostUserEvent(const Link< void *, void > &rLink, void *pCaller=nullptr, bool bReferenceLink=false)
SwTextNode * GetpTextNode() const
Definition: txtfld.hxx:49
void IntersectClipRegion(const tools::Rectangle &rRect)
static Color GetColorAnchor(std::size_t aAuthorIndex)
Definition: PostItMgr.cxx:2179
Of course Writer needs its own rectangles.
Definition: swrect.hxx:34
void Invalidate(sal_uInt16 nId)
void setTiledPainting(bool bTiledPainting)
SwNodeOffset abs(const SwNodeOffset &a)
Definition: nodeoffset.hxx:34
float x
EEControlBits
constexpr TypedWhichId< SvxFontHeightItem > EE_CHAR_FONTHEIGHT(EE_CHAR_START+2)
tools::Long GetFontHeight() const
#define POSTIT_MINIMUMSIZE_WITHOUT_META
OUString SwResId(TranslateId aId)
Definition: swmodule.cxx:164
bool IsValidAndGregorian() const
constexpr tools::Long Width() const
static UITestLogger & getInstance()
void logEvent(const EventDescription &rDescription)
Reference< XNameAccess > m_xContainer
const LocaleDataWrapper & GetLocaleData() const
ESelection aNewSelection(GetSelection())
#define FN_FORMAT_ALL_NOTES
Definition: cmdid.h:771
const vcl::Font & GetLabelFont() const
SwIndex nContent
Definition: pam.hxx:39
unsigned long ULong
constexpr sal_uInt16 KEY_PAGEUP
static Color GetColorDark(std::size_t aAuthorIndex)
Definition: PostItMgr.cxx:2149
sal_Int32 GetStart() const
Definition: txatbase.hxx:88
bool GetHighContrastMode() const
constexpr tools::Long GetWidth() const
#define FN_DELETE_COMMENT
Definition: cmdid.h:769
sal_Int32 nEndPos
tools::Long AdjustBottom(tools::Long nVertMoveDelta)
virtual bool DoesUndo() const =0
Is Undo enabled?
sal_uInt8 GetBlue() const
void DrawRect(const tools::Rectangle &rRect)
SfxItemPool & GetPool() const
float y
#define FN_RESOLVE_NOTE
Definition: cmdid.h:772
SwDoc * GetDoc()
returns Doc. But be careful!
Definition: docsh.hxx:204
WinBits const WB_DIALOGCONTROL
#define FN_REPLY
Definition: cmdid.h:770
void SetLineColor()
sal_Int32 nEndPara
#define SW_MOD()
Definition: swmodule.hxx:255
int i
SwAnnotationWin * GetTopReplyNote()
Find the first annotation for the thread which this annotation is in.
SwDoc & GetDoc()
Definition: node.hxx:213
#define METABUTTON_WIDTH
Window class for the Writer edit area, this is the one handling mouse and keyboard events and doing t...
Definition: edtwin.hxx:59
SwIndex & Assign(SwIndexReg *, sal_Int32)
Definition: index.cxx:206
OUString Apply(const OUString &rStr) const
Definition: SwRewriter.cxx:39
#define FN_DELETE_NOTE_AUTHOR
Definition: cmdid.h:763
#define METABUTTON_HEIGHT
void SetOrigin(const Point &rOrigin)
#define FN_HIDE_NOTE_AUTHOR
Definition: cmdid.h:766
const SwFrame * mpAnchorFrame
IMPL_LINK_NOARG(DocumentTimerManager, DoIdleJobs, Timer *, void)
void SetFillColor()
void AddRule(SwUndoArg eWhat, const OUString &rWith)
Definition: SwRewriter.cxx:25
void SetTextColor(const Color &rColor)
static bool GetLayoutRTL()
virtual void SetMark() override
Unless this is called, the getter method of Mark will return Point.
Definition: viscrs.cxx:1035
#define FN_DELETE_COMMENT_THREAD
Definition: cmdid.h:774
bool IsOnlineSpell() const
Definition: viewopt.hxx:371
static bool IsFieldShadings()
Definition: viewopt.hxx:671
void GrabFocus()
#define Y
SwLayoutInfo maLayoutInfo
constexpr Point TopLeft() const
tools::Long AdjustTop(tools::Long nVertMoveDelta)
::sw::sidebarwindows::AnchorOverlayObject * Anchor()
void SetAnchorState(const AnchorState aState)
std::unique_ptr< drawinglayer::processor2d::BaseProcessor2D > createBaseProcessor2DFromOutputDevice(OutputDevice &rTargetOutDev, const drawinglayer::geometry::ViewInformation2D &rViewInformation2D)
sal_uInt8 GetGreen() const
void Update(sal_uInt16 nId)
OUString getDate(const Date &rDate) const
static std::unique_ptr< OverlayRanges > CreateOverlayRange(SwView const &rDocView, const Color &rColor, std::vector< basegfx::B2DRange > &&rRanges, const bool bShowSolidBorder)
const SfxPoolItem * Put(const SfxPoolItem &rItem, sal_uInt16 nWhich)
SwTextNode is a paragraph in the document model.
Definition: ndtxt.hxx:79
static std::unique_ptr< AnchorOverlayObject > CreateAnchorOverlayObject(SwView const &rDocView, const SwRect &aAnchorRect, tools::Long aPageBorder, const Point &aLineStart, const Point &aLineEnd, const Color &aColorAnchor)
std::vector< SwRect > SwRects
Definition: swregion.hxx:26
std::deque< AttacherIndex_Impl > aIndex
static Color GetColorLight(std::size_t aAuthorIndex)
Definition: PostItMgr.cxx:2164
constexpr tools::Long Height() const
unsigned char sal_uInt8
void SetFont(const vcl::Font &rNewFont)
SlideSorterView & mrView
SwNodes & GetNodes()
Definition: doc.hxx:408
const ::std::vector< Color > ImpSvNumberformatScan::StandardColor COL_BLACK
const SwStartNode * FindTableBoxStartNode() const
Definition: node.hxx:198
void SetFontHeight(tools::Long nHeight)
reference_type * get() const
tools::Long AdjustLeft(tools::Long nHorzMoveDelta)
void DrawSymbol(const tools::Rectangle &rRect, SymbolType eType, const Color &rColor, DrawSymbolFlags nStyle=DrawSymbolFlags::NONE)
void(* f)(TrueTypeTable *)
OUString getTime(const tools::Time &rTime, bool bSec=true, bool b100Sec=false) const
void SetLanguage(SwWrtShell &rWrtSh, std::u16string_view rLangText, bool bIsForSelection, SfxItemSet &rCoreSet)
Definition: langhelper.cxx:214
std::map< OUString, OUString > aParameters
bool NewTableSelection()
Definition: swcrsr.cxx:2528
void DrawText(const Point &rStartPt, const OUString &rStr, sal_Int32 nIndex=0, sal_Int32 nLen=-1, std::vector< tools::Rectangle > *pVector=nullptr, OUString *pDisplayText=nullptr, const SalLayoutGlyphs *pLayoutCache=nullptr)
#define EE_TEXTPOS_ALL
#define FN_POSTIT
Definition: cmdid.h:226
constexpr tools::Long GetHeight() const
#define FN_RESOLVE_NOTE_THREAD
Definition: cmdid.h:773
static Color ColorFromAlphaColor(const sal_uInt8 aTransparency, const Color &aFront, const Color &aBack)
#define FN_DELETE_ALL_NOTES
Definition: cmdid.h:764
sal_Int32 nStartPos