Panel.c 10 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-2010 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
35
#define EVENT_SETSELECTED -1

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

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

}*/

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

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

67
68
69
70
#define KEY_CTRLN      0016            /* control-n key */
#define KEY_CTRLP      0020            /* control-p key */
#define KEY_CTRLF      0006            /* control-f key */
#define KEY_CTRLB      0002            /* control-b key */
Hisham Muhammad's avatar
Hisham Muhammad committed
71

72
Panel* Panel_new(int x, int y, int w, int h, char* type, bool owner, Object_Compare compare) {
73
74
75
   Panel* this;
   this = malloc(sizeof(Panel));
   Panel_init(this, x, y, w, h, type, owner);
76
   this->items->compare = compare;
Hisham Muhammad's avatar
Hisham Muhammad committed
77
78
79
   return this;
}

80
81
82
void Panel_delete(Object* cast) {
   Panel* this = (Panel*)cast;
   Panel_done(this);
Hisham Muhammad's avatar
Hisham Muhammad committed
83
84
85
   free(this);
}

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

108
void Panel_done(Panel* this) {
Hisham Muhammad's avatar
Hisham Muhammad committed
109
   assert (this != NULL);
110
   Vector_delete(this->items);
Hisham Muhammad's avatar
Hisham Muhammad committed
111
112
}

113
inline void Panel_setRichHeader(Panel* this, RichString header) {
Hisham Muhammad's avatar
Hisham Muhammad committed
114
115
116
117
118
119
   assert (this != NULL);

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

Hisham Muhammad's avatar
Hisham Muhammad committed
120
inline void Panel_setHeader(Panel* this, const char* header) {
121
   Panel_setRichHeader(this, RichString_quickString(CRT_colors[PANEL_HEADER_FOCUS], header));
Hisham Muhammad's avatar
Hisham Muhammad committed
122
123
}

124
void Panel_setEventHandler(Panel* this, Panel_EventHandler eh) {
Hisham Muhammad's avatar
Hisham Muhammad committed
125
126
127
   this->eventHandler = eh;
}

128
void Panel_move(Panel* this, int x, int y) {
Hisham Muhammad's avatar
Hisham Muhammad committed
129
130
131
132
133
134
135
   assert (this != NULL);

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

136
void Panel_resize(Panel* this, int w, int h) {
Hisham Muhammad's avatar
Hisham Muhammad committed
137
138
139
140
141
142
143
144
145
   assert (this != NULL);

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

146
void Panel_prune(Panel* this) {
Hisham Muhammad's avatar
Hisham Muhammad committed
147
148
   assert (this != NULL);

149
   Vector_prune(this->items);
Hisham Muhammad's avatar
Hisham Muhammad committed
150
151
152
153
154
155
   this->scrollV = 0;
   this->selected = 0;
   this->oldSelected = 0;
   this->needsRedraw = true;
}

156
void Panel_add(Panel* this, Object* o) {
Hisham Muhammad's avatar
Hisham Muhammad committed
157
158
   assert (this != NULL);

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

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

166
   Vector_insert(this->items, i, o);
Hisham Muhammad's avatar
Hisham Muhammad committed
167
168
169
   this->needsRedraw = true;
}

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

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

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

179
   return Vector_get(this->items, i);
Hisham Muhammad's avatar
Hisham Muhammad committed
180
181
}

182
Object* Panel_remove(Panel* this, int i) {
Hisham Muhammad's avatar
Hisham Muhammad committed
183
184
185
   assert (this != NULL);

   this->needsRedraw = true;
186
187
   Object* removed = Vector_remove(this->items, i);
   if (this->selected > 0 && this->selected >= Vector_size(this->items))
Hisham Muhammad's avatar
Hisham Muhammad committed
188
189
190
191
      this->selected--;
   return removed;
}

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

195
   return Vector_get(this->items, this->selected);
Hisham Muhammad's avatar
Hisham Muhammad committed
196
197
}

198
void Panel_moveSelectedUp(Panel* this) {
Hisham Muhammad's avatar
Hisham Muhammad committed
199
200
   assert (this != NULL);

201
   Vector_moveUp(this->items, this->selected);
Hisham Muhammad's avatar
Hisham Muhammad committed
202
203
204
205
   if (this->selected > 0)
      this->selected--;
}

206
void Panel_moveSelectedDown(Panel* this) {
Hisham Muhammad's avatar
Hisham Muhammad committed
207
208
   assert (this != NULL);

209
210
   Vector_moveDown(this->items, this->selected);
   if (this->selected + 1 < Vector_size(this->items))
Hisham Muhammad's avatar
Hisham Muhammad committed
211
212
213
      this->selected++;
}

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

   return this->selected;
}

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

223
   return Vector_size(this->items);
Hisham Muhammad's avatar
Hisham Muhammad committed
224
225
}

226
void Panel_setSelected(Panel* this, int selected) {
Hisham Muhammad's avatar
Hisham Muhammad committed
227
228
   assert (this != NULL);

229
   selected = MAX(0, MIN(Vector_size(this->items) - 1, selected));
Hisham Muhammad's avatar
Hisham Muhammad committed
230
   this->selected = selected;
231
232
233
   if (this->eventHandler) {
      this->eventHandler(this, EVENT_SETSELECTED);
   }
Hisham Muhammad's avatar
Hisham Muhammad committed
234
235
}

236
void Panel_draw(Panel* this, bool focus) {
Hisham Muhammad's avatar
Hisham Muhammad committed
237
238
239
   assert (this != NULL);

   int first, last;
240
   int itemCount = Vector_size(this->items);
Hisham Muhammad's avatar
Hisham Muhammad committed
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
   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) {
272
273
         RichString_printoffnVal(this->header, y, x, scrollH,
            MIN(this->header.len - scrollH, this->w));
Hisham Muhammad's avatar
Hisham Muhammad committed
274
275
276
277
278
279
280
281
282
283
284
285
      }
      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++) {
286
         Object* itemObj = Vector_get(this->items, i);
287
288
         RichString itemRef;
         RichString_initVal(itemRef);
Hisham Muhammad's avatar
Hisham Muhammad committed
289
290
291
292
293
294
295
         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)
296
               RichString_printoffnVal(itemRef, y+j, x+0, scrollH, amt);
Hisham Muhammad's avatar
Hisham Muhammad committed
297
298
299
300
            attrset(CRT_colors[RESET_COLOR]);
         } else {
            mvhline(y+j, x+0, ' ', this->w);
            if (amt > 0)
301
               RichString_printoffnVal(itemRef, y+j, x+0, scrollH, amt);
Hisham Muhammad's avatar
Hisham Muhammad committed
302
303
304
305
306
307
308
         }
      }
      for (int i = y + (last - first); i < y + this->h; i++)
         mvhline(i, x+0, ' ', this->w);
      this->needsRedraw = false;

   } else {
309
      Object* oldObj = Vector_get(this->items, this->oldSelected);
310
311
      RichString oldRef;
      RichString_initVal(oldRef);
Hisham Muhammad's avatar
Hisham Muhammad committed
312
      oldObj->display(oldObj, &oldRef);
313
      Object* newObj = Vector_get(this->items, this->selected);
314
315
      RichString newRef;
      RichString_initVal(newRef);
Hisham Muhammad's avatar
Hisham Muhammad committed
316
317
318
      newObj->display(newObj, &newRef);
      mvhline(y+ this->oldSelected - this->scrollV, x+0, ' ', this->w);
      if (scrollH < oldRef.len)
319
320
         RichString_printoffnVal(oldRef, y+this->oldSelected - this->scrollV, x,
            this->scrollH, MIN(oldRef.len - scrollH, this->w));
Hisham Muhammad's avatar
Hisham Muhammad committed
321
322
323
324
      attrset(highlight);
      mvhline(y+this->selected - this->scrollV, x+0, ' ', this->w);
      RichString_setAttr(&newRef, highlight);
      if (scrollH < newRef.len)
325
326
         RichString_printoffnVal(newRef, y+this->selected - this->scrollV, x,
            this->scrollH, MIN(newRef.len - scrollH, this->w));
Hisham Muhammad's avatar
Hisham Muhammad committed
327
328
329
330
331
332
      attrset(CRT_colors[RESET_COLOR]);
   }
   this->oldSelected = this->selected;
   move(0, 0);
}

Hisham Muhammad's avatar
Hisham Muhammad committed
333
bool Panel_onKey(Panel* this, int key) {
Hisham Muhammad's avatar
Hisham Muhammad committed
334
335
336
   assert (this != NULL);
   switch (key) {
   case KEY_DOWN:
337
   case KEY_CTRLN:
338
      if (this->selected + 1 < Vector_size(this->items))
Hisham Muhammad's avatar
Hisham Muhammad committed
339
         this->selected++;
Hisham Muhammad's avatar
Hisham Muhammad committed
340
      return true;
Hisham Muhammad's avatar
Hisham Muhammad committed
341
   case KEY_UP:
342
   case KEY_CTRLP:
Hisham Muhammad's avatar
Hisham Muhammad committed
343
344
      if (this->selected > 0)
         this->selected--;
Hisham Muhammad's avatar
Hisham Muhammad committed
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
      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
Hisham Muhammad's avatar
Hisham Muhammad committed
368
   case KEY_LEFT:
369
   case KEY_CTRLB:
Hisham Muhammad's avatar
Hisham Muhammad committed
370
      if (this->scrollH > 0) {
Hisham Muhammad's avatar
Hisham Muhammad committed
371
         this->scrollH -= 5;
Hisham Muhammad's avatar
Hisham Muhammad committed
372
373
         this->needsRedraw = true;
      }
Hisham Muhammad's avatar
Hisham Muhammad committed
374
      return true;
Hisham Muhammad's avatar
Hisham Muhammad committed
375
   case KEY_RIGHT:
376
   case KEY_CTRLF:
Hisham Muhammad's avatar
Hisham Muhammad committed
377
      this->scrollH += 5;
Hisham Muhammad's avatar
Hisham Muhammad committed
378
      this->needsRedraw = true;
Hisham Muhammad's avatar
Hisham Muhammad committed
379
      return true;
Hisham Muhammad's avatar
Hisham Muhammad committed
380
   case KEY_PPAGE:
Hisham Muhammad's avatar
Hisham Muhammad committed
381
382
      this->selected -= (this->h - 1);
      this->scrollV -= (this->h - 1);
Hisham Muhammad's avatar
Hisham Muhammad committed
383
384
      if (this->selected < 0)
         this->selected = 0;
Hisham Muhammad's avatar
Hisham Muhammad committed
385
386
387
388
      if (this->scrollV < 0)
         this->scrollV = 0;
      this->needsRedraw = true;
      return true;
Hisham Muhammad's avatar
Hisham Muhammad committed
389
   case KEY_NPAGE:
Hisham Muhammad's avatar
Hisham Muhammad committed
390
      this->selected += (this->h - 1);
391
      int size = Vector_size(this->items);
Hisham Muhammad's avatar
Hisham Muhammad committed
392
393
      if (this->selected >= size)
         this->selected = size - 1;
Hisham Muhammad's avatar
Hisham Muhammad committed
394
395
396
397
398
      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;
Hisham Muhammad's avatar
Hisham Muhammad committed
399
400
   case KEY_HOME:
      this->selected = 0;
Hisham Muhammad's avatar
Hisham Muhammad committed
401
      return true;
Hisham Muhammad's avatar
Hisham Muhammad committed
402
   case KEY_END:
403
      this->selected = Vector_size(this->items) - 1;
Hisham Muhammad's avatar
Hisham Muhammad committed
404
      return true;
Hisham Muhammad's avatar
Hisham Muhammad committed
405
   }
Hisham Muhammad's avatar
Hisham Muhammad committed
406
   return false;
Hisham Muhammad's avatar
Hisham Muhammad committed
407
}