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 String aUndoStr = ScGlobal::GetRscString( STR_UNDO_EDITNOTE ); 91 pUndoMgr->EnterListAction( aUndoStr, aUndoStr ); 92 if( SdrUndoGroup* pCalcUndo = pDrawLayer->GetCalcUndo() ) 93 { 94 /* Note has been created before editing, if first undo action is 95 an insert action. Needed below to decide whether to drop the 96 undo if editing a new note has been cancelled. */ 97 bNewNote = (pCalcUndo->GetActionCount() > 0) && pCalcUndo->GetAction( 0 )->ISA( SdrUndoNewObj ); 98 // create a "insert note" undo action if needed 99 if( bNewNote ) 100 pUndoMgr->AddUndoAction( new ScUndoReplaceNote( *pDocShell, aNotePos, pNote->GetNoteData(), true, pCalcUndo ) ); 101 else 102 pUndoMgr->AddUndoAction( pCalcUndo ); 103 } 104 } 105 106 if( pNote ) 107 rDoc.LockStreamValid(true); // only the affected sheet is invalidated below 108 109 /* SdrObjEditView::SdrEndTextEdit() may try to delete the entire drawing 110 object, if it does not contain text and has invisible border and fill. 111 This must not happen for note caption objects. They will be removed 112 below together with the cell note if the text is empty (independent of 113 border and area formatting). It is possible to prevent automatic 114 deletion by passing sal_True to this function. The return value changes 115 from SDRENDTEXTEDIT_DELETED to SDRENDTEXTEDIT_SHOULDBEDELETED in this 116 case. */ 117 /*SdrEndTextEditKind eResult =*/ pView->SdrEndTextEdit( pNote != 0 ); 118 119 // or ScEndTextEdit (with drawview.hxx) 120 pViewShell->SetDrawTextUndo( 0 ); 121 122 Cursor* pCur = pWindow->GetCursor(); 123 if( pCur && pCur->IsVisible() ) 124 pCur->Hide(); 125 126 if( pNote ) 127 { 128 // hide the caption object if it is in hidden state 129 pNote->ShowCaptionTemp( aNotePos, false ); 130 131 // update author and date 132 pNote->AutoStamp(); 133 134 /* If the entire text has been cleared, the cell note and its caption 135 object have to be removed. */ 136 SdrTextObj* pTextObject = dynamic_cast< SdrTextObj* >( pObject ); 137 bool bDeleteNote = !pTextObject || !pTextObject->HasText(); 138 if( bDeleteNote ) 139 { 140 if( pUndoMgr ) 141 { 142 // collect the "remove object" drawing undo action created by DeleteNote() 143 pDrawLayer->BeginCalcUndo(); 144 // rescue note data before deletion 145 ScNoteData aNoteData( pNote->GetNoteData() ); 146 // delete note from document (removes caption, but does not delete it) 147 rDoc.DeleteNote( aNotePos ); 148 // create undo action for removed note 149 pUndoMgr->AddUndoAction( new ScUndoReplaceNote( *pDocShell, aNotePos, aNoteData, false, pDrawLayer->GetCalcUndo() ) ); 150 } 151 else 152 { 153 rDoc.DeleteNote( aNotePos ); 154 } 155 // ScDocument::DeleteNote has deleted the note that pNote points to 156 pNote = 0; 157 } 158 159 // finalize the undo list action 160 if( pUndoMgr ) 161 { 162 pUndoMgr->LeaveListAction(); 163 164 /* #i94039# Update the default name "Edit Note" of the undo action 165 if the note has been created before editing or is deleted due 166 to deleted text. If the note has been created *and* is deleted, 167 the last undo action can be removed completely. Note: The 168 function LeaveListAction() removes the last action by itself, 169 if it is empty (when result is SDRENDTEXTEDIT_UNCHANGED). */ 170 if( bNewNote && bDeleteNote ) 171 { 172 pUndoMgr->RemoveLastUndoAction(); 173 } 174 else if( bNewNote || bDeleteNote ) 175 { 176 SfxListUndoAction* pAction = dynamic_cast< SfxListUndoAction* >( pUndoMgr->GetUndoAction() ); 177 DBG_ASSERT( pAction, "FuText::StopEditMode - list undo action expected" ); 178 if( pAction ) 179 pAction->SetComment( ScGlobal::GetRscString( bNewNote ? STR_UNDO_INSERTNOTE : STR_UNDO_DELETENOTE ) ); 180 } 181 } 182 183 // invalidate stream positions only for the affected sheet 184 rDoc.LockStreamValid(false); 185 if (rDoc.IsStreamValid(aNotePos.Tab())) 186 rDoc.SetStreamValid(aNotePos.Tab(), sal_False); 187 } 188 } 189 190 // Called following an EndDragObj() to update the new note rectangle position 191 void FuText::StopDragMode(SdrObject* /*pObject*/) 192 { 193 #if 0 // DR 194 ScViewData& rViewData = *pViewShell->GetViewData(); 195 if( ScDrawObjData* pData = ScDrawLayer::GetNoteCaptionData( pObject, rViewData.GetTabNo() ) ) 196 { 197 ScDocument& rDoc = *rViewData.GetDocument(); 198 const ScAddress& rPos = pData->maStart; 199 ScPostIt* pNote = rDoc.GetNote( rPos ); 200 DBG_ASSERT( pNote && (pNote->GetCaption() == pObject), "FuText::StopDragMode - missing or invalid cell note" ); 201 if( pNote ) 202 { 203 Rectangle aOldRect = pNote->CalcRectangle( rDoc, rPos ); 204 Rectangle aNewRect = pObject->GetLogicRect(); 205 if( aOldRect != aNewRect ) 206 { 207 pNote->UpdateFromRectangle( rDoc, rPos, aNewRect ); 208 OutlinerParaObject* pPObj = pCaption->GetOutlinerParaObject(); 209 bool bVertical = (pPObj && pPObj->IsVertical()); 210 // The new height/width is honoured if property item is reset. 211 if(!bVertical && aNewRect.Bottom() - aNewRect.Top() > aOldRect.Bottom() - aOldRect.Top()) 212 { 213 if(pCaption->IsAutoGrowHeight() && !bVertical) 214 { 215 pCaption->SetMergedItem( SdrTextAutoGrowHeightItem( false ) ); 216 aNote.SetItemSet( *pDoc, pCaption->GetMergedItemSet() ); 217 } 218 } 219 else if(bVertical && aNewRect.Right() - aNewRect.Left() > aOldRect.Right() - aOldRect.Left()) 220 { 221 if(pCaption->IsAutoGrowWidth() && bVertical) 222 { 223 pCaption->SetMergedItem( SdrTextAutoGrowWidthItem( false ) ); 224 aNote.SetItemSet( *pDoc, pCaption->GetMergedItemSet() ); 225 } 226 } 227 pViewShell->SetNote( aTabPos.Col(), aTabPos.Row(), aTabPos.Tab(), aNote ); 228 229 // This repaint should not be necessary but it cleans 230 // up the 'marks' left behind by the note handles 231 // now that notes can simultaineously have handles and edit active. 232 ScRange aDrawRange = rDoc.GetRange( rPos.Tab(), aOldRect ); 233 // Set Start/End Row to previous/next row to allow for handles. 234 if( aDrawRange.aStart.Row() > 0 ) 235 aDrawRange.aStart.IncRow( -1 ); 236 if( aDrawRange.aEnd.Row() < MAXROW ) 237 aDrawRange.aEnd.IncRow( 1 ); 238 ScDocShell* pDocSh = rViewData.GetDocShell(); 239 pDocSh->PostPaint( aDrawRange, PAINT_GRID| PAINT_EXTRAS); 240 } 241 } 242 } 243 #endif 244 } 245 246