Beispiel #1
0
func newTransition(x, y float64) *transition {
	return &transition{
		Rect: geometry.NewRect(x-TransitionWidth/2, y-TransitionHeight/2,
			TransitionWidth, TransitionHeight),
		id: util.GenUUID(),
	}
}
Beispiel #2
0
func (g *group) updateBounds(move bool) {
	if g.model == nil {
		return
	}
	var w, h float64
	x0, y0, x1, y1 := detectBounds(g.model.Items())
	if !g.folded {
		w, h = (x1-x0)+2*GroupMargin, (y1-y0)+2*GroupMargin
		k := math.Ceil(w / GridDefaultGap)
		w = k * GridDefaultGap
		k = math.Ceil(h / GridDefaultGap)
		h = k * GridDefaultGap
	}
	fw, fh := g.getFoldedSize()
	if w < fw {
		w = fw
	}
	if h < fh {
		h = fh
	}
	if move {
		x, y := x0-GroupMargin, y0-GroupMargin
		g.Rect = geometry.NewRect(x, y, w, h)
	} else {
		g.Rect.Resize(w, h)
	}
}
Beispiel #3
0
func newControlPoint(x float64, y float64, modified bool) *controlPoint {
	return &controlPoint{
		geometry.NewRect(
			x-ControlPointWidth/2,
			y-ControlPointHeight/2,
			ControlPointWidth, ControlPointHeight),
		modified,
	}
}
Beispiel #4
0
func constructTransition(model *Transition) *transition {
	t := &transition{
		Rect:       geometry.NewRect(model.X, model.Y, TransitionWidth, TransitionHeight),
		id:         model.Id,
		horizontal: model.Horizontal,
		label:      model.Label,
		kind:       model.Kind,
	}
	if t.horizontal {
		t.Rect.Rotate(t.horizontal)
	}
	return t
}
Beispiel #5
0
func (g *group) Copy() item {
	gNew := newGroup()
	/*
		items := make(map[item]bool, len(g.model.places)+
			len(g.model.transitions)+len(g.model.groups))
		for _, p := range g.model.places {
			items[p] = true
		}
		for _, t := range g.model.transitions {
			items[t] = true
		}
		for _, g := range g.model.groups {
			items[g] = true
		}
		clonemap := group.model.cloneItems(items)
	*/
	gNew.Rect = geometry.NewRect(g.X(), g.Y(), 0, 0)
	gNew.model = g.model
	gNew.label = g.label
	gNew.parent = g.parent
	gNew.folded = g.folded
	return item(gNew)
}
Beispiel #6
0
func (c *Ctrl) handleEvents() {
	go func() {
		var x0, y0 float64
		var focused *vertex
		for {
			switch ev := (<-c.events).(type) {
			case *stopEvent:
				return
			case *keyEvent:
				if c.Layers.Length < 1 {
					continue
				}
				c.handleKeyEvent(ev)
			case *mouseEvent:
				if c.Layers.Length < 1 {
					continue
				}
				x, y := c.WindowCoordsToRelativeGlobal(ev.x, ev.y)

				switch ev.kind {
				case EventMouseHover:
					active := c.Active()
					if active == nil {
						continue
					}
					v, found := active.findV(x, y)
					var text string
					if found {
						text = dioid.Gd{G: v.G(), D: v.D()}.String()
					}
					if text != c.VertexText {
						c.VertexText = text
						qml.Changed(c, &c.VertexText)
					}
				case EventMousePress:
					active := c.Active()
					if active == nil {
						continue
					}
					x0, y0 = x, y
					v, found := active.findV(x, y)

					if c.ModifierKeyShift && !found {
						active.deselectAll()
						v := active.placeV(x, y)
						active.selectV(v)
						focused = v
					} else if !found {
						if !c.ModifierKeyControl {
							active.deselectAll()
							active.update()
						}
						active.util.min = &geometry.Point{x, y}
					} else {
						focused = v
						x0, y0 = v.X, v.Y
						if len(active.selected) > 1 {
							if v.isSelected() && c.ModifierKeyControl {
								active.deselectV(v)
							} else if c.ModifierKeyControl {
								active.selectV(v)
							} else if !v.isSelected() {
								active.deselectAll()
								active.selectV(v)
							}
						} else if !c.ModifierKeyControl {
							active.deselectAll()
							active.selectV(v)
						} else {
							active.selectV(v)
						}
						active.update()
					}
				case EventMouseMove:
					active := c.Active()
					if active == nil {
						continue
					}
					dx, dy := x-x0, y-y0
					x0, y0 = x, y

					if focused != nil {
						active.util.kind = UtilNone
						active.util.max = nil
						//active.placeV(x, y)
						for v := range active.selected {
							v.shift(dx, dy)
						}

						active.update()
					} else {
						active.util.kind = UtilRect
						active.util.max = &geometry.Point{x, y}
						dx := active.util.max.X - active.util.min.X
						dy := active.util.max.Y - active.util.min.Y
						var rect *geometry.Rect
						if dx == 0 || dy == 0 {
							continue
						}
						w, h := math.Abs(dx), math.Abs(dy)
						if dx < 0 && dy < 0 {
							rect = geometry.NewRect(
								active.util.max.X,
								active.util.max.Y,
								w, h,
							)
						} else if dx < 0 /* && dy > 0 */ {
							rect = geometry.NewRect(
								active.util.max.X,
								active.util.max.Y-h,
								w, h,
							)
						} else if dx > 0 && dy < 0 {
							rect = geometry.NewRect(
								active.util.max.X-w,
								active.util.max.Y,
								w, h,
							)
						} else /* dx > 0 && dy > 0 */ {
							rect = geometry.NewRect(
								active.util.min.X,
								active.util.min.Y,
								w, h,
							)
						}
						for _, v := range active.defined {
							if v.bound().Intersect(rect) {
								active.selectV(v)
							} else {
								active.deselectV(v)
							}
						}
						for _, v := range active.temporary {
							if v.bound().Intersect(rect) {
								active.selectV(v)
							} else {
								active.deselectV(v)
							}
						}
						active.update()
					}

				case EventMouseRelease:
					active := c.Active()
					if active == nil {
						continue
					}
					for v := range active.selected {
						v.align()
					}
					focused = nil
					active.util.kind = UtilNone
					active.update()
				}
			default:
				log.Println("Event not supported")
			}
		}
	}()
}
Beispiel #7
0
func (v *vertex) bound() *geometry.Rect {
	return geometry.NewRect(v.X-PointRadius, v.Y-PointRadius, 2*PointRadius, 2*PointRadius)
}
Beispiel #8
0
func (tg *teg) Construct(model *Teg) {
	tg.id = model.Id
	submodels := make(map[string]*teg, len(model.Groups))
	madePlaces := make(map[string]*place, 256)
	for _, g := range model.Groups {
		gNew := newGroup()
		gNew.id = g.Id
		gNew.label = g.Label
		gNew.folded = g.Folded
		gNew.parent = tg

		sub, ok := submodels[g.Model.Id]
		if !ok {
			sub = newTeg()
			sub.Construct(g.Model)
			sub.parent = tg
			submodels[g.Model.Id] = sub
		}

		gNew.model = sub
		gNew.Rect = geometry.NewRect(g.X, g.Y, 0, 0)
		for _, t := range g.Inputs {
			tNew := constructTransition(t)
			proxId, ok := g.Iostate[t.Id]
			if !ok {
				panic(errors.New("group constructing: iostate broken"))
			}
			tNew.group = gNew
			tNew.proxy = gNew.model.findById(proxId).(*transition)
			tNew.parent = tg
			for _, p := range t.In {
				pNew, ok := madePlaces[p.Id]
				if !ok {
					pNew = constructPlace(p)
					pNew.parent = tg
					madePlaces[p.Id] = pNew
					tg.places = append(tg.places, pNew)
				}
				pNew.out = tNew
				tNew.in = append(tNew.in, pNew)
				if p.OutControl != nil {
					pNew.outControl = newControlPoint(p.OutControl.X, p.OutControl.Y, p.OutControl.Modified)
				}
				pNew.refineControls()
			}
			for _, p := range t.Out {
				pInner := gNew.model.findById(p.Id).(*place)
				tNew.out = append(tNew.out, pInner)
			}
			tNew.refineSize()
			gNew.inputs = append(gNew.inputs, tNew)
		}
		for _, t := range g.Outputs {
			tNew := constructTransition(t)
			proxId := g.Iostate[t.Id]
			tNew.group = gNew
			tNew.proxy = gNew.model.findById(proxId).(*transition)
			tNew.parent = tg
			for _, p := range t.Out {
				pNew, ok := madePlaces[p.Id]
				if !ok {
					pNew = constructPlace(p)
					pNew.parent = tg
					madePlaces[p.Id] = pNew
					tg.places = append(tg.places, pNew)
				}
				pNew.in = tNew
				tNew.out = append(tNew.out, pNew)
				if p.InControl != nil {
					pNew.inControl = newControlPoint(p.InControl.X, p.InControl.Y, p.InControl.Modified)
				}
				pNew.refineControls()
			}
			for _, p := range t.In {
				pInner := gNew.model.findById(p.Id).(*place)
				tNew.in = append(tNew.in, pInner)
			}
			tNew.refineSize()
			gNew.outputs = append(gNew.outputs, tNew)
		}

		gNew.iostate = make(map[*transition]*transition, len(gNew.inputs)+len(gNew.outputs))
		for _, t := range gNew.inputs {
			if t.proxy != nil {
				gNew.iostate[t.proxy] = t
			}
		}
		for _, t := range gNew.outputs {
			if t.proxy != nil {
				gNew.iostate[t.proxy] = t
			}
		}

		tg.groups = append(tg.groups, gNew)
		gNew.updateBounds(false)
		gNew.updateIO()
		gNew.adjustIO()
		gNew.Align()
	}
	for _, t := range model.Transitions {
		tNew := constructTransition(t)
		tNew.parent = tg
		for _, p := range t.In {
			pNew, ok := madePlaces[p.Id]
			if !ok {
				pNew = constructPlace(p)
				pNew.parent = tg
				madePlaces[p.Id] = pNew
				tg.places = append(tg.places, pNew)
			}
			pNew.out = tNew
			tNew.in = append(tNew.in, pNew)
			if p.OutControl != nil {
				pNew.outControl = newControlPoint(p.OutControl.X, p.OutControl.Y, p.OutControl.Modified)
			}
			pNew.refineControls()
		}
		for _, p := range t.Out {
			pNew, ok := madePlaces[p.Id]
			if !ok {
				pNew = constructPlace(p)
				pNew.parent = tg
				madePlaces[p.Id] = pNew
				tg.places = append(tg.places, pNew)
			}
			pNew.in = tNew
			tNew.out = append(tNew.out, pNew)
			if p.InControl != nil {
				pNew.inControl = newControlPoint(p.InControl.X, p.InControl.Y, p.InControl.Modified)
			}
			pNew.refineControls()
		}
		tNew.refineSize()
		tg.transitions = append(tg.transitions, tNew)
	}
	for _, p := range model.Places {
		_, ok := madePlaces[p.Id]
		if !ok {
			pNew := constructPlace(p)
			pNew.parent = tg
			tg.places = append(tg.places, pNew)
		}
	}
}
Beispiel #9
0
func (c *Ctrl) handleEvents() {
	go func() {
		var x0, y0 float64
		var focused interface{}
		var copied bool
		for {
			switch ev := (<-c.events).(type) {
			case *stopEvent:
				return
			case *keyEvent:
				c.handleKeyEvent(ev)
			case *mouseEvent:
				x, y := c.WindowCoordsToRelativeGlobal(ev.x, ev.y)

				switch ev.kind {
				case EventMousePress:
					x0, y0 = x, y
					smth, found := c.model.findDrawable(x, y)

					if c.ModifierKeyAlt {
						if !found {
							c.model.deselectAll()
							c.model.update()
						} else if _, cp := smth.(*controlPoint); !cp {
							focused = smth
							c.model.deselectAll()
							c.model.selectItem(smth.(item))
							c.model.update()
						}
						c.model.util.min = &geometry.Point{x, y}
					} else if c.ModifierKeyShift && !found {
						var it item
						c.model.deselectAll()
						if c.ModifierKeyControl {
							it = c.model.addTransition(x, y)
						} else {
							it = c.model.addPlace(x, y)
						}
						c.model.selectItem(it)
						focused = it
						copied = true // prevent copy of item
					} else if !found {
						if !c.ModifierKeyControl {
							c.model.deselectAll()
							c.model.update()
						}
						c.model.util.min = &geometry.Point{x, y}
					} else {
						focused = smth
						if control, ok := smth.(*controlPoint); ok {
							control.modified = true
						} else {
							it := smth.(item)
							//x0, y0 = it.Center().X, it.Center().Y
							if len(c.model.selected) > 1 {
								if c.model.isSelected(it) && c.ModifierKeyControl {
									c.model.deselectItem(it)
								} else if c.ModifierKeyControl {
									c.model.selectItem(it)
								} else if !c.model.isSelected(it) {
									c.model.deselectAll()
									c.model.selectItem(it)
								}
							} else if !c.ModifierKeyControl {
								c.model.deselectAll()
								c.model.selectItem(it)
							} else {
								c.model.selectItem(it)
							}
						}
						c.model.update()
					}
				case EventMouseMove:
					dx, dy := x-x0, y-y0
					x0, y0 = x, y

					if c.ModifierKeyAlt {
						c.model.util.kind = UtilStroke
						c.model.util.max = &geometry.Point{x, y}
						if focused != nil {
							smth, found := c.model.findDrawable(x, y)
							if _, cp := smth.(*controlPoint); found && !cp {
								c.model.selectItem(smth.(item))
							} else if _, cp := focused.(*controlPoint); !found && !cp {
								c.model.deselectAll()
								c.model.selectItem(focused.(item))
							}
						}
						c.model.update()
					} else if c.ModifierKeyShift && !copied {
						copied = true
						clones := c.model.cloneItems(c.model.selected)
						c.model.deselectAll()
						for _, v := range clones {
							c.model.selectItem(v)
						}
						c.model.update()
					} else if focused != nil {
						c.model.util.kind = UtilNone
						c.model.util.max = nil
						if point, cp := focused.(*controlPoint); cp {
							point.Move(x, y)
							c.model.update()
							continue
						}
						toOrder := make(map[*transition]bool, len(c.model.transitions))
						for it := range c.model.selected {
							if p, ok := it.(*place); ok {
								p.Shift(dx, dy)
								if p.in != nil {
									toOrder[p.in] = true
								}
								if p.out != nil {
									toOrder[p.out] = true
								}
							} else if t, ok := it.(*transition); ok {
								if t.proxy == nil {
									t.Shift(dx, dy)
									toOrder[t] = true
								}
							} else {
								it.Shift(dx, dy)
							}
						}
						for t := range toOrder {
							t.OrderArcs(true)
							t.OrderArcs(false)
						}
						c.model.update()
					} else {
						c.model.util.kind = UtilRect
						c.model.util.max = &geometry.Point{x, y}
						dx := c.model.util.max.X - c.model.util.min.X
						dy := c.model.util.max.Y - c.model.util.min.Y
						var rect *geometry.Rect
						if dx == 0 || dy == 0 {
							continue
						}
						w, h := math.Abs(dx), math.Abs(dy)
						if dx < 0 && dy < 0 {
							rect = geometry.NewRect(
								c.model.util.max.X,
								c.model.util.max.Y,
								w, h,
							)
						} else if dx < 0 /* && dy > 0 */ {
							rect = geometry.NewRect(
								c.model.util.max.X,
								c.model.util.max.Y-h,
								w, h,
							)
						} else if dx > 0 && dy < 0 {
							rect = geometry.NewRect(
								c.model.util.max.X-w,
								c.model.util.max.Y,
								w, h,
							)
						} else /* dx > 0 && dy > 0 */ {
							rect = geometry.NewRect(
								c.model.util.min.X,
								c.model.util.min.Y,
								w, h,
							)
						}
						for _, p := range c.model.places {
							if p.Bound().Intersect(rect) {
								c.model.selectItem(p)
							} else {
								c.model.deselectItem(p)
							}
						}
						for _, t := range c.model.transitions {
							if t.Bound().Intersect(rect) {
								c.model.selectItem(t)
							} else {
								c.model.deselectItem(t)
							}
						}
						for _, g := range c.model.groups {
							if g.Bound().Intersect(rect) {
								c.model.selectItem(g)
								for _, t := range g.inputs {
									c.model.selectItem(t)
								}
								for _, t := range g.outputs {
									c.model.selectItem(t)
								}
							} else {
								c.model.deselectItem(g)
								for _, t := range g.inputs {
									c.model.deselectItem(t)
								}
								for _, t := range g.outputs {
									c.model.deselectItem(t)
								}
							}
						}
						c.model.update()
					}

				case EventMouseRelease:
					if c.ModifierKeyAlt && c.model.util.kind == UtilStroke {
						if it, ok := c.model.findDrawable(x, y); focused != nil && focused != it && ok {
							if p, ok := it.(*place); ok && p.in == nil {
								if t, ok := focused.(*transition); ok {
									t.link(p, false)
								} else if p2, ok := focused.(*place); ok && p2.out == nil {
									// p -- p2, new transition between
									pCenter, p2Center := p.Center(), p2.Center()
									t := c.model.addTransition((pCenter.X+p2Center.X)/2,
										(pCenter.Y+p2Center.Y)/2)
									t.link(p2, true)
									t.link(p, false)
								} else {
									log.Println("Unable to link smth to place")
								}
							} else if t, ok := it.(*transition); ok {
								if p, ok := focused.(*place); ok {
									t.link(p, true)
								} else if t2, ok := focused.(*transition); ok {
									// t -- t2, new place between
									tCenter, t2Center := t.Center(), t2.Center()
									p := c.model.addPlace((tCenter.X+t2Center.X)/2,
										(tCenter.Y+t2Center.Y)/2)
									t2.link(p, false)
									t.link(p, true)
								} else {
									log.Println("Unable to link smth to transition")
								}
							}
							c.model.deselectAll()
						} else if focused == nil && !ok {
							// stroking the void, cut the links
							start := c.model.util.min
							end := c.model.util.max
							unlink := func(t *transition, p *place, inbound bool, i int) bool {
								if inbound {
									control := p.outControl.Center()
									borderP := p.BorderPoint(control.X, control.Y, BorderPlaceDist)
									borderT := t.BorderPoint(true, i)
									if geometry.CheckSegmentsCrossing(start, end, borderP, control) ||
										geometry.CheckSegmentsCrossing(start, end, control, borderT) {
										return true
									}
								} else {
									control := p.inControl.Center()
									borderP := p.BorderPoint(control.X, control.Y, BorderPlaceTipDist)
									borderT := t.BorderPoint(false, i)
									if geometry.CheckSegmentsCrossing(start, end, borderP, control) ||
										geometry.CheckSegmentsCrossing(start, end, control, borderT) {
										return true
									}
								}
								return false
							}
							var toUnlink map[*place]bool
							for _, t := range c.model.transitions {
								toUnlink = make(map[*place]bool, len(t.in))
								for i, p := range t.in {
									if unlink(t, p, true, i) {
										toUnlink[p] = true
									}
								}
								for p := range toUnlink {
									t.unlink(p, true, false)
								}
								toUnlink = make(map[*place]bool, len(t.out))
								for i, p := range t.out {
									if unlink(t, p, false, i) {
										toUnlink[p] = true
									}
								}
								for p := range toUnlink {
									t.unlink(p, false, false)
								}
							}
							grps := make(map[*group]bool, len(c.model.groups))
							for _, g := range c.model.groups {
								for _, t := range g.inputs {
									toUnlink = make(map[*place]bool, len(t.in))
									for i, p := range t.in {
										if unlink(t, p, true, i) {
											toUnlink[p] = true
										}
									}
									for p := range toUnlink {
										grps[g] = true
										t.unlink(p, true, true)
									}
								}
								for _, t := range g.outputs {
									toUnlink = make(map[*place]bool, len(t.out))
									for i, p := range t.out {
										if unlink(t, p, false, i) {
											toUnlink[p] = true
										}
									}
									for p := range toUnlink {
										grps[g] = true
										t.unlink(p, false, true)
									}
								}
							}
							for g := range grps {
								g.updateIO()
								g.adjustIO()
							}
						}
					} else {
						toAlign := make(map[item]bool, len(c.model.selected))
						for it := range c.model.selected {
							if _, ok := it.(*group); ok {
								continue
							}
							toAlign[it] = true
						}
						c.alignItems(toAlign)
					}

					focused = nil
					copied = false
					c.model.util.kind = UtilNone
					c.model.update()

				case EventMouseDoubleClick:
					if c.ModifierKeyControl || c.ModifierKeyShift {
						continue
					}
					if focused != nil {
						c.model.deselectAll()
						c.model.selectItem(focused.(item))
						if t, ok := focused.(*transition); ok {
							t.rotate()
							if t.proxy != nil {
								t.group.adjustIO()
							}
							c.model.update()
						}
						if p, ok := focused.(*place); ok {
							if c.ModifierKeyAlt {
								p.timer++
							} else {
								p.counter++
							}
							c.model.update()
						}
						if g, ok := focused.(*group); ok {
							if g.folded {
								c.model.unfoldGroup(g)
							} else {
								c.model.foldGroup(g)
							}
							c.model.update()
						}
					}
				}
			default:
				log.Println("Event not supported")
			}
		}
	}()
}