ecere/gui/StatusBar: Added option to set minimum info width
[sdk] / ecere / src / gui / controls / StatusBar.ec
1 namespace gui::controls;
2
3 import "Window"
4
5 #include <stdarg.h>
6
7 define defaultMinInfoWidth = 300;
8
9 public class StatusBar : Window
10 {
11    class_property(icon) = "<:ecere>controls/statusBar.png";
12
13    background = formColor;
14    nonClient = true;
15    inactive = true;
16    anchor = Anchor { left = 0, right = 0, bottom = 0 };
17    minInfoWidth = defaultMinInfoWidth;
18
19 public:
20    property int minInfoWidth
21    {
22       set { minInfoWidth = value; }
23       get { return minInfoWidth; }
24    }
25
26    void AddField(StatusField field)
27    {
28       if(this && field)
29       {
30          field._statusBar = this;
31          incref field;
32          width += field.width + (guiApp.textMode ? 0 : 6);
33          fields.Add(field);
34          Update(null);
35       }
36    }
37
38    void RemoveField(StatusField field)
39    {
40       if(this && field)
41       {
42          field._statusBar = null;
43          width -= field.width + (guiApp.textMode ? 0 : 6);
44          fields.Remove(field);
45          delete field;
46
47          Update(null);
48       }
49    }
50
51    void Clear()
52    {
53       if(this)
54       {
55          while(fields.first)
56             RemoveField(fields.first);
57       }
58    }
59
60 private:
61    StatusBar()
62    {
63       fields.offset = (uint)(uintptr)&((StatusField)0).prev;
64    }
65
66    ~StatusBar()
67    {
68       Clear();
69    }
70
71    FontResource boldFont { font.faceName, font.size, true, window = this };
72
73    bool OnLoadGraphics()
74    {
75       StatusField field;
76       width = 0;
77       for(field = fields.first; field; field = field.next)
78          width += field.width + (guiApp.textMode ? 0 : 6);
79       return true;
80    }
81
82    bool OnResizing(int * w, int * h)
83    {
84       *h = Max(*h, statusBarHeight);
85       if(!*w) *w = 80;
86       return true;
87    }
88
89    void OnRedraw(Surface surface)
90    {
91       StatusField field;
92       int position = Max(clientSize.w, minInfoWidth + width)-1-2;
93       Box clip { 2, 2, minInfoWidth, statusBarHeight-1 };
94       Window parent = this.parent;
95
96       if(!guiApp.textMode)
97          surface.ThinBevel(false, -1,0, clientSize.w+2, clientSize.h+1);
98
99       for(field = fields.first; field; field = field.next)
100       {
101          int x = position - field.width;
102
103          surface.SetBackground(white);
104          if(!guiApp.textMode)
105          {
106             surface.ThinBevel(true, x - 2, 2, field.width + 4, statusBarHeight-2);
107             surface.SetForeground(field.colorSet ? field.color : foreground);
108          }
109          else
110          {
111             if(parent.borderStyle == sizable && parent.state == normal)
112                surface.SetForeground(field.colorSet ? (field.color == black ? white : field.color) : (foreground == black ? white : foreground));
113             else
114                surface.SetForeground(field.colorSet ? field.color : foreground);
115          }
116          if(field.text)
117          {
118             Box clip { x, 2, x + field.width - 1, statusBarHeight-3 };
119             int tw;
120             surface.Clip(clip);
121             if(field.backColor)
122             {
123                surface.SetBackground(field.backColor);
124                surface.Clear(colorBuffer);
125             }
126             surface.font = field.bold ? boldFont.font : fontObject;
127             surface.TextExtent(field.text, strlen(field.text), &tw, null);
128             surface.WriteTextf(x + (field.width - tw) / 2, 2, field.text);
129             surface.Clip(null);
130          }
131          position -= field.width + (guiApp.textMode ? 0 : 6);
132       }
133
134       // TESTING THIS HERE!
135       clip.right = position;
136       surface.Clip(clip);
137       if(guiApp.textMode && parent.borderStyle == sizable && parent.state == normal)
138          surface.SetForeground(white);
139       else
140          surface.SetForeground(foreground);
141
142       surface.WriteTextf(2, 2, text);
143       surface.Clip(null);
144    }
145
146    watch(caption)
147    {
148       text = property::text;
149       Update(null);
150    };
151
152    const char * text;
153    OldList fields;
154    int width;
155    int minInfoWidth;
156 };
157
158 public class StatusField
159 {
160 public:
161
162    property StatusBar statusBar
163    {
164       set
165       {
166          if(this)
167          {
168             if(_statusBar)
169                _statusBar.RemoveField(this);
170             if(value)
171                value.AddField(this);
172             _statusBar = value;
173          }
174       }
175    }
176    property Color color
177    {
178       set
179       {
180          if(this)
181          {
182             color = value;
183             colorSet = true;
184             if(_statusBar)
185                _statusBar.Update(null);
186          }
187       }
188    }
189    property ColorAlpha backColor
190    {
191       set
192       {
193          if(this)
194          {
195             backColor = value;
196             colorSet = true;
197             if(_statusBar)
198                _statusBar.Update(null);
199          }
200       }
201    }
202    property bool bold
203    {
204       set
205       {
206          if(this) this.bold = value;
207       }
208    }
209
210    property const char * text
211    {
212       set
213       {
214          if(this)
215          {
216             if(value)
217             {
218                int len = strlen(value);
219                text = renew text char[len + 1];
220                CopyBytes(text, value, len + 1);
221             }
222             else
223                delete text;
224             if(_statusBar)
225                _statusBar.Update(null);
226          }
227       }
228    }
229
230    property int width
231    {
232       set
233       {
234          if(this)
235          {
236             if(_statusBar)
237             {
238                _statusBar.width += value - width;
239                _statusBar.Update(null);
240             }
241             width = value;
242          }
243       }
244    }
245
246    void SetTextf(const char * format, ...)
247    {
248       if(this)
249       {
250          delete text;
251          if(format)
252          {
253             char tempText[MAX_F_STRING];
254             va_list args;
255             va_start(args, format);
256             vsnprintf(tempText, sizeof(tempText), format, args);
257             tempText[sizeof(tempText)-1] = 0;
258             va_end(args);
259             text = CopyString(tempText);
260          }
261          if(_statusBar)
262             _statusBar.Update(null);
263       }
264    }
265
266 private:
267    ~StatusField()
268    {
269       delete text;
270    }
271
272    StatusField prev, next;
273    char * text;
274    int width;
275    Color color;
276    ColorAlpha backColor;
277    StatusBar _statusBar;
278    bool colorSet;
279    bool bold;
280 };