libyui-ncurses  2.54.5
NCTablePad.cc
1 /*
2  Copyright (C) 2000-2012 Novell, Inc
3  This library is free software; you can redistribute it and/or modify
4  it under the terms of the GNU Lesser General Public License as
5  published by the Free Software Foundation; either version 2.1 of the
6  License, or (at your option) version 3.0 of the License. This library
7  is distributed in the hope that it will be useful, but WITHOUT ANY
8  WARRANTY; without even the implied warranty of MERCHANTABILITY or
9  FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
10  License for more details. You should have received a copy of the GNU
11  Lesser General Public License along with this library; if not, write
12  to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
13  Floor, Boston, MA 02110-1301 USA
14 */
15 
16 
17 /*-/
18 
19  File: NCTablePad.cc
20 
21  Author: Michael Andres <ma@suse.de>
22 
23 /-*/
24 
25 #define YUILogComponent "ncurses"
26 #include <yui/YUILog.h>
27 #include "NCTablePad.h"
28 #include "NCPopupMenu.h"
29 
30 #include <limits.h>
31 #include <string>
32 
33 
34 void
35 NCTableSortDefault::sort ( std::vector<NCTableLine *>::iterator itemsBegin,
36  std::vector<NCTableLine *>::iterator itemsEnd )
37 {
38  std::sort ( itemsBegin, itemsEnd, Compare(getColumn(), isReverse()) );
39 }
40 
41 
42 bool
43 NCTableSortDefault::Compare::operator() ( const NCTableLine * first,
44  const NCTableLine * second ) const
45 {
46  std::wstring w1 = smartSortKey( first );
47  std::wstring w2 = smartSortKey( second );
48 
49  bool ok1, ok2;
50  long long number1 = toNumber(w1, &ok1);
51  long long number2 = toNumber(w2, &ok2);
52 
53  if ( ok1 && ok2 )
54  {
55  // both are numbers
56  return !reverse ? number1 < number2 : number1 > number2;
57  }
58  else if (ok1 && !ok2)
59  {
60  // int < string
61  return true;
62  }
63  else if (!ok1 && ok2)
64  {
65  // string > int
66  return false;
67  }
68  else
69  {
70  // compare strings using collating information
71  int result = std::wcscoll ( w1.c_str(), w2.c_str() );
72 
73  return !reverse ? result < 0 : result > 0;
74  }
75 }
76 
77 
78 long long
79 NCTableSortDefault::Compare::toNumber(const std::wstring& s, bool* ok) const
80 {
81  try
82  {
83  *ok = true;
84  return std::stoll(s);
85  }
86  catch (...)
87  {
88  *ok = false;
89  return 0;
90  }
91 }
92 
93 
94 std::wstring
95 NCTableSortDefault::Compare::smartSortKey( const NCTableLine * tableLine ) const
96 {
97  const YTableCell* tableCell = tableLine->origItem()->cell(column);
98 
99  if (tableCell->hasSortKey())
100  return NCstring(tableCell->sortKey()).str();
101  else
102  return tableLine->GetCol( column )->Label().getText().begin()->str();
103 }
104 
105 
106 NCTablePad::NCTablePad( int lines, int cols, const NCWidget & p )
107  : NCPad( lines, cols, p )
108  , Headpad( 1, 1 )
109  , dirtyHead( false )
110  , dirtyFormat( false )
111  , ItemStyle( p )
112  , Headline( 0 )
113  , Items( 0 )
114  , citem( 0 )
115  , sortStrategy ( new NCTableSortDefault )
116 {
117 }
118 
119 
120 
121 NCTablePad::~NCTablePad()
122 {
123  ClearTable();
124 }
125 
126 
127 
128 void NCTablePad::assertLine( unsigned idx )
129 {
130  if ( idx >= Lines() )
131  SetLines( idx + 1 );
132 }
133 
134 
135 
136 void NCTablePad::SetLines( unsigned idx )
137 {
138  if ( idx == Lines() )
139  return;
140 
141  unsigned olines = Lines();
142 
143  if ( idx < Lines() )
144  {
145  for ( unsigned i = idx; i < Lines(); ++i )
146  {
147  delete Items[i];
148  }
149  }
150 
151  Items.resize( idx, 0 );
152 
153  for ( unsigned i = olines; i < Lines(); ++i )
154  {
155  if ( !Items[i] )
156  Items[i] = new NCTableLine( 0 );
157  }
158 
159  DirtyFormat();
160 }
161 
162 
163 
164 void NCTablePad::SetLines( std::vector<NCTableLine*> & nItems )
165 {
166  SetLines( 0 );
167  Items = nItems;
168 
169  for ( unsigned i = 0; i < Lines(); ++i )
170  {
171  if ( !Items[i] )
172  Items[i] = new NCTableLine( 0 );
173  }
174 
175  DirtyFormat();
176 }
177 
178 
179 
180 void NCTablePad::AddLine( unsigned idx, NCTableLine * item )
181 {
182  assertLine( idx );
183  delete Items[idx];
184  Items[idx] = item ? item : new NCTableLine( 0 );
185 
186  DirtyFormat();
187 }
188 
189 
190 
191 void NCTablePad::DelLine( unsigned idx )
192 {
193  if ( idx < Lines() )
194  {
195  Items[idx]->ClearLine();
196  DirtyFormat();
197  }
198 }
199 
200 
201 
202 const NCTableLine * NCTablePad::GetLine( unsigned idx ) const
203 {
204  if ( idx < Lines() )
205  return Items[idx];
206 
207  return 0;
208 }
209 
210 
211 
212 NCTableLine * NCTablePad::ModifyLine( unsigned idx )
213 {
214  if ( idx < Lines() )
215  {
216  DirtyFormat();
217  return Items[idx];
218  }
219 
220  return 0;
221 }
222 
223 
224 
225 bool NCTablePad::SetHeadline( const std::vector<NCstring> & head )
226 {
227  bool hascontent = ItemStyle.SetStyleFrom( head );
228  DirtyFormat();
229  update();
230  return hascontent;
231 }
232 
233 
234 
235 void NCTablePad::wRecoded()
236 {
237  DirtyFormat();
238  update();
239 }
240 
241 
242 
243 wpos NCTablePad::CurPos() const
244 {
245  citem.C = srect.Pos.C;
246  return citem;
247 }
248 
249 
250 
251 wsze NCTablePad::UpdateFormat()
252 {
253  // yuiDebug() << std::endl;
254  dirty = true;
255  dirtyFormat = false;
256  ItemStyle.ResetToMinCols();
257 
258  for ( unsigned l = 0; l < Lines(); ++l )
259  {
260  Items[l]->UpdateFormat( ItemStyle );
261  }
262 
263  resize( wsze( Lines(), ItemStyle.TableWidth() ) );
264 
265  return wsze( Lines(), ItemStyle.TableWidth() );
266 }
267 
268 
269 
270 int NCTablePad::DoRedraw()
271 {
272  if ( !Destwin() )
273  {
274  dirty = true;
275  return OK;
276  }
277 
278  // yuiDebug() << "dirtyFormat " << dirtyFormat << std::endl;
279 
280  if ( dirtyFormat )
281  UpdateFormat();
282 
283  bkgdset( ItemStyle.getBG() );
284 
285  clear();
286 
287  wsze lSze( 1, width() );
288 
289  if ( ! pageing() )
290  {
291  for ( unsigned l = 0; l < Lines(); ++l )
292  {
293  Items[l]->DrawAt( *this, wrect( wpos( l, 0 ), lSze ),
294  ItemStyle, (( unsigned )citem.L == l ) );
295  }
296  }
297  // else: item drawing requested via directDraw
298 
299  if ( Headpad.width() != width() )
300  Headpad.resize( 1, width() );
301 
302  Headpad.clear();
303 
304  ItemStyle.Headline().DrawAt( Headpad, wrect( wpos( 0, 0 ), lSze ),
305  ItemStyle, false );
306 
307  SendHead();
308 
309  dirty = false;
310 
311  return update();
312 }
313 
314 
315 
316 void NCTablePad::directDraw( NCursesWindow & w, const wrect at, unsigned lineno )
317 {
318  if ( lineno < Lines() )
319  Items[lineno]->DrawAt( w, at, ItemStyle, ((unsigned)citem.L == lineno) );
320  else
321  yuiWarning() << "Illegal Lineno " << lineno << " (" << Lines() << ")" << std::endl;
322 }
323 
324 
325 
326 int NCTablePad::setpos( const wpos & newpos )
327 {
328  if ( !Lines() )
329  {
330  if ( dirty || dirtyFormat )
331  return DoRedraw();
332 
333  return OK;
334  }
335 
336 #if 0
337  yuiDebug() << newpos << " : l " << Lines() << " : cl " << citem.L
338  << " : d " << dirty << " : df " << dirtyFormat << std::endl;
339 #endif
340 
341  if ( dirtyFormat )
342  UpdateFormat();
343 
344  // save old values
345  int oitem = citem.L;
346 
347  int opos = srect.Pos.C;
348 
349  // calc new values
350  citem.L = newpos.L < 0 ? 0 : newpos.L;
351 
352  if (( unsigned )citem.L >= Lines() )
353  citem.L = Lines() - 1;
354 
355  srect.Pos = wpos( citem.L - ( drect.Sze.H - 1 ) / 2, newpos.C ).between( 0, maxspos );
356 
357  if ( dirty )
358  {
359  return DoRedraw();
360  }
361 
362  if ( ! pageing() )
363  {
364  // adjust only
365  if ( citem.L != oitem )
366  {
367  Items[oitem]->DrawAt( *this, wrect( wpos( oitem, 0 ), wsze( 1, width() ) ),
368  ItemStyle, false );
369  }
370 
371  Items[citem.L]->DrawAt( *this, wrect( wpos( citem.L, 0 ), wsze( 1, width() ) ),
372  ItemStyle, true );
373  }
374  // else: item drawing requested via directDraw
375 
376  if ( srect.Pos.C != opos )
377  SendHead();
378 
379  return update();
380 }
381 
382 
383 
384 void NCTablePad::updateScrollHint()
385 {
386  NCPad::updateScrollHint();
387 }
388 
389 
390 
391 bool NCTablePad::setItemByKey( int key )
392 {
393  if ( HotCol() >= Cols() )
394  return false;
395 
396  if ( key < 0 || UCHAR_MAX < key )
397  return false;
398 
399  unsigned hcol = HotCol();
400 
401  unsigned hkey = tolower( key );
402 
403  for ( unsigned l = 0; l < Lines(); ++l )
404  {
405  if ( Items[l]->GetCol( hcol )->hasHotkey()
406  && (unsigned) tolower( Items[l]->GetCol( hcol )->hotkey() ) == hkey )
407  {
408  ScrlLine( l );
409  return true;
410  }
411  }
412 
413  return false;
414 }
415 
416 //
417 // setOrder() sorts the table according to given column by calling
418 // the sort startegy. Sorting in reverse order is only done
419 // if 'do_reverse' is set to 'true'.
420 //
421 void NCTablePad::setOrder( int col, bool do_reverse )
422 {
423  if ( col < 0 )
424  return;
425 
426  if ( sortStrategy->getColumn() != col )
427  {
428  sortStrategy->setColumn( col );
429  sortStrategy->setReverse( false );
430  }
431  else if ( do_reverse )
432  {
433  sortStrategy->setReverse( !sortStrategy->isReverse() );
434  }
435 
436  // libyui-ncurses-pkg relies on the fact that this function always
437  // does a sort
438 
439  sort();
440 }
441 
442 
443 void NCTablePad::sort()
444 {
445  if (sortStrategy->getColumn() < 0)
446  return;
447 
448  sortStrategy->sort( Items.begin(), Items.end() );
449 
450  dirty = true;
451  update();
452 }
453 
454 
455 
456 bool NCTablePad::handleInput( wint_t key )
457 {
458  return NCPad::handleInput( key );
459 }
460 
461 
462 void NCTablePad::stripHotkeys()
463 {
464  for ( unsigned i = 0; i < Lines(); ++i )
465  {
466  if ( Items[i] )
467  {
468  Items[i]->stripHotkeys();
469  }
470  }
471 }
472 
473 
474 std::ostream & operator<<( std::ostream & str, const NCTablePad & obj )
475 {
476  str << "TablePad: lines " << obj.Lines() << std::endl;
477 
478  for ( unsigned idx = 0; idx < obj.Lines(); ++idx )
479  {
480  str << idx << " " << *obj.GetLine( idx );
481  }
482 
483  return str;
484 }
C++ class for windows.
Definition: ncursesw.h:903
int clear()
Clear the window.
Definition: ncursesw.h:1521
void bkgdset(chtype ch)
Set the background property.
Definition: ncursesw.h:1447
Definition: NCPad.h:93
Definition: position.h:109
virtual void directDraw(NCursesWindow &w, const wrect at, unsigned lineno)
Directly draw a table item at a specific location.
Definition: NCTablePad.cc:316
int width() const
Number of columns in this window.
Definition: ncursesw.h:1074
Definition: position.h:154
WINDOW * w
the curses WINDOW
Definition: ncursesw.h:946
bool pageing() const
Whether the Pad is truncated (we&#39;re pageing).
Definition: NCPad.h:129