xref: /aoo42x/main/sc/source/ui/drawfunc/futext3.cxx (revision cdf0e10c)
1*cdf0e10cSrcweir /*************************************************************************
2*cdf0e10cSrcweir  *
3*cdf0e10cSrcweir  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4*cdf0e10cSrcweir  *
5*cdf0e10cSrcweir  * Copyright 2000, 2010 Oracle and/or its affiliates.
6*cdf0e10cSrcweir  *
7*cdf0e10cSrcweir  * OpenOffice.org - a multi-platform office productivity suite
8*cdf0e10cSrcweir  *
9*cdf0e10cSrcweir  * This file is part of OpenOffice.org.
10*cdf0e10cSrcweir  *
11*cdf0e10cSrcweir  * OpenOffice.org is free software: you can redistribute it and/or modify
12*cdf0e10cSrcweir  * it under the terms of the GNU Lesser General Public License version 3
13*cdf0e10cSrcweir  * only, as published by the Free Software Foundation.
14*cdf0e10cSrcweir  *
15*cdf0e10cSrcweir  * OpenOffice.org is distributed in the hope that it will be useful,
16*cdf0e10cSrcweir  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17*cdf0e10cSrcweir  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18*cdf0e10cSrcweir  * GNU Lesser General Public License version 3 for more details
19*cdf0e10cSrcweir  * (a copy is included in the LICENSE file that accompanied this code).
20*cdf0e10cSrcweir  *
21*cdf0e10cSrcweir  * You should have received a copy of the GNU Lesser General Public License
22*cdf0e10cSrcweir  * version 3 along with OpenOffice.org.  If not, see
23*cdf0e10cSrcweir  * <http://www.openoffice.org/license.html>
24*cdf0e10cSrcweir  * for a copy of the LGPLv3 License.
25*cdf0e10cSrcweir  *
26*cdf0e10cSrcweir  ************************************************************************/
27*cdf0e10cSrcweir 
28*cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
29*cdf0e10cSrcweir #include "precompiled_sc.hxx"
30*cdf0e10cSrcweir 
31*cdf0e10cSrcweir #include <editeng/editeng.hxx>
32*cdf0e10cSrcweir #include <editeng/outlobj.hxx>
33*cdf0e10cSrcweir #include <svx/svdocapt.hxx>
34*cdf0e10cSrcweir #include <svx/svdpage.hxx>
35*cdf0e10cSrcweir #include <svx/svdundo.hxx>
36*cdf0e10cSrcweir #include <svx/svdview.hxx>
37*cdf0e10cSrcweir #include <editeng/editobj.hxx>
38*cdf0e10cSrcweir #include <vcl/cursor.hxx>
39*cdf0e10cSrcweir #include <sfx2/objsh.hxx>
40*cdf0e10cSrcweir #include <editeng/writingmodeitem.hxx>
41*cdf0e10cSrcweir 
42*cdf0e10cSrcweir #include "global.hxx"
43*cdf0e10cSrcweir #include "drwlayer.hxx"
44*cdf0e10cSrcweir #include "userdat.hxx"
45*cdf0e10cSrcweir #include "tabvwsh.hxx"			// oder GetDocument irgendwo
46*cdf0e10cSrcweir #include "document.hxx"
47*cdf0e10cSrcweir #include "editutil.hxx"
48*cdf0e10cSrcweir #include "futext.hxx"
49*cdf0e10cSrcweir #include "docsh.hxx"
50*cdf0e10cSrcweir #include "postit.hxx"
51*cdf0e10cSrcweir #include "globstr.hrc"
52*cdf0e10cSrcweir #include "attrib.hxx"
53*cdf0e10cSrcweir #include "scitems.hxx"
54*cdf0e10cSrcweir #include "drawview.hxx"
55*cdf0e10cSrcweir #include "undocell.hxx"
56*cdf0e10cSrcweir 
57*cdf0e10cSrcweir // ------------------------------------------------------------------------------------
58*cdf0e10cSrcweir //	Editieren von Notiz-Legendenobjekten muss immer ueber StopEditMode beendet werden,
59*cdf0e10cSrcweir //	damit die Aenderungen ins Dokument uebernommen werden!
60*cdf0e10cSrcweir //	(Fontwork-Execute in drawsh und drtxtob passiert nicht fuer Legendenobjekte)
61*cdf0e10cSrcweir //	bTextDirection=sal_True means that this function is called from SID_TEXTDIRECTION_XXX(drtxtob.cxx).
62*cdf0e10cSrcweir // ------------------------------------------------------------------------------------
63*cdf0e10cSrcweir 
64*cdf0e10cSrcweir void FuText::StopEditMode(sal_Bool /*bTextDirection*/)
65*cdf0e10cSrcweir {
66*cdf0e10cSrcweir     SdrObject* pObject = pView->GetTextEditObject();
67*cdf0e10cSrcweir     if( !pObject ) return;
68*cdf0e10cSrcweir 
69*cdf0e10cSrcweir     // relock the internal layer that has been unlocked in FuText::SetInEditMode()
70*cdf0e10cSrcweir 	if ( pObject->GetLayer() == SC_LAYER_INTERN )
71*cdf0e10cSrcweir         pView->LockInternalLayer();
72*cdf0e10cSrcweir 
73*cdf0e10cSrcweir     ScViewData& rViewData = *pViewShell->GetViewData();
74*cdf0e10cSrcweir     ScDocument& rDoc = *rViewData.GetDocument();
75*cdf0e10cSrcweir     ScDrawLayer* pDrawLayer = rDoc.GetDrawLayer();
76*cdf0e10cSrcweir     DBG_ASSERT( pDrawLayer && (pDrawLayer == pDrDoc), "FuText::StopEditMode - missing or different drawing layers" );
77*cdf0e10cSrcweir 
78*cdf0e10cSrcweir     ScAddress aNotePos;
79*cdf0e10cSrcweir     ScPostIt* pNote = 0;
80*cdf0e10cSrcweir     if( const ScDrawObjData* pCaptData = ScDrawLayer::GetNoteCaptionData( pObject, rViewData.GetTabNo() ) )
81*cdf0e10cSrcweir     {
82*cdf0e10cSrcweir         aNotePos = pCaptData->maStart;
83*cdf0e10cSrcweir         pNote = rDoc.GetNote( aNotePos );
84*cdf0e10cSrcweir         DBG_ASSERT( pNote && (pNote->GetCaption() == pObject), "FuText::StopEditMode - missing or invalid cell note" );
85*cdf0e10cSrcweir     }
86*cdf0e10cSrcweir 
87*cdf0e10cSrcweir     ScDocShell* pDocShell = rViewData.GetDocShell();
88*cdf0e10cSrcweir     ::svl::IUndoManager* pUndoMgr = rDoc.IsUndoEnabled() ? pDocShell->GetUndoManager() : 0;
89*cdf0e10cSrcweir     bool bNewNote = false;
90*cdf0e10cSrcweir     if( pNote && pUndoMgr )
91*cdf0e10cSrcweir     {
92*cdf0e10cSrcweir         /*  Put all undo actions already collected (e.g. create caption object)
93*cdf0e10cSrcweir             and all following undo actions (text changed) together into a ListAction. */
94*cdf0e10cSrcweir         String aUndoStr = ScGlobal::GetRscString( STR_UNDO_EDITNOTE );
95*cdf0e10cSrcweir         pUndoMgr->EnterListAction( aUndoStr, aUndoStr );
96*cdf0e10cSrcweir         if( SdrUndoGroup* pCalcUndo = pDrawLayer->GetCalcUndo() )
97*cdf0e10cSrcweir         {
98*cdf0e10cSrcweir             /*  Note has been created before editing, if first undo action is
99*cdf0e10cSrcweir                 an insert action. Needed below to decide whether to drop the
100*cdf0e10cSrcweir                 undo if editing a new note has been cancelled. */
101*cdf0e10cSrcweir             bNewNote = (pCalcUndo->GetActionCount() > 0) && pCalcUndo->GetAction( 0 )->ISA( SdrUndoNewObj );
102*cdf0e10cSrcweir             // create a "insert note" undo action if needed
103*cdf0e10cSrcweir             if( bNewNote )
104*cdf0e10cSrcweir                 pUndoMgr->AddUndoAction( new ScUndoReplaceNote( *pDocShell, aNotePos, pNote->GetNoteData(), true, pCalcUndo ) );
105*cdf0e10cSrcweir             else
106*cdf0e10cSrcweir                 pUndoMgr->AddUndoAction( pCalcUndo );
107*cdf0e10cSrcweir         }
108*cdf0e10cSrcweir     }
109*cdf0e10cSrcweir 
110*cdf0e10cSrcweir     if( pNote )
111*cdf0e10cSrcweir         rDoc.LockStreamValid(true);     // only the affected sheet is invalidated below
112*cdf0e10cSrcweir 
113*cdf0e10cSrcweir     /*  SdrObjEditView::SdrEndTextEdit() may try to delete the entire drawing
114*cdf0e10cSrcweir         object, if it does not contain text and has invisible border and fill.
115*cdf0e10cSrcweir         This must not happen for note caption objects. They will be removed
116*cdf0e10cSrcweir         below together with the cell note if the text is empty (independent of
117*cdf0e10cSrcweir         border and area formatting). It is possible to prevent automatic
118*cdf0e10cSrcweir         deletion by passing sal_True to this function. The return value changes
119*cdf0e10cSrcweir         from SDRENDTEXTEDIT_DELETED to SDRENDTEXTEDIT_SHOULDBEDELETED in this
120*cdf0e10cSrcweir         case. */
121*cdf0e10cSrcweir     /*SdrEndTextEditKind eResult =*/ pView->SdrEndTextEdit( pNote != 0 );
122*cdf0e10cSrcweir 
123*cdf0e10cSrcweir     // or ScEndTextEdit (with drawview.hxx)
124*cdf0e10cSrcweir     pViewShell->SetDrawTextUndo( 0 );
125*cdf0e10cSrcweir 
126*cdf0e10cSrcweir     Cursor* pCur = pWindow->GetCursor();
127*cdf0e10cSrcweir     if( pCur && pCur->IsVisible() )
128*cdf0e10cSrcweir         pCur->Hide();
129*cdf0e10cSrcweir 
130*cdf0e10cSrcweir     if( pNote )
131*cdf0e10cSrcweir     {
132*cdf0e10cSrcweir         // hide the caption object if it is in hidden state
133*cdf0e10cSrcweir         pNote->ShowCaptionTemp( aNotePos, false );
134*cdf0e10cSrcweir 
135*cdf0e10cSrcweir         // update author and date
136*cdf0e10cSrcweir         pNote->AutoStamp();
137*cdf0e10cSrcweir 
138*cdf0e10cSrcweir         /*  If the entire text has been cleared, the cell note and its caption
139*cdf0e10cSrcweir             object have to be removed. */
140*cdf0e10cSrcweir         SdrTextObj* pTextObject = dynamic_cast< SdrTextObj* >( pObject );
141*cdf0e10cSrcweir         bool bDeleteNote = !pTextObject || !pTextObject->HasText();
142*cdf0e10cSrcweir         if( bDeleteNote )
143*cdf0e10cSrcweir         {
144*cdf0e10cSrcweir             if( pUndoMgr )
145*cdf0e10cSrcweir             {
146*cdf0e10cSrcweir                 // collect the "remove object" drawing undo action created by DeleteNote()
147*cdf0e10cSrcweir                 pDrawLayer->BeginCalcUndo();
148*cdf0e10cSrcweir                 // rescue note data before deletion
149*cdf0e10cSrcweir                 ScNoteData aNoteData( pNote->GetNoteData() );
150*cdf0e10cSrcweir                 // delete note from document (removes caption, but does not delete it)
151*cdf0e10cSrcweir                 rDoc.DeleteNote( aNotePos );
152*cdf0e10cSrcweir                 // create undo action for removed note
153*cdf0e10cSrcweir                 pUndoMgr->AddUndoAction( new ScUndoReplaceNote( *pDocShell, aNotePos, aNoteData, false, pDrawLayer->GetCalcUndo() ) );
154*cdf0e10cSrcweir             }
155*cdf0e10cSrcweir             else
156*cdf0e10cSrcweir             {
157*cdf0e10cSrcweir                 rDoc.DeleteNote( aNotePos );
158*cdf0e10cSrcweir             }
159*cdf0e10cSrcweir             // ScDocument::DeleteNote has deleted the note that pNote points to
160*cdf0e10cSrcweir             pNote = 0;
161*cdf0e10cSrcweir         }
162*cdf0e10cSrcweir 
163*cdf0e10cSrcweir         // finalize the undo list action
164*cdf0e10cSrcweir         if( pUndoMgr )
165*cdf0e10cSrcweir         {
166*cdf0e10cSrcweir             pUndoMgr->LeaveListAction();
167*cdf0e10cSrcweir 
168*cdf0e10cSrcweir             /*  #i94039# Update the default name "Edit Note" of the undo action
169*cdf0e10cSrcweir                 if the note has been created before editing or is deleted due
170*cdf0e10cSrcweir                 to deleted text. If the note has been created *and* is deleted,
171*cdf0e10cSrcweir                 the last undo action can be removed completely. Note: The
172*cdf0e10cSrcweir                 function LeaveListAction() removes the last action by itself,
173*cdf0e10cSrcweir                 if it is empty (when result is SDRENDTEXTEDIT_UNCHANGED). */
174*cdf0e10cSrcweir             if( bNewNote && bDeleteNote )
175*cdf0e10cSrcweir             {
176*cdf0e10cSrcweir                 pUndoMgr->RemoveLastUndoAction();
177*cdf0e10cSrcweir             }
178*cdf0e10cSrcweir             else if( bNewNote || bDeleteNote )
179*cdf0e10cSrcweir             {
180*cdf0e10cSrcweir                 SfxListUndoAction* pAction = dynamic_cast< SfxListUndoAction* >( pUndoMgr->GetUndoAction() );
181*cdf0e10cSrcweir                 DBG_ASSERT( pAction, "FuText::StopEditMode - list undo action expected" );
182*cdf0e10cSrcweir                 if( pAction )
183*cdf0e10cSrcweir                     pAction->SetComment( ScGlobal::GetRscString( bNewNote ? STR_UNDO_INSERTNOTE : STR_UNDO_DELETENOTE ) );
184*cdf0e10cSrcweir             }
185*cdf0e10cSrcweir         }
186*cdf0e10cSrcweir 
187*cdf0e10cSrcweir         // invalidate stream positions only for the affected sheet
188*cdf0e10cSrcweir         rDoc.LockStreamValid(false);
189*cdf0e10cSrcweir         if (rDoc.IsStreamValid(aNotePos.Tab()))
190*cdf0e10cSrcweir             rDoc.SetStreamValid(aNotePos.Tab(), sal_False);
191*cdf0e10cSrcweir     }
192*cdf0e10cSrcweir }
193*cdf0e10cSrcweir 
194*cdf0e10cSrcweir // Called following an EndDragObj() to update the new note rectangle position
195*cdf0e10cSrcweir void FuText::StopDragMode(SdrObject* /*pObject*/)
196*cdf0e10cSrcweir {
197*cdf0e10cSrcweir #if 0 // DR
198*cdf0e10cSrcweir     ScViewData& rViewData = *pViewShell->GetViewData();
199*cdf0e10cSrcweir     if( ScDrawObjData* pData = ScDrawLayer::GetNoteCaptionData( pObject, rViewData.GetTabNo() ) )
200*cdf0e10cSrcweir     {
201*cdf0e10cSrcweir         ScDocument& rDoc = *rViewData.GetDocument();
202*cdf0e10cSrcweir         const ScAddress& rPos = pData->maStart;
203*cdf0e10cSrcweir         ScPostIt* pNote = rDoc.GetNote( rPos );
204*cdf0e10cSrcweir         DBG_ASSERT( pNote && (pNote->GetCaption() == pObject), "FuText::StopDragMode - missing or invalid cell note" );
205*cdf0e10cSrcweir         if( pNote )
206*cdf0e10cSrcweir         {
207*cdf0e10cSrcweir             Rectangle aOldRect = pNote->CalcRectangle( rDoc, rPos );
208*cdf0e10cSrcweir             Rectangle aNewRect = pObject->GetLogicRect();
209*cdf0e10cSrcweir             if( aOldRect != aNewRect )
210*cdf0e10cSrcweir             {
211*cdf0e10cSrcweir                 pNote->UpdateFromRectangle( rDoc, rPos, aNewRect );
212*cdf0e10cSrcweir                 OutlinerParaObject* pPObj = pCaption->GetOutlinerParaObject();
213*cdf0e10cSrcweir                 bool bVertical = (pPObj && pPObj->IsVertical());
214*cdf0e10cSrcweir                 // The new height/width is honoured if property item is reset.
215*cdf0e10cSrcweir                 if(!bVertical && aNewRect.Bottom() - aNewRect.Top() > aOldRect.Bottom() - aOldRect.Top())
216*cdf0e10cSrcweir                 {
217*cdf0e10cSrcweir                     if(pCaption->IsAutoGrowHeight() && !bVertical)
218*cdf0e10cSrcweir                     {
219*cdf0e10cSrcweir                         pCaption->SetMergedItem( SdrTextAutoGrowHeightItem( false ) );
220*cdf0e10cSrcweir                         aNote.SetItemSet( *pDoc, pCaption->GetMergedItemSet() );
221*cdf0e10cSrcweir                     }
222*cdf0e10cSrcweir                 }
223*cdf0e10cSrcweir                 else if(bVertical && aNewRect.Right() - aNewRect.Left() > aOldRect.Right() - aOldRect.Left())
224*cdf0e10cSrcweir                 {
225*cdf0e10cSrcweir                     if(pCaption->IsAutoGrowWidth() && bVertical)
226*cdf0e10cSrcweir                     {
227*cdf0e10cSrcweir                         pCaption->SetMergedItem( SdrTextAutoGrowWidthItem( false ) );
228*cdf0e10cSrcweir                         aNote.SetItemSet( *pDoc, pCaption->GetMergedItemSet() );
229*cdf0e10cSrcweir                     }
230*cdf0e10cSrcweir                 }
231*cdf0e10cSrcweir                 pViewShell->SetNote( aTabPos.Col(), aTabPos.Row(), aTabPos.Tab(), aNote );
232*cdf0e10cSrcweir 
233*cdf0e10cSrcweir                 // This repaint should not be necessary but it cleans
234*cdf0e10cSrcweir                 // up the 'marks' left behind  by the note handles
235*cdf0e10cSrcweir                 // now that notes can simultaineously have handles and edit active.
236*cdf0e10cSrcweir                 ScRange aDrawRange = rDoc.GetRange( rPos.Tab(), aOldRect );
237*cdf0e10cSrcweir                 // Set Start/End Row to previous/next row to allow for handles.
238*cdf0e10cSrcweir                 if( aDrawRange.aStart.Row() > 0 )
239*cdf0e10cSrcweir                     aDrawRange.aStart.IncRow( -1 );
240*cdf0e10cSrcweir                 if( aDrawRange.aEnd.Row() < MAXROW )
241*cdf0e10cSrcweir                     aDrawRange.aEnd.IncRow( 1 );
242*cdf0e10cSrcweir                 ScDocShell* pDocSh = rViewData.GetDocShell();
243*cdf0e10cSrcweir                 pDocSh->PostPaint( aDrawRange, PAINT_GRID| PAINT_EXTRAS);
244*cdf0e10cSrcweir             }
245*cdf0e10cSrcweir         }
246*cdf0e10cSrcweir     }
247*cdf0e10cSrcweir #endif
248*cdf0e10cSrcweir }
249*cdf0e10cSrcweir 
250