termkit 0.0.0 → 0.1.0

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.
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