#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", dir="both", * 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 * *
[\ref uml-legend "legend"]
* * there are several levels: * *
    *
  1. The Dw widget is dw::core::ui::Embed. It delegates most to * dw::core::ui::Resource, which has similar methods like * dw::core::Widget. * *
  2. 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 * *
  3. These sub classes are then fully implemented in a platform specific * way. For an example, look at dw::fltk::ui. *
* * 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. * * *

...

* * *

Resources needed for HTML

* * 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. * *

Resources created with \

* * The HTML \ is always implemented by using UI * resources. \ element has the following attributes: * * *
Attribute Implementation *
type This defines the resource you have to instantiate. *
name Not needed within Dw. *
value The initial value is treated differently by different * resources. *
checked Parameter to * dw::core::ui::ResourceFactory::createCheckButtonResource * and dw::core::ui::ResourceFactory::createRadioButtonResource. *
disabled This is provided for all resources by * dw::core::ui::Resource::setEnabled. *
readonly This is provided by * dw::core::ui::TextResource::setEditable. *
size This is handled by styles. *
maxlength Parameter of * dw::core::ui::ResourceFactory::createEntryResource. *
src Handled by the caller (HTML parser). *
alt Handled by the caller (HTML parser). *
usemap Handled by the caller (HTML parser). *
ismap Handled by the caller (HTML parser). *
tabindex Not supported currently. *
accesskey Not supported currently. *
onfocus Not supported currently. *
onblur Not supported currently. *
onselect Not supported currently. *
onchange Not supported currently. *
accept Not supported currently. *
* * For the different values of \em type, the following resources can be * used: * * *
Type Resource * Factory Method *
text dw::core::ui::EntryResource * dw::core::ui::ResourceFactory::createEntryResource *
password dw::core::ui::EntryResource * dw::core::ui::ResourceFactory::createEntryResource *
checkbox dw::core::ui::CheckButtonResource * dw::core::ui::ResourceFactory::createCheckButtonResource *
radio dw::core::ui::RadioButtonResource * dw::core::ui::ResourceFactory::createRadioButtonResource *
submit dw::core::ui::LabelButtonResource * dw::core::ui::ResourceFactory::createLabelButtonResource *
image dw::core::ui::ComplexButtonResource * dw::core::ui::ResourceFactory::createComplexButtonResource, * width a dw::Image inside and relief = false. *
reset dw::core::ui::LabelButtonResource * dw::core::ui::ResourceFactory::createLabelButtonResource *
button dw::core::ui::LabelButtonResource * dw::core::ui::ResourceFactory::createLabelButtonResource *
hidden No rendering necessary. * - *
file Not supported currently. * - *
* *

\, \, and \

* * \ 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. * * \'s are added via dw::core::ui::SelectionResource::addItem. * * \ 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. * *

\

* * \ 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. * *

\

* * For handling \, dw::core::ui::ComplexButtonResource should be used, * with a dw::Textblock inside, and relief = true. The contents of \ * 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 sizeRequestSimpl (Requisition *requisition); void getExtremesSimpl (Extremes *extremes); void sizeAllocateImpl (Allocation *allocation); int getAvailWidthOfChild (Widget *child, bool forceValue); int getAvailHeightOfChild (Widget *child, bool forceValue); void correctRequisitionOfChild (Widget *child, Requisition *requisition, void (*splitHeightFun) (int, int*, int*), bool allowDecreaseWidth, bool allowDecreaseHeight); void correctExtremesOfChild (Widget *child, Extremes *extremes, bool useAdjustmentWidth); void containerSizeChangedForChildren (); void enterNotifyImpl (core::EventCrossing *event); void leaveNotifyImpl (core::EventCrossing *event); bool buttonPressImpl (core::EventButton *event); public: static int CLASS_ID; Embed(Resource *resource); ~Embed(); void setDisplayed (bool displayed); void setEnabled (bool enabled); void draw (View *view, Rectangle *area, DrawingContext *context); Iterator *iterator (Content::Type mask, bool atEnd); void setStyle (style::Style *style); inline Resource *getResource () { return resource; } inline void correctReqWidthOfChildNoRec (Widget *child, Requisition *requisition, bool allowDecreaseWidth) { Widget::correctReqWidthOfChild (child, requisition, allowDecreaseWidth); } inline void correctReqHeightOfChildNoRec (Widget *child, Requisition *requisition, void (*splitHeightFun) (int, int*, int*), bool allowDecreaseHeight) { Widget::correctReqHeightOfChild (child, requisition, splitHeightFun, allowDecreaseHeight); } virtual void correctExtremesOfChildNoRec (Widget *child, Extremes *extremes, bool useAdjustmentWidth) { Widget::correctExtremesOfChild (child, extremes, useAdjustmentWidth); } }; /** * \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; }; /** * \brief Receiver interface for the "clicked" signal. */ class ClickedReceiver: public lout::signal::Receiver { public: virtual void clicked (Resource *resource, EventButton *event) = 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); }; 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 (Resource *resource, EventButton *event); }; Embed *embed; ActivateEmitter activateEmitter; ClickedEmitter clickedEmitter; 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); } inline void emitClicked (EventButton *event) { clickedEmitter.emitClicked (this, event); } public: inline Resource () { embed = NULL; DBG_OBJ_CREATE ("dw::core::ui::Resource"); } virtual ~Resource (); virtual void sizeRequest (Requisition *requisition) = 0; virtual void getExtremes (Extremes *extremes); virtual void sizeAllocate (Allocation *allocation); virtual int getAvailWidthOfChild (Widget *child, bool forceValue); virtual int getAvailHeightOfChild (Widget *child, bool forceValue); virtual void correctRequisitionOfChild (Widget *child, Requisition *requisition, void (*splitHeightFun) (int, int*, int*), bool allowDecreaseWidth, bool allowDecreaseHeight); virtual void correctExtremesOfChild (Widget *child, Extremes *extremes, bool useAdjustmentWidth); virtual void containerSizeChangedForChildren (); virtual void setDisplayed (bool displayed); virtual void draw (View *view, Rectangle *area, DrawingContext *context); 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); } inline void connectClicked (ClickedReceiver *receiver) { clickedEmitter.connectClicked (receiver); } }; class ButtonResource: public Resource {}; /** * \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 resizeQueued (bool extremesChanged); }; friend class LayoutReceiver; LayoutReceiver layoutReceiver; Widget *childWidget; 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); int getAvailWidthOfChild (Widget *child, bool forceValue); int getAvailHeightOfChild (Widget *child, bool forceValue); void correctRequisitionOfChild (Widget *child, Requisition *requisition, void (*splitHeightFun) (int, int*, int*), bool allowDecreaseWidth, bool allowDecreaseHeight); void correctExtremesOfChild (Widget *child, Extremes *extremes, bool useAdjustmentWidth); void containerSizeChangedForChildren (); 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 setItem (int index, bool selected) = 0; virtual void pushGroup (const char *name, bool enabled) = 0; virtual void popGroup () = 0; virtual int getNumberOfItems () = 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_SIZE = -1 }; virtual void setMaxLength (int maxlen) = 0; }; 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 lout::object::Object { public: virtual LabelButtonResource *createLabelButtonResource (const char *label) = 0; virtual ComplexButtonResource *createComplexButtonResource (Widget *widget, bool relief) = 0; virtual ListResource *createListResource (ListResource::SelectionMode selectionMode, int rows) = 0; virtual OptionMenuResource *createOptionMenuResource () = 0; virtual EntryResource *createEntryResource (int size, bool password, const char *label, const char *placeholder) = 0; virtual MultiLineTextResource *createMultiLineTextResource (int cols, int rows, const char *placeholder) = 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__