1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185
|
/*
** Copyright 2002-2011, Double Precision Inc.
**
** See COPYING for distribution information.
*/
#ifndef cursesstatusbar_H
#define cursesstatusbar_H
#include "mycurses.H"
#include "curseskeyhandler.H"
#include "cursescontainer.H"
#include "cursesfield.H"
#include "timer.H"
#include <string>
#include <vector>
#include <wchar.h>
//////////////////////////////////////////////////////////////////////////////
//
// The status bar - moves itself to the bottom of the screen. Occupies three
// last lines: a one line status/help line, and two lines that list current
// keyboard shortcuts.
//
// Status messages are prioritized, and only messages of the same or higher
// priority level are shown. The clearstatus() clears the current message,
// which is also automatically cleared 10 seconds after the first keypress
//
// Messages that cannot fit on one line are automatically word-wrapped, and
// are shown in a larger popup that comes up from the bottom of the screen,
// which must be cleared with a keypress
//
// The status bar can also be converted to a one-line input field, by calling
// the createPrompt() method, which returns a pointer to the created
// CursesField object (which may be further customized). The status bar
// automatically destroys the CursesField abort when the input concludes
// (by pressing ENTER, or by manually calling fieldAbort() ).
//
// The first character of the status line may be a busy-throbber (a rotating
// line). The throbber must be animated by repeatedly calling the busy()
// method (which should be kicked off a 1 second timer). The throbber is
// cleared by clearstatus().
//
// The status bar also includes a summary of all installed KeyHandler
// objects. If the list of available function keys exceeds the available
// space, the list is shown in pieces, with a control key cycling through
// to the next status key summary piece.
class CursesScreen;
class CursesStatusBar : public CursesContainer, public CursesKeyHandler {
std::vector<unicode_char> statusText;
std::vector<unicode_char> progressText;
time_t progressTime;
int busyCounter;
CursesScreen *parentScreen;
std::vector< std::vector<unicode_char> > extendedErrorMsg;
// The status bar is sometimes turned into a one-line field entry.
// This is done by creating a CursesField child, which is why
// CursesStatusBar subclasses CursesContainer.
// We need to subclass CursesField in order to fix up a few things...
class Field : public CursesField {
CursesStatusBar *me;
public:
Field(CursesStatusBar *parent, size_t widthArg,
size_t maxlengthArg,
std::string initValue);
~Field();
bool processKeyInFocus(const Key &key);
bool writeText(const char *text, int row, int col,
const CursesAttr &attr) const;
bool writeText(const std::vector<unicode_char> &text,
int row, int col,
const Curses::CursesAttr &attr) const;
};
Field *fieldActive; // Not NULL when input takes place
std::string fieldValue; // Entered input
bool fieldAborted; // Whether input was aborted
TimerRedirect<CursesStatusBar> clearStatusTimer;
CursesAttr attrStatusBar, attrHotKey, attrHotKeyDescr;
public:
void fieldEnter(); // Accept input
void fieldAbort(); // Abort input
private:
// Shortcut keys.
size_t max_sc_nlen; // Largest shortcut name
size_t max_sc_dlen; // Largest shortcut description
std::vector <std::vector <std::vector <
std::pair< std::vector<unicode_char>,
std::vector<unicode_char> > > > > shortcuts;
// A std::pair of name/description string, inside a two-element vector
// (the two-row column on the status bar), inside a vector of all
// columns that fit on one screen, inside a vector of all pages of
// shortcut descriptions
size_t currentShortcutPage; // Current page of shortcuts shown
void rebuildShortcuts(); // Rebuild the shortcuts array
public:
static std::string shortcut_next_key;
static std::string shortcut_next_descr;
static unicode_char shortcut_next_keycode;
friend class Field;
// Status line priorities
enum statusLevel {
NORMAL, // Normal message
INPROGRESS, // Something's in progress
EXPUNGED, // Folder's been expunged
SYSERROR, // System error
DISCONNECTED, // Server dropped connection
SERVERERROR, // Other server error
LOGINERROR // Login error
};
CursesStatusBar(CursesScreen *parent);
~CursesStatusBar();
static std::string extendedErrorPrompt; // Non empty - wrapped text
int getWidth() const;
int getHeight() const;
void setStatusBarAttr(CursesAttr);
void setHotKeyAttr(CursesAttr);
void setHotKeyDescr(CursesAttr);
void draw();
void resized();
void status(std::string statusText, statusLevel level=NORMAL);
void progress(std::string progress);
bool progressWanted();
void clearstatus();
void busy(); // Throbber animation
void notbusy(); // Not busy any more
// Create a one-line input field.
CursesField *createPrompt(std::string prompt, std::string initvalue="");
bool prompting() const { return fieldActive != NULL; }
bool promptAborted() const { return fieldAborted; }
std::string getPromptValue() const
{
return (fieldActive != NULL ? fieldActive->getText()
: fieldValue);
}
private:
statusLevel currentLevel;
void resetRow();
bool processKey(const Curses::Key &key);
bool listKeys( std::vector< std::pair<std::string, std::string> > &list);
};
#endif
|