libyui-ncurses  2.44.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 /*
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  setCurrentItem( line->getIndex() );
376  YTable::selectItem( item, selected );
377 
378  yuiMilestone() << item->label() << " is selected: " << (selected?"yes":"no") << endl;
379 
380  NCTableTag *tag = static_cast<NCTableTag *>( line->GetCol( 0 ) );
381  tag->SetSelected( selected );
382  }
383 
384  // and redraw
385  DrawPad();
386 }
387 
388 
389 
390 // Mark currently highlighted table item as selected
391 // Yeah, it is really already highlighted, so no need to
392 // selectItem() and setCurrentItem() here again - #493884
393 
394 void NCTable::selectCurrentItem()
395 {
396  const NCTableLine *cline = myPad()->GetLine( myPad()->CurPos().L );
397 
398  if ( cline )
399  YTable::selectItem( cline->origItem(), true );
400 }
401 
402 
403 
404 // Mark all items as deselected
405 
406 void NCTable::deselectAllItems()
407 {
408  if ( !multiselect )
409  {
410  setCurrentItem( -1 );
411  YTable::deselectAllItems();
412  }
413  else
414  {
415  YItemCollection itemCollection = YTable::selectedItems();
416  for ( YItemConstIterator it = itemCollection.begin();
417  it != itemCollection.end(); ++it )
418  {
419  selectItem( *it, false ); // YTable::selectItem(item,false)
420  }
421  }
422 
423  DrawPad();
424 }
425 
426 
427 
428 // return preferred size
429 
430 int NCTable::preferredWidth()
431 {
432  wsze sze = ( biglist ) ? myPad()->tableSize() + 2 : wGetDefsze();
433  return sze.W;
434 }
435 
436 
437 
438 // return preferred size
439 
440 int NCTable::preferredHeight()
441 {
442  wsze sze = ( biglist ) ? myPad()->tableSize() + 2 : wGetDefsze();
443  return sze.H;
444 }
445 
446 
447 
448 // Set new size of the widget
449 
450 void NCTable::setSize( int newwidth, int newheight )
451 {
452  wRelocate( wpos( 0 ), wsze( newheight, newwidth ) );
453 }
454 
455 
456 
457 
458 void NCTable::setLabel( const std::string & nlabel )
459 {
460  // not implemented: YTable::setLabel( nlabel );
461  NCPadWidget::setLabel( NCstring( nlabel ) );
462 }
463 
464 
465 
466 // Set widget state (enabled vs. disabled)
467 
468 void NCTable::setEnabled( bool do_bv )
469 {
470  NCWidget::setEnabled( do_bv );
471  YTable::setEnabled( do_bv );
472 }
473 
474 
475 
476 
477 bool NCTable::setItemByKey( int key )
478 {
479  return myPad()->setItemByKey( key );
480 }
481 
482 
483 
484 
485 
486 // Create new NCTablePad, set its background
487 NCPad * NCTable::CreatePad()
488 {
489  wsze psze( defPadSze() );
490  NCPad * npad = new NCTablePad( psze.H, psze.W, *this );
491  npad->bkgd( listStyle().item.plain );
492 
493  return npad;
494 }
495 
496 
497 
498 // Handle 'special' keys i.e those not handled by parent NCPad class
499 // (space, return). Set items to selected, if appropriate.
500 
501 NCursesEvent NCTable::wHandleInput( wint_t key )
502 {
503  NCursesEvent ret;
504  int citem = getCurrentItem();
505  bool sendEvent = false;
506 
507  if ( ! handleInput( key ) )
508  {
509  switch ( key )
510  {
511  case CTRL( 'o' ):
512  {
513  if ( ! keepSorting() )
514  {
515  // get the column
516  wpos at( ScreenPos() + wpos( win->height() / 2, 1 ) );
517 
518  YItemCollection ic;
519  ic.reserve( _header.size() );
520  unsigned int i = 0;
521 
522  for ( std::vector<NCstring>::const_iterator it = _header.begin();
523  it != _header.end() ; it++, i++ )
524  {
525  // strip the align mark
526  std::string col = ( *it ).Str();
527  col.erase( 0, 1 );
528 
529  YMenuItem *item = new YMenuItem( col ) ;
530  //need to set index explicitly, MenuItem inherits from TreeItem
531  //and these don't have indexes set
532  item->setIndex( i );
533  ic.push_back( item );
534  }
535 
536  NCPopupMenu *dialog = new NCPopupMenu( at, ic.begin(), ic.end() );
537 
538  int column = dialog->post();
539 
540  if ( column != -1 )
541  myPad()->setOrder( column, true ); //enable sorting in reverse order
542 
543  //remove the popup
544  YDialog::deleteTopmostDialog();
545 
546  return NCursesEvent::none;
547  }
548  }
549 
550  case KEY_RETURN:
551  sendEvent = true;
552  case KEY_SPACE:
553  if ( !multiselect )
554  {
555  if ( notify() && citem != -1 )
556  return NCursesEvent::Activated;
557  }
558  else
559  {
560  toggleCurrentItem();
561  // send ValueChanged on Return (like done for NCTree multiSelection)
562  if ( notify() && sendEvent )
563  {
564  return NCursesEvent::ValueChanged;
565  }
566  }
567  break;
568 
569  }
570  }
571 
572 
573  if ( citem != getCurrentItem() )
574  {
575  if ( notify() && immediateMode() )
576  ret = NCursesEvent::SelectionChanged;
577 
578  if ( !multiselect )
579  selectCurrentItem();
580  }
581 
582  return ret;
583 }
584 
585 /**
586  * Toggle item from selected -> deselected and vice versa
587  **/
589 {
590  YTableItem *it = dynamic_cast<YTableItem *>( getCurrentItemPointer() );
591  if ( it )
592  {
593  selectItem( it, !( it->selected() ) );
594  }
595 }
int bkgd(const chtype ch)
Definition: ncursesw.h:1443
Definition: NCPad.h:93
Definition: position.h:109
virtual void setEnabled(bool do_bv)
Definition: NCTable.cc:468
virtual void setEnabled(bool do_bv)=0
Definition: NCWidget.cc:391
Definition: position.h:154
void toggleCurrentItem()
Definition: NCTable.cc:588