Skip to content

Commit

Permalink
live preview Do not handle key events in error case
Browse files Browse the repository at this point in the history
Only process key events while the preview is in design mode and does
not show an error. So far the only key that actually does something
is the delete key, which deletes elements. Unfortunately we do not
know which text range is covered by the element we want to delete,
so we delete random chunks of text.

So disable that when we ran into an error.

This partially addresses slint-ui#4872.
  • Loading branch information
hunger committed Mar 18, 2024
1 parent 257a09d commit 0d2b380
Show file tree
Hide file tree
Showing 5 changed files with 158 additions and 98 deletions.
8 changes: 5 additions & 3 deletions tools/lsp/ui/component-list.slint
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ export component ComponentList {
in property <length> preview-area-width;
in property <length> preview-area-height;

pure callback can-drop(string /* component_type */, length /* x */, length /* y */) -> bool;
callback drop(string /* component_type */, length /* x */, length /* y */);
pure callback can-drop(string/* component_type */, length/* x */, length/* y */) -> bool;
callback drop(string/* component_type */, length/* x */, length/* y */);

private property <bool> preview-visible: preview-area-width > 0px && preview-area-height > 0px;

Expand Down Expand Up @@ -51,7 +51,9 @@ export component ComponentList {
enabled: root.preview-visible;
height: name.preferred-height + 10px;
width: 100%;
name := Text { text: ci; }
name := Text {
text: ci;
}

pointer-event(event) => {
if (self.can-drop-here && event.kind == PointerEventKind.up && event.button == PointerEventButton.left) {
Expand Down
8 changes: 5 additions & 3 deletions tools/lsp/ui/diagnostics-overlay.slint
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ export struct Diagnostics {
}

export component DiagnosticsOverlay {
in property<[Diagnostics]> diagnostics;
out property<bool> diagnostics-open: diagnostics.length != 0;
in property <[Diagnostics]> diagnostics;
out property <bool> diagnostics-open: diagnostics.length != 0;

callback show-document(/* url */ string, /* line */ int, /* column */ int);

Expand All @@ -37,7 +37,9 @@ export component DiagnosticsOverlay {
for diag in root.diagnostics: Rectangle {
TouchArea {
mouse-cursor: pointer;
clicked => { root.show_document(diag.url, diag.line, diag.column); }
clicked => {
root.show_document(diag.url, diag.line, diag.column);
}

Text {
width: 100%;
Expand Down
48 changes: 38 additions & 10 deletions tools/lsp/ui/draw-area.slint
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,6 @@ component SelectionFrame {
root.y = y;
root.width = w;
root.height = h;

if done {
root.update-geometry(x, y, w, h);
}
Expand All @@ -80,13 +79,21 @@ component SelectionFrame {
}
}

export enum DrawAreaMode {
uninitialized,
viewing,
designing,
error,
}

export component DrawArea {
in property <[Diagnostics]> diagnostics;
in property <[Selection]> selections;
in property <component-factory> preview-area;
in property <bool> design-mode;

out property <bool> preview-visible: preview-area-container.has-component && !diagnostics.diagnostics-open;
out property <DrawAreaMode> mode: uninitialized;

out property <length> preview-area-position-x: preview-area-container.absolute-position.x;
out property <length> preview-area-position-y: preview-area-container.absolute-position.y;
Expand All @@ -96,7 +103,8 @@ export component DrawArea {
callback select-at(/* x */ length, /* y */ length, /* enter_component? */ bool);
callback select-behind(/* x */ length, /* y */ length, /* enter_component? */ bool, /* reverse */ bool);
callback show-document(/* url */ string, /* line */ int, /* column */ int);
callback reselect(); // Reselect element e.g. after changing the window size (which may move the element)
callback reselect();
// Reselect element e.g. after changing the window size (which may move the element)
callback unselect();
callback selected-element-update-geometry(/* x */ length, /* y */ length, /* width */ length, /* height */ length);
callback selected-element-delete();
Expand All @@ -117,9 +125,11 @@ export component DrawArea {
height: max(scroll-view.visible-height, main-resizer.height + scroll-view.border);

unselect-area := TouchArea {
clicked => { root.unselect(); }
clicked => {
root.unselect();
}
mouse-cursor: crosshair;
enabled <=> root.design-mode;
enabled: root.mode == DrawAreaMode.designing;
}

content-border := Rectangle {
Expand Down Expand Up @@ -147,12 +157,11 @@ export component DrawArea {
width: preview-area-container.width;
height: preview-area-container.height;


// Also make a condition that abuses the fact that the init callback
// is called every time the condition is dirty, to make sure that the size
// is within the bounds.
// Query the preview-area to make sure this is evaluated when it changes
if preview-area-container.has-component && root.preview-area == preview-area-container.component-factory : Rectangle {
if preview-area-container.has-component && root.preview-area == preview-area-container.component-factory: Rectangle {
init => {
preview-area-container.width = clamp(preview-area-container.width, max(preview-area-container.min-width, 16px), max(preview-area-container.max-width, 16px));
preview-area-container.height = clamp(preview-area-container.height, max(preview-area-container.min-height, 16px), max(preview-area-container.max-height, 16px));
Expand Down Expand Up @@ -204,12 +213,12 @@ export component DrawArea {
self.selection-kind = SelectionKind.none;
}
mouse-cursor: crosshair;
enabled <=> root.design-mode;
enabled: root.mode == DrawAreaMode.designing;
}

selection-display-area := Rectangle {
for s in root.selections: SelectionFrame {
interactive: root.design-mode;
interactive: root.mode == DrawAreaMode.designing;
selection: s;
update-geometry(x, y, w, h) => {
root.selected-element-update-geometry(x, y, w, h);
Expand All @@ -219,7 +228,9 @@ export component DrawArea {
root.selected-element-delete();
}

select-behind(x, y, c, f) => { root.select-behind(x, y, c, f); }
select-behind(x, y, c, f) => {
root.select-behind(x, y, c, f);
}
}
}
}
Expand All @@ -231,6 +242,23 @@ export component DrawArea {
width: 100%;
height: 100%;
diagnostics <=> root.diagnostics;
show-document(url, line, column) => { root.show-document(url, line, column); }
show-document(url, line, column) => {
root.show-document(url, line, column);
}
}

states [
uninitialized when !preview-area-container.has-component: {
root.mode: DrawAreaMode.uninitialized;
}
error when diagnostics.diagnostics-open && preview-area-container.has-component: {
root.mode: DrawAreaMode.error;
}
designing when root.design-mode && !diagnostics.diagnostics-open && preview-area-container.has-component: {
root.mode: DrawAreaMode.designing;
}
viewing when !root.design-mode && !diagnostics.diagnostics-open && preview-area-container.has-component: {
root.mode: DrawAreaMode.viewing;
}
]
}
172 changes: 100 additions & 72 deletions tools/lsp/ui/main.slint
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

import { Button, ComboBox, ListView, ScrollView, VerticalBox } from "std-widgets.slint";
import { ComponentList, ComponentListItem } from "component-list.slint";
import { DrawArea, Selection } from "draw-area.slint";
import { DrawArea, DrawAreaMode, Selection } from "draw-area.slint";
import { HeaderBar } from "header-bar.slint";
import { Diagnostics, DiagnosticsOverlay } from "diagnostics-overlay.slint";

Expand Down Expand Up @@ -53,96 +53,124 @@ export component PreviewUi inherits Window {
width: 100%;
height: 100%;
diagnostics <=> root.diagnostics;
show-document(url, line, column) => { root.show-document(url, line, column); }
show-document(url, line, column) => {
root.show-document(url, line, column);
}
}
}
if (show-preview-ui): VerticalLayout {
HeaderBar {
vertical-stretch: 0.0;

height: self.preferred-height;

pick-button := Button {
text: @tr("Design Mode");
checkable: true;
checked <=> root.design-mode;
clicked() => {
key-handler.focus();
if (show-preview-ui): Rectangle {
VerticalLayout {
HeaderBar {
vertical-stretch: 0.0;

height: self.preferred-height;

pick-button := Button {
text: @tr("Design Mode");
checkable: true;
checked <=> root.design-mode;
clicked() => {
key-handler.focus();
}
}
}

Text {
text: @tr("Style:");
vertical-alignment: center;
}
style-select := ComboBox {
model: root.known-styles;
current-value <=> current-style;
selected(value) => {
root.style-changed();
Text {
text: @tr("Style:");
vertical-alignment: center;
}
}

Text {
text: root.status-text;
vertical-alignment: center;
style-select := ComboBox {
model: root.known-styles;
current-value <=> current-style;
selected(value) => {
root.style-changed();
}
}

Text {
text: root.status-text;
vertical-alignment: center;
}
}
}

HorizontalLayout {
left-sidebar := Rectangle {
VerticalBox {
ComponentList {
known-components <=> root.known-components;
preview-area-position-x: draw-area.preview-area-position-x;
preview-area-position-y: draw-area.preview-area-position-y;
preview-area-width: draw-area.preview-area-width;
preview-area-height: draw-area.preview-area-height;

can-drop(c, x, y) => { return root.can-drop(c, x, y); }
drop(c, x, y) => { root.drop(c, x, y); }
HorizontalLayout {
left-sidebar := Rectangle {
VerticalBox {
ComponentList {
known-components <=> root.known-components;
preview-area-position-x: draw-area.preview-area-position-x;
preview-area-position-y: draw-area.preview-area-position-y;
preview-area-width: draw-area.preview-area-width;
preview-area-height: draw-area.preview-area-height;

can-drop(c, x, y) => {
return root.can-drop(c, x, y);
}
drop(c, x, y) => {
root.drop(c, x, y);
}
}
}
}

states [
states [
visible when !pick-button.checked: {
width: 0px;
width: 0px;
}
hidden when pick-button.checked: {
width: root.side-bar-width;
}
]
}

draw-area := DrawArea {
design-mode <=> root.design-mode;
diagnostics <=> root.diagnostics;
preview-area <=> root.preview-area;
selections <=> root.selections;

select-at(x, y, enter_component) => {
root.select-at(x, y, enter_component);
}
hidden when pick-button.checked: {
width: root.side-bar-width;
selected-element-update-geometry(x, y, w, h) => {
root.selected-element-update-geometry(x, y, w, h);
}
]
}
selected-element-delete() => {
root.selected-element-delete();
}
select-behind(x, y, stay_in_file, reverse) => {
root.select-behind(x, y, stay_in_file, reverse);
}
show-document(url, line, column) => {
root.show-document(url, line, column);
}
unselect() => {
root.unselect();
}
reselect() => {
root.reselect();
}
}

draw-area := DrawArea {
design-mode <=> root.design-mode;
diagnostics <=> root.diagnostics;
preview-area <=> root.preview-area;
selections <=> root.selections;

select-at(x, y, enter_component) => { root.select-at(x, y, enter_component); }
selected-element-update-geometry(x, y, w, h) => { root.selected-element-update-geometry(x, y, w, h); }
selected-element-delete() => { root.selected-element-delete(); }
select-behind(x, y, stay_in_file, reverse) => { root.select-behind(x, y, stay_in_file, reverse); }
show-document(url, line, column) => { root.show-document(url, line, column); }
unselect() => { root.unselect(); }
reselect() => { root.reselect(); }
preferred-width: draw-area.preferred-width + root.side-bar-width/* for left-side-bar */;
}

preferred-width: draw-area.preferred-width + root.side-bar-width /* for left-side-bar */;
}
}
}

key-handler := FocusScope {
enabled: root.design-mode;
key-handler := FocusScope {
enabled: draw-area.mode == DrawAreaMode.designing;

key-released(event) => {
if event.text == Key.Delete {
root.selected-element-delete();
return accept;
key-released(event) => {
if event.text == Key.Delete {
// This `if` should not be necessary, but without it
// we do trigger deletion of Elements while errors
// are on screen.
if draw-area.mode == DrawAreaMode.designing {
root.selected-element-delete();
}
return accept;
}
reject
}
}
reject
}
}
}
Loading

0 comments on commit 0d2b380

Please sign in to comment.