LibreOffice Module sw (master)  1
AnnotationWin2.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 <sal/config.h>
21 
22 #include <cstddef>
23 #include <cstdlib>
24 
25 #include "SidebarWinAcc.hxx"
26 #include <PostItMgr.hxx>
27 #include <AnnotationWin.hxx>
29 #include "SidebarTxtControl.hxx"
30 #include "SidebarScrollBar.hxx"
31 #include "AnchorOverlayObject.hxx"
32 #include "ShadowOverlayObject.hxx"
33 #include "OverlayRanges.hxx"
34 
35 #include <strings.hrc>
36 #include <app.hrc>
37 
38 #include <viewopt.hxx>
39 #include <cmdid.h>
40 
41 #include <editeng/editobj.hxx>
42 #include <editeng/fontitem.hxx>
43 #include <editeng/fhgtitem.hxx>
44 #include <editeng/langitem.hxx>
45 #include <editeng/editview.hxx>
46 #include <editeng/outliner.hxx>
47 #include <editeng/editeng.hxx>
48 #include <editeng/eeitem.hxx>
49 #include <editeng/outlobj.hxx>
50 
51 #include <svl/zforlist.hxx>
52 #include <svl/undo.hxx>
53 #include <svl/stritem.hxx>
54 
55 #include <svx/svxids.hrc>
56 
57 #include <sfx2/viewfrm.hxx>
58 #include <sfx2/bindings.hxx>
59 #include <sfx2/dispatch.hxx>
60 
61 #include <vcl/edit.hxx>
62 #include <vcl/event.hxx>
63 #include <vcl/scrbar.hxx>
64 #include <vcl/svapp.hxx>
65 #include <vcl/menubtn.hxx>
66 #include <vcl/settings.hxx>
67 #include <vcl/ptrstyle.hxx>
68 
69 #include <edtwin.hxx>
70 #include <view.hxx>
71 #include <docsh.hxx>
72 #include <wrtsh.hxx>
73 #include <doc.hxx>
74 #include <swmodule.hxx>
75 #include <langhelper.hxx>
76 
77 #include <txtannotationfld.hxx>
78 #include <ndtxt.hxx>
79 
80 #include <sw_primitivetypes2d.hxx>
88 #include <memory>
89 #include <comphelper/lok.hxx>
91 #include <drawdoc.hxx>
92 
93 using namespace sw::sidebarwindows;
94 
95 namespace
96 {
97 
99 void lcl_translateTwips(vcl::Window const & rParent, vcl::Window& rChild, MouseEvent* pMouseEvent)
100 {
101  // Set map mode, so that callback payloads will contain absolute coordinates instead of relative ones.
102  Point aOffset(rChild.GetOutOffXPixel() - rParent.GetOutOffXPixel(), rChild.GetOutOffYPixel() - rParent.GetOutOffYPixel());
103  if (!rChild.IsMapModeEnabled())
104  {
105  MapMode aMapMode(rChild.GetMapMode());
106  aMapMode.SetMapUnit(MapUnit::MapTwip);
107  aMapMode.SetScaleX(rParent.GetMapMode().GetScaleX());
108  aMapMode.SetScaleY(rParent.GetMapMode().GetScaleY());
109  rChild.SetMapMode(aMapMode);
110  rChild.EnableMapMode();
111  }
112  aOffset = rChild.PixelToLogic(aOffset);
113  MapMode aMapMode(rChild.GetMapMode());
114  aMapMode.SetOrigin(aOffset);
115  aMapMode.SetMapUnit(rParent.GetMapMode().GetMapUnit());
116  rChild.SetMapMode(aMapMode);
117  rChild.EnableMapMode(false);
118 
119  if (pMouseEvent)
120  {
121  // Set event coordinates, so they contain relative coordinates instead of absolute ones.
122  Point aPos = pMouseEvent->GetPosPixel();
123  aPos.Move(-aOffset.getX(), -aOffset.getY());
124  MouseEvent aMouseEvent(aPos, pMouseEvent->GetClicks(), pMouseEvent->GetMode(), pMouseEvent->GetButtons(), pMouseEvent->GetModifier());
125  *pMouseEvent = aMouseEvent;
126  }
127 }
128 
130 vcl::Window* lcl_getHitWindow(sw::annotation::SwAnnotationWin& rParent, const MouseEvent& rMouseEvent)
131 {
132  vcl::Window* pRet = nullptr;
133 
134  rParent.EditWin().Push(PushFlags::MAPMODE);
135  rParent.EditWin().EnableMapMode();
136  for (sal_Int16 i = rParent.GetChildCount() - 1; i >= 0; --i)
137  {
138  vcl::Window* pChild = rParent.GetChild(i);
139 
140  Point aPosition(rParent.GetPosPixel());
141  aPosition.Move(pChild->GetPosPixel().getX(), pChild->GetPosPixel().getY());
142  Size aSize(rParent.GetSizePixel());
143  tools::Rectangle aRectangleLogic(rParent.EditWin().PixelToLogic(aPosition), rParent.EditWin().PixelToLogic(aSize));
144  if (aRectangleLogic.IsInside(rMouseEvent.GetPosPixel()))
145  {
146  pRet = pChild;
147  break;
148  }
149  }
150  rParent.EditWin().Pop();
151  return pRet;
152 }
153 
154 }
155 
156 namespace sw { namespace annotation {
157 
158 #define METABUTTON_WIDTH 16
159 #define METABUTTON_HEIGHT 18
160 #define METABUTTON_AREA_WIDTH 30
161 #define POSTIT_META_HEIGHT sal_Int32(30)
162 #define POSTIT_MINIMUMSIZE_WITHOUT_META 50
163 
164 
165 void SwAnnotationWin::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect)
166 {
167  Window::Paint(rRenderContext, rRect);
168 
169  if (mpMetadataAuthor->IsVisible())
170  {
171  //draw left over space
173  {
174  rRenderContext.SetFillColor(COL_BLACK);
175  }
176  else
177  {
178  rRenderContext.SetFillColor(mColorDark);
179  }
180 
181  rRenderContext.SetLineColor();
182  tools::Rectangle aRectangle(Point(mpMetadataAuthor->GetPosPixel().X() + mpMetadataAuthor->GetSizePixel().Width(),
183  mpMetadataAuthor->GetPosPixel().Y()),
184  Size(GetMetaButtonAreaWidth(),
185  mpMetadataAuthor->GetSizePixel().Height() + mpMetadataDate->GetSizePixel().Height()));
186 
188  aRectangle = rRect;
189  else
190  aRectangle = PixelToLogic(aRectangle);
191  rRenderContext.DrawRect(aRectangle);
192  }
193 }
194 
195 void SwAnnotationWin::PaintTile(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect)
196 {
197  Paint(rRenderContext, rRect);
198 
199  for (sal_uInt16 i = 0; i < GetChildCount(); ++i)
200  {
201  vcl::Window* pChild = GetChild(i);
202 
203  // No point in showing this button till click on it are not handled.
204  if (pChild == mpMenuButton.get())
205  continue;
206 
207  if (!pChild->IsVisible())
208  continue;
209 
210  rRenderContext.Push(PushFlags::MAPMODE);
211  Point aOffset(PixelToLogic(pChild->GetPosPixel()));
212  MapMode aMapMode(rRenderContext.GetMapMode());
213  aMapMode.SetOrigin(aMapMode.GetOrigin() + aOffset);
214  rRenderContext.SetMapMode(aMapMode);
215 
216  bool bPopChild = false;
217  if (pChild->GetMapMode().GetMapUnit() != rRenderContext.GetMapMode().GetMapUnit())
218  {
219  // This is needed for the scrollbar that has its map unit in pixels.
220  pChild->Push(PushFlags::MAPMODE);
221  bPopChild = true;
222  pChild->EnableMapMode();
223  aMapMode = pChild->GetMapMode();
224  aMapMode.SetMapUnit(rRenderContext.GetMapMode().GetMapUnit());
225  aMapMode.SetScaleX(rRenderContext.GetMapMode().GetScaleX());
226  aMapMode.SetScaleY(rRenderContext.GetMapMode().GetScaleY());
227  pChild->SetMapMode(aMapMode);
228  }
229 
230  pChild->Paint(rRenderContext, rRect);
231 
232  if (bPopChild)
233  pChild->Pop();
234  rRenderContext.Pop();
235  }
236 
237  const drawinglayer::geometry::ViewInformation2D aViewInformation;
238  std::unique_ptr<drawinglayer::processor2d::BaseProcessor2D> pProcessor(drawinglayer::processor2d::createBaseProcessor2DFromOutputDevice(rRenderContext, aViewInformation));
239 
240  // drawinglayer sets the map mode to pixels, not needed here.
241  rRenderContext.Pop();
242  // Work in document-global twips.
243  rRenderContext.Pop();
244  if (mpAnchor)
245  pProcessor->process(mpAnchor->getOverlayObjectPrimitive2DSequence());
246  if (mpTextRangeOverlay)
247  pProcessor->process(mpTextRangeOverlay->getOverlayObjectPrimitive2DSequence());
248 
249  rRenderContext.Push(PushFlags::NONE);
250  pProcessor.reset();
251  rRenderContext.Push(PushFlags::NONE);
252 }
253 
254 bool SwAnnotationWin::IsHitWindow(const Point& rPointLogic)
255 {
256  tools::Rectangle aRectangleLogic(EditWin().PixelToLogic(GetPosPixel()), EditWin().PixelToLogic(GetSizePixel()));
257  return aRectangleLogic.IsInside(rPointLogic);
258 }
259 
260 void SwAnnotationWin::SetCursorLogicPosition(const Point& rPosition, bool bPoint, bool bClearMark)
261 {
262  mpSidebarTextControl->Push(PushFlags::MAPMODE);
263  MouseEvent aMouseEvent(rPosition);
264  lcl_translateTwips(EditWin(), *mpSidebarTextControl, &aMouseEvent);
265  Point aPosition(aMouseEvent.GetPosPixel());
266 
267  EditView& rEditView = GetOutlinerView()->GetEditView();
268  rEditView.SetCursorLogicPosition(aPosition, bPoint, bClearMark);
269 
270  mpSidebarTextControl->Pop();
271 }
272 
273 void SwAnnotationWin::Draw(OutputDevice* pDev, const Point& rPt, const Size& rSz, DrawFlags nInFlags)
274 {
275  if (mpMetadataAuthor->IsVisible() )
276  {
277  pDev->SetFillColor(mColorDark);
278  pDev->SetLineColor();
279  pDev->DrawRect( tools::Rectangle( rPt, rSz ) );
280  }
281 
282  if (mpMetadataAuthor->IsVisible())
283  {
284  vcl::Font aOrigFont(mpMetadataAuthor->GetControlFont());
285  Size aSize(PixelToLogic(mpMetadataAuthor->GetSizePixel()));
286  Point aPos(PixelToLogic(mpMetadataAuthor->GetPosPixel()));
287  aPos += rPt;
288  vcl::Font aFont( mpMetadataAuthor->GetSettings().GetStyleSettings().GetFieldFont() );
289  mpMetadataAuthor->SetControlFont( aFont );
290  mpMetadataAuthor->Draw(pDev, aPos, aSize, nInFlags);
291  mpMetadataAuthor->SetControlFont( aOrigFont );
292  }
293 
294  if (mpMetadataDate->IsVisible())
295  {
296  vcl::Font aOrigFont(mpMetadataDate->GetControlFont());
297  Size aSize(PixelToLogic(mpMetadataDate->GetSizePixel()));
298  Point aPos(PixelToLogic(mpMetadataDate->GetPosPixel()));
299  aPos += rPt;
300  vcl::Font aFont( mpMetadataDate->GetSettings().GetStyleSettings().GetFieldFont() );
301  mpMetadataDate->SetControlFont( aFont );
302  mpMetadataDate->Draw(pDev, aPos, aSize, nInFlags);
303  mpMetadataDate->SetControlFont( aOrigFont );
304  }
305 
306  mpSidebarTextControl->Draw(pDev, rPt, rSz, nInFlags);
307 
308  const drawinglayer::geometry::ViewInformation2D aNewViewInfos;
309  std::unique_ptr<drawinglayer::processor2d::BaseProcessor2D> pProcessor(
311  *pDev, aNewViewInfos ));
312 
313  if (mpAnchor)
314  pProcessor->process(mpAnchor->getOverlayObjectPrimitive2DSequence());
315  if (mpTextRangeOverlay)
316  pProcessor->process(mpTextRangeOverlay->getOverlayObjectPrimitive2DSequence());
317  pProcessor.reset();
318 
319  if (!mpVScrollbar->IsVisible())
320  return;
321 
322  vcl::Font aOrigFont(mpMetadataDate->GetControlFont());
323  Color aOrigBg( mpMetadataDate->GetControlBackground() );
324  OUString sOrigText(mpMetadataDate->GetText());
325 
326  Size aSize(PixelToLogic(mpMenuButton->GetSizePixel()));
327  Point aPos(PixelToLogic(mpMenuButton->GetPosPixel()));
328  aPos += rPt;
329 
330  vcl::Font aFont( mpMetadataDate->GetSettings().GetStyleSettings().GetFieldFont() );
331  mpMetadataDate->SetControlFont( aFont );
332  mpMetadataDate->SetControlBackground( Color(0xFFFFFF) );
333  mpMetadataDate->SetText("...");
334  mpMetadataDate->Draw(pDev, aPos, aSize, nInFlags);
335 
336  mpMetadataDate->SetText(sOrigText);
337  mpMetadataDate->SetControlFont( aOrigFont );
338  mpMetadataDate->SetControlBackground( aOrigBg );
339 
340 }
341 
342 void SwAnnotationWin::KeyInput(const KeyEvent& rKeyEvent)
343 {
344  if (mpSidebarTextControl)
345  {
346  mpSidebarTextControl->Push(PushFlags::MAPMODE);
347  lcl_translateTwips(EditWin(), *mpSidebarTextControl, nullptr);
348 
349  mpSidebarTextControl->KeyInput(rKeyEvent);
350 
351  mpSidebarTextControl->Pop();
352  }
353 }
354 
355 void SwAnnotationWin::MouseMove(const MouseEvent& rMouseEvent)
356 {
357  if (vcl::Window* pHit = lcl_getHitWindow(*this, rMouseEvent))
358  {
359  pHit->Push(PushFlags::MAPMODE);
360  MouseEvent aMouseEvent(rMouseEvent);
361  lcl_translateTwips(EditWin(), *pHit, &aMouseEvent);
362 
363  pHit->MouseMove(aMouseEvent);
364 
365  pHit->Pop();
366  }
367 }
368 
369 void SwAnnotationWin::MouseButtonDown(const MouseEvent& rMouseEvent)
370 {
371  if (vcl::Window* pHit = lcl_getHitWindow(*this, rMouseEvent))
372  {
373  pHit->Push(PushFlags::MAPMODE);
374  MouseEvent aMouseEvent(rMouseEvent);
375  lcl_translateTwips(EditWin(), *pHit, &aMouseEvent);
376 
377  pHit->MouseButtonDown(aMouseEvent);
378 
379  pHit->Pop();
380  }
381 }
382 
383 void SwAnnotationWin::MouseButtonUp(const MouseEvent& rMouseEvent)
384 {
385  if (vcl::Window* pHit = lcl_getHitWindow(*this, rMouseEvent))
386  {
387  pHit->Push(PushFlags::MAPMODE);
388  MouseEvent aMouseEvent(rMouseEvent);
389  lcl_translateTwips(EditWin(), *pHit, &aMouseEvent);
390 
391  pHit->MouseButtonUp(aMouseEvent);
392 
393  pHit->Pop();
394  }
395 }
396 
397 void SwAnnotationWin::SetPosSizePixelRect(long nX, long nY, long nWidth, long nHeight,
398  const SwRect& aAnchorRect, const long aPageBorder)
399 {
400  mPosSize = tools::Rectangle(Point(nX,nY),Size(nWidth,nHeight));
401  if (!mAnchorRect.IsEmpty() && mAnchorRect != aAnchorRect)
402  mbAnchorRectChanged = true;
403  mAnchorRect = aAnchorRect;
404  mPageBorder = aPageBorder;
405 }
406 
407 void SwAnnotationWin::SetSize( const Size& rNewSize )
408 {
409  mPosSize.SetSize(rNewSize);
410 }
411 
412 void SwAnnotationWin::SetVirtualPosSize( const Point& aPoint, const Size& aSize)
413 {
414  mPosSize = tools::Rectangle(aPoint,aSize);
415 }
416 
417 void SwAnnotationWin::TranslateTopPosition(const long aAmount)
418 {
419  mPosSize.Move(0,aAmount);
420 }
421 
422 void SwAnnotationWin::ShowAnchorOnly(const Point &aPoint)
423 {
424  HideNote();
425  SetPosAndSize();
426  if (mpAnchor)
427  {
428  mpAnchor->SetSixthPosition(basegfx::B2DPoint(aPoint.X(),aPoint.Y()));
429  mpAnchor->SetSeventhPosition(basegfx::B2DPoint(aPoint.X(),aPoint.Y()));
430  mpAnchor->SetAnchorState(AnchorState::All);
431  mpAnchor->setVisible(true);
432  }
433  if (mpShadow)
434  mpShadow->setVisible(false);
435 }
436 
437 SfxItemSet SwAnnotationWin::DefaultItem()
438 {
439  SfxItemSet aItem( mrView.GetDocShell()->GetPool() );
440  aItem.Put(SvxFontHeightItem(200,100,EE_CHAR_FONTHEIGHT));
441  return aItem;
442 }
443 
444 void SwAnnotationWin::InitControls()
445 {
446  AddEventListener( LINK( this, SwAnnotationWin, WindowEventListener ) );
447 
448  // actual window which holds the user text
449  mpSidebarTextControl = VclPtr<SidebarTextControl>::Create( *this,
451  mrView, mrMgr );
452  mpSidebarTextControl->SetPointer(PointerStyle::Text);
453 
454  // window controls for author and date
455  mpMetadataAuthor = VclPtr<Edit>::Create( this, 0 );
456  mpMetadataAuthor->SetAccessibleName( SwResId( STR_ACCESS_ANNOTATION_AUTHOR_NAME ) );
457  mpMetadataAuthor->EnableRTL(AllSettings::GetLayoutRTL());
458  mpMetadataAuthor->SetReadOnly();
459  mpMetadataAuthor->AlwaysDisableInput(true);
460  mpMetadataAuthor->SetCallHandlersOnInputDisabled(true);
461  mpMetadataAuthor->AddEventListener( LINK( this, SwAnnotationWin, WindowEventListener ) );
462  // we should leave this setting alone, but for this we need a better layout algo
463  // with variable meta size height
464  {
465  AllSettings aSettings = mpMetadataAuthor->GetSettings();
466  StyleSettings aStyleSettings = aSettings.GetStyleSettings();
467  vcl::Font aFont = aStyleSettings.GetFieldFont();
468  aFont.SetFontHeight(8);
469  aStyleSettings.SetFieldFont(aFont);
470  aSettings.SetStyleSettings(aStyleSettings);
471  mpMetadataAuthor->SetSettings(aSettings);
472  }
473 
474  mpMetadataDate = VclPtr<Edit>::Create( this, 0 );
475  mpMetadataDate->SetAccessibleName( SwResId( STR_ACCESS_ANNOTATION_DATE_NAME ) );
476  mpMetadataDate->EnableRTL(AllSettings::GetLayoutRTL());
477  mpMetadataDate->SetReadOnly();
478  mpMetadataDate->AlwaysDisableInput(true);
479  mpMetadataDate->SetCallHandlersOnInputDisabled(true);
480  mpMetadataDate->AddEventListener( LINK( this, SwAnnotationWin, WindowEventListener ) );
481  // we should leave this setting alone, but for this we need a better layout algo
482  // with variable meta size height
483  {
484  AllSettings aSettings = mpMetadataDate->GetSettings();
485  StyleSettings aStyleSettings = aSettings.GetStyleSettings();
486  vcl::Font aFont = aStyleSettings.GetFieldFont();
487  aFont.SetFontHeight(8);
488  aStyleSettings.SetFieldFont(aFont);
489  aSettings.SetStyleSettings(aStyleSettings);
490  mpMetadataDate->SetSettings(aSettings);
491  }
492 
493  SwDocShell* aShell = mrView.GetDocShell();
494  mpOutliner.reset(new Outliner(&aShell->GetPool(),OutlinerMode::TextObject));
495  aShell->GetDoc()->SetCalcFieldValueHdl( mpOutliner.get() );
496  mpOutliner->SetUpdateMode( true );
497  Rescale();
498 
499  mpSidebarTextControl->EnableRTL( false );
500  mpOutlinerView.reset(new OutlinerView ( mpOutliner.get(), mpSidebarTextControl ));
501  mpOutlinerView->SetBackgroundColor(COL_TRANSPARENT);
502  mpOutliner->InsertView(mpOutlinerView.get() );
503  mpOutlinerView->SetOutputArea( PixelToLogic( tools::Rectangle(0,0,1,1) ) );
504 
505  mpOutlinerView->SetAttribs(DefaultItem());
506 
508  {
509  // If there is a callback already registered, inform the new outliner view about it.
510  mpOutlinerView->RegisterViewShell(&mrView);
511  }
512 
513  //create Scrollbars
515  mpVScrollbar->EnableNativeWidget(false);
516  mpVScrollbar->EnableRTL( false );
517  mpVScrollbar->SetScrollHdl(LINK(this, SwAnnotationWin, ScrollHdl));
518  mpVScrollbar->EnableDrag();
519  mpVScrollbar->AddEventListener( LINK( this, SwAnnotationWin, WindowEventListener ) );
520 
521  const SwViewOption* pVOpt = mrView.GetWrtShellPtr()->GetViewOptions();
522  EEControlBits nCntrl = mpOutliner->GetControlWord();
523  // TODO: crash when AUTOCOMPLETE enabled
524  nCntrl |= EEControlBits::MARKFIELDS | EEControlBits::PASTESPECIAL | EEControlBits::AUTOCORRECT | EEControlBits::USECHARATTRIBS; // | EEControlBits::AUTOCOMPLETE;
526  nCntrl |= EEControlBits::MARKFIELDS;
527  else
528  nCntrl &= ~EEControlBits::MARKFIELDS;
529  if (pVOpt->IsOnlineSpell())
530  nCntrl |= EEControlBits::ONLINESPELLING;
531  else
532  nCntrl &= ~EEControlBits::ONLINESPELLING;
533  mpOutliner->SetControlWord(nCntrl);
534 
535  std::size_t aIndex = SW_MOD()->InsertRedlineAuthor(GetAuthor());
536  SetColor( SwPostItMgr::GetColorDark(aIndex),
539 
540  CheckMetaText();
541 
542  mpMenuButton = CreateMenuButton();
543 
545  GetOutlinerView()->StartSpeller();
546  SetPostItText();
547  mpOutliner->CompleteOnlineSpelling();
548 
549  mpSidebarTextControl->Show();
550  mpMetadataAuthor->Show();
551  mpMetadataDate->Show();
552  mpVScrollbar->Show();
553 }
554 
555 void SwAnnotationWin::CheckMetaText()
556 {
557  const SvtSysLocale aSysLocale;
558  const LocaleDataWrapper& rLocalData = aSysLocale.GetLocaleData();
559  OUString sMeta = GetAuthor();
560  if (sMeta.isEmpty())
561  {
562  sMeta = SwResId(STR_NOAUTHOR);
563  }
564  else if (sMeta.getLength() > 23)
565  {
566  sMeta = sMeta.copy(0, 20) + "...";
567  }
568  if ( mpMetadataAuthor->GetText() != sMeta )
569  {
570  mpMetadataAuthor->SetText(sMeta);
571  }
572 
573  Date aDate = GetDate();
574  if (aDate.IsValidAndGregorian() )
575  {
576  sMeta = rLocalData.getDate(aDate);
577  }
578  else
579  {
580  sMeta = SwResId(STR_NODATE);
581  }
582  if (GetTime().GetTime()!=0)
583  {
584  sMeta += " " + rLocalData.getTime( GetTime(),false );
585  }
586  if ( mpMetadataDate->GetText() != sMeta )
587  {
588  mpMetadataDate->SetText(sMeta);
589  }
590 }
591 
592 void SwAnnotationWin::Rescale()
593 {
594  MapMode aMode = GetParent()->GetMapMode();
595  aMode.SetOrigin( Point() );
596  mpOutliner->SetRefMapMode( aMode );
597  SetMapMode( aMode );
598  mpSidebarTextControl->SetMapMode( aMode );
599  const Fraction& rFraction = mrView.GetWrtShellPtr()->GetOut()->GetMapMode().GetScaleY();
600  if ( mpMetadataAuthor )
601  {
602  vcl::Font aFont( mpMetadataAuthor->GetSettings().GetStyleSettings().GetFieldFont() );
603  sal_Int32 nHeight = long(aFont.GetFontHeight() * rFraction);
604  aFont.SetFontHeight( nHeight );
605  mpMetadataAuthor->SetControlFont( aFont );
606  }
607  if ( mpMetadataDate )
608  {
609  vcl::Font aFont( mpMetadataDate->GetSettings().GetStyleSettings().GetFieldFont() );
610  sal_Int32 nHeight = long(aFont.GetFontHeight() * rFraction);
611  aFont.SetFontHeight( nHeight );
612  mpMetadataDate->SetControlFont( aFont );
613  }
614 }
615 
616 void SwAnnotationWin::SetPosAndSize()
617 {
618  bool bChange = false;
619 
620  if (GetSizePixel() != mPosSize.GetSize())
621  {
622  bChange = true;
623  SetSizePixel(mPosSize.GetSize());
624 
626  {
627  // Position is not yet set at VCL level, but the map mode should
628  // contain the right origin to emit the correct cursor position.
629  mpSidebarTextControl->Push(PushFlags::MAPMODE);
630  Point aOffset(mPosSize.Left(), mPosSize.Top());
631  aOffset = PixelToLogic(aOffset);
632  MapMode aMapMode(mpSidebarTextControl->GetMapMode());
633  aMapMode.SetOrigin(aOffset);
634  mpSidebarTextControl->SetMapMode(aMapMode);
635  mpSidebarTextControl->EnableMapMode(false);
636  }
637 
638  DoResize();
639 
641  mpSidebarTextControl->Pop();
642  }
643 
644  if (GetPosPixel().X() != mPosSize.TopLeft().X() || (std::abs(GetPosPixel().Y() - mPosSize.TopLeft().Y()) > 5) )
645  {
646  bChange = true;
647  SetPosPixel(mPosSize.TopLeft());
648 
649  Point aLineStart;
650  Point aLineEnd ;
651  switch ( meSidebarPosition )
652  {
654  {
655  aLineStart = EditWin().PixelToLogic( Point(GetPosPixel().X()+GetSizePixel().Width(),GetPosPixel().Y()-1) );
656  aLineEnd = EditWin().PixelToLogic( Point(GetPosPixel().X(),GetPosPixel().Y()-1) );
657  }
658  break;
660  {
661  aLineStart = EditWin().PixelToLogic( Point(GetPosPixel().X(),GetPosPixel().Y()-1) );
662  aLineEnd = EditWin().PixelToLogic( Point(GetPosPixel().X()+GetSizePixel().Width(),GetPosPixel().Y()-1) );
663  }
664  break;
665  default:
666  OSL_FAIL( "<SwAnnotationWin::SetPosAndSize()> - unexpected position of sidebar" );
667  break;
668  }
669 
670  // LOK has map mode disabled, and we still want to perform pixel ->
671  // twips conversion for the size of the line above the note.
672  if (comphelper::LibreOfficeKit::isActive() && !EditWin().IsMapModeEnabled())
673  {
674  EditWin().EnableMapMode();
675  Size aSize(aLineEnd.getX() - aLineStart.getX(), aLineEnd.getY() - aLineStart.getY());
676  aSize = EditWin().PixelToLogic(aSize);
677  aLineEnd = aLineStart;
678  aLineEnd.Move(aSize.getWidth(), aSize.getHeight());
679  EditWin().EnableMapMode(false);
680  }
681 
682  if (mpAnchor)
683  {
684  mpAnchor->SetAllPosition( basegfx::B2DPoint( mAnchorRect.Left() , mAnchorRect.Bottom() - 5* 15),
685  basegfx::B2DPoint( mAnchorRect.Left()-5*15 , mAnchorRect.Bottom()+5*15),
686  basegfx::B2DPoint( mAnchorRect.Left()+5*15 , mAnchorRect.Bottom()+5*15),
687  basegfx::B2DPoint( mAnchorRect.Left(), mAnchorRect.Bottom()+2*15),
688  basegfx::B2DPoint( mPageBorder ,mAnchorRect.Bottom()+2*15),
689  basegfx::B2DPoint( aLineStart.X(),aLineStart.Y()),
690  basegfx::B2DPoint( aLineEnd.X(),aLineEnd.Y()));
691  }
692  else
693  {
695  mAnchorRect,
696  mPageBorder,
697  aLineStart,
698  aLineEnd,
699  mColorAnchor );
700  if ( mpAnchor )
701  {
702  mpAnchor->setVisible(true);
703  mpAnchor->SetAnchorState(AnchorState::Tri);
704  if (HasChildPathFocus())
705  {
706  mpAnchor->setLineSolid(true);
707  }
708  }
709  }
710  }
711  else
712  {
713  if ( mpAnchor &&
714  ( mpAnchor->getBasePosition() != basegfx::B2DPoint( mAnchorRect.Left() , mAnchorRect.Bottom()-5*15) ) )
715  {
716  mpAnchor->SetTriPosition( basegfx::B2DPoint( mAnchorRect.Left() , mAnchorRect.Bottom() - 5* 15),
717  basegfx::B2DPoint( mAnchorRect.Left()-5*15 , mAnchorRect.Bottom()+5*15),
718  basegfx::B2DPoint( mAnchorRect.Left()+5*15 , mAnchorRect.Bottom()+5*15),
719  basegfx::B2DPoint( mAnchorRect.Left(), mAnchorRect.Bottom()+2*15),
720  basegfx::B2DPoint( mPageBorder , mAnchorRect.Bottom()+2*15));
721  }
722  }
723 
724  if (bChange)
725  {
726  Point aStart = EditWin().PixelToLogic(GetPosPixel()+Point(0,GetSizePixel().Height()));
727  Point aEnd = EditWin().PixelToLogic(GetPosPixel()+Point(GetSizePixel().Width()-1,GetSizePixel().Height()));
728  mpShadow->SetPosition(basegfx::B2DPoint(aStart.X(),aStart.Y()), basegfx::B2DPoint(aEnd.X(),aEnd.Y()));
729  }
730 
731  if (mrMgr.ShowNotes())
732  {
733  if (IsFollow() && !HasChildPathFocus())
734  {
735  // #i111964#
736  if ( mpAnchor )
737  {
738  mpAnchor->SetAnchorState(AnchorState::End);
739  }
740  }
741  else
742  {
743  // #i111964#
744  if ( mpAnchor )
745  {
746  mpAnchor->SetAnchorState(AnchorState::All);
747  }
748  SwAnnotationWin* pWin = GetTopReplyNote();
749  // #i111964#
750  if ( pWin != this && pWin->Anchor() )
751  {
753  }
754  }
755  }
756 
757 
758  // text range overlay
759  maAnnotationTextRanges.clear();
760  if ( mrSidebarItem.maLayoutInfo.mnStartNodeIdx != 0
761  && mrSidebarItem.maLayoutInfo.mnStartContent != -1 )
762  {
763  const SwTextAnnotationField* pTextAnnotationField =
764  dynamic_cast< const SwTextAnnotationField* >( mrSidebarItem.GetFormatField().GetTextField() );
765  SwTextNode* pTextNode = pTextAnnotationField ? pTextAnnotationField->GetpTextNode() : nullptr;
766  SwContentNode* pContentNd = nullptr;
767  if (pTextNode)
768  {
769  SwNodes& rNds = pTextNode->GetDoc()->GetNodes();
770  pContentNd = rNds[mrSidebarItem.maLayoutInfo.mnStartNodeIdx]->GetContentNode();
771  }
772  if (pContentNd)
773  {
774  SwPosition aStartPos( *pContentNd, mrSidebarItem.maLayoutInfo.mnStartContent );
775  SwShellCursor* pTmpCursor = nullptr;
776  const bool bTableCursorNeeded = pTextNode->FindTableBoxStartNode() != pContentNd->FindTableBoxStartNode();
777  if ( bTableCursorNeeded )
778  {
779  SwShellTableCursor* pTableCursor = new SwShellTableCursor( mrView.GetWrtShell(), aStartPos );
780  pTableCursor->SetMark();
781  pTableCursor->GetMark()->nNode = *pTextNode;
782  pTableCursor->GetMark()->nContent.Assign( pTextNode, pTextAnnotationField->GetStart()+1 );
783  pTableCursor->NewTableSelection();
784  pTmpCursor = pTableCursor;
785  }
786  else
787  {
788  SwShellCursor* pCursor = new SwShellCursor( mrView.GetWrtShell(), aStartPos );
789  pCursor->SetMark();
790  pCursor->GetMark()->nNode = *pTextNode;
791  pCursor->GetMark()->nContent.Assign( pTextNode, pTextAnnotationField->GetStart()+1 );
792  pTmpCursor = pCursor;
793  }
794  std::unique_ptr<SwShellCursor> pTmpCursorForAnnotationTextRange( pTmpCursor );
795 
796  // For annotation text range rectangles to be calculated correctly,
797  // we need the map mode disabled
798  bool bDisableMapMode = comphelper::LibreOfficeKit::isActive() && EditWin().IsMapModeEnabled();
799  if (bDisableMapMode)
800  EditWin().EnableMapMode(false);
801 
802  pTmpCursorForAnnotationTextRange->FillRects();
803 
804  if (bDisableMapMode)
805  EditWin().EnableMapMode();
806 
807  SwRects* pRects(pTmpCursorForAnnotationTextRange.get());
808  for(SwRect & rNextRect : *pRects)
809  {
810  const tools::Rectangle aPntRect(rNextRect.SVRect());
811  maAnnotationTextRanges.emplace_back(
812  aPntRect.Left(), aPntRect.Top(),
813  aPntRect.Right() + 1, aPntRect.Bottom() + 1);
814  }
815  }
816  }
817 
818  if (mrMgr.ShowNotes() && !maAnnotationTextRanges.empty())
819  {
820  if ( mpTextRangeOverlay != nullptr )
821  {
822  mpTextRangeOverlay->setRanges( maAnnotationTextRanges );
823  if ( mpAnchor != nullptr && mpAnchor->getLineSolid() )
824  {
825  mpTextRangeOverlay->ShowSolidBorder();
826  }
827  else
828  {
829  mpTextRangeOverlay->HideSolidBorder();
830  }
831  }
832  else if (!IsFollow())
833  {
834  // This window is not a reply, then draw its range overlay.
835  mpTextRangeOverlay =
837  mrView,
838  mColorAnchor,
839  maAnnotationTextRanges,
840  mpAnchor && mpAnchor->getLineSolid() );
841  }
842  }
843  else
844  {
845  mpTextRangeOverlay.reset();
846  }
847 }
848 
849 void SwAnnotationWin::DoResize()
850 {
851  long aTextHeight = LogicToPixel( mpOutliner->CalcTextSize()).Height();
852  long aHeight = GetSizePixel().Height();
853  unsigned long aWidth = GetSizePixel().Width();
854 
855  aHeight -= GetMetaHeight();
856  mpMetadataAuthor->Show();
857  mpMetadataDate->Show();
858  mpSidebarTextControl->SetQuickHelpText(OUString());
859 
860  if (aTextHeight > aHeight)
861  { // we need vertical scrollbars and have to reduce the width
862  aWidth -= GetScrollbarWidth();
863  mpVScrollbar->Show();
864  }
865  else
866  {
867  mpVScrollbar->Hide();
868  }
869 
870  {
871  const Size aSizeOfMetadataControls( GetSizePixel().Width() - GetMetaButtonAreaWidth(),
872  GetMetaHeight()/2 );
873  mpMetadataAuthor->setPosSizePixel( 0,
874  aHeight,
875  aSizeOfMetadataControls.Width(),
876  aSizeOfMetadataControls.Height() );
877  mpMetadataDate->setPosSizePixel( 0,
878  aHeight + aSizeOfMetadataControls.Height(),
879  aSizeOfMetadataControls.Width(),
880  aSizeOfMetadataControls.Height() );
881  }
882 
883  mpOutliner->SetPaperSize( PixelToLogic( Size(aWidth,aHeight) ) ) ;
884  if (!mpVScrollbar->IsVisible())
885  { // if we do not have a scrollbar anymore, we want to see the complete text
886  mpOutlinerView->SetVisArea( PixelToLogic( tools::Rectangle(0,0,aWidth,aHeight) ) );
887  }
888  mpOutlinerView->SetOutputArea( PixelToLogic( tools::Rectangle(0,0,aWidth,aHeight) ) );
889 
891  {
892  mpSidebarTextControl->setPosSizePixel(0, 0, aWidth, aHeight);
893  mpVScrollbar->setPosSizePixel( aWidth, 0, GetScrollbarWidth(), aHeight);
894  }
895  else
896  {
897  mpSidebarTextControl->setPosSizePixel( ( aTextHeight > aHeight ? GetScrollbarWidth() : 0 ), 0,
898  aWidth, aHeight);
899  mpVScrollbar->setPosSizePixel( 0, 0, GetScrollbarWidth(), aHeight);
900  }
901 
902  mpVScrollbar->SetVisibleSize( PixelToLogic(Size(0,aHeight)).Height() );
903  mpVScrollbar->SetPageSize( PixelToLogic(Size(0,aHeight)).Height() * 8 / 10 );
904  mpVScrollbar->SetLineSize( mpOutliner->GetTextHeight() / 10 );
905  SetScrollbar();
906  mpVScrollbar->SetRange( Range(0, mpOutliner->GetTextHeight()));
907 
908  //calculate rects for meta- button
909  const Fraction& fx( GetMapMode().GetScaleX() );
910  const Fraction& fy( GetMapMode().GetScaleY() );
911 
912  const Point aPos( mpMetadataAuthor->GetPosPixel());
913  mpMenuButton->setPosSizePixel( long(aPos.X()+GetSizePixel().Width()-(METABUTTON_WIDTH+10)*fx),
914  long(aPos.Y()+5*fy),
915  long(METABUTTON_WIDTH*fx),
916  long(METABUTTON_HEIGHT*fy) );
917 }
918 
919 void SwAnnotationWin::SetSizePixel( const Size& rNewSize )
920 {
921  Window::SetSizePixel(rNewSize);
922 
923  if (mpShadow)
924  {
925  Point aStart = EditWin().PixelToLogic(GetPosPixel()+Point(0,GetSizePixel().Height()));
926  Point aEnd = EditWin().PixelToLogic(GetPosPixel()+Point(GetSizePixel().Width()-1,GetSizePixel().Height()));
927  mpShadow->SetPosition(basegfx::B2DPoint(aStart.X(),aStart.Y()), basegfx::B2DPoint(aEnd.X(),aEnd.Y()));
928  }
929 }
930 
931 void SwAnnotationWin::SetScrollbar()
932 {
933  mpVScrollbar->SetThumbPos(mpOutlinerView->GetVisArea().Top());
934 }
935 
936 void SwAnnotationWin::ResizeIfNecessary(long aOldHeight, long aNewHeight)
937 {
938  if (aOldHeight != aNewHeight)
939  {
940  //check for lower border or next note
941  long aBorder = mrMgr.GetNextBorder();
942  if (aBorder != -1)
943  {
944  if (aNewHeight > GetMinimumSizeWithoutMeta())
945  {
946  long aNewLowerValue = GetPosPixel().Y() + aNewHeight + GetMetaHeight();
947  if (aNewLowerValue < aBorder)
948  SetSizePixel(Size(GetSizePixel().Width(),aNewHeight+GetMetaHeight()));
949  else
950  SetSizePixel(Size(GetSizePixel().Width(),aBorder - GetPosPixel().Y()));
951  DoResize();
952  Invalidate();
953  }
954  else
955  {
956  if (GetSizePixel().Height() != GetMinimumSizeWithoutMeta() + GetMetaHeight())
957  SetSizePixel(Size(GetSizePixel().Width(),GetMinimumSizeWithoutMeta() + GetMetaHeight()));
958  DoResize();
959  Invalidate();
960  }
961  }
962  else
963  {
964  DoResize();
965  Invalidate();
966  }
967  }
968  else
969  {
970  SetScrollbar();
971  }
972 }
973 
974 void SwAnnotationWin::SetColor(Color aColorDark,Color aColorLight, Color aColorAnchor)
975 {
976  mColorDark = aColorDark;
977  mColorLight = aColorLight;
978  mColorAnchor = aColorAnchor;
979 
980  if ( !Application::GetSettings().GetStyleSettings().GetHighContrastMode() )
981  {
982  {
983  mpMetadataAuthor->SetControlBackground(mColorDark);
984  AllSettings aSettings = mpMetadataAuthor->GetSettings();
985  StyleSettings aStyleSettings = aSettings.GetStyleSettings();
986  aStyleSettings.SetFieldTextColor(aColorAnchor);
987  aSettings.SetStyleSettings(aStyleSettings);
988  mpMetadataAuthor->SetSettings(aSettings);
989  }
990 
991  {
992  mpMetadataDate->SetControlBackground(mColorDark);
993  AllSettings aSettings = mpMetadataDate->GetSettings();
994  StyleSettings aStyleSettings = aSettings.GetStyleSettings();
995  aStyleSettings.SetFieldTextColor(aColorAnchor);
996  aSettings.SetStyleSettings(aStyleSettings);
997  mpMetadataDate->SetSettings(aSettings);
998  }
999 
1000  AllSettings aSettings2 = mpVScrollbar->GetSettings();
1001  StyleSettings aStyleSettings2 = aSettings2.GetStyleSettings();
1002  aStyleSettings2.SetButtonTextColor(Color(0,0,0));
1003  aStyleSettings2.SetCheckedColor(mColorLight); // background
1004  aStyleSettings2.SetShadowColor(mColorAnchor);
1005  aStyleSettings2.SetFaceColor(mColorDark);
1006  aSettings2.SetStyleSettings(aStyleSettings2);
1007  mpVScrollbar->SetSettings(aSettings2);
1008  }
1009 }
1010 
1011 void SwAnnotationWin::SetSidebarPosition(sw::sidebarwindows::SidebarPosition eSidebarPosition)
1012 {
1013  meSidebarPosition = eSidebarPosition;
1014 }
1015 
1016 void SwAnnotationWin::SetReadonly(bool bSet)
1017 {
1018  mbReadonly = bSet;
1019  GetOutlinerView()->SetReadOnly(bSet);
1020 }
1021 
1023 {
1024  Link<LinkParamNone*,void> aLink = mpOutliner->GetModifyHdl();
1025  mpOutliner->SetModifyHdl( Link<LinkParamNone*,void>() );
1026  ESelection aOld = GetOutlinerView()->GetSelection();
1027 
1028  ESelection aNewSelection( 0, 0, mpOutliner->GetParagraphCount()-1, EE_TEXTPOS_ALL );
1029  GetOutlinerView()->SetSelection( aNewSelection );
1030  SfxItemSet aEditAttr(GetOutlinerView()->GetAttribs());
1031  aEditAttr.Put(rNewItem);
1032  GetOutlinerView()->SetAttribs( aEditAttr );
1033 
1034  GetOutlinerView()->SetSelection(aOld);
1035  mpOutliner->SetModifyHdl( aLink );
1036 
1037  const SwViewOption* pVOpt = mrView.GetWrtShellPtr()->GetViewOptions();
1038  EEControlBits nCntrl = mpOutliner->GetControlWord();
1039  // turn off
1040  nCntrl &= ~EEControlBits::ONLINESPELLING;
1041  mpOutliner->SetControlWord(nCntrl);
1042 
1043  //turn back on
1044  if (pVOpt->IsOnlineSpell())
1045  nCntrl |= EEControlBits::ONLINESPELLING;
1046  else
1047  nCntrl &= ~EEControlBits::ONLINESPELLING;
1048  mpOutliner->SetControlWord(nCntrl);
1049 
1050  mpOutliner->CompleteOnlineSpelling();
1051  Invalidate();
1052 }
1053 
1054 void SwAnnotationWin::GetFocus()
1055 {
1056  if (mpSidebarTextControl)
1057  mpSidebarTextControl->GrabFocus();
1058 }
1059 
1060 void SwAnnotationWin::LoseFocus()
1061 {
1062 }
1063 
1064 void SwAnnotationWin::ShowNote()
1065 {
1066  SetPosAndSize();
1067  if (!IsVisible())
1068  Window::Show();
1069  if (mpShadow && !mpShadow->isVisible())
1070  mpShadow->setVisible(true);
1071  if (mpAnchor && !mpAnchor->isVisible())
1072  mpAnchor->setVisible(true);
1073 
1074  // Invalidate.
1075  InvalidateControl();
1076 }
1077 
1078 void SwAnnotationWin::HideNote()
1079 {
1080  if (IsVisible())
1081  Window::Hide();
1082  if (mpAnchor)
1083  {
1084  if (mrMgr.IsShowAnchor())
1085  mpAnchor->SetAnchorState(AnchorState::Tri);
1086  else
1087  mpAnchor->setVisible(false);
1088  }
1089  if (mpShadow && mpShadow->isVisible())
1090  mpShadow->setVisible(false);
1091 }
1092 
1093 void SwAnnotationWin::InvalidateControl()
1094 {
1095  // Invalidate.
1096  mpSidebarTextControl->Push(PushFlags::MAPMODE);
1097  lcl_translateTwips(EditWin(), *mpSidebarTextControl, nullptr);
1098  mpSidebarTextControl->Invalidate();
1099  mpSidebarTextControl->Pop();
1100 }
1101 
1102 void SwAnnotationWin::ActivatePostIt()
1103 {
1104  mrMgr.AssureStdModeAtShell();
1105 
1106  mpOutliner->ClearModifyFlag();
1107  mpOutliner->GetUndoManager().Clear();
1108 
1109  CheckMetaText();
1110  SetViewState(ViewState::EDIT);
1111  GetOutlinerView()->ShowCursor();
1112 
1113  mpOutlinerView->GetEditView().SetInsertMode(mrView.GetWrtShellPtr()->IsInsMode());
1114 
1116  GetOutlinerView()->SetBackgroundColor(mColorDark);
1117 
1118  //tdf#119130 only have the active postit as a dialog control in which pressing
1119  //ctrl+tab cycles between text and button so we don't waste time searching
1120  //thousands of SwAnnotationWins
1121  SetStyle(GetStyle() | WB_DIALOGCONTROL);
1122 }
1123 
1124 void SwAnnotationWin::DeactivatePostIt()
1125 {
1126  //tdf#119130 only have the active postit as a dialog control in which pressing
1127  //ctrl+tab cycles between text and button so we don't waste time searching
1128  //thousands of SwAnnotationWins
1129  SetStyle(GetStyle() & ~WB_DIALOGCONTROL);
1130 
1131  // remove selection, #i87073#
1132  if (GetOutlinerView()->GetEditView().HasSelection())
1133  {
1134  ESelection aSelection = GetOutlinerView()->GetEditView().GetSelection();
1135  aSelection.nEndPara = aSelection.nStartPara;
1136  aSelection.nEndPos = aSelection.nStartPos;
1137  GetOutlinerView()->GetEditView().SetSelection(aSelection);
1138  }
1139 
1140  mpOutliner->CompleteOnlineSpelling();
1141 
1142  SetViewState(ViewState::NORMAL);
1143  // Make sure this view doesn't emit LOK callbacks during the update, as the
1144  // sidebar window's SidebarTextControl doesn't have a valid twip offset
1145  // (map mode origin) during that operation.
1146  bool bTiledPainting = comphelper::LibreOfficeKit::isTiledPainting();
1148  // write the visible text back into the SwField
1149  UpdateData();
1151 
1152  if ( !Application::GetSettings().GetStyleSettings().GetHighContrastMode() )
1153  GetOutlinerView()->SetBackgroundColor(COL_TRANSPARENT);
1154 
1155  if ( !IsProtected() && mpOutliner->GetEditEngine().GetText().isEmpty() )
1156  {
1157  mnEventId = Application::PostUserEvent( LINK( this, SwAnnotationWin, DeleteHdl), nullptr, true );
1158  }
1159 }
1160 
1161 void SwAnnotationWin::ToggleInsMode()
1162 {
1163  if (!mrView.GetWrtShell().IsRedlineOn())
1164  {
1165  //change outliner
1166  mpOutlinerView->GetEditView().SetInsertMode(!mpOutlinerView->GetEditView().IsInsertMode());
1167  //change document
1168  mrView.GetWrtShell().ToggleInsMode();
1169  //update statusbar
1170  SfxBindings &rBnd = mrView.GetViewFrame()->GetBindings();
1171  rBnd.Invalidate(SID_ATTR_INSERT);
1172  rBnd.Update(SID_ATTR_INSERT);
1173  }
1174 }
1175 
1176 void SwAnnotationWin::ExecuteCommand(sal_uInt16 nSlot)
1177 {
1178  mrMgr.AssureStdModeAtShell();
1179 
1180  switch (nSlot)
1181  {
1182  case FN_POSTIT:
1183  case FN_REPLY:
1184  {
1185  // if this note is empty, it will be deleted once losing the focus, so no reply, but only a new note
1186  // will be created
1187  if (!mpOutliner->GetEditEngine().GetText().isEmpty())
1188  {
1189  OutlinerParaObject* pPara = new OutlinerParaObject(*GetOutlinerView()->GetEditView().CreateTextObject());
1190  mrMgr.RegisterAnswer(pPara);
1191  }
1192  if (mrMgr.HasActiveSidebarWin())
1193  mrMgr.SetActiveSidebarWin(nullptr);
1194  SwitchToFieldPos();
1195  mrView.GetViewFrame()->GetDispatcher()->Execute(FN_POSTIT);
1196  break;
1197  }
1198  case FN_DELETE_COMMENT:
1199 
1200  //Delete(); // do not kill the parent of our open popup menu
1201  mnEventId = Application::PostUserEvent( LINK( this, SwAnnotationWin, DeleteHdl), nullptr, true );
1202  break;
1203  case FN_FORMAT_ALL_NOTES:
1204  case FN_DELETE_ALL_NOTES:
1205  case FN_HIDE_ALL_NOTES:
1206  // not possible as slot as this would require that "this" is the active postit
1207  mrView.GetViewFrame()->GetBindings().Execute( nSlot, nullptr, SfxCallMode::ASYNCHRON );
1208  break;
1209  case FN_DELETE_NOTE_AUTHOR:
1210  case FN_HIDE_NOTE_AUTHOR:
1211  {
1212  // not possible as slot as this would require that "this" is the active postit
1213  SfxStringItem aItem( nSlot, GetAuthor() );
1214  const SfxPoolItem* aItems[2];
1215  aItems[0] = &aItem;
1216  aItems[1] = nullptr;
1217  mrView.GetViewFrame()->GetBindings().Execute( nSlot, aItems, SfxCallMode::ASYNCHRON );
1218  }
1219  break;
1220  default:
1221  mrView.GetViewFrame()->GetBindings().Execute( nSlot );
1222  break;
1223  }
1224 }
1225 
1226 SwEditWin& SwAnnotationWin::EditWin()
1227 {
1228  return mrView.GetEditWin();
1229 }
1230 
1231 long SwAnnotationWin::GetPostItTextHeight()
1232 {
1233  return mpOutliner ? LogicToPixel(mpOutliner->CalcTextSize()).Height() : 0;
1234 }
1235 
1236 void SwAnnotationWin::SwitchToPostIt(sal_uInt16 aDirection)
1237 {
1238  SwAnnotationWin* pPostIt = mrMgr.GetNextPostIt(aDirection, this);
1239  if (pPostIt)
1240  pPostIt->GrabFocus();
1241 }
1242 
1243 IMPL_LINK( SwAnnotationWin, WindowEventListener, VclWindowEvent&, rEvent, void )
1244 {
1245  if ( rEvent.GetId() == VclEventId::WindowMouseMove )
1246  {
1247  MouseEvent* pMouseEvt = static_cast<MouseEvent*>(rEvent.GetData());
1248  if ( pMouseEvt->IsEnterWindow() )
1249  {
1250  mbMouseOver = true;
1251  if ( !HasFocus() )
1252  {
1253  SetViewState(ViewState::VIEW);
1254  Invalidate();
1255  }
1256  }
1257  else if ( pMouseEvt->IsLeaveWindow())
1258  {
1259  mbMouseOver = false;
1260  if ( !HasFocus() )
1261  {
1262  SetViewState(ViewState::NORMAL);
1263  Invalidate();
1264  }
1265  }
1266  }
1267  else if ( rEvent.GetId() == VclEventId::WindowActivate &&
1268  rEvent.GetWindow() == mpSidebarTextControl )
1269  {
1270  const bool bLockView = mrView.GetWrtShell().IsViewLocked();
1271  mrView.GetWrtShell().LockView( true );
1272  mrMgr.SetActiveSidebarWin( this );
1273  mrView.GetWrtShell().LockView( bLockView );
1274  mrMgr.MakeVisible( this );
1275  }
1276 }
1277 
1278 IMPL_LINK(SwAnnotationWin, ScrollHdl, ScrollBar*, pScroll, void)
1279 {
1280  long nDiff = GetOutlinerView()->GetEditView().GetVisArea().Top() - pScroll->GetThumbPos();
1281  GetOutlinerView()->Scroll( 0, nDiff );
1282 }
1283 
1285 {
1286  mrView.GetDocShell()->SetModified();
1287 }
1288 
1289 IMPL_LINK_NOARG(SwAnnotationWin, DeleteHdl, void*, void)
1290 {
1291  mnEventId = nullptr;
1292  Delete();
1293 }
1294 
1295 void SwAnnotationWin::ResetAttributes()
1296 {
1297  mpOutlinerView->RemoveAttribsKeepLanguages(true);
1298  mpOutliner->RemoveFields();
1299  mpOutlinerView->SetAttribs(DefaultItem());
1300 }
1301 
1302 sal_Int32 SwAnnotationWin::GetScrollbarWidth()
1303 {
1304  return mrView.GetWrtShell().GetViewOptions()->GetZoom() / 10;
1305 }
1306 
1307 sal_Int32 SwAnnotationWin::GetMetaButtonAreaWidth()
1308 {
1309  const Fraction& f( GetMapMode().GetScaleX() );
1310  return long(METABUTTON_AREA_WIDTH * f);
1311 }
1312 
1313 sal_Int32 SwAnnotationWin::GetMetaHeight()
1314 {
1315  const Fraction& f(mrView.GetWrtShellPtr()->GetOut()->GetMapMode().GetScaleY());
1316  return long(POSTIT_META_HEIGHT * f);
1317 }
1318 
1319 sal_Int32 SwAnnotationWin::GetMinimumSizeWithMeta()
1320 {
1321  return mrMgr.GetMinimumSizeWithMeta();
1322 }
1323 
1324 sal_Int32 SwAnnotationWin::GetMinimumSizeWithoutMeta()
1325 {
1326  const Fraction& f(mrView.GetWrtShellPtr()->GetOut()->GetMapMode().GetScaleY());
1327  return long(POSTIT_MINIMUMSIZE_WITHOUT_META * f);
1328 }
1329 
1330 void SwAnnotationWin::SetSpellChecking()
1331 {
1332  const SwViewOption* pVOpt = mrView.GetWrtShellPtr()->GetViewOptions();
1333  EEControlBits nCntrl = mpOutliner->GetControlWord();
1334  if (pVOpt->IsOnlineSpell())
1335  nCntrl |= EEControlBits::ONLINESPELLING;
1336  else
1337  nCntrl &= ~EEControlBits::ONLINESPELLING;
1338  mpOutliner->SetControlWord(nCntrl);
1339 
1340  mpOutliner->CompleteOnlineSpelling();
1341  Invalidate();
1342 }
1343 
1344 void SwAnnotationWin::SetViewState(ViewState bViewState)
1345 {
1346  switch (bViewState)
1347  {
1348  case ViewState::EDIT:
1349  {
1350  if (mpAnchor)
1351  {
1352  mpAnchor->SetAnchorState(AnchorState::All);
1353  SwAnnotationWin* pWin = GetTopReplyNote();
1354  // #i111964#
1355  if ( pWin != this && pWin->Anchor() )
1356  {
1358  }
1359  mpAnchor->setLineSolid(true);
1360  if ( mpTextRangeOverlay != nullptr )
1361  {
1362  mpTextRangeOverlay->ShowSolidBorder();
1363  }
1364  }
1365  if (mpShadow)
1366  mpShadow->SetShadowState(SS_EDIT);
1367  break;
1368  }
1369  case ViewState::VIEW:
1370  {
1371  if (mpAnchor)
1372  {
1373  mpAnchor->setLineSolid(true);
1374  if ( mpTextRangeOverlay != nullptr )
1375  {
1376  mpTextRangeOverlay->ShowSolidBorder();
1377  }
1378  }
1379  if (mpShadow)
1380  mpShadow->SetShadowState(SS_VIEW);
1381  break;
1382  }
1383  case ViewState::NORMAL:
1384  {
1385  if (mpAnchor)
1386  {
1387  if (IsFollow())
1388  {
1389  // if there is no visible parent note, we want to see the complete anchor ??
1390  //if (IsAnyStackParentVisible())
1391  mpAnchor->SetAnchorState(AnchorState::End);
1392  SwAnnotationWin* pTopWinSelf = GetTopReplyNote();
1393  SwAnnotationWin* pTopWinActive = mrMgr.HasActiveSidebarWin()
1394  ? mrMgr.GetActiveSidebarWin()->GetTopReplyNote()
1395  : nullptr;
1396  // #i111964#
1397  if ( ( pTopWinSelf != this ) &&
1398  ( pTopWinSelf != pTopWinActive ) &&
1399  pTopWinSelf->Anchor() )
1400  {
1401  if ( pTopWinSelf != mrMgr.GetActiveSidebarWin() )
1402  {
1403  pTopWinSelf->Anchor()->setLineSolid(false);
1404  if ( pTopWinSelf->TextRange() != nullptr )
1405  {
1406  pTopWinSelf->TextRange()->HideSolidBorder();
1407  }
1408  }
1409  pTopWinSelf->Anchor()->SetAnchorState(AnchorState::All);
1410  }
1411  }
1412  mpAnchor->setLineSolid(false);
1413  if ( mpTextRangeOverlay != nullptr )
1414  {
1415  mpTextRangeOverlay->HideSolidBorder();
1416  }
1417  }
1418  if ( mpShadow )
1419  {
1420  mpShadow->SetShadowState(SS_NORMAL);
1421  }
1422  break;
1423  }
1424  }
1425 }
1426 
1427 SwAnnotationWin* SwAnnotationWin::GetTopReplyNote()
1428 {
1429  SwAnnotationWin* pTopNote = this;
1430  SwAnnotationWin* pSidebarWin = IsFollow() ? mrMgr.GetNextPostIt(KEY_PAGEUP, this) : nullptr;
1431  while (pSidebarWin)
1432  {
1433  pTopNote = pSidebarWin;
1434  pSidebarWin = pSidebarWin->IsFollow() ? mrMgr.GetNextPostIt(KEY_PAGEUP, pSidebarWin) : nullptr;
1435  }
1436  return pTopNote;
1437 }
1438 
1439 void SwAnnotationWin::SwitchToFieldPos()
1440 {
1441  if ( mrMgr.GetActiveSidebarWin() == this )
1442  mrMgr.SetActiveSidebarWin(nullptr);
1443  GotoPos();
1444  sal_uInt32 aCount = MoveCaret();
1445  if (aCount)
1446  mrView.GetDocShell()->GetWrtShell()->SwCursorShell::Right(aCount, 0);
1447  GrabFocusToDocument();
1448 }
1449 
1450 void SwAnnotationWin::SetChangeTracking( const SwPostItHelper::SwLayoutStatus aLayoutStatus,
1451  const Color& aChangeColor )
1452 {
1453  if ( (mLayoutStatus != aLayoutStatus) ||
1454  (mChangeColor != aChangeColor) )
1455  {
1456  mLayoutStatus = aLayoutStatus;
1457  mChangeColor = aChangeColor;
1458  Invalidate();
1459  }
1460 }
1461 
1462 bool SwAnnotationWin::HasScrollbar() const
1463 {
1464  return mpVScrollbar != nullptr;
1465 }
1466 
1467 bool SwAnnotationWin::IsScrollbarVisible() const
1468 {
1469  return HasScrollbar() && mpVScrollbar->IsVisible();
1470 }
1471 
1472 void SwAnnotationWin::ChangeSidebarItem( SwSidebarItem const & rSidebarItem )
1473 {
1474  const bool bAnchorChanged = mpAnchorFrame != rSidebarItem.maLayoutInfo.mpAnchorFrame;
1475  if ( bAnchorChanged )
1476  {
1477  mrMgr.DisconnectSidebarWinFromFrame( *mpAnchorFrame, *this );
1478  }
1479 
1480  mrSidebarItem = rSidebarItem;
1481  mpAnchorFrame = mrSidebarItem.maLayoutInfo.mpAnchorFrame;
1482 
1483  if ( GetWindowPeer() )
1484  {
1485  SidebarWinAccessible* pAcc =
1486  static_cast<SidebarWinAccessible*>( GetWindowPeer() );
1487  OSL_ENSURE( dynamic_cast<SidebarWinAccessible*>( GetWindowPeer() ),
1488  "<SwAnnotationWin::ChangeSidebarItem(..)> - unexpected type of window peer -> crash possible!" );
1489  pAcc->ChangeSidebarItem( mrSidebarItem );
1490  }
1491 
1492  if ( bAnchorChanged )
1493  {
1494  mrMgr.ConnectSidebarWinToFrame( *(mrSidebarItem.maLayoutInfo.mpAnchorFrame),
1495  mrSidebarItem.GetFormatField(),
1496  *this );
1497  }
1498 }
1499 
1500 css::uno::Reference< css::accessibility::XAccessible > SwAnnotationWin::CreateAccessible()
1501 {
1502  SidebarWinAccessible* pAcc( new SidebarWinAccessible( *this,
1503  mrView.GetWrtShell(),
1504  mrSidebarItem ) );
1505  css::uno::Reference< css::awt::XWindowPeer > xWinPeer( pAcc );
1506  SetWindowPeer( xWinPeer, pAcc );
1507 
1508  css::uno::Reference< css::accessibility::XAccessible > xAcc( xWinPeer, css::uno::UNO_QUERY );
1509  return xAcc;
1510 }
1511 
1512 } } // eof of namespace sw::sidebarwindows
1513 
1514 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
#define FN_HIDE_ALL_NOTES
Definition: cmdid.h:728
virtual Point GetPosPixel() const
void SetCheckedColor(const Color &rColor)
const Fraction & GetScaleX() const
long Width() const
sal_Int32 nStartPara
constexpr::Color COL_BLACK(0x00, 0x00, 0x00)
Marks a position in the document model.
Definition: pam.hxx:35
const SwFrame * mpAnchorFrame
void SetFieldFont(const vcl::Font &rFont)
#define METABUTTON_AREA_WIDTH
void SetStyleSettings(const StyleSettings &rSet)
long Height() const
#define KEY_PAGEUP
WinBits const WB_NODIALOGCONTROL
SwNodeIndex nNode
Definition: pam.hxx:37
::sw::overlay::OverlayRanges * TextRange()
long GetOutOffXPixel() const
MouseEventModifiers GetMode() const
const StyleSettings & GetStyleSettings() const
static const AllSettings & GetSettings()
const SwPosition * GetMark() const
Definition: pam.hxx:209
LanguageType GetLanguage(SfxItemSet const &aSet, sal_uInt16 nLangWhichId)
Definition: langhelper.cxx:402
bool IsMapModeEnabled() const
virtual void SetMark() override
Unless this is called, the getter method of Mark will return Point.
Definition: viscrs.cxx:573
Any GetTime(const OUString &val)
IMPL_LINK(SidebarTextControl, OnlineSpellCallback, SpellCallbackInfo &, rInfo, void)
virtual Size GetSizePixel() const
void SetCalcFieldValueHdl(Outliner *pOutliner)
In the Outliner, set a link to the method for field display in edit objects.
Definition: docdraw.cxx:491
static ImplSVEvent * PostUserEvent(const Link< void *, void > &rLink, void *pCaller=nullptr, bool bReferenceLink=false)
const MapMode & GetMapMode() const
SwTextNode * GetpTextNode() const
Definition: txtfld.hxx:49
static Color GetColorAnchor(std::size_t aAuthorIndex)
Definition: PostItMgr.cxx:2098
WinBits const WB_VSCROLL
Dialog to specify the properties of date form field.
Definition: accfrmobj.cxx:40
void EnableMapMode(bool bEnable=true)
Of course Writer needs its own rectangles.
Definition: swrect.hxx:34
void Invalidate(sal_uInt16 nId)
void setTiledPainting(bool bTiledPainting)
void SetButtonTextColor(const Color &rColor)
EEControlBits
void SetMapMode()
const vcl::Font & GetFieldFont() const
#define POSTIT_MINIMUMSIZE_WITHOUT_META
bool IsValidAndGregorian() const
sal_uInt16 GetClicks() const
void ChangeSidebarItem(const SwSidebarItem &rSidebarItem)
constexpr::Color COL_TRANSPARENT(0xFF, 0xFF, 0xFF, 0xFF)
const LocaleDataWrapper & GetLocaleData() const
ESelection aNewSelection(GetSelection())
#define FN_FORMAT_ALL_NOTES
Definition: cmdid.h:732
sal_uInt16 GetButtons() const
SwIndex nContent
Definition: pam.hxx:38
const Fraction & GetScaleY() const
#define X
bool IsEnterWindow() const
static Color GetColorDark(std::size_t aAuthorIndex)
Definition: PostItMgr.cxx:2068
sal_Int32 GetStart() const
Definition: txatbase.hxx:82
bool GetHighContrastMode() const
#define FN_DELETE_COMMENT
Definition: cmdid.h:730
sal_Int32 nEndPos
static std::unique_ptr< AnchorOverlayObject > CreateAnchorOverlayObject(SwView const &rDocView, const SwRect &aAnchorRect, long aPageBorder, const Point &aLineStart, const Point &aLineEnd, const Color &aColorAnchor)
void DrawRect(const tools::Rectangle &rRect)
SfxItemPool & GetPool() const
long getY() const
void SetMapUnit(MapUnit eUnit)
long getX() const
SwDoc * GetDoc()
returns Doc. But be careful!
Definition: docsh.hxx:203
WinBits const WB_DIALOGCONTROL
#define FN_REPLY
Definition: cmdid.h:731
void SetLineColor()
sal_Int32 nEndPara
#define SW_MOD()
Definition: swmodule.hxx:255
bool IsLeaveWindow() const
SwAnnotationWin * GetTopReplyNote()
Find the first annotation for the thread which this annotation is in.
DrawFlags
static std::unique_ptr< OverlayRanges > CreateOverlayRange(SwView const &rDocView, const Color &rColor, const std::vector< basegfx::B2DRange > &rRanges, const bool bShowSolidBorder)
#define METABUTTON_WIDTH
Window class for the Writer edit area, this is the one handling mouse and keyboard events and doing t...
Definition: edtwin.hxx:58
SwIndex & Assign(SwIndexReg *, sal_Int32)
Definition: index.cxx:198
#define FN_DELETE_NOTE_AUTHOR
Definition: cmdid.h:724
#define METABUTTON_HEIGHT
int i
void SetOrigin(const Point &rOrigin)
#define FN_HIDE_NOTE_AUTHOR
Definition: cmdid.h:727
void SetCursorLogicPosition(const Point &rPosition, bool bPoint, bool bClearMark)
SwDoc * GetDoc()
Definition: node.hxx:702
IMPL_LINK_NOARG(DocumentTimerManager, DoIdleJobs, Timer *, void)
void SetFillColor()
static bool GetLayoutRTL()
virtual void SetMark() override
Unless this is called, the getter method of Mark will return Point.
Definition: viscrs.cxx:740
#define EE_CHAR_FONTHEIGHT
bool IsInside(const Point &rPOINT) const
MapUnit GetMapUnit() const
OUString SwResId(const char *pId)
Definition: swmodule.cxx:191
bool IsOnlineSpell() const
Definition: viewopt.hxx:325
sal_uInt16 GetModifier() const
static bool IsFieldShadings()
Definition: viewopt.hxx:625
void GrabFocus()
long X() const
#define Y
SwLayoutInfo maLayoutInfo
::sw::sidebarwindows::AnchorOverlayObject * Anchor()
void SetAnchorState(const AnchorState aState)
Point PixelToLogic(const Point &rDevicePt) const
std::unique_ptr< drawinglayer::processor2d::BaseProcessor2D > createBaseProcessor2DFromOutputDevice(OutputDevice &rTargetOutDev, const drawinglayer::geometry::ViewInformation2D &rViewInformation2D)
void Update(sal_uInt16 nId)
WinBits const WB_3DLOOK
OUString getDate(const Date &rDate) const
const SfxPoolItem * Put(const SfxPoolItem &rItem, sal_uInt16 nWhich)
SwTextNode is a paragraph in the document model.
Definition: ndtxt.hxx:79
sal_uInt16 GetChildCount() const
std::vector< SwRect > SwRects
Definition: swregion.hxx:26
void SetFaceColor(const Color &rColor)
static Color GetColorLight(std::size_t aAuthorIndex)
Definition: PostItMgr.cxx:2083
SlideSorterView & mrView
bool IsVisible() const
SwNodes & GetNodes()
Definition: doc.hxx:403
static VclPtr< reference_type > Create(Arg &&...arg)
void SetFontHeight(long nHeight)
virtual void Paint(vcl::RenderContext &rRenderContext, const tools::Rectangle &rRect)
#define POSTIT_META_HEIGHT
long GetOutOffYPixel() const
const Point & GetPosPixel() const
void SetLanguage(SwWrtShell &rWrtSh, const OUString &rLangText, bool bIsForSelection, SfxItemSet &rCoreSet)
Definition: langhelper.cxx:223
const SwStartNode * FindTableBoxStartNode() const
Definition: node.hxx:196
void Move(long nHorzMove, long nVertMove)
void(* f)(TrueTypeTable *)
void SetFieldTextColor(const Color &rColor)
void SetShadowColor(const Color &rColor)
OUString getTime(const tools::Time &rTime, bool bSec=true, bool b100Sec=false) const
void Push(PushFlags nFlags=PushFlags::ALL)
bool NewTableSelection()
Definition: swcrsr.cxx:2428
#define EE_TEXTPOS_ALL
#define FN_POSTIT
Definition: cmdid.h:206
long Y() const
vcl::Window * GetChild(sal_uInt16 nChild) const
#define FN_DELETE_ALL_NOTES
Definition: cmdid.h:725
WinBits const WB_DRAG
sal_Int32 nStartPos