% Graph.sim % % Classes pour faire des reseaux graphiques avec des noeuds et des arcs % % Updated may 1997 (j. vaucher) !La classe NodeButton est une classe de bouton qui peut se deplacer dans sa fenetre parente si le un bouton de souris y est enfonce. Ces boutons sont lies a d'autres boutons (parents ou enfants). Les liens sont representes par des lignes. On veut ici que les lignes soient rafraichies lors du deplacement du bouton; Button CLASS NodeButton; BEGIN REF (dictionary) upper,lower; !liste de bouton parents et enfants; PROCEDURE upperpoint(x,y);NAME x,y;INTEGER x,y; !point central en haut; BEGIN x:=min_x+width//2+borderwidth; y:=min_y; END; PROCEDURE lowerpoint(x,y);NAME x,y;INTEGER x,y; !point central en bas; BEGIN x:=min_x+width//2+borderwidth; y:=max_y; END; Integer PROCEDURE HalfWidth; HalfWidth := width/2 + borderwidth; PROCEDURE DrawLinks(ChildrenAndParent);BOOLEAN ChildrenAndParent; !On dessine les liens aux enfants. Dessiner les lignes vers les parents est en option; BEGIN INTEGER x1,y1,x2,y2; PROCEDURE DrawToChild(el);REF (element) el; BEGIN el QUA NodeButton.upperpoint(x2,y2); parent.drawline(x1,y1,x2,y2); END; PROCEDURE DrawToParent(el);REF (element) el; BEGIN el QUA NodeButton.lowerpoint(x2,y2); parent.drawline(x1,y1,x2,y2); END; lowerpoint(x1,y1); lower.for_each_element(DrawToChild); IF ChildrenAndParent THEN BEGIN upperpoint(x1,y1); upper.for_each_element(DrawToParent); END; END; !Fonctions permettant d'etablir des liens parents-enfants entre boutons; PROCEDURE LinkChild(enfant);REF (NodeButton) enfant; BEGIN lower.insert(enfant); enfant.upper.insert(THIS NodeButton); END; PROCEDURE LinkParent(parent);REF (NodeButton) parent; BEGIN upper.insert(parent); parent.lower.insert(THIS NodeButton); END; ! on avertit la fenetre parent; PROCEDURE handle_button_down(b);INTEGER b; parent QUA Nodewindow.handle_node_select(THIS Button); PROCEDURE handle_button_up(b);INTEGER b; !Fin du drag; parent QUA Nodewindow.StopDrag; upper :- NEW simple_dictionary; lower :- NEW simple_dictionary; SetTypeFace("helvetica",8,true,false); SetSize( 2*width_of_text( " " ) + width_of_text( heading_and_key ) , head_height + 4*font_height//3 ); END; MainWindow CLASS Nodewindow; VIRTUAL: PROCEDURE StopDrag IS PROCEDURE StopDrag;; PROCEDURE StartDrag IS PROCEDURE StartDrag(sw);REF(SubWindow) sw;; BEGIN !Parmi les boutons dans Nodes, Drag est le bouton a deplacer; REF(Dictionary) Nodes; REF(NodeButton) Drag; BOOLEAN drag_allowed; PROCEDURE StartDrag(sw);REF(SubWindow) sw; BEGIN EXTERNAL c PROCEDURE xungrabpointer IS PROCEDURE Xungrabpointer;; XUngrabPointer; sw.Raise; Drag:-sw; END; PROCEDURE handle_node_select(sw);REF(SubWindow) sw; IF drag_allowed THEN StartDrag(sw); PROCEDURE StopDrag; Drag:-NONE; PROCEDURE allowdrag; drag_allowed:=TRUE; PROCEDURE disallowdrag; BEGIN drag_allowed:=FALSE; StopDrag; END; !On redessine les liens vers les enfants de chaque bouton; PROCEDURE NodeWindowrefresh; BEGIN PROCEDURE drawlinks(e);REF(element) e; e QUA NodeButton.DrawLinks(FALSE); Clear; Nodes.for_each_element(drawlinks); END; PROCEDURE refresh; NodeWindowRefresh; PROCEDURE handle_button_up(b);INTEGER b; StopDrag; !deplacer le bouton en mode "drag" s'il y en a un; PROCEDURE handle_pointer_motion(x,y); INTEGER x,y; IF Drag =/= NONE THEN BEGIN Drag.DrawLinks(TRUE); !garder le pointeur au centre du bouton a deplacer; Drag.placeAt(X-Drag.width//2,y-Drag.height//2); Drag.DrawLinks(TRUE); END; REF (NodeButton) PROCEDURE MakeNodeButton(l);TEXT l; BEGIN REF (NodeButton) nb; nb :- NEW NodeButton(THIS XWindow,l); nodes.insert(nb); MakeNodeButton :- nb; END; InvertGC; nodes :- NEW Dictionary; pointer_motion_sensitize; button_sensitize; END Nodewindow;