summaryrefslogtreecommitdiffstats
path: root/Panel.c
diff options
context:
space:
mode:
authorHisham Muhammad <hisham@gobolinux.org>2015-01-21 23:27:31 -0200
committerHisham Muhammad <hisham@gobolinux.org>2015-01-21 23:27:31 -0200
commit3383d8e5561dfc6fb2b65e0a194df94ccb5e08af (patch)
treedafba704561386b31b6b8af6dafb5b9a2ba7453c /Panel.c
parent36b78328843d0dae0d0fadbd0e814a8a1546327c (diff)
Sorry about the mega-patch.
This is a work-in-progress, code is currently broken. (Some actions, and notably, the header, are missing.)
Diffstat (limited to 'Panel.c')
-rw-r--r--Panel.c179
1 files changed, 88 insertions, 91 deletions
diff --git a/Panel.c b/Panel.c
index 4355b1e2..8982cc2e 100644
--- a/Panel.c
+++ b/Panel.c
@@ -28,9 +28,11 @@ in the source distribution for its full text.
typedef struct Panel_ Panel;
typedef enum HandlerResult_ {
- HANDLED,
- IGNORED,
- BREAK_LOOP
+ HANDLED = 0x00,
+ IGNORED = 0x01,
+ BREAK_LOOP = 0x02,
+ REFRESH = 0x04,
+ RECALCULATE = 0x08,
} HandlerResult;
#define EVENT_SETSELECTED -1
@@ -54,7 +56,7 @@ struct Panel_ {
Vector* items;
int selected;
int oldSelected;
- char* eventHandlerBuffer;
+ void* eventHandlerState;
int scrollV;
short scrollH;
bool needsRedraw;
@@ -102,7 +104,7 @@ void Panel_init(Panel* this, int x, int y, int w, int h, ObjectClass* type, bool
this->y = y;
this->w = w;
this->h = h;
- this->eventHandlerBuffer = NULL;
+ this->eventHandlerState = NULL;
this->items = Vector_new(type, owner, DEFAULT_SIZE);
this->scrollV = 0;
this->scrollH = 0;
@@ -114,7 +116,7 @@ void Panel_init(Panel* this, int x, int y, int w, int h, ObjectClass* type, bool
void Panel_done(Panel* this) {
assert (this != NULL);
- free(this->eventHandlerBuffer);
+ free(this->eventHandlerState);
Vector_delete(this->items);
RichString_end(this->header);
}
@@ -246,30 +248,11 @@ void Panel_setSelected(Panel* this, int selected) {
void Panel_draw(Panel* this, bool focus) {
assert (this != NULL);
- int itemCount = Vector_size(this->items);
+ int size = Vector_size(this->items);
int scrollH = this->scrollH;
- int y = this->y; int x = this->x;
- int first = this->scrollV;
- if (itemCount > this->h && first > itemCount - this->h) {
- first = itemCount - this->h;
- this->scrollV = first;
- }
- int last = MIN(itemCount, first + MIN(itemCount, 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 = last - this->h;
- this->scrollV = first;
- this->needsRedraw = true;
- }
- if (first < 0)
- first = 0;
- if (last > itemCount)
- last = itemCount;
+ int y = this->y;
+ int x = this->x;
+ int h = this->h;
int headerLen = RichString_sizeVal(this->header);
if (headerLen > 0) {
@@ -285,14 +268,34 @@ void Panel_draw(Panel* this, bool focus) {
attrset(CRT_colors[RESET_COLOR]);
y++;
}
-
+
+ // ensure scroll area is on screen
+ if (this->scrollV < 0) {
+ this->scrollV = 0;
+ this->needsRedraw = true;
+ } else if (this->scrollV >= size) {
+ this->scrollV = MAX(size - 1, 0);
+ this->needsRedraw = true;
+ }
+ // ensure selection is on screen
+ if (this->selected < this->scrollV) {
+ this->scrollV = this->selected;
+ this->needsRedraw = true;
+ } else if (this->selected >= this->scrollV + h) {
+ this->scrollV = this->selected - h + 1;
+ this->needsRedraw = true;
+ }
+
+ int first = this->scrollV;
+ int upTo = MIN(first + h, size);
+
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++) {
+ int line = 0;
+ for(int i = first; line < h && i < upTo; i++) {
Object* itemObj = Vector_get(this->items, i);
assert(itemObj); if(!itemObj) continue;
RichString_begin(item);
@@ -304,15 +307,18 @@ void Panel_draw(Panel* this, bool focus) {
attrset(highlight);
RichString_setAttr(&item, highlight);
}
- mvhline(y + j, x, ' ', this->w);
+ mvhline(y + line, x, ' ', this->w);
if (amt > 0)
- RichString_printoffnVal(item, y+j, x, scrollH, amt);
+ RichString_printoffnVal(item, y + line, x, scrollH, amt);
if (selected)
attrset(CRT_colors[RESET_COLOR]);
RichString_end(item);
+ line++;
+ }
+ while (line < h) {
+ mvhline(y + line, x, ' ', this->w);
+ line++;
}
- for (int i = y + (last - first); i < y + this->h; i++)
- mvhline(i, x+0, ' ', this->w);
this->needsRedraw = false;
} else {
@@ -325,15 +331,15 @@ void Panel_draw(Panel* this, bool focus) {
RichString_begin(new);
Object_display(newObj, &new);
int newLen = RichString_sizeVal(new);
- mvhline(y+ this->oldSelected - this->scrollV, x+0, ' ', this->w);
+ mvhline(y+ this->oldSelected - first, x+0, ' ', this->w);
if (scrollH < oldLen)
- RichString_printoffnVal(old, y+this->oldSelected - this->scrollV, x,
+ RichString_printoffnVal(old, y+this->oldSelected - first, x,
scrollH, MIN(oldLen - scrollH, this->w));
attrset(highlight);
- mvhline(y+this->selected - this->scrollV, x+0, ' ', this->w);
+ mvhline(y+this->selected - first, x+0, ' ', this->w);
RichString_setAttr(&new, highlight);
if (scrollH < newLen)
- RichString_printoffnVal(new, y+this->selected - this->scrollV, x,
+ RichString_printoffnVal(new, y+this->selected - first, x,
scrollH, MIN(newLen - scrollH, this->w));
attrset(CRT_colors[RESET_COLOR]);
RichString_end(new);
@@ -345,38 +351,26 @@ void Panel_draw(Panel* this, bool focus) {
bool Panel_onKey(Panel* this, int key) {
assert (this != NULL);
+
+ int size = Vector_size(this->items);
switch (key) {
case KEY_DOWN:
case KEY_CTRLN:
- if (this->selected + 1 < Vector_size(this->items))
- this->selected++;
- return true;
+ this->selected++;
+ break;
case KEY_UP:
case KEY_CTRLP:
- if (this->selected > 0)
- this->selected--;
- return true;
+ this->selected--;
+ break;
#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;
+ this->selected++;
+ break;
#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;
+ this->selected--;
+ break;
#endif
case KEY_LEFT:
case KEY_CTRLB:
@@ -384,71 +378,74 @@ bool Panel_onKey(Panel* this, int key) {
this->scrollH -= CRT_scrollHAmount;
this->needsRedraw = true;
}
- return true;
+ break;
case KEY_RIGHT:
case KEY_CTRLF:
this->scrollH += CRT_scrollHAmount;
this->needsRedraw = true;
- return true;
+ break;
case KEY_PPAGE:
this->selected -= (this->h - 1);
this->scrollV -= (this->h - 1);
- if (this->selected < 0)
- this->selected = 0;
- if (this->scrollV < 0)
- this->scrollV = 0;
this->needsRedraw = true;
- return true;
+ break;
case KEY_NPAGE:
this->selected += (this->h - 1);
- int size = Vector_size(this->items);
- if (this->selected < 0)
- this->selected = 0;
- if (this->selected >= size)
- this->selected = size - 1;
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;
+ break;
case KEY_HOME:
this->selected = 0;
- return true;
+ break;
case KEY_END:
- this->selected = Vector_size(this->items) - 1;
- return true;
+ this->selected = size - 1;
+ break;
+ default:
+ return false;
+ }
+
+ // ensure selection within bounds
+ if (this->selected < 0) {
+ this->selected = 0;
+ this->needsRedraw = true;
+ } else if (this->selected >= size) {
+ this->selected = size - 1;
+ this->needsRedraw = true;
}
- return false;
+ return true;
}
HandlerResult Panel_selectByTyping(Panel* this, int ch) {
int size = Panel_size(this);
- if (!this->eventHandlerBuffer)
- this->eventHandlerBuffer = calloc(100, 1);
+ if (!this->eventHandlerState)
+ this->eventHandlerState = calloc(100, 1);
+ char* buffer = this->eventHandlerState;
if (isalnum(ch)) {
- int len = strlen(this->eventHandlerBuffer);
+ int len = strlen(buffer);
if (len < 99) {
- this->eventHandlerBuffer[len] = ch;
- this->eventHandlerBuffer[len+1] = '\0';
+ buffer[len] = ch;
+ buffer[len+1] = '\0';
}
for (int try = 0; try < 2; try++) {
- len = strlen(this->eventHandlerBuffer);
+ len = strlen(buffer);
for (int i = 0; i < size; i++) {
char* cur = ((ListItem*) Panel_get(this, i))->value;
while (*cur == ' ') cur++;
- if (strncasecmp(cur, this->eventHandlerBuffer, len) == 0) {
+ if (strncasecmp(cur, buffer, len) == 0) {
Panel_setSelected(this, i);
return HANDLED;
}
}
- this->eventHandlerBuffer[0] = ch;
- this->eventHandlerBuffer[1] = '\0';
+ // if current word did not match,
+ // retry considering the character the start of a new word.
+ buffer[0] = ch;
+ buffer[1] = '\0';
}
return HANDLED;
} else if (ch != ERR) {
- this->eventHandlerBuffer[0] = '\0';
+ buffer[0] = '\0';
}
if (ch == 13) {
return BREAK_LOOP;

© 2014-2024 Faster IT GmbH | imprint | privacy policy