Commit Graph

225 Commits

Author SHA1 Message Date
Elias Naur e5c040be1b widget/material: fix click area offset for Switch
The click area was mistakenly offset by half the track width, but it
really should be offset by half the thumb diameter.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-11-30 14:34:15 +01:00
Elias Naur 3e0b72304a all: replace deprecated pointer.Rect with clip.Rect
Converted with

gofmt -w -r 'pointer.Rect(r) -> clip.Rect(r)' .
gofmt -w -r 'pointer.Ellipse(r) -> clip.Ellipse(layout.FRect(r))' .

combined with 'goimports -w .' to clean up imports.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-11-03 14:12:31 +01:00
Elias Naur 29cea1db49 io/pointer,io/router: replace AreaOp with clip.Op
Pointer hit areas and paint clip areas are separate concepts, but
similar enough to warrant merging. This change replaces pointer hit
areas with clip areas, so Gio is left with just one area concept (in
package op/clip).

The reason for separating the concepts in the original Gio release was
because of my being unsure general path/stroke hit areas would ever be
implemented, let alone efficient.

This change represents a change of mind, in the sense that it's better
to have an incomplete API than two separate area concepts.

Leave the deprecated pointer.Rect, pointer.Ellipse for temporary
backwards compatibility.

This is an API change. Most existing programs should continue to build
with this change, but may have to adjust to having all clip.Ops participate
in InputOp hit areas.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-11-03 14:12:31 +01:00
Chris Waldon c5831de955 widget/material: fix List anchoring with zero minimum constraints
This comment and associated code were designed to guard against
the scrollbar failing to anchor to the proper edge of the content
when the layout.Direction was used with a zero minimum constraint.

However, they were in the wrong place to actually achieve the
desired behavior. This change simply moves the constraints
change to before the invocation of layout.Direction's Layout
method. This fixes the scrollbar appearing on the wrong edge of
content when the content is laid out with a zero minimum constraint.

Signed-off-by: Chris Waldon <christopher.waldon.dev@gmail.com>
2021-11-03 08:57:10 +01:00
Pierre Curto ef36ce3953 widget/material: remove unnecessary Offset in ProgressCircle
Signed-off-by: Pierre Curto <pierre.curto@gmail.com>
2021-11-03 08:56:45 +01:00
Elias Naur 9cf7cc75f4 widget/material: fix slider thumb offset
Change 936c266b03 converted a
transformation pop incorrectly. This change corrects that.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-10-26 12:13:11 +02:00
Elias Naur 960f3068a1 io/pointer: re-introduce PassOp
A previous change merged PassOp with AreaOp under the assumption that
the pass mode would be set on a particular area. That assumption turns
out not to hold, so this change brings back PassOp as an independent
stack operation.

This is an API change: replace AreaOp{Pass: true} with a separate
pointer.PassOp operation.

Fixes gio#288

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-10-09 16:31:54 +02:00
Elias Naur bd1ef92dc4 op/clip: remove complex stroke support
In a discussion with Raph Levien, the author of our compute renderer
implementation, it became clear to me that it's not at all certain that
complex strokes will ever be efficiently supported by a GPU renderer.

At the same time, the machinery for converting a complex stroke to a
GPU-friendly outline has a significant maintenance cost. Further, it is
surprising to users that complex strokes are significantly slower and
allocate memory.

This change removes support for complex strokes, leaving only
round-capped, round-joined strokes supported by the compute renderer.
The default renderer still converts all strokes to outline, but it also
caches the result.

This is an API change. The complex stroke conversion code has been moved
to the external gioui.org/x/stroke package, with a similar API.

Updats gio#282 (Inkeliz brought up the allocation issue)

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-10-08 18:10:47 +02:00
Elias Naur 936c266b03 all: [API] split operation stack into per-state stacks
The op.Save and Load methods exist to support the need for
transformation, clip, pointer area state to behave as stacks. For
example, layout needs to apply an offset to its children but not
subsequent operations.

Before this change, op.Save and Load were used to save and restore the
state:

    ops := new(op.Ops)
    // Save state.
    state := op.Save(ops)
    // Apply offset.
    op.Offset(...).Add(ops)
    // Draw with offset applied.
    draw(ops)
    // Restore state.
    state.Load()

A drawback with the op.Save mechanism is that there is no direct
connection between the state change and the saving and loading of state.
This causes confusion as to when a Save/Load is needed and who is
responsible for performing them, which leads to subtle bugs and over-use
of Save/Loads.

This change gets rid of the general state stack and replaces it with
per-state stacks. There is now a stack for transformation, clip, pointer
areas, and they can only be restored by the code pushing state to them.
The example above now becomes:

    ops := new(op.Ops)
    // Push offset to the transformation stack.
    stack := op.Offset(...).Push(ops)
    // Draw with offset applied.
    draw(ops)
    // Restore state.
    stack.Pop()

For convenience, transformation also be Add'ed if the stack operation is
not required.

Simple state such as the current material no longer has a way to be
restored; it is assumed the client of a PaintOp adds their desired
material operation before it.

API change: replace op.Save/Load with explicit Push/Pop scopes for
op.TransformOps, pointer.AreaOps, clip.Ops.

To ease porting, this change retains a version of op.Save/Load that
saves and restores the transformation and clip stacks. It also retains
an Add method for clip.Op.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-10-08 17:21:56 +02:00
Elias Naur 6f80b94b4a io/pointer,io/router: [API] make pass-through a property of AreaOp
We're about to make operation scopes explicit, which would result in
both AreaOp and PassOp be scoped. However, PassOp seems to light to have
its separate stack, so this change instead makes pass-through a property
of an area. We're assuming that clients that want pass-through are also
aware of the affected hit area.

API change: replace PassOps with the AreaOp.PassThrough field.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-10-08 15:54:50 +02:00
Elias Naur c1298cd755 font/opentype,text,widget: use clip.Op for text shapes, not a macro
This change avoids a macro wrapping every text shape, and prepares text
shaping for scoped clip operations.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-10-07 15:01:17 +02:00
Elias Naur cd5a78f3d8 widget: make Fit.scale a pure function
Most importantly, return dimensions and transformation instead of adding
operations. Makes the function easier to test, and supports scoped
transform and clip stacks.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-10-07 15:01:17 +02:00
Elias Naur 799ee3374d widget,widget/material: scroll using only drag position delta
This commit is based on a patch by Elias that improved drag scrolling
on the scrollbar by locking some parameters of the math at the start
of the scroll event.

I discovered while playing with that implementation that there was
an even simpler approach within his changeset. You can actually
use no information other than the delta between the current and
previous frame's scroll position to compute the scroll distance.
By simplifying the math to rely on no other inputs, the jitter that
we've been fighting simply disappears (it came from other inputs).

Turns out my attempts to make the logic smart were the problem.

Signed-off-by: Chris Waldon <christopher.waldon.dev@gmail.com>
2021-09-17 08:47:13 +02:00
Chris Waldon 77eed223ac widget/material: fix scrollbar indicator partially off-screen bug
This commit fixes a problem that could force the scroll indicator to
lay itself out outside of its configured bounds. This occurred when
the scroll indicator size was increased to meet the minimum size
configured on the style type while the scrollbar was near the end
of the list. The increased size did not take the start position
of the scroll indicator into account, which made the indicator begin
in the correct place, but extend beyond the end of its track.

This commit alters the logic to ensure that the scroll indicator can
never extend beyond the end of its track.

Signed-off-by: Chris Waldon <christopher.waldon.dev@gmail.com>
2021-09-14 06:42:22 +02:00
Chris Waldon da09aabbe8 widget/material: clamp fromListPosition end coordinate
Previously, it was possible for fromListPosition to return
an end coordinate greater than 1, which would make scroll
indicators using those coordinates render beyond the
boundaries of their scroll tracks. One could argue that
this is a bug in the scroll indicator, but I don't think
this method should return data outside of its documented
range.

Signed-off-by: Chris Waldon <christopher.waldon.dev@gmail.com>
2021-09-14 06:42:15 +02:00
Walter Werner SCHNEIDER 8701c253c3 material: update label type scales to match the MD spec
Signed-off-by: Walter Werner SCHNEIDER <contact@schnwalter.eu>
2021-09-01 14:30:27 +02:00
Elias Naur 6e9bb7b91c widget,widget/material: remove Color field from Icon
Icons are meant to be shared among multiple widgets, but their Color
state may end up with unexpected values after use. Replace the state
with and explicit argument to Layout.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-07-28 14:19:39 +02:00
Chris Waldon b3918ce40f widget/material: ensure List accounts for scrollbar size in dims
This commit ensures that the dimensions returned by material.List
include the size of the scrollbar when the scrollbar is set to
the Occupy AnchorStrategy.

Signed-off-by: Chris Waldon <christopher.waldon.dev@gmail.com>
2021-07-13 16:43:38 +02:00
Chris Waldon 78235baaa5 widget/material: ensure List handles zero minimum constraints
This change ensures that the scrollbar anchors to the proper edge of the
content even when the list was drawn with a zero minimum constraint.

Without this, the layout.Direction used to anchor the scrollbar will choose
to use the minimum size and anchor it to the opposite edge of the content.

Signed-off-by: Chris Waldon <christopher.waldon.dev@gmail.com>
2021-07-13 15:09:26 +02:00
Chris Waldon 0e60935856 widget/material: ensure scrollbars can be dragged from list end
The scrollbar implementation prior to this change only adjusted
list.Position.Offset. This works in all circumstances except when
list.Position.BeforeEnd=false. If the position indicates that the
scroll position is at the end of the list, the offset is ignored.

This change ensures that manually dragging the scrollbar always
causes BeforeEnd to be set to true. If the drag ends with the
scrollbar at the end of the list, BeforeEnd will be set
automatically by the next list.Layout call, so this doesn't
prevent the list from optimizing for that case in general.

Signed-off-by: Chris Waldon <christopher.waldon.dev@gmail.com>
2021-07-07 15:51:00 +02:00
Chris Waldon 941aeaae91 widget{,/material}: add List types with scrollbars
To use these lists instead of layout.List, callers simply need to
change declarations of layout.List to widget.List, and to change
calls to layout.List.Layout to material.List(th,&list).Layout.

So this:

    var list layout.List
    list.Layout(gtx, 10, func(gtx C, index int) D {
        return material.Body1(th, fmt.Sprintf("%d", index)).Layout(gtx)
    })

Becomes:

    var list widget.List
    material.List(th, &list).Layout(gtx, 10, func(gtx C, index int) D {
        return material.Body1(th, fmt.Sprintf("%d", index)).Layout(gtx)
    })

Naturally, the material.ListStyle type supports tweaking the scrollbar's
appearance and behavior.

Signed-off-by: Chris Waldon <christopher.waldon.dev@gmail.com>
2021-07-05 16:08:30 +02:00
pierre 2e991f31be widget: make Icon honour its constraints
This is a breaking change as Icon.Layout no longer requests a size.

Before:
  sz := unit.Dp(20)
  ic.Layout(gtx, sz)

After:
  sz := gtx.Metric.Px(unit.Dp(20))
  gtx.Constraints.Min = image.Pt(sz, 0)
  ic.Layout(gtx)

Fixes gio#240

Signed-off-by: pierre <pierre.curto@gmail.com>
2021-07-01 13:15:08 +02:00
Elias Naur a87206c364 widget/material: add ProgressCircle
Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-06-26 18:05:34 +02:00
Inkeliz dd86c9706f widget: add key.InputHint to widget.Editor
Signed-off-by: Inkeliz <inkeliz@inkeliz.com>
2021-06-07 17:00:40 +02:00
Elias Naur d5b70c439c widget/material: draw Loader completely inside its bounds
Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-05-19 19:35:36 +02:00
pierre b6e9c0324d widget: make Editor implement io.Seeker, io.Reader and io.WriterTo
The WriteTo, Seek, Read methods implement a more efficient access to
the Editor content than Text.

Signed-off-by: pierre <pierre.curto@gmail.com>
2021-05-19 17:25:42 +02:00
Elias Naur 23a839a29d widget: clip by most complex shape last
In the new compute renderer, clipping to a complex shape is slower than
filling it. Swap the clip shapes for drawing text so that the text shape
itself is last, and therefore used for filling.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-04-27 16:49:06 +02:00
pierre 5e1a662b94 io/pointer: support nested scrollables
Fixes #185.

Signed-off-by: pierre <pierre.curto@gmail.com>
2021-03-31 09:57:13 +02:00
pierre 4d4b3a627a widget: fixed missing sides in Border
Signed-off-by: pierre <pierre.curto@gmail.com>
2021-03-15 15:38:25 +01:00
Egon Elbre fecfbbb050 op/clip: expose Circle.Path and RRect.Path.
These can be nicely used together with clip.Stroke.

Signed-off-by: Egon Elbre <egonelbre@gmail.com>
2021-03-14 13:28:21 +01:00
Egon Elbre b9f2e0fb41 widget/material: use clip.Circle to draw circles
Signed-off-by: Egon Elbre <egonelbre@gmail.com>
2021-03-14 10:08:58 +01:00
Egon Elbre 9793fcfcd0 widget: add Fit and Position to Image for image placement
Signed-off-by: Egon Elbre <egonelbre@gmail.com>
2021-03-05 10:45:58 +02:00
Egon Elbre 2c5daf10a2 widget: add Fit for scaling widgets
Currently adds four different variants Unscaled, Contain, Cover, ScaleDown and Fill.

Signed-off-by: Egon Elbre <egonelbre@gmail.com>
2021-03-05 10:25:57 +02:00
Elias Naur 2bd539d2de widget/material: use simpler clip.Rect for Clickable clip region
Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-03-03 20:04:46 +01:00
Elias Naur b39d1bdac7 widget: handle hovering of the empty Enum key
Before this change, a radio button with the empty key ("") would be
displayed as hovering if no other button were.

It's still not possible to have no radio buttons selected when one of
them is the empty key. If that's becomes necessary, Enum.Value can be
converted to a *string.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-03-03 18:12:39 +01:00
Elias Naur de7a5985d5 widget/material: remove bogus minimum cosntraint from checkable
checkable.layout forces the label to take up at least constraints.min
space. However, for min == max, the total checkbox plus label would then
overflow. The minimum constraint doesn't seem necessary anymore, so drop
it.

Remove a superfluous layout.W layout as well.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-03-03 17:32:31 +01:00
Elias Naur ffb26b0e17 io/pointer: rename button names to reflect their meaning, not placement
For example, ButtonLeft may be the right-most button for a left-handed user.
Rename the button names to match their intended use.

This is an API change. Use the following commands to update your
projects:

    $ gofmt -r 'pointer.ButtonLeft -> pointer.ButtonPrimary' -w .
    $ gofmt -r 'pointer.ButtonRight -> pointer.ButtonSecondary' -w .
    $ gofmt -r 'pointer.ButtonMiddle -> pointer.ButtonTertiary' -w .

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-03-03 11:08:41 +01:00
Chris Waldon 6faed7e724 widget: fix image scaling
Commit 94d242d broke the widget.Image's Scale field so
that it no longer had any effect on the actual size of
the displayed image. This commit fixes that, as well as
adding tests to confirm that the widget.Image type
scales appropriately with DPI changes and its own Scale
field.

Signed-off-by: Chris Waldon <christopher.waldon.dev@gmail.com>
2021-02-28 10:19:49 +01:00
vsariola a8a48bb809 widget: fix bug how f.pos is calculated in widget.Float
The order of subtraction when calculating f.pos from value was wrong,
so setting a minimum value for a Float never really worked, although
min = 0 worked as intended which is why this probably went unnoticed.

Signed-off-by: vsariola <5684185+vsariola@users.noreply.github.com>
2021-02-15 09:00:11 +01:00
Chris Waldon 6682f75db9 widget/material: use more readable editor default selection color
Signed-off-by: Chris Waldon <christopher.waldon.dev@gmail.com>
2021-02-06 07:51:56 +01:00
Paulo Melo 403f01655a Programmatic Click function
Signed-off-by: Paulo Melo <paulo.durrer.melo@gmail.com>
2021-02-04 11:10:20 +01:00
Larry Clapp f88a8216e9 widget: fix Editor panic
If you created an Editor and immediately SetCaret, it panicked because
e.lines was nil and it looked at e.lines[0].

- Add e.makeValid at the top of SetCaret.
- Add a test case for this situation.

Signed-off-by: Larry Clapp <larry@theclapp.org>
2021-01-24 11:06:55 -05:00
Larry Clapp 34273940a0 widget,widget/material: add selection to the editor
- Allow dragging to be on both horizontal and vertical axes at once.
- Split Editor.caret.pos into caret.start and caret.stop. caret.start is
  the old caret.pos, and is both the position of the caret, and also the
  start of selected text. caret.end is the end of the selected text.
  Start can be after end, e.g. after after Shift-DownArrow.
- Update caret.end after a mouse drag, and various shifted keys
  (Shift-UpArrow, Shift-DownArrow, etc).
- Change Shortcut-C to copy only the selected text, not the whole editor
  text.
- Add Shortcut-X to copy and delete selected text, and Shortcut-A to
  select all text.
- The various Insert/Delete/etc functions now overwrite or delete the
  selection, as appropriate.
- Change MoveCaret to accept a distance for selection end, as well.
  Change SetCaret to accept a selection end offset.
- Add SelectionLen to get the selection length, Selection to get
  selection offsets, SelectedText to get the selected text, and
  ClearSelection to clear the selection.
- Add a rudimentary selection unit test, and extend the deleteWord unit
  test with some text selection cases.
- Add SelectionColor to material.EditorStyle, which defaults to
  Theme.Palette.ContrastBg.

Signed-off-by: Larry Clapp <larry@theclapp.org>
2021-01-24 09:44:52 +01:00
Larry Clapp e78bd15564 widget: refactoring to prep for editor selection
- Move caret from editBuffer.caret to Editor.caret.pos.ofs and related
  refactoring. Move other fields in Editor.caret into Editor.caret.pos.
- Refactor several functions to change a position passed into them,
  rather than changing e.rr.caret directly.
- Add editBuffer.Seek().
- Remove editBuffer.dump().
- Change Editor.Move to MoveCaret.
- Add Editor.SetCaret.
- Updated tests.

Signed-off-by: Larry Clapp <larry@theclapp.org>
2021-01-24 09:44:41 +01:00
Elias Naur 4f45d9a567 io/router: rename Router.Add to the more specific Queue
Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-01-22 16:36:14 +01:00
Elias Naur e70a16c345 io/router/key: add explicit tag to FocusOp; make last SoftKeyboardOp apply
The target of FocusOp is too subtle; be explicit instead and remove
any doubt.

Multiple SoftKeyboardOp in a single frame is rare, but if they do occur,
they should behave as if they were from separate frames: the last one
applies.

As a side-effect the key event router can be much simplified.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-01-22 16:34:51 +01:00
pierre b24df0aa6e widget/material: use clip.UniformRRect
Signed-off-by: pierre <pierre.curto@gmail.com>
2021-01-21 10:30:00 +01:00
Chris Waldon 9231ff47ef widget: make border draw within widget dims as documented
Signed-off-by: Chris Waldon <christopher.waldon.dev@gmail.com>
2021-01-19 20:22:11 +01:00
Egon Elbre eea1dbc176 widget/material: add hover to Switch
Signed-off-by: Egon Elbre <egonelbre@gmail.com>
2021-01-18 10:57:10 +01:00
Egon Elbre bc6798c4ca widget/material: add hovered to RadioButton
Signed-off-by: Egon Elbre <egonelbre@gmail.com>
2021-01-18 10:57:06 +01:00