canis 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.
Files changed (134) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +45 -0
  3. data/CHANGES +52 -0
  4. data/Gemfile +4 -0
  5. data/LICENSE.txt +22 -0
  6. data/README.md +24 -0
  7. data/Rakefile +2 -0
  8. data/canis.gemspec +25 -0
  9. data/examples/alpmenu.rb +46 -0
  10. data/examples/app.sample +19 -0
  11. data/examples/appemail.rb +191 -0
  12. data/examples/atree.rb +105 -0
  13. data/examples/bline.rb +181 -0
  14. data/examples/common/devel.rb +319 -0
  15. data/examples/common/file.rb +93 -0
  16. data/examples/data/README.markdown +9 -0
  17. data/examples/data/brew.txt +38 -0
  18. data/examples/data/color.2 +37 -0
  19. data/examples/data/gemlist.txt +59 -0
  20. data/examples/data/lotr.txt +12 -0
  21. data/examples/data/ports.txt +136 -0
  22. data/examples/data/table.txt +37 -0
  23. data/examples/data/tasks.csv +88 -0
  24. data/examples/data/tasks.txt +27 -0
  25. data/examples/data/todo.txt +16 -0
  26. data/examples/data/todocsv.csv +28 -0
  27. data/examples/data/unix1.txt +21 -0
  28. data/examples/data/unix2.txt +11 -0
  29. data/examples/dbdemo.rb +506 -0
  30. data/examples/dirtree.rb +177 -0
  31. data/examples/newtabbedwindow.rb +100 -0
  32. data/examples/newtesttabp.rb +92 -0
  33. data/examples/tabular.rb +212 -0
  34. data/examples/tasks.rb +179 -0
  35. data/examples/term2.rb +88 -0
  36. data/examples/testbuttons.rb +307 -0
  37. data/examples/testcombo.rb +102 -0
  38. data/examples/testdb.rb +182 -0
  39. data/examples/testfields.rb +208 -0
  40. data/examples/testflowlayout.rb +43 -0
  41. data/examples/testkeypress.rb +98 -0
  42. data/examples/testlistbox.rb +187 -0
  43. data/examples/testlistbox1.rb +199 -0
  44. data/examples/testmessagebox.rb +144 -0
  45. data/examples/testprogress.rb +116 -0
  46. data/examples/testree.rb +107 -0
  47. data/examples/testsplitlayout.rb +53 -0
  48. data/examples/testsplitlayout1.rb +49 -0
  49. data/examples/teststacklayout.rb +48 -0
  50. data/examples/testwsshortcuts.rb +68 -0
  51. data/examples/testwsshortcuts2.rb +129 -0
  52. data/lib/canis.rb +16 -0
  53. data/lib/canis/core/docs/index.txt +104 -0
  54. data/lib/canis/core/docs/list.txt +16 -0
  55. data/lib/canis/core/docs/style_help.yml +34 -0
  56. data/lib/canis/core/docs/tabbedpane.txt +15 -0
  57. data/lib/canis/core/docs/table.txt +31 -0
  58. data/lib/canis/core/docs/textpad.txt +48 -0
  59. data/lib/canis/core/docs/tree.txt +23 -0
  60. data/lib/canis/core/include/.DS_Store +0 -0
  61. data/lib/canis/core/include/action.rb +83 -0
  62. data/lib/canis/core/include/actionmanager.rb +49 -0
  63. data/lib/canis/core/include/appmethods.rb +179 -0
  64. data/lib/canis/core/include/bordertitle.rb +49 -0
  65. data/lib/canis/core/include/canisparser.rb +100 -0
  66. data/lib/canis/core/include/colorparser.rb +437 -0
  67. data/lib/canis/core/include/defaultfilerenderer.rb +64 -0
  68. data/lib/canis/core/include/io.rb +320 -0
  69. data/lib/canis/core/include/layouts/SplitLayout.rb +161 -0
  70. data/lib/canis/core/include/layouts/abstractlayout.rb +213 -0
  71. data/lib/canis/core/include/layouts/flowlayout.rb +104 -0
  72. data/lib/canis/core/include/layouts/stacklayout.rb +109 -0
  73. data/lib/canis/core/include/listbindings.rb +89 -0
  74. data/lib/canis/core/include/listeditable.rb +319 -0
  75. data/lib/canis/core/include/listoperations.rb +61 -0
  76. data/lib/canis/core/include/listselectionmodel.rb +388 -0
  77. data/lib/canis/core/include/multibuffer.rb +173 -0
  78. data/lib/canis/core/include/ractionevent.rb +73 -0
  79. data/lib/canis/core/include/rchangeevent.rb +27 -0
  80. data/lib/canis/core/include/rhistory.rb +95 -0
  81. data/lib/canis/core/include/rinputdataevent.rb +47 -0
  82. data/lib/canis/core/include/textdocument.rb +111 -0
  83. data/lib/canis/core/include/vieditable.rb +175 -0
  84. data/lib/canis/core/include/widgetmenu.rb +66 -0
  85. data/lib/canis/core/system/colormap.rb +165 -0
  86. data/lib/canis/core/system/keydefs.rb +32 -0
  87. data/lib/canis/core/system/ncurses.rb +237 -0
  88. data/lib/canis/core/system/panel.rb +129 -0
  89. data/lib/canis/core/system/window.rb +1081 -0
  90. data/lib/canis/core/util/ansiparser.rb +119 -0
  91. data/lib/canis/core/util/app.rb +696 -0
  92. data/lib/canis/core/util/basestack.rb +412 -0
  93. data/lib/canis/core/util/defaultcolorparser.rb +84 -0
  94. data/lib/canis/core/util/extras/README +5 -0
  95. data/lib/canis/core/util/extras/bottomline.rb +1815 -0
  96. data/lib/canis/core/util/extras/padreader.rb +192 -0
  97. data/lib/canis/core/util/focusmanager.rb +31 -0
  98. data/lib/canis/core/util/helpmanager.rb +160 -0
  99. data/lib/canis/core/util/oldwidgetshortcuts.rb +304 -0
  100. data/lib/canis/core/util/promptmenu.rb +235 -0
  101. data/lib/canis/core/util/rcommandwindow.rb +933 -0
  102. data/lib/canis/core/util/rdialogs.rb +520 -0
  103. data/lib/canis/core/util/textutils.rb +74 -0
  104. data/lib/canis/core/util/viewer.rb +238 -0
  105. data/lib/canis/core/util/widgetshortcuts.rb +508 -0
  106. data/lib/canis/core/widgets/applicationheader.rb +103 -0
  107. data/lib/canis/core/widgets/box.rb +58 -0
  108. data/lib/canis/core/widgets/divider.rb +310 -0
  109. data/lib/canis/core/widgets/extras/README.md +12 -0
  110. data/lib/canis/core/widgets/extras/rtextarea.rb +960 -0
  111. data/lib/canis/core/widgets/extras/stackflow.rb +474 -0
  112. data/lib/canis/core/widgets/keylabelprinter.rb +194 -0
  113. data/lib/canis/core/widgets/listbox.rb +326 -0
  114. data/lib/canis/core/widgets/listfooter.rb +86 -0
  115. data/lib/canis/core/widgets/rcombo.rb +210 -0
  116. data/lib/canis/core/widgets/rcontainer.rb +415 -0
  117. data/lib/canis/core/widgets/rlink.rb +30 -0
  118. data/lib/canis/core/widgets/rmenu.rb +970 -0
  119. data/lib/canis/core/widgets/rmenulink.rb +30 -0
  120. data/lib/canis/core/widgets/rmessagebox.rb +400 -0
  121. data/lib/canis/core/widgets/rprogress.rb +118 -0
  122. data/lib/canis/core/widgets/rtabbedpane.rb +631 -0
  123. data/lib/canis/core/widgets/rtabbedwindow.rb +70 -0
  124. data/lib/canis/core/widgets/rwidget.rb +3634 -0
  125. data/lib/canis/core/widgets/scrollbar.rb +147 -0
  126. data/lib/canis/core/widgets/statusline.rb +113 -0
  127. data/lib/canis/core/widgets/table.rb +1072 -0
  128. data/lib/canis/core/widgets/tabular.rb +264 -0
  129. data/lib/canis/core/widgets/textpad.rb +1674 -0
  130. data/lib/canis/core/widgets/tree.rb +690 -0
  131. data/lib/canis/core/widgets/tree/treecellrenderer.rb +150 -0
  132. data/lib/canis/core/widgets/tree/treemodel.rb +432 -0
  133. data/lib/canis/version.rb +3 -0
  134. metadata +229 -0
@@ -0,0 +1,173 @@
1
+ require 'canis/core/util/promptmenu'
2
+ module Canis
3
+ # this module makes it possible for a textview to maintain multiple buffers
4
+ # The first buffer has been placed using set_content(lines, config).
5
+ # After this, additional buffers mst be supplied with add_content text, config.
6
+ # Also, please note that after you call set_content the first time, you must call
7
+ # add_content so the buffer can be accessed while cycling. will try to fix this.
8
+ # (I don't want to touch textview, would prefer not to write a decorator).
9
+
10
+ # TODO ?? allow setting of a limit, so in some cases where we keep adding
11
+ # programatically, the
12
+ # TODO: maintain cursor and line number so user can revert to same point. this will have to be
13
+ # updated by buffer_next and others.
14
+ # Done: need to be able to set multiple file names. which are read in only when
15
+ # buffer is accessed. filename to be maintained and used as title.
16
+ # == CHANGE:
17
+ # allow filename to be sent, rather than array. Array was very limiting since it
18
+ # did not have a name to list or goto a buffer with. Also, now we can add file names that
19
+ # are read only if the buffer is selected.
20
+ module MultiBuffers
21
+ extend self
22
+
23
+ # add content to buffers of a textview
24
+ # @param [Array] text, or String (filename)
25
+ # @param [Hash] options, typically :content_type => :ansi or :tmux, and :title
26
+ def add_content text, config={}
27
+ unless @_buffers
28
+ bind_key(?\M-n, :buffer_next)
29
+ bind_key(?\M-p, :buffer_prev)
30
+ bind_key(KEY_BACKSPACE, :buffer_prev) # backspace, already hardcoded in textview !
31
+ bind_key(?:, :buffer_menu)
32
+ end
33
+ @_buffers ||= []
34
+ @_buffers_conf ||= []
35
+ @_buffers << text
36
+ if text.is_a? String
37
+ config[:filename] = text
38
+ config[:title] ||= text
39
+ end
40
+ @_buffers_conf << config
41
+ @_buffer_ctr ||= 0
42
+ $log.debug "XXX: HELP adding text #{@_buffers.size} "
43
+ end
44
+
45
+ # supply an array of files to the multibuffer. These will be read
46
+ # as the user presses next or last etc.
47
+ def add_files filearray, config={}
48
+ filearray.each do |e| add_content(e, config.dup); end
49
+ end
50
+
51
+ # display next buffer
52
+ def buffer_next
53
+ buffer_update_info
54
+ @_buffer_ctr += 1
55
+ x = @_buffer_ctr
56
+ l = @_buffers[x]
57
+ if l
58
+ populate_buffer_from_filename x
59
+ else
60
+ @_buffer_ctr = 0
61
+ end
62
+ set_content @_buffers[@_buffer_ctr], @_buffers_conf[@_buffer_ctr]
63
+ buffer_update_position
64
+ end
65
+ def populate_buffer_from_filename x
66
+ l = @_buffers[x]
67
+ if l
68
+ if l.is_a? String
69
+ if File.directory? l
70
+ Dir.chdir(l)
71
+ arr = Dir.entries(".")
72
+ @_buffers[x] = arr
73
+ else
74
+ arr = File.open(l,"r").read.split("\n")
75
+ @_buffers[x] = arr
76
+ end
77
+ end
78
+ end
79
+ end
80
+ #
81
+ # display previous buffer if any
82
+ def buffer_prev
83
+ buffer_update_info
84
+ if @_buffer_ctr < 1
85
+ buffer_last
86
+ return
87
+ end
88
+ @_buffer_ctr -= 1 if @_buffer_ctr > 0
89
+ x = @_buffer_ctr
90
+ l = @_buffers[x]
91
+ if l
92
+ populate_buffer_from_filename x
93
+ l = @_buffers[x]
94
+ $log.debug "bp calling set_content with #{l.class} "
95
+ set_content l, @_buffers_conf[x]
96
+ buffer_update_position
97
+ end
98
+ end
99
+ def buffer_last
100
+ buffer_update_info
101
+ @_buffer_ctr = @_buffers.count - 1
102
+ x = @_buffer_ctr
103
+ l = @_buffers.last
104
+ if l
105
+ populate_buffer_from_filename x
106
+ l = @_buffers[x]
107
+ $log.debug " calling set_content with #{l.class} "
108
+ set_content l, @_buffers_conf.last
109
+ buffer_update_position
110
+ end
111
+ end
112
+ def buffer_at index
113
+ buffer_update_info
114
+ @_buffer_ctr = index
115
+ l = @_buffers[index]
116
+ if l
117
+ populate_buffer_from_filename index
118
+ l = @_buffers[index]
119
+ set_content l, @_buffers_conf[index]
120
+ buffer_update_position
121
+
122
+
123
+ end
124
+ end
125
+ # close window, a bit clever, we really don't know what the CLOSE_KEY is
126
+ def close
127
+ @graphic.ungetch(?q.ord)
128
+ end
129
+ # display a menu so user can do buffer management
130
+ # However, how can application add to these. Or disable, such as when we
131
+ # add buffer delete or buffer insert or edit
132
+ def buffer_menu
133
+ menu = PromptMenu.new self do
134
+ item :n, :buffer_next
135
+ item :p, :buffer_prev
136
+ item :b, :scroll_backward
137
+ item :f, :scroll_forward
138
+ item :l, :list_buffers
139
+ item :q, :close
140
+ submenu :m, "submenu..." do
141
+ item :p, :goto_last_position
142
+ item :r, :scroll_right
143
+ item :l, :scroll_left
144
+ end
145
+ end
146
+ menu.display_new :title => "Buffer Menu"
147
+ end
148
+ # pops up a list of buffers using titles allowing the user to select
149
+ # Based on selection, that buffer is displayed.
150
+ def list_buffers
151
+ arr = []
152
+ @_buffers_conf.each_with_index do |e, i|
153
+ t = e[:title] || "no title for #{i}"
154
+ #$log.debug " TITLE is #{e.title} , t is #{t} "
155
+ arr << t
156
+ end
157
+ ix = popuplist arr
158
+ buffer_at ix
159
+ end
160
+ def buffer_update_info
161
+ x = @_buffer_ctr || 0
162
+ @_buffers_conf[x][:current_index] = @current_index || 0
163
+ @_buffers_conf[x][:curpos] = @curpos || 0
164
+ end
165
+ def buffer_update_position
166
+ x = @_buffer_ctr || 0
167
+ ci = (@_buffers_conf[x][:current_index] || 0)
168
+ goto_line ci
169
+ @curpos = (@_buffers_conf[x][:curpos] || 0)
170
+ end
171
+
172
+ end
173
+ end
@@ -0,0 +1,73 @@
1
+ =begin
2
+ * Name: ActionEvent
3
+ * Description: Event used to notify interested parties that an action has happened on component
4
+ Usually a button press. Nothing more.
5
+ * Author: jkepler (ABCD)
6
+
7
+ --------
8
+ * Date: 2010-09-12 18:53
9
+ * License:
10
+ Same as Ruby's License (http://www.ruby-lang.org/LICENSE.txt)
11
+
12
+ =end
13
+
14
+ # Event created when state changed (as in ViewPort)
15
+ module Canis
16
+ # source - as always is the object whose event has been fired
17
+ # id - event identifier (seems redundant since we bind events often separately.
18
+ # event - is :PRESS
19
+ # action_command - command string associated with event (such as title of button that changed
20
+ ActionEvent = Struct.new(:source, :event, :action_command) do
21
+ # This should always return the most relevant text associated with this object
22
+ # so the user does not have to go through the source object's documentation.
23
+ # It should be a user-friendly string
24
+ # @return text associated with source (label of button)
25
+ def text
26
+ source.text
27
+ end
28
+
29
+ # This is similar to text and can often be just an alias.
30
+ # However, i am putting this for backward compatibility with programs
31
+ # that received the object and called it's getvalue. It is better to use text.
32
+ # @return text associated with source (label of button)
33
+ def getvalue
34
+ source.getvalue
35
+ end
36
+ end
37
+ # a derivative of Action Event for textviews
38
+ # We allow a user to press ENTER on a row and use that for processing.
39
+ # We are basically using TextView as a list in which user can scroll around
40
+ # and move cursor at will.
41
+ class TextActionEvent < ActionEvent
42
+ # current_index or line number starting 0
43
+ attr_accessor :current_index
44
+ # cursor position on the line
45
+ attr_accessor :curpos
46
+ def initialize source, event, action_command, current_index, curpos
47
+ super source, event, action_command
48
+ @current_index = current_index
49
+ @curpos = curpos
50
+ end
51
+ # the text of the line on which the user is
52
+ def text
53
+ source.current_value.to_s
54
+ end
55
+ # the word under the cursor TODO
56
+ # if its a text with pipe delim, then ??
57
+ def word_under_cursor line=text(), pos=@curpos, delim=" "
58
+ line ||= text()
59
+ pos ||= @curpos
60
+ # if pressed on a space, try to go to next word to make easier 2013-03-24
61
+ if line[pos,1] == delim
62
+ while line[pos,1] == delim
63
+ pos += 1
64
+ end
65
+ end
66
+ finish = line.index(delim, pos)
67
+ start = line.rindex(delim,pos)
68
+ finish = -1 if finish.nil?
69
+ start = 0 if start.nil?
70
+ return line[start..finish]
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,27 @@
1
+ =begin
2
+ * Name: ChangeEvent
3
+ * Description: Event used to notify interested parties that state of component has changed
4
+ * Author: jkepler (ABCD)
5
+
6
+ --------
7
+ * Date: 2010-02-26 11:32
8
+ * License:
9
+ Same as Ruby's License (http://www.ruby-lang.org/LICENSE.txt)
10
+
11
+ =end
12
+
13
+ # Event created when state changed (as in ViewPort)
14
+ module Canis
15
+ class ChangeEvent
16
+ attr_accessor :source
17
+ def initialize source
18
+ @source = source
19
+ end
20
+ def to_s
21
+ inspect
22
+ end
23
+ def inspect
24
+ "ChangeEvent #{@source}"
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,95 @@
1
+ # ----------------------------------------------------------------------------- #
2
+ # File: rhistory.rb
3
+ # Description: a module that pops up history, and then updates selected value
4
+ # This goes with Field.
5
+ # e.g.,
6
+ # field.extend(FieldHistory)
7
+ #
8
+ # The module name History was throwing up errors
9
+ # Author: jkepler http://github.com/mare-imbrium/canis/
10
+ # Date: 2011-11-27 - 18:10
11
+ # License: Same as Ruby's License (http://www.ruby-lang.org/LICENSE.txt)
12
+ # Last update: 2011-11-27 - 20:11
13
+ # ----------------------------------------------------------------------------- #
14
+ #
15
+ # supply history for this object, at least give an empty array
16
+ # widget would typically be Field,
17
+ # otherwise it should implement *text()* for getting and setting value
18
+ # and a *CHANGED* event for when user has modified a value and moved out
19
+ # You can externally set $history_key to any unused key, otherwise it is M-h
20
+ module Canis
21
+ extend self
22
+ module FieldHistory
23
+ def self.extended(obj)
24
+
25
+ obj.instance_exec {
26
+ @history ||= []
27
+ $history_key ||= ?\M-h
28
+ # ensure that the field is not overriding this in handle_key
29
+ bind_key($history_key) { _show_history }
30
+ # widget should have CHANGED event, or this will either give error, or just not work
31
+ # else please update history whenever you want a value to be retrieved
32
+ bind(:CHANGED) { @history << @text if @text && (!@history.include? @text) }
33
+ }
34
+ end
35
+
36
+ # pass the array of history values
37
+ # Trying out a change where an item can also be sent in.
38
+ # I am lost, i want the initialization to happen once.
39
+ def history arr
40
+ return @history unless arr
41
+ if arr.is_a? Array
42
+ @history = arr
43
+ else
44
+ @history << arr unless @history.include? arr
45
+ end
46
+ end
47
+ def history=(x); history(x); end
48
+
49
+ # pass in some configuration for histroy such as row and column to show popup on
50
+ def history_config config={}
51
+ @_history_config = config
52
+ end
53
+
54
+ # popup the hist
55
+ #
56
+ private
57
+ def _show_history
58
+ return unless @history
59
+ return if @history.empty?
60
+ list = @history
61
+ @_history_config ||= {}
62
+ #list = ["No history"] if @history.empty?
63
+ raise ArgumentError, "show_history got nil list" unless list
64
+ # calculate r and c
65
+ # col if fine, except for when there's a label.
66
+ wcol = 0 # taking care of when dialog uses history 2012-01-4
67
+ wcol = self.form.window.left if self.form
68
+ c = wcol + ( @field_col || @col) # this is also dependent on window coords, as in a status_window or messagebox
69
+ sz = @history.size
70
+ wrow = 0
71
+ wrow = self.form.window.top if self.form
72
+ crow = wrow + @row
73
+ # if list can be displayed above, then fit it just above
74
+ if crow > sz + 2
75
+ r = crow - sz - 2
76
+ else
77
+ # else fit it in next row
78
+ r = crow + 1
79
+ end
80
+ #r = @row - 10
81
+ #if @row < 10
82
+ #r = @row + 1
83
+ #end
84
+ r = @_history_config[:row] || r
85
+ c = @_history_config[:col] || c
86
+ ret = popuplist(list, :row => r, :col => c, :title => " History ")
87
+ if ret
88
+ self.text = list[ret]
89
+ self.set_form_col
90
+ end
91
+ @form.repaint if @form
92
+ @window.wrefresh if @window
93
+ end
94
+ end # mod History
95
+ end # mod RubyC
@@ -0,0 +1,47 @@
1
+ =begin
2
+ * Name: InputDataEvent
3
+ * Description: Event created when data modified in Field or TextEdit
4
+ * Author: jkepler (ABCD)
5
+
6
+ --------
7
+ * Date: 2008-12-24 17:27
8
+ * License:
9
+ Same as Ruby's License (http://www.ruby-lang.org/LICENSE.txt)
10
+
11
+ NOTE: this is how we used to write code in the Java days. Anyone reading this source,
12
+ this is NOT how to code in rubyland. Please see this link, for how to code such as class:
13
+ http://blog.grayproductions.net/articles/all_about_struct
14
+
15
+ =end
16
+
17
+ # Event created when data modified in Field or TextEdit
18
+ # 2008-12-24 17:54
19
+ module Canis
20
+ class InputDataEvent
21
+ attr_accessor :index0, :index1, :source, :type, :row, :text
22
+ def initialize index0, index1, source, type, row, text
23
+ @index0 = index0
24
+ @index1 = index1
25
+ @source = source
26
+ @type = type
27
+ @row = row
28
+ @text = text
29
+ end
30
+ # until now to_s was returning inspect, but to make it easy for users let us return the value
31
+ # they most expect which is the text that was changed
32
+ def to_s
33
+ inspect
34
+ end
35
+ def inspect
36
+ ## now that textarea.to_s prints content we shouldn pass it here.
37
+ #"#{@type.to_s}, #{@source}, ind0:#{@index0}, ind1:#{@index1}, row:#{@row}, text:#{@text}"
38
+ "#{@type.to_s}, ind0:#{@index0}, ind1:#{@index1}, row:#{@row}, text:#{@text}"
39
+ end
40
+ # this is so that earlier applications were getting source in the block, not an event. they
41
+ # were doing a fld.getvalue, so we must keep those apps running
42
+ # @since 1.2.0 added 2010-09-11 12:25
43
+ def getvalue
44
+ @source.getvalue
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,111 @@
1
+ # ----------------------------------------------------------------------------- #
2
+ # File: textdocument.rb
3
+ # Description: Abstracts complex text preprocessing and rendering from TextPad
4
+ # Author: j kepler http://github.com/mare-imbrium/canis/
5
+ # Date: 2014-06-25 - 12:52
6
+ # License: MIT
7
+ # Last update: 2014-07-08 13:11
8
+ # ----------------------------------------------------------------------------- #
9
+ # textdocument.rb Copyright (C) 2012-2014 j kepler
10
+
11
+ module Canis
12
+ # In an attempt to keep TextPad simple, and move complexity of complex content out of it,
13
+ # I am trying to move specialized processing and rendering to a Document class which manages the same.
14
+ # I would also like to keep content, and content_type etc together. This should percolate to multibuffers
15
+ # to.
16
+ # An application may create a TextDocument object and pass it to TextPad using the +text+ method.
17
+ # Or an app may send in a hash, which +text+ uses to create this object.
18
+ class TextDocument
19
+ attr_accessor :content_type
20
+ attr_accessor :stylesheet
21
+ # +hash+ of options passed in constructor including content_type and stylesheet
22
+ attr_accessor :options
23
+ # +text+ is the original Array<String> which contains markup of some sort
24
+ # which source will retrieve. Changes happen to this (row added, deleted, changed)
25
+ attr_accessor :text
26
+
27
+ # returns the native or transformed format of original content. +text+ gets transformed into
28
+ # native text. The renderer knows how to display native_text.
29
+ #attr_reader :native_text
30
+ def native_text
31
+ unless @native_text
32
+ preprocess_text @text
33
+ end
34
+ return @native_text
35
+ end
36
+ # specify a renderer if you do not want the DefaultRenderer to be installed.
37
+ attr_accessor :renderer
38
+ attr_reader :source
39
+
40
+ def initialize hash
41
+ @parse_required = true
42
+ @options = hash
43
+ @content_type = hash[:content_type]
44
+ @stylesheet = hash[:stylesheet]
45
+ @text = hash[:text]
46
+ $log.debug " TEXTDOCUMENT created with #{@content_type} , #{@stylesheet} "
47
+ raise "textdoc recieves nil content_type in constructor" unless @content_type
48
+ end
49
+ # declare that transformation of entire content is required. Currently called by fire_dimension_changed event
50
+ # of textpad.
51
+ def parse_required
52
+ @parse_required = true
53
+ end
54
+ # set the object that is using this textdocument (typically TextPad).
55
+ # This allows us to bind to events such as adding or deleting a row, or modification of data.
56
+ def source=(sou)
57
+ @source = sou
58
+ if @renderer
59
+ @source.renderer = @renderer
60
+ end
61
+ @source.bind :ROW_CHANGED do | o, ix| parse_line ix ; end
62
+ @source.bind :DIMENSION_CHANGED do | o, _meth| parse_required() ; end
63
+ @source.title = self.title() if self.title()
64
+ end
65
+ # if there is a content_type specfied but nothing to handle the content
66
+ # then we create a default handler.
67
+ def create_default_content_type_handler
68
+ raise "source is nil in textdocument" unless @source
69
+ require 'canis/core/include/colorparser'
70
+ # cp will take the content+type from self and select actual parser
71
+ cp = Chunks::ColorParser.new @source
72
+ @content_type_handler = cp
73
+ end
74
+ # called by textpad to do any parsing or conversion on data since a textdocument by default
75
+ # does some transformation on the content
76
+ def preprocess_text data
77
+ parse_formatted_text data
78
+ end
79
+ # transform a given line number from original content to internal format.
80
+ # Called by textpad when a line changes (update)
81
+ def parse_line(lineno)
82
+ @native_text[lineno] = @content_type_handler.parse_line( @list[lineno])
83
+ end
84
+ # This is now to be called at start when text is set,
85
+ # and whenever there is a data modification.
86
+ # This updates @native_text
87
+ # @param [Array<String>] original content sent in by user
88
+ # which may contain markup
89
+ # @param [Hash] config containing
90
+ # content_type
91
+ # stylesheet
92
+ # @return [Chunklines] content in array of chunks.
93
+ def parse_formatted_text(formatted_text, config=nil)
94
+ return unless @parse_required
95
+
96
+ unless @content_type_handler
97
+ create_default_content_type_handler
98
+ end
99
+ @parse_required = false
100
+ @native_text = @content_type_handler.parse_text formatted_text
101
+ end
102
+ # returns title of document
103
+ def title
104
+ return @options[:title]
105
+ end
106
+ # set title of document (to be displayed by textpad)
107
+ def title=(t)
108
+ @options[:title] = t
109
+ end
110
+ end
111
+ end # mod