cdk 0.9.0

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,614 @@
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.getmaxx
12
+ parent_height = cdkscreen.window.getmaxy
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 = Ncurses::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 == Ncurses::ERR
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
+ mentry.field_win.wmove(mentry.current_row, mentry.current_col)
140
+ mentry.field_win.wrefresh
141
+ end
142
+ end
143
+ end
144
+ @callbackfn = mentry_callback
145
+
146
+ # Do we need to create a shadow.
147
+ if shadow
148
+ @shadow_win = Ncurses::WINDOW.new(box_height, box_width,
149
+ ypos + 1, xpos + 1)
150
+ end
151
+
152
+ # Register
153
+ cdkscreen.register(:MENTRY, self)
154
+ end
155
+
156
+ # This actually activates the mentry widget...
157
+ def activate(actions)
158
+ input = 0
159
+
160
+ # Draw the mentry widget.
161
+ self.draw(@box)
162
+
163
+ if actions.size == 0
164
+ while true
165
+ input = self.getch([])
166
+
167
+ # Inject this character into the widget.
168
+ ret = self.inject(input)
169
+ if @exit_type != :EARLY_EXIT
170
+ return ret
171
+ end
172
+ end
173
+ else
174
+ actions.each do |action|
175
+ ret = self.inject(action)
176
+ if @exit_type != :EARLY_EXIT
177
+ return ret
178
+ end
179
+ end
180
+ end
181
+
182
+ # Set the exit type and exit.
183
+ self.setExitType(0)
184
+ return 0
185
+ end
186
+
187
+ def setTopRow(row)
188
+ if @top_row != row
189
+ @top_row = row
190
+ return true
191
+ end
192
+ return false
193
+ end
194
+
195
+ def setCurPos(row, col)
196
+ if @current_row != row || @current_col != col
197
+ @current_row = row
198
+ @current_col = col
199
+ return true
200
+ end
201
+ return false
202
+ end
203
+
204
+ def KEY_LEFT(moved, redraw)
205
+ result = true
206
+ if @current_col != 0
207
+ moved[0] = self.setCurPos(@current_row, @current_col - 1)
208
+ elsif @current_row == 0
209
+ if @top_row != 0
210
+ moved[0] = self.setCurPos(@current_row, @field_width - 1)
211
+ redraw[0] = self.setTopRow(@top_row - 1)
212
+ end
213
+ else
214
+ moved[0] = self.setCurPos(@current_row - 1, @field_width - 1)
215
+ end
216
+
217
+ if !moved[0] && !redraw[0]
218
+ CDK.Beep
219
+ result = false
220
+ end
221
+ return result
222
+ end
223
+
224
+ def getCursorPos
225
+ return (@current_row + @top_row) * @field_width + @current_col
226
+ end
227
+
228
+ # This injects a character into the widget.
229
+ def inject(input)
230
+ cursor_pos = self.getCursorPos
231
+ pp_return = 1
232
+ ret = -1
233
+ complete = false
234
+
235
+ # Set the exit type.
236
+ self.setExitType(0)
237
+
238
+ # Refresh the field.
239
+ self.drawField
240
+
241
+ # Check if there is a pre-process function to be called.
242
+ unless @pre_process_func.nil?
243
+ # Call the pre-process function
244
+ pp_return = @pre_process_func.call(:MENTRY, self,
245
+ @pre_process_data, input)
246
+ end
247
+
248
+ # Should we continue?
249
+ if pp_return != 0
250
+ # Check for a key binding...
251
+ if self.checkBind(:MENTRY, input)
252
+ complete = true
253
+ else
254
+ moved = false
255
+ redraw = false
256
+
257
+ case input
258
+ when Ncurses::KEY_HOME
259
+ moved = self.setCurPos(0, 0)
260
+ redraw = self.setTopRow(0)
261
+ when Ncurses::KEY_END
262
+ field_characters = @rows * @field_width
263
+ if @info.size < field_characters
264
+ redraw = self.setTopRow(0)
265
+ moved = self.setCurPos(
266
+ @info.size / @field_width, @info.size % @field_width)
267
+ else
268
+ redraw = self.setTopRow(@info.size / @field_width, @rows + 1)
269
+ moved = self.setCurPos(@rows - 1, @info.size % @field_width)
270
+ end
271
+ when Ncurses::KEY_LEFT
272
+ mtmp = [moved]
273
+ rtmp = [redraw]
274
+ self.KEY_LEFT(mtmp, rtmp)
275
+ moved = mtmp[0]
276
+ redraw = rtmp[0]
277
+ when Ncurses::KEY_RIGHT
278
+ if @current_col < @field_width - 1
279
+ if self.getCursorPos + 1 <= @info.size
280
+ moved = self.setCurPos(@current_row, @current_col + 1)
281
+ end
282
+ elsif @current_row == @rows - 1
283
+ if @top_row + @current_row + 1 < @logical_rows
284
+ moved = self.setCurPos(@current_row, 0)
285
+ redraw = self.setTopRow(@top_row + 1)
286
+ end
287
+ else
288
+ moved = self.setCurPos(@current_row + 1, 0)
289
+ end
290
+ if !moved && !redraw
291
+ CDK.Beep
292
+ end
293
+ when Ncurses::KEY_DOWN
294
+ if @current_row != @rows - 1
295
+ if self.getCursorPos + @field_width + 1 <= @info.size
296
+ moved = self.setCurPos(@current_row + 1, @current_col)
297
+ end
298
+ elsif @top_row < @logical_rows - @rows
299
+ if (@top_row + @current_row + 1) * @field_width <= @info.size
300
+ redraw = self.setTopRow(@top_row + 1)
301
+ end
302
+ end
303
+ if !moved && !redraw
304
+ CDK.Beep
305
+ end
306
+ when Ncurses::KEY_UP
307
+ if @current_row != 0
308
+ moved = self.setCurPos(@current_row - 1, @current_col)
309
+ elsif @top_row != 0
310
+ redraw = self.setTopRow(@top_row - 1)
311
+ end
312
+ if !moved && !redraw
313
+ CDK.Beep
314
+ end
315
+ when Ncurses::KEY_BACKSPACE, Ncurses::KEY_DC
316
+ if @disp_type == :VIEWONLY
317
+ CDK.Beep
318
+ elsif @info.length == 0
319
+ CDK.Beep
320
+ elsif input == Ncurses::KEY_DC
321
+ cursor_pos = self.getCursorPos
322
+ if cursor_pos < @info.size
323
+ @info = @info[0...cursor_pos] + @info[cursor_pos + 1..-1]
324
+ self.drawField
325
+ else
326
+ CDK.Beep
327
+ end
328
+ else
329
+ mtmp = [moved]
330
+ rtmp = [redraw]
331
+ hKL = self.KEY_LEFT(mtmp, rtmp)
332
+ moved = mtmp[0]
333
+ rtmp = [redraw]
334
+ if hKL
335
+ cursor_pos = self.getCursorPos
336
+ if cursor_pos < @info.size
337
+ @info = @info[0...cursor_pos] + @info[cursor_pos + 1..-1]
338
+ self.drawField
339
+ else
340
+ CDK.Beep
341
+ end
342
+ end
343
+ end
344
+ when CDK::TRANSPOSE
345
+ if cursor_pos >= @info.size - 1
346
+ CDK.Beep
347
+ else
348
+ holder = @info[cursor_pos]
349
+ @info[cursor_pos] = @info[cursor_pos + 1]
350
+ @info[cursor_pos + 1] = holder
351
+ self.drawField
352
+ end
353
+ when CDK::ERASE
354
+ if @info.size != 0
355
+ self.clean
356
+ self.drawField
357
+ end
358
+ when CDK::CUT
359
+ if @info.size == 0
360
+ CDK.Beep
361
+ else
362
+ @@g_paste_buffer = @info.clone
363
+ self.clean
364
+ self.drawField
365
+ end
366
+ when CDK::COPY
367
+ if @info.size == 0
368
+ CDK.Beep
369
+ else
370
+ @@g_paste_buffer = @info.clone
371
+ end
372
+ when CDK::PASTE
373
+ if @@g_paste_buffer.size == 0
374
+ CDK.Beep
375
+ else
376
+ self.setValue(@@g_paste_buffer)
377
+ self.draw(@box)
378
+ end
379
+ when CDK::KEY_TAB, CDK::KEY_RETURN, Ncurses::KEY_ENTER
380
+ if @info.size < @min + 1
381
+ CDK.Beep
382
+ else
383
+ self.setExitType(input)
384
+ ret = @info
385
+ complete = true
386
+ end
387
+ when Ncurses::ERR
388
+ self.setExitType(input)
389
+ complete = true
390
+ when CDK::KEY_ESC
391
+ self.setExitType(input)
392
+ complete = true
393
+ when CDK::REFRESH
394
+ @screen.erase
395
+ @screen.refresh
396
+ else
397
+ if @disp_type == :VIEWONLY || @info.size >= @total_width
398
+ CDK.Beep
399
+ else
400
+ @callbackfn.call(self, input)
401
+ end
402
+ end
403
+
404
+ if redraw
405
+ self.drawField
406
+ elsif moved
407
+ @field_win.wmove(@current_row, @current_col)
408
+ @field_win.wrefresh
409
+ end
410
+ end
411
+
412
+ # Should we do a post-process?
413
+ if !complete && !(@post_process_func.nil?)
414
+ @post_process_func.call(:MENTRY, self, @post_process_data, input)
415
+ end
416
+ end
417
+
418
+ if !complete
419
+ self.setExitType(0)
420
+ end
421
+
422
+ @result_data = ret
423
+ return ret
424
+ end
425
+
426
+ # This moves the mentry field to the given location.
427
+ def move(xplace, yplace, relative, refresh_flag)
428
+ windows = [@win, @field_win, @label_win, @shadow_win]
429
+ self.move_specific(xplace, yplace, relative, refresh_flag,
430
+ windows, [])
431
+ end
432
+
433
+ # This function redraws the multiple line entry field.
434
+ def drawField
435
+ currchar = @field_width * @top_row
436
+
437
+ self.drawTitle(@win)
438
+ @win.wrefresh
439
+
440
+ lastpos = @info.size
441
+
442
+ # Start redrawing the fields.
443
+ (0...@rows).each do |x|
444
+ (0...@field_width).each do |y|
445
+ if currchar < lastpos
446
+ if Display.isHiddenDisplayType(@disp_type)
447
+ @field_win.mvwaddch(x, y, @filler)
448
+ else
449
+ @field_win.mvwaddch(x, y, @info[currchar].ord | @field_attr)
450
+ currchar += 1
451
+ end
452
+ else
453
+ @field_win.mvwaddch(x, y, @filler)
454
+ end
455
+ end
456
+ end
457
+
458
+ # Refresh the screen.
459
+ @field_win.wmove(@current_row, @current_col)
460
+ @field_win.wrefresh
461
+ end
462
+
463
+ # This function draws the multiple line entry field.
464
+ def draw(box)
465
+ # Box the widget if asked.
466
+ if box
467
+ Draw.drawObjBox(@win, self)
468
+ @win.wrefresh
469
+ end
470
+
471
+ # Do we need to draw in the shadow?
472
+ unless @shadow_win.nil?
473
+ Draw.drawShadow(@shadow_win)
474
+ end
475
+
476
+ # Draw in the label to the widget.
477
+ unless @label_win.nil?
478
+ Draw.writeChtype(@label_win, 0, 0, @label, CDK::HORIZONTAL,
479
+ 0, @label_len)
480
+ @label_win.wrefresh
481
+ end
482
+
483
+ # Draw the mentry field
484
+ self.drawField
485
+ end
486
+
487
+ # This sets the background attribute of the widget.
488
+ def setBKattr(attrib)
489
+ @win.wbkgd(attrib)
490
+ @field_win.wbkgd(attrib)
491
+ unless @label_win.nil?
492
+ @label_win.wbkgd(attrib)
493
+ end
494
+ end
495
+
496
+ # This function erases the multiple line entry field from the screen.
497
+ def erase
498
+ if self.validCDKObject
499
+ CDK.eraseCursesWindow(@field_win)
500
+ CDK.eraseCursesWindow(@label_win)
501
+ CDK.eraseCursesWindow(@win)
502
+ CDK.eraseCursesWindow(@shadow_win)
503
+ end
504
+ end
505
+
506
+ # This function destroys a multiple line entry field widget.
507
+ def destroy
508
+ self.cleanTitle
509
+
510
+ # Clean up the windows.
511
+ CDK.deleteCursesWindow(@field_win)
512
+ CDK.deleteCursesWindow(@label_win)
513
+ CDK.deleteCursesWindow(@shadow_win)
514
+ CDK.deleteCursesWindow(@win)
515
+
516
+ # Clean the key bindings.
517
+ self.cleanBindings(:MENTRY)
518
+
519
+ # Unregister this object.
520
+ CDK::SCREEN.unregister(:MENTRY, self)
521
+ end
522
+
523
+ # This sets multiple attributes of the widget.
524
+ def set(value, min, box)
525
+ self.setValue(value)
526
+ self.setMin(min)
527
+ self.setBox(box)
528
+ end
529
+
530
+ # This removes the old information in the entry field and keeps the
531
+ # new information given.
532
+ def setValue(new_value)
533
+ field_characters = @rows * @field_width
534
+
535
+ @info = new_value
536
+
537
+ # Set the cursor/row info
538
+ if new_value.size < field_characters
539
+ @top_row = 0
540
+ @current_row = new_value.size / @field_width
541
+ @current_col = new_value.size % @field_width
542
+ else
543
+ row_used = new_value.size / @field_width
544
+ @top_row = row_used - @rows + 1
545
+ @current_row = @rows - 1
546
+ @current_col = new_value.size % @field_width
547
+ end
548
+
549
+ # Redraw the widget.
550
+ self.drawField
551
+ end
552
+
553
+ def getValue
554
+ return @info
555
+ end
556
+
557
+ # This sets the filler character to use when drawing the widget.
558
+ def setFillerChar(filler)
559
+ @filler = filler.ord
560
+ end
561
+
562
+ def getFillerChar
563
+ return @filler
564
+ end
565
+
566
+ # This sets the character to use when a hidden character type is used
567
+ def setHiddenChar(character)
568
+ @hidden = character
569
+ end
570
+
571
+ def getHiddenChar
572
+ return @hidden
573
+ end
574
+
575
+ # This sets a minimum length of the widget.
576
+ def setMin(min)
577
+ @min = min
578
+ end
579
+
580
+ def getMin
581
+ return @min
582
+ end
583
+
584
+ # This erases the information in the multiple line entry widget
585
+ def clean
586
+ @info = ''
587
+ @current_row = 0
588
+ @current_col = 0
589
+ @top_row = 0
590
+ end
591
+
592
+ # This sets the callback function.
593
+ def setCB(callback)
594
+ @callbackfn = callback
595
+ end
596
+
597
+ def focus
598
+ @field_win.wmove(0, @current_col)
599
+ @field_win.wrefresh
600
+ end
601
+
602
+ def unfocus
603
+ @field_win.wrefresh
604
+ end
605
+
606
+ def position
607
+ super(@win)
608
+ end
609
+
610
+ def object_type
611
+ :MENTRY
612
+ end
613
+ end
614
+ end