Skip to content

Commit

Permalink
Move RichTextAction views into enum namespace
Browse files Browse the repository at this point in the history
  • Loading branch information
danielsaidi committed Jan 17, 2024
1 parent c47e01f commit 85b3b60
Show file tree
Hide file tree
Showing 15 changed files with 319 additions and 304 deletions.
2 changes: 1 addition & 1 deletion Demo/macOS/EditorScreen.swift
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ struct EditorScreen: View {
}
.toolbar {
ToolbarItem(placement: .automatic) {
RichTextActionButtonStack(
RichTextAction.ButtonStack(
context: context,
actions: [.undo, .redo, .copy]
)
Expand Down
119 changes: 119 additions & 0 deletions Sources/RichTextKit/Actions/RichTextAction+Button.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
//
// RichTextActionButton.swift
// RichTextKit
//
// Created by Daniel Saidi on 2022-12-08.
// Copyright © 2022-2024 Daniel Saidi. All rights reserved.
//

import SwiftUI

public extension RichTextAction {

/**
This button can be used to trigger a ``RichTextAction``.

This renders a plain `Button`, which means that you can
use and configure it as a normal button.
*/
struct Button: View {

/**
Create a rich text action button.

- Parameters:
- action: The action to trigger.
- context: The context to affect.
- fillVertically: WhetherP or not fill up vertical space, by default `false`.
*/
public init(
action: RichTextAction,
context: RichTextContext,
fillVertically: Bool = false
) {
self.action = action
self._context = ObservedObject(wrappedValue: context)
self.fillVertically = fillVertically
}

private let action: RichTextAction
private let fillVertically: Bool

@ObservedObject
private var context: RichTextContext

public var body: some View {
SwiftUI.Button(action: triggerAction) {
action.icon
.frame(maxHeight: fillVertically ? .infinity : nil)
.contentShape(Rectangle())
}
.keyboardShortcut(for: action)
.accessibilityLabel(action.title)
.disabled(!context.canHandle(action))
}
}
}

private extension RichTextAction.Button {

func triggerAction() {
context.handle(action)
}
}

struct RichTextAction_Button_Previews: PreviewProvider {

struct Preview: View {

@StateObject
private var context = RichTextContext()

var body: some View {
HStack {
RichTextAction.Button(
action: .copy,
context: context,
fillVertically: true
)
RichTextAction.Button(
action: .redoLatestChange,
context: context,
fillVertically: true
)
RichTextAction.Button(
action: .undoLatestChange,
context: context,
fillVertically: true
)
RichTextAction.Button(
action: .stepFontSize(points: 1),
context: context,
fillVertically: true
)
RichTextAction.Button(
action: .stepFontSize(points: -1),
context: context,
fillVertically: true
)
RichTextAction.Button(
action: .decreaseIndent(),
context: context,
fillVertically: true
)
RichTextAction.Button(
action: .increaseIndent(),
context: context,
fillVertically: true
)
}
.fixedSize(horizontal: false, vertical: true)
.padding()
.buttonStyle(.bordered)
}
}

static var previews: some View {
Preview()
}
}
102 changes: 102 additions & 0 deletions Sources/RichTextKit/Actions/RichTextAction+ButtonGroup.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
//
// RichTextActionButtonGroup.swift
// RichTextKit
//
// Created by Daniel Saidi on 2022-12-08.
// Copyright © 2022-2024 Daniel Saidi. All rights reserved.
//

#if iOS || macOS || os(visionOS)
import SwiftUI

public extension RichTextAction {

/**
This view lists ``RichTextAction`` buttons in a group.

Since this view uses multiple values, it binds directly
to a ``RichTextContext`` instead of individual values.
*/
struct ButtonGroup: View {

/**
Create a rich text action button stack.

- Parameters:
- context: The context to affect.
- actions: The actions to list, by default all non-size actions.
- greedy: Whether or not the group is horizontally greedy, by default `true`.
*/
public init(
context: RichTextContext,
actions: [RichTextAction],
greedy: Bool = true
) {
self._context = ObservedObject(wrappedValue: context)
self.actions = actions
self.isGreedy = greedy
}

private let actions: [RichTextAction]
private let isGreedy: Bool

@ObservedObject
private var context: RichTextContext

public var body: some View {
ControlGroup {
ForEach(actions) {
RichTextAction.Button(
action: $0,
context: context,
fillVertically: true
)
}
}
.frame(width: groupWidth)
}
}
}

private extension RichTextAction.ButtonGroup {

var groupWidth: CGFloat? {
if isGreedy { return nil }
let count = Double(actions.count)
#if macOS
return 30 * count
#else
return 50 * count
#endif
}
}

struct RichTextAction_ButtonGroup_Previews: PreviewProvider {

struct Preview: View {

@StateObject
private var context = RichTextContext()

func group(greedy: Bool) -> some View {
RichTextAction.ButtonGroup(
context: context,
actions: [.undoLatestChange, .redoLatestChange, .copy],
greedy: greedy
)
}

var body: some View {
VStack {
group(greedy: true)
group(greedy: false)
}
.padding()
}
}

static var previews: some View {
Preview()
}
}
#endif
80 changes: 80 additions & 0 deletions Sources/RichTextKit/Actions/RichTextAction+ButtonStack.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
//
// RichTextAction+ButtonStack.swift
// RichTextKit
//
// Created by Daniel Saidi on 2023-06-01.
// Copyright © 2023-2024 Daniel Saidi. All rights reserved.
//

import SwiftUI

public extension RichTextAction {

/**
This view lists ``RichTextAction`` buttons in a stack.

Since this view controls multiple values, it binds directly
to a ``RichTextContext`` instead of to individual values.
*/
struct ButtonStack: View {

/**
Create a rich text action button stack.

- Parameters:
- context: The context to affect.
- actions: The actions to list, by default all non-size actions.
- spacing: The spacing to apply to stack items, by default `5`.
*/
public init(
context: RichTextContext,
actions: [RichTextAction],
spacing: Double = 5
) {
self._context = ObservedObject(wrappedValue: context)
self.actions = actions
self.spacing = spacing
}

private let actions: [RichTextAction]
private let spacing: Double

@ObservedObject
private var context: RichTextContext

public var body: some View {
HStack(spacing: spacing) {
ForEach(actions) {
RichTextAction.Button(
action: $0,
context: context,
fillVertically: true
).frame(maxHeight: .infinity)
}
}
.fixedSize(horizontal: false, vertical: true)
}
}
}

struct RichTextAction_ButtonStack_Previews: PreviewProvider {

struct Preview: View {

@StateObject
private var context = RichTextContext()

var body: some View {
RichTextAction.ButtonStack(
context: context,
actions: [.undoLatestChange, .redoLatestChange, .copy]
)
.buttonStyle(.bordered)
.padding()
}
}

static var previews: some View {
Preview()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// RichTextKit
//
// Created by Daniel Saidi on 2022-12-13.
// Copyright © 2022-2023 Daniel Saidi. All rights reserved.
// Copyright © 2022-2024 Daniel Saidi. All rights reserved.
//

import SwiftUI
Expand Down
2 changes: 1 addition & 1 deletion Sources/RichTextKit/Actions/RichTextAction.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// RichTextKit
//
// Created by Daniel Saidi on 2022-12-08.
// Copyright © 2022-2023 Daniel Saidi. All rights reserved.
// Copyright © 2022-2024 Daniel Saidi. All rights reserved.
//

import SwiftUI
Expand Down
Loading

0 comments on commit 85b3b60

Please sign in to comment.