3
(C) 2004-2006 Hisham H. Muhammad
4
Released under the GNU GPL, see the COPYING file
5
in the source distribution for its full text.
12
#include "RichString.h"
26
typedef struct Panel_ Panel;
28
typedef enum HandlerResult_ {
34
typedef HandlerResult(*Panel_EventHandler)(Panel*, int);
47
Panel_EventHandler eventHandler;
53
#define MIN(a,b) ((a)<(b)?(a):(b))
56
#define MAX(a,b) ((a)>(b)?(a):(b))
60
char* PANEL_CLASS = "Panel";
62
#define PANEL_CLASS NULL
66
Panel* Panel_new(int x, int y, int w, int h, char* type, bool owner, Object_Compare compare) {
68
this = malloc(sizeof(Panel));
69
Panel_init(this, x, y, w, h, type, owner);
70
this->items->compare = compare;
74
void Panel_delete(Object* cast) {
75
Panel* this = (Panel*)cast;
80
void Panel_init(Panel* this, int x, int y, int w, int h, char* type, bool owner) {
81
Object* super = (Object*) this;
82
Object_setClass(this, PANEL_CLASS);
83
super->delete = Panel_delete;
88
this->eventHandler = NULL;
89
this->items = Vector_new(type, owner, DEFAULT_SIZE, ListItem_compare);
93
this->oldSelected = 0;
94
this->needsRedraw = true;
96
if (String_eq(CRT_termType, "linux"))
97
this->scrollHAmount = 40;
99
this->scrollHAmount = 5;
102
void Panel_done(Panel* this) {
103
assert (this != NULL);
104
Vector_delete(this->items);
107
inline void Panel_setRichHeader(Panel* this, RichString header) {
108
assert (this != NULL);
110
this->header = header;
111
this->needsRedraw = true;
114
inline void Panel_setHeader(Panel* this, char* header) {
115
Panel_setRichHeader(this, RichString_quickString(CRT_colors[PANEL_HEADER_FOCUS], header));
118
void Panel_setEventHandler(Panel* this, Panel_EventHandler eh) {
119
this->eventHandler = eh;
122
void Panel_move(Panel* this, int x, int y) {
123
assert (this != NULL);
127
this->needsRedraw = true;
130
void Panel_resize(Panel* this, int w, int h) {
131
assert (this != NULL);
133
if (this->header.len > 0)
137
this->needsRedraw = true;
140
void Panel_prune(Panel* this) {
141
assert (this != NULL);
143
Vector_prune(this->items);
146
this->oldSelected = 0;
147
this->needsRedraw = true;
150
void Panel_add(Panel* this, Object* o) {
151
assert (this != NULL);
153
Vector_add(this->items, o);
154
this->needsRedraw = true;
157
void Panel_insert(Panel* this, int i, Object* o) {
158
assert (this != NULL);
160
Vector_insert(this->items, i, o);
161
this->needsRedraw = true;
164
void Panel_set(Panel* this, int i, Object* o) {
165
assert (this != NULL);
167
Vector_set(this->items, i, o);
170
Object* Panel_get(Panel* this, int i) {
171
assert (this != NULL);
173
return Vector_get(this->items, i);
176
Object* Panel_remove(Panel* this, int i) {
177
assert (this != NULL);
179
this->needsRedraw = true;
180
Object* removed = Vector_remove(this->items, i);
181
if (this->selected > 0 && this->selected >= Vector_size(this->items))
186
Object* Panel_getSelected(Panel* this) {
187
assert (this != NULL);
189
return Vector_get(this->items, this->selected);
192
void Panel_moveSelectedUp(Panel* this) {
193
assert (this != NULL);
195
Vector_moveUp(this->items, this->selected);
196
if (this->selected > 0)
200
void Panel_moveSelectedDown(Panel* this) {
201
assert (this != NULL);
203
Vector_moveDown(this->items, this->selected);
204
if (this->selected + 1 < Vector_size(this->items))
208
int Panel_getSelectedIndex(Panel* this) {
209
assert (this != NULL);
211
return this->selected;
214
int Panel_getSize(Panel* this) {
215
assert (this != NULL);
217
return Vector_size(this->items);
220
void Panel_setSelected(Panel* this, int selected) {
221
assert (this != NULL);
223
selected = MAX(0, MIN(Vector_size(this->items) - 1, selected));
224
this->selected = selected;
227
void Panel_draw(Panel* this, bool focus) {
228
assert (this != NULL);
231
int itemCount = Vector_size(this->items);
232
int scrollH = this->scrollH;
233
int y = this->y; int x = this->x;
234
first = this->scrollV;
236
if (this->h > itemCount) {
237
last = this->scrollV + itemCount;
238
move(y + last, x + 0);
240
last = MIN(itemCount, this->scrollV + this->h);
242
if (this->selected < first) {
243
first = this->selected;
244
this->scrollV = first;
245
this->needsRedraw = true;
247
if (this->selected >= last) {
248
last = MIN(itemCount, this->selected + 1);
249
first = MAX(0, last - this->h);
250
this->scrollV = first;
251
this->needsRedraw = true;
254
assert(last <= itemCount);
256
if (this->header.len > 0) {
258
? CRT_colors[PANEL_HEADER_FOCUS]
259
: CRT_colors[PANEL_HEADER_UNFOCUS];
261
mvhline(y, x, ' ', this->w);
262
if (scrollH < this->header.len) {
263
mvaddchnstr(y, x, this->header.chstr + scrollH,
264
MIN(this->header.len - scrollH, this->w));
266
attrset(CRT_colors[RESET_COLOR]);
270
int highlight = focus
271
? CRT_colors[PANEL_HIGHLIGHT_FOCUS]
272
: CRT_colors[PANEL_HIGHLIGHT_UNFOCUS];
274
if (this->needsRedraw) {
276
for(int i = first, j = 0; j < this->h && i < last; i++, j++) {
277
Object* itemObj = Vector_get(this->items, i);
279
RichString_initVal(itemRef);
280
itemObj->display(itemObj, &itemRef);
281
int amt = MIN(itemRef.len - scrollH, this->w);
282
if (i == this->selected) {
284
RichString_setAttr(&itemRef, highlight);
285
mvhline(y + j, x+0, ' ', this->w);
287
mvaddchnstr(y+j, x+0, itemRef.chstr + scrollH, amt);
288
attrset(CRT_colors[RESET_COLOR]);
290
mvhline(y+j, x+0, ' ', this->w);
292
mvaddchnstr(y+j, x+0, itemRef.chstr + scrollH, amt);
295
for (int i = y + (last - first); i < y + this->h; i++)
296
mvhline(i, x+0, ' ', this->w);
297
this->needsRedraw = false;
300
Object* oldObj = Vector_get(this->items, this->oldSelected);
302
RichString_initVal(oldRef);
303
oldObj->display(oldObj, &oldRef);
304
Object* newObj = Vector_get(this->items, this->selected);
306
RichString_initVal(newRef);
307
newObj->display(newObj, &newRef);
308
mvhline(y+ this->oldSelected - this->scrollV, x+0, ' ', this->w);
309
if (scrollH < oldRef.len)
310
mvaddchnstr(y+ this->oldSelected - this->scrollV, x+0, oldRef.chstr + this->scrollH, MIN(oldRef.len - scrollH, this->w));
312
mvhline(y+this->selected - this->scrollV, x+0, ' ', this->w);
313
RichString_setAttr(&newRef, highlight);
314
if (scrollH < newRef.len)
315
mvaddchnstr(y+this->selected - this->scrollV, x+0, newRef.chstr + this->scrollH, MIN(newRef.len - scrollH, this->w));
316
attrset(CRT_colors[RESET_COLOR]);
318
this->oldSelected = this->selected;
322
void Panel_onKey(Panel* this, int key) {
323
assert (this != NULL);
326
if (this->selected + 1 < Vector_size(this->items))
330
if (this->selected > 0)
334
if (this->scrollH > 0) {
335
this->scrollH -= this->scrollHAmount;
336
this->needsRedraw = true;
340
this->scrollH += this->scrollHAmount;
341
this->needsRedraw = true;
344
this->selected -= this->h;
345
if (this->selected < 0)
349
this->selected += this->h;
350
int size = Vector_size(this->items);
351
if (this->selected >= size)
352
this->selected = size - 1;
358
this->selected = Vector_size(this->items) - 1;