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