Skip to content

Commit

Permalink
Implement a basic scene graph (which so far only supports having a si…
Browse files Browse the repository at this point in the history
…ngle view) and update examples accordingly

This change was made to be able to introduce multi-windowing and get also get rid of the windowProperties
property currently required to configure the app's window. I've basically followed SwiftUI's API, but
probably not their implementation at all. This was so much easier to figure out after having grappled
with the ViewGraph for so long yesterday.
  • Loading branch information
stackotter committed Oct 23, 2023
1 parent 6e2298e commit 076ed5d
Show file tree
Hide file tree
Showing 25 changed files with 521 additions and 341 deletions.
14 changes: 8 additions & 6 deletions Examples/Counter/CounterApp.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,14 @@ struct CounterApp: App {

let windowProperties = WindowProperties(title: "CounterApp", resizable: true)

var body: some View {
HStack(spacing: 20) {
Button("-") { state.count -= 1 }
Text("Count: \(state.count)", wrap: false)
Button("+") { state.count += 1 }
var body: some Scene {
WindowGroup {
HStack(spacing: 20) {
Button("-") { state.count -= 1 }
Text("Count: \(state.count)", wrap: false)
Button("+") { state.count += 1 }
}
.padding(10)
}
.padding(10)
}
}
38 changes: 20 additions & 18 deletions Examples/FileViewer/FileViewerApp.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,25 +24,27 @@ struct FileViewerApp: App {
resizable: false
)

var body: some View {
#if canImport(FileDialog)
HStack {
VStack {
Text("Selected file: \(state.file?.path ?? "none")")

Button("Click") {
let dialog = FileDialog()
dialog.open { result in
guard case let .success(file) = result else {
return
var body: some Scene {
WindowGroup {
#if canImport(FileDialog)
HStack {
VStack {
Text("Selected file: \(state.file?.path ?? "none")")

Button("Click") {
let dialog = FileDialog()
dialog.open { result in
guard case let .success(file) = result else {
return
}
state.file = file
}
state.file = file
}
}
}.padding(10)
}
#else
Text("FileDialog requires Gtk 4.10")
#endif
}.padding(10)
}
#else
Text("FileDialog requires Gtk 4.10")
#endif
}
}
}
46 changes: 24 additions & 22 deletions Examples/GreetingGenerator/GreetingGenerator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,36 +16,38 @@ struct GreetingGeneratorApp: App {

let windowProperties = WindowProperties(title: "Greeting Generator")

var body: some View {
VStack {
TextField("Name", state.$name)
HStack {
Button("Generate") {
state.greetings.append("Hello, \(state.name)!")
}
Button("Reset") {
state.greetings = []
state.name = ""
var body: some Scene {
WindowGroup {
VStack {
TextField("Name", state.$name)
HStack {
Button("Generate") {
state.greetings.append("Hello, \(state.name)!")
}
Button("Reset") {
state.greetings = []
state.name = ""
}
}
}

if let latest = state.greetings.last {
Text(latest)
.padding(.top, 5)
if let latest = state.greetings.last {
Text(latest)
.padding(.top, 5)

if state.greetings.count > 1 {
Text("History:")
.padding(.top, 20)
if state.greetings.count > 1 {
Text("History:")
.padding(.top, 20)

ScrollView {
ForEach(state.greetings.reversed()[1...]) { greeting in
Text(greeting)
ScrollView {
ForEach(state.greetings.reversed()[1...]) { greeting in
Text(greeting)
}
}
.padding(.top, 8)
}
.padding(.top, 8)
}
}
.padding(10)
}
.padding(10)
}
}
91 changes: 48 additions & 43 deletions Examples/Navigation/NavigationApp.swift
Original file line number Diff line number Diff line change
Expand Up @@ -38,53 +38,58 @@ struct NavigationApp: App {
defaultSize: WindowProperties.Size(200, 250)
)

var body: some View {
NavigationStack(path: state.$path) {
Text("Learn about subject areas")
.padding(.bottom, 10)

NavigationLink("Science", value: SubjectArea.science, path: state.$path)
NavigationLink("Humanities", value: SubjectArea.humanities, path: state.$path)
}
.navigationDestination(for: SubjectArea.self) { area in
switch area {
case .science:
Text("Choose a science subject")
.padding(.bottom, 10)

NavigationLink("Physics", value: ScienceSubject.physics, path: state.$path)
NavigationLink("Chemistry", value: ScienceSubject.chemistry, path: state.$path)
case .humanities:
Text("Choose a humanities subject")
.padding(.bottom, 10)

NavigationLink("English", value: HumanitiesSubject.english, path: state.$path)
NavigationLink("History", value: HumanitiesSubject.history, path: state.$path)
var body: some Scene {
WindowGroup {
NavigationStack(path: state.$path) {
Text("Learn about subject areas")
.padding(.bottom, 10)

NavigationLink("Science", value: SubjectArea.science, path: state.$path)
NavigationLink("Humanities", value: SubjectArea.humanities, path: state.$path)
}

backButton
}
.navigationDestination(for: ScienceSubject.self) { subject in
switch subject {
case .physics:
Text("Physics is applied maths")
case .chemistry:
Text("Chemistry is applied physics")
.navigationDestination(for: SubjectArea.self) { area in
switch area {
case .science:
Text("Choose a science subject")
.padding(.bottom, 10)

NavigationLink("Physics", value: ScienceSubject.physics, path: state.$path)
NavigationLink(
"Chemistry", value: ScienceSubject.chemistry, path: state.$path)
case .humanities:
Text("Choose a humanities subject")
.padding(.bottom, 10)

NavigationLink(
"English", value: HumanitiesSubject.english, path: state.$path)
NavigationLink(
"History", value: HumanitiesSubject.history, path: state.$path)
}

backButton
}

backButton
}
.navigationDestination(for: HumanitiesSubject.self) { subject in
switch subject {
case .english:
Text("I don't like essays")
case .history:
Text("Don't repeat it")
.navigationDestination(for: ScienceSubject.self) { subject in
switch subject {
case .physics:
Text("Physics is applied maths")
case .chemistry:
Text("Chemistry is applied physics")
}

backButton
}

backButton
.navigationDestination(for: HumanitiesSubject.self) { subject in
switch subject {
case .english:
Text("I don't like essays")
case .history:
Text("Don't repeat it")
}

backButton
}
.padding(10)
}
.padding(10)
}

@ViewBuilder
Expand Down
64 changes: 33 additions & 31 deletions Examples/RandomNumberGenerator/RandomNumberGeneratorApp.swift
Original file line number Diff line number Diff line change
Expand Up @@ -38,40 +38,42 @@ struct RandomNumberGeneratorApp: App {
defaultSize: .init(500, 0)
)

var body: some View {
VStack {
Text("Random Number: \(state.randomNumber)")
Button("Generate") {
state.randomNumber = Int.random(in: Int(state.minNum)...Int(state.maxNum))
}
var body: some Scene {
WindowGroup {
VStack {
Text("Random Number: \(state.randomNumber)")
Button("Generate") {
state.randomNumber = Int.random(in: Int(state.minNum)...Int(state.maxNum))
}

Text("Minimum:")
Slider(
state.$minNum.onChange { newValue in
if newValue > state.maxNum {
state.minNum = state.maxNum
}
},
minimum: 0,
maximum: 100
)
Text("Minimum:")
Slider(
state.$minNum.onChange { newValue in
if newValue > state.maxNum {
state.minNum = state.maxNum
}
},
minimum: 0,
maximum: 100
)

Text("Maximum:")
Slider(
state.$maxNum.onChange { newValue in
if newValue < state.minNum {
state.maxNum = state.minNum
}
},
minimum: 0,
maximum: 100
)
Text("Maximum:")
Slider(
state.$maxNum.onChange { newValue in
if newValue < state.minNum {
state.maxNum = state.minNum
}
},
minimum: 0,
maximum: 100
)

Text("Choose a color:")
.padding(.top, 20)
Picker(of: ColorOption.allCases, selection: state.$colorOption)
Text("Choose a color:")
.padding(.top, 20)
Picker(of: ColorOption.allCases, selection: state.$colorOption)
}
.padding(10)
.foregroundColor(state.colorOption?.color ?? .red)
}
.padding(10)
.foregroundColor(state.colorOption?.color ?? .red)
}
}
14 changes: 8 additions & 6 deletions Examples/Split/SplitApp.swift
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,14 @@ struct SplitApp: App {
defaultSize: WindowProperties.Size(600, 250)
)

var body: some View {
switch state.columns {
case .two:
doubleColumn
case .three:
tripleColumn
var body: some Scene {
WindowGroup {
switch state.columns {
case .two:
doubleColumn
case .three:
tripleColumn
}
}
}

Expand Down
18 changes: 10 additions & 8 deletions Examples/Spreadsheet/SpreadsheetApp.swift
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,16 @@ struct SpreadsheetApp: App {

let windowProperties = WindowProperties(title: "SpreadsheetApp", resizable: true)

var body: some View {
Table(state.data) {
TableColumn("Name", value: \Person.name)
TableColumn("Age", value: \Person.age)
TableColumn("Phone", value: \Person.phone)
TableColumn("Email", value: \Person.email)
TableColumn("Occupation", value: \Person.occupation)
var body: some Scene {
WindowGroup {
Table(state.data) {
TableColumn("Name", value: \Person.name)
TableColumn("Age", value: \Person.age)
TableColumn("Phone", value: \Person.phone)
TableColumn("Email", value: \Person.email)
TableColumn("Occupation", value: \Person.occupation)
}
.padding(10)
}
.padding(10)
}
}
Loading

0 comments on commit 076ed5d

Please sign in to comment.