Dialog Toolkit with date pickers

These mods add date pickers - textual, textual with stepper and graphical.
This is a version for debugging, you can use it to create your own library or use as is.
If this works I will add further creating a field and picker together.
Let me know what you think.


Dialog Toolkit Plus mod for debug.scptd.zip (142.1 KB)

edit:
re-uploaded with a few notes, and updated the picture to show the time component of the picker.

1 Like

Thanks for sharing. Does your script library include all of the commands in Shane’s Dialog Toolkit?
Once you finalize your mods, do you expect they will be included by Shane in his library?

On this… Quite a few people have made excellent mods such as this. For practical reasons, I’ve pretty much closed the door to any more changes to my lib, barring any need to fix bugs. Apart from anything else, I’m concerned about file size if I include all the good ones I’ve seen, and I don’t really want to be in the position of picking whose are in and whose aren’t.

I’m delighted that people are creating modified versions — I just ask that they give them unique names, to avoid potential confusion.

Understood. Hopefully, all those who choose to share their enhancements with us will do so in a way that allows us to copy/paste into another script lib. I’m thinking about creating a “DialogToolKitExtras” lib that I could copy all enhancements into. Any reason that won’t work?

Unfortunately it’s not quite that simple. At the moment the code checks to see if a control is one of the types defined in the lib to know what to return (ie, string if it’s a text field, title if it’s a popup, etc), and that code needs to be modified if other widgets are used.

There’s probably a more generic way of going about it, but that’s likely to raise issues of backwards compatibility.

So, how are we supposed to use enhancements provided by others?

They’ll generally provide a modified version. But there’s no easy way to take a bit from one and a bit from another.

Having said that, there’s nothing to stop one (or more) of the people doing the mods from collating them all in one super version (subject to practicalities like file size limits, which are a real issue). It’s just something I just don’t have the time to do.

Does your script library include all of the commands in Shane’s Dialog Toolkit?

Yes, as of version Dialog Toolkit Plus v1.1.2

I hope it gets included as a date field is often needed IMO, otherwise its just to easy for users to enter bad dates that require more work to error check.
In this case its pretty easy to add.

on display enhanced alert and on display enhanced window

gets this line added to:
repeat with aControl in controlsList

else if (aControl's isKindOfClass:(NSDatePicker)) as boolean then
set end of controlResults to aControl's stringValue() as text

Otherwise none of the other code is touched.
BTW thanks to shane for the original and those that have helped so far to advance it.

As Shane mentions later, no reason why we cant create a moded version(s) here.

This is the code that needs reviewed.
The other code thats added is just copied and changed for the dictionary commands and methods with the parameters for calling this code.

--** lv 1
on createDatePickerTextMainThread:theArg
	set {pickerStyle, pickerElements, initialDate, minDateSeconds, maxDateSeconds, theLeft, theBottom, theWidth, extraHeight} to theArg as list
	
	if pickerStyle = textual then
		set theTop to theBottom + 22 + extraHeight -- 22 without pickers
	else
		if pickerStyle = textual stepper then
			set theTop to theBottom + 27 + extraHeight -- 27 with pickers
		end if
	end if
	
	set theField to (NSDatePicker's alloc()'s initWithFrame:{{theLeft, theBottom}, {theWidth, theTop - theBottom}})
	--x, y, w, h
	
	if pickerStyle = textual then
		theField's setDatePickerStyle:(current application's NSTextFieldDatePickerStyle)
	else
		if pickerStyle = textual stepper then
			theField's setDatePickerStyle:(current application's NSTextFieldAndStepperDatePickerStyle)
		else
			--error
		end if
	end if
	
	if pickerElements = YearMonth then
		theField's setDatePickerElements:(current application's NSYearMonthDatePickerElementFlag)
	else
		if pickerElements = YearMonthDay then
			theField's setDatePickerElements:(current application's NSYearMonthDayDatePickerElementFlag)
		else
			if pickerElements = YearMonthDayHourMinute then
				theField's setDatePickerElements:((current application's NSYearMonthDayDatePickerElementFlag) + (current application's NSHourMinuteDatePickerElementFlag as integer))
			else
				if pickerElements = YearMonthDayHourMinuteSecond then
					theField's setDatePickerElements:((current application's NSYearMonthDayDatePickerElementFlag) + (current application's NSHourMinuteSecondDatePickerElementFlag as integer))
				else
					if pickerElements = HourMinute then
						theField's setDatePickerElements:(current application's NSHourMinuteDatePickerElementFlag)
					else
						if pickerElements = HourMinuteSecond then
							theField's setDatePickerElements:(current application's NSHourMinuteSecondDatePickerElementFlag)
						else
							--error set as a default ?
							theField's setDatePickerElements:((current application's NSYearMonthDayDatePickerElementFlag) + (current application's NSHourMinuteSecondDatePickerElementFlag as integer))
						end if
					end if
				end if
			end if
		end if
	end if
	
	set anNSDate to current application's NSDate's dateWithTimeInterval:0.0 sinceDate:initialDate
	--coerce applescript date to nsdate for the interval function below
	
	if minDateSeconds ≠ 0 then
		theField's setMinDate:(anNSDate's dateByAddingTimeInterval:minDateSeconds)
	end if
	if maxDateSeconds ≠ 0 then
		theField's setMaxDate:(anNSDate's dateByAddingTimeInterval:maxDateSeconds)
	end if
	
	tell theField
		--(its setEditable:true)
		(its setBordered:true)
		(its setBezeled:true)
		its (cell()'s setWraps:false)
		its setDateValue:anNSDate
		its setFrameSize:fittingSize()
	end tell
	-- return theField, the top of the field
	set my handlerResult to {theField, theTop}
end createDatePickerTextMainThread:

--** lv 2
on createDatePickerGraphicMainThread:theArg
	set {pickerElements, initialDate, minDateSeconds, maxDateSeconds, theLeft, theBottom, theWidth, extraHeight} to theArg as list
	set theTop to theBottom + 148 -- the controls size w 277 h 148 * w 139 h 148 without time
	set theField to (NSDatePicker's alloc()'s initWithFrame:{{theLeft, theBottom}, {theWidth, theTop - theBottom}})
	
	theField's setDatePickerStyle:(current application's NSClockAndCalendarDatePickerStyle)
	
	if pickerElements = YearMonth then
		set pickerElementsChoice to (current application's NSYearMonthDatePickerElementFlag)
	else
		if pickerElements = YearMonthDay then
			set pickerElementsChoice to (current application's NSYearMonthDayDatePickerElementFlag)
		else
			if pickerElements = YearMonthDayHourMinute then
				set pickerElementsChoice to ((current application's NSYearMonthDatePickerElementFlag) + (current application's NSHourMinuteDatePickerElementFlag as integer))
			else
				if pickerElements = YearMonthDayHourMinuteSecond then
					set pickerElementsChoice to ((current application's NSYearMonthDayDatePickerElementFlag) + (current application's NSHourMinuteSecondDatePickerElementFlag as integer))
				else
					if pickerElements = HourMinute then
						set pickerElementsChoice to (current application's NSHourMinuteDatePickerElementFlag)
					else
						if pickerElements = HourMinuteSecond then
							set pickerElementsChoice to (current application's NSHourMinuteSecondDatePickerElementFlag)
						else
							--error set as a default ?
							set pickerElementsChoice to ((current application's NSYearMonthDayDatePickerElementFlag) + (current application's NSHourMinuteSecondDatePickerElementFlag as integer))
						end if
					end if
				end if
			end if
		end if
	end if
	
	set anNSDate to current application's NSDate's dateWithTimeInterval:0.0 sinceDate:initialDate
	--coerce applescript date to nsdate for the interval function below
	
	if minDateSeconds ≠ 0 then
		theField's setMinDate:(anNSDate's dateByAddingTimeInterval:minDateSeconds)
	end if
	if maxDateSeconds ≠ 0 then
		theField's setMaxDate:(anNSDate's dateByAddingTimeInterval:maxDateSeconds)
	end if
	
	tell theField
		--(its setEditable:true)
		(its setBordered:true)
		(its setBezeled:true)
		its (cell()'s setWraps:false)
		its setDatePickerElements:pickerElementsChoice
		its setDateValue:anNSDate
		its setFrameSize:fittingSize()
	end tell
	-- return theField, the top of the field
	set my handlerResult to {theField, theTop}
end createDatePickerGraphicMainThread:

So when I run with the sample code in the dictionary and add this code to one of Shanes Example scripts (or just by itself), I get the following error:
The «class !MnS» parameter is missing for «event !ASuCrTp».
Any ideas what I am doing wrong?
Here is the code I am using

create datepicker textual stepper ¬
picker elements YearMonthDayHourMinute ¬
initial date ("1/1/2020") ¬
field width 500 ¬
extra height 100

It is probably something really boneheaded on my part.

I should add that I am on 10.13.6

Same here. I’m too unfamiliar with working with additional dictionaries to troubleshoot.

Your passing a string for the date

set {theDateField, theTop} to create datepicker textual stepper picker elements YearMonthDayHourMinute initial date (date "Wednesday, January 1, 2020 at 12:00:00 AM") min date seconds 0 max date seconds 0 left inset theLabelWidth + 8 bottom theTop + 4 field width 200 extra height 50

you also need
min date seconds 0 max date seconds 0
0 means you don’t want to limit the chosen date in anyway.

If you drop the script file on SD it will show you the dictionary.

You will need to learn how to use dialog toolkit in general.