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