Skip to content
Snippets Groups Projects
Select Git revision
  • tanklabsim
  • julia1
  • master default protected
3 results

LabGUI.jl

  • Clone with SSH
  • Clone with HTTPS
  • LabGUI

    This package is used to create GUIs, most suitable for lab applications. See DoubleTankLab for a larger implementation.

    Installation

    First, install WebIO by following the instructions in the link. Then install InteractNext by following the instructions in the link. Then run

    Pkg.add("LabGUI")

    and the package should be installed.

    Usage

    To create a gui, use gui = GUI(), and to get the GUI graphics use gui(). The set! function sets widgets or DOM objects to the gui and add! adds them. The following example produces a hello world gui and serves it with Mux

    using LabGUI, Mux
    gui = GUI()
    
    set!(gui, Node(:div, "Hello world!"))
    
    webio_serve(page("/", req -> gui()))

    It can now be accessed in a browser at http://0.0.0.0:8000.

    Widgets and the construct macro

    The construct macro is a modified version of the @manipulate macro from InteractNext, which permits rearranging the ui as the designer sees fit. Example:

    using LabGUI, Mux
    gui = GUI()
    
    widgets, ui = @construct for x in 1:10
    	Node(:div, "$x")
    end
    set!(gui, widgets) #widgets are set
    set!(gui, Node(:div, ui, gui.widgets[:x])) #dom field is set
    
    webio_serve(page("/", req -> gui()))

    The layout is independent of the number of widgets, and is completely determined by the dom field of the gui. We don't even have to include the widgets in the responder:

    widgets, ui = @construct for x in 1:10
    	Node(:div, "$x")
    end
    set!(gui, widgets) 
    set!(gui, Node(:div, ui)) 

    Now, the widget is not shown, but it can be changed from the julia side by typing (for example) gui[:x] = 2 in the REPL. Generally, set! will be used once for the first widgets and once for the complete ui. Any additional widgets are then be added with add!

    Making Grids

    Some methods are provided which intend to make overall ui design easier, found in src/gridmaker.jl. The function make_grid(n,m) creates an n by m grid node. We can then access its elements using the following syntax:

    grid = make_grid(3,5)
    grid[1,3] ### access of element
    grid = setindex_(grid, "newvalue", i,j) #assignment of "newvalue" at index [i,j]

    The grid is a dom object, so we can use set!(gui, grid) to make it the layout of the gui. Grids can also have other grids as their elements.

    SVG Graphics

    In the file svg_helper.jl one can find some routines used to create SVG graphics with a slightly simpler syntax.

    using LabGUI, InteractNext, Mux
    gui = GUI()
    
    widgets, ui = @construct for x in vslider(5:5:100),
    	y in vslider(5:5:100)
    	Node(svgsvg_symb, #This makes the node an SVG container
    		 svg_circle(100, 100, x, s_color(s_red)),
    		 svg_rect(100, y, 0, y, s_color(s_blue)))
    end
    set!(gui, widgets)
    layout = make_grid(1,3)
    layout = setindex_(layout, gui.widgets[:x], 1, 1)
    layout = setindex_(layout, gui.widgets[:y] , 1, 2)
    layout = setindex_(layout, ui , 1, 3)
    set!(gui, layout)
    
    webio_serve(page("/", req -> gui()))

    Data fields

    The GUI class contains an array container to store lab data in the field gui.data. This makes it easier to plot inside the GUI and to implement functionality such as buttons to export the data (see the DoubleTankLab repository for an example of this). There is also some syntactic sugar to make pushing data to the GUI easier:

    push!(gui, value, index) #pushes value to gui.data[index]
    push!(gui, values, indices::Tuple) #pushes values to data[index] for index in indices

    Animation

    Some methods are provided to facilitate animation of the GUI or parts of it. Example:

    gui = GUI()
    
    widgets, ui = @construct for t in 0:200
    	Node(svgsvg_symb, style=stdattr,
    	svg_rect(300,300),
    	svg_circle(50+t, 250-200*sin(time())^2, 50, 
    		s_color((255*sin(time()/3)^2, 255*sin(time()/5)^2, 255*sin(time()/7)^2))))
    end
    
    set!(gui, widgets)
    set!(gui, Node(:div, gui.widgets[:t], ui))
    animate(gui, :t, 0.05)

    Generally, when animating we want to use a dummy variable to get a fixed framerate and to make the GUI more responsive:

    gui = GUI()
    
    widgets, dummyui = @construct for t in 0:200
    	Node(:div)
    end
    set!(gui, widgets) #This allows us to access symbol access gui[:t] of the value of t below
    
    dummywidgets, ui = @construct for dummy in 0:200
    	Node(svgsvg_symb, style=stdattr,
    	svg_rect(300,300),
    	svg_circle(50+gui[:t], 250-200*sin(time())^2, 50, 
    		s_color(s_blue)))
    end
    
    add!(gui, dummywidgets)
    set!(gui, Node(:div, gui.widgets[:t], ui, dummyui)) #dummyui must be included in the dom, or widgets associated with it (t) will time out
    
    animate(gui, :dummy, 0.05)