#lang scheme/gui
(require "code-write.ss"
"properties.ss"
"mreddesigner-misc.ss"
)
(define/provide current-generate-code (make-parameter #f))
(define/provide mred-widget<%> (interface () ))
(define/provide (mred-widget%% c%)
(class* c% (mred-widget<%>)
(init-field mred-id)
(getter mred-id)
(super-new)
))
(define/provide mred-id%
(class (code-write%% object%)
(super-new)
(init-field
plugin
mred-parent
properties
[widget #f]
)
(field [mred-children '()]
)
(getter/setter widget properties plugin mred-parent)
(when mred-parent
(send mred-parent add-mred-child this))
(let ([props-def (send plugin make-properties)])
(set! properties
(map (λ(dp)(let ([p (findf (λ(p)(equal? (car dp) (car p)))
properties)])
(or p dp)))
props-def)))
(define/public (get-top-level-mred-id)
(if (is-a? mred-parent mred-id%)
(send mred-parent get-top-level-mred-id)
this))
(define/override (code-write-args)
(list (list 'plugin (list 'get-widget-plugin
(list 'quote (send plugin get-type))))
(list 'mred-parent (code-write-value mred-parent))
(list 'properties (code-write-value properties))
)
)
(define/public (get-property field-id)
(dict-ref properties field-id))
(define/public (get-property-value field-id)
(send (get-property field-id) get-value))
(define/public (get-id) (get-property-value 'id))
(define/public (set-random-id)
(send (send (get-property 'id) get-prop)
set-value (send plugin get-random-id)))
(define/public (is-type? t)
(equal? t (get-property-value 'type)))
(define/public (get-mred-children) (reverse mred-children))
(define/public (add-mred-child w)
(set! mred-children (cons w mred-children)))
(define/public (change-property-value field-id new-flat-val)
(send (send (dict-ref properties field-id) get-prop)
set-value new-flat-val))
(define (create-widget parent [props properties])
(set! widget (send plugin make-widget this parent props))
(set! properties props)
)
(define (get-parent-widget)
(and mred-parent
(send mred-parent get-widget)))
(define/public (can-change-child? child)
(and (object-method-arity-includes? widget 'change-children 1)
(member child (send widget get-children))
))
(define/public (replace-widget)
(recreate-top-level-window)
)
(define/public (recreate-widget-hierarchy [parent (get-parent-widget)])
(let ([shown (and (is-a? widget top-level-window<%>) (send widget is-shown?))])
(when shown
(close-window widget))
(set! widget (send plugin make-widget this parent properties))
(when (is-a? widget area-container<%>)
(send widget begin-container-sequence))
(for-each-send (recreate-widget-hierarchy widget) (get-mred-children))
(when (is-a? widget top-level-window<%>)
(send widget show shown)) (when (is-a? widget area-container<%>)
(send widget end-container-sequence))
widget))
(define/public (delete)
(for-each-send delete (get-mred-children))
(when (is-a? widget top-level-window<%>)
(close-window widget))
(when mred-parent
(send mred-parent delete-child this))
(show #f)
)
(define/public (show s)
(when (and widget (object-method-arity-includes? widget 'show 1))
(send widget show s)))
(define/public (show/hide)
(when (and widget (object-method-arity-includes? widget 'show 1))
(send widget show (not (send widget is-shown?)))))
(define/public (get-top-mred-parent)
(if mred-parent
(send mred-parent get-top-mred-parent)
this))
(define/public (get-top-level-window-mred-id)
(if (is-a? widget top-level-window<%>)
this
(and mred-parent
(send mred-parent get-top-level-window-mred-id))
))
(define/public (recreate-top-level-window)
(let ([tlw-mid (get-top-level-window-mred-id)])
(when tlw-mid
(send tlw-mid recreate-widget-hierarchy)
)))
(define/public (delete-child mid)
(set! mred-children (remq mid mred-children))
(let ([midw (send mid get-widget)])
(if (is-a? midw subwindow<%>)
(send widget delete-child midw)
(recreate-top-level-window))
))
(define/public (move-up)
(and mred-parent (send mred-parent move-up-child this)))
(define/public (move-up-child mid-child)
(set! mred-children (list-move-right mred-children mid-child))
(if (can-change-child? mid-child)
(send widget change-children
(λ(l)(list-move-left l (send mid-child get-widget))))
(recreate-top-level-window)
))
(define/public (move-down)
(and mred-parent (send mred-parent move-down-child this)))
(define/public (move-down-child mid-child)
(set! mred-children (list-move-left mred-children mid-child))
(if (can-change-child? mid-child)
(send widget change-children
(λ(l)(list-move-right l (send mid-child get-widget))))
(recreate-top-level-window)
))
(define/public (generate-options)
(append-map (λ(p)(if (send (cdr p) get-no-code)
'()
(send (cdr p) generate-option (string-append* (get-id) "-"))))
properties))
(define/public (generate-code)
(parameterize ([current-generate-code #t])
(let* ([parent-id (if mred-parent (send mred-parent get-id) #f)])
`(set! ,(get-id)
(new ,(send plugin get-code-gen-class-symbol)
(parent ,parent-id)
,@(append-map
(λ(p)(if (send (cdr p) get-no-code)
'()
(list (list (car p)
(send (cdr p) generate-code
(string-append* (get-id) "-"))))))
properties)
))
)))
(define/public (generate-post-code)
(send plugin generate-post-code this))
(create-widget (get-parent-widget))
))
(define/provide (get-all-children mid)
(cons mid
(append-map get-all-children
(send mid get-mred-children))))