iconofthestoneage-doodl 0.0.2 → 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/lib/app/selfrunning.rb +185 -0
- data/lib/app/simple_app.rb +49 -0
- data/lib/app/simple_controller.rb +584 -0
- data/lib/app/simple_model.rb +292 -0
- data/lib/app/simple_view.rb +148 -0
- data/lib/breadth_first_search.rb +69 -0
- data/lib/connected_components.rb +29 -0
- data/lib/depth_first_search.rb +73 -0
- data/lib/edge.rb +57 -0
- data/lib/graph.rb +365 -0
- data/lib/graph_canvas.rb +187 -0
- data/lib/graph_generator.rb +121 -0
- data/lib/jruby/renderer.rb +413 -0
- data/lib/layout/collapse_layout.rb +23 -0
- data/lib/layout/fr_layout.rb +105 -0
- data/lib/layout/isom_layout.rb +77 -0
- data/lib/layout/kk_layout.rb +203 -0
- data/lib/layout/layout.rb +240 -0
- data/lib/layout/morph_layout.rb +65 -0
- data/lib/node.rb +57 -0
- data/lib/shortest_path/all_pair.rb +35 -0
- data/lib/shortest_path/bellman_ford.rb +60 -0
- data/lib/shortest_path/dijkstra.rb +74 -0
- data/lib/shortest_path/floyd_warshall.rb +68 -0
- data/lib/shortest_path/johnson_all_pair.rb +64 -0
- data/lib/shortest_path/single_source.rb +32 -0
- data/spec/breadth_first_search_spec.rb +145 -0
- data/spec/connected_components_spec.rb +50 -0
- data/spec/depth_first_search_spec.rb +89 -0
- data/spec/edge_spec.rb +58 -0
- data/spec/graph_generator_spec.rb +277 -0
- data/spec/graph_spec.rb +269 -0
- data/spec/jruby/renderer_spec.rb +214 -0
- data/spec/layout/layout_spec.rb +146 -0
- data/spec/node_spec.rb +179 -0
- data/spec/rspec_helper.rb +9 -0
- data/spec/rspec_suite.rb +12 -0
- data/spec/shortest_path/bellman_ford_spec.rb +101 -0
- data/spec/shortest_path/dijkstra_spec.rb +133 -0
- data/spec/shortest_path/floyd_warshall_spec.rb +84 -0
- data/spec/shortest_path/johnson_all_pair_spec.rb +90 -0
- metadata +43 -2
@@ -0,0 +1,185 @@
|
|
1
|
+
$LOAD_PATH.unshift File.join(File.dirname(__FILE__), '..', 'lib')
|
2
|
+
|
3
|
+
require "java"
|
4
|
+
|
5
|
+
require "logger"
|
6
|
+
|
7
|
+
require "graph"
|
8
|
+
require "jruby/renderer"
|
9
|
+
require "layout/layout"
|
10
|
+
require "layout/fr_layout"
|
11
|
+
require "layout/isom_layout"
|
12
|
+
require "layout/kk_layout"
|
13
|
+
require "shortest_path/dijkstra"
|
14
|
+
|
15
|
+
include Doodl
|
16
|
+
|
17
|
+
include_class 'javax.swing.JFrame'
|
18
|
+
include_class 'javax.swing.JLabel'
|
19
|
+
include_class 'java.awt.Dimension'
|
20
|
+
include_class 'java.awt.Color'
|
21
|
+
include_class 'java.awt.geom.Rectangle2D'
|
22
|
+
|
23
|
+
$LOG = Logger.new(STDOUT)
|
24
|
+
$LOG.sev_threshold = Logger::INFO
|
25
|
+
|
26
|
+
class Runner
|
27
|
+
def initialize(renderer)
|
28
|
+
@renderer = renderer
|
29
|
+
end
|
30
|
+
def update(observable)
|
31
|
+
@renderer.update_layout(observable)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
frame = JFrame.new("Doodl: Graph Drawing with Ruby")
|
36
|
+
|
37
|
+
renderer = PluggableRenderer.new
|
38
|
+
renderer.paint_iterations = false
|
39
|
+
renderer.setPreferredSize(Dimension.new(800, 600))
|
40
|
+
|
41
|
+
label = JLabel.new("Doodl Graph Drawing!")
|
42
|
+
label.setOpaque(true)
|
43
|
+
label.setBackground(java.awt.Color::BLACK)
|
44
|
+
label.setForeground(java.awt.Color::WHITE)
|
45
|
+
label.setBorder(javax.swing.BorderFactory.createEmptyBorder(5, 10, 5, 10))
|
46
|
+
|
47
|
+
frame.getContentPane().add(renderer, java.awt.BorderLayout::CENTER)
|
48
|
+
frame.getContentPane().add(label, java.awt.BorderLayout::SOUTH)
|
49
|
+
frame.pack
|
50
|
+
frame.setVisible(true)
|
51
|
+
|
52
|
+
graph = UndirectedGraph.new
|
53
|
+
graph.gen_random_graph(7, 10)
|
54
|
+
|
55
|
+
runner = Runner.new(renderer)
|
56
|
+
|
57
|
+
|
58
|
+
|
59
|
+
layouts = [RandomLayout, CircleLayout, FRLayout, ISOMLayout, KKLayout]
|
60
|
+
|
61
|
+
layouts.each do |lc|
|
62
|
+
l = lc.new(renderer)
|
63
|
+
l.graph = graph
|
64
|
+
l.add_observer(runner)
|
65
|
+
l.layout
|
66
|
+
label.setText("Undirected Graph - Layout: #{l.class}")
|
67
|
+
sleep(1)
|
68
|
+
end
|
69
|
+
|
70
|
+
graph.gen_ring_graph(10)
|
71
|
+
layout = ISOMLayout.new(renderer)
|
72
|
+
layout.graph = graph
|
73
|
+
layout.add_observer(runner)
|
74
|
+
layout.layout
|
75
|
+
label.setText("Graph Generator: Ring")
|
76
|
+
sleep(1)
|
77
|
+
|
78
|
+
graph.gen_linear_graph(5)
|
79
|
+
layout.layout
|
80
|
+
label.setText("Graph Generator: Linear")
|
81
|
+
sleep(1)
|
82
|
+
|
83
|
+
graph.gen_connected_graph(6)
|
84
|
+
layout.layout
|
85
|
+
label.setText("Graph Generator: Connected")
|
86
|
+
sleep(1)
|
87
|
+
|
88
|
+
graph.gen_mesh_graph(3)
|
89
|
+
layout.layout
|
90
|
+
label.setText("Graph Generator: Mesh")
|
91
|
+
sleep(1)
|
92
|
+
|
93
|
+
graph.gen_binary_tree(2)
|
94
|
+
layout.layout
|
95
|
+
label.setText("Graph Generator: Binary Tree")
|
96
|
+
sleep(1)
|
97
|
+
|
98
|
+
layout = FRLayout.new(renderer)
|
99
|
+
layout.add_observer(runner)
|
100
|
+
graph = DirectedGraph.new
|
101
|
+
|
102
|
+
graph.gen_random_graph(5, 10)
|
103
|
+
layout.graph = graph
|
104
|
+
layout.layout
|
105
|
+
label.setText("A Directed Graph")
|
106
|
+
sleep(1)
|
107
|
+
|
108
|
+
renderer.node_stroke_color_function { java.awt.Color::BLUE }
|
109
|
+
renderer.repaint
|
110
|
+
label.setText("Customize PluggableRenderer (node_stroke_color)")
|
111
|
+
sleep(1)
|
112
|
+
renderer.node_stroke_color_function { |g,l,n| if n.out_degree > 2 then Color::BLUE else Color::WHITE end}
|
113
|
+
renderer.repaint
|
114
|
+
sleep(1)
|
115
|
+
label.setText("You can define a function that defines the stoke color (e.g. if out_degree >2 then blue else white)")
|
116
|
+
renderer.node_shape_function { |g, l, n| Rectangle2D::Double.new(l[n].x-10, l[n].y-10, 20, 20) }
|
117
|
+
renderer.repaint
|
118
|
+
sleep(1)
|
119
|
+
label.setText("Customize PluggableRenderer (node_shape)")
|
120
|
+
label.setText("Zoom in and out")
|
121
|
+
10.times do
|
122
|
+
renderer.zoom(0.9)
|
123
|
+
sleep(0.5)
|
124
|
+
end
|
125
|
+
label.setText("Zoom absolute (e.g. 100%)")
|
126
|
+
renderer.zoom_absolute(1.0)
|
127
|
+
sleep(1)
|
128
|
+
label.setText("Center on a node")
|
129
|
+
graph.nodes.each do |node|
|
130
|
+
renderer.node_stroke_color_function { |g,l,n| if node == n then Color::BLUE else Color::WHITE end }
|
131
|
+
renderer.center_on_node(node)
|
132
|
+
sleep(0.5)
|
133
|
+
end
|
134
|
+
renderer.node_stroke_color_function { |g,l,n| if n.out_degree > 2 then Color::BLUE else Color::WHITE end}
|
135
|
+
|
136
|
+
begin
|
137
|
+
renderer.set_defaults
|
138
|
+
graph.gen_binary_tree(3)
|
139
|
+
|
140
|
+
source = graph.nodes[1]
|
141
|
+
target = graph.nodes.last
|
142
|
+
|
143
|
+
stdata = graph.attach_node_data(:start)
|
144
|
+
stdata[source] = true
|
145
|
+
endata = graph.attach_node_data(:end)
|
146
|
+
endata[target] = true
|
147
|
+
|
148
|
+
dsp = DijkstraShortestPath.new(graph, source)
|
149
|
+
npath = dsp.node_path_to(target)
|
150
|
+
epath = dsp.edge_path_to(target)
|
151
|
+
|
152
|
+
edata = graph.attach_edge_data(:path)
|
153
|
+
epath.each do |e|
|
154
|
+
edata[e] = true
|
155
|
+
end
|
156
|
+
ndata = graph.attach_node_data(:path)
|
157
|
+
npath.each do |n|
|
158
|
+
ndata[n] = true
|
159
|
+
end
|
160
|
+
|
161
|
+
renderer.edge_stroke_function do |g, l, e|
|
162
|
+
if g.edge_data(:path) and g.edge_data(:path)[e]
|
163
|
+
BasicStroke.new(4)
|
164
|
+
else
|
165
|
+
BasicStroke.new(2)
|
166
|
+
end
|
167
|
+
end
|
168
|
+
renderer.node_stroke_color_function do |g, l, n|
|
169
|
+
if g.node_data(:start) and g.node_data(:start)[n]
|
170
|
+
Color::GREEN
|
171
|
+
elsif g.node_data(:end) and g.node_data(:end)[n]
|
172
|
+
Color::YELLOW
|
173
|
+
elsif g.node_data(:path) and g.node_data(:path)[n]
|
174
|
+
Color::BLUE
|
175
|
+
else
|
176
|
+
Color::WHITE
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
layout = KKLayout.new(renderer)
|
181
|
+
layout.add_observer(runner)
|
182
|
+
layout.layout(graph)
|
183
|
+
label.setText("You can use the PluggabeRender features to highlight a shortest path!")
|
184
|
+
end
|
185
|
+
|
@@ -0,0 +1,49 @@
|
|
1
|
+
$LOAD_PATH.unshift File.join(File.dirname(__FILE__), '../..', 'lib')
|
2
|
+
|
3
|
+
require 'java'
|
4
|
+
|
5
|
+
require 'logger'
|
6
|
+
|
7
|
+
require 'renderer'
|
8
|
+
|
9
|
+
require 'app/simple_controller'
|
10
|
+
require 'app/simple_view'
|
11
|
+
require 'app/simple_model'
|
12
|
+
|
13
|
+
|
14
|
+
require "layout/layout"
|
15
|
+
|
16
|
+
include Doodl
|
17
|
+
|
18
|
+
$LOG = Logger.new(STDOUT)
|
19
|
+
$LOG.sev_threshold = Logger::INFO
|
20
|
+
@view = SimpleView.new
|
21
|
+
@model = SimpleModel.new
|
22
|
+
controller = SimpleController.new
|
23
|
+
|
24
|
+
#setup view
|
25
|
+
@canvas = PluggableRenderer.new
|
26
|
+
@canvas.setPreferredSize(java.awt.Dimension.new(800, 600))
|
27
|
+
|
28
|
+
|
29
|
+
frame = javax.swing.JFrame.new("Graph Doodl App")
|
30
|
+
frame.setDefaultCloseOperation(javax.swing.JFrame::EXIT_ON_CLOSE);
|
31
|
+
frame.getContentPane().add(@canvas)
|
32
|
+
frame.pack
|
33
|
+
frame.setVisible(true)
|
34
|
+
|
35
|
+
@view.canvas = @canvas
|
36
|
+
@view.frame = frame
|
37
|
+
|
38
|
+
#setup model
|
39
|
+
|
40
|
+
#setup controller
|
41
|
+
|
42
|
+
#glueing
|
43
|
+
controller.view = @view
|
44
|
+
@model.view = @view
|
45
|
+
@model.add_observer(@view)
|
46
|
+
controller.model = @model
|
47
|
+
|
48
|
+
@model.set_random_layout
|
49
|
+
#model.new_connected_graph(5)
|
@@ -0,0 +1,584 @@
|
|
1
|
+
require 'java'
|
2
|
+
|
3
|
+
include_class 'java.awt.event.KeyListener'
|
4
|
+
include_class 'java.awt.event.KeyEvent'
|
5
|
+
include_class 'java.awt.event.MouseListener'
|
6
|
+
include_class 'java.awt.event.MouseMotionListener'
|
7
|
+
include_class 'java.awt.event.ActionListener'
|
8
|
+
|
9
|
+
module AppActionListener
|
10
|
+
include ActionListener
|
11
|
+
|
12
|
+
def actionPerformed(event)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
module AppMouseListener
|
17
|
+
include MouseListener
|
18
|
+
|
19
|
+
def mouseEntered(event)
|
20
|
+
end
|
21
|
+
|
22
|
+
def mouseExited(event)
|
23
|
+
end
|
24
|
+
|
25
|
+
def mousePressed(event)
|
26
|
+
end
|
27
|
+
|
28
|
+
def mouseReleased(event)
|
29
|
+
end
|
30
|
+
|
31
|
+
def mouseClicked(event)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
module AppMouseMotionListener
|
36
|
+
include MouseMotionListener
|
37
|
+
|
38
|
+
def mouseDragged(event)
|
39
|
+
end
|
40
|
+
|
41
|
+
def mouseMoved(event)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
module AppKeyListener
|
46
|
+
include KeyListener
|
47
|
+
|
48
|
+
def keyPressed(event)
|
49
|
+
end
|
50
|
+
|
51
|
+
def keyReleased(event)
|
52
|
+
end
|
53
|
+
|
54
|
+
def keyTyped(event)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
class SimpleController
|
59
|
+
|
60
|
+
attr_reader :view, :model
|
61
|
+
|
62
|
+
def view=(view)
|
63
|
+
@view = view
|
64
|
+
@view.add_key_listener(MainKeyListener.new(self))
|
65
|
+
end
|
66
|
+
|
67
|
+
def model=(model)
|
68
|
+
@model = model
|
69
|
+
end
|
70
|
+
|
71
|
+
def add_node
|
72
|
+
@view.add_mouse_listener(AddNodeMouseListener.new(self))
|
73
|
+
end
|
74
|
+
|
75
|
+
def del_node
|
76
|
+
@view.add_mouse_listener(DelNodeMouseListener.new(self))
|
77
|
+
end
|
78
|
+
|
79
|
+
def add_edge
|
80
|
+
@view.add_mouse_listener(AddEdgeMouseListener.new(self))
|
81
|
+
end
|
82
|
+
|
83
|
+
def del_edge
|
84
|
+
@view.add_mouse_listener(DelEdgeMouseListener.new(self))
|
85
|
+
end
|
86
|
+
|
87
|
+
def move_node
|
88
|
+
listener = MoveNodeMouseListener.new(self)
|
89
|
+
@view.add_mouse_motion_listener(listener)
|
90
|
+
@view.add_mouse_listener(listener)
|
91
|
+
end
|
92
|
+
|
93
|
+
def choose_layout
|
94
|
+
@view.add_info_panel("Select Layout. Enter Type [Random, Circle, FR, ISOM]")
|
95
|
+
@view.add_text_field(LayoutActionListener.new(self))
|
96
|
+
end
|
97
|
+
|
98
|
+
def choose_generator
|
99
|
+
@view.add_info_panel("Generate Graph. Enter Generation Mode [Random <s>, Linear <s>, Ring <s>, Mesh <r>, Connected <s>]")
|
100
|
+
@view.add_text_field(GenerateGraphActionListener.new(self))
|
101
|
+
end
|
102
|
+
|
103
|
+
def choose_graph_type
|
104
|
+
@view.add_info_panel("Choose graph type: [directed, undirected]")
|
105
|
+
@view.add_text_field(GraphTypeActionListener.new(self))
|
106
|
+
end
|
107
|
+
|
108
|
+
def do_layout
|
109
|
+
java.lang.Thread.new(java.lang.Runnable.impl { @model.layout.layout }).start
|
110
|
+
end
|
111
|
+
|
112
|
+
def new_graph
|
113
|
+
@model.new_empty_graph
|
114
|
+
java.lang.Thread.new(java.lang.Runnable.impl { @model.layout.layout }).start
|
115
|
+
end
|
116
|
+
|
117
|
+
def new_layout
|
118
|
+
end
|
119
|
+
|
120
|
+
def generate_graph
|
121
|
+
end
|
122
|
+
|
123
|
+
def select_node
|
124
|
+
|
125
|
+
end
|
126
|
+
|
127
|
+
def set_random_layout
|
128
|
+
@model.set_random_layout
|
129
|
+
@model.layout.layout
|
130
|
+
end
|
131
|
+
|
132
|
+
def set_circle_layout
|
133
|
+
@model.set_circle_layout
|
134
|
+
@model.layout.layout
|
135
|
+
end
|
136
|
+
|
137
|
+
def set_fr_layout
|
138
|
+
@model.set_fr_layout
|
139
|
+
java.lang.Thread.new(java.lang.Runnable.impl { @model.layout.layout }).start
|
140
|
+
end
|
141
|
+
|
142
|
+
def set_isom_layout
|
143
|
+
@model.set_isom_layout
|
144
|
+
java.lang.Thread.new(java.lang.Runnable.impl { @model.layout.layout }).start
|
145
|
+
end
|
146
|
+
|
147
|
+
def set_kk_layout
|
148
|
+
@model.set_kk_layout
|
149
|
+
java.lang.Thread.new(java.lang.Runnable.impl { @model.layout.layout }).start
|
150
|
+
end
|
151
|
+
|
152
|
+
def set_morph_layout(target_layout_class)
|
153
|
+
@model.set_morph_layout(target_layout_class)
|
154
|
+
java.lang.Thread.new(java.lang.Runnable.impl { @model.layout.layout }).start
|
155
|
+
end
|
156
|
+
|
157
|
+
def set_collapse_layout
|
158
|
+
@model.set_collapse_layout
|
159
|
+
java.lang.Thread.new(java.lang.Runnable.impl { @model.layout.layout }).start
|
160
|
+
end
|
161
|
+
|
162
|
+
def set_random(size)
|
163
|
+
@model.new_random_graph(size)
|
164
|
+
java.lang.Thread.new(java.lang.Runnable.impl { @model.layout.layout }).start
|
165
|
+
end
|
166
|
+
|
167
|
+
def set_ring(size)
|
168
|
+
@model.new_ring_graph(size)
|
169
|
+
java.lang.Thread.new(java.lang.Runnable.impl { @model.layout.layout }).start
|
170
|
+
end
|
171
|
+
|
172
|
+
def set_bintree(size)
|
173
|
+
@model.new_binary_tree(size)
|
174
|
+
java.lang.Thread.new(java.lang.Runnable.impl { @model.layout.layout }).start
|
175
|
+
end
|
176
|
+
|
177
|
+
def set_connected(size)
|
178
|
+
@model.new_connected_graph(size)
|
179
|
+
java.lang.Thread.new(java.lang.Runnable.impl { @model.layout.layout }).start
|
180
|
+
end
|
181
|
+
|
182
|
+
def set_linear(size)
|
183
|
+
@model.new_linear_graph(size)
|
184
|
+
java.lang.Thread.new(java.lang.Runnable.impl { @model.layout.layout }).start
|
185
|
+
end
|
186
|
+
|
187
|
+
def set_mesh(rows)
|
188
|
+
@model.new_mesh_graph(rows)
|
189
|
+
java.lang.Thread.new(java.lang.Runnable.impl { @model.layout.layout }).start
|
190
|
+
end
|
191
|
+
|
192
|
+
def print_info
|
193
|
+
puts @controller.model.layout
|
194
|
+
puts @controller.model.graph
|
195
|
+
end
|
196
|
+
|
197
|
+
def shortest_path
|
198
|
+
@view.add_mouse_listener(ShortestPathMouseListener.new(self))
|
199
|
+
end
|
200
|
+
|
201
|
+
def shortest_tree
|
202
|
+
@view.add_mouse_listener(ShortestTreeMouseListener.new(self))
|
203
|
+
end
|
204
|
+
|
205
|
+
def count_nodes
|
206
|
+
@model.count_nodes
|
207
|
+
end
|
208
|
+
|
209
|
+
def toggle_paint_iterations
|
210
|
+
@view.toggle_paint_iterations
|
211
|
+
$LOG.info "PluggableRenderer: paint_iterations? #{@view.canvas.paint_iterations?}"
|
212
|
+
end
|
213
|
+
|
214
|
+
def rotate_layout_right
|
215
|
+
@model.rotate_layout(2)
|
216
|
+
end
|
217
|
+
|
218
|
+
def rotate_layout_left
|
219
|
+
@model.rotate_layout(-2)
|
220
|
+
end
|
221
|
+
|
222
|
+
def move_layout_left
|
223
|
+
@model.move_layout(-5, 0)
|
224
|
+
end
|
225
|
+
|
226
|
+
def move_layout_right
|
227
|
+
@model.move_layout(5, 0)
|
228
|
+
end
|
229
|
+
|
230
|
+
def move_layout_up
|
231
|
+
@model.move_layout(0, -5)
|
232
|
+
end
|
233
|
+
|
234
|
+
def move_layout_down
|
235
|
+
@model.move_layout(0, 5)
|
236
|
+
end
|
237
|
+
|
238
|
+
def center_x
|
239
|
+
@model.center_x
|
240
|
+
end
|
241
|
+
|
242
|
+
def center_y
|
243
|
+
@model.center_y
|
244
|
+
end
|
245
|
+
|
246
|
+
end
|
247
|
+
|
248
|
+
class MainKeyListener
|
249
|
+
include AppKeyListener
|
250
|
+
|
251
|
+
def initialize(controller)
|
252
|
+
@controller = controller
|
253
|
+
end
|
254
|
+
|
255
|
+
def keyPressed(event)
|
256
|
+
case event.getKeyCode
|
257
|
+
when KeyEvent::VK_RIGHT
|
258
|
+
if event.isShiftDown
|
259
|
+
@controller.rotate_layout_right
|
260
|
+
else
|
261
|
+
@controller.move_layout_right
|
262
|
+
end
|
263
|
+
when KeyEvent::VK_LEFT
|
264
|
+
if event.isShiftDown
|
265
|
+
@controller.rotate_layout_left
|
266
|
+
else
|
267
|
+
@controller.move_layout_left
|
268
|
+
end
|
269
|
+
when KeyEvent::VK_UP
|
270
|
+
@controller.move_layout_up
|
271
|
+
when KeyEvent::VK_DOWN
|
272
|
+
@controller.move_layout_down
|
273
|
+
end
|
274
|
+
end
|
275
|
+
|
276
|
+
def keyTyped(event)
|
277
|
+
case event.key_char.chr
|
278
|
+
when 'a'
|
279
|
+
@controller.add_node
|
280
|
+
when 'c'
|
281
|
+
@controller.count_nodes
|
282
|
+
when 'd'
|
283
|
+
@controller.del_node
|
284
|
+
when 'u'
|
285
|
+
@controller.del_edge
|
286
|
+
when 'e'
|
287
|
+
@controller.add_edge
|
288
|
+
when 'n'
|
289
|
+
@controller.new_graph
|
290
|
+
when 'g'
|
291
|
+
@controller.choose_generator
|
292
|
+
when 'l'
|
293
|
+
@controller.choose_layout
|
294
|
+
when 'r'
|
295
|
+
@controller.do_layout
|
296
|
+
when 'i'
|
297
|
+
@controller.toggle_paint_iterations
|
298
|
+
when 's'
|
299
|
+
@controller.select_nodes
|
300
|
+
when 'm'
|
301
|
+
@controller.move_node
|
302
|
+
when 'p'
|
303
|
+
@controller.shortest_path
|
304
|
+
when 't'
|
305
|
+
@controller.shortest_tree
|
306
|
+
when 't'
|
307
|
+
@controller.choose_graph_type
|
308
|
+
when 'x'
|
309
|
+
@controller.center_x
|
310
|
+
when 'y'
|
311
|
+
@controller.center_y
|
312
|
+
end
|
313
|
+
end
|
314
|
+
end
|
315
|
+
|
316
|
+
class AddNodeMouseListener
|
317
|
+
include AppMouseListener
|
318
|
+
|
319
|
+
def initialize(controller)
|
320
|
+
@controller = controller
|
321
|
+
end
|
322
|
+
|
323
|
+
def mousePressed(event)
|
324
|
+
@node = @controller.model.add_node_at(event.x, event.y)
|
325
|
+
@controller.model.click(@node)
|
326
|
+
end
|
327
|
+
|
328
|
+
def mouseReleased(event)
|
329
|
+
@controller.model.unclick(@node) if @node
|
330
|
+
@controller.view.remove_mouse_listener(self)
|
331
|
+
end
|
332
|
+
end
|
333
|
+
|
334
|
+
class AddEdgeMouseListener
|
335
|
+
include AppMouseListener
|
336
|
+
|
337
|
+
def initialize(controller)
|
338
|
+
@controller = controller
|
339
|
+
end
|
340
|
+
|
341
|
+
def mousePressed(event)
|
342
|
+
if (!@first)
|
343
|
+
@first = @controller.model.get_nearest_node(event.x, event.y)
|
344
|
+
@controller.model.click(@first)
|
345
|
+
else
|
346
|
+
@second = @controller.model.get_nearest_node(event.x, event.y)
|
347
|
+
@controller.model.click(@second)
|
348
|
+
@edge = @controller.model.add_edge(@first, @second)
|
349
|
+
@controller.model.click_edge(@edge)
|
350
|
+
end
|
351
|
+
end
|
352
|
+
|
353
|
+
def mouseReleased(event)
|
354
|
+
@controller.model.unclick(@first) if @first
|
355
|
+
@controller.model.unclick_edge(@edge) if @edge
|
356
|
+
if @second
|
357
|
+
@controller.view.remove_mouse_listener(self)
|
358
|
+
@controller.model.unclick(@second) if @second
|
359
|
+
end
|
360
|
+
end
|
361
|
+
end
|
362
|
+
|
363
|
+
class DelEdgeMouseListener
|
364
|
+
include AppMouseListener
|
365
|
+
|
366
|
+
def initialize(controller)
|
367
|
+
@controller = controller
|
368
|
+
end
|
369
|
+
|
370
|
+
def mousePressed(event)
|
371
|
+
if (!@first)
|
372
|
+
@first = @controller.model.get_nearest_node(event.x, event.y)
|
373
|
+
@controller.model.click(@first)
|
374
|
+
else
|
375
|
+
@second = @controller.model.get_nearest_node(event.x, event.y)
|
376
|
+
@controller.model.click(@second)
|
377
|
+
@controller.model.click(@first)
|
378
|
+
@edge = @controller.model.get_edge(@first, @second)
|
379
|
+
@controller.model.click_edge(@edge) if @edge
|
380
|
+
end
|
381
|
+
end
|
382
|
+
|
383
|
+
def mouseReleased(event)
|
384
|
+
@controller.model.unclick(@first) if @first
|
385
|
+
if @second
|
386
|
+
@controller.view.remove_mouse_listener(self)
|
387
|
+
@controller.model.unclick(@second)
|
388
|
+
@controller.model.unclick_edge(@edge) if @edge
|
389
|
+
@controller.model.del_edge(@edge) if @edge
|
390
|
+
end
|
391
|
+
end
|
392
|
+
end
|
393
|
+
|
394
|
+
class MoveNodeMouseListener
|
395
|
+
include AppMouseMotionListener
|
396
|
+
include AppMouseListener
|
397
|
+
|
398
|
+
def initialize(controller)
|
399
|
+
@controller = controller
|
400
|
+
end
|
401
|
+
|
402
|
+
def mousePressed(event)
|
403
|
+
node = @controller.model.get_nearest_node(event.x, event.y)
|
404
|
+
@controller.model.click(node)
|
405
|
+
end
|
406
|
+
|
407
|
+
def mouseDragged(event)
|
408
|
+
if (!@node)
|
409
|
+
@node = @controller.model.get_nearest_node(event.x, event.y)
|
410
|
+
location = @controller.model.layout[@node]
|
411
|
+
@delta_x = location.x - event.x
|
412
|
+
@delta_y = location.y - event.y
|
413
|
+
end
|
414
|
+
@controller.model.set_location(@node, (event.x + @delta_x), (event.y + @delta_y))
|
415
|
+
|
416
|
+
end
|
417
|
+
|
418
|
+
def mouseReleased(event)
|
419
|
+
@controller.model.unclick(@node)
|
420
|
+
@controller.view.remove_mouse_listener(self)
|
421
|
+
@controller.view.remove_mouse_motion_listener(self)
|
422
|
+
end
|
423
|
+
end
|
424
|
+
|
425
|
+
class DelNodeMouseListener
|
426
|
+
include AppMouseListener
|
427
|
+
|
428
|
+
def initialize(controller)
|
429
|
+
@controller = controller
|
430
|
+
end
|
431
|
+
|
432
|
+
def mousePressed(event)
|
433
|
+
@node = @controller.model.get_nearest_node(event.x, event.y)
|
434
|
+
@controller.model.click(@node)
|
435
|
+
end
|
436
|
+
|
437
|
+
def mouseReleased(event)
|
438
|
+
if @node
|
439
|
+
@controller.model.unclick(@node)
|
440
|
+
@controller.model.del_node(@node)
|
441
|
+
end
|
442
|
+
@controller.view.remove_mouse_listener(self)
|
443
|
+
end
|
444
|
+
|
445
|
+
end
|
446
|
+
|
447
|
+
class ShortestTreeMouseListener
|
448
|
+
include AppMouseListener
|
449
|
+
|
450
|
+
def initialize(controller)
|
451
|
+
@controller = controller
|
452
|
+
end
|
453
|
+
|
454
|
+
def mousePressed(event)
|
455
|
+
@node = @controller.model.get_nearest_node(event.x, event.y)
|
456
|
+
@controller.model.click(@node)
|
457
|
+
end
|
458
|
+
|
459
|
+
def mouseReleased(event)
|
460
|
+
if @node
|
461
|
+
@controller.model.unclick(@node)
|
462
|
+
@controller.model.dspt(@node)
|
463
|
+
end
|
464
|
+
@controller.view.remove_mouse_listener(self)
|
465
|
+
end
|
466
|
+
|
467
|
+
end
|
468
|
+
|
469
|
+
class ShortestPathMouseListener
|
470
|
+
include AppMouseListener
|
471
|
+
|
472
|
+
def initialize(controller)
|
473
|
+
@controller = controller
|
474
|
+
end
|
475
|
+
|
476
|
+
def mousePressed(event)
|
477
|
+
if (!@first)
|
478
|
+
@first = @controller.model.get_nearest_node(event.x, event.y)
|
479
|
+
@controller.model.click(@first)
|
480
|
+
else
|
481
|
+
@second = @controller.model.get_nearest_node(event.x, event.y)
|
482
|
+
@controller.model.click(@second)
|
483
|
+
@controller.model.click(@first)
|
484
|
+
end
|
485
|
+
end
|
486
|
+
|
487
|
+
def mouseReleased(event)
|
488
|
+
if @first
|
489
|
+
@controller.model.unclick(@first)
|
490
|
+
if @second
|
491
|
+
@controller.model.unclick(@second)
|
492
|
+
@controller.view.remove_mouse_listener(self)
|
493
|
+
@controller.model.dsp(@first, @second)
|
494
|
+
end
|
495
|
+
end
|
496
|
+
end
|
497
|
+
|
498
|
+
end
|
499
|
+
|
500
|
+
class LayoutActionListener
|
501
|
+
def initialize(controller)
|
502
|
+
@controller = controller
|
503
|
+
end
|
504
|
+
|
505
|
+
def actionPerformed(event)
|
506
|
+
return_value = event.getSource.getText
|
507
|
+
a = return_value.split
|
508
|
+
case a[0].downcase
|
509
|
+
when 'random'
|
510
|
+
@controller.set_random_layout
|
511
|
+
when 'circle'
|
512
|
+
@controller.set_circle_layout
|
513
|
+
when 'fr'
|
514
|
+
@controller.set_fr_layout
|
515
|
+
when 'isom'
|
516
|
+
@controller.set_isom_layout
|
517
|
+
when 'kk'
|
518
|
+
@controller.set_kk_layout
|
519
|
+
when 'collapse'
|
520
|
+
@controller.set_collapse_layout
|
521
|
+
when 'morph'
|
522
|
+
@controller.set_morph_layout(a[1])
|
523
|
+
else
|
524
|
+
puts "Wrong Argument"
|
525
|
+
end
|
526
|
+
@controller.view.remove_text_field
|
527
|
+
@controller.view.remove_info_panel
|
528
|
+
end
|
529
|
+
end
|
530
|
+
|
531
|
+
class GenerateGraphActionListener
|
532
|
+
def initialize(controller)
|
533
|
+
@controller = controller
|
534
|
+
end
|
535
|
+
|
536
|
+
def actionPerformed(event)
|
537
|
+
return_value = event.source.getText
|
538
|
+
a = return_value.split
|
539
|
+
if a.size == 2 and a[1].to_i != 0
|
540
|
+
case a[0].downcase
|
541
|
+
when "random"
|
542
|
+
@controller.set_random(a[1].to_i)
|
543
|
+
when "bintree"
|
544
|
+
@controller.set_bintree(a[1].to_i)
|
545
|
+
when "ring"
|
546
|
+
@controller.set_ring(a[1].to_i)
|
547
|
+
when "connected"
|
548
|
+
@controller.set_connected(a[1].to_i)
|
549
|
+
when "mesh"
|
550
|
+
@controller.set_mesh(a[1].to_i)
|
551
|
+
when "linear"
|
552
|
+
@controller.set_linear(a[1].to_i)
|
553
|
+
else
|
554
|
+
puts "No Generator #{a[0]}"
|
555
|
+
end
|
556
|
+
else
|
557
|
+
puts "Wrong Syntax"
|
558
|
+
end
|
559
|
+
@controller.view.remove_text_field
|
560
|
+
@controller.view.remove_info_panel
|
561
|
+
end
|
562
|
+
|
563
|
+
end
|
564
|
+
|
565
|
+
class GraphTypeActionListener
|
566
|
+
def initialize(controller)
|
567
|
+
@controller = controller
|
568
|
+
end
|
569
|
+
|
570
|
+
def actionPerformed(event)
|
571
|
+
return_value = event.getSource.getText
|
572
|
+
case return_value.downcase
|
573
|
+
when 'directed'
|
574
|
+
@controller.model.set_directed
|
575
|
+
when 'undirected'
|
576
|
+
@controller.model.set_undirected
|
577
|
+
else
|
578
|
+
puts "Wrong Argument"
|
579
|
+
end
|
580
|
+
@controller.view.remove_text_field
|
581
|
+
@controller.view.remove_info_panel
|
582
|
+
end
|
583
|
+
end
|
584
|
+
|