partsImageCollectorParser.parse(partsSet, layerOrderMapper,\r
new PartsImageCollectionParser.PartsImageCollectionHandler() {\r
public void detectImageSource(PartsIdentifier partsIdentifier,\r
- Layer layer, int layerOrder, ImageResource imageResource,\r
+ Layer layer, float layerOrder, ImageResource imageResource,\r
ColorConvertParameter param) {\r
if (param == null) {\r
param = new ColorConvertParameter();\r
* @param param\r
* 色変換情報\r
*/\r
- void setImageSource(Layer layer, int layerOrder, ImageResource imageResource, ColorConvertParameter param);\r
+ void setImageSource(Layer layer, float layerOrder, ImageResource imageResource, ColorConvertParameter param);\r
\r
/**\r
* パーツの登録が完了したことを通知する。\r
}\r
}\r
// ジョブリクエスト側よりパーツの登録として呼び出される\r
- public void setImageSource(Layer layer, int layerOrder, ImageResource imageResource,\r
+ public void setImageSource(Layer layer, float layerOrder, ImageResource imageResource,\r
ColorConvertParameter param) {\r
synchronized (imageBuildInfo) {\r
imageBuildInfo.add(new ImageBuildPartsInfo(\r
\r
/**\r
* 合成する個々のイメージ情報 .<br>\r
- * レイヤー順に順序づけられており、同一レイヤーであればOrder順に順序づけられます.<br>\r
+ * 補正済みレイヤー順に順序づけられており、同一レイヤーであればOrder順(定義順)に順序づけられます.<br>\r
*\r
* @author seraphy\r
*/\r
final class ImageBuildPartsInfo implements Comparable<ImageBuildPartsInfo> {\r
\r
+ /**\r
+ * 定義順\r
+ */\r
private int order;\r
\r
- private int layerOrder;\r
+ /**\r
+ * 補正済みレイヤー順\r
+ */\r
+ private float layerOrder;\r
\r
private Layer layer;\r
\r
\r
private ColorConvertParameter colorParam;\r
\r
- public ImageBuildPartsInfo(int order, Layer layer, int layerOrder, ImageResource imageResource,\r
+ public ImageBuildPartsInfo(int order, Layer layer, float layerOrder, ImageResource imageResource,\r
ColorConvertParameter colorParam) {\r
this.order = order;\r
this.layer = layer;\r
\r
public int compareTo(ImageBuildPartsInfo o) {\r
// 補正済みレイヤー順\r
- int ret = layerOrder - o.layerOrder;\r
+ int ret = Float.compare(layerOrder, o.layerOrder);\r
if (ret == 0) {\r
// レイヤー順(フォールバック用。layerOrderが設定されていれば必要ない)\r
ret = layer.compareTo(o.layer);\r
return layer;\r
}\r
\r
- public int getLayerOrder() {\r
+ public float getLayerOrder() {\r
return layerOrder;\r
}\r
\r
package charactermanaj.graphics.filters;\r
\r
-import java.io.IOException;\r
-import java.io.ObjectInputStream;\r
-import java.io.ObjectInputStream.GetField;\r
-import java.io.Serializable;\r
-\r
/**\r
* カラー情報.<br>\r
* RGB置換、GrayLevel、RGBオフセット各種、HSB調整値を持つ.<br>\r
* @author seraphy\r
*/\r
-public final class ColorConvertParameter implements Serializable, Cloneable {\r
-\r
- private static final long serialVersionUID = 3092895708547846162L;\r
+public final class ColorConvertParameter implements Cloneable {\r
\r
/**\r
* 色置換パターン\r
* グレーレベル(0でモノトーン、1でノーマル、0.5で半分ほどモノトーン化)\r
*/\r
private float grayLevel = 1.f;\r
- \r
+\r
private float hue = 0.f;\r
- \r
+\r
private float saturation = 0.f;\r
\r
private float brightness = 0.f;\r
- \r
+\r
private float contrast = 0.f;\r
\r
private int offsetR = 0;\r
private int offsetB = 0;\r
\r
private int offsetA = 0;\r
- \r
+\r
private float factorR = 1.f;\r
\r
private float factorG = 1.f;\r
private float factorB = 1.f;\r
\r
private float factorA = 1.f;\r
- \r
+\r
private float gammaR = 1.f;\r
\r
private float gammaG = 1.f;\r
private float gammaB = 1.f;\r
\r
private float gammaA = 1.f;\r
- \r
- private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {\r
- GetField fields = stream.readFields();\r
- this.rgbChanelMixierPattern = (ColorConv) fields.get("rgbChanelMixierPattern", ColorConv.NONE);\r
- this.grayLevel = fields.get("grayLevel", 1.f);\r
- this.hue = fields.get("hue", 0.f);\r
- this.saturation = fields.get("saturation", 0.f);\r
- this.brightness = fields.get("brightness", 0.f);\r
- this.contrast = fields.get("contrast", 0.f);\r
- this.offsetR = fields.get("offsetR", 0);\r
- this.offsetG = fields.get("offsetG", 0);\r
- this.offsetB = fields.get("offsetB", 0);\r
- this.offsetA = fields.get("offsetA", 0);\r
- this.factorR = fields.get("factorR", 1.f);\r
- this.factorG = fields.get("factorG", 1.f);\r
- this.factorB = fields.get("factorB", 1.f);\r
- this.factorA = fields.get("factorA", 1.f);\r
- this.gammaR = fields.get("gammaR", 1.f);\r
- this.gammaG = fields.get("gammaG", 1.f);\r
- this.gammaB = fields.get("gammaB", 1.f);\r
- this.gammaA = fields.get("gammaA", 1.f);\r
- }\r
\r
@Override\r
public int hashCode() {\r
ret ^= (int)(gammaA * 100);\r
return ret;\r
}\r
- \r
+\r
@Override\r
public boolean equals(Object obj) {\r
if (obj == this) {\r
}\r
return false;\r
}\r
- \r
+\r
public static boolean equals(ColorConvertParameter a, ColorConvertParameter b) {\r
if (a == b) {\r
return true;\r
}\r
return false;\r
}\r
- \r
+\r
@Override\r
public ColorConvertParameter clone() {\r
try {\r
throw new Error("internal error.");\r
}\r
}\r
- \r
+\r
public ColorConv getColorReplace() {\r
return rgbChanelMixierPattern;\r
}\r
public void setBrightness(float brightness) {\r
this.brightness = brightness;\r
}\r
- \r
+\r
public float getContrast() {\r
return contrast;\r
}\r
- \r
+\r
public void setContrast(float contrast) {\r
this.contrast = contrast;\r
}\r
public void setGammaA(float gammaA) {\r
this.gammaA = gammaA;\r
}\r
- \r
+\r
@Override\r
public String toString() {\r
StringBuilder buf = new StringBuilder();\r
buf.append(")");\r
return buf.toString();\r
}\r
- \r
+\r
}\r
\r
import java.io.IOException;\r
import java.io.InputStream;\r
-import java.io.Serializable;\r
import java.net.URI;\r
import java.net.URISyntaxException;\r
import java.net.URL;\r
* クラスローダからリソースを読み込むイメージリソース.<br>\r
* @author seraphy\r
*/\r
-public class EmbeddedImageResource extends ResourceLoader implements ImageResource, Serializable {\r
- \r
- /**\r
- * シリアライズバージョン\r
- */\r
- private static final long serialVersionUID = 703707046457343373L;\r
+public class EmbeddedImageResource extends ResourceLoader implements ImageResource {\r
\r
/**\r
* ロガー\r
* ファイル\r
*/\r
private String resourceName;\r
- \r
- \r
+\r
+\r
public EmbeddedImageResource(String resourceName) {\r
if (resourceName == null) {\r
throw new IllegalArgumentException();\r
}\r
this.resourceName = resourceName;\r
}\r
- \r
+\r
public int compareTo(ImageResource o) {\r
return getFullName().compareTo(o.getFullName());\r
}\r
- \r
+\r
@Override\r
public int hashCode() {\r
return getFullName().hashCode();\r
}\r
return false;\r
}\r
- \r
+\r
public String getFullName() {\r
return resourceName;\r
}\r
- \r
+\r
public URI getURI() {\r
URL url = getResource(resourceName);\r
if (url != null) {\r
}\r
return null;\r
}\r
- \r
+\r
/**\r
* リソースが実在すれば日付は常に1を返す.<br>\r
* リソースが存在しなければ0を返す.<br>\r
}\r
return 0;\r
}\r
- \r
+\r
public InputStream openStream() throws IOException {\r
URL url = getResource(resourceName);\r
if (url == null) {\r
}\r
return url.openStream();\r
}\r
- \r
+\r
@Override\r
public String toString() {\r
return getFullName();\r
import java.io.FileInputStream;\r
import java.io.IOException;\r
import java.io.InputStream;\r
-import java.io.Serializable;\r
import java.net.URI;\r
\r
/**\r
* ファイルシステム上にある画像リソースを示す.\r
* @author seraphy\r
*/\r
-public class FileImageResource implements ImageResource, Serializable {\r
-\r
- /**\r
- * シリアライズバージョン\r
- */\r
- private static final long serialVersionUID = 5397113740824387869L;\r
+public class FileImageResource implements ImageResource {\r
\r
/**\r
* ファイル\r
*/\r
private File file;\r
- \r
- \r
+\r
+\r
public FileImageResource(File file) {\r
if (file == null) {\r
throw new IllegalArgumentException();\r
}\r
this.file = file;\r
}\r
- \r
- \r
+\r
+\r
public long lastModified() {\r
return file.lastModified();\r
}\r
- \r
+\r
public InputStream openStream() throws IOException {\r
return new BufferedInputStream(new FileInputStream(file));\r
}\r
- \r
+\r
@Override\r
public int hashCode() {\r
return file.hashCode();\r
}\r
- \r
+\r
public int compareTo(ImageResource o) {\r
return getFullName().compareTo(o.getFullName());\r
}\r
- \r
+\r
@Override\r
public boolean equals(Object obj) {\r
if (obj == this) {\r
}\r
return false;\r
}\r
- \r
+\r
public String getFullName() {\r
return file.getPath();\r
}\r
- \r
+\r
public URI getURI() {\r
return file.toURI();\r
}\r
- \r
+\r
@Override\r
public String toString() {\r
return file.toString();\r
package charactermanaj.graphics.io;\r
\r
-import java.io.Serializable;\r
-\r
import charactermanaj.util.LocalizedMessageAware;\r
\r
/**\r
* 出力オプションモデル.\r
* @author seraphy\r
*/\r
-public class OutputOption implements Serializable, Cloneable {\r
-\r
- private static final long serialVersionUID = -879599688492364852L;\r
+public class OutputOption implements Cloneable {\r
\r
/**\r
* 拡大縮小時に使用するレンダリングオプション.\r
NONE,\r
BILINER,\r
BICUBIC;\r
- \r
+\r
public String getLocalizedResourceId() {\r
return "outputOption.zoomRenderingType." + name();\r
}\r
* JPEG品質\r
*/\r
private double jpegQuality = 1.;\r
- \r
+\r
/**\r
* ズームの使用可否\r
*/\r
private boolean enableZoom;\r
- \r
+\r
/**\r
* 拡大率\r
*/\r
private double zoomFactor = 1.;\r
- \r
+\r
/**\r
* 拡大縮小に使うアルゴリズム\r
*/\r
private ZoomRenderingType zoomRenderingType = ZoomRenderingType.NONE;\r
- \r
+\r
/**\r
* 出力画像のタイプ\r
*/\r
private PictureMode pictureMode = PictureMode.NORMAL;\r
- \r
+\r
/**\r
* 背景色を強制するか?\r
*/\r
throw new RuntimeException(ex);\r
}\r
}\r
- \r
+\r
public double getJpegQuality() {\r
return jpegQuality;\r
}\r
}\r
this.pictureMode = pictureMode;\r
}\r
- \r
+\r
public boolean isForceBgColor() {\r
return forceBgColor;\r
}\r
- \r
+\r
public void setForceBgColor(boolean forceBgColor) {\r
this.forceBgColor = forceBgColor;\r
}\r
- \r
+\r
public void setEnableZoom(boolean enableZoom) {\r
this.enableZoom = enableZoom;\r
}\r
- \r
+\r
public boolean isEnableZoom() {\r
return enableZoom;\r
}\r
- \r
+\r
/**\r
* 推奨値に変更する.\r
*/\r
public void changeRecommend() {\r
if (zoomFactor > 1.) {\r
zoomRenderingType = ZoomRenderingType.BICUBIC;\r
- \r
+\r
} else if (zoomFactor < 1.) {\r
zoomRenderingType = ZoomRenderingType.BILINER;\r
\r
import java.awt.Dimension;\r
import java.io.File;\r
import java.io.IOException;\r
-import java.io.Serializable;\r
import java.net.URI;\r
import java.util.ArrayList;\r
import java.util.Arrays;\r
* キャラクターデータ\r
* @author seraphy\r
*/\r
-public class CharacterData implements Serializable, PartsSpecResolver {\r
-\r
- /**\r
- * シリアライズバージョン \r
- */\r
- private static final long serialVersionUID = -381763373314240953L;\r
+public class CharacterData implements PartsSpecResolver {\r
\r
/**\r
* ロガー\r
}\r
};\r
\r
- \r
+\r
/**\r
* キャラクターデータを定義しているXMLの位置.<br>\r
* docBase自身はxml定義には含まれず、xmlをロードした位置を記憶するためにPersistentクラスによって設定される.<br>\r
*/\r
private URI docBase;\r
\r
- \r
- \r
+\r
+\r
/**\r
* キャラクターデータの内部用ID.<br>\r
* キャラクターデータの構造を判定するために用いる.<br>\r
*/\r
private String id;\r
- \r
+\r
/**\r
* キャラクターデータの更新番号.<br>\r
* キャラクターデータの構造が変更されたことを識別するために用いる.<br>\r
*/\r
private String rev;\r
- \r
+\r
/**\r
* 表示用名\r
*/\r
* 作成者\r
*/\r
private String author;\r
- \r
+\r
/**\r
* 説明\r
*/\r
* イメージサイズ\r
*/\r
private Dimension imageSize;\r
- \r
+\r
/**\r
* カテゴリ(定義順)\r
*/\r
* 雑多なプロパティ.<br>\r
*/\r
private Properties properties = new Properties();\r
- \r
- \r
+\r
+\r
/**\r
* プリセットのマップ.<br>\r
* キーはプリセット自身のID、値はプリセット自身.<br>\r
*/\r
private HashMap<String, PartsSet> presets = new HashMap<String, PartsSet>();\r
- \r
+\r
/**\r
* デフォルトのプリセットのID\r
*/\r
* カラーグループの定義.<br>\r
*/\r
private OrderedMap<String, ColorGroup> colorGroups = OrderedMap.emptyMap();\r
- \r
- \r
+\r
+\r
/**\r
* お勧めリンクリスト.<br>\r
* Ver0.96以前には存在しないのでnullになり得る.\r
*/\r
private List<RecommendationURL> recommendationURLList;\r
- \r
+\r
/**\r
* パーツカラーマネージャ.<br>\r
* (非シリアライズデータ、デシリアライズ時には新規インスタンスが作成される).<br>\r
*/\r
private transient PartsColorManager partsColorMrg = new PartsColorManager(this);\r
- \r
+\r
/**\r
* パーツデータローダー.<br>\r
* パーツをロードしたときに設定され、リロードするときに使用する.<br>\r
* (非シリアライズデータ、デシリアライズ時はnullのまま).<br>\r
*/\r
private transient PartsDataLoader partsDataLoader;\r
- \r
+\r
/**\r
* パーツイメージのセット.<br>\r
* (キャラクターセットはパーツイメージをもったままシリアライズされることは想定していないが、可能ではある。)\r
private Map<PartsCategory, Map<PartsIdentifier, PartsSpec>> images\r
= new HashMap<PartsCategory, Map<PartsIdentifier, PartsSpec>>();\r
\r
- \r
- \r
- /**\r
- * シリアライズする\r
- * @param stream 出力先\r
- * @throws IOException 失敗\r
- */\r
- private void writeObject(java.io.ObjectOutputStream stream) throws IOException {\r
- stream.defaultWriteObject();\r
- }\r
-\r
/**\r
* 基本情報のみをコピーして返します.<br>\r
* DocBase, ID, REV, Name, Author, Description, ImageSize、および, PartsCategory, ColorGroup, PartSetのコレクションがコピーされます.<br>\r
\r
cd.setAuthor(this.author);\r
cd.setDescription(this.description);\r
- \r
+\r
cd.setImageSize((Dimension)(this.imageSize == null ? null : this.imageSize.clone()));\r
- \r
+\r
cd.setWatchDirectory(this.isWatchDirectory());\r
- \r
+\r
ArrayList<RecommendationURL> recommendationURLList = null;\r
if (this.recommendationURLList != null) {\r
recommendationURLList = new ArrayList<RecommendationURL>();\r
}\r
}\r
cd.setRecommendationURLList(recommendationURLList);\r
- \r
+\r
ArrayList<PartsCategory> partsCategories = new ArrayList<PartsCategory>();\r
partsCategories.addAll(this.getPartsCategories());\r
cd.setPartsCategories(partsCategories.toArray(new PartsCategory[partsCategories.size()]));\r
}\r
cd.setDefaultPartsSetId(this.defaultPartsSetId);\r
}\r
- \r
+\r
return cd;\r
}\r
- \r
+\r
/**\r
* キャラクターデータが同じ構造であるか?<br>\r
* カラーグループ、カテゴリ、レイヤーの各情報が等しければtrue、それ以外はfalse.<br>\r
if (!colorGroup1.containsAll(colorGroup2)) {\r
return false;\r
}\r
- \r
+\r
// カテゴリが等しいか? (順序は問わない)\r
// IDによってのみ判定する.\r
ArrayList<PartsCategory> categories1 = new ArrayList<PartsCategory>(getPartsCategories());\r
- ArrayList<PartsCategory> categories2 = new ArrayList<PartsCategory>(other.getPartsCategories()); \r
+ ArrayList<PartsCategory> categories2 = new ArrayList<PartsCategory>(other.getPartsCategories());\r
Comparator<PartsCategory> sortCategoryId = new Comparator<PartsCategory>() {\r
public int compare(PartsCategory o1, PartsCategory o2) {\r
int ret = o1.getCategoryId().compareTo(o2.getCategoryId());\r
return false;\r
}\r
}\r
- \r
+\r
// レイヤーが等しいか?\r
// ID、重ね順序、dirによってのみ判定する.\r
int mx = categories1.size();\r
for (int idx = 0; idx < mx; idx++) {\r
PartsCategory category1 = categories1.get(idx);\r
PartsCategory category2 = categories2.get(idx);\r
- \r
+\r
ArrayList<Layer> layers1 = new ArrayList<Layer>(category1.getLayers());\r
ArrayList<Layer> layers2 = new ArrayList<Layer>(category2.getLayers());\r
- \r
+\r
Comparator<Layer> sortLayerId = new Comparator<Layer>() {\r
public int compare(Layer o1, Layer o2) {\r
int ret = o1.getId().compareTo(o2.getId());\r
return ret;\r
}\r
};\r
- \r
+\r
Collections.sort(layers1, sortLayerId);\r
Collections.sort(layers2, sortLayerId);\r
\r
return false;\r
}\r
}\r
- \r
+\r
return true;\r
}\r
- \r
+\r
/**\r
* 引数で指定したキャラクター定義とアッパーコンパチブルであるか?<br>\r
* 構造が同一であるか、サイズ違い、もしくはレイヤーの順序、カテゴリの順序、\r
// 自分が相手分のすべてのものを持っていなければ互換性なし.\r
return false;\r
}\r
- \r
+\r
// カテゴリをすべて含むか? (順序は問わない)\r
// IDによってのみ判定する.\r
Map<String, PartsCategory> categoriesNew = new HashMap<String, PartsCategory>();\r
// 自分が相手のすべてのカテゴリを持っていなければ互換性なし.\r
return false;\r
}\r
- \r
+\r
// レイヤーをすべて含むか?\r
// ID、Dirによってのみ判定する.\r
for (Map.Entry<String, PartsCategory> categoryOldEntry : categoriesOld.entrySet()) {\r
if (categoryNew == null) {\r
return false;\r
}\r
- \r
+\r
Map<String, Layer> layersNew = new HashMap<String, Layer>();\r
for (Layer layer : categoryNew.getLayers()) {\r
layersNew.put(layer.getId(), layer);\r
for (Layer layer : categoryOld.getLayers()) {\r
layersOld.put(layer.getId(), layer);\r
}\r
- \r
+\r
if ( !layersNew.keySet().containsAll(layersOld.keySet())) {\r
// 自分が相手のすべてのレイヤー(ID)を持っていなければ互換性なし.\r
return false;\r
}\r
}\r
}\r
- \r
+\r
return true;\r
}\r
- \r
+\r
/**\r
* キャラクターデータの構造を表す文字列を返す.<br>\r
* カテゴリ、レイヤー、色グループのみで構成される.<br>\r
buf.append(",");\r
}\r
buf.append("],");\r
- \r
+\r
// カテゴリ\r
buf.append("category:[");\r
for (PartsCategory category : getPartsCategories()) {\r
buf.append("]},");\r
}\r
buf.append("]}");\r
- \r
+\r
return buf.toString();\r
}\r
\r
buf.append("}");\r
return buf.toString();\r
}\r
- \r
- /**\r
- * デシリアライズする.\r
- * @param stream 入力もと\r
- * @throws IOException 失敗\r
- * @throws ClassNotFoundException 失敗\r
- */\r
- private void readObject(java.io.ObjectInputStream stream) throws IOException, ClassNotFoundException {\r
- stream.defaultReadObject();\r
- partsColorMrg = new PartsColorManager(this);\r
- }\r
- \r
+\r
/**\r
* お勧めリンクのリストを取得する.<br>\r
* 古いキャラクターデータで、お勧めリストノードが存在しない場合はnullとなる.<br>\r
public List<RecommendationURL> getRecommendationURLList() {\r
return recommendationURLList;\r
}\r
- \r
+\r
/**\r
* お勧めリンクリストを設定する.<br>\r
* @param recommendationURLList、null可\r
List<RecommendationURL> recommendationURLList) {\r
this.recommendationURLList = recommendationURLList;\r
}\r
- \r
+\r
\r
/**\r
* 作者を設定する.\r
public void setAuthor(String author) {\r
this.author = author;\r
}\r
- \r
+\r
/**\r
* 説明を設定する.<br>\r
* 説明の改行コードはプラットフォーム固有の改行コードに変換される.<br>\r
}\r
this.description = description;\r
}\r
- \r
+\r
public String getAuthor() {\r
return author;\r
}\r
- \r
+\r
/**\r
* 説明を取得する.<br>\r
* 説明の改行コードはプラットフォーム固有の改行コードとなる.<br>\r
public String getDescription() {\r
return description;\r
}\r
- \r
+\r
public String getId() {\r
return id;\r
}\r
- \r
+\r
public void setId(String id) {\r
this.id = id;\r
}\r
- \r
+\r
public String getRev() {\r
return rev;\r
}\r
- \r
+\r
public void setRev(String rev) {\r
this.rev = rev;\r
}\r
- \r
+\r
public void setDocBase(URI docBase) {\r
this.docBase = docBase;\r
}\r
- \r
+\r
public URI getDocBase() {\r
return docBase;\r
}\r
// デフォルトは監視する.\r
return true;\r
}\r
- \r
+\r
/**\r
* ディレクトリを監視するか指定する.\r
* @param watchDir 監視する場合はtrue、しない場合はfalse\r
public void setWatchDirectory(boolean watchDir) {\r
properties.setProperty("watch-dir", Boolean.toString(watchDir));\r
}\r
- \r
+\r
public String getProperty(String key) {\r
if (key == null || key.trim().length() == 0) {\r
throw new IllegalArgumentException();\r
}\r
return properties.getProperty(key.trim());\r
}\r
- \r
+\r
public void setProperty(String key, String value) {\r
if (key == null || key.trim().length() == 0) {\r
throw new IllegalArgumentException();\r
}\r
properties.setProperty(key.trim(), value);\r
}\r
- \r
+\r
public Collection<String> getPropertyNames() {\r
ArrayList<String> names = new ArrayList<String>();\r
for (Object key : properties.keySet()) {\r
}\r
return names;\r
}\r
- \r
+\r
/**\r
* 有効なキャラクターデータであるか?\r
* ID, Name, DocBaseが存在するものが有効なキャラクターデータである.<br>\r
return id != null && id.length() > 0 && localizedName != null\r
&& localizedName.length() > 0 && docBase != null;\r
}\r
- \r
+\r
/**\r
* 編集可能か?<br>\r
* まだdocbaseが指定されていない新しいインスタンスであるか、\r
if ( !xmlFile.canWrite() || !xmlFile.canRead()) {\r
throw new IOException("書き込み、もしくは読み込みが禁止されているプロファイルです。" + docBase);\r
}\r
- \r
+\r
} else {\r
// character.xmlファイルが、まだ存在していない場合\r
File parent = xmlFile.getParentFile();\r
public void setName(String name) {\r
this.localizedName = name;\r
}\r
- \r
+\r
/**\r
* キャラクター名を取得する.\r
* @return\r
public String getName() {\r
return localizedName;\r
}\r
- \r
+\r
public void setImageSize(Dimension imageSize) {\r
if (imageSize != null) {\r
imageSize = (Dimension) imageSize.clone();\r
}\r
this.imageSize = imageSize;\r
}\r
- \r
+\r
public Dimension getImageSize() {\r
return imageSize != null ? (Dimension) imageSize.clone() : null;\r
}\r
- \r
+\r
public void setColorGroups(Collection<ColorGroup> colorGroups) {\r
if (colorGroups == null) {\r
throw new IllegalArgumentException();\r
}\r
- \r
+\r
ArrayList<ColorGroup> colorGroupWithNA = new ArrayList<ColorGroup>();\r
\r
colorGroupWithNA.add(ColorGroup.NA);\r
colorGroupWithNA.add(colorGroup);\r
}\r
}\r
- \r
+\r
OrderedMap<String, ColorGroup> ret = new OrderedMap<String, ColorGroup>(\r
colorGroupWithNA,\r
new OrderedMap.KeyDetector<String, ColorGroup>() {\r
});\r
this.colorGroups = ret;\r
}\r
- \r
+\r
/**\r
* カラーグループIDからカラーグループを取得する.<br>\r
* 存在しない場合はN/Aを返す.<br>\r
}\r
return ColorGroup.NA;\r
}\r
- \r
+\r
public Collection<ColorGroup> getColorGroups() {\r
return colorGroups.values();\r
}\r
- \r
+\r
public PartsCategory getPartsCategory(String categoryId) {\r
if (partsCategories == null) {\r
return null;\r
}\r
return partsCategories.get(categoryId);\r
}\r
- \r
+\r
public void setPartsCategories(PartsCategory[] partsCategories) {\r
if (partsCategories == null) {\r
partsCategories = new PartsCategory[0];\r
}\r
});\r
}\r
- \r
+\r
public List<PartsCategory> getPartsCategories() {\r
return partsCategories.asList();\r
}\r
- \r
+\r
/**\r
* パーツデータがロード済みであるか?<br>\r
* 少なくとも{@link #loadPartsData(PartsDataLoader)}が一度呼び出されていればtrueとなる.<br>\r
this.partsDataLoader = partsDataLoader;\r
reloadPartsData();\r
}\r
- \r
+\r
/**\r
* パーツデータをリロードする.<br>\r
* ロード時に使用したローダーを使ってパーツを再ロードします.<br>\r
// NOTE: とりあえずパーツの変更を検査せず、常に変更ありにしておく。とりあえず実害ない。\r
return true;\r
}\r
- \r
+\r
/**\r
* {@inheritDoc}\r
*/\r
}\r
return null;\r
}\r
- \r
+\r
/**\r
* {@inheritDoc}\r
*/\r
public PartsColorManager getPartsColorManager() {\r
return this.partsColorMrg;\r
}\r
- \r
+\r
/**\r
* パーツセットを登録します.<br>\r
* お気に入りとプリセットの両方の共用です.<br>\r
presets.put(compatiblePartsSet.getPartsSetId(), compatiblePartsSet);\r
return true;\r
}\r
- \r
+\r
/**\r
* プリセットパーツおよびパーツセット(Favorites)のコレクション.\r
* @return パーツセットのコレクション\r
}\r
}\r
}\r
- \r
+\r
/**\r
* デフォルトのパーツセットを取得する.<br>\r
* そのパーツセットIDが実在するか、あるいは、それがプリセットであるか、などは一切関知しない.<br>\r
public String getDefaultPartsSetId() {\r
return defaultPartsSetId;\r
}\r
- \r
+\r
/**\r
* デフォルトのパーツセットIDを指定する.<br>\r
* nullの場合はデフォルトのパーツセットがないことを示す.<br>\r
public void setDefaultPartsSetId(String defaultPartsSetId) {\r
this.defaultPartsSetId = defaultPartsSetId;\r
}\r
- \r
+\r
@Override\r
public String toString() {\r
StringBuilder buf = new StringBuilder();\r
buf.append("/docBase:" + docBase);\r
return buf.toString();\r
}\r
- \r
+\r
}\r
package charactermanaj.model;\r
\r
-import java.io.Serializable;\r
-\r
/**\r
* カラーグループ.<br>\r
* カラーグループはimmutableであり、構築された値は変更されることはない.<br>\r
* @author seraphy\r
*/\r
-public final class ColorGroup implements Serializable {\r
-\r
- private static final long serialVersionUID = -2127943872189828172L;\r
+public final class ColorGroup {\r
\r
private final String id;\r
- \r
+\r
private final boolean enabled;\r
- \r
+\r
private final String localizedName;\r
\r
public static final ColorGroup NA = new ColorGroup("n/a", "", false);\r
- \r
+\r
public ColorGroup(final String id, final String localizedName) {\r
this(id, localizedName, true);\r
}\r
- \r
+\r
private ColorGroup(final String id, final String localizedName, final boolean enabled) {\r
if (id == null || id.trim().length() == 0) {\r
throw new IllegalArgumentException();\r
this.localizedName = (localizedName == null || localizedName.trim().length() == 0) ? id : localizedName;\r
this.enabled = enabled;\r
}\r
- \r
+\r
public boolean isEnabled() {\r
return enabled;\r
}\r
- \r
+\r
public String getId() {\r
return id;\r
}\r
- \r
+\r
public String getLocalizedName() {\r
return localizedName;\r
}\r
- \r
+\r
@Override\r
public int hashCode() {\r
return id.hashCode();\r
}\r
- \r
+\r
@Override\r
public boolean equals(Object obj) {\r
if (obj == this) {\r
}\r
return false;\r
}\r
- \r
+\r
public static boolean equals(ColorGroup v1, ColorGroup v2) {\r
if (v1 == v2) {\r
return true;\r
}\r
return v1.equals(v2);\r
}\r
- \r
+\r
@Override\r
public String toString() {\r
return getLocalizedName();\r
package charactermanaj.model;\r
\r
-import java.io.Serializable;\r
-\r
import charactermanaj.graphics.filters.ColorConvertParameter;\r
\r
/**\r
- * カラーグループおよび連動フラグを含む色情報.<br> \r
+ * カラーグループおよび連動フラグを含む色情報.<br>\r
* @author seraphy\r
*/\r
-public class ColorInfo implements Serializable, Cloneable {\r
-\r
- private static final long serialVersionUID = 2448550538711608223L;\r
+public class ColorInfo implements Cloneable {\r
\r
private ColorConvertParameter colorParameter = new ColorConvertParameter();\r
- \r
+\r
private boolean syncColorGroup = false;\r
- \r
+\r
private ColorGroup colorGroup = ColorGroup.NA;\r
- \r
+\r
@Override\r
public ColorInfo clone() {\r
ColorInfo colorInfo;\r
colorInfo.colorParameter = (ColorConvertParameter) this.colorParameter.clone();\r
return colorInfo;\r
}\r
- \r
+\r
@Override\r
public int hashCode() {\r
return colorParameter.hashCode() ^ colorGroup.hashCode();\r
}\r
- \r
+\r
@Override\r
public boolean equals(Object obj) {\r
if (obj == this) {\r
this.colorGroup = colorGroup;\r
}\r
}\r
- \r
+\r
@Override\r
public String toString() {\r
StringBuilder buf = new StringBuilder();\r
\r
private Layer layer;\r
\r
- private int layerOrder;\r
+ private float layerOrder;\r
\r
- public static CustomLayerOrder valueOf(PartsCategory category, Layer layer, int layerOrder) {\r
+ public static CustomLayerOrder valueOf(PartsCategory category, Layer layer, float layerOrder) {\r
CustomLayerOrder inst = new CustomLayerOrder();\r
inst.setCategory(category);\r
inst.setLayer(layer);\r
}\r
}\r
\r
- public int getLayerOrder() {\r
+ public float getLayerOrder() {\r
return layerOrder;\r
}\r
\r
- public void setLayerOrder(int layerOrder) {\r
- int old = this.layerOrder;\r
+ public void setLayerOrder(float layerOrder) {\r
+ float old = this.layerOrder;\r
if (old != layerOrder) {\r
this.layerOrder = layerOrder;\r
propChangeSupport.firePropertyChange(LAYER_ORDER, old, layerOrder);\r
int result = 1;\r
result = prime * result + ((category == null) ? 0 : category.hashCode());\r
result = prime * result + ((layer == null) ? 0 : layer.hashCode());\r
- result = prime * result + layerOrder;\r
+ result = prime * result + Float.floatToIntBits(layerOrder);\r
return result;\r
}\r
\r
return false;\r
} else if (!layer.equals(other.layer))\r
return false;\r
- if (layerOrder != other.layerOrder)\r
+ if (Float.floatToIntBits(layerOrder) != Float.floatToIntBits(other.layerOrder))\r
return false;\r
return true;\r
}\r
--- /dev/null
+package charactermanaj.model;\r
+\r
+import java.util.Collections;\r
+import java.util.HashMap;\r
+import java.util.Map;\r
+\r
+public class CustomLayerOrderKey implements Comparable<CustomLayerOrderKey> {\r
+\r
+ private final String id;\r
+\r
+ private final String displayName;\r
+\r
+ private final Map<String, String> localizedNames;\r
+\r
+ public static final String DEFAULT_NAME_KEY = "";\r
+\r
+ public CustomLayerOrderKey(String id, String name, Map<String, String> localizedNames) {\r
+ if (id == null || name == null) {\r
+ throw new NullPointerException("id and name is required.");\r
+ }\r
+ this.id = id;\r
+ this.displayName = name;\r
+ if (localizedNames == null) {\r
+ localizedNames = Collections.emptyMap();\r
+ }\r
+ this.localizedNames = Collections.unmodifiableMap(new HashMap<String, String>(localizedNames));\r
+ }\r
+\r
+ public String getId() {\r
+ return id;\r
+ }\r
+\r
+ public String getDisplayName() {\r
+ return displayName;\r
+ }\r
+\r
+ public Map<String, String> getLocalizedNames() {\r
+ return localizedNames;\r
+ }\r
+\r
+ @Override\r
+ public int hashCode() {\r
+ final int prime = 31;\r
+ int result = 1;\r
+ result = prime * result + ((id == null) ? 0 : id.hashCode());\r
+ return result;\r
+ }\r
+\r
+ @Override\r
+ public boolean equals(Object obj) {\r
+ if (this == obj)\r
+ return true;\r
+ if (obj == null)\r
+ return false;\r
+ if (getClass() != obj.getClass())\r
+ return false;\r
+ CustomLayerOrderKey other = (CustomLayerOrderKey) obj;\r
+ if (id == null) {\r
+ if (other.id != null)\r
+ return false;\r
+ } else if (!id.equals(other.id))\r
+ return false;\r
+ return true;\r
+ }\r
+\r
+ @Override\r
+ public int compareTo(CustomLayerOrderKey o) {\r
+ int ret = displayName.compareTo(o.displayName);\r
+ if (ret == 0) {\r
+ ret = id.compareTo(o.id);\r
+ }\r
+ return ret;\r
+ }\r
+\r
+ @Override\r
+ public String toString() {\r
+ return displayName;\r
+ }\r
+}\r
package charactermanaj.model;\r
\r
-import java.io.Serializable;\r
import java.util.List;\r
import java.util.logging.Level;\r
import java.util.logging.Logger;\r
* レイヤーやカテゴリなどのリレーションシップがない、<br>\r
* 特定のキャラクターデータモデルのツリーの一部には組み込まれていない状態のもの.<br>\r
*/\r
-public class IndependentPartsColorInfo implements Serializable {\r
-\r
- /**\r
- * シリアライズバージョンID\r
- */\r
- private static final long serialVersionUID = -8114086036157411198L;\r
+public class IndependentPartsColorInfo {\r
\r
/**\r
* ロガー\r
* カラーの同期指定\r
*/\r
private boolean syncColorGroup;\r
- \r
+\r
/**\r
* カラー変換パラメータ.<br>\r
*/\r
\r
/**\r
* インスタンス独立の素のカラー情報から、カテゴリやレイヤー、カラーグループのインスタンスと関連づけられたカラー情報に変換してかえす.\r
- * \r
+ *\r
* @param characterData\r
* キャラクターデータ\r
* @param category\r
package charactermanaj.model;\r
\r
import java.awt.Color;\r
-import java.io.Serializable;\r
import java.util.HashMap;\r
import java.util.List;\r
import java.util.Map;\r
+import java.util.Set;\r
import java.util.logging.Level;\r
import java.util.logging.Logger;\r
\r
* レイヤーやカテゴリなどのリレーションシップがない、<br>\r
* 特定のキャラクターデータモデルのツリーの一部には組み込まれていない状態のもの.<br>\r
*/\r
-public class IndependentPartsSetInfo implements Serializable {\r
-\r
- /**\r
- * シリアライズバージョンID\r
- */\r
- private static final long serialVersionUID = 7280485045920860407L;\r
+public class IndependentPartsSetInfo {\r
\r
/**\r
* ロガー\r
private double[] affineTransformParameter;\r
\r
/**\r
+ * アクティブなカスタムレイヤーパターンIDのセット\r
+ */\r
+ private Set<String> activeCustomLayerPatternIds;\r
+\r
+ /**\r
* カテゴリIDをキーとし、パーツ名をキーとしカラー情報のリストを値とするマップを値とする.\r
*/\r
private Map<String, Map<String, List<IndependentPartsColorInfo>>> partsMap = new HashMap<String, Map<String, List<IndependentPartsColorInfo>>>();\r
this.affineTransformParameter = affineTransformParameter;\r
}\r
\r
+ public Set<String> getActiveCustomLayerPatternIds() {\r
+ return activeCustomLayerPatternIds;\r
+ }\r
+\r
+ public void setActiveCustomLayerPatternIds(Set<String> activeCustomLayerPatternIds) {\r
+ this.activeCustomLayerPatternIds = activeCustomLayerPatternIds;\r
+ }\r
+\r
/**\r
* カテゴリIDをキーとし、パーツ名をキーとしカラー情報のリストを値とするマップを値とする.\r
- * \r
+ *\r
* @return カテゴリIDをキーとし、パーツ名をキーとしカラー情報のリストを値とするマップを値とする.\r
*/\r
public Map<String, Map<String, List<IndependentPartsColorInfo>>> getPartsMap() {\r
\r
/**\r
* インスタンス独立のパーツセット情報から、指定されたキャラクターデータに関連づけられた パーツ情報に変換して返す.<br>\r
- * \r
+ *\r
* @param partsSetInfo\r
* インスタンス独立のパーツセット情報\r
* @param characterData\r
partsColorInfo);\r
}\r
}\r
+\r
+ // 適用しているカスタムレイヤー名\r
+ partsSet.setActiveCustomLayerPatternIds(partsSetInfo.getActiveCustomLayerPatternIds());\r
+\r
return partsSet;\r
}\r
}\r
--- /dev/null
+package charactermanaj.model;\r
+\r
+import java.awt.Point;\r
+import java.awt.Rectangle;\r
+import java.io.File;\r
+import java.net.URI;\r
+import java.util.Collections;\r
+import java.util.List;\r
+import java.util.Map;\r
+\r
+import charactermanaj.model.io.WorkingSetXMLReader;\r
+import charactermanaj.ui.model.WallpaperInfo;\r
+\r
+/**\r
+ * WorkingSetのXMLの読み込み時に使用する.<br>\r
+ * 特定のキャラクターデータのインスタンスとの関連を持たない状態の設定値を保持している.<br>\r
+ *\r
+ * @see WorkingSetXMLReader\r
+ * @author seraphy\r
+ */\r
+public class IndependentWorkingSet {\r
+\r
+ /**\r
+ * ドキュメントベース\r
+ */\r
+ private URI characterDocBase;\r
+\r
+ /**\r
+ * キャラクターデータのID, Revと基本構造のシグネチャ\r
+ */\r
+ private String characterDataSig;\r
+\r
+ /**\r
+ * キーはカテゴリid, 値は、パーツ名をキーとしレイヤーごとのカラー情報のリストを値とするマップ\r
+ */\r
+ private Map<String, Map<String, List<IndependentPartsColorInfo>>> partsColorMap = Collections\r
+ .emptyMap();\r
+\r
+ /**\r
+ * 現在の選択中のパーツと色設定からのパーツセット\r
+ */\r
+ private IndependentPartsSetInfo currentPartsSet;\r
+\r
+ /**\r
+ * 最後に使用したディレクトリ(保存用)\r
+ */\r
+ private File lastUsedSaveDir;\r
+\r
+ /**\r
+ * 最後に使用したディレクトリ(Export用)\r
+ */\r
+ private File lastUsedExportDir;\r
+\r
+ /**\r
+ * 最後に使用したお気に入り情報.<br>\r
+ * (最後に使用したお気に入り情報は、ver0.92からサポート)<br>\r
+ */\r
+ private IndependentPartsSetInfo lastUsePresetParts;\r
+\r
+ /**\r
+ * 壁紙情報.<br>\r
+ * (壁紙はver0.97からサポート)<br>\r
+ */\r
+ private WallpaperInfo wallpaperInfo;\r
+\r
+ /**\r
+ * ズーム倍率\r
+ * (ズーム倍率の保存はv0.999から、未指定の場合はnull)\r
+ */\r
+ private Double zoomFactor;\r
+\r
+ /**\r
+ * ビューの中央位置\r
+ * (ズーム倍率の保存はv0.999から、未指定の場合はnull)\r
+ */\r
+ private Point viewPosition;\r
+\r
+ /**\r
+ * ウィンドウの位置と大きさ\r
+ */\r
+ private Rectangle windowRect;\r
+\r
+\r
+ public void setCharacterDocBase(URI characterDocBase) {\r
+ this.characterDocBase = characterDocBase;\r
+ }\r
+\r
+ public URI getCharacterDocBase() {\r
+ return characterDocBase;\r
+ }\r
+\r
+ public String getCharacterDataSig() {\r
+ return characterDataSig;\r
+ }\r
+\r
+ public void setCharacterDataSig(String characterDataSig) {\r
+ this.characterDataSig = characterDataSig;\r
+ }\r
+\r
+ /**\r
+ * パーツカラーマップ\r
+ *\r
+ * @return キーはカテゴリid, 値は、パーツ名をキーとしレイヤーごとのカラー情報のリストを値とするマップ\r
+ */\r
+ public Map<String, Map<String, List<IndependentPartsColorInfo>>> getPartsColorMap() {\r
+ return partsColorMap;\r
+ }\r
+\r
+ public void setPartsColorMap(\r
+ Map<String, Map<String, List<IndependentPartsColorInfo>>> partsColorMap) {\r
+ if (partsColorMap == null) {\r
+ this.partsColorMap = Collections.emptyMap();\r
+ }\r
+ this.partsColorMap = partsColorMap;\r
+ }\r
+\r
+ public void setLastUsedExportDir(File lastUsedExportDir) {\r
+ this.lastUsedExportDir = lastUsedExportDir;\r
+ }\r
+\r
+ public File getLastUsedExportDir() {\r
+ return lastUsedExportDir;\r
+ }\r
+\r
+ public void setLastUsedSaveDir(File lastUsedSaveDir) {\r
+ this.lastUsedSaveDir = lastUsedSaveDir;\r
+ }\r
+\r
+ public File getLastUsedSaveDir() {\r
+ return lastUsedSaveDir;\r
+ }\r
+\r
+ public void setWallpaperInfo(WallpaperInfo wallpaperInfo) {\r
+ this.wallpaperInfo = wallpaperInfo;\r
+ }\r
+\r
+ public WallpaperInfo getWallpaperInfo() {\r
+ return wallpaperInfo;\r
+ }\r
+\r
+ public Double getZoomFactor() {\r
+ return zoomFactor;\r
+ }\r
+\r
+ public void setZoomFactor(Double zoomFactor) {\r
+ this.zoomFactor = zoomFactor;\r
+ }\r
+\r
+ public Point getViewPosition() {\r
+ return viewPosition;\r
+ }\r
+\r
+ public void setViewPosition(Point viewPosition) {\r
+ this.viewPosition = viewPosition;\r
+ }\r
+\r
+ public Rectangle getWindowRect() {\r
+ return windowRect;\r
+ }\r
+\r
+ public void setWindowRect(Rectangle windowRect) {\r
+ this.windowRect = windowRect;\r
+ }\r
+\r
+ public IndependentPartsSetInfo getCurrentPartsSet() {\r
+ return currentPartsSet;\r
+ }\r
+\r
+ public void setCurrentPartsSet(IndependentPartsSetInfo currentPartsSet) {\r
+ this.currentPartsSet = currentPartsSet;\r
+ }\r
+\r
+ public IndependentPartsSetInfo getLastUsePresetParts() {\r
+ return lastUsePresetParts;\r
+ }\r
+\r
+ public void setLastUsePresetParts(IndependentPartsSetInfo lastUsePresetParts) {\r
+ this.lastUsePresetParts = lastUsePresetParts;\r
+ }\r
+\r
+ /**\r
+ * キャラクターデータを指定して、指定されたキャラクターデータ上のインスタンスと関連づけられた\r
+ * カテゴリおよびパーツ名などのインスタンスで構成されるパーツ識別名とカラー情報を、 引数で指定したマップに出力する.\r
+ *\r
+ * @param characterData\r
+ * キャラクターデータ\r
+ * @param partsColorInfoMap\r
+ * パーツ識別名とカラー情報を出力するマップ\r
+ */\r
+ public void createCompatible(CharacterData characterData,\r
+ Map<PartsIdentifier, PartsColorInfo> partsColorInfoMap) {\r
+ if (characterData == null || partsColorInfoMap == null) {\r
+ throw new IllegalArgumentException();\r
+ }\r
+\r
+ for (Map.Entry<String, Map<String, List<IndependentPartsColorInfo>>> catEntry : partsColorMap\r
+ .entrySet()) {\r
+ String categoryId = catEntry.getKey();\r
+ for (Map.Entry<String, List<IndependentPartsColorInfo>> layerEntry : catEntry\r
+ .getValue().entrySet()) {\r
+ String partsName = layerEntry.getKey();\r
+ List<IndependentPartsColorInfo> partsColorInfos = layerEntry\r
+ .getValue();\r
+\r
+ PartsCategory partsCategory = characterData\r
+ .getPartsCategory(categoryId);\r
+ if (partsCategory != null) {\r
+ String localizedName = partsName;\r
+ PartsIdentifier partsIdentifier = new PartsIdentifier(\r
+ partsCategory, partsName, localizedName);\r
+\r
+ PartsColorInfo partsColorInfo = IndependentPartsColorInfo\r
+ .buildPartsColorInfo(characterData, partsCategory,\r
+ partsColorInfos);\r
+ if (partsColorInfo != null) {\r
+ partsColorInfoMap.put(partsIdentifier, partsColorInfo);\r
+ }\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ @Override\r
+ public String toString() {\r
+ StringBuilder buf = new StringBuilder();\r
+ buf.append("(characterDocBase=").append(characterDocBase);\r
+ buf.append(", characterDataSig=").append(characterDataSig);\r
+ buf.append(", partsColorMap=").append(partsColorMap);\r
+ buf.append(", currentPartsSet=").append(currentPartsSet);\r
+ buf.append(", lastUsedSaveDir=").append(lastUsedSaveDir);\r
+ buf.append(", lastUsedExportDir=").append(lastUsedExportDir);\r
+ buf.append(")");\r
+ return buf.toString();\r
+ }\r
+}\r
package charactermanaj.model;\r
\r
import java.io.File;\r
-import java.io.Serializable;\r
\r
/**\r
* レイヤー情報.<br>\r
- * 重ね合わせ順による比較が可能.<br> \r
+ * 重ね合わせ順による比較が可能.<br>\r
* immutableなクラスであり、構築された後に変更されることはない.<br>\r
* 同値であるかは、ID、順序、Dirのみで判断され、それ以外の情報は無視される.<br>\r
* @author seraphy\r
*/\r
-public final class Layer implements Comparable<Layer>, Serializable {\r
-\r
- private static final long serialVersionUID = -6437516046486547811L;\r
+public final class Layer implements Comparable<Layer> {\r
\r
/**\r
* 重ね合わせ順\r
*/\r
private final int order;\r
- \r
+\r
/**\r
* レイヤー識別名\r
*/\r
private final String id;\r
- \r
+\r
/**\r
* レイヤー表示名\r
*/\r
private final String localizedName;\r
- \r
+\r
/**\r
* カラーグループ\r
*/\r
private final ColorGroup colorGroup;\r
- \r
+\r
/**\r
* カラーグループ同期(初期)\r
*/\r
private final boolean initSync;\r
- \r
+\r
/**\r
* 対象ディレクトリ\r
*/\r
private final String dir;\r
- \r
+\r
/**\r
* カラーモデル名\r
*/\r
\r
/**\r
* レイヤー情報を構築する\r
- * \r
+ *\r
* @param id\r
* @param localizedName\r
* @param order\r
this.dir = dir;\r
this.colorModelName = colorModelName;\r
}\r
- \r
+\r
/**\r
* 重ね合わせ順に比較する.\r
* 同順位の場合は名前・ディレクトリから順序を決める.\r
public String getId() {\r
return id;\r
}\r
- \r
+\r
/**\r
* レイヤー表示名を取得する\r
* @return レイヤー表示名\r
public String getLocalizedName() {\r
return localizedName;\r
}\r
- \r
+\r
/**\r
* 重ね合わせ順を取得する.\r
* @return 重ね合わせ順\r
public boolean isInitSync() {\r
return initSync;\r
}\r
- \r
+\r
/**\r
* 対象ディレクトリを取得する.\r
* @return 対象ディレクトリ\r
public String getDir() {\r
return dir;\r
}\r
- \r
+\r
/**\r
* カラーモデル名を取得する.\r
- * \r
+ *\r
* @return カラーモデル名\r
*/\r
public String getColorModelName() {\r
}\r
return false;\r
}\r
- \r
+\r
/**\r
* 同一レイヤーであるか判断する.<br>\r
* IDのみで判断する.<br>\r
\r
import java.io.IOException;\r
import java.io.ObjectInputStream;\r
-import java.io.ObjectOutputStream;\r
-import java.io.Serializable;\r
import java.util.AbstractList;\r
import java.util.AbstractMap;\r
import java.util.AbstractSet;\r
* マップへのvalues()等のコレクションアクセスでは元のコレクションと同じ定義順で返される.<br>\r
* より明確には{{@link #asList()}を使うとリストとしてアクセスすることができる.<br>\r
* 読み込み専用で、書き込みはできない.<br>\r
- * \r
+ *\r
* @author seraphy\r
*\r
* @param <K> データに含まれるキーの型\r
* @param <V> データの型\r
*/\r
-public class OrderedMap<K, V> extends AbstractMap<K, V> implements Serializable {\r
-\r
- /**\r
- * シリアライズバージョンID. \r
- */\r
- private static final long serialVersionUID = 5049488493598426918L;\r
+public class OrderedMap<K, V> extends AbstractMap<K, V> {\r
\r
/**\r
* 空を示す定数インスタンス\r
*/\r
public static final OrderedMap<?, ?> EMPTY_MAP = new OrderedMap<Object, Object>();\r
- \r
+\r
@SuppressWarnings("unchecked")\r
public static final <K, V> OrderedMap<K, V> emptyMap() {\r
return (OrderedMap<K, V>) EMPTY_MAP;\r
}\r
- \r
+\r
public interface KeyDetector<K, V> {\r
- \r
+\r
K getKey(V data);\r
- \r
+\r
}\r
- \r
- protected static class OrderedMapEntry<K, V> implements Map.Entry<K, V>, Serializable {\r
- \r
- private static final long serialVersionUID = 5111249402034089224L;\r
+\r
+ protected static class OrderedMapEntry<K, V> implements Map.Entry<K, V> {\r
\r
private final K key;\r
- \r
+\r
private final V data;\r
- \r
+\r
protected OrderedMapEntry(K key, V data) {\r
this.key = key;\r
this.data = data;\r
}\r
- \r
+\r
public K getKey() {\r
return key;\r
}\r
public V getValue() {\r
return data;\r
}\r
- \r
+\r
public V setValue(V arg0) {\r
throw new UnsupportedOperationException();\r
}\r
* リストとしてのエントリ\r
*/\r
private ArrayList<Map.Entry<K, V>> entries = new ArrayList<Map.Entry<K, V>>();\r
- \r
+\r
/**\r
* マップアクセス用.<br>\r
* シリアライズ時はスキップされ、デシリアライズ時にリストから復元される.<br>\r
}\r
}\r
\r
- /**\r
- * シリアライズ\r
- * @param stream\r
- * @throws IOException\r
- */\r
- private void writeObject(ObjectOutputStream stream) throws IOException {\r
- stream.defaultWriteObject();\r
- }\r
-\r
/**\r
* 空のコレクションを作成する.\r
*/\r
protected OrderedMap() {\r
super();\r
}\r
- \r
+\r
/**\r
* 元となるコレクションをコピーし、そのコレクションの各データのキーを分離しマップアクセス可能にする.<br>\r
* @param datas 元となるコレクション\r
entries.add(new OrderedMapEntry<K, V>(key, data));\r
entryMap.put(key, data);\r
}\r
- \r
+\r
if (entries.size() != entryMap.size()) {\r
throw new IllegalArgumentException("duplicate-key");\r
}\r
}\r
- \r
+\r
@Override\r
public Set<java.util.Map.Entry<K, V>> entrySet() {\r
return new AbstractSet<java.util.Map.Entry<K, V>>() {\r
}\r
};\r
}\r
- \r
+\r
/**\r
* マップの値を定義順のリストとして扱えるようにリストインターフェイスで返す.<br>\r
* 読み込み専用です.<br>\r
}\r
};\r
}\r
- \r
+\r
@Override\r
public V get(Object key) {\r
return entryMap.get(key);\r
}\r
- \r
+\r
@Override\r
public int size() {\r
return entries.size();\r
package charactermanaj.model;\r
\r
-import java.io.Serializable;\r
-\r
/**\r
* パーツの作者情報\r
* @author seraphy\r
*/\r
-public class PartsAuthorInfo implements Serializable {\r
+public class PartsAuthorInfo {\r
\r
- private static final long serialVersionUID = -5308326806956816225L;\r
\r
private String author;\r
- \r
+\r
private String homePage;\r
\r
public String getAuthor() {\r
return author;\r
}\r
- \r
+\r
public String getHomePage() {\r
return homePage;\r
}\r
- \r
+\r
public void setAuthor(String author) {\r
this.author = author;\r
}\r
- \r
+\r
public void setHomePage(String homePage) {\r
this.homePage = homePage;\r
}\r
- \r
}\r
package charactermanaj.model;\r
\r
-import java.io.Serializable;\r
import java.util.Arrays;\r
import java.util.Collections;\r
import java.util.List;\r
\r
/**\r
- * パーツカテゴリ.<br> \r
+ * パーツカテゴリ.<br>\r
* 同値であるかはカテゴリIDが一致するかによってのみ判定します.<br>\r
* それ以外の情報は無視されます.<br>\r
* @author seraphy\r
*/\r
-public final class PartsCategory implements Comparable<PartsCategory>, Serializable {\r
-\r
- /**\r
- * シリアライズバージョンID.\r
- */\r
- private static final long serialVersionUID = -8652242530280056201L;\r
+public final class PartsCategory implements Comparable<PartsCategory> {\r
\r
/**\r
* 順序\r
*/\r
private final int order;\r
- \r
+\r
/**\r
* カテゴリ識別名\r
*/\r
private final String categoryId;\r
- \r
+\r
/**\r
* カテゴリ表示名\r
*/\r
* 複数選択可能?\r
*/\r
private final boolean multipleSelectable;\r
- \r
+\r
/**\r
* 表示行数\r
*/\r
private final int visibleRows;\r
- \r
+\r
/**\r
* レイヤー情報\r
*/\r
private final List<Layer> layers;\r
- \r
+\r
/**\r
* カテゴリを構築する.<br>\r
* @param order 順序\r
this.layers = Collections.unmodifiableList(Arrays.asList(layers.clone()));\r
this.visibleRows = visibleRows;\r
}\r
- \r
+\r
/**\r
* カテゴリの順序を比較して返す.<br>\r
* 順序で比較し、同一順序であれば表示名で比較し、それでも同一であれば識別子で比較します.<br>\r
}\r
return ret;\r
}\r
- \r
+\r
@Override\r
public int hashCode() {\r
return this.categoryId.hashCode();\r
}\r
- \r
+\r
@Override\r
public boolean equals(Object obj) {\r
if (obj == this) {\r
}\r
return false;\r
}\r
- \r
+\r
/**\r
* 同一カテゴリであるか判定します.<br>\r
* nullの場合は常にfalseを返します.<br>\r
}\r
return false;\r
}\r
- \r
+\r
public static boolean equals(PartsCategory o1, PartsCategory o2) {\r
if (o1 == o2) {\r
return true;\r
}\r
return o1.equals(o2);\r
}\r
- \r
+\r
/**\r
* 定義順を取得する\r
* @return 定義順\r
}\r
return false;\r
}\r
- \r
+\r
/**\r
* レイヤー情報\r
* @return レイヤー情報\r
public List<Layer> getLayers() {\r
return layers;\r
}\r
- \r
+\r
/**\r
* レイヤーを取得する.<br>\r
* 該当するレイヤーがなければnull\r
}\r
return null;\r
}\r
- \r
+\r
/**\r
* カテゴリ識別名を取得する.\r
* @return カテゴリ識別名\r
public String getCategoryId() {\r
return categoryId;\r
}\r
- \r
+\r
/**\r
* カテゴリ表示名を取得する.\r
* @return カテゴリ表示名\r
package charactermanaj.model;\r
\r
-import java.io.Serializable;\r
import java.util.AbstractMap;\r
import java.util.Collections;\r
import java.util.HashMap;\r
import charactermanaj.graphics.filters.ColorConvertParameter;\r
\r
/**\r
- * パーツ単位のカラーグループを含む色情報のコレクション.<br> \r
+ * パーツ単位のカラーグループを含む色情報のコレクション.<br>\r
* パーツは複数のレイヤーから構成されるため、レイヤーごとのカラーグループを含む色情報の集合を意味する.<br>\r
* キーのセットはカテゴリに属するレイヤーに固定されており、追加・削除することはできない.<br>\r
* @author seraphy\r
*/\r
-public final class PartsColorInfo extends AbstractMap<Layer, ColorInfo> implements Serializable, Cloneable {\r
+public final class PartsColorInfo extends AbstractMap<Layer, ColorInfo> implements Cloneable {\r
\r
/**\r
* ロガー\r
*/\r
private static final Logger logger = Logger.getLogger(PartsColorInfo.class.getName());\r
- \r
- private static final long serialVersionUID = -8639109147043912257L;\r
\r
/**\r
* パーツが属するカテゴリのレイヤー構成に対する色情報のマップ.<br>\r
* カテゴリ\r
*/\r
private final PartsCategory partsCategory;\r
- \r
+\r
/**\r
* カテゴリを指定して色情報が未設定のインスタンスを構築する.<br>\r
* カテゴリに属するレイヤーが初期化されている.<br>\r
this.partsCategory = partsCategory;\r
init();\r
}\r
- \r
+\r
@Override\r
public PartsColorInfo clone() {\r
try {\r
throw new RuntimeException(ex);\r
}\r
}\r
- \r
+\r
/**\r
* パーツカラー情報を指定したパーツカテゴリに存在するレイヤーに正規化して返す.<br>\r
* カテゴリに存在しないレイヤーの情報は破棄され、結果は有効なレイヤーのみの色情報となる.<br>\r
}\r
return a.equals(b);\r
}\r
- \r
+\r
private void init() {\r
for (Layer layer : partsCategory.getLayers()) {\r
colorInfoMap.put(layer, createColorInfo(layer));\r
}\r
}\r
- \r
+\r
protected ColorInfo createColorInfo(Layer layer) {\r
ColorInfo colorInfo = new ColorInfo();\r
colorInfo.setColorGroup(layer.getColorGroup());\r
colorInfo.setColorParameter(new ColorConvertParameter());\r
return colorInfo;\r
}\r
- \r
+\r
public PartsCategory getPartsCategory() {\r
return partsCategory;\r
}\r
- \r
+\r
@Override\r
public Set<java.util.Map.Entry<Layer, ColorInfo>> entrySet() {\r
return Collections.unmodifiableSet(colorInfoMap.entrySet());\r
}\r
- \r
+\r
/**\r
* カテゴリに属するレイヤーの色情報を設定する.<br>\r
* カテゴリに該当しないレイヤーを指定した場合はIllegalArgumentException例外となる.<br>\r
}\r
return colorInfoMap.put(key, value);\r
}\r
- \r
+\r
@Override\r
public String toString() {\r
StringBuilder buf = new StringBuilder();\r
buf.append(")");\r
return buf.toString();\r
}\r
- \r
+\r
}\r
package charactermanaj.model;\r
\r
-import java.io.Serializable;\r
import java.util.AbstractMap;\r
import java.util.Collections;\r
import java.util.HashMap;\r
\r
import charactermanaj.graphics.io.ImageResource;\r
\r
-public class PartsFiles extends AbstractMap<Layer, ImageResource> implements Serializable {\r
+public class PartsFiles extends AbstractMap<Layer, ImageResource> {\r
\r
- private static final long serialVersionUID = 5799830380308843243L;\r
+ private HashMap<Layer, ImageResource> partsMap = new HashMap<Layer, ImageResource>();\r
\r
- private HashMap<Layer, ImageResource> partsMap = new HashMap<Layer, ImageResource>(); \r
- \r
private final PartsIdentifier partsIdentifier;\r
\r
public PartsFiles(PartsIdentifier partsName) {\r
}\r
this.partsIdentifier = partsName;\r
}\r
- \r
+\r
public PartsIdentifier getPartsIdentifier() {\r
return partsIdentifier;\r
}\r
- \r
+\r
@Override\r
public Set<Map.Entry<Layer, ImageResource>> entrySet() {\r
return Collections.unmodifiableSet(partsMap.entrySet());\r
}\r
- \r
+\r
@Override\r
public ImageResource put(final Layer key, final ImageResource value) {\r
if (key == null || value == null) {\r
}\r
return partsMap.put(key, value);\r
}\r
- \r
+\r
@Override\r
public ImageResource get(Object key) {\r
return partsMap.get(key);\r
}\r
- \r
+\r
@Override\r
public boolean containsKey(Object key) {\r
return partsMap.containsKey(key);\r
}\r
- \r
+\r
public long lastModified() {\r
long maxLastModified = 0;\r
for (ImageResource imageResource : values()) {\r
package charactermanaj.model;\r
\r
-import java.io.Serializable;\r
-\r
/**\r
* パーツ識別子.<br>\r
* パーツ識別子の同値性は同一カテゴリID、且つ、同一のパーツ名(ID)であることによってのみ判定される.<br>\r
* @author seraphy\r
*\r
*/\r
-public final class PartsIdentifier implements Serializable, Comparable<PartsIdentifier> {\r
-\r
- private static final long serialVersionUID = 8943101890389091718L;\r
+public final class PartsIdentifier implements Comparable<PartsIdentifier> {\r
\r
private final PartsCategory partsCategory;\r
- \r
+\r
private final String partsName;\r
- \r
+\r
private final String localizedName;\r
- \r
+\r
public PartsIdentifier(final PartsCategory partsCategory, final String partsName, final String localizedName) {\r
if (partsName == null || partsCategory == null) {\r
throw new IllegalArgumentException();\r
this.partsName = partsName;\r
this.localizedName = (localizedName == null || localizedName.trim().length() == 0) ? partsName : localizedName;\r
}\r
- \r
+\r
public PartsCategory getPartsCategory() {\r
return partsCategory;\r
}\r
- \r
+\r
public boolean hasLayer(Layer layer) {\r
return partsCategory.hasLayer(layer);\r
}\r
- \r
+\r
@Override\r
public int hashCode() {\r
return partsName.hashCode();\r
}\r
- \r
+\r
@Override\r
public boolean equals(Object obj) {\r
if (obj == this) {\r
}\r
return false;\r
}\r
- \r
+\r
public static boolean equals(PartsIdentifier a, PartsIdentifier b) {\r
if (a == b) {\r
return true;\r
}\r
return a.equals(b);\r
}\r
- \r
+\r
public int compareTo(PartsIdentifier o) {\r
if (o == this) {\r
return 0;\r
}\r
return ret;\r
}\r
- \r
+\r
public String getPartsName() {\r
return partsName;\r
}\r
- \r
+\r
public String getLocalizedPartsName() {\r
return localizedName;\r
}\r
public String toString() {\r
return getLocalizedPartsName();\r
}\r
- \r
+\r
}\r
package charactermanaj.model;\r
\r
import java.awt.Color;\r
-import java.io.Serializable;\r
import java.util.AbstractMap;\r
import java.util.ArrayList;\r
import java.util.Arrays;\r
import java.util.List;\r
import java.util.Map;\r
import java.util.Set;\r
+import java.util.TreeSet;\r
\r
/**\r
* パーツセット.<br>\r
* 各カテゴリの選択パーツと、そのパーツの色情報、および背景色をセットにしたもの.<br>\r
* 保存する必要がなければIDおよび表示名は使用されないため、nullとなりえる.<br>\r
- * \r
+ *\r
* @author seraphy\r
- * \r
+ *\r
*/\r
-public final class PartsSet extends AbstractMap<PartsCategory, List<PartsIdentifier>> implements Serializable, Cloneable {\r
-\r
- /**\r
- * シリアライズバージョンID.\r
- */\r
- private static final long serialVersionUID = 5972528889825451761L;\r
+public final class PartsSet extends AbstractMap<PartsCategory, List<PartsIdentifier>> implements Cloneable {\r
\r
/**\r
* PartsSet用のデフォルトのコンパレータ.<br>\r
* 一時的な名前なしのパーツセットとして使われる場合はnull\r
*/\r
private String partsSetId;\r
- \r
+\r
/**\r
* パーツセットの表示名.<br>\r
* 一時的な名前なしのパーツセットとして使われる場合はnull\r
*/\r
private String localizedName;\r
- \r
+\r
/**\r
* プリセットパーツフラグ\r
*/\r
private boolean presetParts;\r
- \r
+\r
/**\r
* パーツセットとともに使われる背景色.<br>\r
*/\r
private Color bgColor;\r
- \r
+\r
/**\r
* アフィン変換用パラメータ.<br>\r
* 変換しない場合はnull.<br>\r
*/\r
private double[] affineTransformParameter;\r
- \r
+\r
+ /**\r
+ * アクティブなカスタムレイヤーパターンIDのセット\r
+ */\r
+ private Set<String> activeCustomLayerPatternIds;\r
+\r
/**\r
* パーツリスト\r
*/\r
private HashMap<PartsCategory, List<PartsIdentifier>> parts = new HashMap<PartsCategory, List<PartsIdentifier>>();\r
- \r
+\r
/**\r
* パーツに対するカラー情報.<br>\r
* かならずしも、パーツに対してカラー情報を設定する必要はない.<br>\r
\r
/**\r
* 名前つきパーツセットを作成する.<br>\r
- * \r
+ *\r
* @param partsSetId\r
* パーツセットID\r
* @param localizedName\r
this.localizedName = localizedName;\r
this.presetParts = presetParts;\r
}\r
- \r
+\r
/**\r
* パーツセットをディープコピーする.<br>\r
* 現在のキャラクターデータのカテゴリインスタンスに関連づけて再生させる場合は、\r
* resolverに現在のキャラクターデータのカテゴリリゾルバを指定します.<br>\r
- * \r
+ *\r
* @param org\r
* 元オブジェクト\r
* @param resolver\r
this.presetParts = org.presetParts;\r
this.bgColor = org.bgColor;\r
this.affineTransformParameter = org.affineTransformParameter == null ? null : org.affineTransformParameter.clone();\r
- \r
+ this.activeCustomLayerPatternIds = org.activeCustomLayerPatternIds == null ? null\r
+ : new TreeSet<String>(org.activeCustomLayerPatternIds);\r
+\r
// ColorInfoMapの正規化\r
for (Map.Entry<PartsIdentifier, PartsColorInfo> partsColorInfoEntry : org.partsColorInfoMap.entrySet()) {\r
PartsIdentifier partsIdentifier = partsColorInfoEntry.getKey();\r
if (resolver != null) {\r
- PartsCategory orgPartsCategory = partsIdentifier.getPartsCategory(); \r
+ PartsCategory orgPartsCategory = partsIdentifier.getPartsCategory();\r
PartsCategory repPartsCategory = resolver.getPartsCategory(orgPartsCategory.getCategoryId());\r
if (repPartsCategory == null) {\r
// 同一IDのカテゴリがリゾルバになければ、このパーツは無かったことにする.\r
.getValue().createCompatible(repPartsCategory);\r
partsColorInfoMap.put(partsIdentifier, copiedPartsColorInfo);\r
}\r
- \r
+\r
// PartsIdentifierの正規化\r
for (Map.Entry<PartsCategory, List<PartsIdentifier>> partsEntry : org.parts.entrySet()) {\r
PartsCategory orgPartsCategory = partsEntry.getKey();\r
parts.put(partsCategory, partsIdentifiers);\r
}\r
}\r
- \r
+\r
/**\r
* リゾルバを使用してパーツカテゴリ(パーツ識別子のカテゴリも含む)のインスタンスを入れ替えます.<br>\r
* パーツセットはキャラクターデータとは独立してロード・セーブされることがあるため、同じ情報でも異なるインスタンスとなる場合があり、\r
* これを是正するために、このメソッドを使用します.<br>\r
* リゾルバから取得できないパーツカテゴリは除去されます.<br>\r
- * \r
+ *\r
* @param resolver\r
* リゾルバ\r
* @return 互換性のあるパーツセット\r
\r
/**\r
* パーツセットをディープコピーする.<br>\r
- * \r
+ *\r
* @return コピーされたパーツセット\r
*/\r
@Override\r
public PartsSet clone() {\r
return new PartsSet(this, null);\r
}\r
- \r
+\r
@Override\r
public int hashCode() {\r
return super.hashCode() ^ (partsSetId == null ? 0 : partsSetId.hashCode());\r
}\r
- \r
+\r
@Override\r
public boolean equals(Object o) {\r
if (o == this) {\r
if (affineTransformParameter == obj.affineTransformParameter\r
|| (affineTransformParameter != null\r
&& Arrays.equals(affineTransformParameter, obj.affineTransformParameter))) {\r
- return true;\r
+ // アクティブなカスタムレイヤーが同一の場合\r
+ if (activeCustomLayerPatternIds == obj.activeCustomLayerPatternIds\r
+ || (activeCustomLayerPatternIds != null\r
+ && activeCustomLayerPatternIds.equals(obj.activeCustomLayerPatternIds))) {\r
+ return true;\r
+ }\r
}\r
}\r
}\r
public void setPresetParts(boolean presetParts) {\r
this.presetParts = presetParts;\r
}\r
- \r
+\r
/**\r
* プリセット用パーツセットであるか? これがfalseの場合は一時的なパーツセットか、もしくはお気に入り用である.<br>\r
- * \r
+ *\r
* @return プリセット用パーツセットである場合\r
*/\r
public boolean isPresetParts() {\r
return presetParts;\r
}\r
- \r
+\r
public void setBgColor(Color bgColor) {\r
this.bgColor = bgColor;\r
}\r
/**\r
* バックグラウンドカラーを取得する.<br>\r
* 設定されていなければnull.<br>\r
- * \r
+ *\r
* @return バックグラウンドカラー、もしくはnull\r
*/\r
public Color getBgColor() {\r
* アフィン変換用パラメータを指定する.<br>\r
* 配列は4または6でなければならない.<br>\r
* アフィン変換しない場合はnull\r
- * \r
+ *\r
* @param affineTransformParameter\r
* 変換パラメータ(4または6個の要素)、もしくはnull\r
*/\r
public void setAffineTransformParameter(double[] affineTransformParameter) {\r
if (affineTransformParameter != null && !(affineTransformParameter.length == 4 || affineTransformParameter.length == 6)) {\r
- throw new IllegalArgumentException("affineTransformParameter invalid length.");\r
+ throw new IllegalArgumentException("The length of affineTransformParameter must be 4 or 6.");\r
}\r
this.affineTransformParameter = affineTransformParameter == null ? null : affineTransformParameter.clone();\r
}\r
- \r
+\r
/**\r
* アフィン変換用のパラメータを取得する.<br>\r
* 変換しない場合はnull.<br>\r
- * \r
+ *\r
* @return アフィン変換用のパラメータ、またはnull\r
*/\r
public double[] getAffineTransformParameter() {\r
return affineTransformParameter == null ? null : affineTransformParameter.clone();\r
}\r
- \r
+\r
+ /**\r
+ * アクティブなカスタムレイヤーパターン名、設定がなければnull可\r
+ * @return\r
+ */\r
+ public Set<String> getActiveCustomLayerPatternIds() {\r
+ return activeCustomLayerPatternIds;\r
+ }\r
+\r
+ public void setActiveCustomLayerPatternIds(Set<String> activeCustomLayerPatternIds) {\r
+ this.activeCustomLayerPatternIds = activeCustomLayerPatternIds;\r
+ }\r
+\r
public void setPartsSetId(String partsSetId) {\r
this.partsSetId = partsSetId;\r
}\r
- \r
+\r
public void setLocalizedName(String localizedName) {\r
this.localizedName = localizedName;\r
}\r
- \r
+\r
/**\r
* プリセットIDを取得する.<br>\r
* 一時的なパーツセットである場合はnull\r
- * \r
+ *\r
* @return プリセットID、またはnull\r
*/\r
public String getPartsSetId() {\r
/**\r
* プリセット名を取得する.<br>\r
* 一時的なパーツセットである場合はnull\r
- * \r
+ *\r
* @return プリセット名、またはnull\r
*/\r
public String getLocalizedName() {\r
return localizedName;\r
}\r
- \r
+\r
/**\r
* パーツセットのエントリセットを取得する.\r
*/\r
public Set<java.util.Map.Entry<PartsCategory, List<PartsIdentifier>>> entrySet() {\r
return parts.entrySet();\r
}\r
- \r
+\r
/**\r
* パーツカラー情報を取得する.<br>\r
* カラー情報が関連づけられていない場合はnullが返される.<br>\r
- * \r
+ *\r
* @param partsIdentifier\r
* パーツ識別子\r
* @return カラー情報、もしくはnull\r
PartsColorInfo partsColorInfo = partsColorInfoMap.get(partsIdentifier);\r
return partsColorInfo == null ? null : partsColorInfo.clone();\r
}\r
- \r
+\r
/**\r
* カテゴリ別にパーツを登録する.<br>\r
* partsNameがnullまたは空文字の場合はカテゴリのみ登録する.<br>\r
* これにより、そのカテゴリに選択がないことを示す.<br>\r
* 複数選択可能なカテゴリの場合、複数回の呼び出しで登録する.(登録順)<br>\r
- * \r
+ *\r
* @param category\r
* カテゴリ\r
* @param partsIdentifier\r
}\r
}\r
}\r
- \r
+\r
/**\r
* すべてのパーツのカラー情報を除去する.<br>\r
*/\r
public void removeColorInfo() {\r
partsColorInfoMap.clear();\r
}\r
- \r
+\r
/**\r
* パーツセットが構造的に一致するか検証します.<br>\r
* nullの場合は常にfalseとなります.<br>\r
- * \r
+ *\r
* @param other\r
* 比較対象、null可\r
* @return パーツ構成が一致すればtrue、そうでなければfalse\r
}\r
return false;\r
}\r
- \r
+\r
/**\r
* 2つのパーツセットが構造的に一致するか検証します.<br>\r
* いずれか一方がnullであればfalseを返します.双方がnullであればtrueを返します.<br>\r
* 双方がnullでなければ{@link #isSameStructure(PartsSet)}で判定されます.<br>\r
- * \r
+ *\r
* @param a\r
* 比較対象1、null可\r
* @param b\r
* 相手側はカテゴリや順序を問わず、少なくとも自分と同じパーツ識別子をもっていれば足りるため、 パーツ構成が同一であるかの判定は行いません.<br>\r
* パーツ構造を含めて判定を行う場合は事前に{@link #isSameStructure(PartsSet)}を呼び出します.<br>\r
* nullの場合は常にfalseとなります.<br>\r
- * \r
+ *\r
* @param other\r
* 判定先、null可\r
* @return 同一であればtrue、そうでなければfalse\r
}\r
return false;\r
}\r
- \r
+\r
+ /**\r
+ * カスタムレイヤーパターンが同一であるか?\r
+ * @param other\r
+ * @return\r
+ */\r
+ public boolean isSameCustomLayers(PartsSet other) {\r
+ if (other != null) {\r
+ Set<String> patternIds = other.getActiveCustomLayerPatternIds();\r
+ return activeCustomLayerPatternIds == null ? patternIds == null\r
+ : activeCustomLayerPatternIds.equals(patternIds);\r
+ }\r
+ return false;\r
+ }\r
+\r
/**\r
* 引数aが保持しているパーツ識別子のカラー情報と同一のカラー情報を引数bがもっているか判定します.<br>\r
* 引数b側はカテゴリや順序を問わず、少なくとも引数aと同じパーツ識別子をもっていれば足りるため、 パーツ構成が同一であるかの判定は行いません.<br>\r
* パーツ構造を含めて判定を行う場合は事前に{@link #isSameStructure(PartsSet, PartsSet)}を呼び出します.<br>\r
* 双方がnullであればtrueとなります.<br>\r
* いずれか一方がnullの場合はfalseとなります.<br>\r
- * \r
+ *\r
* @param a\r
* 対象1、null可\r
* @param b\r
}\r
return a.isSameColor(b);\r
}\r
- \r
+\r
+ /**\r
+ * アクティブなカスタムレイヤーパターン名が同一であるか?\r
+ * @param a\r
+ * @param b\r
+ * @return\r
+ */\r
+ public static boolean isSameCustomLayers(PartsSet a, PartsSet b) {\r
+ if (a == b) {\r
+ return true;\r
+ }\r
+ if (a == null || b == null) {\r
+ return false;\r
+ }\r
+ return a.isSameCustomLayers(b);\r
+ }\r
+\r
/**\r
* このパーツセットが名前をもっているか?\r
- * \r
+ *\r
* @return 名前がある場合はtrue、設定されていないか空文字の場合はfalse\r
*/\r
public boolean hasName() {\r
return localizedName != null && localizedName.length() > 0;\r
}\r
- \r
+\r
@Override\r
public String toString() {\r
StringBuilder buf = new StringBuilder();\r
buf.append("affin-trans-param: " + Arrays.toString(affineTransformParameter) + ", ");\r
buf.append("parts: " + parts + ", ");\r
buf.append("partsColorMap: " + partsColorInfoMap);\r
+ buf.append("activeCustomLayerPatternIds: " + activeCustomLayerPatternIds);\r
buf.append(")");\r
return buf.toString();\r
}\r
- \r
+\r
}\r
package charactermanaj.model;\r
\r
-import java.io.Serializable;\r
-\r
/**\r
* パーツの構成情報.<br>\r
* @author seraphy\r
*/\r
-public class PartsSpec implements Serializable {\r
-\r
- private static final long serialVersionUID = -5275967668710789314L;\r
+public class PartsSpec {\r
\r
private PartsIdentifier partsIdentifier;\r
- \r
+\r
private ColorGroup colorGroup = ColorGroup.NA;\r
- \r
+\r
private PartsFiles partsFiles;\r
- \r
+\r
/**\r
* パーツの作者情報、指定がなければnull\r
*/\r
private PartsAuthorInfo authorInfo;\r
- \r
+\r
/**\r
* パーツのバージョン、指定がなければ0\r
*/\r
private double version;\r
- \r
+\r
/**\r
* ダウンロードURL\r
*/\r
private String downloadURL;\r
\r
- \r
+\r
public PartsSpec(PartsIdentifier partsIdentifier) {\r
if (partsIdentifier == null) {\r
throw new IllegalArgumentException();\r
this.partsIdentifier = partsIdentifier;\r
this.partsFiles = new PartsFiles(partsIdentifier);\r
}\r
- \r
+\r
public PartsIdentifier getPartsIdentifier() {\r
return partsIdentifier;\r
}\r
- \r
+\r
public PartsFiles getPartsFiles() {\r
return partsFiles;\r
}\r
public void setAuthorInfo(PartsAuthorInfo authorInfo) {\r
this.authorInfo = authorInfo;\r
}\r
- \r
+\r
public PartsAuthorInfo getAuthorInfo() {\r
return authorInfo;\r
}\r
- \r
+\r
public String getAuthor() {\r
if (authorInfo != null) {\r
return authorInfo.getAuthor();\r
}\r
return null;\r
}\r
- \r
+\r
public void setVersion(double version) {\r
this.version = version;\r
}\r
- \r
+\r
public double getVersion() {\r
return version;\r
}\r
- \r
+\r
public String getDownloadURL() {\r
return downloadURL;\r
}\r
- \r
+\r
public void setDownloadURL(String downloadURL) {\r
this.downloadURL = downloadURL;\r
}\r
- \r
+\r
public void setColorGroup(ColorGroup colorGroup) {\r
if (colorGroup == null) {\r
colorGroup = ColorGroup.NA;\r
}\r
this.colorGroup = colorGroup;\r
}\r
- \r
+\r
public ColorGroup getColorGroup() {\r
return colorGroup;\r
}\r
- \r
+\r
}\r
package charactermanaj.model;\r
\r
-import java.io.Serializable;\r
-\r
/**\r
* お勧めリンク\r
* @author seraphy\r
*/\r
-public class RecommendationURL implements Serializable, Cloneable {\r
-\r
- private static final long serialVersionUID = 3568122645473390201L;\r
+public class RecommendationURL implements Cloneable {\r
\r
private String displayName;\r
- \r
+\r
private String url;\r
- \r
+\r
@Override\r
public RecommendationURL clone() {\r
try {\r
throw new RuntimeException(ex);\r
}\r
}\r
- \r
+\r
@Override\r
public int hashCode() {\r
if (url == null) {\r
}\r
return url.hashCode();\r
}\r
- \r
+\r
@Override\r
public boolean equals(Object obj) {\r
if (obj == this) {\r
public void setUrl(String url) {\r
this.url = url;\r
}\r
- \r
+\r
@Override\r
public String toString() {\r
return "displayName=" + displayName + "/url=" + url;\r
import java.awt.Point;\r
import java.awt.Rectangle;\r
import java.io.File;\r
-import java.io.IOException;\r
-import java.io.ObjectInputStream;\r
-import java.io.ObjectInputStream.GetField;\r
-import java.io.ObjectStreamClass;\r
-import java.io.Serializable;\r
import java.net.URI;\r
-import java.net.URL;\r
import java.util.Map;\r
-import java.util.logging.Level;\r
import java.util.logging.Logger;\r
\r
import charactermanaj.ui.model.WallpaperInfo;\r
\r
-public class WorkingSet implements Serializable {\r
+public class WorkingSet {\r
\r
/**\r
* ロガー\r
*/\r
private static final Logger logger = Logger.getLogger(WorkingSet.class.getName());\r
\r
- private static final long serialVersionUID = -4728766140876842242L;\r
-\r
private Map<PartsIdentifier, PartsColorInfo> partsColorInfoMap;\r
\r
private String characterDataRev;\r
/**\r
* 現在の選択中のパーツと色設定からのパーツセット\r
*/\r
- private PartsSet partsSet;\r
+ private PartsSet currentPartsSet;\r
\r
private URI characterDocBase;\r
\r
private WallpaperInfo wallpaperInfo;\r
\r
// ver0.999\r
+\r
+ /**\r
+ * ズーム\r
+ */\r
private Double zoomFactor;\r
\r
+ /**\r
+ * ビューの中央位置\r
+ * (ズーム倍率の保存はv0.999から、未指定の場合はnull)\r
+ */\r
private Point viewPosition;\r
\r
- private Rectangle windowRect;\r
-\r
/**\r
- * デシリアライズ\r
- *\r
- * @param inp\r
- * オブジェクトの復元ストリーム\r
- * @throws IOException\r
- * 例外\r
- * @throws ClassNotFoundException\r
- * 例外\r
+ * ウィンドウの位置と大きさ\r
*/\r
- @SuppressWarnings("unchecked")\r
- private void readObject(ObjectInputStream inp) throws IOException,\r
- ClassNotFoundException {\r
- GetField fields = inp.readFields();\r
-\r
- ObjectStreamClass sig = fields.getObjectStreamClass();\r
- if (logger.isLoggable(Level.FINE)) {\r
- logger.log(Level.FINE, "WorkingSetのデシリアライズ name=" + sig.getName()\r
- + "/sid=" + sig.getSerialVersionUID());\r
- }\r
-\r
- partsColorInfoMap = (Map<PartsIdentifier, PartsColorInfo>) fields.get("partsColorInfoMap", null);\r
- characterDataRev = (String) fields.get("characterDataRev", null);\r
- partsSet = (PartsSet) fields.get("partsSet", null);\r
-\r
- Object anyDocBase = fields.get("characterDocBase", null);\r
- if (anyDocBase != null && anyDocBase instanceof URL) {\r
- File file = new File(((URL) anyDocBase).getPath());\r
- anyDocBase = file.toURI();\r
- }\r
- // ver0.95からURI, それ以前はURL\r
- characterDocBase = (URI) anyDocBase;\r
-\r
- lastUsedSaveDir = (File) fields.get("lastUsedSaveDir", null);\r
- lastUsedExportDir = (File) fields.get("lastUsedExportDir", null);\r
-\r
- // ver0.92\r
- lastUsePresetParts = (PartsSet) fields.get("lastUsePresetParts", null);\r
-\r
- // ver0.94\r
- characterData = (CharacterData) fields.get("characterData", null);\r
-\r
- // ver0.97\r
- wallpaperInfo = (WallpaperInfo) fields.get("wallpaperInfo", null);\r
-\r
- // ver0.999\r
- zoomFactor = (Double) fields.get("zoomFactor", null);\r
- viewPosition = (Point) fields.get("viewCenterPoint", null);\r
- windowRect = (Rectangle) fields.get("windowRect", null);\r
- }\r
-\r
+ private Rectangle windowRect;\r
\r
public void setCharacterDataRev(String characterDataRev) {\r
this.characterDataRev = characterDataRev;\r
this.characterDocBase = characterDocBase;\r
}\r
\r
- public void setPartsSet(PartsSet partsSet) {\r
- this.partsSet = partsSet;\r
+ public void setCurrentPartsSet(PartsSet currentPartsSet) {\r
+ this.currentPartsSet = currentPartsSet;\r
}\r
\r
public URI getCharacterDocBase() {\r
return characterDocBase;\r
}\r
\r
- public PartsSet getPartsSet() {\r
- return partsSet;\r
+ public PartsSet getCurrentPartsSet() {\r
+ return currentPartsSet;\r
}\r
\r
public void setLastUsedSaveDir(File lastUsedSaveDir) {\r
import java.util.EnumSet;\r
import java.util.Enumeration;\r
import java.util.LinkedHashMap;\r
+import java.util.List;\r
import java.util.Map;\r
import java.util.Properties;\r
import java.util.logging.Level;\r
import java.util.logging.Logger;\r
\r
import charactermanaj.model.CharacterData;\r
+import charactermanaj.model.CustomLayerOrder;\r
+import charactermanaj.model.CustomLayerOrderKey;\r
import charactermanaj.util.ConfigurationDirUtilities;\r
import charactermanaj.util.LocalizedResourcePropertyLoader;\r
import charactermanaj.util.ResourceLoader;\r
\r
/**\r
* デフォルトキャラクターセットのプロバイダ\r
- * \r
+ *\r
* @author seraphy\r
*/\r
public class CharacterDataDefaultProvider {\r
public static final String DEFAULT_CHARACTER_NAME_V3 = "character3.xml";\r
\r
/**\r
+ * カスタムレイヤー順定義ファイルの末尾名。\r
+ * リソース名「xxxxx.xml」に対して「xxxxx-customlayerorders.xml」のようになる。\r
+ */\r
+ private static final String CUSTOM_LAYER_ORDERS_SUFFIX = "-customlayerorders.xml";\r
+\r
+ /**\r
* ロガー\r
*/\r
private static final Logger logger = Logger\r
.getLogger(CharacterDataDefaultProvider.class.getName());\r
\r
public enum DefaultCharacterDataVersion {\r
- V2() {\r
- public String getResourceName() {\r
- return DEFAULT_CHARACTER_NAME_V2;\r
- }\r
- },\r
- V3() {\r
- public String getResourceName() {\r
- return DEFAULT_CHARACTER_NAME_V3;\r
- }\r
- };\r
+ V2(DEFAULT_CHARACTER_NAME_V2),\r
+ V3(DEFAULT_CHARACTER_NAME_V3);\r
\r
- public abstract String getResourceName();\r
+ DefaultCharacterDataVersion(String reskey) {\r
+ this.reskey = reskey;\r
+ }\r
+\r
+ private final String reskey;\r
+\r
+ public String getResourceName() {\r
+ return reskey;\r
+ }\r
\r
public CharacterData create(CharacterDataDefaultProvider prov) {\r
if (prov == null) {\r
throw new IllegalArgumentException();\r
}\r
try {\r
- return prov.loadPredefinedCharacterData(getResourceName());\r
+ return prov.loadPredefinedCharacterData(reskey);\r
+\r
+ } catch (IOException ex) {\r
+ throw new RuntimeException(\r
+ "can not create the default profile from application's resource",\r
+ ex);\r
+ }\r
+ }\r
+\r
+ public Map<CustomLayerOrderKey, List<CustomLayerOrder>> createCustomLayerOrderMap(CharacterData cd,\r
+ CharacterDataDefaultProvider prov) {\r
+ if (prov == null) {\r
+ throw new IllegalArgumentException();\r
+ }\r
+ try {\r
+ return prov.loadPredefinedCustomLayerOrder(cd, reskey);\r
\r
} catch (IOException ex) {\r
throw new RuntimeException(\r
* デフォルトのキャラクター定義を生成して返す.<br>\r
* 一度生成された場合はキャッシュされる.<br>\r
* 生成されたキャラクター定義のdocBaseはnullであるため、docBaseをセットすること.<br>\r
- * \r
+ *\r
* @param version\r
* デフォルトキャラクターセットのバージョン\r
* @return キャラクター定義\r
return version.create(this);\r
}\r
\r
+ public Map<CustomLayerOrderKey, List<CustomLayerOrder>> createDefaultCustomLayerOrderMap(\r
+ CharacterData cd, DefaultCharacterDataVersion version) {\r
+ if (version == null) {\r
+ throw new IllegalArgumentException();\r
+ }\r
+ return version.createCustomLayerOrderMap(cd, this);\r
+ }\r
+\r
/**\r
* テンプレートリストの定義プロパティを読み込む.<br>\r
* neutral引数がfalseの場合は現在のロケールを優先する.<br>\r
* 引数がtrueの場合は読み込み順を逆転させ、言語中立を優先する.<br>\r
- * \r
+ *\r
* @param neutral\r
* 言語中立を優先する場合\r
* @return テンプレートリストのプロパティ\r
/**\r
* キャラクターデータのxmlファイル名をキーとし、表示名を値とするマップ.<br>\r
* 表示順序でアクセス可能.<br>\r
- * \r
+ *\r
* @return 順序付マップ\r
*/\r
public Map<String, String> getCharacterDataTemplates() {\r
* (現在のロケールの言語に対応するデータを取得し、なければ最初の言語で代替する.)<br>\r
* 生成されたキャラクター定義のdocBaseはnullであるため、使用する場合はdocBaseをセットすること.<br>\r
* 都度、XMLファイルから読み込まれる.<br>\r
- * \r
+ *\r
* @return デフォルトキャラクターデータ\r
* @throws IOException\r
* 失敗\r
}\r
\r
/**\r
+ * XMLリソースファイルから、定義済みのカスタムレイヤーパターンを生成して返す。\r
+ * 指定されたリソース名に対して「-customlayerorders.xml」のような末尾に変えたリソースで検索される。\r
+ * 定義がない場合はnullを返す。\r
+ * @param cd\r
+ * @param name リソース名\r
+ * @return\r
+ * @throws IOException\r
+ */\r
+ public Map<CustomLayerOrderKey, List<CustomLayerOrder>> loadPredefinedCustomLayerOrder(CharacterData cd, String name)\r
+ throws IOException {\r
+ // キャラクター定義xmlへのリソース名から、カスタムレイヤー定義のリソース名を組み立てる\r
+ int pt = name.lastIndexOf(".");\r
+ String nameBody = name.substring(0, pt);\r
+ String customLayerMappingXml = nameBody + CUSTOM_LAYER_ORDERS_SUFFIX;\r
+\r
+ String resKey = DEFAULT_CHARACTER_PREFIX + customLayerMappingXml;\r
+ URL predefinedCharacter = getResource(resKey);\r
+ if (predefinedCharacter == null) {\r
+ // リソースがない\r
+ return null;\r
+ }\r
+\r
+ InputStream is = predefinedCharacter.openStream();\r
+ try {\r
+ logger.log(Level.INFO, "load a predefined custom layer orders. resKey=" + resKey);\r
+ CustomLayerOrderXMLReader xmlReader = new CustomLayerOrderXMLReader(cd);\r
+ return xmlReader.read(is);\r
+\r
+ } finally {\r
+ is.close();\r
+ }\r
+ }\r
+\r
+ /**\r
* リソースを取得する.<br>\r
- * \r
+ *\r
* @param resKey\r
* リソースキー\r
* @return リソース、なければnull\r
/**\r
* カスタマイズ用のテンプレートディレクトリを取得する.<br>\r
* まだ作成されていない場合で、prepareが指示されている場合はフォルダを準備し、 既定のファイルを作成する.<br>\r
- * \r
+ *\r
* @param prepare\r
* 実際にディレクトリを準備する場合はtrue\r
* @return テンプレートディレクトリ\r
/**\r
* "characterDataTemplates*.xml"のファイルは管理ファイルのため、 <br>\r
* ユーザによる書き込みは禁止とする.<br>\r
- * \r
+ *\r
* @param name\r
* @return 書き込み可能であるか?\r
*/\r
\r
/**\r
* 指定したキャラクターデータをテンプレートとして保存する.<br>\r
- * \r
+ *\r
* @param name\r
* 保存するテンプレートファイル名\r
* @param cd\r
public static final String COMPATIBLE_CONFIG_NAME = "character.ini";\r
\r
/**\r
+ * お気に入りのファイル名\r
+ */\r
+ private static final String FAVORITES_FILE_NAME = "favorites.xml";\r
+\r
+ /**\r
+ * サンプルイメージファイル名\r
+ */\r
+ private static final String SAMPLE_IMAGE_FILENAME = "preview.png";\r
+\r
+ /**\r
* ロガー\r
*/\r
private static final Logger logger = Logger\r
private final CharacterDataXMLWriter characterDataXmlWriter = new CharacterDataXMLWriter();\r
\r
/**\r
- * サンプルイメージファイル名\r
- */\r
- private static final String SAMPLE_IMAGE_FILENAME = "preview.png";\r
-\r
- /**\r
* プロファイルの列挙時のエラーハンドラ.<br>\r
- * \r
+ *\r
* @author seraphy\r
*/\r
public interface ProfileListErrorHandler {\r
\r
/**\r
* エラーが発生したことを通知される\r
- * \r
+ *\r
* @param baseDir\r
* 読み込み対象のXMLのファイル\r
* @param ex\r
\r
/**\r
* インスタンスを取得する\r
- * \r
+ *\r
* @return インスタンス\r
*/\r
public static CharacterDataPersistent getInstance() {\r
* 保存先ディレクトリはユーザー固有のキャラクターデータ保存先のディレクトリにキャラクター定義のIDを基本とする ディレクトリを作成して保存される.<br>\r
* ただし、そのディレクトリがすでに存在する場合はランダムな名前で決定される.<br>\r
* 実際のxmlの保存先にあわせてDocBaseが設定されて返される.<br>\r
- * \r
+ *\r
* @param characterData\r
* キャラクターデータ (IDは設定済みであること.それ以外はvalid, editableであること。)\r
* @throws IOException\r
// 保存先を確認\r
File characterPropXML = new File(baseDir, CONFIG_FILE);\r
if (characterPropXML.exists() && !characterPropXML.isFile()) {\r
- throw new IOException("character.xml is not a regular file.:"\r
+ throw new IOException(CONFIG_FILE + " is not a regular file.:"\r
+ characterPropXML);\r
}\r
if (characterPropXML.exists() && !characterPropXML.canWrite()) {\r
\r
/**\r
* リビジョンを生成して返す.\r
- * \r
+ *\r
* @return リビジョン用文字列\r
*/\r
public String generateRev() {\r
\r
/**\r
* 衝突回避用の末尾文字を生成する.\r
- * \r
+ *\r
* @param retryCount\r
* リトライ回数\r
* @return 末尾文字\r
\r
/**\r
* キャラクターデータを更新する.\r
- * \r
+ *\r
* @param characterData\r
* キャラクターデータ(有効かつ編集可能であること)\r
* @throws IOException\r
\r
/**\r
* キャラクターデータのパーツイメージを保存するディレクトリを準備する\r
- * \r
+ *\r
* @param characterData\r
* キャラクターデータ\r
* @param baseDir\r
* キャラクターデータを読み込んだ場合.<br>\r
* 戻り値がfalseの場合は読み込みを以降の読み込みを中断します.<br>\r
* (ただし、すでに読み込み開始している分については中断されません.)\r
- * \r
+ *\r
* @param characterData\r
* @return 継続する場合はtrue、中止する場合はfalse\r
*/\r
* キャラクターデータの読み込みに失敗した場合.<br>\r
* 戻り値がfalseの場合は読み込みを以降の読み込みを中断します.<br>\r
* (ただし、すでに読み込み開始している分については中断されません.)\r
- * \r
+ *\r
* @param dir\r
* 読み込み対象ディレクトリ\r
* @param ex\r
* キャラクターなんとか機のディレクトリとして、標準のcharacter.xmlを生成する.<br>\r
* ただし、書き込み禁止の場合は何もしない.<br>\r
* すでにcharacter.xmlがある場合も何もしない.<br>\r
- * \r
+ *\r
* @param dataDir\r
* キャラクターなんとか機のデータディレクトリ\r
*/\r
/**\r
* キャラクターデータを非同期に読み込む.<br>\r
* 読み込み完了したものが随時、コールバックに渡される.\r
- * \r
+ *\r
* @param callback\r
* @return すべての読み込みが完了したか判定し待機することのできるFuture\r
*/\r
* 読み取りに失敗した場合はエラーハンドラに通知されるが例外は返されない.<br>\r
* 一つも正常なプロファイルがない場合は空のリストが返される.<br>\r
* エラーハンドラの通知は非同期に行われる.\r
- * \r
+ *\r
* @param errorHandler\r
* エラーハンドラ、不要ならばnull\r
* @return プロファイルのリスト(表示名順)、もしくは空\r
// xml形式の場合、キャラクターディレクトリ上に設定する.\r
URI docBase = characterData.getDocBase();\r
File characterDir = new File(docBase).getParentFile();\r
- return new FileUserData(new File(characterDir, "favorites.xml"));\r
+ return new FileUserData(new File(characterDir, FAVORITES_FILE_NAME));\r
}\r
\r
\r
/**\r
* お気に入り(Favorites)を読み込む.<br>\r
* 現在のパーツセットに追加する形で読み込まれ、同じパーツセットIDのものは上書きされます.<br>\r
- * \r
+ *\r
* @param characterData\r
* キャラクターデータ\r
* @throws IOException\r
}\r
\r
UserData favoritesXml = getFavoritesUserData(characterData);\r
- if (favoritesXml.exists()) {\r
+ if (favoritesXml.exists() && favoritesXml.length() > 0) {\r
InputStream is = favoritesXml.openStream();\r
try {\r
characterDataXmlReader.loadPartsSet(characterData, is);\r
* リネームすることでキャラクター定義として認識させなくする.<br>\r
* forceRevmoeがtrueの場合は実際にファイルを削除する.<br>\r
* character.xml、favorites、workingsetのキャッシュも削除される.<br>\r
- * \r
+ *\r
* @param cd\r
* キャラクター定義\r
* @param forceRemove\r
/**\r
* 指定したファイルを削除します.<br>\r
* 指定したファイルがディレクトリを示す場合、このディレクトリを含む配下のすべてのファイルとディレクトリを削除します.<br>\r
- * \r
+ *\r
* @param file\r
* ファイル、またはディレクトリ\r
* @throws IOException\r
/**\r
* サンプルピクチャを読み込む.<br>\r
* ピクチャが存在しなければnullを返す. キャラクター定義がValidでない場合は常にnullを返す.<br>\r
- * \r
+ *\r
* @param characterData\r
* キャラクター定義、null不可\r
* @param loader\r
* キャラクターのサンプルピクチャが登録可能であるか?<br>\r
* キャラクターデータが有効であり、且つ、ファイルの書き込みが可能であればtrueを返す.<br>\r
* キャラクターデータがnullもしくは無効であるか、ファイルプロトコルでないか、ファイルが書き込み禁止であればfalseょ返す.<br>\r
- * \r
+ *\r
* @param characterData\r
* キャラクターデータ\r
* @return 書き込み可能であればtrue、そうでなければfalse\r
* サンプルピクチャとして認識されるファイル位置を返す.<br>\r
* ファイルが実在するかは問わない.<br>\r
* DocBaseが未設定であるか、ファィルプロトコルとして返せない場合はnullを返す.<br>\r
- * \r
+ *\r
* @param characterData\r
* キャラクター定義\r
* @return サンプルピクチャの保存先のファイル位置、もしくはnull\r
\r
/**\r
* サンプルピクチャを保存する.\r
- * \r
+ *\r
* @param characterData\r
* キャラクターデータ\r
* @param samplePicture\r
* character.iniを読み取り、character.xmlを生成します.<br>\r
* すでにcharacter.xmlがある場合は上書きされます.<br>\r
* 途中でエラーが発生した場合はcharacter.xmlは削除されます.<br>\r
- * \r
+ *\r
* @param characterIniFile\r
* 読み取るcharatcer.iniファイル\r
* @param characterXmlFile\r
* おすすめリンクがサポートされてなかったころのデータは、おすすめリンク用のタグそのものが存在せずnullとなる.<br>\r
* サポート後のデータでリンクを未設定にしている場合は、空のリストとなる.<br>\r
* したがって、nullの場合のみ、おすすめリンクを補完する.<br>\r
- * \r
+ *\r
* @param characterData\r
* キャラクターデータ\r
*/\r
import java.util.List;\r
import java.util.Locale;\r
import java.util.Map;\r
+import java.util.Set;\r
+import java.util.TreeSet;\r
import java.util.logging.Level;\r
import java.util.logging.Logger;\r
\r
categoryPartsMap.put(partsName, infoList);\r
}\r
}\r
+\r
+ // アクティブなレイヤーパターン\r
+ for (Element patternsElm : getChildElements(presetElm, "active-custom-layer-patterns")) {\r
+ Set<String> patternIds = new TreeSet<String>();\r
+ for (Element patElm : getChildElements(patternsElm, "pattern")) {\r
+ String id = patElm.getAttribute("id");\r
+ patternIds.add(id);\r
+ }\r
+ partsSetInfo.setActiveCustomLayerPatternIds(patternIds);\r
+ break;\r
+ }\r
+\r
return partsSetInfo;\r
}\r
\r
import java.util.List;\r
import java.util.Locale;\r
import java.util.Map;\r
+import java.util.Set;\r
\r
import javax.xml.XMLConstants;\r
import javax.xml.parsers.DocumentBuilder;\r
\r
/**\r
* パーツ管理情報のXMLへの書き込み用クラス.\r
- * \r
+ *\r
* @author seraphy\r
*/\r
public class CharacterDataXMLWriter {\r
private static final String DEFAULT_NS = "http://charactermanaj.sourceforge.jp/schema/charactermanaj";\r
\r
private final String NS;\r
- \r
+\r
public CharacterDataXMLWriter() {\r
this(DEFAULT_NS);\r
}\r
- \r
+\r
public CharacterDataXMLWriter(String ns) {\r
this.NS = ns;\r
}\r
- \r
+\r
/**\r
* キャラクターデータのXMLの書き込み.\r
- * \r
+ *\r
* @param characterData\r
* @param outstm\r
* @throws IOException\r
\r
/**\r
* キャラクターデータ内のPresetおよびFavotiesのPartssetの双方共通のパーツセット要素のリストを構築する.\r
- * \r
+ *\r
* @param doc\r
* ドキュメントオブジェクト(createElementNS用)\r
* @param baseElement\r
\r
return registeredPartsSetMap.size();\r
}\r
- \r
+\r
/**\r
* パーツセットのXM要素を生成して返す.\r
- * \r
+ *\r
* @param doc\r
* ノードを生成するためのファクトリ\r
* @param lang\r
}\r
}\r
}\r
- \r
+\r
+ // アクティブなレイヤーパターン\r
+ Set<String> patternIds = partsSet.getActiveCustomLayerPatternIds();\r
+ if (patternIds != null) {\r
+ Element patternsElm = doc.createElementNS(NS, "active-custom-layer-patterns");\r
+ for (String patternId : patternIds) {\r
+ Element patElm = doc.createElementNS(NS, "pattern");\r
+ patElm.setAttribute("id", patternId);\r
+ patternsElm.appendChild(patElm);\r
+ }\r
+ nodePreset.appendChild(patternsElm);\r
+ }\r
+\r
return nodePreset;\r
}\r
- \r
+\r
/**\r
* パーツカラー情報のXML要素を生成して返す.<br>\r
- * \r
+ *\r
* @param doc\r
* 要素を作成するためのファクトリ\r
* @param partsColorInfo\r
Float.toString(param.getGrayLevel()));\r
nodeLayer.appendChild(nodeRGBReplace);\r
}\r
- \r
+\r
return nodeColor;\r
}\r
\r
\r
import charactermanaj.model.CharacterData;\r
import charactermanaj.model.CustomLayerOrder;\r
+import charactermanaj.model.CustomLayerOrderKey;\r
import charactermanaj.model.io.CustomLayerOrderPersist.CustomLayerOrderPersistListener.Change;\r
import charactermanaj.util.FileUserData;\r
import charactermanaj.util.UserData;\r
public static class Change extends EventObject {\r
private static final long serialVersionUID = 9176040093651262447L;\r
\r
- private Map<String, List<CustomLayerOrder>> customLayerOrderMap;\r
+ private Map<CustomLayerOrderKey, List<CustomLayerOrder>> customLayerOrderMap;\r
\r
- public Change(CharacterData characterData, Map<String, List<CustomLayerOrder>> customLayerOrderMap) {\r
+ public Change(CharacterData characterData, Map<CustomLayerOrderKey, List<CustomLayerOrder>> customLayerOrderMap) {\r
super(characterData);\r
this.customLayerOrderMap = customLayerOrderMap;\r
}\r
return (CharacterData) super.getSource();\r
}\r
\r
- public Map<String, List<CustomLayerOrder>> getCustomLayerOrderMap() {\r
+ public Map<CustomLayerOrderKey, List<CustomLayerOrder>> getCustomLayerOrderMap() {\r
return customLayerOrderMap;\r
}\r
}\r
return new CustomLayerOrderXMLPersist(characterData);\r
}\r
\r
- public abstract void save(Map<String, List<CustomLayerOrder>> map) throws IOException;\r
+ public abstract boolean exist();\r
\r
- public abstract Map<String, List<CustomLayerOrder>> load() throws IOException;\r
+ public abstract void save(Map<CustomLayerOrderKey, List<CustomLayerOrder>> map) throws IOException;\r
+\r
+ public abstract Map<CustomLayerOrderKey, List<CustomLayerOrder>> load() throws IOException;\r
\r
private static final Map<URI, Queue<CustomLayerOrderPersistListener>> listenersMap =\r
new ConcurrentHashMap<URI, Queue<CustomLayerOrderPersistListener>>();\r
}\r
}\r
\r
- protected void fireEvent(Map<String, List<CustomLayerOrder>> map) {\r
+ protected void fireEvent(Map<CustomLayerOrderKey, List<CustomLayerOrder>> map) {\r
URI uri = characterData.getDocBase();\r
if (uri != null) {\r
Queue<CustomLayerOrderPersistListener> listeners = listenersMap.get(uri);\r
return new FileUserData(new File(characterDir, CUSTOM_LAYER_ORDERS_XML_FILE));\r
}\r
\r
+ public boolean exist() {\r
+ return getCustomLayerOrdersUserData().exists();\r
+ }\r
+\r
@Override\r
- public void save(Map<String, List<CustomLayerOrder>> map) throws IOException {\r
+ public void save(Map<CustomLayerOrderKey, List<CustomLayerOrder>> map) throws IOException {\r
UserData xmlData = getCustomLayerOrdersUserData();\r
OutputStream outstm = xmlData.getOutputStream();\r
try {\r
}\r
\r
@Override\r
- public Map<String, List<CustomLayerOrder>> load() throws IOException {\r
+ public Map<CustomLayerOrderKey, List<CustomLayerOrder>> load() throws IOException {\r
UserData xmlData = getCustomLayerOrdersUserData();\r
- if (xmlData.exists()) {\r
+ if (xmlData.exists() && xmlData.length() > 0) {\r
InputStream is = xmlData.openStream();\r
try {\r
CustomLayerOrderXMLReader xmlReader = new CustomLayerOrderXMLReader(characterData);\r
import java.io.IOException;\r
import java.io.InputStream;\r
import java.util.ArrayList;\r
+import java.util.HashMap;\r
import java.util.List;\r
import java.util.Locale;\r
import java.util.Map;\r
\r
import charactermanaj.model.CharacterData;\r
import charactermanaj.model.CustomLayerOrder;\r
+import charactermanaj.model.CustomLayerOrderKey;\r
import charactermanaj.model.Layer;\r
import charactermanaj.model.PartsCategory;\r
\r
this.cd = cd;\r
}\r
\r
- public Map<String, List<CustomLayerOrder>> read(InputStream is) throws IOException {\r
+ public Map<CustomLayerOrderKey, List<CustomLayerOrder>> read(InputStream is) throws IOException {\r
if (is == null) {\r
throw new IllegalArgumentException();\r
}\r
\r
- Map<String, List<CustomLayerOrder>> map = new TreeMap<String, List<CustomLayerOrder>>();\r
+ Map<CustomLayerOrderKey, List<CustomLayerOrder>> map =\r
+ new TreeMap<CustomLayerOrderKey, List<CustomLayerOrder>>();\r
\r
Document doc = loadDocument(is);\r
String lang = Locale.getDefault().getLanguage();\r
}\r
\r
for (Element elmPattern : getChildElements(docElm, "pattern")) {\r
+ String id = elmPattern.getAttribute("id");\r
String patternName = elmPattern.getAttribute("name");\r
\r
+ if (id == null || id.length() == 0) {\r
+ id = patternName; // idが省略されている場合はnameで代用する\r
+ }\r
+\r
+ Map<String, String> localizedNames = new HashMap<String, String>();\r
+ localizedNames.put(CustomLayerOrderKey.DEFAULT_NAME_KEY, patternName);\r
+\r
for (Element elmLocalizedName : getChildElements(elmPattern, "localized-name")) {\r
String localizedLang = elmLocalizedName.getAttribute("lang");\r
String localizedName = elmLocalizedName.getAttribute("name");\r
+ localizedNames.put(localizedLang, localizedName);\r
if (lang.equals(localizedLang)) {\r
// langが一致すれば、その名前を優先する\r
patternName = localizedName;\r
for (Element elmMapping : getChildElements(elmPattern, "mapping")) {\r
String categoryId = elmMapping.getAttribute("category");\r
String layerId = elmMapping.getAttribute("layer");\r
- int layerOrder = Integer.parseInt(elmMapping.getAttribute("order"));\r
+ float layerOrder = Float.parseFloat(elmMapping.getAttribute("order"));\r
\r
PartsCategory category = cd.getPartsCategory(categoryId);\r
if (category != null) {\r
}\r
}\r
\r
- map.put(patternName, orders);\r
+ CustomLayerOrderKey patternKey = new CustomLayerOrderKey(id, patternName, localizedNames);\r
+ map.put(patternKey, orders);\r
}\r
\r
} catch (RuntimeException ex) {\r
import java.nio.charset.Charset;\r
import java.util.Collections;\r
import java.util.List;\r
-import java.util.Locale;\r
import java.util.Map;\r
\r
import javax.xml.XMLConstants;\r
import org.w3c.dom.Element;\r
\r
import charactermanaj.model.CustomLayerOrder;\r
+import charactermanaj.model.CustomLayerOrderKey;\r
import charactermanaj.model.Layer;\r
import charactermanaj.model.PartsCategory;\r
\r
*/\r
public static final String NS = "http://charactermanaj.osdn.jp/schema/customlayerorder.xsd";\r
\r
- public void write(Map<String, List<CustomLayerOrder>> map, OutputStream outstm) throws IOException {\r
+ public void write(Map<CustomLayerOrderKey, List<CustomLayerOrder>> map, OutputStream outstm) throws IOException {\r
Document doc = createDocument(map);\r
\r
// output xml\r
}\r
}\r
\r
- public Document createDocument(Map<String, List<CustomLayerOrder>> map) {\r
+ public Document createDocument(Map<CustomLayerOrderKey, List<CustomLayerOrder>> map) {\r
if (map == null) {\r
map = Collections.emptyMap();\r
}\r
throw new RuntimeException("JAXP Configuration failed.", ex);\r
}\r
\r
- Locale locale = Locale.getDefault();\r
- String lang = locale.getLanguage();\r
-\r
// ルートの登録\r
Element root = doc.createElementNS(NS, "custom-layer-orders");\r
root.setAttribute("version", VERSION_SIG_1_0);\r
XMLConstants.XML_NS_URI);\r
root.setAttribute("xsi:schemaLocation", NS + " customlayerorder.xsd");\r
\r
- for (Map.Entry<String, List<CustomLayerOrder>> entry : map.entrySet()) {\r
- String name = entry.getKey();\r
+ for (Map.Entry<CustomLayerOrderKey, List<CustomLayerOrder>> entry : map.entrySet()) {\r
+ CustomLayerOrderKey orderKey = entry.getKey();\r
+ String id = orderKey.getId();\r
+ String displayName = orderKey.getDisplayName();\r
+\r
+ Map<String, String> localizedNames = orderKey.getLocalizedNames();\r
+ String defaultName = localizedNames.get(CustomLayerOrderKey.DEFAULT_NAME_KEY);\r
+ if (defaultName == null) {\r
+ defaultName = displayName;\r
+ }\r
+\r
List<CustomLayerOrder> orders = entry.getValue();\r
\r
// パターンの登録\r
Element elmPattern = doc.createElementNS(NS, "pattern");\r
- elmPattern.setAttribute("name", name);\r
+ elmPattern.setAttribute("id", id);\r
+ elmPattern.setAttribute("name", defaultName);\r
root.appendChild(elmPattern);\r
\r
// ローカライズされた名前\r
- Element elmLocalizedName = doc.createElementNS(NS, "localized-name");\r
- elmLocalizedName.setAttribute("lang", lang);\r
- elmLocalizedName.setAttribute("name", name);\r
- elmPattern.appendChild(elmLocalizedName);\r
+ for (Map.Entry<String, String> localizedEntry : localizedNames.entrySet()) {\r
+ String localizedLang = localizedEntry.getKey();\r
+ String localizedName = localizedEntry.getValue();\r
+ if (!CustomLayerOrderKey.DEFAULT_NAME_KEY.equals(localizedLang)) {\r
+ Element elmLocalizedName = doc.createElementNS(NS, "localized-name");\r
+ elmLocalizedName.setAttribute("lang", localizedLang);\r
+ elmLocalizedName.setAttribute("name", localizedName);\r
+ elmPattern.appendChild(elmLocalizedName);\r
+ }\r
+ }\r
\r
// レイヤーマッピング\r
for (CustomLayerOrder order : orders) {\r
elmPattern.appendChild(elmMapping);\r
PartsCategory category = order.getCategory();\r
Layer layer = order.getLayer();\r
- int layerOrder = order.getLayerOrder();\r
+ float layerOrder = order.getLayerOrder();\r
\r
elmMapping.setAttribute("category", category.getCategoryId());\r
elmMapping.setAttribute("layer", layer.getId());\r
- elmMapping.setAttribute("order", Integer.toString(layerOrder));\r
+ elmMapping.setAttribute("order", Float.toString(layerOrder));\r
}\r
}\r
\r
* @param param カラー情報、設定されていない場合はnull\r
*/\r
void detectImageSource(PartsIdentifier partsIdentifier,\r
- Layer layer, int layerOrder, ImageResource imageResource,\r
+ Layer layer, float layerOrder, ImageResource imageResource,\r
ColorConvertParameter param);\r
}\r
\r
*/\r
public interface LayerOrderMapper {\r
\r
- int getLayerOrder(Layer layer);\r
+ float getLayerOrder(Layer layer);\r
}\r
\r
/**\r
PartsFiles partsFiles = partsSpec.getPartsFiles();\r
for (Map.Entry<Layer, ImageResource> entry : partsFiles.entrySet()) {\r
Layer layer = entry.getKey();\r
- int layerOrder = (layerOrderMapper != null) ? layerOrderMapper.getLayerOrder(layer)\r
- : layer.getOrder();\r
- if (layerOrder >= 0) { // レイヤー順が負の場合は画像を構成しない。\r
+ float layerOrder = (layerOrderMapper != null) ? layerOrderMapper.getLayerOrder(layer)\r
+ : (float) layer.getOrder();\r
+ if (!Float.isNaN(layerOrder)) { // NaN値の場合は非表示とする\r
ImageResource file = entry.getValue();\r
ColorConvertParameter param = null;\r
if (partsColorInfo != null) {\r
import java.io.IOException;\r
import java.io.InputStream;\r
import java.io.OutputStream;\r
+import java.net.URI;\r
+import java.util.Map;\r
import java.util.logging.Level;\r
import java.util.logging.Logger;\r
\r
import charactermanaj.model.CharacterData;\r
+import charactermanaj.model.IndependentPartsSetInfo;\r
+import charactermanaj.model.IndependentWorkingSet;\r
+import charactermanaj.model.PartsColorInfo;\r
+import charactermanaj.model.PartsIdentifier;\r
+import charactermanaj.model.PartsSet;\r
import charactermanaj.model.WorkingSet;\r
-import charactermanaj.model.WorkingSet2;\r
import charactermanaj.util.UserData;\r
import charactermanaj.util.UserDataFactory;\r
\r
/**\r
* ワーキングセットの保存と復元.<br>\r
- * \r
+ *\r
* @author seraphy\r
*/\r
public class WorkingSetPersist {\r
\r
/**\r
* ワーキングセットを削除する.\r
- * \r
+ *\r
* @param cd\r
* 対象のキャラクターデータ\r
*/\r
/**\r
* ワーキングセットを保存する.<br>\r
* ワーキングセットインスタンスには、あらかじめ全て設定しておく必要がある.<br>\r
- * \r
+ *\r
* @param workingSet\r
* ワーキングセット\r
* @throws IOException\r
\r
/**\r
* ワーキングセットを取得する.<br>\r
- * \r
+ *\r
* @param characterData\r
* 対象のキャラクターデータ\r
* @return ワーキングセット、なければnull\r
* @throws IOException\r
* 読み込みに失敗した場合\r
*/\r
- public WorkingSet2 loadWorkingSet(CharacterData characterData)\r
+ public WorkingSet loadWorkingSet(CharacterData characterData)\r
throws IOException {\r
if (characterData == null) {\r
throw new IllegalArgumentException();\r
// 保存されていない場合\r
return null;\r
}\r
- WorkingSet2 workingSet2;\r
+\r
+ // キャラクターデータと関連づけられていないワーキングセットデータを取得する\r
+ IndependentWorkingSet workingSet2;\r
\r
InputStream is = workingSetXmlData.openStream();\r
try {\r
is.close();\r
}\r
\r
- return workingSet2;\r
+ // 現在のキャラクターデータと照合する。\r
+ URI docBase = characterData.getDocBase();\r
+ if (docBase != null\r
+ && !docBase.equals(workingSet2.getCharacterDocBase())) {\r
+ // docBaseが一致せず\r
+ logger.log(Level.INFO, "docBase missmatch");\r
+ return null;\r
+ }\r
+ String sig = characterData.toSignatureString();\r
+ if (!sig.equals(workingSet2.getCharacterDataSig())) {\r
+ // 構造が一致せず.\r
+ logger.log(Level.INFO, "character data structure missmatch");\r
+ return null;\r
+ }\r
+\r
+ // 現在のキャラクターデータに関連づけられているワーキングセットとして転記する\r
+\r
+ WorkingSet ws = new WorkingSet();\r
+ ws.setCharacterData(characterData);\r
+ ws.setCharacterDataRev(characterData.getRev());\r
+ ws.setCharacterDocBase(docBase);\r
+\r
+ ws.setLastUsedExportDir(workingSet2.getLastUsedExportDir());\r
+ ws.setLastUsedSaveDir(workingSet2.getLastUsedSaveDir());\r
+\r
+ // パーツの色情報を復元する.\r
+ Map<PartsIdentifier, PartsColorInfo> partsColorInfoMap = characterData\r
+ .getPartsColorManager().getPartsColorInfoMap();\r
+ workingSet2.createCompatible(characterData, partsColorInfoMap);\r
+ ws.setPartsColorInfoMap(partsColorInfoMap);\r
+\r
+ // 選択されているパーツの復元\r
+ IndependentPartsSetInfo partsSetInfo = workingSet2.getCurrentPartsSet();\r
+ if (partsSetInfo != null) {\r
+ PartsSet partsSet = IndependentPartsSetInfo.convertPartsSet(\r
+ partsSetInfo, characterData, false);\r
+ ws.setCurrentPartsSet(partsSet);\r
+\r
+ // 最後に選択したお気に入り情報の復元\r
+ IndependentPartsSetInfo lastUsePresetPartsInfo = workingSet2\r
+ .getLastUsePresetParts();\r
+ if (lastUsePresetPartsInfo != null\r
+ && lastUsePresetPartsInfo.getId() != null\r
+ && lastUsePresetPartsInfo.getId().trim().length() > 0) {\r
+ PartsSet lastUsePresetParts = IndependentPartsSetInfo\r
+ .convertPartsSet(lastUsePresetPartsInfo,\r
+ characterData, false);\r
+ ws.setLastUsePresetParts(lastUsePresetParts);\r
+ }\r
+ }\r
+\r
+ ws.setWallpaperInfo(workingSet2.getWallpaperInfo());\r
+\r
+ ws.setViewPosition(workingSet2.getViewPosition());\r
+ ws.setWindowRect(workingSet2.getWindowRect());\r
+\r
+ return ws;\r
}\r
}\r
\r
import charactermanaj.model.IndependentPartsColorInfo;\r
import charactermanaj.model.IndependentPartsSetInfo;\r
-import charactermanaj.model.WorkingSet2;\r
+import charactermanaj.model.IndependentWorkingSet;\r
import charactermanaj.ui.model.WallpaperInfo;\r
import charactermanaj.ui.model.WallpaperInfo.WallpaperResourceType;\r
import charactermanaj.util.XMLUtilities;\r
* @throws IOException\r
* 読み取りに失敗\r
*/\r
- public WorkingSet2 loadWorkingSet(InputStream is)\r
+ public IndependentWorkingSet loadWorkingSet(InputStream is)\r
throws IOException {\r
if (is == null) {\r
throw new IllegalArgumentException();\r
}\r
\r
- WorkingSet2 workingSet = new WorkingSet2();\r
+ IndependentWorkingSet workingSet = new IndependentWorkingSet();\r
\r
CharacterDataXMLReader characterDataXMLReader = new CharacterDataXMLReader();\r
\r
break; // viewElmは最初の一要素しか想定しない.\r
}\r
\r
-\r
// 現在のパーツ情報\r
for (Element currentPartsSetsElm : getChildElements(docElm,\r
"currentPartsSet")) {\r
root.appendChild(writePartsColorInfoMap(doc, ws.getPartsColorInfoMap()));\r
\r
// 現在のパーツセット\r
- PartsSet currentPartsSet = ws.getPartsSet();\r
+ PartsSet currentPartsSet = ws.getCurrentPartsSet();\r
Element partsSetElm = doc.createElementNS(NS, "currentPartsSet");\r
if (currentPartsSet == null || currentPartsSet.isEmpty()) {\r
partsSetElm.setAttributeNS(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "xsi:nil", "true");\r
package charactermanaj.model.util;\r
\r
+import java.io.BufferedInputStream;\r
import java.io.File;\r
import java.io.FileFilter;\r
-import java.io.OutputStream;\r
+import java.io.FileInputStream;\r
+import java.io.InputStream;\r
import java.net.URI;\r
import java.util.logging.Level;\r
import java.util.logging.Logger;\r
\r
import charactermanaj.model.AppConfig;\r
-import charactermanaj.model.WorkingSet;\r
-import charactermanaj.model.io.WorkingSetPersist;\r
-import charactermanaj.model.io.WorkingSetXMLWriter;\r
-import charactermanaj.ui.RecentCharactersDir;\r
-import charactermanaj.util.FileUserData;\r
-import charactermanaj.util.UserData;\r
+import charactermanaj.model.IndependentWorkingSet;\r
+import charactermanaj.model.io.WorkingSetXMLReader;\r
import charactermanaj.util.UserDataFactory;\r
\r
\r
/**\r
* 開始前の事前準備するためのサポートクラス\r
- * \r
+ *\r
* @author seraphy\r
*/\r
public abstract class StartupSupport {\r
- \r
+\r
private static StartupSupport inst;\r
- \r
+\r
/**\r
* インスタンスを取得する.\r
- * \r
+ *\r
* @return シングルトンインスタンス\r
*/\r
public static synchronized StartupSupport getInstance() {\r
public void doStartup() {\r
StartupSupport[] startups = {\r
new PurgeOldLogs(),\r
- new ConvertRecentCharDirsSerToXmlProps(),\r
- new ConvertWorkingSetSerToXml(),\r
- new PurgeOldCaches(),\r
+ new PurgeOldWorkingSetXml(),\r
+ //new ConvertRecentCharDirsSerToXmlProps(),\r
+ //new ConvertWorkingSetSerToXml(),\r
+ //new PurgeOldCaches(),\r
};\r
for (StartupSupport startup : startups) {\r
logger.log(Level.FINE, "startup operation start. class="\r
}\r
return inst;\r
}\r
- \r
+\r
/**\r
* スタートアップ処理を実施します.\r
*/\r
}\r
\r
/**\r
- * シリアライズによるキャラクターディレクトリリストの保存をXML形式のPropertiesにアップグレードします。\r
- * \r
- * @author seraphy\r
- * \r
+ * 使われていないWorkingset.xmlを削除する\r
*/\r
-class ConvertRecentCharDirsSerToXmlProps extends StartupSupport {\r
- /**\r
- * ロガー\r
- */\r
+class PurgeOldWorkingSetXml extends StartupSupport {\r
+\r
private final Logger logger = Logger.getLogger(getClass().getName());\r
\r
@Override\r
public void doStartup() {\r
- // 旧形式(ver0.991以前)\r
- UserDataFactory factory = UserDataFactory.getInstance();\r
+ AppConfig appConfig = AppConfig.getInstance();\r
+ long purgeOldLogsMillSec = appConfig.getPurgeLogDays() * 24L * 3600L * 1000L;\r
+ if (purgeOldLogsMillSec <= 0) {\r
+ return;\r
+ }\r
\r
- final String FILENAME = "recent-characterdirs.ser";\r
- File prevFile = new File(factory.getSpecialDataDir(FILENAME), FILENAME);\r
+ final String XML_SUFFIX = "-workingset.xml";\r
\r
- try {\r
- if (prevFile.exists()) {\r
- FileUserData recentCharDirs = new FileUserData(prevFile);\r
- RecentCharactersDir obj = (RecentCharactersDir) recentCharDirs\r
- .load();\r
+ UserDataFactory userDataFactory = UserDataFactory.getInstance();\r
+ File dir = userDataFactory.getSpecialDataDir(XML_SUFFIX);\r
\r
- // 新しい形式で保存する.\r
- obj.saveRecents();\r
+ // ワーキングセットの掃除判定日時\r
+ // これよりも新しいものは実際に使われているかを問わず、削除判定しない。\r
+ final long expireDate = System.currentTimeMillis() - purgeOldLogsMillSec;\r
\r
- // 古いファイルを削除する\r
- prevFile.delete();\r
+ File[] xmls = dir.listFiles(new FileFilter() {\r
+ @Override\r
+ public boolean accept(File pathname) {\r
+ return pathname.isFile() && pathname.getName().endsWith(XML_SUFFIX)\r
+ && pathname.lastModified() < expireDate && pathname.length() > 0;\r
}\r
-\r
- } catch (Exception ex) {\r
- logger.log(Level.WARNING, FILENAME + " convert failed.", ex);\r
+ });\r
+ if (xmls == null) {\r
+ logger.log(Level.WARNING, "workingset-dir access failed.");\r
+ return;\r
}\r
- }\r
-}\r
\r
-/**\r
- * シリアライズによるキャラクターディレクトリリストの保存をXML形式のPropertiesにアップグレードします。\r
- * \r
- * @author seraphy\r
- * \r
- */\r
-class ConvertWorkingSetSerToXml extends StartupSupport {\r
- /**\r
- * ロガー\r
- */\r
- private final Logger logger = Logger.getLogger(getClass().getName());\r
-\r
- @Override\r
- public void doStartup() {\r
- final String FILENAME = "workingset.ser";\r
- try {\r
- UserDataFactory userDataFactory = UserDataFactory.getInstance();\r
- File dir = userDataFactory.getSpecialDataDir(FILENAME);\r
- if (!dir.exists()) {\r
- return;\r
- }\r
- File[] files = dir.listFiles(new FileFilter() {\r
- public boolean accept(File pathname) {\r
- String name = pathname.getName();\r
- return name.endsWith(FILENAME);\r
+ for (File xmlFile : xmls) {\r
+ try {\r
+ WorkingSetXMLReader reader = new WorkingSetXMLReader();\r
+ IndependentWorkingSet ws;\r
+ InputStream is = new BufferedInputStream(new FileInputStream(xmlFile));\r
+ try {\r
+ ws = reader.loadWorkingSet(is);\r
+ } finally {\r
+ is.close();\r
}\r
- });\r
- if (files == null) {\r
- logger.log(Level.WARNING, "cache-dir access failed. " + dir);\r
- return;\r
- }\r
- WorkingSetXMLWriter wr = new WorkingSetXMLWriter();\r
- for (File file : files) {\r
- FileUserData fileData = new FileUserData(file);\r
- if (fileData.exists()) {\r
- try {\r
- // serファイルをデシリアライズする.\r
- WorkingSet ws = (WorkingSet) fileData.load();\r
- URI docBase = ws.getCharacterDocBase();\r
- if (docBase != null) {\r
- // XML形式で保存しなおす.\r
- UserData workingSetXmlData = userDataFactory\r
- .getMangledNamedUserData(docBase,\r
- WorkingSetPersist.WORKINGSET_FILE_SUFFIX);\r
- if (!workingSetXmlData.exists()) {\r
- // XML形式データがまだない場合のみ保存しなおす.\r
- OutputStream outstm = workingSetXmlData\r
- .getOutputStream();\r
- try {\r
- wr.writeWorkingSet(ws, outstm);\r
- } finally {\r
- outstm.close();\r
- }\r
- }\r
- }\r
\r
- // serファイルは削除する.\r
- fileData.delete();\r
-\r
- } catch (Exception ex) {\r
- logger.log(Level.WARNING,\r
- FILENAME + " convert failed.", ex);\r
+ URI docBase = ws.getCharacterDocBase();\r
+ if (docBase.getScheme().equals("file")) {\r
+ File characterXml = new File(docBase);\r
+ if (!characterXml.exists()) {\r
+ // キャラクター定義XMLが存在しない = 削除されたキャラクターデータ\r
+ logger.log(Level.INFO, "remove amandone workingset: " + xmlFile + ", docBase=" + docBase);\r
+ xmlFile.delete();\r
+ } else {\r
+ // チェック済みであることを示すためにXMLの更新日時を現在時刻にする\r
+ xmlFile.setLastModified(System.currentTimeMillis());\r
}\r
}\r
- }\r
\r
- } catch (Exception ex) {\r
- logger.log(Level.WARNING, FILENAME + " convert failed.", ex);\r
+ } catch (Exception ex) {\r
+ logger.log(Level.WARNING, "file access failed. " + xmlFile, ex);\r
+ }\r
}\r
}\r
}\r
\r
+// ver0.999で廃止。\r
+///**\r
+// * シリアライズによるキャラクターディレクトリリストの保存をXML形式のPropertiesにアップグレードします。\r
+// *\r
+// * @author seraphy\r
+// *\r
+// */\r
+//class ConvertRecentCharDirsSerToXmlProps extends StartupSupport {\r
+// /**\r
+// * ロガー\r
+// */\r
+// private final Logger logger = Logger.getLogger(getClass().getName());\r
+//\r
+// @Override\r
+// public void doStartup() {\r
+// // 旧形式(ver0.991以前)\r
+// UserDataFactory factory = UserDataFactory.getInstance();\r
+//\r
+// final String FILENAME = "recent-characterdirs.ser";\r
+// File prevFile = new File(factory.getSpecialDataDir(FILENAME), FILENAME);\r
+//\r
+// try {\r
+// if (prevFile.exists()) {\r
+// FileUserData recentCharDirs = new FileUserData(prevFile);\r
+// RecentCharactersDir obj = (RecentCharactersDir) recentCharDirs\r
+// .load();\r
+//\r
+// // 新しい形式で保存する.\r
+// obj.saveRecents();\r
+//\r
+// // 古いファイルを削除する\r
+// prevFile.delete();\r
+// }\r
+//\r
+// } catch (Exception ex) {\r
+// logger.log(Level.WARNING, FILENAME + " convert failed.", ex);\r
+// }\r
+// }\r
+//}\r
+\r
+//ver0.999で廃止。\r
+///**\r
+// * シリアライズによるキャラクターディレクトリリストの保存をXML形式のPropertiesにアップグレードします。\r
+// *\r
+// * @author seraphy\r
+// *\r
+// */\r
+//class ConvertWorkingSetSerToXml extends StartupSupport {\r
+// /**\r
+// * ロガー\r
+// */\r
+// private final Logger logger = Logger.getLogger(getClass().getName());\r
+//\r
+// @Override\r
+// public void doStartup() {\r
+// final String FILENAME = "workingset.ser";\r
+// try {\r
+// UserDataFactory userDataFactory = UserDataFactory.getInstance();\r
+// File dir = userDataFactory.getSpecialDataDir(FILENAME);\r
+// if (!dir.exists()) {\r
+// return;\r
+// }\r
+// File[] files = dir.listFiles(new FileFilter() {\r
+// public boolean accept(File pathname) {\r
+// String name = pathname.getName();\r
+// return name.endsWith(FILENAME);\r
+// }\r
+// });\r
+// if (files == null) {\r
+// logger.log(Level.WARNING, "cache-dir access failed. " + dir);\r
+// return;\r
+// }\r
+// WorkingSetXMLWriter wr = new WorkingSetXMLWriter();\r
+// for (File file : files) {\r
+// FileUserData fileData = new FileUserData(file);\r
+// if (fileData.exists()) {\r
+// try {\r
+// // serファイルをデシリアライズする.\r
+// WorkingSet ws = (WorkingSet) fileData.load();\r
+// URI docBase = ws.getCharacterDocBase();\r
+// if (docBase != null) {\r
+// // XML形式で保存しなおす.\r
+// UserData workingSetXmlData = userDataFactory\r
+// .getMangledNamedUserData(docBase,\r
+// WorkingSetPersist.WORKINGSET_FILE_SUFFIX);\r
+// if (!workingSetXmlData.exists()) {\r
+// // XML形式データがまだない場合のみ保存しなおす.\r
+// OutputStream outstm = workingSetXmlData\r
+// .getOutputStream();\r
+// try {\r
+// wr.writeWorkingSet(ws, outstm);\r
+// } finally {\r
+// outstm.close();\r
+// }\r
+// }\r
+// }\r
+//\r
+// // serファイルは削除する.\r
+// fileData.delete();\r
+//\r
+// } catch (Exception ex) {\r
+// logger.log(Level.WARNING,\r
+// FILENAME + " convert failed.", ex);\r
+// }\r
+// }\r
+// }\r
+//\r
+// } catch (Exception ex) {\r
+// logger.log(Level.WARNING, FILENAME + " convert failed.", ex);\r
+// }\r
+// }\r
+//}\r
+\r
/**\r
* 古いログファイルを消去する.\r
- * \r
+ *\r
* @author seraphy\r
*/\r
class PurgeOldLogs extends StartupSupport {\r
}\r
}\r
\r
-/**\r
- * 古いキャッシュファイルを消去する.<br>\r
- * -character.xml-cache.ser, -favorites.serは、直接xmlでの読み込みになったため、 ただちに消去しても問題ない.<br>\r
- * recent-character.serは、使用されなくなったため、ただちに消去して良い.<br>\r
- * mangled_info.xmlは、*.serを消去したあとには不要となるため、消去する.<br>\r
- * (今後使われることはない)\r
- * \r
- * @author seraphy\r
- */\r
-class PurgeOldCaches extends StartupSupport {\r
-\r
- /**\r
- * ロガー\r
- */\r
- private final Logger logger = Logger.getLogger(getClass().getName());\r
-\r
- @Override\r
- public void doStartup() {\r
- UserDataFactory userDataFactory = UserDataFactory.getInstance();\r
- File cacheDir = userDataFactory.getSpecialDataDir(".ser");\r
- if (cacheDir.exists()) {\r
- File[] files = cacheDir.listFiles();\r
- if (files == null) {\r
- logger.log(Level.WARNING, "cache-dir access failed.");\r
- return;\r
- }\r
- for (File file : files) {\r
- try {\r
- if (!file.isFile() || !file.canWrite()) {\r
- // ファイルでないか、書き込み不可の場合はスキップする.\r
- continue;\r
- }\r
- String name = file.getName();\r
- if (name.endsWith("-character.xml-cache.ser")\r
- || name.endsWith("-favorites.ser")\r
- || name.equals("recent-character.ser")\r
- || name.equals("mangled_info.xml")) {\r
- boolean result = file.delete();\r
- logger.log(Level.INFO, "remove file " + file\r
- + "/succeeded=" + result);\r
- }\r
-\r
- } catch (Exception ex) {\r
- logger.log(Level.WARNING, "remove file failed. " + file, ex);\r
- }\r
- }\r
- }\r
- }\r
-}\r
+//ver0.999で廃止。\r
+///**\r
+// * 古いキャッシュファイルを消去する.<br>\r
+// * -character.xml-cache.ser, -favorites.serは、直接xmlでの読み込みになったため、 ただちに消去しても問題ない.<br>\r
+// * recent-character.serは、使用されなくなったため、ただちに消去して良い.<br>\r
+// * mangled_info.xmlは、*.serを消去したあとには不要となるため、消去する.<br>\r
+// * (今後使われることはない)\r
+// *\r
+// * @author seraphy\r
+// */\r
+//class PurgeOldCaches extends StartupSupport {\r
+//\r
+// /**\r
+// * ロガー\r
+// */\r
+// private final Logger logger = Logger.getLogger(getClass().getName());\r
+//\r
+// @Override\r
+// public void doStartup() {\r
+// UserDataFactory userDataFactory = UserDataFactory.getInstance();\r
+// File cacheDir = userDataFactory.getSpecialDataDir(".ser");\r
+// if (cacheDir.exists()) {\r
+// File[] files = cacheDir.listFiles();\r
+// if (files == null) {\r
+// logger.log(Level.WARNING, "cache-dir access failed.");\r
+// return;\r
+// }\r
+// for (File file : files) {\r
+// try {\r
+// if (!file.isFile() || !file.canWrite()) {\r
+// // ファイルでないか、書き込み不可の場合はスキップする.\r
+// continue;\r
+// }\r
+// String name = file.getName();\r
+// if (name.endsWith("-character.xml-cache.ser")\r
+// || name.endsWith("-favorites.ser")\r
+// || name.equals("recent-character.ser")\r
+// || name.equals("mangled_info.xml")) {\r
+// boolean result = file.delete();\r
+// logger.log(Level.INFO, "remove file " + file\r
+// + "/succeeded=" + result);\r
+// }\r
+//\r
+// } catch (Exception ex) {\r
+// logger.log(Level.WARNING, "remove file failed. " + file, ex);\r
+// }\r
+// }\r
+// }\r
+// }\r
+//}\r
import java.awt.event.KeyEvent;\r
import java.awt.event.MouseAdapter;\r
import java.awt.event.MouseEvent;\r
-import java.io.Serializable;\r
import java.util.ArrayList;\r
import java.util.Arrays;\r
import java.util.Collection;\r
public class ImageSelectPanel extends JPanel {\r
\r
private static final long serialVersionUID = 1L;\r
- \r
+\r
protected static final String STRINGS_RESOURCE = "languages/imageselectpanel";\r
- \r
+\r
\r
/**\r
* 変更通知を受けるリスナ\r
* @param event\r
*/\r
void onSelectChange(ImageSelectPanelEvent event);\r
- \r
+\r
/**\r
* アイテムが選択された場合\r
* @param event\r
*/\r
void onChange(ImageSelectPanelEvent event);\r
- \r
+\r
/**\r
* 色変更ボタンが押された場合\r
* @param event\r
*/\r
void onChangeColor(ImageSelectPanelEvent event);\r
- \r
+\r
/**\r
* 設定ボタンが押された場合\r
* @param event\r
*/\r
void onPreferences(ImageSelectPanelEvent event);\r
- \r
+\r
/**\r
* タイトルがクリックされた場合\r
* @param event\r
void onTitleDblClick(ImageSelectPanelEvent event);\r
};\r
\r
- \r
+\r
/**\r
* 変更通知イベント\r
* @author seraphy\r
*/\r
public static class ImageSelectPanelEvent extends EventObject {\r
- \r
+\r
private static final long serialVersionUID = 1L;\r
- \r
+\r
public ImageSelectPanelEvent(ImageSelectPanel src) {\r
super(src);\r
}\r
- \r
+\r
public ImageSelectPanel getImageSelectPanel() {\r
return (ImageSelectPanel) getSource();\r
}\r
* 通常モード\r
*/\r
NORMAL,\r
- \r
+\r
/**\r
* 最大サイズフリーモード\r
*/\r
EXPANDED\r
}\r
- \r
+\r
/**\r
* パネルノ拡大・縮小時のステップサイズ\r
*/\r
* 変更通知を受けるリスナー\r
*/\r
private final LinkedList<ImageSelectPanelListener> listeners = new LinkedList<ImageSelectPanelListener>();\r
- \r
+\r
/**\r
* リストの一行の高さ\r
*/\r
private final int rowHeight;\r
- \r
+\r
/**\r
* パネルの最小高さ (ボーダー上限 + ヘッダ行の高さ)\r
*/\r
private final int minHeight;\r
- \r
+\r
/**\r
* 現在の表示行数\r
*/\r
private int numOfVisibleRows;\r
- \r
+\r
/**\r
* 最小化モードであるか?\r
*/\r
private DisplayMode displayMode;\r
- \r
+\r
/**\r
* パーツ情報ソース\r
*/\r
private PartsSpecResolver partsSpecResolver;\r
- \r
+\r
/**\r
* パーツ選択テーブル\r
*/\r
private final JTable partsSelectTable;\r
- \r
+\r
/**\r
* パーツ選択テーブルモデル\r
*/\r
private final PartsSelectListModel partsSelectTableModel;\r
- \r
+\r
/**\r
* 選択中のアイテム(複数選択の場合はフォーカスされているもの)、もしくはnull\r
*/\r
private PartsIdentifier selectedPartsIdentifier;\r
- \r
+\r
/**\r
* 選択中のアイテムのリスト(順序あり)、もしくは空\r
*/\r
private List<PartsIdentifier> selectedPartsIdentifiers = Collections.emptyList();\r
- \r
+\r
/**\r
* このパネルが対象とするカテゴリ情報\r
*/\r
private final PartsCategory partsCategory;\r
- \r
+\r
\r
/**\r
* イメージ選択パネルを構築する\r
this.partsSpecResolver = partsSpecResolver;\r
\r
setLayout(new BorderLayout());\r
- \r
+\r
setBorder(BorderFactory.createCompoundBorder(\r
BorderFactory.createEmptyBorder(3, 3, 3, 3),\r
BorderFactory.createCompoundBorder(\r
});\r
\r
AppConfig appConfig = AppConfig.getInstance();\r
- \r
+\r
final Properties strings = LocalizedResourcePropertyLoader.getCachedInstance()\r
.getLocalizedProperties(STRINGS_RESOURCE);\r
- \r
+\r
final Color selectedItemColor = appConfig.getCheckedItemBgColor();\r
- \r
+\r
partsSelectTable = new JTable(partsSelectTableModel, columnModel, selectionModel) {\r
private static final long serialVersionUID = 1L;\r
@Override\r
}\r
};\r
partsSelectTablePopupMenu.add(actDeselectAll);\r
- \r
+\r
partsSelectTable.addMouseListener(new MouseAdapter() {\r
@Override\r
public void mousePressed(MouseEvent e) {\r
}\r
}\r
});\r
- \r
+\r
partsSelectTableModel.addTableModelListener(new TableModelListener() {\r
public void tableChanged(TableModelEvent e) {\r
if (e.getType() == TableModelEvent.UPDATE) {\r
partsSelectTableModel.setChecks(false, partsSelectTable.getSelectedRows());\r
}\r
});\r
- \r
+\r
JScrollPane scrollPane = new JScrollPane(partsSelectTable);\r
scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);\r
- \r
+\r
UIHelper uiUtl = UIHelper.getInstance();\r
JButton leftBtn = uiUtl.createTransparentButton("icons/left.png", "icons/left2.png");\r
JButton rightBtn = uiUtl.createTransparentButton("icons/right.png", "icons/right2.png");\r
rightBtn.setToolTipText(strings.getProperty("tooltip.expand"));\r
colorBtn.setToolTipText(strings.getProperty("tooltip.color"));\r
configBtn.setToolTipText(strings.getProperty("tooltip.config"));\r
- \r
+\r
leftBtn.addActionListener(new ActionListener() {\r
public void actionPerformed(ActionEvent e) {\r
if (isMinimizeMode()) {\r
onPreferences();\r
}\r
});\r
- \r
- \r
+\r
+\r
JPanel btnPanelGrp = new JPanel(new BorderLayout());\r
\r
JToolBar toolBar = new JToolBar();\r
upBtn.setToolTipText(strings.getProperty("tooltip.up"));\r
downBtn.setToolTipText(strings.getProperty("tooltip.down"));\r
sortBtn.setToolTipText(strings.getProperty("tooltip.sort"));\r
- \r
+\r
upBtn.addActionListener(new ActionListener() {\r
public void actionPerformed(ActionEvent e) {\r
onUp();\r
onSort();\r
}\r
});\r
- \r
+\r
JToolBar toolBar2 = new JToolBar();\r
toolBar2.setFloatable(false);\r
toolBar2.add(upBtn);\r
toolBar2.add(sortBtn);\r
btnPanelGrp.add(toolBar2, BorderLayout.SOUTH);\r
}\r
- \r
+\r
JPanel header = new JPanel(new BorderLayout());\r
header.add(btnPanelGrp, BorderLayout.EAST);\r
final JLabel title = new JLabel(" " + partsCategory.getLocalizedCategoryName() + " ");\r
title.setFont(font.deriveFont(Font.BOLD));\r
final Color defaultTitleColor = title.getForeground();\r
final Color hilightColor = appConfig.getSelectPanelTitleColor();\r
- \r
+\r
title.addMouseListener(new MouseAdapter() {\r
@Override\r
public void mousePressed(MouseEvent e) {\r
title.setForeground(defaultTitleColor);\r
}\r
});\r
- \r
+\r
header.add(title, BorderLayout.CENTER);\r
- \r
+\r
add(header, BorderLayout.NORTH);\r
add(scrollPane, BorderLayout.CENTER);\r
\r
rowHeight = partsSelectTable.getRowHeight();\r
- \r
+\r
// パネルの最小高さ (ボーダー上下 + ヘッダ行高さ)\r
Insets insets = getInsets();\r
minHeight = header.getPreferredSize().height + insets.top + insets.bottom;\r
- \r
+\r
// デフォルトのパネル幅を設定する.\r
Dimension dim = new Dimension(200, 200);\r
setPreferredSize(dim);\r
numOfVisibleRows = partsCategory.getVisibleRows();\r
setDisplayMode(DisplayMode.NORMAL);\r
}\r
- \r
+\r
/**\r
* 表示行数から推奨のパネル高さを求める.<br>\r
* パネル高さは1行の高さ x 表示行数 + ヘッダ + ボーダー上下である.<br>\r
protected int calcPreferredHeight(int numOfVisibleRows) {\r
return minHeight + Math.max(0, rowHeight * numOfVisibleRows);\r
}\r
- \r
+\r
/**\r
* パーツをパネルにロードします.<br>\r
* 既存の内容はリセットされたのち、現在の選択パーツ位置にスクロールします.<br>\r
partsSelectTableModel.load(partsSpecResolver.getPartsSpecMap(partsCategory).keySet());\r
scrollToSelectedRow();\r
}\r
- \r
+\r
/**\r
* このイメージ選択パネルの該当カテゴリを返します.<br>\r
* @return カテゴリ\r
// アイテムの選択が変更されたことを通知する.\r
onChange(new ImageSelectPanelEvent(ImageSelectPanel.this));\r
}\r
- \r
+\r
/**\r
* カテゴリのリストでパーツを選択しなおします.<br>\r
* 変更イベントは発生しません.<br>\r
\r
ArrayList<PartsIdentifier> partsIdentifiersBuf = new ArrayList<PartsIdentifier>(partsIdentifiers);\r
Collections.reverse(partsIdentifiersBuf);\r
- \r
+\r
for (PartsIdentifier partsIdentifier : partsIdentifiersBuf) {\r
Iterator<PartsSelectRow> ite = rowModels.iterator();\r
while (ite.hasNext()) {\r
}\r
}\r
}\r
- \r
+\r
// 選択を保存する\r
selectedPartsIdentifier = getSelectedPartsIdentifier();\r
selectedPartsIdentifiers = getSelectedPartsIdentifiers();\r
- \r
+\r
// コンポーネントではなく、モデルに対する直接変更であるため、イベントは発生しません.\r
// そのため再描画させる必要があります.\r
partsSelectTable.repaint();\r
- \r
+\r
// あたらしく選択されたアイテムが表示されるようにスクロールします.\r
scrollToSelectedRow();\r
}\r
- \r
+\r
/**\r
* カテゴリのリストで選択中のアイテムが見えるようにスクロールする.\r
*/\r
setPreferredSize(siz);\r
setMinimumSize(siz);\r
setMaximumSize(sizMax);\r
- \r
+\r
this.displayMode = displayMode;\r
revalidate();\r
}\r
- \r
+\r
public DisplayMode getDisplayMode() {\r
return displayMode;\r
}\r
- \r
+\r
public boolean isMinimizeMode() {\r
return displayMode == DisplayMode.MINIMIZED;\r
}\r
- \r
+\r
/**\r
* カテゴリのパネルを縮小する.<br>\r
* ただし、ヘッダ部よりは小さくならない.<br>\r
// 通常モードの適用\r
setDisplayMode(DisplayMode.NORMAL);\r
}\r
- \r
+\r
public void addImageSelectListener(ImageSelectPanelListener listener) {\r
if (listener == null) {\r
throw new IllegalArgumentException();\r
}\r
listeners.add(listener);\r
}\r
- \r
+\r
public void removeImageSelectListener(ImageSelectPanelListener listener) {\r
listeners.remove(listener);\r
}\r
- \r
+\r
public void requestListFocus() {\r
partsSelectTable.requestFocus();\r
}\r
}\r
}\r
}\r
- \r
+\r
/**\r
* フォーカスのあるアイテムを1つ上に移動します.\r
*/\r
partsSelectTable.repaint();\r
partsSelectTable.requestFocus();\r
}\r
- \r
+\r
/**\r
* 選択中のアイテムを選択順序を維持したまま上側に、それ以外は名前順で下側に集めるようにソートします.<br>\r
*/\r
listener.onTitleClick(event);\r
}\r
}\r
- \r
+\r
/**\r
* タイトルがダブルクリックされた場合\r
*/\r
listener.onTitleDblClick(event);\r
}\r
}\r
- \r
+\r
/**\r
* カラー変更ボタンが押下された場合\r
* @param event\r
onSelectChange(event);\r
}\r
}\r
- \r
+\r
/**\r
* アイテムの選択(フォーカス)が変更された場合.\r
* @param event\r
}\r
}\r
}\r
- \r
+\r
/**\r
* 使用中のアイテムの一覧を返す.(選択順)<br>\r
* @return 使用中のアイテムの一覧.(選択順)、ひとつもなければ空\r
public List<PartsIdentifier> getSelectedPartsIdentifiers() {\r
return partsSelectTableModel.getSelectedPartsIdentifiers();\r
}\r
- \r
+\r
/**\r
* 使用中のアイテムを返す.<br>\r
* 複数選択可能である場合は、使用中のアイテムでフォーカスがある最初のアイテムを返す.<br>\r
* @return 使用中アイテム、もしくはnull\r
*/\r
public PartsIdentifier getSelectedPartsIdentifier() {\r
- \r
+\r
// フォーカスがあたっていて、且つ、チェック状態のアイテムを上から順に走査し、\r
// 該当があれば、最初のものを返す.\r
int[] selRows = partsSelectTable.getSelectedRows();\r
// 該当なし\r
return null;\r
}\r
- \r
+\r
/**\r
* 選択選択パーツカテゴリの選択解除を許可するか?<br>\r
* @return 許可する場合はtrue\r
public boolean isDeselectableSingleCategory() {\r
return partsSelectTableModel.isDeselectableSingleCategory();\r
}\r
- \r
+\r
/**\r
* 選択選択パーツカテゴリの選択解除を許可するか設定する.<br>\r
* @param deselectable 許可する場合はtrue\r
* パーツデータ、表示名と使用中フラグを管理する.\r
* @author seraphy\r
*/\r
-final class PartsSelectRow implements Serializable, Comparable<PartsSelectRow> {\r
- \r
- private static final long serialVersionUID = 5732273802364827L;\r
+final class PartsSelectRow implements Comparable<PartsSelectRow> {\r
\r
private PartsIdentifier partsIdentifier;\r
- \r
+\r
private boolean checked;\r
- \r
+\r
private int displayOrder;\r
- \r
+\r
public PartsSelectRow(final PartsIdentifier partsIdentifier, final boolean checked) {\r
this.partsIdentifier = partsIdentifier;\r
this.checked = checked;\r
}\r
- \r
+\r
/**\r
* 選択されているものを上、そうでないものを下に振り分ける。\r
* 選択されているもの同士、選択されていないもの同士は、互いのディスプレイ順でソートされる.<br>\r
}\r
return ret;\r
}\r
- \r
+\r
public void setDisplayOrder(int displayOrder) {\r
this.displayOrder = displayOrder;\r
}\r
- \r
+\r
public int getDisplayOrder() {\r
return this.displayOrder;\r
}\r
- \r
+\r
@Override\r
public boolean equals(Object obj) {\r
if (obj == this) {\r
}\r
return false;\r
}\r
- \r
+\r
public int hashCode() {\r
return partsIdentifier.hashCode();\r
}\r
- \r
+\r
public PartsIdentifier getPartsIdentifier() {\r
return partsIdentifier;\r
}\r
- \r
+\r
/**\r
* {@link PartsIdentifier#getLocalizedPartsName()}に委譲します.\r
* @return パーツ名\r
public String getPartsName() {\r
return partsIdentifier.getLocalizedPartsName();\r
}\r
- \r
+\r
public boolean isChecked() {\r
return checked;\r
}\r
- \r
+\r
public void setChecked(boolean checked) {\r
this.checked = checked;\r
}\r
private static final long serialVersionUID = 7604828023134579608L;\r
\r
private PartsCategory partsCategory;\r
- \r
- private ArrayList<PartsSelectRow> partsSelectRowList; \r
+\r
+ private ArrayList<PartsSelectRow> partsSelectRowList;\r
\r
/**\r
* カテゴリが複数パーツでない場合でも選択解除を許可するフラグ.\r
this.partsSelectRowList = new ArrayList<PartsSelectRow>();\r
this.partsCategory = partsCategory;\r
}\r
- \r
+\r
public void load(Collection<PartsIdentifier> partsIdentifiers) {\r
if (partsIdentifiers == null) {\r
throw new IllegalArgumentException();\r
}\r
- \r
+\r
// 現在選択されているパーツを保存する\r
HashMap<PartsIdentifier, Integer> selectedPartsIdentifiers = new HashMap<PartsIdentifier, Integer>();\r
for (PartsIdentifier partsIdentifier : getSelectedPartsIdentifiers()) {\r
selectedPartsIdentifiers.put(partsIdentifier, selectedPartsIdentifiers.size());\r
}\r
- \r
+\r
// パーツイメージマップからパーツ名を列挙する.\r
ArrayList<PartsSelectRow> partsSelectList = new ArrayList<PartsSelectRow>();\r
for (PartsIdentifier partsIdentifier : partsIdentifiers) {\r
this.partsSelectRowList = partsSelectList;\r
fireTableDataChanged();\r
}\r
- \r
+\r
/**\r
* 選択選択パーツカテゴリの選択解除を許可するか?<br>\r
* @return 許可する場合はtrue\r
public boolean isDeselectableSingleCategory() {\r
return deselectableSingleCategory;\r
}\r
- \r
+\r
/**\r
* 選択選択パーツカテゴリの選択解除を許可するか設定する.<br>\r
* @param deselectable 許可する場合はtrue\r
public PartsSelectRow getRow(int rowIndex) {\r
return partsSelectRowList.get(rowIndex);\r
}\r
- \r
+\r
public ArrayList<PartsSelectRow> getRowModelList() {\r
return this.partsSelectRowList;\r
}\r
- \r
+\r
public int getColumnCount() {\r
// ヘッダは非表示のためヘッダ名は取得する必要なし.\r
// col 0: 選択ボックス\r
// col 1: パーツ表示名\r
return 2;\r
}\r
- \r
+\r
public int getRowCount() {\r
return partsSelectRowList.size();\r
}\r
- \r
+\r
public Object getValueAt(int rowIndex, int columnIndex) {\r
PartsSelectRow rowModel = partsSelectRowList.get(rowIndex);\r
switch (columnIndex) {\r
}\r
return "";\r
}\r
- \r
+\r
@Override\r
public Class<?> getColumnClass(int columnIndex) {\r
switch (columnIndex) {\r
}\r
return String.class;\r
}\r
- \r
+\r
@Override\r
public boolean isCellEditable(int rowIndex, int columnIndex) {\r
if (columnIndex == 0) {\r
}\r
return false;\r
}\r
- \r
+\r
@Override\r
public void setValueAt(Object aValue, int rowIndex, int columnIndex) {\r
if (columnIndex != 0) {\r
}\r
PartsSelectRow rowModel = partsSelectRowList.get(rowIndex);\r
boolean checked = ((Boolean) aValue).booleanValue();\r
- \r
+\r
if (!checked && rowModel.isChecked() && !deselectableSingleCategory\r
&& !partsCategory.isMultipleSelectable()) {\r
// 複数選択が可能でない場合、現在選択中のチェックは一つしかないはずのため、これを外すことはしない。\r
// ただし単一選択パーツカテゴリでの選択解除が許可されている場合を除く。\r
return;\r
}\r
- \r
+\r
rowModel.setChecked(checked);\r
\r
// カテゴリが複数パーツ選択を許可しておらず、且つ、チェックをつけた場合、\r
fireTableDataChanged();\r
}\r
}\r
- \r
+\r
/**\r
* 選択されているパーツを上に、それ以外を下に振り分ける.<br>\r
* それぞれはパーツの表示名順でソートされる.<br>\r
Collections.sort(partsSelectRowList);\r
fireTableDataChanged();\r
}\r
- \r
+\r
/**\r
* チェックされているパーツのパーツ識別子のリストを返す.<br>\r
* リストの順序はパーツの表示されている順序と等しい.<br>\r
}\r
return selectedRows;\r
}\r
- \r
+\r
/**\r
* 指定したインデックスのパーツのチェック状態を返す.\r
* @param rowIndexes 調べるインデックスの配列\r
}\r
return results;\r
}\r
- \r
+\r
/**\r
* 指定したインデックスのチェック状態を設定する.\r
* @param checked チェックする場合はtrue、チェックを解除する場合はfalse\r
import java.awt.image.BufferedImage;\r
import java.io.File;\r
import java.io.IOException;\r
-import java.io.Serializable;\r
import java.net.URI;\r
import java.sql.Timestamp;\r
import java.text.MessageFormat;\r
\r
/**\r
* インポートウィザードダイアログ.<br>\r
- * \r
+ *\r
* @author seraphy\r
*/\r
public class ImportWizardDialog extends JDialog {\r
\r
private static final long serialVersionUID = 1L;\r
- \r
- \r
+\r
+\r
protected static final String STRINGS_RESOURCE = "languages/importwizdialog";\r
- \r
+\r
\r
public static final int EXIT_PROFILE_UPDATED = 1;\r
- \r
+\r
public static final int EXIT_PROFILE_CREATED = 2;\r
- \r
+\r
public static final int EXIT_CANCELED = 0;\r
\r
- \r
+\r
/**\r
* インポートウィザードの実行結果.<br>\r
*/\r
private int exitCode = EXIT_CANCELED;\r
- \r
+\r
/**\r
* インポートされたキャラクターデータ.<br>\r
*/\r
* 新規の場合はnull\r
*/\r
protected CharacterData current;\r
- \r
- \r
+\r
+\r
private CardLayout mainPanelLayout;\r
\r
private ImportWizardCardPanel activePanel;\r
\r
private AbstractAction actNext;\r
- \r
+\r
private AbstractAction actPrev;\r
\r
private AbstractAction actFinish;\r
- \r
+\r
\r
protected ImportFileSelectPanel importFileSelectPanel;\r
- \r
+\r
protected ImportTypeSelectPanel importTypeSelectPanel;\r
- \r
+\r
protected ImportPartsSelectPanel importPartsSelectPanel;\r
- \r
+\r
protected ImportPresetSelectPanel importPresetSelectPanel;\r
\r
protected ImportModel importModel = new ImportModel();\r
- \r
+\r
/**\r
* プロファイルにパーツデータ・プリセットデータをインポートします.<br>\r
- * \r
+ *\r
* @param parent\r
* 親フレーム\r
* @param current\r
\r
importFileSelectPanel.setSelectFile(initFiles);\r
}\r
- \r
+\r
/**\r
* プロファイルにパーツデータ・プリセットデータをインポートします.<br>\r
- * \r
+ *\r
* @param parent\r
* 親ダイアログ\r
* @param current\r
super(parent, true);\r
initComponent(parent, current);\r
}\r
- \r
+\r
/**\r
* ウィザードダイアログのコンポーネントを初期化します.<br>\r
* currentがnullの場合は新規インポート、そうでない場合は更新インポートとります。\r
- * \r
+ *\r
* @param parent\r
* 親コンテナ\r
* @param current\r
onClose();\r
}\r
});\r
- \r
+\r
Properties strings = LocalizedResourcePropertyLoader.getCachedInstance()\r
.getLocalizedProperties(STRINGS_RESOURCE);\r
\r
}\r
\r
// メインパネル\r
- \r
+\r
Container contentPane = getContentPane();\r
contentPane.setLayout(new BorderLayout());\r
\r
this.mainPanelLayout = new CardLayout(5, 5);\r
mainPanel.setLayout(mainPanelLayout);\r
contentPane.add(mainPanel, BorderLayout.CENTER);\r
- \r
+\r
ChangeListener changeListener = new ChangeListener() {\r
public void stateChanged(ChangeEvent e) {\r
updateBtnPanelState();\r
}\r
};\r
- \r
+\r
ComponentListener componentListener = new ComponentAdapter() {\r
public void componentShown(ComponentEvent e) {\r
onComponentShown((ImportWizardCardPanel) e.getComponent());\r
}\r
};\r
\r
- \r
+\r
// アクション\r
- \r
+\r
this.actNext = new AbstractAction(strings.getProperty("btn.next")) {\r
private static final long serialVersionUID = 1L;\r
public void actionPerformed(ActionEvent e) {\r
this.importFileSelectPanel.addComponentListener(componentListener);\r
this.importFileSelectPanel.addChangeListener(changeListener);\r
mainPanel.add(this.importFileSelectPanel, ImportFileSelectPanel.PANEL_NAME);\r
- \r
+\r
// ImportTypeSelectPanel\r
this.importTypeSelectPanel = new ImportTypeSelectPanel();\r
this.importTypeSelectPanel.addComponentListener(componentListener);\r
this.importTypeSelectPanel.addChangeListener(changeListener);\r
mainPanel.add(this.importTypeSelectPanel, ImportTypeSelectPanel.PANEL_NAME);\r
- \r
+\r
// ImportPartsSelectPanel\r
this.importPartsSelectPanel = new ImportPartsSelectPanel();\r
this.importPartsSelectPanel.addComponentListener(componentListener);\r
this.importPartsSelectPanel.addChangeListener(changeListener);\r
mainPanel.add(this.importPartsSelectPanel, ImportPartsSelectPanel.PANEL_NAME);\r
- \r
+\r
// ImportPresetSelectPanel\r
this.importPresetSelectPanel = new ImportPresetSelectPanel();\r
this.importPresetSelectPanel.addComponentListener(componentListener);\r
this.importPresetSelectPanel.addChangeListener(changeListener);\r
mainPanel.add(this.importPresetSelectPanel, ImportPresetSelectPanel.PANEL_NAME);\r
- \r
- \r
+\r
+\r
// button panel\r
\r
JPanel btnPanel = new JPanel();\r
actPrev.setEnabled(false);\r
actNext.setEnabled(false);\r
actFinish.setEnabled(false);\r
- \r
+\r
GridBagConstraints gbc = new GridBagConstraints();\r
- \r
+\r
gbc.gridx = 0;\r
gbc.gridy = 0;\r
gbc.gridheight = 1;\r
gbc.weightx = 1.;\r
gbc.weighty = 0.;\r
btnPanel.add(Box.createHorizontalGlue(), gbc);\r
- \r
+\r
gbc.gridx = Main.isLinuxOrMacOSX() ? 2 : 1;\r
gbc.gridy = 0;\r
gbc.weightx = 0.;\r
btnPanel.add(new JButton(this.actPrev), gbc);\r
- \r
+\r
gbc.gridx = Main.isLinuxOrMacOSX() ? 3 : 2;\r
gbc.gridy = 0;\r
JButton btnNext = new JButton(this.actNext);\r
btnPanel.add(btnNext, gbc);\r
- \r
+\r
gbc.gridx = Main.isLinuxOrMacOSX() ? 4 : 3;\r
gbc.gridy = 0;\r
btnPanel.add(new JButton(this.actFinish), gbc);\r
btnPanel.add(btnCancel, gbc);\r
\r
contentPane.add(btnPanel, BorderLayout.SOUTH);\r
- \r
+\r
// インプットマップ/アクションマップ\r
- \r
+\r
Toolkit tk = Toolkit.getDefaultToolkit();\r
JRootPane rootPane = getRootPane();\r
- \r
+\r
rootPane.setDefaultButton(btnNext);\r
- \r
+\r
InputMap im = rootPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);\r
ActionMap am = rootPane.getActionMap();\r
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), "closeImportWizDialog");\r
\r
setSize(500, 550);\r
setLocationRelativeTo(parent);\r
- \r
+\r
mainPanelLayout.first(mainPanel);\r
updateBtnPanelState();\r
}\r
- \r
+\r
protected void onComponentShown(JPanel panel) {\r
ImportWizardCardPanel activePanel = (ImportWizardCardPanel) panel;\r
activePanel.onActive(this, this.activePanel);\r
this.activePanel = activePanel;\r
updateBtnPanelState();\r
}\r
- \r
+\r
protected void updateBtnPanelState() {\r
if (activePanel != null) {\r
actPrev.setEnabled(activePanel.isReadyPrevious());\r
actNext.setEnabled(activePanel.isReadyNext());\r
actFinish.setEnabled(activePanel.isReadyFinish());\r
- \r
+\r
} else {\r
setEnableButtons(false);\r
}\r
}\r
- \r
+\r
public void setEnableButtons(boolean enabled) {\r
actPrev.setEnabled(enabled);\r
actNext.setEnabled(enabled);\r
actFinish.setEnabled(enabled);\r
}\r
- \r
+\r
protected String doNext() {\r
if (activePanel == null) {\r
throw new IllegalStateException();\r
}\r
return nextPanelName;\r
}\r
- \r
+\r
protected String doPrevious() {\r
if (activePanel == null) {\r
throw new IllegalStateException();\r
}\r
return activePanel.doPrevious();\r
}\r
- \r
+\r
protected void onClose() {\r
Properties strings = LocalizedResourcePropertyLoader.getCachedInstance()\r
.getLocalizedProperties(STRINGS_RESOURCE);\r
- \r
+\r
if (JOptionPane.showConfirmDialog(this,\r
strings.getProperty("confirm.close"),\r
strings.getProperty("confirm"),\r
// キャンセル\r
this.exitCode = EXIT_CANCELED;\r
this.importedCharacterData = null;\r
- \r
+\r
// ウィンドウを閉じる\r
dispose();\r
}\r
} finally {\r
setCursor(Cursor.getDefaultCursor());\r
}\r
- \r
+\r
// アーカイブを閉じる\r
importFileSelectPanel.closeArchive();\r
- \r
+\r
// 完了メッセージ\r
JOptionPane.showMessageDialog(this, strings.getProperty("complete"));\r
- \r
+\r
// 完了後、ウィンドウを閉じる.\r
this.exitCode = exitCode;\r
this.importedCharacterData = importedCharacterData;\r
dispose();\r
- \r
+\r
} catch (Exception ex) {\r
ErrorMessageHelper.showErrorDialog(this, ex);\r
// ディセーブルにしていたボタンをパネルの状態に戻す.\r
updateBtnPanelState();\r
}\r
}\r
- \r
+\r
/**\r
* ウィザードが閉じられた場合の終了コード. {@link #EXIT_PROFILE_UPDATED}であればプロファイルが更新されており,<br>\r
* {@link #EXIT_PROFILE_CREATED}であればプロファイルが作成されている.<br>\r
* {@link #EXIT_CANCELED}であればキャンセルされている.<br>\r
- * \r
+ *\r
* @return 終了コード\r
*/\r
public int getExitCode() {\r
return exitCode;\r
}\r
- \r
+\r
/**\r
* 新規または更新されたプロファイル、キャンセルされた場合はnull\r
- * \r
+ *\r
* @return プロファイル\r
*/\r
public CharacterData getImportedCharacterData() {\r
return importedCharacterData;\r
}\r
- \r
+\r
/**\r
* アーカイブからの新規プロファイルの作成\r
- * \r
+ *\r
* @return 作成された新規プロファイル\r
* @throws IOException\r
* 失敗\r
if (cd == null || !cd.isValid()) {\r
throw new IllegalStateException("imported caharcer data is invalid." + cd);\r
}\r
- \r
+\r
CharacterDataPersistent persist = CharacterDataPersistent.getInstance();\r
\r
CharacterData characterData = cd.duplicateBasicInfo();\r
// キャラクターセット名と作者名を設定する\r
characterData.setName(importTypeSelectPanel.getCharacterName());\r
characterData.setAuthor(importTypeSelectPanel.getAuthor());\r
- \r
+\r
// プリセットをインポートする場合\r
characterData.clearPartsSets(false);\r
if (importTypeSelectPanel.isImportPreset()) {\r
}\r
characterData.setDefaultPartsSetId(importPresetSelectPanel.getPrefferedDefaultPartsSetId());\r
}\r
- \r
+\r
// プロファイルの新規作成\r
// docBaseが設定されて返される.\r
persist.createProfile(characterData);\r
PartsManageData partsManageData = importModel.getPartsManageData();\r
importModel.updatePartsManageData(partsImageContents, partsManageData, null, characterData);\r
}\r
- \r
+\r
// インポートするピクチャの更新\r
if (importTypeSelectPanel.isImportSampleImage()) {\r
BufferedImage samplePicture = importModel.getSamplePicture();\r
persist.saveSamplePicture(characterData, samplePicture);\r
}\r
}\r
- \r
+\r
return characterData;\r
}\r
- \r
+\r
/**\r
* プロファイルの更新\r
- * \r
+ *\r
* @return 更新されたプロファイル\r
* @throws IOException\r
* 失敗\r
CharacterDataPersistent persist = CharacterDataPersistent.getInstance();\r
\r
CharacterData characterData = current.duplicateBasicInfo();\r
- \r
+\r
boolean imported = false;\r
boolean modCharacterDef = false;\r
boolean modFavories = false;\r
- \r
+\r
// インポートするパーツの更新\r
if (importTypeSelectPanel.isImportPartsImages()) {\r
// パーツのコピー\r
Collection<PartsImageContent> partsImageContents\r
= importPartsSelectPanel.getSelectedPartsImageContents();\r
importModel.copyPartsImageContents(partsImageContents, characterData);\r
- \r
+\r
// パーツ管理情報の追記・更新\r
PartsManageData partsManageData = importModel.getPartsManageData();\r
importModel.updatePartsManageData(partsImageContents, partsManageData, characterData, characterData);\r
- \r
+\r
imported = true;\r
}\r
- \r
+\r
// インポートするピクチャの更新\r
if (importTypeSelectPanel.isImportSampleImage()) {\r
BufferedImage samplePicture = importModel.getSamplePicture();\r
imported = true;\r
}\r
}\r
- \r
+\r
// インポートするパーツセットの更新\r
if (importTypeSelectPanel.isImportPreset()) {\r
for (PartsSet partsSet : importPresetSelectPanel.getSelectedPartsSets()) {\r
modCharacterDef = true;\r
modFavories = true;\r
}\r
- \r
+\r
// 説明の更新\r
if (importTypeSelectPanel.isAddDescription() && imported) {\r
URI archivedFile = importModel.getImportSource();\r
modCharacterDef = true;\r
}\r
}\r
- \r
+\r
// キャラクター定義の更新\r
if (modCharacterDef) {\r
persist.updateProfile(characterData); // キャラクター定義の構造に変化なし\r
if (modFavories) {\r
persist.saveFavorites(characterData);\r
}\r
- \r
+\r
return characterData;\r
}\r
\r
- \r
+\r
}\r
\r
/**\r
* タブの抽象基底クラス.<br>\r
- * \r
+ *\r
* @author seraphy\r
*/\r
abstract class ImportWizardCardPanel extends JPanel {\r
\r
private static final long serialVersionUID = 1L;\r
- \r
+\r
private LinkedList<ChangeListener> listeners = new LinkedList<ChangeListener>();\r
- \r
+\r
public void addChangeListener(ChangeListener l) {\r
if (l != null) {\r
listeners.add(l);\r
}\r
}\r
- \r
+\r
public void removeChangeListener(ChangeListener l) {\r
if (l != null) {\r
listeners.remove(l);\r
}\r
}\r
- \r
+\r
public void fireChangeEvent() {\r
ChangeEvent e = new ChangeEvent(this);\r
for (ChangeListener l : listeners) {\r
l.stateChanged(e);\r
}\r
}\r
- \r
+\r
public void onActive(ImportWizardDialog parent, ImportWizardCardPanel previousPanel) {\r
// なにもしない\r
}\r
- \r
+\r
public boolean isReadyPrevious() {\r
return false;\r
}\r
- \r
+\r
public boolean isReadyNext() {\r
return false;\r
}\r
- \r
+\r
public boolean isReadyFinish() {\r
return false;\r
}\r
public String doNext() {\r
throw new UnsupportedOperationException();\r
}\r
- \r
+\r
public String doPrevious() {\r
throw new UnsupportedOperationException();\r
}\r
\r
/**\r
* ファイル選択パネル\r
- * \r
+ *\r
* @author seraphy\r
*/\r
class ImportFileSelectPanel extends ImportWizardCardPanel {\r
\r
private static final long serialVersionUID = 1L;\r
- \r
+\r
public static final String PANEL_NAME = "fileSelectPanel";\r
\r
/**\r
private static ArchiveFileDialog archiveFileDialog = new ArchiveFileDialog();\r
\r
private ImportWizardDialog parent;\r
- \r
+\r
/**\r
* ファイル名を指定してインポート\r
*/\r
private JRadioButton radioArchiveFile;\r
- \r
+\r
/**\r
* ファイル名入力ボックス\r
*/\r
private JTextField txtArchiveFile;\r
- \r
+\r
/**\r
* ファイル選択ボタン\r
*/\r
* ディレクトリを指定してインポート\r
*/\r
private JRadioButton radioDirectory;\r
- \r
+\r
/**\r
* ディレクトリ入力ボックス\r
*/\r
private JTextField txtDirectory;\r
- \r
+\r
/**\r
* ディレクトリ選択ボタン\r
*/\r
private Action actChooseDirectory;\r
\r
- \r
- \r
+\r
+\r
/* 以下、対象ファイルの読み取り結果 */\r
- \r
- \r
+\r
+\r
public ImportFileSelectPanel() {\r
setLayout(new BorderLayout());\r
- \r
+\r
Properties strings = LocalizedResourcePropertyLoader.getCachedInstance()\r
.getLocalizedProperties(ImportWizardDialog.STRINGS_RESOURCE);\r
\r
fireChangeEvent();\r
}\r
};\r
- \r
+\r
txtArchiveFile = new JTextField();\r
txtDirectory = new JTextField();\r
\r
txtArchiveFile.getDocument().addDocumentListener(documentListener);\r
txtDirectory.getDocument().addDocumentListener(documentListener);\r
- \r
+\r
actChooseFile = new AbstractAction(strings.getProperty("browse")) {\r
private static final long serialVersionUID = 1L;\r
public void actionPerformed(ActionEvent e) {\r
onChooseFile();\r
}\r
};\r
- \r
+\r
actChooseDirectory = new AbstractAction(strings.getProperty("browse")) {\r
private static final long serialVersionUID = 1L;\r
public void actionPerformed(ActionEvent e) {\r
onChooseDirectory();\r
}\r
};\r
- \r
+\r
\r
JPanel fileChoosePanel = new JPanel();\r
GridBagLayout fileChoosePanelLayout = new GridBagLayout();\r
fileChoosePanel.setLayout(fileChoosePanelLayout);\r
- \r
+\r
radioArchiveFile = new JRadioButton(strings.getProperty("importingArchiveFile"));\r
radioDirectory = new JRadioButton(strings.getProperty("importingDirectory"));\r
\r
ButtonGroup btnGroup = new ButtonGroup();\r
btnGroup.add(radioArchiveFile);\r
btnGroup.add(radioDirectory);\r
- \r
+\r
// アーカイブからのインポートをデフォルトとする\r
radioArchiveFile.setSelected(true);\r
- \r
+\r
GridBagConstraints gbc = new GridBagConstraints();\r
\r
gbc.gridx = 0;\r
gbc.anchor = GridBagConstraints.WEST;\r
gbc.fill = GridBagConstraints.BOTH;\r
fileChoosePanel.add(radioArchiveFile, gbc);\r
- \r
+\r
gbc.gridx = 0;\r
gbc.gridy = 1;\r
gbc.gridwidth = 1;\r
gbc.ipadx = 45;\r
gbc.weightx = 0;\r
fileChoosePanel.add(Box.createHorizontalGlue(), gbc);\r
- \r
+\r
gbc.gridx = 1;\r
gbc.gridy = 1;\r
gbc.ipadx = 0;\r
gbc.gridwidth = 1;\r
gbc.weightx = 0;\r
fileChoosePanel.add(Box.createHorizontalGlue(), gbc);\r
- \r
+\r
gbc.gridx = 1;\r
gbc.gridy = 3;\r
gbc.ipadx = 0;\r
gbc.weightx = 1.;\r
gbc.weighty = 1.;\r
fileChoosePanel.add(Box.createGlue(), gbc);\r
- \r
+\r
add(fileChoosePanel, BorderLayout.CENTER);\r
- \r
+\r
// ドロップターゲット\r
new DropTarget(this, new FileDropTarget() {\r
@Override\r
ErrorMessageHelper.showErrorDialog(ImportFileSelectPanel.this, ex);\r
}\r
});\r
- \r
+\r
updateUIState();\r
}\r
\r
/**\r
* アーカイブファイルまたはディレクトリを選択状態とする.<br>\r
* nullの場合は選択を解除する.\r
- * \r
+ *\r
* @param dropFile\r
* アーカイブファイルまたはディレクトリ、もしくはnull\r
*/\r
radioArchiveFile.setSelected(true);\r
}\r
}\r
- \r
+\r
protected void updateUIState() {\r
boolean enableArchiveFile = radioArchiveFile.isSelected();\r
boolean enableDirectory = radioDirectory.isSelected();\r
- \r
+\r
txtArchiveFile.setEnabled(enableArchiveFile);\r
actChooseFile.setEnabled(enableArchiveFile);\r
- \r
+\r
txtDirectory.setEnabled(enableDirectory);\r
actChooseDirectory.setEnabled(enableDirectory);\r
}\r
- \r
+\r
protected void onChooseFile() {\r
File initFile = null;\r
if (txtArchiveFile.getText().trim().length() > 0) {\r
fireChangeEvent();\r
}\r
}\r
- \r
+\r
protected void onChooseDirectory() {\r
String directoryTxt = txtDirectory.getText();\r
JFileChooser dirChooser = new JFileChooser(directoryTxt);\r
}\r
return false;\r
}\r
- \r
+\r
@Override\r
public void onActive(ImportWizardDialog parent, ImportWizardCardPanel previousPanel) {\r
this.parent = parent;\r
- \r
+\r
// 開いているアーカイブがあれば閉じる\r
closeArchive();\r
}\r
- \r
+\r
/**\r
* 開いているアーカイブがあればクローズする.\r
*/\r
// エラーが発生しても、とりあえず無視する.\r
}\r
}\r
- \r
+\r
@Override\r
public String doNext() {\r
if (!isReadyNext()) {\r
return null;\r
}\r
importArchive = file.toURI();\r
- \r
+\r
} else if (radioDirectory.isSelected()) {\r
// ディレクトリによるインポート\r
File file = new File(txtDirectory.getText());\r
// それ以外はサポートしていない.\r
return null;\r
}\r
- \r
+\r
try {\r
parent.importModel.openImportSource(importArchive, parent.current);\r
\r
return null;\r
}\r
};\r
- \r
+\r
WorkerWithProgessDialog<Object> dlg\r
= new WorkerWithProgessDialog<Object>(parent, worker);\r
- \r
+\r
dlg.startAndWait();\r
- \r
+\r
// 読み込めたら次ページへ\r
return ImportTypeSelectPanel.PANEL_NAME;\r
\r
} catch (WorkerException ex) {\r
ErrorMessageHelper.showErrorDialog(this, ex.getCause());\r
- \r
+\r
} catch (Exception ex) {\r
ErrorMessageHelper.showErrorDialog(this, ex);\r
}\r
- \r
+\r
return null;\r
}\r
}\r
\r
-class URLTableRow implements Serializable {\r
- \r
- private static final long serialVersionUID = 3452190266438145049L;\r
+class URLTableRow {\r
\r
private String downloadURL;\r
- \r
+\r
private String author;\r
- \r
+\r
public String getAuthor() {\r
return author;\r
}\r
- \r
+\r
public String getDownloadURL() {\r
return downloadURL;\r
}\r
- \r
+\r
public void setAuthor(String author) {\r
this.author = author;\r
}\r
- \r
+\r
public void setDownloadURL(String downloadURL) {\r
this.downloadURL = downloadURL;\r
}\r
- \r
+\r
}\r
\r
class URLTableModel extends AbstractTableModelWithComboBoxModel<URLTableRow> {\r
private static final long serialVersionUID = 7075478118793390224L;\r
\r
private static final String[] COLUMN_NAMES;\r
- \r
+\r
private static final int[] COLUMN_WIDTHS;\r
- \r
+\r
static {\r
COLUMN_NAMES = new String[] {\r
"作者",\r
300,\r
};\r
}\r
- \r
+\r
@Override\r
public String getColumnName(int column) {\r
return COLUMN_NAMES[column];\r
}\r
- \r
+\r
public int getColumnCount() {\r
return COLUMN_NAMES.length;\r
}\r
- \r
+\r
public Object getValueAt(int rowIndex, int columnIndex) {\r
URLTableRow row = getRow(rowIndex);\r
switch (columnIndex) {\r
}\r
return "";\r
}\r
- \r
+\r
@Override\r
public Class<?> getColumnClass(int columnIndex) {\r
return String.class;\r
}\r
- \r
+\r
\r
public void adjustColumnModel(TableColumnModel columnModel) {\r
for (int idx = 0; idx < COLUMN_WIDTHS.length; idx++) {\r
columnModel.getColumn(idx).setPreferredWidth(COLUMN_WIDTHS[idx]);\r
}\r
}\r
- \r
+\r
public void initModel(CharacterData characterData) {\r
clear();\r
HashMap<String, String> downloadUrlsMap = new HashMap<String, String>();\r
}\r
}\r
}\r
- \r
+\r
for (Map.Entry<String, String> entry : downloadUrlsMap.entrySet()) {\r
String downloadURL = entry.getKey();\r
String author = entry.getValue();\r
row.setAuthor(author);\r
addRow(row);\r
}\r
- \r
+\r
Collections.sort(elements, new Comparator<URLTableRow>() {\r
public int compare(URLTableRow o1, URLTableRow o2) {\r
int ret = o1.getAuthor().compareTo(o2.getAuthor());\r
return ret;\r
}\r
});\r
- \r
+\r
fireTableDataChanged();\r
}\r
}\r
\r
/**\r
* ファイル選択パネル\r
- * \r
+ *\r
* @author seraphy\r
*/\r
class ImportTypeSelectPanel extends ImportWizardCardPanel {\r
- \r
+\r
private static final long serialVersionUID = 1L;\r
\r
public static final String PANEL_NAME = "importTypeSelectPanel";\r
- \r
+\r
private ImportWizardDialog parent;\r
\r
private SamplePicturePanel samplePicturePanel;\r
- \r
+\r
private JTextField txtCharacterId;\r
- \r
+\r
private JTextField txtCharacterRev;\r
\r
private JTextField txtCharacterName;\r
- \r
+\r
private JTextField txtAuthor;\r
- \r
+\r
private JTextArea txtDescription;\r
- \r
+\r
private JCheckBox chkPartsImages;\r
- \r
+\r
private JCheckBox chkPresets;\r
- \r
+\r
private JCheckBox chkSampleImage;\r
- \r
+\r
private JCheckBox chkAddDescription;\r
- \r
+\r
private String additionalDescription;\r
- \r
+\r
\r
/* 以下、選択結果 */\r
- \r
+\r
public ImportTypeSelectPanel() {\r
Properties strings = LocalizedResourcePropertyLoader.getCachedInstance()\r
.getLocalizedProperties(ImportWizardDialog.STRINGS_RESOURCE);\r
txtCharacterId.setEditable(false); // 読み取り専用\r
txtCharacterId.setEnabled(false);\r
archiveInfoPanel.add(txtCharacterId, gbc);\r
- \r
+\r
gbc.gridx = 0;\r
gbc.gridy = 2;\r
gbc.gridheight = 1;\r
.getProperty("basic.sampleImage"))));\r
\r
// /\r
- \r
+\r
gbc.gridx = 0;\r
gbc.gridy = 0;\r
gbc.gridheight = 1;\r
\r
// 呼び出しもと情報\r
CharacterData current = parent.current;\r
- \r
+\r
// キャラクター定義情報\r
CharacterData cd = parent.importModel.getCharacterData();\r
String readme;\r
\r
// 新規の場合でインポートもとが有効なキャラクターセットであれば作成可能\r
final boolean creatable = (current == null && cd != null && cd.isValid());\r
- \r
+\r
// 新規作成の場合はキャラクター定義名と作者名を更新可能とする\r
txtCharacterName.setEnabled(current == null);\r
txtCharacterName.setEditable(current == null);\r
txtAuthor.setEditable(current == null);\r
txtAuthor.setEnabled(current == null);\r
- \r
+\r
// ID、REVが一致するか?\r
boolean matchID = false;\r
boolean matchREV = false;\r
txtCharacterId.setText(cd.getId());\r
txtCharacterRev.setText(cd.getRev());\r
txtCharacterName.setText(cd.getName());\r
- \r
+\r
if (current != null) {\r
// 既存のプロファイルを選択していてインポート結果のキャラクター定義がある場合はID, REVを比較する.\r
matchID = current.getId() == null ? cd.getId() == null : current.getId().equals(cd.getId());\r
matchID = true;\r
matchREV = true;\r
}\r
- \r
+\r
AppConfig appConfig = AppConfig.getInstance();\r
Color invalidBgColor = appConfig.getInvalidBgColor();\r
- \r
+\r
txtCharacterId.setBackground(matchID ? getBackground() : invalidBgColor);\r
txtCharacterRev.setBackground(matchREV ? getBackground() : invalidBgColor);\r
- \r
+\r
txtAuthor.setText(cd.getAuthor());\r
- readme = cd.getDescription(); \r
- \r
+ readme = cd.getDescription();\r
+\r
} else {\r
// ID, REV等は存在しないので空にする\r
txtCharacterId.setText("");\r
txtCharacterRev.setText("");\r
txtCharacterName.setText("");\r
txtAuthor.setText("");\r
- \r
+\r
// readmeで代用\r
readme = parent.importModel.getReadme();\r
}\r
- \r
+\r
// 説明を追記する.\r
boolean existsReadme = (readme != null && readme.trim().length() > 0);\r
additionalDescription = existsReadme ? readme : "";\r
txtDescription.setText(additionalDescription);\r
chkAddDescription.setEnabled((updatable || creatable) && existsReadme);\r
chkAddDescription.setSelected((updatable || creatable) && existsReadme);\r
- \r
+\r
// プリセットまたはお気に入りが存在するか?\r
boolean hasPresetOrFavorites = (cd == null) ? false : !cd.getPartsSets().isEmpty();\r
chkPresets.setEnabled(hasPresetOrFavorites);\r
\r
// パーツイメージ\r
Collection<PartsImageContent> partsImageContentsMap = parent.importModel.getPartsImageContents();\r
- \r
+\r
// パーツが存在するか?\r
boolean hasParts = !partsImageContentsMap.isEmpty();\r
chkPartsImages.setEnabled(hasParts);\r
chkPartsImages.setSelected(hasParts);\r
- \r
+\r
// サンプルピクチャ\r
BufferedImage samplePicture = parent.importModel.getSamplePicture();\r
if (samplePicture != null && (updatable || creatable)) {\r
// パーツまたはお気に入り・プリセットが存在する場合、\r
// および、新規の場合はキャラクター定義が存在する場合はコンテンツ有り\r
boolean hasContents = hasParts || hasPresetOrFavorites\r
- || (current == null && cd != null && cd.isValid()); \r
+ || (current == null && cd != null && cd.isValid());\r
\r
if (!hasContents) {\r
JOptionPane.showMessageDialog(this, strings.getProperty("noContents"));\r
\r
} else if (cd == null) {\r
JOptionPane.showMessageDialog(this, strings.getProperty("notFormalArchive"));\r
- \r
+\r
} else if (!matchID) {\r
String fmt = strings.getProperty("unmatchedProfileId");\r
String msg = MessageFormat.format(fmt,\r
cd.getId() == null ? "" : cd.getId());\r
JOptionPane.showMessageDialog(this, msg);\r
- \r
+\r
} else if (!matchREV) {\r
String fmt = strings.getProperty("unmatchedProfileRev");\r
String msg = MessageFormat.format(fmt, cd.getRev() == null\r
JOptionPane.showMessageDialog(this, msg);\r
}\r
}\r
- \r
+\r
public boolean isImportPreset() {\r
return chkPresets.isSelected();\r
}\r
- \r
+\r
public boolean isImportPartsImages() {\r
return chkPartsImages.isSelected();\r
}\r
- \r
+\r
public boolean isImportSampleImage() {\r
return chkSampleImage.isSelected();\r
}\r
- \r
+\r
public boolean isAddDescription() {\r
return chkAddDescription.isSelected();\r
}\r
- \r
+\r
/**\r
* 説明として追加するドキュメント.<Br>\r
* これはユーザーが編集可能であり、ユーザー編集後の値が取得される.<br>\r
- * \r
+ *\r
* @return 説明として追加するドキュメント\r
*/\r
public String getAdditionalDescription() {\r
return txtDescription.getText();\r
}\r
- \r
+\r
/**\r
* キャラクター定義名を取得する.\r
- * \r
+ *\r
* @return キャラクター定義名\r
*/\r
public String getCharacterName() {\r
return txtCharacterName.getText();\r
}\r
- \r
+\r
/**\r
* 作者名を取得する.\r
- * \r
+ *\r
* @return 作者名\r
*/\r
public String getAuthor() {\r
return txtAuthor.getText();\r
}\r
- \r
+\r
@Override\r
public boolean isReadyPrevious() {\r
return true;\r
}\r
- \r
+\r
@Override\r
public String doPrevious() {\r
return ImportFileSelectPanel.PANEL_NAME;\r
}\r
- \r
+\r
@Override\r
public boolean isReadyNext() {\r
if (isImportPartsImages() || isImportPreset()) {\r
}\r
return false;\r
}\r
- \r
+\r
@Override\r
public boolean isReadyFinish() {\r
if (!isImportPartsImages() && !isImportPreset()) {\r
}\r
return false;\r
}\r
- \r
+\r
@Override\r
public String doNext() {\r
return ImportPartsSelectPanel.PANEL_NAME;\r
\r
/**\r
* パーツ選択パネル\r
- * \r
+ *\r
* @author seraphy\r
*/\r
class ImportPartsSelectPanel extends ImportWizardCardPanel {\r
\r
private static final long serialVersionUID = 1L;\r
\r
- public static final String PANEL_NAME = "importPartsSelectPanel"; \r
- \r
+ public static final String PANEL_NAME = "importPartsSelectPanel";\r
+\r
private ImportWizardDialog parent;\r
- \r
+\r
\r
private ImportPartsTableModel partsTableModel;\r
- \r
+\r
private JPanel profileSizePanel;\r
- \r
+\r
private JTextField txtProfileHeight;\r
- \r
+\r
private int profileWidth;\r
- \r
+\r
private int profileHeight;\r
\r
private JTextField txtProfileWidth;\r
\r
private JTable partsTable;\r
- \r
+\r
private Action actSelectAll;\r
- \r
+\r
private Action actDeselectAll;\r
\r
private Action actSort;\r
\r
private Action actSortByTimestamp;\r
\r
- \r
+\r
public ImportPartsSelectPanel() {\r
Properties strings = LocalizedResourcePropertyLoader.getCachedInstance()\r
.getLocalizedProperties(ImportWizardDialog.STRINGS_RESOURCE);\r
profileSizePanel.setLayout(profileSizePanelLayout);\r
profileSizePanel.setBorder(BorderFactory\r
.createTitledBorder("プロファイルのサイズ"));\r
- \r
+\r
GridBagConstraints gbc = new GridBagConstraints();\r
- \r
+\r
gbc.gridx = 0;\r
gbc.gridy = 0;\r
gbc.gridheight = 1;\r
gbc.gridx = 1;\r
gbc.gridy = 0;\r
profileSizePanel.add(txtProfileWidth, gbc);\r
- \r
+\r
gbc.gridx = 2;\r
gbc.gridy = 0;\r
profileSizePanel.add(new JLabel("高さ:", JLabel.RIGHT), gbc);\r
gbc.gridx = 3;\r
gbc.gridy = 0;\r
profileSizePanel.add(txtProfileHeight, gbc);\r
- \r
+\r
gbc.gridx = 4;\r
gbc.gridy = 0;\r
gbc.weightx = 1.;\r
profileSizePanel.add(Box.createHorizontalGlue(), gbc);\r
\r
add(profileSizePanel, BorderLayout.NORTH);\r
- \r
+\r
partsTableModel = new ImportPartsTableModel();\r
\r
partsTableModel.addTableModelListener(new TableModelListener() {\r
// BooleanのデフォルトのレンダラーはJCheckBoxを継承したJTable$BooleanRenderer\r
comp.setEnabled(isCellEditable(row, column) && isEnabled());\r
}\r
- \r
+\r
// 行モデル取得\r
ImportPartsTableModel model = (ImportPartsTableModel) getModel();\r
ImportPartsModel rowModel = model.getRow(row);\r
- \r
+\r
Long lastModifiedAtCur = rowModel.getLastModifiedAtCurrentProfile();\r
if (lastModifiedAtCur != null) {\r
// 既存のパーツが存在すれば太字\r
boolean warnings = false;\r
if (column == ImportPartsTableModel.COLUMN_LASTMODIFIED) {\r
// 既存のほうが日付が新しければワーニング\r
- if (lastModifiedAtCur != null && \r
+ if (lastModifiedAtCur != null &&\r
rowModel.getLastModified() < lastModifiedAtCur.longValue()) {\r
warnings = true;\r
}\r
warnings = true;\r
}\r
}\r
- \r
+\r
// 前景色、ディセーブル時は灰色\r
Color foregroundColor = isCellSelected(row, column) ? getSelectionForeground() : getForeground();\r
comp.setForeground(isEnabled() ? foregroundColor : disabledForeground);\r
- \r
+\r
// 背景色、警告行は赤色に\r
if (warnings) {\r
AppConfig appConfig = AppConfig.getInstance();\r
comp.setBackground(getBackground());\r
}\r
}\r
- \r
+\r
return comp;\r
}\r
};\r
partsTableModel.setCheck(selRows, false);\r
}\r
};\r
- \r
+\r
final JPopupMenu partsTablePopupMenu = new JPopupMenu();\r
partsTablePopupMenu.add(actPartsSetCheck);\r
partsTablePopupMenu.add(actPartsUnsetCheck);\r
- \r
+\r
partsTable.setComponentPopupMenu(partsTablePopupMenu);\r
- \r
+\r
JScrollPane partsTableSP = new JScrollPane(partsTable);\r
partsTableSP.setBorder(null);\r
JPanel partsTableTitledPanel = new JPanel(new BorderLayout());\r
add(btnPanel, BorderLayout.SOUTH);\r
}\r
\r
- \r
+\r
@Override\r
public void onActive(ImportWizardDialog parent, ImportWizardCardPanel previousPanel) {\r
this.parent = parent;\r
if (previousPanel == parent.importPresetSelectPanel) {\r
return;\r
}\r
- \r
+\r
// インポート対象のプロファイルサイズ\r
CharacterData characterData;\r
if (parent.current == null) {\r
profileSizePanel.revalidate();\r
this.profileHeight = profileHeight;\r
this.profileWidth = profileWidth;\r
- \r
+\r
// パーツのインポート指定があれば編集可能に、そうでなければ表示のみ\r
// (パーツセットのインポートの確認のため、パーツ一覧は表示できるようにしておく)\r
boolean enabled = parent.importTypeSelectPanel.isImportPartsImages();\r
- \r
+\r
partsTable.setEnabled(enabled);\r
actDeselectAll.setEnabled(enabled);\r
actSelectAll.setEnabled(enabled);\r
actSort.setEnabled(enabled);\r
actSortByTimestamp.setEnabled(enabled);\r
- \r
+\r
CharacterData currentProfile = parent.current;\r
Collection<PartsImageContent> partsImageContents = parent.importModel.getPartsImageContents();\r
PartsManageData partsManageData = parent.importModel.getPartsManageData();\r
partsTableModel.initModel(partsImageContents, partsManageData, currentProfile);\r
- \r
+\r
// プリセットのモデルも更新する.\r
Collection<PartsSet> partsSets = null;\r
if (parent.importTypeSelectPanel.isImportPreset()) {\r
partsSets = cd.getPartsSets().values();\r
}\r
}\r
- \r
+\r
String defaultPartsSetId;\r
CharacterData presetImportTarget;\r
if (parent.current == null) {\r
presetImportTarget = parent.current;\r
defaultPartsSetId = null; // 既存の場合はデフォルトのパーツセットであるかは表示する必要ないのでnullにする.\r
}\r
- \r
+\r
parent.importPresetSelectPanel.initModel(partsSets, defaultPartsSetId, presetImportTarget);\r
}\r
\r
public boolean isReadyPrevious() {\r
return true;\r
}\r
- \r
+\r
@Override\r
public String doPrevious() {\r
this.partsTableModel.clear();\r
}\r
return false;\r
}\r
- \r
+\r
@Override\r
public boolean isReadyFinish() {\r
if (this.parent != null) {\r
}\r
return false;\r
}\r
- \r
+\r
public String doNext() {\r
return ImportPresetSelectPanel.PANEL_NAME;\r
};\r
- \r
- \r
+\r
+\r
protected void onSelectAll() {\r
partsTableModel.selectAll();\r
}\r
\r
/**\r
* 選択されたイメージコンテンツのコレクション.<br>\r
- * \r
+ *\r
* @return 選択されたイメージコンテンツのコレクション、なければ空\r
*/\r
public Collection<PartsImageContent> getSelectedPartsImageContents() {\r
return partsTableModel.getSelectedPartsImageContents();\r
}\r
- \r
+\r
/**\r
* すでにプロファイルに登録済みのパーツ識別子、および、これからインポートする予定の選択されたパーツ識別子のコレクション.<br>\r
- * \r
+ *\r
* @return インポートされた、またはインポートするパーツ識別子のコレクション.なければ空.\r
*/\r
public Collection<PartsIdentifier> getImportedPartsIdentifiers() {\r
partsIdentifiers.addAll(partsTableModel.getSelectedPartsIdentifiers());\r
return partsIdentifiers;\r
}\r
- \r
+\r
public void selectByPartsIdentifiers(Collection<PartsIdentifier> partsIdentifiers) {\r
partsTableModel.selectByPartsIdentifiers(partsIdentifiers);\r
}\r
- \r
+\r
}\r
\r
\r
/**\r
* 同じパーツ名をもつイメージのコレクション.<br>\r
* パーツの各レイヤーの集合を想定する.<br>\r
- * \r
+ *\r
* @author seraphy\r
*/\r
class ImportPartsImageSet extends AbstractCollection<PartsImageContent> {\r
* パーツ名\r
*/\r
private String partsName;\r
- \r
+\r
/**\r
* 各レイヤー\r
*/\r
private ArrayList<PartsImageContent> contentSet = new ArrayList<PartsImageContent>();\r
- \r
+\r
private Long lastModified;\r
- \r
+\r
private int width;\r
- \r
+\r
private int height;\r
- \r
+\r
private boolean unmatchedSize;\r
- \r
+\r
private boolean alphaColor;\r
- \r
+\r
private Collection<PartsCategory> partsCategories;\r
- \r
+\r
private boolean checked;\r
\r
- \r
+\r
public ImportPartsImageSet(String partsName) {\r
if (partsName == null || partsName.length() == 0) {\r
throw new IllegalArgumentException();\r
}\r
this.partsName = partsName;\r
}\r
- \r
+\r
public String getPartsName() {\r
return partsName;\r
}\r
- \r
+\r
@Override\r
public int size() {\r
return contentSet.size();\r
}\r
- \r
+\r
public Iterator<PartsImageContent> iterator() {\r
return contentSet.iterator();\r
}\r
- \r
+\r
@Override\r
public boolean add(PartsImageContent o) {\r
if (o == null) {\r
if (!partsName.equals(o.getPartsName())) {\r
throw new IllegalArgumentException();\r
}\r
- \r
+\r
lastModified = null; // リセットする.\r
- \r
+\r
return contentSet.add(o);\r
}\r
- \r
+\r
public int getWidth() {\r
recheck();\r
return width;\r
}\r
- \r
+\r
public int getHeight() {\r
recheck();\r
return height;\r
}\r
- \r
+\r
public boolean isUnmatchedSize() {\r
recheck();\r
return unmatchedSize;\r
}\r
- \r
+\r
public boolean isAlphaColor() {\r
recheck();\r
return alphaColor;\r
}\r
- \r
+\r
public long lastModified() {\r
recheck();\r
return lastModified.longValue();\r
}\r
- \r
+\r
public Collection<PartsCategory> getPartsCategories() {\r
recheck();\r
return this.partsCategories;\r
}\r
- \r
+\r
protected void recheck() {\r
if (lastModified != null) {\r
return;\r
maxHeight = Math.max(maxHeight, header.getHeight());\r
minWidth = Math.max(minWidth, header.getWidth());\r
minHeight = Math.max(minHeight, header.getHeight());\r
- \r
+\r
if (header.getColorType() != 6 && !header.hasTransparencyInformation()) {\r
// TrueColor + Alpha (6)か、アルファ情報があるもの以外はアルファなしとする.\r
alphaColor = false;\r
}\r
- \r
+\r
for (CategoryLayerPair clPair : partsImageContent.getCategoryLayerPairs()) {\r
partsCategories.add(clPair.getPartsCategory());\r
}\r
- \r
+\r
long tm = partsImageContent.lastModified();\r
lastModified = Math.max(lastModified, tm);\r
}\r
- \r
+\r
this.lastModified = Long.valueOf(lastModified);\r
this.width = maxWidth;\r
this.height = maxHeight;\r
public void setChecked(boolean checked) {\r
this.checked = checked;\r
}\r
- \r
+\r
public boolean isChecked() {\r
return checked;\r
}\r
class ImportPartsModel {\r
\r
private PartsIdentifier partsIdentifier;\r
- \r
+\r
private PartsAuthorInfo authorInfo;\r
- \r
+\r
private PartsManageData.PartsVersionInfo versionInfo;\r
- \r
+\r
private PartsSpec partsSpecAtCurrent;\r
- \r
+\r
private ImportPartsImageSet imageSet;\r
- \r
+\r
private int numOfLink;\r
- \r
+\r
private Long lastModifiedAtCurrentProfile;\r
- \r
+\r
\r
/**\r
* 行モデルを構築する\r
- * \r
+ *\r
* @param partsIdentifier\r
* パーツ識別子\r
* @param authorInfo\r
this.partsSpecAtCurrent = partsSpecAtCurrent;\r
this.imageSet = imageSet;\r
this.numOfLink = numOfLink;\r
- \r
+\r
if (partsSpecAtCurrent != null) {\r
lastModifiedAtCurrentProfile = Long.valueOf(partsSpecAtCurrent\r
.getPartsFiles().lastModified());\r
lastModifiedAtCurrentProfile = null;\r
}\r
}\r
- \r
+\r
public int getNumOfLink() {\r
return numOfLink;\r
}\r
- \r
+\r
public PartsIdentifier getPartsIdentifier() {\r
return partsIdentifier;\r
}\r
- \r
+\r
public ImportPartsImageSet getImageSet() {\r
return imageSet;\r
}\r
public String getPartsName() {\r
return partsIdentifier.getLocalizedPartsName();\r
}\r
- \r
+\r
public String getAuthor() {\r
if (authorInfo != null) {\r
return authorInfo.getAuthor();\r
}\r
return null;\r
}\r
- \r
+\r
public String getAuthorAtCurrent() {\r
if (partsSpecAtCurrent != null) {\r
PartsAuthorInfo partsAuthorInfo = partsSpecAtCurrent.getAuthorInfo();\r
}\r
return null;\r
}\r
- \r
+\r
public double getVersion() {\r
if (versionInfo != null) {\r
return versionInfo.getVersion();\r
}\r
return 0;\r
}\r
- \r
+\r
public double getVersionAtCurrent() {\r
if (partsSpecAtCurrent != null) {\r
return partsSpecAtCurrent.getVersion();\r
}\r
return 0;\r
}\r
- \r
+\r
public PartsCategory getPartsCategory() {\r
return partsIdentifier.getPartsCategory();\r
}\r
- \r
+\r
public void setChecked(boolean checked) {\r
imageSet.setChecked(checked);\r
}\r
- \r
+\r
public boolean isChecked() {\r
return imageSet.isChecked();\r
}\r
- \r
+\r
public int getWidth() {\r
return imageSet.getWidth();\r
}\r
- \r
+\r
public int getHeight() {\r
return imageSet.getHeight();\r
}\r
- \r
+\r
public boolean isUnmatchedSize() {\r
return imageSet.isUnmatchedSize();\r
}\r
- \r
+\r
public boolean isAlphaColor() {\r
return imageSet.isAlphaColor();\r
}\r
- \r
+\r
public long getLastModified() {\r
return imageSet.lastModified();\r
}\r
- \r
+\r
public Long getLastModifiedAtCurrentProfile() {\r
return lastModifiedAtCurrentProfile;\r
}\r
private static final long serialVersionUID = 1L;\r
\r
private static final String[] COLUMN_NAMES;\r
- \r
+\r
private static final int[] COLUMN_WIDTHS;\r
- \r
+\r
public static final int COLUMN_LASTMODIFIED = 5;\r
- \r
+\r
public static final int COLUMN_ALPHA = 4;\r
- \r
+\r
public static final int COLUMN_SIZE = 3;\r
- \r
+\r
private Set<PartsIdentifier> currentProfilePartsIdentifiers;\r
- \r
+\r
static {\r
Properties strings = LocalizedResourcePropertyLoader.getCachedInstance()\r
.getLocalizedProperties(ImportWizardDialog.STRINGS_RESOURCE);\r
- \r
+\r
COLUMN_NAMES = new String[] {\r
strings.getProperty("parts.column.check"),\r
strings.getProperty("parts.column.partsname"),\r
Integer.parseInt(strings.getProperty("parts.column.org-version.size")),\r
};\r
}\r
- \r
+\r
\r
/**\r
* モデルを初期化する.<br>\r
- * \r
+ *\r
* @param partsImageContents\r
* インポートもとアーカイブに含まれる、全パーツイメージコンテンツ\r
* @param currentProfile\r
if (partsImageContents == null || partsManageData == null) {\r
return;\r
}\r
- \r
+\r
// 現在のプロファイルが所有する全パーツ一覧を構築する.\r
// 現在のプロファイルがなければ空.\r
HashSet<PartsIdentifier> currentProfilePartsIdentifiers = new HashSet<PartsIdentifier>();\r
}\r
partsImageSet.add(content);\r
}\r
- \r
+\r
// 名前順に並び替える\r
ArrayList<String> partsNames = new ArrayList<String>(partsImageSets.keySet());\r
Collections.sort(partsNames);\r
ImportPartsImageSet partsImageSet = partsImageSets.get(partsName);\r
int numOfLink = partsImageSet.getPartsCategories().size();\r
for (PartsCategory partsCategory : partsImageSet.getPartsCategories()) {\r
- \r
+\r
// パーツ管理情報の索引キー\r
PartsManageData.PartsKey partsKey = new PartsManageData.PartsKey(partsName, partsCategory.getCategoryId());\r
// ローカライズされたパーツ名があれば取得する。なければオリジナルのまま\r
ImportPartsModel rowModel = new ImportPartsModel(\r
partsIdentifier, partsAuthorInfo, versionInfo,\r
partsSpec, partsImageSet, numOfLink);\r
- \r
+\r
addRow(rowModel);\r
}\r
}\r
- \r
+\r
// 既存がないか、既存よりも新しい日付であれば自動的にチェックを設定する.\r
// もしくはバージョンが上であれば自動的にチェックをつける.\r
for (ImportPartsModel rowModel : elements) {\r
- \r
+\r
// 現在のプロファイル上のファイル群の最終更新日\r
Long lastModifiedAtCurrent = rowModel.getLastModifiedAtCurrentProfile();\r
if (lastModifiedAtCurrent == null) {\r
lastModifiedAtCurrent = Long.valueOf(0);\r
}\r
- \r
+\r
// インポートするファイル群の最終更新日\r
ImportPartsImageSet partsImageSet = rowModel.getImageSet();\r
\r
if (lastModifiedAtCurrent.longValue() < partsImageSet.lastModified()) {\r
partsImageSet.setChecked(true);\r
}\r
- \r
+\r
// バージョンが新しければチェックをつける. (改変版や作者名改名もあるので、作者名が同一であるかは問わない.)\r
double versionAtCurrent = rowModel.getVersionAtCurrent();\r
double version = rowModel.getVersion();\r
// 並び替え\r
sort();\r
}\r
- \r
+\r
/**\r
* 選択されているパーツを構成するファイルのコレクションを返します.<br>\r
- * \r
+ *\r
* @return パーツイメージコンテンツのコレクション、選択がなければ空\r
*/\r
public Collection<PartsImageContent> getSelectedPartsImageContents() {\r
IdentityHashMap<ImportPartsImageSet, ImportPartsImageSet> partsImageSets\r
= new IdentityHashMap<ImportPartsImageSet, ImportPartsImageSet>();\r
- \r
+\r
for (ImportPartsModel rowModel : elements) {\r
ImportPartsImageSet partsImageSet = rowModel.getImageSet();\r
if (partsImageSet.isChecked()) {\r
partsImageSets.put(partsImageSet, partsImageSet);\r
}\r
}\r
- \r
+\r
ArrayList<PartsImageContent> partsImageContents = new ArrayList<PartsImageContent>();\r
for (ImportPartsImageSet partsImageSet : partsImageSets.values()) {\r
partsImageContents.addAll(partsImageSet);\r
* 選択されているパーツ識別子のコレクションを返します.<br>\r
* 返されるコレクションには同一のパーツ識別子が複数存在しないことが保証されます.<br>\r
* 一つも選択がない場合は空が返されます.<br>\r
- * \r
+ *\r
* @return パーツ識別子のコレクション.<br>\r
*/\r
public Collection<PartsIdentifier> getSelectedPartsIdentifiers() {\r
}\r
return partsIdentifiers;\r
}\r
- \r
+\r
/**\r
* 現在のプロファイルが所有している全パーツの識別子.<br>\r
* 現在のプロファイルがないか、まったく所有していなければ空.<br>\r
- * \r
+ *\r
* @return 現在のプロファイルが所有するパーツの識別子のコレクション.(重複しない一意であることが保証される.)\r
*/\r
public Collection<PartsIdentifier> getCurrentProfilePartsIdentifers() {\r
public int getColumnCount() {\r
return COLUMN_NAMES.length;\r
}\r
- \r
+\r
@Override\r
public String getColumnName(int column) {\r
return COLUMN_NAMES[column];\r
}\r
- \r
+\r
public Object getValueAt(int rowIndex, int columnIndex) {\r
ImportPartsModel rowModel = getRow(rowIndex);\r
switch (columnIndex) {\r
}\r
return "";\r
}\r
- \r
+\r
@Override\r
public void setValueAt(Object aValue, int rowIndex, int columnIndex) {\r
ImportPartsModel rowModel = getRow(rowIndex);\r
fireListUpdated(rowIndex, rowIndex);\r
}\r
}\r
- \r
+\r
@Override\r
public Class<?> getColumnClass(int columnIndex) {\r
switch (columnIndex) {\r
}\r
return String.class;\r
}\r
- \r
+\r
@Override\r
public boolean isCellEditable(int rowIndex, int columnIndex) {\r
if (columnIndex == 0) {\r
}\r
return false;\r
}\r
- \r
+\r
public void adjustColumnModel(TableColumnModel columnModel) {\r
int mx = columnModel.getColumnCount();\r
for (int idx = 0; idx < mx; idx++) {\r
columnModel.getColumn(idx).setWidth(COLUMN_WIDTHS[idx]);\r
}\r
}\r
- \r
+\r
public void selectAll() {\r
boolean modified = false;\r
for (ImportPartsModel rowModel : elements) {\r
fireTableDataChanged();\r
}\r
}\r
- \r
+\r
public void deselectAll() {\r
boolean modified = false;\r
for (ImportPartsModel rowModel : elements) {\r
fireTableDataChanged();\r
}\r
}\r
- \r
+\r
public void sort() {\r
Collections.sort(elements, new Comparator<ImportPartsModel> () {\r
public int compare(ImportPartsModel o1, ImportPartsModel o2) {\r
return ret;\r
}\r
});\r
- \r
+\r
fireTableDataChanged();\r
}\r
- \r
+\r
public void sortByTimestamp() {\r
Collections.sort(elements, new Comparator<ImportPartsModel> () {\r
public int compare(ImportPartsModel o1, ImportPartsModel o2) {\r
if (ret == 0) {\r
Long tm1 = o1.getLastModifiedAtCurrentProfile();\r
Long tm2 = o2.getLastModifiedAtCurrentProfile();\r
- \r
+\r
long lastModified1 = Math.max(o1.getLastModified(), tm1 == null ? 0 : tm1.longValue());\r
long lastModified2 = Math.max(o2.getLastModified(), tm2 == null ? 0 : tm2.longValue());\r
\r
if (ret == 0) {\r
ret = o1.getPartsIdentifier().compareTo(o2.getPartsIdentifier());\r
}\r
- \r
+\r
return ret == 0 ? 0 : ret > 0 ? 1 : -1;\r
}\r
});\r
\r
/**\r
* 指定したパーツ識別子をチェック状態にする.\r
- * \r
+ *\r
* @param partsIdentifiers\r
* パーツ識別子のコレクション、nullの場合は何もしない.\r
*/\r
fireTableDataChanged();\r
}\r
}\r
- \r
+\r
public void setCheck(int[] selRows, boolean checked) {\r
if (selRows == null || selRows.length == 0) {\r
return;\r
\r
/**\r
* プリセット選択パネル\r
- * \r
+ *\r
* @author seraphy\r
*/\r
class ImportPresetSelectPanel extends ImportWizardCardPanel {\r
\r
private static final long serialVersionUID = 1L;\r
\r
- public static final String PANEL_NAME = "importPresetSelectPanel"; \r
- \r
+ public static final String PANEL_NAME = "importPresetSelectPanel";\r
+\r
private ImportPresetTableModel presetTableModel;\r
- \r
+\r
private ImportWizardDialog parent;\r
- \r
+\r
private JTable presetTable;\r
\r
private Action actSelectAll;\r
- \r
+\r
private Action actDeselectAll;\r
- \r
+\r
private Action actSelectUsedParts;\r
\r
public ImportPresetSelectPanel() {\r
}\r
\r
ImportPresetModel presetModel = presetTableModel.getRow(row);\r
- \r
+\r
// インポート先のプリセットを上書きする場合、もしくはデフォルトのパーツセットの場合は太字にする.\r
if (presetModel.isOverwrite() || presetTableModel.isDefaultPartsSet(row)) {\r
comp.setFont(getFont().deriveFont(Font.BOLD));\r
actSelectUsedParts.setEnabled(parent.importTypeSelectPanel.isImportPartsImages());\r
checkMissingParts();\r
}\r
- \r
+\r
public void checkMissingParts() {\r
Collection<PartsIdentifier> importedPartsIdentifiers = this.parent.importPartsSelectPanel.getImportedPartsIdentifiers();\r
presetTableModel.checkMissingParts(importedPartsIdentifiers);\r
this.parent.importPartsSelectPanel.selectByPartsIdentifiers(requirePartsIdentifiers);\r
checkMissingParts();\r
}\r
- \r
+\r
@Override\r
public boolean isReadyPrevious() {\r
return true;\r
}\r
- \r
+\r
@Override\r
public boolean isReadyNext() {\r
return false;\r
}\r
- \r
+\r
@Override\r
public boolean isReadyFinish() {\r
if (this.parent != null) {\r
}\r
return false;\r
}\r
- \r
+\r
@Override\r
public String doPrevious() {\r
- \r
+\r
return ImportPartsSelectPanel.PANEL_NAME;\r
}\r
- \r
+\r
@Override\r
public String doNext() {\r
return null;\r
}\r
- \r
+\r
public Collection<PartsSet> getSelectedPartsSets() {\r
return presetTableModel.getSelectedPartsSets();\r
}\r
- \r
+\r
/**\r
* デフォルトのパーツセットIDとして使用されることが推奨されるパーツセットIDを取得する.<br>\r
* 明示的なデフォルトのパーツセットIDがなければ、もしくは、 明示的に指定されているパーツセットIDが選択されているパーツセットの中になければ、\r
* 選択されているパーツセットの最初のアイテムを返す.<br>\r
* 選択しているパーツセットが一つもなければnullを返す.<br>\r
- * \r
+ *\r
* @return デフォルトのパーツセット\r
*/\r
public String getPrefferedDefaultPartsSetId() {\r
}\r
return defaultPartsSetId;\r
}\r
- \r
+\r
public void initModel(Collection<PartsSet> partsSets, String defaultPartsSetId, CharacterData presetImportTarget) {\r
presetTableModel.initModel(partsSets, defaultPartsSetId, presetImportTarget);\r
}\r
class ImportPresetModel {\r
\r
private boolean cheched;\r
- \r
+\r
private PartsSet partsSet;\r
- \r
+\r
private boolean overwrite;\r
- \r
+\r
private Collection<PartsIdentifier> missingPartsIdentifiers = Collections.emptySet();\r
- \r
+\r
public ImportPresetModel(PartsSet partsSet, boolean overwrite, boolean checked) {\r
if (partsSet == null) {\r
throw new IllegalArgumentException();\r
this.cheched = checked;\r
this.overwrite = overwrite;\r
}\r
- \r
+\r
public boolean isCheched() {\r
return cheched;\r
}\r
- \r
+\r
public void setCheched(boolean cheched) {\r
this.cheched = cheched;\r
}\r
- \r
+\r
public PartsSet getPartsSet() {\r
return partsSet;\r
}\r
- \r
+\r
public String getPartsSetName() {\r
return partsSet.getLocalizedName();\r
}\r
- \r
+\r
public void setPartsSetName(String name) {\r
if (name == null || name.trim().length() == 0) {\r
throw new IllegalArgumentException();\r
}\r
partsSet.setLocalizedName(name);\r
}\r
- \r
+\r
public Collection<PartsIdentifier> getMissingPartsIdentifiers() {\r
return missingPartsIdentifiers;\r
}\r
- \r
+\r
public boolean hasMissingParts() {\r
return true;\r
}\r
- \r
+\r
public boolean isOverwrite() {\r
return overwrite;\r
}\r
- \r
+\r
public boolean checkMissingParts(Collection<PartsIdentifier> importedPartsIdentifiers) {\r
HashSet<PartsIdentifier> missingPartsIdentifiers = new HashSet<PartsIdentifier>();\r
for (List<PartsIdentifier> partsIdentifiers : partsSet.values()) {\r
}\r
}\r
}\r
- \r
+\r
boolean modified = (!missingPartsIdentifiers.equals(this.missingPartsIdentifiers));\r
if (modified) {\r
this.missingPartsIdentifiers = missingPartsIdentifiers;\r
\r
private static final String[] COLUMN_NAMES; // = {"選択", "プリセット名",\r
// "不足するパーツ"};\r
- \r
+\r
private static final int[] COLUMN_WIDTHS; // = {50, 100, 200};\r
- \r
+\r
static {\r
Properties strings = LocalizedResourcePropertyLoader.getCachedInstance()\r
.getLocalizedProperties(ImportWizardDialog.STRINGS_RESOURCE);\r
- \r
+\r
COLUMN_NAMES = new String[] {\r
strings.getProperty("preset.column.check"),\r
strings.getProperty("preset.column.name"),\r
strings.getProperty("preset.column.missings"),\r
};\r
- \r
+\r
COLUMN_WIDTHS = new int[] {\r
Integer.parseInt(strings.getProperty("preset.column.check.size")),\r
Integer.parseInt(strings.getProperty("preset.column.name.size")),\r
Integer.parseInt(strings.getProperty("preset.column.missings.size")),\r
};\r
}\r
- \r
+\r
private String defaultPartsSetId;\r
- \r
+\r
public String getDefaultPartsSetId() {\r
return defaultPartsSetId;\r
}\r
- \r
+\r
public void setDefaultPartsSetId(String defaultPartsSetId) {\r
this.defaultPartsSetId = defaultPartsSetId;\r
}\r
- \r
+\r
public int getColumnCount() {\r
return COLUMN_NAMES.length;\r
}\r
- \r
+\r
@Override\r
public String getColumnName(int column) {\r
return COLUMN_NAMES[column];\r
}\r
- \r
+\r
@Override\r
public Class<?> getColumnClass(int columnIndex) {\r
switch (columnIndex) {\r
}\r
return String.class;\r
}\r
- \r
+\r
@Override\r
public boolean isCellEditable(int rowIndex, int columnIndex) {\r
if (columnIndex == 0 || columnIndex == 1) {\r
}\r
return "";\r
}\r
- \r
+\r
private String getMissingPartsIdentifiersString(ImportPresetModel rowModel) {\r
StringBuilder buf = new StringBuilder();\r
for (PartsIdentifier partsIdentifier : rowModel.getMissingPartsIdentifiers()) {\r
}\r
return buf.toString();\r
}\r
- \r
+\r
@Override\r
public void setValueAt(Object aValue, int rowIndex, int columnIndex) {\r
ImportPresetModel rowModel = getRow(rowIndex);\r
\r
/**\r
* 指定した行のパーツセットがデフォルトパーツセットであるか?\r
- * \r
+ *\r
* @param rowIndex\r
* 行インデックス\r
* @return デフォルトパーツセットであればtrue、そうでなければfalse\r
ImportPresetModel rowModel = getRow(rowIndex);\r
return rowModel.getPartsSet().getPartsSetId().equals(defaultPartsSetId);\r
}\r
- \r
+\r
public void adjustColumnModel(TableColumnModel columnModel) {\r
int mx = columnModel.getColumnCount();\r
for (int idx = 0; idx < mx; idx++) {\r
columnModel.getColumn(idx).setWidth(COLUMN_WIDTHS[idx]);\r
}\r
}\r
- \r
+\r
/**\r
* パーツセットリストを構築する.<br>\r
- * \r
+ *\r
* @param partsSets\r
* 登録するパーツセット\r
* @param defaultPartsSetId\r
// 新規の場合は既存パーツセットは空.\r
currentProfilesPartsSet = Collections.emptyMap();\r
}\r
- \r
+\r
// インポートもとのパーツセットをテープルモデルに登録する.\r
for (PartsSet partsSet : partsSets) {\r
String partsSetId = partsSet.getPartsSetId();\r
addRow(rowModel);\r
}\r
}\r
- \r
+\r
// デフォルトのパーツセットIDを設定、存在しない場合はnull\r
this.defaultPartsSetId = defaultPartsSetId;\r
- \r
+\r
sort();\r
}\r
- \r
+\r
public Collection<PartsSet> getSelectedPartsSets() {\r
ArrayList<PartsSet> partsSets = new ArrayList<PartsSet>();\r
for (ImportPresetModel rowModel : elements) {\r
fireTableDataChanged();\r
}\r
}\r
- \r
+\r
public void deselectAll() {\r
boolean modified = false;\r
for (ImportPresetModel rowModel : elements) {\r
fireTableDataChanged();\r
}\r
}\r
- \r
+\r
public void sort() {\r
Collections.sort(elements, new Comparator<ImportPresetModel>() {\r
public int compare(ImportPresetModel o1, ImportPresetModel o2) {\r
});\r
fireTableDataChanged();\r
}\r
- \r
+\r
public void checkMissingParts(Collection<PartsIdentifier> importedPartsIdentifiers) {\r
boolean changed = false;\r
- \r
+\r
for (ImportPresetModel rowModel : elements) {\r
if (rowModel.checkMissingParts(importedPartsIdentifiers)) {\r
changed = true;\r
}\r
}\r
- \r
+\r
if (changed) {\r
fireTableDataChanged();\r
}\r
import java.awt.event.ActionEvent;\r
import java.awt.event.ActionListener;\r
import java.awt.event.KeyEvent;\r
+import java.awt.event.MouseAdapter;\r
+import java.awt.event.MouseEvent;\r
import java.awt.event.WindowAdapter;\r
import java.awt.event.WindowEvent;\r
import java.io.File;\r
import java.io.StringWriter;\r
import java.net.URI;\r
import java.util.Collections;\r
+import java.util.Comparator;\r
import java.util.Properties;\r
import java.util.logging.Level;\r
import java.util.logging.Logger;\r
import javax.swing.table.TableCellRenderer;\r
import javax.swing.table.TableColumn;\r
import javax.swing.table.TableColumnModel;\r
+import javax.swing.table.TableRowSorter;\r
\r
import charactermanaj.graphics.filters.ColorConvertParameter;\r
import charactermanaj.graphics.io.ImageResource;\r
\r
protected static final String STRINGS_RESOURCE = "languages/informationdialog";\r
\r
+ private PartsSpecResolver partsSpecResolver;\r
+\r
private JTable informationTable;\r
\r
private InformationTableModel informationTableModel;\r
\r
+ private TableRowSorter<InformationTableModel> sorter;\r
+\r
private boolean modeOpen;\r
\r
- public InformationDialog(JFrame parent, PartsSpecResolver partsSpecResolver, PartsSet partsSet,\r
- LayerOrderMapper layerOrderMapper) {\r
- super(parent, true);\r
+ private Runnable closeHandler;\r
+\r
+ public InformationDialog(JFrame parent, PartsSpecResolver partsSpecResolver, Runnable closeHandler) {\r
+ super(parent, false);\r
+\r
+ this.partsSpecResolver = partsSpecResolver;\r
+ this.closeHandler = closeHandler;\r
\r
AppConfig appConfig = AppConfig.getInstance();\r
modeOpen = appConfig.isInformationDialogOpenMethod();\r
if (partsSpecResolver == null) {\r
throw new IllegalArgumentException("partsSpecResolver is null");\r
}\r
- if (partsSet == null) {\r
- throw new IllegalArgumentException("partsSet is null");\r
- }\r
\r
setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE);\r
addWindowListener(new WindowAdapter() {\r
\r
informationTableModel = new InformationTableModel();\r
\r
- final PNGFileImageHeaderReader pngHeaderReader = PNGFileImageHeaderReader.getInstance();\r
-\r
- PartsImageCollectionParser parser = new PartsImageCollectionParser(partsSpecResolver);\r
- parser.parse(partsSet, layerOrderMapper, new PartsImageCollectionHandler() {\r
- public void detectImageSource(PartsIdentifier partsIdentifier, Layer layer, int layerOrder,\r
- final ImageResource imageResource, ColorConvertParameter param) {\r
-\r
- AbstractAction act = new AbstractAction(strings.getProperty(modeOpen ? "btn.edit.open" : "btn.edit.edit")) {\r
- private static final long serialVersionUID = 1L;\r
- public void actionPerformed(ActionEvent e) {\r
- onOpen(imageResource);\r
- }\r
- };\r
-\r
- URI uri = imageResource.getURI();\r
- if (uri != null && "file".equals(uri.getScheme()) && DesktopUtilities.isSupported()) {\r
- act.setEnabled(true);\r
- } else {\r
- act.setEnabled(false);\r
- }\r
-\r
- PNGFileImageHeader pngHeader;\r
- try {\r
- pngHeader = pngHeaderReader.readHeader(uri);\r
- } catch (IOException ex) {\r
- logger.log(Level.WARNING, "PNG Header loading error.: " + uri, ex);\r
- pngHeader = null;\r
- }\r
-\r
- InformationModel information = new InformationModel(partsIdentifier, layer, layerOrder, imageResource,\r
- param, pngHeader, act);\r
- informationTableModel.addRow(information);\r
- }\r
- });\r
- informationTableModel.sort();\r
-\r
informationTable = new JTable(informationTableModel) {\r
private static final long serialVersionUID = 1L;\r
// セルの幅を大きいものにあわせる\r
informationTable.setDefaultRenderer(JButton.class, new ButtonCellRender());\r
informationTable.setDefaultEditor(JButton.class, new ButtonCellEditor());\r
\r
+ sorter = new TableRowSorter<InformationTableModel>(informationTableModel);\r
+ sorter.setSortable(InformationTableModel.ColumnDef.EDIT_BUTTON.ordinal(), false);\r
+ informationTable.setRowSorter(sorter);\r
+ informationTable.getTableHeader().addMouseListener(new MouseAdapter() {\r
+ @Override\r
+ public void mouseClicked(MouseEvent e) {\r
+ if (e.getClickCount() == 2) {\r
+ // ヘッダをダブルクリックでソート順を解除して、モデルの標準の順番に戻す。\r
+ sorter.setSortKeys(null);\r
+ e.consume();\r
+ }\r
+ }\r
+ });\r
+\r
// セルデータの幅にあわせる(事前に)\r
for (int row = 0; row < informationTable.getRowCount(); row++) {\r
for (int col = 0; col < informationTable.getColumnCount(); col++) {\r
setLocationRelativeTo(parent);\r
}\r
\r
+ public void showPartsInformation(PartsSet partsSet, LayerOrderMapper layerOrderMapper) {\r
+\r
+ final Properties strings = LocalizedResourcePropertyLoader\r
+ .getCachedInstance().getLocalizedProperties(STRINGS_RESOURCE);\r
+ final PNGFileImageHeaderReader pngHeaderReader = PNGFileImageHeaderReader.getInstance();\r
+\r
+ informationTableModel.clear();\r
+ if (partsSet != null) {\r
+ PartsImageCollectionParser parser = new PartsImageCollectionParser(partsSpecResolver);\r
+ parser.parse(partsSet, layerOrderMapper, new PartsImageCollectionHandler() {\r
+ private int serialOrder = 1;\r
+ public void detectImageSource(PartsIdentifier partsIdentifier, Layer layer, float layerOrder,\r
+ final ImageResource imageResource, ColorConvertParameter param) {\r
+\r
+ AbstractAction act = new AbstractAction(\r
+ strings.getProperty(modeOpen ? "btn.edit.open" : "btn.edit.edit")) {\r
+ private static final long serialVersionUID = 1L;\r
+ public void actionPerformed(ActionEvent e) {\r
+ onOpen(imageResource);\r
+ }\r
+ };\r
+\r
+ URI uri = imageResource.getURI();\r
+ if (uri != null && "file".equals(uri.getScheme()) && DesktopUtilities.isSupported()) {\r
+ act.setEnabled(true);\r
+ } else {\r
+ act.setEnabled(false);\r
+ }\r
+\r
+ PNGFileImageHeader pngHeader;\r
+ try {\r
+ pngHeader = pngHeaderReader.readHeader(uri);\r
+ } catch (IOException ex) {\r
+ logger.log(Level.WARNING, "PNG Header loading error.: " + uri, ex);\r
+ pngHeader = null;\r
+ }\r
+\r
+ InformationRowModel information = new InformationRowModel(serialOrder++, partsIdentifier, layer, layerOrder,\r
+ imageResource, param, pngHeader, act);\r
+ informationTableModel.addRow(information);\r
+ }\r
+ });\r
+ informationTableModel.sort();\r
+ }\r
+ }\r
+\r
protected void onClose() {\r
- dispose();\r
+ if (closeHandler != null) {\r
+ closeHandler.run();\r
+ } else {\r
+ dispose();\r
+ }\r
}\r
\r
protected void onCopyFilePath() {\r
StringWriter sw = new StringWriter();\r
PrintWriter pw = new PrintWriter(sw);\r
for (int selRow : informationTable.getSelectedRows()) {\r
- InformationModel information = informationTableModel.getRow(selRow);\r
+ InformationRowModel information = informationTableModel.getRow(selRow);\r
pw.println(information.getImageResourceName());\r
}\r
\r
}\r
}\r
\r
-class InformationTableModel extends AbstractTableModelWithComboBoxModel<InformationModel> {\r
+class InformationTableModel extends AbstractTableModelWithComboBoxModel<InformationRowModel> {\r
\r
- private enum ColumnDef {\r
+ protected enum ColumnDef {\r
PARTS_NAME("column.partsName", String.class) {\r
@Override\r
- public Object getValue(InformationModel information) {\r
+ public Object getValue(InformationRowModel information) {\r
return information.getPartsName();\r
}\r
},\r
CATEGORY("column.categoryName", String.class){\r
@Override\r
- public Object getValue(InformationModel information) {\r
+ public Object getValue(InformationRowModel information) {\r
return information.getCategoryName();\r
}\r
},\r
LAYER("column.layerName", String.class){\r
@Override\r
- public Object getValue(InformationModel information) {\r
+ public Object getValue(InformationRowModel information) {\r
return information.getLayerName();\r
}\r
},\r
DEFAULT_LAYER_ORDER("column.defaultLayerOrder", Integer.class){\r
@Override\r
- public Object getValue(InformationModel information) {\r
+ public Object getValue(InformationRowModel information) {\r
return information.getDefaultLayerOrder();\r
}\r
},\r
- ACTUAL_LAYER_ORDER("column.layerOrder", Integer.class){\r
+ ACTUAL_LAYER_ORDER("column.layerOrder", Float.class){\r
@Override\r
- public Object getValue(InformationModel information) {\r
+ public Object getValue(InformationRowModel information) {\r
return information.getLayerOrder();\r
}\r
},\r
+ ORDER("column.order", Float.class){\r
+ @Override\r
+ public Object getValue(InformationRowModel information) {\r
+ return information.getOrder();\r
+ }\r
+ },\r
IMAGE_SIZE("column.imagesize", String.class){\r
@Override\r
- public Object getValue(InformationModel information) {\r
+ public Object getValue(InformationRowModel information) {\r
return information.getImageSizeStr();\r
}\r
},\r
COLOR_TYPE("column.colortype", String.class){\r
@Override\r
- public Object getValue(InformationModel information) {\r
+ public Object getValue(InformationRowModel information) {\r
return information.getColorTypeStr();\r
}\r
},\r
EDIT_BUTTON("column.editbtn", JButton.class){\r
@Override\r
- public Object getValue(InformationModel information) {\r
+ public Object getValue(InformationRowModel information) {\r
return information.getButton();\r
}\r
};\r
return cls;\r
}\r
\r
- public abstract Object getValue(InformationModel information);\r
+ public abstract Object getValue(InformationRowModel information);\r
}\r
\r
private static final ColumnDef[] COLUMNS = ColumnDef.values();\r
}\r
\r
public Object getValueAt(int rowIndex, int columnIndex) {\r
- InformationModel information = getRow(rowIndex);\r
+ InformationRowModel information = getRow(rowIndex);\r
return COLUMNS[columnIndex].getValue(information);\r
}\r
\r
@Override\r
public boolean isCellEditable(int rowIndex, int columnIndex) {\r
if (JButton.class.equals(COLUMNS[columnIndex].getType())) {\r
- InformationModel information = getRow(rowIndex);\r
+ InformationRowModel information = getRow(rowIndex);\r
return information.getButton().isEnabled();\r
}\r
return false;\r
}\r
}\r
\r
-class InformationModel implements Comparable<InformationModel> {\r
+class InformationRowModel implements Comparable<InformationRowModel> {\r
+\r
+ private int order;\r
\r
private PartsIdentifier partsIdentifier;\r
\r
private Layer layer;\r
\r
- private int layerOrder;\r
+ private float layerOrder;\r
\r
private ImageResource imageResource;\r
\r
\r
private PNGFileImageHeader pngHeader;\r
\r
- public InformationModel(PartsIdentifier partsIdentifier, Layer layer,\r
- int layerOrder,\r
+ public InformationRowModel(int order, PartsIdentifier partsIdentifier, Layer layer,\r
+ float layerOrder,\r
ImageResource imageResource,\r
ColorConvertParameter colorConvertParameter,\r
PNGFileImageHeader pngHeader,\r
AbstractAction actOpen) {\r
+ this.order = order;\r
this.partsIdentifier = partsIdentifier;\r
this.layer = layer;\r
this.layerOrder = layerOrder;\r
if (obj == this) {\r
return true;\r
}\r
- if (obj != null && obj instanceof InformationModel) {\r
- InformationModel o = (InformationModel) obj;\r
+ if (obj != null && obj instanceof InformationRowModel) {\r
+ InformationRowModel o = (InformationRowModel) obj;\r
return partsIdentifier.equals(o.partsIdentifier)\r
&& layer.equals(o.layer);\r
}\r
return false;\r
}\r
\r
- public int compareTo(InformationModel o) {\r
- int ret = partsIdentifier.compareTo(o.partsIdentifier);\r
- if (ret == 0) {\r
- ret = layer.compareTo(o.layer);\r
- }\r
- if (ret == 0) {\r
- ret = imageResource.compareTo(o.imageResource);\r
+ /**\r
+ * パーツのレイヤー毎のソート順の定義\r
+ */\r
+ public static final Comparator<InformationRowModel> COMPARATOR = new Comparator<InformationRowModel>() {\r
+ @Override\r
+ public int compare(InformationRowModel o1, InformationRowModel o2) {\r
+ // 補正済みレイヤー重ね順\r
+ int ret = Float.compare(o1.layerOrder, o2.layerOrder);\r
+ if (ret == 0) {\r
+ // レイヤー重ね順\r
+ ret = o1.layer.compareTo(o2.layer);\r
+ }\r
+ if (ret == 0) {\r
+ // 定義順\r
+ ret = o1.order - o2.order;\r
+ }\r
+ if (ret == 0) {\r
+ // カテゴリ、レイヤー、パーツ名順(念のため)\r
+ ret = o1.partsIdentifier.compareTo(o2.partsIdentifier);\r
+ }\r
+ if (ret == 0) {\r
+ // リソース順(念のため)\r
+ ret = o1.imageResource.compareTo(o2.imageResource);\r
+ }\r
+ return ret;\r
}\r
- return ret;\r
+ };\r
+\r
+ public int compareTo(InformationRowModel o) {\r
+ return COMPARATOR.compare(this, o);\r
+ }\r
+\r
+ public int getOrder() {\r
+ return order;\r
}\r
\r
public String getPartsName() {\r
return this.layer.getOrder();\r
}\r
\r
- public int getLayerOrder() {\r
+ public float getLayerOrder() {\r
return this.layerOrder;\r
}\r
\r
public Object getCellEditorValue() {\r
return null;\r
}\r
-\r
}\r
-\r
import java.util.EventListener;\r
import java.util.EventObject;\r
import java.util.HashMap;\r
+import java.util.HashSet;\r
import java.util.List;\r
+import java.util.Locale;\r
import java.util.Map;\r
import java.util.Properties;\r
+import java.util.Set;\r
+import java.util.UUID;\r
import java.util.concurrent.atomic.AtomicInteger;\r
\r
import javax.swing.AbstractAction;\r
\r
import charactermanaj.Main;\r
import charactermanaj.model.CustomLayerOrder;\r
+import charactermanaj.model.CustomLayerOrderKey;\r
import charactermanaj.model.Layer;\r
import charactermanaj.model.ListChangeListener;\r
import charactermanaj.model.ObservableList;\r
new LayerOrderCustomizeDialogModel.ChangeListener() {\r
@Override\r
public void onChange(Change change) {\r
- String name = change.getName();\r
+ CustomLayerOrderKey orderKey = change.getName();\r
+ String name = orderKey.getDisplayName();\r
if (name == null || name.isEmpty()) {\r
// ※空文字の場合はcurrentプロパティの変更\r
return;\r
switch (change.getChangeType()) {\r
case ADD:\r
// レイヤーパターンが追加された場合\r
- if (patternsModel.indexOf(name) < 0) {\r
- patternsModel.add(name);\r
- patternsModel.setSelectedItem(name); // 登録された名前で選択しなおす為\r
+ if (patternsModel.indexOf(orderKey) < 0) {\r
+ patternsModel.add(orderKey);\r
+ patternsModel.setSelectedItem(orderKey); // 登録された名前で選択しなおす為\r
}\r
break;\r
\r
case REMOVE:\r
// レイヤーパターンが削除された場合\r
if (name != null) {\r
- patternsModel.remove(name);\r
+ patternsModel.remove(orderKey);\r
// 削除時は現在の選択もクリアする。(現在選択のものを削除しているので)\r
patternsModel.setSelectedItem(null);\r
}\r
\r
private JComboBox cmbPatternName = new JComboBox();\r
\r
- private SimpleComboBoxModel<String> patternsModel = new SimpleComboBoxModel<String>();\r
+ private SimpleComboBoxModel<CustomLayerOrderKey> patternsModel = new SimpleComboBoxModel<CustomLayerOrderKey>();\r
\r
private final JTable tblLayerOrder = new JTable();\r
\r
private final LayerOrderTableModel dataModel = new LayerOrderTableModel();\r
\r
- private String lastPatternName;\r
+ private CustomLayerOrderKey lastPatternName;\r
\r
private AbstractAction actRemove;\r
\r
\r
@Override\r
public void actionPerformed(ActionEvent e) {\r
- String name = (String) cmbPatternName.getSelectedItem();\r
- if (patternsModel.contains(name)) {\r
- onSelect(name);\r
+ CustomLayerOrderKey item = findBy(cmbPatternName.getSelectedItem());\r
+ if (item != null) {\r
+ if (patternsModel.contains(item)) {\r
+ onSelect(item);\r
+ }\r
}\r
}\r
});\r
\r
@Override\r
public void actionPerformed(ActionEvent e) {\r
- String name = (String) cmbPatternName.getSelectedItem();\r
- if (name != null && name.trim().length() > 0) {\r
- onSave(name.trim());\r
+ Object inp = cmbPatternName.getSelectedItem();\r
+ if (inp != null) {\r
+ CustomLayerOrderKey name = findBy(inp);\r
+ if (name == null) {\r
+ // 既存の一覧にないので新規キーの作成\r
+ String inpName = inp.toString();\r
+ name = makeOrderKey(inpName);\r
+ }\r
+ lastPatternName = name; // discard changesの確認が出ないように先に保存済みパターン名にしておく\r
+ onSave(name);\r
\r
- // 現在の入力でパターン名が増えたので、\r
- // このパターンを削除可能にするためUI更新を呼び出す\r
+ // 現在の入力のパターン名で削除可能にするためUI更新を呼び出す\r
onChangeComboText();\r
}\r
}\r
\r
@Override\r
public void actionPerformed(ActionEvent e) {\r
- String name = (String) cmbPatternName.getSelectedItem();\r
- onRemove(name);\r
+ CustomLayerOrderKey name = findBy(cmbPatternName.getSelectedItem());\r
+ if (name != null) {\r
+ onRemove(name);\r
+ }\r
}\r
};\r
\r
*/\r
protected void onChangeComboText() {\r
BasicComboBoxEditor cmbEditor = (BasicComboBoxEditor) cmbPatternName.getEditor();\r
- String inpName = (String) cmbEditor.getItem();\r
- if (inpName == null || inpName.trim().length() == 0) {\r
+ Object inp = cmbEditor.getItem();\r
+ if (inp == null || (inp instanceof String && ((String) inp).trim().length() == 0)) {\r
// 空の場合\r
actRemove.setEnabled(false);\r
actSave.setEnabled(false);\r
} else {\r
- actRemove.setEnabled(patternsModel.contains(inpName)); // 既存のパターン名と合致すれば削除可\r
+ actRemove.setEnabled(patternsModel.contains(findBy(inp))); // 既存のパターン名と合致すれば削除可\r
actSave.setEnabled(true); // 文字が入力されていれば登録・更新可\r
}\r
}\r
\r
/**\r
+ * 引数が文字列の場合、コンボボックスに登録されているパターンリストの表示名と一致するオブジェクトを取得する。\r
+ * なければnullを返す。\r
+ * 引数がCustomLayerOrderKey型の場合は、そのまま返す。\r
+ * nullの場合はnullを返す。\r
+ * @param inp 文字列またはCustomLayerOrderKey\r
+ * @return CustomLayerOrderKey、またはnull\r
+ */\r
+ private CustomLayerOrderKey findBy(Object inp) {\r
+ if (inp instanceof CustomLayerOrderKey) {\r
+ return (CustomLayerOrderKey) inp;\r
+ }\r
+ if (inp instanceof String) {\r
+ String inpName = (String) inp;\r
+ int mx = patternsModel.size();\r
+ for (int idx = 0; idx < mx; idx++) {\r
+ CustomLayerOrderKey item = patternsModel.get(idx);\r
+ if (item.toString().equals(inpName)) {\r
+ return item;\r
+ }\r
+ }\r
+ }\r
+ return null;\r
+ }\r
+\r
+ /**\r
+ * キーを作成する\r
+ * @param displayName\r
+ * @return\r
+ */\r
+ private CustomLayerOrderKey makeOrderKey(String displayName) {\r
+\r
+ // 現在保持しているIDの一覧を取得する\r
+ Set<String> usedIds = new HashSet<String>();\r
+ int mx = patternsModel.size();\r
+ for (int idx = 0; idx < mx; idx++) {\r
+ CustomLayerOrderKey key = patternsModel.get(idx);\r
+ usedIds.add(key.getId());\r
+ }\r
+\r
+ // IDとしてふさわしいように空白は除外しておく\r
+ String canonicalName = displayName.replace(" ", "_");\r
+ if (!canonicalName.matches("[A-Za-z0-9_]+")) {\r
+ // アルファベット以外が含まれている場合はランダムなUUIDにする\r
+ canonicalName = UUID.randomUUID().toString();\r
+ }\r
+\r
+ // 名前をもとにIDを衝突しないように振る\r
+ String id = canonicalName;\r
+ for (int idx = 2;; idx++) {\r
+ if (!usedIds.contains(id)) {\r
+ // 既存のIDではないのでOK.\r
+ break;\r
+ }\r
+ id = canonicalName + idx;\r
+ }\r
+\r
+ // 現在のロケールでローカライズ文字列を構築しておく\r
+ Map<String, String> langMap = new HashMap<String, String>();\r
+ Locale locale = Locale.getDefault();\r
+ String lang = locale.getLanguage();\r
+ langMap.put(lang, displayName);\r
+ langMap.put(CustomLayerOrderKey.DEFAULT_NAME_KEY, displayName);\r
+\r
+ return new CustomLayerOrderKey(id, displayName, langMap);\r
+ }\r
+\r
+ /**\r
* カラム定義\r
*/\r
private enum ColumnDef {\r
return item.getLayer().getOrder();\r
}\r
},\r
- CUSTOM_ORDER("column.order", Integer.class, 80, true) {\r
+ CUSTOM_ORDER("column.order", Float.class, 80, true) {\r
@Override\r
public Object getValue(CustomLayerOrder item) {\r
return item.getLayerOrder();\r
ret = o1.getLayer().compareTo(o2.getLayer());\r
}\r
if (ret == 0) {\r
- ret = o1.getLayerOrder() - o2.getLayerOrder();\r
+ ret = Float.compare(o1.getLayerOrder(), o2.getLayerOrder());\r
}\r
return ret;\r
}\r
* @param layer\r
* @param layerOrder\r
*/\r
- public void add(PartsCategory category, Layer layer, int layerOrder) {\r
+ public void add(PartsCategory category, Layer layer, float layerOrder) {\r
if (category == null || layer == null) {\r
throw new NullPointerException("category, layerにnullは指定できません。");\r
}\r
public void setValueAt(Object aValue, int rowIndex, int columnIndex) {\r
if (columns[columnIndex].isEditable()) {\r
CustomLayerOrder item = layerOrderList.get(rowIndex);\r
- item.setLayerOrder(((Number) aValue).intValue());\r
+ if (aValue != null) {\r
+ item.setLayerOrder(((Number) aValue).floatValue());\r
+ }\r
}\r
}\r
\r
final Properties strings = LocalizedResourcePropertyLoader\r
.getCachedInstance().getLocalizedProperties(STRINGS_RESOURCE);\r
\r
- if (lastPatternName == null || lastPatternName.isEmpty()) {\r
+ if (lastPatternName == null) {\r
// パターンをロードしていない場合\r
ObservableList<CustomLayerOrder> oldLayerOrderList = model.getCurrentList();\r
if (!oldLayerOrderList.equals(dataModel.getList())) {\r
* レイヤーパターン名を選択した場合\r
* @param name\r
*/\r
- protected void onSelect(String name) {\r
+ protected void onSelect(CustomLayerOrderKey name) {\r
if (canDiscardChanges()) {\r
// 選択したパターンのロード\r
ObservableList<CustomLayerOrder> layerOrderList = model.getCopy(name);\r
}\r
\r
dataModel.setList(layerOrderList);\r
- String old = this.lastPatternName;\r
+ CustomLayerOrderKey old = this.lastPatternName;\r
this.lastPatternName = name;\r
\r
firePropertyChange("lastPatternName", old, name);\r
* 最後に選択したパターン名を取得する\r
* @return\r
*/\r
- public String getLastPatternName() {\r
+ public CustomLayerOrderKey getLastPatternName() {\r
return lastPatternName;\r
}\r
\r
* 現在の編集をパターン名をつけて保存し、現在の選択パターン名とする。\r
* @param name\r
*/\r
- protected void onSave(String name) {\r
+ protected void onSave(CustomLayerOrderKey name) {\r
model.put(name, dataModel.getList());\r
\r
- String old = this.lastPatternName;\r
+ CustomLayerOrderKey old = this.lastPatternName;\r
if (old == null ? name != null : !old.equals(name)) {\r
this.lastPatternName = name;\r
firePropertyChange("lastPatternName", old, name);\r
* 指定したパターン名を削除して、選択状態を解除する。\r
* @param name\r
*/\r
- protected void onRemove(String name) {\r
+ protected void onRemove(CustomLayerOrderKey name) {\r
final Properties strings = LocalizedResourcePropertyLoader\r
.getCachedInstance().getLocalizedProperties(STRINGS_RESOURCE);\r
\r
return;\r
}\r
\r
+ model.setCurrentList(dataModel.getList()); // 無名の編集状態になるため、discard changesで判定されないように。\r
model.remove(name);\r
\r
- String old = this.lastPatternName;\r
+ CustomLayerOrderKey old = this.lastPatternName;\r
if (old != null) {\r
this.lastPatternName = null;\r
firePropertyChange("lastPatternName", old, null);\r
/**\r
* 順序\r
*/\r
- private int order;\r
+ private float order;\r
\r
/**\r
* 入力確定可能であるか?\r
return selectedLayer;\r
}\r
\r
- public void setOrder(int order) {\r
- int old = this.order;\r
+ public void setOrder(float order) {\r
+ float old = this.order;\r
if (old != order) {\r
this.order = order;\r
propChangeSupport.firePropertyChange(ORDER, old, order);\r
}\r
}\r
\r
- public int getOrder() {\r
+ public float getOrder() {\r
return order;\r
}\r
\r
private void initOrder() {\r
updaingTxtOrderModel.incrementAndGet();\r
try {\r
- txtOrder.setText(Integer.toString(model.getOrder()));\r
+ txtOrder.setText(Float.toString(model.getOrder()));\r
updateTxtOrderState(false);\r
\r
} finally {\r
boolean error = true;\r
try {\r
if (text != null && text.length() > 0) {\r
- int order = Integer.parseInt(text);\r
+ float order = Float.parseFloat(text);\r
model.setOrder(order);\r
error = false;\r
}\r
* モデルのorderが変更されたので画面に反映する\r
*/\r
protected void updateTxtOrder() {\r
- int order = model.getOrder();\r
- Integer old;\r
+ float order = model.getOrder();\r
+ Float old;\r
try {\r
- old = Integer.parseInt(txtOrder.getText());\r
+ old = Float.parseFloat(txtOrder.getText());\r
} catch (RuntimeException ex) {\r
old = null;\r
}\r
// 現在の入力している値と数値的に異なる場合のみ再設定する\r
// (自分のテキストボックス変更イベントによりモデルが変更され、その結果、\r
// テキストボックスへの値変更が呼び出された場合に状態エラーが発生する。)\r
- txtOrder.setText(Integer.toString(order));\r
+ txtOrder.setText(Float.toString(order));\r
updateTxtOrderState(false);\r
}\r
}\r
if (model.isResult()) {\r
PartsCategory category = model.getSelectedPartsCategory();\r
Layer layer = model.getSelectedLayer();\r
- int layerOrder = model.getOrder();\r
+ float layerOrder = model.getOrder();\r
dataModel.add(category, layer, layerOrder);\r
}\r
}\r
}\r
\r
/**\r
+ * 無名のキー名\r
+ */\r
+ public static final CustomLayerOrderKey ANONYMOUS = new CustomLayerOrderKey("", "", null);\r
+\r
+ /**\r
* イベント\r
*/\r
public class Change extends EventObject {\r
/**\r
* レイヤーパターン名\r
*/\r
- private String name;\r
+ private CustomLayerOrderKey name;\r
\r
/**\r
* 変更タイプ\r
*/\r
private ChangeType changeType;\r
\r
- public Change(LayerOrderCustomizeDialogModel source, String name, ChangeType changeType) {\r
+ public Change(LayerOrderCustomizeDialogModel source, CustomLayerOrderKey name, ChangeType changeType) {\r
super(source);\r
this.name = name;\r
this.changeType = changeType;\r
}\r
\r
- public String getName() {\r
+ public CustomLayerOrderKey getName() {\r
return name;\r
}\r
\r
/**\r
* レイヤー名パターンを保持する。(patternsMapから導出され、以後、監視される。)\r
*/\r
- private final ObservableList<String> patternNames = new ObservableList<String>();\r
+ private final ObservableList<CustomLayerOrderKey> patternNames = new ObservableList<CustomLayerOrderKey>();\r
\r
/**\r
* レイヤーパターン名をキーとして、レイヤーの構成リストを値とするマップ。\r
* キーはpatternNamesの監視リストと連携する。\r
*/\r
- private final Map<String, List<CustomLayerOrder>> patternsMap = new HashMap<String, List<CustomLayerOrder>>();\r
+ private final Map<CustomLayerOrderKey, List<CustomLayerOrder>> patternsMap =\r
+ new HashMap<CustomLayerOrderKey, List<CustomLayerOrder>>();\r
\r
/**\r
* レイヤー編集画面の初期値\r
* コンストラクタ\r
*/\r
public LayerOrderCustomizeDialogModel() {\r
- patternNames.addListChangeListener(new ListChangeListener<String>() {\r
+ patternNames.addListChangeListener(new ListChangeListener<CustomLayerOrderKey>() {\r
@Override\r
- public void onChanged(Change<? extends String> c) {\r
+ public void onChanged(Change<? extends CustomLayerOrderKey> c) {\r
switch (c.getType()) {\r
case ADD:\r
// パターン名が追加された場合は、あわせて導出元のマップも追加する\r
- String newName = c.getNewValue();\r
+ CustomLayerOrderKey newName = c.getNewValue();\r
if (!patternsMap.containsKey(newName)) {\r
// まだマップに存在しなければ空のリストを作成しておく\r
patternsMap.put(newName, new ArrayList<CustomLayerOrder>());\r
\r
case REMOVE:\r
// パターン名が削除された場合は、導出元のマップも削除する。\r
- String oldName = c.getOldValue();\r
+ CustomLayerOrderKey oldName = c.getOldValue();\r
patternsMap.remove(oldName);\r
fireEvent(ChangeListener.ChangeType.REMOVE, oldName);\r
break;\r
* @param type 変更タイプ\r
* @param name 名前\r
*/\r
- protected void fireEvent(ChangeListener.ChangeType type, String name) {\r
+ protected void fireEvent(ChangeListener.ChangeType type, CustomLayerOrderKey name) {\r
// Guaranteed to return a non-null array\r
Object[] ll = listeners.getListenerList();\r
// Process the listeners last to first, notifying\r
if (!currentList.equals(this.currentList)) {\r
this.currentList = copyWithoutListeners(\r
currentList != null ? currentList : new ArrayList<CustomLayerOrder>());\r
- fireEvent(ChangeListener.ChangeType.MODIFY, "");\r
+ fireEvent(ChangeListener.ChangeType.MODIFY, ChangeListener.ANONYMOUS);\r
}\r
}\r
\r
- public ObservableList<String> getPatternNames() {\r
+ public ObservableList<CustomLayerOrderKey> getPatternNames() {\r
return patternNames;\r
}\r
\r
- public ObservableList<CustomLayerOrder> getCopy(String name) {\r
+ public ObservableList<CustomLayerOrder> getCopy(CustomLayerOrderKey name) {\r
return copyWithoutListeners(patternsMap.get(name));\r
}\r
\r
- public void put(String name, List<CustomLayerOrder> layerOrderList) {\r
+ public void put(CustomLayerOrderKey name, List<CustomLayerOrder> layerOrderList) {\r
boolean exist = patternsMap.containsKey(name);\r
patternsMap.put(name, copyWithoutListeners(layerOrderList));\r
if (!exist) {\r
}\r
}\r
\r
- public void remove(String name) {\r
+ public void remove(CustomLayerOrderKey name) {\r
if (patternNames.contains(name)) {\r
// 名前の削除によりリスナーでマップも削除される\r
patternNames.remove(name);\r
import java.io.File;\r
import java.io.IOException;\r
import java.lang.reflect.InvocationTargetException;\r
-import java.net.URI;\r
import java.util.ArrayList;\r
import java.util.Collections;\r
import java.util.HashMap;\r
+import java.util.HashSet;\r
import java.util.List;\r
import java.util.Map;\r
import java.util.Properties;\r
+import java.util.Set;\r
import java.util.TreeMap;\r
import java.util.UUID;\r
import java.util.logging.Level;\r
import charactermanaj.model.CharacterDataChangeObserver;\r
import charactermanaj.model.ColorGroup;\r
import charactermanaj.model.CustomLayerOrder;\r
-import charactermanaj.model.IndependentPartsSetInfo;\r
+import charactermanaj.model.CustomLayerOrderKey;\r
import charactermanaj.model.PartsCategory;\r
import charactermanaj.model.PartsColorInfo;\r
import charactermanaj.model.PartsColorManager;\r
import charactermanaj.model.PartsSet;\r
import charactermanaj.model.RecommendationURL;\r
import charactermanaj.model.WorkingSet;\r
-import charactermanaj.model.WorkingSet2;\r
import charactermanaj.model.io.CharacterDataPersistent;\r
import charactermanaj.model.io.CustomLayerOrderPersist;\r
import charactermanaj.model.io.CustomLayerOrderPersist.CustomLayerOrderPersistListener;\r
@Override\r
public void notifyChangeCustomLayerOrder(CustomLayerOrderPersistListener.Change e) {\r
if (!e.getSource().equals(characterData)) { // 自分が送信元の場合は何もしない\r
- Map<String, List<CustomLayerOrder>> map = e.getCustomLayerOrderMap();\r
+ Map<CustomLayerOrderKey, List<CustomLayerOrder>> map = e.getCustomLayerOrderMap();\r
if (map != null) {\r
customLayerPatternMgr.setMap(map);\r
requestPreview();\r
for (Component comp : contentPane.getComponents()) {\r
contentPane.remove(comp);\r
}\r
+\r
+ // 開いている情報ダイアログを閉じる\r
+ closeInformationDialog();\r
+\r
// 開いている検索ダイアログを閉じる\r
closeSearchDialog();\r
\r
imageBuilder = new AsyncImageBuilder(imageLoader);\r
partsSelectionManager = new PartsSelectionManager(partsColorManager,\r
new PartsSelectionManager.ImageBgColorProvider() {\r
- public Color getImageBgColor() {\r
- return wallpaperInfo.getBackgroundColor();\r
- }\r
- public void setImageBgColor(Color imageBgColor) {\r
- applyBackgroundColorOnly(imageBgColor);\r
- }\r
- });\r
+ public Color getImageBgColor() {\r
+ return wallpaperInfo.getBackgroundColor();\r
+ }\r
+\r
+ public void setImageBgColor(Color imageBgColor) {\r
+ applyBackgroundColorOnly(imageBgColor);\r
+ }\r
+ }, new PartsSelectionManager.CustomLayerPatternsIDProvider() {\r
+ @Override\r
+ public Set<String> getActivePatternIds() {\r
+ Set<CustomLayerOrderKey> keys = customLayerPatternMgr.getActivePatternNames();\r
+ Set<String> ids = new HashSet<String>();\r
+ for (CustomLayerOrderKey key : keys) {\r
+ ids.add(key.getId());\r
+ }\r
+ return ids;\r
+ }\r
+ @Override\r
+ public void setActivePatternIds(Set<String> names) {\r
+ Set<CustomLayerOrderKey> keys = new HashSet<CustomLayerOrderKey>();\r
+ for (CustomLayerOrderKey key : customLayerPatternMgr.getMap().keySet()) {\r
+ if (names.contains(key.getId())) {\r
+ keys.add(key);\r
+ }\r
+ }\r
+ customLayerPatternMgr.setActivePatternNames(keys);\r
+ }\r
+ });\r
colorGroupCoordinator = new ColorGroupCoordinator(partsSelectionManager, partsColorManager);\r
partsColorCoordinator = new PartsColorCoordinator(characterData, partsColorManager, colorGroupCoordinator);\r
PartsImageDirectoryWatchAgentFactory agentFactory = PartsImageDirectoryWatchAgentFactory.getFactory();\r
protected void onSelectedCustomLayerMenu(JMenu menu) {\r
// メニューの再構築\r
ArrayList<JMenuItem> menuItems = new ArrayList<JMenuItem>();\r
- for (Map.Entry<String, List<CustomLayerOrder>> entry : customLayerPatternMgr.getMap().entrySet()) {\r
- final String name = entry.getKey();\r
- final JCheckBoxMenuItem menuItem = new JCheckBoxMenuItem(name);\r
- menuItem.setSelected(customLayerPatternMgr.isSelected(name));\r
+ for (Map.Entry<CustomLayerOrderKey, List<CustomLayerOrder>> entry :\r
+ customLayerPatternMgr.getMap().entrySet()) {\r
+ final CustomLayerOrderKey patternKey = entry.getKey();\r
+ final String displayName = patternKey.getDisplayName();\r
+ final JCheckBoxMenuItem menuItem = new JCheckBoxMenuItem(displayName);\r
+ menuItem.setSelected(customLayerPatternMgr.isSelected(patternKey));\r
menuItem.addActionListener(new ActionListener() {\r
@Override\r
public void actionPerformed(ActionEvent e) {\r
- customLayerPatternMgr.setSelected(name, menuItem.isSelected());\r
+ customLayerPatternMgr.setSelected(patternKey, menuItem.isSelected());\r
requestPreview();\r
}\r
});\r
mnuRecomendation.remove(0);\r
}\r
\r
- // お勧めリンクの定義がない場合はデフォルトを用いる.(明示的な空の場合は何もしない.)\r
- CharacterDataPersistent persist = CharacterDataPersistent.getInstance();\r
- persist.compensateRecommendationList(characterData);\r
-\r
// お勧めリンクメニューを作成する.\r
List<RecommendationURL> recommendations = characterData.getRecommendationURLList();\r
if (recommendations != null) {\r
*\r
* @param requestPartsSet\r
* 表示するパーツセット(名前は設定されていなくて良い。お気に入り側を使うので。)\r
- * @param markColorChange\r
- * 色情報が異なる場合に末尾に「*」マークをつける場合はtrue\r
+ * @param markColorOrCustomLayerChange\r
+ * è\89²æ\83\85å ±ã\81¾ã\81\9fã\81¯ã\82«ã\82¹ã\82¿ã\83 ã\83¬ã\82¤ã\83¤ã\83¼ã\81\8cç\95°ã\81ªã\82\8bå ´å\90\88ã\81«æ\9c«å°¾ã\81«ã\80\8c*ã\80\8dã\83\9eã\83¼ã\82¯ã\82\92ã\81¤ã\81\91ã\82\8bå ´å\90\88ã\81¯true\r
*/\r
- private String getSuggestPartsSetName(PartsSet requestPartsSet, boolean markColorChange) {\r
+ private String getSuggestPartsSetName(PartsSet requestPartsSet, boolean markColorOrCustomLayerChange) {\r
String partsSetTitle = null;\r
if (lastUsePresetParts != null &&\r
PartsSet.isSameStructure(requestPartsSet, lastUsePresetParts)) {\r
partsSetTitle = lastUsePresetParts.getLocalizedName();\r
- if (markColorChange && !PartsSet.isSameColor(requestPartsSet, lastUsePresetParts)) {\r
+ if (markColorOrCustomLayerChange && (!PartsSet.isSameColor(requestPartsSet, lastUsePresetParts)\r
+ || !PartsSet.isSameCustomLayers(requestPartsSet, lastUsePresetParts))) {\r
if (partsSetTitle != null) {\r
partsSetTitle += "*";\r
}\r
public void run() {\r
PartsSet partsSet = partsSelectionManager.createPartsSet();\r
result[0] = partsSet;\r
+\r
+ // 表示対象のパーツセットの情報で更新する (情報ダイアログが開いていれば)\r
+ if (informationDialog != null) {\r
+ informationDialog.showPartsInformation(partsSet, customLayerPatternMgr);\r
+ }\r
}\r
};\r
if (SwingUtilities.isEventDispatchThread()) {\r
}\r
\r
/**\r
+ * 情報ダイアログを閉じる\r
+ */\r
+ protected void closeInformationDialog() {\r
+ if (informationDialog != null) {\r
+ informationDialog.dispose();\r
+ informationDialog = null;\r
+ }\r
+ }\r
+\r
+ /**\r
* クリップボードにコピー\r
*\r
* @param screenImage\r
workingSet.setCharacterDocBase(characterData.getDocBase());\r
workingSet.setCharacterDataRev(characterData.getRev());\r
PartsSet partsSet = partsSelectionManager.createPartsSet();\r
- workingSet.setPartsSet(partsSet);\r
+ workingSet.setCurrentPartsSet(partsSet);\r
workingSet.setPartsColorInfoMap(characterData\r
.getPartsColorManager().getPartsColorInfoMap());\r
workingSet.setLastUsedSaveDir(imageSaveHelper.getLastUsedSaveDir());\r
protected void loadCustomLayerOrder() {\r
try {\r
CustomLayerOrderPersist persist = CustomLayerOrderPersist.newInstance(characterData);\r
- Map<String, List<CustomLayerOrder>> map = persist.load();\r
+ Map<CustomLayerOrderKey, List<CustomLayerOrder>> map = persist.load();\r
if (map != null) {\r
customLayerPatternMgr.setMap(map);\r
}\r
return false;\r
}\r
try {\r
- WorkingSetPersist workingSetPersist = WorkingSetPersist\r
- .getInstance();\r
- WorkingSet2 workingSet2 = workingSetPersist\r
+ WorkingSetPersist workingSetPersist = WorkingSetPersist.getInstance();\r
+ WorkingSet workingSet = workingSetPersist\r
.loadWorkingSet(characterData);\r
- if (workingSet2 == null) {\r
+ if (workingSet == null) {\r
// ワーキングセットがない場合.\r
+ // もしくは現在のキャラクターデータと互換性がない場合\r
return false;\r
}\r
\r
+ // ウインドウのサイズ、位置の復元\r
AppConfig appConfig = AppConfig.getInstance();\r
- Rectangle windowRect = workingSet2.getWindowRect();\r
+ Rectangle windowRect = workingSet.getWindowRect();\r
if (appConfig.isEnableRestoreWindow() && windowRect != null) {\r
// 位置の復元\r
GraphicsEnvironment genv = GraphicsEnvironment.getLocalGraphicsEnvironment();\r
dim.height = 100;\r
}\r
setSize(dim);\r
+\r
} else {\r
// デフォルトのウィンドウ位置とサイズ\r
setDefaultWindowLocation();\r
}\r
\r
- URI docBase = characterData.getDocBase();\r
- if (docBase != null\r
- && !docBase.equals(workingSet2.getCharacterDocBase())) {\r
- // docBaseが一致せず\r
- return false;\r
- }\r
- String sig = characterData.toSignatureString();\r
- if (!sig.equals(workingSet2.getCharacterDataSig())) {\r
- // 構造が一致せず.\r
- return false;\r
- }\r
-\r
// パーツの色情報を復元する.\r
Map<PartsIdentifier, PartsColorInfo> partsColorInfoMap = characterData\r
.getPartsColorManager().getPartsColorInfoMap();\r
- workingSet2.createCompatible(characterData, partsColorInfoMap);\r
+ partsColorInfoMap.putAll(workingSet.getPartsColorInfoMap());\r
\r
// 選択されているパーツの復元\r
- IndependentPartsSetInfo partsSetInfo = workingSet2\r
- .getCurrentPartsSet();\r
- if (partsSetInfo != null) {\r
- PartsSet partsSet = IndependentPartsSetInfo.convertPartsSet(\r
- partsSetInfo, characterData, false);\r
+ PartsSet partsSet = workingSet.getCurrentPartsSet();\r
+ if (partsSet != null) {\r
selectPresetParts(partsSet);\r
\r
- // 最後に選択したお気に入り情報の復元\r
- IndependentPartsSetInfo lastUsePresetPartsInfo = workingSet2\r
- .getLastUsePresetParts();\r
- if (lastUsePresetPartsInfo != null\r
- && lastUsePresetPartsInfo.getId() != null\r
- && lastUsePresetPartsInfo.getId().trim().length() > 0) {\r
- PartsSet lastUsePresetParts = IndependentPartsSetInfo\r
- .convertPartsSet(lastUsePresetPartsInfo,\r
- characterData, false);\r
+ // 最後に選択されたパーツセット名と選択されているパーツセットが同一であれば名前を表示する\r
+ PartsSet lastUsePresetParts = workingSet.getLastUsePresetParts();\r
+ if (lastUsePresetParts != null) {\r
if (lastUsePresetParts.isSameStructure(partsSet)) {\r
this.lastUsePresetParts = lastUsePresetParts;\r
showPresetName(lastUsePresetParts);\r
}\r
\r
// 最後に保存したディレクトリを復元する.\r
- imageSaveHelper.setLastUseSaveDir(workingSet2.getLastUsedSaveDir());\r
- ExportWizardDialog.setLastUsedDir(workingSet2\r
+ imageSaveHelper.setLastUseSaveDir(workingSet.getLastUsedSaveDir());\r
+ ExportWizardDialog.setLastUsedDir(workingSet\r
.getLastUsedExportDir());\r
\r
// 壁紙情報を取得する.\r
- WallpaperInfo wallpaperInfo = workingSet2.getWallpaperInfo();\r
+ WallpaperInfo wallpaperInfo = workingSet.getWallpaperInfo();\r
if (wallpaperInfo != null) {\r
// 壁紙情報を保存し、その情報をもとに背景を再描画する.\r
// (適用に失敗した場合はエラーは無視し、壁紙情報は保存しない.)\r
}\r
\r
// ズーム状態を復元する\r
- Double zoomFactor = workingSet2.getZoomFactor();\r
+ Double zoomFactor = workingSet.getZoomFactor();\r
if (appConfig.isEnableRestoreWindow() && zoomFactor != null) {\r
previewPane.setZoomFactor(zoomFactor);\r
- final Point viewPosition = workingSet2.getViewPosition();\r
+ final Point viewPosition = workingSet.getViewPosition();\r
if (viewPosition != null) {\r
previewPane.setViewPosition(viewPosition);\r
}\r
}\r
}\r
\r
+ private InformationDialog informationDialog;\r
+\r
protected void onInformation() {\r
if (!characterData.isValid()) {\r
Toolkit tk = Toolkit.getDefaultToolkit();\r
}\r
\r
PartsSet partsSet = partsSelectionManager.createPartsSet();\r
- InformationDialog infoDlg = new InformationDialog(this, characterData, partsSet, customLayerPatternMgr);\r
- infoDlg.setVisible(true);\r
+ if (informationDialog == null) {\r
+ informationDialog = new InformationDialog(this, characterData, new Runnable() {\r
+ @Override\r
+ public void run() {\r
+ closeInformationDialog();\r
+ }\r
+ });\r
+ }\r
+ informationDialog.showPartsInformation(partsSet, customLayerPatternMgr);\r
+ informationDialog.setVisible(true);\r
}\r
\r
protected void onManageCustomLayer() {\r
\r
// 現在保持しているレイヤーパターンの一覧を取得する\r
final LayerOrderCustomizeDialogModel layerOrderCustomDialogModel = new LayerOrderCustomizeDialogModel();\r
- for (Map.Entry<String, List<CustomLayerOrder>> entry : customLayerPatternMgr.getMap().entrySet()) {\r
- String patternName = entry.getKey();\r
+ for (Map.Entry<CustomLayerOrderKey, List<CustomLayerOrder>> entry :\r
+ customLayerPatternMgr.getMap().entrySet()) {\r
+ CustomLayerOrderKey orderKey = entry.getKey();\r
List<CustomLayerOrder> customLayerOrderList = entry.getValue();\r
- layerOrderCustomDialogModel.put(patternName, customLayerOrderList);\r
+ layerOrderCustomDialogModel.put(orderKey, customLayerOrderList);\r
}\r
\r
// 現在選択しているアクティブなレイヤーパターンを取得する\r
public void onChange(Change change) {\r
try {\r
// 編集されたレイヤーパターンの一覧を保存する。\r
- Map<String, List<CustomLayerOrder>> customLayerPatternMap =\r
- new HashMap<String, List<CustomLayerOrder>>();\r
- for (String patternName : layerOrderCustomDialogModel.getPatternNames()) {\r
- List<CustomLayerOrder> customLayerOrderList = layerOrderCustomDialogModel.getCopy(patternName);\r
+ Map<CustomLayerOrderKey, List<CustomLayerOrder>> customLayerPatternMap =\r
+ new HashMap<CustomLayerOrderKey, List<CustomLayerOrder>>();\r
+ for (CustomLayerOrderKey patternKey : layerOrderCustomDialogModel.getPatternNames()) {\r
+ List<CustomLayerOrder> customLayerOrderList = layerOrderCustomDialogModel.getCopy(patternKey);\r
if (customLayerOrderList != null) {\r
- customLayerPatternMap.put(patternName, customLayerOrderList);\r
+ customLayerPatternMap.put(patternKey, customLayerOrderList);\r
}\r
}\r
\r
layerOrderCustomDlg.setVisible(true);\r
\r
// 最後に選択または保存したパターン名をデフォルトで選択状態とする\r
- String lastPatternName = layerOrderCustomDlg.getLastPatternName();\r
- if (lastPatternName != null && lastPatternName.trim().length() > 0) {\r
+ CustomLayerOrderKey lastPatternName = layerOrderCustomDlg.getLastPatternName();\r
+ if (lastPatternName != null) {\r
customLayerPatternMgr.setSelected(lastPatternName, true);\r
}\r
\r
if (!includeColorInfo) {\r
// カラー情報を除去する.\r
partsSet.removeColorInfo();\r
+ // カスタムレイヤー情報を除去する\r
+ partsSet.setActiveCustomLayerPatternIds(null);\r
}\r
\r
// 新規の場合、もしくは上書きしない場合はIDを設定する.\r
\r
/**\r
* お気に入りの編集ダイアログ\r
- * \r
+ *\r
* @author seraphy\r
*/\r
public class ManageFavoriteDialog extends JDialog {\r
protected static final String STRINGS_RESOURCE = "languages/managefavoritesdialog";\r
\r
private CharacterData characterData;\r
- \r
+\r
private PartsSetListTableModel partsSetListModel;\r
- \r
+\r
private JTable partsSetList;\r
\r
private FavoriteManageCallback callback;\r
\r
/**\r
* 引数で指定されたパーツセットを表示する.\r
- * \r
+ *\r
* @param partsSet\r
*/\r
void selectFavorites(PartsSet partsSet);\r
/**\r
* 指定したキャラクターデータのお気に入りを保存する.<br>\r
* presetを変更した場合はcharacter.xmlを更新するためにsavePreset引数をtrueとする.<br>\r
- * \r
+ *\r
* @param characterData\r
* お気に入りを保存するキャラクターデータ\r
* @param savePreset\r
if (characterData == null) {\r
throw new IllegalArgumentException();\r
}\r
- \r
+\r
setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE);\r
addWindowListener(new WindowAdapter() {\r
@Override\r
onClose();\r
}\r
});\r
- \r
+\r
Properties strings = LocalizedResourcePropertyLoader\r
.getCachedInstance()\r
.getLocalizedProperties(STRINGS_RESOURCE);\r
\r
setTitle(strings.getProperty("manageFavorites"));\r
- \r
+\r
this.characterData = characterData;\r
- \r
+\r
characterData.getPartsSets();\r
- \r
+\r
Container contentPane = getContentPane();\r
contentPane.setLayout(new BorderLayout());\r
- \r
+\r
partsSetListModel = new PartsSetListTableModel();\r
partsSetList = new JTable(partsSetListModel);\r
partsSetList.setRowSelectionAllowed(true);\r
\r
partsSetList.setTableHeader(null);\r
partsSetList.getColumnModel().getColumn(1).setMaxWidth(150);\r
- \r
+\r
partsSetList.getSelectionModel().addListSelectionListener(\r
new ListSelectionListener() {\r
public void valueChanged(ListSelectionEvent e) {\r
GridBagLayout gb = new GridBagLayout();\r
GridBagConstraints gbc = new GridBagConstraints();\r
buttonsPanel.setLayout(gb);\r
- \r
+\r
gbc.gridx = 0;\r
gbc.gridy = 0;\r
gbc.anchor = GridBagConstraints.EAST;\r
gbc.gridx = 0;\r
gbc.gridy = 2;\r
buttonsPanel.add(new JButton(actRename), gbc);\r
- \r
+\r
gbc.gridx = 0;\r
gbc.gridy = 3;\r
gbc.weighty = 1.;\r
buttonsPanel.add(Box.createGlue(), gbc);\r
\r
- \r
+\r
JPanel panel2 = new JPanel();\r
panel2.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 42));\r
panel2.setLayout(new BorderLayout());\r
JScrollPane scr = new JScrollPane(partsSetList);\r
scr.setBorder(BorderFactory.createEtchedBorder());\r
scr.setPreferredSize(new Dimension(300, 150));\r
- \r
+\r
contentPane.add(scr, BorderLayout.CENTER);\r
contentPane.add(buttonsPanel, BorderLayout.EAST);\r
contentPane.add(panel2, BorderLayout.SOUTH);\r
\r
setSize(400, 500);\r
setLocationRelativeTo(parent);\r
- \r
+\r
final JPopupMenu popupMenu = new JPopupMenu();\r
popupMenu.add(new JMenuItem(actSelect));\r
popupMenu.add(new JMenuItem(actRename));\r
int rowIndex = partsSetList.rowAtPoint(pt);\r
if (rowIndex >= 0) {\r
int[] selrows = partsSetList.getSelectedRows();\r
- if (!Arrays.asList(selrows).contains(rowIndex)) {\r
+ Arrays.sort(selrows);\r
+ if (Arrays.binarySearch(selrows, rowIndex) < 0) {\r
// 現在の選択行以外を右クリックした場合、その行を選択行とする.\r
ListSelectionModel selModel = partsSetList\r
.getSelectionModel();\r
\r
updateButtonUI();\r
}\r
- \r
+\r
/**\r
* 現在のキャラクターデータの最新の状態でお気に入り一覧を更新する.\r
*/\r
/**\r
* 選択されている「お気に入り」のパーツセットの一覧を取得する.<br>\r
* プリセットが選択されている場合、それは除外される.<br>\r
- * \r
+ *\r
* @param beep\r
* プリセットが選択されている場合にビープを鳴らすか?\r
* @return お気に入りのパーツセットのリスト、選択がなければ空のリスト.\r
initListModel();\r
}\r
}\r
- \r
+\r
/**\r
* お気に入りのリネーム\r
*/\r
initListModel();\r
}\r
}\r
- \r
+\r
/**\r
* 選択したお気に入りを表示する.\r
*/\r
protected void onClose() {\r
dispose();\r
}\r
- \r
+\r
public void setFavoriteManageCallback(FavoriteManageCallback callback) {\r
this.callback = callback;\r
}\r
import java.io.IOException;\r
import java.net.URI;\r
import java.util.ArrayList;\r
+import java.util.Collections;\r
import java.util.HashMap;\r
import java.util.List;\r
+import java.util.Map;\r
import java.util.concurrent.Future;\r
import java.util.logging.Level;\r
import java.util.logging.Logger;\r
import javax.swing.JFrame;\r
\r
import charactermanaj.model.CharacterData;\r
+import charactermanaj.model.CustomLayerOrder;\r
+import charactermanaj.model.CustomLayerOrderKey;\r
import charactermanaj.model.PartsManageData;\r
import charactermanaj.model.io.CharacterDataDefaultProvider;\r
import charactermanaj.model.io.CharacterDataDefaultProvider.DefaultCharacterDataVersion;\r
import charactermanaj.model.io.CharacterDataPersistent;\r
import charactermanaj.model.io.CharacterDataPersistent.ListProfileCallback;\r
import charactermanaj.model.io.CharacterDataPersistent.ProfileListErrorHandler;\r
+import charactermanaj.model.io.CustomLayerOrderPersist;\r
import charactermanaj.model.io.PartsDataLoader;\r
import charactermanaj.model.io.PartsDataLoaderFactory;\r
import charactermanaj.model.io.PartsInfoXMLReader;\r
\r
/**\r
* プロファイルの選択・管理を行うクラス.\r
- * \r
+ *\r
* @author seraphy\r
*/\r
public final class ProfileListManager {\r
private ProfileListManager() {\r
super();\r
}\r
- \r
+\r
/**\r
* すべてのメインフレームで使用中のキャラクターデータのコレクション.<br>\r
*/\r
- private static final HashMap<URI, Integer> activeCharacterDatas = new HashMap<URI, Integer>(); \r
- \r
+ private static final HashMap<URI, Integer> activeCharacterDatas = new HashMap<URI, Integer>();\r
+\r
/**\r
* キャラクターデータが使用中であるか?<br>\r
* キャラクターデータのDocBaseをもとに判断する.<br>\r
* nullを指定した場合は常にfalseを返す.<br>\r
- * \r
+ *\r
* @param characterData\r
* キャラクターデータ、またはnull\r
* @return 使用中であればtrue\r
return cnt != null && cnt.intValue() > 0;\r
}\r
}\r
- \r
+\r
/**\r
* キャラクターデータが使用中であることを登録する。\r
- * \r
+ *\r
* @param characterData\r
* キャラクターデータ\r
*/\r
}\r
}\r
}\r
- \r
+\r
/**\r
* キャラクターデータの使用中であることを登録解除する。\r
- * \r
+ *\r
* @param characterData\r
* キャラクターデータ\r
*/\r
}\r
}\r
}\r
- \r
+\r
/**\r
* プロファイル選択ダイアログを表示し、選択されたプロファイルのメインフレームを作成して返す.<br>\r
* プロファイルの選択をキャンセルした場合はnullを返す.<br>\r
- * \r
+ *\r
* @param parent\r
* 親フレーム\r
* @return メインフレーム、もしくはnull\r
parent.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));\r
try {\r
newFrame = openProfile(characterData);\r
- \r
+\r
} finally {\r
parent.setCursor(Cursor.getDefaultCursor());\r
}\r
\r
/**\r
* 指定したキャラクター定義で新しいメインフレームを作成して返す.<br>\r
- * \r
+ *\r
* @param characterData\r
* キャラクターデータ\r
* @return 作成されたメインフレーム\r
}\r
\r
// キャラクターデータのロード\r
+ prepare(characterData);\r
loadCharacterData(characterData);\r
loadFavorites(characterData);\r
\r
\r
// 最後に使ったプロファイルとして登録\r
saveRecent(characterData);\r
- \r
+\r
return newFrame;\r
}\r
- \r
+\r
/**\r
* キャラクター定義編集用ダイアログを生成して返す.\r
- * \r
+ *\r
* @author seraphy\r
*/\r
private interface ProfileEditorDialogFactory {\r
- \r
+\r
ProfileEditDialog create(CharacterData characterData);\r
- \r
+\r
}\r
- \r
+\r
/**\r
* キャラクター定義を編集する.<br>\r
- * \r
+ *\r
* @param parent\r
* 親ダイアログ、もしくはnull\r
* @param characterData\r
}\r
});\r
}\r
- \r
+\r
/**\r
* キャラクター定義を編集する.<br>\r
- * \r
+ *\r
* @param parent\r
* 親フレーム、もしくはnull\r
* @param characterData\r
}\r
});\r
}\r
- \r
+\r
/**\r
* キャラクター定義を編集する.<br>\r
- * \r
+ *\r
* @param characterData\r
* キャラクター定義(参照のみ、変更されない.)\r
* @param dialogFactory\r
if (characterData == null || !characterData.isValid()) {\r
throw new IOException("開くことのできないキャラクターデータです。:" + characterData);\r
}\r
- \r
+\r
// キャラクターデータのコピーを作成する.(プリセットも含む)\r
CharacterData original = characterData.duplicateBasicInfo(true);\r
original.clearPartsSets(true); // プリセット以外のパーツセットはクリアする.\r
- \r
+\r
try {\r
loadFavorites(original);\r
\r
ErrorMessageHelper.showErrorDialog(null, ex);\r
// Favoritesの読み込みに失敗しても継続する.\r
}\r
- \r
+\r
// 編集用ダイアログを構築して開く\r
ProfileEditDialog editDlg = dialogFactory.create(original);\r
editDlg.setVisible(true);\r
// キャンセルされた場合\r
return null;\r
}\r
- \r
+\r
// 保存する.\r
CharacterDataPersistent persist = CharacterDataPersistent.getInstance();\r
\r
\r
return newCd;\r
}\r
- \r
+\r
/**\r
- * 最後にしようしたプロファイル、それがなければデフォルトプロファイルを開いて、そのメインフレームを返す.\r
- * \r
+ * 最後に使用したプロファイル、それがなければデフォルトプロファイルを開いて、そのメインフレームを返す.\r
+ *\r
* @return メインフレーム\r
* @throws IOException\r
* 開けなかった場合\r
characterData = loadRecent();\r
if (characterData != null) {\r
// キャラクターデータを読み込む\r
+ prepare(characterData);\r
loadCharacterData(characterData);\r
loadFavorites(characterData);\r
}\r
public boolean receiveCharacterData(\r
CharacterData characterData) {\r
try {\r
+ prepare(characterData);\r
loadCharacterData(characterData);\r
loadFavorites(characterData);\r
synchronized (profiles) {\r
// デフォルトのプロファイルが作成できないことは致命的であるが、\r
// アプリケーションを起動させるために継続する.\r
logger.log(Level.SEVERE, "default profile creation failed.", ex);\r
- \r
+\r
// キャラクター定義として無効なダミーのインスタンスを生成して返す.\r
// 何もできないが、メインフレームを空の状態で表示させることは可能.\r
characterData = new CharacterData();\r
// メインフレームを生成して返す\r
return new MainFrame(characterData);\r
}\r
- \r
+\r
+ /**\r
+ * キャラクターデータの準備を行う\r
+ * @param characterData\r
+ */\r
+ public static void prepare(CharacterData characterData) {\r
+ CustomLayerOrderPersist customLayerOrderPersist = CustomLayerOrderPersist.newInstance(characterData);\r
+ if (!customLayerOrderPersist.exist()) {\r
+ // まだカスタムレイヤーが登録されていない場合(空ファイルの登録は無視する)\r
+ // カスタムレイヤーをまだ使ったことがないキャラクターデータを最初に開いた場合\r
+ String structureSig = characterData.toStructureString();\r
+\r
+ Map<CustomLayerOrderKey, List<CustomLayerOrder>> map = Collections.emptyMap();\r
+\r
+ CharacterDataDefaultProvider defProv = new CharacterDataDefaultProvider();\r
+ CharacterData v3 = defProv.createDefaultCharacterData(DefaultCharacterDataVersion.V3);\r
+ if (v3.toStructureString().equals(structureSig)) {\r
+ // デフォルトのキャラクターセット(v3)と同一構造であれば、\r
+ // V3デフォルト用のカスタムレイヤー定義を事前にセットする\r
+ map = defProv.createDefaultCustomLayerOrderMap(characterData, DefaultCharacterDataVersion.V3);\r
+ }\r
+\r
+ try {\r
+ customLayerOrderPersist.save(map);\r
+ } catch (Exception ex) {\r
+ logger.log(Level.WARNING, "failed to save the custom layer mapping.", ex);\r
+ }\r
+ }\r
+ }\r
+\r
/**\r
* キャラクターデータに、パーツデータをロードする.<br>\r
* お気に入りはロードされないので、必要ならば、このあとで{@link #loadFavorites(CharacterData)}を呼び出す.<br>\r
- * \r
+ *\r
* @param characterData\r
* @throws IOException\r
* 開けなかった場合\r
public static void loadCharacterData(final CharacterData characterData) throws IOException {\r
if (characterData != null && characterData.isValid()) {\r
final PartsInfoXMLReader xmlReader = new PartsInfoXMLReader();\r
- \r
+\r
PartsDataLoaderFactory loaderFactory = PartsDataLoaderFactory.getInstance();\r
PartsDataLoader loader = loaderFactory.createPartsLoader(characterData.getDocBase());\r
PartsDataLoader colorGroupInfoDecorater = new PartsSpecDecorateLoader(loader, characterData.getColorGroups());\r
}\r
}\r
});\r
- \r
+\r
characterData.loadPartsData(partsMngDecorater);\r
}\r
}\r
- \r
+\r
/**\r
* キャラクターデータに、お気に入りをロードする.<br>\r
- * \r
+ *\r
* @param characterData\r
* @throws IOException\r
* 開けなかった場合\r
\r
/**\r
* 最後に使用したキャラクターデータとして記録する.\r
- * \r
+ *\r
* @param characterData\r
* @throws IOException\r
* 保存できなった場合\r
RecentDataPersistent recentPersist = RecentDataPersistent.getInstance();\r
recentPersist.saveRecent(characterData);\r
}\r
- \r
+\r
/**\r
* 最後に使用したキャラクターデータを取得する.\r
- * \r
+ *\r
* @return キャラクターデータ。最後に使用したデータが存在しない場合はnull\r
* @throws IOException\r
* 読み込みに失敗した場合\r
RecentDataPersistent recentPersist = RecentDataPersistent.getInstance();\r
return recentPersist.loadRecent();\r
}\r
- \r
+\r
}\r
import charactermanaj.model.AppConfig;\r
import charactermanaj.model.CharacterData;\r
import charactermanaj.model.CharacterDataChangeObserver;\r
+import charactermanaj.model.CustomLayerOrder;\r
+import charactermanaj.model.CustomLayerOrderKey;\r
import charactermanaj.model.io.CharacterDataDefaultProvider;\r
import charactermanaj.model.io.CharacterDataPersistent;\r
+import charactermanaj.model.io.CustomLayerOrderPersist;\r
import charactermanaj.model.io.PartsImageDirectoryWatchAgent;\r
import charactermanaj.model.io.PartsImageDirectoryWatchAgentFactory;\r
import charactermanaj.ui.util.FileDropTarget;\r
*/\r
protected void onProfileNew(boolean makeDefault) {\r
CharacterData cd = null;\r
+ Map<CustomLayerOrderKey, List<CustomLayerOrder>> customLayerOrderMap = null;\r
+\r
int selRow = characterList.getSelectedRow();\r
if (selRow >= 0) {\r
cd = characterListModel.getRow(selRow);\r
+\r
+ // カスタムレイヤーマッピングをロードする\r
+ if (cd.isValid()) {\r
+ try {\r
+ customLayerOrderMap = CustomLayerOrderPersist.newInstance(cd).load();\r
+ } catch (Exception ex) {\r
+ logger.log(Level.WARNING, "failed to read the custom layer mapping", ex);\r
+ }\r
+ }\r
}\r
\r
CharacterDataPersistent persist = CharacterDataPersistent.getInstance();\r
// テンプレートを読み込む\r
String characterXmlName = selection.getKey();\r
cd = defProv.loadPredefinedCharacterData(characterXmlName);\r
+ customLayerOrderMap = defProv.loadPredefinedCustomLayerOrder(cd, characterXmlName);\r
\r
} catch (Exception ex) {\r
ErrorMessageHelper.showErrorDialog(this, ex);\r
persist.createProfile(newCd);\r
persist.saveFavorites(newCd);\r
\r
+ // カスタムレイヤーマッピングを保存する\r
+ // ※ 設定ダイアログでキャラクターデータ構造を変更している場合には\r
+ // 最初にロードしたカスタムレイヤーの定義と合致しないかもしれないが、とりあえず登録しておく。\r
+ if (customLayerOrderMap == null) {\r
+ customLayerOrderMap = Collections.emptyMap();\r
+ }\r
+ CustomLayerOrderPersist.newInstance(newCd).save(customLayerOrderMap);\r
+\r
} catch (Exception ex) {\r
ErrorMessageHelper.showErrorDialog(this, ex);\r
return;\r
import java.io.IOException;\r
import java.io.InputStream;\r
import java.io.OutputStream;\r
-import java.io.Serializable;\r
import java.net.URI;\r
import java.net.URISyntaxException;\r
import java.util.ArrayList;\r
\r
/**\r
* 最後に使用したキャラクターデータディレクトリと、その履歴情報.<br>\r
- * \r
+ *\r
* @author seraphy\r
*/\r
-public class RecentCharactersDir implements Serializable {\r
- \r
- private static final long serialVersionUID = -5274310741380875405L;\r
- \r
+public class RecentCharactersDir {\r
+\r
/**\r
* 使用したキャラクターデータディレクトリリストの保存先ファイル名\r
*/\r
* 最後に使用したディレクトリ\r
*/\r
private File lastUseCharacterDir;\r
- \r
+\r
/**\r
* 過去に使用したディレクトリ情報\r
*/\r
private ArrayList<File> recentCharacterDirs = new ArrayList<File>();\r
- \r
+\r
/**\r
* ディレクトリの問い合わせ不要フラグ.\r
*/\r
private boolean doNotAskAgain;\r
\r
- \r
+\r
/**\r
* 使用したキャラクターディレクトリの履歴、古いもの順\r
- * \r
+ *\r
* @return\r
*/\r
public List<File> getRecentCharacterDirs() {\r
/**\r
* 使用したキャラクターディレクトリの履歴、新しいもの順.<br>\r
* 表示用であり、追加・削除・変更は不可.\r
- * \r
+ *\r
* @return\r
*/\r
public List<File> getRecentCharacterDirsOrderByNewly() {\r
public void setLastUseCharacterDir(File lastUseCharacterDir) {\r
this.lastUseCharacterDir = lastUseCharacterDir;\r
}\r
- \r
+\r
public File getLastUseCharacterDir() {\r
return lastUseCharacterDir;\r
}\r
lastUseCharacterDir = null;\r
recentCharacterDirs.clear();\r
}\r
- \r
+\r
public boolean isDoNotAskAgain() {\r
return doNotAskAgain;\r
}\r
- \r
+\r
public void setDoNotAskAgain(boolean doNotAskAgain) {\r
this.doNotAskAgain = doNotAskAgain;\r
}\r
/**\r
* ユーザーディレクトリ上の、過去に利用したキャラクターデータディレクトリの一覧をロードする.<br>\r
* 存在しなければ空を返す.\r
- * \r
+ *\r
* @return\r
* @throws IOException\r
*/\r
\r
/**\r
* 利用したキャラクターデータディレクトリの履歴情報をユーザーディレクトリに保存する.\r
- * \r
+ *\r
* @throws IOException\r
*/\r
public void saveRecents() throws IOException {\r
import java.util.Map;\r
import java.util.Set;\r
import java.util.TreeMap;\r
+import java.util.TreeSet;\r
\r
import charactermanaj.model.CustomLayerOrder;\r
+import charactermanaj.model.CustomLayerOrderKey;\r
import charactermanaj.model.Layer;\r
import charactermanaj.model.io.PartsImageCollectionParser.LayerOrderMapper;\r
\r
/**\r
* カスタムレイヤーパターンを保持する\r
*/\r
- private final Map<String, List<CustomLayerOrder>> customLayerPatternMap = new TreeMap<String, List<CustomLayerOrder>>();\r
+ private final Map<CustomLayerOrderKey, List<CustomLayerOrder>> customLayerPatternMap =\r
+ new TreeMap<CustomLayerOrderKey, List<CustomLayerOrder>>();\r
\r
/**\r
* 現在有効にしているカスタムレイヤーパターン名を保持する\r
*/\r
- private final Set<String> activeCustomLayers = new HashSet<String>();\r
+ private final Set<CustomLayerOrderKey> activeCustomLayers = new HashSet<CustomLayerOrderKey>();\r
\r
/**\r
* カスタムレイヤーパターンと有効にしているパターン名から現在有効なレイヤーマッピングを導出する。\r
* まだ導出されていないかリセットされた場合はnull\r
*/\r
- private Map<Layer, Integer> customLayerOrderMap;\r
+ private Map<Layer, Float> customLayerOrderMap;\r
\r
/**\r
* 現在有功にしているカスタムレイヤーの順序をマッピングする\r
*/\r
private void initCustomLayerOrder() {\r
- customLayerOrderMap = new HashMap<Layer, Integer>();\r
- for (String patternName : activeCustomLayers) {\r
- initCustomLayerOrder(customLayerPatternMap.get(patternName));\r
+ customLayerOrderMap = new HashMap<Layer, Float>();\r
+ for (CustomLayerOrderKey patternKey : activeCustomLayers) {\r
+ initCustomLayerOrder(customLayerPatternMap.get(patternKey));\r
}\r
}\r
\r
if (customLayerOrderList != null) {\r
for (CustomLayerOrder customLayerOrder : customLayerOrderList) {\r
Layer layer = customLayerOrder.getLayer();\r
- int layerOrder = customLayerOrder.getLayerOrder();\r
+ float layerOrder = customLayerOrder.getLayerOrder();\r
customLayerOrderMap.put(layer, layerOrder);\r
}\r
}\r
}\r
\r
public void applyCustomLayerOrder(List<CustomLayerOrder> customLayerOrderList) {\r
- customLayerOrderMap = new HashMap<Layer, Integer>();\r
+ customLayerOrderMap = new HashMap<Layer, Float>();\r
initCustomLayerOrder(customLayerOrderList);\r
}\r
\r
@Override\r
- public int getLayerOrder(Layer layer) {\r
+ public float getLayerOrder(Layer layer) {\r
if (customLayerOrderMap == null) {\r
initCustomLayerOrder();\r
}\r
- Integer layerOrder = customLayerOrderMap.get(layer);\r
+ Float layerOrder = customLayerOrderMap.get(layer);\r
if (layerOrder == null) {\r
- layerOrder = layer.getOrder();\r
+ layerOrder = (float) layer.getOrder();\r
}\r
return layerOrder;\r
}\r
*\r
* @return map パターン名をキーとし、カスタムレイヤー順のリストを値とするマップ\r
*/\r
- public Map<String, List<CustomLayerOrder>> getMap() {\r
+ public Map<CustomLayerOrderKey, List<CustomLayerOrder>> getMap() {\r
return customLayerPatternMap;\r
}\r
\r
* (現在のパターン一覧はクリアされる。)\r
* @param map パターン名をキーとし、カスタムレイヤー順のリストを値とするマップ\r
*/\r
- public void setMap(Map<String, List<CustomLayerOrder>> map) {\r
+ public void setMap(Map<CustomLayerOrderKey, List<CustomLayerOrder>> map) {\r
customLayerPatternMap.clear();\r
customLayerPatternMap.putAll(map);\r
activeCustomLayers.retainAll(customLayerPatternMap.keySet()); // 現在存在するパターン名に絞り込む\r
* @param name\r
* @return\r
*/\r
- public boolean isSelected(String name) {\r
+ public boolean isSelected(CustomLayerOrderKey name) {\r
return activeCustomLayers.contains(name);\r
}\r
\r
* @param name\r
* @param selected\r
*/\r
- public void setSelected(String name, boolean selected) {\r
+ public void setSelected(CustomLayerOrderKey name, boolean selected) {\r
if (customLayerPatternMap.containsKey(name)) {\r
if (selected) {\r
unselectConflict(name);\r
}\r
\r
/**\r
+ * 現在アクティブなレイヤーパターン名の一覧のコピーを取得する。\r
+ * @return\r
+ */\r
+ public Set<CustomLayerOrderKey> getActivePatternNames() {\r
+ return new TreeSet<CustomLayerOrderKey>(activeCustomLayers);\r
+ }\r
+\r
+ /**\r
+ * 現在のアクティブなレイヤーパターンの一覧を一括更新する。\r
+ * @param patternNames\r
+ */\r
+ public void setActivePatternNames(Set<CustomLayerOrderKey> patternNames) {\r
+ activeCustomLayers.clear();\r
+ for (CustomLayerOrderKey name : patternNames) {\r
+ if (customLayerPatternMap.containsKey(name)) {\r
+ unselectConflict(name);\r
+ activeCustomLayers.add(name);\r
+ }\r
+ }\r
+ initCustomLayerOrder();\r
+ }\r
+\r
+ /**\r
* 選択するレイヤーパターンと重複するレイヤーをもつパターンがすでに選択されている場合、\r
* その選択を解除する。\r
* @param name 選択するレイヤーパターン\r
*/\r
- private void unselectConflict(String name) {\r
+ private void unselectConflict(CustomLayerOrderKey orderKey) {\r
// 指定されたパターン名が使用しているレイヤー一覧を作成する。\r
Set<Layer> targetLayers = new HashSet<Layer>();\r
- List<CustomLayerOrder> targetLayerOrders = customLayerPatternMap.get(name);\r
+ List<CustomLayerOrder> targetLayerOrders = customLayerPatternMap.get(orderKey);\r
if (targetLayerOrders != null) {\r
for (CustomLayerOrder layerOrder : targetLayerOrders) {\r
targetLayers.add(layerOrder.getLayer());\r
\r
// 現在選択しているレイヤーパターンから、\r
// これから選択しようとしているレイヤーを含んでいる(衝突)パターンを検出する\r
- ArrayList<String> conflictPatterns = new ArrayList<String>();\r
- for (String patternName : activeCustomLayers) {\r
- if (!patternName.equals(name)) { // 自分と同一名であれば検査の必要なし\r
+ ArrayList<CustomLayerOrderKey> conflictPatterns = new ArrayList<CustomLayerOrderKey>();\r
+ for (CustomLayerOrderKey patternName : activeCustomLayers) {\r
+ if (!patternName.equals(orderKey)) { // 自分と同一名であれば検査の必要なし\r
List<CustomLayerOrder> layerOrders = customLayerPatternMap.get(patternName);\r
if (layerOrders != null) {\r
for (CustomLayerOrder layerOrder : layerOrders) {\r
*/\r
public List<CustomLayerOrder> getMergedCustomLayerOrderList() {\r
List<CustomLayerOrder> mergedList = new ArrayList<CustomLayerOrder>();\r
- for (String patternName : activeCustomLayers) {\r
+ for (CustomLayerOrderKey patternName : activeCustomLayers) {\r
List<CustomLayerOrder> list = customLayerPatternMap.get(patternName);\r
if (list != null) {\r
for (CustomLayerOrder layerOrder : list) {\r
import java.util.HashMap;\r
import java.util.List;\r
import java.util.Map;\r
+import java.util.Set;\r
\r
import charactermanaj.model.PartsCategory;\r
import charactermanaj.model.PartsColorInfo;\r
* @author seraphy\r
*/\r
public class PartsSelectionManager {\r
- \r
+\r
/**\r
* 背景色を管理するオブジェクトが実装するインターフェイス.\r
* @author seraphy\r
*/\r
public interface ImageBgColorProvider {\r
- \r
+\r
/**\r
* 背景色を取得する.\r
* @return 背景色\r
}\r
\r
/**\r
+ * アクティブなカスタムレイヤーをIDでやりとりするインターフェイス\r
+ *\r
+ * @author seraphy\r
+ */\r
+ public interface CustomLayerPatternsIDProvider {\r
+\r
+ /**\r
+ * アクティブなカスタムレイヤーパターンのID一覧を取得する\r
+ * @return\r
+ */\r
+ Set<String> getActivePatternIds();\r
+\r
+ /**\r
+ * カスタムレイヤーパターンのIDのセットを指定してアクティブにする。\r
+ * @param names\r
+ */\r
+ void setActivePatternIds(Set<String> names);\r
+ }\r
+\r
+ /**\r
* カテゴリ別パーツ選択パネル.<br>\r
*/\r
private HashMap<PartsCategory, ImageSelectPanel> imageSelectPanels = new HashMap<PartsCategory, ImageSelectPanel>();\r
- \r
+\r
/**\r
* パーツカラーマネージャ.<br>\r
*/\r
private PartsColorManager partsColorMrg;\r
- \r
+\r
/**\r
* 背景色プロバイダ.\r
*/\r
private ImageBgColorProvider imageBgColorProvider;\r
- \r
+\r
/**\r
* アフィン変換用のパラメータ.<br>\r
* 変換しない場合はnull.<br>\r
*/\r
private double[] affineTransformParameter;\r
- \r
+\r
/**\r
* 単一選択カテゴリの選択解除の有効/無効.<br>\r
* 有効にする場合はtrue.<br>\r
*/\r
private boolean deselectableAllCategory;\r
- \r
- \r
+\r
+ /**\r
+ * カスタムレイヤーパターンのプロバイダ\r
+ */\r
+ private CustomLayerPatternsIDProvider customLayerPatternsProvider;\r
+\r
+\r
/**\r
* コンストラクタ\r
* @param partsColorMrg パーツカラーマネージャ\r
*/\r
public PartsSelectionManager(\r
PartsColorManager partsColorMrg,\r
- ImageBgColorProvider imageBgColorProvider\r
+ ImageBgColorProvider imageBgColorProvider,\r
+ CustomLayerPatternsIDProvider customLayerPatternsProvider\r
) {\r
- if (partsColorMrg == null || imageBgColorProvider == null) {\r
+ if (partsColorMrg == null || imageBgColorProvider == null || customLayerPatternsProvider == null) {\r
throw new IllegalArgumentException();\r
}\r
this.partsColorMrg = partsColorMrg;\r
this.imageBgColorProvider = imageBgColorProvider;\r
+ this.customLayerPatternsProvider = customLayerPatternsProvider;\r
}\r
- \r
+\r
\r
/**\r
* パーツをロードする.\r
panel.loadParts();\r
}\r
}\r
- \r
+\r
public void register(ImageSelectPanel imageSelectPanel) {\r
if (imageSelectPanel == null) {\r
throw new IllegalArgumentException();\r
}\r
return null;\r
}\r
- \r
+\r
public Collection<PartsCategory> getAllCategories() {\r
ArrayList<PartsCategory> partsCategories = new ArrayList<PartsCategory>();\r
partsCategories.addAll(imageSelectPanels.keySet());\r
return partsCategories;\r
}\r
- \r
+\r
/**\r
- * 各カテゴリの選択状態と背景をパーツセットで指定されたものに設定します.<br>\r
+ * 各カテゴリの選択状態と背景色、アクティブなカスタムレイヤーをパーツセットで指定されたものに設定します.<br>\r
* @param partsSet パーツセット\r
*/\r
public void selectPartsSet(PartsSet partsSet) {\r
throw new IllegalArgumentException();\r
}\r
\r
+ // パーツを選択する\r
for (ImageSelectPanel panel : imageSelectPanels.values()) {\r
PartsCategory partsCategory = panel.getPartsCategory();\r
List<PartsIdentifier> partsIdentifiers = partsSet.get(partsCategory);\r
}\r
}\r
\r
+ // 背景色を設定する\r
Color bgColor = partsSet.getBgColor();\r
if (bgColor != null) {\r
- setImageBgColor(bgColor); \r
+ setImageBgColor(bgColor);\r
}\r
- \r
+\r
+ // アクティブなカスタムレイヤー名を設定する\r
+ Set<String> customLayerPatternIds = partsSet.getActiveCustomLayerPatternIds();\r
+ if (customLayerPatternIds != null) {\r
+ customLayerPatternsProvider.setActivePatternIds(customLayerPatternIds);\r
+ }\r
+\r
affineTransformParameter = partsSet.getAffineTransformParameter(); // clone済み\r
}\r
- \r
+\r
/**\r
* 現在の選択中のパーツと色設定からパーツセットを構築します.\r
* 選択がなにもない場合は空のパーツセットとなります.<br>\r
}\r
presetParts.setBgColor(getImageBgColor());\r
presetParts.setAffineTransformParameter(affineTransformParameter); // 相手側でcloneする\r
+ presetParts.setActiveCustomLayerPatternIds(customLayerPatternsProvider.getActivePatternIds());\r
return presetParts;\r
}\r
\r
imageSelectPanel.scrollToSelectedRow();\r
}\r
}\r
- \r
+\r
/**\r
* 指定したパーツ識別子にフォーカスを当てて、必要に応じてスクロールします.<br>\r
* 該当するパーツ識別子がどこにもなければ何もしません.<br>\r
imageSelectPanel.setSelection(partsIdentifier);\r
}\r
}\r
- \r
+\r
/**\r
* 背景色を取得する.\r
* @return 背景色\r
public double[] getAffineTransformParameter() {\r
return affineTransformParameter == null ? null : affineTransformParameter.clone();\r
}\r
- \r
+\r
/**\r
* アフィン変換用のパラメータを設定する.<br>\r
* 変換しない場合はnull.<br>\r
public boolean isDeselectableSingleCategory() {\r
return deselectableAllCategory;\r
}\r
- \r
+\r
/**\r
* 選択選択パーツカテゴリの選択解除を許可するか設定する.<br>\r
* @param deselectable 許可する場合はtrue\r
imageSelectPanel.setDeselectableSingleCategory(deselectable);\r
}\r
}\r
- \r
+\r
/**\r
* パーツ選択をすべて解除する.<br>\r
* 単一選択カテゴリが解除されるかどうかは、{@link #isDeselectableSingleCategory()}による.<br>\r
}\r
}\r
}\r
- \r
+\r
/**\r
* 指定したカテゴリ以外のパネルを最小化する.<br>\r
* (指定したカテゴリがnullでなければ、そのカテゴリの最小化は解除される.)<br>\r
}\r
}\r
}\r
- \r
+\r
/**\r
* 指定したカテゴリが最小化モードであるか?\r
* @param partsCategory カテゴリ\r
}\r
return panel.isMinimizeMode();\r
}\r
- \r
+\r
/**\r
* 指定したカテゴリが最小化モードでなく、且つ、他がすべて最小化モードであるか?\r
* (指定カテゴリがない場合は全パネルが最小化モードである場合)<br>\r
\r
import java.awt.Color;\r
import java.io.File;\r
-import java.io.Serializable;\r
\r
/**\r
* 壁紙情報.<br>\r
* @author seraphy\r
*/\r
-public class WallpaperInfo implements Serializable, Cloneable {\r
-\r
- /**\r
- * シリアライズバージョンID\r
- */\r
- private static final long serialVersionUID = -3661482624140948074L;\r
-\r
+public class WallpaperInfo implements Cloneable {\r
\r
/**\r
* 壁紙のリソースタイプ\r
* @author seraphy\r
*/\r
public enum WallpaperResourceType {\r
- \r
+\r
/**\r
* なし\r
*/\r
NONE,\r
- \r
+\r
/**\r
* ファイル\r
*/\r
FILE,\r
- \r
+\r
/**\r
* 定義済み\r
*/\r
PREDEFINED\r
}\r
- \r
+\r
/**\r
* 壁紙リソースのタイプ\r
*/\r
private WallpaperResourceType type = WallpaperResourceType.NONE;\r
- \r
+\r
/**\r
* ファイル\r
*/\r
private File file;\r
- \r
+\r
/**\r
* リソース\r
*/\r
private String resource;\r
- \r
+\r
/**\r
* 壁紙のアルファ値\r
*/\r
private float alpha = 1.f;\r
\r
- \r
+\r
/**\r
* 背景色\r
*/\r
private Color backgroundColor = Color.WHITE;\r
\r
- \r
+\r
@Override\r
public WallpaperInfo clone() {\r
try {\r
throw new RuntimeException(ex);\r
}\r
}\r
- \r
+\r
\r
public WallpaperResourceType getType() {\r
return type;\r
} else if (alpha > 1.f) {\r
alpha = 1.f;\r
}\r
- \r
+\r
this.alpha = alpha;\r
}\r
\r
import java.io.FileOutputStream;\r
import java.io.IOException;\r
import java.io.InputStream;\r
-import java.io.ObjectInputStream;\r
-import java.io.ObjectOutputStream;\r
import java.io.OutputStream;\r
import java.util.logging.Level;\r
import java.util.logging.Logger;\r
* 保存先ファイル\r
*/\r
private File file;\r
- \r
+\r
public FileUserData(File file) {\r
if (file == null) {\r
throw new IllegalArgumentException();\r
}\r
this.file = file;\r
}\r
- \r
+\r
public boolean exists() {\r
return file.exists() && file.isFile();\r
}\r
- \r
+\r
public long lastModified() {\r
return file.lastModified();\r
}\r
- \r
+\r
+ @Override\r
+ public long length() {\r
+ return file.length();\r
+ }\r
+\r
public InputStream openStream() throws IOException {\r
return new BufferedInputStream(new FileInputStream(file));\r
}\r
- \r
+\r
public OutputStream getOutputStream() throws IOException {\r
return new BufferedOutputStream(new FileOutputStream(file));\r
}\r
- \r
+\r
public boolean delete() {\r
try {\r
return file.delete();\r
return false;\r
}\r
}\r
- \r
- public void save(Object userData) throws IOException {\r
- ObjectOutputStream oos = new ObjectOutputStream(getOutputStream());\r
- try {\r
- oos.writeObject(userData);\r
- oos.close();\r
- } finally {\r
- oos.close();\r
- }\r
- }\r
\r
- public Object load() throws IOException {\r
- ObjectInputStream ois = new ObjectInputStream(openStream());\r
- try {\r
- try {\r
- return ois.readObject();\r
-\r
- } catch (ClassNotFoundException ex) {\r
- // 復元先クラスがみつからないということは、このアプリケーションの保存した形式としておかしい\r
- IOException ex2 = new IOException("invalid format.");\r
- ex2.initCause(ex2);\r
- throw ex2;\r
- }\r
- } finally {\r
- ois.close();\r
- }\r
- }\r
- \r
@Override\r
public String toString() {\r
return "FileUserData{file:" + file + "}";\r
* @throws IOException 開けなかった場合\r
*/\r
InputStream openStream() throws IOException;\r
- \r
+\r
/**\r
* データを書き込む\r
* @return 出力ストリーム\r
* @throws IOException 開けなかった場合\r
*/\r
OutputStream getOutputStream() throws IOException;\r
- \r
+\r
/**\r
* 更新日時(エポックタイム)、まだ存在しない場合は0\r
* @return 更新日時\r
*/\r
long lastModified();\r
- \r
+\r
+ /**\r
+ * サイズ\r
+ * @return\r
+ */\r
+ long length();\r
+\r
/**\r
* 存在するか?\r
* @return 存在すればtrue\r
*/\r
boolean exists();\r
- \r
+\r
/**\r
* 削除する.<br>\r
* すでに存在しない場合は何もしない.<br>\r
* @return 削除された場合はtrue\r
*/\r
boolean delete();\r
- \r
- /**\r
- * 引数に指定したオブジェクトをシリアライズします.\r
- * @param obj オブジェクト\r
- * @throws IOException 保存できなかった場合\r
- */\r
- void save(Object obj) throws IOException;\r
- \r
- /**\r
- * オブジェクトをデシリアライズして返します.\r
- * @return オブジェクト\r
- * @throws IOException 取得できなかった場合\r
- */\r
- Object load() throws IOException;\r
- \r
}\r
<entry key="column.layerName">Layer</entry>\r
<entry key="column.defaultLayerOrder">Default Order</entry>\r
<entry key="column.layerOrder">Actual Order</entry>\r
+ <entry key="column.order">No.</entry>\r
<entry key="column.imagesize">Size</entry>\r
<entry key="column.colortype">Color Mode</entry>\r
<entry key="column.imageName">Image</entry>\r
<entry key="column.layerName.width">80</entry>\r
<entry key="column.defaultLayerOrder.width">50</entry>\r
<entry key="column.layerOrder.width">50</entry>\r
+ <entry key="column.order.width">50</entry>\r
<entry key="column.imagesize.width">50</entry>\r
<entry key="column.colortype.width">50</entry>\r
<entry key="column.imageName.width">150</entry>\r
<?xml version="1.0" encoding="UTF-8"?>\r
-<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" \r
+<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified"\r
xmlns:xs="http://www.w3.org/2001/XMLSchema">\r
<xs:element name="custom-layer-orders">\r
<xs:complexType>\r
</xs:complexType>\r
</xs:element>\r
</xs:sequence>\r
+ <xs:attribute type="xs:string" name="id" use="optional"/>\r
<xs:attribute type="xs:string" name="name" use="required"/>\r
</xs:complexType>\r
</xs:element>\r
<display-name xml:lang="zh">脸色</display-name>\r
<display-name xml:lang="zh_TW">臉色</display-name>\r
<layers>\r
- <layer id="face_front"> \r
+ <layer id="face_front">\r
<display-name xml:lang="en">Face</display-name>\r
<display-name xml:lang="ja">表情</display-name>\r
<display-name xml:lang="zh">脸色</display-name>\r
</recommendation>\r
<recommendation>\r
<description xml:lang="en">The storage of an additional parts</description>\r
- <description xml:lang="ja">ã\82ã\83£ã\83©ã\82¯ã\82¿ã\83¼ã\81ªã\82\93ã\81¨ã\81\8bæ©\9f 追å\8a ã\83\91ã\83¼ã\83\84ä¿\9d管庫</description>\r
- <description xml:lang="zh">ã\82ã\83£ã\83©ã\82¯ã\82¿ã\83¼ã\81ªã\82\93ã\81¨ã\81\8bæ©\9f 追å\8a ã\83\91ã\83¼ã\83\84ä¿\9d管庫 (é\9b¶ä»¶ç\9a\84ä¿\9d管åº\93)</description>\r
- <description xml:lang="zh_TW">ã\82ã\83£ã\83©ã\82¯ã\82¿ã\83¼ã\81ªã\82\93ã\81¨ã\81\8bæ©\9f 追å\8a ã\83\91ã\83¼ã\83\84ä¿\9d管庫 (é\9b¶ä»¶ç\9a\84ä¿\9d管庫)</description>\r
- <URL xml:lang="en">http://nantoka.main.jp/</URL>\r
+ <description xml:lang="ja">パーツ保管庫</description>\r
+ <description xml:lang="zh">パーツ保管庫 (零件的保管库)</description>\r
+ <description xml:lang="zh_TW">パーツ保管庫 (零件的保管庫)</description>\r
+ <URL xml:lang="en">https://charactermanaj.osdn.jp/upload.html</URL>\r
</recommendation>\r
</recommendations>\r
\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>\r
+<custom-layer-orders xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.0" xsi:schemaLocation="http://charactermanaj.osdn.jp/schema/customlayerorder.xsd customlayerorder.xsd" xmlns="http://charactermanaj.osdn.jp/schema/customlayerorder.xsd">\r
+ <pattern id="hide_eyes_and_eyebrows" name="bangs covering eyes and eyebrows">\r
+ <localized-name lang="en" name="bangs covering eyes and eyebrows"/>\r
+ <localized-name lang="zh" name="劉海遮住眼睛和眉毛"/>\r
+ <localized-name lang="ja" name="目と眉を髪の下に表示する"/>\r
+ <mapping category="hair_front" layer="hair_front" order="18.4"/>\r
+ <mapping category="hair_front" layer="hair_front_accessory" order="18.5"/>\r
+ <mapping category="eye" layer="eye" order="17.0"/>\r
+ </pattern>\r
+ <pattern id="hide_eyes" name="bangs covering eyes">\r
+ <localized-name lang="en" name="bangs covering eyes"/>\r
+ <localized-name lang="zh" name="劉海遮住眼睛"/>\r
+ <localized-name lang="ja" name="目を髪の下に表示する"/>\r
+ <mapping category="eye" layer="eye" order="12.5"/>\r
+ <mapping category="eye" layer="eye_color" order="12.6"/>\r
+ </pattern>\r
+ <pattern id="hide_eyebrows" name="bangs covering eyebrows">\r
+ <localized-name lang="en" name="bangs covering eyebrows"/>\r
+ <localized-name lang="zh" name="劉海遮住眉毛"/>\r
+ <localized-name lang="ja" name="眉を髪の下に表示する"/>\r
+ <mapping category="hair_front" layer="hair_front" order="16.4"/>\r
+ <mapping category="hair_front" layer="hair_front_accessory" order="16.5"/>\r
+ <mapping category="eye" layer="eye" order="17.0"/>\r
+ </pattern>\r
+</custom-layer-orders>\r
<display-name xml:lang="zh">脸色</display-name>\r
<display-name xml:lang="zh_TW">臉色</display-name>\r
<layers>\r
- <layer id="face_front"> \r
+ <layer id="face_front">\r
<display-name xml:lang="en">Face</display-name>\r
<display-name xml:lang="ja">表情</display-name>\r
<display-name xml:lang="zh">脸色</display-name>\r
</recommendation>\r
<recommendation>\r
<description xml:lang="en">The storage of an additional parts</description>\r
- <description xml:lang="ja">ã\82ã\83£ã\83©ã\82¯ã\82¿ã\83¼ã\81ªã\82\93ã\81¨ã\81\8bæ©\9f 追å\8a ã\83\91ã\83¼ã\83\84ä¿\9d管庫</description>\r
- <description xml:lang="zh">ã\82ã\83£ã\83©ã\82¯ã\82¿ã\83¼ã\81ªã\82\93ã\81¨ã\81\8bæ©\9f 追å\8a ã\83\91ã\83¼ã\83\84ä¿\9d管庫 (é\9b¶ä»¶ç\9a\84ä¿\9d管åº\93)</description>\r
- <description xml:lang="zh_TW">ã\82ã\83£ã\83©ã\82¯ã\82¿ã\83¼ã\81ªã\82\93ã\81¨ã\81\8bæ©\9f 追å\8a ã\83\91ã\83¼ã\83\84ä¿\9d管庫 (é\9b¶ä»¶ç\9a\84ä¿\9d管庫)</description>\r
- <URL xml:lang="en">http://nantoka.main.jp/</URL>\r
+ <description xml:lang="ja">パーツ保管庫</description>\r
+ <description xml:lang="zh">パーツ保管庫 (零件的保管库)</description>\r
+ <description xml:lang="zh_TW">パーツ保管庫 (零件的保管庫)</description>\r
+ <URL xml:lang="en">https://charactermanaj.osdn.jp/upload.html</URL>\r
</recommendation>\r
</recommendations>\r
\r