Back to index

scribus-ng  1.3.4.dfsg+svn20071115
paragraphstyle.cpp
Go to the documentation of this file.
00001 /*
00002  For general Scribus (>=1.3.2) copyright and licensing information please refer
00003  to the COPYING file provided with the program. Following this notice may exist
00004  a copyright and/or license notice that predates the release of Scribus 1.3.2
00005  for which a new license (GPL+exception) is in place.
00006  */
00007 /***************************************************************************
00008 *                                                                         *
00009 *   This program is free software; you can redistribute it and/or modify  *
00010 *   it under the terms of the GNU General Public License as published by  *
00011 *   the Free Software Foundation; either version 2 of the License, or     *
00012 *   (at your option) any later version.                                   *
00013 *                                                                         *
00014 ***************************************************************************/
00015 
00016 
00017 
00018 #include "styles/style.h"
00019 #include "paragraphstyle.h"
00020 #include "resourcecollection.h"
00021 #include "desaxe/saxiohelper.h"
00022 #include "desaxe/simple_actions.h"
00023 
00024 
00025 ParagraphStyle::ParagraphStyle() : Style(), cstyleContext(NULL), cstyleContextIsInh(true), cstyle()
00026 {
00027        setParent("");
00028        cstyleContext.setDefaultStyle( &cstyle );
00029 //     qDebug(QString("ParagraphStyle() %1 pcontext %2 ccontext %3").arg(reinterpret_cast<uint>(this)).arg(reinterpret_cast<uint>(context())).arg(reinterpret_cast<uint>(defaultStyle()->context())));
00030 #define ATTRDEF(attr_TYPE, attr_GETTER, attr_NAME, attr_DEFAULT) \
00031        m_##attr_NAME = attr_DEFAULT; \
00032        inh_##attr_NAME = true;
00033 #include "paragraphstyle.attrdefs.cxx"
00034 #undef ATTRDEF
00035 }
00036 
00037 
00038 ParagraphStyle::ParagraphStyle(const ParagraphStyle& other) : Style(other), cstyleContext(NULL), cstyleContextIsInh(other.cstyleContextIsInh), cstyle(other.charStyle())
00039 {
00040        if (cstyleContextIsInh)
00041               cstyle.setContext(NULL);
00042        else
00043               cstyle.setContext(other.charStyle().context());
00044        cstyleContext.setDefaultStyle( &cstyle );
00045 //     qDebug(QString("ParagraphStyle(%2) %1").arg(reinterpret_cast<uint>(&other)).arg(reinterpret_cast<uint>(this)));
00046        other.validate();
00047 
00048 #define ATTRDEF(attr_TYPE, attr_GETTER, attr_NAME, attr_DEFAULT) \
00049        m_##attr_NAME = other.m_##attr_NAME; \
00050        inh_##attr_NAME = other.inh_##attr_NAME;
00051 #include "paragraphstyle.attrdefs.cxx"
00052 #undef ATTRDEF
00053 }
00054 
00055 ParagraphStyle::~ParagraphStyle()
00056 {
00057 //     qDebug(QString("~ParagraphStyle %1").arg(reinterpret_cast<uint>(this)));
00058 }
00059        
00060 
00061 QString ParagraphStyle::displayName() const
00062 {
00063        if ( hasName() || !hasParent() || !m_context)
00064               return name();
00065        //     else if ( inheritsAll() )
00066        //            return parent()->displayName();
00067        else 
00068               return parentStyle()->displayName() + "+";
00069 }
00070 
00071 
00072 bool ParagraphStyle::equiv(const Style& other) const
00073 {
00074        other.validate();
00075        const ParagraphStyle* oth = dynamic_cast<const ParagraphStyle*> ( & other );
00076        return  oth &&
00077               parent() == oth->parent() && cstyle.equiv(oth->charStyle())
00078 #define ATTRDEF(attr_TYPE, attr_GETTER, attr_NAME, attr_DEFAULT) \
00079               && (inh_##attr_NAME == oth->inh_##attr_NAME) \
00080               && (inh_##attr_NAME || m_##attr_NAME == oth->m_##attr_NAME)
00081 #include "paragraphstyle.attrdefs.cxx"
00082 #undef ATTRDEF
00083               ;
00084 }      
00085 
00086 
00087 /* hm... av
00088 static void updateAutoLinespacing(ParagraphStyle& that)
00089 {
00090        switch (that.lineSpacingMode())
00091        {
00092               case 0: 
00093                      that.setLineSpacing(((that.charStyle().fontSize() / 10.0) * static_cast<double>(typographicSettings.autoLineSpacing) / 100) + (size / 10.0));
00094                      break;
00095               case 1:
00096                      that.setLineSpacing(that.charStyle().font().height(size));
00097                      break;
00098               case 2:
00099                      that.setLineSpacing(typographicSettings.valueBaseGrid-1);
00100                      break;
00101        }
00102 }
00103 */
00104 
00105 ParagraphStyle& ParagraphStyle::operator=(const ParagraphStyle& other) 
00106 {
00107        static_cast<Style&>(*this) = static_cast<const Style&>(other);
00108 
00109        other.validate();
00110        cstyle = other.charStyle();
00111 
00112        // we dont want cstyleContext to point to other's charstyle...
00113        cstyleContext.setDefaultStyle( &cstyle );
00114        
00115        if (cstyleContextIsInh)
00116        {
00117               const ParagraphStyle * parent = dynamic_cast<const ParagraphStyle*> ( parentStyle() );
00118               cstyle.setContext(parent ? parent->charStyleContext() : NULL);
00119        }
00120        else
00121        {
00122               cstyle.setContext(other.charStyle().context());
00123        }
00124        
00125 #define ATTRDEF(attr_TYPE, attr_GETTER, attr_NAME, attr_DEFAULT) \
00126        m_##attr_NAME = other.m_##attr_NAME; \
00127        inh_##attr_NAME = other.inh_##attr_NAME;
00128 #include "paragraphstyle.attrdefs.cxx"
00129 #undef ATTRDEF
00130        return *this;
00131 }
00132 
00133 
00134 void ParagraphStyle::setContext(const StyleContext* context)
00135 {
00136        Style::setContext(context);
00137 //     qDebug(QString("ParagraphStyle::setContext(%1) parent=%2").arg((unsigned long int)context).arg((unsigned long int)oth));
00138        repairImplicitCharStyleInheritance();
00139 }
00140 
00141 void ParagraphStyle::repairImplicitCharStyleInheritance()
00142 {
00143        if (cstyleContextIsInh) {
00144               const ParagraphStyle * newParent = dynamic_cast<const ParagraphStyle*> ( parentStyle() );
00145               cstyle.setContext(newParent ? newParent->charStyleContext() : NULL);
00146        }
00147 }
00148 
00149 
00150 void ParagraphStyle::breakImplicitCharStyleInheritance(bool val)
00151 { 
00152        cstyleContextIsInh = !val;
00153        repairImplicitCharStyleInheritance();
00154 }
00155 
00156 void ParagraphStyle::update(const StyleContext* context)
00157 {
00158        Style::update(context);
00159        assert ( &cstyleContext != cstyle.context());
00160 
00161        repairImplicitCharStyleInheritance();
00162        assert ( &cstyleContext != cstyle.context());
00163        cstyle.validate();
00164        cstyleContext.invalidate();
00165 
00166        const ParagraphStyle * oth = dynamic_cast<const ParagraphStyle*> ( parentStyle() );
00167 //     qDebug(QString("ParagraphStyle::update(%1) parent=%2").arg((unsigned long int)context).arg((unsigned long int)oth));
00168        if (oth) {
00169 #define ATTRDEF(attr_TYPE, attr_GETTER, attr_NAME, attr_DEFAULT) \
00170               if (inh_##attr_NAME) \
00171                      m_##attr_NAME = oth->attr_GETTER();
00172 #include "paragraphstyle.attrdefs.cxx"
00173 #undef ATTRDEF
00174        }
00175 }
00176 
00177 
00178 
00179 void ParagraphStyle::applyStyle(const ParagraphStyle& other) 
00180 {
00181        Style::applyStyle(other);
00182        cstyle.applyCharStyle(other.charStyle());
00183        cstyleContext.invalidate();
00184 #define ATTRDEF(attr_TYPE, attr_GETTER, attr_NAME, attr_DEFAULT) \
00185        if (! other.inh_##attr_NAME) \
00186               set##attr_NAME(other.m_##attr_NAME);
00187 #include "paragraphstyle.attrdefs.cxx"
00188 #undef ATTRDEF
00189 }
00190 
00191 
00192 void ParagraphStyle::eraseStyle(const ParagraphStyle& other) 
00193 {
00194        other.validate();
00195        Style::eraseStyle(other);
00196        cstyle.eraseCharStyle(other.charStyle());
00197        cstyleContext.invalidate();
00198 #define ATTRDEF(attr_TYPE, attr_GETTER, attr_NAME, attr_DEFAULT) \
00199        if (!inh_##attr_NAME && m_##attr_NAME == other.m_##attr_NAME) \
00200               reset##attr_NAME();
00201 #include "paragraphstyle.attrdefs.cxx"
00202 #undef ATTRDEF
00203 }
00204 
00205 void ParagraphStyle::setStyle(const ParagraphStyle & other) 
00206 {
00207        other.validate();
00208        setParent(other.parent());
00209        m_contextversion = -1; 
00210        cstyle.setStyle(other.charStyle());
00211        cstyleContext.invalidate();
00212 #define ATTRDEF(attr_TYPE, attr_GETTER, attr_NAME, attr_DEFAULT) \
00213        inh_##attr_NAME = other.inh_##attr_NAME; \
00214        m_##attr_NAME = other.m_##attr_NAME;
00215 #include "paragraphstyle.attrdefs.cxx"
00216 #undef ATTRDEF
00217 }
00218 
00219 
00220 void ParagraphStyle::getNamedResources(ResourceCollection& lists) const
00221 {
00222        for (const Style* sty = parentStyle(); sty != NULL; sty = sty->parentStyle())
00223               lists.collectStyle(sty->name());
00224        charStyle().getNamedResources(lists);
00225 }
00226 
00227 
00228 void ParagraphStyle::replaceNamedResources(ResourceCollection& newNames)
00229 {
00230        QMap<QString,QString>::ConstIterator it;
00231        
00232        if (hasParent() && (it = (newNames.styles().find(parent()))) != newNames.styles().end())
00233        {
00234               setParent(it.data());
00235               repairImplicitCharStyleInheritance();
00236        }
00237        cstyle.replaceNamedResources(newNames);
00238 }
00239 
00240 
00241 static QString toXMLString(ParagraphStyle::AlignmentType val)
00242 {
00243        return QString::number(static_cast<int>(val));
00244 }
00245 
00246 
00247 static QString toXMLString(const QValueList<ParagraphStyle::TabRecord> & )
00248 {
00249        return "dummy";
00250 }
00251 
00252 void ParagraphStyle::saxx(SaxHandler& handler, const Xml_string& elemtag) const
00253 {
00254        Xml_attr att;
00255        Style::saxxAttributes(att);
00256 #define ATTRDEF(attr_TYPE, attr_GETTER, attr_NAME, attr_DEFAULT) \
00257        if (!inh_##attr_NAME && strcmp(# attr_NAME, "TabValues") != 0) \
00258               att.insert(# attr_NAME, toXMLString(m_##attr_NAME)); 
00259 #include "paragraphstyle.attrdefs.cxx"
00260 #undef ATTRDEF
00261        if (!name().isEmpty())
00262               att["id"] = mkXMLName(elemtag + name());
00263        handler.begin(elemtag, att);
00264 //     if (parentStyle() && hasParent())
00265 //            parentStyle()->saxx(handler);
00266        QValueList<ParagraphStyle::TabRecord>::const_iterator it;
00267        for (it=m_TabValues.begin(); it != m_TabValues.end(); ++it)
00268        {
00269               const ParagraphStyle::TabRecord& tb(*it);
00270               Xml_attr tab;
00271               tab.insert("pos", toXMLString(tb.tabPosition));
00272               tab.insert("fillChar", toXMLString(tb.tabFillChar.unicode()));
00273               tab.insert("type", toXMLString(tb.tabType));
00274               handler.beginEnd("tabstop", tab);
00275        }
00276        if (charStyle() != CharStyle())
00277               charStyle().saxx(handler);
00278        handler.end(elemtag);
00279 }
00280 
00282 class SetCharStyle_body : public desaxe::Action_body
00283 {
00284        void end (const Xml_string& /*tagname*/)
00285        {
00286               ParagraphStyle* pstyle = this->dig->top<ParagraphStyle>(1);
00287               CharStyle* cstyle = this->dig->top<CharStyle>(0);
00288               pstyle->charStyle() = *cstyle;
00289        }
00290 };
00291 
00292 class SetCharStyle : public desaxe::MakeAction<SetCharStyle_body>
00293 {};
00294 
00295 
00296 
00297 class SetTabStop_body : public desaxe::Action_body
00298 {
00299        void begin (const Xml_string& /*tagname*/, Xml_attr attr)
00300        {
00301               ParagraphStyle* pstyle = this->dig->top<ParagraphStyle>();
00302               ParagraphStyle::TabRecord tb;
00303               tb.tabPosition = parseDouble(attr["pos"]);
00304               tb.tabFillChar = QChar(parseInt(attr["fillChar"]));
00305               tb.tabType = parseInt(attr["type"]);
00306               QValueList<ParagraphStyle::TabRecord> tabs = pstyle->tabValues();
00307               tabs.append(tb);
00308               pstyle->setTabValues(tabs);
00309        }
00310 };
00311 
00312 class SetTabStop : public desaxe::MakeAction<SetTabStop_body>
00313 {};
00314 
00315 
00316 
00317 
00318 template<>
00319 ParagraphStyle::AlignmentType parse<ParagraphStyle::AlignmentType>(const Xml_string& str)
00320 {
00321        return parseEnum<ParagraphStyle::AlignmentType>(str);
00322 }
00323 
00324 
00325 template<>
00326 ParagraphStyle::LineSpacingMode parse<ParagraphStyle::LineSpacingMode>(const Xml_string& str)
00327 {
00328        return parseEnum<ParagraphStyle::LineSpacingMode>(str);
00329 }
00330 
00331 
00332 typedef QValueList<ParagraphStyle::TabRecord> Tablist;
00333 
00334 template<>
00335 Tablist parse<Tablist>(const Xml_string& str)
00336 {
00337        return Tablist();
00338 }
00339 
00340 
00341 using namespace desaxe;
00342 
00343 const Xml_string ParagraphStyle::saxxDefaultElem("style");
00344 
00345 void ParagraphStyle::desaxeRules(const Xml_string& prefixPattern, Digester& ruleset, Xml_string elemtag)
00346 {
00347        typedef ParagraphStyle::TabRecord TabRecord;
00348               
00349        Xml_string stylePrefix(Digester::concat(prefixPattern, elemtag));
00350        ruleset.addRule(stylePrefix, Factory<ParagraphStyle>());
00351        ruleset.addRule(stylePrefix, IdRef<ParagraphStyle>());
00352        Style::desaxeRules<ParagraphStyle>(prefixPattern, ruleset, elemtag);
00353 #define ATTRDEF(attr_TYPE, attr_GETTER, attr_NAME, attr_DEFAULT) \
00354        if ( strcmp(# attr_NAME, "TabValues") != 0) \
00355               ruleset.addRule(stylePrefix, SetAttributeWithConversion<ParagraphStyle, attr_TYPE> ( & ParagraphStyle::set##attr_NAME,  # attr_NAME, &parse<attr_TYPE> ));
00356 #include "paragraphstyle.attrdefs.cxx"
00357 #undef ATTRDEF
00358        Xml_string charstylePrefix(Digester::concat(stylePrefix, CharStyle::saxxDefaultElem));
00359        CharStyle::desaxeRules(stylePrefix, ruleset);
00360        ruleset.addRule(charstylePrefix, SetCharStyle());
00361        
00362        Xml_string tabPrefix(Digester::concat(stylePrefix, "tabstop"));
00363        ruleset.addRule(tabPrefix, SetTabStop());
00364 }