Add available font list

This commit is contained in:
Akring 2021-04-19 23:55:12 +08:00
parent 0ca6154229
commit 02509206ec
8 changed files with 164 additions and 45 deletions

View File

@ -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 = "<group>"; };
57055732262C602A004A1FE3 /* CharacterCellView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CharacterCellView.swift; sourceTree = "<group>"; };
57055739262C61DF004A1FE3 /* NSCharacterSetExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NSCharacterSetExtension.swift; sourceTree = "<group>"; };
57EDE58A262DC13600D4533C /* CharacterGraidView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CharacterGraidView.swift; sourceTree = "<group>"; };
57EDE58E262DC22500D4533C /* FontProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FontProvider.swift; sourceTree = "<group>"; };
57EDE592262DC5FC00D4533C /* AvailableFontListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AvailableFontListView.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@ -103,6 +109,7 @@
isa = PBXGroup;
children = (
5705572D262C5F8B004A1FE3 /* FontModel.swift */,
57EDE58E262DC22500D4533C /* FontProvider.swift */,
);
path = Model;
sourceTree = "<group>";
@ -111,6 +118,8 @@
isa = PBXGroup;
children = (
57055732262C602A004A1FE3 /* CharacterCellView.swift */,
57EDE58A262DC13600D4533C /* CharacterGraidView.swift */,
57EDE592262DC5FC00D4533C /* AvailableFontListView.swift */,
);
path = View;
sourceTree = "<group>";
@ -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;
};

View File

@ -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)
}
}
}
}
.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")
}
}
NavigationView {
AvailableFontListView(selectedFontFamily: $selectedFontFamily, selectedFontName: $selectedFontName)
CharacterGraidView(selectedFontFamily: $selectedFontFamily, selectedFontName: $selectedFontName)
}
}
}
/// 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 {

View File

@ -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}")

View File

@ -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)
}
}
}

View File

@ -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)
}
}

View File

@ -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(""))
}
}

View File

@ -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"))
}
}