libyui-ncurses  2.43.3.1
 All Classes Functions Variables
NCTable.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: NCTable.cc
20 
21  Author: Michael Andres <ma@suse.de>
22 
23 /-*/
24 
25 #define YUILogComponent "ncurses"
26 #include <yui/YUILog.h>
27 #include "NCTable.h"
28 #include "NCPopupMenu.h"
29 #include <yui/YMenuButton.h>
30 #include <yui/YTypes.h>
31 
32 using std::endl;
33 
34 NCTable::NCTable( YWidget * parent, YTableHeader *tableHeader, bool multiSelection )
35  : YTable( parent, tableHeader, multiSelection )
36  , NCPadWidget( parent )
37  , biglist( false )
38  , multiselect( multiSelection )
39 {
40  yuiDebug() << std::endl;
41 
42  InitPad();
43  // !!! head is UTF8 encoded, thus should be std::vector<NCstring>
44  if ( !multiselect )
45  {
46  _header.assign( tableHeader->columns(), NCstring( "" ) );
47  for ( int col = 0; col < tableHeader->columns(); col++ )
48  {
49  if ( hasColumn( col ) )
50  {
51  // set alignment first
52  setAlignment( col, alignment( col ) );
53  // and then append header
54  _header[ col ] += NCstring( tableHeader->header( col ) ) ;
55  }
56  }
57  }
58  else
59  {
60  _header.assign( tableHeader->columns()+1, NCstring( "" ) );
61 
62  for ( int col = 1; col <= tableHeader->columns(); col++ )
63  {
64  if ( hasColumn( col-1 ) )
65  {
66  // set alignment first
67  setAlignment( col, alignment( col-1 ) );
68  // and then append header
69  _header[ col ] += NCstring( tableHeader->header( col-1 ) ) ;
70  }
71  }
72  }
73 
74  hasHeadline = myPad()->SetHeadline( _header );
75 
76 }
77 
78 
79 
80 
81 NCTable::~NCTable()
82 {
83  yuiDebug() << std::endl;
84 }
85 
86 
87 
88 // Change individual cell of a table line (to newtext)
89 // provided for backwards compatibility
90 
91 void NCTable::cellChanged( int index, int colnum, const std::string & newtext )
92 {
93  NCTableLine * cl = myPad()->ModifyLine( index );
94 
95  if ( !cl )
96  {
97  yuiWarning() << "No such line: " << wpos( index, colnum ) << newtext << std::endl;
98  }
99  else
100  {
101  NCTableCol * cc = cl->GetCol( colnum );
102 
103  if ( !cc )
104  {
105  yuiWarning() << "No such colnum: " << wpos( index, colnum ) << newtext << std::endl;
106  }
107  else
108  {
109  // use NCtring to enforce recoding from 'utf8'
110  cc->SetLabel( NCstring( newtext ) );
111  DrawPad();
112  }
113  }
114 }
115 
116 
117 
118 // Change individual cell of a table line (to newtext)
119 
120 void NCTable::cellChanged( const YTableCell *cell )
121 {
122 
123  cellChanged( cell->itemIndex(), cell->column(), cell->label() );
124 
125 }
126 
127 
128 
129 // Set all table headers all at once
130 
131 void NCTable::setHeader( std::vector<std::string> head )
132 {
133  _header.assign( head.size(), NCstring( "" ) );
134  YTableHeader *th = new YTableHeader();
135 
136  for ( unsigned int i = 0; i < head.size(); i++ )
137  {
138  th->addColumn( head[ i ] );
139  _header[ i ] += NCstring( head[ i ] ) ;
140  }
141 
142  hasHeadline = myPad()->SetHeadline( _header );
143 
144  YTable::setTableHeader( th );
145 }
146 
147 //
148 // Return table header as std::string std::vector (alignment removed)
149 //
150 void NCTable::getHeader( std::vector<std::string> & header )
151 {
152  header.assign( _header.size(), "" );
153 
154  for ( unsigned int i = 0; i < _header.size(); i++ )
155  {
156  header[ i ] = _header[i].Str().substr( 1 ); // remove alignment
157  }
158 }
159 
160 
161 // Set alignment of i-th table column (left, right, center).
162 // Create temp. header consisting of single letter;
163 // setHeader will append the rest.
164 
165 void NCTable::setAlignment( int col, YAlignmentType al )
166 {
167  std::string s;
168 
169  switch ( al )
170  {
171  case YAlignUnchanged:
172  s = 'L' ;
173  break;
174 
175  case YAlignBegin:
176  s = 'L' ;
177  break;
178 
179  case YAlignCenter:
180  s = 'C' ;
181  break;
182 
183  case YAlignEnd:
184  s = 'R' ;
185  break;
186  }
187 
188  _header[ col ] = NCstring( s );
189 }
190 
191 // Append item (as pointed to by 'yitem') in one-by-one
192 // fashion i.e. the whole table gets redrawn afterwards.
193 void NCTable::addItem( YItem *yitem)
194 {
195  addItem(yitem, false); // add just this one
196 }
197 
198 // Append item (as pointed to by 'yitem') to a table.
199 // This creates visual representation of new table line
200 // consisting of individual cells. Depending on the 2nd
201 // param, table is redrawn. If 'allAtOnce' is set to
202 // true, it is up to the caller to redraw the table.
203 void NCTable::addItem( YItem *yitem, bool allAtOnce )
204 {
205 
206  YTableItem *item = dynamic_cast<YTableItem *>( yitem );
207  YUI_CHECK_PTR( item );
208  YTable::addItem( item );
209  unsigned int itemCount;
210 
211  if ( !multiselect )
212  itemCount = item->cellCount();
213  else
214  itemCount = item->cellCount()+1;
215 
216  std::vector<NCTableCol*> Items( itemCount );
217  unsigned int i = 0;
218 
219  if ( !multiselect )
220  {
221  // Iterate over cells to create columns
222  for ( YTableCellIterator it = item->cellsBegin();
223  it != item->cellsEnd();
224  ++it )
225  {
226  Items[i] = new NCTableCol( NCstring(( *it )->label() ) );
227  i++;
228  }
229  }
230  else
231  {
232  // Create the tag first
233  Items[0] = new NCTableTag( yitem, yitem->selected() );
234  i++;
235  // and then iterate over cells
236  for ( YTableCellIterator it = item->cellsBegin();
237  it != item->cellsEnd();
238  ++it )
239  {
240  Items[i] = new NCTableCol( NCstring(( *it )->label() ) );
241  i++;
242  }
243  }
244 
245  //Insert @idx
246  NCTableLine *newline = new NCTableLine( Items, item->index() );
247 
248  YUI_CHECK_PTR( newline );
249 
250  newline->setOrigItem( item );
251 
252  myPad()->Append( newline );
253 
254  if ( item->selected() )
255  {
256  setCurrentItem( item->index() ) ;
257  }
258 
259  //in one-by-one mode, redraw the table (otherwise, leave it
260  //up to the caller)
261  if (!allAtOnce)
262  {
263  DrawPad();
264  }
265 }
266 
267 // reimplemented here to speed up item insertion
268 // (and prevent inefficient redrawing after every single addItem
269 // call)
270 void NCTable::addItems( const YItemCollection & itemCollection )
271 {
272 
273  for ( YItemConstIterator it = itemCollection.begin();
274  it != itemCollection.end();
275  ++it )
276  {
277  addItem( *it, true);
278  }
279  DrawPad();
280 }
281 
282 // Clear the table (in terms of YTable and visually)
283 
284 void NCTable::deleteAllItems()
285 {
286  myPad()->ClearTable();
287  DrawPad();
288  YTable::deleteAllItems();
289 }
290 
291 
292 
293 // Return index of currently selected table item
294 
295 int NCTable::getCurrentItem()
296 {
297  if ( !myPad()->Lines() )
298  return -1;
299 
300  return keepSorting() ? myPad()->GetLine( myPad()->CurPos().L )->getIndex()
301  : myPad()->CurPos().L;
302 
303 }
304 
305 
306 
307 // Return origin pointer of currently selected table item
308 
309 YItem * NCTable::getCurrentItemPointer()
310 {
311  const NCTableLine *cline = myPad()->GetLine( myPad()->CurPos().L );
312 
313  if ( cline )
314  return cline->origItem();
315  else
316  return 0;
317 }
318 
319 
320 
321 // Highlight item at 'index'
322 
323 void NCTable::setCurrentItem( int index )
324 {
325  myPad()->ScrlLine( index );
326 }
327 
328 
329 
330 // Mark table item (as pointed to by 'yitem') as selected
331 
332 void NCTable::selectItem( YItem *yitem, bool selected )
333 {
334  if ( ! yitem )
335  return;
336 
337  YTableItem *item = dynamic_cast<YTableItem *>( yitem );
338  YUI_CHECK_PTR( item );
339 
340  NCTableLine *line = ( NCTableLine * )item->data();
341  YUI_CHECK_PTR( line );
342 
343  const NCTableLine *current_line = myPad()->GetLine( myPad()->CurPos().L );
344  YUI_CHECK_PTR( current_line );
345 
346  if ( !multiselect )
347  {
348  if ( !selected && ( line == current_line ) )
349  {
350  deselectAllItems();
351  }
352  else
353  {
354  // first highlight only, then select
355  setCurrentItem( line->getIndex() );
356  YTable::selectItem( item, selected );
357  }
358  }
359  else
360  {
361  setCurrentItem( line->getIndex() );
362  YTable::selectItem( item, selected );
363 
364  yuiMilestone() << item->label() << " is selected: " << (selected?"yes":"no") << endl;
365 
366  NCTableTag *tag = static_cast<NCTableTag *>( line->GetCol( 0 ) );
367  tag->SetSelected( selected );
368  }
369 
370  // and redraw
371  DrawPad();
372 }
373 
374 
375 
376 // Mark currently highlighted table item as selected
377 // Yeah, it is really already highlighted, so no need to
378 // selectItem() and setCurrentItem() here again - #493884
379 
380 void NCTable::selectCurrentItem()
381 {
382  const NCTableLine *cline = myPad()->GetLine( myPad()->CurPos().L );
383 
384  if ( cline )
385  YTable::selectItem( cline->origItem(), true );
386 }
387 
388 
389 
390 // Mark all items as deselected
391 
392 void NCTable::deselectAllItems()
393 {
394  setCurrentItem( -1 );
395  YTable::deselectAllItems();
396  DrawPad();
397 }
398 
399 
400 
401 // return preferred size
402 
403 int NCTable::preferredWidth()
404 {
405  wsze sze = ( biglist ) ? myPad()->tableSize() + 2 : wGetDefsze();
406  return sze.W;
407 }
408 
409 
410 
411 // return preferred size
412 
413 int NCTable::preferredHeight()
414 {
415  wsze sze = ( biglist ) ? myPad()->tableSize() + 2 : wGetDefsze();
416  return sze.H;
417 }
418 
419 
420 
421 // Set new size of the widget
422 
423 void NCTable::setSize( int newwidth, int newheight )
424 {
425  wRelocate( wpos( 0 ), wsze( newheight, newwidth ) );
426 }
427 
428 
429 
430 
431 void NCTable::setLabel( const std::string & nlabel )
432 {
433  // not implemented: YTable::setLabel( nlabel );
434  NCPadWidget::setLabel( NCstring( nlabel ) );
435 }
436 
437 
438 
439 // Set widget state (enabled vs. disabled)
440 
441 void NCTable::setEnabled( bool do_bv )
442 {
443  NCWidget::setEnabled( do_bv );
444  YTable::setEnabled( do_bv );
445 }
446 
447 
448 
449 
450 bool NCTable::setItemByKey( int key )
451 {
452  return myPad()->setItemByKey( key );
453 }
454 
455 
456 
457 
458 
459 // Create new NCTablePad, set its background
460 NCPad * NCTable::CreatePad()
461 {
462  wsze psze( defPadSze() );
463  NCPad * npad = new NCTablePad( psze.H, psze.W, *this );
464  npad->bkgd( listStyle().item.plain );
465 
466  return npad;
467 }
468 
469 
470 
471 // Handle 'special' keys i.e those not handled by parent NCPad class
472 // (space, return). Set items to selected, if appropriate.
473 
474 NCursesEvent NCTable::wHandleInput( wint_t key )
475 {
476  NCursesEvent ret;
477  int citem = getCurrentItem();
478 
479  if ( ! handleInput( key ) )
480  {
481  switch ( key )
482  {
483  case CTRL( 'o' ):
484  {
485  if ( ! keepSorting() )
486  {
487  // get the column
488  wpos at( ScreenPos() + wpos( win->height() / 2, 1 ) );
489 
490  YItemCollection ic;
491  ic.reserve( _header.size() );
492  unsigned int i = 0;
493 
494  for ( std::vector<NCstring>::const_iterator it = _header.begin();
495  it != _header.end() ; it++, i++ )
496  {
497  // strip the align mark
498  std::string col = ( *it ).Str();
499  col.erase( 0, 1 );
500 
501  YMenuItem *item = new YMenuItem( col ) ;
502  //need to set index explicitly, MenuItem inherits from TreeItem
503  //and these don't have indexes set
504  item->setIndex( i );
505  ic.push_back( item );
506  }
507 
508  NCPopupMenu *dialog = new NCPopupMenu( at, ic.begin(), ic.end() );
509 
510  int column = dialog->post();
511 
512  if ( column != -1 )
513  myPad()->setOrder( column, true ); //enable sorting in reverse order
514 
515  //remove the popup
516  YDialog::deleteTopmostDialog();
517 
518  return NCursesEvent::none;
519  }
520  }
521 
522  case KEY_SPACE:
523  case KEY_RETURN:
524  if ( !multiselect )
525  {
526  if ( notify() && citem != -1 )
527  return NCursesEvent::Activated;
528  }
529  else
530  {
531  toggleCurrentItem();
532  }
533  break;
534 
535  }
536  }
537 
538 
539  if ( citem != getCurrentItem() )
540  {
541  if ( notify() && immediateMode() )
542  ret = NCursesEvent::SelectionChanged;
543 
544  if ( !multiselect )
545  selectCurrentItem();
546  }
547 
548  return ret;
549 }
550 
551 /**
552  * Toggle item from selected -> deselected and vice versa
553  **/
555 {
556  YTableItem *it = dynamic_cast<YTableItem *>( getCurrentItemPointer() );
557  if ( it )
558  {
559  selectItem( it, !( it->selected() ) );
560  }
561 }