1#
2#  tkextlib/blt/vector.rb
3#                               by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
4#
5
6require 'tk'
7require 'tkextlib/blt.rb'
8
9module Tk::BLT
10  class Vector < TkVariable
11    TkCommandNames = ['::blt::vector'.freeze].freeze
12
13    def self.create(*args)
14      tk_call('::blt::vector', 'create', *args)
15    end
16
17    def self.destroy(*args)
18      tk_call('::blt::vector', 'destroy', *args)
19    end
20
21    def self.expr(expression)
22      tk_call('::blt::vector', 'expr', expression)
23    end
24
25    def self.names(pat=None)
26      list = simplelist(tk_call('::blt::vector', 'names', pat))
27      TkVar_ID_TBL.mutex.synchronize{
28        list.collect{|name|
29          if TkVar_ID_TBL[name]
30            TkVar_ID_TBL[name]
31          elsif name[0..1] == '::' && TkVar_ID_TBL[name[2..-1]]
32            TkVar_ID_TBL[name[2..-1]]
33          else
34            name
35          end
36        }
37      }
38    end
39
40    ####################################
41
42    def initialize(size=nil, keys={})
43      if size.kind_of?(Hash)
44        keys = size
45        size = nil
46      end
47      if size.kind_of?(Array)
48        # [first, last]
49        size = size.join(':')
50      end
51      if size
52        @id = TkCore::INTERP._invoke('::blt::vector', 'create',
53                                     "#auto(#{size})", *hash_kv(keys))
54      else
55        @id = TkCore::INTERP._invoke('::blt::vector', 'create',
56                                     "#auto", *hash_kv(keys))
57      end
58
59      TkVar_ID_TBL.mutex.synchronize{
60        TkVar_ID_TBL[@id] = self
61      }
62
63      @def_default = false
64      @default_val = nil
65
66      @trace_var  = nil
67      @trace_elem = nil
68      @trace_opts = nil
69
70      # teach Tk-ip that @id is global var
71      TkCore::INTERP._invoke_without_enc('global', @id)
72    end
73
74    def destroy
75      tk_call('::blt::vector', 'destroy', @id)
76    end
77
78    def inspect
79      '#<Tk::BLT::Vector: ' + @id + '>'
80    end
81
82    def to_s
83      @id
84    end
85
86    def *(item)
87      list(tk_call(@id, '*', item))
88    end
89
90    def +(item)
91      list(tk_call(@id, '+', item))
92    end
93
94    def -(item)
95      list(tk_call(@id, '-', item))
96    end
97
98    def /(item)
99      list(tk_call(@id, '/', item))
100    end
101
102    def append(*vectors)
103      tk_call(@id, 'append', *vectors)
104    end
105
106    def binread(channel, len=None, keys={})
107      if len.kind_of?(Hash)
108        keys = len
109        len = None
110      end
111      keys = _symbolkey2str(keys)
112      keys['swap'] = None if keys.delete('swap')
113      tk_call(@id, 'binread', channel, len, keys)
114    end
115
116    def clear()
117      tk_call(@id, 'clear')
118      self
119    end
120
121    def delete(*indices)
122      tk_call(@id, 'delete', *indices)
123      self
124    end
125
126    def dup_vector(vec)
127      tk_call(@id, 'dup', vec)
128      self
129    end
130
131    def expr(expression)
132      tk_call(@id, 'expr', expression)
133      self
134    end
135
136    def index(idx, val=None)
137      number(tk_call(@id, 'index', idx, val))
138    end
139
140    def [](idx)
141      index(idx)
142    end
143
144    def []=(idx, val)
145      index(idx, val)
146    end
147
148    def length()
149      number(tk_call(@id, 'length'))
150    end
151
152    def length=(size)
153      number(tk_call(@id, 'length', size))
154    end
155
156    def merge(*vectors)
157      tk_call(@id, 'merge', *vectors)
158      self
159    end
160
161    def normalize(vec=None)
162      tk_call(@id, 'normalize', vec)
163      self
164    end
165
166    def notify(keyword)
167      tk_call(@id, 'notify', keyword)
168      self
169    end
170
171    def offset()
172      number(tk_call(@id, 'offset'))
173    end
174
175    def offset=(val)
176      number(tk_call(@id, 'offset', val))
177    end
178
179    def random()
180      tk_call(@id, 'random')
181    end
182
183    def populate(vector, density=None)
184      tk_call(@id, 'populate', vector, density)
185      self
186    end
187
188    def range(first, last=None)
189      list(tk_call(@id, 'range', first, last))
190    end
191
192    def search(val1, val2=None)
193      list(tk_call(@id, 'search', val1, val2))
194    end
195
196    def set(item)
197      tk_call(@id, 'set', item)
198      self
199    end
200
201    def seq(start, finish=None, step=None)
202      tk_call(@id, 'seq', start, finish, step)
203      self
204    end
205
206    def sort(*vectors)
207      tk_call(@id, 'sort', *vectors)
208      self
209    end
210
211    def sort_reverse(*vectors)
212      tk_call(@id, 'sort', '-reverse', *vectors)
213      self
214    end
215
216    def split(*vectors)
217      tk_call(@id, 'split', *vectors)
218      self
219    end
220
221    def variable(var)
222      tk_call(@id, 'variable', var)
223      self
224    end
225  end
226
227  class VectorAccess < Vector
228    def self.new(name)
229      TkVar_ID_TBL.mutex.synchronize{
230        if TkVar_ID_TBL[name]
231          TkVar_ID_TBL[name]
232        else
233          (obj = self.allocate).instance_eval{
234            initialize(name)
235            TkVar_ID_TBL[@id] = self
236          }
237          obj
238        end
239      }
240    end
241
242    def initialize(vec_name)
243      @id = vec_name
244
245      @def_default = false
246      @default_val = nil
247
248      @trace_var  = nil
249      @trace_elem = nil
250      @trace_opts = nil
251
252      # teach Tk-ip that @id is global var
253      TkCore::INTERP._invoke_without_enc('global', @id)
254    end
255  end
256end
257