[squeak-dev] The Inbox: MorphicExtras-hjh.106.mcz

commits at source.squeak.org commits at source.squeak.org
Mon Jan 21 06:19:32 UTC 2013


A new version of MorphicExtras was added to project The Inbox:
http://source.squeak.org/inbox/MorphicExtras-hjh.106.mcz

==================== Summary ====================

Name: MorphicExtras-hjh.106
Author: hjh
Time: 21 January 2013, 6:18:34.106 am
UUID: 16ee4f0e-5230-1948-939e-4648fa9f5501
Ancestors: MorphicExtras-bf.104

CalendarChooserMorph by  Jon Hylands
<jon at huv.com> 

http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20111103/fb5cbdc0/MorphicExtras-CalendarChooser.obj

Updated #date accessor method to initialize.

=============== Diff against MorphicExtras-bf.104 ===============

Item was changed:
  SystemOrganization addCategory: #'MorphicExtras-Demo'!
  SystemOrganization addCategory: #'MorphicExtras-AdditionalSupport'!
  SystemOrganization addCategory: #'MorphicExtras-AdditionalMorphs'!
  SystemOrganization addCategory: #'MorphicExtras-Widgets'!
  SystemOrganization addCategory: #'MorphicExtras-Books'!
  SystemOrganization addCategory: #'MorphicExtras-Postscript Filters'!
  SystemOrganization addCategory: #'MorphicExtras-Support'!
  SystemOrganization addCategory: #'MorphicExtras-SoundInterface'!
  SystemOrganization addCategory: #'MorphicExtras-Undo'!
  SystemOrganization addCategory: #'MorphicExtras-Postscript Canvases'!
  SystemOrganization addCategory: #'MorphicExtras-PartsBin'!
  SystemOrganization addCategory: #'MorphicExtras-AdditionalWidgets'!
  SystemOrganization addCategory: #'MorphicExtras-Flaps'!
  SystemOrganization addCategory: #'MorphicExtras-Navigators'!
  SystemOrganization addCategory: #'MorphicExtras-GeeMail'!
  SystemOrganization addCategory: #'MorphicExtras-Palettes'!
  SystemOrganization addCategory: #'MorphicExtras-Leds'!
  SystemOrganization addCategory: #'MorphicExtras-SqueakPage'!
  SystemOrganization addCategory: #'MorphicExtras-Text Support'!
  SystemOrganization addCategory: #'MorphicExtras-Obsolete'!
  SystemOrganization addCategory: #'MorphicExtras-EToy-Download'!
+ SystemOrganization addCategory: #'MorphicExtras-CalendarChooser'!

Item was added:
+ Object subclass: #CalendarChooserDay
+ 	instanceVariableNames: 'date bounds owner highlighted'
+ 	classVariableNames: ''
+ 	poolDictionaries: ''
+ 	category: 'MorphicExtras-CalendarChooser'!
+ 
+ !CalendarChooserDay commentStamp: 'Jon 11/2/2011 21:22' prior: 0!
+ A CalendarChooserDay represents a specific day on a monthly calendar.
+ 
+ Instance Variables
+ 	bounds:		<Rectangle>
+ 	date:		<Date>
+ 	highlighted:	<Boolean>
+ 	owner:		<CalendarChooserMorph>
+ 
+ bounds
+ 	- owner-relative bounding box
+ 
+ date
+ 	- the specific date (year/month/day) the CalendarChooserDay represents
+ 
+ highlighted
+ 	- flag to keep track of when a CalendarChooserDay has the mouse dragging over it, and is thus highlighted
+ 
+ owner
+ 	- the morph that contains the CalendarChooserDay, and all its siblings
+ !

Item was added:
+ ----- Method: CalendarChooserDay class>>on:for: (in category 'instance creation') -----
+ on: aDate for: aCalendarChooserMorph
+ 
+ 	^self new
+ 		date: aDate;
+ 		owner: aCalendarChooserMorph;
+ 		yourself.
+ !

Item was added:
+ ----- Method: CalendarChooserDay>>bounds (in category 'accessing') -----
+ bounds
+ 
+ 	^ bounds!

Item was added:
+ ----- Method: CalendarChooserDay>>bounds: (in category 'accessing') -----
+ bounds: aRectangle
+ 
+ 	bounds := aRectangle!

Item was added:
+ ----- Method: CalendarChooserDay>>date (in category 'accessing') -----
+ date
+ 
+ 	^ date!

Item was added:
+ ----- Method: CalendarChooserDay>>date: (in category 'accessing') -----
+ date: aDate
+ 
+ 	date := aDate.
+ !

Item was added:
+ ----- Method: CalendarChooserDay>>debugPrint (in category 'printing') -----
+ debugPrint
+ 
+ 	^(WriteStream on: (String new: 10))
+ 		print: self class;
+ 		nextPutAll: ' (';
+ 		print: self date;
+ 		nextPutAll: ' - ';
+ 		print: self bounds;
+ 		nextPut: $);
+ 		contents!

Item was added:
+ ----- Method: CalendarChooserDay>>drawOn:offset: (in category 'drawing') -----
+ drawOn: aCanvas offset: origin
+ 
+ 	| box dayString textColor textTopLeft textWidth today |
+ 	dayString := date dayOfMonth printString.
+ 	textWidth := owner weekdayFont widthOfString: dayString.
+ 	textTopLeft := bounds topCenter translateBy: (textWidth // -2) @ 3.
+ 	box := ((textTopLeft extent: textWidth @ owner weekdayFont height) insetBy: -8 @ -1) translateBy: origin.
+ 	today := date = Date today.
+ 	textColor := date month = owner date month
+ 		ifTrue: [Color black]
+ 		ifFalse: [Color veryLightGray].
+ 	(date = owner date or: [self highlighted])
+ 		ifTrue: [
+ 			| lineColor fillColor |
+ 			lineColor := today
+ 				ifTrue: [Color red]
+ 				ifFalse: [Color veryLightGray].
+ 			fillColor := self highlighted
+ 				ifTrue: [Color veryVeryLightGray]
+ 				ifFalse: [Color veryLightGray].
+ 			aCanvas fillOval: box color: fillColor borderWidth: 1 borderColor: lineColor].
+ 	today & (date ~= owner date) & self highlighted not
+ 		ifTrue: [aCanvas fillOval: box color: Color white borderWidth: 1 borderColor: Color red].
+ 	aCanvas
+ 		drawString: dayString
+ 		at: textTopLeft + origin
+ 		font: owner weekdayFont
+ 		color: textColor.!

Item was added:
+ ----- Method: CalendarChooserDay>>highlighted (in category 'accessing') -----
+ highlighted
+ 
+ 	^highlighted!

Item was added:
+ ----- Method: CalendarChooserDay>>highlighted: (in category 'accessing') -----
+ highlighted: aBoolean
+ 
+ 	highlighted := aBoolean!

Item was added:
+ ----- Method: CalendarChooserDay>>initialize (in category 'initializing') -----
+ initialize
+ 
+ 	self highlighted: false!

Item was added:
+ ----- Method: CalendarChooserDay>>owner (in category 'accessing') -----
+ owner
+ 
+ 	^ owner!

Item was added:
+ ----- Method: CalendarChooserDay>>owner: (in category 'accessing') -----
+ owner: aCalendarChooserMorph
+ 
+ 	owner := aCalendarChooserMorph!

Item was added:
+ ----- Method: CalendarChooserDay>>printOn: (in category 'printing') -----
+ printOn: aStream
+ 
+ 	aStream
+ 		print: self class;
+ 		nextPutAll: ' (';
+ 		print: self date;
+ 		nextPut: $)!

Item was added:
+ BorderedMorph subclass: #CalendarChooserMorph
+ 	instanceVariableNames: 'date days touchPoints'
+ 	classVariableNames: ''
+ 	poolDictionaries: ''
+ 	category: 'MorphicExtras-CalendarChooser'!
+ 
+ !CalendarChooserMorph commentStamp: 'Jon 11/2/2011 21:24' prior: 0!
+ A CalendarChooserMorph is a standalone morph that represents a selectable monthly calendar.
+ 
+ Instance Variables
+ 	date:		<Date>
+ 	days:		<OrderedCollection of: <CalendarChooserDay>>
+ 	touchPoints:	<Dictionary key: <Rectangle> value: <Symbol>>
+ 
+ date
+ 	- the currently selected date (always within the current month)
+ 
+ days
+ 	- all the days that are visible, including days from the previous month, the current month, and the next month
+ 
+ touchPoints
+ 	- extra hotspots that are touch-responsive (key rectangle is in world coordinates)
+ !

Item was added:
+ ----- Method: CalendarChooserMorph class>>on: (in category 'instance creation') -----
+ on: aDate
+ 
+ 	^self new
+ 		"extent: 200 @ 160;"
+ 		date: aDate;
+ 		yourself.
+ !

Item was added:
+ ----- Method: CalendarChooserMorph class>>openOn: (in category 'instance creation') -----
+ openOn: aDate
+ 
+ 	^(self on: aDate) openInWorld!

Item was added:
+ ----- Method: CalendarChooserMorph>>computeDays (in category 'private') -----
+ computeDays
+ 	"Populate the days instance variable with CalendarChooserDay instances for the receiver's month."
+ 
+ 	| cellHeight cellWidth height topLeft lastMonth nextMonth theDay thisMonth |
+ 	topLeft := 0 @ 25.
+ 	height := self bounds height - 25.
+ 	cellHeight := height // 8.
+ 	height := height - cellHeight.
+ 	cellWidth := self bounds width // 7.
+ 	lastMonth := date month previous.
+ 	thisMonth := date month.
+ 	nextMonth := date month next.
+ 	days := OrderedCollection new.
+ 	1 to: 6 do: [:lineIndex |
+ 		| yOffset |
+ 		yOffset := topLeft y + (lineIndex * cellHeight).
+ 		(self daysForLine: lineIndex) withIndexDo: [:day :dayIndex |
+ 			| cellPosX dayDate |
+ 			dayDate := thisMonth asDate addDays: day - 1.
+ 			(lineIndex = 1 and: [day > 7])
+ 				ifTrue: [dayDate := lastMonth asDate addDays: day - 1].
+ 			(lineIndex > 4 and: [day < 15])
+ 				ifTrue: [dayDate := nextMonth asDate addDays: day - 1].
+ 			cellPosX := cellWidth * (dayIndex - 1).
+ 			days add: (theDay := CalendarChooserDay on: dayDate for: self).
+ 			theDay bounds: (cellPosX @ yOffset extent: cellWidth @ cellHeight)]]!

Item was added:
+ ----- Method: CalendarChooserMorph>>date (in category 'accessing') -----
+ date
+ 
+ 	date isNil ifTrue: [ self date: Date today].
+ 	^date!

Item was added:
+ ----- Method: CalendarChooserMorph>>date: (in category 'accessing') -----
+ date: aDate
+ 
+ 	| recompute |
+ 	recompute := date isNil or: [date month ~= aDate month].
+ 	date := aDate.
+ 	recompute
+ 		ifTrue: [self computeDays]!

Item was added:
+ ----- Method: CalendarChooserMorph>>daysForLine: (in category 'private') -----
+ daysForLine: aNumber
+ 	"Return an array of numbers that correspond to the day-of-month numbers of the given line (row) 
+ 	in the calendar for the month of the receiver's date."
+ 
+ 	| dayCount firstWeekday previousDayCount previousMonthDays lastDay |
+ 	dayCount := date month daysInMonth.
+ 	firstWeekday := Date firstWeekdayOfMonth: date monthIndex year: date year.
+ 	previousDayCount := date month previous daysInMonth.
+ 	"First case - handle the first line specially"
+ 	aNumber = 1
+ 		ifTrue: [
+ 			"If this month's first day is Sunday, the first line is the last week from last month"
+ 			firstWeekday = 1
+ 				ifTrue: [^(previousDayCount - 6 to: previousDayCount) asArray].
+ 
+ 			"Otherwise, its a mix of last month and this month"
+ 			previousMonthDays := (firstWeekday - 1 to: 1 by: -1) collect: [:each | previousDayCount - each + 1].
+ 			^previousMonthDays, ((1 to: 7) asArray copyFrom: 1 to: 7 - previousMonthDays size)].
+ 
+ 	"Recompute the last day from the previous line (I love recursion)"
+ 	lastDay := (self daysForLine: aNumber - 1) last.
+ 	"Second case - the first week of this month starts on Sunday"
+ 	(aNumber = 2 and: [lastDay = previousDayCount])
+ 		ifTrue: [^(1 to: 7) asArray].
+ 
+ 	"Third case - the first week of next month starts on Sunday"
+ 	lastDay = dayCount
+ 		ifTrue: [^(1 to: 7) asArray].
+ 
+ 	"Fourth case - everything else"
+ 	^(lastDay + 1 to: lastDay + 7) collect: [:each |
+ 		each <= dayCount
+ 			ifTrue: [each]
+ 			ifFalse: [each - dayCount]]!

Item was added:
+ ----- Method: CalendarChooserMorph>>defaultBounds (in category 'initializing') -----
+ defaultBounds
+ 	"Answer the default bounds for the receiver."
+ 
+ 	^0 @ 0 corner: 200 @ 160!

Item was added:
+ ----- Method: CalendarChooserMorph>>drawDaysOn: (in category 'drawing') -----
+ drawDaysOn: aCanvas
+ 
+ 	days do: [:each |
+ 		each
+ 			drawOn: aCanvas
+ 			offset: self bounds topLeft]!

Item was added:
+ ----- Method: CalendarChooserMorph>>drawMonthHeaderOn: (in category 'drawing') -----
+ drawMonthHeaderOn: aCanvas
+ 
+ 	| headerWidth headerString box textBox textTopLeft monthBox monthNameWidth yearBox previousMonthBox nextMonthBox |
+ 	headerString := self date asMonth printString.
+ 	headerWidth := self monthNameFont widthOfString: headerString.
+ 	box := self bounds topLeft extent: self bounds width @ 23.
+ 	textTopLeft := self bounds topCenter translateBy: (headerWidth // -2) @ 5.
+ 	textBox := textTopLeft extent: headerWidth @ self monthNameFont height.
+ 	monthNameWidth := self monthNameFont widthOfString: self date monthName, ' '.
+ 	monthBox := textBox topLeft extent: monthNameWidth @ textBox height.
+ 	yearBox := monthBox topRight corner: textBox bottomRight.
+ 	previousMonthBox := (self bounds topLeft translateBy: 10 @ 5) extent: 10 @ self monthNameFont height.
+ 	nextMonthBox := (self bounds topRight translateBy: -20 @ 5) extent: 10 @ self monthNameFont height.
+ 	touchPoints
+ 		at: monthBox put: #handleMonthNameTouched;
+ 		at: yearBox put: #handleYearTouched;
+ 		at: (previousMonthBox expandBy: 10 @ 5) put: #handlePreviousMonthTouched;
+ 		at: (nextMonthBox expandBy: 10 @ 5) put: #handleNextMonthTouched.
+ 	aCanvas
+ 		frameAndFillRectangle: box
+ 		fillColor: Color veryLightGray
+ 		borderWidth: 1
+ 		borderColor: Color black;
+ 		
+ 		line: box bottomLeft
+ 		to: box bottomRight
+ 		width: 2
+ 		color: Color black;
+ 		
+ 		drawString: '<'
+ 		at: previousMonthBox origin
+ 		font: self monthNameFont
+ 		color: Color black;
+ 		
+ 		drawString: '>'
+ 		at: nextMonthBox origin
+ 		font: self monthNameFont
+ 		color: Color black;
+ 
+ 		drawString: headerString
+ 		at: (self bounds topCenter translateBy: (headerWidth // -2) @ 5)
+ 		font: self monthNameFont
+ 		color: Color black.
+ !

Item was added:
+ ----- Method: CalendarChooserMorph>>drawOn: (in category 'drawing') -----
+ drawOn: aCanvas
+ 
+ 	touchPoints := Dictionary new.
+ 	aCanvas
+ 		clipBy: self bounds
+ 		during: [:clippedCanvas |
+ 			clippedCanvas
+ 				fillRectangle: self bounds
+ 				color: Color white.
+ 
+ 			self 
+ 				drawMonthHeaderOn: clippedCanvas;
+ 				drawWeekDayNamesOn: clippedCanvas;
+ 				drawDaysOn: clippedCanvas;
+ 				drawTodayOn: aCanvas.
+ 
+ 			clippedCanvas
+ 				frameRectangle: self bounds
+ 				width: 1
+ 				color: Color black].
+ 
+ 
+ 
+ 	!

Item was added:
+ ----- Method: CalendarChooserMorph>>drawTodayOn: (in category 'drawing') -----
+ drawTodayOn: aCanvas
+ 
+ 	| text textHeight textTopLeft textWidth textBox |
+ 	text := 'Today: ', (Date today printFormat: #(2 1 3 $  3 1 1)).
+ 	textWidth := self weekdayFont widthOfString: text.
+ 	textHeight := self weekdayFont height.
+ 	textTopLeft := self bounds bottomCenter translateBy: (textWidth // -2) @ (textHeight negated - 5).
+ 	textBox := textTopLeft extent: textWidth @ textHeight.
+ 	touchPoints at: textBox put: #handleTodayTouched.
+ 	aCanvas
+ 		drawString: text
+ 		at: textTopLeft
+ 		font: self weekdayFont
+ 		color: Color gray!

Item was added:
+ ----- Method: CalendarChooserMorph>>drawWeekDayNamesOn: (in category 'drawing') -----
+ drawWeekDayNamesOn: aCanvas
+ 
+ 	| cellHeight height topLeft topRight cellWidth |
+ 	topLeft := self bounds topLeft translateBy: 0 @ 25.
+ 	topRight := self bounds topRight translateBy: 0 @ 25.
+ 	height := self bounds height - 25.
+ 	cellHeight := height // 8.
+ 	cellWidth := self bounds width // 7.
+ 	aCanvas
+ 		line: (topLeft translateBy: 0 @ cellHeight) 
+ 		to: (topRight translateBy: 0 @ cellHeight) 
+ 		width: 1
+ 		color: Color black.
+ 
+ 	#('Sun' 'Mon' 'Tue' 'Wed' 'Thu' 'Fri' 'Sat') withIndexDo: [:dayName :dayIndex |
+ 		| cellPosX cellTopCenter textWidth |
+ 		cellPosX := cellWidth * (dayIndex - 1).
+ 		cellTopCenter := topLeft translateBy: ((cellPosX + (cellWidth // 2)) + 1) @ 0.
+ 		textWidth := self weekdayFont widthOfString: dayName.
+ 		aCanvas
+ 			drawString: dayName
+ 			at: (cellTopCenter translateBy: (textWidth // -2) @ 3)
+ 			font: self weekdayFont
+ 			color: Color darkGray]
+ !

Item was added:
+ ----- Method: CalendarChooserMorph>>extent: (in category 'accessing') -----
+ extent: aPoint
+ 	"Since the day objects cache their bounding box, we have to recompute them if the receiver resizes."
+ 
+ 	| result |
+ 	result := super extent: aPoint.
+ 	date notNil
+ 		ifTrue: [self computeDays].
+ 	^result!

Item was added:
+ ----- Method: CalendarChooserMorph>>handleMonthNameTouched (in category 'event handling') -----
+ handleMonthNameTouched
+ 
+ 	| newMonthName dayCount |
+ 	newMonthName := ListChooser
+ 		chooseItemFrom: #('January' 'February' 'March' 'April' 'May' 'June' 'July'
+ 			'August' 'September' 'October' 'November' 'December')
+ 		title: 'Choose a month:'.
+ 
+ 	newMonthName isNil
+ 		ifTrue: [^self].
+ 
+ 	dayCount := (Month month: newMonthName year: date year) daysInMonth.
+ 	self date: (Date newDay: (date dayOfMonth min: dayCount) month: newMonthName year: date year).
+ 	self changed.
+ !

Item was added:
+ ----- Method: CalendarChooserMorph>>handleNextMonthTouched (in category 'event handling') -----
+ handleNextMonthTouched
+ 
+ 	self date: (date addMonths: 1).
+ 	self changed.
+ !

Item was added:
+ ----- Method: CalendarChooserMorph>>handlePreviousMonthTouched (in category 'event handling') -----
+ handlePreviousMonthTouched
+ 
+ 	self date: (date addMonths: -1).
+ 	self changed.
+ !

Item was added:
+ ----- Method: CalendarChooserMorph>>handleTodayTouched (in category 'event handling') -----
+ handleTodayTouched
+ 
+ 	self date: Date today.
+ 	self changed.
+ !

Item was added:
+ ----- Method: CalendarChooserMorph>>handleYearTouched (in category 'event handling') -----
+ handleYearTouched
+ 
+ 	| newYear dayCount |
+ 	newYear := ListChooser
+ 		chooseItemFrom: ((2000 to: 2020) collect: [:each | each printString])
+ 		title: 'Choose a year:'
+ 		addAllowed: true.
+ 
+ 	newYear isNil
+ 		ifTrue: [^self].
+ 
+ 	newYear := newYear asNumber.
+ 	dayCount := (Month month: date monthIndex year: newYear) daysInMonth.
+ 	self date: (Date newDay: (date dayOfMonth min: dayCount) month: date monthIndex year: newYear).
+ 	self changed.!

Item was added:
+ ----- Method: CalendarChooserMorph>>handlesMouseDown: (in category 'event handling') -----
+ handlesMouseDown: event
+ 
+ 	^true!

Item was added:
+ ----- Method: CalendarChooserMorph>>initialize (in category 'initializing') -----
+ initialize
+ 
+ 	super initialize.
+ 	touchPoints := Dictionary new.
+ !

Item was added:
+ ----- Method: CalendarChooserMorph>>monthNameFont (in category 'accessing') -----
+ monthNameFont
+ 
+ 	^TTCFont familyName: 'BitstreamVeraSans' pointSize: 11 emphasis: 3!

Item was added:
+ ----- Method: CalendarChooserMorph>>mouseDown: (in category 'event handling') -----
+ mouseDown: event
+ 	"Handle mouse down and mouse movement. Highlight the day under the mouse."
+ 
+ 	| morphRelativeHitPoint |
+ 	morphRelativeHitPoint := event cursorPoint translateBy: bounds origin negated.
+ 	days do: [:each |
+ 		each highlighted: 	(each bounds containsPoint: morphRelativeHitPoint)].
+ 	self changed.
+ !

Item was added:
+ ----- Method: CalendarChooserMorph>>mouseMove: (in category 'event handling') -----
+ mouseMove: event
+ 
+ 	self mouseDown: event!

Item was added:
+ ----- Method: CalendarChooserMorph>>mouseUp: (in category 'event handling') -----
+ mouseUp: event
+ 	"Check for hotspot hits - handle them if they match.
+ 	Otherwise, convert the event cursor to morph-local, and find the day under it.
+ 	If there is nothing under the mouse when it goes up, nothing happens."
+ 
+ 	| morphRelativeHitPoint |
+ 	touchPoints keysAndValuesDo: [:eachBox :eachSelector |
+ 		(eachBox containsPoint: event cursorPoint)
+ 			ifTrue: [self perform: eachSelector]].
+ 	morphRelativeHitPoint := event cursorPoint translateBy: bounds origin negated.
+ 	days do: [:each |
+ 		each highlighted: false.
+ 		(each bounds containsPoint: morphRelativeHitPoint)
+ 			ifTrue: [self date: each date]].
+ 	self changed.
+ !

Item was added:
+ ----- Method: CalendarChooserMorph>>weekdayFont (in category 'accessing') -----
+ weekdayFont
+ 
+ 	^TTCFont familyName: 'BitstreamVeraSans' pointSize: 10 emphasis: 0!



More information about the Squeak-dev mailing list