summaryrefslogtreecommitdiff
path: root/sw/source/uibase/docvw/AnnotationWin.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sw/source/uibase/docvw/AnnotationWin.cxx')
-rw-r--r--sw/source/uibase/docvw/AnnotationWin.cxx318
1 files changed, 318 insertions, 0 deletions
diff --git a/sw/source/uibase/docvw/AnnotationWin.cxx b/sw/source/uibase/docvw/AnnotationWin.cxx
new file mode 100644
index 000000000000..9ef1e482bae0
--- /dev/null
+++ b/sw/source/uibase/docvw/AnnotationWin.cxx
@@ -0,0 +1,318 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <AnnotationWin.hxx>
+
+#include <AnnotationMenuButton.hxx>
+#include <PostItMgr.hxx>
+
+#include <annotation.hrc>
+#include <popup.hrc>
+#include <cmdid.h>
+
+#include <vcl/menu.hxx>
+
+#include <svl/undo.hxx>
+#include <unotools/syslocale.hxx>
+#include <svl/languageoptions.hxx>
+
+#include <editeng/postitem.hxx>
+#include <editeng/fhgtitem.hxx>
+#include <editeng/langitem.hxx>
+
+#include <editeng/editview.hxx>
+#include <editeng/outliner.hxx>
+#include <editeng/editeng.hxx>
+#include <editeng/editobj.hxx>
+
+#include <docufld.hxx>
+#include <txtfld.hxx>
+#include <ndtxt.hxx>
+#include <view.hxx>
+#include <wrtsh.hxx>
+#include <docsh.hxx>
+#include <doc.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <SwUndoField.hxx>
+
+#include <boost/scoped_ptr.hpp>
+
+namespace sw { namespace annotation {
+
+SwAnnotationWin::SwAnnotationWin( SwEditWin& rEditWin,
+ WinBits nBits,
+ SwPostItMgr& aMgr,
+ SwPostItBits aBits,
+ SwSidebarItem& rSidebarItem,
+ SwFmtFld* aField )
+ : SwSidebarWin( rEditWin, nBits, aMgr, aBits, rSidebarItem )
+ , mpFmtFld(aField)
+ , mpFld( static_cast<SwPostItField*>(aField->GetField()))
+ , mpButtonPopup(0)
+{
+}
+
+SwAnnotationWin::~SwAnnotationWin()
+{
+ delete mpButtonPopup;
+}
+
+void SwAnnotationWin::SetPostItText()
+{
+ //If the cursor was visible, then make it visible again after
+ //changing text, e.g. fdo#33599
+ Cursor *pCursor = GetOutlinerView()->GetEditView().GetCursor();
+ bool bCursorVisible = pCursor && pCursor->IsVisible();
+
+ //If the new text is the same as the old text, keep the same insertion
+ //point .e.g. fdo#33599
+ mpFld = static_cast<SwPostItField*>(mpFmtFld->GetField());
+ OUString sNewText = mpFld->GetPar2();
+ bool bTextUnchanged = sNewText.equals(Engine()->GetEditEngine().GetText());
+ ESelection aOrigSelection(GetOutlinerView()->GetEditView().GetSelection());
+
+ // get text from SwPostItField and insert into our textview
+ Engine()->SetModifyHdl( Link() );
+ Engine()->EnableUndo( false );
+ if( mpFld->GetTextObject() )
+ Engine()->SetText( *mpFld->GetTextObject() );
+ else
+ {
+ Engine()->Clear();
+ GetOutlinerView()->SetAttribs(DefaultItem());
+ GetOutlinerView()->InsertText(sNewText,false);
+ }
+
+ Engine()->ClearModifyFlag();
+ Engine()->GetUndoManager().Clear();
+ Engine()->EnableUndo( true );
+ Engine()->SetModifyHdl( LINK( this, SwAnnotationWin, ModifyHdl ) );
+ if (bTextUnchanged)
+ GetOutlinerView()->GetEditView().SetSelection(aOrigSelection);
+ if (bCursorVisible)
+ GetOutlinerView()->ShowCursor();
+ Invalidate();
+}
+
+void SwAnnotationWin::UpdateData()
+{
+ if ( Engine()->IsModified() )
+ {
+ IDocumentUndoRedo & rUndoRedo(
+ DocView().GetDocShell()->GetDoc()->GetIDocumentUndoRedo());
+ boost::scoped_ptr<SwField> pOldField;
+ if (rUndoRedo.DoesUndo())
+ {
+ pOldField.reset(mpFld->Copy());
+ }
+ mpFld->SetPar2(Engine()->GetEditEngine().GetText());
+ mpFld->SetTextObject(Engine()->CreateParaObject());
+ if (rUndoRedo.DoesUndo())
+ {
+ SwTxtFld *const pTxtFld = mpFmtFld->GetTxtFld();
+ SwPosition aPosition( pTxtFld->GetTxtNode() );
+ aPosition.nContent = *pTxtFld->GetStart();
+ rUndoRedo.AppendUndo(
+ new SwUndoFieldFromDoc(aPosition, *pOldField, *mpFld, 0, true));
+ }
+ // so we get a new layout of notes (anchor position is still the same and we would otherwise not get one)
+ Mgr().SetLayout();
+ // #i98686# if we have several views, all notes should update their text
+ mpFmtFld->Broadcast(SwFmtFldHint( 0, SWFMTFLD_CHANGED));
+ DocView().GetDocShell()->SetModified();
+ }
+ Engine()->ClearModifyFlag();
+ Engine()->GetUndoManager().Clear();
+}
+
+void SwAnnotationWin::Delete()
+{
+ SwSidebarWin::Delete();
+ // we delete the field directly, the Mgr cleans up the PostIt by listening
+ DocView().GetWrtShellPtr()->GotoField(*mpFmtFld);
+ GrabFocusToDocument();
+ DocView().GetWrtShellPtr()->DelRight();
+}
+
+void SwAnnotationWin::GotoPos()
+{
+ DocView().GetDocShell()->GetWrtShell()->GotoField(*mpFmtFld);
+}
+
+sal_uInt32 SwAnnotationWin::MoveCaret()
+{
+ // if this is an answer, do not skip over all following ones, but insert directly behind the current one
+ // but when just leaving a note, skip all following ones as well to continue typing
+ return Mgr().IsAnswer()
+ ? 1
+ : 1 + CountFollowing();
+}
+
+//returns true, if there is another note right before this note
+bool SwAnnotationWin::CalcFollow()
+{
+ SwTxtFld* pTxtFld = mpFmtFld->GetTxtFld();
+ SwPosition aPosition( pTxtFld->GetTxtNode() );
+ aPosition.nContent = *pTxtFld->GetStart();
+ SwTxtAttr * const pTxtAttr =
+ pTxtFld->GetTxtNode().GetTxtAttrForCharAt(
+ aPosition.nContent.GetIndex() - 1,
+ RES_TXTATR_ANNOTATION );
+ const SwField* pFld = pTxtAttr ? pTxtAttr->GetFmtFld().GetField() : 0;
+ return pFld && (pFld->Which()== RES_POSTITFLD);
+}
+
+// counts how many SwPostItField we have right after the current one
+sal_uInt32 SwAnnotationWin::CountFollowing()
+{
+ sal_uInt32 aCount = 1; // we start with 1, so we have to subtract one at the end again
+ SwTxtFld* pTxtFld = mpFmtFld->GetTxtFld();
+ SwPosition aPosition( pTxtFld->GetTxtNode() );
+ aPosition.nContent = *pTxtFld->GetStart();
+
+ SwTxtAttr * pTxtAttr = pTxtFld->GetTxtNode().GetTxtAttrForCharAt(
+ aPosition.nContent.GetIndex() + 1,
+ RES_TXTATR_ANNOTATION );
+ SwField* pFld = pTxtAttr
+ ? const_cast<SwField*>(pTxtAttr->GetFmtFld().GetField())
+ : 0;
+ while ( pFld && ( pFld->Which()== RES_POSTITFLD ) )
+ {
+ aCount++;
+ pTxtAttr = pTxtFld->GetTxtNode().GetTxtAttrForCharAt(
+ aPosition.nContent.GetIndex() + aCount,
+ RES_TXTATR_ANNOTATION );
+ pFld = pTxtAttr
+ ? const_cast<SwField*>(pTxtAttr->GetFmtFld().GetField())
+ : 0;
+ }
+ return aCount - 1;
+}
+
+MenuButton* SwAnnotationWin::CreateMenuButton()
+{
+ mpButtonPopup = new PopupMenu(SW_RES(MN_ANNOTATION_BUTTON));
+ OUString aText = mpButtonPopup->GetItemText( FN_DELETE_NOTE_AUTHOR );
+ SwRewriter aRewriter;
+ aRewriter.AddRule(UndoArg1,GetAuthor());
+ aText = aRewriter.Apply(aText);
+ mpButtonPopup->SetItemText(FN_DELETE_NOTE_AUTHOR,aText);
+ MenuButton* pMenuButton = new AnnotationMenuButton( *this );
+ pMenuButton->SetPopupMenu( mpButtonPopup );
+ pMenuButton->Show();
+ return pMenuButton;
+}
+
+void SwAnnotationWin::InitAnswer(OutlinerParaObject* pText)
+{
+ //collect our old meta data
+ SwSidebarWin* pWin = Mgr().GetNextPostIt(KEY_PAGEUP, this);
+ const SvtSysLocale aSysLocale;
+ const LocaleDataWrapper& rLocalData = aSysLocale.GetLocaleData();
+ SwRewriter aRewriter;
+ aRewriter.AddRule(UndoArg1, pWin->GetAuthor());
+ const OUString aText = aRewriter.Apply(SW_RESSTR(STR_REPLY))
+ + " (" + rLocalData.getDate( pWin->GetDate())
+ + ", " + rLocalData.getTime( pWin->GetTime(), false)
+ + "): \"";
+ GetOutlinerView()->InsertText(aText,false);
+
+ // insert old, selected text or "..."
+ // TODO: iterate over all paragraphs, not only first one to find out if it is empty
+ if (!pText->GetTextObject().GetText(0).isEmpty())
+ GetOutlinerView()->GetEditView().InsertText(pText->GetTextObject());
+ else
+ GetOutlinerView()->InsertText(OUString("..."),false);
+ GetOutlinerView()->InsertText(OUString("\"\n"),false);
+
+ GetOutlinerView()->SetSelection(ESelection(0,0,EE_PARA_ALL,EE_TEXTPOS_ALL));
+ SfxItemSet aAnswerSet( DocView().GetDocShell()->GetPool() );
+ aAnswerSet.Put(SvxFontHeightItem(200,80,EE_CHAR_FONTHEIGHT));
+ aAnswerSet.Put(SvxPostureItem(ITALIC_NORMAL,EE_CHAR_ITALIC));
+ GetOutlinerView()->SetAttribs(aAnswerSet);
+ GetOutlinerView()->SetSelection(ESelection(EE_PARA_MAX_COUNT,EE_TEXTPOS_MAX_COUNT,EE_PARA_MAX_COUNT,EE_TEXTPOS_MAX_COUNT));
+
+ //remove all attributes and reset our standard ones
+ GetOutlinerView()->GetEditView().RemoveAttribsKeepLanguages(true);
+ GetOutlinerView()->SetAttribs(DefaultItem());
+ // lets insert an undo step so the initial text can be easily deleted
+ // but do not use UpdateData() directly, would set modified state again and reentrance into Mgr
+ Engine()->SetModifyHdl( Link() );
+ IDocumentUndoRedo & rUndoRedo(
+ DocView().GetDocShell()->GetDoc()->GetIDocumentUndoRedo());
+ boost::scoped_ptr<SwField> pOldField;
+ if (rUndoRedo.DoesUndo())
+ {
+ pOldField.reset(mpFld->Copy());
+ }
+ mpFld->SetPar2(Engine()->GetEditEngine().GetText());
+ mpFld->SetTextObject(Engine()->CreateParaObject());
+ if (rUndoRedo.DoesUndo())
+ {
+ SwTxtFld *const pTxtFld = mpFmtFld->GetTxtFld();
+ SwPosition aPosition( pTxtFld->GetTxtNode() );
+ aPosition.nContent = *pTxtFld->GetStart();
+ rUndoRedo.AppendUndo(
+ new SwUndoFieldFromDoc(aPosition, *pOldField, *mpFld, 0, true));
+ }
+ Engine()->SetModifyHdl( LINK( this, SwAnnotationWin, ModifyHdl ) );
+ Engine()->ClearModifyFlag();
+ Engine()->GetUndoManager().Clear();
+}
+
+SvxLanguageItem SwAnnotationWin::GetLanguage(void)
+{
+ // set initial language for outliner
+ sal_uInt16 nScriptType = SvtLanguageOptions::GetScriptTypeOfLanguage( mpFld->GetLanguage() );
+ sal_uInt16 nLangWhichId = 0;
+ switch (nScriptType)
+ {
+ case SCRIPTTYPE_LATIN : nLangWhichId = EE_CHAR_LANGUAGE ; break;
+ case SCRIPTTYPE_ASIAN : nLangWhichId = EE_CHAR_LANGUAGE_CJK; break;
+ case SCRIPTTYPE_COMPLEX : nLangWhichId = EE_CHAR_LANGUAGE_CTL; break;
+ default: OSL_FAIL("GetLanguage: wrong script type");
+ }
+ return SvxLanguageItem(mpFld->GetLanguage(),nLangWhichId);
+}
+
+bool SwAnnotationWin::IsProtected()
+{
+ return SwSidebarWin::IsProtected() ||
+ GetLayoutStatus() == SwPostItHelper::DELETED ||
+ ( mpFmtFld && mpFmtFld->IsProtect() );
+}
+
+OUString SwAnnotationWin::GetAuthor()
+{
+ return mpFld->GetPar1();
+}
+
+Date SwAnnotationWin::GetDate()
+{
+ return mpFld->GetDate();
+}
+
+Time SwAnnotationWin::GetTime()
+{
+ return mpFld->GetTime();
+}
+
+} } // end of namespace sw::annotation
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */