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