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