Version 7.6.3.2-android, tag libreoffice-7.6.3.2-android
[LibreOffice.git] / sw / source / uibase / docvw / AnnotationWin2.cxx
blob3f8a1752e890e85ff6b1afae0287f21810bfb1fc
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>
49 #include <svl/undo.hxx>
50 #include <svl/stritem.hxx>
52 #include <sfx2/viewfrm.hxx>
53 #include <sfx2/bindings.hxx>
54 #include <sfx2/dispatch.hxx>
56 #include <vcl/decoview.hxx>
57 #include <vcl/event.hxx>
58 #include <vcl/gradient.hxx>
59 #include <vcl/pdfextoutdevdata.hxx>
60 #include <vcl/svapp.hxx>
61 #include <vcl/settings.hxx>
62 #include <vcl/ptrstyle.hxx>
63 #include <vcl/uitest/logger.hxx>
64 #include <vcl/uitest/eventdescription.hxx>
66 #include <edtwin.hxx>
67 #include <view.hxx>
68 #include <docsh.hxx>
69 #include <wrtsh.hxx>
70 #include <doc.hxx>
71 #include <docufld.hxx>
72 #include <swmodule.hxx>
74 #include <SwRewriter.hxx>
75 #include <txtannotationfld.hxx>
76 #include <ndtxt.hxx>
78 #include <drawinglayer/processor2d/baseprocessor2d.hxx>
79 #include <drawinglayer/processor2d/processor2dtools.hxx>
80 #include <osl/diagnose.h>
81 #include <unotools/localedatawrapper.hxx>
82 #include <unotools/syslocale.hxx>
83 #include <memory>
84 #include <comphelper/lok.hxx>
86 using namespace sw::sidebarwindows;
88 namespace
91 void collectUIInformation( const OUString& aevent , const OUString& aID )
93 EventDescription aDescription;
94 aDescription.aID = aID;
95 aDescription.aParameters = {{"" , ""}};
96 aDescription.aAction = aevent;
97 aDescription.aParent = "MainWindow";
98 aDescription.aKeyWord = "SwEditWinUIObject";
99 UITestLogger::getInstance().logEvent(aDescription);
104 namespace sw::annotation {
106 #define METABUTTON_WIDTH 16
107 #define METABUTTON_HEIGHT 18
108 #define POSTIT_MINIMUMSIZE_WITHOUT_META 50
110 void SwAnnotationWin::PaintTile(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect)
112 bool bMenuButtonVisible = mxMenuButton->get_visible();
113 // No point in showing this button till click on it are not handled.
114 if (bMenuButtonVisible)
115 mxMenuButton->hide();
117 // draw left over space
118 if (Application::GetSettings().GetStyleSettings().GetHighContrastMode())
119 rRenderContext.SetFillColor(COL_BLACK);
120 else
121 rRenderContext.SetFillColor(mColorDark);
122 rRenderContext.SetLineColor();
123 rRenderContext.DrawRect(rRect);
125 m_xContainer->draw(rRenderContext, rRect.TopLeft(), GetSizePixel());
127 const drawinglayer::geometry::ViewInformation2D aViewInformation;
128 std::unique_ptr<drawinglayer::processor2d::BaseProcessor2D> pProcessor(drawinglayer::processor2d::createProcessor2DFromOutputDevice(rRenderContext, aViewInformation));
130 // drawinglayer sets the map mode to pixels, not needed here.
131 rRenderContext.Pop();
132 // Work in document-global twips.
133 rRenderContext.Pop();
134 if (mpAnchor)
135 pProcessor->process(mpAnchor->getOverlayObjectPrimitive2DSequence());
136 if (mpTextRangeOverlay)
137 pProcessor->process(mpTextRangeOverlay->getOverlayObjectPrimitive2DSequence());
139 rRenderContext.Push(vcl::PushFlags::NONE);
140 pProcessor.reset();
141 rRenderContext.Push(vcl::PushFlags::NONE);
143 if (bMenuButtonVisible)
144 mxMenuButton->show();
147 bool SwAnnotationWin::IsHitWindow(const Point& rPointLogic)
149 tools::Rectangle aRectangleLogic(EditWin().PixelToLogic(GetPosPixel()), EditWin().PixelToLogic(GetSizePixel()));
150 return aRectangleLogic.Contains(rPointLogic);
153 void SwAnnotationWin::SetCursorLogicPosition(const Point& rPosition, bool bPoint, bool bClearMark)
155 mxSidebarTextControl->SetCursorLogicPosition(rPosition, bPoint, bClearMark);
158 void SwAnnotationWin::DrawForPage(OutputDevice* pDev, const Point& rPt)
160 // tdf#143511 unclip SysObj so get_extents_relative_to of children
161 // of the SysObj can provide meaningful results
162 UnclipVisibleSysObj();
164 vcl::PDFExtOutDevData *const pPDFExtOutDevData(
165 dynamic_cast<vcl::PDFExtOutDevData*>(pDev->GetExtOutDevData()));
166 if (pPDFExtOutDevData && pPDFExtOutDevData->GetIsExportTaggedPDF())
168 pPDFExtOutDevData->WrapBeginStructureElement(vcl::PDFWriter::NonStructElement, OUString());
171 pDev->Push();
173 pDev->SetFillColor(mColorDark);
174 pDev->SetLineColor();
176 pDev->SetTextColor(mColorAnchor);
177 vcl::Font aFont = maLabelFont;
178 aFont.SetFontHeight(aFont.GetFontHeight() * 20);
179 pDev->SetFont(aFont);
181 Size aSz = PixelToLogic(GetSizePixel());
183 pDev->DrawRect(tools::Rectangle(rPt, aSz));
185 if (mxMetadataAuthor->get_visible())
187 int x, y, width, height;
188 mxMetadataAuthor->get_extents_relative_to(*m_xContainer, x, y, width, height);
189 Point aPos(rPt + PixelToLogic(Point(x, y)));
190 Size aSize(PixelToLogic(Size(width, height)));
192 pDev->Push(vcl::PushFlags::CLIPREGION);
193 pDev->IntersectClipRegion(tools::Rectangle(aPos, aSize));
194 pDev->DrawText(aPos, mxMetadataAuthor->get_label());
195 pDev->Pop();
198 if (mxMetadataDate->get_visible())
200 int x, y, width, height;
201 mxMetadataDate->get_extents_relative_to(*m_xContainer, x, y, width, height);
202 Point aPos(rPt + PixelToLogic(Point(x, y)));
203 Size aSize(PixelToLogic(Size(width, height)));
205 pDev->Push(vcl::PushFlags::CLIPREGION);
206 pDev->IntersectClipRegion(tools::Rectangle(aPos, aSize));
207 pDev->DrawText(aPos, mxMetadataDate->get_label());
208 pDev->Pop();
211 if (mxMetadataResolved->get_visible())
213 int x, y, width, height;
214 mxMetadataResolved->get_extents_relative_to(*m_xContainer, x, y, width, height);
215 Point aPos(rPt + PixelToLogic(Point(x, y)));
216 Size aSize(PixelToLogic(Size(width, height)));
218 pDev->Push(vcl::PushFlags::CLIPREGION);
219 pDev->IntersectClipRegion(tools::Rectangle(aPos, aSize));
220 pDev->DrawText(aPos, mxMetadataResolved->get_label());
221 pDev->Pop();
224 mxSidebarTextControl->DrawForPage(pDev, rPt);
226 const drawinglayer::geometry::ViewInformation2D aNewViewInfos;
227 std::unique_ptr<drawinglayer::processor2d::BaseProcessor2D> pProcessor(
228 drawinglayer::processor2d::createProcessor2DFromOutputDevice(
229 *pDev, aNewViewInfos ));
231 if (mpAnchor)
232 pProcessor->process(mpAnchor->getOverlayObjectPrimitive2DSequence());
233 if (mpTextRangeOverlay)
234 pProcessor->process(mpTextRangeOverlay->getOverlayObjectPrimitive2DSequence());
235 pProcessor.reset();
237 if (mxVScrollbar->get_vpolicy() != VclPolicyType::NEVER)
239 // if there is a scrollbar shown, draw "..." to indicate the comment isn't
240 // completely shown
241 int x, y, width, height;
242 mxMenuButton->get_extents_relative_to(*m_xContainer, x, y, width, height);
243 Point aPos(rPt + PixelToLogic(Point(x, y)));
244 pDev->DrawText(aPos, "...");
247 pDev->Pop();
249 if (pPDFExtOutDevData && pPDFExtOutDevData->GetIsExportTaggedPDF())
251 pPDFExtOutDevData->EndStructureElement();
255 void SwAnnotationWin::SetPosSizePixelRect(tools::Long nX, tools::Long nY, tools::Long nWidth, tools::Long nHeight,
256 const SwRect& aAnchorRect, const tools::Long aPageBorder)
258 mPosSize = tools::Rectangle(Point(nX,nY),Size(nWidth,nHeight));
259 if (!mAnchorRect.IsEmpty() && mAnchorRect != aAnchorRect)
260 mbAnchorRectChanged = true;
261 mAnchorRect = aAnchorRect;
262 mPageBorder = aPageBorder;
265 void SwAnnotationWin::SetSize( const Size& rNewSize )
267 mPosSize.SetSize(rNewSize);
270 void SwAnnotationWin::SetVirtualPosSize( const Point& aPoint, const Size& aSize)
272 mPosSize = tools::Rectangle(aPoint,aSize);
275 void SwAnnotationWin::TranslateTopPosition(const tools::Long aAmount)
277 mPosSize.Move(0,aAmount);
280 void SwAnnotationWin::ShowAnchorOnly(const Point &aPoint)
282 HideNote();
283 SetPosAndSize();
284 if (mpAnchor)
286 mpAnchor->SetSixthPosition(basegfx::B2DPoint(aPoint.X(),aPoint.Y()));
287 mpAnchor->SetSeventhPosition(basegfx::B2DPoint(aPoint.X(),aPoint.Y()));
288 mpAnchor->SetAnchorState(AnchorState::All);
289 mpAnchor->setVisible(true);
291 if (mpShadow)
292 mpShadow->setVisible(false);
295 SfxItemSet SwAnnotationWin::DefaultItem()
297 SfxItemSet aItem( mrView.GetDocShell()->GetPool() );
298 aItem.Put(SvxFontHeightItem(200,100,EE_CHAR_FONTHEIGHT));
299 return aItem;
302 void SwAnnotationWin::InitControls()
304 // window controls for author and date
305 mxMetadataAuthor = m_xBuilder->weld_label("author");
306 mxMetadataAuthor->set_accessible_name( SwResId( STR_ACCESS_ANNOTATION_AUTHOR_NAME ) );
307 mxMetadataAuthor->set_direction(AllSettings::GetLayoutRTL());
309 maLabelFont = Application::GetSettings().GetStyleSettings().GetLabelFont();
310 maLabelFont.SetFontHeight(8);
312 // we should leave this setting alone, but for this we need a better layout algo
313 // with variable meta size height
314 mxMetadataAuthor->set_font(maLabelFont);
316 mxMetadataDate = m_xBuilder->weld_label("date");
317 mxMetadataDate->set_accessible_name( SwResId( STR_ACCESS_ANNOTATION_DATE_NAME ) );
318 mxMetadataDate->set_direction(AllSettings::GetLayoutRTL());
319 mxMetadataDate->connect_mouse_move(LINK(this, SwAnnotationWin, MouseMoveHdl));
321 // we should leave this setting alone, but for this we need a better layout algo
322 // with variable meta size height
323 mxMetadataDate->set_font(maLabelFont);
325 mxMetadataResolved = m_xBuilder->weld_label("resolved");
326 mxMetadataResolved->set_accessible_name( SwResId( STR_ACCESS_ANNOTATION_RESOLVED_NAME ) );
327 mxMetadataResolved->set_direction(AllSettings::GetLayoutRTL());
328 mxMetadataResolved->connect_mouse_move(LINK(this, SwAnnotationWin, MouseMoveHdl));
330 // we should leave this setting alone, but for this we need a better layout algo
331 // with variable meta size height
332 mxMetadataResolved->set_font(maLabelFont);
333 mxMetadataResolved->set_label(SwResId(STR_ACCESS_ANNOTATION_RESOLVED_NAME));
335 SwDocShell* aShell = mrView.GetDocShell();
336 mpOutliner.reset(new Outliner(&aShell->GetPool(),OutlinerMode::TextObject));
337 aShell->GetDoc()->SetCalcFieldValueHdl( mpOutliner.get() );
338 mpOutliner->SetUpdateLayout( true );
340 mpOutlinerView.reset(new OutlinerView(mpOutliner.get(), nullptr));
341 mpOutliner->InsertView(mpOutlinerView.get());
343 //create Scrollbars
344 mxVScrollbar = m_xBuilder->weld_scrolled_window("scrolledwindow", true);
346 mxMenuButton = m_xBuilder->weld_menu_button("menubutton");
347 mxMenuButton->set_size_request(METABUTTON_WIDTH, METABUTTON_HEIGHT);
349 // actual window which holds the user text
350 mxSidebarTextControl.reset(new SidebarTextControl(*this, mrView, mrMgr));
351 mxSidebarTextControlWin.reset(new weld::CustomWeld(*m_xBuilder, "editview", *mxSidebarTextControl));
352 mxSidebarTextControl->SetPointer(PointerStyle::Text);
354 Rescale();
356 mpOutlinerView->SetBackgroundColor(COL_TRANSPARENT);
357 mpOutlinerView->SetOutputArea( PixelToLogic( tools::Rectangle(0,0,1,1) ) );
359 mpOutlinerView->SetAttribs(DefaultItem());
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;
369 if (SwWrtShell* pWrtShell = mrView.GetWrtShellPtr())
371 const SwViewOption* pVOpt = pWrtShell->GetViewOptions();
372 if (pVOpt->IsFieldShadings())
373 nCntrl |= EEControlBits::MARKFIELDS;
374 else
375 nCntrl &= ~EEControlBits::MARKFIELDS;
376 if (pVOpt->IsOnlineSpell())
377 nCntrl |= EEControlBits::ONLINESPELLING;
378 else
379 nCntrl &= ~EEControlBits::ONLINESPELLING;
381 mpOutliner->SetControlWord(nCntrl);
383 std::size_t aIndex = SW_MOD()->InsertRedlineAuthor(GetAuthor());
384 SetColor( SwPostItMgr::GetColorDark(aIndex),
385 SwPostItMgr::GetColorLight(aIndex),
386 SwPostItMgr::GetColorAnchor(aIndex));
388 CheckMetaText();
390 // expand %1 "Author"
391 OUString aText = mxMenuButton->get_item_label("deleteby");
392 SwRewriter aRewriter;
393 aRewriter.AddRule(UndoArg1, GetAuthor());
394 aText = aRewriter.Apply(aText);
395 mxMenuButton->set_item_label("deleteby", aText);
397 mxMenuButton->set_accessible_name(SwResId(STR_ACCESS_ANNOTATION_BUTTON_NAME));
398 mxMenuButton->set_accessible_description(SwResId(STR_ACCESS_ANNOTATION_BUTTON_DESC));
399 mxMenuButton->set_tooltip_text(SwResId(STR_ACCESS_ANNOTATION_BUTTON_DESC));
401 mxMenuButton->connect_toggled(LINK(this, SwAnnotationWin, ToggleHdl));
402 mxMenuButton->connect_selected(LINK(this, SwAnnotationWin, SelectHdl));
403 mxMenuButton->connect_key_press(LINK(this, SwAnnotationWin, KeyInputHdl));
404 mxMenuButton->connect_mouse_move(LINK(this, SwAnnotationWin, MouseMoveHdl));
406 SetLanguage(GetLanguage());
407 GetOutlinerView()->StartSpeller(mxSidebarTextControl->GetDrawingArea());
408 SetPostItText();
409 mpOutliner->CompleteOnlineSpelling();
411 mxSidebarTextControl->Show();
412 mxMetadataAuthor->show();
413 mxMetadataDate->show();
414 mxMetadataResolved->set_visible(IsResolved());
415 mxVScrollbar->set_vpolicy(VclPolicyType::ALWAYS);
418 void SwAnnotationWin::CheckMetaText()
420 const SvtSysLocale aSysLocale;
421 const LocaleDataWrapper& rLocalData = aSysLocale.GetLocaleData();
422 OUString sMeta = GetAuthor();
423 if (sMeta.isEmpty())
425 sMeta = SwResId(STR_NOAUTHOR);
427 else if (sMeta.getLength() > 23)
429 sMeta = OUString::Concat(sMeta.subView(0, 20)) + "...";
431 if ( mxMetadataAuthor->get_label() != sMeta )
433 mxMetadataAuthor->set_label(sMeta);
436 Date aDate = GetDate();
437 if (aDate.IsValidAndGregorian() )
439 sMeta = rLocalData.getDate(aDate);
441 else
443 sMeta = SwResId(STR_NODATE);
445 if (GetTime().GetTime()!=0)
447 sMeta += " " + rLocalData.getTime( GetTime(),false );
449 if ( mxMetadataDate->get_label() != sMeta )
451 mxMetadataDate->set_label(sMeta);
454 std::size_t aIndex = SW_MOD()->InsertRedlineAuthor(GetAuthor());
455 SetColor( SwPostItMgr::GetColorDark(aIndex),
456 SwPostItMgr::GetColorLight(aIndex),
457 SwPostItMgr::GetColorAnchor(aIndex));
460 static Color ColorFromAlphaColor(const sal_uInt8 aTransparency, const Color& aFront, const Color& aBack)
462 return Color(sal_uInt8(aFront.GetRed() * aTransparency / 255.0 + aBack.GetRed() * (1 - aTransparency / 255.0)),
463 sal_uInt8(aFront.GetGreen() * aTransparency / 255.0 + aBack.GetGreen() * (1 - aTransparency / 255.0)),
464 sal_uInt8(aFront.GetBlue() * aTransparency / 255.0 + aBack.GetBlue() * (1 - aTransparency / 255.0)));
467 void SwAnnotationWin::SetMenuButtonColors()
469 if (!mxMenuButton)
470 return;
472 mxMenuButton->set_background(mColorDark);
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 ColorFromAlphaColor(15, mColorAnchor, mColorDark),
487 ColorFromAlphaColor(80, mColorAnchor, mColorDark));
488 xVirDev->DrawGradient(aRect, aGradient);
490 //draw rect around button
491 xVirDev->SetFillColor();
492 xVirDev->SetLineColor(ColorFromAlphaColor(90, mColorAnchor, 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 // 40% distance to the top button border
501 const tools::Long nBorderDistanceTop = ((aSymbolRect.GetHeight() * 400) + 500) / 1000;
502 aSymbolRect.AdjustTop(nBorderDistanceTop );
503 // 15% distance to the bottom button border
504 const tools::Long nBorderDistanceBottom = ((aSymbolRect.GetHeight() * 150) + 500) / 1000;
505 aSymbolRect.AdjustBottom( -nBorderDistanceBottom );
506 DecorationView aDecoView(xVirDev.get());
507 aDecoView.DrawSymbol(aSymbolRect, SymbolType::SPIN_DOWN, GetTextColor(),
508 DrawSymbolFlags::NONE);
509 mxMenuButton->set_image(xVirDev);
510 mxMenuButton->set_size_request(aSize.Width() + 4, aSize.Height() + 4);
513 void SwAnnotationWin::Rescale()
515 // On Android, this method leads to invoke ImpEditEngine::UpdateViews
516 // which hides the text cursor. Moreover it causes sudden document scroll
517 // when modifying a commented text. Not clear the root cause,
518 // anyway skipping this method fixes the problem, and there should be
519 // no side effect, since the client has disabled annotations rendering.
520 if (comphelper::LibreOfficeKit::isActive() && !comphelper::LibreOfficeKit::isTiledAnnotations())
521 return;
523 MapMode aMode = GetParent()->GetMapMode();
524 aMode.SetOrigin( Point() );
525 SetMapMode( aMode );
526 mxSidebarTextControl->SetMapMode( aMode );
528 SwWrtShell* pWrtShell = mrView.GetWrtShellPtr();
529 if (!pWrtShell)
530 return;
531 const Fraction& rFraction = pWrtShell->GetOut()->GetMapMode().GetScaleY();
533 vcl::Font aFont = maLabelFont;
534 sal_Int32 nHeight = tools::Long(aFont.GetFontHeight() * rFraction);
535 aFont.SetFontHeight( nHeight );
537 if (mxMetadataAuthor)
538 mxMetadataAuthor->set_font(aFont);
539 if (mxMetadataDate)
540 mxMetadataDate->set_font(aFont);
541 if (mxMetadataResolved)
542 mxMetadataResolved->set_font(aFont);
543 SetMenuButtonColors();
544 if (mxVScrollbar)
545 mxVScrollbar->set_scroll_thickness(GetPrefScrollbarWidth());
548 void SwAnnotationWin::SetPosAndSize()
550 bool bChange = false;
552 if (GetSizePixel() != mPosSize.GetSize())
554 bChange = true;
555 SetSizePixel(mPosSize.GetSize());
557 DoResize();
560 if (GetPosPixel().X() != mPosSize.Left() || (std::abs(GetPosPixel().Y() - mPosSize.Top()) > 5) )
562 bChange = true;
563 SetPosPixel(mPosSize.TopLeft());
565 Point aLineStart;
566 Point aLineEnd ;
567 switch ( meSidebarPosition )
569 case sw::sidebarwindows::SidebarPosition::LEFT:
571 aLineStart = EditWin().PixelToLogic( Point(GetPosPixel().X()+GetSizePixel().Width(),GetPosPixel().Y()-1) );
572 aLineEnd = EditWin().PixelToLogic( Point(GetPosPixel().X(),GetPosPixel().Y()-1) );
574 break;
575 case sw::sidebarwindows::SidebarPosition::RIGHT:
577 aLineStart = EditWin().PixelToLogic( Point(GetPosPixel().X(),GetPosPixel().Y()-1) );
578 aLineEnd = EditWin().PixelToLogic( Point(GetPosPixel().X()+GetSizePixel().Width(),GetPosPixel().Y()-1) );
580 break;
581 default:
582 OSL_FAIL( "<SwAnnotationWin::SetPosAndSize()> - unexpected position of sidebar" );
583 break;
586 // LOK has map mode disabled, and we still want to perform pixel ->
587 // twips conversion for the size of the line above the note.
588 if (comphelper::LibreOfficeKit::isActive() && !EditWin().IsMapModeEnabled())
590 EditWin().EnableMapMode();
591 Size aSize(aLineEnd.getX() - aLineStart.getX(), aLineEnd.getY() - aLineStart.getY());
592 aSize = EditWin().PixelToLogic(aSize);
593 aLineEnd = aLineStart;
594 aLineEnd.Move(aSize.getWidth(), aSize.getHeight());
595 EditWin().EnableMapMode(false);
598 if (mpAnchor)
600 mpAnchor->SetAllPosition( basegfx::B2DPoint( mAnchorRect.Left() , mAnchorRect.Bottom() - 5* 15),
601 basegfx::B2DPoint( mAnchorRect.Left()-5*15 , mAnchorRect.Bottom()+5*15),
602 basegfx::B2DPoint( mAnchorRect.Left()+5*15 , mAnchorRect.Bottom()+5*15),
603 basegfx::B2DPoint( mAnchorRect.Left(), mAnchorRect.Bottom()+2*15),
604 basegfx::B2DPoint( mPageBorder ,mAnchorRect.Bottom()+2*15),
605 basegfx::B2DPoint( aLineStart.X(),aLineStart.Y()),
606 basegfx::B2DPoint( aLineEnd.X(),aLineEnd.Y()));
608 else
610 mpAnchor = AnchorOverlayObject::CreateAnchorOverlayObject( mrView,
611 mAnchorRect,
612 mPageBorder,
613 aLineStart,
614 aLineEnd,
615 mColorAnchor );
616 if ( mpAnchor )
618 mpAnchor->setVisible(true);
619 mpAnchor->SetAnchorState(AnchorState::Tri);
620 if (HasChildPathFocus())
622 mpAnchor->setLineSolid(true);
627 else
629 if ( mpAnchor &&
630 ( mpAnchor->getBasePosition() != basegfx::B2DPoint( mAnchorRect.Left() , mAnchorRect.Bottom()-5*15) ) )
632 mpAnchor->SetTriPosition( basegfx::B2DPoint( mAnchorRect.Left() , mAnchorRect.Bottom() - 5* 15),
633 basegfx::B2DPoint( mAnchorRect.Left()-5*15 , mAnchorRect.Bottom()+5*15),
634 basegfx::B2DPoint( mAnchorRect.Left()+5*15 , mAnchorRect.Bottom()+5*15),
635 basegfx::B2DPoint( mAnchorRect.Left(), mAnchorRect.Bottom()+2*15),
636 basegfx::B2DPoint( mPageBorder , mAnchorRect.Bottom()+2*15));
640 if (mpShadow && bChange)
642 Point aStart = EditWin().PixelToLogic(GetPosPixel()+Point(0,GetSizePixel().Height()));
643 Point aEnd = EditWin().PixelToLogic(GetPosPixel()+Point(GetSizePixel().Width()-1,GetSizePixel().Height()));
644 mpShadow->SetPosition(basegfx::B2DPoint(aStart.X(),aStart.Y()), basegfx::B2DPoint(aEnd.X(),aEnd.Y()));
647 if (mrMgr.ShowNotes())
649 if (IsFollow() && !HasChildPathFocus())
651 // #i111964#
652 if ( mpAnchor )
654 mpAnchor->SetAnchorState(AnchorState::End);
657 else
659 // #i111964#
660 if ( mpAnchor )
662 mpAnchor->SetAnchorState(AnchorState::All);
664 SwAnnotationWin* pWin = GetTopReplyNote();
665 // #i111964#
666 if ( pWin != this && pWin->Anchor() )
668 pWin->Anchor()->SetAnchorState(AnchorState::End);
674 // text range overlay
675 maAnnotationTextRanges.clear();
676 if ( mrSidebarItem.maLayoutInfo.mnStartNodeIdx != SwNodeOffset(0)
677 && mrSidebarItem.maLayoutInfo.mnStartContent != -1 )
679 const SwTextAnnotationField* pTextAnnotationField =
680 dynamic_cast< const SwTextAnnotationField* >( mrSidebarItem.GetFormatField().GetTextField() );
681 SwTextNode* pTextNode = pTextAnnotationField ? pTextAnnotationField->GetpTextNode() : nullptr;
682 SwContentNode* pContentNd = nullptr;
683 if (pTextNode)
685 SwNodes& rNds = pTextNode->GetDoc().GetNodes();
686 pContentNd = rNds[mrSidebarItem.maLayoutInfo.mnStartNodeIdx]->GetContentNode();
688 if (pContentNd)
690 SwPosition aStartPos( *pContentNd, mrSidebarItem.maLayoutInfo.mnStartContent );
691 SwShellCursor* pTmpCursor = nullptr;
692 const bool bTableCursorNeeded = pTextNode->FindTableBoxStartNode() != pContentNd->FindTableBoxStartNode();
693 if ( bTableCursorNeeded )
695 SwShellTableCursor* pTableCursor = new SwShellTableCursor( mrView.GetWrtShell(), aStartPos );
696 pTableCursor->SetMark();
697 pTableCursor->GetMark()->Assign( *pTextNode, pTextAnnotationField->GetStart()+1 );
698 pTableCursor->NewTableSelection();
699 pTmpCursor = pTableCursor;
701 else
703 SwShellCursor* pCursor = new SwShellCursor( mrView.GetWrtShell(), aStartPos );
704 pCursor->SetMark();
705 pCursor->GetMark()->Assign(*pTextNode, pTextAnnotationField->GetStart()+1 );
706 pTmpCursor = pCursor;
708 std::unique_ptr<SwShellCursor> pTmpCursorForAnnotationTextRange( pTmpCursor );
710 // For annotation text range rectangles to be calculated correctly,
711 // we need the map mode disabled
712 bool bDisableMapMode = comphelper::LibreOfficeKit::isActive() && EditWin().IsMapModeEnabled();
713 if (bDisableMapMode)
714 EditWin().EnableMapMode(false);
716 if (mrSidebarItem.maLayoutInfo.mPositionFromCommentAnchor)
717 pTmpCursorForAnnotationTextRange->FillRects();
719 if (bDisableMapMode)
720 EditWin().EnableMapMode();
722 SwRects* pRects(pTmpCursorForAnnotationTextRange.get());
723 for(const SwRect & rNextRect : *pRects)
725 const tools::Rectangle aPntRect(rNextRect.SVRect());
726 maAnnotationTextRanges.emplace_back(
727 aPntRect.Left(), aPntRect.Top(),
728 aPntRect.Right() + 1, aPntRect.Bottom() + 1);
733 if (mrMgr.ShowNotes() && !maAnnotationTextRanges.empty())
735 if ( mpTextRangeOverlay != nullptr )
737 mpTextRangeOverlay->setRanges( std::vector(maAnnotationTextRanges) );
738 if ( mpAnchor != nullptr && mpAnchor->getLineSolid() )
740 mpTextRangeOverlay->ShowSolidBorder();
742 else
744 mpTextRangeOverlay->HideSolidBorder();
747 else if (!IsFollow())
749 // This window is not a reply, then draw its range overlay.
750 mpTextRangeOverlay =
751 sw::overlay::OverlayRanges::CreateOverlayRange(
752 mrView,
753 mColorAnchor,
754 std::vector(maAnnotationTextRanges),
755 mpAnchor && mpAnchor->getLineSolid() );
758 else
760 mpTextRangeOverlay.reset();
764 void SwAnnotationWin::DoResize()
766 tools::Long aHeight = GetSizePixel().Height();
767 tools::ULong aWidth = GetSizePixel().Width();
769 aHeight -= GetMetaHeight();
771 mpOutliner->SetPaperSize( PixelToLogic( Size(aWidth, aHeight) ) ) ;
772 tools::Long aTextHeight = LogicToPixel( mpOutliner->CalcTextSize()).Height();
774 mxMetadataAuthor->show();
775 if(IsResolved()) { mxMetadataResolved->show(); }
776 mxMetadataDate->show();
778 if (aTextHeight > aHeight)
780 const int nThickness = mxVScrollbar->get_scroll_thickness();
781 if (nThickness)
783 // we need vertical scrollbars and have to reduce the width
784 aWidth -= nThickness;
785 mpOutliner->SetPaperSize(PixelToLogic(Size(aWidth, aHeight)));
787 mxVScrollbar->set_vpolicy(VclPolicyType::ALWAYS);
789 else
791 mxVScrollbar->set_vpolicy(VclPolicyType::NEVER);
794 tools::Rectangle aOutputArea = PixelToLogic(tools::Rectangle(0, 0, aWidth, aHeight));
795 if (mxVScrollbar->get_vpolicy() == VclPolicyType::NEVER)
797 // if we do not have a scrollbar anymore, we want to see the complete text
798 mpOutlinerView->SetVisArea(aOutputArea);
800 mpOutlinerView->SetOutputArea(aOutputArea);
801 mpOutlinerView->ShowCursor(true, true);
803 // Don't leave an empty area at the bottom if we can move the text down.
804 tools::Long nMaxVisAreaTop = mpOutliner->GetTextHeight() - aOutputArea.GetHeight();
805 if (mpOutlinerView->GetVisArea().Top() > nMaxVisAreaTop)
807 GetOutlinerView()->Scroll(0, mpOutlinerView->GetVisArea().Top() - nMaxVisAreaTop);
810 int nUpper = mpOutliner->GetTextHeight();
811 int nCurrentDocPos = mpOutlinerView->GetVisArea().Top();
812 int nStepIncrement = mpOutliner->GetTextHeight() / 10;
813 int nPageIncrement = PixelToLogic(Size(0,aHeight)).Height() * 8 / 10;
814 int nPageSize = PixelToLogic(Size(0,aHeight)).Height();
816 /* limit the page size to below nUpper because gtk's gtk_scrolled_window_start_deceleration has
817 effectively...
819 lower = gtk_adjustment_get_lower
820 upper = gtk_adjustment_get_upper - gtk_adjustment_get_page_size
822 and requires that upper > lower or the deceleration animation never ends
824 nPageSize = std::min(nPageSize, nUpper);
826 mxVScrollbar->vadjustment_configure(nCurrentDocPos, 0, nUpper,
827 nStepIncrement, nPageIncrement, nPageSize);
830 void SwAnnotationWin::SetSizePixel( const Size& rNewSize )
832 if (comphelper::LibreOfficeKit::isActive())
833 return;
835 InterimItemWindow::SetSizePixel(rNewSize);
837 if (mpShadow)
839 Point aStart = EditWin().PixelToLogic(GetPosPixel()+Point(0,GetSizePixel().Height()));
840 Point aEnd = EditWin().PixelToLogic(GetPosPixel()+Point(GetSizePixel().Width()-1,GetSizePixel().Height()));
841 mpShadow->SetPosition(basegfx::B2DPoint(aStart.X(),aStart.Y()), basegfx::B2DPoint(aEnd.X(),aEnd.Y()));
845 void SwAnnotationWin::SetScrollbar()
847 mxVScrollbar->vadjustment_set_value(mpOutlinerView->GetVisArea().Top());
850 void SwAnnotationWin::ResizeIfNecessary(tools::Long aOldHeight, tools::Long aNewHeight)
852 if (aOldHeight != aNewHeight)
854 //check for lower border or next note
855 tools::Long aBorder = mrMgr.GetNextBorder();
856 if (aBorder != -1)
858 if (aNewHeight > GetMinimumSizeWithoutMeta())
860 tools::Long aNewLowerValue = GetPosPixel().Y() + aNewHeight + GetMetaHeight();
861 if (aNewLowerValue < aBorder)
862 SetSizePixel(Size(GetSizePixel().Width(),aNewHeight+GetMetaHeight()));
863 else
864 SetSizePixel(Size(GetSizePixel().Width(),aBorder - GetPosPixel().Y()));
865 DoResize();
866 Invalidate();
868 else
870 if (GetSizePixel().Height() != GetMinimumSizeWithoutMeta() + GetMetaHeight())
871 SetSizePixel(Size(GetSizePixel().Width(),GetMinimumSizeWithoutMeta() + GetMetaHeight()));
872 DoResize();
873 Invalidate();
876 else
878 DoResize();
879 Invalidate();
882 else
884 SetScrollbar();
888 void SwAnnotationWin::SetColor(Color aColorDark,Color aColorLight, Color aColorAnchor)
890 mColorDark = aColorDark;
891 mColorLight = aColorLight;
892 mColorAnchor = aColorAnchor;
894 if ( Application::GetSettings().GetStyleSettings().GetHighContrastMode() )
895 return;
897 m_xContainer->set_background(mColorDark);
898 SetMenuButtonColors();
900 mxMetadataAuthor->set_font_color(aColorAnchor);
902 mxMetadataDate->set_font_color(aColorAnchor);
904 mxMetadataResolved->set_font_color(aColorAnchor);
906 mxVScrollbar->customize_scrollbars(mColorLight,
907 mColorAnchor,
908 mColorDark);
911 void SwAnnotationWin::SetSidebarPosition(sw::sidebarwindows::SidebarPosition eSidebarPosition)
913 meSidebarPosition = eSidebarPosition;
916 void SwAnnotationWin::SetReadonly(bool bSet)
918 mbReadonly = bSet;
919 GetOutlinerView()->SetReadOnly(bSet);
922 void SwAnnotationWin::SetLanguage(const SvxLanguageItem& rNewItem)
924 IDocumentUndoRedo& rUndoRedo(
925 mrView.GetDocShell()->GetDoc()->GetIDocumentUndoRedo());
926 const bool bDocUndoEnabled = rUndoRedo.DoesUndo();
927 const bool bOutlinerUndoEnabled = mpOutliner->IsUndoEnabled();
928 const bool bOutlinerModified = mpOutliner->IsModified();
929 const bool bDisableAndRestoreUndoMode = !bDocUndoEnabled && bOutlinerUndoEnabled;
931 if (bDisableAndRestoreUndoMode)
933 // doc undo is disabled, but outliner was enabled, turn outliner undo off
934 // for the duration of this function
935 mpOutliner->EnableUndo(false);
938 Link<LinkParamNone*,void> aLink = mpOutliner->GetModifyHdl();
939 mpOutliner->SetModifyHdl( Link<LinkParamNone*,void>() );
940 ESelection aOld = GetOutlinerView()->GetSelection();
942 ESelection aNewSelection( 0, 0, mpOutliner->GetParagraphCount()-1, EE_TEXTPOS_ALL );
943 GetOutlinerView()->SetSelection( aNewSelection );
944 SfxItemSet aEditAttr(GetOutlinerView()->GetAttribs());
945 aEditAttr.Put(rNewItem);
946 GetOutlinerView()->SetAttribs( aEditAttr );
948 if (!mpOutliner->IsUndoEnabled() && !bOutlinerModified)
950 // if undo was disabled (e.g. this is a redo action) and we were
951 // originally 'unmodified' keep it that way
952 mpOutliner->ClearModifyFlag();
955 GetOutlinerView()->SetSelection(aOld);
956 mpOutliner->SetModifyHdl( aLink );
958 EEControlBits nCntrl = mpOutliner->GetControlWord();
959 // turn off
960 nCntrl &= ~EEControlBits::ONLINESPELLING;
961 mpOutliner->SetControlWord(nCntrl);
963 if (SwWrtShell* pWrtShell = mrView.GetWrtShellPtr())
965 const SwViewOption* pVOpt = pWrtShell->GetViewOptions();
966 //turn back on
967 if (pVOpt->IsOnlineSpell())
968 nCntrl |= EEControlBits::ONLINESPELLING;
969 else
970 nCntrl &= ~EEControlBits::ONLINESPELLING;
972 mpOutliner->SetControlWord(nCntrl);
974 mpOutliner->CompleteOnlineSpelling();
976 // restore original mode
977 if (bDisableAndRestoreUndoMode)
978 mpOutliner->EnableUndo(true);
980 Invalidate();
983 void SwAnnotationWin::GetFocus()
985 if (mxSidebarTextControl)
986 mxSidebarTextControl->GrabFocus();
989 void SwAnnotationWin::LoseFocus()
993 void SwAnnotationWin::ShowNote()
995 SetPosAndSize();
996 if (!IsVisible())
997 Window::Show();
998 if (mpShadow && !mpShadow->isVisible())
999 mpShadow->setVisible(true);
1000 if (mpAnchor && !mpAnchor->isVisible())
1001 mpAnchor->setVisible(true);
1002 if (mpTextRangeOverlay && !mpTextRangeOverlay->isVisible())
1003 mpTextRangeOverlay->setVisible(true);
1005 collectUIInformation("SHOW",get_id());
1008 void SwAnnotationWin::HideNote()
1010 if (IsVisible())
1011 Window::Hide();
1012 if (mpAnchor)
1014 if (mrMgr.IsShowAnchor())
1015 mpAnchor->SetAnchorState(AnchorState::Tri);
1016 else
1017 mpAnchor->setVisible(false);
1019 if (mpShadow && mpShadow->isVisible())
1020 mpShadow->setVisible(false);
1021 if (mpTextRangeOverlay && mpTextRangeOverlay->isVisible())
1022 mpTextRangeOverlay->setVisible(false);
1023 collectUIInformation("HIDE",get_id());
1026 void SwAnnotationWin::ActivatePostIt()
1028 mrMgr.AssureStdModeAtShell();
1030 mpOutliner->ClearModifyFlag();
1031 mpOutliner->GetUndoManager().Clear();
1033 CheckMetaText();
1034 SetViewState(ViewState::EDIT);
1036 // prevent autoscroll to the old cursor location
1037 // when cursor out of visible area
1038 GetOutlinerView()->ShowCursor(false);
1040 if (SwWrtShell* pWrtShell = mrView.GetWrtShellPtr())
1041 mpOutlinerView->GetEditView().SetInsertMode(pWrtShell->IsInsMode());
1043 if ( !Application::GetSettings().GetStyleSettings().GetHighContrastMode() )
1044 GetOutlinerView()->SetBackgroundColor(mColorDark);
1046 //tdf#119130 only have the active postit as a dialog control in which pressing
1047 //ctrl+tab cycles between text and button so we don't waste time searching
1048 //thousands of SwAnnotationWins
1049 SetStyle(GetStyle() | WB_DIALOGCONTROL);
1052 void SwAnnotationWin::DeactivatePostIt()
1054 //tdf#119130 only have the active postit as a dialog control in which pressing
1055 //ctrl+tab cycles between text and button so we don't waste time searching
1056 //thousands of SwAnnotationWins
1057 SetStyle(GetStyle() & ~WB_DIALOGCONTROL);
1059 // remove selection, #i87073#
1060 if (GetOutlinerView()->GetEditView().HasSelection())
1062 ESelection aSelection = GetOutlinerView()->GetEditView().GetSelection();
1063 aSelection.nEndPara = aSelection.nStartPara;
1064 aSelection.nEndPos = aSelection.nStartPos;
1065 GetOutlinerView()->GetEditView().SetSelection(aSelection);
1068 mpOutliner->CompleteOnlineSpelling();
1070 SetViewState(ViewState::NORMAL);
1071 // Make sure this view doesn't emit LOK callbacks during the update, as the
1072 // sidebar window's SidebarTextControl doesn't have a valid twip offset
1073 // (map mode origin) during that operation.
1074 bool bTiledPainting = comphelper::LibreOfficeKit::isTiledPainting();
1075 comphelper::LibreOfficeKit::setTiledPainting(true);
1076 // write the visible text back into the SwField
1077 UpdateData();
1078 comphelper::LibreOfficeKit::setTiledPainting(bTiledPainting);
1080 if ( !Application::GetSettings().GetStyleSettings().GetHighContrastMode() )
1081 GetOutlinerView()->SetBackgroundColor(COL_TRANSPARENT);
1083 if (!mnDeleteEventId && !IsReadOnlyOrProtected() && mpOutliner->GetEditEngine().GetText().isEmpty())
1085 mnDeleteEventId = Application::PostUserEvent( LINK( this, SwAnnotationWin, DeleteHdl), nullptr, true );
1089 void SwAnnotationWin::ToggleInsMode()
1091 if (!mrView.GetWrtShell().IsRedlineOn())
1093 //change outliner
1094 mpOutlinerView->GetEditView().SetInsertMode(!mpOutlinerView->GetEditView().IsInsertMode());
1095 //change document
1096 mrView.GetWrtShell().ToggleInsMode();
1097 //update statusbar
1098 SfxBindings &rBnd = mrView.GetViewFrame().GetBindings();
1099 rBnd.Invalidate(SID_ATTR_INSERT);
1100 rBnd.Update(SID_ATTR_INSERT);
1104 void SwAnnotationWin::ExecuteCommand(sal_uInt16 nSlot)
1106 mrMgr.AssureStdModeAtShell();
1108 switch (nSlot)
1110 case FN_POSTIT:
1111 case FN_REPLY:
1113 // if this note is empty, it will be deleted once losing the focus, so no reply, but only a new note
1114 // will be created
1115 if (!mpOutliner->GetEditEngine().GetText().isEmpty())
1117 OutlinerParaObject aPara(GetOutlinerView()->GetEditView().CreateTextObject());
1118 mrMgr.RegisterAnswer(&aPara);
1120 if (mrMgr.HasActiveSidebarWin())
1121 mrMgr.SetActiveSidebarWin(nullptr);
1122 SwitchToFieldPos();
1123 mrView.GetViewFrame().GetDispatcher()->Execute(FN_POSTIT);
1125 if (nSlot == FN_REPLY)
1127 // Get newly created SwPostItField and set its paraIdParent
1128 auto pPostItField = mrMgr.GetLatestPostItField();
1129 pPostItField->SetParentId(GetTopReplyNote()->GetParaId());
1131 break;
1133 case FN_DELETE_COMMENT:
1134 //Delete(); // do not kill the parent of our open popup menu
1135 mnDeleteEventId = Application::PostUserEvent( LINK( this, SwAnnotationWin, DeleteHdl), nullptr, true );
1136 break;
1137 case FN_DELETE_COMMENT_THREAD:
1138 DeleteThread();
1139 break;
1140 case FN_RESOLVE_NOTE:
1141 ToggleResolved();
1142 DoResize();
1143 Invalidate();
1144 mrMgr.LayoutPostIts();
1145 break;
1146 case FN_RESOLVE_NOTE_THREAD:
1147 GetTopReplyNote()->SetResolved(!IsThreadResolved());
1148 mrMgr.UpdateResolvedStatus(GetTopReplyNote());
1149 DoResize();
1150 Invalidate();
1151 mrMgr.LayoutPostIts();
1152 break;
1153 case FN_FORMAT_ALL_NOTES:
1154 case FN_DELETE_ALL_NOTES:
1155 case FN_HIDE_ALL_NOTES:
1156 // not possible as slot as this would require that "this" is the active postit
1157 mrView.GetViewFrame().GetBindings().Execute( nSlot, nullptr, SfxCallMode::ASYNCHRON );
1158 break;
1159 case FN_DELETE_NOTE_AUTHOR:
1160 case FN_HIDE_NOTE_AUTHOR:
1162 // not possible as slot as this would require that "this" is the active postit
1163 SfxStringItem aItem( nSlot, GetAuthor() );
1164 const SfxPoolItem* aItems[2];
1165 aItems[0] = &aItem;
1166 aItems[1] = nullptr;
1167 mrView.GetViewFrame().GetBindings().Execute( nSlot, aItems, SfxCallMode::ASYNCHRON );
1169 break;
1170 default:
1171 mrView.GetViewFrame().GetBindings().Execute( nSlot );
1172 break;
1176 SwEditWin& SwAnnotationWin::EditWin()
1178 return mrView.GetEditWin();
1181 tools::Long SwAnnotationWin::GetPostItTextHeight()
1183 return mpOutliner ? LogicToPixel(mpOutliner->CalcTextSize()).Height() : 0;
1186 void SwAnnotationWin::SwitchToPostIt(sal_uInt16 aDirection)
1188 SwAnnotationWin* pPostIt = mrMgr.GetNextPostIt(aDirection, this);
1189 if (pPostIt)
1190 pPostIt->GrabFocus();
1193 IMPL_LINK(SwAnnotationWin, MouseMoveHdl, const MouseEvent&, rMEvt, bool)
1195 if (rMEvt.IsEnterWindow())
1197 mbMouseOver = true;
1198 if ( !HasFocus() )
1200 SetViewState(ViewState::VIEW);
1201 Invalidate();
1204 else if (rMEvt.IsLeaveWindow())
1206 mbMouseOver = false;
1207 if ( !HasFocus() )
1209 SetViewState(ViewState::NORMAL);
1210 Invalidate();
1213 return false;
1216 bool SwAnnotationWin::SetActiveSidebarWin()
1218 if (mrMgr.GetActiveSidebarWin() == this)
1219 return false;
1220 mrView.GetWrtShell().LockView( true );
1221 mrMgr.SetActiveSidebarWin(this);
1222 mrView.GetWrtShell().LockView( true );
1224 return true;
1227 void SwAnnotationWin::UnsetActiveSidebarWin()
1229 if (mrMgr.GetActiveSidebarWin() != this)
1230 return;
1231 mrView.GetWrtShell().LockView( true );
1232 mrMgr.SetActiveSidebarWin(nullptr);
1233 mrView.GetWrtShell().LockView( false );
1236 void SwAnnotationWin::LockView(bool bLock)
1238 mrView.GetWrtShell().LockView( bLock );
1241 IMPL_LINK(SwAnnotationWin, ScrollHdl, weld::ScrolledWindow&, rScrolledWindow, void)
1243 tools::Long nDiff = GetOutlinerView()->GetEditView().GetVisArea().Top() - rScrolledWindow.vadjustment_get_value();
1244 GetOutlinerView()->Scroll( 0, nDiff );
1247 IMPL_LINK_NOARG(SwAnnotationWin, ModifyHdl, LinkParamNone*, void)
1249 mrView.GetDocShell()->SetModified();
1252 IMPL_LINK_NOARG(SwAnnotationWin, DeleteHdl, void*, void)
1254 mnDeleteEventId = nullptr;
1255 Delete();
1258 void SwAnnotationWin::ResetAttributes()
1260 mpOutlinerView->RemoveAttribsKeepLanguages(true);
1261 mpOutliner->RemoveFields();
1262 mpOutlinerView->SetAttribs(DefaultItem());
1265 int SwAnnotationWin::GetPrefScrollbarWidth() const
1267 if (SwWrtShell* pWrtShell = mrView.GetWrtShellPtr())
1269 const Fraction& f(pWrtShell->GetOut()->GetMapMode().GetScaleY());
1270 return tools::Long(Application::GetSettings().GetStyleSettings().GetScrollBarSize() * f);
1272 else
1273 return tools::Long(Application::GetSettings().GetStyleSettings().GetScrollBarSize());
1276 sal_Int32 SwAnnotationWin::GetMetaHeight() const
1278 const int fields = GetNumFields();
1280 sal_Int32 nRequiredHeight = 0;
1281 weld::Label* aLabels[3] = { mxMetadataAuthor.get(), mxMetadataDate.get(), mxMetadataResolved.get() };
1282 for (int i = 0; i < fields; ++i)
1283 nRequiredHeight += aLabels[i]->get_preferred_size().Height();
1285 return nRequiredHeight;
1288 sal_Int32 SwAnnotationWin::GetNumFields() const
1290 return IsResolved() ? 3 : 2;
1293 sal_Int32 SwAnnotationWin::GetMinimumSizeWithMeta() const
1295 return mrMgr.GetMinimumSizeWithMeta();
1298 sal_Int32 SwAnnotationWin::GetMinimumSizeWithoutMeta() const
1300 if (SwWrtShell* pWrtShell = mrView.GetWrtShellPtr())
1302 const Fraction& f(pWrtShell->GetOut()->GetMapMode().GetScaleY());
1303 return tools::Long(POSTIT_MINIMUMSIZE_WITHOUT_META * f);
1305 else
1306 return tools::Long(POSTIT_MINIMUMSIZE_WITHOUT_META);
1309 void SwAnnotationWin::SetSpellChecking()
1311 if (SwWrtShell* pWrtShell = mrView.GetWrtShellPtr())
1313 const SwViewOption* pVOpt = pWrtShell->GetViewOptions();
1314 EEControlBits nCntrl = mpOutliner->GetControlWord();
1315 if (pVOpt->IsOnlineSpell())
1316 nCntrl |= EEControlBits::ONLINESPELLING;
1317 else
1318 nCntrl &= ~EEControlBits::ONLINESPELLING;
1319 mpOutliner->SetControlWord(nCntrl);
1321 mpOutliner->CompleteOnlineSpelling();
1322 Invalidate();
1326 void SwAnnotationWin::SetViewState(ViewState bViewState)
1328 switch (bViewState)
1330 case ViewState::EDIT:
1332 if (mpAnchor)
1334 mpAnchor->SetAnchorState(AnchorState::All);
1335 SwAnnotationWin* pWin = GetTopReplyNote();
1336 // #i111964#
1337 if ( pWin != this && pWin->Anchor() )
1339 pWin->Anchor()->SetAnchorState(AnchorState::End);
1341 mpAnchor->setLineSolid(true);
1342 if ( mpTextRangeOverlay != nullptr )
1344 mpTextRangeOverlay->ShowSolidBorder();
1347 if (mpShadow)
1348 mpShadow->SetShadowState(SS_EDIT);
1349 break;
1351 case ViewState::VIEW:
1353 if (mpAnchor)
1355 mpAnchor->setLineSolid(true);
1356 if ( mpTextRangeOverlay != nullptr )
1358 mpTextRangeOverlay->ShowSolidBorder();
1361 if (mpShadow)
1362 mpShadow->SetShadowState(SS_VIEW);
1363 break;
1365 case ViewState::NORMAL:
1367 if (mpAnchor)
1369 if (IsFollow())
1371 // if there is no visible parent note, we want to see the complete anchor ??
1372 //if (IsAnyStackParentVisible())
1373 mpAnchor->SetAnchorState(AnchorState::End);
1374 SwAnnotationWin* pTopWinSelf = GetTopReplyNote();
1375 SwAnnotationWin* pTopWinActive = mrMgr.HasActiveSidebarWin()
1376 ? mrMgr.GetActiveSidebarWin()->GetTopReplyNote()
1377 : nullptr;
1378 // #i111964#
1379 if ( ( pTopWinSelf != this ) &&
1380 ( pTopWinSelf != pTopWinActive ) &&
1381 pTopWinSelf->Anchor() )
1383 if ( pTopWinSelf != mrMgr.GetActiveSidebarWin() )
1385 pTopWinSelf->Anchor()->setLineSolid(false);
1386 if ( pTopWinSelf->TextRange() != nullptr )
1388 pTopWinSelf->TextRange()->HideSolidBorder();
1391 pTopWinSelf->Anchor()->SetAnchorState(AnchorState::All);
1394 mpAnchor->setLineSolid(false);
1395 if ( mpTextRangeOverlay != nullptr )
1397 mpTextRangeOverlay->HideSolidBorder();
1400 if ( mpShadow )
1402 mpShadow->SetShadowState(SS_NORMAL);
1404 break;
1409 SwAnnotationWin* SwAnnotationWin::GetTopReplyNote()
1411 SwAnnotationWin* pTopNote = this;
1412 SwAnnotationWin* pSidebarWin = IsFollow() ? mrMgr.GetNextPostIt(KEY_PAGEUP, this) : nullptr;
1413 while (pSidebarWin)
1415 pTopNote = pSidebarWin;
1416 pSidebarWin = pSidebarWin->IsFollow() ? mrMgr.GetNextPostIt(KEY_PAGEUP, pSidebarWin) : nullptr;
1418 return pTopNote;
1421 void SwAnnotationWin::SwitchToFieldPos()
1423 if ( mrMgr.GetActiveSidebarWin() == this )
1424 mrMgr.SetActiveSidebarWin(nullptr);
1425 GotoPos();
1426 sal_uInt32 aCount = MoveCaret();
1427 if (aCount)
1428 mrView.GetDocShell()->GetWrtShell()->SwCursorShell::Right(aCount, SwCursorSkipMode::Chars);
1429 GrabFocusToDocument();
1430 collectUIInformation("LEAVE",get_id());
1433 void SwAnnotationWin::SetChangeTracking( const SwPostItHelper::SwLayoutStatus aLayoutStatus,
1434 const Color& aChangeColor )
1436 if ( (mLayoutStatus != aLayoutStatus) ||
1437 (mChangeColor != aChangeColor) )
1439 mLayoutStatus = aLayoutStatus;
1440 mChangeColor = aChangeColor;
1441 Invalidate();
1445 bool SwAnnotationWin::HasScrollbar() const
1447 return static_cast<bool>(mxVScrollbar);
1450 bool SwAnnotationWin::IsScrollbarVisible() const
1452 return HasScrollbar() && mxVScrollbar->get_vpolicy() == VclPolicyType::ALWAYS;
1455 void SwAnnotationWin::ChangeSidebarItem( SwSidebarItem const & rSidebarItem )
1457 #if !ENABLE_WASM_STRIP_ACCESSIBILITY
1458 const bool bAnchorChanged = mpAnchorFrame != rSidebarItem.maLayoutInfo.mpAnchorFrame;
1459 if ( bAnchorChanged )
1461 mrMgr.DisconnectSidebarWinFromFrame( *mpAnchorFrame, *this );
1463 #endif
1465 mrSidebarItem = rSidebarItem;
1466 mpAnchorFrame = mrSidebarItem.maLayoutInfo.mpAnchorFrame;
1468 #if !ENABLE_WASM_STRIP_ACCESSIBILITY
1469 if (mxSidebarWinAccessible)
1470 mxSidebarWinAccessible->ChangeSidebarItem( mrSidebarItem );
1472 if ( bAnchorChanged )
1474 mrMgr.ConnectSidebarWinToFrame( *(mrSidebarItem.maLayoutInfo.mpAnchorFrame),
1475 mrSidebarItem.GetFormatField(),
1476 *this );
1478 #endif
1481 css::uno::Reference< css::accessibility::XAccessible > SwAnnotationWin::CreateAccessible()
1483 #if !ENABLE_WASM_STRIP_ACCESSIBILITY
1484 // This is rather dodgy code. Normally in CreateAccessible, if we want a custom
1485 // object, we return a custom object, but we do no override the default toolkit
1486 // window peer.
1487 if (!mxSidebarWinAccessible)
1488 mxSidebarWinAccessible = new SidebarWinAccessible( *this,
1489 mrView.GetWrtShell(),
1490 mrSidebarItem );
1491 #endif
1492 return mxSidebarWinAccessible;
1495 } // eof of namespace sw::sidebarwindows
1497 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */