htop/Panel.c

400 lines
9.7 KiB
C
Raw Normal View History

2006-03-04 18:16:49 +00:00
/*
2006-05-30 13:47:28 +00:00
htop - Panel.c
2010-02-25 02:08:18 +00:00
(C) 2004-2010 Hisham H. Muhammad
2006-03-04 18:16:49 +00:00
Released under the GNU GPL, see the COPYING file
in the source distribution for its full text.
*/
#include "Object.h"
2006-05-30 13:47:28 +00:00
#include "Panel.h"
#include "Vector.h"
2006-03-04 18:16:49 +00:00
#include "CRT.h"
#include "RichString.h"
#include "ListItem.h"
2006-03-04 18:16:49 +00:00
#include <math.h>
#include <stdbool.h>
#include "debug.h"
#include <assert.h>
#include <curses.h>
//#link curses
/*{
2006-05-30 13:47:28 +00:00
typedef struct Panel_ Panel;
2006-03-04 18:16:49 +00:00
typedef enum HandlerResult_ {
HANDLED,
IGNORED,
BREAK_LOOP
} HandlerResult;
#define EVENT_SETSELECTED -1
2006-05-30 13:47:28 +00:00
typedef HandlerResult(*Panel_EventHandler)(Panel*, int);
2006-03-04 18:16:49 +00:00
2006-05-30 13:47:28 +00:00
struct Panel_ {
2006-03-04 18:16:49 +00:00
Object super;
int x, y, w, h;
WINDOW* window;
Vector* items;
2006-03-04 18:16:49 +00:00
int selected;
int scrollV, scrollH;
int scrollHAmount;
2006-03-04 18:16:49 +00:00
int oldSelected;
bool needsRedraw;
RichString header;
2006-05-30 13:47:28 +00:00
Panel_EventHandler eventHandler;
2006-03-04 18:16:49 +00:00
};
}*/
#ifndef MIN
#define MIN(a,b) ((a)<(b)?(a):(b))
#endif
#ifndef MAX
#define MAX(a,b) ((a)>(b)?(a):(b))
#endif
#ifdef DEBUG
2006-05-30 13:47:28 +00:00
char* PANEL_CLASS = "Panel";
#else
#define PANEL_CLASS NULL
#endif
2006-03-04 18:16:49 +00:00
Panel* Panel_new(int x, int y, int w, int h, char* type, bool owner, Object_Compare compare) {
2006-05-30 13:47:28 +00:00
Panel* this;
this = malloc(sizeof(Panel));
Panel_init(this, x, y, w, h, type, owner);
this->items->compare = compare;
2006-03-04 18:16:49 +00:00
return this;
}
2006-05-30 13:47:28 +00:00
void Panel_delete(Object* cast) {
Panel* this = (Panel*)cast;
Panel_done(this);
2006-03-04 18:16:49 +00:00
free(this);
}
2006-05-30 13:47:28 +00:00
void Panel_init(Panel* this, int x, int y, int w, int h, char* type, bool owner) {
2006-03-04 18:16:49 +00:00
Object* super = (Object*) this;
Object_setClass(this, PANEL_CLASS);
2006-05-30 13:47:28 +00:00
super->delete = Panel_delete;
2006-03-04 18:16:49 +00:00
this->x = x;
this->y = y;
this->w = w;
this->h = h;
this->eventHandler = NULL;
this->items = Vector_new(type, owner, DEFAULT_SIZE, ListItem_compare);
2006-03-04 18:16:49 +00:00
this->scrollV = 0;
this->scrollH = 0;
this->selected = 0;
this->oldSelected = 0;
this->needsRedraw = true;
2009-06-02 04:51:23 +00:00
RichString_prune(&(this->header));
if (String_eq(CRT_termType, "linux"))
2009-06-02 04:51:23 +00:00
this->scrollHAmount = 20;
else
this->scrollHAmount = 5;
2006-03-04 18:16:49 +00:00
}
2006-05-30 13:47:28 +00:00
void Panel_done(Panel* this) {
2006-03-04 18:16:49 +00:00
assert (this != NULL);
Vector_delete(this->items);
2006-03-04 18:16:49 +00:00
}
2006-05-30 13:47:28 +00:00
inline void Panel_setRichHeader(Panel* this, RichString header) {
2006-03-04 18:16:49 +00:00
assert (this != NULL);
this->header = header;
this->needsRedraw = true;
}
2010-02-25 01:43:18 +00:00
inline void Panel_setHeader(Panel* this, const char* header) {
2006-05-30 13:47:28 +00:00
Panel_setRichHeader(this, RichString_quickString(CRT_colors[PANEL_HEADER_FOCUS], header));
2006-03-04 18:16:49 +00:00
}
2006-05-30 13:47:28 +00:00
void Panel_setEventHandler(Panel* this, Panel_EventHandler eh) {
2006-03-04 18:16:49 +00:00
this->eventHandler = eh;
}
2006-05-30 13:47:28 +00:00
void Panel_move(Panel* this, int x, int y) {
2006-03-04 18:16:49 +00:00
assert (this != NULL);
this->x = x;
this->y = y;
this->needsRedraw = true;
}
2006-05-30 13:47:28 +00:00
void Panel_resize(Panel* this, int w, int h) {
2006-03-04 18:16:49 +00:00
assert (this != NULL);
if (this->header.len > 0)
h--;
this->w = w;
this->h = h;
this->needsRedraw = true;
}
2006-05-30 13:47:28 +00:00
void Panel_prune(Panel* this) {
2006-03-04 18:16:49 +00:00
assert (this != NULL);
Vector_prune(this->items);
2006-03-04 18:16:49 +00:00
this->scrollV = 0;
this->selected = 0;
this->oldSelected = 0;
this->needsRedraw = true;
}
2006-05-30 13:47:28 +00:00
void Panel_add(Panel* this, Object* o) {
2006-03-04 18:16:49 +00:00
assert (this != NULL);
Vector_add(this->items, o);
2006-03-04 18:16:49 +00:00
this->needsRedraw = true;
}
2006-05-30 13:47:28 +00:00
void Panel_insert(Panel* this, int i, Object* o) {
2006-03-04 18:16:49 +00:00
assert (this != NULL);
Vector_insert(this->items, i, o);
2006-03-04 18:16:49 +00:00
this->needsRedraw = true;
}
2006-05-30 13:47:28 +00:00
void Panel_set(Panel* this, int i, Object* o) {
2006-03-04 18:16:49 +00:00
assert (this != NULL);
Vector_set(this->items, i, o);
2006-03-04 18:16:49 +00:00
}
2006-05-30 13:47:28 +00:00
Object* Panel_get(Panel* this, int i) {
2006-03-04 18:16:49 +00:00
assert (this != NULL);
return Vector_get(this->items, i);
2006-03-04 18:16:49 +00:00
}
2006-05-30 13:47:28 +00:00
Object* Panel_remove(Panel* this, int i) {
2006-03-04 18:16:49 +00:00
assert (this != NULL);
this->needsRedraw = true;
Object* removed = Vector_remove(this->items, i);
if (this->selected > 0 && this->selected >= Vector_size(this->items))
2006-03-04 18:16:49 +00:00
this->selected--;
return removed;
}
2006-05-30 13:47:28 +00:00
Object* Panel_getSelected(Panel* this) {
2006-03-04 18:16:49 +00:00
assert (this != NULL);
return Vector_get(this->items, this->selected);
2006-03-04 18:16:49 +00:00
}
2006-05-30 13:47:28 +00:00
void Panel_moveSelectedUp(Panel* this) {
2006-03-04 18:16:49 +00:00
assert (this != NULL);
Vector_moveUp(this->items, this->selected);
2006-03-04 18:16:49 +00:00
if (this->selected > 0)
this->selected--;
}
2006-05-30 13:47:28 +00:00
void Panel_moveSelectedDown(Panel* this) {
2006-03-04 18:16:49 +00:00
assert (this != NULL);
Vector_moveDown(this->items, this->selected);
if (this->selected + 1 < Vector_size(this->items))
2006-03-04 18:16:49 +00:00
this->selected++;
}
2006-05-30 13:47:28 +00:00
int Panel_getSelectedIndex(Panel* this) {
2006-03-04 18:16:49 +00:00
assert (this != NULL);
return this->selected;
}
2009-06-02 04:51:23 +00:00
int Panel_size(Panel* this) {
2006-03-04 18:16:49 +00:00
assert (this != NULL);
return Vector_size(this->items);
2006-03-04 18:16:49 +00:00
}
2006-05-30 13:47:28 +00:00
void Panel_setSelected(Panel* this, int selected) {
2006-03-04 18:16:49 +00:00
assert (this != NULL);
selected = MAX(0, MIN(Vector_size(this->items) - 1, selected));
2006-03-04 18:16:49 +00:00
this->selected = selected;
if (this->eventHandler) {
this->eventHandler(this, EVENT_SETSELECTED);
}
2006-03-04 18:16:49 +00:00
}
2006-05-30 13:47:28 +00:00
void Panel_draw(Panel* this, bool focus) {
2006-03-04 18:16:49 +00:00
assert (this != NULL);
int first, last;
int itemCount = Vector_size(this->items);
2006-03-04 18:16:49 +00:00
int scrollH = this->scrollH;
int y = this->y; int x = this->x;
first = this->scrollV;
if (this->h > itemCount) {
last = this->scrollV + itemCount;
move(y + last, x + 0);
} else {
last = MIN(itemCount, this->scrollV + this->h);
}
if (this->selected < first) {
first = this->selected;
this->scrollV = first;
this->needsRedraw = true;
}
if (this->selected >= last) {
last = MIN(itemCount, this->selected + 1);
first = MAX(0, last - this->h);
this->scrollV = first;
this->needsRedraw = true;
}
assert(first >= 0);
assert(last <= itemCount);
if (this->header.len > 0) {
int attr = focus
? CRT_colors[PANEL_HEADER_FOCUS]
: CRT_colors[PANEL_HEADER_UNFOCUS];
attrset(attr);
mvhline(y, x, ' ', this->w);
if (scrollH < this->header.len) {
RichString_printoffnVal(this->header, y, x, scrollH,
MIN(this->header.len - scrollH, this->w));
2006-03-04 18:16:49 +00:00
}
attrset(CRT_colors[RESET_COLOR]);
y++;
}
int highlight = focus
? CRT_colors[PANEL_HIGHLIGHT_FOCUS]
: CRT_colors[PANEL_HIGHLIGHT_UNFOCUS];
if (this->needsRedraw) {
for(int i = first, j = 0; j < this->h && i < last; i++, j++) {
Object* itemObj = Vector_get(this->items, i);
RichString itemRef;
RichString_initVal(itemRef);
2006-03-04 18:16:49 +00:00
itemObj->display(itemObj, &itemRef);
int amt = MIN(itemRef.len - scrollH, this->w);
if (i == this->selected) {
attrset(highlight);
RichString_setAttr(&itemRef, highlight);
mvhline(y + j, x+0, ' ', this->w);
if (amt > 0)
RichString_printoffnVal(itemRef, y+j, x+0, scrollH, amt);
2006-03-04 18:16:49 +00:00
attrset(CRT_colors[RESET_COLOR]);
} else {
mvhline(y+j, x+0, ' ', this->w);
if (amt > 0)
RichString_printoffnVal(itemRef, y+j, x+0, scrollH, amt);
2006-03-04 18:16:49 +00:00
}
}
for (int i = y + (last - first); i < y + this->h; i++)
mvhline(i, x+0, ' ', this->w);
this->needsRedraw = false;
} else {
Object* oldObj = Vector_get(this->items, this->oldSelected);
RichString oldRef;
RichString_initVal(oldRef);
2006-03-04 18:16:49 +00:00
oldObj->display(oldObj, &oldRef);
Object* newObj = Vector_get(this->items, this->selected);
RichString newRef;
RichString_initVal(newRef);
2006-03-04 18:16:49 +00:00
newObj->display(newObj, &newRef);
mvhline(y+ this->oldSelected - this->scrollV, x+0, ' ', this->w);
if (scrollH < oldRef.len)
RichString_printoffnVal(oldRef, y+this->oldSelected - this->scrollV, x,
this->scrollH, MIN(oldRef.len - scrollH, this->w));
2006-03-04 18:16:49 +00:00
attrset(highlight);
mvhline(y+this->selected - this->scrollV, x+0, ' ', this->w);
RichString_setAttr(&newRef, highlight);
if (scrollH < newRef.len)
RichString_printoffnVal(newRef, y+this->selected - this->scrollV, x,
this->scrollH, MIN(newRef.len - scrollH, this->w));
2006-03-04 18:16:49 +00:00
attrset(CRT_colors[RESET_COLOR]);
}
this->oldSelected = this->selected;
move(0, 0);
}
2009-06-02 04:51:23 +00:00
bool Panel_onKey(Panel* this, int key) {
2006-03-04 18:16:49 +00:00
assert (this != NULL);
switch (key) {
case KEY_DOWN:
if (this->selected + 1 < Vector_size(this->items))
2006-03-04 18:16:49 +00:00
this->selected++;
2009-06-02 04:51:23 +00:00
return true;
2006-03-04 18:16:49 +00:00
case KEY_UP:
if (this->selected > 0)
this->selected--;
2009-06-02 04:51:23 +00:00
return true;
#ifdef KEY_C_DOWN
case KEY_C_DOWN:
if (this->selected + 1 < Vector_size(this->items)) {
this->selected++;
if (this->scrollV < Vector_size(this->items) - this->h) {
this->scrollV++;
this->needsRedraw = true;
}
}
return true;
#endif
#ifdef KEY_C_UP
case KEY_C_UP:
if (this->selected > 0) {
this->selected--;
if (this->scrollV > 0) {
this->scrollV--;
this->needsRedraw = true;
}
}
return true;
#endif
2006-03-04 18:16:49 +00:00
case KEY_LEFT:
if (this->scrollH > 0) {
2009-06-02 04:51:23 +00:00
this->scrollH -= 5;
2006-03-04 18:16:49 +00:00
this->needsRedraw = true;
}
2009-06-02 04:51:23 +00:00
return true;
2006-03-04 18:16:49 +00:00
case KEY_RIGHT:
2009-06-02 04:51:23 +00:00
this->scrollH += 5;
2006-03-04 18:16:49 +00:00
this->needsRedraw = true;
2009-06-02 04:51:23 +00:00
return true;
2006-03-04 18:16:49 +00:00
case KEY_PPAGE:
2009-06-02 04:51:23 +00:00
this->selected -= (this->h - 1);
this->scrollV -= (this->h - 1);
2006-03-04 18:16:49 +00:00
if (this->selected < 0)
this->selected = 0;
2009-06-02 04:51:23 +00:00
if (this->scrollV < 0)
this->scrollV = 0;
this->needsRedraw = true;
return true;
2006-03-04 18:16:49 +00:00
case KEY_NPAGE:
2009-06-02 04:51:23 +00:00
this->selected += (this->h - 1);
int size = Vector_size(this->items);
2006-03-04 18:16:49 +00:00
if (this->selected >= size)
this->selected = size - 1;
2009-06-02 04:51:23 +00:00
this->scrollV += (this->h - 1);
if (this->scrollV >= MAX(0, size - this->h))
this->scrollV = MAX(0, size - this->h - 1);
this->needsRedraw = true;
return true;
2006-03-04 18:16:49 +00:00
case KEY_HOME:
this->selected = 0;
2009-06-02 04:51:23 +00:00
return true;
2006-03-04 18:16:49 +00:00
case KEY_END:
this->selected = Vector_size(this->items) - 1;
2009-06-02 04:51:23 +00:00
return true;
2006-03-04 18:16:49 +00:00
}
2009-06-02 04:51:23 +00:00
return false;
2006-03-04 18:16:49 +00:00
}