ui/listwidget.h

Go to the documentation of this file.
00001 // -*- c++ -*-
00002 //
00003 // $Id: listwidget.h,v 1.12 2008-02-19 12:03:38 rafi Exp $
00004 //
00005 // YAPET -- Yet Another Password Encryption Tool
00006 // Copyright (C) 2008  Rafael Ostertag
00007 //
00008 // This program is free software: you can redistribute it and/or modify
00009 // it under the terms of the GNU General Public License as published by
00010 // the Free Software Foundation, either version 3 of the License, or
00011 // (at your option) any later version.
00012 //
00013 // This program is distributed in the hope that it will be useful,
00014 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00015 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016 // GNU General Public License for more details.
00017 //
00018 // You should have received a copy of the GNU General Public License
00019 // along with this program.  If not, see <http://www.gnu.org/licenses/>.
00020 //
00021 
00022 #ifndef _LISTWIDGET_H
00023 #define _LISTWIDGET_H
00024 
00025 #ifdef HAVE_CONFIG_H
00026 # include <config.h>
00027 #endif
00028 
00029 #ifdef HAVE_NCURSES_H
00030 # include <ncurses.h>
00031 #else // HAVE_NCURSES_H
00032 # ifdef HAVE_CURSES_H
00033 #  include <curses.h>
00034 # else
00035 #  error "Neither curses.h nor ncurses.h available"
00036 # endif // HAVE_CURSES_H
00037 #endif // HAVE_NCURSES_H
00038 #include "curswa.h" // Leave this here. It depends on the above includes.
00039 
00040 #ifdef HAVE_ITERATOR
00041 # include <iterator>
00042 #endif
00043 
00044 #ifdef HAVE_LIST
00045 # include <list>
00046 #endif
00047 
00048 #include "uiexception.h"
00049 #include "colors.h"
00050 #include "basewindow.h"
00051 
00052 namespace YAPETUI {
00053 
00068     template<class T>
00069     class ListWidget {
00070     private:
00071         WINDOW* window;
00072 
00073         int width;
00074         int height;
00075 
00082         int start_pos;
00090         int cur_pos;
00091 
00092     protected:
00093         typename std::list<T> itemlist;
00094         typedef typename std::list<T>::size_type l_size_type;
00095 
00096         inline ListWidget(const ListWidget& lw) {}
00097         inline const ListWidget& operator=(const ListWidget& lw) { return *this; }
00098 
00099         int pagesize() { return height-2; }
00100 
00101         void clearWin() throw(UIException) {
00102         Colors::setcolor(window, LISTWIDGET);
00103         int retval = wclear(window);
00104         if (retval == ERR)
00105             throw UIException("Error clearing window");
00106 
00107         retval = box(window, 0, 0);
00108         if (retval == ERR)
00109             throw UIException("Error drawing box around window");
00110         }
00111 
00112         void showScrollIndicators() throw(UIException) {
00113         if (start_pos > 0) {
00114             int retval = mvwaddch(window,
00115                       1,
00116                       width - 1,
00117                       '^');
00118             if (retval == ERR)
00119             throw UIException("Unable to display scroll up indicator");
00120         }
00121 
00122         if ( itemlist.size() - 1  > start_pos + cur_pos &&
00123              itemlist.size() > pagesize()) {
00124             int retval = mvwaddch(window,
00125                       height - 2,
00126                       width - 1,
00127                       'v');
00128             if (retval == ERR)
00129             throw UIException("Unable to display scroll down indicator");
00130         }
00131         }
00132 
00133         void showListItems() throw(UIException) {
00134         int usable_width = width - 2;
00135 
00136         clearWin();
00137 
00138         typename std::list<T>::iterator itemlist_pos = itemlist.begin();
00139         // Advance to the start point
00140         for(int i=0; i<start_pos; itemlist_pos++,i++);
00141 
00142         for(int i=0; i<pagesize() && itemlist_pos != itemlist.end(); itemlist_pos++, i++) {
00143             int retval = mymvwaddnstr(window,
00144                           1 + i,
00145                           1,
00146                           (*itemlist_pos).c_str(),
00147                           usable_width);
00148             if (retval == ERR)
00149             throw UIException("Unable to display item");
00150         }
00151 
00152         showScrollIndicators();
00153         }
00154 
00155         void showSelected(int old_pos) throw(UIException) {
00156         int retval = 0;
00157 
00158         if (itemlist.size() > 0) {
00159             retval = mymvwchgat(window,
00160                       cur_pos + 1,
00161                       1,
00162                       width-2,
00163                       A_REVERSE,
00164                       Colors::getcolor(LISTWIDGET),
00165                       NULL);
00166             if (retval == ERR)
00167             throw UIException("Error move cursor");
00168 
00169         }
00170 
00171         if (old_pos > -1) {
00172             retval = mymvwchgat(window,
00173                       old_pos + 1,
00174                       1,
00175                       width-2,
00176                       A_NORMAL,
00177                       Colors::getcolor(LISTWIDGET),
00178                       NULL);
00179             if (retval == ERR)
00180             throw UIException("Error move cursor");
00181         }
00182         retval = touchwin(window);
00183         if (retval == ERR)
00184             throw UIException("Error touching window");
00185 
00186         retval = wrefresh(window);
00187         if (retval == ERR)
00188             throw UIException("Error refreshing window");
00189         }
00190 
00191         void scrollUp() {
00192         if (itemlist.size() == 0) return;
00193 
00194         if (cur_pos>0) {
00195             int old_pos = cur_pos--;
00196             showSelected(old_pos);
00197         } else {
00198             if (start_pos>0) {
00199             start_pos--;
00200             showListItems();
00201             showSelected(-1);
00202             }
00203         }
00204         }
00205 
00206         void scrollDown() {
00207         if (itemlist.size() == 0) return;
00208 
00209         if ( ((l_size_type)(cur_pos+start_pos))<itemlist.size()-1) {
00210             if (cur_pos < pagesize()-1 ) {
00211             int old_pos = cur_pos++;
00212             showSelected(old_pos);
00213             } else {
00214             if (((l_size_type)start_pos)<itemlist.size()-1) {
00215                 start_pos++;
00216                 showListItems();
00217                 showSelected(-1);
00218             }
00219             }
00220         }
00221         }
00222 
00223         void scrollPageUp() {
00224         if (itemlist.size() == 0) return;
00225 
00226         int old_pos = cur_pos;
00227         cur_pos = 0;
00228         if ( start_pos - pagesize() > 0 ) {
00229             start_pos -= pagesize();
00230         }else {
00231             start_pos = 0;
00232         }
00233         showListItems();
00234         showSelected(old_pos);
00235         }
00236 
00237         void scrollPageDown() {
00238         if (itemlist.size() == 0) return;
00239 
00240         int old_pos = cur_pos;
00241         if ( ((l_size_type)pagesize()) > itemlist.size() - 1 ) {
00242             cur_pos = itemlist.size() - 1;
00243             start_pos = 0;
00244         } else {
00245             start_pos += pagesize() - 1;
00246             if ( ((l_size_type)start_pos) > itemlist.size() -1 ) {
00247             start_pos = itemlist.size() - pagesize() - 1;
00248             }
00249             cur_pos = 0;
00250         }
00251 
00252         showListItems();
00253         showSelected(old_pos);
00254         }
00255 
00256         void scrollHome() {
00257         if (itemlist.size() == 0) return;
00258 
00259         start_pos = 0;
00260         int old_pos = cur_pos;
00261         cur_pos = 0;
00262         showListItems();
00263         showSelected(old_pos);
00264         }
00265 
00266         void scrollEnd() {
00267         if (itemlist.size() == 0) return;
00268 
00269         int old_pos = cur_pos;
00270         start_pos = itemlist.size() - pagesize();
00271         if (start_pos < 0) {
00272             start_pos = 0;
00273             cur_pos = itemlist.size()-1;
00274         } else {
00275             cur_pos = pagesize()-1;
00276         }
00277 
00278         showListItems();
00279         showSelected(old_pos);
00280         }
00281 
00282         void createWindow(int sx, int sy, int w, int h) throw(UIException) {
00283         window = newwin(h, w, sy, sx);
00284         if (window == NULL)
00285             throw UIException("Error creating list window");
00286 
00287         Colors::setcolor(window, LISTWIDGET);
00288 
00289         int retval = keypad(window, true);
00290         if (retval == ERR)
00291             throw UIException("Error enabling keypad");
00292 
00293         box(window, 0, 0);
00294 
00295         // We set them here in case the window was resized
00296         width = w;
00297         height = h;
00298         }
00299 
00300     public:
00321         ListWidget(std::list<T> l, int sx, int sy, int w, int h)
00322         throw(UIException) : window(NULL),
00323                      width(w),
00324                      height(h),
00325                      start_pos(0),
00326                      cur_pos(0),
00327                      itemlist(l) {
00328         if ( sx == -1 ||
00329              sy == -1 ||
00330              width == -1 ||
00331              height == -1 )
00332             throw UIException("No idea of the dimension of the list");
00333 
00334         createWindow(sx, sy, width, height);
00335         }
00336 
00337         virtual ~ListWidget() {
00338             wclear(window);
00339             delwin(window);
00340         }
00341 
00351         void setList(typename std::list<T>& l) {
00352         itemlist = l;
00353         start_pos = 0;
00354         cur_pos = 0;
00355         showListItems();
00356         showSelected(-1);
00357         }
00358 
00366         void replaceCurrentItem(T& item) {
00367         typename std::list<T>::iterator itemlist_pos = itemlist.begin();
00368         for (int i=0;
00369              i<(start_pos + cur_pos) && itemlist_pos != itemlist.end();
00370              itemlist_pos++, i++);
00371 
00372         *itemlist_pos = item;
00373         }
00374 
00375         void deleteSelectedItem() {
00376         if (itemlist.size()==0) return;
00377         typename std::list<T>::iterator itemlist_pos = itemlist.begin();
00378         for (int i=0;
00379              i<(start_pos + cur_pos) && itemlist_pos != itemlist.end();
00380              itemlist_pos++, i++);
00381 
00382         if (itemlist_pos == itemlist.end()) return;
00383         itemlist.erase(itemlist_pos);
00384         scrollUp();
00385         }
00386 
00387 
00388         const std::list<T>& getList() const { return itemlist; }
00389         std::list<T>& getList() { return itemlist; }
00390 
00413         virtual int focus() throw(UIException) {
00414         int retval = box(window, 0, 0);
00415         if (retval == ERR)
00416             throw UIException("Error re-setting the border");
00417 
00418         showScrollIndicators();
00419 
00420         retval = wrefresh(window);
00421         if (retval == ERR)
00422             throw UIException("Error refreshing the list widget");
00423 
00424         int ch;
00425         bool stay_in_loop = true;
00426         while (stay_in_loop) {
00427             ch = wgetch(window);
00428             switch (ch) {
00429             case KEY_UP:
00430             scrollUp();
00431             break;
00432             case KEY_DOWN:
00433             scrollDown();
00434             break;
00435             case KEY_HOME:
00436             case KEY_A1:
00437             scrollHome();
00438             break;
00439             case KEY_END:
00440             case KEY_C1:
00441             scrollEnd();
00442             break;
00443             case KEY_NPAGE:
00444             case KEY_C3:
00445             scrollPageDown();
00446             break;
00447             case KEY_PPAGE:
00448             case KEY_A3:
00449             scrollPageUp();
00450             break;
00451             case KEY_REFRESH:
00452             BaseWindow::refreshAll();
00453             break;
00454             default:
00455             stay_in_loop = false;
00456             break;
00457             }
00458         }
00459 
00460         retval = box(window, 0, '-');
00461         if (retval == ERR)
00462             throw UIException("Error re-setting the border");
00463         retval = wrefresh(window);
00464         if (retval == ERR)
00465             throw UIException("Error refreshing the list widget");
00466 
00467         return ch;
00468         }
00469 
00470         void refresh() throw(UIException) {
00471         showListItems();
00472         showSelected(-1);
00473 
00474         int retval = wrefresh(window);
00475         if (retval == ERR)
00476             throw UIException("Error refreshing list");
00477         }
00478 
00479         void resize(int sx, int sy, int w, int h) throw(UIException) {
00480         int retval = wclear(window);
00481         if (retval == ERR)
00482             throw UIException("Error clearing list");
00483 
00484         retval = wrefresh(window);
00485         if (retval == ERR)
00486             throw UIException("Error refreshing window");
00487 
00488         retval = delwin(window);
00489         if (retval == ERR)
00490             throw UIException("Error deleting window");
00491 
00492         createWindow(sx, sy, w, h);
00493         }
00494 
00495         int getListPos() { return start_pos + cur_pos; }
00496 
00497         T getSelectedItem() {
00498         typename std::list<T>::iterator itemlist_pos = itemlist.begin();
00499         for (int i=0;
00500              i<(start_pos + cur_pos) && itemlist_pos != itemlist.end();
00501              itemlist_pos++, i++);
00502         return *itemlist_pos;
00503         }
00504 
00505         l_size_type size() { return itemlist.size(); }
00506     };
00507 
00508 }
00509 #endif // _LISTWIDGET_H

Generated on Wed Feb 27 16:15:41 2008 for YAPET by  doxygen 1.5.4