COIN-OR::LEMON - Graph Library

source: glemon-0.x/gdc-broken_edge.cc

Last change on this file was 174:95872af46fc4, checked in by Alpar Juttner, 13 years ago

Add copyright headers

File size: 7.3 KB
Line 
1/* -*- C++ -*-
2 *
3 * This file is a part of LEMON, a generic C++ optimization library
4 *
5 * Copyright (C) 2003-2006
6 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
7 * (Egervary Research Group on Combinatorial Optimization, EGRES).
8 *
9 * Permission to use, modify and distribute this software is granted
10 * provided that this copyright notice appears in all copies. For
11 * precise terms see the accompanying LICENSE file.
12 *
13 * This software is provided "AS IS" with no warranty of any kind,
14 * express or implied, and with no claim as to its suitability for any
15 * purpose.
16 *
17 */
18
19#include "graph_displayer_canvas.h"
20#include <cmath>
21
22GraphDisplayerCanvas::EdgeBase::EdgeBase(Gnome::Canvas::Group& _group, Edge _edge, GraphDisplayerCanvas& _canvas) :
23  Gnome::Canvas::Group(_group), edge(_edge), canvas(_canvas), arrow(*this)
24{
25  arrow.property_fill_color().set_value("red");
26  arrow.lower_to_bottom();
27  lower_to_bottom();
28}
29
30GraphDisplayerCanvas::EdgeBase::~EdgeBase()
31{
32}
33
34void GraphDisplayerCanvas::EdgeBase::drawArrow(XY unit_vector_in_dir)
35{
36  MapStorage& ms = canvas.mytab.mapstorage;
37  XY center(ms.arrow_pos[edge]);
38  XY unit_norm_vector(0-unit_vector_in_dir.y, unit_vector_in_dir.x);
39
40  //       /\       // top
41  //      /  \      //
42  //      -  -      // c(enter)l(eft), ccl, ccr, cr
43  //       ||       //
44  //       ||       // b(ottom)l, br
45
46  double size=3;
47
48  XY bl (center - unit_vector_in_dir * 3 * size + unit_norm_vector * size );
49  XY br (center - unit_vector_in_dir * 3 * size - unit_norm_vector * size );
50  XY ccl(center + unit_vector_in_dir *  size + unit_norm_vector * size );
51  XY ccr(center + unit_vector_in_dir *  size - unit_norm_vector * size );
52  XY cl (center + unit_vector_in_dir *  size + unit_norm_vector * 2 * size );
53  XY cr (center + unit_vector_in_dir *  size - unit_norm_vector * 2 * size );
54  XY top(center + unit_vector_in_dir * 3 * size);
55
56  Gnome::Canvas::Points arrow_points;
57  arrow_points.push_back(Gnome::Art::Point( bl.x , bl.y  ) );
58  arrow_points.push_back(Gnome::Art::Point( br.x , br.y  ) );
59  arrow_points.push_back(Gnome::Art::Point( ccr.x, ccr.y ) );
60  arrow_points.push_back(Gnome::Art::Point( cr.x , cr.y  ) );
61  arrow_points.push_back(Gnome::Art::Point( top.x, top.y ) );
62  arrow_points.push_back(Gnome::Art::Point( cl.x , cl.y  ) );
63  arrow_points.push_back(Gnome::Art::Point( ccl.x, ccl.y ) );
64
65  arrow.property_points().set_value(arrow_points);
66}
67
68GraphDisplayerCanvas::BrokenEdge::BrokenEdge(Gnome::Canvas::Group & g,
69    Edge _edge, GraphDisplayerCanvas & gc) : EdgeBase(g, _edge, gc),
70  isbutton(false), line(*this)
71{
72  arrow.signal_event().connect(sigc::mem_fun(*this, &GraphDisplayerCanvas::BrokenEdge::edgeFormerEventHandler));
73
74  line.property_fill_color().set_value("green");
75  line.property_width_units().set_value(10);   
76  line.lower_to_bottom();
77
78  draw();
79}
80
81GraphDisplayerCanvas::BrokenEdge::~BrokenEdge()
82{
83}
84
85void GraphDisplayerCanvas::BrokenEdge::draw()
86{
87  MapStorage& ms = canvas.mytab.mapstorage;
88
89  //calculating coordinates of the direction indicator arrow
90  XY head(ms.coords[ms.graph.target(edge)]);
91  XY center(ms.arrow_pos[edge]);
92
93  XY unit_vector_in_dir(head-center);
94  double length=sqrt( unit_vector_in_dir.normSquare() );
95
96  unit_vector_in_dir/=length;
97
98  // update the arrow
99  drawArrow(unit_vector_in_dir);
100
101  // update the edge
102  Gnome::Canvas::Points points;
103  Node source = ms.graph.source(edge);
104  Node target = ms.graph.target(edge);
105  points.push_back(Gnome::Art::Point(ms.coords[source].x,
106        ms.coords[source].y));
107  points.push_back(Gnome::Art::Point(ms.arrow_pos[edge].x,
108        ms.arrow_pos[edge].y));
109  points.push_back(Gnome::Art::Point(ms.coords[target].x,
110        ms.coords[target].y));
111  line.property_points().set_value(points);
112}
113
114bool GraphDisplayerCanvas::BrokenEdge::edgeFormerEventHandler(GdkEvent* e)
115{
116  switch(e->type)
117  {
118    case GDK_BUTTON_PRESS:
119      //we mark the location of the event to be able to calculate parameters
120      //of dragging
121      if(canvas.getActualTool()!=CREATE_NODE)
122      {
123        canvas.toggleEdgeActivity(this, true);
124        clicked_x=e->button.x;
125        clicked_y=e->button.y;
126        isbutton=true;
127      }
128      break;
129    case GDK_BUTTON_RELEASE:
130      if(canvas.getActualTool()!=CREATE_NODE)
131      {
132        canvas.toggleEdgeActivity(this, false);
133        isbutton=false;
134      }
135      break;
136    case GDK_MOTION_NOTIFY:
137      //we only have to do sg. if the mouse button is pressed
138      if(isbutton)
139      {
140        //new coordinates will be the old values,
141        //because the item will be moved to the
142        //new coordinate therefore the new movement
143        //has to be calculated from here
144
145        double dx=e->motion.x-clicked_x;
146        double dy=e->motion.y-clicked_y;
147
148        Gnome::Canvas::Points points_new;
149
150        canvas.mytab.mapstorage.arrow_pos.set(edge, canvas.mytab.mapstorage.arrow_pos[edge] + XY(dx, dy));
151
152        draw();
153        canvas.textReposition(canvas.mytab.mapstorage.arrow_pos[edge]);
154
155        clicked_x=e->motion.x;
156        clicked_y=e->motion.y;
157
158      }
159    default: break;
160  }
161
162  return true;
163}
164
165void GraphDisplayerCanvas::BrokenEdge::setLineWidth(int w)
166{
167  line.property_width_units().set_value(w);
168}
169
170void GraphDisplayerCanvas::BrokenEdge::setFillColor(Gdk::Color c)
171{
172  line.property_fill_color_gdk().set_value(c);
173}
174
175GraphDisplayerCanvas::LoopEdge::LoopEdge(Gnome::Canvas::Group& _group,
176    Edge _edge, GraphDisplayerCanvas& _canvas) :
177  EdgeBase(_group, _edge, _canvas), line(*this), isbutton(false)
178{
179  arrow.signal_event().connect(sigc::mem_fun(*this, &GraphDisplayerCanvas::LoopEdge::edgeFormerEventHandler));
180
181  line.property_outline_color().set_value("green");
182  line.property_width_units().set_value(10);
183  line.lower_to_bottom();
184
185  draw();
186}
187
188GraphDisplayerCanvas::LoopEdge::~LoopEdge()
189{
190}
191
192void GraphDisplayerCanvas::LoopEdge::draw()
193{
194  MapStorage& ms = canvas.mytab.mapstorage;
195
196  Node node = ms.graph.source(edge);
197  XY center = (ms.coords[node] + ms.arrow_pos[edge]) / 2.0;
198
199  XY unit_vector_in_dir(rot90(center - ms.arrow_pos[edge]));
200  double length = sqrt(unit_vector_in_dir.normSquare());
201  unit_vector_in_dir /= length;
202
203  drawArrow(unit_vector_in_dir);
204
205  double radius =
206    sqrt((ms.arrow_pos[edge] - ms.coords[node]).normSquare()) / 2.0;
207
208  XY p1 = center + XY(-radius,  radius);
209  XY p2 = center + XY( radius, -radius);
210  line.property_x1().set_value(p1.x);
211  line.property_y1().set_value(p1.y);
212  line.property_x2().set_value(p2.x);
213  line.property_y2().set_value(p2.y);
214}
215
216void GraphDisplayerCanvas::LoopEdge::setLineWidth(int w)
217{
218  line.property_width_units().set_value(w);
219}
220
221void GraphDisplayerCanvas::LoopEdge::setFillColor(Gdk::Color c)
222{
223  line.property_outline_color_gdk().set_value(c);
224}
225
226bool GraphDisplayerCanvas::LoopEdge::edgeFormerEventHandler(GdkEvent* e)
227{
228  switch(e->type)
229  {
230    case GDK_BUTTON_PRESS:
231      if(canvas.getActualTool()!=CREATE_NODE)
232      {
233        canvas.toggleEdgeActivity(this, true);
234        isbutton=true;
235      }
236      break;
237    case GDK_BUTTON_RELEASE:
238      if(canvas.getActualTool()!=CREATE_NODE)
239      {
240        canvas.toggleEdgeActivity(this, false);
241        isbutton=false;
242      }
243      break;
244    case GDK_MOTION_NOTIFY:
245      if(isbutton)
246      {
247        canvas.mytab.mapstorage.arrow_pos.set(edge, XY(e->motion.x, e->motion.y));
248
249        draw();
250        canvas.textReposition(canvas.mytab.mapstorage.arrow_pos[edge]);
251      }
252    default: break;
253  }
254  return true;
255}
Note: See TracBrowser for help on using the repository browser.