mirror of
https://github.com/Theaninova/TheaninovOS.git
synced 2026-01-07 16:22:50 +00:00
ags steal
This commit is contained in:
245
desktops/hyprland/ags/modules/lib/actioncenter.js
Normal file
245
desktops/hyprland/ags/modules/lib/actioncenter.js
Normal file
@@ -0,0 +1,245 @@
|
||||
// Not yet used. For cool drag and drop stuff. Thanks DevAlien
|
||||
|
||||
const Toggles = {};
|
||||
Toggles.Wifi = NetworkToggle;
|
||||
Toggles.Bluetooth = BluetoothToggle;
|
||||
Toggles.DND = DNDToggle;
|
||||
Toggles.ThemeToggle = ThemeToggle;
|
||||
Toggles.ProfileToggle = ProfileToggle;
|
||||
// Toggles.Record = RecordToggle;
|
||||
// Toggles.Airplane = AirplaneToggle;
|
||||
// Toggles.DoNotDisturb = DoNotDisturbToggle;
|
||||
const TARGET = [Gtk.TargetEntry.new("text/plain", Gtk.TargetFlags.SAME_APP, 0)];
|
||||
|
||||
export class ActionCenter extends Gtk.Box {
|
||||
static {
|
||||
GObject.registerClass({
|
||||
GTypeName: 'ActionCenter',
|
||||
Properties: {
|
||||
|
||||
},
|
||||
}, this);
|
||||
}
|
||||
|
||||
constructor({ className = "ActionCenter", toggles, ...rest }) {
|
||||
super(rest);
|
||||
this.toggles = Toggles
|
||||
this.currentToggles = Settings.getSetting("toggles", []);
|
||||
this.mainFlowBox = this._setupFlowBox(className + QSView.editing && className + "Editing");
|
||||
this.mainFlowBox.connect("drag_motion", this._dragMotionMain);
|
||||
this.mainFlowBox.connect("drag_drop", this._dragDropMain);
|
||||
this._dragged = {};
|
||||
this._draggedExtra = {};
|
||||
|
||||
this._dragged;
|
||||
this._currentPosition = 0;
|
||||
this._orderedState;
|
||||
this._draggedName;
|
||||
|
||||
this.updateList(toggles, this.mainFlowBox)
|
||||
|
||||
this.set_orientation(Gtk.Orientation.VERTICAL);
|
||||
this.add(this.mainFlowBox)
|
||||
this.mainFlowBox.set_size_request(1, 30)
|
||||
if (QSView.editing) {
|
||||
this.extraFlowBox = this._setupFlowBox(className);
|
||||
this.extraFlowBox.connect("drag_motion", this._dragMotionExtra);
|
||||
this.extraFlowBox.connect("drag_drop", this._dragDropExtra);
|
||||
this.updateList(this._getExtraToggles(), this.extraFlowBox)
|
||||
this.add(Box({
|
||||
vertical: true,
|
||||
children: [
|
||||
Label("Extra widgets"),
|
||||
Label("Drop here to remove or drag from here to add"),
|
||||
this.extraFlowBox
|
||||
]
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
_getExtraToggles() {
|
||||
let toggles = { ...this.toggles }
|
||||
this.currentToggles.map(t => {
|
||||
if (toggles[t]) {
|
||||
delete toggles[t];
|
||||
}
|
||||
});
|
||||
return Object.keys(toggles);
|
||||
}
|
||||
|
||||
_setupFlowBox(className) {
|
||||
const flowBox = new Gtk.FlowBox();
|
||||
flowBox.set_valign(Gtk.Align.FILL);
|
||||
flowBox.set_min_children_per_line(2);
|
||||
flowBox.set_max_children_per_line(2);
|
||||
flowBox.set_selection_mode(Gtk.SelectionMode.NONE);
|
||||
flowBox.get_style_context().add_class(className);
|
||||
flowBox.set_homogeneous(true);
|
||||
flowBox.drag_dest_set(Gtk.DestDefaults.ALL, TARGET, Gdk.DragAction.COPY);
|
||||
|
||||
return flowBox;
|
||||
}
|
||||
|
||||
createWidget = (name, index, type) => {
|
||||
const editSetup = (widget) => {
|
||||
widget.drag_source_set(
|
||||
Gdk.ModifierType.BUTTON1_MASK,
|
||||
TARGET,
|
||||
Gdk.DragAction.COPY
|
||||
);
|
||||
|
||||
widget.connect("drag-begin", (w, context) => {
|
||||
const widgetContainer = widget.get_parent();
|
||||
|
||||
Gtk.drag_set_icon_surface(context, createSurfaceFromWidget(widgetContainer));
|
||||
this._dragged = {
|
||||
widget: widgetContainer.get_parent().get_parent(),
|
||||
container: widgetContainer,
|
||||
name: name,
|
||||
currentPosition: type === "Main" ? index : null,
|
||||
currentPositionExtra: type === "Extra" ? index : null,
|
||||
from: type,
|
||||
}
|
||||
widgetContainer.get_style_context().add_class("hidden");
|
||||
if (type !== "Main") {
|
||||
this.extraFlowBox.remove(this._dragged.widget);
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
});
|
||||
widget.connect("drag-failed", () => {
|
||||
this.updateList(Settings.getSetting("toggles"), this.mainFlowBox)
|
||||
this.updateList(this._getExtraToggles(), this.extraFlowBox)
|
||||
});
|
||||
}
|
||||
|
||||
let row = new Gtk.FlowBoxChild({ visible: true });
|
||||
row.add(Toggles[name]({ setup: QSView.editing && editSetup, QSView: QSView }));
|
||||
row._index = index;
|
||||
row._name = name;
|
||||
return row;
|
||||
}
|
||||
|
||||
updateList(toggles, flowBox) {
|
||||
let type = flowBox === this.mainFlowBox ? "Main" : "Extra"
|
||||
var childrenBox = flowBox.get_children();
|
||||
childrenBox.forEach((element) => {
|
||||
flowBox.remove(element);
|
||||
element.destroy();
|
||||
});
|
||||
|
||||
if (!toggles) return;
|
||||
|
||||
toggles.forEach((name, i) => {
|
||||
if (Toggles[name])
|
||||
flowBox.add(this.createWidget(name, i, type));
|
||||
});
|
||||
flowBox.show_all();
|
||||
}
|
||||
|
||||
|
||||
_dragMotionMain = (widget, context, x, y, time) => {
|
||||
if (this._dragged.currentPositionExtra !== null) {
|
||||
this._dragged.currentPositionExtra = null;
|
||||
if (this._isChild(this.extraFlowBox, this._dragged.widget)) {
|
||||
this.extraFlowBox.remove(this._dragged.widget);
|
||||
}
|
||||
}
|
||||
const children = this.mainFlowBox.get_children();
|
||||
const sampleItem = children[0];
|
||||
const sampleWidth = sampleItem.get_allocation().width;
|
||||
const sampleHeight = sampleItem.get_allocated_height();
|
||||
const perLine = Math.floor(this.mainFlowBox.get_allocation().width / sampleWidth);
|
||||
const pos = Math.floor(y / sampleHeight) * perLine + Math.floor(x / sampleWidth);
|
||||
if (pos >= children.length && pos !== 0) return false;
|
||||
|
||||
if (this._dragged.currentPosition === null) {
|
||||
this.mainFlowBox.insert(this._dragged.widget, pos);
|
||||
|
||||
this._dragged.currentPosition = pos;
|
||||
} else if (this._dragged.currentPosition !== pos) {
|
||||
if (this._isChild(this.mainFlowBox, this._dragged.widget)) {
|
||||
this.mainFlowBox.remove(this._dragged.widget);
|
||||
}
|
||||
|
||||
this.mainFlowBox.insert(this._dragged.widget, pos);
|
||||
|
||||
this._dragged.currentPosition = pos;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
_dragDropMain = () => {
|
||||
if (this._dragged.from !== "Main") {
|
||||
this.currentToggles.splice(this._dragged.currentPosition, 0, this._dragged.name);
|
||||
} else {
|
||||
const indexCurrentToggle = this.currentToggles.indexOf(this._dragged.name);
|
||||
this.currentToggles.splice(indexCurrentToggle, 1);
|
||||
this.currentToggles.splice(this._dragged.currentPosition, 0, this._dragged.name);
|
||||
}
|
||||
|
||||
Settings.setSetting("toggles", this.currentToggles);
|
||||
this._dragged.container.get_style_context().remove_class("hidden");
|
||||
return true;
|
||||
}
|
||||
|
||||
_dragDropExtra = () => {
|
||||
if (this._dragged.from === "Main") {
|
||||
const indexCurrentToggle = this.currentToggles.indexOf(this._dragged.name);
|
||||
this.currentToggles.splice(indexCurrentToggle, 1);
|
||||
}
|
||||
|
||||
Settings.setSetting("toggles", this.currentToggles);
|
||||
this._dragged.container.get_style_context().remove_class("hidden");
|
||||
return true;
|
||||
}
|
||||
|
||||
_dragMotionExtra = (widget, context, x, y, time) => {
|
||||
if (this._dragged.currentPosition !== null) {
|
||||
this._dragged.currentPosition = null;
|
||||
if (this._isChild(this.mainFlowBox, this._dragged.widget)) {
|
||||
this.mainFlowBox.remove(this._dragged.widget);
|
||||
}
|
||||
}
|
||||
|
||||
const children = this.extraFlowBox.get_children();
|
||||
const sampleItem = children[0];
|
||||
let pos = 0;
|
||||
if (sampleItem) {
|
||||
const sampleWidth = sampleItem.get_allocation().width;
|
||||
const sampleHeight = sampleItem.get_allocated_height();
|
||||
const perLine = Math.floor(this.extraFlowBox.get_allocation().width / sampleWidth);
|
||||
pos = Math.floor(y / sampleHeight) * perLine + Math.floor(x / sampleWidth);
|
||||
}
|
||||
|
||||
if (pos >= children.length && pos !== 0) return false;
|
||||
|
||||
if (this._dragged.currentPositionExtra === null) {
|
||||
this.extraFlowBox.insert(this._dragged.widget, pos);
|
||||
|
||||
this._dragged.currentPositionExtra = pos;
|
||||
}
|
||||
|
||||
if (this._dragged.currentPositionExtra !== pos) {
|
||||
if (this._isChild(this.extraFlowBox, this._dragged.widget)) {
|
||||
this.extraFlowBox.remove(this._dragged.widget);
|
||||
}
|
||||
|
||||
this.extraFlowBox.insert(this._dragged.widget, pos);
|
||||
|
||||
this._dragged.currentPositionExtra = pos;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
_isChild(container, widget) {
|
||||
let found = false;
|
||||
container.get_children().forEach((c) => {
|
||||
if (c === widget) found = true;
|
||||
})
|
||||
return found;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
const { Gdk, Gtk } = imports.gi;
|
||||
const GObject = imports.gi.GObject;
|
||||
const Lang = imports.lang;
|
||||
import { Utils, Widget } from '../../imports.js';
|
||||
|
||||
// min-height for diameter
|
||||
// min-width for trough stroke
|
||||
// padding for space between trough and progress
|
||||
// margin for space between widget and parent
|
||||
// background-color for trough color
|
||||
// color for progress color
|
||||
// font size for progress value (0-100px) (hacky i know, but i want animations)
|
||||
// TODO: border-radius for rounded ends maybe (unimportant)
|
||||
export const AnimatedCircProg = (props) => Widget({
|
||||
...props,
|
||||
type: Gtk.DrawingArea,
|
||||
setup: (area) => {
|
||||
const styleContext = area.get_style_context();
|
||||
const width = styleContext.get_property('min-height', Gtk.StateFlags.NORMAL);
|
||||
const height = styleContext.get_property('min-height', Gtk.StateFlags.NORMAL);
|
||||
const padding = styleContext.get_padding(Gtk.StateFlags.NORMAL).left;
|
||||
const marginLeft = styleContext.get_margin(Gtk.StateFlags.NORMAL).left;
|
||||
const marginRight = styleContext.get_margin(Gtk.StateFlags.NORMAL).right;
|
||||
const marginTop = styleContext.get_margin(Gtk.StateFlags.NORMAL).top;
|
||||
const marginBottom = styleContext.get_margin(Gtk.StateFlags.NORMAL).bottom;
|
||||
area.set_size_request(width + marginLeft + marginRight, height + marginTop + marginBottom);
|
||||
area.connect('draw', Lang.bind(area, (area, cr) => {
|
||||
const styleContext = area.get_style_context();
|
||||
const width = styleContext.get_property('min-height', Gtk.StateFlags.NORMAL);
|
||||
const height = styleContext.get_property('min-height', Gtk.StateFlags.NORMAL);
|
||||
const padding = styleContext.get_padding(Gtk.StateFlags.NORMAL).left;
|
||||
const marginLeft = styleContext.get_margin(Gtk.StateFlags.NORMAL).left;
|
||||
const marginRight = styleContext.get_margin(Gtk.StateFlags.NORMAL).right;
|
||||
const marginTop = styleContext.get_margin(Gtk.StateFlags.NORMAL).top;
|
||||
const marginBottom = styleContext.get_margin(Gtk.StateFlags.NORMAL).bottom;
|
||||
area.set_size_request(width + marginLeft + marginRight, height + marginTop + marginBottom);
|
||||
|
||||
const progressValue = styleContext.get_property('font-size', Gtk.StateFlags.NORMAL) / 100.0;
|
||||
|
||||
const bg_stroke = styleContext.get_property('min-width', Gtk.StateFlags.NORMAL);
|
||||
const fg_stroke = bg_stroke - padding;
|
||||
const radius = Math.min(width, height) / 2.0 - Math.max(bg_stroke, fg_stroke) / 2.0;
|
||||
const center_x = width / 2.0 + marginLeft;
|
||||
const center_y = height / 2.0 + marginTop;
|
||||
const start_angle = -Math.PI / 2.0;
|
||||
const end_angle = start_angle + (2 * Math.PI * progressValue);
|
||||
const start_x = center_x + Math.cos(start_angle) * radius;
|
||||
const start_y = center_y + Math.sin(start_angle) * radius;
|
||||
const end_x = center_x + Math.cos(end_angle) * radius;
|
||||
const end_y = center_y + Math.sin(end_angle) * radius;
|
||||
|
||||
// Draw background
|
||||
const background_color = styleContext.get_property('background-color', Gtk.StateFlags.NORMAL);
|
||||
cr.setSourceRGBA(background_color.red, background_color.green, background_color.blue, background_color.alpha);
|
||||
cr.arc(center_x, center_y, radius, 0, 2 * Math.PI);
|
||||
cr.setLineWidth(bg_stroke);
|
||||
cr.stroke();
|
||||
|
||||
// Draw progress
|
||||
const color = styleContext.get_property('color', Gtk.StateFlags.NORMAL);
|
||||
cr.setSourceRGBA(color.red, color.green, color.blue, color.alpha);
|
||||
cr.arc(center_x, center_y, radius, start_angle, end_angle);
|
||||
cr.setLineWidth(fg_stroke);
|
||||
cr.stroke();
|
||||
|
||||
// Draw rounded ends for progress arcs
|
||||
cr.setLineWidth(0);
|
||||
cr.arc(start_x, start_y, fg_stroke / 2, 0, 0 - 0.01);
|
||||
cr.fill();
|
||||
cr.arc(end_x, end_y, fg_stroke / 2, 0, 0 - 0.01);
|
||||
cr.fill();
|
||||
}))
|
||||
},
|
||||
})
|
||||
10
desktops/hyprland/ags/modules/lib/contextmenuitem.js
Normal file
10
desktops/hyprland/ags/modules/lib/contextmenuitem.js
Normal file
@@ -0,0 +1,10 @@
|
||||
const { Gdk, Gtk } = imports.gi;
|
||||
import { Widget } from '../../imports.js';
|
||||
|
||||
export const ContextMenuItem = ({ label, onClick }) => Widget({
|
||||
type: Gtk.MenuItem,
|
||||
label: `${label}`,
|
||||
setup: menuItem => {
|
||||
menuItem.connect("activate", onClick);
|
||||
}
|
||||
})
|
||||
70
desktops/hyprland/ags/modules/lib/cursorhover.js
Normal file
70
desktops/hyprland/ags/modules/lib/cursorhover.js
Normal file
@@ -0,0 +1,70 @@
|
||||
const { Gdk, Gtk } = imports.gi;
|
||||
|
||||
const CLICK_BRIGHTEN_AMOUNT = 0.13;
|
||||
|
||||
export function setupCursorHover(button) {
|
||||
var clicked = false;
|
||||
var dummy = false;
|
||||
var cursorX = 0;
|
||||
var cursorY = 0;
|
||||
const styleContext = button.get_style_context();
|
||||
var clickColor = styleContext.get_property('background-color', Gtk.StateFlags.HOVER);
|
||||
clickColor.green += CLICK_BRIGHTEN_AMOUNT;
|
||||
clickColor.blue += CLICK_BRIGHTEN_AMOUNT;
|
||||
clickColor.red += CLICK_BRIGHTEN_AMOUNT;
|
||||
clickColor = clickColor.to_string();
|
||||
|
||||
const display = Gdk.Display.get_default();
|
||||
button.connect('enter-notify-event', () => {
|
||||
const cursor = Gdk.Cursor.new_from_name(display, 'pointer');
|
||||
button.get_window().set_cursor(cursor);
|
||||
});
|
||||
|
||||
button.connect('leave-notify-event', () => {
|
||||
const cursor = Gdk.Cursor.new_from_name(display, 'default');
|
||||
button.get_window().set_cursor(cursor);
|
||||
});
|
||||
|
||||
// button.add_events(Gdk.EventMask.POINTER_MOTION_MASK);
|
||||
// button.connect('motion-notify-event', (widget, event) => {
|
||||
// [dummy, cursorX, cursorY] = event.get_coords(); // Get the mouse coordinates relative to the widget
|
||||
// if(!clicked) widget.style = `
|
||||
// background-image: radial-gradient(circle at ${cursorX}px ${cursorY}px, rgba(0,0,0,0), rgba(0,0,0,0) 0%, rgba(0,0,0,0) 0%, ${clickColor} 0%, ${clickColor} 0%, ${clickColor} 0%, ${clickColor} 0%, rgba(0,0,0,0) 0%, rgba(0,0,0,0) 0%);
|
||||
// `;
|
||||
// });
|
||||
|
||||
// button.connect('button-press-event', (widget, event) => {
|
||||
// clicked = true;
|
||||
// [dummy, cursorX, cursorY] = event.get_coords(); // Get the mouse coordinates relative to the widget
|
||||
// cursorX = Math.round(cursorX); cursorY = Math.round(cursorY);
|
||||
// widget.style = `
|
||||
// background-image: radial-gradient(circle at ${cursorX}px ${cursorY}px, rgba(0,0,0,0), rgba(0,0,0,0) 0%, rgba(0,0,0,0) 0%, ${clickColor} 0%, ${clickColor} 0%, ${clickColor} 0%, ${clickColor} 0%, rgba(0,0,0,0) 0%, rgba(0,0,0,0) 0%);
|
||||
// `;
|
||||
// widget.toggleClassName('growingRadial', true);
|
||||
// widget.style = `
|
||||
// background-image: radial-gradient(circle at ${cursorX}px ${cursorY}px, rgba(0,0,0,0), rgba(0,0,0,0) 0%, rgba(0,0,0,0) 0%, ${clickColor} 0%, ${clickColor} 0%, ${clickColor} 70%, ${clickColor} 70%, rgba(0,0,0,0) 70%, rgba(0,0,0,0) 70%);
|
||||
// `
|
||||
// });
|
||||
// button.connect('button-release-event', (widget, event) => {
|
||||
// widget.toggleClassName('growingRadial', false);
|
||||
// widget.toggleClassName('fadingRadial', false);
|
||||
// widget.style = `
|
||||
// background-image: radial-gradient(circle at ${cursorX}px ${cursorY}px, rgba(0,0,0,0), rgba(0,0,0,0) 0%, rgba(0,0,0,0) 0%, rgba(0,0,0,0) 0%, rgba(0,0,0,0) 0%, rgba(0,0,0,0) 70%, rgba(0,0,0,0) 70%, rgba(0,0,0,0) 70%, rgba(0,0,0,0) 70%);
|
||||
// `
|
||||
// clicked = false;
|
||||
// });
|
||||
}
|
||||
|
||||
export function setupCursorHoverAim(button) {
|
||||
button.connect('enter-notify-event', () => {
|
||||
const display = Gdk.Display.get_default();
|
||||
const cursor = Gdk.Cursor.new_from_name(display, 'crosshair');
|
||||
button.get_window().set_cursor(cursor);
|
||||
});
|
||||
|
||||
button.connect('leave-notify-event', () => {
|
||||
const display = Gdk.Display.get_default();
|
||||
const cursor = Gdk.Cursor.new_from_name(display, 'default');
|
||||
button.get_window().set_cursor(cursor);
|
||||
});
|
||||
}
|
||||
7
desktops/hyprland/ags/modules/lib/materialicon.js
Normal file
7
desktops/hyprland/ags/modules/lib/materialicon.js
Normal file
@@ -0,0 +1,7 @@
|
||||
import { Widget } from '../../imports.js';
|
||||
|
||||
export const MaterialIcon = (icon, size, props = {}) => Widget.Label({
|
||||
className: `icon-material txt-${size}`,
|
||||
label: icon,
|
||||
...props,
|
||||
})
|
||||
73
desktops/hyprland/ags/modules/lib/navigationindicator.js
Normal file
73
desktops/hyprland/ags/modules/lib/navigationindicator.js
Normal file
@@ -0,0 +1,73 @@
|
||||
const { Gdk, Gtk } = imports.gi;
|
||||
const GObject = imports.gi.GObject;
|
||||
const Lang = imports.lang;
|
||||
import { Utils, Widget } from '../../imports.js';
|
||||
|
||||
// min-height/min-width for height/width
|
||||
// background-color/color for background/indicator color
|
||||
// padding for pad of indicator
|
||||
// font-size for selected index (0-based)
|
||||
export const NavigationIndicator = (count, vertical, props) => Widget({
|
||||
...props,
|
||||
type: Gtk.DrawingArea,
|
||||
setup: (area) => {
|
||||
const styleContext = area.get_style_context();
|
||||
const width = Math.max(styleContext.get_property('min-width', Gtk.StateFlags.NORMAL), area.get_allocated_width());
|
||||
const height = Math.max(styleContext.get_property('min-height', Gtk.StateFlags.NORMAL), area.get_allocated_height());
|
||||
area.set_size_request(width, height);
|
||||
|
||||
area.connect('draw', Lang.bind(area, (area, cr) => {
|
||||
const styleContext = area.get_style_context();
|
||||
const width = Math.max(styleContext.get_property('min-width', Gtk.StateFlags.NORMAL), area.get_allocated_width());
|
||||
const height = Math.max(styleContext.get_property('min-height', Gtk.StateFlags.NORMAL), area.get_allocated_height());
|
||||
// console.log('allocated width/height:', area.get_allocated_width(), '/', area.get_allocated_height())
|
||||
area.set_size_request(width, height);
|
||||
const paddingLeft = styleContext.get_padding(Gtk.StateFlags.NORMAL).left;
|
||||
const paddingRight = styleContext.get_padding(Gtk.StateFlags.NORMAL).right;
|
||||
const paddingTop = styleContext.get_padding(Gtk.StateFlags.NORMAL).top;
|
||||
const paddingBottom = styleContext.get_padding(Gtk.StateFlags.NORMAL).bottom;
|
||||
|
||||
const selectedCell = styleContext.get_property('font-size', Gtk.StateFlags.NORMAL);
|
||||
|
||||
let cellWidth = width;
|
||||
let cellHeight = height;
|
||||
if (vertical) cellHeight /= count;
|
||||
else cellWidth /= count;
|
||||
const indicatorWidth = cellWidth - paddingLeft - paddingRight;
|
||||
const indicatorHeight = cellHeight - paddingTop - paddingBottom;
|
||||
|
||||
const background_color = styleContext.get_property('background-color', Gtk.StateFlags.NORMAL);
|
||||
const color = styleContext.get_property('color', Gtk.StateFlags.NORMAL);
|
||||
cr.setLineWidth(2);
|
||||
// Background
|
||||
cr.setSourceRGBA(background_color.red, background_color.green, background_color.blue, background_color.alpha);
|
||||
cr.rectangle(0, 0, width, height);
|
||||
cr.fill();
|
||||
|
||||
// The indicator line
|
||||
cr.setSourceRGBA(color.red, color.green, color.blue, color.alpha);
|
||||
if (vertical) {
|
||||
cr.rectangle(paddingLeft, paddingTop + cellHeight * selectedCell + indicatorWidth / 2, indicatorWidth, indicatorHeight - indicatorWidth);
|
||||
cr.stroke();
|
||||
cr.rectangle(paddingLeft, paddingTop + cellHeight * selectedCell + indicatorWidth / 2, indicatorWidth, indicatorHeight - indicatorWidth);
|
||||
cr.fill();
|
||||
cr.arc(paddingLeft + indicatorWidth / 2, paddingTop + cellHeight * selectedCell + indicatorWidth / 2, indicatorWidth / 2, Math.PI, 2 * Math.PI);
|
||||
cr.fill();
|
||||
cr.arc(paddingLeft + indicatorWidth / 2, paddingTop + cellHeight * selectedCell + indicatorHeight - indicatorWidth / 2, indicatorWidth / 2, 0, Math.PI);
|
||||
cr.fill();
|
||||
}
|
||||
else {
|
||||
cr.rectangle(paddingLeft + cellWidth * selectedCell + indicatorHeight / 2, paddingTop, indicatorWidth - indicatorHeight, indicatorHeight);
|
||||
cr.stroke();
|
||||
cr.rectangle(paddingLeft + cellWidth * selectedCell + indicatorHeight / 2, paddingTop, indicatorWidth - indicatorHeight, indicatorHeight);
|
||||
cr.fill();
|
||||
cr.arc(paddingLeft + cellWidth * selectedCell + indicatorHeight / 2, paddingTop + indicatorHeight / 2, indicatorHeight / 2, 0.5 * Math.PI, 1.5 * Math.PI);
|
||||
cr.fill();
|
||||
cr.arc(paddingLeft + cellWidth * selectedCell + indicatorWidth - indicatorHeight / 2, paddingTop + indicatorHeight / 2, indicatorHeight / 2, -0.5 * Math.PI, 0.5 * Math.PI);
|
||||
cr.fill();
|
||||
}
|
||||
}))
|
||||
},
|
||||
})
|
||||
|
||||
|
||||
298
desktops/hyprland/ags/modules/lib/notification.js
Normal file
298
desktops/hyprland/ags/modules/lib/notification.js
Normal file
@@ -0,0 +1,298 @@
|
||||
// This file is for the actual widget for each single notification
|
||||
|
||||
const { GLib, Gdk, Gtk } = imports.gi;
|
||||
import { Utils, Widget } from '../../imports.js';
|
||||
const { lookUpIcon, timeout } = Utils;
|
||||
const { Box, EventBox, Icon, Scrollable, Label, Button, Revealer } = Widget;
|
||||
import { MaterialIcon } from "./materialicon.js";
|
||||
import { setupCursorHover } from "./cursorhover.js";
|
||||
|
||||
const NotificationIcon = (notifObject) => {
|
||||
// { appEntry, appIcon, image }, urgency = 'normal'
|
||||
if (notifObject.image) {
|
||||
return Box({
|
||||
valign: 'center',
|
||||
hexpand: false,
|
||||
className: 'notif-icon',
|
||||
style: `
|
||||
background-image: url("${notifObject.image}");
|
||||
background-size: auto 100%;
|
||||
background-repeat: no-repeat;
|
||||
background-position: center;
|
||||
`,
|
||||
});
|
||||
}
|
||||
|
||||
let icon = 'NO_ICON';
|
||||
if (lookUpIcon(notifObject.appIcon))
|
||||
icon = notifObject.appIcon;
|
||||
if (lookUpIcon(notifObject.appEntry))
|
||||
icon = notifObject.appEntry;
|
||||
|
||||
return Box({
|
||||
valign: 'center',
|
||||
hexpand: false,
|
||||
className: 'notif-icon',
|
||||
setup: box => {
|
||||
if (icon != 'NO_ICON') box.pack_start(Icon({
|
||||
icon, size: 30,
|
||||
halign: 'center', hexpand: true,
|
||||
valign: 'center',
|
||||
setup: () => {
|
||||
box.toggleClassName(`notif-icon-material-${notifObject.urgency}`, true);
|
||||
},
|
||||
}), false, true, 0);
|
||||
else box.pack_start(MaterialIcon(`${notifObject.urgency == 'critical' ? 'release_alert' : 'chat'}`, 'hugeass', {
|
||||
hexpand: true,
|
||||
setup: () => box.toggleClassName(`notif-icon-material-${notifObject.urgency}`, true),
|
||||
}), false, true, 0)
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export default ({
|
||||
notifObject,
|
||||
isPopup = false,
|
||||
props = {},
|
||||
} = {}) => {
|
||||
const command = (isPopup ?
|
||||
() => notifObject.dismiss() :
|
||||
() => notifObject.close()
|
||||
)
|
||||
const destroyWithAnims = () => {
|
||||
widget.sensitive = false;
|
||||
notificationBox.setStyle(rightAnim1);
|
||||
Utils.timeout(200, () => {
|
||||
wholeThing.revealChild = false;
|
||||
});
|
||||
Utils.timeout(400, () => {
|
||||
command();
|
||||
wholeThing.destroy();
|
||||
});
|
||||
}
|
||||
const widget = EventBox({
|
||||
onHover: (self) => {
|
||||
self.window.set_cursor(Gdk.Cursor.new_from_name(display, 'grab'));
|
||||
if (!wholeThing._hovered)
|
||||
wholeThing._hovered = true;
|
||||
},
|
||||
onHoverLost: (self) => {
|
||||
self.window.set_cursor(null);
|
||||
if (wholeThing._hovered)
|
||||
wholeThing._hovered = false;
|
||||
if(isPopup) {
|
||||
command();
|
||||
}
|
||||
},
|
||||
onMiddleClick: (self) => {
|
||||
destroyWithAnims();
|
||||
}
|
||||
});
|
||||
const wholeThing = Revealer({
|
||||
properties: [
|
||||
['id', notifObject.id],
|
||||
['close', undefined],
|
||||
['hovered', false],
|
||||
['dragging', false],
|
||||
['destroyWithAnims', () => destroyWithAnims]
|
||||
],
|
||||
revealChild: false,
|
||||
transition: 'slide_down',
|
||||
transitionDuration: 200,
|
||||
child: Box({ // Box to make sure css-based spacing works
|
||||
homogeneous: true,
|
||||
})
|
||||
});
|
||||
|
||||
const display = Gdk.Display.get_default();
|
||||
const notificationContent = Box({
|
||||
...props,
|
||||
className: `${isPopup ? 'popup-' : ''}notif-${notifObject.urgency} spacing-h-10`,
|
||||
children: [
|
||||
NotificationIcon(notifObject),
|
||||
Box({
|
||||
valign: 'center',
|
||||
vertical: true,
|
||||
hexpand: true,
|
||||
children: [
|
||||
Box({
|
||||
children: [
|
||||
Label({
|
||||
xalign: 0,
|
||||
className: 'txt-small txt-semibold titlefont',
|
||||
justify: Gtk.Justification.LEFT,
|
||||
hexpand: true,
|
||||
maxWidthChars: 24,
|
||||
ellipsize: 3,
|
||||
wrap: true,
|
||||
useMarkup: notifObject.summary.startsWith('<'),
|
||||
label: notifObject.summary,
|
||||
}),
|
||||
]
|
||||
}),
|
||||
Label({
|
||||
xalign: 0,
|
||||
className: 'txt-smallie notif-body-${urgency}',
|
||||
useMarkup: true,
|
||||
xalign: 0,
|
||||
justify: Gtk.Justification.LEFT,
|
||||
wrap: true,
|
||||
label: notifObject.body,
|
||||
}),
|
||||
]
|
||||
}),
|
||||
Box({
|
||||
className: 'spacing-h-5',
|
||||
children: [
|
||||
Label({
|
||||
valign: 'center',
|
||||
className: 'txt-smaller txt-semibold',
|
||||
justify: Gtk.Justification.RIGHT,
|
||||
setup: (label) => {
|
||||
const messageTime = GLib.DateTime.new_from_unix_local(notifObject.time);
|
||||
if (messageTime.get_day_of_year() == GLib.DateTime.new_now_local().get_day_of_year()) {
|
||||
label.label = messageTime.format('%H:%M');
|
||||
}
|
||||
else if (messageTime.get_day_of_year() == GLib.DateTime.new_now_local().get_day_of_year() - 1) {
|
||||
label.label = messageTime.format('%H:%M\nYesterday');
|
||||
}
|
||||
else {
|
||||
label.label = messageTime.format('%H:%M\n%d/%m');
|
||||
}
|
||||
}
|
||||
}),
|
||||
Button({
|
||||
className: 'notif-close-btn',
|
||||
onClicked: () => {
|
||||
destroyWithAnims()
|
||||
},
|
||||
child: MaterialIcon('close', 'large', {
|
||||
valign: 'center',
|
||||
}),
|
||||
setup: (button) => setupCursorHover(button),
|
||||
}),
|
||||
]
|
||||
}),
|
||||
|
||||
// what is this? i think it should be at the bottom not on the right
|
||||
// Box({
|
||||
// className: 'actions',
|
||||
// children: actions.map(action => Button({
|
||||
// className: 'action-button',
|
||||
// onClicked: () => Notifications.invoke(id, action.id),
|
||||
// hexpand: true,
|
||||
// child: Label(action.label),
|
||||
// })),
|
||||
// }),
|
||||
]
|
||||
})
|
||||
|
||||
// Gesture stuff
|
||||
|
||||
const gesture = Gtk.GestureDrag.new(widget);
|
||||
var initialDir = 0;
|
||||
// in px
|
||||
const startMargin = 0;
|
||||
const dragThreshold = 100;
|
||||
// in rem
|
||||
const maxOffset = 10.227;
|
||||
const endMargin = 20.455;
|
||||
const disappearHeight = 6.818;
|
||||
const leftAnim1 = `transition: 200ms cubic-bezier(0.05, 0.7, 0.1, 1);
|
||||
margin-left: -${Number(maxOffset + endMargin)}rem;
|
||||
margin-right: ${Number(maxOffset + endMargin)}rem;
|
||||
opacity: 0;`;
|
||||
|
||||
const rightAnim1 = `transition: 200ms cubic-bezier(0.05, 0.7, 0.1, 1);
|
||||
margin-left: ${Number(maxOffset + endMargin)}rem;
|
||||
margin-right: -${Number(maxOffset + endMargin)}rem;
|
||||
opacity: 0;`;
|
||||
|
||||
const notificationBox = Box({
|
||||
properties: [
|
||||
['leftAnim1', leftAnim1],
|
||||
['rightAnim1', rightAnim1],
|
||||
['ready', false],
|
||||
],
|
||||
homogeneous: true,
|
||||
children: [notificationContent],
|
||||
connections: [
|
||||
[gesture, self => {
|
||||
var offset = gesture.get_offset()[1];
|
||||
if (initialDir == 0 && offset != 0)
|
||||
initialDir = (offset > 0 ? 1 : -1)
|
||||
|
||||
if (offset > 0) {
|
||||
if (initialDir < 0)
|
||||
self.setStyle(`margin-left: 0px; margin-right: 0px;`);
|
||||
else
|
||||
self.setStyle(`
|
||||
margin-left: ${Number(offset + startMargin)}px;
|
||||
margin-right: -${Number(offset + startMargin)}px;
|
||||
`);
|
||||
}
|
||||
else if (offset < 0) {
|
||||
if (initialDir > 0)
|
||||
self.setStyle(`margin-left: 0px; margin-right: 0px;`);
|
||||
else {
|
||||
offset = Math.abs(offset);
|
||||
self.setStyle(`
|
||||
margin-right: ${Number(offset + startMargin)}px;
|
||||
margin-left: -${Number(offset + startMargin)}px;
|
||||
`);
|
||||
}
|
||||
}
|
||||
|
||||
wholeThing._dragging = Math.abs(offset) > 10;
|
||||
|
||||
if (widget.window)
|
||||
widget.window.set_cursor(Gdk.Cursor.new_from_name(display, 'grabbing'));
|
||||
}, 'drag-update'],
|
||||
|
||||
[gesture, self => {
|
||||
if (!self._ready) {
|
||||
wholeThing.revealChild = true;
|
||||
self._ready = true;
|
||||
return;
|
||||
}
|
||||
|
||||
const offset = gesture.get_offset()[1];
|
||||
|
||||
if (Math.abs(offset) > dragThreshold && offset * initialDir > 0) {
|
||||
if (offset > 0) {
|
||||
self.setStyle(rightAnim1);
|
||||
widget.sensitive = false;
|
||||
}
|
||||
else {
|
||||
self.setStyle(leftAnim1);
|
||||
widget.sensitive = false;
|
||||
}
|
||||
Utils.timeout(200, () => {
|
||||
wholeThing.revealChild = false
|
||||
});
|
||||
Utils.timeout(400, () => {
|
||||
command();
|
||||
wholeThing.destroy();
|
||||
});
|
||||
}
|
||||
else {
|
||||
self.setStyle(`transition: margin 200ms cubic-bezier(0.05, 0.7, 0.1, 1), opacity 200ms cubic-bezier(0.05, 0.7, 0.1, 1);
|
||||
margin-left: ${startMargin}px;
|
||||
margin-right: ${startMargin}px;
|
||||
margin-bottom: unset; margin-top: unset;
|
||||
opacity: 1;`);
|
||||
if (widget.window)
|
||||
widget.window.set_cursor(Gdk.Cursor.new_from_name(display, 'grab'));
|
||||
|
||||
wholeThing._dragging = false;
|
||||
}
|
||||
initialDir = 0;
|
||||
}, 'drag-end'],
|
||||
|
||||
],
|
||||
})
|
||||
widget.add(notificationBox);
|
||||
wholeThing.child.children = [widget];
|
||||
|
||||
return wholeThing;
|
||||
}
|
||||
51
desktops/hyprland/ags/modules/lib/roundedcorner.js
Normal file
51
desktops/hyprland/ags/modules/lib/roundedcorner.js
Normal file
@@ -0,0 +1,51 @@
|
||||
import { Widget } from '../../imports.js';
|
||||
const { Gtk } = imports.gi;
|
||||
const Lang = imports.lang;
|
||||
|
||||
export const RoundedCorner = (place, props) => Widget({
|
||||
...props,
|
||||
type: Gtk.DrawingArea,
|
||||
halign: place.includes('left') ? 'start' : 'end',
|
||||
valign: place.includes('top') ? 'start' : 'end',
|
||||
setup: widget => {
|
||||
const c = widget.get_style_context().get_property('background-color', Gtk.StateFlags.NORMAL);
|
||||
const r = widget.get_style_context().get_property('border-radius', Gtk.StateFlags.NORMAL);
|
||||
widget.set_size_request(r, r);
|
||||
widget.connect('draw', Lang.bind(widget, (widget, cr) => {
|
||||
const c = widget.get_style_context().get_property('background-color', Gtk.StateFlags.NORMAL);
|
||||
const r = widget.get_style_context().get_property('border-radius', Gtk.StateFlags.NORMAL);
|
||||
// const borderColor = widget.get_style_context().get_property('color', Gtk.StateFlags.NORMAL);
|
||||
// const borderWidth = widget.get_style_context().get_border(Gtk.StateFlags.NORMAL).left; // ur going to write border-width: something anyway
|
||||
widget.set_size_request(r, r);
|
||||
|
||||
switch (place) {
|
||||
case 'topleft':
|
||||
cr.arc(r, r, r, Math.PI, 3 * Math.PI / 2);
|
||||
cr.lineTo(0, 0);
|
||||
break;
|
||||
|
||||
case 'topright':
|
||||
cr.arc(0, r, r, 3 * Math.PI / 2, 2 * Math.PI);
|
||||
cr.lineTo(r, 0);
|
||||
break;
|
||||
|
||||
case 'bottomleft':
|
||||
cr.arc(r, 0, r, Math.PI / 2, Math.PI);
|
||||
cr.lineTo(0, r);
|
||||
break;
|
||||
|
||||
case 'bottomright':
|
||||
cr.arc(0, 0, r, 0, Math.PI / 2);
|
||||
cr.lineTo(r, r);
|
||||
break;
|
||||
}
|
||||
|
||||
cr.closePath();
|
||||
cr.setSourceRGBA(c.red, c.green, c.blue, c.alpha);
|
||||
cr.fill();
|
||||
// cr.setLineWidth(borderWidth);
|
||||
// cr.setSourceRGBA(borderColor.red, borderColor.green, borderColor.blue, borderColor.alpha);
|
||||
// cr.stroke();
|
||||
}));
|
||||
},
|
||||
});
|
||||
69
desktops/hyprland/ags/modules/lib/searchitem.js
Normal file
69
desktops/hyprland/ags/modules/lib/searchitem.js
Normal file
@@ -0,0 +1,69 @@
|
||||
const { Gdk, Gtk } = imports.gi;
|
||||
import { App, Service, Utils, Widget } from '../../imports.js';
|
||||
const { execAsync, exec } = Utils;
|
||||
import { setupCursorHover, setupCursorHoverAim } from "./cursorhover.js";
|
||||
import { MaterialIcon } from './materialicon.js';
|
||||
|
||||
export const searchItem = ({ materialIconName, name, actionName, content, onActivate }) => {
|
||||
const actionText = Widget.Revealer({
|
||||
revealChild: false,
|
||||
transition: "crossfade",
|
||||
transitionDuration: 200,
|
||||
child: Widget.Label({
|
||||
className: 'overview-search-results-txt txt txt-small txt-action',
|
||||
label: `${actionName}`,
|
||||
})
|
||||
});
|
||||
const actionTextRevealer = Widget.Revealer({
|
||||
revealChild: false,
|
||||
transition: "slide_left",
|
||||
transitionDuration: 300,
|
||||
child: actionText,
|
||||
})
|
||||
return Widget.Button({
|
||||
className: 'overview-search-result-btn',
|
||||
onClicked: onActivate,
|
||||
child: Widget.Box({
|
||||
children: [
|
||||
Widget.Box({
|
||||
vertical: false,
|
||||
children: [
|
||||
Widget.Label({
|
||||
className: `icon-material overview-search-results-icon`,
|
||||
label: `${materialIconName}`,
|
||||
}),
|
||||
Widget.Box({
|
||||
vertical: true,
|
||||
children: [
|
||||
Widget.Label({
|
||||
halign: 'start',
|
||||
className: 'overview-search-results-txt txt txt-smallie txt-subtext',
|
||||
label: `${name}`,
|
||||
truncate: "end",
|
||||
}),
|
||||
Widget.Label({
|
||||
halign: 'start',
|
||||
className: 'overview-search-results-txt txt txt-norm',
|
||||
label: `${content}`,
|
||||
truncate: "end",
|
||||
}),
|
||||
]
|
||||
}),
|
||||
Widget.Box({ hexpand: true }),
|
||||
actionTextRevealer,
|
||||
],
|
||||
})
|
||||
]
|
||||
}),
|
||||
connections: [
|
||||
['focus-in-event', (button) => {
|
||||
actionText.revealChild = true;
|
||||
actionTextRevealer.revealChild = true;
|
||||
}],
|
||||
['focus-out-event', (button) => {
|
||||
actionText.revealChild = false;
|
||||
actionTextRevealer.revealChild = false;
|
||||
}],
|
||||
]
|
||||
});
|
||||
}
|
||||
9
desktops/hyprland/ags/modules/lib/separator.js
Normal file
9
desktops/hyprland/ags/modules/lib/separator.js
Normal file
@@ -0,0 +1,9 @@
|
||||
const { Gdk, Gtk } = imports.gi;
|
||||
import { App, Service, Utils, Widget } from '../../imports.js';
|
||||
const { execAsync, exec } = Utils;
|
||||
import { setupCursorHover, setupCursorHoverAim } from "./cursorhover.js";
|
||||
import { MaterialIcon } from './materialicon.js';
|
||||
|
||||
export const separatorLine = Widget.Box({
|
||||
className: 'separator-line',
|
||||
})
|
||||
Reference in New Issue
Block a user