1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_sc.hxx" 30 31 #include <editeng/editeng.hxx> 32 #include <editeng/outlobj.hxx> 33 #include <svx/svdocapt.hxx> 34 #include <svx/svdpage.hxx> 35 #include <svx/svdundo.hxx> 36 #include <svx/svdview.hxx> 37 #include <editeng/editobj.hxx> 38 #include <vcl/cursor.hxx> 39 #include <sfx2/objsh.hxx> 40 #include <editeng/writingmodeitem.hxx> 41 42 #include "global.hxx" 43 #include "drwlayer.hxx" 44 #include "userdat.hxx" 45 #include "tabvwsh.hxx" // oder GetDocument irgendwo 46 #include "document.hxx" 47 #include "editutil.hxx" 48 #include "futext.hxx" 49 #include "docsh.hxx" 50 #include "postit.hxx" 51 #include "globstr.hrc" 52 #include "attrib.hxx" 53 #include "scitems.hxx" 54 #include "drawview.hxx" 55 #include "undocell.hxx" 56 57 // ------------------------------------------------------------------------------------ 58 // Editieren von Notiz-Legendenobjekten muss immer ueber StopEditMode beendet werden, 59 // damit die Aenderungen ins Dokument uebernommen werden! 60 // (Fontwork-Execute in drawsh und drtxtob passiert nicht fuer Legendenobjekte) 61 // bTextDirection=sal_True means that this function is called from SID_TEXTDIRECTION_XXX(drtxtob.cxx). 62 // ------------------------------------------------------------------------------------ 63 64 void FuText::StopEditMode(sal_Bool /*bTextDirection*/) 65 { 66 SdrObject* pObject = pView->GetTextEditObject(); 67 if( !pObject ) return; 68 69 // relock the internal layer that has been unlocked in FuText::SetInEditMode() 70 if ( pObject->GetLayer() == SC_LAYER_INTERN ) 71 pView->LockInternalLayer(); 72 73 ScViewData& rViewData = *pViewShell->GetViewData(); 74 ScDocument& rDoc = *rViewData.GetDocument(); 75 ScDrawLayer* pDrawLayer = rDoc.GetDrawLayer(); 76 DBG_ASSERT( pDrawLayer && (pDrawLayer == pDrDoc), "FuText::StopEditMode - missing or different drawing layers" ); 77 78 ScAddress aNotePos; 79 ScPostIt* pNote = 0; 80 if( const ScDrawObjData* pCaptData = ScDrawLayer::GetNoteCaptionData( pObject, rViewData.GetTabNo() ) ) 81 { 82 aNotePos = pCaptData->maStart; 83 pNote = rDoc.GetNote( aNotePos ); 84 DBG_ASSERT( pNote && (pNote->GetCaption() == pObject), "FuText::StopEditMode - missing or invalid cell note" ); 85 } 86 87 ScDocShell* pDocShell = rViewData.GetDocShell(); 88 ::svl::IUndoManager* pUndoMgr = rDoc.IsUndoEnabled() ? pDocShell->GetUndoManager() : 0; 89 bool bNewNote = false; 90 if( pNote && pUndoMgr ) 91 { 92 /* Put all undo actions already collected (e.g. create caption object) 93 and all following undo actions (text changed) together into a ListAction. */ 94 String aUndoStr = ScGlobal::GetRscString( STR_UNDO_EDITNOTE ); 95 pUndoMgr->EnterListAction( aUndoStr, aUndoStr ); 96 if( SdrUndoGroup* pCalcUndo = pDrawLayer->GetCalcUndo() ) 97 { 98 /* Note has been created before editing, if first undo action is 99 an insert action. Needed below to decide whether to drop the 100 undo if editing a new note has been cancelled. */ 101 bNewNote = (pCalcUndo->GetActionCount() > 0) && pCalcUndo->GetAction( 0 )->ISA( SdrUndoNewObj ); 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(); 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