Panel.c 10.1 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-2011 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;
50
   char* eventHandlerBuffer;
Hisham Muhammad's avatar
Hisham Muhammad committed
51
52
53
54
55
56
57
58
59
60
61
};

}*/

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

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

68
69
70
71
#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
72

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

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

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

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

115
RichString* Panel_getHeader(Panel* this) {
Hisham Muhammad's avatar
Hisham Muhammad committed
116
117
118
   assert (this != NULL);

   this->needsRedraw = true;
119
   return &(this->header);
Hisham Muhammad's avatar
Hisham Muhammad committed
120
121
}

Hisham Muhammad's avatar
Hisham Muhammad committed
122
inline void Panel_setHeader(Panel* this, const char* header) {
123
124
   RichString_write(&(this->header), CRT_colors[PANEL_HEADER_FOCUS], header);
   this->needsRedraw = true;
Hisham Muhammad's avatar
Hisham Muhammad committed
125
126
}

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

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

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

139
void Panel_resize(Panel* this, int w, int h) {
Hisham Muhammad's avatar
Hisham Muhammad committed
140
141
   assert (this != NULL);

142
   if (RichString_sizeVal(this->header) > 0)
Hisham Muhammad's avatar
Hisham Muhammad committed
143
144
145
146
147
148
      h--;
   this->w = w;
   this->h = h;
   this->needsRedraw = true;
}

149
void Panel_prune(Panel* this) {
Hisham Muhammad's avatar
Hisham Muhammad committed
150
151
   assert (this != NULL);

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

159
void Panel_add(Panel* this, Object* o) {
Hisham Muhammad's avatar
Hisham Muhammad committed
160
161
   assert (this != NULL);

162
   Vector_add(this->items, o);
Hisham Muhammad's avatar
Hisham Muhammad committed
163
164
165
   this->needsRedraw = true;
}

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

169
   Vector_insert(this->items, i, o);
Hisham Muhammad's avatar
Hisham Muhammad committed
170
171
172
   this->needsRedraw = true;
}

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

176
   Vector_set(this->items, i, o);
Hisham Muhammad's avatar
Hisham Muhammad committed
177
178
}

179
Object* Panel_get(Panel* this, int i) {
Hisham Muhammad's avatar
Hisham Muhammad committed
180
181
   assert (this != NULL);

182
   return Vector_get(this->items, i);
Hisham Muhammad's avatar
Hisham Muhammad committed
183
184
}

185
Object* Panel_remove(Panel* this, int i) {
Hisham Muhammad's avatar
Hisham Muhammad committed
186
187
188
   assert (this != NULL);

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

195
Object* Panel_getSelected(Panel* this) {
Hisham Muhammad's avatar
Hisham Muhammad committed
196
197
   assert (this != NULL);

198
   return Vector_get(this->items, this->selected);
Hisham Muhammad's avatar
Hisham Muhammad committed
199
200
}

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

204
   Vector_moveUp(this->items, this->selected);
Hisham Muhammad's avatar
Hisham Muhammad committed
205
206
207
208
   if (this->selected > 0)
      this->selected--;
}

209
void Panel_moveSelectedDown(Panel* this) {
Hisham Muhammad's avatar
Hisham Muhammad committed
210
211
   assert (this != NULL);

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

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

   return this->selected;
}

Hisham Muhammad's avatar
Hisham Muhammad committed
223
int Panel_size(Panel* this) {
Hisham Muhammad's avatar
Hisham Muhammad committed
224
225
   assert (this != NULL);

226
   return Vector_size(this->items);
Hisham Muhammad's avatar
Hisham Muhammad committed
227
228
}

229
void Panel_setSelected(Panel* this, int selected) {
Hisham Muhammad's avatar
Hisham Muhammad committed
230
231
   assert (this != NULL);

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

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

242
   int itemCount = Vector_size(this->items);
Hisham Muhammad's avatar
Hisham Muhammad committed
243
244
   int scrollH = this->scrollH;
   int y = this->y; int x = this->x;
245
246
   int first = this->scrollV;
   int last = MIN(itemCount, this->scrollV + MIN(itemCount, this->h));
Hisham Muhammad's avatar
Hisham Muhammad committed
247
248
249
250
251
252
253
254
255
256
257
258
259
260
   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);

261
262
   int headerLen = RichString_sizeVal(this->header);
   if (headerLen > 0) {
Hisham Muhammad's avatar
Hisham Muhammad committed
263
264
265
266
267
      int attr = focus
               ? CRT_colors[PANEL_HEADER_FOCUS]
               : CRT_colors[PANEL_HEADER_UNFOCUS];
      attrset(attr);
      mvhline(y, x, ' ', this->w);
268
      if (scrollH < headerLen) {
269
         RichString_printoffnVal(this->header, y, x, scrollH,
270
            MIN(headerLen - scrollH, this->w));
Hisham Muhammad's avatar
Hisham Muhammad committed
271
272
273
274
275
276
277
278
279
280
281
282
      }
      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++) {
283
         Object* itemObj = Vector_get(this->items, i);
284
285
286
287
         RichString_begin(item);
         itemObj->display(itemObj, &item);
         int itemLen = RichString_sizeVal(item);
         int amt = MIN(itemLen - scrollH, this->w);
Hisham Muhammad's avatar
Hisham Muhammad committed
288
289
         if (i == this->selected) {
            attrset(highlight);
290
            RichString_setAttr(&item, highlight);
Hisham Muhammad's avatar
Hisham Muhammad committed
291
292
            mvhline(y + j, x+0, ' ', this->w);
            if (amt > 0)
293
               RichString_printoffnVal(item, y+j, x+0, scrollH, amt);
Hisham Muhammad's avatar
Hisham Muhammad committed
294
295
296
297
            attrset(CRT_colors[RESET_COLOR]);
         } else {
            mvhline(y+j, x+0, ' ', this->w);
            if (amt > 0)
298
               RichString_printoffnVal(item, y+j, x+0, scrollH, amt);
Hisham Muhammad's avatar
Hisham Muhammad committed
299
         }
300
         RichString_end(item);
Hisham Muhammad's avatar
Hisham Muhammad committed
301
302
303
304
305
306
      }
      for (int i = y + (last - first); i < y + this->h; i++)
         mvhline(i, x+0, ' ', this->w);
      this->needsRedraw = false;

   } else {
307
      Object* oldObj = Vector_get(this->items, this->oldSelected);
308
309
310
      RichString_begin(old);
      oldObj->display(oldObj, &old);
      int oldLen = RichString_sizeVal(old);
311
      Object* newObj = Vector_get(this->items, this->selected);
312
313
314
      RichString_begin(new);
      newObj->display(newObj, &new);
      int newLen = RichString_sizeVal(new);
Hisham Muhammad's avatar
Hisham Muhammad committed
315
      mvhline(y+ this->oldSelected - this->scrollV, x+0, ' ', this->w);
316
317
318
      if (scrollH < oldLen)
         RichString_printoffnVal(old, y+this->oldSelected - this->scrollV, x,
            this->scrollH, MIN(oldLen - scrollH, this->w));
Hisham Muhammad's avatar
Hisham Muhammad committed
319
320
      attrset(highlight);
      mvhline(y+this->selected - this->scrollV, x+0, ' ', this->w);
321
322
323
324
      RichString_setAttr(&new, highlight);
      if (scrollH < newLen)
         RichString_printoffnVal(new, y+this->selected - this->scrollV, x,
            this->scrollH, MIN(newLen - scrollH, this->w));
Hisham Muhammad's avatar
Hisham Muhammad committed
325
      attrset(CRT_colors[RESET_COLOR]);
326
327
      RichString_end(new);
      RichString_end(old);
Hisham Muhammad's avatar
Hisham Muhammad committed
328
329
330
331
332
   }
   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
}