Panel.c 8.67 KB
Newer Older
Hisham Muhammad's avatar
Hisham Muhammad committed
1
/*
2
htop - Panel.c
Hisham Muhammad's avatar
Hisham Muhammad committed
3
(C) 2004-2006 Hisham H. Muhammad
Hisham Muhammad's avatar
Hisham Muhammad committed
4
5
6
7
8
Released under the GNU GPL, see the COPYING file
in the source distribution for its full text.
*/

#include "Object.h"
9
#include "Panel.h"
10
#include "Vector.h"
Hisham Muhammad's avatar
Hisham Muhammad committed
11
12
#include "CRT.h"
#include "RichString.h"
13
#include "ListItem.h"
Hisham Muhammad's avatar
Hisham Muhammad committed
14
15
16
17
18
19
20
21
22
23
24
25

#include <math.h>
#include <stdbool.h>

#include "debug.h"
#include <assert.h>

#include <curses.h>
//#link curses

/*{

26
typedef struct Panel_ Panel;
Hisham Muhammad's avatar
Hisham Muhammad committed
27
28
29
30
31
32
33

typedef enum HandlerResult_ {
   HANDLED,
   IGNORED,
   BREAK_LOOP
} HandlerResult;

34
typedef HandlerResult(*Panel_EventHandler)(Panel*, int);
Hisham Muhammad's avatar
Hisham Muhammad committed
35

36
struct Panel_ {
Hisham Muhammad's avatar
Hisham Muhammad committed
37
38
39
   Object super;
   int x, y, w, h;
   WINDOW* window;
40
   Vector* items;
Hisham Muhammad's avatar
Hisham Muhammad committed
41
42
   int selected;
   int scrollV, scrollH;
43
   int scrollHAmount;
Hisham Muhammad's avatar
Hisham Muhammad committed
44
45
46
   int oldSelected;
   bool needsRedraw;
   RichString header;
47
   Panel_EventHandler eventHandler;
Hisham Muhammad's avatar
Hisham Muhammad committed
48
49
50
51
52
53
54
55
56
57
58
};

}*/

#ifndef MIN
#define MIN(a,b) ((a)<(b)?(a):(b))
#endif
#ifndef MAX
#define MAX(a,b) ((a)>(b)?(a):(b))
#endif

59
#ifdef DEBUG
60
char* PANEL_CLASS = "Panel";
61
62
63
64
#else
#define PANEL_CLASS NULL
#endif

Hisham Muhammad's avatar
Hisham Muhammad committed
65

66
Panel* Panel_new(int x, int y, int w, int h, char* type, bool owner, Object_Compare compare) {
67
68
69
   Panel* this;
   this = malloc(sizeof(Panel));
   Panel_init(this, x, y, w, h, type, owner);
70
   this->items->compare = compare;
Hisham Muhammad's avatar
Hisham Muhammad committed
71
72
73
   return this;
}

74
75
76
void Panel_delete(Object* cast) {
   Panel* this = (Panel*)cast;
   Panel_done(this);
Hisham Muhammad's avatar
Hisham Muhammad committed
77
78
79
   free(this);
}

80
void Panel_init(Panel* this, int x, int y, int w, int h, char* type, bool owner) {
Hisham Muhammad's avatar
Hisham Muhammad committed
81
   Object* super = (Object*) this;
82
   Object_setClass(this, PANEL_CLASS);
83
   super->delete = Panel_delete;
Hisham Muhammad's avatar
Hisham Muhammad committed
84
85
86
87
88
   this->x = x;
   this->y = y;
   this->w = w;
   this->h = h;
   this->eventHandler = NULL;
89
   this->items = Vector_new(type, owner, DEFAULT_SIZE, ListItem_compare);
Hisham Muhammad's avatar
Hisham Muhammad committed
90
91
92
93
94
95
   this->scrollV = 0;
   this->scrollH = 0;
   this->selected = 0;
   this->oldSelected = 0;
   this->needsRedraw = true;
   this->header.len = 0;
96
97
98
99
   if (String_eq(CRT_termType, "linux"))
      this->scrollHAmount = 40;
   else
      this->scrollHAmount = 5;
Hisham Muhammad's avatar
Hisham Muhammad committed
100
101
}

102
void Panel_done(Panel* this) {
Hisham Muhammad's avatar
Hisham Muhammad committed
103
   assert (this != NULL);
104
   Vector_delete(this->items);
Hisham Muhammad's avatar
Hisham Muhammad committed
105
106
}

107
inline void Panel_setRichHeader(Panel* this, RichString header) {
Hisham Muhammad's avatar
Hisham Muhammad committed
108
109
110
111
112
113
   assert (this != NULL);

   this->header = header;
   this->needsRedraw = true;
}

114
115
inline void Panel_setHeader(Panel* this, char* header) {
   Panel_setRichHeader(this, RichString_quickString(CRT_colors[PANEL_HEADER_FOCUS], header));
Hisham Muhammad's avatar
Hisham Muhammad committed
116
117
}

118
void Panel_setEventHandler(Panel* this, Panel_EventHandler eh) {
Hisham Muhammad's avatar
Hisham Muhammad committed
119
120
121
   this->eventHandler = eh;
}

122
void Panel_move(Panel* this, int x, int y) {
Hisham Muhammad's avatar
Hisham Muhammad committed
123
124
125
126
127
128
129
   assert (this != NULL);

   this->x = x;
   this->y = y;
   this->needsRedraw = true;
}

130
void Panel_resize(Panel* this, int w, int h) {
Hisham Muhammad's avatar
Hisham Muhammad committed
131
132
133
134
135
136
137
138
139
   assert (this != NULL);

   if (this->header.len > 0)
      h--;
   this->w = w;
   this->h = h;
   this->needsRedraw = true;
}

140
void Panel_prune(Panel* this) {
Hisham Muhammad's avatar
Hisham Muhammad committed
141
142
   assert (this != NULL);

143
   Vector_prune(this->items);
Hisham Muhammad's avatar
Hisham Muhammad committed
144
145
146
147
148
149
   this->scrollV = 0;
   this->selected = 0;
   this->oldSelected = 0;
   this->needsRedraw = true;
}

150
void Panel_add(Panel* this, Object* o) {
Hisham Muhammad's avatar
Hisham Muhammad committed
151
152
   assert (this != NULL);

153
   Vector_add(this->items, o);
Hisham Muhammad's avatar
Hisham Muhammad committed
154
155
156
   this->needsRedraw = true;
}

157
void Panel_insert(Panel* this, int i, Object* o) {
Hisham Muhammad's avatar
Hisham Muhammad committed
158
159
   assert (this != NULL);

160
   Vector_insert(this->items, i, o);
Hisham Muhammad's avatar
Hisham Muhammad committed
161
162
163
   this->needsRedraw = true;
}

164
void Panel_set(Panel* this, int i, Object* o) {
Hisham Muhammad's avatar
Hisham Muhammad committed
165
166
   assert (this != NULL);

167
   Vector_set(this->items, i, o);
Hisham Muhammad's avatar
Hisham Muhammad committed
168
169
}

170
Object* Panel_get(Panel* this, int i) {
Hisham Muhammad's avatar
Hisham Muhammad committed
171
172
   assert (this != NULL);

173
   return Vector_get(this->items, i);
Hisham Muhammad's avatar
Hisham Muhammad committed
174
175
}

176
Object* Panel_remove(Panel* this, int i) {
Hisham Muhammad's avatar
Hisham Muhammad committed
177
178
179
   assert (this != NULL);

   this->needsRedraw = true;
180
181
   Object* removed = Vector_remove(this->items, i);
   if (this->selected > 0 && this->selected >= Vector_size(this->items))
Hisham Muhammad's avatar
Hisham Muhammad committed
182
183
184
185
      this->selected--;
   return removed;
}

186
Object* Panel_getSelected(Panel* this) {
Hisham Muhammad's avatar
Hisham Muhammad committed
187
188
   assert (this != NULL);

189
   return Vector_get(this->items, this->selected);
Hisham Muhammad's avatar
Hisham Muhammad committed
190
191
}

192
void Panel_moveSelectedUp(Panel* this) {
Hisham Muhammad's avatar
Hisham Muhammad committed
193
194
   assert (this != NULL);

195
   Vector_moveUp(this->items, this->selected);
Hisham Muhammad's avatar
Hisham Muhammad committed
196
197
198
199
   if (this->selected > 0)
      this->selected--;
}

200
void Panel_moveSelectedDown(Panel* this) {
Hisham Muhammad's avatar
Hisham Muhammad committed
201
202
   assert (this != NULL);

203
204
   Vector_moveDown(this->items, this->selected);
   if (this->selected + 1 < Vector_size(this->items))
Hisham Muhammad's avatar
Hisham Muhammad committed
205
206
207
      this->selected++;
}

208
int Panel_getSelectedIndex(Panel* this) {
Hisham Muhammad's avatar
Hisham Muhammad committed
209
210
211
212
213
   assert (this != NULL);

   return this->selected;
}

214
int Panel_getSize(Panel* this) {
Hisham Muhammad's avatar
Hisham Muhammad committed
215
216
   assert (this != NULL);

217
   return Vector_size(this->items);
Hisham Muhammad's avatar
Hisham Muhammad committed
218
219
}

220
void Panel_setSelected(Panel* this, int selected) {
Hisham Muhammad's avatar
Hisham Muhammad committed
221
222
   assert (this != NULL);

223
   selected = MAX(0, MIN(Vector_size(this->items) - 1, selected));
Hisham Muhammad's avatar
Hisham Muhammad committed
224
225
226
   this->selected = selected;
}

227
void Panel_draw(Panel* this, bool focus) {
Hisham Muhammad's avatar
Hisham Muhammad committed
228
229
230
   assert (this != NULL);

   int first, last;
231
   int itemCount = Vector_size(this->items);
Hisham Muhammad's avatar
Hisham Muhammad committed
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
   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) {
         mvaddchnstr(y, x, this->header.chstr + scrollH,
                     MIN(this->header.len - scrollH, this->w));
      }
      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++) {
277
         Object* itemObj = Vector_get(this->items, i);
278
279
         RichString itemRef;
         RichString_initVal(itemRef);
Hisham Muhammad's avatar
Hisham Muhammad committed
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
         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)
               mvaddchnstr(y+j, x+0, itemRef.chstr + scrollH, amt);
            attrset(CRT_colors[RESET_COLOR]);
         } else {
            mvhline(y+j, x+0, ' ', this->w);
            if (amt > 0)
               mvaddchnstr(y+j, x+0, itemRef.chstr + scrollH, amt);
         }
      }
      for (int i = y + (last - first); i < y + this->h; i++)
         mvhline(i, x+0, ' ', this->w);
      this->needsRedraw = false;

   } else {
300
      Object* oldObj = Vector_get(this->items, this->oldSelected);
301
302
      RichString oldRef;
      RichString_initVal(oldRef);
Hisham Muhammad's avatar
Hisham Muhammad committed
303
      oldObj->display(oldObj, &oldRef);
304
      Object* newObj = Vector_get(this->items, this->selected);
305
306
      RichString newRef;
      RichString_initVal(newRef);
Hisham Muhammad's avatar
Hisham Muhammad committed
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
      newObj->display(newObj, &newRef);
      mvhline(y+ this->oldSelected - this->scrollV, x+0, ' ', this->w);
      if (scrollH < oldRef.len)
         mvaddchnstr(y+ this->oldSelected - this->scrollV, x+0, oldRef.chstr + this->scrollH, MIN(oldRef.len - scrollH, this->w));
      attrset(highlight);
      mvhline(y+this->selected - this->scrollV, x+0, ' ', this->w);
      RichString_setAttr(&newRef, highlight);
      if (scrollH < newRef.len)
         mvaddchnstr(y+this->selected - this->scrollV, x+0, newRef.chstr + this->scrollH, MIN(newRef.len - scrollH, this->w));
      attrset(CRT_colors[RESET_COLOR]);
   }
   this->oldSelected = this->selected;
   move(0, 0);
}

322
void Panel_onKey(Panel* this, int key) {
Hisham Muhammad's avatar
Hisham Muhammad committed
323
324
325
   assert (this != NULL);
   switch (key) {
   case KEY_DOWN:
326
      if (this->selected + 1 < Vector_size(this->items))
Hisham Muhammad's avatar
Hisham Muhammad committed
327
328
329
330
331
332
333
334
         this->selected++;
      break;
   case KEY_UP:
      if (this->selected > 0)
         this->selected--;
      break;
   case KEY_LEFT:
      if (this->scrollH > 0) {
335
         this->scrollH -= this->scrollHAmount;
Hisham Muhammad's avatar
Hisham Muhammad committed
336
337
338
339
         this->needsRedraw = true;
      }
      break;
   case KEY_RIGHT:
340
      this->scrollH += this->scrollHAmount;
Hisham Muhammad's avatar
Hisham Muhammad committed
341
342
343
344
345
346
347
348
349
      this->needsRedraw = true;
      break;
   case KEY_PPAGE:
      this->selected -= this->h;
      if (this->selected < 0)
         this->selected = 0;
      break;
   case KEY_NPAGE:
      this->selected += this->h;
350
      int size = Vector_size(this->items);
Hisham Muhammad's avatar
Hisham Muhammad committed
351
352
353
354
355
356
357
      if (this->selected >= size)
         this->selected = size - 1;
      break;
   case KEY_HOME:
      this->selected = 0;
      break;
   case KEY_END:
358
      this->selected = Vector_size(this->items) - 1;
Hisham Muhammad's avatar
Hisham Muhammad committed
359
360
361
      break;
   }
}