slithernix-cdk 0.0.1

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.
@@ -0,0 +1,475 @@
1
+ require_relative 'cdk_objs'
2
+
3
+ module CDK
4
+ class ITEMLIST < CDK::CDKOBJS
5
+ def initialize(cdkscreen, xplace, yplace, title, label, item, count,
6
+ default_item, box, shadow)
7
+ super()
8
+ parent_width = cdkscreen.window.maxx
9
+ parent_height = cdkscreen.window.maxy
10
+ field_width = 0
11
+
12
+ if !self.createList(item, count)
13
+ self.destroy
14
+ return nil
15
+ end
16
+
17
+ self.setBox(box)
18
+ box_height = (@border_size * 2) + 1
19
+
20
+ # Set some basic values of the item list
21
+ @label = ''
22
+ @label_len = 0
23
+ @label_win = nil
24
+
25
+ # Translate the label string to a chtype array
26
+ if !(label.nil?) && label.size > 0
27
+ label_len = []
28
+ @label = CDK.char2Chtype(label, label_len, [])
29
+ @label_len = label_len[0]
30
+ end
31
+
32
+ # Set the box width. Allow an extra char in field width for cursor
33
+ field_width = self.maximumFieldWidth + 1
34
+ box_width = field_width + @label_len + 2 * @border_size
35
+ box_width = self.setTitle(title, box_width)
36
+ box_height += @title_lines
37
+
38
+ # Make sure we didn't extend beyond the dimensions of the window
39
+ @box_width = [box_width, parent_width].min
40
+ @box_height = [box_height, parent_height].min
41
+ self.updateFieldWidth
42
+
43
+ # Rejustify the x and y positions if we need to.
44
+ xtmp = [xplace]
45
+ ytmp = [yplace]
46
+ CDK.alignxy(cdkscreen.window, xtmp, ytmp, box_width, box_height)
47
+ xpos = xtmp[0]
48
+ ypos = ytmp[0]
49
+
50
+ # Make the window.
51
+ @win = Curses::Window.new(box_height, box_width, ypos, xpos)
52
+ if @win.nil?
53
+ self.destroy
54
+ return nil
55
+ end
56
+
57
+ # Make the label window if there was a label.
58
+ if @label.size > 0
59
+ @label_win = @win.subwin(1, @label_len,
60
+ ypos + @border_size + @title_lines,
61
+ xpos + @border_size)
62
+
63
+ if @label_win.nil?
64
+ self.destroy
65
+ return nil
66
+ end
67
+ end
68
+
69
+ @win.keypad(true)
70
+
71
+ # Make the field window.
72
+ if !self.createFieldWin(
73
+ ypos + @border_size + @title_lines,
74
+ xpos + @label_len + @border_size)
75
+ self.destroy
76
+ return nil
77
+ end
78
+
79
+ # Set up the rest of the structure
80
+ @screen = cdkscreen
81
+ @parent = cdkscreen.window
82
+ @shadow_win = nil
83
+ @accepts_focus = true
84
+ @shadow = shadow
85
+
86
+ # Set the default item.
87
+ if default_item >= 0 && default_item < @list_size
88
+ @current_item = default_item
89
+ @default_item = default_item
90
+ else
91
+ @current_item = 0
92
+ @default_item = 0
93
+ end
94
+
95
+ # Do we want a shadow?
96
+ if shadow
97
+ @shadow_win = Curses::Window.new(box_height, box_width,
98
+ ypos + 1, xpos + 1)
99
+ if @shadow_win.nil?
100
+ self.destroy
101
+ return nil
102
+ end
103
+ end
104
+
105
+ # Register this baby.
106
+ cdkscreen.register(:ITEMLIST, self)
107
+ end
108
+
109
+ # This allows the user to play with the widget.
110
+ def activate(actions)
111
+ ret = -1
112
+
113
+ # Draw the widget.
114
+ self.draw(@box)
115
+ self.drawField(true)
116
+
117
+ if actions.nil? || actions.size == 0
118
+ input = 0
119
+
120
+ while true
121
+ input = self.getch([])
122
+
123
+ # Inject the character into the widget.
124
+ ret = self.inject(input)
125
+ if @exit_type != :EARLY_EXIT
126
+ return ret
127
+ end
128
+ end
129
+ else
130
+ # Inject each character one at a time.
131
+ actions.each do |action|
132
+ ret = self.inject(action)
133
+ if @exit_type != :EARLY_EXIT
134
+ return ret
135
+ end
136
+ end
137
+ end
138
+
139
+ # Set the exit type and exit.
140
+ self.setExitType(0)
141
+ return ret
142
+ end
143
+
144
+ # This injects a single character into the widget.
145
+ def inject(input)
146
+ pp_return = 1
147
+ ret = -1
148
+ complete = false
149
+
150
+ # Set the exit type.
151
+ self.setExitType(0)
152
+
153
+ # Draw the widget field
154
+ self.drawField(true)
155
+
156
+ # Check if there is a pre-process function to be called.
157
+ unless @pre_process_func.nil?
158
+ pp_return = @pre_process_func.call(:ITEMLIST, self,
159
+ @pre_process_data, input)
160
+ end
161
+
162
+ # Should we continue?
163
+ if pp_return != 0
164
+ # Check a predefined binding.
165
+ if self.checkBind(:ITEMLIST, input)
166
+ complete = true
167
+ else
168
+ case input
169
+ when Curses::KEY_UP, Curses::KEY_RIGHT, ' ', '+', 'n'
170
+ if @current_item < @list_size - 1
171
+ @current_item += 1
172
+ else
173
+ @current_item = 0
174
+ end
175
+ when Curses::KEY_DOWN, Curses::KEY_LEFT, '-', 'p'
176
+ if @current_item > 0
177
+ @current_item -= 1
178
+ else
179
+ @current_item = @list_size - 1
180
+ end
181
+ when 'd', 'D'
182
+ @current_item = @default_item
183
+ when '0'
184
+ @current_item = 0
185
+ when '$'
186
+ @current_item = @list_size - 1
187
+ when CDK::KEY_ESC
188
+ self.setExitType(input)
189
+ complete = true
190
+ when Curses::Error
191
+ self.setExitType(input)
192
+ complete = true
193
+ when CDK::KEY_TAB, CDK::KEY_RETURN, Curses::KEY_ENTER
194
+ self.setExitType(input)
195
+ ret = @current_item
196
+ complete = true
197
+ when CDK::REFRESH
198
+ @screen.erase
199
+ @screen.refresh
200
+ else
201
+ CDK.Beep
202
+ end
203
+ end
204
+
205
+ # Should we call a post-process?
206
+ if !complete && !(@post_process_func.nil?)
207
+ @post_process_func.call(:ITEMLIST, self, @post_process_data, input)
208
+ end
209
+ end
210
+
211
+ if !complete
212
+ self.drawField(true)
213
+ self.setExitType(0)
214
+ end
215
+
216
+ @result_data = ret
217
+ return ret
218
+ end
219
+
220
+ # This moves the itemlist field to the given location.
221
+ def move(xplace, yplace, relative, refresh_flag)
222
+ windows = [@win, @field_win, @label_win, @shadow_win]
223
+ self.move_specific(xplace, yplace, relative, refresh_flag,
224
+ windows, [])
225
+ end
226
+
227
+ # This draws the widget on the screen.
228
+ def draw(box)
229
+ # Did we ask for a shadow?
230
+ unless @shadow_win.nil?
231
+ Draw.drawShadow(@shadow_win)
232
+ end
233
+
234
+ self.drawTitle(@win)
235
+
236
+ # Draw in the label to the widget.
237
+ unless @label_win.nil?
238
+ Draw.writeChtype(@label_win, 0, 0, @label, CDK::HORIZONTAL,
239
+ 0, @label.size)
240
+ end
241
+
242
+ # Box the widget if asked.
243
+ if box
244
+ Draw.drawObjBox(@win, self)
245
+ end
246
+
247
+ @win.refresh
248
+
249
+ # Draw in the field.
250
+ self.drawField(false)
251
+ end
252
+
253
+ # This sets the background attribute of the widget
254
+ def setBKattr(attrib)
255
+ @win.wbkgd(attrib)
256
+ @field_win.wbkgd(attrib)
257
+ unless @label_win.nil?
258
+ @label_win.wbkgd(attrib)
259
+ end
260
+ end
261
+
262
+ # This function draws the contents of the field.
263
+ def drawField(highlight)
264
+ # Declare local vars.
265
+ current_item = @current_item
266
+
267
+ # Determine how much we have to draw.
268
+ len = [@item_len[current_item], @field_width].min
269
+
270
+ # Erase the field window.
271
+ @field_win.erase
272
+
273
+ # Draw in the current item in the field.
274
+ (0...len).each do |x|
275
+ c = @item[current_item][x]
276
+
277
+ if highlight
278
+ c = c.ord | Curses::A_REVERSE
279
+ end
280
+
281
+ @field_win.mvwaddch(0, x + @item_pos[current_item], c)
282
+ end
283
+
284
+ # Redraw the field window.
285
+ @field_win.refresh
286
+ end
287
+
288
+ # This function removes the widget from the screen.
289
+ def erase
290
+ if self.validCDKObject
291
+ CDK.eraseCursesWindow(@field_win)
292
+ CDK.eraseCursesWindow(@label_win)
293
+ CDK.eraseCursesWindow(@win)
294
+ CDK.eraseCursesWindow(@shadow_win)
295
+ end
296
+ end
297
+
298
+ def destroyInfo
299
+ @list_size = 0
300
+ @item = ''
301
+ end
302
+
303
+ # This function destroys the widget and all the memory it used.
304
+ def destroy
305
+ self.cleanTitle
306
+ self.destroyInfo
307
+
308
+ # Delete the windows
309
+ CDK.deleteCursesWindow(@field_win)
310
+ CDK.deleteCursesWindow(@label_win)
311
+ CDK.deleteCursesWindow(@shadow_win)
312
+ CDK.deleteCursesWindow(@win)
313
+
314
+ # Clean the key bindings.
315
+ self.cleanBindings(:ITEMLIST)
316
+
317
+ CDK::SCREEN.unregister(:ITEMLIST, self)
318
+ end
319
+
320
+ # This sets multiple attributes of the widget.
321
+ def set(list, count, current, box)
322
+ self.setValues(list, count, current)
323
+ self.setBox(box)
324
+ end
325
+
326
+ # This function sets the contents of the list
327
+ def setValues(item, count, default_item)
328
+ if self.createList(item, count)
329
+ old_width = @field_width
330
+
331
+ # Set the default item.
332
+ if default_item >= 0 && default_item < @list_size
333
+ @current_item = default_item
334
+ @default_item = default_item
335
+ end
336
+
337
+ # This will not resize the outer windows but can still make a usable
338
+ # field width if the title made the outer window wide enough
339
+ self.updateFieldWidth
340
+ if @field_width > old_width
341
+ self.createFieldWin(@field_win.begy, @field_win.begx)
342
+ end
343
+
344
+ # Draw the field.
345
+ self.erase
346
+ self.draw(@box)
347
+ end
348
+ end
349
+
350
+ def getValues(size)
351
+ size << @list_size
352
+ return @item
353
+ end
354
+
355
+ # This sets the default/current item of the itemlist
356
+ def setCurrentItem(current_item)
357
+ # Set the default item.
358
+ if current_item >= 0 && current_item < @list_size
359
+ @current_item = current_item
360
+ end
361
+ end
362
+
363
+ def getCurrentItem
364
+ return @current_item
365
+ end
366
+
367
+ # This sets the default item in the list.
368
+ def setDefaultItem(default_item)
369
+ # Make sure the item is in the correct range.
370
+ if default_item < 0
371
+ @default_item = 0
372
+ elsif default_item >= @list_size
373
+ @default_item = @list_size - 1
374
+ else
375
+ @default_item = default_item
376
+ end
377
+ end
378
+
379
+ def getDefaultItem
380
+ return @default_item
381
+ end
382
+
383
+ def focus
384
+ self.drawField(true)
385
+ end
386
+
387
+ def unfocus
388
+ self.drawField(false)
389
+ end
390
+
391
+ def createList(item, count)
392
+ status = false
393
+ new_items = []
394
+ new_pos = []
395
+ new_len = []
396
+ if count >= 0
397
+ field_width = 0
398
+
399
+ # Go through the list and determine the widest item.
400
+ status = true
401
+ (0...count).each do |x|
402
+ # Copy the item to the list.
403
+ lentmp = []
404
+ postmp = []
405
+ new_items << CDK.char2Chtype(item[x], lentmp, postmp)
406
+ new_len << lentmp[0]
407
+ new_pos << postmp[0]
408
+ if new_items[0] == 0
409
+ status = false
410
+ break
411
+ end
412
+ field_width = [field_width, new_len[x]].max
413
+ end
414
+
415
+ # Now we need to justify the strings.
416
+ (0...count).each do |x|
417
+ new_pos[x] = CDK.justifyString(field_width + 1,
418
+ new_len[x], new_pos[x])
419
+ end
420
+
421
+ if status
422
+ self.destroyInfo
423
+
424
+ # Copy in the new information
425
+ @list_size = count
426
+ @item = new_items
427
+ @item_pos = new_pos
428
+ @item_len = new_len
429
+ end
430
+ else
431
+ self.destroyInfo
432
+ status = true
433
+ end
434
+
435
+ return status
436
+ end
437
+
438
+ # Go through the list and determine the widest item.
439
+ def maximumFieldWidth
440
+ max_width = -2**30
441
+
442
+ (0...@list_size).each do |x|
443
+ max_width = [max_width, @item_len[x]].max
444
+ end
445
+ max_width = [max_width, 0].max
446
+
447
+ return max_width
448
+ end
449
+
450
+ def updateFieldWidth
451
+ want = self.maximumFieldWidth + 1
452
+ have = @box_width - @label_len - 2 * @border_size
453
+ @field_width = [want, have].min
454
+ end
455
+
456
+ # Make the field window.
457
+ def createFieldWin(ypos, xpos)
458
+ @field_win = @win.subwin(1, @field_width, ypos, xpos)
459
+ unless @field_win.nil?
460
+ @field_win.keypad(true)
461
+ @input_window = @field_win
462
+ return true
463
+ end
464
+ return false
465
+ end
466
+
467
+ def position
468
+ super(@win)
469
+ end
470
+
471
+ def object_type
472
+ :ITEMLIST
473
+ end
474
+ end
475
+ end
data/lib/cdk/label.rb ADDED
@@ -0,0 +1,207 @@
1
+ require_relative 'cdk_objs'
2
+
3
+ module CDK
4
+ class LABEL < CDK::CDKOBJS
5
+ attr_accessor :win
6
+
7
+ def initialize(cdkscreen, xplace, yplace, mesg, rows, box, shadow)
8
+ super()
9
+ parent_width = cdkscreen::window.maxx
10
+ parent_height = cdkscreen::window.maxy
11
+ box_width = -2**30 # -INFINITY
12
+ box_height = 0
13
+ xpos = [xplace]
14
+ ypos = [yplace]
15
+ x = 0
16
+
17
+ if rows <= 0
18
+ return nil
19
+ end
20
+
21
+ self.setBox(box)
22
+ box_height = rows + 2 * @border_size
23
+
24
+ @info = []
25
+ @info_len = []
26
+ @info_pos = []
27
+
28
+ # Determine the box width.
29
+ (0...rows).each do |x|
30
+ #Translate the string to a chtype array
31
+ info_len = []
32
+ info_pos = []
33
+ @info << CDK.char2Chtype(mesg[x], info_len, info_pos)
34
+ @info_len << info_len[0]
35
+ @info_pos << info_pos[0]
36
+ box_width = [box_width, @info_len[x]].max
37
+ end
38
+ box_width += 2 * @border_size
39
+
40
+ # Create the string alignments.
41
+ (0...rows).each do |x|
42
+ @info_pos[x] = CDK.justifyString(box_width - 2 * @border_size,
43
+ @info_len[x], @info_pos[x])
44
+ end
45
+
46
+ # Make sure we didn't extend beyond the dimensions of the window.
47
+ box_width = if box_width > parent_width
48
+ then parent_width
49
+ else box_width
50
+ end
51
+ box_height = if box_height > parent_height
52
+ then parent_height
53
+ else box_height
54
+ end
55
+
56
+ # Rejustify the x and y positions if we need to
57
+ CDK.alignxy(cdkscreen.window, xpos, ypos, box_width, box_height)
58
+ @screen = cdkscreen
59
+ @parent = cdkscreen.window
60
+ @win = Curses::Window.new(box_height, box_width, ypos[0], xpos[0])
61
+ @shadow_win = nil
62
+ @xpos = xpos[0]
63
+ @ypos = ypos[0]
64
+ @rows = rows
65
+ @box_width = box_width
66
+ @box_height = box_height
67
+ @input_window = @win
68
+ @has_focus = false
69
+ @shadow = shadow
70
+
71
+ if @win.nil?
72
+ self.destroy
73
+ return nil
74
+ end
75
+
76
+ @win.keypad(true)
77
+
78
+ # If a shadow was requested, then create the shadow window.
79
+ if shadow
80
+ @shadow_win = Curses::Window.new(box_height, box_width,
81
+ ypos[0] + 1, xpos[0] + 1)
82
+ end
83
+
84
+ # Register this
85
+ cdkscreen.register(:LABEL, self)
86
+ end
87
+
88
+ # This was added for the builder.
89
+ def activate(actions)
90
+ self.draw(@box)
91
+ end
92
+
93
+ # This sets multiple attributes of the widget
94
+ def set(mesg, lines, box)
95
+ self.setMessage(mesg, lines)
96
+ self.setBox(box)
97
+ end
98
+
99
+ # This sets the information within the label.
100
+ def setMessage(info, info_size)
101
+ # Clean out the old message.`
102
+ (0...@rows).each do |x|
103
+ @info[x] = ''
104
+ @info_pos[x] = 0
105
+ @info_len[x] = 0
106
+ end
107
+
108
+ @rows = if info_size < @rows
109
+ then info_size
110
+ else @rows
111
+ end
112
+
113
+ # Copy in the new message.
114
+ (0...@rows).each do |x|
115
+ info_len = []
116
+ info_pos = []
117
+ @info[x] = CDK.char2Chtype(info[x], info_len, info_pos)
118
+ @info_len[x] = info_len[0]
119
+ @info_pos[x] = CDK.justifyString(@box_width - 2 * @border_size,
120
+ @info_len[x], info_pos[0])
121
+ end
122
+
123
+ # Redraw the label widget.
124
+ self.erase
125
+ self.draw(@box)
126
+ end
127
+
128
+ def getMessage(size)
129
+ size << @rows
130
+ return @info
131
+ end
132
+
133
+ def object_type
134
+ :LABEL
135
+ end
136
+
137
+ def position
138
+ super(@win)
139
+ end
140
+
141
+ # This sets the background attribute of the widget.
142
+ def setBKattr(attrib)
143
+ @win.wbkgd(attrib)
144
+ end
145
+
146
+ # This draws the label widget.
147
+ def draw(box)
148
+ # Is there a shadow?
149
+ unless @shadow_win.nil?
150
+ Draw.drawShadow(@shadow_win)
151
+ end
152
+
153
+ # Box the widget if asked.
154
+ if @box
155
+ Draw.drawObjBox(@win, self)
156
+ end
157
+
158
+ # Draw in the message.
159
+ (0...@rows).each do |x|
160
+ Draw.writeChtype(@win,
161
+ @info_pos[x] + @border_size, x + @border_size,
162
+ @info[x], CDK::HORIZONTAL, 0, @info_len[x])
163
+ end
164
+
165
+ # Refresh the window
166
+ @win.refresh
167
+ end
168
+
169
+ # This erases the label widget
170
+ def erase
171
+ CDK.eraseCursesWindow(@win)
172
+ CDK.eraseCursesWindow(@shadow_win)
173
+ end
174
+
175
+ # This moves the label field to the given location
176
+ # Inherited
177
+ # def move(xplace, yplace, relative, refresh_flag)
178
+ # end
179
+
180
+ # This destroys the label object pointer.
181
+ def destroy
182
+ CDK.deleteCursesWindow(@shadow_win)
183
+ CDK.deleteCursesWindow(@win)
184
+
185
+ self.cleanBindings(:LABEL)
186
+
187
+ CDK::SCREEN.unregister(:LABEL, self)
188
+ end
189
+
190
+ # This pauses until a user hits a key...
191
+ def wait(key)
192
+ function_key = []
193
+ if key.ord == 0
194
+ code = self.getch(function_key)
195
+ else
196
+ # Only exit when a specific key is hit
197
+ while true
198
+ code = self.getch(function_key)
199
+ if code == key
200
+ break
201
+ end
202
+ end
203
+ end
204
+ return code
205
+ end
206
+ end
207
+ end