├── LICENSE
├── README.md
├── Stapler-mini-v0.app
└── Contents
│ ├── Info.plist
│ ├── MacOS
│ └── Stapler-mini-v0
│ ├── PkgInfo
│ ├── Resources
│ ├── AppIcon.icns
│ ├── Assets.car
│ ├── Success1.wav
│ ├── Success2.wav
│ ├── en.lproj
│ │ └── Localizable.strings
│ └── ja.lproj
│ │ └── Localizable.strings
│ └── _CodeSignature
│ └── CodeResources
├── Stapler-mini-v0
├── Stapler-mini-v0.xcodeproj
│ ├── project.pbxproj
│ ├── project.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ └── xcuserdata
│ │ │ └── qdpb.xcuserdatad
│ │ │ └── UserInterfaceState.xcuserstate
│ └── xcuserdata
│ │ └── qdpb.xcuserdatad
│ │ └── xcschemes
│ │ └── xcschememanagement.plist
└── Stapler-mini-v0
│ ├── AppDelegate.swift
│ ├── Assets.xcassets
│ ├── AccentColor.colorset
│ │ └── Contents.json
│ ├── AppIcon.appiconset
│ │ ├── Contents.json
│ │ ├── Icon_v0_128x128@1x.png
│ │ ├── Icon_v0_128x128@2x.png
│ │ ├── Icon_v0_16x16@1x.png
│ │ ├── Icon_v0_16x16@2x.png
│ │ ├── Icon_v0_256x256@1x.png
│ │ ├── Icon_v0_256x256@2x.png
│ │ ├── Icon_v0_32x32@1x.png
│ │ ├── Icon_v0_32x32@2x.png
│ │ ├── Icon_v0_512x512@1x.png
│ │ └── Icon_v0_512x512@2x.png
│ ├── Contents.json
│ └── exportFileIcon.iconset
│ │ ├── icon_128x128.png
│ │ ├── icon_128x128@2x.png
│ │ ├── icon_16x16.png
│ │ ├── icon_16x16@2x.png
│ │ ├── icon_256x256.png
│ │ ├── icon_256x256@2x.png
│ │ ├── icon_32x32.png
│ │ ├── icon_32x32@2x.png
│ │ └── icon_512x512.png
│ ├── ContentView.swift
│ ├── Info.plist
│ ├── Keyboard
│ ├── AddPresetSheetView.swift
│ ├── CustomizeKey
│ │ ├── CustomKeyCategory.swift
│ │ ├── CustomizeKeyTabView.swift
│ │ └── CustomizeKeyView_1u.swift
│ ├── EnterCustomShapeView.swift
│ ├── ExportKeyboardView
│ │ ├── CustomUTType.swift
│ │ ├── ExportSheetView.swift
│ │ ├── KeyboardView_AllLayer.swift
│ │ ├── KeyboardView_EachLayer.swift
│ │ ├── Success1.wav
│ │ └── Success2.wav
│ ├── KeyboardKeyView.swift
│ ├── KeyboardView.swift
│ ├── PresetView.swift
│ └── SelectedDetailView.swift
│ ├── Model&KeyCodeList
│ ├── JSONExporter.swift
│ ├── KeyCodeList.swift
│ └── Preset.swift
│ ├── PresetLabelView.swift
│ ├── Preview Content
│ └── Preview Assets.xcassets
│ │ └── Contents.json
│ ├── Stapler-mini-v0App.swift
│ ├── Stapler_mini_v0.entitlements
│ ├── en.lproj
│ └── Localizable.strings
│ └── ja.lproj
│ └── Localizable.strings
└── 大西配列ANSI.stapler
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2024 9dpbQ
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Stapler-mini
2 | 
3 |
4 | ## どんなアプリ?
5 | **Stapler-mini**は[Karabiner-Elements](https://karabiner-elements.pqrs.org/)で使えるjsonファイルを出力するmacOSアプリケーションです。
6 | いわゆる自作キーボードにおける、レイヤー機能・タップホールド機能を、ドラッグ&ドロップで直感的にカスタマイズすることができます。
7 |
8 | ### レイヤー機能って?
9 | レイヤー機能とはあるキーを押しながら他のキー(例えばAとか)を押した時、他のレイヤーで設定しておいたキー(例えばスクショ⌘⇧3)を出力できるようになるような機能です。シフトキーを押しながら数字キーを押した時には数字ではなく記号が入力されますが、その入力される文字を自分で決められるというイメージです。
10 | stapler-mini-v0では8枚のレイヤーを設定することができます。
11 |
12 | ### タップホールド機能って?
13 | タップホールド機能とはキーを単打したときと長押ししたときで入力される文字を打ち分ける機能です。
14 | 例えばシフトキーやその他の修飾キーは単打をしてもキーのDownUpのみが入力されて実用上では全く意味のない入力ですが、そこに好きなショートカットを入れたりすることが可能なわけです。
15 | 反対にescapeやエンターは単打のような使い方しかしないキーなので、それらの長押しに好きな修飾キーのコンビネーションを入れたりもできます。
16 |
17 | ## 使い方
18 |
19 | ### 0.Karabiner-Elementsをダウンロードしておく
20 | [Karabiner-Elements](https://karabiner-elements.pqrs.org/)からダウンロードして、立ち上げて案内の通りに権限を与えます。SimpleModificationで試しに何か書き換えられたら準備完了です。
21 |
22 | ### 1.本アプリをダウンロードする
23 |
24 |
25 |
26 | ### 2.アプリを立ち上げたらPresetを追加する
27 | とりあえず公開版ではMacBookの本体キーボードのレイアウト3種類(US ,UK, JIS)から選ぶことができます。
28 | 最初に入っているVendorIDとProductIDは僕の環境でのMacBookの本体キーボードのIDなので、型番や環境によっては異なる場合があります。Karabiner-Elements側でIDを確認してその値を入力することでそのデバイスの書き換え用のファイルが出力できるようになります。もしくは書き出しした後に一括で編集してください。
29 |
30 | 注意:環境によっては本体キーボードのVendorIDやProductIDがkarabiner側やシステム情報にも表示されないことがあるようです。その場合はLocationIDで条件付け(デバイスの固定値ではないけど本体キーボードなら多分変わらない)でうまくいっているようですが、何か詳しいことがわかる人がいたらDiscordサーバーで知恵を貸してください!
31 | ```
32 | "conditions": [
33 | {
34 | "type": "device_if",
35 | "identifiers": [
36 | {
37 | "is_built_in_keyboard": true
38 | }
39 | ]
40 | }
41 | ]
42 | ```
43 | 本体キーボード限定の書き換えならこっちの方が良いかも。
44 |
45 |
46 | ### 3.キーをドラッグ&ドロップして好きなようにカスタマイズする
47 | 基本は下側のカスタマイズキーを上部のキーボードビューの任意のキーにドラッグ&ドロップしてカスタマイズを行います。
48 |
49 |
50 | また外部キーボードはVendorIDとProductIDをテキストフィールドに入力することでカスタマイズが可能です。
51 | 本体キーボードともともとのキーコードが一部異なるキーボードを使っている場合、そのキーの書き換えはそのままだとうまくいきません(JISだったらControl↔️Caps Lockとかよくあるパターン)。UserCustomJSONから"from"のキーコードを変更することで一応はカスタマイズが可能です。
52 |
53 | 割り当てたキーのリセットは右クリックから行えます。
54 |
55 |
56 |
57 |
58 |
59 | #### タップホールドをカスタムする
60 | 右側のサイドバーか、キーを**ダブルクリック**してポップアップから、**EnableTapHold**をトグルします。TapとHold二つのキーに対してドラッグ&ドロップをしてカスタムできます。
61 | この時タップホールドを有効にしたのにどちらかが空の状態のままだとjsonファイル出力時にエラーが発生するので注意してください。
62 |
63 | ##### タップホールドのタイプについて
64 | とりあえず公開版には3種類のタップホールドタイプがあります。
65 |
66 | ###### Basic
67 | 一定時間以上押下するとホールドの入力になり、それより早く他のキーが押されたり、キーを解放すると単打が入力される方式のベーシックなタップホールドです。
68 | アルファベットのホーム行に修飾キーホールドを入れたい場合や、閾値を長めに取って誤動作をしないようにしたい場合などに有効です。
69 |
70 |
71 | ⚠️注意⚠️現在BasicタイプにLayer遷移キーを入れたときレイヤーから戻らない不具合を確認しています。
72 | ```
73 | "to_if_held_down": [{"halt":true, "set_variable": {"name": "layer1","value": 1}}]
74 | ```
75 | 問題があるのは```"to_if_held_down"```内の```"halt":true```です。ここを消せば問題なく動くはずです。
76 | もしくはUserCustomJSONをトグルした時にはこの不具合は出てないのでタップ・ホールドにキーを入れてトグルするのが楽です。何かわからないことがあれば[Discordサーバー](https://discord.gg/yVhZfsE2zS)で気軽に質問してください!
77 |
78 | ###### Chord
79 | ピアノでの和音のように他のキーと組み合わせた場合にだけホールドのキーが出力されるタイプです。
80 | 閾値を持たず組み合わせの時のみホールドの出力をするのでレイヤーや修飾キーを早い指遣いで使用することができます。レイヤー遷移キーや、よく使うような修飾キーをホールドに入れる場合にこのタイプを使うことを推奨します。
81 |
82 | ###### Repeat
83 | 基本的にはChordと同じ機能ですが、
84 | 「**・ー**」のように一度タップをした後に長押しするとタップキーの長押しになる性質を持っているタイプです。
85 | BackSpaceやDeleteForwardなど、実用上長押しもするキーをタップに入れるときに推奨されるタイプです。
86 |
87 | ※仕組み上、偶数打目のホールドがタップの長押しになる
88 |
89 | #### レイヤーをカスタムする
90 | Specialタブにある色付き数字キーがレイヤー遷移キーです。これをドロップしたキーが押されている間レイヤーのキーを出力するようになります。
91 |
92 |
93 |
94 |
95 |
96 | 例えばこのようにすれば**かな**のタップで **かな**、**かな**のホールドで**レイヤー3**に遷移します。
97 |
98 |
99 |
100 | 遷移キーを設定したらそのレイヤーマップにキーをドラッグ&ドロップしてカスタマイズしましょう。
101 | マウスカーソルの移動や、スクロールなどを行えるレイヤーの例です。
102 |
103 |
104 |
105 | ### 4.jsonファイルとして出力する
106 | 右上の出力ボタンを押してPresetの概要を眺めてみましょう。壮観だなぁ〜!
107 | 実際にキーボードの書き換えを行えるようにjsonとして書き出しましょう。保存されたファイルがFinderで開いたら成功です。👏
108 | エラーが出た場合はエラーメッセージを見て、どのキーに問題があるのかを確認、タップホールドどちらかが空欄問題ではない場合、スクショを[開発者](https://x.com/9dpbQ)に送りつけて文句を言ってください。
109 |
110 | ### 5.出力したファイルをKarabiner-Elementsで有効化する
111 | #### ⚠️⚠️とりあえず公開版3よりKarabinerのインポート画面が自動で開くようになりました⚠️⚠️
112 | Karabiner側でインポート、Enable Allとすれば設定が有効化できます。ファイルはファイル名が数列になっていますが以下のパスに複製されています。
113 | ```
114 | ~/.config/karabiner/assets/complex_modifications
115 | ```
116 |
117 | #### とりあえず公開版2までは以下を参照
118 | まず出力した時に開いたFinderのウィンドウから、**⌘T**か**⌘N**で新しくタブかウィンドウを開いて**⌘⇧G**で以下のパスを開きます。
119 | ```
120 | ~/.config/karabiner/assets/complex_modifications
121 | ```
122 | 出力したjsonファイルをcomplex_modificationsのフォルダ内にドラッグ&ドロップします。
123 |
124 | ドラドロした後はこんな感じ
125 |
126 |
127 |
128 | Karabiner-Elementsを開いてComplexModificationsタブからAdd predifined rule、Enable Allとすれば設定が有効になっているはずです。メモ帳やEventViewerで確認してみてください。
129 | ドラッグ&ドロップしたのに、設定が見当たらない場合、jsonファイルとして欠陥がある可能性があります。テキストエディタでjsonファイルを開いてエラーがある部分を直せば読み込めるようになるはずです。
130 |
131 | ### 6.最強のプリセットを作り込もう!
132 | レイヤーは8枚あるのでそれなりに余裕を持って自分なりの作業環境を構築できるはずです。
133 | アプリ用のレイヤーを作ったり、数字入力用、記号入力用、カーソル用…と用途別に分けても覚えやすいかもしれません。
134 | 画像出力も可能なので[PureRef](https://www.pureref.com/download.php)と組み合わせて常時画面上に表示するみたいなことも可能です。
135 | また、[開発者が自分の設定を作ってる記事](https://note.com/9dpb/n/nf41952e3e799)もあります。アプリ別なコマンドを設定したり、ちょっと細かいところまで説明してるので参考にしてみてください。
136 |
137 | 最強のプリセットが作れたら[Discordコミュニティ](https://discord.gg/yVhZfsE2zS)やXで自慢しよう!要望とかあれば頑張るかもしれない。
138 |
--------------------------------------------------------------------------------
/Stapler-mini-v0.app/Contents/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | BuildMachineOSBuild
6 | 24A348
7 | CFBundleDevelopmentRegion
8 | en
9 | CFBundleDocumentTypes
10 |
11 |
12 | CFBundleTypeIconFile
13 | exportFileIcon
14 | CFBundleTypeIconSystemGenerated
15 | 1
16 | CFBundleTypeName
17 | Stapler
18 | CFBundleTypeRole
19 | Editor
20 | LSHandlerRank
21 | Default
22 | LSItemContentTypes
23 |
24 | com.example.stapler
25 |
26 | NSDocumentClass
27 | NSDocument
28 |
29 |
30 | CFBundleExecutable
31 | Stapler-mini-v0
32 | CFBundleIconFile
33 | AppIcon
34 | CFBundleIconName
35 | AppIcon
36 | CFBundleIdentifier
37 | com.9dpbQ.Stapler-mini-v0
38 | CFBundleInfoDictionaryVersion
39 | 6.0
40 | CFBundleName
41 | Stapler-mini-v0
42 | CFBundlePackageType
43 | APPL
44 | CFBundleShortVersionString
45 | 1.0
46 | CFBundleSupportedPlatforms
47 |
48 | MacOSX
49 |
50 | CFBundleVersion
51 | 1
52 | DTCompiler
53 | com.apple.compilers.llvm.clang.1_0
54 | DTPlatformBuild
55 | 24A336
56 | DTPlatformName
57 | macosx
58 | DTPlatformVersion
59 | 15.0
60 | DTSDKBuild
61 | 24A336
62 | DTSDKName
63 | macosx15.0
64 | DTXcode
65 | 1600
66 | DTXcodeBuild
67 | 16A242d
68 | LSMinimumSystemVersion
69 | 15.0
70 | UTExportedTypeDeclarations
71 |
72 |
73 | UTTypeConformsTo
74 |
75 | public.data
76 |
77 | UTTypeDescription
78 | for drag & drop CustomizeKey
79 | UTTypeIcons
80 |
81 | UTTypeIdentifier
82 | com.example.customizekey
83 | UTTypeTagSpecification
84 |
85 |
86 |
87 | UTTypeConformsTo
88 |
89 | public.data
90 |
91 | UTTypeDescription
92 | for sharing user's Preset
93 | UTTypeIcons
94 |
95 | UTTypeIconBadgeName
96 | exportFileIcon
97 |
98 | UTTypeIdentifier
99 | com.example.stapler
100 | UTTypeTagSpecification
101 |
102 |
103 |
104 |
105 |
106 |
--------------------------------------------------------------------------------
/Stapler-mini-v0.app/Contents/MacOS/Stapler-mini-v0:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/9dpbQ/Stapler-mini-v0/7939b748c37213fb0e04f4bdd383523d72949760/Stapler-mini-v0.app/Contents/MacOS/Stapler-mini-v0
--------------------------------------------------------------------------------
/Stapler-mini-v0.app/Contents/PkgInfo:
--------------------------------------------------------------------------------
1 | APPL????
--------------------------------------------------------------------------------
/Stapler-mini-v0.app/Contents/Resources/AppIcon.icns:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/9dpbQ/Stapler-mini-v0/7939b748c37213fb0e04f4bdd383523d72949760/Stapler-mini-v0.app/Contents/Resources/AppIcon.icns
--------------------------------------------------------------------------------
/Stapler-mini-v0.app/Contents/Resources/Assets.car:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/9dpbQ/Stapler-mini-v0/7939b748c37213fb0e04f4bdd383523d72949760/Stapler-mini-v0.app/Contents/Resources/Assets.car
--------------------------------------------------------------------------------
/Stapler-mini-v0.app/Contents/Resources/Success1.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/9dpbQ/Stapler-mini-v0/7939b748c37213fb0e04f4bdd383523d72949760/Stapler-mini-v0.app/Contents/Resources/Success1.wav
--------------------------------------------------------------------------------
/Stapler-mini-v0.app/Contents/Resources/Success2.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/9dpbQ/Stapler-mini-v0/7939b748c37213fb0e04f4bdd383523d72949760/Stapler-mini-v0.app/Contents/Resources/Success2.wav
--------------------------------------------------------------------------------
/Stapler-mini-v0.app/Contents/Resources/en.lproj/Localizable.strings:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/9dpbQ/Stapler-mini-v0/7939b748c37213fb0e04f4bdd383523d72949760/Stapler-mini-v0.app/Contents/Resources/en.lproj/Localizable.strings
--------------------------------------------------------------------------------
/Stapler-mini-v0.app/Contents/Resources/ja.lproj/Localizable.strings:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/9dpbQ/Stapler-mini-v0/7939b748c37213fb0e04f4bdd383523d72949760/Stapler-mini-v0.app/Contents/Resources/ja.lproj/Localizable.strings
--------------------------------------------------------------------------------
/Stapler-mini-v0.app/Contents/_CodeSignature/CodeResources:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | files
6 |
7 | Resources/AppIcon.icns
8 |
9 | g6/BZy7qYMUW9ZgH7fykkXSXjvM=
10 |
11 | Resources/Assets.car
12 |
13 | jQgr7hjOpuuIOUq3EX/n+xdnZOg=
14 |
15 | Resources/Success1.wav
16 |
17 | UHwH1E1d4qhJOxt7MyFU4bvNsxw=
18 |
19 | Resources/Success2.wav
20 |
21 | J3ia/8Ciygovm1CLW2E7ulYNkzs=
22 |
23 | Resources/en.lproj/Localizable.strings
24 |
25 | hash
26 |
27 | MkvCMtMWMLpfSFb0Knk1rtntp1U=
28 |
29 | optional
30 |
31 |
32 | Resources/ja.lproj/Localizable.strings
33 |
34 | hash
35 |
36 | XpQ7hNqZBxZPdum5Pmh+UqwTF8s=
37 |
38 | optional
39 |
40 |
41 |
42 | files2
43 |
44 | Resources/AppIcon.icns
45 |
46 | hash2
47 |
48 | qn1hjb+xjJHTAopDTAj/mxKAYUcCJPUTSLQnmmFz6do=
49 |
50 |
51 | Resources/Assets.car
52 |
53 | hash2
54 |
55 | fL0ZkkeQwm4iC8VdcVEc+6/XzTFSxTVbTWLjGcjq6bw=
56 |
57 |
58 | Resources/Success1.wav
59 |
60 | hash2
61 |
62 | b1MWIb2k/VPPvbYXqW1/t7TEmNCWmSiGYrDCdFYWE6k=
63 |
64 |
65 | Resources/Success2.wav
66 |
67 | hash2
68 |
69 | 8z1HhfESQr8CghaFlxBboax39+Rh3iCp3PfWCO+gawU=
70 |
71 |
72 | Resources/en.lproj/Localizable.strings
73 |
74 | hash2
75 |
76 | csR/uf0stYQfkJbVSBBZp4vjGL+Xa025wjYDvKMOijY=
77 |
78 | optional
79 |
80 |
81 | Resources/ja.lproj/Localizable.strings
82 |
83 | hash2
84 |
85 | 1pOcPVC+EEsaOsSrZyB+RDOtJ6DRJjTWrXZLQPtbFik=
86 |
87 | optional
88 |
89 |
90 |
91 | rules
92 |
93 | ^Resources/
94 |
95 | ^Resources/.*\.lproj/
96 |
97 | optional
98 |
99 | weight
100 | 1000
101 |
102 | ^Resources/.*\.lproj/locversion.plist$
103 |
104 | omit
105 |
106 | weight
107 | 1100
108 |
109 | ^Resources/Base\.lproj/
110 |
111 | weight
112 | 1010
113 |
114 | ^version.plist$
115 |
116 |
117 | rules2
118 |
119 | .*\.dSYM($|/)
120 |
121 | weight
122 | 11
123 |
124 | ^(.*/)?\.DS_Store$
125 |
126 | omit
127 |
128 | weight
129 | 2000
130 |
131 | ^(Frameworks|SharedFrameworks|PlugIns|Plug-ins|XPCServices|Helpers|MacOS|Library/(Automator|Spotlight|LoginItems))/
132 |
133 | nested
134 |
135 | weight
136 | 10
137 |
138 | ^.*
139 |
140 | ^Info\.plist$
141 |
142 | omit
143 |
144 | weight
145 | 20
146 |
147 | ^PkgInfo$
148 |
149 | omit
150 |
151 | weight
152 | 20
153 |
154 | ^Resources/
155 |
156 | weight
157 | 20
158 |
159 | ^Resources/.*\.lproj/
160 |
161 | optional
162 |
163 | weight
164 | 1000
165 |
166 | ^Resources/.*\.lproj/locversion.plist$
167 |
168 | omit
169 |
170 | weight
171 | 1100
172 |
173 | ^Resources/Base\.lproj/
174 |
175 | weight
176 | 1010
177 |
178 | ^[^/]+$
179 |
180 | nested
181 |
182 | weight
183 | 10
184 |
185 | ^embedded\.provisionprofile$
186 |
187 | weight
188 | 20
189 |
190 | ^version\.plist$
191 |
192 | weight
193 | 20
194 |
195 |
196 |
197 |
198 |
--------------------------------------------------------------------------------
/Stapler-mini-v0/Stapler-mini-v0.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 77;
7 | objects = {
8 |
9 | /* Begin PBXFileReference section */
10 | CC5B388D2CCE3DE200043844 /* Stapler-mini-v0.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Stapler-mini-v0.app"; sourceTree = BUILT_PRODUCTS_DIR; };
11 | /* End PBXFileReference section */
12 |
13 | /* Begin PBXFileSystemSynchronizedBuildFileExceptionSet section */
14 | CC5B38D42CCE3FEE00043844 /* Exceptions for "Stapler-mini-v0" folder in "Stapler-mini-v0" target */ = {
15 | isa = PBXFileSystemSynchronizedBuildFileExceptionSet;
16 | membershipExceptions = (
17 | Info.plist,
18 | );
19 | target = CC5B388C2CCE3DE200043844 /* Stapler-mini-v0 */;
20 | };
21 | /* End PBXFileSystemSynchronizedBuildFileExceptionSet section */
22 |
23 | /* Begin PBXFileSystemSynchronizedRootGroup section */
24 | CC5B388F2CCE3DE200043844 /* Stapler-mini-v0 */ = {
25 | isa = PBXFileSystemSynchronizedRootGroup;
26 | exceptions = (
27 | CC5B38D42CCE3FEE00043844 /* Exceptions for "Stapler-mini-v0" folder in "Stapler-mini-v0" target */,
28 | );
29 | path = "Stapler-mini-v0";
30 | sourceTree = "";
31 | };
32 | /* End PBXFileSystemSynchronizedRootGroup section */
33 |
34 | /* Begin PBXFrameworksBuildPhase section */
35 | CC5B388A2CCE3DE200043844 /* Frameworks */ = {
36 | isa = PBXFrameworksBuildPhase;
37 | buildActionMask = 2147483647;
38 | files = (
39 | );
40 | runOnlyForDeploymentPostprocessing = 0;
41 | };
42 | /* End PBXFrameworksBuildPhase section */
43 |
44 | /* Begin PBXGroup section */
45 | CC5B38842CCE3DE200043844 = {
46 | isa = PBXGroup;
47 | children = (
48 | CC5B388F2CCE3DE200043844 /* Stapler-mini-v0 */,
49 | CC5B388E2CCE3DE200043844 /* Products */,
50 | );
51 | sourceTree = "";
52 | };
53 | CC5B388E2CCE3DE200043844 /* Products */ = {
54 | isa = PBXGroup;
55 | children = (
56 | CC5B388D2CCE3DE200043844 /* Stapler-mini-v0.app */,
57 | );
58 | name = Products;
59 | sourceTree = "";
60 | };
61 | /* End PBXGroup section */
62 |
63 | /* Begin PBXNativeTarget section */
64 | CC5B388C2CCE3DE200043844 /* Stapler-mini-v0 */ = {
65 | isa = PBXNativeTarget;
66 | buildConfigurationList = CC5B389C2CCE3DE500043844 /* Build configuration list for PBXNativeTarget "Stapler-mini-v0" */;
67 | buildPhases = (
68 | CC5B38892CCE3DE200043844 /* Sources */,
69 | CC5B388A2CCE3DE200043844 /* Frameworks */,
70 | CC5B388B2CCE3DE200043844 /* Resources */,
71 | );
72 | buildRules = (
73 | );
74 | dependencies = (
75 | );
76 | fileSystemSynchronizedGroups = (
77 | CC5B388F2CCE3DE200043844 /* Stapler-mini-v0 */,
78 | );
79 | name = "Stapler-mini-v0";
80 | packageProductDependencies = (
81 | );
82 | productName = "Stapler-mini-v0";
83 | productReference = CC5B388D2CCE3DE200043844 /* Stapler-mini-v0.app */;
84 | productType = "com.apple.product-type.application";
85 | };
86 | /* End PBXNativeTarget section */
87 |
88 | /* Begin PBXProject section */
89 | CC5B38852CCE3DE200043844 /* Project object */ = {
90 | isa = PBXProject;
91 | attributes = {
92 | BuildIndependentTargetsInParallel = 1;
93 | LastSwiftUpdateCheck = 1600;
94 | LastUpgradeCheck = 1600;
95 | TargetAttributes = {
96 | CC5B388C2CCE3DE200043844 = {
97 | CreatedOnToolsVersion = 16.0;
98 | };
99 | };
100 | };
101 | buildConfigurationList = CC5B38882CCE3DE200043844 /* Build configuration list for PBXProject "Stapler-mini-v0" */;
102 | developmentRegion = en;
103 | hasScannedForEncodings = 0;
104 | knownRegions = (
105 | en,
106 | Base,
107 | ja,
108 | );
109 | mainGroup = CC5B38842CCE3DE200043844;
110 | minimizedProjectReferenceProxies = 1;
111 | preferredProjectObjectVersion = 77;
112 | productRefGroup = CC5B388E2CCE3DE200043844 /* Products */;
113 | projectDirPath = "";
114 | projectRoot = "";
115 | targets = (
116 | CC5B388C2CCE3DE200043844 /* Stapler-mini-v0 */,
117 | );
118 | };
119 | /* End PBXProject section */
120 |
121 | /* Begin PBXResourcesBuildPhase section */
122 | CC5B388B2CCE3DE200043844 /* Resources */ = {
123 | isa = PBXResourcesBuildPhase;
124 | buildActionMask = 2147483647;
125 | files = (
126 | );
127 | runOnlyForDeploymentPostprocessing = 0;
128 | };
129 | /* End PBXResourcesBuildPhase section */
130 |
131 | /* Begin PBXSourcesBuildPhase section */
132 | CC5B38892CCE3DE200043844 /* Sources */ = {
133 | isa = PBXSourcesBuildPhase;
134 | buildActionMask = 2147483647;
135 | files = (
136 | );
137 | runOnlyForDeploymentPostprocessing = 0;
138 | };
139 | /* End PBXSourcesBuildPhase section */
140 |
141 | /* Begin XCBuildConfiguration section */
142 | CC5B389A2CCE3DE500043844 /* Debug */ = {
143 | isa = XCBuildConfiguration;
144 | buildSettings = {
145 | ALWAYS_SEARCH_USER_PATHS = NO;
146 | ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
147 | CLANG_ANALYZER_NONNULL = YES;
148 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
149 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
150 | CLANG_ENABLE_MODULES = YES;
151 | CLANG_ENABLE_OBJC_ARC = YES;
152 | CLANG_ENABLE_OBJC_WEAK = YES;
153 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
154 | CLANG_WARN_BOOL_CONVERSION = YES;
155 | CLANG_WARN_COMMA = YES;
156 | CLANG_WARN_CONSTANT_CONVERSION = YES;
157 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
158 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
159 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
160 | CLANG_WARN_EMPTY_BODY = YES;
161 | CLANG_WARN_ENUM_CONVERSION = YES;
162 | CLANG_WARN_INFINITE_RECURSION = YES;
163 | CLANG_WARN_INT_CONVERSION = YES;
164 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
165 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
166 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
167 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
168 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
169 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
170 | CLANG_WARN_STRICT_PROTOTYPES = YES;
171 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
172 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
173 | CLANG_WARN_UNREACHABLE_CODE = YES;
174 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
175 | COPY_PHASE_STRIP = NO;
176 | DEBUG_INFORMATION_FORMAT = dwarf;
177 | ENABLE_STRICT_OBJC_MSGSEND = YES;
178 | ENABLE_TESTABILITY = YES;
179 | ENABLE_USER_SCRIPT_SANDBOXING = YES;
180 | GCC_C_LANGUAGE_STANDARD = gnu17;
181 | GCC_DYNAMIC_NO_PIC = NO;
182 | GCC_NO_COMMON_BLOCKS = YES;
183 | GCC_OPTIMIZATION_LEVEL = 0;
184 | GCC_PREPROCESSOR_DEFINITIONS = (
185 | "DEBUG=1",
186 | "$(inherited)",
187 | );
188 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
189 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
190 | GCC_WARN_UNDECLARED_SELECTOR = YES;
191 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
192 | GCC_WARN_UNUSED_FUNCTION = YES;
193 | GCC_WARN_UNUSED_VARIABLE = YES;
194 | LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
195 | MACOSX_DEPLOYMENT_TARGET = 15.0;
196 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
197 | MTL_FAST_MATH = YES;
198 | ONLY_ACTIVE_ARCH = YES;
199 | SDKROOT = macosx;
200 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)";
201 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
202 | };
203 | name = Debug;
204 | };
205 | CC5B389B2CCE3DE500043844 /* Release */ = {
206 | isa = XCBuildConfiguration;
207 | buildSettings = {
208 | ALWAYS_SEARCH_USER_PATHS = NO;
209 | ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
210 | CLANG_ANALYZER_NONNULL = YES;
211 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
212 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
213 | CLANG_ENABLE_MODULES = YES;
214 | CLANG_ENABLE_OBJC_ARC = YES;
215 | CLANG_ENABLE_OBJC_WEAK = YES;
216 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
217 | CLANG_WARN_BOOL_CONVERSION = YES;
218 | CLANG_WARN_COMMA = YES;
219 | CLANG_WARN_CONSTANT_CONVERSION = YES;
220 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
221 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
222 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
223 | CLANG_WARN_EMPTY_BODY = YES;
224 | CLANG_WARN_ENUM_CONVERSION = YES;
225 | CLANG_WARN_INFINITE_RECURSION = YES;
226 | CLANG_WARN_INT_CONVERSION = YES;
227 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
228 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
229 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
230 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
231 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
232 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
233 | CLANG_WARN_STRICT_PROTOTYPES = YES;
234 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
235 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
236 | CLANG_WARN_UNREACHABLE_CODE = YES;
237 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
238 | COPY_PHASE_STRIP = NO;
239 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
240 | ENABLE_NS_ASSERTIONS = NO;
241 | ENABLE_STRICT_OBJC_MSGSEND = YES;
242 | ENABLE_USER_SCRIPT_SANDBOXING = YES;
243 | GCC_C_LANGUAGE_STANDARD = gnu17;
244 | GCC_NO_COMMON_BLOCKS = YES;
245 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
246 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
247 | GCC_WARN_UNDECLARED_SELECTOR = YES;
248 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
249 | GCC_WARN_UNUSED_FUNCTION = YES;
250 | GCC_WARN_UNUSED_VARIABLE = YES;
251 | LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
252 | MACOSX_DEPLOYMENT_TARGET = 15.0;
253 | MTL_ENABLE_DEBUG_INFO = NO;
254 | MTL_FAST_MATH = YES;
255 | SDKROOT = macosx;
256 | SWIFT_COMPILATION_MODE = wholemodule;
257 | };
258 | name = Release;
259 | };
260 | CC5B389D2CCE3DE500043844 /* Debug */ = {
261 | isa = XCBuildConfiguration;
262 | buildSettings = {
263 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
264 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
265 | CODE_SIGN_ENTITLEMENTS = "Stapler-mini-v0/Stapler_mini_v0.entitlements";
266 | CODE_SIGN_STYLE = Automatic;
267 | COMBINE_HIDPI_IMAGES = YES;
268 | CURRENT_PROJECT_VERSION = 1;
269 | DEVELOPMENT_ASSET_PATHS = "\"Stapler-mini-v0/Preview Content\"";
270 | DEVELOPMENT_TEAM = TBSVB6XDJZ;
271 | ENABLE_HARDENED_RUNTIME = YES;
272 | ENABLE_PREVIEWS = YES;
273 | GENERATE_INFOPLIST_FILE = YES;
274 | INFOPLIST_FILE = "Stapler-mini-v0/Info.plist";
275 | INFOPLIST_KEY_NSHumanReadableCopyright = "";
276 | LD_RUNPATH_SEARCH_PATHS = (
277 | "$(inherited)",
278 | "@executable_path/../Frameworks",
279 | );
280 | MARKETING_VERSION = 1.0;
281 | PRODUCT_BUNDLE_IDENTIFIER = "com.9dpbQ.Stapler-mini-v0";
282 | PRODUCT_NAME = "$(TARGET_NAME)";
283 | SWIFT_EMIT_LOC_STRINGS = YES;
284 | SWIFT_VERSION = 5.0;
285 | };
286 | name = Debug;
287 | };
288 | CC5B389E2CCE3DE500043844 /* Release */ = {
289 | isa = XCBuildConfiguration;
290 | buildSettings = {
291 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
292 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
293 | CODE_SIGN_ENTITLEMENTS = "Stapler-mini-v0/Stapler_mini_v0.entitlements";
294 | CODE_SIGN_STYLE = Automatic;
295 | COMBINE_HIDPI_IMAGES = YES;
296 | CURRENT_PROJECT_VERSION = 1;
297 | DEVELOPMENT_ASSET_PATHS = "\"Stapler-mini-v0/Preview Content\"";
298 | DEVELOPMENT_TEAM = TBSVB6XDJZ;
299 | ENABLE_HARDENED_RUNTIME = YES;
300 | ENABLE_PREVIEWS = YES;
301 | GENERATE_INFOPLIST_FILE = YES;
302 | INFOPLIST_FILE = "Stapler-mini-v0/Info.plist";
303 | INFOPLIST_KEY_NSHumanReadableCopyright = "";
304 | LD_RUNPATH_SEARCH_PATHS = (
305 | "$(inherited)",
306 | "@executable_path/../Frameworks",
307 | );
308 | MARKETING_VERSION = 1.0;
309 | PRODUCT_BUNDLE_IDENTIFIER = "com.9dpbQ.Stapler-mini-v0";
310 | PRODUCT_NAME = "$(TARGET_NAME)";
311 | SWIFT_EMIT_LOC_STRINGS = YES;
312 | SWIFT_VERSION = 5.0;
313 | };
314 | name = Release;
315 | };
316 | /* End XCBuildConfiguration section */
317 |
318 | /* Begin XCConfigurationList section */
319 | CC5B38882CCE3DE200043844 /* Build configuration list for PBXProject "Stapler-mini-v0" */ = {
320 | isa = XCConfigurationList;
321 | buildConfigurations = (
322 | CC5B389A2CCE3DE500043844 /* Debug */,
323 | CC5B389B2CCE3DE500043844 /* Release */,
324 | );
325 | defaultConfigurationIsVisible = 0;
326 | defaultConfigurationName = Release;
327 | };
328 | CC5B389C2CCE3DE500043844 /* Build configuration list for PBXNativeTarget "Stapler-mini-v0" */ = {
329 | isa = XCConfigurationList;
330 | buildConfigurations = (
331 | CC5B389D2CCE3DE500043844 /* Debug */,
332 | CC5B389E2CCE3DE500043844 /* Release */,
333 | );
334 | defaultConfigurationIsVisible = 0;
335 | defaultConfigurationName = Release;
336 | };
337 | /* End XCConfigurationList section */
338 | };
339 | rootObject = CC5B38852CCE3DE200043844 /* Project object */;
340 | }
341 |
--------------------------------------------------------------------------------
/Stapler-mini-v0/Stapler-mini-v0.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Stapler-mini-v0/Stapler-mini-v0.xcodeproj/project.xcworkspace/xcuserdata/qdpb.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/9dpbQ/Stapler-mini-v0/7939b748c37213fb0e04f4bdd383523d72949760/Stapler-mini-v0/Stapler-mini-v0.xcodeproj/project.xcworkspace/xcuserdata/qdpb.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/Stapler-mini-v0/Stapler-mini-v0.xcodeproj/xcuserdata/qdpb.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | Stapler-mini-v0.xcscheme_^#shared#^_
8 |
9 | orderHint
10 | 0
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/Stapler-mini-v0/Stapler-mini-v0/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | ///ウィンドウを閉じたらアプリが終了したり、そういうバックグラウンド処理のクラス。
2 | ///使い方が合ってるかよくわからない
3 | import Foundation
4 | import Cocoa
5 | import SwiftData
6 | import UniformTypeIdentifiers
7 |
8 | class AppDelegate: NSObject, NSApplicationDelegate {
9 | @MainActor
10 | var modelContainer: ModelContainer?
11 |
12 | func applicationDidFinishLaunching(_ aNotification: Notification) {
13 | // SwiftData のモデルコンテナは @main struct で設定されるため、ここでは不要
14 | }
15 |
16 | ///以下🦑アイコンへ.staplerファイルをドロップした時の処理をAIとやってみたけど、全く動かない。
17 | ///ドキュメントタイプのファイルアイコンを設定しても反映されてなかったり、Allowed
18 | /// ContentTypeで.staplerをフィルターにかけれなかったり、そもそもUTTypeの定義に何かしら足りないものがあるからなのかも?
19 | /// それかそもそもこの方法がとんちんかんなのかも
20 | func application(_ sender: NSApplication, openFile filename: String) -> Bool {
21 | let url = URL(fileURLWithPath: filename)
22 | if UTType(filenameExtension: url.pathExtension) == .stapler {
23 | loadPreset(from: url) { preset in
24 | if let preset = preset {
25 | Task { @MainActor in
26 | await self.addPresetToContext(preset)
27 | }
28 | print("Loaded and added preset from dock: \(preset.presetName)")
29 | } else {
30 | print("Failed to load preset from dock")
31 | }
32 | }
33 | return true
34 | }
35 | return false
36 | }
37 |
38 | func application(_ application: NSApplication, open urls: [URL]) {
39 | for url in urls where UTType(filenameExtension: url.pathExtension) == .stapler {
40 | loadPreset(from: url) { preset in
41 | if let preset = preset {
42 | Task { @MainActor in
43 | await self.addPresetToContext(preset)
44 | }
45 | print("Loaded and added preset from dock: \(preset.presetName)")
46 | } else {
47 | print("Failed to load preset from dock")
48 | }
49 | }
50 | }
51 | }
52 |
53 | private func loadPreset(from url: URL, completion: @escaping (Preset?) -> Void) {
54 | do {
55 | let jsonData = try Data(contentsOf: url)
56 | let loadedPreset = try JSONDecoder().decode(Preset.self, from: jsonData)
57 | completion(loadedPreset)
58 | } catch {
59 | print("Failed to load preset: \(error)")
60 | completion(nil)
61 | }
62 | }
63 |
64 | @MainActor
65 | private func addPresetToContext(_ preset: Preset) async {
66 | guard let modelContext = modelContainer?.mainContext else { return }
67 | modelContext.insert(preset)
68 | do {
69 | try modelContext.save()
70 | } catch {
71 | print("Failed to save context after adding preset: \(error)")
72 | }
73 | }
74 |
75 | func applicationWillTerminate(_ aNotification: Notification) {
76 | // アプリケーション終了時の処理
77 | }
78 |
79 | func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool {//ウィンドウを閉じたらアプリが終了するような処理
80 | NSApplication.shared.terminate(self)
81 | return true
82 | }
83 | }
84 |
85 |
86 |
--------------------------------------------------------------------------------
/Stapler-mini-v0/Stapler-mini-v0/Assets.xcassets/AccentColor.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "idiom" : "universal"
5 | }
6 | ],
7 | "info" : {
8 | "author" : "xcode",
9 | "version" : 1
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/Stapler-mini-v0/Stapler-mini-v0/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "Icon_v0_16x16@1x.png",
5 | "idiom" : "mac",
6 | "scale" : "1x",
7 | "size" : "16x16"
8 | },
9 | {
10 | "filename" : "Icon_v0_16x16@2x.png",
11 | "idiom" : "mac",
12 | "scale" : "2x",
13 | "size" : "16x16"
14 | },
15 | {
16 | "filename" : "Icon_v0_32x32@1x.png",
17 | "idiom" : "mac",
18 | "scale" : "1x",
19 | "size" : "32x32"
20 | },
21 | {
22 | "filename" : "Icon_v0_32x32@2x.png",
23 | "idiom" : "mac",
24 | "scale" : "2x",
25 | "size" : "32x32"
26 | },
27 | {
28 | "filename" : "Icon_v0_128x128@1x.png",
29 | "idiom" : "mac",
30 | "scale" : "1x",
31 | "size" : "128x128"
32 | },
33 | {
34 | "filename" : "Icon_v0_128x128@2x.png",
35 | "idiom" : "mac",
36 | "scale" : "2x",
37 | "size" : "128x128"
38 | },
39 | {
40 | "filename" : "Icon_v0_256x256@1x.png",
41 | "idiom" : "mac",
42 | "scale" : "1x",
43 | "size" : "256x256"
44 | },
45 | {
46 | "filename" : "Icon_v0_256x256@2x.png",
47 | "idiom" : "mac",
48 | "scale" : "2x",
49 | "size" : "256x256"
50 | },
51 | {
52 | "filename" : "Icon_v0_512x512@1x.png",
53 | "idiom" : "mac",
54 | "scale" : "1x",
55 | "size" : "512x512"
56 | },
57 | {
58 | "filename" : "Icon_v0_512x512@2x.png",
59 | "idiom" : "mac",
60 | "scale" : "2x",
61 | "size" : "512x512"
62 | }
63 | ],
64 | "info" : {
65 | "author" : "xcode",
66 | "version" : 1
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/Stapler-mini-v0/Stapler-mini-v0/Assets.xcassets/AppIcon.appiconset/Icon_v0_128x128@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/9dpbQ/Stapler-mini-v0/7939b748c37213fb0e04f4bdd383523d72949760/Stapler-mini-v0/Stapler-mini-v0/Assets.xcassets/AppIcon.appiconset/Icon_v0_128x128@1x.png
--------------------------------------------------------------------------------
/Stapler-mini-v0/Stapler-mini-v0/Assets.xcassets/AppIcon.appiconset/Icon_v0_128x128@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/9dpbQ/Stapler-mini-v0/7939b748c37213fb0e04f4bdd383523d72949760/Stapler-mini-v0/Stapler-mini-v0/Assets.xcassets/AppIcon.appiconset/Icon_v0_128x128@2x.png
--------------------------------------------------------------------------------
/Stapler-mini-v0/Stapler-mini-v0/Assets.xcassets/AppIcon.appiconset/Icon_v0_16x16@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/9dpbQ/Stapler-mini-v0/7939b748c37213fb0e04f4bdd383523d72949760/Stapler-mini-v0/Stapler-mini-v0/Assets.xcassets/AppIcon.appiconset/Icon_v0_16x16@1x.png
--------------------------------------------------------------------------------
/Stapler-mini-v0/Stapler-mini-v0/Assets.xcassets/AppIcon.appiconset/Icon_v0_16x16@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/9dpbQ/Stapler-mini-v0/7939b748c37213fb0e04f4bdd383523d72949760/Stapler-mini-v0/Stapler-mini-v0/Assets.xcassets/AppIcon.appiconset/Icon_v0_16x16@2x.png
--------------------------------------------------------------------------------
/Stapler-mini-v0/Stapler-mini-v0/Assets.xcassets/AppIcon.appiconset/Icon_v0_256x256@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/9dpbQ/Stapler-mini-v0/7939b748c37213fb0e04f4bdd383523d72949760/Stapler-mini-v0/Stapler-mini-v0/Assets.xcassets/AppIcon.appiconset/Icon_v0_256x256@1x.png
--------------------------------------------------------------------------------
/Stapler-mini-v0/Stapler-mini-v0/Assets.xcassets/AppIcon.appiconset/Icon_v0_256x256@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/9dpbQ/Stapler-mini-v0/7939b748c37213fb0e04f4bdd383523d72949760/Stapler-mini-v0/Stapler-mini-v0/Assets.xcassets/AppIcon.appiconset/Icon_v0_256x256@2x.png
--------------------------------------------------------------------------------
/Stapler-mini-v0/Stapler-mini-v0/Assets.xcassets/AppIcon.appiconset/Icon_v0_32x32@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/9dpbQ/Stapler-mini-v0/7939b748c37213fb0e04f4bdd383523d72949760/Stapler-mini-v0/Stapler-mini-v0/Assets.xcassets/AppIcon.appiconset/Icon_v0_32x32@1x.png
--------------------------------------------------------------------------------
/Stapler-mini-v0/Stapler-mini-v0/Assets.xcassets/AppIcon.appiconset/Icon_v0_32x32@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/9dpbQ/Stapler-mini-v0/7939b748c37213fb0e04f4bdd383523d72949760/Stapler-mini-v0/Stapler-mini-v0/Assets.xcassets/AppIcon.appiconset/Icon_v0_32x32@2x.png
--------------------------------------------------------------------------------
/Stapler-mini-v0/Stapler-mini-v0/Assets.xcassets/AppIcon.appiconset/Icon_v0_512x512@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/9dpbQ/Stapler-mini-v0/7939b748c37213fb0e04f4bdd383523d72949760/Stapler-mini-v0/Stapler-mini-v0/Assets.xcassets/AppIcon.appiconset/Icon_v0_512x512@1x.png
--------------------------------------------------------------------------------
/Stapler-mini-v0/Stapler-mini-v0/Assets.xcassets/AppIcon.appiconset/Icon_v0_512x512@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/9dpbQ/Stapler-mini-v0/7939b748c37213fb0e04f4bdd383523d72949760/Stapler-mini-v0/Stapler-mini-v0/Assets.xcassets/AppIcon.appiconset/Icon_v0_512x512@2x.png
--------------------------------------------------------------------------------
/Stapler-mini-v0/Stapler-mini-v0/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/Stapler-mini-v0/Stapler-mini-v0/Assets.xcassets/exportFileIcon.iconset/icon_128x128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/9dpbQ/Stapler-mini-v0/7939b748c37213fb0e04f4bdd383523d72949760/Stapler-mini-v0/Stapler-mini-v0/Assets.xcassets/exportFileIcon.iconset/icon_128x128.png
--------------------------------------------------------------------------------
/Stapler-mini-v0/Stapler-mini-v0/Assets.xcassets/exportFileIcon.iconset/icon_128x128@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/9dpbQ/Stapler-mini-v0/7939b748c37213fb0e04f4bdd383523d72949760/Stapler-mini-v0/Stapler-mini-v0/Assets.xcassets/exportFileIcon.iconset/icon_128x128@2x.png
--------------------------------------------------------------------------------
/Stapler-mini-v0/Stapler-mini-v0/Assets.xcassets/exportFileIcon.iconset/icon_16x16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/9dpbQ/Stapler-mini-v0/7939b748c37213fb0e04f4bdd383523d72949760/Stapler-mini-v0/Stapler-mini-v0/Assets.xcassets/exportFileIcon.iconset/icon_16x16.png
--------------------------------------------------------------------------------
/Stapler-mini-v0/Stapler-mini-v0/Assets.xcassets/exportFileIcon.iconset/icon_16x16@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/9dpbQ/Stapler-mini-v0/7939b748c37213fb0e04f4bdd383523d72949760/Stapler-mini-v0/Stapler-mini-v0/Assets.xcassets/exportFileIcon.iconset/icon_16x16@2x.png
--------------------------------------------------------------------------------
/Stapler-mini-v0/Stapler-mini-v0/Assets.xcassets/exportFileIcon.iconset/icon_256x256.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/9dpbQ/Stapler-mini-v0/7939b748c37213fb0e04f4bdd383523d72949760/Stapler-mini-v0/Stapler-mini-v0/Assets.xcassets/exportFileIcon.iconset/icon_256x256.png
--------------------------------------------------------------------------------
/Stapler-mini-v0/Stapler-mini-v0/Assets.xcassets/exportFileIcon.iconset/icon_256x256@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/9dpbQ/Stapler-mini-v0/7939b748c37213fb0e04f4bdd383523d72949760/Stapler-mini-v0/Stapler-mini-v0/Assets.xcassets/exportFileIcon.iconset/icon_256x256@2x.png
--------------------------------------------------------------------------------
/Stapler-mini-v0/Stapler-mini-v0/Assets.xcassets/exportFileIcon.iconset/icon_32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/9dpbQ/Stapler-mini-v0/7939b748c37213fb0e04f4bdd383523d72949760/Stapler-mini-v0/Stapler-mini-v0/Assets.xcassets/exportFileIcon.iconset/icon_32x32.png
--------------------------------------------------------------------------------
/Stapler-mini-v0/Stapler-mini-v0/Assets.xcassets/exportFileIcon.iconset/icon_32x32@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/9dpbQ/Stapler-mini-v0/7939b748c37213fb0e04f4bdd383523d72949760/Stapler-mini-v0/Stapler-mini-v0/Assets.xcassets/exportFileIcon.iconset/icon_32x32@2x.png
--------------------------------------------------------------------------------
/Stapler-mini-v0/Stapler-mini-v0/Assets.xcassets/exportFileIcon.iconset/icon_512x512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/9dpbQ/Stapler-mini-v0/7939b748c37213fb0e04f4bdd383523d72949760/Stapler-mini-v0/Stapler-mini-v0/Assets.xcassets/exportFileIcon.iconset/icon_512x512.png
--------------------------------------------------------------------------------
/Stapler-mini-v0/Stapler-mini-v0/ContentView.swift:
--------------------------------------------------------------------------------
1 | ///メインのビュー
2 | ///色々なビューをここに集結。
3 | import SwiftUI
4 | import SwiftData
5 |
6 | struct ContentView: View {
7 | @Environment(\.modelContext) private var modelContext
8 | @Query(sort: [SortDescriptor(\Preset.presetName, order: .forward)]) private var presets: [Preset]
9 |
10 | @State private var isEditing: Bool = false
11 | @State private var selectedPresetID: UUID? = nil
12 | @FocusState private var isPresetNameFocused: Bool
13 |
14 | @State private var showingAlert = false
15 | @State private var alertMessage = ""
16 | @State private var isSheetPresented_AddPreset: Bool = false
17 | @State private var isSheetPresented_Export: Bool = false
18 | @State private var selectedKeyboardLayout: KeyboardLayout? = nil
19 |
20 | @State private var selectedPreset: Preset? = nil
21 | @State private var selectedKeyboardKey: KeyboardKey = .initial
22 | @State private var isInspectorPresented: Bool = false
23 |
24 |
25 | var body: some View {
26 | NavigationSplitView {
27 | List(selection: $selectedPresetID) {
28 | ForEach(presets, id: \.id) { preset in
29 | NavigationLink {
30 | PresetView(preset: .constant(preset), selectedKeyboardKey: $selectedKeyboardKey)
31 | .navigationTitle(preset.presetName)
32 | .toolbar {
33 | ToolbarItem {
34 | Button(action: {
35 | isSheetPresented_Export = true
36 | }) {
37 | Image(systemName: "square.and.arrow.up")
38 | }
39 | }
40 | }
41 | } label: {
42 | PresetLabelView(
43 | preset: preset,
44 | isEditing: $isEditing,
45 | selectedPresetID: $selectedPresetID,
46 | isFocused: $isPresetNameFocused,
47 | onDelete: {
48 | if let index = presets.firstIndex(where: { $0.id == preset.id }) {
49 | modelContext.delete(presets[index])
50 | selectedPreset = nil
51 | }
52 | }
53 | )
54 | }
55 | .onChange(of: selectedPresetID) {
56 | isEditing = false
57 | selectedPreset = preset
58 | }
59 | }
60 | }
61 | .navigationSplitViewColumnWidth(min: 180, ideal: 200, max: 220)
62 | .toolbar {
63 | ToolbarItem {
64 | Button(action: {isSheetPresented_AddPreset = true }) {
65 | Label("Add Preset", systemImage: "plus")
66 | }
67 |
68 |
69 | }
70 | }
71 |
72 | } detail: {//Presetが選択されていない状態のビュー
73 | Text("Select or Add a preset from + button.")
74 | }
75 | .inspector(isPresented: $isInspectorPresented) {
76 | SelectedDetailView(selectedKeyboardKey: $selectedKeyboardKey, selectedPreset: selectedPreset)
77 | .inspectorColumnWidth(min: 180, ideal: 200, max: 220)
78 | .toolbar {
79 | ToolbarItem {
80 | Button {
81 | isInspectorPresented.toggle()
82 | } label: {
83 | Label("toggle inspector", systemImage: "sidebar.right")
84 | }
85 |
86 | }
87 | }
88 | }
89 | .sheet(isPresented: $isSheetPresented_AddPreset) {
90 | AddPresetSheetView(
91 | selectedKeyboardType: $selectedKeyboardLayout,
92 | isSheetPresented: $isSheetPresented_AddPreset,
93 | onDecision: addPreset,
94 | importPreset: {
95 | loadPreset { preset in
96 | if let preset = preset {
97 | modelContext.insert(preset)
98 | // Presetが正常に読み込まれた場合の処理
99 | print("Loaded Preset: \(preset.presetName)")
100 | } else {
101 | // 読み込みが失敗またはキャンセルされた場合の処理
102 | print("Failed or Canceled to load Preset.")
103 | // showingAlert = true
104 | // alertMessage = "Failed to load Preset. .stapler file is only importable"
105 | }
106 | }
107 | }
108 | )
109 | }
110 | .sheet(isPresented: $isSheetPresented_Export) {
111 | if let index = presets.firstIndex(where: { $0.id == selectedPresetID }) {
112 | let preset = presets[index]
113 | ExportSheetView(preset: preset)
114 | }
115 | }
116 | .alert(isPresented: $showingAlert) {
117 | Alert(title: Text("Import Result"), message: Text(alertMessage), dismissButton: .default(Text("OK")))
118 | }
119 | // .frame(minWidth: 1000, maxWidth: .infinity, minHeight: 800, maxHeight: .infinity)//ウィンドウの最小、最大サイズ
120 | }
121 | private func addPreset(keyboardLayout: KeyboardLayout?) {
122 | guard let keyboardLayout = keyboardLayout else { return }
123 | let newPreset = Preset(presetName: "New Preset", keyboardLayout: keyboardLayout)
124 | modelContext.insert(newPreset)
125 | }
126 | private func deletePresets(offsets: IndexSet) {
127 | withAnimation {
128 | for index in offsets {
129 | modelContext.delete(presets[index])
130 | }
131 | }
132 | }
133 |
134 | }
135 |
136 |
137 | #Preview {
138 | ContentView()
139 | .modelContainer(for: Preset.self, inMemory: true)
140 | }
141 |
142 |
143 |
--------------------------------------------------------------------------------
/Stapler-mini-v0/Stapler-mini-v0/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDocumentTypes
6 |
7 |
8 | CFBundleTypeIconFile
9 | exportFileIcon
10 | CFBundleTypeIconSystemGenerated
11 | 1
12 | CFBundleTypeName
13 | Stapler
14 | CFBundleTypeRole
15 | Editor
16 | LSHandlerRank
17 | Default
18 | LSItemContentTypes
19 |
20 | com.example.stapler
21 |
22 | NSDocumentClass
23 | NSDocument
24 |
25 |
26 | UTExportedTypeDeclarations
27 |
28 |
29 | UTTypeConformsTo
30 |
31 | public.data
32 |
33 | UTTypeDescription
34 | for drag & drop CustomizeKey
35 | UTTypeIcons
36 |
37 | UTTypeIdentifier
38 | com.example.customizekey
39 | UTTypeTagSpecification
40 |
41 |
42 |
43 | UTTypeConformsTo
44 |
45 | public.data
46 |
47 | UTTypeDescription
48 | for sharing user's Preset
49 | UTTypeIcons
50 |
51 | UTTypeIconBadgeName
52 | exportFileIcon
53 |
54 | UTTypeIdentifier
55 | com.example.stapler
56 | UTTypeTagSpecification
57 |
58 |
59 |
60 |
61 |
62 |
--------------------------------------------------------------------------------
/Stapler-mini-v0/Stapler-mini-v0/Keyboard/AddPresetSheetView.swift:
--------------------------------------------------------------------------------
1 | ///プリセットを追加する時のビュー。
2 | ///US/UK/JISから選択するか.staplerファイルをインポートする感じ。
3 | ///
4 | ///現在は本体キーボードしかないけれど、今後はKeyboardViewに柔軟性を持たせて自分の持っているキーボードを再現できるようにしていきたい。
5 | ///そのためにはちょっとクラスの書き換えが必要かなぁ?
6 | ///
7 |
8 | import SwiftUI
9 | // カスタムボタンスタイル
10 | struct CustomShapeButtonStyle_Gradient: ButtonStyle {
11 | let shape: S
12 | let fillColor: LinearGradient
13 | let frameSize: CGSize
14 |
15 | func makeBody(configuration: Configuration) -> some View {
16 | shape
17 | .fill(fillColor)
18 | .frame(width: frameSize.width, height: frameSize.height)
19 | .overlay(
20 | configuration.label
21 | )
22 | .scaleEffect(configuration.isPressed ? 0.98 : 1.0) // 押した時のスケールエフェクト
23 | // .animation(.bouncy, value: configuration.isPressed)
24 | }
25 | }
26 |
27 | struct AddPresetSheetView: View {
28 | @Binding var selectedKeyboardType: KeyboardLayout?
29 | @Binding var isSheetPresented: Bool
30 |
31 | let onDecision: (KeyboardLayout?) -> Void
32 | let importPreset: () -> Void
33 |
34 | var body: some View {
35 | VStack {
36 | HStack {
37 | Text("Select Keyboard Layout")
38 | .font(.headline)
39 | .padding()
40 | Button {
41 | isSheetPresented = false
42 | importPreset()
43 | } label: {
44 | Label("import Preset", systemImage: "square.and.arrow.down")
45 | }
46 | }
47 | VStack {
48 | Text("MacBook Built-in Keyboard")
49 | .font(.caption)
50 | HStack {
51 | // US キーボード
52 | Button(action: {
53 | selectedKeyboardType = .US
54 | }) {
55 | Text("US")
56 | .foregroundColor(selectedKeyboardType == .US ? .accentColor : .white)
57 | .font(.system(size: 20))
58 | }
59 | .buttonStyle(
60 | CustomShapeButtonStyle_Gradient(
61 | shape: RoundedRectangle(cornerRadius: 65 * 0.07),
62 | fillColor: LinearGradient(colors: [.black], startPoint: .bottom, endPoint: .top),
63 | frameSize: CGSize(width: 65 * 1.75 - 65 * 0.07, height: 65 - 65 * 0.07)
64 | )
65 | )
66 | .padding(7)
67 | // JIS キーボード
68 | Button(action: {
69 | selectedKeyboardType = .JIS
70 | }) {
71 | Text("JIS")
72 | .foregroundColor(selectedKeyboardType == .JIS ? .accentColor : .white)
73 | .font(.system(size: 20))
74 | }
75 | .buttonStyle(
76 | CustomShapeButtonStyle_Gradient(
77 | shape: EnterShape_JIS(frameValue: 65),
78 | fillColor: LinearGradient(colors: [.black], startPoint: .bottom, endPoint: .top),
79 | frameSize: CGSize(width: 65*1.5, height: 65*2)
80 | )
81 | )
82 |
83 | // UK キーボード
84 | Button(action: {
85 | selectedKeyboardType = .UK
86 | }) {
87 | Text("UK")
88 | .foregroundColor(selectedKeyboardType == .UK ? .accentColor : .white)
89 | .font(.system(size: 20))
90 | .padding(.leading, 10)
91 | }
92 | .buttonStyle(
93 | CustomShapeButtonStyle_Gradient(
94 | shape: EnterShape_UK(frameValue: 65),
95 | fillColor: LinearGradient(colors: [.black], startPoint: .bottom, endPoint: .top),
96 | frameSize: CGSize(width: 65, height: 65*2)
97 | )
98 | )
99 | }
100 | }
101 | // 決定・キャンセルボタン
102 | HStack {
103 | Button("Cancel") {
104 | isSheetPresented = false
105 | }
106 | .padding()
107 |
108 | Button("Create a Preset") {
109 | onDecision(selectedKeyboardType)
110 | isSheetPresented = false
111 | }
112 | .disabled(selectedKeyboardType == nil)
113 | .padding()
114 | }
115 | }
116 | .padding()
117 | .onAppear {
118 | selectedKeyboardType = nil
119 | }
120 | }
121 | }
122 |
--------------------------------------------------------------------------------
/Stapler-mini-v0/Stapler-mini-v0/Keyboard/CustomizeKey/CustomKeyCategory.swift:
--------------------------------------------------------------------------------
1 | ///カテゴリ別のCustomizeKeyの配列とか
2 |
3 | import Foundation
4 |
5 | struct CustomKeyCategory: Identifiable {
6 | let id: UUID = UUID()
7 | let name: String
8 | let keys: [CustomizeKey]
9 | }
10 |
11 | struct CustomKeyDataSet {
12 | static let basicKeys: CustomKeyCategory = CustomKeyCategory(
13 | name: "Basic",
14 | keys: [
15 | //Alphabets
16 | CustomizeKey(afterDisplaySymbol: "square.dotted", afterKeyOutPut: "vk_none", isUsingSFSymbol: true, helpText: "this key outputs nothing"),
17 | CustomizeKey(afterDisplaySymbol: "A", afterKeyOutPut: "a"),
18 | CustomizeKey(afterDisplaySymbol: "B", afterKeyOutPut: "b"),
19 | CustomizeKey(afterDisplaySymbol: "C", afterKeyOutPut: "c"),
20 | CustomizeKey(afterDisplaySymbol: "D", afterKeyOutPut: "d"),
21 | CustomizeKey(afterDisplaySymbol: "E", afterKeyOutPut: "e"),
22 | CustomizeKey(afterDisplaySymbol: "F", afterKeyOutPut: "f"),
23 | CustomizeKey(afterDisplaySymbol: "G", afterKeyOutPut: "g"),
24 | CustomizeKey(afterDisplaySymbol: "H", afterKeyOutPut: "h"),
25 | CustomizeKey(afterDisplaySymbol: "I", afterKeyOutPut: "i"),
26 | CustomizeKey(afterDisplaySymbol: "J", afterKeyOutPut: "j"),
27 | CustomizeKey(afterDisplaySymbol: "K", afterKeyOutPut: "k"),
28 | CustomizeKey(afterDisplaySymbol: "L", afterKeyOutPut: "l"),
29 | CustomizeKey(afterDisplaySymbol: "M", afterKeyOutPut: "m"),
30 | CustomizeKey(afterDisplaySymbol: "N", afterKeyOutPut: "n"),
31 | CustomizeKey(afterDisplaySymbol: "O", afterKeyOutPut: "o"),
32 | CustomizeKey(afterDisplaySymbol: "P", afterKeyOutPut: "p"),
33 | CustomizeKey(afterDisplaySymbol: "Q", afterKeyOutPut: "q"),
34 | CustomizeKey(afterDisplaySymbol: "R", afterKeyOutPut: "r"),
35 | CustomizeKey(afterDisplaySymbol: "S", afterKeyOutPut: "s"),
36 | CustomizeKey(afterDisplaySymbol: "T", afterKeyOutPut: "t"),
37 | CustomizeKey(afterDisplaySymbol: "U", afterKeyOutPut: "u"),
38 | CustomizeKey(afterDisplaySymbol: "V", afterKeyOutPut: "v"),
39 | CustomizeKey(afterDisplaySymbol: "W", afterKeyOutPut: "w"),
40 | CustomizeKey(afterDisplaySymbol: "X", afterKeyOutPut: "x"),
41 | CustomizeKey(afterDisplaySymbol: "Y", afterKeyOutPut: "y"),
42 | CustomizeKey(afterDisplaySymbol: "Z", afterKeyOutPut: "z"),
43 | //BasicNumbers
44 | CustomizeKey(afterDisplaySymbol: "1", afterKeyOutPut: "1"),
45 | CustomizeKey(afterDisplaySymbol: "2", afterKeyOutPut: "2"),
46 | CustomizeKey(afterDisplaySymbol: "3", afterKeyOutPut: "3"),
47 | CustomizeKey(afterDisplaySymbol: "4", afterKeyOutPut: "4"),
48 | CustomizeKey(afterDisplaySymbol: "5", afterKeyOutPut: "5"),
49 | CustomizeKey(afterDisplaySymbol: "6", afterKeyOutPut: "6"),
50 | CustomizeKey(afterDisplaySymbol: "7", afterKeyOutPut: "7"),
51 | CustomizeKey(afterDisplaySymbol: "8", afterKeyOutPut: "8"),
52 | CustomizeKey(afterDisplaySymbol: "9", afterKeyOutPut: "9"),
53 | CustomizeKey(afterDisplaySymbol: "0", afterKeyOutPut: "0"),
54 |
55 | ]
56 | )
57 | static let symbolKeys: CustomKeyCategory = CustomKeyCategory(
58 | name: "Symbol",
59 | keys: [
60 | //単打で出せるもの(US視点)
61 |
62 |
63 | CustomizeKey(afterDisplaySymbol: "-", afterKeyOutPut: "-"),
64 | CustomizeKey(afterDisplaySymbol: "_", afterKeyOutPut: "_"),//Shift + -
65 |
66 | CustomizeKey(afterDisplaySymbol: "=", afterKeyOutPut: "="),
67 | CustomizeKey(afterDisplaySymbol: "+", afterKeyOutPut: "+"),//Shift + =
68 |
69 | CustomizeKey(afterDisplaySymbol: "\\", afterKeyOutPut: "\\"),//backslash
70 | CustomizeKey(afterDisplaySymbol: "|", afterKeyOutPut: "|"),//Shift + backslash
71 |
72 | CustomizeKey(afterDisplaySymbol: ";", afterKeyOutPut: ";"),
73 | CustomizeKey(afterDisplaySymbol: ":", afterKeyOutPut: ":"),//Shift + ;
74 |
75 | CustomizeKey(afterDisplaySymbol: "`", afterKeyOutPut: "`"),
76 | CustomizeKey(afterDisplaySymbol: "~", afterKeyOutPut: "~"),//Shift + `
77 |
78 | CustomizeKey(afterDisplaySymbol: "'", afterKeyOutPut: "'"),
79 | CustomizeKey(afterDisplaySymbol: "\"", afterKeyOutPut: "\""),//Shift + '
80 |
81 | CustomizeKey(afterDisplaySymbol: ",", afterKeyOutPut: ","),
82 | CustomizeKey(afterDisplaySymbol: ".", afterKeyOutPut: "."),
83 |
84 | CustomizeKey(afterDisplaySymbol: "/", afterKeyOutPut: "/"),
85 | CustomizeKey(afterDisplaySymbol: "?", afterKeyOutPut: "?"),//Shift + slash
86 |
87 | //Shift系
88 | //数字+シフト
89 | CustomizeKey(afterDisplaySymbol: "!", afterKeyOutPut: "!"),//Shift + 1
90 | CustomizeKey(afterDisplaySymbol: "@", afterKeyOutPut: "@"),//Shift + 2
91 | CustomizeKey(afterDisplaySymbol: "#", afterKeyOutPut: "#"),//Shift + 3
92 | CustomizeKey(afterDisplaySymbol: "$", afterKeyOutPut: "$"),//Shift + 4
93 | CustomizeKey(afterDisplaySymbol: "%", afterKeyOutPut: "%"),//Shift + 5
94 | CustomizeKey(afterDisplaySymbol: "^", afterKeyOutPut: "^"),//Shift + 6
95 | CustomizeKey(afterDisplaySymbol: "&", afterKeyOutPut: "&"),//Shift + 7
96 | CustomizeKey(afterDisplaySymbol: "*", afterKeyOutPut: "*"),//Shift + 8
97 | CustomizeKey(afterDisplaySymbol: "(", afterKeyOutPut: "("),//Shift + 9
98 | CustomizeKey(afterDisplaySymbol: ")", afterKeyOutPut: ")"),//Shift + 0
99 |
100 | CustomizeKey(afterDisplaySymbol: "[", afterKeyOutPut: "["),
101 | CustomizeKey(afterDisplaySymbol: "]", afterKeyOutPut: "]"),
102 |
103 | CustomizeKey(afterDisplaySymbol: "{", afterKeyOutPut: "{"),//Shift + [
104 | CustomizeKey(afterDisplaySymbol: "}", afterKeyOutPut: "}"),//Shift + ]
105 |
106 |
107 |
108 | CustomizeKey(afterDisplaySymbol: "<", afterKeyOutPut: "<"),//Shift + ,
109 | CustomizeKey(afterDisplaySymbol: ">", afterKeyOutPut: ">"),//Shift + .
110 |
111 |
112 |
113 | //記号+シフト
114 |
115 | // //Option系 ユーザーがDisplay Nameをいじれるようにしつつ、あとは修飾キートグルでどうにかしてもらうことにする。
116 | // //数字+オプション
117 | // CustomizeKey(afterDisplaySymbol: "º", afterKeyOutPut: "º"),//0
118 | // CustomizeKey(afterDisplaySymbol: "¡", afterKeyOutPut: "¡"),//1
119 | // CustomizeKey(afterDisplaySymbol: "™", afterKeyOutPut: "™"),//2
120 | // CustomizeKey(afterDisplaySymbol: "£", afterKeyOutPut: "£"),//3
121 | // CustomizeKey(afterDisplaySymbol: "¢", afterKeyOutPut: "¢"),//4
122 | // CustomizeKey(afterDisplaySymbol: "∞", afterKeyOutPut: "∞"),//5
123 | // CustomizeKey(afterDisplaySymbol: "§", afterKeyOutPut: "§"),//6
124 | // CustomizeKey(afterDisplaySymbol: "¶", afterKeyOutPut: "¶"),//7
125 | // CustomizeKey(afterDisplaySymbol: "•", afterKeyOutPut: "•"),//8
126 | // CustomizeKey(afterDisplaySymbol: "ª", afterKeyOutPut: "ª"),//9
127 | // //アルファベット+オプション
128 | // CustomizeKey(afterDisplaySymbol: "å", afterKeyOutPut: "å"),//A
129 | // CustomizeKey(afterDisplaySymbol: "∫", afterKeyOutPut: "∫"),//B
130 | // CustomizeKey(afterDisplaySymbol: "ç", afterKeyOutPut: "ç"),//C
131 | // CustomizeKey(afterDisplaySymbol: "∂", afterKeyOutPut: "∂"),//D
132 | // CustomizeKey(afterDisplaySymbol: "´", afterKeyOutPut: "´"),//E
133 | // CustomizeKey(afterDisplaySymbol: "ƒ", afterKeyOutPut: "ƒ"),//F
134 | // CustomizeKey(afterDisplaySymbol: "©", afterKeyOutPut: "©"),//G
135 | // CustomizeKey(afterDisplaySymbol: "˙", afterKeyOutPut: "˙"),//H
136 | // CustomizeKey(afterDisplaySymbol: "ˆ", afterKeyOutPut: "ˆ"),//I
137 | // CustomizeKey(afterDisplaySymbol: "∆", afterKeyOutPut: "∆"),//J
138 | // CustomizeKey(afterDisplaySymbol: "˚", afterKeyOutPut: "˚"),//K
139 | // CustomizeKey(afterDisplaySymbol: "¬", afterKeyOutPut: "¬"),//L
140 | // CustomizeKey(afterDisplaySymbol: "µ", afterKeyOutPut: "µ"),//M
141 | // CustomizeKey(afterDisplaySymbol: "˜", afterKeyOutPut: "˜"),//N
142 | // CustomizeKey(afterDisplaySymbol: "ø", afterKeyOutPut: "ø"),//O
143 | // CustomizeKey(afterDisplaySymbol: "π", afterKeyOutPut: "π"),//P
144 | // CustomizeKey(afterDisplaySymbol: "œ", afterKeyOutPut: "œ"),//Q
145 | // CustomizeKey(afterDisplaySymbol: "®", afterKeyOutPut: "®"),//R
146 | // CustomizeKey(afterDisplaySymbol: "ß", afterKeyOutPut: "ß"),//S
147 | // CustomizeKey(afterDisplaySymbol: "†", afterKeyOutPut: "†"),//T
148 | // CustomizeKey(afterDisplaySymbol: "¨", afterKeyOutPut: "¨"),//U
149 | // CustomizeKey(afterDisplaySymbol: "√", afterKeyOutPut: "√"),//V
150 | // CustomizeKey(afterDisplaySymbol: "∑", afterKeyOutPut: "∑"),//W
151 | // CustomizeKey(afterDisplaySymbol: "≈", afterKeyOutPut: "≈"),//X
152 | // CustomizeKey(afterDisplaySymbol: "¥", afterKeyOutPut: "¥"),//Y
153 | // CustomizeKey(afterDisplaySymbol: "Ω", afterKeyOutPut: "Ω"),//Z
154 | // //記号+オプション
155 | //// CustomizeKey(afterDisplaySymbol: "`", afterKeyOutPut: "`"),//Option + ` 同じっぽい?意味なさそう
156 | // CustomizeKey(afterDisplaySymbol: "–", afterKeyOutPut: "–"),//Option + -
157 | // CustomizeKey(afterDisplaySymbol: "≠", afterKeyOutPut: "≠"),//Option + =
158 | // CustomizeKey(afterDisplaySymbol: "“", afterKeyOutPut: "“"),//Option + [
159 | // CustomizeKey(afterDisplaySymbol: "‘", afterKeyOutPut: "‘"),//Option + ]
160 | // CustomizeKey(afterDisplaySymbol: "«", afterKeyOutPut: "«"),//Option + backslash
161 | // CustomizeKey(afterDisplaySymbol: "…", afterKeyOutPut: "…"),//Option + ;
162 | // CustomizeKey(afterDisplaySymbol: "'", afterKeyOutPut: "'"),//Option + '
163 | // CustomizeKey(afterDisplaySymbol: "≤", afterKeyOutPut: "≤"),//Option + ,
164 | // CustomizeKey(afterDisplaySymbol: "≥", afterKeyOutPut: "≥"),//Option + .
165 | // CustomizeKey(afterDisplaySymbol: "÷", afterKeyOutPut: "÷"),//Option + slash
166 | ]
167 | )
168 | static let keyPadKeys: CustomKeyCategory = CustomKeyCategory(
169 | name: "Keypad",
170 | keys: [
171 | //KeyPadKeys
172 | CustomizeKey(afterDisplaySymbol: "k0", afterKeyOutPut: "keypad_0"),
173 | CustomizeKey(afterDisplaySymbol: "k1", afterKeyOutPut: "keypad_1"),
174 | CustomizeKey(afterDisplaySymbol: "k2", afterKeyOutPut: "keypad_2"),
175 | CustomizeKey(afterDisplaySymbol: "k3", afterKeyOutPut: "keypad_3"),
176 | CustomizeKey(afterDisplaySymbol: "k4", afterKeyOutPut: "keypad_4"),
177 | CustomizeKey(afterDisplaySymbol: "k5", afterKeyOutPut: "keypad_5"),
178 | CustomizeKey(afterDisplaySymbol: "k6", afterKeyOutPut: "keypad_6"),
179 | CustomizeKey(afterDisplaySymbol: "k7", afterKeyOutPut: "keypad_7"),
180 | CustomizeKey(afterDisplaySymbol: "k8", afterKeyOutPut: "keypad_8"),
181 | CustomizeKey(afterDisplaySymbol: "k9", afterKeyOutPut: "keypad_9"),
182 | CustomizeKey(afterDisplaySymbol: "num_lock", afterKeyOutPut: "keypad_num_lock"),
183 | CustomizeKey(afterDisplaySymbol: "k/", afterKeyOutPut: "keypad_slash"),
184 | CustomizeKey(afterDisplaySymbol: "k*", afterKeyOutPut: "keypad_asterisk"),
185 | CustomizeKey(afterDisplaySymbol: "k-", afterKeyOutPut: "keypad_hyphen"),
186 | CustomizeKey(afterDisplaySymbol: "k+", afterKeyOutPut: "keypad_plus"),
187 | CustomizeKey(afterDisplaySymbol: "k=", afterKeyOutPut: "keypad_equal_sign"),
188 | CustomizeKey(afterDisplaySymbol: "enter", afterKeyOutPut: "keypad_enter"),
189 | CustomizeKey(afterDisplaySymbol: "k,", afterKeyOutPut: "keypad_comma"),
190 | CustomizeKey(afterDisplaySymbol: "k.", afterKeyOutPut: "keypad_period"),
191 |
192 | ]
193 | )
194 | static let controlKeys: CustomKeyCategory = CustomKeyCategory(
195 | name: "Control",
196 | keys: [
197 | //Controls
198 | CustomizeKey(afterDisplaySymbol: "return", afterKeyOutPut: "return", isUsingSFSymbol: true),
199 | CustomizeKey(afterDisplaySymbol: "␣", afterKeyOutPut: "␣"),
200 | CustomizeKey(afterDisplaySymbol: "arrow.right.to.line", afterKeyOutPut: "tab", isUsingSFSymbol: true),
201 | CustomizeKey(afterDisplaySymbol: "esc", afterKeyOutPut: "esc"),
202 | CustomizeKey(afterDisplaySymbol: "delete.left", afterKeyOutPut: "BS", isUsingSFSymbol: true),
203 | CustomizeKey(afterDisplaySymbol: "delete.right", afterKeyOutPut: "Del", isUsingSFSymbol: true),
204 | CustomizeKey(afterDisplaySymbol: "かな", afterKeyOutPut: "かな"),
205 | CustomizeKey(afterDisplaySymbol: "英数", afterKeyOutPut: "英数"),
206 | CustomizeKey(afterDisplaySymbol: "変換", afterKeyOutPut: "変換"),
207 | CustomizeKey(afterDisplaySymbol: "無変換", afterKeyOutPut: "無変換"),
208 | //FullSizeControls
209 | CustomizeKey(afterDisplaySymbol: "print_screen", afterKeyOutPut: "print_screen"),
210 | CustomizeKey(afterDisplaySymbol: "scroll_lock", afterKeyOutPut: "scroll_lock"),
211 | CustomizeKey(afterDisplaySymbol: "pause", afterKeyOutPut: "pause"),
212 | CustomizeKey(afterDisplaySymbol: "insert", afterKeyOutPut: "insert"),
213 | CustomizeKey(afterDisplaySymbol: "application", afterKeyOutPut: "application"),
214 | CustomizeKey(afterDisplaySymbol: "help", afterKeyOutPut: "help"),
215 | CustomizeKey(afterDisplaySymbol: "power", afterKeyOutPut: "power"),
216 | //Arrows
217 | CustomizeKey(afterDisplaySymbol: "←", afterKeyOutPut: "←"),
218 | CustomizeKey(afterDisplaySymbol: "↑", afterKeyOutPut: "↑"),
219 | CustomizeKey(afterDisplaySymbol: "→", afterKeyOutPut: "→"),
220 | CustomizeKey(afterDisplaySymbol: "↓", afterKeyOutPut: "↓"),
221 | CustomizeKey(afterDisplaySymbol: "page_up", afterKeyOutPut: "page_up"),
222 | CustomizeKey(afterDisplaySymbol: "page_down", afterKeyOutPut: "page_down"),
223 | CustomizeKey(afterDisplaySymbol: "home", afterKeyOutPut: "home"),
224 | CustomizeKey(afterDisplaySymbol: "end", afterKeyOutPut: "end"),
225 | //MediaControls
226 | //MacOS
227 | CustomizeKey(afterDisplaySymbol: "rectangle.3.group", afterKeyOutPut: "mission_control", isUsingSFSymbol: true),
228 | CustomizeKey(afterDisplaySymbol: "magnifyingglass", afterKeyOutPut: "spotlight", isUsingSFSymbol: true),
229 | CustomizeKey(afterDisplaySymbol: "microphone", afterKeyOutPut: "dictation", isUsingSFSymbol: true),
230 | CustomizeKey(afterDisplaySymbol: "square.grid.3x2", afterKeyOutPut: "launchpad", isUsingSFSymbol: true),
231 | //Sound
232 | CustomizeKey(afterDisplaySymbol: "backward", afterKeyOutPut: "rewind", isUsingSFSymbol: true),
233 | CustomizeKey(afterDisplaySymbol: "playpause", afterKeyOutPut: "play_or_pause", isUsingSFSymbol: true),
234 | CustomizeKey(afterDisplaySymbol: "forward", afterKeyOutPut: "fast_forward", isUsingSFSymbol: true),
235 | CustomizeKey(afterDisplaySymbol: "speaker.slash", afterKeyOutPut: "mute", isUsingSFSymbol: true),
236 | CustomizeKey(afterDisplaySymbol: "speaker.wave.1", afterKeyOutPut: "volume_decrement", isUsingSFSymbol: true),
237 | CustomizeKey(afterDisplaySymbol: "speaker.wave.3", afterKeyOutPut: "volume_increment", isUsingSFSymbol: true),
238 | CustomizeKey(afterDisplaySymbol: "eject", afterKeyOutPut: "eject", isUsingSFSymbol: true),
239 | //Light Displayの3つの差異は?ないなら一つに統合して良い気がする
240 | CustomizeKey(afterDisplaySymbol: "sun.min.fill", afterKeyOutPut: "display_brightness_decrement", isUsingSFSymbol: true),
241 | CustomizeKey(afterDisplaySymbol: "sun.max.fill", afterKeyOutPut: "display_brightness_increment", isUsingSFSymbol: true),
242 |
243 | CustomizeKey(afterDisplaySymbol: "sun.min.fill", afterKeyOutPut: "brightness_down", isUsingSFSymbol: true),
244 | CustomizeKey(afterDisplaySymbol: "sun.max.fill", afterKeyOutPut: "brightness_up", isUsingSFSymbol: true),
245 | CustomizeKey(afterDisplaySymbol: "sun.min.fill", afterKeyOutPut: "brightness_down(2)", isUsingSFSymbol: true),//外部ディスプレイ?
246 | CustomizeKey(afterDisplaySymbol: "sun.max.fill", afterKeyOutPut: "brightness_up(2)", isUsingSFSymbol: true),
247 |
248 | CustomizeKey(afterDisplaySymbol: "light.min", afterKeyOutPut: "illumination_down", isUsingSFSymbol: true),//keyboard backlight
249 | CustomizeKey(afterDisplaySymbol: "light.max", afterKeyOutPut: "illumination_up", isUsingSFSymbol: true),
250 | ]
251 | )
252 |
253 |
254 |
255 |
256 | static let specialKeys: CustomKeyCategory = CustomKeyCategory(
257 | name: "Special",
258 | keys: [
259 | CustomizeKey(afterDisplaySymbol: "1.square", afterKeyOutPut: "layer1", isUsingSFSymbol: true, layerKeyNumber: 1),
260 | CustomizeKey(afterDisplaySymbol: "2.square", afterKeyOutPut: "layer2", isUsingSFSymbol: true, layerKeyNumber: 2),
261 | CustomizeKey(afterDisplaySymbol: "3.square", afterKeyOutPut: "layer3", isUsingSFSymbol: true, layerKeyNumber: 3),
262 | CustomizeKey(afterDisplaySymbol: "4.square", afterKeyOutPut: "layer4", isUsingSFSymbol: true, layerKeyNumber: 4),
263 | CustomizeKey(afterDisplaySymbol: "5.square", afterKeyOutPut: "layer5", isUsingSFSymbol: true, layerKeyNumber: 5),
264 | CustomizeKey(afterDisplaySymbol: "6.square", afterKeyOutPut: "layer6", isUsingSFSymbol: true, layerKeyNumber: 6),
265 | CustomizeKey(afterDisplaySymbol: "7.square", afterKeyOutPut: "layer7", isUsingSFSymbol: true, layerKeyNumber: 7),
266 | CustomizeKey(afterDisplaySymbol: "8.square", afterKeyOutPut: "layer8", isUsingSFSymbol: true, layerKeyNumber: 8),
267 |
268 |
269 | CustomizeKey(afterDisplaySymbol: "L⇧", afterKeyOutPut: "left_shift"),
270 | CustomizeKey(afterDisplaySymbol: "L⌘", afterKeyOutPut: "left_command"),
271 | CustomizeKey(afterDisplaySymbol: "L^", afterKeyOutPut: "left_control"),
272 | CustomizeKey(afterDisplaySymbol: "L⌥", afterKeyOutPut: "left_option"),
273 |
274 | CustomizeKey(afterDisplaySymbol: "R⇧", afterKeyOutPut: "right_shift"),
275 | CustomizeKey(afterDisplaySymbol: "R⌘", afterKeyOutPut: "right_command"),
276 | CustomizeKey(afterDisplaySymbol: "R^", afterKeyOutPut: "right_control"),
277 | CustomizeKey(afterDisplaySymbol: "R⌥", afterKeyOutPut: "right_option"),
278 | CustomizeKey(afterDisplaySymbol: "fn", afterKeyOutPut: "fn"),
279 | ]
280 | )
281 |
282 | static let functionKeys: CustomKeyCategory = CustomKeyCategory(
283 | name: "FunctionKey",
284 | keys: [
285 | CustomizeKey(afterDisplaySymbol: "F1", afterKeyOutPut: "F1"),
286 | CustomizeKey(afterDisplaySymbol: "F2", afterKeyOutPut: "F2"),
287 | CustomizeKey(afterDisplaySymbol: "F3", afterKeyOutPut: "F3"),
288 | CustomizeKey(afterDisplaySymbol: "F4", afterKeyOutPut: "F4"),
289 | CustomizeKey(afterDisplaySymbol: "F5", afterKeyOutPut: "F5"),
290 | CustomizeKey(afterDisplaySymbol: "F6", afterKeyOutPut: "F6"),
291 | CustomizeKey(afterDisplaySymbol: "F7", afterKeyOutPut: "F7"),
292 | CustomizeKey(afterDisplaySymbol: "F8", afterKeyOutPut: "F8"),
293 | CustomizeKey(afterDisplaySymbol: "F9", afterKeyOutPut: "F9"),
294 | CustomizeKey(afterDisplaySymbol: "F10", afterKeyOutPut: "F10"),
295 | CustomizeKey(afterDisplaySymbol: "F11", afterKeyOutPut: "F11"),
296 | CustomizeKey(afterDisplaySymbol: "F12", afterKeyOutPut: "F12"),
297 | CustomizeKey(afterDisplaySymbol: "F13", afterKeyOutPut: "F13"),
298 | CustomizeKey(afterDisplaySymbol: "F14", afterKeyOutPut: "F14"),
299 | CustomizeKey(afterDisplaySymbol: "F15", afterKeyOutPut: "F15"),
300 | CustomizeKey(afterDisplaySymbol: "F16", afterKeyOutPut: "F16"),
301 | CustomizeKey(afterDisplaySymbol: "F17", afterKeyOutPut: "F17"),
302 | CustomizeKey(afterDisplaySymbol: "F18", afterKeyOutPut: "F18"),
303 | CustomizeKey(afterDisplaySymbol: "F19", afterKeyOutPut: "F19"),
304 | CustomizeKey(afterDisplaySymbol: "F20", afterKeyOutPut: "F20"),
305 | CustomizeKey(afterDisplaySymbol: "F21", afterKeyOutPut: "F21"),
306 | CustomizeKey(afterDisplaySymbol: "F22", afterKeyOutPut: "F22"),
307 | CustomizeKey(afterDisplaySymbol: "F23", afterKeyOutPut: "F23"),
308 | CustomizeKey(afterDisplaySymbol: "F24", afterKeyOutPut: "F24"),
309 |
310 |
311 | ]
312 | )
313 |
314 | static let internationalKeys: CustomKeyCategory = CustomKeyCategory(
315 | name: "International",
316 | keys: [
317 | CustomizeKey(afterDisplaySymbol: "international1", afterKeyOutPut: "international1"),
318 | CustomizeKey(afterDisplaySymbol: "international2", afterKeyOutPut: "international2"),
319 | CustomizeKey(afterDisplaySymbol: "international3", afterKeyOutPut: "international3"),
320 | CustomizeKey(afterDisplaySymbol: "international4", afterKeyOutPut: "international4"),
321 | CustomizeKey(afterDisplaySymbol: "international5", afterKeyOutPut: "international5"),
322 | CustomizeKey(afterDisplaySymbol: "international6", afterKeyOutPut: "international6"),
323 | CustomizeKey(afterDisplaySymbol: "international7", afterKeyOutPut: "international7"),
324 | CustomizeKey(afterDisplaySymbol: "international8", afterKeyOutPut: "international8"),
325 | CustomizeKey(afterDisplaySymbol: "international9", afterKeyOutPut: "international9"),
326 | CustomizeKey(afterDisplaySymbol: "lang1", afterKeyOutPut: "lang1"),
327 | CustomizeKey(afterDisplaySymbol: "lang2", afterKeyOutPut: "lang2"),
328 | CustomizeKey(afterDisplaySymbol: "lang3", afterKeyOutPut: "lang3"),
329 | CustomizeKey(afterDisplaySymbol: "lang4", afterKeyOutPut: "lang4"),
330 | CustomizeKey(afterDisplaySymbol: "lang5", afterKeyOutPut: "lang5"),
331 | CustomizeKey(afterDisplaySymbol: "lang6", afterKeyOutPut: "lang6"),
332 | CustomizeKey(afterDisplaySymbol: "lang7", afterKeyOutPut: "lang7"),
333 | CustomizeKey(afterDisplaySymbol: "lang8", afterKeyOutPut: "lang8"),
334 | CustomizeKey(afterDisplaySymbol: "lang9", afterKeyOutPut: "lang9"),
335 |
336 |
337 | ]
338 | )
339 |
340 | static let mouseKeys: CustomKeyCategory = CustomKeyCategory(
341 | name: "Mouse",
342 | keys: [
343 | CustomizeKey(afterDisplaySymbol: "mouse_up", afterKeyOutPut: "mouse_up"),
344 | CustomizeKey(afterDisplaySymbol: "mouse_up(fast)", afterKeyOutPut: "mouse_up(fast)"),
345 | CustomizeKey(afterDisplaySymbol: "mouse_up(slow)", afterKeyOutPut: "mouse_up(slow)"),
346 | CustomizeKey(afterDisplaySymbol: "mouse_down", afterKeyOutPut: "mouse_down"),
347 | CustomizeKey(afterDisplaySymbol: "mouse_down(fast)", afterKeyOutPut: "mouse_down(fast)"),
348 | CustomizeKey(afterDisplaySymbol: "mouse_down(slow)", afterKeyOutPut: "mouse_down(slow)"),
349 | CustomizeKey(afterDisplaySymbol: "mouse_left", afterKeyOutPut: "mouse_left"),
350 | CustomizeKey(afterDisplaySymbol: "mouse_left(fast)", afterKeyOutPut: "mouse_left(fast)"),
351 | CustomizeKey(afterDisplaySymbol: "mouse_left(slow)", afterKeyOutPut: "mouse_left(slow)"),
352 | CustomizeKey(afterDisplaySymbol: "mouse_right", afterKeyOutPut: "mouse_right"),
353 | CustomizeKey(afterDisplaySymbol: "mouse_right(fast)", afterKeyOutPut: "mouse_right(fast)"),
354 | CustomizeKey(afterDisplaySymbol: "mouse_right(slow)", afterKeyOutPut: "mouse_right(slow)"),
355 | CustomizeKey(afterDisplaySymbol: "scroll_up", afterKeyOutPut: "scroll_up"),
356 | CustomizeKey(afterDisplaySymbol: "scroll_up(fast)", afterKeyOutPut: "scroll_up(fast)"),
357 | CustomizeKey(afterDisplaySymbol: "scroll_up(slow)", afterKeyOutPut: "scroll_up(slow)"),
358 | CustomizeKey(afterDisplaySymbol: "scroll_down", afterKeyOutPut: "scroll_down"),
359 | CustomizeKey(afterDisplaySymbol: "scroll_down(fast)", afterKeyOutPut: "scroll_down(fast)"),
360 | CustomizeKey(afterDisplaySymbol: "scroll_down(slow)", afterKeyOutPut: "scroll_down(slow)"),
361 | CustomizeKey(afterDisplaySymbol: "scroll_left", afterKeyOutPut: "scroll_left"),
362 | CustomizeKey(afterDisplaySymbol: "scroll_left(fast)", afterKeyOutPut: "scroll_left(fast)"),
363 | CustomizeKey(afterDisplaySymbol: "scroll_left(slow)", afterKeyOutPut: "scroll_left(slow)"),
364 | CustomizeKey(afterDisplaySymbol: "scroll_right", afterKeyOutPut: "scroll_right"),
365 | CustomizeKey(afterDisplaySymbol: "scroll_right(fast)", afterKeyOutPut: "scroll_right(fast)"),
366 | CustomizeKey(afterDisplaySymbol: "scroll_right(slow)", afterKeyOutPut: "scroll_right(slow)"),
367 | CustomizeKey(afterDisplaySymbol: "speed_multi_plier(2.0)", afterKeyOutPut: "speed_multi_plier(2.0)"),
368 | CustomizeKey(afterDisplaySymbol: "speed_multi_plier(0.5)", afterKeyOutPut: "speed_multi_plier(0.5)"),
369 | CustomizeKey(afterDisplaySymbol: "speed_multi_plier(0.25)", afterKeyOutPut: "speed_multi_plier(0.25)"),
370 | CustomizeKey(afterDisplaySymbol: "speed_multi_plier(0.125)", afterKeyOutPut: "speed_multi_plier(0.125)"),
371 |
372 | CustomizeKey(afterDisplaySymbol: "button1", afterKeyOutPut: "button1"),
373 | CustomizeKey(afterDisplaySymbol: "button2", afterKeyOutPut: "button2"),
374 | CustomizeKey(afterDisplaySymbol: "button3", afterKeyOutPut: "button3"),
375 | CustomizeKey(afterDisplaySymbol: "button4", afterKeyOutPut: "button4"),
376 | CustomizeKey(afterDisplaySymbol: "button5", afterKeyOutPut: "button5"),
377 | CustomizeKey(afterDisplaySymbol: "button6", afterKeyOutPut: "button6"),
378 | CustomizeKey(afterDisplaySymbol: "button7", afterKeyOutPut: "button7"),
379 | CustomizeKey(afterDisplaySymbol: "button8", afterKeyOutPut: "button8"),
380 | CustomizeKey(afterDisplaySymbol: "button9", afterKeyOutPut: "button9"),
381 | CustomizeKey(afterDisplaySymbol: "button10", afterKeyOutPut: "button10"),
382 | CustomizeKey(afterDisplaySymbol: "button11", afterKeyOutPut: "button11"),
383 | CustomizeKey(afterDisplaySymbol: "button12", afterKeyOutPut: "button12"),
384 | CustomizeKey(afterDisplaySymbol: "button13", afterKeyOutPut: "button13"),
385 | CustomizeKey(afterDisplaySymbol: "button14", afterKeyOutPut: "button14"),
386 | CustomizeKey(afterDisplaySymbol: "button15", afterKeyOutPut: "button15"),
387 | CustomizeKey(afterDisplaySymbol: "button16", afterKeyOutPut: "button16"),
388 | CustomizeKey(afterDisplaySymbol: "button17", afterKeyOutPut: "button17"),
389 | CustomizeKey(afterDisplaySymbol: "button18", afterKeyOutPut: "button18"),
390 | CustomizeKey(afterDisplaySymbol: "button19", afterKeyOutPut: "button19"),
391 | CustomizeKey(afterDisplaySymbol: "button20", afterKeyOutPut: "button20"),
392 | CustomizeKey(afterDisplaySymbol: "button21", afterKeyOutPut: "button21"),
393 | CustomizeKey(afterDisplaySymbol: "button22", afterKeyOutPut: "button22"),
394 | CustomizeKey(afterDisplaySymbol: "button23", afterKeyOutPut: "button23"),
395 | CustomizeKey(afterDisplaySymbol: "button24", afterKeyOutPut: "button24"),
396 | CustomizeKey(afterDisplaySymbol: "button25", afterKeyOutPut: "button25"),
397 | CustomizeKey(afterDisplaySymbol: "button26", afterKeyOutPut: "button26"),
398 | CustomizeKey(afterDisplaySymbol: "button27", afterKeyOutPut: "button27"),
399 | CustomizeKey(afterDisplaySymbol: "button28", afterKeyOutPut: "button28"),
400 | CustomizeKey(afterDisplaySymbol: "button29", afterKeyOutPut: "button29"),
401 | CustomizeKey(afterDisplaySymbol: "button30", afterKeyOutPut: "button30"),
402 | CustomizeKey(afterDisplaySymbol: "button31", afterKeyOutPut: "button31"),
403 | CustomizeKey(afterDisplaySymbol: "button32", afterKeyOutPut: "button32"),
404 | ]
405 | )
406 |
407 | static let allCategories: [CustomKeyCategory] = [
408 | basicKeys, symbolKeys, controlKeys, keyPadKeys, specialKeys, functionKeys, internationalKeys, mouseKeys
409 | ]
410 | }
411 |
--------------------------------------------------------------------------------
/Stapler-mini-v0/Stapler-mini-v0/Keyboard/CustomizeKey/CustomizeKeyTabView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CustomizeKeyTabView.swift
3 | // SwiftData Test Project2
4 | //
5 | // Created by qdpb on 2024/09/14.
6 | //
7 |
8 | import SwiftUI
9 |
10 | struct CustomizeKeyTabView: View {
11 | @State private var searchText: String = ""
12 | @State private var selectedTab: String = "" // 現在選択中のタブを管理
13 | // @Binding var externalSearchFieldFocuse: Bool // PresetViewからのバインディング
14 | @FocusState private var internalSearchFieldFocus: Bool // 独自のFocusState
15 | //
16 | // 全カテゴリーのキーをフィルタリング
17 | var filteredAllKeys: [CustomizeKey] {
18 | let allKeys = CustomKeyDataSet.allCategories.flatMap { $0.keys }
19 | if searchText.isEmpty {
20 | return allKeys
21 | } else {
22 | return allKeys.filter { key in
23 | key.afterDisplaySymbol.localizedCaseInsensitiveContains(searchText)
24 | // key.afterKeyOutPut.localizedCaseInsensitiveContains(searchText)
25 | }
26 | }
27 | }
28 |
29 | let columns = [
30 | GridItem(.adaptive(minimum: 65 - 65 * 0.07 + 2.5, maximum: 100))
31 | ]
32 |
33 | var body: some View {
34 | ZStack {
35 | TabView(selection: $selectedTab) {
36 | ForEach(CustomKeyDataSet.allCategories, id: \.id) { category in
37 | ScrollView(.vertical) {
38 | LazyVGrid(columns: columns, spacing: 5) {
39 | ForEach(category.keys, id: \.id) { key in
40 | CustomizeKeyView_1u(customizeKey: key)
41 | }
42 | }
43 | .padding()
44 | }
45 | .tabItem {
46 | Text(category.name)
47 | }
48 | .tag(category.name)
49 | }
50 |
51 | VStack {
52 | ScrollView(.vertical) {
53 | LazyVGrid(columns: columns, spacing: 5) {
54 | ForEach(filteredAllKeys, id: \.id) { key in
55 | CustomizeKeyView_1u(customizeKey: key)
56 | }
57 | }
58 | .padding()
59 | }
60 |
61 | }
62 | .tabItem {
63 | Text("All")
64 | }
65 | .tag("All")
66 | }
67 |
68 | if selectedTab == "All" {
69 | VStack {
70 | HStack {
71 | Spacer()
72 | // 検索バーを表示する
73 | TextField("Search in All Keys", text: $searchText)
74 | .background().cornerRadius(6)
75 | .frame(width: 150)
76 | .textFieldStyle(RoundedBorderTextFieldStyle())
77 | .padding(.trailing, 10)
78 | .focused($internalSearchFieldFocus)
79 | .onSubmit{internalSearchFieldFocus = false}
80 | }
81 |
82 | Spacer()
83 | }
84 | // .onChange(of: externalSearchFieldFocuse) { oldValue, newValue in
85 | // internalSearchFieldFocus = newValue
86 | // }
87 | }
88 | }
89 | }
90 | }
91 |
92 |
93 | // CustomizeKey and CustomKeyDataSet structures remain the same
94 | //ビューを小分けしにたら処理が軽くなるんじゃないかと試したけど無意味でした
95 |
96 | //struct CustomizeKeyTabView: View {
97 | // let columns = [
98 | // GridItem(.adaptive(minimum: 70, maximum: 200)) // 最小・最大幅を調整
99 | // ]
100 | //
101 | // var body: some View {
102 | // TabView {
103 | // ForEach(CustomKeyDataSet.allCategories, id: \.id) { category in
104 | // CustomizeCategoryView(category: category, columns: columns)
105 | // .tabItem {
106 | // Text(category.name)
107 | // }
108 | // }
109 | // }
110 | // }
111 | //}
112 | //
113 | //struct CustomizeCategoryView: View {
114 | // let category: CustomKeyCategory
115 | // let columns: [GridItem]
116 | //
117 | // var body: some View {
118 | // ScrollView(.vertical) {
119 | // CustomizeKeyGridView(keys: category.keys, columns: columns)
120 | // .padding()
121 | // }
122 | // }
123 | //}
124 | //
125 | //struct CustomizeKeyGridView: View {
126 | // let keys: [CustomizeKey]
127 | // let columns: [GridItem]
128 | //
129 | // var body: some View {
130 | // LazyVGrid(columns: columns, spacing: 5) {
131 | // ForEach(keys, id: \.id) { key in
132 | // CustomizeKeyItemView(customizeKey: key)
133 | // }
134 | // }
135 | // }
136 | //}
137 | //
138 | //struct CustomizeKeyItemView: View {
139 | // let customizeKey: CustomizeKey
140 | //
141 | // var body: some View {
142 | // CustomizeKeyView_1u(customizeKey: customizeKey)
143 | // }
144 | //}
145 |
146 | //#Preview {
147 | // CustomizeKeyTabView()
148 | //}
149 |
--------------------------------------------------------------------------------
/Stapler-mini-v0/Stapler-mini-v0/Keyboard/CustomizeKey/CustomizeKeyView_1u.swift:
--------------------------------------------------------------------------------
1 | ///CustomizeKeyクラスの定義とそのひとつ分のビューの定義。
2 | ///
3 | import SwiftUI
4 | import UniformTypeIdentifiers
5 |
6 | //書き換えデータをドラッグしていく元のキー。レイヤーキーなどもここに入るはず。
7 | final class CustomizeKey: Codable, Transferable, Identifiable {
8 | let id: UUID
9 | //まず、変更後の表示シンボルと、打たれる文字(辞書鍵になってるやつ)
10 | let layerKeyNumber: Int
11 | let afterDisplaySymbol: String
12 | let isUsingSFSymbol: Bool
13 | let afterKeyOutPut: String
14 |
15 | let isCustomized: Bool
16 | //修飾キー
17 | let tapWithModifier: Bool
18 | let tapWithShift: Bool
19 | let isTapIncludeShift: Bool//記号をドロップした後にDetail View側でシフトとかをトグルできないようにするためのブール値
20 | let tapWithControl: Bool
21 | let isTapIncludeControl: Bool
22 | let tapWithOption: Bool
23 | let isTapIncludeOption: Bool
24 | let tapWithCommand: Bool
25 | let isTapIncludeCommand: Bool
26 |
27 | let userCustomJSONEnabled: Bool
28 | let userCustomJSONContent: String
29 |
30 | let helpText: String?
31 |
32 | //簡易
33 | init(
34 | afterDisplaySymbol: String,
35 | afterKeyOutPut: String,
36 | isUsingSFSymbol:Bool = false,
37 | helpText: String? = nil,
38 | layerKeyNumber: Int = 0
39 | ) {
40 | self.id = UUID()
41 | self.layerKeyNumber = layerKeyNumber
42 | self.afterDisplaySymbol = afterDisplaySymbol
43 | self.isUsingSFSymbol = isUsingSFSymbol
44 | self.afterKeyOutPut = afterKeyOutPut
45 |
46 | self.isCustomized = true
47 | self.tapWithModifier = false
48 |
49 | self.tapWithShift = false
50 | self.isTapIncludeShift = false
51 | self.tapWithControl = false
52 | self.isTapIncludeControl = false
53 | self.tapWithOption = false
54 | self.isTapIncludeOption = false
55 | self.tapWithCommand = false
56 | self.isTapIncludeCommand = false
57 |
58 | self.userCustomJSONEnabled = false
59 | self.userCustomJSONContent = ""
60 | self.helpText = helpText
61 | }
62 | //全部入り
63 | init(
64 | id: UUID = UUID(),
65 | layerKeyNumber: Int = 0,
66 | afterDisplaySymbol: String,
67 | afterKeyOutPut: String,
68 | isCustomized: Bool = true,
69 |
70 | isTapWithModifier: Bool = false,
71 | tapWithShift: Bool = false,
72 | isTapIncludeShift: Bool = false,
73 | tapWithControl: Bool = false,
74 | isTapIncludeControl: Bool = false,
75 | tapWithOption: Bool = false,
76 | isTapIncludeOption: Bool = false,
77 | tapWithCommand: Bool = false,
78 | isTapIncludeCommand: Bool = false,
79 |
80 | userCustomJSONEnabled: Bool = false,
81 | userCustomJSONContent: String = "",
82 | isUsingSFSymbol:Bool = false,
83 | helpText: String? = nil
84 |
85 | ) {
86 | self.id = id
87 | self.layerKeyNumber = layerKeyNumber
88 | self.afterDisplaySymbol = afterDisplaySymbol
89 | self.afterKeyOutPut = afterKeyOutPut
90 | self.isCustomized = true
91 |
92 | self.tapWithModifier = isTapWithModifier
93 | self.tapWithShift = tapWithShift
94 | self.isTapIncludeShift = isTapIncludeShift
95 | self.tapWithControl = tapWithControl
96 | self.isTapIncludeControl = isTapIncludeControl
97 | self.tapWithOption = tapWithOption
98 | self.isTapIncludeOption = isTapIncludeOption
99 | self.tapWithCommand = tapWithCommand
100 | self.isTapIncludeCommand = isTapIncludeCommand
101 |
102 | self.userCustomJSONEnabled = userCustomJSONEnabled
103 | self.userCustomJSONContent = userCustomJSONContent
104 | self.isUsingSFSymbol = isUsingSFSymbol
105 | self.helpText = helpText
106 | }
107 |
108 |
109 | static var transferRepresentation: some TransferRepresentation {
110 | CodableRepresentation(for: CustomizeKey.self, contentType: .customizekey)
111 | }
112 | }
113 |
114 | extension UTType {
115 | static var customizekey: UTType { UTType(exportedAs: "com.example.customizekey")}
116 | }
117 |
118 | struct CustomizeKeyView_1u: View {
119 | let customizeKey: CustomizeKey
120 | private var backgroundColor: Color {
121 | if customizeKey.afterKeyOutPut == "layer1" {
122 | LayerColor.layer1.customizeKeyBackGroundColor
123 | } else if customizeKey.afterKeyOutPut == "layer2" {
124 | LayerColor.layer2.customizeKeyBackGroundColor
125 | } else if customizeKey.afterKeyOutPut == "layer3" {
126 | LayerColor.layer3.customizeKeyBackGroundColor
127 | } else if customizeKey.afterKeyOutPut == "layer4" {
128 | LayerColor.layer4.customizeKeyBackGroundColor
129 | } else if customizeKey.afterKeyOutPut == "layer5" {
130 | LayerColor.layer5.customizeKeyBackGroundColor
131 | } else if customizeKey.afterKeyOutPut == "layer6" {
132 | LayerColor.layer6.customizeKeyBackGroundColor
133 | } else if customizeKey.afterKeyOutPut == "layer7" {
134 | LayerColor.layer7.customizeKeyBackGroundColor
135 | } else if customizeKey.afterKeyOutPut == "layer8" {
136 | LayerColor.layer8.customizeKeyBackGroundColor
137 | } else {
138 | LayerColor.layer0.customizeKeyBackGroundColor
139 | }
140 | }
141 | var body: some View {
142 | ZStack {
143 | if customizeKey.isUsingSFSymbol {
144 | Image(systemName: customizeKey.afterDisplaySymbol)
145 | } else {
146 | Text(customizeKey.afterDisplaySymbol)
147 | }
148 | }
149 | .foregroundColor(.white)
150 | .font(.system(size: 20))
151 | .frame(width: 65 - 65 * 0.07, height: 65 - 65 * 0.07)
152 | .background(backgroundColor.opacity(0.5))
153 | .cornerRadius(65 * 0.07)
154 | .draggable(customizeKey)
155 | .help(customizeKey.helpText ?? "keycode: \(customizeKey.afterKeyOutPut)")
156 | }
157 | }
158 |
159 | #Preview {
160 | return CustomizeKeyView_1u(customizeKey: CustomizeKey(afterDisplaySymbol: "A", afterKeyOutPut: "A"))
161 | }
162 |
163 |
164 |
--------------------------------------------------------------------------------
/Stapler-mini-v0/Stapler-mini-v0/Keyboard/EnterCustomShapeView.swift:
--------------------------------------------------------------------------------
1 | ///エンターのカスタムシェイプの定義。
2 |
3 | import SwiftUI
4 |
5 | struct EnterShape_JIS: Shape {
6 | let frameValue: CGFloat
7 | private var paddingValue: CGFloat {
8 | frameValue * 0.07
9 | }
10 | private var roundValue: CGFloat {
11 | frameValue * 0.07
12 | }
13 |
14 | func path(in rect: CGRect) -> Path {
15 | Path { path in
16 | // スタートポイント(左上の角丸終わりから時計回りに描画)
17 | let startPoint = CGPoint(x: paddingValue + roundValue, y: paddingValue)
18 | // 1. 左上から右上の丸みの始まりまでのライン
19 | path.move(to: startPoint)
20 | path.addLine(to: CGPoint(x: rect.width - paddingValue - roundValue, y: paddingValue))
21 |
22 | // 2. 右上の角の丸みを描画
23 | path.addArc(center: CGPoint(x: rect.width - paddingValue - roundValue, y: paddingValue + roundValue),
24 | radius: roundValue,
25 | startAngle: .degrees(270),
26 | endAngle: .degrees(0),
27 | clockwise: false)
28 |
29 | // 3. 右側のライン(右上から右下まで)
30 | path.addLine(to: CGPoint(x: rect.width - paddingValue, y: rect.height - paddingValue - roundValue))
31 |
32 | // 4. 右下の丸みを描画
33 | path.addArc(center: CGPoint(x: rect.width - paddingValue - roundValue, y: rect.height - paddingValue - roundValue),
34 | radius: roundValue,
35 | startAngle: .degrees(0),
36 | endAngle: .degrees(90),
37 | clockwise: false)
38 |
39 | // 5. 下側のラインを描画 (エンターキー下部の水平ライン)
40 | path.addLine(to: CGPoint(x: rect.width / 6 + paddingValue + roundValue, y: rect.height - paddingValue))
41 |
42 | // 6. 左下の角の丸みを描画
43 | path.addArc(center: CGPoint(x: rect.width / 6 + paddingValue + roundValue, y: rect.height - paddingValue - roundValue),
44 | radius: roundValue,
45 | startAngle: .degrees(90),
46 | endAngle: .degrees(180),
47 | clockwise: false)
48 |
49 | // 7. 左側のライン1本目を描画
50 | path.addLine(to: CGPoint(x: rect.width / 6 + paddingValue, y: rect.height / 2 - paddingValue + roundValue))
51 | // 8. 左中央の丸みを描画
52 | path.addArc(center: CGPoint(x: rect.width / 6 + paddingValue - roundValue, y: rect.height / 2 - paddingValue + roundValue),
53 | radius: roundValue,
54 | startAngle: .degrees(0),
55 | endAngle: .degrees(-90),
56 | clockwise: true)
57 | // 9. 中央のラインを描画
58 | path.addLine(to: CGPoint(x: paddingValue + roundValue, y: rect.height / 2 - paddingValue))
59 |
60 | // 10. 左下の角の丸みを描画
61 | path.addArc(center: CGPoint(x: paddingValue + roundValue, y: rect.height / 2 - paddingValue - roundValue),
62 | radius: roundValue,
63 | startAngle: .degrees(90),
64 | endAngle: .degrees(180),
65 | clockwise: false)
66 | // 11. 左側のライン2本目
67 | path.addLine(to: CGPoint(x: paddingValue, y: paddingValue + roundValue))
68 |
69 | //12. 左上の丸みを描画
70 | path.addArc(center: CGPoint(x: paddingValue + roundValue, y: paddingValue + roundValue),
71 | radius: roundValue,
72 | startAngle: .degrees(180),
73 | endAngle: .degrees(270),
74 | clockwise: false)
75 |
76 | // パスを閉じる
77 | path.closeSubpath()
78 | }
79 | }
80 | }
81 |
82 | struct EnterShape_JIS_HighLight: Shape {
83 | let frameValue: CGFloat
84 | private var centerRoundValue: CGFloat {
85 | frameValue * 0.07
86 | }
87 | private var roundValue: CGFloat {
88 | frameValue * 0.14
89 | }
90 |
91 | func path(in rect: CGRect) -> Path {
92 | Path { path in
93 | // スタートポイント(左上の角丸終わりから時計回りに描画)
94 | let startPoint = CGPoint(x: roundValue, y: 0)
95 | // 1. 左上から右上の丸みの始まりまでのライン
96 | path.move(to: startPoint)
97 | path.addLine(to: CGPoint(x: rect.width - roundValue, y: 0))
98 |
99 | // 2. 右上の角の丸みを描画
100 | path.addArc(center: CGPoint(x: rect.width - roundValue, y: roundValue),
101 | radius: roundValue,
102 | startAngle: .degrees(270),
103 | endAngle: .degrees(0),
104 | clockwise: false)
105 |
106 | // 3. 右側のライン(右上から右下まで)
107 | path.addLine(to: CGPoint(x: rect.width, y: rect.height - roundValue))
108 |
109 | // 4. 右下の丸みを描画
110 | path.addArc(center: CGPoint(x: rect.width - roundValue, y: rect.height - roundValue),
111 | radius: roundValue,
112 | startAngle: .degrees(0),
113 | endAngle: .degrees(90),
114 | clockwise: false)
115 |
116 | // 5. 下側のラインを描画 (エンターキー下部の水平ライン)
117 | path.addLine(to: CGPoint(x: rect.width / 6 + roundValue, y: rect.height))
118 |
119 | // 6. 左下の角の丸みを描画
120 | path.addArc(center: CGPoint(x: rect.width / 6 + roundValue, y: rect.height - roundValue),
121 | radius: roundValue,
122 | startAngle: .degrees(90),
123 | endAngle: .degrees(180),
124 | clockwise: false)
125 |
126 | // 7. 左側のライン1本目を描画
127 | path.addLine(to: CGPoint(x: rect.width / 6, y: rect.height / 2 + roundValue))
128 | // 8. 左中央の丸みを描画
129 | path.addArc(center: CGPoint(x: rect.width / 6 - centerRoundValue, y: rect.height / 2 + centerRoundValue),
130 | radius: centerRoundValue,
131 | startAngle: .degrees(0),
132 | endAngle: .degrees(-90),
133 | clockwise: true)
134 | // 9. 中央のラインを描画
135 | path.addLine(to: CGPoint(x: roundValue, y: rect.height / 2))
136 |
137 | // 10. 左下の角の丸みを描画
138 | path.addArc(center: CGPoint(x: roundValue, y: rect.height / 2 - roundValue),
139 | radius: roundValue,
140 | startAngle: .degrees(90),
141 | endAngle: .degrees(180),
142 | clockwise: false)
143 | // 11. 左側のライン2本目
144 | path.addLine(to: CGPoint(x: 0, y: roundValue))
145 |
146 | //12. 左上の丸みを描画
147 | path.addArc(center: CGPoint(x: roundValue, y: roundValue),
148 | radius: roundValue,
149 | startAngle: .degrees(180),
150 | endAngle: .degrees(270),
151 | clockwise: false)
152 |
153 | // パスを閉じる
154 | path.closeSubpath()
155 | }
156 | }
157 | }
158 |
159 | struct EnterShape_UK: Shape {
160 | let frameValue: CGFloat
161 | private var paddingValue: CGFloat {
162 | frameValue * 0.07
163 | }
164 | private var roundValue: CGFloat {
165 | frameValue * 0.07
166 | }
167 |
168 |
169 | func path(in rect: CGRect) -> Path {
170 | Path { path in
171 | // スタートポイント(左上の角丸終わりから時計回りに描画)
172 | let startPoint = CGPoint(x: paddingValue + roundValue, y: paddingValue)
173 | // 1. 左上から右上の丸みの始まりまでのライン
174 | path.move(to: startPoint)
175 | path.addLine(to: CGPoint(x: rect.width - paddingValue - roundValue, y: paddingValue))
176 |
177 | // 2. 右上の角の丸みを描画
178 | path.addArc(center: CGPoint(x: rect.width - paddingValue - roundValue, y: paddingValue + roundValue),
179 | radius: roundValue,
180 | startAngle: .degrees(270),
181 | endAngle: .degrees(0),
182 | clockwise: false)
183 |
184 | // 3. 右側のライン(右上から右下まで)
185 | path.addLine(to: CGPoint(x: rect.width - paddingValue, y: rect.height - paddingValue - roundValue))
186 |
187 | // 4. 右下の丸みを描画
188 | path.addArc(center: CGPoint(x: rect.width - paddingValue - roundValue, y: rect.height - paddingValue - roundValue),
189 | radius: roundValue,
190 | startAngle: .degrees(0),
191 | endAngle: .degrees(90),
192 | clockwise: false)
193 |
194 | // 5. 下側のラインを描画 (エンターキー下部の水平ライン)
195 | path.addLine(to: CGPoint(x: rect.width / 4 + paddingValue + roundValue, y: rect.height - paddingValue))
196 |
197 | // 6. 左下の角の丸みを描画
198 | path.addArc(center: CGPoint(x: rect.width / 4 + paddingValue + roundValue, y: rect.height - paddingValue - roundValue),
199 | radius: roundValue,
200 | startAngle: .degrees(90),
201 | endAngle: .degrees(180),
202 | clockwise: false)
203 |
204 | // 7. 左側のライン1本目を描画
205 | path.addLine(to: CGPoint(x: rect.width / 4 + paddingValue, y: rect.height / 2 - paddingValue + roundValue))
206 | // 8. 左中央の丸みを描画
207 | path.addArc(center: CGPoint(x: rect.width / 4 + paddingValue - roundValue, y: rect.height / 2 - paddingValue + roundValue),
208 | radius: roundValue,
209 | startAngle: .degrees(0),
210 | endAngle: .degrees(-90),
211 | clockwise: true)
212 | // 9. 中央のラインを描画
213 | path.addLine(to: CGPoint(x: paddingValue + roundValue, y: rect.height / 2 - paddingValue))
214 |
215 | // 10. 左下の角の丸みを描画
216 | path.addArc(center: CGPoint(x: paddingValue + roundValue, y: rect.height / 2 - paddingValue - roundValue),
217 | radius: roundValue,
218 | startAngle: .degrees(90),
219 | endAngle: .degrees(180),
220 | clockwise: false)
221 | // 11. 左側のライン2本目
222 | path.addLine(to: CGPoint(x: paddingValue, y: paddingValue + roundValue))
223 |
224 | //12. 左上の丸みを描画
225 | path.addArc(center: CGPoint(x: paddingValue + roundValue, y: paddingValue + roundValue),
226 | radius: roundValue,
227 | startAngle: .degrees(180),
228 | endAngle: .degrees(270),
229 | clockwise: false)
230 |
231 | // パスを閉じる
232 | path.closeSubpath()
233 | }
234 | }
235 | }
236 | struct EnterShape_UK_HighLight: Shape {
237 | let frameValue: CGFloat
238 | private var centerRoundValue: CGFloat {
239 | frameValue * 0.07
240 | }
241 | private var roundValue: CGFloat {
242 | frameValue * 0.14
243 | }
244 |
245 |
246 | func path(in rect: CGRect) -> Path {
247 | Path { path in
248 | // スタートポイント(左上の角丸終わりから時計回りに描画)
249 | let startPoint = CGPoint(x: roundValue, y: 0)
250 | // 1. 左上から右上の丸みの始まりまでのライン
251 | path.move(to: startPoint)
252 | path.addLine(to: CGPoint(x: rect.width - roundValue, y: 0))
253 |
254 | // 2. 右上の角の丸みを描画
255 | path.addArc(center: CGPoint(x: rect.width - roundValue, y: roundValue),
256 | radius: roundValue,
257 | startAngle: .degrees(270),
258 | endAngle: .degrees(0),
259 | clockwise: false)
260 |
261 | // 3. 右側のライン(右上から右下まで)
262 | path.addLine(to: CGPoint(x: rect.width, y: rect.height - roundValue))
263 |
264 | // 4. 右下の丸みを描画
265 | path.addArc(center: CGPoint(x: rect.width - roundValue, y: rect.height - roundValue),
266 | radius: roundValue,
267 | startAngle: .degrees(0),
268 | endAngle: .degrees(90),
269 | clockwise: false)
270 |
271 | // 5. 下側のラインを描画 (エンターキー下部の水平ライン)
272 | path.addLine(to: CGPoint(x: rect.width / 4 + roundValue, y: rect.height))
273 |
274 | // 6. 左下の角の丸みを描画
275 | path.addArc(center: CGPoint(x: rect.width / 4 + roundValue, y: rect.height - roundValue),
276 | radius: roundValue,
277 | startAngle: .degrees(90),
278 | endAngle: .degrees(180),
279 | clockwise: false)
280 |
281 | // 7. 左側のライン1本目を描画
282 | path.addLine(to: CGPoint(x: rect.width / 4, y: rect.height / 2 + roundValue))
283 | // 8. 左中央の丸みを描画
284 | path.addArc(center: CGPoint(x: rect.width / 4 - centerRoundValue, y: rect.height / 2 + centerRoundValue),
285 | radius: centerRoundValue,
286 | startAngle: .degrees(0),
287 | endAngle: .degrees(-90),
288 | clockwise: true)
289 | // 9. 中央のラインを描画
290 | path.addLine(to: CGPoint(x: roundValue, y: rect.height / 2))
291 |
292 | // 10. 左下の角の丸みを描画
293 | path.addArc(center: CGPoint(x: roundValue, y: rect.height / 2 - roundValue),
294 | radius: roundValue,
295 | startAngle: .degrees(90),
296 | endAngle: .degrees(180),
297 | clockwise: false)
298 | // 11. 左側のライン2本目
299 | path.addLine(to: CGPoint(x: 0, y: roundValue))
300 |
301 | //12. 左上の丸みを描画
302 | path.addArc(center: CGPoint(x: roundValue, y: roundValue),
303 | radius: roundValue,
304 | startAngle: .degrees(180),
305 | endAngle: .degrees(270),
306 | clockwise: false)
307 |
308 | // パスを閉じる
309 | path.closeSubpath()
310 | }
311 | }
312 | }
313 |
--------------------------------------------------------------------------------
/Stapler-mini-v0/Stapler-mini-v0/Keyboard/ExportKeyboardView/CustomUTType.swift:
--------------------------------------------------------------------------------
1 | ///.staplerファイルの定義とロードとエンコードの処理
2 | ///
3 |
4 | import Foundation
5 | import UniformTypeIdentifiers
6 | import SwiftUI
7 |
8 | extension UTType {
9 | public static let stapler = UTType(exportedAs: "com.example.stapler")
10 | }
11 |
12 | func exportPreset(_ preset: Preset) {
13 | let savePanel = NSSavePanel()
14 | savePanel.allowedContentTypes = [.stapler] // カスタムUTType
15 | savePanel.nameFieldStringValue = "\(preset.presetName).stapler"
16 | savePanel.begin { response in
17 | if response == .OK, let url = savePanel.url {
18 | do {
19 | let jsonData = try JSONEncoder().encode(preset) // PresetをJSONにエンコード
20 | try jsonData.write(to: url) // ファイルに書き込み
21 | print("Preset saved to \(url)")
22 | NSWorkspace.shared.activateFileViewerSelecting([url])
23 | } catch {
24 | print("Failed to save preset: \(error)")
25 | }
26 | }
27 | }
28 | }
29 |
30 | func loadPreset(completion: @escaping (Preset?) -> Void) {
31 | let openPanel = NSOpenPanel()
32 | // openPanel.allowedContentTypes = [.stapler]//ここうまく動かない。下のパターンでもだめ。何が原因か探る必要あり。
33 | // openPanel.allowedFileTypes = ["stapeler"]
34 | openPanel.begin { response in
35 | if response == .OK, let url = openPanel.url {
36 | do {
37 | let jsonData = try Data(contentsOf: url)
38 | let loadedPreset = try JSONDecoder().decode(Preset.self, from: jsonData)
39 | print("Preset loaded: \(loadedPreset)")
40 | completion(loadedPreset) // 成功時にPresetを返す
41 | } catch {
42 | print("Failed to load preset: \(error)")
43 | completion(nil) // エラー時にはnilを返す
44 | }
45 | } else {
46 | completion(nil) // キャンセルされた場合
47 | }
48 | }
49 | }
50 |
51 |
--------------------------------------------------------------------------------
/Stapler-mini-v0/Stapler-mini-v0/Keyboard/ExportKeyboardView/ExportSheetView.swift:
--------------------------------------------------------------------------------
1 | ///出力するときのシート用のビュー。
2 |
3 |
4 | import SwiftUI
5 | import UniformTypeIdentifiers
6 | import PDFKit
7 |
8 |
9 | struct CustomShapeButtonStyle: ButtonStyle {
10 | let shape: S
11 | let fillColor: Color
12 | let frameSize: CGSize
13 |
14 | func makeBody(configuration: Configuration) -> some View {
15 | shape
16 | .fill(fillColor)
17 | .frame(width: frameSize.width, height: frameSize.height)
18 | .overlay(
19 | configuration.label
20 | )
21 | .scaleEffect(configuration.isPressed ? 0.9 : 1.0) // 押した時のアニメーション
22 | // .animation(.easeInOut, value: configuration.isPressed)
23 | }
24 | }
25 |
26 | struct ExportSheetView: View {
27 | let preset: Preset
28 | let keySize: CGFloat = 65
29 | @State var showingAlert: Bool = false
30 | @State var alertMessage: String = ""
31 | @Environment(\.dismiss) private var dismiss
32 |
33 | @State private var showSuccessCheckMark_otherFile = false
34 | @State private var showSuccessCheckMark_JSONFile = false
35 | @State private var animateScale = false
36 |
37 | var body: some View {
38 | ZStack {
39 | mainSheetView
40 | .alert(isPresented: $showingAlert) {
41 | Alert(title: Text("エクスポート結果"), message: Text(alertMessage), dismissButton: .default(Text("OK")))
42 | }
43 | // 成功時のチェックマーク表示
44 | if showSuccessCheckMark_otherFile {
45 | SuccessCheckMarkView_otherFile(isPresented: $showSuccessCheckMark_otherFile, animateScale: $animateScale)
46 | }
47 | if showSuccessCheckMark_JSONFile {
48 | SuccessCheckMarkView_JSON(isPresented: $showSuccessCheckMark_JSONFile, animateScale: $animateScale)
49 | }
50 | }
51 | .animation(.easeInOut, value: showSuccessCheckMark_otherFile)
52 | .animation(.easeInOut, value: showSuccessCheckMark_JSONFile)
53 | }
54 |
55 | private var mainSheetView: some View {
56 | VStack(spacing: 0) {
57 | ZStack {
58 | HStack {
59 | Button(action: {dismiss()}) {
60 | Image(systemName: "xmark.circle")
61 | .font(.system(size: 35))
62 | }
63 | .buttonStyle(CustomShapeButtonStyle(
64 | shape: Circle(),
65 | fillColor: .clear,
66 | frameSize: CGSize(width: 40, height: 40)))
67 | .padding()
68 | Spacer()
69 | }
70 | HStack {
71 | Spacer()
72 | Text("\(preset.presetName)").font(.largeTitle)
73 | Spacer()
74 | }
75 | VStack {
76 | Spacer()
77 | HStack{
78 | Spacer()
79 | Text("VendorID: \(preset.vendorID)")
80 | Text("ProductID: \(preset.productID)")
81 | Divider().frame(height: 10)
82 | Text("KeyCode Region: \(preset.keyCodeRegion)")
83 | }
84 | .font(.caption)
85 | .padding()
86 | }
87 | }
88 | Divider()
89 | // プリセットを受け取って、レイヤーまで一覧できるキーボードビュー
90 | KeyboardView_AllLayer(keySize: keySize, preset: preset)
91 | Divider()
92 | HStack {
93 | Menu {
94 | Button {
95 | exportPNG_AllLayer()
96 | } label: {
97 | Label("Export All Layer as PNG", systemImage: "photo")
98 | }
99 | Button {
100 | exportPDF_AllLayer()
101 | } label: {
102 | Label("Export All Layer as PDF", systemImage: "photo")
103 | }
104 | Button {
105 | exportPDF_EachLayer()
106 | } label: {
107 | Label("Export EachLayer as PDF", systemImage: "photo.stack")
108 | }
109 | } label: {
110 | Label("Export Image", systemImage: "photo")
111 | .padding()
112 | }
113 | Button{
114 | exportPreset(preset)
115 | } label: {
116 | Label("Share Preset as stapler", systemImage: "square.and.arrow.up")
117 | }
118 | Button{
119 | exportJSON()
120 | } label: {
121 | Label ("Export as json", systemImage: "document.badge.gearshape")
122 | }
123 |
124 | }
125 | .padding()
126 | }
127 | }
128 |
129 | // 共通のエクスポート結果表示処理
130 | func handleExportResult(success: Bool, message: String? = nil, fileURL: URL? = nil) {
131 | if success {
132 | showExportSuccessMessage(fileURL: fileURL)
133 | } else {
134 | showExportFailureMessage(errorMessage: message)
135 | }
136 | }
137 | func exportJSON() {
138 | JSONExporter.exportJSON(preset, showingAlert: $showingAlert, alertMessage: $alertMessage, animationBool: $showSuccessCheckMark_JSONFile)
139 | }
140 |
141 | func exportPNG_AllLayer() {
142 | let allLayer = KeyboardView_AllLayer(keySize: 100, preset: preset)
143 | let renderer = ImageRenderer(content: allLayer)
144 |
145 | let savePanel = NSSavePanel()
146 | savePanel.allowedContentTypes = [UTType.png]
147 | savePanel.nameFieldStringValue = "\(preset.presetName).png"
148 |
149 | savePanel.begin { response in
150 | if response == .OK, let url = savePanel.url {
151 | if let imageData = renderer.nsImage?.tiffRepresentation,
152 | let bitmap = NSBitmapImageRep(data: imageData),
153 | let pngData = bitmap.representation(using: .png, properties: [:]) {
154 | do {
155 | try pngData.write(to: url)
156 | handleExportResult(success: true, fileURL: url)
157 | } catch {
158 | handleExportResult(success: false, message: error.localizedDescription)
159 | }
160 | } else {
161 | handleExportResult(success: false, message: "画像の生成に失敗しました。")
162 | }
163 | } else {
164 | showExportCancelledMessage()
165 | }
166 | }
167 | }
168 |
169 | // PDF出力の処理
170 | func exportPDF_AllLayer() {
171 | let allLayer = KeyboardView_AllLayer(keySize: keySize, preset: preset)
172 | let renderer = ImageRenderer(content: allLayer)
173 |
174 | let savePanel = NSSavePanel()
175 | savePanel.allowedContentTypes = [UTType.pdf]
176 | savePanel.nameFieldStringValue = "\(preset.presetName).pdf"
177 |
178 | savePanel.begin { response in
179 | if response == .OK, let url = savePanel.url {
180 | renderer.render { size, context in
181 | var box = CGRect(x: 0, y: 0, width: size.width, height: size.height)
182 | guard let pdfContext = CGContext(url as CFURL, mediaBox: &box, nil) else {
183 | return
184 | }
185 |
186 | pdfContext.beginPDFPage(nil)
187 | context(pdfContext)
188 | pdfContext.endPDFPage()
189 | pdfContext.closePDF()
190 |
191 | handleExportResult(success: true, fileURL: url)
192 | }
193 | } else {
194 | showExportCancelledMessage()
195 | }
196 | }
197 | }
198 | func exportPDF_EachLayer() {
199 | // 各レイヤーのビューを作成
200 | let eachLayer012 = VStack {
201 | KeyboardView_EachLayer(keySize: 100, preset: preset, layer: preset.layer0).padding(.vertical, 10)
202 | KeyboardView_EachLayer(keySize: 100, preset: preset, layer: preset.layer1).padding(.vertical, 10)
203 | KeyboardView_EachLayer(keySize: 100, preset: preset, layer: preset.layer2).padding(.vertical, 10)
204 | }
205 | let eachLayer345 = VStack {
206 | KeyboardView_EachLayer(keySize: 100, preset: preset, layer: preset.layer3).padding(.vertical, 10)
207 | KeyboardView_EachLayer(keySize: 100, preset: preset, layer: preset.layer4).padding(.vertical, 10)
208 | KeyboardView_EachLayer(keySize: 100, preset: preset, layer: preset.layer5).padding(.vertical, 10)
209 | }
210 | let eachLayer678 = VStack {
211 | KeyboardView_EachLayer(keySize: 100, preset: preset, layer: preset.layer6).padding(.vertical, 10)
212 | KeyboardView_EachLayer(keySize: 100, preset: preset, layer: preset.layer7).padding(.vertical, 10)
213 | KeyboardView_EachLayer(keySize: 100, preset: preset, layer: preset.layer8).padding(.vertical, 10)
214 | }
215 | // PDFの保存パネル
216 | let savePanel = NSSavePanel()
217 | savePanel.allowedContentTypes = [UTType.pdf]
218 | savePanel.nameFieldStringValue = "\(preset.presetName)_forEachLayer.pdf"
219 |
220 | savePanel.begin { response in
221 | if response == .OK, let url = savePanel.url {
222 | // PDFのレンダリング処理を開始
223 | let renderers = [
224 | ImageRenderer(content: eachLayer012),
225 | ImageRenderer(content: eachLayer345),
226 | ImageRenderer(content: eachLayer678)
227 |
228 | ]
229 |
230 | // PDFデータの準備
231 | let pdfData = NSMutableData()
232 | let pdfConsumer = CGDataConsumer(data: pdfData as CFMutableData)!
233 |
234 | // 最初のレイヤーのサイズを取得してmediaBoxを設定
235 | var initialSize: CGSize = .zero
236 | renderers.first?.render { size, _ in
237 | initialSize = size
238 | }
239 | var mediaBox = CGRect(origin: .zero, size: initialSize)
240 |
241 | guard let pdfContext = CGContext(consumer: pdfConsumer, mediaBox: &mediaBox, nil) else {
242 | showExportFailureMessage(errorMessage: "Failed to create PDF context")
243 | return
244 | }
245 |
246 | for (index, renderer) in renderers.enumerated() {
247 | renderer.render { size, context in
248 | let box = CGRect(origin: .zero, size: size)
249 | print("Layer \(index) rendered size: \(size)")
250 |
251 | // 新しいPDFページの開始(各ページに正確なサイズを設定)
252 | let pageInfo = [kCGPDFContextMediaBox: box] as CFDictionary
253 | pdfContext.beginPDFPage(pageInfo)
254 | context(pdfContext) // 各レイヤーのビューをレンダリング
255 | pdfContext.endPDFPage() // ページを閉じる
256 | }
257 | }
258 | pdfContext.closePDF()
259 |
260 | // PDFデータをファイルに保存
261 | do {
262 | try pdfData.write(to: url)
263 | showExportSuccessMessage(fileURL: url) // 成功時の処理
264 | } catch {
265 | showExportFailureMessage(errorMessage: "Failed to write PDF: \(error)") // ファイル保存中のエラー処理
266 | }
267 | } else {
268 | showExportCancelledMessage() // ユーザーがキャンセルした場合の処理
269 | }
270 | }
271 | }
272 | // 成功時のメッセージ表示
273 | func showExportSuccessMessage(fileURL: URL?) {
274 | print("ファイルが正常に保存されました。")
275 | // alertMessage = "ファイルが正常に保存されました。"
276 | // showingAlert = true
277 | withAnimation {
278 | showSuccessCheckMark_otherFile = true
279 | }
280 | // クイックルックやFinderで開く
281 | if let fileURL = fileURL {
282 | NSWorkspace.shared.activateFileViewerSelecting([fileURL])
283 | }
284 | }
285 |
286 | // 失敗時のメッセージ表示
287 | func showExportFailureMessage(errorMessage: String?) {
288 | alertMessage = errorMessage ?? "エクスポート中にエラーが発生しました。"
289 | showingAlert = true
290 | print(alertMessage)
291 | }
292 |
293 | // キャンセル時のメッセージ表示
294 | func showExportCancelledMessage() {
295 | print("保存がキャンセルされました。")
296 | }
297 | }
298 |
299 |
300 | struct SuccessCheckMarkView_JSON: View {
301 | @Binding var isPresented: Bool
302 | @Binding var animateScale: Bool
303 | var body: some View {
304 |
305 |
306 | VStack(spacing: 20) {
307 | Image(systemName: "checkmark.circle")
308 | .symbolEffect(.bounce.up, options: .repeat(3), isActive: isPresented)
309 | .font(.system(size: 60))
310 | .foregroundColor(.green)
311 | }
312 | .padding()
313 | .frame(width: 300, height: 200)
314 | .scaleEffect(animateScale ? 1.0 : 0.5) // 初期状態と表示後の大きさ
315 | .onAppear {
316 | withAnimation/*(.easeInOut(duration: 0.3)) */{
317 | animateScale = true // 表示と同時にスケールアップ
318 | }
319 | // playNotificationSound() // 通知音を鳴らす
320 | playCustomSound()
321 | autoDismiss() // 一定時間後に自動で非表示
322 | }
323 | .onDisappear {
324 | animateScale = false // アラートが非表示になった時にリセット
325 | }
326 | }
327 |
328 |
329 | // 一定時間後にアラートを自動的に非表示にする関数
330 | private func autoDismiss() {
331 | DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
332 | isPresented = false
333 | }
334 | }
335 |
336 | // 通知音を鳴らす関数
337 | private func playNotificationSound() {
338 | let sound = NSSound(named: NSSound.Name("Submarine")) // システム通知音を指定
339 | sound?.play() // サウンドを再生
340 | }
341 | // カスタム音声ファイルを再生する関数
342 | private func playCustomSound() {
343 | if let soundURL = Bundle.main.url(forResource: "Success1", withExtension: "wav") { // "customSound.mp3"ファイルを指定
344 | let sound = NSSound(contentsOf: soundURL, byReference: false) // ファイルパスからサウンドをロード
345 | sound?.play() // カスタムサウンドを再生
346 | } else {
347 | print("カスタムサウンドファイルが見つかりませんでした")
348 | }
349 | }
350 | }
351 |
352 |
353 | struct SuccessCheckMarkView_otherFile: View {
354 | @Binding var isPresented: Bool
355 | @Binding var animateScale: Bool
356 | var body: some View {
357 |
358 |
359 | VStack(spacing: 20) {
360 | Image(systemName: "checkmark.circle")
361 | .symbolEffect(.bounce.up, options: .repeat(3), isActive: isPresented)
362 | .font(.system(size: 60))
363 | .foregroundColor(.green)
364 | }
365 | .padding()
366 | .frame(width: 300, height: 200)
367 | .scaleEffect(animateScale ? 1.0 : 0.5) // 初期状態と表示後の大きさ
368 | .onAppear {
369 | withAnimation/*(.easeInOut(duration: 0.3)) */{
370 | animateScale = true // 表示と同時にスケールアップ
371 | }
372 |
373 | autoDismiss() // 一定時間後に自動で非表示
374 | }
375 | .onDisappear {
376 | animateScale = false // アラートが非表示になった時にリセット
377 | }
378 | }
379 |
380 |
381 | // 一定時間後にアラートを自動的に非表示にする関数
382 | private func autoDismiss() {
383 | DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
384 | isPresented = false
385 | }
386 | }
387 | }
388 |
389 |
390 |
--------------------------------------------------------------------------------
/Stapler-mini-v0/Stapler-mini-v0/Keyboard/ExportKeyboardView/Success1.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/9dpbQ/Stapler-mini-v0/7939b748c37213fb0e04f4bdd383523d72949760/Stapler-mini-v0/Stapler-mini-v0/Keyboard/ExportKeyboardView/Success1.wav
--------------------------------------------------------------------------------
/Stapler-mini-v0/Stapler-mini-v0/Keyboard/ExportKeyboardView/Success2.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/9dpbQ/Stapler-mini-v0/7939b748c37213fb0e04f4bdd383523d72949760/Stapler-mini-v0/Stapler-mini-v0/Keyboard/ExportKeyboardView/Success2.wav
--------------------------------------------------------------------------------
/Stapler-mini-v0/Stapler-mini-v0/Keyboard/KeyboardView.swift:
--------------------------------------------------------------------------------
1 | import SwiftUI
2 |
3 | struct BuiltInKeyboardLayerView_US: View {
4 | @Binding var selectedKeyboardKey: KeyboardKey
5 | let keySize: CGFloat
6 | var layer: [KeyboardKey]
7 |
8 | var body: some View {
9 |
10 | VStack(alignment: .leading, spacing: 0) {
11 | HStack (spacing: 0) {//Row1
12 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[0], unitSize: 1.5, baseSize: keySize)
13 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[1], unitSize: 1, baseSize: keySize)
14 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[2], unitSize: 1, baseSize: keySize)
15 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[3], unitSize: 1, baseSize: keySize)
16 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[4], unitSize: 1, baseSize: keySize)
17 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[5], unitSize: 1, baseSize: keySize)
18 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[6], unitSize: 1, baseSize: keySize)
19 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[7], unitSize: 1, baseSize: keySize)
20 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[8], unitSize: 1, baseSize: keySize)
21 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[9], unitSize: 1, baseSize: keySize)
22 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[10], unitSize: 1, baseSize: keySize)
23 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[11], unitSize: 1, baseSize: keySize)
24 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[12], unitSize: 1, baseSize: keySize)
25 |
26 |
27 | }
28 | HStack (spacing: 0) {//Row2
29 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[13], unitSize: 1, baseSize: keySize)
30 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[14], unitSize: 1, baseSize: keySize)
31 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[15], unitSize: 1, baseSize: keySize)
32 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[16], unitSize: 1, baseSize: keySize)
33 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[17], unitSize: 1, baseSize: keySize)
34 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[18], unitSize: 1, baseSize: keySize)
35 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[19], unitSize: 1, baseSize: keySize)
36 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[20], unitSize: 1, baseSize: keySize)
37 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[21], unitSize: 1, baseSize: keySize)
38 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[22], unitSize: 1, baseSize: keySize)
39 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[23], unitSize: 1, baseSize: keySize)
40 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[24], unitSize: 1, baseSize: keySize)
41 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[25], unitSize: 1, baseSize: keySize)
42 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[26], unitSize: 1.5, baseSize: keySize)
43 |
44 |
45 |
46 |
47 | }
48 | HStack (spacing: 0) {//Row3
49 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[27], unitSize: 1.5, baseSize: keySize)
50 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[28], unitSize: 1, baseSize: keySize)
51 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[29], unitSize: 1, baseSize: keySize)
52 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[30], unitSize: 1, baseSize: keySize)
53 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[31], unitSize: 1, baseSize: keySize)
54 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[32], unitSize: 1, baseSize: keySize)
55 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[33], unitSize: 1, baseSize: keySize)
56 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[34], unitSize: 1, baseSize: keySize)
57 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[35], unitSize: 1, baseSize: keySize)
58 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[36], unitSize: 1, baseSize: keySize)
59 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[37], unitSize: 1, baseSize: keySize)
60 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[38], unitSize: 1, baseSize: keySize)
61 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[39], unitSize: 1, baseSize: keySize)
62 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[40], unitSize: 1, baseSize: keySize)
63 |
64 |
65 |
66 | }
67 | HStack (spacing: 0) {//Row4
68 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[41], unitSize: 1.75, baseSize: keySize)
69 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[42], unitSize: 1, baseSize: keySize)
70 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[43], unitSize: 1, baseSize: keySize)
71 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[44], unitSize: 1, baseSize: keySize)
72 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[45], unitSize: 1, baseSize: keySize)
73 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[46], unitSize: 1, baseSize: keySize)
74 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[47], unitSize: 1, baseSize: keySize)
75 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[48], unitSize: 1, baseSize: keySize)
76 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[49], unitSize: 1, baseSize: keySize)
77 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[50], unitSize: 1, baseSize: keySize)
78 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[51], unitSize: 1, baseSize: keySize)
79 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[52], unitSize: 1, baseSize: keySize)
80 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[53], unitSize: 1.75, baseSize: keySize)
81 |
82 |
83 | }
84 | HStack (spacing: 0) {//Row5
85 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[54], unitSize: 2.25, baseSize: keySize)
86 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[55], unitSize: 1, baseSize: keySize)
87 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[56], unitSize: 1, baseSize: keySize)
88 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[57], unitSize: 1, baseSize: keySize)
89 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[58], unitSize: 1, baseSize: keySize)
90 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[59], unitSize: 1, baseSize: keySize)
91 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[60], unitSize: 1, baseSize: keySize)
92 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[61], unitSize: 1, baseSize: keySize)
93 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[62], unitSize: 1, baseSize: keySize)
94 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[63], unitSize: 1, baseSize: keySize)
95 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[64], unitSize: 1, baseSize: keySize)
96 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[65], unitSize: 2.25, baseSize: keySize)
97 |
98 | }
99 | HStack (spacing: 0) {//Row6
100 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[66], unitSize: 1, baseSize: keySize)
101 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[67], unitSize: 1, baseSize: keySize)
102 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[68], unitSize: 1, baseSize: keySize)
103 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[69], unitSize: 1.25, baseSize: keySize)
104 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[70], unitSize: 5, baseSize: keySize)
105 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[71], unitSize: 1.25, baseSize: keySize)
106 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[72], unitSize: 1, baseSize: keySize)
107 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[73], unitSize: 1, baseSize: keySize)
108 | VStack (spacing: 0) {//ここにarrowの上下がくるなぁ〜専用のビューを作らないとダメだね
109 | KeyboardKeyView_arrow(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[74], unitSize: 1, baseSize: keySize)
110 | KeyboardKeyView_arrow(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[75], unitSize: 1, baseSize: keySize)
111 | }
112 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[76], unitSize: 1, baseSize: keySize)
113 | }
114 | }
115 | }
116 | }
117 |
118 | //#Preview {
119 | // let preset = Preset(presetName: "test", keyboardLayout: KeyboardLayout.US)
120 | // @State var selected = KeyboardKey(beforeDisplaySymbol: "1", beforeKeyOutPut: "2")
121 | // BuiltInKeyboardLayerView_US(selectedKeyboardKey: $selected ,layer: preset.layer0)
122 | //}
123 |
124 | struct BuiltInKeyboardLayerView_JIS: View {
125 | @Binding var selectedKeyboardKey: KeyboardKey
126 | let keySize: CGFloat
127 | var layer: [KeyboardKey]
128 | var body: some View {
129 | ZStack {
130 | VStack(alignment: .trailing ,spacing: 0) {
131 | Spacer()
132 | HStack (spacing: 0){
133 | Spacer().frame(width: keySize * 13.25 - keySize * 0.07 * 4 + keySize * 0.07 / 2 )
134 | KeyboardKeyView_enter_JIS(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[53], baseSize: keySize)
135 | }
136 | Spacer()
137 | }
138 | VStack(alignment: .leading ,spacing: 0) {
139 | HStack (spacing: 0) {//Row1
140 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[0], unitSize: 1.5, baseSize: keySize)
141 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[1], unitSize: 1, baseSize: keySize)
142 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[2], unitSize: 1, baseSize: keySize)
143 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[3], unitSize: 1, baseSize: keySize)
144 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[4], unitSize: 1, baseSize: keySize)
145 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[5], unitSize: 1, baseSize: keySize)
146 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[6], unitSize: 1, baseSize: keySize)
147 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[7], unitSize: 1, baseSize: keySize)
148 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[8], unitSize: 1, baseSize: keySize)
149 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[9], unitSize: 1, baseSize: keySize)
150 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[10], unitSize: 1, baseSize: keySize)
151 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[11], unitSize: 1, baseSize: keySize)
152 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[12], unitSize: 1, baseSize: keySize)
153 |
154 |
155 | }
156 | HStack (spacing: 0) {//Row2
157 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[13], unitSize: 1.25, baseSize: keySize)
158 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[14], unitSize: 1, baseSize: keySize)
159 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[15], unitSize: 1, baseSize: keySize)
160 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[16], unitSize: 1, baseSize: keySize)
161 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[17], unitSize: 1, baseSize: keySize)
162 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[18], unitSize: 1, baseSize: keySize)
163 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[19], unitSize: 1, baseSize: keySize)
164 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[20], unitSize: 1, baseSize: keySize)
165 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[21], unitSize: 1, baseSize: keySize)
166 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[22], unitSize: 1, baseSize: keySize)
167 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[23], unitSize: 1, baseSize: keySize)
168 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[24], unitSize: 1, baseSize: keySize)
169 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[25], unitSize: 1, baseSize: keySize)
170 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[26], unitSize: 1.25, baseSize: keySize)//BS
171 |
172 |
173 | }
174 | HStack (spacing: 0) {//Row3
175 |
176 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[27], unitSize: 1, baseSize: keySize)
177 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[28], unitSize: 1, baseSize: keySize)
178 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[29], unitSize: 1, baseSize: keySize)
179 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[30], unitSize: 1, baseSize: keySize)
180 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[31], unitSize: 1, baseSize: keySize)
181 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[32], unitSize: 1, baseSize: keySize)
182 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[33], unitSize: 1, baseSize: keySize)
183 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[34], unitSize: 1, baseSize: keySize)
184 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[35], unitSize: 1, baseSize: keySize)
185 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[36], unitSize: 1, baseSize: keySize)
186 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[37], unitSize: 1, baseSize: keySize)
187 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[38], unitSize: 1, baseSize: keySize)
188 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[39], unitSize: 1, baseSize: keySize)//「
189 |
190 |
191 |
192 |
193 | }
194 | HStack (spacing: 0) {//Row4
195 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[40], unitSize: 1.25, baseSize: keySize)
196 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[41], unitSize: 1, baseSize: keySize)
197 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[42], unitSize: 1, baseSize: keySize)
198 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[43], unitSize: 1, baseSize: keySize)
199 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[44], unitSize: 1, baseSize: keySize)
200 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[45], unitSize: 1, baseSize: keySize)
201 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[46], unitSize: 1, baseSize: keySize)
202 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[47], unitSize: 1, baseSize: keySize)
203 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[48], unitSize: 1, baseSize: keySize)
204 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[49], unitSize: 1, baseSize: keySize)
205 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[50], unitSize: 1, baseSize: keySize)
206 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[51], unitSize: 1, baseSize: keySize)
207 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[52], unitSize: 1, baseSize: keySize)
208 | // KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[53], unitSize: 1.25)//エンター
209 |
210 |
211 | }
212 | HStack (spacing: 0) {//Row5
213 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[54], unitSize: 1.75, baseSize: keySize)
214 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[55], unitSize: 1, baseSize: keySize)
215 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[56], unitSize: 1, baseSize: keySize)
216 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[57], unitSize: 1, baseSize: keySize)
217 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[58], unitSize: 1, baseSize: keySize)
218 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[59], unitSize: 1, baseSize: keySize)
219 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[60], unitSize: 1, baseSize: keySize)
220 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[61], unitSize: 1, baseSize: keySize)
221 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[62], unitSize: 1, baseSize: keySize)
222 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[63], unitSize: 1, baseSize: keySize)
223 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[64], unitSize: 1, baseSize: keySize)
224 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[65], unitSize: 1, baseSize: keySize)
225 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[66], unitSize: 1.75, baseSize: keySize)
226 |
227 |
228 |
229 | }
230 | HStack (spacing: 0) {//Row6
231 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[67], unitSize: 1, baseSize: keySize)
232 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[68], unitSize: 1, baseSize: keySize)
233 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[69], unitSize: 1.25, baseSize: keySize)
234 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[70], unitSize: 1.25, baseSize: keySize)
235 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[71], unitSize: 3.5, baseSize: keySize)
236 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[72], unitSize: 1.25, baseSize: keySize)
237 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[73], unitSize: 1.25, baseSize: keySize)
238 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[74], unitSize: 1, baseSize: keySize)
239 |
240 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[75], unitSize: 1, baseSize: keySize)
241 | VStack (spacing: 0) {
242 | KeyboardKeyView_arrow(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[76], unitSize: 1, baseSize: keySize)
243 | KeyboardKeyView_arrow(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[77], unitSize: 1, baseSize: keySize)
244 | }
245 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[78], unitSize: 1, baseSize: keySize)
246 | }
247 | }
248 | }
249 | }
250 | }
251 |
252 | //#Preview {
253 | // let preset = Preset(presetName: "test", keyboardLayout: KeyboardLayout.JIS)
254 | // @State var selected = KeyboardKey(beforeDisplaySymbol: "1", beforeKeyOutPut: "2")
255 | // BuiltInKeyboardLayerView_JIS(selectedKeyboardKey: $selected, keySize: 75 ,layer: preset.layer0)
256 | //}
257 |
258 | struct BuiltInKeyboardLayerView_UK: View {
259 | @Binding var selectedKeyboardKey: KeyboardKey
260 | let keySize: CGFloat
261 | var layer: [KeyboardKey]
262 |
263 | var body: some View {
264 | ZStack {
265 | VStack(alignment: .trailing ,spacing: 0) {
266 | Spacer()
267 | HStack (spacing: 0){
268 | Spacer().frame(width: keySize * 13.75 - keySize * 0.07 * 4 + keySize * 0.07 / 2)
269 | KeyboardKeyView_enter_UK(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[53], baseSize: keySize)
270 | }
271 | Spacer()
272 | }
273 | VStack(alignment: .leading, spacing: 0) {
274 | HStack (spacing: 0) {//Row1
275 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[0], unitSize: 1.5, baseSize: keySize)
276 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[1], unitSize: 1, baseSize: keySize)
277 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[2], unitSize: 1, baseSize: keySize)
278 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[3], unitSize: 1, baseSize: keySize)
279 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[4], unitSize: 1, baseSize: keySize)
280 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[5], unitSize: 1, baseSize: keySize)
281 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[6], unitSize: 1, baseSize: keySize)
282 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[7], unitSize: 1, baseSize: keySize)
283 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[8], unitSize: 1, baseSize: keySize)
284 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[9], unitSize: 1, baseSize: keySize)
285 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[10], unitSize: 1, baseSize: keySize)
286 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[11], unitSize: 1, baseSize: keySize)
287 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[12], unitSize: 1, baseSize: keySize)
288 |
289 |
290 | }
291 | HStack (spacing: 0) {//Row2
292 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[13], unitSize: 1, baseSize: keySize)
293 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[14], unitSize: 1, baseSize: keySize)
294 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[15], unitSize: 1, baseSize: keySize)
295 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[16], unitSize: 1, baseSize: keySize)
296 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[17], unitSize: 1, baseSize: keySize)
297 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[18], unitSize: 1, baseSize: keySize)
298 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[19], unitSize: 1, baseSize: keySize)
299 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[20], unitSize: 1, baseSize: keySize)
300 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[21], unitSize: 1, baseSize: keySize)
301 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[22], unitSize: 1, baseSize: keySize)
302 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[23], unitSize: 1, baseSize: keySize)
303 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[24], unitSize: 1, baseSize: keySize)
304 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[25], unitSize: 1, baseSize: keySize)
305 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[26], unitSize: 1.5, baseSize: keySize)
306 | }
307 | HStack (spacing: 0) {//Row3
308 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[27], unitSize: 1.5, baseSize: keySize)
309 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[28], unitSize: 1, baseSize: keySize)
310 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[29], unitSize: 1, baseSize: keySize)
311 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[30], unitSize: 1, baseSize: keySize)
312 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[31], unitSize: 1, baseSize: keySize)
313 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[32], unitSize: 1, baseSize: keySize)
314 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[33], unitSize: 1, baseSize: keySize)
315 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[34], unitSize: 1, baseSize: keySize)
316 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[35], unitSize: 1, baseSize: keySize)
317 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[36], unitSize: 1, baseSize: keySize)
318 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[37], unitSize: 1, baseSize: keySize)
319 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[38], unitSize: 1, baseSize: keySize)
320 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[39], unitSize: 1, baseSize: keySize)
321 |
322 |
323 |
324 | }
325 | HStack (spacing: 0) {//Row4
326 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[40], unitSize: 1.75, baseSize: keySize)
327 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[41], unitSize: 1, baseSize: keySize)
328 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[42], unitSize: 1, baseSize: keySize)
329 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[43], unitSize: 1, baseSize: keySize)
330 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[44], unitSize: 1, baseSize: keySize)
331 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[45], unitSize: 1, baseSize: keySize)
332 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[46], unitSize: 1, baseSize: keySize)
333 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[47], unitSize: 1, baseSize: keySize)
334 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[48], unitSize: 1, baseSize: keySize)
335 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[49], unitSize: 1, baseSize: keySize)
336 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[50], unitSize: 1, baseSize: keySize)
337 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[51], unitSize: 1, baseSize: keySize)
338 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[52], unitSize: 1, baseSize: keySize)
339 |
340 | }
341 | HStack (spacing: 0) {//Row5
342 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[54], unitSize: 1.25, baseSize: keySize)
343 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[55], unitSize: 1, baseSize: keySize)
344 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[56], unitSize: 1, baseSize: keySize)
345 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[57], unitSize: 1, baseSize: keySize)
346 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[58], unitSize: 1, baseSize: keySize)
347 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[59], unitSize: 1, baseSize: keySize)
348 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[60], unitSize: 1, baseSize: keySize)
349 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[61], unitSize: 1, baseSize: keySize)
350 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[62], unitSize: 1, baseSize: keySize)
351 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[63], unitSize: 1, baseSize: keySize)
352 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[64], unitSize: 1, baseSize: keySize)
353 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[65], unitSize: 1, baseSize: keySize)
354 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[66], unitSize: 2.25, baseSize: keySize)
355 |
356 |
357 | }
358 | HStack (spacing: 0) {//Row6
359 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[67], unitSize: 1, baseSize: keySize)
360 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[68], unitSize: 1, baseSize: keySize)
361 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[69], unitSize: 1, baseSize: keySize)
362 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[70], unitSize: 1.25, baseSize: keySize)
363 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[71], unitSize: 5, baseSize: keySize)
364 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[72], unitSize: 1.25, baseSize: keySize)
365 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[73], unitSize: 1, baseSize: keySize)
366 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[74], unitSize: 1, baseSize: keySize)
367 | VStack(spacing: 0) {
368 | KeyboardKeyView_arrow(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[75], unitSize: 1, baseSize: keySize)
369 | KeyboardKeyView_arrow(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[76], unitSize: 1, baseSize: keySize)
370 | }
371 | KeyboardKeyView(selectedKeyboardKey: $selectedKeyboardKey, keyboardKey: layer[77], unitSize: 1, baseSize: keySize)
372 |
373 | }
374 | }
375 |
376 | }
377 | }
378 | }
379 |
380 | //#Preview {
381 | // let preset = Preset(presetName: "test", keyboardLayout: KeyboardLayout.UK)
382 | // @State var selected = KeyboardKey(beforeDisplaySymbol: "1", beforeKeyOutPut: "2")
383 | // BuiltInKeyboardLayerView_UK(selectedKeyboardKey: $selected ,layer: preset.layer0)
384 | //}
385 |
--------------------------------------------------------------------------------
/Stapler-mini-v0/Stapler-mini-v0/Keyboard/PresetView.swift:
--------------------------------------------------------------------------------
1 | ///PresetView:Presetを引数にとるビュー。
2 | ///KeyboardView:Presetのレイアウトで分岐してそれぞれのレイアウトを表示する
3 | ///CustomizeKeytab View:ドラッグ元のビュー。
4 |
5 |
6 | import SwiftUI
7 |
8 | //class FocusManager: ObservableObject {
9 | // @FocusState var isNameFocused: Bool = false//これでもダメだった。どうやってみんなフォーカスステート管理してるん?
10 | // @Published var isVendorFocused: Bool = false
11 | // @Published var isProductFocused: Bool = false
12 | // @Published var isSearchFocused: Bool = false
13 | //
14 | // func escapeAllFocus() {
15 | // isNameFocused = false
16 | // isVendorFocused = false
17 | // isProductFocused = false
18 | // isSearchFocused = false
19 | // }
20 | //}
21 |
22 |
23 | struct PresetView: View {
24 | @Binding var preset: Preset
25 | @Binding var selectedKeyboardKey: KeyboardKey
26 | @FocusState var nameFocus: Bool
27 | @FocusState var vendorFocus: Bool
28 | @FocusState var productFocus: Bool
29 | // @State var searchFieldFocus: Bool
30 |
31 | @State var pickerIndex: Int = 0
32 |
33 | var body: some View {
34 | ZStack {
35 | Color.clear
36 | .contentShape(Rectangle())
37 | .frame(maxWidth: .infinity, maxHeight: .infinity) // 画面全体をカバー
38 | .onTapGesture {
39 | escape()
40 | }
41 | VStack {
42 | presetDetailView.padding()
43 | KeyboardView(preset: $preset, selectedKeyboardKey: $selectedKeyboardKey)
44 | CustomizeKeyTabView(/*externalSearchFieldFocuse: $searchFieldFocus*/)
45 | }
46 |
47 | }
48 | .onAppear {
49 | escape()
50 | }
51 |
52 | }
53 | private var presetDetailView: some View {
54 | VStack {
55 | HStack {//プリセット名、ベンダーID、ANSIかJISかなどをここに
56 | Spacer()
57 | TextField("Preset Name", text: $preset.presetName)
58 | .focused($nameFocus)
59 | .onSubmit {
60 | nameFocus = false
61 | }
62 | .textFieldStyle(.roundedBorder)
63 | .frame(width: 300)
64 | Text("VendorID:")
65 | TextField("Vendor ID", text: $preset.vendorID)
66 | .focused($vendorFocus)
67 | .onSubmit {
68 | vendorFocus = false
69 | }
70 | .textFieldStyle(.roundedBorder)
71 | .frame(width: 100)
72 | Text("ProductID:")
73 | TextField("Product ID", text: $preset.productID)
74 | .focused($productFocus)
75 | .onSubmit {
76 | productFocus = false
77 | }
78 | .textFieldStyle(.roundedBorder)
79 | .frame(width: 100)
80 | Picker("", selection: $preset.keyCodeRegion) {
81 | Text("ANSI").tag(KeyCodeRegion.ansi)
82 | Text("JIS").tag(KeyCodeRegion.jis)
83 | Text("ISO").tag(KeyCodeRegion.iso)
84 | }
85 | .pickerStyle(SegmentedPickerStyle())
86 | .frame(width: 200)
87 | Spacer()
88 | }
89 | }
90 | }
91 | private func escape() {
92 | selectedKeyboardKey = .initial
93 | nameFocus = false
94 | vendorFocus = false
95 | productFocus = false
96 | // searchFieldFocus = false
97 | }
98 | }
99 |
100 |
101 | class LayerColorManager: ObservableObject {
102 | @Published var currentLayerColor: LayerColor = .layer0
103 | }
104 |
105 | struct KeyboardView: View {
106 | @Binding var preset: Preset
107 | @Binding var selectedKeyboardKey: KeyboardKey
108 | @State private var selectedLayer = 0
109 |
110 | @State private var selectedLayerColor: LayerColor = .layer0
111 | private let keySize: CGFloat = 65
112 | var body: some View {
113 | VStack {
114 | HStack {
115 | Spacer()
116 | ForEach(0..<9) { index in
117 | Button(action: {
118 | selectedLayer = index
119 | selectedLayerColor = colorForTab(index: selectedLayer)
120 |
121 | }) {
122 | if index == 0 {
123 | Text("Default")
124 | .bold()
125 | .frame(width: 80, height: 25)
126 | } else {
127 | Text("Layer \(index)")
128 | .frame(width: 80, height: 25)
129 | }
130 | }
131 | .buttonStyle(ParallelogramButtonStyle(isSelected: selectedLayer == index, tabIndex: index))
132 | .padding(.horizontal, 5)
133 |
134 | }
135 |
136 | Spacer()
137 |
138 | }
139 | .padding(.horizontal)
140 |
141 | VStack{
142 | switch preset.keyboardLayout {
143 | case .US:
144 | // レイヤーによって表示されるキーボードレイアウトを切り替える
145 | switch selectedLayer {
146 | case 0:
147 | BuiltInKeyboardLayerView_US(selectedKeyboardKey: $selectedKeyboardKey, keySize: keySize, layer: preset.layer0)
148 | case 1:
149 | BuiltInKeyboardLayerView_US(selectedKeyboardKey: $selectedKeyboardKey, keySize: keySize, layer: preset.layer1)
150 | case 2:
151 | BuiltInKeyboardLayerView_US(selectedKeyboardKey: $selectedKeyboardKey, keySize: keySize, layer: preset.layer2)
152 | case 3:
153 | BuiltInKeyboardLayerView_US(selectedKeyboardKey: $selectedKeyboardKey, keySize: keySize, layer: preset.layer3)
154 | case 4:
155 | BuiltInKeyboardLayerView_US(selectedKeyboardKey: $selectedKeyboardKey, keySize: keySize, layer: preset.layer4)
156 | case 5:
157 | BuiltInKeyboardLayerView_US(selectedKeyboardKey: $selectedKeyboardKey, keySize: keySize, layer: preset.layer5)
158 | case 6:
159 | BuiltInKeyboardLayerView_US(selectedKeyboardKey: $selectedKeyboardKey, keySize: keySize, layer: preset.layer6)
160 | case 7:
161 | BuiltInKeyboardLayerView_US(selectedKeyboardKey: $selectedKeyboardKey, keySize: keySize, layer: preset.layer7)
162 | case 8:
163 | BuiltInKeyboardLayerView_US(selectedKeyboardKey: $selectedKeyboardKey, keySize: keySize, layer: preset.layer8)
164 |
165 | default:
166 | EmptyView()
167 | }
168 | case .UK:
169 | switch selectedLayer {
170 | case 0:
171 | BuiltInKeyboardLayerView_UK(selectedKeyboardKey: $selectedKeyboardKey, keySize: keySize, layer: preset.layer0)
172 | case 1:
173 | BuiltInKeyboardLayerView_UK(selectedKeyboardKey: $selectedKeyboardKey, keySize: keySize, layer: preset.layer1)
174 | case 2:
175 | BuiltInKeyboardLayerView_UK(selectedKeyboardKey: $selectedKeyboardKey, keySize: keySize, layer: preset.layer2)
176 | case 3:
177 | BuiltInKeyboardLayerView_UK(selectedKeyboardKey: $selectedKeyboardKey, keySize: keySize, layer: preset.layer3)
178 | case 4:
179 | BuiltInKeyboardLayerView_UK(selectedKeyboardKey: $selectedKeyboardKey, keySize: keySize, layer: preset.layer4)
180 | case 5:
181 | BuiltInKeyboardLayerView_UK(selectedKeyboardKey: $selectedKeyboardKey, keySize: keySize, layer: preset.layer5)
182 | case 6:
183 | BuiltInKeyboardLayerView_UK(selectedKeyboardKey: $selectedKeyboardKey, keySize: keySize, layer: preset.layer6)
184 | case 7:
185 | BuiltInKeyboardLayerView_UK(selectedKeyboardKey: $selectedKeyboardKey, keySize: keySize, layer: preset.layer7)
186 | case 8:
187 | BuiltInKeyboardLayerView_UK(selectedKeyboardKey: $selectedKeyboardKey, keySize: keySize, layer: preset.layer8)
188 |
189 | default:
190 | EmptyView()
191 | }
192 | case .JIS:
193 | switch selectedLayer {
194 | case 0:
195 | BuiltInKeyboardLayerView_JIS(selectedKeyboardKey: $selectedKeyboardKey, keySize: keySize, layer: preset.layer0)
196 | case 1:
197 | BuiltInKeyboardLayerView_JIS(selectedKeyboardKey: $selectedKeyboardKey, keySize: keySize, layer: preset.layer1)
198 | case 2:
199 | BuiltInKeyboardLayerView_JIS(selectedKeyboardKey: $selectedKeyboardKey, keySize: keySize, layer: preset.layer2)
200 | case 3:
201 | BuiltInKeyboardLayerView_JIS(selectedKeyboardKey: $selectedKeyboardKey, keySize: keySize, layer: preset.layer3)
202 | case 4:
203 | BuiltInKeyboardLayerView_JIS(selectedKeyboardKey: $selectedKeyboardKey, keySize: keySize, layer: preset.layer4)
204 | case 5:
205 | BuiltInKeyboardLayerView_JIS(selectedKeyboardKey: $selectedKeyboardKey, keySize: keySize, layer: preset.layer5)
206 | case 6:
207 | BuiltInKeyboardLayerView_JIS(selectedKeyboardKey: $selectedKeyboardKey, keySize: keySize, layer: preset.layer6)
208 | case 7:
209 | BuiltInKeyboardLayerView_JIS(selectedKeyboardKey: $selectedKeyboardKey, keySize: keySize, layer: preset.layer7)
210 | case 8:
211 | BuiltInKeyboardLayerView_JIS(selectedKeyboardKey: $selectedKeyboardKey, keySize: keySize, layer: preset.layer8)
212 | default:
213 | EmptyView()
214 | }
215 | }
216 | }
217 | .padding(keySize * 0.035)
218 | .background(.gray.opacity(0.5))
219 | .cornerRadius(keySize * 0.14 + keySize * 0.035)
220 | .padding()
221 |
222 | }
223 | }
224 | // タブのインデックスに応じたレイヤーの色を取得
225 | private func colorForTab(index: Int) -> LayerColor {
226 | switch index {
227 | case 1:
228 | return .layer1
229 | case 2:
230 | return .layer2
231 | case 3:
232 | return .layer3
233 | case 4:
234 | return .layer4
235 | case 5:
236 | return .layer5
237 | case 6:
238 | return .layer6
239 | case 7:
240 | return .layer7
241 | case 8:
242 | return .layer8
243 | default:
244 | return .layer0
245 | }
246 | }
247 | }
248 |
249 | struct ParallelogramShape: Shape {
250 | func path(in rect: CGRect) -> Path {
251 | var path = Path()
252 |
253 | let skewAmount: CGFloat = rect.maxX * 0.15
254 |
255 | path.move(to: CGPoint(x: skewAmount, y: rect.minY))//左上から時計まわりに
256 | path.addLine(to: CGPoint(x: rect.maxX, y: rect.minY))
257 | path.addLine(to: CGPoint(x: rect.maxX - skewAmount, y: rect.maxY))
258 | path.addLine(to: CGPoint(x: rect.minX, y: rect.maxY))
259 | path.addLine(to: CGPoint(x: skewAmount, y: rect.minY))
260 |
261 | return path
262 | }
263 | }
264 | struct ParallelogramButtonStyle: ButtonStyle {
265 | let isSelected: Bool
266 | let tabIndex: Int
267 |
268 | func makeBody(configuration: Configuration) -> some View {
269 | configuration.label
270 | .foregroundColor(.white)
271 | .background(
272 | ParallelogramShape()
273 | .fill(backgroundColor(isSelected: isSelected,
274 | tabIndex: tabIndex,
275 | isPressed: configuration.isPressed))
276 | )
277 | .scaleEffect(configuration.isPressed ? 0.90 : 1.0)
278 | // .animation(.bouncy, value: configuration.isPressed)
279 | }
280 |
281 | // 背景色を決定する関数
282 | private func backgroundColor(isSelected: Bool, tabIndex: Int, isPressed: Bool) -> Color {
283 | if isSelected {
284 | if tabIndex == 0 {
285 | return .black
286 | } else {
287 | return LayerColor.fromIndex(tabIndex).buttonAndHighLightColor
288 | }
289 | } else {
290 | return isPressed ? Color(red: 80/255, green: 80/255, blue: 88/255/*, opacity: 0.4*/) : Color(red: 96/255, green: 96/255, blue: 104/255)
291 | }
292 | }
293 | }
294 |
295 | enum LayerColor {
296 | case layer0
297 | case layer1
298 | case layer2
299 | case layer3
300 | case layer4
301 | case layer5
302 | case layer6
303 | case layer7
304 | case layer8
305 |
306 | var buttonAndHighLightColor: Color {
307 | switch self {
308 | case .layer0:
309 | return .primary
310 | case .layer1:
311 | return .orange
312 | case .layer2:
313 | return .green
314 | case .layer3:
315 | return .purple
316 | case .layer4:
317 | return .blue
318 | case.layer5:
319 | return .yellow
320 | case .layer6:
321 | return .red
322 | case.layer7:
323 | return .cyan
324 | case .layer8:
325 | return .indigo
326 |
327 | }
328 | }
329 | var textColor: Color {
330 | switch self {
331 | case .layer0:
332 | return .white
333 | case .layer1:
334 | return .orange
335 | case .layer2:
336 | return .green
337 | case .layer3:
338 | return .purple
339 | case .layer4:
340 | return .blue
341 | case.layer5:
342 | return .yellow
343 | case .layer6:
344 | return .red
345 | case.layer7:
346 | return .cyan
347 | case .layer8:
348 | return .indigo
349 | }
350 | }
351 | var textColor_export: Color {
352 | switch self {
353 | case .layer0:
354 | return .gray
355 | case .layer1:
356 | return .orange
357 | case .layer2:
358 | return .green
359 | case .layer3:
360 | return .purple
361 | case .layer4:
362 | return .blue
363 | case.layer5:
364 | return .yellow
365 | case .layer6:
366 | return .red
367 | case.layer7:
368 | return .cyan
369 | case .layer8:
370 | return .indigo
371 | }
372 | }
373 | var customizeKeyBackGroundColor: Color {
374 | switch self {
375 | case .layer0:
376 | return .black
377 | case .layer1:
378 | return .orange
379 | case .layer2:
380 | return .green
381 | case .layer3:
382 | return .purple
383 | case .layer4:
384 | return .blue
385 | case.layer5:
386 | return .yellow
387 | case .layer6:
388 | return .red
389 | case.layer7:
390 | return .cyan
391 | case .layer8:
392 | return .indigo
393 | }
394 | }
395 |
396 | static func fromIndex(_ index: Int) -> LayerColor {
397 | switch index {
398 | case 1:
399 | return .layer1
400 | case 2:
401 | return .layer2
402 | case 3:
403 | return .layer3
404 | case 4:
405 | return .layer4
406 | case 5:
407 | return .layer5
408 | case 6:
409 | return .layer6
410 | case 7:
411 | return .layer7
412 | case 8:
413 | return .layer8
414 | default:
415 | return .layer0
416 | }
417 | }
418 | }
419 | //#Preview {
420 | // KeyboardView()
421 | //}
422 |
--------------------------------------------------------------------------------
/Stapler-mini-v0/Stapler-mini-v0/Keyboard/SelectedDetailView.swift:
--------------------------------------------------------------------------------
1 | ///右側サイドバー(Inspector)の
2 | ///選択したKeyboardKeyの詳細な情報を表示するビュー
3 | ///
4 | import SwiftUI
5 |
6 | struct SelectedDetailView: View {
7 |
8 | @Binding var selectedKeyboardKey: KeyboardKey
9 | let selectedPreset: Preset?
10 | @FocusState private var isFocused_customJSON: Bool
11 | @FocusState private var isFocused_tapDisplaySymbol: Bool
12 | @FocusState private var isFocused_holdDisplaySymbol: Bool
13 |
14 | private var highLightColor_tap: Color { //レイヤー移動のキーが入ってる時の色
15 | LayerColor.fromIndex(selectedKeyboardKey.layerKeyNumber_tap).buttonAndHighLightColor
16 | }
17 | private var highLightColor_hold: Color { //レイヤー移動のキーが入ってる時の色
18 | LayerColor.fromIndex(selectedKeyboardKey.layerKeyNumber_hold).buttonAndHighLightColor
19 | }
20 | private var textColor: Color { //レイヤーに応じて色を変化
21 | LayerColor.fromIndex(selectedKeyboardKey.layerNumber).textColor
22 | }
23 | var body: some View {
24 | ZStack {
25 | Color.clear
26 | .contentShape(Rectangle())
27 | .frame(maxWidth: .infinity, maxHeight: .infinity) // 画面全体をカバー
28 | .onTapGesture {
29 | isFocused_customJSON = false
30 | isFocused_tapDisplaySymbol = false
31 | isFocused_holdDisplaySymbol = false
32 | }
33 | if selectedKeyboardKey.isInitial {
34 | initialKeyboardKeyView
35 | } else {
36 | VStack {
37 | if !selectedKeyboardKey.isTapHoldEnabled {
38 | tapView
39 | } else {
40 | tapHoldView
41 | }
42 | Toggle(isOn: $selectedKeyboardKey.userCustomJSONEnabled) {Text("User Custom JSON")}
43 | // .help("When the toggle is on, a JSON is generated including the text from the text field, ignoring other states.")
44 | .toggleStyle(.switch)
45 | .onChange(of: selectedKeyboardKey.userCustomJSONEnabled, initial: false) {oldValue, newValue in
46 | if newValue {//トグルがオンになった時、KeyboardKeyひとつ分のJSONを返すようにする
47 | let exporter = JSONExporter()
48 | do {
49 | if let jsonContent = try exporter.exportKeyboardKey_userCustomJSON(
50 | selectedKeyboardKey,
51 | keyCodeRegion: selectedPreset?.keyCodeRegion ?? .ansi,
52 | vendorID: selectedPreset?.vendorID ?? "1452",
53 | productID: selectedPreset?.productID ?? "635"
54 | ) {
55 | selectedKeyboardKey.userCustomJSONContent = jsonContent
56 | } else {
57 | // JSONが生成されなかった場合(例:カスタマイズされていない場合)
58 | selectedKeyboardKey.userCustomJSONContent = "There is no customization."
59 | }
60 | } catch {
61 | // エラーが発生した場合の処理
62 | print("Error generating JSON: \(error)")
63 | selectedKeyboardKey.userCustomJSONContent = "Error: Unable to generate JSON"
64 |
65 | // オプション:ユーザーにエラーを通知
66 | // showErrorAlert(message: "Failed to generate JSON. Please try again.")
67 | }
68 | }
69 | if !newValue {//トグルがオフになった時
70 |
71 | isFocused_customJSON = false
72 | }
73 | }
74 | TextEditor(text: $selectedKeyboardKey.userCustomJSONContent)
75 | .disabled(!selectedKeyboardKey.userCustomJSONEnabled)
76 | .focused($isFocused_customJSON)
77 | .foregroundColor(selectedKeyboardKey.userCustomJSONEnabled ? .primary : .gray)
78 | }
79 | .padding()
80 | }
81 | }
82 |
83 | }
84 | private var initialKeyboardKeyView: some View {
85 | VStack {
86 | Text("Select any key on the keyboard view.")
87 | .font(.headline)
88 | .foregroundColor(.secondary)
89 | .padding()
90 | }
91 | }
92 | private func modifierFontSize_tap() -> CGFloat {
93 | var activeModifierCount = 0
94 | if selectedKeyboardKey.tapWithShift { activeModifierCount += 1 }
95 | if selectedKeyboardKey.tapWithControl { activeModifierCount += 1 }
96 | if selectedKeyboardKey.tapWithCommand { activeModifierCount += 1 }
97 | if selectedKeyboardKey.tapWithOption { activeModifierCount += 1 }
98 | if selectedKeyboardKey.tapWithFn { activeModifierCount += 1 }
99 |
100 | switch activeModifierCount {
101 | case 0:
102 | return 15
103 | case 1:
104 | return 15
105 | case 2:
106 | return 10
107 | default:
108 | return 6
109 | }
110 |
111 | }
112 | private func modifierFontSize_hold() -> CGFloat {
113 | var activeModifierCount = 0
114 | if selectedKeyboardKey.holdWithShift { activeModifierCount += 1 }
115 | if selectedKeyboardKey.holdWithControl { activeModifierCount += 1 }
116 | if selectedKeyboardKey.holdWithCommand { activeModifierCount += 1 }
117 | if selectedKeyboardKey.holdWithOption { activeModifierCount += 1 }
118 | if selectedKeyboardKey.holdWithFn { activeModifierCount += 1 }
119 |
120 | switch activeModifierCount {
121 | case 0:
122 | return 15
123 | case 1:
124 | return 15
125 | case 2:
126 | return 10
127 | default:
128 | return 6
129 | }
130 |
131 | }
132 | private var modifierContent_tap: some View {
133 | VStack(spacing: 0) {
134 | if selectedKeyboardKey.tapWithModifier {
135 | Spacer()
136 | HStack(spacing: 0) {
137 | if selectedKeyboardKey.tapWithShift {
138 | Image(systemName: "shift")
139 | }
140 | if selectedKeyboardKey.tapWithControl {
141 | Image(systemName: "control")
142 | }
143 | }
144 | HStack(spacing: 0) {
145 | if selectedKeyboardKey.tapWithCommand {
146 | Image(systemName: "command")
147 | }
148 | if selectedKeyboardKey.tapWithOption {
149 | Image(systemName: "option")
150 | }
151 | }
152 | if selectedKeyboardKey.tapWithFn {
153 | Image(systemName: "globe")
154 | }
155 | Spacer()
156 | } else {
157 | EmptyView()
158 | }
159 | }
160 | .font(.system(size: modifierFontSize_tap()))
161 | }
162 | private var modifierContent_hold: some View {
163 | VStack(spacing: 0) {
164 | if selectedKeyboardKey.holdWithModifier {
165 | Spacer()
166 | HStack(spacing: 0) {
167 | if selectedKeyboardKey.holdWithShift {
168 | Image(systemName: "shift")
169 | }
170 | if selectedKeyboardKey.holdWithControl {
171 | Image(systemName: "control")
172 | }
173 | }
174 | HStack(spacing: 0) {
175 | if selectedKeyboardKey.holdWithCommand {
176 | Image(systemName: "command")
177 | }
178 | if selectedKeyboardKey.holdWithOption {
179 | Image(systemName: "option")
180 | }
181 | }
182 | if selectedKeyboardKey.holdWithFn {
183 | Image(systemName: "globe")
184 | }
185 | Spacer()
186 | } else {
187 | EmptyView()
188 | }
189 | }
190 | .font(.system(size: modifierFontSize_hold()))
191 | }
192 |
193 | private var tapView: some View {
194 | VStack {
195 | Text("Tap Key").font(.caption)
196 | if selectedKeyboardKey.afterKeyOutPut != "" {
197 | HStack(spacing: 0) {
198 | if selectedKeyboardKey.layerKeyNumber_tap > 0 {
199 | // modifierContent_tap.foregroundStyle(highLightColor)
200 | symbolOrText(selectedKeyboardKey.afterDisplaySymbol, isSymbol: selectedKeyboardKey.isAfterTapSFSymbol, size: 20, color: highLightColor_tap)
201 | } else {
202 | modifierContent_tap.foregroundStyle(textColor)
203 | symbolOrText(selectedKeyboardKey.afterDisplaySymbol, isSymbol: selectedKeyboardKey.isAfterTapSFSymbol, size: 20, color: textColor)
204 | }
205 | }
206 | .frame(width: 65, height: 65)
207 | .background(.black)
208 | .cornerRadius(65 * 0.07)
209 | .dropDestination(for: CustomizeKey.self) { items, location in
210 | guard let item = items.first else { return false }
211 | selectedKeyboardKey.applyTapKeyCustomization(from: item)
212 | return true
213 | }
214 | } else {
215 | Text("Drop here")
216 | .font(.caption)
217 | .foregroundColor(.white)
218 | .frame(width: 65, height: 65)
219 | .background(.black)
220 | .cornerRadius(65 * 0.07)
221 | .dropDestination(for: CustomizeKey.self) { items, location in
222 | guard let item = items.first else { return false }
223 | selectedKeyboardKey.applyTapKeyCustomization(from: item)
224 | return true
225 | }
226 | }
227 | HStack {
228 | Spacer()
229 | Text("Enable Tap Hold")
230 | Spacer()
231 | Toggle(isOn: $selectedKeyboardKey.isTapHoldEnabled) {Text("")}.toggleStyle(.switch)
232 | Spacer()
233 | }
234 |
235 | Toggle(isOn: $selectedKeyboardKey.tapWithModifier) { Text("Tap with Modifier")}.toggleStyle(.button)
236 | HStack {
237 | Toggle("⇧",isOn: $selectedKeyboardKey.tapWithShift)
238 | .toggleStyle(.button)
239 | .disabled(!selectedKeyboardKey.tapWithModifier || selectedKeyboardKey.isTapIncludeShift)
240 | Toggle("^",isOn: $selectedKeyboardKey.tapWithControl)
241 | .toggleStyle(.button)
242 | .disabled(!selectedKeyboardKey.tapWithModifier || selectedKeyboardKey.isTapIncludeControl)
243 | }
244 | HStack {
245 | Toggle("⌘",isOn: $selectedKeyboardKey.tapWithCommand)
246 | .toggleStyle(.button)
247 | .disabled(!selectedKeyboardKey.tapWithModifier || selectedKeyboardKey.isTapIncludeCommand)
248 | Toggle("⌥",isOn: $selectedKeyboardKey.tapWithOption)
249 | .toggleStyle(.button)
250 | .disabled(!selectedKeyboardKey.tapWithModifier || selectedKeyboardKey.isTapIncludeOption)
251 | }
252 | Toggle("fn", isOn: $selectedKeyboardKey.tapWithFn)
253 | .toggleStyle(.button)
254 | .disabled(!selectedKeyboardKey.tapWithModifier || selectedKeyboardKey.isTapIncludeFn)
255 |
256 | Toggle("SFSymbol", isOn: $selectedKeyboardKey.isAfterTapSFSymbol)
257 | .toggleStyle(.checkbox)
258 | TextField(selectedKeyboardKey.isAfterTapSFSymbol ? "SymbolName:" : "DisplayName:", text: $selectedKeyboardKey.afterDisplaySymbol)
259 | .focused($isFocused_tapDisplaySymbol)
260 | .disabled(!selectedKeyboardKey.isCustomized)
261 | Text("keycode: \(selectedKeyboardKey.beforeKeyOutPut) → \(selectedKeyboardKey.afterKeyOutPut)")
262 | .font(.caption2)
263 |
264 | }
265 | }
266 | private var tapHoldView: some View {
267 | VStack {
268 | HStack {
269 | Spacer()
270 | VStack {
271 | Text("Tap Key").font(.caption)
272 | ZStack {
273 | if selectedKeyboardKey.afterKeyOutPut != "" { //すでに何かしらドロップされたあとの表示
274 | HStack {
275 | if selectedKeyboardKey.layerKeyNumber_tap > 0 { //holdにレイヤー移動キーが入ってる場合の表示
276 | // modifierContent_tap.foregroundStyle(highLightColor)
277 | symbolOrText(selectedKeyboardKey.afterDisplaySymbol, isSymbol: selectedKeyboardKey.isAfterTapSFSymbol, size: 20, color: highLightColor_tap)
278 | } else {
279 | modifierContent_tap.foregroundStyle(textColor)
280 | symbolOrText(selectedKeyboardKey.afterDisplaySymbol, isSymbol: selectedKeyboardKey.isAfterTapSFSymbol, size: 20, color: textColor)
281 | }
282 | }
283 | } else { //まだドロップされていない状態の時の表示
284 | Text("Drop here")
285 | .font(.caption2)
286 | .foregroundColor(.white)
287 | }
288 | }
289 | .frame(width: 65, height: 65)
290 | .background(.black)
291 | .cornerRadius(65 * 0.07)
292 | .dropDestination(for: CustomizeKey.self) { items, location in
293 | guard let item = items.first else { return false }
294 | selectedKeyboardKey.applyTapKeyCustomization(from: item)
295 | return true
296 | }
297 | }
298 | Spacer()
299 | VStack {
300 | Text("Hold Key").font(.caption)
301 | ZStack {
302 | if selectedKeyboardKey.holdKeyOutPut != "" {
303 | HStack(spacing: 0) {
304 | if selectedKeyboardKey.layerKeyNumber_hold > 0 {
305 | // modifierContent_hold.foregroundStyle(highLightColor_hold)
306 | symbolOrText(selectedKeyboardKey.holdDisplaySymbol, isSymbol: selectedKeyboardKey.isAfterHoldSFSymbol, size: 20, color: highLightColor_hold)
307 | } else {
308 | modifierContent_hold.foregroundStyle(textColor)
309 | symbolOrText(selectedKeyboardKey.holdDisplaySymbol, isSymbol: selectedKeyboardKey.isAfterHoldSFSymbol, size: 20, color: textColor)
310 | }
311 | }
312 | } else {
313 | Text("Drop here")
314 | .font(.caption2)
315 | .foregroundColor(.white)
316 | }
317 | }
318 | .frame(width: 65, height: 65)
319 | .background(.black)
320 | .cornerRadius(65 * 0.07)
321 | .dropDestination(for: CustomizeKey.self) { items, location in
322 | guard let item = items.first else { return false }
323 | selectedKeyboardKey.applyHoldKeyCustomization(from: item)
324 | return true
325 | }
326 | }
327 | Spacer()
328 | }
329 | HStack {
330 | Spacer()
331 | Text("Tap Hold")
332 | Spacer()
333 | Toggle(isOn: $selectedKeyboardKey.isTapHoldEnabled) {Text("")}.toggleStyle(.switch)
334 | Spacer()
335 | }
336 | Picker("", selection: $selectedKeyboardKey.tapHoldType) {
337 | ForEach(TapHoldType.allCases, id: \.self) { type in
338 | Text(type.rawValue.capitalized).tag(type)
339 | }
340 | }
341 | .pickerStyle(SegmentedPickerStyle())
342 | VStack {
343 | Text("Tap Hold Threshold: \(Int(selectedKeyboardKey.tapHoldThreshold)) ms")
344 | Slider(value: $selectedKeyboardKey.tapHoldThreshold, in: 40...500, step: 20)
345 | .disabled(selectedKeyboardKey.tapHoldType != .basic)
346 | .onChange(of: selectedKeyboardKey.tapHoldThreshold) {oldValue, newValue in
347 | // ハプティックフィードバックを発生させる
348 | //レスポンスが終わってるけど、他のビューが重いから?コメントアウトしても良い気がするな
349 | NSHapticFeedbackManager.defaultPerformer.perform(.alignment , performanceTime: .now)
350 | }
351 | .padding(.horizontal)
352 | }
353 | HStack {
354 | VStack {
355 | Toggle("Tap with Modifier", isOn: $selectedKeyboardKey.tapWithModifier)
356 | .toggleStyle(.button)
357 |
358 | //Tap
359 | HStack {
360 | Toggle("⇧",isOn: $selectedKeyboardKey.tapWithShift)
361 | .toggleStyle(.button)
362 | .disabled(!selectedKeyboardKey.tapWithModifier || selectedKeyboardKey.isTapIncludeShift)
363 | Toggle("^",isOn: $selectedKeyboardKey.tapWithControl)
364 | .toggleStyle(.button)
365 | .disabled(!selectedKeyboardKey.tapWithModifier || selectedKeyboardKey.isTapIncludeControl)
366 | }
367 | HStack {
368 | Toggle("⌘",isOn: $selectedKeyboardKey.tapWithCommand)
369 | .toggleStyle(.button)
370 | .disabled(!selectedKeyboardKey.tapWithModifier || selectedKeyboardKey.isTapIncludeCommand)
371 | Toggle("⌥",isOn: $selectedKeyboardKey.tapWithOption)
372 | .toggleStyle(.button)
373 | .disabled(!selectedKeyboardKey.tapWithModifier || selectedKeyboardKey.isTapIncludeOption)
374 | }
375 | Toggle("fn", isOn: $selectedKeyboardKey.tapWithFn)
376 | .toggleStyle(.button)
377 | .disabled(!selectedKeyboardKey.tapWithModifier || selectedKeyboardKey.isTapIncludeFn)
378 | }
379 | Divider().frame(height: 100)
380 | VStack {
381 | Toggle("Hold with Modifier", isOn: $selectedKeyboardKey.holdWithModifier)
382 | .toggleStyle(.button)
383 |
384 | //Hold
385 | HStack {
386 | Toggle("⇧",isOn: $selectedKeyboardKey.holdWithShift)
387 | .toggleStyle(.button)
388 | .disabled(!selectedKeyboardKey.holdWithModifier || selectedKeyboardKey.isHoldIncludeShift)
389 | Toggle("^",isOn: $selectedKeyboardKey.holdWithControl)
390 | .toggleStyle(.button)
391 | .disabled(!selectedKeyboardKey.holdWithModifier || selectedKeyboardKey.isHoldIncludeControl)
392 | }
393 | HStack {
394 | Toggle("⌘",isOn: $selectedKeyboardKey.holdWithCommand)
395 | .toggleStyle(.button)
396 | .disabled(!selectedKeyboardKey.holdWithModifier || selectedKeyboardKey.isHoldIncludeCommand)
397 | Toggle("⌥",isOn: $selectedKeyboardKey.holdWithOption)
398 | .toggleStyle(.button)
399 | .disabled(!selectedKeyboardKey.holdWithModifier || selectedKeyboardKey.isHoldIncludeOption)
400 | }
401 | Toggle("fn", isOn: $selectedKeyboardKey.holdWithFn)
402 | .toggleStyle(.button)
403 | .disabled(!selectedKeyboardKey.holdWithModifier || selectedKeyboardKey.isHoldIncludeFn)
404 | }
405 | }
406 | HStack {
407 | VStack {
408 | Toggle("SFSymbol", isOn: $selectedKeyboardKey.isAfterTapSFSymbol)
409 | .toggleStyle(.checkbox)
410 | TextField(selectedKeyboardKey.isAfterTapSFSymbol ? "SymbolName:": "DisplayName", text: $selectedKeyboardKey.afterDisplaySymbol)
411 | .focused($isFocused_tapDisplaySymbol)
412 | .disabled(!selectedKeyboardKey.isCustomized)
413 | Text("Tap \(selectedKeyboardKey.beforeKeyOutPut) → \(selectedKeyboardKey.afterKeyOutPut)")
414 | .font(.caption2)
415 | }
416 | VStack {
417 | Toggle("SFSymbol", isOn: $selectedKeyboardKey.isAfterHoldSFSymbol)
418 | .toggleStyle(.checkbox)
419 | TextField(selectedKeyboardKey.isAfterHoldSFSymbol ? "SymbolName:": "DisplayName", text: $selectedKeyboardKey.holdDisplaySymbol)
420 | .focused($isFocused_holdDisplaySymbol)
421 | .disabled(!selectedKeyboardKey.isCustomized)
422 | Text("Hold \(selectedKeyboardKey.beforeKeyOutPut) → \(selectedKeyboardKey.holdKeyOutPut)")
423 | .font(.caption2)
424 | }
425 | }
426 | }
427 | }
428 | private func symbolOrText(_ content: String, isSymbol: Bool, size: CGFloat, color: Color) -> some View {
429 | Group {
430 | if isSymbol {
431 | Image(systemName: content)
432 | .font(.system(size: size))
433 | } else {
434 | Text(content)
435 | .font(.system(size: size))
436 | }
437 | }
438 | .foregroundColor(color)
439 | }
440 | }
441 |
442 | struct SelectedDetailView_PopOver: View {
443 | @Binding var selectedKeyboardKey: KeyboardKey
444 | private var highLightColor_tap: Color { //レイヤー移動のキーが入ってる時の色
445 | LayerColor.fromIndex(selectedKeyboardKey.layerKeyNumber_tap).buttonAndHighLightColor
446 | }
447 | private var highLightColor_hold: Color { //レイヤー移動のキーが入ってる時の色
448 | LayerColor.fromIndex(selectedKeyboardKey.layerKeyNumber_hold).buttonAndHighLightColor
449 | }
450 | private var textColor: Color { //レイヤーに応じて色を変化
451 | LayerColor.fromIndex(selectedKeyboardKey.layerNumber).textColor
452 | }
453 |
454 | var body: some View {
455 | VStack {
456 | if !selectedKeyboardKey.isTapHoldEnabled {
457 | tapView
458 | } else {
459 | tapHoldView
460 | }
461 | }
462 | .padding()
463 | .frame(width: 300)
464 | .padding()
465 | }
466 | private func modifierFontSize_tap() -> CGFloat {
467 | var activeModifierCount = 0
468 | if selectedKeyboardKey.tapWithShift { activeModifierCount += 1 }
469 | if selectedKeyboardKey.tapWithControl { activeModifierCount += 1 }
470 | if selectedKeyboardKey.tapWithCommand { activeModifierCount += 1 }
471 | if selectedKeyboardKey.tapWithOption { activeModifierCount += 1 }
472 | if selectedKeyboardKey.tapWithFn { activeModifierCount += 1 }
473 |
474 | switch activeModifierCount {
475 | case 0:
476 | return 15
477 | case 1:
478 | return 15
479 | case 2:
480 | return 10
481 | default:
482 | return 6
483 | }
484 | }
485 | private func modifierFontSize_hold() -> CGFloat {
486 | var activeModifierCount = 0
487 | if selectedKeyboardKey.holdWithShift { activeModifierCount += 1 }
488 | if selectedKeyboardKey.holdWithControl { activeModifierCount += 1 }
489 | if selectedKeyboardKey.holdWithCommand { activeModifierCount += 1 }
490 | if selectedKeyboardKey.holdWithOption { activeModifierCount += 1 }
491 | if selectedKeyboardKey.holdWithFn { activeModifierCount += 1 }
492 |
493 | switch activeModifierCount {
494 | case 0:
495 | return 15
496 | case 1:
497 | return 15
498 | case 2:
499 | return 10
500 | default:
501 | return 6
502 | }
503 | }
504 |
505 | private var modifierContent_tap: some View {
506 | VStack(spacing: 0) {
507 | if selectedKeyboardKey.tapWithModifier {
508 | Spacer()
509 | HStack(spacing: 0) {
510 | if selectedKeyboardKey.tapWithShift {
511 | Image(systemName: "shift")
512 | }
513 | if selectedKeyboardKey.tapWithControl {
514 | Image(systemName: "control")
515 | }
516 | }
517 | HStack(spacing: 0) {
518 | if selectedKeyboardKey.tapWithCommand {
519 | Image(systemName: "command")
520 | }
521 | if selectedKeyboardKey.tapWithOption {
522 | Image(systemName: "option")
523 | }
524 | }
525 | if selectedKeyboardKey.tapWithFn {
526 | Image(systemName: "globe")
527 | }
528 | Spacer()
529 | } else {
530 | EmptyView()
531 | }
532 | }
533 | .font(.system(size: modifierFontSize_tap()))
534 | }
535 | private var modifierContent_hold: some View {
536 | VStack(spacing: 0) {
537 | if selectedKeyboardKey.holdWithModifier {
538 | Spacer()
539 | HStack(spacing: 0) {
540 | if selectedKeyboardKey.holdWithShift {
541 | Image(systemName: "shift")
542 | }
543 | if selectedKeyboardKey.holdWithControl {
544 | Image(systemName: "control")
545 | }
546 | }
547 | HStack(spacing: 0) {
548 | if selectedKeyboardKey.holdWithCommand {
549 | Image(systemName: "command")
550 | }
551 | if selectedKeyboardKey.holdWithOption {
552 | Image(systemName: "option")
553 | }
554 | }
555 | if selectedKeyboardKey.holdWithFn {
556 | Image(systemName: "globe")
557 | }
558 | Spacer()
559 | } else {
560 | EmptyView()
561 | }
562 | }
563 | .font(.system(size: modifierFontSize_hold()))
564 | }
565 |
566 | private var tapView: some View {
567 | VStack {
568 | Text("Tap Key").font(.caption)
569 | HStack(spacing: 0) {
570 | if selectedKeyboardKey.afterKeyOutPut != "" {
571 | if selectedKeyboardKey.layerKeyNumber_tap > 0 {
572 | // modifierContent_tap.foregroundStyle(highLightColor_tap)
573 | symbolOrText(selectedKeyboardKey.afterDisplaySymbol, isSymbol: selectedKeyboardKey.isAfterTapSFSymbol, size: 20, color: highLightColor_tap)
574 | } else {
575 | modifierContent_tap.foregroundStyle(textColor)
576 | symbolOrText(selectedKeyboardKey.afterDisplaySymbol, isSymbol: selectedKeyboardKey.isAfterTapSFSymbol, size: 20, color: textColor)
577 | }
578 |
579 | } else {
580 | Text("Drop here")
581 | .font(.caption)
582 | .foregroundColor(.white)
583 |
584 | }
585 | }
586 | .frame(width: 65, height: 65)
587 | .background(.black)
588 | .cornerRadius(65 * 0.07)
589 | .dropDestination(for: CustomizeKey.self) { items, location in
590 | guard let item = items.first else { return false }
591 | selectedKeyboardKey.applyTapKeyCustomization(from: item)
592 | return true
593 | }
594 |
595 | HStack {
596 | Spacer()
597 | Text("Enable Tap Hold")
598 | Spacer()
599 | Toggle(isOn: $selectedKeyboardKey.isTapHoldEnabled) {Text("")}.toggleStyle(.switch)
600 | Spacer()
601 | }
602 |
603 | Toggle(isOn: $selectedKeyboardKey.tapWithModifier) { Text("Tap with Modifier")}.toggleStyle(.button)
604 | HStack {
605 | Toggle("⇧",isOn: $selectedKeyboardKey.tapWithShift)
606 | .toggleStyle(.button)
607 | .disabled(!selectedKeyboardKey.tapWithModifier || selectedKeyboardKey.isTapIncludeShift)
608 | Toggle("^",isOn: $selectedKeyboardKey.tapWithControl)
609 | .toggleStyle(.button)
610 | .disabled(!selectedKeyboardKey.tapWithModifier || selectedKeyboardKey.isTapIncludeControl)
611 | }
612 | HStack {
613 | Toggle("⌘",isOn: $selectedKeyboardKey.tapWithCommand)
614 | .toggleStyle(.button)
615 | .disabled(!selectedKeyboardKey.tapWithModifier || selectedKeyboardKey.isTapIncludeCommand)
616 | Toggle("⌥",isOn: $selectedKeyboardKey.tapWithOption)
617 | .toggleStyle(.button)
618 | .disabled(!selectedKeyboardKey.tapWithModifier || selectedKeyboardKey.isTapIncludeOption)
619 | }
620 | Toggle("fn", isOn: $selectedKeyboardKey.tapWithFn)
621 | .toggleStyle(.button)
622 | .disabled(!selectedKeyboardKey.tapWithModifier || selectedKeyboardKey.isTapIncludeFn)
623 |
624 | }
625 | }
626 | private var tapHoldView: some View {
627 | VStack {
628 | HStack {
629 | Spacer()
630 | VStack {
631 | Text("Tap Key").font(.caption)
632 | ZStack {
633 | VStack {
634 | if selectedKeyboardKey.afterKeyOutPut != "" { //すでに何かしらドロップされたあとの表示
635 | HStack(spacing: 0) {
636 | if selectedKeyboardKey.layerKeyNumber_tap > 0 {
637 | // modifierContent_tap.foregroundStyle(highLightColor_tap)
638 | symbolOrText(selectedKeyboardKey.afterDisplaySymbol, isSymbol: selectedKeyboardKey.isAfterTapSFSymbol, size: 20, color: highLightColor_tap)
639 | } else {
640 | modifierContent_tap.foregroundStyle(textColor)
641 | symbolOrText(selectedKeyboardKey.afterDisplaySymbol, isSymbol: selectedKeyboardKey.isAfterTapSFSymbol, size: 20, color: textColor)
642 | }
643 | }
644 | } else { //まだドロップされていない状態の時の表示
645 | Text("Drop here")
646 | .font(.caption2)
647 | .foregroundColor(.white)
648 |
649 | }
650 | }
651 | }
652 | .frame(width: 65, height: 65)
653 | .background(.black)
654 | .cornerRadius(65 * 0.07)
655 | .dropDestination(for: CustomizeKey.self) { items, location in
656 | guard let item = items.first else { return false }
657 | selectedKeyboardKey.applyTapKeyCustomization(from: item)
658 | return true
659 | }
660 | }
661 | Spacer()
662 | VStack {
663 | Text("Hold Key").font(.caption)
664 | ZStack {
665 | VStack {
666 | if selectedKeyboardKey.holdKeyOutPut != "" {
667 | HStack(spacing: 0) {
668 | if selectedKeyboardKey.layerKeyNumber_hold > 0 {
669 | modifierContent_hold.foregroundStyle(highLightColor_hold)
670 | symbolOrText(selectedKeyboardKey.holdDisplaySymbol, isSymbol: selectedKeyboardKey.isAfterHoldSFSymbol, size: 20, color: highLightColor_hold)
671 | } else {
672 | modifierContent_hold.foregroundStyle(textColor)
673 | symbolOrText(selectedKeyboardKey.holdDisplaySymbol, isSymbol: selectedKeyboardKey.isAfterHoldSFSymbol, size: 20, color: textColor)
674 | }
675 | }
676 | } else {
677 | Text("Drop here")
678 | .foregroundColor(.white)
679 | .font(.caption2)
680 | }
681 | }
682 | }
683 | .frame(width: 65, height: 65)
684 | .background(.black)
685 | .cornerRadius(65 * 0.07)
686 | .dropDestination(for: CustomizeKey.self) { items, location in
687 | guard let item = items.first else { return false }
688 | selectedKeyboardKey.applyHoldKeyCustomization(from: item)
689 | return true
690 | }
691 | }
692 | Spacer()
693 | }
694 | HStack {
695 | Spacer()
696 | Text("Enable Tap Hold")
697 | Spacer()
698 | Toggle(isOn: $selectedKeyboardKey.isTapHoldEnabled) {Text("")}.toggleStyle(.switch)
699 | Spacer()
700 | }
701 | HStack {
702 | VStack {
703 | Toggle("Tap with Modifier", isOn: $selectedKeyboardKey.tapWithModifier)
704 | .toggleStyle(.button)
705 |
706 | //Tap
707 | HStack {
708 | Toggle("⇧",isOn: $selectedKeyboardKey.tapWithShift)
709 | .toggleStyle(.button)
710 | .disabled(!selectedKeyboardKey.tapWithModifier || selectedKeyboardKey.isTapIncludeShift)
711 | Toggle("^",isOn: $selectedKeyboardKey.tapWithControl)
712 | .toggleStyle(.button)
713 | .disabled(!selectedKeyboardKey.tapWithModifier || selectedKeyboardKey.isTapIncludeControl)
714 | }
715 | HStack {
716 | Toggle("⌘",isOn: $selectedKeyboardKey.tapWithCommand)
717 | .toggleStyle(.button)
718 | .disabled(!selectedKeyboardKey.tapWithModifier || selectedKeyboardKey.isTapIncludeCommand)
719 | Toggle("⌥",isOn: $selectedKeyboardKey.tapWithOption)
720 | .toggleStyle(.button)
721 | .disabled(!selectedKeyboardKey.tapWithModifier || selectedKeyboardKey.isTapIncludeOption)
722 | }
723 | Toggle("fn", isOn: $selectedKeyboardKey.tapWithFn)
724 | .toggleStyle(.button)
725 | .disabled(!selectedKeyboardKey.tapWithModifier || selectedKeyboardKey.isTapIncludeFn)
726 | }
727 | Divider().frame(height: 100)
728 | VStack {
729 | Toggle("Hold with Modifier", isOn: $selectedKeyboardKey.holdWithModifier)
730 | .toggleStyle(.button)
731 |
732 | //Hold
733 | HStack {
734 | Toggle("⇧",isOn: $selectedKeyboardKey.holdWithShift)
735 | .toggleStyle(.button)
736 | .disabled(!selectedKeyboardKey.holdWithModifier || selectedKeyboardKey.isHoldIncludeShift)
737 | Toggle("^",isOn: $selectedKeyboardKey.holdWithControl)
738 | .toggleStyle(.button)
739 | .disabled(!selectedKeyboardKey.holdWithModifier || selectedKeyboardKey.isHoldIncludeControl)
740 | }
741 | HStack {
742 | Toggle("⌘",isOn: $selectedKeyboardKey.holdWithCommand)
743 | .toggleStyle(.button)
744 | .disabled(!selectedKeyboardKey.holdWithModifier || selectedKeyboardKey.isHoldIncludeCommand)
745 | Toggle("⌥",isOn: $selectedKeyboardKey.holdWithOption)
746 | .toggleStyle(.button)
747 | .disabled(!selectedKeyboardKey.holdWithModifier || selectedKeyboardKey.isHoldIncludeOption)
748 | }
749 | Toggle("fn", isOn: $selectedKeyboardKey.holdWithFn)
750 | .toggleStyle(.button)
751 | .disabled(!selectedKeyboardKey.holdWithModifier || selectedKeyboardKey.isHoldIncludeFn)
752 | }
753 | }
754 | }
755 | }
756 | private func symbolOrText(_ content: String, isSymbol: Bool, size: CGFloat, color: Color) -> some View {
757 | Group {
758 | if isSymbol {
759 | Image(systemName: content)
760 | .font(.system(size: size))
761 | } else {
762 | Text(content)
763 | .font(.system(size: size))
764 | }
765 | }
766 | .foregroundColor(color)
767 | }
768 | }
769 |
770 | //#Preview {
771 | // SelectedDetailView()
772 | //}
773 |
--------------------------------------------------------------------------------
/Stapler-mini-v0/Stapler-mini-v0/PresetLabelView.swift:
--------------------------------------------------------------------------------
1 | //Navigation用のラベルビュー。テキストをクリックしたり、右クリしたりしてリネーム、デリートが行えるような感じ。
2 | import SwiftUI
3 |
4 | struct PresetLabelView: View {
5 | let preset: Preset
6 | @Binding var isEditing: Bool
7 | @Binding var selectedPresetID: UUID?
8 | @FocusState.Binding var isFocused: Bool
9 |
10 | var onDelete: () -> Void
11 |
12 | var body: some View {
13 | if isEditing && selectedPresetID == preset.id {
14 | // 1. テキスト編集中のラベル
15 | HStack {
16 | TextField("Preset Name",
17 | text: Binding(
18 | get: { preset.presetName },
19 | set: { newName in
20 | preset.presetName = newName
21 | })
22 | )
23 | .background(.clear)
24 | .focused($isFocused)
25 | .onAppear {
26 | isFocused = true
27 | }
28 | .onSubmit {
29 | isEditing = false
30 | }
31 | }
32 | } else if selectedPresetID == preset.id {
33 | // 2. 選択中の要素のラベル
34 | ZStack {
35 | HStack {
36 | Text(preset.presetName)
37 | .onTapGesture(count: 1) {//テキストをクリックすると編集状態に移行する。
38 | isEditing = true
39 | // print("isEditing is true now!")
40 | }
41 | .contextMenu {
42 | Button("Rename") {
43 | isEditing = true
44 | }
45 | Button("Delete", role: .destructive) {
46 | onDelete()
47 | }.keyboardShortcut(.delete, modifiers: .command)
48 | }
49 | Spacer()
50 | }
51 | HStack(alignment: .bottom) {
52 | Spacer()
53 | Text("\(preset.keyboardLayout)")
54 | .font(.caption2)
55 | .foregroundStyle(.secondary)
56 | }
57 | }
58 | } else {
59 | // 3. 選択されていないラベル
60 | ZStack {
61 | HStack {
62 | Text(preset.presetName)
63 | Spacer()
64 | }
65 | HStack(alignment: .bottom) {
66 | Spacer()
67 | Text("\(preset.keyboardLayout)")
68 | .font(.caption2)
69 | .foregroundStyle(.secondary)
70 | }
71 | }
72 | }
73 |
74 |
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/Stapler-mini-v0/Stapler-mini-v0/Preview Content/Preview Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/Stapler-mini-v0/Stapler-mini-v0/Stapler-mini-v0App.swift:
--------------------------------------------------------------------------------
1 |
2 |
3 | import SwiftUI
4 | import SwiftData
5 |
6 | @main
7 | struct Stapler_mini_v0_App: App {
8 | @NSApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
9 |
10 | init() {
11 | NSWindow.allowsAutomaticWindowTabbing = false
12 | }
13 |
14 | var body: some Scene {
15 | WindowGroup {
16 | ContentView()
17 | .onReceive(NotificationCenter.default.publisher(for: NSApplication.didFinishLaunchingNotification)) { _ in
18 | Task { @MainActor in
19 | guard let modelContainer = try? await prepareModelContainer() else { return }
20 | appDelegate.modelContainer = modelContainer
21 | }
22 | }
23 | }
24 | .modelContainer(for: [Preset.self], isUndoEnabled: true)
25 | .commands {
26 | CommandGroup(replacing: .newItem) {} //File>NewWindow
27 | // Editメニューのカスタマイズ
28 | CommandGroup(replacing: .pasteboard) {} // Edit>Copy Paste...
29 | // CommandGroup(replacing: .textEditing) {} // Edit>AutoFill,Start Dictation, Emoji & Symbolsがわからないが、必要なさそうだから消したい。
30 |
31 |
32 | CommandGroup(replacing: .help) {
33 | Button("アプリの使い方") {
34 | // ヘルプを表示するアクション
35 | NSWorkspace.shared.open(URL(string: "https://note.com/9dpb/n/n471a998bdef8")!)
36 | }
37 | Button("Discordコミュニティで質問する") {
38 | // ヘルプを表示するアクション
39 | NSWorkspace.shared.open(URL(string: "https://discord.gg/yVhZfsE2zS")!)
40 | }
41 | }
42 | }
43 | }
44 |
45 | @MainActor
46 | private func prepareModelContainer() async throws -> ModelContainer {
47 | let schema = Schema([Preset.self])
48 | let modelConfiguration = ModelConfiguration(schema: schema, isStoredInMemoryOnly: false)
49 | return try ModelContainer(for: schema, configurations: [modelConfiguration])
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/Stapler-mini-v0/Stapler-mini-v0/Stapler_mini_v0.entitlements:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | com.apple.security.app-sandbox
6 |
7 | com.apple.security.files.user-selected.read-write
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/Stapler-mini-v0/Stapler-mini-v0/en.lproj/Localizable.strings:
--------------------------------------------------------------------------------
1 | /*
2 | English
3 | */
4 | "selectedDetailView_select" = "Please select any key on the keyboard view.";
5 | "selectedDetailView_enableTapHold" = "Tap Hold";
6 |
7 | "addPresetView_selectLayout" = "Chose keyboard layout";
8 | "addPresetView_cansel" = "Cancel";
9 | "addPresetView_createPreset" = "Create a Preset";
10 |
--------------------------------------------------------------------------------
/Stapler-mini-v0/Stapler-mini-v0/ja.lproj/Localizable.strings:
--------------------------------------------------------------------------------
1 | /*
2 | 日本語
3 | そのうちやります。
4 | */
5 | "selectedDetailView_select" = "キーボードのキーを選択してください。";
6 | "selectedDetailView_enableTapHold" = "Tap Hold";
7 |
8 | "addPresetView_selectLayout" = "キーボードレイアウトを選択してください";
9 | "addPresetView_cansel" = "キャンセル";
10 | "addPresetView_createPreset" = "プリセットを作る";
11 |
--------------------------------------------------------------------------------