ScreenManager.c 6.57 KB
Newer Older
Hisham Muhammad's avatar
Hisham Muhammad committed
1
/*
Hisham Muhammad's avatar
Hisham Muhammad committed
2
htop - ScreenManager.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 "ScreenManager.h"
Hisham Muhammad's avatar
Hisham Muhammad committed
9

10
#include "Panel.h"
Hisham Muhammad's avatar
Hisham Muhammad committed
11
12
#include "Object.h"
#include "debug.h"
Hisham Muhammad's avatar
Hisham Muhammad committed
13

Hisham Muhammad's avatar
Hisham Muhammad committed
14
#include <assert.h>
15
#include <time.h>
Hisham Muhammad's avatar
Hisham Muhammad committed
16
#include <stdlib.h>
Hisham Muhammad's avatar
Hisham Muhammad committed
17
18
19
#include <stdbool.h>

/*{
Hisham Muhammad's avatar
Hisham Muhammad committed
20
21
22
#include "FunctionBar.h"
#include "Vector.h"
#include "Header.h"
Hisham Muhammad's avatar
Hisham Muhammad committed
23
24
25
26
27
28
29
30
31
32
33
34

typedef enum Orientation_ {
   VERTICAL,
   HORIZONTAL
} Orientation;

typedef struct ScreenManager_ {
   int x1;
   int y1;
   int x2;
   int y2;
   Orientation orientation;
35
   Vector* panels;
36
   Vector* fuBars;
37
   int panelCount;
38
39
40
   const FunctionBar* fuBar;
   const Header* header;
   time_t lastScan;
Hisham Muhammad's avatar
Hisham Muhammad committed
41
   bool owner;
42
   bool allowFocusChange;
Hisham Muhammad's avatar
Hisham Muhammad committed
43
44
45
46
} ScreenManager;

}*/

47
ScreenManager* ScreenManager_new(int x1, int y1, int x2, int y2, Orientation orientation, const Header* header, bool owner) {
Hisham Muhammad's avatar
Hisham Muhammad committed
48
49
50
51
52
53
54
55
   ScreenManager* this;
   this = malloc(sizeof(ScreenManager));
   this->x1 = x1;
   this->y1 = y1;
   this->x2 = x2;
   this->y2 = y2;
   this->fuBar = NULL;
   this->orientation = orientation;
56
   this->panels = Vector_new(PANEL_CLASS, owner, DEFAULT_SIZE, NULL);
57
   this->fuBars = Vector_new(FUNCTIONBAR_CLASS, true, DEFAULT_SIZE, NULL);
58
   this->panelCount = 0;
59
   this->header = header;
Hisham Muhammad's avatar
Hisham Muhammad committed
60
   this->owner = owner;
61
   this->allowFocusChange = true;
Hisham Muhammad's avatar
Hisham Muhammad committed
62
63
64
65
   return this;
}

void ScreenManager_delete(ScreenManager* this) {
66
   Vector_delete(this->panels);
67
   Vector_delete(this->fuBars);
Hisham Muhammad's avatar
Hisham Muhammad committed
68
69
70
71
   free(this);
}

inline int ScreenManager_size(ScreenManager* this) {
72
   return this->panelCount;
Hisham Muhammad's avatar
Hisham Muhammad committed
73
74
}

75
void ScreenManager_add(ScreenManager* this, Panel* item, FunctionBar* fuBar, int size) {
Hisham Muhammad's avatar
Hisham Muhammad committed
76
77
   if (this->orientation == HORIZONTAL) {
      int lastX = 0;
78
79
      if (this->panelCount > 0) {
         Panel* last = (Panel*) Vector_get(this->panels, this->panelCount - 1);
Hisham Muhammad's avatar
Hisham Muhammad committed
80
81
82
         lastX = last->x + last->w + 1;
      }
      if (size > 0) {
83
         Panel_resize(item, size, LINES-this->y1+this->y2);
Hisham Muhammad's avatar
Hisham Muhammad committed
84
      } else {
85
         Panel_resize(item, COLS-this->x1+this->x2-lastX, LINES-this->y1+this->y2);
Hisham Muhammad's avatar
Hisham Muhammad committed
86
      }
87
      Panel_move(item, lastX, this->y1);
Hisham Muhammad's avatar
Hisham Muhammad committed
88
89
   }
   // TODO: VERTICAL
90
   Vector_add(this->panels, item);
Hisham Muhammad's avatar
Hisham Muhammad committed
91
   if (fuBar)
92
      Vector_add(this->fuBars, fuBar);
Hisham Muhammad's avatar
Hisham Muhammad committed
93
   else
Hisham Muhammad's avatar
Hisham Muhammad committed
94
      Vector_add(this->fuBars, FunctionBar_new(NULL, NULL, NULL));
Hisham Muhammad's avatar
Hisham Muhammad committed
95
96
   if (!this->fuBar && fuBar) this->fuBar = fuBar;
   item->needsRedraw = true;
97
   this->panelCount++;
Hisham Muhammad's avatar
Hisham Muhammad committed
98
99
}

Hisham Muhammad's avatar
Hisham Muhammad committed
100
Panel* ScreenManager_remove(ScreenManager* this, int idx) {
101
102
   assert(this->panelCount > idx);
   Panel* panel = (Panel*) Vector_remove(this->panels, idx);
Hisham Muhammad's avatar
Hisham Muhammad committed
103
   Vector_remove(this->fuBars, idx);
Hisham Muhammad's avatar
Hisham Muhammad committed
104
   this->fuBar = NULL;
105
   this->panelCount--;
Hisham Muhammad's avatar
Hisham Muhammad committed
106
   return panel;
Hisham Muhammad's avatar
Hisham Muhammad committed
107
108
109
110
111
112
113
}

void ScreenManager_resize(ScreenManager* this, int x1, int y1, int x2, int y2) {
   this->x1 = x1;
   this->y1 = y1;
   this->x2 = x2;
   this->y2 = y2;
114
   int panels = this->panelCount;
Hisham Muhammad's avatar
Hisham Muhammad committed
115
   int lastX = 0;
116
117
   for (int i = 0; i < panels - 1; i++) {
      Panel* panel = (Panel*) Vector_get(this->panels, i);
Hisham Muhammad's avatar
Hisham Muhammad committed
118
119
120
      Panel_resize(panel, panel->w, LINES-y1+y2);
      Panel_move(panel, lastX, y1);
      lastX = panel->x + panel->w + 1;
Hisham Muhammad's avatar
Hisham Muhammad committed
121
   }
122
   Panel* panel = (Panel*) Vector_get(this->panels, panels-1);
Hisham Muhammad's avatar
Hisham Muhammad committed
123
124
   Panel_resize(panel, COLS-x1+x2-lastX, LINES-y1+y2);
   Panel_move(panel, lastX, y1);
Hisham Muhammad's avatar
Hisham Muhammad committed
125
126
}

127
void ScreenManager_run(ScreenManager* this, Panel** lastFocus, int* lastKey) {
Hisham Muhammad's avatar
Hisham Muhammad committed
128
129
   bool quit = false;
   int focus = 0;
130
   
131
   Panel* panelFocus = (Panel*) Vector_get(this->panels, focus);
Hisham Muhammad's avatar
Hisham Muhammad committed
132
133
134
   if (this->fuBar)
      FunctionBar_draw(this->fuBar, NULL);
   
135
136
   this->lastScan = 0;

137
   int ch = 0;
Hisham Muhammad's avatar
Hisham Muhammad committed
138
   while (!quit) {
139
      int panels = this->panelCount;
140
141
142
143
      if (this->header) {
         time_t now = time(NULL);
         if (now > this->lastScan) {
            ProcessList_scan(this->header->pl);
144
            ProcessList_sort(this->header->pl);
145
146
147
            this->lastScan = now;
         }
         Header_draw(this->header);
148
         ProcessList_rebuildPanel(this->header->pl, false, false, false, false, false, NULL);
149
      }
150
151
      for (int i = 0; i < panels; i++) {
         Panel* panel = (Panel*) Vector_get(this->panels, i);
Hisham Muhammad's avatar
Hisham Muhammad committed
152
         Panel_draw(panel, i == focus);
153
         if (i < panels) {
Hisham Muhammad's avatar
Hisham Muhammad committed
154
            if (this->orientation == HORIZONTAL) {
Hisham Muhammad's avatar
Hisham Muhammad committed
155
               mvvline(panel->y, panel->x+panel->w, ' ', panel->h+1);
Hisham Muhammad's avatar
Hisham Muhammad committed
156
157
158
            }
         }
      }
159
      FunctionBar* bar = (FunctionBar*) Vector_get(this->fuBars, focus);
Hisham Muhammad's avatar
Hisham Muhammad committed
160
161
162
163
164
165
166
167
168
169
170
171
172
173
      if (bar)
         this->fuBar = bar;
      if (this->fuBar)
         FunctionBar_draw(this->fuBar, NULL);

      ch = getch();
      
      if (ch == KEY_MOUSE) {
         MEVENT mevent;
         int ok = getmouse(&mevent);
         if (ok == OK) {
            if (mevent.y == LINES - 1) {
               ch = FunctionBar_synthesizeEvent(this->fuBar, mevent.x);
            } else {
174
175
               for (int i = 0; i < this->panelCount; i++) {
                  Panel* panel = (Panel*) Vector_get(this->panels, i);
Hisham Muhammad's avatar
Hisham Muhammad committed
176
177
                  if (mevent.x > panel->x && mevent.x <= panel->x+panel->w &&
                     mevent.y > panel->y && mevent.y <= panel->y+panel->h) {
Hisham Muhammad's avatar
Hisham Muhammad committed
178
                     focus = i;
Hisham Muhammad's avatar
Hisham Muhammad committed
179
180
                     panelFocus = panel;
                     Panel_setSelected(panel, mevent.y - panel->y + panel->scrollV - 1);
Hisham Muhammad's avatar
Hisham Muhammad committed
181
182
183
184
185
186
187
                     break;
                  }
               }
            }
         }
      }
      
Hisham Muhammad's avatar
Hisham Muhammad committed
188
189
      if (panelFocus->eventHandler) {
         HandlerResult result = panelFocus->eventHandler(panelFocus, ch);
Hisham Muhammad's avatar
Hisham Muhammad committed
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
         if (result == HANDLED) {
            continue;
         } else if (result == BREAK_LOOP) {
            quit = true;
            continue;
         }
      }
      
      switch (ch) {
      case ERR:
         continue;
      case KEY_RESIZE:
      {
         ScreenManager_resize(this, this->x1, this->y1, this->x2, this->y2);
         continue;
      }
      case KEY_LEFT:
207
      case KEY_CTRLB:
208
209
         if (!this->allowFocusChange)
            break;
Hisham Muhammad's avatar
Hisham Muhammad committed
210
211
212
         tryLeft:
         if (focus > 0)
            focus--;
213
         panelFocus = (Panel*) Vector_get(this->panels, focus);
Hisham Muhammad's avatar
Hisham Muhammad committed
214
         if (Panel_size(panelFocus) == 0 && focus > 0)
Hisham Muhammad's avatar
Hisham Muhammad committed
215
216
217
            goto tryLeft;
         break;
      case KEY_RIGHT:
218
      case KEY_CTRLF:
Hisham Muhammad's avatar
Hisham Muhammad committed
219
      case 9:
220
221
         if (!this->allowFocusChange)
            break;
Hisham Muhammad's avatar
Hisham Muhammad committed
222
         tryRight:
223
         if (focus < this->panelCount - 1)
Hisham Muhammad's avatar
Hisham Muhammad committed
224
            focus++;
225
226
         panelFocus = (Panel*) Vector_get(this->panels, focus);
         if (Panel_size(panelFocus) == 0 && focus < this->panelCount - 1)
Hisham Muhammad's avatar
Hisham Muhammad committed
227
228
229
230
231
232
233
234
            goto tryRight;
         break;
      case KEY_F(10):
      case 'q':
      case 27:
         quit = true;
         continue;
      default:
Hisham Muhammad's avatar
Hisham Muhammad committed
235
         Panel_onKey(panelFocus, ch);
Hisham Muhammad's avatar
Hisham Muhammad committed
236
237
238
239
         break;
      }
   }

Hisham Muhammad's avatar
Hisham Muhammad committed
240
   *lastFocus = panelFocus;
Hisham Muhammad's avatar
Hisham Muhammad committed
241
242
   *lastKey = ch;
}