/* This file is part of the FElt finite element analysis package. Copyright (C) 1993-2000 Jason I. Gobat and Darren C. Atkinson This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ # include # include # include # include # include # include # include "fe.h" # include "Constraint.h" # include "Canvas.h" # include "Drawing.h" # include "procedures.h" # include "problem.h" # include "globals.h" # include "vfe.h" # include "text_entry.h" # include "objects.h" # include "error.h" # include "Node.h" extern ConstraintDialog constraint_d; extern NodeDialog node_d; void EditAddNode () { if (ConstraintDialogActive (constraint_d) == NULL) { error ("No active constraint defined."); return; } SetEditMode ( ); ChangeStatusLine ("Nodal coordinates:", True); XtRemoveAllCallbacks (drawing, XtNbuttonCallback); XtAddCallback (drawing, XtNbuttonCallback, AddNodeCB, NULL); XtOverrideTranslations (entry, XtParseTranslationTable ("Return: AddNodeAP()")); } void AddNodeCB (w, client_data, call_data) Widget w; XtPointer client_data, call_data; { DrawingReport *report; report = (DrawingReport *) call_data; if (report -> event -> type != ButtonPress) return; if (report -> event -> xbutton.button == 1) DoAddNode (report -> snapped.x, report -> snapped.y, 0.0); if (report -> event -> xbutton.button == 3) QuitEdit ( ); } void AddNodeAP () { char *status; float x,y,z = 0; status = GetTextCoordinates (&x, &y, NULL); if (status == NULL) DoAddNode (x, y, z); } void DoAddNode (x, y, z) float x,y,z; { char message [40]; Node node; unsigned max; node = (Node) TreeMaximum (problem.node_tree); max = node != NULL ? node -> number : 0; node = CreateNode (max + 1); node -> constraint = ConstraintDialogActive (constraint_d); node -> x = x; node -> y = y; node -> z = z; DrawNode (node); sprintf (message, "Added node %d. Nodal coordinates:", node -> number); ChangeStatusLine (message, True); /* The node dialog needs to know that the new node is in the tree before it can display it. */ NodeDialogUpdate (node_d, problem.node_tree, NULL, NULL); NodeDialogDisplay (node_d, node); changeflag = True; } static Node moved_node; static Figure moved_figure; static Figure ghost_figure; static FigureAttributes attr; static int MoveNode (item) Item item; { unsigned i; unsigned numnodes; Element element = (Element) item; Drawn drawn; numnodes = element -> definition -> shapenodes; for (i = 1; i <= numnodes; i ++) if (element -> node [i] == moved_node) { DW_GetAttributes (drawing, ((Drawn) element -> aux) -> figure, &attr); attr.points [i - 1].x = moved_node -> x; attr.points [i - 1].y = moved_node -> y; if (numnodes > 2 && i == 1) { attr.points [numnodes].x = moved_node -> x; attr.points [numnodes].y = moved_node -> y; } drawn = (Drawn) element -> aux; DW_SetAttributes (drawing, drawn -> figure, DW_FigurePoints, &attr); if (drawn -> label != NULL) { ComputeCenter (element, &attr.x, &attr.y); DW_SetAttributes (drawing,drawn->label,DW_FigureLocation,&attr); } } return 0; } void DoWalkNode (node) Node node; { Drawn drawn; moved_node = node; attr.x = node -> x; attr.y = node -> y; drawn = (Drawn) node -> aux; if (drawn == NULL) { DrawNode (node); drawn = (Drawn) node -> aux; } DW_SetAutoRedraw (drawing, False); DW_SetAttributes (drawing, drawn -> figure, DW_FigureLocation, &attr); DW_SetAttributes (drawing, drawn -> label, DW_FigureLocation, &attr); (void) TreeSetIterator (problem.element_tree, MoveNode); (void) TreeIterate (problem.element_tree); DW_SetAutoRedraw (drawing, True); NodeDialogDisplay (node_d, node); changeflag = True; } void DeleteNodeGroup (figures, nfigures) Figure *figures; unsigned nfigures; { unsigned i; Figure fig; Drawn drawn; Node node; unsigned numleft; Boolean firsttime; Boolean newinfo; numleft = 0; firsttime = True; newinfo = False; for (i = 0; i < nfigures; i ++) { fig = figures [i]; DW_GetAttributes (drawing, fig, &attr); if (attr.user_data == NULL || attr.type == TextFigure) continue; node = (Node) attr.user_data; drawn = (Drawn) node -> aux; if (drawn -> type != DrawnNode) continue; if (drawn -> ref_count) { numleft ++; continue; } if (firsttime == True) { firsttime = False; DW_SetAutoRedraw (drawing, False); } newinfo = True; DW_RemoveFigure (drawing, drawn -> figure); DW_RemoveFigure (drawing, drawn -> label); (void) TreeDelete (problem.node_tree, node); DestroyNode (node); } if (newinfo) { NodeDialogDisplay (node_d, NULL); NodeDialogUpdate (node_d, problem.node_tree, NULL, NULL); } if (firsttime == False) { DW_SetAutoRedraw (drawing, True); changeflag = True; } if (numleft) error ("Warning: elements still reference %d node%s.", numleft, numleft > 1 ? "s" : ""); XtFree ((char *) figures); } void DoDeleteNode (node) Node node; { static char message [80]; Drawn drawn = (Drawn) node -> aux; Node newnode; if (drawn -> ref_count) { error ("Node %d is still referenced by %d element%s.", node -> number, drawn -> ref_count, drawn -> ref_count > 1 ? "s" : ""); return; } if (drawn -> figure != NULL) { DW_SetAutoRedraw (drawing, False); DW_RemoveFigure (drawing, drawn -> figure); if (drawn -> label != NULL) DW_RemoveFigure (drawing, drawn -> label); DW_SetAutoRedraw (drawing, True); } sprintf (message, "Node %d deleted. Select node:", node -> number); if (node == NodeDialogActive (node_d)) { newnode = (Node) TreePredecessor (problem.node_tree, node); if (newnode == NULL) newnode = (Node) TreeSuccessor (problem.node_tree, node); NodeDialogDisplay (node_d, newnode); } (void) TreeDelete (problem.node_tree, node); NodeDialogUpdate (node_d, problem.node_tree, NULL, NULL); DestroyNode (node); ChangeStatusLine (message, True); changeflag = True; } void DeleteNodeCB (w, client_data, call_data) Widget w; XtPointer client_data; XtPointer call_data; { DrawingReport *report; FigureAttributes attributes; Figure figure; Drawn drawn; Node node; report = (DrawingReport *) call_data; if (report -> event -> type != ButtonPress) return; if (report -> event -> xbutton.button == 2) { SelectGroup (call_data, DeleteNodeGroup); return; } if (report -> event -> xbutton.button == 3) QuitEdit ( ); if (report -> event -> xbutton.button != 1) return; figure = DW_FindFigure (w, report -> unsnapped.x, report -> unsnapped.y); if (figure == NULL) return; DW_GetAttributes (w, figure, &attributes); if (attributes.user_data == NULL) return; node = (Node) attributes.user_data; drawn = (Drawn) node -> aux; if (drawn -> type != DrawnNode) return; DoDeleteNode (node); } void DeleteNodeAP ( ) { char *status; struct node dummy; Item found; if ((status = GetTextNumber (&dummy.number)) != NULL) { if (!strcmp (status, "w")) SelectGroup (NULL, DeleteNodeGroup); return; } found = TreeSearch (problem.node_tree, (Item) &dummy); if (found == NULL) { error ("Node %d does not exist.", dummy.number); return; } DoDeleteNode (found); } void EditDeleteNode ( ) { Arg arglist [1]; SetEditMode ( ); ChangeStatusLine ("Select node:", True); XtRemoveAllCallbacks (drawing, XtNbuttonCallback); XtAddCallback (drawing, XtNbuttonCallback, DeleteNodeCB, NULL); XtSetArg (arglist [0], XtNcursorName, "dotbox"); XtSetValues (drawing, arglist, 1); XtOverrideTranslations (entry, XtParseTranslationTable ("Return: DeleteNodeAP()")); } void EditNodeCB (w, client_data, call_data) Widget w; XtPointer client_data; XtPointer call_data; { DrawingReport *report; FigureAttributes attributes; Figure figure; Drawn drawn; Node node; report = (DrawingReport *) call_data; if (report -> event -> type != ButtonPress) return; if (report -> event -> xbutton.button == 3) QuitEdit ( ); if (report -> event -> xbutton.button != 1) return; figure = DW_FindFigure (w, report -> unsnapped.x, report -> unsnapped.y); if (figure == NULL) return; DW_GetAttributes (w, figure, &attributes); if (attributes.user_data == NULL) return; node = (Node) attributes.user_data; drawn = (Drawn) node -> aux; if (drawn -> type != DrawnNode) return; NodeDialogDisplay (node_d, node); NodeDialogPopup (node_d); } void EditNodeAP ( ) { char *status; struct node dummy; Item found; if ((status = GetTextNumber (&dummy.number)) != NULL) return; found = TreeSearch (problem.node_tree, (Item) &dummy); if (found == NULL) { error ("Node %d does not exist.", dummy.number); return; } NodeDialogDisplay (node_d, found); NodeDialogPopup (node_d); } void EditNodeNumber ( ) { SetEditMode ( ); ChangeStatusLine ("Select node:", True); XtRemoveAllCallbacks (drawing, XtNbuttonCallback); XtAddCallback (drawing, XtNbuttonCallback, EditNodeCB, NULL); XtOverrideTranslations (entry, XtParseTranslationTable ("Return: EditNodeAP()")); } int DrawNode (node) Node node; { Figure fig; Figure label; char buffer [10]; FigureAttributes attr; Item found; Drawn drawn; found = TreeInsert (problem.node_tree, (Item) node); if (found != (Item) node) return 1; if (DW_SetFont (drawing, canvas -> label_font) == False) (void) DW_SetFont (drawing, "fixed"); if (node -> force && node -> force -> color) { if (DW_SetForeground (drawing, node -> force -> color) == False) (void) DW_SetForeground (drawing, "black"); } else if (node -> constraint -> color) { if (DW_SetForeground (drawing, node -> constraint -> color) == False) (void) DW_SetForeground (drawing, "black"); } else { if (DW_SetForeground (drawing, canvas -> node_color) == False) (void) DW_SetForeground (drawing, "black"); } if (node -> z == 0) { fig = DW_FillArc (drawing, False, node -> x, node -> y, 6.0, 6.0, 0.0, 360.0); if (canvas -> node_numbers == True) { sprintf (buffer, " %d", node -> number); label = DW_DrawText (drawing, True, node -> x, node -> y, buffer); } else label = NULL; } else fig = label = NULL; if (node -> aux == NULL) { drawn = (Drawn) XtNew (struct drawn); node -> aux = (char *) drawn; drawn -> type = DrawnNode; drawn -> ref_count = 0; } else drawn = (Drawn) node -> aux; drawn -> figure = fig; drawn -> label = label; attr.user_data = (char *) node; if (fig != NULL) DW_SetAttributes (drawing, fig, DW_FigureUserData, &attr); if (label != NULL) DW_SetAttributes (drawing, label, DW_FigureUserData, &attr); return 0; } void QuitMoveNode ( ) { DW_RemoveFigure (drawing, ghost_figure); DW_SetInteractive (drawing, False); SetNormalMode ( ); } void WalkNodeCB (w, client_data, call_data) Widget w; XtPointer client_data; XtPointer call_data; { DrawingReport *report; Node node; report = (DrawingReport *) call_data; node = (Node) client_data; if (report -> event -> type == ButtonPress) { if (report -> event -> xbutton.button == 3) QuitMoveNode ( ); if (report -> event -> xbutton.button > 2) return; node -> x = report -> snapped.x; node -> y = report -> snapped.y; DW_RemoveFigure (drawing, ghost_figure); DW_SetInteractive (drawing, False); DoWalkNode (node); SetNormalMode ( ); } else if (report -> event -> type == MotionNotify) { attr.x = report -> snapped.x; attr.y = report -> snapped.y; DW_SetAttributes (drawing, ghost_figure, DW_FigureLocation, &attr); } } void WalkNodeAP ( ) { char *status; float x, y; status = GetTextCoordinates (&x, &y, NULL); if (status != NULL) return; moved_node -> x = x; moved_node -> y = y; QuitMoveNode ( ); DoWalkNode (moved_node); } void DoMoveNode (node, motion) Node node; Boolean motion; { static char buffer [80]; SetEditMode ( ); sprintf (buffer, "Nodal coordinates for node %d:", node -> number); ChangeStatusLine (buffer, True); AssignQuitAbort (QuitMoveNode, "QuitMoveNode", QuitMoveNode,"QuitMoveNode"); XtRemoveAllCallbacks (drawing, XtNbuttonCallback); XtAddCallback (drawing, XtNbuttonCallback, WalkNodeCB, node); if (motion == True) { XtRemoveAllCallbacks (drawing, XtNmotionCallback); XtAddCallback (drawing, XtNmotionCallback, WalkNodeCB, node); DW_SetInteractive (drawing, True); ghost_figure = DW_FillArc (drawing, False, node -> x, node -> y, 6.0, 6.0, 0.0, 360.0); } else { moved_figure = NULL; ghost_figure = NULL; } moved_node = node; XtOverrideTranslations (entry, XtParseTranslationTable ("Return: WalkNodeAP()")); } void MoveNodeCB (w, client_data, call_data) Widget w; XtPointer client_data; XtPointer call_data; { DrawingReport *report; FigureAttributes attributes; Figure figure; Node node; Drawn drawn; report = (DrawingReport *) call_data; if (report -> event -> type != ButtonPress) return; if (report -> event -> xbutton.button == 3) QuitEdit ( ); if (report -> event -> xbutton.button != 1) return; figure = DW_FindFigure (w, report -> unsnapped.x, report -> unsnapped.y); if (figure == NULL) return; DW_GetAttributes (w, figure, &attributes); if (attributes.user_data == NULL) return; node = (Node) attributes.user_data; drawn = (Drawn) node -> aux; if (drawn -> type != DrawnNode) return; moved_figure = figure; DoMoveNode (node, False); } void MoveNodeAP ( ) { char *status; struct node dummy; Item found; if ((status = GetTextNumber (&dummy.number)) != NULL) return; found = TreeSearch (problem.node_tree, &dummy); if (found == NULL) { error ("Node %d does not exist.", dummy.number); return; } DoMoveNode (found, False); } void MoveNodeNumber ( ) { SetEditMode ( ); ChangeStatusLine ("Select node: ", True); XtRemoveAllCallbacks (drawing, XtNbuttonCallback); XtAddCallback (drawing, XtNbuttonCallback, MoveNodeCB, NULL); XtOverrideTranslations (entry, XtParseTranslationTable ("Return: MoveNodeAP()")); } static double mass_value = 0.0; void AssignMassGroup (figures, nfigures) Figure *figures; unsigned nfigures; { unsigned i; Figure fig; Drawn drawn; Node node; for (i = 0; i < nfigures; i ++) { fig = figures [i]; DW_GetAttributes (drawing, fig, &attr); if (attr.user_data == NULL || attr.type == TextFigure) continue; node = (Node) attr.user_data; drawn = (Drawn) node -> aux; if (drawn -> type != DrawnNode) continue; node -> m = mass_value; } changeflag = True; return; } void DoAssignMass (node) Node node; { char message [80]; node -> m = mass_value; if (node == NodeDialogActive (node_d)) NodeDialogDisplay (node_d, node); sprintf (message, "Mass assigned to node %d. Select node:", node -> number); ChangeStatusLine (message, True); changeflag = True; } void AssignMassCB (w, client_data, call_data) Widget w; XtPointer client_data; XtPointer call_data; { DrawingReport *report; FigureAttributes attributes; Figure figure; Drawn drawn; Node node; report = (DrawingReport *) call_data; if (report -> event -> type != ButtonPress) return; if (report -> event -> xbutton.button == 2) { SelectGroup (call_data, AssignMassGroup); return; } if (report -> event -> xbutton.button == 3) QuitEdit ( ); if (report -> event -> xbutton.button != 1) return; figure = DW_FindFigure (w, report -> unsnapped.x, report -> unsnapped.y); if (figure == NULL) return; DW_GetAttributes (w, figure, &attributes); if (attributes.user_data == NULL) return; node = (Node) attributes.user_data; drawn = (Drawn) node -> aux; if (drawn -> type != DrawnNode) return; DoAssignMass (node); } void AssignMassAP ( ) { char *status; struct node dummy; Item found; if ((status = GetTextNumber (&dummy.number)) != NULL) { if (!strcmp (status, "w")) SelectGroup (NULL, AssignMassGroup); return; } found = TreeSearch (problem.node_tree, (Item) &dummy); if (found == NULL) { error ("Node %d does not exist.", dummy.number); return; } DoAssignMass (found); } void SetMassAP ( ) { Arg args [1]; char *status; float m; status = GetTextCoordinates (&m, NULL, NULL); if (status == NULL) mass_value = m; else return; ChangeStatusLine ("Select node:", True); XtSetArg (args [0], XtNcursorName, "dotbox"); XtSetValues (drawing, args, 1); XtAddCallback (drawing, XtNbuttonCallback, AssignMassCB, NULL); XtOverrideTranslations (entry, XtParseTranslationTable ("Return: AssignMassAP()")); } void EditNodalMass ( ) { SetEditMode ( ); ChangeStatusLine ("Enter mass value:", True); XtRemoveAllCallbacks (drawing, XtNbuttonCallback); XtOverrideTranslations (entry, XtParseTranslationTable ("Return: SetMassAP()")); }