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