diff options
author | Laurent Godard <lgodard.libre@laposte.net> | 2013-11-08 13:53:23 +0100 |
---|---|---|
committer | Laurent Godard <lgodard.libre@laposte.net> | 2013-11-12 10:27:05 +0100 |
commit | ea2c91a15d9e8374b2c05cc34af12021f1b1c313 (patch) | |
tree | 89643ccdc5a56a76a1e461b5e1e9b90ee9c63b90 | |
parent | 40276b4ceb72f1d070bb1457ed5b403b35ca4deb (diff) |
refactoring annotations import
consume RichText annotation content outside xshape
Change-Id: If427a5dba1c82a91fd5faa0aacee5ce7d04a581c
-rw-r--r-- | sc/Library_sc.mk | 1 | ||||
-rw-r--r-- | sc/source/filter/xml/annotationtextparacontext.cxx | 431 | ||||
-rw-r--r-- | sc/source/filter/xml/annotationtextparacontext.hxx | 160 | ||||
-rw-r--r-- | sc/source/filter/xml/xmlannoi.cxx | 390 | ||||
-rw-r--r-- | sc/source/filter/xml/xmlannoi.hxx | 54 | ||||
-rw-r--r-- | sc/source/filter/xml/xmlcelli.cxx | 22 |
6 files changed, 1040 insertions, 18 deletions
diff --git a/sc/Library_sc.mk b/sc/Library_sc.mk index 3cd88dbb20a7..0fdacc8d6e5d 100644 --- a/sc/Library_sc.mk +++ b/sc/Library_sc.mk @@ -286,6 +286,7 @@ $(eval $(call gb_Library_add_exception_objects,sc,\ sc/source/filter/xml/XMLTrackedChangesContext \ sc/source/filter/xml/cachedattraccess \ sc/source/filter/xml/celltextparacontext \ + sc/source/filter/xml/annotationtextparacontext \ sc/source/filter/xml/editattributemap \ sc/source/filter/xml/importcontext \ sc/source/filter/xml/sheetdata \ diff --git a/sc/source/filter/xml/annotationtextparacontext.cxx b/sc/source/filter/xml/annotationtextparacontext.cxx new file mode 100644 index 000000000000..b4b6fa2af316 --- /dev/null +++ b/sc/source/filter/xml/annotationtextparacontext.cxx @@ -0,0 +1,431 @@ +/* -*- 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/. + */ + +#include "annotationtextparacontext.hxx" +#include "xmlimprt.hxx" +#include "xmlcelli.hxx" +#include "xmlannoi.hxx" + +#include "xmloff/nmspmap.hxx" +#include "comphelper/string.hxx" + +#include <com/sun/star/xml/sax/XAttributeList.hpp> + +using namespace com::sun::star; + +ScXMLAnnotationTextParaContext::ScXMLAnnotationTextParaContext( + ScXMLImport& rImport, sal_uInt16 nPrefix, const OUString& rLName, ScXMLAnnotationContext& rParent) : + ScXMLImportContext(rImport, nPrefix, rLName), + mrParentCxt(rParent) +{ +} + +void ScXMLAnnotationTextParaContext::StartElement(const uno::Reference<xml::sax::XAttributeList>& /*xAttrList*/) +{ +} + +void ScXMLAnnotationTextParaContext::EndElement() +{ + if (!maContent.isEmpty()) + mrParentCxt.PushParagraphSpan(maContent, OUString()); + + mrParentCxt.PushParagraphEnd(); +} + +void ScXMLAnnotationTextParaContext::Characters(const OUString& rChars) +{ + maContent += rChars; +} + +SvXMLImportContext* ScXMLAnnotationTextParaContext::CreateChildContext( + sal_uInt16 nPrefix, const OUString& rLocalName, const uno::Reference<xml::sax::XAttributeList>& /*xAttrList*/) +{ + if (!maContent.isEmpty()) + { + mrParentCxt.PushParagraphSpan(maContent, OUString()); + maContent = OUString(); + } + + const SvXMLTokenMap& rTokenMap = GetScImport().GetCellTextParaElemTokenMap(); + switch (rTokenMap.Get(nPrefix, rLocalName)) + { + case XML_TOK_CELL_TEXT_S: + return new ScXMLAnnotationFieldSContext(GetScImport(), nPrefix, rLocalName, *this); + case XML_TOK_CELL_TEXT_SPAN: + return new ScXMLAnnotationTextSpanContext(GetScImport(), nPrefix, rLocalName, *this); + case XML_TOK_CELL_TEXT_SHEET_NAME: + return new ScXMLAnnotationFieldSheetNameContext(GetScImport(), nPrefix, rLocalName, *this); + case XML_TOK_CELL_TEXT_DATE: + return new ScXMLAnnotationFieldDateContext(GetScImport(), nPrefix, rLocalName, *this); + case XML_TOK_CELL_TEXT_TITLE: + return new ScXMLAnnotationFieldTitleContext(GetScImport(), nPrefix, rLocalName, *this); + case XML_TOK_CELL_TEXT_URL: + return new ScXMLAnnotationFieldURLContext(GetScImport(), nPrefix, rLocalName, *this); + default: + ; + } + + return new SvXMLImportContext(GetImport(), nPrefix, rLocalName); +} + +void ScXMLAnnotationTextParaContext::PushSpan(const OUString& rSpan, const OUString& rStyleName) +{ + mrParentCxt.PushParagraphSpan(rSpan, rStyleName); +} + +void ScXMLAnnotationTextParaContext::PushFieldSheetName(const OUString& rStyleName) +{ + mrParentCxt.PushParagraphFieldSheetName(rStyleName); +} + +void ScXMLAnnotationTextParaContext::PushFieldDate(const OUString& rStyleName) +{ + mrParentCxt.PushParagraphFieldDate(rStyleName); +} + +void ScXMLAnnotationTextParaContext::PushFieldTitle(const OUString& rStyleName) +{ + mrParentCxt.PushParagraphFieldDocTitle(rStyleName); +} + +void ScXMLAnnotationTextParaContext::PushFieldURL( + const OUString& rURL, const OUString& rRep, const OUString& rStyleName) +{ + mrParentCxt.PushParagraphFieldURL(rURL, rRep, rStyleName); +} + +//------------------------------------------------------------------------------- + +ScXMLAnnotationTextSpanContext::ScXMLAnnotationTextSpanContext( + ScXMLImport& rImport, sal_uInt16 nPrefix, const OUString& rLName, ScXMLAnnotationTextParaContext& rParent) : + ScXMLImportContext(rImport, nPrefix, rLName), + mrParentCxt(rParent) +{ +} + +void ScXMLAnnotationTextSpanContext::StartElement(const uno::Reference<xml::sax::XAttributeList>& xAttrList) +{ + if (!xAttrList.is()) + return; + + OUString aLocalName; + sal_Int16 nAttrCount = xAttrList->getLength(); + + const SvXMLTokenMap& rTokenMap = GetScImport().GetCellTextSpanAttrTokenMap(); + for (sal_Int16 i = 0; i < nAttrCount; ++i) + { + sal_uInt16 nAttrPrefix = GetImport().GetNamespaceMap().GetKeyByAttrName( + xAttrList->getNameByIndex(i), &aLocalName); + + const OUString& rAttrValue = xAttrList->getValueByIndex(i); + sal_uInt16 nToken = rTokenMap.Get(nAttrPrefix, aLocalName); + switch (nToken) + { + case XML_TOK_CELL_TEXT_SPAN_ATTR_STYLE_NAME: + maStyleName = rAttrValue; + break; + default: + ; + } + } +} + +void ScXMLAnnotationTextSpanContext::EndElement() +{ + if (!maContent.isEmpty()) + { + mrParentCxt.PushSpan(maContent, maStyleName); + } +} + +void ScXMLAnnotationTextSpanContext::Characters(const OUString& rChars) +{ + maContent += rChars; +} + +SvXMLImportContext* ScXMLAnnotationTextSpanContext::CreateChildContext( + sal_uInt16 nPrefix, const OUString& rLocalName, const uno::Reference<xml::sax::XAttributeList>& /*xAttrList*/) +{ + if (!maContent.isEmpty()) + { + mrParentCxt.PushSpan(maContent, maStyleName); + maContent = OUString(); + } + + const SvXMLTokenMap& rTokenMap = GetScImport().GetCellTextSpanElemTokenMap(); + switch (rTokenMap.Get(nPrefix, rLocalName)) + { + case XML_TOK_CELL_TEXT_SPAN_ELEM_SHEET_NAME: + { + ScXMLAnnotationFieldSheetNameContext* p = new ScXMLAnnotationFieldSheetNameContext(GetScImport(), nPrefix, rLocalName, mrParentCxt); + p->SetStyleName(maStyleName); + return p; + } + case XML_TOK_CELL_TEXT_SPAN_ELEM_DATE: + { + ScXMLAnnotationFieldDateContext* p = new ScXMLAnnotationFieldDateContext(GetScImport(), nPrefix, rLocalName, mrParentCxt); + p->SetStyleName(maStyleName); + return p; + } + case XML_TOK_CELL_TEXT_SPAN_ELEM_TITLE: + { + ScXMLAnnotationFieldTitleContext* p = new ScXMLAnnotationFieldTitleContext(GetScImport(), nPrefix, rLocalName, mrParentCxt); + p->SetStyleName(maStyleName); + return p; + } + case XML_TOK_CELL_TEXT_SPAN_ELEM_URL: + { + ScXMLAnnotationFieldURLContext* p = new ScXMLAnnotationFieldURLContext(GetScImport(), nPrefix, rLocalName, mrParentCxt); + p->SetStyleName(maStyleName); + return p; + } + case XML_TOK_CELL_TEXT_SPAN_ELEM_S: + { + ScXMLAnnotationFieldSContext* p = new ScXMLAnnotationFieldSContext(GetScImport(), nPrefix, rLocalName, mrParentCxt); + p->SetStyleName(maStyleName); + return p; + } + default: + ; + } + + return new SvXMLImportContext(GetImport(), nPrefix, rLocalName); +} + +//------------------------------------------------------------------ + +ScXMLAnnotationFieldSheetNameContext::ScXMLAnnotationFieldSheetNameContext( + ScXMLImport& rImport, sal_uInt16 nPrefix, const OUString& rLName, ScXMLAnnotationTextParaContext& rParent) : + ScXMLImportContext(rImport, nPrefix, rLName), + mrParentCxt(rParent) +{ +} + +void ScXMLAnnotationFieldSheetNameContext::SetStyleName(const OUString& rStyleName) +{ + maStyleName = rStyleName; +} + +void ScXMLAnnotationFieldSheetNameContext::StartElement(const uno::Reference<xml::sax::XAttributeList>& /*xAttrList*/) +{ + // <text:sheet-name> has no attributes (that I'm aware of). +} + +void ScXMLAnnotationFieldSheetNameContext::EndElement() +{ + mrParentCxt.PushFieldSheetName(maStyleName); +} + +void ScXMLAnnotationFieldSheetNameContext::Characters(const OUString& /*rChars*/) +{ +} + +SvXMLImportContext* ScXMLAnnotationFieldSheetNameContext::CreateChildContext( + sal_uInt16 nPrefix, const OUString& rLocalName, const uno::Reference<xml::sax::XAttributeList>& /*xAttrList*/) +{ + return new SvXMLImportContext(GetImport(), nPrefix, rLocalName); +} + +ScXMLAnnotationFieldDateContext::ScXMLAnnotationFieldDateContext( + ScXMLImport& rImport, sal_uInt16 nPrefix, const OUString& rLName, ScXMLAnnotationTextParaContext& rParent) : + ScXMLImportContext(rImport, nPrefix, rLName), + mrParentCxt(rParent) +{ +} + +void ScXMLAnnotationFieldDateContext::SetStyleName(const OUString& rStyleName) +{ + maStyleName = rStyleName; +} + +void ScXMLAnnotationFieldDateContext::StartElement(const uno::Reference<xml::sax::XAttributeList>& /*xAttrList*/) +{ +} + +void ScXMLAnnotationFieldDateContext::EndElement() +{ + mrParentCxt.PushFieldDate(maStyleName); +} + +void ScXMLAnnotationFieldDateContext::Characters(const OUString& /*rChars*/) +{ +} + +SvXMLImportContext* ScXMLAnnotationFieldDateContext::CreateChildContext( + sal_uInt16 nPrefix, const OUString& rLocalName, const uno::Reference<xml::sax::XAttributeList>& /*xAttrList*/) +{ + return new SvXMLImportContext(GetImport(), nPrefix, rLocalName); +} + +ScXMLAnnotationFieldTitleContext::ScXMLAnnotationFieldTitleContext( + ScXMLImport& rImport, sal_uInt16 nPrefix, const OUString& rLName, ScXMLAnnotationTextParaContext& rParent) : + ScXMLImportContext(rImport, nPrefix, rLName), + mrParentCxt(rParent) +{ +} + +void ScXMLAnnotationFieldTitleContext::SetStyleName(const OUString& rStyleName) +{ + maStyleName = rStyleName; +} + +void ScXMLAnnotationFieldTitleContext::StartElement(const uno::Reference<xml::sax::XAttributeList>& /*xAttrList*/) +{ +} + +void ScXMLAnnotationFieldTitleContext::EndElement() +{ + mrParentCxt.PushFieldTitle(maStyleName); +} + +void ScXMLAnnotationFieldTitleContext::Characters(const OUString& /*rChars*/) +{ +} + +SvXMLImportContext* ScXMLAnnotationFieldTitleContext::CreateChildContext( + sal_uInt16 nPrefix, const OUString& rLocalName, const uno::Reference<xml::sax::XAttributeList>& /*xAttrList*/) +{ + return new SvXMLImportContext(GetImport(), nPrefix, rLocalName); +} + +ScXMLAnnotationFieldURLContext::ScXMLAnnotationFieldURLContext( + ScXMLImport& rImport, sal_uInt16 nPrefix, const OUString& rLName, ScXMLAnnotationTextParaContext& rParent) : + ScXMLImportContext(rImport, nPrefix, rLName), + mrParentCxt(rParent) +{ +} + +void ScXMLAnnotationFieldURLContext::SetStyleName(const OUString& rStyleName) +{ + maStyleName = rStyleName; +} + +void ScXMLAnnotationFieldURLContext::StartElement(const uno::Reference<xml::sax::XAttributeList>& xAttrList) +{ + if (!xAttrList.is()) + return; + + OUString aLocalName; + sal_Int16 nAttrCount = xAttrList->getLength(); + + const SvXMLTokenMap& rTokenMap = GetScImport().GetCellTextURLAttrTokenMap(); + for (sal_Int16 i = 0; i < nAttrCount; ++i) + { + sal_uInt16 nAttrPrefix = GetImport().GetNamespaceMap().GetKeyByAttrName( + xAttrList->getNameByIndex(i), &aLocalName); + + const OUString& rAttrValue = xAttrList->getValueByIndex(i); + sal_uInt16 nToken = rTokenMap.Get(nAttrPrefix, aLocalName); + switch (nToken) + { + case XML_TOK_CELL_TEXT_URL_ATTR_UREF: + maURL = rAttrValue; + break; + case XML_TOK_CELL_TEXT_URL_ATTR_TYPE: + // Ignored for now. + break; + default: + ; + } + } +} + +void ScXMLAnnotationFieldURLContext::EndElement() +{ + mrParentCxt.PushFieldURL(maURL, maRep, maStyleName); +} + +void ScXMLAnnotationFieldURLContext::Characters(const OUString& rChars) +{ + maRep += rChars; +} + +SvXMLImportContext* ScXMLAnnotationFieldURLContext::CreateChildContext( + sal_uInt16 nPrefix, const OUString& rLocalName, const uno::Reference<xml::sax::XAttributeList>& /*xAttrList*/) +{ + return new SvXMLImportContext(GetImport(), nPrefix, rLocalName); +} + +ScXMLAnnotationFieldSContext::ScXMLAnnotationFieldSContext( + ScXMLImport& rImport, sal_uInt16 nPrefix, const OUString& rLName, ScXMLAnnotationTextParaContext& rParent) : + ScXMLImportContext(rImport, nPrefix, rLName), + mrParentCxt(rParent), + mnCount(1) +{ +} + +void ScXMLAnnotationFieldSContext::SetStyleName(const OUString& rStyleName) +{ + maStyleName = rStyleName; +} + +void ScXMLAnnotationFieldSContext::StartElement(const uno::Reference<xml::sax::XAttributeList>& xAttrList) +{ + if (!xAttrList.is()) + return; + + OUString aLocalName; + sal_Int16 nAttrCount = xAttrList->getLength(); + + const SvXMLTokenMap& rTokenMap = GetScImport().GetCellTextSAttrTokenMap(); + for (sal_Int16 i = 0; i < nAttrCount; ++i) + { + sal_uInt16 nAttrPrefix = GetImport().GetNamespaceMap().GetKeyByAttrName( + xAttrList->getNameByIndex(i), &aLocalName); + + const OUString& rAttrValue = xAttrList->getValueByIndex(i); + sal_uInt16 nToken = rTokenMap.Get(nAttrPrefix, aLocalName); + switch (nToken) + { + case XML_TOK_CELL_TEXT_S_ATTR_C: + mnCount = rAttrValue.toInt32(); + if (mnCount <= 0) + mnCount = 1; // worth a warning? + break; + default: + ; + } + } +} + +void ScXMLAnnotationFieldSContext::EndElement() +{ + if (mnCount) + PushSpaces(); +} + +SvXMLImportContext* ScXMLAnnotationFieldSContext::CreateChildContext( + sal_uInt16 nPrefix, const OUString& rLocalName, const uno::Reference<xml::sax::XAttributeList>& /*xAttrList*/) +{ + // <text:s> does not have child elements, but ... + if (mnCount) + { + PushSpaces(); + mnCount = 0; + } + + return new SvXMLImportContext(GetImport(), nPrefix, rLocalName); +} + +void ScXMLAnnotationFieldSContext::PushSpaces() +{ + if (mnCount > 0) + { + if (mnCount == 1) + mrParentCxt.PushSpan(" ", maStyleName); + else + { + OUStringBuffer aBuf( mnCount); + comphelper::string::padToLength( aBuf, mnCount, ' '); + mrParentCxt.PushSpan( aBuf.makeStringAndClear(), maStyleName); + } + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/filter/xml/annotationtextparacontext.hxx b/sc/source/filter/xml/annotationtextparacontext.hxx new file mode 100644 index 000000000000..5071f0e66a9b --- /dev/null +++ b/sc/source/filter/xml/annotationtextparacontext.hxx @@ -0,0 +1,160 @@ +/* -*- 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/. + */ + +#ifndef __SC_XML_ANNOTATIONTEXTPARACONTEXT_HXX__ +#define __SC_XML_ANNOTATIONTEXTPARACONTEXT_HXX__ + +#include "importcontext.hxx" + +class ScXMLImport; +class ScXMLAnnotationContext; + +/** + * This context handles <text:p> element inside <office:annotation>. + */ +class ScXMLAnnotationTextParaContext : public ScXMLImportContext +{ + ScXMLAnnotationContext& mrParentCxt; + OUString maContent; +public: + ScXMLAnnotationTextParaContext(ScXMLImport& rImport, sal_uInt16 nPrefix, const OUString& rLName, ScXMLAnnotationContext& rParent); + + virtual void StartElement(const com::sun::star::uno::Reference<com::sun::star::xml::sax::XAttributeList>& xAttrList); + virtual void EndElement(); + virtual void Characters(const OUString& rChars); + virtual SvXMLImportContext* CreateChildContext( + sal_uInt16 nPrefix, const OUString& rLocalName, const com::sun::star::uno::Reference<com::sun::star::xml::sax::XAttributeList>& xAttrList); + + void PushSpan(const OUString& rSpan, const OUString& rStyleName); + void PushFieldSheetName(const OUString& rStyleName); + void PushFieldDate(const OUString& rStyleName); + void PushFieldTitle(const OUString& rStyleName); + void PushFieldURL(const OUString& rURL, const OUString& rRep, const OUString& rStyleName); +}; + +/** + * This context handles <text:span> element inside <text:p>. + */ +class ScXMLAnnotationTextSpanContext : public ScXMLImportContext +{ + ScXMLAnnotationTextParaContext& mrParentCxt; + OUString maStyleName; + OUString maContent; +public: + ScXMLAnnotationTextSpanContext(ScXMLImport& rImport, sal_uInt16 nPrefix, const OUString& rLName, ScXMLAnnotationTextParaContext& rParent); + + virtual void StartElement(const com::sun::star::uno::Reference<com::sun::star::xml::sax::XAttributeList>& xAttrList); + virtual void EndElement(); + virtual void Characters(const OUString& rChars); + virtual SvXMLImportContext* CreateChildContext( + sal_uInt16 nPrefix, const OUString& rLocalName, const com::sun::star::uno::Reference<com::sun::star::xml::sax::XAttributeList>& xAttrList); +}; + +/** + * This context handles <text:sheet-name> element inside <text:p>. + */ +class ScXMLAnnotationFieldSheetNameContext : public ScXMLImportContext +{ + ScXMLAnnotationTextParaContext& mrParentCxt; + OUString maStyleName; +public: + ScXMLAnnotationFieldSheetNameContext(ScXMLImport& rImport, sal_uInt16 nPrefix, const OUString& rLName, ScXMLAnnotationTextParaContext& rParent); + + void SetStyleName(const OUString& rStyleName); + + virtual void StartElement(const com::sun::star::uno::Reference<com::sun::star::xml::sax::XAttributeList>& xAttrList); + virtual void EndElement(); + virtual void Characters(const OUString& rChars); + virtual SvXMLImportContext* CreateChildContext( + sal_uInt16 nPrefix, const OUString& rLocalName, const com::sun::star::uno::Reference<com::sun::star::xml::sax::XAttributeList>& xAttrList); +}; + +/** + * This context handles <text:date> element inside <text:p>. + */ +class ScXMLAnnotationFieldDateContext : public ScXMLImportContext +{ + ScXMLAnnotationTextParaContext& mrParentCxt; + OUString maStyleName; +public: + ScXMLAnnotationFieldDateContext(ScXMLImport& rImport, sal_uInt16 nPrefix, const OUString& rLName, ScXMLAnnotationTextParaContext& rParent); + + void SetStyleName(const OUString& rStyleName); + + virtual void StartElement(const com::sun::star::uno::Reference<com::sun::star::xml::sax::XAttributeList>& xAttrList); + virtual void EndElement(); + virtual void Characters(const OUString& rChars); + virtual SvXMLImportContext* CreateChildContext( + sal_uInt16 nPrefix, const OUString& rLocalName, const com::sun::star::uno::Reference<com::sun::star::xml::sax::XAttributeList>& xAttrList); +}; + +/** + * This context handles <text:title> element inside <text:p>. + */ +class ScXMLAnnotationFieldTitleContext : public ScXMLImportContext +{ + ScXMLAnnotationTextParaContext& mrParentCxt; + OUString maStyleName; +public: + ScXMLAnnotationFieldTitleContext(ScXMLImport& rImport, sal_uInt16 nPrefix, const OUString& rLName, ScXMLAnnotationTextParaContext& rParent); + + void SetStyleName(const OUString& rStyleName); + + virtual void StartElement(const com::sun::star::uno::Reference<com::sun::star::xml::sax::XAttributeList>& xAttrList); + virtual void EndElement(); + virtual void Characters(const OUString& rChars); + virtual SvXMLImportContext* CreateChildContext( + sal_uInt16 nPrefix, const OUString& rLocalName, const com::sun::star::uno::Reference<com::sun::star::xml::sax::XAttributeList>& xAttrList); +}; + +/** + * This context handles <text:a> element inside <text:p> or <text:span>. + */ +class ScXMLAnnotationFieldURLContext : public ScXMLImportContext +{ + ScXMLAnnotationTextParaContext& mrParentCxt; + OUString maStyleName; + OUString maURL; + OUString maRep; +public: + ScXMLAnnotationFieldURLContext(ScXMLImport& rImport, sal_uInt16 nPrefix, const OUString& rLName, ScXMLAnnotationTextParaContext& rParent); + + void SetStyleName(const OUString& rStyleName); + + virtual void StartElement(const com::sun::star::uno::Reference<com::sun::star::xml::sax::XAttributeList>& xAttrList); + virtual void EndElement(); + virtual void Characters(const OUString& rChars); + virtual SvXMLImportContext* CreateChildContext( + sal_uInt16 nPrefix, const OUString& rLocalName, const com::sun::star::uno::Reference<com::sun::star::xml::sax::XAttributeList>& xAttrList); +}; + +/** + * This context handles <text:s> element inside <text:p> or <text:span>. + */ +class ScXMLAnnotationFieldSContext : public ScXMLImportContext +{ + ScXMLAnnotationTextParaContext& mrParentCxt; + OUString maStyleName; + sal_Int32 mnCount; + + void PushSpaces(); +public: + ScXMLAnnotationFieldSContext(ScXMLImport& rImport, sal_uInt16 nPrefix, const OUString& rLName, ScXMLAnnotationTextParaContext& rParent); + + void SetStyleName(const OUString& rStyleName); + + virtual void StartElement(const com::sun::star::uno::Reference<com::sun::star::xml::sax::XAttributeList>& xAttrList); + virtual void EndElement(); + virtual SvXMLImportContext* CreateChildContext( + sal_uInt16 nPrefix, const OUString& rLocalName, const com::sun::star::uno::Reference<com::sun::star::xml::sax::XAttributeList>& xAttrList); +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/filter/xml/xmlannoi.cxx b/sc/source/filter/xml/xmlannoi.cxx index de6eb7003fcd..be284a8009a4 100644 --- a/sc/source/filter/xml/xmlannoi.cxx +++ b/sc/source/filter/xml/xmlannoi.cxx @@ -27,6 +27,33 @@ #include <xmloff/xmlnmspe.hxx> #include <xmloff/xmltoken.hxx> +#include "annotationtextparacontext.hxx" + +#include <editeng/outlobj.hxx> +#include <editeng/editobj.hxx> +#include "editeng/wghtitem.hxx" +#include "editeng/colritem.hxx" +#include "editeng/fhgtitem.hxx" +#include "editeng/postitem.hxx" +#include "editeng/fontitem.hxx" +#include "editeng/udlnitem.hxx" +#include "editeng/wrlmitem.hxx" +#include "editeng/crossedoutitem.hxx" +#include "editeng/charreliefitem.hxx" +#include "editeng/charscaleitem.hxx" +#include "editeng/contouritem.hxx" +#include "editeng/shdditem.hxx" +#include "editeng/kernitem.hxx" +#include "editeng/autokernitem.hxx" +#include "editeng/escapementitem.hxx" +#include "editeng/emphasismarkitem.hxx" +#include "editeng/langitem.hxx" + +#include "editattributemap.hxx" +#include "editutil.hxx" +#include "xmloff/prstylei.hxx" +#include "document.hxx" + using namespace com::sun::star; using namespace xmloff::token; @@ -53,8 +80,20 @@ ScXMLAnnotationContext::ScXMLAnnotationContext( ScXMLImport& rImport, SvXMLImportContext( rImport, nPrfx, rLName ), mrAnnotationData( rAnnotationData ), pCellContext(pTempCellContext), - pShapeContext(NULL) + pShapeContext(NULL), + mpEditEngine(NULL), + mnCurParagraph(0), + mbHasFormatRuns(false), + mbEditEngineHasText(false) { + + ScDocument* pDoc = rImport.GetDocument(); + mpEditEngine = new ScEditEngineDefaulter(pDoc->GetEnginePool()); + mpEditEngine->SetEditTextObjectPool(pDoc->GetEditPool()); + mpEditEngine->SetUpdateMode(false); + mpEditEngine->EnableUndo(false); + mpEditEngine->Clear(); + uno::Reference<drawing::XShapes> xLocalShapes (GetScImport().GetTables().GetCurrentXShapes()); if (xLocalShapes.is()) { @@ -115,6 +154,16 @@ ScXMLAnnotationContext::~ScXMLAnnotationContext() { } +ScXMLAnnotationContext::ParaFormat::ParaFormat(ScEditEngineDefaulter& rEditEngine) : + maItemSet(rEditEngine.GetEmptyItemSet()) {} + +ScXMLAnnotationContext::Field::Field(SvxFieldData* pData) : mpData(pData) {} + +ScXMLAnnotationContext::Field::~Field() +{ + delete mpData; +} + void ScXMLAnnotationContext::StartElement(const com::sun::star::uno::Reference< com::sun::star::xml::sax::XAttributeList>& xAttrList) { if (pShapeContext) @@ -143,6 +192,11 @@ SvXMLImportContext *ScXMLAnnotationContext::CreateChildContext( sal_uInt16 nPref pContext = new ScXMLContentContext(GetScImport(), nPrefix, rLName, xAttrList, maCreateDateStringBuffer); } + else if( XML_NAMESPACE_TEXT == nPrefix ) + { + if( IsXMLToken( rLName, XML_P ) ) + pContext = new ScXMLAnnotationTextParaContext(GetScImport(), nPrefix, rLName, *this); + } if( !pContext && pShapeContext ) pContext = pShapeContext->CreateChildContext(nPrefix, rLName, xAttrList); @@ -167,14 +221,40 @@ void ScXMLAnnotationContext::EndElement() pShapeContext = NULL; } + // Flush the cached first paragraph if not done before (single line note). + if (maFirstParagraph) + { + mpEditEngine->Clear(); + mpEditEngine->SetText(*maFirstParagraph); + maFirstParagraph.reset(); + } + + // This text either has format runs, has field(s), or consists of multiple lines. + { + ParaFormatsType::const_iterator it = maFormats.begin(), itEnd = maFormats.end(); + for (; it != itEnd; ++it) + { + mpEditEngine->QuickSetAttribs(it->maItemSet, it->maSelection); + } + } + + { + FieldsType::const_iterator it = maFields.begin(), itEnd = maFields.end(); + for (; it != itEnd; ++it) + mpEditEngine->QuickInsertField(SvxFieldItem(*it->mpData, EE_FEATURE_FIELD), it->maSelection); + } + mrAnnotationData.maAuthor = maAuthorBuffer.makeStringAndClear(); mrAnnotationData.maCreateDate = maCreateDateBuffer.makeStringAndClear(); if (mrAnnotationData.maCreateDate.isEmpty()) mrAnnotationData.maCreateDate = maCreateDateStringBuffer.makeStringAndClear(); mrAnnotationData.maSimpleText = maTextBuffer.makeStringAndClear(); + mrAnnotationData.maEditEngine = mpEditEngine; + XMLTableShapeImportHelper* pTableShapeImport = (XMLTableShapeImportHelper*)GetScImport().GetShapeImport().get(); pTableShapeImport->SetAnnotation(NULL); + } void ScXMLAnnotationContext::SetShape( const uno::Reference< drawing::XShape >& rxShape, const uno::Reference< drawing::XShapes >& rxShapes, @@ -191,4 +271,312 @@ void ScXMLAnnotationContext::AddContentStyle( sal_uInt16 nFamily, const OUString mrAnnotationData.maContentStyles.push_back( ScXMLAnnotationStyleEntry( nFamily, rName, rSelection ) ); } +void ScXMLAnnotationContext::PushParagraphSpan(const OUString& rSpan, const OUString& rStyleName) +{ + sal_Int32 nBegin = maParagraph.getLength(); + sal_Int32 nEnd = nBegin + rSpan.getLength(); + maParagraph.append(rSpan); + + PushFormat(nBegin, nEnd, rStyleName); +} + +void ScXMLAnnotationContext::PushParagraphField(SvxFieldData* pData, const OUString& rStyleName) +{ + mbHasFormatRuns = true; + maFields.push_back(new Field(pData)); + Field& rField = maFields.back(); + + sal_Int32 nPos = maParagraph.getLength(); + maParagraph.append(sal_Unicode('\1')); // Placeholder text for inserted field item. + rField.maSelection.nStartPara = mnCurParagraph; + rField.maSelection.nEndPara = mnCurParagraph; + rField.maSelection.nStartPos = nPos; + rField.maSelection.nEndPos = nPos+1; + + PushFormat(nPos, nPos+1, rStyleName); +} + +void ScXMLAnnotationContext::PushParagraphFieldDate(const OUString& rStyleName) +{ + PushParagraphField(new SvxDateField, rStyleName); +} + +void ScXMLAnnotationContext::PushParagraphFieldSheetName(const OUString& rStyleName) +{ + SCTAB nTab = GetScImport().GetTables().GetCurrentCellPos().Tab(); + PushParagraphField(new SvxTableField(nTab), rStyleName); +} + +void ScXMLAnnotationContext::PushParagraphFieldDocTitle(const OUString& rStyleName) +{ + PushParagraphField(new SvxFileField, rStyleName); +} + +void ScXMLAnnotationContext::PushParagraphFieldURL( + const OUString& rURL, const OUString& rRep, const OUString& rStyleName) +{ + OUString aAbsURL = GetScImport().GetAbsoluteReference(rURL); + PushParagraphField(new SvxURLField(aAbsURL, rRep, SVXURLFORMAT_REPR), rStyleName); +} + +void ScXMLAnnotationContext::PushParagraphEnd() +{ + // EditEngine always has at least one paragraph even when its content is empty. + + if (mbEditEngineHasText) + { + if (maFirstParagraph) + { + // Flush the cached first paragraph first. + mpEditEngine->Clear(); + mpEditEngine->SetText(*maFirstParagraph); + maFirstParagraph.reset(); + } + mpEditEngine->InsertParagraph(mpEditEngine->GetParagraphCount(), maParagraph.makeStringAndClear()); + } + else if (mbHasFormatRuns) + { + mpEditEngine->Clear(); + mpEditEngine->SetText(maParagraph.makeStringAndClear()); + mbEditEngineHasText = true; + } + else if (mnCurParagraph == 0) + { + maFirstParagraph.reset(maParagraph.makeStringAndClear()); + mbEditEngineHasText = true; + } + + ++mnCurParagraph; +} + +void ScXMLAnnotationContext::PushFormat(sal_Int32 nBegin, sal_Int32 nEnd, const OUString& rStyleName) +{ + if (rStyleName.isEmpty()) + return; + + // Get the style information from xmloff. + UniReference<XMLPropertySetMapper> xMapper = GetImport().GetTextImport()->GetTextImportPropertySetMapper()->getPropertySetMapper(); + if (!xMapper.is()) + // We can't do anything without the mapper. + return; + + sal_Int32 nEntryCount = xMapper->GetEntryCount(); + + SvXMLStylesContext* pAutoStyles = GetImport().GetAutoStyles(); + + // Style name for text span corresponds with the name of an automatic style. + const XMLPropStyleContext* pStyle = dynamic_cast<const XMLPropStyleContext*>( + pAutoStyles->FindStyleChildContext(XML_STYLE_FAMILY_TEXT_TEXT, rStyleName)); + + if (!pStyle) + // No style by that name found. + return; + + const std::vector<XMLPropertyState>& rProps = pStyle->GetProperties(); + if (rProps.empty()) + return; + + const ScXMLEditAttributeMap& rEditAttrMap = GetScImport().GetEditAttributeMap(); + + mbHasFormatRuns = true; + maFormats.push_back(new ParaFormat(*mpEditEngine)); + ParaFormat& rFmt = maFormats.back(); + rFmt.maSelection.nStartPara = rFmt.maSelection.nEndPara = mnCurParagraph; + rFmt.maSelection.nStartPos = nBegin; + rFmt.maSelection.nEndPos = nEnd; + + boost::scoped_ptr<SfxPoolItem> pPoolItem; + sal_uInt16 nLastItemID = EE_CHAR_END + 1; + + std::vector<XMLPropertyState>::const_iterator it = rProps.begin(), itEnd = rProps.end(); + for (; it != itEnd; ++it) + { + if (it->mnIndex == -1 || it->mnIndex >= nEntryCount) + continue; + + const OUString& rName = xMapper->GetEntryAPIName(it->mnIndex); + const ScXMLEditAttributeMap::Entry* pEntry = rEditAttrMap.getEntryByAPIName(rName); + if (!pEntry) + continue; + + if (nLastItemID != pEntry->mnItemID && pPoolItem) + { + // Flush the last item when the item ID changes. + rFmt.maItemSet.Put(*pPoolItem); + pPoolItem.reset(); + } + + switch (pEntry->mnItemID) + { + case EE_CHAR_FONTINFO: + case EE_CHAR_FONTINFO_CJK: + case EE_CHAR_FONTINFO_CTL: + { + // Font properties need to be consolidated into a single item. + if (!pPoolItem) + pPoolItem.reset(new SvxFontItem(pEntry->mnItemID)); + + pPoolItem->PutValue(it->maValue, pEntry->mnFlag); + } + break; + case EE_CHAR_WEIGHT: + case EE_CHAR_WEIGHT_CJK: + case EE_CHAR_WEIGHT_CTL: + { + if (!pPoolItem) + pPoolItem.reset(new SvxWeightItem(WEIGHT_NORMAL, pEntry->mnItemID)); + + pPoolItem->PutValue(it->maValue, pEntry->mnFlag); + } + break; + case EE_CHAR_FONTHEIGHT: + case EE_CHAR_FONTHEIGHT_CJK: + case EE_CHAR_FONTHEIGHT_CTL: + { + if (!pPoolItem) + pPoolItem.reset(new SvxFontHeightItem(240, 100, pEntry->mnItemID)); + + pPoolItem->PutValue(it->maValue, pEntry->mnFlag); + } + break; + case EE_CHAR_ITALIC: + case EE_CHAR_ITALIC_CJK: + case EE_CHAR_ITALIC_CTL: + { + if (!pPoolItem) + pPoolItem.reset(new SvxPostureItem(ITALIC_NONE, pEntry->mnItemID)); + + pPoolItem->PutValue(it->maValue, pEntry->mnFlag); + } + break; + case EE_CHAR_UNDERLINE: + { + if (!pPoolItem) + pPoolItem.reset(new SvxUnderlineItem(UNDERLINE_NONE, pEntry->mnItemID)); + + pPoolItem->PutValue(it->maValue, pEntry->mnFlag); + } + break; + case EE_CHAR_OVERLINE: + { + if (!pPoolItem) + pPoolItem.reset(new SvxOverlineItem(UNDERLINE_NONE, pEntry->mnItemID)); + + pPoolItem->PutValue(it->maValue, pEntry->mnFlag); + } + break; + case EE_CHAR_COLOR: + { + if (!pPoolItem) + pPoolItem.reset(new SvxColorItem(pEntry->mnItemID)); + + pPoolItem->PutValue(it->maValue, pEntry->mnFlag); + } + break; + case EE_CHAR_WLM: + { + if (!pPoolItem) + pPoolItem.reset(new SvxWordLineModeItem(false, pEntry->mnItemID)); + + pPoolItem->PutValue(it->maValue, pEntry->mnFlag); + } + break; + case EE_CHAR_STRIKEOUT: + { + if (!pPoolItem) + pPoolItem.reset(new SvxCrossedOutItem(STRIKEOUT_NONE, pEntry->mnItemID)); + + pPoolItem->PutValue(it->maValue, pEntry->mnFlag); + } + break; + case EE_CHAR_RELIEF: + { + if (!pPoolItem) + pPoolItem.reset(new SvxCharReliefItem(RELIEF_NONE, pEntry->mnItemID)); + + pPoolItem->PutValue(it->maValue, pEntry->mnFlag); + } + break; + case EE_CHAR_OUTLINE: + { + if (!pPoolItem) + pPoolItem.reset(new SvxContourItem(false, pEntry->mnItemID)); + + pPoolItem->PutValue(it->maValue, pEntry->mnFlag); + } + break; + case EE_CHAR_SHADOW: + { + if (!pPoolItem) + pPoolItem.reset(new SvxShadowedItem(false, pEntry->mnItemID)); + + pPoolItem->PutValue(it->maValue, pEntry->mnFlag); + } + break; + case EE_CHAR_KERNING: + { + if (!pPoolItem) + pPoolItem.reset(new SvxKerningItem(0, pEntry->mnItemID)); + + pPoolItem->PutValue(it->maValue, pEntry->mnFlag); + } + break; + case EE_CHAR_PAIRKERNING: + { + if (!pPoolItem) + pPoolItem.reset(new SvxAutoKernItem(false, pEntry->mnItemID)); + + pPoolItem->PutValue(it->maValue, pEntry->mnFlag); + } + break; + case EE_CHAR_FONTWIDTH: + { + if (!pPoolItem) + pPoolItem.reset(new SvxCharScaleWidthItem(100, pEntry->mnItemID)); + + pPoolItem->PutValue(it->maValue, pEntry->mnFlag); + } + break; + case EE_CHAR_ESCAPEMENT: + { + if (!pPoolItem) + pPoolItem.reset(new SvxEscapementItem(pEntry->mnItemID)); + + pPoolItem->PutValue(it->maValue, pEntry->mnFlag); + } + break; + case EE_CHAR_EMPHASISMARK: + { + if (!pPoolItem) + pPoolItem.reset(new SvxEmphasisMarkItem(EMPHASISMARK_NONE, pEntry->mnItemID)); + + pPoolItem->PutValue(it->maValue, pEntry->mnFlag); + } + break; + case EE_CHAR_LANGUAGE: + case EE_CHAR_LANGUAGE_CJK: + case EE_CHAR_LANGUAGE_CTL: + { + if (!pPoolItem) + pPoolItem.reset(new SvxLanguageItem(LANGUAGE_DONTKNOW, pEntry->mnItemID)); + + pPoolItem->PutValue(it->maValue, pEntry->mnFlag); + } + break; + default: + ; + } + + nLastItemID = pEntry->mnItemID; + } + + if (pPoolItem) + { + rFmt.maItemSet.Put(*pPoolItem); + } + + AddContentStyle( XML_STYLE_FAMILY_TEXT_TEXT, rStyleName, rFmt.maSelection ); + +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/filter/xml/xmlannoi.hxx b/sc/source/filter/xml/xmlannoi.hxx index 8aad19af1dc1..84bb02d7c328 100644 --- a/sc/source/filter/xml/xmlannoi.hxx +++ b/sc/source/filter/xml/xmlannoi.hxx @@ -27,8 +27,15 @@ #include <com/sun/star/drawing/XShape.hpp> #include <com/sun/star/drawing/XShapes.hpp> +#include "svl/itemset.hxx" +#include "editeng/flditem.hxx" + +#include <boost/ptr_container/ptr_vector.hpp> +#include <boost/optional.hpp> + class ScXMLImport; class ScXMLTableRowCellContext; +class ScEditEngineDefaulter; struct ScXMLAnnotationStyleEntry { @@ -59,12 +66,32 @@ struct ScXMLAnnotationData bool mbShown; std::vector<ScXMLAnnotationStyleEntry> maContentStyles; + ScEditEngineDefaulter* maEditEngine; + explicit ScXMLAnnotationData(); ~ScXMLAnnotationData(); }; class ScXMLAnnotationContext : public SvXMLImportContext { + + struct ParaFormat + { + SfxItemSet maItemSet; + ESelection maSelection; + + ParaFormat(ScEditEngineDefaulter& rEditEngine); + }; + + struct Field : boost::noncopyable + { + SvxFieldData* mpData; + ESelection maSelection; + + Field(SvxFieldData* pData); + ~Field(); + }; + public: ScXMLAnnotationContext( ScXMLImport& rImport, sal_uInt16 nPrfx, @@ -94,7 +121,18 @@ public: void AddContentStyle( sal_uInt16 nFamily, const OUString& rName, const ESelection& rSelection ); + // handle caption - callback from annotationtextparacontext + void PushParagraphSpan(const OUString& rSpan, const OUString& rStyleName); + void PushParagraphFieldDate(const OUString& rStyleName); + void PushParagraphFieldSheetName(const OUString& rStyleName); + void PushParagraphFieldDocTitle(const OUString& rStyleName); + void PushParagraphFieldURL(const OUString& rURL, const OUString& rRep, const OUString& rStyleName); + void PushParagraphEnd(); + void PushParagraphField(SvxFieldData* pData, const OUString& rStyleName); + void PushFormat(sal_Int32 nBegin, sal_Int32 nEnd, const OUString& rStyleName); + private: + ScXMLAnnotationData& mrAnnotationData; OUStringBuffer maTextBuffer; OUStringBuffer maAuthorBuffer; @@ -105,6 +143,22 @@ private: const ScXMLImport& GetScImport() const { return (const ScXMLImport&)GetImport(); } ScXMLImport& GetScImport() { return (ScXMLImport&)GetImport(); } + + ScEditEngineDefaulter* mpEditEngine; + OUStringBuffer maParagraph; + sal_Int32 mnCurParagraph; + + typedef boost::ptr_vector<ParaFormat> ParaFormatsType; + typedef boost::ptr_vector<Field> FieldsType; + + ParaFormatsType maFormats; + FieldsType maFields; + + boost::optional<OUString> maFirstParagraph; /// unformatted first paragraph, for better performance. + + bool mbEditEngineHasText; + bool mbHasFormatRuns; + }; diff --git a/sc/source/filter/xml/xmlcelli.cxx b/sc/source/filter/xml/xmlcelli.cxx index 31e5bea9521d..ca7632925724 100644 --- a/sc/source/filter/xml/xmlcelli.cxx +++ b/sc/source/filter/xml/xmlcelli.cxx @@ -874,28 +874,15 @@ void ScXMLTableRowCellContext::SetAnnotation(const ScAddress& rPos) SdrObject* pObject = ::GetSdrObjectFromXShape( mxAnnotationData->mxShape ); OSL_ENSURE( pObject, "ScXMLTableRowCellContext::SetAnnotation - cannot get SdrObject from shape" ); - /* Try to reuse the drawing object already created (but only if the - note is visible, and the object is a caption object). */ - if( mxAnnotationData->mbShown && mxAnnotationData->mbUseShapePos ) - { - if( SdrCaptionObj* pCaption = dynamic_cast< SdrCaptionObj* >( pObject ) ) - { - OSL_ENSURE( !pCaption->GetLogicRect().IsEmpty(), "ScXMLTableRowCellContext::SetAnnotation - invalid caption rectangle" ); - // create the cell note with the caption object - pNote = ScNoteUtil::CreateNoteFromCaption( *pDoc, rPos, *pCaption, true ); - // forget pointer to object (do not create note again below) - pObject = 0; - } - } - - // drawing object has not been used to create a note -> use shape data + // use shape data if( pObject ) { // rescue settings from drawing object before the shape is removed ::std::auto_ptr< SfxItemSet > xItemSet( new SfxItemSet( pObject->GetMergedItemSet() ) ); ::std::auto_ptr< OutlinerParaObject > xOutlinerObj; - if( OutlinerParaObject* pOutlinerObj = pObject->GetOutlinerParaObject() ) - xOutlinerObj.reset( new OutlinerParaObject( *pOutlinerObj ) ); + OutlinerParaObject* pOutlinerObj = new OutlinerParaObject( (*mxAnnotationData->maEditEngine->CreateTextObject()) ); + xOutlinerObj.reset( new OutlinerParaObject( *pOutlinerObj ) ); + Rectangle aCaptionRect; if( mxAnnotationData->mbUseShapePos ) aCaptionRect = pObject->GetLogicRect(); @@ -956,6 +943,7 @@ void ScXMLTableRowCellContext::SetAnnotation(const ScAddress& rPos) pSheetData->AddNoteContentStyle( aIter->mnFamily, aIter->maName, rPos, aIter->maSelection ); ++aIter; } + } // core implementation |