#lang scheme/gui
(require "plugin.ss"
"mred-id.ss"
"properties.ss"
"mreddesigner-misc.ss"
)
(define/provide mred-plugin%
(class object% (super-new)
(init-field
type
tooltip
button-group [(make-properties-var make-properties)]
widget-class
widget-class-symbol code-gen-class-symbol parent-widget-class parent-widget-class-symbol
post-code
)
(field [dir-name #f]
[make-widget-proc #f]
[icon-bitmap #f]
)
(getter type tooltip button-group
widget-class-symbol code-gen-class-symbol
widget-class parent-widget-class parent-widget-class-symbol)
(getter/setter icon-bitmap dir-name)
(define/public (get-random-id)
(gensym (symbol-append* type '-)))
(define/public (make-properties) (make-properties-var))
(define/public (set-make-widget props) (set! make-widget-proc props))
(define/public (make-widget mred-id parent [properties (make-properties)])
(make-widget-proc mred-id parent properties))
(define/public (new-mred-id mid-parent)
(and (can-instanciate? mid-parent)
(new mred-id%
[plugin this]
[mred-parent mid-parent]
[properties (make-properties)])))
(define/public (can-instanciate? mid-parent) (can-instanciate-under? mid-parent parent-widget-class)
(let ([mid-parent-widget (and mid-parent (send mid-parent get-widget))]
[mid-parent-class (and mid-parent
(send (send mid-parent get-plugin)
get-widget-class))])
(or
(eq? #t parent-widget-class)
(and (not mid-parent-class) (not parent-widget-class))
(and (class? parent-widget-class)
(subclass? mid-parent-class parent-widget-class))
(and (list? parent-widget-class)
(ormap (λ(one-parent-class)(can-instanciate? mid-parent one-parent-class))
parent-widget-class))
(and (procedure? parent-widget-class) (parent-widget-class mid-parent-widget)) ))
)
(define/public (generate-post-code mid)
(post-code mid))
))
(define/provide (can-instanciate-under? mid-parent parent-widget-class)
(let ([mid-parent-widget (and mid-parent (send mid-parent get-widget))]
[mid-parent-class (and mid-parent
(send (send mid-parent get-plugin)
get-widget-class))])
(or
(eq? #t parent-widget-class)
(and (not mid-parent-class) (not parent-widget-class))
(and (class? parent-widget-class)
(subclass? mid-parent-class parent-widget-class))
(and (list? parent-widget-class)
(ormap (λ(one-parent-class)(can-instanciate-under? mid-parent one-parent-class))
parent-widget-class))
(and (procedure? parent-widget-class) (parent-widget-class mid-parent-widget)) )))
(define (make-prop:field-pair field-id prop options necessaries no-codes hiddens)
(cons field-id
(new prop:field-id% [value (flat-prop->prop prop)]
[field-id field-id]
[option (member? field-id options)]
[necessary (member? field-id necessaries)]
[no-code (member? field-id no-codes)]
[hidden (member? field-id hiddens)]
)))
(provide make-plugin)
(define-syntax-rule (make-plugin [mred-field val] ...
([field-id prop] ...)
)
(begin
(provide plugin-widget)
(define plugin-widget #f)
(let* ([mred-fields (list [list 'mred-field val] ...)] [mred-quoted-fields (list [list 'mred-field 'val] ...)] [mred-ref (λ(id [dft (λ()(error "key not found in mred-ref:" id))])
(assoc-ref mred-fields id dft))] [mred-quoted-ref (λ(id [dft (λ()(error "key not found in mred-quoted-ref:" id))])
(assoc-ref mred-quoted-fields id dft))] [type (mred-ref 'type)]
[widget-class-symbol (mred-quoted-ref 'widget-class)]
[code-gen-class-symbol (mred-quoted-ref 'code-gen-class widget-class-symbol)]
[options (mred-ref 'options '(callback))]
[necessaries (mred-ref 'necessary '())]
[no-codes (list* 'id (mred-ref 'no-code '()))] [hiddens (mred-ref 'hidden '())]
[make-field-pair (λ(id p)(make-prop:field-pair
id p options necessaries no-codes hiddens))]
)
(set! plugin-widget
(new mred-plugin%
[type type]
[tooltip (mred-ref 'tooltip)]
[button-group (mred-ref 'button-group)]
[widget-class (mred-ref 'widget-class)]
[widget-class-symbol widget-class-symbol] [code-gen-class-symbol code-gen-class-symbol] [parent-widget-class (mred-ref 'parent-class #t)]
[parent-widget-class-symbol (mred-quoted-ref 'parent-class #t)]
[post-code (mred-ref 'post-code (λ()(λ(mid)#f)))]
[make-properties
(λ()(list
(make-field-pair 'id (gensym (symbol-append* type '-)))
(make-field-pair 'code-gen-class (new prop:code% [value code-gen-class-symbol]
[value-code code-gen-class-symbol]))
(make-field-pair 'field-id prop)
...))]
))
(let ([properties-default (send plugin-widget make-properties)])
(send plugin-widget set-make-widget
(λ(mred-id parent properties)
(new (mred-widget%% (mred-ref 'widget-class))
[mred-id mred-id]
[parent parent]
[field-id (send (dict-ref
properties 'field-id
(λ()(dict-ref properties-default 'field-id)))
get-value)]
...
))
))
))
)
(define plugin-dict '())(define/provide (get-widget-plugins)
(map cdr plugin-dict))
(define (add-plugin p)
(set! plugin-dict
(append plugin-dict (list (cons (send p get-type) p)))))
(define/provide (get-widget-plugin type)
(dict-ref plugin-dict type #f))
(define/provide widget-plugins-path "widgets") (define/provide widget-icons-dir "icons")
(define/provide (load-mred-widget-plugins) (load-plugins
widget-plugins-path
(λ(dir-name)
(debug-printf "loading plugin: ~a\n" dir-name)
(let ([p (dynamic-require "widget.ss" 'plugin-widget)])
(send p set-dir-name dir-name)
(send p set-icon-bitmap
(make-object bitmap%
(build-path widget-icons-dir "16x16.png")
'png))
(add-plugin p)
))
)
(void)
)
(define (touch-plugin-files)
(load-plugins
widget-plugins-path
(λ(dir-name)
(let ([file (build-path "widget.ss")])
(debug-printf "plugin: ~a ~a\n" dir-name
(file-exists? file))
(file-or-directory-modify-seconds
file
(current-seconds))
))))