Line data Source code
1 :
2 : #ifndef cursesTableGrid_hpp
3 : #define cursesTableGrid_hpp
4 :
5 : #include <fstream>
6 :
7 : #include <ncurses.h>
8 :
9 : class cursesTableGrid
10 : {
11 : public:
12 :
13 : std::ofstream * fpout {nullptr};
14 :
15 : int m_xLeft {1};
16 : int m_yTop {1};
17 : int m_xRight {-1};
18 : int m_yBot {-1};
19 :
20 : int m_minWidth {78};
21 :
22 : size_t m_currX {0};
23 : size_t m_currY {0};
24 :
25 : size_t m_startRow {0};
26 :
27 : std::vector<std::vector<std::string>> m_cellContents;
28 :
29 : std::vector<float> m_colFraction;
30 :
31 :
32 : WINDOW * m_boxWin {nullptr};
33 : std::vector<std::vector<WINDOW *>> m_gridWin;
34 :
35 : int minWidth( int mw );
36 :
37 : int colWidth( const std::vector<int> & cw );
38 :
39 : int colFraction( const std::vector<float> & cf );
40 :
41 0 : int tabHeight()
42 : {
43 0 : return m_gridWin.size();
44 : }
45 :
46 : bool hasContent( size_t y,
47 : size_t x
48 : );
49 :
50 : int draw();
51 0 : virtual int postDraw()
52 : {
53 0 : return 0;
54 : }
55 :
56 : int print();
57 :
58 0 : virtual int postPrint()
59 : {
60 0 : return 0;
61 : }
62 :
63 : int moveSelected( int nextY,
64 : int nextX
65 : );
66 :
67 : //Call after setting fraction.
68 : int testContents(int nrows);
69 : };
70 :
71 : inline
72 0 : int cursesTableGrid::minWidth( int mw )
73 : {
74 0 : m_minWidth = mw;
75 0 : return 0;
76 : }
77 :
78 : inline
79 0 : int cursesTableGrid::colWidth( const std::vector<int> & cw )
80 : {
81 :
82 0 : int mw = 0;
83 0 : for(size_t i=0;i<cw.size();++i) mw += cw[i];
84 :
85 0 : if( minWidth(mw) < 0)
86 : {
87 0 : return -1;
88 : }
89 :
90 0 : std::vector<float> cf(cw.size());
91 :
92 0 : for(size_t i=0;i<cf.size();++i)
93 : {
94 0 : cf[i] = cw[i];
95 0 : cf[i] /= m_minWidth;
96 : }
97 :
98 0 : return colFraction(cf);
99 0 : }
100 :
101 : inline
102 0 : int cursesTableGrid::colFraction( const std::vector<float> & cf )
103 : {
104 0 : m_colFraction = cf;
105 :
106 0 : return 0;
107 : }
108 :
109 : inline
110 0 : bool cursesTableGrid::hasContent( size_t y,
111 : size_t x
112 : )
113 : {
114 0 : bool hascontent = false;
115 0 : if(y < m_cellContents.size())
116 : {
117 0 : if(x < m_cellContents[y].size()) hascontent = true;
118 : }
119 :
120 0 : return hascontent;
121 : }
122 :
123 : inline
124 0 : int cursesTableGrid::draw()
125 : {
126 : //Todo: box on/off selectable
127 : //Todo: if box on, must be y0>=1, x0>=1
128 :
129 0 : int tabHeight = LINES - m_yTop - 1;
130 0 : if(m_yBot > 0 ) tabHeight -= m_yBot; //else -= 1.
131 :
132 0 : int tabWidth = COLS - m_xLeft - 1;
133 0 : if(m_xRight > 0 ) tabWidth -= m_xRight + 1;
134 :
135 0 : if(m_boxWin)
136 0 : { werase(m_boxWin);
137 0 : wrefresh(m_boxWin);
138 0 : delwin(m_boxWin);
139 : }
140 :
141 0 : m_boxWin = newwin(tabHeight+2, tabWidth+2, m_yTop-1,m_xLeft-1);
142 0 : box(m_boxWin, 0, 0);
143 0 : wrefresh(m_boxWin);
144 :
145 0 : if(m_gridWin.size() > 0)
146 : {
147 0 : for(size_t y =0; y < m_gridWin.size(); ++y)
148 : {
149 0 : for(size_t x=0; x < m_gridWin[y].size(); ++x)
150 : {
151 0 : delwin(m_gridWin[y][x]);
152 : }
153 : }
154 : }
155 :
156 0 : int nDispRow = tabHeight;
157 :
158 0 : int workingWidth = tabWidth;
159 0 : if(workingWidth < m_minWidth) workingWidth = m_minWidth;
160 :
161 0 : int spos = 0;
162 0 : std::vector<int> dispCol_start;
163 0 : std::vector<int> dispCol_width;
164 0 : for(size_t i=0; i< m_colFraction.size(); ++i)
165 : {
166 0 : int cw = m_colFraction[i] * workingWidth + 0.5; //rounded
167 :
168 0 : if(spos + cw > tabWidth) cw = tabWidth-spos;
169 :
170 0 : if(cw == 0 ) break;
171 :
172 0 : dispCol_start.push_back(spos);
173 0 : dispCol_width.push_back(cw);
174 :
175 0 : spos += cw;
176 :
177 0 : if(spos >= tabWidth) break;
178 : }
179 :
180 0 : m_gridWin.resize(nDispRow);
181 :
182 0 : std::string ch;
183 :
184 0 : for(size_t y=0; y< m_gridWin.size(); ++y)
185 : {
186 0 : m_gridWin[y].resize(dispCol_start.size());
187 :
188 0 : if(fpout) *fpout << y;
189 0 : for(size_t x=0; x< m_gridWin[y].size(); ++x)
190 : {
191 0 : m_gridWin[y][x] = newwin(1, dispCol_width[x], m_yTop+y,m_xLeft + dispCol_start[x]);
192 :
193 0 : if(fpout) *fpout << ": " << x << " (" << dispCol_start[x] << "," << dispCol_width[x] << ")";
194 :
195 0 : if(hasContent(m_startRow+y,x)) wprintw(m_gridWin[y][x], "%s", m_cellContents[m_startRow + y][x].c_str());
196 : //else wprintw(m_gridWin[y][x], ".");
197 0 : wrefresh(m_gridWin[y][x]);
198 : }
199 0 : if(fpout) *fpout << std::endl;
200 : }
201 :
202 : //Move cursor if needed.
203 0 : if(m_currY >= m_gridWin.size()) m_currY = m_gridWin.size()-1;
204 0 : if(m_currX >= m_gridWin[m_currY].size()) m_currX = m_gridWin[m_currY].size()-1;
205 :
206 0 : wattron(m_gridWin[m_currY][m_currX], A_REVERSE);
207 0 : wclear(m_gridWin[m_currY][m_currX]);
208 0 : if(hasContent(m_startRow + m_currY, m_currX)) wprintw(m_gridWin[m_currY][m_currX], "%s", m_cellContents[m_startRow+m_currY][m_currX].c_str());
209 0 : wrefresh(m_gridWin[m_currY][m_currX]);
210 :
211 :
212 0 : if(fpout) *fpout << "drawn" << std::endl;
213 :
214 0 : return postDraw();
215 0 : }
216 :
217 : inline
218 0 : int cursesTableGrid::print()
219 : {
220 0 : for(size_t y=0; y< m_gridWin.size(); ++y)
221 : {
222 0 : for(size_t x=0; x< m_gridWin[y].size(); ++x)
223 : {
224 0 : wclear(m_gridWin[y][x]);
225 0 : if(hasContent(m_startRow+y,x)) wprintw(m_gridWin[y][x], "%s", m_cellContents[m_startRow + y][x].c_str());
226 0 : wrefresh(m_gridWin[y][x]);
227 : }
228 : }
229 :
230 0 : return postPrint();
231 : }
232 :
233 : inline
234 : int cursesTableGrid::testContents(int nrows)
235 : {
236 : m_cellContents.resize(nrows);
237 :
238 : for(size_t y=0;y<m_cellContents.size(); ++y)
239 : {
240 : m_cellContents[y].resize(m_colFraction.size());
241 : }
242 :
243 : std::string ch;
244 : for(size_t y=0;y<m_cellContents.size(); ++y)
245 : {
246 : for(size_t x=0; x< m_colFraction.size(); ++x)
247 : {
248 : size_t cw = m_colFraction[x] * m_minWidth + 0.5;
249 :
250 : ch=std::to_string(y) + "," + std::to_string(x);
251 : if( cw > ch.size()+1) ch += std::string( cw-ch.size()-1,'*');
252 : ch += "|";
253 :
254 : if(ch.size() > cw) ch.erase(cw);
255 :
256 : m_cellContents[y][x] = ch;
257 : }
258 : }
259 :
260 : return 0;
261 : }
262 :
263 :
264 : inline
265 0 : int cursesTableGrid::moveSelected( int nextY,
266 : int nextX
267 : )
268 : {
269 : //Do some bounds checks
270 0 : if(m_cellContents.size() == 0 || m_currY >= m_gridWin.size()) return 0;
271 0 : if(m_currX >= m_gridWin[m_currY].size()) return 0;
272 :
273 : //Now turn off the reverse
274 0 : wattroff(m_gridWin[m_currY][m_currX], A_REVERSE);
275 :
276 0 : wclear(m_gridWin[m_currY][m_currX]);
277 0 : if(hasContent(m_startRow + m_currY, m_currX)) wprintw(m_gridWin[m_currY][m_currX], "%s", m_cellContents[m_startRow+m_currY][m_currX].c_str());
278 0 : wrefresh(m_gridWin[m_currY][m_currX]);
279 :
280 0 : if(fpout) *fpout << "nextY: " << nextY << " m_gridWin.size(): " << m_gridWin.size() << std::endl;
281 :
282 0 : bool reprint = false;
283 0 : if(nextY >= (int64_t) m_gridWin.size())
284 : {
285 0 : size_t oldSR = m_startRow;
286 0 : m_startRow += nextY - m_gridWin.size() + 1;
287 :
288 0 : if(m_startRow >= m_cellContents.size()) m_startRow = m_cellContents.size()-1;
289 :
290 0 : if( oldSR != m_startRow) reprint = true;
291 :
292 0 : if(fpout) *fpout << "+m_startRow: " << m_startRow << " " << reprint << std::endl;
293 :
294 0 : nextY = m_gridWin.size()-1;
295 : }
296 :
297 0 : if(nextY < 0)
298 : {
299 0 : size_t oldSR = m_startRow;
300 :
301 0 : if(m_startRow > 0)
302 : {
303 0 : if(m_startRow < (size_t) (-nextY)) m_startRow = 0;
304 0 : else m_startRow += nextY;
305 : }
306 :
307 0 : if( oldSR != m_startRow) reprint = true;
308 :
309 0 : if(fpout) *fpout << "-m_startRow: " << m_startRow << " " << reprint << std::endl;
310 :
311 0 : nextY = 0;
312 : }
313 :
314 0 : if(reprint) print();
315 :
316 : //Move the cursor position
317 0 : if(nextY >= 0 && nextY < (int64_t) m_gridWin.size() && nextX >= 0 && nextX < (int64_t) m_gridWin[0].size())
318 : {
319 0 : m_currY = nextY;
320 0 : m_currX = nextX;
321 : }
322 :
323 : //Turn it back on
324 0 : wattron(m_gridWin[m_currY][m_currX], A_REVERSE);
325 :
326 0 : wclear(m_gridWin[m_currY][m_currX]);
327 0 : if(hasContent(m_startRow + m_currY, m_currX)) wprintw(m_gridWin[m_currY][m_currX], "%s", m_cellContents[m_startRow+m_currY][m_currX].c_str());
328 0 : else wprintw(m_gridWin[m_currY][m_currX], " ");
329 0 : wrefresh(m_gridWin[m_currY][m_currX]);
330 :
331 0 : wattroff(m_gridWin[m_currY][m_currX], A_REVERSE);
332 :
333 0 : return 0;
334 : }
335 :
336 :
337 : #endif //cursesTableGrid_hpp
|