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;
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;
101
   RichString_beginAllocated(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);
111
   RichString_end(this->header);
Hisham Muhammad's avatar
Hisham Muhammad committed
112
113
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

   return this->selected;
}

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

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

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

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

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

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

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

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

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