#lang scheme/base
(require drscheme/tool
mred
mrlib/switchable-button
mrlib/path-dialog
mzlib/unit
scheme/path
scheme/class)
(provide tool@)
(define tool@
(unit
(import drscheme:tool^)
(export drscheme:tool-exports^)
(define (phase1) (void))
(define (phase2) (void))
(define project-icon "project.png")
(define project-icon-sm "project-sm.png")
(define home-dir (find-system-path 'home-dir))
(define saved-tabs-file (string->path "saved-tabs-file.sp"))
(define saved-tabs-file-path (build-path home-dir saved-tabs-file))
(define (projects-unit-frame-mixin super%)
(class super%
(inherit get-menu-bar get-button-panel register-toolbar-button)
(define save-tab-files
(lambda args
(for-each
(lambda (tab)
(let ([editor (send tab get-defs)])
(send editor save-file #f (send editor get-file-format) #t)
))
(send this get-tabs))
(send this update-shown)
))
(define (resolve-save-rel list-of-tab-file-abs-paths save-location-file-abs-path)
(let ((base (get-base-path save-location-file-abs-path)))
(map (lambda (tab-file-abs-path)
(path->string (find-relative-path base (simple-form-path tab-file-abs-path))))
list-of-tab-file-abs-paths)))
(define (resolve-load-rel save-location-file list-of-relative-tab-file-str)
(let ((base (get-base-path save-location-file)))
(map (lambda (relative-tab-file-str)
(build-path base (string->path relative-tab-file-str)))
list-of-relative-tab-file-str)))
(define (get-save-location suggested-starting-path)
(send (new path-dialog% [directory suggested-starting-path]
[put? #t]
[filename "saved-tabs-file.sp"]
[label "Save current tabs to.."]
[message "Save a tabs file"]
[filters (list (list "Scheme Project Files" "*.sp")
(list "Any" "*.*"))]
)
run))
(define (get-load-location suggested-starting-path)
(get-file "Load Tabs file" #f
suggested-starting-path
"saved-tabs-file.sp"
"sp"
'(enter-packages)
(list (list "Scheme Project Files" "*.sp")
(list "Any" "*.*")))
)
(define (save-tabs-to-file out-file)
(call-with-output-file out-file (lambda (i) (write (resolve-save-rel (get-tab-files) out-file) i))
#:exists 'replace
))
(define (reload-tab-from-file in-file)
(for-each (lambda (filename)
(drscheme:unit:open-drscheme-window (path->string filename)))
(let* ((rel-pathstr-list (call-with-input-file in-file (lambda (i) (read i))))
(abs-file-path-list (resolve-load-rel in-file rel-pathstr-list))
(normlized-abs-file-str-list (map simple-form-path abs-file-path-list)))
(remove* (get-tab-files) normlized-abs-file-str-list))))
(define (get-tab-files)
(filter (lambda (filename) filename)
(map (lambda (tab) (get-tab-filename tab))
(send this get-tabs))))
(define (get-base-path file) (let-values (((base-path name dir?) (split-path file)))
base-path))
(define (get-tab-filename tab)
(send (send tab get-defs) get-filename))
(define save-tabs
(lambda args
(let* ((this-tab (send this get-current-tab))
(file (get-tab-filename this-tab))
(save-location (if file (get-save-location (get-base-path file))
(get-save-location home-dir))))
(when save-location (save-tabs-to-file save-location)))))
(define reload-tabs
(lambda args
(let* ((this-tab (send this get-current-tab))
(file (get-tab-filename this-tab))
(load-location (if file (get-load-location (get-base-path file))
(get-load-location home-dir)
)))
(when load-location (reload-tab-from-file load-location)))))
(super-new)
(define project-menu
(new menu% [label "Project"] [parent (get-menu-bar)]))
(make-object separator-menu-item% project-menu)
(define menu-item-save-tabs (new menu-item%
[label "Save tabs list"]
[parent project-menu]
[callback save-tabs]))
(define menu-item-reload-tabs (new menu-item%
[label "Load tabs from saved list"]
[parent project-menu]
[callback reload-tabs]))
(make-object separator-menu-item% project-menu)
(define menu-item-save-tab-files (new menu-item%
[label "Save Tabs"]
[parent project-menu]
[callback save-tab-files]))
(send this update-shown)
(define project-icon-bitmap (make-object bitmap% project-icon-sm 'png/mask))
))
(drscheme:get/extend:extend-unit-frame projects-unit-frame-mixin)
))