Loading files
This file is pinned to the selected release. Download the original to open it in your design tool.
94ec4b8feThis file is pinned to the selected release. Download the original to open it in your design tool.
import {
IconButton,
LineEdit,
MenuItem,
MenuPopup,
ScrollView,
Switch,
} from "../../widgets.slint";
import {
ComponentSignalData,
Data,
EditorCommandSet as Cmd,
} from "../../api.slint";
component HorizontalLine inherits Rectangle {
in property <bool> read-only: false;
height: 1px;
background: {
if read-only {
Data.theme.control-border-disabled
} else {
Data.theme.control-border-disabled
}
};
}
component VerticalLine inherits Rectangle {
in property <bool> read-only: false;
width: 1px;
background: {
if read-only {
Data.theme.control-border-disabled
} else {
Data.theme.control-border-disabled
}
};
}
component ComponentSignalListViewTextCell inherits Rectangle {
in property <string> text;
in property <string> font-family;
in property <length> font-size: 12px;
in property <TextHorizontalAlignment> horizontal-alignment: left;
preferred-width: txt.preferred-width + 10px;
background: Data.theme.window;
txt := Text {
x: 5px;
width: parent.width - 10px;
horizontal-alignment: horizontal-alignment;
vertical-alignment: center;
color: Data.theme.control-text;
font-family: font-family;
font-size: font-size;
text: text;
accessible-role: none;
}
}
export component ComponentSignalListView {
in-out property <[ComponentSignalData]> model;
in property <bool> read-only;
property <length> row-height: 25px;
property <bool> show-ids: self.width > 350px;
property <int> show-forced-net-index: -1;
min-height: min(l.preferred-height, 3 * row-height);
preferred-height: l.preferred-height;
callback edited;
callback focus-rejected;
view := ScrollView {
mouse-drag-pan-enabled: true;
l := VerticalLayout {
padding-right: 8px; // Reserve space for the scrollbar
HorizontalLayout {
VerticalLine {
read-only: read-only;
}
VerticalLayout {
width: self.preferred-width;
HorizontalLine {
read-only: read-only;
}
ComponentSignalListViewTextCell {
height: row-height;
horizontal-alignment: right;
text: "#";
}
for item[index] in model: VerticalLayout {
HorizontalLine {
read-only: read-only;
}
number-cell := ComponentSignalListViewTextCell {
height: row-height;
horizontal-alignment: right;
font-size: 10px;
text: index + 1;
}
}
}
VerticalLine {
read-only: read-only;
}
if show-ids: VerticalLayout {
width: self.preferred-width;
HorizontalLine {
read-only: read-only;
}
ComponentSignalListViewTextCell {
height: row-height;
text: @tr("ID");
}
for item[index] in model: VerticalLayout {
HorizontalLine {
read-only: read-only;
}
id-cell := ComponentSignalListViewTextCell {
height: row-height;
horizontal-alignment: right;
font-family: "Noto Sans Mono";
font-size: 10px;
text: item.id;
}
}
}
if show-ids: VerticalLine {
read-only: read-only;
}
VerticalLayout {
HorizontalLine {
read-only: read-only;
}
name-header := ComponentSignalListViewTextCell {
height: row-height;
text: @tr("Name");
}
for item[index] in model: VerticalLayout {
HorizontalLine {
read-only: read-only;
}
name-edt := LineEdit {
height: row-height;
text: item.name;
validation-error: item.name-error;
read-only: read-only;
frameless: true;
accessible-label: name-header.text;
text-edited(text) => {
model[index].name = text;
}
text-accepted(text) => {
model[index].name = text;
edited();
}
}
}
}
VerticalLine {
read-only: read-only;
}
VerticalLayout {
width: max(self.preferred-width, required-header.preferred-width);
HorizontalLine {
read-only: read-only;
}
required-header := ComponentSignalListViewTextCell {
height: row-height;
text: @tr("Required");
}
for item[index] in model: VerticalLayout {
HorizontalLine {
read-only: read-only;
}
Rectangle {
height: row-height;
background: Data.theme.control;
required-sw := Switch {
width: self.preferred-width;
size: 20px;
status-tip: @tr("If checked, an ERC error is raised when this signal is left unconnected in the schematics");
checked: item.required;
enabled: !read-only;
accessible-label: required-header.text;
toggled(checked) => {
model[index].required = checked;
edited();
}
}
}
}
}
VerticalLine {
read-only: read-only;
}
VerticalLayout {
width: (forced-net-cells-l.preferred-width > 0) ? self.preferred-width : 0;
visible: self.width > 0;
animate width { duration: 150ms; }
HorizontalLine {
read-only: read-only;
}
ComponentSignalListViewTextCell {
height: row-height;
text: @tr("Forced Net Name");
visible: self.width >= self.preferred-width;
}
forced-net-cells-l := VerticalLayout {
for item[index] in model: VerticalLayout {
HorizontalLine {
read-only: read-only;
}
forced-net-edt := LineEdit {
property <bool> request-focus: index == show-forced-net-index;
property <bool> trigger-focus: request-focus && (self.width == self.preferred-width);
height: row-height;
preferred-width: (self.has-focus || request-focus || (!self.text.is-empty)) ? min(200px, root.width * 0.3) : 0;
text: item.forced-net-name;
read-only: read-only;
frameless: true;
changed has-focus => {
if !self.has-focus {
show-forced-net-index = -1;
}
}
changed trigger-focus => {
if trigger-focus {
self.select-all();
self.focus();
}
}
text-edited(text) => {
model[index].forced-net-name = text;
}
text-accepted(text) => {
model[index].forced-net-name = text;
edited();
}
key-pressed(event) => {
if event.text == Key.Escape {
focus-rejected();
return accept;
}
reject
}
}
}
}
}
if forced-net-cells-l.preferred-width > 0: VerticalLine {
read-only: read-only;
}
if !read-only: VerticalLayout {
width: self.preferred-width;
HorizontalLine {
read-only: read-only;
}
ComponentSignalListViewTextCell {
height: row-height;
min-width: row-height;
}
for item[index] in model: VerticalLayout {
HorizontalLine {
read-only: read-only;
}
menu-btn := IconButton {
height: row-height;
background-color: Data.theme.control;
icon-scale: 0.6;
icon: @image-url("../../../../font-awesome/svgs/solid/ellipsis-vertical.svg");
clicked => {
context-menu-item-index = index;
context-menu-x = self.absolute-position.x - root.absolute-position.x;
context-menu-y = self.absolute-position.y - root.absolute-position.y + self.height;
context-menu-popup.show();
}
}
}
}
if !read-only: VerticalLine {
read-only: read-only;
}
}
HorizontalLine {
read-only: read-only;
}
if model.length == 0: HorizontalLayout {
VerticalLine {
read-only: read-only;
}
Rectangle {
height: row-height;
background: Data.theme.control;
no-signals-txt := Text {
width: parent.width - 10px;
horizontal-alignment: left;
font-italic: true;
wrap: word-wrap;
color: Data.theme.control-text-muted;
text: @tr("This package contains no signals (yet).");
}
}
VerticalLine {
read-only: read-only;
}
}
if model.length == 0: HorizontalLine {
read-only: read-only;
}
}
}
property <length> context-menu-x;
property <length> context-menu-y;
property <int> context-menu-item-index;
context-menu-popup := MenuPopup {
x: min(context-menu-x, parent.width - self.width - l.padding-right);
y: context-menu-y;
set-forced-net-name-item := MenuItem {
text: @tr("Set Forced Net Name");
enabled: (model[context-menu-item-index].forced-net-name.is-empty) && (show-forced-net-index != context-menu-item-index);
clicked => {
show-forced-net-index = context-menu-item-index;
}
}
remove-item := MenuItem {
cmd: Cmd.remove;
icon: @image-url("../../../../font-awesome/svgs/solid/trash-can.svg");
shortcuts: "";
clicked => {
model[context-menu-item-index].delete = true;
}
}
}
}