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,770 @@
1
+ require_relative 'cdk_objs'
2
+
3
+ module CDK
4
+ class CALENDAR < CDK::CDKOBJS
5
+ attr_accessor :week_base
6
+ attr_reader :day, :month, :year
7
+
8
+ MONTHS_OF_THE_YEAR = [
9
+ 'NULL',
10
+ 'January',
11
+ 'February',
12
+ 'March',
13
+ 'April',
14
+ 'May',
15
+ 'June',
16
+ 'July',
17
+ 'August',
18
+ 'September',
19
+ 'October',
20
+ 'November',
21
+ 'December',
22
+ ]
23
+
24
+ DAYS_OF_THE_MONTH = [
25
+ -1,
26
+ 31,
27
+ 28,
28
+ 31,
29
+ 30,
30
+ 31,
31
+ 30,
32
+ 31,
33
+ 31,
34
+ 30,
35
+ 31,
36
+ 30,
37
+ 31,
38
+ ]
39
+
40
+ MAX_DAYS = 32
41
+ MAX_MONTHS = 13
42
+ MAX_YEARS = 140
43
+
44
+ CALENDAR_LIMIT = MAX_DAYS * MAX_MONTHS * MAX_YEARS
45
+
46
+ def self.CALENDAR_INDEX(d, m, y)
47
+ (y * CDK::CALENDAR::MAX_MONTHS + m) * CDK::CALENDAR::MAX_DAYS + d
48
+ end
49
+
50
+ def setCalendarCell(d, m, y, value)
51
+ @marker[CDK::CALENDAR.CALENDAR_INDEX(d, m, y)] = value
52
+ end
53
+
54
+ def getCalendarCell(d, m, y)
55
+ @marker[CDK::CALENDAR.CALENDAR_INDEX(d, m, y)]
56
+ end
57
+
58
+ def initialize(cdkscreen, xplace, yplace, title, day, month, year,
59
+ day_attrib, month_attrib, year_attrib, highlight, box, shadow)
60
+ super()
61
+ parent_width = cdkscreen.window.maxx
62
+ parent_height = cdkscreen.window.maxy
63
+ box_width = 24
64
+ box_height = 11
65
+ dayname = 'Su Mo Tu We Th Fr Sa '
66
+ bindings = {
67
+ 'T' => Curses::KEY_HOME,
68
+ 't' => Curses::KEY_HOME,
69
+ 'n' => Curses::KEY_NPAGE,
70
+ CDK::FORCHAR => Curses::KEY_NPAGE,
71
+ 'p' => Curses::KEY_PPAGE,
72
+ CDK::BACKCHAR => Curses::KEY_PPAGE,
73
+ }
74
+
75
+ self.setBox(box)
76
+
77
+ box_width = self.setTitle(title, box_width)
78
+ box_height += @title_lines
79
+
80
+ # Make sure we didn't extend beyond the dimensions of the window.
81
+ box_width = [box_width, parent_width].min
82
+ box_height = [box_height, parent_height].min
83
+
84
+ # Rejustify the x and y positions if we need to.
85
+ xtmp = [xplace]
86
+ ytmp = [yplace]
87
+ CDK.alignxy(cdkscreen.window, xtmp, ytmp, box_width, box_height)
88
+ xpos = xtmp[0]
89
+ ypos = ytmp[0]
90
+
91
+ # Create the calendar window.
92
+ @win = Curses::Window.new(box_height, box_width, ypos, xpos)
93
+
94
+ # Is the window nil?
95
+ if @win.nil?
96
+ self.destroy
97
+ return nil
98
+ end
99
+ @win.keypad(true)
100
+
101
+ # Set some variables.
102
+ @x_offset = (box_width - 20) / 2
103
+ @field_width = box_width - 2 * (1 + @border_size)
104
+
105
+ # Set months and day names
106
+ @month_name = CDK::CALENDAR::MONTHS_OF_THE_YEAR.clone
107
+ @day_name = dayname
108
+
109
+ # Set the rest of the widget values.
110
+ @screen = cdkscreen
111
+ @parent = cdkscreen.window
112
+ @shadow_win = nil
113
+ @xpos = xpos
114
+ @ypos = ypos
115
+ @box_width = box_width
116
+ @box_height = box_height
117
+ @day = day
118
+ @month = month
119
+ @year = year
120
+ @day_attrib = day_attrib
121
+ @month_attrib = month_attrib
122
+ @year_attrib = year_attrib
123
+ @highlight = highlight
124
+ @width = box_width
125
+ @accepts_focus = true
126
+ @input_window = @win
127
+ @week_base = 0
128
+ @shadow = shadow
129
+ @label_win = @win.subwin(1, @field_width,
130
+ ypos + @title_lines + 1, xpos + 1 + @border_size)
131
+ if @label_win.nil?
132
+ self.destroy
133
+ return nil
134
+ end
135
+
136
+ @field_win = @win.subwin(7, 20,
137
+ ypos + @title_lines + 3, xpos + @x_offset)
138
+ if @field_win.nil?
139
+ self.destroy
140
+ return nil
141
+ end
142
+ self.setBox(box)
143
+
144
+ @marker = [0] * CDK::CALENDAR::CALENDAR_LIMIT
145
+
146
+ # If the day/month/year values were 0, then use today's date.
147
+ if @day == 0 && @month == 0 && @year == 0
148
+ date_info = Time.new.gmtime
149
+ @day = date_info.day
150
+ @month = date_info.month
151
+ @year = date_info
152
+ end
153
+
154
+ # Verify the dates provided.
155
+ self.verifyCalendarDate
156
+
157
+ # Determine which day the month starts on.
158
+ @week_day = CDK::CALENDAR.getMonthStartWeekday(@year, @month)
159
+
160
+ # If a shadow was requested, then create the shadow window.
161
+ if shadow
162
+ @shadow_win = Curses::Window.new(box_height, box_width,
163
+ ypos + 1, xpos + 1)
164
+ end
165
+
166
+ # Setup the key bindings.
167
+ bindings.each do |from, to|
168
+ self.bind(:CALENDAR, from, :getc, to)
169
+ end
170
+
171
+ cdkscreen.register(:CALENDAR, self)
172
+ end
173
+
174
+ # This function lets the user play with this widget.
175
+ def activate(actions)
176
+ ret = -1
177
+ self.draw(@box)
178
+
179
+ if actions.nil? || actions.size == 0
180
+ while true
181
+ input = self.getch([])
182
+
183
+ # Inject the character into the widget.
184
+ ret = self.inject(input)
185
+ if @exit_type != :EARLY_EXIT
186
+ return ret
187
+ end
188
+ end
189
+ else
190
+ # Inject each character one at a time.
191
+ actions.each do |action|
192
+ ret = self.inject(action)
193
+ if @exit_type != :EARLY_EXIT
194
+ return ret
195
+ end
196
+ end
197
+ end
198
+ return ret
199
+ end
200
+
201
+ # This injects a single character into the widget.
202
+ def inject(input)
203
+ # Declare local variables
204
+ pp_return = 1
205
+ ret = -1
206
+ complete = false
207
+
208
+ # Set the exit type
209
+ self.setExitType(0)
210
+
211
+ # Refresh the widget field.
212
+ self.drawField
213
+
214
+ # Check if there is a pre-process function to be called.
215
+ unless @pre_process_func.nil?
216
+ pp_return = @pre_process_func.call(:CALENDAR, self,
217
+ @pre_process_data, input)
218
+ end
219
+
220
+ # Should we continue?
221
+ if pp_return != 0
222
+ # Check a predefined binding
223
+ if self.checkBind(:CALENDAR, input)
224
+ self.checkEarlyExit
225
+ complete = true
226
+ else
227
+ case input
228
+ when Curses::KEY_UP
229
+ self.decrementCalendarDay(7)
230
+ when Curses::KEY_DOWN
231
+ self.incrementCalendarDay(7)
232
+ when Curses::KEY_LEFT
233
+ self.decrementCalendarDay(1)
234
+ when Curses::KEY_RIGHT
235
+ self.incrementCalendarDay(1)
236
+ when Curses::KEY_NPAGE
237
+ self.incrementCalendarMonth(1)
238
+ when Curses::KEY_PPAGE
239
+ self.decrementCalendarMonth(1)
240
+ when 'N'
241
+ self.incrementCalendarMonth(6)
242
+ when 'P'
243
+ self.decrementCalendarMonth(6)
244
+ when '-'
245
+ self.decrementCalendarYear(1)
246
+ when '+'
247
+ self.incrementCalendarYear(1)
248
+ when Curses::KEY_HOME
249
+ self.setDate(-1, -1, -1)
250
+ when CDK::KEY_ESC
251
+ self.setExitType(input)
252
+ complete = true
253
+ when Curses::Error
254
+ self.setExitType(input)
255
+ complete = true
256
+ when CDK::KEY_TAB, CDK::KEY_RETURN, Curses::KEY_ENTER
257
+ self.setExitType(input)
258
+ ret = self.getCurrentTime
259
+ complete = true
260
+ when CDK::REFRESH
261
+ @screen.erase
262
+ @screen.refresh
263
+ end
264
+ end
265
+
266
+ # Should we do a post-process?
267
+ if !complete && !(@post_process_func.nil?)
268
+ @post_process_func.call(:CALENDAR, self, @post_process_data, input)
269
+ end
270
+ end
271
+
272
+ if !complete
273
+ self.setExitType(0)
274
+ end
275
+
276
+ @result_data = ret
277
+ return ret
278
+ end
279
+
280
+ # This moves the calendar field to the given location.
281
+ def move(xplace, yplace, relative, refresh_flag)
282
+ windows = [@win, @field_win, @label_win, @shadow_win]
283
+ self.move_specific(xplace, yplace, relative, refresh_flag,
284
+ windows, [])
285
+ end
286
+
287
+ # This draws the calendar widget.
288
+ def draw(box)
289
+ header_len = @day_name.size
290
+ col_len = (6 + header_len) / 7
291
+
292
+ # Is there a shadow?
293
+ unless @shadow_win.nil?
294
+ Draw.drawShadow(@shadow_win)
295
+ end
296
+
297
+ # Box the widget if asked.
298
+ if box
299
+ Draw.drawObjBox(@win, self)
300
+ end
301
+
302
+ self.drawTitle(@win)
303
+
304
+ # Draw in the day-of-the-week header.
305
+ (0...7).each do |col|
306
+ src = col_len * ((col + (@week_base % 7)) % 7)
307
+ dst = col_len * col
308
+ Draw.writeChar(@win, @x_offset + dst, @title_lines + 2,
309
+ @day_name[src..-1], CDK::HORIZONTAL, 0, col_len)
310
+ end
311
+
312
+ @win.refresh
313
+ self.drawField
314
+ end
315
+
316
+ # This draws the month field.
317
+ def drawField
318
+ month_name = @month_name[@month]
319
+ month_length = CDK::CALENDAR.getMonthLength(@year, @month)
320
+ year_index = CDK::CALENDAR.YEAR2INDEX(@year)
321
+ year_len = 0
322
+ save_y = -1
323
+ save_x = -1
324
+
325
+ day = (1 - @week_day + (@week_base % 7))
326
+ if day > 0
327
+ day -= 7
328
+ end
329
+
330
+ (1..6).each do |row|
331
+ (0...7).each do |col|
332
+ if day >= 1 && day <= month_length
333
+ xpos = col * 3
334
+ ypos = row
335
+
336
+ marker = @day_attrib
337
+ temp = '%02d' % day
338
+
339
+ if @day == day
340
+ marker = @highlight
341
+ save_y = ypos + @field_win.begy - @input_window.begy
342
+ save_x = 1
343
+ else
344
+ marker |= self.getMarker(day, @month, year_index)
345
+ end
346
+ Draw.writeCharAttrib(@field_win, xpos, ypos, temp, marker,
347
+ CDK::HORIZONTAL, 0, 2)
348
+ end
349
+ day += 1
350
+ end
351
+ end
352
+ @field_win.refresh
353
+
354
+ # Draw the month in.
355
+ if !(@label_win.nil?)
356
+ temp = '%s %d,' % [month_name, @day]
357
+ Draw.writeChar(@label_win, 0, 0, temp, CDK::HORIZONTAL, 0, temp.size)
358
+ @label_win.clrtoeol
359
+
360
+ # Draw the year in.
361
+ temp = '%d' % [@year]
362
+ year_len = temp.size
363
+ Draw.writeChar(@label_win, @field_width - year_len, 0, temp,
364
+ CDK::HORIZONTAL, 0, year_len)
365
+
366
+ @label_win.move(0, 0)
367
+ @label_win.refresh
368
+ elsif save_y >= 0
369
+ @input_window.move(save_y, save_x)
370
+ @input_window.refresh
371
+ end
372
+ end
373
+
374
+ # This sets multiple attributes of the widget
375
+ def set(day, month, year, day_attrib, month_attrib, year_attrib,
376
+ highlight, box)
377
+ self.setDate(day, month, yar)
378
+ self.setDayAttribute(day_attrib)
379
+ self.setMonthAttribute(month_attrib)
380
+ self.setYearAttribute(year_attrib)
381
+ self.setHighlight(highlight)
382
+ self.setBox(box)
383
+ end
384
+
385
+ # This sets the date and some attributes.
386
+ def setDate(day, month, year)
387
+ # Get the current dates and set the default values for the
388
+ # day/month/year values for the calendar
389
+ date_info = Time.new.gmtime
390
+
391
+ # Set the date elements if we need to.
392
+ @day = if day == -1 then date_info.day else day end
393
+ @month = if month == -1 then date_info.month else month end
394
+ @year = if year == -1 then date_info.year else year end
395
+
396
+ # Verify the date information.
397
+ self.verifyCalendarDate
398
+
399
+ # Get the start of the current month.
400
+ @week_day = CDK::CALENDAR.getMonthStartWeekday(@year, @month)
401
+ end
402
+
403
+ # This returns the current date on the calendar.
404
+ def getDate(day, month, year)
405
+ day << @day
406
+ month << @month
407
+ year << @year
408
+ end
409
+
410
+ # This sets the attribute of the days in the calendar.
411
+ def setDayAttribute(attribute)
412
+ @day_attrib = attribute
413
+ end
414
+
415
+ def getDayAttribute
416
+ return @day_attrib
417
+ end
418
+
419
+ # This sets the attribute of the month names in the calendar.
420
+ def setMonthAttribute(attribute)
421
+ @month_attrib = attribute
422
+ end
423
+
424
+ def getMonthAttribute
425
+ return @month_attrib
426
+ end
427
+
428
+ # This sets the attribute of the year in the calendar.
429
+ def setYearAttribute(attribute)
430
+ @year_attrib = attribute
431
+ end
432
+
433
+ def getYearAttribute
434
+ return @year_attrib
435
+ end
436
+
437
+ # This sets the attribute of the highlight box.
438
+ def setHighlight(highlight)
439
+ @highlight = highlight
440
+ end
441
+
442
+ def getHighlight
443
+ return @highlight
444
+ end
445
+
446
+ # This sets the background attribute of the widget.
447
+ def setBKattr(attrib)
448
+ @win.wbkgd(attrib)
449
+ @field_win.wbkgd(attrib)
450
+ unless @label_win.nil?
451
+ @label_win.wbkgd(attrib)
452
+ end
453
+ end
454
+
455
+ # This erases the calendar widget.
456
+ def erase
457
+ if self.validCDKObject
458
+ CDK.eraseCursesWindow(@label_win)
459
+ CDK.eraseCursesWindow(@field_win)
460
+ CDK.eraseCursesWindow(@win)
461
+ CDK.eraseCursesWindow(@shadow_win)
462
+ end
463
+ end
464
+
465
+ # This destroys the calendar
466
+ def destroy
467
+ self.cleanTitle
468
+
469
+ CDK.deleteCursesWindow(@label_win)
470
+ CDK.deleteCursesWindow(@field_win)
471
+ CDK.deleteCursesWindow(@shadow_win)
472
+ CDK.deleteCursesWindow(@win)
473
+
474
+ # Clean the key bindings.
475
+ self.cleanBindings(:CALENDAR)
476
+
477
+ # Unregister the object.
478
+ CDK::SCREEN.unregister(:CALENDAR, self)
479
+ end
480
+
481
+ # This sets a marker on the calendar.
482
+ def setMarker(day, month, year, marker)
483
+ year_index = CDK::CALENDAR.YEAR2INDEX(year)
484
+ oldmarker = self.getMarker(day, month, year)
485
+
486
+ # Check to see if a marker has not already been set
487
+ if oldmarker != 0
488
+ self.setCalendarCell(day, month, year_index,
489
+ oldmarker | Curses::A_BLINK)
490
+ else
491
+ self.setCalendarCell(day, month, year_index, marker)
492
+ end
493
+ end
494
+
495
+ def getMarker(day, month, year)
496
+ result = 0
497
+ year = CDK::CALENDAR.YEAR2INDEX(year)
498
+ if @marker != 0
499
+ result = self.getCalendarCell(day, month, year)
500
+ end
501
+ return result
502
+ end
503
+
504
+ # This sets a marker on the calendar.
505
+ def removeMarker(day, month, year)
506
+ year_index = CDK::CALENDAR.YEAR2INDEX(year)
507
+ self.setCalendarCell(day, month, year_index, 0)
508
+ end
509
+
510
+ # THis function sets the month name.
511
+ def setMonthNames(months)
512
+ (1...[months.size, @month_name.size].min).each do |x|
513
+ @month_name[x] = months[x]
514
+ end
515
+ end
516
+
517
+ # This function sets the day's name
518
+ def setDaysNames(days)
519
+ @day_name = days.clone
520
+ end
521
+
522
+ # This makes sure that the dates provided exist.
523
+ def verifyCalendarDate
524
+ # Make sure the given year is not less than 1900.
525
+ if @year < 1900
526
+ @year = 1900
527
+ end
528
+
529
+ # Make sure the month is within range.
530
+ if @month > 12
531
+ @month = 12
532
+ end
533
+ if @month < 1
534
+ @month = 1
535
+ end
536
+
537
+ # Make sure the day given is within range of the month.
538
+ month_length = CDK::CALENDAR.getMonthLength(@year, @month)
539
+ if @day < 1
540
+ @day = 1
541
+ end
542
+ if @day > month_length
543
+ @day = month_length
544
+ end
545
+ end
546
+
547
+ # This returns what day of the week the month starts on.
548
+ def self.getMonthStartWeekday(year, month)
549
+ return Time.mktime(year, month, 1, 10, 0, 0).wday
550
+ end
551
+
552
+ # This function returns a 1 if it's a leap year and 0 if not.
553
+ def self.isLeapYear(year)
554
+ result = false
555
+ if year % 4 == 0
556
+ if year % 100 == 0
557
+ if year % 400 == 0
558
+ result = true
559
+ end
560
+ else
561
+ result = true
562
+ end
563
+ end
564
+ return result
565
+ end
566
+
567
+ # This increments the current day by the given value.
568
+ def incrementCalendarDay(adjust)
569
+ month_length = CDK::CALENDAR.getMonthLength(@year, @month)
570
+
571
+ # Make sure we adjust the day correctly.
572
+ if adjust + @day > month_length
573
+ # Have to increment the month by one.
574
+ @day = @day + adjust - month_length
575
+ self.incrementCalendarMonth(1)
576
+ else
577
+ @day += adjust
578
+ self.drawField
579
+ end
580
+ end
581
+
582
+ # This decrements the current day by the given value.
583
+ def decrementCalendarDay(adjust)
584
+ # Make sure we adjust the day correctly.
585
+ if @day - adjust < 1
586
+ # Set the day according to the length of the month.
587
+ if @month == 1
588
+ # make sure we aren't going past the year limit.
589
+ if @year == 1900
590
+ mesg = [
591
+ '<C></U>Error',
592
+ 'Can not go past the year 1900'
593
+ ]
594
+ CDK.Beep
595
+ @screen.popupLabel(mesg, 2)
596
+ return
597
+ end
598
+ month_length = CDK::CALENDAR.getMonthLength(@year - 1, 12)
599
+ else
600
+ month_length = CDK::CALENDAR.getMonthLength(@year, @month - 1)
601
+ end
602
+
603
+ @day = month_length - (adjust - @day)
604
+
605
+ # Have to decrement the month by one.
606
+ self.decrementCalendarMonth(1)
607
+ else
608
+ @day -= adjust
609
+ self.drawField
610
+ end
611
+ end
612
+
613
+ # This increments the current month by the given value.
614
+ def incrementCalendarMonth(adjust)
615
+ # Are we at the end of the year.
616
+ if @month + adjust > 12
617
+ @month = @month + adjust - 12
618
+ @year += 1
619
+ else
620
+ @month += adjust
621
+ end
622
+
623
+ # Get the length of the current month.
624
+ month_length = CDK::CALENDAR.getMonthLength(@year, @month)
625
+ if @day > month_length
626
+ @day = month_length
627
+ end
628
+
629
+ # Get the start of the current month.
630
+ @week_day = CDK::CALENDAR.getMonthStartWeekday(@year, @month)
631
+
632
+ # Redraw the calendar.
633
+ self.erase
634
+ self.draw(@box)
635
+ end
636
+
637
+ # This decrements the current month by the given value.
638
+ def decrementCalendarMonth(adjust)
639
+ # Are we at the end of the year.
640
+ if @month <= adjust
641
+ if @year == 1900
642
+ mesg = [
643
+ '<C></U>Error',
644
+ 'Can not go past the year 1900',
645
+ ]
646
+ CDK.Beep
647
+ @screen.popupLabel(mesg, 2)
648
+ return
649
+ else
650
+ @month = 13 - adjust
651
+ @year -= 1
652
+ end
653
+ else
654
+ @month -= adjust
655
+ end
656
+
657
+ # Get the length of the current month.
658
+ month_length = CDK::CALENDAR.getMonthLength(@year, @month)
659
+ if @day > month_length
660
+ @day = month_length
661
+ end
662
+
663
+ # Get the start o the current month.
664
+ @week_day = CDK::CALENDAR.getMonthStartWeekday(@year, @month)
665
+
666
+ # Redraw the calendar.
667
+ self.erase
668
+ self.draw(@box)
669
+ end
670
+
671
+ # This increments the current year by the given value.
672
+ def incrementCalendarYear(adjust)
673
+ # Increment the year.
674
+ @year += adjust
675
+
676
+ # If we are in Feb make sure we don't trip into voidness.
677
+ if @month == 2
678
+ month_length = CDK::CALENDAR.getMonthLength(@year, @month)
679
+ if @day > month_length
680
+ @day = month_length
681
+ end
682
+ end
683
+
684
+ # Get the start of the current month.
685
+ @week_day = CDK::CALENDAR.getMonthStartWeekday(@year, @month)
686
+
687
+ # Redraw the calendar.
688
+ self.erase
689
+ self.draw(@box)
690
+ end
691
+
692
+ # This decrements the current year by the given value.
693
+ def decrementCalendarYear(adjust)
694
+ # Make sure we don't go out o bounds.
695
+ if @year - adjust < 1900
696
+ mesg = [
697
+ '<C></U>Error',
698
+ 'Can not go past the year 1900',
699
+ ]
700
+ CDK.Beep
701
+ @screen.popupLabel(mesg, 2)
702
+ return
703
+ end
704
+
705
+ # Decrement the year.
706
+ @year -= adjust
707
+
708
+ # If we are in Feb make sure we don't trip into voidness.
709
+ if @month == 2
710
+ month_length = CDK::CALENDAR.getMonthLength(@year, @month)
711
+ if @day > month_length
712
+ @day = month_length
713
+ end
714
+ end
715
+
716
+ # Get the start of the current month.
717
+ @week_day = CDK::CALENDAR.getMonthStartWeekday(@year, @month)
718
+
719
+ # Redraw the calendar.
720
+ self.erase
721
+ self.draw(@box)
722
+ end
723
+
724
+ # This returns the length of the current month.
725
+ def self.getMonthLength(year, month)
726
+ month_length = DAYS_OF_THE_MONTH[month]
727
+
728
+ if month == 2
729
+ month_length += if CDK::CALENDAR.isLeapYear(year)
730
+ then 1
731
+ else 0
732
+ end
733
+ end
734
+
735
+ return month_length
736
+ end
737
+
738
+ # This returns what day of the week the month starts on.
739
+ def getCurrentTime
740
+ # Determine the current time and determine if we are in DST.
741
+ return Time.mktime(@year, @month, @day, 0, 0, 0).gmtime
742
+ end
743
+
744
+ def focus
745
+ # Original: drawCDKFscale(widget, ObjOf (widget)->box);
746
+ self.draw(@box)
747
+ end
748
+
749
+ def unfocus
750
+ # Original: drawCDKFscale(widget, ObjOf (widget)->box);
751
+ self.draw(@box)
752
+ end
753
+
754
+ def self.YEAR2INDEX(year)
755
+ if year >= 1900
756
+ year - 1900
757
+ else
758
+ year
759
+ end
760
+ end
761
+
762
+ def position
763
+ super(@win)
764
+ end
765
+
766
+ def object_type
767
+ :CALENDAR
768
+ end
769
+ end
770
+ end