termkit 0.0.0 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/.ackrc +7 -0
  3. data/.editorconfig +14 -0
  4. data/.gitignore +5 -1
  5. data/.gitlab-ci.yml +70 -0
  6. data/.rdoc_options +21 -0
  7. data/.travis.yml +5 -1
  8. data/Gemfile +8 -0
  9. data/Makefile +16 -1
  10. data/Makefile.common +5 -3
  11. data/README.md +2 -1
  12. data/bin/build_info.sh +22 -0
  13. data/bin/dev +10 -0
  14. data/lib/termkit.rb +32 -0
  15. data/lib/termkit/app/app.rb +61 -0
  16. data/lib/termkit/app/app_curses.rb +159 -0
  17. data/lib/termkit/app/app_ui.rb +153 -0
  18. data/lib/termkit/controller/controller.rb +58 -0
  19. data/lib/termkit/controller/controller_app.rb +22 -0
  20. data/lib/termkit/controller/controller_view.rb +28 -0
  21. data/lib/termkit/event/event.rb +14 -0
  22. data/lib/termkit/event/event_key.rb +33 -0
  23. data/lib/termkit/event/event_later.rb +16 -0
  24. data/lib/termkit/exception/exception_event_key_unhandled.rb +11 -0
  25. data/lib/termkit/exception/exception_event_unhandled.rb +18 -0
  26. data/lib/termkit/exception/exception_initialized_not_class_parent.rb +17 -0
  27. data/lib/termkit/exception/exception_std.rb +11 -0
  28. data/lib/termkit/misc/curses_color.rb +23 -0
  29. data/lib/termkit/misc/point.rb +114 -0
  30. data/lib/termkit/misc/rect.rb +116 -0
  31. data/lib/termkit/misc/size.rb +29 -0
  32. data/lib/termkit/model/model.rb +16 -0
  33. data/lib/termkit/version.rb +5 -4
  34. data/lib/termkit/view/content_view.rb +59 -0
  35. data/lib/termkit/view/content_view_clear.rb +20 -0
  36. data/lib/termkit/view/row_grid_view.rb +12 -0
  37. data/lib/termkit/view/view.rb +825 -0
  38. data/lib/termkit/view/view_grid.rb +12 -0
  39. data/lib/termkit/view/view_table.rb +296 -0
  40. data/lib/termkit/view/view_table_cell.rb +38 -0
  41. data/lib/termkit/view/view_text.rb +63 -0
  42. data/termkit.gemspec +8 -0
  43. data/termkit.sublime-project +2 -2
  44. metadata +120 -5
  45. data/tests/ts_all.rb +0 -1
@@ -0,0 +1,12 @@
1
+
2
+ module TheFox
3
+ module TermKit
4
+
5
+ ##
6
+ # Holds rows of a View's Grid.
7
+ class ViewGrid < Hash
8
+
9
+ end
10
+
11
+ end
12
+ end
@@ -0,0 +1,296 @@
1
+
2
+ # require 'pry'
3
+
4
+ module TheFox
5
+ module TermKit
6
+
7
+ ##
8
+ # View sub-class.
9
+ #
10
+ # Provides functionalities to show data in a scrollable table.
11
+ class TableView < View
12
+
13
+ attr_reader :header
14
+ attr_reader :header_height
15
+ # attr_reader :table
16
+ attr_reader :data
17
+ attr_reader :cells
18
+ attr_reader :cells_height_total
19
+ attr_accessor :highlighted_cell
20
+ attr_reader :cursor_position
21
+ attr_reader :cursor_position_old
22
+ attr_reader :cursor_direction
23
+ attr_reader :page_begin
24
+ attr_reader :page_end
25
+ attr_reader :page_height
26
+ attr_reader :page_direction
27
+
28
+ def initialize(name = nil)
29
+ # puts "TableView initialize '#{name.inspect}'"
30
+ super(name)
31
+
32
+ @header = nil
33
+ @header_height = 0
34
+ @data = []
35
+ @cells = []
36
+ @cells_height_total = 0
37
+ @highlighted_cell = nil
38
+
39
+ @cursor_position = 0
40
+ @cursor_position_old = 0
41
+ @cursor_direction = 0
42
+
43
+ @page_begin = 0
44
+ @page_end = 0
45
+ @page_height = 0
46
+ @page_direction = 0
47
+ @page_range = nil
48
+
49
+ @needs_refresh = true
50
+
51
+ @table = View.new("#{@name}_table")
52
+ @table.is_visible = true
53
+ add_subview(@table)
54
+ end
55
+
56
+ def size=(size)
57
+ super(size)
58
+
59
+ @needs_refresh = true
60
+ calc_page_height
61
+ calc_cursor
62
+ calc_page
63
+ end
64
+
65
+ def header=(header)
66
+ unless header.is_a?(View)
67
+ raise ArgumentError, "Argument is not a View -- #{header.class} given"
68
+ end
69
+
70
+ unless @header.nil?
71
+ remove_subview(@header)
72
+ end
73
+
74
+ @header = header
75
+ unless header.nil?
76
+ @header_height = @header.height
77
+
78
+ add_subview(@header)
79
+ end
80
+
81
+ @table.position = Point.new(0, @header_height)
82
+
83
+ @needs_refresh = true
84
+ calc_page_height
85
+ end
86
+
87
+ def remove_header
88
+ @header = nil
89
+ @header_height = 0
90
+
91
+ @table.position = Point.new(0, @header_height)
92
+
93
+ @needs_refresh = true
94
+ calc_page_height
95
+ end
96
+
97
+ def data=(data)
98
+ if !data.is_a?(Array)
99
+ raise ArgumentError, "Argument is not a Array -- #{data.class} given"
100
+ end
101
+
102
+ @data = data
103
+ @cells = []
104
+
105
+ cell_n = 0
106
+ y_pos = 0
107
+ @data.each do |row|
108
+ cell = nil
109
+
110
+ row_name = "row_#{cell_n}"
111
+
112
+ case row
113
+ when String
114
+ text_view = TextView.new(row, "text_#{row_name}")
115
+ text_view.is_visible = true
116
+ # text_view.text = row
117
+
118
+ cell = CellTableView.new(text_view, "cell_#{row_name}")
119
+ when CellTableView
120
+ cell = row
121
+ else
122
+ raise NotImplementedError, "Class '#{row.class}' not implemented yet"
123
+ end
124
+
125
+ @cells.push(cell)
126
+
127
+ #cell.is_visible = false
128
+ cell.is_visible = true
129
+ #cell.position = Point.new(0, y_pos)
130
+ #@table.add_subview(cell)
131
+
132
+ y_pos += cell.height
133
+ cell_n += 1
134
+ end
135
+
136
+ @cells_height_total = y_pos
137
+
138
+ @needs_refresh = true
139
+ calc_page_height
140
+ calc_cursor
141
+ calc_page
142
+ end
143
+
144
+ def cursor_position=(cursor_position)
145
+ @cursor_position_old = @cursor_position
146
+ @cursor_position = cursor_position
147
+
148
+ @needs_refresh = true
149
+ calc_cursor
150
+ calc_page
151
+ end
152
+
153
+ def cursor_up
154
+ self.cursor_position = @cursor_position - 1
155
+ end
156
+
157
+ def cursor_down
158
+ self.cursor_position = @cursor_position + 1
159
+ end
160
+
161
+ def is_cursor_at_bottom?
162
+ @cursor_position == @cells_height_total - 1
163
+ end
164
+
165
+ def render(area = nil)
166
+ puts "#{@name} -- render r?=#{@needs_refresh ? 'Y' : 'N'}"
167
+ if @needs_refresh
168
+ refresh
169
+ end
170
+
171
+ super(area)
172
+ end
173
+
174
+ def refresh
175
+ new_page_range = Range.new(@page_begin, @page_end)
176
+
177
+ affected_cells = @cells[new_page_range]
178
+
179
+ y_pos = 0
180
+ cell_n = 0
181
+ affected_cells.each do |cell|
182
+ highlighted = @cursor_position == (cell_n + @page_begin)
183
+
184
+ # puts "#{@name} -- [+] #{cell} n=#{cell_n} y=#{y_pos} h=#{highlighted ? 'Y' : 'N'}/#{cell.highlighted ? 'Y' : 'N'}"
185
+ cell.highlighted = highlighted
186
+
187
+ if highlighted
188
+ @highlighted_cell = cell
189
+ end
190
+
191
+ # cell.size = Size.new(@size.width, nil)
192
+
193
+ # puts "#{@name} -- [+] #{cell} y=#{y_pos} position"
194
+ cell.position = Point.new(0, y_pos)
195
+
196
+ unless @table.is_subview?(cell)
197
+ # puts "#{@name} -- [+] #{cell} y=#{y_pos} add_subview"
198
+ @table.add_subview(cell)
199
+ end
200
+
201
+ # puts "#{@name} -- [+] #{cell} y=#{y_pos} END"
202
+
203
+ y_pos += cell.height
204
+ cell_n += 1
205
+ end
206
+
207
+ # Hide out-of-scope cell(s) here. In the best case it's only ONE cell that will
208
+ # be hidden. If you scroll down the top cell will be hidden, if you scroll up
209
+ # only the bottom cell will be hidden.
210
+ (@cells - affected_cells).select{ |cell| cell.is_visible? }.each do |cell|
211
+ # puts "#{@name} -- [-] #{cell} y=#{cell.position.y} r?=#{cell.needs_rendering? ? 'Y' : 'N'}"
212
+ @table.remove_subview(cell)
213
+ end
214
+
215
+ @page_range = new_page_range
216
+ @needs_refresh = false
217
+ end
218
+
219
+ private
220
+
221
+ def calc_page_height
222
+ # puts "calc_page_height"
223
+ if @size.nil? || @size.height.nil?
224
+ # puts "calc_page_height size is nil"
225
+ @page_height = @cells_height_total
226
+ # puts "#{@name} -- calc_page_height A #{@page_height}"
227
+ else
228
+ @page_height = @size.height - @header_height
229
+ # puts "#{@name} -- calc_page_height B #{@page_height} = #{@size.height} - #{@header_height}"
230
+ end
231
+ end
232
+
233
+ def calc_cursor
234
+ # puts "calc_cursor @cursor_position '#{@cursor_position}' '#{@cells_height_total}'"
235
+
236
+ if @cursor_position > @cells_height_total - 1
237
+ @cursor_position = @cells_height_total - 1
238
+ # puts "#{@name} -- calc_cursor A #{@cursor_position}"
239
+ end
240
+ if @cursor_position < 0
241
+ @cursor_position = 0
242
+ # puts "#{@name} -- calc_cursor B #{@cursor_position}"
243
+ end
244
+
245
+ # -1 up
246
+ # 0 unchanged
247
+ # +1 down
248
+ if @cursor_position == @cursor_position_old
249
+ @cursor_direction = 0
250
+ elsif @cursor_position > @cursor_position_old
251
+ @cursor_direction = 1
252
+ else
253
+ @cursor_direction = -1
254
+ end
255
+
256
+ # puts "cursor n='#{@cursor_position}' o='#{@cursor_position_old}' d='#{cursor_direction}'"
257
+ end
258
+
259
+ def calc_page
260
+ # -1 up
261
+ # 0 unchanged
262
+ # +1 down
263
+ if @cursor_position > @page_end
264
+ @page_direction = 1
265
+ elsif @cursor_position < @page_begin
266
+ @page_direction = -1
267
+ else
268
+ @page_direction = 0
269
+ end
270
+
271
+ if @page_direction == 1
272
+ @page_begin = @cursor_position - @page_height + 1
273
+ # puts "#{@name} -- calc_page page_begin A #{page_begin} = #{@cursor_position} - #{@page_height} + 1"
274
+ elsif @page_direction == -1
275
+ @page_begin = @cursor_position
276
+ # puts "#{@name} -- calc_page page_begin B #{page_begin}"
277
+ end
278
+
279
+ page_begin_max = @cells_height_total - @page_height
280
+ if page_begin_max < 0
281
+ page_begin_max = 0
282
+ end
283
+ if @page_begin > page_begin_max
284
+ @page_begin = page_begin_max
285
+ # puts "#{@name} -- calc_page page_begin C #{page_begin}"
286
+ end
287
+
288
+ @page_end = @page_begin + @page_height - 1
289
+
290
+ # puts "#{@name} -- calc_page b=#{@page_begin} e=#{@page_end} h=#{@page_height} d=#{@page_direction}"
291
+ end
292
+
293
+ end
294
+
295
+ end
296
+ end
@@ -0,0 +1,38 @@
1
+
2
+ module TheFox
3
+ module TermKit
4
+
5
+ class CellTableView < View
6
+
7
+ attr_reader :highlighted
8
+
9
+ def initialize(subview, name = nil)
10
+ name = "CellTableView_#{object_id}" if name.nil?
11
+ super(name)
12
+
13
+ @highlighted = false
14
+
15
+ add_subview(subview)
16
+ end
17
+
18
+ def highlighted=(highlighted)
19
+ if @highlighted != highlighted
20
+ if highlighted
21
+ foreground_color = :color_white
22
+ background_color = :color_blue
23
+ end
24
+ @grid_cache.each do |y_pos, row|
25
+ row.each do |x_pos, content|
26
+ content.foreground_color = foreground_color
27
+ content.background_color = background_color
28
+ end
29
+ end
30
+ end
31
+
32
+ @highlighted = highlighted
33
+ end
34
+
35
+ end
36
+
37
+ end
38
+ end
@@ -0,0 +1,63 @@
1
+
2
+ module TheFox
3
+ module TermKit
4
+
5
+ ##
6
+ # Basic Text View class. View sub-class.
7
+ #
8
+ # Provides functionalities to draw text.
9
+ class TextView < View
10
+
11
+ def initialize(text = nil, name = nil)
12
+ name = "TextView_#{object_id}" if name.nil?
13
+ super(name)
14
+
15
+ #puts 'TextView->initialize'
16
+
17
+ if !text.nil?
18
+ draw_text(text)
19
+ end
20
+ end
21
+
22
+ def text=(text)
23
+ if !text.is_a?(String)
24
+ raise ArgumentError, "Argument is not a String -- #{text.class} given"
25
+ end
26
+
27
+ draw_text(text)
28
+ end
29
+
30
+ def draw_text(text)
31
+ changes = 0
32
+
33
+ y_pos = 0
34
+ text.split("\n").each do |line|
35
+ x_pos = 0
36
+
37
+ # puts "line '#{line}'"
38
+
39
+ line.split('').each do |char|
40
+ # puts "c '#{char}'"
41
+
42
+ content = draw_point(Point.new(x_pos, y_pos), char)
43
+ if !content.nil?
44
+ changes += 1
45
+ end
46
+
47
+ # puts " c '#{char}' #{changes}"
48
+
49
+ x_pos += 1
50
+ end
51
+
52
+ # puts "line '#{line}', changes #{changes}"
53
+
54
+ y_pos += 1
55
+ end
56
+
57
+ changes
58
+ end
59
+
60
+ end
61
+
62
+ end
63
+ end
@@ -21,5 +21,13 @@ Gem::Specification.new do |spec|
21
21
  spec.require_paths = ['lib']
22
22
  spec.required_ruby_version = '>=2.1.0'
23
23
 
24
+ spec.add_development_dependency 'pry', '~>0.10'
24
25
  spec.add_development_dependency 'minitest', '~>5.8'
26
+ spec.add_development_dependency 'simplecov', '~>0.12'
27
+ spec.add_development_dependency 'simplecov-phpunit', '~>1.0'
28
+
29
+ spec.add_dependency 'curses', '~>1.0'
30
+ spec.add_dependency 'uuid', '~>2.3'
31
+
32
+ spec.add_dependency 'thefox-ext', '~>1.4'
25
33
  end
@@ -3,8 +3,8 @@
3
3
  {
4
4
  "path": ".",
5
5
  "name": "TermKit",
6
- "folder_exclude_patterns": [ ],
6
+ "folder_exclude_patterns": [ "coverage", "doc", "releases" ],
7
7
  "file_exclude_patterns": [ ]
8
8
  }
9
9
  ]
10
- }
10
+ }
metadata CHANGED
@@ -1,15 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: termkit
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.0
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Christian Mayer
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-07-24 00:00:00.000000000 Z
11
+ date: 2016-10-27 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: pry
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '0.10'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '0.10'
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: minitest
15
29
  requirement: !ruby/object:Gem::Requirement
@@ -24,24 +38,125 @@ dependencies:
24
38
  - - "~>"
25
39
  - !ruby/object:Gem::Version
26
40
  version: '5.8'
41
+ - !ruby/object:Gem::Dependency
42
+ name: simplecov
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '0.12'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '0.12'
55
+ - !ruby/object:Gem::Dependency
56
+ name: simplecov-phpunit
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '1.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '1.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: curses
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '1.0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '1.0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: uuid
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '2.3'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '2.3'
97
+ - !ruby/object:Gem::Dependency
98
+ name: thefox-ext
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '1.4'
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '1.4'
27
111
  description: A Model-View-Controller Framework for Terminal applications.
28
112
  email: christian@fox21.at
29
113
  executables: []
30
114
  extensions: []
31
115
  extra_rdoc_files: []
32
116
  files:
117
+ - ".ackrc"
118
+ - ".editorconfig"
33
119
  - ".gitignore"
120
+ - ".gitlab-ci.yml"
121
+ - ".rdoc_options"
34
122
  - ".travis.yml"
35
123
  - Gemfile
36
124
  - Makefile
37
125
  - Makefile.common
38
126
  - README.md
127
+ - bin/build_info.sh
128
+ - bin/dev
39
129
  - lib/termkit.rb
130
+ - lib/termkit/app/app.rb
131
+ - lib/termkit/app/app_curses.rb
132
+ - lib/termkit/app/app_ui.rb
133
+ - lib/termkit/controller/controller.rb
134
+ - lib/termkit/controller/controller_app.rb
135
+ - lib/termkit/controller/controller_view.rb
136
+ - lib/termkit/event/event.rb
137
+ - lib/termkit/event/event_key.rb
138
+ - lib/termkit/event/event_later.rb
139
+ - lib/termkit/exception/exception_event_key_unhandled.rb
140
+ - lib/termkit/exception/exception_event_unhandled.rb
141
+ - lib/termkit/exception/exception_initialized_not_class_parent.rb
142
+ - lib/termkit/exception/exception_std.rb
143
+ - lib/termkit/misc/curses_color.rb
144
+ - lib/termkit/misc/point.rb
145
+ - lib/termkit/misc/rect.rb
146
+ - lib/termkit/misc/size.rb
147
+ - lib/termkit/model/model.rb
40
148
  - lib/termkit/version.rb
149
+ - lib/termkit/view/content_view.rb
150
+ - lib/termkit/view/content_view_clear.rb
151
+ - lib/termkit/view/row_grid_view.rb
152
+ - lib/termkit/view/view.rb
153
+ - lib/termkit/view/view_grid.rb
154
+ - lib/termkit/view/view_table.rb
155
+ - lib/termkit/view/view_table_cell.rb
156
+ - lib/termkit/view/view_text.rb
41
157
  - termkit.gemspec
42
158
  - termkit.sublime-project
43
- - tests/ts_all.rb
44
- homepage: https://github.com/TheFox/termkit
159
+ homepage: https://termkit.fox21.at/
45
160
  licenses:
46
161
  - GPL-3.0
47
162
  metadata: {}
@@ -61,7 +176,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
61
176
  version: '0'
62
177
  requirements: []
63
178
  rubyforge_project:
64
- rubygems_version: 2.5.1
179
+ rubygems_version: 2.6.7
65
180
  signing_key:
66
181
  specification_version: 4
67
182
  summary: Terminal Model-View-Controller Framework