All Projects → phronmophobic → Membrane

phronmophobic / Membrane

Licence: apache-2.0
A platform agnostic clojure(script) library for creating user interfaces

Programming Languages

c
50402 projects - #5 most used programming language
clojure
4091 projects
clojurescript
191 projects

Projects that are alternatives of or similar to Membrane

Shadertoy Rs
A desktop client for Shadertoy written in Rust
Stars: ✭ 41 (-73.38%)
Mutual labels:  graphics, desktop
3dhop
3D Heritage Online Presenter
Stars: ✭ 89 (-42.21%)
Mutual labels:  graphics, webgl
3d Game Shaders For Beginners
🎮 A step-by-step guide to implementing SSAO, depth of field, lighting, normal mapping, and more for your 3D game.
Stars: ✭ 11,698 (+7496.1%)
Mutual labels:  graphics, webgl
Gltfpp
glTF 2.0 loader for C++14
Stars: ✭ 22 (-85.71%)
Mutual labels:  graphics, webgl
Wechart
Create all the [ch]arts by cax or three.js - Cax 和 three.js 创造一切图[表]
Stars: ✭ 152 (-1.3%)
Mutual labels:  graphics, webgl
Xeogl
A WebGL-based 3D engine for technical visualization. Not actively maintained.
Stars: ✭ 920 (+497.4%)
Mutual labels:  graphics, webgl
Iced
A cross-platform GUI library for Rust, inspired by Elm
Stars: ✭ 12,176 (+7806.49%)
Mutual labels:  graphics, user-interface
Vue Gl
Vue.js components rendering 3D WebGL graphics reactively with three.js
Stars: ✭ 434 (+181.82%)
Mutual labels:  graphics, webgl
Gcanvas
A lightweight cross-platform graphics rendering engine. (超轻量的跨平台图形引擎) https://alibaba.github.io/GCanvas
Stars: ✭ 1,705 (+1007.14%)
Mutual labels:  graphics, webgl
Hilo3d
Hilo3d, a WebGL Rendering Engine.
Stars: ✭ 123 (-20.13%)
Mutual labels:  graphics, webgl
Directxtk12
The DirectX Tool Kit (aka DirectXTK12) is a collection of helper classes for writing DirectX 12 code in C++
Stars: ✭ 765 (+396.75%)
Mutual labels:  graphics, desktop
Engine
Oasis Engine is a web-first and mobile-first high-performance real-time development platform.
Stars: ✭ 2,202 (+1329.87%)
Mutual labels:  graphics, webgl
Icg Webgl
交互式计算机图形学——基于WebGL的自顶向下方法(第七版)的例子与练习题
Stars: ✭ 458 (+197.4%)
Mutual labels:  graphics, webgl
Xna.js
WebGL framework strongly inspired by the XNA library
Stars: ✭ 40 (-74.03%)
Mutual labels:  graphics, webgl
Lume
Create CSS3D/WebGL applications declaratively with HTML. Give regular DOM elements shadow and lighting.
Stars: ✭ 445 (+188.96%)
Mutual labels:  graphics, webgl
Axis3d
Functional 3d graphics library
Stars: ✭ 67 (-56.49%)
Mutual labels:  graphics, webgl
Magnum
Lightweight and modular C++11 graphics middleware for games and data visualization
Stars: ✭ 3,728 (+2320.78%)
Mutual labels:  graphics, webgl
Beam
✨ Expressive WebGL
Stars: ✭ 383 (+148.7%)
Mutual labels:  graphics, webgl
Bgfx
Cross-platform, graphics API agnostic, "Bring Your Own Engine/Framework" style rendering library.
Stars: ✭ 10,252 (+6557.14%)
Mutual labels:  graphics, webgl
Filament
Filament is a real-time physically based rendering engine for Android, iOS, Windows, Linux, macOS, and WebGL2
Stars: ✭ 13,215 (+8481.17%)
Mutual labels:  graphics, webgl

Membrane

Membrane is a platform agnostic clojure library for creating user interfaces.

Membrane provides three layers:

  1. A UI framework, membrane.component, that provides state management for GUIs
  2. A platform agnostic model for graphics and events
  3. Multiple graphics backends that provide concrete implementations for #2

While these three layers are made to work together, they can also be mixed and matched with other implementations. For example, you could use your favorite UI framework and the other layers to reach another platform. Alternatively, you could provide your own ncurses graphics backend and leverage the ui framework and graphics model.

For membrane to run on a platform, the only requirements are

  1. Drawing implementations for graphical primitives like rectangles, text, and images
  2. An event loop that forwards events (eg. mouse clicks, key presses) to membrane and repaints

Supported platforms:

  • Mac OSX
  • Linux
  • the web via WebGL

Experimental platforms

Experimental UI framework integrations

Links

Tutorial
Docs
Examples
Distributing your desktop app
Targeting WebGL
Questions? Comments? Connect with us on clojurians slack in #membrane (join here) or discuss on twitter.

Rationale

Membrane was written because I wanted to build a desktop app with clojure, but I wanted all the cool functional features found in libraries targeting the browser, ie. react, reagent, re-frame, fulcro, etc.

Membrane does not build on top of any existing ui toolkits like Swing, JavaFX, HTML, UIKit, GTK, etc. These toolkits are fundamentally based on an object oriented model and have a deep impedance mismatch with idiomatic clojure code.

As much as possible, the development of the library was meant to follow clojure's principles

  • Use the simplest construct that does the job
  • Data first
  • Pure functions that work with the data
  • Side effects and process at the edges

By applying clojure's principles, several "extras" were obtained for free

  • platform agnostic
  • flexible
  • great for tooling

For more info covering the design of membrane:
What is a User Interface?
Implementing a Functional UI Model
Reusable UI Components

Usage

Leiningen dependency:

[com.phronemophobic/membrane  "0.9.22-beta"]

deps.edn dependency:

com.phronemophobic/membrane {:mvn/version "0.9.22-beta"}

Examples

A Simple Example without the UI Framework

Screenshot: simple counter

(ns counter
  (:require [membrane.skia :as skia]
            [membrane.ui :as ui
             :refer [horizontal-layout
                     button
                     label
                     spacer
                     on]]))

(defonce counter-state (atom 0))

;; Display a "more!" button next to label showing num
;; clicking on "more!" will increment the counter
(defn counter [num]
  (horizontal-layout
   (on :mouse-down (fn [[mouse-x mouse-y]]
                     (swap! counter-state inc)
                     nil)
       (button "more!"))
   (spacer 5 0)
   (label num (ui/font nil 19))))

(comment
    ;; pop up a window that shows our counter
    (skia/run #(counter @counter-state)))

Simple Example using membrane.component UI Framework

Screenshot: simple counter


(ns counter
  (:require [membrane.skia :as skia]
            [membrane.ui :as ui
             :refer [horizontal-layout
                     vertical-layout
                     button
                     label
                     on]]
            [membrane.component :as component
             :refer [defui make-app defeffect]])
  (:gen-class))


;; Display a "more!" button next to label showing num
;; clicking on "more!" will dispatch a ::counter-increment effect
(defui counter [{:keys [num]}]
  (horizontal-layout
   (on :mouse-down (fn [[mouse-x mouse-y]]
                     [[::counter-increment $num]])
       (ui/button "more!"))
   (ui/label num)))

(defeffect ::counter-increment [$num]
  (dispatch! :update $num inc))

(comment
  ;; pop up a window showing our counter with
  ;; num initially set to 10
  (skia/run (make-app #'counter {:num 10})))

Here's an example of how you can use your counter component.

Screenshot: couning counter

;; Display an "Add Counter" button
;; on top of a stack of counters
;;
;; clicking on the "Add Counter" button will
;; add a new counter to the bottom of the stack
;; 
;; clicking on the counters' "more!" buttons will
;; update their respective numbers
(defui counter-counter [{:keys [nums]}]
  (apply
   vertical-layout
   (on :mouse-down (fn [[mx my]]
                     [[::add-counter $nums]])
       (ui/button "Add Counter"))
   (for [num nums]
     (counter {:num num}))))

(defeffect ::add-counter [$nums]
  (dispatch! :update $nums conj 0))

(comment
  ;; pop up a window showing our counter-counter
  ;; with nums initially set to [0 1 2]
  (skia/run (make-app #'counter-counter {:nums [0 1 2]})))

Fun Features

;; graphical elements are values
;; no need to attach elements to the dom to get layout info
(ui/bounds (vertical-layout
           (ui/label "hello")
           (ui/checkbox true)))
>> [30.79296875 27.0]


;; events are pure functions that return effects which are also values
(let [mpos [15 15]]
  (ui/mouse-down
   (ui/translate 10 10
                 (on :mouse-down (fn [[mx my]]
                                   ;;return a sequence of effects
                                   [[:say-hello]])
                     (ui/label "Hello")))
   mpos))
>> ([:say-hello])


;; horizontal and vertical centering!
(skia/run #(let [rect (ui/with-style :membrane.ui/style-stroke
                        (ui/rectangle 200 200))]
             [rect
              (ui/center (ui/label "hello") (ui/bounds rect))]) )


;; save graphical elem as an image
(let [todos [{:complete? false
              :description "first"}
             {:complete? false
              :description "second"}
             {:complete? true
              :description "third"}]]
  (skia/draw-to-image! "todoapp.png"
                       (todo-app {:todos todos :selected-filter :all})))

;; use spec to generate images of variations of your app
(doseq [[i todo-list] (map-indexed vector (gen/sample (s/gen ::todos)))]
  (skia/draw-to-image! (str "todo" i ".png")
                       (ui/vertical-layout
                        (ui/label (with-out-str
                                    (clojure.pprint/pprint todo-list)))
                        (ui/with-style :membrane.ui/style-stroke
                          (ui/path [0 0] [400 0]))
                        (todo-app {:todos todo-list :selected-filter :all}))))

Screenshots

Overview

More Info

That's it! For more in-depth info, check out the tutorial.

Tutorial
Docs
Examples
Distributing your desktop app
Targeting WebGL
Questions? Comments? Connect with us on clojurians slack in #membrane

License

Copyright 2021 Adrian Smith. Membrane is licensed under Apache License v2.0.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].