[futurebasic] Re: [FB] Date/Time Control usage

Message: < previous - next > : Reply : Subscribe : Cleanse
Home   : December 2004 : Group Archive : Group : All Groups

From: bernie <fblist@...>
Date: Tue, 7 Dec 2004 14:38:01 +0000
Brian S wrote:

> I like the idea of using this control (_kControlClockDateProc) to 
> collect a date from a user. It has all the edits built-in and it is 
> simple to retrieve and set the date in the control. However, only 
> years on or after 1904 and prior to/including  2039 are selectable.


Here's a starter... It has a few limitations which I'm sure are 
overcomeable (!)

Everyone: please feel free to improve/correct the code.

N.B. Watch out for missing underscores and other nasties.


'----------
'~'A
'                       Runtime : Rntm Appearance.Incl
'                           CPU : Carbon
'                    CALL Req'd : Off
'~'B

/*

ClockDateControl_2041

Here's an attempt at persuading the editable variety of the ClockDate 
control
to accept dates outside the range 1 Jan, 1904 - 6 Feb, 2040.


LIMITATIONS:

1. Because I've used _kEventControlClick, the window containing the 
control needs _kWindowStandardHandlerAttribute.
2. Unfortunately, this version uses one too many globals (gMouseDelay).
3. Could do with a carbon timer in place of on timer event (maybe this 
would eliminate the global).
4. ...


Bernie Wylde   7 December 2004

*/

include "Tlbx HIView.Incl"
'~'<
_Window1Wnd = 1
_theDate = 1

begin enum 9
_kControlClockHourDayPart
_kControlClockMinuteMonthPart
_kControlClockSecondYearPart
_
_kControlClockUpArrowPart// made up constant name - bw
_kControlClockDownArrowPart// made up constant name - bw
end enum

begin enum 1
_jan
_feb
_mar
_apr
_may
_jun
_jul
_aug
_sep
_oct
_nov
_dec
end enum

begin globals
dim as short gMouseDelay
end globals

'~'1

local fn HIRectToRect(hiRect as ^HIRect)
dim as Rect r

r.left   = hiRect.origin.x
r.top    = hiRect.origin.y
r.right  = r.left + hiRect.size.width
r.bottom = r.top + hiRect.size.height
end fn = r

local fn IsValidDay(longDate as ^LongDateRec)
dim as Boolean bool

bool = _zTrue
if ((longDate.day < 1) or (longDate.day > 31)) then bool = _false : 
exit fn
select longDate.month
case _feb
if (longDate.day > 29) then bool = _false : exit case
long if (longDate.day == 29)
long if ((longDate.year mod 100 == 0) and (longDate.year mod 400))
bool = _false
xelse
if (longDate.year mod 4) then bool = _false
end if
end if
case _apr, _jun, _sep, _nov
if (longDate.day > 30) then bool = _false
end select
end fn = bool

local fn DateKey(btnNum as long, num as short)
dim as Str15            y
dim as LongDateRec    @ longDate
dim as HIViewPartCode @ partCode
dim as long           @ actual
dim as OSStatus         ignore
dim as Boolean          bool

bool = _false
def GetButtonData(btnNum, _kControlEditTextPart, 
_kControlClockLongDateTag, SizeOf(LongDateRec), @longDate, actual)
ignore = fn HIViewGetFocusPart(button&(btnNum), partCode)
select partCode
case _kControlClockHourDayPart
select longDate.day
'~'<
case 1
longDate.day = 10 + num
bool = _zTrue
'~'<
case 2
longDate.day = 20 + num
bool = fn IsValidDay(longDate)
'~'<
case 3
longDate.day = 30 + num
bool = fn IsValidDay(longDate)
end select

long if (bool == _false)
if num then longDate.day = num
end if
'~'<
case _kControlClockMinuteMonthPart
long if ((longDate.month == 1) and ((num >= 0) and (num <= 2)))
longDate.month = 10 + num
xelse
if (num) then longDate.month = num
end if

select longDate.month
case _feb
if (fn IsValidDay(longDate) == _false) then longDate.day = 29
if (fn IsValidDay(longDate) == _false) then longDate.day = 28
case _apr, _jun, _sep, _nov
if (fn IsValidDay(longDate) == _false) then longDate.day = 30
end select
'~'<
case _kControlClockSecondYearPart
y = mid$(str$(longDate.year), 2)
if (longDate.year < 1000) then y = "0" + y
if (longDate.year < 100) then y = "0" + y
if (longDate.year < 10) then y = "0" + y
y = mid$(y, 2) + mid$(str$(num), 2)
longDate.year = val(y)

long if (longDate.month == _feb)
if (fn IsValidDay(longDate) == _false) then longDate.day = 28
end if
end select
'~'<
def SetButtonData(btnNum, _kControlEditTextPart, 
_kControlClockLongDateTag, SizeOf(LongDateRec), @longDate)
end fn

local fn DateArrows(btnNum as long, dir as short)
dim as LongDateRec    @ longDate
dim as HIViewPartCode @ partCode
dim as long           @ actual
dim as OSStatus         ignore

def GetButtonData(btnNum, _kControlEditTextPart, 
_kControlClockLongDateTag, SizeOf(LongDateRec), @longDate, actual)
ignore = fn HIViewGetFocusPart(button&(btnNum), partCode)
select partCode
'~'<
case _kControlClockHourDayPart
longdate.day += dir
long if (fn IsValidDay(longDate) == _false)
long if (dir > 0)
longDate.day = 1
xelse
select longDate.month
case _feb
longDate.day = 29
if (fn IsValidDay(longDate) == _false) then longDate.day = 28
case _apr, _jun, _sep, _nov
longDate.day = 30
case else
longDate.day = 31
end select
end if
end if
'~'<
case _kControlClockMinuteMonthPart
longDate.month += dir
if (longDate.month > 12) then longDate.month = 1
if (longDate.month < 1) then longDate.month = 12

select longDate.month
case _feb
if (fn IsValidDay(longDate) == _false) then longDate.day = 29
if (fn IsValidDay(longDate) == _false) then longDate.day = 28

case _apr, _jun, _sep, _nov
if (fn IsValidDay(longDate) == _false) then longDate.day = 30
end select
'~'<
case _kControlClockSecondYearPart
longDate.year += dir
long if (longDate.month == _feb)
if (fn IsValidDay(longDate) == _false) then longDate.day = 28
end if
end select
'~'<
def SetButtonData(btnNum, _kControlEditTextPart, 
_kControlClockLongDateTag, SizeOf(LongDateRec), @longDate)
end fn

'~'1

local mode
local fn AddEventToHandle(eventClass as UInt32, eventKind as UInt32, h 
as Handle)
dim as EventTypeSpec evnt

evnt.eventClass = eventClass
evnt.eventKind  = eventKind
end fn = fn PtrAndHand(evnt, h, SizeOf(EventTypeSpec))

local fn InstallWindowEvents(w as WindowRef)
dim as Handle   eventH
dim as OSStatus ignore
begin globals
dim as Ptr sWindowEventHandlerUPP
end globals

long if (sWindowEventHandlerUPP == 0)
sWindowEventHandlerUPP = fn NewEventHandlerUPP([proc 
"WindowEventHandler" + _FBprocToProcPtrOffset])
end if
eventH = fn NewHandle(0)
long if (eventH)
'~'<
fn AddEventToHandle(_kEventClassMouse, _kMouseTrackingMouseUp,   eventH)
fn AddEventToHandle(_kEventClassMouse, _kMouseTrackingMouseDown, eventH)
'~'<
ignore = fn InstallEventHandler(fn GetWindowEventTarget(w), 
sWindowEventHandlerUPP, ¬
                                 fn 
GetHandleSize(eventH)\\(SizeOf(EventTypeSpec)), #[eventH], #0, #0)
DisposeHandle(eventH)
end if
end fn

local fn InstallControlEvents(c as ControlRef)
dim as Handle   eventH
dim as OSStatus ignore
begin globals
dim as Ptr sControlEventHandlerUPP
end globals

long if (sControlEventHandlerUPP == 0)
sControlEventHandlerUPP = fn NewEventHandlerUPP([proc 
"ControlEventHandler" + _FBprocToProcPtrOffset])
end if
eventH = fn NewHandle(0)
long if eventH
'~'<
fn AddEventToHandle(_kEventClassControl,  _kEventControlClick, eventH)
fn AddEventToHandle(_kEventClassControl,  _kEventControlHit,   eventH)
fn AddEventToHandle(_kEventClassKeyboard, _kEventRawKeyDown,   eventH)
fn AddEventToHandle(_kEventClassKeyboard, _kEventRawKeyRepeat, eventH)
'~'<
ignore = fn InstallEventHandler(fn GetControlEventTarget(c), 
sControlEventHandlerUPP, ¬
                                 fn 
GetHandleSize(eventH)\\(SizeOf(EventTypeSpec)), #[eventH], #0, #0)
DisposeHandle(eventH)
end if
end fn

long if 0
"ControlEventHandler"
enterproc fn ControlEventHandler(handler as EventHandlerCallRef, evnt 
as EventRef, userData as Ptr) = OSStatus
dim as LongDateRec    @ longDate
dim as Rect             r
dim as HIRect         @ hiRect
dim as HIPoint        @ hiPoint
dim as point          @ pt
dim as HIViewPartCode @ partCode
dim as ControlRef     @ c, focusCtrl
dim as UInt32           eventClass, eventKind
dim as long             result
dim as long           @ actual
dim as short            dir
dim as char           @ ch
dim as OSStatus         ignore

result = _EventNotHandledErr
eventClass = fn GetEventClass(evnt)
eventKind  = fn GetEventKind(evnt)
ignore = fn GetEventParameter(evnt, _kEventParamDirectObject, 
_TypeControlRef, #0, SizeOf(ControlRef), #0, @c)
select eventClass
'~'<
case _kEventClassControl
select eventKind
case _kEventControlClick
fn HIViewGetBounds(c, hiRect)
r = fn HIRectToRect(hiRect)
ignore = fn GetEventParameter(evnt, _kEventParamMouseLocation, 
_typeHIPoint, #0, SizeOf(HIPoint), #0, hiPoint)
pt.h = hiPoint.x
pt.v = hiPoint.y
GlobalToLocal(pt)

c = fn FindControlUnderMouse(pt, window(_wndRef), partCode)
HiliteControl(c, partCode)
select partCode
case _kControlClockHourDayPart, _kControlClockMinuteMonthPart, 
_kControlClockSecondYearPart
ignore = fn SetKeyboardFocus(window(_wndRef), c, partCode)

case _kControlClockUpArrowPart, _kControlClockDownArrowPart
if partCode == _kControlClockUpArrowPart then dir = 1 else dir = -1
gMouseDelay  = 5
fn DateArrows(usr Handle2Btn(c), dir)
result = _noErr
end select
'~'<
case _kEventControlHit
result = _noErr
end select
'~'<
case _kEventClassKeyboard
select eventKind
case _kEventRawKeyDown, _kEventRawKeyRepeat
ignore = fn GetEventParameter(evnt, _kEventParamKeyMacCharCodes, 
_typeChar, #0, SizeOf(char), #0, ch)
fn GetKeyboardFocus(window(_wndRef), focusCtrl)
select
case (ch >= _"0") and (ch <= _"9")
fn DateKey(usr Handle2Btn(focusCtrl), ch - 48)
result = _noErr
case (ch == _fbUpArrowKey)
fn DateArrows(usr Handle2Btn(focusCtrl), 1)
result = _noErr
case (ch == _fbDownArrowKey)
fn DateArrows(usr Handle2Btn(focusCtrl), -1)
result = _noErr
end select
end select
'~'<
end select
exitproc = result
end If

long if 0
"WindowEventHandler"
enterproc fn WindowEventHandler(handler as EventHandlerCallRef, evnt as 
EventRef, userData as Ptr) = OSStatus
dim as HIPoint         @ hiPoint
dim as Point           @ pt
dim as ControlRef      @ c
dim as UInt32            eventClass, eventKind
dim as ControlPartCode @ partCode
dim as long              result
dim as OSStatus          ignore

result = _EventNotHandledErr
eventClass = fn GetEventClass(evnt)
eventKind  = fn GetEventKind(evnt)
select eventClass
'~'<
case _kEventClassMouse
ignore = fn GetEventParameter(evnt, _kEventParamMouseLocation, 
_typeHIPoint, #0, SizeOf(HIPoint), #0, hiPoint)
pt.h = hiPoint.x
pt.v = hiPoint.y
GlobalToLocal(pt)
c = fn FindControlUnderMouse(pt, window(_wndRef), partCode)
select eventKind
case _kMouseTrackingMouseUp   : if (c) then HiliteControl(c, 0)
case _kMouseTrackingMouseDown : if (c == 0) then fn ClearAnyFocus
end select
'~'<
end select
exitproc = result
end If

'~'1

local fn BuildWindow1Wnd
dim as Rect r

SetRect(r, 0, 0, 350, 150)
appearance window -_Window1Wnd, "Pick a date... any date", @r, 
_kDocumentWindowClass, _kWindowStandardHandlerAttribute
def SetWindowBackground(_kThemeActiveDialogBackgroundBrush, _zTrue)
fn InstallWindowEvents(window(_wndRef))
'~'<
SetRect(r, 123, 65, 226, 88)
appearance button _theDate, _activeBtn, _kControlClockNoFlags,,,, @r, 
_kControlClockDateProc
fn InstallControlEvents(button&(_theDate))
'~'<
appearance window _Window1Wnd
end fn

local fn DoTimer
dim ev               as ^EventRecord
dim as Point           @ pt
dim as ControlPartCode @ partCode
dim as ControlRef        c
dim as short             dir

long if fn StillDown
ev = event
pt = ev.where
GlobalToLocal(pt)
c = fn FindControlUnderMouse(pt, window(_wndRef), partCode)
long if c
select partCode
case _kControlClockUpArrowPart   : dir = 1
case _kControlClockDownArrowPart : dir = -1
end select
gMouseDelay--
if (gMouseDelay < 0) then fn DateArrows(usr Handle2Btn(c), dir)
end if
end if
end fn

fn BuildWindow1Wnd

on timer(-6) fn DoTimer

do
HandleEvents
until gFBQuit











// Extra line spaces courtesy the FB4 Editor


'----------