WorkingSetの保存と復元をシリアライズからXML形式に変更した。
@@ -0,0 +1,171 @@ | ||
1 | +package charactermanaj.model; | |
2 | + | |
3 | +import java.awt.Color; | |
4 | +import java.io.Serializable; | |
5 | +import java.util.HashMap; | |
6 | +import java.util.List; | |
7 | +import java.util.Map; | |
8 | +import java.util.logging.Level; | |
9 | +import java.util.logging.Logger; | |
10 | + | |
11 | +/** | |
12 | + * 素のパーツセットの情報.<br> | |
13 | + * レイヤーやカテゴリなどのリレーションシップがない、<br> | |
14 | + * 特定のキャラクターデータモデルのツリーの一部には組み込まれていない状態のもの.<br> | |
15 | + */ | |
16 | +public class IndependentPartsSetInfo implements Serializable { | |
17 | + | |
18 | + /** | |
19 | + * シリアライズバージョンID | |
20 | + */ | |
21 | + private static final long serialVersionUID = 7280485045920860407L; | |
22 | + | |
23 | + /** | |
24 | + * ロガー | |
25 | + */ | |
26 | + private static final Logger logger = Logger | |
27 | + .getLogger(IndependentPartsSetInfo.class.getName()); | |
28 | + | |
29 | + /** | |
30 | + * バーツセットのID | |
31 | + */ | |
32 | + private String id; | |
33 | + | |
34 | + /** | |
35 | + * パーツセットの表示名 | |
36 | + */ | |
37 | + private String displayName; | |
38 | + | |
39 | + /** | |
40 | + * 背景色、未設定であればnull | |
41 | + */ | |
42 | + private Color backgroundColor; | |
43 | + | |
44 | + /** | |
45 | + * アフィン変換パラメータ、未設定であればnull | |
46 | + */ | |
47 | + private double[] affineTransformParameter; | |
48 | + | |
49 | + /** | |
50 | + * カテゴリIDをキーとし、パーツ名をキーとしカラー情報のリストを値とするマップを値とする. | |
51 | + */ | |
52 | + private Map<String, Map<String, List<IndependentPartsColorInfo>>> partsMap = new HashMap<String, Map<String, List<IndependentPartsColorInfo>>>(); | |
53 | + | |
54 | + public String getId() { | |
55 | + return id; | |
56 | + } | |
57 | + | |
58 | + public void setId(String id) { | |
59 | + this.id = id; | |
60 | + } | |
61 | + | |
62 | + public String getDisplayName() { | |
63 | + return displayName; | |
64 | + } | |
65 | + | |
66 | + public void setDisplayName(String displayName) { | |
67 | + this.displayName = displayName; | |
68 | + } | |
69 | + | |
70 | + public Color getBackgroundColor() { | |
71 | + return backgroundColor; | |
72 | + } | |
73 | + | |
74 | + public void setBackgroundColor(Color backgroundColor) { | |
75 | + this.backgroundColor = backgroundColor; | |
76 | + } | |
77 | + | |
78 | + public double[] getAffineTransformParameter() { | |
79 | + return affineTransformParameter; | |
80 | + } | |
81 | + | |
82 | + public void setAffineTransformParameter( | |
83 | + double[] affineTransformParameter) { | |
84 | + this.affineTransformParameter = affineTransformParameter; | |
85 | + } | |
86 | + | |
87 | + /** | |
88 | + * カテゴリIDをキーとし、パーツ名をキーとしカラー情報のリストを値とするマップを値とする. | |
89 | + * | |
90 | + * @return カテゴリIDをキーとし、パーツ名をキーとしカラー情報のリストを値とするマップを値とする. | |
91 | + */ | |
92 | + public Map<String, Map<String, List<IndependentPartsColorInfo>>> getPartsMap() { | |
93 | + return partsMap; | |
94 | + } | |
95 | + | |
96 | + public void setPartsMap( | |
97 | + Map<String, Map<String, List<IndependentPartsColorInfo>>> partsMap) { | |
98 | + if (partsMap == null) { | |
99 | + throw new IllegalArgumentException(); | |
100 | + } | |
101 | + this.partsMap = partsMap; | |
102 | + } | |
103 | + | |
104 | + /** | |
105 | + * インスタンス独立のパーツセット情報から、指定されたキャラクターデータに関連づけられた パーツ情報に変換して返す.<br> | |
106 | + * | |
107 | + * @param partsSetInfo | |
108 | + * インスタンス独立のパーツセット情報 | |
109 | + * @param characterData | |
110 | + * キャラクターデータ | |
111 | + * @param presetParts | |
112 | + * プリセットか? | |
113 | + * @return キャラクターデータに関連づけられたパーツセットインスタンス | |
114 | + */ | |
115 | + public static PartsSet convertPartsSet( | |
116 | + IndependentPartsSetInfo partsSetInfo, CharacterData characterData, | |
117 | + boolean presetParts) { | |
118 | + if (partsSetInfo == null || characterData == null) { | |
119 | + throw new IllegalArgumentException(); | |
120 | + } | |
121 | + PartsSet partsSet = new PartsSet(); | |
122 | + partsSet.setPartsSetId(partsSetInfo.getId()); | |
123 | + partsSet.setLocalizedName(partsSetInfo.getDisplayName()); | |
124 | + partsSet.setPresetParts(presetParts); | |
125 | + | |
126 | + Color backgroundColor = partsSetInfo.getBackgroundColor(); | |
127 | + if (backgroundColor != null) { | |
128 | + partsSet.setBgColor(backgroundColor); | |
129 | + } | |
130 | + | |
131 | + double[] affineTrans = partsSetInfo.getAffineTransformParameter(); | |
132 | + if (affineTrans != null) { | |
133 | + partsSet.setAffineTransformParameter(affineTrans); | |
134 | + } | |
135 | + | |
136 | + Map<String, Map<String, List<IndependentPartsColorInfo>>> partsMap = partsSetInfo | |
137 | + .getPartsMap(); | |
138 | + for (Map.Entry<String, Map<String, List<IndependentPartsColorInfo>>> categoryEntry : partsMap | |
139 | + .entrySet()) { | |
140 | + String categoryId = categoryEntry.getKey(); | |
141 | + Map<String, List<IndependentPartsColorInfo>> categoryPartsMap = categoryEntry | |
142 | + .getValue(); | |
143 | + | |
144 | + PartsCategory partsCategory = characterData | |
145 | + .getPartsCategory(categoryId); | |
146 | + if (partsCategory == null) { | |
147 | + logger.log(Level.WARNING, "undefined category-id: " | |
148 | + + categoryId); | |
149 | + continue; | |
150 | + } | |
151 | + | |
152 | + for (Map.Entry<String, List<IndependentPartsColorInfo>> partsEntry : categoryPartsMap | |
153 | + .entrySet()) { | |
154 | + String partsName = partsEntry.getKey(); | |
155 | + List<IndependentPartsColorInfo> colorInfoList = partsEntry | |
156 | + .getValue(); | |
157 | + | |
158 | + PartsIdentifier partsIdentifier = new PartsIdentifier( | |
159 | + partsCategory, partsName, partsName); | |
160 | + | |
161 | + PartsColorInfo partsColorInfo = IndependentPartsColorInfo | |
162 | + .buildPartsColorInfo(characterData, partsCategory, | |
163 | + colorInfoList); | |
164 | + | |
165 | + partsSet.appendParts(partsCategory, partsIdentifier, | |
166 | + partsColorInfo); | |
167 | + } | |
168 | + } | |
169 | + return partsSet; | |
170 | + } | |
171 | +} |
@@ -0,0 +1,189 @@ | ||
1 | +package charactermanaj.model; | |
2 | + | |
3 | +import java.io.File; | |
4 | +import java.net.URI; | |
5 | +import java.util.Collections; | |
6 | +import java.util.List; | |
7 | +import java.util.Map; | |
8 | + | |
9 | +import charactermanaj.ui.model.WallpaperInfo; | |
10 | + | |
11 | +/** | |
12 | + * WorkingSetのXMLの読み込み時に使用する.<br> | |
13 | + * 特定のキャラクターデータのインスタンスとの関連を持たない状態の設定値を保持している.<br> | |
14 | + * | |
15 | + * @author seraphy | |
16 | + */ | |
17 | +public class WorkingSet2 { | |
18 | + | |
19 | + /** | |
20 | + * ドキュメントベース | |
21 | + */ | |
22 | + private URI characterDocBase; | |
23 | + | |
24 | + /** | |
25 | + * キャラクターデータのID, Revと基本構造のシグネチャ | |
26 | + */ | |
27 | + private String characterDataSig; | |
28 | + | |
29 | + /** | |
30 | + * キーはカテゴリid, 値は、パーツ名をキーとしレイヤーごとのカラー情報のリストを値とするマップ | |
31 | + */ | |
32 | + private Map<String, Map<String, List<IndependentPartsColorInfo>>> partsColorMap = Collections | |
33 | + .emptyMap(); | |
34 | + | |
35 | + /** | |
36 | + * 現在の選択中のパーツと色設定からのパーツセット | |
37 | + */ | |
38 | + private IndependentPartsSetInfo currentPartsSet; | |
39 | + | |
40 | + /** | |
41 | + * 最後に使用したディレクトリ(保存用) | |
42 | + */ | |
43 | + private File lastUsedSaveDir; | |
44 | + | |
45 | + /** | |
46 | + * 最後に使用したディレクトリ(Export用) | |
47 | + */ | |
48 | + private File lastUsedExportDir; | |
49 | + | |
50 | + /** | |
51 | + * 最後に使用したお気に入り情報.<br> | |
52 | + * (最後に使用したお気に入り情報は、ver0.92からサポート)<br> | |
53 | + */ | |
54 | + private IndependentPartsSetInfo lastUsePresetParts; | |
55 | + | |
56 | + /** | |
57 | + * 壁紙情報.<br> | |
58 | + * (壁紙はver0.97からサポート)<br> | |
59 | + */ | |
60 | + private WallpaperInfo wallpaperInfo; | |
61 | + | |
62 | + public void setCharacterDocBase(URI characterDocBase) { | |
63 | + this.characterDocBase = characterDocBase; | |
64 | + } | |
65 | + | |
66 | + public URI getCharacterDocBase() { | |
67 | + return characterDocBase; | |
68 | + } | |
69 | + | |
70 | + public String getCharacterDataSig() { | |
71 | + return characterDataSig; | |
72 | + } | |
73 | + | |
74 | + public void setCharacterDataSig(String characterDataSig) { | |
75 | + this.characterDataSig = characterDataSig; | |
76 | + } | |
77 | + | |
78 | + /** | |
79 | + * パーツカラーマップ | |
80 | + * | |
81 | + * @return キーはカテゴリid, 値は、パーツ名をキーとしレイヤーごとのカラー情報のリストを値とするマップ | |
82 | + */ | |
83 | + public Map<String, Map<String, List<IndependentPartsColorInfo>>> getPartsColorMap() { | |
84 | + return partsColorMap; | |
85 | + } | |
86 | + | |
87 | + public void setPartsColorMap( | |
88 | + Map<String, Map<String, List<IndependentPartsColorInfo>>> partsColorMap) { | |
89 | + if (partsColorMap == null) { | |
90 | + this.partsColorMap = Collections.emptyMap(); | |
91 | + } | |
92 | + this.partsColorMap = partsColorMap; | |
93 | + } | |
94 | + | |
95 | + public void setLastUsedExportDir(File lastUsedExportDir) { | |
96 | + this.lastUsedExportDir = lastUsedExportDir; | |
97 | + } | |
98 | + | |
99 | + public File getLastUsedExportDir() { | |
100 | + return lastUsedExportDir; | |
101 | + } | |
102 | + | |
103 | + public void setLastUsedSaveDir(File lastUsedSaveDir) { | |
104 | + this.lastUsedSaveDir = lastUsedSaveDir; | |
105 | + } | |
106 | + | |
107 | + public File getLastUsedSaveDir() { | |
108 | + return lastUsedSaveDir; | |
109 | + } | |
110 | + | |
111 | + public void setWallpaperInfo(WallpaperInfo wallpaperInfo) { | |
112 | + this.wallpaperInfo = wallpaperInfo; | |
113 | + } | |
114 | + | |
115 | + public WallpaperInfo getWallpaperInfo() { | |
116 | + return wallpaperInfo; | |
117 | + } | |
118 | + | |
119 | + public IndependentPartsSetInfo getCurrentPartsSet() { | |
120 | + return currentPartsSet; | |
121 | + } | |
122 | + | |
123 | + public void setCurrentPartsSet(IndependentPartsSetInfo currentPartsSet) { | |
124 | + this.currentPartsSet = currentPartsSet; | |
125 | + } | |
126 | + | |
127 | + public IndependentPartsSetInfo getLastUsePresetParts() { | |
128 | + return lastUsePresetParts; | |
129 | + } | |
130 | + | |
131 | + public void setLastUsePresetParts(IndependentPartsSetInfo lastUsePresetParts) { | |
132 | + this.lastUsePresetParts = lastUsePresetParts; | |
133 | + } | |
134 | + | |
135 | + /** | |
136 | + * キャラクターデータを指定して、指定されたキャラクターデータ上のインスタンスと関連づけられた | |
137 | + * カテゴリおよびパーツ名などのインスタンスで構成されるパーツ識別名とカラー情報を、 引数で指定したマップに出力する. | |
138 | + * | |
139 | + * @param characterData | |
140 | + * キャラクターデータ | |
141 | + * @param partsColorInfoMap | |
142 | + * パーツ識別名とカラー情報を出力するマップ | |
143 | + */ | |
144 | + public void createCompatible(CharacterData characterData, | |
145 | + Map<PartsIdentifier, PartsColorInfo> partsColorInfoMap) { | |
146 | + if (characterData == null || partsColorInfoMap == null) { | |
147 | + throw new IllegalArgumentException(); | |
148 | + } | |
149 | + | |
150 | + for (Map.Entry<String, Map<String, List<IndependentPartsColorInfo>>> catEntry : partsColorMap | |
151 | + .entrySet()) { | |
152 | + String categoryId = catEntry.getKey(); | |
153 | + for (Map.Entry<String, List<IndependentPartsColorInfo>> layerEntry : catEntry | |
154 | + .getValue().entrySet()) { | |
155 | + String partsName = layerEntry.getKey(); | |
156 | + List<IndependentPartsColorInfo> partsColorInfos = layerEntry | |
157 | + .getValue(); | |
158 | + | |
159 | + PartsCategory partsCategory = characterData | |
160 | + .getPartsCategory(categoryId); | |
161 | + if (partsCategory != null) { | |
162 | + String localizedName = partsName; | |
163 | + PartsIdentifier partsIdentifier = new PartsIdentifier( | |
164 | + partsCategory, partsName, localizedName); | |
165 | + | |
166 | + PartsColorInfo partsColorInfo = IndependentPartsColorInfo | |
167 | + .buildPartsColorInfo(characterData, partsCategory, | |
168 | + partsColorInfos); | |
169 | + if (partsColorInfo != null) { | |
170 | + partsColorInfoMap.put(partsIdentifier, partsColorInfo); | |
171 | + } | |
172 | + } | |
173 | + } | |
174 | + } | |
175 | + } | |
176 | + | |
177 | + @Override | |
178 | + public String toString() { | |
179 | + StringBuilder buf = new StringBuilder(); | |
180 | + buf.append("(characterDocBase=").append(characterDocBase); | |
181 | + buf.append(", characterDataSig=").append(characterDataSig); | |
182 | + buf.append(", partsColorMap=").append(partsColorMap); | |
183 | + buf.append(", currentPartsSet=").append(currentPartsSet); | |
184 | + buf.append(", lastUsedSaveDir=").append(lastUsedSaveDir); | |
185 | + buf.append(", lastUsedExportDir=").append(lastUsedExportDir); | |
186 | + buf.append(")"); | |
187 | + return buf.toString(); | |
188 | + } | |
189 | +} |
@@ -0,0 +1,128 @@ | ||
1 | +package charactermanaj.model; | |
2 | + | |
3 | +import java.io.Serializable; | |
4 | +import java.util.List; | |
5 | +import java.util.logging.Level; | |
6 | +import java.util.logging.Logger; | |
7 | + | |
8 | +import charactermanaj.graphics.filters.ColorConvertParameter; | |
9 | + | |
10 | +/** | |
11 | + * 素のカラー情報.<br> | |
12 | + * レイヤーやカテゴリなどのリレーションシップがない、<br> | |
13 | + * 特定のキャラクターデータモデルのツリーの一部には組み込まれていない状態のもの.<br> | |
14 | + */ | |
15 | +public class IndependentPartsColorInfo implements Serializable { | |
16 | + | |
17 | + /** | |
18 | + * シリアライズバージョンID | |
19 | + */ | |
20 | + private static final long serialVersionUID = -8114086036157411198L; | |
21 | + | |
22 | + /** | |
23 | + * ロガー | |
24 | + */ | |
25 | + private static final Logger logger = Logger | |
26 | + .getLogger(IndependentPartsColorInfo.class.getName()); | |
27 | + | |
28 | + /** | |
29 | + * layerID | |
30 | + */ | |
31 | + private String layerId; | |
32 | + | |
33 | + /** | |
34 | + * カラーグループのid | |
35 | + */ | |
36 | + private String colorGroupId; | |
37 | + | |
38 | + /** | |
39 | + * カラーの同期指定 | |
40 | + */ | |
41 | + private boolean syncColorGroup; | |
42 | + | |
43 | + /** | |
44 | + * カラー変換パラメータ.<br> | |
45 | + */ | |
46 | + private ColorConvertParameter colorConvertParameter = new ColorConvertParameter(); | |
47 | + | |
48 | + public void setLayerId(String layerId) { | |
49 | + this.layerId = layerId; | |
50 | + } | |
51 | + | |
52 | + public String getLayerId() { | |
53 | + return layerId; | |
54 | + } | |
55 | + | |
56 | + public void setColorGroupId(String colorGroupId) { | |
57 | + this.colorGroupId = colorGroupId; | |
58 | + } | |
59 | + | |
60 | + public String getColorGroupId() { | |
61 | + return colorGroupId; | |
62 | + } | |
63 | + | |
64 | + public void setSyncColorGroup(boolean syncColorGroup) { | |
65 | + this.syncColorGroup = syncColorGroup; | |
66 | + } | |
67 | + | |
68 | + public boolean isSyncColorGroup() { | |
69 | + return syncColorGroup; | |
70 | + } | |
71 | + | |
72 | + public void setColorConvertParameter( | |
73 | + ColorConvertParameter colorConvertParameter) { | |
74 | + this.colorConvertParameter = colorConvertParameter; | |
75 | + } | |
76 | + | |
77 | + public ColorConvertParameter getColorConvertParameter() { | |
78 | + return colorConvertParameter; | |
79 | + } | |
80 | + | |
81 | + /** | |
82 | + * インスタンス独立の素のカラー情報から、カテゴリやレイヤー、カラーグループのインスタンスと関連づけられたカラー情報に変換してかえす. | |
83 | + * | |
84 | + * @param characterData | |
85 | + * キャラクターデータ | |
86 | + * @param category | |
87 | + * パーツカテゴリインスタンス | |
88 | + * @param partsColorInfoList | |
89 | + * 素のパーツカラー情報、なければnull可 | |
90 | + * @return パーツカラー情報、パーツカラー情報がなければnull | |
91 | + */ | |
92 | + public static PartsColorInfo buildPartsColorInfo( | |
93 | + CharacterData characterData, | |
94 | + PartsCategory category, | |
95 | + List<IndependentPartsColorInfo> partsColorInfoList) { | |
96 | + if (characterData == null || category == null) { | |
97 | + throw new IllegalArgumentException(); | |
98 | + } | |
99 | + if (partsColorInfoList == null) { | |
100 | + return null; | |
101 | + } | |
102 | + PartsColorInfo partsColorInfo = null; | |
103 | + for (IndependentPartsColorInfo info : partsColorInfoList) { | |
104 | + String layerId = info.getLayerId(); | |
105 | + Layer layer = category.getLayer(layerId); | |
106 | + if (layer == null) { | |
107 | + logger.log(Level.WARNING, "undefined layer: " + layerId); | |
108 | + break; | |
109 | + } | |
110 | + if (partsColorInfo == null) { | |
111 | + partsColorInfo = new PartsColorInfo(category); | |
112 | + } | |
113 | + | |
114 | + ColorInfo colorInfo = partsColorInfo.get(layer); | |
115 | + | |
116 | + // color group | |
117 | + String colorGroupId = info.getColorGroupId(); | |
118 | + ColorGroup colorGroup = characterData.getColorGroup(colorGroupId); | |
119 | + boolean syncColorGroup = info.isSyncColorGroup(); | |
120 | + colorInfo.setColorGroup(colorGroup); | |
121 | + colorInfo.setSyncColorGroup(syncColorGroup); | |
122 | + | |
123 | + // color parameters | |
124 | + colorInfo.setColorParameter(info.getColorConvertParameter()); | |
125 | + } | |
126 | + return partsColorInfo; | |
127 | + } | |
128 | +} | |
\ No newline at end of file |
@@ -0,0 +1,247 @@ | ||
1 | +package charactermanaj.model.io; | |
2 | + | |
3 | +import static charactermanaj.util.XMLUtilities.getChildElements; | |
4 | +import static charactermanaj.util.XMLUtilities.getElementText; | |
5 | + | |
6 | +import java.awt.Color; | |
7 | +import java.io.File; | |
8 | +import java.io.IOException; | |
9 | +import java.io.InputStream; | |
10 | +import java.net.URI; | |
11 | +import java.net.URISyntaxException; | |
12 | +import java.util.HashMap; | |
13 | +import java.util.List; | |
14 | +import java.util.Locale; | |
15 | +import java.util.Map; | |
16 | +import java.util.logging.Logger; | |
17 | + | |
18 | +import org.w3c.dom.Document; | |
19 | +import org.w3c.dom.Element; | |
20 | + | |
21 | +import charactermanaj.model.IndependentPartsColorInfo; | |
22 | +import charactermanaj.model.IndependentPartsSetInfo; | |
23 | +import charactermanaj.model.WorkingSet2; | |
24 | +import charactermanaj.ui.model.WallpaperInfo; | |
25 | +import charactermanaj.ui.model.WallpaperInfo.WallpaperResourceType; | |
26 | +import charactermanaj.util.XMLUtilities; | |
27 | + | |
28 | +/** | |
29 | + * ワーキングセットのXMLデータを読み込む.<br> | |
30 | + * | |
31 | + * @author seraphy | |
32 | + */ | |
33 | +public class WorkingSetXMLReader { | |
34 | + | |
35 | + /** | |
36 | + * ロガー | |
37 | + */ | |
38 | + private static final Logger logger = Logger | |
39 | + .getLogger(WorkingSetXMLReader.class.getCanonicalName()); | |
40 | + | |
41 | + /** | |
42 | + * WorkingSetのXMLファイルの名前空間 | |
43 | + */ | |
44 | + private static final String NS_PREFIX = "http://charactermanaj.sourceforge.jp/schema/charactermanaj-workingset"; | |
45 | + | |
46 | + /** | |
47 | + * XMLコンテンツに対する入力ストリームからワーキングセットを取り出す.<br> | |
48 | + * | |
49 | + * @param is | |
50 | + * 入力ストリーム | |
51 | + * @throws IOException | |
52 | + * 読み取りに失敗 | |
53 | + */ | |
54 | + public WorkingSet2 loadWorkingSet(InputStream is) | |
55 | + throws IOException { | |
56 | + if (is == null) { | |
57 | + throw new IllegalArgumentException(); | |
58 | + } | |
59 | + | |
60 | + WorkingSet2 workingSet = new WorkingSet2(); | |
61 | + | |
62 | + CharacterDataXMLReader characterDataXMLReader = new CharacterDataXMLReader(); | |
63 | + | |
64 | + Document doc = XMLUtilities.loadDocument(is); | |
65 | + | |
66 | + String lang = Locale.getDefault().getLanguage(); | |
67 | + | |
68 | + try { | |
69 | + Element docElm = doc.getDocumentElement(); | |
70 | + if (!"character-workingset".equals(docElm.getNodeName())) { | |
71 | + throw new IOException("Invalid Format."); | |
72 | + } | |
73 | + String ns = docElm.getNamespaceURI(); | |
74 | + if (ns == null || !ns.startsWith(NS_PREFIX)) { | |
75 | + throw new IOException("unsupported xml format"); | |
76 | + } | |
77 | + | |
78 | + String docVersion = docElm.getAttribute("version").trim(); | |
79 | + if (!"1.0".equals(docVersion)) { | |
80 | + throw new IOException("unsupported version: " + docVersion); | |
81 | + } | |
82 | + | |
83 | + // docbase | |
84 | + String characterDocBase = docElm.getAttribute("characterDocBase") | |
85 | + .trim(); | |
86 | + try { | |
87 | + workingSet.setCharacterDocBase(new URI(characterDocBase)); | |
88 | + | |
89 | + } catch (URISyntaxException ex) { | |
90 | + IOException ex2 = new IOException("WorkingSet invalid format."); | |
91 | + ex2.initCause(ex); | |
92 | + throw ex2; | |
93 | + } | |
94 | + | |
95 | + // character data signature | |
96 | + String characterDataSig = getElementText(docElm, "characterDataSig"); | |
97 | + workingSet.setCharacterDataSig(characterDataSig); | |
98 | + | |
99 | + // キーはカテゴリid, 値は、パーツ名をキーとしレイヤーごとのカラー情報のリストを値とするマップ | |
100 | + HashMap<String, Map<String, List<IndependentPartsColorInfo>>> partsColorMap = new HashMap<String, Map<String, List<IndependentPartsColorInfo>>>(); | |
101 | + for (Element partsColorInfoMapElm : getChildElements(docElm, | |
102 | + "partsColorInfoMap")) { | |
103 | + // カラー定義マップを読み込む | |
104 | + HashMap<String, List<IndependentPartsColorInfo>> colorMap = new HashMap<String, List<IndependentPartsColorInfo>>(); | |
105 | + for (Element colorsElm : getChildElements(partsColorInfoMapElm, | |
106 | + "colors")) { | |
107 | + for (Element colorElm : getChildElements(colorsElm, "color")) { | |
108 | + String colorId = colorElm.getAttribute("id"); | |
109 | + List<IndependentPartsColorInfo> colorInfoList = characterDataXMLReader | |
110 | + .readPartsColor(colorElm); | |
111 | + colorMap.put(colorId, colorInfoList); | |
112 | + } | |
113 | + } | |
114 | + | |
115 | + // パーツごとのカラー情報を読み込む | |
116 | + for (Element partsListElm : getChildElements( | |
117 | + partsColorInfoMapElm, "partsList")) { | |
118 | + for (Element partsElm : getChildElements(partsListElm, | |
119 | + "partsIdentifier")) { | |
120 | + String categoryId = partsElm.getAttribute("categoryId"); | |
121 | + String name = partsElm.getAttribute("name"); | |
122 | + String colorId = partsElm.getAttribute("colorId"); | |
123 | + | |
124 | + Map<String, List<IndependentPartsColorInfo>> partsMap = partsColorMap | |
125 | + .get(categoryId); | |
126 | + if (partsMap == null) { | |
127 | + partsMap = new HashMap<String, List<IndependentPartsColorInfo>>(); | |
128 | + partsColorMap.put(categoryId, partsMap); | |
129 | + } | |
130 | + List<IndependentPartsColorInfo> colorInfo = colorMap | |
131 | + .get(colorId); | |
132 | + if (colorInfo == null) { | |
133 | + logger.warning("undefined colorId:" + colorId); | |
134 | + } else { | |
135 | + partsMap.put(name, colorInfo); | |
136 | + } | |
137 | + } | |
138 | + } | |
139 | + } | |
140 | + workingSet.setPartsColorMap(partsColorMap); | |
141 | + | |
142 | + // 最後に使用した保存先ディレクトリ | |
143 | + String lastUsedSaveDirStr = getElementText(docElm, | |
144 | + "lastUsedSaveDir"); | |
145 | + if (lastUsedSaveDirStr != null | |
146 | + && lastUsedSaveDirStr.trim().length() > 0) { | |
147 | + workingSet.setLastUsedSaveDir(new File(lastUsedSaveDirStr | |
148 | + .trim())); | |
149 | + } | |
150 | + | |
151 | + // 最後に使用したエクスポート先ディレクトリ | |
152 | + String lastUsedExportDirStr = getElementText(docElm, | |
153 | + "lastUsedExportDir"); | |
154 | + if (lastUsedExportDirStr != null | |
155 | + && lastUsedExportDirStr.trim().length() > 0) { | |
156 | + workingSet.setLastUsedExportDir(new File(lastUsedExportDirStr | |
157 | + .trim())); | |
158 | + } | |
159 | + | |
160 | + // 壁紙情報 | |
161 | + WallpaperInfo wallpaperInfo = null; | |
162 | + for (Element wallpaperElm : getChildElements(docElm, | |
163 | + "wallpaperInfo")) { | |
164 | + wallpaperInfo = readWallpaperInfo(wallpaperElm); | |
165 | + break; // wallpaperInfoは最初の一要素しか想定しない. | |
166 | + } | |
167 | + workingSet.setWallpaperInfo(wallpaperInfo); | |
168 | + | |
169 | + // 現在のパーツ情報 | |
170 | + for (Element currentPartsSetsElm : getChildElements(docElm, | |
171 | + "currentPartsSet")) { | |
172 | + for (Element presetElm : getChildElements(currentPartsSetsElm, | |
173 | + "preset")) { | |
174 | + IndependentPartsSetInfo currentPartsSet = characterDataXMLReader | |
175 | + .loadPartsSet(presetElm, lang); | |
176 | + workingSet.setCurrentPartsSet(currentPartsSet); | |
177 | + break; // 最初の一要素のみ | |
178 | + } | |
179 | + break; // 最初の一要素のみ | |
180 | + } | |
181 | + | |
182 | + // 最後に使ったお気に入り情報 | |
183 | + for (Element lastUsePresetPartsElm : getChildElements(docElm, | |
184 | + "lastUsePresetParts")) { | |
185 | + for (Element presetElm : getChildElements( | |
186 | + lastUsePresetPartsElm, "preset")) { | |
187 | + IndependentPartsSetInfo lastUsePresetParts = characterDataXMLReader | |
188 | + .loadPartsSet(presetElm, lang); | |
189 | + workingSet.setLastUsePresetParts(lastUsePresetParts); | |
190 | + break; // 最初の一要素のみ | |
191 | + } | |
192 | + break; // 最初の一要素のみ | |
193 | + } | |
194 | + | |
195 | + return workingSet; | |
196 | + | |
197 | + } catch (RuntimeException ex) { | |
198 | + IOException ex2 = new IOException("WorkingSet invalid format."); | |
199 | + ex2.initCause(ex); | |
200 | + throw ex2; | |
201 | + } | |
202 | + } | |
203 | + | |
204 | + /** | |
205 | + * 壁紙情報を読み込む | |
206 | + * | |
207 | + * @param elm | |
208 | + * 壁紙要素 | |
209 | + * @return 壁紙情報、elmがnullの場合はnullを返す. | |
210 | + */ | |
211 | + private WallpaperInfo readWallpaperInfo(Element elm) { | |
212 | + if (elm == null) { | |
213 | + return null; | |
214 | + } | |
215 | + WallpaperInfo wallpaperInfo = new WallpaperInfo(); | |
216 | + | |
217 | + String typStr = getElementText(elm, "type"); | |
218 | + WallpaperResourceType typ = WallpaperResourceType.valueOf(typStr); | |
219 | + wallpaperInfo.setType(typ); | |
220 | + | |
221 | + String res = getElementText(elm, "resource"); | |
222 | + if (res != null && res.trim().length() > 0) { | |
223 | + wallpaperInfo.setResource(res.trim()); | |
224 | + } | |
225 | + | |
226 | + String fileStr = getElementText(elm, "file"); | |
227 | + if (fileStr != null && fileStr.trim().length() > 0) { | |
228 | + wallpaperInfo.setFile(new File(fileStr.trim())); | |
229 | + } | |
230 | + | |
231 | + float alpha = 0f; | |
232 | + String alphaStr = getElementText(elm, "alpha"); | |
233 | + if (alphaStr != null && alphaStr.trim().length() > 0) { | |
234 | + alpha = Float.parseFloat(alphaStr); | |
235 | + wallpaperInfo.setAlpha(alpha); | |
236 | + } | |
237 | + | |
238 | + String backgroundColorStr = getElementText(elm, "backgroundColor"); | |
239 | + if (backgroundColorStr != null | |
240 | + && backgroundColorStr.trim().length() > 0) { | |
241 | + Color backgroundColor = Color.decode(backgroundColorStr.trim()); | |
242 | + wallpaperInfo.setBackgroundColor(backgroundColor); | |
243 | + } | |
244 | + | |
245 | + return wallpaperInfo; | |
246 | + } | |
247 | +} |
@@ -403,9 +403,13 @@ | ||
403 | 403 | |
404 | 404 | /** |
405 | 405 | * パーツセットのXM要素を生成して返す. |
406 | - * @param doc ノードを生成するためのファクトリ | |
407 | - * @param lang 言語識別用(パーツセット名などの登録時のlang属性に必要) | |
408 | - * @param partsSet パーツセット、nullの場合はxsi:nul="true"が返される. | |
406 | + * | |
407 | + * @param doc | |
408 | + * ノードを生成するためのファクトリ | |
409 | + * @param lang | |
410 | + * 言語識別用(パーツセット名などの登録時のlang属性に必要) | |
411 | + * @param partsSet | |
412 | + * パーツセット、nullの場合はxsi:nul="true"が返される. | |
409 | 413 | * @return パーツセット1つ分のXML要素 |
410 | 414 | */ |
411 | 415 | public Element createPartsSetXML(Document doc, String lang, PartsSet partsSet) { |
@@ -493,8 +497,11 @@ | ||
493 | 497 | |
494 | 498 | /** |
495 | 499 | * パーツカラー情報のXML要素を生成して返す.<br> |
496 | - * @param doc 要素を作成するためのファクトリ | |
497 | - * @param partsColorInfo パーツカラー情報 | |
500 | + * | |
501 | + * @param doc | |
502 | + * 要素を作成するためのファクトリ | |
503 | + * @param partsColorInfo | |
504 | + * パーツカラー情報 | |
498 | 505 | * @return パーツカラー情報の要素 |
499 | 506 | */ |
500 | 507 | public Element createPartsColorInfoXML(Document doc, PartsColorInfo partsColorInfo) { |
@@ -1,311 +1,324 @@ | ||
1 | -package charactermanaj.model.io; | |
2 | - | |
3 | -import java.awt.Color; | |
4 | -import java.io.File; | |
5 | -import java.io.IOException; | |
6 | -import java.io.OutputStream; | |
7 | -import java.io.OutputStreamWriter; | |
8 | -import java.net.URI; | |
9 | -import java.nio.charset.Charset; | |
10 | -import java.util.LinkedHashMap; | |
11 | -import java.util.Locale; | |
12 | -import java.util.Map; | |
13 | - | |
14 | -import javax.xml.XMLConstants; | |
15 | -import javax.xml.parsers.DocumentBuilder; | |
16 | -import javax.xml.parsers.DocumentBuilderFactory; | |
17 | -import javax.xml.parsers.ParserConfigurationException; | |
18 | -import javax.xml.transform.OutputKeys; | |
19 | -import javax.xml.transform.Transformer; | |
20 | -import javax.xml.transform.TransformerConfigurationException; | |
21 | -import javax.xml.transform.TransformerException; | |
22 | -import javax.xml.transform.TransformerFactory; | |
23 | -import javax.xml.transform.dom.DOMSource; | |
24 | -import javax.xml.transform.stream.StreamResult; | |
25 | - | |
26 | -import org.w3c.dom.Document; | |
27 | -import org.w3c.dom.Element; | |
28 | - | |
29 | -import charactermanaj.model.CharacterData; | |
30 | -import charactermanaj.model.PartsColorInfo; | |
31 | -import charactermanaj.model.PartsIdentifier; | |
32 | -import charactermanaj.model.PartsSet; | |
33 | -import charactermanaj.model.WorkingSet; | |
34 | -import charactermanaj.ui.model.WallpaperInfo; | |
35 | -import charactermanaj.ui.model.WallpaperInfo.WallpaperResourceType; | |
36 | - | |
37 | -/** | |
38 | - * WorkingSetのXMLへの書き込み | |
39 | - */ | |
40 | -public class WorkingSetXMLWriter { | |
41 | - | |
42 | - /** | |
43 | - * WorkingSetのバージョン | |
44 | - */ | |
45 | - private static final String VERSION_SIG_1_0 = "1.0"; | |
46 | - | |
47 | - /** | |
48 | - * WorkingSetのXMLファイルの名前空間 | |
49 | - */ | |
50 | - private static final String NS = "http://charactermanaj.sourceforge.jp/schema/charactermanaj-workingset"; | |
51 | - | |
52 | - /** | |
53 | - * キャラクターデータのXML化 | |
54 | - */ | |
55 | - private CharacterDataXMLWriter characterDataXmlWriter = | |
56 | - new CharacterDataXMLWriter(NS); | |
57 | - | |
58 | - /** | |
59 | - * ワーキングセットをXML表現で出力ストリームに出力します.<br> | |
60 | - * @param ws ワーキングセット | |
61 | - * @param outstm 出力先ストリーム | |
62 | - * @throws IOException 失敗 | |
63 | - */ | |
64 | - public void writeWorkingSet(WorkingSet ws, OutputStream outstm) throws IOException { | |
65 | - if (ws == null || outstm == null) { | |
66 | - throw new IllegalArgumentException(); | |
67 | - } | |
68 | - | |
69 | - Document doc = createWorkingSetXML(ws); | |
70 | - | |
71 | - // output xml | |
72 | - TransformerFactory txFactory = TransformerFactory.newInstance(); | |
73 | - txFactory.setAttribute("indent-number", Integer.valueOf(4)); | |
74 | - Transformer tfmr; | |
75 | - try { | |
76 | - tfmr = txFactory.newTransformer(); | |
77 | - } catch (TransformerConfigurationException ex) { | |
78 | - throw new RuntimeException("JAXP Configuration Failed.", ex); | |
79 | - } | |
80 | - tfmr.setOutputProperty(OutputKeys.INDENT, "yes"); | |
81 | - | |
82 | - // JDK-4504745 : javax.xml.transform.Transformer encoding does not work properly | |
83 | - // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4504745 | |
84 | - final String encoding = "UTF-8"; | |
85 | - tfmr.setOutputProperty("encoding", encoding); | |
86 | - try { | |
87 | - tfmr.transform(new DOMSource(doc), new StreamResult( | |
88 | - new OutputStreamWriter(outstm, Charset.forName(encoding)))); | |
89 | - | |
90 | - } catch (TransformerException ex) { | |
91 | - IOException ex2 = new IOException("XML Convert failed."); | |
92 | - ex2.initCause(ex); | |
93 | - throw ex2; | |
94 | - } | |
95 | - } | |
96 | - | |
97 | - /** | |
98 | - * ワーキングセットのXMLドキュメントを生成します. | |
99 | - * @param ws ワーキングセット | |
100 | - * @return XMLドキュメント | |
101 | - */ | |
102 | - public Document createWorkingSetXML(WorkingSet ws) { | |
103 | - if (ws == null) { | |
104 | - throw new IllegalArgumentException(); | |
105 | - } | |
106 | - | |
107 | - Document doc; | |
108 | - try { | |
109 | - DocumentBuilderFactory factory = DocumentBuilderFactory | |
110 | - .newInstance(); | |
111 | - factory.setNamespaceAware(true); | |
112 | - DocumentBuilder builder = factory.newDocumentBuilder(); | |
113 | - doc = builder.newDocument(); | |
114 | - } catch (ParserConfigurationException ex) { | |
115 | - throw new RuntimeException("JAXP Configuration failed.", ex); | |
116 | - } | |
117 | - | |
118 | - Locale locale = Locale.getDefault(); | |
119 | - String lang = locale.getLanguage(); | |
120 | - | |
121 | - Element root = doc.createElementNS(NS, "character-workingset"); | |
122 | - root.setAttribute("version", VERSION_SIG_1_0); | |
123 | - | |
124 | - root.setAttributeNS(XMLConstants.XMLNS_ATTRIBUTE_NS_URI, "xmlns:xsi", | |
125 | - XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI); | |
126 | - root.setAttributeNS(XMLConstants.XMLNS_ATTRIBUTE_NS_URI, "xmlns:xml", | |
127 | - XMLConstants.XML_NS_URI); | |
128 | - root.setAttribute("xsi:schemaLocation", NS + " character_ws.xsd"); | |
129 | - | |
130 | - // ドキュメントベース | |
131 | - URI docbase = ws.getCharacterDocBase(); | |
132 | - root.setAttribute("characterDocBase", docbase == null ? "" : docbase.toString()); | |
133 | - | |
134 | - // キャラクターデータのシグネチャ | |
135 | - CharacterData cd = ws.getCharacterData(); | |
136 | - Element characterDataSigElm = doc.createElementNS(NS, "characterDataSig"); | |
137 | - if (cd == null || !cd.isValid()) { | |
138 | - // 指定されていないか有効でない場合は無しとみなす. | |
139 | - characterDataSigElm.setAttributeNS(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "xsi:nil", "true"); | |
140 | - } else { | |
141 | - characterDataSigElm.setTextContent(cd.toSignatureString()); | |
142 | - } | |
143 | - root.appendChild(characterDataSigElm); | |
144 | - | |
145 | - // パーツカラー情報 | |
146 | - root.appendChild(writePartsColorInfoMap(doc, ws.getPartsColorInfoMap())); | |
147 | - | |
148 | - // パーツセット | |
149 | - PartsSet partsSet = ws.getPartsSet(); | |
150 | - Element partsSetElm = doc.createElementNS(NS, "partsSet"); | |
151 | - if (partsSet == null || partsSet.isEmpty()) { | |
152 | - partsSetElm.setAttributeNS(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "xsi:nil", "true"); | |
153 | - | |
154 | - } else { | |
155 | - Element elm = characterDataXmlWriter.createPartsSetXML(doc, lang, partsSet); | |
156 | - partsSetElm.appendChild(elm); | |
157 | - } | |
158 | - root.appendChild(partsSetElm); | |
159 | - | |
160 | - // 最後に使用した保存先ディレクトリ | |
161 | - Element lastUsedSaveDirElm = doc.createElementNS(NS, "lastUsedSaveDir"); | |
162 | - File lastUsedSaveDir = ws.getLastUsedSaveDir(); | |
163 | - if (lastUsedSaveDir == null) { | |
164 | - lastUsedSaveDirElm.setAttributeNS(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "xsi:nil", "true"); | |
165 | - | |
166 | - } else { | |
167 | - lastUsedSaveDirElm.setTextContent(lastUsedSaveDir.getPath()); | |
168 | - } | |
169 | - root.appendChild(lastUsedSaveDirElm); | |
170 | - | |
171 | - // 最後に使用したエクスポート先ディレクトリ | |
172 | - Element lastUsedExportDirElm = doc.createElementNS(NS, "lastUsedExportDir"); | |
173 | - File lastUsedExportDir = ws.getLastUsedExportDir(); | |
174 | - if (lastUsedExportDir == null) { | |
175 | - lastUsedExportDirElm.setAttributeNS(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "xsi:nil", "true"); | |
176 | - | |
177 | - } else { | |
178 | - lastUsedExportDirElm.setTextContent(lastUsedExportDir.getPath()); | |
179 | - } | |
180 | - root.appendChild(lastUsedExportDirElm); | |
181 | - | |
182 | - // 最後に使用したパーツセット情報、なければnull | |
183 | - PartsSet lastUsePresetParts = ws.getLastUsePresetParts(); | |
184 | - Element lastUsePresetPartsElm = doc.createElementNS(NS, "lastUsePresetParts"); | |
185 | - if (lastUsePresetParts == null || lastUsePresetParts.isEmpty()) { | |
186 | - lastUsePresetPartsElm.setAttributeNS(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "xsi:nil", "true"); | |
187 | - | |
188 | - } else { | |
189 | - Element elm = characterDataXmlWriter.createPartsSetXML(doc, lang, lastUsePresetParts); | |
190 | - lastUsePresetPartsElm.appendChild(elm); | |
191 | - } | |
192 | - root.appendChild(lastUsePresetPartsElm); | |
193 | - | |
194 | - // 壁紙情報 | |
195 | - root.appendChild(writeWallpaper(doc, ws.getWallpaperInfo())); | |
196 | - | |
197 | - doc.appendChild(root); | |
198 | - return doc; | |
199 | - } | |
200 | - | |
201 | - /** | |
202 | - * パーツごとのカラー情報のXML要素を生成して返します. | |
203 | - * @param doc 要素のファクトリ | |
204 | - * @param partsColorMap パーツごとのカラー情報のマップ | |
205 | - * @return パーツごとのカラー情報のXML要素 | |
206 | - */ | |
207 | - public Element writePartsColorInfoMap(Document doc, Map<PartsIdentifier, PartsColorInfo> partsColorMap) { | |
208 | - Element partsColorInfoMapElm = doc.createElementNS(NS, "partsColorInfoMap"); | |
209 | - if (partsColorMap != null) { | |
210 | - // 使用しているカラーの設定ごとに番号を振る | |
211 | - // (同じカラー設定であれば同じ番号とする.) | |
212 | - LinkedHashMap<PartsColorInfo, String> colorMap = new LinkedHashMap<PartsColorInfo, String>(); | |
213 | - for (Map.Entry<PartsIdentifier, PartsColorInfo> partsColorEntry : partsColorMap.entrySet()) { | |
214 | - PartsColorInfo partsColorInfo = partsColorEntry.getValue(); | |
215 | - if (partsColorInfo != null && !partsColorInfo.isEmpty()) { | |
216 | - if (!colorMap.containsKey(partsColorInfo)) { | |
217 | - colorMap.put(partsColorInfo, Integer.toString(colorMap.size() + 1)); | |
218 | - } | |
219 | - } | |
220 | - } | |
221 | - | |
222 | - // すべてのカラー設定を出力する. | |
223 | - Element colorsElm = doc.createElementNS(NS, "colors"); | |
224 | - for (Map.Entry<PartsColorInfo, String> colorMapEntry : colorMap.entrySet()) { | |
225 | - PartsColorInfo partsColorInfo = colorMapEntry.getKey(); | |
226 | - String id = colorMapEntry.getValue(); | |
227 | - Element partsColorElm = characterDataXmlWriter.createPartsColorInfoXML(doc, partsColorInfo); | |
228 | - partsColorElm.setAttribute("id", id); | |
229 | - colorsElm.appendChild(partsColorElm); | |
230 | - } | |
231 | - partsColorInfoMapElm.appendChild(colorsElm); | |
232 | - | |
233 | - // パーツと、そのパーツのカラー設定番号の一覧を出力する. | |
234 | - Element partsListElm = doc.createElementNS(NS, "partsList"); | |
235 | - for (Map.Entry<PartsIdentifier, PartsColorInfo> partsColorEntry : partsColorMap.entrySet()) { | |
236 | - PartsIdentifier partsIdentifier = partsColorEntry.getKey(); | |
237 | - PartsColorInfo partsColorInfo = partsColorEntry.getValue(); | |
238 | - if (partsColorInfo != null && !partsColorInfo.isEmpty()) { | |
239 | - String colorId = colorMap.get(partsColorInfo); | |
240 | - if (colorId == null) { | |
241 | - throw new RuntimeException("colorMapが不整合です"); | |
242 | - } | |
243 | - Element partsElm = doc.createElementNS(NS, "partsIdentifier"); | |
244 | - String categoryId = partsIdentifier.getPartsCategory().getCategoryId(); | |
245 | - partsElm.setAttribute("categoryId", categoryId); | |
246 | - partsElm.setAttribute("name", partsIdentifier.getPartsName()); | |
247 | - partsElm.setAttribute("colorId", colorId); | |
248 | - partsListElm.appendChild(partsElm); | |
249 | - } | |
250 | - } | |
251 | - partsColorInfoMapElm.appendChild(partsListElm); | |
252 | - } | |
253 | - return partsColorInfoMapElm; | |
254 | - } | |
255 | - | |
256 | - /** | |
257 | - * 壁紙情報をXML要素として生成する. | |
258 | - * @param doc XML要素のファクトリ | |
259 | - * @param wallpaperInfo 壁紙情報 | |
260 | - * @return 壁紙情報のXML要素 | |
261 | - */ | |
262 | - public Element writeWallpaper(Document doc, WallpaperInfo wallpaperInfo) { | |
263 | - Element elm = doc.createElementNS(NS, "wallpaperInfo"); | |
264 | - | |
265 | - if (wallpaperInfo == null) { | |
266 | - elm.setAttributeNS(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "xsi:nil", "true"); | |
267 | - | |
268 | - } else { | |
269 | - // タイプ | |
270 | - WallpaperResourceType typ = wallpaperInfo.getType(); | |
271 | - Element typElm = doc.createElementNS(NS, "type"); | |
272 | - typElm.setTextContent(typ.name()); | |
273 | - elm.appendChild(typElm); | |
274 | - | |
275 | - // リソース | |
276 | - String res = wallpaperInfo.getResource(); | |
277 | - Element resElm = doc.createElementNS(NS, "resource"); | |
278 | - if (res == null || res.trim().length() == 0) { | |
279 | - resElm.setAttributeNS(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "xsi:nil", "true"); | |
280 | - } else { | |
281 | - resElm.setTextContent(res); | |
282 | - } | |
283 | - elm.appendChild(resElm); | |
284 | - | |
285 | - // ファイル | |
286 | - File file = wallpaperInfo.getFile(); | |
287 | - Element fileElm = doc.createElementNS(NS, "file"); | |
288 | - if (file == null) { | |
289 | - fileElm.setAttributeNS(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "xsi:nil", "true"); | |
290 | - } else { | |
291 | - fileElm.setTextContent(file.getPath()); | |
292 | - } | |
293 | - elm.appendChild(fileElm); | |
294 | - | |
295 | - // アルファ | |
296 | - float alpha = wallpaperInfo.getAlpha(); | |
297 | - Element alphaElm = doc.createElementNS(NS, "alpha"); | |
298 | - alphaElm.setTextContent(Float.toString(alpha)); | |
299 | - elm.appendChild(alphaElm); | |
300 | - | |
301 | - // 背景色 | |
302 | - Color backgroundColor = wallpaperInfo.getBackgroundColor(); | |
303 | - Element bgColorElm = doc.createElementNS(NS, "backgroundColor"); | |
304 | - bgColorElm.setTextContent("#" + Integer.toHexString(backgroundColor.getRGB() & 0xffffff)); | |
305 | - elm.appendChild(bgColorElm); | |
306 | - } | |
307 | - | |
308 | - return elm; | |
309 | - } | |
310 | - | |
311 | -} | |
1 | +package charactermanaj.model.io; | |
2 | + | |
3 | +import java.awt.Color; | |
4 | +import java.io.File; | |
5 | +import java.io.IOException; | |
6 | +import java.io.OutputStream; | |
7 | +import java.io.OutputStreamWriter; | |
8 | +import java.net.URI; | |
9 | +import java.nio.charset.Charset; | |
10 | +import java.util.LinkedHashMap; | |
11 | +import java.util.Locale; | |
12 | +import java.util.Map; | |
13 | + | |
14 | +import javax.xml.XMLConstants; | |
15 | +import javax.xml.parsers.DocumentBuilder; | |
16 | +import javax.xml.parsers.DocumentBuilderFactory; | |
17 | +import javax.xml.parsers.ParserConfigurationException; | |
18 | +import javax.xml.transform.OutputKeys; | |
19 | +import javax.xml.transform.Transformer; | |
20 | +import javax.xml.transform.TransformerConfigurationException; | |
21 | +import javax.xml.transform.TransformerException; | |
22 | +import javax.xml.transform.TransformerFactory; | |
23 | +import javax.xml.transform.dom.DOMSource; | |
24 | +import javax.xml.transform.stream.StreamResult; | |
25 | + | |
26 | +import org.w3c.dom.Document; | |
27 | +import org.w3c.dom.Element; | |
28 | + | |
29 | +import charactermanaj.model.CharacterData; | |
30 | +import charactermanaj.model.PartsColorInfo; | |
31 | +import charactermanaj.model.PartsIdentifier; | |
32 | +import charactermanaj.model.PartsSet; | |
33 | +import charactermanaj.model.WorkingSet; | |
34 | +import charactermanaj.ui.model.WallpaperInfo; | |
35 | +import charactermanaj.ui.model.WallpaperInfo.WallpaperResourceType; | |
36 | + | |
37 | +/** | |
38 | + * WorkingSetのXMLへの書き込み | |
39 | + */ | |
40 | +public class WorkingSetXMLWriter { | |
41 | + | |
42 | + /** | |
43 | + * WorkingSetのバージョン | |
44 | + */ | |
45 | + private static final String VERSION_SIG_1_0 = "1.0"; | |
46 | + | |
47 | + /** | |
48 | + * WorkingSetのXMLファイルの名前空間 | |
49 | + */ | |
50 | + private static final String NS = "http://charactermanaj.sourceforge.jp/schema/charactermanaj-workingset"; | |
51 | + | |
52 | + /** | |
53 | + * キャラクターデータのXML化 | |
54 | + */ | |
55 | + private CharacterDataXMLWriter characterDataXmlWriter = | |
56 | + new CharacterDataXMLWriter(NS); | |
57 | + | |
58 | + /** | |
59 | + * ワーキングセットをXML表現で出力ストリームに出力します.<br> | |
60 | + * | |
61 | + * @param ws | |
62 | + * ワーキングセット | |
63 | + * @param outstm | |
64 | + * 出力先ストリーム | |
65 | + * @throws IOException | |
66 | + * 失敗 | |
67 | + */ | |
68 | + public void writeWorkingSet(WorkingSet ws, OutputStream outstm) throws IOException { | |
69 | + if (ws == null || outstm == null) { | |
70 | + throw new IllegalArgumentException(); | |
71 | + } | |
72 | + | |
73 | + Document doc = createWorkingSetXML(ws); | |
74 | + | |
75 | + // output xml | |
76 | + TransformerFactory txFactory = TransformerFactory.newInstance(); | |
77 | + txFactory.setAttribute("indent-number", Integer.valueOf(4)); | |
78 | + Transformer tfmr; | |
79 | + try { | |
80 | + tfmr = txFactory.newTransformer(); | |
81 | + } catch (TransformerConfigurationException ex) { | |
82 | + throw new RuntimeException("JAXP Configuration Failed.", ex); | |
83 | + } | |
84 | + tfmr.setOutputProperty(OutputKeys.INDENT, "yes"); | |
85 | + | |
86 | + // JDK-4504745 : javax.xml.transform.Transformer encoding does not work properly | |
87 | + // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4504745 | |
88 | + final String encoding = "UTF-8"; | |
89 | + tfmr.setOutputProperty("encoding", encoding); | |
90 | + try { | |
91 | + tfmr.transform(new DOMSource(doc), new StreamResult( | |
92 | + new OutputStreamWriter(outstm, Charset.forName(encoding)))); | |
93 | + | |
94 | + } catch (TransformerException ex) { | |
95 | + IOException ex2 = new IOException("XML Convert failed."); | |
96 | + ex2.initCause(ex); | |
97 | + throw ex2; | |
98 | + } | |
99 | + } | |
100 | + | |
101 | + /** | |
102 | + * ワーキングセットのXMLドキュメントを生成します. | |
103 | + * | |
104 | + * @param ws | |
105 | + * ワーキングセット | |
106 | + * @return XMLドキュメント | |
107 | + */ | |
108 | + public Document createWorkingSetXML(WorkingSet ws) { | |
109 | + if (ws == null) { | |
110 | + throw new IllegalArgumentException(); | |
111 | + } | |
112 | + | |
113 | + Document doc; | |
114 | + try { | |
115 | + DocumentBuilderFactory factory = DocumentBuilderFactory | |
116 | + .newInstance(); | |
117 | + factory.setNamespaceAware(true); | |
118 | + DocumentBuilder builder = factory.newDocumentBuilder(); | |
119 | + doc = builder.newDocument(); | |
120 | + } catch (ParserConfigurationException ex) { | |
121 | + throw new RuntimeException("JAXP Configuration failed.", ex); | |
122 | + } | |
123 | + | |
124 | + Locale locale = Locale.getDefault(); | |
125 | + String lang = locale.getLanguage(); | |
126 | + | |
127 | + Element root = doc.createElementNS(NS, "character-workingset"); | |
128 | + root.setAttribute("version", VERSION_SIG_1_0); | |
129 | + | |
130 | + root.setAttributeNS(XMLConstants.XMLNS_ATTRIBUTE_NS_URI, "xmlns:xsi", | |
131 | + XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI); | |
132 | + root.setAttributeNS(XMLConstants.XMLNS_ATTRIBUTE_NS_URI, "xmlns:xml", | |
133 | + XMLConstants.XML_NS_URI); | |
134 | + root.setAttribute("xsi:schemaLocation", NS + " character_ws.xsd"); | |
135 | + | |
136 | + // ドキュメントベース | |
137 | + URI docbase = ws.getCharacterDocBase(); | |
138 | + root.setAttribute("characterDocBase", docbase == null ? "" : docbase.toString()); | |
139 | + | |
140 | + // キャラクターデータのシグネチャ | |
141 | + CharacterData cd = ws.getCharacterData(); | |
142 | + Element characterDataSigElm = doc.createElementNS(NS, "characterDataSig"); | |
143 | + if (cd == null || !cd.isValid()) { | |
144 | + // 指定されていないか有効でない場合は無しとみなす. | |
145 | + characterDataSigElm.setAttributeNS(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "xsi:nil", "true"); | |
146 | + } else { | |
147 | + characterDataSigElm.setTextContent(cd.toSignatureString()); | |
148 | + } | |
149 | + root.appendChild(characterDataSigElm); | |
150 | + | |
151 | + // パーツカラー情報 | |
152 | + root.appendChild(writePartsColorInfoMap(doc, ws.getPartsColorInfoMap())); | |
153 | + | |
154 | + // 現在のパーツセット | |
155 | + PartsSet currentPartsSet = ws.getPartsSet(); | |
156 | + Element partsSetElm = doc.createElementNS(NS, "currentPartsSet"); | |
157 | + if (currentPartsSet == null || currentPartsSet.isEmpty()) { | |
158 | + partsSetElm.setAttributeNS(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "xsi:nil", "true"); | |
159 | + | |
160 | + } else { | |
161 | + Element elm = characterDataXmlWriter.createPartsSetXML(doc, lang, | |
162 | + currentPartsSet); | |
163 | + partsSetElm.appendChild(elm); | |
164 | + } | |
165 | + root.appendChild(partsSetElm); | |
166 | + | |
167 | + // 最後に使用した保存先ディレクトリ | |
168 | + Element lastUsedSaveDirElm = doc.createElementNS(NS, "lastUsedSaveDir"); | |
169 | + File lastUsedSaveDir = ws.getLastUsedSaveDir(); | |
170 | + if (lastUsedSaveDir == null) { | |
171 | + lastUsedSaveDirElm.setAttributeNS(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "xsi:nil", "true"); | |
172 | + | |
173 | + } else { | |
174 | + lastUsedSaveDirElm.setTextContent(lastUsedSaveDir.getPath()); | |
175 | + } | |
176 | + root.appendChild(lastUsedSaveDirElm); | |
177 | + | |
178 | + // 最後に使用したエクスポート先ディレクトリ | |
179 | + Element lastUsedExportDirElm = doc.createElementNS(NS, "lastUsedExportDir"); | |
180 | + File lastUsedExportDir = ws.getLastUsedExportDir(); | |
181 | + if (lastUsedExportDir == null) { | |
182 | + lastUsedExportDirElm.setAttributeNS(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "xsi:nil", "true"); | |
183 | + | |
184 | + } else { | |
185 | + lastUsedExportDirElm.setTextContent(lastUsedExportDir.getPath()); | |
186 | + } | |
187 | + root.appendChild(lastUsedExportDirElm); | |
188 | + | |
189 | + // 最後に使用したパーツセット情報、なければnull | |
190 | + PartsSet lastUsePresetParts = ws.getLastUsePresetParts(); | |
191 | + Element lastUsePresetPartsElm = doc.createElementNS(NS, "lastUsePresetParts"); | |
192 | + if (lastUsePresetParts == null || lastUsePresetParts.isEmpty()) { | |
193 | + lastUsePresetPartsElm.setAttributeNS(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "xsi:nil", "true"); | |
194 | + | |
195 | + } else { | |
196 | + Element elm = characterDataXmlWriter.createPartsSetXML(doc, lang, lastUsePresetParts); | |
197 | + lastUsePresetPartsElm.appendChild(elm); | |
198 | + } | |
199 | + root.appendChild(lastUsePresetPartsElm); | |
200 | + | |
201 | + // 壁紙情報 | |
202 | + root.appendChild(writeWallpaper(doc, ws.getWallpaperInfo())); | |
203 | + | |
204 | + doc.appendChild(root); | |
205 | + return doc; | |
206 | + } | |
207 | + | |
208 | + /** | |
209 | + * パーツごとのカラー情報のXML要素を生成して返します. | |
210 | + * | |
211 | + * @param doc | |
212 | + * 要素のファクトリ | |
213 | + * @param partsColorMap | |
214 | + * パーツごとのカラー情報のマップ | |
215 | + * @return パーツごとのカラー情報のXML要素 | |
216 | + */ | |
217 | + public Element writePartsColorInfoMap(Document doc, Map<PartsIdentifier, PartsColorInfo> partsColorMap) { | |
218 | + Element partsColorInfoMapElm = doc.createElementNS(NS, "partsColorInfoMap"); | |
219 | + if (partsColorMap != null) { | |
220 | + // 使用しているカラーの設定ごとに番号を振る | |
221 | + // (同じカラー設定であれば同じ番号とする.) | |
222 | + LinkedHashMap<PartsColorInfo, String> colorMap = new LinkedHashMap<PartsColorInfo, String>(); | |
223 | + for (Map.Entry<PartsIdentifier, PartsColorInfo> partsColorEntry : partsColorMap.entrySet()) { | |
224 | + PartsColorInfo partsColorInfo = partsColorEntry.getValue(); | |
225 | + if (partsColorInfo != null && !partsColorInfo.isEmpty()) { | |
226 | + if (!colorMap.containsKey(partsColorInfo)) { | |
227 | + colorMap.put(partsColorInfo, Integer.toString(colorMap.size() + 1)); | |
228 | + } | |
229 | + } | |
230 | + } | |
231 | + | |
232 | + // すべてのカラー設定を出力する. | |
233 | + Element colorsElm = doc.createElementNS(NS, "colors"); | |
234 | + for (Map.Entry<PartsColorInfo, String> colorMapEntry : colorMap.entrySet()) { | |
235 | + PartsColorInfo partsColorInfo = colorMapEntry.getKey(); | |
236 | + String id = colorMapEntry.getValue(); | |
237 | + Element partsColorElm = characterDataXmlWriter.createPartsColorInfoXML(doc, partsColorInfo); | |
238 | + partsColorElm.setAttribute("id", id); | |
239 | + colorsElm.appendChild(partsColorElm); | |
240 | + } | |
241 | + partsColorInfoMapElm.appendChild(colorsElm); | |
242 | + | |
243 | + // パーツと、そのパーツのカラー設定番号の一覧を出力する. | |
244 | + Element partsListElm = doc.createElementNS(NS, "partsList"); | |
245 | + for (Map.Entry<PartsIdentifier, PartsColorInfo> partsColorEntry : partsColorMap.entrySet()) { | |
246 | + PartsIdentifier partsIdentifier = partsColorEntry.getKey(); | |
247 | + PartsColorInfo partsColorInfo = partsColorEntry.getValue(); | |
248 | + if (partsColorInfo != null && !partsColorInfo.isEmpty()) { | |
249 | + String colorId = colorMap.get(partsColorInfo); | |
250 | + if (colorId == null) { | |
251 | + throw new RuntimeException("colorMapが不整合です"); | |
252 | + } | |
253 | + Element partsElm = doc.createElementNS(NS, "partsIdentifier"); | |
254 | + String categoryId = partsIdentifier.getPartsCategory().getCategoryId(); | |
255 | + partsElm.setAttribute("categoryId", categoryId); | |
256 | + partsElm.setAttribute("name", partsIdentifier.getPartsName()); | |
257 | + partsElm.setAttribute("colorId", colorId); | |
258 | + partsListElm.appendChild(partsElm); | |
259 | + } | |
260 | + } | |
261 | + partsColorInfoMapElm.appendChild(partsListElm); | |
262 | + } | |
263 | + return partsColorInfoMapElm; | |
264 | + } | |
265 | + | |
266 | + /** | |
267 | + * 壁紙情報をXML要素として生成する. | |
268 | + * | |
269 | + * @param doc | |
270 | + * XML要素のファクトリ | |
271 | + * @param wallpaperInfo | |
272 | + * 壁紙情報 | |
273 | + * @return 壁紙情報のXML要素 | |
274 | + */ | |
275 | + public Element writeWallpaper(Document doc, WallpaperInfo wallpaperInfo) { | |
276 | + Element elm = doc.createElementNS(NS, "wallpaperInfo"); | |
277 | + | |
278 | + if (wallpaperInfo == null) { | |
279 | + elm.setAttributeNS(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "xsi:nil", "true"); | |
280 | + | |
281 | + } else { | |
282 | + // タイプ | |
283 | + WallpaperResourceType typ = wallpaperInfo.getType(); | |
284 | + Element typElm = doc.createElementNS(NS, "type"); | |
285 | + typElm.setTextContent(typ.name()); | |
286 | + elm.appendChild(typElm); | |
287 | + | |
288 | + // リソース | |
289 | + String res = wallpaperInfo.getResource(); | |
290 | + Element resElm = doc.createElementNS(NS, "resource"); | |
291 | + if (res == null || res.trim().length() == 0) { | |
292 | + resElm.setAttributeNS(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "xsi:nil", "true"); | |
293 | + } else { | |
294 | + resElm.setTextContent(res); | |
295 | + } | |
296 | + elm.appendChild(resElm); | |
297 | + | |
298 | + // ファイル | |
299 | + File file = wallpaperInfo.getFile(); | |
300 | + Element fileElm = doc.createElementNS(NS, "file"); | |
301 | + if (file == null) { | |
302 | + fileElm.setAttributeNS(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "xsi:nil", "true"); | |
303 | + } else { | |
304 | + fileElm.setTextContent(file.getPath()); | |
305 | + } | |
306 | + elm.appendChild(fileElm); | |
307 | + | |
308 | + // アルファ | |
309 | + float alpha = wallpaperInfo.getAlpha(); | |
310 | + Element alphaElm = doc.createElementNS(NS, "alpha"); | |
311 | + alphaElm.setTextContent(Float.toString(alpha)); | |
312 | + elm.appendChild(alphaElm); | |
313 | + | |
314 | + // 背景色 | |
315 | + Color backgroundColor = wallpaperInfo.getBackgroundColor(); | |
316 | + Element bgColorElm = doc.createElementNS(NS, "backgroundColor"); | |
317 | + bgColorElm.setTextContent("#" + Integer.toHexString(backgroundColor.getRGB() & 0xffffff)); | |
318 | + elm.appendChild(bgColorElm); | |
319 | + } | |
320 | + | |
321 | + return elm; | |
322 | + } | |
323 | + | |
324 | +} |
@@ -46,6 +46,7 @@ | ||
46 | 46 | import charactermanaj.util.FileNameNormalizer; |
47 | 47 | import charactermanaj.util.FileUserData; |
48 | 48 | import charactermanaj.util.UserData; |
49 | +import charactermanaj.util.UserDataFactory; | |
49 | 50 | |
50 | 51 | public class CharacterDataPersistent { |
51 | 52 |
@@ -720,10 +721,12 @@ | ||
720 | 721 | } |
721 | 722 | |
722 | 723 | // ワーキングセットの削除 |
723 | - UserData workingSetSer = MainFrame.getWorkingSetUserData(cd, true); | |
724 | - if (workingSetSer != null && workingSetSer.exists()) { | |
725 | - logger.log(Level.INFO, "remove file: " + workingSetSer); | |
726 | - workingSetSer.delete(); | |
724 | + UserDataFactory userDataFactory = UserDataFactory.getInstance(); | |
725 | + UserData workingSetXmlData = userDataFactory.getMangledNamedUserData( | |
726 | + cd.getDocBase(), MainFrame.WORKINGSET_FILE_SUFFIX); | |
727 | + if (workingSetXmlData != null && workingSetXmlData.exists()) { | |
728 | + logger.log(Level.INFO, "remove file: " + workingSetXmlData); | |
729 | + workingSetXmlData.delete(); | |
727 | 730 | } |
728 | 731 | |
729 | 732 | // xmlファイルの拡張子を変更することでキャラクター定義として認識させない. |
@@ -12,8 +12,10 @@ | ||
12 | 12 | import java.net.URI; |
13 | 13 | import java.net.URL; |
14 | 14 | import java.util.ArrayList; |
15 | +import java.util.HashMap; | |
15 | 16 | import java.util.List; |
16 | 17 | import java.util.Locale; |
18 | +import java.util.Map; | |
17 | 19 | import java.util.logging.Level; |
18 | 20 | import java.util.logging.Logger; |
19 | 21 |
@@ -25,11 +27,11 @@ | ||
25 | 27 | import charactermanaj.graphics.filters.ColorConvertParameter; |
26 | 28 | import charactermanaj.model.CharacterData; |
27 | 29 | import charactermanaj.model.ColorGroup; |
28 | -import charactermanaj.model.ColorInfo; | |
30 | +import charactermanaj.model.IndependentPartsColorInfo; | |
31 | +import charactermanaj.model.IndependentPartsSetInfo; | |
32 | +import charactermanaj.model.IndependentPartsSetInfoList; | |
29 | 33 | import charactermanaj.model.Layer; |
30 | 34 | import charactermanaj.model.PartsCategory; |
31 | -import charactermanaj.model.PartsColorInfo; | |
32 | -import charactermanaj.model.PartsIdentifier; | |
33 | 35 | import charactermanaj.model.PartsSet; |
34 | 36 | import charactermanaj.model.RecommendationURL; |
35 | 37 | import charactermanaj.util.XMLUtilities; |
@@ -422,208 +424,291 @@ | ||
422 | 424 | */ |
423 | 425 | protected void loadPartsSet(CharacterData characterData, |
424 | 426 | Element nodePartssets, boolean presetParts, String lang) { |
427 | + IndependentPartsSetInfoList partsSetLst = loadPartsSetList( | |
428 | + nodePartssets, lang); | |
429 | + logger.info("partsSetList: size=" + partsSetLst.size()); | |
425 | 430 | |
431 | + if (presetParts) { | |
432 | + characterData | |
433 | + .setDefaultPartsSetId(partsSetLst.getDefaultPresetId()); | |
434 | + } | |
435 | + | |
436 | + for (IndependentPartsSetInfo partsSetInfo : partsSetLst) { | |
437 | + PartsSet partsSet = IndependentPartsSetInfo.convertPartsSet( | |
438 | + partsSetInfo, characterData, presetParts); | |
439 | + characterData.addPartsSet(partsSet); | |
440 | + } | |
441 | + } | |
442 | + | |
443 | + /** | |
444 | + * CharacterDataのプリセットまたはFavoritesのパーツセットのXMLからパーツセットを読み取って登録する.<br> | |
445 | + * | |
446 | + * @param nodePartssets | |
447 | + * パーツセットのノード、プリセットまたはパーツセットノード | |
448 | + * @param lang | |
449 | + * 言語 | |
450 | + */ | |
451 | + public IndependentPartsSetInfoList loadPartsSetList(Element nodePartssets, | |
452 | + String lang) { | |
453 | + if (nodePartssets == null || lang == null || lang.length() == 0) { | |
454 | + throw new IllegalArgumentException(); | |
455 | + } | |
456 | + | |
457 | + IndependentPartsSetInfoList partsSetLst = new IndependentPartsSetInfoList(); | |
458 | + | |
426 | 459 | // デフォルトのパーツセットID |
427 | - String defaultPresetId = nodePartssets.getAttribute("default-preset") | |
428 | - .trim(); | |
460 | + String defaultPresetId = nodePartssets.getAttribute("default-preset"); | |
461 | + if (defaultPresetId != null) { | |
462 | + defaultPresetId = defaultPresetId.trim(); | |
463 | + } | |
429 | 464 | |
430 | 465 | // パーツセットリストの読み込み |
431 | 466 | for (Element presetElm : getChildElements(nodePartssets, "preset")) { |
432 | - String partsSetId = presetElm.getAttribute("id").trim(); | |
433 | - if (defaultPresetId == null || defaultPresetId.length() == 0) { | |
434 | - defaultPresetId = partsSetId; | |
467 | + IndependentPartsSetInfo partsSetInfo = loadPartsSet(presetElm, lang); | |
468 | + if (partsSetInfo != null) { | |
469 | + String partsSetId = partsSetInfo.getId(); | |
470 | + | |
471 | + // デフォルトのパーツセットIDがない場合は先頭をデフォルトとみなす. | |
472 | + if (defaultPresetId == null || defaultPresetId.length() == 0) { | |
473 | + defaultPresetId = partsSetId; | |
474 | + } | |
475 | + | |
476 | + partsSetLst.add(partsSetInfo); | |
435 | 477 | } |
436 | - String displayName = getLocalizedElementText(presetElm, | |
437 | - "display-name", lang); | |
478 | + } | |
438 | 479 | |
439 | - PartsSet partsSet = new PartsSet(); | |
480 | + if (defaultPresetId.length() == 0) { | |
481 | + // デフォルトパーツセットがないことを示すためのnull | |
482 | + defaultPresetId = null; | |
483 | + } | |
484 | + partsSetLst.setDefaultPresetId(defaultPresetId); | |
440 | 485 | |
441 | - partsSet.setPartsSetId(partsSetId); | |
442 | - partsSet.setLocalizedName(displayName); | |
443 | - partsSet.setPresetParts(presetParts); | |
486 | + return partsSetLst; | |
487 | + } | |
444 | 488 | |
445 | - // bgColor | |
446 | - Element bgColorElm = getFirstChildElement(presetElm, | |
447 | - "background-color"); | |
448 | - if (bgColorElm != null) { | |
449 | - String tmpBgColor = bgColorElm.getAttribute("color"); | |
450 | - try { | |
451 | - Color bgColor = Color.decode(tmpBgColor); | |
452 | - partsSet.setBgColor(bgColor); | |
489 | + /** | |
490 | + * CharacterDataのプリセットまたはFavoritesのパーツセットのXMLからパーツセットを読み取る.<br> | |
491 | + * | |
492 | + * @param nodePartssets | |
493 | + * パーツセットのノード、プリセットまたはパーツセットノード | |
494 | + * @param lang | |
495 | + * 言語 | |
496 | + * @return 素のパーツセット情報、無ければnull | |
497 | + */ | |
498 | + public IndependentPartsSetInfo loadPartsSet(Element presetElm, String lang) { | |
499 | + if (presetElm == null || lang == null) { | |
500 | + return null; | |
501 | + } | |
453 | 502 | |
454 | - } catch (Exception ex) { | |
455 | - logger.log(Level.WARNING, "bgColor parameter is invalid. :" | |
456 | - + tmpBgColor, ex); | |
457 | - // 無視する | |
503 | + IndependentPartsSetInfo partsSetInfo = new IndependentPartsSetInfo(); | |
504 | + | |
505 | + // id | |
506 | + String partsSetId = presetElm.getAttribute("id"); | |
507 | + if (partsSetId != null) { | |
508 | + partsSetId = partsSetId.trim(); | |
509 | + } | |
510 | + if (partsSetId != null && partsSetId.length() == 0) { | |
511 | + partsSetId = null; | |
512 | + } | |
513 | + partsSetInfo.setId(partsSetId); | |
514 | + | |
515 | + // display-name | |
516 | + String displayName = getLocalizedElementText(presetElm, "display-name", | |
517 | + lang); | |
518 | + partsSetInfo.setDisplayName(displayName); | |
519 | + | |
520 | + // bgColor | |
521 | + Element bgColorElm = getFirstChildElement(presetElm, "background-color"); | |
522 | + if (bgColorElm != null) { | |
523 | + String tmpBgColor = bgColorElm.getAttribute("color"); | |
524 | + try { | |
525 | + Color bgColor = Color.decode(tmpBgColor); | |
526 | + partsSetInfo.setBackgroundColor(bgColor); | |
527 | + | |
528 | + } catch (Exception ex) { | |
529 | + logger.log(Level.WARNING, "bgColor parameter is invalid. :" | |
530 | + + tmpBgColor, ex); | |
531 | + // 無視する | |
532 | + } | |
533 | + } | |
534 | + | |
535 | + // affine-transform-parameter | |
536 | + String tmpAffienTrans = getElementText(presetElm, | |
537 | + "affine-transform-parameter"); | |
538 | + if (tmpAffienTrans != null && tmpAffienTrans.trim().length() > 0) { | |
539 | + try { | |
540 | + ArrayList<Double> affineTransformParameterArr = new ArrayList<Double>(); | |
541 | + for (String strParam : tmpAffienTrans.split("\\s+")) { | |
542 | + affineTransformParameterArr.add(Double.valueOf(strParam)); | |
458 | 543 | } |
544 | + double[] affineTransformParameter = new double[affineTransformParameterArr | |
545 | + .size()]; | |
546 | + int idx = 0; | |
547 | + for (double aaffineItem : affineTransformParameterArr) { | |
548 | + affineTransformParameter[idx++] = aaffineItem; | |
549 | + } | |
550 | + partsSetInfo | |
551 | + .setAffineTransformParameter(affineTransformParameter); | |
552 | + | |
553 | + } catch (Exception ex) { | |
554 | + logger.log(Level.WARNING, | |
555 | + "affine transform parameter is invalid. :" | |
556 | + + tmpAffienTrans, ex); | |
557 | + // 無視する. | |
459 | 558 | } |
559 | + } | |
460 | 560 | |
461 | - // affine-transform-parameter | |
462 | - String tmpAffienTrans = getElementText(presetElm, | |
463 | - "affine-transform-parameter"); | |
464 | - if (tmpAffienTrans != null && tmpAffienTrans.trim().length() > 0) { | |
465 | - try { | |
466 | - ArrayList<Double> affineTransformParameterArr = new ArrayList<Double>(); | |
467 | - for (String strParam : tmpAffienTrans.split("\\s+")) { | |
468 | - affineTransformParameterArr.add(Double | |
469 | - .valueOf(strParam)); | |
470 | - } | |
471 | - double[] affineTransformParameter = new double[affineTransformParameterArr | |
472 | - .size()]; | |
473 | - int idx = 0; | |
474 | - for (double aaffineItem : affineTransformParameterArr) { | |
475 | - affineTransformParameter[idx++] = aaffineItem; | |
476 | - } | |
477 | - partsSet.setAffineTransformParameter(affineTransformParameter); | |
561 | + // カテゴリIDをキーとし、パーツ名をキーとしカラー情報のリストを値とするマップを値とする. | |
562 | + Map<String, Map<String, List<IndependentPartsColorInfo>>> partsMap = partsSetInfo | |
563 | + .getPartsMap(); | |
478 | 564 | |
479 | - } catch (Exception ex) { | |
480 | - logger.log(Level.WARNING, | |
481 | - "affine transform parameter is invalid. :" | |
482 | - + tmpAffienTrans, ex); | |
483 | - // 無視する. | |
484 | - } | |
565 | + // Category | |
566 | + for (Element catElm : getChildElements(presetElm, "category")) { | |
567 | + String categoryId = catElm.getAttribute("refid"); | |
568 | + if (categoryId != null) { | |
569 | + categoryId = categoryId.trim(); | |
485 | 570 | } |
571 | + if (categoryId == null || categoryId.length() == 0) { | |
572 | + logger.log(Level.WARNING, "missing category refid: " + catElm); | |
573 | + continue; | |
574 | + } | |
486 | 575 | |
487 | - // Category | |
488 | - for (Element catElm : getChildElements(presetElm, "category")) { | |
489 | - String categoryId = catElm.getAttribute("refid").trim(); | |
490 | - PartsCategory category = characterData | |
491 | - .getPartsCategory(categoryId); | |
492 | - if (category == null) { | |
493 | - System.err.println("undefined category: " + categoryId); | |
576 | + // パーツ名をキーとしカラー情報のリストを値とするマップ. | |
577 | + Map<String, List<IndependentPartsColorInfo>> categoryPartsMap = partsMap | |
578 | + .get(categoryId); | |
579 | + if (categoryPartsMap == null) { | |
580 | + categoryPartsMap = new HashMap<String, List<IndependentPartsColorInfo>>(); | |
581 | + partsMap.put(categoryId, categoryPartsMap); | |
582 | + } | |
583 | + | |
584 | + // Parts | |
585 | + for (Element partsElm : getChildElements(catElm, "parts")) { | |
586 | + String partsName = partsElm.getAttribute("name"); | |
587 | + if (partsName != null) { | |
588 | + partsName = partsName.trim(); | |
589 | + } | |
590 | + if (partsName == null || partsName.length() == 0) { | |
591 | + logger.log(Level.WARNING, "missing parts name. " + partsElm); | |
494 | 592 | continue; |
495 | 593 | } |
496 | 594 | |
497 | - // Parts | |
498 | - for (Element partsElm : getChildElements(catElm, "parts")) { | |
499 | - String partsName = partsElm.getAttribute("name").trim(); | |
595 | + // Color/Layer | |
596 | + List<IndependentPartsColorInfo> infoList = null; | |
597 | + for (Element colorElm : getChildElements(partsElm, "color")) { | |
598 | + infoList = readPartsColor(colorElm); | |
599 | + break; | |
600 | + } | |
601 | + categoryPartsMap.put(partsName, infoList); | |
602 | + } | |
603 | + } | |
604 | + return partsSetInfo; | |
605 | + } | |
500 | 606 | |
501 | - PartsIdentifier partsIdentifier = new PartsIdentifier( | |
502 | - category, partsName, partsName); | |
607 | + /** | |
608 | + * パーツごとのカラー情報のXMLを読み込んで返す.<br> | |
609 | + * パーツは複数のレイヤーから構成されるので、複数レイヤーのカラー情報のリストとして返される.<br> | |
610 | + * (パーツは複数レイヤーをまとめる1つのカテゴリになるので、カテゴリ単位の情報となる.)<br> | |
611 | + * | |
612 | + * @param colorElm | |
613 | + * カラーのXML要素 | |
614 | + * @return 素のカラー情報 | |
615 | + */ | |
616 | + public List<IndependentPartsColorInfo> readPartsColor(Element colorElm) { | |
617 | + if (colorElm == null) { | |
618 | + throw new IllegalArgumentException(); | |
619 | + } | |
503 | 620 | |
504 | - // Color/Layer | |
505 | - PartsColorInfo partsColorInfo = null; | |
506 | - for (Element colorElm : getChildElements(partsElm, "color")) { | |
507 | - for (Element layerElm : getChildElements(colorElm, | |
508 | - "layer")) { | |
509 | - String layerId = layerElm.getAttribute("refid") | |
510 | - .trim(); | |
511 | - Layer layer = category.getLayer(layerId); | |
512 | - if (layer == null) { | |
513 | - logger.log(Level.WARNING, "undefined layer: " | |
514 | - + layerId); | |
515 | - continue; | |
516 | - } | |
621 | + ArrayList<IndependentPartsColorInfo> infoList = new ArrayList<IndependentPartsColorInfo>(); | |
622 | + for (Element layerElm : getChildElements(colorElm, "layer")) { | |
623 | + IndependentPartsColorInfo info = new IndependentPartsColorInfo(); | |
517 | 624 | |
518 | - if (partsColorInfo == null) { | |
519 | - partsColorInfo = new PartsColorInfo(category); | |
520 | - } | |
521 | - ColorInfo colorInfo = partsColorInfo.get(layer); | |
625 | + String layerId = layerElm.getAttribute("refid"); | |
626 | + if (layerId != null) { | |
627 | + layerId = layerId.trim(); | |
628 | + } | |
629 | + if (layerId == null || layerId.length() == 0) { | |
630 | + logger.log(Level.WARNING, "missing layer-id: " + layerElm); | |
631 | + continue; | |
632 | + } | |
633 | + info.setLayerId(layerId); | |
522 | 634 | |
523 | - // color-group | |
524 | - Element colorGroupElm = getFirstChildElement( | |
525 | - layerElm, "color-group"); | |
526 | - if (colorGroupElm != null) { | |
527 | - ColorGroup colorGroup = characterData | |
528 | - .getColorGroup(colorGroupElm | |
529 | - .getAttribute("group").trim()); | |
530 | - boolean syncColorGroup = Boolean | |
531 | - .parseBoolean(colorGroupElm | |
532 | - .getAttribute("synchronized") | |
533 | - .trim()); | |
534 | - colorInfo.setColorGroup(colorGroup); | |
535 | - colorInfo.setSyncColorGroup(syncColorGroup); | |
536 | - } | |
635 | + // color-group | |
636 | + Element colorGroupElm = getFirstChildElement(layerElm, | |
637 | + "color-group"); | |
638 | + if (colorGroupElm != null) { | |
639 | + String colorGroupId = colorGroupElm.getAttribute("group") | |
640 | + .trim(); | |
641 | + info.setColorGroupId(colorGroupId); | |
642 | + boolean syncColorGroup = Boolean.parseBoolean(colorGroupElm | |
643 | + .getAttribute("synchronized").trim()); | |
644 | + info.setSyncColorGroup(syncColorGroup); | |
645 | + } | |
537 | 646 | |
538 | - // rgb | |
539 | - ColorConvertParameter param = colorInfo | |
540 | - .getColorParameter(); | |
541 | - Element nodeRgb = getFirstChildElement(layerElm, | |
542 | - "rgb"); | |
543 | - if (nodeRgb != null) { | |
544 | - for (Element elmRgb : getChildElements(nodeRgb, | |
545 | - null)) { | |
546 | - String rgbName = elmRgb.getNodeName(); | |
547 | - int offset = Integer.parseInt(elmRgb | |
548 | - .getAttribute("offset")); | |
549 | - float factor = Float.parseFloat(elmRgb | |
550 | - .getAttribute("factor")); | |
551 | - float gamma = Float.parseFloat(elmRgb | |
552 | - .getAttribute("gamma")); | |
553 | - if ("red".equals(rgbName)) { | |
554 | - param.setOffsetR(offset); | |
555 | - param.setFactorR(factor); | |
556 | - param.setGammaR(gamma); | |
557 | - } else if ("green".equals(rgbName)) { | |
558 | - param.setOffsetG(offset); | |
559 | - param.setFactorG(factor); | |
560 | - param.setGammaG(gamma); | |
561 | - } else if ("blue".equals(rgbName)) { | |
562 | - param.setOffsetB(offset); | |
563 | - param.setFactorB(factor); | |
564 | - param.setGammaB(gamma); | |
565 | - } else if ("alpha".equals(rgbName)) { | |
566 | - param.setOffsetA(offset); | |
567 | - param.setFactorA(factor); | |
568 | - param.setGammaA(gamma); | |
569 | - } | |
570 | - } | |
571 | - } | |
572 | - | |
573 | - // hsb | |
574 | - Element elmHsb = getFirstChildElement(layerElm, | |
575 | - "hsb"); | |
576 | - if (elmHsb != null) { | |
577 | - float hue = Float.parseFloat(elmHsb | |
578 | - .getAttribute("hue")); | |
579 | - float saturation = Float.parseFloat(elmHsb | |
580 | - .getAttribute("saturation")); | |
581 | - float brightness = Float.parseFloat(elmHsb | |
582 | - .getAttribute("brightness")); | |
583 | - String strContrast = elmHsb.getAttribute( | |
584 | - "contrast").trim(); | |
585 | - param.setHue(hue); | |
586 | - param.setSaturation(saturation); | |
587 | - param.setBrightness(brightness); | |
588 | - if (strContrast != null | |
589 | - && strContrast.length() > 0) { | |
590 | - // ver0.96追加 optional | |
591 | - float contrast = Float | |
592 | - .parseFloat(strContrast); | |
593 | - param.setContrast(contrast); | |
594 | - } | |
595 | - } | |
596 | - | |
597 | - // rgb-replace | |
598 | - Element elmRgbReplace = getFirstChildElement( | |
599 | - layerElm, "rgb-replace"); | |
600 | - if (elmRgbReplace != null) { | |
601 | - Float grayLevel = Float | |
602 | - .parseFloat(elmRgbReplace | |
603 | - .getAttribute("gray")); | |
604 | - ColorConv colorType = ColorConv | |
605 | - .valueOf(elmRgbReplace | |
606 | - .getAttribute("replace-type")); | |
607 | - param.setGrayLevel(grayLevel); | |
608 | - param.setColorReplace(colorType); | |
609 | - } | |
610 | - } | |
647 | + // rgb | |
648 | + ColorConvertParameter param = info.getColorConvertParameter(); | |
649 | + Element nodeRgb = getFirstChildElement(layerElm, "rgb"); | |
650 | + if (nodeRgb != null) { | |
651 | + for (Element elmRgb : getChildElements(nodeRgb, null)) { | |
652 | + String rgbName = elmRgb.getNodeName(); | |
653 | + int offset = Integer | |
654 | + .parseInt(elmRgb.getAttribute("offset")); | |
655 | + float factor = Float.parseFloat(elmRgb | |
656 | + .getAttribute("factor")); | |
657 | + float gamma = Float | |
658 | + .parseFloat(elmRgb.getAttribute("gamma")); | |
659 | + if ("red".equals(rgbName)) { | |
660 | + param.setOffsetR(offset); | |
661 | + param.setFactorR(factor); | |
662 | + param.setGammaR(gamma); | |
663 | + } else if ("green".equals(rgbName)) { | |
664 | + param.setOffsetG(offset); | |
665 | + param.setFactorG(factor); | |
666 | + param.setGammaG(gamma); | |
667 | + } else if ("blue".equals(rgbName)) { | |
668 | + param.setOffsetB(offset); | |
669 | + param.setFactorB(factor); | |
670 | + param.setGammaB(gamma); | |
671 | + } else if ("alpha".equals(rgbName)) { | |
672 | + param.setOffsetA(offset); | |
673 | + param.setFactorA(factor); | |
674 | + param.setGammaA(gamma); | |
611 | 675 | } |
612 | - partsSet.appendParts(category, partsIdentifier, | |
613 | - partsColorInfo); | |
614 | 676 | } |
615 | 677 | } |
616 | 678 | |
617 | - characterData.addPartsSet(partsSet); | |
618 | - } | |
679 | + // hsb | |
680 | + Element elmHsb = getFirstChildElement(layerElm, "hsb"); | |
681 | + if (elmHsb != null) { | |
682 | + float hue = Float.parseFloat(elmHsb.getAttribute("hue")); | |
683 | + float saturation = Float.parseFloat(elmHsb | |
684 | + .getAttribute("saturation")); | |
685 | + float brightness = Float.parseFloat(elmHsb | |
686 | + .getAttribute("brightness")); | |
687 | + String strContrast = elmHsb.getAttribute("contrast").trim(); | |
688 | + param.setHue(hue); | |
689 | + param.setSaturation(saturation); | |
690 | + param.setBrightness(brightness); | |
691 | + if (strContrast != null && strContrast.length() > 0) { | |
692 | + // ver0.96追加 optional | |
693 | + float contrast = Float.parseFloat(strContrast); | |
694 | + param.setContrast(contrast); | |
695 | + } | |
696 | + } | |
619 | 697 | |
620 | - if (presetParts) { | |
621 | - if (defaultPresetId.length() == 0) { | |
622 | - // デフォルトパーツセットがないことを示すためのnull | |
623 | - defaultPresetId = null; | |
698 | + // rgb-replace | |
699 | + Element elmRgbReplace = getFirstChildElement(layerElm, | |
700 | + "rgb-replace"); | |
701 | + if (elmRgbReplace != null) { | |
702 | + Float grayLevel = Float.parseFloat(elmRgbReplace | |
703 | + .getAttribute("gray")); | |
704 | + ColorConv colorType = ColorConv.valueOf(elmRgbReplace | |
705 | + .getAttribute("replace-type")); | |
706 | + param.setGrayLevel(grayLevel); | |
707 | + param.setColorReplace(colorType); | |
624 | 708 | } |
625 | - characterData.setDefaultPartsSetId(defaultPresetId); | |
709 | + | |
710 | + infoList.add(info); | |
626 | 711 | } |
712 | + return infoList; | |
627 | 713 | } |
628 | - | |
629 | 714 | } |
@@ -0,0 +1,63 @@ | ||
1 | +package charactermanaj.model; | |
2 | + | |
3 | +import java.util.ArrayList; | |
4 | + | |
5 | +/** | |
6 | + * 素のパーツセットのコレクション.<br> | |
7 | + * レイヤーやカテゴリなどのリレーションシップがない、<br> | |
8 | + * 特定のキャラクターデータモデルのツリーの一部には組み込まれていない状態のもの.<br> | |
9 | + */ | |
10 | +public class IndependentPartsSetInfoList | |
11 | + extends | |
12 | + ArrayList<IndependentPartsSetInfo> { | |
13 | + | |
14 | + /** | |
15 | + * シリアライズバージョンID | |
16 | + */ | |
17 | + private static final long serialVersionUID = -6121741586284912547L; | |
18 | + | |
19 | + /** | |
20 | + * デフォルトのパーツセットID.<br> | |
21 | + * ない場合はnull.<br> | |
22 | + */ | |
23 | + private String defaultPresetId; | |
24 | + | |
25 | + public String getDefaultPresetId() { | |
26 | + return defaultPresetId; | |
27 | + } | |
28 | + | |
29 | + /** | |
30 | + * デフォルトパーツセットIDを設定する.<br> | |
31 | + * nullはパーツセットIDがないことを示す.<br> | |
32 | + * 空文字はnullとみなされる.<br> | |
33 | + * | |
34 | + * @param defaultPresetId | |
35 | + */ | |
36 | + public void setDefaultPresetId(String defaultPresetId) { | |
37 | + if (defaultPresetId != null) { | |
38 | + defaultPresetId = defaultPresetId.trim(); | |
39 | + if (defaultPresetId.length() == 0) { | |
40 | + // デフォルトパーツセットがないことを示すためのnull | |
41 | + defaultPresetId = null; | |
42 | + } | |
43 | + } | |
44 | + this.defaultPresetId = defaultPresetId; | |
45 | + } | |
46 | + | |
47 | + @Override | |
48 | + public boolean add(IndependentPartsSetInfo o) { | |
49 | + if (o == null) { | |
50 | + throw new IllegalArgumentException(); | |
51 | + } | |
52 | + return super.add(o); | |
53 | + } | |
54 | + | |
55 | + @Override | |
56 | + public IndependentPartsSetInfo set(int index, | |
57 | + IndependentPartsSetInfo element) { | |
58 | + if (element == null) { | |
59 | + throw new IllegalArgumentException(); | |
60 | + } | |
61 | + return super.set(index, element); | |
62 | + } | |
63 | +} | |
\ No newline at end of file |
@@ -27,6 +27,9 @@ | ||
27 | 27 | |
28 | 28 | private String characterDataRev; |
29 | 29 | |
30 | + /** | |
31 | + * 現在の選択中のパーツと色設定からのパーツセット | |
32 | + */ | |
30 | 33 | private PartsSet partsSet; |
31 | 34 | |
32 | 35 | private URI characterDocBase; |
@@ -47,9 +50,13 @@ | ||
47 | 50 | |
48 | 51 | /** |
49 | 52 | * デシリアライズ |
50 | - * @param inp オブジェクトの復元ストリーム | |
51 | - * @throws IOException 例外 | |
52 | - * @throws ClassNotFoundException 例外 | |
53 | + * | |
54 | + * @param inp | |
55 | + * オブジェクトの復元ストリーム | |
56 | + * @throws IOException | |
57 | + * 例外 | |
58 | + * @throws ClassNotFoundException | |
59 | + * 例外 | |
53 | 60 | */ |
54 | 61 | @SuppressWarnings("unchecked") |
55 | 62 | private void readObject(ObjectInputStream inp) throws IOException, |
@@ -96,6 +103,7 @@ | ||
96 | 103 | * REV情報.<br> |
97 | 104 | * キャラクターデータが設定されていない場合に使用される.<br> |
98 | 105 | * (ver0.96以前旧シリアライズデータ互換用)<br> |
106 | + * | |
99 | 107 | * @return |
100 | 108 | */ |
101 | 109 | public String getCharacterDataRev() { |
@@ -147,6 +155,7 @@ | ||
147 | 155 | * 最後に使用したお気に入りの情報.<br> |
148 | 156 | * 一度もプリセットを使ってなければnull.<br> |
149 | 157 | * ver0.94以前には存在しなかったため、nullになりえます。 |
158 | + * | |
150 | 159 | * @return |
151 | 160 | */ |
152 | 161 | public PartsSet getLastUsePresetParts() { |
@@ -154,10 +163,10 @@ | ||
154 | 163 | } |
155 | 164 | |
156 | 165 | /** |
157 | - /** | |
158 | - * 最後に使用したお気に入りの情報.<br> | |
166 | + * /** 最後に使用したお気に入りの情報.<br> | |
159 | 167 | * 一度もプリセットを使ってなければnull.<br> |
160 | 168 | * (ver0.94以前には存在しなかったため、nullになりえます。) |
169 | + * | |
161 | 170 | * @param lastUsePresetParts |
162 | 171 | */ |
163 | 172 | public void setLastUsePresetParts(PartsSet lastUsePresetParts) { |
@@ -171,6 +180,7 @@ | ||
171 | 180 | /** |
172 | 181 | * 使用していたキャラクター定義を取得します.<br> |
173 | 182 | * ver0.95よりも以前には存在しないため、nullとなりえます.<br> |
183 | + * | |
174 | 184 | * @return キャラクターデータ |
175 | 185 | */ |
176 | 186 | public CharacterData getCharacterData() { |
@@ -180,6 +190,7 @@ | ||
180 | 190 | /** |
181 | 191 | * 壁紙情報を取得します.<br> |
182 | 192 | * ver0.97よりも以前には存在しないため、nullとなりえます.<br> |
193 | + * | |
183 | 194 | * @return 壁紙情報 |
184 | 195 | */ |
185 | 196 | public WallpaperInfo getWallpaperInfo() { |
@@ -1,12 +1,19 @@ | ||
1 | 1 | package charactermanaj.model.util; |
2 | 2 | |
3 | 3 | import java.io.File; |
4 | +import java.io.FileFilter; | |
5 | +import java.io.OutputStream; | |
6 | +import java.net.URI; | |
4 | 7 | import java.util.logging.Level; |
5 | 8 | import java.util.logging.Logger; |
6 | 9 | |
7 | 10 | import charactermanaj.model.AppConfig; |
11 | +import charactermanaj.model.WorkingSet; | |
12 | +import charactermanaj.model.io.WorkingSetXMLWriter; | |
13 | +import charactermanaj.ui.MainFrame; | |
8 | 14 | import charactermanaj.ui.RecentCharactersDir; |
9 | 15 | import charactermanaj.util.FileUserData; |
16 | +import charactermanaj.util.UserData; | |
10 | 17 | import charactermanaj.util.UserDataFactory; |
11 | 18 | |
12 | 19 |
@@ -33,10 +40,8 @@ | ||
33 | 40 | public void doStartup() { |
34 | 41 | StartupSupport[] startups = { |
35 | 42 | new PurgeOldLogs(), |
36 | - // new UpgradeCache(), | |
37 | - // new UpgradeFavoritesXml(), | |
38 | - // new PurgeUnusedCache(), | |
39 | 43 | new ConvertRecentCharDirsSerToXmlProps(), |
44 | + new ConvertWorkingSetSerToXml(), | |
40 | 45 | }; |
41 | 46 | for (StartupSupport startup : startups) { |
42 | 47 | logger.log(Level.FINE, "startup operation start. class=" |
@@ -100,363 +105,75 @@ | ||
100 | 105 | } |
101 | 106 | } |
102 | 107 | |
103 | -// /** | |
104 | -// * 古い形式のCacheを移動する. | |
105 | -// * | |
106 | -// * @author seraphy | |
107 | -// * | |
108 | -// */ | |
109 | -// class UpgradeCache extends StartupSupport { | |
110 | -// | |
111 | -// /** | |
112 | -// * ロガー | |
113 | -// */ | |
114 | -// private final Logger logger = Logger.getLogger(getClass().getName()); | |
115 | -// | |
116 | -// @Override | |
117 | -// public void doStartup() { | |
118 | -// UserDataFactory userDataFactory = UserDataFactory.getInstance(); | |
119 | -// File appData = userDataFactory.getSpecialDataDir(null); | |
120 | -// | |
121 | -// // ver0.94まではユーザディレクトリ直下に*.serファイルを配置していたが、 | |
122 | -// // ver0.95以降はcachesに移動したため、旧ファイルがのこっていれば移動する. | |
123 | -// for (File file : appData.listFiles()) { | |
124 | -// try { | |
125 | -// String name = file.getName(); | |
126 | -// if (file.isFile() && name.endsWith(".ser")) { | |
127 | -// File toDir = userDataFactory.getSpecialDataDir(name); | |
128 | -// if ( !appData.equals(toDir)) { | |
129 | -// String convertedName = convertName(name); | |
130 | -// File toFile = new File(toDir, convertedName); | |
131 | -// boolean ret = file.renameTo(toFile); | |
132 | -// logger.log(Level.INFO, "move file " + file + " to " + toFile + " ;successed=" | |
133 | -// + ret); | |
134 | -// } | |
135 | -// } | |
136 | -// } catch (Exception ex) { | |
137 | -// logger.log(Level.WARNING, "file move failed. " + file, ex); | |
138 | -// } | |
139 | -// } | |
140 | -// } | |
141 | -// | |
142 | -// protected String convertName(String name) { | |
143 | -// if (name.endsWith("-workingset.ser") || name.endsWith("-favorites.ser")) { | |
144 | -// // {UUID}-CharacterID-workingset.ser もしくは、-favorites.serの場合は、 | |
145 | -// // {UUID}-workingset.ser / {UUID}-favorites.serに変更する. | |
146 | -// String[] splitedName = name.split("-"); | |
147 | -// if (splitedName.length >= 7) { | |
148 | -// StringBuilder buf = new StringBuilder(); | |
149 | -// for (int idx = 0; idx < 5; idx++) { | |
150 | -// if (idx > 0) { | |
151 | -// buf.append("-"); | |
152 | -// } | |
153 | -// buf.append(splitedName[idx]); | |
154 | -// } | |
155 | -// buf.append("-"); | |
156 | -// buf.append(splitedName[splitedName.length - 1]); | |
157 | -// return buf.toString(); | |
158 | -// } | |
159 | -// } | |
160 | -// return name; | |
161 | -// } | |
162 | -// } | |
108 | +/** | |
109 | + * シリアライズによるキャラクターディレクトリリストの保存をXML形式のPropertiesにアップグレードします。 | |
110 | + * | |
111 | + * @author seraphy | |
112 | + * | |
113 | + */ | |
114 | +class ConvertWorkingSetSerToXml extends StartupSupport { | |
115 | + /** | |
116 | + * ロガー | |
117 | + */ | |
118 | + private final Logger logger = Logger.getLogger(getClass().getName()); | |
163 | 119 | |
164 | -// /** | |
165 | -// * DocBaseのハッシュ値をもとにしたデータをサポートする抽象クラス. | |
166 | -// * | |
167 | -// * @author seraphy | |
168 | -// * | |
169 | -// */ | |
170 | -// abstract class StartupSupportForDocBasedData extends StartupSupport { | |
171 | -// | |
172 | -// /** | |
173 | -// * character.xmlのファイル位置を示すUUID表現を算定するためのアルゴリズムの選択肢.<br> | |
174 | -// * | |
175 | -// * @author seraphy | |
176 | -// */ | |
177 | -// protected enum DocBaseSignatureStoratage { | |
178 | -// | |
179 | -// /** | |
180 | -// * 新形式のcharacter.xmlのUUIDを取得(もしくは生成)する. | |
181 | -// * charatcer.xmlファイルのURIを文字列にしたもののタイプ3-UUID表現.<br> | |
182 | -// */ | |
183 | -// NEW_FORMAT() { | |
184 | -// @Override | |
185 | -// public Map<File, String> getDocBaseSignature(Collection<File> | |
186 | -// characterXmlFiles) { | |
187 | -// HashMap<URI, File> uris = new HashMap<URI, File>(); | |
188 | -// for (File characterXmlFile : characterXmlFiles) { | |
189 | -// uris.put(characterXmlFile.toURI(), characterXmlFile); | |
190 | -// } | |
191 | -// UserDataFactory userDataFactory = UserDataFactory.getInstance(); | |
192 | -// HashMap<File, String> results = new HashMap<File, String>(); | |
193 | -// File storeDir = userDataFactory.getSpecialDataDir("*.ser"); | |
194 | -// for (Map.Entry<URI, String> entry : userDataFactory | |
195 | -// .getMangledNameMap(uris.keySet(), storeDir, true).entrySet()) { | |
196 | -// File characterXmlFile = uris.get(entry.getKey()); | |
197 | -// String mangledName = entry.getValue(); | |
198 | -// results.put(characterXmlFile, mangledName); | |
199 | -// } | |
200 | -// return results; | |
201 | -// } | |
202 | -// }, | |
203 | -// | |
204 | -// /** | |
205 | -// * 旧形式のcharacter.xmlのUUIDを取得する.<br> | |
206 | -// * charatcer.xmlファイルのURLを文字列にしたもののタイプ3-UUID表現.<br> | |
207 | -// */ | |
208 | -// OLD_FORMAT() { | |
209 | -// @Override | |
210 | -// public Map<File, String> getDocBaseSignature(Collection<File> | |
211 | -// characterXmlFiles) { | |
212 | -// HashMap<File, String> results = new HashMap<File, String>(); | |
213 | -// for (File characterXmlFile : characterXmlFiles) { | |
214 | -// String mangledName; | |
215 | -// try { | |
216 | -// @SuppressWarnings("deprecation") | |
217 | -// URL url = characterXmlFile.toURL(); | |
218 | -// mangledName = UUID.nameUUIDFromBytes(url.toString().getBytes()).toString(); | |
219 | -// | |
220 | -// } catch (Exception ex) { | |
221 | -// logger.log(Level.WARNING, | |
222 | -// "character.xmlのファイル位置をUUID化できません。:" | |
223 | -// + characterXmlFile, ex); | |
224 | -// mangledName = null; | |
225 | -// } | |
226 | -// results.put(characterXmlFile, mangledName); | |
227 | -// } | |
228 | -// return results; | |
229 | -// } | |
230 | -// }, | |
231 | -// ; | |
232 | -// | |
233 | -// /** | |
234 | -// * ロガー | |
235 | -// */ | |
236 | -// private static Logger logger = Logger.getLogger( | |
237 | -// DocBaseSignatureStoratage.class.getName()); | |
238 | -// | |
239 | -// /** | |
240 | -// * character.xmlからuuid表現のプレフィックスを算定する. | |
241 | -// * | |
242 | -// * @param characterXmlFile | |
243 | -// * character.xmlのファイルのコレクション | |
244 | -// * @return character.xmlファイルと、それに対応するUUIDのマップ、(UUIDは該当がなければnull) | |
245 | -// */ | |
246 | -// public abstract Map<File, String> getDocBaseSignature(Collection<File> | |
247 | -// characterXmlFiles); | |
248 | -// } | |
249 | -// | |
250 | -// /** | |
251 | -// * すべてのユーザおよびシステムのキャラクターデータのDocBaseをもととした、 | |
252 | -// * キャッシュディレクトリ上のハッシュ値(Prefix)の文字列をキーとし、 そのキャラクターディレクトリを値とするマップを返す.<br> | |
253 | -// * (新タイプの場合は実在するcharacter.xmlに対するmangledNameが生成され登録される.)<br> | |
254 | -// * | |
255 | -// * @param storatage | |
256 | -// * ハッシュ値を生成する戦略(旧タイプ・新タイプのUUIDの区別のため) | |
257 | -// * @return DocBaseをもととしたハッシュ値の文字列表記をキー、キャラクターディレクトリを値とするマップ | |
258 | -// */ | |
259 | -// protected Map<String, File> getDocBaseMapInCaches(DocBaseSignatureStoratage | |
260 | -// storatage) { | |
261 | -// if (storatage == null) { | |
262 | -// throw new IllegalArgumentException(); | |
263 | -// } | |
264 | -// | |
265 | -// // キャラクターデータフォルダ | |
266 | -// DirectoryConfig dirConfig = DirectoryConfig.getInstance(); | |
267 | -// File[] charactersDirs = { | |
268 | -// dirConfig.getCharactersDir() // 現在のキャラクターデータフォルダ | |
269 | -// }; | |
270 | -// | |
271 | -// // キャラクターデータディレクトリを走査し、character.xmlファイルを収集する. | |
272 | -// ArrayList<File> characterXmlFiles = new ArrayList<File>(); | |
273 | -// for (File charactersDir : charactersDirs) { | |
274 | -// if (charactersDir == null || !charactersDir.exists() | |
275 | -// || !charactersDir.isDirectory()) { | |
276 | -// continue; | |
277 | -// } | |
278 | -// for (File characterDir : charactersDir.listFiles()) { | |
279 | -// if ( !characterDir.isDirectory()) { | |
280 | -// continue; | |
281 | -// } | |
282 | -// File characterXml = new File(characterDir, | |
283 | -// CharacterDataPersistent.CONFIG_FILE); | |
284 | -// if ( !characterXml.exists()) { | |
285 | -// continue; | |
286 | -// } | |
287 | -// characterXmlFiles.add(characterXml); | |
288 | -// } | |
289 | -// } | |
290 | -// | |
291 | -// // character.xmlファイルに対するハッシュ化文字列を取得する. | |
292 | -// Map<File, String> docBaseSigMap = | |
293 | -// storatage.getDocBaseSignature(characterXmlFiles); | |
294 | -// | |
295 | -// // ハッシュ化文字列をキーとし、そのcharacter.xmlファイルを値とするマップに変換する. | |
296 | -// HashMap<String, File> docBaseSignatures = new HashMap<String, File>(); | |
297 | -// for (Map.Entry<File, String> entry : docBaseSigMap.entrySet()) { | |
298 | -// docBaseSignatures.put(entry.getValue(), entry.getKey()); | |
299 | -// } | |
300 | -// return docBaseSignatures; | |
301 | -// } | |
302 | -// | |
303 | -// /** | |
304 | -// * 指定したディレクトリ直下にあるDocBaseのUUIDと推定される文字列で始まり、suffixで終わる | |
305 | -// * ファイルのUUIDの部分文字列をキーとし、そのファイルを値とするマップを返す. | |
306 | -// * | |
307 | -// * @param dataDir | |
308 | -// * 対象ディレクトリ | |
309 | -// * @param suffix | |
310 | -// * 対象となるファイル名の末尾文字列、nullまたは空文字の場合は全て | |
311 | -// * @return DocBaseのUUID表現と思われる部分文字列をキーとし、そのファイルを値とするマップ | |
312 | -// */ | |
313 | -// protected Map<String, File> getUUIDMangledNamedMap(File dataDir, String | |
314 | -// suffix) { | |
315 | -// if (dataDir == null || !dataDir.exists() || !dataDir.isDirectory()) { | |
316 | -// throw new IllegalArgumentException(); | |
317 | -// } | |
318 | -// | |
319 | -// Map<String, File> uuidMangledFiles = new HashMap<String, File>(); | |
320 | -// for (File file : dataDir.listFiles()) { | |
321 | -// String name = file.getName(); | |
322 | -// if (file.isFile() && (suffix == null || suffix.length() == 0 || | |
323 | -// name.endsWith(suffix))) { | |
324 | -// String[] sigParts = name.split("-"); | |
325 | -// if (sigParts.length >= 5) { | |
326 | -// // UUIDはa-b-c-d-eの5パーツになり、更に末尾に何らかの文字列が付与されるので | |
327 | -// // 区切り文字は5つ以上になる. | |
328 | -// // UUIDの部分だけ結合し直して復元する. | |
329 | -// StringBuilder sig = new StringBuilder(); | |
330 | -// for (int idx = 0; idx < 5; idx++) { | |
331 | -// if (idx != 0) { | |
332 | -// sig.append("-"); | |
333 | -// } | |
334 | -// sig.append(sigParts[idx]); | |
335 | -// } | |
336 | -// uuidMangledFiles.put(sig.toString(), file); | |
337 | -// } | |
338 | -// } | |
339 | -// } | |
340 | -// return uuidMangledFiles; | |
341 | -// } | |
342 | -// | |
343 | -// } | |
120 | + @Override | |
121 | + public void doStartup() { | |
122 | + // 旧形式(ver0.991以前) | |
123 | + UserDataFactory userDataFactory = UserDataFactory.getInstance(); | |
124 | + final String FILENAME = "workingset.ser"; | |
125 | + File dir = userDataFactory.getSpecialDataDir(FILENAME); | |
126 | + try { | |
127 | + File[] files = dir.listFiles(new FileFilter() { | |
128 | + public boolean accept(File pathname) { | |
129 | + String name = pathname.getName(); | |
130 | + return name.endsWith(FILENAME); | |
131 | + } | |
132 | + }); | |
133 | + if (files != null) { | |
134 | + WorkingSetXMLWriter wr = new WorkingSetXMLWriter(); | |
135 | + for (File file : files) { | |
136 | + FileUserData fileData = new FileUserData(file); | |
137 | + if (fileData.exists()) { | |
138 | + try { | |
139 | + // serファイルをデシリアライズする. | |
140 | + WorkingSet ws = (WorkingSet) fileData.load(); | |
141 | + URI docBase = ws.getCharacterDocBase(); | |
142 | + if (docBase != null) { | |
143 | + // XML形式で保存しなおす. | |
144 | + UserData workingSetXmlData = userDataFactory | |
145 | + .getMangledNamedUserData( | |
146 | + docBase, | |
147 | + MainFrame.WORKINGSET_FILE_SUFFIX); | |
148 | + if (!workingSetXmlData.exists()) { | |
149 | + // XML形式データがまだない場合のみ保存しなおす. | |
150 | + OutputStream outstm = workingSetXmlData | |
151 | + .getOutputStream(); | |
152 | + try { | |
153 | + wr.writeWorkingSet(ws, outstm); | |
154 | + } finally { | |
155 | + outstm.close(); | |
156 | + } | |
157 | + } | |
158 | + } | |
344 | 159 | |
345 | -// /** | |
346 | -// * 古い形式のFavorites.xmlを移動する. | |
347 | -// * | |
348 | -// * @author seraphy | |
349 | -// */ | |
350 | -// class UpgradeFavoritesXml extends StartupSupportForDocBasedData { | |
351 | -// | |
352 | -// /** | |
353 | -// * ロガー | |
354 | -// */ | |
355 | -// private final Logger logger = Logger.getLogger(getClass().getName()); | |
356 | -// | |
357 | -// @Override | |
358 | -// public void doStartup() { | |
359 | -// UserDataFactory userDataFactory = UserDataFactory.getInstance(); | |
360 | -// File appData = userDataFactory.getSpecialDataDir(null); | |
361 | -// | |
362 | -// // キャラクターデータディレクトリを走査しdocBaseの識別子の一覧を取得する | |
363 | -// Map<String, File> docBaseSignatures = getDocBaseMapInCaches( | |
364 | -// DocBaseSignatureStoratage.OLD_FORMAT); | |
365 | -// | |
366 | -// // ver0.94までは*.favorite.xmlはユーザディレクトリ直下に配備していたが | |
367 | -// // ver0.95以降は各キャラクターディレクトリに移動するため、旧docbase-id-favorites.xmlが残っていれば移動する | |
368 | -// // ユーザディレクトリ直下にある*-facotites.xmlを列挙する | |
369 | -// Map<String, File> favorites = getUUIDMangledNamedMap(appData, | |
370 | -// "-favorites.xml"); | |
371 | -// | |
372 | -// // 旧式の*-favorites.xmlを各キャラクターディレクトリに移動する. | |
373 | -// for (Map.Entry<String, File> favoritesEntry : favorites.entrySet()) { | |
374 | -// String sig = favoritesEntry.getKey(); | |
375 | -// File file = favoritesEntry.getValue(); | |
376 | -// try { | |
377 | -// File characterDir = docBaseSignatures.get(sig); | |
378 | -// if (characterDir != null) { | |
379 | -// File toFile = new File(characterDir, "favorites.xml"); | |
380 | -// boolean ret = file.renameTo(toFile); | |
381 | -// logger.log(Level.INFO, "move file " + file + " to " + toFile + " ;successed=" | |
382 | -// + ret); | |
383 | -// } | |
384 | -// | |
385 | -// } catch (Exception ex) { | |
386 | -// logger.log(Level.INFO, "move file failed." + file, ex); | |
387 | -// } | |
388 | -// } | |
389 | -// } | |
390 | -// } | |
160 | + // serファイルは削除する. | |
161 | + fileData.delete(); | |
391 | 162 | |
392 | -// /** | |
393 | -// * 存在しないDocBaseを参照するキャッシュ(*.ser)を削除する.<br> | |
394 | -// * (キャラクターディレクトリを変更した場合は、以前のデータは削除される.)<br> | |
395 | -// * | |
396 | -// * @author seraphy | |
397 | -// */ | |
398 | -// class PurgeUnusedCache extends StartupSupportForDocBasedData { | |
399 | -// | |
400 | -// /** | |
401 | -// * ロガー | |
402 | -// */ | |
403 | -// private final Logger logger = Logger.getLogger(getClass().getName()); | |
404 | -// | |
405 | -// @Override | |
406 | -// public void doStartup() { | |
407 | -// // キャッシュの保存先を取得する. | |
408 | -// UserDataFactory userDataFactory = UserDataFactory.getInstance(); | |
409 | -// File cacheDir = userDataFactory.getSpecialDataDir("*.ser"); | |
410 | -// | |
411 | -// // 現在選択されているキャラクターデータディレクトリ上のUUIDの登録を保証する. | |
412 | -// // (character.xmlに対するUUIDの問い合わせ時に登録がなければ登録される.) | |
413 | -// // (現在選択されていないディレクトリについてはUUIDの登録が行われないので、もしデータベースファイルが | |
414 | -// // 作成されていない場合はキャッシュは一旦削除されることになる.) | |
415 | -// getDocBaseMapInCaches(DocBaseSignatureStoratage.NEW_FORMAT); | |
416 | -// | |
417 | -// // キャッシュ上にあるDocBaseのUUID表現で始まる*.serを列挙 | |
418 | -// String[] suffixes = { | |
419 | -// "-character.xml-cache.ser", // character.xmlのキャッシュ | |
420 | -// "-workingset.ser", // 作業状態のキャッシュ | |
421 | -// "-favorites.ser" // お気に入りのキャッシュ | |
422 | -// }; | |
423 | -// | |
424 | -// // UUIDからURIの索引 | |
425 | -// final Map<String, URI> mangledURIMap = | |
426 | -// userDataFactory.getMangledNameMap(cacheDir); | |
427 | -// | |
428 | -// // キャッシュファイルで使用されているUUIDの示す実体のURIが実在しない場合は、そのキャッシュは不要と見なす. | |
429 | -// for (String suffix : suffixes) { | |
430 | -// Map<String, File> caches = getUUIDMangledNamedMap(cacheDir, suffix); | |
431 | -// for (Map.Entry<String, File> cacheEntry : caches.entrySet()) { | |
432 | -// String mangledUUID = cacheEntry.getKey(); | |
433 | -// File cacheFile = cacheEntry.getValue(); | |
434 | -// try { | |
435 | -// URI uri = mangledURIMap.get(mangledUUID); | |
436 | -// boolean remove = true; | |
437 | -// if (uri != null) { | |
438 | -// File characterXmlFile = new File(uri); | |
439 | -// if (characterXmlFile.exists() || characterXmlFile.isFile()) { | |
440 | -// // UUIDデータベースに登録があり、且つ、 | |
441 | -// // character.xmlが実在する場合のみ削除しない. | |
442 | -// remove = false; | |
443 | -// } | |
444 | -// } | |
445 | -// if (remove) { | |
446 | -// // キャッシュファイルを削除する. | |
447 | -// boolean result = cacheFile.delete(); | |
448 | -// logger.log(Level.INFO, "purge unused cache: " + cacheFile | |
449 | -// + "/succeeded=" + result); | |
450 | -// } | |
451 | -// | |
452 | -// } catch (Exception ex) { | |
453 | -// logger.log(Level.WARNING, "remove file failed. " + cacheFile, ex); | |
454 | -// } | |
455 | -// } | |
456 | -// } | |
457 | -// } | |
458 | -// } | |
163 | + } catch (Exception ex) { | |
164 | + logger.log(Level.WARNING, FILENAME | |
165 | + + " convert failed.", ex); | |
166 | + } | |
167 | + } | |
168 | + } | |
169 | + } | |
459 | 170 | |
171 | + } catch (Exception ex) { | |
172 | + logger.log(Level.WARNING, FILENAME + " convert failed.", ex); | |
173 | + } | |
174 | + } | |
175 | +} | |
176 | + | |
460 | 177 | /** |
461 | 178 | * 古いログファイルを消去する. |
462 | 179 | * |
@@ -27,7 +27,7 @@ | ||
27 | 27 | |
28 | 28 | /** |
29 | 29 | * エントリポイント用クラス |
30 | - * | |
30 | + * | |
31 | 31 | * @author seraphy |
32 | 32 | */ |
33 | 33 | public final class Main implements Runnable { |
@@ -89,7 +89,7 @@ | ||
89 | 89 | /** |
90 | 90 | * Javaの簡易なバージョンを取得する.<br> |
91 | 91 | * 不明な場合は0を返す.<br> |
92 | - * | |
92 | + * | |
93 | 93 | * @return バージョン |
94 | 94 | */ |
95 | 95 | private static double getJavaVersion() { |
@@ -107,7 +107,7 @@ | ||
107 | 107 | |
108 | 108 | /** |
109 | 109 | * UIをセットアップする. |
110 | - * | |
110 | + * | |
111 | 111 | * @throws Exception |
112 | 112 | * いろいろな失敗 |
113 | 113 | */ |
@@ -171,7 +171,7 @@ | ||
171 | 171 | logger.log(Level.WARNING, "failed to set the clipboard-support."); |
172 | 172 | } |
173 | 173 | |
174 | - // LANG, LC_CTYPEが設定されていない場合はエラーを表示する | |
174 | + // LANG, またはLC_CTYPEが設定されていない場合はエラーを表示する | |
175 | 175 | // OSXのJava7(Oracle)を実行する場合、環境変数LANGまたはLC_CTYPEに正しくファイル名の文字コードが設定されていないと |
176 | 176 | // ファイル名を正しく取り扱えず文字化けするため、実行前に確認し警告を表示する。 |
177 | 177 | if (isMacOSX() && getJavaVersion() >= 1.7) { |
@@ -179,7 +179,10 @@ | ||
179 | 179 | String lcctype = System.getenv("LC_CTYPE"); |
180 | 180 | if ((lang == null || lang.trim().length() == 0) && |
181 | 181 | (lcctype == null || lcctype.trim().length() == 0)) { |
182 | - JOptionPane.showMessageDialog(null, "\"LANG\" environment variable is not set!.", | |
182 | + JOptionPane | |
183 | + .showMessageDialog( | |
184 | + null, | |
185 | + "\"LANG\" or \"LC_CTYPE\" environment variable must be set.", | |
183 | 186 | "Configuration Error", JOptionPane.ERROR_MESSAGE); |
184 | 187 | } |
185 | 188 | } |
@@ -249,7 +252,7 @@ | ||
249 | 252 | /** |
250 | 253 | * エントリポイント.<br> |
251 | 254 | * 最初のメインフレームを開いたときにMac OS Xであればスクリーンメニューの登録も行う.<br> |
252 | - * | |
255 | + * | |
253 | 256 | * @param args |
254 | 257 | * 引数(未使用) |
255 | 258 | */ |
@@ -257,22 +260,22 @@ | ||
257 | 260 | // ロガー等の初期化 |
258 | 261 | initLogger(); |
259 | 262 | |
260 | - // MBeanのセットアップ | |
263 | + // MBeanのセットアップ | |
261 | 264 | try { |
262 | 265 | ImageCacheMBeanImpl.setupMBean(); |
263 | 266 | |
264 | 267 | } catch (JMException ex) { |
265 | - // 失敗しても無視して継続する. | |
268 | + // 失敗しても無視して継続する. | |
266 | 269 | logger.log(Level.SEVERE, ex.getMessage(), ex); |
267 | 270 | } |
268 | 271 | |
269 | - // フレームの生成等は、SwingのEDTで実行する. | |
272 | + // フレームの生成等は、SwingのEDTで実行する. | |
270 | 273 | SwingUtilities.invokeLater(new Main()); |
271 | 274 | } |
272 | 275 | |
273 | 276 | /** |
274 | 277 | * Mac OS Xで動作しているか? |
275 | - * | |
278 | + * | |
276 | 279 | * @return Max OS X上であればtrue |
277 | 280 | */ |
278 | 281 | public static boolean isMacOSX() { |
@@ -281,7 +284,7 @@ | ||
281 | 284 | |
282 | 285 | /** |
283 | 286 | * Mac OS X、もしくはlinuxで動作しているか? |
284 | - * | |
287 | + * | |
285 | 288 | * @return Mac OS X、もしくはlinuxで動作していればtrue |
286 | 289 | */ |
287 | 290 | public static boolean isLinuxOrMacOSX() { |
@@ -1,6 +1,7 @@ | ||
1 | 1 | package charactermanaj.ui; |
2 | 2 | |
3 | -import static java.lang.Math.*; | |
3 | +import static java.lang.Math.max; | |
4 | +import static java.lang.Math.min; | |
4 | 5 | |
5 | 6 | import java.awt.BorderLayout; |
6 | 7 | import java.awt.Color; |
@@ -22,8 +23,10 @@ | ||
22 | 23 | import java.awt.image.BufferedImage; |
23 | 24 | import java.io.File; |
24 | 25 | import java.io.IOException; |
26 | +import java.io.InputStream; | |
25 | 27 | import java.io.OutputStream; |
26 | 28 | import java.lang.reflect.InvocationTargetException; |
29 | +import java.net.URI; | |
27 | 30 | import java.util.ArrayList; |
28 | 31 | import java.util.Collections; |
29 | 32 | import java.util.Comparator; |
@@ -67,6 +70,7 @@ | ||
67 | 70 | import charactermanaj.model.AppConfig; |
68 | 71 | import charactermanaj.model.CharacterData; |
69 | 72 | import charactermanaj.model.ColorGroup; |
73 | +import charactermanaj.model.IndependentPartsSetInfo; | |
70 | 74 | import charactermanaj.model.PartsCategory; |
71 | 75 | import charactermanaj.model.PartsColorInfo; |
72 | 76 | import charactermanaj.model.PartsColorManager; |
@@ -74,6 +78,7 @@ | ||
74 | 78 | import charactermanaj.model.PartsSet; |
75 | 79 | import charactermanaj.model.RecommendationURL; |
76 | 80 | import charactermanaj.model.WorkingSet; |
81 | +import charactermanaj.model.WorkingSet2; | |
77 | 82 | import charactermanaj.model.io.CharacterDataPersistent; |
78 | 83 | import charactermanaj.model.io.PartsImageDirectoryWatchAgent; |
79 | 84 | import charactermanaj.model.io.PartsImageDirectoryWatchAgentFactory; |
@@ -80,6 +85,7 @@ | ||
80 | 85 | import charactermanaj.model.io.PartsImageDirectoryWatchEvent; |
81 | 86 | import charactermanaj.model.io.PartsImageDirectoryWatchListener; |
82 | 87 | import charactermanaj.model.io.RecentDataPersistent; |
88 | +import charactermanaj.model.io.WorkingSetXMLReader; | |
83 | 89 | import charactermanaj.model.io.WorkingSetXMLWriter; |
84 | 90 | import charactermanaj.ui.ImageSelectPanel.ImageSelectPanelEvent; |
85 | 91 | import charactermanaj.ui.ImageSelectPanel.ImageSelectPanelListener; |
@@ -108,7 +114,7 @@ | ||
108 | 114 | /** |
109 | 115 | * メインフレーム.<br> |
110 | 116 | * アプリケーションがアクティブである場合は最低でも1つのメインフレームが表示されている.<br> |
111 | - * | |
117 | + * | |
112 | 118 | * @author seraphy |
113 | 119 | */ |
114 | 120 | public class MainFrame extends JFrame { |
@@ -122,6 +128,7 @@ | ||
122 | 128 | |
123 | 129 | protected static final String MENU_STRINGS_RESOURCE = "menu/menu"; |
124 | 130 | |
131 | + public static final String WORKINGSET_FILE_SUFFIX = "workingset.xml"; | |
125 | 132 | |
126 | 133 | /** |
127 | 134 | * メインフレームのアイコン.<br> |
@@ -235,7 +242,7 @@ | ||
235 | 242 | |
236 | 243 | /** |
237 | 244 | * アクティブなメインフレームを設定する. |
238 | - * | |
245 | + * | |
239 | 246 | * @param mainFrame |
240 | 247 | * メインフレーム |
241 | 248 | */ |
@@ -249,7 +256,7 @@ | ||
249 | 256 | /** |
250 | 257 | * 現在アクティブなメインフレームを取得する. まだメインフレームが開かれていない場合はnull.<br> |
251 | 258 | * 最後のメインフレームが破棄中、もしくは破棄済みであれば破棄されたフレームを示すことに注意.<br> |
252 | - * | |
259 | + * | |
253 | 260 | * @return メインフレーム、もしくはnull |
254 | 261 | */ |
255 | 262 | public static MainFrame getActivedMainFrame() { |
@@ -258,7 +265,7 @@ | ||
258 | 265 | |
259 | 266 | /** |
260 | 267 | * インポートされパーツが増減した可能性がある場合に呼び出される. |
261 | - * | |
268 | + * | |
262 | 269 | * @param cd |
263 | 270 | * 対象 |
264 | 271 | * @param newCd |
@@ -325,7 +332,7 @@ | ||
325 | 332 | |
326 | 333 | /** |
327 | 334 | * キャラクターデータが変更されたことを通知される.<br> |
328 | - * | |
335 | + * | |
329 | 336 | * @param cd |
330 | 337 | * キャラクターデータ(変更前) |
331 | 338 | * @param newCd |
@@ -412,7 +419,7 @@ | ||
412 | 419 | |
413 | 420 | /** |
414 | 421 | * お気に入りデータが変更されたことを通知される. |
415 | - * | |
422 | + * | |
416 | 423 | * @param cd |
417 | 424 | * キャラクターデータ |
418 | 425 | */ |
@@ -441,7 +448,7 @@ | ||
441 | 448 | |
442 | 449 | /** |
443 | 450 | * メインフレームを構築する. |
444 | - * | |
451 | + * | |
445 | 452 | * @param characterData |
446 | 453 | * キャラクターデータ |
447 | 454 | */ |
@@ -885,7 +892,7 @@ | ||
885 | 892 | |
886 | 893 | /** |
887 | 894 | * 指定したパーツカテゴリ以外のパーツ選択パネルを最小化する. |
888 | - * | |
895 | + * | |
889 | 896 | * @param partsCategory |
890 | 897 | * パーツカテゴリ、nullの場合は全て最小化する. |
891 | 898 | * @param dblClick |
@@ -932,7 +939,7 @@ | ||
932 | 939 | * デフォルトパーツがなければお気に入りの最初のものを選択する.<br> |
933 | 940 | * それもなければ空として表示する.<br> |
934 | 941 | * パーツの適用に失敗した場合はfalseを返します.(例外は返されません.)<br> |
935 | - * | |
942 | + * | |
936 | 943 | * @param force |
937 | 944 | * すでに選択があっても選択しなおす場合はtrue、falseの場合は選択があれば何もしない. |
938 | 945 | * @return パーツ選択された場合。force=trueの場合はエラーがなければ常にtrueとなります。 |
@@ -982,7 +989,7 @@ | ||
982 | 989 | /** |
983 | 990 | * プリセットを適用しキャラクターイメージを再構築します.<br> |
984 | 991 | * 実行時エラーは画面のレポートされます.<br> |
985 | - * | |
992 | + * | |
986 | 993 | * @param presetParts |
987 | 994 | * パーツセット, nullの場合は何もしない. |
988 | 995 | */ |
@@ -1007,7 +1014,7 @@ | ||
1007 | 1014 | |
1008 | 1015 | /** |
1009 | 1016 | * プリセットとお気に入りを表示順に並べて返す. |
1010 | - * | |
1017 | + * | |
1011 | 1018 | * @return プリセットとお気に入りのリスト(表示順) |
1012 | 1019 | */ |
1013 | 1020 | protected List<PartsSet> getPartsSetList() { |
@@ -1030,7 +1037,7 @@ | ||
1030 | 1037 | |
1031 | 1038 | /** |
1032 | 1039 | * お気に入りメニューが開いたとき |
1033 | - * | |
1040 | + * | |
1034 | 1041 | * @param menu |
1035 | 1042 | */ |
1036 | 1043 | protected void onSelectedFavoriteMenu(JMenu menu) { |
@@ -1075,7 +1082,7 @@ | ||
1075 | 1082 | |
1076 | 1083 | /** |
1077 | 1084 | * ヘルプメニューを開いたときにお勧めメニューを構築する. |
1078 | - * | |
1085 | + * | |
1079 | 1086 | * @param menu |
1080 | 1087 | */ |
1081 | 1088 | protected void onSelectedRecommendationMenu(JMenu mnuRecomendation) { |
@@ -1114,7 +1121,7 @@ | ||
1114 | 1121 | * 最後に選択されたお気に入りと同じ構成であれば、 このお気に入りの名前をプレビューペインのタイトルに設定する.<br> |
1115 | 1122 | * そうでなければデフォルトのパーツセット名(no titleとか)を表示する.<br> |
1116 | 1123 | * 色情報が異なる場合に末尾に「*」マークがつけられる.<br> |
1117 | - * | |
1124 | + * | |
1118 | 1125 | * @param requestPartsSet |
1119 | 1126 | * 表示するパーツセット(名前は設定されていなくて良い。お気に入り側を使うので。), nullの場合はデフォルトのパーツ名 |
1120 | 1127 | */ |
@@ -1130,7 +1137,7 @@ | ||
1130 | 1137 | * パーツセット名を推定する.<br> |
1131 | 1138 | * 最後に選択されたお気に入りと同じ構成であれば、 このお気に入りの名前を返す.<br> |
1132 | 1139 | * お気に入りが選択されていないか構成が異なる場合、お気に入りに名前がない場合はnullを返す.<br> |
1133 | - * | |
1140 | + * | |
1134 | 1141 | * @param requestPartsSet |
1135 | 1142 | * 表示するパーツセット(名前は設定されていなくて良い。お気に入り側を使うので。) |
1136 | 1143 | * @param markColorChange |
@@ -1314,7 +1321,7 @@ | ||
1314 | 1321 | /** |
1315 | 1322 | * 背景色のみ変更し、背景を再描画する.<br> |
1316 | 1323 | * 壁紙情報全体の更新よりも効率化するためのメソッドである.<br> |
1317 | - * | |
1324 | + * | |
1318 | 1325 | * @param bgColor |
1319 | 1326 | * 背景色 |
1320 | 1327 | */ |
@@ -1327,7 +1334,7 @@ | ||
1327 | 1334 | /** |
1328 | 1335 | * 壁紙情報を保存し、その情報をもとに背景を再描画する.<br> |
1329 | 1336 | * ignoreErrorがtrueである場合、適用に失敗した場合はログに記録するのみで、 壁紙情報は保存されず、壁紙も更新されない.<br> |
1330 | - * | |
1337 | + * | |
1331 | 1338 | * @param wallpaperInfo |
1332 | 1339 | * 壁紙情報、null不可 |
1333 | 1340 | * @param ignoreError |
@@ -1557,7 +1564,7 @@ | ||
1557 | 1564 | |
1558 | 1565 | /** |
1559 | 1566 | * クリップボードにコピー |
1560 | - * | |
1567 | + * | |
1561 | 1568 | * @param screenImage |
1562 | 1569 | * スクリーンイメージ |
1563 | 1570 | */ |
@@ -1630,7 +1637,7 @@ | ||
1630 | 1637 | * 現在のプロファイルに対するインポートウィザードを実行する.<br> |
1631 | 1638 | * インポートが実行された場合は、パーツをリロードする.<br> |
1632 | 1639 | * インポートウィザード表示中は監視スレッドは停止される.<br> |
1633 | - * | |
1640 | + * | |
1634 | 1641 | * @param initFile |
1635 | 1642 | * アーカイブファィルまたはディレクトリ、指定がなければnull |
1636 | 1643 | */ |
@@ -1667,7 +1674,7 @@ | ||
1667 | 1674 | * まだロードされていない場合はあらたにロードする.<br> |
1668 | 1675 | * 引数newCdが指定されている場合は、現在のキャラクター定義の説明文を更新する.<br> |
1669 | 1676 | * (説明文の更新以外には使用されない.)<br> |
1670 | - * | |
1677 | + * | |
1671 | 1678 | * @param newCd |
1672 | 1679 | * 説明文更新のための更新されたキャラクターデータを指定する。null可 |
1673 | 1680 | * @param forceRepaint |
@@ -1813,36 +1820,6 @@ | ||
1813 | 1820 | } |
1814 | 1821 | |
1815 | 1822 | /** |
1816 | - * 画面の作業状態を保存するユーザーデータを取得する. | |
1817 | - * | |
1818 | - * @param modeRead | |
1819 | - * 読み込みモード | |
1820 | - * @return ユーザーデータ | |
1821 | - */ | |
1822 | - protected UserData getWorkingSetUserData(boolean modeRead) { | |
1823 | - return getWorkingSetUserData(characterData, modeRead); | |
1824 | - } | |
1825 | - | |
1826 | - /** | |
1827 | - * 画面の作業状態を保存するユーザーデータを取得する.<br> | |
1828 | - * キャラクターデータがnullまたは有効でない場合はnullを返す.<br> | |
1829 | - * | |
1830 | - * @param cd | |
1831 | - * キャラクターデータ | |
1832 | - * @param modeRead | |
1833 | - * 読み込みモード | |
1834 | - * @return 作業状態を保存するユーザーデータ、もしくはnull | |
1835 | - */ | |
1836 | - public static UserData getWorkingSetUserData(CharacterData cd, boolean modeRead) { | |
1837 | - if (cd == null || !cd.isValid()) { | |
1838 | - return null; | |
1839 | - } | |
1840 | - | |
1841 | - UserDataFactory userDataFactory = UserDataFactory.getInstance(); | |
1842 | - return userDataFactory.getMangledNamedUserData(cd.getDocBase(), "workingset.ser"); | |
1843 | - } | |
1844 | - | |
1845 | - /** | |
1846 | 1823 | * 画面の作業状態を保存する. |
1847 | 1824 | */ |
1848 | 1825 | protected void saveWorkingSet() { |
@@ -1850,12 +1827,14 @@ | ||
1850 | 1827 | return; |
1851 | 1828 | } |
1852 | 1829 | try { |
1830 | + // ワーキングセットの作成 | |
1853 | 1831 | WorkingSet workingSet = new WorkingSet(); |
1854 | 1832 | workingSet.setCharacterDocBase(characterData.getDocBase()); |
1855 | 1833 | workingSet.setCharacterDataRev(characterData.getRev()); |
1856 | 1834 | PartsSet partsSet = partsSelectionManager.createPartsSet(); |
1857 | 1835 | workingSet.setPartsSet(partsSet); |
1858 | - workingSet.setPartsColorInfoMap(characterData.getPartsColorManager().getPartsColorInfoMap()); | |
1836 | + workingSet.setPartsColorInfoMap(characterData | |
1837 | + .getPartsColorManager().getPartsColorInfoMap()); | |
1859 | 1838 | workingSet.setLastUsedSaveDir(imageSaveHelper.getLastUsedSaveDir()); |
1860 | 1839 | workingSet.setLastUsedExportDir(ExportWizardDialog.getLastUsedDir()); |
1861 | 1840 | workingSet.setLastUsePresetParts(lastUsePresetParts); |
@@ -1863,13 +1842,11 @@ | ||
1863 | 1842 | .setCharacterData(characterData.duplicateBasicInfo(false)); // パーツセットは保存しない. |
1864 | 1843 | workingSet.setWallpaperInfo(wallpaperInfo); |
1865 | 1844 | |
1866 | - UserData workingSetStore = getWorkingSetUserData(false); | |
1867 | - workingSetStore.save(workingSet); | |
1868 | - | |
1869 | 1845 | // XML形式でのワーキングセットの保存 |
1870 | 1846 | UserDataFactory userDataFactory = UserDataFactory.getInstance(); |
1871 | - UserData xmlData = userDataFactory.getMangledNamedUserData(characterData.getDocBase(), "workingset.xml"); | |
1872 | - OutputStream outstm = xmlData.getOutputStream(); | |
1847 | + UserData workingSetXmlData = userDataFactory.getMangledNamedUserData( | |
1848 | + characterData.getDocBase(), WORKINGSET_FILE_SUFFIX); | |
1849 | + OutputStream outstm = workingSetXmlData.getOutputStream(); | |
1873 | 1850 | try { |
1874 | 1851 | WorkingSetXMLWriter workingSetXmlWriter = new WorkingSetXMLWriter(); |
1875 | 1852 | workingSetXmlWriter.writeWorkingSet(workingSet, outstm); |
@@ -1884,7 +1861,7 @@ | ||
1884 | 1861 | |
1885 | 1862 | /** |
1886 | 1863 | * 画面の作業状態を復元する. |
1887 | - * | |
1864 | + * | |
1888 | 1865 | * @return |
1889 | 1866 | */ |
1890 | 1867 | protected boolean loadWorkingSet() { |
@@ -1892,72 +1869,79 @@ | ||
1892 | 1869 | return false; |
1893 | 1870 | } |
1894 | 1871 | try { |
1895 | - UserData workingSetStore = getWorkingSetUserData(true); | |
1896 | - if (workingSetStore != null && workingSetStore.exists()) { | |
1897 | - WorkingSet workingSet = (WorkingSet) workingSetStore.load(); | |
1898 | - if (!characterData.getDocBase().equals(workingSet.getCharacterDocBase())) { | |
1899 | - // ワーキングセットのキャラクターデータとキャラクターデータを定義しているDocBaseが異なる場合はワーキングセットを無視する | |
1900 | - logger.info("workingset data mismatch:" + characterData); | |
1901 | - return false; | |
1902 | - } | |
1872 | + // XML形式でのワーキングセットの復元 | |
1873 | + UserDataFactory userDataFactory = UserDataFactory.getInstance(); | |
1874 | + UserData workingSetXmlData = userDataFactory.getMangledNamedUserData( | |
1875 | + characterData.getDocBase(), WORKINGSET_FILE_SUFFIX); | |
1876 | + if (workingSetXmlData == null || !workingSetXmlData.exists()) { | |
1877 | + // 保存されていない場合 | |
1878 | + return false; | |
1879 | + } | |
1880 | + WorkingSet2 workingSet2; | |
1903 | 1881 | |
1904 | - CharacterData workingCd = workingSet.getCharacterData(); | |
1905 | - if (workingCd == null) { | |
1906 | - // ワーキングセットにキャラクターデータが設定されていない場合はREVで比較する.(ver0.96以前旧シリアライズデータ互換用) | |
1907 | - String docRev = characterData.getRev(); | |
1908 | - String workRev = workingSet.getCharacterDataRev(); | |
1909 | - if (docRev == null || workRev == null || !docRev.equals(workRev)) { | |
1910 | - // ワーキングセットが保存されてからrevisionが変更されていれば無視する. | |
1911 | - logger.info("workingset revision mismatch: actual=" + characterData + "/workingSet=" + workingSet); | |
1912 | - return false; | |
1913 | - } | |
1882 | + InputStream is = workingSetXmlData.openStream(); | |
1883 | + try { | |
1884 | + WorkingSetXMLReader WorkingSetXMLReader = new WorkingSetXMLReader(); | |
1885 | + workingSet2 = WorkingSetXMLReader.loadWorkingSet(is); | |
1914 | 1886 | |
1915 | - } else if ( !workingCd.isUpperCompatibleStructure(characterData)) { | |
1916 | - // ワーキングセットにキャラクターデータが設定されており、且つ、構造が一致しない場合は無視する.(ver0.96以降) | |
1917 | - logger.info("workingset cd-structure mismatch: actual=" + characterData + "/workingSet=" + workingSet); | |
1918 | - return false; | |
1919 | - } | |
1887 | + } finally { | |
1888 | + is.close(); | |
1889 | + } | |
1920 | 1890 | |
1921 | - // 現在のパーツ色情報にワーキングセットで保存した内容を設定する. | |
1922 | - Map<PartsIdentifier, PartsColorInfo> partsColorInfoMap = characterData.getPartsColorManager().getPartsColorInfoMap(); | |
1923 | - Map<PartsIdentifier, PartsColorInfo> workingPartsColorInfoMap = workingSet.getPartsColorInfoMap(); | |
1924 | - if (workingPartsColorInfoMap != null) { | |
1925 | - for (Map.Entry<PartsIdentifier, PartsColorInfo> entry : workingPartsColorInfoMap.entrySet()) { | |
1926 | - PartsIdentifier partsIdentifier = entry.getKey(); | |
1927 | - PartsColorInfo partsColorInfo = entry.getValue(); | |
1928 | - partsColorInfoMap.put(partsIdentifier, partsColorInfo); | |
1929 | - } | |
1930 | - } | |
1891 | + URI docBase = characterData.getDocBase(); | |
1892 | + if (docBase != null | |
1893 | + && !docBase.equals(workingSet2.getCharacterDocBase())) { | |
1894 | + // docBaseが一致せず | |
1895 | + return false; | |
1896 | + } | |
1897 | + String sig = characterData.toSignatureString(); | |
1898 | + if (!sig.equals(workingSet2.getCharacterDataSig())) { | |
1899 | + // 構造が一致せず. | |
1900 | + return false; | |
1901 | + } | |
1931 | 1902 | |
1932 | - // 選択されているパーツの復元 | |
1933 | - PartsSet partsSet = workingSet.getPartsSet(); | |
1934 | - if (partsSet != null) { | |
1935 | - partsSet = partsSet.createCompatible(characterData); | |
1936 | - selectPresetParts(partsSet); | |
1903 | + // パーツの色情報を復元する. | |
1904 | + Map<PartsIdentifier, PartsColorInfo> partsColorInfoMap = characterData | |
1905 | + .getPartsColorManager().getPartsColorInfoMap(); | |
1906 | + workingSet2.createCompatible(characterData, partsColorInfoMap); | |
1937 | 1907 | |
1938 | - // 最後に選択したお気に入り情報の復元 | |
1939 | - PartsSet lastUsePresetParts = workingSet.getLastUsePresetParts(); | |
1940 | - if (lastUsePresetParts != null && lastUsePresetParts.hasName() | |
1941 | - && lastUsePresetParts.isSameStructure(partsSet)) { | |
1908 | + // 選択されているパーツの復元 | |
1909 | + IndependentPartsSetInfo partsSetInfo = workingSet2 | |
1910 | + .getCurrentPartsSet(); | |
1911 | + if (partsSetInfo != null) { | |
1912 | + PartsSet partsSet = IndependentPartsSetInfo.convertPartsSet( | |
1913 | + partsSetInfo, characterData, false); | |
1914 | + selectPresetParts(partsSet); | |
1915 | + | |
1916 | + // 最後に選択したお気に入り情報の復元 | |
1917 | + IndependentPartsSetInfo lastUsePresetPartsInfo = workingSet2 | |
1918 | + .getLastUsePresetParts(); | |
1919 | + if (lastUsePresetPartsInfo != null | |
1920 | + && lastUsePresetPartsInfo.getId() != null | |
1921 | + && lastUsePresetPartsInfo.getId().trim().length() > 0) { | |
1922 | + PartsSet lastUsePresetParts = IndependentPartsSetInfo | |
1923 | + .convertPartsSet(lastUsePresetPartsInfo, | |
1924 | + characterData, false); | |
1925 | + if (lastUsePresetParts.isSameStructure(partsSet)) { | |
1942 | 1926 | this.lastUsePresetParts = lastUsePresetParts; |
1943 | 1927 | showPresetName(lastUsePresetParts); |
1944 | 1928 | } |
1945 | 1929 | } |
1930 | + } | |
1946 | 1931 | |
1947 | - // 最後に保存したディレクトリを復元する. | |
1948 | - imageSaveHelper.setLastUseSaveDir(workingSet.getLastUsedSaveDir()); | |
1949 | - ExportWizardDialog.setLastUsedDir(workingSet.getLastUsedExportDir()); | |
1932 | + // 最後に保存したディレクトリを復元する. | |
1933 | + imageSaveHelper.setLastUseSaveDir(workingSet2.getLastUsedSaveDir()); | |
1934 | + ExportWizardDialog.setLastUsedDir(workingSet2 | |
1935 | + .getLastUsedExportDir()); | |
1950 | 1936 | |
1951 | - // 壁紙情報を取得する. | |
1952 | - WallpaperInfo wallpaperInfo = workingSet.getWallpaperInfo(); | |
1953 | - if (wallpaperInfo != null) { | |
1954 | - // 壁紙情報を保存し、その情報をもとに背景を再描画する. | |
1955 | - // (適用に失敗した場合はエラーは無視し、壁紙情報は保存しない.) | |
1956 | - applyWallpaperInfo(wallpaperInfo, true); | |
1957 | - } | |
1958 | - | |
1959 | - return true; | |
1937 | + // 壁紙情報を取得する. | |
1938 | + WallpaperInfo wallpaperInfo = workingSet2.getWallpaperInfo(); | |
1939 | + if (wallpaperInfo != null) { | |
1940 | + // 壁紙情報を保存し、その情報をもとに背景を再描画する. | |
1941 | + // (適用に失敗した場合はエラーは無視し、壁紙情報は保存しない.) | |
1942 | + applyWallpaperInfo(wallpaperInfo, true); | |
1960 | 1943 | } |
1944 | + return true; | |
1961 | 1945 | |
1962 | 1946 | } catch (Exception ex) { |
1963 | 1947 | ErrorMessageHelper.showErrorDialog(this, ex); |
@@ -2216,7 +2200,7 @@ | ||
2216 | 2200 | |
2217 | 2201 | /** |
2218 | 2202 | * メニューバーを構築します. |
2219 | - * | |
2203 | + * | |
2220 | 2204 | * @return メニューバー |
2221 | 2205 | */ |
2222 | 2206 | protected JMenuBar createMenuBar() { |
@@ -1,39 +1,30 @@ | ||
1 | -<xs:schema | |
2 | - targetNamespace="http://charactermanaj.sourceforge.jp/schema/charactermanaj" | |
3 | - xmlns="http://charactermanaj.sourceforge.jp/schema/charactermanaj" | |
4 | - xmlns:xs="http://www.w3.org/2001/XMLSchema" | |
5 | - xmlns:xml="http://www.w3.org/XML/1998/namespace" | |
6 | - attributeFormDefault="qualified" | |
7 | - elementFormDefault="qualified"> | |
8 | - <xs:import namespace="http://www.w3.org/XML/1998/namespace" schemaLocation="xml.xsd"/> | |
9 | - | |
1 | +<?xml version="1.0" encoding="UTF-8"?> | |
2 | +<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns="http://charactermanaj.sourceforge.jp/schema/charactermanaj" targetNamespace="http://charactermanaj.sourceforge.jp/schema/charactermanaj" attributeFormDefault="qualified" elementFormDefault="qualified"> | |
3 | + <xs:import namespace="http://www.w3.org/XML/1998/namespace" schemaLocation="xml.xsd" /> | |
10 | 4 | <xs:simpleType name="tokenNotEmpty"> |
11 | - <xs:annotation> | |
12 | - <xs:documentation xml:lang="ja">空文字を許可しないトークンの定義</xs:documentation> | |
13 | - </xs:annotation> | |
5 | + <xs:annotation> | |
6 | + <xs:documentation xml:lang="ja">空文字を許可しないトークンの定義</xs:documentation> | |
7 | + </xs:annotation> | |
14 | 8 | <xs:restriction base="xs:token"> |
15 | - <xs:minLength value="1"/> | |
9 | + <xs:minLength value="1" /> | |
16 | 10 | </xs:restriction> |
17 | 11 | </xs:simpleType> |
18 | - | |
19 | 12 | <xs:simpleType name="floatMax1"> |
20 | 13 | <xs:restriction base="xs:float"> |
21 | - <xs:minInclusive value="0"/> | |
22 | - <xs:maxInclusive value="1"/> | |
14 | + <xs:minInclusive value="0" /> | |
15 | + <xs:maxInclusive value="1" /> | |
23 | 16 | </xs:restriction> |
24 | 17 | </xs:simpleType> |
25 | - | |
26 | 18 | <xs:simpleType name="floatMax1Round"> |
27 | 19 | <xs:restriction base="xs:float"> |
28 | - <xs:minInclusive value="-1"/> | |
29 | - <xs:maxInclusive value="1"/> | |
20 | + <xs:minInclusive value="-1" /> | |
21 | + <xs:maxInclusive value="1" /> | |
30 | 22 | </xs:restriction> |
31 | 23 | </xs:simpleType> |
32 | - | |
33 | 24 | <xs:complexType name="rgbvalue"> |
34 | - <xs:annotation> | |
35 | - <xs:documentation xml:lang="ja">RGB変換パラメータ</xs:documentation> | |
36 | - </xs:annotation> | |
25 | + <xs:annotation> | |
26 | + <xs:documentation xml:lang="ja">RGB変換パラメータ</xs:documentation> | |
27 | + </xs:annotation> | |
37 | 28 | <xs:attribute name="offset" form="unqualified" type="xs:integer" use="required"> |
38 | 29 | <xs:annotation> |
39 | 30 | <xs:documentation xml:lang="ja">オフセット</xs:documentation> |
@@ -50,34 +41,32 @@ | ||
50 | 41 | </xs:annotation> |
51 | 42 | </xs:attribute> |
52 | 43 | </xs:complexType> |
53 | - | |
54 | 44 | <xs:complexType name="hsbvalue"> |
55 | - <xs:annotation> | |
56 | - <xs:documentation xml:lang="ja">HSB変換パラメータ</xs:documentation> | |
57 | - </xs:annotation> | |
58 | - <xs:attribute name="hue" form="unqualified" type="floatMax1Round" use="required"/> | |
59 | - <xs:attribute name="saturation" form="unqualified" type="floatMax1Round" use="required"/> | |
60 | - <xs:attribute name="brightness" form="unqualified" type="floatMax1Round" use="required"/> | |
61 | - <xs:attribute name="contrast" form="unqualified" type="floatMax1Round" use="optional"/><!-- ver0.96追加 --> | |
45 | + <xs:annotation> | |
46 | + <xs:documentation xml:lang="ja">HSB変換パラメータ</xs:documentation> | |
47 | + </xs:annotation> | |
48 | + <xs:attribute name="hue" form="unqualified" type="floatMax1Round" use="required" /> | |
49 | + <xs:attribute name="saturation" form="unqualified" type="floatMax1Round" use="required" /> | |
50 | + <xs:attribute name="brightness" form="unqualified" type="floatMax1Round" use="required" /> | |
51 | + <xs:attribute name="contrast" form="unqualified" type="floatMax1Round" use="optional" /> | |
52 | + <!-- ver0.96追加 --> | |
62 | 53 | </xs:complexType> |
63 | - | |
64 | 54 | <xs:simpleType name="rgbreplacetype"> |
65 | - <xs:annotation> | |
66 | - <xs:documentation xml:lang="ja">RGB置換タイプ</xs:documentation> | |
67 | - </xs:annotation> | |
55 | + <xs:annotation> | |
56 | + <xs:documentation xml:lang="ja">RGB置換タイプ</xs:documentation> | |
57 | + </xs:annotation> | |
68 | 58 | <xs:restriction base="xs:string"> |
69 | - <xs:enumeration value="NONE"/> | |
70 | - <xs:enumeration value="BLUE"/> | |
71 | - <xs:enumeration value="VIOLET"/> | |
72 | - <xs:enumeration value="RED"/> | |
73 | - <xs:enumeration value="YELLOW"/> | |
74 | - <xs:enumeration value="GREEN"/> | |
75 | - <xs:enumeration value="CYAN"/> | |
76 | - <xs:enumeration value="BLACK"/> | |
77 | - <xs:enumeration value="WHITE"/> | |
59 | + <xs:enumeration value="NONE" /> | |
60 | + <xs:enumeration value="BLUE" /> | |
61 | + <xs:enumeration value="VIOLET" /> | |
62 | + <xs:enumeration value="RED" /> | |
63 | + <xs:enumeration value="YELLOW" /> | |
64 | + <xs:enumeration value="GREEN" /> | |
65 | + <xs:enumeration value="CYAN" /> | |
66 | + <xs:enumeration value="BLACK" /> | |
67 | + <xs:enumeration value="WHITE" /> | |
78 | 68 | </xs:restriction> |
79 | 69 | </xs:simpleType> |
80 | - | |
81 | 70 | <xs:complexType name="rgbreplacevalue"> |
82 | 71 | <xs:attribute name="replace-type" form="unqualified" use="required" type="rgbreplacetype"> |
83 | 72 | <xs:annotation> |
@@ -90,7 +79,6 @@ | ||
90 | 79 | </xs:annotation> |
91 | 80 | </xs:attribute> |
92 | 81 | </xs:complexType> |
93 | - | |
94 | 82 | <xs:complexType name="presetsType"> |
95 | 83 | <xs:annotation> |
96 | 84 | <xs:documentation xml:lang="ja">定義済みパーツ組み合わせ例(プリセット)の定義リスト、定義順に表示される。</xs:documentation> |
@@ -109,7 +97,7 @@ | ||
109 | 97 | <xs:complexType> |
110 | 98 | <xs:simpleContent> |
111 | 99 | <xs:extension base="tokenNotEmpty"> |
112 | - <xs:attribute ref="xml:lang" use="required"/> | |
100 | + <xs:attribute ref="xml:lang" use="required" /> | |
113 | 101 | </xs:extension> |
114 | 102 | </xs:simpleContent> |
115 | 103 | </xs:complexType> |
@@ -119,7 +107,7 @@ | ||
119 | 107 | <xs:documentation xml:lang="ja">背景色</xs:documentation> |
120 | 108 | </xs:annotation> |
121 | 109 | <xs:complexType> |
122 | - <xs:attribute name="color" form="unqualified" use="required" type="xs:string"/> | |
110 | + <xs:attribute name="color" form="unqualified" use="required" type="xs:string" /> | |
123 | 111 | </xs:complexType> |
124 | 112 | </xs:element> |
125 | 113 | <xs:element name="affine-transform-parameter" minOccurs="0" maxOccurs="1"> |
@@ -127,7 +115,7 @@ | ||
127 | 115 | <xs:documentation xml:lang="ja">アフィン変換用パラメータ、4または6つの要素からなるマトリックス</xs:documentation> |
128 | 116 | </xs:annotation> |
129 | 117 | <xs:simpleType> |
130 | - <xs:list itemType="xs:double"/> | |
118 | + <xs:list itemType="xs:double" /> | |
131 | 119 | </xs:simpleType> |
132 | 120 | </xs:element> |
133 | 121 | <xs:element name="category" nillable="false" minOccurs="1" maxOccurs="unbounded"> |
@@ -142,58 +130,58 @@ | ||
142 | 130 | </xs:annotation> |
143 | 131 | <xs:complexType> |
144 | 132 | <xs:sequence> |
145 | - <xs:element name="color" nillable="false" minOccurs="0" maxOccurs="1"> | |
133 | + <xs:element name="color" nillable="false" minOccurs="0" maxOccurs="1"> | |
146 | 134 | <xs:annotation> |
147 | 135 | <xs:documentation xml:lang="ja">色定義(オプション)</xs:documentation> |
148 | 136 | </xs:annotation> |
149 | 137 | <xs:complexType> |
150 | - <xs:sequence> | |
138 | + <xs:sequence> | |
151 | 139 | <xs:element name="layer" nillable="false" minOccurs="1" maxOccurs="unbounded"> |
152 | - <xs:complexType> | |
153 | - <xs:sequence> | |
154 | - <xs:element name="color-group" minOccurs="0" maxOccurs="1"> | |
155 | - <xs:complexType> | |
156 | - <xs:attribute name="group" use="required" form="unqualified" type="tokenNotEmpty"> | |
140 | + <xs:complexType> | |
141 | + <xs:sequence> | |
142 | + <xs:element name="color-group" minOccurs="0" maxOccurs="1"> | |
143 | + <xs:complexType> | |
144 | + <xs:attribute name="group" use="required" form="unqualified" type="tokenNotEmpty"> | |
157 | 145 | <xs:annotation> |
158 | - <xs:documentation xml:lang="ja">カラーグループ</xs:documentation> | |
159 | - </xs:annotation> | |
160 | - </xs:attribute> | |
161 | - <xs:attribute name="synchronized" use="required" form="unqualified"> | |
146 | + <xs:documentation xml:lang="ja">カラーグループ</xs:documentation> | |
147 | + </xs:annotation> | |
148 | + </xs:attribute> | |
149 | + <xs:attribute name="synchronized" use="required" form="unqualified"> | |
162 | 150 | <xs:annotation> |
163 | - <xs:documentation xml:lang="ja">カラーグループの同期を行う</xs:documentation> | |
164 | - </xs:annotation> | |
165 | - <xs:simpleType> | |
166 | - <xs:restriction base="xs:boolean"> | |
167 | - <xs:pattern value="true"/> | |
168 | - <xs:pattern value="false"/> | |
169 | - </xs:restriction> | |
170 | - </xs:simpleType> | |
171 | - </xs:attribute> | |
172 | - </xs:complexType> | |
173 | - </xs:element> | |
174 | - <xs:element name="rgb" nillable="false" minOccurs="0" maxOccurs="1"> | |
175 | - <xs:annotation> | |
176 | - <xs:documentation xml:lang="ja">RGB変換</xs:documentation> | |
177 | - </xs:annotation> | |
178 | - <xs:complexType> | |
179 | - <xs:sequence> | |
180 | - <xs:element name="red" type="rgbvalue"/> | |
181 | - <xs:element name="green" type="rgbvalue"/> | |
182 | - <xs:element name="blue" type="rgbvalue"/> | |
183 | - <xs:element name="alpha" type="rgbvalue"/> | |
184 | - </xs:sequence> | |
185 | - </xs:complexType> | |
186 | - </xs:element> | |
187 | - <xs:element name="hsb" nillable="false" type="hsbvalue" minOccurs="0" maxOccurs="1"> | |
188 | - <xs:annotation> | |
189 | - <xs:documentation xml:lang="ja">HSB変換</xs:documentation> | |
190 | - </xs:annotation> | |
191 | - </xs:element> | |
192 | - <xs:element name="rgb-replace" nillable="false" type="rgbreplacevalue" minOccurs="0" maxOccurs="1"> | |
193 | - <xs:annotation> | |
194 | - <xs:documentation xml:lang="ja">RGB置換</xs:documentation> | |
195 | - </xs:annotation> | |
196 | - </xs:element> | |
151 | + <xs:documentation xml:lang="ja">カラーグループの同期を行う</xs:documentation> | |
152 | + </xs:annotation> | |
153 | + <xs:simpleType> | |
154 | + <xs:restriction base="xs:boolean"> | |
155 | + <xs:pattern value="true" /> | |
156 | + <xs:pattern value="false" /> | |
157 | + </xs:restriction> | |
158 | + </xs:simpleType> | |
159 | + </xs:attribute> | |
160 | + </xs:complexType> | |
161 | + </xs:element> | |
162 | + <xs:element name="rgb" nillable="false" minOccurs="0" maxOccurs="1"> | |
163 | + <xs:annotation> | |
164 | + <xs:documentation xml:lang="ja">RGB変換</xs:documentation> | |
165 | + </xs:annotation> | |
166 | + <xs:complexType> | |
167 | + <xs:sequence> | |
168 | + <xs:element name="red" type="rgbvalue" /> | |
169 | + <xs:element name="green" type="rgbvalue" /> | |
170 | + <xs:element name="blue" type="rgbvalue" /> | |
171 | + <xs:element name="alpha" type="rgbvalue" /> | |
172 | + </xs:sequence> | |
173 | + </xs:complexType> | |
174 | + </xs:element> | |
175 | + <xs:element name="hsb" nillable="false" type="hsbvalue" minOccurs="0" maxOccurs="1"> | |
176 | + <xs:annotation> | |
177 | + <xs:documentation xml:lang="ja">HSB変換</xs:documentation> | |
178 | + </xs:annotation> | |
179 | + </xs:element> | |
180 | + <xs:element name="rgb-replace" nillable="false" type="rgbreplacevalue" minOccurs="0" maxOccurs="1"> | |
181 | + <xs:annotation> | |
182 | + <xs:documentation xml:lang="ja">RGB置換</xs:documentation> | |
183 | + </xs:annotation> | |
184 | + </xs:element> | |
197 | 185 | </xs:sequence> |
198 | 186 | <xs:attribute name="refid" use="required" form="unqualified" type="tokenNotEmpty"> |
199 | 187 | <xs:annotation> |
@@ -241,5 +229,4 @@ | ||
241 | 229 | </xs:annotation> |
242 | 230 | </xs:attribute> |
243 | 231 | </xs:complexType> |
244 | - | |
245 | -</xs:schema> | |
232 | +</xs:schema> | |
\ No newline at end of file |
@@ -1,13 +1,7 @@ | ||
1 | -<?xml version="1.0" encoding="utf-8"?> | |
2 | -<xs:schema | |
3 | - targetNamespace="http://charactermanaj.sourceforge.jp/schema/charactermanaj" | |
4 | - xmlns="http://charactermanaj.sourceforge.jp/schema/charactermanaj" | |
5 | - xmlns:xs="http://www.w3.org/2001/XMLSchema" | |
6 | - xmlns:xml="http://www.w3.org/XML/1998/namespace" | |
7 | - attributeFormDefault="qualified" | |
8 | - elementFormDefault="qualified"> | |
9 | - <xs:import namespace="http://www.w3.org/XML/1998/namespace" schemaLocation="xml.xsd"/> | |
10 | - <xs:include schemaLocation="character_inc.xsd"/> | |
1 | +<?xml version="1.0" encoding="UTF-8"?> | |
2 | +<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns="http://charactermanaj.sourceforge.jp/schema/charactermanaj" targetNamespace="http://charactermanaj.sourceforge.jp/schema/charactermanaj" attributeFormDefault="qualified" elementFormDefault="qualified"> | |
3 | + <xs:import namespace="http://www.w3.org/XML/1998/namespace" schemaLocation="xml.xsd" /> | |
4 | + <xs:include schemaLocation="character_inc.xsd" /> | |
11 | 5 | <xs:element name="character"> |
12 | 6 | <xs:annotation> |
13 | 7 | <xs:documentation xml:lang="ja">キャラクターデータの定義</xs:documentation> |
@@ -21,12 +15,11 @@ | ||
21 | 15 | <xs:complexType> |
22 | 16 | <xs:simpleContent> |
23 | 17 | <xs:extension base="tokenNotEmpty"> |
24 | - <xs:attribute ref="xml:lang" use="required" /> | |
18 | + <xs:attribute ref="xml:lang" use="required" /> | |
25 | 19 | </xs:extension> |
26 | 20 | </xs:simpleContent> |
27 | 21 | </xs:complexType> |
28 | 22 | </xs:element> |
29 | - | |
30 | 23 | <xs:element name="information" minOccurs="0" maxOccurs="1"> |
31 | 24 | <xs:annotation> |
32 | 25 | <xs:documentation xml:lang="ja">備考</xs:documentation> |
@@ -60,7 +53,6 @@ | ||
60 | 53 | </xs:sequence> |
61 | 54 | </xs:complexType> |
62 | 55 | </xs:element> |
63 | - | |
64 | 56 | <xs:element name="image-size"> |
65 | 57 | <xs:annotation> |
66 | 58 | <xs:documentation xml:lang="ja">イメージのサイズ(幅と高さ)</xs:documentation> |
@@ -70,7 +62,7 @@ | ||
70 | 62 | <xs:element name="width"> |
71 | 63 | <xs:simpleType> |
72 | 64 | <xs:restriction base="xs:unsignedInt"> |
73 | - <xs:minExclusive value="0"/> | |
65 | + <xs:minExclusive value="0" /> | |
74 | 66 | </xs:restriction> |
75 | 67 | </xs:simpleType> |
76 | 68 | </xs:element> |
@@ -77,7 +69,7 @@ | ||
77 | 69 | <xs:element name="height"> |
78 | 70 | <xs:simpleType> |
79 | 71 | <xs:restriction base="xs:unsignedInt"> |
80 | - <xs:minExclusive value="0"/> | |
72 | + <xs:minExclusive value="0" /> | |
81 | 73 | </xs:restriction> |
82 | 74 | </xs:simpleType> |
83 | 75 | </xs:element> |
@@ -84,7 +76,6 @@ | ||
84 | 76 | </xs:sequence> |
85 | 77 | </xs:complexType> |
86 | 78 | </xs:element> |
87 | - | |
88 | 79 | <xs:element name="settings" minOccurs="0" maxOccurs="1"> |
89 | 80 | <xs:annotation> |
90 | 81 | <xs:documentation xml:lang="ja">雑多なプロパティのコレクション</xs:documentation> |
@@ -98,7 +89,7 @@ | ||
98 | 89 | <xs:complexType> |
99 | 90 | <xs:simpleContent> |
100 | 91 | <xs:extension base="xs:string"> |
101 | - <xs:attribute name="key" form="unqualified" use="required" type="xs:string"/> | |
92 | + <xs:attribute name="key" form="unqualified" use="required" type="xs:string" /> | |
102 | 93 | </xs:extension> |
103 | 94 | </xs:simpleContent> |
104 | 95 | </xs:complexType> |
@@ -106,7 +97,6 @@ | ||
106 | 97 | </xs:sequence> |
107 | 98 | </xs:complexType> |
108 | 99 | </xs:element> |
109 | - | |
110 | 100 | <xs:element name="categories"> |
111 | 101 | <xs:annotation> |
112 | 102 | <xs:documentation xml:lang="ja">カテゴリの定義リスト、出現順で画面に表示される。</xs:documentation> |
@@ -131,7 +121,7 @@ | ||
131 | 121 | <xs:complexType> |
132 | 122 | <xs:simpleContent> |
133 | 123 | <xs:extension base="tokenNotEmpty"> |
134 | - <xs:attribute ref="xml:lang" use="required"/> | |
124 | + <xs:attribute ref="xml:lang" use="required" /> | |
135 | 125 | </xs:extension> |
136 | 126 | </xs:simpleContent> |
137 | 127 | </xs:complexType> |
@@ -155,7 +145,7 @@ | ||
155 | 145 | <xs:complexType> |
156 | 146 | <xs:simpleContent> |
157 | 147 | <xs:extension base="tokenNotEmpty"> |
158 | - <xs:attribute ref="xml:lang" use="required"/> | |
148 | + <xs:attribute ref="xml:lang" use="required" /> | |
159 | 149 | </xs:extension> |
160 | 150 | </xs:simpleContent> |
161 | 151 | </xs:complexType> |
@@ -181,8 +171,8 @@ | ||
181 | 171 | </xs:annotation> |
182 | 172 | <xs:simpleType> |
183 | 173 | <xs:restriction base="xs:boolean"> |
184 | - <xs:pattern value="true"/> | |
185 | - <xs:pattern value="false"/> | |
174 | + <xs:pattern value="true" /> | |
175 | + <xs:pattern value="false" /> | |
186 | 176 | </xs:restriction> |
187 | 177 | </xs:simpleType> |
188 | 178 | </xs:attribute> |
@@ -221,8 +211,8 @@ | ||
221 | 211 | </xs:annotation> |
222 | 212 | <xs:simpleType> |
223 | 213 | <xs:restriction base="xs:boolean"> |
224 | - <xs:pattern value="true"/> | |
225 | - <xs:pattern value="false"/> | |
214 | + <xs:pattern value="true" /> | |
215 | + <xs:pattern value="false" /> | |
226 | 216 | </xs:restriction> |
227 | 217 | </xs:simpleType> |
228 | 218 | </xs:attribute> |
@@ -231,7 +221,6 @@ | ||
231 | 221 | </xs:sequence> |
232 | 222 | </xs:complexType> |
233 | 223 | </xs:element> |
234 | - | |
235 | 224 | <xs:element name="colorGroups" minOccurs="0" maxOccurs="1"> |
236 | 225 | <xs:annotation> |
237 | 226 | <xs:documentation xml:lang="ja">カラーグループの定義リスト</xs:documentation> |
@@ -251,7 +240,7 @@ | ||
251 | 240 | <xs:complexType> |
252 | 241 | <xs:simpleContent> |
253 | 242 | <xs:extension base="tokenNotEmpty"> |
254 | - <xs:attribute ref="xml:lang" use="required"/> | |
243 | + <xs:attribute ref="xml:lang" use="required" /> | |
255 | 244 | </xs:extension> |
256 | 245 | </xs:simpleContent> |
257 | 246 | </xs:complexType> |
@@ -267,7 +256,6 @@ | ||
267 | 256 | </xs:sequence> |
268 | 257 | </xs:complexType> |
269 | 258 | </xs:element> |
270 | - | |
271 | 259 | <xs:element name="recommendations" minOccurs="0" maxOccurs="1"> |
272 | 260 | <xs:annotation> |
273 | 261 | <xs:documentation xml:lang="ja">お薦めリンクのリスト</xs:documentation> |
@@ -318,16 +306,14 @@ | ||
318 | 306 | </xs:sequence> |
319 | 307 | </xs:complexType> |
320 | 308 | </xs:element> |
321 | - | |
322 | 309 | <xs:element name="presets" minOccurs="0" maxOccurs="1" type="presetsType"> |
323 | 310 | <xs:annotation> |
324 | 311 | <xs:documentation xml:lang="ja">定義済みパーツ組み合わせ例(プリセット)の定義リスト、定義順に表示される。</xs:documentation> |
325 | 312 | </xs:annotation> |
326 | - </xs:element> | |
327 | - | |
313 | + </xs:element> | |
328 | 314 | </xs:sequence> |
329 | - <xs:attribute name="id" form="unqualified" type="tokenNotEmpty" use="required"/> | |
330 | - <xs:attribute name="rev" form="unqualified" type="tokenNotEmpty" use="required"/> | |
315 | + <xs:attribute name="id" form="unqualified" type="tokenNotEmpty" use="required" /> | |
316 | + <xs:attribute name="rev" form="unqualified" type="tokenNotEmpty" use="required" /> | |
331 | 317 | <xs:attribute name="version" form="unqualified" type="tokenNotEmpty" use="required"> |
332 | 318 | <xs:annotation> |
333 | 319 | <xs:documentation xml:lang="ja">このXMLのバージョン番号、1.0固定。</xs:documentation> |
@@ -334,18 +320,17 @@ | ||
334 | 320 | </xs:annotation> |
335 | 321 | </xs:attribute> |
336 | 322 | </xs:complexType> |
337 | - | |
338 | 323 | <xs:key name="category-id"> |
339 | - <xs:selector xpath="categories/category"/> | |
340 | - <xs:field xpath="@id"/> | |
324 | + <xs:selector xpath="categories/category" /> | |
325 | + <xs:field xpath="@id" /> | |
341 | 326 | </xs:key> |
342 | 327 | <xs:key name="layer-id"> |
343 | - <xs:selector xpath="categories/category/layers/layer"/> | |
344 | - <xs:field xpath="@id"/> | |
328 | + <xs:selector xpath="categories/category/layers/layer" /> | |
329 | + <xs:field xpath="@id" /> | |
345 | 330 | </xs:key> |
346 | 331 | <xs:key name="colorGroup-id"> |
347 | - <xs:selector xpath="colorGroups/colorGroup"/> | |
348 | - <xs:field xpath="@id"/> | |
332 | + <xs:selector xpath="colorGroups/colorGroup" /> | |
333 | + <xs:field xpath="@id" /> | |
349 | 334 | </xs:key> |
350 | 335 | </xs:element> |
351 | -</xs:schema> | |
336 | +</xs:schema> | |
\ No newline at end of file |