xref: /aoo4110/main/svx/inc/svx/framelinkarray.hxx (revision b1cdbd2c)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 #ifndef SVX_FRAMELINKARRAY_HXX
25 #define SVX_FRAMELINKARRAY_HXX
26 
27 #include <svx/framelink.hxx>
28 
29 #include <memory>
30 
31 #include <vector>
32 #include "svx/svxdllapi.h"
33 
34 namespace svx {
35 namespace frame {
36 
37 // ============================================================================
38 
39 
40 struct Cell
41 {
42     Style               maLeft;
43     Style               maRight;
44     Style               maTop;
45     Style               maBottom;
46     Style               maTLBR;
47     Style               maBLTR;
48     long                mnAddLeft;
49     long                mnAddRight;
50     long                mnAddTop;
51     long                mnAddBottom;
52     bool                mbMergeOrig;
53     bool                mbOverlapX;
54     bool                mbOverlapY;
55 
56     explicit            Cell();
57 
IsMergedsvx::frame::Cell58     inline bool         IsMerged() const { return mbMergeOrig || mbOverlapX || mbOverlapY; }
IsOverlappedsvx::frame::Cell59     inline bool         IsOverlapped() const { return mbOverlapX || mbOverlapY; }
60 
61     void                MirrorSelfX( bool bMirrorStyles, bool bSwapDiag );
62     void                MirrorSelfY( bool bMirrorStyles, bool bSwapDiag );
63 };
64 
65 typedef std::vector< long >     LongVec;
66 typedef std::vector< Cell >     CellVec;
67 
68 struct ArrayImpl
69 {
70     CellVec             maCells;
71     LongVec             maWidths;
72     LongVec             maHeights;
73     mutable LongVec     maXCoords;
74     mutable LongVec     maYCoords;
75     size_t              mnWidth;
76     size_t              mnHeight;
77     size_t              mnFirstClipCol;
78     size_t              mnFirstClipRow;
79     size_t              mnLastClipCol;
80     size_t              mnLastClipRow;
81     mutable bool        mbXCoordsDirty;
82     mutable bool        mbYCoordsDirty;
83     bool                mbDiagDblClip;
84 
85     explicit            ArrayImpl( size_t nWidth, size_t nHeight, bool bDiagDblClip );
86 
IsValidPossvx::frame::ArrayImpl87     inline bool         IsValidPos( size_t nCol, size_t nRow ) const
88                             { return (nCol < mnWidth) && (nRow < mnHeight); }
GetIndexsvx::frame::ArrayImpl89     inline size_t       GetIndex( size_t nCol, size_t nRow ) const
90                             { return nRow * mnWidth + nCol; }
91 
92     const Cell&         GetCell( size_t nCol, size_t nRow ) const;
93     Cell&               GetCellAcc( size_t nCol, size_t nRow );
94 
95     size_t              GetMergedFirstCol( size_t nCol, size_t nRow ) const;
96     size_t              GetMergedFirstRow( size_t nCol, size_t nRow ) const;
97     size_t              GetMergedLastCol( size_t nCol, size_t nRow ) const;
98     size_t              GetMergedLastRow( size_t nCol, size_t nRow ) const;
99 
100     const Cell&         GetMergedOriginCell( size_t nCol, size_t nRow ) const;
101     Cell&               GetMergedOriginCellAcc( size_t nCol, size_t nRow );
102 
103     bool                IsMergedOverlappedLeft( size_t nCol, size_t nRow ) const;
104     bool                IsMergedOverlappedRight( size_t nCol, size_t nRow ) const;
105     bool                IsMergedOverlappedTop( size_t nCol, size_t nRow ) const;
106     bool                IsMergedOverlappedBottom( size_t nCol, size_t nRow ) const;
107 
108     bool                IsInClipRange( size_t nCol, size_t nRow ) const;
109     bool                IsColInClipRange( size_t nCol ) const;
110     bool                IsRowInClipRange( size_t nRow ) const;
111 
GetMirrorColsvx::frame::ArrayImpl112     inline size_t       GetMirrorCol( size_t nCol ) const { return mnWidth - nCol - 1; }
GetMirrorRowsvx::frame::ArrayImpl113     inline size_t       GetMirrorRow( size_t nRow ) const { return mnHeight - nRow - 1; }
114 
115     long                GetColPosition( size_t nCol ) const;
116     long                GetRowPosition( size_t nRow ) const;
117 
118     long                GetColWidth( size_t nFirstCol, size_t nLastCol ) const;
119     long                GetRowHeight( size_t nFirstRow, size_t nLastRow ) const;
120 
121     double              GetHorDiagAngle( size_t nCol, size_t nRow, bool bSimple = false ) const;
122     double              GetVerDiagAngle( size_t nCol, size_t nRow, bool bSimple = false ) const;
123 };
124 
125 /** Stores frame styles of an array of cells, supports merged ranges.
126 
127     This class is able to store the frame styles of an array of cells and to
128     draw the entire array or parts of it to any output device.
129 
130     Every cell contains the style of the left, right, top, bottom, top-left to
131     bottom-right, and bottom-left to top-right frame border.
132 
133     On drawing, the thicker frame border of neighbored cells is selected
134     automatically. All borders are drawn "connected", that means, the correct
135     start and end coordinates of all lines of the borders are calculated,
136     especaially, if they are drawn together with diagonal frame borders.
137 
138     This array fully supports merged cell ranges. In a merged range, the frame
139     borders of the top-left cell is extended to the entire range, and all other
140     cells in that range are overlapped. Again, all connected frame borders,
141     also diagonals and frame borders from adjacent merged ranges, are handled
142     automatically.
143 
144     Additionally, a clipping range can be set. If such a range is used, all
145     frame borders outside this range are completely ignored, and are not used
146     in the connected border calculation anymore.
147 
148     The array can be mirrored in both directions. It is possible to specify,
149     whether to mirror the double frame styles, and whether to swap diagonal
150     frame borders.
151  */
152 class SVX_DLLPUBLIC Array
153 {
154 public:
155     /** Constructs an empty array. */
156     explicit            Array();
157 
158     /** Constructs an array with the specified width and height. */
159     explicit            Array( size_t nWidth, size_t nHeight );
160 
161     /** Destructs the array. */
162                         ~Array();
163 
164     // array size and column/row indexes --------------------------------------
165 
166     /** Reinitializes the array with the specified size. Clears all styles. */
167     void                Initialize( size_t nWidth, size_t nHeight );
168 
169     /** Clears all line styles, column widths, row heights, merge data, and the clip range. */
170     void                Clear();
171 
172     /** Returns the number of columns in the array. */
173     size_t              GetColCount() const;
174 
175     /** Returns the number of rows in the array. */
176     size_t              GetRowCount() const;
177 
178     /** Returns the number of cells in the array. */
179     size_t              GetCellCount() const;
180 
181     /** Returns the column index of the specified cell index. */
182     size_t              GetColFromIndex( size_t nCellIndex ) const;
183 
184     /** Returns the row index of the specified cell index. */
185     size_t              GetRowFromIndex( size_t nCellIndex ) const;
186 
187     /** Returns the cell index from the cell address (nCol,nRow). */
188     size_t              GetCellIndex( size_t nCol, size_t nRow, bool bRTL = false) const;
189 
190     // cell border styles -----------------------------------------------------
191 
192     /** Sets the left frame style of the cell (nCol,nRow). Ignores merged ranges. */
193     void                SetCellStyleLeft( size_t nCol, size_t nRow, const Style& rStyle );
194 
195     /** Sets the right frame style of the cell (nCol,nRow). Ignores merged ranges. */
196     void                SetCellStyleRight( size_t nCol, size_t nRow, const Style& rStyle );
197 
198     /** Sets the top frame style of the cell (nCol,nRow). Ignores merged ranges. */
199     void                SetCellStyleTop( size_t nCol, size_t nRow, const Style& rStyle );
200 
201     /** Sets the bottom frame style of the specified cell (nCol,nRow). Ignores merged ranges. */
202     void                SetCellStyleBottom( size_t nCol, size_t nRow, const Style& rStyle );
203 
204     /** Sets the top-left to bottom-right frame style of the cell (nCol,nRow). Ignores merged ranges. */
205     void                SetCellStyleTLBR( size_t nCol, size_t nRow, const Style& rStyle );
206 
207     /** Sets the bottom-left to top-right frame style of the cell (nCol,nRow). Ignores merged ranges. */
208     void                SetCellStyleBLTR( size_t nCol, size_t nRow, const Style& rStyle );
209 
210     /** Sets both diagonal frame styles of the specified cell (nCol,nRow). Ignores merged ranges. */
211     void                SetCellStyleDiag( size_t nCol, size_t nRow, const Style& rTLBR, const Style& rBLTR );
212 
213     /** Sets the left frame style of the specified column. Ignores merged ranges. */
214     void                SetColumnStyleLeft( size_t nCol, const Style& rStyle );
215 
216     /** Sets the right frame style of the specified column. Ignores merged ranges. */
217     void                SetColumnStyleRight( size_t nCol, const Style& rStyle );
218 
219     /** Sets the top frame style of the specified row. Ignores merged ranges. */
220     void                SetRowStyleTop( size_t nRow, const Style& rStyle );
221 
222     /** Sets the bottom frame style of the specified row. Ignores merged ranges. */
223     void                SetRowStyleBottom( size_t nRow, const Style& rStyle );
224 
225     /** Returns the left frame style of the cell (nCol,nRow).
226         @param bSimple
227             true = Ignores merged ranges and neighbor cells;
228             false = Returns thicker of own left style or right style of the cell to the left.
229                 Returns the style only if visible (i.e. at left border of a merged range).
230         @return
231             The left frame style or an invisible style for invalid cell addresses. */
232     const Style&        GetCellStyleLeft( size_t nCol, size_t nRow, bool bSimple = false ) const;
233 
234     /** Returns the right frame style of the cell (nCol,nRow).
235         @param bSimple
236             true = Ignores merged ranges and neighbor cells;
237             false = Returns thicker of own right style or left style of the cell to the right.
238                 Returns the style only if visible (i.e. at right border of a merged range).
239         @return
240             The left frame style or an invisible style for invalid cell addresses. */
241     const Style&        GetCellStyleRight( size_t nCol, size_t nRow, bool bSimple = false ) const;
242 
243     /** Returns the top frame style of the cell (nCol,nRow).
244         @param bSimple
245             true = Ignores merged ranges and neighbor cells;
246             false = Returns thicker of own top style or bottom style of the cell above.
247                 Returns the style only if visible (i.e. at top border of a merged range).
248         @return
249             The top frame style or an invisible style for invalid cell addresses. */
250     const Style&        GetCellStyleTop( size_t nCol, size_t nRow, bool bSimple = false ) const;
251 
252     /** Returns the top frame style of the cell (nCol,nRow).
253         @param bSimple
254             true = Ignores merged ranges and neighbor cells;
255             false = Returns thicker of own top style or bottom style of the cell above.
256                 Returns the style only if visible (i.e. at top border of a merged range).
257         @return
258             The top frame style or an invisible style for invalid cell addresses. */
259     const Style&        GetCellStyleBottom( size_t nCol, size_t nRow, bool bSimple = false ) const;
260 
261     /** Returns the top-left to bottom-right frame style of the cell (nCol,nRow).
262         @param bSimple
263             true = Ignores merged ranges;
264             false = Returns the visible style (i.e. from top-left corner of a merged range).
265         @return
266             The top-left to bottom-right frame style or an invisible style for invalid cell addresses. */
267     const Style&        GetCellStyleTLBR( size_t nCol, size_t nRow, bool bSimple = false ) const;
268 
269     /** Returns the bottom-left to top-right frame style of the cell (nCol,nRow).
270         @param bSimple
271             true = Ignores merged ranges;
272             false = Returns the visible style (i.e. from top-left corner of a merged range).
273         @return
274             The bottom-left to top-right frame style or an invisible style for invalid cell addresses. */
275     const Style&        GetCellStyleBLTR( size_t nCol, size_t nRow, bool bSimple = false ) const;
276 
277     /** Returns the top-left to bottom-right frame style of the cell (nCol,nRow).
278         @return
279             The top-left to bottom-right frame style, if the cell is not part of
280             a merged range, or if (nCol,nRow) is the top-left corner of a merged
281             range (useful to find connected frame styles).
282             An invisible style for invalid cell addresses. */
283     const Style&        GetCellStyleTL( size_t nCol, size_t nRow ) const;
284 
285     /** Returns the top-left to bottom-right frame style of the cell (nCol,nRow).
286         @return
287             The top-left to bottom-right frame style, if the cell is not part of
288             a merged range, or if (nCol,nRow) is the bottom-right corner of a
289             merged range (useful to find connected frame styles).
290             An invisible style for invalid cell addresses. */
291     const Style&        GetCellStyleBR( size_t nCol, size_t nRow ) const;
292 
293     /** Returns the bottom-left to top-right frame style of the cell (nCol,nRow).
294         @return
295             The bottom-left to top-right frame style, if the cell is not part of
296             a merged range, or if (nCol,nRow) is the bottom-left corner of a
297             merged range (useful to find connected frame styles).
298             An invisible style for invalid cell addresses. */
299     const Style&        GetCellStyleBL( size_t nCol, size_t nRow ) const;
300 
301     /** Returns the bottom-left to top-right frame style of the cell (nCol,nRow).
302         @return
303             The bottom-left to top-right frame style, if the cell is not part of
304             a merged range, or if (nCol,nRow) is the top-right corner of a
305             merged range (useful to find connected frame styles).
306             An invisible style for invalid cell addresses. */
307     const Style&        GetCellStyleTR( size_t nCol, size_t nRow ) const;
308 
309     // cell merging -----------------------------------------------------------
310 
311     /** Inserts a new merged cell range.
312         @precond  The range must not intersect other merged ranges. */
313     void                SetMergedRange( size_t nFirstCol, size_t nFirstRow, size_t nLastCol, size_t nLastRow );
314 
315     /** Removes the merged cell range that contains (nCol,nRow). */
316     void                RemoveMergedRange( size_t nCol, size_t nRow );
317 
318     /** Sets an additional left width for the merged range that contains (nCol,nRow).
319         @descr  Useful to handle merged ranges that are not completely part of the array.
320         @precond  The merged range must be at the left border of the array. */
321     void                SetAddMergedLeftSize( size_t nCol, size_t nRow, long nAddSize );
322 
323     /** Sets an additional right width for the merged range that contains (nCol,nRow).
324         @descr  Useful to handle merged ranges that are not completely part of the array.
325         @precond  The merged range must be at the right border of the array. */
326     void                SetAddMergedRightSize( size_t nCol, size_t nRow, long nAddSize );
327 
328     /** Sets an additional top height for the merged range that contains (nCol,nRow).
329         @descr  Useful to handle merged ranges that are not completely part of the array.
330         @precond  The merged range must be at the top border of the array. */
331     void                SetAddMergedTopSize( size_t nCol, size_t nRow, long nAddSize );
332 
333     /** Sets an additional bottom height for the merged range that contains (nCol,nRow).
334         @descr  Useful to handle merged ranges that are not completely part of the array.
335         @precond  The merged range must be at the bottom border of the array. */
336     void                SetAddMergedBottomSize( size_t nCol, size_t nRow, long nAddSize );
337 
338     /** Returns true, if the cell (nCol,nRow) is part of a merged range. */
339     bool                IsMerged( size_t nCol, size_t nRow ) const;
340 
341     /** Returns true, if the cell (nCol,nRow) is the top-left corner of a merged range. */
342     bool                IsMergedOrigin( size_t nCol, size_t nRow ) const;
343 
344     /** Returns true, if the cell (nCol,nRow) is overlapped by a merged range. */
345     bool                IsMergedOverlapped( size_t nCol, size_t nRow ) const;
346 
347     /** Returns true, if the left border of the cell (nCol,nRow) is overlapped by a merged range. */
348     bool                IsMergedOverlappedLeft( size_t nCol, size_t nRow ) const;
349 
350     /** Returns true, if the right border of the cell (nCol,nRow) is overlapped by a merged range. */
351     bool                IsMergedOverlappedRight( size_t nCol, size_t nRow ) const;
352 
353     /** Returns true, if the top border of the cell (nCol,nRow) is overlapped by a merged range. */
354     bool                IsMergedOverlappedTop( size_t nCol, size_t nRow ) const;
355 
356     /** Returns true, if the bottom border of the cell (nCol,nRow) is overlapped by a merged range. */
357     bool                IsMergedOverlappedBottom( size_t nCol, size_t nRow ) const;
358 
359     /** Returns the address of the top-left cell of the merged range that contains (nCol,nRow). */
360     void                GetMergedOrigin( size_t& rnFirstCol, size_t& rnFirstRow, size_t nCol, size_t nRow ) const;
361 
362     /** Returns the range size of the merged range thst contains (nCol,nRow). */
363     void                GetMergedSize( size_t& rnWidth, size_t& rnHeight, size_t nCol, size_t nRow ) const;
364 
365     /** Returns the top-left and bottom-right address of the merged range that contains (nCol,nRow). */
366     void                GetMergedRange( size_t& rnFirstCol, size_t& rnFirstRow,
367                             size_t& rnLastCol, size_t& rnLastRow, size_t nCol, size_t nRow ) const;
368 
369     // clipping ---------------------------------------------------------------
370 
371     /** Sets a clipping range.
372         @descr
373             No cell borders outside of this clipping range will be drawn. In
374             difference to simply using the DrawRange() function with the same
375             range, a clipping range causes the drawing functions to completely
376             ignore the frame styles connected from outside. This is used i.e.
377             in Calc to print single pages and to draw the print preview.
378             Partly visible diagonal frame borders in merged ranges are correctly
379             clipped too. This array can handle only one clip range at a time. */
380     void                SetClipRange( size_t nFirstCol, size_t nFirstRow, size_t nLastCol, size_t nLastRow );
381 
382     /** Removes the clipping range set with the SetClipRange() function. */
383     void                RemoveClipRange();
384 
385     /** Returns true, if the cell (bCol,nRow) is inside the current clip range. */
386     bool                IsInClipRange( size_t nCol, size_t nRow ) const;
387 
388     /** Returns the rectangle (output coordinates) of the current clipping range. */
389     Rectangle           GetClipRangeRectangle() const;
390 
391     // cell coordinates -------------------------------------------------------
392 
393     /** Sets the X output coordinate of the left column. */
394     void                SetXOffset( long nXOffset );
395 
396     /** Sets the Y output coordinate of the top row. */
397     void                SetYOffset( long nYOffset );
398 
399     /** Sets the output width of the specified column. */
400     void                SetColWidth( size_t nCol, long nWidth );
401 
402     /** Sets the output height of the specified row. */
403     void                SetRowHeight( size_t nRow, long nHeight );
404 
405     /** Sets the same output width for all columns. */
406     void                SetAllColWidths( long nWidth );
407 
408     /** Sets the same output height for all rows. */
409     void                SetAllRowHeights( long nHeight );
410 
411     /** Returns the X output coordinate of the left border of the specified column.
412         @descr  The column index <array-width> returns the X output coordinate
413                 of the right array border. */
414     long                GetColPosition( size_t nCol ) const;
415 
416     /** Returns the Y output coordinate of the top border of the specified row.
417         @descr  The row index <array-height> returns the Y output coordinate
418                 of the bottom array border. */
419     long                GetRowPosition( size_t nRow ) const;
420 
421     /** Returns the output width of the specified column. */
422     long                GetColWidth( size_t nCol ) const;
423 
424     /** Returns the output width of the specified range of columns. */
425     long                GetColWidth( size_t nFirstCol, size_t nLastCol ) const;
426 
427     /** Returns the output height of the specified row. */
428     long                GetRowHeight( size_t nRow ) const;
429 
430     /** Returns the output height of the specified range of rows. */
431     long                GetRowHeight( size_t nFirstRow, size_t nLastRow ) const;
432 
433     /** Returns the output width of the entire array. */
434     long                GetWidth() const;
435 
436     /** Returns the output height of the entire array. */
437     long                GetHeight() const;
438 
439     /** Returns the top-left output position of the cell (nCol,nRow).
440         @param bSimple
441             true = Ignores merged ranges;
442             false = Returns output position of top-left corner of merged ranges. */
443     Point               GetCellPosition( size_t nCol, size_t nRow, bool bSimple = false ) const;
444 
445     /** Returns the output size of the cell (nCol,nRow).
446         @param bSimple
447             true = Ignores merged ranges;
448             false = Returns total output size of merged ranges. */
449     Size                GetCellSize( size_t nCol, size_t nRow, bool bSimple = false ) const;
450 
451     /** Returns the output rectangle of the cell (nCol,nRow).
452         @param bSimple
453             true = Ignores merged ranges;
454             false = Returns total output rectangle of merged ranges. */
455     Rectangle           GetCellRect( size_t nCol, size_t nRow, bool bSimple = false ) const;
456 
457     // diagonal frame borders -------------------------------------------------
458 
459     /** Returns the angle between horizontal and diagonal border of the cell (nCol,nRow).
460         @param bSimple
461             true = Ignores merged ranges;
462             false = Returns the horizontal angle of merged ranges. */
463     double              GetHorDiagAngle( size_t nCol, size_t nRow, bool bSimple = false ) const;
464 
465     /** Returns the angle between vertical and diagonal border of the cell (nCol,nRow).
466         @param bSimple
467             true = Ignores merged ranges;
468             false = Returns the vertical angle of merged ranges. */
469     double              GetVerDiagAngle( size_t nCol, size_t nRow, bool bSimple = false ) const;
470 
471     /** Specifies whether to use polygon clipping to draw diagonal frame borders.
472         @descr
473             If enabled, diagonal frame borders are drawn interrupted, if they are
474             crossed by a double frame border. Polygon clipping is very expensive
475             and should only be used for very small output devices (i.e. in the
476             Border tab page). Default after construction is OFF. */
477     void                SetUseDiagDoubleClipping( bool bSet );
478 
479     /** Returns true, if polygon clipping is used to draw diagonal frame borders. */
480     bool                GetUseDiagDoubleClipping() const;
481 
482     // mirroring --------------------------------------------------------------
483 
484     /** Mirrors the entire array horizontally.
485         @param bMirrorStyles
486             true = Swap primary and secondary line of all vertical double frame borders.
487         @param bSwapDiag
488             true = Swap top-left to bottom-right and bottom-left to top-right frame borders. */
489     void                MirrorSelfX( bool bMirrorStyles, bool bSwapDiag );
490 
491     /** Mirrors the entire array vertically.
492         @param bMirrorStyles
493             true = Swap primary and secondary line of all horizontal double frame borders.
494         @param bSwapDiag
495             true = Swap top-left to bottom-right and bottom-left to top-right frame borders. */
496     void                MirrorSelfY( bool bMirrorStyles, bool bSwapDiag );
497 
498     // drawing ----------------------------------------------------------------
499 
500     /** Draws the cell (nCol,nRow), if it is inside the clipping range.
501         @param pForceColor
502             If not NULL, only this color will be used to draw all frame borders. */
503     void                DrawCell( OutputDevice& rDev, size_t nCol, size_t nRow,
504                             const Color* pForceColor = 0 ) const;
505 
506     /** Draws the part of the specified range, that is inside the clipping range.
507         @param pForceColor
508             If not NULL, only this color will be used to draw all frame borders. */
509     void                DrawRange( OutputDevice& rDev,
510                             size_t nFirstCol, size_t nFirstRow,
511                             size_t nLastCol, size_t nLastRow,
512                             const Color* pForceColor = 0 ) const;
513 
514     /** Draws the part of the array, that is inside the clipping range.
515         @param pForceColor
516             If not NULL, only this color will be used to draw all frame borders. */
517     void                DrawArray( OutputDevice& rDev, const Color* pForceColor = 0 ) const;
518 
519     // ------------------------------------------------------------------------
520 
521 private:
522     typedef std::auto_ptr< ArrayImpl > ArrayImplPtr;
523 
524     ArrayImplPtr        mxImpl;
525 };
526 
527 // ============================================================================
528 
529 } // namespace frame
530 } // namespace svx
531 
532 #endif
533 
534