Apr 2001, S.Geerken@ping.de Last update: Dec 2004 ======= DwStyle ======= Styles of Dillo Widgets Note ==== DwStyle has derived from DwPageAttr, and its current structure is very similar to it. In the future, there will be some changes and extensions. Namely: - image maps will be handled differently (done), - margins, borders, paddings (done), - background colors/images, and - cursors and tooltips will perhaps move into DwStyle. Furthermore, widgets will probably refer to different styles for different states. Overview ======== DwStyle provides some resources and attributes for drawing widgets, as well as for parts of a widget (e.g., DwPage uses DwStyle's for its words). Creating a style is done by filling a DwStyle with the attributes (except the ref_count), and calling Dw_style_new: DwStyle style_attrs, *style; style_attrs.foo = bar; // etc. style = a_Dw_style_new (&style_attrs, random_window); // do something with style After this, the attributes of 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 and modify them: style_attrs = *another_style; style_attrs.foo = bar; style = a_Dw_style_new (&style_attrs, random_window); The font structure can be created by Dw_style_font_new, in a similar way (the GdkFont in font_attrs will be ignored), and colors by Dw_style_color_new, passing 0xrrggbb as an argument. Note that fonts and colors are only intended to be used in conjunction with DwStyle. Lengths and Percentages ======================= DwStyleLength is a simple data type for lengths and percentages: - A length refers to an absolute measurement. It is used to represent the HTML type %Pixels; and the CSS type . 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). - A percentage refers to a value relative to another value. It is used for the HTML type %Length; (except %Pixels;), and the CSS type . - A relative length can be used in lists of HTML MultiLengths. Since many values in CSS may be either lengths or percentages, a single type is very useful. Useful macros and functions --------------------------- Macros for creating lengths: DW_STYLE_CREATE_LENGTH (n) Returns a length of n pixels. DW_STYLE_CREATE_EX_LENGTH (n) Returns a length of n times the 'x-height' DW_STYLE_CREATE_EM_LENGTH (n) Returns a length of n times the 'font-size' DW_STYLE_CREATE_PERCENTAGE (n) Returns a percentage, n is relative to 1, not to 100. DW_STYLE_CREATE_RELATIVE (n) Returns a relative length. DW_STYLE_UNDEF_LENGTH Used to indicate unspecified sizes, errors, and the end of a list of lengths. Furthermore, there are some functions in html.c: DwStyleLength Html_parse_length (gchar *attr); Returns a length or a percentage, or DW_STYLE_UNDEF_LENGTH in case of an error. DwStyleLength* Html_parse_multi_length (gchar *attr); Returns a vector of lengths/percentages. The caller has to free the result when it is not longer used. Macros for examining lengths: DW_STYLE_IS_LENGTH (l) Returns TRUE if l is a length. DW_STYLE_IS_PERCENTAGE (l) Returns TRUE if l is a percentage. DW_STYLE_IS_RELATIVE (l) Returns TRUE if l is a relative length. DW_STYLE_GET_LENGTH (l, f) Returns the value of a length in pixels, as an integer. f is the font, this is used if l is based on font sizes. DW_STYLE_GET_PERCENTAGE (l) Returns the value of a percentage, relative to 1, as a float. DW_STYLE_GET_RELATIVE (l) Returns the value of a relative length, as a float. Representation -------------- Notes: 1. This is not part of the interface and may change! Use the macros described above. 2. Negative numbers may not work yet. DwStyleLength is represented by an integer (n is the number of bits of an integer): - Undefined lengths are represented by 0. - Lenghts in pixel: +---+ - - - +---+---+---+---+ | int value | 0 | 1 | +---+ - - - +---+---+---+---+ n-1 3 2 1 0 - Lengths in in x-height: +---+ - - - +---+---+---+---+ | real value | 0 | 1 | 1 | +---+ - - - +---+---+---+---+ n-1 3 2 1 0 - Lengths in in font-size: +---+ - - - +---+---+---+---+ | real value | 1 | 1 | 1 | +---+ - - - +---+---+---+---+ n-1 3 2 1 0 - Percentages: +---+ - - - +---+---+---+---+ | real value | 0 | 1 | 0 | +---+ - - - +---+---+---+---+ n-1 3 2 1 0 - Relative lengths: +---+ - - - +---+---+---+---+ | real value | 1 | 1 | 0 | +---+ - - - +---+---+---+---+ n-1 3 2 1 0 A "real value" is a fixed point number consisting of (m is the number of bits of the value, not the whole integer): +---+ - - - +---+---+ - - - +---+ | integer part | rest | +---+ - - - +---+---+ - - - +---+ m 16 15 0 For *internal* use, there are two converting macros, DW_STYLE_REAL_TO_FLOAT and DW_STYLE_FLOAT_TO_REAL. DwStyle Boxes ============= The CSS Box Model ----------------- For borders, margins etc., DwStyle uses the box model defined by CSS2. DwStyle contains some members defining these attributes. A widget must use these values for any calculation of sizes. There are some helper functions (see dw_style.h). A DwStyle box looks quite similar to a CSS box: ,-- margin.left | ,-- border.left | | ,-- padding.left |---+---+---| +---------------------------------------+ --- | | | margin.top | +-------------------------------+ | -+- | | Border | | | border.top | | +-----------------------+ | | -+- | | | Padding | | | | padding.top new widget | | | +---------------+ | | | --- allocation -->| | | | | | | | | | | | Content | | | | former widget ------------>| | | | | allocation | | | +---------------+ | | | --- | | | | | | | margin.bottom | | +-----------------------+ | | -+- | | | | | border.bottom | +-------------------------------+ | -+- | | | padding.bottom +---------------------------------------+ --- |---+---+---| padding.right --' | | border.right --' | margin.right --' Background colors ----------------- The background color is stored in style->background_color, which 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 viewport, 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.) Drawing ------- There is a new function Dw_widget_draw_widget_box, which should be called at the beginning of Dw_foo_draw. For parts referring to styles (e.g., words in a page), Dw_widget_draw_box should be used. Notes on Memory Management ========================== Memory management is done by reference counting, a_Dw_style_new returns a pointer to DwStyle with an increased reference counter, so you should care about calling Dw_style_unref if it is not used anymore. You do *not* need to care about the reference counters of fonts and styles. In detail: - a_Dw_style_ref is called in * a_Dw_widget_set_style, to assign a style to a widget, * a_Dw_page_add_text, a_Dw_page_add_widget, a_Dw_page_add_anchor, to assign a style to a word, * and Html_push_tag (often the reference counter is again decreased shortly after this). - a_Dw_unref_style is called in: * Dw_page_destroy, Dw_widget_destroy, Html_cleanup_tag, Html_pop_tag, Html_close, * a_Dw_widget_set_style, Html_set_top_font (and several Html_tag_open_... functions), these functions overwrite an existing style. HTML Stack ========== (This is not DwStyle specific, but may be useful if you are working on the HTML parser.) The topmost element of the HTML stack contains a (reference to a) style which will be used to add the text to the current page. If you use a style only for a short while (see Html_tag_open_frame for an example), you may use it this way: style_attrs = *html->stack[html->stack_top].style; style_attrs.foo = bar; style = a_Dw_style_new (&style_attrs, random_window); Do not forget to unref it afterwards. A good choice for random_window is html->bw->main_window->window. In many cases, you want to set the style for the content of an element (e.g., ). Then you must store it in the stack: DwStyle style_attrs, *old_style; old_style = html->stack[html->stack_top].style; style_attrs = *old_style; style_attrs.foo = bar; html->stack[html->stack_top].style = a_Dw_style_new (&style_attrs, random_window); a_Dw_style_unref (old_style); The macro HTML_SET_TOP_ATTR can be used for single attributes, for changing more attributes, this code should be copied for efficiency.