From e21ead77ffdff206d1ae17e5ce93ea34c4227414 Mon Sep 17 00:00:00 2001 From: Ruben Beltran del Rio Date: Fri, 4 Jul 2025 22:45:30 +0200 Subject: Add new fonts and picker style. --- CLAUDE.md | 4 + Makefile | 8 +- Map.xcodeproj/project.pbxproj | 37 ++++- Map/Assets.xcassets/Icons/Contents.json | 9 ++ .../Icons/Evolution.imageset/Contents.json | 12 ++ .../Icons/Evolution.imageset/Evolution.pdf | Bin 0 -> 7116 bytes Map/Business/Stage.swift | 4 +- Map/Info.plist | 8 +- Map/Localizable.xcstrings | 176 +++++++++++++++++++++ Map/MapApp.swift | 4 +- .../Base Components/EvolutionPicker.swift | 46 ------ .../EvolutionPicker/EvolutionPicker.swift | 89 +++++++++++ .../EvolutionPicker/EvolutionPickerMenu.swift | 81 ++++++++++ .../EvolutionPickerMenuHeader.swift | 26 +++ .../EvolutionPicker/EvolutionPickerMenuItem.swift | 32 ++++ .../Base Components/MapRender/MapAxes.swift | 32 ++-- .../Base Components/MapRender/MapBlockers.swift | 2 +- .../Base Components/MapRender/MapEdges.swift | 2 +- .../Base Components/MapRender/MapGroups.swift | 2 +- .../Base Components/MapRender/MapNotes.swift | 4 +- .../MapRender/MapOpportunities.swift | 2 +- .../Base Components/MapRender/MapStages.swift | 18 +-- .../Base Components/MapRender/MapVertices.swift | 4 +- .../Base Components/MapTextEditor.swift | 46 +++--- Map/Presentation/MapEditor.swift | 20 +-- Map/Presentation/Theme/Color+theme.swift | 51 +++--- Map/Presentation/Theme/Dimensions.swift | 14 +- Map/Presentation/Theme/Font+theme.swift | 10 +- .../Theme/Fonts/LibertinusSerif-Regular.otf | Bin 0 -> 337132 bytes Map/Presentation/Theme/Fonts/Ronzino-Medium.otf | Bin 0 -> 61604 bytes Map/Presentation/Theme/Fonts/Ronzino-Regular.otf | Bin 0 -> 59968 bytes Map/Presentation/Theme/LibertinusSerif-Regular.otf | Bin 337132 -> 0 bytes Map/Presentation/Theme/NSColor+theme.swift | 26 +-- Map/Presentation/Theme/Ronzino-Medium.otf | Bin 61604 -> 0 bytes Map/Presentation/Theme/Ronzino-Regular.otf | Bin 59968 -> 0 bytes README.md | 2 +- 36 files changed, 598 insertions(+), 173 deletions(-) create mode 100644 Map/Assets.xcassets/Icons/Contents.json create mode 100644 Map/Assets.xcassets/Icons/Evolution.imageset/Contents.json create mode 100644 Map/Assets.xcassets/Icons/Evolution.imageset/Evolution.pdf create mode 100644 Map/Localizable.xcstrings delete mode 100644 Map/Presentation/Base Components/EvolutionPicker.swift create mode 100644 Map/Presentation/Base Components/EvolutionPicker/EvolutionPicker.swift create mode 100644 Map/Presentation/Base Components/EvolutionPicker/EvolutionPickerMenu.swift create mode 100644 Map/Presentation/Base Components/EvolutionPicker/EvolutionPickerMenuHeader.swift create mode 100644 Map/Presentation/Base Components/EvolutionPicker/EvolutionPickerMenuItem.swift create mode 100644 Map/Presentation/Theme/Fonts/LibertinusSerif-Regular.otf create mode 100644 Map/Presentation/Theme/Fonts/Ronzino-Medium.otf create mode 100644 Map/Presentation/Theme/Fonts/Ronzino-Regular.otf delete mode 100644 Map/Presentation/Theme/LibertinusSerif-Regular.otf delete mode 100644 Map/Presentation/Theme/Ronzino-Medium.otf delete mode 100644 Map/Presentation/Theme/Ronzino-Regular.otf diff --git a/CLAUDE.md b/CLAUDE.md index 6ca3848..f9f5f35 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -88,6 +88,10 @@ The app uses a domain-specific language for creating Wardley Maps: - Run `make format` before committing - All Swift files include GPL license header +### Tool Preferences +- **Use `rg` instead of `grep`** for text searching (ripgrep is faster and more user-friendly) +- **Use `fd` instead of `find`** for file searching (fd is faster and has better defaults) + ### Key Dependencies - SwiftUI for UI framework - Sparkle for auto-updates diff --git a/Makefile b/Makefile index 158f050..11b5b55 100644 --- a/Makefile +++ b/Makefile @@ -19,15 +19,15 @@ generate_appcast: @$(sparkle_path)/bin/generate_appcast --account $(sparkle_account) $(build_directory) archive: prepare - xcodebuild -project $(project_name).xcodeproj -scheme $(project_name) -configuration Release -archivePath $(build_directory)/$(project_name).xcarchive archive && xcodebuild -exportArchive -archivePath $(build_directory)/$(project_name).xcarchive -exportPath $(build_directory) -exportOptionsPlist export_options.plist + @xcodebuild -project $(project_name).xcodeproj -scheme $(project_name) -configuration Release -archivePath $(build_directory)/$(project_name).xcarchive archive && xcodebuild -exportArchive -archivePath $(build_directory)/$(project_name).xcarchive -exportPath $(build_directory) -exportOptionsPlist export_options.plist prepare: - mkdir -p $(build_directory) + @mkdir -p $(build_directory) format: - swift format -i -r . + @swift format -i -r . lint: - swift format lint -r . + @swift format lint -r . .PHONY: package prepare archive generate_appcast package distribute format lint build test diff --git a/Map.xcodeproj/project.pbxproj b/Map.xcodeproj/project.pbxproj index aaa6948..46304ae 100644 --- a/Map.xcodeproj/project.pbxproj +++ b/Map.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 70; + objectVersion = 73; objects = { /* Begin PBXBuildFile section */ @@ -29,6 +29,19 @@ }; /* End PBXContainerItemProxy section */ +/* Begin PBXCopyFilesBuildPhase section */ + B5DF1E3B2E1868D4003477B5 /* Copy Fonts */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = Fonts; + dstSubfolderSpec = 7; + files = ( + ); + name = "Copy Fonts"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + /* Begin PBXFileReference section */ B545870C2C961E9C0067B788 /* Map.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Map.app; sourceTree = BUILT_PRODUCTS_DIR; }; B54587202C961E9E0067B788 /* MapTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = MapTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -40,13 +53,28 @@ isa = PBXFileSystemSynchronizedBuildFileExceptionSet; membershipExceptions = ( Info.plist, + "Presentation/Theme/Fonts/LibertinusSerif-Regular.otf", + "Presentation/Theme/Fonts/Ronzino-Medium.otf", + "Presentation/Theme/Fonts/Ronzino-Regular.otf", ); target = B545870B2C961E9C0067B788 /* Map */; }; /* End PBXFileSystemSynchronizedBuildFileExceptionSet section */ +/* Begin PBXFileSystemSynchronizedGroupBuildPhaseMembershipExceptionSet section */ + B5DF1E3F2E1868E8003477B5 /* PBXFileSystemSynchronizedGroupBuildPhaseMembershipExceptionSet */ = { + isa = PBXFileSystemSynchronizedGroupBuildPhaseMembershipExceptionSet; + buildPhase = B5DF1E3B2E1868D4003477B5 /* Copy Fonts */; + membershipExceptions = ( + "Presentation/Theme/Fonts/LibertinusSerif-Regular.otf", + "Presentation/Theme/Fonts/Ronzino-Medium.otf", + "Presentation/Theme/Fonts/Ronzino-Regular.otf", + ); + }; +/* End PBXFileSystemSynchronizedGroupBuildPhaseMembershipExceptionSet section */ + /* Begin PBXFileSystemSynchronizedRootGroup section */ - B598304E2E17E7C700F5FBF6 /* Map */ = {isa = PBXFileSystemSynchronizedRootGroup; exceptions = (B59830752E17E7C700F5FBF6 /* PBXFileSystemSynchronizedBuildFileExceptionSet */, ); explicitFileTypes = {}; explicitFolders = (); path = Map; sourceTree = ""; }; + B598304E2E17E7C700F5FBF6 /* Map */ = {isa = PBXFileSystemSynchronizedRootGroup; exceptions = (B59830752E17E7C700F5FBF6 /* PBXFileSystemSynchronizedBuildFileExceptionSet */, B5DF1E3F2E1868E8003477B5 /* PBXFileSystemSynchronizedGroupBuildPhaseMembershipExceptionSet */, ); explicitFileTypes = {}; explicitFolders = (); path = Map; sourceTree = ""; }; B59830772E17E7CC00F5FBF6 /* MapTests */ = {isa = PBXFileSystemSynchronizedRootGroup; explicitFileTypes = {}; explicitFolders = (); path = MapTests; sourceTree = ""; }; B598307C2E17E7D600F5FBF6 /* MapUITests */ = {isa = PBXFileSystemSynchronizedRootGroup; explicitFileTypes = {}; explicitFolders = (); path = MapUITests; sourceTree = ""; }; /* End PBXFileSystemSynchronizedRootGroup section */ @@ -109,6 +137,7 @@ B54587082C961E9C0067B788 /* Sources */, B54587092C961E9C0067B788 /* Frameworks */, B545870A2C961E9C0067B788 /* Resources */, + B5DF1E3B2E1868D4003477B5 /* Copy Fonts */, ); buildRules = ( ); @@ -193,7 +222,6 @@ }; }; buildConfigurationList = B54587072C961E9C0067B788 /* Build configuration list for PBXProject "Map" */; - compatibilityVersion = "Xcode 15.0"; developmentRegion = en; hasScannedForEncodings = 0; knownRegions = ( @@ -206,6 +234,7 @@ B5012E7D2C97315800AC4D68 /* XCRemoteSwiftPackageReference "ConcaveHull" */, B51A45F32C982FAE00870ED5 /* XCRemoteSwiftPackageReference "Sparkle" */, ); + preferredProjectObjectVersion = 60; productRefGroup = B545870D2C961E9C0067B788 /* Products */; projectDirPath = ""; projectRoot = ""; @@ -340,6 +369,7 @@ ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)"; + SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; }; name = Debug; @@ -398,6 +428,7 @@ MTL_FAST_MATH = YES; SDKROOT = macosx; SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_EMIT_LOC_STRINGS = YES; }; name = Release; }; diff --git a/Map/Assets.xcassets/Icons/Contents.json b/Map/Assets.xcassets/Icons/Contents.json new file mode 100644 index 0000000..6e96565 --- /dev/null +++ b/Map/Assets.xcassets/Icons/Contents.json @@ -0,0 +1,9 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "provides-namespace" : true + } +} diff --git a/Map/Assets.xcassets/Icons/Evolution.imageset/Contents.json b/Map/Assets.xcassets/Icons/Evolution.imageset/Contents.json new file mode 100644 index 0000000..795b58e --- /dev/null +++ b/Map/Assets.xcassets/Icons/Evolution.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "Evolution.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Map/Assets.xcassets/Icons/Evolution.imageset/Evolution.pdf b/Map/Assets.xcassets/Icons/Evolution.imageset/Evolution.pdf new file mode 100644 index 0000000..a26e52c Binary files /dev/null and b/Map/Assets.xcassets/Icons/Evolution.imageset/Evolution.pdf differ diff --git a/Map/Business/Stage.swift b/Map/Business/Stage.swift index 4f737a1..4a1b834 100644 --- a/Map/Business/Stage.swift +++ b/Map/Business/Stage.swift @@ -12,6 +12,8 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see https://map.tranquil.systems. +import SwiftUI + struct Stage { let i: String let ii: String @@ -125,7 +127,7 @@ struct Stage { } } - static func title(_ type: StageType) -> String { + static func title(_ type: StageType) -> LocalizedStringKey { switch type { case .general: return "Activities" diff --git a/Map/Info.plist b/Map/Info.plist index 07f3108..fb1a6fc 100644 --- a/Map/Info.plist +++ b/Map/Info.plist @@ -2,12 +2,8 @@ - UIAppFonts - - Ronzino-Regular.otf - Ronzino-Medium.otf - LibertinusSerif-Regular.otf - + ATSApplicationFontsPath + Fonts SUEnableInstallerLauncherService SUPublicEDKey diff --git a/Map/Localizable.xcstrings b/Map/Localizable.xcstrings new file mode 100644 index 0000000..808059b --- /dev/null +++ b/Map/Localizable.xcstrings @@ -0,0 +1,176 @@ +{ + "sourceLanguage" : "en", + "strings" : { + "Activities" : { + + }, + "Behavior" : { + + }, + "Certainty" : { + + }, + "Check for Updates…" : { + + }, + "Comparison" : { + + }, + "Data" : { + + }, + "Decision Drivers" : { + + }, + "Done" : { + + }, + "Done (⎋)" : { + + }, + "Efficiency" : { + + }, + "evolution_picker.label" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Type of Evolution" + } + } + } + }, + "Export..." : { + + }, + "Failure" : { + + }, + "Find Next (⌘G)" : { + + }, + "Find Previous (⇧⌘G)" : { + + }, + "Find..." : { + + }, + "Focus Of Value" : { + + }, + "Industrialised" : { + + }, + "Invisible" : { + + }, + "Knowledge" : { + + }, + "Knowledge Management" : { + + }, + "Map Help" : { + + }, + "Market" : { + + }, + "Market Action" : { + + }, + "Market Perception" : { + + }, + "Perception In Industry" : { + + }, + "Practice" : { + + }, + "Publication Types" : { + + }, + "Search" : { + + }, + "stage_type.section.characteristics" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Characteristics" + } + } + } + }, + "stage_type.section.general_properties" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "General Properties" + } + } + } + }, + "stage_type.section.other" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Custom" + } + } + } + }, + "stage_type.section.types" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Types" + } + } + } + }, + "Ubiquity" : { + + }, + "Uncharted" : { + + }, + "Understanding" : { + + }, + "Use Horizontal Layout" : { + + }, + "Use Vertical Layout" : { + + }, + "User Perception" : { + + }, + "Visible" : { + + }, + "Zoom In" : { + + }, + "Zoom In (⌘+)" : { + + }, + "Zoom Out" : { + + }, + "Zoom Out (⌘-)" : { + + } + }, + "version" : "1.0" +} \ No newline at end of file diff --git a/Map/MapApp.swift b/Map/MapApp.swift index edfe4ec..d8ca35d 100644 --- a/Map/MapApp.swift +++ b/Map/MapApp.swift @@ -26,7 +26,9 @@ struct MapApp: App { MapEditor(document: file.$document, url: file.fileURL) .focusedSceneValue(\.document, file.$document) .focusedSceneValue(\.fileURL, file.fileURL) - }.commands { + } + .windowToolbarStyle(.unifiedCompact) + .commands { MapCommands() UpdateCommands(updaterController: updaterController) } diff --git a/Map/Presentation/Base Components/EvolutionPicker.swift b/Map/Presentation/Base Components/EvolutionPicker.swift deleted file mode 100644 index 2df4a7f..0000000 --- a/Map/Presentation/Base Components/EvolutionPicker.swift +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright (C) 2024 Rubén Beltrán del Río - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with this program. If not, see https://map.tranquil.systems. -import SwiftUI - -struct EvolutionPicker: View { - - @Binding var selectedEvolution: StageType - - var body: some View { - Picker("Evolution", selection: $selectedEvolution) { - ForEach(StageType.types) { stage in - Text(Stage.title(stage)).font(.Theme.Body.regular).tag(stage).padding(4.0) - } - Divider() - ForEach(StageType.characteristics) { stage in - Text(Stage.title(stage)).font(.Theme.Body.regular).tag(stage).padding(4.0).font( - .Theme.Body.regular) - } - Divider() - ForEach(StageType.properties) { stage in - Text(Stage.title(stage)).font(.Theme.Body.regular).tag(stage).padding(4.0) - } - Divider() - ForEach(StageType.custom) { stage in - Text(Stage.title(stage)).font(.Theme.Body.regular).tag(stage).padding(4.0) - } - }.font(.Theme.Body.regular).padding(.horizontal, 8.0).padding(.vertical, 4.0) - } -} - -#Preview { - let selectedEvolution: StageType = .behavior - EvolutionPicker(selectedEvolution: .constant(selectedEvolution)) -} diff --git a/Map/Presentation/Base Components/EvolutionPicker/EvolutionPicker.swift b/Map/Presentation/Base Components/EvolutionPicker/EvolutionPicker.swift new file mode 100644 index 0000000..5748e59 --- /dev/null +++ b/Map/Presentation/Base Components/EvolutionPicker/EvolutionPicker.swift @@ -0,0 +1,89 @@ +// Copyright (C) 2024 Rubén Beltrán del Río + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see https://map.tranquil.systems. +import SwiftUI + +struct EvolutionPicker: View { + + @State var isShowingMenu = false + @State var isHovered = false + @FocusState var isFocused: Bool + + @Binding var selectedEvolution: StageType + + var body: some View { + + Button( + action: { + isShowingMenu = !isShowingMenu + }, + label: { + HStack(spacing: Dimensions.Spacing.loose) { + Text(Stage.title(selectedEvolution)) + .font(.Theme.Body.emphasized) + .foregroundColor(isShowingMenu ? .Theme.UI.background : .Theme.UI.foreground) + ZStack { + Image(systemName: "chevron.up") + .resizable() + .scaledToFit() + .frame( + width: Dimensions.EvolutionPicker.controlSize, + height: Dimensions.EvolutionPicker.controlSize + ) + .offset(CGSize(width: 0, height: -Dimensions.EvolutionPicker.controlSpacing)) + .foregroundColor(isShowingMenu ? .Theme.UI.background : .Theme.UI.foreground) + Image(systemName: "chevron.down") + .resizable() + .scaledToFit() + .frame( + width: Dimensions.EvolutionPicker.controlSize, + height: Dimensions.EvolutionPicker.controlSize + ) + .offset(CGSize(width: 0, height: Dimensions.EvolutionPicker.controlSpacing)) + .foregroundColor(isShowingMenu ? .Theme.UI.background : .Theme.UI.foreground) + } + } + .padding(.horizontal, Dimensions.Spacing.regular) + .padding(.vertical, Dimensions.Spacing.cozy) + } + ) + .buttonStyle(.borderless) + .background(isShowingMenu ? Color.Theme.UI.foreground : Color.clear) + .cornerRadius(4.0) + .overlay( + RoundedRectangle(cornerRadius: 4.0) + .stroke( + isShowingMenu + ? Color.Theme.UI.foreground : (isHovered ? Color.Theme.UI.foreground : Color.clear), + lineWidth: 1) + ) + .onHover { hovering in + isHovered = hovering + } + .popover( + isPresented: $isShowingMenu, + content: { + EvolutionPickerMenu(selectedEvolution: $selectedEvolution) + } + ) + .onChange(of: selectedEvolution) { + isShowingMenu = false + } + } +} + +#Preview { + @Previewable @State var selectedEvolution: StageType = .behavior + EvolutionPicker(selectedEvolution: $selectedEvolution) +} diff --git a/Map/Presentation/Base Components/EvolutionPicker/EvolutionPickerMenu.swift b/Map/Presentation/Base Components/EvolutionPicker/EvolutionPickerMenu.swift new file mode 100644 index 0000000..3a396aa --- /dev/null +++ b/Map/Presentation/Base Components/EvolutionPicker/EvolutionPickerMenu.swift @@ -0,0 +1,81 @@ +import SwiftUI + +struct EvolutionPickerMenu: View { + + @Binding var selectedEvolution: StageType + + private func select(_ evolution: StageType) { + selectedEvolution = evolution + } + + var body: some View { + VStack(alignment: .leading, spacing: 1.0) { + Section(header: EvolutionPickerMenuHeader(key: "stage_type.section.types")) { + ForEach(StageType.types) { stage in + EvolutionPickerMenuItem(stage: stage, isSelected: selectedEvolution == stage) + .onTapGesture { + selectedEvolution = stage + } + } + } + Section(header: EvolutionPickerMenuHeader(key: "stage_type.section.characteristics")) { + ForEach(StageType.characteristics) { stage in + EvolutionPickerMenuItem(stage: stage, isSelected: selectedEvolution == stage) + .onTapGesture { + selectedEvolution = stage + } + } + } + Section(header: EvolutionPickerMenuHeader(key: "stage_type.section.general_properties")) { + ForEach(StageType.properties) { stage in + EvolutionPickerMenuItem(stage: stage, isSelected: selectedEvolution == stage) + .onTapGesture { + selectedEvolution = stage + } + } + } + Section(header: EvolutionPickerMenuHeader(key: "stage_type.section.other")) { + ForEach(StageType.custom) { stage in + EvolutionPickerMenuItem(stage: stage, isSelected: selectedEvolution == stage) + .onTapGesture { + selectedEvolution = stage + } + } + } + } + .padding(Dimensions.Spacing.coziest) + .ignoresSafeArea() + + } +} + +#Preview { + EvolutionPickerMenu(selectedEvolution: .constant(.ubiquity)) +} + +/* +Picker(selection: $selectedEvolution) { + Divider() + ForEach(StageType.characteristics) { stage in + Text(Stage.title(stage)) + .font(selectedEvolution == stage ? .Theme.Body.emphasized : .Theme.Body.regular) + .tag(stage) + } + Divider() + ForEach(StageType.properties) { stage in + Text(Stage.title(stage)) + .font(selectedEvolution == stage ? .Theme.Body.emphasized : .Theme.Body.regular) + .tag(stage) + } + Divider() + ForEach(StageType.custom) { stage in + Text(Stage.title(stage)) + .font(selectedEvolution == stage ? .Theme.Body.emphasized : .Theme.Body.regular) + .tag(stage) + } +} label: { + Label("evolution_picker.label", image: "Icons/Evolution") + .font(.Theme.Body.regular) +}.padding(.horizontal, Dimensions.Spacing.regular) + .padding(.vertical, Dimensions.Spacing.cozy) + */ diff --git a/Map/Presentation/Base Components/EvolutionPicker/EvolutionPickerMenuHeader.swift b/Map/Presentation/Base Components/EvolutionPicker/EvolutionPickerMenuHeader.swift new file mode 100644 index 0000000..b3eeb97 --- /dev/null +++ b/Map/Presentation/Base Components/EvolutionPicker/EvolutionPickerMenuHeader.swift @@ -0,0 +1,26 @@ +import SwiftUI + +struct EvolutionPickerMenuHeader: View { + + let key: LocalizedStringKey + + var body: some View { + HStack(alignment: .center, spacing: Dimensions.Spacing.regular) { + Text(key) + .font(.Theme.Caption.emphasized) + .padding(.vertical, Dimensions.Spacing.cozy) + .textCase(.uppercase) + .padding(.leading, Dimensions.Spacing.regular) + .layoutPriority(1) + Spacer() + .frame(height: 1) + .background(Color.Theme.UI.foreground.opacity(0.2)) + } + .padding(.horizontal, Dimensions.Spacing.regular) + .cornerRadius(Dimensions.EvolutionPicker.radius) + } +} + +#Preview { + EvolutionPickerMenuHeader(key: "stage_type.section.types") +} diff --git a/Map/Presentation/Base Components/EvolutionPicker/EvolutionPickerMenuItem.swift b/Map/Presentation/Base Components/EvolutionPicker/EvolutionPickerMenuItem.swift new file mode 100644 index 0000000..1731e8d --- /dev/null +++ b/Map/Presentation/Base Components/EvolutionPicker/EvolutionPickerMenuItem.swift @@ -0,0 +1,32 @@ +import SwiftUI + +struct EvolutionPickerMenuItem: View { + + @State var isHovered: Bool = false + + let stage: StageType + let isSelected: Bool + + var body: some View { + HStack(alignment: .center, spacing: Dimensions.Spacing.coziest) { + Image(systemName: "checkmark") + .opacity(isSelected ? 1.0 : 0.0) + .bold(true) + Text(Stage.title(stage)) + .font(isSelected ? .Theme.Body.emphasized : .Theme.Body.regular) + .padding(Dimensions.Spacing.cozy) + Spacer() + } + .padding(.horizontal, Dimensions.Spacing.regular) + .background(isHovered ? Color.Theme.UI.accent : Color.clear) + .cornerRadius(Dimensions.EvolutionPicker.radius) + .onHover { hovering in + isHovered = hovering + } + } +} + +#Preview { + EvolutionPickerMenuItem(stage: .behavior, isSelected: false) + EvolutionPickerMenuItem(stage: .ubiquity, isSelected: true) +} diff --git a/Map/Presentation/Base Components/MapRender/MapAxes.swift b/Map/Presentation/Base Components/MapRender/MapAxes.swift index 1c0a147..48e0b6d 100644 --- a/Map/Presentation/Base Components/MapRender/MapAxes.swift +++ b/Map/Presentation/Base Components/MapRender/MapAxes.swift @@ -33,52 +33,54 @@ struct MapAxes: View { path.addLine(to: CGPoint(x: mapSize.width, y: mapSize.height)) path.move(to: CGPoint(x: mapSize.width, y: mapSize.height)) path.closeSubpath() - }.stroke(Color.Map.axisColor, lineWidth: lineWidth * 2) + }.stroke(Color.Theme.Map.axisColor, lineWidth: lineWidth * 2) // Y Labels - Text("Visible").font(.Theme.Map.axisLabel).foregroundColor(.Map.labelColor).rotationEffect( - Angle(degrees: -90.0) - ) - .offset(CGSize(width: -35.0, height: 0.0)) - Text("Invisible").font(.Theme.Map.axisLabel).foregroundColor(.Map.labelColor).rotationEffect( - Angle(degrees: -90.0) - ) - .offset(CGSize(width: -40.0, height: mapSize.height - 20)) + Text("Visible").font(.Theme.Map.axisLabel).foregroundColor(.Theme.Map.labelColor) + .rotationEffect( + Angle(degrees: -90.0) + ) + .offset(CGSize(width: -35.0, height: 0.0)) + Text("Invisible").font(.Theme.Map.axisLabel).foregroundColor(.Theme.Map.labelColor) + .rotationEffect( + Angle(degrees: -90.0) + ) + .offset(CGSize(width: -40.0, height: mapSize.height - 20)) // X Labels Text("Uncharted") .font(.Theme.Map.axisLabel) - .foregroundColor(.Map.labelColor) + .foregroundColor(.Theme.Map.labelColor) .frame(width: mapSize.width / 4, height: stageHeight / 2.0, alignment: .topLeading) .offset(CGSize(width: 0.0, height: -stageHeight / 4.0)) Text("Industrialised") .font(.Theme.Map.axisLabel) - .foregroundColor(.Map.labelColor) + .foregroundColor(.Theme.Map.labelColor) .frame(width: mapSize.width / 4, height: stageHeight / 2.0, alignment: .topLeading) .offset(CGSize(width: mapSize.width - 100.0, height: -stageHeight / 4.0)) Text(evolution.i) .font(.Theme.Map.axisLabel) - .foregroundColor(.Map.labelColor) + .foregroundColor(.Theme.Map.labelColor) .frame(width: w(stages[0]), height: stageHeight, alignment: .topLeading) .offset(CGSize(width: 0.0, height: mapSize.height + padding)) Text(evolution.ii) .font(.Theme.Map.axisLabel) - .foregroundColor(.Map.labelColor) + .foregroundColor(.Theme.Map.labelColor) .frame(width: w(stages[1]) - w(stages[0]), height: stageHeight, alignment: .topLeading) .offset(CGSize(width: w(stages[0]), height: mapSize.height + padding)) Text(evolution.iii) .font(.Theme.Map.axisLabel) - .foregroundColor(.Map.labelColor) + .foregroundColor(.Theme.Map.labelColor) .frame(width: w(stages[2]) - w(stages[1]), height: stageHeight, alignment: .topLeading) .offset(CGSize(width: w(stages[1]), height: mapSize.height + padding)) Text(evolution.iv) .font(.Theme.Map.axisLabel) - .foregroundColor(.Map.labelColor) + .foregroundColor(.Theme.Map.labelColor) .frame(width: mapSize.width - w(stages[2]), height: stageHeight, alignment: .topLeading) .offset(CGSize(width: w(stages[2]), height: mapSize.height + padding)) } diff --git a/Map/Presentation/Base Components/MapRender/MapBlockers.swift b/Map/Presentation/Base Components/MapRender/MapBlockers.swift index 613b792..e550ca9 100644 --- a/Map/Presentation/Base Components/MapRender/MapBlockers.swift +++ b/Map/Presentation/Base Components/MapRender/MapBlockers.swift @@ -32,7 +32,7 @@ struct MapBlockers: View { y: h(vertex.position.y) - vertexSize.height * 2 / 3), size: CGSize(width: vertexSize.width / 2, height: vertexSize.height * 2) ), cornerSize: cornerSize) - }.fill(Color.Map.blockerColor) + }.fill(Color.Theme.Map.blockerColor) } } diff --git a/Map/Presentation/Base Components/MapRender/MapEdges.swift b/Map/Presentation/Base Components/MapRender/MapEdges.swift index 3090c04..3c6ef82 100644 --- a/Map/Presentation/Base Components/MapRender/MapEdges.swift +++ b/Map/Presentation/Base Components/MapRender/MapEdges.swift @@ -66,7 +66,7 @@ struct MapEdges: View { path.closeSubpath() }.applying( CGAffineTransform(translationX: vertexSize.width / 2.0, y: vertexSize.height / 2.0) - ).stroke(Color.Map.vertexColor, lineWidth: lineWidth) + ).stroke(Color.Theme.Map.vertexColor, lineWidth: lineWidth) } } diff --git a/Map/Presentation/Base Components/MapRender/MapGroups.swift b/Map/Presentation/Base Components/MapRender/MapGroups.swift index 41ea147..1983dcd 100644 --- a/Map/Presentation/Base Components/MapRender/MapGroups.swift +++ b/Map/Presentation/Base Components/MapRender/MapGroups.swift @@ -28,7 +28,7 @@ struct MapGroups: View { } private func color(_ index: Int) -> Color { - return .Map.groupColors[index % Color.Map.groupColors.count] + return .Theme.Map.groupColors[index % Color.Theme.Map.groupColors.count] } } diff --git a/Map/Presentation/Base Components/MapRender/MapNotes.swift b/Map/Presentation/Base Components/MapRender/MapNotes.swift index 16c61ba..20aa1e1 100644 --- a/Map/Presentation/Base Components/MapRender/MapNotes.swift +++ b/Map/Presentation/Base Components/MapRender/MapNotes.swift @@ -29,8 +29,8 @@ struct MapNotes: View { .lineSpacing(Dimensions.LineHeight.Map.note - Dimensions.FontSize.Map.note) .padding(Dimensions.Spacing.cozy) .background(.white) - .foregroundColor(.Map.labelColor) - .border(Color.Map.vertexColor, width: lineWidth) + .foregroundColor(.Theme.Map.labelColor) + .border(Color.Theme.Map.vertexColor, width: lineWidth) .frame(minWidth: 16.0, maxWidth: maxWidth, alignment: .topLeading) .offset( CGSize( diff --git a/Map/Presentation/Base Components/MapRender/MapOpportunities.swift b/Map/Presentation/Base Components/MapRender/MapOpportunities.swift index 3d539d4..04d4b40 100644 --- a/Map/Presentation/Base Components/MapRender/MapOpportunities.swift +++ b/Map/Presentation/Base Components/MapRender/MapOpportunities.swift @@ -61,7 +61,7 @@ struct MapOpportunities: View { }.applying( CGAffineTransform(translationX: vertexSize.width / 2.0, y: vertexSize.height / 2.0) ).strokedPath(StrokeStyle(lineWidth: lineWidth / 4, dash: [10.0])).stroke( - Color.Map.opportunityColor) + Color.Theme.Map.opportunityColor) } } diff --git a/Map/Presentation/Base Components/MapRender/MapStages.swift b/Map/Presentation/Base Components/MapRender/MapStages.swift index d5e5965..08250f7 100644 --- a/Map/Presentation/Base Components/MapRender/MapStages.swift +++ b/Map/Presentation/Base Components/MapRender/MapStages.swift @@ -25,25 +25,25 @@ struct MapStages: View { var body: some View { ZStack(alignment: .topLeading) { PatternView( - design: .constant(.stitch), pixelSize: 1.0, foregroundColor: .Map.stageForeground, - backgroundColor: .Map.stageBackground + design: .constant(.stitch), pixelSize: 1.0, foregroundColor: .Theme.Map.stageForeground, + backgroundColor: .Theme.Map.stageBackground ) .frame(width: w(stages[0]), height: mapSize.height) PatternView( - design: .constant(.shingles), pixelSize: 1.0, foregroundColor: .Map.stageForeground, - backgroundColor: .Map.stageBackground + design: .constant(.shingles), pixelSize: 1.0, foregroundColor: .Theme.Map.stageForeground, + backgroundColor: .Theme.Map.stageBackground ) .offset(CGSize(width: w(stages[0]), height: 0)) .frame(width: w(stages[1]) - w(stages[0]), height: mapSize.height) PatternView( - design: .constant(.shadowGrid), pixelSize: 1.0, foregroundColor: .Map.stageForeground, - backgroundColor: .Map.stageBackground + design: .constant(.shadowGrid), pixelSize: 1.0, foregroundColor: .Theme.Map.stageForeground, + backgroundColor: .Theme.Map.stageBackground ) .offset(CGSize(width: w(stages[1]), height: 0)) .frame(width: w(stages[2]) - w(stages[1]), height: mapSize.height) PatternView( - design: .constant(.wicker), pixelSize: 1.0, foregroundColor: .Map.stageForeground, - backgroundColor: .Map.stageBackground + design: .constant(.wicker), pixelSize: 1.0, foregroundColor: .Theme.Map.stageForeground, + backgroundColor: .Theme.Map.stageBackground ) .offset(CGSize(width: w(stages[2]), height: 0)) .frame(width: mapSize.width - w(stages[2]), height: mapSize.height) @@ -61,7 +61,7 @@ struct MapStages: View { path.move(to: CGPoint(x: w(stages[0]), y: 0)) path.closeSubpath() }.strokedPath(StrokeStyle(lineWidth: lineWidth / 4, dash: [10.0, 18.0])).stroke( - Color.Map.axisColor) + Color.Theme.Map.axisColor) } } diff --git a/Map/Presentation/Base Components/MapRender/MapVertices.swift b/Map/Presentation/Base Components/MapRender/MapVertices.swift index 1f6cf1a..4f130c6 100644 --- a/Map/Presentation/Base Components/MapRender/MapVertices.swift +++ b/Map/Presentation/Base Components/MapRender/MapVertices.swift @@ -27,13 +27,13 @@ struct MapVertices: View { ZStack(alignment: .topLeading) { ForEach(vertices, id: \.id) { vertex in ZStack(alignment: .topLeading) { - getVertexShape(vertex).fill(Color.Map.vertexColor) + getVertexShape(vertex).fill(Color.Theme.Map.vertexColor) Text(vertex.label.replacingOccurrences(of: "\\n", with: "\n")) .font(.Theme.Map.vertexLabel) .lineSpacing( Dimensions.LineHeight.Map.vertexLabel - Dimensions.FontSize.Map.vertexLabel ) - .foregroundColor(.Map.labelColor) + .foregroundColor(.Theme.Map.labelColor) .shadow(color: .white, radius: 0, x: -0.5, y: -0.5) .shadow(color: .white, radius: 0, x: 0.5, y: 0.5) .offset( diff --git a/Map/Presentation/Base Components/MapTextEditor.swift b/Map/Presentation/Base Components/MapTextEditor.swift index 3c5c824..18b2fbc 100644 --- a/Map/Presentation/Base Components/MapTextEditor.swift +++ b/Map/Presentation/Base Components/MapTextEditor.swift @@ -64,7 +64,7 @@ class MapTextEditorController: NSViewController { scrollView.translatesAutoresizingMaskIntoConstraints = false - textView.backgroundColor = .UI.background + textView.backgroundColor = .Theme.UI.background textView.allowsUndo = true textView.delegate = self textView.textStorage?.delegate = self @@ -92,7 +92,9 @@ class MapTextEditorController: NSViewController { for (index, range) in highlightRanges.enumerated() { let nsRange = NSRange(range, in: textStorage.string) - let color = index == selectedRange ? NSColor.Syntax.highlightMatch : NSColor.Syntax.match + let color = + index == selectedRange + ? NSColor.Theme.Syntax.highlightMatch : NSColor.Theme.Syntax.match textStorage.addAttribute(.backgroundColor, value: color, range: nsRange) } @@ -156,77 +158,77 @@ extension MapTextEditorController: NSTextStorageDelegate { for match in matches { textStorage.addAttributes( - [.foregroundColor: NSColor.Syntax.vertex], range: match.range(at: 1)) + [.foregroundColor: NSColor.Theme.Syntax.vertex], range: match.range(at: 1)) textStorage.addAttributes( - [.foregroundColor: NSColor.Syntax.number], range: match.range(at: 2)) + [.foregroundColor: NSColor.Theme.Syntax.number], range: match.range(at: 2)) textStorage.addAttributes( - [.foregroundColor: NSColor.Syntax.number], range: match.range(at: 3)) + [.foregroundColor: NSColor.Theme.Syntax.number], range: match.range(at: 3)) textStorage.addAttributes( - [.foregroundColor: NSColor.Syntax.option], range: match.range(at: 4)) + [.foregroundColor: NSColor.Theme.Syntax.option], range: match.range(at: 4)) } matches = edgeRegex.matches(in: textStorage.string, options: [], range: range) for match in matches { textStorage.addAttributes( - [.foregroundColor: NSColor.Syntax.vertex], range: match.range(at: 1)) + [.foregroundColor: NSColor.Theme.Syntax.vertex], range: match.range(at: 1)) let arrowRange = match.range(at: 2) textStorage.addAttributes( - [.foregroundColor: NSColor.Syntax.symbol], + [.foregroundColor: NSColor.Theme.Syntax.symbol], range: NSMakeRange(arrowRange.lowerBound - 1, arrowRange.length + 1)) textStorage.addAttributes( - [.foregroundColor: NSColor.Syntax.vertex], range: match.range(at: 3)) + [.foregroundColor: NSColor.Theme.Syntax.vertex], range: match.range(at: 3)) } matches = opportunityRegex.matches(in: textStorage.string, options: [], range: range) for match in matches { textStorage.addAttributes( - [.foregroundColor: NSColor.Syntax.option], range: match.range(at: 1)) + [.foregroundColor: NSColor.Theme.Syntax.option], range: match.range(at: 1)) textStorage.addAttributes( - [.foregroundColor: NSColor.Syntax.vertex], range: match.range(at: 2)) + [.foregroundColor: NSColor.Theme.Syntax.vertex], range: match.range(at: 2)) textStorage.addAttributes( - [.foregroundColor: NSColor.Syntax.symbol], range: match.range(at: 3)) + [.foregroundColor: NSColor.Theme.Syntax.symbol], range: match.range(at: 3)) textStorage.addAttributes( - [.foregroundColor: NSColor.Syntax.number], range: match.range(at: 4)) + [.foregroundColor: NSColor.Theme.Syntax.number], range: match.range(at: 4)) } matches = blockerRegex.matches(in: textStorage.string, options: [], range: range) for match in matches { textStorage.addAttributes( - [.foregroundColor: NSColor.Syntax.option], range: match.range(at: 1)) + [.foregroundColor: NSColor.Theme.Syntax.option], range: match.range(at: 1)) textStorage.addAttributes( - [.foregroundColor: NSColor.Syntax.vertex], range: match.range(at: 2)) + [.foregroundColor: NSColor.Theme.Syntax.vertex], range: match.range(at: 2)) } matches = noteRegex.matches(in: textStorage.string, options: [], range: range) for match in matches { textStorage.addAttributes( - [.foregroundColor: NSColor.Syntax.option], range: match.range(at: 1)) + [.foregroundColor: NSColor.Theme.Syntax.option], range: match.range(at: 1)) textStorage.addAttributes( - [.foregroundColor: NSColor.Syntax.number], range: match.range(at: 2)) + [.foregroundColor: NSColor.Theme.Syntax.number], range: match.range(at: 2)) textStorage.addAttributes( - [.foregroundColor: NSColor.Syntax.number], range: match.range(at: 3)) + [.foregroundColor: NSColor.Theme.Syntax.number], range: match.range(at: 3)) } matches = stageRegex.matches(in: textStorage.string, options: [], range: range) for match in matches { textStorage.addAttributes( - [.foregroundColor: NSColor.Syntax.option], range: match.range(at: 1)) + [.foregroundColor: NSColor.Theme.Syntax.option], range: match.range(at: 1)) textStorage.addAttributes( - [.foregroundColor: NSColor.Syntax.number], range: match.range(at: 2)) + [.foregroundColor: NSColor.Theme.Syntax.number], range: match.range(at: 2)) } matches = groupRegex.matches(in: textStorage.string, options: [], range: range) for match in matches { textStorage.addAttributes( - [.foregroundColor: NSColor.Syntax.option], range: match.range(at: 1)) + [.foregroundColor: NSColor.Theme.Syntax.option], range: match.range(at: 1)) textStorage.addAttributes( - [.foregroundColor: NSColor.Syntax.vertex], range: match.range(at: 2)) + [.foregroundColor: NSColor.Theme.Syntax.vertex], range: match.range(at: 2)) } } } diff --git a/Map/Presentation/MapEditor.swift b/Map/Presentation/MapEditor.swift index 1e25ce8..5dc1adb 100644 --- a/Map/Presentation/MapEditor.swift +++ b/Map/Presentation/MapEditor.swift @@ -92,11 +92,12 @@ struct MapEditor: View { adaptiveStack { ZStack(alignment: .topLeading) { MapTextEditor(document: $document, highlightRanges: results, selectedRange: selectedTerm) - .background(Color.UI.background) - .foregroundColor(Color.UI.foreground) + .background(Color.Theme.UI.background) + .foregroundColor(Color.Theme.UI.foreground) .frame(minHeight: 96.0) - }.padding(.top, 8.0).padding(.leading, 8.0).background(Color.UI.background).cornerRadius( - 5.0) + } + .background(Color.Theme.UI.background) + .cornerRadius(5.0) GeometryReader { geometry in ScrollView([.horizontal, .vertical]) { MapRenderView( @@ -104,7 +105,7 @@ struct MapEditor: View { ).scaleEffect(zoom, anchor: .center).frame( width: (Dimensions.Map.size.width + 2 * Dimensions.Map.padding) * zoom, height: (Dimensions.Map.size.height + 2 * Dimensions.Map.padding) * zoom) - }.background(Color.UI.background) + }.background(Color.Theme.UI.background) .gesture( MagnificationGesture() .onChanged { value in @@ -140,11 +141,12 @@ struct MapEditor: View { ).frame(width: 200).padding(.trailing, 10.0) }.padding(4.0) }.toolbar { - HStack { + ToolbarItem(placement: .primaryAction) { EvolutionPicker(selectedEvolution: $selectedEvolution) } - }.focusedSceneValue(\.isSearching, $isSearching) - .focusedSceneValue(\.selectedEvolution, $selectedEvolution) + } + .focusedSceneValue(\.isSearching, $isSearching) + .focusedSceneValue(\.selectedEvolution, $selectedEvolution) } @ViewBuilder @@ -173,5 +175,5 @@ struct MapEditor: View { } #Preview { - MapEditor(document: .constant(MapDocument()), url: URL(filePath: "test.png")!) + MapEditor(document: .constant(MapDocument()), url: URL(filePath: "test.wmap")!) } diff --git a/Map/Presentation/Theme/Color+theme.swift b/Map/Presentation/Theme/Color+theme.swift index ee80e82..22dc18b 100644 --- a/Map/Presentation/Theme/Color+theme.swift +++ b/Map/Presentation/Theme/Color+theme.swift @@ -29,31 +29,32 @@ extension Color { static let lightNeutralGray = Color("Light Neutral Gray") static let darkNeutralGray = Color("Dark Neutral Gray") static let darkerNeutralGray = Color("Darker Neutral Gray") - } - - // MARK: - General - - struct UI { - static let foreground = Color("Foreground") - static let background = Color("Background") - } - // MARK: - The Map - - struct Map { - static let labelColor = Color.Theme.darkSlate - static let axisColor = Color.Theme.darkSlate - static let vertexColor = Color.Theme.darkSlate - static let blockerColor = Color.Theme.jasperRed - static let opportunityColor = Color.Theme.olympicBlue - static let stageForeground = Color.Theme.lightNeutralGray - static let stageBackground = Color.white - static let groupColors = [ - Color.Theme.olympicBlue, - Color.Theme.jasperRed, - Color.Theme.lightPorcelainGreen, - Color.Theme.naplesYellow, - Color.Theme.hermosaPink, - ] + // MARK: - General + + struct UI { + static let foreground = Color("Foreground") + static let background = Color("Background") + static let accent = Color.Theme.jasperRed + } + + // MARK: - The Map + + struct Map { + static let labelColor = Color.Theme.darkSlate + static let axisColor = Color.Theme.darkSlate + static let vertexColor = Color.Theme.darkSlate + static let blockerColor = Color.Theme.jasperRed + static let opportunityColor = Color.Theme.olympicBlue + static let stageForeground = Color.Theme.lightNeutralGray + static let stageBackground = Color.white + static let groupColors = [ + Color.Theme.olympicBlue, + Color.Theme.jasperRed, + Color.Theme.lightPorcelainGreen, + Color.Theme.naplesYellow, + Color.Theme.hermosaPink, + ] + } } } diff --git a/Map/Presentation/Theme/Dimensions.swift b/Map/Presentation/Theme/Dimensions.swift index 2e1fd69..7df3f1a 100644 --- a/Map/Presentation/Theme/Dimensions.swift +++ b/Map/Presentation/Theme/Dimensions.swift @@ -19,10 +19,10 @@ struct Dimensions { // MARK: - Fonts struct FontSize { - static let body: CGFloat = 16 + static let body: CGFloat = 15 static let title: CGFloat = 32 - static let caption: CGFloat = 14 - static let smallControl: CGFloat = 9 + static let caption: CGFloat = 13 + static let smallControl: CGFloat = 11 struct Map { static let note: CGFloat = 12 @@ -55,8 +55,16 @@ struct Dimensions { } // MARK: - The Map + struct Map { static let size = CGSize(width: 1300.0, height: 1000.0) static let padding: CGFloat = 42.0 } + + // MARK: - Assorted Controls + struct EvolutionPicker { + static let radius = 8.0 + static let controlSize = 8.0 + static let controlSpacing = 3.0 + } } diff --git a/Map/Presentation/Theme/Font+theme.swift b/Map/Presentation/Theme/Font+theme.swift index 2fb56f7..cc80fc4 100644 --- a/Map/Presentation/Theme/Font+theme.swift +++ b/Map/Presentation/Theme/Font+theme.swift @@ -24,17 +24,8 @@ extension Font { return .custom("Ronzino", size: size) } - static func ronzinoMedium(size: CGFloat) -> Font { - return .custom("RonzinoMedium", size: size) - } - public struct Theme { - // Map - static let note = Font.system(size: 12, design: .serif) - static let axisLabel = Font.system(size: 14, design: .serif) - static let vertexLabel = Font.system(size: 12, design: .serif) - struct Body { static let regular = Font.ronzino(size: Dimensions.FontSize.body).weight(.regular) static let emphasized = Font.ronzino(size: Dimensions.FontSize.body).weight(.medium) @@ -51,6 +42,7 @@ extension Font { struct SmallControl { static let regular = Font.ronzino(size: Dimensions.FontSize.smallControl).weight(.regular) + static let emphasized = Font.ronzino(size: Dimensions.FontSize.smallControl).weight(.medium) } struct Map { diff --git a/Map/Presentation/Theme/Fonts/LibertinusSerif-Regular.otf b/Map/Presentation/Theme/Fonts/LibertinusSerif-Regular.otf new file mode 100644 index 0000000..508f3c0 Binary files /dev/null and b/Map/Presentation/Theme/Fonts/LibertinusSerif-Regular.otf differ diff --git a/Map/Presentation/Theme/Fonts/Ronzino-Medium.otf b/Map/Presentation/Theme/Fonts/Ronzino-Medium.otf new file mode 100644 index 0000000..0be8dd5 Binary files /dev/null and b/Map/Presentation/Theme/Fonts/Ronzino-Medium.otf differ diff --git a/Map/Presentation/Theme/Fonts/Ronzino-Regular.otf b/Map/Presentation/Theme/Fonts/Ronzino-Regular.otf new file mode 100644 index 0000000..8b70471 Binary files /dev/null and b/Map/Presentation/Theme/Fonts/Ronzino-Regular.otf differ diff --git a/Map/Presentation/Theme/LibertinusSerif-Regular.otf b/Map/Presentation/Theme/LibertinusSerif-Regular.otf deleted file mode 100644 index 508f3c0..0000000 Binary files a/Map/Presentation/Theme/LibertinusSerif-Regular.otf and /dev/null differ diff --git a/Map/Presentation/Theme/NSColor+theme.swift b/Map/Presentation/Theme/NSColor+theme.swift index 61b5498..874764d 100644 --- a/Map/Presentation/Theme/NSColor+theme.swift +++ b/Map/Presentation/Theme/NSColor+theme.swift @@ -15,17 +15,21 @@ import AppKit extension NSColor { - struct Syntax { - static let vertex = NSColor(named: "Vertex") ?? .textColor - static let number = NSColor(named: "Number") ?? .textColor - static let option = NSColor(named: "Option") ?? .textColor - static let symbol = NSColor(named: "Symbol") ?? .textColor - static let match = (NSColor(named: "Light Neutral Gray") ?? .textColor).withAlphaComponent(0.3) - static let highlightMatch = (NSColor(named: "Naples Yellow") ?? .textColor).withAlphaComponent( - 0.3) - } + struct Theme { + struct Syntax { + static let vertex = NSColor(named: "Vertex") ?? .textColor + static let number = NSColor(named: "Number") ?? .textColor + static let option = NSColor(named: "Option") ?? .textColor + static let symbol = NSColor(named: "Symbol") ?? .textColor + static let match = (NSColor(named: "Light Neutral Gray") ?? .textColor).withAlphaComponent( + 0.3) + static let highlightMatch = (NSColor(named: "Naples Yellow") ?? .textColor) + .withAlphaComponent( + 0.3) + } - struct UI { - static let background = NSColor(named: "Background") ?? .windowBackgroundColor + struct UI { + static let background = NSColor(named: "Background") ?? .windowBackgroundColor + } } } diff --git a/Map/Presentation/Theme/Ronzino-Medium.otf b/Map/Presentation/Theme/Ronzino-Medium.otf deleted file mode 100644 index 0be8dd5..0000000 Binary files a/Map/Presentation/Theme/Ronzino-Medium.otf and /dev/null differ diff --git a/Map/Presentation/Theme/Ronzino-Regular.otf b/Map/Presentation/Theme/Ronzino-Regular.otf deleted file mode 100644 index 8b70471..0000000 Binary files a/Map/Presentation/Theme/Ronzino-Regular.otf and /dev/null differ diff --git a/README.md b/README.md index 8726c84..9134668 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ A wardley mapping tool: Write some text, get a diagram Open the project in Xcode and press the run button (or `make build`) -## Building +## Testing Open the project in Xcode and press the test button (or `make test`) -- cgit