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