Skip to content

Commit

Permalink
Add Primary/Secondary/Tertiary/QuaternaryContentStyle (#419)
Browse files Browse the repository at this point in the history
  • Loading branch information
carson-katri committed Jul 7, 2021
1 parent 4a7748a commit 2efa80a
Show file tree
Hide file tree
Showing 9 changed files with 195 additions and 22 deletions.
5 changes: 4 additions & 1 deletion Sources/TokamakCore/Shapes/ShapeStyles/BackgroundStyle.swift
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,9 @@ public extension View {
}

public func modifyEnvironment(_ values: inout EnvironmentValues) {
values._backgroundStyle = .init(styles: [style, style, style], environment: values)
values._backgroundStyle = .init(
styles: (primary: style, secondary: style, tertiary: style),
environment: values
)
}
}
104 changes: 104 additions & 0 deletions Sources/TokamakCore/Shapes/ShapeStyles/ContentStyles.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
// Copyright 2020-2021 Tokamak contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Created by Carson Katri on 7/7/21.
//

@frozen public struct PrimaryContentStyle {
@inlinable
public init() {}
}

extension PrimaryContentStyle: ShapeStyle {
public func _apply(to shape: inout _ShapeStyle_Shape) {
if !shape.inRecursiveStyle,
let foregroundStyle = shape.environment._foregroundStyle
{
if foregroundStyle.styles.primary is Self {
shape.inRecursiveStyle = true
}
foregroundStyle.styles.primary._apply(to: &shape)
} else {
shape.result = .color(shape.environment.foregroundColor ?? .primary)
}
}

public static func _apply(to shape: inout _ShapeStyle_ShapeType) {}
}

@frozen public struct SecondaryContentStyle {
@inlinable
public init() {}
}

extension SecondaryContentStyle: ShapeStyle {
public func _apply(to shape: inout _ShapeStyle_Shape) {
if !shape.inRecursiveStyle,
let foregroundStyle = shape.environment._foregroundStyle
{
if foregroundStyle.styles.secondary is Self {
shape.inRecursiveStyle = true
}
foregroundStyle.styles.secondary._apply(to: &shape)
} else {
shape.result = .color((shape.environment.foregroundColor ?? .primary).opacity(0.5))
}
}

public static func _apply(to shape: inout _ShapeStyle_ShapeType) {}
}

@frozen public struct TertiaryContentStyle {
@inlinable
public init() {}
}

extension TertiaryContentStyle: ShapeStyle {
public func _apply(to shape: inout _ShapeStyle_Shape) {
if !shape.inRecursiveStyle,
let foregroundStyle = shape.environment._foregroundStyle
{
if foregroundStyle.styles.tertiary is Self {
shape.inRecursiveStyle = true
}
foregroundStyle.styles.tertiary._apply(to: &shape)
} else {
shape.result = .color((shape.environment.foregroundColor ?? .primary).opacity(0.3))
}
}

public static func _apply(to shape: inout _ShapeStyle_ShapeType) {}
}

@frozen public struct QuaternaryContentStyle {
@inlinable
public init() {}
}

extension QuaternaryContentStyle: ShapeStyle {
public func _apply(to shape: inout _ShapeStyle_Shape) {
if !shape.inRecursiveStyle,
let foregroundStyle = shape.environment._foregroundStyle
{
if foregroundStyle.styles.tertiary is Self {
shape.inRecursiveStyle = true
}
foregroundStyle.styles.tertiary._apply(to: &shape)
} else {
shape.result = .color((shape.environment.foregroundColor ?? .primary).opacity(0.2))
}
}

public static func _apply(to shape: inout _ShapeStyle_ShapeType) {}
}
28 changes: 20 additions & 8 deletions Sources/TokamakCore/Shapes/ShapeStyles/ForegroundStyle.swift
Original file line number Diff line number Diff line change
Expand Up @@ -60,24 +60,36 @@ public extension View {
}

@inlinable
func foregroundStyle<S1, S2, S3>(_ primary: S1, _ secondary: S2,
_ tertiary: S3) -> some View
func foregroundStyle<S1, S2, S3>(
_ primary: S1,
_ secondary: S2,
_ tertiary: S3
) -> some View
where S1: ShapeStyle, S2: ShapeStyle, S3: ShapeStyle
{
modifier(_ForegroundStyleModifier(styles: [primary, secondary, tertiary]))
modifier(_ForegroundStyleModifier(primary: primary, secondary: secondary, tertiary: tertiary))
}
}

@frozen public struct _ForegroundStyleModifier: ViewModifier, EnvironmentModifier {
public var styles: [ShapeStyle]
@frozen public struct _ForegroundStyleModifier<Primary, Secondary, Tertiary>: ViewModifier,
EnvironmentModifier
where Primary: ShapeStyle, Secondary: ShapeStyle, Tertiary: ShapeStyle
{
public var primary: Primary
public var secondary: Secondary
public var tertiary: Tertiary

@inlinable
public init(styles: [ShapeStyle]) {
self.styles = styles
public init(
primary: Primary,
secondary: Secondary,
tertiary: Tertiary
) {
(self.primary, self.secondary, self.tertiary) = (primary, secondary, tertiary)
}

public typealias Body = Never
public func modifyEnvironment(_ values: inout EnvironmentValues) {
values._foregroundStyle = .init(styles: styles, environment: values)
values._foregroundStyle = .init(styles: (primary, secondary, tertiary), environment: values)
}
}
28 changes: 15 additions & 13 deletions Sources/TokamakCore/Shapes/ShapeStyles/ShapeStyle.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,23 +23,23 @@ public protocol ShapeStyle {
}

public struct AnyShapeStyle: ShapeStyle {
let styles: [ShapeStyle]
let styles: (primary: ShapeStyle, secondary: ShapeStyle, tertiary: ShapeStyle)
var stylesArray: [ShapeStyle] {
[styles.primary, styles.secondary, styles.tertiary]
}

let environment: EnvironmentValues

public func _apply(to shape: inout _ShapeStyle_Shape) {
shape.environment = environment
if styles.count > 1 {
let results = styles.map { style -> _ShapeStyle_Shape.Result in
var copy = shape
style._apply(to: &copy)
return copy.result
}
shape
.result =
.resolved(.array(results.compactMap { $0.resolvedStyle(on: shape, in: environment) }))
} else if let first = styles.first {
first._apply(to: &shape)
let results = stylesArray.map { style -> _ShapeStyle_Shape.Result in
var copy = shape
style._apply(to: &copy)
return copy.result
}
shape
.result =
.resolved(.array(results.compactMap { $0.resolvedStyle(on: shape, in: environment) }))

switch shape.operation {
case let .prepare(text, level):
Expand All @@ -50,7 +50,9 @@ public struct AnyShapeStyle: ShapeStyle {
shape.result = .prepared(Text(storage: text.storage, modifiers: modifiers))
case let .resolveStyle(levels):
if case let .resolved(resolved) = shape.result {
if case let .array(children) = resolved {
if case let .array(children) = resolved,
children.count >= levels.upperBound
{
shape.result = .resolved(.array(.init(children[levels])))
}
} else if let resolved = shape.result.resolvedStyle(on: shape, in: environment) {
Expand Down
9 changes: 9 additions & 0 deletions Sources/TokamakDOM/Core.swift
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,16 @@ public typealias Rectangle = TokamakCore.Rectangle
public typealias RoundedRectangle = TokamakCore.RoundedRectangle
public typealias ContainerRelativeShape = TokamakCore.ContainerRelativeShape

// MARK: Shape Styles

public typealias PrimaryContentStyle = TokamakCore.PrimaryContentStyle
public typealias SecondaryContentStyle = TokamakCore.SecondaryContentStyle
public typealias TertiaryContentStyle = TokamakCore.TertiaryContentStyle
public typealias QuaternaryContentStyle = TokamakCore.QuaternaryContentStyle

public typealias ForegroundStyle = TokamakCore.ForegroundStyle
public typealias BackgroundStyle = TokamakCore.BackgroundStyle

public typealias Material = TokamakCore.Material

// MARK: Primitive values
Expand Down
12 changes: 12 additions & 0 deletions Sources/TokamakDemo/ShapeStyleDemo.swift
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,18 @@ struct ShapeStyleDemo: View {
}
}
}
HStack {
VStack {
Text("Primary")
.foregroundStyle(PrimaryContentStyle())
Text("Secondary")
.foregroundStyle(SecondaryContentStyle())
Text("Tertiary")
.foregroundStyle(TertiaryContentStyle())
Text("Quaternary")
.foregroundStyle(QuaternaryContentStyle())
}
}
#endif
}
}
9 changes: 9 additions & 0 deletions Sources/TokamakStaticHTML/Core.swift
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,16 @@ public typealias Rectangle = TokamakCore.Rectangle
public typealias RoundedRectangle = TokamakCore.RoundedRectangle
public typealias ContainerRelativeShape = TokamakCore.ContainerRelativeShape

// MARK: Shape Styles

public typealias PrimaryContentStyle = TokamakCore.PrimaryContentStyle
public typealias SecondaryContentStyle = TokamakCore.SecondaryContentStyle
public typealias TertiaryContentStyle = TokamakCore.TertiaryContentStyle
public typealias QuaternaryContentStyle = TokamakCore.QuaternaryContentStyle

public typealias ForegroundStyle = TokamakCore.ForegroundStyle
public typealias BackgroundStyle = TokamakCore.BackgroundStyle

public typealias Material = TokamakCore.Material

// MARK: Primitive values
Expand Down
22 changes: 22 additions & 0 deletions Tests/TokamakStaticHTMLTests/RenderingTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,28 @@ final class RenderingTests: XCTestCase {
)
}

func testContentStyles() {
assertSnapshot(
matching: HStack {
Rectangle()
.frame(width: 50, height: 50)
.foregroundStyle(PrimaryContentStyle())
Rectangle()
.frame(width: 50, height: 50)
.foregroundStyle(SecondaryContentStyle())
Rectangle()
.frame(width: 50, height: 50)
.foregroundStyle(TertiaryContentStyle())
Rectangle()
.frame(width: 50, height: 50)
.foregroundStyle(QuaternaryContentStyle())
}
.foregroundColor(.blue),
as: .image(size: .init(width: 275, height: 100)),
timeout: defaultSnapshotTimeout
)
}

func testMaterial() {
assertSnapshot(
matching: ZStack {
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 2efa80a

Please sign in to comment.