Mercurial > dillo_port1.3
view dw/style.hh @ 1039:4ed33b76809c
wrap long lines in src/ css code
author | corvid <corvid@lavabit.com> |
---|---|
date | Sun, 19 Apr 2009 10:25:22 +0200 |
parents | b277eed3119c |
children | 37f26396a31b |
line wrap: on
line source
#ifndef __DW_STYLE_HH__ #define __DW_STYLE_HH__ #include <stdint.h> #ifndef __INCLUDED_FROM_DW_CORE_HH__ # error Do not include this file directly, use "core.hh" instead. #endif namespace dw { namespace core { /** * \brief Anything related to Dillo %Widget styles is defined here. * * <h3>Overview</h3> * * dw::core::style::Style provides some resources and attributes for * drawing widgets, as well as for parts of a widget (e.g., dw::Textblock * uses styles for its words). Creating a style is done by filling a * dw::core::style::StyleAttrs with the attributes and calling * dw::core::style::Style::create: * * \code * dw::core::style::Style styleAttrs; * dw::core::style::Style *style; * dw::core::Layout *layout; * * // ... * * styleAttrs.foo = bar; * // etc. * style = dw::core::style::Style::create (&styleAttrs, layout); * // do something with style * \endcode * * After this, the attributes of a dw::core::style::Style should not be * changed anymore, since styles are often shared between different * widgets etc. (see below). Most times, you simply copy the attributes * of another style (possible, since dw::core::style::Style is a sub * class of dw::core::style::StyleAttrs), modify them and create a new * style: * * \code * styleAttrs = *anotherStyle; * styleAttrs.foo = baz; * style = dw::core::style::Style::create (&styleAttrs, layout); * \endcode * * The dw::core::style::Font structure can be created by * dw::core::style::Font::create, in a similar, with * dw::core::style::FontAttrs, and colors by * dw::core::style::Color::create, passing 0xrrggbb as an * argument. Furthermore, there is dw::core::style::Tooltip, created by * dw::core::style::Tooltip::create. * * Notice that fonts, colors and tooltips are only intended to be used in * conjunction with dw::core::style::Style. * * * <h3>Naming</h3> * * dw::core::style::Style will become important for CSS, each CSS * attribute, which is supported by dillo, will refer to an attribute in * dw::core::style::Style. For this reason, the attributes in * dw::core::style::Style get the names from the CSS attributes, with * "camelCase" instead of hythens (e.g. "background-color" becomes * "backgroundColor"). * * However, dw::core::style::Style will be extended by some more * attributes, which are not defined by CSS. To distinguish them, they * get the prefix "x_", e.g. dw::core::style::Style::x_link. * * * <h3>Lengths and Percentages</h3> * * dw::core::style::Length is a simple data type for lengths and * percentages: * * <ul> * <li> A length refers to an absolute measurement. It is used to * represent the HTML type %Pixels; and the CSS type \<length\>. * * For CSS lenghts, there are two units: (i) pixels and absolute * units, which have to be converted to pixels (a pixel is, unlike * in the CSS specification, treated as absolute unit), and (ii) the * relative units "em" and "ex" (see below). * * <li> A percentage refers to a value relative to another value. It is * used for the HTML type %Length; (except %Pixels;), and the CSS * type \<percentage\>. * * <li> A relative length can be used in lists of HTML MultiLengths. * </ul> * * Since many values in CSS may be either lengths or percentages, a * single type is very useful. * * <h4>Useful Functions</h4> * * Creating lengths: * * <ul> * <li> dw::core::style::createAbsLength * <li> dw::core::style::createPerLength * <li> dw::core::style::createRelLength * </ul> * * Examine lengths: * * <ul> * <li> dw::core::style::isAbsLength * <li> dw::core::style::isPerLength * <li> dw::core::style::isRelLength * <li> dw::core::style::absLengthVal * <li> dw::core::style::perLengthVal * <li> dw::core::style::relLengthVal * </ul> * * * <h3>Boxes</h3> * * <h4>The CSS %Box Model</h4> * * For borders, margins etc., the box model defined by CSS2 is * used. dw::core::style::Style contains some members defining these * attributes. A dw::core::Widget must use these values for any * calculation of sizes. There are some helper functions (see * dw/style.hh). A dw::core::style::Style box looks quite similar to a * CSS box: * * \image html dw-style-box-model.png * * <h4>Background colors</h4> * * The background color is stored in * dw::core::style::Style::backgroundColor, which may be NULL (the * background color of the parent widget is shining through). * * For toplevel widgets, this color is set as the background color of the * views (dw::core::View::setBgColor), for other widgets, a filled * rectangle is drawn, covering the content and padding. (This is * compliant with CSS2, the background color of the toplevel element * covers the whole canvas.) * * <h4>Drawing</h4> * * The following methods may be useful: * * <ul> * <li> dw::core::Widget::drawWidgetBox for drawing the box of a widget * (typically at the beginning of the implementation of * dw::core::Widget::draw), and * * <li> dw::core::Widget::drawBox, for drawing parts of a widget (e.g. * dw::Textblock::Word, which has its own dw::Textblock::Word::style). * </ul> * * * <h3>Notes on Memory Management</h3> * * Memory management is done by reference counting, * dw::core::style::Style::create returns a pointer to * dw::core::style::Style with an increased reference counter, so you * should care about calling dw::core::style::Style::unref if it is not * used anymore. You do \em not need to care about the reference counters * of fonts and styles. * * In detail: * * <ul> * <li> dw::core::style::Style::ref is called in * * <ul> * <li> dw::core::Widget::setStyle to assign a style to a widget, * <li> dw::Textblock::addText, dw::Textblock::addWidget, * dw::Textblock::addAnchor, dw::Textblock::addSpace, * dw::Textblock::addParbreak and dw::Textblock::addLinebreak, * to assign a style to a dw::Textblock::Word, and * <li> by the HTML parser, when pushing an element on the stack. * </ul> * * <li> dw::core::style::Style::unref is called in * * <ul> * <li> dw::core::Widget::~Widget, dw::Textblock::~Textblock, by the * HTML parser, when popping an element fom the stack, and * <li> dw::core::Widget::setStyle, dw::Textblock::addText etc., * these methods overwrite an existing style. * </ul> * </ul> */ namespace style { enum Cursor { CURSOR_COSSHAIR, CURSOR_DEFAULT, CURSOR_POINTER, CURSOR_MOVE, CURSOR_E_RESIZE, CURSOR_NE_RESIZE, CURSOR_NW_RESIZE, CURSOR_N_RESIZE, CURSOR_SE_RESIZE, CURSOR_SW_RESIZE, CURSOR_S_RESIZE, CURSOR_W_RESIZE, CURSOR_TEXT, CURSOR_WAIT, CURSOR_HELP }; enum BorderStyle { BORDER_NONE, BORDER_HIDDEN, BORDER_DOTTED, BORDER_DASHED, BORDER_SOLID, BORDER_DOUBLE, BORDER_GROOVE, BORDER_RIDGE, BORDER_INSET, BORDER_OUTSET }; enum TextAlignType { TEXT_ALIGN_LEFT, TEXT_ALIGN_RIGHT, TEXT_ALIGN_CENTER, TEXT_ALIGN_JUSTIFY, TEXT_ALIGN_STRING }; enum VAlignType { VALIGN_TOP, VALIGN_BOTTOM, VALIGN_MIDDLE, VALIGN_BASELINE, VALIGN_SUB, VALIGN_SUPER }; /** * \todo Incomplete. Has to be completed for a CSS implementation. */ enum DisplayType { DISPLAY_BLOCK, DISPLAY_INLINE, DISPLAY_LIST_ITEM, DISPLAY_TABLE, DISPLAY_TABLE_ROW_GROUP, DISPLAY_TABLE_HEADER_GROUP, DISPLAY_TABLE_FOOTER_GROUP, DISPLAY_TABLE_ROW, DISPLAY_TABLE_CELL, DISPLAY_LAST }; enum ListStyleType { LIST_STYLE_TYPE_DISC, LIST_STYLE_TYPE_CIRCLE, LIST_STYLE_TYPE_SQUARE, LIST_STYLE_TYPE_DECIMAL, LIST_STYLE_TYPE_DECIMAL_LEADING_ZERO, LIST_STYLE_TYPE_LOWER_ROMAN, LIST_STYLE_TYPE_UPPER_ROMAN, LIST_STYLE_TYPE_LOWER_GREEK, LIST_STYLE_TYPE_LOWER_ALPHA, LIST_STYLE_TYPE_LOWER_LATIN, LIST_STYLE_TYPE_UPPER_ALPHA, LIST_STYLE_TYPE_UPPER_LATIN, LIST_STYLE_TYPE_HEBREW, LIST_STYLE_TYPE_ARMENIAN, LIST_STYLE_TYPE_GEORGIAN, LIST_STYLE_TYPE_CJK_IDEOGRAPHIC, LIST_STYLE_TYPE_HIRAGANA, LIST_STYLE_TYPE_KATAKANA, LIST_STYLE_TYPE_HIRAGANA_IROHA, LIST_STYLE_TYPE_KATAKANA_IROHA, LIST_STYLE_TYPE_NONE }; enum FontStyle { FONT_STYLE_NORMAL, FONT_STYLE_ITALIC, FONT_STYLE_OBLIQUE }; enum TextDecoration { TEXT_DECORATION_NONE = 0, TEXT_DECORATION_UNDERLINE = 1 << 0, TEXT_DECORATION_OVERLINE = 1 << 1, TEXT_DECORATION_LINE_THROUGH = 1 << 2, TEXT_DECORATION_BLINK = 1 << 3 }; enum WhiteSpace { WHITE_SPACE_NORMAL, WHITE_SPACE_PRE, WHITE_SPACE_NOWRAP }; /** * \brief Type for representing all lengths within dw::core::style. * * Lengths are int's. Absolute lengths are represented in the following way: * * \image html dw-style-length-absolute.png * * Percentages: * * \image html dw-style-length-percentage.png * * Relative lengths (only used in HTML): * * \image html dw-style-length-relative.png * * This is an implementation detail, use one of the following functions: * * Creating lengths: * * <ul> * <li> dw::core::style::createAbsLength * <li> dw::core::style::createPerLength * <li> dw::core::style::createRelLength * </ul> * * Examine lengths: * * <ul> * <li> dw::core::style::isAbsLength * <li> dw::core::style::isPerLength * <li> dw::core::style::isRelLength * <li> dw::core::style::absLengthVal * <li> dw::core::style::perLengthVal * <li> dw::core::style::relLengthVal * </ul> * * "auto" lenghths are represented as dw::core::style::LENGTH_AUTO. */ typedef int Length; /** \brief Returns a length of \em n pixels. */ inline Length createAbsLength(int n) { return (n << 2) | 1; } /** \brief Returns a percentage, \em v is relative to 1, not to 100. */ inline Length createPerLength(double v) { return ((int)(v * (1 << 18)) & ~3) | 2; } /** \brief Returns a relative length. */ inline Length createRelLength(double v) { return ((int)(v * (1 << 18)) & ~3) | 3; } /** \brief Returns true if \em l is an absolute length. */ inline bool isAbsLength(Length l) { return (l & 3) == 1; } /** \brief Returns true if \em l is a percentage. */ inline bool isPerLength(Length l) { return (l & 3) == 2; } /** \brief Returns true if \em l is a relative length. */ inline bool isRelLength(Length l) { return (l & 3) == 3; } /** \brief Returns the value of a length in pixels, as an integer. */ inline int absLengthVal(Length l) { return l >> 2; } /** \brief Returns the value of a percentage, relative to 1, as a double. */ inline double perLengthVal(Length l) { return (double)(l & ~3) / (1 << 18); } /** \brief Returns the value of a relative length, as a float. */ inline double relLengthVal(Length l) { return (double)(l & ~3) / (1 << 18); } enum { /** \brief Represents "auto" lengths. */ LENGTH_AUTO = 0 }; /** * \brief Represents a dimension box according to the CSS box model. * * Used for dw::core::style::Style::margin, * dw::core::style::Style::borderWidth, and dw::core::style::Style::padding. */ class Box { public: /* in future also percentages */ int top, right, bottom, left; inline void setVal(int val) { top = right = bottom = left = val; } inline bool equals (Box *other) { return top == other->top && right == other->right && bottom == other->bottom && left == other->left; } inline int hashValue () { return top + right + bottom + left; } }; class Font; class Color; class Tooltip; /** * \sa dw::core::style */ class StyleAttrs : public object::Object { public: Font *font; int textDecoration; /* No TextDecoration because of problems converting * TextDecoration <-> int */ Color *color, *backgroundColor; TextAlignType textAlign; VAlignType valign; char textAlignChar; /* In future, strings will be supported. */ int hBorderSpacing, vBorderSpacing; Length width, height; Box margin, borderWidth, padding; struct { Color *top, *right, *bottom, *left; } borderColor; struct { BorderStyle top, right, bottom, left; } borderStyle; DisplayType display; WhiteSpace whiteSpace; ListStyleType listStyleType; Cursor cursor; int x_link; int x_img; Tooltip *x_tooltip; void initValues (); void resetValues (); bool sizeDiffs (StyleAttrs *otherStyleAttrs); inline void setBorderColor(Color *val) { borderColor.top = borderColor.right = borderColor.bottom = borderColor.left = val; } inline void setBorderStyle(BorderStyle val) { borderStyle.top = borderStyle.right = borderStyle.bottom = borderStyle.left = val; } inline int boxOffsetX () { return margin.left + borderWidth.left + padding.left; } inline int boxRestWidth () { return margin.right + borderWidth.right + padding.right; } inline int boxDiffWidth () { return boxOffsetX () + boxRestWidth (); } inline int boxOffsetY () { return margin.top + borderWidth.top + padding.top; } inline int boxRestHeight () { return margin.bottom + borderWidth.bottom + padding.bottom; } inline int boxDiffHeight () { return boxOffsetY () + boxRestHeight (); } inline bool hasBackground () { return backgroundColor != NULL; } bool equals (object::Object *other); int hashValue (); }; /** * \sa dw::core::style */ class Style: public StyleAttrs { private: static int totalRef; int refCount; static container::typed::HashTable <StyleAttrs, Style> *styleTable; Style (StyleAttrs *attrs); protected: ~Style(); void copyAttrs (StyleAttrs *attrs); public: inline static Style *create (Layout *layout, StyleAttrs *attrs) { Style *style = styleTable->get (attrs); if (style) { style->ref (); } else { style = new Style (attrs); styleTable->put(style, style); } return style; } inline void ref () { refCount++; } inline void unref () { if (--refCount == 0) delete this; } }; /** * \sa dw::core::style */ class TooltipAttrs: public object::String { public: TooltipAttrs(const char *text): object::String(text) { } }; /** * \sa dw::core::style */ class Tooltip: public TooltipAttrs { private: int refCount; Tooltip (const char *text): TooltipAttrs(text) { refCount = 0; } public: inline Tooltip *create (Layout *layout, const char *text) { return new Tooltip (text); } inline void ref () { refCount++; } inline void unref () { if (--refCount == 0) delete this; } inline void onEnter () { } inline void onLeave () { } inline void onMotion () { } }; /** * \sa dw::core::style */ class FontAttrs: public object::Object { public: const char *name; int size; int weight; FontStyle style; bool equals(object::Object *other); int hashValue(); }; /** * \sa dw::core::style */ class Font: public FontAttrs { private: int refCount; static Font *create0 (Layout *layout, FontAttrs *attrs, bool tryEverything); protected: inline Font () { refCount = 0; } virtual ~Font (); void copyAttrs (FontAttrs *attrs); public: int ascent, descent; int spaceWidth; int xHeight; static Font *create (Layout *layout, FontAttrs *attrs); static Font *createFromList (Layout *layout, FontAttrs *attrs, char *defaultFamily); inline void ref () { refCount++; } inline void unref () { if (--refCount == 0) delete this; } }; /** * \sa dw::core::style */ class ColorAttrs: public object::Object { protected: int color; public: inline ColorAttrs(int color) { this->color = color; } inline int getColor () { return color; } bool equals(object::Object *other); int hashValue(); }; /** * \sa dw::core::style */ class Color: public ColorAttrs { private: int refCount; void remove(dw::core::Layout *layout); int shadeColor (int color, int d); protected: inline Color (int color): ColorAttrs (color) { refCount = 0; } virtual ~Color (); public: enum Shading { SHADING_NORMAL, SHADING_INVERSE, SHADING_DARK, SHADING_LIGHT, SHADING_NUM }; protected: int shadeColor (int color, Shading shading); public: static Color *create (Layout *layout, int color); inline void ref () { refCount++; } inline void unref () { if (--refCount == 0) delete this; } }; void drawBorder (View *view, Rectangle *area, int x, int y, int width, int height, Style *style, bool inverse); void drawBackground (View *view, Rectangle *area, int x, int y, int width, int height, Style *style, bool inverse); void numtostr (int num, char *buf, int buflen, ListStyleType listStyleType); } // namespace style } // namespace dw } // namespace core #endif // __DW_STYLE_HH__