#include "xcddraw.h" #include #include #include extern "C" double sqrt(double); int button2Pressed = 0; int button1Pressed = 0; int moving_flag = 0; int last_mouse_x; int last_mouse_y; VertexStore *vertex_store = new VertexStore(); ObjectStore *consedge_store = new ObjectStore(); ObjectStore *repedge_store = new ObjectStore(); ObjectStore *altedge_store = new ObjectStore(); ObjectStore *inhedge_store = new ObjectStore(); ObjectStore *paredge_store = new ObjectStore(); ObjectStore *parinstedge_store = new ObjectStore(); VertexObject *drawing_vertex = NULL; EdgeObject *drawing_edge = NULL; GraphicsObject *selected_object = NULL; int box_height = 60; int box_width = 60; extern void assign_actual_pars( int &changed,ParameterAssignmentStore*tmpstore,VertexObject *); extern void select_clicked_obj(int x,int y,long,GraphicsObject*&); extern void reorder_classes(); extern void deleteObject(GraphicsObject* ); void cancelDrawingVertexCallback(Widget w,XtPointer,XtPointer) { drawing_vertex->xor_draw(); XUngrabPointer(XtDisplay(draw_area),0); /* free data */ drawing_vertex = NULL; sprintf(message,"Draw vertex: The drwaing vertex is canceled.\n"); xm_print_message(message); XBell(XtDisplay(draw_area),0); } void cancelDrawingEdgeCallback(Widget w,XtPointer,XtPointer) { drawing_edge->xor_draw(); XUngrabPointer(XtDisplay(draw_area),0); /* free data */ drawing_edge = NULL; sprintf(message,"Draw edge: The drwaing edge is canceled.\n"); xm_print_message(message); XBell(XtDisplay(draw_area),0); return; } void redrawCallback(Widget w,XtPointer, XtPointer) { XClearWindow(XtDisplay(draw_area), XtWindow(draw_area)); XClearArea(XtDisplay(draw_area), XtWindow(draw_area), 0, 0, 0, 0, True); } void reorderCallback(Widget w,XtPointer, XtPointer) { reorder_classes(); } void read_class_name(Widget w,char **r,XmSelectionBoxCallbackStruct *cbs) { if (cbs->value == NULL) { dialog_done = 1; XtDestroyWidget(w); } if (!XmStringGetLtoR ( cbs->value,XmSTRING_DEFAULT_CHARSET,r )) { dialog_done = 1; *r = NULL; XtDestroyWidget(w); } if (((*r == NULL || strlen(*r)==0)) && (drawing_choices.tv || drawing_choices.pv)) { *r = NULL; xm_print_message("Vertex name is needed.\n"); XBell(XtDisplay(w),0); return; } if (*r == NULL) { dialog_done = 1; *r = NULL; xm_print_message("System error: unable to get the typed data.\n"); XtDestroyWidget(w); } if (strlen(*r)==0) { dialog_done = 1; XtDestroyWidget(w); return; } /* name check */ /* ABC $INT ABC@ASA ABBD@@ASAS */ int i = 0; int has_alphabet = 0; if ((*r)[i] == '$') { if (drawing_choices.ev == 0) { free(*r); *r = NULL; xm_print_message("Draw vertex: $ can only be used for external vertex names.\n"); XBell(XtDisplay(w),0); return; } i++; } if ( ((*r)[i] != '_') && (((*r)[i] > 'Z') || ((*r)[i] < 'A')) && (((*r)[i] > 'z') || ((*r)[i] < 'a'))) { free(*r); *r = NULL; sprintf(message,"Draw vertex: %s is not a legal vertex name.\n",*r); xm_print_message(message); XBell(XtDisplay(w),0); return; } if ((*r)[i] != '_') has_alphabet = 1; i++; while (((*r)[i] != '\0') && ((*r)[i] != '@')) { if ((((*r)[i] > 'Z') || ((*r)[i] < 'A')) && (((*r)[i] > 'z') || ((*r)[i] < 'a')) && (((*r)[i] > '9') || ((*r)[i] < '0')) && ((*r)[i] != '_')) { free(*r); *r = NULL; sprintf(message,"Draw vertex: %s is not a legal vertex name.\n",*r); xm_print_message(message); XBell(XtDisplay(w),0); return; } if ((((*r)[i] <= 'Z') && ((*r)[i] >= 'A')) || (((*r)[i] <= 'z') && ((*r)[i] >= 'a'))) has_alphabet = 1; i++; } if ((*r)[i] == '\0') { if (has_alphabet) { if (drawing_choices.tv) { if ((strcmp(*r,"DemString") != 0) && (strcmp(*r,"DemText") != 0) && (strcmp(*r,"DemNumber") != 0) && (strcmp(*r,"DemReal") != 0) && (strcmp(*r,"DemIdent") != 0)) { free(*r); *r = NULL; sprintf(message,"Draw vertex: Legal terminal vertex names are: \n DemIdent, DemString, DemText, DemNumber and DemReal.\n"); xm_print_message(message); XBell(XtDisplay(w),0); return; } } else if ((drawing_choices.ev) && ((*r)[0] != '$')) { free(*r); *r = NULL; sprintf(message,"Draw vertex: %s is not a legal external xcddrawvertex name.\n",*r); xm_print_message(message); XBell(XtDisplay(w),0); return; } else if ((strcmp(*r,"DemString") == 0) || (strcmp(*r,"DemText") == 0) || (strcmp(*r,"DemNumber") == 0) || (strcmp(*r,"DemReal") == 0) || (strcmp(*r,"DemIdent") == 0)) { free(*r); *r = NULL; sprintf(message,"Draw vertex: %s is a terminal class name.\n",*r); xm_print_message(message); XBell(XtDisplay(w),0); return; } /* checking whether the name is used for different vertex */ if (drawing_choices.pv == 0) { int legal = 1; if (drawing_choices.cv) vertex_store->check_conflict_name(*r,legal,CONS_VERTEX); if (drawing_choices.av) vertex_store->check_conflict_name(*r,legal,ALT_VERTEX); if (drawing_choices.rv) vertex_store->check_conflict_name(*r,legal,REP_VERTEX); if (!legal) { sprintf(message, "Draw vertex: %s has been used for a different kind of vertex.\n",*r); xm_print_message(message); XBell(XtDisplay(w),0); free(*r); *r = NULL; return; } } char *tmp = (char*)malloc(strlen(*r)+1); strcpy(tmp,*r); free(*r); *r = tmp; dialog_done = 1; XtDestroyWidget(w); return; } else { free(*r); *r = NULL; sprintf(message, "Draw vertex: There is no alphabet in %s.\n",*r); xm_print_message(message); XBell(XtDisplay(w),0); return; } } if (drawing_choices.ev == 0) { free(*r); *r = NULL; sprintf(message,"Draw vertex: External vertex names are in the forms like $int, A@C or Widget@@MOTIF.\n"); xm_print_message(message); XBell(XtDisplay(w),0); return; } if (!has_alphabet) { free(*r); *r = NULL; sprintf(message,"Draw vertex: There is no alphabet in %s.\n",*r); xm_print_message(message); XBell(XtDisplay(w),0); return; } i++; if ((*r)[i] == '@') i++; if ((*r)[i] == '\0') { free(*r); *r = NULL; sprintf(message,"Draw vertex: External vertex names are in the forms like $int, A@C or Widget@@MOTIF.\n"); xm_print_message(message); XBell(XtDisplay(w),0); return; } has_alphabet = 0; while ((*r)[i] != '\0') { if ((((*r)[i] > 'Z') || ((*r)[i] < 'A')) && (((*r)[i] > 'z') || ((*r)[i] < 'a')) && (((*r)[i] > '9') || ((*r)[i] < '0')) && ((*r)[i] != '_')) { free(*r); *r = NULL; sprintf(message,"Draw vertex: %s is not a legal vertex name.\n",*r); xm_print_message(message); XBell(XtDisplay(w),0); return; } if ((((*r)[i] <= 'Z') && ((*r)[i] >= 'A')) || (((*r)[i] <= 'z') && ((*r)[i] >= 'a'))) has_alphabet = 1; i++; } if (has_alphabet) { char *tmp = (char*)malloc(strlen(*r)+1); strcpy(tmp,*r); free(*r); *r = tmp; dialog_done = 1; XtDestroyWidget(w); return; } else { free(*r); *r = NULL; sprintf(message,"Draw vertex: %s is not a legal vertex name.\n",*r); xm_print_message(message); XBell(XtDisplay(w),0); return; } } void read_label_name(Widget w,char **r,XmSelectionBoxCallbackStruct *cbs) { if (cbs->value == NULL) { dialog_done = 1; XtDestroyWidget(w); } if (!XmStringGetLtoR ( cbs->value,XmSTRING_DEFAULT_CHARSET,r )) { dialog_done = 1; *r = NULL; XtDestroyWidget(w); } if (*r == NULL || strlen(*r)==0) { *r = NULL; sprintf(message,"Draw edge: Edge label is needed.\n"); xm_print_message(message); XBell(XtDisplay(w),0); return; } /* name check */ int i = 0; int has_alphabet = 0; if ( ((*r)[i] != '_') && (((*r)[i] > 'Z') || ((*r)[i] < 'A')) && (((*r)[i] > 'z') || ((*r)[i] < 'a'))) { free(*r); *r = NULL; sprintf(message,"Draw edge: %s is not a legal edge label.\n",*r); xm_print_message(message); XBell(XtDisplay(w),0); return; } if ((*r)[i] != '_') has_alphabet = 1; i++; while ((*r)[i] != '\0') { if ((((*r)[i] > 'Z') || ((*r)[i] < 'A')) && (((*r)[i] > 'z') || ((*r)[i] < 'a')) && (((*r)[i] > '9') || ((*r)[i] < '0')) && ((*r)[i] != '_')) { free(*r); *r = NULL; sprintf(message,"Draw edge: %s is not a legal edge label.\n",*r); xm_print_message(message); XBell(XtDisplay(w),0); return; } if ((((*r)[i] <= 'Z') && ((*r)[i] >= 'A')) || (((*r)[i] <= 'z') && ((*r)[i] >= 'a'))) has_alphabet = 1; i++; } if (has_alphabet) { char *tmp = (char*)malloc(strlen(*r)+1); strcpy(tmp,*r); free(*r); *r = tmp; dialog_done = 1; XtDestroyWidget(w); return; } else { free(*r); *r = NULL; sprintf(message,"Draw edge: %s is not a legal edge label.\n",*r); xm_print_message(message); XBell(XtDisplay(w),0); return; } } void cancelDialog(Widget w,XtPointer unused,XmSelectionBoxCallbackStruct *cbs) { dialog_done = 1; XtDestroyWidget(w); } void enter_class_name(Widget parent, char *prompt, char**r) { Widget dialog; XmString t = XmStringCreateSimple(prompt); int n; n = 0; XtSetArg(wargs[n], XmNselectionLabelString, t); n++; XtSetArg(wargs[n], XmNautoUnmanage, False); n++; XtSetArg(wargs[n], XmNdialogStyle, XmDIALOG_APPLICATION_MODAL); n++; dialog = XmCreatePromptDialog(parent, "Prompt", wargs, n); XmStringFree(t); /* always destroy compound strings when done */ /* When the user types the name, call read_name() ... */ XtAddCallback(dialog, XmNokCallback, (XtCallbackProc)read_class_name, (XtPointer)r); /* If the user selects cancel, just destroy the dialog */ XtAddCallback(dialog, XmNcancelCallback, (XtCallbackProc)cancelDialog, NULL); /* No help is available... */ XtSetSensitive( XmSelectionBoxGetChild(dialog, XmDIALOG_HELP_BUTTON), False); XtManageChild(dialog); XtPopup(XtParent(dialog), XtGrabExclusive); dialog_done = 0; while ( dialog_done == 0 || XtAppPending(app)) XtAppProcessEvent(app, XtIMAll); } void enter_label_name(Widget parent, char *prompt, char**r) { Widget dialog; XmString t = XmStringCreateSimple(prompt); int n; XUngrabPointer(XtDisplay(draw_area),0); n = 0; XtSetArg(wargs[n], XmNselectionLabelString, t); n++; XtSetArg(wargs[n], XmNautoUnmanage, False); n++; XtSetArg(wargs[n], XmNdialogStyle, XmDIALOG_APPLICATION_MODAL); n++; dialog = XmCreatePromptDialog(parent, "Prompt", wargs, n); XmStringFree(t); /* always destroy compound strings when done */ /* When the user types the name, call read_name() ... */ XtAddCallback(dialog, XmNokCallback, (XtCallbackProc)read_label_name, (XtPointer)r); /* If the user selects cancel, just destroy the dialog */ XtAddCallback(dialog, XmNcancelCallback, (XtCallbackProc)cancelDialog, NULL); /* No help is available... */ XtSetSensitive( XmSelectionBoxGetChild(dialog, XmDIALOG_HELP_BUTTON), False); XtManageChild(dialog); XtPopup(XtParent(dialog), XtGrabExclusive); dialog_done = 0; while ( dialog_done == 0 || XtAppPending(app)) XtAppProcessEvent(app, XtIMAll); } void create_vertex_rubber_box( int oldx, int oldy, int *x, int *y) { *x = oldx; *y = oldy; if (*x + box_width >= view_width) *x = view_width - box_width; if (*y + box_height >= view_height) *y = view_height - box_height; *x += pix_hoffset; *y += pix_voffset; } VertexObject *create_construction_vertex() { ConstructionVertex *tmp_v = new ConstructionVertex(); ClassNameObject *tmp_name = new ClassNameObject(); Rectangle *tmp_box = new Rectangle(); tmp_v->set_name(tmp_name); tmp_v->set_box(tmp_box); return tmp_v; } VertexObject *create_terminal_vertex() { TerminalVertex *tmp_v = new TerminalVertex(); ClassNameObject *tmp_name = new ClassNameObject(); TRectangle *tmp_box = new TRectangle(); tmp_v->set_name(tmp_name); tmp_v->set_box(tmp_box); return tmp_v; } VertexObject *create_alternation_vertex() { AlternationVertex *tmp_v = new AlternationVertex(); ClassNameObject *tmp_name = new ClassNameObject(); Hexagon *tmp_box = new Hexagon(); tmp_v->set_name(tmp_name); tmp_v->set_box(tmp_box); return tmp_v; } VertexObject *create_repetition_vertex() { RepetitionVertex *tmp_v = new RepetitionVertex(); ClassNameObject *tmp_name = new ClassNameObject(); HexagonRect *tmp_box = new HexagonRect(); tmp_v->set_name(tmp_name); tmp_v->set_box(tmp_box); return tmp_v; } VertexObject *create_external_vertex() { ExternalVertex *tmp_v = new ExternalVertex(); ClassNameObject *tmp_name = new ClassNameObject(); ERectangle *tmp_box = new ERectangle(); tmp_v->set_name(tmp_name); tmp_v->set_box(tmp_box); return tmp_v; } VertexObject *create_param_vertex() { ParameterVertex *tmp_v = new ParameterVertex(); ClassNameObject *tmp_name = new ClassNameObject(); Circle *tmp_box = new Circle(); tmp_v->set_name(tmp_name); tmp_v->set_box(tmp_box); return tmp_v; } void start_drawing_vertex( graphics_data *data, enum draw_kind kind, VertexObject* (*create_vertex) (), XEvent *e) { int x,y; if (drawing_vertex != NULL) return; if ((view_width < box_width) || (view_height < box_height)) { sprintf(message,"Window is too small to draw.\n"); xm_print_message(message); XBell(XtDisplay(draw_area),0); return; } data->last_action = kind; create_vertex_rubber_box(e->xbutton.x,e->xbutton.y,&x,&y); data->last_x = data->start_x = x; data->last_y = data->start_y = y; drawing_vertex = create_vertex(); drawing_vertex->set_xy(x,y); drawing_vertex->xor_draw(); } void finish_drawing_vertex(XEvent *e, graphics_data *data) { char *name = NULL; data->last_action = NONE; XUngrabPointer(XtDisplay(draw_area),0); /* ask class name */ enter_class_name(draw_area,"Enter Class Name:", &name); drawing_vertex->xor_draw(); if (name) { int x,y; /* set name */ create_vertex_rubber_box(e->xbutton.x,e->xbutton.y,&x,&y); drawing_vertex->set_xy(x,y); drawing_vertex->set_name(name,x,y+13); if (selected_object) selected_object->unSelect(); selected_object = NULL; if (strlen(name) ==0) drawing_vertex->set_is_template(0); /* store vertex object */ vertex_store->append(drawing_vertex); drawing_vertex->draw(); check_update_flag(); } else delete drawing_vertex; drawing_vertex = NULL; } void scroll_window(int x, int y, int &isItScrolled) { int newx,newy; int inc = 30; /* for scrolling */ int new_width, new_height, oldw, oldh; int do_clear = 0; int vdoit = 0; int hdoit = 0; oldw = view_width; oldh = view_height; new_width = view_width; new_height = view_height; if (abs(y - view_height) < 3) { newy = y - inc; if ((int)new_height >= draw_area_height) { if (pix_voffset != 0) vdoit = 1; pix_voffset = 0; sw_voffset = (view_height - draw_area_height)/2; do_clear = 1; new_height = draw_area_height; } else { if (pix_voffset + inc > draw_area_height - new_height) { pix_voffset = draw_area_height - new_height; vdoit = 1; } else if (pix_voffset != draw_area_height - new_height) { pix_voffset += inc; vdoit = 1; } sw_voffset = 0; if (oldh > draw_area_height) do_clear = 1; } if (vdoit) { XtVaSetValues(draw_vsb, XmNsliderSize, max(new_height, 1), XmNvalue, pix_voffset, XmNpageIncrement, max(new_height-1, 1), NULL); } } if (abs(y) < 3) { newy = inc; if ((int)new_height >= draw_area_height) { if (pix_voffset != 0) vdoit = 1; pix_voffset = 0; sw_voffset = (view_height - draw_area_height)/2; do_clear = 1; new_height = draw_area_height; } else { if ( (pix_voffset <= inc) && (pix_voffset != 0) ) { pix_voffset = 0; vdoit = 1; } else if (pix_voffset != 0) { pix_voffset -= inc; vdoit = 1; } sw_voffset = 0; if (oldh > draw_area_height) do_clear = 1; } if (vdoit) { XtVaSetValues(draw_vsb, XmNsliderSize, max(new_height, 1), XmNvalue, pix_voffset, XmNpageIncrement, max(new_height-1, 1), NULL); } } if ( abs(x - view_width) < 3 ) { newx = x - inc; if ((int)new_width >= draw_area_width) { if (pix_hoffset != 0) hdoit = 1; pix_hoffset = 0; sw_hoffset = (view_width - draw_area_width)/2; do_clear = 1; new_width = draw_area_width; } else { if (pix_hoffset + inc > draw_area_width - new_width) { pix_hoffset = draw_area_width - new_width; hdoit = 1; } else if (pix_hoffset != draw_area_width - new_width) { pix_hoffset += inc; hdoit = 1; } sw_hoffset = 0; if (oldw > draw_area_width) do_clear = 1; } if (hdoit) { XtVaSetValues(draw_hsb, XmNsliderSize, max(new_width, 1), XmNvalue, pix_hoffset, XmNpageIncrement, max(new_width-1, 1), NULL); } } if (abs(x) < 3) { newx = inc; if ((int)new_width >= draw_area_width) { if (pix_hoffset != 0) hdoit = 1; pix_hoffset = 0; sw_hoffset = (view_width - draw_area_width)/2; do_clear = 1; new_width = draw_area_width; } else { if ((pix_hoffset <= inc) && (pix_hoffset != 0)) { pix_hoffset = 0; hdoit = 1; } else if (pix_hoffset != 0) { pix_hoffset -= inc; hdoit = 1; } sw_hoffset = 0; if (oldw > draw_area_width) do_clear = 1; } if (hdoit) { XtVaSetValues(draw_hsb, XmNsliderSize, max(new_width, 1), XmNvalue, pix_hoffset, XmNpageIncrement, max(new_width-1, 1), NULL); } } if (vdoit || hdoit) { isItScrolled = 1; XClearWindow(XtDisplay(draw_area), XtWindow(draw_area)); XClearArea(XtDisplay(draw_area), XtWindow(draw_area), 0, 0, 0, 0, True); create_zoom_view(NULL,NULL,NULL); /* if it exists, nothing done */ } else { } } void fail_to_draw_edge(graphics_data* data) { /* redraw the line to erase */ drawing_edge->xor_draw(); delete drawing_edge; drawing_edge = NULL; data->last_action = NONE; XBell(XtDisplay(draw_area),0); XUngrabPointer(XtDisplay(draw_area),0); return; } void checking_incoming_edge( VertexObject *sv, graphics_data* data, VertexObject*ev) { /* should be of the same kind */ if (data->choice->pie && sv->get_kind() != ev->get_kind()) { sprintf(message,"Draw edge: The source and the target vertices have to be the same type.\n"); xm_print_message(message); fail_to_draw_edge(data); return; } /* need to provide arguments */ if (data->choice->ie && ev->isTemplateInst() && !ev->no_formal_parameters()) { sprintf(message,"Draw edge: The target vertex has formal arguments.\n"); xm_print_message(message); fail_to_draw_edge(data); return; } switch (ev->get_kind()) { case CONS_VERTEX: { if (data->choice->pe) { sprintf(message, "Draw edge: Construction vertices cannot have incoming parameter edges.\n"); xm_print_message(message); fail_to_draw_edge(data); return; } if (data->choice->ie) { sprintf(message, "Draw edge: Construction vertices cannot have incoming inheritance edges.\n"); xm_print_message(message); fail_to_draw_edge(data); return; } if (data->choice->pie && ev->no_formal_parameters()) { sprintf(message, "Draw edge: The target vertex does not have formal arguments.\n"); xm_print_message(message); fail_to_draw_edge(data); return; } break; } case ALT_VERTEX: { if (data->choice->pe) { sprintf(message, "Draw edge: Alternationn vertices cannot have incoming parameter edges.\n"); xm_print_message(message); fail_to_draw_edge(data); return; } if (data->choice->pie && ev->no_formal_parameters()) { sprintf(message, "Draw edge: The target vertex does not have formal arguments.\n"); xm_print_message(message); fail_to_draw_edge(data); return; } break; } case REP_VERTEX: { if (data->choice->ae) { sprintf(message, "Draw edge: Repetition vertices cannot have incoming alternation edges.\n"); xm_print_message(message); fail_to_draw_edge(data); return; } if (data->choice->ie) { sprintf(message, "Draw edge: Repetition vertices cannot have incoming inheritance edges.\n"); xm_print_message(message); fail_to_draw_edge(data); return; } if (data->choice->pe) { sprintf(message, "Draw edge: Repetition vertices cannot have incoming parameter edges.\n"); xm_print_message(message); fail_to_draw_edge(data); return; } if (data->choice->pie && ev->no_formal_parameters()) { sprintf(message, "Draw edge: The target vertex does not have formal arguments.\n"); xm_print_message(message); fail_to_draw_edge(data); return; } break; } case TERM_VERTEX: { if (data->choice->ae) { sprintf(message, "Draw edge: Terminal vertices cannot have incoming alternation edges.\n"); xm_print_message(message); fail_to_draw_edge(data); return; } if (data->choice->ie) { sprintf(message, "Draw edge: Terminal vertices cannot have incoming inheritance edges.\n"); xm_print_message(message); fail_to_draw_edge(data); return; } if (data->choice->pe) { sprintf(message, "Draw edge: Terminal vertices cannot have incoming parameter edges.\n"); xm_print_message(message); fail_to_draw_edge(data); return; } if (data->choice->pie) { sprintf(message, "Draw edge: Terminal vertices cannot have incoming template instantiation edges.\n"); xm_print_message(message); fail_to_draw_edge(data); return; } break; } case EXT_VERTEX: { if (data->choice->ae) { sprintf(message, "Draw edge: External vertices cannot have incoming alternation edges.\n"); xm_print_message(message); fail_to_draw_edge(data); return; } if (data->choice->pe) { sprintf(message, "Draw edge: External vertices can not have incoming parameter edges.\n"); xm_print_message(message); fail_to_draw_edge(data); return; } if ( data->choice->pie && ev->no_formal_parameters()) { sprintf(message, "Draw edge: The target vertex does not have formal arguments.\n"); xm_print_message(message); fail_to_draw_edge(data); return; } break; } case PARAM_VERTEX: { if (data->choice->ae) { sprintf(message, "Draw edge: Paramter vertices cannot have incoming alternation edges.\n"); xm_print_message(message); fail_to_draw_edge(data); return; } if (data->choice->ie) { sprintf(message, "Draw edge: Paramter vertices cannot have incoming inheritance edges.\n"); xm_print_message(message); fail_to_draw_edge(data); return; } break; } default: { sprintf(message,"Draw edge: Fatal error: unknown vertex kind (draw line)\n"); xm_print_message(message); assert(0); exit(1); } } } void press_draw(Widget w,graphics_data* data,XEvent* e) { static long last_time = 0; typedef enum click_kind_t { SINGLE_CLICK, DOUBLE_CLICKS }; click_kind_t click_kind; if (e->xbutton.time - last_time < 180) click_kind = DOUBLE_CLICKS; else click_kind = SINGLE_CLICK; last_time = e->xbutton.time; static Cursor pencil_cur = NULL; if (pencil_cur == NULL) pencil_cur = XCreateFontCursor(XtDisplay(w),XC_pencil); static Cursor sel_cur = NULL; if (sel_cur == NULL) sel_cur = XCreateFontCursor(XtDisplay(w),XC_hand2); static Cursor box_cur = NULL; if (box_cur == NULL) box_cur = XCreateFontCursor(XtDisplay(w),XC_dotbox); static Cursor del_cur = NULL; if (del_cur == NULL) del_cur = XCreateFontCursor(XtDisplay(w),XC_pirate); if (e->xbutton.button == Button1) { button1Pressed = 1; if (data->choice->sel || data->choice->trash) XGrabPointer( XtDisplay(w), XtWindow(w), TRUE, ButtonPressMask | ButtonMotionMask | ButtonReleaseMask | PointerMotionMask | EnterWindowMask | LeaveWindowMask , GrabModeAsync, GrabModeAsync, XtWindow(draw_area), sel_cur, 0); else if (data->choice->re || data->choice->oe || data->choice->ae || data->choice->ie || data->choice->pe || data->choice->pie) XGrabPointer( XtDisplay(w), XtWindow(w), TRUE, ButtonPressMask | ButtonMotionMask | ButtonReleaseMask | PointerMotionMask | EnterWindowMask | LeaveWindowMask, GrabModeAsync, GrabModeAsync, XtWindow(draw_area), pencil_cur, 0); else XGrabPointer( XtDisplay(w), XtWindow(w), TRUE, ButtonPressMask | ButtonMotionMask | ButtonReleaseMask | PointerMotionMask | EnterWindowMask | LeaveWindowMask, GrabModeAsync, GrabModeAsync, XtWindow(draw_area), box_cur, 0); if (data->choice->sel || data->choice->trash) { if (selected_object) selected_object->unSelect(); selected_object = NULL; select_clicked_obj(e->xbutton.x,e->xbutton.y, e->xbutton.time,selected_object); button1Pressed = 0; button2Pressed = 0; /* UnGrabButton and UnGrabPointer are taken care by ButtonRelease */ if (!selected_object) return; selected_object->draw_select(); if (data->choice->trash) { int done = 0; selected_object->deleteObject(done); if (done && (selected_object->get_selected_flag() == SELECT_EDGE || selected_object->get_selected_flag() == SELECT_VERTEX || selected_object->get_selected_flag() == SELECT_EDGE_END_POINT || selected_object->get_selected_flag() == SELECT_EDGE_START_POINT || selected_object->get_selected_flag() == SELECT_EDGE_LABEL)) { delete selected_object; selected_object = NULL; XUngrabPointer(XtDisplay(draw_area),0); XClearWindow(XtDisplay(draw_area), XtWindow(draw_area)); XClearArea(XtDisplay(draw_area), XtWindow(draw_area), 0, 0, 0, 0, True); check_update_flag(); } else if (done) { check_update_flag(); } selected_object = NULL; XUngrabPointer(XtDisplay(draw_area),0); XClearWindow(XtDisplay(draw_area), XtWindow(draw_area)); XClearArea(XtDisplay(draw_area), XtWindow(draw_area), 0, 0, 0, 0, True); return; } if (click_kind == DOUBLE_CLICKS) { XUngrabPointer(XtDisplay(w),0); selected_object->doubleClickPopup(); redraw(); } return; } if (data->choice->cv) start_drawing_vertex(data,CONS_VERTEX,create_construction_vertex,e); else if (data->choice->av) start_drawing_vertex(data,ALT_VERTEX,create_alternation_vertex,e); else if (data->choice->rv) start_drawing_vertex(data,REP_VERTEX,create_repetition_vertex,e); else if (data->choice->tv) start_drawing_vertex(data,TERM_VERTEX,create_terminal_vertex,e); else if (data->choice->ev) start_drawing_vertex(data,EXT_VERTEX,create_external_vertex,e); else if (data->choice->pv) start_drawing_vertex(data,PARAM_VERTEX,create_param_vertex,e); else { /* you must be drawing an edge */ int x,y; PointObject *npt; x = e->xbutton.x; y = e->xbutton.y; if (drawing_edge == NULL) { /* found the point on the boundary of a box-object */ VertexObject * start_vertex = NULL; vertex_store->select_box(x,y, e->xbutton.x + pix_hoffset, e->xbutton.y + pix_voffset,start_vertex); if (!start_vertex) { XUngrabPointer(XtDisplay(w),0); return; } /* from what kind of vertex */ if (start_vertex->get_kind() == TERM_VERTEX) { sprintf(message, "Draw edge: You cannot draw edges from terminal vertices.\n"); xm_print_message(message); XUngrabPointer(XtDisplay(w),0); XBell(XtDisplay(w),0); return; } if (start_vertex->get_kind() == PARAM_VERTEX) { sprintf(message, "Draw edge: You cannot draw edges from parameter vertices.\n"); xm_print_message(message); XUngrabPointer(XtDisplay(w),0); XBell(XtDisplay(w),0); return; } if ((start_vertex->get_kind() == EXT_VERTEX) && (!data->choice->ae) && (!data->choice->pe) && (!data->choice->pie)) { sprintf(message, "Draw edge: Extenal vertices can only have outgoing alternation, template instantiation and parameter edges.\n"); xm_print_message(message); XUngrabPointer(XtDisplay(w),0); XBell(XtDisplay(w),0); return; } if ((start_vertex->get_kind() == CONS_VERTEX) && (data->choice->ae)) { sprintf(message, "Draw edge: You cannot draw alternation edges from construction vertices.\n"); xm_print_message(message); XUngrabPointer(XtDisplay(w),0); XBell(XtDisplay(w),0); return; } if ((start_vertex->get_kind() == REP_VERTEX) && data->choice->ae) { sprintf(message, "Draw edge: You cannot draw alternation edges from repetition vertices.\n"); xm_print_message(message); XUngrabPointer(XtDisplay(w),0); XBell(XtDisplay(w),0); return; } if ((start_vertex->get_kind() == REP_VERTEX) && ( data->choice->re || data->choice->oe) && (start_vertex->get_subhome()->has_rep_edge())) { sprintf(message, "Draw edge: There is an outgoing repetition edge already.\n"); xm_print_message(message); XUngrabPointer(XtDisplay(w),0); XBell(XtDisplay(w),0); return; } if (start_vertex->isTemplateInst() && !data->choice->pie) { sprintf(message, "Draw edge: Only outgoing template instance edges allowed.\n"); xm_print_message(message); XUngrabPointer(XtDisplay(w),0); XBell(XtDisplay(w),0); return; } if (!start_vertex->isTemplateInst() && data->choice->pie) { sprintf(message, "Draw edge: You cannot draw outgoing template instance edges.\n"); xm_print_message(message); XUngrabPointer(XtDisplay(w),0); XBell(XtDisplay(w),0); return; } if (!start_vertex->get_outgoing_parinstedge_store()->empty() && data->choice->pie) { sprintf(message, "Draw edge: There is an outgoing template instantiation edge already.\n"); xm_print_message(message); XUngrabPointer(XtDisplay(w),0); XBell(XtDisplay(w),0); return; } if (start_vertex->get_kind() == REP_VERTEX && !start_vertex->get_outgoing_repedge_store()->empty() && ( data->choice->re || data->choice->oe)) { sprintf(message, "Draw edge: There is an outgoing repetition edge already.\n"); xm_print_message(message); XUngrabPointer(XtDisplay(w),0); XBell(XtDisplay(w),0); return; } if (data->choice->pe) { assert( start_vertex->get_subhome() ); if ( start_vertex->get_subhome()->vertexInUse()) { sprintf(message,"Draw edge: The template is being used.\n"); xm_print_message(message); XUngrabPointer(XtDisplay(w),0); XBell(XtDisplay(w),0); return; } } drawing_edge = new UndeterminedEdge(); drawing_edge->set_from_vertex(start_vertex); npt = new PointObject(); npt->set_x(x); npt->set_y(y); drawing_edge->append(npt); npt = new PointObject(); npt->set_x(x); npt->set_y(y); drawing_edge->append(npt); if (data->choice->re) data->last_action = REQ_EDGE; else if (data->choice->oe) data->last_action = OPT_EDGE; else if (data->choice->ae) data->last_action = ALT_EDGE; else if (data->choice->ie) data->last_action = INH_EDGE; else if (data->choice->pe) data->last_action = PAR_EDGE; else if (data->choice->pie) data->last_action = PAR_INST_EDGE; drawing_edge->xor_draw_last_segment(); return; } /* intermediate points go here */ /* erase the old */ assert( drawing_edge != NULL ); npt = new PointObject(); npt->set_x(x + pix_hoffset); npt->set_y(y + pix_voffset); drawing_edge->append(npt); drawing_edge->xor_draw_last_segment(); } } else if (e->xbutton.button == Button2) { button2Pressed = 1; if (drawing_vertex) /* I've finished moving the drawing vertex */ { finish_drawing_vertex(e,data); } else if (drawing_edge) /* I have finished moving the drawing edge */ { int x,y; PointObject *npt; EdgeObject *tmp_edge = NULL; ParameterAssignmentStore *tmpstore = NULL; /* found the point on the boundary of a box-object */ VertexObject * end_vertex = NULL; vertex_store->select_box(x,y, e->xbutton.x + pix_hoffset, e->xbutton.y + pix_voffset,end_vertex); if (!end_vertex) return; /* from what kind of vertex, to what kind of vertex check whether it is meaningful . dont forget to free space. */ checking_incoming_edge(drawing_edge->get_from_vertex(), data,end_vertex); if (!drawing_edge) /* no illegal connection */ return; /* checking duplication goes here */ int ret = 1; if (data->choice->pe) drawing_edge->get_from_vertex()->get_subhome() ->no_duplicate_target(ret,PAR_EDGE, end_vertex->get_vertex_name()); if (data->choice->ae) drawing_edge->get_from_vertex()->get_subhome() ->no_duplicate_target(ret,ALT_EDGE, end_vertex->get_vertex_name()); if (data->choice->ie) drawing_edge->get_from_vertex()->get_subhome() ->no_duplicate_target(ret,INH_EDGE, end_vertex->get_vertex_name()); if (data->choice->ie) drawing_edge->get_from_vertex()->get_subhome() ->no_duplicate_target(ret,PAR_INST_EDGE, end_vertex->get_vertex_name()); if (ret == 0) { /* redraw the line to erase */ drawing_edge->xor_draw(); data->last_action = NONE; XUngrabPointer(XtDisplay(w),0); /* free data */ delete drawing_edge; drawing_edge = NULL; sprintf(message,"Draw edge: The same edge exists already.\n"); xm_print_message(message); XBell(XtDisplay(w),0); return; } /* Cycle checking */ /************************************************************** ** All checking done (except edge label) ** ***************************************************************/ drawing_edge->set_xy(x,y); if (data->choice->re) { if (drawing_edge->get_from_vertex()->get_kind() == REP_VERTEX) { tmp_edge = new ReqRepetitionEdge(); tmp_edge->set_points(drawing_edge->get_points()); tmp_edge->set_max_x(drawing_edge->get_max_x()); tmp_edge->set_max_y(drawing_edge->get_max_y()); tmp_edge->set_min_x(drawing_edge->get_min_x()); tmp_edge->set_min_y(drawing_edge->get_min_y()); tmp_edge->set_from_vertex(drawing_edge->get_from_vertex()); tmp_edge->set_to_vertex(end_vertex); } else { char *name = NULL; enter_label_name(draw_area,"Enter Edge Label:", &name); if (name == NULL) { /* redraw the line to erase */ drawing_edge->xor_draw(); data->last_action = NONE; XUngrabPointer(XtDisplay(w),0); /* free data */ delete drawing_edge; drawing_edge = NULL; sprintf(message,"Draw edge: The drawing edge is canceled.\n"); xm_print_message(message); XBell(XtDisplay(w),0); return; } tmp_edge = new ReqConstructionEdge(); tmp_edge->set_points(drawing_edge->get_points()); tmp_edge->set_max_x(drawing_edge->get_max_x()); tmp_edge->set_max_y(drawing_edge->get_max_y()); tmp_edge->set_min_x(drawing_edge->get_min_x()); tmp_edge->set_min_y(drawing_edge->get_min_y()); ((ReqConstructionEdge*)tmp_edge)->initial_set_label(name); tmp_edge->set_from_vertex(drawing_edge->get_from_vertex()); tmp_edge->set_to_vertex(end_vertex); } } else if (data->choice->oe) { if (drawing_edge->get_from_vertex()->get_kind() == REP_VERTEX) { tmp_edge = new OptRepetitionEdge(); tmp_edge->set_points(drawing_edge->get_points()); tmp_edge->set_max_x(drawing_edge->get_max_x()); tmp_edge->set_max_y(drawing_edge->get_max_y()); tmp_edge->set_min_x(drawing_edge->get_min_x()); tmp_edge->set_min_y(drawing_edge->get_min_y()); tmp_edge->set_from_vertex(drawing_edge->get_from_vertex()); tmp_edge->set_to_vertex(end_vertex); } else { char *name = NULL; enter_label_name(draw_area,"Enter Edge Label:", &name); if (name == NULL) { /* redraw the line to erase */ drawing_edge->xor_draw(); data->last_action = NONE; XUngrabPointer(XtDisplay(w),0); /* free data */ delete drawing_edge; drawing_edge = NULL; sprintf(message,"Draw edge: The drawing edge is canceled.\n"); xm_print_message(message); XBell(XtDisplay(w),0); return; } tmp_edge = new OptConstructionEdge(); tmp_edge->set_points(drawing_edge->get_points()); tmp_edge->set_max_x(drawing_edge->get_max_x()); tmp_edge->set_max_y(drawing_edge->get_max_y()); tmp_edge->set_min_x(drawing_edge->get_min_x()); tmp_edge->set_min_y(drawing_edge->get_min_y()); ((OptConstructionEdge*)tmp_edge)->initial_set_label(name); tmp_edge->set_from_vertex(drawing_edge->get_from_vertex()); tmp_edge->set_to_vertex(end_vertex); } } else if (data->choice->ae) { tmp_edge = new AlternationEdge(); tmp_edge->set_points(drawing_edge->get_points()); tmp_edge->set_max_x(drawing_edge->get_max_x()); tmp_edge->set_max_y(drawing_edge->get_max_y()); tmp_edge->set_min_x(drawing_edge->get_min_x()); tmp_edge->set_min_y(drawing_edge->get_min_y()); tmp_edge->set_from_vertex(drawing_edge->get_from_vertex()); tmp_edge->set_to_vertex(end_vertex); } else if (data->choice->ie) { tmp_edge = new InheritanceEdge(); tmp_edge->set_points(drawing_edge->get_points()); tmp_edge->set_max_x(drawing_edge->get_max_x()); tmp_edge->set_max_y(drawing_edge->get_max_y()); tmp_edge->set_min_x(drawing_edge->get_min_x()); tmp_edge->set_min_y(drawing_edge->get_min_y()); tmp_edge->set_from_vertex(drawing_edge->get_from_vertex()); tmp_edge->set_to_vertex(end_vertex); } else if (data->choice->pe) { tmp_edge = new ParameterEdge(); tmp_edge->set_points(drawing_edge->get_points()); tmp_edge->set_max_x(drawing_edge->get_max_x()); tmp_edge->set_max_y(drawing_edge->get_max_y()); tmp_edge->set_min_x(drawing_edge->get_min_x()); tmp_edge->set_min_y(drawing_edge->get_min_y()); tmp_edge->set_from_vertex(drawing_edge->get_from_vertex()); tmp_edge->set_to_vertex(end_vertex); } else if (data->choice->pie) { if (end_vertex->no_formal_parameters()) { sprintf(message,"Draw edge: There is no formal argument.\n"); xm_print_message(message); /* redraw the line to erase */ drawing_edge->xor_draw(); fail_to_draw_edge(data); return; } /* assigning formal arguments It should not be allowed that no change occurs */ tmpstore = new ParameterAssignmentStore(); int changed = 0; end_vertex->get_parassignstore()-> duplicate_parassign(tmpstore,1); assign_actual_pars(changed,tmpstore,drawing_edge->get_from_vertex()); /* operate on tmpstore */ if (!changed) { sprintf(message,"Draw edge: You need provide actual arguments.\n"); xm_print_message(message); /* redraw the line to erase */ drawing_edge->xor_draw(); fail_to_draw_edge(data); return; } tmp_edge = new ParameterInstEdge(); tmp_edge->set_points(drawing_edge->get_points()); tmp_edge->set_max_x(drawing_edge->get_max_x()); tmp_edge->set_max_y(drawing_edge->get_max_y()); tmp_edge->set_min_x(drawing_edge->get_min_x()); tmp_edge->set_min_y(drawing_edge->get_min_y()); tmp_edge->set_from_vertex(drawing_edge->get_from_vertex()); tmp_edge->set_to_vertex(end_vertex); tmp_edge->get_from_vertex()->set_subhome( tmp_edge->get_to_vertex()->get_subhome()); } assert( tmp_edge != NULL || drawing_edge != NULL ); /* redraw the line to erase */ drawing_edge->xor_draw(); drawing_edge->set_points(NULL); /* tell destructor */ delete drawing_edge; drawing_edge = tmp_edge; /* store edge and select */ check_update_flag(); switch (drawing_edge->get_kind()) { case REQ_C_EDGE: case OPT_C_EDGE: /* this function also appends the edge to the lists of */ /* incoming and outgoing edges. */ consedge_store->append_edge(drawing_edge); drawing_edge->get_from_vertex()->get_subhome()-> get_outgoing_consedge_store()->append(drawing_edge); /* check the from and to vertices and see whether */ /* they are name-sensitive vertice */ break; case ALT_EDGE: /* this function also appends the edge to the lists of */ /* incoming and outgoing edges. */ altedge_store->append_edge(drawing_edge); /* check the from and to vertices and see whether */ /* they are name-sensitive vertice */ break; case REQ_R_EDGE: case OPT_R_EDGE: /* this function also appends the edge to the lists of */ /* incoming and outgoing edges. */ repedge_store->append_edge(drawing_edge); /* check the from and to vertices and see whether */ /* they are name-sensitive vertice */ break; case INH_EDGE: /* this function also appends the edge to the lists of */ /* incoming and outgoing edges. */ inhedge_store->append_edge(drawing_edge); /* check the from and to vertices and see whether */ /* they are name-sensitive vertice */ break; case PAR_EDGE: /* this function also appends the edge to the lists of */ /* incoming and outgoing edges. */ paredge_store->append_edge(drawing_edge); /* check the from and to vertices and see whether */ /* they are name-sensitive vertice */ drawing_edge->get_from_vertex()->get_subhome() ->append_parassign((ParameterEdge*)drawing_edge); break; case PAR_INST_EDGE: /* this function also appends the edge to the lists of */ /* incoming and outgoing edges. */ parinstedge_store->append_edge(drawing_edge); /* check the from and to vertices and see whether */ /* they are name-sensitive vertice */ /* duplicate parameter assignments */ /* go up along the instatiation hierarchy */ drawing_edge->get_from_vertex()->duplicate_parassign(tmpstore,0); assert(tmpstore != NULL); delete tmpstore; /* to be finished */ if (drawing_edge->get_to_vertex()->isTemplateInst()) { /* shared objec !! */ assert(drawing_edge->get_to_vertex()->get_template_name()); drawing_edge->get_from_vertex()->set_template_name( drawing_edge->get_to_vertex()->get_template_name()); } else { /* is an template */ assert(drawing_edge->get_to_vertex()->get_name()); drawing_edge->get_from_vertex() ->set_template_name(drawing_edge->get_to_vertex()->get_name()); } /* move the from vertex to its new home */ vertex_store->remove_from_unbound(drawing_edge->get_from_vertex()); vertex_store->append(drawing_edge->get_from_vertex()); break; default: { sprintf(message,"Fatal error: unknown vertex kind(draw line)\n"); xm_print_message(message); assert(0); exit(1); } } /* final draw and select edge label */ if (selected_object) selected_object->unSelect(); selected_object = NULL; if (data->choice->pe || data->choice->pie) redraw(); else drawing_edge->draw(); drawing_edge = NULL; data->last_action = NONE; XUngrabPointer(XtDisplay(w),0); } else { /* XGrabButton(XtDisplay(draw_area), Button2, AnyModifier, XtWindow(draw_area), TRUE, Button2MotionMask, GrabModeAsync, GrabModeAsync, XtWindow(draw_area), XCreateFontCursor(XtDisplay(draw_area),XC_crosshair)); */ /* end of moving , if anything selected */ assert(drawing_vertex == NULL && drawing_edge == NULL); if (selected_object) selected_object->unSelect(); selected_object = NULL; select_clicked_obj(e->xbutton.x,e->xbutton.y,e->xbutton.time, selected_object); if (!selected_object) return; if (click_kind == DOUBLE_CLICKS) selected_object->addBreakPoint(e->xbutton.x,e->xbutton.y); selected_object->draw_select(); moving_flag = 1; last_mouse_x = e->xbutton.x + pix_hoffset; last_mouse_y = e->xbutton.y + pix_voffset; button2Pressed = 1; /* redraw(); */ return; } } else if (e->xbutton.button == Button3) { if (drawing_edge) { Widget popupMenu = XmCreateSimplePopupMenu(draw_area,"Menu",NULL,0); XtManageChild(XmCreateLabelGadget(popupMenu,"Drawing Edge",NULL,0)); int n = 0; XtSetArg(wargs[n],XmNseparatorType ,XmDOUBLE_LINE); n++; XtManageChild(XmCreateSeparatorGadget(popupMenu,"DrawingEdge",wargs,n)); Widget cancel = XmCreatePushButton(popupMenu,"Cancel",NULL,0); XtManageChild(cancel); XtAddCallback(cancel,XmNactivateCallback, (XtCallbackProc)cancelDrawingEdgeCallback,NULL); XmMenuPosition(popupMenu,(XButtonPressedEvent*) e); XtManageChild(popupMenu); return; } else if (drawing_vertex) { Widget popupMenu = XmCreateSimplePopupMenu(draw_area,"Menu",NULL,0); XtManageChild(XmCreateLabelGadget(popupMenu,"Drawing Vertex",NULL,0)); int n = 0; XtSetArg(wargs[n],XmNseparatorType ,XmDOUBLE_LINE); n++; XtManageChild(XmCreateSeparatorGadget(popupMenu,"DrawingVertex",wargs,n)); Widget cancel = XmCreatePushButton(popupMenu,"Cancel",NULL,0); XtManageChild(cancel); XtAddCallback(cancel,XmNactivateCallback, (XtCallbackProc)cancelDrawingVertexCallback,NULL); XmMenuPosition(popupMenu,(XButtonPressedEvent*) e); XtManageChild(popupMenu); return; } else if (selected_object) selected_object->helpPopupMenu(e,e->xbutton.x,e->xbutton.y); else { Widget popupMenu = XmCreateSimplePopupMenu(draw_area,"Menu",NULL,0); XtManageChild(XmCreateLabelGadget(popupMenu,"General",NULL,0)); int n = 0; XtSetArg(wargs[n],XmNseparatorType ,XmDOUBLE_LINE); n++; XtManageChild(XmCreateSeparatorGadget(popupMenu,"General",wargs,n)); Widget redisp = XmCreatePushButton(popupMenu,"Redisplay",NULL,0); XtManageChild(redisp); Widget reorder=XmCreatePushButton(popupMenu,"Reorder vertices",NULL,0); XtManageChild(reorder); XtAddCallback(redisp,XmNactivateCallback, (XtCallbackProc)redrawCallback,NULL); XtAddCallback(reorder,XmNactivateCallback, (XtCallbackProc)reorderCallback,NULL); XmMenuPosition(popupMenu,(XButtonPressedEvent*) e); XtManageChild(popupMenu); } } } int not_in_drawing_process() { return drawing_edge == NULL && drawing_vertex == NULL; } void track_draw(Widget w,graphics_data* data,XEvent* e) { /* for button 1 and 2*/ int x,y; if (button1Pressed && not_in_drawing_process()) { int unused = 0; scroll_window(e->xmotion.x,e->xmotion.y,unused); return; } if (button2Pressed && not_in_drawing_process()) { /* set new coordinates and redraw(); */ int didit = 0; scroll_window(e->xmotion.x,e->xmotion.y,didit); if (selected_object != NULL && moving_flag && didit == 0) { switch (selected_object->get_selected_flag()) { case SELECT_VERTEX: selected_object->drawRelated(); selected_object->drawSelected(selected_object->get_selected_flag()); break; case SELECT_VERTEX_NAME: selected_object->draw(); selected_object->drawSelected(selected_object->get_selected_flag()); break; case SELECT_EDGE_START_POINT: selected_object->drawRelated(); selected_object->drawSelected(selected_object->get_selected_flag()); break; case SELECT_EDGE_END_POINT: selected_object->drawRelated(); selected_object->drawSelected(selected_object->get_selected_flag()); break; case SELECT_EDGE_INNER_POINT: selected_object->drawRelated(); selected_object->drawSelected(selected_object->get_selected_flag()); break; case SELECT_EDGE_LABEL: selected_object->draw(); selected_object->drawSelected(selected_object->get_selected_flag()); break; case SELECT_EDGE: case NOT_SELECTED: default: break; } } if (selected_object != NULL && moving_flag) { int cur_mouse_x = e->xmotion.x + pix_hoffset; int cur_mouse_y = e->xmotion.y + pix_voffset; int dx = cur_mouse_x - last_mouse_x; int dy = cur_mouse_y - last_mouse_y; last_mouse_x = cur_mouse_x; last_mouse_y = cur_mouse_y; if (dx || dy) check_update_flag(); switch (selected_object->get_selected_flag()) { case SELECT_VERTEX: selected_object->move_vertex(dx,dy); break; case SELECT_VERTEX_NAME: selected_object->move_vertex_name(dx,dy); break; case SELECT_EDGE_START_POINT: selected_object->move_start_point(cur_mouse_x,cur_mouse_y); break; case SELECT_EDGE_END_POINT: selected_object->move_end_point(cur_mouse_x,cur_mouse_y); break; case SELECT_EDGE_INNER_POINT: selected_object->move_inner_point(dx,dy); break; case SELECT_EDGE_LABEL: selected_object->move_edge_name(dx,dy); break; case SELECT_EDGE: case NOT_SELECTED: default: break; } } if (selected_object != NULL && moving_flag && didit == 0) { switch (selected_object->get_selected_flag()) { case SELECT_VERTEX: selected_object->drawRelated(); selected_object->drawSelected(selected_object->get_selected_flag()); break; case SELECT_VERTEX_NAME: selected_object->drawSelected(selected_object->get_selected_flag()); selected_object->draw(); break; case SELECT_EDGE_START_POINT: selected_object->drawRelated(); selected_object->drawSelected(selected_object->get_selected_flag()); break; case SELECT_EDGE_END_POINT: selected_object->drawRelated(); selected_object->drawSelected(selected_object->get_selected_flag()); break; case SELECT_EDGE_INNER_POINT: selected_object->drawRelated(); selected_object->drawSelected(selected_object->get_selected_flag()); break; case SELECT_EDGE_LABEL: selected_object->drawSelected(selected_object->get_selected_flag()); selected_object->draw(); break; case SELECT_EDGE: case NOT_SELECTED: default: break; } } return; } if (drawing_vertex != NULL) { drawing_vertex->xor_draw(); /* scroll window and draw all the figures which have been drawn */ int unused = 0; scroll_window(e->xmotion.x,e->xmotion.y,unused); /* redraw the figure being drawn */ create_vertex_rubber_box(e->xbutton.x,e->xbutton.y,&x,&y); drawing_vertex->set_xy(x,y); drawing_vertex->xor_draw(); return; } if (drawing_edge != NULL) { x = e->xbutton.x; y = e->xbutton.y; /* erase the old drawing line */ drawing_edge->xor_draw_last_segment(); /* scroll window and draw all the figures which have been drawn */ int isItScrolled = 0; scroll_window(e->xmotion.x,e->xmotion.y,isItScrolled); /* xorgc_draw again */ drawing_edge->set_xy(x + pix_hoffset,y + pix_voffset); if (isItScrolled) drawing_edge->xor_draw(); else drawing_edge->xor_draw_last_segment(); } return; } void move_objects(Widget w,graphics_data* data,XEvent* e) { if (!button2Pressed) return; if (drawing_edge != NULL) return; if (drawing_edge != NULL) return; if (selected_object == NULL) return; /* implement move here */ } void release_draw(Widget w,graphics_data* data,XEvent* e) { if (e->xbutton.button == Button1) { button1Pressed = 0; if (data->choice->sel || data->choice->trash) { XUngrabPointer(XtDisplay(w),0); } } if (e->xbutton.button == Button2) { button2Pressed = 0; if (moving_flag) { moving_flag = 0; /* redraw objects */ redraw(); } } } void GraphicsObject::addBreakPoint(int cx,int cy) { } void EdgeObject::addBreakPoint(int cx,int cy) { if (SELECT_EDGE == this->get_selected_flag()) { if (points) points->addBreakPoint(cx,cy); this->set_selected_flag(SELECT_EDGE_INNER_POINT); } check_update_flag(); } void PointObjectList::addBreakPoint(int cx,int cy) { if (!this->get_next()) return; double x0 = this->get_elm()->get_x() - pix_hoffset; double y0 = this->get_elm()->get_y() - pix_voffset; double x1 = this->get_next()->get_elm()->get_x() - pix_hoffset; double y1 = this->get_next()->get_elm()->get_y() - pix_voffset; double x2 = cx; double y2 = cy; x1 = x1 - x0; y1 = y1 - y0; x2 = x2 - x0; y2 = y2 - y0; x0 = y0 = 0; double cos_alpha = x1*x2 + y1*y2; if (cos_alpha < 0) { if (this->get_next()) this->get_next()->addBreakPoint(cx,cy); return; } x0 = this->get_next()->get_elm()->get_x() - pix_hoffset; y0 = this->get_next()->get_elm()->get_y() - pix_voffset; x1 = this->get_elm()->get_x() - pix_hoffset; y1 = this->get_elm()->get_y() - pix_voffset; x2 = cx; y2 = cy; x1 = x1 - x0; y1 = y1 - y0; x2 = x2 - x0; y2 = y2 - y0; x0 = y0 = 0; cos_alpha = x1*x2 + y1*y2; if (cos_alpha < 0) { if (this->get_next()) this->get_next()->addBreakPoint(cx,cy); return; } if (y0 == y1) { if (abs(y2 - y0) < 4) { PointObjectList *pl = new PointObjectList(); PointObject *pt = new PointObject(); pt->set_x(cx + pix_hoffset); pt->set_y(this->get_next()->get_elm()->get_y()); pt->set_selected_flag(SELECT_EDGE_INNER_POINT); pl->set_elm(pt); pl->set_next(this->get_next()); pl->set_prev(this); this->get_next()->set_prev(pl); this->set_next(pl); return; } else { if (this->get_next()) this->get_next()->addBreakPoint(cx,cy); return; } } if (x0 == x1) { if (abs(x2 - x0) < 4) { PointObjectList *pl = new PointObjectList(); PointObject *pt = new PointObject(); pt->set_x(this->get_next()->get_elm()->get_x()); pt->set_y(cy + pix_voffset); pt->set_selected_flag(SELECT_EDGE_INNER_POINT); pl->set_elm(pt); pl->set_next(this->get_next()); pl->set_prev(this); this->get_next()->set_prev(pl); this->set_next(pl); return; } else { if (this->get_next()) this->get_next()->addBreakPoint(cx,cy); return; } } double sin_alpha = abs(x1*y2 - x2*y1)/ (sqrt(x1*x1 + y1*y1)*sqrt(x2*x2 + y2*y2)); x0 = this->get_next()->get_elm()->get_x() - pix_hoffset; y0 = this->get_next()->get_elm()->get_y() - pix_voffset; x1 = this->get_elm()->get_x() - pix_hoffset; y1 = this->get_elm()->get_y() - pix_voffset; x2 = cx; y2 = cy; if ((sqrt((x2-x0)*(x2-x0) + (y2-y0)*(y2-y0)) * sin_alpha) < 6) { double d = (y1 - y0)/(x1 - x0); double x = (d*d*x0 - d*y0 + x2 + d*y2)/(d*d + 1); double y = d*(x - x0) + y0; PointObjectList *pl = new PointObjectList(); PointObject *pt = new PointObject(); pt->set_x(((int)x) + pix_hoffset); pt->set_y(((int)y) + pix_voffset); pt->set_selected_flag(SELECT_EDGE_INNER_POINT); pl->set_elm(pt); pl->set_next(this->get_next()); pl->set_prev(this); this->get_next()->set_prev(pl); this->set_next(pl); return; } else { if (this->get_next()) this->get_next()->addBreakPoint(cx,cy); return; } }