- add progress to histogram
[FaRetSys.git] / Block.cs
blob0b44a1d123e8822dbf4f4929ca5f79691de2130b
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 IPlugin 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 ImageSurface StateBad = new ImageSurface(System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "data/state-bad.png"));
152 private static ImageSurface StateGood = new ImageSurface(System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "data/state-good.png"));
153 private static ImageSurface StateNotReady = new ImageSurface(System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "data/state-not-ready.png"));
154 private static ImageSurface StateReady = new ImageSurface(System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "data/state-ready.png"));
155 private static ImageSurface Clock = new ImageSurface(System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "data/clock.png"));
157 private static bool ConfigGradient = Config.Get("block/gradient", true);
158 private static bool ConfigInner = Config.Get("block/innerpath", true);
159 private static bool ConfigRound = Config.Get("block/round", true);
160 private static bool ConfigSmoothConnections = Config.Get("block/smoothconnections", true);
162 public enum State
164 Good,
165 Bad,
166 NotReady,
167 Ready
170 public bool ShowError
172 set { showerror = value; }
175 public IPlugin Plugin
177 get { return plugin; }
180 public int X
182 get { return x; }
185 public int Y
187 get { return y; }
190 public Socket[] SocketIn
192 get { return socketin; }
195 public Socket[] SocketOut
197 get { return socketout; }
200 public bool Working
202 get { return working; }
203 set { working = value; }
206 public Block(Schematic s, Context c, IPlugin plugin, int x, int y)
208 this.schematic = s;
209 this.plugin = plugin;
210 this.x = x;
211 this.y = y;
213 plugin.Block = this;
215 UpdateCoordinates(c);
217 socketin = new Socket[plugin.NumIn];
218 socketout = new Socket[plugin.NumOut];
220 int curpos = 10+(h-20-CalcHeight(plugin.NumIn))/2;
221 for(int i=0; i<plugin.NumIn; i++)
223 socketin[i] = new Socket(0, curpos, this, Socket.T.In, i);
224 curpos += 15;
227 curpos = 10+(h-20-CalcHeight(plugin.NumOut))/2;
228 for(int i=0; i<plugin.NumOut; i++)
230 socketout[i] = new Socket(w-10, curpos, this, Socket.T.Out, i);
231 curpos += 15;
235 public static void CheckGConf()
237 bool NewConfigGradient = Config.Get("block/gradient", true);
238 bool NewConfigInner = Config.Get("block/innerpath", true);
239 bool NewConfigRound = Config.Get("block/round", true);
240 bool NewConfigSmoothConnections = Config.Get("block/smoothconnections", true);
242 bool redraw =
243 ConfigGradient != NewConfigGradient ||
244 ConfigInner != NewConfigInner ||
245 ConfigRound != NewConfigRound ||
246 ConfigSmoothConnections != NewConfigSmoothConnections;
248 ConfigGradient = NewConfigGradient;
249 ConfigInner = NewConfigInner;
250 ConfigRound = NewConfigRound;
251 ConfigSmoothConnections = NewConfigSmoothConnections;
253 if(redraw)
254 MainWindow.RedrawSchematic();
257 public object Overlap(int x, int y)
259 if(x < this.x || x > this.x + w || y < this.y || y > this.y + h)
260 return null;
262 if(x < this.x + 10)
263 // porty wejściowe
265 int curpos = this.y+10+(h-20-CalcHeight(socketin.Length))/2;
267 for(int i=0; i<socketin.Length; i++)
269 if(y > curpos && y < curpos + 10)
270 return socketin[i];
272 curpos += 15;
275 else if(x > this.x + w - 10)
277 // porty wyjściowe
278 int curpos = this.y+10+(h-20-CalcHeight(socketout.Length))/2;
280 for(int i=0; i<socketout.Length; i++)
282 if(y > curpos && y < curpos + 10)
283 return socketout[i];
285 curpos += 15;
289 return this;
292 // FIXME wpisany na sztywno rozmiar obszaru roboczego
293 public void Move(int dx, int dy)
295 x += dx;
296 y += dy;
298 if(x < 0)
299 x = 0;
300 else if(x+w >= 2048)
301 x = 2048-w;
303 if(y < 0)
304 y = 0;
305 else if(y+h >= 2048)
306 y = 2048-h;
309 // usuwa wszystkie połączenia
310 public void Disconnect()
312 for(int i=0; i<socketin.Length; i++)
313 socketin[i].Disconnect();
315 for(int i=0; i<socketout.Length; i++)
316 socketout[i].Disconnect();
319 // wykonywane po zmianie liczby slotów we wtyczce
320 private void UpdateCoordinates()
322 int h1 = CalcHeight(plugin.NumIn);
323 int h2 = CalcHeight(plugin.NumOut);
325 // rozmiar bloku
326 h = Math.Max(Math.Max(th, h1), h2) + 20;
328 // położenie tekstu
329 ty = h/2 + th/2;
331 if(ty > h-15)
332 ty = h-15;
334 // położenie stanu
335 if(plugin is ConnectorPlugin)
336 sy = h/2 - 4;
337 else
338 sy = h - 11;
340 // położenie zegarka
341 cy = h/2 - 16;
344 // wykonywane tylko raz, przez konstruktor
345 private void UpdateCoordinates(Context c)
347 TextExtents t = c.TextExtents(plugin.Info.ShortName);
349 th = (int)t.Height;
351 // rozmiar bloku
352 w = (int)t.Width + 30;
354 // położenie tekstu
355 tx = 15;
357 // położenie stanu
358 if(plugin is ConnectorPlugin)
359 sx = w/2 - 4;
360 else
361 sx = w/2 - 3;
363 // położenie zegarka
364 cx = w/2 - 16;
366 UpdateCoordinates();
369 public void Draw(Context c, object selected)
371 DrawSockets(c);
373 if(this == selected || (selected is Socket && (selected as Socket).Parent == this))
374 DrawBlock(c, true);
375 else
376 DrawBlock(c, false);
378 DrawState(c);
379 if(working)
381 DrawClock(c);
382 DrawClockProgress(c, plugin.Progress);
385 if(selected is Socket)
387 for(int i=0; i<socketin.Length; i++)
388 if(socketin[i] == selected)
390 socketin[i].Draw(c);
391 return;
394 for(int i=0; i<socketout.Length; i++)
395 if(socketout[i] == selected)
397 socketout[i].Draw(c);
398 return;
402 if(showerror)
404 c.Color = new Color(1, 0, 0, 0.5);
405 DrawPath(c);
406 c.Fill();
410 public State CheckState()
412 for(int i=0; i<socketin.Length; i++)
413 if(SocketIn[i].Other == null)
414 return State.NotReady;
416 if(Plugin.WorkDone)
417 return State.Good;
419 if(WorkPossible())
420 return State.Ready;
421 else
422 return State.Bad;
425 public bool WorkPossible()
427 for(int i=0; i<socketin.Length; i++)
428 if(socketin[i].Other.Parent.CheckState() != State.Good)
429 return false;
431 return true;
434 private void DrawClock(Context c)
436 c.Save();
437 c.Translate(x + cx, y + cy);
438 Clock.Show(c, 0, 0);
439 c.Stroke();
440 c.Restore();
443 private void DrawClockProgress(Context c, float progress)
445 // FIXME infinite progress not supported now
446 if(progress == -1)
447 return;
449 c.Save();
450 c.Color = new Color(0.5, 0.5, 1, 0.75);
451 c.Translate(x + w/2, y + h/2);
452 c.MoveTo(0, 0);
453 if(progress == -1)
455 progressTimer += 0.01f;
456 c.Arc(0, 0, 8, progressTimer, progressTimer + 1.5);
458 else
460 c.ArcNegative(0, 0, 8, -90 * Math.PI/180, (-89 + 356 * progress ) * Math.PI/180);
462 c.ClosePath();
463 c.Fill();
464 c.Restore();
466 schematic.QueueDraw();
469 private void DrawState(Context c)
471 State s = CheckState();
473 c.Color = new Color(1, 1, 1);
474 c.Save();
475 c.Translate(x + sx, y + sy);
477 if(s == State.NotReady)
478 StateNotReady.Show(c, 0, 0);
479 else if(s == State.Bad)
480 StateBad.Show(c, 0, 0);
481 else if(s == State.Good)
482 StateGood.Show(c, 0, 0);
483 else
484 StateReady.Show(c, 0, 0);
486 c.Stroke();
487 c.Restore();
490 private void DrawBlockGradient(Context c)
492 LinearGradient g = new LinearGradient(0, y, 0, y+h);
493 if(plugin is IInPlugin)
495 g.AddColorStop(0, new Color(0.65, 0.85, 1.00, 0.85));
496 g.AddColorStop(0.33, new Color(0.45, 0.65, 1.00, 0.85));
497 g.AddColorStop(1, new Color(0.20, 0.50, 0.80, 0.85));
499 else if(plugin is IOutPlugin)
501 g.AddColorStop(0, new Color(1.00, 0.85, 1.00, 0.85));
502 g.AddColorStop(0.33, new Color(1.00, 0.65, 1.00, 0.85));
503 g.AddColorStop(1, new Color(0.80, 0.40, 0.80, 0.85));
505 else if(plugin is IImgProcPlugin)
507 g.AddColorStop(0, new Color(0.75, 1.00, 0.75, 0.85));
508 g.AddColorStop(0.33, new Color(0.55, 1.00, 0.55, 0.85));
509 g.AddColorStop(1, new Color(0.30, 0.80, 0.30, 0.85));
511 else if(plugin is IResProcPlugin)
513 g.AddColorStop(0, new Color(1.00, 0.75, 0.75, 0.85));
514 g.AddColorStop(0.33, new Color(1.00, 0.55, 0.55, 0.85));
515 g.AddColorStop(1, new Color(0.80, 0.30, 0.30, 0.85));
517 else if(plugin is IComparatorPlugin)
519 g.AddColorStop(0, new Color(1.00, 1.00, 0.75, 0.85));
520 g.AddColorStop(0.33, new Color(1.00, 1.00, 0.55, 0.85));
521 g.AddColorStop(1, new Color(0.80, 0.80, 0.30, 0.85));
523 else if(plugin is IOtherPlugin)
525 g.AddColorStop(0, new Color(0.7, 0.7, 0.7, 0.85));
526 g.AddColorStop(0.33, new Color(0.5, 0.5, 0.5, 0.85));
527 g.AddColorStop(1, new Color(0.35, 0.35, 0.35, 0.85));
530 DrawPath(c);
531 c.Pattern = g;
532 c.FillPreserve();
535 private void DrawBlockNoGradient(Context c)
537 if(plugin is IInPlugin)
538 c.Color = new Color(0.35, 0.55, 0.95, 0.85);
539 else if(plugin is IOutPlugin)
540 c.Color = new Color(0.95, 0.55, 0.95, 0.85);
541 else if(plugin is IImgProcPlugin)
542 c.Color = new Color(0.45, 0.95, 0.45, 0.85);
543 else if(plugin is IResProcPlugin)
544 c.Color = new Color(0.95, 0.45, 0.45, 0.85);
545 else if(plugin is IComparatorPlugin)
546 c.Color = new Color(0.95, 0.95, 0.45, 0.85);
547 else if(plugin is IOtherPlugin)
548 c.Color = new Color(0.5, 0.5, 0.5, 0.85);
550 DrawPath(c);
551 c.FillPreserve();
554 private void DrawBlock(Context c, bool IsSelected)
556 if(ConfigGradient)
557 DrawBlockGradient(c);
558 else
559 DrawBlockNoGradient(c);
561 if(showerror)
562 c.Color = new Color(1, 0, 0);
563 else if(IsSelected)
564 c.Color = new Color(0.2, 0.2, 1);
565 else
566 c.Color = new Color(0, 0, 0);
568 c.LineWidth = 2.0;
570 c.Stroke();
572 if(ConfigInner)
574 c.Color = new Color(1, 1, 1, 0.5);
575 c.LineWidth = 1;
576 DrawPathInner(c);
577 c.Stroke();
580 c.Color = new Color(0, 0, 0);
582 c.Save();
583 c.Translate(x + tx, y + ty);
584 c.ShowText(plugin.Info.ShortName);
585 c.Stroke();
586 c.Restore();
589 private void DrawSockets(Context c)
591 int curpos = y+10+(h-20-CalcHeight(socketout.Length))/2;
593 for(int i=0; i<socketout.Length; i++)
595 if(socketout[i].Other == null)
597 c.LineWidth = 1.5;
598 c.Arc(x+w-3, curpos+5, 4, 0, 2*Math.PI);
599 c.Color = new Color(1, 1, 1, 0.8);
600 c.FillPreserve();
601 c.Color = new Color(0, 0, 0);
602 c.Stroke();
604 else
606 c.LineWidth = 2.0;
607 c.MoveTo(x+w, curpos);
609 if(ConfigRound)
610 c.CurveTo(x+w-10, curpos, x+w-10, curpos+10, x+w, curpos+10);
611 else
613 c.LineTo(x+w-8, curpos);
614 c.LineTo(x+w-8, curpos+10);
615 c.LineTo(x+w, curpos+10);
618 c.LineTo(x+w, curpos);
619 c.Color = new Color(1, 1, 1, 0.8);
620 c.Fill();
621 c.MoveTo(x+w, curpos);
622 c.LineTo(x+w, curpos+10);
623 c.Color = new Color(0, 0, 0);
624 c.Stroke();
627 curpos += 15;
630 curpos = y+10+(h-20-CalcHeight(socketin.Length))/2;
632 for(int i=0; i<socketin.Length; i++)
634 if(socketin[i].Other != null)
636 c.LineWidth = 2.0;
637 c.MoveTo(x, curpos);
639 if(ConfigRound)
640 c.CurveTo(x+10, curpos, x+10, curpos+10, x, curpos+10);
641 else
643 c.LineTo(x+8, curpos);
644 c.LineTo(x+8, curpos+10);
645 c.LineTo(x, curpos+10);
648 c.LineTo(x, curpos);
649 c.Color = new Color(1, 1, 1, 0.8);
650 c.Fill();
651 c.MoveTo(x, curpos);
652 c.LineTo(x, curpos+10);
653 c.Color = new Color(0, 0, 0);
654 c.Stroke();
657 curpos += 15;
661 public void DrawConnections(Context c)
663 int curpos = y+15+(h-20-CalcHeight(socketout.Length))/2;
665 c.LineWidth = 1.0;
666 c.Color = new Color(0, 0, 0);
667 for(int i=0; i<socketout.Length; i++)
669 if(socketout[i].Other != null)
671 c.MoveTo(x+w, curpos);
673 if(ConfigSmoothConnections)
674 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);
675 else
676 c.LineTo(socketout[i].Other.PX, socketout[i].Other.PY+5);
678 c.Stroke();
681 curpos += 15;
685 private int CalcHeight(int sockets)
687 return Math.Max(sockets*10 + (sockets-1)*5, 0);
690 private void DrawPath(Context c)
692 if(ConfigRound)
693 DrawPathRound(c);
694 else
695 DrawPathSquare(c);
698 private void DrawPathRound(Context c)
700 // 1-------2
701 // | |
702 // | |
703 // 4-------3
705 // 1
706 c.MoveTo(x+10, y);
707 c.LineTo(x+w-10, y);
708 // 2
709 c.CurveTo(x+w, y, x+w, y, x+w, y+10);
711 // gniazda wyjściowe
712 if(socketout.Length == 0)
713 c.LineTo(x+w, y+h-10);
714 else
716 int curpos = y+10+(h-20-CalcHeight(socketout.Length))/2;
718 c.LineTo(x+w, curpos);
720 for(int i=0; i<socketout.Length; i++)
722 if(i!=0)
724 curpos += 5;
725 c.LineTo(x+w, curpos);
728 c.CurveTo(x+w-10, curpos, x+w-10, curpos+10, x+w, curpos+10);
729 curpos += 10;
732 c.LineTo(x+w,y+h-10);
735 // 3
736 c.CurveTo(x+w, y+h, x+w, y+h, x+w-10, y+h);
737 c.LineTo(x+10, y+h);
738 // 4
739 c.CurveTo(x, y+h, x, y+h, x, y+h-10);
741 // gniazda wejściowe
742 if(socketin.Length == 0)
743 c.LineTo(x, y+10);
744 else
746 int curpos = y+h-10-(h-20-CalcHeight(socketin.Length))/2;
748 c.LineTo(x, curpos);
750 for(int i=0; i<socketin.Length; i++)
752 if(i!=0)
754 curpos -= 5;
755 c.LineTo(x, curpos);
758 c.CurveTo(x+10, curpos, x+10, curpos-10, x, curpos-10);
759 curpos -= 10;
762 c.LineTo(x,y+10);
765 // 1
766 c.CurveTo(x, y, x, y, x+10, y);
769 private void DrawPathSquare(Context c)
771 // 1-------2
772 // | |
773 // | |
774 // 4-------3
776 // 1
777 c.MoveTo(x, y);
778 c.LineTo(x+w, y);
780 // 2
781 // gniazda wyjściowe
782 if(socketout.Length == 0)
783 c.LineTo(x+w, y+h);
784 else
786 int curpos = y+10+(h-20-CalcHeight(socketout.Length))/2;
788 c.LineTo(x+w, curpos);
790 for(int i=0; i<socketout.Length; i++)
792 if(i!=0)
794 curpos += 5;
795 c.LineTo(x+w, curpos);
798 c.LineTo(x+w-8, curpos);
799 c.LineTo(x+w-8, curpos+10);
800 c.LineTo(x+w, curpos+10);
802 curpos += 10;
805 c.LineTo(x+w,y+h);
808 // 3
809 c.LineTo(x, y+h);
811 // 4
812 // gniazda wejściowe
813 if(socketin.Length == 0)
814 c.LineTo(x, y);
815 else
817 int curpos = y+h-10-(h-20-CalcHeight(socketin.Length))/2;
819 c.LineTo(x, curpos);
821 for(int i=0; i<socketin.Length; i++)
823 if(i!=0)
825 curpos -= 5;
826 c.LineTo(x, curpos);
829 c.LineTo(x+8, curpos);
830 c.LineTo(x+8, curpos-10);
831 c.LineTo(x, curpos-10);
833 curpos -= 10;
836 c.LineTo(x,y+10);
840 c.LineTo(x, y);
841 c.LineTo(x+1, y);
844 private void DrawPathInner(Context c)
846 if(ConfigRound)
847 DrawPathInnerRound(c);
848 // TODO
849 // else
850 // DrawPathInnerSquare(c);
854 private void DrawPathInnerRound(Context c)
856 // 1-------2
857 // | |
858 // | |
859 // 4-------3
861 // 1
862 c.MoveTo(x+11.5, y+1.5);
863 c.LineTo(x+w-11.5, y+1.5);
864 // 2
865 c.CurveTo(x+w-1.5, y+1.5, x+w-1.5, y+1.5, x+w-1.5, y+8.5);
867 // gniazda wyjściowe
868 if(socketout.Length == 0)
869 c.LineTo(x+w-1.5, y+h-11.5);
870 else
872 int curpos = y+10+(h-20-CalcHeight(socketout.Length))/2;
874 c.LineTo(x+w-1.5, curpos-1.5);
876 for(int i=0; i<socketout.Length; i++)
878 if(i!=0)
880 curpos += 5;
881 c.LineTo(x+w-1.5, curpos-1.5);
884 c.CurveTo(x+w-11.5, curpos-1.5, x+w-11.5, curpos+11.5, x+w-1.5, curpos+11.5);
885 curpos += 10;
888 c.LineTo(x+w-1.5, y+h-8.5);
891 // 3
892 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);
893 c.LineTo(x+11.5, y+h-1.5);
894 // 4
895 c.CurveTo(x+1.5, y+h-1.5, x+1.5, y+h-1.5, x+1.5, y+h-8.5);
897 // gniazda wejściowe
898 if(socketin.Length == 0)
899 c.LineTo(x+1.5, y+11.5);
900 else
902 int curpos = y+h-10-(h-20-CalcHeight(socketin.Length))/2;
904 c.LineTo(x+1.5, curpos+1.5);
906 for(int i=0; i<socketin.Length; i++)
908 if(i!=0)
910 curpos -= 5;
911 c.LineTo(x+1.5, curpos+1.5);
914 c.CurveTo(x+11.5, curpos+1.5, x+11.5, curpos-11.5, x+1.5, curpos-11.5);
915 curpos -= 10;
918 c.LineTo(x+1.5, y+8.5);
921 // 1
922 c.CurveTo(x+1.5, y+1.5, x+1.5, y+1.5, x+11.5, y+1.5);
925 private void Invalidate(bool x)
927 Plugin.WorkDone = false;
928 Plugin.Invalidate();
930 for(int i=0; i<socketout.Length; i++)
932 Socket o = socketout[i].Other;
934 if(o != null && o.Parent.CheckState() == State.Good)
935 o.Parent.Invalidate(true);
939 public void Invalidate()
941 Invalidate(true);
942 schematic.QueueDraw();
945 public void SlotsChanged()
947 UpdateCoordinates();
949 if(socketin.Length != plugin.NumIn)
951 Socket[] newsocketin = new Socket[plugin.NumIn];
952 int curpos = 10+(h-20-CalcHeight(plugin.NumIn))/2;
954 for(int i=0; i<plugin.NumIn; i++)
956 if(i < socketin.Length)
957 newsocketin[i] = socketin[i];
958 else
959 newsocketin[i] = new Socket(0, curpos, this, Socket.T.In, i);
960 curpos += 15;
962 for(int i=plugin.NumIn; i<socketout.Length; i++)
963 socketout[i].Disconnect();
965 socketin = newsocketin;
967 else
969 int curpos = 10+(h-20-CalcHeight(socketin.Length))/2;
971 for(int i=0; i<socketin.Length; i++)
973 socketin[i].Y = curpos;
974 curpos += 15;
978 if(socketout.Length != plugin.NumOut)
980 Socket[] newsocketout = new Socket[plugin.NumOut];
981 int curpos = 10+(h-20-CalcHeight(plugin.NumOut))/2;
983 for(int i=0; i<plugin.NumOut; i++)
985 if(i < socketout.Length)
986 newsocketout[i] = socketout[i];
987 else
988 newsocketout[i] = new Socket(w-10, curpos, this, Socket.T.Out, i);
989 curpos += 15;
991 for(int i=plugin.NumOut; i<socketout.Length; i++)
992 socketout[i].Disconnect();
994 socketout = newsocketout;
996 else
998 int curpos = 10+(h-20-CalcHeight(socketout.Length))/2;
1000 for(int i=0; i<socketout.Length; i++)
1002 socketout[i].Y = curpos;
1003 curpos += 15;
1007 schematic.QueueDraw();
1008 Invalidate();