Mercurial > hg > ucis.core
annotate FBGUI.cs @ 27:5bfc6c68591e
FBGUI: Added numeric up/down control, fix for transparent control background
author | Ivo Smits <Ivo@UCIS.nl> |
---|---|
date | Tue, 16 Apr 2013 01:16:45 +0200 |
parents | 7f0b7a53a000 |
children |
rev | line source |
---|---|
23 | 1 ???using System; |
2 using System.Collections.Generic; | |
3 using System.Drawing; | |
4 using System.Drawing.Drawing2D; | |
5 using System.Drawing.Imaging; | |
6 using System.IO; | |
7 using System.Threading; | |
8 using System.Windows.Forms; | |
9 using UCIS.VNCServer; | |
10 using ThreadingTimer = System.Threading.Timer; | |
11 | |
12 namespace UCIS.FBGUI { | |
13 public interface IFBGControl { | |
14 Rectangle Bounds { get; set; } | |
15 Boolean Visible { get; set; } | |
16 void Paint(Graphics g); | |
17 void MouseMove(Point position, MouseButtons buttons); | |
18 void MouseDown(Point position, MouseButtons buttons); | |
19 void MouseUp(Point position, MouseButtons buttons); | |
20 void KeyDown(Keys key); | |
21 void KeyPress(Char keyChar); | |
22 void KeyUp(Keys key); | |
23 void LostKeyboardCapture(); | |
24 void Orphaned(); | |
25 } | |
26 public interface IFBGContainerControl { | |
27 Size Size { get; } //Todo: really necessary? Probably not. | |
28 void Invalidate(IFBGControl control, Rectangle rect); | |
29 void AddControl(IFBGControl control); | |
30 void RemoveControl(IFBGControl control); | |
31 Boolean CaptureMouse(IFBGControl control, Boolean capture); | |
32 Boolean CaptureKeyboard(IFBGControl control, Boolean capture); | |
33 } | |
34 public class FBGControl : IFBGControl { | |
35 private Rectangle bounds = new Rectangle(0, 0, 100, 100); | |
36 private Color backColor = Color.Transparent; | |
37 private Boolean visible = true; | |
38 public virtual IFBGContainerControl Parent { get; private set; } | |
39 public event MouseEventHandler OnMouseDown; | |
40 public event MouseEventHandler OnMouseMove; | |
41 public event MouseEventHandler OnMouseUp; | |
42 public event PaintEventHandler OnPaint; | |
43 public event EventHandler OnResize; | |
44 public event EventHandler OnMove; | |
45 public FBGControl(IFBGContainerControl parent) { | |
46 this.Parent = parent; | |
47 if (Parent != null) Parent.AddControl(this); | |
48 } | |
49 public virtual Rectangle Bounds { | |
50 get { return bounds; } | |
51 set { | |
52 if (bounds == value) return; | |
53 Rectangle old = bounds; | |
54 bounds = value; | |
55 Parent.Invalidate(this, Rectangle.Union(new Rectangle(Point.Empty, value.Size), new Rectangle(old.X - value.X, old.Y - value.Y, old.Width, old.Height))); | |
56 if (value.Location != old.Location) RaiseEvent(OnMove); | |
57 if (value.Size != old.Size) RaiseEvent(OnResize); | |
58 } | |
59 } | |
60 public virtual Boolean Visible { | |
61 get { return visible; } | |
62 set { | |
63 visible = value; | |
64 Invalidate(); | |
65 } | |
66 } | |
67 public Size Size { get { return Bounds.Size; } set { Rectangle r = Bounds; r.Size = value; Bounds = r; } } | |
68 public Point Location { get { return Bounds.Location; } set { Rectangle r = Bounds; r.Location = value; Bounds = r; } } | |
69 public int Left { get { return Bounds.Left; } set { Rectangle r = Bounds; r.X = value; Bounds = r; } } | |
70 public int Top { get { return Bounds.Top; } set { Rectangle r = Bounds; r.Y = value; Bounds = r; } } | |
71 public int Width { get { return Bounds.Width; } set { Rectangle r = Bounds; r.Width = value; Bounds = r; } } | |
72 public int Height { get { return Bounds.Height; } set { Rectangle r = Bounds; r.Height = value; Bounds = r; } } | |
73 public virtual Color BackColor { get { return backColor; } set { if (backColor == value) return; backColor = value; Invalidate(); } } | |
74 public virtual void Invalidate() { | |
75 Invalidate(new Rectangle(Point.Empty, Bounds.Size)); | |
76 } | |
77 public virtual void Invalidate(Rectangle rect) { | |
78 Parent.Invalidate(this, rect); | |
79 } | |
80 void IFBGControl.Paint(Graphics g) { Paint(g); } | |
81 void IFBGControl.MouseMove(Point position, MouseButtons buttons) { MouseMove(position, buttons); } | |
82 void IFBGControl.MouseDown(Point position, MouseButtons buttons) { MouseDown(position, buttons); } | |
83 void IFBGControl.MouseUp(Point position, MouseButtons buttons) { MouseUp(position, buttons); } | |
84 void IFBGControl.KeyDown(Keys g) { KeyDown(g); } | |
85 void IFBGControl.KeyPress(Char g) { KeyPress(g); } | |
86 void IFBGControl.KeyUp(Keys g) { KeyUp(g); } | |
87 void IFBGControl.LostKeyboardCapture() { LostKeyboardCapture(); } | |
88 void IFBGControl.Orphaned() { Orphaned(); } | |
89 protected virtual void Paint(Graphics g) { | |
90 if (!visible) return; | |
27
5bfc6c68591e
FBGUI: Added numeric up/down control, fix for transparent control background
Ivo Smits <Ivo@UCIS.nl>
parents:
26
diff
changeset
|
91 if (backColor.A == 0xff) g.Clear(backColor); |
5bfc6c68591e
FBGUI: Added numeric up/down control, fix for transparent control background
Ivo Smits <Ivo@UCIS.nl>
parents:
26
diff
changeset
|
92 else if (backColor.A != 0) using (Brush brush = new SolidBrush(backColor)) g.FillRectangle(brush, g.ClipBounds); |
23 | 93 RaiseEvent(OnPaint, new PaintEventArgs(g, Rectangle.Round(g.ClipBounds))); |
94 } | |
95 protected virtual void MouseMove(Point position, MouseButtons buttons) { RaiseEvent(OnMouseMove, new MouseEventArgs(buttons, 0, position.X, position.Y, 0)); } | |
96 protected virtual void MouseDown(Point position, MouseButtons buttons) { RaiseEvent(OnMouseDown, new MouseEventArgs(buttons, 1, position.X, position.Y, 0)); } | |
97 protected virtual void MouseUp(Point position, MouseButtons buttons) { RaiseEvent(OnMouseUp, new MouseEventArgs(buttons, 1, position.X, position.Y, 0)); } | |
98 protected virtual Boolean CaptureMouse(Boolean capture) { | |
99 return Parent.CaptureMouse(this, capture); | |
100 } | |
101 protected virtual void KeyDown(Keys key) { } | |
102 protected virtual void KeyPress(Char keyChar) { } | |
103 protected virtual void KeyUp(Keys key) { } | |
104 protected virtual Boolean CaptureKeyboard(Boolean capture) { | |
105 return Parent.CaptureKeyboard(this, capture); | |
106 } | |
107 protected virtual void LostKeyboardCapture() { } | |
108 protected virtual void Orphaned() { | |
109 //IDisposable disp = this as IDisposable; | |
110 //if (!ReferenceEquals(disp, null)) disp.Dispose(); | |
111 } | |
112 protected void RaiseEvent(KeyEventHandler eh, KeyEventArgs ea) { if (eh != null) eh(this, ea); } | |
113 protected void RaiseEvent(KeyPressEventHandler eh, KeyPressEventArgs ea) { if (eh != null) eh(this, ea); } | |
114 protected void RaiseEvent(MouseEventHandler eh, MouseEventArgs ea) { if (eh != null) eh(this, ea); } | |
115 protected void RaiseEvent(PaintEventHandler eh, PaintEventArgs ea) { if (eh != null) eh(this, ea); } | |
116 protected void RaiseEvent<T>(EventHandler<T> eh, T ea) where T : EventArgs { if (eh != null) eh(this, ea); } | |
117 protected void RaiseEvent(EventHandler eh, EventArgs ea) { if (eh != null) eh(this, ea); } | |
118 protected void RaiseEvent(EventHandler eh) { if (eh != null) eh(this, new EventArgs()); } | |
119 } | |
120 public class FBGContainerControl : FBGControl, IFBGContainerControl { | |
121 protected List<IFBGControl> controls = new List<IFBGControl>(); | |
26
7f0b7a53a000
FBGUI: Allow derived classes to access some internals
Ivo Smits <Ivo@UCIS.nl>
parents:
23
diff
changeset
|
122 protected IFBGControl mouseCaptureControl = null; |
7f0b7a53a000
FBGUI: Allow derived classes to access some internals
Ivo Smits <Ivo@UCIS.nl>
parents:
23
diff
changeset
|
123 protected IFBGControl keyboardCaptureControl = null; |
23 | 124 private Rectangle childarea = Rectangle.Empty; |
125 public Rectangle ClientRectangle { get { return childarea; } protected set { childarea = value; Invalidate(); } } | |
126 public FBGContainerControl(IFBGContainerControl parent) : base(parent) { } | |
127 Size IFBGContainerControl.Size { get { return childarea.IsEmpty ? Bounds.Size : childarea.Size; } } | |
128 void IFBGContainerControl.AddControl(IFBGControl control) { AddControl(control); } | |
129 protected virtual void AddControl(IFBGControl control) { | |
130 controls.Add(control); | |
131 if (control.Visible) Invalidate(control); | |
132 } | |
133 public virtual void RemoveControl(IFBGControl control) { | |
134 if (controls.Remove(control)) { | |
135 if (control.Visible) Invalidate(control); | |
136 CaptureMouse(control, false); | |
137 CaptureKeyboard(control, false); | |
138 control.Orphaned(); | |
139 } | |
140 } | |
141 public virtual Point PointToChild(IFBGControl child, Point point) { | |
142 return point - (Size)child.Bounds.Location - (Size)ClientRectangle.Location; | |
143 } | |
144 public virtual Point PointFromChild(IFBGControl child, Point point) { | |
145 return point + (Size)child.Bounds.Location + (Size)ClientRectangle.Location; | |
146 } | |
147 public virtual void BringControlToFront(IFBGControl control) { | |
148 if (controls.Count == 0) return; | |
149 if (ReferenceEquals(controls[controls.Count - 1], control)) return; | |
150 if (!controls.Remove(control)) return; | |
151 controls.Add(control); | |
152 if (control.Visible) Invalidate(control); | |
153 } | |
154 public virtual void Invalidate(IFBGControl control) { | |
155 Invalidate(new Rectangle(PointFromChild(control, Point.Empty), control.Bounds.Size)); | |
156 } | |
157 public virtual void Invalidate(IFBGControl control, Rectangle rect) { | |
158 Invalidate(new Rectangle(PointFromChild(control, rect.Location), rect.Size)); | |
159 } | |
160 protected override void Paint(Graphics g) { | |
161 base.Paint(g); | |
162 if (controls == null) return; | |
163 GraphicsState state2 = null; | |
164 if (!childarea.IsEmpty) { | |
165 state2 = g.Save(); | |
166 g.TranslateTransform(childarea.X, childarea.Y, MatrixOrder.Append); | |
167 g.IntersectClip(new Rectangle(Point.Empty, childarea.Size)); | |
168 } | |
169 foreach (IFBGControl control in controls) { | |
170 if (!control.Visible) continue; | |
171 if (control.Bounds.Width <= 0 || control.Bounds.Height <= 0) continue; | |
172 if (!g.ClipBounds.IntersectsWith((RectangleF)control.Bounds)) continue; | |
173 GraphicsState state = g.Save(); | |
174 g.TranslateTransform(control.Bounds.X, control.Bounds.Y, MatrixOrder.Append); | |
175 g.IntersectClip(new Rectangle(Point.Empty, control.Bounds.Size)); | |
176 control.Paint(g); | |
177 g.Restore(state); | |
178 } | |
179 if (state2 != null) g.Restore(state2); | |
180 } | |
181 public IFBGControl FindControlAtPosition(Point p) { | |
182 if (!childarea.IsEmpty && !childarea.Contains(p)) return null; | |
183 p.Offset(-childarea.X, -childarea.Y); | |
184 return ((List<IFBGControl>)controls).FindLast(delegate(IFBGControl control) { return control.Visible && control.Bounds.Contains(p); }); | |
185 } | |
186 protected override void MouseMove(Point position, MouseButtons buttons) { | |
187 IFBGControl control = mouseCaptureControl != null ? mouseCaptureControl : FindControlAtPosition(position); | |
188 if (control == null) { | |
189 base.MouseMove(position, buttons); | |
190 } else { | |
191 control.MouseMove(PointToChild(control, position), buttons); | |
192 } | |
193 } | |
194 protected override void MouseDown(Point position, MouseButtons buttons) { | |
195 IFBGControl control = mouseCaptureControl != null ? mouseCaptureControl : FindControlAtPosition(position); | |
196 if (control == null) { | |
197 base.MouseDown(position, buttons); | |
198 } else { | |
199 control.MouseDown(PointToChild(control, position), buttons); | |
200 } | |
201 } | |
202 protected override void MouseUp(Point position, MouseButtons buttons) { | |
203 IFBGControl control = mouseCaptureControl != null ? mouseCaptureControl : FindControlAtPosition(position); | |
204 if (control == null) { | |
205 base.MouseUp(position, buttons); | |
206 } else { | |
207 control.MouseUp(PointToChild(control, position), buttons); | |
208 } | |
209 } | |
210 Boolean IFBGContainerControl.CaptureMouse(IFBGControl control, Boolean capture) { return CaptureMouse(control, capture); } | |
211 protected Boolean CaptureMouse(IFBGControl control, Boolean capture) { | |
212 if (capture && !ReferenceEquals(mouseCaptureControl, null)) return false; | |
213 if (!capture && !ReferenceEquals(mouseCaptureControl, control)) return false; | |
214 if (!CaptureMouse(capture)) return false; | |
215 mouseCaptureControl = capture ? control : null; | |
216 return true; | |
217 } | |
218 protected override void KeyDown(Keys key) { | |
219 if (ReferenceEquals(keyboardCaptureControl, null)) base.KeyDown(key); | |
220 else keyboardCaptureControl.KeyDown(key); | |
221 } | |
222 protected override void KeyPress(Char keyChar) { | |
223 if (ReferenceEquals(keyboardCaptureControl, null)) base.KeyPress(keyChar); | |
224 else keyboardCaptureControl.KeyPress(keyChar); | |
225 } | |
226 protected override void KeyUp(Keys key) { | |
227 if (ReferenceEquals(keyboardCaptureControl, null)) base.KeyUp(key); | |
228 else keyboardCaptureControl.KeyUp(key); | |
229 } | |
230 Boolean IFBGContainerControl.CaptureKeyboard(IFBGControl control, Boolean capture) { return CaptureKeyboard(control, capture); } | |
231 protected Boolean CaptureKeyboard(IFBGControl control, Boolean capture) { | |
232 if (!capture && !ReferenceEquals(keyboardCaptureControl, control)) return false; | |
233 if (!CaptureKeyboard(capture)) return false; | |
234 IFBGControl prev = keyboardCaptureControl; | |
235 keyboardCaptureControl = capture ? control : null; | |
236 if (prev != null) LostKeyboardCapture(); | |
237 return true; | |
238 } | |
239 protected override void LostKeyboardCapture() { | |
240 base.LostKeyboardCapture(); | |
241 if (keyboardCaptureControl != null) keyboardCaptureControl.LostKeyboardCapture(); | |
242 } | |
243 protected override void Orphaned() { | |
244 base.Orphaned(); | |
245 IFBGControl[] c = controls.ToArray(); | |
246 controls.Clear(); | |
247 foreach (IFBGControl control in c) control.Orphaned(); | |
248 mouseCaptureControl = null; | |
249 keyboardCaptureControl = null; | |
250 } | |
251 } | |
252 public class FBGDockContainer : FBGContainerControl { | |
253 private Dictionary<IFBGControl, DockStyle> dockStyles = new Dictionary<IFBGControl, DockStyle>(); | |
254 private Dictionary<IFBGControl, AnchorStyles> anchorStyles = new Dictionary<IFBGControl, AnchorStyles>(); | |
255 private Rectangle oldBounds; | |
256 public FBGDockContainer(IFBGContainerControl parent) | |
257 : base(parent) { | |
258 oldBounds = ClientRectangle.IsEmpty ? Bounds : new Rectangle(Bounds.Location + (Size)ClientRectangle.Location, ClientRectangle.Size); | |
259 } | |
260 protected override void AddControl(IFBGControl control) { | |
261 base.AddControl(control); | |
262 } | |
263 public override void BringControlToFront(IFBGControl control) { | |
264 base.BringControlToFront(control); | |
265 if (dockStyles.ContainsKey(control)) DoLayout(); | |
266 } | |
267 public override void RemoveControl(IFBGControl control) { | |
268 base.RemoveControl(control); | |
269 if (dockStyles.Remove(control)) DoLayout(); | |
270 } | |
271 public override Rectangle Bounds { | |
272 get { return base.Bounds; } | |
273 set { | |
274 base.Bounds = value; | |
275 DoLayout(); | |
276 Rectangle newBounds = ClientRectangle.IsEmpty ? Bounds : new Rectangle(Bounds.Location + (Size)ClientRectangle.Location, ClientRectangle.Size); | |
277 foreach (KeyValuePair<IFBGControl, AnchorStyles> c in anchorStyles) { | |
278 Rectangle b = c.Key.Bounds; | |
279 if ((c.Value & AnchorStyles.Right) != 0) { | |
280 if ((c.Value & AnchorStyles.Left) == 0) b.X += newBounds.Width - oldBounds.Width; | |
281 else b.Width += newBounds.Width - oldBounds.Width; | |
282 } else if ((c.Value & AnchorStyles.Left) == 0) b.X += newBounds.X - oldBounds.X; | |
283 if ((c.Value & AnchorStyles.Bottom) != 0) { | |
284 if ((c.Value & AnchorStyles.Top) == 0) b.Y += newBounds.Height - oldBounds.Height; | |
285 else b.Height += newBounds.Height - oldBounds.Height; | |
286 } else if ((c.Value & AnchorStyles.Top) == 0) b.Y += newBounds.Y - oldBounds.Y; | |
287 c.Key.Bounds = b; | |
288 } | |
289 oldBounds = newBounds; | |
290 } | |
291 } | |
292 public DockStyle GetDockStyle(IFBGControl control) { | |
293 DockStyle ds; | |
294 if (!dockStyles.TryGetValue(control, out ds)) ds = DockStyle.None; | |
295 return ds; | |
296 } | |
297 public void SetDockStyle(IFBGControl control, DockStyle style) { | |
298 if (style == DockStyle.None) { | |
299 if (dockStyles.Remove(control)) DoLayout(); | |
300 } else if (controls.Contains(control)) { | |
301 anchorStyles.Remove(control); | |
302 dockStyles[control] = style; | |
303 DoLayout(); | |
304 } | |
305 } | |
306 public AnchorStyles GetAnchorStyle(IFBGControl control) { | |
307 AnchorStyles ds; | |
308 if (!anchorStyles.TryGetValue(control, out ds)) ds = AnchorStyles.Left | AnchorStyles.Top; | |
309 return ds; | |
310 } | |
311 public void SetAnchorStyle(IFBGControl control, AnchorStyles style) { | |
312 if (style == (AnchorStyles.Left | AnchorStyles.Top)) { | |
313 anchorStyles.Remove(control); | |
314 } else if (controls.Contains(control)) { | |
315 dockStyles.Remove(control); | |
316 anchorStyles[control] = style; | |
317 } | |
318 } | |
319 public void SetAnchor(IFBGControl control, AnchorStyles style, int value) { | |
320 if (controls.Contains(control)) { | |
321 AnchorStyles oldstyle; | |
322 if (!anchorStyles.TryGetValue(control, out oldstyle)) oldstyle = AnchorStyles.Left | AnchorStyles.Top; | |
323 Rectangle b = control.Bounds; | |
324 switch (style) { | |
325 case AnchorStyles.None: throw new ArgumentException("style", "Anchor style can not be None"); | |
326 case AnchorStyles.Left: b.X = value; break; | |
327 case AnchorStyles.Top: b.Y = value; break; | |
328 case AnchorStyles.Right: | |
329 if ((oldstyle & AnchorStyles.Left) == 0) b.X = ClientRectangle.Width - b.Width - value; | |
330 else b.Width = ClientRectangle.Width - b.X - value; | |
331 break; | |
332 case AnchorStyles.Bottom: | |
333 if ((oldstyle & AnchorStyles.Top) == 0) b.Y = ClientRectangle.Height - b.Height - value; | |
334 else b.Height = ClientRectangle.Height - b.Y - value; | |
335 break; | |
336 default: throw new ArgumentOutOfRangeException("style", "The value vor the style argument is invalid"); | |
337 } | |
338 control.Bounds = b; | |
339 dockStyles.Remove(control); | |
340 anchorStyles[control] = oldstyle | style; | |
341 } | |
342 } | |
343 private void DoLayout() { | |
344 Rectangle a = new Rectangle(Point.Empty, ClientRectangle.IsEmpty ? Bounds.Size : ClientRectangle.Size); | |
345 foreach (KeyValuePair<IFBGControl, DockStyle> c in dockStyles) { | |
346 Rectangle b = c.Key.Bounds; | |
347 if (c.Value == DockStyle.Left) { | |
348 b.Location = a.Location; | |
349 b.Height = a.Height; | |
350 a.X += b.Width; | |
351 a.Width -= b.Width; | |
352 } else if (c.Value == DockStyle.Top) { | |
353 b.Location = a.Location; | |
354 b.Width = a.Width; | |
355 a.Y += b.Height; | |
356 a.Height -= b.Height; | |
357 } else if (c.Value == DockStyle.Right) { | |
358 b.X = a.X + a.Width - b.Width; | |
359 b.Y = a.Y; | |
360 b.Height = a.Height; | |
361 a.Width -= b.Width; | |
362 } else if (c.Value == DockStyle.Bottom) { | |
363 b.X = a.X; | |
364 b.Y = a.Y + a.Height - b.Height; | |
365 b.Width = a.Width; | |
366 a.Height -= b.Height; | |
367 } else if (c.Value == DockStyle.Fill) { | |
368 b = a; | |
369 } | |
370 c.Key.Bounds = b; | |
371 if (a.Width < 0) a.Width = 0; | |
372 if (a.Height < 0) a.Height = 0; | |
373 } | |
374 } | |
375 } | |
376 public class FBGGroupBox : FBGDockContainer { | |
377 private String text = String.Empty; | |
378 public FBGGroupBox(IFBGContainerControl parent) | |
379 : base(parent) { | |
380 ClientRectangle = new Rectangle(1, 15, Bounds.Width - 2, Bounds.Height - 17); | |
381 } | |
382 public override Rectangle Bounds { | |
383 get { return base.Bounds; } | |
384 set { | |
385 ClientRectangle = new Rectangle(1, 15, value.Width - 2, value.Height - 17); | |
386 base.Bounds = value; | |
387 } | |
388 } | |
389 public String Text { get { return text; } set { if (text == value) return; text = value; Invalidate(new Rectangle(0, 0, Bounds.Width, 15)); } } | |
390 protected override void Paint(Graphics g) { | |
391 base.Paint(g); | |
392 g.DrawRectangle(Pens.Gray, 0, 6, Bounds.Width - 1, Bounds.Height - 7); | |
393 SizeF ss = g.MeasureString(Text, SystemFonts.DefaultFont, new Size(Bounds.Width - 10 - 9, 15)); | |
394 g.FillRectangle(SystemBrushes.Control, 9, 0, ss.Width, ss.Height); | |
395 g.DrawString(Text, SystemFonts.DefaultFont, Brushes.DarkBlue, new Rectangle(9, 0, Bounds.Width - 10 - 9, 15)); | |
396 } | |
397 } | |
398 public class WinFormsFBGHost : Control, IFBGContainerControl { | |
399 private IFBGControl childControl = null; | |
400 private IFBGControl mouseCaptureControl = null; | |
401 private IFBGControl keyboardCaptureControl = null; | |
402 public IFBGControl ChildControl { get { return childControl; } } | |
403 | |
404 public WinFormsFBGHost() { | |
405 DoubleBuffered = true; | |
406 } | |
407 | |
408 public virtual Point PointToChild(IFBGControl child, Point point) { | |
409 return point - (Size)child.Bounds.Location; | |
410 } | |
411 public virtual Point PointFromChild(IFBGControl child, Point point) { | |
412 return point + (Size)child.Bounds.Location; | |
413 } | |
414 | |
415 Size IFBGContainerControl.Size { get { return ClientSize; } } | |
416 void IFBGContainerControl.Invalidate(IFBGControl control, Rectangle rect) { | |
417 Invalidate(new Rectangle(PointFromChild(control, rect.Location), rect.Size)); | |
418 } | |
419 void IFBGContainerControl.AddControl(IFBGControl control) { | |
420 if (!ReferenceEquals(childControl, null)) throw new InvalidOperationException("This container can have only one child control"); | |
421 childControl = control; | |
422 control.Bounds = new Rectangle(Point.Empty, ClientSize); | |
423 Invalidate(control.Bounds); | |
424 } | |
425 void IFBGContainerControl.RemoveControl(IFBGControl control) { | |
426 if (!ReferenceEquals(childControl, control)) return; | |
427 childControl = null; | |
428 Invalidate(control.Bounds); | |
429 if (mouseCaptureControl == control) mouseCaptureControl = null; | |
430 if (keyboardCaptureControl == control) control = null; | |
431 control.Orphaned(); | |
432 } | |
433 Boolean IFBGContainerControl.CaptureMouse(IFBGControl control, Boolean capture) { | |
434 if (capture && !ReferenceEquals(mouseCaptureControl, null)) return false; | |
435 if (!capture && !ReferenceEquals(mouseCaptureControl, control)) return false; | |
436 mouseCaptureControl = capture ? control : null; | |
437 return true; | |
438 } | |
439 Boolean IFBGContainerControl.CaptureKeyboard(IFBGControl control, Boolean capture) { | |
440 if (!capture && !ReferenceEquals(keyboardCaptureControl, control)) return false; | |
441 keyboardCaptureControl = capture ? control : null; | |
442 return true; | |
443 } | |
444 | |
445 protected override void OnPaint(PaintEventArgs e) { | |
446 base.OnPaint(e); | |
447 Graphics g = e.Graphics; | |
448 GraphicsState state = g.Save(); | |
449 g.SetClip(e.ClipRectangle); | |
450 if (ReferenceEquals(childControl, null)) return; | |
451 if (childControl.Bounds.Width <= 0 || childControl.Bounds.Height <= 0) return; | |
452 if (!g.ClipBounds.IntersectsWith((RectangleF)childControl.Bounds)) return; | |
453 g.TranslateTransform(childControl.Bounds.X, childControl.Bounds.Y, MatrixOrder.Append); | |
454 g.IntersectClip(new Rectangle(Point.Empty, childControl.Bounds.Size)); | |
455 childControl.Paint(g); | |
456 g.Restore(state); | |
457 } | |
458 protected override void OnResize(EventArgs e) { | |
459 if (!ReferenceEquals(childControl, null)) childControl.Bounds = new Rectangle(Point.Empty, ClientSize); | |
460 base.OnResize(e); | |
461 } | |
462 protected override void OnMouseDown(MouseEventArgs e) { | |
463 base.OnMouseDown(e); | |
464 IFBGControl control = mouseCaptureControl != null ? mouseCaptureControl : childControl; | |
465 if (control != null) control.MouseDown(PointToChild(control, e.Location), e.Button); | |
466 } | |
467 protected override void OnMouseUp(MouseEventArgs e) { | |
468 base.OnMouseUp(e); | |
469 IFBGControl control = mouseCaptureControl != null ? mouseCaptureControl : childControl; | |
470 if (control != null) control.MouseUp(PointToChild(control, e.Location), e.Button); | |
471 } | |
472 protected override void OnMouseMove(MouseEventArgs e) { | |
473 IFBGControl control = mouseCaptureControl != null ? mouseCaptureControl : childControl; | |
474 if (control != null) control.MouseMove(PointToChild(control, e.Location), e.Button); | |
475 } | |
476 protected override bool IsInputChar(char charCode) { | |
477 return true; | |
478 } | |
479 protected override bool IsInputKey(Keys keyData) { | |
480 return true; | |
481 } | |
482 protected override void OnKeyDown(KeyEventArgs e) { | |
483 //base.OnKeyDown(e); | |
484 if (!ReferenceEquals(keyboardCaptureControl, null)) keyboardCaptureControl.KeyDown(e.KeyData); | |
485 } | |
486 protected override void OnKeyPress(KeyPressEventArgs e) { | |
487 //base.OnKeyPress(e); | |
488 if (!ReferenceEquals(keyboardCaptureControl, null)) keyboardCaptureControl.KeyPress(e.KeyChar); | |
489 } | |
490 protected override void OnKeyUp(KeyEventArgs e) { | |
491 //base.OnKeyUp(e); | |
492 if (!ReferenceEquals(keyboardCaptureControl, null)) keyboardCaptureControl.KeyUp(e.KeyData); | |
493 } | |
494 protected override void OnHandleDestroyed(EventArgs e) { | |
495 if (!ReferenceEquals(childControl, null)) childControl.Orphaned(); | |
496 base.OnHandleDestroyed(e); | |
497 } | |
498 } | |
499 public class FBGCursor { | |
500 public Image Image { get; private set; } | |
501 public Point Hotspot { get; private set; } | |
502 public Size Size { get; private set; } | |
503 public FBGCursor(Image image, Point hotspot) { | |
504 this.Image = image; | |
505 this.Hotspot = hotspot; | |
506 this.Size = image.Size; | |
507 } | |
508 | |
509 private const String ArrowCursorImageData = "iVBORw0KGgoAAAANSUhEUgAAAAwAAAAVCAYAAAByrA+0AAAAkUlEQVR42pWTORbEMAhDJb3cYNqUuf+JUk6bM2iKLM9DvGAqG/MFxpgAfKwbkTQBwOe7ewqwnYZ0L7KQyk0GUnSMINWcPUgtpRakXr01SKOuREiZ3pcQz329KeR7YpZaUCkQ50wjxWYGko8aSduGbZD8m2bF4NQsxeBj3XiX92rrzOfpvkMrizBpS+/wyuLynj9U+GDtLEEVuQAAAABJRU5ErkJggg=="; | |
510 public static readonly FBGCursor ArrowCursor = new FBGCursor(Image.FromStream(new MemoryStream(Convert.FromBase64String(ArrowCursorImageData))), Point.Empty); | |
511 } | |
512 public class FBGRenderer : FBGContainerControl, IDisposable { | |
513 private FBGCursor cursor = null; | |
514 private Point cursorposition = Point.Empty; | |
515 public IFramebuffer Framebuffer { get; private set; } | |
26
7f0b7a53a000
FBGUI: Allow derived classes to access some internals
Ivo Smits <Ivo@UCIS.nl>
parents:
23
diff
changeset
|
516 private Bitmap Frontbuffer = null; |
7f0b7a53a000
FBGUI: Allow derived classes to access some internals
Ivo Smits <Ivo@UCIS.nl>
parents:
23
diff
changeset
|
517 protected Object RenderLock = new object(); |
23 | 518 public event EventHandler<InvalidateEventArgs> Painted; |
26
7f0b7a53a000
FBGUI: Allow derived classes to access some internals
Ivo Smits <Ivo@UCIS.nl>
parents:
23
diff
changeset
|
519 protected Size size = Size.Empty; |
23 | 520 private ThreadingTimer PaintTimer = null; |
521 private Boolean PaintScheduled = false; | |
522 private int PaintDelay = 0; | |
523 public Boolean SuspendDrawing { | |
524 get { return suspenddrawing; } | |
525 set { | |
526 lock (RenderLock) { | |
527 suspenddrawing = value; | |
528 if (!value) { | |
529 Refresh(DirtyRectangle); | |
530 DirtyRectangle = Rectangle.Empty; | |
531 } | |
532 } | |
533 } | |
534 } | |
535 public int RedrawDelay { | |
536 get { return PaintDelay; } | |
537 set { | |
538 lock (RenderLock) { | |
539 if (value < 0) throw new ArgumentOutOfRangeException("value"); | |
540 PaintDelay = value; | |
541 if (PaintDelay == 0) { | |
542 if (PaintTimer != null) PaintTimer.Dispose(); | |
543 PaintTimer = null; | |
544 if (PaintScheduled) PaintTimerCallback(null); | |
545 } else { | |
546 PaintTimer = new ThreadingTimer(PaintTimerCallback); | |
547 } | |
548 } | |
549 } | |
550 } | |
551 private Boolean suspenddrawing = false; | |
552 private Rectangle DirtyRectangle; | |
553 | |
554 public FBGCursor Cursor { | |
555 get { return cursor; } | |
556 set { | |
27
5bfc6c68591e
FBGUI: Added numeric up/down control, fix for transparent control background
Ivo Smits <Ivo@UCIS.nl>
parents:
26
diff
changeset
|
557 if (cursor == value) return; |
23 | 558 cursor = value; |
559 Invalidate(); | |
560 } | |
561 } | |
562 public Point CursorPosition { | |
563 get { return cursorposition; } | |
564 set { | |
565 if (cursorposition == value) return; | |
566 Point oldposition = cursorposition; | |
567 cursorposition = value; | |
568 if (cursor == null) return; | |
569 Size s = cursor.Size; | |
570 if (s.Width == 0 && s.Height == 0) s = new Size(32, 32); | |
571 Rectangle r = Rectangle.Union(new Rectangle(oldposition, s), new Rectangle(cursorposition, s)); | |
572 r.Offset(-cursor.Hotspot.X, -cursor.Hotspot.Y); | |
573 if (Environment.OSVersion.Platform == PlatformID.Unix) { | |
574 r = Rectangle.Union(r, Rectangle.Union(new Rectangle(oldposition.X - 2, oldposition.Y - 2, 4, 4), new Rectangle(cursorposition.X - 2, cursorposition.Y - 2, 4, 4))); | |
575 } | |
576 Invalidate(r); | |
577 } | |
578 } | |
579 public override Rectangle Bounds { | |
580 get { return new Rectangle(Point.Empty, size); } | |
581 set { throw new NotSupportedException("Can not change the top control bounds"); } | |
582 } | |
583 public FBGRenderer(IFramebuffer fb) : this(fb.Width, fb.Height) { | |
584 Framebuffer = fb; | |
585 } | |
586 public FBGRenderer(Size fbsize) : this(fbsize.Width, fbsize.Height) { } | |
587 public FBGRenderer(int width, int height) : this(new Bitmap(width, height, PixelFormat.Format32bppRgb)) { } | |
588 public FBGRenderer(Bitmap bmp) : base(null) { | |
589 Frontbuffer = bmp; | |
590 BackColor = SystemColors.Control; | |
591 size = Frontbuffer.Size; | |
592 } | |
26
7f0b7a53a000
FBGUI: Allow derived classes to access some internals
Ivo Smits <Ivo@UCIS.nl>
parents:
23
diff
changeset
|
593 protected FBGRenderer() : base(null) { |
7f0b7a53a000
FBGUI: Allow derived classes to access some internals
Ivo Smits <Ivo@UCIS.nl>
parents:
23
diff
changeset
|
594 BackColor = SystemColors.Control; |
7f0b7a53a000
FBGUI: Allow derived classes to access some internals
Ivo Smits <Ivo@UCIS.nl>
parents:
23
diff
changeset
|
595 } |
23 | 596 public override void Invalidate(Rectangle rect) { |
597 if (rect.Width == 0 || rect.Height == 0) return; | |
598 lock (RenderLock) { | |
599 if (SuspendDrawing || PaintTimer != null) { | |
600 DirtyRectangle = DirtyRectangle.IsEmpty ? rect : Rectangle.Union(DirtyRectangle, rect); | |
601 if (!SuspendDrawing && !PaintScheduled) { | |
602 PaintScheduled = true; | |
603 PaintTimer.Change(PaintDelay, Timeout.Infinite); | |
604 } | |
605 } else { | |
606 Refresh(rect); | |
607 } | |
608 } | |
609 } | |
610 private void PaintTimerCallback(Object state) { | |
611 try { | |
612 lock (RenderLock) { | |
613 PaintScheduled = false; | |
614 Refresh(DirtyRectangle); | |
615 DirtyRectangle = Rectangle.Empty; | |
616 } | |
617 } catch { } | |
618 } | |
26
7f0b7a53a000
FBGUI: Allow derived classes to access some internals
Ivo Smits <Ivo@UCIS.nl>
parents:
23
diff
changeset
|
619 protected virtual void Refresh(Rectangle rect) { |
23 | 620 lock (RenderLock) { |
621 rect.Intersect(Bounds); | |
622 if (rect.Width == 0 || rect.Height == 0) return; | |
26
7f0b7a53a000
FBGUI: Allow derived classes to access some internals
Ivo Smits <Ivo@UCIS.nl>
parents:
23
diff
changeset
|
623 if (Frontbuffer != null) { |
7f0b7a53a000
FBGUI: Allow derived classes to access some internals
Ivo Smits <Ivo@UCIS.nl>
parents:
23
diff
changeset
|
624 using (Graphics g = Graphics.FromImage(Frontbuffer)) { |
7f0b7a53a000
FBGUI: Allow derived classes to access some internals
Ivo Smits <Ivo@UCIS.nl>
parents:
23
diff
changeset
|
625 g.SetClip(rect); |
7f0b7a53a000
FBGUI: Allow derived classes to access some internals
Ivo Smits <Ivo@UCIS.nl>
parents:
23
diff
changeset
|
626 Paint(g); |
7f0b7a53a000
FBGUI: Allow derived classes to access some internals
Ivo Smits <Ivo@UCIS.nl>
parents:
23
diff
changeset
|
627 } |
7f0b7a53a000
FBGUI: Allow derived classes to access some internals
Ivo Smits <Ivo@UCIS.nl>
parents:
23
diff
changeset
|
628 if (Framebuffer != null) Framebuffer.DrawImage(Frontbuffer, rect, rect.Location); |
23 | 629 } |
630 RaiseEvent(Painted, new InvalidateEventArgs(rect)); | |
631 } | |
632 } | |
633 protected override void Paint(Graphics g) { | |
634 base.Paint(g); | |
635 if (Cursor != null) { | |
636 Point r = CursorPosition; | |
637 r.Offset(-cursor.Hotspot.X, -cursor.Hotspot.Y); | |
638 g.DrawImageUnscaled(Cursor.Image, r); | |
639 } | |
640 } | |
641 protected override Boolean CaptureMouse(Boolean capture) { | |
642 return true; | |
643 } | |
644 protected override Boolean CaptureKeyboard(bool capture) { | |
645 return true; | |
646 } | |
26
7f0b7a53a000
FBGUI: Allow derived classes to access some internals
Ivo Smits <Ivo@UCIS.nl>
parents:
23
diff
changeset
|
647 public virtual void Dispose() { |
23 | 648 lock (RenderLock) { |
649 if (PaintTimer != null) PaintTimer.Dispose(); | |
650 PaintTimer = null; | |
651 } | |
652 Orphaned(); | |
653 if (Frontbuffer != null) Frontbuffer.Dispose(); | |
654 } | |
655 public Bitmap LockBitmapBuffer() { | |
656 Monitor.Enter(RenderLock); | |
657 return Frontbuffer; | |
658 } | |
659 public void UnlockBitmapBuffer() { | |
660 Monitor.Exit(RenderLock); | |
661 } | |
662 public new void MouseMove(Point position, MouseButtons buttons) { base.MouseMove(position, buttons); } | |
663 public new void MouseDown(Point position, MouseButtons buttons) { base.MouseDown(position, buttons); } | |
664 public new void MouseUp(Point position, MouseButtons buttons) { base.MouseUp(position, buttons); } | |
665 public new void KeyDown(Keys key) { base.KeyDown(key); } | |
666 public new void KeyPress(Char key) { base.KeyPress(key); } | |
667 public new void KeyUp(Keys key) { base.KeyUp(key); } | |
668 } | |
669 public class FBGForm : FBGDockContainer { | |
670 private Point prevPosition = Point.Empty; | |
671 private NonClientOps moveresize = 0; | |
672 private String text = String.Empty; | |
673 public event EventHandler TextChanged; | |
674 public Boolean Sizable { get; set; } | |
675 public Boolean Movable { get; set; } | |
676 public Boolean Closable { get; set; } | |
677 [Flags] | |
678 private enum NonClientOps : int { | |
679 None = 0, | |
680 Move = 1, | |
681 ResizeLeft = 2, | |
682 ResizeRight = 4, | |
683 ResizeTop = 8, | |
684 ResizeBottom = 16, | |
685 ButtonClose = 32, | |
686 MoveResize = ResizeLeft | ResizeRight | ResizeBottom | ResizeTop | Move, | |
687 } | |
688 public FBGForm(IFBGContainerControl parent) : base(parent) { | |
689 BackColor = SystemColors.Control; | |
690 ClientRectangle = new Rectangle(4, 22, Bounds.Width - 8, Bounds.Height - 26); | |
691 Sizable = true; | |
692 Movable = true; | |
693 Closable = false; | |
694 } | |
695 public override Rectangle Bounds { | |
696 get { return base.Bounds; } | |
697 set { | |
698 ClientRectangle = new Rectangle(4, 22, value.Width - 8, value.Height - 26); | |
699 base.Bounds = value; | |
700 } | |
701 } | |
702 public String Text { get { return text; } set { if (text == value) return; text = value; Invalidate(new Rectangle(0, 0, Bounds.Width, 20)); RaiseEvent(TextChanged); } } | |
703 protected override void MouseDown(Point p, MouseButtons buttons) { | |
704 NonClientOps mr = 0; | |
705 if ((buttons & MouseButtons.Left) != 0) { | |
706 if ((new Rectangle(Bounds.Width - 5 - 14, 4, 14, 14)).Contains(p)) { | |
707 mr = NonClientOps.ButtonClose; | |
708 } else { | |
709 if (Sizable) { | |
710 if (Movable) { | |
711 if (p.X < 4) mr |= NonClientOps.ResizeLeft; | |
712 if (p.Y < 4) mr |= NonClientOps.ResizeTop; | |
713 } | |
714 if (p.X >= Bounds.Width - 4) mr |= NonClientOps.ResizeRight; | |
715 if (p.Y >= Bounds.Height - 4) mr |= NonClientOps.ResizeBottom; | |
716 } | |
717 if (mr == 0 && Movable && p.Y < 20) mr = NonClientOps.Move; | |
718 } | |
719 } | |
720 if (mr != 0) { | |
721 moveresize = mr; | |
722 prevPosition = p; | |
723 CaptureMouse(true); | |
724 } else { | |
725 base.MouseDown(p, buttons); | |
726 } | |
727 } | |
728 protected override void MouseMove(Point position, MouseButtons buttons) { | |
729 if (moveresize == 0) { | |
730 base.MouseMove(position, buttons); | |
731 } else if ((moveresize & NonClientOps.MoveResize) != 0) { | |
732 Rectangle b = Bounds; | |
733 int dx = position.X - prevPosition.X; | |
734 int dy = position.Y - prevPosition.Y; | |
735 if (moveresize == NonClientOps.Move) b.Offset(dx, dy); | |
736 if ((moveresize & NonClientOps.ResizeLeft) != 0) { | |
737 b.X += dx; | |
738 b.Width -= dx; | |
739 } else if ((moveresize & NonClientOps.ResizeRight) != 0) { | |
740 b.Width += dx; | |
741 prevPosition.X = position.X; | |
742 } | |
743 if ((moveresize & NonClientOps.ResizeTop) != 0) { | |
744 b.Y += dy; | |
745 b.Height -= dy; | |
746 } else if ((moveresize & NonClientOps.ResizeBottom) != 0) { | |
747 b.Height += dy; | |
748 prevPosition.Y = position.Y; | |
749 } | |
750 if (b.Width < 55) b.Width = 55; | |
751 if (b.Height < 25) b.Height = 25; | |
752 Bounds = b; | |
753 } | |
754 } | |
755 protected override void MouseUp(Point position, MouseButtons buttons) { | |
756 if (moveresize == 0) { | |
757 base.MouseUp(position, buttons); | |
758 } else if ((buttons & MouseButtons.Left) != 0) { | |
759 MouseMove(position, buttons); | |
760 CaptureMouse(false); | |
761 if (moveresize == NonClientOps.ButtonClose && (new Rectangle(Bounds.Width - 5 - 14, 4, 14, 14)).Contains(position) && Closable) Close(); | |
762 moveresize = 0; | |
763 } | |
764 } | |
765 protected override void Paint(Graphics g) { | |
766 base.Paint(g); | |
767 g.DrawRectangle(Pens.Gray, 0, 0, Bounds.Width - 1, Bounds.Height - 1); | |
768 g.DrawRectangle(Pens.LightGray, 1, 1, Bounds.Width - 3, Bounds.Height - 3); | |
769 g.DrawRectangle(Pens.DarkGray, 2, 20, Bounds.Width - 5, Bounds.Height - 23); | |
770 g.DrawRectangle(Pens.Gray, 3, 21, Bounds.Width - 7, Bounds.Height - 25); | |
771 using (Brush b = new LinearGradientBrush(new Rectangle(0, 1, 1, 18), Color.Gray, Color.LightGray, LinearGradientMode.Vertical)) | |
772 g.FillRectangle(b, 2, 2, Bounds.Width - 4, 18); | |
773 | |
774 g.DrawString(Text, SystemFonts.CaptionFont, Brushes.Black, 4, 1); | |
775 | |
776 g.DrawRectangle(Pens.Gray, Bounds.Width - 5 - 14, 4, 14, 14); | |
777 g.DrawRectangle(Pens.Gray, Bounds.Width - 5 - 14 - 16, 4, 14, 14); | |
778 g.DrawRectangle(Pens.Gray, Bounds.Width - 5 - 14 - 32, 4, 14, 14); | |
779 using (Brush b = new LinearGradientBrush(new Rectangle(0, 5, 1, 13), Color.LightGray, Color.DarkGray, LinearGradientMode.Vertical)) { | |
780 g.FillRectangle(b, Bounds.Width - 5 - 14 + 1, 5, 13, 13); | |
781 g.FillRectangle(b, Bounds.Width - 5 - 14 + 1 - 16, 5, 13, 13); | |
782 g.FillRectangle(b, Bounds.Width - 5 - 14 + 1 - 32, 5, 13, 13); | |
783 } | |
784 if (Closable) { | |
785 g.DrawLine(Pens.Black, Bounds.Width - 5 - 14 + 3, 4 + 3, Bounds.Width - 5 - 14 + 14 - 3, 4 + 14 - 3); | |
786 g.DrawLine(Pens.Black, Bounds.Width - 5 - 14 + 3, 4 + 14 - 3, Bounds.Width - 5 - 14 + 14 - 3, 4 + 3); | |
787 } | |
788 } | |
789 public void Close() { | |
790 Parent.RemoveControl(this); | |
791 } | |
792 } | |
793 public class FBGDesktop : FBGContainerControl { | |
794 FBGContainerControl windowcontainer; | |
795 FBGContainerControl menucontainer; | |
796 Boolean startup = true; | |
797 class FBGWindowState { | |
798 public IFBGControl Control; | |
799 public FBGButton MenuButton; | |
800 public Boolean Visible; | |
801 public Rectangle OldBounds; | |
802 public FBGWindowState(IFBGControl cntrl, FBGButton btn) { | |
803 Control = cntrl; | |
804 MenuButton = btn; | |
805 Visible = true; | |
806 } | |
807 } | |
808 Dictionary<IFBGControl, FBGWindowState> windowstates = new Dictionary<IFBGControl, FBGWindowState>(); | |
809 public FBGDesktop(IFBGContainerControl parent) : base(parent) { | |
810 menucontainer = new FBGContainerControl(this); | |
811 menucontainer.Bounds = new Rectangle(0, Bounds.Height - 25, Bounds.Width, 25); | |
812 windowcontainer = new FBGContainerControl(this); | |
813 windowcontainer.Bounds = new Rectangle(0, 0, Bounds.Width, Bounds.Height - 25); | |
814 startup = false; | |
815 } | |
816 public override Rectangle Bounds { | |
817 get { return base.Bounds; } | |
818 set { | |
819 if (Bounds == value) return; | |
820 base.Bounds = value; | |
821 if (startup) return; | |
822 menucontainer.Bounds = new Rectangle(0, value.Height - 25, value.Width, 25); | |
823 windowcontainer.Bounds = new Rectangle(0, 0, value.Width, value.Height - 25); | |
824 ScaleMenuButtons(); | |
825 } | |
826 } | |
827 protected override void AddControl(IFBGControl control) { | |
828 if (startup) { | |
829 base.AddControl(control); | |
830 return; | |
831 } | |
832 ((IFBGContainerControl)windowcontainer).AddControl(control); | |
833 FBGButton btn = new FBGButton(menucontainer); | |
834 FBGForm formcontrol = control as FBGForm; | |
835 if (formcontrol == null) { | |
836 btn.Text = "Untitled"; | |
837 } else { | |
838 formcontrol.TextChanged += delegate(Object sender, EventArgs e) { | |
839 btn.Text = formcontrol.Text; | |
840 }; | |
841 btn.Text = formcontrol.Text; | |
842 } | |
843 FBGWindowState ws = new FBGWindowState(control, btn); | |
844 windowstates.Add(control, ws); | |
845 ScaleMenuButtons(); | |
846 btn.Click += delegate(Object sender, EventArgs e) { | |
847 if (ws.Visible) { | |
848 if (ws.MenuButton.BackColor == Color.DarkGray) { | |
849 ws.OldBounds = ws.Control.Bounds; | |
850 ws.Visible = false; | |
851 ws.Control.Bounds = Rectangle.Empty; | |
852 } else { | |
853 windowcontainer.BringControlToFront(ws.Control); | |
854 foreach (FBGWindowState wsa in windowstates.Values) if (!ReferenceEquals(ws, wsa)) wsa.MenuButton.BackColor = SystemColors.ButtonFace; | |
855 ws.MenuButton.BackColor = Color.DarkGray; | |
856 } | |
857 } else { | |
858 ws.Control.Bounds = ws.OldBounds; | |
859 ws.Visible = true; | |
860 windowcontainer.BringControlToFront(ws.Control); | |
861 foreach (FBGWindowState wsa in windowstates.Values) if (!ReferenceEquals(ws, wsa)) wsa.MenuButton.BackColor = SystemColors.ButtonFace; | |
862 ws.MenuButton.BackColor = Color.DarkGray; | |
863 } | |
864 }; | |
865 } | |
866 public override void RemoveControl(IFBGControl control) { | |
867 windowcontainer.RemoveControl(control); | |
868 windowstates.Remove(control); | |
869 ScaleMenuButtons(); | |
870 } | |
871 private void ScaleMenuButtons() { | |
872 int bcount = windowstates.Count; | |
873 int bwidth = 200; | |
874 int twidth = bwidth * bcount; | |
875 if (twidth > Bounds.Width) bwidth = menucontainer.Bounds.Width / bcount; | |
876 int i = 0; | |
877 foreach (FBGWindowState ws in windowstates.Values) { | |
878 ws.MenuButton.Bounds = new Rectangle(i * bwidth, 0, bwidth, 25); | |
879 i++; | |
880 } | |
881 } | |
882 protected override void Paint(Graphics g) { | |
883 base.Paint(g); | |
884 g.DrawLine(Pens.Black, 0, Bounds.Height - 25, Bounds.Width, Bounds.Height - 25); | |
885 } | |
886 protected override void MouseDown(Point position, MouseButtons buttons) { | |
887 IFBGControl control = FindControlAtPosition(position); | |
888 if (ReferenceEquals(control, windowcontainer)) { | |
889 control = windowcontainer.FindControlAtPosition(PointToChild(windowcontainer, position)); | |
890 if (!ReferenceEquals(control, null)) { | |
891 windowcontainer.BringControlToFront(control); | |
892 foreach (FBGWindowState ws in windowstates.Values) | |
893 ws.MenuButton.BackColor = ReferenceEquals(ws.Control, control) ? Color.DarkGray : SystemColors.ButtonFace; | |
894 } | |
895 } | |
896 base.MouseDown(position, buttons); | |
897 } | |
898 } | |
899 | |
900 public class FBGLabel : FBGControl, IDisposable { | |
901 public FBGLabel(IFBGContainerControl parent) : base(parent) { | |
902 Size = new Size(200, 16); | |
903 } | |
904 private String text = String.Empty; | |
905 private Font font = SystemFonts.DefaultFont; | |
906 private Brush brush = SystemBrushes.ControlText; | |
907 private StringFormat stringformat = new StringFormat(); | |
908 public String Text { get { return text; } set { text = value; Invalidate(); } } | |
909 public Font Font { get { return font; } set { font = value; Invalidate(); } } | |
910 public Brush Brush { get { return brush; } set { brush = value; Invalidate(); } } | |
911 public Color Color { set { Brush = new SolidBrush(value); } } | |
912 public StringAlignment Alignment { get { return stringformat.Alignment; } set { stringformat.Alignment = value; Invalidate(); } } | |
913 public StringFormatFlags FormatFlags { get { return stringformat.FormatFlags; } set { stringformat.FormatFlags = value; Invalidate(); } } | |
914 public StringAlignment LineAlignment { get { return stringformat.LineAlignment; } set { stringformat.LineAlignment = value; Invalidate(); } } | |
915 public StringTrimming Trimming { get { return stringformat.Trimming; } set { stringformat.Trimming = value; Invalidate(); } } | |
916 protected override void Paint(Graphics g) { | |
917 base.Paint(g); | |
918 g.DrawString(text, font, brush, new Rectangle(Point.Empty, Bounds.Size), stringformat); | |
919 } | |
920 public void Dispose() { | |
921 stringformat.Dispose(); | |
922 } | |
923 protected override void Orphaned() { | |
924 base.Orphaned(); | |
925 Dispose(); | |
926 } | |
927 } | |
928 public class FBGTextBox : FBGControl { | |
929 public FBGTextBox(IFBGContainerControl parent) : base(parent) { | |
930 BackColor = Color.White; | |
931 Size = new Size(200, 20); | |
932 } | |
933 private String text = String.Empty; | |
934 private Char passwordChar = (Char)0; | |
935 private Font font = new Font(FontFamily.GenericMonospace, 10); | |
936 private Brush brush = SystemBrushes.ControlText; | |
937 private Boolean hasKeyboardFocus = false; | |
938 public String Text { get { return text; } set { text = value; if (CaretPosition > text.Length) CaretPosition = text.Length; Invalidate(); RaiseEvent(TextChanged); } } | |
939 public Font Font { get { return font; } set { font = value; Invalidate(); } } | |
940 public Brush Brush { get { return brush; } set { brush = value; Invalidate(); } } | |
941 public Color Color { set { Brush = new SolidBrush(value); } } | |
942 public Int32 CaretPosition { get; private set; } | |
943 public Char PasswordChar { get { return passwordChar; } set { passwordChar = value; Invalidate(); } } | |
944 public event EventHandler TextChanged; | |
945 public event KeyPressEventHandler OnKeyPress; | |
946 protected override void Paint(Graphics g) { | |
947 base.Paint(g); | |
948 g.DrawRectangle(Pens.Gray, 0, 0, Bounds.Width - 1, Bounds.Height - 1); | |
949 using (StringFormat sf_nonprinting = new StringFormat(StringFormat.GenericTypographic)) { | |
950 sf_nonprinting.Trimming = StringTrimming.None; | |
951 sf_nonprinting.FormatFlags = StringFormatFlags.DisplayFormatControl | StringFormatFlags.MeasureTrailingSpaces; | |
952 sf_nonprinting.HotkeyPrefix = System.Drawing.Text.HotkeyPrefix.None; | |
953 | |
954 float x = 1; | |
955 float y = 1; | |
956 float w = Width - 2; | |
957 if (hasKeyboardFocus && CaretPosition == 0) { | |
958 g.DrawLine(Pens.Black, x + 2, 2, x + 2, Height - 4); | |
959 } | |
960 String c = passwordChar == 0 ? null : new String(passwordChar, 1); | |
961 for (int i = 0; i < text.Length; i++) { | |
962 if (passwordChar == 0) c = text.Substring(i, 1); | |
963 SizeF s = g.MeasureString(c, font, (int)Math.Ceiling(w), sf_nonprinting); | |
964 g.DrawString(c, font, brush, x, y); | |
965 x += (float)Math.Ceiling(s.Width); | |
966 w -= (float)Math.Ceiling(s.Width); | |
967 | |
968 if (hasKeyboardFocus && i == CaretPosition - 1) { | |
969 g.DrawLine(Pens.Black, x + 2, 2, x + 2, Height - 4); | |
970 } | |
971 } | |
972 } | |
973 } | |
974 protected override void MouseDown(Point position, MouseButtons buttons) { | |
975 hasKeyboardFocus = CaptureKeyboard(true); | |
976 CaretPosition = text.Length; | |
977 float x = 1; | |
978 String c = passwordChar == 0 ? null : new String(passwordChar, 1); | |
979 for (int i = 0; i < text.Length; i++) { | |
980 if (passwordChar == 0) c = text.Substring(i, 1); | |
981 Size s; | |
982 try { | |
983 s = TextRenderer.MeasureText(c, font, Size.Empty, TextFormatFlags.NoPadding | TextFormatFlags.NoPrefix); | |
984 } catch (Exception) { | |
985 break; | |
986 } | |
987 x += s.Width; | |
988 if (position.X < x) { | |
989 CaretPosition = i; | |
990 break; | |
991 } | |
992 } | |
993 Invalidate(); | |
994 } | |
995 protected override void KeyDown(Keys key) { | |
996 if ((key & Keys.KeyCode) == Keys.Left) { | |
997 CaretPosition--; | |
998 if (CaretPosition < 0) CaretPosition = 0; | |
999 Invalidate(); | |
1000 } else if ((key & Keys.KeyCode) == Keys.Right) { | |
1001 CaretPosition++; | |
1002 if (CaretPosition > text.Length) CaretPosition = text.Length; | |
1003 Invalidate(); | |
1004 } else if ((key & Keys.KeyCode) == Keys.Home) { | |
1005 CaretPosition = 0; | |
1006 Invalidate(); | |
1007 } else if ((key & Keys.KeyCode) == Keys.End) { | |
1008 CaretPosition = text.Length; | |
1009 Invalidate(); | |
1010 } else if ((key & Keys.Control) != 0 && (key & Keys.KeyCode) == Keys.V) { | |
1011 String cbtext = Clipboard.GetText(TextDataFormat.UnicodeText); | |
1012 CaretPosition += cbtext.Length; | |
1013 Text = Text.Insert(CaretPosition - cbtext.Length, cbtext); | |
1014 } | |
1015 } | |
1016 protected override void KeyPress(char keyChar) { | |
1017 KeyPressEventArgs e = new KeyPressEventArgs(keyChar); | |
1018 RaiseEvent(OnKeyPress, e); | |
1019 if (e.Handled) return; | |
1020 hasKeyboardFocus = true; | |
1021 if (keyChar == 8) { | |
1022 if (CaretPosition > 0) { | |
1023 CaretPosition--; | |
1024 Text = Text.Remove(CaretPosition, 1); | |
1025 } | |
1026 } else if (keyChar == 127) { | |
1027 if (CaretPosition < Text.Length) { | |
1028 Text = Text.Remove(CaretPosition, 1); | |
1029 } | |
1030 } else if (keyChar < 32) { | |
1031 } else { | |
1032 CaretPosition++; | |
1033 Text = Text.Insert(CaretPosition - 1, new String(keyChar, 1)); | |
1034 } | |
1035 } | |
1036 public void Focus() { | |
1037 hasKeyboardFocus = CaptureKeyboard(true); | |
1038 } | |
1039 protected override void LostKeyboardCapture() { | |
1040 base.LostKeyboardCapture(); | |
1041 hasKeyboardFocus = false; | |
1042 Invalidate(); | |
1043 } | |
1044 } | |
1045 public class FBGButton : FBGControl { | |
1046 public FBGButton(IFBGContainerControl parent) : base(parent) { | |
1047 BackColor = SystemColors.ButtonFace; | |
1048 } | |
1049 private String text = String.Empty; | |
1050 private Font font = SystemFonts.DefaultFont; | |
1051 private Color color = SystemColors.ControlText; | |
1052 private Boolean pressed = false; | |
1053 private Boolean enabled = true; | |
1054 public String Text { get { return text; } set { text = value; Invalidate(); } } | |
1055 public Font Font { get { return font; } set { font = value; Invalidate(); } } | |
1056 public Color Color { get { return color; } set { color = value; Invalidate(); } } | |
1057 public Boolean Enabled { get { return enabled; } set { enabled = value; Invalidate(); } } | |
1058 public event EventHandler Click; | |
1059 protected override void Paint(Graphics g) { | |
1060 base.Paint(g); | |
1061 if (Bounds.Width == 0 || Bounds.Height == 0) return; | |
1062 if (BackColor == SystemColors.ButtonFace) { | |
1063 ControlPaint.DrawButton(g, new Rectangle(0, 0, Bounds.Width, Bounds.Height), enabled ? (pressed ? ButtonState.Pushed : ButtonState.Normal) : ButtonState.Inactive); | |
1064 } else { | |
1065 //Hackish and not completely right... | |
1066 //Todo: borrowed from mono... possible licencing issues!? | |
1067 g.DrawLine(new Pen(ControlPaint.LightLight(BackColor)), 0, 0, Bounds.Width, 0); | |
1068 g.DrawLine(new Pen(ControlPaint.LightLight(BackColor)), 0, 0, 0, Bounds.Height); | |
1069 g.DrawLine(new Pen(ControlPaint.Dark(BackColor)), 1, Bounds.Height - 2, Bounds.Width - 1, Bounds.Height - 2); | |
1070 g.DrawLine(new Pen(ControlPaint.Dark(BackColor)), Bounds.Width - 2, 1, Bounds.Width - 2, Bounds.Height - 2); | |
1071 g.DrawLine(new Pen(ControlPaint.DarkDark(BackColor)), 0, Bounds.Height - 1, Bounds.Width, Bounds.Height - 1); | |
1072 g.DrawLine(new Pen(ControlPaint.DarkDark(BackColor)), Bounds.Width - 1, 1, Bounds.Width - 1, Bounds.Height - 1); | |
1073 Graphics dc = g; | |
1074 Rectangle rectangle = new Rectangle(0, 0, Bounds.Width - 1, Bounds.Height - 1); | |
1075 Color ColorControl = BackColor; | |
1076 Color ColorControlLight = ControlPaint.Light(ColorControl); | |
1077 ButtonState state = pressed ? ButtonState.Pushed : ButtonState.Normal; | |
1078 using (Pen NormalPen = new Pen(BackColor), LightPen = new Pen(ControlPaint.Light(BackColor)), DarkPen = new Pen(ControlPaint.Dark(BackColor))) { | |
1079 // sadly enough, the rectangle gets always filled with a hatchbrush | |
1080 using (HatchBrush hb = new HatchBrush(HatchStyle.Percent50, Color.FromArgb(Math.Min(255, ColorControl.R + 3), ColorControl.G, ColorControl.B), ColorControl)) { | |
1081 dc.FillRectangle(hb, rectangle.X + 1, rectangle.Y + 1, rectangle.Width - 2, rectangle.Height - 2); | |
1082 } | |
1083 if ((state & ButtonState.All) == ButtonState.All || ((state & ButtonState.Checked) == ButtonState.Checked && (state & ButtonState.Flat) == ButtonState.Flat)) { | |
1084 using (HatchBrush hb = new HatchBrush(HatchStyle.Percent50, ColorControlLight, ColorControl)) { | |
1085 dc.FillRectangle(hb, rectangle.X + 2, rectangle.Y + 2, rectangle.Width - 4, rectangle.Height - 4); | |
1086 } | |
1087 dc.DrawRectangle(SystemPens.ControlDark, rectangle.X, rectangle.Y, rectangle.Width - 1, rectangle.Height - 1); | |
1088 } else if ((state & ButtonState.Flat) == ButtonState.Flat) { | |
1089 dc.DrawRectangle(SystemPens.ControlDark, rectangle.X, rectangle.Y, rectangle.Width - 1, rectangle.Height - 1); | |
1090 } else if ((state & ButtonState.Checked) == ButtonState.Checked) { | |
1091 using (HatchBrush hb = new HatchBrush(HatchStyle.Percent50, ColorControlLight, ColorControl)) { | |
1092 dc.FillRectangle(hb, rectangle.X + 2, rectangle.Y + 2, rectangle.Width - 4, rectangle.Height - 4); | |
1093 } | |
1094 Pen pen = DarkPen; | |
1095 dc.DrawLine(pen, rectangle.X, rectangle.Y, rectangle.X, rectangle.Bottom - 2); | |
1096 dc.DrawLine(pen, rectangle.X + 1, rectangle.Y, rectangle.Right - 2, rectangle.Y); | |
1097 | |
1098 pen = NormalPen; | |
1099 dc.DrawLine(pen, rectangle.X + 1, rectangle.Y + 1, rectangle.X + 1, rectangle.Bottom - 3); | |
1100 dc.DrawLine(pen, rectangle.X + 2, rectangle.Y + 1, rectangle.Right - 3, rectangle.Y + 1); | |
1101 | |
1102 pen = LightPen; | |
1103 dc.DrawLine(pen, rectangle.X, rectangle.Bottom - 1, rectangle.Right - 2, rectangle.Bottom - 1); | |
1104 dc.DrawLine(pen, rectangle.Right - 1, rectangle.Y, rectangle.Right - 1, rectangle.Bottom - 1); | |
1105 } else if (((state & ButtonState.Pushed) == ButtonState.Pushed) && ((state & ButtonState.Normal) == ButtonState.Normal)) { | |
1106 Pen pen = DarkPen; | |
1107 dc.DrawLine(pen, rectangle.X, rectangle.Y, rectangle.X, rectangle.Bottom - 2); | |
1108 dc.DrawLine(pen, rectangle.X + 1, rectangle.Y, rectangle.Right - 2, rectangle.Y); | |
1109 | |
1110 pen = NormalPen; | |
1111 dc.DrawLine(pen, rectangle.X + 1, rectangle.Y + 1, rectangle.X + 1, rectangle.Bottom - 3); | |
1112 dc.DrawLine(pen, rectangle.X + 2, rectangle.Y + 1, rectangle.Right - 3, rectangle.Y + 1); | |
1113 | |
1114 pen = LightPen; | |
1115 dc.DrawLine(pen, rectangle.X, rectangle.Bottom - 1, rectangle.Right - 2, rectangle.Bottom - 1); | |
1116 dc.DrawLine(pen, rectangle.Right - 1, rectangle.Y, rectangle.Right - 1, rectangle.Bottom - 1); | |
1117 } else if (((state & ButtonState.Inactive) == ButtonState.Inactive) || ((state & ButtonState.Normal) == ButtonState.Normal)) { | |
1118 Pen pen = LightPen; | |
1119 dc.DrawLine(pen, rectangle.X, rectangle.Y, rectangle.Right - 2, rectangle.Y); | |
1120 dc.DrawLine(pen, rectangle.X, rectangle.Y, rectangle.X, rectangle.Bottom - 2); | |
1121 | |
1122 pen = NormalPen; | |
1123 dc.DrawLine(pen, rectangle.X + 1, rectangle.Bottom - 2, rectangle.Right - 2, rectangle.Bottom - 2); | |
1124 dc.DrawLine(pen, rectangle.Right - 2, rectangle.Y + 1, rectangle.Right - 2, rectangle.Bottom - 3); | |
1125 | |
1126 pen = DarkPen; | |
1127 dc.DrawLine(pen, rectangle.X, rectangle.Bottom - 1, rectangle.Right - 1, rectangle.Bottom - 1); | |
1128 dc.DrawLine(pen, rectangle.Right - 1, rectangle.Y, rectangle.Right - 1, rectangle.Bottom - 2); | |
1129 } | |
1130 } | |
1131 } | |
1132 Rectangle frect = new Rectangle(Point.Empty, Bounds.Size); | |
1133 SizeF textsize = g.MeasureString(Text, Font); | |
1134 using (Brush b = new SolidBrush(enabled ? Color : Color.DarkGray)) { | |
1135 g.DrawString(Text, Font, b, new PointF(Bounds.Width / 2.0f - textsize.Width / 2.0f, Bounds.Height / 2.0f - textsize.Height / 2.0f)); | |
1136 } | |
1137 } | |
1138 protected override void MouseDown(Point position, MouseButtons buttons) { | |
1139 pressed = true; | |
1140 Invalidate(); | |
1141 CaptureMouse(true); | |
1142 base.MouseDown(position, buttons); | |
1143 } | |
1144 protected override void MouseUp(Point position, MouseButtons buttons) { | |
1145 pressed = false; | |
1146 Invalidate(); | |
1147 CaptureMouse(false); | |
1148 if (position.X >= 0 && position.X <= Bounds.Width && position.Y >= 0 && position.Y <= Bounds.Height && enabled) RaiseEvent(Click); | |
1149 base.MouseUp(position, buttons); | |
1150 } | |
1151 protected override void KeyDown(Keys key) { | |
1152 if (key == Keys.Return || key == Keys.Space) { | |
1153 pressed = true; | |
1154 Invalidate(); | |
1155 } | |
1156 base.KeyDown(key); | |
1157 } | |
1158 protected override void KeyUp(Keys key) { | |
1159 if (key == Keys.Return || key == Keys.Space) { | |
1160 if (pressed) RaiseEvent(Click); | |
1161 pressed = false; | |
1162 Invalidate(); | |
1163 } | |
1164 base.KeyUp(key); | |
1165 } | |
1166 public void Focus() { | |
1167 CaptureKeyboard(true); | |
1168 } | |
1169 } | |
1170 public class FBGCheckBox : FBGControl { | |
1171 public FBGCheckBox(IFBGContainerControl parent) : base(parent) { } | |
1172 private String text = String.Empty; | |
1173 private Font font = SystemFonts.DefaultFont; | |
1174 private Color color = SystemColors.ControlText; | |
1175 private Boolean _checked = false; | |
1176 public String Text { get { return text; } set { text = value; Invalidate(); } } | |
1177 public Font Font { get { return font; } set { font = value; Invalidate(); } } | |
1178 public Color Color { get { return color; } set { color = value; Invalidate(); } } | |
1179 public Boolean Checked { get { return _checked; } set { _checked = value; Invalidate(); } } | |
1180 public event EventHandler CheckedChanged; | |
1181 protected override void Paint(Graphics g) { | |
1182 base.Paint(g); | |
1183 ControlPaint.DrawCheckBox(g, 0, 0, 13, 13, _checked ? ButtonState.Checked : ButtonState.Normal); | |
1184 g.DrawString(Text, Font, new SolidBrush(Color), 15, 0); | |
1185 } | |
1186 protected override void MouseDown(Point position, MouseButtons buttons) { | |
1187 Checked = !Checked; | |
1188 RaiseEvent(CheckedChanged); | |
1189 base.MouseDown(position, buttons); | |
1190 } | |
1191 } | |
1192 public class FBGImageBox : FBGControl { | |
1193 Image image = null; | |
1194 PictureBoxSizeMode sizeMode = PictureBoxSizeMode.Normal; | |
1195 Rectangle imageRect; | |
1196 public Image Image { get { return image; } set { image = value; UpdateImageRect(false); } } | |
1197 public FBGImageBox(IFBGContainerControl parent) : base(parent) { } | |
1198 public PictureBoxSizeMode SizeMode { get { return sizeMode; } set { sizeMode = value; UpdateImageRect(false); } } | |
1199 public override Rectangle Bounds { | |
1200 get { | |
1201 return base.Bounds; | |
1202 } | |
1203 set { | |
1204 UpdateImageRect(true); | |
1205 base.Bounds = value; | |
1206 } | |
1207 } | |
1208 private void UpdateImageRect(Boolean boundsset) { | |
1209 if (image == null) return; | |
1210 if (!boundsset && sizeMode == PictureBoxSizeMode.AutoSize) { | |
1211 Size = Image.Size; | |
1212 return; | |
1213 } | |
1214 switch (sizeMode) { | |
1215 case PictureBoxSizeMode.AutoSize: | |
1216 case PictureBoxSizeMode.Normal: | |
1217 imageRect = new Rectangle(Point.Empty, image.Size); | |
1218 break; | |
1219 case PictureBoxSizeMode.CenterImage: | |
1220 imageRect = new Rectangle(Width / 2 - image.Width / 2, Height / 2 - Image.Height / 2, Width, Height); | |
1221 break; | |
1222 case PictureBoxSizeMode.StretchImage: | |
1223 imageRect = new Rectangle(Point.Empty, Size); | |
1224 break; | |
1225 case PictureBoxSizeMode.Zoom: | |
1226 float xrat = (float)Width / (float)image.Width; | |
1227 float yrat = (float)Height / (float)image.Height; | |
1228 float rat = Math.Min(xrat, yrat); | |
1229 SizeF dispsize = new SizeF(image.Width * rat, image.Height * rat); | |
1230 imageRect = Rectangle.Round(new RectangleF(Width / 2f - dispsize.Width / 2f, Height / 2f - dispsize.Height / 2f, dispsize.Width, dispsize.Height)); | |
1231 break; | |
1232 } | |
1233 if (!boundsset) Invalidate(); | |
1234 } | |
1235 protected override void Paint(Graphics g) { | |
1236 if (!Visible) return; | |
1237 base.Paint(g); | |
1238 if (image != null) g.DrawImage(image, imageRect); | |
1239 } | |
1240 } | |
1241 public class FBGListBox : FBGControl { | |
1242 private List<Object> items = new List<object>(); | |
1243 private Object selected = null; | |
1244 private Object highlighted = null; | |
1245 private Boolean hasScrollBar = false; | |
1246 private Boolean hitScrollBar = false; | |
1247 private int offset = 0; | |
1248 private ButtonState buttonUpState = ButtonState.Normal; | |
1249 private ButtonState buttonDownState = ButtonState.Normal; | |
1250 private Converter<Object, String> itemFormatter = null; | |
1251 public Converter<Object, String> ItemFormatter { get { return itemFormatter; } set { itemFormatter = value; Invalidate(); } } | |
1252 public FBGListBox(IFBGContainerControl parent) | |
1253 : base(parent) { | |
1254 BackColor = Color.White; | |
1255 } | |
1256 public void AddItem(Object item) { | |
1257 items.Add(item); | |
1258 Invalidate(); | |
1259 } | |
1260 protected override void Paint(Graphics g) { | |
1261 base.Paint(g); | |
1262 g.DrawRectangle(Pens.DarkBlue, 0, 0, Bounds.Width - 1, Bounds.Height - 1); | |
1263 int lh = (int)Math.Ceiling(SystemFonts.DefaultFont.GetHeight()); | |
1264 int th = lh * items.Count; | |
1265 int y = 2; | |
1266 using (Pen dottedpen = new Pen(Brushes.Black)) { | |
1267 dottedpen.DashStyle = DashStyle.Dot; | |
1268 using (StringFormat sf = new StringFormat(StringFormatFlags.NoWrap)) { | |
1269 for (int i = offset; i < items.Count; i++) { | |
1270 Object item = items[i]; | |
1271 String text = itemFormatter == null ? (item == null ? String.Empty : item.ToString()) : itemFormatter(item); | |
1272 if (item == selected) g.FillRectangle(Brushes.DarkGray, 2, y, Bounds.Width - 4, lh); | |
1273 if (item == highlighted) g.DrawRectangle(dottedpen, 2, y, Bounds.Width - 5, lh - 1); | |
1274 g.DrawString(text, SystemFonts.DefaultFont, SystemBrushes.WindowText, new Rectangle(3, y, Bounds.Width - 6, lh), sf); | |
1275 y += lh; | |
1276 if (y + lh + 2 >= Bounds.Height) break; | |
1277 } | |
1278 } | |
1279 } | |
1280 if (y < th) hasScrollBar = true; | |
1281 if (hasScrollBar) { | |
1282 int xoff = Bounds.Width - 17; | |
1283 using (Brush b = new LinearGradientBrush(new Rectangle(xoff, 0, 17, 1), Color.LightGray, Color.White, LinearGradientMode.Horizontal)) | |
1284 g.FillRectangle(b, xoff, 17, 16, Bounds.Height - 17 - 17); | |
1285 ControlPaint.DrawScrollButton(g, xoff, 1, 16, 16, ScrollButton.Up, buttonUpState); | |
1286 ControlPaint.DrawScrollButton(g, xoff, Bounds.Height - 17, 16, 16, ScrollButton.Down, buttonDownState); | |
1287 g.DrawRectangle(Pens.Black, new Rectangle(xoff, 17 + offset * (Bounds.Height - 17 - 17 - 20) / (items.Count - 1), 15, 20)); | |
1288 } | |
1289 } | |
1290 protected override void MouseDown(Point position, MouseButtons buttons) { | |
1291 if ((buttons & MouseButtons.Left) != 0) { | |
1292 CaptureMouse(true); | |
1293 if (hasScrollBar && position.X > Bounds.Width - 17) { | |
1294 hitScrollBar = true; | |
1295 if (position.Y < 17) { | |
1296 offset--; | |
1297 buttonUpState = ButtonState.Pushed; | |
1298 } else if (position.Y > Bounds.Height - 17) { | |
1299 offset++; | |
1300 buttonDownState = ButtonState.Pushed; | |
1301 } else { | |
1302 offset = (int)Math.Round((position.Y - 17) * (items.Count - 1) / (double)(Bounds.Height - 17 - 17 - 10)); | |
1303 } | |
1304 if (offset < 0) offset = 0; | |
1305 if (offset >= items.Count) offset = items.Count - 1; | |
1306 Invalidate(); | |
1307 } else { | |
1308 MouseHandler(position, buttons); | |
1309 } | |
1310 } | |
1311 } | |
1312 protected override void MouseMove(Point position, MouseButtons buttons) { | |
1313 if (hitScrollBar) { | |
1314 if (position.Y < 17) { | |
1315 } else if (position.Y > Bounds.Height - 17) { | |
1316 } else { | |
1317 offset = (int)Math.Round((position.Y - 17) * (items.Count - 1) / (double)(Bounds.Height - 17 - 17 - 10)); | |
1318 if (offset < 0) offset = 0; | |
1319 if (offset >= items.Count) offset = items.Count - 1; | |
1320 Invalidate(); | |
1321 } | |
1322 return; | |
1323 } | |
1324 MouseHandler(position, buttons); | |
1325 } | |
1326 protected override void MouseUp(Point position, MouseButtons buttons) { | |
1327 if ((buttons & MouseButtons.Left) != 0) { | |
1328 CaptureMouse(false); | |
1329 buttonUpState = buttonDownState = ButtonState.Normal; | |
1330 Invalidate(); | |
1331 if (hitScrollBar) { | |
1332 hitScrollBar = false; | |
1333 return; | |
1334 } | |
1335 } | |
1336 if (hitScrollBar) return; | |
1337 MouseHandler(position, buttons); | |
1338 } | |
1339 private void MouseHandler(Point position, MouseButtons buttons) { | |
1340 if ((buttons & MouseButtons.Left) != 0) { | |
1341 int lh = (int)Math.Ceiling(SystemFonts.DefaultFont.GetHeight()); | |
1342 int i = (position.Y - 2) / lh + offset; | |
1343 if (i < 0) i = 0; | |
1344 if (i >= items.Count) i = items.Count - 1; | |
1345 Boolean changed = false; | |
1346 Object current = items[i]; | |
1347 if (!ReferenceEquals(highlighted, current)) changed = true; | |
1348 highlighted = current; | |
1349 if ((new Rectangle(Point.Empty, Bounds.Size)).Contains(position)) { | |
1350 if (!ReferenceEquals(selected, current)) changed = true; | |
1351 selected = current; | |
1352 } | |
1353 if (changed) Invalidate(); | |
1354 } | |
1355 } | |
1356 } | |
27
5bfc6c68591e
FBGUI: Added numeric up/down control, fix for transparent control background
Ivo Smits <Ivo@UCIS.nl>
parents:
26
diff
changeset
|
1357 public abstract class FBGUpDownControlBase : FBGControl { |
5bfc6c68591e
FBGUI: Added numeric up/down control, fix for transparent control background
Ivo Smits <Ivo@UCIS.nl>
parents:
26
diff
changeset
|
1358 private ButtonState buttonUpState = ButtonState.Normal; |
5bfc6c68591e
FBGUI: Added numeric up/down control, fix for transparent control background
Ivo Smits <Ivo@UCIS.nl>
parents:
26
diff
changeset
|
1359 private ButtonState buttonDownState = ButtonState.Normal; |
5bfc6c68591e
FBGUI: Added numeric up/down control, fix for transparent control background
Ivo Smits <Ivo@UCIS.nl>
parents:
26
diff
changeset
|
1360 public FBGUpDownControlBase(IFBGContainerControl parent) : base(parent) { |
5bfc6c68591e
FBGUI: Added numeric up/down control, fix for transparent control background
Ivo Smits <Ivo@UCIS.nl>
parents:
26
diff
changeset
|
1361 BackColor = Color.White; |
5bfc6c68591e
FBGUI: Added numeric up/down control, fix for transparent control background
Ivo Smits <Ivo@UCIS.nl>
parents:
26
diff
changeset
|
1362 Height = 25; |
5bfc6c68591e
FBGUI: Added numeric up/down control, fix for transparent control background
Ivo Smits <Ivo@UCIS.nl>
parents:
26
diff
changeset
|
1363 } |
5bfc6c68591e
FBGUI: Added numeric up/down control, fix for transparent control background
Ivo Smits <Ivo@UCIS.nl>
parents:
26
diff
changeset
|
1364 protected override void Paint(Graphics g) { |
5bfc6c68591e
FBGUI: Added numeric up/down control, fix for transparent control background
Ivo Smits <Ivo@UCIS.nl>
parents:
26
diff
changeset
|
1365 base.Paint(g); |
5bfc6c68591e
FBGUI: Added numeric up/down control, fix for transparent control background
Ivo Smits <Ivo@UCIS.nl>
parents:
26
diff
changeset
|
1366 g.DrawRectangle(Pens.DarkBlue, 0, 0, Bounds.Width - 1, Bounds.Height - 1); |
5bfc6c68591e
FBGUI: Added numeric up/down control, fix for transparent control background
Ivo Smits <Ivo@UCIS.nl>
parents:
26
diff
changeset
|
1367 int lh = (int)Math.Ceiling(SystemFonts.DefaultFont.GetHeight()); |
5bfc6c68591e
FBGUI: Added numeric up/down control, fix for transparent control background
Ivo Smits <Ivo@UCIS.nl>
parents:
26
diff
changeset
|
1368 String text = SelectedText; |
5bfc6c68591e
FBGUI: Added numeric up/down control, fix for transparent control background
Ivo Smits <Ivo@UCIS.nl>
parents:
26
diff
changeset
|
1369 if (text == null) { |
5bfc6c68591e
FBGUI: Added numeric up/down control, fix for transparent control background
Ivo Smits <Ivo@UCIS.nl>
parents:
26
diff
changeset
|
1370 g.FillRectangle(Brushes.DarkGray, 2, 2, Bounds.Width - 4 - 16, Bounds.Height - 4); |
5bfc6c68591e
FBGUI: Added numeric up/down control, fix for transparent control background
Ivo Smits <Ivo@UCIS.nl>
parents:
26
diff
changeset
|
1371 } else { |
5bfc6c68591e
FBGUI: Added numeric up/down control, fix for transparent control background
Ivo Smits <Ivo@UCIS.nl>
parents:
26
diff
changeset
|
1372 using (StringFormat sf = new StringFormat(StringFormatFlags.NoWrap)) { |
5bfc6c68591e
FBGUI: Added numeric up/down control, fix for transparent control background
Ivo Smits <Ivo@UCIS.nl>
parents:
26
diff
changeset
|
1373 sf.LineAlignment = StringAlignment.Center; |
5bfc6c68591e
FBGUI: Added numeric up/down control, fix for transparent control background
Ivo Smits <Ivo@UCIS.nl>
parents:
26
diff
changeset
|
1374 g.FillRectangle(Brushes.LightGray, 2, 2, Bounds.Width - 4 - 16, Bounds.Height - 4); |
5bfc6c68591e
FBGUI: Added numeric up/down control, fix for transparent control background
Ivo Smits <Ivo@UCIS.nl>
parents:
26
diff
changeset
|
1375 g.DrawString(text, SystemFonts.DefaultFont, SystemBrushes.WindowText, new Rectangle(3, 2, Bounds.Width - 6 - 16, Bounds.Height - 4), sf); |
5bfc6c68591e
FBGUI: Added numeric up/down control, fix for transparent control background
Ivo Smits <Ivo@UCIS.nl>
parents:
26
diff
changeset
|
1376 } |
5bfc6c68591e
FBGUI: Added numeric up/down control, fix for transparent control background
Ivo Smits <Ivo@UCIS.nl>
parents:
26
diff
changeset
|
1377 } |
5bfc6c68591e
FBGUI: Added numeric up/down control, fix for transparent control background
Ivo Smits <Ivo@UCIS.nl>
parents:
26
diff
changeset
|
1378 int xoff = Bounds.Width - 17; |
5bfc6c68591e
FBGUI: Added numeric up/down control, fix for transparent control background
Ivo Smits <Ivo@UCIS.nl>
parents:
26
diff
changeset
|
1379 int he = (Bounds.Height - 2) / 2; |
5bfc6c68591e
FBGUI: Added numeric up/down control, fix for transparent control background
Ivo Smits <Ivo@UCIS.nl>
parents:
26
diff
changeset
|
1380 ControlPaint.DrawScrollButton(g, xoff, 1, 16, he, ScrollButton.Up, buttonUpState); |
5bfc6c68591e
FBGUI: Added numeric up/down control, fix for transparent control background
Ivo Smits <Ivo@UCIS.nl>
parents:
26
diff
changeset
|
1381 ControlPaint.DrawScrollButton(g, xoff, Bounds.Height - he - 1, 16, he, ScrollButton.Down, buttonDownState); |
5bfc6c68591e
FBGUI: Added numeric up/down control, fix for transparent control background
Ivo Smits <Ivo@UCIS.nl>
parents:
26
diff
changeset
|
1382 } |
5bfc6c68591e
FBGUI: Added numeric up/down control, fix for transparent control background
Ivo Smits <Ivo@UCIS.nl>
parents:
26
diff
changeset
|
1383 protected abstract String SelectedText { get; } |
5bfc6c68591e
FBGUI: Added numeric up/down control, fix for transparent control background
Ivo Smits <Ivo@UCIS.nl>
parents:
26
diff
changeset
|
1384 protected override void MouseDown(Point position, MouseButtons buttons) { |
5bfc6c68591e
FBGUI: Added numeric up/down control, fix for transparent control background
Ivo Smits <Ivo@UCIS.nl>
parents:
26
diff
changeset
|
1385 CaptureKeyboard(true); |
5bfc6c68591e
FBGUI: Added numeric up/down control, fix for transparent control background
Ivo Smits <Ivo@UCIS.nl>
parents:
26
diff
changeset
|
1386 if ((buttons & MouseButtons.Left) != 0) { |
5bfc6c68591e
FBGUI: Added numeric up/down control, fix for transparent control background
Ivo Smits <Ivo@UCIS.nl>
parents:
26
diff
changeset
|
1387 CaptureMouse(true); |
5bfc6c68591e
FBGUI: Added numeric up/down control, fix for transparent control background
Ivo Smits <Ivo@UCIS.nl>
parents:
26
diff
changeset
|
1388 if (position.X > Bounds.Width - 17) { |
5bfc6c68591e
FBGUI: Added numeric up/down control, fix for transparent control background
Ivo Smits <Ivo@UCIS.nl>
parents:
26
diff
changeset
|
1389 if (position.Y < Bounds.Height / 2) { |
5bfc6c68591e
FBGUI: Added numeric up/down control, fix for transparent control background
Ivo Smits <Ivo@UCIS.nl>
parents:
26
diff
changeset
|
1390 buttonUpState = ButtonState.Pushed; |
5bfc6c68591e
FBGUI: Added numeric up/down control, fix for transparent control background
Ivo Smits <Ivo@UCIS.nl>
parents:
26
diff
changeset
|
1391 ButtonPressUp(); |
5bfc6c68591e
FBGUI: Added numeric up/down control, fix for transparent control background
Ivo Smits <Ivo@UCIS.nl>
parents:
26
diff
changeset
|
1392 } else { |
5bfc6c68591e
FBGUI: Added numeric up/down control, fix for transparent control background
Ivo Smits <Ivo@UCIS.nl>
parents:
26
diff
changeset
|
1393 buttonDownState = ButtonState.Pushed; |
5bfc6c68591e
FBGUI: Added numeric up/down control, fix for transparent control background
Ivo Smits <Ivo@UCIS.nl>
parents:
26
diff
changeset
|
1394 ButtonPressDown(); |
5bfc6c68591e
FBGUI: Added numeric up/down control, fix for transparent control background
Ivo Smits <Ivo@UCIS.nl>
parents:
26
diff
changeset
|
1395 } |
5bfc6c68591e
FBGUI: Added numeric up/down control, fix for transparent control background
Ivo Smits <Ivo@UCIS.nl>
parents:
26
diff
changeset
|
1396 Invalidate(new Rectangle(Bounds.Width - 16, 0, 16, Bounds.Height)); |
5bfc6c68591e
FBGUI: Added numeric up/down control, fix for transparent control background
Ivo Smits <Ivo@UCIS.nl>
parents:
26
diff
changeset
|
1397 } |
5bfc6c68591e
FBGUI: Added numeric up/down control, fix for transparent control background
Ivo Smits <Ivo@UCIS.nl>
parents:
26
diff
changeset
|
1398 } |
5bfc6c68591e
FBGUI: Added numeric up/down control, fix for transparent control background
Ivo Smits <Ivo@UCIS.nl>
parents:
26
diff
changeset
|
1399 } |
5bfc6c68591e
FBGUI: Added numeric up/down control, fix for transparent control background
Ivo Smits <Ivo@UCIS.nl>
parents:
26
diff
changeset
|
1400 protected override void MouseUp(Point position, MouseButtons buttons) { |
5bfc6c68591e
FBGUI: Added numeric up/down control, fix for transparent control background
Ivo Smits <Ivo@UCIS.nl>
parents:
26
diff
changeset
|
1401 if ((buttons & MouseButtons.Left) != 0) { |
5bfc6c68591e
FBGUI: Added numeric up/down control, fix for transparent control background
Ivo Smits <Ivo@UCIS.nl>
parents:
26
diff
changeset
|
1402 CaptureMouse(false); |
5bfc6c68591e
FBGUI: Added numeric up/down control, fix for transparent control background
Ivo Smits <Ivo@UCIS.nl>
parents:
26
diff
changeset
|
1403 buttonUpState = buttonDownState = ButtonState.Normal; |
5bfc6c68591e
FBGUI: Added numeric up/down control, fix for transparent control background
Ivo Smits <Ivo@UCIS.nl>
parents:
26
diff
changeset
|
1404 Invalidate(new Rectangle(Bounds.Width - 16, 0, 16, Bounds.Height)); |
5bfc6c68591e
FBGUI: Added numeric up/down control, fix for transparent control background
Ivo Smits <Ivo@UCIS.nl>
parents:
26
diff
changeset
|
1405 } |
5bfc6c68591e
FBGUI: Added numeric up/down control, fix for transparent control background
Ivo Smits <Ivo@UCIS.nl>
parents:
26
diff
changeset
|
1406 } |
5bfc6c68591e
FBGUI: Added numeric up/down control, fix for transparent control background
Ivo Smits <Ivo@UCIS.nl>
parents:
26
diff
changeset
|
1407 protected override void KeyDown(Keys key) { |
5bfc6c68591e
FBGUI: Added numeric up/down control, fix for transparent control background
Ivo Smits <Ivo@UCIS.nl>
parents:
26
diff
changeset
|
1408 base.KeyDown(key); |
5bfc6c68591e
FBGUI: Added numeric up/down control, fix for transparent control background
Ivo Smits <Ivo@UCIS.nl>
parents:
26
diff
changeset
|
1409 if (key == Keys.Down) ButtonPressDown(); |
5bfc6c68591e
FBGUI: Added numeric up/down control, fix for transparent control background
Ivo Smits <Ivo@UCIS.nl>
parents:
26
diff
changeset
|
1410 else if (key == Keys.Up) ButtonPressUp(); |
5bfc6c68591e
FBGUI: Added numeric up/down control, fix for transparent control background
Ivo Smits <Ivo@UCIS.nl>
parents:
26
diff
changeset
|
1411 } |
5bfc6c68591e
FBGUI: Added numeric up/down control, fix for transparent control background
Ivo Smits <Ivo@UCIS.nl>
parents:
26
diff
changeset
|
1412 protected abstract void ButtonPressUp(); |
5bfc6c68591e
FBGUI: Added numeric up/down control, fix for transparent control background
Ivo Smits <Ivo@UCIS.nl>
parents:
26
diff
changeset
|
1413 protected abstract void ButtonPressDown(); |
5bfc6c68591e
FBGUI: Added numeric up/down control, fix for transparent control background
Ivo Smits <Ivo@UCIS.nl>
parents:
26
diff
changeset
|
1414 } |
5bfc6c68591e
FBGUI: Added numeric up/down control, fix for transparent control background
Ivo Smits <Ivo@UCIS.nl>
parents:
26
diff
changeset
|
1415 public class FBGDomainUpDown : FBGUpDownControlBase { |
23 | 1416 private List<Object> items = new List<object>(); |
1417 private int selectedIndex = -1; | |
1418 private Converter<Object, String> itemFormatter = null; | |
1419 public Boolean AllowSelectEmpty { get; set; } | |
1420 public Converter<Object, String> ItemFormatter { get { return itemFormatter; } set { itemFormatter = value; Invalidate(); } } | |
1421 public event EventHandler SelectedIndexChanged; | |
27
5bfc6c68591e
FBGUI: Added numeric up/down control, fix for transparent control background
Ivo Smits <Ivo@UCIS.nl>
parents:
26
diff
changeset
|
1422 public FBGDomainUpDown(IFBGContainerControl parent) : base(parent) { } |
23 | 1423 public void AddItem(Object item) { |
1424 items.Add(item); | |
1425 Invalidate(); | |
1426 } | |
1427 public void RemoveItem(Object item) { | |
1428 items.Remove(item); | |
1429 FixSelectedIndex(0); | |
1430 } | |
1431 public void RemoveItem(int index) { | |
1432 items.RemoveAt(index); | |
1433 FixSelectedIndex(0); | |
1434 } | |
1435 public int SelectedIndex { | |
1436 get { return selectedIndex; } | |
1437 set { | |
1438 if (value < -2 || value >= items.Count) throw new ArgumentOutOfRangeException("value", "Value must be between -1 and the number of items minus one"); | |
1439 if (selectedIndex == value) return; | |
1440 selectedIndex = value; | |
1441 Invalidate(); | |
1442 RaiseEvent(SelectedIndexChanged); | |
1443 } | |
1444 } | |
1445 public Object SelectedItem { | |
1446 get { return selectedIndex == -1 ? null : items[selectedIndex]; } | |
1447 set { | |
1448 if (value == null) { | |
1449 SelectedIndex = -1; | |
1450 } else { | |
1451 for (int i = 0; i < items.Count; i++) { | |
1452 if (items[i] == value) { | |
1453 SelectedIndex = i; | |
1454 break; | |
1455 } | |
1456 } | |
1457 } | |
1458 } | |
1459 } | |
27
5bfc6c68591e
FBGUI: Added numeric up/down control, fix for transparent control background
Ivo Smits <Ivo@UCIS.nl>
parents:
26
diff
changeset
|
1460 protected override string SelectedText { |
5bfc6c68591e
FBGUI: Added numeric up/down control, fix for transparent control background
Ivo Smits <Ivo@UCIS.nl>
parents:
26
diff
changeset
|
1461 get { |
5bfc6c68591e
FBGUI: Added numeric up/down control, fix for transparent control background
Ivo Smits <Ivo@UCIS.nl>
parents:
26
diff
changeset
|
1462 if (selectedIndex == -1) return null; |
5bfc6c68591e
FBGUI: Added numeric up/down control, fix for transparent control background
Ivo Smits <Ivo@UCIS.nl>
parents:
26
diff
changeset
|
1463 Object item = items[selectedIndex]; |
5bfc6c68591e
FBGUI: Added numeric up/down control, fix for transparent control background
Ivo Smits <Ivo@UCIS.nl>
parents:
26
diff
changeset
|
1464 if (itemFormatter != null) return itemFormatter(item); |
5bfc6c68591e
FBGUI: Added numeric up/down control, fix for transparent control background
Ivo Smits <Ivo@UCIS.nl>
parents:
26
diff
changeset
|
1465 if (item == null) return null; |
5bfc6c68591e
FBGUI: Added numeric up/down control, fix for transparent control background
Ivo Smits <Ivo@UCIS.nl>
parents:
26
diff
changeset
|
1466 return item.ToString(); |
5bfc6c68591e
FBGUI: Added numeric up/down control, fix for transparent control background
Ivo Smits <Ivo@UCIS.nl>
parents:
26
diff
changeset
|
1467 } |
5bfc6c68591e
FBGUI: Added numeric up/down control, fix for transparent control background
Ivo Smits <Ivo@UCIS.nl>
parents:
26
diff
changeset
|
1468 } |
23 | 1469 private void FixSelectedIndex(int change) { |
1470 int value = selectedIndex; | |
1471 if (value == 0 && change == -1 && !AllowSelectEmpty) change = 0; | |
1472 value += change; | |
1473 if (value < -1) value = -1; | |
1474 if (value >= items.Count) value = items.Count - 1; | |
1475 SelectedIndex = value; | |
1476 } | |
27
5bfc6c68591e
FBGUI: Added numeric up/down control, fix for transparent control background
Ivo Smits <Ivo@UCIS.nl>
parents:
26
diff
changeset
|
1477 protected override void ButtonPressDown() { |
5bfc6c68591e
FBGUI: Added numeric up/down control, fix for transparent control background
Ivo Smits <Ivo@UCIS.nl>
parents:
26
diff
changeset
|
1478 FixSelectedIndex(1); |
5bfc6c68591e
FBGUI: Added numeric up/down control, fix for transparent control background
Ivo Smits <Ivo@UCIS.nl>
parents:
26
diff
changeset
|
1479 } |
5bfc6c68591e
FBGUI: Added numeric up/down control, fix for transparent control background
Ivo Smits <Ivo@UCIS.nl>
parents:
26
diff
changeset
|
1480 protected override void ButtonPressUp() { |
5bfc6c68591e
FBGUI: Added numeric up/down control, fix for transparent control background
Ivo Smits <Ivo@UCIS.nl>
parents:
26
diff
changeset
|
1481 FixSelectedIndex(-1); |
5bfc6c68591e
FBGUI: Added numeric up/down control, fix for transparent control background
Ivo Smits <Ivo@UCIS.nl>
parents:
26
diff
changeset
|
1482 } |
5bfc6c68591e
FBGUI: Added numeric up/down control, fix for transparent control background
Ivo Smits <Ivo@UCIS.nl>
parents:
26
diff
changeset
|
1483 } |
5bfc6c68591e
FBGUI: Added numeric up/down control, fix for transparent control background
Ivo Smits <Ivo@UCIS.nl>
parents:
26
diff
changeset
|
1484 public class FBGNumericUpDown : FBGUpDownControlBase { |
5bfc6c68591e
FBGUI: Added numeric up/down control, fix for transparent control background
Ivo Smits <Ivo@UCIS.nl>
parents:
26
diff
changeset
|
1485 private int minimum = 0; |
5bfc6c68591e
FBGUI: Added numeric up/down control, fix for transparent control background
Ivo Smits <Ivo@UCIS.nl>
parents:
26
diff
changeset
|
1486 private int maximum = 0; |
5bfc6c68591e
FBGUI: Added numeric up/down control, fix for transparent control background
Ivo Smits <Ivo@UCIS.nl>
parents:
26
diff
changeset
|
1487 private int value = 0; |
5bfc6c68591e
FBGUI: Added numeric up/down control, fix for transparent control background
Ivo Smits <Ivo@UCIS.nl>
parents:
26
diff
changeset
|
1488 public event EventHandler SelectedValueChanged; |
5bfc6c68591e
FBGUI: Added numeric up/down control, fix for transparent control background
Ivo Smits <Ivo@UCIS.nl>
parents:
26
diff
changeset
|
1489 public FBGNumericUpDown(IFBGContainerControl parent) : base(parent) { } |
5bfc6c68591e
FBGUI: Added numeric up/down control, fix for transparent control background
Ivo Smits <Ivo@UCIS.nl>
parents:
26
diff
changeset
|
1490 public int Value { |
5bfc6c68591e
FBGUI: Added numeric up/down control, fix for transparent control background
Ivo Smits <Ivo@UCIS.nl>
parents:
26
diff
changeset
|
1491 get { return value; } |
5bfc6c68591e
FBGUI: Added numeric up/down control, fix for transparent control background
Ivo Smits <Ivo@UCIS.nl>
parents:
26
diff
changeset
|
1492 set { if (this.value == value) return; this.value = value; Invalidate(); RaiseEvent(SelectedValueChanged); } |
23 | 1493 } |
27
5bfc6c68591e
FBGUI: Added numeric up/down control, fix for transparent control background
Ivo Smits <Ivo@UCIS.nl>
parents:
26
diff
changeset
|
1494 public int Minimum { |
5bfc6c68591e
FBGUI: Added numeric up/down control, fix for transparent control background
Ivo Smits <Ivo@UCIS.nl>
parents:
26
diff
changeset
|
1495 get { return minimum; } |
5bfc6c68591e
FBGUI: Added numeric up/down control, fix for transparent control background
Ivo Smits <Ivo@UCIS.nl>
parents:
26
diff
changeset
|
1496 set { minimum = value; if (this.value < minimum) this.Value = minimum; } |
5bfc6c68591e
FBGUI: Added numeric up/down control, fix for transparent control background
Ivo Smits <Ivo@UCIS.nl>
parents:
26
diff
changeset
|
1497 } |
5bfc6c68591e
FBGUI: Added numeric up/down control, fix for transparent control background
Ivo Smits <Ivo@UCIS.nl>
parents:
26
diff
changeset
|
1498 public int Maximum { |
5bfc6c68591e
FBGUI: Added numeric up/down control, fix for transparent control background
Ivo Smits <Ivo@UCIS.nl>
parents:
26
diff
changeset
|
1499 get { return maximum; } |
5bfc6c68591e
FBGUI: Added numeric up/down control, fix for transparent control background
Ivo Smits <Ivo@UCIS.nl>
parents:
26
diff
changeset
|
1500 set { maximum = value; if (this.value > maximum) this.Value = maximum; } |
23 | 1501 } |
27
5bfc6c68591e
FBGUI: Added numeric up/down control, fix for transparent control background
Ivo Smits <Ivo@UCIS.nl>
parents:
26
diff
changeset
|
1502 public int Step { get; set; } |
5bfc6c68591e
FBGUI: Added numeric up/down control, fix for transparent control background
Ivo Smits <Ivo@UCIS.nl>
parents:
26
diff
changeset
|
1503 protected override string SelectedText { |
5bfc6c68591e
FBGUI: Added numeric up/down control, fix for transparent control background
Ivo Smits <Ivo@UCIS.nl>
parents:
26
diff
changeset
|
1504 get { return value.ToString(); } |
23 | 1505 } |
27
5bfc6c68591e
FBGUI: Added numeric up/down control, fix for transparent control background
Ivo Smits <Ivo@UCIS.nl>
parents:
26
diff
changeset
|
1506 protected override void ButtonPressDown() { |
5bfc6c68591e
FBGUI: Added numeric up/down control, fix for transparent control background
Ivo Smits <Ivo@UCIS.nl>
parents:
26
diff
changeset
|
1507 Value = Math.Max(minimum, value - Step); |
5bfc6c68591e
FBGUI: Added numeric up/down control, fix for transparent control background
Ivo Smits <Ivo@UCIS.nl>
parents:
26
diff
changeset
|
1508 } |
5bfc6c68591e
FBGUI: Added numeric up/down control, fix for transparent control background
Ivo Smits <Ivo@UCIS.nl>
parents:
26
diff
changeset
|
1509 protected override void ButtonPressUp() { |
5bfc6c68591e
FBGUI: Added numeric up/down control, fix for transparent control background
Ivo Smits <Ivo@UCIS.nl>
parents:
26
diff
changeset
|
1510 Value = Math.Min(maximum, value + Step); |
23 | 1511 } |
1512 } | |
1513 public interface IFBGTreeParent { | |
1514 FBGTreeView TreeView { get; } | |
1515 int Depth { get; } | |
1516 void AddChild(FBGTreeNode node); | |
1517 void RemoveChild(FBGTreeNode node); | |
1518 } | |
1519 public class FBGTreeNode : IFBGTreeParent { | |
1520 private List<FBGTreeNode> children = new List<FBGTreeNode>(); | |
1521 private Boolean expanded = true; | |
1522 private Boolean hasCheckBox = false; | |
1523 private Boolean isChecked = false; | |
1524 private Object item; | |
1525 | |
1526 public FBGTreeView TreeView { get; private set; } | |
1527 public int Depth { get; private set; } | |
1528 public Object Tag { get; set; } | |
1529 public IFBGTreeParent Parent { get; private set; } | |
1530 | |
1531 public IList<FBGTreeNode> Children { get { return children.AsReadOnly(); } } | |
1532 | |
1533 public Object Item { | |
1534 get { return item; } | |
1535 set { | |
1536 item = value; | |
1537 Invalidate(); | |
1538 } | |
1539 } | |
1540 public Boolean Expanded { | |
1541 get { return expanded; } | |
1542 set { | |
1543 if (expanded == value) return; | |
1544 expanded = value; | |
1545 UpdateTree(); | |
1546 } | |
1547 } | |
1548 public Boolean HasCheckBox { | |
1549 get { return hasCheckBox; } | |
1550 set { | |
1551 if (hasCheckBox == value) return; | |
1552 hasCheckBox = value; | |
1553 Invalidate(); | |
1554 } | |
1555 } | |
1556 public Boolean Checked { | |
1557 get { return isChecked; } | |
1558 set { | |
1559 if (isChecked == value) return; | |
1560 isChecked = value; | |
1561 Invalidate(); | |
1562 if (TreeView != null) TreeView.RaiseNodeCheckedChanged(this); | |
1563 } | |
1564 } | |
1565 | |
1566 public FBGTreeNode(IFBGTreeParent parent, Object item) { | |
1567 this.TreeView = parent.TreeView; | |
1568 this.Depth = parent.Depth + 1; | |
1569 this.Parent = parent; | |
1570 this.item = item; | |
1571 parent.AddChild(this); | |
1572 } | |
1573 | |
1574 public void Remove() { | |
1575 Parent.RemoveChild(this); | |
1576 } | |
1577 void IFBGTreeParent.AddChild(FBGTreeNode node) { | |
1578 children.Add(node); | |
1579 if (Expanded) UpdateTree(); | |
1580 else Invalidate(); | |
1581 } | |
1582 void IFBGTreeParent.RemoveChild(FBGTreeNode node) { | |
1583 children.Remove(node); | |
1584 TreeView.ReleaseNodeFromTree(node); | |
1585 if (Expanded) UpdateTree(); | |
1586 else Invalidate(); | |
1587 } | |
1588 public void Invalidate() { | |
1589 if (TreeView != null) TreeView.Invalidate(this); | |
1590 } | |
1591 private void UpdateTree() { | |
1592 if (TreeView != null) TreeView.UpdateView(); | |
1593 } | |
1594 public FBGTreeNode AddNode(Object item) { | |
1595 return new FBGTreeNode(this, item); | |
1596 } | |
1597 } | |
1598 public class FBGTreeView : FBGControl, IFBGTreeParent { | |
1599 private List<FBGTreeNode> items = new List<FBGTreeNode>(); | |
1600 private List<FBGTreeNode> itemsView = new List<FBGTreeNode>(); | |
1601 private FBGTreeNode selected = null; | |
1602 private FBGTreeNode highlighted = null; | |
1603 private Boolean hasScrollBar = false; | |
1604 private Boolean hitScrollBar = false; | |
1605 private int offset = 0; | |
1606 private ButtonState buttonUpState = ButtonState.Normal; | |
1607 private ButtonState buttonDownState = ButtonState.Normal; | |
1608 private Converter<Object, String> itemFormatter = null; | |
1609 | |
1610 public Converter<Object, String> ItemFormatter { get { return itemFormatter; } set { itemFormatter = value; Invalidate(); } } | |
1611 public FBGTreeNode SelectedNode { get { return selected; } set { if (selected != value) { selected = value; Invalidate(); RaiseEvent(SelectedNodeChanged); } } } | |
1612 public IList<FBGTreeNode> Nodes { get { return items.AsReadOnly(); } } | |
1613 | |
1614 public event EventHandler SelectedNodeChanged; | |
1615 public event EventHandler NodeCheckedChanged; | |
1616 | |
1617 public FBGTreeView(IFBGContainerControl parent) : base(parent) { | |
1618 BackColor = Color.White; | |
1619 } | |
1620 FBGTreeView IFBGTreeParent.TreeView { get { return this; } } | |
1621 int IFBGTreeParent.Depth { get { return -1; } } | |
1622 void IFBGTreeParent.AddChild(FBGTreeNode node) { | |
1623 items.Add(node); | |
1624 UpdateView(); | |
1625 } | |
1626 void IFBGTreeParent.RemoveChild(FBGTreeNode node) { | |
1627 items.Remove(node); | |
1628 ReleaseNodeFromTree(node); | |
1629 UpdateView(); | |
1630 } | |
1631 public FBGTreeNode AddNode(Object item) { return new FBGTreeNode(this, item); } | |
1632 internal void ReleaseNodeFromTree(FBGTreeNode node) { | |
1633 if (highlighted == node) highlighted = null; | |
1634 if (selected == node) SelectedNode = null; | |
1635 } | |
1636 internal void RaiseNodeCheckedChanged(FBGTreeNode node) { | |
1637 RaiseEvent(NodeCheckedChanged); | |
1638 } | |
1639 internal void UpdateView() { | |
1640 List<FBGTreeNode> newView = new List<FBGTreeNode>(); | |
1641 Stack<Queue<FBGTreeNode>> stack = new Stack<Queue<FBGTreeNode>>(); | |
1642 stack.Push(new Queue<FBGTreeNode>(items)); | |
1643 while (stack.Count > 0) { | |
1644 Queue<FBGTreeNode> list = stack.Peek(); | |
1645 if (list.Count == 0) { | |
1646 stack.Pop(); | |
1647 continue; | |
1648 } | |
1649 FBGTreeNode item = list.Dequeue(); | |
1650 newView.Add(item); | |
1651 if (item.Expanded) stack.Push(new Queue<FBGTreeNode>(item.Children)); | |
1652 } | |
1653 itemsView = newView; | |
1654 Invalidate(); | |
1655 } | |
1656 internal void Invalidate(FBGTreeNode node) { | |
1657 int i = itemsView.IndexOf(node); | |
1658 if (i == -1) return; | |
1659 int lh = (int)Math.Ceiling(SystemFonts.DefaultFont.GetHeight() / 2.0) * 2; | |
1660 Invalidate(new Rectangle(1, i * lh, Bounds.Width - 1, lh)); | |
1661 } | |
1662 protected override void Paint(Graphics g) { | |
1663 base.Paint(g); | |
1664 | |
1665 int lh = (int)Math.Ceiling(SystemFonts.DefaultFont.GetHeight() / 2.0) * 2; | |
1666 int th = lh * itemsView.Count; | |
1667 hasScrollBar = offset > 0 || th + 2 > Bounds.Height; | |
1668 int y = 2; | |
1669 using (Pen dottedpen = new Pen(Brushes.Black)) { | |
1670 dottedpen.DashStyle = DashStyle.Dot; | |
1671 using (StringFormat sf = new StringFormat(StringFormatFlags.NoWrap)) { | |
1672 int lw = Bounds.Width - 2; | |
1673 if (hasScrollBar) lw -= 17; | |
1674 for (int i = offset; i < itemsView.Count; i++) { | |
1675 FBGTreeNode item = itemsView[i]; | |
1676 if (y + 2 < Bounds.Height) { | |
1677 Object obj = item.Item; | |
1678 String text = itemFormatter == null ? (obj == null ? String.Empty : obj.ToString()) : itemFormatter(obj); | |
1679 if (item == selected) g.FillRectangle(Brushes.DarkGray, 2, y, lw - 2, lh); | |
1680 if (item == highlighted) g.DrawRectangle(dottedpen, 2, y, lw - 3, lh - 1); | |
1681 int x = 3 + 19 * item.Depth + 14; | |
1682 if (item.HasCheckBox) { | |
1683 x += 2; | |
1684 ControlPaint.DrawCheckBox(g, x, y, lh, lh, item.Checked ? ButtonState.Checked : ButtonState.Normal); | |
1685 x += lh + 1; | |
1686 } | |
1687 g.DrawString(text, SystemFonts.DefaultFont, SystemBrushes.WindowText, new Rectangle(x, y, lw - x, lh), sf); | |
1688 } | |
1689 int upto = y + 2 + 4 - 8; | |
1690 for (int j = i - 1; j >= 0; j--) { | |
1691 if (itemsView[j].Depth < item.Depth) { | |
1692 break; | |
1693 } | |
1694 if (itemsView[j].Depth == item.Depth) { | |
1695 if (itemsView[j].Children.Count > 0) { | |
1696 upto = 2 + lh * (j - offset) + 10; | |
1697 } else { | |
1698 upto = 2 + lh * (j - offset) + 6; | |
1699 } | |
1700 break; | |
1701 } | |
1702 if (j <= offset) { | |
1703 upto = 2 + 2 + 4 - 8; | |
1704 break; | |
1705 } | |
1706 } | |
1707 if (item.Children.Count > 0) { | |
1708 g.DrawRectangle(Pens.Black, 3 + 19 * item.Depth, y + 2, 8, 8); | |
1709 g.DrawLine(Pens.Black, 3 + 19 * item.Depth + 2, y + 2 + 4, 3 + 19 * item.Depth + 6, y + 2 + 4); | |
1710 if (!item.Expanded) g.DrawLine(Pens.Black, 3 + 19 * item.Depth + 4, y + 4, 3 + 19 * item.Depth + 4, y + 2 + 6); | |
1711 | |
1712 g.DrawLine(dottedpen, 3 + 19 * item.Depth + 8, y + 2 + 4, 3 + 19 * item.Depth + 14, y + 2 + 4); | |
1713 g.DrawLine(dottedpen, 3 + 19 * item.Depth + 4, y + 2 + 4 - 6, 3 + 19 * item.Depth + 4, upto); | |
1714 } else { | |
1715 g.DrawLine(dottedpen, 3 + 19 * item.Depth + 4, y + 2 + 4, 3 + 19 * item.Depth + 14, y + 2 + 4); | |
1716 g.DrawLine(dottedpen, 3 + 19 * item.Depth + 4, y + 2 + 4 - 2, 3 + 19 * item.Depth + 4, upto); | |
1717 } | |
1718 y += lh; | |
1719 //if (y + lh + 2 >= Bounds.Height && item.Depth == 0) break; | |
1720 if (y + 2 >= Bounds.Height && item.Depth == 0) break; | |
1721 } | |
1722 } | |
1723 } | |
1724 //if (y < th) hasScrollBar = true; | |
1725 //hasScrollBar = true; | |
1726 if (hasScrollBar) { | |
1727 int xoff = Bounds.Width - 17; | |
1728 using (Brush b = new LinearGradientBrush(new Rectangle(xoff, 0, 17, 1), Color.LightGray, Color.White, LinearGradientMode.Horizontal)) | |
1729 g.FillRectangle(b, xoff, 17, 16, Bounds.Height - 17 - 17); | |
1730 ControlPaint.DrawScrollButton(g, xoff, 1, 16, 16, ScrollButton.Up, buttonUpState); | |
1731 ControlPaint.DrawScrollButton(g, xoff, Bounds.Height - 17, 16, 16, ScrollButton.Down, buttonDownState); | |
1732 g.DrawRectangle(Pens.Black, new Rectangle(xoff, 17 + offset * (Bounds.Height - 17 - 17 - 20) / (itemsView.Count - 1), 15, 20)); | |
1733 } | |
1734 | |
1735 g.DrawRectangle(Pens.DarkBlue, 0, 0, Bounds.Width - 1, Bounds.Height - 1); | |
1736 } | |
1737 protected override void MouseDown(Point position, MouseButtons buttons) { | |
1738 CaptureKeyboard(true); | |
1739 if ((buttons & MouseButtons.Left) != 0) { | |
1740 CaptureMouse(true); | |
1741 if (hasScrollBar && position.X > Bounds.Width - 17) { | |
1742 hitScrollBar = true; | |
1743 if (position.Y < 17) { | |
1744 offset--; | |
1745 buttonUpState = ButtonState.Pushed; | |
1746 } else if (position.Y > Bounds.Height - 17) { | |
1747 offset++; | |
1748 buttonDownState = ButtonState.Pushed; | |
1749 } else { | |
1750 offset = (int)Math.Round((position.Y - 17) * (itemsView.Count - 1) / (double)(Bounds.Height - 17 - 17 - 10)); | |
1751 } | |
1752 if (offset < 0) offset = 0; | |
1753 if (offset >= itemsView.Count) offset = itemsView.Count - 1; | |
1754 Invalidate(); | |
1755 } else { | |
1756 MouseHandler(position, buttons, true); | |
1757 } | |
1758 } | |
1759 } | |
1760 protected override void MouseMove(Point position, MouseButtons buttons) { | |
1761 if (hitScrollBar) { | |
1762 if (position.Y < 17) { | |
1763 } else if (position.Y > Bounds.Height - 17) { | |
1764 } else { | |
1765 offset = (int)Math.Round((position.Y - 17) * (itemsView.Count - 1) / (double)(Bounds.Height - 17 - 17 - 10)); | |
1766 if (offset < 0) offset = 0; | |
1767 if (offset >= itemsView.Count) offset = itemsView.Count - 1; | |
1768 Invalidate(); | |
1769 } | |
1770 return; | |
1771 } | |
1772 MouseHandler(position, buttons, false); | |
1773 } | |
1774 protected override void MouseUp(Point position, MouseButtons buttons) { | |
1775 if ((buttons & MouseButtons.Left) != 0) { | |
1776 CaptureMouse(false); | |
1777 buttonUpState = buttonDownState = ButtonState.Normal; | |
1778 Invalidate(); | |
1779 if (hitScrollBar) { | |
1780 hitScrollBar = false; | |
1781 return; | |
1782 } | |
1783 } | |
1784 if (hitScrollBar) return; | |
1785 MouseHandler(position, buttons, false); | |
1786 } | |
1787 private void MouseHandler(Point position, MouseButtons buttons, Boolean down) { | |
1788 if ((buttons & MouseButtons.Left) != 0 && itemsView.Count > 0) { | |
1789 int lh = (int)Math.Ceiling(SystemFonts.DefaultFont.GetHeight() / 2.0) * 2; | |
1790 int i = (position.Y - 2) / lh + offset; | |
1791 if (i < 0) i = 0; | |
1792 if (i >= itemsView.Count) i = itemsView.Count - 1; | |
1793 Boolean changed = false; | |
1794 FBGTreeNode current = itemsView[i]; | |
1795 if (!ReferenceEquals(highlighted, current)) changed = true; | |
1796 highlighted = current; | |
1797 if (current.Children.Count > 0 && (new Rectangle(3 + 19 * current.Depth, 2 + lh * (i - offset) + 2, 8, 8)).Contains(position)) { | |
1798 if (down) current.Expanded = !current.Expanded; | |
1799 } else if (current.HasCheckBox && (new Rectangle(3 + 19 * current.Depth + 14 + 2, 2 + lh * (i - offset), lh, lh)).Contains(position)) { | |
1800 if (down) current.Checked = !current.Checked; | |
1801 } else if ((new Rectangle(Point.Empty, Bounds.Size)).Contains(position)) { | |
1802 SelectedNode = current; | |
1803 changed = false; | |
1804 } | |
1805 if (changed) Invalidate(); | |
1806 } | |
1807 } | |
1808 protected override void KeyDown(Keys key) { | |
1809 base.KeyDown(key); | |
1810 if (key == Keys.Up) { | |
1811 int i = itemsView.IndexOf(selected); | |
1812 i--; | |
1813 if (i >= 0) SelectAndScrollIntoView(itemsView[i]); | |
1814 } else if (key == Keys.Down) { | |
1815 int i = itemsView.IndexOf(selected); | |
1816 i++; | |
1817 if (i < itemsView.Count) SelectAndScrollIntoView(itemsView[i]); | |
1818 } else if (key == Keys.Left && selected != null) { | |
1819 if (selected.Expanded && selected.Children.Count > 0) { | |
1820 selected.Expanded = false; | |
1821 } else { | |
1822 FBGTreeNode tn = selected.Parent as FBGTreeNode; | |
1823 if (tn != null) SelectAndScrollIntoView(tn); | |
1824 } | |
1825 } else if (key == Keys.Right && selected != null) { | |
1826 if (!selected.Expanded && selected.Children.Count > 0) { | |
1827 selected.Expanded = true; | |
1828 } else if (selected.Children.Count > 0) { | |
1829 SelectAndScrollIntoView(selected.Children[0]); | |
1830 } | |
1831 } else if (key == Keys.Space && selected != null) { | |
1832 if (selected.HasCheckBox) selected.Checked = !selected.Checked; | |
1833 } | |
1834 } | |
1835 private void SelectAndScrollIntoView(FBGTreeNode tn) { | |
1836 int i = itemsView.IndexOf(tn); | |
1837 if (i == -1) { | |
1838 for (FBGTreeNode tp = tn.Parent as FBGTreeNode; tp != null; tp = tp.Parent as FBGTreeNode) if (!tp.Expanded) tp.Expanded = true; | |
1839 i = itemsView.IndexOf(tn); | |
1840 } | |
1841 if (i != -1) { | |
1842 int lh = (int)Math.Ceiling(SystemFonts.DefaultFont.GetHeight() / 2.0) * 2; | |
1843 if (i < offset) offset = i; | |
1844 offset = Math.Max(offset, i - Bounds.Height / lh + 1); | |
1845 } | |
1846 highlighted = tn; | |
1847 SelectedNode = tn; | |
1848 } | |
1849 } | |
1850 } |