slithernix-cdk 0.0.1

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