cid#1607171 Data race condition
[LibreOffice.git] / sd / source / ui / view / sdview.cxx
blob5a6be3034fb89bb7ad7b79b42995cd08ee115af6
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <config_features.h>
22 #include <com/sun/star/embed/NoVisualAreaSizeException.hpp>
23 #include <com/sun/star/embed/XEmbeddedObject.hpp>
24 #include <com/sun/star/linguistic2/XSpellChecker1.hpp>
26 #include <View.hxx>
27 #include <slideshow.hxx>
28 #include <avmedia/mediawindow.hxx>
29 #include <editeng/outlobj.hxx>
30 #include <editeng/unolingu.hxx>
31 #include <o3tl/deleter.hxx>
32 #include <svx/obj3d.hxx>
33 #include <svx/fmview.hxx>
34 #include <editeng/outliner.hxx>
35 #include <svx/svdograf.hxx>
36 #include <svx/svdoole2.hxx>
37 #include <svx/svdundo.hxx>
39 #include <vcl/settings.hxx>
41 #include <officecfg/Office/Common.hxx>
42 #include <officecfg/Office/Impress.hxx>
43 #include <sfx2/dispatch.hxx>
44 #include <svx/svdpagv.hxx>
45 #include <svx/svdoutl.hxx>
46 #include <svx/sdr/contact/displayinfo.hxx>
47 #include <unotools/configmgr.hxx>
49 #include <svx/svdetc.hxx>
50 #include <editeng/editstat.hxx>
52 #include <sfx2/viewfrm.hxx>
53 #include <toolkit/helper/vclunohelper.hxx>
54 #include <svx/xfillit0.hxx>
56 #include <app.hrc>
57 #include <strings.hrc>
58 #include <Window.hxx>
59 #include <Client.hxx>
60 #include <drawdoc.hxx>
61 #include <DrawDocShell.hxx>
62 #include <sdmod.hxx>
63 #include <sdpage.hxx>
64 #include <sdresid.hxx>
65 #include <unokywds.hxx>
66 #include <ViewClipboard.hxx>
67 #include <undo/undomanager.hxx>
68 #include <svx/sdr/contact/viewobjectcontact.hxx>
69 #include <svx/sdr/contact/viewcontact.hxx>
70 #include <svx/svdotable.hxx>
71 #include <EventMultiplexer.hxx>
72 #include <ViewShellBase.hxx>
73 #include <ViewShell.hxx>
75 #include <basegfx/polygon/b2dpolygontools.hxx>
76 #include <basegfx/color/bcolor.hxx>
77 #include <drawinglayer/attribute/lineattribute.hxx>
78 #include <drawinglayer/attribute/strokeattribute.hxx>
79 #include <drawinglayer/primitive2d/textlayoutdevice.hxx>
80 #include <drawinglayer/primitive2d/PolygonStrokePrimitive2D.hxx>
81 #include <svx/sdr/contact/objectcontact.hxx>
82 #include <svx/sdr/table/tablecontroller.hxx>
83 #include <basegfx/matrix/b2dhommatrix.hxx>
84 #include <drawinglayer/primitive2d/textprimitive2d.hxx>
85 #include <svx/unoapi.hxx>
86 #include <basegfx/matrix/b2dhommatrixtools.hxx>
87 #include <comphelper/lok.hxx>
88 #include <sfx2/lokhelper.hxx>
89 #include <LibreOfficeKit/LibreOfficeKitEnums.h>
90 #include <DrawController.hxx>
92 #include <memory>
93 #include <numeric>
95 using namespace com::sun::star;
96 using namespace com::sun::star::uno;
97 using namespace sdr::table;
98 namespace sd {
100 View::View(
101 SdDrawDocument& rDrawDoc,
102 OutputDevice* pOutDev,
103 ViewShell* pViewShell)
104 : FmFormView(rDrawDoc, pOutDev),
105 mrDoc(rDrawDoc),
106 mpDocSh(rDrawDoc.GetDocSh()),
107 mpViewSh(pViewShell),
108 mpDropMarkerObj(nullptr),
109 mnDragSrcPgNum(SDRPAGE_NOTFOUND),
110 mnAction(DND_ACTION_NONE),
111 maDropErrorIdle("sd View DropError"),
112 maDropInsertFileIdle("sd View DropInsertFile"),
113 mnLockRedrawSmph(0),
114 mbIsDropAllowed(true),
115 maSmartTags(*this),
116 mpClipboard (new ViewClipboard (*this))
118 // #i73602# Use default from the configuration
119 SetBufferedOverlayAllowed(!comphelper::IsFuzzing() && officecfg::Office::Common::Drawinglayer::OverlayBuffer_DrawImpress::get());
121 // #i74769#, #i75172# Use default from the configuration
122 SetBufferedOutputAllowed(!comphelper::IsFuzzing() && officecfg::Office::Common::Drawinglayer::PaintBuffer_DrawImpress::get());
124 EnableExtendedKeyInputDispatcher(false);
125 EnableExtendedMouseEventDispatcher(false);
127 SetUseIncompatiblePathCreateInterface(false);
129 SetMinMoveDistancePixel(2);
130 SetHitTolerancePixel(2);
131 SetMeasureLayer(sUNO_LayerName_measurelines);
133 // Timer for delayed drop (has to be for MAC)
134 maDropErrorIdle.SetInvokeHandler( LINK(this, View, DropErrorHdl) );
135 maDropInsertFileIdle.SetInvokeHandler( LINK(this, View, DropInsertFileHdl) );
138 void View::ImplClearDrawDropMarker()
140 mpDropMarker.reset();
143 View::~View()
145 maSmartTags.Dispose();
147 // release content of selection clipboard, if we own the content
148 ClearSelectionClipboard();
150 #if HAVE_FEATURE_AVMEDIA
151 if (mxDropMediaSizeListener)
153 suppress_fun_call_w_exception(mxDropMediaSizeListener->dispose());
154 mxDropMediaSizeListener.clear();
156 #endif
158 maDropErrorIdle.Stop();
159 maDropInsertFileIdle.Stop();
161 ImplClearDrawDropMarker();
163 while(PaintWindowCount())
165 // remove all registered OutDevs
166 suppress_fun_call_w_exception(DeleteDeviceFromPaintView(*GetFirstOutputDevice()));
170 namespace {
172 class ViewRedirector : public sdr::contact::ViewObjectContactRedirector
174 public:
175 ViewRedirector();
177 // all default implementations just call the same methods at the original. To do something
178 // different, override the method and at least do what the method does.
179 virtual void createRedirectedPrimitive2DSequence(
180 const sdr::contact::ViewObjectContact& rOriginal,
181 const sdr::contact::DisplayInfo& rDisplayInfo,
182 drawinglayer::primitive2d::Primitive2DDecompositionVisitor& rVisitor) override;
187 ViewRedirector::ViewRedirector()
191 void ViewRedirector::createRedirectedPrimitive2DSequence(
192 const sdr::contact::ViewObjectContact& rOriginal,
193 const sdr::contact::DisplayInfo& rDisplayInfo,
194 drawinglayer::primitive2d::Primitive2DDecompositionVisitor& rVisitor)
196 SdrObject* pObject = rOriginal.GetViewContact().TryToGetSdrObject();
197 SdrPage* pSdrPage = pObject ? pObject->getSdrPageFromSdrObject() : nullptr;
198 if(!pObject || !pSdrPage)
200 // not a SdrObject visualisation (maybe e.g. page) or no page
201 sdr::contact::ViewObjectContactRedirector::createRedirectedPrimitive2DSequence(rOriginal, rDisplayInfo, rVisitor);
202 return;
205 const bool bDoCreateGeometry(pSdrPage->checkVisibility( rOriginal, rDisplayInfo, true ));
207 if(!bDoCreateGeometry &&
208 (( pObject->GetObjInventor() != SdrInventor::Default ) || ( pObject->GetObjIdentifier() != SdrObjKind::Page )) )
209 return;
211 PresObjKind eKind(PresObjKind::NONE);
212 const bool bSubContentProcessing(rDisplayInfo.GetSubContentActive());
213 const bool bIsMasterPageObject(pSdrPage->IsMasterPage());
214 const bool bIsPrinting(rOriginal.GetObjectContact().isOutputToPrinter());
215 const SdrPageView* pPageView = rOriginal.GetObjectContact().TryToGetSdrPageView();
216 const SdrPage* pVisualizedPage = GetSdrPageFromXDrawPage(rOriginal.GetObjectContact().getViewInformation2D().getVisualizedPage());
217 const SdPage* pObjectsSdPage = dynamic_cast< SdPage* >(pSdrPage);
218 const bool bIsInsidePageObj(pPageView && pPageView->GetPage() != pVisualizedPage);
220 // check if we need to draw a placeholder border. Never do it for
221 // objects inside a SdrPageObj and never when printing
222 if(!bIsInsidePageObj && !bIsPrinting)
224 bool bCreateOutline(false);
226 if( pObject->IsEmptyPresObj() && DynCastSdrTextObj( pObject ) != nullptr )
228 if( !bSubContentProcessing || !pObject->IsNotVisibleAsMaster() )
230 eKind = pObjectsSdPage ? pObjectsSdPage->GetPresObjKind(pObject) : PresObjKind::NONE;
231 bCreateOutline = true;
234 else if( ( pObject->GetObjInventor() == SdrInventor::Default ) && ( pObject->GetObjIdentifier() == SdrObjKind::Text ) )
236 if( pObjectsSdPage )
238 eKind = pObjectsSdPage->GetPresObjKind(pObject);
240 if((eKind == PresObjKind::Footer) || (eKind == PresObjKind::Header) || (eKind == PresObjKind::DateTime) || (eKind == PresObjKind::SlideNumber) )
242 if( !bSubContentProcessing )
244 // only draw a boundary for header&footer objects on the masterpage itself
245 bCreateOutline = true;
250 else if( ( pObject->GetObjInventor() == SdrInventor::Default ) && ( pObject->GetObjIdentifier() == SdrObjKind::Page ) )
252 // only for handout page, else this frame will be created for each
253 // page preview object in SlideSorter and PagePane
254 if(pObjectsSdPage && PageKind::Handout == pObjectsSdPage->GetPageKind())
256 bCreateOutline = true;
259 if (bCreateOutline)
260 bCreateOutline = officecfg::Office::Impress::Misc::TextObject::ShowBoundary::get();
262 if(bCreateOutline)
264 // empty presentation objects get a gray frame
265 const svtools::ColorConfig aColorConfig;
266 const svtools::ColorConfigValue aColor( aColorConfig.GetColorValue( svtools::DOCBOUNDARIES ) );
268 // get basic object transformation
269 const basegfx::BColor aRGBColor(aColor.nColor.getBColor());
270 basegfx::B2DHomMatrix aObjectMatrix;
271 basegfx::B2DPolyPolygon aObjectPolyPolygon;
272 pObject->TRGetBaseGeometry(aObjectMatrix, aObjectPolyPolygon);
274 // create dashed border
276 // create object polygon
277 basegfx::B2DPolygon aPolygon(basegfx::utils::createUnitPolygon());
278 aPolygon.transform(aObjectMatrix);
280 // create line and stroke attribute
281 ::std::vector< double > aDotDashArray { 160.0, 80.0 };
283 const double fFullDotDashLen(::std::accumulate(aDotDashArray.begin(), aDotDashArray.end(), 0.0));
284 const drawinglayer::attribute::LineAttribute aLine(aRGBColor);
285 drawinglayer::attribute::StrokeAttribute aStroke(std::move(aDotDashArray), fFullDotDashLen);
287 // create primitive and add
288 const drawinglayer::primitive2d::Primitive2DReference xRef(new drawinglayer::primitive2d::PolygonStrokePrimitive2D(
289 std::move(aPolygon),
290 aLine,
291 std::move(aStroke)));
292 rVisitor.visit(xRef);
295 // now paint the placeholder description, but only when masterpage
296 // is displayed as page directly (MasterPage view)
297 if(!bSubContentProcessing && bIsMasterPageObject)
299 OUString aObjectString;
301 switch( eKind )
303 case PresObjKind::Title:
305 if(pObjectsSdPage && pObjectsSdPage->GetPageKind() == PageKind::Standard)
307 static OUString aTitleAreaStr(SdResId(STR_PLACEHOLDER_DESCRIPTION_TITLE));
308 aObjectString = aTitleAreaStr;
311 break;
313 case PresObjKind::Outline:
315 static OUString aOutlineAreaStr(SdResId(STR_PLACEHOLDER_DESCRIPTION_OUTLINE));
316 aObjectString = aOutlineAreaStr;
317 break;
319 case PresObjKind::Footer:
321 static OUString aFooterAreaStr(SdResId(STR_PLACEHOLDER_DESCRIPTION_FOOTER));
322 aObjectString = aFooterAreaStr;
323 break;
325 case PresObjKind::Header:
327 static OUString aHeaderAreaStr(SdResId(STR_PLACEHOLDER_DESCRIPTION_HEADER));
328 aObjectString = aHeaderAreaStr;
329 break;
331 case PresObjKind::DateTime:
333 static OUString aDateTimeStr(SdResId(STR_PLACEHOLDER_DESCRIPTION_DATETIME));
334 aObjectString = aDateTimeStr;
335 break;
337 case PresObjKind::Notes:
339 static OUString aDateTimeStr(SdResId(STR_PLACEHOLDER_DESCRIPTION_NOTES));
340 aObjectString = aDateTimeStr;
341 break;
343 case PresObjKind::SlideNumber:
345 if(pObjectsSdPage && pObjectsSdPage->GetPageKind() == PageKind::Standard)
347 static OUString aSlideAreaStr(SdResId(STR_PLACEHOLDER_DESCRIPTION_SLIDE));
348 aObjectString = aSlideAreaStr;
350 else
352 static OUString aNumberAreaStr(SdResId(STR_PLACEHOLDER_DESCRIPTION_NUMBER));
353 aObjectString = aNumberAreaStr;
355 break;
357 default:
359 break;
363 if( !aObjectString.isEmpty() )
365 // decompose object matrix to be able to place text correctly
366 basegfx::B2DTuple aScale;
367 basegfx::B2DTuple aTranslate;
368 double fRotate, fShearX;
369 aObjectMatrix.decompose(aScale, aTranslate, fRotate, fShearX);
371 // create font
372 SdrTextObj* pTextObj = DynCastSdrTextObj( pObject );
373 const SdrTextVertAdjust eTVA(pTextObj ? pTextObj->GetTextVerticalAdjust() : SDRTEXTVERTADJUST_CENTER);
374 vcl::Font aScaledVclFont;
376 // use a text size factor to get more reliable text sizes from the text layouter
377 // (and from vcl), tipp from HDU
378 static const sal_uInt32 nTextSizeFactor(100);
380 // use a factor to get more linear text size calculations
381 aScaledVclFont.SetFontHeight( 500 * nTextSizeFactor );
383 // get basic geometry and get text size
384 drawinglayer::primitive2d::TextLayouterDevice aTextLayouter;
385 aTextLayouter.setFont(aScaledVclFont);
386 const sal_Int32 nTextLength(aObjectString.getLength());
388 // do not forget to use the factor again to get the width for the 500
389 const double fTextWidth(aTextLayouter.getTextWidth(aObjectString, 0, nTextLength) * (1.0 / nTextSizeFactor));
390 const double fTextHeight(aTextLayouter.getTextHeight() * (1.0 / nTextSizeFactor));
392 // calculate text primitive position. If text is at bottom, use top for
393 // the extra text and vice versa
394 const double fHorDist(125);
395 const double fVerDist(125);
396 const double fPosX((aTranslate.getX() + aScale.getX()) - fTextWidth - fHorDist);
397 const double fPosY((SDRTEXTVERTADJUST_BOTTOM == eTVA)
398 ? aTranslate.getY() - fVerDist + fTextHeight
399 : (aTranslate.getY() + aScale.getY()) - fVerDist);
401 // get font attributes; use normally scaled font
402 vcl::Font aVclFont;
403 basegfx::B2DVector aTextSizeAttribute;
405 aVclFont.SetFontHeight( 500 );
407 drawinglayer::attribute::FontAttribute aFontAttribute(
408 drawinglayer::primitive2d::getFontAttributeFromVclFont(
409 aTextSizeAttribute,
410 aVclFont,
411 false,
412 false));
414 // fill text matrix
415 const basegfx::B2DHomMatrix aTextMatrix(basegfx::utils::createScaleShearXRotateTranslateB2DHomMatrix(
416 aTextSizeAttribute.getX(), aTextSizeAttribute.getY(),
417 fShearX,
418 fRotate,
419 fPosX, fPosY));
421 // create DXTextArray (can be empty one)
422 ::std::vector< double > aDXArray{};
424 // create locale; this may need some more information in the future
425 css::lang::Locale aLocale;
427 // create primitive and add
428 const drawinglayer::primitive2d::Primitive2DReference xRef(
429 new drawinglayer::primitive2d::TextSimplePortionPrimitive2D(
430 aTextMatrix,
431 aObjectString,
433 nTextLength,
434 std::move(aDXArray),
436 std::move(aFontAttribute),
437 std::move(aLocale),
438 aRGBColor));
439 rVisitor.visit(xRef);
445 if(bDoCreateGeometry)
447 sdr::contact::ViewObjectContactRedirector::createRedirectedPrimitive2DSequence(
448 rOriginal,
449 rDisplayInfo, rVisitor);
453 namespace
455 void setOutlinerBgFromPage(::Outliner& rOutl, SdrPageView& rPgView, bool bScreenDisplay)
457 SdrPage* pPage = rPgView.GetPage();
458 if (pPage)
460 // #i75566# Name change GetBackgroundColor -> GetPageBackgroundColor and
461 // hint value if screen display. Only then the AutoColor mechanisms shall be applied
462 rOutl.SetBackgroundColor(pPage->GetPageBackgroundColor(&rPgView, bScreenDisplay));
468 * The event will be forwarded to the View
470 void View::CompleteRedraw(OutputDevice* pOutDev, const vcl::Region& rReg, sdr::contact::ViewObjectContactRedirector* pRedirector /*=0*/)
472 // execute ??
473 if (mnLockRedrawSmph != 0)
474 return;
476 SdrPageView* pPgView = GetSdrPageView();
478 if (pPgView)
480 SdPage* pPage = static_cast<SdPage*>( pPgView->GetPage() );
481 if( pPage )
483 SdrOutliner& rOutl = mrDoc.GetDrawOutliner();
484 bool bScreenDisplay(true);
486 // #i75566# printing; suppress AutoColor BackgroundColor generation
487 // for visibility reasons by giving GetPageBackgroundColor()
488 // the needed hint
489 // #i75566# PDF export; suppress AutoColor BackgroundColor generation (see printing)
490 if (pOutDev && ((OUTDEV_PRINTER == pOutDev->GetOutDevType())
491 || (OUTDEV_PDF == pOutDev->GetOutDevType())))
492 bScreenDisplay = false;
494 setOutlinerBgFromPage(rOutl, *pPgView, bScreenDisplay);
498 ViewRedirector aViewRedirector;
499 FmFormView::CompleteRedraw(pOutDev, rReg, pRedirector ? pRedirector : &aViewRedirector);
502 void View::MarkListHasChanged()
504 FmFormView::MarkListHasChanged();
506 const SdrMarkList& rMarkList = GetMarkedObjectList();
507 if( rMarkList.GetMarkCount() > 0 )
508 maSmartTags.deselect();
511 bool View::SetAttributes(const SfxItemSet& rSet, bool bReplaceAll, bool /*bSlide*/, bool /*bMaster*/)
513 bool bOk = FmFormView::SetAttributes(rSet, bReplaceAll);
514 return bOk;
517 void View::GetAttributes( SfxItemSet& rTargetSet, bool bOnlyHardAttr ) const
519 FmFormView::GetAttributes( rTargetSet, bOnlyHardAttr );
523 * Is a presentation object selected?
525 bool View::IsPresObjSelected(bool bOnPage, bool bOnMasterPage, bool bCheckPresObjListOnly, bool bCheckLayoutOnly) const
527 SdrMarkList* pMarkList;
529 if (mnDragSrcPgNum != SDRPAGE_NOTFOUND &&
530 mnDragSrcPgNum != GetSdrPageView()->GetPage()->GetPageNum())
532 /* Drag&Drop is in progress
533 Source and destination page are different:
534 we use the saved mark list */
535 pMarkList = mpDragSrcMarkList.get();
537 else
539 // We use the current mark list
540 pMarkList = new SdrMarkList(GetMarkedObjectList());
543 SdrMark* pMark;
544 SdPage* pPage;
546 bool bSelected = false;
547 bool bMasterPage = false;
549 for (size_t nMark = pMarkList->GetMarkCount(); nMark && !bSelected; )
551 --nMark;
552 // Backwards through mark list
553 pMark = pMarkList->GetMark(nMark);
554 SdrObject* pObj = pMark->GetMarkedSdrObj();
556 if ( pObj && ( bCheckPresObjListOnly || pObj->IsEmptyPresObj() || pObj->GetUserCall() ) )
558 pPage = static_cast<SdPage*>( pObj->getSdrPageFromSdrObject() );
559 bMasterPage = pPage && pPage->IsMasterPage();
561 if ( (bMasterPage && bOnMasterPage) || (!bMasterPage && bOnPage) )
563 if ( pPage && pPage->IsPresObj(pObj) )
565 if( bCheckLayoutOnly )
567 PresObjKind eKind = pPage->GetPresObjKind(pObj);
569 if((eKind != PresObjKind::Footer) && (eKind != PresObjKind::Header) && (eKind != PresObjKind::DateTime) && (eKind != PresObjKind::SlideNumber) )
570 bSelected = true;
572 else
574 bSelected = true;
581 if (pMarkList != mpDragSrcMarkList.get())
583 delete pMarkList;
586 return bSelected;
589 void View::SelectAll()
591 if ( IsTextEdit() )
593 OutlinerView* pOLV = GetTextEditOutlinerView();
594 const ::Outliner* pOutliner = GetTextEditOutliner();
595 pOLV->SelectRange( 0, pOutliner->GetParagraphCount() );
597 else
599 MarkAll();
603 bool View::SetStyleSheet(SfxStyleSheet* pStyleSheet, bool bDontRemoveHardAttr)
605 // forward to SdrView
606 FmFormView::SetStyleSheet(pStyleSheet, bDontRemoveHardAttr);
607 return true;
611 * Start text input
613 static void SetSpellOptions( const SdDrawDocument& rDoc, EEControlBits& rCntrl )
615 bool bOnlineSpell = rDoc.GetOnlineSpell();
617 if( bOnlineSpell )
618 rCntrl |= EEControlBits::ONLINESPELLING;
619 else
620 rCntrl &= ~EEControlBits::ONLINESPELLING;
623 void OutlinerMasterViewFilter::Start(SdrOutliner *pOutl)
625 m_pOutl = pOutl;
626 OutlinerView* pOutlView = m_pOutl->GetView(0);
627 m_bReadOnly = pOutlView->IsReadOnly();
628 pOutlView->SetReadOnly(true);
631 void OutlinerMasterViewFilter::End()
633 if (m_pOutl)
635 OutlinerView* pOutlView = m_pOutl->GetView(0);
636 pOutlView->SetReadOnly(m_bReadOnly);
637 m_pOutl = nullptr;
641 SfxViewShell* View::GetSfxViewShell() const
643 SfxViewShell* pRet = nullptr;
645 if (mpViewSh)
646 pRet = &mpViewSh->GetViewShellBase();
648 return pRet;
651 // Create a new view-local UndoManager manager for Impress/Draw
652 std::unique_ptr<SdrUndoManager> View::createLocalTextUndoManager()
654 std::unique_ptr<SdrUndoManager> pUndoManager(new sd::UndoManager);
655 pUndoManager->SetDocShell(mpDocSh);
656 return pUndoManager;
659 bool View::SdrBeginTextEdit(
660 SdrObject* pObj, SdrPageView* pPV, vcl::Window* pWin,
661 bool bIsNewObj,
662 SdrOutliner* pOutl, OutlinerView* pGivenOutlinerView,
663 bool bDontDeleteOutliner, bool bOnlyOneView, bool bGrabFocus )
665 SdrPage* pPage = pObj ? pObj->getSdrPageFromSdrObject() : nullptr;
666 bool bMasterPage = pPage && pPage->IsMasterPage();
668 GetViewShell()->GetViewShellBase().GetEventMultiplexer()->MultiplexEvent(
669 EventMultiplexerEventId::BeginTextEdit, static_cast<void*>(pObj) );
671 if( pOutl==nullptr && pObj )
672 pOutl = SdrMakeOutliner(OutlinerMode::TextObject, pObj->getSdrModelFromSdrObject()).release();
674 // make draw&impress specific initialisations
675 if( pOutl )
677 pOutl->SetStyleSheetPool(static_cast<SfxStyleSheetPool*>( mrDoc.GetStyleSheetPool() ));
678 pOutl->SetCalcFieldValueHdl(LINK(SdModule::get(), SdModule, CalcFieldValueHdl));
679 EEControlBits nCntrl = pOutl->GetControlWord();
680 nCntrl |= EEControlBits::ALLOWBIGOBJS;
681 nCntrl |= EEControlBits::MARKFIELDS;
682 nCntrl |= EEControlBits::AUTOCORRECT;
684 nCntrl &= ~EEControlBits::ULSPACESUMMATION;
685 if ( mrDoc.IsSummationOfParagraphs() )
686 nCntrl |= EEControlBits::ULSPACESUMMATION;
688 SetSpellOptions( mrDoc, nCntrl );
690 pOutl->SetControlWord(nCntrl);
692 Reference< linguistic2::XSpellChecker1 > xSpellChecker( LinguMgr::GetSpellChecker() );
693 if ( xSpellChecker.is() )
694 pOutl->SetSpeller( xSpellChecker );
696 Reference< linguistic2::XHyphenator > xHyphenator( LinguMgr::GetHyphenator() );
697 if( xHyphenator.is() )
698 pOutl->SetHyphenator( xHyphenator );
700 pOutl->SetDefaultLanguage( Application::GetSettings().GetLanguageTag().getLanguageType() );
703 if (mpViewSh)
705 // check if we have IASS active and propagate that info to the view with the active TextEdit
706 rtl::Reference< SlideShow > xSlideshow(SlideShow::GetSlideShow(mpViewSh->GetViewShellBase()));
707 const bool bIASS(xSlideshow.is() && xSlideshow->isRunning() && xSlideshow->IsInteractiveSlideshow());
708 setInteractiveSlideShow(bIASS);
711 bool bReturn = FmFormView::SdrBeginTextEdit(
712 pObj, pPV, pWin, bIsNewObj, pOutl,
713 pGivenOutlinerView, bDontDeleteOutliner,
714 bOnlyOneView, bGrabFocus);
716 if ( mpViewSh )
718 mpViewSh->GetViewShellBase().GetDrawController()->FireSelectionChangeListener();
720 if (pObj && pObj->GetObjIdentifier() == SdrObjKind::Table)
721 mpViewSh->UpdateScrollBars();
723 if (comphelper::LibreOfficeKit::isActive())
725 if (OutlinerView* pView = GetTextEditOutlinerView())
727 ::tools::Rectangle aRectangle = pView->GetOutputArea();
728 if (pWin && pWin->GetMapMode().GetMapUnit() == MapUnit::Map100thMM)
730 aRectangle = o3tl::convert(aRectangle, o3tl::Length::mm100, o3tl::Length::twip);
732 OString sRectangle = aRectangle.toString();
733 SfxLokHelper::notifyOtherViews(&mpViewSh->GetViewShellBase(), LOK_CALLBACK_VIEW_LOCK, "rectangle", sRectangle);
738 if (::Outliner* pOL = bReturn ? GetTextEditOutliner() : nullptr)
740 if (pObj)
742 if( pObj->GetObjInventor() == SdrInventor::Default && pObj->GetObjIdentifier() == SdrObjKind::Table )
744 Color aBackground = GetTextEditBackgroundColor(*this);
745 pOL->SetBackgroundColor( aBackground );
747 else
749 // tdf#148140 Set the background to determine autocolor.
750 // Use any explicit bg with fallback to underlying page if
751 // none found
752 if (!pObj->setSuitableOutlinerBg(*pOL) && pPV)
753 setOutlinerBgFromPage(*pOL, *pPV, true);
757 pOL->SetParaInsertedHdl(LINK(this, View, OnParagraphInsertedHdl));
758 pOL->SetParaRemovingHdl(LINK(this, View, OnParagraphRemovingHdl));
761 if (bMasterPage && bReturn && pOutl)
763 const SdrTextObj* pTextObj = pOutl->GetTextObj();
764 const SdPage* pSdPage = pTextObj ? static_cast<const SdPage*>(pTextObj->getSdrPageFromSdrObject()) : nullptr;
765 const PresObjKind eKind = pSdPage ? pSdPage->GetPresObjKind(const_cast<SdrTextObj*>(pTextObj)) : PresObjKind::NONE;
766 switch (eKind)
768 case PresObjKind::Title:
769 case PresObjKind::Outline:
770 case PresObjKind::Text:
771 maMasterViewFilter.Start(pOutl);
772 break;
773 default:
774 break;
778 return bReturn;
781 /** ends current text editing */
782 SdrEndTextEditKind View::SdrEndTextEdit(bool bDontDeleteReally)
784 maMasterViewFilter.End();
786 SdrTextObj* pObj = GetTextEditObject();
788 bool bDefaultTextRestored = RestoreDefaultText( pObj );
789 const bool bSaveSetModifiedEnabled = mpDocSh && mpDocSh->IsEnableSetModified();
790 if (bDefaultTextRestored)
792 if (bSaveSetModifiedEnabled)
793 mpDocSh->EnableSetModified(false);
796 SdrEndTextEditKind eKind = FmFormView::SdrEndTextEdit(bDontDeleteReally);
798 if( bDefaultTextRestored )
800 if (bSaveSetModifiedEnabled)
801 mpDocSh->EnableSetModified();
803 if( pObj && !pObj->IsEmptyPresObj() )
805 pObj->SetEmptyPresObj( true );
807 else
809 eKind = SdrEndTextEditKind::Unchanged;
812 else if( pObj && pObj->IsEmptyPresObj() && pObj->HasText() )
814 SdrPage* pPage = pObj->getSdrPageFromSdrObject();
815 if( !pPage || !pPage->IsMasterPage() )
816 pObj->SetEmptyPresObj( false );
819 GetViewShell()->GetViewShellBase().GetEventMultiplexer()->MultiplexEvent(
820 EventMultiplexerEventId::EndTextEdit,
821 static_cast<void*>(pObj) );
823 if( pObj )
825 if ( mpViewSh )
827 mpViewSh->GetViewShellBase().GetDrawController()->FireSelectionChangeListener();
829 if (comphelper::LibreOfficeKit::isActive())
830 SfxLokHelper::notifyOtherViews(&mpViewSh->GetViewShellBase(), LOK_CALLBACK_VIEW_LOCK, "rectangle", "EMPTY"_ostr);
834 SdPage* pPage = dynamic_cast< SdPage* >( pObj->getSdrPageFromSdrObject() );
835 if( pPage )
836 pPage->onEndTextEdit( pObj );
839 return eKind;
842 /** restores the default text if the given text object is currently in edit mode and
843 no text has been entered already. Is only useful just before text edit ends. */
844 bool View::RestoreDefaultText( SdrTextObj* pTextObj )
846 bool bRestored = false;
848 if( pTextObj && (pTextObj == GetTextEditObject()) )
850 if( !pTextObj->HasText() )
852 SdPage* pPage = dynamic_cast< SdPage* >( pTextObj->getSdrPageFromSdrObject() );
854 if(pPage)
856 bRestored = pPage->RestoreDefaultText( pTextObj );
857 if( bRestored )
859 SdrOutliner* pOutliner = GetTextEditOutliner();
860 pTextObj->SetTextEditOutliner( pOutliner );
861 OutlinerParaObject* pParaObj = pTextObj->GetOutlinerParaObject();
862 if (pOutliner)
863 pOutliner->SetText(*pParaObj);
869 return bRestored;
873 * Sets the original size of the marked objects.
875 void View::SetMarkedOriginalSize()
877 std::unique_ptr<SdrUndoGroup> pUndoGroup(new SdrUndoGroup(mrDoc));
878 const SdrMarkList& rMarkList = GetMarkedObjectList();
879 const size_t nCount = rMarkList.GetMarkCount();
880 bool bOK = false;
882 for( size_t i = 0; i < nCount; ++i )
884 SdrObject* pObj = rMarkList.GetMark(i)->GetMarkedSdrObj();
886 if( pObj->GetObjInventor() == SdrInventor::Default )
888 if( pObj->GetObjIdentifier() == SdrObjKind::OLE2 )
890 uno::Reference < embed::XEmbeddedObject > xObj = static_cast<SdrOle2Obj*>(pObj)->GetObjRef();
891 if( xObj.is() )
893 // TODO/LEAN: working with VisualArea can switch object to running state
895 sal_Int64 nAspect = static_cast<SdrOle2Obj*>(pObj)->GetAspect();
896 Size aOleSize;
898 if ( nAspect == embed::Aspects::MSOLE_ICON )
900 MapMode aMap100( MapUnit::Map100thMM );
901 aOleSize = static_cast<SdrOle2Obj*>(pObj)->GetOrigObjSize( &aMap100 );
902 bOK = true;
904 else
906 MapUnit aUnit = VCLUnoHelper::UnoEmbed2VCLMapUnit( xObj->getMapUnit( nAspect ) );
909 awt::Size aSz = xObj->getVisualAreaSize( nAspect );
910 aOleSize = OutputDevice::LogicToLogic(Size(aSz.Width, aSz.Height), MapMode(aUnit), MapMode(MapUnit::Map100thMM));
911 bOK = true;
913 catch( embed::NoVisualAreaSizeException& )
917 if ( bOK )
919 ::tools::Rectangle aDrawRect( pObj->GetLogicRect() );
921 pUndoGroup->AddAction( mrDoc.GetSdrUndoFactory().CreateUndoGeoObject( *pObj ) );
922 pObj->Resize( aDrawRect.TopLeft(), Fraction( aOleSize.Width(), aDrawRect.GetWidth() ),
923 Fraction( aOleSize.Height(), aDrawRect.GetHeight() ) );
927 else if( pObj->GetObjIdentifier() == SdrObjKind::Graphic )
929 const SdrGrafObj* pSdrGrafObj = static_cast< const SdrGrafObj* >(pObj);
930 const Size aSize = pSdrGrafObj->getOriginalSize( );
931 pUndoGroup->AddAction(GetModel().GetSdrUndoFactory().CreateUndoGeoObject(*pObj));
932 ::tools::Rectangle aRect( pObj->GetLogicRect() );
933 aRect.SetSize( aSize );
934 pObj->SetLogicRect( aRect );
935 bOK = true;
940 if( bOK )
942 pUndoGroup->SetComment(SdResId(STR_UNDO_ORIGINALSIZE));
943 mpDocSh->GetUndoManager()->AddUndoAction(std::move(pUndoGroup));
948 * Connect OLE object to client.
950 void View::DoConnect(SdrOle2Obj* pObj)
952 if (!mpViewSh)
953 return;
955 uno::Reference < embed::XEmbeddedObject > xObj( pObj->GetObjRef() );
956 if( !xObj.is() )
957 return;
959 ::sd::Window* pWindow = mpViewSh->GetActiveWindow();
960 SfxInPlaceClient* pSdClient = mpViewSh-> GetViewShellBase().FindIPClient( xObj, pWindow );
961 if ( pSdClient )
962 return;
964 pSdClient = new Client(pObj, mpViewSh, pWindow);
965 ::tools::Rectangle aRect = pObj->GetLogicRect();
967 // TODO/LEAN: working with visual area can switch object to running state
968 Size aDrawSize = aRect.GetSize();
970 MapMode aMapMode( mrDoc.GetScaleUnit() );
971 Size aObjAreaSize = pObj->GetOrigObjSize( &aMapMode );
973 Fraction aScaleWidth (aDrawSize.Width(), aObjAreaSize.Width() );
974 Fraction aScaleHeight(aDrawSize.Height(), aObjAreaSize.Height() );
975 aScaleWidth.ReduceInaccurate(10); // compatible to SdrOle2Obj
976 aScaleHeight.ReduceInaccurate(10);
977 pSdClient->SetSizeScale(aScaleWidth, aScaleHeight);
979 // visible area is only changed in-place!
980 // the object area must be set after the scaling, since it triggers resize
981 aRect.SetSize(aObjAreaSize);
982 pSdClient->SetObjArea(aRect);
986 bool View::IsMorphingAllowed() const
988 const SdrMarkList& rMarkList = GetMarkedObjectList();
989 bool bRet = false;
991 if ( rMarkList.GetMarkCount() == 2 )
993 const SdrObject* pObj1 = rMarkList.GetMark( 0 )->GetMarkedSdrObj();
994 const SdrObject* pObj2 = rMarkList.GetMark( 1 )->GetMarkedSdrObj();
995 const SdrObjKind nKind1 = pObj1->GetObjIdentifier();
996 const SdrObjKind nKind2 = pObj2->GetObjIdentifier();
998 if ( ( nKind1 != SdrObjKind::Text && nKind2 != SdrObjKind::Text ) &&
999 ( nKind1 != SdrObjKind::TitleText && nKind2 != SdrObjKind::TitleText ) &&
1000 ( nKind1 != SdrObjKind::OutlineText && nKind2 != SdrObjKind::OutlineText ) &&
1001 ( nKind1 != SdrObjKind::Group && nKind2 != SdrObjKind::Group ) &&
1002 ( nKind1 != SdrObjKind::Line && nKind2 != SdrObjKind::Line ) &&
1003 ( nKind1 != SdrObjKind::PolyLine && nKind2 != SdrObjKind::PolyLine ) &&
1004 ( nKind1 != SdrObjKind::PathLine && nKind2 != SdrObjKind::PathLine ) &&
1005 ( nKind1 != SdrObjKind::FreehandLine && nKind2 != SdrObjKind::FreehandLine ) &&
1006 ( nKind1 != SdrObjKind::PathPolyLine && nKind2 != SdrObjKind::PathPolyLine ) &&
1007 ( nKind1 != SdrObjKind::Measure && nKind2 != SdrObjKind::Measure ) &&
1008 ( nKind1 != SdrObjKind::Edge && nKind2 != SdrObjKind::Edge ) &&
1009 ( nKind1 != SdrObjKind::Graphic && nKind2 != SdrObjKind::Graphic ) &&
1010 ( nKind1 != SdrObjKind::OLE2 && nKind2 != SdrObjKind::OLE2 ) &&
1011 ( nKind1 != SdrObjKind::Caption && nKind2 != SdrObjKind::Caption ) &&
1012 DynCastE3dObject( pObj1 ) == nullptr && DynCastE3dObject( pObj2 ) == nullptr )
1014 SfxItemSetFixed<XATTR_FILLSTYLE, XATTR_FILLSTYLE> aSet1( mrDoc.GetPool() );
1015 SfxItemSetFixed<XATTR_FILLSTYLE, XATTR_FILLSTYLE> aSet2( mrDoc.GetPool() );
1017 aSet1.Put(pObj1->GetMergedItemSet());
1018 aSet2.Put(pObj2->GetMergedItemSet());
1020 const drawing::FillStyle eFillStyle1 = aSet1.Get( XATTR_FILLSTYLE ).GetValue();
1021 const drawing::FillStyle eFillStyle2 = aSet2.Get( XATTR_FILLSTYLE ).GetValue();
1023 if( ( eFillStyle1 == drawing::FillStyle_NONE || eFillStyle1 == drawing::FillStyle_SOLID ) &&
1024 ( eFillStyle2 == drawing::FillStyle_NONE || eFillStyle2 == drawing::FillStyle_SOLID ) )
1025 bRet = true;
1029 return bRet;
1032 bool View::IsVectorizeAllowed() const
1034 const SdrMarkList& rMarkList = GetMarkedObjectList();
1035 bool bRet = false;
1037 if( rMarkList.GetMarkCount() == 1 )
1039 const SdrGrafObj* pObj = dynamic_cast< const SdrGrafObj* >(rMarkList.GetMark( 0 )->GetMarkedSdrObj());
1041 if(pObj)
1043 if(GraphicType::Bitmap == pObj->GetGraphicType() && !pObj->isEmbeddedVectorGraphicData())
1045 bRet = true;
1050 return bRet;
1053 IMPL_LINK( View, OnParagraphInsertedHdl, ::Outliner::ParagraphHdlParam, aParam, void )
1055 SdrObject* pObj = GetTextEditObject();
1057 if( aParam.pPara && pObj )
1059 SdPage* pPage = dynamic_cast< SdPage* >( pObj->getSdrPageFromSdrObject() );
1060 if( pPage )
1061 pPage->onParagraphInserted( aParam.pOutliner, aParam.pPara, pObj );
1066 * Handler for the deletion of the pages (paragraphs).
1068 IMPL_LINK( View, OnParagraphRemovingHdl, ::Outliner::ParagraphHdlParam, aParam, void )
1070 SdrObject* pObj = GetTextEditObject();
1072 if( aParam.pPara && pObj )
1074 SdPage* pPage = dynamic_cast< SdPage* >( pObj->getSdrPageFromSdrObject() );
1075 if( pPage )
1076 pPage->onParagraphRemoving( aParam.pOutliner, aParam.pPara, pObj );
1080 bool View::isRecordingUndo() const
1082 if( mrDoc.IsUndoEnabled() )
1084 sd::UndoManager* pUndoManager = mrDoc.GetUndoManager();
1085 return pUndoManager && pUndoManager->IsInListAction();
1087 else
1089 return false;
1093 void View::AddCustomHdl()
1095 maSmartTags.addCustomHandles( maHdlList );
1098 void View::updateHandles()
1100 AdjustMarkHdl();
1103 SdrViewContext View::GetContext() const
1105 SdrViewContext eContext = SdrViewContext::Standard;
1106 if( maSmartTags.getContext( eContext ) )
1107 return eContext;
1108 else
1109 return FmFormView::GetContext();
1112 bool View::HasMarkablePoints() const
1114 if( maSmartTags.HasMarkablePoints() )
1115 return true;
1116 else
1117 return FmFormView::HasMarkablePoints();
1120 sal_Int32 View::GetMarkablePointCount() const
1122 sal_Int32 nCount = FmFormView::GetMarkablePointCount();
1123 nCount += maSmartTags.GetMarkablePointCount();
1124 return nCount;
1127 bool View::HasMarkedPoints() const
1129 if( maSmartTags.HasMarkedPoints() )
1130 return true;
1131 else
1132 return FmFormView::HasMarkedPoints();
1135 bool View::MarkPoint(SdrHdl& rHdl, bool bUnmark )
1137 if( maSmartTags.MarkPoint( rHdl, bUnmark ) )
1138 return true;
1139 else
1140 return FmFormView::MarkPoint( rHdl, bUnmark );
1143 bool View::MarkPoints(const ::tools::Rectangle* pRect, bool bUnmark)
1145 if( maSmartTags.MarkPoints( pRect, bUnmark ) )
1146 return true;
1147 else
1148 return FmFormView::MarkPoints( pRect, bUnmark );
1151 void View::CheckPossibilities()
1153 FmFormView::CheckPossibilities();
1154 maSmartTags.CheckPossibilities();
1157 void View::OnBeginPasteOrDrop( PasteOrDropInfos* pInfo )
1159 SdrOutliner* pOutliner = GetTextEditOutliner();
1160 if (!pOutliner)
1161 return;
1163 // Turn character attributes of the paragraph of the insert position into
1164 // character-level attributes, so they are not lost when OnEndPasteOrDrop()
1165 // sets the paragraph stylesheet.
1166 SfxItemSet aSet(pOutliner->GetParaAttribs(pInfo->nStartPara));
1167 pOutliner->SetCharAttribs(pInfo->nStartPara, aSet);
1170 /** this is called after a paste or drop operation, make sure that the newly inserted paragraphs
1171 get the correct style sheet. */
1172 void View::OnEndPasteOrDrop( PasteOrDropInfos* pInfo )
1174 /* Style Sheet handling */
1175 SdrTextObj* pTextObj = GetTextEditObject();
1176 SdrOutliner* pOutliner = GetTextEditOutliner();
1177 if( !pOutliner || !pTextObj || !pTextObj->getSdrPageFromSdrObject() )
1178 return;
1180 SdPage* pPage = static_cast< SdPage* >( pTextObj->getSdrPageFromSdrObject() );
1181 const PresObjKind eKind = pPage->GetPresObjKind(pTextObj);
1183 // outline kinds are taken care of in Outliner::ImplSetLevelDependentStyleSheet
1184 if( eKind == PresObjKind::Outline )
1185 return;
1187 SfxStyleSheet* pStyleSheet = nullptr;
1188 if( eKind != PresObjKind::NONE )
1189 pStyleSheet = pPage->GetStyleSheetForPresObj(eKind);
1190 else
1191 pStyleSheet = pTextObj->GetStyleSheet();
1192 // just put the object style on each new paragraph
1193 for ( sal_Int32 nPara = pInfo->nStartPara; nPara <= pInfo->nEndPara; nPara++ )
1195 pOutliner->SetStyleSheet( nPara, pStyleSheet );
1199 bool View::ShouldToggleOn(
1200 const bool bBulletOnOffMode,
1201 const bool bNormalBullet)
1203 // If setting bullets/numbering by the dialog, always should toggle on.
1204 if (!bBulletOnOffMode)
1205 return true;
1206 SdrModel& rSdrModel = GetModel();
1208 bool bToggleOn = false;
1209 std::unique_ptr<SdrOutliner> pOutliner(SdrMakeOutliner(OutlinerMode::TextObject, rSdrModel));
1210 const SdrMarkList& rMarkList = GetMarkedObjectList();
1211 const size_t nMarkCount = rMarkList.GetMarkCount();
1212 for (size_t nIndex = 0; nIndex < nMarkCount && !bToggleOn; ++nIndex)
1214 SdrTextObj* pTextObj = DynCastSdrTextObj(rMarkList.GetMark(nIndex)->GetMarkedSdrObj());
1215 if (!pTextObj || pTextObj->IsTextEditActive())
1216 continue;
1217 if( dynamic_cast< const SdrTableObj *>( pTextObj ) != nullptr)
1219 SdrTableObj* pTableObj = dynamic_cast< SdrTableObj* >(pTextObj);
1220 if (!pTableObj)
1221 continue;
1222 CellPos aStart, aEnd;
1223 SvxTableController* pTableController = dynamic_cast< SvxTableController* >(getSelectionController().get());
1224 if (pTableController)
1226 pTableController->getSelectedCells(aStart, aEnd);
1228 else
1230 aStart = SdrTableObj::getFirstCell();
1231 aEnd = pTableObj->getLastCell();
1233 sal_Int32 nColCount = pTableObj->getColumnCount();
1234 for (sal_Int32 nRow = aStart.mnRow; nRow <= aEnd.mnRow && !bToggleOn; nRow++)
1236 for (sal_Int32 nCol = aStart.mnCol; nCol <= aEnd.mnCol && !bToggleOn; nCol++)
1238 sal_Int32 nCellIndex = nRow * nColCount + nCol;
1239 SdrText* pText = pTableObj->getText(nCellIndex);
1240 if (!pText || !pText->GetOutlinerParaObject())
1241 continue;
1242 pOutliner->SetText(*(pText->GetOutlinerParaObject()));
1243 sal_Int16 nStatus = pOutliner->GetBulletsNumberingStatus();
1244 bToggleOn = (bNormalBullet && nStatus != 0) || (!bNormalBullet && nStatus != 1);
1245 pOutliner->Clear();
1249 else
1251 OutlinerParaObject* pParaObj = pTextObj->GetOutlinerParaObject();
1252 if (!pParaObj)
1253 continue;
1254 pOutliner->SetText(*pParaObj);
1255 sal_Int16 nStatus = pOutliner->GetBulletsNumberingStatus();
1256 bToggleOn = (bNormalBullet && nStatus != 0) || (!bNormalBullet && nStatus != 1);
1257 pOutliner->Clear();
1260 return bToggleOn;
1263 void View::ChangeMarkedObjectsBulletsNumbering(
1264 const bool bToggle,
1265 const bool bHandleBullets,
1266 const SvxNumRule* pNumRule )
1268 SdrModel& rSdrModel = GetModel();
1269 OutputDevice* pOut = GetFirstOutputDevice();
1270 vcl::Window* pWindow = pOut ? pOut->GetOwnerWindow() : nullptr;
1271 if (!pWindow)
1272 return;
1274 const bool bUndoEnabled = rSdrModel.IsUndoEnabled();
1275 std::unique_ptr<SdrUndoGroup> pUndoGroup(bUndoEnabled ? new SdrUndoGroup(rSdrModel) : nullptr);
1277 const bool bToggleOn = ShouldToggleOn( bToggle, bHandleBullets );
1279 std::unique_ptr<SdrOutliner> pOutliner(SdrMakeOutliner(OutlinerMode::TextObject, rSdrModel));
1280 OutlinerView aOutlinerView(pOutliner.get(), pWindow);
1282 const SdrMarkList& rMarkList = GetMarkedObjectList();
1283 const size_t nMarkCount = rMarkList.GetMarkCount();
1284 for (size_t nIndex = 0; nIndex < nMarkCount; ++nIndex)
1286 SdrTextObj* pTextObj = DynCastSdrTextObj(rMarkList.GetMark(nIndex)->GetMarkedSdrObj());
1287 if (!pTextObj || pTextObj->IsTextEditActive())
1288 continue;
1289 if( dynamic_cast< SdrTableObj *>( pTextObj ) != nullptr)
1291 SdrTableObj* pTableObj = dynamic_cast< SdrTableObj* >(pTextObj);
1292 if (!pTableObj)
1293 continue;
1294 CellPos aStart, aEnd;
1295 SvxTableController* pTableController = dynamic_cast< SvxTableController* >(getSelectionController().get());
1296 if (pTableController)
1298 pTableController->getSelectedCells(aStart, aEnd);
1300 else
1302 aStart = SdrTableObj::getFirstCell();
1303 aEnd = pTableObj->getLastCell();
1305 sal_Int32 nColCount = pTableObj->getColumnCount();
1306 for (sal_Int32 nRow = aStart.mnRow; nRow <= aEnd.mnRow; nRow++)
1308 for (sal_Int32 nCol = aStart.mnCol; nCol <= aEnd.mnCol; nCol++)
1310 sal_Int32 nCellIndex = nRow * nColCount + nCol;
1311 SdrText* pText = pTableObj->getText(nCellIndex);
1312 if (!pText || !pText->GetOutlinerParaObject())
1313 continue;
1315 pOutliner->SetText(*(pText->GetOutlinerParaObject()));
1316 if (bUndoEnabled)
1318 pUndoGroup->AddAction(rSdrModel.GetSdrUndoFactory().CreateUndoObjectSetText(*pTextObj, nCellIndex));
1320 if ( !bToggleOn )
1322 aOutlinerView.SwitchOffBulletsNumbering();
1324 else
1326 aOutlinerView.ApplyBulletsNumbering( bHandleBullets, pNumRule, bToggle );
1328 sal_uInt32 nParaCount = pOutliner->GetParagraphCount();
1329 pText->SetOutlinerParaObject(pOutliner->CreateParaObject(0, static_cast<sal_uInt16>(nParaCount)));
1330 pOutliner->Clear();
1333 // Broadcast the object change event.
1334 if (!pTextObj->AdjustTextFrameWidthAndHeight())
1336 pTextObj->SetChanged();
1337 pTextObj->BroadcastObjectChange();
1340 else
1342 OutlinerParaObject* pParaObj = pTextObj->GetOutlinerParaObject();
1343 if (!pParaObj)
1344 continue;
1345 pOutliner->SetText(*pParaObj);
1346 if (bUndoEnabled)
1348 pUndoGroup->AddAction(
1349 rSdrModel.GetSdrUndoFactory().CreateUndoObjectSetText(*pTextObj, 0));
1351 if ( !bToggleOn )
1353 aOutlinerView.SwitchOffBulletsNumbering();
1355 else
1357 aOutlinerView.ApplyBulletsNumbering( bHandleBullets, pNumRule, bToggle );
1359 sal_uInt32 nParaCount = pOutliner->GetParagraphCount();
1360 pTextObj->SetOutlinerParaObject(pOutliner->CreateParaObject(0, static_cast<sal_uInt16>(nParaCount)));
1361 pOutliner->Clear();
1365 if ( bUndoEnabled && pUndoGroup->GetActionCount() > 0 )
1367 rSdrModel.BegUndo();
1368 rSdrModel.AddUndo(std::move(pUndoGroup));
1369 rSdrModel.EndUndo();
1373 } // end of namespace sd
1375 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */