cdk 0.9.0

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.getmaxx
9
+ parent_height = cdkscreen.window.getmaxy
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 = Ncurses::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 = Ncurses::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 Ncurses::KEY_UP, Ncurses::KEY_RIGHT, ' '.ord, '+'.ord, 'n'.ord
170
+ if @current_item < @list_size - 1
171
+ @current_item += 1
172
+ else
173
+ @current_item = 0
174
+ end
175
+ when Ncurses::KEY_DOWN, Ncurses::KEY_LEFT, '-'.ord, 'p'.ord
176
+ if @current_item > 0
177
+ @current_item -= 1
178
+ else
179
+ @current_item = @list_size - 1
180
+ end
181
+ when 'd'.ord, 'D'.ord
182
+ @current_item = @default_item
183
+ when '0'.ord
184
+ @current_item = 0
185
+ when '$'.ord
186
+ @current_item = @list_size - 1
187
+ when CDK::KEY_ESC
188
+ self.setExitType(input)
189
+ complete = true
190
+ when Ncurses::ERR
191
+ self.setExitType(input)
192
+ complete = true
193
+ when CDK::KEY_TAB, CDK::KEY_RETURN, Ncurses::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.wrefresh
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.werase
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 | Ncurses::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.wrefresh
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.getbegy, @field_win.getbegx)
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