From 5d94c0a7d44a2255b81815a52a7056a94a39842d Mon Sep 17 00:00:00 2001 From: nippy Date: Sat, 18 Apr 2026 13:49:56 +0200 Subject: update Raveos themes --- .../quickshell/Modules/Notepad/NotepadTabs.qml | 285 +++++++++++++++++++++ 1 file changed, 285 insertions(+) create mode 100644 raveos-theme/hyprland/theme-data/DankMaterialShell/quickshell/Modules/Notepad/NotepadTabs.qml (limited to 'raveos-theme/hyprland/theme-data/DankMaterialShell/quickshell/Modules/Notepad/NotepadTabs.qml') diff --git a/raveos-theme/hyprland/theme-data/DankMaterialShell/quickshell/Modules/Notepad/NotepadTabs.qml b/raveos-theme/hyprland/theme-data/DankMaterialShell/quickshell/Modules/Notepad/NotepadTabs.qml new file mode 100644 index 0000000..05a21d1 --- /dev/null +++ b/raveos-theme/hyprland/theme-data/DankMaterialShell/quickshell/Modules/Notepad/NotepadTabs.qml @@ -0,0 +1,285 @@ +pragma ComponentBehavior: Bound +import QtQuick +import QtQuick.Controls +import qs.Common +import qs.Services +import qs.Widgets + +Column { + id: root + + property var currentTab: NotepadStorageService.tabs.length > NotepadStorageService.currentTabIndex ? NotepadStorageService.tabs[NotepadStorageService.currentTabIndex] : null + property bool contentLoaded: false + property int draggedIndex: -1 + property int dropTargetIndex: -1 + property bool suppressShiftAnimation: false + readonly property real tabItemSize: 128 + Theme.spacingXS + + signal tabSwitched(int tabIndex) + signal tabClosed(int tabIndex) + signal newTabRequested + + function hasUnsavedChangesForTab(tab) { + if (!tab) + return false; + + if (tab.id === currentTab?.id) { + return root.parent?.hasUnsavedChanges ? root.parent.hasUnsavedChanges() : false; + } + return false; + } + + spacing: Theme.spacingXS + + Row { + width: parent.width + height: 36 + spacing: Theme.spacingXS + + ScrollView { + width: parent.width - newTabButton.width - Theme.spacingXS + height: parent.height + clip: true + + ScrollBar.horizontal.visible: false + ScrollBar.vertical.visible: false + + Row { + spacing: Theme.spacingXS + + Repeater { + model: NotepadStorageService.tabs + + delegate: Item { + id: delegateItem + required property int index + required property var modelData + + readonly property bool isActive: NotepadStorageService.currentTabIndex === index + readonly property bool isHovered: tabMouseArea.containsMouse && !closeMouseArea.containsMouse + readonly property real tabWidth: 128 + property bool longPressing: false + property bool dragging: false + property point dragStartPos: Qt.point(0, 0) + property int targetIndex: -1 + property int originalIndex: -1 + property real dragAxisOffset: 0 + + Timer { + id: longPressTimer + interval: 200 + repeat: false + onTriggered: { + if (NotepadStorageService.tabs.length > 1) { + delegateItem.longPressing = true + } + } + } + + readonly property real shiftOffset: { + if (root.draggedIndex < 0) + return 0 + if (index === root.draggedIndex) + return 0 + var dragIdx = root.draggedIndex + var dropIdx = root.dropTargetIndex + var myIdx = index + var shiftAmount = root.tabItemSize + if (dropIdx < 0) + return 0 + if (dragIdx < dropIdx && myIdx > dragIdx && myIdx <= dropIdx) + return -shiftAmount + if (dragIdx > dropIdx && myIdx >= dropIdx && myIdx < dragIdx) + return shiftAmount + return 0 + } + + width: tabWidth + height: 32 + z: dragging ? 100 : 0 + + transform: Translate { + x: shiftOffset + Behavior on x { + enabled: !root.suppressShiftAnimation + NumberAnimation { + duration: 150 + easing.type: Easing.OutCubic + } + } + } + + Item { + id: tabVisual + anchors.fill: parent + z: 1 + layer.enabled: dragging + layer.smooth: true + + transform: Translate { + x: dragging ? dragAxisOffset : 0 + } + + Rectangle { + id: tabRect + anchors.fill: parent + radius: Theme.cornerRadius + color: isActive ? Theme.primaryPressed : isHovered ? Theme.primaryHoverLight : Theme.withAlpha(Theme.primaryPressed, 0) + border.width: isActive || dragging ? 0 : 1 + border.color: dragging ? Theme.primary : Theme.outlineMedium + clip: true + + Row { + id: tabContent + anchors.fill: parent + anchors.leftMargin: Theme.spacingM + anchors.rightMargin: Theme.spacingM + spacing: Theme.spacingXS + + StyledText { + id: tabText + width: parent.width - (tabCloseButton.visible ? tabCloseButton.width + Theme.spacingXS : 0) + text: { + var prefix = "" + if (hasUnsavedChangesForTab(modelData)) { + prefix = "● " + } + return prefix + (modelData.title || "Untitled") + } + font.pixelSize: Theme.fontSizeSmall + color: isActive ? Theme.primary : Theme.surfaceText + font.weight: isActive ? Font.Medium : Font.Normal + elide: Text.ElideMiddle + maximumLineCount: 1 + wrapMode: Text.NoWrap + anchors.verticalCenter: parent.verticalCenter + } + + Rectangle { + id: tabCloseButton + width: 20 + height: 20 + radius: Theme.cornerRadius + color: closeMouseArea.containsMouse ? Theme.surfaceTextHover : Theme.withAlpha(Theme.surfaceTextHover, 0) + visible: NotepadStorageService.tabs.length > 1 + anchors.verticalCenter: parent.verticalCenter + + DankIcon { + name: "close" + size: 14 + color: Theme.surfaceTextMedium + anchors.centerIn: parent + } + + MouseArea { + id: closeMouseArea + anchors.fill: parent + hoverEnabled: true + cursorShape: Qt.PointingHandCursor + z: 100 + + onClicked: root.tabClosed(index) + } + } + } + + Behavior on color { + ColorAnimation { + duration: Theme.shortDuration + easing.type: Theme.standardEasing + } + } + } + } + + MouseArea { + id: tabMouseArea + anchors.fill: parent + hoverEnabled: true + preventStealing: dragging || longPressing + cursorShape: dragging || longPressing ? Qt.ClosedHandCursor : Qt.PointingHandCursor + acceptedButtons: Qt.LeftButton + + onPressed: mouse => { + if (mouse.button === Qt.LeftButton && NotepadStorageService.tabs.length > 1) { + delegateItem.dragStartPos = Qt.point(mouse.x, mouse.y) + longPressTimer.start() + } + } + + onReleased: mouse => { + longPressTimer.stop() + var wasDragging = delegateItem.dragging + var didReorder = wasDragging && delegateItem.targetIndex >= 0 && delegateItem.targetIndex !== delegateItem.originalIndex + + if (didReorder) { + root.suppressShiftAnimation = true + NotepadStorageService.reorderTab(delegateItem.originalIndex, delegateItem.targetIndex) + } + + delegateItem.longPressing = false + delegateItem.dragging = false + delegateItem.dragAxisOffset = 0 + delegateItem.targetIndex = -1 + delegateItem.originalIndex = -1 + root.draggedIndex = -1 + root.dropTargetIndex = -1 + if (didReorder) { + Qt.callLater(() => { + root.suppressShiftAnimation = false + }) + } + + if (wasDragging || mouse.button !== Qt.LeftButton) + return + root.tabSwitched(index) + } + + onPositionChanged: mouse => { + if (delegateItem.longPressing && !delegateItem.dragging) { + var distance = Math.sqrt(Math.pow(mouse.x - delegateItem.dragStartPos.x, 2) + Math.pow(mouse.y - delegateItem.dragStartPos.y, 2)) + if (distance > 5) { + delegateItem.dragging = true + delegateItem.targetIndex = index + delegateItem.originalIndex = index + root.draggedIndex = index + root.dropTargetIndex = index + } + } + + if (!delegateItem.dragging) + return + + var axisOffset = mouse.x - delegateItem.dragStartPos.x + delegateItem.dragAxisOffset = axisOffset + + var itemSize = root.tabItemSize + var rawSlot = axisOffset / itemSize + var slotOffset = rawSlot >= 0 + ? Math.floor(rawSlot + 0.4) + : Math.ceil(rawSlot - 0.4) + var tabCount = NotepadStorageService.tabs.length + var newTargetIndex = Math.max(0, Math.min(tabCount - 1, delegateItem.originalIndex + slotOffset)) + + if (newTargetIndex !== delegateItem.targetIndex) { + delegateItem.targetIndex = newTargetIndex + root.dropTargetIndex = newTargetIndex + } + } + } + } + } + } + } + + DankActionButton { + id: newTabButton + width: 32 + height: 32 + iconName: "add" + iconSize: Theme.iconSize - 4 + iconColor: Theme.surfaceText + onClicked: root.newTabRequested() + } + } +} -- cgit v1.3