SSPreferences // Troubleshoot the text overflow issues, etc.

This commit is contained in:
ShikiSuen 2023-03-04 19:48:36 +08:00
parent 58da06bad0
commit 25cf9bfbf8
4 changed files with 65 additions and 30 deletions

View File

@ -8,4 +8,4 @@
See its original repository for details: https://github.com/sindresorhus/Preferences/
Note: In vChewing IME, this module is renamed to SSPreferences due to potential namespace conflicts with InputMethodKit's own method of implementing system preferences pane.
Note: In vChewing IME, this module is renamed to SSPreferences due to potential namespace conflicts with InputMethodKit's own method of implementing system preferences pane. Also, this module has been heavily modded for vChewing-specific necessities.

View File

@ -47,30 +47,28 @@ public extension SSPreferences {
public var body: some View {
let sections = sectionBuilder()
let labelWidth = max(minimumLabelWidth, maximumLabelWidth)
return VStack(alignment: .preferenceSectionLabel) {
ForEach(0 ..< sections.count, id: \.self) { index in
viewForSection(sections, index: index)
if sections[index].label != nil {
sections[index].bodyLimited(rightPaneWidth: contentWidth - labelWidth)
} else {
sections[index]
.alignmentGuide(.preferenceSectionLabel) { $0[.leading] + labelWidth }
}
if sections[index].bottomDivider, index < sections.count - 1 {
Divider()
.frame(height: 10)
.alignmentGuide(.preferenceSectionLabel) { $0[.leading] + labelWidth }
}
}
}
.modifier(Section.LabelWidthModifier(maximumWidth: $maximumLabelWidth))
.frame(width: Double(contentWidth), alignment: .leading)
.frame(width: contentWidth, alignment: .leading)
.padding(.vertical, 20)
.padding(.horizontal, 30)
}
@ViewBuilder
private func viewForSection(_ sections: [Section], index: Int) -> some View {
sections[index]
if index != sections.count - 1, sections[index].bottomDivider {
Divider()
// Strangely doesn't work without width being specified. Probably because of custom alignment.
.frame(width: Double(contentWidth), height: 20)
.alignmentGuide(.preferenceSectionLabel) {
$0[.leading] + Double(max(minimumLabelWidth, maximumLabelWidth))
}
}
}
}
}

View File

@ -92,5 +92,6 @@ public extension View {
font(.system(size: 11.0))
// TODO: Use `.foregroundStyle` when targeting macOS 12.
.foregroundColor(.secondary)
.frame(maxWidth: .infinity, alignment: .leading)
}
}

View File

@ -51,11 +51,33 @@ public extension SSPreferences {
}
}
public let label: AnyView
public private(set) var label: AnyView?
public let content: AnyView
public let bottomDivider: Bool
public let verticalAlignment: VerticalAlignment
/**
A section is responsible for controlling a single preference without Label.
- Parameters:
- bottomDivider: Whether to place a `Divider` after the section content. Default is `false`.
- verticalAlignement: The vertical alignment of the section content.
- verticalAlignment:
- label: A view describing preference handled by this section.
- content: A content view.
*/
public init<Content: View>(
bottomDivider: Bool = false,
verticalAlignment: VerticalAlignment = .firstTextBaseline,
@ViewBuilder content: @escaping () -> Content
) {
label = nil
self.bottomDivider = bottomDivider
self.verticalAlignment = verticalAlignment
let stack = VStack(alignment: .leading) { content() }
self.content = stack.eraseToAnyView()
}
/**
A section is responsible for controlling a single preference.
@ -92,33 +114,47 @@ public extension SSPreferences {
- content: A content view.
*/
public init<Content: View>(
title: String,
title: String? = nil,
bottomDivider: Bool = false,
verticalAlignment: VerticalAlignment = .firstTextBaseline,
@ViewBuilder content: @escaping () -> Content
) {
let textLabel = {
Text(title)
.font(.system(size: 13.0))
.overlay(LabelOverlay())
.eraseToAnyView()
if let title = title {
let textLabel = {
Text(title)
.font(.system(size: 13.0))
.overlay(LabelOverlay())
.eraseToAnyView()
}
self.init(
bottomDivider: bottomDivider,
verticalAlignment: verticalAlignment,
label: textLabel,
content: content
)
return
}
self.init(
bottomDivider: bottomDivider,
verticalAlignment: verticalAlignment,
label: textLabel,
content: content
)
}
public var body: some View {
public func bodyLimited(rightPaneWidth: CGFloat? = nil) -> some View {
HStack(alignment: verticalAlignment) {
label
.alignmentGuide(.preferenceSectionLabel) { $0[.trailing] }
content
Spacer()
if let label = label {
label.alignmentGuide(.preferenceSectionLabel) { $0[.trailing] }
}
HStack {
content
Spacer()
}.frame(maxWidth: rightPaneWidth)
}
}
public var body: some View {
bodyLimited()
}
}
}