editview.cc
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:42k
源码类别:

通讯编程

开发平台:

Visual C++

  1. /*
  2.  * Copyright (C) 1997 by the University of Southern California
  3.  *
  4.  * This program is free software; you can redistribute it and/or
  5.  * modify it under the terms of the GNU General Public License,
  6.  * version 2, as published by the Free Software Foundation.
  7.  *
  8.  * This program is distributed in the hope that it will be useful,
  9.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  11.  * GNU General Public License for more details.
  12.  *
  13.  * You should have received a copy of the GNU General Public License along
  14.  * with this program; if not, write to the Free Software Foundation, Inc.,
  15.  * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
  16.  *
  17.  *
  18.  * The copyright of this module includes the following
  19.  * linking-with-specific-other-licenses addition:
  20.  *
  21.  * In addition, as a special exception, the copyright holders of
  22.  * this module give you permission to combine (via static or
  23.  * dynamic linking) this module with free software programs or
  24.  * libraries that are released under the GNU LGPL and with code
  25.  * included in the standard release of ns-2 under the Apache 2.0
  26.  * license or under otherwise-compatible licenses with advertising
  27.  * requirements (or modified versions of such code, with unchanged
  28.  * license).  You may copy and distribute such a system following the
  29.  * terms of the GNU GPL for this module and the licenses of the
  30.  * other code concerned, provided that you include the source code of
  31.  * that other code when and as the GNU GPL requires distribution of
  32.  * source code.
  33.  *
  34.  * Note that people who make modified versions of this module
  35.  * are not obligated to grant this special exception for their
  36.  * modified versions; it is their choice whether to do so.  The GNU
  37.  * General Public License gives permission to release a modified
  38.  * version without this exception; this exception also makes it
  39.  * possible to release a modified version which carries forward this
  40.  * exception.
  41.  *
  42.  * $Header: /cvsroot/nsnam/nam-1/editview.cc,v 1.36 2007/02/12 07:08:43 tom_henderson Exp $
  43.  */
  44. #include <stdlib.h>
  45. #ifdef WIN32
  46. #include <windows.h>
  47. #endif
  48. #include <ctype.h>
  49. #include <math.h>
  50. #include "view.h"
  51. #include "bbox.h"
  52. #include "netmodel.h"
  53. #include "editview.h"
  54. #include "tclcl.h"
  55. #include "paint.h"
  56. #include "tag.h"
  57. #include "node.h"
  58. #include "edge.h"
  59. #include "agent.h"
  60. void EditView::DeleteCmdProc(ClientData cd)
  61. {
  62. EditView *ev = (EditView *)cd;
  63. if (ev->tk_ != NULL) {
  64. Tk_DestroyWindow(ev->tk_);
  65. }
  66. }
  67. //----------------------------------------------------------------------
  68. //----------------------------------------------------------------------
  69. EditView::EditView(const char *name, NetModel* m) 
  70.         : NetView(name), defTag_(NULL)
  71. {
  72. if (tk_!=0) {
  73. Tcl& tcl = Tcl::instance();
  74. cmd_ = Tcl_CreateCommand(tcl.interp(), Tk_PathName(tk_), 
  75.  command, 
  76.  (ClientData)this, DeleteCmdProc);
  77. }
  78. char str[256];
  79. model_ = m;
  80. sprintf(str, "def%-u", (long)this);
  81. defTag_ = new Tag(str);
  82. model_->add_tag(defTag_);
  83. editing_stage_ = NONE;
  84. }
  85. //----------------------------------------------------------------------
  86. // EditView::EditView(const char *name, NetModel* m,
  87. //                    int width, int height)
  88. //----------------------------------------------------------------------
  89. EditView::EditView(const char *name, NetModel* m, int width, int height)
  90.   : NetView(name, SQUARE, width, height), defTag_(NULL) {
  91. char str[256];
  92. if (tk_!=0) {
  93. Tcl& tcl = Tcl::instance();
  94. cmd_ = Tcl_CreateCommand(tcl.interp(), Tk_PathName(tk_),
  95.                          command, (ClientData) this,
  96.                          DeleteCmdProc);
  97. }
  98. model_ = m;
  99. sprintf(str, "def%-u", (long)this);
  100. defTag_ = new Tag(name);
  101. model_->add_tag(defTag_);
  102. editing_stage_ = NONE;
  103. }
  104. EditView::~EditView()
  105. {
  106. model_->remove_view(this);
  107. if (defTag_ != NULL) {
  108. model_->delete_tag(defTag_->name());
  109. delete defTag_;
  110. defTag_ = NULL;
  111. }
  112. // Delete Tcl command created
  113. //   Tcl& tcl = Tcl::instance();
  114. //   Tcl_DeleteCommandFromToken(tcl.interp(), cmd_);
  115. }
  116. //----------------------------------------------------------------------
  117. // int 
  118. // EditView::command(ClientData cd, Tcl_Interp* tcl,
  119. //                   int argc, char **argv)
  120. //    Parse Tcl command interface
  121. //      - setPoint, addNode, addLink addAgent, deleteObject, etc...
  122. //----------------------------------------------------------------------
  123. int EditView::command(ClientData cd, Tcl_Interp* tcl,
  124.                       int argc, CONST84 char **argv) {
  125.   EditorNetModel * editor_net_model;
  126.   Node * node, * source, * destination;
  127.   Edge * edge;
  128.   Agent * source_agent, * destination_agent;
  129.   TrafficSource * traffic_source;
  130.   LossModel * loss_model;
  131.   //double world_x, world_y;
  132.   
  133.   if (argc < 2) {
  134.     Tcl_AppendResult(tcl, """, argv[0], "": arg mismatch", 0);
  135.     return (TCL_ERROR);
  136.   }
  137.   char c = argv[1][0];
  138.   int length = strlen(argv[1]);
  139.   EditView * ev = (EditView *) cd;
  140.   editor_net_model = (EditorNetModel *) ev->model_;
  141.   float cx, cy;
  142.   int flag;
  143.   // Following implements several useful interactive commands of 
  144.   // Tk's canvas. Their syntax and semantics are kept as close to
  145.   // those of Tk canvas as possible.
  146.   if ((c == 'd') && (strncmp(argv[1], "draw", length) == 0)) {
  147.     // Redraw seen at time = argv[2]
  148.     ev->draw(strtod(argv[2],NULL));
  149.     return TCL_OK;
  150.   } else if ((c == 'c') && (strncmp(argv[1], "close", length) == 0)) {
  151.     ev->destroy();
  152.     return TCL_OK;
  153.   } else if ((c == 'd') &&
  154.              (strncmp(argv[1], "dctag", length) == 0)) {
  155.     /*
  156.      * <view> dctag
  157.      * 
  158.      * Delete the current selection, start all over.
  159.      */
  160.     if (ev->defTag_ != NULL)
  161.       ev->defTag_->remove();
  162.     ev->draw();
  163.     return (TCL_OK);
  164.   } else if ((c == 's') &&
  165.              (strncmp(argv[1], "setPoint", length) == 0)) {
  166.     /*
  167.      * <view> setPoint x y addFlag
  168.      * 
  169.      * Select the object (if any) under point (x, y). If no such
  170.      * object, set current point to (x, y)
  171.      */
  172.     if (argc != 5) {
  173.       Tcl_AppendResult(tcl, "wrong # args: should be "",
  174.                             argv[0], " setPoint x y addFlag"", 
  175.                             (char *)NULL);
  176.       return (TCL_ERROR);
  177.     }
  178.     cx = strtod(argv[2], NULL);
  179.     cy = strtod(argv[3], NULL);
  180.     flag = strtol(argv[4], NULL, 10);
  181.     return ev->cmdSetPoint(cx, cy, flag);
  182.   } else if ((c == 'd') && (strncmp(argv[1], "deleteObject", length) == 0)) { 
  183.     cx = strtod(argv[2], NULL);
  184.     cy = strtod(argv[3], NULL);
  185.     return  ev->cmdDeleteObj(cx, cy);
  186.   } else if ((c == 'm') && (strncmp(argv[1], "moveTo", length) == 0)) { 
  187.     /*
  188.      * <view> moveto x y
  189.      * 
  190.      * Move the current selected object (if any) or the 
  191.      * rubber band to point (x, y)
  192.      */
  193.     if (argc != 4) {
  194.       Tcl_AppendResult(tcl, "wrong # args: should be "",
  195.                              argv[0],
  196.                             " moveTo x y"", (char *)NULL);
  197.       return (TCL_ERROR);
  198.     }
  199.     cx = strtod(argv[2], NULL);
  200.     cy = strtod(argv[3], NULL);
  201.     return ev->cmdMoveTo(cx, cy);
  202.   } else if ((c == 'r') && (strncmp(argv[1], "releasePoint", length) == 0)) {
  203.     /*
  204.      * <view> releasePoint x y
  205.      * 
  206.      * If any object is selected, set the object's
  207.      * position to point (x,y); otherwise set the rubber
  208.      * band rectangle and select all the objects in that
  209.      * rectangle Note: we need a default tag for the
  210.      * selection in rubber band.  
  211.      */
  212.     if (argc != 4) {
  213.       Tcl_AppendResult(tcl, "wrong # args: should be "",
  214.            argv[0],
  215.            " releasePoint x y"", (char *)NULL);
  216.       return (TCL_ERROR);
  217.     }
  218.     cx = strtod(argv[2], NULL);
  219.     cy = strtod(argv[3], NULL);
  220.     return ev->cmdReleasePoint(cx, cy);
  221.   } else if ((c == 's') && (strncmp(argv[1], "setNodeProperty", length) == 0)) {
  222.     // <view> setNodeProperty nodeid nodepropertyvalue properyname
  223.     int nodeid = atoi(argv[2]);
  224.     return ev->cmdsetNodeProperty(nodeid, argv[3], argv[4]);
  225.   } else if ((c == 's') && (strncmp(argv[1], "setAgentProperty", length) == 0)) {
  226.      // <view> setAgentProperty nodeid nodepropertyvalue properyname
  227.     int agentid = atoi(argv[2]);
  228.     return ev->cmdsetAgentProperty(agentid, argv[3], argv[4]);
  229.   } else if ((c == 's') && (strncmp(argv[1], "setLinkProperty", length) == 0)) {
  230.     // <view> setLinkProperty sid did propertyvalue properyname
  231.     int source_id = atoi(argv[2]);
  232.     int destination_id = atoi(argv[3]);
  233.     return ev->cmdsetLinkProperty(source_id, destination_id,
  234.                                   argv[4], argv[5]);
  235.   } else if ((c == 's') &&
  236.              (strncmp(argv[1], "setQueueHandleProperty", length) == 0)) {
  237.     // Called by the following code in Editor.tcl
  238.     // ------------------------------------------------------------
  239.     // $editor_view_ setQueueHandleProperty $source $destination 
  240.     //                                      $property_value 
  241.     //                                      $property_variable
  242.     //
  243.     //  - argv[2] = source
  244.     //  - argv[3] = destination
  245.     //  - argv[4] = value
  246.     //  - argv[5] = variable name
  247.     editor_net_model->setQueueHandleProperty(atoi(argv[2]), atoi(argv[3]),
  248.                                               argv[4], argv[5]);
  249.     ev->draw();
  250.     return TCL_OK;
  251.   } else if ((c == 's') &&
  252.              (strncmp(argv[1], "setTrafficSourceProperty", length) == 0)) {
  253.     // <view> setTrafficSourceProperty id propertyvalue propertyname
  254.     int id = atoi(argv[2]);
  255.     const char * value = argv[3];
  256.     const char * variable_name = argv[4];
  257.     return ev->cmdsetTrafficSourceProperty(id, value, variable_name);
  258.  
  259.   } else if ((c == 's') &&
  260.              (strncmp(argv[1], "setLossModelProperty", length) == 0)) {
  261.     // <view> setLossModelProperty id propertyvalue propertyname
  262.     int id = atoi(argv[2]);
  263.     const char * value = argv[3];
  264.     const char * variable_name = argv[4];
  265.     return ev->cmdsetLossModelProperty(id, value, variable_name);
  266.   } else if ((c == 'a') && (strncmp(argv[1], "addNode", length) == 0)) {
  267.     // <view> addNode x y
  268.     //   - add a new Node under current (x,y) with default size
  269.     cx = strtod(argv[2], NULL);
  270.     cy = strtod(argv[3], NULL);
  271.     return ev->cmdaddNode(cx, cy);
  272.   } else if ((c == 'i') && (strncmp(argv[1], "importNode", length) == 0)) {
  273.     // Used when reading a nam editor file to add a node created in tcl
  274.     // to this editview and its editornetmodel
  275.     node = (Node *) TclObject::lookup(argv[2]);
  276.     //world_x = atof(argv[3]);
  277.     //world_y = atof(argv[4]);
  278.     if (node) {
  279.       if (editor_net_model->addNode(node)) {
  280.      //   node->place(world_x, world_y);
  281.      //   ev->draw();
  282.         return TCL_OK;
  283.       }
  284.     }
  285.     fprintf(stderr, "Error creating node.n");
  286.     return TCL_ERROR;
  287.   } else if ((c == 'a') && (strncmp(argv[1], "attachNodes", length) == 0)) {
  288.     // <view> linkNodes source_id destination_id
  289.     //   - link 2 existing nodes to each other
  290.     edge = (Edge *) TclObject::lookup(argv[2]);
  291.     source = (Node *) TclObject::lookup(argv[3]);
  292.     destination = (Node *) TclObject::lookup(argv[4]);
  293.     edge->attachNodes(source, destination);
  294.     editor_net_model->addEdge(edge);
  295.     ev->draw();  
  296.     return TCL_OK;
  297.   } else if ((c == 'a') && (strncmp(argv[1], "addLink", length) == 0)) {
  298.     //  <view> addLink x y 
  299.     //    - add a new Link if its start AND end point is inside of 
  300.     cx = strtod(argv[2], NULL);
  301.     cy = strtod(argv[3], NULL);
  302.     return ev->cmdaddLink(cx, cy);
  303.   } else if ((c == 'a') && (strncmp(argv[1], "addQueueHandle", length) == 0)) {
  304.     //  <view> addQueueHandle edge queue_type
  305.     edge = (Edge *) TclObject::lookup(argv[2]);
  306.     if (edge) {
  307.       editor_net_model->addQueueHandle(edge, argv[3]);
  308.     }
  309.     return TCL_OK;
  310.     
  311.   
  312.   // --------------- Agent -----------------
  313.   } else if ((c == 'a') && (strncmp(argv[1], "addAgent", length) == 0)) {
  314.     // <view> addAgent x y agent
  315.     //   - add a new agent
  316.     cx = strtod(argv[2], NULL);
  317.     cy = strtod(argv[3], NULL);
  318.     const char * agent_name = argv[4];
  319.     return ev->cmdaddAgent(cx, cy, agent_name);
  320.   } else if ((c == 'i') && (strncmp(argv[1], "importAgent", length) == 0)) {
  321.     source_agent = (Agent *) TclObject::lookup(argv[2]);
  322.     node = (Node *) TclObject::lookup(argv[3]);
  323.     return editor_net_model->addAgent(source_agent, node);
  324.   } else if ((c == 'l') && (strncmp(argv[1], "linkAgents", length) == 0)) {
  325.     // <view> linkAgents source_id destination_id
  326.     //   - link 2 existing agents to each other
  327.     source_agent = (Agent *) TclObject::lookup(argv[2]);
  328.     destination_agent = (Agent *) TclObject::lookup(argv[3]);
  329.     return editor_net_model->addAgentLink(source_agent, destination_agent);
  330.   } else if ((c == 's') && (strncmp(argv[1], "showAgentLink", length) == 0)) {
  331.     cx = strtod(argv[2], NULL);
  332.     cy = strtod(argv[3], NULL);
  333.     return ev->showAgentLink(cx, cy);
  334.   } else if ((c == 'h') && (strncmp(argv[1], "hideAgentLinks", length) == 0)) {
  335.     editor_net_model->hideAgentLinks();
  336.     ev->draw();
  337.     return TCL_OK;
  338.  
  339.   // --------------- Traffic Source -----------------
  340.   } else if ((c == 'a') &&
  341.              (strncmp(argv[1], "addTrafficSource", length) == 0)) {
  342.     // <view> addTrafficSource x y trafficsource_type
  343.     //   -  add a new TrafficSource
  344.     cx = strtod(argv[2], NULL);
  345.     cy = strtod(argv[3], NULL);
  346.     // argv[4] is the name of the traffic source
  347.     return ev->cmdaddTrafficSource(cx, cy, argv[4]);
  348.   } else if ((c == 'a') &&
  349.              (strncmp(argv[1], "attachTrafficSource", length) == 0)) {
  350.     traffic_source = (TrafficSource *) TclObject::lookup(argv[2]);
  351.     source_agent = (Agent *) TclObject::lookup(argv[3]);
  352.     return editor_net_model->addTrafficSource(traffic_source, source_agent);
  353.   // ----------- Loss Models ----------------
  354.   } else if ((c == 'a') &&
  355.              (strncmp(argv[1], "addLossModel", length) == 0)) {
  356.     // <view> addLossModel x y lossmodel
  357.     cx = strtod(argv[2], NULL);
  358.     cy = strtod(argv[3], NULL);
  359.     // argv[4] is the type of the loss model to add
  360.     return ev->cmdaddLossModel(cx, cy, argv[4]);
  361.   } else if ((c == 'a') &&
  362.              (strncmp(argv[1], "attachLossModel", length) == 0)) {
  363.     loss_model = (LossModel *) TclObject::lookup(argv[2]);
  364.     source = (Node *) TclObject::lookup(argv[3]);
  365.     destination = (Node *) TclObject::lookup(argv[4]);
  366.     edge = source->find_edge(destination->number());
  367.     return editor_net_model->addLossModel(loss_model, edge);
  368.   
  369.   // ----------- Object and Object Properties ----------------
  370.   } else if ((c == 'g') &&
  371.              (strncmp(argv[1], "getObjectInformation", length) == 0)) {
  372.  
  373.     // <view> getObject x y
  374.     //   - return object under current point
  375.     cx = strtod(argv[2], NULL);
  376.     cy = strtod(argv[3], NULL);
  377.     return ev->cmdgetObjectInformation(cx, cy);
  378.   } else if ((c == 'g') &&
  379.              (strncmp(argv[1], "getObjectProperty", length) == 0)) {
  380.     // <view> getObjectPropert x y [type]
  381.     //  - return properties for object under current point
  382.     //  - if type is passed in then pass that to object
  383.     cx = strtod(argv[2], NULL);
  384.     cy = strtod(argv[3], NULL);
  385.     if (argc == 5) {
  386.       return ev->cmdgetObjectProperties(cx, cy, argv[4]);
  387.     } else {
  388.       return ev->cmdgetObjProperty(cx, cy);
  389.     }
  390.   } else if ((c == 'v') && (strncmp(argv[1], "view_mode", length)==0)) {
  391.     /*
  392.      * <view> view_mode
  393.      * 
  394.      * clear defTag_ and change to view mode
  395.      */
  396.     ev->view_mode();
  397.     return TCL_OK;
  398.   }
  399.   return (NetView::command(cd, tcl, argc, argv));
  400. }
  401. int EditView::cmdsetNodeProperty(int id, const char * value, const char * variable)
  402. {
  403. EditorNetModel* emodel_ = (EditorNetModel *) model_;
  404.   // goto enetmodel.cc
  405. emodel_->setNodeProperty(id, value, variable);
  406. // EditType oldt_;
  407. // oldt_ = editing_stage_;
  408. // editing_stage_ = END_OBJECT;
  409. draw();
  410. // editing_stage_ = NONE;
  411. // model_->update(model_->now());
  412. // editing_stage_ = oldt_;
  413. return(TCL_OK);
  414. }
  415. int EditView::cmdsetAgentProperty(int id, const char * value, const char * variable) {
  416. EditorNetModel* emodel_ = (EditorNetModel *) model_;
  417. emodel_->setAgentProperty(id, value ,variable);
  418. draw();  
  419. return(TCL_OK);
  420. }
  421. int EditView::cmdsetLinkProperty(int sid, int did,
  422.                                  const char * value, const char * variable) {
  423.   EditorNetModel * emodel_ = (EditorNetModel *) model_;
  424.   emodel_->setLinkProperty(sid, did, value, variable);
  425.   draw();
  426.   return(TCL_OK);
  427. }
  428. //----------------------------------------------------------------------
  429. // int
  430. // EditView::cmdsetTrafficSourceProperty(int sid, int did, const char *pv, int pn)
  431. //----------------------------------------------------------------------
  432. int
  433. EditView::cmdsetTrafficSourceProperty(int id, const char * value, const char * variable) {
  434.   EditorNetModel* emodel_ = (EditorNetModel *) model_;
  435.   emodel_->setTrafficSourceProperty(id, value, variable);
  436.   draw();
  437.   return(TCL_OK);
  438. }        
  439. //----------------------------------------------------------------------
  440. // int
  441. // EditView::cmdsetLossModelProperty(int id, char * value, char * variable) 
  442. //----------------------------------------------------------------------
  443. int
  444. EditView::cmdsetLossModelProperty(int id, const char * value, const char * variable) {
  445.   EditorNetModel* emodel_ = (EditorNetModel *) model_;
  446.   emodel_->setLossModelProperty(id, value, variable);
  447.   draw();
  448.   return(TCL_OK);
  449. }        
  450. //----------------------------------------------------------------------
  451. // int 
  452. // EditView::cmdgetObjProperty(float cx, float cy)
  453. //   - get properties for a selected object
  454. //----------------------------------------------------------------------
  455. int 
  456. EditView::cmdgetObjProperty(float cx, float cy) { 
  457. Animation *p;
  458. Tcl& tcl = Tcl::instance();
  459. // matrix_ comes from class View (view.h)
  460. //  - imap is the inverse mapping
  461. //    (i.e from screen to world coordinate systems)
  462. matrix_.imap(cx, cy);
  463. // Finds the object which contains the coordinate (cx, cy)
  464. p = model_->inside(cx, cy);
  465. if (p == NULL) {
  466.    tcl.resultf("NONE");
  467. } else {
  468.    tcl.resultf("%s",p->property());
  469.   }
  470. return(TCL_OK);
  471. }
  472. //----------------------------------------------------------------------
  473. // int 
  474. // EditView::cmdgetObjectProperties(float cx, float cy, char * type)
  475. //   - get properties for a selected object and the specific 
  476. //     type within that object
  477. //----------------------------------------------------------------------
  478. int 
  479. EditView::cmdgetObjectProperties(float cx, float cy, const char * type) { 
  480. Animation * animation_object;
  481. Tcl& tcl = Tcl::instance();
  482. // matrix_ comes from class View (view)
  483. //  - imap is the inverse mapping
  484. //    (i.e from screen to world coordinate systems)
  485. matrix_.imap(cx, cy);
  486. // Finds the object which contains the coordinate (cx, cy)
  487. animation_object = model_->inside(cx, cy);
  488. if (animation_object == NULL) {
  489.    tcl.resultf("NONE");
  490. } else {
  491.    tcl.resultf("%s",animation_object->getProperties(type));
  492. }
  493. return(TCL_OK);
  494. }
  495. //----------------------------------------------------------------------
  496. //----------------------------------------------------------------------
  497. int EditView::cmdgetObjectInformation(float cx, float cy) { 
  498. Tcl& tcl = Tcl::instance();
  499. matrix_.imap(cx, cy);
  500. Animation *p = model_->inside(cx, cy);
  501. if (p == NULL) {
  502. tcl.resultf("NONE");
  503. } else {
  504. tcl.resultf("%s",p->info());
  505. }
  506. return(TCL_OK);
  507. }
  508. //----------------------------------------------------------------------
  509. // int
  510. // EditView::cmdaddLink(float cx, float cy)
  511. //   - Note: all cx_ and cy_ below are in *window* coordinates
  512. //----------------------------------------------------------------------
  513. int
  514. EditView::cmdaddLink(float cx, float cy) {
  515.   Animation * p;
  516.   static Animation * old_p;
  517.   EditorNetModel* emodel_ = (EditorNetModel *) model_;
  518.   cx_ = cx;
  519.   cy_ = cy;
  520.   matrix_.imap(cx, cy);
  521.   // Do we have a node  on current point ?
  522.   p = model_->inside(cx, cy);
  523.   if (p == NULL) {
  524.     defTag_->remove();
  525.     if (editing_stage_ == START_LINK) {
  526.        editing_stage_ = NONE;
  527.       draw();
  528.     }
  529.     return (TCL_OK);
  530.   }
  531.   if (p->classid() == ClassNodeID) {
  532.     if (editing_stage_ != START_LINK) {
  533.       old_p = p;                /* remember the orig node */
  534.       startSetObject(p, cx_, cy_);
  535.       editing_stage_ = START_LINK;
  536.      } else if ((old_p == p)||(old_p->classid()!=ClassNodeID)) {
  537.        editing_stage_ = NONE;
  538.        draw();
  539.        // to support making link by click-&-click 
  540.        editing_stage_ = START_LINK; 
  541.      } else {
  542.        // add a new link b/w the two nodes
  543.        startSetObject(p, cx_, cy_);
  544.        Node *src, *dst;
  545.        src = (Node *)old_p;
  546.        dst = (Node *)p;
  547.        emodel_->addLink(src, dst);
  548.        editing_stage_ = END_OBJECT;
  549.      
  550.        // Erase old positions
  551.        defTag_->draw(this, model_->now());
  552.        // At least we should redo scale estimation and
  553.        // place everything
  554.        defTag_->move(this, rb_.xmax - oldx_, rb_.ymax - oldy_);
  555.        model_->recalc();
  556.        model_->render(this);
  557.        defTag_->remove();
  558.        editing_stage_ = NONE;
  559.        draw();
  560.        editing_stage_ = NONE;
  561.      }
  562.   } else if (p->classid() == ClassAgentID) {
  563.     if (editing_stage_ != START_LINK) {
  564.       old_p = p;
  565.       startSetObject(p, cx_, cy_);
  566.       editing_stage_ = START_LINK;
  567.     } else if ((old_p == p)||(old_p->classid()!= ClassAgentID)) {
  568.       editing_stage_ = NONE;
  569.       draw();
  570.       // to support making agent-link by click-&-click
  571.       editing_stage_ = START_LINK;
  572.     } else {
  573.       startSetObject(p, cx_, cy_);
  574.       Agent *src_agent, *dst_agent;
  575.       src_agent = (Agent *)old_p;
  576.       dst_agent = (Agent *)p;
  577.       emodel_->addAgentLink(src_agent, dst_agent);
  578.       editing_stage_ = END_OBJECT;
  579.       defTag_->draw(this, model_->now());
  580.       defTag_->move(this, rb_.xmax - oldx_, rb_.ymax - oldy_);
  581.       model_->recalc();
  582.       model_->render(this);
  583.       defTag_->remove();
  584.       editing_stage_ = NONE;
  585.       draw();
  586.     }
  587.   } else {
  588.     editing_stage_ = NONE;
  589.   }
  590.   return(TCL_OK);
  591. }
  592. //----------------------------------------------------------------------
  593. // int 
  594. // EditView::cmdaddAgent(float cx, float cy, char* agent)
  595. //----------------------------------------------------------------------
  596. int EditView::cmdaddAgent(float cx, float cy, const char* agent) {
  597.   Animation * p;
  598.   Node * src;
  599.   EditorNetModel* emodel_ = (EditorNetModel *)model_;
  600.   // Switch from screen coordinates to world coordinates
  601.   matrix_.imap(cx, cy);
  602.   // Do we have a node on the clicked point ?
  603.   p = model_->inside(cx, cy);
  604.   if (p == NULL) {
  605.     defTag_->remove();
  606.     return (TCL_OK);
  607.   } 
  608.   if (p->classid() == ClassNodeID) {
  609.     // Yes, we have a node to which we can add the agent
  610.     src = (Node *) p;
  611.     // goto EditorNetModel::addAgent(...) in enetmodel.cc
  612.     emodel_->addAgent(src, agent, cx, cy);
  613.     draw();
  614.   } else {
  615.     return (TCL_OK);
  616.   }
  617.   return(TCL_OK);
  618. }
  619. //----------------------------------------------------------------------
  620. // int EditView::showAgentLink(float cx, float cy)
  621. //----------------------------------------------------------------------
  622. int EditView::showAgentLink(float cx, float cy) {
  623. Animation * animation;
  624. Agent * agent;
  625. // Change from screen coordinates to worl coordinates
  626. matrix_.imap(cx, cy);
  627. // Get the clicked on animation object.
  628. animation = model_->inside(cx, cy);
  629. if (animation != NULL && animation->classid() == ClassAgentID) {
  630. agent = (Agent *) animation;
  631. agent->showLink();
  632. draw();
  633. }
  634. return(TCL_OK);
  635. }
  636. //----------------------------------------------------------------------
  637. // int 
  638. // EditView::cmdaddNode(float cx, float cy)
  639. //   Note: all cx_ and cy_ below are in *window* coordinates
  640. //----------------------------------------------------------------------
  641. int EditView::cmdaddNode(float cx, float cy) {
  642.   Animation * animation_object;
  643.   EditorNetModel* emodel_ = (EditorNetModel *)model_;
  644.   // Convert screen coordinates to world coordinates
  645.   matrix_.imap(cx, cy);
  646.   // Check to see if an object already exists on the click point
  647.   animation_object = model_->inside(cx,cy);
  648.   if (animation_object == NULL) {
  649.     defTag_->remove();
  650.     emodel_->addNode(cx, cy);
  651.     draw();
  652.   } 
  653.   return(TCL_OK);
  654. }
  655. //----------------------------------------------------------------------
  656. // int
  657. // EditView::cmdDeleteObj(float cx, float cy)
  658. //----------------------------------------------------------------------
  659. int
  660. EditView::cmdDeleteObj(float cx, float cy) {
  661.   Animation * p;  // I don't know why p was chosen for the varible name
  662.                   // Just to confuse other programmers, I guess
  663.   
  664.   // First of all, clear the old point 
  665.   cx_ = cx;
  666.   cy_ = cy;
  667.                 
  668.   // Do we have an animation object on the clicked point?
  669.   matrix_.imap(cx, cy);
  670.   p = model_->inside(cx, cy);
  671.   if (p == NULL) {
  672.     defTag_->remove();
  673.     return (TCL_OK);
  674.   }       
  675.   
  676.   // If object is already selected unselect it
  677.   if (p->isTagged()) {
  678.     if (p->numTag() > 1) {
  679.       fprintf(stderr, "Error: More than one tag for an object %d!n",
  680.                        p->id());
  681.       p = NULL;
  682.     } else {
  683.       p = p->getLastTag();
  684.     }
  685.   }
  686.   // Only nodes, links, agents, traffic sources and
  687.   // loss models can be deleted
  688.   if ((p->classid() != ClassNodeID) &&
  689.       (p->classid() != ClassEdgeID) &&
  690.       (p->classid() != ClassAgentID) &&
  691.       (p->classid() != ClassTrafficSourceID) &&
  692.       (p->classid() != ClassLossModelID)) {
  693.     p = NULL;
  694.   }
  695.   if (p == NULL) {
  696.     defTag_->remove();
  697.   } else {
  698.     if (p->classid() == ClassNodeID) {
  699.       Node * n = (Node *) p;
  700.       EditorNetModel * emodel_ = (EditorNetModel *) model_;
  701.       emodel_->removeNode(n);
  702.       draw();
  703.     } 
  704.     if (p->classid() == ClassEdgeID) {
  705.       Edge * e = (Edge *) p;
  706.       EditorNetModel * emodel_ = (EditorNetModel *) model_;
  707.       emodel_->removeLink(e);
  708.       draw();
  709.     } 
  710.     if (p->classid() == ClassAgentID) {
  711.       Agent * a = (Agent *) p;
  712.       EditorNetModel* emodel_ = (EditorNetModel *) model_;
  713.       emodel_->removeAgent(a);
  714.       draw();
  715.     }
  716.     if (p->classid() == ClassTrafficSourceID) {
  717.       TrafficSource * ts = (TrafficSource *) p;
  718.       EditorNetModel* emodel_ = (EditorNetModel *) model_;
  719.       emodel_->removeTrafficSource(ts);
  720.       draw();
  721.     }
  722.     if (p->classid() == ClassLossModelID) {
  723.       LossModel * lossmodel = (LossModel *) p;
  724.       EditorNetModel* emodel_ = (EditorNetModel *) model_;
  725.       emodel_->removeLossModel(lossmodel);
  726.       draw();
  727.     }
  728.   }
  729.   return (TCL_OK);
  730. }
  731. //----------------------------------------------------------------------
  732. // int 
  733. // EditView::cmdaddTrafficSource(float cx, float cy, char * type)
  734. //----------------------------------------------------------------------
  735. int
  736. EditView::cmdaddTrafficSource(float cx, float cy, const char * type) {
  737.   Animation * object;
  738.   Agent * agent;
  739.   EditorNetModel* emodel_ = (EditorNetModel *)model_;
  740.   // Switch from screen coordinates to world coordinates
  741.   matrix_.imap(cx, cy);
  742.   // Do we have an agent on the clicked point ?
  743.   object = model_->inside(cx, cy);
  744.   if (object == NULL) {
  745.     defTag_->remove();
  746.     return (TCL_OK);
  747.   } 
  748.   if (object->classid() == ClassAgentID) {
  749.     // Yes, we have a node to which we can add the agent
  750.     agent = (Agent *) object;
  751.     // goto EditorNetModel::addTrafficSource(...) in enetmodel.cc
  752.     emodel_->addTrafficSource(agent, type, cx, cy);
  753.     draw();
  754.   } else {
  755.     return (TCL_OK);
  756.   }
  757.   return(TCL_OK);
  758. }
  759. //----------------------------------------------------------------------
  760. // int 
  761. // EditView::cmdaddLossModel(float cx, float cy, char * type)
  762. //----------------------------------------------------------------------
  763. int
  764. EditView::cmdaddLossModel(float cx, float cy, const char * type) {
  765. Animation * object;
  766. Node * source, * destination;
  767. Edge * edge, * reverse_edge;
  768. EditorNetModel* emodel_ = (EditorNetModel *) model_;
  769. // Switch from screen coordinates to world coordinates
  770. matrix_.imap(cx, cy);
  771. // Do we have a link on the clicked point ?
  772. object = model_->inside(cx, cy);
  773. if (object == NULL) {
  774. defTag_->remove();
  775. return (TCL_OK);
  776. if (object->classid() == ClassEdgeID ||
  777. object->classid() == ClassQueueHandleID ) {
  778. //
  779. // Yes, we have a possible edge to which we can add the loss model
  780. if (object->classid() == ClassQueueHandleID ) {
  781. edge = ((QueueHandle *) object)->getEdge();
  782. } else {
  783. edge = (Edge *) object;
  784. }
  785. if (edge) {
  786. // Check distance to source to determine if we should attach 
  787. // to the forward or reverse edge
  788. source = edge->getSourceNode();
  789. destination = edge->getDestinationNode();
  790. if (source->distance(cx, cy) > destination->distance(cx,cy)) {
  791. // if source is farther away than destination then place
  792. // this loss model on the reverse edge
  793. reverse_edge = emodel_->lookupEdge(destination->number(), source->number());
  794. if (reverse_edge) { // Make sure there is a reverse edge
  795. edge = reverse_edge;
  796. }
  797. }
  798. // goto EditorNetModel::addTrafficSource(...) in enetmodel.cc
  799. emodel_->addLossModel(edge, type, cx, cy);
  800. draw();
  801. }
  802. }
  803. return(TCL_OK);
  804. }
  805. // ---------------------------------------------------------------------
  806. // int 
  807. // EditView::cmdSetPoint(float cx, float cy, int bAdd)
  808. //   - Note: all cx_ and cy_ below are in *window* coordinates
  809. // ---------------------------------------------------------------------
  810. int 
  811. EditView::cmdSetPoint(float cx, float cy, int add_object) {
  812.   Animation * animation_object;
  813.   // First of all, clean the old group
  814.   cx_ = cx;
  815.   cy_ = cy;
  816.   // Inverse Map cx, cy to world coordinates
  817.   matrix_.imap(cx, cy);
  818.   // Do we have anything on current point?
  819.   animation_object = model_->inside(cx, cy);
  820.   // If nothing at this point start selection rubberband
  821.   if (animation_object == NULL) {
  822.     defTag_->remove();
  823.     startRubberBand(cx_, cy_);
  824.     return (TCL_OK);
  825.   }
  826.   // Otherwise look to move object if it is a node or a Tag
  827.   //   - A tag is a grouping marker, if an object is tagged then
  828.   //     that tag group can be moved together
  829.   if (animation_object->isTagged()) {
  830.     if (animation_object->numTag() > 1) {
  831.       fprintf(stderr, "Error: More than one tag for object %d!n",
  832.                        animation_object->id());
  833.       animation_object = NULL;
  834.     } else {
  835.       animation_object = animation_object->getLastTag();
  836.     }
  837.   }
  838.   
  839.   // Only nodes and tags can be moved
  840.   if ((animation_object->classid() == ClassNodeID) ||
  841.       (animation_object->classid() == ClassTagID)) {
  842.     
  843.     // If a single non-tag object is selected, or explicitly 
  844.     // instructed, remove the previous selection.  Otherwise,
  845.     // the object under the current point will be added to the
  846.     // entire tagged selection
  847.     if (!add_object && (animation_object != defTag_)) {
  848.       defTag_->remove();
  849.     }
  850.     // Just tags the object as being selected.
  851.     // Draws a box around the tagged object
  852.     startSetObject(animation_object, cx_, cy_);
  853.   } else {
  854.     defTag_->remove();
  855.     startRubberBand(cx_, cy_);
  856.   }
  857.   return (TCL_OK);
  858. }
  859. //----------------------------------------------------------------------
  860. // int
  861. // EditView::cmdMoveTo(float cx, float cy)
  862. //   - Moves object to end location
  863. //   - Ends the rubber band selection
  864. //----------------------------------------------------------------------
  865. int EditView::cmdMoveTo(float cx, float cy) {
  866.   // cx and cy should be in screen (canvas) coordinates
  867.   cx_ = cx;
  868.   cy_ = cy;
  869.   switch (editing_stage_) {
  870.     case START_RUBBERBAND:
  871.     case MOVE_RUBBERBAND:
  872.       oldx_ = rb_.xmax;
  873.       oldy_ = rb_.ymax;
  874.       rb_.xmax = cx_;
  875.       rb_.ymax = cy_;
  876.       editing_stage_ = MOVE_RUBBERBAND;
  877.       clip_ = rb_;
  878.       clip_.adjust();
  879.       if (clip_.xmin > oldx_) 
  880.         clip_.xmin = oldx_;
  881.       if (clip_.xmax < oldx_) 
  882.         clip_.xmax = oldx_;
  883.       if (clip_.ymin > oldy_) 
  884.         clip_.ymin = oldy_;
  885.       if (clip_.ymax < oldy_) 
  886.         clip_.ymax = oldy_;
  887.       break;
  888.     case START_OBJECT:
  889.     case MOVE_OBJECT: {
  890.       oldx_ = rb_.xmax;
  891.       oldy_ = rb_.ymax;
  892.       rb_.xmax = cx_;
  893.       rb_.ymax = cy_;
  894.       editing_stage_ = MOVE_OBJECT;
  895.       clip_.clear();
  896.       defTag_->merge(clip_);
  897.       matrix_.map(clip_.xmin, clip_.ymin);
  898.       matrix_.map(clip_.xmax, clip_.ymax);
  899.       clip_.adjust();
  900.       // Actual move and final bbox computation is done in render
  901.       break;
  902.       case START_LINK:
  903.       case MOVE_LINK:
  904.         // I believe this is never reached and should be removed
  905.         // maybe it is changed in the future
  906.         oldx_ = rb_.xmax;
  907.         oldy_ = rb_.ymax;
  908.         rb_.xmax = cx_;
  909.         rb_.ymax = cy_;
  910.         editing_stage_ = MOVE_LINK;
  911.         clip_ = rb_;
  912.         clip_.adjust();
  913.         if (clip_.xmin > oldx_)
  914.           clip_.xmin = oldx_;
  915.         if (clip_.xmax < oldx_)
  916.           clip_.xmax = oldx_;
  917.         if (clip_.ymin > oldy_)
  918.           clip_.ymin = oldy_;
  919.         if (clip_.ymax < oldy_)
  920.           clip_.ymax = oldy_;
  921.         break;
  922.       }
  923.     default:
  924.       // to avoid segmentation fault from click-n-dragging
  925.       return (TCL_OK);
  926.   }
  927.   draw();
  928.   return (TCL_OK);
  929. }
  930. int EditView::cmdReleasePoint(float cx, float cy) {
  931. static char buffer[512];
  932. int chars_written;
  933. cx_ = cx;
  934. cy_ = cy;
  935. Tcl & tcl = Tcl::instance();
  936. switch (editing_stage_) {
  937. case START_RUBBERBAND:
  938. case MOVE_RUBBERBAND: {
  939. oldx_ = rb_.xmax; oldy_ = rb_.ymax;
  940. rb_.xmax = cx_, rb_.ymax = cy_;
  941. // Need to add the region to defTag_
  942. clip_ = rb_;
  943. clip_.adjust();
  944. BBox bb = clip_;
  945. matrix_.imap(bb.xmin, bb.ymin);
  946. matrix_.imap(bb.xmax, bb.ymax);
  947. bb.adjust();
  948. model_->tagArea(bb, defTag_, 1);
  949. // We can do a total redraw
  950. editing_stage_ = NONE;
  951. draw();
  952. // Get time movement info for node markers on time slider
  953. // defTag_->addNodeMovementDestination(this, cx - oldx_, cy - oldy_, model_->now());
  954. // chars_written = defTag_->getNodeMovementTimes(buffer, 512);
  955. // if (chars_written == -1) {
  956. tcl.resultf("NONE");
  957. // } else {
  958. // tcl.resultf("%s", buffer);
  959. // }
  960. break;
  961. }
  962. case START_OBJECT:
  963. case MOVE_OBJECT: {
  964. oldx_ = rb_.xmax;
  965. oldy_ = rb_.ymax;
  966. rb_.xmax = cx_;
  967. rb_.ymax = cy_;
  968. clip_.clear();
  969. defTag_->merge(clip_);
  970. matrix_.map(clip_.xmin, clip_.ymin);
  971. matrix_.map(clip_.xmax, clip_.ymax);
  972. clip_.adjust();
  973. // Later in render() we'll compute the real bbox
  974. editing_stage_ = END_OBJECT;
  975. draw();
  976. editing_stage_ = NONE;
  977. model_->update(model_->now());
  978. //      defTag_->move(this, rb_.xmax - oldx_, rb_.ymax - oldy_);
  979. // Get time movement info for node markers on time slider
  980. defTag_->addNodeMovementDestination(this, cx - oldx_, cy - oldy_, model_->now());
  981. chars_written = defTag_->getNodeMovementTimes(buffer, 512);
  982. if (chars_written == -1) {
  983. tcl.resultf("NONE");
  984. } else {
  985. tcl.resultf("%s", buffer);
  986. }
  987. break;
  988. }
  989. case START_LINK:
  990. case MOVE_LINK: {
  991. editing_stage_ = START_LINK;
  992. draw();
  993. model_->update(model_->now());
  994. cmdaddLink(cx_, cy_);
  995. tcl.resultf("NONE");
  996. break;
  997. }
  998. default:
  999. // This cannot happen!
  1000. editing_stage_ = NONE;
  1001. draw();
  1002. tcl.resultf("NONE");
  1003. }
  1004. return (TCL_OK);
  1005. }
  1006. //----------------------------------------------------------------------
  1007. //----------------------------------------------------------------------
  1008. inline void
  1009. EditView::startRubberBand(float cx, float cy) {
  1010. // Nothing's here. Set rubber band.
  1011. editing_stage_ = START_RUBBERBAND;
  1012. rb_.xmin = rb_.xmax = cx;
  1013. rb_.ymin = rb_.ymax = cy;
  1014. clip_ = rb_;
  1015. }
  1016. //----------------------------------------------------------------------
  1017. //----------------------------------------------------------------------
  1018. inline void
  1019. EditView::startSetObject(Animation * animation_object, float cx, float cy) {
  1020. // Find an object, add it to group
  1021. editing_stage_ = START_OBJECT;
  1022. // Add it into defTag_
  1023. if (animation_object != defTag_) {
  1024. model_->tagObject(defTag_, animation_object);
  1025. }
  1026. rb_.xmin = rb_.xmax = cx;
  1027. rb_.ymin = rb_.ymax = cy;
  1028. clip_.clear();
  1029. defTag_->merge(clip_);
  1030. // for the bounding box (bbox)
  1031. oldx_ = rb_.xmax;
  1032. oldy_ = rb_.ymax;
  1033. rb_.xmax = cx_;
  1034. rb_.ymax = cy_;
  1035. clip_.clear();
  1036. defTag_->merge(clip_);
  1037. matrix_.map(clip_.xmin, clip_.ymin);
  1038. matrix_.map(clip_.xmax, clip_.ymax);
  1039. clip_.adjust();
  1040. // Later in render() we'll compute the real bbox
  1041. // We have selected the object and now we are at the end of 
  1042. // the object selection process
  1043. editing_stage_ = END_OBJECT;
  1044. draw();
  1045. editing_stage_ = NONE;
  1046. model_->update(model_->now());
  1047. editing_stage_ = START_OBJECT;
  1048. }
  1049. //----------------------------------------------------------------------
  1050. // void EditView::draw()
  1051. //----------------------------------------------------------------------
  1052. void EditView::draw() {
  1053. if (editing_stage_ == NONE) {
  1054. View::draw();
  1055. } else {
  1056. // Ignore the cleaning part
  1057. render();
  1058.  
  1059. // XXX Don't understand why clip's height and width need to 
  1060. // increase 3 to draw tagged objects correctly. 
  1061. XCopyArea(Tk_Display(tk_), offscreen_, Tk_WindowId(tk_), 
  1062.           background_,(int)clip_.xmin, (int)clip_.ymin, 
  1063.           (int)clip_.width()+3, (int)clip_.height()+3, 
  1064.           (int)clip_.xmin, (int)clip_.ymin);
  1065. }
  1066. }
  1067. //----------------------------------------------------------------------
  1068. // void EditView::draw(double current_time)
  1069. //----------------------------------------------------------------------
  1070. void EditView::draw(double current_time) {
  1071. model_->update(current_time);
  1072. }
  1073. //----------------------------------------------------------------------
  1074. //----------------------------------------------------------------------
  1075. void EditView::xline(float x0, float y0, float x1, float y1, GC gc) {
  1076.   XDrawLine(Tk_Display(tk_), offscreen_, gc, (int) x0, (int) y0,
  1077.                                              (int) x1, (int) y1);
  1078. }
  1079. // Without transform.
  1080. void EditView::xrect(float x0, float y0, float x1, float y1, GC gc)
  1081. {
  1082. int x = (int) floor(x0);
  1083. int y = (int) floor(y0);
  1084. int w = (int)(x1 - x0);
  1085. if (w < 0) {
  1086. x = (int) ceil(x1);
  1087. w = -w;
  1088. }
  1089. int h = (int)(y1 - y0);
  1090. if (h < 0) {
  1091. h = -h;
  1092. y = (int)ceil(y1);
  1093. }
  1094. XDrawRectangle(Tk_Display(tk_), offscreen_, gc, x, y, w, h);
  1095. }
  1096. void EditView::line(float x0, float y0, float x1, float y1, int color)
  1097. {
  1098. if (editing_stage_ != NONE)
  1099. View::line(x0, y0, x1, y1, Paint::instance()->Xor());
  1100. else 
  1101. View::line(x0, y0, x1, y1, color);
  1102. }
  1103. void EditView::rect(float x0, float y0, float x1, float y1, int color)
  1104. {
  1105. if (editing_stage_ != NONE)
  1106. View::rect(x0, y0, x1, y1, Paint::instance()->Xor());
  1107. else 
  1108. View::rect(x0, y0, x1, y1, color);
  1109. }
  1110. void EditView::polygon(const float* x, const float* y, int n, int color)
  1111. {
  1112. if (editing_stage_ != NONE)
  1113. View::polygon(x, y, n, Paint::instance()->Xor());
  1114. else 
  1115. View::polygon(x, y, n, color);
  1116. }
  1117. void EditView::fill(const float* x, const float* y, int n, int color)
  1118. {
  1119. if (editing_stage_ != NONE)
  1120. View::fill(x, y, n, Paint::instance()->Xor());
  1121. else 
  1122. View::fill(x, y, n, color);
  1123. }
  1124. void EditView::circle(float x, float y, float r, int color)
  1125. {
  1126. if (editing_stage_ != NONE)
  1127. View::circle(x, y, r, Paint::instance()->Xor());
  1128. else 
  1129. View::circle(x, y, r, color);
  1130. }
  1131. // Do not display any string, because no xor font gc
  1132. void EditView::string(float fx, float fy, float dim, const char* s, int anchor)
  1133. {
  1134. if (editing_stage_ == NONE)
  1135. View::string(fx, fy, dim, s, anchor);
  1136. }
  1137. //----------------------------------------------------------------------
  1138. // void
  1139. // EditView::BoundingBox(BBox &bb)
  1140. //   - This copies the area in which an animation drawn may be drawn
  1141. //     into (clipping area) the destination bb.  
  1142. //----------------------------------------------------------------------
  1143. void
  1144. EditView::BoundingBox(BBox &bb) {
  1145.   double temp;
  1146.   
  1147.   // Calculate the world coordinates for the view's canvas
  1148.   matrix_.imap(0.0, 0.0, bb.xmin, bb.ymin);
  1149.   matrix_.imap(width_, height_, bb.xmax, bb.ymax);
  1150.   // Check to make sure xmin, ymin is the lower left corner
  1151.   // and xmax, ymax is the upper right
  1152.   if (bb.xmin > bb.xmax) {
  1153.     temp = bb.xmax;
  1154.     bb.xmax = bb.xmin;
  1155.     bb.xmin = temp;
  1156.   }
  1157.   if (bb.ymin > bb.ymax) {
  1158.     temp = bb.ymax;
  1159.     bb.ymax = bb.ymin;
  1160.     bb.ymin = temp;
  1161.   }
  1162. }
  1163. void
  1164. EditView::getWorldBox(BBox &bb) {
  1165.   model_->BoundingBox(bb);
  1166. }
  1167. //----------------------------------------------------------------------
  1168. // void 
  1169. // EditView::render()
  1170. //   - not sure why this is called render but it seems to take care of 
  1171. //     rubberband selections and moving a selection on the screen
  1172. //   - I believe the real "rendering" is done in model_->render()
  1173. //     which is of type NetModel.  -- mehringe@isi.edu
  1174. //
  1175. //----------------------------------------------------------------------
  1176. void
  1177. EditView::render() {
  1178.   // Here we can compute the clipping box for render
  1179.   Paint *paint = Paint::instance();
  1180.   GC gc = paint->paint_to_gc(paint->Xor());
  1181.   switch (editing_stage_) {
  1182.     case START_RUBBERBAND:
  1183.       // draw rubber band
  1184.       xrect(rb_.xmin, rb_.ymin, rb_.xmax, rb_.ymax, gc);
  1185.       break;
  1186.     case MOVE_RUBBERBAND: 
  1187.       // erase previous rubberband
  1188.       xrect(rb_.xmin, rb_.ymin, oldx_, oldy_, gc);
  1189.       // draw new rubberband
  1190.       xrect(rb_.xmin, rb_.ymin, rb_.xmax, rb_.ymax, gc);
  1191.       break;
  1192.     case END_RUBBERBAND: 
  1193.       // erase previous rubber band
  1194.       xrect(rb_.xmin, rb_.ymin, oldx_, oldy_, gc);
  1195.       // XXX Should draw the tag?
  1196.       model_->render(this);
  1197.       editing_stage_ = NONE;
  1198.       break;
  1199.     case START_OBJECT:
  1200.       xrect(rb_.xmin, rb_.ymin, rb_.xmax, rb_.ymax, gc);
  1201.       // xor-draw all relevant objects
  1202.       defTag_->draw(this, model_->now());
  1203.       break;
  1204.     case MOVE_OBJECT: 
  1205.       // erase old positions first.
  1206.       if ((oldx_ == rb_.xmax) && (oldy_ == rb_.ymax)) 
  1207.         return;
  1208.       defTag_->draw(this, model_->now());
  1209.       // move these objects
  1210.       defTag_->move(this, rb_.xmax - oldx_, rb_.ymax - oldy_);
  1211.       BBox bb;
  1212.       bb.clear();
  1213.       defTag_->merge(bb);
  1214.       matrix_.imap(bb.xmin, bb.ymin);
  1215.       matrix_.imap(bb.xmax, bb.ymax);
  1216.       bb.adjust();
  1217.       clip_.merge(bb);
  1218.       defTag_->draw(this, model_->now());
  1219.       break;
  1220.     case END_OBJECT:
  1221.       // Erase old positions
  1222.       defTag_->draw(this, model_->now());
  1223.       // At least we should redo scale estimation and 
  1224.       // place everything
  1225.       defTag_->move(this, rb_.xmax - oldx_, rb_.ymax - oldy_);
  1226.       model_->recalc();
  1227.       model_->render(this);
  1228.       editing_stage_ = NONE;
  1229.       break;
  1230.     case START_LINK:
  1231.       line(link_start_x_, link_start_y_, link_end_x_, link_end_y_, 3);
  1232.       defTag_->draw(this, model_->now());
  1233.       break;
  1234.     case MOVE_LINK:
  1235.       // erase previous link
  1236.       xline(rb_.xmin, rb_.ymin, oldx_, oldy_, gc);
  1237.       // draw new rubberband
  1238.       xline(rb_.xmin, rb_.ymin, rb_.xmax, rb_.ymax, gc);
  1239.       break;
  1240.     case END_LINK:
  1241.       // erase previous link
  1242.       xline(rb_.xmin, rb_.ymin, oldx_, oldy_, gc);
  1243.       // XXX Should draw the tag?
  1244.       model_->render(this);
  1245.       editing_stage_ = NONE;
  1246.       break;
  1247.     default:
  1248.       // redraw model
  1249.       model_->render(this);
  1250.       break;
  1251.   }
  1252.   return;
  1253. }