Initial commit
This commit is contained in:
commit
0d37eb04f2
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
/subprojects/blueprint-compiler
|
||||||
|
/node_modules
|
||||||
|
/build
|
||||||
|
/install
|
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
[submodule "gi-types"]
|
||||||
|
path = gi-types
|
||||||
|
url = https://gitlab.gnome.org/BrainBlasted/gi-typescript-definitions.git
|
20
data/com.subgraph.citadel.Realms.data.gresource.xml
Normal file
20
data/com.subgraph.citadel.Realms.data.gresource.xml
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<gresources>
|
||||||
|
<gresource prefix="/com/subgraph/citadel/Realms">
|
||||||
|
<file>ui/RealmListItem.ui</file>
|
||||||
|
<file>ui/RealmRow.ui</file>
|
||||||
|
<file>ui/RealmsView.ui</file>
|
||||||
|
<file>ui/RealmInfo.ui</file>
|
||||||
|
<file>ui/RealmInfoEntry.ui</file>
|
||||||
|
<file>ui/Window.ui</file>
|
||||||
|
<file>ui/ConfigureRealm.ui</file>
|
||||||
|
<file>ui/ConfigureOption.ui</file>
|
||||||
|
<file>ui/ColorSchemeChooser.ui</file>
|
||||||
|
<file>ui/ColorSchemeListItem.ui</file>
|
||||||
|
<file>ui/HelpWindow.ui</file>
|
||||||
|
<file>css/style.css</file>
|
||||||
|
<file>dbus-interfaces/com.subgraph.realms.Manager2.xml</file>
|
||||||
|
<file>dbus-interfaces/com.subgraph.realms.Realm.xml</file>
|
||||||
|
<file>dbus-interfaces/com.subgraph.realms.RealmFS.xml</file>
|
||||||
|
</gresource>
|
||||||
|
</gresources>
|
6
data/com.subgraph.citadel.Realms.desktop
Normal file
6
data/com.subgraph.citadel.Realms.desktop
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
[Desktop Entry]
|
||||||
|
Name=Realms
|
||||||
|
Type=Application
|
||||||
|
Exec=com.subgraph.citadel.Realms
|
||||||
|
Terminal=false
|
||||||
|
Icon=com.subgraph.citadel.Realms
|
10
data/css/style.css
Normal file
10
data/css/style.css
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
|
||||||
|
welcome {
|
||||||
|
border-spacing: 18px;
|
||||||
|
margin: 36px;
|
||||||
|
}
|
||||||
|
|
||||||
|
welcome.big > label {
|
||||||
|
font-size: 1.4em;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
17
data/dbus-interfaces/com.subgraph.realms.Manager2.xml
Normal file
17
data/dbus-interfaces/com.subgraph.realms.Manager2.xml
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
<node>
|
||||||
|
<interface name="com.subgraph.realms.Manager2">
|
||||||
|
<method name="CreateRealm">
|
||||||
|
<arg type="s" name="name" direction="in" />
|
||||||
|
</method>
|
||||||
|
<method name="GetCurrent">
|
||||||
|
<arg type="u" direction="out" />
|
||||||
|
</method>
|
||||||
|
<method name="RealmFromCitadelPid">
|
||||||
|
<arg name="pid" type="u" direction="in" />
|
||||||
|
<arg type="(us)" direction="out" />
|
||||||
|
</method>
|
||||||
|
<method name="GetGlobalConfig">
|
||||||
|
<arg type="a{ss}" direction="out"/>
|
||||||
|
</method>
|
||||||
|
</interface>
|
||||||
|
</node>
|
27
data/dbus-interfaces/com.subgraph.realms.Realm.xml
Normal file
27
data/dbus-interfaces/com.subgraph.realms.Realm.xml
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
<node>
|
||||||
|
<interface name="com.subgraph.realms.Realm">
|
||||||
|
<method name="GetConfig">
|
||||||
|
<arg type="a{ss}" direction="out"/>
|
||||||
|
</method>
|
||||||
|
|
||||||
|
<method name="SetConfig">
|
||||||
|
<arg type="a(ss)" direction="in"/>
|
||||||
|
</method>
|
||||||
|
|
||||||
|
<method name="Start"/>
|
||||||
|
<method name="Stop"/>
|
||||||
|
<method name="Restart"/>
|
||||||
|
<method name="SetCurrent"/>
|
||||||
|
|
||||||
|
<property name="Name" type="s" access="read"/>
|
||||||
|
<property name="Description" type="s" access="read"/>
|
||||||
|
<property name="PidNS" type="t" access="read"/>
|
||||||
|
<property name="RealmFS" type="u" access="read"/>
|
||||||
|
<!--
|
||||||
|
0 = Stopped, 1 = Starting, 2 = Running, 3 = Current, 4 = Stopping,
|
||||||
|
-->
|
||||||
|
<property name="RunStatus" type="u" access="read"/>
|
||||||
|
<property name="IsSystemRealm" type="b" access="read" />
|
||||||
|
<property name="Timestamp" type="t" access="read" />
|
||||||
|
</interface>
|
||||||
|
</node>
|
11
data/dbus-interfaces/com.subgraph.realms.RealmFS.xml
Normal file
11
data/dbus-interfaces/com.subgraph.realms.RealmFS.xml
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
<node>
|
||||||
|
<interface name="com.subgraph.realms.RealmFS">
|
||||||
|
<property name="Name" type="s" access="read" />
|
||||||
|
<property name="Path" type="s" access="read" />
|
||||||
|
<property name="Mountpoint" type="s" access="read" />
|
||||||
|
<property name="Activated" type="b" access="read" />
|
||||||
|
<property name="InUse" type="b" access="read" />
|
||||||
|
<property name="AllocatedSpace" type="t" access="read" />
|
||||||
|
<property name="FreeSpace" type="t" access="read" />
|
||||||
|
</interface>
|
||||||
|
</node>
|
BIN
data/icons/com.subgraph.Realms.png
Normal file
BIN
data/icons/com.subgraph.Realms.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 37 KiB |
30
data/meson.build
Normal file
30
data/meson.build
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
blueprints = custom_target('blueprints',
|
||||||
|
input: files(
|
||||||
|
'ui/Window.blp',
|
||||||
|
'ui/RealmListItem.blp',
|
||||||
|
'ui/RealmRow.blp',
|
||||||
|
'ui/RealmsView.blp',
|
||||||
|
'ui/RealmInfo.blp',
|
||||||
|
'ui/RealmInfoEntry.blp',
|
||||||
|
'ui/ConfigureOption.blp',
|
||||||
|
'ui/ConfigureRealm.blp',
|
||||||
|
'ui/ColorSchemeChooser.blp',
|
||||||
|
'ui/ColorSchemeListItem.blp',
|
||||||
|
'ui/HelpWindow.blp',
|
||||||
|
),
|
||||||
|
output: '.',
|
||||||
|
command: [find_program('blueprint-compiler'), 'batch-compile', '@OUTPUT@', '@CURRENT_SOURCE_DIR@', '@INPUT@'],
|
||||||
|
)
|
||||||
|
|
||||||
|
gnome.compile_resources(
|
||||||
|
APP_ID + '.data',
|
||||||
|
APP_ID + '.data.gresource.xml',
|
||||||
|
gresource_bundle: true,
|
||||||
|
install: true,
|
||||||
|
install_dir: get_option('datadir') / APP_ID,
|
||||||
|
dependencies: blueprints,
|
||||||
|
)
|
||||||
|
|
||||||
|
install_data('icons/com.subgraph.Realms.png', install_dir: join_paths(get_option('datadir'), 'icons/hicolor/512x512/apps')) /icons W [1
|
||||||
|
|
||||||
|
|
35
data/ui/ColorSchemeChooser.blp
Normal file
35
data/ui/ColorSchemeChooser.blp
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
|
||||||
|
using Gtk 4.0;
|
||||||
|
using Adw 1;
|
||||||
|
|
||||||
|
template $ColorSchemeChooser: Adw.NavigationPage {
|
||||||
|
title: "Choose Color Scheme";
|
||||||
|
tag: "realm-colorscheme";
|
||||||
|
Adw.ToolbarView {
|
||||||
|
[top]
|
||||||
|
Adw.HeaderBar {}
|
||||||
|
content : Paned {
|
||||||
|
|
||||||
|
position: 200;
|
||||||
|
|
||||||
|
ScrolledWindow {
|
||||||
|
styles ["sidebar"]
|
||||||
|
|
||||||
|
child: ListView colorList {
|
||||||
|
tab-behavior: item;
|
||||||
|
|
||||||
|
styles ["navigation-sidebar"]
|
||||||
|
factory: Gtk.BuilderListItemFactory {
|
||||||
|
resource: "/com/subgraph/citadel/Realms/ui/ColorSchemeListItem.ui";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
Label previewLabel {
|
||||||
|
use-markup: true;
|
||||||
|
xalign: 0;
|
||||||
|
yalign: 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
13
data/ui/ColorSchemeListItem.blp
Normal file
13
data/ui/ColorSchemeListItem.blp
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
using Gtk 4.0;
|
||||||
|
|
||||||
|
template Gtk.ListItem {
|
||||||
|
focusable: false;
|
||||||
|
child: Gtk.TreeExpander expander {
|
||||||
|
list-row: bind (template.item) as <TreeListRow>;
|
||||||
|
child: Label {
|
||||||
|
hexpand: true;
|
||||||
|
halign: start;
|
||||||
|
label: bind expander.item as <$ColorSchemeNode>.text;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
84
data/ui/ConfigureDialog.blp
Normal file
84
data/ui/ConfigureDialog.blp
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
using Gtk 4.0;
|
||||||
|
using Adw 1;
|
||||||
|
|
||||||
|
ColorDialog colorDialog {
|
||||||
|
title: "Choose a window label color";
|
||||||
|
modal: true;
|
||||||
|
with-alpha: false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template $ConfigureDialog: Adw.Dialog {
|
||||||
|
title: "Configure Realm";
|
||||||
|
content-width: 640;
|
||||||
|
styles ["preferences"]
|
||||||
|
|
||||||
|
child: Adw.NavigationView navigationView {
|
||||||
|
|
||||||
|
Adw.NavigationPage {
|
||||||
|
title: bind template.title;
|
||||||
|
Adw.ToolbarView {
|
||||||
|
[top]
|
||||||
|
Adw.Banner changedBanner {
|
||||||
|
title: "Realm configuration has changed.";
|
||||||
|
button-label: "Apply";
|
||||||
|
button-clicked => $_onApplyClicked();
|
||||||
|
}
|
||||||
|
|
||||||
|
Adw.PreferencesPage {
|
||||||
|
Adw.PreferencesGroup optionsGroup {
|
||||||
|
title: "Options";
|
||||||
|
}
|
||||||
|
Adw.PreferencesGroup {
|
||||||
|
title: "Other";
|
||||||
|
|
||||||
|
Adw.ComboRow overlayCombo {
|
||||||
|
title: "Overlay";
|
||||||
|
model: StringList {
|
||||||
|
strings [
|
||||||
|
"Storage",
|
||||||
|
"TmpFS",
|
||||||
|
"None",
|
||||||
|
]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
Adw.ComboRow realmfsCombo {
|
||||||
|
title: "RealmFS";
|
||||||
|
model: StringList {
|
||||||
|
strings []
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
Adw.ActionRow {
|
||||||
|
title: "Color Scheme";
|
||||||
|
activatable-widget: colorSchemeButton;
|
||||||
|
[suffix]
|
||||||
|
Button colorSchemeButton {
|
||||||
|
can-focus: false;
|
||||||
|
label: "Default Dark";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Adw.ActionRow {
|
||||||
|
title: "Window Label Color";
|
||||||
|
activatable-widget: labelColorButton;
|
||||||
|
|
||||||
|
[suffix]
|
||||||
|
ColorDialogButton labelColorButton {
|
||||||
|
can-focus: false;
|
||||||
|
dialog: colorDialog;
|
||||||
|
rgba: "#ffff00000000";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // Adw.PreferencesGroup ("Other")
|
||||||
|
} // Adw.PreferencesPage
|
||||||
|
} // Adw.ToolbarView
|
||||||
|
} // Adw.NavigationPage
|
||||||
|
|
||||||
|
|
||||||
|
}; // Adw.NavigationView
|
||||||
|
} // $ConfigureDialog
|
||||||
|
|
||||||
|
|
23
data/ui/ConfigureOption.blp
Normal file
23
data/ui/ConfigureOption.blp
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
using Gtk 4.0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
template $ConfigureOption: ListBoxRow {
|
||||||
|
width-request: 100;
|
||||||
|
activatable: false;
|
||||||
|
selectable: false;
|
||||||
|
|
||||||
|
child: Box {
|
||||||
|
margin-bottom: 5;
|
||||||
|
spacing: 30;
|
||||||
|
|
||||||
|
Label name {
|
||||||
|
hexpand: true;
|
||||||
|
halign: start;
|
||||||
|
}
|
||||||
|
|
||||||
|
Switch switch {
|
||||||
|
halign: end;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
*/
|
75
data/ui/ConfigureRealm.blp
Normal file
75
data/ui/ConfigureRealm.blp
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
using Gtk 4.0;
|
||||||
|
using Adw 1;
|
||||||
|
|
||||||
|
|
||||||
|
ColorDialog colorDialog {
|
||||||
|
title: "Choose a window label color";
|
||||||
|
modal: true;
|
||||||
|
with-alpha: false;
|
||||||
|
}
|
||||||
|
|
||||||
|
template $ConfigureRealm: Adw.NavigationPage {
|
||||||
|
title: "Realm Config";
|
||||||
|
tag: "realm-config";
|
||||||
|
|
||||||
|
Adw.ToolbarView {
|
||||||
|
[top]
|
||||||
|
Adw.HeaderBar {}
|
||||||
|
[top]
|
||||||
|
Adw.Banner changedBanner {
|
||||||
|
title: "Realm configuration has changed.";
|
||||||
|
button-label: "Apply";
|
||||||
|
button-clicked => $_onApplyClicked();
|
||||||
|
}
|
||||||
|
|
||||||
|
content: Adw.PreferencesPage {
|
||||||
|
Adw.PreferencesGroup optionsGroup {
|
||||||
|
title: "Options";
|
||||||
|
}
|
||||||
|
|
||||||
|
Adw.PreferencesGroup {
|
||||||
|
title: "Other";
|
||||||
|
Adw.ComboRow overlayCombo {
|
||||||
|
title: "Overlay";
|
||||||
|
model: StringList {
|
||||||
|
strings [
|
||||||
|
"Storage",
|
||||||
|
"TmpFS",
|
||||||
|
"None",
|
||||||
|
]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
Adw.ComboRow realmfsCombo {
|
||||||
|
title: "RealmFS";
|
||||||
|
model: StringList {
|
||||||
|
strings []
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
Adw.ActionRow {
|
||||||
|
title: "Color Scheme";
|
||||||
|
activatable-widget: colorSchemeButton;
|
||||||
|
[suffix]
|
||||||
|
Button colorSchemeButton {
|
||||||
|
can-focus: false;
|
||||||
|
label: "Default Dark";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Adw.ActionRow {
|
||||||
|
title: "Window Label Color";
|
||||||
|
activatable-widget: labelColorButton;
|
||||||
|
|
||||||
|
[suffix]
|
||||||
|
ColorDialogButton labelColorButton {
|
||||||
|
can-focus: false;
|
||||||
|
dialog: colorDialog;
|
||||||
|
rgba: "#ffff00000000";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // Adw.PreferencesGroup ("Other")
|
||||||
|
|
||||||
|
}; // Adw.PreferencesPage
|
||||||
|
} // Adw.ToolbarView
|
||||||
|
} // $ConfigureRealm
|
39
data/ui/HelpWindow.blp
Normal file
39
data/ui/HelpWindow.blp
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
using Gtk 4.0;
|
||||||
|
|
||||||
|
ShortcutsWindow helpWindow {
|
||||||
|
modal: true;
|
||||||
|
can-focus: false;
|
||||||
|
|
||||||
|
ShortcutsSection {
|
||||||
|
ShortcutsGroup {
|
||||||
|
title: "General";
|
||||||
|
|
||||||
|
ShortcutsShortcut {
|
||||||
|
accelerator: "Up k";
|
||||||
|
title: "Previous / Up";
|
||||||
|
}
|
||||||
|
ShortcutsShortcut {
|
||||||
|
accelerator: "Down j";
|
||||||
|
title: "Next / Down";
|
||||||
|
}
|
||||||
|
|
||||||
|
ShortcutsShortcut {
|
||||||
|
accelerator: "h question";
|
||||||
|
title: "Display keyboard help";
|
||||||
|
}
|
||||||
|
ShortcutsShortcut {
|
||||||
|
accelerator: "q";
|
||||||
|
title: "Quit";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ShortcutsGroup {
|
||||||
|
title: "Realm";
|
||||||
|
|
||||||
|
ShortcutsShortcut {
|
||||||
|
accelerator: "c";
|
||||||
|
title: "Configure selected Realm";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
25
data/ui/RealmInfo.blp
Normal file
25
data/ui/RealmInfo.blp
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
using Gtk 4.0;
|
||||||
|
|
||||||
|
template $RealmInfo: ScrolledWindow {
|
||||||
|
Box {
|
||||||
|
orientation: horizontal;
|
||||||
|
margin-bottom: 18;
|
||||||
|
margin-top: 18;
|
||||||
|
margin-start: 18;
|
||||||
|
margin-end: 18;
|
||||||
|
|
||||||
|
Box column {
|
||||||
|
orientation: vertical;
|
||||||
|
spacing: 12;
|
||||||
|
hexpand: true;
|
||||||
|
|
||||||
|
Label columnTitle {
|
||||||
|
label: "Realm";
|
||||||
|
halign: start;
|
||||||
|
|
||||||
|
styles [ "title-2" ]
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
19
data/ui/RealmInfoEntry.blp
Normal file
19
data/ui/RealmInfoEntry.blp
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
using Gtk 4.0;
|
||||||
|
|
||||||
|
template $RealmInfoEntry: Box {
|
||||||
|
orientation: vertical;
|
||||||
|
Label nameLabel {
|
||||||
|
halign: start;
|
||||||
|
styles [
|
||||||
|
"dim-label",
|
||||||
|
"caption",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
Label valueLabel {
|
||||||
|
halign: start;
|
||||||
|
wrap: true;
|
||||||
|
xalign: 0;
|
||||||
|
use-markup: true;
|
||||||
|
}
|
||||||
|
}
|
7
data/ui/RealmListItem.blp
Normal file
7
data/ui/RealmListItem.blp
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
using Gtk 4.0;
|
||||||
|
|
||||||
|
template Gtk.ListItem {
|
||||||
|
child: $RealmRow {
|
||||||
|
realm: bind template.item;
|
||||||
|
};
|
||||||
|
}
|
15
data/ui/RealmRow.blp
Normal file
15
data/ui/RealmRow.blp
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
using Gtk 4.0;
|
||||||
|
|
||||||
|
template $RealmRow {
|
||||||
|
layout-manager: BoxLayout {
|
||||||
|
orientation: horizontal;
|
||||||
|
};
|
||||||
|
Label nameLabel {
|
||||||
|
xalign: 0;
|
||||||
|
label: bind template.realm as <$Realm>.name;
|
||||||
|
styles [
|
||||||
|
"heading",
|
||||||
|
"dim-label",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
39
data/ui/RealmsView.blp
Normal file
39
data/ui/RealmsView.blp
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
using Gtk 4.0;
|
||||||
|
|
||||||
|
template $RealmsView {
|
||||||
|
selected-realm: bind realmsSelection.selected-item;
|
||||||
|
layout-manager: BinLayout {};
|
||||||
|
Frame {
|
||||||
|
width-request: 200;
|
||||||
|
[label]
|
||||||
|
Label {
|
||||||
|
margin-start: 10;
|
||||||
|
margin-top: 20;
|
||||||
|
styles ["title-4"]
|
||||||
|
label: "Realms";
|
||||||
|
}
|
||||||
|
|
||||||
|
ScrolledWindow {
|
||||||
|
child: ListView {
|
||||||
|
styles ["navigation-sidebar"]
|
||||||
|
margin-start: 20;
|
||||||
|
margin-end: 20;
|
||||||
|
margin-top: 10;
|
||||||
|
show-separators: true;
|
||||||
|
focusable: false;
|
||||||
|
can-focus: false;
|
||||||
|
model: SingleSelection realmsSelection {
|
||||||
|
model: FilterListModel hiddenRealmsFilterModel {
|
||||||
|
model: SortListModel {
|
||||||
|
model: $RealmModel{};
|
||||||
|
sorter: CustomSorter realmSorter {};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
factory: BuilderListItemFactory {
|
||||||
|
resource: "/com/subgraph/citadel/Realms/ui/RealmListItem.ui";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
60
data/ui/Window.blp
Normal file
60
data/ui/Window.blp
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
using Gtk 4.0;
|
||||||
|
using Adw 1;
|
||||||
|
|
||||||
|
menu menu {
|
||||||
|
section {
|
||||||
|
item {
|
||||||
|
action: "app.about";
|
||||||
|
label: "About Realms";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
template $RealmsWindow : Adw.ApplicationWindow {
|
||||||
|
default-width: 1000;
|
||||||
|
default-height: 640;
|
||||||
|
|
||||||
|
/* 'width-request and 'height-request' declare minimum window size */
|
||||||
|
width-request: 400;
|
||||||
|
height-request: 300;
|
||||||
|
|
||||||
|
title: "Realms";
|
||||||
|
|
||||||
|
Adw.NavigationView navView {
|
||||||
|
|
||||||
|
Adw.NavigationPage {
|
||||||
|
title: "Realms";
|
||||||
|
tag: "main";
|
||||||
|
Adw.ToolbarView {
|
||||||
|
[top]
|
||||||
|
Adw.HeaderBar header {
|
||||||
|
title-widget: Adw.WindowTitle {
|
||||||
|
title: "Realms";
|
||||||
|
};
|
||||||
|
[end]
|
||||||
|
MenuButton {
|
||||||
|
can-focus: false;
|
||||||
|
primary: true;
|
||||||
|
menu-model: menu;
|
||||||
|
icon-name: "open-menu-symbolic";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
content: Paned {
|
||||||
|
resize-end-child: true;
|
||||||
|
resize-start-child: false;
|
||||||
|
shrink-start-child: false;
|
||||||
|
$RealmsView realmsView {}
|
||||||
|
$RealmInfo {
|
||||||
|
realm: bind realmsView.selected-realm;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$ConfigureRealm configureRealm {
|
||||||
|
navigation-view: navView;
|
||||||
|
colorscheme-chooser: colorChooser;
|
||||||
|
}
|
||||||
|
|
||||||
|
$ColorSchemeChooser colorChooser {}
|
||||||
|
}
|
||||||
|
}
|
1
gi-types
Submodule
1
gi-types
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit dbbaa0527556cd3ce5434c4a5072cd99348eff7a
|
89
js/Application.js
Normal file
89
js/Application.js
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
||||||
|
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
||||||
|
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
||||||
|
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
||||||
|
};
|
||||||
|
var _Application_instances, _a, _Application_setupAccelerators, _Application_setupActions, _Application_onQuit, _Application_onRealmConfig, _Application_onShowHelp, _Application_onAbout;
|
||||||
|
import Adw from 'gi://Adw';
|
||||||
|
import Gtk from 'gi://Gtk?version=4.0';
|
||||||
|
import Gio from 'gi://Gio';
|
||||||
|
import GObject from 'gi://GObject';
|
||||||
|
import './model/RealmManager.js';
|
||||||
|
import './model/Realm.js';
|
||||||
|
import './RealmsView.js';
|
||||||
|
import './RealmRow.js';
|
||||||
|
import './RealmInfo.js';
|
||||||
|
import './RealmModel.js';
|
||||||
|
import './ConfigureRealm.js';
|
||||||
|
import { Window } from './Window.js';
|
||||||
|
export class Application extends Adw.Application {
|
||||||
|
constructor() {
|
||||||
|
super({
|
||||||
|
application_id: 'com.subgraph.citadel.Realms',
|
||||||
|
flags: Gio.ApplicationFlags.DEFAULT_FLAGS,
|
||||||
|
});
|
||||||
|
_Application_instances.add(this);
|
||||||
|
}
|
||||||
|
vfunc_activate() {
|
||||||
|
let { activeWindow } = this;
|
||||||
|
if (!activeWindow) {
|
||||||
|
activeWindow = new Window(this);
|
||||||
|
activeWindow.set_hide_on_close(true);
|
||||||
|
}
|
||||||
|
activeWindow.present();
|
||||||
|
}
|
||||||
|
vfunc_startup() {
|
||||||
|
super.vfunc_startup();
|
||||||
|
__classPrivateFieldGet(this, _Application_instances, "m", _Application_setupActions).call(this);
|
||||||
|
__classPrivateFieldGet(this, _Application_instances, "m", _Application_setupAccelerators).call(this);
|
||||||
|
// this.#loadStyleSheet();
|
||||||
|
const styleManager = Adw.StyleManager.get_default();
|
||||||
|
styleManager.colorScheme = Adw.ColorScheme.FORCE_DARK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_a = Application, _Application_instances = new WeakSet(), _Application_setupAccelerators = function _Application_setupAccelerators() {
|
||||||
|
this.set_accels_for_action('app.quit', ['q']);
|
||||||
|
this.set_accels_for_action('app.realmConfig', ['c']);
|
||||||
|
this.set_accels_for_action('app.showHelp', ['h', 'question']);
|
||||||
|
}, _Application_setupActions = function _Application_setupActions() {
|
||||||
|
this.add_action_entries([
|
||||||
|
// @ts-ignore
|
||||||
|
{ name: 'quit', activate: __classPrivateFieldGet(this, _Application_instances, "m", _Application_onQuit).bind(this) },
|
||||||
|
// @ts-ignore
|
||||||
|
{ name: 'realmConfig', activate: __classPrivateFieldGet(this, _Application_instances, "m", _Application_onRealmConfig).bind(this) },
|
||||||
|
// @ts-ignore
|
||||||
|
{ name: 'showHelp', activate: __classPrivateFieldGet(this, _Application_instances, "m", _Application_onShowHelp).bind(this) },
|
||||||
|
// @ts-ignore
|
||||||
|
{ name: 'about', activate: __classPrivateFieldGet(this, _Application_instances, "m", _Application_onAbout).bind(this) },
|
||||||
|
]);
|
||||||
|
}, _Application_onQuit = function _Application_onQuit() {
|
||||||
|
let { activeWindow } = this;
|
||||||
|
if (activeWindow) {
|
||||||
|
activeWindow.close();
|
||||||
|
}
|
||||||
|
}, _Application_onRealmConfig = function _Application_onRealmConfig() {
|
||||||
|
let { activeWindow } = this;
|
||||||
|
if (activeWindow) {
|
||||||
|
let window = activeWindow;
|
||||||
|
const realm = window.realms_view.selectedRealm;
|
||||||
|
if (realm) {
|
||||||
|
window.configureRealm(realm);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, _Application_onShowHelp = function _Application_onShowHelp() {
|
||||||
|
const help = Gtk.Builder.new_from_resource('/com/subgraph/citadel/Realms/ui/HelpWindow.ui').get_object('helpWindow');
|
||||||
|
help.set_transient_for(this._window);
|
||||||
|
help.present();
|
||||||
|
}, _Application_onAbout = function _Application_onAbout() {
|
||||||
|
const dialog = new Adw.AboutDialog({
|
||||||
|
application_icon: 'face-smile',
|
||||||
|
application_name: 'Realms',
|
||||||
|
developer_name: "Subgraph",
|
||||||
|
});
|
||||||
|
dialog.present(this._window);
|
||||||
|
};
|
||||||
|
(() => {
|
||||||
|
GObject.registerClass({
|
||||||
|
GTypeName: 'RealmsApplication'
|
||||||
|
}, _a);
|
||||||
|
})();
|
176
js/ColorSchemeChooser.js
Normal file
176
js/ColorSchemeChooser.js
Normal file
@ -0,0 +1,176 @@
|
|||||||
|
var _a;
|
||||||
|
import Adw from 'gi://Adw';
|
||||||
|
import GObject from 'gi://GObject';
|
||||||
|
import GLib from 'gi://GLib';
|
||||||
|
import Gdk from 'gi://Gdk?version=4.0';
|
||||||
|
import Gtk from 'gi://Gtk?version=4.0';
|
||||||
|
import { ColorSchemeModel } from './ColorSchemeModel.js';
|
||||||
|
class PreviewRenderer {
|
||||||
|
constructor(theme) {
|
||||||
|
this.theme = theme;
|
||||||
|
this.buffer = '';
|
||||||
|
}
|
||||||
|
colorAttrib(name, color) {
|
||||||
|
this.buffer += ` ${name}='${color}'`;
|
||||||
|
}
|
||||||
|
colorSpan(fg, bg = null) {
|
||||||
|
this.buffer += '<span';
|
||||||
|
if (fg) {
|
||||||
|
this.colorAttrib("foreground", fg);
|
||||||
|
}
|
||||||
|
if (bg) {
|
||||||
|
this.colorAttrib("background", bg);
|
||||||
|
}
|
||||||
|
this.buffer += ">";
|
||||||
|
}
|
||||||
|
endSpan() {
|
||||||
|
this.buffer += '</span>';
|
||||||
|
}
|
||||||
|
nl() {
|
||||||
|
this.buffer += ' \n ';
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
print(idx, text) {
|
||||||
|
let s = GLib.markup_escape_text(text, text.length);
|
||||||
|
let c = this.theme.terminal_palette_color(idx);
|
||||||
|
this.colorSpan(c);
|
||||||
|
this.buffer += s;
|
||||||
|
this.endSpan();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
vtype(text) {
|
||||||
|
return this.print(3, text);
|
||||||
|
}
|
||||||
|
konst(text) {
|
||||||
|
return this.print(1, text);
|
||||||
|
}
|
||||||
|
func(text) {
|
||||||
|
return this.print(4, text);
|
||||||
|
}
|
||||||
|
string(text) {
|
||||||
|
return this.print(2, text);
|
||||||
|
}
|
||||||
|
keyword(text) {
|
||||||
|
return this.print(5, text);
|
||||||
|
}
|
||||||
|
comment(text) {
|
||||||
|
return this.print(8, text);
|
||||||
|
}
|
||||||
|
text(text) {
|
||||||
|
let color = this.theme.terminal_foreground();
|
||||||
|
this.colorSpan(color);
|
||||||
|
this.buffer += text;
|
||||||
|
this.endSpan();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
renderPreview() {
|
||||||
|
let name = this.theme.name;
|
||||||
|
this.nl()
|
||||||
|
.comment('/**').nl()
|
||||||
|
.comment(' * An example of how this color scheme').nl()
|
||||||
|
.comment(' * might look in a text editor with syntax').nl()
|
||||||
|
.comment(' * highlighting.').nl()
|
||||||
|
.comment(' */').nl()
|
||||||
|
.nl()
|
||||||
|
.func('#include ').string('<stdio.h>').nl()
|
||||||
|
.func('#include ').string('<stdlib.h>').nl()
|
||||||
|
.nl()
|
||||||
|
.vtype('static char').text(' theme[] = ').string(`"${name}"`).text(';').nl()
|
||||||
|
.nl()
|
||||||
|
.vtype('int').text(' main(').vtype('int').text(' argc, ').vtype('char').text(' **argv) {').nl()
|
||||||
|
.text(' printf(').string('"Hello, ').keyword('%s').text('!').keyword('\\n').string('"').text(', theme);').nl()
|
||||||
|
.text(' exit(').konst('0').text(');').nl()
|
||||||
|
.text('}')
|
||||||
|
.nl();
|
||||||
|
return this.buffer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export class ColorSchemeChooser extends Adw.NavigationPage {
|
||||||
|
addExpandToggleShortcut(keyval) {
|
||||||
|
let trigger = Gtk.KeyvalTrigger.new(keyval, Gdk.ModifierType.NO_MODIFIER_MASK);
|
||||||
|
let action = Gtk.CallbackAction.new((expander) => expander.activate_action('listitem.toggle-expand', null));
|
||||||
|
Gtk.TreeExpander.add_shortcut(Gtk.Shortcut.new(trigger, action));
|
||||||
|
}
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.model = new ColorSchemeModel();
|
||||||
|
this._previewLabel.add_css_class("preview");
|
||||||
|
this.css_provider = new Gtk.CssProvider();
|
||||||
|
const display = Gdk.Display.get_default();
|
||||||
|
if (display) {
|
||||||
|
Gtk.StyleContext.add_provider_for_display(display, this.css_provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION);
|
||||||
|
}
|
||||||
|
this.addExpandToggleShortcut(Gdk.KEY_space);
|
||||||
|
this.addExpandToggleShortcut(Gdk.KEY_l);
|
||||||
|
this._colorList.connect('activate', () => {
|
||||||
|
this.previewSelectedTheme();
|
||||||
|
});
|
||||||
|
this._colorList.single_click_activate = true;
|
||||||
|
this._colorList.model = this.model.selection;
|
||||||
|
const keyController = new Gtk.EventControllerKey();
|
||||||
|
keyController.connect('key-pressed', (_, keyval) => {
|
||||||
|
switch (keyval) {
|
||||||
|
case Gdk.KEY_j:
|
||||||
|
case Gdk.KEY_Down:
|
||||||
|
this.nextScheme();
|
||||||
|
break;
|
||||||
|
case Gdk.KEY_k:
|
||||||
|
case Gdk.KEY_Up:
|
||||||
|
this.prevScheme();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this._colorList.add_controller(keyController);
|
||||||
|
}
|
||||||
|
nextScheme() {
|
||||||
|
let pos = this.model.changeSelected(1);
|
||||||
|
if (pos) {
|
||||||
|
this._colorList.scroll_to(pos, Gtk.ListScrollFlags.SELECT | Gtk.ListScrollFlags.FOCUS, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
prevScheme() {
|
||||||
|
let pos = this.model.changeSelected(-1);
|
||||||
|
if (pos) {
|
||||||
|
this._colorList.scroll_to(pos, Gtk.ListScrollFlags.SELECT | Gtk.ListScrollFlags.FOCUS, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
selectTheme(id) {
|
||||||
|
const DEFAULT_THEME = '3024';
|
||||||
|
let row = this.model.searchId(id !== null && id !== void 0 ? id : DEFAULT_THEME);
|
||||||
|
if (row) {
|
||||||
|
let pos = row.get_position();
|
||||||
|
this.model.selectPosition(pos);
|
||||||
|
this._colorList.scroll_to(pos, Gtk.ListScrollFlags.SELECT | Gtk.ListScrollFlags.FOCUS, null);
|
||||||
|
this.previewSelectedTheme();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
getSelectedTheme() {
|
||||||
|
return this.model.selectedTheme();
|
||||||
|
}
|
||||||
|
previewSelectedTheme() {
|
||||||
|
let theme = this.model.selectedTheme();
|
||||||
|
if (theme) {
|
||||||
|
this.setBackgroundColor(theme);
|
||||||
|
let renderer = new PreviewRenderer(theme);
|
||||||
|
// @ts-ignore
|
||||||
|
this._previewLabel.label = renderer.renderPreview();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setBackgroundColor(theme) {
|
||||||
|
let css = `
|
||||||
|
label.preview {
|
||||||
|
background-color: ${theme.terminal_background()};
|
||||||
|
font-family: monospace;
|
||||||
|
font-size: 14pt;
|
||||||
|
}`;
|
||||||
|
this.css_provider.load_from_string(css);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_a = ColorSchemeChooser;
|
||||||
|
(() => {
|
||||||
|
GObject.registerClass({
|
||||||
|
GTypeName: 'ColorSchemeChooser',
|
||||||
|
Template: 'resource:///com/subgraph/citadel/Realms/ui/ColorSchemeChooser.ui',
|
||||||
|
InternalChildren: ['colorList', 'previewLabel'],
|
||||||
|
}, _a);
|
||||||
|
})();
|
147
js/ColorSchemeModel.js
Normal file
147
js/ColorSchemeModel.js
Normal file
@ -0,0 +1,147 @@
|
|||||||
|
var _a;
|
||||||
|
import GObject from 'gi://GObject';
|
||||||
|
import Gio from 'gi://Gio';
|
||||||
|
import Gtk from 'gi://Gtk?version=4.0';
|
||||||
|
import { Base16Theme } from './model/Base16Themes.js';
|
||||||
|
class ModelBuilder {
|
||||||
|
constructor() {
|
||||||
|
this.CATEGORIES = [
|
||||||
|
['atelier', 'Atelier'],
|
||||||
|
['black-metal', 'Black Metal'],
|
||||||
|
['brushtrees', 'Brush Trees'],
|
||||||
|
['classic', 'Classic'],
|
||||||
|
['default', 'Default'],
|
||||||
|
['google', 'Google'],
|
||||||
|
['grayscale', 'Grayscale'],
|
||||||
|
['gruvbox', 'Gruvbox'],
|
||||||
|
['harmonic', 'Harmonic'],
|
||||||
|
['ia', 'iA'],
|
||||||
|
['material', 'Material'],
|
||||||
|
['papercolor', 'PaperColor'],
|
||||||
|
['solarized', 'Solarized'],
|
||||||
|
['summerfruit', 'Summerfruit'],
|
||||||
|
['tomorrow', 'Tomorrow'],
|
||||||
|
['unikitty', 'Unikitty'],
|
||||||
|
];
|
||||||
|
this.currentCategory = null;
|
||||||
|
this.storeModel = new Gio.ListStore(ColorSchemeNode);
|
||||||
|
}
|
||||||
|
matchesCategory(theme) {
|
||||||
|
return (this.CATEGORIES.length > 0 && theme.id.startsWith(this.CATEGORIES[0][0]));
|
||||||
|
}
|
||||||
|
appendCurrentCategory() {
|
||||||
|
if (this.currentCategory) {
|
||||||
|
this.storeModel.append(this.currentCategory);
|
||||||
|
this.currentCategory = null;
|
||||||
|
this.CATEGORIES.shift();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
addToCategory(theme) {
|
||||||
|
if (!this.currentCategory) {
|
||||||
|
this.currentCategory = new ColorSchemeNode(this.CATEGORIES[0][1]);
|
||||||
|
}
|
||||||
|
this.currentCategory.addChild(new ColorSchemeNode(theme.name, theme));
|
||||||
|
}
|
||||||
|
addTheme(theme) {
|
||||||
|
if (this.matchesCategory(theme)) {
|
||||||
|
this.addToCategory(theme);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (this.currentCategory) {
|
||||||
|
this.appendCurrentCategory();
|
||||||
|
}
|
||||||
|
this.storeModel.append(new ColorSchemeNode(theme.name, theme));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static buildTreeModel() {
|
||||||
|
let builder = new ModelBuilder();
|
||||||
|
Base16Theme.THEME_LIST.forEach(theme => builder.addTheme(theme));
|
||||||
|
return Gtk.TreeListModel.new(builder.storeModel, false, false, item => item.child_model);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export class ColorSchemeNode extends GObject.Object {
|
||||||
|
constructor(text, theme = null) {
|
||||||
|
super();
|
||||||
|
this._text = text;
|
||||||
|
this.theme = theme;
|
||||||
|
this.child_model = null;
|
||||||
|
}
|
||||||
|
get text() {
|
||||||
|
return this._text;
|
||||||
|
}
|
||||||
|
addChild(child) {
|
||||||
|
if (this.child_model === null) {
|
||||||
|
this.child_model = new Gio.ListStore(_a);
|
||||||
|
}
|
||||||
|
this.child_model.append(child);
|
||||||
|
}
|
||||||
|
matchesId(id) {
|
||||||
|
return this.theme !== null && this.theme.id === id;
|
||||||
|
}
|
||||||
|
searchChildren(id) {
|
||||||
|
if (this.child_model) {
|
||||||
|
for (let i = 0; i < this.child_model.n_items; i++) {
|
||||||
|
let node = this.child_model.get_item(i);
|
||||||
|
if (node.matchesId(id)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_a = ColorSchemeNode;
|
||||||
|
(() => {
|
||||||
|
GObject.registerClass({
|
||||||
|
GTypeName: 'ColorSchemeNode',
|
||||||
|
Properties: {
|
||||||
|
'text': GObject.ParamSpec.string('text', '', '', GObject.ParamFlags.READWRITE, ''),
|
||||||
|
}
|
||||||
|
}, _a);
|
||||||
|
})();
|
||||||
|
export class ColorSchemeModel {
|
||||||
|
constructor() {
|
||||||
|
this.treeModel = ModelBuilder.buildTreeModel();
|
||||||
|
this.selection = Gtk.SingleSelection.new(this.treeModel);
|
||||||
|
}
|
||||||
|
selectedTheme() {
|
||||||
|
// @ts-ignore
|
||||||
|
let item = this.selection.selected_item.item;
|
||||||
|
return item === null || item === void 0 ? void 0 : item.theme;
|
||||||
|
}
|
||||||
|
changeSelected(offset) {
|
||||||
|
const n_items = this.selection.n_items;
|
||||||
|
if (n_items <= 1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const pos = this.selection.selected;
|
||||||
|
if (pos == Gtk.INVALID_LIST_POSITION) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const newPos = pos + offset;
|
||||||
|
if (newPos < 0 || newPos >= n_items) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.selection.selected = newPos;
|
||||||
|
return newPos;
|
||||||
|
}
|
||||||
|
selectPosition(pos) {
|
||||||
|
this.selection.selected = pos;
|
||||||
|
}
|
||||||
|
searchId(id, from = 0) {
|
||||||
|
for (let i = from; i < this.treeModel.n_items; i++) {
|
||||||
|
let row = this.treeModel.get_row(i);
|
||||||
|
let item = row === null || row === void 0 ? void 0 : row.item;
|
||||||
|
if (item && item.matchesId(id)) {
|
||||||
|
return row;
|
||||||
|
}
|
||||||
|
if (item.searchChildren(id)) {
|
||||||
|
row === null || row === void 0 ? void 0 : row.set_expanded(true);
|
||||||
|
if (from === 0) {
|
||||||
|
return this.searchId(id, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
151
js/ConfigureRealm.js
Normal file
151
js/ConfigureRealm.js
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
var _a;
|
||||||
|
import GObject from 'gi://GObject';
|
||||||
|
import Gdk from 'gi://Gdk?version=4.0';
|
||||||
|
import Gtk from 'gi://Gtk?version=4.0';
|
||||||
|
import Adw from 'gi://Adw';
|
||||||
|
import { BoolOptionData } from './model/RealmConfig.js';
|
||||||
|
import { Base16Theme } from './model/Base16Themes.js';
|
||||||
|
import { RealmManager } from './model/RealmManager.js';
|
||||||
|
import { ColorSchemeChooser } from './ColorSchemeChooser.js';
|
||||||
|
class OptionState {
|
||||||
|
constructor(row) {
|
||||||
|
this.value = null;
|
||||||
|
this.row = row;
|
||||||
|
}
|
||||||
|
initValue(value) {
|
||||||
|
this.value = value;
|
||||||
|
this.originalValue = value;
|
||||||
|
this.row.active = value;
|
||||||
|
}
|
||||||
|
/** @param {any} value */
|
||||||
|
setValue(value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
hasChanged() {
|
||||||
|
return this.value !== this.originalValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export class ConfigureRealm extends Adw.NavigationPage {
|
||||||
|
constructor() {
|
||||||
|
var _b, _c;
|
||||||
|
super();
|
||||||
|
this.realm = null;
|
||||||
|
this.optionState = new Map();
|
||||||
|
this.theme = Base16Theme.lookup('default-dark');
|
||||||
|
this._addOptions();
|
||||||
|
const keyController = new Gtk.EventControllerKey();
|
||||||
|
keyController.connect('key-pressed', (_, keyval) => {
|
||||||
|
if (keyval === Gdk.KEY_j) {
|
||||||
|
this.vfunc_move_focus(Gtk.DirectionType.TAB_FORWARD);
|
||||||
|
}
|
||||||
|
else if (keyval === Gdk.KEY_k) {
|
||||||
|
this.vfunc_move_focus(Gtk.DirectionType.TAB_BACKWARD);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.add_controller(keyController);
|
||||||
|
(_b = this._labelColorButton) === null || _b === void 0 ? void 0 : _b.connect('notify::rgba', () => this._scanChanges());
|
||||||
|
(_c = this._colorSchemeButton) === null || _c === void 0 ? void 0 : _c.connect('clicked', () => {
|
||||||
|
var _b;
|
||||||
|
(_b = this.navigationView) === null || _b === void 0 ? void 0 : _b.push_by_tag('realm-colorscheme');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
get colorschemeChooser() {
|
||||||
|
return this._colorschemeChooser;
|
||||||
|
}
|
||||||
|
set colorschemeChooser(val) {
|
||||||
|
this._colorschemeChooser = val;
|
||||||
|
}
|
||||||
|
set navigationView(val) {
|
||||||
|
var _b;
|
||||||
|
this._navigationView = val;
|
||||||
|
(_b = this._navigationView) === null || _b === void 0 ? void 0 : _b.connect('popped', (_view, page) => {
|
||||||
|
if (page === this.colorschemeChooser) {
|
||||||
|
let theme = this.colorschemeChooser.getSelectedTheme();
|
||||||
|
if (theme && this._colorSchemeButton) {
|
||||||
|
this.theme = theme;
|
||||||
|
this._colorSchemeButton.label = this.theme.name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
get navigationView() {
|
||||||
|
return this._navigationView;
|
||||||
|
}
|
||||||
|
configure(realm) {
|
||||||
|
this.realm = realm;
|
||||||
|
this.set_title(`Configure realm-${realm.name}`);
|
||||||
|
this._setOptions(realm);
|
||||||
|
}
|
||||||
|
_setOptions(realm) {
|
||||||
|
var _b;
|
||||||
|
let config = realm.config;
|
||||||
|
this.optionState.forEach((op, name) => {
|
||||||
|
let v = config.get_bool(name);
|
||||||
|
op.initValue(v);
|
||||||
|
});
|
||||||
|
let scheme = realm.config.get_colorscheme();
|
||||||
|
this.theme = Base16Theme.lookup(scheme);
|
||||||
|
if (this.theme && this._colorSchemeButton) {
|
||||||
|
this._colorSchemeButton.label = this.theme.name;
|
||||||
|
(_b = this.colorschemeChooser) === null || _b === void 0 ? void 0 : _b.selectTheme(this.theme.id);
|
||||||
|
}
|
||||||
|
let realmfs_list = RealmManager.instance().realmfsList();
|
||||||
|
// @ts-ignore
|
||||||
|
let model = this._realmfsCombo.model;
|
||||||
|
if (model.n_items > 0) {
|
||||||
|
model.splice(0, model.n_items, []);
|
||||||
|
}
|
||||||
|
realmfs_list.forEach(realmfs => model.append(realmfs.name));
|
||||||
|
let labelColor = realm.getLabelColor();
|
||||||
|
this._labelColorButton.rgba = labelColor;
|
||||||
|
this._scanChanges();
|
||||||
|
}
|
||||||
|
_addOptions() {
|
||||||
|
BoolOptionData.allOptions().forEach(option => {
|
||||||
|
let row = new Adw.SwitchRow({
|
||||||
|
title: option.description,
|
||||||
|
});
|
||||||
|
if (option.tooltip.length > 0) {
|
||||||
|
row.tooltipMarkup = option.tooltip;
|
||||||
|
}
|
||||||
|
let state = new OptionState(row);
|
||||||
|
this.optionState.set(option.name, state);
|
||||||
|
row.connect("notify::active", () => {
|
||||||
|
state.setValue(row.active);
|
||||||
|
this._scanChanges();
|
||||||
|
});
|
||||||
|
this._optionsGroup.add(row);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
_scanChanges() {
|
||||||
|
var _b;
|
||||||
|
let changed = false;
|
||||||
|
this.optionState.forEach(op => {
|
||||||
|
if (op.hasChanged()) {
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
let labelColor = (_b = this.realm) === null || _b === void 0 ? void 0 : _b.getLabelColor();
|
||||||
|
if (labelColor) {
|
||||||
|
if (!this._labelColorButton.rgba.equal(labelColor)) {
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this._changedBanner.set_revealed(changed);
|
||||||
|
}
|
||||||
|
_onApplyClicked() {
|
||||||
|
print("clikkk");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_a = ConfigureRealm;
|
||||||
|
(() => {
|
||||||
|
GObject.registerClass({
|
||||||
|
GTypeName: "ConfigureRealm",
|
||||||
|
Template: 'resource:///com/subgraph/citadel/Realms/ui/ConfigureRealm.ui',
|
||||||
|
InternalChildren: ['optionsGroup', 'changedBanner', 'overlayCombo', 'realmfsCombo', 'colorSchemeButton', 'labelColorButton'],
|
||||||
|
Properties: {
|
||||||
|
'navigation-view': GObject.ParamSpec.object('navigation-view', '', '', GObject.ParamFlags.READWRITE, Adw.NavigationView),
|
||||||
|
'colorscheme-chooser': GObject.ParamSpec.object('colorscheme-chooser', '', '', GObject.ParamFlags.READWRITE, ColorSchemeChooser),
|
||||||
|
}
|
||||||
|
}, _a);
|
||||||
|
})();
|
131
js/RealmInfo.js
Normal file
131
js/RealmInfo.js
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
var _a;
|
||||||
|
import GObject from 'gi://GObject';
|
||||||
|
import Gtk from 'gi://Gtk?version=4.0';
|
||||||
|
import { Realm } from "./model/Realm.js";
|
||||||
|
import { RealmInfoEntry } from './RealmInfoEntry.js';
|
||||||
|
const Sections = {
|
||||||
|
STATUS: 'Status',
|
||||||
|
OPTIONS: 'Options',
|
||||||
|
REALMFS: 'RealmFS',
|
||||||
|
MOUNTPOINT: 'RealmFS Mountpoint',
|
||||||
|
};
|
||||||
|
export class RealmInfo extends Gtk.ScrolledWindow {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this._buffer = "";
|
||||||
|
this._changeId = 0;
|
||||||
|
this._realm = null;
|
||||||
|
this._entries = new Map();
|
||||||
|
this._addEntries({
|
||||||
|
left: [
|
||||||
|
Sections.STATUS,
|
||||||
|
Sections.REALMFS,
|
||||||
|
Sections.MOUNTPOINT,
|
||||||
|
Sections.OPTIONS,
|
||||||
|
],
|
||||||
|
right: []
|
||||||
|
});
|
||||||
|
}
|
||||||
|
_addEntries(labels) {
|
||||||
|
let addSectionEntries = (section, entries) => {
|
||||||
|
entries.forEach(name => {
|
||||||
|
let entry = new RealmInfoEntry(name);
|
||||||
|
this._entries.set(name, entry);
|
||||||
|
section.append(entry);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
addSectionEntries(this._column, labels['left']);
|
||||||
|
}
|
||||||
|
get realm() {
|
||||||
|
return this._realm;
|
||||||
|
}
|
||||||
|
set realm(value) {
|
||||||
|
if (this.realm === value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (this._realm) {
|
||||||
|
this._realm.disconnect(this._changeId);
|
||||||
|
}
|
||||||
|
this._realm = value;
|
||||||
|
if (this._realm) {
|
||||||
|
this._changeId = this._realm.connect('changed', () => {
|
||||||
|
this.displayRealm();
|
||||||
|
});
|
||||||
|
this.displayRealm();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setEntry(name, value) {
|
||||||
|
let entry = this._entries.get(name);
|
||||||
|
if (entry) {
|
||||||
|
entry.setValue(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setEntryVisible(name, isVisible = true) {
|
||||||
|
let entry = this._entries.get(name);
|
||||||
|
if (entry) {
|
||||||
|
entry.set_visible(isVisible);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
displayConfig() {
|
||||||
|
var _b;
|
||||||
|
let config = (_b = this._realm) === null || _b === void 0 ? void 0 : _b.config;
|
||||||
|
if (config) {
|
||||||
|
let enabled_default = config.enabled_bool_option_labels(true);
|
||||||
|
let enabled = config.enabled_bool_option_labels(false);
|
||||||
|
let buffer = enabled_default.join(' ');
|
||||||
|
buffer += '\n';
|
||||||
|
buffer += enabled.map(s => `<u>${s}</u>`)
|
||||||
|
.join(' ');
|
||||||
|
this.setEntry(Sections.OPTIONS, buffer);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.setEntry(Sections.OPTIONS, '');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
displayRealmFS() {
|
||||||
|
var _b;
|
||||||
|
let realmfs = (_b = this._realm) === null || _b === void 0 ? void 0 : _b.realmfs;
|
||||||
|
if (realmfs) {
|
||||||
|
this.setEntryVisible(Sections.REALMFS);
|
||||||
|
this.setEntry(Sections.REALMFS, `${realmfs.name}-realmfs.img`);
|
||||||
|
if (realmfs.activated) {
|
||||||
|
this.setEntryVisible(Sections.MOUNTPOINT);
|
||||||
|
this.setEntry(Sections.MOUNTPOINT, realmfs.mountpoint);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.setEntryVisible(Sections.MOUNTPOINT, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.setEntryVisible(Sections.REALMFS, false);
|
||||||
|
this.setEntryVisible(Sections.MOUNTPOINT, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
displayRealm() {
|
||||||
|
if (this._realm) {
|
||||||
|
this._columnTitle.label = `Realm ${this._realm.name}`;
|
||||||
|
if (this._realm.is_running()) {
|
||||||
|
this.setEntry("Status", "Running");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.setEntry("Status", "Stopped");
|
||||||
|
}
|
||||||
|
this.displayConfig();
|
||||||
|
this.displayRealmFS();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_a = RealmInfo;
|
||||||
|
(() => {
|
||||||
|
GObject.registerClass({
|
||||||
|
GTypeName: "RealmInfo",
|
||||||
|
Template: 'resource:///com/subgraph/citadel/Realms/ui/RealmInfo.ui',
|
||||||
|
Properties: {
|
||||||
|
'realm': GObject.ParamSpec.object('realm', '', '', GObject.ParamFlags.READWRITE, Realm),
|
||||||
|
},
|
||||||
|
InternalChildren: [
|
||||||
|
'column',
|
||||||
|
'columnTitle',
|
||||||
|
]
|
||||||
|
}, _a);
|
||||||
|
})();
|
20
js/RealmInfoEntry.js
Normal file
20
js/RealmInfoEntry.js
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
var _a;
|
||||||
|
import GObject from 'gi://GObject';
|
||||||
|
import Gtk from 'gi://Gtk?version=4.0';
|
||||||
|
export class RealmInfoEntry extends Gtk.Box {
|
||||||
|
constructor(name) {
|
||||||
|
super();
|
||||||
|
this._nameLabel.label = name;
|
||||||
|
}
|
||||||
|
setValue(value) {
|
||||||
|
this._valueLabel.label = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_a = RealmInfoEntry;
|
||||||
|
(() => {
|
||||||
|
GObject.registerClass({
|
||||||
|
GTypeName: "RealmInfoEntry",
|
||||||
|
Template: 'resource:///com/subgraph/citadel/Realms/ui/RealmInfoEntry.ui',
|
||||||
|
InternalChildren: ['nameLabel', 'valueLabel']
|
||||||
|
}, _a);
|
||||||
|
})();
|
42
js/RealmModel.js
Normal file
42
js/RealmModel.js
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
var _a;
|
||||||
|
import Gio from 'gi://Gio';
|
||||||
|
import GObject from 'gi://GObject';
|
||||||
|
import { Realm } from './model/Realm.js';
|
||||||
|
import { RealmManager } from "./model/RealmManager.js";
|
||||||
|
export class RealmModel extends GObject.Object {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this._realms = [];
|
||||||
|
this._realmManager = RealmManager.instance();
|
||||||
|
this._realmManager.connect('realm-added', (_manager, realm) => {
|
||||||
|
let pos = this._realms.length;
|
||||||
|
this._realms.push(realm);
|
||||||
|
// @ts-ignore
|
||||||
|
this.items_changed(pos, 0, 1);
|
||||||
|
});
|
||||||
|
this._realmManager.connect('realm-removed', (_manager, realm) => {
|
||||||
|
let pos = this._realms.findIndex(r => r === realm);
|
||||||
|
if (pos >= 0) {
|
||||||
|
this._realms.splice(pos, 1);
|
||||||
|
// @ts-ignore
|
||||||
|
this.items_changed(pos, 1, 0);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
vfunc_get_item_type() {
|
||||||
|
return Realm;
|
||||||
|
}
|
||||||
|
vfunc_get_item(position) {
|
||||||
|
return this._realms[position] || null;
|
||||||
|
}
|
||||||
|
vfunc_get_n_items() {
|
||||||
|
return this._realms.length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_a = RealmModel;
|
||||||
|
(() => {
|
||||||
|
GObject.registerClass({
|
||||||
|
GTypeName: 'RealmModel',
|
||||||
|
Implements: [Gio.ListModel],
|
||||||
|
}, _a);
|
||||||
|
})();
|
51
js/RealmRow.js
Normal file
51
js/RealmRow.js
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
var _a;
|
||||||
|
import GObject from 'gi://GObject';
|
||||||
|
import Gtk from 'gi://Gtk?version=4.0';
|
||||||
|
import { Realm } from './model/Realm.js';
|
||||||
|
export class RealmRow extends Gtk.Widget {
|
||||||
|
constructor() {
|
||||||
|
super(...arguments);
|
||||||
|
this._notifyId = 0;
|
||||||
|
}
|
||||||
|
get realm() {
|
||||||
|
if (this._realm === undefined) {
|
||||||
|
this._realm = null;
|
||||||
|
}
|
||||||
|
return this._realm;
|
||||||
|
}
|
||||||
|
set realm(value) {
|
||||||
|
if (this.realm === value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (this.realm && this._notifyId) {
|
||||||
|
this.realm.disconnect(this._notifyId);
|
||||||
|
this._notifyId = 0;
|
||||||
|
}
|
||||||
|
this._realm = value;
|
||||||
|
if (this.realm) {
|
||||||
|
this._notifyId = this.realm.connect('notify', this.syncRealm.bind(this));
|
||||||
|
this.syncRealm();
|
||||||
|
}
|
||||||
|
this.notify('realm');
|
||||||
|
}
|
||||||
|
syncRealm() {
|
||||||
|
if (this.realm && this.realm.is_running()) {
|
||||||
|
this._nameLabel.remove_css_class('dim-label');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// @ts-ignore
|
||||||
|
this._nameLabel.add_css_class('dim-label');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_a = RealmRow;
|
||||||
|
(() => {
|
||||||
|
GObject.registerClass({
|
||||||
|
GTypeName: 'RealmRow',
|
||||||
|
Template: 'resource:///com/subgraph/citadel/Realms/ui/RealmRow.ui',
|
||||||
|
Properties: {
|
||||||
|
'realm': GObject.ParamSpec.object('realm', '', '', GObject.ParamFlags.READWRITE, Realm),
|
||||||
|
},
|
||||||
|
InternalChildren: ['nameLabel'],
|
||||||
|
}, _a);
|
||||||
|
})();
|
91
js/RealmsView.js
Normal file
91
js/RealmsView.js
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
var _a;
|
||||||
|
import GObject from 'gi://GObject';
|
||||||
|
import Gdk from 'gi://Gdk?version=4.0';
|
||||||
|
import Gtk from 'gi://Gtk?version=4.0';
|
||||||
|
import { Realm } from "./model/Realm.js";
|
||||||
|
export class RealmsView extends Gtk.Widget {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this._selectedRealm = null;
|
||||||
|
this._setupHiddenRealmsFilter();
|
||||||
|
this._setupRealmSorter();
|
||||||
|
const keyController = new Gtk.EventControllerKey();
|
||||||
|
keyController.connect('key-pressed', (_, keyval) => {
|
||||||
|
switch (keyval) {
|
||||||
|
case Gdk.KEY_j:
|
||||||
|
case Gdk.KEY_Down:
|
||||||
|
this.nextRealm();
|
||||||
|
break;
|
||||||
|
case Gdk.KEY_k:
|
||||||
|
case Gdk.KEY_Up:
|
||||||
|
this.prevRealm();
|
||||||
|
break;
|
||||||
|
case Gdk.KEY_Escape:
|
||||||
|
this.activate_action('app.quit', null);
|
||||||
|
print("escaped");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.add_controller(keyController);
|
||||||
|
}
|
||||||
|
_changeSelected(offset) {
|
||||||
|
const n_items = this._realmsSelection.n_items;
|
||||||
|
if (n_items <= 1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const pos = this._realmsSelection.selected;
|
||||||
|
if (pos == Gtk.INVALID_LIST_POSITION) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const newPos = pos + offset;
|
||||||
|
if (newPos < 0 || newPos >= n_items) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this._realmsSelection.selected = newPos;
|
||||||
|
}
|
||||||
|
nextRealm() {
|
||||||
|
this._changeSelected(1);
|
||||||
|
}
|
||||||
|
prevRealm() {
|
||||||
|
this._changeSelected(-1);
|
||||||
|
}
|
||||||
|
get selectedRealm() {
|
||||||
|
return this._selectedRealm;
|
||||||
|
}
|
||||||
|
set selectedRealm(value) {
|
||||||
|
if (this.selectedRealm === value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this._selectedRealm = value;
|
||||||
|
}
|
||||||
|
_setupHiddenRealmsFilter() {
|
||||||
|
this._hiddenRealmsFilterModel.filter = Gtk.CustomFilter.new(item => !item.is_system_realm);
|
||||||
|
}
|
||||||
|
_setupRealmSorter() {
|
||||||
|
// 1) Sort 'Current' the lowest (top of list).
|
||||||
|
// 2) Then sort 'Running' lower than not 'Running'
|
||||||
|
// 3) Realms in the same run state sorted by lowest timestamp
|
||||||
|
this._realmSorter.set_sort_func((a, b) => {
|
||||||
|
if (a.is_current || (a.is_running && !b.is_running)) {
|
||||||
|
return Gtk.Ordering.SMALLER;
|
||||||
|
}
|
||||||
|
else if (b.is_current || (b.is_running && !a.is_running)) {
|
||||||
|
return Gtk.Ordering.LARGER;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return b.timestamp - a.timestamp;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_a = RealmsView;
|
||||||
|
(() => {
|
||||||
|
GObject.registerClass({
|
||||||
|
GTypeName: 'RealmsView',
|
||||||
|
Template: 'resource:///com/subgraph/citadel/Realms/ui/RealmsView.ui',
|
||||||
|
Properties: {
|
||||||
|
'selected-realm': GObject.ParamSpec.object('selected-realm', '', '', GObject.ParamFlags.READWRITE, Realm),
|
||||||
|
},
|
||||||
|
InternalChildren: ['realmsSelection', 'hiddenRealmsFilterModel', 'realmSorter'],
|
||||||
|
}, _a);
|
||||||
|
})();
|
28
js/Window.js
Normal file
28
js/Window.js
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
var _a;
|
||||||
|
import GObject from 'gi://GObject';
|
||||||
|
import Adw from 'gi://Adw';
|
||||||
|
export class Window extends Adw.ApplicationWindow {
|
||||||
|
constructor(application) {
|
||||||
|
super({ application: application });
|
||||||
|
}
|
||||||
|
configureRealm(realm) {
|
||||||
|
this._configureRealm.configure(realm);
|
||||||
|
this._navView.push(this._configureRealm);
|
||||||
|
}
|
||||||
|
get realms_view() {
|
||||||
|
return this._realmsView;
|
||||||
|
}
|
||||||
|
vfunc_close_request() {
|
||||||
|
super.vfunc_close_request();
|
||||||
|
this.run_dispose();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_a = Window;
|
||||||
|
(() => {
|
||||||
|
GObject.registerClass({
|
||||||
|
GTypeName: 'RealmsWindow',
|
||||||
|
Template: 'resource:///com/subgraph/citadel/Realms/ui/Window.ui',
|
||||||
|
InternalChildren: ['realmsView', 'configureRealm', 'navView'],
|
||||||
|
}, _a);
|
||||||
|
})();
|
822
js/colors/Base16Theme.js
Normal file
822
js/colors/Base16Theme.js
Normal file
@ -0,0 +1,822 @@
|
|||||||
|
export class Base16Theme {
|
||||||
|
static add(id, name, colors) {
|
||||||
|
const theme = new Base16Theme(id, name, colors);
|
||||||
|
Base16Theme.THEMES.push(theme);
|
||||||
|
}
|
||||||
|
constructor(id, name, colors) {
|
||||||
|
this.id = id;
|
||||||
|
this.name = name;
|
||||||
|
this.colors = colors;
|
||||||
|
}
|
||||||
|
color(idx) {
|
||||||
|
let hex = this.colors[idx].toString(16).padStart(6, '0');
|
||||||
|
return `#${hex}`;
|
||||||
|
}
|
||||||
|
terminal_background() {
|
||||||
|
return this.color(0);
|
||||||
|
}
|
||||||
|
terminal_foreground() {
|
||||||
|
return this.color(5);
|
||||||
|
}
|
||||||
|
terminal_palette_color(idx) {
|
||||||
|
return this.color(Base16Theme.TERM_MAP[idx]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Base16Theme.CATEGORIES = [
|
||||||
|
['atelier', 'Atelier'],
|
||||||
|
['black-metal', 'Black Metal'],
|
||||||
|
['brushtrees', 'Brush Trees'],
|
||||||
|
['classic', 'Classic'],
|
||||||
|
['default', 'Default'],
|
||||||
|
['google', 'Google'],
|
||||||
|
['grayscale', 'Grayscale'],
|
||||||
|
['gruvbox', 'Gruvbox'],
|
||||||
|
['harmonic', 'Harmonic'],
|
||||||
|
['ia', 'iA'],
|
||||||
|
['material', 'Material'],
|
||||||
|
['papercolor', 'PaperColor'],
|
||||||
|
['solarized', 'Solarized'],
|
||||||
|
['summerfruit', 'Summerfruit'],
|
||||||
|
['tomorrow', 'Tomorrow'],
|
||||||
|
['unikitty', 'Unikitty'],
|
||||||
|
];
|
||||||
|
Base16Theme.TERM_MAP = [
|
||||||
|
0x00, 0x08, 0x0B, 0x0A, 0x0D, 0x0E, 0x0C, 0x05,
|
||||||
|
0x03, 0x08, 0x0B, 0x0A, 0x0D, 0x0E, 0x0C, 0x07,
|
||||||
|
0x09, 0x0F, 0x01, 0x02, 0x04, 0x06,
|
||||||
|
];
|
||||||
|
Base16Theme.THEMES = [];
|
||||||
|
Base16Theme.add("3024", "3024", [
|
||||||
|
0x090300, 0x3a3432, 0x4a4543, 0x5c5855,
|
||||||
|
0x807d7c, 0xa5a2a2, 0xd6d5d4, 0xf7f7f7,
|
||||||
|
0xdb2d20, 0xe8bbd0, 0xfded02, 0x01a252,
|
||||||
|
0xb5e4f4, 0x01a0e4, 0xa16a94, 0xcdab53,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("apathy", 'Apathy', [
|
||||||
|
0x031A16, 0x0B342D, 0x184E45, 0x2B685E,
|
||||||
|
0x5F9C92, 0x81B5AC, 0xA7CEC8, 0xD2E7E4,
|
||||||
|
0x3E9688, 0x3E7996, 0x3E4C96, 0x883E96,
|
||||||
|
0x963E4C, 0x96883E, 0x4C963E, 0x3E965B,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("ashes", "Ashes", [
|
||||||
|
0x1C2023, 0x393F45, 0x565E65, 0x747C84,
|
||||||
|
0xADB3BA, 0xC7CCD1, 0xDFE2E5, 0xF3F4F5,
|
||||||
|
0xC7AE95, 0xC7C795, 0xAEC795, 0x95C7AE,
|
||||||
|
0x95AEC7, 0xAE95C7, 0xC795AE, 0xC79595,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("atelier-cave-light", "Atelier Cave Light", [
|
||||||
|
0xefecf4, 0xe2dfe7, 0x8b8792, 0x7e7887,
|
||||||
|
0x655f6d, 0x585260, 0x26232a, 0x19171c,
|
||||||
|
0xbe4678, 0xaa573c, 0xa06e3b, 0x2a9292,
|
||||||
|
0x398bc6, 0x576ddb, 0x955ae7, 0xbf40bf,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("atelier-cave", "Atelier Cave", [
|
||||||
|
0x19171c, 0x26232a, 0x585260, 0x655f6d,
|
||||||
|
0x7e7887, 0x8b8792, 0xe2dfe7, 0xefecf4,
|
||||||
|
0xbe4678, 0xaa573c, 0xa06e3b, 0x2a9292,
|
||||||
|
0x398bc6, 0x576ddb, 0x955ae7, 0xbf40bf,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("atelier-dune-light", "Atelier Dune Light", [
|
||||||
|
0xfefbec, 0xe8e4cf, 0xa6a28c, 0x999580,
|
||||||
|
0x7d7a68, 0x6e6b5e, 0x292824, 0x20201d,
|
||||||
|
0xd73737, 0xb65611, 0xae9513, 0x60ac39,
|
||||||
|
0x1fad83, 0x6684e1, 0xb854d4, 0xd43552,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("atelier-dune", "Atelier Dune", [
|
||||||
|
0x20201d, 0x292824, 0x6e6b5e, 0x7d7a68,
|
||||||
|
0x999580, 0xa6a28c, 0xe8e4cf, 0xfefbec,
|
||||||
|
0xd73737, 0xb65611, 0xae9513, 0x60ac39,
|
||||||
|
0x1fad83, 0x6684e1, 0xb854d4, 0xd43552,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("atelier-estuary-light", "Atelier Estuary Light", [
|
||||||
|
0xf4f3ec, 0xe7e6df, 0x929181, 0x878573,
|
||||||
|
0x6c6b5a, 0x5f5e4e, 0x302f27, 0x22221b,
|
||||||
|
0xba6236, 0xae7313, 0xa5980d, 0x7d9726,
|
||||||
|
0x5b9d48, 0x36a166, 0x5f9182, 0x9d6c7c,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("atelier-estuary", "Atelier Estuary", [
|
||||||
|
0x22221b, 0x302f27, 0x5f5e4e, 0x6c6b5a,
|
||||||
|
0x878573, 0x929181, 0xe7e6df, 0xf4f3ec,
|
||||||
|
0xba6236, 0xae7313, 0xa5980d, 0x7d9726,
|
||||||
|
0x5b9d48, 0x36a166, 0x5f9182, 0x9d6c7c,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("atelier-forest-light", "Atelier Forest Light", [
|
||||||
|
0xf1efee, 0xe6e2e0, 0xa8a19f, 0x9c9491,
|
||||||
|
0x766e6b, 0x68615e, 0x2c2421, 0x1b1918,
|
||||||
|
0xf22c40, 0xdf5320, 0xc38418, 0x7b9726,
|
||||||
|
0x3d97b8, 0x407ee7, 0x6666ea, 0xc33ff3,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("atelier-forest", "Atelier Forest", [
|
||||||
|
0x1b1918, 0x2c2421, 0x68615e, 0x766e6b,
|
||||||
|
0x9c9491, 0xa8a19f, 0xe6e2e0, 0xf1efee,
|
||||||
|
0xf22c40, 0xdf5320, 0xc38418, 0x7b9726,
|
||||||
|
0x3d97b8, 0x407ee7, 0x6666ea, 0xc33ff3,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("atelier-heath-light", "Atelier Heath Light", [
|
||||||
|
0xf7f3f7, 0xd8cad8, 0xab9bab, 0x9e8f9e,
|
||||||
|
0x776977, 0x695d69, 0x292329, 0x1b181b,
|
||||||
|
0xca402b, 0xa65926, 0xbb8a35, 0x918b3b,
|
||||||
|
0x159393, 0x516aec, 0x7b59c0, 0xcc33cc,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("atelier-heath", "Atelier Heath", [
|
||||||
|
0x1b181b, 0x292329, 0x695d69, 0x776977,
|
||||||
|
0x9e8f9e, 0xab9bab, 0xd8cad8, 0xf7f3f7,
|
||||||
|
0xca402b, 0xa65926, 0xbb8a35, 0x918b3b,
|
||||||
|
0x159393, 0x516aec, 0x7b59c0, 0xcc33cc,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("atelier-lakeside-light", "Atelier Lakeside Light", [
|
||||||
|
0xebf8ff, 0xc1e4f6, 0x7ea2b4, 0x7195a8,
|
||||||
|
0x5a7b8c, 0x516d7b, 0x1f292e, 0x161b1d,
|
||||||
|
0xd22d72, 0x935c25, 0x8a8a0f, 0x568c3b,
|
||||||
|
0x2d8f6f, 0x257fad, 0x6b6bb8, 0xb72dd2,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("atelier-lakeside", "Atelier Lakeside", [
|
||||||
|
0x161b1d, 0x1f292e, 0x516d7b, 0x5a7b8c,
|
||||||
|
0x7195a8, 0x7ea2b4, 0xc1e4f6, 0xebf8ff,
|
||||||
|
0xd22d72, 0x935c25, 0x8a8a0f, 0x568c3b,
|
||||||
|
0x2d8f6f, 0x257fad, 0x6b6bb8, 0xb72dd2,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("atelier-plateau-light", "Atelier Plateau Light", [
|
||||||
|
0xf4ecec, 0xe7dfdf, 0x8a8585, 0x7e7777,
|
||||||
|
0x655d5d, 0x585050, 0x292424, 0x1b1818,
|
||||||
|
0xca4949, 0xb45a3c, 0xa06e3b, 0x4b8b8b,
|
||||||
|
0x5485b6, 0x7272ca, 0x8464c4, 0xbd5187,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("atelier-plateau", "Atelier Plateau", [
|
||||||
|
0x1b1818, 0x292424, 0x585050, 0x655d5d,
|
||||||
|
0x7e7777, 0x8a8585, 0xe7dfdf, 0xf4ecec,
|
||||||
|
0xca4949, 0xb45a3c, 0xa06e3b, 0x4b8b8b,
|
||||||
|
0x5485b6, 0x7272ca, 0x8464c4, 0xbd5187,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("atelier-savanna-light", "Atelier Savanna Light", [
|
||||||
|
0xecf4ee, 0xdfe7e2, 0x87928a, 0x78877d,
|
||||||
|
0x5f6d64, 0x526057, 0x232a25, 0x171c19,
|
||||||
|
0xb16139, 0x9f713c, 0xa07e3b, 0x489963,
|
||||||
|
0x1c9aa0, 0x478c90, 0x55859b, 0x867469,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("atelier-savanna", "Atelier Savanna", [
|
||||||
|
0x171c19, 0x232a25, 0x526057, 0x5f6d64,
|
||||||
|
0x78877d, 0x87928a, 0xdfe7e2, 0xecf4ee,
|
||||||
|
0xb16139, 0x9f713c, 0xa07e3b, 0x489963,
|
||||||
|
0x1c9aa0, 0x478c90, 0x55859b, 0x867469,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("atelier-seaside-light", "Atelier Seaside Light", [
|
||||||
|
0xf4fbf4, 0xcfe8cf, 0x8ca68c, 0x809980,
|
||||||
|
0x687d68, 0x5e6e5e, 0x242924, 0x131513,
|
||||||
|
0xe6193c, 0x87711d, 0x98981b, 0x29a329,
|
||||||
|
0x1999b3, 0x3d62f5, 0xad2bee, 0xe619c3,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("atelier-seaside", "Atelier Seaside", [
|
||||||
|
0x131513, 0x242924, 0x5e6e5e, 0x687d68,
|
||||||
|
0x809980, 0x8ca68c, 0xcfe8cf, 0xf4fbf4,
|
||||||
|
0xe6193c, 0x87711d, 0x98981b, 0x29a329,
|
||||||
|
0x1999b3, 0x3d62f5, 0xad2bee, 0xe619c3,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("atelier-sulphurpool-light", "Atelier Sulphurpool Light", [
|
||||||
|
0xf5f7ff, 0xdfe2f1, 0x979db4, 0x898ea4,
|
||||||
|
0x6b7394, 0x5e6687, 0x293256, 0x202746,
|
||||||
|
0xc94922, 0xc76b29, 0xc08b30, 0xac9739,
|
||||||
|
0x22a2c9, 0x3d8fd1, 0x6679cc, 0x9c637a,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("atelier-sulphurpool", "Atelier Sulphurpool", [
|
||||||
|
0x202746, 0x293256, 0x5e6687, 0x6b7394,
|
||||||
|
0x898ea4, 0x979db4, 0xdfe2f1, 0xf5f7ff,
|
||||||
|
0xc94922, 0xc76b29, 0xc08b30, 0xac9739,
|
||||||
|
0x22a2c9, 0x3d8fd1, 0x6679cc, 0x9c637a,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("atlas", "Atlas", [
|
||||||
|
0x002635, 0x00384d, 0x517F8D, 0x6C8B91,
|
||||||
|
0x869696, 0xa1a19a, 0xe6e6dc, 0xfafaf8,
|
||||||
|
0xff5a67, 0xf08e48, 0xffcc1b, 0x7fc06e,
|
||||||
|
0x14747e, 0x5dd7b9, 0x9a70a4, 0xc43060,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("bespin", "Bespin", [
|
||||||
|
0x28211c, 0x36312e, 0x5e5d5c, 0x666666,
|
||||||
|
0x797977, 0x8a8986, 0x9d9b97, 0xbaae9e,
|
||||||
|
0xcf6a4c, 0xcf7d34, 0xf9ee98, 0x54be0d,
|
||||||
|
0xafc4db, 0x5ea6ea, 0x9b859d, 0x937121,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("black-metal-bathory", "Black Metal (Bathory)", [
|
||||||
|
0x000000, 0x121212, 0x222222, 0x333333,
|
||||||
|
0x999999, 0xc1c1c1, 0x999999, 0xc1c1c1,
|
||||||
|
0x5f8787, 0xaaaaaa, 0xe78a53, 0xfbcb97,
|
||||||
|
0xaaaaaa, 0x888888, 0x999999, 0x444444,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("black-metal-burzum", "Black Metal (Burzum)", [
|
||||||
|
0x000000, 0x121212, 0x222222, 0x333333,
|
||||||
|
0x999999, 0xc1c1c1, 0x999999, 0xc1c1c1,
|
||||||
|
0x5f8787, 0xaaaaaa, 0x99bbaa, 0xddeecc,
|
||||||
|
0xaaaaaa, 0x888888, 0x999999, 0x444444,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("black-metal-dark-funeral", "Black Metal (Dark Funeral)", [
|
||||||
|
0x000000, 0x121212, 0x222222, 0x333333,
|
||||||
|
0x999999, 0xc1c1c1, 0x999999, 0xc1c1c1,
|
||||||
|
0x5f8787, 0xaaaaaa, 0x5f81a5, 0xd0dfee,
|
||||||
|
0xaaaaaa, 0x888888, 0x999999, 0x444444,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("black-metal-gorgoroth", "Black Metal (Gorgoroth)", [
|
||||||
|
0x000000, 0x121212, 0x222222, 0x333333,
|
||||||
|
0x999999, 0xc1c1c1, 0x999999, 0xc1c1c1,
|
||||||
|
0x5f8787, 0xaaaaaa, 0x8c7f70, 0x9b8d7f,
|
||||||
|
0xaaaaaa, 0x888888, 0x999999, 0x444444,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("black-metal-immortal", "Black Metal (Immortal)", [
|
||||||
|
0x000000, 0x121212, 0x222222, 0x333333,
|
||||||
|
0x999999, 0xc1c1c1, 0x999999, 0xc1c1c1,
|
||||||
|
0x5f8787, 0xaaaaaa, 0x556677, 0x7799bb,
|
||||||
|
0xaaaaaa, 0x888888, 0x999999, 0x444444,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("black-metal-khold", "Black Metal (Khold)", [
|
||||||
|
0x000000, 0x121212, 0x222222, 0x333333,
|
||||||
|
0x999999, 0xc1c1c1, 0x999999, 0xc1c1c1,
|
||||||
|
0x5f8787, 0xaaaaaa, 0x974b46, 0xeceee3,
|
||||||
|
0xaaaaaa, 0x888888, 0x999999, 0x444444,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("black-metal-marduk", "Black Metal (Marduk)", [
|
||||||
|
0x000000, 0x121212, 0x222222, 0x333333,
|
||||||
|
0x999999, 0xc1c1c1, 0x999999, 0xc1c1c1,
|
||||||
|
0x5f8787, 0xaaaaaa, 0x626b67, 0xa5aaa7,
|
||||||
|
0xaaaaaa, 0x888888, 0x999999, 0x444444,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("black-metal-mayhem", "Black Metal (Mayhem)", [
|
||||||
|
0x000000, 0x121212, 0x222222, 0x333333,
|
||||||
|
0x999999, 0xc1c1c1, 0x999999, 0xc1c1c1,
|
||||||
|
0x5f8787, 0xaaaaaa, 0xeecc6c, 0xf3ecd4,
|
||||||
|
0xaaaaaa, 0x888888, 0x999999, 0x444444,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("black-metal-nile", "Black Metal (Nile)", [
|
||||||
|
0x000000, 0x121212, 0x222222, 0x333333,
|
||||||
|
0x999999, 0xc1c1c1, 0x999999, 0xc1c1c1,
|
||||||
|
0x5f8787, 0xaaaaaa, 0x777755, 0xaa9988,
|
||||||
|
0xaaaaaa, 0x888888, 0x999999, 0x444444,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("black-metal-venom", "Black Metal (Venom)", [
|
||||||
|
0x000000, 0x121212, 0x222222, 0x333333,
|
||||||
|
0x999999, 0xc1c1c1, 0x999999, 0xc1c1c1,
|
||||||
|
0x5f8787, 0xaaaaaa, 0x79241f, 0xf8f7f2,
|
||||||
|
0xaaaaaa, 0x888888, 0x999999, 0x444444,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("black-metal", "Black Metal", [
|
||||||
|
0x000000, 0x121212, 0x222222, 0x333333,
|
||||||
|
0x999999, 0xc1c1c1, 0x999999, 0xc1c1c1,
|
||||||
|
0x5f8787, 0xaaaaaa, 0xa06666, 0xdd9999,
|
||||||
|
0xaaaaaa, 0x888888, 0x999999, 0x444444,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("brewer", "Brewer", [
|
||||||
|
0x0c0d0e, 0x2e2f30, 0x515253, 0x737475,
|
||||||
|
0x959697, 0xb7b8b9, 0xdadbdc, 0xfcfdfe,
|
||||||
|
0xe31a1c, 0xe6550d, 0xdca060, 0x31a354,
|
||||||
|
0x80b1d3, 0x3182bd, 0x756bb1, 0xb15928,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("bright", "Bright", [
|
||||||
|
0x000000, 0x303030, 0x505050, 0xb0b0b0,
|
||||||
|
0xd0d0d0, 0xe0e0e0, 0xf5f5f5, 0xffffff,
|
||||||
|
0xfb0120, 0xfc6d24, 0xfda331, 0xa1c659,
|
||||||
|
0x76c7b7, 0x6fb3d2, 0xd381c3, 0xbe643c,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("brogrammer", "Brogrammer", [
|
||||||
|
0x1f1f1f, 0xf81118, 0x2dc55e, 0xecba0f,
|
||||||
|
0x2a84d2, 0x4e5ab7, 0x1081d6, 0xd6dbe5,
|
||||||
|
0xd6dbe5, 0xde352e, 0x1dd361, 0xf3bd09,
|
||||||
|
0x1081d6, 0x5350b9, 0x0f7ddb, 0xffffff,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("brushtrees-dark", "Brush Trees Dark", [
|
||||||
|
0x485867, 0x5A6D7A, 0x6D828E, 0x8299A1,
|
||||||
|
0x98AFB5, 0xB0C5C8, 0xC9DBDC, 0xE3EFEF,
|
||||||
|
0xb38686, 0xd8bba2, 0xaab386, 0x87b386,
|
||||||
|
0x86b3b3, 0x868cb3, 0xb386b2, 0xb39f9f,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("brushtrees", "Brush Trees", [
|
||||||
|
0xE3EFEF, 0xC9DBDC, 0xB0C5C8, 0x98AFB5,
|
||||||
|
0x8299A1, 0x6D828E, 0x5A6D7A, 0x485867,
|
||||||
|
0xb38686, 0xd8bba2, 0xaab386, 0x87b386,
|
||||||
|
0x86b3b3, 0x868cb3, 0xb386b2, 0xb39f9f,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("chalk", "Chalk", [
|
||||||
|
0x151515, 0x202020, 0x303030, 0x505050,
|
||||||
|
0xb0b0b0, 0xd0d0d0, 0xe0e0e0, 0xf5f5f5,
|
||||||
|
0xfb9fb1, 0xeda987, 0xddb26f, 0xacc267,
|
||||||
|
0x12cfc0, 0x6fc2ef, 0xe1a3ee, 0xdeaf8f,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("circus", "Circus", [
|
||||||
|
0x191919, 0x202020, 0x303030, 0x5f5a60,
|
||||||
|
0x505050, 0xa7a7a7, 0x808080, 0xffffff,
|
||||||
|
0xdc657d, 0x4bb1a7, 0xc3ba63, 0x84b97c,
|
||||||
|
0x4bb1a7, 0x639ee4, 0xb888e2, 0xb888e2,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("classic-dark", "Classic Dark", [
|
||||||
|
0x151515, 0x202020, 0x303030, 0x505050,
|
||||||
|
0xB0B0B0, 0xD0D0D0, 0xE0E0E0, 0xF5F5F5,
|
||||||
|
0xAC4142, 0xD28445, 0xF4BF75, 0x90A959,
|
||||||
|
0x75B5AA, 0x6A9FB5, 0xAA759F, 0x8F5536,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("classic-light", "Classic Light", [
|
||||||
|
0xF5F5F5, 0xE0E0E0, 0xD0D0D0, 0xB0B0B0,
|
||||||
|
0x505050, 0x303030, 0x202020, 0x151515,
|
||||||
|
0xAC4142, 0xD28445, 0xF4BF75, 0x90A959,
|
||||||
|
0x75B5AA, 0x6A9FB5, 0xAA759F, 0x8F5536,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("codeschool", "Codeschool", [
|
||||||
|
0x232c31, 0x1c3657, 0x2a343a, 0x3f4944,
|
||||||
|
0x84898c, 0x9ea7a6, 0xa7cfa3, 0xb5d8f6,
|
||||||
|
0x2a5491, 0x43820d, 0xa03b1e, 0x237986,
|
||||||
|
0xb02f30, 0x484d79, 0xc59820, 0xc98344,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("cupcake", "Cupcake", [
|
||||||
|
0xfbf1f2, 0xf2f1f4, 0xd8d5dd, 0xbfb9c6,
|
||||||
|
0xa59daf, 0x8b8198, 0x72677E, 0x585062,
|
||||||
|
0xD57E85, 0xEBB790, 0xDCB16C, 0xA3B367,
|
||||||
|
0x69A9A7, 0x7297B9, 0xBB99B4, 0xBAA58C,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("cupertino", "Cupertino", [
|
||||||
|
0xffffff, 0xc0c0c0, 0xc0c0c0, 0x808080,
|
||||||
|
0x808080, 0x404040, 0x404040, 0x5e5e5e,
|
||||||
|
0xc41a15, 0xeb8500, 0x826b28, 0x007400,
|
||||||
|
0x318495, 0x0000ff, 0xa90d91, 0x826b28,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("darktooth", "Darktooth", [
|
||||||
|
0x1D2021, 0x32302F, 0x504945, 0x665C54,
|
||||||
|
0x928374, 0xA89984, 0xD5C4A1, 0xFDF4C1,
|
||||||
|
0xFB543F, 0xFE8625, 0xFAC03B, 0x95C085,
|
||||||
|
0x8BA59B, 0x0D6678, 0x8F4673, 0xA87322,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("default-dark", "Default Dark", [
|
||||||
|
0x181818, 0x282828, 0x383838, 0x585858,
|
||||||
|
0xb8b8b8, 0xd8d8d8, 0xe8e8e8, 0xf8f8f8,
|
||||||
|
0xab4642, 0xdc9656, 0xf7ca88, 0xa1b56c,
|
||||||
|
0x86c1b9, 0x7cafc2, 0xba8baf, 0xa16946,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("default-light", "Default Light", [
|
||||||
|
0xf8f8f8, 0xe8e8e8, 0xd8d8d8, 0xb8b8b8,
|
||||||
|
0x585858, 0x383838, 0x282828, 0x181818,
|
||||||
|
0xab4642, 0xdc9656, 0xf7ca88, 0xa1b56c,
|
||||||
|
0x86c1b9, 0x7cafc2, 0xba8baf, 0xa16946,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("dracula", "Dracula", [
|
||||||
|
0x282936, 0x3a3c4e, 0x4d4f68, 0x626483,
|
||||||
|
0x62d6e8, 0xe9e9f4, 0xf1f2f8, 0xf7f7fb,
|
||||||
|
0xea51b2, 0xb45bcf, 0x00f769, 0xebff87,
|
||||||
|
0xa1efe4, 0x62d6e8, 0xb45bcf, 0x00f769,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("eighties", "Eighties", [
|
||||||
|
0x2d2d2d, 0x393939, 0x515151, 0x747369,
|
||||||
|
0xa09f93, 0xd3d0c8, 0xe8e6df, 0xf2f0ec,
|
||||||
|
0xf2777a, 0xf99157, 0xffcc66, 0x99cc99,
|
||||||
|
0x66cccc, 0x6699cc, 0xcc99cc, 0xd27b53,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("embers", "Embers", [
|
||||||
|
0x16130F, 0x2C2620, 0x433B32, 0x5A5047,
|
||||||
|
0x8A8075, 0xA39A90, 0xBEB6AE, 0xDBD6D1,
|
||||||
|
0x826D57, 0x828257, 0x6D8257, 0x57826D,
|
||||||
|
0x576D82, 0x6D5782, 0x82576D, 0x825757,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("flat", "Flat", [
|
||||||
|
0x2C3E50, 0x34495E, 0x7F8C8D, 0x95A5A6,
|
||||||
|
0xBDC3C7, 0xe0e0e0, 0xf5f5f5, 0xECF0F1,
|
||||||
|
0xE74C3C, 0xE67E22, 0xF1C40F, 0x2ECC71,
|
||||||
|
0x1ABC9C, 0x3498DB, 0x9B59B6, 0xbe643c,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("fruit-soda", "Fruit Soda", [
|
||||||
|
0xf1ecf1, 0xe0dee0, 0xd8d5d5, 0xb5b4b6,
|
||||||
|
0x979598, 0x515151, 0x474545, 0x2d2c2c,
|
||||||
|
0xfe3e31, 0xfe6d08, 0xf7e203, 0x47f74c,
|
||||||
|
0x0f9cfd, 0x2931df, 0x611fce, 0xb16f40,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("github", "Github", [
|
||||||
|
0xffffff, 0xf5f5f5, 0xc8c8fa, 0x969896,
|
||||||
|
0xe8e8e8, 0x333333, 0xffffff, 0xffffff,
|
||||||
|
0xed6a43, 0x0086b3, 0x795da3, 0x183691,
|
||||||
|
0x183691, 0x795da3, 0xa71d5d, 0x333333,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("google-dark", "Google Dark", [
|
||||||
|
0x1d1f21, 0x282a2e, 0x373b41, 0x969896,
|
||||||
|
0xb4b7b4, 0xc5c8c6, 0xe0e0e0, 0xffffff,
|
||||||
|
0xCC342B, 0xF96A38, 0xFBA922, 0x198844,
|
||||||
|
0x3971ED, 0x3971ED, 0xA36AC7, 0x3971ED,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("google-light", "Google Light", [
|
||||||
|
0xffffff, 0xe0e0e0, 0xc5c8c6, 0xb4b7b4,
|
||||||
|
0x969896, 0x373b41, 0x282a2e, 0x1d1f21,
|
||||||
|
0xCC342B, 0xF96A38, 0xFBA922, 0x198844,
|
||||||
|
0x3971ED, 0x3971ED, 0xA36AC7, 0x3971ED,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("grayscale-dark", "Grayscale Dark", [
|
||||||
|
0x101010, 0x252525, 0x464646, 0x525252,
|
||||||
|
0xababab, 0xb9b9b9, 0xe3e3e3, 0xf7f7f7,
|
||||||
|
0x7c7c7c, 0x999999, 0xa0a0a0, 0x8e8e8e,
|
||||||
|
0x868686, 0x686868, 0x747474, 0x5e5e5e,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("grayscale-light", "Grayscale Light", [
|
||||||
|
0xf7f7f7, 0xe3e3e3, 0xb9b9b9, 0xababab,
|
||||||
|
0x525252, 0x464646, 0x252525, 0x101010,
|
||||||
|
0x7c7c7c, 0x999999, 0xa0a0a0, 0x8e8e8e,
|
||||||
|
0x868686, 0x686868, 0x747474, 0x5e5e5e,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("greenscreen", "Green Screen", [
|
||||||
|
0x001100, 0x003300, 0x005500, 0x007700,
|
||||||
|
0x009900, 0x00bb00, 0x00dd00, 0x00ff00,
|
||||||
|
0x007700, 0x009900, 0x007700, 0x00bb00,
|
||||||
|
0x005500, 0x009900, 0x00bb00, 0x005500,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("gruvbox-dark-hard", "Gruvbox dark, hard", [
|
||||||
|
0x1d2021, 0x3c3836, 0x504945, 0x665c54,
|
||||||
|
0xbdae93, 0xd5c4a1, 0xebdbb2, 0xfbf1c7,
|
||||||
|
0xfb4934, 0xfe8019, 0xfabd2f, 0xb8bb26,
|
||||||
|
0x8ec07c, 0x83a598, 0xd3869b, 0xd65d0e,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("gruvbox-dark-medium", "Gruvbox dark, medium", [
|
||||||
|
0x282828, 0x3c3836, 0x504945, 0x665c54,
|
||||||
|
0xbdae93, 0xd5c4a1, 0xebdbb2, 0xfbf1c7,
|
||||||
|
0xfb4934, 0xfe8019, 0xfabd2f, 0xb8bb26,
|
||||||
|
0x8ec07c, 0x83a598, 0xd3869b, 0xd65d0e,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("gruvbox-dark-pale", "Gruvbox dark, pale", [
|
||||||
|
0x262626, 0x3a3a3a, 0x4e4e4e, 0x8a8a8a,
|
||||||
|
0x949494, 0xdab997, 0xd5c4a1, 0xebdbb2,
|
||||||
|
0xd75f5f, 0xff8700, 0xffaf00, 0xafaf00,
|
||||||
|
0x85ad85, 0x83adad, 0xd485ad, 0xd65d0e,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("gruvbox-dark-soft", "Gruvbox dark, soft", [
|
||||||
|
0x32302f, 0x3c3836, 0x504945, 0x665c54,
|
||||||
|
0xbdae93, 0xd5c4a1, 0xebdbb2, 0xfbf1c7,
|
||||||
|
0xfb4934, 0xfe8019, 0xfabd2f, 0xb8bb26,
|
||||||
|
0x8ec07c, 0x83a598, 0xd3869b, 0xd65d0e,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("gruvbox-light-hard", "Gruvbox light, hard", [
|
||||||
|
0xf9f5d7, 0xebdbb2, 0xd5c4a1, 0xbdae93,
|
||||||
|
0x665c54, 0x504945, 0x3c3836, 0x282828,
|
||||||
|
0x9d0006, 0xaf3a03, 0xb57614, 0x79740e,
|
||||||
|
0x427b58, 0x076678, 0x8f3f71, 0xd65d0e,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("gruvbox-light-medium", "Gruvbox light, medium", [
|
||||||
|
0xfbf1c7, 0xebdbb2, 0xd5c4a1, 0xbdae93,
|
||||||
|
0x665c54, 0x504945, 0x3c3836, 0x282828,
|
||||||
|
0x9d0006, 0xaf3a03, 0xb57614, 0x79740e,
|
||||||
|
0x427b58, 0x076678, 0x8f3f71, 0xd65d0e,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("gruvbox-light-soft", "Gruvbox light, soft", [
|
||||||
|
0xf2e5bc, 0xebdbb2, 0xd5c4a1, 0xbdae93,
|
||||||
|
0x665c54, 0x504945, 0x3c3836, 0x282828,
|
||||||
|
0x9d0006, 0xaf3a03, 0xb57614, 0x79740e,
|
||||||
|
0x427b58, 0x076678, 0x8f3f71, 0xd65d0e,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("harmonic-dark", "Harmonic16 Dark", [
|
||||||
|
0x0b1c2c, 0x223b54, 0x405c79, 0x627e99,
|
||||||
|
0xaabcce, 0xcbd6e2, 0xe5ebf1, 0xf7f9fb,
|
||||||
|
0xbf8b56, 0xbfbf56, 0x8bbf56, 0x56bf8b,
|
||||||
|
0x568bbf, 0x8b56bf, 0xbf568b, 0xbf5656,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("harmonic-light", "Harmonic16 Light", [
|
||||||
|
0xf7f9fb, 0xe5ebf1, 0xcbd6e2, 0xaabcce,
|
||||||
|
0x627e99, 0x405c79, 0x223b54, 0x0b1c2c,
|
||||||
|
0xbf8b56, 0xbfbf56, 0x8bbf56, 0x56bf8b,
|
||||||
|
0x568bbf, 0x8b56bf, 0xbf568b, 0xbf5656,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("heetch-light", "Heetch Light", [
|
||||||
|
0xfeffff, 0x392551, 0x7b6d8b, 0x9c92a8,
|
||||||
|
0xddd6e5, 0x5a496e, 0x470546, 0x190134,
|
||||||
|
0x27d9d5, 0xbdb6c5, 0x5ba2b6, 0xf80059,
|
||||||
|
0xc33678, 0x47f9f5, 0xbd0152, 0xdedae2,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("heetch", "Heetch Dark", [
|
||||||
|
0x190134, 0x392551, 0x5A496E, 0x7B6D8B,
|
||||||
|
0x9C92A8, 0xBDB6C5, 0xDEDAE2, 0xFEFFFF,
|
||||||
|
0x27D9D5, 0x5BA2B6, 0x8F6C97, 0xC33678,
|
||||||
|
0xF80059, 0xBD0152, 0x82034C, 0x470546,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("helios", "Helios", [
|
||||||
|
0x1d2021, 0x383c3e, 0x53585b, 0x6f7579,
|
||||||
|
0xcdcdcd, 0xd5d5d5, 0xdddddd, 0xe5e5e5,
|
||||||
|
0xd72638, 0xeb8413, 0xf19d1a, 0x88b92d,
|
||||||
|
0x1ba595, 0x1e8bac, 0xbe4264, 0xc85e0d,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("hopscotch", "Hopscotch", [
|
||||||
|
0x322931, 0x433b42, 0x5c545b, 0x797379,
|
||||||
|
0x989498, 0xb9b5b8, 0xd5d3d5, 0xffffff,
|
||||||
|
0xdd464c, 0xfd8b19, 0xfdcc59, 0x8fc13e,
|
||||||
|
0x149b93, 0x1290bf, 0xc85e7c, 0xb33508,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("horizon-dark", "Horizon Dark", [
|
||||||
|
0x1c1e26, 0x232530, 0x2e303e, 0x676a8d,
|
||||||
|
0xced1d0, 0xcbced0, 0xdcdfe4, 0xe3e6ee,
|
||||||
|
0xe93c58, 0xe58d7d, 0xefb993, 0xefaf8e,
|
||||||
|
0x24a8b4, 0xdf5273, 0xb072d1, 0xe4a382,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("ia-dark", "iA Dark", [
|
||||||
|
0x1a1a1a, 0x222222, 0x1d414d, 0x767676,
|
||||||
|
0xb8b8b8, 0xcccccc, 0xe8e8e8, 0xf8f8f8,
|
||||||
|
0xd88568, 0xd86868, 0xb99353, 0x83a471,
|
||||||
|
0x7c9cae, 0x8eccdd, 0xb98eb2, 0x8b6c37,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("ia-light", "iA Light", [
|
||||||
|
0xf6f6f6, 0xdedede, 0xbde5f2, 0x898989,
|
||||||
|
0x767676, 0x181818, 0xe8e8e8, 0xf8f8f8,
|
||||||
|
0x9c5a02, 0xc43e18, 0xc48218, 0x38781c,
|
||||||
|
0x2d6bb1, 0x48bac2, 0xa94598, 0x8b6c37,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("icy", "Icy Dark", [
|
||||||
|
0x021012, 0x031619, 0x041f23, 0x052e34,
|
||||||
|
0x064048, 0x095b67, 0x0c7c8c, 0x109cb0,
|
||||||
|
0x16c1d9, 0xb3ebf2, 0x80deea, 0x4dd0e1,
|
||||||
|
0x26c6da, 0x00bcd4, 0x00acc1, 0x0097a7,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("irblack", "IR Black", [
|
||||||
|
0x000000, 0x242422, 0x484844, 0x6c6c66,
|
||||||
|
0x918f88, 0xb5b3aa, 0xd9d7cc, 0xfdfbee,
|
||||||
|
0xff6c60, 0xe9c062, 0xffffb6, 0xa8ff60,
|
||||||
|
0xc6c5fe, 0x96cbfe, 0xff73fd, 0xb18a3d,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("isotope", "Isotope", [
|
||||||
|
0x000000, 0x404040, 0x606060, 0x808080,
|
||||||
|
0xc0c0c0, 0xd0d0d0, 0xe0e0e0, 0xffffff,
|
||||||
|
0xff0000, 0xff9900, 0xff0099, 0x33ff00,
|
||||||
|
0x00ffff, 0x0066ff, 0xcc00ff, 0x3300ff,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("macintosh", "Macintosh", [
|
||||||
|
0x000000, 0x404040, 0x404040, 0x808080,
|
||||||
|
0x808080, 0xc0c0c0, 0xc0c0c0, 0xffffff,
|
||||||
|
0xdd0907, 0xff6403, 0xfbf305, 0x1fb714,
|
||||||
|
0x02abea, 0x0000d3, 0x4700a5, 0x90713a,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("marrakesh", "Marrakesh", [
|
||||||
|
0x201602, 0x302e00, 0x5f5b17, 0x6c6823,
|
||||||
|
0x86813b, 0x948e48, 0xccc37a, 0xfaf0a5,
|
||||||
|
0xc35359, 0xb36144, 0xa88339, 0x18974e,
|
||||||
|
0x75a738, 0x477ca1, 0x8868b3, 0xb3588e,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("materia", "Materia", [
|
||||||
|
0x263238, 0x2C393F, 0x37474F, 0x707880,
|
||||||
|
0xC9CCD3, 0xCDD3DE, 0xD5DBE5, 0xFFFFFF,
|
||||||
|
0xEC5F67, 0xEA9560, 0xFFCC00, 0x8BD649,
|
||||||
|
0x80CBC4, 0x89DDFF, 0x82AAFF, 0xEC5F67,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("material-darker", "Material Darker", [
|
||||||
|
0x212121, 0x303030, 0x353535, 0x4A4A4A,
|
||||||
|
0xB2CCD6, 0xEEFFFF, 0xEEFFFF, 0xFFFFFF,
|
||||||
|
0xF07178, 0xF78C6C, 0xFFCB6B, 0xC3E88D,
|
||||||
|
0x89DDFF, 0x82AAFF, 0xC792EA, 0xFF5370,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("material-lighter", "Material Lighter", [
|
||||||
|
0xFAFAFA, 0xE7EAEC, 0xCCEAE7, 0xCCD7DA,
|
||||||
|
0x8796B0, 0x80CBC4, 0x80CBC4, 0xFFFFFF,
|
||||||
|
0xFF5370, 0xF76D47, 0xFFB62C, 0x91B859,
|
||||||
|
0x39ADB5, 0x6182B8, 0x7C4DFF, 0xE53935,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("material-palenight", "Material Palenight", [
|
||||||
|
0x292D3E, 0x444267, 0x32374D, 0x676E95,
|
||||||
|
0x8796B0, 0x959DCB, 0x959DCB, 0xFFFFFF,
|
||||||
|
0xF07178, 0xF78C6C, 0xFFCB6B, 0xC3E88D,
|
||||||
|
0x89DDFF, 0x82AAFF, 0xC792EA, 0xFF5370,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("material-vivid", "Material Vivid", [
|
||||||
|
0x202124, 0x27292c, 0x323639, 0x44464d,
|
||||||
|
0x676c71, 0x80868b, 0x9e9e9e, 0xffffff,
|
||||||
|
0xf44336, 0xff9800, 0xffeb3b, 0x00e676,
|
||||||
|
0x00bcd4, 0x2196f3, 0x673ab7, 0x8d6e63,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("material", "Material", [
|
||||||
|
0x263238, 0x2E3C43, 0x314549, 0x546E7A,
|
||||||
|
0xB2CCD6, 0xEEFFFF, 0xEEFFFF, 0xFFFFFF,
|
||||||
|
0xF07178, 0xF78C6C, 0xFFCB6B, 0xC3E88D,
|
||||||
|
0x89DDFF, 0x82AAFF, 0xC792EA, 0xFF5370,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("mellow-purple", "Mellow Purple", [
|
||||||
|
0x1e0528, 0x1A092D, 0x331354, 0x320f55,
|
||||||
|
0x873582, 0xffeeff, 0xffeeff, 0xf8c0ff,
|
||||||
|
0x00d9e9, 0xaa00a3, 0x955ae7, 0x05cb0d,
|
||||||
|
0xb900b1, 0x550068, 0x8991bb, 0x4d6fff,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("mexico-light", "Mexico Light", [
|
||||||
|
0xf8f8f8, 0xe8e8e8, 0xd8d8d8, 0xb8b8b8,
|
||||||
|
0x585858, 0x383838, 0x282828, 0x181818,
|
||||||
|
0xab4642, 0xdc9656, 0xf79a0e, 0x538947,
|
||||||
|
0x4b8093, 0x7cafc2, 0x96609e, 0xa16946,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("mocha", "Mocha", [
|
||||||
|
0x3B3228, 0x534636, 0x645240, 0x7e705a,
|
||||||
|
0xb8afad, 0xd0c8c6, 0xe9e1dd, 0xf5eeeb,
|
||||||
|
0xcb6077, 0xd28b71, 0xf4bc87, 0xbeb55b,
|
||||||
|
0x7bbda4, 0x8ab3b5, 0xa89bb9, 0xbb9584,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("monokai", "Monokai", [
|
||||||
|
0x272822, 0x383830, 0x49483e, 0x75715e,
|
||||||
|
0xa59f85, 0xf8f8f2, 0xf5f4f1, 0xf9f8f5,
|
||||||
|
0xf92672, 0xfd971f, 0xf4bf75, 0xa6e22e,
|
||||||
|
0xa1efe4, 0x66d9ef, 0xae81ff, 0xcc6633,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("nord", "Nord", [
|
||||||
|
0x2E3440, 0x3B4252, 0x434C5E, 0x4C566A,
|
||||||
|
0xD8DEE9, 0xE5E9F0, 0xECEFF4, 0x8FBCBB,
|
||||||
|
0x88C0D0, 0x81A1C1, 0x5E81AC, 0xBF616A,
|
||||||
|
0xD08770, 0xEBCB8B, 0xA3BE8C, 0xB48EAD,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("ocean", "Ocean", [
|
||||||
|
0x2b303b, 0x343d46, 0x4f5b66, 0x65737e,
|
||||||
|
0xa7adba, 0xc0c5ce, 0xdfe1e8, 0xeff1f5,
|
||||||
|
0xbf616a, 0xd08770, 0xebcb8b, 0xa3be8c,
|
||||||
|
0x96b5b4, 0x8fa1b3, 0xb48ead, 0xab7967,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("oceanicnext", "OceanicNext", [
|
||||||
|
0x1B2B34, 0x343D46, 0x4F5B66, 0x65737E,
|
||||||
|
0xA7ADBA, 0xC0C5CE, 0xCDD3DE, 0xD8DEE9,
|
||||||
|
0xEC5F67, 0xF99157, 0xFAC863, 0x99C794,
|
||||||
|
0x5FB3B3, 0x6699CC, 0xC594C5, 0xAB7967,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("one-light", "One Light", [
|
||||||
|
0xfafafa, 0xf0f0f1, 0xe5e5e6, 0xa0a1a7,
|
||||||
|
0x696c77, 0x383a42, 0x202227, 0x090a0b,
|
||||||
|
0xca1243, 0xd75f00, 0xc18401, 0x50a14f,
|
||||||
|
0x0184bc, 0x4078f2, 0xa626a4, 0x986801,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("onedark", "OneDark", [
|
||||||
|
0x282c34, 0x353b45, 0x3e4451, 0x545862,
|
||||||
|
0x565c64, 0xabb2bf, 0xb6bdca, 0xc8ccd4,
|
||||||
|
0xe06c75, 0xd19a66, 0xe5c07b, 0x98c379,
|
||||||
|
0x56b6c2, 0x61afef, 0xc678dd, 0xbe5046,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("outrun-dark", "Outrun Dark", [
|
||||||
|
0x00002A, 0x20204A, 0x30305A, 0x50507A,
|
||||||
|
0xB0B0DA, 0xD0D0FA, 0xE0E0FF, 0xF5F5FF,
|
||||||
|
0xFF4242, 0xFC8D28, 0xF3E877, 0x59F176,
|
||||||
|
0x0EF0F0, 0x66B0FF, 0xF10596, 0xF003EF,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("papercolor-dark", "PaperColor Dark", [
|
||||||
|
0x1c1c1c, 0xaf005f, 0x5faf00, 0xd7af5f,
|
||||||
|
0x5fafd7, 0x808080, 0xd7875f, 0xd0d0d0,
|
||||||
|
0x585858, 0x5faf5f, 0xafd700, 0xaf87d7,
|
||||||
|
0xffaf00, 0xff5faf, 0x00afaf, 0x5f8787,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("papercolor-light", "PaperColor Light", [
|
||||||
|
0xeeeeee, 0xaf0000, 0x008700, 0x5f8700,
|
||||||
|
0x0087af, 0x878787, 0x005f87, 0x444444,
|
||||||
|
0xbcbcbc, 0xd70000, 0xd70087, 0x8700af,
|
||||||
|
0xd75f00, 0xd75f00, 0x005faf, 0x005f87,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("paraiso", "Paraiso", [
|
||||||
|
0x2f1e2e, 0x41323f, 0x4f424c, 0x776e71,
|
||||||
|
0x8d8687, 0xa39e9b, 0xb9b6b0, 0xe7e9db,
|
||||||
|
0xef6155, 0xf99b15, 0xfec418, 0x48b685,
|
||||||
|
0x5bc4bf, 0x06b6ef, 0x815ba4, 0xe96ba8,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("phd", "PhD", [
|
||||||
|
0x061229, 0x2a3448, 0x4d5666, 0x717885,
|
||||||
|
0x9a99a3, 0xb8bbc2, 0xdbdde0, 0xffffff,
|
||||||
|
0xd07346, 0xf0a000, 0xfbd461, 0x99bf52,
|
||||||
|
0x72b9bf, 0x5299bf, 0x9989cc, 0xb08060,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("pico", "Pico", [
|
||||||
|
0x000000, 0x1d2b53, 0x7e2553, 0x008751,
|
||||||
|
0xab5236, 0x5f574f, 0xc2c3c7, 0xfff1e8,
|
||||||
|
0xff004d, 0xffa300, 0xfff024, 0x00e756,
|
||||||
|
0x29adff, 0x83769c, 0xff77a8, 0xffccaa,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("pop", "Pop", [
|
||||||
|
0x000000, 0x202020, 0x303030, 0x505050,
|
||||||
|
0xb0b0b0, 0xd0d0d0, 0xe0e0e0, 0xffffff,
|
||||||
|
0xeb008a, 0xf29333, 0xf8ca12, 0x37b349,
|
||||||
|
0x00aabb, 0x0e5a94, 0xb31e8d, 0x7a2d00,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("porple", "Porple", [
|
||||||
|
0x292c36, 0x333344, 0x474160, 0x65568a,
|
||||||
|
0xb8b8b8, 0xd8d8d8, 0xe8e8e8, 0xf8f8f8,
|
||||||
|
0xf84547, 0xd28e5d, 0xefa16b, 0x95c76f,
|
||||||
|
0x64878f, 0x8485ce, 0xb74989, 0x986841,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("qualia", "Qualia", [
|
||||||
|
0x101010, 0x454545, 0x454545, 0x454545,
|
||||||
|
0x808080, 0xc0c0c0, 0xc0c0c0, 0x454545,
|
||||||
|
0xefa6a2, 0xa3b8ef, 0xe6a3dc, 0x80c990,
|
||||||
|
0xc8c874, 0x50cacd, 0xe0af85, 0x808080,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("railscasts", "Railscasts", [
|
||||||
|
0x2b2b2b, 0x272935, 0x3a4055, 0x5a647e,
|
||||||
|
0xd4cfc9, 0xe6e1dc, 0xf4f1ed, 0xf9f7f3,
|
||||||
|
0xda4939, 0xcc7833, 0xffc66d, 0xa5c261,
|
||||||
|
0x519f50, 0x6d9cbe, 0xb6b3eb, 0xbc9458,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("rebecca", "Rebecca", [
|
||||||
|
0x292a44, 0x663399, 0x383a62, 0x666699,
|
||||||
|
0xa0a0c5, 0xf1eff8, 0xccccff, 0x53495d,
|
||||||
|
0xa0a0c5, 0xefe4a1, 0xae81ff, 0x6dfedf,
|
||||||
|
0x8eaee0, 0x2de0a7, 0x7aa5ff, 0xff79c6,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("seti", "Seti UI", [
|
||||||
|
0x151718, 0x282a2b, 0x3B758C, 0x41535B,
|
||||||
|
0x43a5d5, 0xd6d6d6, 0xeeeeee, 0xffffff,
|
||||||
|
0xcd3f45, 0xdb7b55, 0xe6cd69, 0x9fca56,
|
||||||
|
0x55dbbe, 0x55b5db, 0xa074c4, 0x8a553f,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("shapeshifter", "Shapeshifter", [
|
||||||
|
0xf9f9f9, 0xe0e0e0, 0xababab, 0x555555,
|
||||||
|
0x343434, 0x102015, 0x040404, 0x000000,
|
||||||
|
0xe92f2f, 0xe09448, 0xdddd13, 0x0ed839,
|
||||||
|
0x23edda, 0x3b48e3, 0xf996e2, 0x69542d,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("snazzy", "Snazzy", [
|
||||||
|
0x282a36, 0x34353e, 0x43454f, 0x78787e,
|
||||||
|
0xa5a5a9, 0xe2e4e5, 0xeff0eb, 0xf1f1f0,
|
||||||
|
0xff5c57, 0xff9f43, 0xf3f99d, 0x5af78e,
|
||||||
|
0x9aedfe, 0x57c7ff, 0xff6ac1, 0xb2643c,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("solarflare", "Solar Flare", [
|
||||||
|
0x18262F, 0x222E38, 0x586875, 0x667581,
|
||||||
|
0x85939E, 0xA6AFB8, 0xE8E9ED, 0xF5F7FA,
|
||||||
|
0xEF5253, 0xE66B2B, 0xE4B51C, 0x7CC844,
|
||||||
|
0x52CBB0, 0x33B5E1, 0xA363D5, 0xD73C9A,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("solarized-dark", "Solarized Dark", [
|
||||||
|
0x002b36, 0x073642, 0x586e75, 0x657b83,
|
||||||
|
0x839496, 0x93a1a1, 0xeee8d5, 0xfdf6e3,
|
||||||
|
0xdc322f, 0xcb4b16, 0xb58900, 0x859900,
|
||||||
|
0x2aa198, 0x268bd2, 0x6c71c4, 0xd33682,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("solarized-light", "Solarized Light", [
|
||||||
|
0xfdf6e3, 0xeee8d5, 0x93a1a1, 0x839496,
|
||||||
|
0x657b83, 0x586e75, 0x073642, 0x002b36,
|
||||||
|
0xdc322f, 0xcb4b16, 0xb58900, 0x859900,
|
||||||
|
0x2aa198, 0x268bd2, 0x6c71c4, 0xd33682,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("spacemacs", "Spacemacs", [
|
||||||
|
0x1f2022, 0x282828, 0x444155, 0x585858,
|
||||||
|
0xb8b8b8, 0xa3a3a3, 0xe8e8e8, 0xf8f8f8,
|
||||||
|
0xf2241f, 0xffa500, 0xb1951d, 0x67b11d,
|
||||||
|
0x2d9574, 0x4f97d7, 0xa31db1, 0xb03060,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("summerfruit-dark", "Summerfruit Dark", [
|
||||||
|
0x151515, 0x202020, 0x303030, 0x505050,
|
||||||
|
0xB0B0B0, 0xD0D0D0, 0xE0E0E0, 0xFFFFFF,
|
||||||
|
0xFF0086, 0xFD8900, 0xABA800, 0x00C918,
|
||||||
|
0x1FAAAA, 0x3777E6, 0xAD00A1, 0xCC6633,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("summerfruit-light", "Summerfruit Light", [
|
||||||
|
0xFFFFFF, 0xE0E0E0, 0xD0D0D0, 0xB0B0B0,
|
||||||
|
0x000000, 0x101010, 0x151515, 0x202020,
|
||||||
|
0xFF0086, 0xFD8900, 0xABA800, 0x00C918,
|
||||||
|
0x1FAAAA, 0x3777E6, 0xAD00A1, 0xCC6633,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("synth-midnight-dark", "Synth Midnight", [
|
||||||
|
0x040404, 0x141414, 0x242424, 0x61507A,
|
||||||
|
0xBFBBBF, 0xDFDBDF, 0xEFEBEF, 0xFFFBFF,
|
||||||
|
0xB53B50, 0xE4600E, 0xDAE84D, 0x06EA61,
|
||||||
|
0x7CEDE9, 0x03AEFF, 0xEA5CE2, 0x9D4D0E,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("tomorrow-night-eighties", "Tomorrow Night Eighties", [
|
||||||
|
0x2d2d2d, 0x393939, 0x515151, 0x999999,
|
||||||
|
0xb4b7b4, 0xcccccc, 0xe0e0e0, 0xffffff,
|
||||||
|
0xf2777a, 0xf99157, 0xffcc66, 0x99cc99,
|
||||||
|
0x66cccc, 0x6699cc, 0xcc99cc, 0xa3685a,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("tomorrow-night", "Tomorrow Night", [
|
||||||
|
0x1d1f21, 0x282a2e, 0x373b41, 0x969896,
|
||||||
|
0xb4b7b4, 0xc5c8c6, 0xe0e0e0, 0xffffff,
|
||||||
|
0xcc6666, 0xde935f, 0xf0c674, 0xb5bd68,
|
||||||
|
0x8abeb7, 0x81a2be, 0xb294bb, 0xa3685a,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("tomorrow", "Tomorrow", [
|
||||||
|
0xffffff, 0xe0e0e0, 0xd6d6d6, 0x8e908c,
|
||||||
|
0x969896, 0x4d4d4c, 0x282a2e, 0x1d1f21,
|
||||||
|
0xc82829, 0xf5871f, 0xeab700, 0x718c00,
|
||||||
|
0x3e999f, 0x4271ae, 0x8959a8, 0xa3685a,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("tube", "London Tube", [
|
||||||
|
0x231f20, 0x1c3f95, 0x5a5758, 0x737171,
|
||||||
|
0x959ca1, 0xd9d8d8, 0xe7e7e8, 0xffffff,
|
||||||
|
0xee2e24, 0xf386a1, 0xffd204, 0x00853e,
|
||||||
|
0x85cebc, 0x009ddc, 0x98005d, 0xb06110,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("twilight", "Twilight", [
|
||||||
|
0x1e1e1e, 0x323537, 0x464b50, 0x5f5a60,
|
||||||
|
0x838184, 0xa7a7a7, 0xc3c3c3, 0xffffff,
|
||||||
|
0xcf6a4c, 0xcda869, 0xf9ee98, 0x8f9d6a,
|
||||||
|
0xafc4db, 0x7587a6, 0x9b859d, 0x9b703f,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("unikitty-dark", "Unikitty Dark", [
|
||||||
|
0x2e2a31, 0x4a464d, 0x666369, 0x838085,
|
||||||
|
0x9f9da2, 0xbcbabe, 0xd8d7da, 0xf5f4f7,
|
||||||
|
0xd8137f, 0xd65407, 0xdc8a0e, 0x17ad98,
|
||||||
|
0x149bda, 0x796af5, 0xbb60ea, 0xc720ca,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("unikitty-light", "Unikitty Light", [
|
||||||
|
0xffffff, 0xe1e1e2, 0xc4c3c5, 0xa7a5a8,
|
||||||
|
0x89878b, 0x6c696e, 0x4f4b51, 0x322d34,
|
||||||
|
0xd8137f, 0xd65407, 0xdc8a0e, 0x17ad98,
|
||||||
|
0x149bda, 0x775dff, 0xaa17e6, 0xe013d0,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("woodland", "Woodland", [
|
||||||
|
0x231e18, 0x302b25, 0x48413a, 0x9d8b70,
|
||||||
|
0xb4a490, 0xcabcb1, 0xd7c8bc, 0xe4d4c8,
|
||||||
|
0xd35c5c, 0xca7f32, 0xe0ac16, 0xb7ba53,
|
||||||
|
0x6eb958, 0x88a4d3, 0xbb90e2, 0xb49368,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("xcode-dusk", "XCode Dusk", [
|
||||||
|
0x282B35, 0x3D4048, 0x53555D, 0x686A71,
|
||||||
|
0x7E8086, 0x939599, 0xA9AAAE, 0xBEBFC2,
|
||||||
|
0xB21889, 0x786DC5, 0x438288, 0xDF0002,
|
||||||
|
0x00A0BE, 0x790EAD, 0xB21889, 0xC77C48,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("zenburn", "Zenburn", [
|
||||||
|
0x383838, 0x404040, 0x606060, 0x6f6f6f,
|
||||||
|
0x808080, 0xdcdccc, 0xc0c0c0, 0xffffff,
|
||||||
|
0xdca3a3, 0xdfaf8f, 0xe0cf9f, 0x5f7f5f,
|
||||||
|
0x93e0e3, 0x7cb8bb, 0xdc8cc3, 0x000000,
|
||||||
|
]);
|
111
js/colors/ColorSchemeModel.js
Normal file
111
js/colors/ColorSchemeModel.js
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
var _a;
|
||||||
|
import GObject from 'gi://GObject';
|
||||||
|
import Gio from 'gi://Gio';
|
||||||
|
import Gtk from 'gi://Gtk?version=4.0';
|
||||||
|
import { Base16Theme } from './Base16Theme.js';
|
||||||
|
export class ColorSchemeModel {
|
||||||
|
constructor() {
|
||||||
|
let builder = new TreeModelBuilder();
|
||||||
|
this.treeModel = builder.buildTreeModel();
|
||||||
|
this.selection = Gtk.SingleSelection.new(this.treeModel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
class ColorModelNode extends GObject.Object {
|
||||||
|
constructor(data) {
|
||||||
|
super();
|
||||||
|
this.data = data;
|
||||||
|
}
|
||||||
|
get text() {
|
||||||
|
return this.data.name;
|
||||||
|
}
|
||||||
|
child_model() {
|
||||||
|
if (this.data instanceof ColorThemeCategory) {
|
||||||
|
return this.data.children;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
isThemeWithId(id) {
|
||||||
|
return (this.data instanceof Base16Theme) &&
|
||||||
|
(this.data.id === id);
|
||||||
|
}
|
||||||
|
hasChildThemeWithId(id) {
|
||||||
|
const child_model = this.child_model();
|
||||||
|
if (child_model) {
|
||||||
|
for (let i = 0; i < child_model.n_items; i++) {
|
||||||
|
let node = child_model.get_item(i);
|
||||||
|
if (node.isThemeWithId(id)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
static newScheme(color) {
|
||||||
|
return new _a(color);
|
||||||
|
}
|
||||||
|
static newCategory(category) {
|
||||||
|
return new _a(category);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_a = ColorModelNode;
|
||||||
|
(() => {
|
||||||
|
GObject.registerClass({
|
||||||
|
GTypeName: 'ColorModelNode',
|
||||||
|
Properties: {
|
||||||
|
'text': GObject.ParamSpec.string('text', '', '', GObject.ParamFlags.READWRITE, ''),
|
||||||
|
}
|
||||||
|
}, _a);
|
||||||
|
})();
|
||||||
|
class ColorThemeCategory {
|
||||||
|
constructor(name) {
|
||||||
|
this.name = name;
|
||||||
|
this.children = new Gio.ListStore(ColorModelNode);
|
||||||
|
}
|
||||||
|
append(color) {
|
||||||
|
this.children.append(ColorModelNode.newScheme(color));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
class TreeModelBuilder {
|
||||||
|
constructor() {
|
||||||
|
this.categories = Base16Theme.CATEGORIES;
|
||||||
|
this.currentCategory = null;
|
||||||
|
this.storeModel = new Gio.ListStore(ColorModelNode);
|
||||||
|
}
|
||||||
|
buildTreeModel() {
|
||||||
|
Base16Theme.THEMES.forEach(theme => this.addTheme(theme));
|
||||||
|
return Gtk.TreeListModel.new(this.storeModel, false, false, item => item.child_model());
|
||||||
|
}
|
||||||
|
appendCurrentCategory() {
|
||||||
|
if (this.currentCategory) {
|
||||||
|
this.storeModel.append(ColorModelNode.newCategory(this.currentCategory));
|
||||||
|
this.currentCategory = null;
|
||||||
|
this.categories.shift();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
matchesNextCategory(theme) {
|
||||||
|
if (this.categories.length === 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
let [id, _name] = this.categories[0];
|
||||||
|
return theme.id === id;
|
||||||
|
}
|
||||||
|
addTheme(theme) {
|
||||||
|
if (this.matchesNextCategory(theme)) {
|
||||||
|
this.addToCategory(theme);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (this.currentCategory) {
|
||||||
|
this.appendCurrentCategory();
|
||||||
|
}
|
||||||
|
this.storeModel.append(ColorModelNode.newScheme(theme));
|
||||||
|
}
|
||||||
|
addToCategory(theme) {
|
||||||
|
if (!this.currentCategory) {
|
||||||
|
let [_id, name] = this.categories[0];
|
||||||
|
this.currentCategory = new ColorThemeCategory(name);
|
||||||
|
}
|
||||||
|
this.currentCategory.append(theme);
|
||||||
|
}
|
||||||
|
}
|
6
js/main.js
Normal file
6
js/main.js
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
import 'gi://Gdk?version=4.0';
|
||||||
|
import 'gi://Gtk?version=4.0';
|
||||||
|
import { Application } from './Application.js';
|
||||||
|
export function main(argv) {
|
||||||
|
return new Application().run(argv);
|
||||||
|
}
|
809
js/model/Base16Themes.js
Normal file
809
js/model/Base16Themes.js
Normal file
@ -0,0 +1,809 @@
|
|||||||
|
const TERM_MAP = [
|
||||||
|
0x00, 0x08, 0x0B, 0x0A, 0x0D, 0x0E, 0x0C, 0x05,
|
||||||
|
0x03, 0x08, 0x0B, 0x0A, 0x0D, 0x0E, 0x0C, 0x07,
|
||||||
|
0x09, 0x0F, 0x01, 0x02, 0x04, 0x06,
|
||||||
|
];
|
||||||
|
export class Base16Theme {
|
||||||
|
constructor(id, name, colors) {
|
||||||
|
this.id = id;
|
||||||
|
this.name = name;
|
||||||
|
this.colors = colors;
|
||||||
|
}
|
||||||
|
static add(id, name, colors) {
|
||||||
|
const theme = new Base16Theme(id, name, colors);
|
||||||
|
Base16Theme.THEME_LIST.push(theme);
|
||||||
|
Base16Theme.THEMES.set(id, theme);
|
||||||
|
}
|
||||||
|
static lookup(id) {
|
||||||
|
return Base16Theme.THEMES.get(id);
|
||||||
|
}
|
||||||
|
color(idx) {
|
||||||
|
let hex = this.colors[idx].toString(16).padStart(6, '0');
|
||||||
|
return `#${hex}`;
|
||||||
|
}
|
||||||
|
terminal_background() {
|
||||||
|
return this.color(0);
|
||||||
|
}
|
||||||
|
terminal_foreground() {
|
||||||
|
return this.color(5);
|
||||||
|
}
|
||||||
|
terminal_palette_color(idx) {
|
||||||
|
return this.color(TERM_MAP[idx]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Base16Theme.THEMES = new Map();
|
||||||
|
Base16Theme.THEME_LIST = [];
|
||||||
|
Base16Theme.add("3024", "3024", [
|
||||||
|
0x090300, 0x3a3432, 0x4a4543, 0x5c5855,
|
||||||
|
0x807d7c, 0xa5a2a2, 0xd6d5d4, 0xf7f7f7,
|
||||||
|
0xdb2d20, 0xe8bbd0, 0xfded02, 0x01a252,
|
||||||
|
0xb5e4f4, 0x01a0e4, 0xa16a94, 0xcdab53,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("apathy", 'Apathy', [
|
||||||
|
0x031A16, 0x0B342D, 0x184E45, 0x2B685E,
|
||||||
|
0x5F9C92, 0x81B5AC, 0xA7CEC8, 0xD2E7E4,
|
||||||
|
0x3E9688, 0x3E7996, 0x3E4C96, 0x883E96,
|
||||||
|
0x963E4C, 0x96883E, 0x4C963E, 0x3E965B,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("ashes", "Ashes", [
|
||||||
|
0x1C2023, 0x393F45, 0x565E65, 0x747C84,
|
||||||
|
0xADB3BA, 0xC7CCD1, 0xDFE2E5, 0xF3F4F5,
|
||||||
|
0xC7AE95, 0xC7C795, 0xAEC795, 0x95C7AE,
|
||||||
|
0x95AEC7, 0xAE95C7, 0xC795AE, 0xC79595,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("atelier-cave-light", "Atelier Cave Light", [
|
||||||
|
0xefecf4, 0xe2dfe7, 0x8b8792, 0x7e7887,
|
||||||
|
0x655f6d, 0x585260, 0x26232a, 0x19171c,
|
||||||
|
0xbe4678, 0xaa573c, 0xa06e3b, 0x2a9292,
|
||||||
|
0x398bc6, 0x576ddb, 0x955ae7, 0xbf40bf,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("atelier-cave", "Atelier Cave", [
|
||||||
|
0x19171c, 0x26232a, 0x585260, 0x655f6d,
|
||||||
|
0x7e7887, 0x8b8792, 0xe2dfe7, 0xefecf4,
|
||||||
|
0xbe4678, 0xaa573c, 0xa06e3b, 0x2a9292,
|
||||||
|
0x398bc6, 0x576ddb, 0x955ae7, 0xbf40bf,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("atelier-dune-light", "Atelier Dune Light", [
|
||||||
|
0xfefbec, 0xe8e4cf, 0xa6a28c, 0x999580,
|
||||||
|
0x7d7a68, 0x6e6b5e, 0x292824, 0x20201d,
|
||||||
|
0xd73737, 0xb65611, 0xae9513, 0x60ac39,
|
||||||
|
0x1fad83, 0x6684e1, 0xb854d4, 0xd43552,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("atelier-dune", "Atelier Dune", [
|
||||||
|
0x20201d, 0x292824, 0x6e6b5e, 0x7d7a68,
|
||||||
|
0x999580, 0xa6a28c, 0xe8e4cf, 0xfefbec,
|
||||||
|
0xd73737, 0xb65611, 0xae9513, 0x60ac39,
|
||||||
|
0x1fad83, 0x6684e1, 0xb854d4, 0xd43552,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("atelier-estuary-light", "Atelier Estuary Light", [
|
||||||
|
0xf4f3ec, 0xe7e6df, 0x929181, 0x878573,
|
||||||
|
0x6c6b5a, 0x5f5e4e, 0x302f27, 0x22221b,
|
||||||
|
0xba6236, 0xae7313, 0xa5980d, 0x7d9726,
|
||||||
|
0x5b9d48, 0x36a166, 0x5f9182, 0x9d6c7c,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("atelier-estuary", "Atelier Estuary", [
|
||||||
|
0x22221b, 0x302f27, 0x5f5e4e, 0x6c6b5a,
|
||||||
|
0x878573, 0x929181, 0xe7e6df, 0xf4f3ec,
|
||||||
|
0xba6236, 0xae7313, 0xa5980d, 0x7d9726,
|
||||||
|
0x5b9d48, 0x36a166, 0x5f9182, 0x9d6c7c,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("atelier-forest-light", "Atelier Forest Light", [
|
||||||
|
0xf1efee, 0xe6e2e0, 0xa8a19f, 0x9c9491,
|
||||||
|
0x766e6b, 0x68615e, 0x2c2421, 0x1b1918,
|
||||||
|
0xf22c40, 0xdf5320, 0xc38418, 0x7b9726,
|
||||||
|
0x3d97b8, 0x407ee7, 0x6666ea, 0xc33ff3,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("atelier-forest", "Atelier Forest", [
|
||||||
|
0x1b1918, 0x2c2421, 0x68615e, 0x766e6b,
|
||||||
|
0x9c9491, 0xa8a19f, 0xe6e2e0, 0xf1efee,
|
||||||
|
0xf22c40, 0xdf5320, 0xc38418, 0x7b9726,
|
||||||
|
0x3d97b8, 0x407ee7, 0x6666ea, 0xc33ff3,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("atelier-heath-light", "Atelier Heath Light", [
|
||||||
|
0xf7f3f7, 0xd8cad8, 0xab9bab, 0x9e8f9e,
|
||||||
|
0x776977, 0x695d69, 0x292329, 0x1b181b,
|
||||||
|
0xca402b, 0xa65926, 0xbb8a35, 0x918b3b,
|
||||||
|
0x159393, 0x516aec, 0x7b59c0, 0xcc33cc,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("atelier-heath", "Atelier Heath", [
|
||||||
|
0x1b181b, 0x292329, 0x695d69, 0x776977,
|
||||||
|
0x9e8f9e, 0xab9bab, 0xd8cad8, 0xf7f3f7,
|
||||||
|
0xca402b, 0xa65926, 0xbb8a35, 0x918b3b,
|
||||||
|
0x159393, 0x516aec, 0x7b59c0, 0xcc33cc,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("atelier-lakeside-light", "Atelier Lakeside Light", [
|
||||||
|
0xebf8ff, 0xc1e4f6, 0x7ea2b4, 0x7195a8,
|
||||||
|
0x5a7b8c, 0x516d7b, 0x1f292e, 0x161b1d,
|
||||||
|
0xd22d72, 0x935c25, 0x8a8a0f, 0x568c3b,
|
||||||
|
0x2d8f6f, 0x257fad, 0x6b6bb8, 0xb72dd2,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("atelier-lakeside", "Atelier Lakeside", [
|
||||||
|
0x161b1d, 0x1f292e, 0x516d7b, 0x5a7b8c,
|
||||||
|
0x7195a8, 0x7ea2b4, 0xc1e4f6, 0xebf8ff,
|
||||||
|
0xd22d72, 0x935c25, 0x8a8a0f, 0x568c3b,
|
||||||
|
0x2d8f6f, 0x257fad, 0x6b6bb8, 0xb72dd2,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("atelier-plateau-light", "Atelier Plateau Light", [
|
||||||
|
0xf4ecec, 0xe7dfdf, 0x8a8585, 0x7e7777,
|
||||||
|
0x655d5d, 0x585050, 0x292424, 0x1b1818,
|
||||||
|
0xca4949, 0xb45a3c, 0xa06e3b, 0x4b8b8b,
|
||||||
|
0x5485b6, 0x7272ca, 0x8464c4, 0xbd5187,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("atelier-plateau", "Atelier Plateau", [
|
||||||
|
0x1b1818, 0x292424, 0x585050, 0x655d5d,
|
||||||
|
0x7e7777, 0x8a8585, 0xe7dfdf, 0xf4ecec,
|
||||||
|
0xca4949, 0xb45a3c, 0xa06e3b, 0x4b8b8b,
|
||||||
|
0x5485b6, 0x7272ca, 0x8464c4, 0xbd5187,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("atelier-savanna-light", "Atelier Savanna Light", [
|
||||||
|
0xecf4ee, 0xdfe7e2, 0x87928a, 0x78877d,
|
||||||
|
0x5f6d64, 0x526057, 0x232a25, 0x171c19,
|
||||||
|
0xb16139, 0x9f713c, 0xa07e3b, 0x489963,
|
||||||
|
0x1c9aa0, 0x478c90, 0x55859b, 0x867469,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("atelier-savanna", "Atelier Savanna", [
|
||||||
|
0x171c19, 0x232a25, 0x526057, 0x5f6d64,
|
||||||
|
0x78877d, 0x87928a, 0xdfe7e2, 0xecf4ee,
|
||||||
|
0xb16139, 0x9f713c, 0xa07e3b, 0x489963,
|
||||||
|
0x1c9aa0, 0x478c90, 0x55859b, 0x867469,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("atelier-seaside-light", "Atelier Seaside Light", [
|
||||||
|
0xf4fbf4, 0xcfe8cf, 0x8ca68c, 0x809980,
|
||||||
|
0x687d68, 0x5e6e5e, 0x242924, 0x131513,
|
||||||
|
0xe6193c, 0x87711d, 0x98981b, 0x29a329,
|
||||||
|
0x1999b3, 0x3d62f5, 0xad2bee, 0xe619c3,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("atelier-seaside", "Atelier Seaside", [
|
||||||
|
0x131513, 0x242924, 0x5e6e5e, 0x687d68,
|
||||||
|
0x809980, 0x8ca68c, 0xcfe8cf, 0xf4fbf4,
|
||||||
|
0xe6193c, 0x87711d, 0x98981b, 0x29a329,
|
||||||
|
0x1999b3, 0x3d62f5, 0xad2bee, 0xe619c3,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("atelier-sulphurpool-light", "Atelier Sulphurpool Light", [
|
||||||
|
0xf5f7ff, 0xdfe2f1, 0x979db4, 0x898ea4,
|
||||||
|
0x6b7394, 0x5e6687, 0x293256, 0x202746,
|
||||||
|
0xc94922, 0xc76b29, 0xc08b30, 0xac9739,
|
||||||
|
0x22a2c9, 0x3d8fd1, 0x6679cc, 0x9c637a,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("atelier-sulphurpool", "Atelier Sulphurpool", [
|
||||||
|
0x202746, 0x293256, 0x5e6687, 0x6b7394,
|
||||||
|
0x898ea4, 0x979db4, 0xdfe2f1, 0xf5f7ff,
|
||||||
|
0xc94922, 0xc76b29, 0xc08b30, 0xac9739,
|
||||||
|
0x22a2c9, 0x3d8fd1, 0x6679cc, 0x9c637a,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("atlas", "Atlas", [
|
||||||
|
0x002635, 0x00384d, 0x517F8D, 0x6C8B91,
|
||||||
|
0x869696, 0xa1a19a, 0xe6e6dc, 0xfafaf8,
|
||||||
|
0xff5a67, 0xf08e48, 0xffcc1b, 0x7fc06e,
|
||||||
|
0x14747e, 0x5dd7b9, 0x9a70a4, 0xc43060,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("bespin", "Bespin", [
|
||||||
|
0x28211c, 0x36312e, 0x5e5d5c, 0x666666,
|
||||||
|
0x797977, 0x8a8986, 0x9d9b97, 0xbaae9e,
|
||||||
|
0xcf6a4c, 0xcf7d34, 0xf9ee98, 0x54be0d,
|
||||||
|
0xafc4db, 0x5ea6ea, 0x9b859d, 0x937121,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("black-metal-bathory", "Black Metal (Bathory)", [
|
||||||
|
0x000000, 0x121212, 0x222222, 0x333333,
|
||||||
|
0x999999, 0xc1c1c1, 0x999999, 0xc1c1c1,
|
||||||
|
0x5f8787, 0xaaaaaa, 0xe78a53, 0xfbcb97,
|
||||||
|
0xaaaaaa, 0x888888, 0x999999, 0x444444,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("black-metal-burzum", "Black Metal (Burzum)", [
|
||||||
|
0x000000, 0x121212, 0x222222, 0x333333,
|
||||||
|
0x999999, 0xc1c1c1, 0x999999, 0xc1c1c1,
|
||||||
|
0x5f8787, 0xaaaaaa, 0x99bbaa, 0xddeecc,
|
||||||
|
0xaaaaaa, 0x888888, 0x999999, 0x444444,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("black-metal-dark-funeral", "Black Metal (Dark Funeral)", [
|
||||||
|
0x000000, 0x121212, 0x222222, 0x333333,
|
||||||
|
0x999999, 0xc1c1c1, 0x999999, 0xc1c1c1,
|
||||||
|
0x5f8787, 0xaaaaaa, 0x5f81a5, 0xd0dfee,
|
||||||
|
0xaaaaaa, 0x888888, 0x999999, 0x444444,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("black-metal-gorgoroth", "Black Metal (Gorgoroth)", [
|
||||||
|
0x000000, 0x121212, 0x222222, 0x333333,
|
||||||
|
0x999999, 0xc1c1c1, 0x999999, 0xc1c1c1,
|
||||||
|
0x5f8787, 0xaaaaaa, 0x8c7f70, 0x9b8d7f,
|
||||||
|
0xaaaaaa, 0x888888, 0x999999, 0x444444,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("black-metal-immortal", "Black Metal (Immortal)", [
|
||||||
|
0x000000, 0x121212, 0x222222, 0x333333,
|
||||||
|
0x999999, 0xc1c1c1, 0x999999, 0xc1c1c1,
|
||||||
|
0x5f8787, 0xaaaaaa, 0x556677, 0x7799bb,
|
||||||
|
0xaaaaaa, 0x888888, 0x999999, 0x444444,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("black-metal-khold", "Black Metal (Khold)", [
|
||||||
|
0x000000, 0x121212, 0x222222, 0x333333,
|
||||||
|
0x999999, 0xc1c1c1, 0x999999, 0xc1c1c1,
|
||||||
|
0x5f8787, 0xaaaaaa, 0x974b46, 0xeceee3,
|
||||||
|
0xaaaaaa, 0x888888, 0x999999, 0x444444,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("black-metal-marduk", "Black Metal (Marduk)", [
|
||||||
|
0x000000, 0x121212, 0x222222, 0x333333,
|
||||||
|
0x999999, 0xc1c1c1, 0x999999, 0xc1c1c1,
|
||||||
|
0x5f8787, 0xaaaaaa, 0x626b67, 0xa5aaa7,
|
||||||
|
0xaaaaaa, 0x888888, 0x999999, 0x444444,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("black-metal-mayhem", "Black Metal (Mayhem)", [
|
||||||
|
0x000000, 0x121212, 0x222222, 0x333333,
|
||||||
|
0x999999, 0xc1c1c1, 0x999999, 0xc1c1c1,
|
||||||
|
0x5f8787, 0xaaaaaa, 0xeecc6c, 0xf3ecd4,
|
||||||
|
0xaaaaaa, 0x888888, 0x999999, 0x444444,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("black-metal-nile", "Black Metal (Nile)", [
|
||||||
|
0x000000, 0x121212, 0x222222, 0x333333,
|
||||||
|
0x999999, 0xc1c1c1, 0x999999, 0xc1c1c1,
|
||||||
|
0x5f8787, 0xaaaaaa, 0x777755, 0xaa9988,
|
||||||
|
0xaaaaaa, 0x888888, 0x999999, 0x444444,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("black-metal-venom", "Black Metal (Venom)", [
|
||||||
|
0x000000, 0x121212, 0x222222, 0x333333,
|
||||||
|
0x999999, 0xc1c1c1, 0x999999, 0xc1c1c1,
|
||||||
|
0x5f8787, 0xaaaaaa, 0x79241f, 0xf8f7f2,
|
||||||
|
0xaaaaaa, 0x888888, 0x999999, 0x444444,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("black-metal", "Black Metal", [
|
||||||
|
0x000000, 0x121212, 0x222222, 0x333333,
|
||||||
|
0x999999, 0xc1c1c1, 0x999999, 0xc1c1c1,
|
||||||
|
0x5f8787, 0xaaaaaa, 0xa06666, 0xdd9999,
|
||||||
|
0xaaaaaa, 0x888888, 0x999999, 0x444444,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("brewer", "Brewer", [
|
||||||
|
0x0c0d0e, 0x2e2f30, 0x515253, 0x737475,
|
||||||
|
0x959697, 0xb7b8b9, 0xdadbdc, 0xfcfdfe,
|
||||||
|
0xe31a1c, 0xe6550d, 0xdca060, 0x31a354,
|
||||||
|
0x80b1d3, 0x3182bd, 0x756bb1, 0xb15928,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("bright", "Bright", [
|
||||||
|
0x000000, 0x303030, 0x505050, 0xb0b0b0,
|
||||||
|
0xd0d0d0, 0xe0e0e0, 0xf5f5f5, 0xffffff,
|
||||||
|
0xfb0120, 0xfc6d24, 0xfda331, 0xa1c659,
|
||||||
|
0x76c7b7, 0x6fb3d2, 0xd381c3, 0xbe643c,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("brogrammer", "Brogrammer", [
|
||||||
|
0x1f1f1f, 0xf81118, 0x2dc55e, 0xecba0f,
|
||||||
|
0x2a84d2, 0x4e5ab7, 0x1081d6, 0xd6dbe5,
|
||||||
|
0xd6dbe5, 0xde352e, 0x1dd361, 0xf3bd09,
|
||||||
|
0x1081d6, 0x5350b9, 0x0f7ddb, 0xffffff,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("brushtrees-dark", "Brush Trees Dark", [
|
||||||
|
0x485867, 0x5A6D7A, 0x6D828E, 0x8299A1,
|
||||||
|
0x98AFB5, 0xB0C5C8, 0xC9DBDC, 0xE3EFEF,
|
||||||
|
0xb38686, 0xd8bba2, 0xaab386, 0x87b386,
|
||||||
|
0x86b3b3, 0x868cb3, 0xb386b2, 0xb39f9f,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("brushtrees", "Brush Trees", [
|
||||||
|
0xE3EFEF, 0xC9DBDC, 0xB0C5C8, 0x98AFB5,
|
||||||
|
0x8299A1, 0x6D828E, 0x5A6D7A, 0x485867,
|
||||||
|
0xb38686, 0xd8bba2, 0xaab386, 0x87b386,
|
||||||
|
0x86b3b3, 0x868cb3, 0xb386b2, 0xb39f9f,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("chalk", "Chalk", [
|
||||||
|
0x151515, 0x202020, 0x303030, 0x505050,
|
||||||
|
0xb0b0b0, 0xd0d0d0, 0xe0e0e0, 0xf5f5f5,
|
||||||
|
0xfb9fb1, 0xeda987, 0xddb26f, 0xacc267,
|
||||||
|
0x12cfc0, 0x6fc2ef, 0xe1a3ee, 0xdeaf8f,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("circus", "Circus", [
|
||||||
|
0x191919, 0x202020, 0x303030, 0x5f5a60,
|
||||||
|
0x505050, 0xa7a7a7, 0x808080, 0xffffff,
|
||||||
|
0xdc657d, 0x4bb1a7, 0xc3ba63, 0x84b97c,
|
||||||
|
0x4bb1a7, 0x639ee4, 0xb888e2, 0xb888e2,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("classic-dark", "Classic Dark", [
|
||||||
|
0x151515, 0x202020, 0x303030, 0x505050,
|
||||||
|
0xB0B0B0, 0xD0D0D0, 0xE0E0E0, 0xF5F5F5,
|
||||||
|
0xAC4142, 0xD28445, 0xF4BF75, 0x90A959,
|
||||||
|
0x75B5AA, 0x6A9FB5, 0xAA759F, 0x8F5536,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("classic-light", "Classic Light", [
|
||||||
|
0xF5F5F5, 0xE0E0E0, 0xD0D0D0, 0xB0B0B0,
|
||||||
|
0x505050, 0x303030, 0x202020, 0x151515,
|
||||||
|
0xAC4142, 0xD28445, 0xF4BF75, 0x90A959,
|
||||||
|
0x75B5AA, 0x6A9FB5, 0xAA759F, 0x8F5536,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("codeschool", "Codeschool", [
|
||||||
|
0x232c31, 0x1c3657, 0x2a343a, 0x3f4944,
|
||||||
|
0x84898c, 0x9ea7a6, 0xa7cfa3, 0xb5d8f6,
|
||||||
|
0x2a5491, 0x43820d, 0xa03b1e, 0x237986,
|
||||||
|
0xb02f30, 0x484d79, 0xc59820, 0xc98344,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("cupcake", "Cupcake", [
|
||||||
|
0xfbf1f2, 0xf2f1f4, 0xd8d5dd, 0xbfb9c6,
|
||||||
|
0xa59daf, 0x8b8198, 0x72677E, 0x585062,
|
||||||
|
0xD57E85, 0xEBB790, 0xDCB16C, 0xA3B367,
|
||||||
|
0x69A9A7, 0x7297B9, 0xBB99B4, 0xBAA58C,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("cupertino", "Cupertino", [
|
||||||
|
0xffffff, 0xc0c0c0, 0xc0c0c0, 0x808080,
|
||||||
|
0x808080, 0x404040, 0x404040, 0x5e5e5e,
|
||||||
|
0xc41a15, 0xeb8500, 0x826b28, 0x007400,
|
||||||
|
0x318495, 0x0000ff, 0xa90d91, 0x826b28,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("darktooth", "Darktooth", [
|
||||||
|
0x1D2021, 0x32302F, 0x504945, 0x665C54,
|
||||||
|
0x928374, 0xA89984, 0xD5C4A1, 0xFDF4C1,
|
||||||
|
0xFB543F, 0xFE8625, 0xFAC03B, 0x95C085,
|
||||||
|
0x8BA59B, 0x0D6678, 0x8F4673, 0xA87322,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("default-dark", "Default Dark", [
|
||||||
|
0x181818, 0x282828, 0x383838, 0x585858,
|
||||||
|
0xb8b8b8, 0xd8d8d8, 0xe8e8e8, 0xf8f8f8,
|
||||||
|
0xab4642, 0xdc9656, 0xf7ca88, 0xa1b56c,
|
||||||
|
0x86c1b9, 0x7cafc2, 0xba8baf, 0xa16946,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("default-light", "Default Light", [
|
||||||
|
0xf8f8f8, 0xe8e8e8, 0xd8d8d8, 0xb8b8b8,
|
||||||
|
0x585858, 0x383838, 0x282828, 0x181818,
|
||||||
|
0xab4642, 0xdc9656, 0xf7ca88, 0xa1b56c,
|
||||||
|
0x86c1b9, 0x7cafc2, 0xba8baf, 0xa16946,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("dracula", "Dracula", [
|
||||||
|
0x282936, 0x3a3c4e, 0x4d4f68, 0x626483,
|
||||||
|
0x62d6e8, 0xe9e9f4, 0xf1f2f8, 0xf7f7fb,
|
||||||
|
0xea51b2, 0xb45bcf, 0x00f769, 0xebff87,
|
||||||
|
0xa1efe4, 0x62d6e8, 0xb45bcf, 0x00f769,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("eighties", "Eighties", [
|
||||||
|
0x2d2d2d, 0x393939, 0x515151, 0x747369,
|
||||||
|
0xa09f93, 0xd3d0c8, 0xe8e6df, 0xf2f0ec,
|
||||||
|
0xf2777a, 0xf99157, 0xffcc66, 0x99cc99,
|
||||||
|
0x66cccc, 0x6699cc, 0xcc99cc, 0xd27b53,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("embers", "Embers", [
|
||||||
|
0x16130F, 0x2C2620, 0x433B32, 0x5A5047,
|
||||||
|
0x8A8075, 0xA39A90, 0xBEB6AE, 0xDBD6D1,
|
||||||
|
0x826D57, 0x828257, 0x6D8257, 0x57826D,
|
||||||
|
0x576D82, 0x6D5782, 0x82576D, 0x825757,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("flat", "Flat", [
|
||||||
|
0x2C3E50, 0x34495E, 0x7F8C8D, 0x95A5A6,
|
||||||
|
0xBDC3C7, 0xe0e0e0, 0xf5f5f5, 0xECF0F1,
|
||||||
|
0xE74C3C, 0xE67E22, 0xF1C40F, 0x2ECC71,
|
||||||
|
0x1ABC9C, 0x3498DB, 0x9B59B6, 0xbe643c,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("fruit-soda", "Fruit Soda", [
|
||||||
|
0xf1ecf1, 0xe0dee0, 0xd8d5d5, 0xb5b4b6,
|
||||||
|
0x979598, 0x515151, 0x474545, 0x2d2c2c,
|
||||||
|
0xfe3e31, 0xfe6d08, 0xf7e203, 0x47f74c,
|
||||||
|
0x0f9cfd, 0x2931df, 0x611fce, 0xb16f40,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("github", "Github", [
|
||||||
|
0xffffff, 0xf5f5f5, 0xc8c8fa, 0x969896,
|
||||||
|
0xe8e8e8, 0x333333, 0xffffff, 0xffffff,
|
||||||
|
0xed6a43, 0x0086b3, 0x795da3, 0x183691,
|
||||||
|
0x183691, 0x795da3, 0xa71d5d, 0x333333,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("google-dark", "Google Dark", [
|
||||||
|
0x1d1f21, 0x282a2e, 0x373b41, 0x969896,
|
||||||
|
0xb4b7b4, 0xc5c8c6, 0xe0e0e0, 0xffffff,
|
||||||
|
0xCC342B, 0xF96A38, 0xFBA922, 0x198844,
|
||||||
|
0x3971ED, 0x3971ED, 0xA36AC7, 0x3971ED,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("google-light", "Google Light", [
|
||||||
|
0xffffff, 0xe0e0e0, 0xc5c8c6, 0xb4b7b4,
|
||||||
|
0x969896, 0x373b41, 0x282a2e, 0x1d1f21,
|
||||||
|
0xCC342B, 0xF96A38, 0xFBA922, 0x198844,
|
||||||
|
0x3971ED, 0x3971ED, 0xA36AC7, 0x3971ED,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("grayscale-dark", "Grayscale Dark", [
|
||||||
|
0x101010, 0x252525, 0x464646, 0x525252,
|
||||||
|
0xababab, 0xb9b9b9, 0xe3e3e3, 0xf7f7f7,
|
||||||
|
0x7c7c7c, 0x999999, 0xa0a0a0, 0x8e8e8e,
|
||||||
|
0x868686, 0x686868, 0x747474, 0x5e5e5e,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("grayscale-light", "Grayscale Light", [
|
||||||
|
0xf7f7f7, 0xe3e3e3, 0xb9b9b9, 0xababab,
|
||||||
|
0x525252, 0x464646, 0x252525, 0x101010,
|
||||||
|
0x7c7c7c, 0x999999, 0xa0a0a0, 0x8e8e8e,
|
||||||
|
0x868686, 0x686868, 0x747474, 0x5e5e5e,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("greenscreen", "Green Screen", [
|
||||||
|
0x001100, 0x003300, 0x005500, 0x007700,
|
||||||
|
0x009900, 0x00bb00, 0x00dd00, 0x00ff00,
|
||||||
|
0x007700, 0x009900, 0x007700, 0x00bb00,
|
||||||
|
0x005500, 0x009900, 0x00bb00, 0x005500,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("gruvbox-dark-hard", "Gruvbox dark, hard", [
|
||||||
|
0x1d2021, 0x3c3836, 0x504945, 0x665c54,
|
||||||
|
0xbdae93, 0xd5c4a1, 0xebdbb2, 0xfbf1c7,
|
||||||
|
0xfb4934, 0xfe8019, 0xfabd2f, 0xb8bb26,
|
||||||
|
0x8ec07c, 0x83a598, 0xd3869b, 0xd65d0e,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("gruvbox-dark-medium", "Gruvbox dark, medium", [
|
||||||
|
0x282828, 0x3c3836, 0x504945, 0x665c54,
|
||||||
|
0xbdae93, 0xd5c4a1, 0xebdbb2, 0xfbf1c7,
|
||||||
|
0xfb4934, 0xfe8019, 0xfabd2f, 0xb8bb26,
|
||||||
|
0x8ec07c, 0x83a598, 0xd3869b, 0xd65d0e,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("gruvbox-dark-pale", "Gruvbox dark, pale", [
|
||||||
|
0x262626, 0x3a3a3a, 0x4e4e4e, 0x8a8a8a,
|
||||||
|
0x949494, 0xdab997, 0xd5c4a1, 0xebdbb2,
|
||||||
|
0xd75f5f, 0xff8700, 0xffaf00, 0xafaf00,
|
||||||
|
0x85ad85, 0x83adad, 0xd485ad, 0xd65d0e,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("gruvbox-dark-soft", "Gruvbox dark, soft", [
|
||||||
|
0x32302f, 0x3c3836, 0x504945, 0x665c54,
|
||||||
|
0xbdae93, 0xd5c4a1, 0xebdbb2, 0xfbf1c7,
|
||||||
|
0xfb4934, 0xfe8019, 0xfabd2f, 0xb8bb26,
|
||||||
|
0x8ec07c, 0x83a598, 0xd3869b, 0xd65d0e,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("gruvbox-light-hard", "Gruvbox light, hard", [
|
||||||
|
0xf9f5d7, 0xebdbb2, 0xd5c4a1, 0xbdae93,
|
||||||
|
0x665c54, 0x504945, 0x3c3836, 0x282828,
|
||||||
|
0x9d0006, 0xaf3a03, 0xb57614, 0x79740e,
|
||||||
|
0x427b58, 0x076678, 0x8f3f71, 0xd65d0e,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("gruvbox-light-medium", "Gruvbox light, medium", [
|
||||||
|
0xfbf1c7, 0xebdbb2, 0xd5c4a1, 0xbdae93,
|
||||||
|
0x665c54, 0x504945, 0x3c3836, 0x282828,
|
||||||
|
0x9d0006, 0xaf3a03, 0xb57614, 0x79740e,
|
||||||
|
0x427b58, 0x076678, 0x8f3f71, 0xd65d0e,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("gruvbox-light-soft", "Gruvbox light, soft", [
|
||||||
|
0xf2e5bc, 0xebdbb2, 0xd5c4a1, 0xbdae93,
|
||||||
|
0x665c54, 0x504945, 0x3c3836, 0x282828,
|
||||||
|
0x9d0006, 0xaf3a03, 0xb57614, 0x79740e,
|
||||||
|
0x427b58, 0x076678, 0x8f3f71, 0xd65d0e,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("harmonic-dark", "Harmonic16 Dark", [
|
||||||
|
0x0b1c2c, 0x223b54, 0x405c79, 0x627e99,
|
||||||
|
0xaabcce, 0xcbd6e2, 0xe5ebf1, 0xf7f9fb,
|
||||||
|
0xbf8b56, 0xbfbf56, 0x8bbf56, 0x56bf8b,
|
||||||
|
0x568bbf, 0x8b56bf, 0xbf568b, 0xbf5656,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("harmonic-light", "Harmonic16 Light", [
|
||||||
|
0xf7f9fb, 0xe5ebf1, 0xcbd6e2, 0xaabcce,
|
||||||
|
0x627e99, 0x405c79, 0x223b54, 0x0b1c2c,
|
||||||
|
0xbf8b56, 0xbfbf56, 0x8bbf56, 0x56bf8b,
|
||||||
|
0x568bbf, 0x8b56bf, 0xbf568b, 0xbf5656,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("heetch-light", "Heetch Light", [
|
||||||
|
0xfeffff, 0x392551, 0x7b6d8b, 0x9c92a8,
|
||||||
|
0xddd6e5, 0x5a496e, 0x470546, 0x190134,
|
||||||
|
0x27d9d5, 0xbdb6c5, 0x5ba2b6, 0xf80059,
|
||||||
|
0xc33678, 0x47f9f5, 0xbd0152, 0xdedae2,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("heetch", "Heetch Dark", [
|
||||||
|
0x190134, 0x392551, 0x5A496E, 0x7B6D8B,
|
||||||
|
0x9C92A8, 0xBDB6C5, 0xDEDAE2, 0xFEFFFF,
|
||||||
|
0x27D9D5, 0x5BA2B6, 0x8F6C97, 0xC33678,
|
||||||
|
0xF80059, 0xBD0152, 0x82034C, 0x470546,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("helios", "Helios", [
|
||||||
|
0x1d2021, 0x383c3e, 0x53585b, 0x6f7579,
|
||||||
|
0xcdcdcd, 0xd5d5d5, 0xdddddd, 0xe5e5e5,
|
||||||
|
0xd72638, 0xeb8413, 0xf19d1a, 0x88b92d,
|
||||||
|
0x1ba595, 0x1e8bac, 0xbe4264, 0xc85e0d,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("hopscotch", "Hopscotch", [
|
||||||
|
0x322931, 0x433b42, 0x5c545b, 0x797379,
|
||||||
|
0x989498, 0xb9b5b8, 0xd5d3d5, 0xffffff,
|
||||||
|
0xdd464c, 0xfd8b19, 0xfdcc59, 0x8fc13e,
|
||||||
|
0x149b93, 0x1290bf, 0xc85e7c, 0xb33508,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("horizon-dark", "Horizon Dark", [
|
||||||
|
0x1c1e26, 0x232530, 0x2e303e, 0x676a8d,
|
||||||
|
0xced1d0, 0xcbced0, 0xdcdfe4, 0xe3e6ee,
|
||||||
|
0xe93c58, 0xe58d7d, 0xefb993, 0xefaf8e,
|
||||||
|
0x24a8b4, 0xdf5273, 0xb072d1, 0xe4a382,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("ia-dark", "iA Dark", [
|
||||||
|
0x1a1a1a, 0x222222, 0x1d414d, 0x767676,
|
||||||
|
0xb8b8b8, 0xcccccc, 0xe8e8e8, 0xf8f8f8,
|
||||||
|
0xd88568, 0xd86868, 0xb99353, 0x83a471,
|
||||||
|
0x7c9cae, 0x8eccdd, 0xb98eb2, 0x8b6c37,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("ia-light", "iA Light", [
|
||||||
|
0xf6f6f6, 0xdedede, 0xbde5f2, 0x898989,
|
||||||
|
0x767676, 0x181818, 0xe8e8e8, 0xf8f8f8,
|
||||||
|
0x9c5a02, 0xc43e18, 0xc48218, 0x38781c,
|
||||||
|
0x2d6bb1, 0x48bac2, 0xa94598, 0x8b6c37,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("icy", "Icy Dark", [
|
||||||
|
0x021012, 0x031619, 0x041f23, 0x052e34,
|
||||||
|
0x064048, 0x095b67, 0x0c7c8c, 0x109cb0,
|
||||||
|
0x16c1d9, 0xb3ebf2, 0x80deea, 0x4dd0e1,
|
||||||
|
0x26c6da, 0x00bcd4, 0x00acc1, 0x0097a7,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("irblack", "IR Black", [
|
||||||
|
0x000000, 0x242422, 0x484844, 0x6c6c66,
|
||||||
|
0x918f88, 0xb5b3aa, 0xd9d7cc, 0xfdfbee,
|
||||||
|
0xff6c60, 0xe9c062, 0xffffb6, 0xa8ff60,
|
||||||
|
0xc6c5fe, 0x96cbfe, 0xff73fd, 0xb18a3d,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("isotope", "Isotope", [
|
||||||
|
0x000000, 0x404040, 0x606060, 0x808080,
|
||||||
|
0xc0c0c0, 0xd0d0d0, 0xe0e0e0, 0xffffff,
|
||||||
|
0xff0000, 0xff9900, 0xff0099, 0x33ff00,
|
||||||
|
0x00ffff, 0x0066ff, 0xcc00ff, 0x3300ff,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("macintosh", "Macintosh", [
|
||||||
|
0x000000, 0x404040, 0x404040, 0x808080,
|
||||||
|
0x808080, 0xc0c0c0, 0xc0c0c0, 0xffffff,
|
||||||
|
0xdd0907, 0xff6403, 0xfbf305, 0x1fb714,
|
||||||
|
0x02abea, 0x0000d3, 0x4700a5, 0x90713a,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("marrakesh", "Marrakesh", [
|
||||||
|
0x201602, 0x302e00, 0x5f5b17, 0x6c6823,
|
||||||
|
0x86813b, 0x948e48, 0xccc37a, 0xfaf0a5,
|
||||||
|
0xc35359, 0xb36144, 0xa88339, 0x18974e,
|
||||||
|
0x75a738, 0x477ca1, 0x8868b3, 0xb3588e,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("materia", "Materia", [
|
||||||
|
0x263238, 0x2C393F, 0x37474F, 0x707880,
|
||||||
|
0xC9CCD3, 0xCDD3DE, 0xD5DBE5, 0xFFFFFF,
|
||||||
|
0xEC5F67, 0xEA9560, 0xFFCC00, 0x8BD649,
|
||||||
|
0x80CBC4, 0x89DDFF, 0x82AAFF, 0xEC5F67,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("material-darker", "Material Darker", [
|
||||||
|
0x212121, 0x303030, 0x353535, 0x4A4A4A,
|
||||||
|
0xB2CCD6, 0xEEFFFF, 0xEEFFFF, 0xFFFFFF,
|
||||||
|
0xF07178, 0xF78C6C, 0xFFCB6B, 0xC3E88D,
|
||||||
|
0x89DDFF, 0x82AAFF, 0xC792EA, 0xFF5370,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("material-lighter", "Material Lighter", [
|
||||||
|
0xFAFAFA, 0xE7EAEC, 0xCCEAE7, 0xCCD7DA,
|
||||||
|
0x8796B0, 0x80CBC4, 0x80CBC4, 0xFFFFFF,
|
||||||
|
0xFF5370, 0xF76D47, 0xFFB62C, 0x91B859,
|
||||||
|
0x39ADB5, 0x6182B8, 0x7C4DFF, 0xE53935,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("material-palenight", "Material Palenight", [
|
||||||
|
0x292D3E, 0x444267, 0x32374D, 0x676E95,
|
||||||
|
0x8796B0, 0x959DCB, 0x959DCB, 0xFFFFFF,
|
||||||
|
0xF07178, 0xF78C6C, 0xFFCB6B, 0xC3E88D,
|
||||||
|
0x89DDFF, 0x82AAFF, 0xC792EA, 0xFF5370,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("material-vivid", "Material Vivid", [
|
||||||
|
0x202124, 0x27292c, 0x323639, 0x44464d,
|
||||||
|
0x676c71, 0x80868b, 0x9e9e9e, 0xffffff,
|
||||||
|
0xf44336, 0xff9800, 0xffeb3b, 0x00e676,
|
||||||
|
0x00bcd4, 0x2196f3, 0x673ab7, 0x8d6e63,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("material", "Material", [
|
||||||
|
0x263238, 0x2E3C43, 0x314549, 0x546E7A,
|
||||||
|
0xB2CCD6, 0xEEFFFF, 0xEEFFFF, 0xFFFFFF,
|
||||||
|
0xF07178, 0xF78C6C, 0xFFCB6B, 0xC3E88D,
|
||||||
|
0x89DDFF, 0x82AAFF, 0xC792EA, 0xFF5370,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("mellow-purple", "Mellow Purple", [
|
||||||
|
0x1e0528, 0x1A092D, 0x331354, 0x320f55,
|
||||||
|
0x873582, 0xffeeff, 0xffeeff, 0xf8c0ff,
|
||||||
|
0x00d9e9, 0xaa00a3, 0x955ae7, 0x05cb0d,
|
||||||
|
0xb900b1, 0x550068, 0x8991bb, 0x4d6fff,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("mexico-light", "Mexico Light", [
|
||||||
|
0xf8f8f8, 0xe8e8e8, 0xd8d8d8, 0xb8b8b8,
|
||||||
|
0x585858, 0x383838, 0x282828, 0x181818,
|
||||||
|
0xab4642, 0xdc9656, 0xf79a0e, 0x538947,
|
||||||
|
0x4b8093, 0x7cafc2, 0x96609e, 0xa16946,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("mocha", "Mocha", [
|
||||||
|
0x3B3228, 0x534636, 0x645240, 0x7e705a,
|
||||||
|
0xb8afad, 0xd0c8c6, 0xe9e1dd, 0xf5eeeb,
|
||||||
|
0xcb6077, 0xd28b71, 0xf4bc87, 0xbeb55b,
|
||||||
|
0x7bbda4, 0x8ab3b5, 0xa89bb9, 0xbb9584,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("monokai", "Monokai", [
|
||||||
|
0x272822, 0x383830, 0x49483e, 0x75715e,
|
||||||
|
0xa59f85, 0xf8f8f2, 0xf5f4f1, 0xf9f8f5,
|
||||||
|
0xf92672, 0xfd971f, 0xf4bf75, 0xa6e22e,
|
||||||
|
0xa1efe4, 0x66d9ef, 0xae81ff, 0xcc6633,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("nord", "Nord", [
|
||||||
|
0x2E3440, 0x3B4252, 0x434C5E, 0x4C566A,
|
||||||
|
0xD8DEE9, 0xE5E9F0, 0xECEFF4, 0x8FBCBB,
|
||||||
|
0x88C0D0, 0x81A1C1, 0x5E81AC, 0xBF616A,
|
||||||
|
0xD08770, 0xEBCB8B, 0xA3BE8C, 0xB48EAD,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("ocean", "Ocean", [
|
||||||
|
0x2b303b, 0x343d46, 0x4f5b66, 0x65737e,
|
||||||
|
0xa7adba, 0xc0c5ce, 0xdfe1e8, 0xeff1f5,
|
||||||
|
0xbf616a, 0xd08770, 0xebcb8b, 0xa3be8c,
|
||||||
|
0x96b5b4, 0x8fa1b3, 0xb48ead, 0xab7967,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("oceanicnext", "OceanicNext", [
|
||||||
|
0x1B2B34, 0x343D46, 0x4F5B66, 0x65737E,
|
||||||
|
0xA7ADBA, 0xC0C5CE, 0xCDD3DE, 0xD8DEE9,
|
||||||
|
0xEC5F67, 0xF99157, 0xFAC863, 0x99C794,
|
||||||
|
0x5FB3B3, 0x6699CC, 0xC594C5, 0xAB7967,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("one-light", "One Light", [
|
||||||
|
0xfafafa, 0xf0f0f1, 0xe5e5e6, 0xa0a1a7,
|
||||||
|
0x696c77, 0x383a42, 0x202227, 0x090a0b,
|
||||||
|
0xca1243, 0xd75f00, 0xc18401, 0x50a14f,
|
||||||
|
0x0184bc, 0x4078f2, 0xa626a4, 0x986801,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("onedark", "OneDark", [
|
||||||
|
0x282c34, 0x353b45, 0x3e4451, 0x545862,
|
||||||
|
0x565c64, 0xabb2bf, 0xb6bdca, 0xc8ccd4,
|
||||||
|
0xe06c75, 0xd19a66, 0xe5c07b, 0x98c379,
|
||||||
|
0x56b6c2, 0x61afef, 0xc678dd, 0xbe5046,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("outrun-dark", "Outrun Dark", [
|
||||||
|
0x00002A, 0x20204A, 0x30305A, 0x50507A,
|
||||||
|
0xB0B0DA, 0xD0D0FA, 0xE0E0FF, 0xF5F5FF,
|
||||||
|
0xFF4242, 0xFC8D28, 0xF3E877, 0x59F176,
|
||||||
|
0x0EF0F0, 0x66B0FF, 0xF10596, 0xF003EF,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("papercolor-dark", "PaperColor Dark", [
|
||||||
|
0x1c1c1c, 0xaf005f, 0x5faf00, 0xd7af5f,
|
||||||
|
0x5fafd7, 0x808080, 0xd7875f, 0xd0d0d0,
|
||||||
|
0x585858, 0x5faf5f, 0xafd700, 0xaf87d7,
|
||||||
|
0xffaf00, 0xff5faf, 0x00afaf, 0x5f8787,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("papercolor-light", "PaperColor Light", [
|
||||||
|
0xeeeeee, 0xaf0000, 0x008700, 0x5f8700,
|
||||||
|
0x0087af, 0x878787, 0x005f87, 0x444444,
|
||||||
|
0xbcbcbc, 0xd70000, 0xd70087, 0x8700af,
|
||||||
|
0xd75f00, 0xd75f00, 0x005faf, 0x005f87,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("paraiso", "Paraiso", [
|
||||||
|
0x2f1e2e, 0x41323f, 0x4f424c, 0x776e71,
|
||||||
|
0x8d8687, 0xa39e9b, 0xb9b6b0, 0xe7e9db,
|
||||||
|
0xef6155, 0xf99b15, 0xfec418, 0x48b685,
|
||||||
|
0x5bc4bf, 0x06b6ef, 0x815ba4, 0xe96ba8,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("phd", "PhD", [
|
||||||
|
0x061229, 0x2a3448, 0x4d5666, 0x717885,
|
||||||
|
0x9a99a3, 0xb8bbc2, 0xdbdde0, 0xffffff,
|
||||||
|
0xd07346, 0xf0a000, 0xfbd461, 0x99bf52,
|
||||||
|
0x72b9bf, 0x5299bf, 0x9989cc, 0xb08060,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("pico", "Pico", [
|
||||||
|
0x000000, 0x1d2b53, 0x7e2553, 0x008751,
|
||||||
|
0xab5236, 0x5f574f, 0xc2c3c7, 0xfff1e8,
|
||||||
|
0xff004d, 0xffa300, 0xfff024, 0x00e756,
|
||||||
|
0x29adff, 0x83769c, 0xff77a8, 0xffccaa,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("pop", "Pop", [
|
||||||
|
0x000000, 0x202020, 0x303030, 0x505050,
|
||||||
|
0xb0b0b0, 0xd0d0d0, 0xe0e0e0, 0xffffff,
|
||||||
|
0xeb008a, 0xf29333, 0xf8ca12, 0x37b349,
|
||||||
|
0x00aabb, 0x0e5a94, 0xb31e8d, 0x7a2d00,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("porple", "Porple", [
|
||||||
|
0x292c36, 0x333344, 0x474160, 0x65568a,
|
||||||
|
0xb8b8b8, 0xd8d8d8, 0xe8e8e8, 0xf8f8f8,
|
||||||
|
0xf84547, 0xd28e5d, 0xefa16b, 0x95c76f,
|
||||||
|
0x64878f, 0x8485ce, 0xb74989, 0x986841,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("qualia", "Qualia", [
|
||||||
|
0x101010, 0x454545, 0x454545, 0x454545,
|
||||||
|
0x808080, 0xc0c0c0, 0xc0c0c0, 0x454545,
|
||||||
|
0xefa6a2, 0xa3b8ef, 0xe6a3dc, 0x80c990,
|
||||||
|
0xc8c874, 0x50cacd, 0xe0af85, 0x808080,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("railscasts", "Railscasts", [
|
||||||
|
0x2b2b2b, 0x272935, 0x3a4055, 0x5a647e,
|
||||||
|
0xd4cfc9, 0xe6e1dc, 0xf4f1ed, 0xf9f7f3,
|
||||||
|
0xda4939, 0xcc7833, 0xffc66d, 0xa5c261,
|
||||||
|
0x519f50, 0x6d9cbe, 0xb6b3eb, 0xbc9458,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("rebecca", "Rebecca", [
|
||||||
|
0x292a44, 0x663399, 0x383a62, 0x666699,
|
||||||
|
0xa0a0c5, 0xf1eff8, 0xccccff, 0x53495d,
|
||||||
|
0xa0a0c5, 0xefe4a1, 0xae81ff, 0x6dfedf,
|
||||||
|
0x8eaee0, 0x2de0a7, 0x7aa5ff, 0xff79c6,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("seti", "Seti UI", [
|
||||||
|
0x151718, 0x282a2b, 0x3B758C, 0x41535B,
|
||||||
|
0x43a5d5, 0xd6d6d6, 0xeeeeee, 0xffffff,
|
||||||
|
0xcd3f45, 0xdb7b55, 0xe6cd69, 0x9fca56,
|
||||||
|
0x55dbbe, 0x55b5db, 0xa074c4, 0x8a553f,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("shapeshifter", "Shapeshifter", [
|
||||||
|
0xf9f9f9, 0xe0e0e0, 0xababab, 0x555555,
|
||||||
|
0x343434, 0x102015, 0x040404, 0x000000,
|
||||||
|
0xe92f2f, 0xe09448, 0xdddd13, 0x0ed839,
|
||||||
|
0x23edda, 0x3b48e3, 0xf996e2, 0x69542d,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("snazzy", "Snazzy", [
|
||||||
|
0x282a36, 0x34353e, 0x43454f, 0x78787e,
|
||||||
|
0xa5a5a9, 0xe2e4e5, 0xeff0eb, 0xf1f1f0,
|
||||||
|
0xff5c57, 0xff9f43, 0xf3f99d, 0x5af78e,
|
||||||
|
0x9aedfe, 0x57c7ff, 0xff6ac1, 0xb2643c,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("solarflare", "Solar Flare", [
|
||||||
|
0x18262F, 0x222E38, 0x586875, 0x667581,
|
||||||
|
0x85939E, 0xA6AFB8, 0xE8E9ED, 0xF5F7FA,
|
||||||
|
0xEF5253, 0xE66B2B, 0xE4B51C, 0x7CC844,
|
||||||
|
0x52CBB0, 0x33B5E1, 0xA363D5, 0xD73C9A,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("solarized-dark", "Solarized Dark", [
|
||||||
|
0x002b36, 0x073642, 0x586e75, 0x657b83,
|
||||||
|
0x839496, 0x93a1a1, 0xeee8d5, 0xfdf6e3,
|
||||||
|
0xdc322f, 0xcb4b16, 0xb58900, 0x859900,
|
||||||
|
0x2aa198, 0x268bd2, 0x6c71c4, 0xd33682,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("solarized-light", "Solarized Light", [
|
||||||
|
0xfdf6e3, 0xeee8d5, 0x93a1a1, 0x839496,
|
||||||
|
0x657b83, 0x586e75, 0x073642, 0x002b36,
|
||||||
|
0xdc322f, 0xcb4b16, 0xb58900, 0x859900,
|
||||||
|
0x2aa198, 0x268bd2, 0x6c71c4, 0xd33682,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("spacemacs", "Spacemacs", [
|
||||||
|
0x1f2022, 0x282828, 0x444155, 0x585858,
|
||||||
|
0xb8b8b8, 0xa3a3a3, 0xe8e8e8, 0xf8f8f8,
|
||||||
|
0xf2241f, 0xffa500, 0xb1951d, 0x67b11d,
|
||||||
|
0x2d9574, 0x4f97d7, 0xa31db1, 0xb03060,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("summerfruit-dark", "Summerfruit Dark", [
|
||||||
|
0x151515, 0x202020, 0x303030, 0x505050,
|
||||||
|
0xB0B0B0, 0xD0D0D0, 0xE0E0E0, 0xFFFFFF,
|
||||||
|
0xFF0086, 0xFD8900, 0xABA800, 0x00C918,
|
||||||
|
0x1FAAAA, 0x3777E6, 0xAD00A1, 0xCC6633,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("summerfruit-light", "Summerfruit Light", [
|
||||||
|
0xFFFFFF, 0xE0E0E0, 0xD0D0D0, 0xB0B0B0,
|
||||||
|
0x000000, 0x101010, 0x151515, 0x202020,
|
||||||
|
0xFF0086, 0xFD8900, 0xABA800, 0x00C918,
|
||||||
|
0x1FAAAA, 0x3777E6, 0xAD00A1, 0xCC6633,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("synth-midnight-dark", "Synth Midnight", [
|
||||||
|
0x040404, 0x141414, 0x242424, 0x61507A,
|
||||||
|
0xBFBBBF, 0xDFDBDF, 0xEFEBEF, 0xFFFBFF,
|
||||||
|
0xB53B50, 0xE4600E, 0xDAE84D, 0x06EA61,
|
||||||
|
0x7CEDE9, 0x03AEFF, 0xEA5CE2, 0x9D4D0E,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("tomorrow-night-eighties", "Tomorrow Night Eighties", [
|
||||||
|
0x2d2d2d, 0x393939, 0x515151, 0x999999,
|
||||||
|
0xb4b7b4, 0xcccccc, 0xe0e0e0, 0xffffff,
|
||||||
|
0xf2777a, 0xf99157, 0xffcc66, 0x99cc99,
|
||||||
|
0x66cccc, 0x6699cc, 0xcc99cc, 0xa3685a,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("tomorrow-night", "Tomorrow Night", [
|
||||||
|
0x1d1f21, 0x282a2e, 0x373b41, 0x969896,
|
||||||
|
0xb4b7b4, 0xc5c8c6, 0xe0e0e0, 0xffffff,
|
||||||
|
0xcc6666, 0xde935f, 0xf0c674, 0xb5bd68,
|
||||||
|
0x8abeb7, 0x81a2be, 0xb294bb, 0xa3685a,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("tomorrow", "Tomorrow", [
|
||||||
|
0xffffff, 0xe0e0e0, 0xd6d6d6, 0x8e908c,
|
||||||
|
0x969896, 0x4d4d4c, 0x282a2e, 0x1d1f21,
|
||||||
|
0xc82829, 0xf5871f, 0xeab700, 0x718c00,
|
||||||
|
0x3e999f, 0x4271ae, 0x8959a8, 0xa3685a,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("tube", "London Tube", [
|
||||||
|
0x231f20, 0x1c3f95, 0x5a5758, 0x737171,
|
||||||
|
0x959ca1, 0xd9d8d8, 0xe7e7e8, 0xffffff,
|
||||||
|
0xee2e24, 0xf386a1, 0xffd204, 0x00853e,
|
||||||
|
0x85cebc, 0x009ddc, 0x98005d, 0xb06110,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("twilight", "Twilight", [
|
||||||
|
0x1e1e1e, 0x323537, 0x464b50, 0x5f5a60,
|
||||||
|
0x838184, 0xa7a7a7, 0xc3c3c3, 0xffffff,
|
||||||
|
0xcf6a4c, 0xcda869, 0xf9ee98, 0x8f9d6a,
|
||||||
|
0xafc4db, 0x7587a6, 0x9b859d, 0x9b703f,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("unikitty-dark", "Unikitty Dark", [
|
||||||
|
0x2e2a31, 0x4a464d, 0x666369, 0x838085,
|
||||||
|
0x9f9da2, 0xbcbabe, 0xd8d7da, 0xf5f4f7,
|
||||||
|
0xd8137f, 0xd65407, 0xdc8a0e, 0x17ad98,
|
||||||
|
0x149bda, 0x796af5, 0xbb60ea, 0xc720ca,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("unikitty-light", "Unikitty Light", [
|
||||||
|
0xffffff, 0xe1e1e2, 0xc4c3c5, 0xa7a5a8,
|
||||||
|
0x89878b, 0x6c696e, 0x4f4b51, 0x322d34,
|
||||||
|
0xd8137f, 0xd65407, 0xdc8a0e, 0x17ad98,
|
||||||
|
0x149bda, 0x775dff, 0xaa17e6, 0xe013d0,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("woodland", "Woodland", [
|
||||||
|
0x231e18, 0x302b25, 0x48413a, 0x9d8b70,
|
||||||
|
0xb4a490, 0xcabcb1, 0xd7c8bc, 0xe4d4c8,
|
||||||
|
0xd35c5c, 0xca7f32, 0xe0ac16, 0xb7ba53,
|
||||||
|
0x6eb958, 0x88a4d3, 0xbb90e2, 0xb49368,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("xcode-dusk", "XCode Dusk", [
|
||||||
|
0x282B35, 0x3D4048, 0x53555D, 0x686A71,
|
||||||
|
0x7E8086, 0x939599, 0xA9AAAE, 0xBEBFC2,
|
||||||
|
0xB21889, 0x786DC5, 0x438288, 0xDF0002,
|
||||||
|
0x00A0BE, 0x790EAD, 0xB21889, 0xC77C48,
|
||||||
|
]);
|
||||||
|
Base16Theme.add("zenburn", "Zenburn", [
|
||||||
|
0x383838, 0x404040, 0x606060, 0x6f6f6f,
|
||||||
|
0x808080, 0xdcdccc, 0xc0c0c0, 0xffffff,
|
||||||
|
0xdca3a3, 0xdfaf8f, 0xe0cf9f, 0x5f7f5f,
|
||||||
|
0x93e0e3, 0x7cb8bb, 0xdc8cc3, 0x000000,
|
||||||
|
]);
|
69
js/model/LabelColors.js
Normal file
69
js/model/LabelColors.js
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
import Gdk from 'gi://Gdk?version=4.0';
|
||||||
|
import Gio from 'gi://Gio';
|
||||||
|
const CITADEL_SETTINGS_SCHEMA = 'com.subgraph.citadel';
|
||||||
|
const LABEL_COLOR_LIST_KEY = 'label-color-list';
|
||||||
|
const REALM_LABEL_COLORS_KEY = 'realm-label-colors';
|
||||||
|
const DEFAULT_LABEL_COLOR = new Gdk.RGBA({ red: 153, green: 193, blue: 241, });
|
||||||
|
export class LabelColorManager {
|
||||||
|
constructor() {
|
||||||
|
this._citadelSettings = new Gio.Settings({ schema_id: CITADEL_SETTINGS_SCHEMA });
|
||||||
|
this._defaultColors = [];
|
||||||
|
this._realmLabelColors = new Map();
|
||||||
|
this._loadColors();
|
||||||
|
}
|
||||||
|
_loadColors() {
|
||||||
|
let entries = this._citadelSettings.get_strv(LABEL_COLOR_LIST_KEY);
|
||||||
|
entries.forEach(entry => {
|
||||||
|
let c = new Gdk.RGBA();
|
||||||
|
if (c.parse(entry)) {
|
||||||
|
this._defaultColors.push(c);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
entries = this._citadelSettings.get_strv(REALM_LABEL_COLORS_KEY);
|
||||||
|
entries.forEach(entry => {
|
||||||
|
let parts = entry.split(":");
|
||||||
|
if (parts.length === 2) {
|
||||||
|
let c = new Gdk.RGBA();
|
||||||
|
if (c.parse(parts[1])) {
|
||||||
|
this._realmLabelColors.set(parts[0], c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
updateRealmColor(realm, color) {
|
||||||
|
this._realmLabelColors.set(realm.name, color);
|
||||||
|
this._storeRealmColors();
|
||||||
|
}
|
||||||
|
lookupRealmColor(realm) {
|
||||||
|
let c = this._realmLabelColors.get(realm.name);
|
||||||
|
if (c) {
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
let newColor = this._allocateColor();
|
||||||
|
this.updateRealmColor(realm, newColor);
|
||||||
|
return newColor;
|
||||||
|
}
|
||||||
|
_storeRealmColors() {
|
||||||
|
let entries = [];
|
||||||
|
this._realmLabelColors.forEach((v, k) => {
|
||||||
|
entries.push(`${k}:${v.to_string()}`);
|
||||||
|
});
|
||||||
|
entries.sort();
|
||||||
|
this._citadelSettings.set_strv(REALM_LABEL_COLORS_KEY, entries);
|
||||||
|
}
|
||||||
|
_allocateColor() {
|
||||||
|
// 1) No default colors? return a built in color
|
||||||
|
if (this._defaultColors.length === 0) {
|
||||||
|
return DEFAULT_LABEL_COLOR;
|
||||||
|
}
|
||||||
|
// 2) Find first color on default color list that isn't used already
|
||||||
|
let usedColors = Array.from(this._realmLabelColors.values());
|
||||||
|
let defaultColor = this._defaultColors.find(color => !usedColors.some(c => c.equal(color)));
|
||||||
|
if (defaultColor) {
|
||||||
|
return defaultColor;
|
||||||
|
}
|
||||||
|
// 3) Choose a random element of the default list
|
||||||
|
let index = Math.floor(Math.random() * this._defaultColors.length);
|
||||||
|
return this._defaultColors[index];
|
||||||
|
}
|
||||||
|
}
|
183
js/model/ObjectManager.js
Normal file
183
js/model/ObjectManager.js
Normal file
@ -0,0 +1,183 @@
|
|||||||
|
import Gio from 'gi://Gio';
|
||||||
|
import GLib from 'gi://GLib';
|
||||||
|
const Signals = imports.signals;
|
||||||
|
Gio._promisify(Gio.DBusProxy.prototype, 'init_async', 'init_finish');
|
||||||
|
// Specified in the D-Bus specification here:
|
||||||
|
// http://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces-objectmanager
|
||||||
|
const ObjectManagerIface = `
|
||||||
|
<node>
|
||||||
|
<interface name="org.freedesktop.DBus.ObjectManager">
|
||||||
|
<method name="GetManagedObjects">
|
||||||
|
<arg name="objects" type="a{oa{sa{sv}}}" direction="out"/>
|
||||||
|
</method>
|
||||||
|
<signal name="InterfacesAdded">
|
||||||
|
<arg name="objectPath" type="o"/>
|
||||||
|
<arg name="interfaces" type="a{sa{sv}}" />
|
||||||
|
</signal>
|
||||||
|
<signal name="InterfacesRemoved">
|
||||||
|
<arg name="objectPath" type="o"/>
|
||||||
|
<arg name="interfaces" type="as" />
|
||||||
|
</signal>
|
||||||
|
</interface>
|
||||||
|
</node>`;
|
||||||
|
const ObjectManagerInfo = Gio.DBusInterfaceInfo.new_for_xml(ObjectManagerIface);
|
||||||
|
;
|
||||||
|
export class ObjectManager {
|
||||||
|
constructor(params) {
|
||||||
|
var _a;
|
||||||
|
this._connection = params.connection;
|
||||||
|
this._serviceName = params.name;
|
||||||
|
this._managerPath = params.objectPath;
|
||||||
|
this._cancellable = (_a = params.cancellable) !== null && _a !== void 0 ? _a : null;
|
||||||
|
this._managerProxy = new Gio.DBusProxy({
|
||||||
|
g_connection: this._connection,
|
||||||
|
g_interface_name: ObjectManagerInfo.name,
|
||||||
|
g_interface_info: ObjectManagerInfo,
|
||||||
|
g_name: this._serviceName,
|
||||||
|
g_object_path: this._managerPath,
|
||||||
|
g_flags: Gio.DBusProxyFlags.DO_NOT_AUTO_START,
|
||||||
|
});
|
||||||
|
this._interfaceInfos = {};
|
||||||
|
this._objects = {};
|
||||||
|
this._interfaces = {};
|
||||||
|
this._onLoaded = params.onLoaded;
|
||||||
|
if (params.knownInterfaces)
|
||||||
|
this._registerInterfaces(params.knownInterfaces);
|
||||||
|
this._initManagerProxy();
|
||||||
|
}
|
||||||
|
_completeLoad() {
|
||||||
|
if (this._onLoaded)
|
||||||
|
this._onLoaded();
|
||||||
|
}
|
||||||
|
async _addInterface(objectPath, interfaceName) {
|
||||||
|
let info = this._interfaceInfos[interfaceName];
|
||||||
|
if (!info)
|
||||||
|
return;
|
||||||
|
const proxy = new Gio.DBusProxy({
|
||||||
|
g_connection: this._connection,
|
||||||
|
g_name: this._serviceName,
|
||||||
|
g_object_path: objectPath,
|
||||||
|
g_interface_name: interfaceName,
|
||||||
|
g_interface_info: info,
|
||||||
|
g_flags: Gio.DBusProxyFlags.DO_NOT_AUTO_START,
|
||||||
|
});
|
||||||
|
try {
|
||||||
|
await proxy.init_async(GLib.PRIORITY_DEFAULT, this._cancellable);
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
logError(e, `could not initialize proxy for interface ${interfaceName}`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let isNewObject;
|
||||||
|
if (!this._objects[objectPath]) {
|
||||||
|
this._objects[objectPath] = {};
|
||||||
|
isNewObject = true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
isNewObject = false;
|
||||||
|
}
|
||||||
|
this._objects[objectPath][interfaceName] = proxy;
|
||||||
|
if (!this._interfaces[interfaceName])
|
||||||
|
this._interfaces[interfaceName] = [];
|
||||||
|
this._interfaces[interfaceName].push(proxy);
|
||||||
|
if (isNewObject)
|
||||||
|
this.emit('object-added', objectPath);
|
||||||
|
this.emit('interface-added', interfaceName, proxy);
|
||||||
|
}
|
||||||
|
_removeInterface(objectPath, interfaceName) {
|
||||||
|
if (!this._objects[objectPath])
|
||||||
|
return;
|
||||||
|
let proxy = this._objects[objectPath][interfaceName];
|
||||||
|
if (this._interfaces[interfaceName]) {
|
||||||
|
let index = this._interfaces[interfaceName].indexOf(proxy);
|
||||||
|
if (index >= 0)
|
||||||
|
this._interfaces[interfaceName].splice(index, 1);
|
||||||
|
if (this._interfaces[interfaceName].length === 0)
|
||||||
|
delete this._interfaces[interfaceName];
|
||||||
|
}
|
||||||
|
this.emit('interface-removed', interfaceName, proxy);
|
||||||
|
delete this._objects[objectPath][interfaceName];
|
||||||
|
if (Object.keys(this._objects[objectPath]).length === 0) {
|
||||||
|
delete this._objects[objectPath];
|
||||||
|
this.emit('object-removed', objectPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
async _initManagerProxy() {
|
||||||
|
try {
|
||||||
|
await this._managerProxy.init_async(GLib.PRIORITY_DEFAULT, this._cancellable);
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
logError(e, `could not initialize object manager for object ${this._serviceName}`);
|
||||||
|
this._completeLoad();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this._managerProxy.connectSignal('InterfacesAdded', (_objectManager, _sender, [objectPath, interfaces]) => {
|
||||||
|
let interfaceNames = Object.keys(interfaces);
|
||||||
|
for (let i = 0; i < interfaceNames.length; i++)
|
||||||
|
this._addInterface(objectPath, interfaceNames[i]);
|
||||||
|
});
|
||||||
|
this._managerProxy.connectSignal('InterfacesRemoved', (_objectManager, _sender, [objectPath, interfaceNames]) => {
|
||||||
|
for (let i = 0; i < interfaceNames.length; i++)
|
||||||
|
this._removeInterface(objectPath, interfaceNames[i]);
|
||||||
|
});
|
||||||
|
if (Object.keys(this._interfaceInfos).length === 0) {
|
||||||
|
this._completeLoad();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this._managerProxy.connect('notify::g-name-owner', () => {
|
||||||
|
if (this._managerProxy.g_name_owner)
|
||||||
|
this._onNameAppeared();
|
||||||
|
else
|
||||||
|
this._onNameVanished();
|
||||||
|
});
|
||||||
|
if (this._managerProxy.g_name_owner)
|
||||||
|
this._onNameAppeared().catch(logError);
|
||||||
|
}
|
||||||
|
async _onNameAppeared() {
|
||||||
|
try {
|
||||||
|
const [objects] = await this._managerProxy.GetManagedObjectsAsync();
|
||||||
|
if (!objects) {
|
||||||
|
this._completeLoad();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const objectPaths = Object.keys(objects);
|
||||||
|
await Promise.allSettled(objectPaths.flatMap(objectPath => {
|
||||||
|
const object = objects[objectPath];
|
||||||
|
const interfaceNames = Object.getOwnPropertyNames(object);
|
||||||
|
return interfaceNames.map(ifaceName => this._addInterface(objectPath, ifaceName));
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
catch (error) {
|
||||||
|
logError(error, `could not get remote objects for service ${this._serviceName} path ${this._managerPath}`);
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
this._completeLoad();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_onNameVanished() {
|
||||||
|
let objectPaths = Object.keys(this._objects);
|
||||||
|
for (let i = 0; i < objectPaths.length; i++) {
|
||||||
|
let objectPath = objectPaths[i];
|
||||||
|
let object = this._objects[objectPath];
|
||||||
|
let interfaceNames = Object.keys(object);
|
||||||
|
for (let j = 0; j < interfaceNames.length; j++) {
|
||||||
|
let interfaceName = interfaceNames[j];
|
||||||
|
if (object[interfaceName])
|
||||||
|
this._removeInterface(objectPath, interfaceName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_registerInterfaces(interfaces) {
|
||||||
|
for (let i = 0; i < interfaces.length; i++) {
|
||||||
|
let info = Gio.DBusInterfaceInfo.new_for_xml(interfaces[i]);
|
||||||
|
this._interfaceInfos[info.name] = info;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
getProxiesForInterface(interfaceName) {
|
||||||
|
let proxyList = this._interfaces[interfaceName];
|
||||||
|
if (!proxyList)
|
||||||
|
return [];
|
||||||
|
return proxyList;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Signals.addSignalMethods(ObjectManager.prototype);
|
73
js/model/OptionData.js
Normal file
73
js/model/OptionData.js
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
export class OptionData {
|
||||||
|
constructor(description, tooltip) {
|
||||||
|
this.tooltip = tooltip;
|
||||||
|
this.description = description;
|
||||||
|
}
|
||||||
|
static add(name, description, tooltip) {
|
||||||
|
OptionData.map.set(name, new OptionData(description, tooltip));
|
||||||
|
}
|
||||||
|
static description(name) {
|
||||||
|
var _a;
|
||||||
|
return (_a = OptionData.map.get(name)) === null || _a === void 0 ? void 0 : _a.description;
|
||||||
|
}
|
||||||
|
static tooltip(name) {
|
||||||
|
var _a;
|
||||||
|
return (_a = OptionData.map.get(name)) === null || _a === void 0 ? void 0 : _a.tooltip;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
OptionData.map = new Map();
|
||||||
|
OptionData.add('use-gpu', 'Use GPU in Realm', `If enabled the render node device <tt><b>/dev/dri/renderD128</b></tt> will be mounted into the realm container.
|
||||||
|
|
||||||
|
If privileged device <tt><b>/dev/dri/card0</b></tt> is also needed set
|
||||||
|
additional variable in realm configuration file:
|
||||||
|
|
||||||
|
<tt><b>use-gpu-card0 = true</b></tt>
|
||||||
|
`);
|
||||||
|
OptionData.add('use-wayland', 'Use Wayland in Realm', `If enabled access to Wayland display will be permitted in realm by adding wayland socket to realm.
|
||||||
|
|
||||||
|
<tt><b>/run/user/1000/wayland-0</b></tt>
|
||||||
|
|
||||||
|
`);
|
||||||
|
OptionData.add('use-x11', 'Use X11 in Realm', `If enabled access to X11 server will be added by mounting directory X11 directory into realm.
|
||||||
|
|
||||||
|
<tt><b>/tmp/.X11-unix</b></tt>
|
||||||
|
|
||||||
|
`);
|
||||||
|
OptionData.add('use-sound', 'Use sound in Realm', `If enabled allows use of sound inside of realm. The following items will be added:
|
||||||
|
|
||||||
|
<tt><b>/dev/snd</b></tt>
|
||||||
|
<tt><b>/dev/shm</b></tt>
|
||||||
|
<tt><b>/run/user/1000/pulse</b></tt>
|
||||||
|
|
||||||
|
`);
|
||||||
|
OptionData.add('use-shared-dir', 'Mount /Shared directory in Realm', `If enabled the shared directory will be mounted as <tt><b>/Shared</b></tt> in home directory of realm.
|
||||||
|
|
||||||
|
This directory is shared between all realms with this option enabled and is an easy way to move files between realms.
|
||||||
|
|
||||||
|
`);
|
||||||
|
OptionData.add('use-network', 'Realm has network access', `If enabled the realm will have access to the network.`);
|
||||||
|
OptionData.add('use-kvm', 'Use KVM (/dev/kvm) in Realm', `If enabled device <tt><b>/dev/kvm</b></tt> will be added to realm`);
|
||||||
|
OptionData.add('use-ephemeral-home', 'Use ephemeral tmpfs mount for home directory', `If enabled the home directory of realm will be set up in ephemeral mode.
|
||||||
|
|
||||||
|
The ephemeral home directory is set up with the following steps:
|
||||||
|
|
||||||
|
1. Home directory is mounted as tmpfs filesystem
|
||||||
|
2. Any files in <tt><b>/realms/skel</b></tt> are copied into home directory
|
||||||
|
3. Any files in <tt><b>/realms/realm-$name/skel</b></tt> are copied into home directory.
|
||||||
|
4. Any directories listed in config file variable <tt><b>ephemeral_persistent_dirs</b></tt>
|
||||||
|
are bind mounted from <tt><b>/realms/realm-$name/home</b></tt> into ephemeral
|
||||||
|
home directory.
|
||||||
|
|
||||||
|
`);
|
||||||
|
OptionData.add('overlay', 'Type of rootfs overlay Realm is configured to use.', `<b><big>Overlay</big></b>
|
||||||
|
Type of rootfs overlay realm is configured to use.
|
||||||
|
<b>None</b> Don't use a rootfs overlay
|
||||||
|
<b>TmpFS</b> Use a rootfs overlay stored on tmpfs
|
||||||
|
<b>Storage</b> Use a rootfs overlay stored on disk in storage partition
|
||||||
|
`);
|
||||||
|
OptionData.add('realmfs', 'Root filesystem image to use for Realm.', `<b><big>RealmFS</big></b>
|
||||||
|
Root filesystem image to use for realm.`);
|
||||||
|
OptionData.add('colorscheme', 'Terminal Color Scheme', `<b><big>Terminal Color Scheme</big></b>
|
||||||
|
Choose a color scheme to use in the terminals in this realm.`);
|
||||||
|
OptionData.add('window-label-color', 'Window Label Color', `<b><big>Window Label Color</big></b>
|
||||||
|
Set a color to be used when a label is drawn on the window titlebar indicating which realm the application is running in.`);
|
94
js/model/Realm.js
Normal file
94
js/model/Realm.js
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
var _a;
|
||||||
|
import GObject from 'gi://GObject';
|
||||||
|
import { RealmFS } from './RealmFS.js';
|
||||||
|
import { RealmConfig } from './RealmConfig.js';
|
||||||
|
export const RunStatus = {
|
||||||
|
STOPPED: 0,
|
||||||
|
STARTING: 1,
|
||||||
|
RUNNING: 2,
|
||||||
|
CURRENT: 3,
|
||||||
|
STOPPING: 4,
|
||||||
|
};
|
||||||
|
export class Realm extends GObject.Object {
|
||||||
|
constructor(proxy, labelColors) {
|
||||||
|
super();
|
||||||
|
this.config = new RealmConfig();
|
||||||
|
this._proxy = proxy;
|
||||||
|
this._labelColors = labelColors;
|
||||||
|
this._proxy.connect('g-properties-changed', (_proxy, _changed, _invalidated) => {
|
||||||
|
this._sync();
|
||||||
|
});
|
||||||
|
this._sync();
|
||||||
|
}
|
||||||
|
get realmfs() {
|
||||||
|
return this._realmfs;
|
||||||
|
}
|
||||||
|
set realmfs(value) {
|
||||||
|
if (this.realmfs === value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this._realmfs = value;
|
||||||
|
this.emit('changed');
|
||||||
|
}
|
||||||
|
_sync() {
|
||||||
|
this._name = this._proxy.Name;
|
||||||
|
this._description = this._proxy.Description;
|
||||||
|
this._pidns = this._proxy.PidNS;
|
||||||
|
this._run_status = this._proxy.RunStatus;
|
||||||
|
this._is_system_realm = this._proxy.IsSystemRealm;
|
||||||
|
this.emit('changed');
|
||||||
|
}
|
||||||
|
get name() {
|
||||||
|
return this._name;
|
||||||
|
}
|
||||||
|
get description() {
|
||||||
|
return this._description;
|
||||||
|
}
|
||||||
|
get pidns() {
|
||||||
|
return this._pidns;
|
||||||
|
}
|
||||||
|
get run_status() {
|
||||||
|
return this._run_status;
|
||||||
|
}
|
||||||
|
get is_system_realm() {
|
||||||
|
return this._is_system_realm;
|
||||||
|
}
|
||||||
|
is_running() {
|
||||||
|
return this.run_status === RunStatus.RUNNING || this.run_status === RunStatus.CURRENT;
|
||||||
|
}
|
||||||
|
is_current() {
|
||||||
|
return this.run_status === RunStatus.CURRENT;
|
||||||
|
}
|
||||||
|
getLabelColor() {
|
||||||
|
return this._labelColors.lookupRealmColor(this);
|
||||||
|
}
|
||||||
|
setLabelColor(color) {
|
||||||
|
this._labelColors.updateRealmColor(this, color);
|
||||||
|
}
|
||||||
|
realmfs_index() {
|
||||||
|
return this._proxy.RealmFS;
|
||||||
|
}
|
||||||
|
set_global_config(config) {
|
||||||
|
this.config.set_global_config(config);
|
||||||
|
}
|
||||||
|
async load_config() {
|
||||||
|
const result = await this._proxy.GetConfigAsync();
|
||||||
|
this.config.set_config(result[0]);
|
||||||
|
this.emit('changed');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_a = Realm;
|
||||||
|
(() => {
|
||||||
|
GObject.registerClass({
|
||||||
|
GTypeName: 'Realm',
|
||||||
|
Properties: {
|
||||||
|
'name': GObject.ParamSpec.string('name', '', '', GObject.ParamFlags.READWRITE, ''),
|
||||||
|
'description': GObject.ParamSpec.string('description', '', '', GObject.ParamFlags.READWRITE, ''),
|
||||||
|
'pidns': GObject.ParamSpec.uint64('pidns', '', '', GObject.ParamFlags.READWRITE, 0, Number.MAX_SAFE_INTEGER, 0),
|
||||||
|
'run-status': GObject.ParamSpec.uint('run-status', '', '', GObject.ParamFlags.READWRITE, 0, 4, 0),
|
||||||
|
'is-system-realm': GObject.ParamSpec.boolean('is-system-realm', '', '', GObject.ParamFlags.READWRITE, false),
|
||||||
|
'realmfs': GObject.ParamSpec.object('realmfs', '', '', GObject.ParamFlags.READWRITE, RealmFS),
|
||||||
|
},
|
||||||
|
Signals: { 'changed': {} },
|
||||||
|
}, _a);
|
||||||
|
})();
|
94
js/model/RealmConfig.js
Normal file
94
js/model/RealmConfig.js
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
import { OptionData } from './OptionData.js';
|
||||||
|
export class BoolOptionData {
|
||||||
|
constructor(name) {
|
||||||
|
var _a, _b;
|
||||||
|
this.name = name;
|
||||||
|
this.description = (_a = OptionData.description(name)) !== null && _a !== void 0 ? _a : name;
|
||||||
|
this.tooltip = (_b = OptionData.tooltip(name)) !== null && _b !== void 0 ? _b : "";
|
||||||
|
}
|
||||||
|
static allOptions() {
|
||||||
|
let options = [];
|
||||||
|
BoolOptionData.ALL_OPTIONS.forEach(name => {
|
||||||
|
options.push(new BoolOptionData(name));
|
||||||
|
});
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
BoolOptionData.ALL_OPTIONS = [
|
||||||
|
'use-gpu',
|
||||||
|
'use-wayland',
|
||||||
|
'use-x11',
|
||||||
|
'use-sound',
|
||||||
|
'use-network',
|
||||||
|
'use-kvm',
|
||||||
|
'use-shared-dir',
|
||||||
|
'use-ephemeral-home',
|
||||||
|
];
|
||||||
|
export class ConfigOption {
|
||||||
|
constructor(name, value, defaultValue, description, tooltip) {
|
||||||
|
this.name = name;
|
||||||
|
this.value = value;
|
||||||
|
this.defaultValue = defaultValue;
|
||||||
|
this.description = description;
|
||||||
|
this.tooltip = tooltip;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export class RealmConfig {
|
||||||
|
constructor() {
|
||||||
|
this._configVars = {};
|
||||||
|
this._globalConfig = {};
|
||||||
|
}
|
||||||
|
set_config(config) {
|
||||||
|
this._configVars = config;
|
||||||
|
}
|
||||||
|
set_global_config(globalConfig) {
|
||||||
|
this._globalConfig = globalConfig;
|
||||||
|
}
|
||||||
|
get_var(name) {
|
||||||
|
let value = this._configVars[name];
|
||||||
|
if (value && value.length > 0) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
value = this._globalConfig[name];
|
||||||
|
if (value && value.length > 0) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
get_bool(name) {
|
||||||
|
return this.get_var(name) === 'true';
|
||||||
|
}
|
||||||
|
get_colorscheme() {
|
||||||
|
var _a;
|
||||||
|
return (_a = this.get_var('terminal-scheme')) !== null && _a !== void 0 ? _a : 'default-dark';
|
||||||
|
}
|
||||||
|
get_realmfs() {
|
||||||
|
var _a;
|
||||||
|
return (_a = this.get_var('realmfs')) !== null && _a !== void 0 ? _a : 'base';
|
||||||
|
}
|
||||||
|
static capitalize(term) {
|
||||||
|
const acronyms = ["gpu", "kvm"];
|
||||||
|
if (acronyms.find(s => term === s)) {
|
||||||
|
return term.toUpperCase();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return term.charAt(0).toUpperCase() + term.slice(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static option_label(key) {
|
||||||
|
return key.substring(4)
|
||||||
|
.split('-')
|
||||||
|
.map(RealmConfig.capitalize)
|
||||||
|
.join('');
|
||||||
|
}
|
||||||
|
is_enabled_bool_option(name, value, isDefault) {
|
||||||
|
const default_val = this._globalConfig[name];
|
||||||
|
return name.startsWith("use-") && value === "true" && (value === default_val) === isDefault;
|
||||||
|
}
|
||||||
|
enabled_bool_option_labels(isDefault) {
|
||||||
|
return Object.entries(this._configVars)
|
||||||
|
.filter(([k, v]) => this.is_enabled_bool_option(k, v, isDefault))
|
||||||
|
.map(([k,]) => RealmConfig.option_label(k))
|
||||||
|
.sort();
|
||||||
|
}
|
||||||
|
}
|
69
js/model/RealmFS.js
Normal file
69
js/model/RealmFS.js
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
var _a;
|
||||||
|
import GObject from 'gi://GObject';
|
||||||
|
const OBJECT_PREFIX = "/com/subgraph/Realms2/RealmFS";
|
||||||
|
export class RealmFS extends GObject.Object {
|
||||||
|
constructor(proxy) {
|
||||||
|
super();
|
||||||
|
this._proxy = proxy;
|
||||||
|
this._proxy.connect('g-properties-changed', (_proxy, _changed, _invalidated) => {
|
||||||
|
this._sync();
|
||||||
|
});
|
||||||
|
this._sync();
|
||||||
|
}
|
||||||
|
index() {
|
||||||
|
let path = this._proxy.get_object_path();
|
||||||
|
if (path.startsWith(OBJECT_PREFIX)) {
|
||||||
|
const tail = path.substring(OBJECT_PREFIX.length);
|
||||||
|
let index = Number.parseInt(tail);
|
||||||
|
if (!Number.isNaN(index)) {
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
get name() {
|
||||||
|
return this._name;
|
||||||
|
}
|
||||||
|
get in_use() {
|
||||||
|
return this._in_use;
|
||||||
|
}
|
||||||
|
get activated() {
|
||||||
|
return this._activated;
|
||||||
|
}
|
||||||
|
get mountpoint() {
|
||||||
|
return this._mountpoint;
|
||||||
|
}
|
||||||
|
get path() {
|
||||||
|
return this._path;
|
||||||
|
}
|
||||||
|
get free_space() {
|
||||||
|
return this._free_space;
|
||||||
|
}
|
||||||
|
get allocated_space() {
|
||||||
|
return this._allocated_space;
|
||||||
|
}
|
||||||
|
_sync() {
|
||||||
|
this._name = this._proxy.Name;
|
||||||
|
this._in_use = this._proxy.InUse;
|
||||||
|
this._activated = this._proxy.Activated;
|
||||||
|
this._mountpoint = this._proxy.Mountpoint;
|
||||||
|
this._path = this._proxy.Path;
|
||||||
|
this._free_space = this._proxy.FreeSpace;
|
||||||
|
this._allocated_space = this._proxy.AllocatedSpace;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_a = RealmFS;
|
||||||
|
(() => {
|
||||||
|
GObject.registerClass({
|
||||||
|
GTypeName: 'RealmFS',
|
||||||
|
Properties: {
|
||||||
|
'name': GObject.ParamSpec.string('name', '', '', GObject.ParamFlags.READWRITE, ''),
|
||||||
|
'in-use': GObject.ParamSpec.boolean('in-use', '', '', GObject.ParamFlags.READWRITE, false),
|
||||||
|
'activated': GObject.ParamSpec.boolean('activated', '', '', GObject.ParamFlags.READWRITE, false),
|
||||||
|
'mountpoint': GObject.ParamSpec.string('mountpoint', '', '', GObject.ParamFlags.READWRITE, ''),
|
||||||
|
'path': GObject.ParamSpec.string('path', '', '', GObject.ParamFlags.READWRITE, ''),
|
||||||
|
'free-space': GObject.ParamSpec.uint64('free-space', '', '', GObject.ParamFlags.READWRITE, 0, Number.MAX_SAFE_INTEGER, 0),
|
||||||
|
'allocated-space': GObject.ParamSpec.uint64('allocated-space', '', '', GObject.ParamFlags.READWRITE, 0, Number.MAX_SAFE_INTEGER, 0),
|
||||||
|
},
|
||||||
|
}, _a);
|
||||||
|
})();
|
140
js/model/RealmManager.js
Normal file
140
js/model/RealmManager.js
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
import Gio from 'gi://Gio';
|
||||||
|
import { ObjectManager } from './ObjectManager.js';
|
||||||
|
import { loadInterfaceXML } from './Utils.js';
|
||||||
|
import { Realm } from './Realm.js';
|
||||||
|
import { RealmFS } from './RealmFS.js';
|
||||||
|
import { LabelColorManager } from './LabelColors.js';
|
||||||
|
const Signals = imports.signals;
|
||||||
|
const RealmIface = loadInterfaceXML("com.subgraph.realms.Realm");
|
||||||
|
const RealmFSIface = loadInterfaceXML("com.subgraph.realms.RealmFS");
|
||||||
|
const BUS_NAME = 'com.subgraph.Realms2';
|
||||||
|
const OBJECT_PATH = '/com/subgraph/Realms2';
|
||||||
|
const ManagerInterface = loadInterfaceXML("com.subgraph.realms.Manager2");
|
||||||
|
const ManagerProxy = Gio.DBusProxy.makeProxyWrapper(ManagerInterface);
|
||||||
|
;
|
||||||
|
export class RealmManager {
|
||||||
|
static instance() {
|
||||||
|
return RealmManager.INSTANCE;
|
||||||
|
}
|
||||||
|
constructor() {
|
||||||
|
this._globalConfig = {};
|
||||||
|
this._realms = {};
|
||||||
|
this._realmfs = {};
|
||||||
|
this._realmfs = {};
|
||||||
|
this._objectManager = new ObjectManager({
|
||||||
|
connection: Gio.DBus.system,
|
||||||
|
name: 'com.subgraph.Realms2',
|
||||||
|
objectPath: '/com/subgraph/Realms2',
|
||||||
|
knownInterfaces: [RealmIface, RealmFSIface],
|
||||||
|
onLoaded: this._onLoaded.bind(this),
|
||||||
|
});
|
||||||
|
this._proxy = new ManagerProxy(Gio.DBus.system, BUS_NAME, OBJECT_PATH, (_proxy, error) => {
|
||||||
|
if (error) {
|
||||||
|
logError(error);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this._setGlobalConfig().catch(logError);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this._labelColors = new LabelColorManager();
|
||||||
|
}
|
||||||
|
async _setGlobalConfig() {
|
||||||
|
let result = await this._proxy.GetGlobalConfigAsync();
|
||||||
|
this._globalConfig = result[0];
|
||||||
|
this._assignGlobalConfigToRealms();
|
||||||
|
}
|
||||||
|
async _onLoaded() {
|
||||||
|
let realms = this._objectManager.getProxiesForInterface('com.subgraph.realms.Realm');
|
||||||
|
for (let i = 0; i < realms.length; i++) {
|
||||||
|
this._addRealm(realms[i]);
|
||||||
|
}
|
||||||
|
let realmfs = this._objectManager.getProxiesForInterface('com.subgraph.realms.RealmFS');
|
||||||
|
for (let i = 0; i < realmfs.length; i++) {
|
||||||
|
this._addRealmFS(realmfs[i]);
|
||||||
|
}
|
||||||
|
this._objectManager.connect('interface-added', (_objectManager, interfaceName, proxy) => {
|
||||||
|
if (interfaceName === 'com.subgraph.Realm') {
|
||||||
|
this._addRealm(proxy);
|
||||||
|
}
|
||||||
|
else if (interfaceName === 'com.subgraph.RealmFS') {
|
||||||
|
this._addRealmFS(proxy);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this._objectManager.connect('interface-removed', (_objectManager, interfaceName, proxy) => {
|
||||||
|
if (interfaceName === 'com.subgraph.Realm') {
|
||||||
|
this._removeRealm(proxy);
|
||||||
|
}
|
||||||
|
else if (interfaceName === 'com.subgraph.RealmFS') {
|
||||||
|
this._removeRealmFS(proxy);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
async _addRealm(proxy) {
|
||||||
|
let objectPath = proxy.get_object_path();
|
||||||
|
let realm = new Realm(proxy, this._labelColors);
|
||||||
|
this._realms[objectPath] = realm;
|
||||||
|
this._findRealmFSForRealm(realm);
|
||||||
|
if (this._globalConfig) {
|
||||||
|
realm.set_global_config(this._globalConfig);
|
||||||
|
}
|
||||||
|
await realm.load_config();
|
||||||
|
this.emit('realm-added', realm);
|
||||||
|
}
|
||||||
|
_removeRealm(proxy) {
|
||||||
|
var _a;
|
||||||
|
let objectPath = proxy.get_object_path();
|
||||||
|
if (((_a = this._realms[objectPath]) === null || _a === void 0 ? void 0 : _a._proxy) === proxy) {
|
||||||
|
let realm = this._realms[objectPath];
|
||||||
|
delete this._realms[objectPath];
|
||||||
|
this.emit('realm-removed', realm);
|
||||||
|
}
|
||||||
|
proxy.disconnectAll();
|
||||||
|
}
|
||||||
|
_addRealmFS(proxy) {
|
||||||
|
let objectPath = proxy.get_object_path();
|
||||||
|
let realmfs = new RealmFS(proxy);
|
||||||
|
this._realmfs[objectPath] = realmfs;
|
||||||
|
this._assignRealmFSToRealms(realmfs);
|
||||||
|
this.emit('realmfs-added', realmfs);
|
||||||
|
}
|
||||||
|
_findRealmFSForRealm(realm) {
|
||||||
|
var _a;
|
||||||
|
if (realm.realmfs_index() > 0) {
|
||||||
|
realm.realmfs = (_a = Object.values(this._realmfs)
|
||||||
|
.find(realmfs => realmfs.index() === realm.realmfs_index())) !== null && _a !== void 0 ? _a : null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
realmfsList() {
|
||||||
|
return Object.values(this._realmfs);
|
||||||
|
}
|
||||||
|
_assignRealmFSToRealms(realmfs) {
|
||||||
|
Object.values(this._realms).forEach(r => {
|
||||||
|
if (r.realmfs_index() > 0 && r.realmfs_index() === realmfs.index() && r.realmfs != realmfs) {
|
||||||
|
r.realmfs = realmfs;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
_assignGlobalConfigToRealms() {
|
||||||
|
Object.values(this._realms).forEach(r => r.set_global_config(this._globalConfig));
|
||||||
|
}
|
||||||
|
_removeRealmFSFromRealms(realmfs) {
|
||||||
|
Object.values(this._realms).forEach(r => {
|
||||||
|
if (r.realmfs === realmfs) {
|
||||||
|
r.realmfs = null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
_removeRealmFS(proxy) {
|
||||||
|
var _a;
|
||||||
|
let objectPath = proxy.get_object_path();
|
||||||
|
if (((_a = this._realmfs[objectPath]) === null || _a === void 0 ? void 0 : _a._proxy) === proxy) {
|
||||||
|
let realmfs = this._realmfs[objectPath];
|
||||||
|
delete this._realmfs[objectPath];
|
||||||
|
this._removeRealmFSFromRealms(realmfs);
|
||||||
|
this.emit('realmfs-removed', realmfs);
|
||||||
|
}
|
||||||
|
proxy.disconnectAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
RealmManager.INSTANCE = new RealmManager();
|
||||||
|
Signals.addSignalMethods(RealmManager.prototype);
|
14
js/model/Utils.js
Normal file
14
js/model/Utils.js
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import Gio from 'gi://Gio';
|
||||||
|
export function loadInterfaceXML(iface) {
|
||||||
|
let uri = `resource:///com/subgraph/citadel/Realms/dbus-interfaces/${iface}.xml`;
|
||||||
|
let f = Gio.File.new_for_uri(uri);
|
||||||
|
try {
|
||||||
|
let [_ok, bytes] = f.load_contents(null);
|
||||||
|
// @ts-ignore
|
||||||
|
return new TextDecoder().decode(bytes);
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
log(`Failed to load D-Bus interface ${iface}`);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
16
meson.build
Normal file
16
meson.build
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
project(
|
||||||
|
'Realms',
|
||||||
|
version: '0.0.1',
|
||||||
|
license: ['GLP-Stallmans-Razor'],
|
||||||
|
meson_version: '>= 0.59.0'
|
||||||
|
)
|
||||||
|
|
||||||
|
APP_ID = 'com.subgraph.citadel.Realms'
|
||||||
|
|
||||||
|
gnome = import('gnome')
|
||||||
|
|
||||||
|
#tsc = find_program('tsc', required: true)
|
||||||
|
|
||||||
|
subdir('data')
|
||||||
|
subdir('src')
|
||||||
|
|
27
package-lock.json
generated
Normal file
27
package-lock.json
generated
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
{
|
||||||
|
"name": "Realms",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"lockfileVersion": 3,
|
||||||
|
"requires": true,
|
||||||
|
"packages": {
|
||||||
|
"": {
|
||||||
|
"name": "Realms",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"dependencies": {
|
||||||
|
"typescript": "^5.3.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/typescript": {
|
||||||
|
"version": "5.6.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz",
|
||||||
|
"integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==",
|
||||||
|
"bin": {
|
||||||
|
"tsc": "bin/tsc",
|
||||||
|
"tsserver": "bin/tsserver"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14.17"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
12
package.json
Normal file
12
package.json
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"name": "Realms",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"main": "src/main.ts",
|
||||||
|
"dependencies": {
|
||||||
|
"typescript": "^5.3.3"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"build": "tsc --strict",
|
||||||
|
"typecheck": "tsc --strict --noEmit"
|
||||||
|
}
|
||||||
|
}
|
120
src/Application.ts
Normal file
120
src/Application.ts
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
import Adw from 'gi://Adw';
|
||||||
|
import Gtk from 'gi://Gtk?version=4.0';
|
||||||
|
import Gio from 'gi://Gio';
|
||||||
|
import GObject from 'gi://GObject';
|
||||||
|
|
||||||
|
import './model/RealmManager.js';
|
||||||
|
import './model/Realm.js';
|
||||||
|
import './RealmsView.js';
|
||||||
|
import './RealmRow.js';
|
||||||
|
import './RealmInfo.js';
|
||||||
|
import './RealmModel.js';
|
||||||
|
import './ConfigureRealm.js';
|
||||||
|
|
||||||
|
|
||||||
|
import { Window } from './Window.js';
|
||||||
|
|
||||||
|
|
||||||
|
export class Application extends Adw.Application {
|
||||||
|
static {
|
||||||
|
GObject.registerClass({
|
||||||
|
GTypeName: 'RealmsApplication'
|
||||||
|
}, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
_window?: Window;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super({
|
||||||
|
application_id: 'com.subgraph.citadel.Realms',
|
||||||
|
flags: Gio.ApplicationFlags.DEFAULT_FLAGS,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
vfunc_activate() {
|
||||||
|
let {activeWindow} = this;
|
||||||
|
if (!activeWindow) {
|
||||||
|
activeWindow = new Window(this);
|
||||||
|
activeWindow.set_hide_on_close(true);
|
||||||
|
}
|
||||||
|
activeWindow.present();
|
||||||
|
}
|
||||||
|
|
||||||
|
vfunc_startup() {
|
||||||
|
super.vfunc_startup();
|
||||||
|
this.#setupActions();
|
||||||
|
this.#setupAccelerators();
|
||||||
|
// this.#loadStyleSheet();
|
||||||
|
const styleManager = Adw.StyleManager.get_default();
|
||||||
|
styleManager.colorScheme = Adw.ColorScheme.FORCE_DARK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
#loadStyleSheet() {
|
||||||
|
const provider = new Gtk.CssProvider();
|
||||||
|
provider.load_from_resource('/com/subgraph/citadel/Realms/css/style.css');
|
||||||
|
|
||||||
|
const display = Gdk.Display.get_default();
|
||||||
|
if (display) {
|
||||||
|
Gtk.StyleContext.add_provider_for_display(
|
||||||
|
display,
|
||||||
|
provider,
|
||||||
|
Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
#setupAccelerators() {
|
||||||
|
this.set_accels_for_action('app.quit', ['q']);
|
||||||
|
this.set_accels_for_action('app.realmConfig', ['c']);
|
||||||
|
this.set_accels_for_action('app.showHelp', ['h','question']);
|
||||||
|
}
|
||||||
|
|
||||||
|
#setupActions() {
|
||||||
|
this.add_action_entries([
|
||||||
|
// @ts-ignore
|
||||||
|
{ name: 'quit', activate: this.#onQuit.bind(this) },
|
||||||
|
// @ts-ignore
|
||||||
|
{ name: 'realmConfig', activate: this.#onRealmConfig.bind(this) },
|
||||||
|
// @ts-ignore
|
||||||
|
{ name: 'showHelp', activate: this.#onShowHelp.bind(this) },
|
||||||
|
// @ts-ignore
|
||||||
|
{ name: 'about', activate: this.#onAbout.bind(this) },
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#onQuit() {
|
||||||
|
let {activeWindow} = this;
|
||||||
|
if (activeWindow) {
|
||||||
|
activeWindow.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#onRealmConfig() {
|
||||||
|
let {activeWindow} = this;
|
||||||
|
if (activeWindow) {
|
||||||
|
let window = activeWindow as Window;
|
||||||
|
|
||||||
|
const realm = window.realms_view.selectedRealm;
|
||||||
|
if (realm) {
|
||||||
|
window.configureRealm(realm);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#onShowHelp() {
|
||||||
|
const help: Gtk.ShortcutsWindow = Gtk.Builder.new_from_resource('/com/subgraph/citadel/Realms/ui/HelpWindow.ui').get_object('helpWindow');
|
||||||
|
help.set_transient_for(this._window);
|
||||||
|
help.present();
|
||||||
|
}
|
||||||
|
|
||||||
|
#onAbout() {
|
||||||
|
const dialog = new Adw.AboutDialog({
|
||||||
|
application_icon: 'face-smile',
|
||||||
|
application_name: 'Realms',
|
||||||
|
developer_name: "Subgraph",
|
||||||
|
})
|
||||||
|
dialog.present(this._window);
|
||||||
|
}
|
||||||
|
}
|
225
src/ColorSchemeChooser.ts
Normal file
225
src/ColorSchemeChooser.ts
Normal file
@ -0,0 +1,225 @@
|
|||||||
|
import Adw from 'gi://Adw';
|
||||||
|
import GObject from 'gi://GObject';
|
||||||
|
import GLib from 'gi://GLib';
|
||||||
|
import Gdk from 'gi://Gdk?version=4.0';
|
||||||
|
import Gtk from 'gi://Gtk?version=4.0';
|
||||||
|
|
||||||
|
import {Base16Theme} from './model/Base16Themes.js';
|
||||||
|
import {ColorSchemeModel} from './ColorSchemeModel.js';
|
||||||
|
|
||||||
|
|
||||||
|
class PreviewRenderer {
|
||||||
|
|
||||||
|
private theme: Base16Theme;
|
||||||
|
private buffer: string;
|
||||||
|
|
||||||
|
constructor(theme: Base16Theme) {
|
||||||
|
this.theme = theme;
|
||||||
|
this.buffer = '';
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
colorAttrib(name: string, color: string) {
|
||||||
|
this.buffer += ` ${name}='${color}'`;
|
||||||
|
}
|
||||||
|
|
||||||
|
colorSpan(fg: string, bg = null) {
|
||||||
|
this.buffer += '<span';
|
||||||
|
if (fg) {
|
||||||
|
this.colorAttrib("foreground", fg);
|
||||||
|
}
|
||||||
|
if (bg) {
|
||||||
|
this.colorAttrib("background", bg);
|
||||||
|
}
|
||||||
|
this.buffer += ">";
|
||||||
|
}
|
||||||
|
|
||||||
|
endSpan() {
|
||||||
|
this.buffer += '</span>';
|
||||||
|
}
|
||||||
|
|
||||||
|
nl() {
|
||||||
|
this.buffer += ' \n ';
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
print(idx: number, text: string) {
|
||||||
|
let s = GLib.markup_escape_text(text, text.length);
|
||||||
|
let c = this.theme.terminal_palette_color(idx);
|
||||||
|
this.colorSpan(c);
|
||||||
|
this.buffer += s;
|
||||||
|
this.endSpan();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
vtype(text: string) {
|
||||||
|
return this.print(3, text);
|
||||||
|
}
|
||||||
|
|
||||||
|
konst(text: string) {
|
||||||
|
return this.print(1, text);
|
||||||
|
}
|
||||||
|
|
||||||
|
func(text: string) {
|
||||||
|
return this.print(4, text);
|
||||||
|
}
|
||||||
|
|
||||||
|
string(text: string) {
|
||||||
|
return this.print(2, text);
|
||||||
|
}
|
||||||
|
|
||||||
|
keyword(text: string) {
|
||||||
|
return this.print(5, text);
|
||||||
|
}
|
||||||
|
|
||||||
|
comment(text: string) {
|
||||||
|
return this.print(8, text);
|
||||||
|
}
|
||||||
|
|
||||||
|
text(text: string) {
|
||||||
|
let color = this.theme.terminal_foreground();
|
||||||
|
this.colorSpan(color);
|
||||||
|
this.buffer += text;
|
||||||
|
this.endSpan();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
renderPreview() {
|
||||||
|
let name = this.theme.name;
|
||||||
|
this.nl()
|
||||||
|
.comment('/**').nl()
|
||||||
|
.comment(' * An example of how this color scheme').nl()
|
||||||
|
.comment(' * might look in a text editor with syntax').nl()
|
||||||
|
.comment(' * highlighting.').nl()
|
||||||
|
.comment(' */').nl()
|
||||||
|
.nl()
|
||||||
|
.func('#include ').string('<stdio.h>').nl()
|
||||||
|
.func('#include ').string('<stdlib.h>').nl()
|
||||||
|
.nl()
|
||||||
|
.vtype('static char').text(' theme[] = ').string(`"${name}"`).text(';').nl()
|
||||||
|
.nl()
|
||||||
|
.vtype('int').text(' main(').vtype('int').text(' argc, ').vtype('char').text(' **argv) {').nl()
|
||||||
|
.text(' printf(').string('"Hello, ').keyword('%s').text('!').keyword('\\n').string('"').text(', theme);').nl()
|
||||||
|
.text(' exit(').konst('0').text(');').nl()
|
||||||
|
.text('}')
|
||||||
|
.nl();
|
||||||
|
|
||||||
|
return this.buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export class ColorSchemeChooser extends Adw.NavigationPage{
|
||||||
|
|
||||||
|
private _colorList!: Gtk.ListView;
|
||||||
|
private _previewLabel!: Gtk.Label;
|
||||||
|
css_provider: Gtk.CssProvider;
|
||||||
|
model: ColorSchemeModel;
|
||||||
|
|
||||||
|
static {
|
||||||
|
GObject.registerClass({
|
||||||
|
GTypeName: 'ColorSchemeChooser',
|
||||||
|
Template: 'resource:///com/subgraph/citadel/Realms/ui/ColorSchemeChooser.ui',
|
||||||
|
InternalChildren: ['colorList', 'previewLabel'],
|
||||||
|
}, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
addExpandToggleShortcut(keyval: number) {
|
||||||
|
let trigger = Gtk.KeyvalTrigger.new(keyval, Gdk.ModifierType.NO_MODIFIER_MASK);
|
||||||
|
let action = Gtk.CallbackAction.new((expander) => expander.activate_action('listitem.toggle-expand', null));
|
||||||
|
Gtk.TreeExpander.add_shortcut(Gtk.Shortcut.new(trigger, action));
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
|
||||||
|
this.model = new ColorSchemeModel();
|
||||||
|
|
||||||
|
this._previewLabel.add_css_class("preview");
|
||||||
|
this.css_provider = new Gtk.CssProvider();
|
||||||
|
|
||||||
|
const display = Gdk.Display.get_default();
|
||||||
|
if (display) {
|
||||||
|
Gtk.StyleContext.add_provider_for_display(
|
||||||
|
display,
|
||||||
|
this.css_provider,
|
||||||
|
Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.addExpandToggleShortcut(Gdk.KEY_space);
|
||||||
|
this.addExpandToggleShortcut(Gdk.KEY_l);
|
||||||
|
|
||||||
|
|
||||||
|
this._colorList.connect('activate', () => {
|
||||||
|
this.previewSelectedTheme();
|
||||||
|
})
|
||||||
|
this._colorList.single_click_activate = true;
|
||||||
|
this._colorList.model = this.model.selection;
|
||||||
|
|
||||||
|
const keyController = new Gtk.EventControllerKey();
|
||||||
|
keyController.connect('key-pressed', (_, keyval) => {
|
||||||
|
switch (keyval) {
|
||||||
|
case Gdk.KEY_j:
|
||||||
|
case Gdk.KEY_Down:
|
||||||
|
this.nextScheme();
|
||||||
|
break;
|
||||||
|
case Gdk.KEY_k:
|
||||||
|
case Gdk.KEY_Up:
|
||||||
|
this.prevScheme();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this._colorList.add_controller(keyController);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
nextScheme() {
|
||||||
|
let pos = this.model.changeSelected(1);
|
||||||
|
if (pos) {
|
||||||
|
this._colorList.scroll_to(pos, Gtk.ListScrollFlags.SELECT | Gtk.ListScrollFlags.FOCUS, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
prevScheme() {
|
||||||
|
let pos = this.model.changeSelected(-1);
|
||||||
|
if(pos) {
|
||||||
|
this._colorList.scroll_to(pos, Gtk.ListScrollFlags.SELECT | Gtk.ListScrollFlags.FOCUS, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
selectTheme(id?: string) {
|
||||||
|
const DEFAULT_THEME = '3024';
|
||||||
|
let row = this.model.searchId(id ?? DEFAULT_THEME);
|
||||||
|
if (row) {
|
||||||
|
let pos = row.get_position();
|
||||||
|
this.model.selectPosition(pos);
|
||||||
|
this._colorList.scroll_to(pos, Gtk.ListScrollFlags.SELECT | Gtk.ListScrollFlags.FOCUS, null);
|
||||||
|
this.previewSelectedTheme();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getSelectedTheme() {
|
||||||
|
return this.model.selectedTheme();
|
||||||
|
}
|
||||||
|
|
||||||
|
previewSelectedTheme() {
|
||||||
|
let theme = this.model.selectedTheme();
|
||||||
|
if (theme) {
|
||||||
|
this.setBackgroundColor(theme);
|
||||||
|
let renderer = new PreviewRenderer(theme);
|
||||||
|
// @ts-ignore
|
||||||
|
this._previewLabel.label = renderer.renderPreview();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setBackgroundColor(theme: Base16Theme) {
|
||||||
|
let css = `
|
||||||
|
label.preview {
|
||||||
|
background-color: ${theme.terminal_background()};
|
||||||
|
font-family: monospace;
|
||||||
|
font-size: 14pt;
|
||||||
|
}`;
|
||||||
|
this.css_provider.load_from_string(css);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
176
src/ColorSchemeModel.ts
Normal file
176
src/ColorSchemeModel.ts
Normal file
@ -0,0 +1,176 @@
|
|||||||
|
import GObject from 'gi://GObject';
|
||||||
|
import Gio from 'gi://Gio';
|
||||||
|
import Gtk from 'gi://Gtk?version=4.0';
|
||||||
|
|
||||||
|
import {Base16Theme} from './model/Base16Themes.js';
|
||||||
|
|
||||||
|
class ModelBuilder {
|
||||||
|
CATEGORIES = [
|
||||||
|
['atelier', 'Atelier'],
|
||||||
|
['black-metal', 'Black Metal'],
|
||||||
|
['brushtrees', 'Brush Trees'],
|
||||||
|
['classic', 'Classic'],
|
||||||
|
['default', 'Default'],
|
||||||
|
['google', 'Google'],
|
||||||
|
['grayscale', 'Grayscale'],
|
||||||
|
['gruvbox', 'Gruvbox'],
|
||||||
|
['harmonic', 'Harmonic'],
|
||||||
|
['ia', 'iA'],
|
||||||
|
['material', 'Material'],
|
||||||
|
['papercolor', 'PaperColor'],
|
||||||
|
['solarized', 'Solarized'],
|
||||||
|
['summerfruit', 'Summerfruit'],
|
||||||
|
['tomorrow', 'Tomorrow'],
|
||||||
|
['unikitty', 'Unikitty'],
|
||||||
|
];
|
||||||
|
|
||||||
|
currentCategory: null | ColorSchemeNode = null;
|
||||||
|
storeModel = new Gio.ListStore(ColorSchemeNode);
|
||||||
|
|
||||||
|
|
||||||
|
matchesCategory(theme: Base16Theme): boolean {
|
||||||
|
return (this.CATEGORIES.length > 0 && theme.id.startsWith(this.CATEGORIES[0][0]))
|
||||||
|
}
|
||||||
|
|
||||||
|
appendCurrentCategory() {
|
||||||
|
if (this.currentCategory) {
|
||||||
|
this.storeModel.append(this.currentCategory);
|
||||||
|
this.currentCategory = null;
|
||||||
|
this.CATEGORIES.shift();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
addToCategory(theme: Base16Theme) {
|
||||||
|
if (!this.currentCategory) {
|
||||||
|
this.currentCategory = new ColorSchemeNode(this.CATEGORIES[0][1]);
|
||||||
|
}
|
||||||
|
this.currentCategory.addChild(new ColorSchemeNode(theme.name, theme));
|
||||||
|
}
|
||||||
|
|
||||||
|
addTheme(theme: Base16Theme) {
|
||||||
|
if (this.matchesCategory(theme)) {
|
||||||
|
this.addToCategory(theme);
|
||||||
|
} else {
|
||||||
|
if (this.currentCategory) {
|
||||||
|
this.appendCurrentCategory();
|
||||||
|
}
|
||||||
|
this.storeModel.append(new ColorSchemeNode(theme.name, theme));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static buildTreeModel(): Gtk.TreeListModel {
|
||||||
|
let builder = new ModelBuilder();
|
||||||
|
Base16Theme.THEME_LIST.forEach(theme => builder.addTheme(theme));
|
||||||
|
return Gtk.TreeListModel.new(
|
||||||
|
builder.storeModel,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
item => (item as ColorSchemeNode).child_model,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export class ColorSchemeNode extends GObject.Object {
|
||||||
|
private _text: string;
|
||||||
|
|
||||||
|
theme: Base16Theme | null;
|
||||||
|
child_model: Gio.ListStore | null;
|
||||||
|
static {
|
||||||
|
GObject.registerClass({
|
||||||
|
GTypeName: 'ColorSchemeNode',
|
||||||
|
Properties: {
|
||||||
|
'text': GObject.ParamSpec.string('text', '', '', GObject.ParamFlags.READWRITE, ''),
|
||||||
|
}
|
||||||
|
|
||||||
|
}, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(text: string, theme: Base16Theme | null = null) {
|
||||||
|
super();
|
||||||
|
this._text = text;
|
||||||
|
this.theme = theme;
|
||||||
|
this.child_model = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
get text(): string {
|
||||||
|
return this._text;
|
||||||
|
}
|
||||||
|
|
||||||
|
addChild(child: ColorSchemeNode) {
|
||||||
|
if(this.child_model === null) {
|
||||||
|
this.child_model = new Gio.ListStore(ColorSchemeNode);
|
||||||
|
}
|
||||||
|
this.child_model.append(child);
|
||||||
|
}
|
||||||
|
|
||||||
|
matchesId(id: string): boolean {
|
||||||
|
return this.theme !== null && this.theme.id === id;
|
||||||
|
}
|
||||||
|
|
||||||
|
searchChildren(id: string): boolean {
|
||||||
|
if (this.child_model) {
|
||||||
|
for(let i = 0; i < this.child_model.n_items; i++) {
|
||||||
|
let node = this.child_model.get_item(i) as ColorSchemeNode;
|
||||||
|
if (node.matchesId(id)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class ColorSchemeModel {
|
||||||
|
selection: Gtk.SingleSelection;
|
||||||
|
treeModel: Gtk.TreeListModel;
|
||||||
|
constructor() {
|
||||||
|
this.treeModel = ModelBuilder.buildTreeModel();
|
||||||
|
this.selection = Gtk.SingleSelection.new(this.treeModel);
|
||||||
|
}
|
||||||
|
|
||||||
|
selectedTheme() {
|
||||||
|
// @ts-ignore
|
||||||
|
let item = this.selection.selected_item.item;
|
||||||
|
return item?.theme;
|
||||||
|
}
|
||||||
|
|
||||||
|
changeSelected(offset: number) {
|
||||||
|
const n_items = this.selection.n_items;
|
||||||
|
if (n_items <= 1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const pos = this.selection.selected;
|
||||||
|
if (pos == Gtk.INVALID_LIST_POSITION) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const newPos = pos + offset;
|
||||||
|
if (newPos < 0 || newPos >= n_items) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.selection.selected = newPos;
|
||||||
|
return newPos;
|
||||||
|
}
|
||||||
|
|
||||||
|
selectPosition(pos: number) {
|
||||||
|
this.selection.selected = pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
searchId(id: string, from = 0): Gtk.TreeListRow | null {
|
||||||
|
for(let i = from; i < this.treeModel.n_items; i++) {
|
||||||
|
let row = this.treeModel.get_row(i);
|
||||||
|
let item = row?.item as ColorSchemeNode;
|
||||||
|
if (item && item.matchesId(id)) {
|
||||||
|
return row;
|
||||||
|
}
|
||||||
|
if (item.searchChildren(id)) {
|
||||||
|
row?.set_expanded(true);
|
||||||
|
if(from === 0) {
|
||||||
|
return this.searchId(id, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
189
src/ConfigureRealm.ts
Normal file
189
src/ConfigureRealm.ts
Normal file
@ -0,0 +1,189 @@
|
|||||||
|
import GObject from 'gi://GObject'
|
||||||
|
import Gdk from 'gi://Gdk?version=4.0'
|
||||||
|
import Gtk from 'gi://Gtk?version=4.0'
|
||||||
|
import Adw from 'gi://Adw';
|
||||||
|
|
||||||
|
import {Realm} from './model/Realm.js';
|
||||||
|
import {BoolOptionData} from './model/RealmConfig.js';
|
||||||
|
import {Base16Theme} from './model/Base16Themes.js';
|
||||||
|
import { RealmManager } from './model/RealmManager.js';
|
||||||
|
import {ColorSchemeChooser} from './ColorSchemeChooser.js';
|
||||||
|
|
||||||
|
class OptionState {
|
||||||
|
value: any = null;
|
||||||
|
originalValue: any;
|
||||||
|
|
||||||
|
row: Adw.SwitchRow;
|
||||||
|
|
||||||
|
constructor(row: Adw.SwitchRow) {
|
||||||
|
this.row = row;
|
||||||
|
}
|
||||||
|
|
||||||
|
initValue(value: any) {
|
||||||
|
this.value = value;
|
||||||
|
this.originalValue = value;
|
||||||
|
this.row.active = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @param {any} value */
|
||||||
|
setValue(value: any) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
hasChanged() {
|
||||||
|
return this.value !== this.originalValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export class ConfigureRealm extends Adw.NavigationPage {
|
||||||
|
|
||||||
|
static {
|
||||||
|
GObject.registerClass({
|
||||||
|
GTypeName: "ConfigureRealm",
|
||||||
|
Template: 'resource:///com/subgraph/citadel/Realms/ui/ConfigureRealm.ui',
|
||||||
|
InternalChildren: ['optionsGroup', 'changedBanner', 'overlayCombo', 'realmfsCombo', 'colorSchemeButton', 'labelColorButton'],
|
||||||
|
Properties: {
|
||||||
|
'navigation-view': GObject.ParamSpec.object('navigation-view', '', '', GObject.ParamFlags.READWRITE, Adw.NavigationView),
|
||||||
|
'colorscheme-chooser': GObject.ParamSpec.object('colorscheme-chooser', '', '', GObject.ParamFlags.READWRITE, ColorSchemeChooser),
|
||||||
|
}
|
||||||
|
}, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
realm: Realm | null = null;
|
||||||
|
|
||||||
|
private _colorSchemeButton!: Gtk.Button ;
|
||||||
|
|
||||||
|
private _labelColorButton!: Gtk.ColorDialogButton;
|
||||||
|
|
||||||
|
private _optionsGroup!: Adw.PreferencesGroup;
|
||||||
|
private _changedBanner!: Adw.Banner;
|
||||||
|
|
||||||
|
private _navigationView!: Adw.NavigationView;
|
||||||
|
|
||||||
|
private _colorschemeChooser!: ColorSchemeChooser;
|
||||||
|
|
||||||
|
optionState: Map<string, OptionState> = new Map();
|
||||||
|
|
||||||
|
theme = Base16Theme.lookup('default-dark');
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this._addOptions();
|
||||||
|
const keyController = new Gtk.EventControllerKey();
|
||||||
|
keyController.connect('key-pressed', (_, keyval) => {
|
||||||
|
if (keyval === Gdk.KEY_j) {
|
||||||
|
this.vfunc_move_focus(Gtk.DirectionType.TAB_FORWARD);
|
||||||
|
} else if (keyval === Gdk.KEY_k) {
|
||||||
|
this.vfunc_move_focus(Gtk.DirectionType.TAB_BACKWARD);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.add_controller(keyController);
|
||||||
|
this._labelColorButton?.connect('notify::rgba', () => this._scanChanges());
|
||||||
|
this._colorSchemeButton?.connect('clicked', () => {
|
||||||
|
this.navigationView?.push_by_tag('realm-colorscheme');
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
get colorschemeChooser() {
|
||||||
|
return this._colorschemeChooser;
|
||||||
|
}
|
||||||
|
|
||||||
|
set colorschemeChooser(val) {
|
||||||
|
this._colorschemeChooser = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
set navigationView(val) {
|
||||||
|
this._navigationView = val;
|
||||||
|
this._navigationView?.connect('popped', (_view, page) => {
|
||||||
|
if (page === this.colorschemeChooser) {
|
||||||
|
let theme = this.colorschemeChooser.getSelectedTheme();
|
||||||
|
if (theme && this._colorSchemeButton) {
|
||||||
|
this.theme = theme;
|
||||||
|
this._colorSchemeButton.label = this.theme.name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
get navigationView() {
|
||||||
|
return this._navigationView;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
configure(realm: Realm) {
|
||||||
|
this.realm = realm;
|
||||||
|
this.set_title(`Configure realm-${realm.name}`);
|
||||||
|
this._setOptions(realm);
|
||||||
|
}
|
||||||
|
|
||||||
|
_setOptions(realm: Realm) {
|
||||||
|
let config = realm.config;
|
||||||
|
this.optionState.forEach((op,name) => {
|
||||||
|
let v = config.get_bool(name);
|
||||||
|
op.initValue(v);
|
||||||
|
})
|
||||||
|
|
||||||
|
let scheme = realm.config.get_colorscheme();
|
||||||
|
this.theme = Base16Theme.lookup(scheme);
|
||||||
|
if (this.theme && this._colorSchemeButton) {
|
||||||
|
this._colorSchemeButton.label = this.theme.name;
|
||||||
|
this.colorschemeChooser?.selectTheme(this.theme.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
let realmfs_list = RealmManager.instance().realmfsList();
|
||||||
|
// @ts-ignore
|
||||||
|
let model = this._realmfsCombo.model;
|
||||||
|
if(model.n_items > 0) {
|
||||||
|
model.splice(0, model.n_items, []);
|
||||||
|
}
|
||||||
|
realmfs_list.forEach(realmfs => model.append(realmfs.name));
|
||||||
|
|
||||||
|
let labelColor = realm.getLabelColor();
|
||||||
|
this._labelColorButton.rgba = labelColor;
|
||||||
|
|
||||||
|
this._scanChanges();
|
||||||
|
}
|
||||||
|
|
||||||
|
_addOptions() {
|
||||||
|
BoolOptionData.allOptions().forEach(option => {
|
||||||
|
let row = new Adw.SwitchRow({
|
||||||
|
title: option.description,
|
||||||
|
});
|
||||||
|
if (option.tooltip.length > 0) {
|
||||||
|
row.tooltipMarkup = option.tooltip;
|
||||||
|
}
|
||||||
|
let state = new OptionState(row);
|
||||||
|
this.optionState.set(option.name, state);
|
||||||
|
|
||||||
|
row.connect("notify::active", () => {
|
||||||
|
state.setValue(row.active);
|
||||||
|
this._scanChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
this._optionsGroup.add(row);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
_scanChanges() {
|
||||||
|
let changed = false;
|
||||||
|
this.optionState.forEach(op => {
|
||||||
|
if (op.hasChanged()) {
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
let labelColor = this.realm?.getLabelColor();
|
||||||
|
if (labelColor) {
|
||||||
|
if (!this._labelColorButton.rgba.equal(labelColor)) {
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this._changedBanner.set_revealed(changed);
|
||||||
|
}
|
||||||
|
|
||||||
|
_onApplyClicked() {
|
||||||
|
print("clikkk");
|
||||||
|
}
|
||||||
|
}
|
147
src/RealmInfo.ts
Normal file
147
src/RealmInfo.ts
Normal file
@ -0,0 +1,147 @@
|
|||||||
|
import GObject from 'gi://GObject'
|
||||||
|
import Gtk from 'gi://Gtk?version=4.0';
|
||||||
|
import {Realm} from "./model/Realm.js";
|
||||||
|
|
||||||
|
import {RealmInfoEntry} from './RealmInfoEntry.js';
|
||||||
|
|
||||||
|
const Sections = {
|
||||||
|
STATUS: 'Status',
|
||||||
|
OPTIONS: 'Options',
|
||||||
|
REALMFS: 'RealmFS',
|
||||||
|
MOUNTPOINT: 'RealmFS Mountpoint',
|
||||||
|
};
|
||||||
|
|
||||||
|
export class RealmInfo extends Gtk.ScrolledWindow {
|
||||||
|
private _column!: Gtk.Box;
|
||||||
|
private _columnTitle!: Gtk.Label;
|
||||||
|
|
||||||
|
static {
|
||||||
|
GObject.registerClass({
|
||||||
|
GTypeName: "RealmInfo",
|
||||||
|
Template: 'resource:///com/subgraph/citadel/Realms/ui/RealmInfo.ui',
|
||||||
|
Properties: {
|
||||||
|
'realm': GObject.ParamSpec.object('realm', '', '', GObject.ParamFlags.READWRITE, Realm),
|
||||||
|
},
|
||||||
|
InternalChildren: [
|
||||||
|
'column',
|
||||||
|
'columnTitle',
|
||||||
|
]
|
||||||
|
}, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
_buffer = "";
|
||||||
|
_changeId: number = 0;
|
||||||
|
_realm: Realm | null = null;
|
||||||
|
|
||||||
|
_entries: Map<string, RealmInfoEntry> = new Map();
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this._addEntries({
|
||||||
|
left: [
|
||||||
|
Sections.STATUS,
|
||||||
|
Sections.REALMFS,
|
||||||
|
Sections.MOUNTPOINT,
|
||||||
|
Sections.OPTIONS,
|
||||||
|
],
|
||||||
|
right: []
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
_addEntries(labels: { left: string[]; right: string[]; }) {
|
||||||
|
let addSectionEntries = (section: Gtk.Box, entries: string[]) => {
|
||||||
|
entries.forEach(name => {
|
||||||
|
let entry = new RealmInfoEntry(name);
|
||||||
|
this._entries.set(name, entry);
|
||||||
|
section.append(entry);
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
addSectionEntries(this._column, labels['left']);
|
||||||
|
}
|
||||||
|
|
||||||
|
get realm(): Realm | null {
|
||||||
|
return this._realm;
|
||||||
|
}
|
||||||
|
|
||||||
|
set realm(value) {
|
||||||
|
if (this.realm === value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (this._realm) {
|
||||||
|
this._realm.disconnect(this._changeId);
|
||||||
|
}
|
||||||
|
this._realm = value;
|
||||||
|
if (this._realm) {
|
||||||
|
this._changeId = this._realm.connect('changed', () => {
|
||||||
|
this.displayRealm();
|
||||||
|
});
|
||||||
|
this.displayRealm();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
setEntry(name: string, value: string) {
|
||||||
|
let entry = this._entries.get(name);
|
||||||
|
if (entry) {
|
||||||
|
entry.setValue(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setEntryVisible(name: string, isVisible: boolean = true) {
|
||||||
|
let entry = this._entries.get(name);
|
||||||
|
if (entry) {
|
||||||
|
entry.set_visible(isVisible);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
displayConfig() {
|
||||||
|
let config = this._realm?.config;
|
||||||
|
if (config) {
|
||||||
|
let enabled_default = config.enabled_bool_option_labels(true);
|
||||||
|
let enabled = config.enabled_bool_option_labels(false);
|
||||||
|
let buffer = enabled_default.join(' ');
|
||||||
|
buffer += '\n';
|
||||||
|
buffer += enabled.map(s => `<u>${s}</u>`)
|
||||||
|
.join(' ');
|
||||||
|
this.setEntry(Sections.OPTIONS, buffer);
|
||||||
|
} else {
|
||||||
|
this.setEntry(Sections.OPTIONS, '');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
displayRealmFS() {
|
||||||
|
let realmfs = this._realm?.realmfs;
|
||||||
|
if (realmfs) {
|
||||||
|
this.setEntryVisible(Sections.REALMFS);
|
||||||
|
this.setEntry(Sections.REALMFS, `${realmfs.name}-realmfs.img`);
|
||||||
|
if(realmfs.activated) {
|
||||||
|
this.setEntryVisible(Sections.MOUNTPOINT);
|
||||||
|
this.setEntry(Sections.MOUNTPOINT, realmfs.mountpoint);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
this.setEntryVisible(Sections.MOUNTPOINT, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
this.setEntryVisible(Sections.REALMFS, false);
|
||||||
|
this.setEntryVisible(Sections.MOUNTPOINT, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
displayRealm() {
|
||||||
|
if (this._realm) {
|
||||||
|
this._columnTitle.label = `Realm ${this._realm.name}`;
|
||||||
|
if (this._realm.is_running()) {
|
||||||
|
this.setEntry("Status", "Running");
|
||||||
|
} else {
|
||||||
|
this.setEntry("Status", "Stopped");
|
||||||
|
}
|
||||||
|
this.displayConfig();
|
||||||
|
this.displayRealmFS();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
24
src/RealmInfoEntry.ts
Normal file
24
src/RealmInfoEntry.ts
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
import GObject from 'gi://GObject'
|
||||||
|
import Gtk from 'gi://Gtk?version=4.0';
|
||||||
|
|
||||||
|
export class RealmInfoEntry extends Gtk.Box {
|
||||||
|
private _nameLabel!: Gtk.Label;
|
||||||
|
private _valueLabel!: Gtk.Label;
|
||||||
|
static {
|
||||||
|
GObject.registerClass({
|
||||||
|
GTypeName: "RealmInfoEntry",
|
||||||
|
Template: 'resource:///com/subgraph/citadel/Realms/ui/RealmInfoEntry.ui',
|
||||||
|
InternalChildren: ['nameLabel', 'valueLabel']
|
||||||
|
}, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(name: string) {
|
||||||
|
super();
|
||||||
|
this._nameLabel.label = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
setValue(value: string) {
|
||||||
|
this._valueLabel.label = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
49
src/RealmModel.ts
Normal file
49
src/RealmModel.ts
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
import Gio from 'gi://Gio';
|
||||||
|
import GObject from 'gi://GObject';
|
||||||
|
import { Realm } from './model/Realm.js';
|
||||||
|
import {RealmManager} from "./model/RealmManager.js";
|
||||||
|
|
||||||
|
export class RealmModel extends GObject.Object {
|
||||||
|
static {
|
||||||
|
GObject.registerClass({
|
||||||
|
GTypeName: 'RealmModel',
|
||||||
|
Implements: [Gio.ListModel],
|
||||||
|
}, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
_realms: Realm[] = [];
|
||||||
|
_realmManager: RealmManager;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this._realmManager = RealmManager.instance();
|
||||||
|
|
||||||
|
this._realmManager.connect('realm-added', (_manager, realm: Realm) => {
|
||||||
|
let pos = this._realms.length;
|
||||||
|
this._realms.push(realm);
|
||||||
|
// @ts-ignore
|
||||||
|
this.items_changed(pos, 0, 1);
|
||||||
|
});
|
||||||
|
|
||||||
|
this._realmManager.connect('realm-removed', (_manager, realm) => {
|
||||||
|
let pos = this._realms.findIndex(r => r === realm);
|
||||||
|
if (pos >= 0) {
|
||||||
|
this._realms.splice(pos, 1);
|
||||||
|
// @ts-ignore
|
||||||
|
this.items_changed(pos, 1, 0);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
vfunc_get_item_type() {
|
||||||
|
return Realm;
|
||||||
|
}
|
||||||
|
|
||||||
|
vfunc_get_item(position: number) {
|
||||||
|
return this._realms[position] || null;
|
||||||
|
}
|
||||||
|
|
||||||
|
vfunc_get_n_items() {
|
||||||
|
return this._realms.length;
|
||||||
|
}
|
||||||
|
}
|
59
src/RealmRow.ts
Normal file
59
src/RealmRow.ts
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
import GObject from 'gi://GObject';
|
||||||
|
import Gtk from 'gi://Gtk?version=4.0';
|
||||||
|
|
||||||
|
import { Realm } from './model/Realm.js';
|
||||||
|
|
||||||
|
export class RealmRow extends Gtk.Widget {
|
||||||
|
private _nameLabel!: Gtk.Label;
|
||||||
|
|
||||||
|
static {
|
||||||
|
GObject.registerClass({
|
||||||
|
GTypeName: 'RealmRow',
|
||||||
|
Template: 'resource:///com/subgraph/citadel/Realms/ui/RealmRow.ui',
|
||||||
|
Properties: {
|
||||||
|
'realm': GObject.ParamSpec.object('realm', '','',GObject.ParamFlags.READWRITE, Realm),
|
||||||
|
},
|
||||||
|
InternalChildren: ['nameLabel'],
|
||||||
|
}, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
_realm!: Realm | null;
|
||||||
|
|
||||||
|
_notifyId = 0;
|
||||||
|
|
||||||
|
|
||||||
|
get realm() {
|
||||||
|
if (this._realm === undefined) {
|
||||||
|
this._realm = null;
|
||||||
|
}
|
||||||
|
return this._realm;
|
||||||
|
}
|
||||||
|
set realm(value) {
|
||||||
|
if(this.realm === value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(this.realm && this._notifyId) {
|
||||||
|
this.realm.disconnect(this._notifyId);
|
||||||
|
this._notifyId = 0;
|
||||||
|
}
|
||||||
|
this._realm = value;
|
||||||
|
|
||||||
|
if(this.realm) {
|
||||||
|
this._notifyId = this.realm.connect('notify', this.syncRealm.bind(this));
|
||||||
|
this.syncRealm();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.notify('realm');
|
||||||
|
}
|
||||||
|
|
||||||
|
syncRealm() {
|
||||||
|
if (this.realm && this.realm.is_running()) {
|
||||||
|
this._nameLabel.remove_css_class('dim-label');
|
||||||
|
} else {
|
||||||
|
// @ts-ignore
|
||||||
|
this._nameLabel.add_css_class('dim-label');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
106
src/RealmsView.ts
Normal file
106
src/RealmsView.ts
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
import GObject from 'gi://GObject';
|
||||||
|
import Gdk from 'gi://Gdk?version=4.0';
|
||||||
|
import Gtk from 'gi://Gtk?version=4.0';
|
||||||
|
|
||||||
|
import {Realm} from "./model/Realm.js";
|
||||||
|
|
||||||
|
export class RealmsView extends Gtk.Widget {
|
||||||
|
private _realmsSelection!: Gtk.SingleSelection;
|
||||||
|
private _hiddenRealmsFilterModel!: Gtk.FilterListModel;
|
||||||
|
private _realmSorter!: Gtk.CustomSorter;
|
||||||
|
|
||||||
|
static {
|
||||||
|
GObject.registerClass({
|
||||||
|
GTypeName: 'RealmsView',
|
||||||
|
Template: 'resource:///com/subgraph/citadel/Realms/ui/RealmsView.ui',
|
||||||
|
Properties: {
|
||||||
|
'selected-realm': GObject.ParamSpec.object('selected-realm', '', '', GObject.ParamFlags.READWRITE, Realm),
|
||||||
|
},
|
||||||
|
InternalChildren: ['realmsSelection', 'hiddenRealmsFilterModel', 'realmSorter'],
|
||||||
|
}, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
_selectedRealm = null;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this._setupHiddenRealmsFilter();
|
||||||
|
this._setupRealmSorter();
|
||||||
|
const keyController = new Gtk.EventControllerKey();
|
||||||
|
keyController.connect('key-pressed', (_, keyval) => {
|
||||||
|
switch (keyval) {
|
||||||
|
case Gdk.KEY_j:
|
||||||
|
case Gdk.KEY_Down:
|
||||||
|
this.nextRealm();
|
||||||
|
break;
|
||||||
|
case Gdk.KEY_k:
|
||||||
|
case Gdk.KEY_Up:
|
||||||
|
this.prevRealm();
|
||||||
|
break;
|
||||||
|
case Gdk.KEY_Escape:
|
||||||
|
this.activate_action('app.quit', null);
|
||||||
|
print ("escaped");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.add_controller(keyController);
|
||||||
|
}
|
||||||
|
|
||||||
|
_changeSelected(offset: number) {
|
||||||
|
const n_items = this._realmsSelection.n_items;
|
||||||
|
|
||||||
|
if (n_items <= 1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const pos = this._realmsSelection.selected;
|
||||||
|
if (pos == Gtk.INVALID_LIST_POSITION) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const newPos = pos + offset;
|
||||||
|
|
||||||
|
if (newPos < 0 || newPos >= n_items) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this._realmsSelection.selected = newPos;
|
||||||
|
}
|
||||||
|
|
||||||
|
nextRealm() {
|
||||||
|
this._changeSelected(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
prevRealm() {
|
||||||
|
this._changeSelected(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
get selectedRealm() {
|
||||||
|
return this._selectedRealm;
|
||||||
|
}
|
||||||
|
|
||||||
|
set selectedRealm(value) {
|
||||||
|
if (this.selectedRealm === value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this._selectedRealm = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
_setupHiddenRealmsFilter() {
|
||||||
|
this._hiddenRealmsFilterModel.filter = Gtk.CustomFilter.new(item => !(item as Realm).is_system_realm);
|
||||||
|
}
|
||||||
|
|
||||||
|
_setupRealmSorter() {
|
||||||
|
// 1) Sort 'Current' the lowest (top of list).
|
||||||
|
// 2) Then sort 'Running' lower than not 'Running'
|
||||||
|
// 3) Realms in the same run state sorted by lowest timestamp
|
||||||
|
this._realmSorter.set_sort_func((a,b) => {
|
||||||
|
if (a.is_current || (a.is_running && !b.is_running)) {
|
||||||
|
return Gtk.Ordering.SMALLER;
|
||||||
|
} else if (b.is_current || (b.is_running && !a.is_running)) {
|
||||||
|
return Gtk.Ordering.LARGER;
|
||||||
|
} else {
|
||||||
|
return b.timestamp - a.timestamp;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
41
src/Window.ts
Normal file
41
src/Window.ts
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
import GObject from 'gi://GObject';
|
||||||
|
import Adw from 'gi://Adw';
|
||||||
|
import { Realm } from './model/Realm.js';
|
||||||
|
import {ConfigureRealm} from './ConfigureRealm.js'
|
||||||
|
import { RealmsView } from './RealmsView.js';
|
||||||
|
|
||||||
|
export class Window extends Adw.ApplicationWindow {
|
||||||
|
|
||||||
|
private _realmsView!: RealmsView;
|
||||||
|
private _configureRealm!: ConfigureRealm;
|
||||||
|
private _navView!: Adw.NavigationView;
|
||||||
|
|
||||||
|
static {
|
||||||
|
GObject.registerClass({
|
||||||
|
GTypeName: 'RealmsWindow',
|
||||||
|
Template: 'resource:///com/subgraph/citadel/Realms/ui/Window.ui',
|
||||||
|
InternalChildren: ['realmsView', 'configureRealm', 'navView'],
|
||||||
|
}, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(application: Adw.Application) {
|
||||||
|
super({ application: application });
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
configureRealm(realm: Realm) {
|
||||||
|
this._configureRealm.configure(realm);
|
||||||
|
this._navView.push(this._configureRealm);
|
||||||
|
}
|
||||||
|
|
||||||
|
get realms_view() {
|
||||||
|
return this._realmsView;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
vfunc_close_request() {
|
||||||
|
super.vfunc_close_request();
|
||||||
|
this.run_dispose();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
1097
src/colors/Base16Theme.ts
Normal file
1097
src/colors/Base16Theme.ts
Normal file
File diff suppressed because it is too large
Load Diff
147
src/colors/ColorSchemeModel.ts
Normal file
147
src/colors/ColorSchemeModel.ts
Normal file
@ -0,0 +1,147 @@
|
|||||||
|
import GObject from 'gi://GObject';
|
||||||
|
import Gio from 'gi://Gio';
|
||||||
|
import Gtk from 'gi://Gtk?version=4.0';
|
||||||
|
|
||||||
|
import { Base16Theme } from './Base16Theme.js';
|
||||||
|
|
||||||
|
|
||||||
|
export class ColorSchemeModel {
|
||||||
|
selection: Gtk.SingleSelection;
|
||||||
|
treeModel: Gtk.TreeListModel;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
let builder = new TreeModelBuilder();
|
||||||
|
this.treeModel = builder.buildTreeModel();
|
||||||
|
this.selection = Gtk.SingleSelection.new(this.treeModel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ColorModelNode extends GObject.Object {
|
||||||
|
static {
|
||||||
|
GObject.registerClass({
|
||||||
|
GTypeName: 'ColorModelNode',
|
||||||
|
Properties: {
|
||||||
|
'text': GObject.ParamSpec.string('text', '', '', GObject.ParamFlags.READWRITE, ''),
|
||||||
|
|
||||||
|
}
|
||||||
|
}, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
data: Base16Theme | ColorThemeCategory;
|
||||||
|
|
||||||
|
constructor(data: Base16Theme | ColorThemeCategory) {
|
||||||
|
super();
|
||||||
|
this.data = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
get text(): string {
|
||||||
|
return this.data.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
child_model() {
|
||||||
|
if (this.data instanceof ColorThemeCategory) {
|
||||||
|
return this.data.children;
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
isThemeWithId(id: string): boolean {
|
||||||
|
return (this.data instanceof Base16Theme) &&
|
||||||
|
(this.data.id === id);
|
||||||
|
}
|
||||||
|
|
||||||
|
hasChildThemeWithId(id: string): boolean {
|
||||||
|
const child_model = this.child_model();
|
||||||
|
|
||||||
|
if (child_model) {
|
||||||
|
for (let i = 0; i < child_model.n_items; i++) {
|
||||||
|
let node = child_model.get_item(i) as ColorModelNode;
|
||||||
|
if (node.isThemeWithId(id)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static newScheme(color: Base16Theme) {
|
||||||
|
return new ColorModelNode(color);
|
||||||
|
}
|
||||||
|
|
||||||
|
static newCategory(category: ColorThemeCategory) {
|
||||||
|
return new ColorModelNode(category);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ColorThemeCategory {
|
||||||
|
name: string;
|
||||||
|
children: Gio.ListStore;
|
||||||
|
|
||||||
|
constructor(name: string) {
|
||||||
|
this.name = name;
|
||||||
|
this.children = new Gio.ListStore(ColorModelNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
append(color: Base16Theme) {
|
||||||
|
this.children.append(ColorModelNode.newScheme(color));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class TreeModelBuilder {
|
||||||
|
categories: [string,string][];
|
||||||
|
currentCategory: null | ColorThemeCategory;
|
||||||
|
storeModel: Gio.ListStore;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.categories = Base16Theme.CATEGORIES;
|
||||||
|
this.currentCategory = null;
|
||||||
|
this.storeModel = new Gio.ListStore(ColorModelNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
buildTreeModel() {
|
||||||
|
Base16Theme.THEMES.forEach(theme => this.addTheme(theme));
|
||||||
|
return Gtk.TreeListModel.new(
|
||||||
|
this.storeModel,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
item => (item as ColorModelNode).child_model(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
appendCurrentCategory() {
|
||||||
|
if (this.currentCategory) {
|
||||||
|
this.storeModel.append(ColorModelNode.newCategory(this.currentCategory));
|
||||||
|
this.currentCategory = null;
|
||||||
|
this.categories.shift();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
matchesNextCategory(theme: Base16Theme): boolean {
|
||||||
|
if (this.categories.length === 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
let [id, _name] = this.categories[0];
|
||||||
|
return theme.id === id;
|
||||||
|
}
|
||||||
|
|
||||||
|
addTheme(theme: Base16Theme) {
|
||||||
|
if (this.matchesNextCategory(theme)) {
|
||||||
|
this.addToCategory(theme);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (this.currentCategory) {
|
||||||
|
this.appendCurrentCategory();
|
||||||
|
}
|
||||||
|
this.storeModel.append(ColorModelNode.newScheme(theme));
|
||||||
|
}
|
||||||
|
|
||||||
|
addToCategory(theme: Base16Theme) {
|
||||||
|
if (!this.currentCategory) {
|
||||||
|
let [_id, name] = this.categories[0];
|
||||||
|
this.currentCategory = new ColorThemeCategory(name);
|
||||||
|
}
|
||||||
|
this.currentCategory.append(theme);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
27
src/com.subgraph.citadel.Realms.js
Normal file
27
src/com.subgraph.citadel.Realms.js
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
#!@GJS@ -m
|
||||||
|
|
||||||
|
import GLib from 'gi://GLib'
|
||||||
|
|
||||||
|
// Initialize the package
|
||||||
|
imports.package.init({
|
||||||
|
name: '@PACKAGE_NAME@',
|
||||||
|
version: '@PACKAGE_VERSION@',
|
||||||
|
prefix: '@PREFIX@',
|
||||||
|
libdir: '@LIBDIR@',
|
||||||
|
});
|
||||||
|
|
||||||
|
// Import the main module and run the main function
|
||||||
|
const loop = new GLib.MainLoop(null, false);
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
|
import('resource:///com/subgraph/citadel/Realms/js/main.js')
|
||||||
|
.then((main) => {
|
||||||
|
GLib.idle_add(GLib.PRIORITY_DEFAULT_IDLE, () => {
|
||||||
|
loop.quit();
|
||||||
|
imports.package.run(main);
|
||||||
|
return GLib.SOURCE_REMOVE;
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch(logError);
|
||||||
|
|
||||||
|
loop.run();
|
26
src/com.subgraph.citadel.Realms.src.gresource.xml
Normal file
26
src/com.subgraph.citadel.Realms.src.gresource.xml
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<gresources>
|
||||||
|
<gresource prefix="/com/subgraph/citadel/Realms/js">
|
||||||
|
<file>main.js</file>
|
||||||
|
<file>model/Base16Themes.js</file>
|
||||||
|
<file>model/LabelColors.js</file>
|
||||||
|
<file>model/ObjectManager.js</file>
|
||||||
|
<file>model/RealmManager.js</file>
|
||||||
|
<file>model/Realm.js</file>
|
||||||
|
<file>model/RealmConfig.js</file>
|
||||||
|
<file>model/OptionData.js</file>
|
||||||
|
<file>model/RealmFS.js</file>
|
||||||
|
<file>model/Utils.js</file>
|
||||||
|
<file>Application.js</file>
|
||||||
|
<file>ConfigureRealm.js</file>
|
||||||
|
<file>ColorSchemeChooser.js</file>
|
||||||
|
<file>ColorSchemeModel.js</file>
|
||||||
|
|
||||||
|
<file>RealmRow.js</file>
|
||||||
|
<file>RealmsView.js</file>
|
||||||
|
<file>RealmInfo.js</file>
|
||||||
|
<file>RealmInfoEntry.js</file>
|
||||||
|
<file>RealmModel.js</file>
|
||||||
|
<file>Window.js</file>
|
||||||
|
</gresource>
|
||||||
|
</gresources>
|
8
src/main.ts
Normal file
8
src/main.ts
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
import 'gi://Gdk?version=4.0'
|
||||||
|
import 'gi://Gtk?version=4.0'
|
||||||
|
|
||||||
|
import { Application } from './Application.js'
|
||||||
|
|
||||||
|
export function main(argv: string[]) {
|
||||||
|
return new Application().run(argv);
|
||||||
|
}
|
24
src/meson.build
Normal file
24
src/meson.build
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
configure_file(
|
||||||
|
input: APP_ID + '.js',
|
||||||
|
output: APP_ID,
|
||||||
|
configuration: {
|
||||||
|
'GJS': find_program('gjs').full_path(),
|
||||||
|
'PACKAGE_NAME': APP_ID,
|
||||||
|
'PACKAGE_VERSION': meson.project_version(),
|
||||||
|
'PREFIX': get_option('prefix'),
|
||||||
|
'LIBDIR': get_option('prefix') / get_option('libdir')
|
||||||
|
},
|
||||||
|
install_dir: get_option('bindir'),
|
||||||
|
install_mode: 'rwxr-xr-x'
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
app_resource = gnome.compile_resources(
|
||||||
|
APP_ID + '.src',
|
||||||
|
APP_ID + '.src.gresource.xml',
|
||||||
|
gresource_bundle: true,
|
||||||
|
source_dir: '../js',
|
||||||
|
install: true,
|
||||||
|
install_dir: get_option('datadir') / APP_ID,
|
||||||
|
)
|
1081
src/model/Base16Themes.ts
Normal file
1081
src/model/Base16Themes.ts
Normal file
File diff suppressed because it is too large
Load Diff
89
src/model/LabelColors.ts
Normal file
89
src/model/LabelColors.ts
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
import Gdk from 'gi://Gdk?version=4.0';
|
||||||
|
import Gio from 'gi://Gio';
|
||||||
|
import {Realm} from './Realm.js'
|
||||||
|
|
||||||
|
const CITADEL_SETTINGS_SCHEMA = 'com.subgraph.citadel';
|
||||||
|
const LABEL_COLOR_LIST_KEY = 'label-color-list';
|
||||||
|
const REALM_LABEL_COLORS_KEY = 'realm-label-colors';
|
||||||
|
|
||||||
|
const DEFAULT_LABEL_COLOR = new Gdk.RGBA({ red: 153, green: 193, blue: 241, });
|
||||||
|
|
||||||
|
export class LabelColorManager {
|
||||||
|
private _citadelSettings: Gio.Settings;
|
||||||
|
private _defaultColors: Gdk.RGBA[];
|
||||||
|
private _realmLabelColors: Map<string, Gdk.RGBA>;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this._citadelSettings = new Gio.Settings({ schema_id: CITADEL_SETTINGS_SCHEMA });
|
||||||
|
this._defaultColors = [];
|
||||||
|
this._realmLabelColors = new Map();
|
||||||
|
this._loadColors();
|
||||||
|
}
|
||||||
|
|
||||||
|
_loadColors() {
|
||||||
|
let entries = this._citadelSettings.get_strv(LABEL_COLOR_LIST_KEY);
|
||||||
|
entries.forEach(entry => {
|
||||||
|
let c = new Gdk.RGBA();
|
||||||
|
if (c.parse(entry)) {
|
||||||
|
this._defaultColors.push(c);
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
entries = this._citadelSettings.get_strv(REALM_LABEL_COLORS_KEY);
|
||||||
|
entries.forEach(entry => {
|
||||||
|
let parts = entry.split(":");
|
||||||
|
if (parts.length === 2) {
|
||||||
|
let c = new Gdk.RGBA();
|
||||||
|
if (c.parse(parts[1])) {
|
||||||
|
this._realmLabelColors.set(parts[0], c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
updateRealmColor(realm: Realm, color: Gdk.RGBA) {
|
||||||
|
this._realmLabelColors.set(realm.name, color);
|
||||||
|
this._storeRealmColors();
|
||||||
|
}
|
||||||
|
|
||||||
|
lookupRealmColor(realm: Realm): Gdk.RGBA {
|
||||||
|
let c = this._realmLabelColors.get(realm.name);
|
||||||
|
if (c) {
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
let newColor = this._allocateColor();
|
||||||
|
this.updateRealmColor(realm, newColor);
|
||||||
|
return newColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
_storeRealmColors() {
|
||||||
|
let entries: string[] = [];
|
||||||
|
this._realmLabelColors.forEach((v,k) => {
|
||||||
|
entries.push(`${k}:${v.to_string()}`);
|
||||||
|
});
|
||||||
|
entries.sort();
|
||||||
|
|
||||||
|
this._citadelSettings.set_strv(REALM_LABEL_COLORS_KEY, entries);
|
||||||
|
}
|
||||||
|
|
||||||
|
_allocateColor() {
|
||||||
|
// 1) No default colors? return a built in color
|
||||||
|
if (this._defaultColors.length === 0) {
|
||||||
|
return DEFAULT_LABEL_COLOR;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2) Find first color on default color list that isn't used already
|
||||||
|
let usedColors = Array.from(this._realmLabelColors.values());
|
||||||
|
let defaultColor = this._defaultColors.find(color => !usedColors.some(c => c.equal(color)));
|
||||||
|
if (defaultColor) {
|
||||||
|
return defaultColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3) Choose a random element of the default list
|
||||||
|
let index = Math.floor(Math.random() * this._defaultColors.length);
|
||||||
|
return this._defaultColors[index];
|
||||||
|
}
|
||||||
|
}
|
239
src/model/ObjectManager.ts
Normal file
239
src/model/ObjectManager.ts
Normal file
@ -0,0 +1,239 @@
|
|||||||
|
import Gio from 'gi://Gio';
|
||||||
|
import GLib from 'gi://GLib';
|
||||||
|
const Signals = imports.signals;
|
||||||
|
|
||||||
|
import type {SignalMethods} from 'gjs';
|
||||||
|
|
||||||
|
Gio._promisify(Gio.DBusProxy.prototype, 'init_async', 'init_finish');
|
||||||
|
|
||||||
|
// Specified in the D-Bus specification here:
|
||||||
|
// http://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces-objectmanager
|
||||||
|
const ObjectManagerIface = `
|
||||||
|
<node>
|
||||||
|
<interface name="org.freedesktop.DBus.ObjectManager">
|
||||||
|
<method name="GetManagedObjects">
|
||||||
|
<arg name="objects" type="a{oa{sa{sv}}}" direction="out"/>
|
||||||
|
</method>
|
||||||
|
<signal name="InterfacesAdded">
|
||||||
|
<arg name="objectPath" type="o"/>
|
||||||
|
<arg name="interfaces" type="a{sa{sv}}" />
|
||||||
|
</signal>
|
||||||
|
<signal name="InterfacesRemoved">
|
||||||
|
<arg name="objectPath" type="o"/>
|
||||||
|
<arg name="interfaces" type="as" />
|
||||||
|
</signal>
|
||||||
|
</interface>
|
||||||
|
</node>`;
|
||||||
|
|
||||||
|
const ObjectManagerInfo = Gio.DBusInterfaceInfo.new_for_xml(ObjectManagerIface);
|
||||||
|
|
||||||
|
|
||||||
|
export interface ObjectManager extends SignalMethods {};
|
||||||
|
|
||||||
|
export class ObjectManager {
|
||||||
|
private _connection: Gio.DBusConnection;
|
||||||
|
private _serviceName: string;
|
||||||
|
private _managerPath: string;
|
||||||
|
private _cancellable: any;
|
||||||
|
private _interfaceInfos: { [s: string]: Gio.DBusInterfaceInfo };
|
||||||
|
private _objects: { [s: string]: { [s: string]: Gio.DBusProxy }};
|
||||||
|
private _onLoaded: any;
|
||||||
|
private _managerProxy: Gio.DBusProxy;
|
||||||
|
private _interfaces: { [s: string]: Gio.DBusProxy[] };
|
||||||
|
|
||||||
|
constructor(params: { connection: Gio.DBusConnection; name: string; objectPath: string; knownInterfaces: any; onLoaded: any; cancellable?: any; }) {
|
||||||
|
this._connection = params.connection;
|
||||||
|
this._serviceName = params.name;
|
||||||
|
this._managerPath = params.objectPath;
|
||||||
|
this._cancellable = params.cancellable ?? null;
|
||||||
|
|
||||||
|
this._managerProxy = new Gio.DBusProxy({
|
||||||
|
g_connection: this._connection,
|
||||||
|
g_interface_name: ObjectManagerInfo.name,
|
||||||
|
g_interface_info: ObjectManagerInfo,
|
||||||
|
g_name: this._serviceName,
|
||||||
|
g_object_path: this._managerPath,
|
||||||
|
g_flags: Gio.DBusProxyFlags.DO_NOT_AUTO_START,
|
||||||
|
});
|
||||||
|
|
||||||
|
this._interfaceInfos = {};
|
||||||
|
this._objects = {};
|
||||||
|
this._interfaces = {};
|
||||||
|
this._onLoaded = params.onLoaded;
|
||||||
|
|
||||||
|
if (params.knownInterfaces)
|
||||||
|
this._registerInterfaces(params.knownInterfaces);
|
||||||
|
|
||||||
|
this._initManagerProxy();
|
||||||
|
}
|
||||||
|
|
||||||
|
_completeLoad() {
|
||||||
|
if (this._onLoaded)
|
||||||
|
this._onLoaded();
|
||||||
|
}
|
||||||
|
|
||||||
|
async _addInterface(objectPath: string, interfaceName: string) {
|
||||||
|
let info = this._interfaceInfos[interfaceName];
|
||||||
|
|
||||||
|
if (!info)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const proxy = new Gio.DBusProxy({
|
||||||
|
g_connection: this._connection,
|
||||||
|
g_name: this._serviceName,
|
||||||
|
g_object_path: objectPath,
|
||||||
|
g_interface_name: interfaceName,
|
||||||
|
g_interface_info: info,
|
||||||
|
g_flags: Gio.DBusProxyFlags.DO_NOT_AUTO_START,
|
||||||
|
});
|
||||||
|
|
||||||
|
try {
|
||||||
|
await proxy.init_async(GLib.PRIORITY_DEFAULT, this._cancellable);
|
||||||
|
} catch (e: any) {
|
||||||
|
logError(e, `could not initialize proxy for interface ${interfaceName}`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let isNewObject;
|
||||||
|
if (!this._objects[objectPath]) {
|
||||||
|
this._objects[objectPath] = {};
|
||||||
|
isNewObject = true;
|
||||||
|
} else {
|
||||||
|
isNewObject = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
this._objects[objectPath][interfaceName] = proxy;
|
||||||
|
|
||||||
|
if (!this._interfaces[interfaceName])
|
||||||
|
this._interfaces[interfaceName] = [];
|
||||||
|
|
||||||
|
this._interfaces[interfaceName].push(proxy);
|
||||||
|
|
||||||
|
if (isNewObject)
|
||||||
|
this.emit('object-added', objectPath);
|
||||||
|
|
||||||
|
this.emit('interface-added', interfaceName, proxy);
|
||||||
|
}
|
||||||
|
|
||||||
|
_removeInterface(objectPath: string, interfaceName: string) {
|
||||||
|
if (!this._objects[objectPath])
|
||||||
|
return;
|
||||||
|
|
||||||
|
let proxy = this._objects[objectPath][interfaceName];
|
||||||
|
|
||||||
|
if (this._interfaces[interfaceName]) {
|
||||||
|
let index = this._interfaces[interfaceName].indexOf(proxy);
|
||||||
|
|
||||||
|
if (index >= 0)
|
||||||
|
this._interfaces[interfaceName].splice(index, 1);
|
||||||
|
|
||||||
|
if (this._interfaces[interfaceName].length === 0)
|
||||||
|
delete this._interfaces[interfaceName];
|
||||||
|
}
|
||||||
|
|
||||||
|
this.emit('interface-removed', interfaceName, proxy);
|
||||||
|
|
||||||
|
delete this._objects[objectPath][interfaceName];
|
||||||
|
|
||||||
|
if (Object.keys(this._objects[objectPath]).length === 0) {
|
||||||
|
delete this._objects[objectPath];
|
||||||
|
this.emit('object-removed', objectPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async _initManagerProxy() {
|
||||||
|
try {
|
||||||
|
await this._managerProxy.init_async(
|
||||||
|
GLib.PRIORITY_DEFAULT, this._cancellable);
|
||||||
|
} catch (e: any) {
|
||||||
|
logError(e, `could not initialize object manager for object ${this._serviceName}`);
|
||||||
|
|
||||||
|
this._completeLoad();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this._managerProxy.connectSignal('InterfacesAdded',
|
||||||
|
(_objectManager: any, _sender: any, [objectPath, interfaces]: any) => {
|
||||||
|
let interfaceNames = Object.keys(interfaces);
|
||||||
|
for (let i = 0; i < interfaceNames.length; i++)
|
||||||
|
this._addInterface(objectPath, interfaceNames[i]);
|
||||||
|
});
|
||||||
|
this._managerProxy.connectSignal('InterfacesRemoved',
|
||||||
|
(_objectManager: any, _sender: any, [objectPath, interfaceNames]: any) => {
|
||||||
|
for (let i = 0; i < interfaceNames.length; i++)
|
||||||
|
this._removeInterface(objectPath, interfaceNames[i]);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (Object.keys(this._interfaceInfos).length === 0) {
|
||||||
|
this._completeLoad();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this._managerProxy.connect('notify::g-name-owner', () => {
|
||||||
|
if (this._managerProxy.g_name_owner)
|
||||||
|
this._onNameAppeared();
|
||||||
|
else
|
||||||
|
this._onNameVanished();
|
||||||
|
});
|
||||||
|
|
||||||
|
if (this._managerProxy.g_name_owner)
|
||||||
|
this._onNameAppeared().catch(logError);
|
||||||
|
}
|
||||||
|
|
||||||
|
async _onNameAppeared() {
|
||||||
|
try {
|
||||||
|
const [objects] = await this._managerProxy.GetManagedObjectsAsync();
|
||||||
|
|
||||||
|
if (!objects) {
|
||||||
|
this._completeLoad();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const objectPaths = Object.keys(objects);
|
||||||
|
await Promise.allSettled(objectPaths.flatMap(objectPath => {
|
||||||
|
const object = objects[objectPath];
|
||||||
|
const interfaceNames = Object.getOwnPropertyNames(object);
|
||||||
|
return interfaceNames.map(
|
||||||
|
ifaceName => this._addInterface(objectPath, ifaceName));
|
||||||
|
}));
|
||||||
|
} catch (error: any) {
|
||||||
|
logError(error, `could not get remote objects for service ${this._serviceName} path ${this._managerPath}`);
|
||||||
|
} finally {
|
||||||
|
this._completeLoad();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_onNameVanished() {
|
||||||
|
let objectPaths = Object.keys(this._objects);
|
||||||
|
for (let i = 0; i < objectPaths.length; i++) {
|
||||||
|
let objectPath = objectPaths[i];
|
||||||
|
let object = this._objects[objectPath];
|
||||||
|
|
||||||
|
let interfaceNames = Object.keys(object);
|
||||||
|
for (let j = 0; j < interfaceNames.length; j++) {
|
||||||
|
let interfaceName = interfaceNames[j];
|
||||||
|
|
||||||
|
if (object[interfaceName])
|
||||||
|
this._removeInterface(objectPath, interfaceName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_registerInterfaces(interfaces: string | any[]) {
|
||||||
|
for (let i = 0; i < interfaces.length; i++) {
|
||||||
|
let info = Gio.DBusInterfaceInfo.new_for_xml(interfaces[i]);
|
||||||
|
this._interfaceInfos[info.name] = info;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
getProxiesForInterface(interfaceName: string) {
|
||||||
|
let proxyList = this._interfaces[interfaceName];
|
||||||
|
|
||||||
|
if (!proxyList)
|
||||||
|
return [];
|
||||||
|
|
||||||
|
return proxyList;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Signals.addSignalMethods(ObjectManager.prototype);
|
109
src/model/OptionData.ts
Normal file
109
src/model/OptionData.ts
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
|
||||||
|
export class OptionData {
|
||||||
|
tooltip;
|
||||||
|
description;
|
||||||
|
static map: Map<string, OptionData> = new Map();
|
||||||
|
|
||||||
|
constructor(description: string, tooltip: string) {
|
||||||
|
this.tooltip = tooltip;
|
||||||
|
this.description = description;
|
||||||
|
}
|
||||||
|
|
||||||
|
static add(name: string, description: string, tooltip: string) {
|
||||||
|
OptionData.map.set(name, new OptionData(description, tooltip));
|
||||||
|
}
|
||||||
|
|
||||||
|
static description(name: string) {
|
||||||
|
return OptionData.map.get(name)?.description;
|
||||||
|
}
|
||||||
|
|
||||||
|
static tooltip(name: string) {
|
||||||
|
return OptionData.map.get(name)?.tooltip;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
OptionData.add('use-gpu','Use GPU in Realm',
|
||||||
|
|
||||||
|
`If enabled the render node device <tt><b>/dev/dri/renderD128</b></tt> will be mounted into the realm container.
|
||||||
|
|
||||||
|
If privileged device <tt><b>/dev/dri/card0</b></tt> is also needed set
|
||||||
|
additional variable in realm configuration file:
|
||||||
|
|
||||||
|
<tt><b>use-gpu-card0 = true</b></tt>
|
||||||
|
`);
|
||||||
|
|
||||||
|
OptionData.add('use-wayland', 'Use Wayland in Realm',
|
||||||
|
|
||||||
|
`If enabled access to Wayland display will be permitted in realm by adding wayland socket to realm.
|
||||||
|
|
||||||
|
<tt><b>/run/user/1000/wayland-0</b></tt>
|
||||||
|
|
||||||
|
`);
|
||||||
|
|
||||||
|
OptionData.add('use-x11', 'Use X11 in Realm',
|
||||||
|
|
||||||
|
`If enabled access to X11 server will be added by mounting directory X11 directory into realm.
|
||||||
|
|
||||||
|
<tt><b>/tmp/.X11-unix</b></tt>
|
||||||
|
|
||||||
|
`);
|
||||||
|
|
||||||
|
OptionData.add('use-sound', 'Use sound in Realm',
|
||||||
|
|
||||||
|
`If enabled allows use of sound inside of realm. The following items will be added:
|
||||||
|
|
||||||
|
<tt><b>/dev/snd</b></tt>
|
||||||
|
<tt><b>/dev/shm</b></tt>
|
||||||
|
<tt><b>/run/user/1000/pulse</b></tt>
|
||||||
|
|
||||||
|
`);
|
||||||
|
|
||||||
|
OptionData.add('use-shared-dir', 'Mount /Shared directory in Realm',
|
||||||
|
|
||||||
|
`If enabled the shared directory will be mounted as <tt><b>/Shared</b></tt> in home directory of realm.
|
||||||
|
|
||||||
|
This directory is shared between all realms with this option enabled and is an easy way to move files between realms.
|
||||||
|
|
||||||
|
`);
|
||||||
|
|
||||||
|
OptionData.add('use-network', 'Realm has network access',
|
||||||
|
`If enabled the realm will have access to the network.`);
|
||||||
|
|
||||||
|
OptionData.add('use-kvm', 'Use KVM (/dev/kvm) in Realm',
|
||||||
|
`If enabled device <tt><b>/dev/kvm</b></tt> will be added to realm`);
|
||||||
|
|
||||||
|
|
||||||
|
OptionData.add('use-ephemeral-home', 'Use ephemeral tmpfs mount for home directory',
|
||||||
|
|
||||||
|
`If enabled the home directory of realm will be set up in ephemeral mode.
|
||||||
|
|
||||||
|
The ephemeral home directory is set up with the following steps:
|
||||||
|
|
||||||
|
1. Home directory is mounted as tmpfs filesystem
|
||||||
|
2. Any files in <tt><b>/realms/skel</b></tt> are copied into home directory
|
||||||
|
3. Any files in <tt><b>/realms/realm-$name/skel</b></tt> are copied into home directory.
|
||||||
|
4. Any directories listed in config file variable <tt><b>ephemeral_persistent_dirs</b></tt>
|
||||||
|
are bind mounted from <tt><b>/realms/realm-$name/home</b></tt> into ephemeral
|
||||||
|
home directory.
|
||||||
|
|
||||||
|
`);
|
||||||
|
|
||||||
|
OptionData.add('overlay', 'Type of rootfs overlay Realm is configured to use.',
|
||||||
|
`<b><big>Overlay</big></b>
|
||||||
|
Type of rootfs overlay realm is configured to use.
|
||||||
|
<b>None</b> Don't use a rootfs overlay
|
||||||
|
<b>TmpFS</b> Use a rootfs overlay stored on tmpfs
|
||||||
|
<b>Storage</b> Use a rootfs overlay stored on disk in storage partition
|
||||||
|
`);
|
||||||
|
|
||||||
|
OptionData.add('realmfs', 'Root filesystem image to use for Realm.',
|
||||||
|
`<b><big>RealmFS</big></b>
|
||||||
|
Root filesystem image to use for realm.`);
|
||||||
|
|
||||||
|
OptionData.add('colorscheme', 'Terminal Color Scheme',
|
||||||
|
`<b><big>Terminal Color Scheme</big></b>
|
||||||
|
Choose a color scheme to use in the terminals in this realm.`);
|
||||||
|
|
||||||
|
OptionData.add('window-label-color', 'Window Label Color',
|
||||||
|
`<b><big>Window Label Color</big></b>
|
||||||
|
Set a color to be used when a label is drawn on the window titlebar indicating which realm the application is running in.`);
|
129
src/model/Realm.ts
Normal file
129
src/model/Realm.ts
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
import GObject from 'gi://GObject';
|
||||||
|
import Gio from 'gi://Gio';
|
||||||
|
|
||||||
|
import {RealmFS} from './RealmFS.js';
|
||||||
|
import {RealmConfig} from './RealmConfig.js';
|
||||||
|
import {LabelColorManager} from './LabelColors.js';
|
||||||
|
import { RGBA } from 'gi-types/gdk4.js';
|
||||||
|
|
||||||
|
export const RunStatus = {
|
||||||
|
STOPPED: 0,
|
||||||
|
STARTING: 1,
|
||||||
|
RUNNING: 2,
|
||||||
|
CURRENT: 3,
|
||||||
|
STOPPING: 4,
|
||||||
|
};
|
||||||
|
|
||||||
|
export class Realm extends GObject.Object {
|
||||||
|
private _name!: string;
|
||||||
|
private _description!: string;
|
||||||
|
private _pidns!: number;
|
||||||
|
private _run_status!: number;
|
||||||
|
private _is_system_realm!: boolean;
|
||||||
|
private _realmfs!: RealmFS | null;
|
||||||
|
private _labelColors: LabelColorManager;
|
||||||
|
|
||||||
|
static {
|
||||||
|
GObject.registerClass({
|
||||||
|
GTypeName: 'Realm',
|
||||||
|
Properties: {
|
||||||
|
'name': GObject.ParamSpec.string('name', '', '', GObject.ParamFlags.READWRITE, ''),
|
||||||
|
'description': GObject.ParamSpec.string('description', '', '', GObject.ParamFlags.READWRITE, ''),
|
||||||
|
'pidns': GObject.ParamSpec.uint64('pidns', '', '', GObject.ParamFlags.READWRITE,
|
||||||
|
0, Number.MAX_SAFE_INTEGER, 0),
|
||||||
|
'run-status': GObject.ParamSpec.uint('run-status', '', '', GObject.ParamFlags.READWRITE,
|
||||||
|
0, 4, 0),
|
||||||
|
'is-system-realm': GObject.ParamSpec.boolean('is-system-realm', '', '', GObject.ParamFlags.READWRITE, false),
|
||||||
|
'realmfs': GObject.ParamSpec.object('realmfs', '', '', GObject.ParamFlags.READWRITE, RealmFS),
|
||||||
|
},
|
||||||
|
Signals: { 'changed': {}},
|
||||||
|
}, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
_proxy: Gio.DBusProxy;
|
||||||
|
|
||||||
|
config = new RealmConfig();
|
||||||
|
|
||||||
|
|
||||||
|
constructor(proxy: Gio.DBusProxy, labelColors: LabelColorManager) {
|
||||||
|
super();
|
||||||
|
this._proxy = proxy;
|
||||||
|
this._labelColors = labelColors;
|
||||||
|
this._proxy.connect('g-properties-changed', (_proxy, _changed, _invalidated) => {
|
||||||
|
this._sync();
|
||||||
|
});
|
||||||
|
this._sync();
|
||||||
|
}
|
||||||
|
|
||||||
|
get realmfs(): RealmFS | null {
|
||||||
|
return this._realmfs;
|
||||||
|
}
|
||||||
|
|
||||||
|
set realmfs(value: RealmFS | null) {
|
||||||
|
if (this.realmfs === value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this._realmfs = value;
|
||||||
|
this.emit('changed');
|
||||||
|
}
|
||||||
|
|
||||||
|
_sync() {
|
||||||
|
this._name = this._proxy.Name;
|
||||||
|
this._description = this._proxy.Description;
|
||||||
|
this._pidns = this._proxy.PidNS;
|
||||||
|
this._run_status = this._proxy.RunStatus;
|
||||||
|
this._is_system_realm = this._proxy.IsSystemRealm;
|
||||||
|
this.emit('changed');
|
||||||
|
}
|
||||||
|
|
||||||
|
get name() {
|
||||||
|
return this._name;
|
||||||
|
}
|
||||||
|
get description() {
|
||||||
|
return this._description;
|
||||||
|
}
|
||||||
|
|
||||||
|
get pidns() {
|
||||||
|
return this._pidns;
|
||||||
|
}
|
||||||
|
|
||||||
|
get run_status() {
|
||||||
|
return this._run_status;
|
||||||
|
}
|
||||||
|
|
||||||
|
get is_system_realm() {
|
||||||
|
return this._is_system_realm;
|
||||||
|
}
|
||||||
|
|
||||||
|
is_running() {
|
||||||
|
return this.run_status === RunStatus.RUNNING || this.run_status === RunStatus.CURRENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
is_current() {
|
||||||
|
return this.run_status === RunStatus.CURRENT
|
||||||
|
}
|
||||||
|
|
||||||
|
getLabelColor() {
|
||||||
|
return this._labelColors.lookupRealmColor(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
setLabelColor(color: RGBA) {
|
||||||
|
this._labelColors.updateRealmColor(this, color);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
realmfs_index() {
|
||||||
|
return this._proxy.RealmFS
|
||||||
|
}
|
||||||
|
|
||||||
|
set_global_config(config: { [s: string]: string; }) {
|
||||||
|
this.config.set_global_config(config);
|
||||||
|
}
|
||||||
|
|
||||||
|
async load_config() {
|
||||||
|
const result = await this._proxy.GetConfigAsync();
|
||||||
|
this.config.set_config(result[0]);
|
||||||
|
this.emit('changed');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
116
src/model/RealmConfig.ts
Normal file
116
src/model/RealmConfig.ts
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
|
||||||
|
import {OptionData} from './OptionData.js';
|
||||||
|
|
||||||
|
export class BoolOptionData {
|
||||||
|
static ALL_OPTIONS = [
|
||||||
|
'use-gpu',
|
||||||
|
'use-wayland',
|
||||||
|
'use-x11',
|
||||||
|
'use-sound',
|
||||||
|
'use-network',
|
||||||
|
'use-kvm',
|
||||||
|
'use-shared-dir',
|
||||||
|
'use-ephemeral-home',
|
||||||
|
]
|
||||||
|
|
||||||
|
name;
|
||||||
|
description;
|
||||||
|
tooltip;
|
||||||
|
|
||||||
|
constructor(name: string) {
|
||||||
|
this.name = name;
|
||||||
|
this.description = OptionData.description(name) ?? name;
|
||||||
|
this.tooltip = OptionData.tooltip(name) ?? "";
|
||||||
|
}
|
||||||
|
|
||||||
|
static allOptions(): BoolOptionData[] {
|
||||||
|
let options: BoolOptionData[] = [];
|
||||||
|
BoolOptionData.ALL_OPTIONS.forEach(name => {
|
||||||
|
options.push(new BoolOptionData(name));
|
||||||
|
|
||||||
|
})
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class ConfigOption {
|
||||||
|
name;
|
||||||
|
value;
|
||||||
|
defaultValue;
|
||||||
|
description;
|
||||||
|
tooltip;
|
||||||
|
|
||||||
|
constructor(name: string, value: string, defaultValue: string, description: string, tooltip: string) {
|
||||||
|
this.name = name;
|
||||||
|
this.value = value;
|
||||||
|
this.defaultValue = defaultValue;
|
||||||
|
this.description = description;
|
||||||
|
this.tooltip = tooltip;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class RealmConfig {
|
||||||
|
_configVars: { [s: string]: string; } = {};
|
||||||
|
_globalConfig: { [s: string]: string; } = {};
|
||||||
|
|
||||||
|
set_config(config: { [s: string]: string; }) {
|
||||||
|
this._configVars = config;
|
||||||
|
}
|
||||||
|
|
||||||
|
set_global_config(globalConfig: { [s: string]: string; }) {
|
||||||
|
this._globalConfig = globalConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
get_var(name: string) {
|
||||||
|
let value = this._configVars[name];
|
||||||
|
if (value && value.length > 0) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
value = this._globalConfig[name];
|
||||||
|
if (value && value.length > 0) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
get_bool(name: string): boolean {
|
||||||
|
return this.get_var(name) === 'true';
|
||||||
|
}
|
||||||
|
|
||||||
|
get_colorscheme() {
|
||||||
|
return this.get_var('terminal-scheme') ?? 'default-dark';
|
||||||
|
}
|
||||||
|
|
||||||
|
get_realmfs() {
|
||||||
|
return this.get_var('realmfs') ?? 'base';
|
||||||
|
}
|
||||||
|
|
||||||
|
static capitalize(term: string) {
|
||||||
|
const acronyms = ["gpu", "kvm"];
|
||||||
|
if (acronyms.find(s => term === s)) {
|
||||||
|
return term.toUpperCase();
|
||||||
|
} else {
|
||||||
|
return term.charAt(0).toUpperCase() + term.slice(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static option_label(key: string) {
|
||||||
|
return key.substring(4)
|
||||||
|
.split('-')
|
||||||
|
.map(RealmConfig.capitalize)
|
||||||
|
.join('');
|
||||||
|
}
|
||||||
|
|
||||||
|
is_enabled_bool_option(name: string, value: string, isDefault: boolean) {
|
||||||
|
const default_val = this._globalConfig[name];
|
||||||
|
return name.startsWith("use-") && value === "true" && (value === default_val) === isDefault;
|
||||||
|
}
|
||||||
|
|
||||||
|
enabled_bool_option_labels(isDefault: boolean) {
|
||||||
|
return Object.entries(this._configVars)
|
||||||
|
.filter(([k,v]) => this.is_enabled_bool_option(k, v, isDefault))
|
||||||
|
.map(([k,]) => RealmConfig.option_label(k))
|
||||||
|
.sort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
93
src/model/RealmFS.ts
Normal file
93
src/model/RealmFS.ts
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
import GObject from 'gi://GObject';
|
||||||
|
import Gio from 'gi://Gio';
|
||||||
|
|
||||||
|
const OBJECT_PREFIX = "/com/subgraph/Realms2/RealmFS";
|
||||||
|
|
||||||
|
export class RealmFS extends GObject.Object {
|
||||||
|
private _name!: string;
|
||||||
|
private _in_use!: boolean;
|
||||||
|
private _activated!: boolean;
|
||||||
|
private _mountpoint!: string;
|
||||||
|
private _path!: string;
|
||||||
|
private _free_space!: number;
|
||||||
|
private _allocated_space!: number;
|
||||||
|
|
||||||
|
static {
|
||||||
|
GObject.registerClass({
|
||||||
|
GTypeName: 'RealmFS',
|
||||||
|
Properties: {
|
||||||
|
'name': GObject.ParamSpec.string('name', '', '', GObject.ParamFlags.READWRITE, ''),
|
||||||
|
'in-use': GObject.ParamSpec.boolean('in-use', '', '', GObject.ParamFlags.READWRITE, false),
|
||||||
|
'activated': GObject.ParamSpec.boolean('activated', '', '', GObject.ParamFlags.READWRITE, false),
|
||||||
|
'mountpoint': GObject.ParamSpec.string('mountpoint', '', '', GObject.ParamFlags.READWRITE, ''),
|
||||||
|
'path': GObject.ParamSpec.string('path', '', '', GObject.ParamFlags.READWRITE, ''),
|
||||||
|
'free-space': GObject.ParamSpec.uint64('free-space', '', '', GObject.ParamFlags.READWRITE,
|
||||||
|
0, Number.MAX_SAFE_INTEGER, 0),
|
||||||
|
'allocated-space': GObject.ParamSpec.uint64('allocated-space', '', '', GObject.ParamFlags.READWRITE,
|
||||||
|
0, Number.MAX_SAFE_INTEGER, 0),
|
||||||
|
},
|
||||||
|
}, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
_proxy: Gio.DBusProxy;
|
||||||
|
|
||||||
|
constructor(proxy: Gio.DBusProxy) {
|
||||||
|
super();
|
||||||
|
this._proxy = proxy;
|
||||||
|
this._proxy.connect('g-properties-changed', (_proxy, _changed, _invalidated) => {
|
||||||
|
this._sync();
|
||||||
|
});
|
||||||
|
this._sync();
|
||||||
|
}
|
||||||
|
|
||||||
|
index() {
|
||||||
|
let path = this._proxy.get_object_path();
|
||||||
|
if (path.startsWith(OBJECT_PREFIX)) {
|
||||||
|
const tail = path.substring(OBJECT_PREFIX.length);
|
||||||
|
let index = Number.parseInt(tail);
|
||||||
|
if (!Number.isNaN(index)) {
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
get name() {
|
||||||
|
return this._name;
|
||||||
|
}
|
||||||
|
|
||||||
|
get in_use() {
|
||||||
|
return this._in_use;
|
||||||
|
}
|
||||||
|
|
||||||
|
get activated() {
|
||||||
|
return this._activated;
|
||||||
|
}
|
||||||
|
|
||||||
|
get mountpoint() {
|
||||||
|
return this._mountpoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
get path() {
|
||||||
|
return this._path;
|
||||||
|
}
|
||||||
|
|
||||||
|
get free_space() {
|
||||||
|
return this._free_space;
|
||||||
|
}
|
||||||
|
|
||||||
|
get allocated_space() {
|
||||||
|
return this._allocated_space;
|
||||||
|
}
|
||||||
|
|
||||||
|
_sync() {
|
||||||
|
this._name = this._proxy.Name;
|
||||||
|
this._in_use = this._proxy.InUse;
|
||||||
|
this._activated = this._proxy.Activated;
|
||||||
|
this._mountpoint = this._proxy.Mountpoint;
|
||||||
|
this._path = this._proxy.Path;
|
||||||
|
this._free_space = this._proxy.FreeSpace;
|
||||||
|
this._allocated_space = this._proxy.AllocatedSpace;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
171
src/model/RealmManager.ts
Normal file
171
src/model/RealmManager.ts
Normal file
@ -0,0 +1,171 @@
|
|||||||
|
import Gio from 'gi://Gio';
|
||||||
|
|
||||||
|
import {ObjectManager} from './ObjectManager.js';
|
||||||
|
import {loadInterfaceXML} from './Utils.js'
|
||||||
|
import {Realm} from './Realm.js';
|
||||||
|
import {RealmFS} from './RealmFS.js';
|
||||||
|
import {LabelColorManager} from './LabelColors.js';
|
||||||
|
|
||||||
|
import type {SignalMethods} from 'gjs';
|
||||||
|
|
||||||
|
const Signals = imports.signals;
|
||||||
|
|
||||||
|
const RealmIface = loadInterfaceXML("com.subgraph.realms.Realm");
|
||||||
|
const RealmFSIface = loadInterfaceXML("com.subgraph.realms.RealmFS");
|
||||||
|
|
||||||
|
const BUS_NAME = 'com.subgraph.Realms2';
|
||||||
|
const OBJECT_PATH = '/com/subgraph/Realms2';
|
||||||
|
const ManagerInterface = loadInterfaceXML("com.subgraph.realms.Manager2");
|
||||||
|
const ManagerProxy = Gio.DBusProxy.makeProxyWrapper(ManagerInterface);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
export interface RealmManager extends SignalMethods {};
|
||||||
|
|
||||||
|
export class RealmManager {
|
||||||
|
|
||||||
|
_globalConfig: { [s: string]: string; } = {};
|
||||||
|
_realms: { [s: string]: Realm; } = {};
|
||||||
|
_realmfs: { [s: string]: RealmFS; } = {};
|
||||||
|
|
||||||
|
static INSTANCE = new RealmManager();
|
||||||
|
private _objectManager: ObjectManager;
|
||||||
|
private _labelColors: LabelColorManager;
|
||||||
|
private _proxy: Gio.DBusProxy;
|
||||||
|
|
||||||
|
|
||||||
|
static instance(): RealmManager {
|
||||||
|
return RealmManager.INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this._realmfs = {};
|
||||||
|
|
||||||
|
this._objectManager = new ObjectManager({
|
||||||
|
connection: Gio.DBus.system,
|
||||||
|
name: 'com.subgraph.Realms2',
|
||||||
|
objectPath: '/com/subgraph/Realms2',
|
||||||
|
knownInterfaces: [RealmIface, RealmFSIface],
|
||||||
|
onLoaded: this._onLoaded.bind(this),
|
||||||
|
});
|
||||||
|
this._proxy = new ManagerProxy(Gio.DBus.system, BUS_NAME, OBJECT_PATH,
|
||||||
|
(_proxy: any, error: any) => {
|
||||||
|
if(error) {
|
||||||
|
logError(error);
|
||||||
|
} else {
|
||||||
|
this._setGlobalConfig().catch(logError);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this._labelColors = new LabelColorManager();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async _setGlobalConfig() {
|
||||||
|
let result = await this._proxy.GetGlobalConfigAsync();
|
||||||
|
this._globalConfig = result[0];
|
||||||
|
this._assignGlobalConfigToRealms();
|
||||||
|
}
|
||||||
|
|
||||||
|
async _onLoaded() {
|
||||||
|
let realms = this._objectManager.getProxiesForInterface('com.subgraph.realms.Realm');
|
||||||
|
for (let i = 0; i < realms.length; i++) {
|
||||||
|
this._addRealm(realms[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
let realmfs = this._objectManager.getProxiesForInterface('com.subgraph.realms.RealmFS');
|
||||||
|
for (let i = 0; i < realmfs.length; i++) {
|
||||||
|
this._addRealmFS(realmfs[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
this._objectManager.connect('interface-added', (_objectManager, interfaceName, proxy) => {
|
||||||
|
if (interfaceName === 'com.subgraph.Realm') {
|
||||||
|
this._addRealm(proxy);
|
||||||
|
} else if (interfaceName === 'com.subgraph.RealmFS') {
|
||||||
|
this._addRealmFS(proxy);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this._objectManager.connect('interface-removed', (_objectManager, interfaceName, proxy) => {
|
||||||
|
if (interfaceName === 'com.subgraph.Realm') {
|
||||||
|
this._removeRealm(proxy);
|
||||||
|
} else if (interfaceName === 'com.subgraph.RealmFS') {
|
||||||
|
this._removeRealmFS(proxy);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async _addRealm(proxy: Gio.DBusProxy) {
|
||||||
|
let objectPath = proxy.get_object_path();
|
||||||
|
let realm = new Realm(proxy, this._labelColors);
|
||||||
|
this._realms[objectPath] = realm;
|
||||||
|
this._findRealmFSForRealm(realm);
|
||||||
|
if (this._globalConfig) {
|
||||||
|
realm.set_global_config(this._globalConfig);
|
||||||
|
}
|
||||||
|
await realm.load_config();
|
||||||
|
this.emit('realm-added', realm);
|
||||||
|
}
|
||||||
|
|
||||||
|
_removeRealm(proxy: Gio.DBusProxy) {
|
||||||
|
let objectPath = proxy.get_object_path();
|
||||||
|
if (this._realms[objectPath]?._proxy === proxy) {
|
||||||
|
let realm = this._realms[objectPath];
|
||||||
|
delete this._realms[objectPath];
|
||||||
|
this.emit('realm-removed', realm);
|
||||||
|
}
|
||||||
|
proxy.disconnectAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
_addRealmFS(proxy: Gio.DBusProxy) {
|
||||||
|
let objectPath = proxy.get_object_path();
|
||||||
|
let realmfs = new RealmFS(proxy);
|
||||||
|
this._realmfs[objectPath] = realmfs;
|
||||||
|
this._assignRealmFSToRealms(realmfs);
|
||||||
|
this.emit('realmfs-added', realmfs);
|
||||||
|
}
|
||||||
|
|
||||||
|
_findRealmFSForRealm(realm: Realm) {
|
||||||
|
if (realm.realmfs_index() > 0) {
|
||||||
|
realm.realmfs = Object.values(this._realmfs)
|
||||||
|
.find(realmfs => realmfs.index() === realm.realmfs_index()) ?? null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
realmfsList() {
|
||||||
|
return Object.values(this._realmfs);
|
||||||
|
}
|
||||||
|
|
||||||
|
_assignRealmFSToRealms(realmfs: RealmFS) {
|
||||||
|
Object.values(this._realms).forEach(r => {
|
||||||
|
if (r.realmfs_index() > 0 && r.realmfs_index() === realmfs.index() && r.realmfs != realmfs) {
|
||||||
|
r.realmfs = realmfs;
|
||||||
|
}
|
||||||
|
}) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
_assignGlobalConfigToRealms() {
|
||||||
|
Object.values(this._realms).forEach(r => r.set_global_config(this._globalConfig));
|
||||||
|
}
|
||||||
|
|
||||||
|
_removeRealmFSFromRealms(realmfs: RealmFS) {
|
||||||
|
Object.values(this._realms).forEach(r => {
|
||||||
|
if (r.realmfs === realmfs) {
|
||||||
|
r.realmfs = null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
_removeRealmFS(proxy: Gio.DBusProxy) {
|
||||||
|
let objectPath = proxy.get_object_path();
|
||||||
|
if (this._realmfs[objectPath]?._proxy === proxy) {
|
||||||
|
let realmfs = this._realmfs[objectPath];
|
||||||
|
delete this._realmfs[objectPath];
|
||||||
|
this._removeRealmFSFromRealms(realmfs);
|
||||||
|
this.emit('realmfs-removed', realmfs);
|
||||||
|
}
|
||||||
|
proxy.disconnectAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Signals.addSignalMethods(RealmManager.prototype);
|
17
src/model/Utils.ts
Normal file
17
src/model/Utils.ts
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import Gio from 'gi://Gio';
|
||||||
|
|
||||||
|
export function loadInterfaceXML(iface: string): string | null {
|
||||||
|
|
||||||
|
let uri = `resource:///com/subgraph/citadel/Realms/dbus-interfaces/${iface}.xml`;
|
||||||
|
let f = Gio.File.new_for_uri(uri);
|
||||||
|
|
||||||
|
try {
|
||||||
|
let [_ok, bytes] = f.load_contents(null);
|
||||||
|
// @ts-ignore
|
||||||
|
return new TextDecoder().decode(bytes);
|
||||||
|
} catch (e) {
|
||||||
|
log(`Failed to load D-Bus interface ${iface}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
9
subprojects/blueprint-compiler.wrap
Normal file
9
subprojects/blueprint-compiler.wrap
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
[wrap-git]
|
||||||
|
directory = blueprint-compiler
|
||||||
|
url = https://gitlab.gnome.org/jwestman/blueprint-compiler.git
|
||||||
|
revision = main
|
||||||
|
depth = 1
|
||||||
|
|
||||||
|
[provide]
|
||||||
|
program_names = blueprint-compiler
|
||||||
|
|
40
tsconfig.json
Normal file
40
tsconfig.json
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"strictNullChecks": true,
|
||||||
|
"noImplicitReturns": true,
|
||||||
|
"noImplicitAny": true,
|
||||||
|
"noUnusedParameters": true,
|
||||||
|
"experimentalDecorators": true,
|
||||||
|
"strict": true,
|
||||||
|
|
||||||
|
"paths": {
|
||||||
|
"*": [
|
||||||
|
"*",
|
||||||
|
"types/*",
|
||||||
|
"gi-types/*"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"target": "ES2018",
|
||||||
|
"baseUrl": ".",
|
||||||
|
"moduleResolution": "node",
|
||||||
|
"module": "ES2020",
|
||||||
|
"outDir": "js",
|
||||||
|
"lib": [
|
||||||
|
"es2020"
|
||||||
|
],
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"typeRoots": [
|
||||||
|
"types",
|
||||||
|
"gi-types",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"include": [
|
||||||
|
"gi-types/gi.d.ts",
|
||||||
|
"types/ambient.d.ts",
|
||||||
|
"types/gjs.d.ts",
|
||||||
|
"src/**/*",
|
||||||
|
],
|
||||||
|
"exclude": [
|
||||||
|
"node_modules/@types/**",
|
||||||
|
],
|
||||||
|
}
|
32
types/ambient.d.ts
vendored
Normal file
32
types/ambient.d.ts
vendored
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
declare function _(id: string): string;
|
||||||
|
declare function print(args: string): void;
|
||||||
|
declare function log(obj: object, others?: object[]): void;
|
||||||
|
declare function log(msg: string, subsitutions?: any[]): void;
|
||||||
|
|
||||||
|
declare const pkg: {
|
||||||
|
version: string;
|
||||||
|
name: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
declare module console {
|
||||||
|
export function error(obj: object, others?: object[]): void;
|
||||||
|
export function error(msg: string, subsitutions?: any[]): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
declare class TextDecoder {
|
||||||
|
constructor(format: string);
|
||||||
|
decode(buffer: ArrayBuffer): string;
|
||||||
|
}
|
||||||
|
declare class TextEncoder {
|
||||||
|
constructor();
|
||||||
|
encode(str: string): Uint8Array;
|
||||||
|
}
|
||||||
|
|
||||||
|
declare interface String {
|
||||||
|
format(...replacements: string[]): string;
|
||||||
|
format(...replacements: number[]): string;
|
||||||
|
}
|
||||||
|
declare interface Number {
|
||||||
|
toFixed(digits: number): number;
|
||||||
|
}
|
||||||
|
|
35
types/gettext.d.ts
vendored
Normal file
35
types/gettext.d.ts
vendored
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
export namespace Gettext {
|
||||||
|
export enum LocaleCategory {
|
||||||
|
CTYPE = 0,
|
||||||
|
NUMERIC = 1,
|
||||||
|
TIME = 2,
|
||||||
|
COLLATE = 3,
|
||||||
|
MONETARY = 4,
|
||||||
|
MESSAGES = 5,
|
||||||
|
ALL = 6,
|
||||||
|
}
|
||||||
|
|
||||||
|
export function setlocale(category: LocaleCategory, locale: string | null): string | null;
|
||||||
|
export function textdomain(domainName: string): void;
|
||||||
|
export function bindtextdomain(domainName: string, dirName: string): void;
|
||||||
|
|
||||||
|
export function gettext(msgid: string): string;
|
||||||
|
export function dgettext(domainName: string | null, msgid: string): string;
|
||||||
|
export function dcgettext(domainName: string | null, msgid: string, category: LocaleCategory): string;
|
||||||
|
|
||||||
|
export function ngettext(msgid1: string, msgid2: string, n: number): string;
|
||||||
|
export function dngettext(domainName: string | null, msgid1: string, msgid2: string, n: number): string;
|
||||||
|
|
||||||
|
export function pgettext(context: string | null, msgid: string): string;
|
||||||
|
export function dpgettext(domainName: string | null, context: string | null, msgid: string): string;
|
||||||
|
|
||||||
|
export class GettextObject {
|
||||||
|
gettext(msgid: string): string;
|
||||||
|
ngettext(msgid1: string, msgid2: string, n: number): string;
|
||||||
|
pgettext(context: string | null, msgid: string): string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function domain(domainName: string | null): GettextObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Gettext;
|
183
types/gjs.d.ts
vendored
Normal file
183
types/gjs.d.ts
vendored
Normal file
@ -0,0 +1,183 @@
|
|||||||
|
/**
|
||||||
|
* Type Definitions for Gjs (https://gjs.guide/)
|
||||||
|
*
|
||||||
|
* These type definitions are automatically generated, do not edit them by hand.
|
||||||
|
* If you found a bug fix it in ts-for-gir itself or create a bug report on https://github.com/gjsify/ts-for-gir
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
import type GObject from '@girs/gobject-2.0';
|
||||||
|
import type GLib from '@girs/glib-2.0';
|
||||||
|
|
||||||
|
import gettext from './gettext.js';
|
||||||
|
import system from './system.js';
|
||||||
|
import cairo from './cairo.js';
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* You can use the `Signals.addSignalMethods` method to apply the `Signals` convenience methods to an `Object`.
|
||||||
|
* Generally, this is called on an object prototype, but may also be called on an object instance.
|
||||||
|
* You can use this Interface for this object or prototype to make the methods in typescript known
|
||||||
|
* @example
|
||||||
|
* ```ts
|
||||||
|
* const Signals = imports.signals;
|
||||||
|
*
|
||||||
|
* // Define an interface with the same name of your class to make the methods known
|
||||||
|
* interface Events extends Signals.Methods {}
|
||||||
|
*
|
||||||
|
* class Events {}
|
||||||
|
* Signals.addSignalMethods(Events.prototype);
|
||||||
|
*
|
||||||
|
* const events = new Events();
|
||||||
|
*
|
||||||
|
* // Typescript will not complain here
|
||||||
|
* events.emit("test-signal", "test argument");
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
export interface SignalMethods {
|
||||||
|
/**
|
||||||
|
* Connects a callback to a signal for an object. Pass the returned ID to
|
||||||
|
* `disconnect()` to remove the handler.
|
||||||
|
*
|
||||||
|
* If `callback` returns `true`, emission will stop and no other handlers will be
|
||||||
|
* invoked.
|
||||||
|
*
|
||||||
|
* > Warning: Unlike GObject signals, `this` within a signal callback will always
|
||||||
|
* > refer to the global object (ie. `globalThis`).
|
||||||
|
*
|
||||||
|
* @param sigName A signal name
|
||||||
|
* @param callback A callback function
|
||||||
|
* @returns A handler ID
|
||||||
|
*/
|
||||||
|
connect(sigName: string, callback: (self: any, ...args: any[]) => void): number;
|
||||||
|
/**
|
||||||
|
* Emits a signal for an object. Emission stops if a signal handler returns `true`.
|
||||||
|
*
|
||||||
|
* Unlike GObject signals, it is not necessary to declare signals or define their
|
||||||
|
* signature. Simply call `emit()` with whatever signal name you wish, with
|
||||||
|
* whatever arguments you wish.
|
||||||
|
* @param sigName A signal name
|
||||||
|
* @param args Any number of arguments, of any type
|
||||||
|
*/
|
||||||
|
emit(sigName: string, ...args: any[]): void;
|
||||||
|
/**
|
||||||
|
* Disconnects a handler for a signal.
|
||||||
|
* @param id The ID of the handler to be disconnected
|
||||||
|
*/
|
||||||
|
disconnect(id: number): void;
|
||||||
|
/**
|
||||||
|
* Disconnects all signal handlers for an object.
|
||||||
|
*/
|
||||||
|
disconnectAll(): void;
|
||||||
|
/**
|
||||||
|
* Checks if a handler ID is connected.
|
||||||
|
* @param id The ID of the handler to be disconnected
|
||||||
|
* @returns `true` if connected, or `false` if not
|
||||||
|
*/
|
||||||
|
signalHandlerIsConnected(id: number): boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
declare namespace signals {
|
||||||
|
interface Methods {
|
||||||
|
/**
|
||||||
|
* Connects a callback to a signal for an object. Pass the returned ID to
|
||||||
|
* `disconnect()` to remove the handler.
|
||||||
|
*
|
||||||
|
* If `callback` returns `true`, emission will stop and no other handlers will be
|
||||||
|
* invoked.
|
||||||
|
*
|
||||||
|
* > Warning: Unlike GObject signals, `this` within a signal callback will always
|
||||||
|
* > refer to the global object (ie. `globalThis`).
|
||||||
|
*
|
||||||
|
* @param sigName A signal name
|
||||||
|
* @param callback A callback function
|
||||||
|
* @returns A handler ID
|
||||||
|
*/
|
||||||
|
connect(sigName: string, callback: (self: any, ...args: any[]) => void): number;
|
||||||
|
/**
|
||||||
|
* Emits a signal for an object. Emission stops if a signal handler returns `true`.
|
||||||
|
*
|
||||||
|
* Unlike GObject signals, it is not necessary to declare signals or define their
|
||||||
|
* signature. Simply call `emit()` with whatever signal name you wish, with
|
||||||
|
* whatever arguments you wish.
|
||||||
|
* @param sigName A signal name
|
||||||
|
* @param args Any number of arguments, of any type
|
||||||
|
*/
|
||||||
|
emit(sigName: string, ...args: any[]): void;
|
||||||
|
/**
|
||||||
|
* Disconnects a handler for a signal.
|
||||||
|
* @param id The ID of the handler to be disconnected
|
||||||
|
*/
|
||||||
|
disconnect(id: number): void;
|
||||||
|
/**
|
||||||
|
* Disconnects all signal handlers for an object.
|
||||||
|
*/
|
||||||
|
disconnectAll(): void;
|
||||||
|
/**
|
||||||
|
* Checks if a handler ID is connected.
|
||||||
|
* @param id The ID of the handler to be disconnected
|
||||||
|
* @returns `true` if connected, or `false` if not
|
||||||
|
*/
|
||||||
|
signalHandlerIsConnected(id: number): boolean;
|
||||||
|
}
|
||||||
|
export function addSignalMethods<T = any>(proto: T): proto is T & Methods;
|
||||||
|
}
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface GjsGiImports {
|
||||||
|
// Will be extended by the import of more gir types
|
||||||
|
versions: {
|
||||||
|
[namespace: string]: string;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
interface GjsImports {
|
||||||
|
gi: GjsGiImports;
|
||||||
|
signals: typeof signals;
|
||||||
|
searchPath: string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run `pkg.initGettext()` before using this.
|
||||||
|
* Currently not implemented.
|
||||||
|
*/
|
||||||
|
const N_: undefined | ((x: string) => string);
|
||||||
|
|
||||||
|
function print(...args: any[]): void;
|
||||||
|
function printerr(...args: any[]): void;
|
||||||
|
function log(obj: object, others?: object[]): void;
|
||||||
|
function log(msg: string, substitutions?: any[]): void;
|
||||||
|
function logError(exception: object, message?: any): void;
|
||||||
|
function logError(message?: any): void;
|
||||||
|
|
||||||
|
interface BooleanConstructor {
|
||||||
|
$gtype: GObject.GType<boolean>;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface NumberConstructor {
|
||||||
|
$gtype: GObject.GType<number>;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface StringConstructor {
|
||||||
|
$gtype: GObject.GType<string>;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface StringConstructor {
|
||||||
|
$gtype: GObject.GType<string>;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ObjectConstructor {
|
||||||
|
$gtype: GObject.GType<Object>;
|
||||||
|
}
|
||||||
|
|
||||||
|
const imports: GjsImports;
|
||||||
|
|
||||||
|
const ARGV: string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
declare const _imports: GjsImports;
|
||||||
|
export default _imports;
|
||||||
|
export { _imports as imports };
|
6
types/gjs.js
Normal file
6
types/gjs.js
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
const imports = globalThis.imports || {};
|
||||||
|
|
||||||
|
export { imports }
|
||||||
|
export default imports;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user