Montag, 13. Mai 2013

ObjectStudio 8 New UI: DateTimePicker (Part 1)

The DateTimePicker (Class UIDateTimePicker) is the first control I am going to have a more detailled look at.

Open a demo like this:

TestUI new testOpenUIDateTimePicker

Do not forget to call UIView initialize before.


We now add the functionality to set a Date before opening the control and to enable the DTS_SHOWNONE style.

Adding a value: method

I do not know how exactly the new UI API to set values will look like, so I just implement a value: method to try it out.

value: aTimestamp
    self dateOrTime: aTimestamp.
    self setSystemTime: aTimestamp.

setSystemTime: aTimestamp
    self privateSetSystemTime: aTimestamp.

 privateSetSystemTime: aTimestamp
    | st res |

    st := self lib SYSTEMTIME gcCalloc.
    aTimestamp isNil ifFalse: [
        st 
            memberAt: #wYear put: aTimestamp date year;
            memberAt: #wMonth put: aTimestamp date months;
            memberAt: #wDay put: aTimestamp date dayOfMonth;
            memberAt: #wHour put: aTimestamp time hours;
            memberAt: #wMinute put: aTimestamp time minutes;
            memberAt: #wSecond put: aTimestamp time seconds;
            memberAt: #wMilliseconds put: aTimestamp time milliseconds.
        ].

    res := self lib
                SendMessage: self windowHandle
                msg: DTM_SETSYSTEMTIME
                wParam: (aTimestamp isNil ifTrue: [GDT_NONE] ifFalse: [GDT_VALID])
                lParam: (st ifNotNil: [st referentAddress]).
    ^res

create
    super create.
    dateOrTime ifNotNil: [
        self setSystemTime: dateOrTime.
    ].

Adding the DTS_SHOWNONE style

To add the DTS_SHOWNONE style we need to add it to the styles before creating the control. Setting it afterwards does not seem to work. In the example code we will close and create the control when the setShowNoneTo: method is called and the control is already open. Better would be to only set this style before creating it, maybe the Designer for the new UI will include some options to add styles.

Closing and (re-)creating the same control does not work in the current preview because the hwnd instance variable is not set to nil after destroying the view (I am not shure if this is by intent or not). So I added the following overwrite to UIView:

UIView>>close
    self privateClose.
    self privateDestroy.
    self hwnd: nil.

In the Date and Time Picker control you need to check some results for GDT_NONE (Checkbox is unset) and GDT_VALID (Checkbox is set and the Date Time is valid). Here is the complete code for UIDateTimePicker.

setShowNoneTo: aBoolean
    aBoolean ifTrue: [
        "SetStyle does not change the style attribute"
        self setStyle: DTS_SHOWNONE.
        self style: (self style bitOr: DTS_SHOWNONE).
    ] ifFalse: [
        self removeStyle: DTS_SHOWNONE.
        self style: (self style bitAnd: DTS_SHOWNONE bitInvert).
    ].

    "Seems we need to recreate to apply this style"
    self isOpen ifTrue: [
        self close; create.
    ].

getShowNone
    self isOpen ifFalse: [^false].
    ^(self privateGetStyle bitAnd: DTS_SHOWNONE) > 0

privateGetSystemTime
    | st res |
    st := self lib SYSTEMTIME gcCalloc.
    res := self lib
                SendMessage: self windowHandle
                msg: DTM_GETSYSTEMTIME
                wParam: 0
                lParam: st referentAddress.
    ^res == GDT_VALID
        ifTrue: [self lib timestampFromSysTime: st contents]
        ifFalse: [nil]

privateDateTimeChange: aNotifyEvent
    | struct oldTs |
    struct := self lib LPNMDATETIMECHANGE cast: aNotifyEvent lParam.

    (struct memberAt: #dwFlags) == GDT_NONE
        ifTrue: 
            [oldTs := self dateOrTime.
            self dateOrTime: nil.
            oldTs ifNotNil: [self announce: (UIChangeAnnouncement before: oldTs after: self dateOrTime)]].

    (struct memberAt: #dwFlags) == GDT_VALID
        ifTrue: 
            [oldTs := self dateOrTime.
            self dateOrTime: (self lib timestampFromSysTime: (struct memberAt: #st)).
            self dateOrTime = oldTs
                ifFalse: [self announce: (UIChangeAnnouncement before: oldTs after: self dateOrTime)]].

Test it

Write a Test class method in TestUI like:

testOpenUIDateTimePickerEx
    | view value |

    value := (Timestamp fromDate: {2000 1 1} asDate andTime: (Time fromSeconds: 0)).
    
    view := self new testOpenUIDateTimePicker.
    view ctrl1 value: value. 

    view ctrl1 setShowNoneTo: true.
    self new ctrl1 getSystemTime out.
    
    view ctrl1 value: nil.
    self new ctrl1 getSystemTime out.

    view ctrl1 setShowNoneTo: false.
    self new ctrl1 getSystemTime out.

    self new testCloseUIDateTimePicker


Or try in using the workspace.


Next I will show how to change the display style (short, long).

Download code from here.

Keine Kommentare: