forked from HEL/circuiteria
		
	
		
			
				
	
	
		
			106 lines
		
	
	
		
			2.3 KiB
		
	
	
	
		
			Typst
		
	
	
	
	
	
			
		
		
	
	
			106 lines
		
	
	
		
			2.3 KiB
		
	
	
	
		
			Typst
		
	
	
	
	
	
#import "@preview/cetz:0.2.2": draw, coordinate
 | 
						|
#import "ports.typ": add-ports, add-port
 | 
						|
 | 
						|
#let find-port(ports, id) = {
 | 
						|
  for (side, side-ports) in ports {
 | 
						|
    for (i, port) in side-ports.enumerate() {
 | 
						|
      if port.id == id {
 | 
						|
        return (side, i)
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
  panic("Could not find port with id " + str(id))
 | 
						|
}
 | 
						|
 | 
						|
#let default-draw-shape(id, tl, tr, br, bl, fill, stroke) = {
 | 
						|
  return ({}, tl, tr, br, bl)
 | 
						|
}
 | 
						|
 | 
						|
#let elmt(
 | 
						|
  draw-shape: default-draw-shape,
 | 
						|
  x: none,
 | 
						|
  y: none,
 | 
						|
  w: none,
 | 
						|
  h: none,
 | 
						|
  name: none,
 | 
						|
  name-anchor: "center",
 | 
						|
  ports: (),
 | 
						|
  ports-margins: (),
 | 
						|
  fill: none,
 | 
						|
  stroke: black + 1pt,
 | 
						|
  id: "",
 | 
						|
  auto-ports: true,
 | 
						|
  ports-y: (),
 | 
						|
  debug: (
 | 
						|
    ports: false
 | 
						|
  )
 | 
						|
) = draw.get-ctx(ctx => {
 | 
						|
  let width = w
 | 
						|
  let height = h
 | 
						|
 | 
						|
  let x = x
 | 
						|
  let y = y
 | 
						|
  if x == none { panic("Parameter x must be set") }
 | 
						|
  if y == none { panic("Parameter y must be set") }
 | 
						|
  if w == none { panic("Parameter w must be set") }
 | 
						|
  if h == none { panic("Parameter h must be set") }
 | 
						|
 | 
						|
  if (type(x) == dictionary) {
 | 
						|
    let offset = x.rel
 | 
						|
    let to = x.to
 | 
						|
    let (ctx, to-pos) = coordinate.resolve(ctx, (rel: (offset, 0), to: to))
 | 
						|
    x = to-pos.at(0)
 | 
						|
  }
 | 
						|
  
 | 
						|
  if (type(y) == dictionary) {
 | 
						|
    let from = y.from
 | 
						|
    let to = y.to
 | 
						|
    let (to-side, i) = find-port(ports, to)
 | 
						|
    let margins = (0%, 0%)
 | 
						|
    if to-side in ports-margins {
 | 
						|
      margins = ports-margins.at(to-side)
 | 
						|
    }
 | 
						|
    let used-pct = 100% - margins.at(0) - margins.at(1)
 | 
						|
    let used-height = height * used-pct / 100%
 | 
						|
    let top-margin = height * margins.at(0) / 100%
 | 
						|
    
 | 
						|
    let dy = used-height * (i + 1) / (ports.at(to-side).len() + 1)
 | 
						|
 | 
						|
    if not auto-ports {
 | 
						|
      top-margin = 0
 | 
						|
      dy = ports-y.at(to)(height)
 | 
						|
    }
 | 
						|
    
 | 
						|
    let (ctx, from-pos) = coordinate.resolve(ctx, from)
 | 
						|
    y = from-pos.at(1) + dy - height + top-margin
 | 
						|
  }
 | 
						|
 | 
						|
  let tl = (x, y + height)
 | 
						|
  let tr = (x + width, y + height)
 | 
						|
  let br = (x + width, y)
 | 
						|
  let bl = (x, y)
 | 
						|
 | 
						|
  // Workaround because CeTZ needs to have all draw functions in the body
 | 
						|
  let func = {}
 | 
						|
  (func, tl, tr, br, bl) = draw-shape(id, tl, tr, br, bl, fill, stroke)
 | 
						|
  func
 | 
						|
 | 
						|
  if (name != none) {
 | 
						|
    draw.content(
 | 
						|
      (name: id, anchor: name-anchor),
 | 
						|
      anchor: name-anchor,
 | 
						|
      padding: 0.5em,
 | 
						|
      align(center)[*#name*]
 | 
						|
    )
 | 
						|
  }
 | 
						|
 | 
						|
  if auto-ports {
 | 
						|
    add-ports(
 | 
						|
      id,
 | 
						|
      tl, tr, br, bl,
 | 
						|
      ports,
 | 
						|
      ports-margins,
 | 
						|
      debug: debug.ports
 | 
						|
    )
 | 
						|
  }
 | 
						|
}) |