1 /************************************************************************* * 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2008 by Sun Microsystems, Inc. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * $RCSfile: $ 10 * $Revision: $ 11 * 12 * This file is part of OpenOffice.org. 13 * 14 * OpenOffice.org is free software: you can redistribute it and/or modify 15 * it under the terms of the GNU Lesser General Public License version 3 16 * only, as published by the Free Software Foundation. 17 * 18 * OpenOffice.org is distributed in the hope that it will be useful, 19 * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 * GNU Lesser General Public License version 3 for more details 22 * (a copy is included in the LICENSE file that accompanied this code). 23 * 24 * You should have received a copy of the GNU Lesser General Public License 25 * version 3 along with OpenOffice.org. If not, see 26 * <http://www.openoffice.org/license.html> 27 * for a copy of the LGPLv3 License. 28 * 29 ************************************************************************/ 30 31 #include "precompiled_sw.hxx" 32 33 #include <AnnotationWin.hxx> 34 35 #include <AnnotationMenuButton.hxx> 36 #include <PostItMgr.hxx> 37 38 #include <annotation.hrc> 39 #include <popup.hrc> 40 #include <cmdid.h> 41 42 #include <vcl/menu.hxx> 43 44 #include <svl/undo.hxx> 45 #include <unotools/syslocale.hxx> 46 #include <svl/languageoptions.hxx> 47 48 #include <editeng/postitem.hxx> 49 #include <editeng/fhgtitem.hxx> 50 #include <editeng/langitem.hxx> 51 52 #include <editeng/editview.hxx> 53 #include <editeng/outliner.hxx> 54 #include <editeng/editeng.hxx> 55 #include <editeng/editobj.hxx> 56 57 #include <docufld.hxx> // SwPostItField 58 #include <txtfld.hxx> 59 #include <ndtxt.hxx> 60 #include <view.hxx> 61 #include <wrtsh.hxx> 62 #include <docsh.hxx> 63 #include <doc.hxx> 64 #include <IDocumentUndoRedo.hxx> 65 #include <SwUndoField.hxx> 66 67 68 namespace sw { namespace annotation { 69 70 SwAnnotationWin::SwAnnotationWin( SwEditWin& rEditWin, 71 WinBits nBits, 72 SwPostItMgr& aMgr, 73 SwPostItBits aBits, 74 SwSidebarItem& rSidebarItem, 75 SwFmtFld* aField ) 76 : SwSidebarWin( rEditWin, nBits, aMgr, aBits, rSidebarItem ) 77 , mpFmtFld(aField) 78 , mpFld( static_cast<SwPostItField*>(aField->GetFld())) 79 , mpButtonPopup(0) 80 { 81 } 82 83 SwAnnotationWin::~SwAnnotationWin() 84 { 85 delete mpButtonPopup; 86 } 87 88 void SwAnnotationWin::SetPostItText() 89 { 90 // get text from SwPostItField and insert into our textview 91 Engine()->SetModifyHdl( Link() ); 92 Engine()->EnableUndo( sal_False ); 93 mpFld = static_cast<SwPostItField*>(mpFmtFld->GetFld()); 94 if( mpFld->GetTextObject() ) 95 Engine()->SetText( *mpFld->GetTextObject() ); 96 else 97 { 98 Engine()->Clear(); 99 GetOutlinerView()->SetAttribs(DefaultItem()); 100 GetOutlinerView()->InsertText(mpFld->GetPar2(),false); 101 } 102 103 Engine()->ClearModifyFlag(); 104 Engine()->GetUndoManager().Clear(); 105 Engine()->EnableUndo( sal_True ); 106 Engine()->SetModifyHdl( LINK( this, SwAnnotationWin, ModifyHdl ) ); 107 Invalidate(); 108 } 109 110 void SwAnnotationWin::UpdateData() 111 { 112 if ( Engine()->IsModified() ) 113 { 114 IDocumentUndoRedo & rUndoRedo( 115 DocView().GetDocShell()->GetDoc()->GetIDocumentUndoRedo()); 116 ::std::auto_ptr<SwField> pOldField; 117 if (rUndoRedo.DoesUndo()) 118 { 119 pOldField.reset(mpFld->Copy()); 120 } 121 mpFld->SetPar2(Engine()->GetEditEngine().GetText()); 122 mpFld->SetTextObject(Engine()->CreateParaObject()); 123 if (rUndoRedo.DoesUndo()) 124 { 125 SwTxtFld *const pTxtFld = mpFmtFld->GetTxtFld(); 126 SwPosition aPosition( pTxtFld->GetTxtNode() ); 127 aPosition.nContent = *pTxtFld->GetStart(); 128 rUndoRedo.AppendUndo( 129 new SwUndoFieldFromDoc(aPosition, *pOldField, *mpFld, 0, true)); 130 } 131 // so we get a new layout of notes (anchor position is still the same and we would otherwise not get one) 132 Mgr().SetLayout(); 133 // #i98686# if we have several views, all notes should update their text 134 mpFmtFld->Broadcast(SwFmtFldHint( 0, SWFMTFLD_CHANGED)); 135 DocView().GetDocShell()->SetModified(); 136 } 137 Engine()->ClearModifyFlag(); 138 Engine()->GetUndoManager().Clear(); 139 } 140 141 void SwAnnotationWin::Delete() 142 { 143 SwSidebarWin::Delete(); 144 // we delete the field directly, the Mgr cleans up the PostIt by listening 145 DocView().GetWrtShellPtr()->GotoField(*mpFmtFld); 146 GrabFocusToDocument(); 147 DocView().GetWrtShellPtr()->DelRight(); 148 } 149 150 void SwAnnotationWin::GotoPos() 151 { 152 DocView().GetDocShell()->GetWrtShell()->GotoField(*mpFmtFld); 153 } 154 155 sal_uInt32 SwAnnotationWin::MoveCaret() 156 { 157 // if this is an answer, do not skip over all following ones, but insert directly behind the current one 158 // but when just leaving a note, skip all following ones as well to continue typing 159 return Mgr().IsAnswer() 160 ? 1 161 : 1 + CountFollowing(); 162 } 163 164 //returns true, if there is another note right before this note 165 bool SwAnnotationWin::CalcFollow() 166 { 167 SwTxtFld* pTxtFld = mpFmtFld->GetTxtFld(); 168 SwPosition aPosition( pTxtFld->GetTxtNode() ); 169 aPosition.nContent = *pTxtFld->GetStart(); 170 SwTxtAttr * const pTxtAttr = pTxtFld->GetTxtNode().GetTxtAttrForCharAt( 171 aPosition.nContent.GetIndex() - 1, RES_TXTATR_FIELD ); 172 const SwField* pFld = pTxtAttr ? pTxtAttr->GetFld().GetFld() : 0; 173 return pFld && (pFld->Which()== RES_POSTITFLD); 174 } 175 176 // counts how many SwPostItField we have right after the current one 177 sal_uInt32 SwAnnotationWin::CountFollowing() 178 { 179 sal_uInt32 aCount = 1; // we start with 1, so we have to subtract one at the end again 180 SwTxtFld* pTxtFld = mpFmtFld->GetTxtFld(); 181 SwPosition aPosition( pTxtFld->GetTxtNode() ); 182 aPosition.nContent = *pTxtFld->GetStart(); 183 184 SwTxtAttr * pTxtAttr = pTxtFld->GetTxtNode().GetTxtAttrForCharAt( 185 aPosition.nContent.GetIndex() + 1, 186 RES_TXTATR_FIELD ); 187 SwField* pFld = pTxtAttr 188 ? const_cast<SwField*>(pTxtAttr->GetFld().GetFld()) 189 : 0; 190 while ( pFld && ( pFld->Which()== RES_POSTITFLD ) ) 191 { 192 aCount++; 193 pTxtAttr = pTxtFld->GetTxtNode().GetTxtAttrForCharAt( 194 aPosition.nContent.GetIndex() + aCount, 195 RES_TXTATR_FIELD ); 196 pFld = pTxtAttr 197 ? const_cast<SwField*>(pTxtAttr->GetFld().GetFld()) 198 : 0; 199 } 200 return aCount - 1; 201 } 202 203 MenuButton* SwAnnotationWin::CreateMenuButton() 204 { 205 mpButtonPopup = new PopupMenu(SW_RES(MN_ANNOTATION_BUTTON)); 206 XubString aText = mpButtonPopup->GetItemText( FN_DELETE_NOTE_AUTHOR ); 207 SwRewriter aRewriter; 208 aRewriter.AddRule(UNDO_ARG1,GetAuthor()); 209 aText = aRewriter.Apply(aText); 210 mpButtonPopup->SetItemText(FN_DELETE_NOTE_AUTHOR,aText); 211 MenuButton* pMenuButton = new AnnotationMenuButton( *this ); 212 pMenuButton->SetPopupMenu( mpButtonPopup ); 213 pMenuButton->Show(); 214 return pMenuButton; 215 } 216 217 void SwAnnotationWin::InitAnswer(OutlinerParaObject* pText) 218 { 219 //collect our old meta data 220 SwSidebarWin* pWin = Mgr().GetNextPostIt(KEY_PAGEUP, this); 221 const SvtSysLocale aSysLocale; 222 const LocaleDataWrapper& rLocalData = aSysLocale.GetLocaleData(); 223 String aText = String(SW_RES(STR_REPLY)); 224 SwRewriter aRewriter; 225 aRewriter.AddRule(UNDO_ARG1, pWin->GetAuthor()); 226 aText = aRewriter.Apply(aText); 227 aText.Append(String(rtl::OUString::createFromAscii(" (") + 228 String(rLocalData.getDate( pWin->GetDate())) + rtl::OUString::createFromAscii(", ") + 229 String(rLocalData.getTime( pWin->GetTime(),false)) + rtl::OUString::createFromAscii("): \""))); 230 GetOutlinerView()->InsertText(aText,false); 231 232 // insert old, selected text or "..." 233 // TOOD: iterate over all paragraphs, not only first one to find out if it is empty 234 if (pText->GetTextObject().GetText(0) != String(rtl::OUString::createFromAscii(""))) 235 GetOutlinerView()->GetEditView().InsertText(pText->GetTextObject()); 236 else 237 GetOutlinerView()->InsertText(rtl::OUString::createFromAscii("..."),false); 238 GetOutlinerView()->InsertText(rtl::OUString::createFromAscii("\"\n"),false); 239 240 GetOutlinerView()->SetSelection(ESelection(0x0,0x0,0xFFFF,0xFFFF)); 241 SfxItemSet aAnswerSet( DocView().GetDocShell()->GetPool() ); 242 aAnswerSet.Put(SvxFontHeightItem(200,80,EE_CHAR_FONTHEIGHT)); 243 aAnswerSet.Put(SvxPostureItem(ITALIC_NORMAL,EE_CHAR_ITALIC)); 244 GetOutlinerView()->SetAttribs(aAnswerSet); 245 GetOutlinerView()->SetSelection(ESelection(0xFFFF,0xFFFF,0xFFFF,0xFFFF)); 246 247 //remove all attributes and reset our standard ones 248 GetOutlinerView()->GetEditView().RemoveAttribsKeepLanguages(true); 249 GetOutlinerView()->SetAttribs(DefaultItem()); 250 // lets insert an undo step so the initial text can be easily deleted 251 // but do not use UpdateData() directly, would set modified state again and reentrance into Mgr 252 Engine()->SetModifyHdl( Link() ); 253 IDocumentUndoRedo & rUndoRedo( 254 DocView().GetDocShell()->GetDoc()->GetIDocumentUndoRedo()); 255 ::std::auto_ptr<SwField> pOldField; 256 if (rUndoRedo.DoesUndo()) 257 { 258 pOldField.reset(mpFld->Copy()); 259 } 260 mpFld->SetPar2(Engine()->GetEditEngine().GetText()); 261 mpFld->SetTextObject(Engine()->CreateParaObject()); 262 if (rUndoRedo.DoesUndo()) 263 { 264 SwTxtFld *const pTxtFld = mpFmtFld->GetTxtFld(); 265 SwPosition aPosition( pTxtFld->GetTxtNode() ); 266 aPosition.nContent = *pTxtFld->GetStart(); 267 rUndoRedo.AppendUndo( 268 new SwUndoFieldFromDoc(aPosition, *pOldField, *mpFld, 0, true)); 269 } 270 Engine()->SetModifyHdl( LINK( this, SwAnnotationWin, ModifyHdl ) ); 271 Engine()->ClearModifyFlag(); 272 Engine()->GetUndoManager().Clear(); 273 } 274 275 SvxLanguageItem SwAnnotationWin::GetLanguage(void) 276 { 277 // set initial language for outliner 278 sal_uInt16 nScriptType = SvtLanguageOptions::GetScriptTypeOfLanguage( mpFld->GetLanguage() ); 279 sal_uInt16 nLangWhichId = 0; 280 switch (nScriptType) 281 { 282 case SCRIPTTYPE_LATIN : nLangWhichId = EE_CHAR_LANGUAGE ; break; 283 case SCRIPTTYPE_ASIAN : nLangWhichId = EE_CHAR_LANGUAGE_CJK; break; 284 case SCRIPTTYPE_COMPLEX : nLangWhichId = EE_CHAR_LANGUAGE_CTL; break; 285 default: DBG_ERROR("GetLanguage: wrong script tye"); 286 } 287 return SvxLanguageItem(mpFld->GetLanguage(),nLangWhichId); 288 } 289 290 bool SwAnnotationWin::IsProtected() 291 { 292 return SwSidebarWin::IsProtected() || 293 GetLayoutStatus() == SwPostItHelper::DELETED || 294 ( mpFmtFld ? mpFmtFld->IsProtect() : false ); 295 } 296 297 String SwAnnotationWin::GetAuthor() 298 { 299 return mpFld->GetPar1(); 300 } 301 302 Date SwAnnotationWin::GetDate() 303 { 304 return mpFld->GetDate(); 305 } 306 307 Time SwAnnotationWin::GetTime() 308 { 309 return mpFld->GetTime(); 310 } 311 312 } } // end of namespace sw::annotation 313