Hi Tomas,

> I tried httpGate and found that it makes apps significantly less
> responsive compared to connecting directly via specific port.  Is that
> expected behaviour?

Hm, strange. 'httpGate should not be a bottleneck, and I never observed
any slow down.

How strong is the effect (e.g. in millisecs)? Could you perhaps try to
locate the reason? For example, can you see where it possibly hangs
if you start it as

   strace -f /.../httpGate ...



> I found that if I choose [New] in the example app/ and then do not
> fill anything in the dialog and do not choose [Save], a new db object
> is created even though it is possibly not valid (e.g. if +Need is
> specified for some field).  This is due to the fact that the db object
> is created before user choses [Save] in the dialog:
> 
> (gui '(+Button) ,"New" '(newUrl '(+A) '(f genKey 'f '+A)))
> 
> Is it a bug or am I doing something wrong?

No, but this is the desired behavior :-)

A new object is created immediately if you press the "New" button,
because the following GUI page needs that object to be operative. The
behavior of most components in that page depends on the underlying
object.

IMHO, It does no harm if the object is not yet completely filled in.
Even more, the user should not be forced to enter all data immediately,
he may decide to continue his work later. The object is created if the
user says so, it can be found from now on in search dialogs, or he can
decide to delete it later.

Also, many constraints may depend on mutual conditions, where you have
to enter data on possibly different objects and locations, until these
conditions can be checked.

So the philosophy in that GUI is to let the user continue to work as he
likes, and postpone critical checks until these data are really needed.


Real-world applications have a 'check>' method for most classes.
Unfortunately, the demo "app/" does not contain an example for this.

A typical case would be the '+Ord' class to have a 'check>' method,
checking that this order has a number, a date, a customer, and at least
one position, and a button in the GUI to actually "book" or "close" that
order. The 'check>' method usually recursively calls the 'check>' method
of connected objects (here the data in the customer object (name,
address etc.) and the articles in the postion objects (prices etc.).

Then the user can enter and modify data as needed, and in the final step
of closing that order it will be verified.

But all this is a philosophical issue, any application is free to
implement additional checks at each stage. This was all omitted
in the demo "app/" to keep it simple.


OK, having said this, I should provide an example. For the matter of
demonstration, I implemented those checks for the demo app (see
attachments). They are called when the "PDF-Print" button is pressed
(this demo never "closes" orders).

I don't know if I should keep them in the official release. The problem
is that all these messages have to be translated :-(



> Suppose I have two classes +A and +B with m-n relationship f:
> 
> (class +A)

BTW, please don't forget to inherit from '+Entity':

   (class +A +Entity)


> (rel f (+List +Joint) f (+B))
> 
> (class +B)
> (rel f (+List +Joint) f (+A))
> 
> What is the easiest way to display and edit the f field (link
> instances of +A and +B together)?  I thought of something like
> <select> with "multiple" attribute but what is the picolisp way
> (reusing existing components)?
> 
> (gui '(+E/R ???) '(f : home obj) ???)

Each object of '+A' or '+B' have a list of objects of the other class.
So the recommended way is to have a '+Chart' on each side.

            (gui '(+E/R +Chart) '(f : home obj) ..)

The contents of these charts depend very much on what should be
displayed of each object. I think there are some applicable examples in
"app/" and "doc/family.l".

Select boxes with multiple selections are currently not supported.



> There is bin/psh mentioned in app dev manual.  How do I eval an
> expression in the picolisp server it is attached to?  The repl seems
> to be local but what if I want to change and inspect something in the

Yes, it runs in a child process (like each of the connected GUIs) of the
application server.

> running server without stopping it?

You can do manual changes to the DB witout problems. Any 'put!>' etc.
will be properly propagated.


However, if you really want to change something in the parent process
(e.g. loading a file or modifying a global variable), there is the
"boss" mechanism.

To use it, "main.l" should include

   (load "lib/boss.l")

Then you can say in 'psh' things like:

   (boss 'load "someAdditionalFile.l")

or

   (boss 'setq '*GlobalVariable 123)

so that further child processes will inherit these changes.

Cheers,
- Alex
# 14apr08abu
# (c) Software Lab. Alexander Burger

### Entity/Relations ###
#
#           nr    nm                   nr    nm               nm
#            |    |                     |    |                |
#          +-*----*-+                 +-*----*-+           +--*-----+
#          |        |             sup |        |           |        |
#    str --*  CuSu  O-----------------*  Item  *-- inv     |  Role  @-- perm
#          |        |                 |        |           |        |
#          +-*-*--O-+                 +----O---+           [EMAIL PROTECTED]
#            | |  |                        |                    | usr
#   nm  tel -+ |  |                        |                    |
#    |         |  |                        | itm                | role
#  +-*-----+   |  |   +-------+        +---*---+           +----*---+
#  |       |   |  |   |       |    ord |       |           |        |
#  |  Sal  +---+  +---*  Ord  @--------*  Pos  |      nm --*  User  *-- pw
#  |       |      cus |       | pos    |       |           |        |
#  +-*---*-+          +-*---*-+        +-*---*-+           +--------+
#    |   |              |   |            |   |
#   hi   sex           nr  dat          pr   cnt

(extend +Role)

(dm url> (Tab)
   (and (may RoleAdmin) (list "app/role.l" '*ID This)) )


(extend +User)
(rel nam (+String))                             # Full Name
(rel tel (+String))                             # Phone
(rel em  (+String))                             # EMail

(dm url> (Tab)
   (and (may UserAdmin) (list "app/user.l" '*ID This)) )


# Salutation
(class +Sal +Entity)
(rel nm  (+Key +String))                        # Salutation
(rel hi  (+String))                             # Greeting
(rel sex (+Any))                                # T:male, 0:female

(dm url> (Tab)
   (and (may Customer) (list "app/sal.l" '*ID This)) )

(dm hi> (Nm)
   (or (text (: hi) Nm) ,"Dear Sir or Madam,") )


# Customer/Supplier
(class +CuSu +Entity)
(rel nr  (+Need +Key +Number))                  # Customer/Supplier Number
(rel sal (+Link) (+Sal))                        # Salutation
(rel nm  (+Sn +Idx +String))                    # Name
(rel nm2 (+String))                             # Name 2
(rel str (+Ref +String))                        # Street
(rel plz (+Ref +String))                        # Zip
(rel ort (+Ref +String))                        # City
(rel cty (+Ref +String))                        # Country
(rel tel (+Fold +Ref +String))                  # Phone
(rel fax (+String))                             # Fax
(rel mob (+Fold +Ref +String))                  # Mobile
(rel em  (+String))                             # EMail
(rel txt (+Blob))                               # Memo

(dm url> (Tab)
   (and (may Customer) (list "app/cusu.l"  '*Tab Tab  '*ID This)) )

(dm check> ()
   (make
      (or (: nr) (link ,"No customer number"))
      (or (: nm) (link ,"No name"))
      (unless (and (: str) (: plz) (: ort))
         (link ,"Incomplete address") ) ) )


# Item
(class +Item +Entity)
(rel nr  (+Need +Key +Number))                  # Item Number
(rel nm  (+Sn +Idx +String))                    # Item Description
(rel sup (+Ref +Link) NIL (+CuSu))              # Supplier
(rel inv (+Number))                             # Inventory
(rel pr  (+Ref +Number) NIL 2)                  # Price
(rel txt (+Blob))                               # Memo
(rel jpg (+Blob))                               # Picture

(dm url> (Tab)
   (and (may Item) (list "app/item.l" '*ID This)) )

(dm cnt> ()
   (-
      (or (: inv) 0)
      (sum '((This) (: cnt))
         (collect 'itm '+Pos This) ) ) )

(dm check> ()
   (make
      (or (: nr) (link ,"No item number"))
      (or (: nm) (link ,"No item description")) ) )


# Order
(class +Ord +Entity)
(rel nr  (+Need +Key +Number))                  # Order Number
(rel dat (+Need +Ref +Date))                    # Order date
(rel cus (+Ref +Link) NIL (+CuSu))              # Customer
(rel pos (+List +Joint) ord (+Pos))             # Positions

(dm url> (Tab)
   (and (may Order) (list "app/ord.l" '*ID This)) )

(dm sum> ()
   (sum 'sum> (: pos)) )

(dm check> ()
   (make
      (or (: nr) (link ,"No order number"))
      (or (: dat) (link ,"No order date"))
      (or (: cus) (link ,"No customer"))
      (and (: cus) (check> @) (chain @))
      (or (: pos) (link ,"No positions"))
      (chain (mapcan 'check> (: pos))) ) )


(class +Pos +Entity)
(rel ord (+Dep +Joint) (art) pos (+Ord))        # Order
(rel itm (+Ref +Link) NIL (+Item))              # Item
(rel pr  (+Number) 2)                           # Price
(rel cnt (+Number))                             # Quantity

(dm sum> ()
   (* (: pr) (: cnt)) )

(dm check> ()
   (make
      (or (: itm) (link ,"Position without item"))
      (and (: itm) (check> @) (chain @))
      (or (: pr) (link ,"Position without price"))
      (or (: cnt) (link ,"Position without quantity")) ) )


# Database sizes
(dbs
   (1 +Role +User +Sal)                         # (1 . 128)
   (2 +CuSu)                                    # (2 . 256)
   (1 +Item +Ord)                               # (3 . 128)
   (0 +Pos)                                     # (4 . 64)
   (2 (+Role nm) (+User nm) (+Sal nm))          # (5 . 256)
   (3 (+CuSu nr nm str plz ort cty tel mob))    # (6 . 512)
   (3 (+Item nr nm sup pr))                     # (7 . 512)
   (3 (+Ord nr dat cus) (+Pos itm)) )           # (8 . 512)

# vi:et:ts=3:sw=3
# 14apr08abu
# (c) Software Lab. Alexander Burger

(must "Order" Order)

(menu ,"Order"
   (ifn *ID
      (prog
         (<h3> NIL ,"Select" " " ,"Order")
         (form 'dialog (choOrd T)) )
      (<h3> NIL ,"Order")
      (form NIL
         (<h2> NIL (<id> (: nr)))
         (panel T ,"Order No. @1" '(may Delete) '(choOrd T) 'nr '+Ord)
         (<grid> 4
            ,"Date" NIL
            (gui '(+E/R +DateField) '(dat : home obj) 10)
            (gui '(+View +TextField)
               '(text ,"(@1 Positions)" (length (: home obj pos))) )
            ,"Customer" (gui '(+ChoButton) '(choCuSu (field 1)))
            (gui '(+E/R +Obj +TextField) '(cus : home obj) '(nm +CuSu) 30)
            (gui '(+View +TextField) '(field -1 'obj 'ort) 30) )
         (----)
         (gui '(+Set +E/R +Chart) '((L) (filter bool L)) '(pos : home obj) 8
            '((Pos I)
               (with Pos
                  (list I NIL (: itm) (or (: pr) (: itm pr)) (: cnt) (sum> 
Pos)) ) )
            '((L D)
               (cond
                  (D
                     (put!> D 'itm (caddr L))
                     (put!> D 'pr (cadddr L))
                     (put!> D 'cnt (get L 5))
                     (and (get D 'itm) D) )
                  ((caddr L)
                     (new! '(+Pos)
                        'ord (: home obj)
                        'itm (caddr L) ) ) ) ) )
         (<table> NIL NIL
            '((align) (btn) (NIL ,"Item") (NIL ,"Price") (NIL ,"Quantity") (NIL 
,"Total") (btn) (btn))
            (do 8
               (<row> NIL
                  (gui 1 '(+NumField))
                  (gui 2 '(+ChoButton) '(choItem (field 1)))
                  (gui 3 '(+Obj +TextField) '(nm +Item) 30)
                  (gui 4 '(+FixField) 2 12)
                  (gui 5 '(+NumField) 8)
                  (gui 6 '(+Sgn +Lock +FixField) 2 12)
                  (gui 7 '(+DelRowButton))
                  (gui 8 '(+BubbleButton)) ) )
            (<row> NIL NIL NIL (scroll 8) NIL NIL
               (gui '(+Sgn +View +FixField) '(sum> (: home obj)) 2 12) ) )
         (<spread>
            (gui '(+Rid +Button) ,"PDF-Print"
               '(if (check> (: home obj))
                  (note ,"Can't close order" (uniq @))
                  (psOut 0 ,"Order" (ps> (: home obj))) ) )
            (editButton T) ) ) ) )

# vi:et:ts=3:sw=3

Reply via email to