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