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