ScreenManager.c 6.55 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
#include "Object.h"
Hisham Muhammad's avatar
Hisham Muhammad committed
12

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

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

typedef enum Orientation_ {
   VERTICAL,
   HORIZONTAL
} Orientation;

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

}*/

46
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
47
48
49
50
51
52
53
54
   ScreenManager* this;
   this = malloc(sizeof(ScreenManager));
   this->x1 = x1;
   this->y1 = y1;
   this->x2 = x2;
   this->y2 = y2;
   this->fuBar = NULL;
   this->orientation = orientation;
55
   this->panels = Vector_new(PANEL_CLASS, owner, DEFAULT_SIZE, NULL);
56
   this->fuBars = Vector_new(FUNCTIONBAR_CLASS, true, DEFAULT_SIZE, NULL);
57
   this->panelCount = 0;
58
   this->header = header;
Hisham Muhammad's avatar
Hisham Muhammad committed
59
   this->owner = owner;
60
   this->allowFocusChange = true;
Hisham Muhammad's avatar
Hisham Muhammad committed
61
62
63
64
   return this;
}

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

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

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

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

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

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

136
   int ch = 0;
Hisham Muhammad's avatar
Hisham Muhammad committed
137
   while (!quit) {
138
      int panels = this->panelCount;
139
140
141
142
      if (this->header) {
         time_t now = time(NULL);
         if (now > this->lastScan) {
            ProcessList_scan(this->header->pl);
143
            ProcessList_sort(this->header->pl);
144
145
146
            this->lastScan = now;
         }
         Header_draw(this->header);
147
         ProcessList_rebuildPanel(this->header->pl, false, false, false, false, NULL);
148
      }
149
150
      for (int i = 0; i < panels; i++) {
         Panel* panel = (Panel*) Vector_get(this->panels, i);
Hisham Muhammad's avatar
Hisham Muhammad committed
151
         Panel_draw(panel, i == focus);
152
         if (i < panels) {
Hisham Muhammad's avatar
Hisham Muhammad committed
153
            if (this->orientation == HORIZONTAL) {
Hisham Muhammad's avatar
Hisham Muhammad committed
154
               mvvline(panel->y, panel->x+panel->w, ' ', panel->h+1);
Hisham Muhammad's avatar
Hisham Muhammad committed
155
156
157
            }
         }
      }
158
      FunctionBar* bar = (FunctionBar*) Vector_get(this->fuBars, focus);
Hisham Muhammad's avatar
Hisham Muhammad committed
159
160
161
162
163
164
165
166
167
168
169
170
171
172
      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 {
173
174
               for (int i = 0; i < this->panelCount; i++) {
                  Panel* panel = (Panel*) Vector_get(this->panels, i);
Hisham Muhammad's avatar
Hisham Muhammad committed
175
176
                  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
177
                     focus = i;
Hisham Muhammad's avatar
Hisham Muhammad committed
178
179
                     panelFocus = panel;
                     Panel_setSelected(panel, mevent.y - panel->y + panel->scrollV - 1);
Hisham Muhammad's avatar
Hisham Muhammad committed
180
181
182
183
184
185
186
                     break;
                  }
               }
            }
         }
      }
      
Hisham Muhammad's avatar
Hisham Muhammad committed
187
188
      if (panelFocus->eventHandler) {
         HandlerResult result = panelFocus->eventHandler(panelFocus, ch);
Hisham Muhammad's avatar
Hisham Muhammad committed
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
         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:
206
      case KEY_CTRLB:
207
208
         if (!this->allowFocusChange)
            break;
Hisham Muhammad's avatar
Hisham Muhammad committed
209
210
211
         tryLeft:
         if (focus > 0)
            focus--;
212
         panelFocus = (Panel*) Vector_get(this->panels, focus);
Hisham Muhammad's avatar
Hisham Muhammad committed
213
         if (Panel_size(panelFocus) == 0 && focus > 0)
Hisham Muhammad's avatar
Hisham Muhammad committed
214
215
216
            goto tryLeft;
         break;
      case KEY_RIGHT:
217
      case KEY_CTRLF:
Hisham Muhammad's avatar
Hisham Muhammad committed
218
      case 9:
219
220
         if (!this->allowFocusChange)
            break;
Hisham Muhammad's avatar
Hisham Muhammad committed
221
         tryRight:
222
         if (focus < this->panelCount - 1)
Hisham Muhammad's avatar
Hisham Muhammad committed
223
            focus++;
224
225
         panelFocus = (Panel*) Vector_get(this->panels, focus);
         if (Panel_size(panelFocus) == 0 && focus < this->panelCount - 1)
Hisham Muhammad's avatar
Hisham Muhammad committed
226
227
228
229
230
231
232
233
            goto tryRight;
         break;
      case KEY_F(10):
      case 'q':
      case 27:
         quit = true;
         continue;
      default:
Hisham Muhammad's avatar
Hisham Muhammad committed
234
         Panel_onKey(panelFocus, ch);
Hisham Muhammad's avatar
Hisham Muhammad committed
235
236
237
238
         break;
      }
   }

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