Commit Graph

83 Commits

Author SHA1 Message Date
Elias Naur 6ef1ff7cfb widget/material: remove Inset from ButtonLayoutStyle
ButtonLayout is for custom button content; insets belong to the
custom content, not the button.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2020-06-30 20:44:35 +02:00
Gordon Klaus 5368743478 widget,widget/material: add Float and Slider
Signed-off-by: Gordon Klaus <gordon.klaus@gmail.com>
2020-06-22 12:17:35 +02:00
Elias Naur 878131189b all: remove redundant op.TransformOp.Offset
Use op.Offset instead, or create and manipulate a f32.Affine2D.

API change. Update your code with a gofmt rule:

	gofmt -r 'op.TransformOp{}.Offset -> op.Offset'

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2020-06-21 22:41:56 +02:00
Elias Naur 9e3d3b6f58 text,font/gofont: replace text.Collection with slice of FontFaces
A slice of FontFace pairs are simpler, and thread safe in case a client
wants to append or modify the font collection.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2020-06-21 21:44:28 +02:00
Chris Waldon 9f6e09317d widget/material: add disabled state support to all widgets
This commit configures all remaining widgets to draw themselves in a disabled state
when their layout.Context is disabled. A description of the
strategy employed by each follows:

- Checkbox and RadioButton: Draws the icon component in a lighter color. Currently the label text is left
in its default color.
- ProgressBar: The "progress" color is lightened, but not as much as the background color. This makes the current progress value still readable.
- Editor: The cursor is no longer drawn and the text is lightened.
- Switch: The track is unchanged, but the circular "thumb" component is lightened.

Signed-off-by: Chris Waldon <christopher.waldon.dev@gmail.com>
2020-06-15 09:53:49 +02:00
Elias Naur 5fe3785bbd widget/material: make Switch disabled color configurable
Signed-off-by: Elias Naur <mail@eliasnaur.com>
2020-06-10 20:20:36 +02:00
Elias Naur 6380baacb6 all: move Now from system.Config to system.FrameEvent
Then, make layout.Context.Now a field, copied from FrameEvent.Now.

API change:

	gofmt -r 'gtx.Now() -> gtx.Now'

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2020-06-09 23:23:08 +02:00
Elias Naur a24a2c9fb6 widget/material: fade out inkwells a little longer than their expansions
Signed-off-by: Elias Naur <mail@eliasnaur.com>
2020-06-09 22:29:43 +02:00
Elias Naur 0715c801e2 widget,widget/material: convert Switch to use Clickable
Signed-off-by: Elias Naur <mail@eliasnaur.com>
2020-06-09 22:12:41 +02:00
Elias Naur f7fea02312 widget: immediately fade out cancelled button press inkwells
Signed-off-by: Elias Naur <mail@eliasnaur.com>
2020-06-09 21:51:39 +02:00
Elias Naur ce56464923 widget,gesture: fade out cancelled inkwells
While here, adjust inkwell sizes to match gtx.Constraints.Min.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2020-06-08 23:50:00 +02:00
Elias Naur 36f4267a6c widget/material: fade in inkwells
When a clickable is pressed and dragged any enclosing List will grab and
cancels the press. To minimize visual dicontinuity, smoothly fade in the
inkwell.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2020-06-08 22:07:02 +02:00
Chris Waldon cc5f8fcffe widget/material: add support for disabled buttons
This leverages the new semantics of a disabled layout.Context
to draw all of the button types in a disabled state.

Signed-off-by: Chris Waldon <christopher.waldon.dev@gmail.com>
2020-06-08 10:16:50 +02:00
Elias Naur b07d34354e text,widget/material: make font collections explicit
Before this change, package font implemented a global font registry,
with the usual problems of package global state.

This change deletes the global registry and introduces the text.Collection
type for representing a list of fonts and their faces. Collection exports
Lookup that finds the closest match and its face.

The existing FontRegistry is renamed to Cache to reflect its new limited
functionality: a cache of shapes and measurements on top of a Collection.

Then, material.NewTheme is changed to take a Collection and initialize
a Cache.

Updates gio#19 because multiple windows require a separate (writable) Cache per
window, while (read-only) Collections may be shared.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2020-06-07 16:27:43 +02:00
Elias Naur c19ed05342 op: change CallOp to be a return value from MacroOp.Stop
Converting

	macro := op.Record(ops)
	...
	macro.Stop()

	macro.Add()

to

	macro := op.Record(ops)
	...
	call := macro.Stop()

	call.Add(ops)

Which is more general (call.Add can take a different ops than the op.Record
that started it), and enforced the order between Stop and the subsequent Add.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2020-06-02 12:07:20 +02:00
Thomas Bruyelle ae8a377cda op: add op.Push and op.Record funcs
The funcs replace stack.Push and macro.Record, which become private.
This makes stack and macro faster to write, in particular for stacks
where you can just write the following line to save and restore the
state :

  defer op.Push(ops).Pop()

This usage requires Push to return a pointer (since Pop has a pointer
receiver), or else the code doesn't compile.

For consistancy, I tried to do the same for op.Record, but this implied
to turn all the MacroOp fields into pointers, and this caused some
panics. As a result, op.Record doesn't return a pointer.

An other side effect pointed by Larry Clapp: StackOp and MacroOp are not
re-usable any more, you have to allocate a new one for each usage, using
the described funcs above.

Signed-off-by: Thomas Bruyelle <thomas.bruyelle@gmail.com>
2020-06-02 10:39:56 +02:00
Elias Naur f2df7c1458 widget: change Enum.Layout to follow layout protocol
Respect constraints and return dimensions.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2020-05-24 13:52:48 +02:00
Elias Naur 31d722d9eb widget: change Bool.Layout to follow layout protocol
Just like Clickable, Bool.Layout should respect constraints and
return its dimensions.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2020-05-24 13:50:03 +02:00
Elias Naur 8d838e89f5 widget,widget/material: rename widget.Click to widget.Press
Press tracks pointer presses, not clicks, and we're about to add a Click
type that does.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2020-05-24 13:19:34 +02:00
Elias Naur d017c722f5 widget,widget/material: only process events in Layout methods
Before this change, events were typically processed twice or more per
widget: once in the Layout method for refreshing the visual state, and
once per method that queries for state changes.

One example is widget.Clickable that processed events in both its Layout
and Clicked method.

This change establishes the convention that events are processed once, in
the Layout method. There are several advantages to that approach:

- Query methods such as Clickable.Clicked no longer need a layout.Context.
- State updates from events only occur in Layout.
- Widgets are simplified because they won't need a separate processEvents
(or similar) method and won't forget to call it from methods other than Layout.
- Useless calls to gtx.Events are avoided (gtx.Events only returns events
for the first call each frame for a given event.Tag).

The disadvantage is that state updates from input events will not appear
before Layout. For example, in the call sequence

	var btn *widget.Clickable

	if btn.Clicked() {...}
	btn.Layout(...)

the Clicked call will not detect an incoming click until the frame after it
happened.

This is ok because

- The Gio event router automatically dispatches an extra frame after events
arrive, bounding the latency from events to queries such as Clicked to
at most one frame (~17 ms).
- The potential extra frame of latency does not apply to Layout methods as long
as they process events before drawing. In other words, the visual feedback
from input events are not delayed because of this change.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2020-05-24 13:03:23 +02:00
Elias Naur 2451750782 widget/material: move widget state object from Layout methods to constructors
Instead of, say,

	var th *material.Theme
	var btn *widget.Clickable

	material.Button(th, "Click me").Layout(gtx, btn)

move the widget state objects to the constructor:

	material.Button(th, btn, "Click me").Layout(gtx)

The advatage is that several widgets can now be used without
wrapping them in function literals. For example,

	layout.Inset{}.Layout(gtx, func(gtx layout.Context) layout.Dimensions {
		material.Button(th, "Click me").Layout(gtx, btn)
	})

collapses to just

	layout.Inset{}.Layout(gtx, material.Button(th, btn, "Click me").Layout)

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2020-05-23 22:28:49 +02:00
Elias Naur 3af01a3f43 layout: change Widget to take explicit Context and return explicit Dimensions
Change the definition of Widget from the implicit

        type Widget func()

to the explicit functional

        type Widget func(gtx layout.Context) layout.Dimensions

The advantages are numerous:

- Clearer connection between the incoming context and the output dimensions.
- Returning the Dimensions are impossible to omit.
- Contexts passed by value, so its fields can be exported
and freely mutated by the program.

The only disadvantage is the longer function literals and the many "returns".
What tipped the scales in favour of the explicit Widget variant is that type
aliases can dramatically shorten the literals:

	type (
		C = layout.Context
		D = layout.Dimensions
	)

	widget := func(gtx C) D {
		...
	}

Note that the aliases are not part of the Gio API and it is up to each user
whether they want to use them.

Finally the Go proposal for lightweight function literals,
https://github.com/golang/go/issues/21498, may remove the disadvantage
completely in future.

Context becomes a plain struct with only public fields, and its Reset is
replaced by a NewContext convenience constructor.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2020-05-23 22:28:49 +02:00
Elias Naur af10307f4a widget/material: drop Padding from IconButtonStyle
Use Inset instead, matching the other buttons.

Redefine Size to apply to the icon size, without padding.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2020-05-23 10:44:10 +02:00
Elias Naur 7a13c2c905 widget/material: correctly apply alpha to ProgressBar color
color.RGBA values are pre-multiplied, so transparency must be applied
to all components.

Fixes gio#117

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2020-05-19 15:39:43 +02:00
Elias Naur 013ea395b4 all: use new rectangle and point convenience functions
Signed-off-by: Elias Naur <mail@eliasnaur.com>
2020-05-19 11:03:30 +02:00
Elias Naur 7bf3265ccd layout,widget: transpose Constraints to use image.Points for limits
Instead of

    type Contraints struct {
	    Width, Height Constraint
    }

use

    type Constraints struct {
	    Min, Max image.Point
    }

which leads to simpler use. For example, the Min method is trivally replaced by
the field, and the RigidConstraints constructor is no longer a net win.

API Change. Rewrites:

    gofmt -r 'gtx.Constraints.Min() -> gtx.Constraints.Min'
    gofmt -r 'gtx.Constraints.Width.Min -> gtx.Constraints.Min.X'
    gofmt -r 'gtx.Constraints.Height.Min -> gtx.Constraints.Min.Y'
    gofmt -r 'gtx.Constraints.Height.Max -> gtx.Constraints.Max.Y'
    gofmt -r 'gtx.Constraints.Width.Max -> gtx.Constraints.Max.X'

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2020-05-19 09:58:07 +02:00
Elias Naur 23baeff18d widget/button,widget/material: introduce Clickable for generic click areas
material.Clickable is useful for adding a click response to any widget
or area.

Rename widget.Button to widget.Clickable to reflect the wider use
spectrum.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2020-05-11 13:17:14 +02:00
Elias Naur fd2cb4a7a1 widget,widget/material: use constraints for setting up hit area
Before this change, the widget.Button.Layout method assumed the caller had set
up the pointer hit area before. Further, the very common rectangular hit
areas needed both an AreaOp and a widget.Button.Layout call.

Make widget.Button less subtle and more useful by setting up a
pointer hit area given by the incoming minimum constraints.

Drop a pointer.AreaOp made redundant by the change.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2020-05-11 12:37:08 +02:00
Elias Naur 4e20ea83a1 widget/material: use cosntraints for setting pointer hit areas
Signed-off-by: Elias Naur <mail@eliasnaur.com>
2020-05-11 12:23:18 +02:00
Elias Naur c32b3fe43a widget/material: drop Color from ButtonLayoutStyle
Setting a ColorOp before calling a widget function is too subtle.
Let the widget manage its color instead.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2020-05-11 11:31:48 +02:00
Elias Naur 26da49e145 widget/material: add Switch widget
Signed-off-by: Elias Naur <mail@eliasnaur.com>
2020-05-05 10:38:31 +02:00
Elias Naur 6b4eb710b3 widget: rename CheckBox to Bool
We're about to introduce the Switch widget that re-uses the same
state type as CheckBox. The Bool name covers both uses.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2020-05-04 17:13:50 +02:00
Elias Naur 52d8a8867d widget,widget/material: export CheckBox.Checked
Similar to the previous change to Enum, expose the current state of
the CheckBox. Rename the Checked method to just Update and get rid
of the SetChecked method.

Fixes gio#100

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2020-05-03 21:28:33 +02:00
Elias Naur f1e266a9e7 widget,widget/material: export Enum.Value
The Value method both updated the enum value and returned it.

In order to access the current value withoutm, expose the Value
field of the enum and rename the method to Update. As a bonus we
can get rid of the SetValue method as well.

Updates gio#96

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2020-05-03 21:28:33 +02:00
Elias Naur 060cff257f material: make theme constructors stand-alone functions
The multitude of widget methods on Theme is unnecessary coupling in that all
possible widgets either have to be included in package material, or be
different than 3rd party widgets:

	var th *Theme

	// Core widget, calling a method on Theme.
	th.Button(...).Layout(...)

	// 3rd party widget, calling a function taking a Theme.
	datepicker.New(th, ...).Layout(...)

Another reason for the Theme methods was to enable a poor man's
theme replacement, so that you could use the same code for
compatible themes. For example,

	mat.Button(...).Layout(...)

would not need to change if the type of mat changed, as long as
the new type had a compatible method Button.

However, that point misses the fact that the mat variable had to
be declared somewhere, naming the theme package:

	var mat *material.Theme (or, say, *cocoa.Theme)

A better and complete way to replace a theme is to use import renaming.
For example, to replace the material theme with a hypothetical Windows
theme, replace

	import theme "gioui.org/widget/material"

with

	import theme "github.com/somebody/windows

This change moves all Theme widget methods to be standalone functions,
and renames the widget style types accordingly.

For example, instead of the method

	func (t *Theme) Button(...) Button

there is now a function

	func Button(t *Theme, ...) ButtonStyle

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2020-05-03 13:03:04 +02:00
Elias Naur e460e4f4bf widget,widget/material: move Image and Icon to widget package
There is nothing theme-specific about displaying images and icons,
so move the types from the material package to the generic widget
package.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2020-05-03 12:22:32 +02:00
Elias Naur fa7f9d3ba8 widget/material: report icons dimensions after running Icon.Layout
Signed-off-by: Elias Naur <mail@eliasnaur.com>
2020-05-02 20:56:33 +02:00
Elias Naur b1aed3eae0 Revert "widget/material: propagate ButtonLayout minimum constraints to content"
This reverts commit 52ccc183b5.

Reason for revert:

This doesn't seem like a good idea after all. The reason for the change was to
propagate the minimum constraints to the button content. But in the simplest case,
a label, stretching the button will make the label stretch as well, leaving the label
top-aligned.

We'll revisit this issue if a real use-case comes up.
2020-04-16 19:57:19 +02:00
metaclips da01fbdea7 widget/material: add ProgressBar
Add progress indicator support to material widget

Signed-off-by: metaclips <utimichael9@gmail.com>
2020-04-02 21:05:13 +02:00
Elias Naur 27d81b8c7e widget/material: re-center Button label
A previous change propagated the minimum layout constraints to Button's
content, which made Button no longer center its label when stretched.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2020-03-27 16:40:13 +01:00
Elias Naur 52ccc183b5 widget/material: propagate ButtonLayout minimum constraints to content
The previous change fixed a regression where minimum constraints larger than 0
would not affect the button. This change moves the minimum constraints one
level lower so the content widget will see them as well. The wrapping
layout.Center ensures that any misbehaving widgets still end up centered.

Add a test to lock in the new behaviour and the previous fix.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2020-03-25 17:52:02 +01:00
metaclips f7a23ad46a widget/material: draw button to max width with ButtonLayout
This patch allows support to draw button to maximum width using ButtonLayout.
2020-03-25 17:41:01 +01:00
metaclips 5d7fbd761f widget/material: add ButtonLayout
Add ButtonLayout for adding button behaviour and style to arbitrary content such
as a combined icon-and-text button.
Fixes #43

Signed-off-by: metaclips <utimichael9@gmail.com>
2020-03-22 13:20:32 +01:00
Elias Naur 148a2828e7 layout: don't force Expanded Stack children larger than their minimum
Instead, honor the constraints after laying out both Stacked and
Expanded children.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2020-02-29 14:06:25 +01:00
Elias Naur bfb50cef5d all: remove unused fields, functions and add missing error handling
Credit to staticcheck.io.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2020-02-27 22:26:54 +01:00
Larry Clapp 0dd77be975 widget/material: allow button Inset to be customizable
Signed-off-by: Larry Clapp <larry@theclapp.org>
2020-02-17 15:37:08 +01:00
Elias Naur 69dfd2e3a5 op/paint: add support for efficient ImageOp subimages
The new field ImageOp.Rect is initialized to cover the entire source
image, but can be modified to draw only a section of it.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2020-02-13 13:15:32 +01:00
Elias Naur 4c220f4554 text: simplify text layout and shaping API
First, replace LayoutOptions with an explicit maximum width parameter.  The
single-field option struct doesn't carry its weight, and I don't think we'll
see more global layout options in the future. Rather, I expect options to cover
spans of text or be part of a Font.

Second, replace the unit.Converter with an scaled text size. It's simpler and
allow the Editor and similar widgets to easily detect whether their cached
layouts are stale. Package text no longer depends on package unit, which is
now dealt with at the widget-level only.

Finally, remove the Size field from Font. It was a design mistake: a Font is
assumed to cover all sizes, as evidenced by the FontRegistry disregarding
Size when looking up fonts.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2020-02-03 23:32:55 +01:00
Elias Naur fb7337f794 layout: replace Align with a Layout method on Direction
It's one less type (Align) and shorter:

Before:

	layout.Align(layout.Center).Layout(...)

After

	layout.Center.Layout(...)

It is also safer: since `layout.Align(...)` was a casting operation,
the Go compiler would not complain about an incompatible constant.

For example, the widget/material package contained a wrong cast:

	layout.Align(layout.Start)

which should have been

	layout.Align(layout.W)

After this change, attempting `layout.Start.Layout(...)` result
in a compile error.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2020-02-02 17:13:02 +01:00
Elias Naur e25b1639b9 text: make Shaper an interface
And rename out the caching implementation to FontRegistry.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2020-01-13 14:48:31 +01:00