#ifdef HAVE_CONFIG_H # include #endif #include #include "callbacks.h" #include "interface.h" #include "support.h" #include "ens.h" /* * Global variables */ #include "globals.h" /* Backing pixmap for drawing area */ static GdkPixmap *global_pixmap = NULL; /* Private functions */ static void draw_network(graph N); static void reset_drawing_area(GtkWidget *widget); static void draw_branch_white(GtkWidget *widget, graph_edge edge_ptr, graph_vertex vertex_ptr1, graph_vertex vertex_ptr2); static void draw_branch_halo(GtkWidget *widget, graph_edge edge_ptr, graph_vertex vertex_ptr1, graph_vertex vertex_ptr2, GdkColor color); static void draw_bus(GtkWidget *widget, graph_vertex vertex_ptr); static void draw_branch(GtkWidget *widget, graph_edge edge_ptr, graph_vertex vertex_ptr1, graph_vertex vertex_ptr2); static void draw_breakpoints(GtkWidget *widget, graph N); static locate_bus_with_id(GtkWidget *widget, graph N, edge_id_type id); static void draw_rectangle (GtkWidget *widget, gint x, gint y); static void draw_segment (GtkWidget *widget, gint x1, gint y1, gint x2, gint y2); static graph_edge get_branch_from_coords (graph N, int x, int y); static graph_vertex get_bus_from_coords (graph N, int x, int y); /* Private global variables */ static graph N=NULL; /**************************************************************************************** * Functions added by myself follow ****************************************************************************************/ void ini_network(int argc, char *argv[]) { FILE* fd; int nareas; area_id_type* selareas; int nselareas; int i; char file_line[200], command[100]; area_id_type area_id; int index_first_area; boolean all_selected_areas; /* Open the specified files for reading */ fd = fopen(argv[1],"r"); if(fd == NULL) { printf("Error: File %s not found\n", argv[1]); exit(-1); } /* If some areas are specified */ index_first_area = 2; if(argc>index_first_area) { all_selected_areas = FALSE; nselareas = argc - index_first_area; selareas = (area_id_type*)malloc(sizeof(area_id_type)*nselareas); for(i=0;iallocation.width; update_rect.height = widget->allocation.height; /* Paint the drawing area in white */ gdk_draw_rectangle (global_pixmap, widget->style->white_gc, TRUE, 0, 0, widget->allocation.width, widget->allocation.height); gtk_widget_draw (widget, &update_rect); } /*--------------------------------------------------------------------------------------*/ static void draw_branch_white(GtkWidget *widget, graph_edge edge_ptr, graph_vertex vertex_ptr1, graph_vertex vertex_ptr2) { GdkColor white; GdkRectangle update_rect; gint x1, y1, x2, y2; gint branch_width; branch_width = (gint)global_branch_width; white.red = 65535; white.green = 65535; white.blue = 65535; /* Get endpoint coords */ x1 = (gint)Xcoord(vertex_ptr1) + global_xmargin; y1 = (gint)Ycoord(vertex_ptr1) + global_ymargin; x2 = (gint)Xcoord(vertex_ptr2) + global_xmargin; y2 = (gint)Ycoord(vertex_ptr2) + global_ymargin; /* Draw white line to repaint later its actual state */ gdk_gc_set_rgb_fg_color(widget->style->black_gc,&white); gdk_gc_set_line_attributes(widget->style->black_gc,/* Graphic context */ branch_width, /* Line width */ GDK_LINE_SOLID, /* Line style (GDK_LINE_SOLID, GDK_LINE_ON_OFF_DASH, GDK_LINE_DOUBLE_DASH) */ GDK_CAP_BUTT, /* Cap style (GDK_CAP_NOT_LAST, GDK_CAP_BUTT, GDK_CAP_ROUND, GDK_CAP_PROJECTING) */ GDK_JOIN_MITER /* Join style (GDK_JOIN_MITER, GDK_JOIN_ROUND, GDK_JOIN_BEVEL) */ ); gdk_draw_line (global_pixmap, widget->style->black_gc, x1, y1, x2, y2); /* Update screen */ update_rect.x = (x1 <= x2 ? x1 : x2) - branch_width; update_rect.y = (y1 <= y2 ? y1 : y2) - branch_width; update_rect.width = abs(x2-x1) + 2 * branch_width; update_rect.height = abs(y2-y1)+ 2 * branch_width; gtk_widget_draw (widget, &update_rect); } /*--------------------------------------------------------------------------------------*/ static void draw_branch_halo(GtkWidget *widget, graph_edge edge_ptr, graph_vertex vertex_ptr1, graph_vertex vertex_ptr2, GdkColor color) { GdkRectangle update_rect; gint halo_width; gint x1, y1, x2, y2; /* Halo width */ halo_width = (gint)2*global_bus_side+1; /* Get endpoint coords */ x1 = (gint)Xcoord(vertex_ptr1) + global_xmargin; y1 = (gint)Ycoord(vertex_ptr1) + global_ymargin; x2 = (gint)Xcoord(vertex_ptr2) + global_xmargin; y2 = (gint)Ycoord(vertex_ptr2) + global_ymargin; /* Draw halo around the end buses */ gdk_gc_set_rgb_fg_color(widget->style->black_gc,&color); gdk_gc_set_line_attributes(widget->style->black_gc, /* Graphic context */ 1, /* Line width */ GDK_LINE_SOLID, /* Line style (GDK_LINE_SOLID, GDK_LINE_ON_OFF_DASH, GDK_LINE_DOUBLE_DASH) */ GDK_CAP_BUTT, /* Cap style (GDK_CAP_NOT_LAST, GDK_CAP_BUTT, GDK_CAP_ROUND, GDK_CAP_PROJECTING) */ GDK_JOIN_MITER /* Join style (GDK_JOIN_MITER, GDK_JOIN_ROUND, GDK_JOIN_BEVEL) */ ); gdk_draw_arc (global_pixmap, widget->style->black_gc, TRUE, x1 - global_bus_side, /* x top left corner of enclosing rectangle */ y1 - global_bus_side, /* y top left corner of enclosing rectangle */ halo_width, /* width of encosing rectangle */ halo_width, /* height of enclosing rectangle */ 0, /* initial angle in 1/64th of degree */ 360*64 /* final angle in 1/64th of degree */ ); gdk_draw_arc (global_pixmap, widget->style->black_gc, TRUE, x2 - global_bus_side, /* x top left corner of enclosing rectangle */ y2 - global_bus_side, /* y top left corner of enclosing rectangle */ halo_width, /* width of encosing rectangle */ halo_width, /* height of enclosing rectangle */ 0, /* initial angle in 1/64th of degree */ 360*64 /* final angle in 1/64th of degree */ ); /* Draw halo around the branch */ gdk_gc_set_rgb_fg_color(widget->style->black_gc,&color); gdk_gc_set_line_attributes(widget->style->black_gc, /* Graphic context */ halo_width, /* Line width */ GDK_LINE_SOLID, /* Line style (GDK_LINE_SOLID, GDK_LINE_ON_OFF_DASH, GDK_LINE_DOUBLE_DASH) */ GDK_CAP_BUTT, /* Cap style (GDK_CAP_NOT_LAST, GDK_CAP_BUTT, GDK_CAP_ROUND, GDK_CAP_PROJECTING) */ GDK_JOIN_MITER /* Join style (GDK_JOIN_MITER, GDK_JOIN_ROUND, GDK_JOIN_BEVEL) */ ); gdk_draw_line (global_pixmap, widget->style->black_gc, x1, y1, x2, y2); /* Update screen with pixmap */ update_rect.x = (x1 <= x2 ? x1 : x2) - global_bus_side; update_rect.y = (y1 <= y2 ? y1 : y2) - global_bus_side; update_rect.width = abs(x2-x1) + 2 * global_bus_side; update_rect.height = abs(y2-y1)+ 2 * global_bus_side; gtk_widget_draw (widget, &update_rect); } /*--------------------------------------------------------------------------------------*/ static void draw_bus(GtkWidget *widget, graph_vertex vertex_ptr) { GdkRectangle update_rect; GdkColor buscolor, contourcolor, sourcecolor, white, black, red; gint side; gint xcenter, ycenter, xcorner, ycorner; side = (gint)global_bus_side; xcenter = (gint)Xcoord(vertex_ptr) + global_xmargin; ycenter = (gint)Ycoord(vertex_ptr) + global_ymargin; xcorner = xcenter - (side-1)/2; /* side is assumed to be odd */ ycorner = ycenter - (side-1)/2; /* side is assumed to be odd */ update_rect.x = xcenter - 3 * side; update_rect.y = ycorner - 3 * side; update_rect.width = 6 * side; update_rect.height = 6 * side; white.red = 65535; white.green = 65535; white.blue = 65535; black.red = 0; black.green = 0; black.blue = 0; red.red = 65535; red.green = 0; red.blue = 0; /* Define colors */ contourcolor = black; sourcecolor = contourcolor; if(VERTEX_STATE(vertex_ptr) == CONNECTED) buscolor = red; else buscolor = white; /* If bus is a source, draw the transformer symbol */ if(VERTEX_TYPE(vertex_ptr)==FEEDER_VERTEX) { gdk_gc_set_rgb_fg_color(widget->style->black_gc,&sourcecolor); gdk_gc_set_line_attributes(widget->style->black_gc, /* Graphic context */ 1, /* Line width */ GDK_LINE_SOLID, /* Line style (GDK_LINE_SOLID, GDK_LINE_ON_OFF_DASH, GDK_LINE_DOUBLE_DASH) */ GDK_CAP_BUTT, /* Cap style (GDK_CAP_NOT_LAST, GDK_CAP_BUTT, GDK_CAP_ROUND, GDK_CAP_PROJECTING) */ GDK_JOIN_MITER /* Join style (GDK_JOIN_MITER, GDK_JOIN_ROUND, GDK_JOIN_BEVEL) */ ); gdk_draw_arc (global_pixmap, widget->style->black_gc, FALSE, xcenter - side, /* x top left corner of enclosing rectangle */ ycenter - 2 * side, /* y top left corner of enclosing rectangle */ 2 * side, /* width of encosing rectangle */ 2 * side, /* height of enclosing rectangle */ 0, /* initial angle in 1/64th of degree */ 360*64 /* final angle in 1/64th of degree */ ); gdk_draw_arc (global_pixmap, widget->style->black_gc, FALSE, xcenter - side, /* x top left corner of enclosing rectangle */ ycenter - 3 * side, /* y top left corner of enclosing rectangle */ 2 * side, /* width of encosing rectangle */ 2 * side, /* height of enclosing rectangle */ 0, /* initial angle in 1/64th of degree */ 360*64 /* final angle in 1/64th of degree */ ); } /* Draw bus contour */ if(Cabs(VERTEX_INJ_PWR(vertex_ptr)) >= 1e-10) { /* If the bus has injected power, we draw a box around it */ gdk_gc_set_rgb_fg_color(widget->style->black_gc,&contourcolor); gdk_draw_rectangle (global_pixmap, widget->style->black_gc, TRUE, xcorner-2, ycorner-2, side+4, side+4); gdk_gc_set_rgb_fg_color(widget->style->black_gc,&white); gdk_draw_rectangle (global_pixmap, widget->style->black_gc, TRUE, xcorner-1, ycorner-1, side+2, side+2); } gdk_gc_set_rgb_fg_color(widget->style->black_gc,&contourcolor); gdk_draw_rectangle (global_pixmap, widget->style->black_gc, TRUE, xcorner, ycorner, side, side); /* Draw bus interior to pixmap */ gdk_gc_set_rgb_fg_color(widget->style->black_gc,&buscolor); gdk_draw_rectangle (global_pixmap, widget->style->black_gc, TRUE, xcorner+1, ycorner+1, side-2, side-2); /* Update drawing area on screen */ gtk_widget_draw (widget, &update_rect); } /*--------------------------------------------------------------------------------------*/ static void draw_branch(GtkWidget *widget, graph_edge edge_ptr, graph_vertex vertex_ptr1, graph_vertex vertex_ptr2) { GdkRectangle update_rect; gint x1, y1, x2, y2; gint branch_width; GdkColor color, white, gray, normal_branch_color, switch_branch_color; GdkLineStyle line_style; branch_width = (gint)global_branch_width; x1 = (gint)Xcoord(vertex_ptr1) + global_xmargin; y1 = (gint)Ycoord(vertex_ptr1) + global_ymargin; x2 = (gint)Xcoord(vertex_ptr2) + global_xmargin; y2 = (gint)Ycoord(vertex_ptr2) + global_ymargin; update_rect.x = (x1 <= x2 ? x1 : x2) - branch_width; update_rect.y = (y1 <= y2 ? y1 : y2) - branch_width; update_rect.width = abs(x2-x1) + 2 * branch_width; update_rect.height = abs(y2-y1)+ 2 * branch_width; white.red = 65535; white.green = 65535; white.blue = 65535; gray.red = 30000; gray.green = 30000; gray.blue = 30000; switch_branch_color.red = 0; switch_branch_color.green = 65535; switch_branch_color.blue = 0; normal_branch_color.red = 0; normal_branch_color.green = 0; normal_branch_color.blue = 0; /* Set line style according to switch state */ if(EDGE_STATE(edge_ptr) == OPEN) line_style = GDK_LINE_ON_OFF_DASH; else line_style = GDK_LINE_SOLID; gdk_gc_set_line_attributes(widget->style->black_gc,/* Graphic context */ branch_width, /* Line width */ line_style, /* Line style (GDK_LINE_SOLID, GDK_LINE_ON_OFF_DASH, GDK_LINE_DOUBLE_DASH) */ GDK_CAP_BUTT, /* Cap style (GDK_CAP_NOT_LAST, GDK_CAP_BUTT, GDK_CAP_ROUND, GDK_CAP_PROJECTING) */ GDK_JOIN_MITER /* Join style (GDK_JOIN_MITER, GDK_JOIN_ROUND, GDK_JOIN_BEVEL) */ ); /* Set line color according to switch type */ if(EDGE_TYPE(edge_ptr)==SWITCH_EDGE) gdk_gc_set_rgb_fg_color(widget->style->black_gc,&switch_branch_color); else gdk_gc_set_rgb_fg_color(widget->style->black_gc,&normal_branch_color); /* Draw line on pixmap */ gdk_draw_line (global_pixmap, widget->style->black_gc, x1, y1, x2, y2); /* Update screen with pixmap */ gtk_widget_draw (widget, &update_rect); } /*--------------------------------------------------------------------------------------*/ static void draw_rectangle (GtkWidget *widget, gint x, gint y) { GdkRectangle update_rect; GdkColor mycolor; update_rect.x = x - 2; update_rect.y = y - 2; update_rect.width = 4; update_rect.height = 4; mycolor.red = 65535; mycolor.green = 0; mycolor.blue = 0; gdk_gc_set_rgb_fg_color(widget->style->black_gc,&mycolor); gdk_draw_rectangle (global_pixmap, widget->style->black_gc, TRUE, update_rect.x, update_rect.y, update_rect.width, update_rect.height); gtk_widget_draw (widget, &update_rect); } /*--------------------------------------------------------------------------------------*/ static void draw_segment (GtkWidget *widget, gint x1, gint y1, gint x2, gint y2) { GdkRectangle update_rect; update_rect.x = (x1 <= x2 ? x1 : x2); update_rect.y = (y1 <= y2 ? y1 : y2); update_rect.width = abs(x2-x1)+1; update_rect.height = abs(y2-y1)+1; gdk_gc_set_line_attributes(widget->style->black_gc, /* Graphic context */ 2, /* Line width */ GDK_LINE_SOLID, /* Line style */ GDK_CAP_BUTT, /* Cap style */ GDK_JOIN_MITER /* Join style */ ); gdk_draw_line (global_pixmap, widget->style->black_gc, x1, y1, x2, y2); gtk_widget_draw (widget, &update_rect); } /*--------------------------------------------------------------------------------------*/ static graph_edge get_branch_from_coords(graph N, int x, int y) /* * Check whether there is a branch below the pointer */ { boolean found; graph_vertex pv; graph_edge pe, curr_e; gint x1, y1, x2, y2, xbl, ybl, width, height; double Rx, Ry, normR, wx, wy, dist_to_orig, eps; found = FALSE; for(pv=N; found!=TRUE && pv!=NULL; pv=NEXT(pv)) { for(pe=EMANATING(pv); found!=TRUE && pe!=NULL; pe=NEXT(pe)) { if(COPY(pe)==1) { x1 = Xcoord(pv) + global_xmargin; y1 = Ycoord(pv) + global_ymargin; x2 = Xcoord(VERTEX_PTR(pe)) + global_xmargin; y2 = Ycoord(VERTEX_PTR(pe)) + global_ymargin; xbl = (x1 <= x2 ? x1 : x2); ybl = (y1 <= y2 ? y1 : y2); width = abs(x2-x1); height = abs(y2-y1); Rx = ((double)(x2 - x1)); Ry = ((double)(y2 - y1)); normR = sqrt(pow(Rx,2.0) + pow(Ry,2.0)); wx = Rx / normR; wy = Ry / normR; dist_to_orig = wy * ((double)x2) - wx * ((double)y2); eps = ((double)global_branch_width)/1.5; found = (x >= xbl && x <= xbl+width && y >= ybl && y <= ybl+height && wy * ((double)x) - wx * ((double)y) >= dist_to_orig - eps && wy * ((double)x) - wx * ((double)y) <= dist_to_orig + eps); curr_e = pe; } } } if (found) return(curr_e); else return(NULL); } /*--------------------------------------------------------------------------------------*/ static graph_vertex get_bus_from_coords(graph N, int x, int y) /* * Checks whether there is a bus on point (x,y). If there is one, it * returns a pointer to the bus, otherwise it returns NULL. */ { graph_vertex pv, curr_v; boolean found = FALSE; for(pv=N; found!=TRUE && pv!=NULL; pv=NEXT(pv)) { found = (x >= Xcoord(pv) + global_xmargin - 2 && x <= Xcoord(pv) + global_xmargin + 2 && y >= Ycoord(pv) + global_ymargin - 2 && y <= Ycoord(pv) + global_ymargin + 2); curr_v = pv; } return( found? curr_v : NULL); } /*--------------------------------------------------------------------------------------*/ static locate_bus_with_id(GtkWidget *widget, graph N, edge_id_type id) { GdkRectangle update_rect; GdkColor color; gint xcenter, ycenter, xcorner, ycorner; gint radius, width; graph_vertex vertex_ptr; vertex_ptr = find_bus_with_id(N,id); if(vertex_ptr!=NULL) { radius = 13; width = 4; xcenter = (gint)Xcoord(vertex_ptr) + global_xmargin; ycenter = (gint)Ycoord(vertex_ptr) + global_ymargin; xcorner = xcenter - radius; ycorner = ycenter - radius; update_rect.x = xcorner; update_rect.y = ycorner; update_rect.width = (2*radius)+width; update_rect.height = (2*radius)+width; color.red = 65535; color.green = 0; color.blue = 0; gdk_gc_set_rgb_fg_color(widget->style->black_gc,&color); gdk_gc_set_line_attributes(widget->style->black_gc, /* Graphic context */ width, /* Line width */ GDK_LINE_SOLID, /* Line style (GDK_LINE_SOLID, GDK_LINE_ON_OFF_DASH, GDK_LINE_DOUBLE_DASH) */ GDK_CAP_BUTT, /* Cap style (GDK_CAP_NOT_LAST, GDK_CAP_BUTT, GDK_CAP_ROUND, GDK_CAP_PROJECTING) */ GDK_JOIN_MITER /* Join style (GDK_JOIN_MITER, GDK_JOIN_ROUND, GDK_JOIN_BEVEL) */ ); gdk_draw_arc (global_pixmap, widget->style->black_gc, FALSE, xcorner, /* x top left corner of enclosing rectangle */ ycorner, /* y top left corner of enclosing rectangle */ 2*radius, /* width of encosing rectangle */ 2*radius, /* height of enclosing rectangle */ 0, /* initial angle in 1/64th of degree */ 360*64 /* final angle in 1/64th of degree */ ); /* Update drawing area on screen */ gtk_widget_draw (widget, &update_rect); } else { printf("Bus not found\n"); exit(-1); } } /**************************************************************************************** * Functions (actually their prototypes) added by Glade follow ****************************************************************************************/ void on_open_activate (GtkMenuItem *menuitem, gpointer user_data) { } /*--------------------------------------------------------------------------------------*/ void on_save_activate (GtkMenuItem *menuitem, gpointer user_data) { } /*--------------------------------------------------------------------------------------*/ void on_saveas_activate (GtkMenuItem *menuitem, gpointer user_data) { } /*--------------------------------------------------------------------------------------*/ void on_preferences_activate (GtkMenuItem *menuitem, gpointer user_data) { } /*--------------------------------------------------------------------------------------*/ void on_quit_activate (GtkMenuItem *menuitem, gpointer user_data) { gtk_main_quit(); } /*--------------------------------------------------------------------------------------*/ void on_find_bus_activate (GtkMenuItem *menuitem, gpointer user_data) { } /*--------------------------------------------------------------------------------------*/ void on_find_branch_activate (GtkMenuItem *menuitem, gpointer user_data) { } /*--------------------------------------------------------------------------------------*/ void on_find_area_activate (GtkMenuItem *menuitem, gpointer user_data) { } /*--------------------------------------------------------------------------------------*/ void on_find_sources_activate (GtkMenuItem *menuitem, gpointer user_data) { } /*--------------------------------------------------------------------------------------*/ void on_add_element_activate (GtkMenuItem *menuitem, gpointer user_data) { } /*--------------------------------------------------------------------------------------*/ void on_add_bus_activate (GtkMenuItem *menuitem, gpointer user_data) { } /*--------------------------------------------------------------------------------------*/ void on_add_branch_activate (GtkMenuItem *menuitem, gpointer user_data) { } /*--------------------------------------------------------------------------------------*/ void on_remove_element_activate (GtkMenuItem *menuitem, gpointer user_data) { } /*--------------------------------------------------------------------------------------*/ void on_remove_bus_activate (GtkMenuItem *menuitem, gpointer user_data) { } /*--------------------------------------------------------------------------------------*/ void on_remove_branch_activate (GtkMenuItem *menuitem, gpointer user_data) { } /*--------------------------------------------------------------------------------------*/ void on_about1_activate (GtkMenuItem *menuitem, gpointer user_data) { } /*--------------------------------------------------------------------------------------*/ on_drawingarea_main_configure_event (GtkWidget *widget, GdkEventConfigure *event, gpointer user_data) /* Handler for configure_event's of the main window. * This function is called whenever the main drawing area * changes size, including when it is originally created */ { /* Free previous pixmap if it existed */ if (global_pixmap) gdk_pixmap_unref(global_pixmap); /* Generate a new pixmap with the new size of the drawing area */ global_pixmap = gdk_pixmap_new(widget->window, widget->allocation.width, widget->allocation.height, -1); /* Paint the drawing area in white */ gdk_draw_rectangle (global_pixmap, widget->style->white_gc, TRUE, 0, 0, widget->allocation.width, widget->allocation.height); /* Draw the network if it has already been loaded */ if(N!=NULL) { draw_network(N); } return TRUE; } /*--------------------------------------------------------------------------------------*/ gboolean on_drawingarea_main_expose_event (GtkWidget *widget, GdkEventExpose *event, gpointer user_data) { gdk_draw_pixmap(widget->window, widget->style->fg_gc[GTK_WIDGET_STATE (widget)], global_pixmap, event->area.x, event->area.y, event->area.x, event->area.y, event->area.width, event->area.height); return FALSE; } /*--------------------------------------------------------------------------------------*/ gboolean on_drawingarea_main_motion_notify_event (GtkWidget *widget, GdkEventMotion *event, gpointer user_data) /* Handler for motion notify events on the drawing area. This function is called * whenever some motion event occurs on this window, like moving the mouse on it, * with or without clicking. */ { gint x, y; GdkModifierType state; gint context_id; GtkWidget* status_bar; gchar *buff; graph_vertex vertex_ptr; graph_edge edge_ptr; /************************************************************* * Compute x and y coordinates of event, and its state *************************************************************/ /* Necessary to only process as many motion events as the machine can process */ if (event->is_hint) gdk_window_get_pointer (event->window, &x, &y, &state); else { x = event->x; y = event->y; state = event->state; } /************************************************************* * Process "drag while clocking" events *************************************************************/ /* Draws a rectangle */ /* if (state & GDK_BUTTON1_MASK && global_pixmap != NULL) */ /* draw_rectangle (widget, x, y); */ /************************************************************* * Process "pointer on bus/branch" events *************************************************************/ /* Get pointer and context id of status bar */ status_bar = lookup_widget(GTK_WIDGET(widget),"statusbar1"); context_id = gtk_statusbar_get_context_id(GTK_STATUSBAR(status_bar), "sb1_main_context"); /* If it is on a bus, print the bus state to the status bar */ if(status_bar!=NULL && N!=NULL) { /* Check whether there is a bus below the pointer */ vertex_ptr = get_bus_from_coords(N, x, y); if(vertex_ptr!=NULL) { /* There is a bus and we print its state on the status bar */ buff = g_strdup_printf ("Bus %u, Area %u: Voltage=[%.3f,%.3f] p.u. (%.3f KV), Inj. Power=[%.3f,%.3f] p.u (%.4lf KVA)", VERTEX_ID(vertex_ptr), VERTEX_AREA(vertex_ptr), VERTEX_VOLTAGE(vertex_ptr).r, VERTEX_VOLTAGE(vertex_ptr).i, Cabs(VERTEX_VOLTAGE(vertex_ptr)) * VBASE, VERTEX_INJ_PWR(vertex_ptr).r, VERTEX_INJ_PWR(vertex_ptr).i, Cabs(VERTEX_INJ_PWR(vertex_ptr)) * SBASE ); gtk_statusbar_push (GTK_STATUSBAR (status_bar), context_id, buff); g_free (buff); } else { /* Check whether there is a branch below the pointer */ edge_ptr = get_branch_from_coords(N, x, y); if(edge_ptr!=NULL) { /* There is a branch and we print its state onto the status bar */ buff = g_strdup_printf ("Branch %u: I=[%.4f,%.4f] p.u. (%.4f A), Imax=%.4f A, Z = [%.2e,%.2e] p.u. (%.2e Ohm)", EDGE_ID(edge_ptr), EDGE_INTENSITY(edge_ptr).r, EDGE_INTENSITY(edge_ptr).i, Cabs(EDGE_INTENSITY(edge_ptr)) * IBASE, EDGE_MAX_INTENSITY(edge_ptr), EDGE_IMPEDANCE(edge_ptr).r, EDGE_IMPEDANCE(edge_ptr).i, Cabs(EDGE_IMPEDANCE(edge_ptr)) * ZBASE ); gtk_statusbar_push (GTK_STATUSBAR (status_bar), context_id, buff); g_free (buff); } } /* If no bus/branch was found, remove the last message from the status bar, to leave it empty */ if(vertex_ptr==NULL && edge_ptr==NULL) { gtk_statusbar_pop(GTK_STATUSBAR(status_bar), context_id); } } return TRUE; } /*--------------------------------------------------------------------------------------*/ gboolean on_drawingarea_main_button_press_event (GtkWidget *widget, GdkEventButton *event, gpointer user_data) { graph_edge edge_ptr; /* If we press mouse button 1 on a branch ... */ if (event->button == 1 && global_pixmap != NULL) { edge_ptr = get_branch_from_coords(N, event->x, event->y); /* if(edge_ptr!=NULL && EDGE_TYPE(edge_ptr)==SWITCH_EDGE) */ if(edge_ptr!=NULL) { printf("Clicked on switch\n"); toggle_branch_state_with_ptr(edge_ptr); power_flow_network(N); draw_network(N); } } return TRUE; }