1 /*
2  * Copyright (C) 2020 Linux Studio Plugins Project <https://lsp-plug.in/>
3  *           (C) 2020 Vladimir Sadovnikov <sadko4u@gmail.com>
4  *
5  * This file is part of lsp-plugins
6  * Created on: 20 июн. 2017 г.
7  *
8  * lsp-plugins is free software: you can redistribute it and/or modify
9  * it under the terms of the GNU Lesser General Public License as published by
10  * the Free Software Foundation, either version 3 of the License, or
11  * any later version.
12  *
13  * lsp-plugins is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public License
19  * along with lsp-plugins. If not, see <https://www.gnu.org/licenses/>.
20  */
21 
22 #ifndef UI_TK_LSPGRID_H_
23 #define UI_TK_LSPGRID_H_
24 
25 namespace lsp
26 {
27     namespace tk
28     {
29 
30         class LSPGrid: public LSPWidgetContainer
31         {
32             public:
33                 static const w_class_t    metadata;
34 
35             protected:
36                 typedef struct cell_t
37                 {
38                     size_request_t      r;
39                     realize_t           a;
40                     realize_t           s;
41                     padding_t           p;
42                     LSPWidget          *pWidget;
43 
44                     ssize_t             nRows;      // Number of rows taken by cell
45                     ssize_t             nCols;      // Number of columns taken by cell
46                 } cell_t;
47 
48                 typedef struct header_t
49                 {
50                     ssize_t             nMinSize;
51                     ssize_t             nSize;
52                     ssize_t             nSpacing;
53                     ssize_t             nOffset;
54                     bool                bExpand;
55                 } header_t;
56 
57             protected:
58                 size_t      nHSpacing;
59                 size_t      nVSpacing;
60                 size_t      nCurrRow;
61                 size_t      nCurrCol;
62                 bool        bVertical;
63 
64                 cstorage<cell_t>    vCells;
65                 cstorage<header_t>  vRows;
66                 cstorage<header_t>  vCols;
67 
68             protected:
69                 virtual LSPWidget  *find_widget(ssize_t x, ssize_t y);
70 
71                 void                destroy_cells();
72                 static inline bool  hidden_widget(const cell_t *w);
73                 static void         split_size(header_t *h, size_t items, size_t size);
74                 static void         distribute_size(cstorage<header_t> &vh, size_t idx, size_t items, size_t rq_size);
75                 static size_t       estimate_size(cstorage<header_t> &vh, size_t idx, size_t items, size_t *spacing);
76                 static void         assign_coords(header_t *h, size_t items, size_t start);
77                 cell_t             *alloc_cell();
78                 status_t            tag_cell(cell_t *c, bool main);
79 
80             public:
81                 explicit LSPGrid(LSPDisplay *dpy, bool horizontal = true);
82                 virtual ~LSPGrid();
83 
84                 virtual status_t    init();
85                 virtual void        destroy();
86 
87             //---------------------------------------------------------------------------------
88             // Properties
89             public:
90                 /** Get number of columns
91                  *
92                  * @return number of columns
93                  */
columns()94                 inline size_t               columns() const { return vCols.size(); };
95 
96                 /** Get number of rows
97                  *
98                  * @return number of rows
99                  */
rows()100                 inline size_t               rows() const    { return vRows.size(); };
101 
102                 /** Get vertical spacing between cells
103                  *
104                  * @return vertical spacing between cells
105                  */
vertical_spacing()106                 inline size_t               vertical_spacing() const { return nVSpacing; };
107 
108                 /** Get vertical spacing between cells
109                  *
110                  * @return vertical spacing between cells
111                  */
vspacing()112                 inline size_t               vspacing() const { return nVSpacing; };
113 
114                 /** Get horizontal spacing between cells
115                  *
116                  * @return horizontal spacing between cells
117                  */
horizontal_spacing()118                 inline size_t               horizontal_spacing() const { return nHSpacing; };
119 
120                 /** Get horizontal spacing between cells
121                  *
122                  * @return horizontal spacing between cells
123                  */
hspacing()124                 inline size_t               hspacing() const { return nHSpacing; };
125 
126                 /** Check that grid has vertical orientation
127                  *
128                  * @return true if grid has vertical orientation
129                  */
vertical_orientation()130                 inline bool                 vertical_orientation() const { return bVertical; };
131 
132                 /** Check that grid has vertical orientation
133                  *
134                  * @return true if grid has vertical orientation
135                  */
vertical()136                 inline bool                 vertical() const { return bVertical; };
137 
138                 /** Check that grid has horizontal orientation
139                  *
140                  * @return true if grid has horizontal orientation
141                  */
horizontal_orientation()142                 inline bool                 horizontal_orientation() const { return !bVertical; };
143 
144                 /** Check that grid has horizontal orientation
145                  *
146                  * @return true if grid has horizontal orientation
147                  */
horizontal()148                 inline bool                 horizontal() const { return !bVertical; };
149 
150                 /** Get grid orientation
151                  *
152                  * @return grid orientation
153                  */
orientation()154                 inline orientation_t        orientation() const { return (bVertical) ? O_VERTICAL : O_HORIZONTAL; };
155 
156             //---------------------------------------------------------------------------------
157             // Manipulation
158             public:
159                 /** Set number of rows in the table
160                  *
161                  * @param rows number of rows in the table
162                  * @return status of operation
163                  */
164                 status_t                    set_rows(size_t rows);
165 
166                 /** Set number of columns in the table
167                  *
168                  * @param rows number of columns in the table
169                  * @return status of operation
170                  */
171                 status_t                    set_columns(size_t columns);
172 
173                 /** Set table orientation
174                  *
175                  * @param value table orientation
176                  * @return status of operation
177                  */
178                 status_t                    set_orientation(orientation_t value);
179 
180                 /** Set table vertical orientation
181                  *
182                  * @param value vertical orientation flag
183                  * @return status of operation
184                  */
185                 inline status_t             set_vertical(bool value = true) { return set_orientation((value) ? O_VERTICAL : O_HORIZONTAL); }
186 
187                 /** Set table horizontal orientation
188                  *
189                  * @param value horizontal orientation flag
190                  * @return status of operation
191                  */
192                 inline status_t             set_horizontal(bool value = true) { return set_orientation((value) ? O_HORIZONTAL : O_VERTICAL); }
193 
194                 /** Set grid's vertical spacing
195                  *
196                  * @param value grid's vertical spacing
197                  * @return status of operation
198                  */
199                 status_t                    set_hspacing(size_t value);
200 
201                 /** Set grid's horizontal spacing
202                  *
203                  * @param value grid's horizontal spacing
204                  * @return status of operation
205                  */
206                 status_t                    set_vspacing(size_t value);
207 
208                 /** Set spacing for the grid
209                  *
210                  * @param hor horizontal spacing
211                  * @param vert vertical spacing
212                  * @return status of operation
213                  */
214                 status_t                    set_spacing(size_t hor, size_t vert);
215 
216                 /** Render widget
217                  *
218                  * @param s surface to render
219                  * @param force force flag
220                  */
221                 virtual void render(ISurface *s, bool force);
222 
223                 /** Add widget to the grid
224                  *
225                  * @param widget widget to add
226                  * @return status of operation
227                  */
228                 virtual status_t add(LSPWidget *widget);
229 
230                 /** Add widget to the grid
231                  *
232                  * @param widget widget to add
233                  * @param rowspan number of rows
234                  * @param colspan number of columns
235                  * @return status of operation
236                  */
237                 virtual status_t add(LSPWidget *widget, size_t rowspan, size_t colspan);
238 
239                 /** Remove widget from grid
240                  *
241                  * @param widget widget to remove
242                  * @return status of operation
243                  */
244                 virtual status_t remove(LSPWidget *widget);
245 
246                 /** Realize the widget
247                  *
248                  * @param r realization structure
249                  */
250                 virtual void realize(const realize_t *r);
251 
252                 /** Size request of the widget
253                  *
254                  * @param r size request
255                  */
256                 virtual void size_request(size_request_t *r);
257 
258         };
259 
260     } /* namespace tk */
261 } /* namespace lsp */
262 
263 #endif /* UI_TK_LSPGRID_H_ */
264