/* * PDFedit - free program for PDF document manipulation. * Copyright (C) 2006, 2007 PDFedit team: Michal Hocko, * Miroslav Jahoda, * Jozef Misutka, * Martin Petricek * * Project is hosted on http://sourceforge.net/projects/pdfedit */ // vim:tabstop=4:shiftwidth=4:noexpandtab:textwidth=80 /* * * $RCSfile: modecontroller.h,v $ * * $Log: modecontroller.h,v $ * Revision 1.18 2007/04/25 18:24:35 bilboq * * applied patch from Martin Michlmayr to fix compilation with gcc-4.3 * * fixed some typos in comments * * Revision 1.17 2007/02/04 20:17:02 mstsxfx * Common Licence comment for all cc and h files available in doc/licence_header * file and its content to all cc and h files in src/{gui,kernel,utils} * directories. * Xpdf code, QSA and QOutputDevice code are not touched * * Revision 1.16 2006/09/06 14:18:31 hockm0bm * typo fix * * Revision 1.15 2006/06/29 20:44:05 hockm0bm * doc update * * Revision 1.14 2006/06/06 11:46:03 hockm0bm * Refactoring changes * * * ModeMatcher * - uses == instead of equals (sync with RulesManager change) * * ModeRule * - operator == replaces equals method (implementation same) * * Revision 1.13 2006/06/06 10:15:12 hockm0bm * loadFromFile method removed * - uses default implementation from RulesManager * * Revision 1.12 2006/06/06 09:19:45 hockm0bm * * ModeController moved to configuration namespace * * ModeController::loadFromFile * - fileName is const string & now * * Revision 1.11 2006/06/01 18:49:06 hockm0bm * typo fix * * Revision 1.10 2006/06/01 14:46:24 hockm0bm * doc update - doxygen warnings removed (if possible) * * Revision 1.9 2006/06/01 14:12:47 hockm0bm * * ModeConfigurationParser * - parse method corrected: mdReadOnly was missing, handling of * baseParser.parse return value, trims modeString and output type * and name, uses tokenizer function for ruleString parsing * - loadFromFile implemented * - documentation update * * ModeController * - doc update * * Revision 1.8 2006/05/31 22:36:58 hockm0bm * ModeConfigurationParser * - setStream method implemented * - first scratch of loadFromFile * * Revision 1.7 2006/05/31 20:10:22 hockm0bm * * PropertyMode enhanced and documented * * ModeRule, ModeMatcher, ModeConfigurationParser classes added * - used by Modecontroller * * New Modecontroller implementation * - IModeController removed * - enherits from ModeRulesManager * - setDefaultMode method added * - loadFromFile added - not implemented yet (parser ready) * * Revision 1.6 2006/05/31 07:06:24 hockm0bm * doc update and prepared to be implemented * - just for sync * */ #ifndef _MODECONTROLLER_H_ #define _MODECONTROLLER_H_ #include "static.h" #include "utils/rulesmanager.h" #include "utils/confparser.h" //===================================================================================== /** * Enum describing property mode. * */ enum PropertyMode { /** Unknown mode. */ mdUnknown, /** Normal mode. * Should be visible and read write. Normal property. */ mdNormal, /** Hidden mode. * Should not be visible but read write (when it is shown). Property is not * very important to see (just technical detail) but when it is visible, it * should be changeable. */ mdHidden, /** Read-only mode. * Should not be editable when it is visible. It doesn't make much sense to * change such properties. */ mdReadOnly, /** Advanced mode. * Should not be visible and editable. It is very dangeroous to change such * properties. */ mdAdvanced }; namespace configuration { /** Rule structure for mode. * This type is used for RulesManager RuleType in ModeController. * * @see RulesManager * @see ModeController */ struct ModeRule { /** Complex value type. */ std::string type; /** Field name in complex type. */ std::string name; /** Comparator method. * @param rule Rule to compare with. * * Given rule is same as given one if its type and name fields are same as * these. * * @return true if given rule is same, false otherwise. */ bool operator==(const ModeRule & rule)const { return type==rule.type && name==rule.name; } }; /** Typedef to IRuleMatcher for ModeMatcher. */ typedef rulesmanager::IRuleMatcher IModeMatcher; /** Implementator of IRuleMatcher for ModeRule. * * See functor operator for more precise information about mode rules * matching evaluation. */ class ModeMatcher: public IModeMatcher { public: typedef IModeMatcher::priority_t priority_t; /** Priority for weakest match. */ static const priority_t PRIO0=0; /** Priority for type only match. */ static const priority_t PRIO1=1; /** Priority for name only match. */ static const priority_t PRIO2=2; /** Priority for full match. */ static const priority_t PRIO3=3; /** Determines whether given rule matches given original. * @param original Original rule. * @param rule Rule to check whether matches. * @param priority Place where to store priority of match (only if non NULL * and matches). * * Rules: * * * @return true if given rule matches original, false otherwise. */ virtual bool operator()(const ModeRule & original, const ModeRule & rule, priority_t * priority)const; }; /** Typedef to RulesManager for ModeController. */ typedef rulesmanager::RulesManager ModeRulesManager; /** Decorator for IConfigurationParser with ModeRule and PropertyMode * specialization. * * This class doesn't provide any stream reading. Instead it delegates all * reading work to low-level baseParser (provided in constructor) which provides * string representation of Rule and mode. Responisbility of this class is to * parse those values to correct ModeRule and PropertyMode types. *
* ModeRule is supposed to have format: *
 * Type[.Value] : stringmode
 * 
* All other IConfigurationParser operations are delegated to the baseParser. */ class ModeConfigurationParser: public IConfigurationParser { public: typedef IConfigurationParser StringParser; private: /** Low level string parser. * This parser is initialized in constructor and it is used for input data * parsing. */ StringParser & baseParser; public: /** Initialization constructor. * Initializes baseParser field. */ ModeConfigurationParser(StringParser & parser):baseParser(parser) {} /** Sets new data stream. * @param str Stream to set. * * Delegates to baseStream (sets stream to low level string parser). * * @return Current stream reference. */ std::istream * setStream(std::istream * str) { return baseParser.setStream(str); } /** Skips current key, value pair. * Delegates to baseParser.skip() */ void skip() { baseParser.skip(); } /** Checks whether we are on end of data. * * Delegates to baseParser.eod() * * @return true if there is nothing more to read, false otherwise. */ bool eod() { return baseParser.eod(); } /** Parses key, value pair and transforms them to rule and mode. * @param rule Reference where to put parsed rule. * @param mode Reference where to put parsed mode. * * Delegates to baseParser.parse and transforms returned strings to rule * and mode. *

* Rule string has format: *

	 * type[.name]
	 * 
* If `.' is not found name or there are no characters behind, name is * empty. Everything before `.' is Type. It can also be empty. Both parts * are trimed before set (all leading and trailing blanks re skiped). *
* Name string should be same as PropertyMode names. If not recognized, * returns with an error. *
* Note that !parse() && eod() means no error but nothing more to parse. * * @return true if parsing was successful, false otherwise. */ bool parse(ModeRule & rule, PropertyMode & mode); }; /** * Basic mode controller implementation. * * Provides mapping from type, name pair to Property mode, where type stands for * complex type name (Value of complex - dictionary - Type field value) and name * for field name in given complex type. *

* Rules *
* We will write type, name pair in following format: *

 * type[.name]: mode
 * 
* not specified is represented by empty string or word containing just * blanks. *
    *
  • not specified type and name. Each type name combination matches. *
     * Example:
     * .: mdUnknown
     * is same as
     * : mdUnknown
     *
     * Default mode is mdUnknown
     * 
    * *
  • type with name unspecified is same as pure type and specifies all fields * from dictionary with given Type field value. *
     * Example:
     * Page. : mdAdvanced
     * is same as
     * Page : mdAdvanced
     *
     * All fields from Page complex value is mdAdvanced
     * 
    * *
  • unspecified type and specified name stands for all fields with given name * with no respect to complex type. It has higher priority than pure type * specification. *
     * Example:
     * Page. : mdNormal
     * .Value: mdReadOnly
     *
     * Page.foo is mdNormal
     * Page.Value is mdReadOnly
     * Foo.Value is mdReadOnly
     * 
    * *
  • Type, Name specifies concrete field on complex type (Type field value of * complex) and field name in this complex. This has the highest priority. *
     * Example:
     * Page. : mdNormal
     * .Value: mdReadOnly
     * Page.Value: mdAdvanced
     *
     * Page.Value is mdAdvanced
     * Page.foo is mdNormal
     * foo.Value is mdReadOnly
     * 
    * *
  • Most specific mapping is always used if multiple rules matches. *
  • No matching rule stands for default policy (value returned by * getDefaultMode). *
  • type, name are case sensitive. *
* *

* Usage
* Instance with empty constructor is created with mdUnknown default mode. If * you need to specify different one, use setDefaultMode method or constructor * with parameter. *
* Rules for modes can be add either manualy by addRule (inherited from * RulesManager class) method or from file using loadFromFile method. * loadFromFile method requires file name and parser parameters. Second one is * implementator which implements parsing functionality for given configuration * file format. *

 * Example:
 *
 * // Initializes mode controller
 * //============================
 * 
 * // creates ModeController instance
 * ModeController modeControler;
 *
 * // Creates low-level parser for simple configuration files (one line one
 * // setting). This base parser is used by ConfParser which is used by
 * // ModeController in loadFromFile 
 * StringConfigurationParser baseParser(StringConfigurationParser(NULL));
 * ModeController::ConfParser parser(baseParser);
 * 
 * // parser is ready, we can load rules 
 * int result=modeControler.loadFromFile(fileName, parser);
 * if(result==-1)
 *   cerr << "File \""<
 */
class ModeController: public ModeRulesManager
{
	/** Default mode.
	 *
	 * Value is set in constructor.
	 */
	PropertyMode defaultMode;

	/** Matcher for rules.
	 *
	 * This matched for supertype matcher intialization in constructor.
	 */
	ModeMatcher matcher;
public:

	/** Type for configuration parser for loadFromFile method.
	 *
	 * @see ModeConfigurationParser
	 */
	typedef ModeConfigurationParser ConfParser;
	
	/** Constructor.
	 *
	 * Intiailizes defaultMode to mdUnknown.
	 * Sets ModeMatcher instance to ModeRulesManager.
	 */
	ModeController():defaultMode(mdUnknown)
	{ 
		// initializes specialized rules matcher for property modes.
		setRuleMatcher(&matcher);
	}

	/** Constructor with default mode.
	 * @param defMod Default mode to be used.
	 *
	 * Initializes defaultMode with given one.
	 * Sets ModeMatcher instance to ModeRulesManager.
	 */
	ModeController(PropertyMode defMod):defaultMode(defMod)
	{
		// initializes specialized rules matcher for property modes.
		setRuleMatcher(&matcher);
	}

	/** Virtual destructor.
	 * This method is empty, because no special treatment is required.
	 */
	virtual ~ModeController () {}

	/** 
	 * Get default mode.
	 * 
	 * Default policy for non matching rules.
	 * @return defaultMode field value.
	 */
	virtual PropertyMode getDefaultMode() const
	{
		return defaultMode;
	}

	/** Sets default mode.
	 * @param mode New default mode.
	 *
	 * @return Previous value of default mode.
	 */
	virtual PropertyMode setDefaultMode(PropertyMode mode)
	{
		PropertyMode old=defaultMode;

		defaultMode=mode;

		return old;
	}

	/**
	 * Get mode for value with given type and name.
	 * @param type Type field value of complex type.
	 * @param name Name if the field in complex type.
	 * 
	 * Given parameters may be empty what means not specified.
	 * 
* If no rule matches given pair, getDefaultMode is returned. * * @see RulesManager::findMatching * @return Mode which is most specific for given type, name pair. */ virtual PropertyMode getMode (const std::string& type, const std::string& name) const { ModeRule rule={type, name}; PropertyMode mode; // delegates to ModeRulesManager and uses returned mode if(findMatching(rule, &mode)) return mode; // didn't match - defaultMode is used return defaultMode; } }; } // namespace configuration #endif //_MODECONTROLLER_H_