Initial import of Dillo
This commit is contained in:
302
dw/oofawarewidget.hh
Normal file
302
dw/oofawarewidget.hh
Normal file
@ -0,0 +1,302 @@
|
||||
#ifndef __DW_OOFAWAREWIDGET_HH__
|
||||
#define __DW_OOFAWAREWIDGET_HH__
|
||||
|
||||
#include "core.hh"
|
||||
#include "outofflowmgr.hh"
|
||||
|
||||
namespace dw {
|
||||
|
||||
namespace oof {
|
||||
|
||||
/**
|
||||
* \brief Base class for widgets which can act as container and
|
||||
* generator for widgets out of flow.
|
||||
*
|
||||
* (Perhaps it should be diffenciated between the two roles, container
|
||||
* and generator, but this would make multiple inheritance necessary.)
|
||||
*
|
||||
* See \ref dw-out-of-flow for an overview.
|
||||
*
|
||||
* Requirements for sub classes (in most cases refer to dw::Textblock
|
||||
* as a good example):
|
||||
*
|
||||
* - A sub class should at least take care to call these methods at the
|
||||
* respective points:
|
||||
*
|
||||
* - dw::oof::OOFAwareWidget::correctRequisitionByOOF (from
|
||||
* dw::core::Widget::getExtremesImpl)
|
||||
* - dw::oof::OOFAwareWidget::correctExtremesByOOF (from
|
||||
* dw::core::Widget::sizeRequestImpl)
|
||||
* - dw::oof::OOFAwareWidget::sizeAllocateStart
|
||||
* - dw::oof::OOFAwareWidget::sizeAllocateEnd (latter two from
|
||||
* dw::core::Widget::sizeAllocateImpl)
|
||||
* - dw::oof::OOFAwareWidget::containerSizeChangedForChildrenOOF
|
||||
* (from dw::core::Widget::containerSizeChangedForChildren)
|
||||
* - dw::oof::OOFAwareWidget::drawOOF (from dw::core::Widget::draw)
|
||||
* - dw::oof::OOFAwareWidget::getWidgetOOFAtPoint (from
|
||||
* dw::core::Widget::getWidgetAtPoint)
|
||||
*
|
||||
* - Implementations of dw::core::Widget::getAvailWidthOfChild and
|
||||
* dw::core::Widget::getAvailHeightOfChild have to distinguish
|
||||
* between widgets in flow and out of flow; general pattern:
|
||||
*
|
||||
* \code
|
||||
* if (isWidgetOOF (child) && getWidgetOutOfFlowMgr(child) &&
|
||||
* getWidgetOutOfFlowMgr(child)->dealingWithSizeOfChild (child))
|
||||
* width =
|
||||
* getWidgetOutOfFlowMgr(child)->getAvailWidthOfChild (child,forceValue);
|
||||
* else {
|
||||
* // ... specific implementation ...
|
||||
* \endcode
|
||||
*
|
||||
* See also implementations of dw::Textblock and dw::Table. (Open
|
||||
* issue: What about dw::core::Widget::correctRequisitionOfChild and
|
||||
* dw::core::Widget::correctExtremesOfChild? Currently, all widgets
|
||||
* are used the default implementation.)
|
||||
*
|
||||
* - Iterators have to consider widgets out of flow;
|
||||
* dw::oof::OOFAwareWidget::OOFAwareWidgetIterator is recommended as
|
||||
* base class.
|
||||
*
|
||||
* - dw::core::Widget::parentRef has to be set for widgets in flow; if
|
||||
* not used further, a simple *makeParentRefInFlow(0)* is sufficient
|
||||
* (as dw::Table::addCell does). Widgets which are only containers,
|
||||
* but not generators, do not have to care about widgets out of
|
||||
* flow in this regard.
|
||||
*
|
||||
* For both generators and containers of floats (which is only
|
||||
* implemented by dw::Textblock) it gets a bit more complicated.
|
||||
*
|
||||
* \todo Currently, on the level of dw::oof::OOFAwareWidget, nothing
|
||||
* is done about dw::core::Widget::markSizeChange and
|
||||
* dw::core::Widget::markExtremesChange. This does not matter, though:
|
||||
* dw::Textblock takes care of these, and dw::Table is only connected
|
||||
* to subclasses of dw::oof::OOFPositionedMgr, which do care about
|
||||
* these. However, this should be considered for completeness.
|
||||
*/
|
||||
class OOFAwareWidget: public core::Widget
|
||||
{
|
||||
protected:
|
||||
enum { OOFM_FLOATS, OOFM_ABSOLUTE, OOFM_RELATIVE, OOFM_FIXED, NUM_OOFM };
|
||||
static const char *OOFM_NAME[NUM_OOFM];
|
||||
enum { PARENT_REF_OOFM_BITS = 3,
|
||||
PARENT_REF_OOFM_MASK = (1 << PARENT_REF_OOFM_BITS) - 1 };
|
||||
|
||||
class OOFAwareWidgetIterator: public core::Iterator
|
||||
{
|
||||
private:
|
||||
enum { NUM_SECTIONS = NUM_OOFM + 1 };
|
||||
int sectionIndex; // 0 means in flow, otherwise OOFM index + 1
|
||||
int index;
|
||||
|
||||
int numParts (int sectionIndex, int numContentsInFlow = -1);
|
||||
void getPart (int sectionIndex, int index, core::Content *content);
|
||||
|
||||
protected:
|
||||
virtual int numContentsInFlow () = 0;
|
||||
virtual void getContentInFlow (int index, core::Content *content) = 0;
|
||||
|
||||
void setValues (int sectionIndex, int index);
|
||||
inline void cloneValues (OOFAwareWidgetIterator *other)
|
||||
{ other->setValues (sectionIndex, index); }
|
||||
|
||||
inline bool inFlow () { return sectionIndex == 0; }
|
||||
inline int getInFlowIndex () { assert (inFlow ()); return index; }
|
||||
void highlightOOF (int start, int end, core::HighlightLayer layer);
|
||||
void unhighlightOOF (int direction, core::HighlightLayer layer);
|
||||
void getAllocationOOF (int start, int end, core::Allocation *allocation);
|
||||
|
||||
public:
|
||||
OOFAwareWidgetIterator (OOFAwareWidget *widget, core::Content::Type mask,
|
||||
bool atEnd, int numContentsInFlow);
|
||||
|
||||
void intoStringBuffer(lout::misc::StringBuffer *sb);
|
||||
int compareTo(lout::object::Comparable *other);
|
||||
|
||||
bool next ();
|
||||
bool prev ();
|
||||
};
|
||||
|
||||
inline bool isParentRefOOF (int parentRef)
|
||||
{ return parentRef != -1 && (parentRef & PARENT_REF_OOFM_MASK); }
|
||||
|
||||
inline int makeParentRefInFlow (int inFlowSubRef)
|
||||
{ return (inFlowSubRef << PARENT_REF_OOFM_BITS); }
|
||||
inline int getParentRefInFlowSubRef (int parentRef)
|
||||
{ assert (!isParentRefOOF (parentRef));
|
||||
return parentRef >> PARENT_REF_OOFM_BITS; }
|
||||
|
||||
inline int makeParentRefOOF (int oofmIndex, int oofmSubRef)
|
||||
{ return (oofmSubRef << PARENT_REF_OOFM_BITS) | (oofmIndex + 1); }
|
||||
inline int getParentRefOOFSubRef (int parentRef)
|
||||
{ assert (isParentRefOOF (parentRef));
|
||||
return parentRef >> PARENT_REF_OOFM_BITS; }
|
||||
inline int getParentRefOOFIndex (int parentRef)
|
||||
{ assert (isParentRefOOF (parentRef));
|
||||
return (parentRef & PARENT_REF_OOFM_MASK) - 1; }
|
||||
inline oof::OutOfFlowMgr *getParentRefOutOfFlowMgr (int parentRef)
|
||||
{ return outOfFlowMgr[getParentRefOOFIndex (parentRef)]; }
|
||||
|
||||
inline bool isWidgetOOF (Widget *widget)
|
||||
{ return isParentRefOOF (widget->parentRef); }
|
||||
|
||||
inline int getWidgetInFlowSubRef (Widget *widget)
|
||||
{ return getParentRefInFlowSubRef (widget->parentRef); }
|
||||
|
||||
inline int getWidgetOOFSubRef (Widget *widget)
|
||||
{ return getParentRefOOFSubRef (widget->parentRef); }
|
||||
inline int getWidgetOOFIndex (Widget *widget)
|
||||
{ return getParentRefOOFIndex (widget->parentRef); }
|
||||
inline oof::OutOfFlowMgr *getWidgetOutOfFlowMgr (Widget *widget)
|
||||
{ return getParentRefOutOfFlowMgr (widget->parentRef); }
|
||||
|
||||
OOFAwareWidget *oofContainer[NUM_OOFM];
|
||||
OutOfFlowMgr *outOfFlowMgr[NUM_OOFM];
|
||||
core::Requisition requisitionWithoutOOF;
|
||||
|
||||
inline OutOfFlowMgr *searchOutOfFlowMgr (int oofmIndex)
|
||||
{ return oofContainer[oofmIndex] ?
|
||||
oofContainer[oofmIndex]->outOfFlowMgr[oofmIndex] : NULL; }
|
||||
|
||||
static int getOOFMIndex (Widget *widget);
|
||||
|
||||
void initOutOfFlowMgrs ();
|
||||
void correctRequisitionByOOF (core::Requisition *requisition,
|
||||
void (*splitHeightFun) (int, int*, int*));
|
||||
void correctExtremesByOOF (core::Extremes *extremes);
|
||||
void sizeAllocateStart (core::Allocation *allocation);
|
||||
void sizeAllocateEnd ();
|
||||
void containerSizeChangedForChildrenOOF ();
|
||||
|
||||
virtual void drawLevel (core::View *view, core::Rectangle *area, int level,
|
||||
core::DrawingContext *context);
|
||||
void drawOOF (core::View *view, core::Rectangle *area,
|
||||
core::DrawingContext *context);
|
||||
|
||||
Widget *getWidgetAtPoint (int x, int y,
|
||||
core::GettingWidgetAtPointContext *context);
|
||||
virtual Widget *getWidgetAtPointLevel (int x, int y, int level,
|
||||
core::GettingWidgetAtPointContext
|
||||
*context);
|
||||
Widget *getWidgetOOFAtPoint (int x, int y,
|
||||
core::GettingWidgetAtPointContext *context);
|
||||
|
||||
static bool isOOFContainer (Widget *widget, int oofmIndex);
|
||||
|
||||
void notifySetAsTopLevel();
|
||||
void notifySetParent();
|
||||
|
||||
void removeChild (Widget *child);
|
||||
|
||||
virtual bool adjustExtraSpaceWhenCorrectingRequisitionByOOF ();
|
||||
|
||||
public:
|
||||
enum {
|
||||
SL_START, SL_BACKGROUND, SL_SC_BOTTOM, SL_IN_FLOW, SL_OOF_REF,
|
||||
SL_OOF_CONT, SL_SC_TOP, SL_END };
|
||||
|
||||
static int CLASS_ID;
|
||||
|
||||
OOFAwareWidget ();
|
||||
~OOFAwareWidget ();
|
||||
|
||||
static const char *stackingLevelText (int level);
|
||||
|
||||
static inline bool testStyleFloat (core::style::Style *style)
|
||||
{ return style->vloat != core::style::FLOAT_NONE; }
|
||||
|
||||
static inline bool testStyleAbsolutelyPositioned (core::style::Style *style)
|
||||
{ return IMPL_POS && style->position == core::style::POSITION_ABSOLUTE; }
|
||||
static inline bool testStyleFixedlyPositioned (core::style::Style *style)
|
||||
{ return IMPL_POS && style->position == core::style::POSITION_FIXED; }
|
||||
static inline bool testStyleRelativelyPositioned (core::style::Style *style)
|
||||
{ return IMPL_POS && style->position == core::style::POSITION_RELATIVE; }
|
||||
|
||||
static inline bool testStylePositioned (core::style::Style *style)
|
||||
{ return testStyleAbsolutelyPositioned (style) ||
|
||||
testStyleRelativelyPositioned (style) ||
|
||||
testStyleFixedlyPositioned (style); }
|
||||
|
||||
static inline bool testStyleOutOfFlow (core::style::Style *style)
|
||||
{ // Second part is equivalent to testStylePositioned(), but we still keep
|
||||
// the two separately.
|
||||
return testStyleFloat (style) || testStyleAbsolutelyPositioned (style)
|
||||
|| testStyleRelativelyPositioned (style)
|
||||
|| testStyleFixedlyPositioned (style); }
|
||||
|
||||
static inline bool testWidgetFloat (Widget *widget)
|
||||
{ return testStyleFloat (widget->getStyle ()); }
|
||||
|
||||
static inline bool testWidgetAbsolutelyPositioned (Widget *widget)
|
||||
{ return testStyleAbsolutelyPositioned (widget->getStyle ()); }
|
||||
static inline bool testWidgetFixedlyPositioned (Widget *widget)
|
||||
{ return testStyleFixedlyPositioned (widget->getStyle ()); }
|
||||
static inline bool testWidgetRelativelyPositioned (Widget *widget)
|
||||
{ return testStyleRelativelyPositioned (widget->getStyle ()); }
|
||||
|
||||
static inline bool testWidgetPositioned (Widget *widget)
|
||||
{ return testStylePositioned (widget->getStyle ()); }
|
||||
|
||||
static inline bool testWidgetOutOfFlow (Widget *widget)
|
||||
{ return testStyleOutOfFlow (widget->getStyle ()); }
|
||||
|
||||
inline core::Requisition *getRequisitionWithoutOOF ()
|
||||
{ return &requisitionWithoutOOF; }
|
||||
|
||||
bool doesWidgetOOFInterruptDrawing (Widget *widget);
|
||||
|
||||
void draw (core::View *view, core::Rectangle *area,
|
||||
core::DrawingContext *context);
|
||||
|
||||
/**
|
||||
* Update content in flow, down from `ref`. Uses e. g. when floats sizes have
|
||||
* changed.
|
||||
*/
|
||||
virtual void updateReference (int ref);
|
||||
|
||||
/**
|
||||
* Called by an implementation of dw::oof::OutOfFlowMgr (actually only
|
||||
* OOFPosRelMgr) for the generator of a widget out of flow, when the
|
||||
* reference size has changed. (The size of the reference is 0 * 0 for all
|
||||
* other implementations of dw::oof::OutOfFlowMgr.)
|
||||
*/
|
||||
virtual void widgetRefSizeChanged (int externalIndex);
|
||||
|
||||
/**
|
||||
* Called by an implementation of dw::oof::OutOfFlowMgr when the size of the
|
||||
* container has changed, typically in sizeAllocateEnd.
|
||||
*/
|
||||
virtual void oofSizeChanged (bool extremesChanged);
|
||||
|
||||
/**
|
||||
* Return position relative to container, not regarding
|
||||
* margin/border/padding, Called by OOFFloatsMgr to position floats.
|
||||
*/
|
||||
virtual int getGeneratorX (int oofmIndex);
|
||||
|
||||
/**
|
||||
* Return position relative to container, not regarding
|
||||
* margin/border/padding, Called by OOFFloatsMgr to position floats.
|
||||
*/
|
||||
virtual int getGeneratorY (int oofmIndex);
|
||||
|
||||
/**
|
||||
* Return width including margin/border/padding Called by OOFFloatsMgr to
|
||||
* position floats.
|
||||
*/
|
||||
virtual int getGeneratorWidth ();
|
||||
|
||||
virtual int getMaxGeneratorWidth ();
|
||||
|
||||
virtual bool usesMaxGeneratorWidth ();
|
||||
|
||||
virtual bool isPossibleOOFContainer (int oofmIndex);
|
||||
|
||||
virtual bool isPossibleOOFContainerParent (int oofmIndex);
|
||||
};
|
||||
|
||||
} // namespace oof
|
||||
|
||||
} // namespace dw
|
||||
|
||||
#endif // __DW_OOFAWAREWIDGET_HH__
|
||||
Reference in New Issue
Block a user