- renamed aa to offset
[FaRetSys.git] / Block.cs
blob29b5e537404d4ae2fd1848a198db421c8bc6a007
1 using System;
2 using System.IO;
3 using System.Reflection;
4 using Cairo;
6 namespace Eithne
8 class Socket
10 private readonly int num;
11 private int x, y;
12 private readonly Block parent;
13 private readonly T type;
14 private Socket other;
16 public enum T
18 In,
19 Out
22 public int X
24 get { return x; }
27 public int Y
29 get { return y; }
30 set { y = value; }
33 public int PX
35 get { return parent.X + x; }
38 public int PY
40 get { return parent.Y + y; }
43 public Block Parent
45 get { return parent; }
48 public T Type
50 get { return type; }
53 public Socket Other
55 get { return other; }
58 public int Num
60 get { return num; }
63 public Socket(int x, int y, Block parent, T type, int num)
65 this.x = x;
66 this.y = y;
67 this.parent = parent;
68 this.type = type;
69 this.num = num;
71 other = null;
74 public void Draw(Context c)
76 int xc = parent.X + x;
77 int yc = parent.Y + y + 5;
79 if(other == null)
81 if(type == T.Out)
83 c.Arc(xc+6.5, yc, 4, 0, 2*Math.PI);
84 c.Color = new Color(0.2, 0.2, 1, 0.6);
85 c.Fill();
88 else
90 int r = 6;
92 if(type == T.Out)
93 xc += 7;
94 else
95 xc += 3;
97 c.Arc(xc, yc, r, 0, 2*Math.PI);
98 c.Color = new Color(1, 0, 0);
99 c.LineWidth = 2.5;
100 c.FillPreserve();
101 c.Color = new Color(0.3, 0, 0);
102 c.Stroke();
103 c.MoveTo(xc-0.707*r, yc-0.707*r);
104 c.LineTo(xc+0.707*r, yc+0.707*r);
105 c.Stroke();
106 c.MoveTo(xc-0.707*r, yc+0.707*r);
107 c.LineTo(xc+0.707*6, yc-0.707*6);
108 c.Stroke();
112 public void Disconnect()
114 if(other != null)
116 if(type == T.In)
117 parent.Invalidate();
118 else
119 other.parent.Invalidate();
121 other.other = null;
122 other = null;
126 public void Connect(Socket to)
128 Disconnect();
129 to.Disconnect();
131 other = to;
132 to.other = this;
136 class Block : IBlock
138 private readonly Plugin.Base plugin;
139 private readonly Schematic schematic;
140 private int x, y;
141 private int h = 0, w = 0, th = 0;
142 private int tx = 0, ty = 0;
143 private int sx = 0, sy = 0;
144 private int cx = 0, cy = 0;
145 private Socket[] socketin = null;
146 private Socket[] socketout = null;
147 private bool working = false;
148 private bool showerror = false;
149 private float progressTimer = 0;
151 private static bool ConfigGradient = Config.Get("block/gradient", true);
152 private static bool ConfigInner = Config.Get("block/innerpath", true);
153 private static bool ConfigRound = Config.Get("block/round", true);
154 private static bool ConfigSmoothConnections = Config.Get("block/smoothconnections", true);
155 private static bool ConfigProgress = Config.Get("block/progress", true);
157 public enum State
159 Good,
160 Bad,
161 NotReady,
162 Ready
165 public bool ShowError
167 set { showerror = value; }
170 public Plugin.Base Plugin
172 get { return plugin; }
175 public int X
177 get { return x; }
180 public int Y
182 get { return y; }
185 public Socket[] SocketIn
187 get { return socketin; }
190 public Socket[] SocketOut
192 get { return socketout; }
195 public bool Working
197 get { return working; }
198 set { working = value; }
201 public Block(Schematic s, Context c, Plugin.Base plugin, int x, int y)
203 this.schematic = s;
204 this.plugin = plugin;
205 this.x = x;
206 this.y = y;
208 plugin.Block = this;
210 UpdateCoordinates(c);
212 socketin = new Socket[plugin.NumIn];
213 socketout = new Socket[plugin.NumOut];
215 int curpos = 10+(h-20-CalcHeight(plugin.NumIn))/2;
216 for(int i=0; i<plugin.NumIn; i++)
218 socketin[i] = new Socket(0, curpos, this, Socket.T.In, i);
219 curpos += 15;
222 curpos = 10+(h-20-CalcHeight(plugin.NumOut))/2;
223 for(int i=0; i<plugin.NumOut; i++)
225 socketout[i] = new Socket(w-10, curpos, this, Socket.T.Out, i);
226 curpos += 15;
230 public static void CheckGConf()
232 bool NewConfigGradient = Config.Get("block/gradient", true);
233 bool NewConfigInner = Config.Get("block/innerpath", true);
234 bool NewConfigRound = Config.Get("block/round", true);
235 bool NewConfigSmoothConnections = Config.Get("block/smoothconnections", true);
236 bool NewConfigProgress = Config.Get("block/progress", true);
238 bool redraw =
239 ConfigGradient != NewConfigGradient ||
240 ConfigInner != NewConfigInner ||
241 ConfigRound != NewConfigRound ||
242 ConfigSmoothConnections != NewConfigSmoothConnections ||
243 ConfigProgress != NewConfigProgress;
245 ConfigGradient = NewConfigGradient;
246 ConfigInner = NewConfigInner;
247 ConfigRound = NewConfigRound;
248 ConfigSmoothConnections = NewConfigSmoothConnections;
249 ConfigProgress = NewConfigProgress;
251 if(redraw)
252 MainWindow.RedrawSchematic();
255 public object Overlap(int x, int y)
257 if(x < this.x || x > this.x + w || y < this.y || y > this.y + h)
258 return null;
260 if(x < this.x + 10)
261 // input sockets
263 int curpos = this.y+10+(h-20-CalcHeight(socketin.Length))/2;
265 for(int i=0; i<socketin.Length; i++)
267 if(y > curpos && y < curpos + 10)
268 return socketin[i];
270 curpos += 15;
273 else if(x > this.x + w - 10)
275 // output sockets
276 int curpos = this.y+10+(h-20-CalcHeight(socketout.Length))/2;
278 for(int i=0; i<socketout.Length; i++)
280 if(y > curpos && y < curpos + 10)
281 return socketout[i];
283 curpos += 15;
287 return this;
290 // FIXME hardcoded working area size
291 public void Move(int dx, int dy)
293 x += dx;
294 y += dy;
296 if(x < 0)
297 x = 0;
298 else if(x+w >= 2048)
299 x = 2048-w;
301 if(y < 0)
302 y = 0;
303 else if(y+h >= 2048)
304 y = 2048-h;
307 // removes all connections
308 public void Disconnect()
310 for(int i=0; i<socketin.Length; i++)
311 socketin[i].Disconnect();
313 for(int i=0; i<socketout.Length; i++)
314 socketout[i].Disconnect();
317 // called after slot number is changed
318 private void UpdateCoordinates()
320 int h1 = CalcHeight(plugin.NumIn);
321 int h2 = CalcHeight(plugin.NumOut);
323 // block size
324 h = Math.Max(Math.Max(th, h1), h2) + 20;
326 // text location
327 ty = h/2 + th/2;
329 if(ty > h-15)
330 ty = h-15;
332 // status location
333 if(plugin is ConnectorPlugin)
334 sy = h/2;
335 else
336 sy = h - 7;
338 // clock location
339 cy = h/2;
342 // called only once, by constructor
343 private void UpdateCoordinates(Context c)
345 TextExtents t = c.TextExtents(plugin.Info.ShortName);
347 th = (int)t.Height;
349 // block size
350 w = (int)t.Width + 30;
352 // text location
353 tx = 15;
355 // status location
356 if(plugin is ConnectorPlugin)
357 sx = w/2;
358 else
359 sx = w/2 + 1;
361 // clock location
362 cx = w/2;
364 UpdateCoordinates();
367 public void Draw(Context c, object selected)
369 DrawSockets(c);
371 if(this == selected || (selected is Socket && (selected as Socket).Parent == this))
372 DrawBlock(c, true);
373 else
374 DrawBlock(c, false);
376 DrawState(c);
377 if(working)
379 DrawClock(c);
380 if(ConfigProgress)
381 DrawClockProgress(c, plugin.Progress);
384 if(selected is Socket)
386 for(int i=0; i<socketin.Length; i++)
387 if(socketin[i] == selected)
389 socketin[i].Draw(c);
390 return;
393 for(int i=0; i<socketout.Length; i++)
394 if(socketout[i] == selected)
396 socketout[i].Draw(c);
397 return;
401 if(showerror)
403 c.Color = new Color(1, 0, 0, 0.5);
404 DrawPath(c);
405 c.Fill();
409 public State CheckState()
411 for(int i=0; i<socketin.Length; i++)
412 if(SocketIn[i].Other == null)
413 return State.NotReady;
415 if(Plugin.WorkDone)
416 return State.Good;
418 if(WorkPossible())
419 return State.Ready;
420 else
421 return State.Bad;
424 public bool WorkPossible()
426 for(int i=0; i<socketin.Length; i++)
427 if(socketin[i].Other.Parent.CheckState() != State.Good)
428 return false;
430 return true;
433 private void DrawClock(Context c)
435 LinearGradient g;
437 c.LineWidth = 1;
439 c.Save();
440 c.Translate(x + cx, y + cy);
442 // shadow
443 c.Color = new Color(0, 0, 0, 0.1);
444 c.Arc(0, 0, 14, 0, 2 * Math.PI);
445 c.Fill();
446 c.Arc(0, 0, 13, 0, 2 * Math.PI);
447 c.Fill();
449 // background
450 c.Arc(0, 0, 12, 0, 2 * Math.PI);
451 c.Color = new Color(0.525, 0.525, 0.525);
452 c.FillPreserve();
453 c.Color = new Color(0.455, 0.455, 0.455);
454 c.Stroke();
456 // outline
457 c.Color = new Color(1, 1, 1, 0.25);
458 c.Arc(0, 0, 11, 0, 2 * Math.PI);
459 c.Stroke();
461 // clock face
462 c.Arc(0, 0, 8, 0, 2 * Math.PI);
463 g = new LinearGradient(7, 7, -7, -7);
464 g.AddColorStopRgb(0, new Color(0.796, 0.796, 0.796));
465 g.AddColorStopRgb(1, new Color(1, 1, 1));
466 c.Pattern = g;
467 c.FillPreserve();
468 g = new LinearGradient(7, 7, -7, -7);
469 g.AddColorStopRgb(0, new Color(1, 1, 1));
470 g.AddColorStopRgb(1, new Color(0.627, 0.627, 0.627));
471 c.Pattern = g;
472 c.Stroke();
474 // hand center
475 c.LineWidth = 0.5;
476 c.Arc(0.5, 0.5, 1.25, 0, 2 * Math.PI);
477 c.Color = new Color(0.95, 0.95, 0.95);
478 c.FillPreserve();
479 c.Color = new Color(0.1, 0.1, 0.1);
480 c.Stroke();
482 // minute hand
483 c.MoveTo(0.5+Math.Sin(-1.15)*1.5, 0.5+Math.Cos(-1.15)*1.5);
484 c.LineTo(0.5+Math.Sin(-1.15)*6.5, 0.5+Math.Cos(-1.15)*6.5);
485 c.Stroke();
487 // hour hand
488 c.LineWidth = 0.75;
490 c.MoveTo(0.5+Math.Sin(1.15)*1.5, 0.5+Math.Cos(1.15)*1.5);
491 c.LineTo(0.5+Math.Sin(1.15)*5, 0.5+Math.Cos(1.15)*5);
492 c.Stroke();
494 // hour markers
495 c.LineWidth = 1;
497 c.Arc(0.5, 6.5, 0.75, 0, 2 * Math.PI);
498 c.Color = new Color(0.058, 0.058, 0.058);
499 c.Fill();
501 c.Arc(0.5, -5.5, 0.75, 0, 2 * Math.PI);
502 c.Color = new Color(0.44, 0.44, 0.44);
503 c.Fill();
505 c.Arc(6.5, 0.5, 0.75, 0, 2 * Math.PI);
506 c.Color = new Color(0.113, 0.113, 0.113);
507 c.Fill();
509 c.Arc(-5.5, 0.5, 0.75, 0, 2 * Math.PI);
510 c.Color = new Color(0.38, 0.38, 0.38);
511 c.Fill();
513 c.Restore();
516 private void DrawClockProgress(Context c, float progress)
518 c.Save();
519 c.Color = new Color(0.5, 0.5, 1, 0.75);
520 c.Translate(x + w/2, y + h/2);
521 c.MoveTo(0, 0);
522 if(progress == -1)
524 progressTimer += 0.2f;
525 c.Arc(0, 0, 8, progressTimer, progressTimer + 1.5);
527 else
529 c.ArcNegative(0, 0, 8, -90 * Math.PI/180, (-89 + 356 * progress ) * Math.PI/180);
531 c.ClosePath();
532 c.Fill();
533 c.Restore();
536 private void DrawState(Context c)
538 State s = CheckState();
540 LinearGradient GradientOutline = new LinearGradient(x+sx-1, y+sy-3, x+sx+1, y+sy+3);
541 GradientOutline.AddColorStopRgb(0, new Color(0.06, 0.06, 0.627));
542 GradientOutline.AddColorStopRgb(1, new Color(0.06, 0.06, 0.25));
544 LinearGradient GradientInside = new LinearGradient(x+sx-2, y+sy-2, x+sx-1, y+sy+1);
546 if(s == State.NotReady)
548 GradientInside.AddColorStopRgb(0, new Color(0.5, 0.5, 0.5));
549 GradientInside.AddColorStopRgb(1, new Color(0.06, 0.06, 0.06));
551 else if(s == State.Bad)
553 GradientInside.AddColorStopRgb(0, new Color(1, 0.25, 0.25));
554 GradientInside.AddColorStopRgb(1, new Color(0.627, 0.03, 0.03));
556 else if(s == State.Good)
558 GradientInside.AddColorStopRgb(0, new Color(0.5, 1, 0.5));
559 GradientInside.AddColorStopRgb(1, new Color(0.25, 0.75, 0.25));
561 else
563 GradientInside.AddColorStopRgb(0, new Color(1, 0.75, 0));
564 GradientInside.AddColorStopRgb(1, new Color(1, 0.5, 0));
567 c.Pattern = GradientInside;
568 c.Arc(x+sx, y+sy, 4, 0, 2 * Math.PI);
569 c.FillPreserve();
571 c.Pattern = GradientOutline;
572 c.Stroke();
574 c.Color = new Color(1, 1, 1, 0.25);
575 c.Arc(x+sx, y+sy, 3, 0, 2 * Math.PI);
576 c.Stroke();
579 private void DrawBlockGradient(Context c)
581 LinearGradient g = new LinearGradient(0, y, 0, y+h);
582 if(plugin is Plugin.In)
584 g.AddColorStop(0, new Color(0.65, 0.85, 1.00, 0.85));
585 g.AddColorStop(0.33, new Color(0.45, 0.65, 1.00, 0.85));
586 g.AddColorStop(1, new Color(0.20, 0.50, 0.80, 0.85));
588 else if(plugin is Plugin.Out)
590 g.AddColorStop(0, new Color(1.00, 0.85, 1.00, 0.85));
591 g.AddColorStop(0.33, new Color(1.00, 0.65, 1.00, 0.85));
592 g.AddColorStop(1, new Color(0.80, 0.40, 0.80, 0.85));
594 else if(plugin is Plugin.ImgProc)
596 g.AddColorStop(0, new Color(0.75, 1.00, 0.75, 0.85));
597 g.AddColorStop(0.33, new Color(0.55, 1.00, 0.55, 0.85));
598 g.AddColorStop(1, new Color(0.30, 0.80, 0.30, 0.85));
600 else if(plugin is Plugin.ResProc)
602 g.AddColorStop(0, new Color(1.00, 0.75, 0.75, 0.85));
603 g.AddColorStop(0.33, new Color(1.00, 0.55, 0.55, 0.85));
604 g.AddColorStop(1, new Color(0.80, 0.30, 0.30, 0.85));
606 else if(plugin is Plugin.Comparator)
608 g.AddColorStop(0, new Color(1.00, 1.00, 0.75, 0.85));
609 g.AddColorStop(0.33, new Color(1.00, 1.00, 0.55, 0.85));
610 g.AddColorStop(1, new Color(0.80, 0.80, 0.30, 0.85));
612 else if(plugin is Plugin.Other)
614 g.AddColorStop(0, new Color(0.7, 0.7, 0.7, 0.85));
615 g.AddColorStop(0.33, new Color(0.5, 0.5, 0.5, 0.85));
616 g.AddColorStop(1, new Color(0.35, 0.35, 0.35, 0.85));
619 DrawPath(c);
620 c.Pattern = g;
621 c.FillPreserve();
624 private void DrawBlockNoGradient(Context c)
626 if(plugin is Plugin.In)
627 c.Color = new Color(0.35, 0.55, 0.95, 0.85);
628 else if(plugin is Plugin.Out)
629 c.Color = new Color(0.95, 0.55, 0.95, 0.85);
630 else if(plugin is Plugin.ImgProc)
631 c.Color = new Color(0.45, 0.95, 0.45, 0.85);
632 else if(plugin is Plugin.ResProc)
633 c.Color = new Color(0.95, 0.45, 0.45, 0.85);
634 else if(plugin is Plugin.Comparator)
635 c.Color = new Color(0.95, 0.95, 0.45, 0.85);
636 else if(plugin is Plugin.Other)
637 c.Color = new Color(0.5, 0.5, 0.5, 0.85);
639 DrawPath(c);
640 c.FillPreserve();
643 private void DrawBlock(Context c, bool IsSelected)
645 if(ConfigGradient)
646 DrawBlockGradient(c);
647 else
648 DrawBlockNoGradient(c);
650 if(showerror)
651 c.Color = new Color(1, 0, 0);
652 else if(IsSelected)
653 c.Color = new Color(0.2, 0.2, 1);
654 else
655 c.Color = new Color(0, 0, 0);
657 c.LineWidth = 2.0;
659 c.Stroke();
661 if(ConfigInner)
663 c.Color = new Color(1, 1, 1, 0.5);
664 c.LineWidth = 1;
665 DrawPathInner(c);
666 c.Stroke();
669 c.Color = new Color(0, 0, 0);
671 c.Save();
672 c.Translate(x + tx, y + ty);
673 c.ShowText(plugin.Info.ShortName);
674 c.Stroke();
675 c.Restore();
678 private void DrawSockets(Context c)
680 int curpos = y+10+(h-20-CalcHeight(socketout.Length))/2;
682 for(int i=0; i<socketout.Length; i++)
684 if(socketout[i].Other == null)
686 c.LineWidth = 1.5;
687 c.Arc(x+w-3, curpos+5, 4, 0, 2*Math.PI);
688 c.Color = new Color(1, 1, 1, 0.8);
689 c.FillPreserve();
690 c.Color = new Color(0, 0, 0);
691 c.Stroke();
693 else
695 c.LineWidth = 2.0;
696 c.MoveTo(x+w-1, curpos);
698 if(ConfigRound)
699 c.CurveTo(x+w-10, curpos, x+w-10, curpos+10, x+w-1, curpos+10);
700 else
702 c.LineTo(x+w-8, curpos);
703 c.LineTo(x+w-8, curpos+10);
704 c.LineTo(x+w-1, curpos+10);
707 c.ClosePath();
708 c.Color = new Color(1, 1, 1, 0.8);
709 c.Fill();
710 c.MoveTo(x+w, curpos);
711 c.LineTo(x+w, curpos+10);
712 c.Color = new Color(0, 0, 0);
713 c.Stroke();
716 curpos += 15;
719 curpos = y+10+(h-20-CalcHeight(socketin.Length))/2;
721 for(int i=0; i<socketin.Length; i++)
723 if(socketin[i].Other != null)
725 c.LineWidth = 2.0;
726 c.MoveTo(x+1, curpos);
728 if(ConfigRound)
729 c.CurveTo(x+10, curpos, x+10, curpos+10, x+1, curpos+10);
730 else
732 c.LineTo(x+8, curpos);
733 c.LineTo(x+8, curpos+10);
734 c.LineTo(x+1, curpos+10);
737 c.ClosePath();
738 c.Color = new Color(1, 1, 1, 0.8);
739 c.Fill();
740 c.MoveTo(x, curpos);
741 c.LineTo(x, curpos+10);
742 c.Color = new Color(0, 0, 0);
743 c.Stroke();
746 curpos += 15;
750 public void DrawConnections(Context c)
752 int curpos = y+15+(h-20-CalcHeight(socketout.Length))/2;
754 c.LineWidth = 1.0;
755 c.Color = new Color(0, 0, 0);
756 for(int i=0; i<socketout.Length; i++)
758 if(socketout[i].Other != null)
760 c.MoveTo(x+w, curpos);
762 if(ConfigSmoothConnections)
763 c.CurveTo(x+w+10, curpos, socketout[i].Other.PX-10, socketout[i].Other.PY+5, socketout[i].Other.PX, socketout[i].Other.PY+5);
764 else
765 c.LineTo(socketout[i].Other.PX, socketout[i].Other.PY+5);
767 c.Stroke();
770 curpos += 15;
774 private int CalcHeight(int sockets)
776 return Math.Max(sockets*10 + (sockets-1)*5, 0);
779 private void DrawPath(Context c)
781 if(ConfigRound)
782 DrawPathRound(c);
783 else
784 DrawPathSquare(c);
787 private void DrawPathRound(Context c)
789 // 1-------2
790 // | |
791 // | |
792 // 4-------3
794 // 1
795 c.MoveTo(x+10, y);
796 c.LineTo(x+w-10, y);
797 // 2
798 c.CurveTo(x+w, y, x+w, y, x+w, y+10);
800 // output sockets
801 if(socketout.Length == 0)
802 c.LineTo(x+w, y+h-10);
803 else
805 int curpos = y+10+(h-20-CalcHeight(socketout.Length))/2;
807 c.LineTo(x+w, curpos);
809 for(int i=0; i<socketout.Length; i++)
811 if(i!=0)
813 curpos += 5;
814 c.LineTo(x+w, curpos);
817 c.CurveTo(x+w-10, curpos, x+w-10, curpos+10, x+w, curpos+10);
818 curpos += 10;
821 c.LineTo(x+w,y+h-10);
824 // 3
825 c.CurveTo(x+w, y+h, x+w, y+h, x+w-10, y+h);
826 c.LineTo(x+10, y+h);
827 // 4
828 c.CurveTo(x, y+h, x, y+h, x, y+h-10);
830 // input sockets
831 if(socketin.Length == 0)
832 c.LineTo(x, y+10);
833 else
835 int curpos = y+h-10-(h-20-CalcHeight(socketin.Length))/2;
837 c.LineTo(x, curpos);
839 for(int i=0; i<socketin.Length; i++)
841 if(i!=0)
843 curpos -= 5;
844 c.LineTo(x, curpos);
847 c.CurveTo(x+10, curpos, x+10, curpos-10, x, curpos-10);
848 curpos -= 10;
851 c.LineTo(x,y+10);
854 // 1
855 c.CurveTo(x, y, x, y, x+10, y);
858 private void DrawPathSquare(Context c)
860 // 1-------2
861 // | |
862 // | |
863 // 4-------3
865 // 1
866 c.MoveTo(x, y);
867 c.LineTo(x+w, y);
869 // 2
870 // output sockets
871 if(socketout.Length == 0)
872 c.LineTo(x+w, y+h);
873 else
875 int curpos = y+10+(h-20-CalcHeight(socketout.Length))/2;
877 c.LineTo(x+w, curpos);
879 for(int i=0; i<socketout.Length; i++)
881 if(i!=0)
883 curpos += 5;
884 c.LineTo(x+w, curpos);
887 c.LineTo(x+w-8, curpos);
888 c.LineTo(x+w-8, curpos+10);
889 c.LineTo(x+w, curpos+10);
891 curpos += 10;
894 c.LineTo(x+w,y+h);
897 // 3
898 c.LineTo(x, y+h);
900 // 4
901 // input sockets
902 if(socketin.Length == 0)
903 c.LineTo(x, y);
904 else
906 int curpos = y+h-10-(h-20-CalcHeight(socketin.Length))/2;
908 c.LineTo(x, curpos);
910 for(int i=0; i<socketin.Length; i++)
912 if(i!=0)
914 curpos -= 5;
915 c.LineTo(x, curpos);
918 c.LineTo(x+8, curpos);
919 c.LineTo(x+8, curpos-10);
920 c.LineTo(x, curpos-10);
922 curpos -= 10;
925 c.LineTo(x,y+10);
929 c.LineTo(x, y);
930 c.LineTo(x+1, y);
933 private void DrawPathInner(Context c)
935 if(ConfigRound)
936 DrawPathInnerRound(c);
937 // TODO
938 // else
939 // DrawPathInnerSquare(c);
943 private void DrawPathInnerRound(Context c)
945 // 1-------2
946 // | |
947 // | |
948 // 4-------3
950 // 1
951 c.MoveTo(x+11.5, y+1.5);
952 c.LineTo(x+w-11.5, y+1.5);
953 // 2
954 c.CurveTo(x+w-1.5, y+1.5, x+w-1.5, y+1.5, x+w-1.5, y+8.5);
956 // output sockets
957 if(socketout.Length == 0)
958 c.LineTo(x+w-1.5, y+h-11.5);
959 else
961 int curpos = y+10+(h-20-CalcHeight(socketout.Length))/2;
963 c.LineTo(x+w-1.5, curpos-1.5);
965 for(int i=0; i<socketout.Length; i++)
967 if(i!=0)
969 curpos += 5;
970 c.LineTo(x+w-1.5, curpos-1.5);
973 c.CurveTo(x+w-11.5, curpos-1.5, x+w-11.5, curpos+11.5, x+w-1.5, curpos+11.5);
974 curpos += 10;
977 c.LineTo(x+w-1.5, y+h-8.5);
980 // 3
981 c.CurveTo(x+w-1.5, y+h-1.5, x+w-1.5, y+h-1.5, x+w-11.5, y+h-1.5);
982 c.LineTo(x+11.5, y+h-1.5);
983 // 4
984 c.CurveTo(x+1.5, y+h-1.5, x+1.5, y+h-1.5, x+1.5, y+h-8.5);
986 // input sockets
987 if(socketin.Length == 0)
988 c.LineTo(x+1.5, y+11.5);
989 else
991 int curpos = y+h-10-(h-20-CalcHeight(socketin.Length))/2;
993 c.LineTo(x+1.5, curpos+1.5);
995 for(int i=0; i<socketin.Length; i++)
997 if(i!=0)
999 curpos -= 5;
1000 c.LineTo(x+1.5, curpos+1.5);
1003 c.CurveTo(x+11.5, curpos+1.5, x+11.5, curpos-11.5, x+1.5, curpos-11.5);
1004 curpos -= 10;
1007 c.LineTo(x+1.5, y+8.5);
1010 // 1
1011 c.CurveTo(x+1.5, y+1.5, x+1.5, y+1.5, x+11.5, y+1.5);
1014 private void Invalidate(bool x)
1016 Plugin.WorkDone = false;
1017 Plugin.Invalidate();
1019 for(int i=0; i<socketout.Length; i++)
1021 Socket o = socketout[i].Other;
1023 if(o != null && o.Parent.CheckState() == State.Good)
1024 o.Parent.Invalidate(true);
1028 public void Invalidate()
1030 Invalidate(true);
1031 schematic.QueueDraw();
1034 public void SlotsChanged()
1036 UpdateCoordinates();
1038 if(socketin.Length != plugin.NumIn)
1040 Socket[] newsocketin = new Socket[plugin.NumIn];
1041 int curpos = 10+(h-20-CalcHeight(plugin.NumIn))/2;
1043 for(int i=0; i<plugin.NumIn; i++)
1045 if(i < socketin.Length)
1046 newsocketin[i] = socketin[i];
1047 else
1048 newsocketin[i] = new Socket(0, curpos, this, Socket.T.In, i);
1049 curpos += 15;
1051 for(int i=plugin.NumIn; i<socketout.Length; i++)
1052 socketout[i].Disconnect();
1054 socketin = newsocketin;
1056 else
1058 int curpos = 10+(h-20-CalcHeight(socketin.Length))/2;
1060 for(int i=0; i<socketin.Length; i++)
1062 socketin[i].Y = curpos;
1063 curpos += 15;
1067 if(socketout.Length != plugin.NumOut)
1069 Socket[] newsocketout = new Socket[plugin.NumOut];
1070 int curpos = 10+(h-20-CalcHeight(plugin.NumOut))/2;
1072 for(int i=0; i<plugin.NumOut; i++)
1074 if(i < socketout.Length)
1075 newsocketout[i] = socketout[i];
1076 else
1077 newsocketout[i] = new Socket(w-10, curpos, this, Socket.T.Out, i);
1078 curpos += 15;
1080 for(int i=plugin.NumOut; i<socketout.Length; i++)
1081 socketout[i].Disconnect();
1083 socketout = newsocketout;
1085 else
1087 int curpos = 10+(h-20-CalcHeight(socketout.Length))/2;
1089 for(int i=0; i<socketout.Length; i++)
1091 socketout[i].Y = curpos;
1092 curpos += 15;
1096 schematic.QueueDraw();
1097 Invalidate();