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(mpModel->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 = GetModel() && 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 = mpModel->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 if (GetModel())
1499 {
1500 SdrHint aHint(SdrHintKind::BeginEdit, *pTextObj);
1501 GetModel()->Broadcast(aHint);
1502 }
1503
1504 mpTextEditOutliner->setVisualizedPage(nullptr);
1505
1506 if (mxSelectionController.is())
1507 mxSelectionController->onSelectionHasChanged();
1508
1509 if (GetModel() && IsUndoEnabled()
1510 && !GetModel()->GetDisableTextEditUsesCommonUndoManager())
1511 {
1512 SdrUndoManager* pSdrUndoManager = nullptr;
1514
1516 pSdrUndoManager = mpLocalTextEditUndoManager.get();
1517
1518 if (pSdrUndoManager)
1519 {
1520 // we have an outliner, undo manager and it's an EditUndoManager, exchange
1521 // the document undo manager and the default one from the outliner and tell
1522 // it that text edit starts by setting a callback if it needs to end text edit mode.
1523 assert(nullptr == mpOldTextEditUndoManager);
1524
1525 mpOldTextEditUndoManager = mpTextEditOutliner->SetUndoManager(pSdrUndoManager);
1526 pSdrUndoManager->SetEndTextEditHdl(LINK(this, SdrObjEditView, EndTextEditHdl));
1527 }
1528 else
1529 {
1530 OSL_ENSURE(false,
1531 "The document undo manager is not derived from SdrUndoManager (!)");
1532 }
1533 }
1534
1535 return true; // ran fine, let TextEdit run now
1536 }
1537 else
1538 {
1539 mpTextEditOutliner->SetCalcFieldValueHdl(aOldCalcFieldValueLink);
1540 mpTextEditOutliner->SetBeginPasteOrDropHdl(Link<PasteOrDropInfos*, void>());
1541 mpTextEditOutliner->SetEndPasteOrDropHdl(Link<PasteOrDropInfos*, void>());
1542 }
1543 }
1544 if (mpTextEditOutliner != nullptr)
1545 {
1546 mpTextEditOutliner->setVisualizedPage(nullptr);
1547 }
1548
1549 // something went wrong...
1550 if (!bDontDeleteOutliner)
1551 {
1552 delete pGivenOutliner;
1553 if (pGivenOutlinerView != nullptr)
1554 {
1555 delete pGivenOutlinerView;
1556 pGivenOutlinerView = nullptr;
1557 }
1558 }
1559 mpTextEditOutliner.reset();
1560
1561 mpTextEditOutlinerView = nullptr;
1562 mxWeakTextEditObj.clear();
1563 mpTextEditPV = nullptr;
1564 mpTextEditWin = nullptr;
1566
1567 return false;
1568}
1569
1571{
1574 vcl::Window* pTEWin = mpTextEditWin;
1575 OutlinerView* pTEOutlinerView = mpTextEditOutlinerView;
1576 vcl::Cursor* pTECursorBuffer = pTextEditCursorBuffer;
1577 SdrUndoManager* pUndoEditUndoManager = nullptr;
1578 bool bNeedToUndoSavedRedoTextEdit(false);
1579
1580 if (GetModel() && IsUndoEnabled() && pTEObj && mpTextEditOutliner
1581 && !GetModel()->GetDisableTextEditUsesCommonUndoManager())
1582 {
1583 // change back the UndoManager to the remembered original one
1584 SfxUndoManager* pOriginal = mpTextEditOutliner->SetUndoManager(mpOldTextEditUndoManager);
1585 mpOldTextEditUndoManager = nullptr;
1586
1587 if (pOriginal)
1588 {
1589 // check if we got back our document undo manager
1590 SdrUndoManager* pSdrUndoManager = mpLocalTextEditUndoManager.get();
1591
1592 if (pSdrUndoManager && dynamic_cast<SdrUndoManager*>(pOriginal) == pSdrUndoManager)
1593 {
1594 if (pSdrUndoManager->isEndTextEditTriggeredFromUndo())
1595 {
1596 // remember the UndoManager where missing Undos have to be triggered after end
1597 // text edit. When the undo had triggered the end text edit, the original action
1598 // which had to be undone originally is not yet undone.
1599 pUndoEditUndoManager = pSdrUndoManager;
1600
1601 // We are ending text edit; if text edit was triggered from undo, execute all redos
1602 // to create a complete text change undo action for the redo buffer. Also mark this
1603 // state when at least one redo was executed; the created extra TextChange needs to
1604 // be undone in addition to the first real undo outside the text edit changes
1605 while (pSdrUndoManager->GetRedoActionCount()
1606 > pSdrUndoManager->GetRedoActionCountBeforeTextEdit())
1607 {
1608 bNeedToUndoSavedRedoTextEdit = true;
1609 pSdrUndoManager->Redo();
1610 }
1611 }
1612
1613 // reset the callback link and let the undo manager cleanup all text edit
1614 // undo actions to get the stack back to the form before the text edit
1616 }
1617 else
1618 {
1619 OSL_ENSURE(false, "Got UndoManager back in SdrEndTextEdit which is NOT the "
1620 "expected document UndoManager (!)");
1621 delete pOriginal;
1622 }
1623
1624 // cid#1493241 - Wrapper object use after free
1625 if (pUndoEditUndoManager == mpLocalTextEditUndoManager.get())
1626 pUndoEditUndoManager = nullptr;
1628 }
1629 }
1630 else
1631 {
1632 assert(nullptr == mpOldTextEditUndoManager); // cannot be restored!
1633 }
1634
1635 if (GetModel())
1636 if (auto pTextEditObj = mxWeakTextEditObj.get())
1637 {
1638 SdrHint aHint(SdrHintKind::EndEdit, *pTextEditObj);
1639 GetModel()->Broadcast(aHint);
1640 }
1641
1642 // if new mechanism was used, clean it up. At cleanup no need to check
1643 // for LibreOfficeKit
1645 {
1648 }
1649
1650 mxWeakTextEditObj.clear();
1651 mpTextEditPV = nullptr;
1652 mpTextEditWin = nullptr;
1653 mpTextEditOutlinerView = nullptr;
1654 pTextEditCursorBuffer = nullptr;
1656
1657 if (SdrOutliner* pTEOutliner = mpTextEditOutliner.release())
1658 {
1659 bool bModified = pTEOutliner->IsModified();
1660 if (pTEOutlinerView != nullptr)
1661 {
1662 pTEOutlinerView->HideCursor();
1663 }
1664 if (pTEObj != nullptr)
1665 {
1666 pTEOutliner->CompleteOnlineSpelling();
1667
1668 std::unique_ptr<SdrUndoObjSetText> pTxtUndo;
1669
1670 if (bModified)
1671 {
1672 sal_Int32 nText;
1673 for (nText = 0; nText < pTEObj->getTextCount(); ++nText)
1674 if (pTEObj->getText(nText) == pTEObj->getActiveText())
1675 break;
1676
1677 pTxtUndo.reset(
1678 dynamic_cast<SdrUndoObjSetText*>(GetModel()
1679 ->GetSdrUndoFactory()
1680 .CreateUndoObjectSetText(*pTEObj, nText)
1681 .release()));
1682 }
1683 DBG_ASSERT(!bModified || pTxtUndo,
1684 "svx::SdrObjEditView::EndTextEdit(), could not create undo action!");
1685 // Set old CalcFieldValue-Handler again, this
1686 // has to happen before Obj::EndTextEdit(), as this does UpdateFields().
1687 pTEOutliner->SetCalcFieldValueHdl(aOldCalcFieldValueLink);
1688 pTEOutliner->SetBeginPasteOrDropHdl(Link<PasteOrDropInfos*, void>());
1689 pTEOutliner->SetEndPasteOrDropHdl(Link<PasteOrDropInfos*, void>());
1690
1691 const bool bUndo = IsUndoEnabled();
1692 if (bUndo)
1693 {
1694 OUString aObjName(pTEObj->TakeObjNameSingul());
1695 BegUndo(SvxResId(STR_UndoObjSetText), aObjName);
1696 }
1697
1698 pTEObj->EndTextEdit(*pTEOutliner);
1699
1700 if ((pTEObj->GetRotateAngle() != 0_deg100) || (pTEObj && pTEObj->IsFontwork()))
1701 {
1702 pTEObj->ActionChanged();
1703 }
1704
1705 if (pTxtUndo != nullptr)
1706 {
1707 pTxtUndo->AfterSetText();
1708 if (!pTxtUndo->IsDifferent())
1709 {
1710 pTxtUndo.reset();
1711 }
1712 }
1713 // check deletion of entire TextObj
1714 std::unique_ptr<SdrUndoAction> pDelUndo;
1715 bool bDelObj = false;
1716 if (mbTextEditNewObj)
1717 {
1718 bDelObj = pTEObj->IsTextFrame() && !pTEObj->HasText() && !pTEObj->IsEmptyPresObj()
1719 && !pTEObj->HasFill() && !pTEObj->HasLine();
1720
1721 if (pTEObj->IsInserted() && bDelObj
1722 && pTEObj->GetObjInventor() == SdrInventor::Default && !bDontDeleteReally)
1723 {
1724 SdrObjKind eIdent = pTEObj->GetObjIdentifier();
1725 if (eIdent == SdrObjKind::Text)
1726 {
1727 pDelUndo = GetModel()->GetSdrUndoFactory().CreateUndoDeleteObject(*pTEObj);
1728 }
1729 }
1730 }
1731 if (pTxtUndo)
1732 {
1733 if (bUndo)
1734 AddUndo(std::move(pTxtUndo));
1736 }
1737 if (pDelUndo != nullptr)
1738 {
1739 if (bUndo)
1740 {
1741 AddUndo(std::move(pDelUndo));
1742 }
1744 DBG_ASSERT(pTEObj->getParentSdrObjListFromSdrObject() != nullptr,
1745 "SdrObjEditView::SdrEndTextEdit(): Fatal: Object edited doesn't have an "
1746 "ObjList!");
1747 if (pTEObj->getParentSdrObjListFromSdrObject() != nullptr)
1748 {
1749 pTEObj->getParentSdrObjListFromSdrObject()->RemoveObject(pTEObj->GetOrdNum());
1750 CheckMarked(); // remove selection immediately...
1751 }
1752 }
1753 else if (bDelObj)
1754 { // for Writer: the app has to do the deletion itself.
1756 }
1757
1758 if (bUndo)
1759 EndUndo(); // EndUndo after Remove, in case UndoStack is deleted immediately
1760
1761 // Switch on any TextAnimation again after TextEdit
1762 if (pTEObj)
1763 {
1764 pTEObj->SetTextAnimationAllowed(true);
1765 }
1766
1767 // Since IsMarkHdlWhenTextEdit() is ignored, it is necessary
1768 // to call AdjustMarkHdl() always.
1769 AdjustMarkHdl();
1770 }
1771 // delete all OutlinerViews
1772 for (size_t i = pTEOutliner->GetViewCount(); i > 0;)
1773 {
1774 i--;
1775 OutlinerView* pOLV = pTEOutliner->GetView(i);
1776 sal_uInt16 nMorePix = pOLV->GetInvalidateMore() + 10;
1777 vcl::Window* pWin = pOLV->GetWindow();
1778 tools::Rectangle aRect(pOLV->GetOutputArea());
1779 pTEOutliner->RemoveView(i);
1780 if (!mbTextEditDontDelete || i != 0)
1781 {
1782 // may not own the zeroth one
1783 delete pOLV;
1784 }
1785 aRect.Union(aTextEditArea);
1786 aRect.Union(aMinTextEditArea);
1787 aRect = pWin->LogicToPixel(aRect);
1788 aRect.AdjustLeft(-nMorePix);
1789 aRect.AdjustTop(-nMorePix);
1790 aRect.AdjustRight(nMorePix);
1791 aRect.AdjustBottom(nMorePix);
1792 aRect = pWin->PixelToLogic(aRect);
1793 InvalidateOneWin(*pWin->GetOutDev(), aRect);
1794 pWin->GetOutDev()->SetFillColor();
1796 }
1797 // and now the Outliner itself
1799 delete pTEOutliner;
1800 else
1801 pTEOutliner->Clear();
1802 if (pTEWin != nullptr)
1803 {
1804 pTEWin->SetCursor(pTECursorBuffer);
1805 }
1808 {
1810 }
1811 // coverity[leaked_storage] - if pTEOutliner wasn't deleted it didn't really belong to us
1812 }
1813
1814 if (pTEObj && !pTEObj->getSdrModelFromSdrObject().isLocked() && pTEObj->GetBroadcaster())
1815 {
1816 SdrHint aHint(SdrHintKind::EndEdit, *pTEObj);
1817 const_cast<SfxBroadcaster*>(pTEObj->GetBroadcaster())->Broadcast(aHint);
1818 }
1819
1820 if (pUndoEditUndoManager)
1821 {
1822 if (bNeedToUndoSavedRedoTextEdit)
1823 {
1824 // undo the text edit action since it was created as part of an EndTextEdit
1825 // callback from undo itself. This needs to be done after the call to
1826 // FmFormView::SdrEndTextEdit since it gets created there
1827 pUndoEditUndoManager->Undo();
1828 }
1829
1830 // trigger the Undo which was not executed, but lead to this
1831 // end text edit
1832 pUndoEditUndoManager->Undo();
1833 }
1834
1835 return eRet;
1836}
1837
1838// info about TextEdit. Default is false.
1839bool SdrObjEditView::IsTextEdit() const { return mxWeakTextEditObj.get().is(); }
1840
1841// info about TextEditPageView. Default is 0L.
1843
1845{
1846 if (pWin == nullptr)
1847 return nullptr;
1848 if (mpTextEditOutliner == nullptr)
1849 return nullptr;
1850 OutlinerView* pNewView = nullptr;
1851 size_t nWinCount = mpTextEditOutliner->GetViewCount();
1852 for (size_t i = 0; i < nWinCount && pNewView == nullptr; i++)
1853 {
1854 OutlinerView* pView = mpTextEditOutliner->GetView(i);
1855 if (pView->GetWindow() == pWin)
1856 pNewView = pView;
1857 }
1858 return pNewView;
1859}
1860
1862{
1863 if (!(mxWeakTextEditObj.get() && pWin != nullptr && pWin != mpTextEditWin))
1864 return;
1865
1866 OutlinerView* pNewView = ImpFindOutlinerView(pWin);
1867 if (pNewView != nullptr && pNewView != mpTextEditOutlinerView)
1868 {
1869 if (mpTextEditOutlinerView != nullptr)
1870 {
1872 }
1873 mpTextEditOutlinerView = pNewView;
1874 mpTextEditWin = pWin;
1875 pWin->GrabFocus(); // Make the cursor blink here as well
1876 pNewView->ShowCursor();
1878 }
1879}
1880
1881bool SdrObjEditView::IsTextEditHit(const Point& rHit) const
1882{
1883 bool bOk = false;
1884 if (mxWeakTextEditObj.get())
1885 {
1886 tools::Rectangle aEditArea;
1887 if (OutlinerView* pOLV = mpTextEditOutliner->GetView(0))
1888 aEditArea.Union(pOLV->GetOutputArea());
1889
1890 if (aEditArea.Contains(rHit))
1891 { // check if any characters were actually hit
1892 const Point aPnt(rHit - aEditArea.TopLeft());
1893 tools::Long nHitTol = 2000;
1894 if (OutputDevice* pRef = mpTextEditOutliner->GetRefDevice())
1895 nHitTol = OutputDevice::LogicToLogic(nHitTol, MapUnit::Map100thMM,
1896 pRef->GetMapMode().GetMapUnit());
1897
1898 bOk = mpTextEditOutliner->IsTextPos(aPnt, static_cast<sal_uInt16>(nHitTol));
1899 }
1900 }
1901 return bOk;
1902}
1903
1904bool SdrObjEditView::IsTextEditFrameHit(const Point& rHit) const
1905{
1906 bool bOk = false;
1908 {
1909 OutlinerView* pOLV = mpTextEditOutliner->GetView(0);
1910 if (pOLV)
1911 {
1912 vcl::Window* pWin = pOLV->GetWindow();
1913 if (pText != nullptr && pText->IsTextFrame() && pWin != nullptr)
1914 {
1915 sal_uInt16 nPixSiz = pOLV->GetInvalidateMore();
1917 aEditArea.Union(pOLV->GetOutputArea());
1918 if (!aEditArea.Contains(rHit))
1919 {
1920 Size aSiz(pWin->PixelToLogic(Size(nPixSiz, nPixSiz)));
1921 aEditArea.AdjustLeft(-(aSiz.Width()));
1922 aEditArea.AdjustTop(-(aSiz.Height()));
1923 aEditArea.AdjustRight(aSiz.Width());
1924 aEditArea.AdjustBottom(aSiz.Height());
1925 bOk = aEditArea.Contains(rHit);
1926 }
1927 }
1928 }
1929 }
1930 return bOk;
1931}
1932
1933std::unique_ptr<TextChainCursorManager>
1935{
1936 *bOutHandled = false;
1937
1939 if (!pTextObj)
1940 return nullptr;
1941
1942 if (!pTextObj->GetNextLinkInChain() && !pTextObj->GetPrevLinkInChain())
1943 return nullptr;
1944
1945 std::unique_ptr<TextChainCursorManager> pCursorManager(
1946 new TextChainCursorManager(this, pTextObj.get()));
1947 if (pCursorManager->HandleKeyEvent(rKEvt))
1948 {
1949 // Possibly do other stuff here if necessary...
1950 // XXX: Careful with the checks below (in KeyInput) for pWin and co. You should do them here I guess.
1951 *bOutHandled = true;
1952 }
1953
1954 return pCursorManager;
1955}
1956
1958{
1960 {
1961 /* Start special handling of keys within a chain */
1962 // We possibly move to another box before any handling
1963 bool bHandled = false;
1964 std::unique_ptr<TextChainCursorManager> xCursorManager(
1965 ImpHandleMotionThroughBoxesKeyInput(rKEvt, &bHandled));
1966 if (bHandled)
1967 return true;
1968 /* End special handling of keys within a chain */
1969
1970 if (mpTextEditOutlinerView->PostKeyEvent(rKEvt, pWin))
1971 {
1972 if (mpModel)
1973 {
1974 if (mpTextEditOutliner && mpTextEditOutliner->IsModified())
1976 }
1977
1978 /* Start chaining processing */
1980 ImpMoveCursorAfterChainingEvent(xCursorManager.get());
1981 /* End chaining processing */
1982
1983 if (pWin != nullptr && pWin != mpTextEditWin)
1984 SetTextEditWin(pWin);
1986 return true;
1987 }
1988 }
1989 return SdrGlueEditView::KeyInput(rKEvt, pWin);
1990}
1991
1993{
1994 if (mpTextEditOutlinerView != nullptr)
1995 {
1996 bool bPostIt = mpTextEditOutliner->IsInSelectionMode();
1997 if (!bPostIt)
1998 {
1999 Point aPt(rMEvt.GetPosPixel());
2000 if (pWin != nullptr)
2001 aPt = pWin->PixelToLogic(aPt);
2002 else if (mpTextEditWin != nullptr)
2003 aPt = mpTextEditWin->PixelToLogic(aPt);
2004 bPostIt = IsTextEditHit(aPt);
2005 }
2006 if (bPostIt)
2007 {
2008 Point aPixPos(rMEvt.GetPosPixel());
2009 if (pWin)
2010 {
2012 if (aPixPos.X() < aR.Left())
2013 aPixPos.setX(aR.Left());
2014 if (aPixPos.X() > aR.Right())
2015 aPixPos.setX(aR.Right());
2016 if (aPixPos.Y() < aR.Top())
2017 aPixPos.setY(aR.Top());
2018 if (aPixPos.Y() > aR.Bottom())
2019 aPixPos.setY(aR.Bottom());
2020 }
2021 MouseEvent aMEvt(aPixPos, rMEvt.GetClicks(), rMEvt.GetMode(), rMEvt.GetButtons(),
2022 rMEvt.GetModifier());
2024 {
2025 if (pWin != nullptr && pWin != mpTextEditWin->GetOutDev()
2026 && pWin->GetOutDevType() == OUTDEV_WINDOW)
2029 return true;
2030 }
2031 }
2032 }
2033 return SdrGlueEditView::MouseButtonDown(rMEvt, pWin);
2034}
2035
2037{
2038 if (mpTextEditOutlinerView != nullptr)
2039 {
2040 bool bPostIt = mpTextEditOutliner->IsInSelectionMode();
2041 if (!bPostIt)
2042 {
2043 Point aPt(rMEvt.GetPosPixel());
2044 if (pWin != nullptr)
2045 aPt = pWin->PixelToLogic(aPt);
2046 else if (mpTextEditWin != nullptr)
2047 aPt = mpTextEditWin->PixelToLogic(aPt);
2048 bPostIt = IsTextEditHit(aPt);
2049 }
2050 if (bPostIt && pWin)
2051 {
2052 Point aPixPos(rMEvt.GetPosPixel());
2054 if (aPixPos.X() < aR.Left())
2055 aPixPos.setX(aR.Left());
2056 if (aPixPos.X() > aR.Right())
2057 aPixPos.setX(aR.Right());
2058 if (aPixPos.Y() < aR.Top())
2059 aPixPos.setY(aR.Top());
2060 if (aPixPos.Y() > aR.Bottom())
2061 aPixPos.setY(aR.Bottom());
2062 MouseEvent aMEvt(aPixPos, rMEvt.GetClicks(), rMEvt.GetMode(), rMEvt.GetButtons(),
2063 rMEvt.GetModifier());
2065 {
2067 return true;
2068 }
2069 }
2070 }
2071 return SdrGlueEditView::MouseButtonUp(rMEvt, pWin);
2072}
2073
2075{
2076 if (mpTextEditOutlinerView != nullptr)
2077 {
2078 bool bSelMode = mpTextEditOutliner->IsInSelectionMode();
2079 bool bPostIt = bSelMode;
2080 if (!bPostIt)
2081 {
2082 Point aPt(rMEvt.GetPosPixel());
2083 if (pWin)
2084 aPt = pWin->PixelToLogic(aPt);
2085 else if (mpTextEditWin)
2086 aPt = mpTextEditWin->PixelToLogic(aPt);
2087 bPostIt = IsTextEditHit(aPt);
2088 }
2089 if (bPostIt)
2090 {
2091 Point aPixPos(rMEvt.GetPosPixel());
2093 if (pWin)
2094 aR = pWin->LogicToPixel(aR);
2095 else if (mpTextEditWin)
2096 aR = mpTextEditWin->LogicToPixel(aR);
2097 if (aPixPos.X() < aR.Left())
2098 aPixPos.setX(aR.Left());
2099 if (aPixPos.X() > aR.Right())
2100 aPixPos.setX(aR.Right());
2101 if (aPixPos.Y() < aR.Top())
2102 aPixPos.setY(aR.Top());
2103 if (aPixPos.Y() > aR.Bottom())
2104 aPixPos.setY(aR.Bottom());
2105 MouseEvent aMEvt(aPixPos, rMEvt.GetClicks(), rMEvt.GetMode(), rMEvt.GetButtons(),
2106 rMEvt.GetModifier());
2107 if (mpTextEditOutlinerView->MouseMove(aMEvt) && bSelMode)
2108 {
2110 return true;
2111 }
2112 }
2113 }
2114 return SdrGlueEditView::MouseMove(rMEvt, pWin);
2115}
2116
2118{
2119 // as long as OutlinerView returns a sal_Bool, it only gets CommandEventId::StartDrag
2120 if (mpTextEditOutlinerView != nullptr)
2121 {
2122 if (rCEvt.GetCommand() == CommandEventId::StartDrag)
2123 {
2124 bool bPostIt = mpTextEditOutliner->IsInSelectionMode() || !rCEvt.IsMouseEvent();
2125 if (!bPostIt && rCEvt.IsMouseEvent())
2126 {
2127 Point aPt(rCEvt.GetMousePosPixel());
2128 if (pWin != nullptr)
2129 aPt = pWin->PixelToLogic(aPt);
2130 else if (mpTextEditWin != nullptr)
2131 aPt = mpTextEditWin->PixelToLogic(aPt);
2132 bPostIt = IsTextEditHit(aPt);
2133 }
2134 if (bPostIt)
2135 {
2136 Point aPixPos(rCEvt.GetMousePosPixel());
2137 if (rCEvt.IsMouseEvent() && pWin)
2138 {
2141 if (aPixPos.X() < aR.Left())
2142 aPixPos.setX(aR.Left());
2143 if (aPixPos.X() > aR.Right())
2144 aPixPos.setX(aR.Right());
2145 if (aPixPos.Y() < aR.Top())
2146 aPixPos.setY(aR.Top());
2147 if (aPixPos.Y() > aR.Bottom())
2148 aPixPos.setY(aR.Bottom());
2149 }
2150 CommandEvent aCEvt(aPixPos, rCEvt.GetCommand(), rCEvt.IsMouseEvent());
2151 // Command is void at the OutlinerView, sadly
2153 if (pWin != nullptr && pWin != mpTextEditWin)
2154 SetTextEditWin(pWin);
2156 return true;
2157 }
2158 }
2159 else
2160 {
2163 {
2164 // It could execute CommandEventId::ExtTextInput, while SdrObjEditView::KeyInput
2165 // isn't called
2166 if (mpTextEditOutliner && mpTextEditOutliner->IsModified())
2168 }
2169 return true;
2170 }
2171 }
2172 return SdrGlueEditView::Command(rCEvt, pWin);
2173}
2174
2176{
2177 bool bRet = false;
2178 if (mpTextEditOutliner != nullptr && mpTextEditOutlinerView != nullptr)
2179 {
2181 {
2182 const sal_Int32 nParaCnt = mpTextEditOutliner->GetParagraphCount();
2183 Paragraph* pLastPara
2184 = mpTextEditOutliner->GetParagraph(nParaCnt > 1 ? nParaCnt - 1 : 0);
2185
2187 if (aESel.nStartPara == 0 && aESel.nStartPos == 0 && aESel.nEndPara == (nParaCnt - 1))
2188 {
2189 if (mpTextEditOutliner->GetText(pLastPara).getLength() == aESel.nEndPos)
2190 bRet = true;
2191 }
2192 // in case the selection was done backwards
2193 if (!bRet && aESel.nEndPara == 0 && aESel.nEndPos == 0
2194 && aESel.nStartPara == (nParaCnt - 1))
2195 {
2196 if (mpTextEditOutliner->GetText(pLastPara).getLength() == aESel.nStartPos)
2197 bRet = true;
2198 }
2199 }
2200 else
2201 {
2202 bRet = true;
2203 }
2204 }
2205 return bRet;
2206}
2207
2209{
2210 if (mpTextEditOutlinerView != nullptr && mpTextEditWin != nullptr)
2211 {
2212 vcl::Cursor* pCsr = mpTextEditWin->GetCursor();
2213 if (pCsr != nullptr)
2214 {
2215 Size aSiz(pCsr->GetSize());
2216 if (!aSiz.IsEmpty())
2217 {
2219 }
2220 }
2221 }
2222}
2223
2225{
2226 SvtScriptType nScriptType = SvtScriptType::NONE;
2227
2228 if (IsTextEdit())
2229 {
2230 auto pText = mxWeakTextEditObj.get();
2231 if (pText->GetOutlinerParaObject())
2232 nScriptType = pText->GetOutlinerParaObject()->GetTextObject().GetScriptType();
2233
2236 }
2237 else
2238 {
2239 const size_t nMarkCount(GetMarkedObjectCount());
2240
2241 for (size_t i = 0; i < nMarkCount; ++i)
2242 {
2244
2245 if (pParaObj)
2246 {
2247 nScriptType |= pParaObj->GetTextObject().GetScriptType();
2248 }
2249 }
2250 }
2251
2252 if (nScriptType == SvtScriptType::NONE)
2253 nScriptType = SvtScriptType::LATIN;
2254
2255 return nScriptType;
2256}
2257
2258void SdrObjEditView::GetAttributes(SfxItemSet& rTargetSet, bool bOnlyHardAttr) const
2259{
2260 if (mxSelectionController.is())
2261 if (mxSelectionController->GetAttributes(rTargetSet, bOnlyHardAttr))
2262 return;
2263
2264 if (IsTextEdit())
2265 {
2267 "SdrObjEditView::GetAttributes(): mpTextEditOutlinerView=NULL");
2268 DBG_ASSERT(mpTextEditOutliner != nullptr,
2269 "SdrObjEditView::GetAttributes(): mpTextEditOutliner=NULL");
2270
2271 auto pText = mxWeakTextEditObj.get();
2272 // take care of bOnlyHardAttr(!)
2273 if (!bOnlyHardAttr && pText->GetStyleSheet())
2274 rTargetSet.Put(pText->GetStyleSheet()->GetItemSet());
2275
2276 // add object attributes
2277 rTargetSet.Put(pText->GetMergedItemSet());
2278
2280 {
2281 // FALSE= regard InvalidItems as "holes," not as Default
2282 rTargetSet.Put(mpTextEditOutlinerView->GetAttribs(), false);
2283 }
2284
2285 if (GetMarkedObjectCount() == 1 && GetMarkedObjectByIndex(0) == pText.get())
2286 {
2288 }
2289 }
2290 else
2291 {
2292 SdrGlueEditView::GetAttributes(rTargetSet, bOnlyHardAttr);
2293 }
2294}
2295
2296bool SdrObjEditView::SetAttributes(const SfxItemSet& rSet, bool bReplaceAll)
2297{
2298 bool bRet = false;
2300 bool bTextEdit = mpTextEditOutlinerView != nullptr && pTextEditObj != nullptr;
2301 bool bAllTextSelected = ImpIsTextEditAllSelected();
2302 const SfxItemSet* pSet = &rSet;
2303
2304 if (!bTextEdit)
2305 {
2306 // no TextEdit active -> all Items to drawing object
2307 if (mxSelectionController.is())
2308 bRet = mxSelectionController->SetAttributes(*pSet, bReplaceAll);
2309
2310 if (!bRet)
2311 {
2312 SdrGlueEditView::SetAttributes(*pSet, bReplaceAll);
2313 bRet = true;
2314 }
2315 }
2316 else
2317 {
2318#ifdef DBG_UTIL
2319 {
2320 bool bHasEEFeatureItems = false;
2321 SfxItemIter aIter(rSet);
2322 for (const SfxPoolItem* pItem = aIter.GetCurItem(); !bHasEEFeatureItems && pItem;
2323 pItem = aIter.NextItem())
2324 {
2325 if (!IsInvalidItem(pItem))
2326 {
2327 sal_uInt16 nW = pItem->Which();
2328 if (nW >= EE_FEATURE_START && nW <= EE_FEATURE_END)
2329 bHasEEFeatureItems = true;
2330 }
2331 }
2332
2333 if (bHasEEFeatureItems)
2334 {
2335 std::unique_ptr<weld::MessageDialog> xInfoBox(Application::CreateMessageDialog(
2336 nullptr, VclMessageType::Info, VclButtonsType::Ok,
2337 "SdrObjEditView::SetAttributes(): Setting EE_FEATURE items "
2338 "at the SdrView does not make sense! It only leads to "
2339 "overhead and unreadable documents."));
2340 xInfoBox->run();
2341 }
2342 }
2343#endif
2344
2345 bool bOnlyEEItems;
2346 bool bNoEEItems = !SearchOutlinerItems(*pSet, bReplaceAll, &bOnlyEEItems);
2347 // everything selected? -> attributes to the border, too
2348 // if no EEItems, attributes to the border only
2349 if (bAllTextSelected || bNoEEItems)
2350 {
2351 if (mxSelectionController.is())
2352 bRet = mxSelectionController->SetAttributes(*pSet, bReplaceAll);
2353
2354 if (!bRet)
2355 {
2356 const bool bUndo = IsUndoEnabled();
2357
2358 if (bUndo)
2359 {
2360 BegUndo(ImpGetDescriptionString(STR_EditSetAttributes));
2361 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pTextEditObj));
2362
2363 // If this is a text object also rescue the OutlinerParaObject since
2364 // applying attributes to the object may change text layout when
2365 // multiple portions exist with multiple formats. If an OutlinerParaObject
2366 // really exists and needs to be rescued is evaluated in the undo
2367 // implementation itself.
2368 bool bRescueText(pTextEditObj);
2369
2370 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoAttrObject(
2371 *pTextEditObj, false, !bNoEEItems || bRescueText));
2372 EndUndo();
2373 }
2374
2375 pTextEditObj->SetMergedItemSetAndBroadcast(*pSet, bReplaceAll);
2376
2377 FlushComeBackTimer(); // to set ModeHasChanged immediately
2378 }
2379 }
2380 else if (!bOnlyEEItems)
2381 {
2382 // Otherwise split Set, if necessary.
2383 // Now we build an ItemSet aSet that doesn't contain EE_Items from
2384 // *pSet (otherwise it would be a copy).
2385 WhichRangesContainer pNewWhichTable
2387 SfxItemSet aSet(mpModel->GetItemPool(), std::move(pNewWhichTable));
2388 SfxWhichIter aIter(aSet);
2389 sal_uInt16 nWhich = aIter.FirstWhich();
2390 while (nWhich != 0)
2391 {
2392 const SfxPoolItem* pItem;
2393 SfxItemState eState = pSet->GetItemState(nWhich, false, &pItem);
2394 if (eState == SfxItemState::SET)
2395 aSet.Put(*pItem);
2396 nWhich = aIter.NextWhich();
2397 }
2398
2399 if (mxSelectionController.is())
2400 bRet = mxSelectionController->SetAttributes(aSet, bReplaceAll);
2401
2402 if (!bRet)
2403 {
2404 if (IsUndoEnabled())
2405 {
2406 BegUndo(ImpGetDescriptionString(STR_EditSetAttributes));
2407 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pTextEditObj));
2408 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoAttrObject(*pTextEditObj));
2409 EndUndo();
2410 }
2411
2412 pTextEditObj->SetMergedItemSetAndBroadcast(aSet, bReplaceAll);
2413
2414 if (GetMarkedObjectCount() == 1 && GetMarkedObjectByIndex(0) == pTextEditObj.get())
2415 {
2417 }
2418 }
2420 }
2421 if (!bNoEEItems)
2422 {
2423 // and now the attributes to the EditEngine
2424 if (bReplaceAll)
2425 {
2427 }
2429
2431 if (mpModel && pTEOutliner && pTEOutliner->IsModified())
2433
2435 }
2436 bRet = true;
2437 }
2438 return bRet;
2439}
2440
2442{
2443 SfxStyleSheet* pSheet = nullptr;
2444
2445 if (mxSelectionController.is())
2446 {
2447 if (mxSelectionController->GetStyleSheet(pSheet))
2448 return pSheet;
2449 }
2450
2452 {
2454 }
2455 else
2456 {
2458 }
2459 return pSheet;
2460}
2461
2462void SdrObjEditView::SetStyleSheet(SfxStyleSheet* pStyleSheet, bool bDontRemoveHardAttr)
2463{
2464 if (mxSelectionController.is())
2465 {
2466 if (mxSelectionController->SetStyleSheet(pStyleSheet, bDontRemoveHardAttr))
2467 return;
2468 }
2469
2470 // if we are currently in edit mode we must also set the stylesheet
2471 // on all paragraphs in the Outliner for the edit view
2472 if (nullptr != mpTextEditOutlinerView)
2473 {
2475
2476 const sal_Int32 nParaCount = pOutliner->GetParagraphCount();
2477 for (sal_Int32 nPara = 0; nPara < nParaCount; nPara++)
2478 {
2479 pOutliner->SetStyleSheet(nPara, pStyleSheet);
2480 }
2481 }
2482
2483 SdrGlueEditView::SetStyleSheet(pStyleSheet, bDontRemoveHardAttr);
2484}
2485
2487{
2488 SdrGlueEditView::AddDeviceToPaintView(rNewDev, pWindow);
2489
2491 && rNewDev.GetOutDevType() == OUTDEV_WINDOW)
2492 {
2493 OutlinerView* pOutlView = ImpMakeOutlinerView(rNewDev.GetOwnerWindow(), nullptr);
2494 mpTextEditOutliner->InsertView(pOutlView);
2495 }
2496}
2497
2499{
2501
2503 && rOldDev.GetOutDevType() == OUTDEV_WINDOW)
2504 {
2505 for (size_t i = mpTextEditOutliner->GetViewCount(); i > 0;)
2506 {
2507 i--;
2508 OutlinerView* pOLV = mpTextEditOutliner->GetView(i);
2509 if (pOLV && pOLV->GetWindow() == rOldDev.GetOwnerWindow())
2510 {
2511 mpTextEditOutliner->RemoveView(i);
2512 }
2513 }
2514 }
2515
2516 lcl_RemoveTextEditOutlinerViews(this, GetSdrPageView(), &rOldDev);
2517}
2518
2520{
2521 return mpTextEditOutliner != nullptr && mpTextEditOutliner->IsInSelectionMode();
2522}
2523
2524// MacroMode
2525
2526void SdrObjEditView::BegMacroObj(const Point& rPnt, short nTol, SdrObject* pObj, SdrPageView* pPV,
2527 vcl::Window* pWin)
2528{
2529 BrkMacroObj();
2530 if (pObj != nullptr && pPV != nullptr && pWin != nullptr && pObj->HasMacro())
2531 {
2532 nTol = ImpGetHitTolLogic(nTol, nullptr);
2533 pMacroObj = pObj;
2534 pMacroPV = pPV;
2535 pMacroWin = pWin;
2536 mbMacroDown = false;
2537 nMacroTol = sal_uInt16(nTol);
2538 aMacroDownPos = rPnt;
2539 MovMacroObj(rPnt);
2540 }
2541}
2542
2543void SdrObjEditView::ImpMacroUp(const Point& rUpPos)
2544{
2545 if (pMacroObj != nullptr && mbMacroDown)
2546 {
2547 SdrObjMacroHitRec aHitRec;
2548 aHitRec.aPos = rUpPos;
2549 aHitRec.nTol = nMacroTol;
2550 aHitRec.pVisiLayer = &pMacroPV->GetVisibleLayers();
2551 aHitRec.pPageView = pMacroPV;
2552 pMacroObj->PaintMacro(*pMacroWin->GetOutDev(), tools::Rectangle(), aHitRec);
2553 mbMacroDown = false;
2554 }
2555}
2556
2557void SdrObjEditView::ImpMacroDown(const Point& rDownPos)
2558{
2559 if (pMacroObj != nullptr && !mbMacroDown)
2560 {
2561 SdrObjMacroHitRec aHitRec;
2562 aHitRec.aPos = rDownPos;
2563 aHitRec.nTol = nMacroTol;
2564 aHitRec.pVisiLayer = &pMacroPV->GetVisibleLayers();
2565 aHitRec.pPageView = pMacroPV;
2566 pMacroObj->PaintMacro(*pMacroWin->GetOutDev(), tools::Rectangle(), aHitRec);
2567 mbMacroDown = true;
2568 }
2569}
2570
2571void SdrObjEditView::MovMacroObj(const Point& rPnt)
2572{
2573 if (pMacroObj == nullptr)
2574 return;
2575
2576 SdrObjMacroHitRec aHitRec;
2577 aHitRec.aPos = rPnt;
2578 aHitRec.nTol = nMacroTol;
2579 aHitRec.pVisiLayer = &pMacroPV->GetVisibleLayers();
2580 aHitRec.pPageView = pMacroPV;
2581 bool bDown = pMacroObj->IsMacroHit(aHitRec);
2582 if (bDown)
2583 ImpMacroDown(rPnt);
2584 else
2585 ImpMacroUp(rPnt);
2586}
2587
2589{
2590 if (pMacroObj != nullptr)
2591 {
2593 pMacroObj = nullptr;
2594 pMacroPV = nullptr;
2595 pMacroWin = nullptr;
2596 }
2597}
2598
2600{
2601 if (pMacroObj != nullptr && mbMacroDown)
2602 {
2604 SdrObjMacroHitRec aHitRec;
2605 aHitRec.aPos = aMacroDownPos;
2606 aHitRec.nTol = nMacroTol;
2607 aHitRec.pVisiLayer = &pMacroPV->GetVisibleLayers();
2608 aHitRec.pPageView = pMacroPV;
2609 bool bRet = pMacroObj->DoMacro(aHitRec);
2610 pMacroObj = nullptr;
2611 pMacroPV = nullptr;
2612 pMacroWin = nullptr;
2613 return bRet;
2614 }
2615 else
2616 {
2617 BrkMacroObj();
2618 return false;
2619 }
2620}
2621
2624void SdrObjEditView::getTextSelection(css::uno::Any& rSelection)
2625{
2626 if (!IsTextEdit())
2627 return;
2628
2629 OutlinerView* pOutlinerView = GetTextEditOutlinerView();
2630 if (!(pOutlinerView && pOutlinerView->HasSelection()))
2631 return;
2632
2633 SdrObject* pObj = GetTextEditObject();
2634
2635 if (!pObj)
2636 return;
2637
2638 css::uno::Reference<css::text::XText> xText(pObj->getUnoShape(), css::uno::UNO_QUERY);
2639 if (xText.is())
2640 {
2641 SvxUnoTextBase* pRange = comphelper::getFromUnoTunnel<SvxUnoTextBase>(xText);
2642 if (pRange)
2643 {
2644 rSelection <<= pRange->createTextCursorBySelection(pOutlinerView->GetSelection());
2645 }
2646 }
2647}
2648
2649/* check if we have a single selection and that single object likes
2650 to handle the mouse and keyboard events itself
2651
2652 TODO: the selection controller should be queried from the
2653 object specific view contact. Currently this method only
2654 works for tables.
2655*/
2657{
2659
2660 if (mxSelectionController.is())
2661 {
2663 mxSelectionController->onSelectionHasChanged();
2664 }
2665
2666 mxSelectionController.clear();
2667
2668 const SdrMarkList& rMarkList = GetMarkedObjectList();
2669 if (rMarkList.GetMarkCount() != 1)
2670 return;
2671
2672 const SdrObject* pObj(rMarkList.GetMark(0)->GetMarkedSdrObj());
2673 SdrView* pView(dynamic_cast<SdrView*>(this));
2674
2675 // check for table
2676 if (pObj && pView && (pObj->GetObjInventor() == SdrInventor::Default)
2677 && (pObj->GetObjIdentifier() == SdrObjKind::Table))
2678 {
2680 *pView, static_cast<const sdr::table::SdrTableObj&>(*pObj), mxLastSelectionController);
2681
2682 if (mxSelectionController.is())
2683 {
2685 mxSelectionController->onSelectionHasChanged();
2686 }
2687 }
2688}
2689
2690IMPL_LINK(SdrObjEditView, EndPasteOrDropHdl, PasteOrDropInfos*, pInfo, void)
2691{
2692 OnEndPasteOrDrop(pInfo);
2693}
2694
2695IMPL_LINK(SdrObjEditView, BeginPasteOrDropHdl, PasteOrDropInfos*, pInfo, void)
2696{
2697 OnBeginPasteOrDrop(pInfo);
2698}
2699
2701{
2702 // applications can derive from these virtual methods to do something before a drop or paste operation
2703}
2704
2706{
2707 // applications can derive from these virtual methods to do something before a drop or paste operation
2708}
2709
2711{
2712 sal_uInt16 nLevel = 0xFFFF;
2713 if (IsTextEdit())
2714 {
2716 "SdrObjEditView::GetAttributes(): mpTextEditOutlinerView=NULL");
2717 DBG_ASSERT(mpTextEditOutliner != nullptr,
2718 "SdrObjEditView::GetAttributes(): mpTextEditOutliner=NULL");
2720 {
2721 //start and end position
2723 sal_uInt16 nStartPara = ::std::min(aSelect.nStartPara, aSelect.nEndPara);
2724 sal_uInt16 nEndPara = ::std::max(aSelect.nStartPara, aSelect.nEndPara);
2725 //get level from each paragraph
2726 nLevel = 0;
2727 for (sal_uInt16 nPara = nStartPara; nPara <= nEndPara; nPara++)
2728 {
2729 sal_uInt16 nParaDepth
2730 = 1 << static_cast<sal_uInt16>(mpTextEditOutliner->GetDepth(nPara));
2731 if (!(nLevel & nParaDepth))
2732 nLevel += nParaDepth;
2733 }
2734 //reduce one level for Outliner Object
2735 //if( nLevel > 0 && GetTextEditObject()->GetObjIdentifier() == OBJ_OUTLINETEXT )
2736 // nLevel = nLevel >> 1;
2737 //no bullet paragraph selected
2738 if (nLevel == 0)
2739 nLevel = 0xFFFF;
2740 }
2741 }
2742 return nLevel;
2743}
2744
2746 SdrObjKind nObjectIdentifier)
2747{
2748 if (nObjectInventor != SdrInventor::Default && nObjectInventor != SdrInventor::E3d)
2749 return false;
2750 switch (nObjectIdentifier)
2751 {
2752 case SdrObjKind::NONE:
2753 case SdrObjKind::Group:
2754 return false;
2755 case SdrObjKind::Line:
2767 case SdrObjKind::Text:
2771 case SdrObjKind::OLE2:
2772 case SdrObjKind::Table:
2773 return true;
2775 return false;
2776 case SdrObjKind::Edge:
2779 return true;
2780 case SdrObjKind::Page:
2783 case SdrObjKind::UNO:
2784 return false;
2786 return true;
2787 default:
2788 return false;
2789 }
2790}
2791
2792static const WhichRangesContainer& GetFormatRangeImpl(bool bTextOnly)
2793{
2794 static const WhichRangesContainer gFull(
2797 SDRATTR_MISC_LAST, // table cell formats
2801
2802 static const WhichRangesContainer gTextOnly(
2804 EE_CHAR_END>);
2805
2806 return bTextOnly ? gTextOnly : gFull;
2807}
2808
2809void SdrObjEditView::TakeFormatPaintBrush(std::shared_ptr<SfxItemSet>& rFormatSet)
2810{
2811 const SdrMarkList& rMarkList = GetMarkedObjectList();
2812 if (rMarkList.GetMarkCount() <= 0)
2813 return;
2814
2816
2817 rFormatSet = std::make_shared<SfxItemSet>(GetModel()->GetItemPool(),
2818 GetFormatRangeImpl(pOLV != nullptr));
2819 if (pOLV)
2820 {
2821 rFormatSet->Put(pOLV->GetAttribs());
2822 }
2823 else
2824 {
2825 const bool bOnlyHardAttr = false;
2826 rFormatSet->Put(GetAttrFromMarked(bOnlyHardAttr));
2827 }
2828
2829 // check for cloning from table cell, in which case we need to copy cell-specific formatting attributes
2830 const SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj();
2831 if (pObj && (pObj->GetObjInventor() == SdrInventor::Default)
2832 && (pObj->GetObjIdentifier() == SdrObjKind::Table))
2833 {
2834 auto pTable = static_cast<const sdr::table::SdrTableObj*>(pObj);
2835 if (mxSelectionController.is() && pTable->getActiveCell().is())
2836 {
2837 mxSelectionController->GetAttributes(*rFormatSet, false);
2838 }
2839 }
2840}
2841
2843 const SfxItemSet& rSourceSet, const SfxItemSet& rTargetSet,
2844 bool bNoCharacterFormats, bool bNoParagraphFormats)
2845{
2846 SfxItemSet aPaintSet(rPool, pRanges);
2847
2848 for (const auto& pRange : pRanges)
2849 {
2850 sal_uInt16 nWhich = pRange.first;
2851 const sal_uInt16 nLastWhich = pRange.second;
2852
2853 if (bNoCharacterFormats && (nWhich == EE_CHAR_START))
2854 continue;
2855
2856 if (bNoParagraphFormats && (nWhich == EE_PARA_START))
2857 continue;
2858
2859 for (; nWhich <= nLastWhich; nWhich++)
2860 {
2861 const SfxPoolItem* pSourceItem = rSourceSet.GetItem(nWhich);
2862 const SfxPoolItem* pTargetItem = rTargetSet.GetItem(nWhich);
2863
2864 if ((pSourceItem && !pTargetItem)
2865 || (pSourceItem && pTargetItem && *pSourceItem != *pTargetItem))
2866 {
2867 aPaintSet.Put(*pSourceItem);
2868 }
2869 }
2870 }
2871 return aPaintSet;
2872}
2873
2875 SdrText* pText, bool bNoCharacterFormats,
2876 bool bNoParagraphFormats)
2877{
2878 OutlinerParaObject* pParaObj = pText ? pText->GetOutlinerParaObject() : nullptr;
2879 if (!pParaObj)
2880 return;
2881
2882 SdrOutliner& rOutliner = rTextObj.ImpGetDrawOutliner();
2883 rOutliner.SetText(*pParaObj);
2884
2885 sal_Int32 nParaCount(rOutliner.GetParagraphCount());
2886
2887 if (!nParaCount)
2888 return;
2889
2890 for (sal_Int32 nPara = 0; nPara < nParaCount; nPara++)
2891 {
2892 if (!bNoCharacterFormats)
2893 rOutliner.RemoveCharAttribs(nPara);
2894
2895 SfxItemSet aSet(rOutliner.GetParaAttribs(nPara));
2896 aSet.Put(CreatePaintSet(GetFormatRangeImpl(true), *aSet.GetPool(), rFormatSet, aSet,
2897 bNoCharacterFormats, bNoParagraphFormats));
2898 rOutliner.SetParaAttribs(nPara, aSet);
2899 }
2900
2901 std::optional<OutlinerParaObject> pTemp = rOutliner.CreateParaObject(0, nParaCount);
2902 rOutliner.Clear();
2903
2904 rTextObj.NbcSetOutlinerParaObjectForText(std::move(pTemp), pText);
2905}
2906
2908{
2910 {
2911 if (typeid(mpTextEditOutliner->GetUndoManager()) != typeid(EditUndoManager))
2912 {
2913 // Non-owning pointer, clear it.
2914 mpTextEditOutliner->SetUndoManager(nullptr);
2915 }
2916 }
2917
2918 mpOldTextEditUndoManager = nullptr;
2919}
2920
2921void SdrObjEditView::ApplyFormatPaintBrush(SfxItemSet& rFormatSet, bool bNoCharacterFormats,
2922 bool bNoParagraphFormats)
2923{
2924 if (mxSelectionController.is()
2925 && mxSelectionController->ApplyFormatPaintBrush(rFormatSet, bNoCharacterFormats,
2926 bNoParagraphFormats))
2927 {
2928 return;
2929 }
2930
2932 const SdrMarkList& rMarkList = GetMarkedObjectList();
2933 if (!pOLV)
2934 {
2935 SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj();
2936 const SfxItemSet& rShapeSet = pObj->GetMergedItemSet();
2937
2938 // if not in text edit mode (aka the user selected text or clicked on a word)
2939 // apply formatting attributes to selected shape
2940 // All formatting items (see ranges above) that are unequal in selected shape and
2941 // the format paintbrush are hard set on the selected shape.
2942
2943 const WhichRangesContainer& pRanges = rFormatSet.GetRanges();
2944 bool bTextOnly = true;
2945
2946 for (const auto& pRange : pRanges)
2947 {
2948 if ((pRange.first != EE_PARA_START) && (pRange.first != EE_CHAR_START))
2949 {
2950 bTextOnly = false;
2951 break;
2952 }
2953 }
2954
2955 if (!bTextOnly)
2956 {
2957 SfxItemSet aPaintSet(CreatePaintSet(GetFormatRangeImpl(false), *rShapeSet.GetPool(),
2958 rFormatSet, rShapeSet, bNoCharacterFormats,
2959 bNoParagraphFormats));
2960 SetAttrToMarked(aPaintSet, false /*bReplaceAll*/);
2961 }
2962
2963 // now apply character and paragraph formatting to text, if the shape has any
2964 SdrTextObj* pTextObj = DynCastSdrTextObj(pObj);
2965 if (pTextObj)
2966 {
2967 sal_Int32 nText = pTextObj->getTextCount();
2968
2969 while (--nText >= 0)
2970 {
2971 SdrText* pText = pTextObj->getText(nText);
2972 ApplyFormatPaintBrushToText(rFormatSet, *pTextObj, pText, bNoCharacterFormats,
2973 bNoParagraphFormats);
2974 }
2975 }
2976 }
2977 else
2978 {
2979 ::Outliner* pOutliner = pOLV->GetOutliner();
2980 if (pOutliner)
2981 {
2982 const EditEngine& rEditEngine = pOutliner->GetEditEngine();
2983
2984 ESelection aSel(pOLV->GetSelection());
2985 if (!aSel.HasRange())
2986 pOLV->SetSelection(rEditEngine.GetWord(aSel, css::i18n::WordType::DICTIONARY_WORD));
2987
2988 const bool bRemoveParaAttribs = !bNoParagraphFormats;
2989 pOLV->RemoveAttribsKeepLanguages(bRemoveParaAttribs);
2990 SfxItemSet aSet(pOLV->GetAttribs());
2991 SfxItemSet aPaintSet(CreatePaintSet(GetFormatRangeImpl(true), *aSet.GetPool(),
2992 rFormatSet, aSet, bNoCharacterFormats,
2993 bNoParagraphFormats));
2994 pOLV->SetAttribs(aPaintSet);
2995 }
2996 }
2997
2998 // check for cloning to table cell, in which case we need to copy cell-specific formatting attributes
2999 SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj();
3000 if (pObj && (pObj->GetObjInventor() == SdrInventor::Default)
3001 && (pObj->GetObjIdentifier() == SdrObjKind::Table))
3002 {
3003 auto pTable = static_cast<sdr::table::SdrTableObj*>(pObj);
3004 if (pTable->getActiveCell().is() && mxSelectionController.is())
3005 {
3006 mxSelectionController->SetAttributes(rFormatSet, false);
3007 }
3008 }
3009}
3010
3011/* 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, bool bMobile=false)
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:182
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:132
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:1146
const SfxItemPool & GetItemPool() const
Definition: svdmodel.hxx:318
SdrUndoFactory & GetSdrUndoFactory() const
returns the models undo factory.
Definition: svdmodel.cxx:1845
OutputDevice * GetRefDevice() const
Definition: svdmodel.hxx:334
bool SetAttributes(const SfxItemSet &rSet, bool bReplaceAll)
Definition: svdedxv.cxx:2296
sal_uInt16 GetSelectionLevel() const
Definition: svdedxv.cxx:2710
bool IsTextEditInSelectionMode() const
Definition: svdedxv.cxx:2519
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:2599
virtual void DeleteDeviceFromPaintView(OutputDevice &rOldWin) override
Definition: svdedxv.cxx:2498
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:2175
vcl::Cursor * pTextEditCursorBuffer
Definition: svdedxv.hxx:90
SdrPageView * pMacroPV
Definition: svdedxv.hxx:92
virtual void OnBeginPasteOrDrop(PasteOrDropInfos *pInfo)
Definition: svdedxv.cxx:2700
virtual ~SdrObjEditView() override
Definition: svdedxv.cxx:93
bool mbTextEditDontDelete
Definition: svdedxv.hxx:102
OutlinerView * ImpFindOutlinerView(vcl::Window const *pWin) const
Definition: svdedxv.cxx:1844
virtual void OnEndPasteOrDrop(PasteOrDropInfos *pInfo)
Definition: svdedxv.cxx:2705
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:2745
virtual SdrEndTextEditKind SdrEndTextEdit(bool bDontDeleteReally=false)
Definition: svdedxv.cxx:1570
virtual bool KeyInput(const KeyEvent &rKEvt, vcl::Window *pWin) override
Definition: svdedxv.cxx:1957
void DisposeUndoManager()
Definition: svdedxv.cxx:2907
virtual void EditViewInputContext(const InputContext &rInputContext) override
Definition: svdedxv.cxx:830
void MovMacroObj(const Point &rPnt)
Definition: svdedxv.cxx:2571
const OutlinerView * GetTextEditOutlinerView() const
Definition: svdedxv.hxx:252
virtual bool MouseButtonUp(const MouseEvent &rMEvt, OutputDevice *pWin) override
Definition: svdedxv.cxx:2036
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:2874
virtual bool MouseMove(const MouseEvent &rMEvt, OutputDevice *pWin) override
handle mouse over effects for handles
Definition: svdedxv.cxx:2074
std::unique_ptr< TextChainCursorManager > ImpHandleMotionThroughBoxesKeyInput(const KeyEvent &rKEvt, bool *bOutHandled)
Definition: svdedxv.cxx:1934
void getTextSelection(css::uno::Any &rSelection)
fills the given any with a XTextCursor for the current text selection.
Definition: svdedxv.cxx:2624
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:2258
sdr::overlay::OverlayObjectList maTEOverlayGroup
Definition: svdedxv.hxx:80
void BrkMacroObj()
Definition: svdedxv.cxx:2588
virtual bool IsAction() const override
Definition: svdedxv.cxx:103
bool IsTextEditFrameHit(const Point &rHit) const
Definition: svdedxv.cxx:1904
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:1861
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:2208
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:2809
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:1992
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:2921
virtual css::uno::Reference< css::datatransfer::dnd::XDropTarget > GetDropTarget() override
Definition: svdedxv.cxx:823
void ImpMacroDown(const Point &rDownPos)
Definition: svdedxv.cxx:2557
SdrPageView * GetTextEditPageView() const
Definition: svdedxv.cxx:1842
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:2526
SfxStyleSheet * GetStyleSheet() const
Definition: svdedxv.cxx:2441
void SetStyleSheet(SfxStyleSheet *pStyleSheet, bool bDontRemoveHardAttr)
Definition: svdedxv.cxx:2462
tools::Rectangle aTextEditArea
Definition: svdedxv.hxx:95
virtual bool Command(const CommandEvent &rCEvt, vcl::Window *pWin) override
Definition: svdedxv.cxx:2117
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:1881
virtual void AddDeviceToPaintView(OutputDevice &rNewDev, vcl::Window *pWindow) override
Definition: svdedxv.cxx:2486
void TextEditDrawing(SdrPaintWindow &rPaintWindow)
Definition: svdedxv.cxx:844
virtual bool IsTextEdit() const final override
Definition: svdedxv.cxx:1839
virtual void MarkListHasChanged() override
Definition: svdedxv.cxx:2656
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:2224
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:2543
const SdrPageView * pPageView
Definition: svdobj.hxx:141
const SdrLayerIDSet * pVisiLayer
Definition: svdobj.hxx:140
sal_uInt16 nTol
Definition: svdobj.hxx:142
Abstract DrawObject.
Definition: svdobj.hxx:261
virtual bool DoMacro(const SdrObjMacroHitRec &rRec)
Definition: svdobj.cxx:1887
virtual SdrInventor GetObjInventor() const
Definition: svdobj.cxx:621
virtual OutlinerParaObject * GetOutlinerParaObject() const
Definition: svdobj.cxx:1836
virtual css::uno::Reference< css::drawing::XShape > getUnoShape()
Definition: svdobj.cxx:2869
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:1870
virtual SdrObjKind GetObjIdentifier() const
Definition: svdobj.cxx:626
SdrPage * getSdrPageFromSdrObject() const
Definition: svdobj.cxx:279
const SfxItemSet & GetMergedItemSet() const
Definition: svdobj.cxx:1977
bool IsMacroHit(const SdrObjMacroHitRec &rRec) const
Definition: svdobj.cxx:1892
virtual SdrLayerID GetLayer() const
Definition: svdobj.cxx:645
virtual bool HasMacro() const
Definition: svdobj.cxx:1850
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:399
virtual void AddDeviceToPaintView(OutputDevice &rNewDev, vcl::Window *pWindow)
Definition: svdpntv.cxx:388
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:359
SdrModel * GetModel() const
Definition: svdpntv.hxx:261
virtual void MakeVisible(const tools::Rectangle &rRect, vcl::Window &rWin)
Definition: svdpntv.cxx:1014
sal_uInt16 ImpGetHitTolLogic(short nHitTol, const OutputDevice *pOut) const
Definition: svdpntv.cxx:319
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:864
virtual bool KeyInput(const KeyEvent &rKEvt, vcl::Window *pWin)
Definition: svdpntv.cxx:785
sal_uInt32 PaintWindowCount() const
Definition: svdpntv.hxx:219
virtual bool MouseButtonDown(const MouseEvent &, OutputDevice *)
Definition: svdpntv.hxx:449
SdrPageView * GetSdrPageView() const
Definition: svdpntv.hxx:300
void FlushComeBackTimer() const
Definition: svdpntv.cxx:248
SdrModel * mpModel
Definition: svdpntv.hxx:125
const vcl::Region & GetRedrawRegion() const
OutputDevice & GetTargetOutputDevice()
OutputDevice & GetOutputDevice() const
bool OutputToWindow() const
vcl::Window * GetWindow() const
SdrOutliner & ImpGetDrawOutliner() const
Definition: svdotext.cxx:1179
bool IsFitToSize() const
returns true if the old feature for fitting shape content should into shape is enabled....
Definition: svdotext.cxx:1872
void NbcSetOutlinerParaObjectForText(std::optional< OutlinerParaObject > pTextObject, SdrText *pText)
Definition: svdotext.cxx:1367
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:452
virtual sal_Int32 getTextCount() const override
returns the number of texts available for this object.
Definition: svdotext.cxx:2103
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:332
virtual SdrObjKind GetObjIdentifier() const override
Definition: svdotext.cxx:447
virtual SdrText * getText(sal_Int32 nIndex) const override
returns the nth available text.
Definition: svdotext.cxx:2088
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 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:2842
IMPL_LINK(SdrObjEditView, ImpOutlinerStatusEventHdl, EditStatus &, rEditStat, void)
Definition: svdedxv.cxx:1061
static const WhichRangesContainer & GetFormatRangeImpl(bool bTextOnly)
Definition: svdedxv.cxx:2792
SdrEndTextEditKind
Definition: svdedxv.hxx:50
WhichRangesContainer RemoveWhichRange(const WhichRangesContainer &pOldWhichTable, sal_uInt16 nRangeBeg, sal_uInt16 nRangeEnd)
Definition: svdetc.cxx:383
bool SearchOutlinerItems(const SfxItemSet &rSet, bool bInklDefaults, bool *pbOnlyEE)
Search an ItemSet for Outliner/EditEngine Items.
Definition: svdetc.cxx:360
Color GetTextEditBackgroundColor(const SdrObjEditView &rView)
Definition: svdetc.cxx:681
std::unique_ptr< SdrOutliner > SdrMakeOutliner(OutlinerMode nOutlinerMode, SdrModel &rModel)
Create an Outliner with the engine-global default settings on the heap.
Definition: svdetc.cxx:340
SdrHintKind
Definition: svdmodel.hxx:102
SdrTextObj * DynCastSdrTextObj(SdrObject *pObj)
Definition: svdobj.cxx:3217
SdrInventor
Definition: svdobj.hxx:99
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)