[Seaside-dev] WAMiniCalendar rewrite

Paolo Bonzini bonzini at gnu.org
Sun Feb 24 17:40:46 UTC 2008


The attached changeset reimplements WAMiniCalendar to not use Squeak's 
additional date classes (except if one uses the #month and #month: 
accessors; for now in GNU Smalltalk they will not be available).  In 
addition, to make the patch more palatable, it eases localization (one 
has to reimplement #monthNames and #weekDays).

I checked that the methods I used, especially #addDays: and 
#subtractDays:, are available in VW too.

Paolo
-------------- next part --------------
WAComponent subclass: #WAMiniCalendar
	instanceVariableNames: 'monthIndex year date canSelectBlock selectBlock'
	classVariableNames: ''
	poolDictionaries: ''
	category: 'Seaside-Core-Components-Widgets'!

WAMiniCalendar comment: 'WAMiniCalendar renders a monthly calendar. Users can navigate by month, year, or select a year and a month. Users can select a date in the calendar. Set canSelectBlock to control which dates a user can select. Use selectBlock to perform an action when a user selects a date. WAMiniCalendar>>date returns the selected date.

Select "Mini Calendar" tab of the Functional Seaside Test Suite to run an example  (http://127.0.0.1:xxxx/seaside/tests/alltests)

Instance Variables:
	canSelectBlock		<BlockClosure with date argument>	return true if date argument should be rendered with a link, ie user can select that date
	date		<WAValueHolder on a date>	Selected date
	monthIndex		<WAValueHolder on an Integer>	Currently displayed month
	year		<WAValueHolder on an Integer>	Currently displayed year
	selectBlock		<BlockClosure with date argument> called when user selects a date

'!

!WAMiniCalendar class methodsFor: 'testing'!

canBeRoot
	^true
!

example
	^self new
! !

!WAMiniCalendar methodsFor: 'testing'!

canSelect: aDate
	^canSelectBlock value: aDate
! !

!WAMiniCalendar methodsFor: 'accessing'!

canSelectBlock: aBlock
	canSelectBlock := aBlock
!

month
	^Month month: self monthIndex year: self year
!

month: aMonth
	self monthIndex: aMonth monthIndex.
	self year: aMonth year.
!

selectBlock: aBlock
	selectBlock := aBlock
!

states
	^Array with: date with: monthIndex with: year
! !

!WAMiniCalendar methodsFor: 'accessing-delegated'!

date
	^date contents
!

date: aDate
	date contents: aDate.
	monthIndex contents: aDate monthIndex.
	year contents: aDate year
!

monthIndex
	^monthIndex contents
!

monthIndex: anInteger
	monthIndex contents: anInteger
!

year
	^year contents
!

year: anIntegerOrString
	year contents: ([anIntegerOrString asInteger] on: Error do: [:error | 1900])
! !

!WAMiniCalendar methodsFor: 'initialization'!

initialize
	super initialize.
	monthIndex := WAValueHolder with: Date today monthIndex.
	year := WAValueHolder with: Date today year.
	date := WAValueHolder new.
	canSelectBlock := [:value | true].
	selectBlock := [:value | self answer: value]
! !

!WAMiniCalendar methodsFor: 'localization'!

monthNames
	^(1 to: 12) collect: [ :each | Date nameOfMonth: each ]
!

weekDays
	^(1 to: 7) collect: [:i | (Date nameOfDay: i) first: 3]
! !

!WAMiniCalendar methodsFor: 'private'!

monthName
	^(Date nameOfMonth: self monthIndex)
!

monthHeading
	^self monthName , ' ' , self year toString
!

weeksDo: aBlock
	| day nextMonth |
	day := Date newDay: 1 monthIndex: self monthIndex year: self year.
	day := day subtractDays: day dayOfWeek.
	nextMonth := (self monthIndex \\ 12) + 1.
	[ day monthIndex = nextMonth ] whileFalse: [
		aBlock value: day.
		day := day addDays: 7 ]
! !

!WAMiniCalendar methodsFor: 'rendering'!

renderCellForDate: aDate on: html
	html tableData: 
		[(aDate monthIndex = self monthIndex and: [ aDate year = self year ])
			ifTrue: 
			[html span
				class: (self date = aDate ifTrue: ['calendarArchiveDate']);
				with: [(self canSelect: aDate) 
					ifTrue: 
						[html anchor
							callback: [self select: aDate];
							with: aDate dayOfMonth]
					ifFalse: [html text: aDate dayOfMonth]]]]
!

renderContentOn: html
	html div
		class: 'calendar';
		with: 
			[html span
				class: 'calendarCaption';
				with: [self renderMonthHeadingOn: html].
			html table: 
				[html tableRow
					class: 'calendarTitle';
					with: [self weekDays do: [:each | html tableData: each]].
						self weeksDo: [:week | self renderRowForWeek: week on: html]].
			self renderMonthNavigationOn: html.
			html
				space;
				space.
			self renderYearNavigationOn: html]
!

renderMonthHeadingOn: html
	html form: 
		[html select
			list: (1 to: 12);
			on: #monthIndex of: self;
			labels: [:index | Date nameOfMonth: index].
		html textInput
			maxLength: 4;
			on: #year of: self.
		html submitButton text: 'Refresh']
!

renderMonthNavigationOn: html
	| tab |
	tab := #(12 1 2 3 4 5 6 7 8 9 10 11 12 1).
	html span
		class: 'calendarPrevious';
		with: 
			[html anchor
				callback: [
					self monthIndex = 1
						ifTrue: [ self monthIndex: 12; year: self year - 1]
						ifFalse: [ self monthIndex: self monthIndex - 1 ]];
				with: ((self monthNames at: (tab at: self monthIndex)) first: 3)].
	html space.
	html span
		class: 'calendarNext';
		with: 
			[html anchor
				callback: [
					self monthIndex = 12
						ifTrue: [ self monthIndex: 1; year: self year + 1]
						ifFalse: [ self monthIndex: self monthIndex + 1 ]];
				with: ((self monthNames at: (tab at: self monthIndex + 2)) first: 3)].
!

renderRowForWeek: initialDay on: html
	html 
		tableRow: [0 to: 6 do: [:each |
			self renderCellForDate: (initialDay addDays: each) on: html]]
!

renderYearNavigationOn: html
	html span
		class: 'calendarPrevious';
		with: 
			[html anchor
				callback: [self year: self year - 1];
				with: self year - 1].
	html space.
	html span
		class: 'calendarNext';
		with: 
			[html anchor
				callback: [self year: self year + 1];
				with: self year + 1]
! !

!WAMiniCalendar methodsFor: 'action'!

select: aDate
	self date: aDate.
	selectBlock value: aDate
! !



More information about the seaside-dev mailing list