aboutsummaryrefslogtreecommitdiff
path: root/dw/ooffloatsmgr.hh
blob: 8f5cdd1f1f2dde6ecde945d4d612e81518a135c7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
#ifndef __DW_OOFFLOATSMGR_HH__
#define __DW_OOFFLOATSMGR_HH__

#include "outofflowmgr.hh"

namespace dw {

namespace oof {

/**
 * \brief OutOfFlowMgr implementation dealing with floats.
 *
 * Note: The identifiers and comments of this class still refer to
 * "Textblock" instead of "OOFAwareWidget"; should be cleaned up some
 * day. (OTOH, these widgets are always textblocks.)
 */
class OOFFloatsMgr: public OutOfFlowMgr
{
   friend class WidgetInfo;

private:
   enum Side { LEFT, RIGHT };
   enum SFVType { GB, CB };

   OOFAwareWidget *container;

   // These two values are redundant to TBInfo::wasAllocated and
   // TBInfo::allocation, for some special cases.
   bool containerWasAllocated;
   core::Allocation containerAllocation;

   class WidgetInfo: public lout::object::Object
   {
   private:
      bool wasAllocated;
      int xCB, yCB; // relative to the containing block
      int width, height;

      OOFFloatsMgr *oofm;
      core::Widget *widget;

   protected:
      OOFFloatsMgr *getOOFFloatsMgr () { return oofm; }

   public:
      WidgetInfo (OOFFloatsMgr *oofm, core::Widget *widget);

      inline bool wasThenAllocated () { return wasAllocated; }
      inline int getOldXCB () { return xCB; }
      inline int getOldYCB () { return yCB; }
      inline int getOldWidth () { return width; }
      inline int getOldHeight () { return height; }


      void update (bool wasAllocated, int xCB, int yCB, int width, int height);

      inline core::Widget *getWidget () { return widget; }
   };

   class Float: public WidgetInfo
   {
   public:
      class ComparePosition: public lout::object::Comparator
      {
      private:
         OOFFloatsMgr *oofm;
         OOFAwareWidget *refTB;
         SFVType type; // actually only used for debugging

      public:
         ComparePosition (OOFFloatsMgr *oofm, OOFAwareWidget *refTB,
                          SFVType type)
         { this->oofm = oofm; this->refTB = refTB; this->type = type; }
         int compare(Object *o1, Object *o2);
      };

      class CompareSideSpanningIndex: public lout::object::Comparator
      {
      public:
         int compare(Object *o1, Object *o2);
      };

      class CompareGBAndExtIndex: public lout::object::Comparator
      {
      private:
         OOFFloatsMgr *oofm;
         SFVType type; // actually only used for debugging

      public:
         CompareGBAndExtIndex (OOFFloatsMgr *oofm, SFVType type)
         { this->oofm = oofm; this->type = type; }
         int compare(Object *o1, Object *o2);
      };

      OOFAwareWidget *generatingBlock;
      int externalIndex;
      int yReq, yReal; // relative to generator, not container
      int indexGBList; /* Refers to TBInfo::leftFloatsGB or
                          TBInfo::rightFloatsGB, respectively. -1
                          initially. */
      int indexCBList; /* Refers to leftFloatsCB or rightFloatsCB,
                          respectively. -1 initially. */
      int sideSpanningIndex, mark;
      core::Requisition size;
      int cbLineBreakWidth; /* On which the calculation of relative sizes
                               is based. Height not yet used, and probably
                               not added before size redesign. */
      bool dirty, sizeChangedSinceLastAllocation;

      Float (OOFFloatsMgr *oofm, core::Widget *widget,
             OOFAwareWidget *generatingBlock, int externalIndex);

      inline bool isNowAllocated () { return getWidget()->wasAllocated (); }
      inline int getNewXCB () { return getWidget()->getAllocation()->x -
            getOOFFloatsMgr()->containerAllocation.x; }
      inline int getNewYCB () { return getWidget()->getAllocation()->y -
            getOOFFloatsMgr()->containerAllocation.y; }
      inline int getNewWidth () { return getWidget()->getAllocation()->width; }
      inline int getNewHeight () { return getWidget()->getAllocation()->ascent +
            getWidget()->getAllocation()->descent; }
      void updateAllocation ();

      inline int *getIndexRef (SFVType type) {
         return type == GB ? &indexGBList : &indexCBList; }
      inline int getIndex (SFVType type) { return *(getIndexRef (type)); }
      inline void setIndex (SFVType type, int value) {
         *(getIndexRef (type)) = value; }

      void intoStringBuffer(lout::misc::StringBuffer *sb);

      bool covers (OOFAwareWidget *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>
   {
   public:
      SFVType type;

   private:
      OOFFloatsMgr *oofm;
      Side side;

   public:
      inline SortedFloatsVector (OOFFloatsMgr *oofm, Side side, SFVType type) :
         lout::container::typed::Vector<Float> (1, false)
      { this->oofm = oofm; this->side = side; this->type = type; }

      int findFloatIndex (OOFAwareWidget *lastGB, int lastExtIndex);
      int find (OOFAwareWidget *textblock, int y, int start, int end);
      int findFirst (OOFAwareWidget *textblock, int y, int h,
                     OOFAwareWidget *lastGB, int lastExtIndex, int *lastReturn);
      int findLastBeforeSideSpanningIndex (int sideSpanningIndex);
      void put (Float *vloat);

      inline lout::container::typed::Iterator<Float> iterator()
      { return lout::container::typed::Vector<Float>::iterator (); }
      inline int size ()
      { 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 WidgetInfo
   {
   public:
      int lineBreakWidth;
      int index; // position within "tbInfos"

      TBInfo *parent;
      int parentExtIndex;

      // These two values are set by sizeAllocateStart(), and they are
      // accessable also within sizeAllocateEnd() for the same
      // textblock, for which allocation and WAS_ALLOCATED is set
      // *after* sizeAllocateEnd(). See the two functions
      // wasAllocated(Widget*) and getAllocation(Widget*) (further
      // down) for usage.
      bool wasAllocated;
      core::Allocation allocation;

      // These two lists store all floats generated by this textblock,
      // as long as this textblock is not allocates.
      SortedFloatsVector *leftFloatsGB, *rightFloatsGB;

      TBInfo (OOFFloatsMgr *oofm, OOFAwareWidget *textblock,
              TBInfo *parent, int parentExtIndex);
      ~TBInfo ();

      inline bool isNowAllocated () {
         return getOOFFloatsMgr()->wasAllocated (getOOFAwareWidget ()); }
      inline int getNewXCB () {
         return getOOFFloatsMgr()->getAllocation (getOOFAwareWidget ())->x -
            getOOFFloatsMgr()->containerAllocation.x; }
      inline int getNewYCB () {
         return getOOFFloatsMgr()->getAllocation (getOOFAwareWidget ())->y -
            getOOFFloatsMgr()->containerAllocation.y; }
      inline int getNewWidth () {
         return getOOFFloatsMgr()->getAllocation (getOOFAwareWidget ())->width; }
      inline int getNewHeight () {
         core::Allocation *allocation =
            getOOFFloatsMgr()->getAllocation (getOOFAwareWidget ());
         return allocation->ascent + allocation->descent; }
      void updateAllocation ();

      inline OOFAwareWidget *getOOFAwareWidget () { return (OOFAwareWidget*)getWidget (); }
   };

   // 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;

   // These two attributes are used in the size allocation process;
   // see sizeAllocateStart and sizeAllocateEnd.
   int lastAllocatedLeftFloat, lastAllocatedRightFloat;

   lout::container::typed::HashTable<lout::object::TypedPointer
                                     <dw::core::Widget>, Float> *floatsByWidget;

   lout::container::typed::Vector<TBInfo> *tbInfos;
   lout::container::typed::HashTable<lout::object::TypedPointer<OOFAwareWidget>,
                                     TBInfo> *tbInfosByOOFAwareWidget;

   int lastLeftTBIndex, lastRightTBIndex, leftFloatsMark, rightFloatsMark;

   /**
    * Variant of Widget::wasAllocated(), which can also be used within
    * OOFM::sizeAllocateEnd().
    */
   inline bool wasAllocated (OOFAwareWidget *textblock) {
      return getOOFAwareWidget(textblock)->wasAllocated;
   }

   /**
    * Variant of Widget::getAllocation(), which can also be used
    * within OOFM::sizeAllocateEnd().
    */
   inline core::Allocation *getAllocation (OOFAwareWidget *textblock) {
      return &(getOOFAwareWidget(textblock)->allocation);
   }

   void moveExternalIndices (SortedFloatsVector *list, int oldStartIndex,
                             int diff);
   Float *findFloatByWidget (core::Widget *widget);

   void moveFromGBToCB (Side side);
   void sizeAllocateFloats (Side side, int newLastAllocatedFloat);
   int calcFloatX (Float *vloat, Side side, int gbX, int gbWidth,
                   int gbLineBreakWidth);

   bool hasRelationChanged (TBInfo *tbInfo,int *minFloatPos,
                            core::Widget **minFloat);
   bool hasRelationChanged (TBInfo *tbInfo, Side side, int *minFloatPos,
                            core::Widget **minFloat);
   bool hasRelationChanged (bool oldTBAlloc,
                            int oldTBx, int oldTBy, int oldTBw, int oldTBh,
                            int newTBx, int newTBy, int newTBw, int newTBh,
                            bool oldFlAlloc,
                            int oldFlx, int oldFly, int oldFlw, int oldFlh,
                            int newFlx, int newFly, int newFlw, int newFlh,
                            Side side, int *floatPos);

   void checkAllocatedFloatCollisions (Side side);

   bool doFloatsExceedCB (Side side);
   bool haveExtremesChanged (Side side);

   void drawFloats (SortedFloatsVector *list, core::View *view,
                    core::Rectangle *area);
   core::Widget *getFloatWidgetAtPoint (SortedFloatsVector *list, int x, int y,
                                        int level);

   bool collidesV (Float *vloat, Float *other, SFVType type, int *yReal);
   bool collidesH (Float *vloat, Float *other, SFVType type);

   void getFloatsListsAndSide (Float *vloat, SortedFloatsVector **listSame,
                               SortedFloatsVector **listOpp, Side *side);

   void getFloatsSize (core::Requisition *cbReq, Side side, int *width,
                       int *height);
   void getFloatsExtremes (core::Extremes *cbExtr, Side side, int *minWidth,
                           int *maxWidth);
   bool getFloatDiffToCB (Float *vloat, int *leftDiff, int *rightDiff);

   TBInfo *getOOFAwareWidget (OOFAwareWidget *textblock);
   int getBorder (OOFAwareWidget *textblock, Side side, int y, int h,
                  OOFAwareWidget *lastGB, int lastExtIndex);
   SortedFloatsVector *getFloatsListForOOFAwareWidget (OOFAwareWidget
                                                       *textblock,
                                                       Side side);
   bool hasFloat (OOFAwareWidget *textblock, Side side, int y, int h,
                  OOFAwareWidget *lastGB, int lastExtIndex);

   int getFloatHeight (OOFAwareWidget *textblock, Side side, int y, int h,
                       OOFAwareWidget *lastGB, int lastExtIndex);

   int getClearPosition (OOFAwareWidget *textblock, Side side);

   void ensureFloatSize (Float *vloat);

   inline static int createSubRefLeftFloat (int index) { return index << 1; }
   inline static int createSubRefRightFloat (int index)
   { return (index << 1) | 1; }

   inline static bool isSubRefLeftFloat (int ref)
   { return ref != -1 && (ref & 1) == 0; }
   inline static bool isSubRefRightFloat (int ref)
   { return ref != -1 && (ref & 1) == 1; }

   inline static int getFloatIndexFromSubRef (int ref)
   { return ref == -1 ? ref : (ref >> 1); }

public:
   OOFFloatsMgr (OOFAwareWidget *container);
   ~OOFFloatsMgr ();

   void sizeAllocateStart (OOFAwareWidget *caller,
                           core::Allocation *allocation);
   void sizeAllocateEnd (OOFAwareWidget *caller);
   void containerSizeChangedForChildren ();
   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);
   static bool _isWidgetHandledByOOFM (core::Widget *widget);
   void addWidgetInFlow (OOFAwareWidget *textblock, OOFAwareWidget *parentBlock,
                         int externalIndex);
   int addWidgetOOF (core::Widget *widget, OOFAwareWidget *generatingBlock,
                     int externalIndex);
   void moveExternalIndices (OOFAwareWidget *generatingBlock, int oldStartIndex,
                             int diff);

   void tellPosition (core::Widget *widget, int yReq);

   void getSize (core::Requisition *cbReq, int *oofWidth, int *oofHeight);
   void getExtremes (core::Extremes *cbExtr,
                     int *oofMinWidth, int *oofMaxWidth);

   int getLeftBorder (OOFAwareWidget *textblock, int y, int h,
                      OOFAwareWidget *lastGB, int lastExtIndex);
   int getRightBorder (OOFAwareWidget *textblock, int y, int h,
                       OOFAwareWidget *lastGB, int lastExtIndex);

   bool hasFloatLeft (OOFAwareWidget *textblock, int y, int h,
                      OOFAwareWidget *lastGB, int lastExtIndex);
   bool hasFloatRight (OOFAwareWidget *textblock, int y, int h, 
                       OOFAwareWidget *lastGB, int lastExtIndex);

   int getLeftFloatHeight (OOFAwareWidget *textblock, int y, int h,
                           OOFAwareWidget *lastGB, int lastExtIndex);
   int getRightFloatHeight (OOFAwareWidget *textblock, int y, int h,
                            OOFAwareWidget *lastGB, int lastExtIndex);

   bool affectsLeftBorder (core::Widget *widget);
   bool affectsRightBorder (core::Widget *widget);

   int getClearPosition (OOFAwareWidget *textblock);

   bool dealingWithSizeOfChild (core::Widget *child);
   int getAvailWidthOfChild (core::Widget *child, bool forceValue);
   int getAvailHeightOfChild (core::Widget *child, bool forceValue);

   int getNumWidgets ();
   core::Widget *getWidget (int i);
};

} // namespace oof

} // namespace dw

#endif // __DW_OOFFLOATSMGR_HH__