slithernix-cdk 0.0.1

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