luis пре 7 година
родитељ
комит
b8bfb12f4f

+ 1 - 1
browser/vue-flow/src/components/flow/link.vue

@@ -37,7 +37,7 @@ export default {
       }
       s = Math.max(s, 2)
       const x2 = this.x2 - (this.pointer ? 4 : 15.5)
-      const x1 = this.x1 + 7
+      const x1 = this.x1 + 4
       return `M${x1},${this.y1} C${x1 + s},${this.y1} ${x2 - s},${this.y2} ${x2},${this.y2}`
     }
   }

+ 0 - 1
browser/vue-flow/src/components/flow/manager.vue

@@ -431,7 +431,6 @@ export default {
       this.$flowService[type](param)
     },
     sendDocumentUpdate (nodeData) {
-      console.log('T:', JSON.stringify(this.nodeData, null, ' '))
       this.$flowService.documentUpdate(this.nodeData, this.$route.params.sessId)
     },
     // HELPERS depending on svg ref

+ 57 - 27
browser/vue-flow/src/components/flow/node.vue

@@ -1,4 +1,5 @@
 <template>
+
   <g
     class="flow-node"
     :class="{
@@ -8,6 +9,7 @@
     @mousedown.stop.prevent="$emit('nodePointerDown',$event)"
     @dblclick="$emit('nodeDoubleClick',$event)"
   >
+
     <rect
       class="flow-node__selection"
       stroke-dasharray="7,3"
@@ -16,12 +18,47 @@
       :width="bodyProps.width+8"
       :height="bodyProps.height+8"
     />
+
+    <!--      <circle
+        :r="bodyProps.r+4"
+        stroke-dasharray="7,3"
+        class="flow-node__selection"
+        />-->
+    <svg
+      v-if="nodeStyle.shape == 'thing'"
+      ref="body"
+      viewBox="0 0 100 100"
+      preserveAspectRatio="XMinYMin"
+      class="flow-node__body"
+      :class="{'flow-node__body--dragging':dragging}"
+      v-bind="bodyProps"
+    >
+      <path
+        d="
+      M 0 0
+      l 90 0
+      l 10 50
+      l -10 50
+      l -90 0
+      c 10 -20, 10 -80, 0 -100
+      Z
+      "
+    /></svg>
+    <circle
+      v-else-if="nodeStyle.shape == 'circle'"
+      ref="body"
+      class="flow-node__body"
+      :class="{'flow-node__body--dragging':dragging}"
+      v-bind="bodyProps"
+    />
     <rect
+      v-else
       ref="body"
       class="flow-node__body"
       :class="{'flow-node__body--dragging':dragging}"
       v-bind="bodyProps"
     />
+
     <text
       ref="label"
       class="flow-node__label"
@@ -71,10 +108,19 @@
     </text>
 
   </g>
+
 </template>
 
 <script>
-
+import utils from '@/utils/utils'
+const shapeOpts = {
+  'circle': {
+    textWrap: 'any'
+  },
+  default: {
+    textWrap: 'white-space'
+  }
+}
 export default {
   name: 'FlowNode',
   props: {
@@ -97,24 +143,9 @@ export default {
   },
   computed: {
     labelWrap () {
-      var ret = []
-      const parts = this.label.split(' ', -1)
       let wrapThreshold = 10 // initial wrap threshold
-      parts.forEach(n => {
-        wrapThreshold = Math.max(n.length + 1, wrapThreshold)
-      })
-      ret.push(parts[0])
-      for (let i = 1; i < parts.length; i++) {
-        let ri = ret.length - 1 // last
-        if (ret[ret.length - 1].length + parts[i].length > wrapThreshold) {
-          ret.push(parts[i])
-        } else {
-          // we can add to same
-          ret[ri] += ' ' + parts[i]
-        }
-      }
-
-      return ret
+      const opt = shapeOpts[this.nodeStyle.shape] || shapeOpts.default
+      return utils.textWrap(this.label, wrapThreshold, opt.textWrap)
     },
     labelProps () {
       return {
@@ -126,23 +157,22 @@ export default {
       }
     },
     bodyProps () {
-      let width = this.labelRect.width + 30
+      let width = this.labelRect.width + 46
       let height = Math.max(this.labelRect.height + 20, 60)
-      if (this.nodeStyle.type === 'circle') {
-        height = Math.max(width, height)
-        width = height
+      if (this.nodeStyle.shape === 'circle') {
+        width = height = Math.max(width, height)
       }
+
       const rect = {
         x: -width / 2,
         y: -height / 2,
         width: width,
         height: height,
-        stroke: this.nodeStyle.color,
-        fill: this.nodeStyle.color
+        stroke: this.nodeStyle.color || '#777',
+        fill: this.nodeStyle.color || '#777'
       }
-      if (this.nodeStyle && this.nodeStyle.type === 'circle') {
-        rect.rx = width
-        rect.ry = width
+      if (this.nodeStyle.shape === 'circle') {
+        rect.r = Math.max(width / 2, height / 2)
       }
       return rect
     },

+ 15 - 7
browser/vue-flow/src/components/main.vue

@@ -133,10 +133,11 @@ export default {
   data () {
     return {
       registry: {
+        // Fixed default stuff
         'Input': {
           group: 'Generic',
           output: 'any',
-          style: { color: '#686', textColor: '#fff', type: 'circle' },
+          style: { color: '#686', textColor: '#fff', shape: 'circle' },
           props: {} // should be sent in the node
         },
         'Variable': {
@@ -148,13 +149,23 @@ export default {
         'Const': {
           group: 'Generic',
           output: 'any',
-          style: { color: '#777', textColor: '#333' },
+          style: {
+            color: '#777',
+            textColor: '#333',
+            shape: 'circle'
+          },
           props: {value: ''}
         },
+        'Test': {
+          group: 'Generic',
+          output: 'any',
+          style: {
+            shape: 'thing'
+          }
+        },
 
         'MatMul': { group: 'Machine learning', inputs: [ '[]float32', '[]float32' ], output: '[]float32', style: { color: '#a44', textColor: 'white' } },
-        // 'Input': { group: 'Machine learning', inputs: [], output: '[]float32', style: { 'color': '#686', 'textColor': '#fff' } },
-        'Activator': { group: 'Machine learning', inputs: [ '[]float32' ], output: '[]float32', style: { color: '#a44', textColor: 'white', type: 'circle' } },
+        'Activator': { group: 'Machine learning', inputs: [ '[]float32' ], output: '[]float32', style: { color: '#a44', textColor: 'white', shape: 'circle' } },
 
         'test': { group: 'Text', inputs: [ '[]float32', 'string' ], output: 'string', style: {'color': '#a93'} },
         'reverse': { group: 'Text', inputs: [ 'string' ], output: 'string', style: {'color': '#a93'} },
@@ -182,12 +193,9 @@ export default {
         if (!val === null && !oldVal) { return }
         if (!val) {
           this.$refs.flowManager.sendDocumentUpdate()
-          // this.sendDocumentUpdate()
           return
         }
         this.$refs.flowManager.sendFlowEvent('nodeUpdate', [this.nodeInspectTarget])
-        // this.$emit('sparta', 'testing')
-        // this.sendFlowEvent('nodeUpdate', this.nodeInspectTarget)
       },
       deep: true
     }

+ 33 - 0
browser/vue-flow/src/utils/utils.js

@@ -24,5 +24,38 @@ module.exports = {
     for (var i = 0; i < n; i++) { text += possible.charAt(Math.floor(Math.random() * possible.length)) }
 
     return text
+  },
+  textWrap (text, maxLen, opt) {
+    const ret = []
+    let parts = text.split(' ', -1)
+    switch (opt) {
+      case 'white-space':
+        parts.forEach(n => { maxLen = Math.max(n.length + 1, maxLen) })
+        break
+      case 'any':
+        // Break any word bigger than wrapThreshold
+        let newParts = []
+        parts.forEach(n => {
+          while (n.length > maxLen) {
+            const pre = n.substring(0, maxLen)
+            newParts.push(pre)
+            n = n.substr(maxLen)
+          }
+          newParts.push(n)
+        })
+        parts = newParts
+        break
+    }
+    ret.push(parts[0])
+    for (let i = 1; i < parts.length; i++) {
+      let ri = ret.length - 1 // last
+      if (ret[ret.length - 1].length + parts[i].length > maxLen) {
+        ret.push(parts[i])
+      } else {
+        // we can add to same
+        ret[ri] += ' ' + parts[i]
+      }
+    }
+    return ret
   }
 }

+ 9 - 2
go/src/flow/flow.go

@@ -3,6 +3,7 @@ package flow
 import (
 	"bytes"
 	"encoding/json"
+	"flow/registry"
 	"fmt"
 	"io"
 	"log"
@@ -10,6 +11,12 @@ import (
 	"reflect"
 )
 
+var (
+	globalRegistry = registry.New()
+	// Register a func globally
+	Register = globalRegistry.Register
+)
+
 // Data interface
 type Data = interface{}
 
@@ -23,7 +30,7 @@ type opEntry struct {
 // We could Create a single array of operations
 // refs would only mean id, types would be embed in operation
 type Flow struct {
-	registry *Registry
+	registry *registry.Registry
 
 	consts     []Data
 	data       map[string]Data // Should be named, to fetch later
@@ -53,7 +60,7 @@ func (f *Flow) Err() error {
 }
 
 //SetRegistry use the registry specified
-func (f *Flow) SetRegistry(r *Registry) *Flow {
+func (f *Flow) SetRegistry(r *registry.Registry) *Flow {
 	f.registry = r
 	// chain
 	return f

+ 12 - 12
go/src/flow/flow_test.go

@@ -7,7 +7,7 @@ import (
 
 	"flow"
 
-	. "flow/internal/tests"
+	. "flow/internal/check"
 )
 
 func TestSerialize(t *testing.T) {
@@ -50,7 +50,7 @@ func TestConst(t *testing.T) {
 
 	c := f.Const(1)
 	res := c.Process()
-	CheckEq(t, res, 1)
+	Check(t).Eq(res, 1)
 }
 func TestOp(t *testing.T) {
 	f := flow.New()
@@ -63,10 +63,10 @@ func TestOp(t *testing.T) {
 		[]float32{1, 2, 3},
 	)
 	res, err := f.Run(add)
-	CheckEq(t, err, nil)
+	Check(t).Eq(err, nil)
 
 	test := []float32{3, 6, 9}
-	CheckEq(t, test, res)
+	Check(t).Eq(test, res)
 }
 
 func TestVariable(t *testing.T) {
@@ -74,11 +74,11 @@ func TestVariable(t *testing.T) {
 	v := f.Var("v1", 1)
 
 	res := v.Process()
-	CheckEq(t, res, 1)
+	Check(t).Eq(res, 1)
 
 	v.Set(2)
 	res = v.Process()
-	CheckEq(t, res, 2)
+	Check(t).Eq(res, 2)
 }
 
 func TestCache(t *testing.T) {
@@ -88,7 +88,7 @@ func TestCache(t *testing.T) {
 		var res interface{}
 		for i := 1; i < 5; i++ {
 			res = r.Process()
-			CheckEq(t, res, i)
+			Check(t).Eq(res, i)
 		}
 	}
 	{
@@ -96,9 +96,9 @@ func TestCache(t *testing.T) {
 		inc := f.Op("inc")
 		add := f.Op("add", inc, inc)
 		res = add.Process() // 1+1
-		CheckEq(t, res, 2)
+		Check(t).Eq(res, 2)
 		res = add.Process() // 2+2
-		CheckEq(t, res, 4)
+		Check(t).Eq(res, 4)
 	}
 }
 func TestReference(t *testing.T) {
@@ -107,14 +107,14 @@ func TestReference(t *testing.T) {
 	f.DefOp("1", "vecadd", []float32{1, 2, 3}, []float32{1, 2, 3}) // result 2 4 6
 
 	op := f.Op("vecmul", f.Res("1"), []float32{2, 2, 2}) // 4 8 12
-	CheckErr(t, f.Err())
+	Check(t).Err(f.Err())
 
-	CheckDiff(t, nil, op)
+	Check(t).Diff(nil, op)
 
 	desired := []float32{4, 8, 12}
 
 	res := op.Process()
-	CheckEq(t, res, desired)
+	Check(t).Eq(res, desired)
 }
 
 func TestHandler(t *testing.T) {

+ 2 - 30
go/src/flow/internal/tests/utils.go

@@ -1,13 +1,6 @@
-package tests
+package flow_test
 
-// Some funcs
-import (
-	"fmt"
-	"reflect"
-	"testing"
-
-	vecasm "github.com/gohxs/vec-benchmark/asm"
-)
+import vecasm "github.com/gohxs/vec-benchmark/asm"
 
 func VecMul(a, b []float32) []float32 {
 
@@ -57,24 +50,3 @@ func Min(p ...int) int {
 	}
 	return min
 }
-func CheckErr(t *testing.T, err error) {
-	if err != nil {
-		t.Fatal(err)
-	}
-}
-
-func CheckEq(t *testing.T, a, b interface{}) {
-	msg := fmt.Sprintf("Expect %v got %v", a, b)
-	if !reflect.DeepEqual(a, b) {
-		t.Fatalf("\033[31m[FAIL] %s\033[0m", msg)
-	}
-	t.Logf("\033[32m[PASS]\033[m %s", msg)
-}
-
-func CheckDiff(t *testing.T, a, b interface{}) {
-	msg := fmt.Sprintf("Expect NOT %v got %v", a, b)
-	if reflect.DeepEqual(a, b) {
-		t.Fatalf("\033[31m[FAIL] %s\033[0m", msg)
-	}
-	t.Logf("\033[32m[PASS]\033[m %s", msg)
-}

+ 44 - 0
go/src/flow/internal/check/check.go

@@ -0,0 +1,44 @@
+package check_test
+
+import (
+	"fmt"
+	"reflect"
+	"testing"
+)
+
+//Check return a checker
+func Check(t *testing.T) Checker {
+	return Checker{T: t}
+}
+
+// Checker test checking helper
+type Checker struct {
+	*testing.T
+}
+
+//Err check for error
+func (t Checker) Err(err error) {
+	msg := fmt.Sprintf("Checking for error: %v", err)
+	if err != nil {
+		t.Fatalf("\033[31m[FAIL] %s\033[0m", msg)
+	}
+	t.Logf("\033[32m[PASS]\033[m %s", msg)
+}
+
+//Eq check if equal
+func (t Checker) Eq(a, b interface{}) {
+	msg := fmt.Sprintf("Expect %v got %v", a, b)
+	if !reflect.DeepEqual(a, b) {
+		t.Fatalf("\033[31m[FAIL] %s\033[0m", msg)
+	}
+	t.Logf("\033[32m[PASS]\033[m %s", msg)
+}
+
+//Diff check if different
+func (t Checker) Diff(a, b interface{}) {
+	msg := fmt.Sprintf("Expect NOT %v got %v", a, b)
+	if reflect.DeepEqual(a, b) {
+		t.Fatalf("\033[31m[FAIL] %s\033[0m", msg)
+	}
+	t.Logf("\033[32m[PASS]\033[m %s", msg)
+}

+ 9 - 3
go/src/flow/operation.go

@@ -23,7 +23,8 @@ func newOpCtx() OpCtx {
 func dumbSet(params ...Data) {}
 
 // Operation interface
-type Operation interface {
+type Operation interface { // Id perhaps?
+	Id() string
 	Set(inputs ...Data) // Special var method
 	Process(params ...Data) Data
 }
@@ -39,6 +40,11 @@ type operation struct {
 	process func(ctx OpCtx, params ...Data) Data
 }
 
+// Id returns string Id of the operaton
+func (o *operation) Id() string {
+	return o.id.(string)
+}
+
 // Process operation process wrapper
 func (o *operation) Process(params ...Data) Data {
 	return o.processWithCtx(newOpCtx(), params...)
@@ -116,11 +122,11 @@ func opFunc(f *Flow, id string) *operation {
 
 			}
 			f.trigger("nodeStart", map[string]Data{
-				"id": id,
+				"op": op,
 			})
 			ret := reflect.ValueOf(op.executor).Call(callParam)[0].Interface()
 			f.trigger("nodeFinish", map[string]Data{
-				"id":     id,
+				"op":     op,
 				"result": ret,
 			})
 

+ 0 - 58
go/src/flow/registry.go

@@ -1,58 +0,0 @@
-package flow
-
-import (
-	"fmt"
-	"reflect"
-)
-
-// Global
-var (
-	globalRegistry = NewRegistry()
-	Register       = globalRegistry.Register
-)
-
-// Registry function registry
-type Registry struct {
-	data map[string]interface{}
-}
-
-// NewRegistry creates a new registry
-func NewRegistry() *Registry {
-	return &Registry{map[string]interface{}{}}
-}
-
-//Register should be a func only register
-func (r *Registry) Register(name string, v interface{}) error {
-	fntyp := reflect.TypeOf(v)
-	if fntyp.Kind() != reflect.Func {
-		return ErrNotAFunc
-	}
-	if fntyp.NumOut() == 0 {
-		return ErrOutput
-	}
-
-	r.data[name] = v
-	return nil
-}
-
-// Get an entry
-func (r *Registry) Get(name string, params ...interface{}) (interface{}, error) {
-	v, ok := r.data[name]
-	if !ok {
-		return nil, fmt.Errorf("Entry '%s' not found", name)
-	}
-
-	// We already know this is a function
-	// and that returns 1 or more values
-	vtyp := reflect.TypeOf(v)
-	if vtyp.Out(0).Kind() == reflect.Func {
-		fparam := make([]reflect.Value, len(params))
-		for i := range params {
-			fparam[i] = reflect.ValueOf(params[i])
-		}
-		// Call the func and return the thing
-		v = reflect.ValueOf(v).Call(fparam)[0].Interface()
-	}
-
-	return v, nil
-}

+ 10 - 0
go/src/flow/registry/errors.go

@@ -0,0 +1,10 @@
+package registry
+
+import "errors"
+
+// flow Errors
+var (
+	ErrNotFound = errors.New("Entry not found")
+	ErrNotAFunc = errors.New("Is not a function")
+	ErrOutput   = errors.New("Invalid output")
+)

+ 106 - 0
go/src/flow/registry/registry.go

@@ -0,0 +1,106 @@
+package registry
+
+import (
+	"fmt"
+	"reflect"
+)
+
+// Global
+
+// Description of an entry
+type Description struct {
+	Name     string
+	Category []string
+	Inputs   []string
+	Output   string
+}
+
+// Entry contains a function description params etc
+type Entry struct {
+	fn interface{}
+}
+
+// Registry function registry
+type Registry struct {
+	data map[string]*Entry
+}
+
+// New creates a new registry
+func New() *Registry {
+	return &Registry{map[string]*Entry{}}
+}
+
+//Register should be a func only register
+func (r *Registry) Register(name string, v interface{}) error {
+	fntyp := reflect.TypeOf(v)
+	if fntyp.Kind() != reflect.Func {
+		return ErrNotAFunc
+	}
+	if fntyp.NumOut() == 0 {
+		return ErrOutput
+	}
+
+	r.data[name] = &Entry{fn: v}
+	return nil
+}
+
+// Get an entry
+func (r *Registry) Get(name string, params ...interface{}) (interface{}, error) {
+	e, ok := r.data[name]
+	if !ok {
+		return nil, fmt.Errorf("Entry '%s' not found", name)
+	}
+	v := e.fn
+	// We already know this is a function
+	// and that returns 1 or more values
+	vtyp := reflect.TypeOf(v)
+	if vtyp.Out(0).Kind() == reflect.Func {
+		fparam := make([]reflect.Value, len(params))
+		for i := range params {
+			fparam[i] = reflect.ValueOf(params[i])
+		}
+		// Call the func and return the thing
+		v = reflect.ValueOf(v).Call(fparam)[0].Interface()
+	}
+
+	return v, nil
+}
+
+//Describe named fn
+func (r *Registry) Describe(name string) (*Description, error) {
+	e, ok := r.data[name]
+	if !ok {
+		return nil, fmt.Errorf("Entry '%s' not found", name)
+	}
+	fnTyp := reflect.TypeOf(e.fn)
+	Inputs := []string{}
+
+	nInputs := fnTyp.NumIn()
+	for i := 0; i < nInputs; i++ {
+		Inputs = append(Inputs, fmt.Sprint(fnTyp.In(i)))
+	}
+	Output := fmt.Sprint(fnTyp.Out(0))
+	desc := &Description{
+		Name:     name,
+		Category: []string{"generic"},
+		Inputs:   Inputs,
+		Output:   Output,
+	}
+
+	return desc, nil
+}
+
+// Descriptions Description list
+func (r *Registry) Descriptions() ([]Description, error) {
+	ret := make([]Description, len(r.data))
+	i := 0
+	for k := range r.data {
+		d, err := r.Describe(k)
+		if err != nil {
+			return nil, err
+		}
+		ret[i] = *d
+		i++
+	}
+	return ret, nil
+}

+ 54 - 0
go/src/flow/registry/registry_test.go

@@ -0,0 +1,54 @@
+package registry_test
+
+import (
+	"flow/registry"
+	"testing"
+
+	. "flow/internal/check"
+)
+
+func TestRegistryGet(t *testing.T) {
+	c := Check(t)
+
+	r := registry.New()
+	r.Register("vecadd", dummy1)
+
+	fn, err := r.Get("vecadd")
+
+	c.Err(err)
+	c.Diff(nil, fn)
+
+}
+
+func TestRegistry(t *testing.T) {
+	c := Check(t)
+
+	r := registry.New()
+	r.Register("vecadd", dummy1)
+
+	d, err := r.Describe("vecadd")
+	c.Err(err)
+
+	t.Log(d)
+
+}
+func TestDescriptions(t *testing.T) {
+	c := Check(t)
+
+	r := registry.New()
+	r.Register("vecadd", dummy1)
+	r.Register("vecstr", dummy2)
+
+	d, err := r.Descriptions()
+	c.Err(err)
+
+	t.Log(d)
+
+}
+
+func dummy1([]float32, []float32) []float32 {
+	return []float32{1, 3, 3, 7}
+}
+func dummy2([]float32) string {
+	return ""
+}

+ 6 - 2
go/src/flowx/main.go

@@ -3,6 +3,7 @@ package main
 import (
 	"encoding/json"
 	"flow"
+	"flow/registry"
 	"flowserver"
 	"log"
 
@@ -62,11 +63,14 @@ const jsonRaw = `
 
 func main() {
 	prettylog.Global()
-	doc := flowserver.FlowDocument{[]flowserver.Node{}, []flowserver.Link{}}
+	doc := flowserver.FlowDocument{
+		Nodes: []flowserver.Node{},
+		Links: []flowserver.Link{},
+	}
 	json.Unmarshal([]byte(jsonRaw), &doc)
 	// Handling flow
 	//
-	reg := flow.NewRegistry()
+	reg := registry.New()
 	reg.Register("StrCat", StrCat)
 	reg.Register("StrReverse", StrReverse)