00001 namespace Grendel.Base { 00002 using System; 00003 using System.Drawing; 00004 using System.Drawing.Text; 00005 using System.Drawing.Drawing2D; 00006 using System.Windows.Forms; 00007 using System.Diagnostics; 00008 using System.Collections.Generic; 00009 using System.Reflection; 00010 using System.IO; 00011 00012 public delegate void AnimationEvent(); 00013 public delegate void PaintEvent(); 00014 public delegate void MouseEvent(MouseButtons buttons, Position absolutePosition); 00015 00021 public interface ICanvasImplementation { 00022 void DrawLine(WorldMatrix m, float x1, float y1, float x2, float y2, float width, Color color); 00023 void FillTriangle(WorldMatrix m, float x1, float y1, float x2, float y2, float x3, float y3, 00024 Color color, bool margin); 00025 void DrawText(WorldMatrix m, float x, float y, string text, Color color, Font font); 00026 void Display(int width, int height, int msecAnimationInterval); 00027 void DrawBitmap(WorldMatrix m, float x, float y, IBitmap bitmap); 00028 void DrawCircle(WorldMatrix m, float x, float y, float r, float lineWidth, Color color); 00029 void DrawBezier(WorldMatrix m, float p0x, float p0y, float p1x, float p1y, 00030 float p2x, float p2y, float p3x, float p3y, 00031 float width, Color color); 00032 double TextWidth(Font f, string text); 00033 double TextHeight(Font f, string text); 00037 IDialogBuilder DialogBuilder {get;} 00038 IBitmap LoadBitmap(Stream bitmapStream); 00039 void Invalidate(); 00044 event PaintEvent Repainting; 00048 event AnimationEvent Animation; 00052 event MouseEvent MouseInteraction; 00053 } 00054 00055 [Flags] 00056 public enum StandardButtons { 00057 OK = 0x1, 00058 Cancel = 0x2, 00059 None = 0 00060 } 00061 00066 public interface IDialogBuilder { 00071 void AddButton(string key); 00076 void AddInput(string key, object initialValue); 00081 void AddSeparator(); 00087 string ExecuteDialog(int minimalWidth, StandardButtons stdButtons); 00092 object GetValue(string key); 00096 IEnumerable<string> Keys {get;} 00097 } 00098 00099 public interface IBitmap { 00100 void Dispose(); 00101 int Width {get;} 00102 int Height {get;} 00103 } 00104 00108 public class WFormsCanvasImplementation : ICanvasImplementation { 00109 private Control form = null; 00110 private Timer timer = new Timer(); 00111 private Graphics painter = null; 00112 00113 public event PaintEvent Repainting; 00114 public event AnimationEvent Animation; 00115 public event MouseEvent MouseInteraction; 00116 00117 public WFormsCanvasImplementation() {} 00118 00119 internal WFormsCanvasImplementation(Control c, int msecAnimationInterval) { 00120 form = c; 00121 form.Paint += this.OnPaint; 00122 form.MouseDown += this.OnMouseDown; 00123 timer.Tick += this.OnTick; 00124 timer.Interval = msecAnimationInterval; 00125 timer.Start(); 00126 } 00127 00128 public void Display (int width, int height, int msecAnimationInterval) { 00129 if (form != null) 00130 return; 00131 form = new DBForm(); 00132 form.Width = width; 00133 form.Height = height; 00134 form.BackColor = System.Drawing.Color.White; 00135 form.Paint += this.OnPaint; 00136 form.MouseDown += this.OnMouseDown; 00137 form.Text = "Drawing area"; 00138 timer.Tick += this.OnTick; 00139 timer.Interval = msecAnimationInterval; 00140 timer.Start(); 00141 Application.Run((Form)form); 00142 } 00143 00144 internal System.Drawing.Color ToDrawingColor(Color c) { 00145 return System.Drawing.Color.FromArgb(255 - c.Transparence, c.RedComponent, 00146 c.GreenComponent, c.BlueComponent); 00147 } 00148 00149 internal void Transform(WorldMatrix wm, Graphics g) { 00150 double [,] am = wm.ToArrayMatrix(); 00151 Matrix m = new Matrix((float)am[0,0], (float)am[0,1], (float)am[1,0], (float)am[1,1], 00152 (float)am[2,0], (float)am[2,1]); 00153 g.Transform = m; 00154 } 00155 00156 internal System.Drawing.Font ToDrawingFont(Font f) { 00157 System.Drawing.FontStyle style; 00158 if (f.Style == FontStyle.Italic || f.Style == FontStyle.BoldItalic) 00159 style = System.Drawing.FontStyle.Italic; 00160 else 00161 style = System.Drawing.FontStyle.Regular; 00162 if (f.Style == FontStyle.Bold || f.Style == FontStyle.BoldItalic) 00163 style |= System.Drawing.FontStyle.Bold; 00164 00165 FontFamily family = null; 00166 if(f.IsGeneric) 00167 switch(f.GenericFamily) { 00168 case GenericFontFamily.Serif: 00169 family = new FontFamily(GenericFontFamilies.Serif); 00170 break; 00171 case GenericFontFamily.SansSerif: 00172 family = new FontFamily(GenericFontFamilies.SansSerif); 00173 break; 00174 case GenericFontFamily.Monospace: 00175 family = new FontFamily(GenericFontFamilies.Monospace); 00176 break; 00177 default: 00178 Debug.Fail("Unknown generic fontfamily"); 00179 break; 00180 } 00181 else 00182 family = new FontFamily(f.FontFamily); 00183 return new System.Drawing.Font(family, (float)f.Size, style, GraphicsUnit.Pixel); 00184 } 00185 00186 public void DrawLine (WorldMatrix m, float x1, float y1, float x2, float y2, float width, Color color) { 00187 if(painter != null) { 00188 Transform(m, painter); 00189 painter.DrawLine(new Pen(ToDrawingColor(color), width), x1, y1, x2, y2); 00190 } 00191 } 00192 00193 public void DrawBezier(WorldMatrix m, float p0x, float p0y, float p1x, float p1y, 00194 float p2x, float p2y, float p3x, float p3y, 00195 float width, Color color) { 00196 if(painter != null) { 00197 Transform(m, painter); 00198 painter.DrawBezier(new Pen(ToDrawingColor(color), width), p0x, p0y, p1x, p1y, 00199 p2x, p2y, p3x, p3y); 00200 } 00201 } 00202 00203 public void DrawCircle (WorldMatrix m, float x, float y, float r, float lineWidth, Color color) 00204 { 00205 if(painter != null) { 00206 Transform(m, painter); 00207 painter.DrawEllipse(new Pen(ToDrawingColor(color), lineWidth), x, y, 2*r, 2*r); 00208 } 00209 } 00210 00211 00212 public void DrawText (WorldMatrix m, float x, float y, string text, Color color, Font font) { 00213 if(painter != null) { 00214 Brush b = new SolidBrush(ToDrawingColor(color)); 00215 System.Drawing.Font f = ToDrawingFont(font); 00216 Transform(m, painter); 00217 painter.DrawString(text, f, b, (float)x, (float) y); 00218 } 00219 } 00220 00221 public void FillTriangle (WorldMatrix m, float x1, float y1, float x2, float y2, float x3, float y3, 00222 Color color, bool margin) { 00223 if(painter != null) { 00224 Brush b = new SolidBrush(ToDrawingColor(color)); 00225 PointF[] pts = new PointF[]{new PointF(x1, y1), new PointF(x2, y2), new PointF(x3, y3)}; 00226 Transform(m, painter); 00227 painter.FillPolygon(b, pts); 00228 if(margin) 00229 painter.DrawPolygon(new Pen(new SolidBrush(ToDrawingColor(color)), 0.5f), pts); 00230 } 00231 00232 } 00233 00234 public void DrawBitmap (WorldMatrix m, float x, float y, IBitmap bitmap) { 00235 if (painter == null) 00236 return; 00237 Transform(m, painter); 00238 painter.DrawImage(((WFBitmap)bitmap).InternalBitmap, x, y); 00239 } 00240 00241 00242 public IBitmap LoadBitmap (Stream bitmapStream) { 00243 return WFBitmap.LoadFromFile(bitmapStream); 00244 } 00245 00246 00247 public void Invalidate() { 00248 if(form != null) 00249 form.Invalidate(); 00250 } 00251 00252 00253 private void OnPaint(object sender, PaintEventArgs e) { 00254 painter = e.Graphics; 00255 painter.SmoothingMode = SmoothingMode.AntiAlias; 00256 Repainting(); 00257 painter = null; 00258 } 00259 00260 private void OnMouseDown(object sender, MouseEventArgs e) { 00261 MouseInteraction( 00262 new MouseButtons(e.Button == System.Windows.Forms.MouseButtons.Left, 00263 e.Button == System.Windows.Forms.MouseButtons.Middle, 00264 e.Button == System.Windows.Forms.MouseButtons.Right 00265 ), 00266 new Position(e.X, e.Y) 00267 ); 00268 } 00269 00270 private void OnTick(object sender, EventArgs e) { 00271 if(Animation != null) 00272 Animation(); 00273 } 00274 00275 public IDialogBuilder DialogBuilder { 00276 get { return new WFormDialogBuilder(); } 00277 } 00278 00279 00280 public double TextHeight (Font f, string text) { 00281 using (Form pf = new Form()) { 00282 using (Graphics p = pf.CreateGraphics()) { 00283 return p.MeasureString(text, ToDrawingFont(f)).Height; 00284 } 00285 } 00286 } 00287 00288 public double TextWidth (Font f, string text) { 00289 using (Form pf = new Form()) { 00290 using (Graphics p = pf.CreateGraphics()) { 00291 return p.MeasureString(text, ToDrawingFont(f)).Width; 00292 } 00293 } 00294 } 00295 } 00296 00297 internal class WFBitmap : IBitmap { 00298 private Bitmap ib = null; 00299 00300 private WFBitmap() {} 00301 00302 public static IBitmap LoadFromFile (Stream bitmapStream) { 00303 WFBitmap b = new WFBitmap(); 00304 b.ib = new Bitmap(bitmapStream); 00305 return b; 00306 } 00307 00308 public void Dispose () 00309 { 00310 ib.Dispose(); 00311 ib = null; 00312 } 00313 00314 public int Height { 00315 get { 00316 Debug.Assert(ib != null, "Undefined bitmap"); 00317 return ib.Height; } 00318 } 00319 00320 public int Width { 00321 get { 00322 Debug.Assert(ib != null, "Undefined bitmap"); 00323 return ib.Width; 00324 } 00325 } 00326 00327 internal Bitmap InternalBitmap { 00328 get { 00329 Debug.Assert(ib != null, "Undefined bitmap"); 00330 return ib; 00331 } 00332 } 00333 00334 } 00335 00336 internal class WFormDialogBuilder : IDialogBuilder { 00337 private Dictionary<string, Control> keyToControl = new Dictionary<string,Control>(); 00338 private Dictionary<Control, string> controlToKey = new Dictionary<Control,string>(); 00339 private Dictionary<string, object> initialValues = new Dictionary<string,object>(); 00340 private List<string> keys = new List<string>(); 00341 Form dialog = null; 00342 string clickedButton; 00343 00344 public void AddButton (string key) { 00345 Button b = new Button(); 00346 b.Text = key; 00347 b.Tag = true; 00348 keyToControl[key] = b; 00349 controlToKey[b] = key; 00350 keys.Add(key); 00351 } 00352 00353 public void AddInput (string key, object initialValue) { 00354 keys.Add(key); 00355 initialValues[key] = initialValue; 00356 if(initialValue.GetType() == typeof(bool)) { 00357 ComboBox cb = new ComboBox(); 00358 cb.Items.AddRange(new string[]{"true", "false"}); 00359 cb.SelectedIndex = (bool)initialValue ? 0 : 1; 00360 cb.DropDownStyle = ComboBoxStyle.DropDownList; 00361 keyToControl[key] = cb; 00362 controlToKey[cb] = key; 00363 cb.Tag = false; 00364 } 00365 else if (initialValue.GetType() == typeof(Color)) { 00366 Color c = (Color) initialValue; 00367 Button b = new Button(); 00368 b.Text = initialValue.ToString(); 00369 b.BackColor = System.Drawing.Color.FromArgb(255 - c.Transparence, c.RedComponent, 00370 c.GreenComponent, c.BlueComponent); 00371 b.Click += delegate (Object sender, EventArgs e) { 00372 ColorDialog d = new ColorDialog(); 00373 d.Color = b.BackColor; 00374 if (d.ShowDialog() == DialogResult.OK) { 00375 System.Drawing.Color nc = d.Color; 00376 b.BackColor = nc; 00377 b.Text = (new Color(nc.R, nc.G, nc.B, 255 - nc.A)).ToString(); 00378 } 00379 }; 00380 keyToControl[key] = b; 00381 controlToKey[b] = key; 00382 b.Tag = false; 00383 } 00384 else { 00385 TextBox tb = new TextBox(); 00386 tb.Text = initialValue.ToString(); 00387 keyToControl[key] = tb; 00388 controlToKey[tb] = key; 00389 tb.Tag = false; 00390 } 00391 } 00392 00393 public void AddSeparator () 00394 { 00395 throw new NotImplementedException (); 00396 } 00397 00398 00399 public string ExecuteDialog (int minimalWidth, StandardButtons stdButtons) 00400 { 00401 int count = keys.Count; 00402 dialog = new Form(); 00403 dialog.Width = minimalWidth; 00404 dialog.Height = (count + (stdButtons != StandardButtons.None ? 2 : 1)) * 32; 00405 for(int i=0; i<count;i++) { 00406 string key = keys[i]; 00407 Control c = keyToControl[key]; 00408 if(c is Button && (bool) c.Tag) { 00409 c.Click += OnClick; 00410 c.Location = new Point(10, i*32+6); 00411 c.Size = new Size(dialog.Width - 30, 24); 00412 } 00413 else { 00414 Label label = new Label(); 00415 label.Text = key; 00416 label.Location = new Point(10, i*32+6); 00417 label.Size = new Size(dialog.Width / 3 - 15, 24); 00418 dialog.Controls.Add(label); 00419 c.Location = new Point(dialog.Width / 3 + 10, i*32+4); 00420 c.Size = new Size(2 * dialog.Width / 3 - 20, 24); 00421 } 00422 dialog.Controls.Add(c); 00423 } 00424 if(stdButtons != StandardButtons.None) { 00425 int i = count; 00426 if((stdButtons & StandardButtons.OK) != 0) { 00427 Button bOK = new Button(); 00428 bOK.Text = "OK"; 00429 bOK.Size = new Size(70, 24); 00430 bOK.Location = new Point(dialog.Width - 160, i*32 + 6); 00431 bOK.Click += OnClick; 00432 dialog.Controls.Add(bOK); 00433 } 00434 if((stdButtons & StandardButtons.Cancel) != 0) { 00435 Button bCancel = new Button(); 00436 bCancel.Text = "Cancel"; 00437 bCancel.Size = new Size(70, 24); 00438 bCancel.Location = new Point(dialog.Width - 80, i*32 + 6); 00439 bCancel.Click += OnClick; 00440 dialog.Controls.Add(bCancel); 00441 } 00442 } 00443 clickedButton = ""; 00444 dialog.ShowDialog(); 00445 return clickedButton; 00446 } 00447 00448 void OnClick(object sender, EventArgs e) { 00449 clickedButton = ((Button) sender).Text; 00450 dialog.Close(); 00451 } 00452 00453 public object GetValue (string key) { 00454 try { 00455 Type retType = initialValues[key].GetType(); 00456 return retType.GetMethod("Parse", new Type[]{typeof(string)}) 00457 .Invoke(null, new object[]{keyToControl[key].Text}); 00458 } 00459 catch(TargetInvocationException) { 00460 return initialValues[key]; 00461 } 00462 00463 } 00464 00465 public IEnumerable<string> Keys { 00466 get { 00467 foreach(string key in keys) 00468 yield return key; 00469 } 00470 } 00471 00472 00473 } 00474 00475 internal class DBForm : Form { 00476 internal DBForm() : base() { 00477 DoubleBuffered = true; 00478 } 00479 } 00480 }