В рамках сооружения нового слоя модели для alterator. Сейчас идёт работа
над "языком форм" alterator. У нас будет использоваться классическая
модель MVC. Кстати сразу, если кто знает ещё какие хорошие модели - шлите
урлы, попробуем и их на зуб.

Задачи которые мы хотим решить:
1. Облегчить пользователю соединение между слоем backend и слоем ui.
   Это у нас будет обеспечиваться за счёт предоставление большого числа
   готовых view и controller'ов.
2. Обеспечить возможность сотворения формы из отдельных фрагментов,
инсталлируемых по мере необходимости. (user: ldap + postfix + samba + ...)

1. Создание view.
   Каждый view есть некий "виджет" со стандартным набором атрибутов.
   Для view поля это: field-name,field-value,field-data. Первые сами
   говорят за себя, последний атрибут - доп. данные , например список для 
combobox.

   Виджет может быть реализован на браузере интерфейса, а может быть
   создан из готовых кусочков, вот например так как показано ниже:

----------------
(document:surround "/std/base")

(document:envelop  with-proxy-attributes
                   ((field-name ((proxy-set self value) (lbl text value))
                                ((proxy-get self value) (lbl text)))
                    (field-data ((proxy-set self value) #f);;ignore
                                ((proxy-get self) #f));;ignore
                    (field-value ((proxy-set self value) (txt text value))
                                 ((proxy-get self) (txt text)))))

type "hbox"
layout-policy 100 -1

(document:id lbl (label "" layout-policy 50 -1))
(document:id txt (edit "" layout-policy -2 -1))
----------------

2. Создание контроллера для view.
   Контроллер есть объект (см. соотв. документацию на alterator, про объектную 
систему), со стандартными 
   методами.
   Например для контроллера поля это есть: field-update, field-commit.
   Для контроллера формы это есть: form-update, form-commit.
   

3. Соединяем это всё вместе. В alterator мы можем позволить себе при
создании UI "склеивать" view с их контролерами. Поэтому после конструирования 
мы работаем с этим конгломератом.
Этот комментарий для понимания кода, простому пользователю можно с этим даже не 
заморачиваться.

4. Простейший пример формы:

4.1 Контроллер формы simple-object - работает с экземпляром того или иного
класса. В данном случае с экземплярами класса "/local_users".
-----
(define (simple-object class)
  (object #f
          ((form-update self name)
           (define-operation list-subwidgets)
           (define-operation field-update #f)
           (let ((cmd (woo-read-first (string-append class "/" name))))
             (for-each (lambda(f) (field-update f cmd))
                       (list-subwidgets self))))
          ((form-commit self name)
           (define-operation list-subwidgets)
           (define-operation field-commit '())
           (apply woo-write (string-append class "/" name)
                  (append-map (lambda(f) (field-commit f))
                              (list-subwidgets self))))))
-----
(Note: мусор в виде define-operation может быть вынесен в стандартные
библиотеки)

4.1 Контроллер поля simple-property - работает индивидуально с конкретным
свойством того или иного экземпляра класса.
---
(define (simple-property property)
  (object #f
          ((field-update self obj)
             (self field-value (woo-get-option obj property)))
          ((field-commit self)
           (list property (self field-value)))))
---

4.2 Каждое поле создаётся командой:
(field "url-view" "name" controller <другие параметры к view>)
Где url-view - урл документа, содержащего описание view данного поля.
Для простых пользователей планируется заготовить набор стандартных view, и 
контроллеров.
Пример:
----------
(field '/fields/text "My property (simple-property 'property))
----------

4.3 Каждая форма создаётся командой:
(form "url-view" "name" controller <поля и другие параметры к view>)
Например:
----------
(form '/fields/prop-list "My object" (simple-object '/some_users)
       layout-policy 100 30
       (field ... )
       ...)
----------

4.4 Ниже приведён полный пример формы, для пользователей.
    Обратите внимание, что кнопки управления вынесены из view по имени 
"/std/vbox" (стандартная вертикальная группа виджетов), но ничто не препятсвует 
сделать управление прямо внутри view. Зато можно посмотреть на то как при 
желании
    можно обращаться с наружи к этому конгломерату "view + controller".
    Также обратите внимание. что при необходимости можно смешивать поля и 
другие виджеты произвольной природы.

---------------
(document:id f1
             (form "/std/vbox" "User's properties" (simple-object 
"/local_users")
                   layout-policy 100 -1
                   (field  "/b" "Comment:" (simple-property 'gecos))
                   (label "Not a field in the form")
                   (field  "/b" "Home:" (simple-property 'home))
                   (field  "/b" "Shell:" (simple-property 'shell))))
(hbox
 (document:id username (edit "<username>"))
 (button "Update"
         (when clicked
           (define-operation form-update)
           (form-update f1 (username text))))
 (button "Commit"
         (when clicked
           (define-operation form-commit)
           (form-commit f1 (username text)))))
--------------

В аттаче приложены файлы, чтобы можно было запустить этот пример в своём
alterator.

--
С наилучшими пожеланиями
Станислав Иевлев.
(document:surround "/std/base")

(document:envelop with-attributes
                   (field-name field-value field-data
                    form-name))

(define (field url name controller . args)
  (let ((widget (document:subdocument url)))
   (apply widget field-name name args)
   (join widget
         controller
         (object #f ((extract-widget self) widget)))))


(define (form url name controller . args)
  (let ((widget (document:subdocument url)))
    (apply widget form-name name args)
    (join widget
          controller
          (object #f ((extract-widget self) widget)))))


(define (simple-property property)
  (object #f
          ((field-update self obj)
             (self field-value (woo-get-option obj property)))
          ((field-commit self)
           (list property (self field-value)))))

(define (simple-object class)
  (object #f
          ((form-update self name)
           (define-operation list-subwidgets)
           (define-operation field-update #f)
           (let ((cmd (woo-read-first (string-append class "/" name))))
             (for-each (lambda(f) (field-update f cmd))
                       (list-subwidgets self))))
          ((form-commit self name)
           (define-operation list-subwidgets)
           (define-operation field-commit '())
           (apply woo-write (string-append class "/" name)
                  (append-map (lambda(f) (field-commit f))
                              (list-subwidgets self))))))


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(document:id f1
             (form "/std/vbox" "User's properties" (simple-object 
"/local_users")
                   layout-policy 100 -1
                   ;;(document:insert-all '/lll)
                   (field  "/b" "Comment:" (simple-property 'gecos))
                   (label "Not a field in the form")
                   (field  "/b" "Home:" (simple-property 'home))
                   (field  "/b" "Shell:" (simple-property 'shell))))

(hbox
 (document:id username (edit "<username>"))
 (button "Update"
         (when clicked
           (define-operation form-update)
           (form-update f1 (username text))))
 (button "Commit"
         (when clicked
           (define-operation form-commit)
           (form-commit f1 (username text)))))
(document:surround "/std/base")

(document:envelop  with-proxy-attributes
                   ((field-name ((proxy-set self value) (lbl text value))
                                ((proxy-get self value) (lbl text)))
                    (field-data ((proxy-set self value) #f);;ignore
                                ((proxy-get self) #f));;ignore
                    (field-value ((proxy-set self value) (txt text value))
                                 ((proxy-get self) (txt text)))))

type "hbox"
layout-policy 100 -1

(document:id lbl (label "" layout-policy 50 -1))
(document:id txt (edit "" layout-policy -2 -1))
_______________________________________________
Devel-conf mailing list
[email protected]
https://lists.altlinux.org/mailman/listinfo/devel-conf

Ответить