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