Loading files
9d2aa90beThis file is pinned to the selected release. Download the original to open it in your design tool.
import { ScrollView } from "std-widgets.slint";
import {
Badge,
IconButton,
ListViewItemButton,
PanelHeader,
} from "widgets.slint";
import {
Backend,
BoardAction,
Constants,
Data,
EditorCommandSet as Cmd,
LibraryData,
LibraryElementAction,
ProjectAction,
ProjectData,
SchematicAction,
TabType,
} from "api.slint";
enum ItemType {
schematic,
board,
library,
}
component DocumentsListItem inherits Rectangle {
in property <ItemType> type;
in property <string> text;
in property <image> icon;
in property <bool> selected: false;
in property <length> scrollbar-width;
callback clicked <=> ta.clicked;
callback schematic-action-triggered(a: SchematicAction);
callback board-action-triggered(a: BoardAction);
height: 27px;
background: (ta.has-hover || selected) ? #454545 : transparent;
if selected: Rectangle {
x: 0;
y: 0;
width: 2px;
height: root.height;
background: Constants.librepcb-color;
}
ta := TouchArea {
HorizontalLayout {
padding: 3px;
padding-left: 5px;
padding-right: 5px;
spacing: 5px;
Rectangle {
width: self.height;
Image {
x: 2px;
y: self.x;
width: self.height;
height: parent.height - 2 * self.x;
colorize: txt.color;
image-fit: contain;
source: icon;
accessible-role: none;
}
}
txt := Text {
vertical-alignment: center;
overflow: elide;
text: text;
}
if (ta.has-hover || selected) && (type == ItemType.schematic): rename-btn := ListViewItemButton {
y: (parent.height - self.height) / 2;
height: 18px;
icon: Cmd.sheet-rename.icon;
tooltip: Cmd.sheet-rename.text;
clicked => {
schematic-action-triggered(SchematicAction.rename);
}
}
if (ta.has-hover || selected) && (type == ItemType.schematic): delete-schematic-btn := ListViewItemButton {
y: (parent.height - self.height) / 2;
height: 18px;
icon: @image-url("../../../font-awesome/svgs/solid/trash-can.svg");
tooltip: Cmd.sheet-remove.text;
clicked => {
schematic-action-triggered(SchematicAction.delete);
}
}
if (ta.has-hover || selected) && (type == ItemType.board): open-3d-btn := ListViewItemButton {
y: (parent.height - self.height) / 2;
height: 20px;
icon: @image-url("../../../bootstrap-icons/icons/badge-3d.svg");
tooltip: @tr("Open 3D View");
clicked => {
board-action-triggered(BoardAction.open-3d);
}
}
if (ta.has-hover || selected) && (type == ItemType.board): setup-btn := ListViewItemButton {
y: (parent.height - self.height) / 2;
height: 18px;
icon: @image-url("../../../font-awesome/svgs/solid/sliders.svg");
tooltip: Cmd.board-setup.text;
clicked => {
board-action-triggered(BoardAction.open-setup-dialog);
}
}
if (ta.has-hover || selected) && (type == ItemType.board): copy-btn := ListViewItemButton {
y: (parent.height - self.height) / 2;
height: 18px;
icon: Cmd.board-copy.icon;
tooltip: Cmd.board-copy.text;
clicked => {
board-action-triggered(BoardAction.copy);
}
}
if (ta.has-hover || selected) && (type == ItemType.board): delete-board-btn := ListViewItemButton {
y: (parent.height - self.height) / 2;
height: 18px;
icon: @image-url("../../../font-awesome/svgs/solid/trash-can.svg");
tooltip: Cmd.board-remove.text;
clicked => {
board-action-triggered(BoardAction.delete);
}
}
// Reserve space for scrollbar.
Rectangle {
width: scrollbar-width;
}
}
}
}
component ProjectSection inherits Rectangle {
in property <ProjectData> project;
in property <int> project-index;
in property <length> scrollbar-width;
VerticalLayout {
header-ta := TouchArea {
z: 10; // For the tooltip.
header := PanelHeader {
title: project.name.to-uppercase();
if project.unsaved-changes && project.writable: save-badge := Badge {
y: (parent.height - self.height) / 2;
text: @tr("save").to-lowercase();
text-color: #dddd00;
clickable: true;
clicked => {
Backend.trigger-project(project-index, ProjectAction.save);
}
}
new-sheet-btn := IconButton {
cmd: Cmd.sheet-new;
icon-scale: 60%;
clicked => {
Backend.trigger-project(project-index, ProjectAction.new-sheet);
}
}
new-board-btn := IconButton {
cmd: Cmd.board-new;
icon: @image-url("../../../bootstrap-icons/icons/motherboard.svg");
icon-scale: 60%;
clicked => {
Backend.trigger-project(project-index, ProjectAction.new-board);
}
}
setup-dialog-btn := IconButton {
cmd: Cmd.project-setup;
icon-scale: 60%;
clicked => {
Backend.trigger-project(project-index, ProjectAction.open-setup-dialog);
}
}
close-btn := IconButton {
cmd: Cmd.project-close;
icon-scale: 60%;
clicked => {
Backend.trigger-project(project-index, ProjectAction.close);
}
}
// Reserve space for scrollbar.
Rectangle {
width: scrollbar-width;
}
}
clicked => {
Data.set-current-project(project-index);
}
}
for schematic[index] in project.schematics: schematic-item := DocumentsListItem {
type: ItemType.schematic;
text: schematic.name;
icon: @image-url("../../../font-awesome/svgs/regular/image.svg");
selected: (Data.current-tab.type == TabType.schematic) && (Data.current-schematic-tab.project-index == project-index) && (Data.current-schematic-tab.schematic-index == index);
scrollbar-width: scrollbar-width;
clicked => {
Backend.trigger-schematic(project-index, index, SchematicAction.open);
}
schematic-action-triggered(a) => {
Backend.trigger-schematic(project-index, index, a);
}
}
for board[index] in project.boards: board-item := DocumentsListItem {
type: ItemType.board;
text: board.name;
icon: @image-url("../../../bootstrap-icons/icons/motherboard.svg");
selected: {
if Data.current-tab.type == TabType.board-2d {
(Data.current-board-2d-tab.project-index == project-index) && (Data.current-board-2d-tab.board-index == index)
} else if Data.current-tab.type == TabType.board-3d {
(Data.current-board-3d-tab.project-index == project-index) && (Data.current-board-3d-tab.board-index == index)
} else {
false
}
};
scrollbar-width: scrollbar-width;
clicked => {
Backend.trigger-board(project-index, index, BoardAction.open-2d);
}
board-action-triggered(a) => {
Backend.trigger-board(project-index, index, a);
}
}
}
if project-index == Data.current-project-index: Rectangle {
x: 0;
y: 8px;
width: 1px;
height: parent.height - self.y - 4px;
background: #29d682;
}
}
component LibrarySection inherits Rectangle {
in property <LibraryData> library;
in property <int> library-index;
in property <length> scrollbar-width;
VerticalLayout {
header-ta := TouchArea {
z: 10; // For the tooltip.
header := PanelHeader {
title: library.name.to-uppercase();
close-btn := IconButton {
tooltip: @tr("Close Library");
status-tip: @tr("Close this library and all its opened tabs");
icon: @image-url("../../../font-awesome/svgs/solid/xmark.svg");
icon-scale: 60%;
clicked => {
Backend.trigger-library-element(library.path, LibraryElementAction.close);
}
}
// Reserve space for scrollbar.
Rectangle {
width: scrollbar-width;
}
}
clicked => {
Data.set-current-library(library-index);
}
}
overview-item := DocumentsListItem {
type: ItemType.library;
text: @tr("Library Overview");
icon: @image-url("../../../bootstrap-icons/icons/database.svg");
selected: (Data.current-tab.type == TabType.library) && (Data.current-library-tab.library-index == library-index);
scrollbar-width: scrollbar-width;
clicked => {
Backend.trigger-library-element(library.path, LibraryElementAction.open);
}
}
for section in Data.sections: VerticalLayout {
for tab[idx] in section.component-category-tabs: VerticalLayout {
if (!tab.path.is-empty) && (tab.library-index == library-index): DocumentsListItem {
type: ItemType.library;
text: section.tabs[idx].title;
icon: @image-url("../../../bootstrap-icons/icons/folder.svg");
selected: (Data.current-tab.type == TabType.component-category) && (Data.current-component-category-tab.library-index == library-index) && (Data.current-component-category-tab.path == tab.path);
scrollbar-width: scrollbar-width;
clicked => {
Backend.trigger-library-element(tab.path, LibraryElementAction.open);
}
}
}
for tab[idx] in section.package-category-tabs: VerticalLayout {
if (!tab.path.is-empty) && (tab.library-index == library-index): DocumentsListItem {
type: ItemType.library;
text: section.tabs[idx].title;
icon: @image-url("../../../bootstrap-icons/icons/folder.svg");
selected: (Data.current-tab.type == TabType.package-category) && (Data.current-package-category-tab.library-index == library-index) && (Data.current-package-category-tab.path == tab.path);
scrollbar-width: scrollbar-width;
clicked => {
Backend.trigger-library-element(tab.path, LibraryElementAction.open);
}
}
}
for tab[idx] in section.symbol-tabs: VerticalLayout {
if (!tab.path.is-empty) && (tab.library-index == library-index): DocumentsListItem {
type: ItemType.library;
text: section.tabs[idx].title;
icon: @image-url("../../../../img/library/symbol.png");
selected: (Data.current-tab.type == TabType.symbol) && (Data.current-symbol-tab.library-index == library-index) && (Data.current-symbol-tab.path == tab.path);
scrollbar-width: scrollbar-width;
clicked => {
Backend.trigger-library-element(tab.path, LibraryElementAction.open);
}
}
}
for tab[idx] in section.package-tabs: VerticalLayout {
if (!tab.path.is-empty) && (tab.library-index == library-index): DocumentsListItem {
type: ItemType.library;
text: section.tabs[idx].title;
icon: @image-url("../../../../img/library/package.png");
selected: (Data.current-tab.type == TabType.package) && (Data.current-package-tab.library-index == library-index) && (Data.current-package-tab.path == tab.path);
scrollbar-width: scrollbar-width;
clicked => {
Backend.trigger-library-element(tab.path, LibraryElementAction.open);
}
}
}
for tab[idx] in section.component-tabs: VerticalLayout {
if (!tab.path.is-empty) && (tab.library-index == library-index): DocumentsListItem {
type: ItemType.library;
text: section.tabs[idx].title;
icon: @image-url("../../../bootstrap-icons/icons/cpu.svg");
selected: (Data.current-tab.type == TabType.component) && (Data.current-component-tab.library-index == library-index) && (Data.current-component-tab.path == tab.path);
scrollbar-width: scrollbar-width;
clicked => {
Backend.trigger-library-element(tab.path, LibraryElementAction.open);
}
}
}
for tab[idx] in section.device-tabs: VerticalLayout {
if (!tab.path.is-empty) && (tab.library-index == library-index): DocumentsListItem {
type: ItemType.library;
text: section.tabs[idx].title;
icon: @image-url("../../../../img/library/device.png");
selected: (Data.current-tab.type == TabType.device) && (Data.current-device-tab.library-index == library-index) && (Data.current-device-tab.path == tab.path);
scrollbar-width: scrollbar-width;
clicked => {
Backend.trigger-library-element(tab.path, LibraryElementAction.open);
}
}
}
}
}
if library-index == Data.current-library-index: Rectangle {
x: 0;
y: 8px;
width: 1px;
height: parent.height - self.y - 4px;
background: #29d682;
}
}
export component DocumentsPanel inherits Rectangle {
background: #2a2a2a;
ScrollView {
property <length> scrollbar-width: (self.height < self.viewport-height) ? 7px : 0;
VerticalLayout {
alignment: start;
for project[project-index] in Data.projects: project-item := ProjectSection {
project: project;
project-index: project-index;
scrollbar-width: scrollbar-width;
}
for library[library-index] in Data.libraries: library-item := LibrarySection {
library: library;
library-index: library-index;
scrollbar-width: scrollbar-width;
}
}
}
}