diff options
author | jcid <devnull@localhost> | 2008-09-24 18:44:40 +0200 |
---|---|---|
committer | jcid <devnull@localhost> | 2008-09-24 18:44:40 +0200 |
commit | c377e06400f138325a9a9d43d91a9272691867a1 (patch) | |
tree | 49f3ca1c46af11a058a68714899d4137ec717618 /dw/ui.hh | |
parent | 642f9b3e747859a7256ea12fab9f9ed50aa9253a (diff) |
- Moved the dw2 tree into dillo2's tree.
Diffstat (limited to 'dw/ui.hh')
-rw-r--r-- | dw/ui.hh | 564 |
1 files changed, 564 insertions, 0 deletions
diff --git a/dw/ui.hh b/dw/ui.hh new file mode 100644 index 00000000..de3e1b2b --- /dev/null +++ b/dw/ui.hh @@ -0,0 +1,564 @@ +#ifndef __DW_UI_HH__ +#define __DW_UI_HH__ + +#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 embedded UI widgets is defined here. + * + * UI resources are another abstraction for Dw widgets, which are not + * fully implemented in a platform-independent way. Typically, they + * involve creating widgets, which the underlying UI toolkit provides. + * + * As you see in this diagram: + * + * \dot + * digraph G { + * node [shape=record, fontname=Helvetica, fontsize=10]; + * edge [arrowhead="none", arrowtail="empty", labelfontname=Helvetica, + * labelfontsize=10, color="#404040", labelfontcolor="#000080"]; + * fontname=Helvetica; fontsize=10; + * + * subgraph cluster_core { + * style="dashed"; color="#000080"; fontname=Helvetica; fontsize=10; + * label="dw::core"; + * + * subgraph cluster_ui { + * style="dashed"; color="#000080"; fontname=Helvetica; fontsize=10; + * label="dw::core::ui"; + * + * Embed [URL="\ref dw::core::ui::Embed"]; + * Resource [color="#a0a0a0", URL="\ref dw::core::ui::Resource"]; + * LabelButtonResource [color="#a0a0a0", + * URL="\ref dw::core::ui::LabelButtonResource"]; + * EntryResource [color="#a0a0a0", + * URL="\ref dw::core::ui::EntryResource"]; + * etc [color="#a0a0a0", label="..."]; + * } + * + * Widget [URL="\ref dw::core::Widget", color="#a0a0a0"]; + * } + * + * subgraph cluster_fltk { + * style="dashed"; color="#000080"; fontname=Helvetica; fontsize=10; + * label="dw::fltk::ui"; + * + * FltkLabelButtonResource + * [URL="\ref dw::fltk::ui::FltkLabelButtonResource"]; + * FltkEntryResource [URL="\ref dw::fltk::ui::FltkEntryResource"]; + * } + * + * Widget -> Embed; + * Embed -> Resource [arrowhead="open", arrowtail="none", + * headlabel="1", taillabel="1"]; + * Resource -> LabelButtonResource; + * Resource -> EntryResource; + * Resource -> etc; + * LabelButtonResource -> FltkLabelButtonResource; + * EntryResource -> FltkEntryResource; + * } + * \enddot + * + * <center>[\ref uml-legend "legend"]</center> + * + * there are several levels: + * + * <ol> + * <li> The Dw widget is dw::core::ui::Embed. It delegates most to + * dw::core::ui::Resource, which has similar methods like + * dw::core::Widget. + * + * <li> There are several sub interfaces of dw::core::ui::Resource, which + * may provide methods, as e.g. dw::core::ui::ListResource::addItem. In a + * platform independent context, you can cast the result of + * dw::core::ui::Embed::getResource to a specific sub class, if you + * know, which one is used. E.g., if you know, that a given instance + * dw::core::ui::Embed refers to a dw::core::ui::ListResource, you can + * write something like: + * + * \code + * dw::core::ui::Embed *embed; + * //... + * ((dw::core::ui::ListResource*)embed->getResource ())->addItem ("Hello!"); + * \endcode + * + * <li> These sub classes are then fully implemented in a platform specific + * way. For an example, look at dw::fltk::ui. + * </ol> + * + * There is a factory interface, dw::core::ui::ResourceFactory, which + * provides methods for creating common resources. By calling + * dw::core::Layout::getResourceFactory, which calls + * dw::core::Platform::getResourceFactory, you get the factory for the used + * platform. + * + * It is possible to define additional sub classes of + * dw::core::ui::Resource, but since they are not provided by + * dw::core::ui::ResourceFactory, you have to define some other + * abstractions, if you want to remain platform independent. + * + * + * <h3>...</h3> + * + * + * <h3>Resouces needed for HTML</h3> + * + * This chapter describes, how the form controls defined by HTML are + * implemented in Dw. Some of them do not refer to UI resources, but to + * other widgets, links to the respective documentations are provided + * here. + * + * <h4>Resouces created with \<INPUT\></h4> + * + * The HTML \<INPUT\> is always implemented by using UI + * resources. \<INPUT\> element has the following attributes: + * + * <table> + * <tr><th>Attribute <th>Implementation + * <tr><td>type <td>This defines the resource you have to instanciate. + * <tr><td>name <td>Not needed within Dw. + * <tr><td>value <td>The initial value is treated differently by different + * resources. + * <tr><td>checked <td>Parameter to + * dw::core::ui::ResourceFactory::createCheckButtonResource + * and dw::core::ui::ResourceFactory::createRadioButtonResource. + * <tr><td>disabled <td>This is provided for all resources by + * dw::core::ui::Resource::setEnabled. + * <tr><td>readonly <td>This is provided by + * dw::core::ui::TextResource::setEditable. + * <tr><td>size <td>This is handled by styles. + * <tr><td>maxlength <td>Parameter of + * dw::core::ui::ResourceFactory::createEntryResource. + * <tr><td>src <td>Handled by the caller (HTML parser). + * <tr><td>alt <td>Handled by the caller (HTML parser). + * <tr><td>usemap <td>Handled by the caller (HTML parser). + * <tr><td>ismap <td>Handled by the caller (HTML parser). + * <tr><td>tabindex <td>Not supported currently. + * <tr><td>accesskey <td>Not supported currently. + * <tr><td>onfocus <td>Not supported currently. + * <tr><td>onblur <td>Not supported currently. + * <tr><td>onselect <td>Not supported currently. + * <tr><td>onchange <td>Not supported currently. + * <tr><td>accept <td>Not supported currently. + * </table> + * + * For the different values of \em type, the following resources can be + * used: + * + * <table> + * <tr><th>Type <th>Resource + * <th>Factory Method + * <tr><td>text <td>dw::core::ui::EntryResource + * <td>dw::core::ui::ResourceFactory::createEntryResource + * <tr><td>password <td>dw::core::ui::EntryResource + * <td>dw::core::ui::ResourceFactory::createEntryResource + * <tr><td>checkbox <td>dw::core::ui::CheckButtonResource + * <td>dw::core::ui::ResourceFactory::createCheckButtonResource + * <tr><td>radio <td>dw::core::ui::RadioButtonResource + * <td>dw::core::ui::ResourceFactory::createRadioButtonResource + * <tr><td>submit <td>dw::core::ui::LabelButtonResource + * <td>dw::core::ui::ResourceFactory::createLabelButtonResource + * <tr><td>image <td>dw::core::ui::ComplexButtonResource + * <td>dw::core::ui::ResourceFactory::createComplexButtonResource, + * width a dw::Image inside and relief = false. + * <tr><td>reset <td>dw::core::ui::LabelButtonResource + * <td>dw::core::ui::ResourceFactory::createLabelButtonResource + * <tr><td>button <td>dw::core::ui::LabelButtonResource + * <td>dw::core::ui::ResourceFactory::createLabelButtonResource + * <tr><td>hidden <td>No rendering necessary. + * <td>- + * <tr><td>file <td>Not supported currently. + * <td>- + * </table> + * + * <h4>\<SELECT\>, \<OPTGROUP\>, and \<OPTION\></h4> + * + * \<SELECT\> is implemented either by dw::core::ui::OptionMenuResource + * (better suitable for \em size = 1 and single selection) or + * dw::core::ui::ListResource, which have a common base, + * dw::core::ui::SelectionResource. In the latter case, \em size must be + * specified via dw::core::style::Style. + * + * Factory methods are dw::core::ui::ResourceFactory::createListResource and + * dw::core::ui::ResourceFactory::createOptionMenuResource. + * + * \<OPTION\>'s are added via dw::core::ui::SelectionResource::addItem. + * + * \<OPTGROUP\> are created by using dw::core::ui::SelectionResource::pushGroup + * and dw::core::ui::SelectionResource::popGroup. + * + * For lists, the selection mode must be set in + * dw::core::ui::ResourceFactory::createListResource. + * + * <h4>\<TEXTAREA\></h4> + * + * \<TEXTAREA\> is implemented by dw::core::ui::MultiLineTextResource, + * the factory method is + * dw::core::ui::ResourceFactory::createMultiLineTextResource. + * dw::core::ui::TextResource::setEditable can be used, as for entries. + * + * <h4>\<BUTTON\></h4> + * + * For handling \<BUTTON\>, dw::core::ui::ComplexButtonResource should be used, + * with a dw::Textblock inside, and relief = true. The contents of \<BUTTON\> + * is then added to the dw::Textblock. + * + * \todo describe activation signal + */ +namespace ui { + +class Resource; + +/** + * \brief A widget for embedding UI widgets. + * + * \sa dw::core::ui + */ +class Embed: public Widget +{ + friend class Resource; + +private: + Resource *resource; + +protected: + void sizeRequestImpl (Requisition *requisition); + void getExtremesImpl (Extremes *extremes); + void sizeAllocateImpl (Allocation *allocation); + void enterNotifyImpl (core::EventCrossing *event); + void leaveNotifyImpl (core::EventCrossing *event); + +public: + static int CLASS_ID; + + Embed(Resource *resource); + ~Embed(); + + void setWidth (int width); + void setAscent (int ascent); + void setDescent (int descent); + void draw (View *view, Rectangle *area); + Iterator *iterator (Content::Type mask, bool atEnd); + void setStyle (style::Style *style); + + inline void setUsesHints () { setFlags (USES_HINTS); } + + inline Resource *getResource () { return resource; } +}; + +/** + * \brief Basic interface for all resources. + * + * \sa dw::core::ui + */ +class Resource +{ + friend class Embed; + +public: + /** + * \brief Receiver interface for the "activate" signal. + */ + class ActivateReceiver: public lout::signal::Receiver + { + public: + virtual void activate (Resource *resource) = 0; + virtual void enter (Resource *resource) = 0; + virtual void leave (Resource *resource) = 0; + }; + +private: + class ActivateEmitter: public lout::signal::Emitter + { + protected: + bool emitToReceiver (lout::signal::Receiver *receiver, int signalNo, + int argc, Object **argv); + public: + inline void connectActivate (ActivateReceiver *receiver) { + connect (receiver); } + void emitActivate (Resource *resource); + void emitEnter (Resource *resource); + void emitLeave (Resource *resource); + }; + + Embed *embed; + ActivateEmitter activateEmitter; + + void emitEnter (); + void emitLeave (); +protected: + inline void queueResize (bool extremesChanged) { + if (embed) embed->queueResize (0, extremesChanged); + } + + virtual Embed *getEmbed () { return embed; } + virtual void setEmbed (Embed *embed); + + inline void emitActivate () { + return activateEmitter.emitActivate (this); } + +public: + inline Resource () { embed = NULL; } + + virtual ~Resource (); + + virtual void sizeRequest (Requisition *requisition) = 0; + virtual void getExtremes (Extremes *extremes); + virtual void sizeAllocate (Allocation *allocation); + virtual void setWidth (int width); + virtual void setAscent (int ascent); + virtual void setDescent (int descent); + virtual void draw (View *view, Rectangle *area); + virtual Iterator *iterator (Content::Type mask, bool atEnd) = 0; + virtual void setStyle (style::Style *style); + + virtual bool isEnabled () = 0; + virtual void setEnabled (bool enabled) = 0; + + inline void connectActivate (ActivateReceiver *receiver) { + activateEmitter.connectActivate (receiver); } +}; + + +class ButtonResource: public Resource +{ +public: + /** + * \brief Receiver interface for the "clicked" signal. + */ + class ClickedReceiver: public lout::signal::Receiver + { + public: + virtual void clicked (ButtonResource *resource, int buttonNo, int x, + int y) = 0; + }; + +private: + class ClickedEmitter: public lout::signal::Emitter + { + protected: + bool emitToReceiver (lout::signal::Receiver *receiver, int signalNo, + int argc, Object **argv); + public: + inline void connectClicked (ClickedReceiver *receiver) { + connect (receiver); } + void emitClicked (ButtonResource *resource, int buttonNo, int x, int y); + }; + + ClickedEmitter clickedEmitter; + +protected: + inline void emitClicked (int buttonNo, int x, int y) { + return clickedEmitter.emitClicked (this, buttonNo, x, y); } + +public: + inline void connectClicked (ClickedReceiver *receiver) { + clickedEmitter.connectClicked (receiver); } +}; + +/** + * \brief Interface for labelled buttons resources. + */ +class LabelButtonResource: public ButtonResource +{ +public: + Iterator *iterator (Content::Type mask, bool atEnd); + + virtual const char *getLabel () = 0; + virtual void setLabel (const char *label) = 0; +}; + +class ComplexButtonResource: public ButtonResource +{ +private: + class LayoutReceiver: public Layout::Receiver + { + public: + ComplexButtonResource *resource; + + void canvasSizeChanged (int width, int ascent, int descent); + }; + + friend class LayoutReceiver; + LayoutReceiver layoutReceiver; + + Widget *widget; + +protected: + Layout *layout; + int click_x, click_y; + + void setEmbed (Embed *embed); + + virtual Platform *createPlatform () = 0; + virtual void setLayout (Layout *layout) = 0; + + virtual int reliefXThickness () = 0; + virtual int reliefYThickness () = 0; + + void init (Widget *widget); + +public: + ComplexButtonResource (); + ~ComplexButtonResource (); + + void sizeRequest (Requisition *requisition); + void getExtremes (Extremes *extremes); + void sizeAllocate (Allocation *allocation); + void setWidth (int width); + void setAscent (int ascent); + void setDescent (int descent); + Iterator *iterator (Content::Type mask, bool atEnd); + int getClickX () {return click_x;}; + int getClickY () {return click_y;}; +}; + +/** + * \brief Base interface for dw::core::ui::ListResource and + * dw::core::ui::OptionMenuResource. + */ +class SelectionResource: public Resource +{ +public: + virtual void addItem (const char *str, bool enabled, bool selected) = 0; + + virtual void pushGroup (const char *name, bool enabled) = 0; + virtual void popGroup () = 0; + + virtual int getNumberOfItems () = 0; + virtual const char *getItem (int index) = 0; + virtual bool isSelected (int index) = 0; +}; + +class ListResource: public SelectionResource +{ +public: + enum SelectionMode { + /** + * \brief Exactly one item is selected. + * + * If no item is selected initially, the first one is selected. + */ + SELECTION_EXACTLY_ONE, + + /** + * \brief Exactly one item is selected, except possibly at the beginning. + * + * If no item is selected initially, no one is selected automatically. + * The user may not unselect the only selected item. + */ + SELECTION_EXACTLY_ONE_BY_USER, + + /** + * \brief At most one item is selected. + * + * If no item is selected initially, no one is selected automatically. + * The user may unselect the only selected item. + */ + SELECTION_AT_MOST_ONE, + + /** + * \brief An arbitrary number of items may be selected. + */ + SELECTION_MULTIPLE + }; +}; + +class OptionMenuResource: public SelectionResource +{ +}; + +class TextResource: public Resource +{ +public: + Iterator *iterator (Content::Type mask, bool atEnd); + + virtual const char *getText () = 0; + virtual void setText (const char *text) = 0; + virtual bool isEditable () = 0; + virtual void setEditable (bool editable) = 0; +}; + +class EntryResource: public TextResource +{ +public: + enum { UNLIMITED_MAX_LENGTH = -1 }; +}; + +class MultiLineTextResource: public TextResource +{ +}; + + +class ToggleButtonResource: public Resource +{ +public: + virtual bool isActivated () = 0; + virtual void setActivated (bool activated) = 0; +}; + +class CheckButtonResource: public ToggleButtonResource +{ +public: + Iterator *iterator (Content::Type mask, bool atEnd); +}; + +class RadioButtonResource: public ToggleButtonResource +{ +public: + class GroupIterator + { + protected: + GroupIterator () { } + virtual ~GroupIterator (); + + public: + virtual bool hasNext () = 0; + virtual RadioButtonResource *getNext () = 0; + virtual void unref () = 0; + }; + + /** + * \brief Return an iterator, to access all radio button resources + * within the group. + */ + virtual GroupIterator *groupIterator () = 0; + + Iterator *iterator (Content::Type mask, bool atEnd); +}; + + +/** + * \brief A factory for the common resource. + */ +class ResourceFactory: public object::Object +{ +public: + virtual LabelButtonResource *createLabelButtonResource (const char *label) + = 0; + virtual ComplexButtonResource *createComplexButtonResource (Widget *widget, + bool relief) + = 0; + virtual ListResource *createListResource (ListResource::SelectionMode + selectionMode) = 0; + virtual OptionMenuResource *createOptionMenuResource () = 0; + virtual EntryResource *createEntryResource (int maxLength, + bool password) = 0; + virtual MultiLineTextResource *createMultiLineTextResource (int cols, + int rows) = 0; + virtual CheckButtonResource *createCheckButtonResource (bool activated) = 0; + virtual RadioButtonResource *createRadioButtonResource (RadioButtonResource + *groupedWith, + bool activated) = 0; +}; + +} // namespace ui +} // namespace core +} // namespace dw + +#endif // __DW_UI_HH__ |