ScreenManager.c 6.04 KB
Newer Older
Hisham Muhammad's avatar
Hisham Muhammad committed
1
2
3
4
5
6
7
8
/*
htop
(C) 2004-2006 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file
in the source distribution for its full text.
*/

#include "ScreenManager.h"
9
#include "Panel.h"
Hisham Muhammad's avatar
Hisham Muhammad committed
10
#include "Object.h"
11
#include "Vector.h"
Hisham Muhammad's avatar
Hisham Muhammad committed
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include "FunctionBar.h"

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

#include <stdbool.h>

/*{

typedef enum Orientation_ {
   VERTICAL,
   HORIZONTAL
} Orientation;

typedef struct ScreenManager_ {
   int x1;
   int y1;
   int x2;
   int y2;
   Orientation orientation;
32
33
   Vector* items;
   Vector* fuBars;
Hisham Muhammad's avatar
Hisham Muhammad committed
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
   int itemCount;
   FunctionBar* fuBar;
   bool owner;
} ScreenManager;

}*/

ScreenManager* ScreenManager_new(int x1, int y1, int x2, int y2, Orientation orientation, bool owner) {
   ScreenManager* this;
   this = malloc(sizeof(ScreenManager));
   this->x1 = x1;
   this->y1 = y1;
   this->x2 = x2;
   this->y2 = y2;
   this->fuBar = NULL;
   this->orientation = orientation;
50
   this->items = Vector_new(PANEL_CLASS, owner, DEFAULT_SIZE);
51
   this->fuBars = Vector_new(FUNCTIONBAR_CLASS, true, DEFAULT_SIZE);
Hisham Muhammad's avatar
Hisham Muhammad committed
52
53
54
55
56
57
   this->itemCount = 0;
   this->owner = owner;
   return this;
}

void ScreenManager_delete(ScreenManager* this) {
58
59
   Vector_delete(this->items);
   Vector_delete(this->fuBars);
Hisham Muhammad's avatar
Hisham Muhammad committed
60
61
62
63
64
65
66
   free(this);
}

inline int ScreenManager_size(ScreenManager* this) {
   return this->itemCount;
}

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

92
Panel* ScreenManager_remove(ScreenManager* this, int index) {
Hisham Muhammad's avatar
Hisham Muhammad committed
93
   assert(this->itemCount > index);
Hisham Muhammad's avatar
Hisham Muhammad committed
94
   Panel* panel = (Panel*) Vector_remove(this->items, index);
95
   Vector_remove(this->fuBars, index);
Hisham Muhammad's avatar
Hisham Muhammad committed
96
97
   this->fuBar = NULL;
   this->itemCount--;
Hisham Muhammad's avatar
Hisham Muhammad committed
98
   return panel;
Hisham Muhammad's avatar
Hisham Muhammad committed
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
}

void ScreenManager_setFunctionBar(ScreenManager* this, FunctionBar* fuBar) {
   if (this->owner && this->fuBar)
      FunctionBar_delete((Object*)this->fuBar);
   this->fuBar = fuBar;
}

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

125
void ScreenManager_run(ScreenManager* this, Panel** lastFocus, int* lastKey) {
Hisham Muhammad's avatar
Hisham Muhammad committed
126
127
128
   bool quit = false;
   int focus = 0;
         
Hisham Muhammad's avatar
Hisham Muhammad committed
129
   Panel* panelFocus = (Panel*) Vector_get(this->items, focus);
Hisham Muhammad's avatar
Hisham Muhammad committed
130
131
132
133
134
135
136
   if (this->fuBar)
      FunctionBar_draw(this->fuBar, NULL);
   
   int ch;
   while (!quit) {
      int items = this->itemCount;
      for (int i = 0; i < items; i++) {
Hisham Muhammad's avatar
Hisham Muhammad committed
137
138
         Panel* panel = (Panel*) Vector_get(this->items, i);
         Panel_draw(panel, i == focus);
Hisham Muhammad's avatar
Hisham Muhammad committed
139
140
         if (i < items) {
            if (this->orientation == HORIZONTAL) {
Hisham Muhammad's avatar
Hisham Muhammad committed
141
               mvvline(panel->y, panel->x+panel->w, ' ', panel->h+1);
Hisham Muhammad's avatar
Hisham Muhammad committed
142
143
144
            }
         }
      }
145
      FunctionBar* bar = (FunctionBar*) Vector_get(this->fuBars, focus);
Hisham Muhammad's avatar
Hisham Muhammad committed
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
      if (bar)
         this->fuBar = bar;
      if (this->fuBar)
         FunctionBar_draw(this->fuBar, NULL);

      ch = getch();
      
      bool loop = false;
      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 {
               for (int i = 0; i < this->itemCount; i++) {
Hisham Muhammad's avatar
Hisham Muhammad committed
162
163
164
                  Panel* panel = (Panel*) Vector_get(this->items, i);
                  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
165
                     focus = i;
Hisham Muhammad's avatar
Hisham Muhammad committed
166
167
                     panelFocus = panel;
                     Panel_setSelected(panel, mevent.y - panel->y + panel->scrollV - 1);
Hisham Muhammad's avatar
Hisham Muhammad committed
168
169
170
171
172
173
174
175
176
                     loop = true;
                     break;
                  }
               }
            }
         }
      }
      if (loop) continue;
      
Hisham Muhammad's avatar
Hisham Muhammad committed
177
178
      if (panelFocus->eventHandler) {
         HandlerResult result = panelFocus->eventHandler(panelFocus, ch);
Hisham Muhammad's avatar
Hisham Muhammad committed
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
         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:
         tryLeft:
         if (focus > 0)
            focus--;
Hisham Muhammad's avatar
Hisham Muhammad committed
199
200
         panelFocus = (Panel*) Vector_get(this->items, focus);
         if (Panel_getSize(panelFocus) == 0 && focus > 0)
Hisham Muhammad's avatar
Hisham Muhammad committed
201
202
203
204
205
206
207
            goto tryLeft;
         break;
      case KEY_RIGHT:
      case 9:
         tryRight:
         if (focus < this->itemCount - 1)
            focus++;
Hisham Muhammad's avatar
Hisham Muhammad committed
208
209
         panelFocus = (Panel*) Vector_get(this->items, focus);
         if (Panel_getSize(panelFocus) == 0 && focus < this->itemCount - 1)
Hisham Muhammad's avatar
Hisham Muhammad committed
210
211
212
213
214
215
216
217
            goto tryRight;
         break;
      case KEY_F(10):
      case 'q':
      case 27:
         quit = true;
         continue;
      default:
Hisham Muhammad's avatar
Hisham Muhammad committed
218
         Panel_onKey(panelFocus, ch);
Hisham Muhammad's avatar
Hisham Muhammad committed
219
220
221
222
         break;
      }
   }

Hisham Muhammad's avatar
Hisham Muhammad committed
223
   *lastFocus = panelFocus;
Hisham Muhammad's avatar
Hisham Muhammad committed
224
225
   *lastKey = ch;
}