#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?))])
(debug-printf "recreate-widget-hierarchy: enter\n")
(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 area-container<%>)
(send widget end-container-sequence))
(when (is-a? widget top-level-window<%>)
(send widget show shown))
(debug-printf "recreate-widget-hierarchy: exit\n")
widget))
(define/public (delete)
(debug-printf "delete: enter\n")
(when (is-a? this top-level-window<%>)
(close-window this))
(show #f)
(when (is-a? this area-container<%>)
(send this begin-container-sequence))
(for-each-send delete (get-mred-children))
(when (is-a? this area-container<%>)
(send this end-container-sequence))
(when mred-parent (send mred-parent delete-child this))
(debug-printf "delete: exit\n")
(void)
)
(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-project-dir)
(let* ([top-mid (get-top-mred-parent)] [proj-file (send top-mid get-property-value 'file)]
[base-dir (and proj-file (path-only (string->path proj-file)))])
base-dir))
(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)]
[base-dir (get-project-dir)]
)
(when tlw-mid
(parameterize ([current-directory (or base-dir (current-directory))])
(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<%>)
(when (member midw (send widget get-children))
(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-pre-code)
(parameterize ([current-property-mred-id this])
(append (send plugin generate-pre-code this)
(append-map (λ(p)(if (send (cdr p) get-no-code)
'()
(send (cdr p) generate-pre-code)))
properties))))
(define/public (generate-options)
(parameterize ([current-property-mred-id this])
(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]
[current-property-mred-id this])
(let* ([parent-id (if mred-parent (send mred-parent get-id) #f)]
[id (get-id)]
[prefix (string-append* id "-")])
`(set! ,id
(new ,(send (get-property 'code-gen-class)
generate-code prefix)
(parent ,parent-id)
,@(append-map
(λ(p)(if (or (send (cdr p) get-no-code)
(equal? (car p) 'code-gen-class))
'()
(list (list (car p)
(send (cdr p) generate-code prefix)))))
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))
)
)