/* 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. */ /************************************************************************ * File: element.c * * * * Description: This file contains the public and private function and * * definitions for the element dialog box. * ************************************************************************/ # include # include # include # include # include # include # include # include # include # include # include # include "Layout.h" # include "Element.h" # include "TabGroup.h" # include "util.h" # include "objects.h" # include "post.h" # include "problem.h" # include "error.h" # include "definition.h" # ifndef X_NOT_STDC_ENV # include # else extern int atoi ( ); # endif struct element_dialog { Widget shell; /* topLevelShell */ Widget layout; /* Layout layout */ Widget number; /* Label number */ Widget type; /* Label type */ Widget up; /* Repeater up */ Widget down; /* Repeater down */ Widget left; /* Command left */ Widget right; /* Command right */ Widget node [6]; /* AsciiText node[1-6] */ Widget m_name; /* AsciiText materialName */ Widget m_button; /* MenuButton materialButton */ Widget m_menu; /* SimpleMenu materialMenu */ Widget l_name [3]; /* AsciiText load[1-3]Name */ Widget l_button [3];/* MenuButton load[1-3Button */ Widget l_menu; /* SimpleMenu loadMenu */ Widget viewport; /* Viewport viewport */ Widget stresses; /* Label stresses */ Widget help; /* MenuButton help */ Widget accept; /* Command accept */ Widget dismiss; /* Command dismiss */ Widget delete; /* Command delete */ Widget new; /* Command new */ Widget copy; /* Command copy */ XtCallbackProc callback; XtPointer closure; unsigned offset; unsigned new_copy; Boolean new_materials; Boolean new_loads; Definition definition; Element active; unsigned node_values [32]; Tree elements; Tree materials; Tree loads; Tree nodes; }; static String labels [ ] = { "Number:", "Type:", "Nodes:", "Stresses" }; static String names [ ] = { "numberLabel", "typeLabel", "nodes", "stressLabel" }; /* Bitmaps */ #define up_width 12 #define up_height 12 static char up_bits[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0xf0, 0x00, 0xf8, 0x01, 0xfc, 0x03, 0xfe, 0x07, 0xfe, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; #define down_width 12 #define down_height 12 static char down_bits[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x07, 0xfe, 0x07, 0xfc, 0x03, 0xf8, 0x01, 0xf0, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; #define left_width 12 #define left_height 12 static char left_bits[] = { 0x00, 0x00, 0x80, 0x01, 0xc0, 0x01, 0xe0, 0x01, 0xf0, 0x01, 0xf8, 0x01, 0xf8, 0x01, 0xf0, 0x01, 0xe0, 0x01, 0xc0, 0x01, 0x80, 0x01, 0x00, 0x00}; #define right_width 12 #define right_height 12 static char right_bits[] = { 0x00, 0x00, 0x18, 0x00, 0x38, 0x00, 0x78, 0x00, 0xf8, 0x00, 0xf8, 0x01, 0xf8, 0x01, 0xf8, 0x00, 0x78, 0x00, 0x38, 0x00, 0x18, 0x00, 0x00, 0x00}; static Pixmap up_bitmap; static Pixmap down_bitmap; static Pixmap left_bitmap; static Pixmap right_bitmap; /* Resources */ static Pixel highlight; static String layout_string = "\ vertical { \ 4 \ horizontal { \ 4 \ up \ 4 \ down \ 4 \ numberLabel \ 4 \ number \ 40 \ typeLabel \ 4 \ type \ 4 <+inf -100%> \ } \ 4 \ separator1 <+inf -100% *> \ 4 \ horizontal { \ 4 \ left \ 4 \ right \ 4 \ nodes \ 4 \ node1 \ node2 \ node3 \ node4 \ node5 \ node6 \ 4 <+inf -100%> \ } \ 4 \ separator2 <+inf -100% *> \ 4 \ vertical { \ horizontal { \ 4 \ materialButton 4 materialName <+inf -100% *> 4 \ load2Button 4 load2Name <+inf -100% *> 4 \ } \ 4 \ horizontal { \ 4 \ load1Button 4 load1Name <+inf -100% *> 4 \ load3Button 4 load3Name <+inf -100% *> 4 \ } \ } \ 4 \ separator3 <+inf -100% *> \ 4 \ horizontal { \ 4 \ stressLabel \ 4 <+inf -100%> \ } \ 4 \ horizontal { \ 4 \ viewport <+inf -100% * +inf -100%> \ 4 \ } \ 4 \ separator4 <+inf -100% *> \ 4 \ horizontal { \ 4 \ help \ 4 <+inf -100%> \ accept \ 4 <+inf -100%> \ dismiss \ 4 <+inf -100%> \ delete \ 4 <+inf -100%> \ new \ 4 <+inf -100%> \ copy \ 4 \ } \ 4 \ }"; static Arg color_args [ ] = { {XtNborderColor, (XtArgVal) &highlight}, }; static Arg shell_args [ ] = { {XtNtitle, (XtArgVal) NULL}, {XtNiconName, (XtArgVal) NULL}, }; static Arg layout_args [ ] = { {XtNlayout, (XtArgVal) NULL}, }; static Arg edit_text_args [ ] = { {XtNeditType, (XtArgVal) XawtextEdit}, {XtNborderWidth, (XtArgVal) 0}, {XtNpieceSize, (XtArgVal) 32}, {XtNcursorName, (XtArgVal) "left_ptr"}, }; static Arg node_args [ ] = { {XtNeditType, (XtArgVal) XawtextEdit}, {XtNborderWidth, (XtArgVal) 0}, {XtNpieceSize, (XtArgVal) 32}, {XtNcursorName, (XtArgVal) "left_ptr"}, {XtNwidth, (XtArgVal) 40}, }; static Arg stress_args [ ] = { {XtNresize, (XtArgVal) True}, {XtNjustify, (XtArgVal) XtJustifyLeft}, {XtNborderWidth, (XtArgVal) 0}, }; static Arg viewport_args [ ] = { {XtNallowVert, (XtArgVal) True}, {XtNallowHoriz, (XtArgVal) True}, {XtNuseBottom, (XtArgVal) True}, {XtNuseRight, (XtArgVal) True}, {XtNforceBars, (XtArgVal) False}, {XtNborderWidth, (XtArgVal) 0}, }; static Arg button_args [ ] = { {XtNlabel, (XtArgVal) ""}, {XtNmenuName, (XtArgVal) ""}, {XtNborderWidth, (XtArgVal) 0}, {XtNresize, (XtArgVal) False}, }; static Arg number_args [ ] = { {XtNlabel, (XtArgVal) ""}, {XtNresize, (XtArgVal) True}, {XtNborderWidth, (XtArgVal) 0}, }; static Arg label_args [ ] = { {XtNlabel, (XtArgVal) ""}, {XtNborderWidth, (XtArgVal) 0}, }; static Arg core_args [ ] = { {XtNwidth, (XtArgVal) 3}, {XtNheight, (XtArgVal) 3}, }; static Arg bitmap_args [ ] = { {XtNbitmap, (XtArgVal) NULL}, }; /* Translation tables */ static String text_table = "Return: ElementDialogAction(accept)\n\ Escape: ElementDialogAction(dismiss)\n\ Ctrld: ElementDialogAction(delete)\n\ Ctrlc: ElementDialogAction(copy)\n\ Ctrln: ElementDialogAction(new)\n\ Ctrlh: ElementDialogAction(help)\n\ : SetFocus() select-start()"; static XtTranslations text_translations; static String command_table = "Return: ElementDialogAction(accept)\n\ Escape: ElementDialogAction(dismiss)\n\ Ctrld: ElementDialogAction(delete)\n\ Ctrlc: ElementDialogAction(copy)\n\ Ctrln: ElementDialogAction(new)\n\ Ctrlh: ElementDialogAction(help)\n\ space: AutoRepeat(off) set()\n\ space: AutoRepeat(saved) notify() unset()"; static XtTranslations command_translations; static String button_table = "Return: ElementDialogAction(accept)\n\ Escape: ElementDialogAction(dismiss)\n\ Ctrld: ElementDialogAction(delete)\n\ Ctrlc: ElementDialogAction(copy)\n\ Ctrln: ElementDialogAction(new)\n\ Ctrlh: ElementDialogAction(help)\n\ : ElementDialogMenu() PostMenu()\n\ space: ElementDialogMenu() PostMenu()"; static XtTranslations button_translations; static String repeater_table = "Return: ElementDialogAction(accept)\n\ Escape: ElementDialogAction(dismiss)\n\ Ctrld: ElementDialogAction(delete)\n\ Ctrlc: ElementDialogAction(copy)\n\ Ctrln: ElementDialogAction(new)\n\ Ctrlh: ElementDialogAction(help)\n\ space: AutoRepeat(off) set()\n\ space: AutoRepeat(saved) notify() unset()"; static XtTranslations repeater_translations; static String viewport_table = "Return: ElementDialogAction(accept)\n\ Escape: ElementDialogAction(dismiss)\n\ Ctrld: ElementDialogAction(delete)\n\ Ctrlc: ElementDialogAction(copy)\n\ Ctrln: ElementDialogAction(new)\n\ Ctrlh: ElementDialogAction(help)\n\ : SetFocus()"; static XtTranslations viewport_translations; static String help_table = "Return: ElementDialogAction(accept)\n\ Escape: ElementDialogAction(dismiss)\n\ Ctrld: ElementDialogAction(delete)\n\ Ctrlc: ElementDialogAction(copy)\n\ Ctrln: ElementDialogAction(new)\n\ Ctrlh: ElementDialogAction(help)\n\ space: PostMenu()"; static XtTranslations help_translations; /* Help message. */ static String help_message = "\ The element form is used to define, edit and delete elements. Elements can \ also be selected by using the drawing area. Use the arrows to change \ the current element. The menus and fields above define the behavior of the \ current element. Use the 'Accept' button to register your changes. 'Delete' \ erases the current element. 'New' empties all fields creating a new element. \ 'Copy' creates a new element without changing any fields."; /* Menu creation variables */ static Cardinal child_number; static WidgetList children; static Dimension max_width; static XtWidgetGeometry preferred; static Widget menu_button; /************************************************************************ * Function: SetLoadEntry * * * * Description: Sets the label of the next menu entry to the name of * * the specified load. * ************************************************************************/ static int SetLoadEntry (item) Item item; { SetLabelString (children [child_number], ((Distributed) item) -> name); XtQueryGeometry (children [child_number ++], NULL, &preferred); if (preferred.width > max_width) max_width = preferred.width; return 0; } /************************************************************************ * Function: UpdateLoadMenu * * * * Description: Updates the load menu on popup if necessary to the list * * of current loads. * ************************************************************************/ static void UpdateLoadMenu (w, client_data, call_data) Widget w; XtPointer client_data; XtPointer call_data; { Arg args [2]; char buffer [32]; Cardinal overflow; Cardinal num_loads; Cardinal i; Cardinal num_children; ElementDialog eltd; eltd = (ElementDialog) client_data; if (eltd -> new_loads == False) return; XtSetArg (args [0], XtNchildren, &children); XtSetArg (args [1], XtNnumChildren, &num_children); XtGetValues (w, args, 2); num_loads = TreeSize (eltd -> loads) + 1; for (i = num_children; i < num_loads; i ++) { sprintf (buffer, "load%d", i); XtCreateManagedWidget (XtNewString (buffer), smeBSBObjectClass, eltd -> l_menu, NULL, 0); } if (num_children > num_loads) { overflow = num_children - num_loads; XtUnmanageChildren (children + num_loads, overflow); } XtSetArg (args [0], XtNchildren, &children); XtSetArg (args [1], XtNnumChildren, &num_children); XtGetValues (w, args, 2); XtQueryGeometry (children [0], NULL, &preferred); max_width = preferred.width; child_number = 1; TreeSetIterator (eltd -> loads, SetLoadEntry); TreeIterate (eltd -> loads); eltd -> new_loads = False; XtSetArg (args [0], XtNwidth, max_width); XtSetValues (w, args, 1); } /************************************************************************ * Function: UpdateLoadName * * * * Description: Updates the load name on popdown if necessary. * ************************************************************************/ static void UpdateLoadName (w, client_data, call_data) Widget w; XtPointer client_data; XtPointer call_data; { Cardinal i; Widget name; ElementDialog eltd; if (!(w = XawSimpleMenuGetActiveEntry (w))) return; name = NULL; eltd = (ElementDialog) client_data; for (i = 0; i < 3; i ++) if (menu_button == eltd -> l_button [i]) { name = eltd -> l_name [i]; break; } if (!strcmp (XtName (w), "- none -")) SetTextString (name, ""); else SetTextString (name, GetLabelString (w)); } /************************************************************************ * Function: SetMaterialEntry * * * * Description: Sets the label of the next menu entry to the name of * * the specified material. * ************************************************************************/ static int SetMaterialEntry (item) Item item; { SetLabelString (children [child_number], ((Material) item) -> name); XtQueryGeometry (children [child_number ++], NULL, &preferred); if (preferred.width > max_width) max_width = preferred.width; return 0; } /************************************************************************ * Function: UpdateMaterialMenu * * * * Description: Updates the material menu on popup if necessary to the * * list of current materials. * ************************************************************************/ static void UpdateMaterialMenu (w, client_data, call_data) Widget w; XtPointer client_data; XtPointer call_data; { Arg args [2]; char buffer [32]; Cardinal overflow; Cardinal num_materials; Cardinal i; Cardinal num_children; ElementDialog eltd; eltd = (ElementDialog) client_data; if (eltd -> new_materials == False) return; XtSetArg (args [0], XtNchildren, &children); XtSetArg (args [1], XtNnumChildren, &num_children); XtGetValues (w, args, 2); num_materials = TreeSize (eltd -> materials); if (num_materials <= 0) { num_materials ++; SetLabelString (children [0], "- no materials defined -"); XtQueryGeometry (children [0], NULL, &preferred); max_width = preferred.width; } else max_width = 0; for (i = num_children; i < num_materials; i ++) { sprintf (buffer, "material%d", i); XtCreateManagedWidget (XtNewString (buffer), smeBSBObjectClass, eltd -> m_menu, NULL, 0); } if (num_children > num_materials) { overflow = num_children - num_materials; XtUnmanageChildren (children + num_materials, overflow); } XtSetArg (args [0], XtNchildren, &children); XtSetArg (args [1], XtNnumChildren, &num_children); XtGetValues (w, args, 2); child_number = 0; TreeSetIterator (eltd -> materials, SetMaterialEntry); TreeIterate (eltd -> materials); XtSetArg (args [0], XtNwidth, max_width); XtSetValues (w, args, 1); } /************************************************************************ * Function: UpdateMaterialName * * * * Description: Updates the material name on popdown if necessary. * ************************************************************************/ static void UpdateMaterialName (w, client_data, call_data) Widget w; XtPointer call_data; XtPointer client_data; { String label; ElementDialog eltd; if (!(w = XawSimpleMenuGetActiveEntry (w))) return; eltd = (ElementDialog) client_data; label = GetLabelString (w); if (!strcmp (label, "- no materials defined -")) SetTextString (eltd -> m_name, ""); else SetTextString (eltd -> m_name, label); } /************************************************************************ * Function: SetNumber * * * * Description: Sets the label of the number widget. * ************************************************************************/ static void SetNumber (eltd, number) ElementDialog eltd; unsigned number; { char buffer [10]; sprintf (buffer, "%u", number); SetLabelString (eltd -> number, buffer); } /************************************************************************ * Function: SetType * * * * Description: Sets the label of the type widget. * ************************************************************************/ static void SetType (eltd, defn) ElementDialog eltd; Definition defn; { Cardinal i; unsigned numnodes; SetLabelString (eltd -> type, defn -> name); eltd -> offset = 0; eltd -> definition = defn; numnodes = eltd -> definition -> numnodes; if (numnodes >= 6) numnodes = 6; for (i = 0; i < numnodes; i ++) if (!XtIsSensitive (eltd -> node [i])) XtSetSensitive (eltd -> node [i], True); for (i = numnodes; i < 6; i ++) { SetTextString (eltd -> node [i], ""); if (HasFocus (eltd -> node [i])) SetFocus (eltd -> node [numnodes - 1]); if (XtIsSensitive (eltd -> node [i])) XtSetSensitive (eltd -> node [i], False); } } /************************************************************************ * Function: DisplayNodes * * * * Description: Displays the node array. * ************************************************************************/ static void DisplayNodes (eltd) ElementDialog eltd; { Cardinal i; Cardinal j; unsigned numnodes; char buffer [32]; numnodes = eltd -> definition -> numnodes; if (numnodes > 6) numnodes = 6; for (i = 0, j = eltd -> offset; i < numnodes; i ++, j ++) if (eltd -> node_values [j]) { sprintf (buffer, "%u", eltd -> node_values [j]); SetTextString (eltd -> node [i], buffer); } else SetTextString (eltd -> node [i], ""); } /************************************************************************ * Function: RetrieveNodes * * * * Description: Retrieves the displayed nodes. * ************************************************************************/ static void RetrieveNodes (eltd) ElementDialog eltd; { Cardinal i; Cardinal j; unsigned numnodes; numnodes = eltd -> definition -> numnodes; if (numnodes > 6) numnodes = 6; for (i = 0, j = eltd -> offset; i < numnodes; i ++, j ++) eltd -> node_values [j] = atoi (GetTextString (eltd -> node [i])); } /************************************************************************ * Function: Menu * * * * Description: Records the menu button which activated the menu. * ************************************************************************/ static void Menu (w, event, params, num_params) Widget w; XEvent *event; String *params; Cardinal *num_params; { menu_button = w; } /************************************************************************ * Function: Action * * * * Description: An action procedure which emulates the pressing of the * * specified button. * ************************************************************************/ static void Action (w, event, params, num_params) Widget w; XEvent *event; String *params; Cardinal *num_params; { if (XtClass (w) == topLevelShellWidgetClass) w = XtNameToWidget (w, "layout.dismiss"); else w = XtNameToWidget (XtParent (w), params [0]); if (!strcmp (XtName (w), "help")) XtCallActionProc (w, "PostMenu", event, NULL, 0); else XtCallCallbacks (w, XtNcallback, NULL); } /************************************************************************ * Function: Up * * * * Description: Displays the next highest numbered element. * ************************************************************************/ static void Up (w, client_data, call_data) Widget w; XtPointer client_data; XtPointer call_data; { Element element; ElementDialog eltd; eltd = (ElementDialog) client_data; if (eltd -> active == NULL) return; element = (Element) TreeSuccessor (eltd -> elements, eltd -> active); if (element != NULL) ElementDialogDisplay (eltd, element); } /************************************************************************ * Function: Down * * * * Description: Displays the next lowest numbered element. * ************************************************************************/ static void Down (w, client_data, call_data) Widget w; XtPointer client_data; XtPointer call_data; { Element element; ElementDialog eltd; eltd = (ElementDialog) client_data; if (eltd -> active == NULL) return; element = (Element) TreePredecessor (eltd -> elements, eltd -> active); if (element != NULL) ElementDialogDisplay (eltd, element); } /************************************************************************ * Function: Left * * * * Description: Shifts the list of displayed nodes to the right. * ************************************************************************/ static void Left (w, client_data, call_data) Widget w; XtPointer client_data; XtPointer call_data; { unsigned numnodes; ElementDialog eltd; eltd = (ElementDialog) client_data; numnodes = eltd -> definition -> numnodes; if (numnodes > 6 && eltd -> offset > 0) { RetrieveNodes (eltd); eltd -> offset --; DisplayNodes (eltd); } } /************************************************************************ * Function: Right * * * * Description: Shifts the list of displayed nodes to the left. * ************************************************************************/ static void Right (w, client_data, call_data) Widget w; XtPointer client_data; XtPointer call_data; { unsigned numnodes; ElementDialog eltd; eltd = (ElementDialog) client_data; numnodes = eltd -> definition -> numnodes; if (numnodes > 6 && eltd -> offset < numnodes - 6) { RetrieveNodes (eltd); eltd -> offset ++; DisplayNodes (eltd); } } /************************************************************************ * Function: Accept * * * * Description: Accepts changes made to the currently displayed * * element. If the material is empty or the material or * * or a load does not exist then an error is reported. * * Otherwise, a new element is created if a new/copy * * operation is in effect. The element is then * * redisplayed to correct any invalid entries. * ************************************************************************/ static void Accept (w, client_data, call_data) Widget w; XtPointer client_data; XtPointer call_data; { Cardinal i; unsigned numnodes; unsigned shapenodes; Material material; Distributed load; struct element original; struct distributed l_dummy; struct material m_dummy; struct node n_dummy; Element active; ElementDialog eltd; ElementDialogInfo info; Node node; Node nodes [32]; Node original_nodes [32]; eltd = (ElementDialog) client_data; /* Copy the original element if necessary. */ if (eltd -> active != NULL) { original = *eltd -> active; original.node = original_nodes; for (i = 1; i <= eltd -> definition -> numnodes; i ++) original_nodes [i] = eltd -> active -> node [i]; } /* Retrieve the material. */ m_dummy.name = GetTextString (eltd -> m_name); material = (Material) TreeSearch (eltd -> materials, &m_dummy); if (material == NULL) { XBell (XtDisplay (eltd -> shell), 0); SetTextString (eltd -> m_name, ""); SetFocus (eltd -> m_name); return; } /* Retrieve the nodes. */ numnodes = eltd -> definition -> numnodes; shapenodes = eltd -> definition -> shapenodes; RetrieveNodes (eltd); for (i = 0; i < numnodes; i ++) { n_dummy.number = eltd -> node_values [i]; if (n_dummy.number == 0) { if (i < shapenodes) { if (i < eltd -> offset) { eltd -> offset = i; DisplayNodes (eltd); } else if (i >= eltd -> offset + 6) { eltd -> offset = i - 5; DisplayNodes (eltd); } XBell (XtDisplay (eltd -> shell), 0); SetTextString (eltd -> node [i], ""); SetFocus (eltd -> node [i]); return; } nodes [i] = NULL; } else { node = (Node) TreeSearch (eltd -> nodes, &n_dummy); if (node == NULL) { if (i < eltd -> offset) { eltd -> offset = i; DisplayNodes (eltd); } else if (i >= eltd -> offset + 6) { eltd -> offset = i - 5; DisplayNodes (eltd); } XBell (XtDisplay (eltd -> shell), 0); SetTextString (eltd -> node [i], ""); SetFocus (eltd -> node [i]); return; } nodes [i] = node; } } /* Create a new element as needed. */ if (eltd -> new_copy) { eltd -> active = CreateElement (eltd -> new_copy, eltd -> definition); TreeInsert (eltd -> elements, eltd -> active); } active = eltd -> active; active -> material = material; /* Retrieve the loads. */ active -> numdistributed = 0; for (i = 0; i < 3; i ++) { l_dummy.name = GetTextString (eltd -> l_name [i]); load = (Distributed) TreeSearch (eltd -> loads, &l_dummy); if (load != NULL) active -> distributed [++ active -> numdistributed] = load; } for (i = active -> numdistributed + 1; i <= 3; i ++) active -> distributed [i] = NULL; /* Copy the nodes. */ for (i = 0; i < numnodes; i ++) active -> node [i + 1] = nodes [i]; if (eltd -> callback != NULL) { info.dialog = eltd; info.element = active; info.deleted = False; info.proceed = True; info.original = &original; eltd -> callback (eltd -> shell, eltd -> closure, &info); } ElementDialogUpdate (eltd, eltd -> elements, NULL, NULL, NULL); } /************************************************************************ * Function: Dismiss * * * * Description: Pops down the dialog box. * ************************************************************************/ static void Dismiss (w, client_data, call_data) Widget w; XtPointer client_data; XtPointer call_data; { ElementDialog eltd; eltd = (ElementDialog) client_data; XtPopdown (eltd -> shell); } /************************************************************************ * Function: Delete * * * * Description: Deletes the active element if a new/copy operation is * * not in effect. The dialog is then updated. * ************************************************************************/ static void Delete (w, client_data, call_data) Widget w; XtPointer client_data; XtPointer call_data; { Element active; Element element; ElementDialog eltd; ElementDialogInfo info; eltd = (ElementDialog) client_data; if (!eltd -> new_copy) { if (eltd -> callback) { w = eltd -> shell; info.dialog = eltd; info.element = eltd -> active; info.deleted = True; info.proceed = True; eltd -> callback (w, eltd -> closure, &info); if (info.proceed == False) return; } active = eltd -> active; if (!(element = (Element) TreePredecessor (eltd -> elements, active))) element = (Element) TreeSuccessor (eltd -> elements, active); TreeDelete (eltd -> elements, active); DestroyElement (active); eltd -> active = element; } ElementDialogUpdate (eltd, eltd -> elements, NULL, NULL, NULL); } /************************************************************************ * Function: Copy * * * * Description: Selects a new element number, clears the stresses, * * and sets the flag indicating that a new/copy operation * * is in effect. * ************************************************************************/ static void Copy (w, client_data, call_data) Widget w; XtPointer client_data; XtPointer call_data; { Element element; ElementDialog eltd; eltd = (ElementDialog) client_data; element = (Element) TreeMaximum (eltd -> elements); eltd -> new_copy = element != NULL ? element -> number + 1 : 1; SetNumber (eltd, eltd -> new_copy); SetLabelString (eltd -> stresses, ""); } /************************************************************************ * Function: New * * * * Description: Selects a new element number, clears all entries in the * * element dialog, and sets the flag indicating that a * * new/copy operation is in effect. * ************************************************************************/ static void New (w, client_data, call_data) Widget w; XtPointer client_data; XtPointer call_data; { Cardinal i; unsigned numnodes; ElementDialog eltd; eltd = (ElementDialog) client_data; Copy (NULL, client_data, NULL); SetTextString (eltd -> m_name, ""); SetTextString (eltd -> l_name [0], ""); SetTextString (eltd -> l_name [1], ""); SetTextString (eltd -> l_name [2], ""); numnodes = eltd -> definition -> numnodes; if (numnodes > 6) numnodes = 6; for (i = 0; i < numnodes; i ++) SetTextString (eltd -> node [i], ""); } /************************************************************************ * Function: ElementDialogCreate * * * * Description: Creates a new element dialog. You would never want to * * have more than one of these but the interface is kept * * consistent with those of the other dialogs. * ************************************************************************/ ElementDialog ElementDialogCreate (parent, name, title, callback, closure) Widget parent; String name; String title; XtCallbackProc callback; XtPointer closure; { Cardinal i; Arg args [1]; char buffer [32]; Widget group [25]; Window window; ElementDialog eltd; Dimension width; Position x; static XtAppContext app_context = NULL; static XtActionsRec actions [ ] = {{"ElementDialogAction", Action}, {"ElementDialogMenu", Menu}}; /* Perform one time initialization. */ if (app_context == NULL) { app_context = XtWidgetToApplicationContext (parent); XtAppAddActions (app_context, actions, XtNumber (actions)); AddAutoRepeatAction (app_context); layout_args [0].value = StringToLayout (parent, layout_string); text_translations = XtParseTranslationTable (text_table); button_translations = XtParseTranslationTable (button_table); command_translations = XtParseTranslationTable (command_table); repeater_translations = XtParseTranslationTable (repeater_table); viewport_translations = XtParseTranslationTable (viewport_table); help_translations = XtParseTranslationTable (help_table); window = RootWindowOfScreen (XtScreen (parent)); up_bitmap = XCreateBitmapFromData (XtDisplay (parent), window, up_bits, up_width, up_height); down_bitmap = XCreateBitmapFromData (XtDisplay (parent), window, down_bits, down_width, down_height); left_bitmap = XCreateBitmapFromData (XtDisplay (parent), window, left_bits, left_width, left_height); right_bitmap = XCreateBitmapFromData (XtDisplay (parent), window, right_bits, right_width, right_height); } /* Create the element dialog and its widgets. */ XtSetArg (shell_args [0], XtNtitle, title); XtSetArg (shell_args [1], XtNiconName, title); eltd = XtNew (struct element_dialog); eltd -> callback = callback; eltd -> closure = closure; eltd -> active = NULL; eltd -> new_loads = True; eltd -> new_materials = True; eltd -> shell = XtCreatePopupShell (name, topLevelShellWidgetClass, parent, shell_args, XtNumber (shell_args)); eltd -> layout = XtCreateManagedWidget ("layout", layoutWidgetClass, eltd -> shell, layout_args, XtNumber (layout_args)); eltd -> number = XtCreateManagedWidget ("number", labelWidgetClass, eltd -> layout, number_args, XtNumber (number_args)); eltd -> type = XtCreateManagedWidget ("type", labelWidgetClass, eltd -> layout, number_args, XtNumber (number_args)); bitmap_args [0].value = (XtArgVal) up_bitmap; eltd -> up = XtCreateManagedWidget ("up", repeaterWidgetClass, eltd -> layout, bitmap_args, XtNumber (bitmap_args)); bitmap_args [0].value = (XtArgVal) down_bitmap; eltd -> down = XtCreateManagedWidget ("down", repeaterWidgetClass, eltd -> layout, bitmap_args, XtNumber (bitmap_args)); bitmap_args [0].value = (XtArgVal) left_bitmap; eltd -> left = XtCreateManagedWidget ("left", commandWidgetClass, eltd -> layout, bitmap_args, XtNumber (bitmap_args)); bitmap_args [0].value = (XtArgVal) right_bitmap; eltd -> right = XtCreateManagedWidget ("right", commandWidgetClass, eltd -> layout, bitmap_args, XtNumber (bitmap_args)); eltd -> m_menu = XtCreatePopupShell ("materialMenu", simpleMenuWidgetClass, eltd -> layout, NULL, 0); XtSetArg (button_args [0], XtNlabel, "Material:"); XtSetArg (button_args [1], XtNmenuName, "materialMenu"); eltd -> m_button = XtCreateManagedWidget ("materialButton", menuButtonWidgetClass, eltd -> layout, button_args, XtNumber (button_args)); eltd -> m_name = XtCreateManagedWidget ("materialName", asciiTextWidgetClass, eltd -> layout, edit_text_args, XtNumber (edit_text_args)); XtSetArg (button_args [0], XtNlabel, "Material:"); XtSetArg (button_args [1], XtNmenuName, "loadMenu"); eltd -> l_button [0] = XtCreateManagedWidget ("load1Button", menuButtonWidgetClass, eltd -> layout, button_args, XtNumber (button_args)); eltd -> l_name [0] = XtCreateManagedWidget ("load1Name", asciiTextWidgetClass, eltd -> layout, edit_text_args, XtNumber (edit_text_args)); XtSetArg (button_args [0], XtNlabel, "Load 2:"); eltd -> l_button [1] = XtCreateManagedWidget ("load2Button", menuButtonWidgetClass, eltd -> layout, button_args, XtNumber (button_args)); eltd -> l_name [1] = XtCreateManagedWidget ("load2Name", asciiTextWidgetClass, eltd -> layout, edit_text_args, XtNumber (edit_text_args)); XtSetArg (button_args [0], XtNlabel, "Load 3:"); eltd -> l_button [2] = XtCreateManagedWidget ("load3Button", menuButtonWidgetClass, eltd -> layout, button_args, XtNumber (button_args)); eltd -> l_name [2] = XtCreateManagedWidget ("load3Name", asciiTextWidgetClass, eltd -> layout, edit_text_args, XtNumber (edit_text_args)); eltd -> l_menu = XtCreatePopupShell ("loadMenu", simpleMenuWidgetClass, eltd -> layout, NULL, 0); eltd -> viewport = XtCreateManagedWidget ("viewport", viewportWidgetClass, eltd -> layout, viewport_args, XtNumber (viewport_args)); eltd -> stresses = XtCreateManagedWidget ("stresses", labelWidgetClass, eltd -> viewport, stress_args, XtNumber (stress_args)); eltd -> accept = XtCreateManagedWidget ("accept", commandWidgetClass, eltd -> layout, NULL, 0); eltd -> dismiss = XtCreateManagedWidget ("dismiss", commandWidgetClass, eltd -> layout, NULL, 0); eltd -> delete = XtCreateManagedWidget ("delete", commandWidgetClass, eltd -> layout, NULL, 0); eltd -> new = XtCreateManagedWidget ("new", commandWidgetClass, eltd -> layout, NULL, 0); eltd -> copy = XtCreateManagedWidget ("copy", commandWidgetClass, eltd -> layout, NULL, 0); eltd -> help = CreateHelpButton (eltd -> layout, "help"); for (i = 0; i < 6; i ++) { sprintf (buffer, "node%d", i + 1); eltd -> node [i] = XtCreateManagedWidget (XtNewString (buffer), asciiTextWidgetClass, eltd -> layout, node_args, XtNumber (node_args)); } for (i = 0; i < XtNumber (labels); i ++) { label_args [0].value = (XtArgVal) labels [i]; XtCreateManagedWidget (names [i], labelWidgetClass, eltd -> layout, label_args, XtNumber (label_args)); } XtCreateManagedWidget ("separator1", coreWidgetClass, eltd -> layout, core_args, XtNumber (core_args)); XtCreateManagedWidget ("separator2", coreWidgetClass, eltd -> layout, core_args, XtNumber (core_args)); XtCreateManagedWidget ("separator3", coreWidgetClass, eltd -> layout, core_args, XtNumber (core_args)); XtCreateManagedWidget ("separator4", coreWidgetClass, eltd -> layout, core_args, XtNumber (core_args)); XtCreateManagedWidget ("- none -", smeBSBObjectClass, eltd -> m_menu, NULL, 0); XtCreateManagedWidget ("- none -", smeBSBObjectClass, eltd -> l_menu, NULL, 0); AddPostMenuActions (eltd -> m_menu); AddPostMenuActions (eltd -> l_menu); /* Create a tab group for the element dialog. */ group [0] = eltd -> up; group [1] = eltd -> down; group [2] = eltd -> left; group [3] = eltd -> right; group [4] = eltd -> node [0]; group [5] = eltd -> node [1]; group [6] = eltd -> node [2]; group [7] = eltd -> node [3]; group [8] = eltd -> node [4]; group [9] = eltd -> node [5]; group [10] = eltd -> m_button; group [11] = eltd -> m_name; group [12] = eltd -> l_button [0]; group [13] = eltd -> l_name [0]; group [14] = eltd -> l_button [1]; group [15] = eltd -> l_name [1]; group [16] = eltd -> l_button [2]; group [17] = eltd -> l_name [2]; group [18] = eltd -> viewport; group [19] = eltd -> help; group [20] = eltd -> accept; group [21] = eltd -> dismiss; group [22] = eltd -> delete; group [23] = eltd -> new; group [24] = eltd -> copy; XtGetValues (eltd -> layout, color_args, XtNumber (color_args)); CreateTabGroup (eltd -> shell, group, XtNumber(group), highlight, True); XtRealizeWidget (eltd -> shell); SetFocus (eltd -> up); SetType (eltd, (Definition) TreeMinimum (problem.definition_tree)); button_args [0].value = (XtArgVal) "Load 1:"; XtSetValues (eltd -> l_button [0], button_args, 1); XtSetArg (args [0], XtNwidth, &width); XtGetValues (eltd -> layout, args, 1); XtSetArg (args [0], XtNx, &x); XtGetValues (eltd -> help, args, 1); UpdateHelpMessage (eltd -> help, help_message, width - 2 * x); /* Add the translations to each widget. */ AddDeleteWindowProtocol (eltd -> shell, "ElementDialogAction()"); XtOverrideTranslations (eltd -> up, repeater_translations); XtOverrideTranslations (eltd -> down, repeater_translations); XtOverrideTranslations (eltd -> left, repeater_translations); XtOverrideTranslations (eltd -> right, repeater_translations); XtOverrideTranslations (eltd -> m_name, text_translations); XtOverrideTranslations (eltd -> l_name [0], text_translations); XtOverrideTranslations (eltd -> l_name [1], text_translations); XtOverrideTranslations (eltd -> l_name [2], text_translations); XtOverrideTranslations (eltd -> m_button, button_translations); XtOverrideTranslations (eltd -> l_button [0], button_translations); XtOverrideTranslations (eltd -> l_button [1], button_translations); XtOverrideTranslations (eltd -> l_button [2], button_translations); XtOverrideTranslations (eltd -> accept, command_translations); XtOverrideTranslations (eltd -> dismiss, command_translations); XtOverrideTranslations (eltd -> delete, command_translations); XtOverrideTranslations (eltd -> new, command_translations); XtOverrideTranslations (eltd -> copy, command_translations); XtOverrideTranslations (eltd -> viewport, viewport_translations); XtOverrideTranslations (eltd -> help, help_translations); for (i = 0; i < 6; i ++) XtOverrideTranslations (eltd -> node [i], text_translations); /* Add the necessary callbacks. */ XtAddCallback (eltd -> up, XtNcallback, Up, (XtPointer) eltd); XtAddCallback (eltd -> down, XtNcallback, Down, (XtPointer) eltd); XtAddCallback (eltd -> left, XtNcallback, Left, (XtPointer) eltd); XtAddCallback (eltd -> right, XtNcallback, Right, (XtPointer) eltd); XtAddCallback (eltd -> accept, XtNcallback, Accept, (XtPointer) eltd); XtAddCallback (eltd -> dismiss, XtNcallback, Dismiss, (XtPointer) eltd); XtAddCallback (eltd -> delete, XtNcallback, Delete, (XtPointer) eltd); XtAddCallback (eltd -> new, XtNcallback, New, (XtPointer) eltd); XtAddCallback (eltd -> copy, XtNcallback, Copy, (XtPointer) eltd); XtAddCallback (eltd -> m_menu, XtNpopupCallback, UpdateMaterialMenu, (XtPointer) eltd); XtAddCallback (eltd -> m_menu, XtNpopdownCallback, UpdateMaterialName, (XtPointer) eltd); XtAddCallback (eltd -> l_menu, XtNpopupCallback, UpdateLoadMenu, (XtPointer) eltd); XtAddCallback (eltd -> l_menu, XtNpopdownCallback, UpdateLoadName, (XtPointer) eltd); return eltd; } /************************************************************************ * Function: ElementDialogPopup * * * * Description: Pops up the specified element dialog. * ************************************************************************/ void ElementDialogPopup (eltd) ElementDialog eltd; { XtPopup (eltd -> shell, XtGrabNone); } /************************************************************************ * Function: ElementDialogUpdate * * * * Description: Updates the specified element dialog with the specified * * trees. * ************************************************************************/ void ElementDialogUpdate (eltd, elements, materials, loads, nodes) ElementDialog eltd; Tree elements; Tree materials; Tree loads; Tree nodes; { /* Remember to update the menus if necessary. */ if (materials != NULL) { eltd -> materials = materials; eltd -> new_materials = True; } if (loads != NULL) { eltd -> loads = loads; eltd -> new_loads = True; } if (nodes != NULL) eltd -> nodes = nodes; /* Determine a new active element if necessary. */ if (elements == NULL && eltd -> active == NULL) eltd -> active = (Element) TreeMinimum (eltd -> elements); if (elements && (eltd -> active == NULL || eltd -> elements != elements)) eltd -> active = (Element) TreeMinimum (elements); if (elements != NULL) { eltd -> elements = elements; if (eltd -> active != NULL) ElementDialogDisplay (eltd, eltd -> active); else New (NULL, (XtPointer) eltd, NULL); } } /************************************************************************ * Function: ElementDialogActive * * * * Description: Returns the currently displayed (active) element. * ************************************************************************/ Element ElementDialogActive (eltd) ElementDialog eltd; { return eltd -> active; } /************************************************************************ * Function: ElementDialogDisplay * * * * Description: Displays the specified element. * ************************************************************************/ void ElementDialogDisplay (eltd, element) ElementDialog eltd; Element element; { unsigned numnodes; Distributed load; Cardinal i; Cardinal j; Cardinal count; Element active; char buffer [2048]; /* Check if the element exists. */ eltd -> active = element; if (eltd -> active == NULL) return; active = eltd -> active; eltd -> new_copy = 0; /* Update all of the entries. */ SetNumber (eltd, active -> number); SetType (eltd, active -> definition); if (active -> material != NULL) SetTextString (eltd -> m_name, active -> material -> name); else SetTextString (eltd -> m_name, ""); for (i = 1; i <= 3; i ++) if (active -> numdistributed >= i && (load = active -> distributed [i])) SetTextString (eltd -> l_name [i - 1], load -> name); else SetTextString (eltd -> l_name [i - 1], ""); numnodes = active -> definition -> numnodes; for (i = 1; i <= numnodes; i ++) if (element -> node [i] != NULL) eltd -> node_values [i - 1] = element -> node [i] -> number; else eltd -> node_values [i - 1] = 0; if (element -> ninteg == 0 || element -> stress == NULL) SetLabelString (eltd -> stresses, "No stresses available"); else { count = 0; buffer [0] = 0; for (i = 1; i <= element -> ninteg; i ++) for (j = 1; j <= element -> definition -> numstresses; j ++) { sprintf (buffer + strlen (buffer), "%11.5g ", element -> stress [i] -> values [j]); if (++ count == 6) { sprintf (buffer + strlen (buffer), "\n"); count = 0; } } SetLabelString (eltd -> stresses, buffer); } XawViewportSetCoordinates (eltd -> viewport, 0, 0); DisplayNodes (eltd); }