/* $Id: components.c,v 10.1 92/10/06 22:58:11 ca Exp $ */ #include #include #include "sim.h" #include "simx.h" #include "xtables.h" #include "comptypes.h" /* This file contains the code for creating and painting component windows. A component window consists of a box with the name of the component in it. pop_comp_window() creates component window paint_comp_window() fills component window with text unpop_comp_window() destroys component window component_xy() returns x,y location of a component component_event_handler() handles button pres events for components */ /* This routine accepts a pointer to a component and its x,y cordinates and creates a window for the component. It creates the xcomponent structure for that component and returns the window's X ID number. */ XCOMPONENT *pop_comp_window(scomponent, x, y) COMPONENT *scomponent; /* component's data structure */ int x, y; /* x and y coordinates of component */ { XCOMPONENT *xcomponent; /* the component's data structure */ PARAM *parameter; char name_string[30]; Window comp_window; /* window id of component window when created */ int height, width, border_width; /* First parameter in list is always the name of comp. */ parameter = (Param *)scomponent->co_params->q_head; strcpy(name_string, (*(parameter->p_make_text)) (scomponent, parameter)); if (scomponent->co_type == LINK) { height = the_environment.comp_font_info->ascent + the_environment.comp_font_info->descent + 2; width = XTextWidth(the_environment.comp_font_info, name_string, strlen(name_string)) + 2; border_width = 0; } else { height = the_environment.component_window_height; width = the_environment.component_window_width; border_width = the_environment.border_width; } /* Create and map the window */ comp_window = XCreateSimpleWindow(the_environment.the_display, the_environment.back_window, x, y, width, height, border_width, the_environment.fore_color, the_environment.component_color[scomponent->co_type]); XSelectInput(the_environment.the_display, comp_window, ExposureMask); XMapWindow(the_environment.the_display, comp_window); /* Now put an entry in comp_xtable for the component */ if(!(xcomponent = (XCOMPONENT *) sim_malloc(sizeof(XCOMPONENT)))) return((XCOMPONENT *) NULL); xcomponent->scomponent = scomponent; xcomponent->comp_window = comp_window; xcomponent->info_window = (int) NULL; xcomponent->which_one = COMP_WINDOW; xcomponent->num_meters = 0; xcomponent->num_params = 0; xcomponent->user_x = xcomponent->x = x; xcomponent->user_y = xcomponent->y = y; xcomponent->width = width; xcomponent->height = height; /* Get vertical and horizontal positioning of text in window*/ xcomponent->hposition = (int) height - ((height - the_environment.comp_font_info->ascent - the_environment.comp_font_info->descent)/2); xcomponent->wposition = (int) (width - XTextWidth(the_environment.comp_font_info, name_string, strlen(name_string)))/2; XSaveContext(the_environment.the_display, comp_window, comp_xtable, (caddr_t)xcomponent); /* Return the window id. */ return (xcomponent); } /* This rountine accepts a pointer to a component's data structure and "paints" it with its name and any meters. */ paint_comp_window(scomponent, xcomponent) COMPONENT *scomponent; /* pointer to the component */ XCOMPONENT *xcomponent; /* xcomponent structure for component */ { char *name_string; PARAM *parameter; XTextItem xtext; if (xcomponent == NULL) xcomponent = (XCOMPONENT *) scomponent->co_picture; /* Draw its name in it. */ parameter = (Param *)scomponent->co_params->q_head; name_string = (*(parameter->p_make_text)) (scomponent, parameter); xtext.chars = name_string; xtext.nchars = strlen(name_string); xtext.font = the_environment.comp_font; xtext.delta = 0; XDrawText(the_environment.the_display, xcomponent->comp_window, the_environment.the_gc, xcomponent->wposition, xcomponent->hposition, &xtext, 1); } /* This routine deletes a component's window */ unpop_comp_window(scomponent) COMPONENT *scomponent; { XCOMPONENT *xcomponent; /* get rid of infowindow if it exists */ if (scomponent->co_menu_up) unpop_info_window(scomponent); /* get rid of component window */ xcomponent = (XCOMPONENT *) scomponent->co_picture; /* first, get rid of meters */ while(xcomponent->num_meters != 0) { unpop_meter(scomponent, xcomponent->m_list[0]); } XDestroyWindow(the_environment.the_display, xcomponent->comp_window); XDeleteContext(the_environment.the_display, xcomponent->comp_window, comp_xtable); free((char *)xcomponent); XFlush(the_environment.the_display); } /* This routine returns the x and y location of a component */ component_xy(scomponent, x, y) COMPONENT *scomponent; int *x, *y; { XCOMPONENT *xcomponent; xcomponent = (XCOMPONENT *) scomponent->co_picture; if (xcomponent) { *x = xcomponent->x; *y = xcomponent->y; } else { *x = 0; *y = 0; } return (TRUE); } /* This routine handles button press events for the components. The routine accepts a pointer to the event structure for the button press, a pointer to the component's xcomponent, and a variable indicating whether or not the event is a click-release or a click-drag-release. */ component_button_event_handler(xcomponent, bevent, c_m_r) XCOMPONENT *xcomponent; XButtonPressedEvent *bevent; int c_m_r; { int x,y; /* position of component on screen */ short oldx, oldy; /* old position of the component */ /* If it is a right-click-drag-release, then move the component's window to a new location */ if ((bevent->button == user_bindings.move.button) && (bevent->state == user_bindings.move.key) && (c_m_r == 1)) { /* get the new location */ x = (int) bevent->x; y = (int) bevent->y; oldx = (short) xcomponent->x; oldy = (short) xcomponent->y; move_window(&x, &y, xcomponent->width, xcomponent->height, x - oldx, y - oldy); /* and move the component there */ XMoveWindow(the_environment.the_display, xcomponent->comp_window, x, y); xcomponent->x = x; xcomponent->y = y; move_component_array_modify(xcomponent->scomponent, oldx, oldy); XClearWindow(the_environment.the_display, the_environment.back_window); connect_components(); } /* If the event is a middle-click, toggle the component's information window. */ else if ((bevent->button == user_bindings.select.button) && (bevent->state == user_bindings.select.key)) { if (xcomponent->scomponent->co_menu_up) /* erase info window */ { unpop_info_window(xcomponent->scomponent); xcomponent->scomponent->co_menu_up = FALSE; } else /* create info window */ { if (pop_info_window(xcomponent->scomponent) != -1) xcomponent->scomponent->co_menu_up = TRUE; } } else if ((bevent->button == user_bindings.create.button) && (bevent->state == user_bindings.create.key) && (c_m_r == 0)) { create_component(bevent->x, bevent->y, xcomponent->scomponent); } else if ((bevent->button == user_bindings.create.button) && (bevent->state == user_bindings.create.key) && (c_m_r == 1)) { x = bevent->x; y = bevent->y; move_window(&x, &y, the_environment.component_window_width, the_environment.component_window_height, 0, 0); create_component(x, y, xcomponent->scomponent); } } void comp_display_all() { Component *c; XCOMPONENT *xcomponent; short int x, y; for (c = (Component *)comps->l_head; c; c = (Component *)c->co_next){ xcomponent = (XCOMPONENT *) c->co_picture; x = (short) xcomponent->x; y = (short) xcomponent->y; xcomponent->x = (int) xcomponent->user_x; xcomponent->y = (int) xcomponent->user_y; XMoveWindow(the_environment.the_display, xcomponent->comp_window, xcomponent->x, xcomponent->y); } make_line_array(); XClearWindow(the_environment.the_display, the_environment.back_window); connect_components(); XFlush(the_environment.the_display); } void comp_display_nodes() { Component *c; XCOMPONENT *xcomponent, *xc1, *xc2; short int x, y; for (c = (Component *)comps->l_head; c; c = (Component *)c->co_next) if (c->co_type != NODE && (Neighbor *) (c->co_neighbors->l_head) != NULL) { xcomponent = (XCOMPONENT *) c->co_picture; x = xcomponent->user_x = (short) xcomponent->x; y = xcomponent->user_y = (short) xcomponent->y; if (c->co_type == LINK && ((Neighbor *)(c->co_neighbors->l_head))->n_c && ((Neighbor *)(c->co_neighbors->l_head))->n_next->n_c) { xc1 = (XCOMPONENT *) ((Neighbor *)(c->co_neighbors->l_head))->n_c->co_picture; xc2 = (XCOMPONENT *) ((Neighbor *)(c->co_neighbors->l_head))->n_next->n_c->co_picture; xcomponent->x = (xc1->x + xc2->x + (xc1->width + xc2->width)/2)/2 - xcomponent->width / 2+1; xcomponent->y = (xc1->y + xc2->y + (xc1->height + xc2->height)/2)/2 - xcomponent->height / 2+1; } else if (((Neighbor *) (c->co_neighbors->l_head))->n_c){ xcomponent->x = ((XCOMPONENT *) ((Neighbor *) (c->co_neighbors->l_head))->n_c->co_picture)->x; xcomponent->y = ((XCOMPONENT *) ((Neighbor *) (c->co_neighbors->l_head))->n_c->co_picture)->y; } XMoveWindow(the_environment.the_display, xcomponent->comp_window, xcomponent->x, xcomponent->y); } for (c = (Component *)comps->l_head; c != NULL; c = (Component *)c->co_next) if (c->co_type == NODE) { xcomponent = (XCOMPONENT *) c->co_picture; XRaiseWindow(the_environment.the_display, xcomponent->comp_window); } make_line_array(); XClearWindow(the_environment.the_display, the_environment.back_window); connect_components(); XFlush(the_environment.the_display); } void comp_display_sorted() { Component *c, *nc; XCOMPONENT *xcomponent, *xc_node, *xpic2; short int x, y; Neighbor *neigh; int i, j; for (c = (Component *)comps->l_head; c; c = (Component *)c->co_next) if (c->co_type == NODE) { neigh = (Neighbor *) c->co_neighbors->l_head; xc_node = (XCOMPONENT *) c->co_picture; for (i = j = 0; neigh; neigh = neigh->n_next) { nc = neigh->n_c; xcomponent = (XCOMPONENT *) nc->co_picture; x = (short) xcomponent->x; y = (short) xcomponent->y; switch (nc->co_class) { case (ROUTE_CLASS) : xcomponent->x = xc_node->x - 20 + 1; xcomponent->y = xc_node->y + 20 * j + 1; j++; break; case (LINK_CLASS) : break; default : xcomponent->x = xc_node->x + 20 + 1; xcomponent->y = xc_node->y + 20 * i + 1; i++; } XMoveWindow(the_environment.the_display, xcomponent->comp_window, xcomponent->x, xcomponent->y); } } for (c = (Component *)comps->l_head; c; c = (Component *)c->co_next) if (c->co_type == NODE) { xcomponent = (XCOMPONENT *) c->co_picture; XRaiseWindow(the_environment.the_display, xcomponent->comp_window); } make_line_array(); XClearWindow(the_environment.the_display, the_environment.back_window); connect_components(); XFlush(the_environment.the_display); }