• R/O
  • SSH
  • HTTPS

charactermanaj: コミット


コミットメタ情報

リビジョン90 (tree)
日時2013-12-29 06:39:28
作者seraphy

ログメッセージ

WorkingSetの保存と復元をシリアライズからXML形式に変更した。

変更サマリ

差分

--- trunk/src/charactermanaj/model/IndependentPartsSetInfo.java (nonexistent)
+++ trunk/src/charactermanaj/model/IndependentPartsSetInfo.java (revision 90)
@@ -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+}
--- trunk/src/charactermanaj/model/WorkingSet2.java (nonexistent)
+++ trunk/src/charactermanaj/model/WorkingSet2.java (revision 90)
@@ -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+}
--- trunk/src/charactermanaj/model/IndependentPartsColorInfo.java (nonexistent)
+++ trunk/src/charactermanaj/model/IndependentPartsColorInfo.java (revision 90)
@@ -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
--- trunk/src/charactermanaj/model/io/WorkingSetXMLReader.java (nonexistent)
+++ trunk/src/charactermanaj/model/io/WorkingSetXMLReader.java (revision 90)
@@ -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+}
--- trunk/src/charactermanaj/model/io/CharacterDataXMLWriter.java (revision 89)
+++ trunk/src/charactermanaj/model/io/CharacterDataXMLWriter.java (revision 90)
@@ -403,9 +403,13 @@
403403
404404 /**
405405 * パーツセットの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"が返される.
409413 * @return パーツセット1つ分のXML要素
410414 */
411415 public Element createPartsSetXML(Document doc, String lang, PartsSet partsSet) {
@@ -493,8 +497,11 @@
493497
494498 /**
495499 * パーツカラー情報のXML要素を生成して返す.<br>
496- * @param doc 要素を作成するためのファクトリ
497- * @param partsColorInfo パーツカラー情報
500+ *
501+ * @param doc
502+ * 要素を作成するためのファクトリ
503+ * @param partsColorInfo
504+ * パーツカラー情報
498505 * @return パーツカラー情報の要素
499506 */
500507 public Element createPartsColorInfoXML(Document doc, PartsColorInfo partsColorInfo) {
--- trunk/src/charactermanaj/model/io/WorkingSetXMLWriter.java (revision 89)
+++ trunk/src/charactermanaj/model/io/WorkingSetXMLWriter.java (revision 90)
@@ -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+}
--- trunk/src/charactermanaj/model/io/CharacterDataPersistent.java (revision 89)
+++ trunk/src/charactermanaj/model/io/CharacterDataPersistent.java (revision 90)
@@ -46,6 +46,7 @@
4646 import charactermanaj.util.FileNameNormalizer;
4747 import charactermanaj.util.FileUserData;
4848 import charactermanaj.util.UserData;
49+import charactermanaj.util.UserDataFactory;
4950
5051 public class CharacterDataPersistent {
5152
@@ -720,10 +721,12 @@
720721 }
721722
722723 // ワーキングセットの削除
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();
727730 }
728731
729732 // xmlファイルの拡張子を変更することでキャラクター定義として認識させない.
--- trunk/src/charactermanaj/model/io/CharacterDataXMLReader.java (revision 89)
+++ trunk/src/charactermanaj/model/io/CharacterDataXMLReader.java (revision 90)
@@ -12,8 +12,10 @@
1212 import java.net.URI;
1313 import java.net.URL;
1414 import java.util.ArrayList;
15+import java.util.HashMap;
1516 import java.util.List;
1617 import java.util.Locale;
18+import java.util.Map;
1719 import java.util.logging.Level;
1820 import java.util.logging.Logger;
1921
@@ -25,11 +27,11 @@
2527 import charactermanaj.graphics.filters.ColorConvertParameter;
2628 import charactermanaj.model.CharacterData;
2729 import charactermanaj.model.ColorGroup;
28-import charactermanaj.model.ColorInfo;
30+import charactermanaj.model.IndependentPartsColorInfo;
31+import charactermanaj.model.IndependentPartsSetInfo;
32+import charactermanaj.model.IndependentPartsSetInfoList;
2933 import charactermanaj.model.Layer;
3034 import charactermanaj.model.PartsCategory;
31-import charactermanaj.model.PartsColorInfo;
32-import charactermanaj.model.PartsIdentifier;
3335 import charactermanaj.model.PartsSet;
3436 import charactermanaj.model.RecommendationURL;
3537 import charactermanaj.util.XMLUtilities;
@@ -422,208 +424,291 @@
422424 */
423425 protected void loadPartsSet(CharacterData characterData,
424426 Element nodePartssets, boolean presetParts, String lang) {
427+ IndependentPartsSetInfoList partsSetLst = loadPartsSetList(
428+ nodePartssets, lang);
429+ logger.info("partsSetList: size=" + partsSetLst.size());
425430
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+
426459 // デフォルトのパーツセット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+ }
429464
430465 // パーツセットリストの読み込み
431466 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);
435477 }
436- String displayName = getLocalizedElementText(presetElm,
437- "display-name", lang);
478+ }
438479
439- PartsSet partsSet = new PartsSet();
480+ if (defaultPresetId.length() == 0) {
481+ // デフォルトパーツセットがないことを示すためのnull
482+ defaultPresetId = null;
483+ }
484+ partsSetLst.setDefaultPresetId(defaultPresetId);
440485
441- partsSet.setPartsSetId(partsSetId);
442- partsSet.setLocalizedName(displayName);
443- partsSet.setPresetParts(presetParts);
486+ return partsSetLst;
487+ }
444488
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+ }
453502
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));
458543 }
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+ // 無視する.
459558 }
559+ }
460560
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();
478564
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();
485570 }
571+ if (categoryId == null || categoryId.length() == 0) {
572+ logger.log(Level.WARNING, "missing category refid: " + catElm);
573+ continue;
574+ }
486575
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);
494592 continue;
495593 }
496594
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+ }
500606
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+ }
503620
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();
517624
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);
522634
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+ }
537646
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);
611675 }
612- partsSet.appendParts(category, partsIdentifier,
613- partsColorInfo);
614676 }
615677 }
616678
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+ }
619697
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);
624708 }
625- characterData.setDefaultPartsSetId(defaultPresetId);
709+
710+ infoList.add(info);
626711 }
712+ return infoList;
627713 }
628-
629714 }
--- trunk/src/charactermanaj/model/IndependentPartsSetInfoList.java (nonexistent)
+++ trunk/src/charactermanaj/model/IndependentPartsSetInfoList.java (revision 90)
@@ -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
--- trunk/src/charactermanaj/model/WorkingSet.java (revision 89)
+++ trunk/src/charactermanaj/model/WorkingSet.java (revision 90)
@@ -27,6 +27,9 @@
2727
2828 private String characterDataRev;
2929
30+ /**
31+ * 現在の選択中のパーツと色設定からのパーツセット
32+ */
3033 private PartsSet partsSet;
3134
3235 private URI characterDocBase;
@@ -47,9 +50,13 @@
4750
4851 /**
4952 * デシリアライズ
50- * @param inp オブジェクトの復元ストリーム
51- * @throws IOException 例外
52- * @throws ClassNotFoundException 例外
53+ *
54+ * @param inp
55+ * オブジェクトの復元ストリーム
56+ * @throws IOException
57+ * 例外
58+ * @throws ClassNotFoundException
59+ * 例外
5360 */
5461 @SuppressWarnings("unchecked")
5562 private void readObject(ObjectInputStream inp) throws IOException,
@@ -96,6 +103,7 @@
96103 * REV情報.<br>
97104 * キャラクターデータが設定されていない場合に使用される.<br>
98105 * (ver0.96以前旧シリアライズデータ互換用)<br>
106+ *
99107 * @return
100108 */
101109 public String getCharacterDataRev() {
@@ -147,6 +155,7 @@
147155 * 最後に使用したお気に入りの情報.<br>
148156 * 一度もプリセットを使ってなければnull.<br>
149157 * ver0.94以前には存在しなかったため、nullになりえます。
158+ *
150159 * @return
151160 */
152161 public PartsSet getLastUsePresetParts() {
@@ -154,10 +163,10 @@
154163 }
155164
156165 /**
157- /**
158- * 最後に使用したお気に入りの情報.<br>
166+ * /** 最後に使用したお気に入りの情報.<br>
159167 * 一度もプリセットを使ってなければnull.<br>
160168 * (ver0.94以前には存在しなかったため、nullになりえます。)
169+ *
161170 * @param lastUsePresetParts
162171 */
163172 public void setLastUsePresetParts(PartsSet lastUsePresetParts) {
@@ -171,6 +180,7 @@
171180 /**
172181 * 使用していたキャラクター定義を取得します.<br>
173182 * ver0.95よりも以前には存在しないため、nullとなりえます.<br>
183+ *
174184 * @return キャラクターデータ
175185 */
176186 public CharacterData getCharacterData() {
@@ -180,6 +190,7 @@
180190 /**
181191 * 壁紙情報を取得します.<br>
182192 * ver0.97よりも以前には存在しないため、nullとなりえます.<br>
193+ *
183194 * @return 壁紙情報
184195 */
185196 public WallpaperInfo getWallpaperInfo() {
--- trunk/src/charactermanaj/model/util/StartupSupport.java (revision 89)
+++ trunk/src/charactermanaj/model/util/StartupSupport.java (revision 90)
@@ -1,12 +1,19 @@
11 package charactermanaj.model.util;
22
33 import java.io.File;
4+import java.io.FileFilter;
5+import java.io.OutputStream;
6+import java.net.URI;
47 import java.util.logging.Level;
58 import java.util.logging.Logger;
69
710 import charactermanaj.model.AppConfig;
11+import charactermanaj.model.WorkingSet;
12+import charactermanaj.model.io.WorkingSetXMLWriter;
13+import charactermanaj.ui.MainFrame;
814 import charactermanaj.ui.RecentCharactersDir;
915 import charactermanaj.util.FileUserData;
16+import charactermanaj.util.UserData;
1017 import charactermanaj.util.UserDataFactory;
1118
1219
@@ -33,10 +40,8 @@
3340 public void doStartup() {
3441 StartupSupport[] startups = {
3542 new PurgeOldLogs(),
36- // new UpgradeCache(),
37- // new UpgradeFavoritesXml(),
38- // new PurgeUnusedCache(),
3943 new ConvertRecentCharDirsSerToXmlProps(),
44+ new ConvertWorkingSetSerToXml(),
4045 };
4146 for (StartupSupport startup : startups) {
4247 logger.log(Level.FINE, "startup operation start. class="
@@ -100,363 +105,75 @@
100105 }
101106 }
102107
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());
163119
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+ }
344159
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();
391162
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+ }
459170
171+ } catch (Exception ex) {
172+ logger.log(Level.WARNING, FILENAME + " convert failed.", ex);
173+ }
174+ }
175+}
176+
460177 /**
461178 * 古いログファイルを消去する.
462179 *
--- trunk/src/charactermanaj/Main.java (revision 89)
+++ trunk/src/charactermanaj/Main.java (revision 90)
@@ -27,7 +27,7 @@
2727
2828 /**
2929 * エントリポイント用クラス
30- *
30+ *
3131 * @author seraphy
3232 */
3333 public final class Main implements Runnable {
@@ -89,7 +89,7 @@
8989 /**
9090 * Javaの簡易なバージョンを取得する.<br>
9191 * 不明な場合は0を返す.<br>
92- *
92+ *
9393 * @return バージョン
9494 */
9595 private static double getJavaVersion() {
@@ -107,7 +107,7 @@
107107
108108 /**
109109 * UIをセットアップする.
110- *
110+ *
111111 * @throws Exception
112112 * いろいろな失敗
113113 */
@@ -171,7 +171,7 @@
171171 logger.log(Level.WARNING, "failed to set the clipboard-support.");
172172 }
173173
174- // LANG, LC_CTYPEが設定されていない場合はエラーを表示する
174+ // LANG, またはLC_CTYPEが設定されていない場合はエラーを表示する
175175 // OSXのJava7(Oracle)を実行する場合、環境変数LANGまたはLC_CTYPEに正しくファイル名の文字コードが設定されていないと
176176 // ファイル名を正しく取り扱えず文字化けするため、実行前に確認し警告を表示する。
177177 if (isMacOSX() && getJavaVersion() >= 1.7) {
@@ -179,7 +179,10 @@
179179 String lcctype = System.getenv("LC_CTYPE");
180180 if ((lang == null || lang.trim().length() == 0) &&
181181 (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.",
183186 "Configuration Error", JOptionPane.ERROR_MESSAGE);
184187 }
185188 }
@@ -249,7 +252,7 @@
249252 /**
250253 * エントリポイント.<br>
251254 * 最初のメインフレームを開いたときにMac OS Xであればスクリーンメニューの登録も行う.<br>
252- *
255+ *
253256 * @param args
254257 * 引数(未使用)
255258 */
@@ -257,22 +260,22 @@
257260 // ロガー等の初期化
258261 initLogger();
259262
260- // MBeanのセットアップ
263+ // MBeanのセットアップ
261264 try {
262265 ImageCacheMBeanImpl.setupMBean();
263266
264267 } catch (JMException ex) {
265- // 失敗しても無視して継続する.
268+ // 失敗しても無視して継続する.
266269 logger.log(Level.SEVERE, ex.getMessage(), ex);
267270 }
268271
269- // フレームの生成等は、SwingのEDTで実行する.
272+ // フレームの生成等は、SwingのEDTで実行する.
270273 SwingUtilities.invokeLater(new Main());
271274 }
272275
273276 /**
274277 * Mac OS Xで動作しているか?
275- *
278+ *
276279 * @return Max OS X上であればtrue
277280 */
278281 public static boolean isMacOSX() {
@@ -281,7 +284,7 @@
281284
282285 /**
283286 * Mac OS X、もしくはlinuxで動作しているか?
284- *
287+ *
285288 * @return Mac OS X、もしくはlinuxで動作していればtrue
286289 */
287290 public static boolean isLinuxOrMacOSX() {
--- trunk/src/charactermanaj/ui/MainFrame.java (revision 89)
+++ trunk/src/charactermanaj/ui/MainFrame.java (revision 90)
@@ -1,6 +1,7 @@
11 package charactermanaj.ui;
22
3-import static java.lang.Math.*;
3+import static java.lang.Math.max;
4+import static java.lang.Math.min;
45
56 import java.awt.BorderLayout;
67 import java.awt.Color;
@@ -22,8 +23,10 @@
2223 import java.awt.image.BufferedImage;
2324 import java.io.File;
2425 import java.io.IOException;
26+import java.io.InputStream;
2527 import java.io.OutputStream;
2628 import java.lang.reflect.InvocationTargetException;
29+import java.net.URI;
2730 import java.util.ArrayList;
2831 import java.util.Collections;
2932 import java.util.Comparator;
@@ -67,6 +70,7 @@
6770 import charactermanaj.model.AppConfig;
6871 import charactermanaj.model.CharacterData;
6972 import charactermanaj.model.ColorGroup;
73+import charactermanaj.model.IndependentPartsSetInfo;
7074 import charactermanaj.model.PartsCategory;
7175 import charactermanaj.model.PartsColorInfo;
7276 import charactermanaj.model.PartsColorManager;
@@ -74,6 +78,7 @@
7478 import charactermanaj.model.PartsSet;
7579 import charactermanaj.model.RecommendationURL;
7680 import charactermanaj.model.WorkingSet;
81+import charactermanaj.model.WorkingSet2;
7782 import charactermanaj.model.io.CharacterDataPersistent;
7883 import charactermanaj.model.io.PartsImageDirectoryWatchAgent;
7984 import charactermanaj.model.io.PartsImageDirectoryWatchAgentFactory;
@@ -80,6 +85,7 @@
8085 import charactermanaj.model.io.PartsImageDirectoryWatchEvent;
8186 import charactermanaj.model.io.PartsImageDirectoryWatchListener;
8287 import charactermanaj.model.io.RecentDataPersistent;
88+import charactermanaj.model.io.WorkingSetXMLReader;
8389 import charactermanaj.model.io.WorkingSetXMLWriter;
8490 import charactermanaj.ui.ImageSelectPanel.ImageSelectPanelEvent;
8591 import charactermanaj.ui.ImageSelectPanel.ImageSelectPanelListener;
@@ -108,7 +114,7 @@
108114 /**
109115 * メインフレーム.<br>
110116 * アプリケーションがアクティブである場合は最低でも1つのメインフレームが表示されている.<br>
111- *
117+ *
112118 * @author seraphy
113119 */
114120 public class MainFrame extends JFrame {
@@ -122,6 +128,7 @@
122128
123129 protected static final String MENU_STRINGS_RESOURCE = "menu/menu";
124130
131+ public static final String WORKINGSET_FILE_SUFFIX = "workingset.xml";
125132
126133 /**
127134 * メインフレームのアイコン.<br>
@@ -235,7 +242,7 @@
235242
236243 /**
237244 * アクティブなメインフレームを設定する.
238- *
245+ *
239246 * @param mainFrame
240247 * メインフレーム
241248 */
@@ -249,7 +256,7 @@
249256 /**
250257 * 現在アクティブなメインフレームを取得する. まだメインフレームが開かれていない場合はnull.<br>
251258 * 最後のメインフレームが破棄中、もしくは破棄済みであれば破棄されたフレームを示すことに注意.<br>
252- *
259+ *
253260 * @return メインフレーム、もしくはnull
254261 */
255262 public static MainFrame getActivedMainFrame() {
@@ -258,7 +265,7 @@
258265
259266 /**
260267 * インポートされパーツが増減した可能性がある場合に呼び出される.
261- *
268+ *
262269 * @param cd
263270 * 対象
264271 * @param newCd
@@ -325,7 +332,7 @@
325332
326333 /**
327334 * キャラクターデータが変更されたことを通知される.<br>
328- *
335+ *
329336 * @param cd
330337 * キャラクターデータ(変更前)
331338 * @param newCd
@@ -412,7 +419,7 @@
412419
413420 /**
414421 * お気に入りデータが変更されたことを通知される.
415- *
422+ *
416423 * @param cd
417424 * キャラクターデータ
418425 */
@@ -441,7 +448,7 @@
441448
442449 /**
443450 * メインフレームを構築する.
444- *
451+ *
445452 * @param characterData
446453 * キャラクターデータ
447454 */
@@ -885,7 +892,7 @@
885892
886893 /**
887894 * 指定したパーツカテゴリ以外のパーツ選択パネルを最小化する.
888- *
895+ *
889896 * @param partsCategory
890897 * パーツカテゴリ、nullの場合は全て最小化する.
891898 * @param dblClick
@@ -932,7 +939,7 @@
932939 * デフォルトパーツがなければお気に入りの最初のものを選択する.<br>
933940 * それもなければ空として表示する.<br>
934941 * パーツの適用に失敗した場合はfalseを返します.(例外は返されません.)<br>
935- *
942+ *
936943 * @param force
937944 * すでに選択があっても選択しなおす場合はtrue、falseの場合は選択があれば何もしない.
938945 * @return パーツ選択された場合。force=trueの場合はエラーがなければ常にtrueとなります。
@@ -982,7 +989,7 @@
982989 /**
983990 * プリセットを適用しキャラクターイメージを再構築します.<br>
984991 * 実行時エラーは画面のレポートされます.<br>
985- *
992+ *
986993 * @param presetParts
987994 * パーツセット, nullの場合は何もしない.
988995 */
@@ -1007,7 +1014,7 @@
10071014
10081015 /**
10091016 * プリセットとお気に入りを表示順に並べて返す.
1010- *
1017+ *
10111018 * @return プリセットとお気に入りのリスト(表示順)
10121019 */
10131020 protected List<PartsSet> getPartsSetList() {
@@ -1030,7 +1037,7 @@
10301037
10311038 /**
10321039 * お気に入りメニューが開いたとき
1033- *
1040+ *
10341041 * @param menu
10351042 */
10361043 protected void onSelectedFavoriteMenu(JMenu menu) {
@@ -1075,7 +1082,7 @@
10751082
10761083 /**
10771084 * ヘルプメニューを開いたときにお勧めメニューを構築する.
1078- *
1085+ *
10791086 * @param menu
10801087 */
10811088 protected void onSelectedRecommendationMenu(JMenu mnuRecomendation) {
@@ -1114,7 +1121,7 @@
11141121 * 最後に選択されたお気に入りと同じ構成であれば、 このお気に入りの名前をプレビューペインのタイトルに設定する.<br>
11151122 * そうでなければデフォルトのパーツセット名(no titleとか)を表示する.<br>
11161123 * 色情報が異なる場合に末尾に「*」マークがつけられる.<br>
1117- *
1124+ *
11181125 * @param requestPartsSet
11191126 * 表示するパーツセット(名前は設定されていなくて良い。お気に入り側を使うので。), nullの場合はデフォルトのパーツ名
11201127 */
@@ -1130,7 +1137,7 @@
11301137 * パーツセット名を推定する.<br>
11311138 * 最後に選択されたお気に入りと同じ構成であれば、 このお気に入りの名前を返す.<br>
11321139 * お気に入りが選択されていないか構成が異なる場合、お気に入りに名前がない場合はnullを返す.<br>
1133- *
1140+ *
11341141 * @param requestPartsSet
11351142 * 表示するパーツセット(名前は設定されていなくて良い。お気に入り側を使うので。)
11361143 * @param markColorChange
@@ -1314,7 +1321,7 @@
13141321 /**
13151322 * 背景色のみ変更し、背景を再描画する.<br>
13161323 * 壁紙情報全体の更新よりも効率化するためのメソッドである.<br>
1317- *
1324+ *
13181325 * @param bgColor
13191326 * 背景色
13201327 */
@@ -1327,7 +1334,7 @@
13271334 /**
13281335 * 壁紙情報を保存し、その情報をもとに背景を再描画する.<br>
13291336 * ignoreErrorがtrueである場合、適用に失敗した場合はログに記録するのみで、 壁紙情報は保存されず、壁紙も更新されない.<br>
1330- *
1337+ *
13311338 * @param wallpaperInfo
13321339 * 壁紙情報、null不可
13331340 * @param ignoreError
@@ -1557,7 +1564,7 @@
15571564
15581565 /**
15591566 * クリップボードにコピー
1560- *
1567+ *
15611568 * @param screenImage
15621569 * スクリーンイメージ
15631570 */
@@ -1630,7 +1637,7 @@
16301637 * 現在のプロファイルに対するインポートウィザードを実行する.<br>
16311638 * インポートが実行された場合は、パーツをリロードする.<br>
16321639 * インポートウィザード表示中は監視スレッドは停止される.<br>
1633- *
1640+ *
16341641 * @param initFile
16351642 * アーカイブファィルまたはディレクトリ、指定がなければnull
16361643 */
@@ -1667,7 +1674,7 @@
16671674 * まだロードされていない場合はあらたにロードする.<br>
16681675 * 引数newCdが指定されている場合は、現在のキャラクター定義の説明文を更新する.<br>
16691676 * (説明文の更新以外には使用されない.)<br>
1670- *
1677+ *
16711678 * @param newCd
16721679 * 説明文更新のための更新されたキャラクターデータを指定する。null可
16731680 * @param forceRepaint
@@ -1813,36 +1820,6 @@
18131820 }
18141821
18151822 /**
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- /**
18461823 * 画面の作業状態を保存する.
18471824 */
18481825 protected void saveWorkingSet() {
@@ -1850,12 +1827,14 @@
18501827 return;
18511828 }
18521829 try {
1830+ // ワーキングセットの作成
18531831 WorkingSet workingSet = new WorkingSet();
18541832 workingSet.setCharacterDocBase(characterData.getDocBase());
18551833 workingSet.setCharacterDataRev(characterData.getRev());
18561834 PartsSet partsSet = partsSelectionManager.createPartsSet();
18571835 workingSet.setPartsSet(partsSet);
1858- workingSet.setPartsColorInfoMap(characterData.getPartsColorManager().getPartsColorInfoMap());
1836+ workingSet.setPartsColorInfoMap(characterData
1837+ .getPartsColorManager().getPartsColorInfoMap());
18591838 workingSet.setLastUsedSaveDir(imageSaveHelper.getLastUsedSaveDir());
18601839 workingSet.setLastUsedExportDir(ExportWizardDialog.getLastUsedDir());
18611840 workingSet.setLastUsePresetParts(lastUsePresetParts);
@@ -1863,13 +1842,11 @@
18631842 .setCharacterData(characterData.duplicateBasicInfo(false)); // パーツセットは保存しない.
18641843 workingSet.setWallpaperInfo(wallpaperInfo);
18651844
1866- UserData workingSetStore = getWorkingSetUserData(false);
1867- workingSetStore.save(workingSet);
1868-
18691845 // XML形式でのワーキングセットの保存
18701846 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();
18731850 try {
18741851 WorkingSetXMLWriter workingSetXmlWriter = new WorkingSetXMLWriter();
18751852 workingSetXmlWriter.writeWorkingSet(workingSet, outstm);
@@ -1884,7 +1861,7 @@
18841861
18851862 /**
18861863 * 画面の作業状態を復元する.
1887- *
1864+ *
18881865 * @return
18891866 */
18901867 protected boolean loadWorkingSet() {
@@ -1892,72 +1869,79 @@
18921869 return false;
18931870 }
18941871 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;
19031881
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);
19141886
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+ }
19201890
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+ }
19311902
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);
19371907
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)) {
19421926 this.lastUsePresetParts = lastUsePresetParts;
19431927 showPresetName(lastUsePresetParts);
19441928 }
19451929 }
1930+ }
19461931
1947- // 最後に保存したディレクトリを復元する.
1948- imageSaveHelper.setLastUseSaveDir(workingSet.getLastUsedSaveDir());
1949- ExportWizardDialog.setLastUsedDir(workingSet.getLastUsedExportDir());
1932+ // 最後に保存したディレクトリを復元する.
1933+ imageSaveHelper.setLastUseSaveDir(workingSet2.getLastUsedSaveDir());
1934+ ExportWizardDialog.setLastUsedDir(workingSet2
1935+ .getLastUsedExportDir());
19501936
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);
19601943 }
1944+ return true;
19611945
19621946 } catch (Exception ex) {
19631947 ErrorMessageHelper.showErrorDialog(this, ex);
@@ -2216,7 +2200,7 @@
22162200
22172201 /**
22182202 * メニューバーを構築します.
2219- *
2203+ *
22202204 * @return メニューバー
22212205 */
22222206 protected JMenuBar createMenuBar() {
--- trunk/resources/schema/character_inc.xsd (revision 89)
+++ trunk/resources/schema/character_inc.xsd (revision 90)
@@ -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" />
104 <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>
148 <xs:restriction base="xs:token">
15- <xs:minLength value="1"/>
9+ <xs:minLength value="1" />
1610 </xs:restriction>
1711 </xs:simpleType>
18-
1912 <xs:simpleType name="floatMax1">
2013 <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" />
2316 </xs:restriction>
2417 </xs:simpleType>
25-
2618 <xs:simpleType name="floatMax1Round">
2719 <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" />
3022 </xs:restriction>
3123 </xs:simpleType>
32-
3324 <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>
3728 <xs:attribute name="offset" form="unqualified" type="xs:integer" use="required">
3829 <xs:annotation>
3930 <xs:documentation xml:lang="ja">オフセット</xs:documentation>
@@ -50,34 +41,32 @@
5041 </xs:annotation>
5142 </xs:attribute>
5243 </xs:complexType>
53-
5444 <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追加 -->
6253 </xs:complexType>
63-
6454 <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>
6858 <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" />
7868 </xs:restriction>
7969 </xs:simpleType>
80-
8170 <xs:complexType name="rgbreplacevalue">
8271 <xs:attribute name="replace-type" form="unqualified" use="required" type="rgbreplacetype">
8372 <xs:annotation>
@@ -90,7 +79,6 @@
9079 </xs:annotation>
9180 </xs:attribute>
9281 </xs:complexType>
93-
9482 <xs:complexType name="presetsType">
9583 <xs:annotation>
9684 <xs:documentation xml:lang="ja">定義済みパーツ組み合わせ例(プリセット)の定義リスト、定義順に表示される。</xs:documentation>
@@ -109,7 +97,7 @@
10997 <xs:complexType>
11098 <xs:simpleContent>
11199 <xs:extension base="tokenNotEmpty">
112- <xs:attribute ref="xml:lang" use="required"/>
100+ <xs:attribute ref="xml:lang" use="required" />
113101 </xs:extension>
114102 </xs:simpleContent>
115103 </xs:complexType>
@@ -119,7 +107,7 @@
119107 <xs:documentation xml:lang="ja">背景色</xs:documentation>
120108 </xs:annotation>
121109 <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" />
123111 </xs:complexType>
124112 </xs:element>
125113 <xs:element name="affine-transform-parameter" minOccurs="0" maxOccurs="1">
@@ -127,7 +115,7 @@
127115 <xs:documentation xml:lang="ja">アフィン変換用パラメータ、4または6つの要素からなるマトリックス</xs:documentation>
128116 </xs:annotation>
129117 <xs:simpleType>
130- <xs:list itemType="xs:double"/>
118+ <xs:list itemType="xs:double" />
131119 </xs:simpleType>
132120 </xs:element>
133121 <xs:element name="category" nillable="false" minOccurs="1" maxOccurs="unbounded">
@@ -142,58 +130,58 @@
142130 </xs:annotation>
143131 <xs:complexType>
144132 <xs:sequence>
145- <xs:element name="color" nillable="false" minOccurs="0" maxOccurs="1">
133+ <xs:element name="color" nillable="false" minOccurs="0" maxOccurs="1">
146134 <xs:annotation>
147135 <xs:documentation xml:lang="ja">色定義(オプション)</xs:documentation>
148136 </xs:annotation>
149137 <xs:complexType>
150- <xs:sequence>
138+ <xs:sequence>
151139 <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">
157145 <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">
162150 <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>
197185 </xs:sequence>
198186 <xs:attribute name="refid" use="required" form="unqualified" type="tokenNotEmpty">
199187 <xs:annotation>
@@ -241,5 +229,4 @@
241229 </xs:annotation>
242230 </xs:attribute>
243231 </xs:complexType>
244-
245-</xs:schema>
232+</xs:schema>
\ No newline at end of file
--- trunk/resources/schema/character.xsd (revision 89)
+++ trunk/resources/schema/character.xsd (revision 90)
@@ -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" />
115 <xs:element name="character">
126 <xs:annotation>
137 <xs:documentation xml:lang="ja">キャラクターデータの定義</xs:documentation>
@@ -21,12 +15,11 @@
2115 <xs:complexType>
2216 <xs:simpleContent>
2317 <xs:extension base="tokenNotEmpty">
24- <xs:attribute ref="xml:lang" use="required" />
18+ <xs:attribute ref="xml:lang" use="required" />
2519 </xs:extension>
2620 </xs:simpleContent>
2721 </xs:complexType>
2822 </xs:element>
29-
3023 <xs:element name="information" minOccurs="0" maxOccurs="1">
3124 <xs:annotation>
3225 <xs:documentation xml:lang="ja">備考</xs:documentation>
@@ -60,7 +53,6 @@
6053 </xs:sequence>
6154 </xs:complexType>
6255 </xs:element>
63-
6456 <xs:element name="image-size">
6557 <xs:annotation>
6658 <xs:documentation xml:lang="ja">イメージのサイズ(幅と高さ)</xs:documentation>
@@ -70,7 +62,7 @@
7062 <xs:element name="width">
7163 <xs:simpleType>
7264 <xs:restriction base="xs:unsignedInt">
73- <xs:minExclusive value="0"/>
65+ <xs:minExclusive value="0" />
7466 </xs:restriction>
7567 </xs:simpleType>
7668 </xs:element>
@@ -77,7 +69,7 @@
7769 <xs:element name="height">
7870 <xs:simpleType>
7971 <xs:restriction base="xs:unsignedInt">
80- <xs:minExclusive value="0"/>
72+ <xs:minExclusive value="0" />
8173 </xs:restriction>
8274 </xs:simpleType>
8375 </xs:element>
@@ -84,7 +76,6 @@
8476 </xs:sequence>
8577 </xs:complexType>
8678 </xs:element>
87-
8879 <xs:element name="settings" minOccurs="0" maxOccurs="1">
8980 <xs:annotation>
9081 <xs:documentation xml:lang="ja">雑多なプロパティのコレクション</xs:documentation>
@@ -98,7 +89,7 @@
9889 <xs:complexType>
9990 <xs:simpleContent>
10091 <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" />
10293 </xs:extension>
10394 </xs:simpleContent>
10495 </xs:complexType>
@@ -106,7 +97,6 @@
10697 </xs:sequence>
10798 </xs:complexType>
10899 </xs:element>
109-
110100 <xs:element name="categories">
111101 <xs:annotation>
112102 <xs:documentation xml:lang="ja">カテゴリの定義リスト、出現順で画面に表示される。</xs:documentation>
@@ -131,7 +121,7 @@
131121 <xs:complexType>
132122 <xs:simpleContent>
133123 <xs:extension base="tokenNotEmpty">
134- <xs:attribute ref="xml:lang" use="required"/>
124+ <xs:attribute ref="xml:lang" use="required" />
135125 </xs:extension>
136126 </xs:simpleContent>
137127 </xs:complexType>
@@ -155,7 +145,7 @@
155145 <xs:complexType>
156146 <xs:simpleContent>
157147 <xs:extension base="tokenNotEmpty">
158- <xs:attribute ref="xml:lang" use="required"/>
148+ <xs:attribute ref="xml:lang" use="required" />
159149 </xs:extension>
160150 </xs:simpleContent>
161151 </xs:complexType>
@@ -181,8 +171,8 @@
181171 </xs:annotation>
182172 <xs:simpleType>
183173 <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" />
186176 </xs:restriction>
187177 </xs:simpleType>
188178 </xs:attribute>
@@ -221,8 +211,8 @@
221211 </xs:annotation>
222212 <xs:simpleType>
223213 <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" />
226216 </xs:restriction>
227217 </xs:simpleType>
228218 </xs:attribute>
@@ -231,7 +221,6 @@
231221 </xs:sequence>
232222 </xs:complexType>
233223 </xs:element>
234-
235224 <xs:element name="colorGroups" minOccurs="0" maxOccurs="1">
236225 <xs:annotation>
237226 <xs:documentation xml:lang="ja">カラーグループの定義リスト</xs:documentation>
@@ -251,7 +240,7 @@
251240 <xs:complexType>
252241 <xs:simpleContent>
253242 <xs:extension base="tokenNotEmpty">
254- <xs:attribute ref="xml:lang" use="required"/>
243+ <xs:attribute ref="xml:lang" use="required" />
255244 </xs:extension>
256245 </xs:simpleContent>
257246 </xs:complexType>
@@ -267,7 +256,6 @@
267256 </xs:sequence>
268257 </xs:complexType>
269258 </xs:element>
270-
271259 <xs:element name="recommendations" minOccurs="0" maxOccurs="1">
272260 <xs:annotation>
273261 <xs:documentation xml:lang="ja">お薦めリンクのリスト</xs:documentation>
@@ -318,16 +306,14 @@
318306 </xs:sequence>
319307 </xs:complexType>
320308 </xs:element>
321-
322309 <xs:element name="presets" minOccurs="0" maxOccurs="1" type="presetsType">
323310 <xs:annotation>
324311 <xs:documentation xml:lang="ja">定義済みパーツ組み合わせ例(プリセット)の定義リスト、定義順に表示される。</xs:documentation>
325312 </xs:annotation>
326- </xs:element>
327-
313+ </xs:element>
328314 </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" />
331317 <xs:attribute name="version" form="unqualified" type="tokenNotEmpty" use="required">
332318 <xs:annotation>
333319 <xs:documentation xml:lang="ja">このXMLのバージョン番号、1.0固定。</xs:documentation>
@@ -334,18 +320,17 @@
334320 </xs:annotation>
335321 </xs:attribute>
336322 </xs:complexType>
337-
338323 <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" />
341326 </xs:key>
342327 <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" />
345330 </xs:key>
346331 <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" />
349334 </xs:key>
350335 </xs:element>
351-</xs:schema>
336+</xs:schema>
\ No newline at end of file
旧リポジトリブラウザで表示