1 // This may look like C code, but it's really -*- C++ -*- 2 /* 3 * Copyright (C) 2008 Emweb bv, Herent, Belgium. 4 * 5 * See the LICENSE file for terms of use. 6 */ 7 #ifndef WCSS_STYLE_SHEET_H_ 8 #define WCSS_STYLE_SHEET_H_ 9 10 #include <vector> 11 #include <set> 12 #include <string> 13 14 #include <Wt/WBreak.h> 15 #include <Wt/WCssDecorationStyle.h> 16 17 namespace Wt { 18 19 class WApplication; 20 class WCssStyleSheet; 21 class WCssTemplateWidget; 22 23 /*! \class WCssRule Wt/WCssStyleSheet.h Wt/WCssStyleSheet.h 24 * \brief Abstract rule in a CSS style sheet. 25 * 26 * A rule presents CSS style properties that are applied to a selected 27 * set of elements. 28 * 29 * Use WCssTemplateRule if you would like to use a widget as a 30 * template for specifying (<i>and</i> updating) a style rule, using 31 * the widgets style properties, or WCssTextRule if you wish to 32 * directly specify the CSS declarations. 33 * 34 * \sa WCssStyleSheet 35 * 36 * \ingroup style 37 */ 38 class WT_API WCssRule : public WObject 39 { 40 public: 41 /*! \brief Destructor. 42 */ 43 virtual ~WCssRule(); 44 45 /*! \brief Sets the selector. 46 * 47 * \note The selector can only be changed as long as the rule hasn't 48 * been rendered. 49 */ setSelector(const std::string & selector)50 void setSelector(const std::string& selector) { selector_ = selector; } 51 52 /*! \brief Returns the selector. 53 */ selector()54 virtual std::string selector() const { return selector_; } 55 56 /*! \brief Returns the style sheet to which this rule belongs. 57 */ sheet()58 WCssStyleSheet *sheet() const { return sheet_; } 59 60 /*! \brief Indicates that the rule has changed and needs updating 61 */ 62 void modified(); 63 64 /*! \brief Returns the declarations. 65 * 66 * This is a semi-colon separated list of CSS declarations. 67 */ 68 virtual std::string declarations() = 0; 69 70 virtual bool updateDomElement(DomElement& cssRuleElement, bool all); 71 72 protected: 73 /*! \brief Creates a new CSS rule with given selector. 74 */ 75 WCssRule(const std::string& selector); 76 77 private: 78 std::string selector_; 79 WCssStyleSheet *sheet_; 80 81 friend class WCssStyleSheet; 82 }; 83 84 /*! \class WCssTemplateRule Wt/WCssStyleSheet.h Wt/WCssStyleSheet.h 85 * \brief A CSS rule based on a template widget. 86 * 87 * This is a CSS rule whose CSS style properties are defined based on 88 * properties of a template widget. When modifying the template 89 * widget, these changes are reflected on the CSS rule and thus all 90 * widgets that have this CSS rule. 91 * 92 * \if cpp 93 * Usage example: 94 * \code 95 * Wt::WCssTemplateRule *styleRule = 96 * Wt::WApplication::instance()->styleSheet().addRule( 97 * std::make_unique<Wt::WCssTemplateRule>("#" + id() + " .item")); 98 * 99 * styleRule->templateWidget()->resize(100, WLength::Auto); 100 * styleRule->templateWidget()->decorationStyle().setCursor(Cursor::PointingHand); 101 * \endcode 102 * \endif 103 * 104 * \sa Wt::WCssStyleSheet 105 * 106 * \ingroup style 107 */ 108 class WT_API WCssTemplateRule : public WCssRule 109 { 110 public: 111 /*! \brief Creates a CSS rule with a given selector. 112 * 113 * The selector should be a valid CSS selector. 114 * 115 * \note If you want to update the rule, then the selector should be 116 * unique and not contain commas, since this is not supported by 117 * Microsoft Internet Explorer. 118 */ 119 WCssTemplateRule(const std::string& selector); 120 121 ~WCssTemplateRule(); 122 123 /*! \brief Returns the widget that is used as a template. 124 * 125 * Various properties of the widget are reflected in the CSS style: 126 * - size and dimensions: WWidget::resize(), WWidget::setMinimumSize(), 127 * and WWidget::setMaximumSize() 128 * - its position: WWidget::setPositionScheme(), WWidget::setOffsets(), 129 * WWidget::setFloatSide(), WWidget::setClearSides() 130 * - visibility: WWidget::hide(), WWidget::show() and WWidget::setHidden() 131 * - margins: WWidget::setMargin() 132 * - line height: WWidget::setLineHeight() 133 * - all decoration style properties: WWidget::decorationStyle() 134 * 135 * When modifying one of these properties of the returned widget, the 136 * rule will be updated accordingly. 137 */ 138 WWidget *templateWidget(); 139 140 virtual std::string declarations() override; 141 142 virtual bool updateDomElement(DomElement& cssRuleElement, bool all) override; 143 144 private: 145 std::unique_ptr<WCssTemplateWidget> widget_; 146 }; 147 148 /*! \class WCssTextRule Wt/WCssStyleSheet.h Wt/WCssStyleSheet.h 149 * \brief A CSS rule specified directly using CSS declarations 150 * 151 * \if cpp 152 * Usage example: 153 * \code 154 * auto styleRule = std::make_unique<Wt::WCssTextRule>(".MyWidget .item", "width: 100px; cursor: pointer;"); 155 * Wt::WApplication::instance()->styleSheet().addRule(std::move(styleRule)); 156 * \endcode 157 * \endif 158 * 159 * \sa WCssStyleSheet 160 * 161 * \ingroup style 162 */ 163 class WT_API WCssTextRule : public WCssRule 164 { 165 public: 166 /*! \brief Creates a CSS rule with a given selector and declarations. 167 */ 168 WCssTextRule(const std::string& selector, 169 const WT_USTRING& declarations); 170 171 virtual std::string declarations() override; 172 173 private: 174 WT_USTRING declarations_; 175 }; 176 177 /*! \class WCssStyleSheet Wt/WCssStyleSheet.h Wt/WCssStyleSheet.h 178 * \brief A CSS style sheet. 179 * 180 * \if cpp 181 * Usage example: 182 * \code 183 * Wt::WApplication::instance()->styleSheet().addRule(".MyWidget .item", "width: 100px; cursor: pointer;"); 184 * \endcode 185 * \endif 186 * 187 * \sa WApplication::styleSheet() 188 * 189 * \ingroup style 190 */ 191 class WT_API WCssStyleSheet 192 { 193 public: 194 /*! \brief Creates a new (internal) style sheet. 195 */ 196 WCssStyleSheet(); 197 198 WCssStyleSheet(const WCssStyleSheet &) = delete; 199 WCssStyleSheet& operator=(const WCssStyleSheet &) = delete; 200 201 /*! \brief Destroys a style sheet, and all rules in it. 202 */ 203 ~WCssStyleSheet(); 204 205 206 /*! \brief Adds a CSS rule. 207 * 208 * Add a rule using the CSS selector \p selector, with CSS 209 * declarations in \p declarations. These declarations must be a 210 * list separated by semi-colons (;). 211 * 212 * Optionally, you may give a \p ruleName, which may later be 213 * used to check if the rule was already defined. 214 * 215 * \sa isDefined() 216 */ 217 WCssTextRule *addRule(const std::string& selector, 218 const WT_USTRING& declarations, 219 const std::string& ruleName = std::string()); 220 221 #ifndef WT_TARGET_JAVA 222 /* Interprets as UTF-8 */ 223 WCssTextRule *addRule(const std::string& selector, 224 const std::string& declarations, 225 const std::string& ruleName = std::string()); 226 227 /* Interprets as UTF-8 */ 228 WCssTextRule *addRule(const std::string& selector, 229 const char *declarations, 230 const std::string& ruleName = std::string()); 231 #endif 232 233 /*! \brief Adds a CSS rule. 234 * 235 * Add a rule using the CSS selector \p selector, with styles specified 236 * in \p style. 237 * 238 * Optionally, you may give a \p ruleName, which may later be 239 * used to check if the rule was already defined. 240 * 241 * \sa isDefined() 242 */ 243 WCssTemplateRule *addRule(const std::string& selector, 244 const WCssDecorationStyle& style, 245 const std::string& ruleName = std::string()); 246 247 /*! \brief Adds a CSS rule. 248 * 249 * Optionally, you may give a \p ruleName, which may later be 250 * used to check if the rule was already defined. 251 * Note: you may not pass the same rule to 2 diffrent applications. 252 * 253 * \sa isDefined() 254 */ 255 WCssRule *addRule(std::unique_ptr<WCssRule> rule, 256 const std::string& ruleName = std::string()); 257 258 template <typename Rule> addRule(std::unique_ptr<Rule> rule)259 Rule *addRule(std::unique_ptr<Rule> rule) 260 #ifndef WT_TARGET_JAVA 261 { 262 Rule *result = rule.get(); 263 addRule(std::unique_ptr<WCssRule>(std::move(rule))); 264 return result; 265 } 266 #else // WT_TARGET_JAVA 267 ; 268 #endif // WT_TARGET_JAVA 269 270 /*! \brief Returns if a rule was already defined in this style sheet. 271 * 272 * Returns whether a rule was added with the given \p ruleName. 273 * 274 * \sa addRule() 275 */ 276 bool isDefined(const std::string& ruleName) const; 277 278 /*! \brief Removes a rule. 279 */ 280 std::unique_ptr<WCssRule> removeRule(WCssRule *rule); 281 282 void ruleModified(WCssRule *rule); 283 284 void cssText(WStringStream& out, bool all); 285 286 void javaScriptUpdate(WApplication *app, WStringStream& js, bool all); 287 288 private: 289 typedef std::vector<std::unique_ptr<WCssRule> > RuleList; 290 typedef std::set<WCssRule *> RuleSet; 291 292 RuleList rules_; 293 std::vector<WCssRule *> rulesAdded_; 294 295 RuleSet rulesModified_; 296 std::vector<std::string> rulesRemoved_; 297 298 std::set<std::string> defined_; 299 300 bool isDirty(); 301 302 friend class WebRenderer; 303 }; 304 305 } 306 307 #endif // WCSS_STYLE_SHEET_H_ 308