1
2
3
4
5
6 using System;
7 using System.Collections;
8
9 namespace System.Windows
10 {
11 public class StatusBar : Control
12 {
13 private enum Flags : sbyte
14 {
15 none = 0, changed = 1 << 0
16 }
17
18 private const int initialHeight = 20;
19 private const int topLineWidth = 1;
20
21 public StatusBar(const Font& font_, const Color& backgroundColor, const Point& location, const Size& size, Dock dock, Anchors anchors) :
22 base("System.Windows.StatusBar", DefaultWindowClassStyle(), DefaultChildWindowStyle(), DefaultExtendedWindowStyle(),
23 backgroundColor, "statusBar", location, size, dock, anchors), flags(Flags.none), font(font_), stringFormat(), textColor(Color.Black()),
24 textBrush(textColor),
25 topLineColor(215u, 215u, 215u), topLinePen(topLineColor, 1.0f),
26 sunkenBorderOuterTopLeftColor(160u, 160u, 160u), sunkenBorderOuterTopLeftPen(sunkenBorderOuterTopLeftColor, 1.0f),
27 sunkenBorderInnerTopLeftColor(105u, 105u, 105u), sunkenBorderInnerTopLeftPen(sunkenBorderInnerTopLeftColor, 1.0f),
28 sunkenBorderOuterRightBottomColor(Color.White()), sunkenBorderOuterRightBottomPen(sunkenBorderOuterRightBottomColor, 1.0f),
29 sunkenBorderInnerRightBottomColor(227u, 227u, 227u), sunkenBorderInnerRightBottomPen(sunkenBorderInnerRightBottomColor, 1.0f),
30 raisedBorderOuterTopLeftColor(227u, 227u, 227u), raisedBorderOuterTopLeftPen(raisedBorderOuterTopLeftColor, 1.0f),
31 raisedBorderOuterRightBottomColor(105u, 105u, 105u), raisedBorderOuterRightBottomPen(raisedBorderOuterRightBottomColor, 1.0f),
32 raisedBorderInnerTopLeftColor(Color.White()), raisedBorderInnerTopLeftPen(raisedBorderInnerTopLeftColor, 1.0f),
33 raisedBorderInnerRightBottomColor(160u, 160u, 160u), raisedBorderInnerRightBottomPen(raisedBorderInnerRightBottomColor, 1.0f)
34 {
35 SetChanged();
36 }
37 public StatusBar() : this(Font(FontFamily("Segoe UI"), 9.0f), DefaultControlBackgroundColor(), Point(0, 0), Size(0, initialHeight), Dock.bottom, Anchors.none)
38 {
39 }
40 public void AddItem(StatusBarItem* statusBarItem)
41 {
42 statusBarItem->SetStatusBar(this);
43 statusBarItems.Add(UniquePtr<StatusBarItem>(statusBarItem));
44 SetChanged();
45 }
46 public inline nothrow const Color& TextColor() const
47 {
48 return textColor;
49 }
50 public void SetTextColor(const Color& textColor_)
51 {
52 if (textColor != textColor_)
53 {
54 SetChanged();
55 textColor = textColor_;
56 textBrush = SolidBrush(textColor);
57 }
58 }
59 internal inline nothrow const Brush& TextBrush() const
60 {
61 return textBrush;
62 }
63 internal inline nothrow const Font& TextFont() const
64 {
65 return font;
66 }
67 internal inline nothrow const Pen& TopLinePen() const
68 {
69 return topLinePen;
70 }
71 public inline nothrow const Color& TopLineColor() const
72 {
73 return topLineColor;
74 }
75 public void SetTopLineColor(const Color& topLineColor_)
76 {
77 if (topLineColor != topLineColor_)
78 {
79 SetChanged();
80 topLineColor = topLineColor_;
81 topLinePen = Pen(topLineColor, 1.0f);
82 }
83 }
84 public inline nothrow const Color& SunkenBorderOuterTopLeftColor() const
85 {
86 return sunkenBorderOuterTopLeftColor;
87 }
88 public void SetSunkenBorderOuterTopLeftColor(const Color& sunkenBorderOuterTopLeftColor_)
89 {
90 if (sunkenBorderOuterTopLeftColor != sunkenBorderOuterTopLeftColor_)
91 {
92 SetChanged();
93 sunkenBorderOuterTopLeftColor = sunkenBorderOuterTopLeftColor_;
94 sunkenBorderOuterTopLeftPen = Pen(sunkenBorderOuterTopLeftColor, 1.0f);
95 }
96 }
97 internal inline nothrow const Pen& SunkenBorderOuterTopLeftPen() const
98 {
99 return sunkenBorderOuterTopLeftPen;
100 }
101 public inline nothrow const Color& SunkenBorderInnerTopLeftColor() const
102 {
103 return sunkenBorderInnerTopLeftColor;
104 }
105 public void SetSunkenBorderInnerTopLeftColor(const Color& sunkenBorderInnerTopLeftColor_)
106 {
107 if (sunkenBorderInnerTopLeftColor != sunkenBorderInnerTopLeftColor_)
108 {
109 SetChanged();
110 sunkenBorderInnerTopLeftColor = sunkenBorderInnerTopLeftColor_;
111 sunkenBorderInnerTopLeftPen = Pen(sunkenBorderInnerTopLeftColor, 1.0f);
112 }
113 }
114 internal inline nothrow const Pen& SunkenBorderInnerTopLeftPen() const
115 {
116 return sunkenBorderInnerTopLeftPen;
117 }
118 public inline nothrow const Color& SunkenBorderOuterRightBottomColor() const
119 {
120 return sunkenBorderOuterRightBottomColor;
121 }
122 public void SetSunkenBorderOuterRightBottomColor(const Color& sunkenBorderOuterRightBottomColor_)
123 {
124 if (sunkenBorderOuterRightBottomColor != sunkenBorderOuterRightBottomColor_)
125 {
126 SetChanged();
127 sunkenBorderOuterRightBottomColor = sunkenBorderOuterRightBottomColor_;
128 sunkenBorderOuterRightBottomPen = Pen(sunkenBorderOuterRightBottomColor, 1.0f);
129 }
130 }
131 internal inline nothrow const Pen& SunkenBorderOuterRightBottomPen() const
132 {
133 return sunkenBorderOuterRightBottomPen;
134 }
135 public inline nothrow const Color& SunkenBorderInnerRightBottomColor() const
136 {
137 return sunkenBorderInnerRightBottomColor;
138 }
139 public void SetSunkenBorderInnerRightBottomColor(const Color& sunkenBorderInnerRightBottomColor_)
140 {
141 if (sunkenBorderInnerRightBottomColor != sunkenBorderInnerRightBottomColor_)
142 {
143 SetChanged();
144 sunkenBorderInnerRightBottomColor = sunkenBorderInnerRightBottomColor_;
145 sunkenBorderInnerRightBottomPen = Pen(sunkenBorderInnerRightBottomColor, 1.0f);
146 }
147 }
148 internal inline nothrow const Pen& SunkenBorderInnerRightBottomPen() const
149 {
150 return sunkenBorderInnerRightBottomPen;
151 }
152 public inline nothrow const Color& RaisedBorderOuterTopLeftColor() const
153 {
154 return raisedBorderOuterTopLeftColor;
155 }
156 public void SetRaisedBorderOuterTopLeftColor(const Color& raisedBorderOuterTopLeftColor_)
157 {
158 if (raisedBorderOuterTopLeftColor != raisedBorderOuterTopLeftColor_)
159 {
160 SetChanged();
161 raisedBorderOuterTopLeftColor = raisedBorderOuterTopLeftColor_;
162 raisedBorderOuterTopLeftPen = Pen(raisedBorderOuterTopLeftColor, 1.0f);
163 }
164 }
165 internal inline nothrow const Pen& RaisedBorderOuterTopLeftPen() const
166 {
167 return raisedBorderOuterTopLeftPen;
168 }
169 public inline nothrow const Color& RaisedBorderOuterRightBottomColor() const
170 {
171 return raisedBorderOuterRightBottomColor;
172 }
173 public void SetRaisedBorderRightBottomColor(const Color& raisedBorderOuterRightBottomColor_)
174 {
175 if (raisedBorderOuterRightBottomColor != raisedBorderOuterRightBottomColor_)
176 {
177 SetChanged();
178 raisedBorderOuterRightBottomColor = raisedBorderOuterRightBottomColor_;
179 raisedBorderOuterRightBottomPen = Pen(raisedBorderOuterRightBottomColor, 1.0f);
180 }
181 }
182 internal inline nothrow const Pen& RaisedBorderOuterRightBottomPen() const
183 {
184 return raisedBorderOuterRightBottomPen;
185 }
186 public inline nothrow const Color& RaisedBorderInnerTopLeftColor() const
187 {
188 return raisedBorderInnerTopLeftColor;
189 }
190 public void SetRaisedBorderInnerTopLeftColor(const Color& raisedBorderInnerTopLeftColor_)
191 {
192 if (raisedBorderInnerTopLeftColor != raisedBorderInnerTopLeftColor_)
193 {
194 SetChanged();
195 raisedBorderInnerTopLeftColor = raisedBorderInnerTopLeftColor_;
196 raisedBorderInnerTopLeftPen = Pen(raisedBorderInnerTopLeftColor, 1.0f);
197 }
198 }
199 internal inline nothrow const Pen& RaisedBorderInnerTopLeftPen() const
200 {
201 return raisedBorderInnerTopLeftPen;
202 }
203
204 public inline nothrow const Color& RaisedBorderInnerRightBottomColor() const
205 {
206 return raisedBorderInnerRightBottomColor;
207 }
208 public void SetRaisedBorderInnerRightBottomColor(const Color& raisedBorderInnerRightBottomColor_)
209 {
210 if (raisedBorderInnerRightBottomColor != raisedBorderInnerRightBottomColor_)
211 {
212 SetChanged();
213 raisedBorderInnerRightBottomColor = raisedBorderInnerRightBottomColor_;
214 raisedBorderInnerRightBottomPen = Pen(raisedBorderInnerRightBottomColor, 1.0f);
215 }
216 }
217 internal inline nothrow const Pen& RaisedBorderInnerRightBottomPen() const
218 {
219 return raisedBorderInnerRightBottomPen;
220 }
221 protected override nothrow Padding DefaultPadding() const
222 {
223 return Padding(4, 4, 4, 4);
224 }
225 protected override void OnPaint(PaintEventArgs& args)
226 {
227 if (Changed())
228 {
229 ResetChanged();
230 Measure(args.graphics);
231 }
232 args.graphics.Clear(BackgroundColor());
233 DrawTopLine(args.graphics);
234 DrawItems(args.graphics);
235 base->OnPaint(args);
236 }
237 private void DrawTopLine(Graphics& graphics)
238 {
239 Size size = GetSize();
240 Point start(0, 0);
241 Point end(size.w - 1, 0);
242 graphics.DrawLineChecked(topLinePen, start, end);
243 }
244 private void DrawItems(Graphics& graphics)
245 {
246 long n = statusBarItems.Count();
247 for (long i = 0; i < n; ++i;)
248 {
249 StatusBarItem* item = statusBarItems[i].Get();
250 item->Draw(graphics);
251 }
252 }
253 private void Measure(Graphics& graphics)
254 {
255 LogView* logView = Application.GetLogView();
256 Padding padding = DefaultPadding();
257 int statusBarItemBorderWidth = StatusBarItem.BorderWidth();
258 int statusBarItemHorizontalPadding = StatusBarItem.HorizontalPadding();
259 int textHeight = 0;
260 long n = statusBarItems.Count();
261 for (long i = 0; i < n; ++i;)
262 {
263 StatusBarItem* item = statusBarItems[i].Get();
264 string s = item->Text();
265 ustring u(ToUtf32(s));
266 string z('0', u.Length());
267 RectF rect = graphics.MeasureStringChecked(z, font, PointF(0, 0), stringFormat);
268 textHeight = Max(textHeight, cast<int>(rect.size.h));
269 item->SetTextWidth(cast<int>(rect.size.w));
270 }
271 if (textHeight != 0)
272 {
273 int height = topLineWidth + padding.Vertical() + 2 * statusBarItemBorderWidth + textHeight;
274 Size size = GetSize();
275 size.h = height;
276 SetSize(size);
277 DockWindow();
278 Point leftOrigin(padding.left, topLineWidth + padding.top);
279 long springIndex = -1;
280 for (long i = 0; i < n; ++i;)
281 {
282 StatusBarItem* item = statusBarItems[i].Get();
283 if (item->Spring())
284 {
285 springIndex = i;
286 break;
287 }
288 item->SetLocation(leftOrigin);
289 item->SetSize(Size(2 * statusBarItemBorderWidth + statusBarItemHorizontalPadding + item->TextWidth(), 2 * statusBarItemBorderWidth + textHeight));
290 leftOrigin.x = leftOrigin.x + item->GetSize().w;
291 }
292 Point rightOrigin(size.w - 1 - padding.right, topLineWidth + padding.top);
293 if (springIndex != -1)
294 {
295 for (long i = n - 1; i > springIndex; --i;)
296 {
297 StatusBarItem* item = statusBarItems[i].Get();
298 if (item->Spring())
299 {
300 break;
301 }
302 item->SetSize(Size(2 * statusBarItemBorderWidth + statusBarItemHorizontalPadding + item->TextWidth(), 2 * statusBarItemBorderWidth + textHeight));
303 rightOrigin.x = rightOrigin.x - item->GetSize().w;
304 item->SetLocation(rightOrigin);
305 }
306 StatusBarItem* springItem = statusBarItems[springIndex].Get();
307 springItem->SetLocation(leftOrigin);
308 springItem->SetSize(Size(rightOrigin.x - leftOrigin.x + 1, 2 * statusBarItemBorderWidth + textHeight));
309 }
310 }
311 }
312 private inline nothrow bool Changed() const
313 {
314 return (flags & Flags.changed) != Flags.none;
315 }
316 internal inline nothrow void SetChanged()
317 {
318 flags = cast<Flags>(flags | Flags.changed);
319 }
320 private inline nothrow void ResetChanged()
321 {
322 flags = cast<Flags>(flags & ~Flags.changed);
323 }
324 private Flags flags;
325 private Font font;
326 private StringFormat stringFormat;
327 private List<UniquePtr<StatusBarItem>> statusBarItems;
328 private Color textColor;
329 private SolidBrush textBrush;
330 private Color topLineColor;
331 private Pen topLinePen;
332 private Color sunkenBorderOuterTopLeftColor;
333 private Pen sunkenBorderOuterTopLeftPen;
334 private Color sunkenBorderInnerTopLeftColor;
335 private Pen sunkenBorderInnerTopLeftPen;
336 private Color sunkenBorderOuterRightBottomColor;
337 private Pen sunkenBorderOuterRightBottomPen;
338 private Color sunkenBorderInnerRightBottomColor;
339 private Pen sunkenBorderInnerRightBottomPen;
340 private Color raisedBorderOuterTopLeftColor;
341 private Pen raisedBorderOuterTopLeftPen;
342 private Color raisedBorderOuterRightBottomColor;
343 private Pen raisedBorderOuterRightBottomPen;
344 private Color raisedBorderInnerTopLeftColor;
345 private Pen raisedBorderInnerTopLeftPen;
346 private Color raisedBorderInnerRightBottomColor;
347 private Pen raisedBorderInnerRightBottomPen;
348 }
349
350 public class StatusBarItem
351 {
352 public enum BorderStyle : sbyte
353 {
354 flat, sunken, raised
355 }
356 public static nothrow int BorderWidth()
357 {
358 return 2;
359 }
360 public static nothrow int HorizontalPadding()
361 {
362 return 4;
363 }
364 public nothrow StatusBarItem(const string& text_, BorderStyle borderStyle_, bool spring_) : statusBar(null), text(text_), borderStyle(borderStyle_), spring(spring_)
365 {
366 }
367 public nothrow StatusBarItem(const string& text, BorderStyle borderStyle) : this(text, borderStyle, false)
368 {
369 }
370 public nothrow StatusBarItem(const string& text) : this(text, BorderStyle.flat)
371 {
372 }
373 public nothrow StatusBarItem() : this(string())
374 {
375 }
376 public nothrow const Point& Location() const
377 {
378 return location;
379 }
380 public nothrow void SetLocation(const Point& location_)
381 {
382 location = location_;
383 }
384 public nothrow const Size& GetSize() const
385 {
386 return size;
387 }
388 public nothrow void SetSize(const Size& size_)
389 {
390 size = size_;
391 }
392 public inline nothrow const string& Text() const
393 {
394 return text;
395 }
396 public void SetText(const string& text_)
397 {
398 if (text != text_)
399 {
400 text = text_;
401 Invalidate();
402 }
403 }
404 public inline nothrow int TextWidth() const
405 {
406 return textWidth;
407 }
408 public inline nothrow void SetTextWidth(int textWidth_)
409 {
410 textWidth = textWidth_;
411 }
412 public inline nothrow BorderStyle GetBorderStyle() const
413 {
414 return borderStyle;
415 }
416 public void SetBorderStyle(BorderStyle borderStyle_)
417 {
418 if (borderStyle != borderStyle_)
419 {
420 borderStyle = borderStyle_;
421 Invalidate();
422 }
423 }
424 public inline nothrow bool Spring() const
425 {
426 return spring;
427 }
428 public void SetSpring(bool spring_)
429 {
430 if (spring != spring_)
431 {
432 spring = spring_;
433 Invalidate();
434 }
435 }
436 public virtual default ~StatusBarItem();
437 public void Draw(Graphics& graphics)
438 {
439 DrawBorder(graphics);
440 DrawText(graphics);
441 }
442 private void DrawText(Graphics& graphics)
443 {
444 const Brush& brush = statusBar->TextBrush();
445 const Font& font = statusBar->TextFont();
446 PointF origin(location.x + 2 + HorizontalPadding() / 2, location.y + 2);
447 graphics.DrawStringChecked(text, font, origin, brush);
448 }
449 private void DrawBorder(Graphics& graphics)
450 {
451 switch (borderStyle)
452 {
453 case BorderStyle.sunken:
454 {
455 DrawSunkenBorder(graphics);
456 break;
457 }
458 case BorderStyle.raised:
459 {
460 DrawRaisedBorder(graphics);
461 break;
462 }
463 }
464 }
465 private void DrawSunkenBorder(Graphics& graphics)
466 {
467 const Pen& outerTopLeftPen = statusBar->SunkenBorderOuterTopLeftPen();
468 graphics.DrawLineChecked(outerTopLeftPen, location, Point(location.x + size.w - 2, location.y));
469 graphics.DrawLineChecked(outerTopLeftPen, location, Point(location.x, location.y + size.h - 2));
470 const Pen& outerRightBottomPen = statusBar->SunkenBorderOuterRightBottomPen();
471 graphics.DrawLineChecked(outerRightBottomPen, Point(location.x + size.w - 1, location.y), Point(location.x + size.w - 1, location.y + size.h - 1));
472 graphics.DrawLineChecked(outerRightBottomPen, Point(location.x, location.y + size.h - 1), Point(location.x + size.w - 1, location.y + size.h - 1));
473 const Pen& innerTopLeftPen = statusBar->SunkenBorderInnerTopLeftPen();
474 graphics.DrawLineChecked(innerTopLeftPen, Point(location.x + 1, location.y + 1), Point(location.x + size.w - 3, location.y + 1));
475 graphics.DrawLineChecked(innerTopLeftPen, Point(location.x + 1, location.y + 1), Point(location.x + 1, location.y + size.h - 3));
476 const Pen& innerRightBottomPen = statusBar->SunkenBorderInnerRightBottomPen();
477 graphics.DrawLineChecked(innerRightBottomPen, Point(location.x + size.w - 2, location.y + 1), Point(location.x + size.w - 2, location.y + size.h - 2));
478 graphics.DrawLineChecked(innerRightBottomPen, Point(location.x + 1, location.y + size.h - 2), Point(location.x + size.w - 2, location.y + size.h - 2));
479 }
480 private void DrawRaisedBorder(Graphics& graphics)
481 {
482 const Pen& outerTopLeftPen = statusBar->RaisedBorderOuterTopLeftPen();
483 graphics.DrawLineChecked(outerTopLeftPen, location, Point(location.x + size.w - 2, location.y));
484 graphics.DrawLineChecked(outerTopLeftPen, location, Point(location.x, location.y + size.h - 2));
485 const Pen& outerRightBottomPen = statusBar->RaisedBorderOuterRightBottomPen();
486 graphics.DrawLineChecked(outerRightBottomPen, Point(location.x + size.w - 1, location.y), Point(location.x + size.w - 1, location.y + size.h - 1));
487 graphics.DrawLineChecked(outerRightBottomPen, Point(location.x, location.y + size.h - 1), Point(location.x + size.w - 1, location.y + size.h - 1));
488 const Pen& innerTopLeftPen = statusBar->RaisedBorderInnerTopLeftPen();
489 graphics.DrawLineChecked(innerTopLeftPen, Point(location.x + 1, location.y + 1), Point(location.x + size.w - 3, location.y + 1));
490 graphics.DrawLineChecked(innerTopLeftPen, Point(location.x + 1, location.y + 1), Point(location.x + 1, location.y + size.h - 3));
491 const Pen& innerRightBottomPen = statusBar->RaisedBorderInnerRightBottomPen();
492 graphics.DrawLineChecked(innerRightBottomPen, Point(location.x + size.w - 2, location.y + 1), Point(location.x + size.w - 2, location.y + size.h - 2));
493 graphics.DrawLineChecked(innerRightBottomPen, Point(location.x + 1, location.y + size.h - 2), Point(location.x + size.w - 2, location.y + size.h - 2));
494 }
495 internal nothrow void SetStatusBar(StatusBar* statusBar_)
496 {
497 statusBar = statusBar_;
498 }
499 public void Invalidate()
500 {
501 if (statusBar != null)
502 {
503 statusBar->SetChanged();
504 statusBar->Invalidate();
505 }
506 }
507 private StatusBar* statusBar;
508 private Point location;
509 private Size size;
510 private int textWidth;
511 private string text;
512 private BorderStyle borderStyle;
513 private bool spring;
514 }
515 }