LibreOffice Module svx (master) 1
svdedxv.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 <com/sun/star/i18n/WordType.hpp>
21#include <editeng/editdata.hxx>
22#include <editeng/editeng.hxx>
23#include <editeng/editobj.hxx>
24#include <editeng/editstat.hxx>
25#include <editeng/outlobj.hxx>
26#include <editeng/unotext.hxx>
27#include <o3tl/deleter.hxx>
28#include <svl/itemiter.hxx>
29#include <svl/style.hxx>
30#include <svl/whiter.hxx>
32#include <svx/sdtfchim.hxx>
34#include <svx/svdedxv.hxx>
35#include <svx/svdetc.hxx>
36#include <svx/svdotable.hxx>
37#include <svx/svdotext.hxx>
38#include <svx/svdoutl.hxx>
39#include <svx/svdpage.hxx>
40#include <svx/svdpagv.hxx>
41#include <svx/svdundo.hxx>
42#include <vcl/canvastools.hxx>
43#include <vcl/commandevent.hxx>
44#include <vcl/cursor.hxx>
45#include <vcl/weld.hxx>
46#include <vcl/window.hxx>
47#include <comphelper/lok.hxx>
53#include <editeng/outliner.hxx>
54#include <sal/log.hxx>
56#include <sfx2/viewsh.hxx>
57#include <svx/dialmgr.hxx>
61#include <svx/sdrpagewindow.hxx>
64#include <svx/strings.hrc>
65#include <svx/svdviter.hxx>
67#include <textchain.hxx>
68#include <textchaincursor.hxx>
69#include <tools/debug.hxx>
70#include <vcl/svapp.hxx>
71
72#include <memory>
73
75 : SdrGlueEditView(rSdrModel, pOut)
76 , mpTextEditPV(nullptr)
77 , mpTextEditOutlinerView(nullptr)
78 , mpTextEditWin(nullptr)
79 , pTextEditCursorBuffer(nullptr)
80 , pMacroObj(nullptr)
81 , pMacroPV(nullptr)
82 , pMacroWin(nullptr)
83 , nMacroTol(0)
84 , mbTextEditDontDelete(false)
85 , mbTextEditOnlyOneView(false)
86 , mbTextEditNewObj(false)
87 , mbQuickTextEditMode(true)
88 , mbMacroDown(false)
89 , mpOldTextEditUndoManager(nullptr)
90{
91}
92
94{
95 mpTextEditWin = nullptr; // so there's no ShowCursor in SdrEndTextEdit
96 assert(!IsTextEdit());
97 if (IsTextEdit())
99 mpTextEditOutliner.reset();
100 assert(nullptr == mpOldTextEditUndoManager); // should have been reset
101}
102
104
106{
107 if (IsMacroObj())
108 MovMacroObj(rPnt);
110}
111
113{
114 if (IsMacroObj())
115 EndMacroObj();
117}
118
120{
121 BrkMacroObj();
123}
124
126{
127 BrkMacroObj();
129}
130
132{
133 SdrPageView* pPageView = SdrGlueEditView::ShowSdrPage(pPage);
134
135 if (comphelper::LibreOfficeKit::isActive() && pPageView)
136 {
137 // Check if other views have an active text edit on the same page as
138 // this one.
139 SdrViewIter::ForAllViews(pPageView->GetPage(), [this](SdrView* pView) {
140 if (pView == this || !pView->IsTextEdit())
141 return;
142
143 OutputDevice* pOutDev = GetFirstOutputDevice();
144 if (!pOutDev || pOutDev->GetOutDevType() != OUTDEV_WINDOW)
145 return;
146
147 // Found one, so create an outliner view, to get invalidations when
148 // the text edit changes.
149 // Call GetSfxViewShell() to make sure ImpMakeOutlinerView()
150 // registers the view shell of this draw view, and not the view
151 // shell of pView.
152 OutlinerView* pOutlinerView
153 = pView->ImpMakeOutlinerView(pOutDev->GetOwnerWindow(), nullptr, GetSfxViewShell());
154 pOutlinerView->HideCursor();
155 pView->GetTextEditOutliner()->InsertView(pOutlinerView);
156 });
157 }
158
159 return pPageView;
160}
161
162namespace
163{
165void lcl_RemoveTextEditOutlinerViews(SdrObjEditView const* pThis, SdrPageView const* pPageView,
166 OutputDevice const* pOutputDevice)
167{
169 return;
170
171 if (!pPageView)
172 return;
173
174 if (!pOutputDevice || pOutputDevice->GetOutDevType() != OUTDEV_WINDOW)
175 return;
176
177 SdrViewIter::ForAllViews(pPageView->GetPage(), [&pThis, &pOutputDevice](SdrView* pView) {
178 if (pView == pThis || !pView->IsTextEdit())
179 return;
180
181 SdrOutliner* pOutliner = pView->GetTextEditOutliner();
182 for (size_t nView = 0; nView < pOutliner->GetViewCount(); ++nView)
183 {
184 OutlinerView* pOutlinerView = pOutliner->GetView(nView);
185 if (pOutlinerView->GetWindow()->GetOutDev() != pOutputDevice)
186 continue;
187
188 pOutliner->RemoveView(pOutlinerView);
189 delete pOutlinerView;
190 }
191 });
192}
193}
194
196{
197 lcl_RemoveTextEditOutlinerViews(this, GetSdrPageView(), GetFirstOutputDevice());
198
200 {
201 // HideSdrPage() will clear mpPageView, avoid a dangling pointer.
202 mpTextEditPV = nullptr;
203 }
204
206}
207
209{
210 if (IsMacroObj())
211 {
213 }
214 else
215 {
217 }
218}
219
221{
222 SdrGlueEditView::Notify(rBC, rHint);
223 if (mpTextEditOutliner == nullptr)
224 return;
225
226 // change of printer while editing
227 if (rHint.GetId() != SfxHintId::ThisIsAnSdrHint)
228 return;
229
230 const SdrHint* pSdrHint = static_cast<const SdrHint*>(&rHint);
231 SdrHintKind eKind = pSdrHint->GetKind();
232 if (eKind == SdrHintKind::RefDeviceChange)
233 {
234 mpTextEditOutliner->SetRefDevice(GetModel().GetRefDevice());
235 }
237 {
239 }
240}
241
243{
246 if (pTextObj && !pTextObj->IsInserted())
247 SdrEndTextEdit(); // object deleted
248 // TextEditObj changed?
249 if (!IsTextEdit())
250 return;
251
252 if (pTextObj != nullptr)
253 {
254 size_t nOutlViewCnt = mpTextEditOutliner->GetViewCount();
255 bool bAreaChg = false;
256 bool bAnchorChg = false;
257 bool bColorChg = false;
258 bool bContourFrame = pTextObj->IsContourTextFrame();
259 EEAnchorMode eNewAnchor(EEAnchorMode::VCenterHCenter);
261 aOldArea.Union(aTextEditArea);
262 Color aNewColor;
263 { // check area
264 Size aPaperMin1;
265 Size aPaperMax1;
266 tools::Rectangle aEditArea1;
267 tools::Rectangle aMinArea1;
268 pTextObj->TakeTextEditArea(&aPaperMin1, &aPaperMax1, &aEditArea1, &aMinArea1);
269 Point aPvOfs(pTextObj->GetTextEditOffset());
270
271 // add possible GridOffset to up-to-now view-independent EditAreas
272 basegfx::B2DVector aGridOffset(0.0, 0.0);
273 if (getPossibleGridOffsetForSdrObject(aGridOffset, pTextObj.get(), GetSdrPageView()))
274 {
275 const Point aOffset(basegfx::fround(aGridOffset.getX()),
276 basegfx::fround(aGridOffset.getY()));
277
278 aEditArea1 += aOffset;
279 aMinArea1 += aOffset;
280 }
281
282 aEditArea1.Move(aPvOfs.X(), aPvOfs.Y());
283 aMinArea1.Move(aPvOfs.X(), aPvOfs.Y());
284 tools::Rectangle aNewArea(aMinArea1);
285 aNewArea.Union(aEditArea1);
286
287 if (aNewArea != aOldArea || aEditArea1 != aTextEditArea || aMinArea1 != aMinTextEditArea
288 || mpTextEditOutliner->GetMinAutoPaperSize() != aPaperMin1
289 || mpTextEditOutliner->GetMaxAutoPaperSize() != aPaperMax1)
290 {
291 aTextEditArea = aEditArea1;
292 aMinTextEditArea = aMinArea1;
293
294 const bool bPrevUpdateLayout = mpTextEditOutliner->SetUpdateLayout(false);
295 mpTextEditOutliner->SetMinAutoPaperSize(aPaperMin1);
296 mpTextEditOutliner->SetMaxAutoPaperSize(aPaperMax1);
297 mpTextEditOutliner->SetPaperSize(Size(0, 0)); // re-format Outliner
298
299 if (!bContourFrame)
300 {
301 mpTextEditOutliner->ClearPolygon();
302 EEControlBits nStat = mpTextEditOutliner->GetControlWord();
303 nStat |= EEControlBits::AUTOPAGESIZE;
304 mpTextEditOutliner->SetControlWord(nStat);
305 }
306 else
307 {
308 EEControlBits nStat = mpTextEditOutliner->GetControlWord();
309 nStat &= ~EEControlBits::AUTOPAGESIZE;
310 mpTextEditOutliner->SetControlWord(nStat);
311 tools::Rectangle aAnchorRect;
312 pTextObj->TakeTextAnchorRect(aAnchorRect);
313 pTextObj->ImpSetContourPolygon(*mpTextEditOutliner, aAnchorRect, true);
314 }
315 for (size_t nOV = 0; nOV < nOutlViewCnt; nOV++)
316 {
317 OutlinerView* pOLV = mpTextEditOutliner->GetView(nOV);
318 EVControlBits nStat0 = pOLV->GetControlWord();
319 EVControlBits nStat = nStat0;
320 // AutoViewSize only if not ContourFrame.
321 if (!bContourFrame)
322 nStat |= EVControlBits::AUTOSIZE;
323 else
324 nStat &= ~EVControlBits::AUTOSIZE;
325 if (nStat != nStat0)
326 pOLV->SetControlWord(nStat);
327 }
328
329 mpTextEditOutliner->SetUpdateLayout(bPrevUpdateLayout);
330 bAreaChg = true;
331 }
332 }
333 if (mpTextEditOutlinerView != nullptr)
334 { // check fill and anchor
336 eNewAnchor = pTextObj->GetOutlinerViewAnchorMode();
337 bAnchorChg = eOldAnchor != eNewAnchor;
339 aNewColor = GetTextEditBackgroundColor(*this);
340 bColorChg = aOldColor != aNewColor;
341 }
342 // refresh always when it's a contour frame. That
343 // refresh is necessary since it triggers the repaint
344 // which makes the Handles visible. Changes at TakeTextRect()
345 // seem to have resulted in a case where no refresh is executed.
346 // Before that, a refresh must have been always executed
347 // (else this error would have happened earlier), thus I
348 // even think here a refresh should be done always.
349 // Since follow-up problems cannot even be guessed I only
350 // add this one more case to the if below.
351 // BTW: It's VERY bad style that here, inside ModelHasChanged()
352 // the outliner is again massively changed for the text object
353 // in text edit mode. Normally, all necessary data should be
354 // set at SdrBeginTextEdit(). Some changes and value assigns in
355 // SdrBeginTextEdit() are completely useless since they are set here
356 // again on ModelHasChanged().
357 if (bContourFrame || bAreaChg || bAnchorChg || bColorChg)
358 {
359 for (size_t nOV = 0; nOV < nOutlViewCnt; nOV++)
360 {
361 OutlinerView* pOLV = mpTextEditOutliner->GetView(nOV);
362 { // invalidate old OutlinerView area
363 vcl::Window* pWin = pOLV->GetWindow();
364 tools::Rectangle aTmpRect(aOldArea);
365 sal_uInt16 nPixSiz = pOLV->GetInvalidateMore() + 1;
366 Size aMore(pWin->PixelToLogic(Size(nPixSiz, nPixSiz)));
367 aTmpRect.AdjustLeft(-(aMore.Width()));
368 aTmpRect.AdjustRight(aMore.Width());
369 aTmpRect.AdjustTop(-(aMore.Height()));
370 aTmpRect.AdjustBottom(aMore.Height());
371 InvalidateOneWin(*pWin->GetOutDev(), aTmpRect);
372 }
373 if (bAnchorChg)
374 pOLV->SetAnchorMode(eNewAnchor);
375 if (bColorChg)
376 pOLV->SetBackgroundColor(aNewColor);
377
378 pOLV->SetOutputArea(
379 aTextEditArea); // because otherwise, we're not re-anchoring correctly
381 }
383 }
384 }
386}
387
388namespace
389{
390class TextEditFrameOverlayObject;
391class TextEditHighContrastOverlaySelection;
392
406class TextEditOverlayObject : public sdr::overlay::OverlayObject
407{
408protected:
410 std::unique_ptr<sdr::overlay::OverlaySelection> mxOverlayTransparentSelection;
411 std::unique_ptr<TextEditHighContrastOverlaySelection> mxOverlayHighContrastSelection;
412 std::unique_ptr<TextEditFrameOverlayObject> mxOverlayFrame;
413
415 OutlinerView& mrOutlinerView;
416
418 basegfx::B2DRange maLastRange;
420
424
425 // geometry creation for OverlayObject, can use local *Last* values
428
429public:
430 TextEditOverlayObject(const Color& rColor, OutlinerView& rOutlinerView);
431 virtual ~TextEditOverlayObject() override;
432
433 sdr::overlay::OverlayObject* getOverlaySelection();
434 sdr::overlay::OverlayObject* getOverlayFrame();
435
436 const OutlinerView& getOutlinerView() const { return mrOutlinerView; }
437
441
442 // data write access. In this OverlayObject we only have the
443 // callback that triggers detecting if something *has* changed
444 void checkDataChange(const basegfx::B2DRange& rMinTextEditArea);
445 void checkSelectionChange();
446
447 const basegfx::B2DRange& getRange() const { return maRange; }
448 const drawinglayer::primitive2d::Primitive2DContainer& getTextPrimitives() const
449 {
450 return maTextPrimitives;
451 }
452};
453
454class TextEditFrameOverlayObject : public sdr::overlay::OverlayObject
455{
456private:
457 const TextEditOverlayObject& mrTextEditOverlayObject;
458
459 // geometry creation for OverlayObject, can use local *Last* values
462
463public:
464 TextEditFrameOverlayObject(const TextEditOverlayObject& rTextEditOverlayObject);
466 virtual ~TextEditFrameOverlayObject() override;
467};
468
469class TextEditHighContrastOverlaySelection : public sdr::overlay::OverlayObject
470{
471private:
472 const TextEditOverlayObject& mrTextEditOverlayObject;
473 std::vector<basegfx::B2DRange> maRanges;
474
475 // geometry creation for OverlayObject, can use local *Last* values
478
479public:
480 TextEditHighContrastOverlaySelection(const TextEditOverlayObject& rTextEditOverlayObject);
481 void setRanges(std::vector<basegfx::B2DRange>&& rNew);
482 virtual ~TextEditHighContrastOverlaySelection() override;
483};
484
485TextEditHighContrastOverlaySelection::TextEditHighContrastOverlaySelection(
486 const TextEditOverlayObject& rTextEditOverlayObject)
487 : OverlayObject(rTextEditOverlayObject.getBaseColor())
488 , mrTextEditOverlayObject(rTextEditOverlayObject)
489{
490 allowAntiAliase(rTextEditOverlayObject.allowsAntiAliase());
491 // use selection colors in HighContrast mode
492 mbHighContrastSelection = true;
493}
494
495void TextEditHighContrastOverlaySelection::setRanges(std::vector<basegfx::B2DRange>&& rNew)
496{
497 if (rNew != maRanges)
498 {
499 maRanges = std::move(rNew);
500 objectChange();
501 }
502}
503
505TextEditHighContrastOverlaySelection::createOverlayObjectPrimitive2DSequence()
506{
508
509 size_t nCount = maRanges.size();
510
511 if (nCount)
512 {
513 basegfx::B2DPolyPolygon aClipPolyPolygon;
514
515 basegfx::BColor aRGBColor(getBaseColor().getBColor());
516
517 for (size_t a = 0; a < nCount; ++a)
518 aClipPolyPolygon.append(basegfx::utils::createPolygonFromRect(maRanges[a]));
519
520 // This is used in high contrast mode, we will render the selection
521 // with the bg forced to the selection Highlight color and the fg color
522 // forced to the HighlightText color
527 aRGBColor)));
528 aRetval.append(mrTextEditOverlayObject.getTextPrimitives());
530 new drawinglayer::primitive2d::MaskPrimitive2D(aClipPolyPolygon, std::move(aRetval))));
531 }
532
533 return aRetval;
534}
535
536TextEditHighContrastOverlaySelection::~TextEditHighContrastOverlaySelection()
537{
538 if (getOverlayManager())
539 {
540 getOverlayManager()->remove(*this);
541 }
542}
543
544sdr::overlay::OverlayObject* TextEditOverlayObject::getOverlaySelection()
545{
546 if (mxOverlayTransparentSelection)
547 return mxOverlayTransparentSelection.get();
548 return mxOverlayHighContrastSelection.get();
549}
550
551sdr::overlay::OverlayObject* TextEditOverlayObject::getOverlayFrame()
552{
553 if (!mxOverlayFrame)
554 mxOverlayFrame.reset(new TextEditFrameOverlayObject(*this));
555 return mxOverlayFrame.get();
556}
557
559TextEditOverlayObject::createOverlayObjectPrimitive2DSequence()
560{
562
563 // add buffered TextPrimitives
564 aRetval.append(maTextPrimitives);
565
566 return aRetval;
567}
568
570TextEditFrameOverlayObject::createOverlayObjectPrimitive2DSequence()
571{
573
575 const double fTransparence(SvtOptionsDrawinglayer::GetTransparentSelectionPercent() * 0.01);
576 const sal_uInt16 nPixSiz(mrTextEditOverlayObject.getOutlinerView().GetInvalidateMore() - 1);
577
579 mrTextEditOverlayObject.getRange(), getBaseColor().getBColor(), fTransparence,
580 std::max(6, nPixSiz - 2), // grow
581 0.0, // shrink
582 0.0));
583
584 return aRetval;
585}
586
587TextEditOverlayObject::TextEditOverlayObject(const Color& rColor, OutlinerView& rOutlinerView)
588 : OverlayObject(rColor)
589 , mrOutlinerView(rOutlinerView)
590{
591 // no AA for TextEdit overlay
592 allowAntiAliase(false);
593
594 // create local OverlaySelection - this is an integral part of EditText
595 // visualization
596 if (Application::GetSettings().GetStyleSettings().GetHighContrastMode())
597 {
598 mxOverlayHighContrastSelection.reset(new TextEditHighContrastOverlaySelection(*this));
599 }
600 else
601 {
602 std::vector<basegfx::B2DRange> aEmptySelection{};
603 mxOverlayTransparentSelection.reset(new sdr::overlay::OverlaySelection(
604 sdr::overlay::OverlayType::Transparent, rColor, std::move(aEmptySelection), true));
605 }
606}
607
608TextEditOverlayObject::~TextEditOverlayObject()
609{
610 mxOverlayTransparentSelection.reset();
611 mxOverlayHighContrastSelection.reset();
612
613 if (getOverlayManager())
614 {
615 getOverlayManager()->remove(*this);
616 }
617}
618
619TextEditFrameOverlayObject::TextEditFrameOverlayObject(
620 const TextEditOverlayObject& rTextEditOverlayObject)
621 : OverlayObject(rTextEditOverlayObject.getBaseColor())
622 , mrTextEditOverlayObject(rTextEditOverlayObject)
623{
624 allowAntiAliase(rTextEditOverlayObject.allowsAntiAliase());
625 // use selection colors in HighContrast mode
626 mbHighContrastSelection = true;
627}
628
629TextEditFrameOverlayObject::~TextEditFrameOverlayObject()
630{
631 if (getOverlayManager())
632 {
633 getOverlayManager()->remove(*this);
634 }
635}
636
638TextEditOverlayObject::getOverlayObjectPrimitive2DSequence() const
639{
640 if (!getPrimitive2DSequence().empty())
641 {
642 if (!maRange.equal(maLastRange) || maLastTextPrimitives != maTextPrimitives)
643 {
644 // conditions of last local decomposition have changed, delete to force new evaluation
645 const_cast<TextEditOverlayObject*>(this)->resetPrimitive2DSequence();
646 }
647 }
648
649 if (getPrimitive2DSequence().empty())
650 {
651 // remember new buffered values
652 const_cast<TextEditOverlayObject*>(this)->maLastRange = maRange;
653 const_cast<TextEditOverlayObject*>(this)->maLastTextPrimitives = maTextPrimitives;
654 }
655
656 // call base implementation
657 return OverlayObject::getOverlayObjectPrimitive2DSequence();
658}
659
660void TextEditOverlayObject::checkDataChange(const basegfx::B2DRange& rMinTextEditArea)
661{
662 bool bObjectChange(false);
663
664 // check current range
665 const tools::Rectangle aOutArea(mrOutlinerView.GetOutputArea());
667 aNewRange.expand(rMinTextEditArea);
668
669 if (aNewRange != maRange)
670 {
671 maRange = aNewRange;
672 bObjectChange = true;
673 }
674
675 // check if text primitives did change
676 SdrOutliner* pSdrOutliner = dynamic_cast<SdrOutliner*>(getOutlinerView().GetOutliner());
677
678 if (pSdrOutliner)
679 {
680 // get TextPrimitives directly from active Outliner
681 basegfx::B2DHomMatrix aNewTransformA;
682 basegfx::B2DHomMatrix aNewTransformB;
683 basegfx::B2DRange aClipRange;
685
686 // active Outliner is always in unified oriented coordinate system (currently)
687 // so just translate to TopLeft of visible Range. Keep in mind that top-left
688 // depends on vertical text and top-to-bottom text attributes
689 const tools::Rectangle aVisArea(mrOutlinerView.GetVisArea());
690 const bool bVerticalWriting(pSdrOutliner->IsVertical());
691 const bool bTopToBottom(pSdrOutliner->IsTopToBottom());
692 const double fStartInX(bVerticalWriting && bTopToBottom
693 ? aOutArea.Right() - aVisArea.Left()
694 : aOutArea.Left() - aVisArea.Left());
695 const double fStartInY(bVerticalWriting && !bTopToBottom
696 ? aOutArea.Bottom() - aVisArea.Top()
697 : aOutArea.Top() - aVisArea.Top());
698
699 aNewTransformB.translate(fStartInX, fStartInY);
700
701 // get the current TextPrimitives. This is the most expensive part
702 // of this mechanism, it *may* be possible to buffer layouted
703 // primitives per ParaPortion with/in/dependent on the EditEngine
704 // content if needed. For now, get and compare
706 aNewTextPrimitives, *pSdrOutliner, aNewTransformA, aNewTransformB, aClipRange);
707
708 if (aNewTextPrimitives != maTextPrimitives)
709 {
710 maTextPrimitives = std::move(aNewTextPrimitives);
711 bObjectChange = true;
712 }
713 }
714
715 if (bObjectChange)
716 {
717 // if there really *was* a change signal the OverlayManager to
718 // refresh this object's visualization
719 objectChange();
720
721 if (mxOverlayFrame)
722 mxOverlayFrame->objectChange();
723
724 // on data change, always do a SelectionChange, too
725 // since the selection is an integral part of text visualization
726 checkSelectionChange();
727 }
728}
729
730void TextEditOverlayObject::checkSelectionChange()
731{
732 if (!(getOverlaySelection() && getOverlayManager()))
733 return;
734
735 std::vector<tools::Rectangle> aLogicRects;
736 std::vector<basegfx::B2DRange> aLogicRanges;
737 const Size aLogicPixel(getOverlayManager()->getOutputDevice().PixelToLogic(Size(1, 1)));
738
739 // get logic selection
740 getOutlinerView().GetSelectionRectangles(aLogicRects);
741
742 aLogicRanges.reserve(aLogicRects.size());
743 for (const auto& aRect : aLogicRects)
744 {
745 // convert from logic Rectangles to logic Ranges, do not forget to add
746 // one Unit (in this case logical units for one pixel, pre-calculated)
747 aLogicRanges.emplace_back(
748 aRect.Left() - aLogicPixel.Width(), aRect.Top() - aLogicPixel.Height(),
749 aRect.Right() + aLogicPixel.Width(), aRect.Bottom() + aLogicPixel.Height());
750 }
751
752 if (mxOverlayTransparentSelection)
753 mxOverlayTransparentSelection->setRanges(std::move(aLogicRanges));
754 else
755 mxOverlayHighContrastSelection->setRanges(std::move(aLogicRanges));
756}
757} // end of anonymous namespace
758
759// TextEdit
760
761// callback from the active EditView, forward to evtl. existing instances of the
762// TextEditOverlayObject(s). This will additionally update the selection which
763// is an integral part of the text visualization
765{
766 if (!IsTextEdit())
767 return;
768
769 // MinTextRange may have changed. Forward it, too
770 const basegfx::B2DRange aMinTextRange
772
773 for (sal_uInt32 a(0); a < maTEOverlayGroup.count(); a++)
774 {
775 TextEditOverlayObject* pCandidate
776 = dynamic_cast<TextEditOverlayObject*>(&maTEOverlayGroup.getOverlayObject(a));
777
778 if (pCandidate)
779 {
780 pCandidate->checkDataChange(aMinTextRange);
781 }
782 }
783}
784
785// callback from the active EditView, forward to evtl. existing instances of the
786// TextEditOverlayObject(s). This cvall *only* updates the selection visualization
787// which is e.g. used when only the selection is changed, but not the text
789{
790 if (!IsTextEdit())
791 return;
792
793 for (sal_uInt32 a(0); a < maTEOverlayGroup.count(); a++)
794 {
795 TextEditOverlayObject* pCandidate
796 = dynamic_cast<TextEditOverlayObject*>(&maTEOverlayGroup.getOverlayObject(a));
797
798 if (pCandidate)
799 {
800 pCandidate->checkSelectionChange();
801 }
802 }
803}
804
806
808{
809 return mpTextEditWin->GetPointerPosPixel();
810}
811
812css::uno::Reference<css::datatransfer::clipboard::XClipboard> SdrObjEditView::GetClipboard() const
813{
814 if (!mpTextEditWin)
815 return nullptr;
816 return mpTextEditWin->GetClipboard();
817}
818
819css::uno::Reference<css::datatransfer::dnd::XDropTarget> SdrObjEditView::GetDropTarget()
820{
821 if (!mpTextEditWin)
822 return nullptr;
823 return mpTextEditWin->GetDropTarget();
824}
825
827{
828 if (!mpTextEditWin)
829 return;
830 mpTextEditWin->SetInputContext(rInputContext);
831}
832
833void SdrObjEditView::EditViewCursorRect(const tools::Rectangle& rRect, int nExtTextInputWidth)
834{
835 if (!mpTextEditWin)
836 return;
837 mpTextEditWin->SetCursorRect(&rRect, nExtTextInputWidth);
838}
839
841{
843 {
844 // adapt all TextEditOverlayObject(s), so call EditViewInvalidate()
845 // to update accordingly (will update selection, too). Suppress new
846 // stuff when LibreOfficeKit is active
848 }
849 else
850 {
851 // draw old text edit stuff
852 if (IsTextEdit())
853 {
854 const SdrOutliner* pActiveOutliner = GetTextEditOutliner();
855
856 if (pActiveOutliner)
857 {
858 const sal_uInt32 nViewCount(pActiveOutliner->GetViewCount());
859
860 if (nViewCount)
861 {
862 const vcl::Region& rRedrawRegion = rPaintWindow.GetRedrawRegion();
863 const tools::Rectangle aCheckRect(rRedrawRegion.GetBoundRect());
864
865 for (sal_uInt32 i(0); i < nViewCount; i++)
866 {
867 OutlinerView* pOLV = pActiveOutliner->GetView(i);
868
869 // If rPaintWindow knows that the output device is a render
870 // context and is aware of the underlying vcl::Window,
871 // compare against that; that's how double-buffering can
872 // still find the matching OutlinerView.
873 OutputDevice* pOutputDevice = rPaintWindow.GetWindow()
874 ? rPaintWindow.GetWindow()->GetOutDev()
875 : &rPaintWindow.GetOutputDevice();
876 if (pOLV->GetWindow()->GetOutDev() == pOutputDevice
878 {
879 ImpPaintOutlinerView(*pOLV, aCheckRect,
880 rPaintWindow.GetTargetOutputDevice());
881 return;
882 }
883 }
884 }
885 }
886 }
887 }
888}
889
891 OutputDevice& rTargetDevice) const
892{
893 const SdrTextObj* pText = GetTextEditObject();
894 bool bTextFrame(pText && pText->IsTextFrame());
895 bool bFitToSize(mpTextEditOutliner->GetControlWord() & EEControlBits::STRETCHING);
896 bool bModified(mpTextEditOutliner->IsModified());
897 tools::Rectangle aBlankRect(rOutlView.GetOutputArea());
898 aBlankRect.Union(aMinTextEditArea);
899 tools::Rectangle aPixRect(rTargetDevice.LogicToPixel(aBlankRect));
900
901 // in the tiled rendering case, the setup is incomplete, and we very
902 // easily get an empty rRect on input - that will cause that everything is
903 // clipped; happens in case of editing text inside a shape in Calc.
904 // FIXME would be better to complete the setup so that we don't get an
905 // empty rRect here
907 aBlankRect.Intersection(rRect);
908
909 rOutlView.GetOutliner()->SetUpdateLayout(true); // Bugfix #22596#
910 rOutlView.Paint(aBlankRect, &rTargetDevice);
911
912 if (!bModified)
913 {
914 mpTextEditOutliner->ClearModifyFlag();
915 }
916
917 if (bTextFrame && !bFitToSize)
918 {
919 // completely reworked to use primitives; this ensures same look and functionality
920 const drawinglayer::geometry::ViewInformation2D aViewInformation2D;
921 std::unique_ptr<drawinglayer::processor2d::BaseProcessor2D> xProcessor(
923 aViewInformation2D));
924
925 const bool bMapModeEnabled(rTargetDevice.IsMapModeEnabled());
927 const Color aHilightColor(SvtOptionsDrawinglayer::getHilightColor());
928 const double fTransparence(SvtOptionsDrawinglayer::GetTransparentSelectionPercent() * 0.01);
929 const sal_uInt16 nPixSiz(rOutlView.GetInvalidateMore() - 1);
932 aRange, aHilightColor.getBColor(), fTransparence, std::max(6, nPixSiz - 2), // grow
933 0.0, // shrink
934 0.0));
935 const drawinglayer::primitive2d::Primitive2DContainer aSequence{ xReference };
936
937 rTargetDevice.EnableMapMode(false);
938 xProcessor->process(aSequence);
939 rTargetDevice.EnableMapMode(bMapModeEnabled);
940 }
941
942 rOutlView.ShowCursor(/*bGotoCursor=*/true, /*bActivate=*/true);
943}
944
946{
947 vcl::Window* pWin = rOutlView.GetWindow();
948
949 if (!pWin)
950 return;
951
952 const SdrTextObj* pText = GetTextEditObject();
953 bool bTextFrame(pText && pText->IsTextFrame());
954 bool bFitToSize(pText && pText->IsFitToSize());
955
956 if (!bTextFrame || bFitToSize)
957 return;
958
959 tools::Rectangle aBlankRect(rOutlView.GetOutputArea());
960 aBlankRect.Union(aMinTextEditArea);
961 tools::Rectangle aPixRect(pWin->LogicToPixel(aBlankRect));
962 sal_uInt16 nPixSiz(rOutlView.GetInvalidateMore() - 1);
963
964 aPixRect.AdjustLeft(-1);
965 aPixRect.AdjustTop(-1);
966 aPixRect.AdjustRight(1);
967 aPixRect.AdjustBottom(1);
968
969 {
970 // limit xPixRect because of driver problems when pixel coordinates are too far out
971 Size aMaxXY(pWin->GetOutputSizePixel());
972 tools::Long a(2 * nPixSiz);
973 tools::Long nMaxX(aMaxXY.Width() + a);
974 tools::Long nMaxY(aMaxXY.Height() + a);
975
976 if (aPixRect.Left() < -a)
977 aPixRect.SetLeft(-a);
978 if (aPixRect.Top() < -a)
979 aPixRect.SetTop(-a);
980 if (aPixRect.Right() > nMaxX)
981 aPixRect.SetRight(nMaxX);
982 if (aPixRect.Bottom() > nMaxY)
983 aPixRect.SetBottom(nMaxY);
984 }
985
986 tools::Rectangle aOuterPix(aPixRect);
987 aOuterPix.AdjustLeft(-nPixSiz);
988 aOuterPix.AdjustTop(-nPixSiz);
989 aOuterPix.AdjustRight(nPixSiz);
990 aOuterPix.AdjustBottom(nPixSiz);
991
992 bool bMapModeEnabled(pWin->IsMapModeEnabled());
993 pWin->EnableMapMode(false);
994 pWin->Invalidate(aOuterPix);
995 pWin->EnableMapMode(bMapModeEnabled);
996}
997
999 SfxViewShell* pViewShell) const
1000{
1001 // background
1002 Color aBackground(GetTextEditBackgroundColor(*this));
1004 bool bTextFrame = pText != nullptr && pText->IsTextFrame();
1005 bool bContourFrame = pText != nullptr && pText->IsContourTextFrame();
1006 // create OutlinerView
1007 OutlinerView* pOutlView = pGivenView;
1008 mpTextEditOutliner->SetUpdateLayout(false);
1009
1010 if (pOutlView == nullptr)
1011 {
1012 pOutlView = new OutlinerView(mpTextEditOutliner.get(), pWin);
1013 }
1014 else
1015 {
1016 pOutlView->SetWindow(pWin);
1017 }
1018
1019 if (mbNegativeX)
1020 pOutlView->GetEditView().SetNegativeX(mbNegativeX);
1021
1022 // disallow scrolling
1023 EVControlBits nStat = pOutlView->GetControlWord();
1024 nStat &= ~EVControlBits::AUTOSCROLL;
1025 // AutoViewSize only if not ContourFrame.
1026 if (!bContourFrame)
1027 nStat |= EVControlBits::AUTOSIZE;
1028 if (bTextFrame)
1029 {
1030 sal_uInt16 nPixSiz = maHdlList.GetHdlSize() * 2 + 1;
1031 nStat |= EVControlBits::INVONEMORE;
1032 pOutlView->SetInvalidateMore(nPixSiz);
1033 }
1034 pOutlView->SetControlWord(nStat);
1035 pOutlView->SetBackgroundColor(aBackground);
1036
1037 // In case we're in the process of constructing a new view shell,
1038 // SfxViewShell::Current() may still point to the old one. So if possible,
1039 // depend on the application owning this draw view to provide the view
1040 // shell.
1041 SfxViewShell* pSfxViewShell = pViewShell ? pViewShell : GetSfxViewShell();
1042 pOutlView->RegisterViewShell(pSfxViewShell ? pSfxViewShell : SfxViewShell::Current());
1043
1044 if (pText != nullptr)
1045 {
1046 pOutlView->SetAnchorMode(pText->GetOutlinerViewAnchorMode());
1047 mpTextEditOutliner->SetFixedCellHeight(
1048 pText->GetMergedItem(SDRATTR_TEXT_USEFIXEDCELLHEIGHT).GetValue());
1049 }
1050 // do update before setting output area so that aTextEditArea can be recalculated
1051 mpTextEditOutliner->SetUpdateLayout(true);
1052 pOutlView->SetOutputArea(aTextEditArea);
1053 ImpInvalidateOutlinerView(*pOutlView);
1054 return pOutlView;
1055}
1056
1057IMPL_LINK(SdrObjEditView, ImpOutlinerStatusEventHdl, EditStatus&, rEditStat, void)
1058{
1059 if (mpTextEditOutliner)
1060 {
1061 rtl::Reference<SdrTextObj> pTextObj = mxWeakTextEditObj.get();
1062 if (pTextObj)
1063 {
1064 pTextObj->onEditOutlinerStatusEvent(&rEditStat);
1065 }
1066 }
1067}
1068
1070{
1071 if (!mpTextEditOutliner)
1072 return;
1073
1076 if (pTextObj && pOLV)
1077 {
1078 TextChain* pTextChain = pTextObj->GetTextChain();
1079
1080 // XXX: IsChainable and GetNilChainingEvent are a bit mixed up atm
1081 if (!pTextObj->IsChainable())
1082 {
1083 return;
1084 }
1085 // This is true during an underflow-caused overflow (with pEdtOutl->SetText())
1086 if (pTextChain->GetNilChainingEvent(pTextObj.get()))
1087 {
1088 return;
1089 }
1090
1091 // We prevent to trigger further handling of overflow/underflow for pTextObj
1092 pTextChain->SetNilChainingEvent(pTextObj.get(), true); // XXX
1093
1094 // Save previous selection pos // NOTE: It must be done to have the right CursorEvent in KeyInput
1095 pTextChain->SetPreChainingSel(pTextObj.get(), pOLV->GetSelection());
1096 //maPreChainingSel = new ESelection(pOLV->GetSelection());
1097
1098 // Handling Undo
1099 const int nText = 0; // XXX: hardcoded index (SdrTextObj::getText handles only 0)
1100
1101 const bool bUndoEnabled = IsUndoEnabled();
1102 std::unique_ptr<SdrUndoObjSetText> pTxtUndo;
1103 if (bUndoEnabled)
1104 pTxtUndo.reset(
1105 dynamic_cast<SdrUndoObjSetText*>(GetModel()
1106 .GetSdrUndoFactory()
1107 .CreateUndoObjectSetText(*pTextObj, nText)
1108 .release()));
1109
1110 // trigger actual chaining
1111 pTextObj->onChainingEvent();
1112
1113 if (pTxtUndo)
1114 {
1115 pTxtUndo->AfterSetText();
1116 if (!pTxtUndo->IsDifferent())
1117 {
1118 pTxtUndo.reset();
1119 }
1120 }
1121
1122 if (pTxtUndo)
1123 AddUndo(std::move(pTxtUndo));
1124
1125 //maCursorEvent = new CursorChainingEvent(pTextChain->GetCursorEvent(pTextObj));
1126 //SdrTextObj *pNextLink = pTextObj->GetNextLinkInChain();
1127
1128 // NOTE: Must be called. Don't let the function return if you set it to true and not reset it
1129 pTextChain->SetNilChainingEvent(pTextObj.get(), false);
1130 }
1131 else
1132 {
1133 // XXX
1134 SAL_INFO("svx.chaining", "[OnChaining] No Edit Outliner View");
1135 }
1136}
1137
1138IMPL_LINK_NOARG(SdrObjEditView, ImpAfterCutOrPasteChainingEventHdl, LinkParamNone*, void)
1139{
1140 SdrTextObj* pTextObj = GetTextEditObject();
1141 if (!pTextObj)
1142 return;
1143 ImpChainingEventHdl();
1144 TextChainCursorManager aCursorManager(this, pTextObj);
1145 ImpMoveCursorAfterChainingEvent(&aCursorManager);
1146}
1147
1149{
1151
1152 if (!pTextObj || !pCursorManager)
1153 return;
1154
1155 // Check if it has links to move it to
1156 if (!pTextObj || !pTextObj->IsChainable())
1157 return;
1158
1159 TextChain* pTextChain = pTextObj->GetTextChain();
1160 ESelection aNewSel = pTextChain->GetPostChainingSel(pTextObj.get());
1161
1162 pCursorManager->HandleCursorEventAfterChaining(pTextChain->GetCursorEvent(pTextObj.get()),
1163 aNewSel);
1164
1165 // Reset event
1166 pTextChain->SetCursorEvent(pTextObj.get(), CursorChainingEvent::NULL_EVENT);
1167}
1168
1169IMPL_LINK(SdrObjEditView, ImpOutlinerCalcFieldValueHdl, EditFieldInfo*, pFI, void)
1170{
1171 bool bOk = false;
1172 OUString& rStr = pFI->GetRepresentation();
1173 rStr.clear();
1174 rtl::Reference<SdrTextObj> pTextObj = mxWeakTextEditObj.get();
1175 if (pTextObj != nullptr)
1176 {
1177 std::optional<Color> pTxtCol;
1178 std::optional<Color> pFldCol;
1179 std::optional<FontLineStyle> pFldLineStyle;
1180 bOk = pTextObj->CalcFieldValue(pFI->GetField(), pFI->GetPara(), pFI->GetPos(), true,
1181 pTxtCol, pFldCol, pFldLineStyle, rStr);
1182 if (bOk)
1183 {
1184 if (pTxtCol)
1185 {
1186 pFI->SetTextColor(*pTxtCol);
1187 }
1188 if (pFldLineStyle)
1189 {
1190 pFI->SetFontLineStyle(*pFldLineStyle);
1191 }
1192 if (pFldCol)
1193 {
1194 pFI->SetFieldColor(*pFldCol);
1195 }
1196 else
1197 {
1198 pFI->SetFieldColor(COL_LIGHTGRAY); // TODO: remove this later on (357)
1199 }
1200 }
1201 }
1202 Outliner& rDrawOutl = GetModel().GetDrawOutliner(pTextObj.get());
1203 Link<EditFieldInfo*, void> aDrawOutlLink = rDrawOutl.GetCalcFieldValueHdl();
1204 if (!bOk && aDrawOutlLink.IsSet())
1205 {
1206 aDrawOutlLink.Call(pFI);
1207 bOk = !rStr.isEmpty();
1208 }
1209 if (!bOk)
1210 {
1211 aOldCalcFieldValueLink.Call(pFI);
1212 }
1213}
1214
1215IMPL_LINK_NOARG(SdrObjEditView, EndTextEditHdl, SdrUndoManager*, void) { SdrEndTextEdit(); }
1216
1217// Default implementation - null UndoManager
1218std::unique_ptr<SdrUndoManager> SdrObjEditView::createLocalTextUndoManager()
1219{
1220 SAL_WARN("svx", "SdrObjEditView::createLocalTextUndoManager needs to be overridden");
1221 return std::unique_ptr<SdrUndoManager>();
1222}
1223
1225 bool bIsNewObj, SdrOutliner* pGivenOutliner,
1226 OutlinerView* pGivenOutlinerView, bool bDontDeleteOutliner,
1227 bool bOnlyOneView, bool bGrabFocus)
1228{
1229 // FIXME cannot be an assert() yet, the code is not ready for that;
1230 // eg. press F7 in Impress when you are inside a text object with spelling
1231 // mistakes => boom; and it is unclear how to avoid that
1232 SAL_WARN_IF(IsTextEdit(), "svx", "SdrBeginTextEdit called when IsTextEdit() is already true.");
1233 // FIXME this encourages all sorts of bad habits and should be removed
1235
1236 SdrTextObj* pObj = DynCastSdrTextObj(pObj_);
1237 if (!pObj)
1238 return false; // currently only possible with text objects
1239
1240 if (bGrabFocus && pWin)
1241 {
1242 // attention, this call may cause an EndTextEdit() call to this view
1243 pWin->GrabFocus(); // to force the cursor into the edit view
1244 }
1245
1246 mbTextEditDontDelete = bDontDeleteOutliner && pGivenOutliner != nullptr;
1247 mbTextEditOnlyOneView = bOnlyOneView;
1248 mbTextEditNewObj = bIsNewObj;
1249 const sal_uInt32 nWinCount(PaintWindowCount());
1250
1251 bool bBrk(false);
1252
1253 if (!pWin)
1254 {
1255 for (sal_uInt32 i = 0; i < nWinCount && !pWin; i++)
1256 {
1257 SdrPaintWindow* pPaintWindow = GetPaintWindow(i);
1258
1259 if (OUTDEV_WINDOW == pPaintWindow->GetOutputDevice().GetOutDevType())
1260 {
1261 pWin = pPaintWindow->GetOutputDevice().GetOwnerWindow();
1262 }
1263 }
1264
1265 // break, when no window exists
1266 if (!pWin)
1267 {
1268 bBrk = true;
1269 }
1270 }
1271
1272 if (!bBrk && !pPV)
1273 {
1274 pPV = GetSdrPageView();
1275
1276 // break, when no PageView for the object exists
1277 if (!pPV)
1278 {
1279 bBrk = true;
1280 }
1281 }
1282
1283 // no TextEdit on objects in locked Layer
1284 if (pPV && pPV->GetLockedLayers().IsSet(pObj->GetLayer()))
1285 {
1286 bBrk = true;
1287 }
1288
1290 {
1291 OSL_FAIL("SdrObjEditView::SdrBeginTextEdit(): Old Outliner still exists.");
1292 mpTextEditOutliner.reset();
1293 }
1294
1295 if (!bBrk)
1296 {
1297 mpTextEditWin = pWin;
1298 mpTextEditPV = pPV;
1299 mxWeakTextEditObj = pObj;
1300 if (pGivenOutliner)
1301 {
1302 mpTextEditOutliner.reset(pGivenOutliner);
1303 pGivenOutliner = nullptr; // so we don't delete it on the error path
1304 }
1305 else
1307 = SdrMakeOutliner(OutlinerMode::TextObject, pObj->getSdrModelFromSdrObject());
1308
1309 {
1311 }
1312
1313 aOldCalcFieldValueLink = mpTextEditOutliner->GetCalcFieldValueHdl();
1314 // FieldHdl has to be set by SdrBeginTextEdit, because this call an UpdateFields
1315 mpTextEditOutliner->SetCalcFieldValueHdl(
1316 LINK(this, SdrObjEditView, ImpOutlinerCalcFieldValueHdl));
1317 mpTextEditOutliner->SetBeginPasteOrDropHdl(LINK(this, SdrObjEditView, BeginPasteOrDropHdl));
1318 mpTextEditOutliner->SetEndPasteOrDropHdl(LINK(this, SdrObjEditView, EndPasteOrDropHdl));
1319
1320 // It is just necessary to make the visualized page known. Set it.
1321 mpTextEditOutliner->setVisualizedPage(pPV->GetPage());
1322
1324 mpTextEditOutliner->SetTextObjNoInit(pTextObj.get());
1325
1326 if (pTextObj->BegTextEdit(*mpTextEditOutliner))
1327 {
1328 // switch off any running TextAnimations
1329 pTextObj->SetTextAnimationAllowed(false);
1330
1331 // remember old cursor
1332 if (mpTextEditOutliner->GetViewCount() != 0)
1333 {
1334 mpTextEditOutliner->RemoveView(static_cast<size_t>(0));
1335 }
1336
1337 // Determine EditArea via TakeTextEditArea.
1338 // TODO: This could theoretically be left out, because TakeTextRect() calculates the aTextEditArea,
1339 // but aMinTextEditArea has to happen, too (therefore leaving this in right now)
1340 pTextObj->TakeTextEditArea(nullptr, nullptr, &aTextEditArea, &aMinTextEditArea);
1341
1342 tools::Rectangle aTextRect;
1343 tools::Rectangle aAnchorRect;
1344 pTextObj->TakeTextRect(*mpTextEditOutliner, aTextRect, true,
1345 &aAnchorRect /* Give true here, not false */);
1346
1347 if (!pTextObj->IsContourTextFrame())
1348 {
1349 // FitToSize not together with ContourFrame, for now
1350 if (pTextObj->IsFitToSize())
1351 aTextRect = aAnchorRect;
1352 }
1353
1354 aTextEditArea = aTextRect;
1355
1356 // add possible GridOffset to up-to-now view-independent EditAreas
1357 basegfx::B2DVector aGridOffset(0.0, 0.0);
1358 if (getPossibleGridOffsetForSdrObject(aGridOffset, pTextObj.get(), pPV))
1359 {
1360 const Point aOffset(basegfx::fround(aGridOffset.getX()),
1361 basegfx::fround(aGridOffset.getY()));
1362
1363 aTextEditArea += aOffset;
1364 aMinTextEditArea += aOffset;
1365 }
1366
1367 Point aPvOfs(pTextObj->GetTextEditOffset());
1368 aTextEditArea.Move(aPvOfs.X(), aPvOfs.Y());
1369 aMinTextEditArea.Move(aPvOfs.X(), aPvOfs.Y());
1371
1373
1374 // Since IsMarkHdlWhenTextEdit() is ignored, it is necessary
1375 // to call AdjustMarkHdl() always.
1376 AdjustMarkHdl();
1377
1378 mpTextEditOutlinerView = ImpMakeOutlinerView(pWin, pGivenOutlinerView);
1379
1381 {
1382 // activate visualization of EditView on Overlay, suppress when
1383 // LibreOfficeKit is active
1385
1386 const Color aHilightColor(SvtOptionsDrawinglayer::getHilightColor());
1387 const SdrTextObj* pText = GetTextEditObject();
1388 // show for cases like tdf#94223 but not for table cells like tdf#151311
1389 const bool bVisualizeSurroundingFrame(
1390 pText && pText->GetObjIdentifier() != SdrObjKind::Table);
1391 SdrPageView* pPageView = GetSdrPageView();
1392
1393 if (pPageView)
1394 {
1395 for (sal_uInt32 b(0); b < pPageView->PageWindowCount(); b++)
1396 {
1397 const SdrPageWindow& rPageWindow = *pPageView->GetPageWindow(b);
1398
1399 if (rPageWindow.GetPaintWindow().OutputToWindow())
1400 {
1402 = rPageWindow.GetOverlayManager();
1403 if (xManager.is())
1404 {
1405 std::unique_ptr<TextEditOverlayObject> pNewTextEditOverlayObject(
1406 new TextEditOverlayObject(aHilightColor,
1408
1409 xManager->add(*pNewTextEditOverlayObject);
1410 if (bVisualizeSurroundingFrame)
1411 xManager->add(*pNewTextEditOverlayObject->getOverlayFrame());
1412 xManager->add(*pNewTextEditOverlayObject->getOverlaySelection());
1413
1414 maTEOverlayGroup.append(std::move(pNewTextEditOverlayObject));
1415 }
1416 }
1417 }
1418 }
1419 }
1420
1421 // check if this view is already inserted
1422 size_t i2, nCount = mpTextEditOutliner->GetViewCount();
1423 for (i2 = 0; i2 < nCount; i2++)
1424 {
1425 if (mpTextEditOutliner->GetView(i2) == mpTextEditOutlinerView)
1426 break;
1427 }
1428
1429 if (i2 == nCount)
1431
1434
1435 // register all windows as OutlinerViews with the Outliner
1436 if (!bOnlyOneView)
1437 {
1438 for (sal_uInt32 i = 0; i < nWinCount; i++)
1439 {
1440 SdrPaintWindow* pPaintWindow = GetPaintWindow(i);
1441 OutputDevice& rOutDev = pPaintWindow->GetOutputDevice();
1442
1443 if (&rOutDev != pWin->GetOutDev() && OUTDEV_WINDOW == rOutDev.GetOutDevType())
1444 {
1445 OutlinerView* pOutlView
1446 = ImpMakeOutlinerView(rOutDev.GetOwnerWindow(), nullptr);
1447 mpTextEditOutliner->InsertView(pOutlView, static_cast<sal_uInt16>(i));
1448 }
1449 }
1450
1452 {
1453 // Register an outliner view for all other sdr views that
1454 // show the same page, so that when the text edit changes,
1455 // all interested windows get an invalidation.
1457 SdrView* pView) {
1458 if (pView == this)
1459 return;
1460
1461 for (sal_uInt32 nViewPaintWindow = 0;
1462 nViewPaintWindow < pView->PaintWindowCount(); ++nViewPaintWindow)
1463 {
1464 SdrPaintWindow* pPaintWindow = pView->GetPaintWindow(nViewPaintWindow);
1465 OutputDevice& rOutDev = pPaintWindow->GetOutputDevice();
1466
1467 if (&rOutDev != pWin->GetOutDev()
1468 && OUTDEV_WINDOW == rOutDev.GetOutDevType())
1469 {
1470 OutlinerView* pOutlView
1471 = ImpMakeOutlinerView(rOutDev.GetOwnerWindow(), nullptr);
1472 pOutlView->HideCursor();
1473 rOutDev.GetOwnerWindow()->SetCursor(nullptr);
1474 mpTextEditOutliner->InsertView(pOutlView);
1475 }
1476 }
1477 });
1478 }
1479 }
1480
1482 mpTextEditOutliner->SetStatusEventHdl(
1483 LINK(this, SdrObjEditView, ImpOutlinerStatusEventHdl));
1484 if (pTextObj->IsChainable())
1485 {
1487 LINK(this, SdrObjEditView, ImpAfterCutOrPasteChainingEventHdl));
1488 }
1489
1490 mpTextEditOutliner->ClearModifyFlag();
1491
1492 if (pTextObj->IsFitToSize())
1493 {
1495 }
1496
1497 SdrHint aHint(SdrHintKind::BeginEdit, *pTextObj);
1498 GetModel().Broadcast(aHint);
1499
1500 mpTextEditOutliner->setVisualizedPage(nullptr);
1501
1502 if (mxSelectionController.is())
1503 mxSelectionController->onSelectionHasChanged();
1504
1505 if (IsUndoEnabled() && !GetModel().GetDisableTextEditUsesCommonUndoManager())
1506 {
1507 SdrUndoManager* pSdrUndoManager = nullptr;
1509
1511 pSdrUndoManager = mpLocalTextEditUndoManager.get();
1512
1513 if (pSdrUndoManager)
1514 {
1515 // we have an outliner, undo manager and it's an EditUndoManager, exchange
1516 // the document undo manager and the default one from the outliner and tell
1517 // it that text edit starts by setting a callback if it needs to end text edit mode.
1518 assert(nullptr == mpOldTextEditUndoManager);
1519
1520 mpOldTextEditUndoManager = mpTextEditOutliner->SetUndoManager(pSdrUndoManager);
1521 pSdrUndoManager->SetEndTextEditHdl(LINK(this, SdrObjEditView, EndTextEditHdl));
1522 }
1523 else
1524 {
1525 OSL_ENSURE(false,
1526 "The document undo manager is not derived from SdrUndoManager (!)");
1527 }
1528 }
1529
1530 return true; // ran fine, let TextEdit run now
1531 }
1532 else
1533 {
1534 mpTextEditOutliner->SetCalcFieldValueHdl(aOldCalcFieldValueLink);
1535 mpTextEditOutliner->SetBeginPasteOrDropHdl(Link<PasteOrDropInfos*, void>());
1536 mpTextEditOutliner->SetEndPasteOrDropHdl(Link<PasteOrDropInfos*, void>());
1537 }
1538 }
1539 if (mpTextEditOutliner != nullptr)
1540 {
1541 mpTextEditOutliner->setVisualizedPage(nullptr);
1542 }
1543
1544 // something went wrong...
1545 if (!bDontDeleteOutliner)
1546 {
1547 delete pGivenOutliner;
1548 if (pGivenOutlinerView != nullptr)
1549 {
1550 delete pGivenOutlinerView;
1551 pGivenOutlinerView = nullptr;
1552 }
1553 }
1554 mpTextEditOutliner.reset();
1555
1556 mpTextEditOutlinerView = nullptr;
1557 mxWeakTextEditObj.clear();
1558 mpTextEditPV = nullptr;
1559 mpTextEditWin = nullptr;
1560 maHdlList.SetMoveOutside(false);
1561
1562 return false;
1563}
1564
1566{
1569 vcl::Window* pTEWin = mpTextEditWin;
1570 OutlinerView* pTEOutlinerView = mpTextEditOutlinerView;
1571 vcl::Cursor* pTECursorBuffer = pTextEditCursorBuffer;
1572 SdrUndoManager* pUndoEditUndoManager = nullptr;
1573 bool bNeedToUndoSavedRedoTextEdit(false);
1574
1575 if (IsUndoEnabled() && pTEObj && mpTextEditOutliner
1576 && !GetModel().GetDisableTextEditUsesCommonUndoManager())
1577 {
1578 // change back the UndoManager to the remembered original one
1579 SfxUndoManager* pOriginal = mpTextEditOutliner->SetUndoManager(mpOldTextEditUndoManager);
1580 mpOldTextEditUndoManager = nullptr;
1581
1582 if (pOriginal)
1583 {
1584 // check if we got back our document undo manager
1585 SdrUndoManager* pSdrUndoManager = mpLocalTextEditUndoManager.get();
1586
1587 if (pSdrUndoManager && dynamic_cast<SdrUndoManager*>(pOriginal) == pSdrUndoManager)
1588 {
1589 if (pSdrUndoManager->isEndTextEditTriggeredFromUndo())
1590 {
1591 // remember the UndoManager where missing Undos have to be triggered after end
1592 // text edit. When the undo had triggered the end text edit, the original action
1593 // which had to be undone originally is not yet undone.
1594 pUndoEditUndoManager = pSdrUndoManager;
1595
1596 // We are ending text edit; if text edit was triggered from undo, execute all redos
1597 // to create a complete text change undo action for the redo buffer. Also mark this
1598 // state when at least one redo was executed; the created extra TextChange needs to
1599 // be undone in addition to the first real undo outside the text edit changes
1600 while (pSdrUndoManager->GetRedoActionCount()
1601 > pSdrUndoManager->GetRedoActionCountBeforeTextEdit())
1602 {
1603 bNeedToUndoSavedRedoTextEdit = true;
1604 pSdrUndoManager->Redo();
1605 }
1606 }
1607
1608 // reset the callback link and let the undo manager cleanup all text edit
1609 // undo actions to get the stack back to the form before the text edit
1611 }
1612 else
1613 {
1614 OSL_ENSURE(false, "Got UndoManager back in SdrEndTextEdit which is NOT the "
1615 "expected document UndoManager (!)");
1616 delete pOriginal;
1617 }
1618
1619 // cid#1493241 - Wrapper object use after free
1620 if (pUndoEditUndoManager == mpLocalTextEditUndoManager.get())
1621 pUndoEditUndoManager = nullptr;
1623 }
1624 }
1625 else
1626 {
1627 assert(nullptr == mpOldTextEditUndoManager); // cannot be restored!
1628 }
1629
1630 if (auto pTextEditObj = mxWeakTextEditObj.get())
1631 {
1632 SdrHint aHint(SdrHintKind::EndEdit, *pTextEditObj);
1633 GetModel().Broadcast(aHint);
1634 }
1635
1636 // if new mechanism was used, clean it up. At cleanup no need to check
1637 // for LibreOfficeKit
1639 {
1642 }
1643
1644 mxWeakTextEditObj.clear();
1645 mpTextEditPV = nullptr;
1646 mpTextEditWin = nullptr;
1647 mpTextEditOutlinerView = nullptr;
1648 pTextEditCursorBuffer = nullptr;
1650
1651 if (SdrOutliner* pTEOutliner = mpTextEditOutliner.release())
1652 {
1653 bool bModified = pTEOutliner->IsModified();
1654 if (pTEOutlinerView != nullptr)
1655 {
1656 pTEOutlinerView->HideCursor();
1657 }
1658 if (pTEObj != nullptr)
1659 {
1660 pTEOutliner->CompleteOnlineSpelling();
1661
1662 std::unique_ptr<SdrUndoObjSetText> pTxtUndo;
1663
1664 if (bModified)
1665 {
1666 sal_Int32 nText;
1667 for (nText = 0; nText < pTEObj->getTextCount(); ++nText)
1668 if (pTEObj->getText(nText) == pTEObj->getActiveText())
1669 break;
1670
1671 pTxtUndo.reset(
1672 dynamic_cast<SdrUndoObjSetText*>(GetModel()
1673 .GetSdrUndoFactory()
1674 .CreateUndoObjectSetText(*pTEObj, nText)
1675 .release()));
1676 }
1677 DBG_ASSERT(!bModified || pTxtUndo,
1678 "svx::SdrObjEditView::EndTextEdit(), could not create undo action!");
1679 // Set old CalcFieldValue-Handler again, this
1680 // has to happen before Obj::EndTextEdit(), as this does UpdateFields().
1681 pTEOutliner->SetCalcFieldValueHdl(aOldCalcFieldValueLink);
1682 pTEOutliner->SetBeginPasteOrDropHdl(Link<PasteOrDropInfos*, void>());
1683 pTEOutliner->SetEndPasteOrDropHdl(Link<PasteOrDropInfos*, void>());
1684
1685 const bool bUndo = IsUndoEnabled();
1686 if (bUndo)
1687 {
1688 OUString aObjName(pTEObj->TakeObjNameSingul());
1689 BegUndo(SvxResId(STR_UndoObjSetText), aObjName);
1690 }
1691
1692 pTEObj->EndTextEdit(*pTEOutliner);
1693
1694 if ((pTEObj->GetRotateAngle() != 0_deg100) || (pTEObj && pTEObj->IsFontwork()))
1695 {
1696 pTEObj->ActionChanged();
1697 }
1698
1699 if (pTxtUndo != nullptr)
1700 {
1701 pTxtUndo->AfterSetText();
1702 if (!pTxtUndo->IsDifferent())
1703 {
1704 pTxtUndo.reset();
1705 }
1706 }
1707 // check deletion of entire TextObj
1708 std::unique_ptr<SdrUndoAction> pDelUndo;
1709 bool bDelObj = false;
1710 if (mbTextEditNewObj)
1711 {
1712 bDelObj = pTEObj->IsTextFrame() && !pTEObj->HasText() && !pTEObj->IsEmptyPresObj()
1713 && !pTEObj->HasFill() && !pTEObj->HasLine();
1714
1715 if (pTEObj->IsInserted() && bDelObj
1716 && pTEObj->GetObjInventor() == SdrInventor::Default && !bDontDeleteReally)
1717 {
1718 SdrObjKind eIdent = pTEObj->GetObjIdentifier();
1719 if (eIdent == SdrObjKind::Text)
1720 {
1721 pDelUndo = GetModel().GetSdrUndoFactory().CreateUndoDeleteObject(*pTEObj);
1722 }
1723 }
1724 }
1725 if (pTxtUndo)
1726 {
1727 if (bUndo)
1728 AddUndo(std::move(pTxtUndo));
1730 }
1731 if (pDelUndo != nullptr)
1732 {
1733 if (bUndo)
1734 {
1735 AddUndo(std::move(pDelUndo));
1736 }
1738 DBG_ASSERT(pTEObj->getParentSdrObjListFromSdrObject() != nullptr,
1739 "SdrObjEditView::SdrEndTextEdit(): Fatal: Object edited doesn't have an "
1740 "ObjList!");
1741 if (pTEObj->getParentSdrObjListFromSdrObject() != nullptr)
1742 {
1743 pTEObj->getParentSdrObjListFromSdrObject()->RemoveObject(pTEObj->GetOrdNum());
1744 CheckMarked(); // remove selection immediately...
1745 }
1746 }
1747 else if (bDelObj)
1748 { // for Writer: the app has to do the deletion itself.
1750 }
1751
1752 if (bUndo)
1753 EndUndo(); // EndUndo after Remove, in case UndoStack is deleted immediately
1754
1755 // Switch on any TextAnimation again after TextEdit
1756 if (pTEObj)
1757 {
1758 pTEObj->SetTextAnimationAllowed(true);
1759 }
1760
1761 // Since IsMarkHdlWhenTextEdit() is ignored, it is necessary
1762 // to call AdjustMarkHdl() always.
1763 AdjustMarkHdl();
1764 }
1765 // delete all OutlinerViews
1766 for (size_t i = pTEOutliner->GetViewCount(); i > 0;)
1767 {
1768 i--;
1769 OutlinerView* pOLV = pTEOutliner->GetView(i);
1770 sal_uInt16 nMorePix = pOLV->GetInvalidateMore() + 10;
1771 vcl::Window* pWin = pOLV->GetWindow();
1772 tools::Rectangle aRect(pOLV->GetOutputArea());
1773 pTEOutliner->RemoveView(i);
1774 if (!mbTextEditDontDelete || i != 0)
1775 {
1776 // may not own the zeroth one
1777 delete pOLV;
1778 }
1779 aRect.Union(aTextEditArea);
1780 aRect.Union(aMinTextEditArea);
1781 aRect = pWin->LogicToPixel(aRect);
1782 aRect.AdjustLeft(-nMorePix);
1783 aRect.AdjustTop(-nMorePix);
1784 aRect.AdjustRight(nMorePix);
1785 aRect.AdjustBottom(nMorePix);
1786 aRect = pWin->PixelToLogic(aRect);
1787 InvalidateOneWin(*pWin->GetOutDev(), aRect);
1788 pWin->GetOutDev()->SetFillColor();
1790 }
1791 // and now the Outliner itself
1793 delete pTEOutliner;
1794 else
1795 pTEOutliner->Clear();
1796 if (pTEWin != nullptr)
1797 {
1798 pTEWin->SetCursor(pTECursorBuffer);
1799 }
1802 {
1804 }
1805 // coverity[leaked_storage] - if pTEOutliner wasn't deleted it didn't really belong to us
1806 }
1807
1808 if (pTEObj && !pTEObj->getSdrModelFromSdrObject().isLocked() && pTEObj->GetBroadcaster())
1809 {
1810 SdrHint aHint(SdrHintKind::EndEdit, *pTEObj);
1811 const_cast<SfxBroadcaster*>(pTEObj->GetBroadcaster())->Broadcast(aHint);
1812 }
1813
1814 if (pUndoEditUndoManager)
1815 {
1816 if (bNeedToUndoSavedRedoTextEdit)
1817 {
1818 // undo the text edit action since it was created as part of an EndTextEdit
1819 // callback from undo itself. This needs to be done after the call to
1820 // FmFormView::SdrEndTextEdit since it gets created there
1821 pUndoEditUndoManager->Undo();
1822 }
1823
1824 // trigger the Undo which was not executed, but lead to this
1825 // end text edit
1826 pUndoEditUndoManager->Undo();
1827 }
1828
1829 return eRet;
1830}
1831
1832// info about TextEdit. Default is false.
1833bool SdrObjEditView::IsTextEdit() const { return mxWeakTextEditObj.get().is(); }
1834
1835// info about TextEditPageView. Default is 0L.
1837
1839{
1840 if (pWin == nullptr)
1841 return nullptr;
1842 if (mpTextEditOutliner == nullptr)
1843 return nullptr;
1844 OutlinerView* pNewView = nullptr;
1845 size_t nWinCount = mpTextEditOutliner->GetViewCount();
1846 for (size_t i = 0; i < nWinCount && pNewView == nullptr; i++)
1847 {
1848 OutlinerView* pView = mpTextEditOutliner->GetView(i);
1849 if (pView->GetWindow() == pWin)
1850 pNewView = pView;
1851 }
1852 return pNewView;
1853}
1854
1856{
1857 if (!(mxWeakTextEditObj.get() && pWin != nullptr && pWin != mpTextEditWin))
1858 return;
1859
1860 OutlinerView* pNewView = ImpFindOutlinerView(pWin);
1861 if (pNewView != nullptr && pNewView != mpTextEditOutlinerView)
1862 {
1863 if (mpTextEditOutlinerView != nullptr)
1864 {
1866 }
1867 mpTextEditOutlinerView = pNewView;
1868 mpTextEditWin = pWin;
1869 pWin->GrabFocus(); // Make the cursor blink here as well
1870 pNewView->ShowCursor();
1872 }
1873}
1874
1876{
1877 bool bOk = false;
1878 if (mxWeakTextEditObj.get())
1879 {
1880 tools::Rectangle aEditArea;
1881 if (OutlinerView* pOLV = mpTextEditOutliner->GetView(0))
1882 aEditArea.Union(pOLV->GetOutputArea());
1883
1884 if (aEditArea.Contains(rHit))
1885 { // check if any characters were actually hit
1886 const Point aPnt(rHit - aEditArea.TopLeft());
1887 tools::Long nHitTol = 2000;
1888 if (OutputDevice* pRef = mpTextEditOutliner->GetRefDevice())
1889 nHitTol = OutputDevice::LogicToLogic(nHitTol, MapUnit::Map100thMM,
1890 pRef->GetMapMode().GetMapUnit());
1891
1892 bOk = mpTextEditOutliner->IsTextPos(aPnt, static_cast<sal_uInt16>(nHitTol));
1893 }
1894 }
1895 return bOk;
1896}
1897
1899{
1900 bool bOk = false;
1902 {
1903 OutlinerView* pOLV = mpTextEditOutliner->GetView(0);
1904 if (pOLV)
1905 {
1906 vcl::Window* pWin = pOLV->GetWindow();
1907 if (pText != nullptr && pText->IsTextFrame() && pWin != nullptr)
1908 {
1909 sal_uInt16 nPixSiz = pOLV->GetInvalidateMore();
1911 aEditArea.Union(pOLV->GetOutputArea());
1912 if (!aEditArea.Contains(rHit))
1913 {
1914 Size aSiz(pWin->PixelToLogic(Size(nPixSiz, nPixSiz)));
1915 aEditArea.AdjustLeft(-(aSiz.Width()));
1916 aEditArea.AdjustTop(-(aSiz.Height()));
1917 aEditArea.AdjustRight(aSiz.Width());
1918 aEditArea.AdjustBottom(aSiz.Height());
1919 bOk = aEditArea.Contains(rHit);
1920 }
1921 }
1922 }
1923 }
1924 return bOk;
1925}
1926
1927std::unique_ptr<TextChainCursorManager>
1929{
1930 *bOutHandled = false;
1931
1933 if (!pTextObj)
1934 return nullptr;
1935
1936 if (!pTextObj->GetNextLinkInChain() && !pTextObj->GetPrevLinkInChain())
1937 return nullptr;
1938
1939 std::unique_ptr<TextChainCursorManager> pCursorManager(
1940 new TextChainCursorManager(this, pTextObj.get()));
1941 if (pCursorManager->HandleKeyEvent(rKEvt))
1942 {
1943 // Possibly do other stuff here if necessary...
1944 // XXX: Careful with the checks below (in KeyInput) for pWin and co. You should do them here I guess.
1945 *bOutHandled = true;
1946 }
1947
1948 return pCursorManager;
1949}
1950
1952{
1954 {
1955 /* Start special handling of keys within a chain */
1956 // We possibly move to another box before any handling
1957 bool bHandled = false;
1958 std::unique_ptr<TextChainCursorManager> xCursorManager(
1959 ImpHandleMotionThroughBoxesKeyInput(rKEvt, &bHandled));
1960 if (bHandled)
1961 return true;
1962 /* End special handling of keys within a chain */
1963
1964 if (mpTextEditOutlinerView->PostKeyEvent(rKEvt, pWin))
1965 {
1966 if (mpTextEditOutliner && mpTextEditOutliner->IsModified())
1967 GetModel().SetChanged();
1968
1969 /* Start chaining processing */
1971 ImpMoveCursorAfterChainingEvent(xCursorManager.get());
1972 /* End chaining processing */
1973
1974 if (pWin != nullptr && pWin != mpTextEditWin)
1975 SetTextEditWin(pWin);
1977 return true;
1978 }
1979 }
1980 return SdrGlueEditView::KeyInput(rKEvt, pWin);
1981}
1982
1984{
1985 if (mpTextEditOutlinerView != nullptr)
1986 {
1987 bool bPostIt = mpTextEditOutliner->IsInSelectionMode();
1988 if (!bPostIt)
1989 {
1990 Point aPt(rMEvt.GetPosPixel());
1991 if (pWin != nullptr)
1992 aPt = pWin->PixelToLogic(aPt);
1993 else if (mpTextEditWin != nullptr)
1994 aPt = mpTextEditWin->PixelToLogic(aPt);
1995 bPostIt = IsTextEditHit(aPt);
1996 }
1997 if (bPostIt)
1998 {
1999 Point aPixPos(rMEvt.GetPosPixel());
2000 if (pWin)
2001 {
2003 if (aPixPos.X() < aR.Left())
2004 aPixPos.setX(aR.Left());
2005 if (aPixPos.X() > aR.Right())
2006 aPixPos.setX(aR.Right());
2007 if (aPixPos.Y() < aR.Top())
2008 aPixPos.setY(aR.Top());
2009 if (aPixPos.Y() > aR.Bottom())
2010 aPixPos.setY(aR.Bottom());
2011 }
2012 MouseEvent aMEvt(aPixPos, rMEvt.GetClicks(), rMEvt.GetMode(), rMEvt.GetButtons(),
2013 rMEvt.GetModifier());
2015 {
2016 if (pWin != nullptr && pWin != mpTextEditWin->GetOutDev()
2017 && pWin->GetOutDevType() == OUTDEV_WINDOW)
2020 return true;
2021 }
2022 }
2023 }
2024 return SdrGlueEditView::MouseButtonDown(rMEvt, pWin);
2025}
2026
2028{
2029 if (mpTextEditOutlinerView != nullptr)
2030 {
2031 bool bPostIt = mpTextEditOutliner->IsInSelectionMode();
2032 if (!bPostIt)
2033 {
2034 Point aPt(rMEvt.GetPosPixel());
2035 if (pWin != nullptr)
2036 aPt = pWin->PixelToLogic(aPt);
2037 else if (mpTextEditWin != nullptr)
2038 aPt = mpTextEditWin->PixelToLogic(aPt);
2039 bPostIt = IsTextEditHit(aPt);
2040 }
2041 if (bPostIt && pWin)
2042 {
2043 Point aPixPos(rMEvt.GetPosPixel());
2045 if (aPixPos.X() < aR.Left())
2046 aPixPos.setX(aR.Left());
2047 if (aPixPos.X() > aR.Right())
2048 aPixPos.setX(aR.Right());
2049 if (aPixPos.Y() < aR.Top())
2050 aPixPos.setY(aR.Top());
2051 if (aPixPos.Y() > aR.Bottom())
2052 aPixPos.setY(aR.Bottom());
2053 MouseEvent aMEvt(aPixPos, rMEvt.GetClicks(), rMEvt.GetMode(), rMEvt.GetButtons(),
2054 rMEvt.GetModifier());
2056 {
2058 return true;
2059 }
2060 }
2061 }
2062 return SdrGlueEditView::MouseButtonUp(rMEvt, pWin);
2063}
2064
2066{
2067 if (mpTextEditOutlinerView != nullptr)
2068 {
2069 bool bSelMode = mpTextEditOutliner->IsInSelectionMode();
2070 bool bPostIt = bSelMode;
2071 if (!bPostIt)
2072 {
2073 Point aPt(rMEvt.GetPosPixel());
2074 if (pWin)
2075 aPt = pWin->PixelToLogic(aPt);
2076 else if (mpTextEditWin)
2077 aPt = mpTextEditWin->PixelToLogic(aPt);
2078 bPostIt = IsTextEditHit(aPt);
2079 }
2080 if (bPostIt)
2081 {
2082 Point aPixPos(rMEvt.GetPosPixel());
2084 if (pWin)
2085 aR = pWin->LogicToPixel(aR);
2086 else if (mpTextEditWin)
2087 aR = mpTextEditWin->LogicToPixel(aR);
2088 if (aPixPos.X() < aR.Left())
2089 aPixPos.setX(aR.Left());
2090 if (aPixPos.X() > aR.Right())
2091 aPixPos.setX(aR.Right());
2092 if (aPixPos.Y() < aR.Top())
2093 aPixPos.setY(aR.Top());
2094 if (aPixPos.Y() > aR.Bottom())
2095 aPixPos.setY(aR.Bottom());
2096 MouseEvent aMEvt(aPixPos, rMEvt.GetClicks(), rMEvt.GetMode(), rMEvt.GetButtons(),
2097 rMEvt.GetModifier());
2098 if (mpTextEditOutlinerView->MouseMove(aMEvt) && bSelMode)
2099 {
2101 return true;
2102 }
2103 }
2104 }
2105 return SdrGlueEditView::MouseMove(rMEvt, pWin);
2106}
2107
2109{
2110 // as long as OutlinerView returns a sal_Bool, it only gets CommandEventId::StartDrag
2111 if (mpTextEditOutlinerView != nullptr)
2112 {
2113 if (rCEvt.GetCommand() == CommandEventId::StartDrag)
2114 {
2115 bool bPostIt = mpTextEditOutliner->IsInSelectionMode() || !rCEvt.IsMouseEvent();
2116 if (!bPostIt && rCEvt.IsMouseEvent())
2117 {
2118 Point aPt(rCEvt.GetMousePosPixel());
2119 if (pWin != nullptr)
2120 aPt = pWin->PixelToLogic(aPt);
2121 else if (mpTextEditWin != nullptr)
2122 aPt = mpTextEditWin->PixelToLogic(aPt);
2123 bPostIt = IsTextEditHit(aPt);
2124 }
2125 if (bPostIt)
2126 {
2127 Point aPixPos(rCEvt.GetMousePosPixel());
2128 if (rCEvt.IsMouseEvent() && pWin)
2129 {
2132 if (aPixPos.X() < aR.Left())
2133 aPixPos.setX(aR.Left());
2134 if (aPixPos.X() > aR.Right())
2135 aPixPos.setX(aR.Right());
2136 if (aPixPos.Y() < aR.Top())
2137 aPixPos.setY(aR.Top());
2138 if (aPixPos.Y() > aR.Bottom())
2139 aPixPos.setY(aR.Bottom());
2140 }
2141 CommandEvent aCEvt(aPixPos, rCEvt.GetCommand(), rCEvt.IsMouseEvent());
2142 // Command is void at the OutlinerView, sadly
2144 if (pWin != nullptr && pWin != mpTextEditWin)
2145 SetTextEditWin(pWin);
2147 return true;
2148 }
2149 }
2150 else
2151 {
2154 {
2155 // It could execute CommandEventId::ExtTextInput, while SdrObjEditView::KeyInput
2156 // isn't called
2157 if (mpTextEditOutliner && mpTextEditOutliner->IsModified())
2158 GetModel().SetChanged();
2159 }
2160 return true;
2161 }
2162 }
2163 return SdrGlueEditView::Command(rCEvt, pWin);
2164}
2165
2167{
2168 bool bRet = false;
2169 if (mpTextEditOutliner != nullptr && mpTextEditOutlinerView != nullptr)
2170 {
2172 {
2173 const sal_Int32 nParaCnt = mpTextEditOutliner->GetParagraphCount();
2174 Paragraph* pLastPara
2175 = mpTextEditOutliner->GetParagraph(nParaCnt > 1 ? nParaCnt - 1 : 0);
2176
2178 if (aESel.nStartPara == 0 && aESel.nStartPos == 0 && aESel.nEndPara == (nParaCnt - 1))
2179 {
2180 if (mpTextEditOutliner->GetText(pLastPara).getLength() == aESel.nEndPos)
2181 bRet = true;
2182 }
2183 // in case the selection was done backwards
2184 if (!bRet && aESel.nEndPara == 0 && aESel.nEndPos == 0
2185 && aESel.nStartPara == (nParaCnt - 1))
2186 {
2187 if (mpTextEditOutliner->GetText(pLastPara).getLength() == aESel.nStartPos)
2188 bRet = true;
2189 }
2190 }
2191 else
2192 {
2193 bRet = true;
2194 }
2195 }
2196 return bRet;
2197}
2198
2200{
2201 if (mpTextEditOutlinerView != nullptr && mpTextEditWin != nullptr)
2202 {
2203 vcl::Cursor* pCsr = mpTextEditWin->GetCursor();
2204 if (pCsr != nullptr)
2205 {
2206 Size aSiz(pCsr->GetSize());
2207 if (!aSiz.IsEmpty())
2208 {
2210 }
2211 }
2212 }
2213}
2214
2216{
2217 SvtScriptType nScriptType = SvtScriptType::NONE;
2218
2219 if (IsTextEdit())
2220 {
2221 auto pText = mxWeakTextEditObj.get();
2222 if (pText->GetOutlinerParaObject())
2223 nScriptType = pText->GetOutlinerParaObject()->GetTextObject().GetScriptType();
2224
2227 }
2228 else
2229 {
2230 const size_t nMarkCount(GetMarkedObjectCount());
2231
2232 for (size_t i = 0; i < nMarkCount; ++i)
2233 {
2235
2236 if (pParaObj)
2237 {
2238 nScriptType |= pParaObj->GetTextObject().GetScriptType();
2239 }
2240 }
2241 }
2242
2243 if (nScriptType == SvtScriptType::NONE)
2244 nScriptType = SvtScriptType::LATIN;
2245
2246 return nScriptType;
2247}
2248
2249void SdrObjEditView::GetAttributes(SfxItemSet& rTargetSet, bool bOnlyHardAttr) const
2250{
2251 if (mxSelectionController.is())
2252 if (mxSelectionController->GetAttributes(rTargetSet, bOnlyHardAttr))
2253 return;
2254
2255 if (IsTextEdit())
2256 {
2258 "SdrObjEditView::GetAttributes(): mpTextEditOutlinerView=NULL");
2259 DBG_ASSERT(mpTextEditOutliner != nullptr,
2260 "SdrObjEditView::GetAttributes(): mpTextEditOutliner=NULL");
2261
2262 auto pText = mxWeakTextEditObj.get();
2263 // take care of bOnlyHardAttr(!)
2264 if (!bOnlyHardAttr && pText->GetStyleSheet())
2265 rTargetSet.Put(pText->GetStyleSheet()->GetItemSet());
2266
2267 // add object attributes
2268 rTargetSet.Put(pText->GetMergedItemSet());
2269
2271 {
2272 // FALSE= regard InvalidItems as "holes," not as Default
2273 rTargetSet.Put(mpTextEditOutlinerView->GetAttribs(), false);
2274 }
2275
2276 if (GetMarkedObjectCount() == 1 && GetMarkedObjectByIndex(0) == pText.get())
2277 {
2279 }
2280 }
2281 else
2282 {
2283 SdrGlueEditView::GetAttributes(rTargetSet, bOnlyHardAttr);
2284 }
2285}
2286
2287bool SdrObjEditView::SetAttributes(const SfxItemSet& rSet, bool bReplaceAll)
2288{
2289 bool bRet = false;
2291 bool bTextEdit = mpTextEditOutlinerView != nullptr && pTextEditObj != nullptr;
2292 bool bAllTextSelected = ImpIsTextEditAllSelected();
2293 const SfxItemSet* pSet = &rSet;
2294
2295 if (!bTextEdit)
2296 {
2297 // no TextEdit active -> all Items to drawing object
2298 if (mxSelectionController.is())
2299 bRet = mxSelectionController->SetAttributes(*pSet, bReplaceAll);
2300
2301 if (!bRet)
2302 {
2303 SdrGlueEditView::SetAttributes(*pSet, bReplaceAll);
2304 bRet = true;
2305 }
2306 }
2307 else
2308 {
2309#ifdef DBG_UTIL
2310 {
2311 bool bHasEEFeatureItems = false;
2312 SfxItemIter aIter(rSet);
2313 for (const SfxPoolItem* pItem = aIter.GetCurItem(); !bHasEEFeatureItems && pItem;
2314 pItem = aIter.NextItem())
2315 {
2316 if (!IsInvalidItem(pItem))
2317 {
2318 sal_uInt16 nW = pItem->Which();
2319 if (nW >= EE_FEATURE_START && nW <= EE_FEATURE_END)
2320 bHasEEFeatureItems = true;
2321 }
2322 }
2323
2324 if (bHasEEFeatureItems)
2325 {
2326 std::unique_ptr<weld::MessageDialog> xInfoBox(Application::CreateMessageDialog(
2327 nullptr, VclMessageType::Info, VclButtonsType::Ok,
2328 "SdrObjEditView::SetAttributes(): Setting EE_FEATURE items "
2329 "at the SdrView does not make sense! It only leads to "
2330 "overhead and unreadable documents."));
2331 xInfoBox->run();
2332 }
2333 }
2334#endif
2335
2336 bool bOnlyEEItems;
2337 bool bNoEEItems = !SearchOutlinerItems(*pSet, bReplaceAll, &bOnlyEEItems);
2338 // everything selected? -> attributes to the border, too
2339 // if no EEItems, attributes to the border only
2340 if (bAllTextSelected || bNoEEItems)
2341 {
2342 if (mxSelectionController.is())
2343 bRet = mxSelectionController->SetAttributes(*pSet, bReplaceAll);
2344
2345 if (!bRet)
2346 {
2347 const bool bUndo = IsUndoEnabled();
2348
2349 if (bUndo)
2350 {
2351 BegUndo(ImpGetDescriptionString(STR_EditSetAttributes));
2352 AddUndo(GetModel().GetSdrUndoFactory().CreateUndoGeoObject(*pTextEditObj));
2353
2354 // If this is a text object also rescue the OutlinerParaObject since
2355 // applying attributes to the object may change text layout when
2356 // multiple portions exist with multiple formats. If an OutlinerParaObject
2357 // really exists and needs to be rescued is evaluated in the undo
2358 // implementation itself.
2359 bool bRescueText(pTextEditObj);
2360
2361 AddUndo(GetModel().GetSdrUndoFactory().CreateUndoAttrObject(
2362 *pTextEditObj, false, !bNoEEItems || bRescueText));
2363 EndUndo();
2364 }
2365
2366 pTextEditObj->SetMergedItemSetAndBroadcast(*pSet, bReplaceAll);
2367
2368 FlushComeBackTimer(); // to set ModeHasChanged immediately
2369 }
2370 }
2371 else if (!bOnlyEEItems)
2372 {
2373 // Otherwise split Set, if necessary.
2374 // Now we build an ItemSet aSet that doesn't contain EE_Items from
2375 // *pSet (otherwise it would be a copy).
2376 WhichRangesContainer pNewWhichTable
2378 SfxItemSet aSet(GetModel().GetItemPool(), std::move(pNewWhichTable));
2379 SfxWhichIter aIter(aSet);
2380 sal_uInt16 nWhich = aIter.FirstWhich();
2381 while (nWhich != 0)
2382 {
2383 const SfxPoolItem* pItem;
2384 SfxItemState eState = pSet->GetItemState(nWhich, false, &pItem);
2385 if (eState == SfxItemState::SET)
2386 aSet.Put(*pItem);
2387 nWhich = aIter.NextWhich();
2388 }
2389
2390 if (mxSelectionController.is())
2391 bRet = mxSelectionController->SetAttributes(aSet, bReplaceAll);
2392
2393 if (!bRet)
2394 {
2395 if (IsUndoEnabled())
2396 {
2397 BegUndo(ImpGetDescriptionString(STR_EditSetAttributes));
2398 AddUndo(GetModel().GetSdrUndoFactory().CreateUndoGeoObject(*pTextEditObj));
2399 AddUndo(GetModel().GetSdrUndoFactory().CreateUndoAttrObject(*pTextEditObj));
2400 EndUndo();
2401 }
2402
2403 pTextEditObj->SetMergedItemSetAndBroadcast(aSet, bReplaceAll);
2404
2405 if (GetMarkedObjectCount() == 1 && GetMarkedObjectByIndex(0) == pTextEditObj.get())
2406 {
2408 }
2409 }
2411 }
2412 if (!bNoEEItems)
2413 {
2414 // and now the attributes to the EditEngine
2415 if (bReplaceAll)
2416 {
2418 }
2420
2422 if (pTEOutliner && pTEOutliner->IsModified())
2423 GetModel().SetChanged();
2424
2426 }
2427 bRet = true;
2428 }
2429 return bRet;
2430}
2431
2433{
2434 SfxStyleSheet* pSheet = nullptr;
2435
2436 if (mxSelectionController.is())
2437 {
2438 if (mxSelectionController->GetStyleSheet(pSheet))
2439 return pSheet;
2440 }
2441
2443 {
2445 }
2446 else
2447 {
2449 }
2450 return pSheet;
2451}
2452
2453void SdrObjEditView::SetStyleSheet(SfxStyleSheet* pStyleSheet, bool bDontRemoveHardAttr)
2454{
2455 if (mxSelectionController.is())
2456 {
2457 if (mxSelectionController->SetStyleSheet(pStyleSheet, bDontRemoveHardAttr))
2458 return;
2459 }
2460
2461 // if we are currently in edit mode we must also set the stylesheet
2462 // on all paragraphs in the Outliner for the edit view
2463 if (nullptr != mpTextEditOutlinerView)
2464 {
2466
2467 const sal_Int32 nParaCount = pOutliner->GetParagraphCount();
2468 for (sal_Int32 nPara = 0; nPara < nParaCount; nPara++)
2469 {
2470 pOutliner->SetStyleSheet(nPara, pStyleSheet);
2471 }
2472 }
2473
2474 SdrGlueEditView::SetStyleSheet(pStyleSheet, bDontRemoveHardAttr);
2475}
2476
2478{
2479 SdrGlueEditView::AddDeviceToPaintView(rNewDev, pWindow);
2480
2482 && rNewDev.GetOutDevType() == OUTDEV_WINDOW)
2483 {
2484 OutlinerView* pOutlView = ImpMakeOutlinerView(rNewDev.GetOwnerWindow(), nullptr);
2485 mpTextEditOutliner->InsertView(pOutlView);
2486 }
2487}
2488
2490{
2492
2494 && rOldDev.GetOutDevType() == OUTDEV_WINDOW)
2495 {
2496 for (size_t i = mpTextEditOutliner->GetViewCount(); i > 0;)
2497 {
2498 i--;
2499 OutlinerView* pOLV = mpTextEditOutliner->GetView(i);
2500 if (pOLV && pOLV->GetWindow() == rOldDev.GetOwnerWindow())
2501 {
2502 mpTextEditOutliner->RemoveView(i);
2503 }
2504 }
2505 }
2506
2507 lcl_RemoveTextEditOutlinerViews(this, GetSdrPageView(), &rOldDev);
2508}
2509
2511{
2512 return mpTextEditOutliner != nullptr && mpTextEditOutliner->IsInSelectionMode();
2513}
2514
2515// MacroMode
2516
2517void SdrObjEditView::BegMacroObj(const Point& rPnt, short nTol, SdrObject* pObj, SdrPageView* pPV,
2518 vcl::Window* pWin)
2519{
2520 BrkMacroObj();
2521 if (pObj != nullptr && pPV != nullptr && pWin != nullptr && pObj->HasMacro())
2522 {
2523 nTol = ImpGetHitTolLogic(nTol, nullptr);
2524 pMacroObj = pObj;
2525 pMacroPV = pPV;
2526 pMacroWin = pWin;
2527 mbMacroDown = false;
2528 nMacroTol = sal_uInt16(nTol);
2529 aMacroDownPos = rPnt;
2530 MovMacroObj(rPnt);
2531 }
2532}
2533
2535{
2536 if (pMacroObj != nullptr && mbMacroDown)
2537 {
2538 SdrObjMacroHitRec aHitRec;
2539 aHitRec.aPos = rUpPos;
2540 aHitRec.nTol = nMacroTol;
2541 aHitRec.pVisiLayer = &pMacroPV->GetVisibleLayers();
2542 aHitRec.pPageView = pMacroPV;
2543 pMacroObj->PaintMacro(*pMacroWin->GetOutDev(), tools::Rectangle(), aHitRec);
2544 mbMacroDown = false;
2545 }
2546}
2547
2549{
2550 if (pMacroObj != nullptr && !mbMacroDown)
2551 {
2552 SdrObjMacroHitRec aHitRec;
2553 aHitRec.aPos = rDownPos;
2554 aHitRec.nTol = nMacroTol;
2555 aHitRec.pVisiLayer = &pMacroPV->GetVisibleLayers();
2556 aHitRec.pPageView = pMacroPV;
2557 pMacroObj->PaintMacro(*pMacroWin->GetOutDev(), tools::Rectangle(), aHitRec);
2558 mbMacroDown = true;
2559 }
2560}
2561
2563{
2564 if (pMacroObj == nullptr)
2565 return;
2566
2567 SdrObjMacroHitRec aHitRec;
2568 aHitRec.aPos = rPnt;
2569 aHitRec.nTol = nMacroTol;
2570 aHitRec.pVisiLayer = &pMacroPV->GetVisibleLayers();
2571 aHitRec.pPageView = pMacroPV;
2572 bool bDown = pMacroObj->IsMacroHit(aHitRec);
2573 if (bDown)
2574 ImpMacroDown(rPnt);
2575 else
2576 ImpMacroUp(rPnt);
2577}
2578
2580{
2581 if (pMacroObj != nullptr)
2582 {
2584 pMacroObj = nullptr;
2585 pMacroPV = nullptr;
2586 pMacroWin = nullptr;
2587 }
2588}
2589
2591{
2592 if (pMacroObj != nullptr && mbMacroDown)
2593 {
2595 SdrObjMacroHitRec aHitRec;
2596 aHitRec.aPos = aMacroDownPos;
2597 aHitRec.nTol = nMacroTol;
2598 aHitRec.pVisiLayer = &pMacroPV->GetVisibleLayers();
2599 aHitRec.pPageView = pMacroPV;
2600 bool bRet = pMacroObj->DoMacro(aHitRec);
2601 pMacroObj = nullptr;
2602 pMacroPV = nullptr;
2603 pMacroWin = nullptr;
2604 return bRet;
2605 }
2606 else
2607 {
2608 BrkMacroObj();
2609 return false;
2610 }
2611}
2612
2615void SdrObjEditView::getTextSelection(css::uno::Any& rSelection)
2616{
2617 if (!IsTextEdit())
2618 return;
2619
2620 OutlinerView* pOutlinerView = GetTextEditOutlinerView();
2621 if (!(pOutlinerView && pOutlinerView->HasSelection()))
2622 return;
2623
2624 SdrObject* pObj = GetTextEditObject();
2625
2626 if (!pObj)
2627 return;
2628
2629 css::uno::Reference<css::text::XText> xText(pObj->getUnoShape(), css::uno::UNO_QUERY);
2630 if (xText.is())
2631 {
2632 SvxUnoTextBase* pRange = comphelper::getFromUnoTunnel<SvxUnoTextBase>(xText);
2633 if (pRange)
2634 {
2635 rSelection <<= pRange->createTextCursorBySelection(pOutlinerView->GetSelection());
2636 }
2637 }
2638}
2639
2640/* check if we have a single selection and that single object likes
2641 to handle the mouse and keyboard events itself
2642
2643 TODO: the selection controller should be queried from the
2644 object specific view contact. Currently this method only
2645 works for tables.
2646*/
2648{
2650
2651 if (mxSelectionController.is())
2652 {
2654 mxSelectionController->onSelectionHasChanged();
2655 }
2656
2657 mxSelectionController.clear();
2658
2659 const SdrMarkList& rMarkList = GetMarkedObjectList();
2660 if (rMarkList.GetMarkCount() != 1)
2661 return;
2662
2663 const SdrObject* pObj(rMarkList.GetMark(0)->GetMarkedSdrObj());
2664 SdrView* pView(dynamic_cast<SdrView*>(this));
2665
2666 // check for table
2667 if (pObj && pView && (pObj->GetObjInventor() == SdrInventor::Default)
2668 && (pObj->GetObjIdentifier() == SdrObjKind::Table))
2669 {
2671 *pView, static_cast<const sdr::table::SdrTableObj&>(*pObj), mxLastSelectionController);
2672
2673 if (mxSelectionController.is())
2674 {
2676 mxSelectionController->onSelectionHasChanged();
2677 }
2678 }
2679}
2680
2681IMPL_LINK(SdrObjEditView, EndPasteOrDropHdl, PasteOrDropInfos*, pInfo, void)
2682{
2683 OnEndPasteOrDrop(pInfo);
2684}
2685
2686IMPL_LINK(SdrObjEditView, BeginPasteOrDropHdl, PasteOrDropInfos*, pInfo, void)
2687{
2688 OnBeginPasteOrDrop(pInfo);
2689}
2690
2692{
2693 // applications can derive from these virtual methods to do something before a drop or paste operation
2694}
2695
2697{
2698 // applications can derive from these virtual methods to do something before a drop or paste operation
2699}
2700
2702{
2703 sal_uInt16 nLevel = 0xFFFF;
2704 if (IsTextEdit())
2705 {
2707 "SdrObjEditView::GetAttributes(): mpTextEditOutlinerView=NULL");
2708 DBG_ASSERT(mpTextEditOutliner != nullptr,
2709 "SdrObjEditView::GetAttributes(): mpTextEditOutliner=NULL");
2711 {
2712 //start and end position
2714 sal_uInt16 nStartPara = ::std::min(aSelect.nStartPara, aSelect.nEndPara);
2715 sal_uInt16 nEndPara = ::std::max(aSelect.nStartPara, aSelect.nEndPara);
2716 //get level from each paragraph
2717 nLevel = 0;
2718 for (sal_uInt16 nPara = nStartPara; nPara <= nEndPara; nPara++)
2719 {
2720 sal_uInt16 nParaDepth
2721 = 1 << static_cast<sal_uInt16>(mpTextEditOutliner->GetDepth(nPara));
2722 if (!(nLevel & nParaDepth))
2723 nLevel += nParaDepth;
2724 }
2725 //reduce one level for Outliner Object
2726 //if( nLevel > 0 && GetTextEditObject()->GetObjIdentifier() == OBJ_OUTLINETEXT )
2727 // nLevel = nLevel >> 1;
2728 //no bullet paragraph selected
2729 if (nLevel == 0)
2730 nLevel = 0xFFFF;
2731 }
2732 }
2733 return nLevel;
2734}
2735
2737 SdrObjKind nObjectIdentifier)
2738{
2739 if (nObjectInventor != SdrInventor::Default && nObjectInventor != SdrInventor::E3d)
2740 return false;
2741 switch (nObjectIdentifier)
2742 {
2743 case SdrObjKind::NONE:
2744 case SdrObjKind::Group:
2745 return false;
2746 case SdrObjKind::Line:
2758 case SdrObjKind::Text:
2762 case SdrObjKind::OLE2:
2763 case SdrObjKind::Table:
2764 return true;
2766 return false;
2767 case SdrObjKind::Edge:
2770 return true;
2771 case SdrObjKind::Page:
2774 case SdrObjKind::UNO:
2775 return false;
2777 return true;
2778 default:
2779 return false;
2780 }
2781}
2782
2783static const WhichRangesContainer& GetFormatRangeImpl(bool bTextOnly)
2784{
2785 static const WhichRangesContainer gFull(
2788 SDRATTR_MISC_LAST, // table cell formats
2792
2793 static const WhichRangesContainer gTextOnly(
2795 EE_CHAR_END>);
2796
2797 return bTextOnly ? gTextOnly : gFull;
2798}
2799
2800void SdrObjEditView::TakeFormatPaintBrush(std::shared_ptr<SfxItemSet>& rFormatSet)
2801{
2802 const SdrMarkList& rMarkList = GetMarkedObjectList();
2803 if (rMarkList.GetMarkCount() <= 0)
2804 return;
2805
2807
2808 rFormatSet = std::make_shared<SfxItemSet>(GetModel().GetItemPool(),
2809 GetFormatRangeImpl(pOLV != nullptr));
2810 if (pOLV)
2811 {
2812 rFormatSet->Put(pOLV->GetAttribs());
2813 }
2814 else
2815 {
2816 const bool bOnlyHardAttr = false;
2817 rFormatSet->Put(GetAttrFromMarked(bOnlyHardAttr));
2818 }
2819
2820 // check for cloning from table cell, in which case we need to copy cell-specific formatting attributes
2821 const SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj();
2822 if (pObj && (pObj->GetObjInventor() == SdrInventor::Default)
2823 && (pObj->GetObjIdentifier() == SdrObjKind::Table))
2824 {
2825 auto pTable = static_cast<const sdr::table::SdrTableObj*>(pObj);
2826 if (mxSelectionController.is() && pTable->getActiveCell().is())
2827 {
2828 mxSelectionController->GetAttributes(*rFormatSet, false);
2829 }
2830 }
2831}
2832
2834 const SfxItemSet& rSourceSet, const SfxItemSet& rTargetSet,
2835 bool bNoCharacterFormats, bool bNoParagraphFormats)
2836{
2837 SfxItemSet aPaintSet(rPool, pRanges);
2838
2839 for (const auto& pRange : pRanges)
2840 {
2841 sal_uInt16 nWhich = pRange.first;
2842 const sal_uInt16 nLastWhich = pRange.second;
2843
2844 if (bNoCharacterFormats && (nWhich == EE_CHAR_START))
2845 continue;
2846
2847 if (bNoParagraphFormats && (nWhich == EE_PARA_START))
2848 continue;
2849
2850 for (; nWhich <= nLastWhich; nWhich++)
2851 {
2852 const SfxPoolItem* pSourceItem = rSourceSet.GetItem(nWhich);
2853 const SfxPoolItem* pTargetItem = rTargetSet.GetItem(nWhich);
2854
2855 if ((pSourceItem && !pTargetItem)
2856 || (pSourceItem && pTargetItem && *pSourceItem != *pTargetItem))
2857 {
2858 aPaintSet.Put(*pSourceItem);
2859 }
2860 }
2861 }
2862 return aPaintSet;
2863}
2864
2866 SdrText* pText, bool bNoCharacterFormats,
2867 bool bNoParagraphFormats)
2868{
2869 OutlinerParaObject* pParaObj = pText ? pText->GetOutlinerParaObject() : nullptr;
2870 if (!pParaObj)
2871 return;
2872
2873 SdrOutliner& rOutliner = rTextObj.ImpGetDrawOutliner();
2874 rOutliner.SetText(*pParaObj);
2875
2876 sal_Int32 nParaCount(rOutliner.GetParagraphCount());
2877
2878 if (!nParaCount)
2879 return;
2880
2881 for (sal_Int32 nPara = 0; nPara < nParaCount; nPara++)
2882 {
2883 if (!bNoCharacterFormats)
2884 rOutliner.RemoveCharAttribs(nPara);
2885
2886 SfxItemSet aSet(rOutliner.GetParaAttribs(nPara));
2887 aSet.Put(CreatePaintSet(GetFormatRangeImpl(true), *aSet.GetPool(), rFormatSet, aSet,
2888 bNoCharacterFormats, bNoParagraphFormats));
2889 rOutliner.SetParaAttribs(nPara, aSet);
2890 }
2891
2892 std::optional<OutlinerParaObject> pTemp = rOutliner.CreateParaObject(0, nParaCount);
2893 rOutliner.Clear();
2894
2895 rTextObj.NbcSetOutlinerParaObjectForText(std::move(pTemp), pText);
2896}
2897
2899{
2901 {
2902 if (typeid(mpTextEditOutliner->GetUndoManager()) != typeid(EditUndoManager))
2903 {
2904 // Non-owning pointer, clear it.
2905 mpTextEditOutliner->SetUndoManager(nullptr);
2906 }
2907 }
2908
2909 mpOldTextEditUndoManager = nullptr;
2910}
2911
2912void SdrObjEditView::ApplyFormatPaintBrush(SfxItemSet& rFormatSet, bool bNoCharacterFormats,
2913 bool bNoParagraphFormats)
2914{
2915 if (mxSelectionController.is()
2916 && mxSelectionController->ApplyFormatPaintBrush(rFormatSet, bNoCharacterFormats,
2917 bNoParagraphFormats))
2918 {
2919 return;
2920 }
2921
2923 const SdrMarkList& rMarkList = GetMarkedObjectList();
2924 if (!pOLV)
2925 {
2926 SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj();
2927 const SfxItemSet& rShapeSet = pObj->GetMergedItemSet();
2928
2929 // if not in text edit mode (aka the user selected text or clicked on a word)
2930 // apply formatting attributes to selected shape
2931 // All formatting items (see ranges above) that are unequal in selected shape and
2932 // the format paintbrush are hard set on the selected shape.
2933
2934 const WhichRangesContainer& pRanges = rFormatSet.GetRanges();
2935 bool bTextOnly = true;
2936
2937 for (const auto& pRange : pRanges)
2938 {
2939 if ((pRange.first != EE_PARA_START) && (pRange.first != EE_CHAR_START))
2940 {
2941 bTextOnly = false;
2942 break;
2943 }
2944 }
2945
2946 if (!bTextOnly)
2947 {
2948 SfxItemSet aPaintSet(CreatePaintSet(GetFormatRangeImpl(false), *rShapeSet.GetPool(),
2949 rFormatSet, rShapeSet, bNoCharacterFormats,
2950 bNoParagraphFormats));
2951 SetAttrToMarked(aPaintSet, false /*bReplaceAll*/);
2952 }
2953
2954 // now apply character and paragraph formatting to text, if the shape has any
2955 SdrTextObj* pTextObj = DynCastSdrTextObj(pObj);
2956 if (pTextObj)
2957 {
2958 sal_Int32 nText = pTextObj->getTextCount();
2959
2960 while (--nText >= 0)
2961 {
2962 SdrText* pText = pTextObj->getText(nText);
2963 ApplyFormatPaintBrushToText(rFormatSet, *pTextObj, pText, bNoCharacterFormats,
2964 bNoParagraphFormats);
2965 }
2966 }
2967 }
2968 else
2969 {
2970 ::Outliner* pOutliner = pOLV->GetOutliner();
2971 if (pOutliner)
2972 {
2973 const EditEngine& rEditEngine = pOutliner->GetEditEngine();
2974
2975 ESelection aSel(pOLV->GetSelection());
2976 if (!aSel.HasRange())
2977 pOLV->SetSelection(rEditEngine.GetWord(aSel, css::i18n::WordType::DICTIONARY_WORD));
2978
2979 const bool bRemoveParaAttribs = !bNoParagraphFormats;
2980 pOLV->RemoveAttribsKeepLanguages(bRemoveParaAttribs);
2981 SfxItemSet aSet(pOLV->GetAttribs());
2982 SfxItemSet aPaintSet(CreatePaintSet(GetFormatRangeImpl(true), *aSet.GetPool(),
2983 rFormatSet, aSet, bNoCharacterFormats,
2984 bNoParagraphFormats));
2985 pOLV->SetAttribs(aPaintSet);
2986 }
2987 }
2988
2989 // check for cloning to table cell, in which case we need to copy cell-specific formatting attributes
2990 SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj();
2991 if (pObj && (pObj->GetObjInventor() == SdrInventor::Default)
2992 && (pObj->GetObjIdentifier() == SdrObjKind::Table))
2993 {
2994 auto pTable = static_cast<sdr::table::SdrTableObj*>(pObj);
2995 if (pTable->getActiveCell().is() && mxSelectionController.is())
2996 {
2997 mxSelectionController->SetAttributes(rFormatSet, false);
2998 }
2999 }
3000}
3001
3002/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
::rtl::Reference< IEventProcessor > xProcessor
B2DRange maRange
static const AllSettings & GetSettings()
static weld::MessageDialog * CreateMessageDialog(weld::Widget *pParent, VclMessageType eMessageType, VclButtonsType eButtonType, const OUString &rPrimaryMessage, const ILibreOfficeKitNotifier *pNotifier=nullptr)
basegfx::BColor getBColor() const
CommandEventId GetCommand() const
const Point & GetMousePosPixel() const
bool IsMouseEvent() const
OUString GetWord(sal_Int32 nPara, sal_Int32 nIndex)
virtual SvtScriptType GetScriptType() const=0
void SetNegativeX(bool bSet)
void setEditViewCallbacks(EditViewCallbacks *pEditViewCallbacks)
MouseEventModifiers GetMode() const
sal_uInt16 GetModifier() const
sal_uInt16 GetClicks() const
sal_uInt16 GetButtons() const
const Point & GetPosPixel() const
const EditTextObject & GetTextObject() const
bool MouseMove(const MouseEvent &)
void SetEndCutPasteLinkHdl(const Link< LinkParamNone *, void > &rLink)
bool Command(const CommandEvent &rCEvt)
void SetSelection(const ESelection &)
SvtScriptType GetSelectedScriptType() const
void Paint(const tools::Rectangle &rRect, OutputDevice *pTargetDevice=nullptr)
void SetControlWord(EVControlBits nWord)
bool HasSelection() const
bool MouseButtonUp(const MouseEvent &)
void RegisterViewShell(OutlinerViewShell *pViewShell)
void SetOutputArea(const tools::Rectangle &rRect)
void SetBackgroundColor(const Color &rColor)
vcl::Window * GetWindow() const
void RemoveAttribs(bool bRemoveParaAttribs, bool bKeepLanguages=false)
const SfxStyleSheet * GetStyleSheet() const
tools::Rectangle const & GetOutputArea() const
void HideCursor(bool bDeactivate=false)
ESelection GetSelection() const
bool PostKeyEvent(const KeyEvent &rKEvt, vcl::Window const *pFrameWin=nullptr)
EVControlBits GetControlWord() const
EEAnchorMode GetAnchorMode() const
SfxItemSet GetAttribs()
void SetWindow(vcl::Window *pWindow)
Outliner * GetOutliner() const
void SetAttribs(const SfxItemSet &)
bool MouseButtonDown(const MouseEvent &)
void RemoveAttribsKeepLanguages(bool bRemoveParaAttribs)
sal_uInt16 GetInvalidateMore() const
void SetAnchorMode(EEAnchorMode eMode)
void SetInvalidateMore(sal_uInt16 nPixel)
Color const & GetBackgroundColor() const
EditView & GetEditView() const
void ShowCursor(bool bGotoCursor=true, bool bActivate=false)
void SetText(const OutlinerParaObject &)
const EditEngine & GetEditEngine() const
std::optional< OutlinerParaObject > CreateParaObject(sal_Int32 nStartPara=0, sal_Int32 nParaCount=EE_PARA_ALL) const
void Clear()
void SetStyleSheet(sal_Int32 nPara, SfxStyleSheet *pStyle)
bool SetUpdateLayout(bool bUpdate)
OutlinerView * GetView(size_t nIndex) const
void SetParaAttribs(sal_Int32 nPara, const SfxItemSet &)
const Link< EditFieldInfo *, void > & GetCalcFieldValueHdl() const
SfxItemSet const & GetParaAttribs(sal_Int32 nPara) const
bool IsVertical() const
void RemoveCharAttribs(sal_Int32 nPara, sal_uInt16 nWhich=0)
size_t GetViewCount() const
bool IsModified() const
bool IsTopToBottom() const
sal_Int32 GetParagraphCount() const
void EnableMapMode(bool bEnable=true)
SAL_WARN_UNUSED_RESULT Point PixelToLogic(const Point &rDevicePt) const
SAL_WARN_UNUSED_RESULT Point LogicToLogic(const Point &rPtSource, const MapMode *pMapModeSource, const MapMode *pMapModeDest) const
void SetLineColor()
void SetFillColor()
SAL_WARN_UNUSED_RESULT Point LogicToPixel(const Point &rLogicPt) const
OutDevType GetOutDevType() const
virtual vcl::Window * GetOwnerWindow() const
bool IsMapModeEnabled() const
constexpr tools::Long Y() const
void setX(tools::Long nX)
void setY(tools::Long nY)
constexpr tools::Long X() const
SfxItemSet GetAttrFromMarked(bool bOnlyHardAttr) const
Definition: svdedtv1.cxx:891
bool IsUndoEnabled() const
Definition: svdedtv.cxx:1056
virtual void MarkListHasChanged() override
Definition: svdedtv.cxx:371
void SetAttrToMarked(const SfxItemSet &rAttr, bool bReplaceAll)
Definition: svdedtv1.cxx:1063
void SetNotPersistAttrToMarked(const SfxItemSet &rAttr)
Definition: svdedtv1.cxx:686
SfxStyleSheet * GetStyleSheet() const
Definition: svdedtv1.cxx:1351
void AddUndo(std::unique_ptr< SdrUndoAction > pUndo)
Definition: svdedtv.hxx:196
void BegUndo()
Definition: svdedtv.hxx:178
void SetStyleSheet(SfxStyleSheet *pStyleSheet, bool bDontRemoveHardAttr)
Definition: svdedtv1.cxx:1360
void SetAttributes(const SfxItemSet &rSet, bool bReplaceAll)
Definition: svdedtv1.cxx:1342
virtual void ModelHasChanged() override
Definition: svdedtv.cxx:377
void MergeNotPersistAttrFromMarked(SfxItemSet &rAttr) const
Definition: svdedtv1.cxx:784
void GetAttributes(SfxItemSet &rTargetSet, bool bOnlyHardAttr) const
Definition: svdedtv1.cxx:1330
void EndUndo()
Definition: svdedtv.cxx:295
sal_uInt16 GetHdlSize() const
Definition: svdhdl.hxx:463
void SetMoveOutside(bool bOn)
Definition: svdhdl.cxx:2206
SdrHintKind GetKind() const
Definition: svdmodel.hxx:133
bool IsSet(SdrLayerID a) const
Definition: svdsob.hxx:69
size_t GetMarkCount() const
Definition: svdmark.hxx:178
void SetNameDirty()
Definition: svdmark.hxx:193
SdrMark * GetMark(size_t nNum) const
Definition: svdmark.cxx:230
virtual SfxViewShell * GetSfxViewShell() const
Get access to the view shell owning this draw view, if any.
Definition: svdmrkv.cxx:1834
OUString ImpGetDescriptionString(TranslateId pStrCacheID, ImpGetDescriptionOptions nOpt=ImpGetDescriptionOptions::NONE) const
Definition: svdmrkv.cxx:2656
const SdrMarkList & GetMarkedObjectList() const
Definition: svdmrkv.hxx:258
virtual void EndAction() override
Definition: svdmrkv.cxx:313
SdrObject * GetMarkedObjectByIndex(size_t nNum) const
Definition: svdmrkv.hxx:263
SdrHdlList maHdlList
Definition: svdmrkv.hxx:107
SdrMarkList & GetMarkedObjectListWriteAccess()
Definition: svdmrkv.hxx:254
virtual bool IsAction() const override
Definition: svdmrkv.cxx:290
size_t GetMarkedObjectCount() const
Definition: svdmrkv.hxx:264
bool mbNegativeX
Definition: svdmrkv.hxx:134
virtual void Notify(SfxBroadcaster &rBC, const SfxHint &rHint) override
Definition: svdmrkv.cxx:199
virtual void BckAction() override
Definition: svdmrkv.cxx:331
void CheckMarked()
Definition: svdmrkv.cxx:1839
virtual void MovAction(const Point &rPnt) override
Definition: svdmrkv.cxx:295
virtual void HideSdrPage() override
Definition: svdmrkv.cxx:366
virtual void BrkAction() override
Definition: svdmrkv.cxx:339
bool getPossibleGridOffsetForSdrObject(basegfx::B2DVector &rOffset, const SdrObject *pObj, const SdrPageView *pPV) const
Definition: svdmrkv.cxx:2227
void AdjustMarkHdl(SfxViewShell *pOtherShell=nullptr)
Definition: svdmrkv.cxx:2614
virtual void TakeActionRect(tools::Rectangle &rRect) const override
Definition: svdmrkv.cxx:347
virtual bool MouseMove(const MouseEvent &rMEvt, OutputDevice *pWin) override
handle mouse over effects for handles
Definition: svdmrkv.cxx:1666
SdrObject * GetMarkedSdrObj() const
Definition: svdmark.hxx:68
sal_uInt16 GetDefaultTabulator() const
Definition: svdmodel.hxx:341
virtual void SetChanged(bool bFlg=true)
Definition: svdmodel.cxx:1143
SdrUndoFactory & GetSdrUndoFactory() const
returns the models undo factory.
Definition: svdmodel.cxx:1915
OutputDevice * GetRefDevice() const
Definition: svdmodel.hxx:334
bool SetAttributes(const SfxItemSet &rSet, bool bReplaceAll)
Definition: svdedxv.cxx:2287
sal_uInt16 GetSelectionLevel() const
Definition: svdedxv.cxx:2701
bool IsTextEditInSelectionMode() const
Definition: svdedxv.cxx:2510
SdrTextObj * GetTextEditObject() const
Definition: svdedxv.hxx:234
virtual std::unique_ptr< SdrUndoManager > createLocalTextUndoManager()
Definition: svdedxv.cxx:1218
void ImpChainingEventHdl()
Definition: svdedxv.cxx:1069
tools::Rectangle aMinTextEditArea
Definition: svdedxv.hxx:96
bool EndMacroObj()
Definition: svdedxv.cxx:2590
virtual void DeleteDeviceFromPaintView(OutputDevice &rOldWin) override
Definition: svdedxv.cxx:2489
virtual void EditViewInvalidate(const tools::Rectangle &rRect) override
Definition: svdedxv.cxx:764
SfxUndoManager * mpOldTextEditUndoManager
Definition: svdedxv.hxx:112
virtual void BrkAction() override
Definition: svdedxv.cxx:125
std::unique_ptr< SdrOutliner > mpTextEditOutliner
Definition: svdedxv.hxx:86
bool ImpIsTextEditAllSelected() const
Definition: svdedxv.cxx:2166
vcl::Cursor * pTextEditCursorBuffer
Definition: svdedxv.hxx:90
SdrPageView * pMacroPV
Definition: svdedxv.hxx:92
virtual void OnBeginPasteOrDrop(PasteOrDropInfos *pInfo)
Definition: svdedxv.cxx:2691
virtual ~SdrObjEditView() override
Definition: svdedxv.cxx:93
bool mbTextEditDontDelete
Definition: svdedxv.hxx:102
OutlinerView * ImpFindOutlinerView(vcl::Window const *pWin) const
Definition: svdedxv.cxx:1838
virtual void OnEndPasteOrDrop(PasteOrDropInfos *pInfo)
Definition: svdedxv.cxx:2696
VclPtr< vcl::Window > mpTextEditWin
Definition: svdedxv.hxx:88
Point aMacroDownPos
Definition: svdedxv.hxx:98
SdrObject * pMacroObj
Definition: svdedxv.hxx:91
OutlinerView * mpTextEditOutlinerView
Definition: svdedxv.hxx:87
static bool SupportsFormatPaintbrush(SdrInventor nObjectInventor, SdrObjKind nObjectIdentifier)
returns true if the shape identified by its inventor and identifier supports format paint brush opera...
Definition: svdedxv.cxx:2736
virtual SdrEndTextEditKind SdrEndTextEdit(bool bDontDeleteReally=false)
Definition: svdedxv.cxx:1565
virtual bool KeyInput(const KeyEvent &rKEvt, vcl::Window *pWin) override
Definition: svdedxv.cxx:1951
void DisposeUndoManager()
Definition: svdedxv.cxx:2898
virtual void EditViewInputContext(const InputContext &rInputContext) override
Definition: svdedxv.cxx:826
void MovMacroObj(const Point &rPnt)
Definition: svdedxv.cxx:2562
const OutlinerView * GetTextEditOutlinerView() const
Definition: svdedxv.hxx:252
virtual bool MouseButtonUp(const MouseEvent &rMEvt, OutputDevice *pWin) override
Definition: svdedxv.cxx:2027
virtual OutputDevice & EditViewOutputDevice() const override
Definition: svdedxv.cxx:805
static void ApplyFormatPaintBrushToText(SfxItemSet const &rFormatSet, SdrTextObj &rTextObj, SdrText *pText, bool bNoCharacterFormats, bool bNoParagraphFormats)
helper function for selections with multiple SdrText for one SdrTextObj (f.e.
Definition: svdedxv.cxx:2865
virtual bool MouseMove(const MouseEvent &rMEvt, OutputDevice *pWin) override
handle mouse over effects for handles
Definition: svdedxv.cxx:2065
std::unique_ptr< TextChainCursorManager > ImpHandleMotionThroughBoxesKeyInput(const KeyEvent &rKEvt, bool *bOutHandled)
Definition: svdedxv.cxx:1928
void getTextSelection(css::uno::Any &rSelection)
fills the given any with a XTextCursor for the current text selection.
Definition: svdedxv.cxx:2615
virtual void MovAction(const Point &rPnt) override
Definition: svdedxv.cxx:105
void HideSdrPage() override
Definition: svdedxv.cxx:195
void GetAttributes(SfxItemSet &rTargetSet, bool bOnlyHardAttr) const
Definition: svdedxv.cxx:2249
sdr::overlay::OverlayObjectList maTEOverlayGroup
Definition: svdedxv.hxx:80
void BrkMacroObj()
Definition: svdedxv.cxx:2579
virtual bool IsAction() const override
Definition: svdedxv.cxx:103
bool IsTextEditFrameHit(const Point &rHit) const
Definition: svdedxv.cxx:1898
bool mbMacroDown
Definition: svdedxv.hxx:106
Link< EditFieldInfo *, void > aOldCalcFieldValueLink
Definition: svdedxv.hxx:97
void ImpPaintOutlinerView(OutlinerView &rOutlView, const tools::Rectangle &rRect, OutputDevice &rTargetDevice) const
Definition: svdedxv.cxx:890
void SetTextEditWin(vcl::Window *pWin)
Definition: svdedxv.cxx:1855
rtl::Reference< sdr::SelectionController > mxLastSelectionController
Definition: svdedxv.hxx:109
virtual Point EditViewPointerPosPixel() const override
Definition: svdedxv.cxx:807
virtual void ModelHasChanged() override
Definition: svdedxv.cxx:242
void ImpMakeTextCursorAreaVisible()
Definition: svdedxv.cxx:2199
virtual void EndAction() override
Definition: svdedxv.cxx:112
void TakeFormatPaintBrush(std::shared_ptr< SfxItemSet > &rFormatSet)
returns a format paint brush set from the current selection
Definition: svdedxv.cxx:2800
virtual void Notify(SfxBroadcaster &rBC, const SfxHint &rHint) override
Definition: svdedxv.cxx:220
virtual void TakeActionRect(tools::Rectangle &rRect) const override
Definition: svdedxv.cxx:208
virtual bool MouseButtonDown(const MouseEvent &rMEvt, OutputDevice *pWin) override
Definition: svdedxv.cxx:1983
bool IsMacroObj() const
Definition: svdedxv.hxx:291
std::unique_ptr< SdrUndoManager > mpLocalTextEditUndoManager
Definition: svdedxv.hxx:113
virtual css::uno::Reference< css::datatransfer::clipboard::XClipboard > GetClipboard() const override
Definition: svdedxv.cxx:812
virtual void EditViewCursorRect(const tools::Rectangle &rRect, int nExtTextInputWidth) override
Definition: svdedxv.cxx:833
rtl::Reference< sdr::SelectionController > mxSelectionController
Definition: svdedxv.hxx:108
void ApplyFormatPaintBrush(SfxItemSet &rFormatSet, bool bNoCharacterFormats, bool bNoParagraphFormats)
applies a format paint brush set from the current selection.
Definition: svdedxv.cxx:2912
virtual css::uno::Reference< css::datatransfer::dnd::XDropTarget > GetDropTarget() override
Definition: svdedxv.cxx:819
void ImpMacroDown(const Point &rDownPos)
Definition: svdedxv.cxx:2548
SdrPageView * GetTextEditPageView() const
Definition: svdedxv.cxx:1836
VclPtr< vcl::Window > pMacroWin
Definition: svdedxv.hxx:93
void BegMacroObj(const Point &rPnt, short nTol, SdrObject *pObj, SdrPageView *pPV, vcl::Window *pWin)
Definition: svdedxv.cxx:2517
SfxStyleSheet * GetStyleSheet() const
Definition: svdedxv.cxx:2432
void SetStyleSheet(SfxStyleSheet *pStyleSheet, bool bDontRemoveHardAttr)
Definition: svdedxv.cxx:2453
tools::Rectangle aTextEditArea
Definition: svdedxv.hxx:95
virtual bool Command(const CommandEvent &rCEvt, vcl::Window *pWin) override
Definition: svdedxv.cxx:2108
SdrObjEditView(SdrModel &rSdrModel, OutputDevice *pOut)
Definition: svdedxv.cxx:74
SdrPageView * ShowSdrPage(SdrPage *pPage) override
Definition: svdedxv.cxx:131
OutlinerView * ImpMakeOutlinerView(vcl::Window *pWin, OutlinerView *pGivenView, SfxViewShell *pViewShell=nullptr) const
Definition: svdedxv.cxx:998
bool IsTextEditHit(const Point &rHit) const
Definition: svdedxv.cxx:1875
virtual void AddDeviceToPaintView(OutputDevice &rNewDev, vcl::Window *pWindow) override
Definition: svdedxv.cxx:2477
void TextEditDrawing(SdrPaintWindow &rPaintWindow)
Definition: svdedxv.cxx:840
virtual bool IsTextEdit() const final override
Definition: svdedxv.cxx:1833
virtual void MarkListHasChanged() override
Definition: svdedxv.cxx:2647
unotools::WeakReference< SdrTextObj > mxWeakTextEditObj
Definition: svdedxv.hxx:84
bool mbTextEditOnlyOneView
Definition: svdedxv.hxx:103
bool mbTextEditNewObj
Definition: svdedxv.hxx:104
virtual void EditViewSelectionChange() override
Definition: svdedxv.cxx:788
virtual SvtScriptType GetScriptType() const
Definition: svdedxv.cxx:2215
void ImpInvalidateOutlinerView(OutlinerView const &rOutlView) const
Definition: svdedxv.cxx:945
void ImpMoveCursorAfterChainingEvent(TextChainCursorManager *pCursorManager)
Definition: svdedxv.cxx:1148
virtual bool SdrBeginTextEdit(SdrObject *pObj, SdrPageView *pPV=nullptr, vcl::Window *pWin=nullptr, bool bIsNewObj=false, SdrOutliner *pGivenOutliner=nullptr, OutlinerView *pGivenOutlinerView=nullptr, bool bDontDeleteOutliner=false, bool bOnlyOneView=false, bool bGrabFocus=true)
Definition: svdedxv.cxx:1224
const SdrOutliner * GetTextEditOutliner() const
Definition: svdedxv.hxx:244
SdrPageView * mpTextEditPV
Definition: svdedxv.hxx:85
virtual void BckAction() override
Definition: svdedxv.cxx:119
sal_uInt16 nMacroTol
Definition: svdedxv.hxx:100
void ImpMacroUp(const Point &rUpPos)
Definition: svdedxv.cxx:2534
const SdrPageView * pPageView
Definition: svdobj.hxx:140
const SdrLayerIDSet * pVisiLayer
Definition: svdobj.hxx:139
sal_uInt16 nTol
Definition: svdobj.hxx:141
Abstract DrawObject.
Definition: svdobj.hxx:260
virtual bool DoMacro(const SdrObjMacroHitRec &rRec)
Definition: svdobj.cxx:1884
virtual SdrInventor GetObjInventor() const
Definition: svdobj.cxx:621
virtual OutlinerParaObject * GetOutlinerParaObject() const
Definition: svdobj.cxx:1833
virtual css::uno::Reference< css::drawing::XShape > getUnoShape()
Definition: svdobj.cxx:2866
virtual const tools::Rectangle & GetCurrentBoundRect() const
Definition: svdobj.cxx:962
SdrModel & getSdrModelFromSdrObject() const
Definition: svdobj.cxx:289
virtual void PaintMacro(OutputDevice &rOut, const tools::Rectangle &rDirtyRect, const SdrObjMacroHitRec &rRec) const
Definition: svdobj.cxx:1867
virtual SdrObjKind GetObjIdentifier() const
Definition: svdobj.cxx:626
SdrPage * getSdrPageFromSdrObject() const
Definition: svdobj.cxx:279
const SfxItemSet & GetMergedItemSet() const
Definition: svdobj.cxx:1974
bool IsMacroHit(const SdrObjMacroHitRec &rRec) const
Definition: svdobj.cxx:1889
virtual SdrLayerID GetLayer() const
Definition: svdobj.cxx:645
virtual bool HasMacro() const
Definition: svdobj.cxx:1847
const SdrLayerIDSet & GetVisibleLayers() const
Definition: svdpagv.hxx:210
sal_uInt32 PageWindowCount() const
Definition: svdpagv.hxx:89
const SdrLayerIDSet & GetLockedLayers() const
Definition: svdpagv.hxx:214
SdrPage * GetPage() const
Definition: svdpagv.hxx:166
SdrPageWindow * GetPageWindow(sal_uInt32 nIndex) const
Definition: svdpagv.cxx:83
rtl::Reference< sdr::overlay::OverlayManager > const & GetOverlayManager() const
SdrPaintWindow & GetPaintWindow() const
A SdrPage contains exactly one SdrObjList and a description of the physical page dimensions (size / m...
Definition: svdpage.hxx:379
virtual void DeleteDeviceFromPaintView(OutputDevice &rOldDev)
Definition: svdpntv.cxx:398
virtual void AddDeviceToPaintView(OutputDevice &rNewDev, vcl::Window *pWindow)
Definition: svdpntv.cxx:387
virtual bool MouseButtonUp(const MouseEvent &, OutputDevice *)
Definition: svdpntv.hxx:473
SdrPaintWindow * GetPaintWindow(sal_uInt32 nIndex) const
Definition: svdpntv.cxx:75
OutputDevice * GetFirstOutputDevice() const
Definition: svdpntv.cxx:91
virtual SdrPageView * ShowSdrPage(SdrPage *pPage)
Definition: svdpntv.cxx:358
virtual void MakeVisible(const tools::Rectangle &rRect, vcl::Window &rWin)
Definition: svdpntv.cxx:1015
sal_uInt16 ImpGetHitTolLogic(short nHitTol, const OutputDevice *pOut) const
Definition: svdpntv.cxx:318
virtual bool Command(const CommandEvent &, vcl::Window *)
Definition: svdpntv.hxx:476
virtual void InvalidateOneWin(OutputDevice &rWin)
If the View should not call Invalidate() on the windows, override the following 2 methods and do some...
Definition: svdpntv.cxx:865
virtual bool KeyInput(const KeyEvent &rKEvt, vcl::Window *pWin)
Definition: svdpntv.cxx:786
sal_uInt32 PaintWindowCount() const
Definition: svdpntv.hxx:241
virtual bool MouseButtonDown(const MouseEvent &, OutputDevice *)
Definition: svdpntv.hxx:472
SdrPageView * GetSdrPageView() const
Definition: svdpntv.hxx:323
SdrModel & GetModel() const
Definition: svdpntv.hxx:282
void FlushComeBackTimer() const
Definition: svdpntv.cxx:247
const vcl::Region & GetRedrawRegion() const
OutputDevice & GetTargetOutputDevice()
OutputDevice & GetOutputDevice() const
bool OutputToWindow() const
vcl::Window * GetWindow() const
SdrOutliner & ImpGetDrawOutliner() const
Definition: svdotext.cxx:1194
bool IsFitToSize() const
returns true if the old feature for fitting shape content should into shape is enabled....
Definition: svdotext.cxx:1940
void NbcSetOutlinerParaObjectForText(std::optional< OutlinerParaObject > pTextObject, SdrText *pText)
Definition: svdotext.cxx:1435
static bool HasTextImpl(SdrOutliner const *pOutliner)
returns false if the given pointer is NULL or if the given SdrOutliner contains no text.
Definition: svdotext.cxx:458
virtual sal_Int32 getTextCount() const override
returns the number of texts available for this object.
Definition: svdotext.cxx:2171
static void impDecomposeBlockTextPrimitiveDirect(drawinglayer::primitive2d::Primitive2DContainer &rTarget, SdrOutliner &rOutliner, const basegfx::B2DHomMatrix &rNewTransformA, const basegfx::B2DHomMatrix &rNewTransformB, const basegfx::B2DRange &rClipRange)
bool IsTextFrame() const
Definition: svdotext.hxx:359
virtual SdrObjKind GetObjIdentifier() const override
Definition: svdotext.cxx:453
virtual SdrText * getText(sal_Int32 nIndex) const override
returns the nth available text.
Definition: svdotext.cxx:2156
OutlinerParaObject * GetOutlinerParaObject()
Definition: svdtext.cxx:78
virtual std::unique_ptr< SdrUndoAction > CreateUndoDeleteObject(SdrObject &rObject, bool bOrdNumDirect=false)
Definition: svdundo.cxx:1694
size_t GetRedoActionCountBeforeTextEdit() const
virtual bool Redo() override
void SetEndTextEditHdl(const Link< SdrUndoManager *, void > &rLink)
bool isEndTextEditTriggeredFromUndo() const
virtual bool Undo() override
react depending on edit mode and if no more undo is possible
void Broadcast(const SfxHint &rHint)
SfxHintId GetId() const
const SfxPoolItem * GetCurItem() const
const SfxPoolItem * NextItem()
const WhichRangesContainer & GetRanges() const
SfxItemPool * GetPool() const
SfxItemState GetItemState(sal_uInt16 nWhich, bool bSrchInParent=true, const SfxPoolItem **ppItem=nullptr) const
const SfxPoolItem * GetItem(sal_uInt16 nWhich, bool bSearchInParent=true) const
const SfxPoolItem * Put(const SfxPoolItem &rItem, sal_uInt16 nWhich)
static SAL_WARN_UNUSED_RESULT SfxViewShell * Current()
sal_uInt16 FirstWhich()
sal_uInt16 NextWhich()
bool IsEmpty() const
constexpr tools::Long Height() const
constexpr tools::Long Width() const
static bool GetIsAutomaticFontColor()
css::uno::Reference< css::text::XTextCursor > createTextCursorBySelection(const ESelection &rSel)
void HandleCursorEventAfterChaining(const CursorChainingEvent aCurEvt, const ESelection &aNewSel)
bool GetNilChainingEvent(const SdrTextObj *)
Definition: textchain.cxx:38
ESelection const & GetPostChainingSel(const SdrTextObj *)
Definition: textchain.cxx:60
CursorChainingEvent const & GetCursorEvent(const SdrTextObj *)
Definition: textchain.cxx:27
void SetCursorEvent(const SdrTextObj *, CursorChainingEvent const &)
Definition: textchain.cxx:32
void SetPreChainingSel(const SdrTextObj *, ESelection const &)
Definition: textchain.cxx:54
void SetNilChainingEvent(const SdrTextObj *, bool)
Definition: textchain.cxx:43
void translate(double fX, double fY)
void append(const B2DPolygon &rPolygon, sal_uInt32 nCount=1)
B2DRange getB2DRange() const
void expand(const Tuple2D< TYPE > &rTuple)
TYPE getX() const
TYPE getY() const
void append(const Primitive2DReference &)
void append(std::unique_ptr< OverlayObject > pOverlayObject)
OverlayObject & getOverlayObject(sal_uInt32 nIndex) const
virtual drawinglayer::primitive2d::Primitive2DContainer createOverlayObjectPrimitive2DSequence()
virtual drawinglayer::primitive2d::Primitive2DContainer getOverlayObjectPrimitive2DSequence() const
bool Contains(const Point &rPOINT) const
constexpr void SetLeft(tools::Long v)
constexpr void SetTop(tools::Long v)
constexpr tools::Long Top() const
constexpr Point TopLeft() const
constexpr void SetRight(tools::Long v)
void Move(tools::Long nHorzMoveDelta, tools::Long nVertMoveDelta)
constexpr tools::Long Right() const
tools::Long AdjustTop(tools::Long nVertMoveDelta)
tools::Long AdjustRight(tools::Long nHorzMoveDelta)
constexpr void SetBottom(tools::Long v)
tools::Rectangle & Union(const tools::Rectangle &rRect)
tools::Long AdjustBottom(tools::Long nVertMoveDelta)
tools::Long AdjustLeft(tools::Long nHorzMoveDelta)
tools::Rectangle & Intersection(const tools::Rectangle &rRect)
constexpr tools::Long Left() const
constexpr tools::Long Bottom() const
constexpr bool IsEmpty() const
rtl::Reference< interface_type > SAL_CALL get() const
const Point & GetPos() const
const Size & GetSize() const
tools::Rectangle GetBoundRect() const
Point LogicToPixel(const Point &rLogicPt) const
void SetCursor(vcl::Cursor *pCursor)
void GrabFocus()
vcl::Cursor * GetCursor() const
bool IsMapModeEnabled() const
::OutputDevice const * GetOutDev() const
Point PixelToLogic(const Point &rDevicePt) const
Size GetOutputSizePixel() const
void Invalidate(InvalidateFlags nFlags=InvalidateFlags::NONE)
void EnableMapMode(bool bEnable=true)
constexpr ::Color COL_LIGHTGRAY(0xC0, 0xC0, 0xC0)
constexpr ::Color COL_BLACK(0x00, 0x00, 0x00)
int nCount
#define DBG_ASSERT(sCon, aError)
#define suppress_fun_call_w_exception(expr)
OUString SvxResId(TranslateId aId)
Definition: dialmgr.cxx:24
EEAnchorMode
EEControlBits
EVControlBits
constexpr sal_uInt16 EE_FEATURE_END(EE_FEATURE_FIELD+0)
constexpr sal_uInt16 EE_PARA_START(EE_ITEMS_START+0)
constexpr sal_uInt16 EE_ITEMS_END(EE_FEATURE_END)
constexpr sal_uInt16 EE_CHAR_START(EE_PARA_END+1)
constexpr sal_uInt16 EE_FEATURE_START(EE_CHAR_END+1)
constexpr sal_uInt16 EE_CHAR_END(EE_CHAR_START+32)
constexpr sal_uInt16 EE_PARA_END(EE_PARA_START+19)
constexpr sal_uInt16 EE_ITEMS_START(OWN_ATTR_VALUE_END+1)
uno_Any a
SvtScriptType
#define SAL_WARN_IF(condition, area, stream)
#define SAL_WARN(area, stream)
#define SAL_INFO(area, stream)
void ForAllViews(const SdrPage *pPage, std::function< void(SdrView *)> f)
Definition: svdviter.cxx:83
sal_uInt16 GetTransparentSelectionPercent()
B2DPolygon createPolygonFromRect(const B2DRectangle &rRect, double fRadiusX, double fRadiusY)
B2DRange getRange(const B2DPolygon &rCandidate)
B2IRange fround(const B2DRange &rRange)
std::unique_ptr< BaseProcessor2D > createProcessor2DFromOutputDevice(OutputDevice &rTargetOutDev, const drawinglayer::geometry::ViewInformation2D &rViewInformation2D)
int i
rtl::Reference< sdr::SelectionController > CreateTableController(SdrView &rView, const SdrTableObj &rObj, const rtl::Reference< sdr::SelectionController > &xRefController)
static constexpr auto Items
long Long
basegfx::B2DRange b2DRectangleFromRectangle(const ::tools::Rectangle &rRect)
OUTDEV_WINDOW
SfxItemState
bool IsInvalidItem(const SfxPoolItem *pItem)
static SfxItemSet & rSet
bool HasRange() const
sal_Int32 nStartPara
sal_Int32 nEndPos
sal_Int32 nStartPos
sal_Int32 nEndPara
constexpr sal_uInt16 SDRATTR_TABLE_FIRST(SDRATTR_CUSTOMSHAPE_LAST+1)
constexpr sal_uInt16 SDRATTR_MISC_LAST(SDRATTR_TEXT_CLIPVERTOVERFLOW)
constexpr sal_uInt16 SDRATTR_GLOW_LAST(SDRATTR_GLOW_TRANSPARENCY)
constexpr sal_uInt16 SDRATTR_GLOW_FIRST(SDRATTR_TABLE_LAST+1)
constexpr sal_uInt16 SDRATTR_GRAF_LAST(SDRATTR_GRAFCROP)
constexpr sal_uInt16 SDRATTR_SHADOW_FIRST(XATTR_END+1)
constexpr TypedWhichId< SdrTextFixedCellHeightItem > SDRATTR_TEXT_USEFIXEDCELLHEIGHT(SDRATTR_MISC_FIRST+23)
constexpr sal_uInt16 SDRATTR_SOFTEDGE_LAST(SDRATTR_SOFTEDGE_RADIUS)
constexpr sal_uInt16 SDRATTR_MISC_FIRST(SDRATTR_CAPTION_LAST+1)
constexpr sal_uInt16 SDRATTR_TABLE_LAST(SDRATTR_TABLE_CELL_GRABBAG)
constexpr sal_uInt16 SDRATTR_GRAF_FIRST(SDRATTR_NOTPERSIST_LAST+1)
constexpr sal_uInt16 SDRATTR_SHADOW_LAST(SDRATTR_SHADOWALIGNMENT)
constexpr sal_uInt16 SDRATTR_SOFTEDGE_FIRST(SDRATTR_GLOW_LAST+1)
IMPL_LINK_NOARG(SdrObjEditView, ImpAfterCutOrPasteChainingEventHdl, LinkParamNone *, void)
Definition: svdedxv.cxx:1138
static SfxItemSet CreatePaintSet(const WhichRangesContainer &pRanges, SfxItemPool &rPool, const SfxItemSet &rSourceSet, const SfxItemSet &rTargetSet, bool bNoCharacterFormats, bool bNoParagraphFormats)
Definition: svdedxv.cxx:2833
IMPL_LINK(SdrObjEditView, ImpOutlinerStatusEventHdl, EditStatus &, rEditStat, void)
Definition: svdedxv.cxx:1057
static const WhichRangesContainer & GetFormatRangeImpl(bool bTextOnly)
Definition: svdedxv.cxx:2783
SdrEndTextEditKind
Definition: svdedxv.hxx:50
WhichRangesContainer RemoveWhichRange(const WhichRangesContainer &pOldWhichTable, sal_uInt16 nRangeBeg, sal_uInt16 nRangeEnd)
Definition: svdetc.cxx:375
bool SearchOutlinerItems(const SfxItemSet &rSet, bool bInklDefaults, bool *pbOnlyEE)
Search an ItemSet for Outliner/EditEngine Items.
Definition: svdetc.cxx:352
Color GetTextEditBackgroundColor(const SdrObjEditView &rView)
Definition: svdetc.cxx:673
std::unique_ptr< SdrOutliner > SdrMakeOutliner(OutlinerMode nOutlinerMode, SdrModel &rModel)
Create an Outliner with the engine-global default settings on the heap.
Definition: svdetc.cxx:332
SdrHintKind
Definition: svdmodel.hxx:103
SdrTextObj * DynCastSdrTextObj(SdrObject *pObj)
Definition: svdobj.cxx:3212
SdrInventor
Definition: svdobj.hxx:98
SdrObjKind
Definition: svdobjkind.hxx:25
@ Group
abstract object (SdrObject)
@ Measure
object that represents a SdrPage
@ Page
Polyline represented by SdrPathObj.
@ Caption
connector object
@ PathFill
open Bezier-curve
@ Line
object group
@ Polygon
circle cut
@ Table
media shape
@ FreehandLine
closed Bezier-curve
@ UNO
continuously activated OLE (PlugIn-Frame or similar)
@ PathLine
PolyLine.
@ CustomShape
Universal Network Object packed into SvDraw object.
@ CircleOrEllipse
rectangle (round corners optional)
@ PathPoly
caption object
@ Text
closed free-hand line
@ OLE2
foreign graphic (StarView Graphic)
@ OLEPluginFrame
measurement object
@ Graphic
OutlineText, special text object for StarDraw.
@ CircleCut
circle arc
@ Rectangle
line
@ PathPolyLine
Polygon/PolyPolygon represented by SdrPathObj.
@ CircleSection
circle, ellipse
@ OutlineText
TitleText, special text object for StarDraw.
@ CircleArc
circle section
@ PolyLine
polygon, PolyPolygon
@ Edge
OLE object.
@ TitleText
text object
@ FreehandFill
open free-hand line
oslFileHandle & pOut
constexpr TypedWhichId< XFillAttrSetItem > XATTRSET_FILL(XATTR_FILL_LAST+1)
constexpr sal_uInt16 XATTR_LINE_FIRST(XATTR_START)
constexpr sal_uInt16 XATTR_FILL_FIRST(XATTRSET_LINE+1)
constexpr sal_uInt16 XATTR_LINE_LAST(XATTR_LINECAP)