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 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 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