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