gitoe 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +18 -0
  3. data/.gitmodules +3 -0
  4. data/Gemfile +7 -0
  5. data/Gemfile.lock +91 -0
  6. data/Guardfile +8 -0
  7. data/LICENSE.txt +22 -0
  8. data/README.md +30 -0
  9. data/Rakefile +35 -0
  10. data/Rules +47 -0
  11. data/bin/gitoe +36 -0
  12. data/content/gitoe-draw.coffee +342 -0
  13. data/content/gitoe-repo.coffee +546 -0
  14. data/content/gitoe.coffee +182 -0
  15. data/content/index.haml +71 -0
  16. data/content/jquery/jquery-1.9.1.min.js +5 -0
  17. data/content/jquery/jquery.scrollTo.min.js +7 -0
  18. data/content/raphael-min.js +10 -0
  19. data/content/reset.sass +46 -0
  20. data/content/style.sass +109 -0
  21. data/gitoe.gemspec +34 -0
  22. data/lib/gitoe.rb +16 -0
  23. data/lib/gitoe/httpserver/public/gitoe-draw.js +399 -0
  24. data/lib/gitoe/httpserver/public/gitoe-repo.js +618 -0
  25. data/lib/gitoe/httpserver/public/gitoe.js +249 -0
  26. data/lib/gitoe/httpserver/public/index.html +49 -0
  27. data/lib/gitoe/httpserver/public/jquery/jquery-1.9.1.min.js +5 -0
  28. data/lib/gitoe/httpserver/public/jquery/jquery.scrollTo.min.js +7 -0
  29. data/lib/gitoe/httpserver/public/raphael-min.js +10 -0
  30. data/lib/gitoe/httpserver/public/reset.css +45 -0
  31. data/lib/gitoe/httpserver/public/style.css +106 -0
  32. data/lib/gitoe/httpserver/repos.rb +71 -0
  33. data/lib/gitoe/httpserver/static.rb +17 -0
  34. data/lib/gitoe/repo/repo.rb +174 -0
  35. data/lib/gitoe/repo/rugged.rb +121 -0
  36. data/lib/gitoe/version.rb +3 -0
  37. data/nanoc.yaml +77 -0
  38. data/test/test.rb +9 -0
  39. data/todo.markdown +16 -0
  40. data/vendor/jquery-1.9.1.min.js +5 -0
  41. data/vendor/raphael-min.js +10 -0
  42. 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
@@ -0,0 +1,18 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ .sass-cache
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ crash.log
data/.gitmodules ADDED
@@ -0,0 +1,3 @@
1
+ [submodule "vendor/jquery.scrollTo"]
2
+ path = vendor/jquery.scrollTo
3
+ url = https://github.com/flesler/jquery.scrollTo.git
data/Gemfile ADDED
@@ -0,0 +1,7 @@
1
+ source 'http://rubygems.org'
2
+
3
+ # XXX a working version over https://github.com/guard/guard-nanoc.git
4
+ gem "guard-nanoc", :git => "https://github.com/nanoc/guard-nanoc.git"
5
+
6
+ # Specify your gem's dependencies in gitoe.gemspec
7
+ gemspec
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
@@ -0,0 +1,8 @@
1
+ # A sample Guardfile
2
+ # More info at https://github.com/guard/guard#readme
3
+
4
+ guard 'nanoc' do
5
+ watch('nanoc.yaml') # Change this to config.yaml if you use the old config file name
6
+ watch('Rules')
7
+ watch(%r{^(content)/.*$})
8
+ end
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