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.
data/lib/cdk/mentry.rb ADDED
@@ -0,0 +1,616 @@
1
+ require_relative 'cdk_objs'
2
+
3
+ module CDK
4
+ class MENTRY < CDK::CDKOBJS
5
+ attr_accessor :info, :current_col, :current_row, :top_row
6
+ attr_reader :disp_type, :field_width, :rows, :field_win
7
+
8
+ def initialize(cdkscreen, xplace, yplace, title, label, field_attr,
9
+ filler, disp_type, f_width, f_rows, logical_rows, min, box, shadow)
10
+ super()
11
+ parent_width = cdkscreen.window.maxx
12
+ parent_height = cdkscreen.window.maxy
13
+ field_width = f_width
14
+ field_rows = f_rows
15
+
16
+ self.setBox(box)
17
+
18
+ # If the field_width is a negative value, the field_width will be
19
+ # COLS-field_width, otherwise the field_width will be the given width.
20
+ field_width = CDK.setWidgetDimension(parent_width, field_width, 0)
21
+
22
+ # If the field_rows is a negative value, the field_rows will be
23
+ # ROWS-field_rows, otherwise the field_rows will be the given rows.
24
+ field_rows = CDK.setWidgetDimension(parent_width, field_rows, 0)
25
+ box_height = field_rows + 2
26
+
27
+ # Set some basic values of the mentry field
28
+ @label = ''
29
+ @label_len = 0
30
+ @label_win = nil
31
+
32
+ # We need to translate the string label to a chtype array
33
+ if label.size > 0
34
+ label_len = []
35
+ @label = CDK.char2Chtype(label, label_len, [])
36
+ @label_len = label_len[0]
37
+ end
38
+ box_width = @label_len + field_width + 2
39
+
40
+ old_width = box_width
41
+ box_width = self.setTitle(title, box_width)
42
+ horizontal_adjust = (box_width - old_width) / 2
43
+
44
+ box_height += @title_lines
45
+
46
+ # Make sure we didn't extend beyond the parent window.
47
+ box_width = [box_width, parent_width].min
48
+ box_height = [box_height, parent_height].min
49
+ field_width = [box_width - @label_len - 2, field_width].min
50
+ field_rows = [box_height - @title_lines - 2, field_rows].min
51
+
52
+ # Rejustify the x and y positions if we need to.
53
+ xtmp = [xplace]
54
+ ytmp = [yplace]
55
+ CDK.alignxy(cdkscreen.window, xtmp, ytmp, box_width, box_height)
56
+ xpos = xtmp[0]
57
+ ypos = ytmp[0]
58
+
59
+ # Make the label window.
60
+ @win = Curses::Window.new(box_height, box_width, ypos, xpos)
61
+
62
+ # Is the window nil?
63
+ if @win.nil?
64
+ self.destroy
65
+ return nil
66
+ end
67
+
68
+ # Create the label window.
69
+ if @label.size > 0
70
+ @label_win = @win.subwin(field_rows, @label_len + 2,
71
+ ypos + @title_lines + 1, xpos + horizontal_adjust + 1)
72
+ end
73
+
74
+ # make the field window.
75
+ @field_win = @win.subwin(field_rows, field_width,
76
+ ypos + @title_lines + 1, xpos + @label_len + horizontal_adjust + 1)
77
+
78
+ # Turn on the keypad.
79
+ @field_win.keypad(true)
80
+ @win.keypad(true)
81
+
82
+ # Set up the rest of the structure.
83
+ @parent = cdkscreen.window
84
+ @total_width = (field_width * logical_rows) + 1
85
+
86
+ # Create the info string
87
+ @info = ''
88
+
89
+ # Set up the rest of the widget information.
90
+ @screen = cdkscreen
91
+ @shadow_win = nil
92
+ @field_attr = field_attr
93
+ @field_width = field_width
94
+ @rows = field_rows
95
+ @box_height = box_height
96
+ @box_width = box_width
97
+ @filler = filler.ord
98
+ @hidden = filler.ord
99
+ @input_window = @win
100
+ @accepts_focus = true
101
+ @current_row = 0
102
+ @current_col = 0
103
+ @top_row = 0
104
+ @shadow = shadow
105
+ @disp_type = disp_type
106
+ @min = min
107
+ @logical_rows = logical_rows
108
+
109
+ # This is a generic character parser for the mentry field. It is used as
110
+ # a callback function, so any personal modifications can be made by
111
+ # creating a new function and calling that one the mentry activation.
112
+ mentry_callback = lambda do |mentry, character|
113
+ cursor_pos = mentry.getCursorPos
114
+ newchar = Display.filterByDisplayType(mentry.disp_type, character)
115
+
116
+ if newchar == Curses::Error
117
+ CDK.Beep
118
+ else
119
+ mentry.info = mentry.info[0...cursor_pos] + newchar.chr +
120
+ mentry.info[cursor_pos..-1]
121
+ mentry.current_col += 1
122
+
123
+ mentry.drawField
124
+
125
+ # Have we gone out of bounds
126
+ if mentry.current_col >= mentry.field_width
127
+ # Update the row and col values.
128
+ mentry.current_col = 0
129
+ mentry.current_row += 1
130
+
131
+ # If we have gone outside of the visual boundaries, we
132
+ # need to scroll the window.
133
+ if mentry.current_row == mentry.rows
134
+ # We have to redraw the screen
135
+ mentry.current_row -= 1
136
+ mentry.top_row += 1
137
+ mentry.drawField
138
+ end
139
+ # REMEMBER THIS, this line causes a widget to appear in the top left
140
+ #mentry.field_win.move(mentry.current_row, mentry.current_col)
141
+ mentry.field_win.refresh
142
+ end
143
+ end
144
+ end
145
+ @callbackfn = mentry_callback
146
+
147
+ # Do we need to create a shadow.
148
+ if shadow
149
+ @shadow_win = Curses::Window.new(box_height, box_width,
150
+ ypos + 1, xpos + 1)
151
+ end
152
+
153
+ # Register
154
+ cdkscreen.register(:MENTRY, self)
155
+ end
156
+
157
+ # This actually activates the mentry widget...
158
+ def activate(actions)
159
+ input = 0
160
+
161
+ # Draw the mentry widget.
162
+ self.draw(@box)
163
+
164
+ if actions.size == 0
165
+ while true
166
+ input = self.getch([])
167
+
168
+ # Inject this character into the widget.
169
+ ret = self.inject(input)
170
+ if @exit_type != :EARLY_EXIT
171
+ return ret
172
+ end
173
+ end
174
+ else
175
+ actions.each do |action|
176
+ ret = self.inject(action)
177
+ if @exit_type != :EARLY_EXIT
178
+ return ret
179
+ end
180
+ end
181
+ end
182
+
183
+ # Set the exit type and exit.
184
+ self.setExitType(0)
185
+ return 0
186
+ end
187
+
188
+ def setTopRow(row)
189
+ if @top_row != row
190
+ @top_row = row
191
+ return true
192
+ end
193
+ return false
194
+ end
195
+
196
+ def setCurPos(row, col)
197
+ if @current_row != row || @current_col != col
198
+ @current_row = row
199
+ @current_col = col
200
+ return true
201
+ end
202
+ return false
203
+ end
204
+
205
+ def KEY_LEFT(moved, redraw)
206
+ result = true
207
+ if @current_col != 0
208
+ moved[0] = self.setCurPos(@current_row, @current_col - 1)
209
+ elsif @current_row == 0
210
+ if @top_row != 0
211
+ moved[0] = self.setCurPos(@current_row, @field_width - 1)
212
+ redraw[0] = self.setTopRow(@top_row - 1)
213
+ end
214
+ else
215
+ moved[0] = self.setCurPos(@current_row - 1, @field_width - 1)
216
+ end
217
+
218
+ if !moved[0] && !redraw[0]
219
+ CDK.Beep
220
+ result = false
221
+ end
222
+ return result
223
+ end
224
+
225
+ def getCursorPos
226
+ return (@current_row + @top_row) * @field_width + @current_col
227
+ end
228
+
229
+ # This injects a character into the widget.
230
+ def inject(input)
231
+ cursor_pos = self.getCursorPos
232
+ pp_return = 1
233
+ ret = -1
234
+ complete = false
235
+
236
+ # Set the exit type.
237
+ self.setExitType(0)
238
+
239
+ # Refresh the field.
240
+ self.drawField
241
+
242
+ # Check if there is a pre-process function to be called.
243
+ unless @pre_process_func.nil?
244
+ # Call the pre-process function
245
+ pp_return = @pre_process_func.call(:MENTRY, self,
246
+ @pre_process_data, input)
247
+ end
248
+
249
+ # Should we continue?
250
+ if pp_return != 0
251
+ # Check for a key binding...
252
+ if self.checkBind(:MENTRY, input)
253
+ complete = true
254
+ else
255
+ moved = false
256
+ redraw = false
257
+
258
+ case input
259
+ when Curses::KEY_HOME
260
+ moved = self.setCurPos(0, 0)
261
+ redraw = self.setTopRow(0)
262
+ when Curses::KEY_END
263
+ field_characters = @rows * @field_width
264
+ if @info.size < field_characters
265
+ redraw = self.setTopRow(0)
266
+ moved = self.setCurPos(
267
+ @info.size / @field_width, @info.size % @field_width)
268
+ else
269
+ redraw = self.setTopRow(@info.size / @field_width, @rows + 1)
270
+ moved = self.setCurPos(@rows - 1, @info.size % @field_width)
271
+ end
272
+ when Curses::KEY_LEFT
273
+ mtmp = [moved]
274
+ rtmp = [redraw]
275
+ self.KEY_LEFT(mtmp, rtmp)
276
+ moved = mtmp[0]
277
+ redraw = rtmp[0]
278
+ when Curses::KEY_RIGHT
279
+ if @current_col < @field_width - 1
280
+ if self.getCursorPos + 1 <= @info.size
281
+ moved = self.setCurPos(@current_row, @current_col + 1)
282
+ end
283
+ elsif @current_row == @rows - 1
284
+ if @top_row + @current_row + 1 < @logical_rows
285
+ moved = self.setCurPos(@current_row, 0)
286
+ redraw = self.setTopRow(@top_row + 1)
287
+ end
288
+ else
289
+ moved = self.setCurPos(@current_row + 1, 0)
290
+ end
291
+ if !moved && !redraw
292
+ CDK.Beep
293
+ end
294
+ when Curses::KEY_DOWN
295
+ if @current_row != @rows - 1
296
+ if self.getCursorPos + @field_width + 1 <= @info.size
297
+ moved = self.setCurPos(@current_row + 1, @current_col)
298
+ end
299
+ elsif @top_row < @logical_rows - @rows
300
+ if (@top_row + @current_row + 1) * @field_width <= @info.size
301
+ redraw = self.setTopRow(@top_row + 1)
302
+ end
303
+ end
304
+ if !moved && !redraw
305
+ CDK.Beep
306
+ end
307
+ when Curses::KEY_UP
308
+ if @current_row != 0
309
+ moved = self.setCurPos(@current_row - 1, @current_col)
310
+ elsif @top_row != 0
311
+ redraw = self.setTopRow(@top_row - 1)
312
+ end
313
+ if !moved && !redraw
314
+ CDK.Beep
315
+ end
316
+ when Curses::KEY_BACKSPACE, Curses::KEY_DC
317
+ if @disp_type == :VIEWONLY
318
+ CDK.Beep
319
+ elsif @info.length == 0
320
+ CDK.Beep
321
+ elsif input == Curses::KEY_DC
322
+ cursor_pos = self.getCursorPos
323
+ if cursor_pos < @info.size
324
+ @info = @info[0...cursor_pos] + @info[cursor_pos + 1..-1]
325
+ self.drawField
326
+ else
327
+ CDK.Beep
328
+ end
329
+ else
330
+ mtmp = [moved]
331
+ rtmp = [redraw]
332
+ hKL = self.KEY_LEFT(mtmp, rtmp)
333
+ moved = mtmp[0]
334
+ rtmp = [redraw]
335
+ if hKL
336
+ cursor_pos = self.getCursorPos
337
+ if cursor_pos < @info.size
338
+ @info = @info[0...cursor_pos] + @info[cursor_pos + 1..-1]
339
+ self.drawField
340
+ else
341
+ CDK.Beep
342
+ end
343
+ end
344
+ end
345
+ when CDK::TRANSPOSE
346
+ if cursor_pos >= @info.size - 1
347
+ CDK.Beep
348
+ else
349
+ holder = @info[cursor_pos]
350
+ @info[cursor_pos] = @info[cursor_pos + 1]
351
+ @info[cursor_pos + 1] = holder
352
+ self.drawField
353
+ end
354
+ when CDK::ERASE
355
+ if @info.size != 0
356
+ self.clean
357
+ self.drawField
358
+ end
359
+ when CDK::CUT
360
+ if @info.size == 0
361
+ CDK.Beep
362
+ else
363
+ @@g_paste_buffer = @info.clone
364
+ self.clean
365
+ self.drawField
366
+ end
367
+ when CDK::COPY
368
+ if @info.size == 0
369
+ CDK.Beep
370
+ else
371
+ @@g_paste_buffer = @info.clone
372
+ end
373
+ when CDK::PASTE
374
+ if @@g_paste_buffer.size == 0
375
+ CDK.Beep
376
+ else
377
+ self.setValue(@@g_paste_buffer)
378
+ self.draw(@box)
379
+ end
380
+ when CDK::KEY_TAB, CDK::KEY_RETURN, Curses::KEY_ENTER
381
+ if @info.size < @min + 1
382
+ CDK.Beep
383
+ else
384
+ self.setExitType(input)
385
+ ret = @info
386
+ complete = true
387
+ end
388
+ when Curses::Error
389
+ self.setExitType(input)
390
+ complete = true
391
+ when CDK::KEY_ESC
392
+ self.setExitType(input)
393
+ complete = true
394
+ when CDK::REFRESH
395
+ @screen.erase
396
+ @screen.refresh
397
+ else
398
+ if @disp_type == :VIEWONLY || @info.size >= @total_width
399
+ CDK.Beep
400
+ else
401
+ @callbackfn.call(self, input)
402
+ end
403
+ end
404
+
405
+ if redraw
406
+ self.drawField
407
+ elsif moved
408
+ #@field_win.move(@current_row, @current_col)
409
+ @field_win.refresh
410
+ end
411
+ end
412
+
413
+ # Should we do a post-process?
414
+ if !complete && !(@post_process_func.nil?)
415
+ @post_process_func.call(:MENTRY, self, @post_process_data, input)
416
+ end
417
+ end
418
+
419
+ if !complete
420
+ self.setExitType(0)
421
+ end
422
+
423
+ @result_data = ret
424
+ return ret
425
+ end
426
+
427
+ # This moves the mentry field to the given location.
428
+ def move(xplace, yplace, relative, refresh_flag)
429
+ raise "WTF"
430
+ windows = [@win, @field_win, @label_win, @shadow_win]
431
+ self.move_specific(xplace, yplace, relative, refresh_flag,
432
+ windows, [])
433
+ end
434
+
435
+ # This function redraws the multiple line entry field.
436
+ def drawField
437
+ currchar = @field_width * @top_row
438
+
439
+ self.drawTitle(@win)
440
+ @win.refresh
441
+
442
+ lastpos = @info.size
443
+
444
+ # Start redrawing the fields.
445
+ (0...@rows).each do |x|
446
+ (0...@field_width).each do |y|
447
+ if currchar < lastpos
448
+ if Display.isHiddenDisplayType(@disp_type)
449
+ @field_win.mvwaddch(x, y, @filler)
450
+ else
451
+ @field_win.mvwaddch(x, y, @info[currchar].ord | @field_attr)
452
+ currchar += 1
453
+ end
454
+ else
455
+ @field_win.mvwaddch(x, y, @filler)
456
+ end
457
+ end
458
+ end
459
+
460
+ # Refresh the screen.
461
+ #@field_win.move(@current_row, @current_col)
462
+ @field_win.refresh
463
+ end
464
+
465
+ # This function draws the multiple line entry field.
466
+ def draw(box)
467
+ # Box the widget if asked.
468
+ if box
469
+ Draw.drawObjBox(@win, self)
470
+ @win.refresh
471
+ end
472
+
473
+ # Do we need to draw in the shadow?
474
+ unless @shadow_win.nil?
475
+ Draw.drawShadow(@shadow_win)
476
+ end
477
+
478
+ # Draw in the label to the widget.
479
+ unless @label_win.nil?
480
+ Draw.writeChtype(@label_win, 0, 0, @label, CDK::HORIZONTAL,
481
+ 0, @label_len)
482
+ @label_win.refresh
483
+ end
484
+
485
+ # Draw the mentry field
486
+ self.drawField
487
+ end
488
+
489
+ # This sets the background attribute of the widget.
490
+ def setBKattr(attrib)
491
+ @win.wbkgd(attrib)
492
+ @field_win.wbkgd(attrib)
493
+ unless @label_win.nil?
494
+ @label_win.wbkgd(attrib)
495
+ end
496
+ end
497
+
498
+ # This function erases the multiple line entry field from the screen.
499
+ def erase
500
+ if self.validCDKObject
501
+ CDK.eraseCursesWindow(@field_win)
502
+ CDK.eraseCursesWindow(@label_win)
503
+ CDK.eraseCursesWindow(@win)
504
+ CDK.eraseCursesWindow(@shadow_win)
505
+ end
506
+ end
507
+
508
+ # This function destroys a multiple line entry field widget.
509
+ def destroy
510
+ self.cleanTitle
511
+
512
+ # Clean up the windows.
513
+ CDK.deleteCursesWindow(@field_win)
514
+ CDK.deleteCursesWindow(@label_win)
515
+ CDK.deleteCursesWindow(@shadow_win)
516
+ CDK.deleteCursesWindow(@win)
517
+
518
+ # Clean the key bindings.
519
+ self.cleanBindings(:MENTRY)
520
+
521
+ # Unregister this object.
522
+ CDK::SCREEN.unregister(:MENTRY, self)
523
+ end
524
+
525
+ # This sets multiple attributes of the widget.
526
+ def set(value, min, box)
527
+ self.setValue(value)
528
+ self.setMin(min)
529
+ self.setBox(box)
530
+ end
531
+
532
+ # This removes the old information in the entry field and keeps the
533
+ # new information given.
534
+ def setValue(new_value)
535
+ field_characters = @rows * @field_width
536
+
537
+ @info = new_value
538
+
539
+ # Set the cursor/row info
540
+ if new_value.size < field_characters
541
+ @top_row = 0
542
+ @current_row = new_value.size / @field_width
543
+ @current_col = new_value.size % @field_width
544
+ else
545
+ row_used = new_value.size / @field_width
546
+ @top_row = row_used - @rows + 1
547
+ @current_row = @rows - 1
548
+ @current_col = new_value.size % @field_width
549
+ end
550
+
551
+ # Redraw the widget.
552
+ self.drawField
553
+ end
554
+
555
+ def getValue
556
+ return @info
557
+ end
558
+
559
+ # This sets the filler character to use when drawing the widget.
560
+ def setFillerChar(filler)
561
+ @filler = filler.ord
562
+ end
563
+
564
+ def getFillerChar
565
+ return @filler
566
+ end
567
+
568
+ # This sets the character to use when a hidden character type is used
569
+ def setHiddenChar(character)
570
+ @hidden = character
571
+ end
572
+
573
+ def getHiddenChar
574
+ return @hidden
575
+ end
576
+
577
+ # This sets a minimum length of the widget.
578
+ def setMin(min)
579
+ @min = min
580
+ end
581
+
582
+ def getMin
583
+ return @min
584
+ end
585
+
586
+ # This erases the information in the multiple line entry widget
587
+ def clean
588
+ @info = ''
589
+ @current_row = 0
590
+ @current_col = 0
591
+ @top_row = 0
592
+ end
593
+
594
+ # This sets the callback function.
595
+ def setCB(callback)
596
+ @callbackfn = callback
597
+ end
598
+
599
+ def focus
600
+ #@field_win.move(0, @current_col)
601
+ @field_win.refresh
602
+ end
603
+
604
+ def unfocus
605
+ @field_win.refresh
606
+ end
607
+
608
+ def position
609
+ super(@win)
610
+ end
611
+
612
+ def object_type
613
+ :MENTRY
614
+ end
615
+ end
616
+ end