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.

ObjectStudio 8 New UI

The newest preview version of ObjectStudio 8.5 does include a preview package for the new UI framework. You must load the package using the parcel manager (Directories => parcels/preview)

The new UI is based on the Win32 APIs, MFC seems not to be used any more.

The base class is ObjectStudio.UIView. There is a class TestUI which one can use as a demo controller. The API calls are implemented in ObjectStudio.UIView.UILib.

To display a new empty window without any icons:

UIView initialize.
UIView new create.


 

I had to change the create and privateCreate methods in UIView to get this working.

create
    self isOpen ifTrue: [^self].
    UIView critical: 
            [self class createWindow: self.
            "hhk := self hookWindowCreate." 
            [self privateCreate] ensure: 
                    [self class createWindow: nil.
                    "self unhookWindowCreate: hhk"]]

privateCreate

    | aHwnd |
    aHwnd := self lib
                CreateWindowEx: self wndExStyle
                class: (self class wndClassName isString
                        ifTrue: [self class wndClassName gcCopyToHeapUnicode]
                        ifFalse: [self class wndClassName])
                window: self windowName gcCopyToHeapUnicode
                style: self wndStyle 
                x: self position x
                y: self position y
                width: self extent x
                height: self extent y
                parent: (self parent isNil ifTrue: [0] ifFalse: [self parent windowHandle])
                menu: 0
                hInst: 0
                lParam: 0.

    self windowHandle: aHwnd datum .
    self registerWindow: aHwnd datum.

    aHwnd datum = self windowHandle
        ifFalse: 
            [(UICreateWindowExError new)
                originalHwnd: self windowHandle;
                newHwnd: aHwnd datum;
                raiseSignal]


If you want a window with the standard windows icons:

(UIView new)
    style: UIView defaultStyle;
    create;
    setDefaultEvents.


In the TestUI class they do it a bit different (also this code does not display the left icon):

TestUI new testOpenWindow


Download code from here.
See also this post from Cincom.

Xpert.Ivy unter Debian mit Postgresql installieren

Eine kurze Anleitung wie man Xpert.Ivy 4.3.9 unter Debian Linux 6.0 "Squeeze" mit einer Postgresql Datenbank installieren kann.

Das folgende wurde auf einem gehosteten VServer von nine.ch durchgeführt.

Als erstes muss Postgresql installiert werden mit:

# apt-get install postgresql postgresql-client

Um später die Xpert.Ivy Systemdatenbank erstellen zu können, müssen die Init-DBs von Postgres mit UTF-8 Encoding erstellt werden. Da dies bei mir nach der Installation der Packages nicht so war, musste ich das von Hand durchführen.

Zuerst prüfen wir die vorhandenen (deutschen) Locales:
# locale -a | grep de_ 

Anschliessend löschen wir die bei der Installation erstellte Datenbank und erstellen sei neu:

# su postgres
# pg_dropcluster --stop 8.4 main
# pg_createcluster --locale de_CH.UTF-8 --start 8.4 main

Nun muss noch die "plgsql" Sprache installiert werden:

# su postgres
# createlang plpgsql template1


Und zum Schluss muss noch ein Benutzer für Xpert.Ivy erstellt werden:

# su postgres
# createuser ivy
# psql alter user ivy password 'x'


Admin Remote Zugriff
- pgAdmin downloaden
- apt-get install postgresql-contrib
- psql postgres -f adminpack.sql
- postregsql.conf => listen *
- pg_ => host hinzuguegen

 Xpert.Ivy konfigurieren
- wget http://...zip - unzip installieren ?
- Lizenzdatei kopieren
- ./XpertIvyServerConfig.sh -headless

 Links
http://wiki.debian.org/PostgreSql
 http://supriyadisw.net/installing-postgresql-on-debian.html