/flux/node.go

https://code.google.com/p/gordon-go/ · Go · 471 lines · 423 code · 40 blank · 8 comment · 102 complexity · c652b68120fe185c166b4f287b1a5471 MD5 · raw file

  1. // Copyright 2014 Gordon Klaus. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package main
  5. import (
  6. "code.google.com/p/gordon-go/go/types"
  7. . "code.google.com/p/gordon-go/gui"
  8. "go/token"
  9. "math"
  10. "strconv"
  11. "strings"
  12. "time"
  13. )
  14. type node interface {
  15. View
  16. Mouser
  17. block() *block
  18. setBlock(b *block)
  19. inputs() []*port
  20. outputs() []*port
  21. inConns() []*connection
  22. outConns() []*connection
  23. }
  24. type nodeBase struct {
  25. *ViewBase
  26. self node
  27. AggregateMouser
  28. blk *block
  29. pkg *pkgText
  30. text *Text
  31. ins []*port
  32. outs []*port
  33. godefer string
  34. godeferText *Text
  35. typ *typeView
  36. focused bool
  37. gap float64
  38. }
  39. func newNodeBase(self node) *nodeBase {
  40. return newGoDeferNodeBase(self, "")
  41. }
  42. func newGoDeferNodeBase(self node, godefer string) *nodeBase {
  43. n := &nodeBase{self: self, godefer: godefer}
  44. n.ViewBase = NewView(n)
  45. n.AggregateMouser = AggregateMouser{NewClickFocuser(self), NewMover(self)}
  46. n.pkg = newPkgText()
  47. n.Add(n.pkg)
  48. n.text = NewText("")
  49. n.text.SetBackgroundColor(noColor)
  50. n.text.TextChanged = func(string) { n.reform() }
  51. n.Add(n.text)
  52. n.godeferText = NewText(godefer)
  53. n.godeferText.SetBackgroundColor(noColor)
  54. n.godeferText.SetTextColor(color(special{}, true, false))
  55. n.Add(n.godeferText)
  56. n.ViewBase.Self = self
  57. return n
  58. }
  59. func (n *nodeBase) newInput(v *types.Var) *port {
  60. p := newInput(n.self, v)
  61. n.Add(p)
  62. n.ins = append(n.ins, p)
  63. n.reform()
  64. return p
  65. }
  66. func (n *nodeBase) newOutput(v *types.Var) *port {
  67. p := newOutput(n.self, v)
  68. if n.godefer == "" || v.Type == seqType {
  69. n.Add(p)
  70. n.outs = append(n.outs, p)
  71. n.reform()
  72. }
  73. return p
  74. }
  75. func (n *nodeBase) addSeqPorts() {
  76. n.newInput(newVar("seq", seqType))
  77. n.newOutput(newVar("seq", seqType))
  78. n.reform()
  79. }
  80. func (n *nodeBase) removePortBase(p *port) { // intentionally named to not implement interface{removePort(*port)}
  81. for _, c := range p.conns {
  82. c.blk.removeConn(c)
  83. }
  84. ports := &n.ins
  85. if p.out {
  86. ports = &n.outs
  87. }
  88. for i, p2 := range *ports {
  89. if p2 == p {
  90. *ports = append((*ports)[:i], (*ports)[i+1:]...)
  91. n.Remove(p)
  92. n.reform()
  93. if i > 0 && (*ports)[i-1].obj.Type != seqType { // assumes sequencing port, if present, is at index 0
  94. i--
  95. }
  96. if i < len(*ports) {
  97. SetKeyFocus((*ports)[i])
  98. } else {
  99. SetKeyFocus(n.self)
  100. }
  101. break
  102. }
  103. }
  104. }
  105. func (n *nodeBase) reform() {
  106. if n.godefer != "" {
  107. n.godeferText.SetText(n.godefer)
  108. }
  109. x := -(Width(n.godeferText) + Width(n.pkg) + Width(n.text)) / 2
  110. if n.typ != nil {
  111. x -= Width(n.typ) / 2
  112. }
  113. n.godeferText.Move(Pt(x, -Height(n.godeferText)/2))
  114. x += Width(n.godeferText)
  115. n.pkg.Move(Pt(x, -Height(n.pkg)/2))
  116. x += Width(n.pkg)
  117. n.text.Move(Pt(x, -Height(n.text)/2))
  118. if n.typ != nil {
  119. x += Width(n.text)
  120. n.typ.Move(Pt(x, -Height(n.typ)/2))
  121. }
  122. if n.text.Text() != "" {
  123. n.gap = math.Max(math.Max(Height(n.godeferText), Height(n.pkg)), Height(n.text)) / 2
  124. }
  125. if n.typ != nil {
  126. n.gap = math.Max(n.gap, Height(n.typ)/2)
  127. }
  128. ins, outs := ins(n), outs(n)
  129. numIn := float64(len(ins))
  130. numOut := float64(len(outs))
  131. rx, ry := (math.Max(numIn, numOut)+1)*portSize/2, 1.0*portSize
  132. rect := ZR
  133. for i, p := range ins {
  134. x := portSize * (float64(i) - (numIn-1)/2)
  135. y := n.gap + ry*math.Sqrt(rx*rx-x*x)/rx
  136. if numIn > 1 {
  137. y += 8
  138. }
  139. MoveCenter(p, Pt(x, y))
  140. rect = rect.Union(RectInParent(p))
  141. }
  142. for i, p := range outs {
  143. x := portSize * (float64(i) - (numOut-1)/2)
  144. y := -n.gap - ry*math.Sqrt(rx*rx-x*x)/rx
  145. if numOut > 1 {
  146. y -= 8
  147. }
  148. MoveCenter(p, Pt(x, y))
  149. rect = rect.Union(RectInParent(p))
  150. }
  151. if p := seqIn(n); p != nil {
  152. MoveCenter(p, Pt(0, n.gap))
  153. }
  154. if p := seqOut(n); p != nil {
  155. MoveCenter(p, Pt(0, -n.gap))
  156. }
  157. if _, ok := n.self.(*portsNode); ok {
  158. // portsNode rect must have an edge at y==0 or arrangement will diverge
  159. n.SetRect(rect)
  160. } else {
  161. ResizeToFit(n, 0)
  162. }
  163. rearrange(n.blk)
  164. }
  165. func (n nodeBase) block() *block { return n.blk }
  166. func (n *nodeBase) setBlock(b *block) { n.blk = b }
  167. func (n nodeBase) inputs() []*port { return n.ins }
  168. func (n nodeBase) outputs() []*port { return n.outs }
  169. func (n nodeBase) inConns() (conns []*connection) {
  170. for _, p := range n.inputs() {
  171. for _, c := range p.conns {
  172. conns = append(conns, c)
  173. }
  174. }
  175. return
  176. }
  177. func (n nodeBase) outConns() (conns []*connection) {
  178. for _, p := range n.outputs() {
  179. for _, c := range p.conns {
  180. conns = append(conns, c)
  181. }
  182. }
  183. return
  184. }
  185. func (n *nodeBase) Move(p Point) {
  186. n.ViewBase.Move(p)
  187. nodeMoved(n.self)
  188. }
  189. func nodeMoved(n node) {
  190. for _, c := range append(n.inConns(), n.outConns()...) {
  191. c.reform()
  192. }
  193. if KeyFocus(n) == n {
  194. // TODO: not ZP for if and select
  195. panTo(n, ZP)
  196. }
  197. }
  198. func (n *nodeBase) TookKeyFocus() {
  199. n.focused = true
  200. panTo(n, ZP)
  201. }
  202. func (n *nodeBase) LostKeyFocus() {
  203. n.focused = false
  204. }
  205. func (n *nodeBase) Paint() {
  206. SetColor(lineColor)
  207. SetLineWidth(3)
  208. for _, p := range append(ins(n), outs(n)...) {
  209. pt := CenterInParent(p)
  210. dy := n.gap
  211. if p.out {
  212. dy = -dy
  213. }
  214. y := (pt.Y-dy)/2 + dy
  215. DrawBezier(Pt(0, dy), Pt(0, y), Pt(pt.X, y), pt)
  216. }
  217. if n.focused && (n.text.Text() != "" || n.typ != nil) {
  218. r := RectInParent(n.godeferText).Union(RectInParent(n.pkg)).Union(RectInParent(n.text))
  219. if n.typ != nil {
  220. r = r.Union(RectInParent(n.typ))
  221. }
  222. DrawRect(r)
  223. }
  224. }
  225. type pkgText struct {
  226. *ViewBase
  227. text *Text
  228. pkg *types.Package
  229. leave chan bool
  230. }
  231. func newPkgText() *pkgText {
  232. t := &pkgText{}
  233. t.ViewBase = NewView(t)
  234. t.text = NewText("")
  235. t.text.SetTextColor(color(&pkgObject{}, true, false))
  236. t.text.SetBackgroundColor(noColor)
  237. t.Add(t.text)
  238. t.leave = make(chan bool, 1)
  239. return t
  240. }
  241. func (t *pkgText) setPkg(p *types.Package) {
  242. t.pkg = p
  243. t.setText(p.Name)
  244. }
  245. func (t *pkgText) setText(s string) {
  246. t.text.SetText(s + ".")
  247. dx := Width(t) - Width(t.text)
  248. t.Move(Pos(t).Add(Pt(dx, 0)))
  249. Resize(t, Size(t.text))
  250. }
  251. func (t *pkgText) Mouse(m MouseEvent) {
  252. if m.Enter {
  253. go func() {
  254. select {
  255. case <-time.After(time.Second):
  256. Do(t, func() { t.setText(t.pkg.Path) })
  257. <-t.leave
  258. Do(t, func() { t.setText(t.pkg.Name) })
  259. case <-t.leave:
  260. }
  261. }()
  262. } else if m.Leave {
  263. t.leave <- true
  264. } else {
  265. MouseParent(t, m)
  266. }
  267. }
  268. var seqType = struct{ types.Type }{}
  269. func seqIn(n node) *port {
  270. for _, in := range n.inputs() {
  271. if in.obj.Type == seqType {
  272. return in
  273. }
  274. }
  275. return nil
  276. }
  277. func seqOut(n node) *port {
  278. for _, out := range n.outputs() {
  279. if out.obj.Type == seqType {
  280. return out
  281. }
  282. }
  283. return nil
  284. }
  285. func ins(n node) (p []*port) {
  286. for _, in := range n.inputs() {
  287. if in.obj.Type != seqType {
  288. p = append(p, in)
  289. }
  290. }
  291. return
  292. }
  293. func outs(n node) (p []*port) {
  294. for _, out := range n.outputs() {
  295. if out.obj.Type != seqType {
  296. p = append(p, out)
  297. }
  298. }
  299. return
  300. }
  301. type basicLiteralNode struct {
  302. *nodeBase
  303. kind token.Token
  304. }
  305. func newBasicLiteralNode(kind token.Token) *basicLiteralNode {
  306. n := &basicLiteralNode{kind: kind}
  307. n.nodeBase = newNodeBase(n)
  308. out := n.newOutput(nil)
  309. n.addSeqPorts()
  310. switch kind {
  311. case token.INT, token.FLOAT:
  312. if kind == token.INT {
  313. out.setType(types.Typ[types.UntypedInt])
  314. } else {
  315. out.setType(types.Typ[types.UntypedFloat])
  316. }
  317. n.text.Validate = func(s *string) bool {
  318. *s = strings.TrimLeft(*s, "0")
  319. if *s == "" || *s == "-" {
  320. *s = "0"
  321. }
  322. if (*s)[0] == '.' {
  323. *s = "0" + *s
  324. }
  325. if l := len(*s); (*s)[l-1] == '-' {
  326. if (*s)[0] == '-' {
  327. *s = (*s)[1 : l-1]
  328. } else {
  329. *s = "-" + (*s)[:l-1]
  330. }
  331. }
  332. if _, err := strconv.ParseInt(*s, 10, 64); err == nil {
  333. n.kind = token.INT
  334. out.setType(types.Typ[types.UntypedInt])
  335. } else {
  336. if _, err := strconv.ParseFloat(*s, 4096); err == nil {
  337. n.kind = token.FLOAT
  338. out.setType(types.Typ[types.UntypedFloat])
  339. } else {
  340. return false
  341. }
  342. }
  343. return true
  344. }
  345. case token.IMAG:
  346. // TODO
  347. case token.STRING:
  348. out.setType(types.Typ[types.UntypedString])
  349. case token.CHAR:
  350. out.setType(types.Typ[types.UntypedRune])
  351. n.text.Validate = func(s *string) bool {
  352. if *s == "" {
  353. return false
  354. }
  355. *s = (*s)[len(*s)-1:]
  356. return true
  357. }
  358. }
  359. n.text.Accept = func(string) { SetKeyFocus(n) }
  360. return n
  361. }
  362. func (n *basicLiteralNode) KeyPress(k KeyEvent) {
  363. switch k.Key {
  364. case KeyEnter:
  365. s := n.text.Text()
  366. t := n.outs[0].obj.Type
  367. n.text.Reject = func() {
  368. n.text.SetText(s)
  369. n.outs[0].setType(t)
  370. SetKeyFocus(n)
  371. }
  372. SetKeyFocus(n.text)
  373. default:
  374. n.nodeBase.KeyPress(k)
  375. }
  376. }
  377. type compositeLiteralNode struct {
  378. *nodeBase
  379. }
  380. func newCompositeLiteralNode(currentPkg *types.Package) *compositeLiteralNode {
  381. n := &compositeLiteralNode{}
  382. n.nodeBase = newNodeBase(n)
  383. out := n.newOutput(nil)
  384. n.addSeqPorts()
  385. n.typ = newTypeView(&out.obj.Type, currentPkg)
  386. n.typ.mode = compositeOrPtrType
  387. n.Add(n.typ)
  388. return n
  389. }
  390. func (n *compositeLiteralNode) editType() {
  391. n.typ.editType(func() {
  392. if t := *n.typ.typ; t != nil {
  393. n.setType(t)
  394. } else {
  395. n.blk.removeNode(n)
  396. SetKeyFocus(n.blk)
  397. }
  398. })
  399. }
  400. func (n *compositeLiteralNode) setType(t types.Type) {
  401. n.typ.setType(t)
  402. n.outs[0].setType(t)
  403. n.blk.func_().addPkgRef(t)
  404. t, _ = indirect(t)
  405. local := true
  406. if nt, ok := t.(*types.Named); ok {
  407. t = nt.UnderlyingT
  408. local = nt.Obj.Pkg == n.blk.func_().pkg()
  409. }
  410. switch t := t.(type) {
  411. case *types.Struct:
  412. for _, f := range t.Fields {
  413. if local || f.IsExported() {
  414. n.newInput(f)
  415. }
  416. }
  417. case *types.Slice:
  418. // TODO: variable number of inputs? (same can be achieved using append.) variable number of index/value input pairs?
  419. case *types.Map:
  420. // TODO: variable number of key/value input pairs?
  421. }
  422. MoveCenter(n.typ, ZP)
  423. n.gap = Height(n.typ) / 2
  424. n.reform()
  425. SetKeyFocus(n)
  426. }
  427. func (n *compositeLiteralNode) removePort(p *port) {
  428. if p.bad {
  429. n.removePortBase(p)
  430. }
  431. }