Created
December 25, 2025 01:33
-
-
Save johnsusek/fbd702f1abc26e9f3518f4c52bc46bdb to your computer and use it in GitHub Desktop.
KitchenSinkView.swift
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import SwiftGodot | |
| import SwiftGodotBuilder | |
| struct ExampleType { | |
| var name: String | |
| var value: Int | |
| } | |
| struct KitchenSinkView: View { | |
| @State var shake = true | |
| @State var dismiss = true | |
| @State var acceptDialog: AcceptDialog? | |
| @State var fileDialog: FileDialog? | |
| @State var graphEdit: GraphEdit? | |
| var body: some View { | |
| CanvasLayer$ { | |
| SafeArea(top: 10, right: 10, bottom: 10, left: 10) { | |
| TabContainer$ { | |
| Tab("Buttons") { | |
| VBoxContainer$ { | |
| HBoxContainer$ { | |
| Button$() | |
| .text("Button") | |
| .onSignal(\.pressed) { _ in print("Button pressed") } | |
| CheckBox$() | |
| .text("CheckBox") | |
| .onSignal(\.toggled) { _, pressed in print("CheckBox: \(pressed)") } | |
| CheckButton$() | |
| .text("CheckButton") | |
| .onSignal(\.toggled) { _, pressed in print("CheckButton: \(pressed)") } | |
| } | |
| } | |
| } | |
| Tab("Text Input") { | |
| VBoxContainer$ { | |
| LineEdit$() | |
| .placeholderText("LineEdit - single line text...") | |
| .onSignal(\.textChanged) { _, text in print("LineEdit: \(text)") } | |
| TextEdit$() | |
| .placeholderText("TextEdit - multi-line text...") | |
| .minSize([0, 80]) | |
| .onSignal(\.textChanged) { _ in print("TextEdit changed") } | |
| SpinBox$() | |
| .minValue(0) | |
| .maxValue(100) | |
| .value(50) | |
| .onSignal(\.valueChanged) { _, val in print("SpinBox: \(val)") } | |
| } | |
| } | |
| Tab("Sliders & Ranges") { | |
| VBoxContainer$ { | |
| HBoxContainer$ { | |
| Label$().text("HSlider:") | |
| HSlider$() | |
| .minValue(0) | |
| .maxValue(100) | |
| .value(50) | |
| .sizeH(.expandFill) | |
| .onSignal(\.valueChanged) { _, val in print("HSlider: \(val)") } | |
| } | |
| HBoxContainer$ { | |
| Label$().text("VSlider:") | |
| VSlider$() | |
| .minValue(0) | |
| .maxValue(100) | |
| .value(75) | |
| .minSize([0, 80]) | |
| .onSignal(\.valueChanged) { _, val in print("VSlider: \(val)") } | |
| } | |
| HBoxContainer$ { | |
| Label$().text("ProgressBar:") | |
| ProgressBar$() | |
| .minValue(0) | |
| .maxValue(100) | |
| .value(65) | |
| .showPercentage(true) | |
| .sizeH(.expandFill) | |
| } | |
| HBoxContainer$ { | |
| Label$().text("HScrollBar:") | |
| HScrollBar$() | |
| .minValue(0) | |
| .maxValue(100) | |
| .value(30) | |
| .sizeH(.expandFill) | |
| } | |
| } | |
| } | |
| Tab("Themes") { | |
| VBoxContainer$ { | |
| Label$() | |
| .text("This label uses a custom theme") | |
| } | |
| .theme(Theme([ | |
| "Label": [ | |
| "colors": ["fontColor": Color.purple], | |
| "fontSizes": ["fontSize": 32], | |
| ], | |
| ])) | |
| } | |
| Tab("StyleBox") { | |
| VBoxContainer$ { | |
| PanelContainer$ { | |
| Label$().text("Styled Panel") | |
| } | |
| .panelStyle( | |
| StyleBoxFlat$() | |
| .bgColor(.black.withAlpha(0.9)) | |
| .borderColor(.cyan) | |
| .borderWidth(2) | |
| .cornerRadius(8) | |
| .shadowColor(.black.withAlpha(0.5)) | |
| .shadowSize(12) | |
| ) | |
| } | |
| } | |
| Tab("Misc") { | |
| VBoxContainer$ { | |
| HBoxContainer$ { | |
| Label$().text("ColorRect") | |
| ColorRect$() | |
| .color(.red) | |
| .minSize([50, 30]) | |
| } | |
| PanelContainer$ { | |
| Label$().text("Content inside PanelContainer") | |
| } | |
| HSeparator$() | |
| } | |
| } | |
| Tab("Containers") { | |
| ScrollContainer$ { | |
| VBoxContainer$ { | |
| HSplitContainer$ { | |
| Label$().text("Left Pane") | |
| Label$().text("Right Pane") | |
| } | |
| .minSize([200, 0]) | |
| HSeparator$() | |
| VSplitContainer$ { | |
| Label$().text("Top Pane") | |
| Label$().text("Bottom Pane") | |
| } | |
| .minSize([0, 80]) | |
| HSeparator$() | |
| CenterContainer$ { | |
| Button$().text("Centered Button") | |
| } | |
| .minSize([0, 50]) | |
| HSeparator$() | |
| GridContainer$ { | |
| Button$().text("1") | |
| Button$().text("2") | |
| Button$().text("3") | |
| Button$().text("4") | |
| Button$().text("5") | |
| Button$().text("6") | |
| } | |
| .columns(3) | |
| HSeparator$() | |
| HFlowContainer$ { | |
| Button$().text("One") | |
| Button$().text("Two") | |
| Button$().text("Three") | |
| Button$().text("Four") | |
| Button$().text("Five") | |
| } | |
| HSeparator$() | |
| VBoxContainer$ { | |
| VFlowContainer$ { | |
| Button$().text("A") | |
| Button$().text("B") | |
| Button$().text("C") | |
| } | |
| .minSize([0, 80]) | |
| } | |
| } | |
| } | |
| .size(.expandFill) | |
| } | |
| Tab("ContextMenu") { | |
| CenterContainer$ { | |
| Label$().text("Right-click me") | |
| .contextMenu { | |
| MenuItem("Cut", id: 0) | |
| MenuItem("Copy", id: 1) | |
| MenuItem("Paste", id: 2) | |
| MenuSeparator() | |
| MenuItem("Delete", id: 10) | |
| } onItemPressed: { id in | |
| print("Context action: \(id)") | |
| } | |
| } | |
| } | |
| Tab("Tree") { | |
| Tree$ { | |
| TreeNode("Root") { | |
| TreeNode("Child 1") | |
| TreeNode("Child 2", editable: true) { | |
| TreeNode("Grandchild") | |
| } | |
| } | |
| } | |
| .onItemSelected { print("Selected") } | |
| .onItemActivated { print("Double-clicked") } | |
| } | |
| Tab("Item List") { | |
| ItemList$ { | |
| ListItem("Apple") | |
| ListItem("Banana") | |
| ListItem("Cherry", disabled: true) | |
| } | |
| .onItemSelected { index in print("Selected: \(index)") } | |
| .onItemActivated { index in print("Activated: \(index)") } | |
| } | |
| Tab("OptionButton") { | |
| VBoxContainer$ { | |
| OptionButton$ { | |
| Option("Small", id: 0) | |
| Option("Medium", id: 1) | |
| Option("Large", id: 2) | |
| OptionSeparator() | |
| Option("Custom...", id: 99) | |
| } | |
| .onItemSelected { id in print("Selected: \(id)") } | |
| } | |
| } | |
| Tab("ColorPicker") { | |
| ScrollContainer$ { | |
| ColorPicker$ { | |
| Preset(.red) | |
| Preset(.green) | |
| Preset(.blue) | |
| Preset(hex: "#FF6600") | |
| Preset(r: 128, g: 0, b: 255) | |
| } | |
| .onColorChanged { color in print("Color: \(color)") } | |
| } | |
| } | |
| Tab("Dialogs") { | |
| VBoxContainer$ { | |
| Button$() | |
| .text("Show Accept") | |
| .onSignal(\.pressed) { _ in | |
| acceptDialog?.popupCentered() | |
| } | |
| Button$() | |
| .text("Show File") | |
| .onSignal(\.pressed) { _ in | |
| fileDialog?.popupCentered() | |
| } | |
| } | |
| } | |
| Tab("RichTextLabel") { | |
| RichTextLabel$ { | |
| Bold("Important: ") | |
| "Normal text " | |
| Colored(.red, "Warning!") | |
| Newline() | |
| Italic { | |
| "Nested " | |
| Bold("formatting") | |
| } | |
| Newline() | |
| Paragraph { | |
| FontSize(24, "Large text") | |
| } | |
| } | |
| } | |
| Tab("GraphEdit") { | |
| GraphEdit$ { | |
| GraphNode$(name: "add", title: "Add") { | |
| Slot("A", left: Port(.blue, type: Float.self)) | |
| Slot("B", left: Port(.green, type: Float.self)) | |
| // Custom content in slots | |
| Slot(right: Port(.red, type: Float.self)) { | |
| SpinBox$().value(1.0).minValue(0).maxValue(100) | |
| } | |
| } | |
| .positionOffset([100, 100]) | |
| .onSignal(\.slotUpdated) { _, slotIndex in | |
| GD.print("Slot A updated on node 'add', slot index: \(slotIndex)") | |
| } | |
| GraphNode$(name: "subtract", title: "Subtract") { | |
| Slot("Value", left: Port(.green, type: Int.self)) | |
| } | |
| .positionOffset([300, 100]) | |
| } | |
| .showGrid(false) | |
| .showMenu(false) | |
| .minimapEnabled(false) | |
| .rightDisconnects(true) | |
| .ref($graphEdit) | |
| .onSignal(\.nodeSelected) { _, n in | |
| guard let n else { return } | |
| GD.print("Node selected: \(n)") | |
| } | |
| .onSignal(\.connectionRequest) { _, fromNode, fromPort, toNode, toPort in | |
| GD.print("Connect request from \(fromNode) port \(fromPort) to \(toNode) port \(toPort)") | |
| _ = graphEdit?.connectNode(fromNode: fromNode, fromPort: Int32(fromPort), toNode: toNode, toPort: Int32(toPort)) | |
| } | |
| .onSignal(\.disconnectionRequest) { _, fromNode, fromPort, toNode, toPort in | |
| GD.print("Disconnect request from \(fromNode) port \(fromPort) to \(toNode) port \(toPort)") | |
| _ = graphEdit?.disconnectNode(fromNode: fromNode, fromPort: Int32(fromPort), toNode: toNode, toPort: Int32(toPort)) | |
| } | |
| } | |
| } | |
| } | |
| FileDialog$() | |
| .filter("Images", "*.png,*.jpg") | |
| .filter("All Files", "*") | |
| .onFileSelected { path in print(path) } | |
| .ref($fileDialog) | |
| AcceptDialog$ { | |
| DialogButton("Save", action: "save") | |
| DialogButton("Don't Save", action: "discard") | |
| CancelButton() | |
| } | |
| .title("Unsaved Changes") | |
| .dialogText("Save before closing?") | |
| .onConfirmed { print("OK") } | |
| .onCustomAction { action in | |
| print("Custom action: \(action)") | |
| } | |
| .ref($acceptDialog) | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment