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