Skip to content

Commit

Permalink
#94 Initial ability to apply custom window padding
Browse files Browse the repository at this point in the history
  • Loading branch information
MrKai77 committed Feb 2, 2024
1 parent 9ea8e31 commit 113b521
Show file tree
Hide file tree
Showing 13 changed files with 298 additions and 34 deletions.
26 changes: 25 additions & 1 deletion Loop.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,10 @@
A8D5A7D62A91384D004EA5BB /* DirectionSelectorSquareSegment.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8D5A7D52A91384D004EA5BB /* DirectionSelectorSquareSegment.swift */; };
A8D5A7D82A913862004EA5BB /* DirectionSelectorCircleSegment.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8D5A7D72A913862004EA5BB /* DirectionSelectorCircleSegment.swift */; };
A8D5A7DA2A913B4C004EA5BB /* RadialMenuDirectionSelectorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8D5A7D92A913B4C004EA5BB /* RadialMenuDirectionSelectorView.swift */; };
A8D6D2FF2B6C87F80061B11F /* PaddingConfigurationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8D6D2FE2B6C87F80061B11F /* PaddingConfigurationView.swift */; };
A8D6D3012B6C894C0061B11F /* PaddingModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8D6D3002B6C894C0061B11F /* PaddingModel.swift */; };
A8D6D3032B6C8D750061B11F /* PaddingPreviewView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8D6D3022B6C8D750061B11F /* PaddingPreviewView.swift */; };
A8D6D3052B6C92F20061B11F /* WallpaperView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8D6D3042B6C92F20061B11F /* WallpaperView.swift */; };
A8DCC97B2980D5F500D41065 /* Defaults in Frameworks */ = {isa = PBXBuildFile; productRef = A8DCC97A2980D5F500D41065 /* Defaults */; };
A8DCC9882981B9E100D41065 /* RadialMenuSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8DCC9872981B9E100D41065 /* RadialMenuSettingsView.swift */; };
A8DCC98A2981F43F00D41065 /* PreviewSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8DCC9892981F43F00D41065 /* PreviewSettingsView.swift */; };
Expand Down Expand Up @@ -141,6 +145,10 @@
A8D5A7D52A91384D004EA5BB /* DirectionSelectorSquareSegment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DirectionSelectorSquareSegment.swift; sourceTree = "<group>"; };
A8D5A7D72A913862004EA5BB /* DirectionSelectorCircleSegment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DirectionSelectorCircleSegment.swift; sourceTree = "<group>"; };
A8D5A7D92A913B4C004EA5BB /* RadialMenuDirectionSelectorView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadialMenuDirectionSelectorView.swift; sourceTree = "<group>"; };
A8D6D2FE2B6C87F80061B11F /* PaddingConfigurationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PaddingConfigurationView.swift; sourceTree = "<group>"; };
A8D6D3002B6C894C0061B11F /* PaddingModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PaddingModel.swift; sourceTree = "<group>"; };
A8D6D3022B6C8D750061B11F /* PaddingPreviewView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PaddingPreviewView.swift; sourceTree = "<group>"; };
A8D6D3042B6C92F20061B11F /* WallpaperView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WallpaperView.swift; sourceTree = "<group>"; };
A8DCC9872981B9E100D41065 /* RadialMenuSettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadialMenuSettingsView.swift; sourceTree = "<group>"; };
A8DCC9892981F43F00D41065 /* PreviewSettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreviewSettingsView.swift; sourceTree = "<group>"; };
A8E1575E298654960005761C /* AboutView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AboutView.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -184,6 +192,8 @@
A80900D32AA3F9F20085C63B /* VisualEffectView.swift */,
A85B560D2AAAD62C00386ACE /* EventMonitor.swift */,
A86B97AC2AB79E2500099D7F /* ShakeEffect.swift */,
A8D6D3002B6C894C0061B11F /* PaddingModel.swift */,
A8D6D3042B6C92F20061B11F /* WallpaperView.swift */,
A8063A722B19891900EAB3D9 /* grid.metal */,
);
path = Utilities;
Expand Down Expand Up @@ -273,8 +283,8 @@
isa = PBXGroup;
children = (
A84497C82B393595003D4CF3 /* CustomKeybindView.swift */,
A84497CC2B3A52C7003D4CF3 /* PreviewWindowButton.swift */,
A84497CA2B395D8C003D4CF3 /* AnchorPicker.swift */,
A84497CC2B3A52C7003D4CF3 /* PreviewWindowButton.swift */,
);
path = "Custom Keybinds";
sourceTree = "<group>";
Expand Down Expand Up @@ -324,6 +334,7 @@
children = (
A8063A6D2B19599D00EAB3D9 /* SettingsView.swift */,
A882660729809F6F00BCB197 /* GeneralSettingsView.swift */,
A8D6D3062B6C99C10061B11F /* Padding */,
A8DCC9872981B9E100D41065 /* RadialMenuSettingsView.swift */,
A8DCC9892981F43F00D41065 /* PreviewSettingsView.swift */,
A84497CE2B3A57E8003D4CF3 /* Keybindings */,
Expand All @@ -349,6 +360,15 @@
path = "Custom Window Sizes";
sourceTree = "<group>";
};
A8D6D3062B6C99C10061B11F /* Padding */ = {
isa = PBXGroup;
children = (
A8D6D2FE2B6C87F80061B11F /* PaddingConfigurationView.swift */,
A8D6D3022B6C8D750061B11F /* PaddingPreviewView.swift */,
);
path = Padding;
sourceTree = "<group>";
};
A8E59C2C297F5E9A0064D4BA = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -513,12 +533,14 @@
A8D5A7D62A91384D004EA5BB /* DirectionSelectorSquareSegment.swift in Sources */,
A8BE09DB2B113FD700DBB242 /* KeycorderModel.swift in Sources */,
A82521EC29E234EB00139654 /* AboutViewController.swift in Sources */,
A8D6D3012B6C894C0061B11F /* PaddingModel.swift in Sources */,
A86DAE2C2B3E31F800B968F0 /* CustomCyclingKeybindItemView.swift in Sources */,
A82DDBDE2AEC736300D7F974 /* AnimationConfiguration.swift in Sources */,
A84497CD2B3A52C7003D4CF3 /* PreviewWindowButton.swift in Sources */,
A8789F6729805B190040512E /* RadialMenuView.swift in Sources */,
A8330ABD2A3AC0CA00673C8D /* Bundle+Extensions.swift in Sources */,
A86B97AD2AB79E2500099D7F /* ShakeEffect.swift in Sources */,
A8D6D3032B6C8D750061B11F /* PaddingPreviewView.swift in Sources */,
A82740982AB00FCE00B9BDC5 /* Color+Extensions.swift in Sources */,
A869C1A12B38C6E600AD1A84 /* StageManager.swift in Sources */,
A8DCC9882981B9E100D41065 /* RadialMenuSettingsView.swift in Sources */,
Expand All @@ -528,6 +550,7 @@
A80900D52AA3F9F30085C63B /* VisualEffectView.swift in Sources */,
A8330AC12A3AC13100673C8D /* Defaults+Extensions.swift in Sources */,
A80900D42AA3F9F30085C63B /* BetaIndicator.swift in Sources */,
A8D6D2FF2B6C87F80061B11F /* PaddingConfigurationView.swift in Sources */,
A8E1575F298654960005761C /* AboutView.swift in Sources */,
A8DCC98A2981F43F00D41065 /* PreviewSettingsView.swift in Sources */,
A87376F62AA288EB001890F4 /* Window.swift in Sources */,
Expand All @@ -551,6 +574,7 @@
A86CB7332A3D22E7006A78F2 /* WindowEngine.swift in Sources */,
A8E59C39297F5E9A0064D4BA /* LoopApp.swift in Sources */,
A8330ACB2A3AC1C000673C8D /* Angle+Extensions.swift in Sources */,
A8D6D3052B6C92F20061B11F /* WallpaperView.swift in Sources */,
A8F0125D2AEDFEC70017307F /* KeybindingsSettingsView.swift in Sources */,
A864F4682AA660CD00579738 /* WindowDragManager.swift in Sources */,
A8504D2D2A85832F00C2EFDA /* SoftwareUpdater.swift in Sources */,
Expand Down
2 changes: 1 addition & 1 deletion Loop/Extensions/Defaults+Extensions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ extension Defaults.Keys {
static let timesLooped = Key<Int>("timesLooped", default: 0)
static let windowSnapping = Key<Bool>("windowSnapping", default: false) // BETA
static let animateWindowResizes = Key<Bool>("animateWindowResizes", default: false) // BETA
static let windowPadding = Key<CGFloat>("windowPadding", default: 0)
static let padding = Key<PaddingModel>("padding", default: PaddingModel.defaultConfig)
static let restoreWindowFrameOnDrag = Key<Bool>("restoreWindowFrameOnDrag", default: true)
static let resizeWindowUnderCursor = Key<Bool>("resizeWindowUnderCursor", default: false)

Expand Down
8 changes: 6 additions & 2 deletions Loop/Preview Window/PreviewView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ struct PreviewView: View {

@Default(.useGradient) var useGradient
@Default(.previewPadding) var previewPadding
@Default(.windowPadding) var windowPadding
@Default(.padding) var padding
@Default(.previewCornerRadius) var previewCornerRadius
@Default(.previewBorderThickness) var previewBorderThickness
@Default(.animationConfiguration) var animationConfiguration
Expand All @@ -52,7 +52,11 @@ struct PreviewView: View {
lineWidth: previewBorderThickness
)
}
.padding(windowPadding + previewPadding + previewBorderThickness / 2)
.padding(previewPadding + previewBorderThickness / 2)
.padding(.top, padding.top)
.padding(.bottom, padding.bottom)
.padding(.leading, padding.left)
.padding(.trailing, padding.right)

.frame(
width: self.currentAction.previewWindowWidth(geo.size.width, window),
Expand Down
19 changes: 12 additions & 7 deletions Loop/Settings/GeneralSettingsView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ struct GeneralSettingsView: View {
@Default(.notificationWhenIconUnlocked) var notificationWhenIconUnlocked
@Default(.timesLooped) var timesLooped
@Default(.animateWindowResizes) var animateWindowResizes
@Default(.windowPadding) var windowPadding
@Default(.padding) var padding
@Default(.windowSnapping) var windowSnapping
@Default(.animationConfiguration) var animationConfiguration
@Default(.restoreWindowFrameOnDrag) var restoreWindowFrameOnDrag
Expand All @@ -32,6 +32,8 @@ struct GeneralSettingsView: View {
@State var userDisabledLoopNotifications: Bool = false
@State var iconFooter: String?

@State var isConfiguringPadding: Bool = false

var body: some View {
Form {
Section("Behavior") {
Expand Down Expand Up @@ -76,12 +78,15 @@ struct GeneralSettingsView: View {
}
}

Slider(value: $windowPadding,
in: 0...50,
step: 5,
minimumValueLabel: Text("0px"),
maximumValueLabel: Text("50px")) {
Text("Window Padding")
HStack {
Text("Padding")
Spacer()
Button("Configure…") {
self.isConfiguringPadding = true
}
}
.sheet(isPresented: self.$isConfiguringPadding) {
PaddingConfigurationView(isSheetShown: $isConfiguringPadding, paddingModel: $padding)
}

Toggle(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ struct CustomCyclingKeybindView: View {
}
.frame(width: 450)
.fixedSize(horizontal: false, vertical: true)
.background(.background)

.onAppear {
self.cycleDirections = self.action.cycle ?? []
Expand Down
10 changes: 0 additions & 10 deletions Loop/Settings/Keybindings/Custom Keybinds/AnchorPicker.swift
Original file line number Diff line number Diff line change
Expand Up @@ -43,17 +43,7 @@ struct AnchorPicker: View {
}
}
.animation(.snappy, value: self.anchor)
.aspectRatio(16/10, contentMode: .fit)
.padding(8)
.background {
if let screen = NSScreen.screenWithMouse,
let url = NSWorkspace.shared.desktopImageURL(for: screen),
let image = NSImage(contentsOf: url) {
Image(nsImage: image)
.resizable()
.aspectRatio(contentMode: .fill)
}
}
}

@ViewBuilder
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,13 @@ struct CustomKeybindView: View {
}

Section {
AnchorPicker(anchor: self.$action.anchor)
.ignoresSafeArea()
.padding(-10)
ZStack {
WallpaperView().equatable()
AnchorPicker(anchor: self.$action.anchor)
}
.ignoresSafeArea()
.padding(-10)
.aspectRatio(16/10, contentMode: .fit)
}

if self.action.anchor == .center || self.action.anchor == .macOSCenter {
Expand Down Expand Up @@ -133,6 +137,7 @@ struct CustomKeybindView: View {
}
.frame(width: 400)
.fixedSize(horizontal: false, vertical: true)
.background(.background)

.onAppear {
if self.action.measureSystem == nil {
Expand Down
131 changes: 131 additions & 0 deletions Loop/Settings/Padding/PaddingConfigurationView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
//
// PaddingConfigurationView.swift
// Loop
//
// Created by Kai Azim on 2024-02-01.
//

import SwiftUI

struct PaddingConfigurationView: View {
@Binding var isSheetShown: Bool
@Binding var paddingModel: PaddingModel
@State var useSteppers: Bool = false

var body: some View {
VStack {
Form {
Section("Padding") {
Toggle("Custom Screen Padding", isOn: $paddingModel.configureScreenPadding)
Toggle("Use Custom Values", isOn: $useSteppers)
}

Section(content: {
ZStack {
WallpaperView().equatable()
PaddingPreviewView($paddingModel)
}
.ignoresSafeArea()
.padding(-10)
.aspectRatio(16/10, contentMode: .fit)
}, footer: {
HStack {
Text("This preview is not to scale.")
.font(.caption)
.foregroundStyle(.secondary)
Spacer()
}
})

if paddingModel.configureScreenPadding {
Section {
paddingAdjuster("Window Gaps", value: $paddingModel.window.toDoubleBinding())
}

Section("Screen Padding") {
paddingAdjuster("Top", value: $paddingModel.top.toDoubleBinding())
paddingAdjuster("Bottom", value: $paddingModel.bottom.toDoubleBinding())
paddingAdjuster("Right", value: $paddingModel.right.toDoubleBinding())
paddingAdjuster("Left", value: $paddingModel.left.toDoubleBinding())
}
} else {
paddingAdjuster(
"Padding",
value: Binding(
get: {
paddingModel.window
},
set: {
paddingModel.window = $0
paddingModel.top = $0
paddingModel.bottom = $0
paddingModel.right = $0
paddingModel.left = $0
}
)
)
}
}
.formStyle(.grouped)
.scrollDisabled(true)

HStack {
Button {
isSheetShown = false
} label: {
Text("Done")
}
.controlSize(.large)
}
.offset(y: -14)
}
.frame(width: 400)
.fixedSize(horizontal: false, vertical: true)
.background(.background)
}

@ViewBuilder
func paddingAdjuster(_ title: String, value: Binding<Double>) -> some View {
if self.useSteppers {
paddingStepper(title, value: value)
} else {
paddingSlider(title, value: value)
}
}

@ViewBuilder
func paddingSlider(_ title: String, value: Binding<Double>) -> some View {
Slider(
value: value,
in: 0...50,
step: 5,
minimumValueLabel: Text("0px"),
maximumValueLabel: Text("50px")
) {
Text(title)
}
}

@ViewBuilder
func paddingStepper(_ title: String, value: Binding<Double>) -> some View {
HStack {
Stepper(
title,
value: value,
in: 0...100,
format: .number
)
Text("px")
}
}
}

extension Binding where Value == CGFloat {
fileprivate func toDoubleBinding() -> Binding<Double> {
Binding<Double>(get: {
Double(self.wrappedValue)
}, set: {
self.wrappedValue = CGFloat($0)
})
}
}
44 changes: 44 additions & 0 deletions Loop/Settings/Padding/PaddingPreviewView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
//
// PaddingPreviewView.swift
// Loop
//
// Created by Kai Azim on 2024-02-01.
//

import SwiftUI

struct PaddingPreviewView: View {

@Binding var paddingModel: PaddingModel

init(_ paddingModel: Binding<PaddingModel>) {
self._paddingModel = paddingModel
}

var body: some View {
ZStack {
HStack(spacing: paddingModel.window) {
blurredWindow()

VStack(spacing: paddingModel.window) {
blurredWindow()
blurredWindow()
}
}
.padding(.top, paddingModel.top)
.padding(.bottom, paddingModel.bottom)
.padding(.leading, paddingModel.right)
.padding(.trailing, paddingModel.left)
}
}

@ViewBuilder
func blurredWindow() -> some View {
VisualEffectView(material: .hudWindow, blendingMode: .withinWindow)
.overlay {
RoundedRectangle(cornerRadius: 10)
.strokeBorder(.white.opacity(0.1), lineWidth: 2)
}
.clipShape(.rect(cornerRadius: 10))
}
}
Loading

0 comments on commit 113b521

Please sign in to comment.