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