[e-cvs] cvs commit: e/src/esrc/scripts eDesk.e intro.updoc

markm@eros.cs.jhu.edu markm@eros.cs.jhu.edu
Sat, 27 Oct 2001 13:34:08 -0400


markm       01/10/27 13:34:08

  Added:       src/esrc/com/skyhunter/e/awt/dnd dragDropKit.emaker
               src/esrc/com/skyhunter/e/net moreRecentVowFuncMaker.emaker
               src/esrc/com/skyhunter/e/util stackTraceFunc.emaker
               src/esrc/com/skyhunter/eDesk
                        navPanelControllerMakerAuthor.emaker
                        serverDescVowAuthor.emaker testConfigurator.updoc
                        testNavPanel.e testNavPanel.updoc
               src/esrc/com/skyhunter/eDesk/icons folder.gif
               src/esrc/scripts eDesk.e intro.updoc
  Log:
  New eDesk files, for the new eDesk, some of whose files were committed
  in the previous 'cvs commit'

Revision  Changes    Path
1.1                  e/src/esrc/com/skyhunter/e/awt/dnd/dragDropKit.emaker

Index: dragDropKit.emaker
===================================================================

//Copyright (C) 2001 Combex. All Rights Reserved.

def dragDropKitAuthor(awt__uriGetter, traceln) :near {
    def dragDropKit {
        #uses class java.awt.dnd.DropTargetEvent in specifying
        #dataflavor only so there is a concrete class for the 
        #dataflavor (java.lang.Object does not work!)
        #Users of the E dnd system must specify a reactor
        # to mimeType := DataFlavor javaJVMLocalObjectMimeType() +
        #              "; class=java.awt.dnd.DropTargetEvent"
        #to transfer eobjects
        to makeTransferableLocalEObject(eObject) :near {
            def DataFlavor := <awt:datatransfer.DataFlavor>
                    def mimeType := DataFlavor javaJVMLocalObjectMimeType() +
                      "; class=java.awt.dnd.DropTargetEvent"
            def transferable {
                to getTransferData(flavor) :near {
                    eObject
                }
                to getTransferDataFlavors() :any {
                    traceln("getting transfer flavors")
                    def flavors := [DataFlavor new(mimeType)]
                    traceln("transfer flavors: " + flavors)
                    flavors 
                }
                to isDataFlavorSupported(flavor) :boolean {
                    flavor isMimeTypeEqual(mimeType)
                }
                match [verb, args] {
                    traceln("BAD: transfer got surprise message: " + verb)
                }
            }
        }
        to setupLocalDragSource(component, localEObjectFunc) {
            def dragSourceListener {
                to dragDropEnd(blah1) {traceln("drag source sees dragdropend")}
                to dragEnter(blah2) {traceln("drag source sees dragenter")}
                to dragExit(blah3) {traceln("drag source sees dragexit")}
                to dragOver (blah4) {
                    #traceln("drag source sees dragover")
                }
                to dropActionChanged(blah) {traceln("dropactionchanged")}
                match [verb,args] {traceln("dragsource says: " + verb)}
            }
            def dragGestureListener {
                to dragGestureRecognized(dragEvent) {
                    def eObject := localEObjectFunc()
                    def objCarrier := dragDropKit makeTransferableLocalEObject(eObject)
                    traceln("dragging object: " + eObject)
                    traceln("dragEvent: " + dragEvent)
                    traceln ("sourcel: " + dragSourceListener)
                    def cursor := <awt:dnd.DragSource> DefaultMoveDrop()
                    traceln("cursor: " + cursor)
                    try {
                        dragEvent startDrag(
                            cursor,
                            objCarrier,
                            dragSourceListener)
                    } catch err {traceln("dragevent err: " + err)}
                    traceln ("started drag")
                }
                match [verb,args] {traceln("gesturer heard: " + verb)}
            }
            def dragSource := <awt:dnd.DragSource> getDefaultDragSource()
            dragSource createDefaultDragGestureRecognizer(
                component,
                <awt:dnd.DnDConstants> ACTION_COPY_OR_MOVE(),
                dragGestureListener)
        }
    }
}



1.1                  e/src/esrc/com/skyhunter/e/net/moreRecentVowFuncMaker.emaker

Index: moreRecentVowFuncMaker.emaker
===================================================================
class moreRecentVowFuncMaker() :near {
    def obsoleteError := "Obsolete Data"
    var mostRecentlyFulfilledIndex := 0
    var nextPromiseIndex := 1
    def moreRecentVow(nextPromise) :any {
        def [onlyMoreRecentPromise,resolver] := PromiseMaker()
        def thisPromiseIndex := nextPromiseIndex
        nextPromiseIndex += 1
        when (nextPromise) -> done(resolution) {
            if (thisPromiseIndex > mostRecentlyFulfilledIndex) {
                resolver resolve(resolution)
                mostRecentlyFulfilledIndex := thisPromiseIndex
            } else { resolver smash(obsoleteError) }
        } catch e {
            if (thisPromiseIndex > mostRecentlyFulfilledIndex) {
                mostRecentlyFulfilledIndex := thisPromiseIndex
                resolver smash(e)
            } else { resolver smash(obsoleteError) }
        }
        onlyMoreRecentPromise
    }
}





1.1                  e/src/esrc/com/skyhunter/e/util/stackTraceFunc.emaker

Index: stackTraceFunc.emaker
===================================================================
//Copyright (C) 2001 Combex. All Rights Reserved.
def stackTraceFunc(err) :pbc {
    err eStack() + "\n\n" +
      err leaf() javaStack()    
}



1.1                  e/src/esrc/com/skyhunter/eDesk/navPanelControllerMakerAuthor.emaker

Index: navPanelControllerMakerAuthor.emaker
===================================================================
#!/usr/local/bin/e
//License Agreement:
// The contents of this file are subject to the Mozilla Public License Version 1.1 (the "License");
// you may not use this file except in compliance with the License. You may obtain a copy of the License at
// http://www.skyhunter.com/marcs/securit-Edesk-license.html
// Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
// ANY KIND, either express or implied. See the License for the specific language governing rights and
// limitations under the License.
//The Original Code is The Securit-Edesk Configurator Program.
//The Initial Developer of the Original Code is Marc Stiegler. Portions created by
// Marc Stiegler are Copyright (C) Marc Stiegler. All Rights Reserved.
//**********

def navPanelControllerMakerAuthor(unsafe__uriGetter, awt__uriGetter, swing__uriGetter, traceln) :any {
    
    def JPanel__quasiParser := <import:org.erights.ex.swing.JPanelQParserMaker> new(awt__uriGetter, swing__uriGetter)
    def promiseAllResolved := <import:com.skyhunter.e.net.promiseAllResolved>
    def uiKit := <import:com.skyhunter.ex.swing.uiKitAuthor>(awt__uriGetter,
                                                             swing__uriGetter)
    
    def dirIcon := <swing:ImageIcon> new(<resource:com/skyhunter/eDesk/icons/folder.gif>)
    
    def moreRecentVowFuncMaker := <import:com.skyhunter.e.net.moreRecentVowFuncMaker>
    
    def diskNavStub {
        to dupNavigator() :near {diskNavStub}
        to getStorageName() :String {""}
        to versionNumber() :pbc {0}
        to getCurrentPath() :String {""}
        to getParentPath() :String {""}
        to listCurrentSubdirectoriesAndFiles() :pbc {[[],[]]}
        match [verb, args] {}
    }
    
    def unAssociatedIcon := <swing:ImageIcon> new(<resource:com/skyhunter/eDesk/icons/stranger.gif>)
    def cellRenderer {
        to getListCellRendererComponent(listPanel, cell,
                                        index, isSelected, cellHasFocus) :near {
            def component := cell composeComponent()
            def label := cell getLabel()
            if (isSelected) {
                label setBackground(<awt:Color> cyan())
            } else {
                label setBackground(<awt:Color> white())
            }
            component
        }
    }
    
    def dirNameFromPath(path) :pbc {
        traceln("path: " + path)
        def parts := path split("/")
        if (parts size() >= 2) {
            parts[parts size() - 2] + "/"
        } else {""}
    }
    
    def computeSuffix(name) :near {
        def parts := name split(".")
        def size := parts size()
        if (size == 1) {
            ""
        } else {
            parts[size - 1]
        }
    }
    
    class cellMaker(var name, isDir) :near {
        var component := null
        var label := null
        var icon := null
        var iconPane := null
        def cell {
            to composeComponent() :near {
                if (component != null) {
                    component
                } else {
                    icon := if (isDir) {dirIcon} else {unAssociatedIcon}
                    iconPane := <swing:JLabel> new(icon)
                    iconPane setIcon(icon)
                    label := <swing:JTextField> new(name)
                    label setBorder(<swing:BorderFactory> createEmptyBorder(0,0,0,0))
                    label setEditable(false)
                    component := JPanel`$iconPane $label.X`
                }
            }
            to rename(newName) {
                name := newName
                component := null
            }
            to isDir() :pbc {isDir}
            to getLabel() :near {label}
            to getIconPane() :near {iconPane}
        }
    }
    
    def composeCellArray(dirsFiles) :pbc {
        def list := [] diverge()
        for each in dirsFiles[0] {
            list push(cellMaker new(each, true))
        }
        for each in dirsFiles[1] {
            list push(cellMaker new(each, false))
        }
        list snapshot()
    }
    
    class navPanelControllerMaker(optHigherDirControllerVow, optLowerDirControllerVow, suffixMapper, windowController) :near {
        def localReactor
        var diskNavRcvr := diskNavStub
        def recentPathVow := moreRecentVowFuncMaker new()
        def recentFilesListVow := moreRecentVowFuncMaker new()
        def listPanel := <swing:JList> new()
        listPanel setCellRenderer(cellRenderer)
        def listScroller := <swing:JScrollPane> new(listPanel)
        def locationLabel := <swing:JLabel> new()
        def refreshButton := uiKit newToolButton(<resource:com/skyhunter/eDesk/icons/refresh.gif>,
                                                 "Refresh", def act(){localReactor reload()})
        def mainPanel := JPanel`$refreshButton   $locationLabel.X
                                $listScroller.Y  >  `
        
        def navPanelController
        
        def listPaneListener{
            to mouseClicked(theEvent) {
                #traceln("into mouseClicked")
                def clickLocation := <unsafe:java.awt.Point> new(theEvent getX(), theEvent getY())
                def selectionIndex := listPanel  locationToIndex(clickLocation)
                if (!(listPanel  isSelectedIndex(selectionIndex))) {
                    listPanel  setSelectedIndex(selectionIndex)
                }
                if (theEvent getClickCount() > 1) {
                    def cell := listPanel  getSelectedValue()
                    if (cell isDir()) {
                        traceln("double clicked on dir")
                        navPanelController openDir()
                    } else {
                        #dialogVowMaker new("DoubleClick TBD",
                        #                   "<html>Double click default open not yet available",
                        #                   null, ["OK"])
                    }
                } else if (theEvent isPopupTrigger() ||
                             <unsafe:javax.swing.SwingUtilities> isRightMouseButton(theEvent)) {
                    traceln("into is popup")
                    windowController showFilePopup(navPanelController, theEvent getX(),
                                                   theEvent getY())
                }
                
            }
            match _ {}
        }
        listPanel  addMouseListener(listPaneListener)
        
        def bind localReactor {
            to reload() {
                windowController setStatus("Refreshing Listing")
                def currentPathVow := recentPathVow (diskNavRcvr <- getCurrentPath())
                def dirsVow := recentFilesListVow (diskNavRcvr <- listCurrentSubdirectoriesAndFiles())
                when (dirsVow, currentPathVow) -> done(dirsFilesTuple, currentPath) {
                    locationLabel setText(dirNameFromPath(currentPath))
                    listPanel setListData(composeCellArray(dirsFilesTuple))
                    windowController setStatus("Refresh done.")
                } catch err {
                    #connectionWarning("Screen Refresh Failed\n" + err)
                    traceln("err in reload: " + err)
                    #windowController setStatus("Refresh failed")
                }
            }
        }
        
        def navReactors := [] asMap() diverge()
        
        
        def listSelectionListener {
            to valueChanged(event) {
                def onlyOne := listPanel getSelectedValues() size() == 1
                def selection := listPanel getSelectedValue()
                def isDir := selection != null && selection isDir()
                if (onlyOne && isDir) {
                    for each => stub in navReactors {
                        each selectedDir(navPanelController)
                    }
                }
            }
        }
        listPanel addListSelectionListener(listSelectionListener)
        
        def dragDropKit := <import:com.skyhunter.e.awt.dnd.dragDropKit> (awt__uriGetter, traceln)
        def getFileRcvrs() :any {navPanelController getSelectedFileRcvrs() }
        dragDropKit setupLocalDragSource(listPanel , getFileRcvrs ) 
                
        def clear() {
            for each => stub in navReactors {each cleared(navPanelController)}
            diskNavRcvr := diskNavStub
            localReactor reload()
        }
        
        def lowerPaneReactor {
            to openingDir(controller) {
                traceln("opening dir reached in lower listener")
                def nextNavRcvr := controller dupDiskNavRcvr()
                for each => stub in navReactors {each lowerDirOpening(navPanelController)}
                diskNavRcvr := nextNavRcvr
                localReactor reload()
                for each => stub in navReactors {each openedDir(navPanelController)}
            }
            to lowerDirOpening(controller) {
                lowerPaneReactor openingDir(controller)
            }
            match [verb, args] {}
        }
        when (optLowerDirControllerVow) -> doneLower(lowerController) {
            if (lowerController != null) {
                lowerController <- addNavReactor(lowerPaneReactor)
            }
        } catch prob {traceln("disaster with lowerController: " + prob)}
        
        def upperPaneReactor {
            to goingUp(controller) {
                for each => stub in navReactors {each goingUp(navPanelController)}
                diskNavRcvr := controller dupDiskNavRcvr()
                localReactor reload()
                for each => stub in navReactors {each wentUp(navPanelController)}
                
            }
            to lowerDirOpening(controller) {}
            to wentUp(controller) {}
            to jumped(controller) {clear()}
            to cleared(controller) {clear()}
            to openingDir(controller) {clear()}
            to openedDir(controller) {}
            to selectedDir(controller) {
                def newSelection := (controller getSelectedNames())[0]
                diskNavRcvr := controller dupDiskNavRcvr()
                diskNavRcvr <- changeToSubdirectory(newSelection)
                localReactor reload()
                for each => stub in navReactors {each jumped(navPanelController)}
            }
            to deletionsMade(controller) {
                when (diskNavRcvr <- currentDirExists()) -> done(exists) {
                    if (!exists) {clear()}
                } catch prob {traceln("deletionsmade prob: " + prob)}
            }
            match [verb, args] {traceln("Got verb in upperPaneReactor: " + verb)}
        }
        
        when (optHigherDirControllerVow) -> doneHigher(higherController) {
            if (higherController != null) {
                higherController <- addNavReactor(upperPaneReactor)
            }
        } catch prob {traceln("disaster with higherController: " + prob)}
        
        def bind navPanelController {
            to setDiskNavRcvr(newNavRcvr) {
                diskNavRcvr := newNavRcvr
                localReactor reload()
            }
            to getDiskNavRcvr() :any {diskNavRcvr }
            to dupDiskNavRcvr() :any {
                if (diskNavRcvr == null) {
                    null
                } else {diskNavRcvr <- dupNavigator()}
            }
            to addNavReactor(reactor) {navReactors[reactor] := null}
            to removeNavReactor(reactor) {navReactors removeKey(reactor)}
            to goto(path) {
                diskNavRcvr <-changeToDirectory(path)
                localReactor reload()
                for each => stub in navReactors {each jumped(navPanelController)}
            }
            to gotoHome() {
                diskNavRcvr <- gotoHome()
                localReactor reload()
                for each => stub in navReactors {each jumped(navPanelController)}
            }
            to reload() {localReactor reload()}
            to deletionsMade() {
                localReactor reload()
                for each => stub in navReactors {each deletionsMade(navPanelController)}
            }
            to getCellRenderer() :near {cellRenderer}
            to getMainPanel() :near {mainPanel}
            to getListPanel() :near {listPanel}
            to goUp() {
                for each => stub in navReactors { each goingUp(navPanelController)}
                diskNavRcvr <- goUp()
                localReactor reload()
                for each => stub in navReactors { each wentUp(navPanelController)}
            }
            to openDir() {
                traceln("into open dir")
                def newDirName := (navPanelController getSelectedNames() )[0]
                traceln("newDir: " + newDirName)
                for each => stub in navReactors { each openingDir(navPanelController)}
                traceln("told reactors opening")
                diskNavRcvr <- changeToSubdirectory(newDirName)
                #listPanel  clearSelection()
                traceln("about to change dir: " + diskNavRcvr)
                
                localReactor reload()
                traceln("about to tell reactors opened")
                for each => stub in navReactors { each openedDir(navPanelController)}
            }
            to getSelectedNames() :pbc {
                def names := [] diverge()
                def cells := listPanel getSelectedValues()
                for each in cells {
                    names push(each getLabel() getText())
                }
                names snapshot()
            }
            to getSelectedFileRcvrs() :pbc {
                def fileRcvrs := [] diverge()
                for each in navPanelController getSelectedNames() {
                    fileRcvrs push(diskNavRcvr <- getFileNamed(each))
                }
                fileRcvrs snapshot()
            }
        }
    }
}



1.1                  e/src/esrc/com/skyhunter/eDesk/serverDescVowAuthor.emaker

Index: serverDescVowAuthor.emaker
===================================================================
#!/usr/local/bin/e
//License Agreement:
// The contents of this file are subject to the Mozilla Public License Version 1.1 (the "License");
// you may not use this file except in compliance with the License. You may obtain a copy of the License at
// http://www.skyhunter.com/marcs/securit-Edesk-license.html
// Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
// ANY KIND, either express or implied. See the License for the specific language governing rights and
// limitations under the License.
//The Original Code is The Securit-Edesk Configurator Program.
//The Initial Developer of the Original Code is Marc Stiegler. Portions created by
// Marc Stiegler are Copyright (C) Marc Stiegler. All Rights Reserved.
//**********

def serverDescVowAuthor(unsafe__uriGetter, awt__uriGetter, swing__uriGetter, frameMaker, traceln) :any {
    
    def JPanel__quasiParser := <import:org.erights.ex.swing.JPanelQParserMaker> new(awt__uriGetter, swing__uriGetter)
    def promiseAllResolved := <import:com.skyhunter.e.net.promiseAllResolved>
    #def uriTools := <import:com.skyhunter.e.net.uriToolsAuthor>(introducer,
    #                                                            sturdyRef)
    def uiSet := <import:com.skyhunter.ex.swing.uiKitAuthor>(awt__uriGetter,
                                                             swing__uriGetter)
    def dialogVowMaker := <import:com.skyhunter.ex.swing.dialogVowMakerAuthor>(
        awt__uriGetter,
        swing__uriGetter,
        JPanel__quasiParser,
        frameMaker)
    
    #integer string converter
    def toInt(numString) :near {(<unsafe:java.lang.Integer> new(numString)) intValue()}
    
    #****** Configurator Specific Code ***********
    
    def mainFrame := frameMaker new()
    def [configVow, configSolver] := PromiseMaker() 
    def configReady
    def windowTitleField := <swing:JTextField> new("My eDesk Server")
    def rootPathField := <swing:JTextField> new()
    def homePathField := <swing:JTextField> new("c:\\windows\\desktop")
    def capFileField := <swing:JTextField> new("edeskServer.eds")
    def serverOnlyBox := <swing:JCheckBox> new()
    serverOnlyBox setText("Server Only")
    serverOnlyBox setSelected(false)
    def isReadOnlyBox := <swing:JCheckBox> new()
    isReadOnlyBox setText("Read Only")
    isReadOnlyBox setSelected(true)
    def okButton := uiSet newButton("OK",configReady)
    def l(text) :near {<swing:JLabel> new(text)}
    def formPane :=
      JPanel`${l("Browser-Window Title")}          $windowTitleField.X
		${l("Home Path")}                   $homePathField.X
		$serverOnlyBox                      >
		${l("   Write Capability To")}      $capFileField.X 
		${l(" ")}                           >
		${l("    Security Configuration")}  >      
		$isReadOnlyBox                      >      
		${l("Top Accessible Directory")}    $rootPathField.X 
		$okButton                           > `
    
    traceln("config form about to make window")
    #create form window
    def mainPane := mainFrame getContentPane()
    mainFrame setDefaultCloseOperation(<swing:WindowConstants> DISPOSE_ON_CLOSE())
    mainPane add(formPane)
    mainFrame setTitle("Configure Edesk")
    mainFrame pack()
    #mainFrame setSize(400,200)
    mainFrame show()
    
    def bind configReady() {
        #traceln("made it")
        configSolver resolve (`
            <serverDesc>
            <windowTitle>${windowTitleField getText()}</windowTitle>
            <home>${homePathField getText()}</home>
            <serverOnly>${if (serverOnlyBox isSelected()) { "true"} else {"false"}}</serverOnly>
            <capabilityFile>${capFileField getText()}</capabilityFile>
            <isReadOnly>${if (isReadOnlyBox isSelected()) {"true"} else {"false"}}<isReadOnly>
            <virtualRoot>${rootPathField getText()}</virtualRoot>
            </serverDesc>
            `)
        mainFrame dispose()
    }
    
    configVow
}



1.1                  e/src/esrc/com/skyhunter/eDesk/testConfigurator.updoc

Index: testConfigurator.updoc
===================================================================
? def frameMaker := <swing:JFrame> 
# value: <unsafe:javax.swing.JFrame>

? def traceln := println
# value: <println>

? 
? def configurator := <import:com.skyhunter.eDesk.serverDescVowAuthor> (unsafe__uriGetter, awt__uriGetter, 
>                                                                      swing__uriGetter, frameMaker, traceln)
config form about to make window
# value: <Eventual ref>

? when (configurator) -> done(serverDesc) {
>     println("server desc: ")
>     println(serverDesc)
> } catch prob {println("prob with desc: " + prob)}
# value: <Eventual ref>

? 
server desc: 

            <serverDesc>
            <windowTitle>My eDesk Server</windowTitle>
            <home>c:\windows\desktop</home>
            <serverOnly>false</serverOnly>
            <capabilityFile>edeskServer.eds</capabilityFile>
            <isReadOnly>true<isReadOnly>
            <virtualRoot></virtualRoot>
            </serverDesc>
            
? 
server desc: 
<serverDesc>
            <windowTitle>My eDesk Server</windowTitle>
            <home>c:\windows\desktop</home>
            <serverOnly>false</serverOnly>
            <capabilityFile>edeskServer.eds</capabilityFile>
            <isReadOnly>true<isReadOnly>
            <virtualRoot></virtualRoot>
            </serverDesc>
            
? 


1.1                  e/src/esrc/com/skyhunter/eDesk/testNavPanel.e

Index: testNavPanel.e
===================================================================
def testNavigator {
    to listCurrentSubdirectoriesAndFiles() :pbc {[["dir1", "dir2"],["file1","f2"]]}
    to getCurrentPath() :pbc {"path1/path2"}
}
# value: <testNavigator>

def traceln := println

def frame := <swing:JFrame> new("test nav panel")
def navMaker := <import:com.skyhunter.eDesk.navPanelControllerMakerAuthor> (
    unsafe__uriGetter, awt__uriGetter, swing__uriGetter, println)
# value: <navPanelControllerMaker>

def winController {match [verb, args] {traceln("winController requested to: " + verb)}}
def navPanel := navMaker new(null, null, null, winController)
# value: <navPanelController>

navPanel setDiskNavRcvr(testNavigator)

frame setContentPane(navPanel getMainPanel())

frame show()






1.1                  e/src/esrc/com/skyhunter/eDesk/testNavPanel.updoc

Index: testNavPanel.updoc
===================================================================
? def testNavigator {
>     to listCurrentSubdirectoriesAndFiles() :pbc {[["dir1", "dir2"],["file1","f2"]]}
>     to getCurrentPath() :pbc {"path1/path2"}
> }
# value: <testNavigator>

? def frame := <swing:JFrame> new("test nav panel")
# value: javax.swing.JFrame[frame0,0,0,0x0,invalid,hidden,layout=java.awt.BorderLayout,resizable,title=test nav panel,defaultCloseOperation=HIDE_ON_CLOSE,rootPane=javax.swing.JRootPane[,0,0,0x0,invalid,layout=javax.swing.JRootPane$RootLayout,alignmentX=null,alignmentY=null,border=,flags=1538,maximumSize=,minimumSize=,preferredSize=],rootPaneCheckingEnabled=true]

? def navMaker := <import:com.skyhunter.eDesk.navPanelControllerMakerAuthor> (
>     unsafe__uriGetter, awt__uriGetter, swing__uriGetter, println)
# value: <navPanelControllerMaker>

? def navPanel := navMaker new(null, null, null)
# value: <navPanelController>

? navPanel setDiskNavRcvr(testNavigator)
about to reloadPane<testNavigator>
? frame setContentPane(navPanel getMainPanel())
? frame show()
? 


1.1                  e/src/esrc/com/skyhunter/eDesk/icons/folder.gif

Index: folder.gif
===================================================================
GIF89a
0j1S	HJ*ëX


1.1                  e/src/esrc/scripts/eDesk.e

Index: eDesk.e
===================================================================
//License Agreement:
// The contents of this file are subject to the Mozilla Public License Version 1.1 (the "License");
// you may not use this file except in compliance with the License. You may obtain a copy of the License at
// http://www.skyhunter.com/marcs/securit-Edesk-license.html
// Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
// ANY KIND, either express or implied. See the License for the specific language governing rights and
// limitations under the License.
//The Original Code is The Securit-Edesk Program.
//The Initial Developer of the Original Code is Marc Stiegler. Portions created by
// Marc Stiegler are Copyright (C) Marc Stiegler. All Rights Reserved.
//**********


# set up tracing; stub out all the printing for operational version
def traceln(str) { println(str) }
traceln("started")
def versionNumber := "0.7"

def io__uriGetter := <unsafe:java.io.*>
def ser__uriGetter := <unsafe:org.erights.e.elib.serial.*>
def SerializerMaker := <ser:Serializer>
def UnserializerMaker := <ser:Unserializer>

def byte := <unsafe:java.lang.Byte> TYPE()
def makeErr(text) :near {<unsafe:java.lang.Exception> new(text)}



class frameMakerMaker(iconURL) :near {
    def image := <swing:ImageIcon> new(iconURL) getImage()
    def frameMaker {
        to new(title) :near {
            def frame := <swing:JFrame> new(title)
            frame setIconImage(image)
            frame
        }
        to new() :near {
            frameMaker new("")
        }
    }
}
traceln("compiled maker maker")
def eFrameMaker := frameMakerMaker new(
    <resource:org/erights/e/icons/green-e-on-white-16.gif>)
def strangerFrameMaker := frameMakerMaker new(
    <resource:com/skyhunter/eDesk/icons/stranger.gif>)
def superFrameMaker := frameMakerMaker new(
    <resource:com/skyhunter/eDesk/icons/super.gif>)

traceln("got frame makers")

def promiseAllResolved := <import:com.skyhunter.e.net.promiseAllResolved>
def uriTools := <import:com.skyhunter.e.net.uriToolsAuthor>(introducer,
                                                            sturdyRef)
def uiTools := <import:com.skyhunter.ex.swing.uiToolsAuthor>(awt__uriGetter,
                                                             swing__uriGetter)
def dialogVowMaker := <import:com.skyhunter.ex.swing.dialogVowMakerAuthor>(
    awt__uriGetter,
    swing__uriGetter,
    JPanel__quasiParser,
    superFrameMaker)
def sendValveMaker := <import:com.skyhunter.e.net.sendValveMaker>
def standardWindow := <import:com.skyhunter.ex.swing.standardWindowMakerAuthor>(interp, superFrameMaker)

traceln("got standardWindow")

def progressWindowMaker := <import:com.skyhunter.eDesk.progressWindowMakerAuthor>(
    swing__uriGetter, standardWindow)

class vowsMonitorMaker(): any {
    def [bundlePromise,resolver] := PromiseMaker()
    def bundle := [] diverge()
    def vowsMonitor {
        to add (thePromise) {bundle push(thePromise)}
        to finishAll() {resolver resolve(promiseAllResolved(bundle))}
        to promiseFinish() : any {bundlePromise}
    }
}

traceln("about to def installer")
def installer := <import:com.skyhunter.installer.persistentInstallerAuthor> run(
    unsafe__uriGetter,
    file__uriGetter,
    interp,
    introducer,
    interp getProps(),
    traceln,
    stdout)
traceln("about to build appsManager")
def edeskHomePath := "~/eDeskPrivate/"
//XXX use these dir and file text strings from resources ubiquitously
def appsDirPath :=  edeskHomePath +
  <resource:com/skyhunter/eDesk/strings/installedAppsDir.txt> getText() trim()
traceln("appsDirPath: " + appsDirPath)
def appsDir := <file: appsDirPath>
if (!(appsDir exists())) {appsDir mkdirs()}
def appsDescPath :=  appsDirPath + <resource:com/skyhunter/eDesk/strings/appsDescFile.txt> getText() trim()
traceln("appsDescPath: " + appsDescPath)
def appsDescFile := <file: appsDescPath>
if (!(appsDescFile exists())) {appsDescFile setText("<installed></installed>" )}
def installedAppsManager := <import:com.skyhunter.eDesk.installedAppsManagerMaker> new(
    appsDescFile, traceln )

traceln("did appsManager: " + installedAppsManager)

def connectionWarning(description) {
    dialogVowMaker new("Connection apparently lost",
                       `<html><b>Lost Connection</b><p><pre>$description</pre>`,
                       null, ["OK"])
}

class forwarderMaker(target) : any {
    def forwarder  {
        match [verb,args] {E send(target,verb,args)}
    }
}
def makeWriteFile {
    to run(fileName) : any {<file: fileName>}
    to label() : any {""}
}
def makeReadFile {
    to run(fileName) : any { (<file: fileName>) transReadOnly()}
    to label(): any {"(Read Only)"}
}
def fileHash(file, numBytesToHash) : any {
    def MDMaker := <unsafe:java.security.MessageDigest>
    var blockSize := 100000
    var hashedBytes := 0
    def openFile(file) : any {
        E call(<io:FileInputStream>, "new(File)", [file])
    }
    def sha := MDMaker getInstance("SHA")
    def inStream := openFile(file)
    var result := []
    if (numBytesToHash <= file length()) {
        while (hashedBytes < numBytesToHash) {
            if (numBytesToHash - hashedBytes < blockSize) {blockSize := numBytesToHash - hashedBytes}
            def buf := byte[blockSize]
            def count := inStream read(buf)
            sha update(buf, 0, count)
            hashedBytes := hashedBytes + blockSize
        }
        result := sha digest()
    }
    inStream close()
    traceln("hashed: " + result)
    result
}

class readOnlyToFileCopierMaker(myFile) : any {
    def fileCopier {
        to copyEventually(a,farProgressObserver,c,d) : any {
            farProgressObserver <- copyFailed()
            def [dead,resolver] := PromiseMaker()
            resolver smash(makeErr("readOnlyFile"))
            dead
        }
        match _ { }
    }
}
class writeableToFileCopierMaker(myFile) : any {
    var myOutputStream := null
    var myTempFile := null
    var myRemoteProgressObserver := null
    def [copyPromise,resolver] := PromiseMaker()
    def fileCopier {
        to copyEventually(farFile, farProgressObserver,
                          farLastResortForwarderToSelf, farLastResortForwarderToFarFile) : any {
            traceln("into copy eventually" + farProgressObserver)
            myTempFile := <file: ((myFile getAbsolutePath()) + ".tmp")>
            traceln("did temp file creation")
            def sendBytesRequest(fromCopier,toCopier) : any {
                var fileVow := null
                if (myTempFile exists()) {
                    traceln("temp file exists")
                    def hash := fileHash(myTempFile, myTempFile length())
                    fileVow := fromCopier <- sendToPartialFile(toCopier, myTempFile length(), hash)
                } else if (myFile exists()) {
                    traceln("about to hash in file copier")
                    def hash := fileHash(myFile, myFile length())
                    fileVow := fromCopier <- sendToExistingFile(toCopier, myFile length(), hash)
                } else {
                    fileVow := fromCopier <- sendByteBlocks(toCopier)
                }
                fileVow
            }
            def fp := sendBytesRequest(farFile, fileCopier)
            traceln("fp: " + fp)
            when (fp) -> done(connection) {
                Ref whenBroken(farFile, def breaker(err){
                    resolver smash(makeErr ("lost file copy connection: " + err))
                    farProgressObserver copyFailed()
                })
            } catch err {
                sendBytesRequest (farLastResortForwarderToFarFile, farLastResortForwarderToSelf)
                traceln("using forwarders to copy file")
                Ref whenBroken(farLastResortForwarderToFarFile, def breaker(p2) {
                    resolver smash(makeErr ("lost forwarded file copy connection" + p2))
                    farProgressObserver copyFailed()
                })
            }
            myRemoteProgressObserver := farProgressObserver
            copyPromise
        }
        to amountBeingSent(amount) {myRemoteProgressObserver <-setFileSize(amount)}
        to receiveByteBlock(count,bytes) {
            if (myOutputStream == null) {
                myOutputStream := E call(<io:FileOutputStream>, "new(String)", [(myTempFile getAbsolutePath())])
                traceln("receiveBytes made stream")
            }
            traceln("receiving bytes")
            myOutputStream write(bytes,0,count)
            try {myOutputStream flush()} catch e{}
            myRemoteProgressObserver <- updateCount(count)
        }
        to existingFileIsFine() {
            myRemoteProgressObserver <- completed()
            resolver resolve(true)
        }
        to partialFileIsFine() {
            traceln("in partialIsFine")
            myOutputStream := E call(<io:RandomAccessFile>, "new(File, String)",[myTempFile,"rw"])
            myOutputStream skipBytes(myTempFile length())
            traceln("should have skipped by now")
        }
        to allBytesSent() {
            #if output stream does not exist, file transferred was 0 length
            if (myOutputStream != null) {
                myOutputStream close()
            } else if (!(myTempFile exists())) {myTempFile setText("")}
            if (myFile exists()) {myFile delete()}
            myTempFile renameTo(myFile)
            myRemoteProgressObserver <- completed()
            resolver resolve(true)
        }
    }
}

traceln ("about to compile toFileCopierMaker")

var toFileCopierMaker := writeableToFileCopierMaker
class fromFileCopierMaker (myFile) : any {
    def fileCopier {
        to sendByteBlocks(farRecipient, startIndex) {
            traceln("send bytes recipient:" + farRecipient)
            farRecipient <- amountBeingSent(myFile length() - startIndex)
            def inStream := E call(<io:FileInputStream>, "new(String)", [(myFile getAbsolutePath())])
            inStream skip (startIndex)
            var blockSize := 50000
            var bytes := byte[blockSize]
            def sendRemainingBlocks() {
                def bytesAvailable := inStream available()
                if (bytesAvailable > 0) {
                    if (bytesAvailable < blockSize) {
                        blockSize := bytesAvailable
                        bytes := byte[blockSize]
                    }
                    //def bytes := byte[blockSize]
                    def count := inStream read(bytes)
                    traceln("about to send receiveByteBlock for" + (myFile getAbsolutePath()))
                    def sentPromise := farRecipient <- receiveByteBlock(count,bytes)
                    when (sentPromise) -> done(sent) {
                        sendRemainingBlocks()
                    } catch err {traceln("lost connection transferrring file: " + err)}
                } else {
                    inStream close()
                    farRecipient <- allBytesSent()
                }
            }
            sendRemainingBlocks ()
        }
        to sendByteBlocks(farRecipient) {fileCopier sendByteBlocks(farRecipient, 0)}
        to sendToExistingFile(farRecipient, farSize, farHash) {
            if (myFile length() == farSize && fileHash(myFile, myFile length()) == farHash ) {
                traceln("copy file is duplicate")
                farRecipient <- existingFileIsFine()
            } else {
                traceln("copy file is not duplicate")
                fileCopier sendByteBlocks(farRecipient)
            }
        }
        to sendToPartialFile(farRecipient, farSize, farHash) {
            if (myFile length() >=  farSize && fileHash(myFile, farSize) == farHash ) {
                traceln("partial file is good:" + farSize + "my size" +myFile length())
                farRecipient <- partialFileIsFine()
                fileCopier sendByteBlocks(farRecipient, farSize)
            } else {
                traceln("partial file is not duplicate")
                fileCopier sendByteBlocks(farRecipient)
            }
        }
    }
}
//FileModel
class fileModelMaker(myFile) :any {
    def fileModel  {
        to getFromCopier() : any {fromFileCopierMaker new(myFile) }
        to getToCopier() : any {toFileCopierMaker new(myFile)}
        delegate {myFile}
    }
}

class fileProgressObserverMaker(title, farFile) : any {
    def myWindow := progressWindowMaker new(title)
    var bytesSent := 0
    def localFailed() {myWindow closeWindow()}
    Ref whenBroken(farFile, def breaker(p) {
        localFailed()
    })
    def fileProgressObserver {
        to completed() {
            traceln("completed file transfer!")
            myWindow closeWindow()
        }
        to setFileSize(theSize) {myWindow setFileSize(theSize)}
        to updateCount(countIncrement) {
            bytesSent := bytesSent + countIncrement
            myWindow setProgress(bytesSent)
        }
        to copyFailed() {
            localFailed()
        }
    }
}
def fileProgressObserverStub {
    match _ {}
}
def quickEditMaker := <import:com.skyhunter.eDesk.quickEditMakerAuthor>(traceln, awt__uriGetter,
                                                                        swing__uriGetter, connectionWarning,
                                                                        standardWindow, dialogVowMaker )

traceln("about to compile navigatorWindowMaker")

//NavigatorWindow
class navigatorWindowMaker(myFtController, myDiskNavigator) : any {
    def navigatorWindow
    def myStorageName := myDiskNavigator <- getStorageName()
    def navFrame := standardWindow("", navigatorWindow)
    when (myStorageName) -> done(name) {
        navFrame setTitle(name)
    } catch err{}
    def mainPane := navFrame getContentPane()
    
    #make the menus
    def menuReactor {
        to doNewWindow(){navigatorWindow dupWindow() }
        to doOpenRemote() {navigatorWindow openRemote() }
        to doAbouteDesk() {
            def html := <resource:com/skyhunter/eDesk/strings/about.txt> getText()
            dialogVowMaker  new("About eDesk", html, null, ["OK"])
        }
        to doQuickHelp() {
            def html := <resource:com/skyhunter/eDesk/strings/help.txt> getText()
            dialogVowMaker  new("Quick Help", html, null, ["OK"])
        }
        match [verb,args] {traceln("menu hit for " + verb)}
    }
    def mm := <import:com.skyhunter.ex.swing.menuMakerAuthor> (
        swing__uriGetter,
        <unsafe:org.erights.e.ui.jed.EAction>,
        menuReactor)
    def menuBar := mm menuBar([
        mm menu("&Windows", [
            mm action("&New Window",  "Ctrl+N"),
            mm action("Open Remote...", "Ctrl+O")
        ]),
        mm menu("&Help", [
            mm action("&Quick Help"),
            "--"
            mm action("&About eDesk")
        ])
    ])
    navFrame setJMenuBar(menuBar)
    
    def statusPanel := <swing:JLabel> new()
    def setStatus(status) {statusPanel setText(status)}
    def navPanelServer
    
    def navPanelControllerMaker := <import:com.skyhunter.eDesk.navPanelControllerMakerAuthor> (
        unsafe__uriGetter, awt__uriGetter, swing__uriGetter, println)
    
    def navPanelController1
    def navPanelController2
    def navPanelController3
    def bind navPanelController1 := navPanelControllerMaker new(null, navPanelController2, installedAppsManager , navPanelServer )
    def bind navPanelController2 := navPanelControllerMaker new(navPanelController1, navPanelController3, installedAppsManager , navPanelServer )
    def bind navPanelController3 := navPanelControllerMaker new(navPanelController2, null, installedAppsManager,  navPanelServer )
    
    class navWinActionMaker(actionName) :near {
        def action() {E call(navigatorWindow, actionName, [])}
    }
    def gotoButton := uiTools newToolButton(
        <resource:com/skyhunter/eDesk/icons/goto.gif>,
        "Goto", navWinActionMaker new("gotoFieldName"))
    def upButton := uiTools newToolButton(
        <resource:com/skyhunter/eDesk/icons/up.gif>,
        "Up", navWinActionMaker new("goUp"))
    def homeButton := uiTools newToolButton(
        <resource:com/skyhunter/eDesk/icons/home.gif>,
        "Home", navWinActionMaker new("goHome"))
    def fullPathTextField := <swing:JTextField> new()
    def enterKeyListener{
        to keyPressed(theEvent) {
            if (theEvent getKeyCode() == <unsafe:java.awt.event.KeyEvent> VK_ENTER()) {
                navigatorWindow gotoFieldName()
            }
        }
        match _ {}
    }
    fullPathTextField addKeyListener(enterKeyListener)
    def refreshLocal() {
        navPanelController1 reload()
        navPanelController2 reload()
        navPanelController3 reload()
        traceln("BAD: RefreshLocal!")
    }
    def newFile(navPanelController) {
        def newName := <swing:JOptionPane> showInputDialog(navFrame, "Name for New File: ", "New File", <swing:JOptionPane> QUESTION_MESSAGE())
        if (newName != null && newName size() >0) {
            navPanelController getDiskNavRcvr() <- newFile(newName)
        }
        navPanelController reload()
    }
    def newDir(navPanelController) {
        def newName := <swing:JOptionPane> showInputDialog(navFrame, "Name for New Folder: ", "New Folder", <swing:JOptionPane> QUESTION_MESSAGE())
        traceln("Dir Name: " + newName)
        if (newName != null && newName size() >0) {
            navPanelController getDiskNavRcvr() <- makeDir(newName)
        }
        navPanelController reload()
    }
    def openDir(navPanelController) {
        navPanelController openDir()
    }
    def openEDesk(navPanelController) {
            def fileNames := navPanelController getSelectedNames()
            def navRcvr := navPanelController dupDiskNavRcvr()
            if (fileNames != null && fileNames size() >0) {
                for each in fileNames {
                    myFtController openEdesk(navRcvr <- getFileNamed(each))
                }
            }
    }
    def propertiesList(navPanelController) {
        def fileRcvrList := navPanelController getSelectedFileRcvrs()
        if (fileRcvrList != null) {
            setStatus("Showing files properties")
            for each in fileRcvrList {
                traceln("a file properties")
                def path := each <- getPath()
                def canonical := each <- getCanonicalPath()
                def fileSize := each <- length()
                def lastModified := each <- lastModified()
                traceln("requested properties")
                when (path, canonical, fileSize,lastModified) -> done(p,c,f,l) {
                    traceln("all resolved")
                    def modDate := E call(<unsafe:java.util.Date>, "new(long)",[lastModified])
                    def display :=
                      `<html><table><tr>
                    <td><b>Full Path:</b></td><td>$path</td>
                    </tr><tr>
                    <td><b>Canonical Path:</b></td><td>$canonical</td>
                    </tr><tr>
                    <td><b>Size:</b></td><td>$fileSize</td>
                    </tr><tr>
                    <td><b>Last Modified:</b></td><td>$modDate</td>
                    </tr></table></html>`
                    dialogVowMaker  new("Properties For " + each, display, null, ["OK"])
                    setStatus("")
                } catch e { connectionWarning(e)}
            }
        }
    }
    def renameList(navPanelController) {
        def theList := navPanelController getSelectedNames()
        def diskNavRcvr := navPanelController dupDiskNavRcvr()
        setStatus("Renaming files")
        for each in theList {
            def newName := <swing:JOptionPane> showInputDialog (null, "New Name for: " + each , "Rename" , <swing:JOptionPane> QUESTION_MESSAGE(), null, null, each)
            if (newName != null && newName size() >0) {
                diskNavRcvr <- rename(each, newName)
            }
        }
        navPanelController  reload()
    }
    def deleteList(navPanelController){
        def theList := navPanelController getSelectedNames()
        def navRcvr := navPanelController dupDiskNavRcvr()
        def deletionVows := [] diverge()
        setStatus("Deleting files")
        for each in theList {
            deletionVows push(navRcvr <- deleteFileObject(each))
        }
        when (promiseAllResolved(deletionVows)) -> done(deletions) {
            navPanelController  <- deletionsMade()
        } catch prob {traceln("deletions incomplete: " + prob)}
    }
    def copyList(navPanelController) {
        def fileRcvrs := navPanelController getSelectedFileRcvrs()
        def localNavigator := navPanelController dupDiskNavRcvr()
        myFtController copyFrom (fileRcvrs, localNavigator)
    }
    def pasteFromPanel(navPanelController) {
        setStatus("Paste/Copying files")
        myFtController paste(navPanelController dupDiskNavRcvr(), navigatorWindow)
    }
    def installCaplet(navPanelController) {
        def sourceFileVow := (navPanelController  getSelectedFileRcvrs())[0]
        when (sourceFileVow) -> done(sourceFile) {
            installer install(sourceFile, installedAppsManager )
        } catch prob {traceln("prob in install catch" + prob)}
    }
    def runCaplet{
        to run(navPanelController) {
            def sourceFileVow := (navPanelController getSelectedFileRcvrs())[0]
            when (sourceFileVow) -> done(sourceFile) {
                runCaplet(sourceFile,[])
            } catch prob {traceln("sourcefile prob in runcaplet: " + prob)}
        }
        to run(sourceFile, docRcvrs) {
            
            def powerboxControllerMaker := <import:com.skyhunter.e.security.powerboxControllerMakerAuthor> run(
                unsafe__uriGetter, file__uriGetter, interp, traceln, stdout)
            traceln("made powerboxMaker")
            def appDesc := installedAppsManager getAppBySourcePath(sourceFile getCanonicalPath())
            traceln("got appDesc: " + appDesc)
            def findImage() :near {
                var image := null
                if (appDesc maps("Icon")) {
                    def path := appDesc["Icon"]
                    traceln("appDesc maps Icon: " + path )
                    var iconfile := (sourceFile getParentFile())[path]
                    if (!(iconfile exists())) {
                        iconfile := <file: appDesc["Icon"]>
                    }
                    if (iconfile exists()) {
                        image := <swing:ImageIcon> new(iconfile getCanonicalPath()) getImage()
                    }
                }
                traceln("returning image: " + image)
                image
            }
            
            def powerboxController := powerboxControllerMaker new(
                appDesc get("Name", sourceFile getCanonicalPath()),
                findImage(), <file: appDesc["RunPath"]> getText())
            def box := powerboxController getPowerbox()
            powerboxController setCap(box DOC_SUFFIX(), appDesc get("Suffix", null))
            powerboxController setCap(box INITIAL_DOC_RCVRS(), docRcvrs)
            traceln("about to launch file")
            powerboxController launchFile(sourceFile)
            traceln("launch initiated")
        }
    }
    def bind navPanelServer {
        to setStatus(text) {setStatus(text)}
        to showFilePopup(navPanelController, showX, showY) {
            def myNavigatorRcvr := navPanelController dupDiskNavRcvr()
            def selectedFileNames := navPanelController getSelectedNames()
            def selectedCells := navPanelController getListPanel() getSelectedValues()
            traceln("got selected names: " + selectedFileNames)
            def appReactor {
                match[verb, args] {
                    def docRcvrs := [] diverge()
                    def appMap := installedAppsManager optAppByPetName(verb)
                    def sourceFile := <file: appMap["SourcePath"]>
                    for each in selectedFileNames {
                        docRcvrs push(myNavigatorRcvr <- getFileNamed(each))
                    }
                    runCaplet(sourceFile, docRcvrs)
                }
            }
            class appActionMaker(appPetName) :near {
                def action(){E call(appReactor, appPetName,[])}
            }
            def appsMenu := <swing:JMenu> new("Open With")
            for each in installedAppsManager getAppPetNames() {
                uiTools addMenuItem(appsMenu, each, appActionMaker new(each))
            }
            var suffix := ""
            if (selectedFileNames size() > 0) {
                def sections := selectedFileNames[0] split(".")
                if (sections size() > 1) {suffix := sections[sections size() - 1]}
            }
            class actionMaker(func) :near {
                def action(){E send(func, "run", [navPanelController])}
            }
            traceln("about to make popup frame")
            def popup := <swing:JPopupMenu> new("File Ops")
            def popWithUniversalChoices() {
                traceln("into pop universal choices")
                uiTools  addMenuItem(popup,"Paste", actionMaker new(pasteFromPanel))
                uiTools  addMenuItem(popup,"New File", actionMaker new(newFile))
                uiTools  addMenuItem(popup,"New Folder", actionMaker new(newDir))
                popup  show(navPanelController getListPanel(), showX, showY)
            }
            def popWithDirChoices() {
                uiTools addMenuItem(popup, "Open Folder", actionMaker new(openDir))
                uiTools  addMenuItem(popup,"Copy", actionMaker new(copyList))
                uiTools  addMenuItem(popup, "Delete", actionMaker new(deleteList))
                uiTools  addMenuItem(popup, "Rename", actionMaker new(renameList))
                popWithUniversalChoices()
            }
            def popWithAllDocChoices() {
                E call(popup, "add(JMenuItem)", [appsMenu])
                uiTools  addMenuItem(popup,"Copy", actionMaker new(copyList))
                uiTools  addMenuItem(popup, "Delete", actionMaker new(deleteList))
                uiTools  addMenuItem(popup, "Rename", actionMaker new(renameList))
                uiTools  addMenuItem(popup,"Properties", actionMaker new(propertiesList))
                popWithUniversalChoices()
            }
            if (selectedFileNames size() > 0) {
                if (selectedCells[0] isDir()) {
                    traceln("is dir")
                    popWithDirChoices()
                } else if (suffix == "edesk-cap") {
                    uiTools  addMenuItem(popup,"Open Edesk", actionMaker new(openEDesk))
                    popWithAllDocChoices()
                } else if (suffix == "caplet") {
                    uiTools  addMenuItem(popup,"Install", actionMaker new(installCaplet))
                    def pathVow := myNavigatorRcvr <- getFileNamed(selectedFileNames[0]) <- getCanonicalPath()
                    when (pathVow) -> done(path) {
                        if (installedAppsManager optAppBySourcePath(path) != null) {
                            uiTools  addMenuItem(popup,"Run", actionMaker new(runCaplet))
                        }
                        popWithAllDocChoices()
                    } catch prob {traceln("popup caplet path prob: " + prob)}
                } else {popWithAllDocChoices() }
            } else {
                popWithUniversalChoices()
            }
        }
    }
    def toolbarPane :=
      JPanel`$upButton $homeButton $gotoButton $fullPathTextField.X `
    def navPanelsPane := uiTools makeGridRow([navPanelController1 getMainPanel(), navPanelController2 getMainPanel(), navPanelController3 getMainPanel()])
    def realPane := JPanel`$toolbarPane
                           $navPanelsPane.Y
                           $statusPanel`
    mainPane add(realPane)
    #refreshLocal()
    navFrame pack()
    navFrame show()
    
    def resetPathField() {
            when (navPanelController1 getDiskNavRcvr() <- getCurrentPath()) -> done(path) {
                fullPathTextField setText(path)
            } catch prob {traceln("prob getting path" + prob)}
    
    }
    def navReactorForPathField {
        to wentUp(c) {resetPathField()}
        to jumped(c) {resetPathField()}
        to openedDir(c) {resetPathField()}
        match [verb, args] {}
    }
    navPanelController1 addNavReactor(navReactorForPathField)
    navPanelController1 setDiskNavRcvr(myDiskNavigator)
    resetPathField() 
    
    def  bind navigatorWindow  {
        #to getDiskNavigator(): any {diskNav1()}
        to dupWindow() {
            navigatorWindowMaker new(myFtController, navPanelController1 <- dupDiskNavRcvr())
        }
        to gotoFieldName()  {
            navPanelController1 goto(fullPathTextField getText())
        }
        to getStorageName(): any {myStorageName}
        to refresh() {refreshLocal()}
        to windowClosing() {navFrame dispose()}
        to goUp() {
            #myDiskNavigator <- goUp()
            #navigatorWindow refresh()
            navPanelController1 goUp()
        }
        to goHome() {
            #myDiskNavigator <- gotoHome()
            #navigatorWindow refresh()
            navPanelController1 gotoHome()
        }
        to openRemote() {myFtController openRemote()}
        to openEdesk() {
            def fileNames := navPanelController1 getSelectedNames()
            if (fileNames != null && fileNames size() >0) {
                for each in fileNames {
                    myFtController openEdesk(myDiskNavigator <- getFileNamed(each))
                }
            }
        }
    }
}
//DiskNavigator
class diskNavigatorMaker (var myHomeDirectoryPath, myStorageName, var myRootDirPath, makeFileFunction) : any {
    #traceln("into making disk navigator")
    var myCurrentDir := makeFileFunction(myHomeDirectoryPath)
    //file: myHomeDirectoryPath
    def dirPathString (path) : any {
        //makes sure a dir separator is at end
        def sep := <io:File> separator()
        var answerPath := path
        def lastCharString := path(path size() - 1, path size() )
        if (lastCharString == sep || lastCharString == "/") {
            answerPath := path
        } else {
            answerPath := path + sep
        }
        answerPath
    }
    def dirPath (theDir) : any { dirPathString(theDir getPath())}
    def isInRootTree(theDir) : any {
        var answer := true
        if (myRootDirPath != null) {
            answer := dirPathString(theDir getCanonicalPath()) startsWith(myRootDirPath)
        }
        answer
    }
    def setCurrentDir(theDir) {
        if (theDir exists() && isInRootTree(theDir)) {myCurrentDir := theDir}
    }
    if (myRootDirPath != null) {
        myRootDirPath := dirPathString((makeFileFunction(myRootDirPath)) getCanonicalPath())
        if (isInRootTree(myCurrentDir)) {
            traceln("home is part of the root tree")
        } else {
            println("Home path not part of root tree! Changing")
            myCurrentDir := makeFileFunction( myRootDirPath)
            myHomeDirectoryPath := myRootDirPath
        }
    }
    #traceln("making navigator")
    def diskNavigator {
        //offers MakeAnotherNavigator(homeDirname) returns the navigator uri
        to dupNavigator(): any {
            traceln("into dupnavigator")
            def newNav := diskNavigatorMaker new(myHomeDirectoryPath, myStorageName, myRootDirPath, makeFileFunction)
            newNav changeToDirectory (myCurrentDir getAbsolutePath())
            newNav
        }
        to getStorageName(): any {myStorageName + makeFileFunction label()}
        to versionNumber(): any {versionNumber}
        to currentDirExists() :boolean {myCurrentDir exists()}
        to getCurrentPath (): any {
            if (! (myCurrentDir exists())) {diskNavigator gotoHome()}
            myCurrentDir getAbsolutePath()
        }
        to getParentPath(): any {myCurrentDir getParent()}
        to newFile(name) {
            def theFile := makeFileFunction( (dirPath(myCurrentDir) + name))
            if (! (theFile exists())) {
                theFile setText("")
            }
        }
        to makeDir(dirName) {
            def fullName := dirPath(myCurrentDir) + dirName
            (makeFileFunction( fullName)) mkdir()
        }
        to gotoHome() {
            myCurrentDir := makeFileFunction( myHomeDirectoryPath)
        }
        to changeToDirectory(fullPathName) {
            #traceln("change to directory: " + fullPathName)
            setCurrentDir(makeFileFunction( fullPathName))
        }
        to changeToSubdirectory(name) {
            setCurrentDir(makeFileFunction( (dirPath(myCurrentDir) + name)))
            traceln("diskNav changed to subdir: " +dirPath(myCurrentDir))
        }
        to goUp() {setCurrentDir(makeFileFunction( (myCurrentDir getParent())))}
        to listCurrentSubdirectoriesAndFiles(): any {
            if (! (myCurrentDir exists())) {diskNavigator gotoHome()}
            def fileobjNames := myCurrentDir list()
            def dirTuple := [] diverge()
            def fileTuple := [] diverge()
            #traceln("into list subs, count:" + fileobjNames size())
            for next in fileobjNames {
                if ((makeFileFunction( (dirPath(myCurrentDir) + next))) isDirectory()) {
                    dirTuple push(next)
                } else {
                    fileTuple push(next)
                }
            }
            [dirTuple sort() snapshot(), fileTuple sort() snapshot()]
        }
        to getFileNamed(name) : any {
            fileModelMaker new(makeFileFunction( (dirPath(myCurrentDir) + name)))
        }
        to rename(fileName,newName) {
            (makeFileFunction (dirPath(myCurrentDir) + fileName)) renameTo(makeFileFunction (dirPath(myCurrentDir) + newName))
        }
        to deleteFileObject(fileName) {
            def fileObj := diskNavigator getFileNamed(fileName)
            try {fileObj delete()} catch e1 {}
            if (fileObj exists() && fileObj isDirectory()) {
                traceln("found undeleted dir")
                for each in fileObj {
                    if (each isFile()) {
                        try {each delete()} catch e2{traceln("no file delete" + e2)}
                    } else {
                        def subNavigator := diskNavigator dupNavigator()
                        traceln("got sub navigator for delete")
                        subNavigator changeToSubdirectory (fileName)
                        traceln("about to del dir "+ each getName())
                        subNavigator deleteFileObject(each getName())
                    }
                }
                try {fileObj delete()} catch e3 { traceln("delete folder try 2 failed" + e3)}
            }
        }
    }
}
class revokableConnectionMaker (myFtController) : any {
    def revokableConnection {
        to getANavigator(): any {
            myFtController getANavigator()
        }
        to versionNumber(): any {versionNumber}
    }
}
// farOverwriteAnswerer uses state pattern
// with different functions for different behaviors
// it select the right function with lazy evaluation:
// if there's never a preexisting file to consider overwriting,
// no overwriting policy request ever goes to the user
class overwriteAnswererMaker (): any {
    def alwaysOverwrite(fileName) : any {true}
    def neverOverwrite(fileName) : any {false}
    def askOverwrite(fileName) : any {
        def [answerPromise, resolver] := PromiseMaker()
        def answerDialog := dialogVowMaker  new("Overwrite?", "Overwrite file " + fileName + "?", null, ["Yes","No"])
        when (answerDialog) -> done(answer) {
            resolver resolve (answerDialog getClickedButton() == "Yes")
        } catch err {}
        answerPromise
    }
    var answerFunctionSelectionAlreadyStarted := false
    def [answerFunction,functionResolver] := PromiseMaker()
    def determineOverwritePlan() {
        answerFunctionSelectionAlreadyStarted := true
        def planDialogPromise := dialogVowMaker  new("OverwritePolicy", "When should files be overwritten?", null, ["Always","Never","After Confirmation"])
        when (planDialogPromise) -> done(planDialog) {
            def button := planDialog getClickedButton()
            if (button == "Always") {
                functionResolver resolve(alwaysOverwrite)
            }else if (button == "Never") {
                functionResolver resolve(neverOverwrite)
            }else {functionResolver resolve(askOverwrite)}
        } catch err {}
    }
    def overwriteAnswerer {
        to promiseOverwriteAnswer(fileName) :any {
            if (!answerFunctionSelectionAlreadyStarted) {determineOverwritePlan()}
            answerFunction <- run(fileName)
        }
    }
    overwriteAnswerer
}

traceln("about to compile copyAction")

def copyAction(farFromFile,farToFile,fileName ) : any {
    def vow
    def firstvow := farToFile <- getToCopier() <- copyEventually(farFromFile <- getFromCopier(),
                                                 fileProgressObserverMaker new("Copying " + fileName, farToFile),
                                                 forwarderMaker new(farToFile), forwarderMaker new(farFromFile))
    when (firstvow) -> done(result) {
        traceln("copyaction success: " + result)
        def bind vow := result
    } catch prob {
        traceln("copyaction failure: " + prob + prob eStack())
        traceln("now trying backup strategy") 
        def bind vow := farToFile <- getToCopier() <- copyEventually(forwarderMaker new(farFromFile),
                                                 fileProgressObserverMaker new("Copying " + fileName, farToFile),
                                                 forwarderMaker new(farToFile), forwarderMaker new(farFromFile))
        
    }
    when (vow) -> donevow(finished) {
        traceln("vow resolved nicely")
    } catch vowprob {traceln ("copyaction vow failed finally completely")}
    vow
}


//Sequencer of file copies to limit the number of progress windows and the number
// of big fromFile copy buffers in existence at any one time
def copySequencer := sendValveMaker  new(5)

def copyFiles(fromNavigator, toNavigator, overwriteAnswerer) : any {
    traceln("into copyFiles" + fromNavigator+toNavigator + overwriteAnswerer)
    def copyVows := vowsMonitorMaker new()
    def copyBase(farFromFile, farToFile, fileName) {
        copyVows add(copySequencer makeActionVow([copyAction, "run", [farFromFile, farToFile, fileName]]))
    }
    def filesDirsPromise := fromNavigator <- listCurrentSubdirectoriesAndFiles()
    when (filesDirsPromise) -> done(filesDirs) {
        def fileNames := filesDirs[1]
        for each in fileNames {
            def nextFromFile := fromNavigator <- getFileNamed(each)
            def nextToFile := toNavigator <- getFileNamed(each)
            when (nextToFile <- exists()) -> doneNext(doesExist) {
                if ( doesExist) {
                    def shouldCopy := overwriteAnswerer promiseOverwriteAnswer(each)
                    when (shouldCopy) -> doneCopy(copyFulfilled) {
                        if (shouldCopy) {
                            copyBase(nextFromFile, nextToFile, each)
                        }
                    } catch err {}
                } else {
                    copyBase(nextFromFile, nextToFile, each)
                }
            } catch err{}
        }
        copyVows finishAll()
    } catch err {traceln("error not caught in old version getting filesDirs: " + err)}
    copyVows promiseFinish()
}
class marshalledDirPromiser(farOuterNavigator, farDir) : any {
    traceln("make marshall" + farOuterNavigator + farDir)
    def [marshalledDirPromise, resolver] := PromiseMaker()
    var farDirNavigator := null
    var dirExists := farDir <- exists()
    def dirName := farDir <- getName()
    def dirCanonicalPath := farDir <- getCanonicalPath()
    def dirPath := farDir <- getPath()
    def fillWhenDirExists() {
        farDirNavigator := farOuterNavigator <- dupNavigator()
        farDirNavigator <- changeToSubdirectory (dirName)
        dirExists := true
    }
    def marshalledDir := {
        when (dirPath) -> done(dirPathR) {
            if (dirExists) {fillWhenDirExists()}
            resolver resolve(marshalledDir)
            traceln("dir paths: " + dirCanonicalPath + " :" + dirPath)
        } catch err {
            resolver smash(makeErr ("dead dir: "+ err))
        }
        def marshalledDir {
            to getDir() : any {farDir}
            to getOuterNavigator() :any {farOuterNavigator}
            to getDirNavigator() :any {farDirNavigator}
            to exists() : any {dirExists}
            to getName() : any {dirName}
            to promiseMarshalledSubDir(subName) : any {
                def farSubdir := farDirNavigator <- getFileNamed(subName)
                marshalledDirPromiser new(farDirNavigator,farSubdir)
            }
            to makeSelf() : any {
                var makePromise := null
                if (!dirExists) {
                    makePromise :=  farDir <-mkdir()
                    fillWhenDirExists()
                }
                makePromise
            }
            to isProperSubDir() : any {dirCanonicalPath toLowerCase() == dirPath toLowerCase()}
            to getCanonicalPath() :any {dirCanonicalPath}
            to getPath() : any {dirPath}
        }
    }
    marshalledDirPromise
}

traceln("got up to paster")

//paster
def paster {
    to paste(farFromFiles, fromDiskNavigator, initialToDiskNavigator, toNavigatorWindow) {
        traceln("into paster paste:" + farFromFiles + fromDiskNavigator + toNavigatorWindow)
        def toDiskNavigator := initialToDiskNavigator <- dupNavigator()
        def allDone := vowsMonitorMaker new()
        def myOverwriter := overwriteAnswererMaker new()
        for each in farFromFiles {
            traceln("got each file" + each)
            def isDir := each <- isDirectory()
            def [nextCopyPromise, nextResolver] := PromiseMaker()
            allDone add(nextCopyPromise)
            when (isDir) -> done(isDirR) {
                if (isDirR) {
                    def nextPromise := paster copyDirBegin(each,
                                                           fromDiskNavigator, toDiskNavigator, myOverwriter)
                    nextResolver resolve(nextPromise)
                }else{
                    def nextPromise := paster pasteFile(each,
                                                        toDiskNavigator)
                    nextResolver resolve(nextPromise)
                }
            } catch err {}
        }
        allDone finishAll()
        when (allDone promiseFinish()) -> done(p) {
            traceln("about to refresh after pasting files")
            toNavigatorWindow refresh()
        } catch err {
            toNavigatorWindow refresh()
            connectionWarning("Some files may not have been copy/pasted.\n" + err)
        }
    }
    to pasteFile(fromFilePromise, toDiskNavigator) : any {
        traceln("into pasteFile")
        def  [finishPromise,resolver] := PromiseMaker()
        def startCopyTo(target,fromName) {
            traceln("about to copy in pastefile")
            def finalPromise := copySequencer makeActionVow(
                [copyAction, "run", [fromFilePromise, target, fromName]])
            traceln("about to start resolver in pastefile")
            when (finalPromise) -> done(p) {
                traceln("about to resolve in pastefile: " + p)
                resolver resolve(p)
            } catch err{traceln("err in pasteFile finalpromise: " + err)}
        }
        def fromNamePromise := fromFilePromise <- getName()
        when (fromNamePromise) -> done(fromName) {
            traceln("paste is getting target " + fromName)
            var target := toDiskNavigator <- getFileNamed(fromName)
            traceln("paste target eventually requested")
            when (target <- exists()) -> done2(fileExists) {
                traceln("resolved target exists")
                if (fileExists) {
                    traceln("file exists: " + fromName)
                    def result := <swing:JOptionPane> showInputDialog (null,
                                                                       "Confirm or change name, or cancel",
                                                                       "File " + fromName  + " already exists",
                                                                       <swing:JOptionPane> QUESTION_MESSAGE(), null, null, fromName + "")
                    if (result != null) {
                        if (result != fromName) {
                            target := toDiskNavigator <- getFileNamed(result)
                        }
                        startCopyTo(target,fromName)
                    } else {
                        resolver resolve("user canceled")
                    }
                } else {
                    traceln("about to copyeventually")
                    startCopyTo(target,fromName)
                }
            } catch err2 {
                traceln("err getting fileExists " + err2)
            }
        } catch err {connectionWarning(err)}
        finishPromise
    }
    to copyDirCautiously(marshalledFromDir, marshalledToDir, createdDirPaths, overwriteAnswerer) : any {
        traceln("in copyDirCautiously" + marshalledFromDir + " :" +marshalledToDir)
        //only continue copying if the fromDir is not something we just
        // created as a todir(indicating we are copying a dir into its own subdir)
        //and if the fromdir is not a symlink running off to someplace odd)
        traceln("is proper subdir " + (marshalledFromDir isProperSubDir()))
        def copyVows := vowsMonitorMaker new()
        if ((! (createdDirPaths contains(marshalledFromDir getCanonicalPath()))) && marshalledFromDir isProperSubDir()) {
            traceln("continuing copying in cautiously")
            if (! (marshalledToDir exists())) {
                marshalledToDir makeSelf()
                traceln("made dir")
                createdDirPaths push(marshalledToDir getCanonicalPath())
            }
            copyVows add(copyFiles(marshalledFromDir getDirNavigator(), marshalledToDir getDirNavigator(),overwriteAnswerer))
            def filesDirsPromise := marshalledFromDir getDirNavigator() <- listCurrentSubdirectoriesAndFiles()
            when (filesDirsPromise) -> done(filesDirs) {
                def dirs := filesDirs[0]
                for each in dirs {
                    traceln("copying dir: " + each)
                    def [subDirPromise,subDirResolver] := PromiseMaker()
                    copyVows add(subDirPromise)
                    def fromSubNavigator := marshalledFromDir getDirNavigator()
                    def marshalledFromSubDir := marshalledDirPromiser new(fromSubNavigator, fromSubNavigator <- getFileNamed(each))
                    def toSubNavigator := marshalledToDir getDirNavigator()
                    def marshalledToSubDir := marshalledDirPromiser new(toSubNavigator, toSubNavigator <- getFileNamed(each))
                    def dirsReadyVow := promiseAllResolved([marshalledToSubDir, marshalledFromSubDir])
                    when (dirsReadyVow) -> done2(dirsReady) {
                        subDirResolver resolve(paster copyDirCautiously (marshalledFromSubDir,  marshalledToSubDir, createdDirPaths, overwriteAnswerer))
                    } catch e {
                        connectionWarning(e)
                        subDirResolver smash(makeErr ("Couldn't connect to directory: " + e))
                    }
                }
                copyVows finishAll()
            } catch err {}
        } else {copyVows finishAll()}
        copyVows promiseFinish()
    }
    to copyDirBegin(farFromDir, farFromDisk, toDiskNavigator, overwriteAnswerer) : any {
        def farToDisk := toDiskNavigator <- dupNavigator()
        def fromDir := marshalledDirPromiser new(farFromDisk,farFromDir)
        def createdDirPaths := [] diverge()
        def [dirCopyCompletePromise, dirCopyCompleteResolver] := PromiseMaker()
        when (fromDir) -> done(fromDirR) {
            def farToDir := farToDisk <- getFileNamed(fromDir getName())
            def toDir := marshalledDirPromiser new(farToDisk, farToDir)
            when (toDir) -> done2(toDirR) {
                def copyPromise := paster copyDirCautiously (fromDir, toDir, createdDirPaths, overwriteAnswerer)
                dirCopyCompleteResolver resolve(copyPromise)
            }catch err2 {
                dirCopyCompleteResolver smash(makeErr ("Lost connection: " +err2))
                connectionWarning(err2)
            }
        } catch err {}
        dirCopyCompletePromise
    }
}

def makeDefaultConfigMap() :near {
    def map := [] asKeys() diverge()
    map["windowTitle"] := "My eDesk"
    map["home"] :=  if (<file:~/Desktop> exists()) {"~/Desktop"} else {"~/"}
    map["serverOnly"] := false
    map["capabilityFile"] := null
    map["makeFileFunction"] := makeWriteFile
    map["virtualRoot"] := null
    map
}

#assumes it is getting a default config, modifying from there
def setConfigFromCommandLine(configMap) {
    def commandArgs := interp getArgs()
    configMap["windowTitle"] := commandArgs[0]
    configMap["serverOnly"] := commandArgs[1] != "gui"
    configMap["home"] := commandArgs[2]
    if (commandArgs size() > 3) {configMap["capabilityFile"] := commandArgs[3]}
    if (commandArgs size() >4) {configMap["virtualRoot"] := commandArgs[4]}
    if (commandArgs size() > 5 && commandArgs[5] != "write") {
        traceln("Read Only File System")
        configMap["makeFileFunction"] := makeReadFile
        #diddling rather global variable
        toFileCopierMaker := readOnlyToFileCopierMaker
    }
}

traceln("about to compile setconfig from file")

#assumes it is getting a default config, modifying from there
def setConfigFromFile(configFile,configMap) {
    if (configFile exists()) {
        for each in configFile {
            if (each =~ `@keyword=@value${"\n"}`) {
                if (keyword == "isReadOnly" && value=="true") {
                    configMap["makeFileFunction"]:=makeReadFile
                } else if (keyword == "serverOnly") {
                    configMap[keyword] := value == "true"
                } else {configMap[keyword] := value }
            }
        }
    }
}

traceln("about to compile ftControllerMaker")


//ftController
class ftControllerMaker(): any {
    def  ftController
    var copyBuffer := null
    var copyBufferDiskNavigator := null
    var configMap := makeDefaultConfigMap()
    def commandArgs := interp getArgs()
    traceln("command arguments" + commandArgs)
    if (commandArgs size() > 1) {setConfigFromCommandLine(configMap)}
    if (commandArgs size() < 1) {setConfigFromFile(<file:edesk.conf>, configMap)}
    if (commandArgs size() == 1) {setConfigFromFile(<file: commandArgs[0]>, configMap)}
    def myHomeNavigator := diskNavigatorMaker new(configMap["home"],
                                                  configMap["windowTitle"], configMap["virtualRoot"], configMap["makeFileFunction"])
    if (configMap["serverOnly"]) {
        def identityFilePath := edeskHomePath + configMap["windowTitle"] + ".edesk-private"
        def identityFile := <file: identityFilePath>
        def conn := revokableConnectionMaker new(ftController)
        def sturdyConn
        traceln("server only")
        if (!(identityFile exists())) {
            traceln("first incarnation")
            def keyPair := introducer newVatIdentity()
            introducer onTheAir()
            def netConfig := introducer getNetConfig()
            def [bind sturdyConn, swissBase] := 
                sturdyRef incarnate(conn)
            SerializerMaker recordFile(identityFile, [netConfig, keyPair, swissBase])
        } else {
            traceln("reincarnation")
            def [netConfig, keyPair, swissBase] := UnserializerMaker playFile(identityFile)
            introducer setNetConfig(netConfig)
            introducer setVatIdentity(keyPair)
            introducer onTheAir()
            def bind sturdyConn := sturdyRef reincarnate(conn, swissBase)
        }
        def capFile := <file: configMap["capabilityFile"]>
        def cap := introducer sturdyToURI(sturdyConn)
        traceln("made cap: " + cap)
        capFile setText(cap)
        println("Disk Navigator Operational")
    } else {
        navigatorWindowMaker new(ftController, myHomeNavigator)
        introducer onTheAir()
    }
    
    def  getRemoteConnectionURI(): any {
        var uri  := null
        def blah := eFrameMaker new("")
        def dialog := <awt:FileDialog> new(blah, "Select an Edesk erights file")
        dialog show()
        var path := dialog getFile()
        if (path != null) {
            path := dialog getDirectory() + path
            uri := (<file:  path>) getText()
            traceln("connection is:" + uri)
        }
        uri
    }
    def buildNavWindow(uri) {
        traceln("in buildnavwin, uri:" + uri)
        def connector:= uriTools promiseObject(uri)
        traceln("connector is" + connector)
        def navigator := connector <- getANavigator()
        def versionPromise := connector <-versionNumber()
        when (versionPromise) -> done(version) {
            traceln("ha! resolved promise")
            if (version == versionNumber) {
                navigatorWindowMaker new(ftController,  navigator)
            } else {
                connectionWarning("Wrong Version")
            }
        } catch err {
            connectionWarning("Remote Navigator Not Acquired\n"  + err)
            traceln("connection failure" + err)
        }
    }
    def bind ftController  {
        to copyFrom(fromFilePromises,fromDiskNavigator) {
            copyBuffer := fromFilePromises
            copyBufferDiskNavigator := fromDiskNavigator <- dupNavigator()
            traceln("copyFrom: " + fromFilePromises + copyBufferDiskNavigator)
        }
        to paste(toDiskNavigator, navigatorWindow) {
            traceln("paste started with: " + copyBuffer + copyBufferDiskNavigator)
            paster paste(copyBuffer, copyBufferDiskNavigator, toDiskNavigator, navigatorWindow)
        }
        to getANavigator(): any {
            diskNavigatorMaker new(configMap["home"], configMap["windowTitle"],
                                   configMap["virtualRoot"], configMap["makeFileFunction"])
        }
        to openRemote() {
            def uri := getRemoteConnectionURI()
            if (uri != null) {
                buildNavWindow(uri)
            }
        }
        to openEdesk(filePromise) {
            def uri := filePromise <- getText()
            when (uri) -> done(uriR) {
                buildNavWindow(uri)
            } catch err {
                connectionWarning("No Edesk server")
            }
        }
    }
}

traceln("about to make controller")
def baseController := ftControllerMaker new()
interp blockAtTop()




1.1                  e/src/esrc/scripts/intro.updoc

Index: intro.updoc
===================================================================
Elmer is a simple text editor that also executes embedded
command line examples.  Try hitting enter below

    ? 2 + 3