1 {
2 Define el frame que implementa la interfaz gráfica donde se muestra el PIC y al que
3 se le pueden agreagr compoentes electrónicos adicionales como leds, o pantallas LCD.
4
5 Creado por Tito Hinostroza 05/2018.
6 Modif. por Tito Hinostroza 08/2018.
7 }
8 unit FramePICDiagram;
9 {$mode objfpc}{$H+}
10 interface
11 uses
12 Classes, SysUtils, FileUtil, fgl, Types, Forms, Controls, ExtCtrls, Graphics,
13 Menus, ActnList, LCLProc, ogEditionMot, ogMotGraf2D, ogDefObjGraf, PicCore,
14 Parser, MisUtils;
15 type
16 { TPinGraph }
17 {Objeto que modela a un pin físico de un componente electrónico.
18 Se penso en usar el mismo tipo TpicCore.pines[] y usar ese arreglo como contenedor
19 de objetos TPinGraph, pero considerando que los pines están fuertemente asociados a
20 un punto de conexión, se decidió crearlo como una extensión de TPtoConx, así se
21 simplifica considerablemente la administración.}
22 TPinGraph = class(TPtoConx)
23 private //Parámetros del modelo interno del Pin
24 {Cuando es un componente común. se leerán estos parámetros, como modelo
25 del pin.}
26 vThev: single;
27 rThev: single;
28 procedure GetModel(out vThev0, rThev0: Single); //Devuelve parámetros del modelo eléctrico
29 procedure SetModel(vThev0, rThev0: Single); //Fija parámetros del modelo eléctrico
30 private //Valores de voltaje e impedancia del nodo al que se encuentra conectado
31 vNod: single;
32 rNod: single;
33 procedure SetNodePars(vNod0, rNod0: Single); //Fija parámetros debido al nodoconectado
34 private //Campos adicionales cuando es pin de un PIC
35 {Se necesita una referencia al PIC cuando este pin es parte de un PIC.}
36 pic : TPicCore;
37 nPin : integer; //Número de pin (del encapsulado)
38 private //Propiedades geométricas
39 x1, y1, x2, y2: Single; //Cordenadas cuando se representa como rectángulo
40 lbl : string; //Etiqueta
41 xLbl, yLbl: Single; //Posición de la etiqueta
42 public
43 //procedure GetThevNod(out vThev0, rThev0: Single);//Devuelve parámetros del modelo eléctrico
44 procedure SetLabel(xl, yl: Single; txt: string; align: TAlignment =
45 taLeftJustify);
46 constructor Create(mGraf: TMotGraf); //OJO: No es override
47 end;
48 TPicPinList = specialize TFPGObjectList<TPinGraph>; //Lista para gestionar los puntos de control
49
50 { TOgComponent }
51 {Incluye propiedades de los componentes para este editor gráfico.}
52 TOgComponent = class(TObjGraf)
53 private
54 public
55 Ref: string; //Nomenclatura única del componente: R1, R2, CI1
56 ShowRef: boolean;
57 xRef, yRef: Single; //Ubicación relativa de la etiqueta Ref
58 // pins: TPicPinList; //Lista de pines
AddPtoConexnull59 function AddPtoConex(xOff, yOff: Single): TPinGraph; override;
AddPinnull60 function AddPin(xCnx, yCnx, x1, y1, x2, y2: Single): TPinGraph;
61 constructor Create(mGraf: TMotGraf); override;
62 destructor Destroy; override;
63 end;
64
65 TNode = class;
66
67 { TOgConector }
68 TOgConector = class(TOgComponent)
69 private
70 OnConnect: procedure of object;
71 OnDisconnect: procedure of object;
72 nodParent: TNode;
73 PaintBox : TPaintBox; //Referencia al PaintBox donde se dibuja
74 ptos: array of TFPoint;
75 procedure PCtlConnect(pCtl: TPtoCtrl; pCnx: TPtoConx);
76 procedure PCtlDisconnect(pCtl: TPtoCtrl; pCnx: TPtoConx);
ConnectedTonull77 function ConnectedTo(ogCon: TOgConector): boolean;
78 public
IsSelectedBynull79 function IsSelectedBy(xr, yr: Integer): Boolean; override;
80 procedure Draw; override;
81 constructor Create(mGraf: TMotGraf); override;
82 destructor Destroy; override;
83 end;
84 TConnectorList = specialize TFPGObjectList<TOgConector>; //Lista para gestionar los puntos de control
85
86 { TNode }
87 TNode = class
88 private
89 vt, rt: Single;
90 connectorList: TConnectorList;
91 pinList : TPicPinList; //Lista de pines conectadas al nodo
92 procedure UpdateModel;
Containsnull93 function Contains(ogCon: TOgConector): boolean;
ConnectedTonull94 function ConnectedTo(ogCon: TOgConector): boolean;
95 procedure AddConnector(ogCon: TOgConector);
96 public
97 constructor Create;
98 destructor Destroy; override;
99 end;
100 TNodeList = specialize TFPGObjectList<TNode>; //Lista de nodos
101
102 { TOgPic }
103 //Define el objeto gráfico PIC
104 TOgPic = class(TOgComponent)
105 private
106 pic: TPicCore; //referencia al PIC
107 xpin: Single; //Posición X del Pin
108 nPinsDiag: Integer; //Número de pines a dibujar
109 nPinsSide: Integer;
110 public
111 procedure SetPic(pic0: TPicCore);
112 procedure Draw; override;
113 constructor Create(mGraf: TMotGraf); override;
114 destructor Destroy; override;
115 end;
116
117 { TOgLogicState }
118 //Define el objeto gráfico LogicState
119 TOgLogicState = class(TOgComponent)
120 private
121 ptos: array of TFPoint;
122 pin: TPinGraph;
123 public
124 //procedure SetState(Value: boolean);
125 procedure Draw; override;
126 constructor Create(mGraf: TMotGraf); override;
127 destructor Destroy; override;
128 end;
129
130 { TOgLedRed }
131 //Define el objeto Diodo Led
132 TOgLedRed = class(TOgComponent)
133 private
134 pin: TPinGraph;
135 public
136 //procedure SetState(Value: boolean);
137 procedure Draw; override;
138 constructor Create(mGraf: TMotGraf); override;
139 destructor Destroy; override;
140 end;
141
142 { TOg7Segment }
143 //Define el objeto Display de 7 segmentos
144 TOg7Segment = class(TOgComponent)
145 private
146 pinA: TPinGraph;
147 pinB: TPinGraph;
148 pinC: TPinGraph;
149 pinD: TPinGraph;
150 pinE: TPinGraph;
151 pinF: TPinGraph;
152 pinG: TPinGraph;
153 public
154 //procedure SetState(Value: boolean);
155 procedure Draw; override;
156 constructor Create(mGraf: TMotGraf); override;
157 destructor Destroy; override;
158 end;
159
160 { TOgResisten }
161 //Define el objeto Resistencia (Resistor)
162 TOgResisten = class(TOgComponent)
163 private
164 public
165 //procedure SetState(Value: boolean);
166 procedure Draw; override;
167 constructor Create(mGraf: TMotGraf); override;
168 destructor Destroy; override;
169 end;
170
171 { TfraPICDiagram }
172 TfraPICDiagram = class(TFrame)
173 acAddLogTog: TAction;
174 acGenDelObject: TAction;
175 acGenConnTo: TAction;
176 acAddConn: TAction;
177 acAddLed: TAction;
178 acAddResis: TAction;
179 acAdd7SegComC: TAction;
180 acGenReconn: TAction;
181 ActionList1: TActionList;
182 MenuItem1: TMenuItem;
183 MenuItem2: TMenuItem;
184 MenuItem4: TMenuItem;
185 MenuItem5: TMenuItem;
186 mnReconn: TMenuItem;
187 mnConnect: TMenuItem;
188 mnReset: TMenuItem;
189 mnRun: TMenuItem;
190 MenuItem3: TMenuItem;
191 mnAddLogicTog: TMenuItem;
192 mnStepOver: TMenuItem;
193 mnDelete: TMenuItem;
194 PaintBox1: TPaintBox;
195 PopupMenu1: TPopupMenu;
196 procedure acAdd7SegComCExecute(Sender: TObject);
197 procedure acAddConnExecute(Sender: TObject);
198 procedure acAddLedExecute(Sender: TObject);
199 procedure acAddLogTogExecute(Sender: TObject);
200 procedure acAddResisExecute(Sender: TObject);
201 procedure acGenConnToExecute(Sender: TObject);
202 procedure acGenDelObjectExecute(Sender: TObject);
203 procedure acGenReconnExecute(Sender: TObject);
204 private //Nombres y referencias
205 procedure connectorChange;
ExistsNamenull206 function ExistsName(AName: string): boolean;
UniqueNamenull207 function UniqueName(NameBase: string): string;
ExistsRefnull208 function ExistsRef(ARef: string): TOgComponent;
UniqueRefnull209 function UniqueRef(RefBase: string): string;
210 private //Manejo de nodos
211 nodeList: TNodeList;
212 procedure AddConnectorToNodes(ogCon: TOgConector);
213 procedure UpdateNodeList;
214 private
215 Fpic: TPicCore;
216 ogPic: TOgPic;
217 motEdi: TEditionMot;
218 procedure ConnectAction(Sender: TObject);
219 procedure fraPICDiagramKeyDown(Sender: TObject; var Key: Word;
220 Shift: TShiftState);
221 procedure motEdi_MouseUpRight(Shift: TShiftState; x, y: integer);
222 procedure motEdi_MouseDown(Sender: TObject; Button: TMouseButton;
223 Shift: TShiftState; X, Y: Integer);
224 procedure motEdi_MouseUp(Sender: TObject; Button: TMouseButton;
225 Shift: TShiftState; X, Y: Integer);
226 public
227 procedure Refrescar;
228 procedure SetCompiler(cxp0: TCompilerBase);
229 constructor Create(AOwner: TComponent) ; override;
230 destructor Destroy; override;
231 end;
232
233 implementation
234 {$R *.lfm}
235 const
236 SEP_PIN = 20; //Separación entre pines
237 LON_PIN = 10; //Longitud de pin
238 //Colores pro defecto
239 COL_CI = $404040; //Circuitos Integrados
240 COL_GND = $404040; //GND
241 COL_VCC = clRed; //Voltajes VCC
242 COL_HIM = $A0A0A0; //Alta impedancia
243 COL_RES = $9FE7F9; //Cuerpo de resistencias
244 const //ID para componentes
245 ID_PINGRAF = 1; //Un pin que desciende de un Punto de conexión
246 ID_COMPON = 10; //Componentes en general
247 ID_PIC = 11;
248 ID_CONNEC = 12;
249 ID_LEDRES = 13;
250 ID_RESIST = 14;
251 ID_7SEGME = 15;
252 ID_TOG_LOG = 16;
253
GetThevColnull254 function GetThevCol(vt, rt: Single): TColor;
255 {Devuelve un color que representa el estado de un circuito de Thevening.}
256 begin
257 if rt>1e+6 then begin
258 //Se considera alta impedancia
259 exit(COL_HIM);
260 end else begin
261 //Tiene potencial
262 if vt > 2.5 then begin
263 exit(COL_VCC);
264 end else begin
265 exit(COL_GND);
266 end;
267 end;
268 end;
ResParallelnull269 function ResParallel(r1, r2: Single): Single; inline;
270 begin
271 if r1+r2=0 then begin
272 exit(0)
273 end else begin
274 exit(r1*r2/(r1+r2));
275 end;
276 end;
277 { TNode }
278 procedure TNode.UpdateModel;
279 {Devuelve los parámetros de Thevening del nodo. Esto es útil para leer el voltaje del
280 nodo en cualquier momento, que es parte de un análisis común por nodos.}
281 var
282 pin: TPinGraph;
283 r0 : Single;
284 v1, r1, v2, r2: Single;
285 nResistor, nSource: integer; //Contadores y banderas
286 begin
287 //Casos especiales
288 if pinList.Count = 0 then begin
289 //Nodo sin conexiones
290 vt := 0;
291 rt := 1e+9; //Alta impedancia
292 end else if pinList.Count = 1 then begin
293 //Conectado a un solo pin
294 pinList[0].GetModel(vt, rt); //Mismo modelo del nodo
295 end else begin
296 //Conectado a varios pines
297 {Va simplificando por un lado las que son fuentes (en v1, r1)
298 y por otro las que son solo resistencias (en r0). La idea es que al final
299 se tenga:
300
301 +--[R1]---
302 |
303 [V1]
304 |
305 ---
306
307 Y por el otro:
308
309 ----+
310 |
311 [R0]
312 |
313 ---
314 }
315 nResistor := 0;
316 nSource := 0;
317 for pin in pinList do begin
318 pin.GetModel(v2, r2);
319 if v2 = 0 then begin
320 //Es resistencia pura
321 if nResistor=0 then begin
322 //Primera resistencia
323 r0 := r2; //toma su valor
324 end else begin
325 r0 := ResParallel(r0, r2); //Acumula en paralelo
326 end;
327 inc(nResistor); //Lleva la cuenta
328 end else begin
329 //Es fuente con resistencia
330 if nSource=0 then begin
331 //Primera fuente
332 v1 := v2; //Toma su valor
333 r1 := r2;
334 end else begin
335 if r1+r2 = 0 then begin
336 //Hay conexión directa de dos fuentes
337 {Se pone valor de voltaje promedio para evitar la indeterminación, pero
338 ralemnte debería generarse un error o advertencia.}
339 v1 := (v1+v2)/2;
340 end else begin
341 v1 := v2 + (v1-v2)*r2/(r1+r2);
342 end;
343 r1 := ResParallel(r1, r2);
344 end;
345 inc(nSource); //lleva la cuenta
346 end;
347 end;
348 //Ya se han explorado todos los pines. Ahora analzia lso casos
349 if nSource=0 then begin
350 //Todas son resistncias
351 vt := 0;
352 rt := r0; //Resistencia acumulada
353 end else if nResistor=0 then begin
354 //Todas son fuentes thevening
355 vt := v1; //Voltaje acumulado
356 rt := r1; //Resistencia acumulada
357 end else begin
358 //Caso general: Fuentes de thevening con resistencia:
359 vt := v1*r0/(r0 + r1);
360 rt := ResParallel(r0, r1);
361 end;
362 end;
363 //debugln('Nodo actualizado: %d fuentes, %d resist.', [nSource, nResistor]);
364 {Ahora que ya se tienen los valores de voltaje e impedancia del nodo, pasa esa
365 información a todos los pines de los componentes conectados, para uniformizar estados}
366 for pin in pinList do begin
367 pin.SetNodePars(vt, rt);
368 end;
369 end;
Containsnull370 function TNode.Contains(ogCon: TOgConector): boolean;
371 {Indica si el conector está en la lista de conectores del nodo.}
372 var
373 c: TOgConector;
374 begin
375 for c in connectorList do begin
376 if c = ogCon then exit(true);
377 end;
378 //No está
379 exit(false);
380 end;
ConnectedTonull381 function TNode.ConnectedTo(ogCon: TOgConector): boolean;
382 {Indica si el conector indicado, está eléctricamente conectado a este nodo.}
383 var
384 c: TOgConector;
385 begin
386 //Verifia si etsá conectado a alguno de los conectores del nodo
387 for c in connectorList do begin
388 if c.ConnectedTo(ogCon) then exit(true);
389 end;
390 //No está conectado a ningún conector
391 exit(false);
392 end;
393 procedure TNode.AddConnector(ogCon: TOgConector);
394 {Agrega un connector a la lista de conectores del nodo. Se supone que todo los
395 conectores de un nodo están eléctrticamenet conectados.}
396 procedure AddPinOf(pCtl: TPtoCtrl);
397 var
398 pin: TPinGraph;
399 begin
400 if pCtl.ConnectedTo<>nil then begin
401 if pCtl.ConnectedTo.Id = ID_PINGRAF then begin
402 pin := TPinGraph(pCtl.ConnectedTo);
403 if pinList.IndexOf(pin) = -1 then begin
404 //No existe el pin, lo agrega
405 pinList.Add(pin);
406 end;
407 end;
408 end;
409 end;
410 begin
411 connectorList.Add(ogCon);
412 ogCon.nodParent := self; //Guarda referencia
413 //También se guardan los pines a los que se encuentra conectado
414 AddPinOf(ogCon.pcBEGIN);
415 AddPinOf(ogCon.pcEND);
416 end;
417 constructor TNode.Create;
418 begin
419 connectorList:= TConnectorList.Create(false);
420 pinList := TPicPinList.Create(false);
421 end;
422 destructor TNode.Destroy;
423 begin
424 pinList.Destroy;
425 connectorList.Destroy;
426 inherited Destroy;
427 end;
428 { TPinGraph }
429 procedure TPinGraph.GetModel(out vThev0, rThev0: Single);
430 {Devuelve el equivalente de Thevening del pin. Equivale a devolver el modelo eléctrico
431 del pin, cuando está desconectado.}
432 begin
433 if pic = nil then begin
434 //No pertenece a un PIC, lee directamente sus parámetros
435 vThev0 := vThev;
436 rThev0 := rThev;
437 end else begin
438 //Es pin de un pic
439 pic.GetPinThev(nPin, vThev0, rThev0);
440 end;
441 end;
442 procedure TPinGraph.SetModel(vThev0, rThev0: Single);
443 begin
444 if pic = nil then begin
445 //No pertenece a un PIC, lee directamente sus parámetros
446 vThev := vThev0;
447 rThev := rThev0;
448 end else begin
449 //Es pin de un pic. No se puede cambiar
450 end;
451 end;
452 procedure TPinGraph.SetNodePars(vNod0, rNod0: Single);
453 {Fija los valores de voltaje que debe tener el pin, y la impedancia que debe ver,
454 por el efecto de estar conectado a algún nodo.
455 Se supone que ya se ha hecho el cálculo de voltaje/impedancia em el nodo.}
456 begin
457 if pic = nil then begin
458 //No pertenece a un PIC
459 vNod := vNod0;
460 rNod := rNod0;
461 end else begin
462 //Es parte de un PIC
463 pic.SetNodePars(nPin, vNod0, rNod0);
464 end;
465 end;
466 procedure TPinGraph.SetLabel(xl, yl: Single; txt: string;
467 align: TAlignment = taLeftJustify);
468 begin
469 lbl := txt;
470 yLbl := yl;
471 case align of
472 taLeftJustify: xLbl := xl; //Justificado a la
473 taRightJustify: xLbl := xl - v2d.TextWidth(txt);
474 end
475 end;
476 constructor TPinGraph.Create(mGraf: TMotGraf);
477 begin
478 inherited Create(mGraf);
479 {Se usa un ID porque identificar un objeto por ID es más rápido que usar
480 la comparación con: <variable> IS <Alguna Clase>.}
481 id := ID_PINGRAF;
482 end;
483 { TOgComponent }
TOgComponent.AddPtoConexnull484 function TOgComponent.AddPtoConex(xOff, yOff: Single): TPinGraph;
485 {Reescribimos nuestra propia función porque no vamos a agregar objetos TPtoConx,
486 sino objetos TPinGraph.}
487 begin
488 Result := TPinGraph.Create(v2d);
489 ////// Esta sección es similar al del método virtual AddPtoConex //////
490 Result.xFac := xOff/Width;
491 Result.yFac := yOff/Height;
492 //Actualiza coordenadas absolutas
493 Result.x := x + xOff;
494 Result.y := x + yOff;
495 Result.Parent := self;
496 PtosConex.Add(Result);
497 end;
TOgComponent.AddPinnull498 function TOgComponent.AddPin(xCnx, yCnx, //Coord. del punto de conexión
499 x1, y1, x2, y2: Single): TPinGraph;
500 var
501 pin: TPinGraph;
502 begin
503 pin := AddPtoConex(xCnx, yCnx);
504 pin.v2d := self.v2d;
505 pin.x1 := x1;
506 pin.y1 := y1;
507 pin.x2 := x2;
508 pin.y2 := y2;
509 pin.nPin := PtosConex.Count;
510 Result := pin;
511 end;
512 constructor TOgComponent.Create(mGraf: TMotGraf);
513 begin
514 Id := ID_COMPON;
515 inherited Create(mGraf);
516 end;
517 destructor TOgComponent.Destroy;
518 begin
519 inherited Destroy;
520 end;
521 { TOgConector }
522 procedure TOgConector.PCtlConnect(pCtl: TPtoCtrl; pCnx: TPtoConx);
523 {Un punto de control se conecta a un punto de conexión }
524 begin
525 if OnConnect<>nil then OnConnect();
526 end;
527 procedure TOgConector.PCtlDisconnect(pCtl: TPtoCtrl; pCnx: TPtoConx);
528 {Un punto de control se desconecta a un punto de conexión }
529 begin
530 if OnDisconnect<>nil then OnDisconnect();
531 end;
TOgConector.ConnectedTonull532 function TOgConector.ConnectedTo(ogCon: TOgConector): boolean;
533 {Verifica si hay conexión entre este conector y "ogCon"}
ConnectedSameConexionPointnull534 function ConnectedSameConexionPoint(p1, p2: TPtoCtrl): boolean;
535 {Indica si los puntos de control indicados, están conectados al mismo Punto
536 de Conexión.}
537 begin
538 if p1.ConnectedTo = nil then exit(false); //No está conectado a nada
539 if p2.ConnectedTo = nil then exit(false); //No está conectado a nada
540 if p1.ConnectedTo = p2.ConnectedTo then exit(true) else exit(false);
541 end;
542 begin
543 if ConnectedSameConexionPoint(pcBEGIN, ogCon.pcBEGIN) then exit(true);
544 if ConnectedSameConexionPoint(pcBEGIN, ogCon.pcEND) then exit(true);
545 if ConnectedSameConexionPoint(pcEND, ogCon.pcBEGIN) then exit(true);
546 if ConnectedSameConexionPoint(pcEND, ogCon.pcEND) then exit(true);
547 exit(false);
548 end;
IsSelectedBynull549 function TOgConector.IsSelectedBy(xr, yr: Integer): Boolean;
550 var
551 x0, y0, x1, y1: Integer;
552 begin
553 v2d.XYpant(pcBEGIN.x, pcBEGIN.y, x0, y0);
554 v2d.XYpant(pcEND.x, pcEND.y, x1, y1);
555 Result := PointSelectSegment(xr, yr, x0, y0, x1, y1 );
556 end;
557 procedure TOgConector.Draw;
558 const
559 ANCHO1 = 7;
560 ANCHO2 = 50;
561 ALTO1 = 10;
562 ALTO2 = 30;
563 var
564 col: TColor;
565 pct : TPtoCtrl;
566 pcn : TPtoConx;
567 x1, y1: Single;
568 pMouse: TPoint;
569 begin
570 //Descripción
571 //v2d.SetText(clBlack, 11,'', true);
572 //v2d.Texto(X + 2, Y -20, 'Conector');
573 //Cuerpo
574 col := GetThevCol(nodParent.vt, nodParent.rt); //Se supone que el nodo padre ya está actualizado
575 v2d.SetPen(psSolid, 1, col);
576 v2d.Line(pcBEGIN.x, pcBEGIN.y, pcEND.x, pcEND.y);
577 //Implementamos nosotros el remarcado y selección, para personalizar mejor
578 //---------------Draw mark --------------
579 if Marked and Highlight then begin
580 //Resaltado
581 v2d.SetPen(psSolid, 2, clBlue); //RGB(128, 128, 255)
582 v2d.Line(pcBEGIN.x, pcBEGIN.y, pcEND.x, pcEND.y);
583 //Marcador de Voltaje
584 v2d.SetPen(psSolid, 1, clBlack); //RGB(128, 128, 255)
585 v2d.SetBrush(clYellow);
586 pMouse := PaintBox.ScreenToClient(Mouse.CursorPos);
587 x1 := v2d.Xvirt(pMouse.x, pMouse.y);
588 y1 := v2d.Yvirt(pMouse.x, pMouse.y);
589 // v2d.RectangR(x1, y1, x1+10, y1+20);
590 ptos[0].x := x1;
591 ptos[0].y := y1;
592 ptos[1].x := x1+ANCHO1;
593 ptos[1].y := y1-ALTO1;
594 ptos[2].x := x1+ANCHO1;
595 ptos[2].y := y1-ALTO2;
596 ptos[3].x := x1+ANCHO2;
597 ptos[3].y := y1-ALTO2;
598 ptos[4].x := x1+ANCHO2;
599 ptos[4].y := y1-ALTO1;
600 ptos[5].x := x1+20;
601 ptos[5].y := y1-ALTO1;
602 v2d.Polygon(ptos);
603
604 v2d.SetText(True, False, False);
605 v2d.SetText(clBlack);
606 v2d.Texto(x1+ANCHO1+3, y1 - ALTO2+2, Format('%.2fV', [nodParent.vt]));
607 end;
608 //--------------- Draw selection state--------------
609 if Selected Then begin
610 if behav = behav1D then begin
611 for pct in PtosControl1 do pct.Draw; //Dibuja puntos de control
612 end else if behav = behav2D then begin
613 for pct in PtosControl2 do pct.Draw; //Dibuja puntos de control
614 end;
615 end;
616 //Draw Connection Points
617 if ShowPtosConex then begin
618 for pcn in PtosConex do pcn.Draw;
619 end;
620 //if MarkConnectPoints then begin
621 for pcn in PtosConex do if pcn.Marked then pcn.Mark;
622 //end
623 end;
624 constructor TOgConector.Create(mGraf: TMotGraf);
625 begin
626 inherited Create(mGraf);
627 Id := ID_CONNEC;
628 setlength(ptos, 6);
629 pcBEGIN.OnConnect := @PCtlConnect;
630 pcEND.OnConnect := @PCtlConnect;
631 pcBEGIN.OnDisconnect := @PCtlDisconnect;
632 pcEND.OnDisconnect := @PCtlDisconnect;
633 end;
634 destructor TOgConector.Destroy;
635 begin
636 inherited Destroy;
637 end;
638 { TOgPic }
639 procedure TOgPic.SetPic(pic0: TPicCore);
640 {Fija el dispositivo de trabajo y prepara las estructuras que
641 definen la geometría del componente, de modo que el dibujo sea rápido.}
642 var
643 newHeight, i: Integer;
644 ypin: Single;
645 pin: TPinGraph;
646 begin
647 pic := pic0; //Actualiza referencia
648 Name := pic0.Model;
649 //Define geometría del cuerpo del PIC
650 if pic.Npins <= 6 then begin
651 nPinsDiag := 6;
652 end else if pic.Npins <=8 then begin
653 nPinsDiag := 8;
654 end else if pic.Npins <=14 then begin
655 nPinsDiag := 14;
656 end else if pic.Npins <=18 then begin
657 nPinsDiag := 18;
658 end else if pic.Npins <=28 then begin
659 nPinsDiag := 28;
660 end else if pic.Npins <=40 then begin
661 nPinsDiag := 40;
662 end else begin
663 //Caso de muchos pines
664 nPinsDiag := 40;
665 end;
666 nPinsSide := nPinsDiag div 2; //Pines pro lado
667 newHeight := nPinsSide * SEP_PIN; //Altura del chip
668 //Actualiza tamaño. Se debe hacer antes de calcular las posiciones de los Ptos. de Conexión.
669 ReSize(Width, newHeight);
670 {Calcula posiciones relativas de los pines asumiendo un formato de encapsulado DIL.
671 Se crearán también los puntos de conexión en cada uno de los pines}
672 PtosConex.Clear; //Se aprovechará para crear puntos de conexión
673 //Pines de la izquierda
674 ypin := SEP_PIN/2; //posición inicial
675 xpin := -LON_PIN+3;
676 for i:=1 to nPinsSide do begin
677 //Pin
678 pin := AddPin(xpin, ypin-1,
679 xpin, ypin-5, xpin+LON_PIN+1, ypin+5);
680 pin.SetLabel(5, ypin-8, pic.pines[i].GetLabel);
681 pin.pic := pic0; //guarda referencia el PIC
682 //pin.lValue := @;
683 //Calcula siguiente posición
684 ypin := ypin + SEP_PIN;
685 end;
686 //Pines de la derecha
687 ypin := SEP_PIN/2 + (nPinsSide-1) * SEP_PIN; //posición inicial
688 xpin := width-3;
689 for i:=nPinsSide+1 to nPinsDiag do begin
690 //Pin
691 pin := AddPin(xpin+LON_PIN-1, ypin,
692 xpin, ypin-5, xpin+LON_PIN-1, ypin+5);
693 pin.SetLabel(xpin-2, ypin-8, pic.pines[i].GetLabel, taRightJustify);
694 pin.pic := pic0; //guarda referencia el PIC
695 //Calcula siguiente posición
696 ypin := ypin - SEP_PIN;
697 end;
698 //Actualiza posición.
699 Relocate(x, y); //Se mantiene la posición, pero se hace para actualizar a los puntos de conexión
700 end;
701 procedure TOgPic.Draw;
702 const
703 RAD_MARK = 15; //Radio de la marca superior del chip
704 var
705 ancho, rt, vt, xMed: Single;
706 pin : TPinGraph;
707 pCnx: TPtoConx;
708 begin
709 if pic= nil then begin
710 v2d.SetPen(psSolid, 1, clBlack);
711 v2d.SetBrush(clGray);
712 v2d.RectangR(x, y, x+Width, y+Height);
713 end else begin //Caso normal
714 xMed := x + width/2;
715 //Dibuja título
716 ancho := v2d.TextWidth(Name);
717 v2d.SetText(True, False, False);
718 v2d.Texto(xMed - ancho/2 , y - 18, Name);
719 //Dibuja cuerpo
720 v2d.SetText(False, False, False);
721 v2d.SetText($D0D0D0);
722 v2d.SetPen(psSolid, 1, clGray);
723 v2d.SetBrush(COL_CI);
724 v2d.RectangR(x, y, x+Width, y+Height); //fondo
725 v2d.SetBrush($202020);
726 v2d.RadialPie(xMed-RAD_MARK ,y-RAD_MARK, xMed+RAD_MARK,y+RAD_MARK,2880,2880);
727 //Dibuja los pines
728 for pCnx in self.PtosConex do begin
729 pin := TPinGraph(pCnx);
730 //En el PIC, los pines se pintan con el color del modelo interno
731 pin.GetModel(vt, rt);
732 v2d.SetBrush(GetThevCol(vt,rt)); //Rellena de acuerdo al estado
733 v2d.rectangR(x+pin.x1, y+pin.y1, x+pin.x2, y+pin.y2);
734 v2d.Texto(x+pin.xLbl, y+pin.yLbl, pin.lbl);
735 end;
736 end;
737 inherited;
738 end;
739 constructor TOgPic.Create(mGraf: TMotGraf);
740 begin
741 inherited Create(mGraf);
742 ID := ID_PIC;
743 Width := 140;
744 Height := 180;
745 // pcTOP_CEN.Visible := false;
746 // pcBOT_CEN.Visible := false;
747 // pcCEN_LEF.Visible := false;
748 // pcCEN_RIG.Visible := false;
749 SizeLocked := true;
750 // ShowPtosConex:=true; //Muestra los puntos de conexión
751 end;
752 destructor TOgPic.Destroy;
753 begin
754 inherited Destroy;
755 end;
756 { TOgLogicState }
757 procedure TOgLogicState.Draw;
758 var
759 ancho: Single;
760 begin
761 //Dibuja título
762 ancho := v2d.TextWidth(Name);
763 v2d.SetText(COL_GND);
764 v2d.SetText(True, False, False);
765 v2d.Texto(x + width/2 - ancho/2 , y - 18, Name);
766 //Dibuja cuerpo
767 v2d.SetPen(psSolid, 1, clBlack);
768 if pin.vThev>2.5 then begin
769 v2d.SetBrush(clRed)
770 end else begin
771 v2d.SetBrush(clGray);
772 end;
773 //v2d.RectangR(x, y, x+Width, y+Height);
774 ptos[0].x := x;
775 ptos[0].y := y;
776 ptos[1].x := x+20;
777 ptos[1].y := y;
778 ptos[2].x := x+30;
779 ptos[2].y := y+10;
780 ptos[3].x := x+20;
781 ptos[3].y := y+20;
782 ptos[4].x := x;
783 ptos[4].y := y+20;
784 v2d.Polygon(ptos);
785 inherited;
786 end;
787 constructor TOgLogicState.Create(mGraf: TMotGraf);
788 begin
789 inherited Create(mGraf);
790 id := ID_TOG_LOG;
791 setlength(ptos, 5);
792 Width := 30;
793 Height := 20;
794 pcTOP_CEN.Visible := false;
795 pcBOT_CEN.Visible := false;
796 pcCEN_LEF.Visible := false;
797 pcCEN_RIG.Visible := false;
798 SizeLocked := true;
799 pin := AddPin(30, 10, 0, 0, 0, 0);
800 pin.rThev := 0;
801 pin.vThev := 5; //voltios
802 //ShowPtosConex:=true;
803 end;
804 destructor TOgLogicState.Destroy;
805 begin
806 inherited Destroy;
807 end;
808 { TOgLedRed }
809 procedure TOgLedRed.Draw;
810 var
811 ancho, x2, y2, yled: Single;
812 begin
813 x2:=x+width;
814 yled := y + 40;
815 y2:=y+height;
816 //Dibuja título
817 ancho := v2d.TextWidth(Name);
818 v2d.SetText(COL_GND);
819 v2d.SetText(True, False, False);
820 v2d.Texto(x + width/2 - ancho/2 , y - 18, Name);
821 //Verifica valor lógico
822
823 //FState
824 //Dibuja cuerpo
825 v2d.SetPen(psSolid, 2, COL_GND);
826 //Línea vertioal y conexión a tierra
827 v2d.Line(x+12, y, x+12, y2);
828 v2d.Line(x+5, y2, x+19, y2);
829 //Resistencia
830 v2d.SetPen(psSolid, 1, COL_GND);
831 v2d.SetBrush(COL_RES);
832 v2d.RectangR(x+5, y+10, x2-5, y+35);
833 //Símbolo circular
834 if pin.vNod>2 then v2d.SetBrush(clRed)
835 else v2d.SetBrush(clGray);
836 v2d.Ellipse(x, yled, x+width, yled+24);
837 v2d.Ellipse(x+3, yled+3, x+width-3, yled+24-3);
838 inherited;
839 end;
840 constructor TOgLedRed.Create(mGraf: TMotGraf);
841 begin
842 inherited Create(mGraf);
843 id := ID_LEDRES;
844 Width := 24;
845 Height := 70;
846 pcTOP_CEN.Visible := false;
847 pcBOT_CEN.Visible := false;
848 pcCEN_LEF.Visible := false;
849 pcCEN_RIG.Visible := false;
850 SizeLocked := true;
851 pin := AddPin(12, 0, 0, 0, 0, 0);
852 pin.SetModel(0, 470); //0V, 470ohms. Por ahora se modela así
853 pin.lbl := 'VLed';
854 //ShowPtosConex:=true;
855 end;
856 destructor TOgLedRed.Destroy;
857 begin
858 inherited Destroy;
859 end;
860 { TOg7Segment }
861 procedure TOg7Segment.Draw;
862 var
863 ancho, x2, y2, x1, y1, y3: Single;
864 pCnx: TPtoConx;
865 pin: TPinGraph;
866 begin
867 //Dibuja título
868 ancho := v2d.TextWidth(Name);
869 v2d.SetText(COL_GND);
870 v2d.SetText(True, False, False);
871 v2d.Texto(x + width/2 - ancho/2 , y - 18, Name);
872 //Dibuja cuerpo
873 v2d.SetPen(psSolid, 2, COL_GND);
874 v2d.SetBrush(COL_HIM);
875 v2d.RectangR(x, y, x+Width, y+Height);
876 //Segmentos
877 x1 := x +10;
878 x2 := x+width-10;
879 y1 := y + 10;
880 y2 := y + 50;
881 y3 := y + 90;
882 //Segment A
883 if pinA.vNod>2 then begin
884 v2d.SetPen(psSolid, 1, clRed); v2d.SetBrush(clRed);
885 end else begin
886 v2d.SetPen(psSolid, 1, $808080); v2d.SetBrush($808080);
887 end;
888 v2d.RectangR(x1, y1-3, x2, y1+3);
889 //Segment B
890 if pinB.vNod>2 then begin
891 v2d.SetPen(psSolid, 1, clRed); v2d.SetBrush(clRed);
892 end else begin
893 v2d.SetPen(psSolid, 1, $808080); v2d.SetBrush($808080);
894 end;
895 v2d.RectangR(x2-3, y1+3, x2+3, y2-3);
896 //Segment C
897 if pinC.vNod>2 then begin
898 v2d.SetPen(psSolid, 1, clRed); v2d.SetBrush(clRed);
899 end else begin
900 v2d.SetPen(psSolid, 1, $808080); v2d.SetBrush($808080);
901 end;
902 v2d.RectangR(x2-3, y2+3, x2+3, y3-3);
903 //Segment D
904 if pinD.vNod>2 then begin
905 v2d.SetPen(psSolid, 1, clRed); v2d.SetBrush(clRed);
906 end else begin
907 v2d.SetPen(psSolid, 1, $808080); v2d.SetBrush($808080);
908 end;
909 v2d.RectangR(x1, y3-3, x2, y3+3);
910 //Segment E
911 if pinE.vNod>2 then begin
912 v2d.SetPen(psSolid, 1, clRed); v2d.SetBrush(clRed);
913 end else begin
914 v2d.SetPen(psSolid, 1, $808080); v2d.SetBrush($808080);
915 end;
916 v2d.RectangR(x1-3, y2+3, x1+3, y3-3);
917 //Segment F
918 if pinF.vNod>2 then begin
919 v2d.SetPen(psSolid, 1, clRed); v2d.SetBrush(clRed);
920 end else begin
921 v2d.SetPen(psSolid, 1, $808080); v2d.SetBrush($808080);
922 end;
923 v2d.RectangR(x1-3, y1+3, x1+3, y2-3);
924 //Segment G
925 if pinG.vNod>2 then begin
926 v2d.SetPen(psSolid, 1, clRed); v2d.SetBrush(clRed);
927 end else begin
928 v2d.SetPen(psSolid, 1, $808080); v2d.SetBrush($808080);
929 end;
930 v2d.RectangR(x1, y2-3, x2, y2+3);
931
932 //conexión a tierra
933 v2d.SetPen(psSolid, 1, COL_GND);
934 y2 := y + height + 10;
935 v2d.Line(x+30, y+height, x+30, y2);
936 v2d.Line(x+24, y2, x+36, y2);
937 //Dibuja los pines
938 v2d.SetPen(psSolid, 1, COL_GND);
939 for pCnx in PtosConex do begin
940 pin := TPinGraph(pCnx);
941 //En el PIC, los pines se pintan con el color del modelo interno
942 v2d.SetBrush(clWhite); //Rellena de acuerdo al estado
943 v2d.Line(pin.x, pin.y, pin.x+7, pin.y);
944 v2d.Texto(x+pin.xLbl, y+pin.yLbl, pin.lbl);
945 end;
946 inherited;
947 end;
948 constructor TOg7Segment.Create(mGraf: TMotGraf);
949 begin
950 inherited Create(mGraf);
951 id := ID_7SEGME;
952 Width := 60;
953 Height := 100;
954 pcTOP_CEN.Visible := false;
955 pcBOT_CEN.Visible := false;
956 pcCEN_LEF.Visible := false;
957 pcCEN_RIG.Visible := false;
958 SizeLocked := true;
959 pinA := AddPin(-7, 5, 0, 0, 0, 0);
960 pinA.SetModel(0, 680);
961 pinA.lbl := 'A';
962 pinB := AddPin(-7,20, 0, 0, 0, 0);
963 pinB.SetModel(0, 680);
964 pinB.lbl := 'B';
965 pinC := AddPin(-7,35, 0, 0, 0, 0);
966 pinC.SetModel(0, 680);
967 pinC.lbl := 'C';
968 pinD := AddPin(-7,50, 0, 0, 0, 0);
969 pinD.SetModel(0, 680);
970 pinD.lbl := 'D';
971 pinE := AddPin(-7,65, 0, 0, 0, 0);
972 pinE.SetModel(0, 680);
973 pinE.lbl := 'E';
974 pinF := AddPin(-7,80, 0, 0, 0, 0);
975 pinF.SetModel(0, 680);
976 pinF.lbl := 'F';
977 pinG := AddPin(-7,95, 0, 0, 0, 0);
978 pinG.SetModel(0, 680);
979 pinG.lbl := 'G';
980 //ShowPtosConex:=true;
981 end;
982 destructor TOg7Segment.Destroy;
983 begin
984 inherited Destroy;
985 end;
986 { TOgResisten }
987 procedure TOgResisten.Draw;
988 var
989 ancho, x2, y2: Single;
990 begin
991 x2:=x+width;
992 y2:=y+height;
993 //Dibuja título
994 ancho := v2d.TextWidth(Name);
995 v2d.SetText(COL_GND);
996 v2d.SetText(True, False, False);
997 v2d.Texto(x + width/2 - ancho/2 , y - 18, Name);
998 //Verifica valor lógico
999
1000 //Línea vertioal y conexión a tierra
1001 v2d.SetPen(psSolid, 2, COL_GND);
1002 v2d.Line(x+12, y, x+12, y2);
1003 v2d.Line(x+5, y2, x+19, y2);
1004 //Resistencia
1005 v2d.SetPen(psSolid, 1, COL_GND);
1006 v2d.SetBrush(COL_RES);
1007 v2d.RectangR(x+5, y+20, x2-5, y+50);
1008 inherited;
1009 end;
1010 constructor TOgResisten.Create(mGraf: TMotGraf);
1011 var
1012 pin: TPinGraph;
1013 begin
1014 inherited Create(mGraf);
1015 id := ID_RESIST;
1016 Width := 24;
1017 Height := 70;
1018 pcTOP_CEN.Visible := false;
1019 pcBOT_CEN.Visible := false;
1020 pcCEN_LEF.Visible := false;
1021 pcCEN_RIG.Visible := false;
1022 SizeLocked := true;
1023 pin := AddPin(12, 0, 0, 0, 0, 0);
1024 pin.rThev := 1000;
1025 pin.vThev := 0;
1026 //ShowPtosConex:=true;
1027 end;
1028 destructor TOgResisten.Destroy;
1029 begin
1030 inherited Destroy;
1031 end;
1032 { TfraPICDiagram }
1033 procedure TfraPICDiagram.Refrescar;
1034 var
1035 nod: TNode;
1036 begin
1037 {Aqui debería hacerse la actualización del PIC, y de los otros elementos que se mueven
1038 con reloj.}
1039 //pic.ExecNCycle()
1040 {Actualiza el estado de los Nodos porqu se supone que los voltajes o resisetncias de
1041 los componentes pueden haber cambiado (Como los pines de salida del PIC).}
1042 if nodeList <> nil then begin
1043 for nod in nodeList do begin
1044 nod.UpdateModel;
1045 end;
1046 end; //Protección
1047 motEdi.Refresh;
1048 end;
1049 procedure TfraPICDiagram.SetCompiler(cxp0: TCompilerBase);
1050 begin
1051 Fpic := cxp0.picCore;
1052 //Inicia dispositivo
1053 ogPic.SetPic(cxp0.picCore);
1054 //Al fijar el PIC, se elimina y crea un nuevo PIC,por ello hay que llamar a UpdateNodeList().
1055 UpdateNodeList;
1056 end;
1057 procedure TfraPICDiagram.fraPICDiagramKeyDown(Sender: TObject; var Key: Word;
1058 Shift: TShiftState);
1059 begin
1060 MsgBox('fraPICDiagramKeyDown');
1061 end;
1062 procedure TfraPICDiagram.ConnectAction(Sender: TObject);
1063 var
1064 mnItem: TMenuItem;
1065 oc: TOgConector;
1066 a: TStringDynArray;
1067 comp1, comp2: TOgComponent;
1068 nPin1, nPin2: LongInt;
1069 pCnx1, pCnx2: TPtoConx;
1070 pin1 , pin2: TPinGraph;
1071 id1, id2: String;
1072 begin
1073 if Sender is TMenuItem then begin
1074 mnItem := TMenuItem(Sender);
1075 //Agrega conector
1076 acAddConnExecute(self);
1077 oc := TOgConector(motEdi.Selected);
1078 //Ubica nodo Inicial
1079 // MsgBox(mnItem.Hint);
1080 a := Explode('-', mnItem.Hint);
1081 id1 := a[0];
1082 id2 := a[1];
1083 a := Explode('.', id1);
1084 comp1 := ExistsRef(a[0]);
1085 nPin1 := StrToInt(a[1]);
1086 pCnx1 := comp1.PtosConex[nPin1-1];
1087 if not(pCnx1 is TPinGraph) then exit;
1088 pin1 := TPinGraph(pCnx1);
1089 //Ubica nodo final
1090 a := Explode('.', id2);
1091 comp2 := ExistsRef(a[0]);
1092 nPin2 := StrToInt(a[1]);
1093 pCnx2 := comp2.PtosConex[nPin2-1];
1094 if not(pCnx2 is TPinGraph) then exit;
1095 pin2 := TPinGraph(pCnx2);
1096 //Ahora se conecta el conector a los Punttos de Conexión
1097 pin1.ConnectTo(oc.pcBEGIN);
1098 pin1.Locate(pin1.x, pin1.y); //Actualiza el "enganche"
1099 pin2.ConnectTo(oc.pcEND);
1100 pin2.Locate(pin2.x, pin2.y); //Actualiza el "enganche"
1101 //oc.Selec; //Selecciona el conector
1102 Refrescar;
1103 end;
1104 end;
1105 //Manejo de nodos
1106 procedure TfraPICDiagram.AddConnectorToNodes(ogCon: TOgConector);
1107 {Agrega un conector al nodo que corresponda (al que contiene conectores que están
1108 unidos eléctricamente a "conn"), o crea un nuevo nodo.}
1109 var
1110 nod, newNode: TNode;
1111 begin
1112 for nod in nodeList do begin
1113 if nod.Contains(ogCon) then begin
1114 //Ya lo contiene en su lista. No hay nada que hacer.
1115 exit;
1116 end else if nod.ConnectedTo(ogCon) then begin
1117 //Está eléctricamente conectado, pero no está en la lista
1118 nod.AddConnector(ogCon); //Lo agrega
1119 exit;
1120 end;
1121 end;
1122 //No pertenece a ningún nodo existente.
1123 newNode := TNode.Create; //Se crea con sus listas de conectores y pines vacías
1124 newNode.AddConnector(ogCon);
1125 nodeList.Add(newNode);
1126 end;
1127 procedure TfraPICDiagram.UpdateNodeList;
1128 {Actualiza la lista de nodos a partir de los conectores existentes. Esta tarea
1129 es importante para realizar el análisis correcto del voltaje e impedancia del nodo.
1130 Como esta tarea puede ser algo pesada, por optimización se debe realizar solo cuando
1131 se pueda producir cambios en los nodos (creación, eliminación, conexión y desconexión)}
1132 var
1133 og: TObjGraf;
1134 ogCon: TOgConector;
1135 begin
1136 nodeList.Clear;
1137 //Explora objetos gráfiocs
1138 for og in motEdi.objects do begin
1139 if og is TOgConector then begin
1140 ogCon := TOgConector(og);
1141 AddConnectorToNodes(ogCon);
1142 end;
1143 end;
1144 //debugln('Lista de Nodos:');
1145 //for nod in nodeList do begin
1146 // debugln(' Nodo con '+IntToStr(nod.connectorList.Count)+' conectores.');
1147 //end;
1148 end;
ExistsNamenull1149 function TfraPICDiagram.ExistsName(AName: string): boolean;
1150 {Indica si existe algún componente con el nombre AName}
1151 var
1152 og: TObjGraf;
1153 begin
1154 for og in motEdi.objects do begin
1155 if og.Name = AName then exit(true);
1156 end;
1157 exit(false);
1158 end;
TfraPICDiagram.UniqueNamenull1159 function TfraPICDiagram.UniqueName(NameBase: string): string;
1160 {Obtiene un nombre único tomando como base la cadena "NameBase", de modo que si
1161 en "NameBase" se indica "Nombre", se generará los nombres Nombre1, Nombre2, ... }
1162 var
1163 n: Integer;
1164 begin
1165 n := 1; //Empieza con este valor
1166 Result := NameBase + IntToStr(n); //Nombre tentativo
1167 While ExistsName(Result) do begin
1168 Inc(n);
1169 Result := NameBase + IntToStr(n);
1170 end;
1171 end;
ExistsRefnull1172 function TfraPICDiagram.ExistsRef(ARef: string): TOgComponent;
1173 {Indica si existe algún componente con la referencia Aref. Si no existe devuelve NIL.}
1174 var
1175 og: TObjGraf;
1176 begin
1177 for og in motEdi.objects do begin
1178 if not(og is TOgComponent) then continue;
1179 if TOgComponent(og).Ref = ARef then exit(TOgComponent(og));
1180 end;
1181 exit(Nil);
1182 end;
TfraPICDiagram.UniqueRefnull1183 function TfraPICDiagram.UniqueRef(RefBase: string): string;
1184 {Obtiene una referencia única tomando como base la cadena "RefBase", de modo que si
1185 en "RefBase" se indica "R", se generará los nombres R1, R2, R3, ... }
1186 var
1187 n: Integer;
1188 begin
1189 n := 1; //Empieza con este valor
1190 Result := RefBase + IntToStr(n); //Nombre tentativo
1191 While ExistsRef(Result)<>nil do begin
1192 Inc(n);
1193 Result := RefBase + IntToStr(n);
1194 end;
1195 end;
1196 procedure TfraPICDiagram.motEdi_MouseDown(Sender: TObject; Button: TMouseButton;
1197 Shift: TShiftState; X, Y: Integer);
1198 var
1199 LogInp: TOgLogicState;
1200 //pCnx: TPtoConx;
1201 //oc: TOgConector;
1202 //xv, yv: Single;
1203 begin
1204 if motEdi.selection.Count = 1 then begin
1205 //Hay uno seleccionado
1206 if motEdi.Selected.IsSelectedBy(X,Y) then begin
1207 //Click sobre un objeto seleccionado
1208 if motEdi.Selected is TOgLogicState then begin
1209 LogInp := TOgLogicState(motEdi.Selected);
1210 LogInp.pin.vThev := 5;
1211 Refrescar;
1212 //MsgBox('TOggle');
1213 end;
1214 end;
1215 end;
1216 //Verifica si se inicia la conexión de un pin
1217 // if Button = mbLeft then begin
1218 // pCnx := motEdi.ConnectionPointMarked;
1219 // if pCnx <> nil then begin
1220 // //Se soltó en con un punto de conexión marcado
1221 // oc := TOgConector.Create(motEdi.v2d); //Crea objeto
1222 // oc.behav := behav1D; //De tipo conector
1223 // motEdi.AddGraphObject(oc); //Lo agrega al editor
1224 // //Ahora se conecta un nodo (Punto de control) al Pto. de Conexión
1225 // pCnx.ConnectTo(oc.pcBEGIN);
1226 // pCnx.Locate(pCnx.x, pCnx.y); //Actualiza el "enganche"
1227 // oc.Selec; //Selecciona el conector
1228 // motEdi.v2d.XYvirt(X, Y, xv, yv); //Obtiene coordenadas del mouse
1229 // //oc.pcEND.Locate(xv+50, yv+50); //Posiciona Punto final del conector
1230 // oc.pcEND.OnChangePosition(oc.pcEND, 0, 0, xv+20, yv+20);
1231 // //oc.ReSize(oc.Width, oc.Height);
1232 // motEdi.CapturoEvento := oc; //Indica al motor de edición que el conector se está dimensionando
1233 // motEdi.EstPuntero := EP_DIMEN_OBJ; //Pone editor en modo "Dimensionando"
1234 // motEdi.Refrescar; //Actualiza pantalla
1235 // end;
1236 // end;
1237 end;
1238 procedure TfraPICDiagram.motEdi_MouseUp(Sender: TObject; Button: TMouseButton;
1239 Shift: TShiftState; X, Y: Integer);
1240 var
1241 LogInp: TOgLogicState;
1242 begin
1243 if motEdi.selection.Count = 1 then begin
1244 //Hay un componente seleccionado
1245 if motEdi.Selected.IsSelectedBy(X,Y) then begin
1246 if motEdi.Selected is TOgLogicState then begin
1247 LogInp := TOgLogicState(motEdi.Selected);
1248 LogInp.pin.vThev := 0;
1249 end;
1250 end;
1251 end;
1252 end;
1253 procedure TfraPICDiagram.motEdi_MouseUpRight(Shift: TShiftState; x, y: integer);
1254 procedure VisibActionsAdd(State: boolean);
1255 begin
1256 acAddLogTog.Visible := State;
1257 acAddLed.Visible := State;
1258 acAddConn.Visible := State;
1259 acAddResis.Visible := State;
1260 acAdd7SegComC.Visible := State;
1261 end;
1262 var
1263 og: TObjGraf;
1264 it, it2: TMenuItem;
1265 pin2, pin1: TPinGraph;
1266 comp1, comp2: TOgComponent;
1267 pCnx, pCnx2: TPtoConx;
1268 begin
1269 //Verifica el estado para activar acciones
1270 acGenDelObject.Visible := motEdi.selection.Count>0;
1271 if motEdi.selection.Count = 0 then begin
1272 //Ninguno seleccionado
1273 mnReset.Visible := true;
1274 mnRun.Visible := true;
1275 mnStepOver.Visible:= false;
1276 //mnAddLogicTog.Visible := true;
1277 VisibActionsAdd(true);
1278 end else if (motEdi.selection.Count = 1) and (motEdi.Selected is TOgComponent) then begin
1279 //Hay un componente seleccionado
1280 comp1 := TOgComponent(motEdi.Selected); //Componente fuente
1281 mnReset.Visible := true;
1282 mnRun.Visible := true;
1283 mnStepOver.Visible:= true;
1284 //mnAddLogicTog.Visible := false;
1285 VisibActionsAdd(false);
1286 end else begin
1287 //Se ha seleccionado otra cosa o hay varios seleccionados
1288 mnReset.Visible := false;
1289 mnRun.Visible := false;
1290 mnStepOver.Visible:= false;
1291 //mnAddLogicTog.Visible := false;
1292 VisibActionsAdd(false);
1293 end;
1294 //Verifica la funcionalidad del menú de "Conectar a"
1295 //Verifica si se está marcado un punto de Conexión
1296 pCnx := motEdi.ConnectionPointMarked;
1297 if pCnx = nil then begin
1298 mnConnect.Visible := false;
1299 end else begin
1300 mnConnect.Visible := true;
1301 //mnAddLogicTog.Visible := false; //Para que no confunda
1302 VisibActionsAdd(false);
1303 //Ubica componente de origen
1304 if not(pCnx.Parent is TOgComponent) then exit;
1305 comp1 := TOgComponent(pCnx.Parent);
1306 pin1 := TPinGraph(pCnx); //El Pto. de Conex. debe ser un pin
1307 if (comp1 = nil) or (pin1=nil) then exit; //Protección
1308 mnConnect.Caption := Format('Connect %s to', [pin1.lbl]);
1309 //Actualiza menú de Conexión, con objetos gráficos
1310 mnConnect.Clear;
1311 for og in motEdi.objects do begin
1312 if not(og is TOgComponent) then continue;
1313 if og is TOgConector then continue;;
1314 it := AddItemToMenu(mnConnect, og.Name, nil);
1315 comp2 := TOgComponent(og);
1316 for pCnx2 in comp2.PtosConex do begin
1317 pin2 := TPinGraph(pCnx2);
1318 if pin2.lbl = 'NC' then continue; //No conectado
1319 if pin2 = nil then continue;
1320 it2 := AddItemToMenu(it, pin2.lbl, @ConnectAction);
1321 it2.Hint := comp1.Ref + '.' + IntToStr(pin1.nPin)+'-'+
1322 comp2.Ref + '.' + IntToStr(pin2.nPin);
1323 end;
1324 end;
1325 end;
1326 //Muestra
1327 PopupMenu1.PopUp;
1328 end;
1329 constructor TfraPICDiagram.Create(AOwner: TComponent);
1330 begin
1331 inherited Create(AOwner);
1332 //crea motor de edición
1333 motEdi := TEditionMot.Create(PaintBox1);
1334 nodeList := TNodeList.Create(true);
1335 //agrega objeto
1336 ogPic := TOgPic.Create(motEdi.v2d);
1337 ogPic.Ref := 'CI1';
1338 ogPic.Highlight := false;
1339
1340 motEdi.AddGraphObject(ogPic);
1341 OnKeyDown := @fraPICDiagramKeyDown;
1342 motEdi.OnMouseDownLeft := @motEdi_MouseDown;
1343 motEdi.OnMouseUp := @motEdi_MouseUp;
1344 motEdi.OnMouseUpRight := @motEdi_MouseUpRight;
1345 end;
1346 destructor TfraPICDiagram.Destroy;
1347 begin
1348 nodeList.Destroy;
1349 {Marca "nodeList" en NIL porque cuando se destruye "motEdi", si es que hay connectores,
1350 unidos a algún componente, estos intentarán llamar a "UpdateNodeList", cuando se
1351 desconecten, al momento de destruirse, y "UpdateNodeList" intentaría acceder a "nodeList"}
1352 nodeList := nil;
1353 motEdi.Destroy;
1354 inherited Destroy;
1355 end;
1356 procedure TfraPICDiagram.connectorChange;
1357 begin
1358 if nodeList = nil then exit; //Protección
1359 UpdateNodeList;
1360 end;
1361 /////////////////////// Acciones /////////////////////////
1362 procedure TfraPICDiagram.acGenConnToExecute(Sender: TObject);
1363 {Connecta el Pin de un objeto a otro.
1364 No se implementa aquí porque se implementa de forma dinámica.}
1365 begin
1366 end;
1367 procedure TfraPICDiagram.acAddLogTogExecute(Sender: TObject);
1368 {Agrega un Objeto Gráfico LogicToggle}
1369 var
1370 logTog: TOgLogicState;
1371 begin
1372 logTog := TOgLogicState.Create(motEdi.v2d);
1373 logTog.Highlight := false;
1374 logTog.Name := UniqueName('Logic');
1375 logTog.Ref := UniqueRef('LG'); //Genera nombe único
1376 motEdi.AddGraphObject(logTog);
1377 logTog.Selec;
1378 Refrescar;
1379 end;
1380 procedure TfraPICDiagram.acAddResisExecute(Sender: TObject);
1381 {Agrega un Objeto Gráfico Resistencia}
1382 var
1383 res: TOgResisten;
1384 begin
1385 res := TOgResisten.Create(motEdi.v2d);
1386 res.Highlight := false;
1387 res.Name := UniqueName('R');
1388 res.Ref := UniqueRef('R'); //Genera nombe único
1389 motEdi.AddGraphObject(res);
1390 res.Selec;
1391 Refrescar;
1392 end;
1393 procedure TfraPICDiagram.acAddLedExecute(Sender: TObject);
1394 {Agrega un Objeto Gráfico Led}
1395 var
1396 led: TOgLedRed;
1397 begin
1398 led := TOgLedRed.Create(motEdi.v2d);
1399 led.Highlight := false;
1400 led.Name := UniqueName('Led');
1401 led.Ref := UniqueRef('D'); //Genera nombe único
1402 motEdi.AddGraphObject(led);
1403 led.Selec;
1404 Refrescar;
1405 end;
1406 procedure TfraPICDiagram.acAddConnExecute(Sender: TObject);
1407 var
1408 conn: TOgConector;
1409 begin
1410 conn := TOgConector.Create(motEdi.v2d);
1411 conn.behav := behav1D; //De tipo conector
1412 //conn.Highlight := false;
1413 conn.Name := UniqueName('Connector');
1414 conn.Ref := UniqueRef('CN'); //Genera nombe único
1415 conn.OnConnect := @connectorChange;
1416 conn.OnDisconnect := @connectorChange;
1417 conn.PaintBox := PaintBox1; //Necesita esta referencia
1418 motEdi.AddGraphObject(conn);
1419 conn.Selec;
1420 UpdateNodeList;
1421 Refrescar;
1422 end;
1423 procedure TfraPICDiagram.acAdd7SegComCExecute(Sender: TObject);
1424 {Agrega un Objeto "Display" de 7 segmentos}
1425 var
1426 led: TOg7Segment;
1427 begin
1428 led := TOg7Segment.Create(motEdi.v2d);
1429 led.Highlight := false;
1430 led.Name := UniqueName('V7S');
1431 led.Ref := UniqueRef('V7S'); //Genera nombe único
1432 motEdi.AddGraphObject(led);
1433 led.Selec;
1434 Refrescar;
1435 end;
1436 procedure TfraPICDiagram.acGenDelObjectExecute(Sender: TObject);
1437 {Elimina un Objeto Gráfico.}
1438 begin
1439 if ogPic.Selected then begin
1440 MsgExc('Cannot delete PIC device.');
1441 ogPic.Deselec;
1442 end;
1443 //Elimina elementos seleccionados
1444 motEdi.DeleteSelected;
1445 UpdateNodeList;
1446 end;
1447 procedure TfraPICDiagram.acGenReconnExecute(Sender: TObject);
1448 {Reconecta componentes del diagrama, de acuerdo a las coordenadas de los conectores.}
1449 var
1450 og: TObjGraf;
1451 ogCon: TOgConector;
1452 xp, yp: Integer;
1453 selPntCnx: TPtoConx;
1454 begin
1455 nodeList.Clear;
1456 //Explora objetos gráfiocs
1457 for og in motEdi.objects do begin
1458 if og is TOgConector then begin
1459 ogCon := TOgConector(og);
1460 if ogCon.pcBEGIN.ConnectedTo = nil then begin
1461 motEdi.v2d.XYpant(ogCon.pcBEGIN.x, ogCon.pcBEGIN.y, xp, yp);
1462 selPntCnx := motEdi.SelectPointOfConexion(xp, yp, 2);
1463 if selPntCnx <> nil then selPntCnx.ConnectTo(ogCon.pcBEGIN);
1464 end;
1465 if ogCon.pcEND.ConnectedTo = nil then begin
1466 motEdi.v2d.XYpant(ogCon.pcEND.x, ogCon.pcEND.y, xp, yp);
1467 selPntCnx := motEdi.SelectPointOfConexion(xp, yp, 2);
1468 if selPntCnx <> nil then selPntCnx.ConnectTo(ogCon.pcEND);
1469 end;
1470 end;
1471 end;
1472 UpdateNodeList;
1473 end;
1474
1475 end.
1476
1477