Panel.c 9.7 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
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

Hisham Muhammad's avatar
Hisham Muhammad committed
67

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

   return this->selected;
}

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

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

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

225
   selected = MAX(0, MIN(Vector_size(this->items) - 1, selected));
Hisham Muhammad's avatar
Hisham Muhammad committed
226
   this->selected = selected;
227
228
229
   if (this->eventHandler) {
      this->eventHandler(this, EVENT_SETSELECTED);
   }
Hisham Muhammad's avatar
Hisham Muhammad committed
230
231
}

232
void Panel_draw(Panel* this, bool focus) {
Hisham Muhammad's avatar
Hisham Muhammad committed
233
234
235
   assert (this != NULL);

   int first, last;
236
   int itemCount = Vector_size(this->items);
Hisham Muhammad's avatar
Hisham Muhammad committed
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
   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) {
268
269
         RichString_printoffnVal(this->header, y, x, scrollH,
            MIN(this->header.len - 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
         RichString itemRef;
         RichString_initVal(itemRef);
Hisham Muhammad's avatar
Hisham Muhammad committed
285
286
287
288
289
290
291
         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)
292
               RichString_printoffnVal(itemRef, 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(itemRef, y+j, x+0, scrollH, amt);
Hisham Muhammad's avatar
Hisham Muhammad committed
298
299
300
301
302
303
304
         }
      }
      for (int i = y + (last - first); i < y + this->h; i++)
         mvhline(i, x+0, ' ', this->w);
      this->needsRedraw = false;

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

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