gitoe 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +18 -0
- data/.gitmodules +3 -0
- data/Gemfile +7 -0
- data/Gemfile.lock +91 -0
- data/Guardfile +8 -0
- data/LICENSE.txt +22 -0
- data/README.md +30 -0
- data/Rakefile +35 -0
- data/Rules +47 -0
- data/bin/gitoe +36 -0
- data/content/gitoe-draw.coffee +342 -0
- data/content/gitoe-repo.coffee +546 -0
- data/content/gitoe.coffee +182 -0
- data/content/index.haml +71 -0
- data/content/jquery/jquery-1.9.1.min.js +5 -0
- data/content/jquery/jquery.scrollTo.min.js +7 -0
- data/content/raphael-min.js +10 -0
- data/content/reset.sass +46 -0
- data/content/style.sass +109 -0
- data/gitoe.gemspec +34 -0
- data/lib/gitoe.rb +16 -0
- data/lib/gitoe/httpserver/public/gitoe-draw.js +399 -0
- data/lib/gitoe/httpserver/public/gitoe-repo.js +618 -0
- data/lib/gitoe/httpserver/public/gitoe.js +249 -0
- data/lib/gitoe/httpserver/public/index.html +49 -0
- data/lib/gitoe/httpserver/public/jquery/jquery-1.9.1.min.js +5 -0
- data/lib/gitoe/httpserver/public/jquery/jquery.scrollTo.min.js +7 -0
- data/lib/gitoe/httpserver/public/raphael-min.js +10 -0
- data/lib/gitoe/httpserver/public/reset.css +45 -0
- data/lib/gitoe/httpserver/public/style.css +106 -0
- data/lib/gitoe/httpserver/repos.rb +71 -0
- data/lib/gitoe/httpserver/static.rb +17 -0
- data/lib/gitoe/repo/repo.rb +174 -0
- data/lib/gitoe/repo/rugged.rb +121 -0
- data/lib/gitoe/version.rb +3 -0
- data/nanoc.yaml +77 -0
- data/test/test.rb +9 -0
- data/todo.markdown +16 -0
- data/vendor/jquery-1.9.1.min.js +5 -0
- data/vendor/raphael-min.js +10 -0
- metadata +239 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: bd353bb620692d7931c95fbb0366c0d7bbc5b97b
|
4
|
+
data.tar.gz: 6ca8600540cc942b042f01026d6b1dd0eef5de3e
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 575750976f459a8a4ed8934673b1ce143eb85fa29559a98b37ce2a7245cb78498bca2743dd8c278f6174ad0f6db59bd4bad826a829446c9c81eaf2030be2794c
|
7
|
+
data.tar.gz: febe71ce3581f012e283c8b4882e84b97a4cfee96442aafec73ae81d75fb0dd9a9c6516fcad07275b52d1bf52862049df4f0ac47473535e86f352784df04f94a
|
data/.gitignore
ADDED
data/.gitmodules
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,91 @@
|
|
1
|
+
GIT
|
2
|
+
remote: https://github.com/nanoc/guard-nanoc.git
|
3
|
+
revision: ab6d3a3f19b73b37b1cff8e12bfae527bf63c98b
|
4
|
+
specs:
|
5
|
+
guard-nanoc (1.0.0b1)
|
6
|
+
|
7
|
+
PATH
|
8
|
+
remote: .
|
9
|
+
specs:
|
10
|
+
gitoe (0.1.0)
|
11
|
+
activesupport
|
12
|
+
rugged
|
13
|
+
sinatra
|
14
|
+
|
15
|
+
GEM
|
16
|
+
remote: http://rubygems.org/
|
17
|
+
specs:
|
18
|
+
activesupport (3.2.13)
|
19
|
+
i18n (= 0.6.1)
|
20
|
+
multi_json (~> 1.0)
|
21
|
+
coderay (1.0.9)
|
22
|
+
coffee-script (2.2.0)
|
23
|
+
coffee-script-source
|
24
|
+
execjs
|
25
|
+
coffee-script-source (1.6.2)
|
26
|
+
colored (1.2)
|
27
|
+
cri (2.3.0)
|
28
|
+
colored (>= 1.2)
|
29
|
+
daemons (1.1.9)
|
30
|
+
eventmachine (1.0.3)
|
31
|
+
execjs (1.4.0)
|
32
|
+
multi_json (~> 1.0)
|
33
|
+
ffi (1.8.1)
|
34
|
+
formatador (0.2.4)
|
35
|
+
guard (1.8.0)
|
36
|
+
formatador (>= 0.2.4)
|
37
|
+
listen (>= 1.0.0)
|
38
|
+
lumberjack (>= 1.0.2)
|
39
|
+
pry (>= 0.9.10)
|
40
|
+
thor (>= 0.14.6)
|
41
|
+
haml (4.0.2)
|
42
|
+
tilt
|
43
|
+
i18n (0.6.1)
|
44
|
+
listen (1.0.2)
|
45
|
+
rb-fsevent (>= 0.9.3)
|
46
|
+
rb-inotify (>= 0.9)
|
47
|
+
rb-kqueue (>= 0.2)
|
48
|
+
lumberjack (1.0.3)
|
49
|
+
method_source (0.8.1)
|
50
|
+
multi_json (1.7.2)
|
51
|
+
nanoc (3.6.3)
|
52
|
+
cri (~> 2.3)
|
53
|
+
pry (0.9.12.1)
|
54
|
+
coderay (~> 1.0.5)
|
55
|
+
method_source (~> 0.8)
|
56
|
+
slop (~> 3.4)
|
57
|
+
rack (1.5.2)
|
58
|
+
rack-protection (1.5.0)
|
59
|
+
rack
|
60
|
+
rb-fsevent (0.9.3)
|
61
|
+
rb-inotify (0.9.0)
|
62
|
+
ffi (>= 0.5.0)
|
63
|
+
rb-kqueue (0.2.0)
|
64
|
+
ffi (>= 0.5.0)
|
65
|
+
rugged (0.16.0)
|
66
|
+
sass (3.2.7)
|
67
|
+
sinatra (1.4.2)
|
68
|
+
rack (~> 1.5, >= 1.5.2)
|
69
|
+
rack-protection (~> 1.4)
|
70
|
+
tilt (~> 1.3, >= 1.3.4)
|
71
|
+
slop (3.4.4)
|
72
|
+
thin (1.5.1)
|
73
|
+
daemons (>= 1.0.9)
|
74
|
+
eventmachine (>= 0.12.6)
|
75
|
+
rack (>= 1.0.0)
|
76
|
+
thor (0.18.1)
|
77
|
+
tilt (1.3.7)
|
78
|
+
|
79
|
+
PLATFORMS
|
80
|
+
ruby
|
81
|
+
|
82
|
+
DEPENDENCIES
|
83
|
+
coffee-script
|
84
|
+
gitoe!
|
85
|
+
guard
|
86
|
+
guard-nanoc!
|
87
|
+
haml
|
88
|
+
nanoc (>= 3.6.3)
|
89
|
+
pry
|
90
|
+
sass
|
91
|
+
thin
|
data/Guardfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Wang Guan
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
gitoe
|
2
|
+
=====
|
3
|
+
#### a local web app, to show local git changes
|
4
|
+
|
5
|
+
gitoe (hopefully) reveals:
|
6
|
+
|
7
|
+
- what did I do ?
|
8
|
+
- what did this `git command` do ?
|
9
|
+
|
10
|
+
gitoe can be installed by:
|
11
|
+
|
12
|
+
$ gem install gitoe
|
13
|
+
|
14
|
+
And running
|
15
|
+
|
16
|
+
$ gitoe
|
17
|
+
|
18
|
+
starts a local web server at [127.0.0.1:12345](127.0.0.1:12345).
|
19
|
+
|
20
|
+
it works by
|
21
|
+
- dig commits out of the repo, and visualize them
|
22
|
+
- look into `.git/logs/refs`, and parses `reflog` message.
|
23
|
+
|
24
|
+
gitoe is build upon
|
25
|
+
|
26
|
+
- [sinatra](www.sinatrarb.com)
|
27
|
+
- [libgit2/rugged](https://github.com/libgit2/rugged)
|
28
|
+
- [jquery](http://jquery.com/)
|
29
|
+
- [Raphaël](http://raphaeljs.com/)
|
30
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
2
|
+
require "rake/testtask"
|
3
|
+
|
4
|
+
Rake::TestTask.new do |t|
|
5
|
+
t.pattern = "test/test*.rb"
|
6
|
+
end
|
7
|
+
|
8
|
+
desc "gitoe (development)"
|
9
|
+
task :run do
|
10
|
+
ENV["RACK_ENV"] = "development"
|
11
|
+
sh "bundle exec gitoe"
|
12
|
+
end
|
13
|
+
|
14
|
+
desc "gitoe (production)"
|
15
|
+
task :production do
|
16
|
+
ENV["RACK_ENV"] = "production"
|
17
|
+
sh "bundle exec gitoe"
|
18
|
+
end
|
19
|
+
|
20
|
+
desc "watch and re-compile with guard"
|
21
|
+
task :guard do
|
22
|
+
sh "bundle exec guard"
|
23
|
+
end
|
24
|
+
|
25
|
+
desc "watch and re-compile with guard"
|
26
|
+
task :watch do
|
27
|
+
sh "bundle exec nanoc watch"
|
28
|
+
end
|
29
|
+
|
30
|
+
desc "compile with nanoc"
|
31
|
+
task :compile do
|
32
|
+
sh "bundle exec nanoc"
|
33
|
+
end
|
34
|
+
|
35
|
+
task :default => :run
|
data/Rules
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# A few helpful tips about the Rules file:
|
4
|
+
#
|
5
|
+
# * The string given to #compile and #route are matching patterns for
|
6
|
+
# identifiers--not for paths. Therefore, you can’t match on extension.
|
7
|
+
#
|
8
|
+
# * The order of rules is important: for each item, only the first matching
|
9
|
+
# rule is applied.
|
10
|
+
#
|
11
|
+
# * Item identifiers start and end with a slash (e.g. “/about/” for the file
|
12
|
+
# “content/about.html”). To select all children, grandchildren, … of an
|
13
|
+
# item, use the pattern “/about/*/”; “/about/*” will also select the parent,
|
14
|
+
# because “*” matches zero or more characters.
|
15
|
+
|
16
|
+
compile '*' do
|
17
|
+
if item.binary?
|
18
|
+
# don’t filter binary items
|
19
|
+
else
|
20
|
+
case item[:extension]
|
21
|
+
when "haml"
|
22
|
+
filter :haml
|
23
|
+
when "coffee"
|
24
|
+
filter :coffeescript
|
25
|
+
when "sass"
|
26
|
+
filter :sass
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
route '*' do
|
32
|
+
if item.binary?
|
33
|
+
# Write item with identifier /foo/ to /foo.ext
|
34
|
+
item.identifier.chop + '.' + item[:extension]
|
35
|
+
else
|
36
|
+
case item[ :extension ]
|
37
|
+
when "coffee"
|
38
|
+
item.identifier.chop + '.js'
|
39
|
+
when 'sass'
|
40
|
+
item.identifier.chop + '.css'
|
41
|
+
when 'haml'
|
42
|
+
item.identifier + 'index.html'
|
43
|
+
else
|
44
|
+
raise "not sure what to do with #{item}"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
data/bin/gitoe
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "sinatra"
|
4
|
+
require "gitoe/httpserver/static"
|
5
|
+
require "gitoe/httpserver/repos"
|
6
|
+
|
7
|
+
handler = \
|
8
|
+
begin
|
9
|
+
require "thin"
|
10
|
+
Rack::Handler::Thin
|
11
|
+
rescue LoadError
|
12
|
+
false
|
13
|
+
end ||
|
14
|
+
|
15
|
+
handler ||= \
|
16
|
+
begin
|
17
|
+
require "mongrel"
|
18
|
+
Rack::Handler::Mongrel
|
19
|
+
rescue LoadError
|
20
|
+
false
|
21
|
+
end
|
22
|
+
|
23
|
+
handler ||= \
|
24
|
+
Rack::Handler::WEBrick
|
25
|
+
|
26
|
+
root = Rack::Builder.new do
|
27
|
+
|
28
|
+
use Rack::Deflater
|
29
|
+
map "/repo" do run Gitoe::HTTPServer::Repos.new end
|
30
|
+
map "/" do run Gitoe::HTTPServer::Static.new end
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
root = Rack::Reloader.new(root,cooldown=0) if ENV["RACK_ENV"]=="development"
|
35
|
+
|
36
|
+
handler.run root, Port: 12345
|
@@ -0,0 +1,342 @@
|
|
1
|
+
$ = jQuery or throw "demand jQuery"
|
2
|
+
R = Raphael or throw "demand Raphael"
|
3
|
+
|
4
|
+
clone = (obj)->
|
5
|
+
$.extend({},obj)
|
6
|
+
|
7
|
+
strcmp = exports.gitoe.strcmp
|
8
|
+
|
9
|
+
class DAGLayout
|
10
|
+
# TODO a more proper placement, for
|
11
|
+
# - less crossing
|
12
|
+
# - better looking
|
13
|
+
# want: referencing to position of parents
|
14
|
+
# XXX Maybe re-layouting
|
15
|
+
# XXX Maybe layout in layer --- how to trigger?
|
16
|
+
constructor: (@cb)->
|
17
|
+
# @cb:
|
18
|
+
# draw_node : ( id, layer, pos )
|
19
|
+
|
20
|
+
# topo
|
21
|
+
@children = {} # { id: [ children ] }
|
22
|
+
@parents = {} # { id: [ parents ] }
|
23
|
+
|
24
|
+
# layout
|
25
|
+
@layer = {} # { id : layer }
|
26
|
+
@position = {} # { id : position }
|
27
|
+
@grid = {} # { layer: [ position: id ] }
|
28
|
+
@layer_span = {}# { id : num }
|
29
|
+
|
30
|
+
add_node: ( id, parents )=>
|
31
|
+
@topo( id, parents )
|
32
|
+
|
33
|
+
layer = @get_layer( id )
|
34
|
+
layer_span = @get_layer_span( id, layer )
|
35
|
+
pos = @get_position( id, layer, layer_span )
|
36
|
+
|
37
|
+
@cb.draw_node( id, layer, pos, layer_span )
|
38
|
+
|
39
|
+
get_layer: (id)->
|
40
|
+
# layer = 1 + max[ parent.layer ]
|
41
|
+
layer = 0
|
42
|
+
for parent in @parents[id]
|
43
|
+
parent_layer = @layer[parent]
|
44
|
+
if parent_layer >= layer
|
45
|
+
layer = parent_layer + 1
|
46
|
+
@grid[layer] ?= []
|
47
|
+
@layer[id] = layer
|
48
|
+
|
49
|
+
get_layer_span: (id, layer)->
|
50
|
+
layer_span = 1
|
51
|
+
l = {}
|
52
|
+
for parent in @parents[id]
|
53
|
+
parent_layer = @layer[parent]
|
54
|
+
l[parent] = parent_layer
|
55
|
+
if parent_layer + layer_span < layer
|
56
|
+
layer_span = layer - parent_layer
|
57
|
+
@layer_span[id] = layer_span
|
58
|
+
|
59
|
+
get_position: ( id, layer, layer_span )->
|
60
|
+
# first appropriate position,
|
61
|
+
# which
|
62
|
+
# - is not occupied, on layers of <id> and all fake nodes
|
63
|
+
# - TODO and preferably shorten edges
|
64
|
+
position = -1
|
65
|
+
conflict = true
|
66
|
+
layers_to_check = [(layer-layer_span+1)..(layer)]
|
67
|
+
grid = @grid
|
68
|
+
while conflict
|
69
|
+
position++
|
70
|
+
occupied = layers_to_check.filter (layer)->
|
71
|
+
grid[layer][position]
|
72
|
+
if occupied.length == 0
|
73
|
+
conflict = false
|
74
|
+
|
75
|
+
for layer in layers_to_check
|
76
|
+
@grid[layer][position] = id
|
77
|
+
@position[id] = position
|
78
|
+
|
79
|
+
topo: ( id, parents )->
|
80
|
+
for parent in parents
|
81
|
+
cs = @children[ parent ]
|
82
|
+
if cs is undefined
|
83
|
+
throw "<#{id}> added before its parent <#{parent}>"
|
84
|
+
else
|
85
|
+
cs.push id
|
86
|
+
if @parents[id]
|
87
|
+
throw "<#{id}> added more than once"
|
88
|
+
@parents[id] = parents
|
89
|
+
@children[id] = []
|
90
|
+
|
91
|
+
query_parents: (id)=>
|
92
|
+
@parents[id]
|
93
|
+
query_pos: (id)=>{
|
94
|
+
layer : @layer[id]
|
95
|
+
pos : @position[id]
|
96
|
+
}
|
97
|
+
|
98
|
+
class GitoeCanvas
|
99
|
+
@CONST : {
|
100
|
+
canvas: {
|
101
|
+
width : 300
|
102
|
+
height: 100
|
103
|
+
}
|
104
|
+
padding_left: 60
|
105
|
+
padding_top : 40
|
106
|
+
outer_width : 80
|
107
|
+
outer_height: 60
|
108
|
+
commit_handle: 10
|
109
|
+
box: {
|
110
|
+
width: 60
|
111
|
+
height: 20
|
112
|
+
radius: 2
|
113
|
+
attr: {
|
114
|
+
fill : "lightblue"
|
115
|
+
"stroke-width": 2
|
116
|
+
stroke : 'black'
|
117
|
+
}
|
118
|
+
}
|
119
|
+
text_attr: {
|
120
|
+
'font-family': 'mono'
|
121
|
+
'font-size': 12
|
122
|
+
}
|
123
|
+
path_style: {
|
124
|
+
fill: 'pink'
|
125
|
+
strokeWidth: 3
|
126
|
+
}
|
127
|
+
}
|
128
|
+
|
129
|
+
constructor: ( id_container )->
|
130
|
+
@dag = new DAGLayout(draw_node: @draw_async)
|
131
|
+
@constant = clone GitoeCanvas.CONST
|
132
|
+
@init_canvas( id_container )
|
133
|
+
@objs = {} # { sha1 : canvas objs }
|
134
|
+
@div = $("##{id_container}")
|
135
|
+
@ref_objs = {} # { ref_name: canvas objs }
|
136
|
+
|
137
|
+
add_commit_async: (commit)=>
|
138
|
+
setTimeout( @add_commit.bind( @, commit ) , 500 )
|
139
|
+
|
140
|
+
draw_async: (sha1, layer, pos)=>
|
141
|
+
setTimeout( @draw.bind( @,sha1,layer,pos ), 0 )
|
142
|
+
|
143
|
+
# TODO
|
144
|
+
# ref_on_commit: (ref)
|
145
|
+
# ref_on_ref: (ref1, ref2)
|
146
|
+
# destroy: (sha1)->
|
147
|
+
# remove sha1's canvas objects
|
148
|
+
|
149
|
+
add_commit: (commit)->
|
150
|
+
@dag.add_node( commit.sha1, commit.parents )
|
151
|
+
|
152
|
+
draw: (sha1,layer,pos)->
|
153
|
+
if @objs[sha1]
|
154
|
+
@destroy sha1
|
155
|
+
coord = @commit_coord(layer, pos)
|
156
|
+
parents = @dag.query_parents(sha1).map( @dag.query_pos )
|
157
|
+
|
158
|
+
commit_box = @draw_commit_box(coord)
|
159
|
+
text = @draw_commit_text(coord, sha1)
|
160
|
+
paths = @draw_paths(coord, parents)
|
161
|
+
need_focus = !!(@canvas_inc_height(coord.top) + @canvas_inc_width(coord.left) )
|
162
|
+
if need_focus
|
163
|
+
@focus(coord)
|
164
|
+
@objs[sha1] = {
|
165
|
+
commit_box : commit_box
|
166
|
+
text : text
|
167
|
+
paths : paths
|
168
|
+
}
|
169
|
+
|
170
|
+
clear_refs: ()->
|
171
|
+
for ref_name, objs of @ref_objs
|
172
|
+
for obj in (objs or [])
|
173
|
+
obj.remove()
|
174
|
+
|
175
|
+
set_refs: (refs)->
|
176
|
+
# refs: { ref_name : [ sha1 ] }
|
177
|
+
@clear_refs()
|
178
|
+
# console.log refs
|
179
|
+
|
180
|
+
ref_names_sorted = Object.keys(refs).sort( strcmp )
|
181
|
+
|
182
|
+
for ref_name, ref_index in ref_names_sorted
|
183
|
+
@ref_objs[ ref_name ] = @draw_ref( ref_index, ref_name, refs[ref_name] )
|
184
|
+
|
185
|
+
draw_ref: ( ref_index, ref_name, sha1s )-> # [ canvas objs ]
|
186
|
+
# TODO
|
187
|
+
sha1_last = sha1s[ sha1s.length - 1 ]
|
188
|
+
p_last = @dag.query_pos(sha1_last)
|
189
|
+
coord_last = @commit_coord( p_last.layer, p_last.pos )
|
190
|
+
@focus @commit_coord( p_last.layer, p_last.pos )
|
191
|
+
[
|
192
|
+
@draw_ref_path( ref_index, sha1s )
|
193
|
+
@draw_ref_text( ref_index, coord_last, ref_name )
|
194
|
+
@draw_ref_pointer( ref_index, coord_last )
|
195
|
+
]
|
196
|
+
|
197
|
+
draw_ref_pointer: ( ref_index, p_last )->
|
198
|
+
@canvas.path(
|
199
|
+
|
200
|
+
)
|
201
|
+
|
202
|
+
draw_ref_text: ( ref_index, coord_last, ref_name )->
|
203
|
+
console.log ref_index, coord_last, ref_name
|
204
|
+
@canvas.text(
|
205
|
+
coord_last.left + @constant.box.width + (0.6+ref_index) * 30 + ref_name.length * 2,
|
206
|
+
coord_last.top + @constant.box.height * (1+ref_index)/3
|
207
|
+
ref_name
|
208
|
+
).attr(@constant.text_attr)
|
209
|
+
|
210
|
+
draw_ref_path: ( ref_index, sha1s, textbox_width )-> # path
|
211
|
+
command_array = []
|
212
|
+
current = prev = null
|
213
|
+
handler_top = @constant.box.height * (1+ref_index)/3
|
214
|
+
for sha1, index in sha1s
|
215
|
+
prev = current
|
216
|
+
current = @commit_coord_by_sha1( sha1 )
|
217
|
+
if index is 0 # first comit in path
|
218
|
+
command_array.push [
|
219
|
+
'M'
|
220
|
+
current.left + @constant.box.width
|
221
|
+
current.top + handler_top
|
222
|
+
]...
|
223
|
+
else
|
224
|
+
command_array.push [
|
225
|
+
'Q'
|
226
|
+
50 + ref_index * 40 + @constant.box.width + Math.max(current.left, prev.left)
|
227
|
+
(current.top + prev.top)/2 + handler_top - 35
|
228
|
+
@constant.box.width + current.left
|
229
|
+
current.top + handler_top
|
230
|
+
]...
|
231
|
+
@canvas.path(command_array.join(' '))
|
232
|
+
|
233
|
+
commit_coord: (layer,pos)->{
|
234
|
+
# left and top coord of commit-box
|
235
|
+
left: (@constant.padding_left + @constant.outer_width * pos)
|
236
|
+
top : (@constant.padding_top + @constant.outer_height * layer)
|
237
|
+
}
|
238
|
+
commit_coord_by_sha1: (sha1)->
|
239
|
+
p = @dag.query_pos(sha1)
|
240
|
+
@commit_coord( p.layer, p.pos )
|
241
|
+
|
242
|
+
draw_commit_box: (coord)->
|
243
|
+
@canvas.rect(
|
244
|
+
coord.left,
|
245
|
+
coord.top,
|
246
|
+
@constant.box.width,
|
247
|
+
@constant.box.height,
|
248
|
+
@constant.box.radius
|
249
|
+
).attr(@constant.box.attr)
|
250
|
+
|
251
|
+
draw_commit_text: (coord,sha1)->
|
252
|
+
@canvas.text(
|
253
|
+
coord.left + @constant.box.width/2,
|
254
|
+
coord.top + @constant.box.height/2,
|
255
|
+
sha1[0..7]
|
256
|
+
).attr(@constant.text_attr)
|
257
|
+
|
258
|
+
draw_paths: (coord, parents_pos)->
|
259
|
+
paths = []
|
260
|
+
start = [
|
261
|
+
'M'
|
262
|
+
coord.left + @constant.box.width/2
|
263
|
+
coord.top
|
264
|
+
].join ' '
|
265
|
+
for p in parents_pos
|
266
|
+
coord_p = @commit_coord(p.layer, p.pos)
|
267
|
+
path_command = @path_command(coord, coord_p)
|
268
|
+
if path_command
|
269
|
+
paths.push @canvas.path( start + path_command )
|
270
|
+
paths
|
271
|
+
|
272
|
+
path_command: ( coord, coord_p )->
|
273
|
+
# command string to draw path,
|
274
|
+
# ref http://www.w3.org/TR/SVG/paths.html#PathDataLinetoCommands
|
275
|
+
bottom_of_parent = {
|
276
|
+
x: coord_p.left + @constant.box.width / 2
|
277
|
+
y: coord_p.top + @constant.box.height
|
278
|
+
}
|
279
|
+
top_of_highest_fake_node = {
|
280
|
+
x: coord.left + @constant.box.width / 2
|
281
|
+
y: coord_p.top + @constant.outer_height
|
282
|
+
}
|
283
|
+
if coord.left == coord_p.left # same column
|
284
|
+
[
|
285
|
+
'L'
|
286
|
+
bottom_of_parent.x
|
287
|
+
bottom_of_parent.y
|
288
|
+
].join ' '
|
289
|
+
else
|
290
|
+
vertical_distance = @constant.outer_height - @constant.box.height
|
291
|
+
ratio = 0.3
|
292
|
+
[
|
293
|
+
'L'
|
294
|
+
top_of_highest_fake_node.x
|
295
|
+
top_of_highest_fake_node.y
|
296
|
+
'C'
|
297
|
+
top_of_highest_fake_node.x
|
298
|
+
@mix( top_of_highest_fake_node.y, bottom_of_parent.y , ratio)
|
299
|
+
bottom_of_parent.x
|
300
|
+
@mix( top_of_highest_fake_node.y, bottom_of_parent.y , 1-ratio)
|
301
|
+
bottom_of_parent.x
|
302
|
+
bottom_of_parent.y
|
303
|
+
].join ' '
|
304
|
+
|
305
|
+
mix: (a,b,ratio)->
|
306
|
+
a*ratio + b*(1-ratio)
|
307
|
+
focus: (coord)->
|
308
|
+
@div.scrollTo {
|
309
|
+
left: coord.left - 200
|
310
|
+
top : coord.top - 200
|
311
|
+
}
|
312
|
+
|
313
|
+
init_canvas: (id_canvas)->
|
314
|
+
@canvas_size = clone @constant.canvas
|
315
|
+
@canvas = R(
|
316
|
+
id_canvas,
|
317
|
+
@canvas_size.width,
|
318
|
+
@canvas_size.height
|
319
|
+
)
|
320
|
+
|
321
|
+
canvas_inc_width: (left)->
|
322
|
+
if left + @constant.outer_width > @canvas_size.width
|
323
|
+
@canvas_size.width += 1*@constant.outer_width
|
324
|
+
@canvas_resize()
|
325
|
+
true
|
326
|
+
else
|
327
|
+
false
|
328
|
+
canvas_inc_height: (top)->
|
329
|
+
if top + @constant.outer_height > @canvas_size.height
|
330
|
+
@canvas_size.height += 1*@constant.outer_height
|
331
|
+
@canvas_resize()
|
332
|
+
true
|
333
|
+
else
|
334
|
+
false
|
335
|
+
canvas_resize: ()->
|
336
|
+
@canvas.setSize(
|
337
|
+
@canvas_size.width,
|
338
|
+
@canvas_size.height,
|
339
|
+
)
|
340
|
+
|
341
|
+
@exports ?= { gitoe: {} }
|
342
|
+
exports.gitoe.GitoeCanvas = GitoeCanvas
|