diff --git a/FontFace.xcodeproj/project.pbxproj b/FontFace.xcodeproj/project.pbxproj index 920ec7f..c0f9a07 100644 --- a/FontFace.xcodeproj/project.pbxproj +++ b/FontFace.xcodeproj/project.pbxproj @@ -16,6 +16,9 @@ 5705572E262C5F8B004A1FE3 /* FontModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5705572D262C5F8B004A1FE3 /* FontModel.swift */; }; 57055733262C602A004A1FE3 /* CharacterCellView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 57055732262C602A004A1FE3 /* CharacterCellView.swift */; }; 5705573A262C61DF004A1FE3 /* NSCharacterSetExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 57055739262C61DF004A1FE3 /* NSCharacterSetExtension.swift */; }; + 57EDE58B262DC13600D4533C /* CharacterGraidView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 57EDE58A262DC13600D4533C /* CharacterGraidView.swift */; }; + 57EDE58F262DC22500D4533C /* FontProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 57EDE58E262DC22500D4533C /* FontProvider.swift */; }; + 57EDE593262DC5FC00D4533C /* AvailableFontListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 57EDE592262DC5FC00D4533C /* AvailableFontListView.swift */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ @@ -30,6 +33,9 @@ 5705572D262C5F8B004A1FE3 /* FontModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FontModel.swift; sourceTree = ""; }; 57055732262C602A004A1FE3 /* CharacterCellView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CharacterCellView.swift; sourceTree = ""; }; 57055739262C61DF004A1FE3 /* NSCharacterSetExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NSCharacterSetExtension.swift; sourceTree = ""; }; + 57EDE58A262DC13600D4533C /* CharacterGraidView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CharacterGraidView.swift; sourceTree = ""; }; + 57EDE58E262DC22500D4533C /* FontProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FontProvider.swift; sourceTree = ""; }; + 57EDE592262DC5FC00D4533C /* AvailableFontListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AvailableFontListView.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -103,6 +109,7 @@ isa = PBXGroup; children = ( 5705572D262C5F8B004A1FE3 /* FontModel.swift */, + 57EDE58E262DC22500D4533C /* FontProvider.swift */, ); path = Model; sourceTree = ""; @@ -111,6 +118,8 @@ isa = PBXGroup; children = ( 57055732262C602A004A1FE3 /* CharacterCellView.swift */, + 57EDE58A262DC13600D4533C /* CharacterGraidView.swift */, + 57EDE592262DC5FC00D4533C /* AvailableFontListView.swift */, ); path = View; sourceTree = ""; @@ -232,8 +241,11 @@ 5705571D262C5EA1004A1FE3 /* ContentView.swift in Sources */, 5705571B262C5EA1004A1FE3 /* FontFaceApp.swift in Sources */, 5705572E262C5F8B004A1FE3 /* FontModel.swift in Sources */, + 57EDE58B262DC13600D4533C /* CharacterGraidView.swift in Sources */, + 57EDE593262DC5FC00D4533C /* AvailableFontListView.swift in Sources */, 5705573A262C61DF004A1FE3 /* NSCharacterSetExtension.swift in Sources */, 57055733262C602A004A1FE3 /* CharacterCellView.swift in Sources */, + 57EDE58F262DC22500D4533C /* FontProvider.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/FontFace.xcodeproj/project.xcworkspace/xcuserdata/lvjun.xcuserdatad/UserInterfaceState.xcuserstate b/FontFace.xcodeproj/project.xcworkspace/xcuserdata/lvjun.xcuserdatad/UserInterfaceState.xcuserstate index 959a580..2f77a87 100644 Binary files a/FontFace.xcodeproj/project.xcworkspace/xcuserdata/lvjun.xcuserdatad/UserInterfaceState.xcuserstate and b/FontFace.xcodeproj/project.xcworkspace/xcuserdata/lvjun.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/Shared/ContentView.swift b/Shared/ContentView.swift index 55c78b3..f34ac28 100644 --- a/Shared/ContentView.swift +++ b/Shared/ContentView.swift @@ -9,54 +9,18 @@ import SwiftUI struct ContentView: View { - let columns = [ - GridItem(.flexible()), - GridItem(.flexible()), - GridItem(.flexible()), - GridItem(.flexible()), - GridItem(.flexible()), - GridItem(.flexible()), - ] + @State private var selectedFontFamily: String = "" + @State private var selectedFontName: String = "" var body: some View { - ZStack(alignment: .top) { - ScrollView { - LazyVGrid(columns: columns) { - ForEach(fetchFontList(), id: \.self) { characterModel in - CharacterCellView(name: "PingFang", characterModel: characterModel) - } - } + NavigationView { + AvailableFontListView(selectedFontFamily: $selectedFontFamily, selectedFontName: $selectedFontName) + CharacterGraidView(selectedFontFamily: $selectedFontFamily, selectedFontName: $selectedFontName) } } - .padding() - .frame(minWidth: 600, idealWidth: 700, minHeight: 400, idealHeight: 800, alignment: .center) - .toolbar { - ToolbarItem(placement: .primaryAction) { - Menu { - - } label: { - Image(systemName: "square.and.arrow.up.on.square.fill") - } - } - } - } } -/// 获取字符集及其 Unicode -/// - Returns: StringCharacter -func fetchFontList() -> [CharacterModel] { - if let name = NSFontManager.shared.availableFontFamilies.first { - - if let font = NSFontManager.shared.font(withFamily: name, traits: .boldFontMask, weight: 1, size: 30) { - - let set = font.coveredCharacterSet as NSCharacterSet - - return set.characters - } - } - - return [] -} + struct ContentView_Previews: PreviewProvider { static var previews: some View { diff --git a/Shared/Model/FontModel.swift b/Shared/Model/FontModel.swift index 96183ec..65351b1 100644 --- a/Shared/Model/FontModel.swift +++ b/Shared/Model/FontModel.swift @@ -9,7 +9,7 @@ import Foundation struct FontModel: Hashable { var name: String - var characters: [CharacterModel] + var familyName: String } struct CharacterModel: Hashable { @@ -17,6 +17,6 @@ struct CharacterModel: Hashable { var unicode: String } -let mockFontModel = FontModel(name: "PingFang", characters: [mockCharacterModel]) +let mockFontModel = FontModel(name: "PingFang", familyName: "PingFang") let mockCharacterModel = CharacterModel(character: "T", unicode: "\u{e638}") diff --git a/Shared/Model/FontProvider.swift b/Shared/Model/FontProvider.swift new file mode 100644 index 0000000..d594579 --- /dev/null +++ b/Shared/Model/FontProvider.swift @@ -0,0 +1,37 @@ +// +// FontProvider.swift +// FontFace (macOS) +// +// Created by 吕俊 on 2021/4/19. +// + +import Cocoa + +class FontProvider { + static let shared = FontProvider() + private init() {} + + /// Fetch CharacterModel for given font family + /// - Returns: CharacterModel List + func fetchCharacterList(familyName: String) -> [CharacterModel] { + + guard let font = NSFontManager.shared.font(withFamily: familyName, traits: .smallCapsFontMask, weight: 1, size: 30) else { return [] } + + let set = font.coveredCharacterSet as NSCharacterSet + + return set.characters.filter({ !$0.character.isEmpty || !$0.unicode.isEmpty}) + } + + /// Fetch available font List + /// - Returns: FontModel List + func fetchAvailableFontList() -> [FontModel] { + + return NSFontManager.shared.availableFontFamilies + .compactMap({NSFontManager.shared.font(withFamily: $0, traits: .boldFontMask, weight: 1, size: 30)}) + .compactMap { font -> FontModel? in + guard let name = font.displayName else { return nil } + guard let familyName = font.familyName else { return nil } + return FontModel(name: name, familyName: familyName) + } + } +} diff --git a/Shared/Utils/NSCharacterSetExtension.swift b/Shared/Utils/NSCharacterSetExtension.swift index f10bc1d..55fd100 100644 --- a/Shared/Utils/NSCharacterSetExtension.swift +++ b/Shared/Utils/NSCharacterSetExtension.swift @@ -22,7 +22,6 @@ extension NSCharacterSet { let unicodeValue = String(data: dataenc!, encoding: String.Encoding.utf8) ?? "" let v = CharacterModel(character: String(s), unicode: unicodeValue) - results.append(v) } } diff --git a/Shared/View/AvailableFontListView.swift b/Shared/View/AvailableFontListView.swift new file mode 100644 index 0000000..158f959 --- /dev/null +++ b/Shared/View/AvailableFontListView.swift @@ -0,0 +1,42 @@ +// +// AvailableFontListView.swift +// FontFace (macOS) +// +// Created by 吕俊 on 2021/4/19. +// + +import SwiftUI + +struct AvailableFontListView: View { + + @Binding var selectedFontFamily: String + + @Binding var selectedFontName: String + + var body: some View { + ScrollView { + LazyVStack(alignment: .leading) { + ForEach(FontProvider.shared.fetchAvailableFontList(), id: \.self) { fontModel in + HStack { + Text(fontModel.name) + .font(.body) + .padding() + + Spacer() + } + .onTapGesture { + selectedFontFamily = fontModel.familyName + selectedFontName = fontModel.name + } + .background(fontModel.name == selectedFontName ? Color.red : Color.clear) + } + } + } + } +} + +struct AvailableFontListView_Previews: PreviewProvider { + static var previews: some View { + AvailableFontListView(selectedFontFamily: .constant(""), selectedFontName: .constant("")) + } +} diff --git a/Shared/View/CharacterGraidView.swift b/Shared/View/CharacterGraidView.swift new file mode 100644 index 0000000..08e4aea --- /dev/null +++ b/Shared/View/CharacterGraidView.swift @@ -0,0 +1,65 @@ +// +// CharacterGraidView.swift +// FontFace (macOS) +// +// Created by 吕俊 on 2021/4/19. +// + +import SwiftUI + +struct CharacterGraidView: View { + + @Binding var selectedFontFamily: String + @Binding var selectedFontName: String + + let columns = [ + GridItem(.flexible()), + GridItem(.flexible()), + GridItem(.flexible()), + GridItem(.flexible()), + GridItem(.flexible()), + GridItem(.flexible()), + ] + + var body: some View { + ZStack(alignment: .top) { + let list = FontProvider.shared.fetchCharacterList(familyName: selectedFontFamily) + + if list.isEmpty { + Text("Select a font to preview") + .font(.title) + } else { + ScrollView { + LazyVGrid(columns: columns) { + ForEach(list, id: \.self) { characterModel in + CharacterCellView(name: selectedFontName, characterModel: characterModel) + } + } + } + } + } + .padding() + .frame(minWidth: 600, idealWidth: 700, minHeight: 400, idealHeight: 800, alignment: .center) + .toolbar { + ToolbarItem(placement: .primaryAction) { + Menu { + + } label: { + Image(systemName: "square.and.arrow.up.on.square.fill") + } + } + } + } + + func empty() -> Bool { + return true + } +} + + + +struct CharacterGraidView_Previews: PreviewProvider { + static var previews: some View { + CharacterGraidView(selectedFontFamily: .constant("PingFang"), selectedFontName: .constant("PingFang")) + } +}