Skip to content

Instantly share code, notes, and snippets.

@typesupply
Last active February 17, 2023 18:03
Show Gist options
  • Save typesupply/d01e0fa069e3f04f0da6ec0ba5df38ae to your computer and use it in GitHub Desktop.
Save typesupply/d01e0fa069e3f04f0da6ec0ba5df38ae to your computer and use it in GitHub Desktop.

Intro Session

Why does ezui exist?

We've learned a lot.

We have been making type design tool UIs for over 25 years. We have a lot of experience and examples to learn from. Our API for building UI hasn't changed much in 25 years. (We're still using the W API from RoboFont.) It works, but can we have something better?

Break it into a design problem...

We have four different levels of where interfaces are needed:

  • script
  • extension
  • app-like extension
  • app

There are some common design patterns among all of these. Most of the UI is just a bunch of buttons, text fields, checkboxes, etc. lined up. These are pretty basic Web 1.0 forms, actually.

Merz and Subscriber introduced some new models that have been useful.

  • Merz: The coder use a very simple descriptions to build things. Behind the scenes, these descriptions are converted to complex objects that use sophisticated optimization techniques.
  • Subscriber: The coder subclasses a base class and automatically inherits a lot of potential behavior. As long as the design pattern is followed, everything just works and complex, tedious stuff is completely abstracted away.

Apple gave us new tools.

iOS introduced the idea that, hey, maybe positioning things with absolute coordinates kind of sucks and maybe could just go away.

  1. First there was auto layout with constraints, hugging, priorities and other stuff. This was powerful, but pretty gnarly to do manually.
  2. Then there was an ASCII format for building these. This was great... as long as you understood the syntax. Sometimes it wasn't great even when you understood the syntax. I added this to vanilla several years ago.
  3. Then came stacks and grids. You simply put stuff in and the stuff is positioned automatically. You can put a stack inside of a stack inside of a grid inside of a grid inside of a stack and it just works. Most of the time.

Vanilla has problems.

Vanilla is a Pythonic wrapper around Cocoa. It's a pretty direct wrapper apart from List. It was built when absolute positioning was all that was available. (NSLayoutContraint was still 8+ years away!) Everything in vanilla is manual: you have to add the controls, wire up the callbacks and so on. Vanilla is verbose and fiddly, which sucks when trying to write a quick script. Once you have your controls in place, it's a pain to change the layout of or add new controls to the interface. Finally, since vanilla is just a wrapper around the Cocoa objects, it doesn't help with layout. This makes it very easy to make ugly interfaces that don't come close to following the macOS HIG.

Some goals for a new thing.

  1. Make it super easy to use in scripts.
  2. Build all the magic stuff into the objects that each script had to implement each time.
  3. Follow the HIG automatically.
  4. The API should be memorable and predictable. Method and attribute names should follow some guidelines for tense, structure, etc.
  5. It must be VERY EASY to change the design of the interface.

So... build it?

I learned auto layout and built something that didn't work. I relearned auto layout and built something that didn't work. I relearned auto layout and built something that didn't work.

ezui is really ezui 5.0 or higher. It seems to have stabilized about a year ago so I'm considering it ready for use.

Concepts.

ezui is made of stuff. These stuff have names:

  • item: a button, a field, a slider.
  • container: an item that contains other items.
  • window: a window.

Additionally, there are special things called forms that are containers of controls that are prebuilt for you.

There is no positioning geometry. You put your items in a container and they will be positioned automatically. There is very limited sizing geometry. The only time you need to give the size for something is when it doesn't have an intrinsic size. And, even then, there are fallbacks.

Each item may have an identifier. This identifier is used to automatically connect your callbacks to the item, to get/set values from/to the item and to get the item if you want to interact with it directly.

You don't build objects directly. You describe your containers and items with a Markdown and ASCII art inspired syntax called EZML (EZ Markup Language). You provide additional information for your items with simple dictionaries.

Demo time because it's easier to understand it by looking at it than by hearing me jibber jabber.

The Base Structure:

import ezui

class Demo(ezui.WindowController):

	def build(self):
		pass

	def started(self):
		pass

	def destroy(self):
		pass

Demo()
  1. Subclass ezui.WindowController.
  2. Define build, started methods. Optionally define a destroy method.

To build your interface, define your items in build. Open the window in started.

import ezui

class Demo(ezui.WindowController):

	def build(self):
		content = """
		(Hello World) @helloWorldButton
		------X------ @slider
		"""
		descriptionData = dict(
			silder1=dict(
				value=0.5,
				minValue=0,
				maxValue=1.0,
				tickMarks=3
			)
		)
		self.w = ezui.EZWindow(
			content=content,
			descriptionData=descriptionData,
			controller=self
		)

	def started(self):
		self.w.open()

	def destroy(self):
		pass

	def helloWorldButtonCallback(self, sender):
		print("Hello world!")

	def sliderCallback(self, sender):
		value = sender.get()
		print(f"slider: {value}")

Demo()

Some of the items.

... and the syntax for creating them.

  • Label
  • (PushButton)
  • [ ] Checkbox
  • ( ) RadioButtons
  • ---X--- # Slider
  • [_TextField_]
  • |---| # Table
    • group rows
    • cell types
    • popover at index
  • * WebView (to show complex data)

If I see item combinations happening frequently, I'll try to add them as official items. For example, ---X--- [__] # SliderAndTextField.

Some of the containers.

... and how nesting works.

  • * Box
  • * Tabs
  • * VerticalStack
  • * OneColumnForm
  • * TwoColumnForm

Some of the windows.

  • Window
  • Sheet
  • PopUp

ezui.WindowController has useful stuff.

  • File system interaction.
  • Progress.

Content types.

  • Colors. (r, g, b, a) or NSColor
  • Fonts.
  • Images. (use SF Symbols)

Intro Lab

  • exercise 1
  • exercise 2
  • exercise 3






Advanced Session

  • migrating from vanilla
  • splits
  • working with Subscriber
  • creating a custom item
  • table pro
    • views for rows
    • getters and setters
    • value converters
  • drag and drop
  • building without ezml (works but don't unless you really need to)

Advanced Lab

  • maybe just build stuff upon request?
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment