LibreOffice Module sw (master)  1
PostItMgr.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 <boost/property_tree/json_parser.hpp>
21 
22 #include <PostItMgr.hxx>
23 #include <postithelper.hxx>
24 
25 #include <AnnotationWin.hxx>
27 #include <accmap.hxx>
28 
29 #include <SidebarWindowsConsts.hxx>
30 #include "AnchorOverlayObject.hxx"
31 #include "ShadowOverlayObject.hxx"
32 
33 #include <vcl/svapp.hxx>
34 #include <vcl/outdev.hxx>
35 #include <vcl/settings.hxx>
36 
37 #include <chrdlgmodes.hxx>
38 #include <viewopt.hxx>
39 #include <view.hxx>
40 #include <docsh.hxx>
41 #include <wrtsh.hxx>
42 #include <doc.hxx>
45 #include <fldbas.hxx>
46 #include <fmtfld.hxx>
47 #include <docufld.hxx>
48 #include <edtwin.hxx>
49 #include <txtfld.hxx>
50 #include <txtannotationfld.hxx>
51 #include <rootfrm.hxx>
52 #include <SwRewriter.hxx>
53 #include <tools/color.hxx>
54 #include <unotools/datetime.hxx>
55 
56 #include <swmodule.hxx>
57 #include <strings.hrc>
58 #include <cmdid.h>
59 
60 #include <sfx2/request.hxx>
61 #include <sfx2/event.hxx>
62 #include <svl/srchitem.hxx>
63 
64 #include <svl/languageoptions.hxx>
65 #include <svl/hint.hxx>
66 
67 #include <svx/svdview.hxx>
68 #include <editeng/eeitem.hxx>
69 #include <editeng/langitem.hxx>
70 #include <editeng/outliner.hxx>
71 #include <editeng/outlobj.hxx>
72 
73 #include <comphelper/lok.hxx>
74 #include <comphelper/string.hxx>
75 #include <LibreOfficeKit/LibreOfficeKitEnums.h>
76 
77 #include <annotsh.hxx>
78 #include <swabstdlg.hxx>
79 #include <memory>
80 
81 // distance between Anchor Y and initial note position
82 #define POSTIT_INITIAL_ANCHOR_DISTANCE 20
83 //distance between two postits
84 #define POSTIT_SPACE_BETWEEN 8
85 #define POSTIT_MINIMUMSIZE_WITH_META 60
86 #define POSTIT_SCROLL_SIDEBAR_HEIGHT 20
87 
88 // if we layout more often we stop, this should never happen
89 #define MAX_LOOP_COUNT 50
90 
91 using namespace sw::sidebarwindows;
92 using namespace sw::annotation;
93 
94 namespace {
95 
96  enum class CommentNotificationType { Add, Remove, Modify, Resolve };
97 
98  bool comp_pos(const std::unique_ptr<SwSidebarItem>& a, const std::unique_ptr<SwSidebarItem>& b)
99  {
100  // sort by anchor position
101  SwPosition aPosAnchorA = a->GetAnchorPosition();
102  SwPosition aPosAnchorB = b->GetAnchorPosition();
103 
104  bool aAnchorAInFooter = false;
105  bool aAnchorBInFooter = false;
106 
107  // is the anchor placed in Footnote or the Footer?
108  if( aPosAnchorA.nNode.GetNode().FindFootnoteStartNode() || aPosAnchorA.nNode.GetNode().FindFooterStartNode() )
109  aAnchorAInFooter = true;
110  if( aPosAnchorB.nNode.GetNode().FindFootnoteStartNode() || aPosAnchorB.nNode.GetNode().FindFooterStartNode() )
111  aAnchorBInFooter = true;
112 
113  // fdo#34800
114  // if AnchorA is in footnote, and AnchorB isn't
115  // we do not want to change over the position
116  if( aAnchorAInFooter && !aAnchorBInFooter )
117  return false;
118  // if aAnchorA is not placed in a footnote, and aAnchorB is
119  // force a change over
120  else if( !aAnchorAInFooter && aAnchorBInFooter )
121  return true;
122  // If neither or both are in the footer, compare the positions.
123  // Since footnotes are in Inserts section of nodes array and footers
124  // in Autotext section, all footnotes precede any footers so no need
125  // to check that.
126  else
127  return aPosAnchorA < aPosAnchorB;
128  }
129 
131  void lcl_CommentNotification(const SwView* pView, const CommentNotificationType nType, const SwSidebarItem* pItem, const sal_uInt32 nPostItId)
132  {
134  return;
135 
136  boost::property_tree::ptree aAnnotation;
137  aAnnotation.put("action", (nType == CommentNotificationType::Add ? "Add" :
138  (nType == CommentNotificationType::Remove ? "Remove" :
139  (nType == CommentNotificationType::Modify ? "Modify" :
140  (nType == CommentNotificationType::Resolve ? "Resolve" : "???")))));
141  aAnnotation.put("id", nPostItId);
142  if (nType != CommentNotificationType::Remove && pItem != nullptr)
143  {
145 
146  const SwPostItField* pField = pWin->GetPostItField();
147  const SwRect& aRect = pWin->GetAnchorRect();
148  tools::Rectangle aSVRect(aRect.Pos().getX(),
149  aRect.Pos().getY(),
150  aRect.Pos().getX() + aRect.SSize().Width(),
151  aRect.Pos().getY() + aRect.SSize().Height());
152 
154  {
155  // Comments on frames: anchor position is the corner position, not the whole frame.
156  aSVRect.SetSize(Size(0, 0));
157  }
158 
159  std::vector<OString> aRects;
160  for (const basegfx::B2DRange& aRange : pWin->GetAnnotationTextRanges())
161  {
162  const SwRect rect(aRange.getMinX(), aRange.getMinY(), aRange.getWidth(), aRange.getHeight());
163  aRects.push_back(rect.SVRect().toString());
164  }
165  const OString sRects = comphelper::string::join("; ", aRects);
166 
167  aAnnotation.put("id", pField->GetPostItId());
168  aAnnotation.put("parent", pWin->CalcParent());
169  aAnnotation.put("author", pField->GetPar1().toUtf8().getStr());
170  aAnnotation.put("text", pField->GetPar2().toUtf8().getStr());
171  aAnnotation.put("resolved", pField->GetResolved() ? "true" : "false");
172  aAnnotation.put("dateTime", utl::toISO8601(pField->GetDateTime().GetUNODateTime()));
173  aAnnotation.put("anchorPos", aSVRect.toString());
174  aAnnotation.put("textRange", sRects.getStr());
175  }
176 
177  boost::property_tree::ptree aTree;
178  aTree.add_child("comment", aAnnotation);
179  std::stringstream aStream;
180  boost::property_tree::write_json(aStream, aTree);
181  std::string aPayload = aStream.str();
182 
183  if (pView)
184  {
185  pView->libreOfficeKitViewCallback(LOK_CALLBACK_COMMENT, aPayload.c_str());
186  }
187  }
188 
189 } // anonymous namespace
190 
192  : mpView(pView)
193  , mpWrtShell(mpView->GetDocShell()->GetWrtShell())
194  , mpEditWin(&mpView->GetEditWin())
195  , mnEventId(nullptr)
196  , mbWaitingForCalcRects(false)
197  , mpActivePostIt(nullptr)
198  , mbLayout(false)
199  , mbLayoutHeight(0)
200  , mbLayouting(false)
201  , mbReadOnly(mpView->GetDocShell()->IsReadOnly())
202  , mbDeleteNote(true)
203  , mbIsShowAnchor( false )
204 {
205  if(!mpView->GetDrawView() )
207 
208  SwNoteProps aProps;
209  mbIsShowAnchor = aProps.IsShowAnchor();
210 
211  //make sure we get the colour yellow always, even if not the first one of comments or redlining
212  SW_MOD()->GetRedlineAuthor();
213 
214  // collect all PostIts and redline comments that exist after loading the document
215  // don't check for existence for any of them, don't focus them
216  AddPostIts(false,false);
217  /* this code can be used once we want redline comments in the Sidebar
218  AddRedlineComments(false,false);
219  */
220  // we want to receive stuff like SfxHintId::DocChanged
222  if (!mvPostItFields.empty())
223  {
224  mbWaitingForCalcRects = true;
226  }
227 }
228 
230 {
231  if ( mnEventId )
233  // forget about all our Sidebar windows
236 
237  mPages.clear();
238 }
239 
241 {
243  bool bRemoved = false;
244  auto it = mvPostItFields.begin();
245  while(it != mvPostItFields.end())
246  {
247  if (!(*it)->UseElement(*mpWrtShell->GetLayout(), rIDRA))
248  {
249  EndListening(const_cast<SfxBroadcaster&>(*(*it)->GetBroadcaster()));
250  std::unique_ptr<SwSidebarItem> p = std::move(*it);
251  it = mvPostItFields.erase(it);
252  if (GetActiveSidebarWin() == p->mpPostIt)
253  SetActiveSidebarWin(nullptr);
254  p->mpPostIt.disposeAndClear();
255  bRemoved = true;
256  }
257  else
258  ++it;
259  }
260 
261  if ( !bRemoved )
262  return;
263 
264  // make sure that no deleted items remain in page lists
265  // todo: only remove deleted ones?!
266  if ( mvPostItFields.empty() )
267  {
269  PrepareView();
270  }
271  else
272  // if postits are their make sure that page lists are not empty
273  // otherwise sudden paints can cause pain (in BorderOverPageBorder)
274  CalcRects();
275 }
276 
277 SwSidebarItem* SwPostItMgr::InsertItem(SfxBroadcaster* pItem, bool bCheckExistence, bool bFocus)
278 {
279  if (bCheckExistence)
280  {
281  for (auto const& postItField : mvPostItFields)
282  {
283  if ( postItField->GetBroadcaster() == pItem )
284  return nullptr;
285  }
286  }
287  mbLayout = bFocus;
288 
289  SwSidebarItem* pAnnotationItem = nullptr;
290  if (auto pSwFormatField = dynamic_cast< SwFormatField *>( pItem ))
291  {
292  mvPostItFields.push_back(std::make_unique<SwAnnotationItem>(*pSwFormatField, bFocus));
293  pAnnotationItem = mvPostItFields.back().get();
294  }
295  assert(dynamic_cast< const SwFormatField *>( pItem ) && "Mgr::InsertItem: seems like new stuff was added");
296  StartListening(*pItem);
297  return pAnnotationItem;
298 }
299 
301 {
302  EndListening(*pBroadcast);
303  auto i = std::find_if(mvPostItFields.begin(), mvPostItFields.end(),
304  [&pBroadcast](const std::unique_ptr<SwSidebarItem>& pField) { return pField->GetBroadcaster() == pBroadcast; });
305  if (i != mvPostItFields.end())
306  {
307  std::unique_ptr<SwSidebarItem> p = std::move(*i);
308  // tdf#120487 remove from list before dispose, so comment window
309  // won't be recreated due to the entry still in the list if focus
310  // transferring from the pPostIt triggers relayout of postits
311  // tdf#133348 remove from list before calling SetActiveSidebarWin
312  // so GetNextPostIt won't deal with mvPostItFields containing empty unique_ptr
313  mvPostItFields.erase(i);
314  if (GetActiveSidebarWin() == p->mpPostIt)
315  SetActiveSidebarWin(nullptr);
316  p->mpPostIt.disposeAndClear();
317  }
318  mbLayout = true;
319  PrepareView();
320 }
321 
322 void SwPostItMgr::Notify( SfxBroadcaster& rBC, const SfxHint& rHint )
323 {
324  if ( const SfxEventHint* pSfxEventHint = dynamic_cast<const SfxEventHint*>(&rHint) )
325  {
326  if ( pSfxEventHint->GetEventId() == SfxEventHintId::SwEventLayoutFinished )
327  {
328  if ( !mbWaitingForCalcRects && !mvPostItFields.empty())
329  {
330  mbWaitingForCalcRects = true;
332  }
333  }
334  }
335  else if ( const SwFormatFieldHint * pFormatHint = dynamic_cast<const SwFormatFieldHint*>(&rHint) )
336  {
337  SwFormatField* pField = const_cast <SwFormatField*>( pFormatHint->GetField() );
338  switch ( pFormatHint->Which() )
339  {
341  {
342  if (!pField)
343  {
344  AddPostIts();
345  break;
346  }
347  // get field to be inserted from hint
348  if ( pField->IsFieldInDoc() )
349  {
350  bool bEmpty = !HasNotes();
351  SwSidebarItem* pItem = InsertItem( pField, true, false );
352 
353  if (bEmpty && !mvPostItFields.empty())
354  PrepareView(true);
355 
356  // True until the layout of this post it finishes
357  if (pItem)
358  pItem->mbPendingLayout = true;
359  }
360  else
361  {
362  OSL_FAIL("Inserted field not in document!" );
363  }
364  break;
365  }
367  {
368  if (mbDeleteNote)
369  {
370  if (!pField)
371  {
373  break;
374  }
375  RemoveItem(pField);
376 
377  // If LOK has disabled tiled annotations, emit annotation callbacks
379  {
380  SwPostItField* pPostItField = static_cast<SwPostItField*>(pField->GetField());
381  lcl_CommentNotification(mpView, CommentNotificationType::Remove, nullptr, pPostItField->GetPostItId());
382  }
383  }
384  break;
385  }
387  {
388  if (pFormatHint->GetView()== mpView)
389  Focus(rBC);
390  break;
391  }
394  {
395  SwFormatField* pFormatField = dynamic_cast<SwFormatField*>(&rBC);
396  for (auto const& postItField : mvPostItFields)
397  {
398  if ( pFormatField == postItField->GetBroadcaster() )
399  {
400  if (postItField->mpPostIt)
401  {
402  postItField->mpPostIt->SetPostItText();
403  mbLayout = true;
404  }
405 
406  // If LOK has disabled tiled annotations, emit annotation callbacks
408  {
409  if(SwFormatFieldHintWhich::CHANGED == pFormatHint->Which())
410  lcl_CommentNotification(mpView, CommentNotificationType::Modify, postItField.get(), 0);
411  else
412  lcl_CommentNotification(mpView, CommentNotificationType::Resolve, postItField.get(), 0);
413  }
414  break;
415  }
416  }
417  break;
418  }
419 
421  {
422  SwFormatField* pFormatField = dynamic_cast<SwFormatField*>(&rBC);
423  for (auto const& postItField : mvPostItFields)
424  {
425  if ( pFormatField == postItField->GetBroadcaster() )
426  {
427  if (postItField->mpPostIt)
428  {
429  const SvtScriptType nScriptType = SvtLanguageOptions::GetScriptTypeOfLanguage( postItField->GetFormatField().GetField()->GetLanguage() );
430  sal_uInt16 nLangWhichId = 0;
431  switch (nScriptType)
432  {
433  case SvtScriptType::LATIN : nLangWhichId = EE_CHAR_LANGUAGE ; break;
434  case SvtScriptType::ASIAN : nLangWhichId = EE_CHAR_LANGUAGE_CJK; break;
435  case SvtScriptType::COMPLEX : nLangWhichId = EE_CHAR_LANGUAGE_CTL; break;
436  default: break;
437  }
438  postItField->mpPostIt->SetLanguage(
440  postItField->GetFormatField().GetField()->GetLanguage(),
441  nLangWhichId) );
442  }
443  break;
444  }
445  }
446  break;
447  }
448  }
449  }
450  else
451  {
452  SfxHintId nId = rHint.GetId();
453  switch ( nId )
454  {
455  case SfxHintId::ModeChanged:
456  {
457  if ( mbReadOnly != mpView->GetDocShell()->IsReadOnly() )
458  {
461  mbLayout = true;
462  }
463  break;
464  }
465  case SfxHintId::DocChanged:
466  {
467  if ( mpView->GetDocShell() == &rBC )
468  {
469  if ( !mbWaitingForCalcRects && !mvPostItFields.empty())
470  {
471  mbWaitingForCalcRects = true;
473  }
474  }
475  break;
476  }
477  case SfxHintId::SwSplitNodeOperation:
478  {
479  // if we are in a SplitNode/Cut operation, do not delete note and then add again, as this will flicker
481  break;
482  }
483  case SfxHintId::Dying:
484  {
485  if ( mpView->GetDocShell() != &rBC )
486  {
487  // field to be removed is the broadcaster
488  OSL_FAIL("Notification for removed SwFormatField was not sent!");
489  RemoveItem(&rBC);
490  }
491  break;
492  }
493  default: break;
494  }
495  }
496 }
497 
499 {
501  {
502  SfxRequest aRequest(mpView->GetViewFrame(), SID_TOGGLE_NOTES);
503  mpView->ExecViewOptions(aRequest);
504  }
505 
506  for (auto const& postItField : mvPostItFields)
507  {
508  // field to get the focus is the broadcaster
509  if ( &rBC == postItField->GetBroadcaster() )
510  {
511  if (postItField->mpPostIt)
512  {
513  postItField->mpPostIt->GrabFocus();
514  MakeVisible(postItField->mpPostIt);
515  }
516  else
517  {
518  // when the layout algorithm starts, this postit is created and receives focus
519  postItField->mbFocus = true;
520  }
521  }
522  }
523 }
524 
526 {
527  if ( mnEventId )
528  {
529  // if CalcRects() was forced and an event is still pending: remove it
530  // it is superfluous and also may cause reentrance problems if triggered while layouting
532  mnEventId = nullptr;
533  }
534 
535  bool bChange = false;
536  bool bRepair = false;
538  if ( !mvPostItFields.empty() )
539  {
541  for (auto const& pItem : mvPostItFields)
542  {
543  if (!pItem->UseElement(*mpWrtShell->GetLayout(), rIDRA))
544  {
545  OSL_FAIL("PostIt is not in doc or other wrong use");
546  bRepair = true;
547  continue;
548  }
549  const SwRect aOldAnchorRect( pItem->maLayoutInfo.mPosition );
550  const SwPostItHelper::SwLayoutStatus eOldLayoutStatus = pItem->mLayoutStatus;
551  const SwNodeOffset nOldStartNodeIdx( pItem->maLayoutInfo.mnStartNodeIdx );
552  const sal_Int32 nOldStartContent( pItem->maLayoutInfo.mnStartContent );
553  {
554  // update layout information
555  const SwTextAnnotationField* pTextAnnotationField =
556  dynamic_cast< const SwTextAnnotationField* >( pItem->GetFormatField().GetTextField() );
557  const ::sw::mark::IMark* pAnnotationMark =
558  pTextAnnotationField != nullptr ? pTextAnnotationField->GetAnnotationMark() : nullptr;
559  if ( pAnnotationMark != nullptr )
560  {
561  pItem->mLayoutStatus =
563  pItem->maLayoutInfo,
564  pItem->GetAnchorPosition(),
565  pAnnotationMark );
566  }
567  else
568  {
569  pItem->mLayoutStatus =
571  }
572  }
573  bChange = bChange
574  || pItem->maLayoutInfo.mPosition != aOldAnchorRect
575  || pItem->mLayoutStatus != eOldLayoutStatus
576  || pItem->maLayoutInfo.mnStartNodeIdx != nOldStartNodeIdx
577  || pItem->maLayoutInfo.mnStartContent != nOldStartContent;
578  }
579 
580  // show notes in right order in navigator
581  //prevent Anchors during layout to overlap, e.g. when moving a frame
582  if (mvPostItFields.size()>1 )
583  std::stable_sort(mvPostItFields.begin(), mvPostItFields.end(), comp_pos);
584 
585  // sort the items into the right page vector, so layout can be done by page
586  for (auto const& pItem : mvPostItFields)
587  {
589  {
590  if (pItem->mpPostIt)
591  pItem->mpPostIt->HideNote();
592  continue;
593  }
594 
595  if( SwPostItHelper::HIDDEN == pItem->mLayoutStatus )
596  {
598  {
599  if (pItem->mpPostIt)
600  pItem->mpPostIt->HideNote();
601  continue;
602  }
603  }
604 
605  const tools::ULong aPageNum = pItem->maLayoutInfo.mnPageNumber;
606  if (aPageNum > mPages.size())
607  {
608  const tools::ULong nNumberOfPages = mPages.size();
609  mPages.reserve(aPageNum);
610  for (tools::ULong j=0; j<aPageNum - nNumberOfPages; ++j)
611  mPages.emplace_back( new SwPostItPageItem());
612  }
613  mPages[aPageNum-1]->mvSidebarItems.push_back(pItem.get());
614  mPages[aPageNum-1]->mPageRect = pItem->maLayoutInfo.mPageFrame;
615  mPages[aPageNum-1]->eSidebarPosition = pItem->maLayoutInfo.meSidebarPosition;
616  }
617 
619  {
621  if( nLayoutHeight > mbLayoutHeight )
622  {
623  if (mPages[0]->bScrollbar || HasScrollbars())
624  bChange = true;
625  }
626  else if( nLayoutHeight < mbLayoutHeight )
627  {
628  if (mPages[0]->bScrollbar || !BorderOverPageBorder(1))
629  bChange = true;
630  }
631  }
632  }
633 
634  if ( bRepair )
636 
638  mbWaitingForCalcRects = false;
639  return bChange;
640 }
641 
643 {
644  for (auto const& postItField : mvPostItFields)
645  {
646  if (postItField->mbShow && postItField->mpPostIt && postItField->mpPostIt->HasScrollbar())
647  return true;
648  }
649  return false;
650 }
651 
653 {
654  // we do not just delete the SwPostItPageItem, so offset/scrollbar is not lost
655  tools::Long lPageSize = mpWrtShell->GetNumPages();
656  tools::Long lContainerSize = mPages.size();
657 
658  if (lContainerSize < lPageSize)
659  {
660  mPages.reserve(lPageSize);
661  for (tools::Long i=0; i<lPageSize - lContainerSize;i++)
662  mPages.emplace_back( new SwPostItPageItem());
663  }
664  else if (lContainerSize > lPageSize)
665  {
666  for (int i=mPages.size()-1; i >= lPageSize;--i)
667  {
668  mPages.pop_back();
669  }
670  }
671  // only clear the list, DO NOT delete the objects itself
672  for (auto const& page : mPages)
673  {
674  page->mvSidebarItems.clear();
675  if (mvPostItFields.empty())
676  page->bScrollbar = false;
677  }
678 }
679 
681 {
682  bool bEnableMapMode = comphelper::LibreOfficeKit::isActive() && !mpEditWin->IsMapModeEnabled();
683  if (bEnableMapMode)
685 
686  if ( !mvPostItFields.empty() && !mbWaitingForCalcRects )
687  {
688  mbLayouting = true;
689 
690  //loop over all pages and do the layout
691  // - create SwPostIt if necessary
692  // - place SwPostIts on their initial position
693  // - calculate necessary height for all PostIts together
694  bool bUpdate = false;
695  for (std::unique_ptr<SwPostItPageItem>& pPage : mPages)
696  {
697  // only layout if there are notes on this page
698  if (!pPage->mvSidebarItems.empty())
699  {
700  std::vector<SwAnnotationWin*> aVisiblePostItList;
701  tools::ULong lNeededHeight = 0;
702  tools::Long mlPageBorder = 0;
703  tools::Long mlPageEnd = 0;
704 
705  for (auto const& pItem : pPage->mvSidebarItems)
706  {
707  VclPtr<SwAnnotationWin> pPostIt = pItem->mpPostIt;
708 
709  if (pPage->eSidebarPosition == sw::sidebarwindows::SidebarPosition::LEFT )
710  {
711  // x value for notes positioning
712  mlPageBorder = mpEditWin->LogicToPixel( Point( pPage->mPageRect.Left(), 0)).X() - GetSidebarWidth(true);// - GetSidebarBorderWidth(true);
713  //bending point
714  mlPageEnd =
716  ? pItem->maLayoutInfo.mPagePrtArea.Left()
717  : pPage->mPageRect.Left() + 350;
718  }
719  else if (pPage->eSidebarPosition == sw::sidebarwindows::SidebarPosition::RIGHT )
720  {
721  // x value for notes positioning
722  mlPageBorder = mpEditWin->LogicToPixel( Point(pPage->mPageRect.Right(), 0)).X() + GetSidebarBorderWidth(true);
723  //bending point
724  mlPageEnd =
726  ? pItem->maLayoutInfo.mPagePrtArea.Right() :
727  pPage->mPageRect.Right() - 350;
728  }
729 
730  if (pItem->mbShow)
731  {
733  tools::Long aPostItHeight = 0;
734  if (!pPostIt)
735  {
736  pPostIt = pItem->GetSidebarWindow( mpView->GetEditWin(),
737  *this );
738  pPostIt->InitControls();
739  pPostIt->SetReadonly(mbReadOnly);
740  pItem->mpPostIt = pPostIt;
741  if (mpAnswer)
742  {
743  if (static_cast<bool>(pPostIt->CalcParent())) //do we really have another note in front of this one
744  pPostIt->InitAnswer(*mpAnswer);
745  mpAnswer.reset();
746  }
747  }
748 
749  pPostIt->SetChangeTracking(
750  pItem->mLayoutStatus,
752  pPostIt->SetSidebarPosition(pPage->eSidebarPosition);
753  pPostIt->SetFollow(static_cast<bool>(pPostIt->CalcParent()));
754  aPostItHeight = ( pPostIt->GetPostItTextHeight() < pPostIt->GetMinimumSizeWithoutMeta()
755  ? pPostIt->GetMinimumSizeWithoutMeta()
756  : pPostIt->GetPostItTextHeight() )
757  + pPostIt->GetMetaHeight();
758  pPostIt->SetPosSizePixelRect( mlPageBorder ,
760  GetSidebarWidth(true),
761  aPostItHeight,
762  pItem->maLayoutInfo.mPosition,
763  mlPageEnd );
764  pPostIt->ChangeSidebarItem( *pItem );
765 
766  if (pItem->mbFocus)
767  {
768  mbLayout = true;
769  pPostIt->GrabFocus();
770  pItem->mbFocus = false;
771  }
772  // only the visible postits are used for the final layout
773  aVisiblePostItList.push_back(pPostIt);
774  lNeededHeight += pPostIt->IsFollow() ? aPostItHeight : aPostItHeight+GetSpaceBetween();
775  }
776  else // we don't want to see it
777  {
778  if (pPostIt)
779  pPostIt->HideNote();
780  }
781  }
782 
783  if ((!aVisiblePostItList.empty()) && ShowNotes())
784  {
785  bool bOldScrollbar = pPage->bScrollbar;
786  if (ShowNotes())
787  pPage->bScrollbar = LayoutByPage(aVisiblePostItList, pPage->mPageRect.SVRect(), lNeededHeight);
788  else
789  pPage->bScrollbar = false;
790  if (!pPage->bScrollbar)
791  {
792  pPage->lOffset = 0;
793  }
794  else if (sal_Int32 nScrollSize = GetScrollSize())
795  {
796  //when we changed our zoom level, the offset value can be too big, so lets check for the largest possible zoom value
797  tools::Long aAvailableHeight = mpEditWin->LogicToPixel(Size(0,pPage->mPageRect.Height())).Height() - 2 * GetSidebarScrollerHeight();
798  tools::Long lOffset = -1 * nScrollSize * (aVisiblePostItList.size() - aAvailableHeight / nScrollSize);
799  if (pPage->lOffset < lOffset)
800  pPage->lOffset = lOffset;
801  }
802  bUpdate = (bOldScrollbar != pPage->bScrollbar) || bUpdate;
803  const tools::Long aSidebarheight = pPage->bScrollbar ? mpEditWin->PixelToLogic(Size(0,GetSidebarScrollerHeight())).Height() : 0;
804  /*
805  TODO
806  - enlarge all notes till GetNextBorder(), as we resized to average value before
807  */
808  //lets hide the ones which overlap the page
809  for (auto const& visiblePostIt : aVisiblePostItList)
810  {
811  if (pPage->lOffset != 0)
812  visiblePostIt->TranslateTopPosition(pPage->lOffset);
813 
814  bool bBottom = mpEditWin->PixelToLogic(Point(0,visiblePostIt->VirtualPos().Y()+visiblePostIt->VirtualSize().Height())).Y() <= (pPage->mPageRect.Bottom()-aSidebarheight);
815  bool bTop = mpEditWin->PixelToLogic(Point(0,visiblePostIt->VirtualPos().Y())).Y() >= (pPage->mPageRect.Top()+aSidebarheight);
816  if ( bBottom && bTop )
817  {
818  // When tiled rendering, make sure that only the
819  // view that has the comment focus emits callbacks,
820  // so the editing view jumps to the comment, but
821  // not the others.
822  bool bTiledPainting = comphelper::LibreOfficeKit::isTiledPainting();
823  if (!bTiledPainting)
824  // No focus -> disable callbacks.
825  comphelper::LibreOfficeKit::setTiledPainting(!visiblePostIt->HasChildPathFocus());
826  visiblePostIt->ShowNote();
827  if (!bTiledPainting)
829  }
830  else
831  {
832  if (mpEditWin->PixelToLogic(Point(0,visiblePostIt->VirtualPos().Y())).Y() < (pPage->mPageRect.Top()+aSidebarheight))
833  {
834  if ( pPage->eSidebarPosition == sw::sidebarwindows::SidebarPosition::LEFT )
835  visiblePostIt->ShowAnchorOnly(Point( pPage->mPageRect.Left(),
836  pPage->mPageRect.Top()));
837  else if ( pPage->eSidebarPosition == sw::sidebarwindows::SidebarPosition::RIGHT )
838  visiblePostIt->ShowAnchorOnly(Point( pPage->mPageRect.Right(),
839  pPage->mPageRect.Top()));
840  }
841  else
842  {
843  if ( pPage->eSidebarPosition == sw::sidebarwindows::SidebarPosition::LEFT )
844  visiblePostIt->ShowAnchorOnly(Point(pPage->mPageRect.Left(),
845  pPage->mPageRect.Bottom()));
846  else if ( pPage->eSidebarPosition == sw::sidebarwindows::SidebarPosition::RIGHT )
847  visiblePostIt->ShowAnchorOnly(Point(pPage->mPageRect.Right(),
848  pPage->mPageRect.Bottom()));
849  }
850  OSL_ENSURE(pPage->bScrollbar,"SwPostItMgr::LayoutByPage(): note overlaps, but bScrollbar is not true");
851  }
852  }
853  }
854  else
855  {
856  for (auto const& visiblePostIt : aVisiblePostItList)
857  {
858  visiblePostIt->SetPosAndSize();
859  }
860 
861  bool bOldScrollbar = pPage->bScrollbar;
862  pPage->bScrollbar = false;
863  bUpdate = (bOldScrollbar != pPage->bScrollbar) || bUpdate;
864  }
865 
866  for (auto const& visiblePostIt : aVisiblePostItList)
867  {
869  {
870  if (visiblePostIt->GetSidebarItem().mbPendingLayout)
871  lcl_CommentNotification(mpView, CommentNotificationType::Add, &visiblePostIt->GetSidebarItem(), 0);
872  else if (visiblePostIt->IsAnchorRectChanged())
873  {
874  lcl_CommentNotification(mpView, CommentNotificationType::Modify, &visiblePostIt->GetSidebarItem(), 0);
875  visiblePostIt->ResetAnchorRectChanged();
876  }
877  }
878 
879  // Layout for this post it finished now
880  visiblePostIt->GetSidebarItem().mbPendingLayout = false;
881  }
882  }
883  else
884  {
885  if (pPage->bScrollbar)
886  bUpdate = true;
887  pPage->bScrollbar = false;
888  }
889  }
890 
891  if (!ShowNotes())
892  { // we do not want to see the notes anymore -> Options-Writer-View-Notes
894  bool bRepair = false;
895  for (auto const& postItField : mvPostItFields)
896  {
897  if (!postItField->UseElement(*mpWrtShell->GetLayout(), rIDRA))
898  {
899  OSL_FAIL("PostIt is not in doc!");
900  bRepair = true;
901  continue;
902  }
903 
904  if (postItField->mpPostIt)
905  {
906  postItField->mpPostIt->HideNote();
907  if (postItField->mpPostIt->HasChildPathFocus())
908  {
909  SetActiveSidebarWin(nullptr);
910  postItField->mpPostIt->GrabFocusToDocument();
911  }
912  }
913  }
914 
915  if ( bRepair )
917  }
918 
919  // notes scrollbar is otherwise not drawn correctly for some cases
920  // scrollbar area is enough
921  if (bUpdate)
922  mpEditWin->Invalidate(); /*This is a super expensive relayout and render of the entire page*/
923 
924  mbLayouting = false;
925  }
926 
927  if (bEnableMapMode)
928  mpEditWin->EnableMapMode(false);
929 }
930 
932 {
933  if ( mPages[aPage-1]->mvSidebarItems.empty() )
934  {
935  OSL_FAIL("Notes SidePane painted but no rects and page lists calculated!");
936  return false;
937  }
938 
939  auto aItem = mPages[aPage-1]->mvSidebarItems.end();
940  --aItem;
941  OSL_ENSURE ((*aItem)->mpPostIt,"BorderOverPageBorder: NULL postIt, should never happen");
942  if ((*aItem)->mpPostIt)
943  {
944  const tools::Long aSidebarheight = mPages[aPage-1]->bScrollbar ? mpEditWin->PixelToLogic(Size(0,GetSidebarScrollerHeight())).Height() : 0;
945  const tools::Long aEndValue = mpEditWin->PixelToLogic(Point(0,(*aItem)->mpPostIt->GetPosPixel().Y()+(*aItem)->mpPostIt->GetSizePixel().Height())).Y();
946  return aEndValue <= mPages[aPage-1]->mPageRect.Bottom()-aSidebarheight;
947  }
948  else
949  return false;
950 }
951 
952 void SwPostItMgr::DrawNotesForPage(OutputDevice *pOutDev, sal_uInt32 nPage)
953 {
954  assert(nPage < mPages.size());
955  if (nPage >= mPages.size())
956  return;
957  for (auto const& pItem : mPages[nPage]->mvSidebarItems)
958  {
959  SwAnnotationWin* pPostIt = pItem->mpPostIt;
960  if (!pPostIt)
961  continue;
962  Point aPoint(mpEditWin->PixelToLogic(pPostIt->GetPosPixel()));
963  pPostIt->DrawForPage(pOutDev, aPoint);
964  }
965 }
966 
968 {
969  for (const std::unique_ptr<SwSidebarItem>& pItem : mvPostItFields)
970  {
971  SwAnnotationWin* pPostIt = pItem->mpPostIt;
972  if (!pPostIt)
973  continue;
974 
975  bool bEnableMapMode = !mpEditWin->IsMapModeEnabled();
977  rRenderContext.Push(vcl::PushFlags::MAPMODE);
978  Point aOffset(mpEditWin->PixelToLogic(pPostIt->GetPosPixel()));
979  MapMode aMapMode(rRenderContext.GetMapMode());
980  aMapMode.SetOrigin(aMapMode.GetOrigin() + aOffset);
981  rRenderContext.SetMapMode(aMapMode);
982  Size aSize(rRenderContext.PixelToLogic(pPostIt->GetSizePixel()));
983  tools::Rectangle aRectangle(Point(0, 0), aSize);
984 
985  pPostIt->PaintTile(rRenderContext, aRectangle);
986 
987  rRenderContext.Pop();
988  if (bEnableMapMode)
989  mpEditWin->EnableMapMode(false);
990  }
991 }
992 
993 void SwPostItMgr::Scroll(const tools::Long lScroll,const tools::ULong aPage)
994 {
995  OSL_ENSURE((lScroll % GetScrollSize() )==0,"SwPostItMgr::Scroll: scrolling by wrong value");
996  // do not scroll more than necessary up or down
997  if ( ((mPages[aPage-1]->lOffset == 0) && (lScroll>0)) || ( BorderOverPageBorder(aPage) && (lScroll<0)) )
998  return;
999 
1000  const bool bOldUp = ArrowEnabled(KEY_PAGEUP,aPage);
1001  const bool bOldDown = ArrowEnabled(KEY_PAGEDOWN,aPage);
1002  const tools::Long aSidebarheight = mpEditWin->PixelToLogic(Size(0,GetSidebarScrollerHeight())).Height();
1003  for (auto const& item : mPages[aPage-1]->mvSidebarItems)
1004  {
1005  SwAnnotationWin* pPostIt = item->mpPostIt;
1006  // if this is an answer, we should take the normal position and not the real, slightly moved position
1007  pPostIt->SetVirtualPosSize(pPostIt->GetPosPixel(),pPostIt->GetSizePixel());
1008  pPostIt->TranslateTopPosition(lScroll);
1009 
1010  if (item->mbShow)
1011  {
1012  bool bBottom = mpEditWin->PixelToLogic(Point(0,pPostIt->VirtualPos().Y()+pPostIt->VirtualSize().Height())).Y() <= (mPages[aPage-1]->mPageRect.Bottom()-aSidebarheight);
1013  bool bTop = mpEditWin->PixelToLogic(Point(0,pPostIt->VirtualPos().Y())).Y() >= (mPages[aPage-1]->mPageRect.Top()+aSidebarheight);
1014  if ( bBottom && bTop)
1015  {
1016  pPostIt->ShowNote();
1017  }
1018  else
1019  {
1020  if ( mpEditWin->PixelToLogic(Point(0,pPostIt->VirtualPos().Y())).Y() < (mPages[aPage-1]->mPageRect.Top()+aSidebarheight))
1021  {
1022  if (mPages[aPage-1]->eSidebarPosition == sw::sidebarwindows::SidebarPosition::LEFT)
1023  pPostIt->ShowAnchorOnly(Point(mPages[aPage-1]->mPageRect.Left(),mPages[aPage-1]->mPageRect.Top()));
1024  else if (mPages[aPage-1]->eSidebarPosition == sw::sidebarwindows::SidebarPosition::RIGHT)
1025  pPostIt->ShowAnchorOnly(Point(mPages[aPage-1]->mPageRect.Right(),mPages[aPage-1]->mPageRect.Top()));
1026  }
1027  else
1028  {
1029  if (mPages[aPage-1]->eSidebarPosition == sw::sidebarwindows::SidebarPosition::LEFT)
1030  pPostIt->ShowAnchorOnly(Point(mPages[aPage-1]->mPageRect.Left(),mPages[aPage-1]->mPageRect.Bottom()));
1031  else if (mPages[aPage-1]->eSidebarPosition == sw::sidebarwindows::SidebarPosition::RIGHT)
1032  pPostIt->ShowAnchorOnly(Point(mPages[aPage-1]->mPageRect.Right(),mPages[aPage-1]->mPageRect.Bottom()));
1033  }
1034  }
1035  }
1036  }
1037  mPages[aPage-1]->lOffset += lScroll;
1038  if ( (bOldUp != ArrowEnabled(KEY_PAGEUP,aPage)) ||(bOldDown != ArrowEnabled(KEY_PAGEDOWN,aPage)) )
1039  {
1042  }
1043 }
1044 
1045 void SwPostItMgr::AutoScroll(const SwAnnotationWin* pPostIt,const tools::ULong aPage )
1046 {
1047  // otherwise all notes are visible
1048  if (!mPages[aPage-1]->bScrollbar)
1049  return;
1050 
1051  const tools::Long aSidebarheight = mpEditWin->PixelToLogic(Size(0,GetSidebarScrollerHeight())).Height();
1052  const bool bBottom = mpEditWin->PixelToLogic(Point(0,pPostIt->GetPosPixel().Y()+pPostIt->GetSizePixel().Height())).Y() <= (mPages[aPage-1]->mPageRect.Bottom()-aSidebarheight);
1053  const bool bTop = mpEditWin->PixelToLogic(Point(0,pPostIt->GetPosPixel().Y())).Y() >= (mPages[aPage-1]->mPageRect.Top()+aSidebarheight);
1054  if ( !(bBottom && bTop))
1055  {
1056  const tools::Long aDiff = bBottom ? mpEditWin->LogicToPixel(Point(0,mPages[aPage-1]->mPageRect.Top() + aSidebarheight)).Y() - pPostIt->GetPosPixel().Y() :
1057  mpEditWin->LogicToPixel(Point(0,mPages[aPage-1]->mPageRect.Bottom() - aSidebarheight)).Y() - (pPostIt->GetPosPixel().Y()+pPostIt->GetSizePixel().Height());
1058  // this just adds the missing value to get the next a* GetScrollSize() after aDiff
1059  // e.g aDiff= 61 POSTIT_SCROLL=50 --> lScroll = 100
1060  const auto nScrollSize = GetScrollSize();
1061  assert(nScrollSize);
1062  const tools::Long lScroll = bBottom ? (aDiff + ( nScrollSize - (aDiff % nScrollSize))) : (aDiff - (nScrollSize + (aDiff % nScrollSize)));
1063  Scroll(lScroll, aPage);
1064  }
1065 }
1066 
1068 {
1069  tools::Long aPage = -1;
1070  // we don't know the page yet, lets find it ourselves
1071  std::vector<SwPostItPageItem*>::size_type n=0;
1072  for (auto const& page : mPages)
1073  {
1074  for (auto const& item : page->mvSidebarItems)
1075  {
1076  if (item->mpPostIt==pPostIt)
1077  {
1078  aPage = n+1;
1079  break;
1080  }
1081  }
1082  ++n;
1083  }
1084  if (aPage!=-1)
1085  AutoScroll(pPostIt,aPage);
1086  tools::Rectangle aNoteRect (Point(pPostIt->GetPosPixel().X(),pPostIt->GetPosPixel().Y()-5),pPostIt->GetSizePixel());
1087  if (!aNoteRect.IsEmpty())
1089 }
1090 
1091 bool SwPostItMgr::ArrowEnabled(sal_uInt16 aDirection,tools::ULong aPage) const
1092 {
1093  switch (aDirection)
1094  {
1095  case KEY_PAGEUP:
1096  {
1097  return (mPages[aPage-1]->lOffset != 0);
1098  }
1099  case KEY_PAGEDOWN:
1100  {
1101  return (!BorderOverPageBorder(aPage));
1102  }
1103  default: return false;
1104  }
1105 }
1106 
1107 Color SwPostItMgr::GetArrowColor(sal_uInt16 aDirection,tools::ULong aPage) const
1108 {
1109  if (ArrowEnabled(aDirection,aPage))
1110  {
1111  if (Application::GetSettings().GetStyleSettings().GetHighContrastMode())
1112  return COL_WHITE;
1113  else
1115  }
1116  else
1117  {
1119  }
1120 }
1121 
1122 bool SwPostItMgr::LayoutByPage(std::vector<SwAnnotationWin*> &aVisiblePostItList, const tools::Rectangle& rBorder, tools::Long lNeededHeight)
1123 {
1124  /*** General layout idea:***/
1125  // - if we have space left, we always move the current one up,
1126  // otherwise the next one down
1127  // - first all notes are resized
1128  // - then the real layout starts
1129 
1130  //rBorder is the page rect
1131  const tools::Rectangle aBorder = mpEditWin->LogicToPixel(rBorder);
1132  tools::Long lTopBorder = aBorder.Top() + 5;
1133  tools::Long lBottomBorder = aBorder.Bottom() - 5;
1134  const tools::Long lVisibleHeight = lBottomBorder - lTopBorder; //aBorder.GetHeight() ;
1135  const size_t nPostItListSize = aVisiblePostItList.size();
1136  tools::Long lTranslatePos = 0;
1137  bool bScrollbars = false;
1138 
1139  // do all necessary resizings
1140  if (nPostItListSize > 0 && lVisibleHeight < lNeededHeight)
1141  {
1142  // ok, now we have to really resize and adding scrollbars
1143  const tools::Long lAverageHeight = (lVisibleHeight - nPostItListSize*GetSpaceBetween()) / nPostItListSize;
1144  if (lAverageHeight<GetMinimumSizeWithMeta())
1145  {
1146  bScrollbars = true;
1147  lTopBorder += GetSidebarScrollerHeight() + 10;
1148  lBottomBorder -= (GetSidebarScrollerHeight() + 10);
1149  for (auto const& visiblePostIt : aVisiblePostItList)
1150  visiblePostIt->SetSize(Size(visiblePostIt->VirtualSize().getWidth(),visiblePostIt->GetMinimumSizeWithMeta()));
1151  }
1152  else
1153  {
1154  for (auto const& visiblePostIt : aVisiblePostItList)
1155  {
1156  if ( visiblePostIt->VirtualSize().getHeight() > lAverageHeight)
1157  visiblePostIt->SetSize(Size(visiblePostIt->VirtualSize().getWidth(),lAverageHeight));
1158  }
1159  }
1160  }
1161 
1162  //start the real layout so nothing overlaps anymore
1163  if (aVisiblePostItList.size()>1)
1164  {
1165  int loop = 0;
1166  bool bDone = false;
1167  // if no window is moved anymore we are finished
1168  while (!bDone)
1169  {
1170  loop++;
1171  bDone = true;
1172  tools::Long lSpaceUsed = lTopBorder + GetSpaceBetween();
1173  for(auto i = aVisiblePostItList.begin(); i != aVisiblePostItList.end() ; ++i)
1174  {
1175  auto aNextPostIt = i;
1176  ++aNextPostIt;
1177 
1178  if (aNextPostIt != aVisiblePostItList.end())
1179  {
1180  lTranslatePos = ( (*i)->VirtualPos().Y() + (*i)->VirtualSize().Height()) - (*aNextPostIt)->VirtualPos().Y();
1181  if (lTranslatePos > 0) // note windows overlaps the next one
1182  {
1183  // we are not done yet, loop at least once more
1184  bDone = false;
1185  // if there is space left, move the current note up
1186  // it could also happen that there is no space left for the first note due to a scrollbar
1187  // then we also jump into, so we move the current one up and the next one down
1188  if ( (lSpaceUsed <= (*i)->VirtualPos().Y()) || (i==aVisiblePostItList.begin()))
1189  {
1190  // we have space left, so let's move the current one up
1191  if ( ((*i)->VirtualPos().Y()- lTranslatePos - GetSpaceBetween()) > lTopBorder)
1192  {
1193  if ((*aNextPostIt)->IsFollow())
1194  (*i)->TranslateTopPosition(-1*(lTranslatePos+ANCHORLINE_WIDTH));
1195  else
1196  (*i)->TranslateTopPosition(-1*(lTranslatePos+GetSpaceBetween()));
1197  }
1198  else
1199  {
1200  tools::Long lMoveUp = (*i)->VirtualPos().Y() - lTopBorder;
1201  (*i)->TranslateTopPosition(-1* lMoveUp);
1202  if ((*aNextPostIt)->IsFollow())
1203  (*aNextPostIt)->TranslateTopPosition( (lTranslatePos+ANCHORLINE_WIDTH) - lMoveUp);
1204  else
1205  (*aNextPostIt)->TranslateTopPosition( (lTranslatePos+GetSpaceBetween()) - lMoveUp);
1206  }
1207  }
1208  else
1209  {
1210  // no space left, left move the next one down
1211  if ((*aNextPostIt)->IsFollow())
1212  (*aNextPostIt)->TranslateTopPosition(lTranslatePos+ANCHORLINE_WIDTH);
1213  else
1214  (*aNextPostIt)->TranslateTopPosition(lTranslatePos+GetSpaceBetween());
1215  }
1216  }
1217  else
1218  {
1219  // the first one could overlap the topborder instead of a second note
1220  if (i==aVisiblePostItList.begin())
1221  {
1222  tools::Long lMoveDown = lTopBorder - (*i)->VirtualPos().Y();
1223  if (lMoveDown>0)
1224  {
1225  bDone = false;
1226  (*i)->TranslateTopPosition( lMoveDown);
1227  }
1228  }
1229  }
1230  if ( (*aNextPostIt)->IsFollow() )
1231  lSpaceUsed += (*i)->VirtualSize().Height() + ANCHORLINE_WIDTH;
1232  else
1233  lSpaceUsed += (*i)->VirtualSize().Height() + GetSpaceBetween();
1234  }
1235  else
1236  {
1237  //(*i) is the last visible item
1238  auto aPrevPostIt = i;
1239  --aPrevPostIt;
1240  lTranslatePos = ( (*aPrevPostIt)->VirtualPos().Y() + (*aPrevPostIt)->VirtualSize().Height() ) - (*i)->VirtualPos().Y();
1241  if (lTranslatePos > 0)
1242  {
1243  bDone = false;
1244  if ( ((*i)->VirtualPos().Y()+ (*i)->VirtualSize().Height()+lTranslatePos) < lBottomBorder)
1245  {
1246  if ( (*i)->IsFollow() )
1247  (*i)->TranslateTopPosition(lTranslatePos+ANCHORLINE_WIDTH);
1248  else
1249  (*i)->TranslateTopPosition(lTranslatePos+GetSpaceBetween());
1250  }
1251  else
1252  {
1253  (*i)->TranslateTopPosition(lBottomBorder - ((*i)->VirtualPos().Y()+ (*i)->VirtualSize().Height()) );
1254  }
1255  }
1256  else
1257  {
1258  // note does not overlap, but we might be over the lower border
1259  // only do this if there are no scrollbars, otherwise notes are supposed to overlap the border
1260  if (!bScrollbars && ((*i)->VirtualPos().Y()+ (*i)->VirtualSize().Height() > lBottomBorder) )
1261  {
1262  bDone = false;
1263  (*i)->TranslateTopPosition(lBottomBorder - ((*i)->VirtualPos().Y()+ (*i)->VirtualSize().Height()));
1264  }
1265  }
1266  }
1267  }
1268  // security check so we don't loop forever
1269  if (loop>MAX_LOOP_COUNT)
1270  {
1271  OSL_FAIL("PostItMgr::Layout(): We are looping forever");
1272  break;
1273  }
1274  }
1275  }
1276  else
1277  {
1278  // only one left, make sure it is not hidden at the top or bottom
1279  auto i = aVisiblePostItList.begin();
1280  lTranslatePos = lTopBorder - (*i)->VirtualPos().Y();
1281  if (lTranslatePos>0)
1282  {
1283  (*i)->TranslateTopPosition(lTranslatePos+GetSpaceBetween());
1284  }
1285  lTranslatePos = lBottomBorder - ((*i)->VirtualPos().Y()+ (*i)->VirtualSize().Height());
1286  if (lTranslatePos<0)
1287  {
1288  (*i)->TranslateTopPosition(lTranslatePos);
1289  }
1290  }
1291  return bScrollbars;
1292  }
1293 
1294 void SwPostItMgr::AddPostIts(const bool bCheckExistence, const bool bFocus)
1295 {
1296  const bool bEmpty = mvPostItFields.empty();
1299  std::vector<SwFormatField*> vFormatFields;
1300  pType->CollectPostIts(vFormatFields, rIDRA, mpWrtShell->GetLayout()->IsHideRedlines());
1301  for(auto pFormatField : vFormatFields)
1302  InsertItem(pFormatField, bCheckExistence, bFocus);
1303  // if we just added the first one we have to update the view for centering
1304  if (bEmpty && !mvPostItFields.empty())
1305  PrepareView(true);
1306 }
1307 
1309 {
1310  for (auto& postItField : mvPostItFields)
1311  {
1312  EndListening( *const_cast<SfxBroadcaster*>(postItField->GetBroadcaster()) );
1313  postItField->mpPostIt.disposeAndClear();
1314  postItField.reset();
1315  }
1316  mvPostItFields.clear();
1317 
1318  // all postits removed, no items should be left in pages
1320 }
1321 
1322 namespace {
1323 
1324 class FilterFunctor
1325 {
1326 public:
1327  virtual bool operator()(const SwFormatField* pField) const = 0;
1328  virtual ~FilterFunctor() {}
1329 };
1330 
1331 class IsPostitField : public FilterFunctor
1332 {
1333 public:
1334  bool operator()(const SwFormatField* pField) const override
1335  {
1336  return pField->GetField()->GetTyp()->Which() == SwFieldIds::Postit;
1337  }
1338 };
1339 
1340 class IsPostitFieldWithAuthorOf : public FilterFunctor
1341 {
1342  OUString m_sAuthor;
1343 public:
1344  explicit IsPostitFieldWithAuthorOf(const OUString &rAuthor)
1345  : m_sAuthor(rAuthor)
1346  {
1347  }
1348  bool operator()(const SwFormatField* pField) const override
1349  {
1350  if (pField->GetField()->GetTyp()->Which() != SwFieldIds::Postit)
1351  return false;
1352  return static_cast<const SwPostItField*>(pField->GetField())->GetPar1() == m_sAuthor;
1353  }
1354 };
1355 
1356 class IsPostitFieldWithPostitId : public FilterFunctor
1357 {
1358  sal_uInt32 m_nPostItId;
1359 public:
1360  explicit IsPostitFieldWithPostitId(sal_uInt32 nPostItId)
1361  : m_nPostItId(nPostItId)
1362  {}
1363 
1364  bool operator()(const SwFormatField* pField) const override
1365  {
1366  if (pField->GetField()->GetTyp()->Which() != SwFieldIds::Postit)
1367  return false;
1368  return static_cast<const SwPostItField*>(pField->GetField())->GetPostItId() == m_nPostItId;
1369  }
1370 };
1371 
1372 class IsFieldNotDeleted : public FilterFunctor
1373 {
1374 private:
1375  IDocumentRedlineAccess const& m_rIDRA;
1376  FilterFunctor const& m_rNext;
1377 
1378 public:
1379  IsFieldNotDeleted(IDocumentRedlineAccess const& rIDRA,
1380  const FilterFunctor & rNext)
1381  : m_rIDRA(rIDRA)
1382  , m_rNext(rNext)
1383  {
1384  }
1385  bool operator()(const SwFormatField* pField) const override
1386  {
1387  if (!m_rNext(pField))
1388  return false;
1389  if (!pField->GetTextField())
1390  return false;
1391  return !sw::IsFieldDeletedInModel(m_rIDRA, *pField->GetTextField());
1392  }
1393 };
1394 
1395 //Manages the passed in vector by automatically removing entries if they are deleted
1396 //and automatically adding entries if they appear in the document and match the
1397 //functor.
1398 //
1399 //This will completely refill in the case of a "anonymous" NULL pField stating
1400 //rather unhelpfully that "something changed" so you may process the same
1401 //Fields more than once.
1402 class FieldDocWatchingStack : public SfxListener
1403 {
1404  std::vector<std::unique_ptr<SwSidebarItem>>& sidebarItemVector;
1405  std::vector<const SwFormatField*> v;
1406  SwDocShell& m_rDocShell;
1407  FilterFunctor& m_rFilter;
1408 
1409  virtual void Notify(SfxBroadcaster&, const SfxHint& rHint) override
1410  {
1411  const SwFormatFieldHint* pHint = dynamic_cast<const SwFormatFieldHint*>(&rHint);
1412  if (!pHint)
1413  return;
1414 
1415  bool bAllInvalidated = false;
1416  if (pHint->Which() == SwFormatFieldHintWhich::REMOVED)
1417  {
1418  const SwFormatField* pField = pHint->GetField();
1419  bAllInvalidated = pField == nullptr;
1420  if (!bAllInvalidated && m_rFilter(pField))
1421  {
1422  EndListening(const_cast<SwFormatField&>(*pField));
1423  v.erase(std::remove(v.begin(), v.end(), pField), v.end());
1424  }
1425  }
1426  else if (pHint->Which() == SwFormatFieldHintWhich::INSERTED)
1427  {
1428  const SwFormatField* pField = pHint->GetField();
1429  bAllInvalidated = pField == nullptr;
1430  if (!bAllInvalidated && m_rFilter(pField))
1431  {
1432  StartListening(const_cast<SwFormatField&>(*pField));
1433  v.push_back(pField);
1434  }
1435  }
1436 
1437  if (bAllInvalidated)
1438  FillVector();
1439 
1440  return;
1441  }
1442 
1443 public:
1444  FieldDocWatchingStack(std::vector<std::unique_ptr<SwSidebarItem>>& in, SwDocShell &rDocShell, FilterFunctor& rFilter)
1445  : sidebarItemVector(in)
1446  , m_rDocShell(rDocShell)
1447  , m_rFilter(rFilter)
1448  {
1449  FillVector();
1450  StartListening(m_rDocShell);
1451  }
1452  void FillVector()
1453  {
1454  EndListeningToAllFields();
1455  v.clear();
1456  v.reserve(sidebarItemVector.size());
1457  for (auto const& p : sidebarItemVector)
1458  {
1459  const SwFormatField& rField = p->GetFormatField();
1460  if (!m_rFilter(&rField))
1461  continue;
1462  StartListening(const_cast<SwFormatField&>(rField));
1463  v.push_back(&rField);
1464  }
1465  }
1466  void EndListeningToAllFields()
1467  {
1468  for (auto const& pField : v)
1469  {
1470  EndListening(const_cast<SwFormatField&>(*pField));
1471  }
1472  }
1473  virtual ~FieldDocWatchingStack() override
1474  {
1475  EndListeningToAllFields();
1476  EndListening(m_rDocShell);
1477  }
1478  const SwFormatField* pop()
1479  {
1480  if (v.empty())
1481  return nullptr;
1482  const SwFormatField* p = v.back();
1483  EndListening(const_cast<SwFormatField&>(*p));
1484  v.pop_back();
1485  return p;
1486  }
1487 };
1488 
1489 }
1490 
1491 // copy to new vector, otherwise RemoveItem would operate and delete stuff on mvPostItFields as well
1492 // RemoveItem will clean up the core field and visible postit if necessary
1493 // we cannot just delete everything as before, as postits could move into change tracking
1494 void SwPostItMgr::Delete(const OUString& rAuthor)
1495 {
1497  if (HasActiveSidebarWin() && (GetActiveSidebarWin()->GetAuthor() == rAuthor))
1498  {
1499  SetActiveSidebarWin(nullptr);
1500  }
1501  SwRewriter aRewriter;
1502  aRewriter.AddRule(UndoArg1, SwResId(STR_DELETE_AUTHOR_NOTES) + rAuthor);
1503  mpWrtShell->StartUndo( SwUndoId::DELETE, &aRewriter );
1504 
1505  IsPostitFieldWithAuthorOf aFilter(rAuthor);
1507  IsFieldNotDeleted aFilter2(rIDRA, aFilter);
1508  FieldDocWatchingStack aStack(mvPostItFields, *mpView->GetDocShell(), aFilter2);
1509  while (const SwFormatField* pField = aStack.pop())
1510  {
1511  if (mpWrtShell->GotoField(*pField))
1512  mpWrtShell->DelRight();
1513  }
1514  mpWrtShell->EndUndo();
1515  PrepareView();
1517  mbLayout = true;
1518  CalcRects();
1519  LayoutPostIts();
1520 }
1521 
1522 void SwPostItMgr::Delete(sal_uInt32 nPostItId)
1523 {
1525  if (HasActiveSidebarWin() &&
1526  mpActivePostIt->GetPostItField()->GetPostItId() == nPostItId)
1527  {
1528  SetActiveSidebarWin(nullptr);
1529  }
1530  SwRewriter aRewriter;
1531  aRewriter.AddRule(UndoArg1, SwResId(STR_CONTENT_TYPE_SINGLE_POSTIT));
1532  mpWrtShell->StartUndo( SwUndoId::DELETE, &aRewriter );
1533 
1534  IsPostitFieldWithPostitId aFilter(nPostItId);
1536  IsFieldNotDeleted aFilter2(rIDRA, aFilter);
1537  FieldDocWatchingStack aStack(mvPostItFields, *mpView->GetDocShell(), aFilter2);
1538  const SwFormatField* pField = aStack.pop();
1539  if (pField && mpWrtShell->GotoField(*pField))
1540  mpWrtShell->DelRight();
1541  mpWrtShell->EndUndo();
1542  PrepareView();
1544  mbLayout = true;
1545  CalcRects();
1546  LayoutPostIts();
1547 }
1548 
1549 void SwPostItMgr::DeleteCommentThread(sal_uInt32 nPostItId)
1550 {
1552 
1553  SwRewriter aRewriter;
1554  aRewriter.AddRule(UndoArg1, SwResId(STR_CONTENT_TYPE_SINGLE_POSTIT));
1555 
1556  // We have no undo ID at the moment.
1557 
1558  IsPostitFieldWithPostitId aFilter(nPostItId);
1559  FieldDocWatchingStack aStack(mvPostItFields, *mpView->GetDocShell(), aFilter);
1560  const SwFormatField* pField = aStack.pop();
1561  // pField now contains our AnnotationWin object
1562  if (pField) {
1563  SwAnnotationWin* pWin = GetSidebarWin(pField);
1564  pWin->DeleteThread();
1565  }
1566  PrepareView();
1568  mbLayout = true;
1569  CalcRects();
1570  LayoutPostIts();
1571 }
1572 
1573 void SwPostItMgr::ToggleResolved(sal_uInt32 nPostItId)
1574 {
1576 
1577  SwRewriter aRewriter;
1578  aRewriter.AddRule(UndoArg1, SwResId(STR_CONTENT_TYPE_SINGLE_POSTIT));
1579 
1580  // We have no undo ID at the moment.
1581 
1582  IsPostitFieldWithPostitId aFilter(nPostItId);
1583  FieldDocWatchingStack aStack(mvPostItFields, *mpView->GetDocShell(), aFilter);
1584  const SwFormatField* pField = aStack.pop();
1585  // pField now contains our AnnotationWin object
1586  if (pField) {
1587  SwAnnotationWin* pWin = GetSidebarWin(pField);
1588  pWin->ToggleResolved();
1589  }
1590 
1591  PrepareView();
1593  mbLayout = true;
1594  CalcRects();
1595  LayoutPostIts();
1596 }
1597 
1598 void SwPostItMgr::ToggleResolvedForThread(sal_uInt32 nPostItId)
1599 {
1601 
1602  SwRewriter aRewriter;
1603  aRewriter.AddRule(UndoArg1, SwResId(STR_CONTENT_TYPE_SINGLE_POSTIT));
1604 
1605  // We have no undo ID at the moment.
1606 
1607  IsPostitFieldWithPostitId aFilter(nPostItId);
1608  FieldDocWatchingStack aStack(mvPostItFields, *mpView->GetDocShell(), aFilter);
1609  const SwFormatField* pField = aStack.pop();
1610  // pField now contains our AnnotationWin object
1611  if (pField) {
1612  SwAnnotationWin* pWin = GetSidebarWin(pField);
1613  pWin->ToggleResolvedForThread();
1614  }
1615 
1616  PrepareView();
1618  mbLayout = true;
1619  CalcRects();
1620  LayoutPostIts();
1621 }
1622 
1623 
1625 {
1627  SetActiveSidebarWin(nullptr);
1628  SwRewriter aRewriter;
1629  aRewriter.AddRule(UndoArg1, SwResId(STR_DELETE_ALL_NOTES) );
1630  mpWrtShell->StartUndo( SwUndoId::DELETE, &aRewriter );
1631 
1632  IsPostitField aFilter;
1634  IsFieldNotDeleted aFilter2(rIDRA, aFilter);
1635  FieldDocWatchingStack aStack(mvPostItFields, *mpView->GetDocShell(),
1636  aFilter2);
1637  while (const SwFormatField* pField = aStack.pop())
1638  {
1639  if (mpWrtShell->GotoField(*pField))
1640  mpWrtShell->DelRight();
1641  }
1642 
1643  mpWrtShell->EndUndo();
1644  PrepareView();
1646  mbLayout = true;
1647  CalcRects();
1648  LayoutPostIts();
1649 }
1650 
1652 {
1653  if (mvPostItFields.empty())
1654  return;
1656  sw::annotation::SwAnnotationWin *pWin = pOrigActiveWin;
1657  if (!pWin)
1658  {
1659  for (auto const& postItField : mvPostItFields)
1660  {
1661  pWin = postItField->mpPostIt;
1662  if (pWin)
1663  break;
1664  }
1665  }
1666  if (!pWin)
1667  return;
1668  SetActiveSidebarWin(pWin);
1669  OutlinerView* pOLV = pWin->GetOutlinerView();
1670  SfxItemSet aEditAttr(pOLV->GetAttribs());
1673  aDlgAttr.Put(aEditAttr);
1676  sal_uInt16 nRet = pDlg->Execute();
1677  if (RET_OK == nRet)
1678  {
1679  aDlgAttr.Put(*pDlg->GetOutputItemSet());
1680  FormatAll(aDlgAttr);
1681  }
1682  pDlg.disposeAndClear();
1683  SetActiveSidebarWin(pOrigActiveWin);
1684 }
1685 
1686 void SwPostItMgr::FormatAll(const SfxItemSet &rNewAttr)
1687 {
1689  SwRewriter aRewriter;
1690  aRewriter.AddRule(UndoArg1, SwResId(STR_FORMAT_ALL_NOTES) );
1691  mpWrtShell->StartUndo( SwUndoId::INSATTR, &aRewriter );
1692 
1693  for (auto const& postItField : mvPostItFields)
1694  {
1695  if (!postItField->mpPostIt)
1696  continue;
1697  OutlinerView* pOLV = postItField->mpPostIt->GetOutlinerView();
1698  //save old selection
1699  ESelection aOrigSel(pOLV->GetSelection());
1700  //select all
1701  Outliner *pOutliner = pOLV->GetOutliner();
1702  if (pOutliner)
1703  {
1704  sal_Int32 nParaCount = pOutliner->GetParagraphCount();
1705  if (nParaCount > 0)
1706  pOLV->SelectRange(0, nParaCount);
1707  }
1708  //set new char properties
1709  pOLV->SetAttribs(rNewAttr);
1710  //restore old selection
1711  pOLV->SetSelection(aOrigSel);
1712  // tdf#91596 store updated formatting in SwField
1713  postItField->mpPostIt->UpdateData();
1714  }
1715 
1716  mpWrtShell->EndUndo();
1717  PrepareView();
1719  mbLayout = true;
1720  CalcRects();
1721  LayoutPostIts();
1722 }
1723 
1724 void SwPostItMgr::Hide( std::u16string_view rAuthor )
1725 {
1726  for (auto const& postItField : mvPostItFields)
1727  {
1728  if ( postItField->mpPostIt && (postItField->mpPostIt->GetAuthor() == rAuthor) )
1729  {
1730  postItField->mbShow = false;
1731  postItField->mpPostIt->HideNote();
1732  }
1733  }
1734 
1735  LayoutPostIts();
1736 }
1737 
1739 {
1740  for (auto const& postItField : mvPostItFields)
1741  {
1742  postItField->mbShow = false;
1743  postItField->mpPostIt->HideNote();
1744  }
1745 }
1746 
1748 {
1749  for (auto const& postItField : mvPostItFields)
1750  {
1751  postItField->mbShow = true;
1752  }
1753  LayoutPostIts();
1754 }
1755 
1757 {
1758  for (auto const& postItField : mvPostItFields)
1759  {
1760  if ( postItField->GetBroadcaster() == pBroadcaster)
1761  return postItField->mpPostIt;
1762  }
1763  return nullptr;
1764 }
1765 
1767 {
1768  for (auto const& postItField : mvPostItFields)
1769  {
1770  if ( postItField->GetFormatField().GetField() == pField )
1771  return postItField->mpPostIt.get();
1772  }
1773  return nullptr;
1774 }
1775 
1777 {
1778  for (auto const& postItField : mvPostItFields)
1779  {
1780  if ( static_cast<const SwPostItField*>(postItField->GetFormatField().GetField())->GetPostItId() == nPostItId )
1781  return postItField->mpPostIt.get();
1782  }
1783  return nullptr;
1784 }
1785 
1787  SwAnnotationWin* aPostIt )
1788 {
1789  if (mvPostItFields.size()>1)
1790  {
1791  auto i = std::find_if(mvPostItFields.begin(), mvPostItFields.end(),
1792  [&aPostIt](const std::unique_ptr<SwSidebarItem>& pField) { return pField->mpPostIt == aPostIt; });
1793  if (i == mvPostItFields.end())
1794  return nullptr;
1795 
1796  auto iNextPostIt = i;
1797  if (aDirection == KEY_PAGEUP)
1798  {
1799  if ( iNextPostIt == mvPostItFields.begin() )
1800  {
1801  return nullptr;
1802  }
1803  --iNextPostIt;
1804  }
1805  else
1806  {
1807  ++iNextPostIt;
1808  if ( iNextPostIt == mvPostItFields.end() )
1809  {
1810  return nullptr;
1811  }
1812  }
1813  // lets quit, we are back at the beginning
1814  if ( (*iNextPostIt)->mpPostIt == aPostIt)
1815  return nullptr;
1816  return (*iNextPostIt)->mpPostIt;
1817  }
1818  else
1819  return nullptr;
1820 }
1821 
1823 {
1824  for (auto const& pPage : mPages)
1825  {
1826  for(auto b = pPage->mvSidebarItems.begin(); b!= pPage->mvSidebarItems.end(); ++b)
1827  {
1828  if ((*b)->mpPostIt == mpActivePostIt)
1829  {
1830  auto aNext = b;
1831  ++aNext;
1832  bool bFollow = (aNext != pPage->mvSidebarItems.end()) && (*aNext)->mpPostIt->IsFollow();
1833  if ( pPage->bScrollbar || bFollow )
1834  {
1835  return -1;
1836  }
1837  else
1838  {
1839  //if this is the last item, return the bottom border otherwise the next item
1840  if (aNext == pPage->mvSidebarItems.end())
1841  return mpEditWin->LogicToPixel(Point(0,pPage->mPageRect.Bottom())).Y() - GetSpaceBetween();
1842  else
1843  return (*aNext)->mpPostIt->GetPosPixel().Y() - GetSpaceBetween();
1844  }
1845  }
1846  }
1847  }
1848 
1849  OSL_FAIL("SwPostItMgr::GetNextBorder(): We have to find a next border here");
1850  return -1;
1851 }
1852 
1853 void SwPostItMgr::SetShadowState(const SwPostItField* pField,bool bCursor)
1854 {
1855  if (pField)
1856  {
1857  if (pField !=mShadowState.mpShadowField)
1858  {
1860  {
1861  // reset old one if still alive
1862  // TODO: does not work properly if mouse and cursor was set
1863  sw::annotation::SwAnnotationWin* pOldPostIt =
1865  if (pOldPostIt && pOldPostIt->Shadow() && (pOldPostIt->Shadow()->GetShadowState() != SS_EDIT))
1866  pOldPostIt->SetViewState(ViewState::NORMAL);
1867  }
1868  //set new one, if it is not currently edited
1869  sw::annotation::SwAnnotationWin* pNewPostIt = GetAnnotationWin(pField);
1870  if (pNewPostIt && pNewPostIt->Shadow() && (pNewPostIt->Shadow()->GetShadowState() != SS_EDIT))
1871  {
1872  pNewPostIt->SetViewState(ViewState::VIEW);
1873  //remember our new field
1874  mShadowState.mpShadowField = pField;
1875  mShadowState.bCursor = false;
1876  mShadowState.bMouse = false;
1877  }
1878  }
1879  if (bCursor)
1880  mShadowState.bCursor = true;
1881  else
1882  mShadowState.bMouse = true;
1883  }
1884  else
1885  {
1887  {
1888  if (bCursor)
1889  mShadowState.bCursor = false;
1890  else
1891  mShadowState.bMouse = false;
1893  {
1894  // reset old one if still alive
1896  if (pOldPostIt && pOldPostIt->Shadow() && (pOldPostIt->Shadow()->GetShadowState() != SS_EDIT))
1897  {
1898  pOldPostIt->SetViewState(ViewState::NORMAL);
1899  mShadowState.mpShadowField = nullptr;
1900  }
1901  }
1902  }
1903  }
1904 }
1905 
1906 void SwPostItMgr::PrepareView(bool bIgnoreCount)
1907 {
1908  if (!HasNotes() || bIgnoreCount)
1909  {
1911  SwRootFrame* pLayout = mpWrtShell->GetLayout();
1912  if ( pLayout )
1916  }
1917 }
1918 
1920 {
1921  if (mPages.size() > aPage-1)
1922  return (mPages[aPage-1]->bScrollbar && !mbWaitingForCalcRects);
1923  else
1924  return false;
1925 }
1926 
1927 bool SwPostItMgr::IsHit(const Point &aPointPixel)
1928 {
1929  if (HasNotes() && ShowNotes())
1930  {
1931  const Point aPoint = mpEditWin->PixelToLogic(aPointPixel);
1932  const SwRootFrame* pLayout = mpWrtShell->GetLayout();
1933  SwRect aPageFrame;
1934  const tools::ULong nPageNum = SwPostItHelper::getPageInfo( aPageFrame, pLayout, aPoint );
1935  if( nPageNum )
1936  {
1937  tools::Rectangle aRect;
1938  OSL_ENSURE(mPages.size()>nPageNum-1,"SwPostitMgr:: page container size wrong");
1939  aRect = mPages[nPageNum-1]->eSidebarPosition == sw::sidebarwindows::SidebarPosition::LEFT
1940  ? tools::Rectangle(Point(aPageFrame.Left()-GetSidebarWidth()-GetSidebarBorderWidth(),aPageFrame.Top()),Size(GetSidebarWidth(),aPageFrame.Height()))
1941  : tools::Rectangle( Point(aPageFrame.Right()+GetSidebarBorderWidth(),aPageFrame.Top()) , Size(GetSidebarWidth(),aPageFrame.Height()));
1942  if (aRect.Contains(aPoint))
1943  {
1944  // we hit the note's sidebar
1945  // lets now test for the arrow area
1946  if (mPages[nPageNum-1]->bScrollbar)
1947  return ScrollbarHit(nPageNum,aPoint);
1948  else
1949  return false;
1950  }
1951  }
1952  }
1953  return false;
1954 }
1955 
1957 {
1958  vcl::Window* pRet = nullptr;
1959 
1960  if (HasNotes() && ShowNotes())
1961  {
1962  bool bEnableMapMode = !mpEditWin->IsMapModeEnabled();
1963  if (bEnableMapMode)
1965 
1966  for (const std::unique_ptr<SwSidebarItem>& pItem : mvPostItFields)
1967  {
1968  SwAnnotationWin* pPostIt = pItem->mpPostIt;
1969  if (!pPostIt)
1970  continue;
1971 
1972  if (pPostIt->IsHitWindow(rPointLogic))
1973  {
1974  pRet = pPostIt;
1975  break;
1976  }
1977  }
1978 
1979  if (bEnableMapMode)
1980  mpEditWin->EnableMapMode(false);
1981  }
1982 
1983  return pRet;
1984 }
1985 
1987 {
1988  SwRect aPageRect = mPages[aPage-1]->mPageRect;
1989  Point aPointBottom = mPages[aPage-1]->eSidebarPosition == sw::sidebarwindows::SidebarPosition::LEFT
1990  ? Point(aPageRect.Left() - GetSidebarWidth() - GetSidebarBorderWidth() + mpEditWin->PixelToLogic(Size(2,0)).Width(),aPageRect.Bottom()- mpEditWin->PixelToLogic(Size(0,2+GetSidebarScrollerHeight())).Height())
1991  : Point(aPageRect.Right() + GetSidebarBorderWidth() + mpEditWin->PixelToLogic(Size(2,0)).Width(),aPageRect.Bottom()- mpEditWin->PixelToLogic(Size(0,2+GetSidebarScrollerHeight())).Height());
1993  return tools::Rectangle(aPointBottom,aSize);
1994 }
1995 
1997 {
1998  SwRect aPageRect = mPages[aPage-1]->mPageRect;
1999  Point aPointTop = mPages[aPage-1]->eSidebarPosition == sw::sidebarwindows::SidebarPosition::LEFT
2000  ? Point(aPageRect.Left() - GetSidebarWidth() -GetSidebarBorderWidth()+ mpEditWin->PixelToLogic(Size(2,0)).Width(),aPageRect.Top() + mpEditWin->PixelToLogic(Size(0,2)).Height())
2001  : Point(aPageRect.Right() + GetSidebarBorderWidth() + mpEditWin->PixelToLogic(Size(2,0)).Width(),aPageRect.Top() + mpEditWin->PixelToLogic(Size(0,2)).Height());
2003  return tools::Rectangle(aPointTop,aSize);
2004 }
2005 
2006 //IMPORTANT: if you change the rects here, also change SwPageFrame::PaintNotesSidebar()
2007 bool SwPostItMgr::ScrollbarHit(const tools::ULong aPage,const Point &aPoint)
2008 {
2009  SwRect aPageRect = mPages[aPage-1]->mPageRect;
2010  Point aPointBottom = mPages[aPage-1]->eSidebarPosition == sw::sidebarwindows::SidebarPosition::LEFT
2011  ? Point(aPageRect.Left() - GetSidebarWidth()-GetSidebarBorderWidth() + mpEditWin->PixelToLogic(Size(2,0)).Width(),aPageRect.Bottom()- mpEditWin->PixelToLogic(Size(0,2+GetSidebarScrollerHeight())).Height())
2012  : Point(aPageRect.Right() + GetSidebarBorderWidth()+ mpEditWin->PixelToLogic(Size(2,0)).Width(),aPageRect.Bottom()- mpEditWin->PixelToLogic(Size(0,2+GetSidebarScrollerHeight())).Height());
2013 
2014  Point aPointTop = mPages[aPage-1]->eSidebarPosition == sw::sidebarwindows::SidebarPosition::LEFT
2015  ? Point(aPageRect.Left() - GetSidebarWidth()-GetSidebarBorderWidth()+ mpEditWin->PixelToLogic(Size(2,0)).Width(),aPageRect.Top() + mpEditWin->PixelToLogic(Size(0,2)).Height())
2016  : Point(aPageRect.Right()+GetSidebarBorderWidth()+ mpEditWin->PixelToLogic(Size(2,0)).Width(),aPageRect.Top() + mpEditWin->PixelToLogic(Size(0,2)).Height());
2017 
2018  tools::Rectangle aRectBottom(GetBottomScrollRect(aPage));
2019  tools::Rectangle aRectTop(GetTopScrollRect(aPage));
2020 
2021  if (aRectBottom.Contains(aPoint))
2022  {
2023  if (aPoint.X() < tools::Long((aPointBottom.X() + GetSidebarWidth()/3)))
2024  Scroll( GetScrollSize(),aPage);
2025  else
2026  Scroll( -1*GetScrollSize(), aPage);
2027  return true;
2028  }
2029  else if (aRectTop.Contains(aPoint))
2030  {
2031  if (aPoint.X() < tools::Long((aPointTop.X() + GetSidebarWidth()/3*2)))
2032  Scroll(GetScrollSize(), aPage);
2033  else
2034  Scroll(-1*GetScrollSize(), aPage);
2035  return true;
2036  }
2037  return false;
2038 }
2039 
2041 {
2042  if ( mbWaitingForCalcRects || mbLayouting || mvPostItFields.empty() )
2043  return;
2044 
2045  // find first valid note
2046  SwAnnotationWin *pFirstPostIt = nullptr;
2047  for (auto const& postItField : mvPostItFields)
2048  {
2049  pFirstPostIt = postItField->mpPostIt;
2050  if (pFirstPostIt)
2051  break;
2052  }
2053 
2054  //if we have not found a valid note, forget about it and leave
2055  if (!pFirstPostIt)
2056  return;
2057 
2058  // yeah, I know, if this is a left page it could be wrong, but finding the page and the note is probably not even faster than just doing it
2059  // check, if anchor overlay object exists.
2060  const tools::Long aAnchorX = pFirstPostIt->Anchor()
2061  ? mpEditWin->LogicToPixel( Point(static_cast<tools::Long>(pFirstPostIt->Anchor()->GetSixthPosition().getX()),0)).X()
2062  : 0;
2063  const tools::Long aAnchorY = pFirstPostIt->Anchor()
2064  ? mpEditWin->LogicToPixel( Point(0,static_cast<tools::Long>(pFirstPostIt->Anchor()->GetSixthPosition().getY()))).Y() + 1
2065  : 0;
2066  if (Point(aAnchorX,aAnchorY) == pFirstPostIt->GetPosPixel())
2067  return;
2068 
2069  tools::Long aAnchorPosX = 0;
2070  tools::Long aAnchorPosY = 0;
2071  for (const std::unique_ptr<SwPostItPageItem>& pPage : mPages)
2072  {
2073  for (auto const& item : pPage->mvSidebarItems)
2074  {
2075  // check, if anchor overlay object exists.
2076  if ( item->mbShow && item->mpPostIt && item->mpPostIt->Anchor() )
2077  {
2078  aAnchorPosX = pPage->eSidebarPosition == sw::sidebarwindows::SidebarPosition::LEFT
2079  ? mpEditWin->LogicToPixel( Point(static_cast<tools::Long>(item->mpPostIt->Anchor()->GetSeventhPosition().getX()),0)).X()
2080  : mpEditWin->LogicToPixel( Point(static_cast<tools::Long>(item->mpPostIt->Anchor()->GetSixthPosition().getX()),0)).X();
2081  aAnchorPosY = mpEditWin->LogicToPixel( Point(0,static_cast<tools::Long>(item->mpPostIt->Anchor()->GetSixthPosition().getY()))).Y() + 1;
2082  item->mpPostIt->SetPosPixel(Point(aAnchorPosX,aAnchorPosY));
2083  }
2084  }
2085  }
2086 }
2087 
2089 {
2090  // we only want to see notes if Options - Writer - View - Notes is ticked
2091  return mpWrtShell->GetViewOptions()->IsPostIts();
2092 }
2093 
2095 {
2096  return !mvPostItFields.empty();
2097 }
2098 
2100 {
2101  bool bEnableMapMode = !mpWrtShell->GetOut()->IsMapModeEnabled();
2102  sal_uInt16 nZoom = mpWrtShell->GetViewOptions()->GetZoom();
2103  if (comphelper::LibreOfficeKit::isActive() && !bEnableMapMode)
2104  {
2105  // The output device is the tile and contains the real wanted scale factor.
2106  double fScaleX = double(mpWrtShell->GetOut()->GetMapMode().GetScaleX());
2107  nZoom = fScaleX * 100;
2108  }
2109  tools::ULong aWidth = static_cast<tools::ULong>(nZoom * 1.8);
2110 
2111  if (bPx)
2112  return aWidth;
2113  else
2114  {
2115  if (bEnableMapMode)
2116  // The output device is the window.
2118  tools::Long nRet = mpWrtShell->GetOut()->PixelToLogic(Size(aWidth, 0)).Width();
2119  if (bEnableMapMode)
2120  mpWrtShell->GetOut()->EnableMapMode(false);
2121  return nRet;
2122  }
2123 }
2124 
2126 {
2127  if (bPx)
2128  return 2;
2129  else
2130  return mpWrtShell->GetOut()->PixelToLogic(Size(2,0)).Width();
2131 }
2132 
2133 Color SwPostItMgr::GetColorDark(std::size_t aAuthorIndex)
2134 {
2135  if (!Application::GetSettings().GetStyleSettings().GetHighContrastMode())
2136  {
2137  static const Color aArrayNormal[] = {
2141 
2142  return aArrayNormal[ aAuthorIndex % SAL_N_ELEMENTS( aArrayNormal )];
2143  }
2144  else
2145  return COL_WHITE;
2146 }
2147 
2148 Color SwPostItMgr::GetColorLight(std::size_t aAuthorIndex)
2149 {
2150  if (!Application::GetSettings().GetStyleSettings().GetHighContrastMode())
2151  {
2152  static const Color aArrayLight[] = {
2156 
2157  return aArrayLight[ aAuthorIndex % SAL_N_ELEMENTS( aArrayLight )];
2158  }
2159  else
2160  return COL_WHITE;
2161 }
2162 
2163 Color SwPostItMgr::GetColorAnchor(std::size_t aAuthorIndex)
2164 {
2165  if (!Application::GetSettings().GetStyleSettings().GetHighContrastMode())
2166  {
2167  static const Color aArrayAnchor[] = {
2171 
2172  return aArrayAnchor[ aAuthorIndex % SAL_N_ELEMENTS( aArrayAnchor )];
2173  }
2174  else
2175  return COL_WHITE;
2176 }
2177 
2179 {
2180  if ( p == mpActivePostIt )
2181  return;
2182 
2183  // we need the temp variable so we can set mpActivePostIt before we call DeactivatePostIt
2184  // therefore we get a new layout in DOCCHANGED when switching from postit to document,
2185  // otherwise, GetActivePostIt() would still hold our old postit
2186  SwAnnotationWin* pActive = mpActivePostIt;
2187  mpActivePostIt = p;
2188  if (pActive)
2189  {
2190  pActive->DeactivatePostIt();
2191  mShadowState.mpShadowField = nullptr;
2192  }
2193  if (mpActivePostIt)
2194  {
2196  mpView->AttrChangedNotify(nullptr);
2198  }
2199 }
2200 
2201 IMPL_LINK_NOARG( SwPostItMgr, CalcHdl, void*, void )
2202 {
2203  mnEventId = nullptr;
2204  if ( mbLayouting )
2205  {
2206  OSL_FAIL("Reentrance problem in Layout Manager!");
2207  mbWaitingForCalcRects = false;
2208  return;
2209  }
2210 
2211  // do not change order, even if it would seem so in the first place, we need the calcrects always
2212  if (CalcRects() || mbLayout)
2213  {
2214  mbLayout = false;
2215  LayoutPostIts();
2216  }
2217 }
2218 
2220 {
2221  for (auto const& postItField : mvPostItFields)
2222  if ( postItField->mpPostIt )
2223  postItField->mpPostIt->Rescale();
2224 }
2225 
2227 {
2228  const Fraction& f( mpEditWin->GetMapMode().GetScaleY() );
2229  return sal_Int32(POSTIT_INITIAL_ANCHOR_DISTANCE * f);
2230 }
2231 
2233 {
2234  const Fraction& f( mpEditWin->GetMapMode().GetScaleY() );
2235  return sal_Int32(POSTIT_SPACE_BETWEEN * f);
2236 }
2237 
2239 {
2240  const Fraction& f( mpEditWin->GetMapMode().GetScaleY() );
2241  return sal_Int32((POSTIT_SPACE_BETWEEN + POSTIT_MINIMUMSIZE_WITH_META) * f);
2242 }
2243 
2245 {
2246  const Fraction& f( mpEditWin->GetMapMode().GetScaleY() );
2247  return sal_Int32(POSTIT_MINIMUMSIZE_WITH_META * f);
2248 }
2249 
2251 {
2252  const Fraction& f( mpEditWin->GetMapMode().GetScaleY() );
2253  return sal_Int32(POSTIT_SCROLL_SIDEBAR_HEIGHT * f);
2254 }
2255 
2257 {
2258  for (auto const& postItField : mvPostItFields)
2259  if ( postItField->mpPostIt )
2260  postItField->mpPostIt->SetSpellChecking();
2261 }
2262 
2264 {
2265  for (auto const& postItField : mvPostItFields)
2266  if ( postItField->mpPostIt )
2267  postItField->mpPostIt->SetReadonly( mbReadOnly );
2268 }
2269 
2271 {
2272  for (auto const& postItField : mvPostItFields)
2273  if ( postItField->mpPostIt )
2274  postItField->mpPostIt->CheckMetaText();
2275 
2276 }
2277 
2278 sal_uInt16 SwPostItMgr::Replace(SvxSearchItem const * pItem)
2279 {
2281  sal_uInt16 aResult = pWin->GetOutlinerView()->StartSearchAndReplace( *pItem );
2282  if (!aResult)
2283  SetActiveSidebarWin(nullptr);
2284  return aResult;
2285 }
2286 
2287 sal_uInt16 SwPostItMgr::FinishSearchReplace(const i18nutil::SearchOptions2& rSearchOptions, bool bSrchForward)
2288 {
2290  SvxSearchItem aItem(SID_SEARCH_ITEM );
2291  aItem.SetSearchOptions(rSearchOptions);
2292  aItem.SetBackward(!bSrchForward);
2293  sal_uInt16 aResult = pWin->GetOutlinerView()->StartSearchAndReplace( aItem );
2294  if (!aResult)
2295  SetActiveSidebarWin(nullptr);
2296  return aResult;
2297 }
2298 
2299 sal_uInt16 SwPostItMgr::SearchReplace(const SwFormatField &pField, const i18nutil::SearchOptions2& rSearchOptions, bool bSrchForward)
2300 {
2301  sal_uInt16 aResult = 0;
2302  SwAnnotationWin* pWin = GetSidebarWin(&pField);
2303  if (pWin)
2304  {
2305  ESelection aOldSelection = pWin->GetOutlinerView()->GetSelection();
2306  if (bSrchForward)
2307  pWin->GetOutlinerView()->SetSelection(ESelection(0,0,0,0));
2308  else
2309  pWin->GetOutlinerView()->SetSelection(
2311  SvxSearchItem aItem(SID_SEARCH_ITEM );
2312  aItem.SetSearchOptions(rSearchOptions);
2313  aItem.SetBackward(!bSrchForward);
2314  aResult = pWin->GetOutlinerView()->StartSearchAndReplace( aItem );
2315  if (!aResult)
2316  pWin->GetOutlinerView()->SetSelection(aOldSelection);
2317  else
2318  {
2319  SetActiveSidebarWin(pWin);
2320  MakeVisible(pWin);
2321  }
2322  }
2323  return aResult;
2324 }
2325 
2327 {
2328  // deselect any drawing or frame and leave editing mode
2329  SdrView* pSdrView = mpWrtShell->GetDrawView();
2330  if ( pSdrView && pSdrView->IsTextEdit() )
2331  {
2332  bool bLockView = mpWrtShell->IsViewLocked();
2333  mpWrtShell->LockView( true );
2335  mpWrtShell->LockView( bLockView );
2336  }
2337 
2339  {
2344 
2347  }
2348 }
2349 
2351 {
2352  return mpActivePostIt != nullptr;
2353 }
2354 
2356 {
2357  return HasActiveSidebarWin() &&
2358  mpActivePostIt != nullptr;
2359 }
2360 
2362 {
2363  if ( HasActiveSidebarWin() )
2364  {
2366  }
2367 }
2368 
2370 {
2371  if ( HasActiveSidebarWin() )
2372  {
2374  }
2375 }
2376 
2378 {
2379  if ( HasActiveSidebarWin() )
2380  {
2382  }
2383 }
2384 
2386 {
2387  if ( HasActiveSidebarWin() )
2388  {
2389  mpActivePostIt->Hide();
2390  }
2391 }
2392 
2394 {
2395  if ( HasActiveSidebarWin() )
2396  {
2398  }
2399 }
2400 
2402  const SwFormatField& rFormatField,
2403  SwAnnotationWin& rSidebarWin )
2404 {
2405  if ( mpFrameSidebarWinContainer == nullptr )
2406  {
2408  }
2409 
2410  const bool bInserted = mpFrameSidebarWinContainer->insert( rFrame, rFormatField, rSidebarWin );
2411  if ( bInserted &&
2413  {
2414  mpWrtShell->GetAccessibleMap()->InvalidatePosOrSize( nullptr, nullptr, &rSidebarWin, SwRect() );
2415  }
2416 }
2417 
2419  SwAnnotationWin& rSidebarWin )
2420 {
2421  if ( mpFrameSidebarWinContainer != nullptr )
2422  {
2423  const bool bRemoved = mpFrameSidebarWinContainer->remove( rFrame, rSidebarWin );
2424  if ( bRemoved &&
2426  {
2427  mpWrtShell->GetAccessibleMap()->A11yDispose( nullptr, nullptr, &rSidebarWin );
2428  }
2429  }
2430 }
2431 
2433 {
2434  bool bRet( false );
2435 
2436  if ( mpFrameSidebarWinContainer != nullptr )
2437  {
2438  bRet = !mpFrameSidebarWinContainer->empty( rFrame );
2439  }
2440 
2441  return bRet;
2442 }
2443 
2445  const sal_Int32 nIndex )
2446 {
2447  vcl::Window* pSidebarWin( nullptr );
2448 
2449  if ( mpFrameSidebarWinContainer != nullptr )
2450  {
2451  pSidebarWin = mpFrameSidebarWinContainer->get( rFrame, nIndex );
2452  }
2453 
2454  return pSidebarWin;
2455 }
2456 
2458  std::vector< vcl::Window* >* pChildren )
2459 {
2460  if ( mpFrameSidebarWinContainer != nullptr )
2461  {
2462  mpFrameSidebarWinContainer->getAll( rFrame, pChildren );
2463  }
2464 }
2465 
2467  for (auto const& pPage : mPages)
2468  {
2469  for(auto b = pPage->mvSidebarItems.begin(); b!= pPage->mvSidebarItems.end(); ++b)
2470  {
2471  if ((*b)->mpPostIt->IsResolved())
2472  {
2473  (*b)->mpPostIt->SetResolved(true);
2474  (*b)->mpPostIt->GetSidebarItem().mbShow = visible;
2475  }
2476  }
2477  }
2478  LayoutPostIts();
2479 }
2480 
2482  // Given the topmost note as an argument, scans over all notes and sets the
2483  // 'resolved' state of each descendant of the top notes to the resolved state
2484  // of the top note.
2485  bool resolved = topNote->IsResolved();
2486  for (auto const& pPage : mPages)
2487  {
2488  for(auto b = pPage->mvSidebarItems.begin(); b!= pPage->mvSidebarItems.end(); ++b)
2489  {
2490  if((*b)->mpPostIt->GetTopReplyNote() == topNote) {
2491  (*b)->mpPostIt->SetResolved(resolved);
2492  }
2493  }
2494  }
2495 }
2496 
2498 void SwNoteProps::Notify( const css::uno::Sequence< OUString >& ) {}
2499 
2500 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
virtual Point GetPosPixel() const
vcl::RenderContext * GetOut() const
Definition: viewsh.hxx:339
SfxViewFrame * GetViewFrame() const
const Fraction & GetScaleX() const
Instances of SwFields and those derived from it occur 0 to n times.
Definition: fldbas.hxx:241
void StopShellTimer()
Definition: view.cxx:1786
bool IsHit(const Point &aPointPixel)
Definition: PostItMgr.cxx:1927
constexpr::Color COL_AUTHOR1_DARK(0xC6, 0x92, 0x00)
Base class of the Writer layout elements.
Definition: frame.hxx:315
double getY() const
bool mbWaitingForCalcRects
Definition: PostItMgr.hxx:133
void CheckForRemovedPostIts()
Definition: PostItMgr.cxx:240
constexpr::Color COL_AUTHOR4_NORMAL(0xE4, 0xD2, 0xF5)
SfxHintId
void Right(const tools::Long nRight)
Definition: swrect.hxx:202
constexpr::Color COL_AUTHOR9_DARK(0xD1, 0x76, 0x00)
Marks a position in the document model.
Definition: pam.hxx:36
vcl::Window * GetSidebarWinForFrameByIndex(const SwFrame &rFrame, const sal_Int32 nIndex)
Definition: PostItMgr.cxx:2444
void SetViewState(::sw::sidebarwindows::ViewState bViewState)
void HideActiveSidebarWin()
Definition: PostItMgr.cxx:2385
const SwField * GetField() const
Definition: fmtfld.hxx:111
virtual void DrawSelChanged() override
Definition: wrtsh3.cxx:105
void FormatAll(const SfxItemSet &rNewAttr)
Definition: PostItMgr.cxx:1686
SdrView * GetDrawView()
Definition: vnew.cxx:373
constexpr::Color COL_AUTHOR7_LIGHT(0xF2, 0xFE, 0xB5)
constexpr::Color COL_AUTHOR2_LIGHT(0xE9, 0xF2, 0xFF)
const SwStartNode * FindFooterStartNode() const
Definition: node.hxx:206
virtual ~SwPostItMgr() override
Definition: PostItMgr.cxx:229
OUString toISO8601(const css::util::DateTime &rDateTime)
const SwRect & GetAnchorRect() const
virtual const SfxItemSet * GetOutputItemSet() const =0
sal_Int32 GetInitialAnchorDistance() const
Definition: PostItMgr.cxx:2226
#define POSTIT_INITIAL_ANCHOR_DISTANCE
Definition: PostItMgr.cxx:82
void CollectPostIts(std::vector< SwFormatField * > &rvFormatFields, IDocumentRedlineAccess const &rIDRA, bool HideRedlines)
Definition: fldbas.cxx:186
virtual SwFieldType * GetFieldType(SwFieldIds nResId, const OUString &rName, bool bDbFieldMatching) const =0
void Left(const tools::Long nLeft)
Definition: swrect.hxx:197
SwNodeIndex nNode
Definition: pam.hxx:38
bool Contains(const Point &rPOINT) const
IMPL_LINK_NOARG(SwPostItMgr, CalcHdl, void *, void)
Definition: PostItMgr.cxx:2201
CommentNotificationType
constexpr::Color COL_AUTHOR8_LIGHT(0xE2, 0xEA, 0xF1)
bool HasScrollbars() const
Definition: PostItMgr.cxx:642
sal_Int32 StartSearchAndReplace(const SvxSearchItem &rSearchItem)
void SetSearchOptions(const i18nutil::SearchOptions2 &rOpt)
long Long
void disposeAndClear()
constexpr::Color COL_AUTHOR2_NORMAL(0xD8, 0xE8, 0xFF)
bool IsPostIts() const
Definition: viewopt.hxx:273
static const AllSettings & GetSettings()
void Push(vcl::PushFlags nFlags=vcl::PushFlags::ALL)
std::size_t mRedlineAuthor
SwFormatFieldHintWhich Which() const
Definition: fmtfld.hxx:177
bool IsMapModeEnabled() const
sal_Int64 n
virtual Size GetSizePixel() const
tools::ULong getPageInfo(SwRect &rPageFrame, const SwRootFrame *, const Point &)
sal_Int32 GetMinimumSizeWithoutMeta() const
#define POSTIT_MINIMUMSIZE_WITH_META
Definition: PostItMgr.cxx:85
sw::annotation::SwAnnotationWin * GetSidebarWin(const SfxBroadcaster *pBroadcaster) const
Definition: PostItMgr.cxx:1756
sal_Int16 nId
VclPtr< sw::annotation::SwAnnotationWin > mpActivePostIt
Definition: PostItMgr.hxx:134
virtual OUString GetPar1() const override
Author.
Definition: docufld.cxx:1800
SwUndoId EndUndo(SwUndoId eUndoId=SwUndoId::EMPTY, const SwRewriter *pRewriter=nullptr)
Closes parenthesis of nUndoId, not used by UI.
Definition: edws.cxx:234
constexpr::Color COL_AUTHOR1_NORMAL(0xFF, 0xFF, 0x9E)
static ImplSVEvent * PostUserEvent(const Link< void *, void > &rLink, void *pCaller=nullptr, bool bReferenceLink=false)
const MapMode & GetMapMode() const
const IDocumentSettingAccess & getIDocumentSettingAccess() const
Provides access to the document setting interface.
Definition: viewsh.cxx:2716
constexpr::Color COL_AUTHOR2_DARK(0x06, 0x46, 0xA2)
SwNode & GetNode() const
Definition: ndindex.hxx:121
void SetActiveSidebarWin(sw::annotation::SwAnnotationWin *p)
Definition: PostItMgr.cxx:2178
vcl::Window * IsHitSidebarWindow(const Point &rPointLogic)
Get the matching window that is responsible for handling mouse events of rPointLogic, if any.
Definition: PostItMgr.cxx:1956
void EnterStdMode()
Definition: select.cxx:551
SwEditWin & GetEditWin()
Definition: view.hxx:416
sal_Int32 GetParagraphCount() const
tools::Long getLayoutHeight(const SwRootFrame *pRoot)
void Pos(const Point &rNew)
Definition: swrect.hxx:171
bool mPositionFromCommentAnchor
If true, the overlay arrow points to the comment anchor, otherwise it points to the commented frame...
static Color GetColorAnchor(std::size_t aAuthorIndex)
Definition: PostItMgr.cxx:2163
bool HasActiveAnnotationWin() const
Definition: PostItMgr.cxx:2355
constexpr::Color COL_AUTHOR8_NORMAL(0xD3, 0xDE, 0xE8)
constexpr TypedWhichId< SvxLanguageItem > EE_CHAR_LANGUAGE_CJK(EE_CHAR_START+15)
SwSidebarItem * InsertItem(SfxBroadcaster *pItem, bool bCheckExistence, bool bFocus)
Definition: PostItMgr.cxx:277
constexpr::Color COL_AUTHOR3_LIGHT(0xE2, 0xFA, 0xCF)
void EnableMapMode(bool bEnable=true)
Of course Writer needs its own rectangles.
Definition: swrect.hxx:34
bool IsHitWindow(const Point &rPointLogic)
Is there a matching sub-widget inside this sidebar widget for rPointLogic?
void setTiledPainting(bool bTiledPainting)
void EndAllAction()
Definition: edws.cxx:97
The root element of a Writer document layout.
Definition: rootfrm.hxx:82
void SetMapMode()
SfxHintId GetId() const
bool LayoutByPage(std::vector< sw::annotation::SwAnnotationWin * > &aVisiblePostItList, const tools::Rectangle &rBorder, tools::Long lNeededHeight)
Definition: PostItMgr.cxx:1122
bool DelRight()
Definition: delete.cxx:295
SwWrtShell & GetWrtShell() const
Definition: view.hxx:413
const SwPostItField * GetPostItField() const
const sal_Int8 ANCHORLINE_WIDTH
void ShowHideResolvedNotes(bool visible)
Definition: PostItMgr.cxx:2466
OUString SwResId(TranslateId aId)
Definition: swmodule.cxx:165
IDocumentFieldsAccess const & getIDocumentFieldsAccess() const
Definition: doc.cxx:357
constexpr::Color COL_AUTHOR3_NORMAL(0xDA, 0xF8, 0xC1)
void PaintTile(vcl::RenderContext &rRenderContext, const tools::Rectangle &rRect)
void InvalidatePosOrSize(const SwFrame *pFrame, const SdrObject *pObj, vcl::Window *pWindow, const SwRect &rOldFrame)
Definition: accmap.cxx:2300
bool mbDeleteNote
Definition: PostItMgr.hxx:139
std::unique_ptr< sw::sidebarwindows::SwFrameSidebarWinContainer > mpFrameSidebarWinContainer
Definition: PostItMgr.hxx:146
constexpr::Color COL_AUTHOR9_NORMAL(0xFF, 0xE2, 0xB9)
#define COL_NOTES_SIDEPANE_ARROW_DISABLED
Definition: PostItMgr.hxx:61
void SetSidebarPosition(sw::sidebarwindows::SidebarPosition eSidebarPosition)
const SwView & GetView() const
Definition: wrtsh.hxx:431
#define MAX_LOOP_COUNT
Definition: PostItMgr.cxx:89
void DisconnectSidebarWinFromFrame(const SwFrame &rFrame, sw::annotation::SwAnnotationWin &rSidebarWin)
Definition: PostItMgr.cxx:2418
SwAccessibleMap * GetAccessibleMap()
Definition: viewsh.cxx:2571
constexpr::Color COL_AUTHOR4_LIGHT(0xEF, 0xE4, 0xF8)
OString join(std::string_view rSeparator, const std::vector< OString > &rSequence)
const Fraction & GetScaleY() const
constexpr OUStringLiteral IsReadOnly(u"IsReadOnly")
const SwTextField * GetTextField() const
Definition: fmtfld.hxx:129
unsigned long ULong
void DrawNotesForPage(OutputDevice *pOutDev, sal_uInt32 nPage)
Definition: PostItMgr.cxx:952
SW_DLLPUBLIC void UpdateDataOnActiveSidebarWin()
Definition: PostItMgr.cxx:2369
VclPtr< sw::annotation::SwAnnotationWin > mpPostIt
void EnableMapMode(bool bEnable=true)
void SelectRange(sal_Int32 nFirst, sal_Int32 nCount)
SwView * mpView
Definition: PostItMgr.hxx:127
constexpr sal_uInt16 KEY_PAGEUP
static Color GetColorDark(std::size_t aAuthorIndex)
Definition: PostItMgr.cxx:2133
virtual void libreOfficeKitViewCallback(int nType, const char *pPayload) const override
void ExecViewOptions(SfxRequest &)
Definition: view0.cxx:361
constexpr::Color COL_AUTHOR6_LIGHT(0xE6, 0xFA, 0xFA)
const IDocumentRedlineAccess & getIDocumentRedlineAccess() const
Provides access to the document redline interface.
Definition: viewsh.cxx:2724
void PrepareView(bool bIgnoreCount=false)
Definition: PostItMgr.cxx:1906
#define POSTIT_SPACE_BETWEEN
Definition: PostItMgr.cxx:84
void MakeVisible(const SwRect &)
Definition: viewsh.cxx:630
void PaintTile(OutputDevice &rRenderContext)
Definition: PostItMgr.cxx:967
ImplSVEvent * mnEventId
Definition: PostItMgr.hxx:132
void SetBackward(bool bNewBackward)
void GetAllSidebarWinForFrame(const SwFrame &rFrame, std::vector< vcl::Window * > *pChildren)
Definition: PostItMgr.cxx:2457
#define SAL_N_ELEMENTS(arr)
sal_Int32 GetSpaceBetween() const
Definition: PostItMgr.cxx:2232
constexpr::Color COL_AUTHOR6_DARK(0x00, 0x80, 0x80)
css::util::DateTime GetUNODateTime() const
static void RemoveUserEvent(ImplSVEvent *nUserEvent)
bool CalcRects()
Definition: PostItMgr.cxx:525
SwDoc * GetDoc()
returns Doc. But be careful!
Definition: docsh.hxx:203
void ConnectSidebarWinToFrame(const SwFrame &rFrame, const SwFormatField &rFormatField, sw::annotation::SwAnnotationWin &rSidebarWin)
Definition: PostItMgr.cxx:2401
sal_uInt32 GetPostItId() const
Definition: docufld.hxx:481
#define POSTIT_SCROLL_SIDEBAR_HEIGHT
Definition: PostItMgr.cxx:86
const DateTime & GetDateTime() const
Definition: docufld.hxx:478
void DeleteCommentThread(sal_uInt32 nPostItId)
Definition: PostItMgr.cxx:1549
SvtScriptType
void ToggleResolved(sal_uInt32 nPostItId)
Definition: PostItMgr.cxx:1573
#define SW_MOD()
Definition: swmodule.hxx:256
Point LogicToPixel(const Point &rLogicPt) const
void SetAttribs(const SfxItemSet &)
int i
::sw::mark::IMark * GetAnnotationMark() const
Definition: atrfld.cxx:742
const SwFormatField * GetField() const
Definition: fmtfld.hxx:176
SwRect mPageFrame
void DeleteActiveSidebarWin()
Definition: PostItMgr.cxx:2377
void Scroll(const tools::Long lScroll, const tools::ULong aPage)
Definition: PostItMgr.cxx:993
sal_uInt16 SearchReplace(const SwFormatField &pField, const i18nutil::SearchOptions2 &rSearchOptions, bool bSrchForward)
Definition: PostItMgr.cxx:2299
FieldShadowState mShadowState
Definition: PostItMgr.hxx:140
bool BorderOverPageBorder(tools::ULong aPage) const
Definition: PostItMgr.cxx:931
constexpr::Color COL_AUTHOR3_DARK(0x57, 0x9D, 0x1C)
const MapMode & GetMapMode() const
SwRect mPagePrtArea
void SetSize(const Size &rSize)
virtual void Invalidate(InvalidateFlags nFlags=InvalidateFlags::NONE)
void AddPostIts(bool bCheckExistence=true, bool bFocus=true)
Definition: PostItMgr.cxx:1294
SwUndoId StartUndo(SwUndoId eUndoId=SwUndoId::EMPTY, const SwRewriter *pRewriter=nullptr)
Undo: set up Undo parenthesis, return nUndoId of this parenthesis.
Definition: edws.cxx:223
void MakeVisible(const sw::annotation::SwAnnotationWin *pPostIt)
Definition: PostItMgr.cxx:1067
constexpr::Color COL_AUTHOR7_DARK(0x8C, 0x84, 0x00)
void AddRule(SwUndoArg eWhat, const OUString &rWith)
Definition: SwRewriter.cxx:25
void AutoScroll(const sw::annotation::SwAnnotationWin *pPostIt, const tools::ULong aPage)
Definition: PostItMgr.cxx:1045
constexpr sal_uInt16 KEY_PAGEDOWN
void SetVirtualPosSize(const Point &aPoint, const Size &aSize)
SvtScriptType GetScriptTypeOfLanguage(LanguageType nLang)
constexpr tools::Long Top() const
Outliner * GetOutliner() const
static SwAbstractDialogFactory * Create()
Definition: swabstdlg.cxx:36
tools::ULong GetSidebarBorderWidth(bool bPx=false) const
Definition: PostItMgr.cxx:2125
const sal_Int16 mnEventId
void Focus(const SfxBroadcaster &rBC)
Definition: PostItMgr.cxx:498
constexpr::Color COL_AUTHOR8_DARK(0x35, 0x55, 0x6B)
void StartListening(SfxBroadcaster &rBroadcaster, DuplicateHandling eDuplicateHanding=DuplicateHandling::Unexpected)
Point PixelToLogic(const Point &rDevicePt) const
void SSize(const Size &rNew)
Definition: swrect.hxx:180
void LeaveDrawCreate()
Definition: view.hxx:538
tools::ULong GetSidebarWidth(bool bPx=false) const
Definition: PostItMgr.cxx:2099
VclPtr< SwEditWin > mpEditWin
Definition: PostItMgr.hxx:129
void GrabFocus()
tools::ULong mnPageNumber
#define Y
sal_uInt32 CalcParent()
Calculate parent postit id of current annotation window.
SwDocShell * GetDocShell()
Definition: view.cxx:1127
const SwPostItField * mpShadowField
Definition: PostItMgr.hxx:77
bool IsReadOnly() const
constexpr::Color COL_AUTHOR1_LIGHT(0xFF, 0xFF, 0xC3)
bool HasFrameConnectedSidebarWins(const SwFrame &rFrame)
Definition: PostItMgr.cxx:2432
SwLayoutInfo maLayoutInfo
SwFieldType * GetTyp() const
Definition: fldbas.hxx:393
void Delete()
Definition: PostItMgr.cxx:1624
constexpr::Color COL_AUTHOR7_NORMAL(0xED, 0xFC, 0xA3)
constexpr::Color COL_AUTHOR4_DARK(0x69, 0x2B, 0x9D)
::sw::sidebarwindows::AnchorOverlayObject * Anchor()
SW_DLLPUBLIC bool HasActiveSidebarWin() const
Definition: PostItMgr.cxx:2350
void RemoveSidebarWin()
Definition: PostItMgr.cxx:1308
void LayoutPostIts()
Definition: PostItMgr.cxx:680
constexpr tools::Long Bottom() const
SAL_WARN_UNUSED_RESULT Point PixelToLogic(const Point &rDevicePt) const
bool ScrollbarHit(const tools::ULong aPage, const Point &aPoint)
Definition: PostItMgr.cxx:2007
void CheckMetaText()
Definition: PostItMgr.cxx:2270
std::optional< OutlinerParaObject > mpAnswer
Definition: PostItMgr.hxx:141
void PreparePageContainer()
Definition: PostItMgr.cxx:652
ESelection GetSelection() const
void ExecuteFormatAllDialog(SwView &rView)
Definition: PostItMgr.cxx:1651
SwPostItHelper::SwLayoutStatus mLayoutStatus
constexpr TypedWhichId< SvxLanguageItem > EE_CHAR_LANGUAGE_CTL(EE_CHAR_START+16)
float v
void A11yDispose(const SwFrame *pFrame, const SdrObject *pObj, vcl::Window *pWindow, bool bRecursive=false, bool bCanSkipInvisible=true)
Definition: accmap.cxx:2174
void DrawForPage(OutputDevice *pDev, const Point &rPos)
void SetFollow(bool bIsFollow)
constexpr::Color COL_AUTHOR5_NORMAL(0xFE, 0xCD, 0xD0)
void ChangeSidebarItem(SwSidebarItem const &rSidebarItem)
bool IsMapModeEnabled() const
virtual void Notify(SfxBroadcaster &rBC, const SfxHint &rHint)
bool IsFieldInDoc() const
Definition: atrfld.cxx:419
void TranslateTopPosition(const tools::Long aAmount)
const SfxPoolItem * Put(const SfxPoolItem &rItem, sal_uInt16 nWhich)
sal_uInt16 GetNumPages() const
Definition: viewsh.cxx:685
void Bottom(const tools::Long nBottom)
Definition: swrect.hxx:211
SwNodeOffset mnStartNodeIdx
void AssureStdModeAtShell()
Definition: PostItMgr.cxx:2326
void ShowAnchorOnly(const Point &aPoint)
void GrabFocusOnActiveSidebarWin()
Definition: PostItMgr.cxx:2361
void SetSelection(const ESelection &)
void InitAnswer(OutlinerParaObject const &rText)
sal_uInt16 Replace(SvxSearchItem const *pItem)
Definition: PostItMgr.cxx:2278
void ToggleInsModeOnActiveSidebarWin()
Definition: PostItMgr.cxx:2393
bool GotoField(const SwFormatField &rField)
Definition: wrtsh3.cxx:66
void MakeDrawView()
Definition: vnew.cxx:363
void SetReadOnlyState()
Definition: PostItMgr.cxx:2263
virtual bool IsTextEdit() const final override
const basegfx::B2DPoint & GetSixthPosition() const
weld::Window * GetFrameWeld() const
sal_Int32 GetSidebarScrollerHeight() const
Definition: PostItMgr.cxx:2250
static Color GetColorLight(std::size_t aAuthorIndex)
Definition: PostItMgr.cxx:2148
virtual VclPtr< sw::annotation::SwAnnotationWin > GetSidebarWindow(SwEditWin &rEditWin, SwPostItMgr &aMgr)=0
const std::vector< basegfx::B2DRange > & GetAnnotationTextRanges() const
virtual void ImplCommit() override
Definition: PostItMgr.cxx:2497
bool IsFieldDeletedInModel(IDocumentRedlineAccess const &rIDRA, SwTextField const &rTextField)
void CorrectPositions()
Definition: PostItMgr.cxx:2040
sal_Int32 GetScrollSize() const
Definition: PostItMgr.cxx:2238
constexpr tools::Long Height() const
virtual SwPosition GetAnchorPosition() const =0
sw::sidebarwindows::SidebarPosition meSidebarPosition
void LockView(bool b)
Definition: viewsh.hxx:463
const SwViewOption * GetViewOptions() const
Definition: viewsh.hxx:424
#define COL_NOTES_SIDEPANE_ARROW_ENABLED
Definition: PostItMgr.hxx:60
bool mbLayouting
Definition: PostItMgr.hxx:137
const ::std::vector< Color > ImpSvNumberformatScan::StandardColor COL_WHITE
virtual bool UseElement(SwRootFrame const &, IDocumentRedlineAccess const &)=0
bool ArrowEnabled(sal_uInt16 aDirection, tools::ULong aPage) const
Definition: PostItMgr.cxx:1091
bool ShowScrollbar(const tools::ULong aPage) const
Definition: PostItMgr.cxx:1919
void Notify(SfxBroadcaster &rBC, const SfxHint &rHint) override
Definition: PostItMgr.cxx:322
void SetChangeTracking(const SwPostItHelper::SwLayoutStatus aStatus, const Color &aColor)
RET_OK
void UpdateResolvedStatus(const sw::annotation::SwAnnotationWin *topNote)
Definition: PostItMgr.cxx:2481
bool mbIsShowAnchor
Definition: PostItMgr.hxx:143
void EndListening(SfxBroadcaster &rBroadcaster, bool bRemoveAllDuplicates=false)
sal_Int32 GetMinimumSizeWithMeta() const
Definition: PostItMgr.cxx:2244
void Top(const tools::Long nTop)
Definition: swrect.hxx:206
sal_uInt16 GetZoom() const
Definition: viewopt.hxx:505
void EndTextEdit()
Deletes object if required.
Definition: feshview.cxx:1308
size_t IsObjSelected() const
Definition: feshview.cxx:1240
void * p
void UnSelectFrame()
Definition: select.cxx:323
#define EE_TEXTPOS_MAX_COUNT
void Rescale()
Definition: PostItMgr.cxx:2219
bool HasNotes() const
Definition: PostItMgr.cxx:2094
constexpr TypedWhichId< SvxLanguageItem > EE_CHAR_LANGUAGE(EE_CHAR_START+14)
UnoViewSharedPtr mpView
bool IsHideRedlines() const
Replacement for sw::DocumentRedlineManager::GetRedlineFlags() (this is layout-level redline hiding)...
Definition: rootfrm.hxx:422
void setSidebarChanged(SwRootFrame *pRoot, bool bBrowseMode)
virtual bool get(DocumentSettingId id) const =0
Return the specified document setting.
constexpr::Color COL_AUTHOR5_LIGHT(0xFF, 0xE3, 0xE5)
sw::annotation::SwAnnotationWin * GetActiveSidebarWin()
Definition: PostItMgr.hxx:234
void LeaveSelFrameMode()
Definition: select.cxx:720
void SetSpellChecking()
Definition: PostItMgr.cxx:2256
std::vector< std::unique_ptr< SwPostItPageItem > > mPages
Definition: PostItMgr.hxx:131
tools::Rectangle GetTopScrollRect(const tools::ULong aPage) const
Definition: PostItMgr.cxx:1996
sw::annotation::SwAnnotationWin * GetNextPostIt(sal_uInt16 aDirection, sw::annotation::SwAnnotationWin *aPostIt)
Definition: PostItMgr.cxx:1786
tools::Long mbLayoutHeight
Definition: PostItMgr.hxx:136
SwPostItMgr(SwView *aDoc)
Definition: PostItMgr.cxx:191
reference_type * get() const
virtual OUString GetPar2() const override
Text.
Definition: docufld.cxx:1812
double getX() const
void SetPosSizePixelRect(tools::Long nX, tools::Long nY, tools::Long nWidth, tools::Long nHeight, const SwRect &aAnchorRect, const tools::Long PageBorder)
SfxItemSet GetAttribs()
Color GetArrowColor(sal_uInt16 aDirection, tools::ULong aPage) const
Definition: PostItMgr.cxx:1107
void(* f)(TrueTypeTable *)
sal_Int32 mnStartContent
tools::Long GetNextBorder()
Definition: PostItMgr.cxx:1822
bool mbReadOnly
Definition: PostItMgr.hxx:138
bool IsShowAnchor() const
Definition: PostItMgr.hxx:105
bool IsShowHiddenChar(bool bHard=false) const
Definition: viewopt.hxx:321
::sw::sidebarwindows::ShadowOverlayObject * Shadow()
virtual SdrView * GetDrawView() const override
Definition: viewdraw.cxx:621
virtual VclPtr< SfxAbstractTabDialog > CreateSwCharDlg(weld::Window *pParent, SwView &pVw, const SfxItemSet &rCoreSet, SwCharDlgMode nDialogMode, const OUString *pFormatStr=nullptr)=0
bool ShowNotes() const
Definition: PostItMgr.cxx:2088
#define EE_PARA_MAX_COUNT
constexpr::Color COL_AUTHOR9_LIGHT(0xFF, 0xE7, 0xC7)
void SetShadowState(const SwPostItField *pField, bool bCursor=true)
Definition: PostItMgr.cxx:1853
void StartAllAction()
For all views of this document.
Definition: edws.cxx:86
constexpr::Color COL_AUTHOR6_NORMAL(0xD2, 0xF6, 0xF6)
SwRootFrame * GetLayout() const
Definition: viewsh.cxx:2122
static SfxItemPool * GetAnnotationPool(SwView const &rV)
Definition: annotsh.cxx:122
SwLayoutStatus getLayoutInfos(SwLayoutInfo &o_rInfo, const SwPosition &rAnchorPos, const sw::mark::IMark *pAnnotationMark=nullptr)
virtual const SwFormatField & GetFormatField() const =0
virtual void Notify(const css::uno::Sequence< OUString > &aPropertyNames) override
Definition: PostItMgr.cxx:2498
void Height(tools::Long nNew)
Definition: swrect.hxx:193
SwFieldIds Which() const
Definition: fldbas.hxx:273
void ToggleResolvedForThread(sal_uInt32 nPostItId)
Definition: PostItMgr.cxx:1598
std::vector< std::unique_ptr< SwSidebarItem > > mvPostItFields
Definition: PostItMgr.hxx:130
sw::annotation::SwAnnotationWin * GetAnnotationWin(const SwPostItField *pField) const
Definition: PostItMgr.cxx:1766
const SwStartNode * FindFootnoteStartNode() const
Definition: node.hxx:202
bool IsViewLocked() const
Definition: viewsh.hxx:462
SwRect mPosition
void RemoveItem(SfxBroadcaster *pBroadcast)
Definition: PostItMgr.cxx:300
Definition: view.hxx:144
bool GetResolved() const
Definition: docufld.cxx:1776
sal_uInt16 FinishSearchReplace(const i18nutil::SearchOptions2 &rSearchOptions, bool bSrchForward)
Definition: PostItMgr.cxx:2287
SwWrtShell * mpWrtShell
Definition: PostItMgr.hxx:128
bool IsSelFrameMode() const
Definition: wrtsh.hxx:173
constexpr::Color COL_AUTHOR5_DARK(0xC5, 0x00, 0x0B)
tools::Rectangle GetBottomScrollRect(const tools::ULong aPage) const
Definition: PostItMgr.cxx:1986