Skip to content

Commit 0f69501

Browse files
committed
iconfont 类代码生成器
1 parent 10b58dd commit 0f69501

21 files changed

+777
-145
lines changed

assets/iconfont/icon_builder.dart

-49
This file was deleted.

assets/iconfont/iconfont.ttf

264 Bytes
Binary file not shown.

lib/app/navigation/desk_ui/unit_desk_navigation.dart

+1-1
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ class _UnitDeskNavigationState extends State<UnitDeskNavigation> {
6565
onItemClick: _onItemClick, itemData: {
6666
//底栏图标
6767
"组件集录": TolyIcon.icon_layout, "收藏集录": TolyIcon.icon_star,
68-
"绘制集录": Icons.palette, "代码生成": Icons.widgets,
68+
"绘制集录": Icons.palette, "代码生成": TolyIcon.icon_fast,
6969
"要点集录": TolyIcon.icon_bug,
7070
},
7171
),

lib/code_gen/code_gen_page.dart

+32-12
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import 'dart:io';
2-
3-
import 'package:file_selector/file_selector.dart';
42
import 'package:flutter/material.dart';
3+
import 'package:flutter_unit/code_gen/icon_font_gen/icon_font_gen_page.dart';
54

65
import 'class_generator.dart';
76
import 'desk_widget_top_bar.dart';
@@ -22,6 +21,7 @@ class CodeGenPage extends StatefulWidget {
2221
class _CodeGenPageState extends State<CodeGenPage> {
2322

2423
TextEditingController _dirPath = TextEditingController();
24+
final PageController _ctrl = PageController();
2525
int selectIndex = 0;
2626

2727
final List<String> selectData = [
@@ -50,12 +50,30 @@ class _CodeGenPageState extends State<CodeGenPage> {
5050
children: [
5151
DeskCodeGenTopBar(
5252
onTapGen: _doGen,
53-
onTabPressed: (int value) {},
53+
onTabPressed: (int value) {
54+
_ctrl.jumpToPage(value);
55+
},
5456
),
55-
Expanded(child: Center(
56-
child: Text(
57-
'敬请期待'
58-
),
57+
Expanded(child: PageView(
58+
controller:_ctrl,
59+
children: [
60+
IconFontGenPage(),
61+
Center(
62+
child: Text(
63+
'敬请期待'
64+
),
65+
),
66+
Center(
67+
child: Text(
68+
'敬请期待'
69+
),
70+
),
71+
Center(
72+
child: Text(
73+
'敬请期待'
74+
),
75+
)
76+
],
5977
)),
6078
if(false)
6179
Padding(
@@ -64,11 +82,11 @@ class _CodeGenPageState extends State<CodeGenPage> {
6482
children: [
6583
GestureDetector(
6684
onTap: () async{
67-
final String? directoryPath = await getDirectoryPath();
68-
if (directoryPath != null) {
69-
print("====$directoryPath=========");
70-
_dirPath.text = directoryPath;
71-
}
85+
// final String? directoryPath = await getDirectoryPath();
86+
// if (directoryPath != null) {
87+
// print("====$directoryPath=========");
88+
// _dirPath.text = directoryPath;
89+
// }
7290
},
7391
child: Icon(Icons.file_copy_outlined)),
7492
SizedBox(width: 20,),
@@ -124,6 +142,8 @@ class _CodeGenPageState extends State<CodeGenPage> {
124142
clazz1.write2File(Directory(_dirPath.text));
125143
}
126144
}
145+
146+
127147
}
128148

129149
class GenInput extends StatelessWidget {

lib/code_gen/desk_widget_top_bar.dart

+2-7
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ class DeskCodeGenTopBar extends StatefulWidget {
1919
class _DeskCodeGenTopBarState extends State<DeskCodeGenTopBar> with SingleTickerProviderStateMixin {
2020
late TabController tabController;
2121

22-
static const List<String> _tabs = ['数据类', 'IconFont', '状态管理', 'Json 解析',];
22+
static const List<String> _tabs = ['IconFont', '数据类' , '状态管理', 'Json 解析',];
2323

2424
@override
2525
void initState() {
@@ -62,12 +62,7 @@ class _DeskCodeGenTopBarState extends State<DeskCodeGenTopBar> with SingleTicke
6262
),
6363
),
6464
Spacer(),
65-
ElevatedButton(
66-
style: ElevatedButton.styleFrom(
67-
elevation: 0,
68-
shape: StadiumBorder()
69-
),
70-
onPressed: widget.onTapGen, child: Text('生成代码')),
65+
7166
const SizedBox(width: 20,),
7267
WindowButtons(),
7368
],
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
2+
import 'package:app_config/app_config.dart';
3+
import 'package:flutter/material.dart';
4+
5+
6+
7+
class GenMessageAction extends StatelessWidget {
8+
final VoidCallback onGen;
9+
const GenMessageAction({Key? key, required this.onGen}) : super(key: key);
10+
11+
@override
12+
Widget build(BuildContext context) {
13+
return Row(
14+
crossAxisAlignment: CrossAxisAlignment.start,
15+
children: [
16+
Expanded(child: Text(
17+
'使用方式:\n1. 在 iconfont.cn 挑选图标,加入项目,下载压缩包。\n2. 选择 Flutter 项目地址,配置资源、产物文件位置。\n3. 点击生成代码按钮,即可生成相关代码。',
18+
style: TextStyle(
19+
color: Theme.of(context).primaryColor,fontWeight: FontWeight.bold),)),
20+
ElevatedButton(
21+
style: ElevatedButton.styleFrom(
22+
elevation: 0,
23+
shape: const StadiumBorder()
24+
),
25+
onPressed:onGen, child: Wrap(
26+
crossAxisAlignment: WrapCrossAlignment.center,
27+
spacing: 4,
28+
children: [
29+
Icon(TolyIcon.icon_fast,size: 16,),
30+
const Text('生成代码',style: TextStyle(height: 1,fontSize: 12),),
31+
],
32+
)),
33+
],
34+
);
35+
}
36+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
import 'dart:convert';
2+
import 'dart:io';
3+
import 'package:archive/archive_io.dart';
4+
5+
import 'icon_font_gen_config.dart';
6+
import 'package:path/path.dart' as path;
7+
8+
class IconFontClassParser{
9+
10+
void gen(IconFontGenConfig config){
11+
final inputStream = InputFileStream(config.srcZip);
12+
// 将压缩包有用资源解压到目标文件
13+
final archive = ZipDecoder().decodeBuffer(inputStream);
14+
for (var file in archive.files) {
15+
if (file.isFile) {
16+
if (file.name.endsWith('.ttf')) {
17+
final outputStream = OutputFileStream(config.ttfDistPath);
18+
file.writeContent(outputStream);
19+
outputStream.close();
20+
}
21+
if (file.name.endsWith('.json')) {
22+
dynamic data = file.content;
23+
String jsonContent = utf8.decode(data);
24+
String resultCode = parser(jsonContent,config.fontFamily);
25+
File distFile = File(config.distFilePath);
26+
if(!distFile.existsSync()){
27+
distFile.createSync(recursive: true);
28+
}
29+
distFile.writeAsStringSync(resultCode);
30+
setYaml(config);
31+
}
32+
}
33+
}
34+
}
35+
36+
String parser(String input,String fontFamily){
37+
dynamic map = json.decode(input);
38+
List<dynamic> glyphs = map['glyphs'] as List<dynamic>;
39+
String code = '';
40+
for(int i=0;i<glyphs.length;i++){
41+
String fieldName = glyphs[i]['font_class'];
42+
String unicode = glyphs[i]['unicode'];
43+
String lineCode = """static const IconData $fieldName = IconData(0x$unicode, fontFamily: "$fontFamily");\n""";
44+
code+=lineCode;
45+
}
46+
47+
String result =
48+
"""
49+
import 'package:flutter/widgets.dart';
50+
// Power By 张风捷特烈--- Generated file. Do not edit.
51+
// 欢迎支持: https://github.com/toly1994328/FlutterUnit
52+
class $fontFamily {
53+
$fontFamily._();
54+
$code
55+
}
56+
""";
57+
return result;
58+
}
59+
60+
// 修改 pubspec.yaml
61+
void setYaml(IconFontGenConfig config){
62+
String familyName = config.fontFamily;
63+
String fontAssetsDist = config.yamlAssetDist;
64+
final String filePath = path.join(config.projectPath,'pubspec.yaml');
65+
// final String filePath = r'E:\Projects\Flutter\FlutterUnit\pubspec.yaml';
66+
67+
File pubspecFile = File(filePath);
68+
69+
List<String> lines = pubspecFile.readAsLinesSync();
70+
71+
RegExp fontsRegex = RegExp(r'^ fonts:',multiLine: true);
72+
bool hasFonts = fontsRegex.hasMatch(lines.join('\n'));
73+
74+
if(!hasFonts){
75+
// 当前没有 fonts 节点,需要添加到 flutter 节点下
76+
int index = lines.indexWhere((e) => e.startsWith('flutter:'));
77+
List<String> fonts = [
78+
' fonts:',
79+
' - family: $familyName',
80+
' fonts:',
81+
' - asset: $fontAssetsDist',
82+
];
83+
84+
lines.insertAll(index+1, fonts);
85+
pubspecFile.writeAsStringSync(lines.join('\n'));
86+
return;
87+
}
88+
// 存在 fonts 节点,查询 family ,有没有当前字体图标
89+
bool hasTargetFamily = false;
90+
RegExp regExp = RegExp(r'^ +- family: +(\w+)');
91+
92+
for(int i=0;i<lines.length;i++){
93+
String line = lines[i];
94+
if(line.startsWith(regExp)){
95+
String family = regExp.allMatches(line).first.group(1)??'';
96+
if(family == familyName){
97+
hasTargetFamily = true;
98+
break;
99+
}
100+
}
101+
}
102+
if(!hasTargetFamily){
103+
int index = lines.indexWhere((e) => e.startsWith(fontsRegex));
104+
List<String> fonts = [
105+
' - family: $familyName',
106+
' fonts:',
107+
' - asset: $fontAssetsDist',
108+
];
109+
lines.insertAll(index+1, fonts);
110+
pubspecFile.writeAsStringSync(lines.join('\n'));
111+
return;
112+
}
113+
}
114+
115+
// // 修改 pubspec.yaml
116+
// void setYaml(IconFontGenConfig config){
117+
// String fontFamily = config.fontFamily;
118+
// String assets = config.assetsDist.replaceAll('\\', '/');
119+
//
120+
// final String filePath = path.join(config.projectPath,'pubspec.yaml');
121+
// File pubspecFile = File(filePath);
122+
// final String pubspec = pubspecFile.readAsStringSync();
123+
// final doc = loadYaml(pubspec);
124+
// final modifiableDoc = getModifiableNode(doc);
125+
//
126+
// YamlList? fontsList = doc['flutter']['fonts'] as YamlList?;
127+
// if(fontsList == null){
128+
// // 新文件,没有配置 fonts 节点
129+
// modifiableDoc['flutter']['fonts'] = YamlMap.wrap({
130+
// 'family': fontFamily,
131+
// 'fonts':YamlList.wrap([YamlMap.wrap({'asset':'$assets/iconfont.ttf'})])
132+
// });
133+
// }else{
134+
// final modifiableList = getModifiableNode(fontsList);
135+
// modifiableList.removeWhere((e) => e['family'] == fontFamily);
136+
// modifiableList.add(
137+
// YamlMap.wrap({
138+
// 'family': fontFamily,
139+
// 'fonts':YamlList.wrap([YamlMap.wrap({'asset':'$assets/iconfont.ttf'})])
140+
// })
141+
// );
142+
// modifiableDoc['flutter']['fonts'] = modifiableList;
143+
// }
144+
// final targetYaml = toYamlString(modifiableDoc);
145+
// pubspecFile.writeAsStringSync(targetYaml);
146+
// }
147+
148+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import 'package:path/path.dart' as path;
2+
3+
class IconFontGenConfig {
4+
final String srcZip;
5+
final String projectPath;
6+
final String assetsDist;
7+
final String fileDist;
8+
9+
IconFontGenConfig({
10+
this.srcZip = '',
11+
this.projectPath = '',
12+
String? assetsDist,
13+
String? fileDist,
14+
}) : fileDist = fileDist ?? 'lib${spa}app${spa}gen${spa}toly_icon.dart',
15+
assetsDist = assetsDist ?? 'assets${spa}iconfont';
16+
17+
static String get spa => path.separator;
18+
19+
String get distFilePath => path.join(projectPath, fileDist);
20+
21+
String get distAssetsDir => path.join(projectPath, assetsDist);
22+
23+
String get ttfDistPath => path.join(distAssetsDir, path.basenameWithoutExtension(fileDist)+".ttf");
24+
25+
String get yamlAssetDist => assetsDist.replaceAll('\\', '/')+"/"+path.basename(ttfDistPath);
26+
27+
String get fontFamily => path
28+
.basenameWithoutExtension(fileDist)
29+
.split('_')
30+
.map((e) => e[0].toUpperCase() + e.substring(1,))
31+
.join('');
32+
33+
factory IconFontGenConfig.fromJson(Map<String, dynamic> map) {
34+
return IconFontGenConfig(
35+
srcZip: map['srcZip'] ?? '',
36+
projectPath: map['projectPath'] ?? '',
37+
assetsDist: map["assetsDist"] ?? '',
38+
fileDist: map["fileDist"] ?? '');
39+
}
40+
41+
Map<String, dynamic> toJson() => {
42+
'srcZip': srcZip,
43+
'projectPath': projectPath,
44+
'assetsDist': assetsDist,
45+
'fileDist': fileDist,
46+
};
47+
}

0 commit comments

Comments
 (0)