mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2025-12-05 21:15:38 -05:00
launcher: consistent spacing of grid mode
This commit is contained in:
@@ -192,7 +192,6 @@ Item {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
SpotlightContextMenuPopup {
|
||||
id: popupContextMenu
|
||||
|
||||
@@ -244,16 +243,17 @@ Item {
|
||||
spacing: Theme.spacingM
|
||||
clip: false
|
||||
|
||||
Row {
|
||||
width: parent.width
|
||||
spacing: Theme.spacingM
|
||||
leftPadding: Theme.spacingS
|
||||
topPadding: Theme.spacingS
|
||||
Item {
|
||||
id: searchRow
|
||||
width: parent.width - Theme.spacingS * 2
|
||||
height: 56
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
|
||||
DankTextField {
|
||||
id: searchField
|
||||
|
||||
width: parent.width - 80 - Theme.spacingL
|
||||
anchors.left: parent.left
|
||||
anchors.right: buttonsContainer.left
|
||||
anchors.rightMargin: Theme.spacingM
|
||||
height: 56
|
||||
cornerRadius: Theme.cornerRadius
|
||||
backgroundColor: Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
|
||||
@@ -302,9 +302,18 @@ Item {
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
id: buttonsContainer
|
||||
width: viewModeButtons.visible ? viewModeButtons.width : (fileSearchButtons.visible ? fileSearchButtons.width : 0)
|
||||
height: 36
|
||||
anchors.right: parent.right
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
Row {
|
||||
id: viewModeButtons
|
||||
spacing: Theme.spacingXS
|
||||
visible: searchMode === "apps" && appLauncher.model.count > 0
|
||||
anchors.right: parent.right
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
Rectangle {
|
||||
@@ -359,8 +368,10 @@ Item {
|
||||
}
|
||||
|
||||
Row {
|
||||
id: fileSearchButtons
|
||||
spacing: Theme.spacingXS
|
||||
visible: searchMode === "files"
|
||||
anchors.right: parent.right
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
Rectangle {
|
||||
@@ -448,6 +459,7 @@ Item {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
width: parent.width
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
import QtQuick
|
||||
import Quickshell
|
||||
import Quickshell.Widgets
|
||||
import qs.Common
|
||||
import qs.Widgets
|
||||
|
||||
@@ -12,28 +10,41 @@ Rectangle {
|
||||
signal itemRightClicked(int index, var modelData, real mouseX, real mouseY)
|
||||
|
||||
function resetScroll() {
|
||||
resultsList.contentY = 0
|
||||
resultsList.contentY = 0;
|
||||
if (gridLoader.item) {
|
||||
gridLoader.item.contentY = 0
|
||||
gridLoader.item.contentY = 0;
|
||||
}
|
||||
}
|
||||
|
||||
function getSelectedItemPosition() {
|
||||
if (!appLauncher) return { x: 0, y: 0 };
|
||||
if (!appLauncher)
|
||||
return {
|
||||
x: 0,
|
||||
y: 0
|
||||
};
|
||||
|
||||
const selectedIndex = appLauncher.selectedIndex;
|
||||
if (appLauncher.viewMode === "list") {
|
||||
const itemY = selectedIndex * (resultsList.itemHeight + resultsList.itemSpacing) - resultsList.contentY;
|
||||
return { x: resultsList.width / 2, y: itemY + resultsList.itemHeight / 2 };
|
||||
return {
|
||||
x: resultsList.width / 2,
|
||||
y: itemY + resultsList.itemHeight / 2
|
||||
};
|
||||
} else if (gridLoader.item) {
|
||||
const grid = gridLoader.item;
|
||||
const row = Math.floor(selectedIndex / grid.actualColumns);
|
||||
const col = selectedIndex % grid.actualColumns;
|
||||
const itemX = col * grid.cellWidth + grid.leftMargin + grid.cellWidth / 2;
|
||||
const itemY = row * grid.cellHeight - grid.contentY + grid.cellHeight / 2;
|
||||
return { x: itemX, y: itemY };
|
||||
return {
|
||||
x: itemX,
|
||||
y: itemY
|
||||
};
|
||||
}
|
||||
return { x: 0, y: 0 };
|
||||
return {
|
||||
x: 0,
|
||||
y: 0
|
||||
};
|
||||
}
|
||||
|
||||
radius: Theme.cornerRadius
|
||||
@@ -56,14 +67,13 @@ Rectangle {
|
||||
|
||||
function ensureVisible(index) {
|
||||
if (index < 0 || index >= count)
|
||||
return
|
||||
|
||||
const itemY = index * (itemHeight + itemSpacing)
|
||||
const itemBottom = itemY + itemHeight
|
||||
return;
|
||||
const itemY = index * (itemHeight + itemSpacing);
|
||||
const itemBottom = itemY + itemHeight;
|
||||
if (itemY < contentY)
|
||||
contentY = itemY
|
||||
contentY = itemY;
|
||||
else if (itemBottom > contentY + height)
|
||||
contentY = itemBottom - height
|
||||
contentY = itemBottom - height;
|
||||
}
|
||||
|
||||
anchors.fill: parent
|
||||
@@ -79,18 +89,18 @@ Rectangle {
|
||||
reuseItems: true
|
||||
onCurrentIndexChanged: {
|
||||
if (keyboardNavigationActive)
|
||||
ensureVisible(currentIndex)
|
||||
ensureVisible(currentIndex);
|
||||
}
|
||||
onItemClicked: (index, modelData) => {
|
||||
if (appLauncher)
|
||||
appLauncher.launchApp(modelData)
|
||||
appLauncher.launchApp(modelData);
|
||||
}
|
||||
onItemRightClicked: (index, modelData, mouseX, mouseY) => {
|
||||
resultsContainer.itemRightClicked(index, modelData, mouseX, mouseY);
|
||||
}
|
||||
onKeyboardNavigationReset: () => {
|
||||
if (appLauncher)
|
||||
appLauncher.keyboardNavigationActive = false
|
||||
appLauncher.keyboardNavigationActive = false;
|
||||
}
|
||||
|
||||
delegate: AppLauncherListDelegate {
|
||||
@@ -105,7 +115,7 @@ Rectangle {
|
||||
iconUnicodeScale: 0.8
|
||||
onItemClicked: (idx, modelData) => resultsList.itemClicked(idx, modelData)
|
||||
onItemRightClicked: (idx, modelData, mouseX, mouseY) => {
|
||||
resultsList.itemRightClicked(idx, modelData, mouseX, mouseY)
|
||||
resultsList.itemRightClicked(idx, modelData, mouseX, mouseY);
|
||||
}
|
||||
onKeyboardNavigationReset: resultsList.keyboardNavigationReset
|
||||
}
|
||||
@@ -130,11 +140,11 @@ Rectangle {
|
||||
|
||||
onWidthChanged: {
|
||||
if (visible && Math.abs(width - _lastWidth) > 1) {
|
||||
_lastWidth = width
|
||||
active = false
|
||||
_lastWidth = width;
|
||||
active = false;
|
||||
Qt.callLater(() => {
|
||||
active = true
|
||||
})
|
||||
active = true;
|
||||
});
|
||||
}
|
||||
}
|
||||
sourceComponent: Component {
|
||||
@@ -148,14 +158,13 @@ Rectangle {
|
||||
property bool adaptiveColumns: false
|
||||
property int minCellWidth: 120
|
||||
property int maxCellWidth: 160
|
||||
property int cellPadding: 8
|
||||
property real iconSizeRatio: 0.55
|
||||
property int maxIconSize: 48
|
||||
property int minIconSize: 32
|
||||
property bool hoverUpdatesSelection: false
|
||||
property bool keyboardNavigationActive: appLauncher ? appLauncher.keyboardNavigationActive : false
|
||||
property int baseCellWidth: adaptiveColumns ? Math.max(minCellWidth, Math.min(maxCellWidth, width / columns)) : (width - Theme.spacingS * 2) / columns
|
||||
property int baseCellHeight: baseCellWidth + 20
|
||||
property real baseCellWidth: adaptiveColumns ? Math.max(minCellWidth, Math.min(maxCellWidth, width / columns)) : width / columns
|
||||
property real baseCellHeight: baseCellWidth + 20
|
||||
property int actualColumns: adaptiveColumns ? Math.floor(width / cellWidth) : columns
|
||||
property int remainingSpace: width - (actualColumns * cellWidth)
|
||||
|
||||
@@ -165,47 +174,44 @@ Rectangle {
|
||||
|
||||
function ensureVisible(index) {
|
||||
if (index < 0 || index >= count)
|
||||
return
|
||||
|
||||
const itemY = Math.floor(index / actualColumns) * cellHeight
|
||||
const itemBottom = itemY + cellHeight
|
||||
return;
|
||||
const itemY = Math.floor(index / actualColumns) * cellHeight;
|
||||
const itemBottom = itemY + cellHeight;
|
||||
if (itemY < contentY)
|
||||
contentY = itemY
|
||||
contentY = itemY;
|
||||
else if (itemBottom > contentY + height)
|
||||
contentY = itemBottom - height
|
||||
contentY = itemBottom - height;
|
||||
}
|
||||
|
||||
anchors.fill: parent
|
||||
model: appLauncher ? appLauncher.model : null
|
||||
clip: true
|
||||
cellWidth: baseCellWidth
|
||||
cellHeight: baseCellHeight
|
||||
leftMargin: Math.max(Theme.spacingS, remainingSpace / 2)
|
||||
rightMargin: leftMargin
|
||||
focus: true
|
||||
interactive: true
|
||||
cacheBuffer: Math.max(0, Math.min(height * 2, 1000))
|
||||
reuseItems: true
|
||||
onCurrentIndexChanged: {
|
||||
if (keyboardNavigationActive)
|
||||
ensureVisible(currentIndex)
|
||||
ensureVisible(currentIndex);
|
||||
}
|
||||
onItemClicked: (index, modelData) => {
|
||||
if (appLauncher)
|
||||
appLauncher.launchApp(modelData)
|
||||
appLauncher.launchApp(modelData);
|
||||
}
|
||||
onItemRightClicked: (index, modelData, mouseX, mouseY) => {
|
||||
resultsContainer.itemRightClicked(index, modelData, mouseX, mouseY);
|
||||
}
|
||||
onKeyboardNavigationReset: () => {
|
||||
if (appLauncher)
|
||||
appLauncher.keyboardNavigationActive = false
|
||||
appLauncher.keyboardNavigationActive = false;
|
||||
}
|
||||
|
||||
delegate: AppLauncherGridDelegate {
|
||||
gridView: resultsGrid
|
||||
cellWidth: resultsGrid.cellWidth
|
||||
cellHeight: resultsGrid.cellHeight
|
||||
cellPadding: resultsGrid.cellPadding
|
||||
minIconSize: resultsGrid.minIconSize
|
||||
maxIconSize: resultsGrid.maxIconSize
|
||||
iconSizeRatio: resultsGrid.iconSizeRatio
|
||||
@@ -214,7 +220,7 @@ Rectangle {
|
||||
currentIndex: resultsGrid.currentIndex
|
||||
onItemClicked: (idx, modelData) => resultsGrid.itemClicked(idx, modelData)
|
||||
onItemRightClicked: (idx, modelData, mouseX, mouseY) => {
|
||||
resultsGrid.itemRightClicked(idx, modelData, mouseX, mouseY)
|
||||
resultsGrid.itemRightClicked(idx, modelData, mouseX, mouseY);
|
||||
}
|
||||
onKeyboardNavigationReset: resultsGrid.keyboardNavigationReset
|
||||
}
|
||||
|
||||
@@ -252,18 +252,19 @@ DankPopout {
|
||||
}
|
||||
}
|
||||
|
||||
Row {
|
||||
width: parent.width
|
||||
Item {
|
||||
width: parent.width - Theme.spacingS * 2
|
||||
height: 40
|
||||
spacing: Theme.spacingM
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
visible: searchField.text.length === 0
|
||||
leftPadding: Theme.spacingS
|
||||
|
||||
Rectangle {
|
||||
width: 180
|
||||
height: 40
|
||||
radius: Theme.cornerRadius
|
||||
color: "transparent"
|
||||
anchors.left: parent.left
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
DankDropdown {
|
||||
anchors.fill: parent
|
||||
@@ -278,13 +279,9 @@ DankPopout {
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
width: parent.width - 290
|
||||
height: 1
|
||||
}
|
||||
|
||||
Row {
|
||||
spacing: 4
|
||||
anchors.right: parent.right
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
DankActionButton {
|
||||
@@ -314,7 +311,8 @@ DankPopout {
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
width: searchField.width
|
||||
x: searchField.x
|
||||
height: {
|
||||
let usedHeight = 40 + Theme.spacingS;
|
||||
usedHeight += 52 + Theme.spacingS;
|
||||
@@ -350,8 +348,6 @@ DankPopout {
|
||||
}
|
||||
|
||||
anchors.fill: parent
|
||||
anchors.leftMargin: Theme.spacingS
|
||||
anchors.rightMargin: Theme.spacingS
|
||||
anchors.bottomMargin: Theme.spacingS
|
||||
visible: appLauncher.viewMode === "list"
|
||||
model: appLauncher.model
|
||||
@@ -410,14 +406,13 @@ DankPopout {
|
||||
property bool adaptiveColumns: false
|
||||
property int minCellWidth: 120
|
||||
property int maxCellWidth: 160
|
||||
property int cellPadding: 8
|
||||
property real iconSizeRatio: 0.6
|
||||
property int maxIconSize: 56
|
||||
property int minIconSize: 32
|
||||
property bool hoverUpdatesSelection: false
|
||||
property bool keyboardNavigationActive: appLauncher.keyboardNavigationActive
|
||||
property int baseCellWidth: adaptiveColumns ? Math.max(minCellWidth, Math.min(maxCellWidth, width / columns)) : (width - Theme.spacingS * 2) / columns
|
||||
property int baseCellHeight: baseCellWidth + 20
|
||||
property real baseCellWidth: adaptiveColumns ? Math.max(minCellWidth, Math.min(maxCellWidth, width / columns)) : width / columns
|
||||
property real baseCellHeight: baseCellWidth + 20
|
||||
property int actualColumns: adaptiveColumns ? Math.floor(width / cellWidth) : columns
|
||||
|
||||
property int remainingSpace: width - (actualColumns * cellWidth)
|
||||
@@ -438,16 +433,12 @@ DankPopout {
|
||||
}
|
||||
|
||||
anchors.fill: parent
|
||||
anchors.leftMargin: Theme.spacingS
|
||||
anchors.rightMargin: Theme.spacingS
|
||||
anchors.bottomMargin: Theme.spacingS
|
||||
visible: appLauncher.viewMode === "grid"
|
||||
model: appLauncher.model
|
||||
clip: true
|
||||
cellWidth: baseCellWidth
|
||||
cellHeight: baseCellHeight
|
||||
leftMargin: Math.max(Theme.spacingS, remainingSpace / 2)
|
||||
rightMargin: leftMargin
|
||||
focus: true
|
||||
interactive: true
|
||||
cacheBuffer: Math.max(0, Math.min(height * 2, 1000))
|
||||
@@ -472,7 +463,6 @@ DankPopout {
|
||||
gridView: appGrid
|
||||
cellWidth: appGrid.cellWidth
|
||||
cellHeight: appGrid.cellHeight
|
||||
cellPadding: appGrid.cellPadding
|
||||
minIconSize: appGrid.minIconSize
|
||||
maxIconSize: appGrid.maxIconSize
|
||||
iconSizeRatio: appGrid.iconSizeRatio
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import Quickshell
|
||||
import qs.Common
|
||||
import qs.Widgets
|
||||
|
||||
@@ -12,7 +10,6 @@ Rectangle {
|
||||
required property var gridView
|
||||
property int cellWidth: 120
|
||||
property int cellHeight: 120
|
||||
property int cellPadding: 8
|
||||
property int minIconSize: 32
|
||||
property int maxIconSize: 64
|
||||
property real iconSizeRatio: 0.5
|
||||
@@ -31,10 +28,10 @@ Rectangle {
|
||||
|
||||
signal itemClicked(int index, var modelData)
|
||||
signal itemRightClicked(int index, var modelData, real mouseX, real mouseY)
|
||||
signal keyboardNavigationReset()
|
||||
signal keyboardNavigationReset
|
||||
|
||||
width: cellWidth - cellPadding
|
||||
height: cellHeight - cellPadding
|
||||
width: cellWidth
|
||||
height: cellHeight
|
||||
radius: Theme.cornerRadius
|
||||
color: currentIndex === index ? Theme.withAlpha(Theme.surfaceContainerHighest, Theme.popupTransparency) : mouseArea.containsMouse ? Theme.withAlpha(Theme.surfaceContainerHighest, Theme.popupTransparency) : "transparent"
|
||||
|
||||
@@ -87,27 +84,27 @@ Rectangle {
|
||||
z: 10
|
||||
onEntered: {
|
||||
if (root.hoverUpdatesSelection && !root.keyboardNavigationActive)
|
||||
root.gridView.currentIndex = root.index
|
||||
root.gridView.currentIndex = root.index;
|
||||
}
|
||||
onPositionChanged: {
|
||||
root.keyboardNavigationReset()
|
||||
root.keyboardNavigationReset();
|
||||
}
|
||||
onClicked: mouse => {
|
||||
if (mouse.button === Qt.LeftButton) {
|
||||
root.itemClicked(root.index, root.model)
|
||||
root.itemClicked(root.index, root.model);
|
||||
}
|
||||
}
|
||||
onPressAndHold: mouse => {
|
||||
if (!root.isPlugin) {
|
||||
const globalPos = mapToItem(null, mouse.x, mouse.y)
|
||||
root.itemRightClicked(root.index, root.model, globalPos.x, globalPos.y)
|
||||
const globalPos = mapToItem(null, mouse.x, mouse.y);
|
||||
root.itemRightClicked(root.index, root.model, globalPos.x, globalPos.y);
|
||||
}
|
||||
}
|
||||
onPressed: mouse => {
|
||||
if (mouse.button === Qt.RightButton && !root.isPlugin) {
|
||||
const globalPos = mapToItem(null, mouse.x, mouse.y)
|
||||
root.itemRightClicked(root.index, root.model, globalPos.x, globalPos.y)
|
||||
mouse.accepted = true
|
||||
const globalPos = mapToItem(null, mouse.x, mouse.y);
|
||||
root.itemRightClicked(root.index, root.model, globalPos.x, globalPos.y);
|
||||
mouse.accepted = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user