aboutsummaryrefslogtreecommitdiff
path: root/dw/outofflowmgr.hh
diff options
context:
space:
mode:
Diffstat (limited to 'dw/outofflowmgr.hh')
-rw-r--r--dw/outofflowmgr.hh235
1 files changed, 235 insertions, 0 deletions
diff --git a/dw/outofflowmgr.hh b/dw/outofflowmgr.hh
new file mode 100644
index 00000000..f312ee0f
--- /dev/null
+++ b/dw/outofflowmgr.hh
@@ -0,0 +1,235 @@
+#ifndef __DW_OUTOFFLOWMGR_HH__
+#define __DW_OUTOFFLOWMGR_HH__
+
+#include "core.hh"
+
+namespace dw {
+
+class Textblock;
+
+/**
+ * \brief Represents additional data for containing blocks.
+ */
+class OutOfFlowMgr
+{
+private:
+ enum Side { LEFT, RIGHT };
+
+ Textblock *containingBlock;
+
+ // These two values are set by sizeAllocateStart(), and they are
+ // accessable also within sizeAllocateEnd(), and also for the
+ // containing block, for which allocation and WAS_ALLOCATED is set
+ // *after* sizeAllocateEnd(). See the two inline functions below
+ // for usage.
+ core::Allocation containingBlockAllocation;
+ bool containingBlockWasAllocated;
+
+ class Float: public lout::object::Comparable
+ {
+ private:
+ OutOfFlowMgr *oofm;
+
+ public:
+ core::Widget *widget;
+ Textblock *generatingBlock;
+ int yReq, yReal; // relative to generator, not container
+ int index, mark;
+ core::Requisition size;
+ bool dirty;
+
+ Float (OutOfFlowMgr *oofm, core::Widget *widget,
+ Textblock *generatingBlock);
+
+ void intoStringBuffer(lout::misc::StringBuffer *sb);
+ int compareTo(Comparable *other);
+
+ int yForTextblock (Textblock *textblock, int y);
+ inline int yForTextblock (Textblock *textblock)
+ { return yForTextblock (textblock, yReal); }
+ int yForContainer (int y);
+ inline int yForContainer () { return yForContainer (yReal); }
+ bool covers (Textblock *textblock, int y, int h);
+ };
+
+ /**
+ * This list is kept sorted.
+ *
+ * To prevent accessing methods of the base class in an
+ * uncontrolled way, the inheritance is private, not public; this
+ * means that all methods must be delegated (see iterator(), size()
+ * etc. below.)
+ *
+ * TODO Update comment: still sorted, but ...
+ *
+ * More: add() and change() may check order again.
+ */
+ class SortedFloatsVector: private lout::container::typed::Vector<Float>
+ {
+ private:
+ OutOfFlowMgr *oofm;
+
+ public:
+ inline SortedFloatsVector (OutOfFlowMgr *oofm) :
+ lout::container::typed::Vector<Float> (1, false)
+ { this->oofm = oofm; }
+
+ int find (Textblock *textblock, int y);
+ int findFirst (Textblock *textblock, int y, int h);
+ inline void put (Float *vloat)
+ { lout::container::typed::Vector<Float>::put (vloat);
+ vloat->index = size() - 1; }
+ inline void change (Float *vloat) { }
+
+ inline lout::container::typed::Iterator<Float> iterator()
+ { return lout::container::typed::Vector<Float>::iterator (); }
+ inline int size () // For size, cleanup is irrelevant.
+ { return lout::container::typed::Vector<Float>::size (); }
+ inline Float *get (int pos)
+ { return lout::container::typed::Vector<Float>::get (pos); }
+ inline void clear ()
+ { lout::container::typed::Vector<Float>::clear (); }
+ };
+
+ class TBInfo: public lout::object::Object
+ {
+ public:
+ bool wasAllocated;
+ int xCB, yCB; // relative to the containing block
+ int width, height, index;
+
+ // These two lists store all floats generated by this textblock,
+ // as long as this textblock is not allocates.
+ SortedFloatsVector *leftFloatsGB, *rightFloatsGB;
+
+ TBInfo (OutOfFlowMgr *oofm);
+ ~TBInfo ();
+ };
+
+ // These two lists store all floats, in the order in which they are
+ // defined. Only used for iterators.
+ lout::container::typed::Vector<Float> *leftFloatsAll, *rightFloatsAll;
+
+ // These two lists store all floats whose generators are already
+ // allocated.
+ SortedFloatsVector *leftFloatsCB, *rightFloatsCB;
+
+ lout::container::typed::HashTable<lout::object::TypedPointer
+ <dw::core::Widget>, Float> *floatsByWidget;
+
+ lout::container::typed::List<TBInfo> *tbInfos;
+ lout::container::typed::HashTable<lout::object::TypedPointer <Textblock>,
+ TBInfo> *tbInfosByTextblock;
+
+ int lastLeftTBIndex, lastRightTBIndex, leftFloatsMark, rightFloatsMark;
+
+ /**
+ * Variant of Widget::wasAllocated(), which can also be used within
+ * OOFM::sizeAllocateEnd(), and also for the generating block.
+ */
+ inline bool wasAllocated (core::Widget *widget) {
+ return widget->wasAllocated () ||
+ (widget == (core::Widget*)containingBlock &&
+ containingBlockWasAllocated); }
+
+ /**
+ * Variant of Widget::getAllocation(), which can also be used
+ * within OOFM::sizeAllocateEnd(), and also for the generating
+ * block.
+ */
+ inline core::Allocation *getAllocation (core::Widget *widget) {
+ return widget == (core::Widget*)containingBlock ?
+ &containingBlockAllocation : widget->getAllocation (); }
+
+ Float *findFloatByWidget (core::Widget *widget);
+
+ void moveFromGBToCB (Side side);
+ void sizeAllocateFloats (Side side);
+ bool isTextblockCoveredByFloats (Textblock *tb, int tbx, int tby,
+ int tbWidth, int tbHeight, int *floatPos,
+ core::Widget **vloat);
+ bool isTextblockCoveredByFloats (SortedFloatsVector *list, Textblock *tb,
+ int tbx, int tby, int tbWidth, int tbHeight,
+ int *floatPos, core::Widget **vloat);
+
+ void draw (SortedFloatsVector *list, core::View *view,
+ core::Rectangle *area);
+ core::Widget *getWidgetAtPoint (SortedFloatsVector *list, int x, int y,
+ int level);
+ void tellPositionOrNot (core::Widget *widget, int yReq, bool positioned);
+ void checkCoverage (Float *vloat, int oldY);
+
+ void getFloatsLists (Float *vloat, SortedFloatsVector **listSame,
+ SortedFloatsVector **listOpp);
+
+ int getFloatsSize (SortedFloatsVector *list);
+ void accumExtremes (SortedFloatsVector *list, int *oofMinWidth,
+ int *oofMaxWidth);
+ TBInfo *registerCaller (Textblock *textblock);
+ int getBorder (Textblock *textblock, Side side, int y, int h);
+ bool hasFloat (Textblock *textblock, Side side, int y, int h);
+
+ void ensureFloatSize (Float *vloat);
+ int getBorderDiff (Textblock *textblock, Float *vloat, Side side);
+
+
+ inline static bool isRefFloat (int ref)
+ { return ref != -1 && (ref & 1) == 1; }
+ inline static bool isRefLeftFloat (int ref)
+ { return ref != -1 && (ref & 3) == 1; }
+ inline static bool isRefRightFloat (int ref)
+ { return ref != -1 && (ref & 3) == 3; }
+
+ inline static int createRefLeftFloat (int index)
+ { return (index << 2) | 1; }
+ inline static int createRefRightFloat (int index)
+ { return (index << 2) | 3; }
+
+ inline static int getFloatIndexFromRef (int ref)
+ { return ref == -1 ? ref : (ref >> 2); }
+
+public:
+ OutOfFlowMgr (Textblock *containingBlock);
+ ~OutOfFlowMgr ();
+
+ void sizeAllocateStart (core::Allocation *containingBlockAllocation);
+ void sizeAllocateEnd ();
+ void draw (core::View *view, core::Rectangle *area);
+
+ void markSizeChange (int ref);
+ void markExtremesChange (int ref);
+ core::Widget *getWidgetAtPoint (int x, int y, int level);
+
+ static bool isWidgetOutOfFlow (core::Widget *widget);
+ void addWidget (core::Widget *widget, Textblock *generatingBlock);
+
+ void tellNoPosition (core::Widget *widget);
+ void tellPosition (core::Widget *widget, int y);
+
+ void getSize (int cbWidth, int cbHeight, int *oofWidth, int *oofHeight);
+ void getExtremes (int cbMinWidth, int cbMaxWidth, int *oofMinWidth,
+ int *oofMaxWidth);
+
+ int getLeftBorder (Textblock *textblock, int y, int h);
+ int getRightBorder (Textblock *textblock, int y, int h);
+
+ bool hasFloatLeft (Textblock *textblock, int y, int h);
+ bool hasFloatRight (Textblock *textblock, int y, int h);
+
+ inline static bool isRefOutOfFlow (int ref)
+ { return ref != -1 && (ref & 1) != 0; }
+ inline static int createRefNormalFlow (int lineNo) { return lineNo << 1; }
+ inline static int getLineNoFromRef (int ref)
+ { return ref == -1 ? ref : (ref >> 1); }
+
+ // for iterators
+ inline int getNumWidgets () {
+ return leftFloatsAll->size() + rightFloatsAll->size(); }
+ inline core::Widget *getWidget (int i) {
+ return i < leftFloatsAll->size() ? leftFloatsAll->get(i)->widget :
+ rightFloatsAll->get(i - leftFloatsAll->size())->widget; }
+};
+
+} // namespace dw
+
+#endif // __DW_OUTOFFLOWMGR_HH__