canis 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
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