aboutsummaryrefslogtreecommitdiff
path: root/dw/ui.hh
diff options
context:
space:
mode:
Diffstat (limited to 'dw/ui.hh')
-rw-r--r--dw/ui.hh564
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__