aboutsummaryrefslogtreecommitdiff
path: root/dw/widget.hh
diff options
context:
space:
mode:
authorjcid <devnull@localhost>2008-09-24 18:44:40 +0200
committerjcid <devnull@localhost>2008-09-24 18:44:40 +0200
commitc377e06400f138325a9a9d43d91a9272691867a1 (patch)
tree49f3ca1c46af11a058a68714899d4137ec717618 /dw/widget.hh
parent642f9b3e747859a7256ea12fab9f9ed50aa9253a (diff)
- Moved the dw2 tree into dillo2's tree.
Diffstat (limited to 'dw/widget.hh')
-rw-r--r--dw/widget.hh465
1 files changed, 465 insertions, 0 deletions
diff --git a/dw/widget.hh b/dw/widget.hh
new file mode 100644
index 00000000..1bcfd032
--- /dev/null
+++ b/dw/widget.hh
@@ -0,0 +1,465 @@
+#ifndef __DW_WIDGET_HH__
+#define __DW_WIDGET_HH__
+
+#ifndef __INCLUDED_FROM_DW_CORE_HH__
+# error Do not include this file directly, use "core.hh" instead.
+#endif
+
+#include "../lout/identity.hh"
+
+/**
+ * \brief The type for callback functions.
+ */
+typedef void (*DW_Callback_t)(void *data);
+
+namespace dw {
+namespace core {
+
+/**
+ * \brief The base class of all dillo widgets.
+ *
+ * \sa\ref dw-overview, \ref dw-layout-widgets
+ */
+class Widget: public identity::IdentifiableObject
+{
+ friend class Layout;
+
+public:
+ class EventReceiver: public lout::signal::Receiver
+ {
+ public:
+ virtual bool buttonPress (Widget *widget, EventButton *event);
+ virtual bool buttonRelease (Widget *widget, EventButton *event);
+ virtual bool motionNotify (Widget *widget, EventMotion *event);
+ virtual void enterNotify (Widget *widget, EventCrossing *event);
+ virtual void leaveNotify (Widget *widget, EventCrossing *event);
+ };
+
+ /**
+ * \brief This receiver is for signals related to HTML pages.
+ *
+ * The \em link argument to all signals defines a number, which has
+ * been passed before, e.g. by setting dw::core::style::Style::x_link.
+ * When defining this number (e.g in dw::core::style::Style::x_link),
+ * and when receiving the signal, the caller must interpret these numbers
+ * in a consistent way. In the HTML link block, this number is an index
+ * to an array of URLs.
+ *
+ * \em link = -1 represents an undefined link.
+ *
+ * The \em img argument to all signals defines a number which has
+ * been passed before, e.g. by setting dw::core::style::Style::x_img.
+ * When defining this number (e.g in dw::core::style::Style::x_img),
+ * and when receiving the signal, the caller must interpret these numbers
+ * in a consistent way. In the HTML link block, this number is an index
+ * to an array of structures containing image information.
+ *
+ * \em img = -1 represents an undefined image.
+ *
+ * \em x and \em y define the coordinates within the link area. They are
+ * only used for server-side image maps, see dw::Image.
+ *
+ * \sa dw::Image, dw::Textblock
+ */
+ class LinkReceiver: public lout::signal::Receiver
+ {
+ public:
+ /**
+ * \brief Called, when a link is entered, left, or the position has
+ * changed.
+ *
+ * When a link is entered, this method is called with the respective
+ * arguments. When a link is left, this method is called with all
+ * three arguments (\em link, \em x, \em y) set to -1.
+ *
+ * When coordinates are supported, a change of the coordinates also
+ * causes emitting this signal.
+ */
+ virtual bool enter (Widget *widget, int link, int img, int x, int y);
+
+ /**
+ * \brief Called, when the user has pressed the mouse button on a
+ * link (but not yet released).
+ *
+ * The causing event is passed as \em event.
+ */
+ virtual bool press (Widget *widget, int link, int img, int x, int y,
+ EventButton *event);
+
+ /**
+ * \brief Called, when the user has released the mouse button on a
+ * link.
+ *
+ * The causing event is passed as \em event.
+ */
+ virtual bool release (Widget *widget, int link, int img, int x, int y,
+ EventButton *event);
+
+ /**
+ * \brief Called, when the user has clicked on a link.
+ *
+ * For mouse interaction, this is equivalent to "press" and "release"
+ * on the same link. In this case, \em event contains the "release"
+ * event.
+ *
+ * When activating links via keyboard is supported, only a "clicked"
+ * signal will be emitted, and \em event will be NULL.
+ */
+ virtual bool click (Widget *widget, int link, int img, int x, int y,
+ EventButton *event);
+ };
+
+private:
+ class EventEmitter: public lout::signal::Emitter
+ {
+ private:
+ enum { BUTTON_PRESS, BUTTON_RELEASE, MOTION_NOTIFY, ENTER_NOTIFY,
+ LEAVE_NOTIFY };
+
+ protected:
+ bool emitToReceiver (lout::signal::Receiver *receiver, int signalNo,
+ int argc, Object **argv);
+
+ public:
+ inline void connectEvent (EventReceiver *receiver)
+ { connect (receiver); }
+
+ bool emitButtonPress (Widget *widget, EventButton *event);
+ bool emitButtonRelease (Widget *widget, EventButton *event);
+ bool emitMotionNotify (Widget *widget, EventMotion *event);
+ void emitEnterNotify (Widget *widget, EventCrossing *event);
+ void emitLeaveNotify (Widget *widget, EventCrossing *event);
+ };
+
+ class LinkEmitter: public lout::signal::Emitter
+ {
+ private:
+ enum { ENTER, PRESS, RELEASE, CLICK };
+
+ protected:
+ bool emitToReceiver (lout::signal::Receiver *receiver, int signalNo,
+ int argc, Object **argv);
+
+ public:
+ inline void connectLink (LinkReceiver *receiver) { connect (receiver); }
+
+ bool emitEnter (Widget *widget, int link, int img, int x, int y);
+ bool emitPress (Widget *widget, int link, int img, int x, int y,
+ EventButton *event);
+ bool emitRelease (Widget *widget, int link, int img, int x, int y,
+ EventButton *event);
+ bool emitClick (Widget *widget, int link, int img, int x, int y,
+ EventButton *event);
+ };
+
+ EventEmitter eventEmitter;
+
+ style::Style *style;
+
+
+protected:
+ enum Flags {
+ /**
+ * \brief Set, when dw::core::Widget::requisition is not up to date
+ * anymore.
+ */
+ NEEDS_RESIZE = 1 << 0,
+
+ /**
+ * \brief Only used internally, set to enforce size allocation.
+ *
+ * (I've forgotten the case, for which this is necessary.)
+ */
+ NEEDS_ALLOCATE = 1 << 1,
+
+ /**
+ * \brief Set, when dw::core::Widget::extremes is not up to date
+ * anymore.
+ */
+ EXTREMES_CHANGED = 1 << 2,
+
+ /**
+ * \brief Set by the widget itself (in the constructor), when set...
+ * methods are implemented.
+ *
+ * Will hopefully be removed, after redesigning the size model.
+ */
+ USES_HINTS = 1 << 3,
+
+ /**
+ * \brief Set by the widget itself (in the constructor), when it contains
+ * some contents, e.g. an image, as opposed to a horizontal ruler.
+ *
+ * Will hopefully be removed, after redesigning the size model.
+ */
+ HAS_CONTENTS = 1 << 4,
+
+ /**
+ * \brief Set, when a widget was already once allocated,
+ *
+ * The dw::Image widget uses this flag, see dw::Image::setBuffer.
+ */
+ WAS_ALLOCATED = 1 << 5,
+ };
+
+private:
+ /**
+ * \brief The parent widget, NULL for top-level widgets.
+ */
+ Widget *parent;
+
+ Flags flags;
+
+ /**
+ * \brief Size_request() stores the result of the last call of
+ * size_request_impl().
+ *
+ * Do not read this directly, but call size_request().
+ */
+ Requisition requisition;
+
+ /**
+ * \brief Analogue to dw::core::Widget::requisition.
+ */
+ Extremes extremes;
+
+ /**
+ * \brief See dw::core::Widget::setBgColor().
+ */
+ style::Color *bgColor;
+
+ /**
+ * \brief See dw::core::Widget::setButtonSensitive().
+ */
+ bool buttonSensitive;
+
+ /**
+ * \brief See dw::core::Widget::setButtonSensitive().
+ */
+ bool buttonSensitiveSet;
+
+public:
+ /**
+ * \brief This value is defined by the parent widget, and used for
+ * incremential resizing.
+ *
+ * See documentation for an explanation.
+ */
+ int parentRef;
+
+protected:
+ LinkEmitter linkEmitter;
+
+ /**
+ * \brief The current allocation: size and position, always relative to the
+ * canvas.
+ */
+ Allocation allocation;
+
+ inline int getHeight () { return allocation.ascent + allocation.descent; }
+ inline int getContentWidth() { return allocation.width
+ - style->boxDiffWidth (); }
+ inline int getContentHeight() { return getHeight ()
+ - style->boxDiffHeight (); }
+
+ Layout *layout;
+
+ inline void setFlags (Flags f) { flags = (Flags)(flags | f); }
+ inline void unsetFlags (Flags f) { flags = (Flags)(flags & ~f); }
+
+
+ inline void queueDraw ()
+ {
+ queueDrawArea (0, 0, allocation.width, getHeight());
+ }
+ void queueDrawArea (int x, int y, int width, int height);
+ void queueResize (int ref, bool extremesChanged);
+
+ /**
+ * \brief See \ref dw-widget-sizes.
+ */
+ virtual void sizeRequestImpl (Requisition *requisition) = 0;
+
+ /**
+ * \brief See \ref dw-widget-sizes.
+ */
+ virtual void getExtremesImpl (Extremes *extremes);
+
+ /**
+ * \brief See \ref dw-widget-sizes.
+ */
+ virtual void sizeAllocateImpl (Allocation *allocation);
+
+ /**
+ * \brief Called after sizeAllocateImpl() to redraw necessary areas.
+ * By default the whole widget is redrawn.
+ */
+ virtual void resizeDrawImpl () { queueDraw (); };
+
+ /**
+ * \brief See \ref dw-widget-sizes.
+ */
+ virtual void markSizeChange (int ref);
+
+ /**
+ * \brief See \ref dw-widget-sizes.
+ */
+ virtual void markExtremesChange (int ref);
+
+ virtual bool buttonPressImpl (EventButton *event);
+ virtual bool buttonReleaseImpl (EventButton *event);
+ virtual bool motionNotifyImpl (EventMotion *event);
+ virtual void enterNotifyImpl (EventCrossing *event);
+ virtual void leaveNotifyImpl (EventCrossing *event);
+
+ inline char *addAnchor (const char* name)
+ { return layout->addAnchor (this, name); }
+
+ inline char *addAnchor (const char* name, int y)
+ { return layout->addAnchor (this, name, y); }
+
+ inline void changeAnchor (char* name, int y)
+ { layout->changeAnchor (this, name, y); }
+
+ inline void removeAnchor (char* name)
+ { layout->removeAnchor (this, name); }
+
+ //inline void updateBgColor () { layout->updateBgColor (); }
+
+ inline void setCursor (style::Cursor cursor)
+ { layout->setCursor (cursor); }
+
+ inline bool selectionButtonPress (Iterator *it, int charPos, int linkNo,
+ EventButton *event, bool withinContent)
+ { return layout->selectionState.buttonPress (it, charPos, linkNo, event,
+ withinContent); }
+
+ inline bool selectionButtonRelease (Iterator *it, int charPos, int linkNo,
+ EventButton *event, bool withinContent)
+ { return layout->selectionState.buttonRelease (it, charPos, linkNo, event,
+ withinContent); }
+
+ inline bool selectionButtonMotion (Iterator *it, int charPos, int linkNo,
+ EventMotion *event, bool withinContent)
+ { return layout->selectionState.buttonMotion (it, charPos, linkNo, event,
+ withinContent); }
+
+ inline bool selectionHandleEvent (SelectionState::EventType eventType,
+ Iterator *it, int charPos, int linkNo,
+ MousePositionEvent *event,
+ bool withinContent)
+ { return layout->selectionState.handleEvent (eventType, it, charPos, linkNo,
+ event, withinContent); }
+
+private:
+ void *deleteCallbackData;
+ DW_Callback_t deleteCallbackFunc;
+
+public:
+ inline void setDeleteCallback(DW_Callback_t func, void *data)
+ { deleteCallbackFunc = func; deleteCallbackData = data; }
+
+public:
+ static int CLASS_ID;
+
+ Widget ();
+ ~Widget ();
+
+ inline bool needsResize () { return flags & NEEDS_RESIZE; }
+ inline bool needsAllocate () { return flags & NEEDS_ALLOCATE; }
+ inline bool extremesChanged () { return flags & EXTREMES_CHANGED; }
+ inline bool wasAllocated () { return flags & WAS_ALLOCATED; }
+
+ inline void connectEvent (EventReceiver *receiver)
+ { eventEmitter.connectEvent (receiver); }
+
+ inline void connectLink (LinkReceiver *receiver)
+ { linkEmitter.connectLink (receiver); }
+
+ inline bool emitLinkEnter (int link, int img, int x, int y)
+ { return linkEmitter.emitEnter (this, link, img, x, y); }
+
+ inline bool emitLinkPress (int link, int img,
+ int x, int y, EventButton *event)
+ { return linkEmitter.emitPress (this, link, img, x, y, event); }
+
+ inline bool emitLinkRelease (int link, int img,
+ int x, int y, EventButton *event)
+ { return linkEmitter.emitRelease (this, link, img, x, y, event); }
+
+ inline bool emitLinkClick (int link, int img,
+ int x, int y, EventButton *event)
+ { return linkEmitter.emitClick (this, link, img, x, y, event); }
+
+ inline bool usesHints () { return flags & USES_HINTS; }
+ inline bool hasContents () { return flags & HAS_CONTENTS; }
+
+ void setParent (Widget *parent);
+
+ inline style::Style *getStyle () { return style; }
+ /** \todo I do not like this. */
+ inline Allocation *getAllocation () { return &allocation; }
+
+ void sizeRequest (Requisition *requisition);
+ void getExtremes (Extremes *extremes);
+ void sizeAllocate (Allocation *allocation);
+ virtual void setWidth (int width);
+ virtual void setAscent (int ascent);
+ virtual void setDescent (int descent);
+
+ bool intersects (Rectangle *area, Rectangle *intersection);
+
+ /** Area is given in widget coordinates. */
+ virtual void draw (View *view, Rectangle *area) = 0;
+
+ bool buttonPress (EventButton *event);
+ bool buttonRelease (EventButton *event);
+ bool motionNotify (EventMotion *event);
+ void enterNotify (EventCrossing *event);
+ void leaveNotify (EventCrossing *event);
+
+ virtual void setStyle (style::Style *style);
+ void setBgColor (style::Color *bgColor);
+ style::Color *getBgColor ();
+
+ void drawBox (View *view, style::Style *style, Rectangle *area,
+ int x, int y, int width, int height, bool inverse);
+ void drawWidgetBox (View *view, Rectangle *area, bool inverse);
+ void drawSelected (View *view, Rectangle *area);
+
+ void setButtonSensitive (bool buttonSensitive);
+ inline bool isButtonSensitive () { return buttonSensitive; }
+
+ inline Widget *getParent () { return parent; }
+ Widget *getTopLevel ();
+ int getLevel ();
+ Widget *getNearestCommonAncestor (Widget *otherWidget);
+
+ inline Layout *getLayout () { return layout; }
+
+ virtual Widget *getWidgetAtPoint (int x, int y, int level);
+
+ void scrollTo (HPosition hpos, VPosition vpos,
+ int x, int y, int width, int height);
+
+ /**
+ * \brief Return an iterator for this widget.
+ *
+ * \em mask can narrow the types returned by the iterator, this can
+ * enhance performance quite much, e.g. when only searching for child
+ * widgets.
+ *
+ * With \em atEnd == false, the iterator starts \em before the beginning,
+ * i.e. the first call of dw::core::Iterator::next will let the iterator
+ * point on the first piece of contents. Likewise, With \em atEnd == true,
+ * the iterator starts \em after the last piece of contents, call
+ * dw::core::Iterator::prev in this case.
+ */
+ virtual Iterator *iterator (Content::Type mask, bool atEnd) = 0;
+ virtual void removeChild (Widget *child);
+};
+
+} // namespace dw
+} // namespace core
+
+#endif // __DW_WIDGET_HH__