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