Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Comparing changes

Choose two branches to see what's changed or to start a new pull request. If you need to, you can also compare across forks.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also compare across forks.
base fork: bytbox/EVAN
base: 7999976685
...
head fork: bytbox/EVAN
compare: 81cc254954
  • 12 commits
  • 30 files changed
  • 0 commit comments
  • 1 contributor
View
4 .gitignore
@@ -2,7 +2,7 @@
__pycache__
*.o
*.hi
-json2hs/json2hs
+evan2hs/evan2hs
dist
lib/evan
bin
@@ -15,3 +15,5 @@ docs/
gui/fdocs.py
lib
contrib/
+.depends
+gui/evan
View
18 build.bash
@@ -12,14 +12,6 @@ cpipe() {
. ./common.sh
-if test $PY && test $IMDISP; then
- # TODO keep going even when deps not found
- echo Checking python dependencies...
- python3 -c 'import tkinter'
-else
- echo "Python dependencies not present; will prepare evan.py anyway"
-fi
-
echo Creating directories...
rm -rf bin
mkdir -p bin lib analysis
@@ -29,6 +21,10 @@ HSINST="cabal install --bindir=$EVANROOT/bin"
echo Unpacking contrib...
tar xzf contrib.tgz
+echo Building GUI...
+cd $EVANROOT/gui
+make | cpipe
+
#echo Updating haskell package database...
#cabal update 2>&1 | cpipe
@@ -47,11 +43,6 @@ mkdir -p docs
perl -Icontrib/perl-json tools/xdocs.pl evanlib/EVAN > docs/reference.json
$EVANBIN/evan-mkref-html < docs/reference.json > docs/reference.html
-echo Preparing python GUI...
-cd $EVANROOT/gui
-./genTools.pl
-./genDocs.pl
-
if test $GO; then
echo Building httpd...
cd $EVANROOT/httpd
@@ -65,6 +56,5 @@ cd $EVANROOT
echo Populating bin/...
ln -s `pwd`/tools/json2hs/json2hs.py bin/json2hs
ln -s `pwd`/scripts/evan-compile bin/evan-compile
-tools/merge.pl gui/evan.py > bin/evan
chmod +x bin/evan
View
3  clean.sh
@@ -16,6 +16,9 @@ for d in $HSCLEAN; do
cabal clean -v0
done
+cd $EVANROOT/gui
+make clean
+
if test $GO; then
echo Cleaning httpd...
cd $EVANROOT/httpd
View
4 common.sh
@@ -8,10 +8,6 @@ if which go > /dev/null 2>/dev/null; then
GO=`which go`
fi
-if which python3 > /dev/null 2>/dev/null; then
- PY=`which python3`
-fi
-
if which display > /dev/null 2>/dev/null; then
IMDISP=`which display`
fi
View
25 gui/Makefile
@@ -0,0 +1,25 @@
+MODULES = main program canvas json
+HEADERS = fltk.hh program.hh canvas.hh json.hh
+
+LIBS = -lfltk
+LDFLAGS =
+CXXFLAGS = -O2 -Wall
+
+SOURCE = ${MODULES:=.cc}
+OBJECTS = ${MODULES:=.o}
+
+all: evan
+
+.depends: ${SOURCE} ${HEADERS}
+ ${CXX} -MM ${SOURCE} > $@
+
+-include .depends
+
+evan: ${OBJECTS}
+ ${CXX} -o $@ ${LDFLAGS} ${OBJECTS} ${LIBS}
+
+clean:
+ ${RM} evan ${OBJECTS} .depends
+
+.PHONY: all clean
+
View
0  gui/README
No changes.
View
41 gui/about.py
@@ -1,41 +0,0 @@
-# About dialog for the EVAN python+tk frontend. See README for notes.
-
-from tkinter import *
-
-VERSION = '0.1'
-
-class AboutDialog(Toplevel):
- def __init__(self, parent):
- Toplevel.__init__(self, parent)
- self.parent = parent
- self.title("About EVAN")
- #self.transient(parent)
- body = Frame(self)
- Label(body, text="EVAN "+VERSION).pack()
- self.initial_focus = body
- body.pack(padx=5, pady=5)
- self.grab_set()
- self.protocol("WM_DELETE_WINDOW", self.cancel)
- self.geometry("+%d+%d" % (parent.winfo_rootx()+50,
- parent.winfo_rooty()+50))
- self.initial_focus.focus_set()
- self.wait_window(self)
-
- def cancel(self):
- self.parent.focus_set()
- self.destroy()
-
- def validate(self):
- return 1
-
- def apply(self):
- pass
-
-about_dialog_parent = None
-
-def prepareAbout(parent):
- global about_dialog_parent
- about_dialog_parent = parent
-
-def showAbout():
- ad = AboutDialog(about_dialog_parent)
View
27 gui/canvas.cc
@@ -0,0 +1,27 @@
+#include "canvas.hh"
+
+#include <vector>
+using namespace std;
+
+WComment::WComment(Comment *c)
+ : Fl_Widget(c->pos.x, c->pos.y, 5, 5), c(c) {
+
+}
+
+void WComment::draw() {
+ draw_box(FL_BORDER_BOX, FL_CYAN);
+}
+
+Canvas::Canvas(int x, int y, int w, int h, Program *p)
+ : Fl_Widget(x, y, w, h, p->Name()), p(p) {
+ // TODO create widgets from program
+}
+
+void Canvas::draw() {
+ draw_box(FL_DOWN_BOX, FL_WHITE);
+
+ for (map<int, Fl_Widget *>::iterator i = parts.begin(); i != parts.end(); i++) {
+ (*i).second->draw();
+ }
+}
+
View
40 gui/canvas.hh
@@ -0,0 +1,40 @@
+#ifndef CANVAS_HH
+#define CANVAS_HH
+
+#include "program.hh"
+
+#include "fltk.hh"
+
+#include <FL/fl_draw.H>
+
+#include <map>
+#include <vector>
+
+class WComment : public Fl_Widget {
+public:
+ WComment(Comment *);
+ virtual void draw();
+protected:
+ Comment *c;
+private:
+};
+
+class WBlock : public Fl_Widget {
+public:
+ virtual void draw();
+protected:
+private:
+};
+
+class Canvas : public Fl_Widget {
+public:
+ Canvas(int, int, int, int, Program *p = Program::sample());
+ virtual void draw();
+protected:
+ Program *p;
+ std::map<int, Fl_Widget *> parts;
+private:
+};
+
+#endif /* !CANVAS_HH */
+
View
309 gui/canvas.py
@@ -1,309 +0,0 @@
-# Canvas handling for the python+tk frontend. See README for notes.
-
-from tkinter import *
-from tkinter.filedialog import *
-from tkinter.font import *
-
-#!START local
-from external import *
-from program import *
-from results import *
-#!END local
-
-FILETYPES = [("EVAN Programs", ".evan")]
-DATATYPES = [("HEPEVT", ".dat"), ("LHE", ".lhe")]
-
-FONTA = ("Helvetica", 10, "bold")
-FONTB = ("Times", 10)
-
-BLOCK_HEIGHT = 26
-PORT_HEIGHT = 10
-
-class CanvasState:
- """ Encapsulates the state of the canvas as well as the user interaction
- logic. """
-
- def __init__(self, canvas, root):
- self.last_x = -1
- self.last_y = -1
- self.isdown = False
- self.dragdist = 0
- self.canvas = canvas
- self.root = root
- self.program = None
- self.tool = None
- self.selname = None
- self.selected = None
- self.seloutput = None
- self.selinput = None
- self.objectsById = {}
- self.outputs = {}
- self.inputs = {}
- self.datafname = None
-
- def useTool(self, tool):
- self.tool = tool
-
- def canvas_down(self, event):
- self.isdown = True
- self.dragdist = 0
- x = self.canvas.canvasx(event.x)
- y = self.canvas.canvasy(event.y)
- self.last_x, self.last_y = x, y
-
- if self.tool is not None:
- self.tool(self.program, x, y, self.root)
- self.tool = None
- self.update_display()
- return
-
- self.selname, self.selected = self.obj_at(x, y)
- if self.selected is None and self.seloutput is None:
- # find out if an output was clicked
- self.seloutput = self.out_at(x, y)
- elif self.selected is None and self.seloutput:
- selinput = self.in_at(x, y)
- seloutput = self.seloutput
- self.seloutput = None
- if selinput:
- p = Pipe(seloutput, selinput)
- self.program.add_pipe(p)
-
- self.update_display()
-
- def canvas_up(self, event):
- self.isdown = False
- x = self.canvas.canvasx(event.x)
- y = self.canvas.canvasy(event.y)
- self.last_x, self.last_y = x, y
-
- def canvas_move(self, event):
- # TODO change cursor
- x = self.canvas.canvasx(event.x)
- y = self.canvas.canvasy(event.y)
- if self.isdown and self.selected:
- dx = x - self.last_x
- dy = y - self.last_y
- self.selected.move(dx, dy)
- self.last_x, self.last_y = x, y
- self.update_display()
-
- def dele(self, event=None):
- self.program.delete(self.selname)
- self.update_display()
-
- def newProg(self, event=None):
- """ Create a new program. Called when the menu item File->New is activated.
- """
-
- self.program = Program()
- self.program.std_init()
- self.update_display()
- self.fname = None
-
- def loadProg(self, event=None):
- """ Load a program from a file. Called when the menu item File->Open is
- activated. """
-
- nfname = askopenfilename(defaultextension=".evan", filetypes = FILETYPES)
- if nfname is None or len(nfname) < 1:
- # do nothing!
- return
- self.fname = nfname
- with open(self.fname) as f:
- self.program = program_from_json(f.read())
- self.update_display()
-
- def openProg(self, fname):
- """ Load a program from the given filename. """
-
- self.fname = fname
- with open(fname) as f:
- self.program = program_from_json(f.read())
- self.update_display()
-
- def saveProg(self, event=None):
- """ Save a program to a file. Called when the menu item File->Save is
- activated. """
-
- if self.fname is None:
- self.fname = asksaveasfilename(defaultextension=".evan", filetypes = FILETYPES)
- if self.fname is not None and len(self.fname) > 0:
- with open(self.fname, 'w') as f:
- f.write(self.program.as_json())
-
- def saveProgAs(self):
- """ Save a program to a selected file. Called when the menu item File->Save
- As is activated. """
-
- nfname = asksaveasfilename(defaultextension=".evan", filetypes = FILETYPES)
- if nfname is not None and len(nfname) > 0:
- self.fname = nfname
- self.saveProg()
-
- def do_compile(self):
- """ Perform compilation. """
-
- self.saveProg()
- compile_prog(self)
-
- def do_run(self):
- """ Run the analysis. """
-
- if self.datafname is None:
- self.do_run_on()
- return
- self.saveProg()
- if compile_prog(self):
- r = run_prog(self, self.datafname)
- display_results(r)
-
- def do_run_on(self):
- """ Ask for a filename and run the analysis on that file. """
-
- self.saveProg()
- if compile_prog(self):
- self.datafname = askopenfilename(filetypes = DATATYPES)
- r = run_prog(self, self.datafname)
- display_results(r)
-
- def obj_at(self, x, y):
- """ Find and return the object at the specified co-ordinates. """
-
- if self.in_at(x, y) is not None or self.out_at(x, y) is not None:
- return None, None
-
- for i in range(0,5):
- ids = self.canvas.find_overlapping(x-i,y-i,x+i,y+i)
- for id in ids:
- if id in self.objectsById:
- return self.objectsById[id]
-
- return None, None
-
- def in_at(self, x, y):
- """ Find and return the object with an output at the specified co-ordinates. """
-
- ids = self.canvas.find_overlapping(x,y,x,y)
- for id in ids:
- if id in self.inputs:
- return self.inputs[id]
-
- return None
-
- def out_at(self, x, y):
- """ Find and return the object with an output at the specified co-ordinates. """
-
- ids = self.canvas.find_overlapping(x,y,x,y)
- for id in ids:
- if id in self.outputs:
- return self.outputs[id]
-
- return None
-
- def block_width(self, b):
- return 70
-
- def update_display(self):
- """ Update the canvas display. """
-
- # TODO don't re-draw /everything/ - use find_all and Graphical.ids
-
- self.canvas.delete(ALL)
- objects = self.program.objects
-
- if self.selected is None and self.seloutput:
- # We're in the process of drawing a pipe
- w = self.block_width(objects[self.seloutput[0]])
- oc = objects[self.seloutput[0]].output_count
- o = self.seloutput[1]
- sp = objects[self.seloutput[0]].pos()
- self.canvas.create_line(
- sp[0] - w/2 + (w/oc)/2 + o*(w/oc),
- sp[1]+BLOCK_HEIGHT/2+PORT_HEIGHT,
- self.last_x,
- self.last_y)
-
- for obj in objects:
- o = objects[obj]
- if o.kind == PIPE:
- sn, si = o.source
- dn, di = o.dest
- sp, dp = objects[sn].pos(), objects[dn].pos()
- sw = self.block_width(objects[sn])
- oc = objects[sn].output_count
- on = si
- dw = self.block_width(objects[dn])
- ic = objects[dn].input_count
- i = di
- color = "#000000"
- if o is self.selected:
- color = "#ff2255"
- ld = self.canvas.create_line(
- sp[0] - sw/2 + (sw/oc)/2 + on*sw/oc,
- sp[1]+BLOCK_HEIGHT/2+PORT_HEIGHT,
- dp[0] - dw/2 + (dw/ic)/2 + i*dw/ic,
- dp[1]-BLOCK_HEIGHT/2-PORT_HEIGHT,
- fill=color)
- self.objectsById[ld] = obj, o
-
- for obj in objects:
- o = objects[obj]
- if o.kind == BLOCK:
- b=o
- fill = "#00ffff"
- afill = "#aaffff"
- if o is self.selected:
- fill = "#ffff00"
- afill = "#ffffaa"
- # TODO get size of glyph or string
- h = BLOCK_HEIGHT
- w = self.block_width(o)
- pos = o.pos()
- i = self.canvas.create_rectangle(
- pos[0]-w/2, pos[1]-h/2, pos[0]+w/2, pos[1]+h/2,
- fill=fill, activefill=afill)
- self.objectsById[i] = obj, o
-
- mh = PORT_HEIGHT
- # input and output blocks
- for i in range(0, b.input_count):
- iw = w/b.input_count
- ob = self.canvas.create_rectangle(
- pos[0]-w/2+i*iw,
- pos[1]-h/2-mh,
- pos[0]-w/2+(i+1)*iw,
- pos[1]-h/2,
- fill=fill, activefill=afill)
- self.inputs[ob] = obj, i
-
- for i in range(0, b.output_count):
- ow = w/b.output_count
- ob = self.canvas.create_rectangle(
- pos[0]-w/2+i*ow,
- pos[1]+h/2,
- pos[0]-w/2+(i+1)*ow,
- pos[1]+h/2+mh,
- fill=fill, activefill=afill)
- self.outputs[ob] = obj, i
-
- bt = b.ident
- for p in o.params:
- bt += " : " + p
-
- self.canvas.create_text(pos, font=FONTA,
- text=bt, state=DISABLED)
-
- if o.kind == COMMENT:
- cid = obj
- comment = o
- h = 26
- w = 160
- pos = comment.pos()
- i = self.canvas.create_rectangle(
- pos[0]-w/2, pos[1]-h/2, pos[0]+w/2, pos[1]+h/2,
- fill="#ffff00", activefill="#ffffaa")
- self.objectsById[i] = cid, comment
- self.canvas.create_text(pos, font=FONTB,
- text=comment.text, state=DISABLED, width=w)
-
View
5 gui/docs.py
@@ -1,5 +0,0 @@
-""" Documentation handling. See README for notes. """
-
-#!START local
-from fdocs import *
-#!END
View
154 gui/evan.py
@@ -1,154 +0,0 @@
-#!/usr/bin/env python3
-
-# Main component of the EVAN python+tk frontend. See README for notes.
-
-from optparse import *
-import random
-
-from tkinter import *
-from tkinter.filedialog import *
-
-#!START local
-from about import *
-from canvas import *
-from docs import *
-from program import *
-from tools import *
-#!END local
-
-VERSION = '0.1'
-
-# parse options
-parser = OptionParser(usage="usage: %prog [fname.evan]", version="EVAN "+VERSION)
-options, args = parser.parse_args()
-
-arg_progname = None
-if len(args) > 1:
- parser.print_help()
- exit(1)
-if len(args) == 1:
- arg_progname = args[0]
-
-def make_menubar(root):
- """ Initializes the menus."""
-
- menubar = Menu(root)
- root.config(menu=menubar)
-
- # File menu
- filemenu = Menu(menubar, tearoff=0)
- menubar.add_cascade(label="File", underline=0, menu=filemenu)
- filemenu.add_command(label="New", underline=0, command=cState.newProg)
- filemenu.add_command(label="Open...", underline=0, command=cState.loadProg)
- filemenu.add_command(label="Save", underline=0, command=cState.saveProg)
- filemenu.add_command(label="Save As...", underline=5, command=cState.saveProgAs)
- filemenu.add_separator()
- filemenu.add_command(label="Exit", underline=1, command=root.destroy)
-
- # Help menu
- helpmenu = Menu(menubar, tearoff=0)
- menubar.add_cascade(label="Help", underline=0, menu=helpmenu)
- helpmenu.add_command(label="About", underline=0, command=showAbout)
-
-def use_tool(t, cState):
- return lambda:cState.useTool(t)
-
-# A popup toolbar.
-class Popup(Menu):
-
- def __init__(self, cState, root, tb, cname, cat):
- Menu.__init__(self, root, tearoff=0)
- self.tb = tb
- self.up = False
- for n in cat:
- self.add_command(label=n, command=use_tool(cat[n], cState))
-
- def popup(self):
- if self.up:
- self.unpost()
- self.up = False
- else:
- self.up = True
- try:
- self.post(self.tb.x, self.tb.y)
- finally:
- self.grab_release()
-
-# Toolbar. Yes, the toolbar goes on the left side; not the top, not the right,
-# and not the bottom. Screens are wider than they are tall, and people will
-# tend to be working on the left side of the screen, making a left-handed
-# toolbar easier to use. This shouldn't even be configurable - any attempt to
-# change it is probably a mistake.
-class Toolbar(Frame):
- def __init__(self, cState, root):
- Frame.__init__(self, root, bd=2, relief=SUNKEN)
- self.pack(side=LEFT, anchor='nw', fill=BOTH, expand=0)
- self.x = 0
- self.y = 0
-
- def move(self, e):
- self.x, self.y = e.x_root, e.y_root
-
- def populate(self):
- Button(self, text="Compile", command=cState.do_compile).pack(side=TOP)
- Button(self, text="Run", command=cState.do_run).pack(side=TOP)
- Button(self, text="Run On...", command=cState.do_run_on).pack(side=TOP)
- for tool in tools:
- b = Button(self, text=tool, command=use_tool(tools[tool], cState))
- b.pack(side=TOP)
-
- for cat in categories:
- p = Popup(cState, root, self, cat, categories[cat])
- b = Button(self, text=cat, command=p.popup)
- b.pack(side=TOP)
-
-# Set up the GUI
-root = Tk()
-root.title('EVAN')
-root.protocol('WM_DELETE_WINDOW', root.destroy)
-
-# Drawing area
-drawFrame = Frame(root)
-drawFrame.pack(side=RIGHT, anchor='ne', fill=BOTH, expand=1)
-extraFrame = Frame(drawFrame)
-extraFrame.pack(side=TOP, anchor='nw', fill=BOTH, expand=1)
-canvas = Canvas(extraFrame, bg='white', bd=2, relief=SUNKEN)
-canvas.pack(side=LEFT, anchor='nw', fill=BOTH, expand=1)
-cState = CanvasState(canvas, root)
-# And event hooks
-canvas.bind('<ButtonPress>', cState.canvas_down)
-canvas.bind('<ButtonRelease>', cState.canvas_up)
-canvas.bind('<Motion>', cState.canvas_move)
-root.bind('<x>', cState.dele)
-root.bind('<Control-n>', cState.newProg)
-root.bind('<Control-o>', cState.loadProg)
-root.bind('<Control-s>', cState.saveProg)
-
-# canvas should be scrollable, in both directions
-hBar = Scrollbar(drawFrame, orient=HORIZONTAL)
-hBar.pack(side=BOTTOM, anchor='se', fill=X)
-hBar.config(command=canvas.xview)
-canvas.config(xscrollcommand=hBar.set)
-
-vBar = Scrollbar(extraFrame, orient=VERTICAL)
-vBar.pack(side=RIGHT, anchor='ne', fill=Y)
-vBar.config(command=canvas.yview)
-canvas.config(yscrollcommand=vBar.set)
-
-toolbar = Toolbar(cState, root)
-toolbar.populate()
-root.bind('<Motion>', toolbar.move)
-
-# Menu bar
-make_menubar(root)
-
-# Initialize.
-if arg_progname is None:
- cState.newProg()
-else:
- cState.openProg(arg_progname)
-
-prepareAbout(root)
-
-# Main loop
-root.mainloop()
View
59 gui/external.py
@@ -1,59 +0,0 @@
-""" Execution control. See README for notes. """
-
-import os
-import os.path
-import shutil
-import subprocess
-
-BUILD_DIR = "_evan_build"
-
-def build_dir(prog):
- """ Creates, if necessary, a directory to be used for builds, and returns
- the name. """
-
- fn = prog.fname
- dn = os.path.dirname(fn)
- bdn = os.path.join(dn, BUILD_DIR)
- if not os.path.exists(bdn):
- os.mkdir(bdn)
- sbdn = os.path.join(bdn, os.path.basename(fn))
- if not os.path.exists(sbdn):
- os.mkdir(sbdn)
- return sbdn
-
-def compile_prog(prog):
- """ Compiles the given program. """
-
- d = build_dir(prog)
- # Copy the .evan file into the build dir
- shutil.copy(prog.fname, d)
- fname = os.path.join(d, prog.fname)
- # Run evan-compile on the copied file
- PIPE=subprocess.PIPE
- p = subprocess.Popen(["evan-compile", fname], stdout=PIPE, stderr=PIPE)
- out, err = p.communicate()
- e = err.decode('utf-8')
- if len(e) > 0:
- handle_error(e)
- return False
- return True
-
-def run_prog(prog, datafname):
- """ Runs the given program on the given dataset. The results are returned.
- """
-
- d = build_dir(prog)
- xname = os.path.join(d, os.path.splitext(prog.fname)[0])
- PIPE = subprocess.PIPE
- p = subprocess.Popen([xname, datafname], stdout=PIPE, stderr=PIPE)
- out, err = p.communicate()
- e = err.decode('utf-8')
- if len(e) > 0:
- handle_error(e)
- return None
-
- return out.decode('utf-8')
-
-def handle_error(e):
- print("ERR: " + e) # TODO dialog or error pane or something
-
View
126 gui/fltk.hh
@@ -0,0 +1,126 @@
+#ifndef _FULL_FL_H
+#define _FULL_FL_H
+
+#include <FL/Fl_Adjuster.H>
+#include <FL/Fl_Bitmap.H>
+#include <FL/Fl_BMP_Image.H>
+#include <FL/Fl_Box.H>
+#include <FL/Fl_Browser_.H>
+#include <FL/Fl_Browser.H>
+#include <FL/Fl_Button.H>
+#include <FL/Fl_Cairo.H>
+#include <FL/Fl_Cairo_Window.H>
+#include <FL/Fl_Chart.H>
+#include <FL/Fl_Check_Browser.H>
+#include <FL/Fl_Check_Button.H>
+#include <FL/Fl_Choice.H>
+#include <FL/Fl_Clock.H>
+#include <FL/Fl_Color_Chooser.H>
+#include <FL/Fl_Counter.H>
+#include <FL/Fl_Device.H>
+#include <FL/Fl_Dial.H>
+#include <FL/Fl_Double_Window.H>
+#include <FL/Fl_Export.H>
+#include <FL/Fl_File_Browser.H>
+#include <FL/Fl_File_Chooser.H>
+#include <FL/Fl_File_Icon.H>
+#include <FL/Fl_File_Input.H>
+#include <FL/Fl_Fill_Dial.H>
+#include <FL/Fl_Fill_Slider.H>
+#include <FL/Fl_Float_Input.H>
+#include <FL/Fl_FormsBitmap.H>
+#include <FL/Fl_FormsPixmap.H>
+#include <FL/Fl_Free.H>
+#include <FL/Fl_GIF_Image.H>
+#include <FL/Fl_Gl_Window.H>
+#include <FL/Fl_Group.H>
+#include <FL/Fl.H>
+#include <FL/Fl_Help_Dialog.H>
+#include <FL/Fl_Help_View.H>
+#include <FL/Fl_Hold_Browser.H>
+#include <FL/Fl_Hor_Fill_Slider.H>
+#include <FL/Fl_Hor_Nice_Slider.H>
+#include <FL/Fl_Hor_Slider.H>
+#include <FL/Fl_Hor_Value_Slider.H>
+#include <FL/Fl_Image.H>
+#include <FL/Fl_Input_Choice.H>
+#include <FL/Fl_Input_.H>
+#include <FL/Fl_Input.H>
+#include <FL/Fl_Int_Input.H>
+#include <FL/Fl_JPEG_Image.H>
+#include <FL/Fl_Light_Button.H>
+#include <FL/Fl_Line_Dial.H>
+#include <FL/Fl_Menu_Bar.H>
+#include <FL/Fl_Menu_Button.H>
+#include <FL/Fl_Menu_.H>
+#include <FL/Fl_Menu.H>
+#include <FL/Fl_Menu_Item.H>
+#include <FL/Fl_Menu_Window.H>
+#include <FL/Fl_Multi_Browser.H>
+#include <FL/Fl_Multi_Label.H>
+#include <FL/Fl_Multiline_Input.H>
+#include <FL/Fl_Multiline_Output.H>
+#include <FL/Fl_Native_File_Chooser.H>
+#include <FL/Fl_Nice_Slider.H>
+#include <FL/Fl_Object.H>
+#include <FL/Fl_Output.H>
+#include <FL/Fl_Overlay_Window.H>
+#include <FL/Fl_Pack.H>
+#include <FL/Fl_Paged_Device.H>
+#include <FL/Fl_Pixmap.H>
+#include <FL/Fl_Plugin.H>
+#include <FL/Fl_PNG_Image.H>
+#include <FL/Fl_PNM_Image.H>
+#include <FL/Fl_Positioner.H>
+#include <FL/Fl_PostScript.H>
+#include <FL/Fl_Preferences.H>
+#include <FL/Fl_Printer.H>
+#include <FL/Fl_Progress.H>
+#include <FL/Fl_Radio_Button.H>
+#include <FL/Fl_Radio_Light_Button.H>
+#include <FL/Fl_Radio_Round_Button.H>
+#include <FL/Fl_Repeat_Button.H>
+#include <FL/Fl_Return_Button.H>
+#include <FL/Fl_RGB_Image.H>
+#include <FL/Fl_Roller.H>
+#include <FL/Fl_Round_Button.H>
+#include <FL/Fl_Round_Clock.H>
+#include <FL/Fl_Scrollbar.H>
+#include <FL/Fl_Scroll.H>
+#include <FL/Fl_Secret_Input.H>
+#include <FL/Fl_Select_Browser.H>
+#include <FL/Fl_Shared_Image.H>
+#include <FL/Fl_Simple_Counter.H>
+#include <FL/Fl_Single_Window.H>
+#include <FL/Fl_Slider.H>
+#include <FL/Fl_Spinner.H>
+#include <FL/Fl_Sys_Menu_Bar.H>
+#include <FL/Fl_Table.H>
+#include <FL/Fl_Table_Row.H>
+#include <FL/Fl_Tabs.H>
+#include <FL/Fl_Text_Buffer.H>
+#include <FL/Fl_Text_Display.H>
+#include <FL/Fl_Text_Editor.H>
+#include <FL/Fl_Tiled_Image.H>
+#include <FL/Fl_Tile.H>
+#include <FL/Fl_Timer.H>
+#include <FL/Fl_Toggle_Button.H>
+#include <FL/Fl_Toggle_Light_Button.H>
+#include <FL/Fl_Toggle_Round_Button.H>
+#include <FL/Fl_Tooltip.H>
+#include <FL/Fl_Tree.H>
+#include <FL/Fl_Tree_Item_Array.H>
+#include <FL/Fl_Tree_Item.H>
+#include <FL/Fl_Tree_Prefs.H>
+#include <FL/Fl_Valuator.H>
+#include <FL/Fl_Value_Input.H>
+#include <FL/Fl_Value_Output.H>
+#include <FL/Fl_Value_Slider.H>
+#include <FL/Fl_Widget.H>
+#include <FL/Fl_Window.H>
+#include <FL/Fl_Wizard.H>
+#include <FL/Fl_XBM_Image.H>
+#include <FL/Fl_XPM_Image.H>
+
+#endif /* ! _FULL_FL_H */
+
View
20 gui/genDocs.pl
@@ -1,20 +0,0 @@
-#!/usr/bin/perl
-
-use strict;
-use warnings;
-
-open FIN, "../docs/reference.json" or die $!;
-open FOUT, ">fdocs.py" or die $!;
-print FOUT <<END;
-""" Auto-generated file. Do not modify. """
-
-docs = """
-END
-while (<FIN>) {
- print FOUT;
-}
-print FOUT <<END;
-"""
-END
-close FOUT or die $!;
-close FIN or die $!;
View
50 gui/genTools.pl
@@ -1,50 +0,0 @@
-#!/usr/bin/perl
-
-use File::Basename qw/dirname/;
-
-use strict;
-use warnings;
-
-sub ptup;
-
-# TODO support aliases
-
-open FOUT, ">ftools.py" or die $!;
-
-print FOUT <<END;
-""" Auto-generated file. Do not modify. """
-
-def addFTools(add_category):
-END
-
-my $ed = dirname $0;
-my $pdir = $ARGV[0] || "$ed/../evanlib/EVAN";
-my @hsfiles = glob "$pdir/*.lhs";
-for my $f (@hsfiles) {
- $f =~ /\/(\w+)\.lhs/;
- print FOUT " add_category('$1', [\n";
- open FIN, $f or die $!;
- my $hs = "";
- $hs .= $_ while <FIN>;
- close FIN or die $!;
- while ($hs =~ /^>? *_([A-Z]\w*) *:: *(.*=> *)?(.*?) *-> (.*?) *-> *(.*)/mg) {
- my ($name, $paramstr, $argstr, $restr) = ($1, $3, $4, $5);
- my @params = ptup $paramstr;
- my @args = ptup $argstr;
- my @res = ptup $restr;
- my ($pl, $al, $rl) = ($#params+1, $#args+1, $#res+1);
- my $pstr = join ",", map {"'$_'"} @params;
- print FOUT " ('$name', [$pstr], $al, $rl),\n";
- }
- print FOUT " ])\n";
-}
-
-sub ptup {
- my $as = shift;
- $as =~ s/^\( *//;
- $as =~ s/ *\)$//;
- my @args = split /,/, $as;
- return @args;
-}
-
-close FOUT;
View
24 gui/ids.py
@@ -1,24 +0,0 @@
-""" Id registry. See README for notes. """
-
-#!START local
-
-#!END local
-
-class Registry:
- def __init__(self, n=1):
- self.n = n
-
- def next(self):
- n = self.n
- self.n = self.n+1
- return str(n)
-
- def named(self, name):
- return "_" + name + "_reg_" + self.next()
-
- def as_object(self):
- return {
- "kind": 'registry',
- "n": self.n
- }
-
View
5 gui/json.cc
@@ -0,0 +1,5 @@
+#include "json.hh"
+
+#include <map>
+using namespace std;
+
View
15 gui/json.hh
@@ -0,0 +1,15 @@
+#ifndef JSON_HH
+#define JSON_HH
+
+namespace json {
+
+class Schema {
+public:
+protected:
+private:
+};
+
+}
+
+#endif /* !JSON_HH */
+
View
84 gui/main.cc
@@ -0,0 +1,84 @@
+#include <iostream>
+using namespace std;
+
+#include "canvas.hh"
+#include "program.hh"
+
+#include "fltk.hh"
+
+#define TITLE "EVAN"
+#define MENU_HEIGHT 28
+#define TOOL_HEIGHT 30
+#define TB_WIDTH 100
+
+/* Callbacks */
+void Cb_About (Fl_Widget *, void *);
+void Cb_Quit (Fl_Widget *, void *);
+
+/* Singleton GUI Components */
+Fl_Double_Window *main_window;
+Fl_Menu_Bar *menu_bar;
+Fl_Pack *tool_bar;
+Canvas *canvas;
+Fl_Button *run_button, *comment_button;
+
+Fl_Window *about_window;
+
+Fl_Menu_Item menu_items[] = {
+ { "&File", 0, 0, 0, FL_SUBMENU },
+ { "&New", FL_COMMAND + 'n', 0, 0},
+ { "&Open", FL_COMMAND + 'o', 0, 0},
+ { "&Save", FL_COMMAND + 's', 0, 0},
+ { "Save &As", 0, 0, 0},
+ { "E&xit", FL_COMMAND + 'q', (Fl_Callback *)Cb_Quit, 0 },
+ { 0 },
+
+ { "&Help", 0, 0, 0, FL_SUBMENU },
+ { "&About", 0, (Fl_Callback *)Cb_About, 0},
+ { 0 },
+
+
+ { 0 }
+};
+
+void MkGui() {
+ int wh = Fl::h(), ww = Fl::w();
+ main_window = new Fl_Double_Window(ww * .8, wh * .8, TITLE);
+ menu_bar = new Fl_Menu_Bar(0, 0, main_window->w(), MENU_HEIGHT);
+ menu_bar->copy(menu_items);
+
+ tool_bar = new Fl_Pack(0, MENU_HEIGHT+1, TB_WIDTH, 0);
+ run_button = new Fl_Button(0, 0, 0, TOOL_HEIGHT, "Run");
+ comment_button = new Fl_Button(0, 0, 0, TOOL_HEIGHT, "Comment");
+ tool_bar->end();
+
+ canvas = new Canvas(TB_WIDTH+1, MENU_HEIGHT+1,
+ main_window->w()-TB_WIDTH-2,
+ main_window->h()-MENU_HEIGHT-2);
+
+ main_window->end();
+
+ about_window = new Fl_Window(ww * .2, wh * .2, "About EVAN");
+ Fl_Text_Display *td = new Fl_Text_Display(0, 0, about_window->w(), about_window->h());
+ Fl_Text_Buffer *ab = new Fl_Text_Buffer();
+ ab->text("EVAN v0.1");
+ td->buffer(ab);
+ about_window->end();
+}
+
+void Cb_Quit(Fl_Widget *, void *) {
+ delete main_window;
+ exit(0);
+}
+
+void Cb_About(Fl_Widget *, void *) {
+ about_window->show();
+}
+
+int main(int argc, char *argv[]) {
+ Fl::scheme("plastic");
+ MkGui();
+ main_window->show();
+ return Fl::run();
+}
+
View
14 gui/program.cc
@@ -0,0 +1,14 @@
+#include "program.hh"
+
+#include <vector>
+using namespace std;
+
+Program *Program::sample() {
+ Program *p = new Program();
+ return p;
+}
+
+const char *Program::Name() {
+ return filename;
+}
+
View
44 gui/program.hh
@@ -0,0 +1,44 @@
+#ifndef PROGRAM_HH
+#define PROGRAM_HH
+
+#include <string>
+#include <vector>
+
+struct Position {
+ int x, y;
+};
+
+class Comment {
+public:
+ Comment(std::string text, Position pos) : text(text), pos(pos) {};
+ std::string text;
+ Position pos;
+};
+
+struct Block {
+ Position pos;
+};
+
+struct Loop {
+ Position ul;
+ Position lr;
+};
+
+class Program {
+public:
+ const char *Name();
+
+ static Program *sample();
+
+ std::vector<Comment> comments;
+ std::vector<Block> blocks;
+ std::vector<Loop> loops;
+protected:
+ char *filename;
+private:
+};
+
+Program *sample_program();
+
+#endif /* !PROGRAM_HH */
+
View
202 gui/program.py
@@ -1,202 +0,0 @@
-""" Program data structures. See README for notes. """
-
-import json
-
-#!START local
-from ids import *
-#!END local
-
-# The distance to shift when adding a block
-POS_SHIFT = 0, 60
-
-last = 100, 0
-
-REGISTRY = "registry"
-COMMENT = "comment"
-PIPE = "pipe"
-BLOCK = "block"
-
-class Json:
- def as_json(self):
- return json.dumps(self.as_object(), indent=2)
-
-class Graphical:
- """ The graphical representation of an object. This class doesn't actually
- interact with a canvas; it simply makes doing so in an efficient way
- possible. """
-
- def init_pos(self):
- global last
- pos = (last[0] + POS_SHIFT[0], last[1] + POS_SHIFT[1])
- last = pos
- self._pos = pos
- self.ids = []
-
- def pos(self):
- return self._pos
-
- def move(self, dx, dy):
- """ Move this element by the specified amount. """
-
- self._pos = ((self._pos[0]+dx), (self._pos[1]+dy))
-
- def g_as_object(self):
- """ Convert to a json-able object. """
-
- return {"x": self._pos[0], "y": self._pos[1]}
-
- def g_from_object(self, o):
- """ Initialize from a json object. """
- self._pos = o["x"], o["y"]
-
-class Program(Json):
- """ A program consists, in our model, of a set of blocks and pipes. """
-
- def __init__(self):
- """ A program is not initialized blank - there is an input and an
- output block """
-
- Json.__init__(self)
- self.registry = Registry()
- self.objects = {}
-
- def std_init(self):
- self.objects = {
- "Events1": Block("Events", 0, 1),
- "Return1": Block("Return", 1, 0),
- "_comment1": Comment("Hello, world!"),
- }
-
- def add_pipe(self, p):
- """ Add a pseudo-anonymous pipe. """
-
- name = self.registry.named("pipe") # TODO this is a bug
- self.objects[name] = p
- d, i = p.dest
- self.objects[d].inputs[i] = name
-
- def delete(self, name):
- """ Delete the named object. If the object is a block, any adjoining
- pipes will also be deleted. """
-
- if name in self.objects:
- o = self.objects[name]
- if o.kind == BLOCK:
- # delete all associated pipes
- todel = []
- for pn in self.objects:
- p = self.objects[pn]
- if p.kind == PIPE:
- if p.source[0] == name or p.dest[0] == name:
- todel.append(pn)
- for pn in todel:
- del self.objects[pn]
- del self.objects[name]
-
- def as_object(self):
- """ Convert to a json-able object. """
-
- top = {}
- for obj in self.objects:
- top[obj] = self.objects[obj].as_object()
- top["registry"] = self.registry.as_object()
- return top
-
- def from_object(self, top):
- """ Convert from a json object. """
-
- for n in top:
- o = top[n]
- if not 'params' in o:
- o['params'] = []
- if o['kind'] == COMMENT:
- self.objects[n] = Comment(o["text"])
- self.objects[n].g_from_object(o["graphics"])
- if o['kind'] == BLOCK:
- self.objects[n] = Block(o["ident"], o["input-count"], o["output-count"], params=o['params'])
- self.objects[n].inputs = o["inputs"]
- self.objects[n].g_from_object(o["graphics"])
- if o['kind'] == PIPE:
- self.objects[n] = Pipe(o["source"], o["destination"], o["ident"])
- if o['kind'] == REGISTRY:
- self.registry = Registry(o['n'])
-
-class Comment(Json, Graphical):
- """ A comment. """
-
- def __init__(self, text):
- Json.__init__(self)
- Graphical.init_pos(self)
- self.text = text
- self.kind = COMMENT
-
- def as_object(self):
- """ Convert to a json-able object."""
-
- return {
- "kind": COMMENT,
- "graphics": self.g_as_object(),
- "text": self.text
- }
-
-class Block(Json, Graphical):
- """ A block represents a function call. """
-
- def __init__(self, i, ic=0, oc=0, params=[]):
- Json.__init__(self)
- Graphical.init_pos(self)
- self.ident = i
- self.input_count = ic
- self.output_count = oc
- self.params = params
- self.kind = BLOCK
-
- # initialize input array
- self.inputs = [None]*ic
-
- def as_object(self):
- """ Convert to a json-able object. """
-
- return {
- "kind": BLOCK,
- "ident": self.ident,
- "output-count": self.output_count,
- "input-count": self.input_count,
- "params": self.params,
- "inputs": self.inputs,
- "graphics": self.g_as_object(),
- }
-
-class Pipe(Json):
- """ A pipe represents a variable. """
-
- def __init__(self, source, dest, i=None):
- Json.__init__(self)
-
- if i is None:
- i = "_pipe_" + source[0] + "__" + str(source[1])
- self.ident = i
- self.source = source
- self.dest = dest
- self.kind = PIPE
-
- def move(self, dx, dy):
- pass
-
- def as_object(self):
- """ Convert to a json-able object. """
-
- return {
- "kind": PIPE,
- "ident": self.ident,
- "source": self.source,
- "destination": self.dest,
- }
-
-def program_from_json(j):
- """ Create a program object from the JSON string in the given file. """
-
- jo = json.loads(j)
- p = Program()
- p.from_object(jo)
- return p
View
42 gui/results.py
@@ -1,42 +0,0 @@
-# Displaying results for the python+tk frontend. See README for notes.
-
-import json
-import re
-import subprocess
-from tkinter import *
-
-def display_results(rs):
- """ Displays the given results. """
-
- r = json.loads(rs)
- if isinstance(r, str):
- root = Tk()
- root.title('Results')
- root.protocol('WM_DELETE_WINDOW', root.destroy)
-
- resFrame = Frame(root)
- resFrame.pack(side=LEFT, anchor='nw', fill=BOTH, expand=1)
-
- resDisp = Canvas(resFrame, bg='white', bd=2, relief=SUNKEN)
- resDisp.pack(side=LEFT, anchor='nw', fill=BOTH, expand=1)
- resDisp.create_text(20, 20, text=r)
- elif isinstance(r, dict):
- m = r['mime']
- k = r['kind']
- if 'data' in r:
- d = r['data']
- elif 'file' in r:
- fn = r['file']
- #f = open(fn, "rb")
- #d = f.read()
- #f.close()
- subprocess.call(["display", fn])
- else:
- # TODO ERROR
- return
-
- # TODO error
- return
- else:
- print(r)
-
View
86 gui/tools.py
@@ -1,86 +0,0 @@
-""" Tool list. See README for notes. """
-
-from tkinter import *
-from tkinter.simpledialog import *
-import random
-
-#!START local
-from ftools import *
-from ids import *
-from program import *
-#!END local
-
-def newComment(prog, x, y):
- # TODO use the registry
- name = ''.join([random.choice('abcdefghijklmnopqrstuvwxyz') for i in range(12)])
- c = Comment("Hello, world")
- c._pos = (x, y)
- prog.objects[name] = c
-
-class BlockTool:
- def __init__(self, name, p, i, o):
- self.name = name
- self.ins = i
- self.outs = o
- self.params = p
-
- def __call__(self, prog, x, y, root):
- name = ''.join([random.choice('abcdefghijklmnopqrstuvwxyz') for i in range(12)])
- pinf = []
- if len(self.params) > 0:
- pinf = self.prompt(root)
- b = Block(self.name, self.ins, self.outs, params=pinf)
- b._pos = (x, y)
- prog.objects[name] = b
-
- def prompt(self, root):
- pd = ParamDialog(root, self.name, self.params)
- return pd.res
-
-class ParamDialog(Dialog):
-
- def __init__(self, parent, name, ps):
- self.name = name
- self.ps = ps
- self.es = [None]*len(self.ps)
- self.res = [None]*len(self.ps)
- Dialog.__init__(self, parent, "Block Parameters")
-
- def body(self, master):
- i = 0
- for par in self.ps:
- Label(master, text=par).grid(row=i)
- self.es[i] = Entry(master)
- self.es[i].grid(row=i, column=1)
- i += 1
- return self.es[0]
-
- def apply(self):
- i = 0
- for par in self.ps:
- r = self.es[i].get()
- self.res[i] = r
- i += 1
-
-tools = {
- "Cancel": None,
- "Comment": newComment,
-}
-
-categories = {}
-
-def addBlockTool(name, i, o):
- tools[name] = BlockTool(name, i, o)
-
-def addBlockTools(toolInfo):
- for info in toolInfo:
- addBlockTool(info[0], info[1], info[2])
-
-def add_category(name, toolinfo):
- ts = {}
- for info in toolinfo:
- ts[info[0]] = BlockTool(info[0], info[1], info[2], info[3])
- categories[name+">"] = ts
- #addBlockTools(toolinfo)
-
-addFTools(add_category)
View
3  tools/evan2hs/Makefile
@@ -0,0 +1,3 @@
+all:
+ ghc --make evan2hs
+
View
18 tools/evan2hs/evan2hs.hs
@@ -0,0 +1,18 @@
+module Main where
+
+import Text.ParserCombinators.Parsec
+
+skip p = p >> return ()
+
+comment = skip $ char '['
+
+tokEach = skip $ string "each"
+
+statement = tokEach <|> comment
+
+parser = statement
+
+parseFile f c = runParser parser () f c
+
+main = putStrLn . show . parseFile "<stdin>" =<< getContents
+
View
4 tools/json2hs/json2hs.lhs
@@ -1,4 +0,0 @@
-> module Main where
-
-> main = undefined
-
View
71 tools/json2hs/json2hs.py
@@ -1,71 +0,0 @@
-#!/usr/bin/env python3
-
-import json
-import sys
-
-rd = {}
-
-def rid(i):
- """ Represent an EVAN identifier as a valid haskell identifier, returning
- the resulting string. """
-
- return "_"+i
-
-def elem(i, n):
- """ Returns a string representing the haskell lambda expression to retreive
- element i of an n-tuple. """
-
- ps = ['_']*n
- ps[i] = 'x'
- return '(\ (' + ','.join(ps) + ') -> x)'
-
-def render(p, i):
- if i in rd:
- return '', []
- rd[i] = True
- o = p[i]
- r = ""
- deps = [] # the dependency stack
- k = o['kind']
- if k == 'block':
- ident = o['ident']
- if ident == 'Done':
- rs, deps = render(p, o['inputs'][0])
- d = deps.pop()
- rds, ds = render(p, d)
- r = rds + rid(i) + ' = ' + rs + '} ; return ' + rid(o['inputs'][0]) + '} ; '
- deps = ds
- elif ident == 'Each':
- # We don't render the dependency here, we just pass it down to be
- # handled by 'Done'.
- inp = o['inputs'][0]
- deps.append(inp)
- r = "do {" + rid(i) + ' <- ' + rid(inp) + ' ; let {'
- else:
- ds = ""
- r = rid(i) + ' = '
- for inp in o['inputs']:
- d, dep = render(p, inp)
- deps += dep
- ds += d
- r += rid(ident) + ' ('
- r += ','.join([x for x in o['params']]) + ') ('
- r += ','.join(['_'+x for x in o['inputs']]) + ') ; '
- r = ds + r
- elif k == 'pipe':
- src = o['source']
- rp, deps = render(p, src[0])
- r = rp + rid(i) + " = " + elem(src[1], p[src[0]]['output-count']) + ' '
- r += rid(src[0]) + ';'
- return r, deps
-
-prog = json.load(sys.stdin)
-
-imports = ['EVAN', 'EVAN.Primitive', 'EVAN.Math', 'EVAN.Tracks', 'EVAN.Output']
-
-print ("module Main where")
-for imp in imports:
- print ("import "+imp)
-
-p, deps = render(prog, 'Return1')
-print ("main = do { let {" + p + "}; _Return1 }")
View
40 tools/merge.pl
@@ -1,40 +0,0 @@
-#!/usr/bin/perl
-
-use strict;
-use warnings;
-
-use File::Basename qw/dirname/;
-
-# This script is used to combine the various python files that compose the evan
-# executable into a single script that can be copied, standalone (but for
-# evan-compile etc.), to bin/.
-
-sub write_script;
-
-sub write_script {
- my ($fname, $dir) = @_;
- my ($local) = 0;
- my $fh;
- open $fh, "<$fname" or die "$fname: $!";
- while (my $line = <$fh>) {
- chomp $line;
- if ($line =~ /#!START local/) {
- $local = 1;
- next;
- } elsif ($line =~ /#!END local/) {
- $local = 0;
- next;
- }
- if ($local and $line =~ /from ([a-z]+) import \*/) {
- write_script "$dir/$1.py", $dir;
- } else {
- print "$line\n";
- }
-
- }
- print "\n";
- close $fh;
-}
-
-print "usage: $0 script.py > output.py\n" and exit 1 unless $ARGV[0];
-write_script $ARGV[0], dirname $ARGV[0];

No commit comments for this range

Something went wrong with that request. Please try again.