Version 4.3.0.0.beta1, tag libreoffice-4.3.0.0.beta1
[LibreOffice.git] / svx / source / svdraw / svdedxv.cxx
bloba0bbfa1a267e417fdf017549c7d413697bd65f62
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 <com/sun/star/i18n/WordType.hpp>
21 #include <svtools/accessibilityoptions.hxx>
22 #include <svx/svdedxv.hxx>
23 #include <svl/solar.hrc>
24 #include <svl/itemiter.hxx>
25 #include <vcl/msgbox.hxx>
26 #include <vcl/hatch.hxx>
27 #include <svl/whiter.hxx>
28 #include <svl/style.hxx>
29 #include <editeng/editstat.hxx>
30 #include <vcl/cursor.hxx>
31 #include <editeng/unotext.hxx>
32 #include <editeng/editdata.hxx>
33 #include <editeng/editeng.hxx>
34 #include <editeng/editobj.hxx>
35 #include <editeng/outlobj.hxx>
36 #include <editeng/scripttypeitem.hxx>
37 #include <svx/svdoutl.hxx>
38 #include <svx/sdtfchim.hxx>
39 #include <svx/svdotext.hxx>
40 #include <svx/svdundo.hxx>
41 #include "svx/svditer.hxx"
42 #include "svx/svdpagv.hxx"
43 #include "svx/svdpage.hxx"
44 #include "svx/svdetc.hxx"
45 #include "svx/svdotable.hxx"
46 #include <svx/selectioncontroller.hxx>
47 #ifdef DBG_UTIL
48 #include <svdibrow.hxx>
49 #endif
50 #include <svx/svddrgv.hxx>
51 #include "svx/svdstr.hrc"
52 #include "svdglob.hxx"
53 #include "svx/globl3d.hxx"
54 #include <editeng/outliner.hxx>
55 #include <editeng/adjustitem.hxx>
56 #include <svtools/colorcfg.hxx>
57 #include <vcl/svapp.hxx>
58 #include <svx/sdrpaintwindow.hxx>
59 #include <svx/sdrundomanager.hxx>
60 #include <sdr/overlay/overlaytools.hxx>
61 #include <svx/sdr/table/tablecontroller.hxx>
62 #include <drawinglayer/processor2d/processor2dtools.hxx>
66 void SdrObjEditView::ImpClearVars()
68 bQuickTextEditMode=true;
69 bMacroMode=true;
70 pTextEditOutliner=NULL;
71 pTextEditOutlinerView=NULL;
72 pTextEditPV=NULL;
73 pTextEditWin=NULL;
74 pTextEditCursorMerker=NULL;
75 pEditPara=NULL;
76 bTextEditNewObj=false;
77 bMacroDown=false;
78 pMacroObj=NULL;
79 pMacroPV=NULL;
80 pMacroWin=NULL;
81 nMacroTol=0;
82 bTextEditDontDelete=false;
83 bTextEditOnlyOneView=false;
86 SdrObjEditView::SdrObjEditView(SdrModel* pModel1, OutputDevice* pOut):
87 SdrGlueEditView(pModel1,pOut),
88 mpOldTextEditUndoManager(0)
90 ImpClearVars();
93 SdrObjEditView::~SdrObjEditView()
95 pTextEditWin = NULL; // so there's no ShowCursor in SdrEndTextEdit
96 if (IsTextEdit())
97 SdrEndTextEdit();
98 delete pTextEditOutliner;
99 delete mpOldTextEditUndoManager;
104 bool SdrObjEditView::IsAction() const
106 return IsMacroObj() || SdrGlueEditView::IsAction();
109 void SdrObjEditView::MovAction(const Point& rPnt)
111 if (IsMacroObj()) MovMacroObj(rPnt);
112 SdrGlueEditView::MovAction(rPnt);
115 void SdrObjEditView::EndAction()
117 if (IsMacroObj()) EndMacroObj();
118 SdrGlueEditView::EndAction();
121 void SdrObjEditView::BckAction()
123 BrkMacroObj();
124 SdrGlueEditView::BckAction();
127 void SdrObjEditView::BrkAction()
129 BrkMacroObj();
130 SdrGlueEditView::BrkAction();
133 void SdrObjEditView::TakeActionRect(Rectangle& rRect) const
135 if (IsMacroObj()) {
136 rRect=pMacroObj->GetCurrentBoundRect();
137 } else {
138 SdrGlueEditView::TakeActionRect(rRect);
142 void SdrObjEditView::Notify(SfxBroadcaster& rBC, const SfxHint& rHint)
144 SdrGlueEditView::Notify(rBC,rHint);
145 // change of printer while editing
146 SdrHint* pSdrHint=PTR_CAST(SdrHint,&rHint);
147 if (pSdrHint!=NULL && pTextEditOutliner!=NULL) {
148 SdrHintKind eKind=pSdrHint->GetKind();
149 if (eKind==HINT_REFDEVICECHG) {
150 pTextEditOutliner->SetRefDevice(pMod->GetRefDevice());
152 if (eKind==HINT_DEFAULTTABCHG) {
153 pTextEditOutliner->SetDefTab(pMod->GetDefaultTabulator());
155 if (eKind==HINT_DEFFONTHGTCHG) {
158 if (eKind==HINT_MODELSAVED) {
159 pTextEditOutliner->ClearModifyFlag();
164 void SdrObjEditView::ModelHasChanged()
166 SdrGlueEditView::ModelHasChanged();
167 if (mxTextEditObj.is() && !mxTextEditObj->IsInserted()) SdrEndTextEdit(); // object deleted
168 // TextEditObj changed?
169 if (IsTextEdit()) {
170 SdrTextObj* pTextObj=dynamic_cast<SdrTextObj*>( mxTextEditObj.get() );
171 if (pTextObj!=NULL) {
172 sal_uIntPtr nOutlViewAnz=pTextEditOutliner->GetViewCount();
173 bool bAreaChg=false;
174 bool bAnchorChg=false;
175 bool bColorChg=false;
176 bool bContourFrame=pTextObj->IsContourTextFrame();
177 EVAnchorMode eNewAnchor(ANCHOR_VCENTER_HCENTER);
178 Rectangle aOldArea(aMinTextEditArea);
179 aOldArea.Union(aTextEditArea);
180 Color aNewColor;
181 { // check area
182 Size aPaperMin1;
183 Size aPaperMax1;
184 Rectangle aEditArea1;
185 Rectangle aMinArea1;
186 pTextObj->TakeTextEditArea(&aPaperMin1,&aPaperMax1,&aEditArea1,&aMinArea1);
188 Point aPvOfs(pTextObj->GetTextEditOffset());
189 // Hack for calc, transform position of edit object according
190 // to current zoom so as objects relative position to grid
191 // appears stable
192 aEditArea1 += pTextObj->GetGridOffset();
193 aMinArea1 += pTextObj->GetGridOffset();
194 aEditArea1.Move(aPvOfs.X(),aPvOfs.Y());
195 aMinArea1.Move(aPvOfs.X(),aPvOfs.Y());
196 Rectangle aNewArea(aMinArea1);
197 aNewArea.Union(aEditArea1);
199 if (aNewArea!=aOldArea || aEditArea1!=aTextEditArea || aMinArea1!=aMinTextEditArea ||
200 pTextEditOutliner->GetMinAutoPaperSize()!=aPaperMin1 || pTextEditOutliner->GetMaxAutoPaperSize()!=aPaperMax1) {
201 aTextEditArea=aEditArea1;
202 aMinTextEditArea=aMinArea1;
203 pTextEditOutliner->SetUpdateMode(false);
204 pTextEditOutliner->SetMinAutoPaperSize(aPaperMin1);
205 pTextEditOutliner->SetMaxAutoPaperSize(aPaperMax1);
206 pTextEditOutliner->SetPaperSize(Size(0,0)); // re-format Outliner
207 if (!bContourFrame) {
208 pTextEditOutliner->ClearPolygon();
209 sal_uIntPtr nStat=pTextEditOutliner->GetControlWord();
210 nStat|=EE_CNTRL_AUTOPAGESIZE;
211 pTextEditOutliner->SetControlWord(nStat);
212 } else {
213 sal_uIntPtr nStat=pTextEditOutliner->GetControlWord();
214 nStat&=~EE_CNTRL_AUTOPAGESIZE;
215 pTextEditOutliner->SetControlWord(nStat);
216 Rectangle aAnchorRect;
217 pTextObj->TakeTextAnchorRect(aAnchorRect);
218 pTextObj->ImpSetContourPolygon(*pTextEditOutliner,aAnchorRect, true);
220 for (sal_uIntPtr nOV=0; nOV<nOutlViewAnz; nOV++) {
221 OutlinerView* pOLV=pTextEditOutliner->GetView(nOV);
222 sal_uIntPtr nStat0=pOLV->GetControlWord();
223 sal_uIntPtr nStat=nStat0;
224 // AutoViewSize only if not ContourFrame.
225 if (!bContourFrame) nStat|=EV_CNTRL_AUTOSIZE;
226 else nStat&=~EV_CNTRL_AUTOSIZE;
227 if (nStat!=nStat0) pOLV->SetControlWord(nStat);
229 pTextEditOutliner->SetUpdateMode(true);
230 bAreaChg=true;
233 if (pTextEditOutlinerView!=NULL) { // check fill and anchor
234 EVAnchorMode eOldAnchor=pTextEditOutlinerView->GetAnchorMode();
235 eNewAnchor=(EVAnchorMode)pTextObj->GetOutlinerViewAnchorMode();
236 bAnchorChg=eOldAnchor!=eNewAnchor;
237 Color aOldColor(pTextEditOutlinerView->GetBackgroundColor());
238 aNewColor = GetTextEditBackgroundColor(*this);
239 bColorChg=aOldColor!=aNewColor;
241 // refresh always when it's a contour frame. That
242 // refresh is necessary since it triggers the repaint
243 // which makes the Handles visible. Changes at TakeTextRect()
244 // seem to have resulted in a case where no refresh is executed.
245 // Before that, a refresh must have been always executed
246 // (else this error would have happened earlier), thus I
247 // even think here a refresh should be done always.
248 // Since follow-up problems cannot even be guessed I only
249 // add this one more case to the if below.
250 // BTW: It's VERY bad style that here, inside ModelHasChanged()
251 // the outliner is again massively changed for the text object
252 // in text edit mode. Normally, all necessary data should be
253 // set at SdrBeginTextEdit(). Some changes and value assigns in
254 // SdrBeginTextEdit() are completely useless since they are set here
255 // again on ModelHasChanged().
256 if (bContourFrame || bAreaChg || bAnchorChg || bColorChg)
258 for (sal_uIntPtr nOV=0; nOV<nOutlViewAnz; nOV++)
260 OutlinerView* pOLV=pTextEditOutliner->GetView(nOV);
261 { // invalidate old OutlinerView area
262 Window* pWin=pOLV->GetWindow();
263 Rectangle aTmpRect(aOldArea);
264 sal_uInt16 nPixSiz=pOLV->GetInvalidateMore()+1;
265 Size aMore(pWin->PixelToLogic(Size(nPixSiz,nPixSiz)));
266 aTmpRect.Left()-=aMore.Width();
267 aTmpRect.Right()+=aMore.Width();
268 aTmpRect.Top()-=aMore.Height();
269 aTmpRect.Bottom()+=aMore.Height();
270 InvalidateOneWin(*pWin,aTmpRect);
272 if (bAnchorChg)
273 pOLV->SetAnchorMode(eNewAnchor);
274 if (bColorChg)
275 pOLV->SetBackgroundColor( aNewColor );
277 pOLV->SetOutputArea(aTextEditArea); // because otherwise, we're not re-anchoring correctly
278 ImpInvalidateOutlinerView(*pOLV);
280 pTextEditOutlinerView->ShowCursor();
283 ImpMakeTextCursorAreaVisible();
288 // TextEdit
291 void SdrObjEditView::TextEditDrawing(SdrPaintWindow& rPaintWindow) const
293 // draw old text edit stuff
294 if(IsTextEdit())
296 const SdrOutliner* pActiveOutliner = GetTextEditOutliner();
298 if(pActiveOutliner)
300 const sal_uInt32 nViewAnz(pActiveOutliner->GetViewCount());
302 if(nViewAnz)
304 const Region& rRedrawRegion = rPaintWindow.GetRedrawRegion();
305 const Rectangle aCheckRect(rRedrawRegion.GetBoundRect());
307 for(sal_uInt32 i(0); i < nViewAnz; i++)
309 OutlinerView* pOLV = pActiveOutliner->GetView(i);
311 if(pOLV->GetWindow() == &rPaintWindow.GetOutputDevice())
313 ImpPaintOutlinerView(*pOLV, aCheckRect, rPaintWindow.GetTargetOutputDevice());
314 return;
322 void SdrObjEditView::ImpPaintOutlinerView(OutlinerView& rOutlView, const Rectangle& rRect, OutputDevice& rTargetDevice) const
324 const SdrTextObj* pText = PTR_CAST(SdrTextObj,GetTextEditObject());
325 bool bTextFrame(pText && pText->IsTextFrame());
326 bool bFitToSize(0 != (pTextEditOutliner->GetControlWord() & EE_CNTRL_STRETCHING));
327 bool bModifyMerk(pTextEditOutliner->IsModified()); // #43095#
328 Rectangle aBlankRect(rOutlView.GetOutputArea());
329 aBlankRect.Union(aMinTextEditArea);
330 Rectangle aPixRect(rTargetDevice.LogicToPixel(aBlankRect));
331 aBlankRect.Intersection(rRect);
332 rOutlView.GetOutliner()->SetUpdateMode(true); // Bugfix #22596#
333 rOutlView.Paint(aBlankRect, &rTargetDevice);
335 if(!bModifyMerk)
337 // #43095#
338 pTextEditOutliner->ClearModifyFlag();
341 if(bTextFrame && !bFitToSize)
343 // completely reworked to use primitives; this ensures same look and functionality
344 const drawinglayer::geometry::ViewInformation2D aViewInformation2D;
345 drawinglayer::processor2d::BaseProcessor2D* pProcessor = drawinglayer::processor2d::createProcessor2DFromOutputDevice(
346 rTargetDevice,
347 aViewInformation2D);
349 if(pProcessor)
351 const bool bMerk(rTargetDevice.IsMapModeEnabled());
352 const basegfx::B2DRange aRange(aPixRect.Left(), aPixRect.Top(), aPixRect.Right(), aPixRect.Bottom());
353 const SvtOptionsDrawinglayer aSvtOptionsDrawinglayer;
354 const Color aHilightColor(aSvtOptionsDrawinglayer.getHilightColor());
355 const double fTransparence(aSvtOptionsDrawinglayer.GetTransparentSelectionPercent() * 0.01);
356 const sal_uInt16 nPixSiz(rOutlView.GetInvalidateMore() - 1);
357 const drawinglayer::primitive2d::Primitive2DReference xReference(
358 new drawinglayer::primitive2d::OverlayRectanglePrimitive(
359 aRange,
360 aHilightColor.getBColor(),
361 fTransparence,
362 std::max(6, nPixSiz - 2), // grow
363 0.0, // shrink
364 0.0));
365 const drawinglayer::primitive2d::Primitive2DSequence aSequence(&xReference, 1);
367 rTargetDevice.EnableMapMode(false);
368 pProcessor->process(aSequence);
369 rTargetDevice.EnableMapMode(bMerk);
370 delete pProcessor;
374 rOutlView.ShowCursor();
377 void SdrObjEditView::ImpInvalidateOutlinerView(OutlinerView& rOutlView) const
379 Window* pWin = rOutlView.GetWindow();
381 if(pWin)
383 const SdrTextObj* pText = PTR_CAST(SdrTextObj,GetTextEditObject());
384 bool bTextFrame(pText && pText->IsTextFrame());
385 bool bFitToSize(pText && pText->IsFitToSize());
387 if(bTextFrame && !bFitToSize)
389 Rectangle aBlankRect(rOutlView.GetOutputArea());
390 aBlankRect.Union(aMinTextEditArea);
391 Rectangle aPixRect(pWin->LogicToPixel(aBlankRect));
392 sal_uInt16 nPixSiz(rOutlView.GetInvalidateMore() - 1);
394 aPixRect.Left()--;
395 aPixRect.Top()--;
396 aPixRect.Right()++;
397 aPixRect.Bottom()++;
400 // limit xPixRect because of driver problems when pixel coordinates are too far out
401 Size aMaxXY(pWin->GetOutputSizePixel());
402 long a(2 * nPixSiz);
403 long nMaxX(aMaxXY.Width() + a);
404 long nMaxY(aMaxXY.Height() + a);
406 if (aPixRect.Left ()<-a) aPixRect.Left()=-a;
407 if (aPixRect.Top ()<-a) aPixRect.Top ()=-a;
408 if (aPixRect.Right ()>nMaxX) aPixRect.Right ()=nMaxX;
409 if (aPixRect.Bottom()>nMaxY) aPixRect.Bottom()=nMaxY;
412 Rectangle aOuterPix(aPixRect);
413 aOuterPix.Left()-=nPixSiz;
414 aOuterPix.Top()-=nPixSiz;
415 aOuterPix.Right()+=nPixSiz;
416 aOuterPix.Bottom()+=nPixSiz;
418 bool bMerk(pWin->IsMapModeEnabled());
419 pWin->EnableMapMode(false);
420 pWin->Invalidate(aOuterPix);
421 pWin->EnableMapMode(bMerk);
426 OutlinerView* SdrObjEditView::ImpMakeOutlinerView(Window* pWin, bool /*bNoPaint*/, OutlinerView* pGivenView) const
428 // background
429 Color aBackground(GetTextEditBackgroundColor(*this));
430 SdrTextObj* pText = dynamic_cast< SdrTextObj * >( mxTextEditObj.get() );
431 bool bTextFrame=pText!=NULL && pText->IsTextFrame();
432 bool bContourFrame=pText!=NULL && pText->IsContourTextFrame();
433 // create OutlinerView
434 OutlinerView* pOutlView=pGivenView;
435 pTextEditOutliner->SetUpdateMode(false);
436 if (pOutlView==NULL) pOutlView = new OutlinerView(pTextEditOutliner,pWin);
437 else pOutlView->SetWindow(pWin);
438 // disallow scrolling
439 sal_uIntPtr nStat=pOutlView->GetControlWord();
440 nStat&=~EV_CNTRL_AUTOSCROLL;
441 // AutoViewSize only if not ContourFrame.
442 if (!bContourFrame) nStat|=EV_CNTRL_AUTOSIZE;
443 if (bTextFrame) {
444 sal_uInt16 nPixSiz=aHdl.GetHdlSize()*2+1;
445 nStat|=EV_CNTRL_INVONEMORE;
446 pOutlView->SetInvalidateMore(nPixSiz);
448 pOutlView->SetControlWord(nStat);
449 pOutlView->SetBackgroundColor( aBackground );
450 if (pText!=NULL)
452 pOutlView->SetAnchorMode((EVAnchorMode)(pText->GetOutlinerViewAnchorMode()));
453 pTextEditOutliner->SetFixedCellHeight(((const SdrTextFixedCellHeightItem&)pText->GetMergedItem(SDRATTR_TEXT_USEFIXEDCELLHEIGHT)).GetValue());
455 // do update before setting output area so that aTextEditArea can be recalculated
456 pTextEditOutliner->SetUpdateMode(true);
457 pOutlView->SetOutputArea(aTextEditArea);
458 ImpInvalidateOutlinerView(*pOutlView);
459 return pOutlView;
462 IMPL_LINK(SdrObjEditView,ImpOutlinerStatusEventHdl,EditStatus*,pEditStat)
464 if(pTextEditOutliner )
466 SdrTextObj* pTextObj = dynamic_cast< SdrTextObj * >( mxTextEditObj.get() );
467 if( pTextObj )
469 pTextObj->onEditOutlinerStatusEvent( pEditStat );
472 return 0;
475 IMPL_LINK(SdrObjEditView,ImpOutlinerCalcFieldValueHdl,EditFieldInfo*,pFI)
477 bool bOk=false;
478 OUString& rStr=pFI->GetRepresentation();
479 rStr = "";
480 SdrTextObj* pTextObj = dynamic_cast< SdrTextObj* >( mxTextEditObj.get() );
481 if (pTextObj!=NULL) {
482 Color* pTxtCol=NULL;
483 Color* pFldCol=NULL;
484 bOk=pTextObj->CalcFieldValue(pFI->GetField(),pFI->GetPara(),pFI->GetPos(),true,pTxtCol,pFldCol,rStr);
485 if (bOk) {
486 if (pTxtCol!=NULL) {
487 pFI->SetTxtColor(*pTxtCol);
488 delete pTxtCol;
490 if (pFldCol!=NULL) {
491 pFI->SetFldColor(*pFldCol);
492 delete pFldCol;
493 } else {
494 pFI->SetFldColor(Color(COL_LIGHTGRAY)); // TODO: remove this later on (357)
498 Outliner& rDrawOutl=pMod->GetDrawOutliner(pTextObj);
499 Link aDrawOutlLink=rDrawOutl.GetCalcFieldValueHdl();
500 if (!bOk && aDrawOutlLink.IsSet()) {
501 aDrawOutlLink.Call(pFI);
502 bOk = !rStr.isEmpty();
504 if (!bOk && aOldCalcFieldValueLink.IsSet()) {
505 return aOldCalcFieldValueLink.Call(pFI);
507 return 0;
510 IMPL_LINK(SdrObjEditView, EndTextEditHdl, SdrUndoManager*, /*pUndoManager*/)
512 SdrEndTextEdit();
513 return 0;
516 SdrUndoManager* SdrObjEditView::getSdrUndoManagerForEnhancedTextEdit() const
518 // default returns registered UndoManager
519 return GetModel() ? dynamic_cast< SdrUndoManager* >(GetModel()->GetSdrUndoManager()) : 0;
522 bool SdrObjEditView::SdrBeginTextEdit(
523 SdrObject* pObj, SdrPageView* pPV, Window* pWin,
524 bool bIsNewObj, SdrOutliner* pGivenOutliner,
525 OutlinerView* pGivenOutlinerView,
526 bool bDontDeleteOutliner, bool bOnlyOneView,
527 bool bGrabFocus)
529 SdrEndTextEdit();
531 if( dynamic_cast< SdrTextObj* >( pObj ) == 0 )
532 return false; // currently only possible with text objects
534 if(bGrabFocus && pWin)
536 // attention, this call may cause an EndTextEdit() call to this view
537 pWin->GrabFocus(); // to force the cursor into the edit view
540 bTextEditDontDelete=bDontDeleteOutliner && pGivenOutliner!=NULL;
541 bTextEditOnlyOneView=bOnlyOneView;
542 bTextEditNewObj=bIsNewObj;
543 const sal_uInt32 nWinAnz(PaintWindowCount());
544 sal_uInt32 i;
545 bool bBrk(false);
546 // break, when no object given
548 if(!pObj)
550 bBrk = true;
553 if(!bBrk && !pWin)
555 for(i = 0L; i < nWinAnz && !pWin; i++)
557 SdrPaintWindow* pPaintWindow = GetPaintWindow(i);
559 if(OUTDEV_WINDOW == pPaintWindow->GetOutputDevice().GetOutDevType())
561 pWin = (Window*)(&pPaintWindow->GetOutputDevice());
565 // break, when no window exists
566 if(!pWin)
568 bBrk = true;
572 if(!bBrk && !pPV)
574 pPV = GetSdrPageView();
576 // break, when no PageView for the object exists
577 if(!pPV)
579 bBrk = true;
583 if(pObj && pPV)
585 // no TextEdit on objects in locked Layer
586 if(pPV->GetLockedLayers().IsSet(pObj->GetLayer()))
588 bBrk = true;
592 if(pTextEditOutliner)
594 OSL_FAIL("SdrObjEditView::SdrBeginTextEdit(): Old Outliner still exists.");
595 delete pTextEditOutliner;
596 pTextEditOutliner = 0L;
599 if(!bBrk)
601 pTextEditWin=pWin;
602 pTextEditPV=pPV;
603 mxTextEditObj.reset( pObj );
604 pTextEditOutliner=pGivenOutliner;
605 if (pTextEditOutliner==NULL)
606 pTextEditOutliner = SdrMakeOutliner( OUTLINERMODE_TEXTOBJECT, mxTextEditObj->GetModel() );
609 SvtAccessibilityOptions aOptions;
610 pTextEditOutliner->ForceAutoColor( aOptions.GetIsAutomaticFontColor() );
613 bool bEmpty = mxTextEditObj->GetOutlinerParaObject()==NULL;
615 aOldCalcFieldValueLink=pTextEditOutliner->GetCalcFieldValueHdl();
616 // FieldHdl has to be set by SdrBeginTextEdit, because this call an UpdateFields
617 pTextEditOutliner->SetCalcFieldValueHdl(LINK(this,SdrObjEditView,ImpOutlinerCalcFieldValueHdl));
618 pTextEditOutliner->SetBeginPasteOrDropHdl(LINK(this,SdrObjEditView,BeginPasteOrDropHdl));
619 pTextEditOutliner->SetEndPasteOrDropHdl(LINK(this,SdrObjEditView, EndPasteOrDropHdl));
621 // It is just necessary to make the visualized page known. Set it.
622 pTextEditOutliner->setVisualizedPage(pPV->GetPage());
624 pTextEditOutliner->SetTextObjNoInit( dynamic_cast< SdrTextObj* >( mxTextEditObj.get() ) );
626 if(mxTextEditObj->BegTextEdit(*pTextEditOutliner))
628 SdrTextObj* pTextObj = dynamic_cast< SdrTextObj* >( mxTextEditObj.get() );
629 DBG_ASSERT( pTextObj, "svx::SdrObjEditView::BegTextEdit(), no text object?" );
630 if( !pTextObj )
631 return false;
633 // switch off any running TextAnimations
634 pTextObj->SetTextAnimationAllowed(false);
636 // remember old cursor
637 if (pTextEditOutliner->GetViewCount()!=0)
639 OutlinerView* pTmpOLV=pTextEditOutliner->RemoveView(static_cast<size_t>(0));
640 if(pTmpOLV!=NULL && pTmpOLV!=pGivenOutlinerView)
641 delete pTmpOLV;
644 // Determine EditArea via TakeTextEditArea.
645 // TODO: This could theoretically be left out, because TakeTextRect() calculates the aTextEditArea,
646 // but aMinTextEditArea has to happen, too (therefore leaving this in right now)
647 pTextObj->TakeTextEditArea(NULL,NULL,&aTextEditArea,&aMinTextEditArea);
649 Rectangle aTextRect;
650 Rectangle aAnchorRect;
651 pTextObj->TakeTextRect(*pTextEditOutliner, aTextRect, true,
652 &aAnchorRect /* Give true here, not false */);
654 if ( !pTextObj->IsContourTextFrame() )
656 // FitToSize not together with ContourFrame, for now
657 if (pTextObj->IsFitToSize())
658 aTextRect = aAnchorRect;
661 aTextEditArea = aTextRect;
663 // Hack for calc, transform position of edit object according
664 // to current zoom so as objects relative position to grid
665 // appears stable
667 Point aPvOfs(pTextObj->GetTextEditOffset());
668 aTextEditArea += pTextObj->GetGridOffset();
669 aTextEditArea.Move(aPvOfs.X(),aPvOfs.Y());
670 aMinTextEditArea += pTextObj->GetGridOffset();
671 aMinTextEditArea.Move(aPvOfs.X(),aPvOfs.Y());
672 pTextEditCursorMerker=pWin->GetCursor();
674 aHdl.SetMoveOutside(true);
676 // #i72757#
677 // Since IsMarkHdlWhenTextEdit() is ignored, it is necessary
678 // to call AdjustMarkHdl() always.
679 AdjustMarkHdl();
681 pTextEditOutlinerView=ImpMakeOutlinerView(pWin,!bEmpty,pGivenOutlinerView);
683 // check if this view is already inserted
684 sal_uIntPtr i2,nCount = pTextEditOutliner->GetViewCount();
685 for( i2 = 0; i2 < nCount; i2++ )
687 if( pTextEditOutliner->GetView(i2) == pTextEditOutlinerView )
688 break;
691 if( i2 == nCount )
692 pTextEditOutliner->InsertView(pTextEditOutlinerView,0);
694 aHdl.SetMoveOutside(false);
695 aHdl.SetMoveOutside(true);
697 // register all windows as OutlinerViews with the Outliner
698 if(!bOnlyOneView)
700 for(i = 0L; i < nWinAnz; i++)
702 SdrPaintWindow* pPaintWindow = GetPaintWindow(i);
703 OutputDevice& rOutDev = pPaintWindow->GetOutputDevice();
705 if(&rOutDev != pWin && OUTDEV_WINDOW == rOutDev.GetOutDevType())
707 OutlinerView* pOutlView = ImpMakeOutlinerView((Window*)(&rOutDev), !bEmpty, 0L);
708 pTextEditOutliner->InsertView(pOutlView, (sal_uInt16)i);
713 pTextEditOutlinerView->ShowCursor();
714 pTextEditOutliner->SetStatusEventHdl(LINK(this,SdrObjEditView,ImpOutlinerStatusEventHdl));
715 #ifdef DBG_UTIL
716 if (pItemBrowser!=NULL) pItemBrowser->SetDirty();
717 #endif
718 pTextEditOutliner->ClearModifyFlag();
720 if (pTextObj->IsFitToSize())
722 pWin->Invalidate(aTextEditArea);
725 if( GetModel() )
727 SdrHint aHint(*pTextObj);
728 aHint.SetKind(HINT_BEGEDIT);
729 GetModel()->Broadcast(aHint);
732 pTextEditOutliner->setVisualizedPage(0);
734 if( mxSelectionController.is() )
735 mxSelectionController->onSelectionHasChanged();
737 if(IsUndoEnabled() && GetModel() && !GetModel()->GetDisableTextEditUsesCommonUndoManager())
739 SdrUndoManager* pSdrUndoManager = getSdrUndoManagerForEnhancedTextEdit();
741 if(pSdrUndoManager)
743 // we have an outliner, undo manager and it's an EditUndoManager, exchange
744 // the document undo manager and the default one from the outliner and tell
745 // it that text edit starts by setting a callback if it needs to end text edit mode.
746 if(mpOldTextEditUndoManager)
748 // should not happen, delete it since it was probably forgotten somewhere
749 OSL_ENSURE(false, "Deleting forgotten old TextEditUndoManager, should be checked (!)");
750 delete mpOldTextEditUndoManager;
751 mpOldTextEditUndoManager = 0;
754 mpOldTextEditUndoManager = pTextEditOutliner->SetUndoManager(pSdrUndoManager);
755 pSdrUndoManager->SetEndTextEditHdl(LINK(this, SdrObjEditView, EndTextEditHdl));
757 else
759 OSL_ENSURE(false, "The document undo manager is not derived from SdrUndoManager (!)");
763 return true; // ran fine, let TextEdit run now
765 else
767 pTextEditOutliner->SetCalcFieldValueHdl(aOldCalcFieldValueLink);
768 pTextEditOutliner->SetBeginPasteOrDropHdl(Link());
769 pTextEditOutliner->SetEndPasteOrDropHdl(Link());
772 if (pTextEditOutliner != NULL)
774 pTextEditOutliner->setVisualizedPage(0);
777 // something went wrong...
778 if(!bDontDeleteOutliner)
780 if(pGivenOutliner!=NULL)
782 delete pGivenOutliner;
783 pTextEditOutliner = NULL;
785 if(pGivenOutlinerView!=NULL)
787 delete pGivenOutlinerView;
788 pGivenOutlinerView = NULL;
791 if( pTextEditOutliner!=NULL )
793 delete pTextEditOutliner;
796 pTextEditOutliner=NULL;
797 pTextEditOutlinerView=NULL;
798 mxTextEditObj.reset(0);
799 pTextEditPV=NULL;
800 pTextEditWin=NULL;
801 aHdl.SetMoveOutside(false);
803 return false;
806 SdrEndTextEditKind SdrObjEditView::SdrEndTextEdit(bool bDontDeleteReally)
808 SdrEndTextEditKind eRet=SDRENDTEXTEDIT_UNCHANGED;
809 SdrTextObj* pTEObj = dynamic_cast< SdrTextObj* >( mxTextEditObj.get() );
810 Window* pTEWin =pTextEditWin;
811 SdrOutliner* pTEOutliner =pTextEditOutliner;
812 OutlinerView* pTEOutlinerView=pTextEditOutlinerView;
813 Cursor* pTECursorMerker=pTextEditCursorMerker;
814 SdrUndoManager* pUndoEditUndoManager = 0;
815 bool bNeedToUndoSavedRedoTextEdit(false);
817 if(IsUndoEnabled() && GetModel() && pTEObj && pTEOutliner && !GetModel()->GetDisableTextEditUsesCommonUndoManager())
819 // change back the UndoManager to the remembered original one
820 ::svl::IUndoManager* pOriginal = pTEOutliner->SetUndoManager(mpOldTextEditUndoManager);
821 mpOldTextEditUndoManager = 0;
823 if(pOriginal)
825 // check if we got back our document undo manager
826 SdrUndoManager* pSdrUndoManager = getSdrUndoManagerForEnhancedTextEdit();
828 if(pSdrUndoManager && dynamic_cast< SdrUndoManager* >(pOriginal) == pSdrUndoManager)
830 if(pSdrUndoManager->isEndTextEditTriggeredFromUndo())
832 // remember the UndoManager where missing Undos have to be triggered after end
833 // text edit. When the undo had triggered the end text edit, the original action
834 // which had to be undone originally is not yet undone.
835 pUndoEditUndoManager = pSdrUndoManager;
837 // We are ending text edit; if text edit was triggered from undo, execute all redos
838 // to create a complete text change undo action for the redo buffer. Also mark this
839 // state when at least one redo was executed; the created extra TextChange needs to
840 // be undone in addition to the first real undo outside the text edit changes
841 while(pSdrUndoManager->GetRedoActionCount())
843 bNeedToUndoSavedRedoTextEdit = true;
844 pSdrUndoManager->Redo();
848 // reset the callback link and let the undo manager cleanup all text edit
849 // undo actions to get the stack back to the form before the text edit
850 pSdrUndoManager->SetEndTextEditHdl(Link());
852 else
854 OSL_ENSURE(false, "Got UndoManager back in SdrEndTextEdit which is NOT the expected document UndoManager (!)");
855 delete pOriginal;
860 if( GetModel() && mxTextEditObj.is() )
862 SdrHint aHint(*mxTextEditObj.get());
863 aHint.SetKind(HINT_ENDEDIT);
864 GetModel()->Broadcast(aHint);
867 mxTextEditObj.reset(0);
868 pTextEditPV=NULL;
869 pTextEditWin=NULL;
870 pTextEditOutliner=NULL;
871 pTextEditOutlinerView=NULL;
872 pTextEditCursorMerker=NULL;
873 aTextEditArea=Rectangle();
875 if (pTEOutliner!=NULL)
877 bool bModified=pTEOutliner->IsModified();
878 if (pTEOutlinerView!=NULL)
880 pTEOutlinerView->HideCursor();
882 if (pTEObj!=NULL)
884 pTEOutliner->CompleteOnlineSpelling();
886 SdrUndoObjSetText* pTxtUndo = 0;
888 if( bModified )
890 sal_Int32 nText;
891 for( nText = 0; nText < pTEObj->getTextCount(); ++nText )
892 if( pTEObj->getText( nText ) == pTEObj->getActiveText() )
893 break;
895 pTxtUndo = dynamic_cast< SdrUndoObjSetText* >( GetModel()->GetSdrUndoFactory().CreateUndoObjectSetText(*pTEObj, nText ) );
897 DBG_ASSERT( !bModified || pTxtUndo, "svx::SdrObjEditView::EndTextEdit(), could not create undo action!" );
898 // Set old CalcFieldValue-Handler again, this
899 // has to happen before Obj::EndTextEdit(), as this does UpdateFields().
900 pTEOutliner->SetCalcFieldValueHdl(aOldCalcFieldValueLink);
901 pTEOutliner->SetBeginPasteOrDropHdl(Link());
902 pTEOutliner->SetEndPasteOrDropHdl(Link());
904 const bool bUndo = IsUndoEnabled();
905 if( bUndo )
907 OUString aObjName(pTEObj->TakeObjNameSingul());
908 BegUndo(ImpGetResStr(STR_UndoObjSetText),aObjName);
911 pTEObj->EndTextEdit(*pTEOutliner);
913 if( (pTEObj->GetRotateAngle() != 0) || (pTEObj && pTEObj->ISA(SdrTextObj) && ((SdrTextObj*)pTEObj)->IsFontwork()) )
915 pTEObj->ActionChanged();
918 if (pTxtUndo!=NULL)
920 pTxtUndo->AfterSetText();
921 if (!pTxtUndo->IsDifferent())
923 delete pTxtUndo;
924 pTxtUndo=NULL;
927 // check deletion of entire TextObj
928 SdrUndoAction* pDelUndo=NULL;
929 bool bDelObj=false;
930 SdrTextObj* pTextObj=PTR_CAST(SdrTextObj,pTEObj);
931 if (pTextObj!=NULL && bTextEditNewObj)
933 bDelObj=pTextObj->IsTextFrame() &&
934 !pTextObj->HasText() &&
935 !pTextObj->IsEmptyPresObj() &&
936 !pTextObj->HasFill() &&
937 !pTextObj->HasLine();
939 if(pTEObj->IsInserted() && bDelObj && pTextObj->GetObjInventor()==SdrInventor && !bDontDeleteReally)
941 SdrObjKind eIdent=(SdrObjKind)pTextObj->GetObjIdentifier();
942 if(eIdent==OBJ_TEXT || eIdent==OBJ_TEXTEXT)
944 pDelUndo= GetModel()->GetSdrUndoFactory().CreateUndoDeleteObject(*pTEObj);
948 if (pTxtUndo!=NULL)
950 if( bUndo )
951 AddUndo(pTxtUndo);
952 eRet=SDRENDTEXTEDIT_CHANGED;
954 if (pDelUndo!=NULL)
956 if( bUndo )
958 AddUndo(pDelUndo);
960 else
962 delete pDelUndo;
964 eRet=SDRENDTEXTEDIT_DELETED;
965 DBG_ASSERT(pTEObj->GetObjList()!=NULL,"SdrObjEditView::SdrEndTextEdit(): Fatal: Object edited doesn't have an ObjList!");
966 if (pTEObj->GetObjList()!=NULL)
968 pTEObj->GetObjList()->RemoveObject(pTEObj->GetOrdNum());
969 CheckMarked(); // remove selection immediately...
972 else if (bDelObj)
973 { // for Writer: the app has to do the deletion itself.
974 eRet=SDRENDTEXTEDIT_SHOULDBEDELETED;
977 if( bUndo )
978 EndUndo(); // EndUndo after Remove, in case UndoStack is deleted immediately
980 // Switch on any TextAnimation again after TextEdit
981 if(pTEObj->ISA(SdrTextObj))
983 ((SdrTextObj*)pTEObj)->SetTextAnimationAllowed(true);
986 // #i72757#
987 // Since IsMarkHdlWhenTextEdit() is ignored, it is necessary
988 // to call AdjustMarkHdl() always.
989 AdjustMarkHdl();
991 // delete all OutlinerViews
992 for (sal_uIntPtr i=pTEOutliner->GetViewCount(); i>0;)
994 i--;
995 OutlinerView* pOLV=pTEOutliner->GetView(i);
996 sal_uInt16 nMorePix=pOLV->GetInvalidateMore() + 10;
997 Window* pWin=pOLV->GetWindow();
998 Rectangle aRect(pOLV->GetOutputArea());
999 pTEOutliner->RemoveView(i);
1000 if (!bTextEditDontDelete || i!=0)
1002 // may not own the zeroth one
1003 delete pOLV;
1005 aRect.Union(aTextEditArea);
1006 aRect.Union(aMinTextEditArea);
1007 aRect=pWin->LogicToPixel(aRect);
1008 aRect.Left()-=nMorePix;
1009 aRect.Top()-=nMorePix;
1010 aRect.Right()+=nMorePix;
1011 aRect.Bottom()+=nMorePix;
1012 aRect=pWin->PixelToLogic(aRect);
1013 InvalidateOneWin(*pWin,aRect);
1014 pWin->SetFillColor();
1015 pWin->SetLineColor(COL_BLACK);
1016 pWin->DrawPixel(aRect.TopLeft());
1017 pWin->DrawPixel(aRect.TopRight());
1018 pWin->DrawPixel(aRect.BottomLeft());
1019 pWin->DrawPixel(aRect.BottomRight());
1021 // and now the Outliner itself
1022 if (!bTextEditDontDelete) delete pTEOutliner;
1023 else pTEOutliner->Clear();
1024 if (pTEWin!=NULL) {
1025 pTEWin->SetCursor(pTECursorMerker);
1027 aHdl.SetMoveOutside(false);
1028 if (eRet!=SDRENDTEXTEDIT_UNCHANGED)
1030 GetMarkedObjectListWriteAccess().SetNameDirty();
1032 #ifdef DBG_UTIL
1033 if (pItemBrowser)
1035 GetMarkedObjectListWriteAccess().SetNameDirty();
1036 pItemBrowser->SetDirty();
1038 #endif
1041 if( pTEObj &&
1042 pTEObj->GetModel() &&
1043 !pTEObj->GetModel()->isLocked() &&
1044 pTEObj->GetBroadcaster())
1046 SdrHint aHint(HINT_ENDEDIT);
1047 aHint.SetObject(pTEObj);
1048 ((SfxBroadcaster*)pTEObj->GetBroadcaster())->Broadcast(aHint);
1051 if(pUndoEditUndoManager)
1053 if(bNeedToUndoSavedRedoTextEdit)
1055 // undo the text edit action since it was created as part of an EndTextEdit
1056 // callback from undo itself. This needs to be done after the call to
1057 // FmFormView::SdrEndTextEdit since it gets created there
1058 pUndoEditUndoManager->Undo();
1061 // trigger the Undo which was not executed, but lead to this
1062 // end text edit
1063 pUndoEditUndoManager->Undo();
1066 return eRet;
1070 // info about TextEdit. Default is false.
1071 bool SdrObjEditView::IsTextEdit() const
1073 return mxTextEditObj.is();
1076 // info about TextEditPageView. Default is 0L.
1077 SdrPageView* SdrObjEditView::GetTextEditPageView() const
1079 return pTextEditPV;
1084 OutlinerView* SdrObjEditView::ImpFindOutlinerView(Window* pWin) const
1086 if (pWin==NULL) return NULL;
1087 if (pTextEditOutliner==NULL) return NULL;
1088 OutlinerView* pNewView=NULL;
1089 sal_uIntPtr nWinAnz=pTextEditOutliner->GetViewCount();
1090 for (sal_uIntPtr i=0; i<nWinAnz && pNewView==NULL; i++) {
1091 OutlinerView* pView=pTextEditOutliner->GetView(i);
1092 if (pView->GetWindow()==pWin) pNewView=pView;
1094 return pNewView;
1097 void SdrObjEditView::SetTextEditWin(Window* pWin)
1099 if(mxTextEditObj.is() && pWin!=NULL && pWin!=pTextEditWin)
1101 OutlinerView* pNewView=ImpFindOutlinerView(pWin);
1102 if (pNewView!=NULL && pNewView!=pTextEditOutlinerView)
1104 if (pTextEditOutlinerView!=NULL)
1106 pTextEditOutlinerView->HideCursor();
1108 pTextEditOutlinerView=pNewView;
1109 pTextEditWin=pWin;
1110 pWin->GrabFocus(); // Make the cursor blink here as well
1111 pNewView->ShowCursor();
1112 ImpMakeTextCursorAreaVisible();
1117 bool SdrObjEditView::IsTextEditHit(const Point& rHit, short nTol) const
1119 bool bOk=false;
1120 if(mxTextEditObj.is())
1122 nTol=ImpGetHitTolLogic(nTol,NULL);
1123 // only a third of the tolerance here, so handles can be hit well
1124 nTol=nTol/3;
1125 nTol=0; // no hit tolerance here any more
1127 Rectangle aEditArea;
1128 OutlinerView* pOLV=pTextEditOutliner->GetView(0);
1129 if (pOLV!=NULL)
1131 aEditArea.Union(pOLV->GetOutputArea());
1133 aEditArea.Left()-=nTol;
1134 aEditArea.Top()-=nTol;
1135 aEditArea.Right()+=nTol;
1136 aEditArea.Bottom()+=nTol;
1137 bOk=aEditArea.IsInside(rHit);
1138 if (bOk)
1139 { // check if any characters were actually hit
1140 Point aPnt(rHit); aPnt-=aEditArea.TopLeft();
1141 long nHitTol = 2000;
1142 OutputDevice* pRef = pTextEditOutliner->GetRefDevice();
1143 if( pRef )
1144 nHitTol = pRef->LogicToLogic( nHitTol, MAP_100TH_MM, pRef->GetMapMode().GetMapUnit() );
1146 bOk = pTextEditOutliner->IsTextPos( aPnt, (sal_uInt16)nHitTol );
1149 return bOk;
1152 bool SdrObjEditView::IsTextEditFrameHit(const Point& rHit) const
1154 bool bOk=false;
1155 if(mxTextEditObj.is())
1157 SdrTextObj* pText= dynamic_cast<SdrTextObj*>(mxTextEditObj.get());
1158 OutlinerView* pOLV=pTextEditOutliner->GetView(0);
1159 if( pOLV )
1161 Window* pWin=pOLV->GetWindow();
1162 if (pText!=NULL && pText->IsTextFrame() && pOLV!=NULL && pWin!=NULL) {
1163 sal_uInt16 nPixSiz=pOLV->GetInvalidateMore();
1164 Rectangle aEditArea(aMinTextEditArea);
1165 aEditArea.Union(pOLV->GetOutputArea());
1166 if (!aEditArea.IsInside(rHit)) {
1167 Size aSiz(pWin->PixelToLogic(Size(nPixSiz,nPixSiz)));
1168 aEditArea.Left()-=aSiz.Width();
1169 aEditArea.Top()-=aSiz.Height();
1170 aEditArea.Right()+=aSiz.Width();
1171 aEditArea.Bottom()+=aSiz.Height();
1172 bOk=aEditArea.IsInside(rHit);
1177 return bOk;
1182 bool SdrObjEditView::KeyInput(const KeyEvent& rKEvt, Window* pWin)
1184 if(pTextEditOutlinerView)
1186 if (pTextEditOutlinerView->PostKeyEvent(rKEvt, pWin))
1188 if( pMod )
1190 if( pTextEditOutliner && pTextEditOutliner->IsModified() )
1191 pMod->SetChanged( true );
1194 if (pWin!=NULL && pWin!=pTextEditWin) SetTextEditWin(pWin);
1195 #ifdef DBG_UTIL
1196 if (pItemBrowser!=NULL) pItemBrowser->SetDirty();
1197 #endif
1198 ImpMakeTextCursorAreaVisible();
1199 return true;
1202 return SdrGlueEditView::KeyInput(rKEvt,pWin);
1205 bool SdrObjEditView::MouseButtonDown(const MouseEvent& rMEvt, Window* pWin)
1207 if (pTextEditOutlinerView!=NULL) {
1208 bool bPostIt=pTextEditOutliner->IsInSelectionMode();
1209 if (!bPostIt) {
1210 Point aPt(rMEvt.GetPosPixel());
1211 if (pWin!=NULL) aPt=pWin->PixelToLogic(aPt);
1212 else if (pTextEditWin!=NULL) aPt=pTextEditWin->PixelToLogic(aPt);
1213 bPostIt=IsTextEditHit(aPt,nHitTolLog);
1215 if (bPostIt) {
1216 Point aPixPos(rMEvt.GetPosPixel());
1217 if (pWin)
1219 Rectangle aR(pWin->LogicToPixel(pTextEditOutlinerView->GetOutputArea()));
1220 if (aPixPos.X()<aR.Left ()) aPixPos.X()=aR.Left ();
1221 if (aPixPos.X()>aR.Right ()) aPixPos.X()=aR.Right ();
1222 if (aPixPos.Y()<aR.Top ()) aPixPos.Y()=aR.Top ();
1223 if (aPixPos.Y()>aR.Bottom()) aPixPos.Y()=aR.Bottom();
1225 MouseEvent aMEvt(aPixPos,rMEvt.GetClicks(),rMEvt.GetMode(),
1226 rMEvt.GetButtons(),rMEvt.GetModifier());
1227 if (pTextEditOutlinerView->MouseButtonDown(aMEvt)) {
1228 if (pWin!=NULL && pWin!=pTextEditWin) SetTextEditWin(pWin);
1229 #ifdef DBG_UTIL
1230 if (pItemBrowser!=NULL) pItemBrowser->SetDirty();
1231 #endif
1232 ImpMakeTextCursorAreaVisible();
1233 return true;
1237 return SdrGlueEditView::MouseButtonDown(rMEvt,pWin);
1240 bool SdrObjEditView::MouseButtonUp(const MouseEvent& rMEvt, Window* pWin)
1242 if (pTextEditOutlinerView!=NULL) {
1243 bool bPostIt=pTextEditOutliner->IsInSelectionMode();
1244 if (!bPostIt) {
1245 Point aPt(rMEvt.GetPosPixel());
1246 if (pWin!=NULL) aPt=pWin->PixelToLogic(aPt);
1247 else if (pTextEditWin!=NULL) aPt=pTextEditWin->PixelToLogic(aPt);
1248 bPostIt=IsTextEditHit(aPt,nHitTolLog);
1250 if (bPostIt) {
1251 Point aPixPos(rMEvt.GetPosPixel());
1252 Rectangle aR(pWin->LogicToPixel(pTextEditOutlinerView->GetOutputArea()));
1253 if (aPixPos.X()<aR.Left ()) aPixPos.X()=aR.Left ();
1254 if (aPixPos.X()>aR.Right ()) aPixPos.X()=aR.Right ();
1255 if (aPixPos.Y()<aR.Top ()) aPixPos.Y()=aR.Top ();
1256 if (aPixPos.Y()>aR.Bottom()) aPixPos.Y()=aR.Bottom();
1257 MouseEvent aMEvt(aPixPos,rMEvt.GetClicks(),rMEvt.GetMode(),
1258 rMEvt.GetButtons(),rMEvt.GetModifier());
1259 if (pTextEditOutlinerView->MouseButtonUp(aMEvt)) {
1260 #ifdef DBG_UTIL
1261 if (pItemBrowser!=NULL) pItemBrowser->SetDirty();
1262 #endif
1263 ImpMakeTextCursorAreaVisible();
1264 return true;
1268 return SdrGlueEditView::MouseButtonUp(rMEvt,pWin);
1271 bool SdrObjEditView::MouseMove(const MouseEvent& rMEvt, Window* pWin)
1273 if (pTextEditOutlinerView!=NULL) {
1274 bool bSelMode=pTextEditOutliner->IsInSelectionMode();
1275 bool bPostIt=bSelMode;
1276 if (!bPostIt) {
1277 Point aPt(rMEvt.GetPosPixel());
1278 if (pWin!=NULL) aPt=pWin->PixelToLogic(aPt);
1279 else if (pTextEditWin!=NULL) aPt=pTextEditWin->PixelToLogic(aPt);
1280 bPostIt=IsTextEditHit(aPt,nHitTolLog);
1282 if (bPostIt) {
1283 Point aPixPos(rMEvt.GetPosPixel());
1284 Rectangle aR(pWin->LogicToPixel(pTextEditOutlinerView->GetOutputArea()));
1285 if (aPixPos.X()<aR.Left ()) aPixPos.X()=aR.Left ();
1286 if (aPixPos.X()>aR.Right ()) aPixPos.X()=aR.Right ();
1287 if (aPixPos.Y()<aR.Top ()) aPixPos.Y()=aR.Top ();
1288 if (aPixPos.Y()>aR.Bottom()) aPixPos.Y()=aR.Bottom();
1289 MouseEvent aMEvt(aPixPos,rMEvt.GetClicks(),rMEvt.GetMode(),
1290 rMEvt.GetButtons(),rMEvt.GetModifier());
1291 if (pTextEditOutlinerView->MouseMove(aMEvt) && bSelMode) {
1292 #ifdef DBG_UTIL
1293 if (pItemBrowser!=NULL) pItemBrowser->SetDirty();
1294 #endif
1295 ImpMakeTextCursorAreaVisible();
1296 return true;
1300 return SdrGlueEditView::MouseMove(rMEvt,pWin);
1303 bool SdrObjEditView::Command(const CommandEvent& rCEvt, Window* pWin)
1305 // as long as OutlinerView returns a sal_Bool, it only gets COMMAND_STARTDRAG
1306 if (pTextEditOutlinerView!=NULL)
1308 if (rCEvt.GetCommand()==COMMAND_STARTDRAG) {
1309 bool bPostIt=pTextEditOutliner->IsInSelectionMode() || !rCEvt.IsMouseEvent();
1310 if (!bPostIt && rCEvt.IsMouseEvent()) {
1311 Point aPt(rCEvt.GetMousePosPixel());
1312 if (pWin!=NULL) aPt=pWin->PixelToLogic(aPt);
1313 else if (pTextEditWin!=NULL) aPt=pTextEditWin->PixelToLogic(aPt);
1314 bPostIt=IsTextEditHit(aPt,nHitTolLog);
1316 if (bPostIt) {
1317 Point aPixPos(rCEvt.GetMousePosPixel());
1318 if (rCEvt.IsMouseEvent()) {
1319 Rectangle aR(pWin->LogicToPixel(pTextEditOutlinerView->GetOutputArea()));
1320 if (aPixPos.X()<aR.Left ()) aPixPos.X()=aR.Left ();
1321 if (aPixPos.X()>aR.Right ()) aPixPos.X()=aR.Right ();
1322 if (aPixPos.Y()<aR.Top ()) aPixPos.Y()=aR.Top ();
1323 if (aPixPos.Y()>aR.Bottom()) aPixPos.Y()=aR.Bottom();
1325 CommandEvent aCEvt(aPixPos,rCEvt.GetCommand(),rCEvt.IsMouseEvent());
1326 // Command is void at the OutlinerView, sadly
1327 pTextEditOutlinerView->Command(aCEvt);
1328 if (pWin!=NULL && pWin!=pTextEditWin) SetTextEditWin(pWin);
1329 #ifdef DBG_UTIL
1330 if (pItemBrowser!=NULL) pItemBrowser->SetDirty();
1331 #endif
1332 ImpMakeTextCursorAreaVisible();
1333 return true;
1336 else
1338 pTextEditOutlinerView->Command(rCEvt);
1339 return true;
1342 return SdrGlueEditView::Command(rCEvt,pWin);
1347 bool SdrObjEditView::ImpIsTextEditAllSelected() const
1349 bool bRet=false;
1350 if (pTextEditOutliner!=NULL && pTextEditOutlinerView!=NULL)
1352 if(SdrTextObj::HasTextImpl( pTextEditOutliner ) )
1354 const sal_Int32 nParaAnz=pTextEditOutliner->GetParagraphCount();
1355 Paragraph* pLastPara=pTextEditOutliner->GetParagraph( nParaAnz > 1 ? nParaAnz - 1 : 0 );
1357 ESelection aESel(pTextEditOutlinerView->GetSelection());
1358 if (aESel.nStartPara==0 && aESel.nStartPos==0 && aESel.nEndPara==(nParaAnz-1))
1360 if( pTextEditOutliner->GetText(pLastPara).getLength() == aESel.nEndPos )
1361 bRet = true;
1363 // in case the selection was done backwards
1364 if (!bRet && aESel.nEndPara==0 && aESel.nEndPos==0 && aESel.nStartPara==(nParaAnz-1))
1366 if(pTextEditOutliner->GetText(pLastPara).getLength() == aESel.nStartPos)
1367 bRet = true;
1370 else
1372 bRet=true;
1375 return bRet;
1378 void SdrObjEditView::ImpMakeTextCursorAreaVisible()
1380 if (pTextEditOutlinerView!=NULL && pTextEditWin!=NULL) {
1381 Cursor* pCsr=pTextEditWin->GetCursor();
1382 if (pCsr!=NULL) {
1383 Size aSiz(pCsr->GetSize());
1384 if (aSiz.Width()!=0 && aSiz.Height()!=0) {
1385 MakeVisible(Rectangle(pCsr->GetPos(),aSiz),*pTextEditWin);
1391 sal_uInt16 SdrObjEditView::GetScriptType() const
1393 sal_uInt16 nScriptType = 0;
1395 if( IsTextEdit() )
1397 if( mxTextEditObj->GetOutlinerParaObject() )
1398 nScriptType = mxTextEditObj->GetOutlinerParaObject()->GetTextObject().GetScriptType();
1400 if( pTextEditOutlinerView )
1401 nScriptType = pTextEditOutlinerView->GetSelectedScriptType();
1403 else
1405 sal_uInt32 nMarkCount( GetMarkedObjectCount() );
1407 for( sal_uInt32 i = 0; i < nMarkCount; i++ )
1409 OutlinerParaObject* pParaObj = GetMarkedObjectByIndex( i )->GetOutlinerParaObject();
1411 if( pParaObj )
1413 nScriptType |= pParaObj->GetTextObject().GetScriptType();
1418 if( nScriptType == 0 )
1419 nScriptType = SCRIPTTYPE_LATIN;
1421 return nScriptType;
1424 bool SdrObjEditView::GetAttributes(SfxItemSet& rTargetSet, bool bOnlyHardAttr) const
1426 if( mxSelectionController.is() )
1427 if( mxSelectionController->GetAttributes( rTargetSet, bOnlyHardAttr ) )
1428 return true;
1430 if(IsTextEdit())
1432 DBG_ASSERT(pTextEditOutlinerView!=NULL,"SdrObjEditView::GetAttributes(): pTextEditOutlinerView=NULL");
1433 DBG_ASSERT(pTextEditOutliner!=NULL,"SdrObjEditView::GetAttributes(): pTextEditOutliner=NULL");
1435 // take care of bOnlyHardAttr(!)
1436 if(!bOnlyHardAttr && mxTextEditObj->GetStyleSheet())
1437 rTargetSet.Put(mxTextEditObj->GetStyleSheet()->GetItemSet());
1439 // add object attributes
1440 rTargetSet.Put( mxTextEditObj->GetMergedItemSet() );
1442 if( mxTextEditObj->GetOutlinerParaObject() )
1443 rTargetSet.Put( SvxScriptTypeItem( mxTextEditObj->GetOutlinerParaObject()->GetTextObject().GetScriptType() ) );
1445 if(pTextEditOutlinerView)
1447 // FALSE= regard InvalidItems as "holes," not as Default
1448 rTargetSet.Put(pTextEditOutlinerView->GetAttribs(), false);
1449 rTargetSet.Put( SvxScriptTypeItem( pTextEditOutlinerView->GetSelectedScriptType() ) );
1452 if(GetMarkedObjectCount()==1 && GetMarkedObjectByIndex(0)==mxTextEditObj.get())
1454 MergeNotPersistAttrFromMarked(rTargetSet, bOnlyHardAttr);
1457 return true;
1459 else
1461 return SdrGlueEditView::GetAttributes(rTargetSet, bOnlyHardAttr);
1465 bool SdrObjEditView::SetAttributes(const SfxItemSet& rSet, bool bReplaceAll)
1467 bool bRet=false;
1468 bool bTextEdit=pTextEditOutlinerView!=NULL && mxTextEditObj.is();
1469 bool bAllTextSelected=ImpIsTextEditAllSelected();
1470 const SfxItemSet* pSet=&rSet;
1472 if (!bTextEdit)
1474 // no TextEdit activw -> all Items to drawing object
1475 if( mxSelectionController.is() )
1476 bRet=mxSelectionController->SetAttributes(*pSet,bReplaceAll );
1478 if( !bRet )
1480 bRet=SdrGlueEditView::SetAttributes(*pSet,bReplaceAll);
1483 else
1485 #ifdef DBG_UTIL
1487 bool bHasEEFeatureItems=false;
1488 SfxItemIter aIter(rSet);
1489 const SfxPoolItem* pItem=aIter.FirstItem();
1490 while (!bHasEEFeatureItems && pItem!=NULL)
1492 if (!IsInvalidItem(pItem))
1494 sal_uInt16 nW=pItem->Which();
1495 if (nW>=EE_FEATURE_START && nW<=EE_FEATURE_END)
1496 bHasEEFeatureItems=true;
1499 pItem=aIter.NextItem();
1502 if(bHasEEFeatureItems)
1504 OUString aMessage("SdrObjEditView::SetAttributes(): Setting EE_FEATURE items at the SdrView does not make sense! It only leads to overhead and unreadable documents.");
1505 InfoBox(NULL, aMessage).Execute();
1508 #endif
1510 bool bOnlyEEItems;
1511 bool bNoEEItems=!SearchOutlinerItems(*pSet,bReplaceAll,&bOnlyEEItems);
1512 // everything selected? -> attributes to the border, too
1513 // if no EEItems, attributes to the border only
1514 if (bAllTextSelected || bNoEEItems)
1516 if( mxSelectionController.is() )
1517 bRet=mxSelectionController->SetAttributes(*pSet,bReplaceAll );
1519 if( !bRet )
1521 const bool bUndo = IsUndoEnabled();
1523 if( bUndo )
1525 OUString aStr;
1526 ImpTakeDescriptionStr(STR_EditSetAttributes,aStr);
1527 BegUndo(aStr);
1528 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*mxTextEditObj.get()));
1530 // #i43537#
1531 // If this is a text object also rescue the OutlinerParaObject since
1532 // applying attributes to the object may change text layout when
1533 // multiple portions exist with multiple formats. If a OutlinerParaObject
1534 // really exists and needs to be rescued is evaluated in the undo
1535 // implementation itself.
1536 bool bRescueText = dynamic_cast< SdrTextObj* >(mxTextEditObj.get());
1538 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoAttrObject(*mxTextEditObj.get(),false,!bNoEEItems || bRescueText));
1539 EndUndo();
1542 mxTextEditObj->SetMergedItemSetAndBroadcast(*pSet, bReplaceAll);
1544 FlushComeBackTimer(); // to set ModeHasChanged immediately
1545 bRet=true;
1548 else if (!bOnlyEEItems)
1550 // Otherwise split Set, if necessary.
1551 // Now we build an ItemSet aSet that doesn't contain EE_Items from
1552 // *pSet (otherwise it would be a copy).
1553 sal_uInt16* pNewWhichTable=RemoveWhichRange(pSet->GetRanges(),EE_ITEMS_START,EE_ITEMS_END);
1554 SfxItemSet aSet(pMod->GetItemPool(),pNewWhichTable);
1555 delete[] pNewWhichTable;
1556 SfxWhichIter aIter(aSet);
1557 sal_uInt16 nWhich=aIter.FirstWhich();
1558 while (nWhich!=0)
1560 const SfxPoolItem* pItem;
1561 SfxItemState eState=pSet->GetItemState(nWhich,false,&pItem);
1562 if (eState==SFX_ITEM_SET) aSet.Put(*pItem);
1563 nWhich=aIter.NextWhich();
1567 if( mxSelectionController.is() )
1568 bRet=mxSelectionController->SetAttributes(aSet,bReplaceAll );
1570 if( !bRet )
1572 if( IsUndoEnabled() )
1574 OUString aStr;
1575 ImpTakeDescriptionStr(STR_EditSetAttributes,aStr);
1576 BegUndo(aStr);
1577 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*mxTextEditObj.get()));
1578 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoAttrObject(*mxTextEditObj.get(),false,false));
1579 EndUndo();
1582 mxTextEditObj->SetMergedItemSetAndBroadcast(aSet, bReplaceAll);
1584 if (GetMarkedObjectCount()==1 && GetMarkedObjectByIndex(0)==mxTextEditObj.get())
1586 SetNotPersistAttrToMarked(aSet,bReplaceAll);
1589 FlushComeBackTimer();
1590 bRet=true;
1592 if(!bNoEEItems)
1594 // and now the attributes to the EditEngine
1595 if (bReplaceAll) {
1596 pTextEditOutlinerView->RemoveAttribs( true );
1598 pTextEditOutlinerView->SetAttribs(rSet);
1600 #ifdef DBG_UTIL
1601 if (pItemBrowser!=NULL)
1602 pItemBrowser->SetDirty();
1603 #endif
1605 ImpMakeTextCursorAreaVisible();
1607 bRet=true;
1609 return bRet;
1612 SfxStyleSheet* SdrObjEditView::GetStyleSheet() const
1614 SfxStyleSheet* pSheet = 0;
1616 if( mxSelectionController.is() )
1618 if( mxSelectionController->GetStyleSheet( pSheet ) )
1619 return pSheet;
1622 if ( pTextEditOutlinerView )
1624 pSheet = pTextEditOutlinerView->GetStyleSheet();
1626 else
1628 pSheet = SdrGlueEditView::GetStyleSheet();
1630 return pSheet;
1633 bool SdrObjEditView::SetStyleSheet(SfxStyleSheet* pStyleSheet, bool bDontRemoveHardAttr)
1635 if( mxSelectionController.is() )
1637 if( mxSelectionController->SetStyleSheet( pStyleSheet, bDontRemoveHardAttr ) )
1638 return true;
1641 // if we are currently in edit mode we must also set the stylesheet
1642 // on all paragraphs in the Outliner for the edit view
1643 if( NULL != pTextEditOutlinerView )
1645 Outliner* pOutliner = pTextEditOutlinerView->GetOutliner();
1647 const sal_Int32 nParaCount = pOutliner->GetParagraphCount();
1648 for( sal_Int32 nPara = 0; nPara < nParaCount; nPara++ )
1650 pOutliner->SetStyleSheet( nPara, pStyleSheet );
1654 return SdrGlueEditView::SetStyleSheet(pStyleSheet,bDontRemoveHardAttr);
1659 void SdrObjEditView::AddWindowToPaintView(OutputDevice* pNewWin)
1661 SdrGlueEditView::AddWindowToPaintView(pNewWin);
1663 if(mxTextEditObj.is() && !bTextEditOnlyOneView && pNewWin->GetOutDevType()==OUTDEV_WINDOW)
1665 OutlinerView* pOutlView=ImpMakeOutlinerView((Window*)pNewWin,false,NULL);
1666 pTextEditOutliner->InsertView(pOutlView);
1670 void SdrObjEditView::DeleteWindowFromPaintView(OutputDevice* pOldWin)
1672 SdrGlueEditView::DeleteWindowFromPaintView(pOldWin);
1674 if(mxTextEditObj.is() && !bTextEditOnlyOneView && pOldWin->GetOutDevType()==OUTDEV_WINDOW)
1676 for (sal_uIntPtr i=pTextEditOutliner->GetViewCount(); i>0;) {
1677 i--;
1678 OutlinerView* pOLV=pTextEditOutliner->GetView(i);
1679 if (pOLV && pOLV->GetWindow()==(Window*)pOldWin) {
1680 delete pTextEditOutliner->RemoveView(i);
1686 bool SdrObjEditView::IsTextEditInSelectionMode() const
1688 return pTextEditOutliner!=NULL && pTextEditOutliner->IsInSelectionMode();
1692 // MacroMode
1695 bool SdrObjEditView::BegMacroObj(const Point& rPnt, short nTol, SdrObject* pObj, SdrPageView* pPV, Window* pWin)
1697 BrkMacroObj();
1698 if (pObj!=NULL && pPV!=NULL && pWin!=NULL && pObj->HasMacro()) {
1699 nTol=ImpGetHitTolLogic(nTol,NULL);
1700 pMacroObj=pObj;
1701 pMacroPV=pPV;
1702 pMacroWin=pWin;
1703 bMacroDown=false;
1704 nMacroTol=sal_uInt16(nTol);
1705 aMacroDownPos=rPnt;
1706 MovMacroObj(rPnt);
1708 return false;
1711 void SdrObjEditView::ImpMacroUp(const Point& rUpPos)
1713 if (pMacroObj!=NULL && bMacroDown)
1715 SdrObjMacroHitRec aHitRec;
1716 aHitRec.aPos=rUpPos;
1717 aHitRec.aDownPos=aMacroDownPos;
1718 aHitRec.nTol=nMacroTol;
1719 aHitRec.pVisiLayer=&pMacroPV->GetVisibleLayers();
1720 aHitRec.pPageView=pMacroPV;
1721 aHitRec.pOut=pMacroWin;
1722 pMacroObj->PaintMacro(*pMacroWin,Rectangle(),aHitRec);
1723 bMacroDown=false;
1727 void SdrObjEditView::ImpMacroDown(const Point& rDownPos)
1729 if (pMacroObj!=NULL && !bMacroDown)
1731 SdrObjMacroHitRec aHitRec;
1732 aHitRec.aPos=rDownPos;
1733 aHitRec.aDownPos=aMacroDownPos;
1734 aHitRec.nTol=nMacroTol;
1735 aHitRec.pVisiLayer=&pMacroPV->GetVisibleLayers();
1736 aHitRec.pPageView=pMacroPV;
1737 aHitRec.bDown=true;
1738 aHitRec.pOut=pMacroWin;
1739 pMacroObj->PaintMacro(*pMacroWin,Rectangle(),aHitRec);
1740 bMacroDown=true;
1744 void SdrObjEditView::MovMacroObj(const Point& rPnt)
1746 if (pMacroObj!=NULL) {
1747 SdrObjMacroHitRec aHitRec;
1748 aHitRec.aPos=rPnt;
1749 aHitRec.aDownPos=aMacroDownPos;
1750 aHitRec.nTol=nMacroTol;
1751 aHitRec.pVisiLayer=&pMacroPV->GetVisibleLayers();
1752 aHitRec.pPageView=pMacroPV;
1753 aHitRec.bDown=bMacroDown;
1754 aHitRec.pOut=pMacroWin;
1755 bool bDown=pMacroObj->IsMacroHit(aHitRec);
1756 if (bDown) ImpMacroDown(rPnt);
1757 else ImpMacroUp(rPnt);
1761 void SdrObjEditView::BrkMacroObj()
1763 if (pMacroObj!=NULL) {
1764 ImpMacroUp(aMacroDownPos);
1765 pMacroObj=NULL;
1766 pMacroPV=NULL;
1767 pMacroWin=NULL;
1771 bool SdrObjEditView::EndMacroObj()
1773 if (pMacroObj!=NULL && bMacroDown) {
1774 ImpMacroUp(aMacroDownPos);
1775 SdrObjMacroHitRec aHitRec;
1776 aHitRec.aPos=aMacroDownPos;
1777 aHitRec.aDownPos=aMacroDownPos;
1778 aHitRec.nTol=nMacroTol;
1779 aHitRec.pVisiLayer=&pMacroPV->GetVisibleLayers();
1780 aHitRec.pPageView=pMacroPV;
1781 aHitRec.bDown=true;
1782 aHitRec.pOut=pMacroWin;
1783 bool bRet=pMacroObj->DoMacro(aHitRec);
1784 pMacroObj=NULL;
1785 pMacroPV=NULL;
1786 pMacroWin=NULL;
1787 return bRet;
1788 } else {
1789 BrkMacroObj();
1790 return false;
1794 /** fills the given any with a XTextCursor for the current text selection.
1795 Leaves the any untouched if there currently is no text selected */
1796 void SdrObjEditView::getTextSelection( ::com::sun::star::uno::Any& rSelection )
1798 if( IsTextEdit() )
1800 OutlinerView* pOutlinerView = GetTextEditOutlinerView();
1801 if( pOutlinerView && pOutlinerView->HasSelection() )
1803 SdrObject* pObj = GetTextEditObject();
1805 if( pObj )
1807 ::com::sun::star::uno::Reference< ::com::sun::star::text::XText > xText( pObj->getUnoShape(), ::com::sun::star::uno::UNO_QUERY );
1808 if( xText.is() )
1810 SvxUnoTextBase* pRange = SvxUnoTextBase::getImplementation( xText );
1811 if( pRange )
1813 rSelection <<= pRange->createTextCursorBySelection( pOutlinerView->GetSelection() );
1821 /* check if we have a single selection and that single object likes
1822 to handle the mouse and keyboard events itself
1824 TODO: the selection controller should be queried from the
1825 object specific view contact. Currently this method only
1826 works for tables.
1828 void SdrObjEditView::MarkListHasChanged()
1830 SdrGlueEditView::MarkListHasChanged();
1832 if( mxSelectionController.is() )
1834 mxLastSelectionController = mxSelectionController;
1835 mxSelectionController->onSelectionHasChanged();
1838 mxSelectionController.clear();
1840 const SdrMarkList& rMarkList=GetMarkedObjectList();
1841 if( rMarkList.GetMarkCount() == 1 )
1843 const SdrObject* pObj= rMarkList.GetMark(0)->GetMarkedSdrObj();
1844 // check for table
1845 if( pObj && (pObj->GetObjInventor() == SdrInventor ) && (pObj->GetObjIdentifier() == OBJ_TABLE) )
1847 mxSelectionController = sdr::table::CreateTableController( this, pObj, mxLastSelectionController );
1848 if( mxSelectionController.is() )
1850 mxLastSelectionController.clear();
1851 mxSelectionController->onSelectionHasChanged();
1857 IMPL_LINK( SdrObjEditView, EndPasteOrDropHdl, PasteOrDropInfos*, pInfos )
1859 OnEndPasteOrDrop( pInfos );
1860 return 0;
1863 IMPL_LINK( SdrObjEditView, BeginPasteOrDropHdl, PasteOrDropInfos*, pInfos )
1865 OnBeginPasteOrDrop( pInfos );
1866 return 0;
1869 void SdrObjEditView::OnBeginPasteOrDrop( PasteOrDropInfos* )
1871 // applications can derive from these virtual methods to do something before a drop or paste operation
1874 void SdrObjEditView::OnEndPasteOrDrop( PasteOrDropInfos* )
1876 // applications can derive from these virtual methods to do something before a drop or paste operation
1879 sal_uInt16 SdrObjEditView::GetSelectionLevel() const
1881 sal_uInt16 nLevel = 0xFFFF;
1882 if( IsTextEdit() )
1884 DBG_ASSERT(pTextEditOutlinerView!=NULL,"SdrObjEditView::GetAttributes(): pTextEditOutlinerView=NULL");
1885 DBG_ASSERT(pTextEditOutliner!=NULL,"SdrObjEditView::GetAttributes(): pTextEditOutliner=NULL");
1886 if( pTextEditOutlinerView )
1888 //start and end position
1889 ESelection aSelect = pTextEditOutlinerView->GetSelection();
1890 sal_uInt16 nStartPara = ::std::min( aSelect.nStartPara, aSelect.nEndPara );
1891 sal_uInt16 nEndPara = ::std::max( aSelect.nStartPara, aSelect.nEndPara );
1892 //get level from each paragraph
1893 nLevel = 0;
1894 for( sal_uInt16 nPara = nStartPara; nPara <= nEndPara; nPara++ )
1896 sal_uInt16 nParaDepth = 1 << pTextEditOutliner->GetDepth( nPara );
1897 if( !(nLevel & nParaDepth) )
1898 nLevel += nParaDepth;
1900 //reduce one level for Outliner Object
1901 //if( nLevel > 0 && GetTextEditObject()->GetObjIdentifier() == OBJ_OUTLINETEXT )
1902 // nLevel = nLevel >> 1;
1903 //no bullet paragraph selected
1904 if( nLevel == 0)
1905 nLevel = 0xFFFF;
1908 return nLevel;
1911 bool SdrObjEditView::SupportsFormatPaintbrush( sal_uInt32 nObjectInventor, sal_uInt16 nObjectIdentifier ) const
1913 if( nObjectInventor != SdrInventor && nObjectInventor != E3dInventor )
1914 return false;
1915 switch(nObjectIdentifier)
1917 case OBJ_NONE:
1918 case OBJ_GRUP:
1919 return false;
1920 case OBJ_LINE:
1921 case OBJ_RECT:
1922 case OBJ_CIRC:
1923 case OBJ_SECT:
1924 case OBJ_CARC:
1925 case OBJ_CCUT:
1926 case OBJ_POLY:
1927 case OBJ_PLIN:
1928 case OBJ_PATHLINE:
1929 case OBJ_PATHFILL:
1930 case OBJ_FREELINE:
1931 case OBJ_FREEFILL:
1932 case OBJ_SPLNLINE:
1933 case OBJ_SPLNFILL:
1934 case OBJ_TEXT:
1935 case OBJ_TEXTEXT:
1936 case OBJ_TITLETEXT:
1937 case OBJ_OUTLINETEXT:
1938 case OBJ_GRAF:
1939 case OBJ_OLE2:
1940 case OBJ_TABLE:
1941 return true;
1942 case OBJ_EDGE:
1943 case OBJ_CAPTION:
1944 return false;
1945 case OBJ_PATHPOLY:
1946 case OBJ_PATHPLIN:
1947 return true;
1948 case OBJ_PAGE:
1949 case OBJ_MEASURE:
1950 case OBJ_DUMMY:
1951 case OBJ_FRAME:
1952 case OBJ_UNO:
1953 return false;
1954 case OBJ_CUSTOMSHAPE:
1955 return true;
1956 default:
1957 return false;
1961 static const sal_uInt16* GetFormatRangeImpl( bool bTextOnly )
1963 static const sal_uInt16 gRanges[] = {
1964 SDRATTR_SHADOW_FIRST, SDRATTR_SHADOW_LAST,
1965 SDRATTR_GRAF_FIRST, SDRATTR_GRAF_LAST,
1966 SDRATTR_TABLE_FIRST, SDRATTR_TABLE_LAST,
1967 XATTR_LINE_FIRST, XATTR_LINE_LAST,
1968 XATTR_FILL_FIRST, XATTRSET_FILL,
1969 EE_PARA_START, EE_PARA_END,
1970 EE_CHAR_START, EE_CHAR_END,
1973 return &gRanges[ bTextOnly ? 10 : 0];
1976 bool SdrObjEditView::TakeFormatPaintBrush( boost::shared_ptr< SfxItemSet >& rFormatSet )
1978 if( mxSelectionController.is() && mxSelectionController->TakeFormatPaintBrush(rFormatSet) )
1979 return true;
1981 const SdrMarkList& rMarkList = GetMarkedObjectList();
1982 if( rMarkList.GetMarkCount() >= 1 )
1984 OutlinerView* pOLV = GetTextEditOutlinerView();
1986 rFormatSet.reset( new SfxItemSet( GetModel()->GetItemPool(), GetFormatRangeImpl( pOLV != NULL ) ) );
1987 if( pOLV )
1989 rFormatSet->Put( pOLV->GetAttribs() );
1991 else
1993 const bool bOnlyHardAttr = false;
1994 rFormatSet->Put( GetAttrFromMarked(bOnlyHardAttr) );
1996 return true;
1999 return false;
2002 static SfxItemSet CreatePaintSet( const sal_uInt16 *pRanges, SfxItemPool& rPool, const SfxItemSet& rSourceSet, const SfxItemSet& rTargetSet, bool bNoCharacterFormats, bool bNoParagraphFormats )
2004 SfxItemSet aPaintSet( rPool, pRanges );
2006 while( *pRanges )
2008 sal_uInt16 nWhich = *pRanges++;
2009 const sal_uInt16 nLastWhich = *pRanges++;
2011 if( bNoCharacterFormats && (nWhich == EE_CHAR_START) )
2012 continue;
2014 if( bNoParagraphFormats && (nWhich == EE_PARA_START ) )
2015 continue;
2017 for( ; nWhich < nLastWhich; nWhich++ )
2019 const SfxPoolItem* pSourceItem = rSourceSet.GetItem( nWhich );
2020 const SfxPoolItem* pTargetItem = rTargetSet.GetItem( nWhich );
2022 if( (pSourceItem && !pTargetItem) || (pSourceItem && pTargetItem && !((*pSourceItem) == (*pTargetItem)) ) )
2024 aPaintSet.Put( *pSourceItem );
2028 return aPaintSet;
2031 void SdrObjEditView::ApplyFormatPaintBrushToText( SfxItemSet& rFormatSet, SdrTextObj& rTextObj, SdrText* pText, bool bNoCharacterFormats, bool bNoParagraphFormats )
2033 OutlinerParaObject* pParaObj = pText ? pText->GetOutlinerParaObject() : 0;
2034 if(pParaObj)
2036 SdrOutliner& rOutliner = rTextObj.ImpGetDrawOutliner();
2037 rOutliner.SetText(*pParaObj);
2039 sal_Int32 nParaCount(rOutliner.GetParagraphCount());
2041 if(nParaCount)
2043 for(sal_Int32 nPara = 0; nPara < nParaCount; nPara++)
2045 if( !bNoCharacterFormats )
2046 rOutliner.QuickRemoveCharAttribs( nPara, /* remove all */0 );
2048 SfxItemSet aSet(rOutliner.GetParaAttribs(nPara));
2049 aSet.Put(CreatePaintSet( GetFormatRangeImpl(true), *aSet.GetPool(), rFormatSet, aSet, bNoCharacterFormats, bNoParagraphFormats ) );
2050 rOutliner.SetParaAttribs(nPara, aSet);
2053 OutlinerParaObject* pTemp = rOutliner.CreateParaObject(0, nParaCount);
2054 rOutliner.Clear();
2056 rTextObj.NbcSetOutlinerParaObjectForText(pTemp,pText);
2061 void SdrObjEditView::ApplyFormatPaintBrush( SfxItemSet& rFormatSet, bool bNoCharacterFormats, bool bNoParagraphFormats )
2063 if( !mxSelectionController.is() || !mxSelectionController->ApplyFormatPaintBrush( rFormatSet, bNoCharacterFormats, bNoParagraphFormats ) )
2065 const SdrMarkList& rMarkList = GetMarkedObjectList();
2066 SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj();
2067 OutlinerView* pOLV = GetTextEditOutlinerView();
2069 const SfxItemSet& rShapeSet = pObj->GetMergedItemSet();
2071 if( !pOLV )
2073 // if not in text edit mode (aka the user selected text or clicked on a word)
2074 // apply formatting attributes to selected shape
2075 // All formatting items (see ranges above) that are unequal in selected shape and
2076 // the format paintbrush are hard set on the selected shape.
2078 const sal_uInt16* pRanges = rFormatSet.GetRanges();
2079 bool bTextOnly = true;
2081 while( *pRanges )
2083 if( (*pRanges != EE_PARA_START) && (*pRanges != EE_CHAR_START) )
2085 bTextOnly = false;
2086 break;
2088 pRanges += 2;
2091 if( !bTextOnly )
2093 SfxItemSet aPaintSet( CreatePaintSet( GetFormatRangeImpl(false), *rShapeSet.GetPool(), rFormatSet, rShapeSet, bNoCharacterFormats, bNoParagraphFormats ) );
2094 const bool bReplaceAll = false;
2095 SetAttrToMarked(aPaintSet, bReplaceAll);
2098 // now apply character and paragraph formatting to text, if the shape has any
2099 SdrTextObj* pTextObj = dynamic_cast<SdrTextObj*>(pObj);
2100 if( pTextObj )
2102 sal_Int32 nText = pTextObj->getTextCount();
2104 while( --nText >= 0 )
2106 SdrText* pText = pTextObj->getText( nText );
2107 ApplyFormatPaintBrushToText( rFormatSet, *pTextObj, pText, bNoCharacterFormats, bNoParagraphFormats );
2111 else
2113 ::Outliner* pOutliner = pOLV->GetOutliner();
2114 if( pOutliner )
2116 const EditEngine& rEditEngine = pOutliner->GetEditEngine();
2118 ESelection aSel( pOLV->GetSelection() );
2119 if( !aSel.HasRange() )
2120 pOLV->SetSelection( rEditEngine.GetWord( aSel, com::sun::star::i18n::WordType::DICTIONARY_WORD ) );
2122 const bool bRemoveParaAttribs = !bNoParagraphFormats;
2123 pOLV->RemoveAttribsKeepLanguages( bRemoveParaAttribs );
2124 SfxItemSet aSet( pOLV->GetAttribs() );
2125 SfxItemSet aPaintSet( CreatePaintSet(GetFormatRangeImpl(true), *aSet.GetPool(), rFormatSet, aSet, bNoCharacterFormats, bNoParagraphFormats ) );
2126 pOLV->SetAttribs( aPaintSet );
2132 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */