4 * License : The MIT License
5 * Copyright(c) 2008 olyutorskii
8 package jp.sfjp.jindolf.config;
11 import java.awt.Rectangle;
12 import java.awt.image.BufferedImage;
14 import java.io.IOException;
15 import java.nio.file.Path;
16 import java.nio.file.Paths;
17 import java.text.MessageFormat;
18 import java.util.HashMap;
19 import java.util.List;
21 import java.util.logging.Logger;
22 import javax.imageio.ImageIO;
23 import jp.sfjp.jindolf.data.Avatar;
24 import jp.sfjp.jindolf.data.DialogPref;
25 import jp.sfjp.jindolf.glyph.Font2Json;
26 import jp.sfjp.jindolf.glyph.FontInfo;
27 import jp.sfjp.jindolf.net.ProxyInfo;
28 import jp.sfjp.jindolf.view.AvatarPics;
29 import jp.sfjp.jindolf.view.LocalAvatarImg;
30 import jp.sourceforge.jovsonz.JsBoolean;
31 import jp.sourceforge.jovsonz.JsObject;
32 import jp.sourceforge.jovsonz.JsPair;
33 import jp.sourceforge.jovsonz.JsString;
34 import jp.sourceforge.jovsonz.JsTypes;
35 import jp.sourceforge.jovsonz.JsValue;
40 public class AppSetting{
43 private static final int DEF_WIDTH = 800;
44 private static final int DEF_HEIGHT = 600;
46 private static final String HASH_FONT = "font";
47 private static final String HASH_USEBODYICON = "useBodyIcon";
48 private static final String HASH_USEMONOTOMB = "useMonoTomb";
49 private static final String HASH_SIMPLEMODE = "isSimpleMode";
50 private static final String HASH_ALIGNBALOON = "alignBaloonWidth";
51 private static final String HASH_PROXY = "proxy";
53 private static final String MSG_NOIMG =
55 + "{1}の表示に代替イメージを使います。";
57 private static final Logger LOGGER = Logger.getAnonymousLogger();
60 private final OptionInfo optInfo;
61 private final ConfigStore configStore;
62 private final Rectangle frameRect;
64 private FontInfo fontInfo;
66 private ProxyInfo proxyInfo = ProxyInfo.DEFAULT;
68 private DialogPref dialogPref = new DialogPref();
70 private JsValue loadedNetConfig;
71 private JsValue loadedTalkConfig;
73 private final Map<String, BufferedImage> avatarFaceMap = new HashMap<>();
74 private final Map<String, BufferedImage> avatarBodyMap = new HashMap<>();
79 * @param info コマンドライン引数
81 public AppSetting(OptionInfo info){
85 this.configStore = parseConfigStore(this.optInfo);
86 this.frameRect = parseGeometrySetting(this.optInfo);
94 * @param option コマンドラインオプション情報
97 private static ConfigStore parseConfigStore(OptionInfo option){
98 CmdOption opt = option.getExclusiveOption(CmdOption.OPT_CONFDIR,
99 CmdOption.OPT_NOCONF );
102 boolean isImplicitPath;
105 if(opt == CmdOption.OPT_NOCONF){
107 isImplicitPath = true;
109 }else if(opt == CmdOption.OPT_CONFDIR){
111 isImplicitPath = false;
112 String optPath = option.getStringArg(opt);
113 configPath = FileUtils.supplyFullPath(new File(optPath));
116 isImplicitPath = true;
117 configPath = ConfigFile.getImplicitConfigDirectory();
121 new ConfigStore(useConfig, isImplicitPath, configPath);
128 * @param option コマンドラインオプション情報
131 private static Rectangle parseGeometrySetting(OptionInfo option){
132 Rectangle result = new Rectangle(Integer.MIN_VALUE,
139 ival = option.initialFrameWidth();
140 if(ival != null) result.width = ival;
142 ival = option.initialFrameHeight();
143 if(ival != null) result.height = ival;
145 ival = option.initialFrameXpos();
146 if(ival != null) result.x = ival;
148 ival = option.initialFrameYpos();
149 if(ival != null) result.y = ival;
157 * @param baseFont 元のフォント設定。
158 * @return コマンドライン設定で補正されたフォント設定
160 private FontInfo parseFontOption(FontInfo baseFont){
163 String fontName = this.optInfo.getStringArg(CmdOption.OPT_INITFONT);
164 if(fontName != null){
165 Font font = Font.decode(fontName);
166 result = baseFont.deriveFont(font);
171 Boolean useAntiAlias =
172 this.optInfo.getBooleanArg(CmdOption.OPT_ANTIALIAS);
173 if(useAntiAlias == null){
174 useAntiAlias = baseFont.isAntiAliased();
177 Boolean useFractional =
178 this.optInfo.getBooleanArg(CmdOption.OPT_FRACTIONAL);
179 if(useFractional == null){
180 useFractional = baseFont.usesFractionalMetrics();
183 result = result.deriveRenderContext(useAntiAlias,
191 * @return コマンドラインオプション情報
193 public OptionInfo getOptionInfo(){
201 public ConfigStore getConfigStore(){
202 return this.configStore;
209 public int initialFrameWidth(){
210 int width = this.frameRect.width;
218 public int initialFrameHeight(){
219 int height = this.frameRect.height;
225 * 特に指示されていなければInteger.MIN_VALUEを返す。
226 * @return 初期のフレーム位置のX座標
228 public int initialFrameXpos(){
229 int xPos = this.frameRect.x;
235 * 特に指示されていなければInteger.MIN_VALUEを返す。
236 * @return 初期のフレーム位置のY座標
238 public int initialFrameYpos(){
239 int yPos = this.frameRect.y;
247 public FontInfo getFontInfo(){
248 if(this.fontInfo == null){
249 this.fontInfo = parseFontOption(FontInfo.DEFAULT_FONTINFO);
251 return this.fontInfo;
256 * @param fontInfo フォント設定
258 public void setFontInfo(FontInfo fontInfo){
259 this.fontInfo = fontInfo;
267 public ProxyInfo getProxyInfo(){
268 return this.proxyInfo;
273 * @param proxyInfo プロクシ設定。nullならプロクシなしと解釈される。
275 public void setProxyInfo(ProxyInfo proxyInfo){
276 if(proxyInfo == null) this.proxyInfo = ProxyInfo.DEFAULT;
277 else this.proxyInfo = proxyInfo;
285 public DialogPref getDialogPref(){
286 return this.dialogPref;
293 public void setDialogPref(DialogPref pref){
294 if(pref == null) this.dialogPref = new DialogPref();
295 else this.dialogPref = pref;
302 private void loadNetConfig(){
303 JsObject root = this.configStore.loadNetConfig();
304 if(root == null) return;
305 this.loadedNetConfig = root;
307 JsValue value = root.getValue(HASH_PROXY);
308 if( ! (value instanceof JsObject) ) return;
309 JsObject proxy = (JsObject) value;
311 ProxyInfo info = ProxyInfo.decodeJson(proxy);
321 private void loadTalkConfig(){
322 JsObject root = this.configStore.loadTalkConfig();
323 if(root == null) return;
324 this.loadedTalkConfig = root;
326 JsValue value = root.getValue(HASH_FONT);
327 if(value instanceof JsObject){
328 JsObject font = (JsObject) value;
329 FontInfo info = Font2Json.decodeJson(font);
330 info = parseFontOption(info);
334 DialogPref pref = new DialogPref();
336 value = root.getValue(HASH_USEBODYICON);
337 if(value instanceof JsBoolean){
338 boolValue = (JsBoolean) value;
339 pref.setBodyImageSetting(boolValue.booleanValue());
341 value = root.getValue(HASH_USEMONOTOMB);
342 if(value instanceof JsBoolean){
343 boolValue = (JsBoolean) value;
344 pref.setMonoImageSetting(boolValue.booleanValue());
346 value = root.getValue(HASH_SIMPLEMODE);
347 if(value instanceof JsBoolean){
348 boolValue = (JsBoolean) value;
349 pref.setSimpleMode(boolValue.booleanValue());
351 value = root.getValue(HASH_ALIGNBALOON);
352 if(value instanceof JsBoolean){
353 boolValue = (JsBoolean) value;
354 pref.setAlignBalooonWidthSetting(boolValue.booleanValue());
362 * JSONをパースしAvatar-Image間マップに反映させる。
367 private void parseImgMap(JsObject json, Map<String, BufferedImage> map){
368 Path imgDir = this.configStore.getLocalImgDir();
370 List<JsPair> pairList = json.getPairList();
371 for(JsPair pair : pairList){
372 String avatarId = pair.getName();
373 JsValue value = pair.getValue();
375 if(value.getJsTypes() != JsTypes.STRING) continue;
376 JsString sVal = (JsString)value;
377 String imgName = sVal.toRawString();
379 Path imgPath = Paths.get(imgName);
380 Path full = imgDir.resolve(imgPath);
381 File file = full.toFile();
382 if( ! file.isAbsolute()
385 || ! file.canRead() ){
386 String msg = MessageFormat.format(
387 MSG_NOIMG, file.getPath(), avatarId
395 image = ImageIO.read(file);
396 }catch(IOException e){
397 String msg = MessageFormat.format(
398 MSG_NOIMG, file.getPath(), avatarId
404 map.put(avatarId, image);
413 private void loadLocalImageConfig(){
414 JsObject root = this.configStore.loadLocalImgConfig();
415 if(root == null) return;
417 JsValue faceConfig = root.getValue("avatarFace");
418 JsValue bodyConfig = root.getValue("avatarBody");
419 if(faceConfig.getJsTypes() != JsTypes.OBJECT) return;
420 if(bodyConfig.getJsTypes() != JsTypes.OBJECT) return;
422 JsObject jsonFace = (JsObject) faceConfig;
423 parseImgMap(jsonFace, this.avatarFaceMap);
426 JsObject jsonBody = (JsObject) bodyConfig;
427 parseImgMap(jsonBody, this.avatarBodyMap);
433 * ローカル代替イメージを画像キャッシュに反映させる。
435 * @param avatarPics 画像キャッシュ
437 public void applyLocalImage(AvatarPics avatarPics){
438 BufferedImage graveImage = this.avatarFaceMap.get("tomb");
439 BufferedImage graveBodyImage = this.avatarBodyMap.get("tomb");
441 if(graveImage == null){
442 graveImage = LocalAvatarImg.getGraveImage();
444 if(graveBodyImage == null){
445 graveBodyImage = LocalAvatarImg.getGraveBodyImage();
448 avatarPics.setGraveImage(graveImage);
449 avatarPics.setGraveBodyImage(graveBodyImage);
451 for(Avatar avatar : Avatar.getPredefinedAvatarList()){
452 String avatarId = avatar.getIdentifier();
454 BufferedImage faceImage = this.avatarFaceMap.get(avatarId);
455 BufferedImage bodyImage = this.avatarBodyMap.get(avatarId);
457 if(faceImage == null){
458 faceImage = LocalAvatarImg.getAvatarFaceImage(avatarId);
460 if(bodyImage == null){
461 bodyImage = LocalAvatarImg.getAvatarBodyImage(avatarId);
464 avatarPics.setAvatarFaceImage(avatar, faceImage);
465 avatarPics.setAvatarBodyImage(avatar, bodyImage);
474 private void saveNetConfig(){
475 if( ! getConfigStore().useStoreFile() ) return;
477 JsObject root = new JsObject();
478 JsObject proxy = ProxyInfo.buildJson(getProxyInfo());
479 root.putValue(HASH_PROXY, proxy);
481 if(this.loadedNetConfig != null){
482 if(this.loadedNetConfig.equals(root)) return;
485 this.configStore.saveNetConfig(root);
493 private void saveTalkConfig(){
494 if( ! getConfigStore().useStoreFile() ) return;
496 JsObject root = new JsObject();
498 JsObject font = Font2Json.buildJson(getFontInfo());
499 root.putValue(HASH_FONT, font);
501 DialogPref pref = getDialogPref();
503 new JsPair(HASH_USEBODYICON, pref.useBodyImage());
505 new JsPair(HASH_USEMONOTOMB, pref.useMonoImage());
507 new JsPair(HASH_SIMPLEMODE, pref.isSimpleMode());
509 new JsPair(HASH_ALIGNBALOON, pref.alignBaloonWidth());
510 root.putPair(useBodyIcon);
511 root.putPair(useMonoTomb);
512 root.putPair(isSimple);
513 root.putPair(alignBaloon);
515 if(this.loadedTalkConfig != null){
516 if(this.loadedTalkConfig.equals(root)) return;
519 this.configStore.saveTalkConfig(root);
525 * 各種設定を設定格納ディレクトリからロードする。
527 public void loadConfig(){
530 loadLocalImageConfig();
535 * 各種設定を設定格納ディレクトリへセーブする。
537 public void saveConfig(){