#include #include #include #include #include #include "objectInterface.h" #include "dotImporter.h" #include "psExporter.h" #include "visioExporter.h" #include "optFileWriter.h" #include "optFileReader.h" extern GtkWidget *drawingarea1; extern GtkWidget *statusbar1; extern GtkWidget *scrolledwindow1; extern int node_selected; objectInterface::objectInterface() { my_nodes = new nodes(); my_physics = new physics(this); selected_node = 0; draw_nodes = draw_springs = true; filename = 0; } objectInterface::~objectInterface() { free(filename); delete my_nodes; delete my_physics; } void objectInterface::create_new() { delete my_nodes; my_nodes = new nodes(); status("All nodes destroyed."); // make save button do save as... if (filename != 0) free(filename); } void objectInterface::open(char *what_file) { optFileReader *reader = new optFileReader(what_file, my_nodes); int read_success = reader->read(); delete reader; if (read_success) { // save filename so save button doesn't do save as... if (filename != 0) free(filename); filename = strdup(what_file); my_nodes->assign_layers(); int length = strlen(what_file) + 9; char *message = new char[length]; snprintf(message, length, "%s opened.", what_file); status(message); delete message; } else { char *message = new char[17]; snprintf(message, 17, "File open failed\0"); status(message); delete message; } } int objectInterface::save() { if (filename == 0) return 1; else { char *temp = strdup(filename); save_as(temp); free(temp); } return 0; } void objectInterface::save_as(char *what_file) { if (filename != 0) free(filename); filename = strdup(what_file); optFileWriter *writer = new optFileWriter(what_file, my_nodes); writer->write(); delete writer; int length = strlen(what_file) + 8; char *message = new char[length]; snprintf(message, length, "%s saved.", what_file); status(message); delete message; } void objectInterface::import(char *what_file) { delete my_nodes; my_nodes = new nodes(); status("All nodes destroyed."); dotImporter *importer = new dotImporter(what_file, my_nodes); int import_success = importer->import(); delete importer; if (import_success) { my_nodes->assign_layers(); int length = strlen(what_file) + 11; char *message = new char[length]; snprintf(message, 75, "%s imported.", what_file); status(message); delete message; // make save button do save as... if (filename != 0) free(filename); } else { char *message = new char[14]; snprintf(message, 14, "Import failed\0"); status(message); delete message; } } void objectInterface::export_to_visio(char *what_file) { visioExporter *exporter = new visioExporter(what_file, my_nodes); exporter->do_export(); delete exporter; int length = strlen(what_file) + 23; char *message = new char[length]; snprintf(message, length, "%s exported as Visio csv", what_file); status(message); delete message; } void objectInterface::export_as_ps(char *what_file) { psExporter *exporter = new psExporter(what_file, my_nodes); exporter->do_export(); delete exporter; int length = strlen(what_file) + 24; char *message = new char[length]; snprintf(message, length, "%s exported as postscript", what_file); status(message); delete message; } void objectInterface::export_as_gif(char *what_file) { status("function not implemented."); } void objectInterface::set_model_parameters(int new_node_width, int new_node_height, float new_node_mass, float new_node_charge, int new_spring_length, float new_spring_constant, float max_sa_movement, bool new_draw_nodes, bool new_draw_springs, int new_layers_to_hide) { node_width = new_node_width; node_height = new_node_height; draw_nodes = new_draw_nodes; draw_springs = new_draw_springs; layers_to_hide = new_layers_to_hide; my_physics->set_parameters(new_node_mass, new_node_charge, new_spring_length, new_spring_constant, max_sa_movement, layers_to_hide); } void objectInterface::separate_nodes() { my_physics->separate_nodes(my_nodes); } void objectInterface::advance_model() { // Move it, boys! my_physics->advance(my_nodes); } void objectInterface::draw_model() { node *temp_node; node *temp_node2; // Get the largest and smallest x and y coordinates float smallx, smally, bigx, bigy, thisx, thisy, thisx2, thisy2; smallx = smally = 15000; bigx = bigy = -15000; for (int temp = 0; temp < my_nodes->number_of_nodes(); temp++) { temp_node = my_nodes->get_node(temp); if (temp_node->get_layer() > layers_to_hide) { thisx = temp_node->x_pos; thisy = temp_node->y_pos; if (thisx < smallx) smallx = thisx; else if (thisx > bigx) bigx = thisx; if (thisy < smally) smally = thisy; else if (thisy > bigy) bigy = thisy; } } // compensate for the size of nodes float half_node_width = 0.5 * node_width; float half_node_height = 0.5 * node_height; smallx -= half_node_width; bigx += half_node_width; smally -= half_node_height; bigy += half_node_height; // Clear the drawing space gdk_window_clear(drawingarea1->window); // resize the drawing area so everything will fit (remember the smallest // values) IF our drawing area is smaller than it should be. We don' shreenk. if ((drawingarea1->allocation.width < (int) (bigx - smallx + 2)) || (drawingarea1->allocation.height < (int) (bigy - smally + 2))) { gtk_widget_set_usize (drawingarea1, (int) (bigx - smallx + 2), (int) (bigy - smally + 2)); } if (draw_nodes || draw_springs) { // Draw the nodes, adjusting so the node with the smallest values is // drawn in positive space for (int temp = 0; temp < my_nodes->number_of_nodes(); temp++) { temp_node = my_nodes->get_node(temp); // only draw this node if it isn't in a layer we should hide if (temp_node->get_layer() > layers_to_hide) { thisx = temp_node->x_pos - smallx + 1; thisy = temp_node->y_pos - smally + 1; if (draw_nodes) gdk_draw_rectangle(drawingarea1->window, drawingarea1->style-> fg_gc[drawingarea1->state], FALSE, (int) (thisx - (0.5 * node_width)), (int) (thisy - (0.5 * node_height)), node_width, node_height); if (draw_springs) { // Draw lines to the nodes we point to for (int temp2 = 0; temp2 < temp_node->number_of_connections; temp2++) { temp_node2 = temp_node->connecting_nodes[temp2]; // only draw the line if the destination node isn't in a // layer we should hide if (temp_node2->get_layer() > layers_to_hide) { thisx2 = temp_node2->x_pos - smallx + 1; thisy2 = temp_node2->y_pos - smally + 1; gdk_draw_line(drawingarea1->window, drawingarea1->style-> fg_gc[drawingarea1->state], (int) thisx, (int) thisy, (int) thisx2, (int) thisy2); } //******* mebbee put this back in as a configuration option // Triangle pointy at the end of the connection //GdkPoint *points = new GdkPoint[3]; //points = compute_arrowhead_points(points, thisx, thisy, // thisx2, thisy2); //gdk_draw_polygon(drawingarea1->window, // drawingarea1->style->fg_gc[drawingarea1->state], // TRUE, // points, // 3); //delete points; } } } } } } GdkPoint *objectInterface::compute_arrowhead_points(GdkPoint *points, int x1, int y1, int x2, int y2) { int point_length = 8; int half_width = 3; int x_difference = abs(x2 - x1); int y_difference = abs(y2 - y1); float theta = atan(y_difference/x_difference); // first point is at the end of the line points[0].x = x2; points[0].y = y2; float cross_point_x; float cross_point_y; if (x2 > x1) cross_point_x = x2 - (cos(theta) * point_length); else cross_point_x = x2 + (cos(theta) * point_length); if (y2 > y1) cross_point_y = y2 - (sin(theta) * point_length); else cross_point_y = y2 + (sin(theta) * point_length); float theta2 = M_PI_2 - theta; if (x2 > x1) { points[1].x = (int) (cross_point_x - (cos(theta2) * half_width)); points[2].x = (int) (cross_point_x + (cos(theta2) * half_width)); } else { points[1].x = (int) (cross_point_x + (cos(theta2) * half_width)); points[2].x = (int) (cross_point_x - (cos(theta2) * half_width)); } if (y2 < y1) { points[1].y = (int) (cross_point_y - (sin(theta2) * half_width)); points[2].y = (int) (cross_point_y + (sin(theta2) * half_width)); } else { points[1].y = (int) (cross_point_y + (sin(theta2) * half_width)); points[2].y = (int) (cross_point_y - (sin(theta2) * half_width)); } return points; } void objectInterface::select_node_at(float which_x, float which_y) { // Translate the clicked (display) coordinates to our real coordinates float my_x = which_x; float my_y = which_y; float horizontal_scroll_offset = gtk_scrolled_window_get_hadjustment((GtkScrolledWindow *) scrolledwindow1)-> value; float vertical_scroll_offset = gtk_scrolled_window_get_vadjustment((GtkScrolledWindow *) scrolledwindow1)-> value; my_x += horizontal_scroll_offset; my_y += vertical_scroll_offset; translate_coordinates(&my_x, &my_y); // Grab the first node within a node's size of the real coordinates node *temp_node; float x_difference, y_difference; char *message; for (int temp = 0; temp < my_nodes->number_of_nodes(); temp++) { temp_node = my_nodes->get_node(temp); if (temp_node->get_layer() > layers_to_hide) { x_difference = temp_node->x_pos - my_x; y_difference = temp_node->y_pos - my_y; if (x_difference < 0) x_difference = -x_difference; if (y_difference < 0) y_difference = -y_difference; if ((x_difference < (0.5 * node_width)) && (y_difference < (0.5 * node_height))) { selected_node = temp_node; message = new char[75]; snprintf(message, 75, "%s Node Selected. Click again to place it.", temp_node->name); status(message); delete message; node_selected = 1; return; } } } } void objectInterface::move_selected_node_to(float new_x, float new_y) { // Translate the clicked (display) coordinates to our real coordinates float my_x = new_x; float my_y = new_y; float horizontal_scroll_offset = gtk_scrolled_window_get_hadjustment((GtkScrolledWindow *) scrolledwindow1)-> value; float vertical_scroll_offset = gtk_scrolled_window_get_vadjustment((GtkScrolledWindow *) scrolledwindow1)-> value; my_x += horizontal_scroll_offset; my_y += vertical_scroll_offset; translate_coordinates(&my_x, &my_y); // Move the node selected_node->x_pos = my_x; selected_node->y_pos = my_y; // Deselect the node selected_node = 0; node_selected = 0; status(" "); } void objectInterface::translate_coordinates(float *x, float *y) { // Get the largest and smallest x and y coordinates float smallx, smally, bigx, bigy, thisx, thisy; node *temp_node; smallx = smally = 15000; bigx = bigy = -15000; for (int temp = 0; temp < my_nodes->number_of_nodes(); temp++) { temp_node = my_nodes->get_node(temp); if (temp_node->get_layer() > layers_to_hide) { thisx = temp_node->x_pos; thisy = temp_node->y_pos; if (thisx < smallx) smallx = thisx; if (thisx > bigx) bigx = thisx; if (thisy < smally) smally = thisy; if (thisy > bigy) bigy = thisy; } } // compensate for the size of nodes float half_node_width = 0.5 * node_width; float half_node_height = 0.5 * node_height; smallx -= half_node_width; bigx += half_node_width; smally -= half_node_height; bigy += half_node_height; *x = *x + smallx - 1; *y = *y + smally - 1; } void objectInterface::status(char *message) { gtk_statusbar_pop((GtkStatusbar *) statusbar1, gtk_statusbar_get_context_id((GtkStatusbar *) statusbar1, "pop")); gtk_statusbar_push((GtkStatusbar *) statusbar1, gtk_statusbar_get_context_id((GtkStatusbar *) statusbar1, "push"), message); } void objectInterface::gather_nodes_with_layer(int which_layer) { my_nodes->gather_nodes_with_layer(which_layer); }