Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Basic dropdown widget integration #4013

Merged
merged 14 commits into from
Jan 11, 2023

Conversation

Frizi
Copy link
Contributor

@Frizi Frizi commented Dec 30, 2022

Pull Request Description

Implements https://www.pivotaltracker.com/n/projects/2539304/stories/184023445

Added a dropdown widget to graph node for all span tree nodes that have tag values present. When an option is selected, the controller receives a partial expression update, which targets specific crumbs of the expression (similar to how edge endpoint updates work).

trim-dropdown.mp4

Important Notes

Right now the dropdown widget is recreated every time the node is edited, including a dropdown option being selected. This causes it to close every time. I wanted to get around that by diffing span trees, but I wasn't able to do it in useful way. Additionally, current implementation of node input expression view heavily relies on being reinitialized from scratch every time. This led to more necessary changes than I was comfortable with for this task. I believe it will be easier to implement it as part of more complete widget support, especially after dynamic data support, as we will have proper widget type information.

Checklist

Please include the following checklist in your PR:

  • The documentation has been updated if necessary.
  • All code conforms to the
    Scala,
    Java,
    and
    Rust
    style guides.
  • All code has been tested:
    • Unit tests have been written where possible.
    • If GUI codebase was changed: Enso GUI was tested when built using BOTH
      ./run ide build and ./run ide watch.

@Frizi Frizi force-pushed the wip/frizi/dropdown-integration-184023445 branch from 6beece1 to 107aaf5 Compare January 2, 2023 10:46
@Frizi Frizi marked this pull request as ready for review January 2, 2023 11:49
CHANGELOG.md Outdated
@@ -79,6 +79,8 @@
the project is changed from the last saved snapshot and lighter when the
snapshot matches the current project state.
- [Added shortcut to interrupt the program][3967]
- [Added dropdown for node argument value suggestions.][4013] Currently it
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be understandable by the user (user != power user). This sentence is really hard to parse. Can we make it a little bit more elaborate and easier to understand, please?

app/gui/src/presenter/graph.rs Outdated Show resolved Hide resolved
app/gui/src/presenter/graph/state.rs Outdated Show resolved Hide resolved
app/gui/view/graph-editor/src/component/node.rs Outdated Show resolved Hide resolved

/// Possible widgets for a node input.
#[derive(Clone, Debug, CloneRef)]
pub enum NodeWidget {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of such Enum, I'd allow any "widget" to be registered on nodes. Just like visualisations. We should allow for custom widgets in the future (as we allow for custom visualisations). We can leave it for now, but in such a case, we should write in the comment that this is a temporary solution that will be removed in <...> task.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm going to add a note in the comment in this specific case. But in general I don't like putting comments about uncertain future into the code. The current dynamic widgets design doc lists all initial widget types explicitly, so this is why I went with an enum to begin with, as that was the pragmatic choice.

Given that we have dynamic visualizations, I agree that this is likely to change at some point. But I believe we don't yet have any specific tasks planned for that.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The design doc lists all the things in order to make it easy to understand. However, the design in the code should be generic, as we know that we will have user-defined widgets sooner than later. Changing such a fundamental assumption later would make a lot of changes in the code, so it's better to do it in the code beforehand. I'd like to make it the extensible way before all the widgets tasks are finished, so just please take care of that when designing the arch here :)

app/gui/view/graph-editor/src/lib.rs Outdated Show resolved Hide resolved
@Frizi Frizi requested a review from wdanilo January 5, 2023 11:06
Copy link
Member

@JaroslavTulach JaroslavTulach left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I got the static drop down widgets working on the Text.trim example. Selecting a value for an argument works, but how do I "unselect an argument value"? In the following picture

drop-downs

I have got wrong value for what (tracked in pivotal) - shouldn't the user be able to click and revert the what value back to default?

Other than that, I am really glad the drop down feature is coming. It really improves the usability of the IDE.

Copy link
Contributor

@hubertp hubertp left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've done similar QA and have similar comments to Jaroslav - essentially I would like to come back to the default value without deleting the node completely and starting from scratch. How would I do that?

ArgumentInfo::new(t.name.clone(), t.tp.clone(), t.tag_values.clone()),
Self::InsertionPoint(t) =>
ArgumentInfo::new(t.name.clone(), t.tp.clone(), t.tag_values.clone()),
_ => return None,
Copy link
Contributor

@hubertp hubertp Jan 9, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not a Rust expert but I find this explicit return rather unexpected. I preferred the previous style even if it was more verbose.

Copy link
Contributor Author

@Frizi Frizi Jan 10, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've seen and used this specific pattern (wrapping match in Some and returning None in specific branch) many times before, my impression is that it is fairly common. But I agree that for short match blocks like this it is probably not worth. In this specific case, it is allowing the expression to fit into a single line. Given that I'm going to add another parameter here anyway, I might split it into multiple lines and get back to the fully implicit return form.

@hubertp
Copy link
Contributor

hubertp commented Jan 10, 2023

@Frizi are the names somehow specially formatted already or is that customized for Location?
Screenshot from 2023-01-10 12-09-27
Notice that in the above example we insert fully qualified names which later leads to errors.

@JaroslavTulach
Copy link
Member

@Frizi are the names somehow specially formatted already ... Notice that in the above example we insert fully qualified names which later leads to errors.

According to the original design the idea was:

Each entry in the tagValues array shall represent a valid Enso value.
E.g. if the entry is evaluated as an Enso code, it shall be valid. That means each value
can represent a number, a quoted string or fully qualified name
of an atom constructor applicable as an argument to the function invocation.
The IDE is expected to deal with the entries:

  • Shorten them appropriately for user presentation.
  • Display just parts of the text.
  • Decide which of the fully qualified names to import.

@Frizi
Copy link
Contributor Author

Frizi commented Jan 10, 2023

My understanding is that the fully qualified names delivered in tagValues should always be valid to insert as is into the code. The instances where this is currently not true are a bug. For simplicity, I don't want to modify imports. The visual shortening is not done yet, as the rendered code line cannot differ from actual in-file code (except minor trimming like for skip/freeze macros). Eventually we will move away from displaying the raw code, and there will be widgets rendered instead. It is technically possible to display the names shortened inside the dropdown already. I'd still prefer to do it together with the in-node widget and use the same logic for both.

It is not possible to deselect the dropdown option right now after selecting it, but It sounds fairly easy to add for arguments that have hasDefault set to true. I'll add it. Without it, you had to edit the node and remove the argument text manually (with ctrl-click on the node).

Copy link
Contributor

@hubertp hubertp left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Been playing with it a bit more and it appears to slightly break when more parameters are present ?
Screenshot from 2023-01-10 16-39-59
Notice how names of parameters are now gone but the selection dot for dropdowns are there

@Frizi
Copy link
Contributor Author

Frizi commented Jan 10, 2023

@hubertp the parameters are not gone. There are _ symbols in place. The dots slightly cover them so it's not very clear, but those are temporary anyway. That means there indeed are three arguments that can be autocompleted there.

@hubertp
Copy link
Contributor

hubertp commented Jan 10, 2023

@hubertp the parameters are not gone. There are _ symbols in place. The dots slightly cover them so it's not very clear, but those are temporary anyway. That means there indeed are three arguments that can be autocompleted there.

I see, yeah, I had to zoom in the screenshot. But why are there _ symbols in place rather than the names of parameters?
Like here
Screenshot from 2023-01-10 17-02-11

@Frizi
Copy link
Contributor Author

Frizi commented Jan 10, 2023

Good question. The dropdowns fills in the argument AST position with the given value. It is always treated as a positional argument. That means all arguments in front of it are automatically filled with _, as you need something there to get the argument position right.

Using argument names directly leads to all sorts of wrong parsing. I don't think that this syntax is in well supported in IDE now, and certainly it is out of scope of this PR.

image

@Frizi Frizi force-pushed the wip/frizi/dropdown-integration-184023445 branch from c3ff113 to 5a27ca2 Compare January 10, 2023 18:00
@Frizi Frizi force-pushed the wip/frizi/dropdown-integration-184023445 branch from 5a27ca2 to a6fcebe Compare January 11, 2023 10:59
@hubertp
Copy link
Contributor

hubertp commented Jan 11, 2023

When removing the dropdown could we come back to what was before (i.e. not _)? Or is that due to the same problem as discussed above?

Kazam_screencast_00005.mp4

@Frizi
Copy link
Contributor Author

Frizi commented Jan 11, 2023

It is similar reason. Outright removing an argument in first position isn't possible. I am not sure why but it is explicitly disallowed by the spantree logic. This behaves exactly the same as disconnecting an edge would. When a function has more arguments and you unselect the last one, it will be completely removed.

@Frizi Frizi added the CI: Ready to merge This PR is eligible for automatic merge label Jan 11, 2023
@mergify mergify bot merged commit fe1cf9a into develop Jan 11, 2023
@mergify mergify bot deleted the wip/frizi/dropdown-integration-184023445 branch January 11, 2023 14:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
CI: Ready to merge This PR is eligible for automatic merge
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants