Panel.c 8.46 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
13
14
15
16
17
18
19
20
21
22
23
24
#include "CRT.h"
#include "RichString.h"

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

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

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

/*{

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

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

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

35
struct Panel_ {
Hisham Muhammad's avatar
Hisham Muhammad committed
36
37
38
   Object super;
   int x, y, w, h;
   WINDOW* window;
39
   Vector* items;
Hisham Muhammad's avatar
Hisham Muhammad committed
40
41
42
43
44
   int selected;
   int scrollV, scrollH;
   int oldSelected;
   bool needsRedraw;
   RichString header;
45
   Panel_EventHandler eventHandler;
Hisham Muhammad's avatar
Hisham Muhammad committed
46
47
};

48
extern char* PANEL_CLASS;
Hisham Muhammad's avatar
Hisham Muhammad committed
49
50
51
52
53
54
55
56
57
58
59

}*/

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

/* private property */
60
char* PANEL_CLASS = "Panel";
Hisham Muhammad's avatar
Hisham Muhammad committed
61

62
63
64
65
Panel* Panel_new(int x, int y, int w, int h, char* type, bool owner) {
   Panel* this;
   this = malloc(sizeof(Panel));
   Panel_init(this, x, y, w, h, type, owner);
Hisham Muhammad's avatar
Hisham Muhammad committed
66
67
68
   return this;
}

69
70
71
void Panel_delete(Object* cast) {
   Panel* this = (Panel*)cast;
   Panel_done(this);
Hisham Muhammad's avatar
Hisham Muhammad committed
72
73
74
   free(this);
}

75
void Panel_init(Panel* this, int x, int y, int w, int h, char* type, bool owner) {
Hisham Muhammad's avatar
Hisham Muhammad committed
76
   Object* super = (Object*) this;
77
78
   super->class = PANEL_CLASS;
   super->delete = Panel_delete;
Hisham Muhammad's avatar
Hisham Muhammad committed
79
80
81
82
83
   this->x = x;
   this->y = y;
   this->w = w;
   this->h = h;
   this->eventHandler = NULL;
84
   this->items = Vector_new(type, owner, DEFAULT_SIZE);
Hisham Muhammad's avatar
Hisham Muhammad committed
85
86
87
88
89
90
91
92
   this->scrollV = 0;
   this->scrollH = 0;
   this->selected = 0;
   this->oldSelected = 0;
   this->needsRedraw = true;
   this->header.len = 0;
}

93
void Panel_done(Panel* this) {
Hisham Muhammad's avatar
Hisham Muhammad committed
94
95
   assert (this != NULL);
   RichString_delete(this->header);
96
   Vector_delete(this->items);
Hisham Muhammad's avatar
Hisham Muhammad committed
97
98
}

99
inline void Panel_setRichHeader(Panel* this, RichString header) {
Hisham Muhammad's avatar
Hisham Muhammad committed
100
101
102
103
104
105
106
107
108
   assert (this != NULL);

   if (this->header.len > 0) {
      RichString_delete(this->header);
   }
   this->header = header;
   this->needsRedraw = true;
}

109
110
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
111
112
}

113
void Panel_setEventHandler(Panel* this, Panel_EventHandler eh) {
Hisham Muhammad's avatar
Hisham Muhammad committed
114
115
116
   this->eventHandler = eh;
}

117
void Panel_move(Panel* this, int x, int y) {
Hisham Muhammad's avatar
Hisham Muhammad committed
118
119
120
121
122
123
124
   assert (this != NULL);

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

125
void Panel_resize(Panel* this, int w, int h) {
Hisham Muhammad's avatar
Hisham Muhammad committed
126
127
128
129
130
131
132
133
134
   assert (this != NULL);

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

135
void Panel_prune(Panel* this) {
Hisham Muhammad's avatar
Hisham Muhammad committed
136
137
   assert (this != NULL);

138
   Vector_prune(this->items);
Hisham Muhammad's avatar
Hisham Muhammad committed
139
140
141
142
143
144
   this->scrollV = 0;
   this->selected = 0;
   this->oldSelected = 0;
   this->needsRedraw = true;
}

145
void Panel_add(Panel* this, Object* o) {
Hisham Muhammad's avatar
Hisham Muhammad committed
146
147
   assert (this != NULL);

148
   Vector_add(this->items, o);
Hisham Muhammad's avatar
Hisham Muhammad committed
149
150
151
   this->needsRedraw = true;
}

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

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

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

162
   Vector_set(this->items, i, o);
Hisham Muhammad's avatar
Hisham Muhammad committed
163
164
}

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

168
   return Vector_get(this->items, i);
Hisham Muhammad's avatar
Hisham Muhammad committed
169
170
}

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

   this->needsRedraw = true;
175
176
   Object* removed = Vector_remove(this->items, i);
   if (this->selected > 0 && this->selected >= Vector_size(this->items))
Hisham Muhammad's avatar
Hisham Muhammad committed
177
178
179
180
      this->selected--;
   return removed;
}

181
Object* Panel_getSelected(Panel* this) {
Hisham Muhammad's avatar
Hisham Muhammad committed
182
183
   assert (this != NULL);

184
   return Vector_get(this->items, this->selected);
Hisham Muhammad's avatar
Hisham Muhammad committed
185
186
}

187
void Panel_moveSelectedUp(Panel* this) {
Hisham Muhammad's avatar
Hisham Muhammad committed
188
189
   assert (this != NULL);

190
   Vector_moveUp(this->items, this->selected);
Hisham Muhammad's avatar
Hisham Muhammad committed
191
192
193
194
   if (this->selected > 0)
      this->selected--;
}

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

198
199
   Vector_moveDown(this->items, this->selected);
   if (this->selected + 1 < Vector_size(this->items))
Hisham Muhammad's avatar
Hisham Muhammad committed
200
201
202
      this->selected++;
}

203
int Panel_getSelectedIndex(Panel* this) {
Hisham Muhammad's avatar
Hisham Muhammad committed
204
205
206
207
208
   assert (this != NULL);

   return this->selected;
}

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

212
   return Vector_size(this->items);
Hisham Muhammad's avatar
Hisham Muhammad committed
213
214
}

215
void Panel_setSelected(Panel* this, int selected) {
Hisham Muhammad's avatar
Hisham Muhammad committed
216
217
   assert (this != NULL);

218
   selected = MAX(0, MIN(Vector_size(this->items) - 1, selected));
Hisham Muhammad's avatar
Hisham Muhammad committed
219
220
221
   this->selected = selected;
}

222
void Panel_draw(Panel* this, bool focus) {
Hisham Muhammad's avatar
Hisham Muhammad committed
223
224
225
   assert (this != NULL);

   int first, last;
226
   int itemCount = Vector_size(this->items);
Hisham Muhammad's avatar
Hisham Muhammad committed
227
228
229
230
231
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
   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++) {
272
         Object* itemObj = Vector_get(this->items, i);
Hisham Muhammad's avatar
Hisham Muhammad committed
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
         RichString itemRef = RichString_new();
         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 {
294
      Object* oldObj = Vector_get(this->items, this->oldSelected);
Hisham Muhammad's avatar
Hisham Muhammad committed
295
296
      RichString oldRef = RichString_new();
      oldObj->display(oldObj, &oldRef);
297
      Object* newObj = Vector_get(this->items, this->selected);
Hisham Muhammad's avatar
Hisham Muhammad committed
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
      RichString newRef = RichString_new();
      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);
}

314
void Panel_onKey(Panel* this, int key) {
Hisham Muhammad's avatar
Hisham Muhammad committed
315
316
317
   assert (this != NULL);
   switch (key) {
   case KEY_DOWN:
318
      if (this->selected + 1 < Vector_size(this->items))
Hisham Muhammad's avatar
Hisham Muhammad committed
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
         this->selected++;
      break;
   case KEY_UP:
      if (this->selected > 0)
         this->selected--;
      break;
   case KEY_LEFT:
      if (this->scrollH > 0) {
         this->scrollH -= 5;
         this->needsRedraw = true;
      }
      break;
   case KEY_RIGHT:
      this->scrollH += 5;
      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;
342
      int size = Vector_size(this->items);
Hisham Muhammad's avatar
Hisham Muhammad committed
343
344
345
346
347
348
349
      if (this->selected >= size)
         this->selected = size - 1;
      break;
   case KEY_HOME:
      this->selected = 0;
      break;
   case KEY_END:
350
      this->selected = Vector_size(this->items) - 1;
Hisham Muhammad's avatar
Hisham Muhammad committed
351
352
353
      break;
   }
}