docthemes: Save themes def. to a file when added to ColorSets
[LibreOffice.git] / sw / source / uibase / docvw / AnnotationWin2.cxx
blob6bd5eeb72992bda767a3c346aa94414df8674d3b
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <config_wasm_strip.h>
22 #include <sal/config.h>
24 #include <cstddef>
26 #include "SidebarWinAcc.hxx"
27 #include <PostItMgr.hxx>
28 #include <AnnotationWin.hxx>
29 #include <IDocumentUndoRedo.hxx>
30 #include <basegfx/range/b2drange.hxx>
31 #include "SidebarTxtControl.hxx"
32 #include "AnchorOverlayObject.hxx"
33 #include "ShadowOverlayObject.hxx"
34 #include "OverlayRanges.hxx"
36 #include <strings.hrc>
38 #include <viewopt.hxx>
39 #include <cmdid.h>
41 #include <editeng/fhgtitem.hxx>
42 #include <editeng/langitem.hxx>
43 #include <editeng/editview.hxx>
44 #include <editeng/outliner.hxx>
45 #include <editeng/editeng.hxx>
46 #include <editeng/eeitem.hxx>
47 #include <editeng/outlobj.hxx>
48 #include <editeng/editund2.hxx>
50 #include <svl/undo.hxx>
51 #include <svl/stritem.hxx>
53 #include <sfx2/viewfrm.hxx>
54 #include <sfx2/bindings.hxx>
55 #include <sfx2/dispatch.hxx>
57 #include <vcl/decoview.hxx>
58 #include <vcl/event.hxx>
59 #include <vcl/gradient.hxx>
60 #include <vcl/pdfextoutdevdata.hxx>
61 #include <vcl/svapp.hxx>
62 #include <vcl/settings.hxx>
63 #include <vcl/ptrstyle.hxx>
64 #include <vcl/uitest/logger.hxx>
65 #include <vcl/uitest/eventdescription.hxx>
67 #include <edtwin.hxx>
68 #include <view.hxx>
69 #include <docsh.hxx>
70 #include <wrtsh.hxx>
71 #include <doc.hxx>
72 #include <docstyle.hxx>
73 #include <docufld.hxx>
74 #include <swmodule.hxx>
76 #include <SwRewriter.hxx>
77 #include <txtannotationfld.hxx>
78 #include <ndtxt.hxx>
79 #include <svtools/colorcfg.hxx>
81 #include <drawinglayer/processor2d/baseprocessor2d.hxx>
82 #include <drawinglayer/processor2d/processor2dtools.hxx>
83 #include <officecfg/Office/Writer.hxx>
84 #include <osl/diagnose.h>
85 #include <unotools/localedatawrapper.hxx>
86 #include <unotools/syslocale.hxx>
87 #include <memory>
88 #include <comphelper/lok.hxx>
90 using namespace sw::sidebarwindows;
92 namespace
95 void collectUIInformation( const OUString& aevent , const OUString& aID )
97 EventDescription aDescription;
98 aDescription.aID = aID;
99 aDescription.aParameters = {{"" , ""}};
100 aDescription.aAction = aevent;
101 aDescription.aParent = "MainWindow";
102 aDescription.aKeyWord = "SwEditWinUIObject";
103 UITestLogger::getInstance().logEvent(aDescription);
108 namespace sw::annotation {
110 #define METABUTTON_WIDTH 16
111 #define METABUTTON_HEIGHT 18
112 #define POSTIT_MINIMUMSIZE_WITHOUT_META 50
114 void SwAnnotationWin::PaintTile(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect)
116 bool bMenuButtonVisible = mxMenuButton->get_visible();
117 // No point in showing this button till click on it are not handled.
118 if (bMenuButtonVisible)
119 mxMenuButton->hide();
121 // draw left over space
122 if (Application::GetSettings().GetStyleSettings().GetHighContrastMode())
123 rRenderContext.SetFillColor(COL_BLACK);
124 else
125 rRenderContext.SetFillColor(mColorDark);
126 rRenderContext.SetLineColor();
127 rRenderContext.DrawRect(rRect);
129 m_xContainer->draw(rRenderContext, rRect.TopLeft(), GetSizePixel());
131 const drawinglayer::geometry::ViewInformation2D aViewInformation;
132 std::unique_ptr<drawinglayer::processor2d::BaseProcessor2D> pProcessor(drawinglayer::processor2d::createProcessor2DFromOutputDevice(rRenderContext, aViewInformation));
134 // drawinglayer sets the map mode to pixels, not needed here.
135 rRenderContext.Pop();
136 // Work in document-global twips.
137 rRenderContext.Pop();
138 if (mpAnchor)
139 pProcessor->process(mpAnchor->getOverlayObjectPrimitive2DSequence());
140 if (mpTextRangeOverlay)
141 pProcessor->process(mpTextRangeOverlay->getOverlayObjectPrimitive2DSequence());
143 rRenderContext.Push(vcl::PushFlags::NONE);
144 pProcessor.reset();
145 rRenderContext.Push(vcl::PushFlags::NONE);
147 if (bMenuButtonVisible)
148 mxMenuButton->show();
151 bool SwAnnotationWin::IsHitWindow(const Point& rPointLogic)
153 tools::Rectangle aRectangleLogic(EditWin().PixelToLogic(tools::Rectangle(GetPosPixel(),GetSizePixel())));
154 return aRectangleLogic.Contains(rPointLogic);
157 void SwAnnotationWin::SetCursorLogicPosition(const Point& rPosition, bool bPoint, bool bClearMark)
159 mxSidebarTextControl->SetCursorLogicPosition(rPosition, bPoint, bClearMark);
162 void SwAnnotationWin::DrawForPage(OutputDevice* pDev, const Point& rPt)
164 // tdf#143511 unclip SysObj so get_extents_relative_to of children
165 // of the SysObj can provide meaningful results
166 UnclipVisibleSysObj();
168 vcl::PDFExtOutDevData *const pPDFExtOutDevData(
169 dynamic_cast<vcl::PDFExtOutDevData*>(pDev->GetExtOutDevData()));
170 if (pPDFExtOutDevData && pPDFExtOutDevData->GetIsExportTaggedPDF())
172 pPDFExtOutDevData->WrapBeginStructureElement(vcl::pdf::StructElement::NonStructElement, OUString());
175 pDev->Push();
177 pDev->SetFillColor(mColorDark);
178 pDev->SetLineColor();
180 pDev->SetTextColor(mColorDark.IsDark() ? COL_WHITE : COL_BLACK);
181 vcl::Font aFont = maLabelFont;
182 aFont.SetFontHeight(aFont.GetFontHeight() * 20);
183 pDev->SetFont(aFont);
185 Size aSz = PixelToLogic(GetSizePixel());
187 pDev->DrawRect(tools::Rectangle(rPt, aSz));
189 if (mxMetadataAuthor->get_visible())
191 int x, y, width, height;
192 mxMetadataAuthor->get_extents_relative_to(*m_xContainer, x, y, width, height);
193 Point aPos(rPt + PixelToLogic(Point(x, y)));
194 Size aSize(PixelToLogic(Size(width, height)));
196 pDev->Push(vcl::PushFlags::CLIPREGION);
197 pDev->IntersectClipRegion(tools::Rectangle(aPos, aSize));
198 pDev->DrawText(aPos, mxMetadataAuthor->get_label());
199 pDev->Pop();
202 if (mxMetadataDate->get_visible())
204 int x, y, width, height;
205 mxMetadataDate->get_extents_relative_to(*m_xContainer, x, y, width, height);
206 Point aPos(rPt + PixelToLogic(Point(x, y)));
207 Size aSize(PixelToLogic(Size(width, height)));
209 pDev->Push(vcl::PushFlags::CLIPREGION);
210 pDev->IntersectClipRegion(tools::Rectangle(aPos, aSize));
211 pDev->DrawText(aPos, mxMetadataDate->get_label());
212 pDev->Pop();
215 if (mxMetadataResolved->get_visible())
217 int x, y, width, height;
218 mxMetadataResolved->get_extents_relative_to(*m_xContainer, x, y, width, height);
219 Point aPos(rPt + PixelToLogic(Point(x, y)));
220 Size aSize(PixelToLogic(Size(width, height)));
222 pDev->Push(vcl::PushFlags::CLIPREGION);
223 pDev->IntersectClipRegion(tools::Rectangle(aPos, aSize));
224 pDev->DrawText(aPos, mxMetadataResolved->get_label());
225 pDev->Pop();
228 mxSidebarTextControl->DrawForPage(pDev, rPt);
230 const drawinglayer::geometry::ViewInformation2D aNewViewInfos;
231 std::unique_ptr<drawinglayer::processor2d::BaseProcessor2D> pProcessor(
232 drawinglayer::processor2d::createProcessor2DFromOutputDevice(
233 *pDev, aNewViewInfos ));
235 if (mpAnchor)
236 pProcessor->process(mpAnchor->getOverlayObjectPrimitive2DSequence());
237 if (mpTextRangeOverlay)
238 pProcessor->process(mpTextRangeOverlay->getOverlayObjectPrimitive2DSequence());
239 pProcessor.reset();
241 if (mxVScrollbar->get_vpolicy() != VclPolicyType::NEVER)
243 // if there is a scrollbar shown, draw "..." to indicate the comment isn't
244 // completely shown
245 int x, y, width, height;
246 mxMenuButton->get_extents_relative_to(*m_xContainer, x, y, width, height);
247 Point aPos(rPt + PixelToLogic(Point(x, y)));
248 pDev->DrawText(aPos, u"..."_ustr);
251 pDev->Pop();
253 if (pPDFExtOutDevData && pPDFExtOutDevData->GetIsExportTaggedPDF())
255 pPDFExtOutDevData->EndStructureElement();
259 void SwAnnotationWin::SetPosSizePixelRect(tools::Long nX, tools::Long nY, tools::Long nWidth, tools::Long nHeight,
260 const tools::Long aPageBorder)
262 mPosSize = tools::Rectangle(Point(nX,nY),Size(nWidth,nHeight));
263 mPageBorder = aPageBorder;
266 void SwAnnotationWin::SetAnchorRect(const SwRect& aAnchorRect)
268 if (!mAnchorRect.IsEmpty() && mAnchorRect != aAnchorRect)
269 mbAnchorRectChanged = true;
270 mAnchorRect = aAnchorRect;
273 void SwAnnotationWin::SetSize( const Size& rNewSize )
275 mPosSize.SetSize(rNewSize);
278 void SwAnnotationWin::SetVirtualPosSize( const Point& aPoint, const Size& aSize)
280 mPosSize = tools::Rectangle(aPoint,aSize);
283 void SwAnnotationWin::TranslateTopPosition(const tools::Long aAmount)
285 mPosSize.Move(0,aAmount);
288 void SwAnnotationWin::ShowAnchorOnly(const Point &aPoint)
290 HideNote();
291 SetPosAndSize();
292 if (mpAnchor)
294 mpAnchor->SetSixthPosition(basegfx::B2DPoint(aPoint.X(),aPoint.Y()));
295 mpAnchor->SetSeventhPosition(basegfx::B2DPoint(aPoint.X(),aPoint.Y()));
296 mpAnchor->SetAnchorState(AnchorState::All);
297 mpAnchor->setVisible(true);
299 if (mpShadow)
300 mpShadow->setVisible(false);
303 void SwAnnotationWin::InitControls()
305 // window controls for author and date
306 mxMetadataAuthor = m_xBuilder->weld_label(u"author"_ustr);
307 mxMetadataAuthor->set_accessible_name( SwResId( STR_ACCESS_ANNOTATION_AUTHOR_NAME ) );
308 mxMetadataAuthor->set_direction(AllSettings::GetLayoutRTL());
310 maLabelFont = Application::GetSettings().GetStyleSettings().GetLabelFont();
311 maLabelFont.SetFontHeight(8);
313 // we should leave this setting alone, but for this we need a better layout algo
314 // with variable meta size height
315 mxMetadataAuthor->set_font(maLabelFont);
317 mxMetadataDate = m_xBuilder->weld_label(u"date"_ustr);
318 mxMetadataDate->set_accessible_name( SwResId( STR_ACCESS_ANNOTATION_DATE_NAME ) );
319 mxMetadataDate->set_direction(AllSettings::GetLayoutRTL());
320 mxMetadataDate->connect_mouse_move(LINK(this, SwAnnotationWin, MouseMoveHdl));
322 // we should leave this setting alone, but for this we need a better layout algo
323 // with variable meta size height
324 mxMetadataDate->set_font(maLabelFont);
326 mxMetadataResolved = m_xBuilder->weld_label(u"resolved"_ustr);
327 mxMetadataResolved->set_accessible_name( SwResId( STR_ACCESS_ANNOTATION_RESOLVED_NAME ) );
328 mxMetadataResolved->set_direction(AllSettings::GetLayoutRTL());
329 mxMetadataResolved->connect_mouse_move(LINK(this, SwAnnotationWin, MouseMoveHdl));
331 // we should leave this setting alone, but for this we need a better layout algo
332 // with variable meta size height
333 mxMetadataResolved->set_font(maLabelFont);
334 mxMetadataResolved->set_label(SwResId(STR_ACCESS_ANNOTATION_RESOLVED_NAME));
336 SwDocShell* aShell = mrView.GetDocShell();
337 mpOutliner.reset(new Outliner(&aShell->GetPool(),OutlinerMode::TextObject));
338 mpOutliner->SetStyleSheetPool(static_cast<SwDocStyleSheetPool*>(aShell->GetStyleSheetPool())->GetEEStyleSheetPool());
339 aShell->GetDoc()->SetCalcFieldValueHdl( mpOutliner.get() );
340 mpOutliner->SetUpdateLayout( true );
342 mpOutlinerView.reset(new OutlinerView(mpOutliner.get(), nullptr));
343 mpOutliner->InsertView(mpOutlinerView.get());
345 //create Scrollbars
346 mxVScrollbar = m_xBuilder->weld_scrolled_window(u"scrolledwindow"_ustr, true);
348 mxMenuButton = m_xBuilder->weld_menu_button(u"menubutton"_ustr);
349 mxMenuButton->set_size_request(METABUTTON_WIDTH, METABUTTON_HEIGHT);
351 // actual window which holds the user text
352 mxSidebarTextControl.reset(new SidebarTextControl(*this, mrView, mrMgr));
353 mxSidebarTextControlWin.reset(new weld::CustomWeld(*m_xBuilder, u"editview"_ustr, *mxSidebarTextControl));
354 mxSidebarTextControl->SetPointer(PointerStyle::Text);
356 Rescale();
358 mpOutlinerView->SetBackgroundColor(COL_TRANSPARENT);
359 mpOutlinerView->SetOutputArea( PixelToLogic( tools::Rectangle(0,0,1,1) ) );
361 mxVScrollbar->set_direction(false);
362 mxVScrollbar->connect_vadjustment_changed(LINK(this, SwAnnotationWin, ScrollHdl));
363 mxVScrollbar->connect_mouse_move(LINK(this, SwAnnotationWin, MouseMoveHdl));
365 EEControlBits nCntrl = mpOutliner->GetControlWord();
366 // TODO: crash when AUTOCOMPLETE enabled
367 nCntrl |= EEControlBits::MARKFIELDS | EEControlBits::PASTESPECIAL | EEControlBits::AUTOCORRECT | EEControlBits::USECHARATTRIBS; // | EEControlBits::AUTOCOMPLETE;
368 // Our stylesheet pool follows closely the core paragraph styles.
369 // We don't want the rtf import (during paste) to mess with that.
370 nCntrl &= ~EEControlBits::RTFSTYLESHEETS;
372 if (SwWrtShell* pWrtShell = mrView.GetWrtShellPtr())
374 const SwViewOption* pVOpt = pWrtShell->GetViewOptions();
375 if (pVOpt->IsFieldShadings())
376 nCntrl |= EEControlBits::MARKFIELDS;
377 else
378 nCntrl &= ~EEControlBits::MARKFIELDS;
379 if (pVOpt->IsOnlineSpell())
380 nCntrl |= EEControlBits::ONLINESPELLING;
381 else
382 nCntrl &= ~EEControlBits::ONLINESPELLING;
384 mpOutliner->SetControlWord(nCntrl);
386 std::size_t aIndex = SwModule::get()->InsertRedlineAuthor(GetAuthor());
387 SetColor( SwPostItMgr::GetColorDark(aIndex),
388 SwPostItMgr::GetColorLight(aIndex),
389 SwPostItMgr::GetColorAnchor(aIndex));
391 CheckMetaText();
393 // expand %1 "Author"
394 OUString aText = mxMenuButton->get_item_label(u"deleteby"_ustr);
395 SwRewriter aRewriter;
396 aRewriter.AddRule(UndoArg1, GetAuthor());
397 aText = aRewriter.Apply(aText);
398 mxMenuButton->set_item_label(u"deleteby"_ustr, aText);
400 mxMenuButton->set_accessible_name(SwResId(STR_ACCESS_ANNOTATION_BUTTON_NAME));
401 mxMenuButton->set_accessible_description(SwResId(STR_ACCESS_ANNOTATION_BUTTON_DESC));
402 mxMenuButton->set_tooltip_text(SwResId(STR_ACCESS_ANNOTATION_BUTTON_DESC));
404 mxMenuButton->connect_toggled(LINK(this, SwAnnotationWin, ToggleHdl));
405 mxMenuButton->connect_selected(LINK(this, SwAnnotationWin, SelectHdl));
406 mxMenuButton->connect_key_press(LINK(this, SwAnnotationWin, KeyInputHdl));
407 mxMenuButton->connect_mouse_move(LINK(this, SwAnnotationWin, MouseMoveHdl));
409 GetOutlinerView()->StartSpeller(mxSidebarTextControl->GetDrawingArea());
410 SetPostItText();
411 mpOutliner->CompleteOnlineSpelling();
413 mxSidebarTextControl->Show();
414 mxMetadataAuthor->show();
415 mxMetadataDate->show();
416 mxMetadataResolved->set_visible(IsResolved());
417 mxVScrollbar->set_vpolicy(VclPolicyType::ALWAYS);
420 void SwAnnotationWin::CheckMetaText()
422 const SvtSysLocale aSysLocale;
423 const LocaleDataWrapper& rLocalData = aSysLocale.GetLocaleData();
424 OUString sMeta = GetAuthor();
425 if (sMeta.isEmpty())
427 sMeta = SwResId(STR_NOAUTHOR);
429 else if (sMeta.getLength() > 23)
431 sMeta = OUString::Concat(sMeta.subView(0, 20)) + "...";
433 if ( mxMetadataAuthor->get_label() != sMeta )
435 mxMetadataAuthor->set_label(sMeta);
438 Date aDate = GetDate();
439 if (aDate.IsValidAndGregorian() )
441 sMeta = rLocalData.getDate(aDate);
443 else
445 sMeta = SwResId(STR_NODATE);
447 if (GetTime().GetTime()!=0)
449 sMeta += " " + rLocalData.getTime( GetTime(),false );
451 if ( mxMetadataDate->get_label() != sMeta )
453 mxMetadataDate->set_label(sMeta);
455 UpdateColors();
458 void SwAnnotationWin::UpdateColors()
460 std::size_t aIndex = SwModule::get()->InsertRedlineAuthor(GetAuthor());
461 SetColor( SwPostItMgr::GetColorDark(aIndex),
462 SwPostItMgr::GetColorLight(aIndex),
463 SwPostItMgr::GetColorAnchor(aIndex));
464 // draw comments either black or white depending on the document background
465 // TODO: make editeng depend on the actual note background
466 mpOutlinerView->SetBackgroundColor(svtools::ColorConfig().GetColorValue(svtools::DOCCOLOR).nColor);
469 void SwAnnotationWin::SetMenuButtonColors()
471 if (!mxMenuButton)
472 return;
474 SwWrtShell* pWrtShell = mrView.GetWrtShellPtr();
475 if (!pWrtShell)
476 return;
477 const Fraction& rFraction = pWrtShell->GetOut()->GetMapMode().GetScaleY();
479 ScopedVclPtrInstance<VirtualDevice> xVirDev;
480 Size aSize(tools::Long(METABUTTON_WIDTH * rFraction),
481 tools::Long(METABUTTON_HEIGHT * rFraction));
482 tools::Rectangle aRect(Point(0, 0), aSize);
483 xVirDev->SetOutputSizePixel(aSize);
485 Gradient aGradient(css::awt::GradientStyle_LINEAR,
486 mColorLight,
487 mColorDark);
488 xVirDev->DrawGradient(aRect, aGradient);
490 //draw rect around button
491 xVirDev->SetFillColor();
492 xVirDev->SetLineColor(mColorDark.IsDark() ? mColorLight : mColorDark);
493 xVirDev->DrawRect(aRect);
495 tools::Rectangle aSymbolRect(aRect);
496 // 25% distance to the left and right button border
497 const tools::Long nBorderDistanceLeftAndRight = ((aSymbolRect.GetWidth() * 250) + 500) / 1000;
498 aSymbolRect.AdjustLeft(nBorderDistanceLeftAndRight );
499 aSymbolRect.AdjustRight( -nBorderDistanceLeftAndRight );
500 // 30% distance to the top button border
501 const tools::Long nBorderDistanceTop = ((aSymbolRect.GetHeight() * 300) + 500) / 1000;
502 aSymbolRect.AdjustTop(nBorderDistanceTop );
503 // 25% distance to the bottom button border
504 const tools::Long nBorderDistanceBottom = ((aSymbolRect.GetHeight() * 250) + 500) / 1000;
505 aSymbolRect.AdjustBottom( -nBorderDistanceBottom );
507 DecorationView aDecoView(xVirDev.get());
508 aDecoView.DrawSymbol(aSymbolRect, SymbolType::SPIN_DOWN, mColorDark.IsDark() ? COL_WHITE : COL_BLACK,
509 DrawSymbolFlags::NONE);
510 mxMenuButton->set_image(xVirDev);
511 mxMenuButton->set_size_request(aSize.Width() + 4, aSize.Height() + 4);
514 void SwAnnotationWin::Rescale()
516 // On Android, this method leads to invoke ImpEditEngine::UpdateViews
517 // which hides the text cursor. Moreover it causes sudden document scroll
518 // when modifying a commented text. Not clear the root cause,
519 // anyway skipping this method fixes the problem, and there should be
520 // no side effect, since the client has disabled annotations rendering.
521 if (comphelper::LibreOfficeKit::isActive() && !comphelper::LibreOfficeKit::isTiledAnnotations())
522 return;
524 MapMode aMode = GetParent()->GetMapMode();
525 aMode.SetOrigin( Point() );
526 SetMapMode( aMode );
527 mxSidebarTextControl->SetMapMode( aMode );
529 SwWrtShell* pWrtShell = mrView.GetWrtShellPtr();
530 if (!pWrtShell)
531 return;
532 const Fraction& rFraction = pWrtShell->GetOut()->GetMapMode().GetScaleY();
534 vcl::Font aFont = maLabelFont;
535 sal_Int32 nHeight = tools::Long(aFont.GetFontHeight() * rFraction);
536 aFont.SetFontHeight( nHeight );
538 if (mxMetadataAuthor)
539 mxMetadataAuthor->set_font(aFont);
540 if (mxMetadataDate)
541 mxMetadataDate->set_font(aFont);
542 if (mxMetadataResolved)
543 mxMetadataResolved->set_font(aFont);
544 SetMenuButtonColors();
545 if (mxVScrollbar)
546 mxVScrollbar->set_scroll_thickness(GetPrefScrollbarWidth());
549 void SwAnnotationWin::SetPosAndSize()
551 const bool bShowNotes = mrMgr.ShowNotes();
552 if (bShowNotes)
554 bool bChange = false;
556 if (GetSizePixel() != mPosSize.GetSize())
558 bChange = true;
559 SetSizePixel(mPosSize.GetSize());
561 DoResize();
564 if (GetPosPixel().X() != mPosSize.Left() || (std::abs(GetPosPixel().Y() - mPosSize.Top()) > 5) )
566 bChange = true;
567 SetPosPixel(mPosSize.TopLeft());
570 if (bChange)
572 Point aLineStart;
573 Point aLineEnd ;
574 switch ( meSidebarPosition )
576 case sw::sidebarwindows::SidebarPosition::LEFT:
578 aLineStart = EditWin().PixelToLogic( Point(GetPosPixel().X()+GetSizePixel().Width(),GetPosPixel().Y()-1) );
579 aLineEnd = EditWin().PixelToLogic( Point(GetPosPixel().X(),GetPosPixel().Y()-1) );
581 break;
582 case sw::sidebarwindows::SidebarPosition::RIGHT:
584 aLineStart = EditWin().PixelToLogic( Point(GetPosPixel().X(),GetPosPixel().Y()-1) );
585 aLineEnd = EditWin().PixelToLogic( Point(GetPosPixel().X()+GetSizePixel().Width(),GetPosPixel().Y()-1) );
587 break;
588 default:
589 OSL_FAIL( "<SwAnnotationWin::SetPosAndSize()> - unexpected position of sidebar" );
590 break;
593 // LOK has map mode disabled, and we still want to perform pixel ->
594 // twips conversion for the size of the line above the note.
595 if (comphelper::LibreOfficeKit::isActive() && !EditWin().IsMapModeEnabled())
597 EditWin().EnableMapMode();
598 Size aSize(aLineEnd.getX() - aLineStart.getX(), aLineEnd.getY() - aLineStart.getY());
599 aSize = EditWin().PixelToLogic(aSize);
600 aLineEnd = aLineStart;
601 aLineEnd.Move(aSize.getWidth(), aSize.getHeight());
602 EditWin().EnableMapMode(false);
605 if (mpAnchor)
607 mpAnchor->SetAllPosition( basegfx::B2DPoint( mAnchorRect.Left() , mAnchorRect.Bottom() - 5* 15),
608 basegfx::B2DPoint( mAnchorRect.Left()-5*15 , mAnchorRect.Bottom()+5*15),
609 basegfx::B2DPoint( mAnchorRect.Left()+5*15 , mAnchorRect.Bottom()+5*15),
610 basegfx::B2DPoint( mAnchorRect.Left(), mAnchorRect.Bottom()+2*15),
611 basegfx::B2DPoint( mPageBorder ,mAnchorRect.Bottom()+2*15),
612 basegfx::B2DPoint( aLineStart.X(),aLineStart.Y()),
613 basegfx::B2DPoint( aLineEnd.X(),aLineEnd.Y()));
615 else
617 mpAnchor = AnchorOverlayObject::CreateAnchorOverlayObject( mrView,
618 mAnchorRect,
619 mPageBorder,
620 aLineStart,
621 aLineEnd,
622 mColorAnchor );
623 if ( mpAnchor )
625 mpAnchor->setVisible(true);
626 mpAnchor->SetAnchorState(AnchorState::Tri);
627 if (HasChildPathFocus())
629 mpAnchor->setLineSolid(true);
634 else
636 if ( mpAnchor &&
637 ( mpAnchor->getBasePosition() != basegfx::B2DPoint( mAnchorRect.Left() , mAnchorRect.Bottom()-5*15) ) )
639 mpAnchor->SetTriPosition( basegfx::B2DPoint( mAnchorRect.Left() , mAnchorRect.Bottom() - 5* 15),
640 basegfx::B2DPoint( mAnchorRect.Left()-5*15 , mAnchorRect.Bottom()+5*15),
641 basegfx::B2DPoint( mAnchorRect.Left()+5*15 , mAnchorRect.Bottom()+5*15),
642 basegfx::B2DPoint( mAnchorRect.Left(), mAnchorRect.Bottom()+2*15),
643 basegfx::B2DPoint( mPageBorder , mAnchorRect.Bottom()+2*15));
647 if (mpShadow && bChange)
649 Point aStart = EditWin().PixelToLogic(GetPosPixel()+Point(0,GetSizePixel().Height()));
650 Point aEnd = EditWin().PixelToLogic(GetPosPixel()+Point(GetSizePixel().Width()-1,GetSizePixel().Height()));
651 mpShadow->SetPosition(basegfx::B2DPoint(aStart.X(),aStart.Y()), basegfx::B2DPoint(aEnd.X(),aEnd.Y()));
654 if (IsFollow() && !HasChildPathFocus())
656 // #i111964#
657 if ( mpAnchor )
659 mpAnchor->SetAnchorState(AnchorState::End);
662 else
664 // #i111964#
665 if ( mpAnchor )
667 mpAnchor->SetAnchorState(AnchorState::All);
669 SwAnnotationWin* pWin = GetTopReplyNote();
670 // #i111964#
671 if ( pWin != this && pWin->Anchor() )
673 pWin->Anchor()->SetAnchorState(AnchorState::End);
678 // text range overlay
679 maAnnotationTextRanges.clear();
680 if ( mpSidebarItem->maLayoutInfo.mnStartNodeIdx != SwNodeOffset(0)
681 && mpSidebarItem->maLayoutInfo.mnStartContent != -1 )
683 const SwTextAnnotationField* pTextAnnotationField =
684 dynamic_cast< const SwTextAnnotationField* >( mpSidebarItem->GetFormatField().GetTextField() );
685 SwTextNode* pTextNode = pTextAnnotationField ? pTextAnnotationField->GetpTextNode() : nullptr;
686 SwContentNode* pContentNd = nullptr;
687 if (pTextNode)
689 SwNodes& rNds = pTextNode->GetDoc().GetNodes();
690 pContentNd = rNds[mpSidebarItem->maLayoutInfo.mnStartNodeIdx]->GetContentNode();
692 if (pContentNd)
694 SwPosition aStartPos( *pContentNd, mpSidebarItem->maLayoutInfo.mnStartContent );
695 SwShellCursor* pTmpCursor = nullptr;
696 const bool bTableCursorNeeded = pTextNode->FindTableBoxStartNode() != pContentNd->FindTableBoxStartNode();
697 if ( bTableCursorNeeded )
699 SwShellTableCursor* pTableCursor = new SwShellTableCursor( mrView.GetWrtShell(), aStartPos );
700 pTableCursor->SetMark();
701 pTableCursor->GetMark()->Assign( *pTextNode, pTextAnnotationField->GetStart()+1 );
702 pTableCursor->NewTableSelection();
703 pTmpCursor = pTableCursor;
705 else
707 SwShellCursor* pCursor = new SwShellCursor( mrView.GetWrtShell(), aStartPos );
708 pCursor->SetMark();
709 pCursor->GetMark()->Assign(*pTextNode, pTextAnnotationField->GetStart()+1 );
710 pTmpCursor = pCursor;
712 std::unique_ptr<SwShellCursor> pTmpCursorForAnnotationTextRange( pTmpCursor );
714 // For annotation text range rectangles to be calculated correctly,
715 // we need the map mode disabled
716 bool bDisableMapMode = comphelper::LibreOfficeKit::isActive() && EditWin().IsMapModeEnabled();
717 if (bDisableMapMode)
718 EditWin().EnableMapMode(false);
720 if (mpSidebarItem->maLayoutInfo.mPositionFromCommentAnchor)
721 pTmpCursorForAnnotationTextRange->FillRects();
723 if (bDisableMapMode)
724 EditWin().EnableMapMode();
726 SwRects* pRects(pTmpCursorForAnnotationTextRange.get());
727 for(const SwRect & rNextRect : *pRects)
729 const tools::Rectangle aPntRect(rNextRect.SVRect());
730 maAnnotationTextRanges.emplace_back(
731 aPntRect.Left(), aPntRect.Top(),
732 aPntRect.Right() + 1, aPntRect.Bottom() + 1);
737 if (bShowNotes && !maAnnotationTextRanges.empty())
739 if ( mpTextRangeOverlay != nullptr )
741 mpTextRangeOverlay->setRanges( std::vector(maAnnotationTextRanges) );
742 if ( mpAnchor != nullptr && mpAnchor->getLineSolid() )
744 mpTextRangeOverlay->ShowSolidBorder();
746 else
748 mpTextRangeOverlay->HideSolidBorder();
751 else if (!IsFollow())
753 // This window is not a reply, then draw its range overlay.
754 mpTextRangeOverlay =
755 sw::overlay::OverlayRanges::CreateOverlayRange(
756 mrView,
757 mColorAnchor,
758 std::vector(maAnnotationTextRanges),
759 mpAnchor && mpAnchor->getLineSolid() );
762 else
764 mpTextRangeOverlay.reset();
768 void SwAnnotationWin::DoResize()
770 tools::Long aHeight = GetSizePixel().Height();
771 tools::ULong aWidth = GetSizePixel().Width();
773 aHeight -= GetMetaHeight();
775 mpOutliner->SetPaperSize( PixelToLogic( Size(aWidth, aHeight) ) ) ;
776 tools::Long aTextHeight = LogicToPixel( mpOutliner->CalcTextSize()).Height();
778 mxMetadataAuthor->show();
779 if(IsResolved()) { mxMetadataResolved->show(); }
780 mxMetadataDate->show();
782 if (aTextHeight > aHeight)
784 const int nThickness = mxVScrollbar->get_scroll_thickness();
785 if (nThickness)
787 // we need vertical scrollbars and have to reduce the width
788 aWidth -= nThickness;
789 mpOutliner->SetPaperSize(PixelToLogic(Size(aWidth, aHeight)));
791 mxVScrollbar->set_vpolicy(VclPolicyType::ALWAYS);
793 else
795 mxVScrollbar->set_vpolicy(VclPolicyType::NEVER);
798 tools::Rectangle aOutputArea = PixelToLogic(tools::Rectangle(0, 0, aWidth, aHeight));
799 if (mxVScrollbar->get_vpolicy() == VclPolicyType::NEVER)
801 // if we do not have a scrollbar anymore, we want to see the complete text
802 mpOutlinerView->SetVisArea(aOutputArea);
804 mpOutlinerView->SetOutputArea(aOutputArea);
805 mpOutlinerView->ShowCursor(true, true);
807 // Don't leave an empty area at the bottom if we can move the text down.
808 tools::Long nMaxVisAreaTop = mpOutliner->GetTextHeight() - aOutputArea.GetHeight();
809 if (mpOutlinerView->GetVisArea().Top() > nMaxVisAreaTop)
811 GetOutlinerView()->Scroll(0, mpOutlinerView->GetVisArea().Top() - nMaxVisAreaTop);
814 int nUpper = mpOutliner->GetTextHeight();
815 int nCurrentDocPos = mpOutlinerView->GetVisArea().Top();
816 int nStepIncrement = mpOutliner->GetTextHeight() / 10;
817 int nPageIncrement = PixelToLogic(Size(0,aHeight)).Height() * 8 / 10;
818 int nPageSize = PixelToLogic(Size(0,aHeight)).Height();
820 /* limit the page size to below nUpper because gtk's gtk_scrolled_window_start_deceleration has
821 effectively...
823 lower = gtk_adjustment_get_lower
824 upper = gtk_adjustment_get_upper - gtk_adjustment_get_page_size
826 and requires that upper > lower or the deceleration animation never ends
828 nPageSize = std::min(nPageSize, nUpper);
830 mxVScrollbar->vadjustment_configure(nCurrentDocPos, 0, nUpper,
831 nStepIncrement, nPageIncrement, nPageSize);
834 void SwAnnotationWin::SetSizePixel( const Size& rNewSize )
836 if (comphelper::LibreOfficeKit::isActive())
837 return;
839 InterimItemWindow::SetSizePixel(rNewSize);
841 if (mpShadow)
843 Point aStart = EditWin().PixelToLogic(GetPosPixel()+Point(0,GetSizePixel().Height()));
844 Point aEnd = EditWin().PixelToLogic(GetPosPixel()+Point(GetSizePixel().Width()-1,GetSizePixel().Height()));
845 mpShadow->SetPosition(basegfx::B2DPoint(aStart.X(),aStart.Y()), basegfx::B2DPoint(aEnd.X(),aEnd.Y()));
849 void SwAnnotationWin::SetScrollbar()
851 mxVScrollbar->vadjustment_set_value(mpOutlinerView->GetVisArea().Top());
854 void SwAnnotationWin::ResizeIfNecessary(tools::Long aOldHeight, tools::Long aNewHeight)
856 if (aOldHeight != aNewHeight)
858 //check for lower border or next note
859 tools::Long aBorder = mrMgr.GetNextBorder();
860 if (aBorder != -1)
862 if (aNewHeight > GetMinimumSizeWithoutMeta())
864 tools::Long aNewLowerValue = GetPosPixel().Y() + aNewHeight + GetMetaHeight();
865 if (aNewLowerValue < aBorder)
866 SetSizePixel(Size(GetSizePixel().Width(),aNewHeight+GetMetaHeight()));
867 else
868 SetSizePixel(Size(GetSizePixel().Width(),aBorder - GetPosPixel().Y()));
869 DoResize();
870 Invalidate();
872 else
874 if (GetSizePixel().Height() != GetMinimumSizeWithoutMeta() + GetMetaHeight())
875 SetSizePixel(Size(GetSizePixel().Width(),GetMinimumSizeWithoutMeta() + GetMetaHeight()));
876 DoResize();
877 Invalidate();
880 else
882 DoResize();
883 Invalidate();
886 else
888 SetScrollbar();
892 void SwAnnotationWin::SetColor(Color aColorDark,Color aColorLight, Color aColorAnchor)
894 mColorDark = aColorDark;
895 mColorLight = aColorLight;
896 mColorAnchor = aColorAnchor;
898 if ( Application::GetSettings().GetStyleSettings().GetHighContrastMode() )
899 return;
901 m_xContainer->set_background(mColorDark);
902 SetMenuButtonColors();
904 Color aColor(mColorDark.IsDark() ? COL_WHITE : COL_BLACK);
905 mxMetadataAuthor->set_font_color(aColor);
907 mxMetadataDate->set_font_color(aColor);
909 mxMetadataResolved->set_font_color(aColor);
911 mxVScrollbar->customize_scrollbars(mColorLight,
912 mColorAnchor,
913 mColorDark);
916 void SwAnnotationWin::SetSidebarPosition(sw::sidebarwindows::SidebarPosition eSidebarPosition)
918 meSidebarPosition = eSidebarPosition;
921 void SwAnnotationWin::SetReadonly(bool bSet)
923 mbReadonly = bSet;
924 GetOutlinerView()->SetReadOnly(bSet);
927 void SwAnnotationWin::GetFocus()
929 if (mxSidebarTextControl)
930 mxSidebarTextControl->GrabFocus();
933 void SwAnnotationWin::LoseFocus()
937 void SwAnnotationWin::ShowNote()
939 SetPosAndSize();
940 if (!IsVisible())
941 Window::Show();
942 if (mpShadow && !mpShadow->isVisible())
943 mpShadow->setVisible(true);
944 if (mpAnchor && !mpAnchor->isVisible())
945 mpAnchor->setVisible(true);
946 if (mpTextRangeOverlay && !mpTextRangeOverlay->isVisible())
947 mpTextRangeOverlay->setVisible(true);
949 collectUIInformation(u"SHOW"_ustr,get_id());
952 void SwAnnotationWin::HideNote()
954 if (IsVisible())
955 Window::Hide();
956 if (mpAnchor)
958 if (officecfg::Office::Writer::Notes::ShowAnkor::get())
959 mpAnchor->SetAnchorState(AnchorState::Tri);
960 else
961 mpAnchor->setVisible(false);
963 if (mpShadow && mpShadow->isVisible())
964 mpShadow->setVisible(false);
965 if (mpTextRangeOverlay && mpTextRangeOverlay->isVisible())
966 mpTextRangeOverlay->setVisible(false);
967 collectUIInformation(u"HIDE"_ustr,get_id());
970 void SwAnnotationWin::ActivatePostIt()
972 mrMgr.AssureStdModeAtShell();
974 mpOutliner->ClearModifyFlag();
975 mpOutliner->GetUndoManager().Clear();
977 CheckMetaText();
978 SetViewState(ViewState::EDIT);
980 // prevent autoscroll to the old cursor location
981 // when cursor out of visible area
982 GetOutlinerView()->ShowCursor(false);
984 if (SwWrtShell* pWrtShell = mrView.GetWrtShellPtr())
985 mpOutlinerView->GetEditView().SetInsertMode(pWrtShell->IsInsMode());
987 if ( !Application::GetSettings().GetStyleSettings().GetHighContrastMode() )
988 GetOutlinerView()->SetBackgroundColor(mColorDark);
990 //tdf#119130 only have the active postit as a dialog control in which pressing
991 //ctrl+tab cycles between text and button so we don't waste time searching
992 //thousands of SwAnnotationWins
993 SetStyle(GetStyle() | WB_DIALOGCONTROL);
995 mrView.GetDocShell()->Broadcast(SfxHint(SfxHintId::SwNavigatorUpdateTracking));
998 void SwAnnotationWin::DeactivatePostIt()
1000 //tdf#119130 only have the active postit as a dialog control in which pressing
1001 //ctrl+tab cycles between text and button so we don't waste time searching
1002 //thousands of SwAnnotationWins
1003 SetStyle(GetStyle() & ~WB_DIALOGCONTROL);
1005 // remove selection, #i87073#
1006 if (GetOutlinerView()->GetEditView().HasSelection())
1008 ESelection aSelection = GetOutlinerView()->GetEditView().GetSelection();
1009 aSelection.CollapseToStart();
1010 GetOutlinerView()->GetEditView().SetSelection(aSelection);
1013 mpOutliner->CompleteOnlineSpelling();
1015 SetViewState(ViewState::NORMAL);
1016 // Make sure this view doesn't emit LOK callbacks during the update, as the
1017 // sidebar window's SidebarTextControl doesn't have a valid twip offset
1018 // (map mode origin) during that operation.
1019 bool bTiledPainting = comphelper::LibreOfficeKit::isTiledPainting();
1020 comphelper::LibreOfficeKit::setTiledPainting(true);
1021 // write the visible text back into the SwField
1022 UpdateData();
1023 comphelper::LibreOfficeKit::setTiledPainting(bTiledPainting);
1025 if ( !Application::GetSettings().GetStyleSettings().GetHighContrastMode() )
1026 GetOutlinerView()->SetBackgroundColor(COL_TRANSPARENT);
1028 if (!mnDeleteEventId && !IsReadOnlyOrProtected() && !mpOutliner->GetEditEngine().HasText())
1030 mnDeleteEventId = Application::PostUserEvent( LINK( this, SwAnnotationWin, DeleteHdl), nullptr, true );
1034 void SwAnnotationWin::ToggleInsMode()
1036 if (!mrView.GetWrtShell().IsRedlineOn())
1038 //change outliner
1039 mpOutlinerView->GetEditView().SetInsertMode(!mpOutlinerView->GetEditView().IsInsertMode());
1040 //change document
1041 mrView.GetWrtShell().ToggleInsMode();
1042 //update statusbar
1043 SfxBindings &rBnd = mrView.GetViewFrame().GetBindings();
1044 rBnd.Invalidate(SID_ATTR_INSERT);
1045 rBnd.Update(SID_ATTR_INSERT);
1049 void SwAnnotationWin::ExecuteCommand(sal_uInt16 nSlot)
1051 mrMgr.AssureStdModeAtShell();
1053 switch (nSlot)
1055 case FN_POSTIT:
1056 case FN_REPLY:
1058 const bool bReply = nSlot == FN_REPLY;
1059 // if this note is empty, it will be deleted once losing the focus, so no reply, but only a new note
1060 // will be created
1061 if (!mrMgr.IsAnswer() && mpOutliner->GetEditEngine().HasText())
1063 OutlinerParaObject aPara(GetOutlinerView()->GetEditView().CreateTextObject());
1064 mrMgr.RegisterAnswer(aPara);
1066 if (mrMgr.HasActiveSidebarWin())
1067 mrMgr.SetActiveSidebarWin(nullptr);
1068 SwitchToFieldPos();
1070 SwDocShell* pShell = mrView.GetDocShell();
1071 if (bReply)
1072 pShell->GetDoc()->GetIDocumentUndoRedo().StartUndo(SwUndoId::INSERT, nullptr);
1074 // synchronous dispatch
1075 mrView.GetViewFrame().GetDispatcher()->Execute(FN_POSTIT);
1077 if (bReply)
1079 // Get newly created SwPostItField and set its paraIdParent
1080 auto pPostItField = mrMgr.GetLatestPostItField();
1081 pPostItField->SetParentId(GetParaId());
1082 pPostItField->SetParentPostItId(GetPostItField()->GetPostItId());
1083 this->GeneratePostItName();
1084 pPostItField->SetParentName(GetPostItField()->GetName());
1086 // In this case, force generating the associated window
1087 // synchronously so we can bundle its use of the registered
1088 // "Answer" into the same undo group that the synchronous
1089 // FN_POSTIT was put in
1090 mrMgr.GetOrCreateAnnotationWindowForLatestPostItField();
1092 SwRewriter aRewriter;
1093 aRewriter.AddRule(UndoArg1, pPostItField->GetDescription());
1094 pShell->GetDoc()->GetIDocumentUndoRedo().EndUndo(SwUndoId::INSERT, &aRewriter);
1096 break;
1098 case FN_DELETE_COMMENT:
1099 //Delete(); // do not kill the parent of our open popup menu
1100 mnDeleteEventId = Application::PostUserEvent( LINK( this, SwAnnotationWin, DeleteHdl), nullptr, true );
1101 break;
1102 case FN_DELETE_COMMENT_THREAD:
1103 DeleteThread();
1104 break;
1105 case FN_RESOLVE_NOTE:
1106 ToggleResolved();
1107 DoResize();
1108 Invalidate();
1109 mrMgr.LayoutPostIts();
1110 break;
1111 case FN_RESOLVE_NOTE_THREAD:
1112 GetTopReplyNote()->SetResolved(!IsThreadResolved());
1113 mrMgr.UpdateResolvedStatus(GetTopReplyNote());
1114 DoResize();
1115 Invalidate();
1116 mrMgr.LayoutPostIts();
1117 break;
1118 case FN_FORMAT_ALL_NOTES:
1119 case FN_DELETE_ALL_NOTES:
1120 case FN_HIDE_ALL_NOTES:
1121 // not possible as slot as this would require that "this" is the active postit
1122 mrView.GetViewFrame().GetBindings().Execute( nSlot, nullptr, SfxCallMode::ASYNCHRON );
1123 break;
1124 case FN_DELETE_NOTE_AUTHOR:
1125 case FN_HIDE_NOTE_AUTHOR:
1127 // not possible as slot as this would require that "this" is the active postit
1128 SfxStringItem aItem( nSlot, GetAuthor() );
1129 const SfxPoolItem* aItems[2];
1130 aItems[0] = &aItem;
1131 aItems[1] = nullptr;
1132 mrView.GetViewFrame().GetBindings().Execute( nSlot, aItems, SfxCallMode::ASYNCHRON );
1134 break;
1135 case FN_PROMOTE_COMMENT:
1136 SetAsRoot();
1137 DoResize();
1138 Invalidate();
1139 mrMgr.LayoutPostIts();
1140 break;
1141 default:
1142 mrView.GetViewFrame().GetBindings().Execute( nSlot );
1143 break;
1147 SwEditWin& SwAnnotationWin::EditWin()
1149 return mrView.GetEditWin();
1152 tools::Long SwAnnotationWin::GetPostItTextHeight()
1154 return mpOutliner ? LogicToPixel(mpOutliner->CalcTextSize()).Height() : 0;
1157 void SwAnnotationWin::SwitchToPostIt(sal_uInt16 aDirection)
1159 SwAnnotationWin* pPostIt = mrMgr.GetNextPostIt(aDirection, this);
1160 if (pPostIt)
1161 pPostIt->GrabFocus();
1164 IMPL_LINK(SwAnnotationWin, MouseMoveHdl, const MouseEvent&, rMEvt, bool)
1166 if (rMEvt.IsEnterWindow())
1168 mbMouseOver = true;
1169 if ( !HasFocus() )
1171 SetViewState(ViewState::VIEW);
1172 Invalidate();
1175 else if (rMEvt.IsLeaveWindow())
1177 mbMouseOver = false;
1178 if ( !HasFocus() )
1180 SetViewState(ViewState::NORMAL);
1181 Invalidate();
1184 return false;
1187 bool SwAnnotationWin::SetActiveSidebarWin()
1189 if (mrMgr.GetActiveSidebarWin() == this)
1190 return false;
1191 mrView.GetWrtShell().LockView( true );
1192 mrMgr.SetActiveSidebarWin(this);
1193 mrView.GetWrtShell().LockView( true );
1195 return true;
1198 void SwAnnotationWin::UnsetActiveSidebarWin()
1200 if (mrMgr.GetActiveSidebarWin() != this)
1201 return;
1202 mrView.GetWrtShell().LockView( true );
1203 mrMgr.SetActiveSidebarWin(nullptr);
1204 mrView.GetWrtShell().LockView( false );
1207 void SwAnnotationWin::LockView(bool bLock)
1209 mrView.GetWrtShell().LockView( bLock );
1212 IMPL_LINK(SwAnnotationWin, ScrollHdl, weld::ScrolledWindow&, rScrolledWindow, void)
1214 tools::Long nDiff = GetOutlinerView()->GetEditView().GetVisArea().Top() - rScrolledWindow.vadjustment_get_value();
1215 GetOutlinerView()->Scroll( 0, nDiff );
1218 IMPL_LINK_NOARG(SwAnnotationWin, ModifyHdl, LinkParamNone*, void)
1220 mrView.GetDocShell()->SetModified();
1223 IMPL_LINK_NOARG(SwAnnotationWin, DeleteHdl, void*, void)
1225 mnDeleteEventId = nullptr;
1226 Delete();
1229 void SwAnnotationWin::ResetAttributes()
1231 mpOutlinerView->RemoveAttribsKeepLanguages(true);
1232 mpOutliner->RemoveFields();
1235 int SwAnnotationWin::GetPrefScrollbarWidth() const
1237 if (SwWrtShell* pWrtShell = mrView.GetWrtShellPtr())
1239 const Fraction& f(pWrtShell->GetOut()->GetMapMode().GetScaleY());
1240 return tools::Long(Application::GetSettings().GetStyleSettings().GetScrollBarSize() * f);
1242 else
1243 return tools::Long(Application::GetSettings().GetStyleSettings().GetScrollBarSize());
1246 sal_Int32 SwAnnotationWin::GetMetaHeight() const
1248 const int fields = GetNumFields();
1250 sal_Int32 nRequiredHeight = 0;
1251 weld::Label* aLabels[3] = { mxMetadataAuthor.get(), mxMetadataDate.get(), mxMetadataResolved.get() };
1252 for (int i = 0; i < fields; ++i)
1253 nRequiredHeight += aLabels[i]->get_preferred_size().Height();
1255 return nRequiredHeight;
1258 sal_Int32 SwAnnotationWin::GetNumFields() const
1260 return IsResolved() ? 3 : 2;
1263 sal_Int32 SwAnnotationWin::GetMinimumSizeWithMeta() const
1265 return mrMgr.GetMinimumSizeWithMeta();
1268 sal_Int32 SwAnnotationWin::GetMinimumSizeWithoutMeta() const
1270 if (SwWrtShell* pWrtShell = mrView.GetWrtShellPtr())
1272 const Fraction& f(pWrtShell->GetOut()->GetMapMode().GetScaleY());
1273 return tools::Long(POSTIT_MINIMUMSIZE_WITHOUT_META * f);
1275 else
1276 return tools::Long(POSTIT_MINIMUMSIZE_WITHOUT_META);
1279 void SwAnnotationWin::SetSpellChecking()
1281 if (SwWrtShell* pWrtShell = mrView.GetWrtShellPtr())
1283 const SwViewOption* pVOpt = pWrtShell->GetViewOptions();
1284 EEControlBits nCntrl = mpOutliner->GetControlWord();
1285 mpOutliner->SetControlWord(nCntrl & ~EEControlBits::ONLINESPELLING);
1286 if (pVOpt->IsOnlineSpell())
1287 mpOutliner->SetControlWord(nCntrl | EEControlBits::ONLINESPELLING);
1289 mpOutliner->CompleteOnlineSpelling();
1290 Invalidate();
1294 void SwAnnotationWin::SetViewState(ViewState bViewState)
1296 switch (bViewState)
1298 case ViewState::EDIT:
1300 if (mpAnchor)
1302 mpAnchor->SetAnchorState(AnchorState::All);
1303 SwAnnotationWin* pWin = GetTopReplyNote();
1304 // #i111964#
1305 if ( pWin != this && pWin->Anchor() )
1307 pWin->Anchor()->SetAnchorState(AnchorState::End);
1309 mpAnchor->setLineSolid(true);
1310 if ( mpTextRangeOverlay != nullptr )
1312 mpTextRangeOverlay->ShowSolidBorder();
1315 if (mpShadow)
1316 mpShadow->SetShadowState(SS_EDIT);
1317 break;
1319 case ViewState::VIEW:
1321 if (mpAnchor)
1323 mpAnchor->setLineSolid(true);
1324 if ( mpTextRangeOverlay != nullptr )
1326 mpTextRangeOverlay->ShowSolidBorder();
1329 if (mpShadow)
1330 mpShadow->SetShadowState(SS_VIEW);
1331 break;
1333 case ViewState::NORMAL:
1335 if (mpAnchor)
1337 if (IsFollow())
1339 // if there is no visible parent note, we want to see the complete anchor ??
1340 //if (IsAnyStackParentVisible())
1341 mpAnchor->SetAnchorState(AnchorState::End);
1342 SwAnnotationWin* pTopWinSelf = GetTopReplyNote();
1343 SwAnnotationWin* pTopWinActive = mrMgr.HasActiveSidebarWin()
1344 ? mrMgr.GetActiveSidebarWin()->GetTopReplyNote()
1345 : nullptr;
1346 // #i111964#
1347 if ( ( pTopWinSelf != this ) &&
1348 ( pTopWinSelf != pTopWinActive ) &&
1349 pTopWinSelf->Anchor() )
1351 if ( pTopWinSelf != mrMgr.GetActiveSidebarWin() )
1353 pTopWinSelf->Anchor()->setLineSolid(false);
1354 if ( pTopWinSelf->TextRange() != nullptr )
1356 pTopWinSelf->TextRange()->HideSolidBorder();
1359 pTopWinSelf->Anchor()->SetAnchorState(AnchorState::All);
1362 mpAnchor->setLineSolid(false);
1363 if ( mpTextRangeOverlay != nullptr )
1365 mpTextRangeOverlay->HideSolidBorder();
1368 if ( mpShadow )
1370 mpShadow->SetShadowState(SS_NORMAL);
1372 break;
1377 SwAnnotationWin* SwAnnotationWin::GetTopReplyNote()
1379 for (SwAnnotationWin* pTopNote = this;;)
1381 if (!pTopNote->IsFollow())
1382 return pTopNote;
1383 SwAnnotationWin* pPrev = mrMgr.GetNextPostIt(KEY_PAGEUP, pTopNote);
1384 if (!pPrev)
1385 return pTopNote;
1386 pTopNote = pPrev;
1390 void SwAnnotationWin::SwitchToFieldPos()
1392 if ( mrMgr.GetActiveSidebarWin() == this )
1393 mrMgr.SetActiveSidebarWin(nullptr);
1394 GotoPos();
1395 sal_uInt32 aCount = MoveCaret();
1396 if (aCount)
1397 mrView.GetDocShell()->GetWrtShell()->SwCursorShell::Right(aCount, SwCursorSkipMode::Chars);
1398 GrabFocusToDocument();
1399 collectUIInformation(u"LEAVE"_ustr,get_id());
1402 void SwAnnotationWin::SetChangeTracking( const SwPostItHelper::SwLayoutStatus aLayoutStatus,
1403 const Color& aChangeColor )
1405 if ( (mLayoutStatus != aLayoutStatus) ||
1406 (mChangeColor != aChangeColor) )
1408 mLayoutStatus = aLayoutStatus;
1409 mChangeColor = aChangeColor;
1410 Invalidate();
1414 bool SwAnnotationWin::HasScrollbar() const
1416 return static_cast<bool>(mxVScrollbar);
1419 bool SwAnnotationWin::IsScrollbarVisible() const
1421 return HasScrollbar() && mxVScrollbar->get_vpolicy() == VclPolicyType::ALWAYS;
1424 void SwAnnotationWin::ChangeSidebarItem( SwAnnotationItem & rSidebarItem )
1426 #if !ENABLE_WASM_STRIP_ACCESSIBILITY
1427 const bool bAnchorChanged = mpAnchorFrame != rSidebarItem.maLayoutInfo.mpAnchorFrame;
1428 if (bAnchorChanged && mpAnchorFrame)
1430 mrMgr.DisconnectSidebarWinFromFrame( *mpAnchorFrame, *this );
1432 #endif
1434 mpSidebarItem = &rSidebarItem;
1435 mpAnchorFrame = mpSidebarItem->maLayoutInfo.mpAnchorFrame;
1436 assert(mpAnchorFrame);
1438 #if !ENABLE_WASM_STRIP_ACCESSIBILITY
1439 if (mxSidebarWinAccessible)
1440 mxSidebarWinAccessible->ChangeSidebarItem( *mpSidebarItem );
1442 if ( bAnchorChanged )
1444 mrMgr.ConnectSidebarWinToFrame( *(mpSidebarItem->maLayoutInfo.mpAnchorFrame),
1445 mpSidebarItem->GetFormatField(),
1446 *this );
1448 #endif
1451 css::uno::Reference< css::accessibility::XAccessible > SwAnnotationWin::CreateAccessible()
1453 #if !ENABLE_WASM_STRIP_ACCESSIBILITY
1454 if (!mxSidebarWinAccessible)
1455 mxSidebarWinAccessible = new SidebarWinAccessible( *this,
1456 mrView.GetWrtShell(),
1457 *mpSidebarItem );
1458 #endif
1459 return mxSidebarWinAccessible;
1462 } // eof of namespace sw::sidebarwindows
1464 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */