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