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 = 164 pTxtFld->GetTxtNode().GetTxtAttrForCharAt( 165 aPosition.nContent.GetIndex() - 1, 166 RES_TXTATR_ANNOTATION ); 167 const SwField* pFld = pTxtAttr ? pTxtAttr->GetFmtFld().GetField() : 0; 168 return pFld && (pFld->Which()== RES_POSTITFLD); 169 } 170 171 // counts how many SwPostItField we have right after the current one 172 sal_uInt32 SwAnnotationWin::CountFollowing() 173 { 174 sal_uInt32 aCount = 1; // we start with 1, so we have to subtract one at the end again 175 SwTxtFld* pTxtFld = mpFmtFld->GetTxtFld(); 176 SwPosition aPosition( pTxtFld->GetTxtNode() ); 177 aPosition.nContent = *pTxtFld->GetStart(); 178 179 SwTxtAttr * pTxtAttr = pTxtFld->GetTxtNode().GetTxtAttrForCharAt( 180 aPosition.nContent.GetIndex() + 1, 181 RES_TXTATR_ANNOTATION ); 182 SwField* pFld = pTxtAttr 183 ? const_cast<SwField*>(pTxtAttr->GetFmtFld().GetField()) 184 : 0; 185 while ( pFld && ( pFld->Which()== RES_POSTITFLD ) ) 186 { 187 aCount++; 188 pTxtAttr = pTxtFld->GetTxtNode().GetTxtAttrForCharAt( 189 aPosition.nContent.GetIndex() + aCount, 190 RES_TXTATR_ANNOTATION ); 191 pFld = pTxtAttr 192 ? const_cast<SwField*>(pTxtAttr->GetFmtFld().GetField()) 193 : 0; 194 } 195 return aCount - 1; 196 } 197 198 MenuButton* SwAnnotationWin::CreateMenuButton() 199 { 200 mpButtonPopup = new PopupMenu(SW_RES(MN_ANNOTATION_BUTTON)); 201 XubString aText = mpButtonPopup->GetItemText( FN_DELETE_NOTE_AUTHOR ); 202 SwRewriter aRewriter; 203 aRewriter.AddRule(UNDO_ARG1,GetAuthor()); 204 aText = aRewriter.Apply(aText); 205 mpButtonPopup->SetItemText(FN_DELETE_NOTE_AUTHOR,aText); 206 MenuButton* pMenuButton = new AnnotationMenuButton( *this ); 207 pMenuButton->SetPopupMenu( mpButtonPopup ); 208 pMenuButton->Show(); 209 return pMenuButton; 210 } 211 212 void SwAnnotationWin::InitAnswer(OutlinerParaObject* pText) 213 { 214 //collect our old meta data 215 SwSidebarWin* pWin = Mgr().GetNextPostIt(KEY_PAGEUP, this); 216 const SvtSysLocale aSysLocale; 217 const LocaleDataWrapper& rLocalData = aSysLocale.GetLocaleData(); 218 String aText = String(SW_RES(STR_REPLY)); 219 SwRewriter aRewriter; 220 aRewriter.AddRule(UNDO_ARG1, pWin->GetAuthor()); 221 aText = aRewriter.Apply(aText); 222 aText.Append(String(rtl::OUString::createFromAscii(" (") + 223 String(rLocalData.getDate( pWin->GetDate())) + rtl::OUString::createFromAscii(", ") + 224 String(rLocalData.getTime( pWin->GetTime(),false)) + rtl::OUString::createFromAscii("): \""))); 225 GetOutlinerView()->InsertText(aText,false); 226 227 // insert old, selected text or "..." 228 // TOOD: iterate over all paragraphs, not only first one to find out if it is empty 229 if (pText->GetTextObject().GetText(0) != String(rtl::OUString::createFromAscii(""))) 230 GetOutlinerView()->GetEditView().InsertText(pText->GetTextObject()); 231 else 232 GetOutlinerView()->InsertText(rtl::OUString::createFromAscii("..."),false); 233 GetOutlinerView()->InsertText(rtl::OUString::createFromAscii("\"\n"),false); 234 235 GetOutlinerView()->SetSelection(ESelection(0x0,0x0,0xFFFF,0xFFFF)); 236 SfxItemSet aAnswerSet( DocView().GetDocShell()->GetPool() ); 237 aAnswerSet.Put(SvxFontHeightItem(200,80,EE_CHAR_FONTHEIGHT)); 238 aAnswerSet.Put(SvxPostureItem(ITALIC_NORMAL,EE_CHAR_ITALIC)); 239 GetOutlinerView()->SetAttribs(aAnswerSet); 240 GetOutlinerView()->SetSelection(ESelection(0xFFFF,0xFFFF,0xFFFF,0xFFFF)); 241 242 //remove all attributes and reset our standard ones 243 GetOutlinerView()->GetEditView().RemoveAttribsKeepLanguages(true); 244 GetOutlinerView()->SetAttribs(DefaultItem()); 245 // lets insert an undo step so the initial text can be easily deleted 246 // but do not use UpdateData() directly, would set modified state again and reentrance into Mgr 247 Engine()->SetModifyHdl( Link() ); 248 IDocumentUndoRedo & rUndoRedo( 249 DocView().GetDocShell()->GetDoc()->GetIDocumentUndoRedo()); 250 ::std::auto_ptr<SwField> pOldField; 251 if (rUndoRedo.DoesUndo()) 252 { 253 pOldField.reset(mpFld->Copy()); 254 } 255 mpFld->SetPar2(Engine()->GetEditEngine().GetText()); 256 mpFld->SetTextObject(Engine()->CreateParaObject()); 257 if (rUndoRedo.DoesUndo()) 258 { 259 SwTxtFld *const pTxtFld = mpFmtFld->GetTxtFld(); 260 SwPosition aPosition( pTxtFld->GetTxtNode() ); 261 aPosition.nContent = *pTxtFld->GetStart(); 262 rUndoRedo.AppendUndo( 263 new SwUndoFieldFromDoc(aPosition, *pOldField, *mpFld, 0, true)); 264 } 265 Engine()->SetModifyHdl( LINK( this, SwAnnotationWin, ModifyHdl ) ); 266 Engine()->ClearModifyFlag(); 267 Engine()->GetUndoManager().Clear(); 268 } 269 270 SvxLanguageItem SwAnnotationWin::GetLanguage(void) 271 { 272 // set initial language for outliner 273 sal_uInt16 nScriptType = SvtLanguageOptions::GetScriptTypeOfLanguage( mpFld->GetLanguage() ); 274 sal_uInt16 nLangWhichId = 0; 275 switch (nScriptType) 276 { 277 case SCRIPTTYPE_LATIN : nLangWhichId = EE_CHAR_LANGUAGE ; break; 278 case SCRIPTTYPE_ASIAN : nLangWhichId = EE_CHAR_LANGUAGE_CJK; break; 279 case SCRIPTTYPE_COMPLEX : nLangWhichId = EE_CHAR_LANGUAGE_CTL; break; 280 default: DBG_ERROR("GetLanguage: wrong script tye"); 281 } 282 return SvxLanguageItem(mpFld->GetLanguage(),nLangWhichId); 283 } 284 285 bool SwAnnotationWin::IsProtected() 286 { 287 return SwSidebarWin::IsProtected() || 288 GetLayoutStatus() == SwPostItHelper::DELETED || 289 ( mpFmtFld ? mpFmtFld->IsProtect() : false ); 290 } 291 292 String SwAnnotationWin::GetAuthor() 293 { 294 return mpFld->GetPar1(); 295 } 296 297 Date SwAnnotationWin::GetDate() 298 { 299 return mpFld->GetDate(); 300 } 301 302 Time SwAnnotationWin::GetTime() 303 { 304 return mpFld->GetTime(); 305 } 306 307 } } // end of namespace sw::annotation 308