1 package charactermanaj.model;
4 import java.beans.PropertyChangeListener;
5 import java.beans.PropertyChangeSupport;
6 import java.io.BufferedOutputStream;
8 import java.io.FileNotFoundException;
9 import java.io.FileOutputStream;
10 import java.io.IOException;
11 import java.io.InputStream;
12 import java.io.OutputStream;
15 import java.nio.charset.Charset;
16 import java.util.ArrayList;
17 import java.util.Collections;
18 import java.util.HashMap;
19 import java.util.HashSet;
20 import java.util.List;
21 import java.util.Locale;
23 import java.util.Properties;
25 import java.util.logging.Level;
26 import java.util.logging.Logger;
27 import java.util.regex.Pattern;
29 import charactermanaj.util.ApplicationLogHandler;
30 import charactermanaj.util.BeanPropertiesUtilities;
31 import charactermanaj.util.BeanPropertiesUtilities.PropertyAccessor;
32 import charactermanaj.util.BeanPropertiesUtilities.PropertyAccessorMap;
33 import charactermanaj.util.ConfigurationDirUtilities;
36 * アプリケーションの全域にわたる設定.<br>
37 * アプリケーション設定は、クラスパス上のリソース、コートベース直下のappConfig.xml、ユーザーごとのappConfig.xmlの順に読み込まれます.<br>
38 * 設定値は{@link BeanPropertiesUtilities}によってXMLプロパティファイルとして永続化されます。<br>
41 * @see BeanPropertiesUtilities
43 public final class AppConfig {
48 private static final String CONFIG_NAME = "appConfig.xml";
51 * 全ユーザー用キャラクターディレクトリのシステムプロパティのキー名.<br>
53 public static final String COMMON_CHARACTER_DIR_PROPERTY_NAME = "character.dir";
58 private static final String DEFAULT_SPECIFICATION_VERSION = "1.0";
64 private static final Logger logger = Logger.getLogger(AppConfig.class.getName());
70 private static final AppConfig singleton = new AppConfig();
75 private final PropertyChangeSupport propChangeSupport = new PropertyChangeSupport(this);
78 public void addPropertyChangeListener(PropertyChangeListener listener) {
79 propChangeSupport.addPropertyChangeListener(listener);
82 public void removePropertyChangeListener(PropertyChangeListener listener) {
83 propChangeSupport.removePropertyChangeListener(listener);
86 public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) {
87 propChangeSupport.addPropertyChangeListener(propertyName, listener);
90 public void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) {
91 propChangeSupport.removePropertyChangeListener(propertyName, listener);
99 public static AppConfig getInstance() {
106 private AppConfig() {
110 private String implementationVersion;
112 private String specificationVersion;
116 * ビルドされたjarパッケージからバージョン情報を取得する.<br>
117 * クラスパスの実行からのバージョンは常に「develop」となる.<br>
121 public String getImplementationVersion() {
122 return implementationVersion;
127 * ビルドされたjarパッケージからバージョン情報を取得する.<br>
128 * クラスパスの実行からのバージョンは常に「develop」となる.<br>
132 public String getSpecificationVersion() {
133 return specificationVersion;
137 * ビルドされたjarパッケージからバージョン情報を取得する.<br>
138 * クラスパスの実行からのバージョンは常に「develop」となる.<br>
140 private void loadAppVersions() {
141 Package pak = this.getClass().getPackage();
142 String implementationVersion = "develop";
143 String specificationVersion = DEFAULT_SPECIFICATION_VERSION;
145 String vInfo = pak.getImplementationVersion();
146 if (vInfo != null && implementationVersion.trim().length() > 0) {
147 implementationVersion = vInfo.trim();
149 String specVInfo = pak.getSpecificationVersion();
150 if (specVInfo != null && specVInfo.trim().length() > 0) {
151 specificationVersion = specVInfo.trim();
155 this.implementationVersion = implementationVersion;
156 this.specificationVersion = specificationVersion;
160 * 設定ファイルのロケール固有版へのファイル末尾の修飾文字列を読み込み順に取得する.
161 * @param locale ロケール、nullの場合はデフォルト
162 * @return ロケールを表すファイル末尾の修飾文字列の読み込み順のリスト
164 private String[] getLocalizedSuffix(Locale locale) {
165 if (locale == null) {
166 locale = Locale.getDefault();
169 String language = locale.getLanguage();
170 String country = locale.getCountry();
171 String variant = locale.getVariant();
173 return new String[] {
176 "_" + language + "_" + country,
177 "_" + language + "_" + country + "_" + variant,
182 * 指定されたファイル名の拡張子の前にロケール固有の修飾文字列を付与したリスト作成して返す.
184 * @param locale ロケール、nullの場合はデフォルト
185 * @return ロケールの検索順序でのロケール固有の修飾文字列が付与されたファイルのリスト
187 private List<File> expandLocalizedSuffix(File base, Locale locale) {
188 String path = base.getPath();
190 int pt = path.lastIndexOf(".");
193 left = path.substring(0, pt);
194 right = path.substring(pt);
201 ArrayList<File> files = new ArrayList<File>();
202 for (String suffix : getLocalizedSuffix(locale)) {
203 String newPath = left + suffix + right;
204 //System.out.println("newpath=" + newPath);
205 files.add(new File(newPath));
211 * 設定ファイルの読み込み順序で、読み込むべきURIのリストを返す.<br>
213 * <li>(1) リソース上の/appConfig.xml</li>
214 * <li>(2) appConfigFileシステムプロパティで指定されたファイル</li>
215 * <li>(3) コードベース下のappConfig.xml</li>
216 * <li>(4) アプリケーションデータ保存先のappConfig.xml</li>
218 * appConfigFileシステムプロパティがある場合は、(1)(2)の順。 <br>
219 * 指定がない場合は、(1)(3)(4)の順に読み取る.<br>
221 * @return 優先順位での設定ファイルの読み込み先URIのリスト
222 * @throws IOException
224 public List<URI> getCandidateURIs() throws IOException {
225 List<URI> uris = new ArrayList<URI>();
226 // リソース中の既定 (ロケール識別あり)
227 getAppConfigResourceURI(uris);
229 // システムプロパティでappConfig.xmlを明示している場合は、それを読み込む。
230 // (appConfigFileシステムプロパティが空の場合は、リソース埋め込みの既定の設定だけをよみこむ)
231 String specifiedAppConfig = System.getProperty("appConfigFile");
232 if (specifiedAppConfig != null) {
233 if (specifiedAppConfig.trim().length() > 0) {
234 File specifiedAppConfigFile = new File(specifiedAppConfig);
235 uris.add(specifiedAppConfigFile.toURI());
239 // システムプロパティて明示していない場合は、まずコードベースを使用する.(ロケール識別あり)
240 File codeBase = ConfigurationDirUtilities.getApplicationBaseDir();
241 for (File localizedFile : expandLocalizedSuffix(new File(codeBase,
242 CONFIG_NAME).getCanonicalFile(), null)) {
243 uris.add(localizedFile.toURI());
246 // システムプロパティて明示していない場合は、次にユーザディレクトリを使用する.
247 File userDataDir = ConfigurationDirUtilities.getUserDataDir();
248 uris.add(new File(userDataDir, CONFIG_NAME).toURI());
254 * リソース上のAppConfigの読み込みURIを追記して返す
257 protected void getAppConfigResourceURI(List<URI> uris) {
258 for (File localizedFile : expandLocalizedSuffix(new File(getClass()
259 .getResource("/" + CONFIG_NAME).getPath()), null)) {
260 uris.add(localizedFile.toURI());
265 * 保存先の試行順序ごとのファイルのリスト。
269 public List<File> getPrioritySaveFileList() {
270 ArrayList<File> saveFiles = new ArrayList<File>();
272 String specifiedAppConfig = System.getProperty("appConfigFile");
273 if (specifiedAppConfig != null) {
274 // システムプロパティでappConfig.xmlを明示している場合
275 if (specifiedAppConfig.trim().length() > 0) {
276 File specifiedAppConfigFile = new File(specifiedAppConfig);
277 if (!specifiedAppConfigFile.exists()
278 || specifiedAppConfigFile.canWrite()) {
279 // まだ存在しないか、書き込み可能である場合のみ候補とする.
280 saveFiles.add(specifiedAppConfigFile);
284 // システムプロパティappConfigFileがなければユーザディレクトリへ書き込む
285 // ユーザディレクトリは常に候補とする.
286 File userDataDir = ConfigurationDirUtilities.getUserDataDir();
287 saveFiles.add(new File(userDataDir, CONFIG_NAME));
295 * 存在しないか、読み取りに失敗した場合は、該当ファイルはスキップされる.<br>
297 public void loadConfig() {
299 loadConfig(getCandidateURIs());
300 } catch (IOException ex) {
301 throw new RuntimeException("appConfig.xml loading failed.", ex);
307 * 存在しないか、読み取りに失敗した場合は、該当ファイルはスキップされる.<br>
308 * @param uris パラメーターの読み込み順
310 public void loadConfig(List<URI> uris) {
312 uris = Collections.emptyList();
314 Properties config = new Properties();
316 for (URI uri : uris) {
318 continue; // リソースがない場合はnullになる
320 // ファイルの実在チェック (チェックできる場合のみ)
321 if ("file".equals(uri.getScheme())) {
322 File file = new File(uri);
323 if (!file.exists()) {
324 logger.log(Level.CONFIG, "appConfig.xml is not found.:" + file);
328 // appConfig.xmlの読み込みを行う.
329 // Properties#loadFromXML() はXMLからキーを読み取り、既存のキーに対して上書きする.
330 // XMLに存在しないキーは読み込み前のままなので、繰り返し呼び出すことで「重ね合わせ」することができる.
332 URL resourceURL = uri.toURL();
333 InputStream is = resourceURL.openStream();
335 config.loadFromXML(is);
336 logger.log(Level.CONFIG, "appConfig.xml is loaded.:" + uri);
341 } catch (FileNotFoundException ex) {
342 logger.log(Level.CONFIG, "appConfig.xml is not found.: " + uri, ex);
343 // 無視する (無い場合は十分にありえるので「情報」レベルでログ。)
344 } catch (Exception ex) {
345 logger.log(Level.WARNING, "appConfig.xml loading failed.: " + uri, ex);
350 } catch (RuntimeException ex) {
351 throw new RuntimeException("appConfig.xml loading failed.", ex);
353 BeanPropertiesUtilities.loadFromProperties(this, config);
357 * プロパティをアプリケーションデータの指定した保存先に保存する.
359 * @throws IOException
362 public void saveConfig(List<File> prioritySaveFiles) throws IOException {
363 Properties config = getProperties();
364 IOException oex = null;
365 for (File configStore : prioritySaveFiles) {
367 OutputStream os = new BufferedOutputStream(
368 new FileOutputStream(configStore));
370 config.storeToXML(os, CONFIG_NAME, "UTF-8");
377 } catch (IOException ex) {
378 logger.log(Level.WARNING, "アプリケーション設定の保存に失敗しました" + ex, ex);
383 // 例外が発生していれば、最後の例外を返す.
390 * プロパティをアプリケーションデータの保存先に保存する.
392 * @throws IOException
395 public void saveConfig() throws IOException {
396 saveConfig(getPrioritySaveFileList());
400 * アプリケーション設定値のデフォルト値(リソース上のAppConfigのみ)を取得する
403 public static Map<String, Object> getDefaultProperties() {
404 PropertyAccessorMap<AppConfig> accessorMap = BeanPropertiesUtilities.getPropertyAccessorMap(AppConfig.class);
406 AppConfig dummy = new AppConfig(); // アプリケーションから参照されないダミーのインスタンスを作成する.
408 // リソース上のAppConfigのみ読み込み
409 List<URI> uris = new ArrayList<URI>();
410 dummy.getAppConfigResourceURI(uris);
411 dummy.loadConfig(uris);
413 accessorMap.setBean(dummy);
416 Map<String, Object> defMap = new HashMap<String, Object>();
417 for (Map.Entry<String, PropertyAccessor> propEntry : accessorMap.entrySet()) {
418 String name = propEntry.getKey();
419 PropertyAccessor accessor = propEntry.getValue();
420 Object value = accessor.getValue();
421 defMap.put(name, value);
427 * Propertiesの値を設定した場合に設定できない項目があるかチェックする.<br>
428 * このメソッドを呼び出しても、アプリケーション設定自身は何も影響されない.<br>
432 * @return 設定できなかったプロパティキーのコレクション、問題なければ空が返される.
434 public static Set<String> checkProperties(Map<String, Object> props) {
436 throw new IllegalArgumentException();
438 AppConfig dummy = new AppConfig(); // アプリケーションから参照されないダミーのインスタンスを作成する.
439 return update(props, dummy);
444 * Propertiesの値で設定を更新する.<br>
448 * @return 設定できなかったプロパティキーのコレクション、問題なければ空が返される.
450 public Set<String> update(Map<String, Object> props) {
451 return update(props, this);
455 * Propertiesの値で設定を更新する.<br>
460 * 適用するAppConfigのインスタンス(ドライランと本番の切り替え用)
461 * @return 設定できなかったプロパティキーのコレクション、問題なければ空が返される.
463 private static Set<String> update(Map<String, Object> props, AppConfig bean) {
465 throw new IllegalArgumentException();
467 HashSet<String> rejectedNames = new HashSet<String>();
469 PropertyAccessorMap<AppConfig> accessorMap = BeanPropertiesUtilities.getPropertyAccessorMap(AppConfig.class);
470 accessorMap.setBean(bean);
472 for (Map.Entry<String, Object> propEntry : props.entrySet()) {
473 String name = propEntry.getKey();
474 Object value = propEntry.getValue();
476 PropertyAccessor accessor = accessorMap.get(name);
477 if (accessor == null) {
479 rejectedNames.add(name);
483 Class<?> propertyType = accessor.getPropertyType();
484 if (propertyType.isPrimitive() && value == null) {
485 // プリミティブ型なのにnullは入れられない
486 rejectedNames.add(name);
491 accessor.setValue(value);
493 } catch (Exception ex) {
494 // 何らかの理由でプロパティの設定に失敗している場合
495 rejectedNames.add(name);
496 logger.log(Level.WARNING, "invalid propery: " + name + " /val=" + value, ex);
500 return rejectedNames;
504 * このアプリケーション設定をプロパティに書き出して返します.<br>
508 public Properties getProperties() {
509 Properties config = new Properties();
510 BeanPropertiesUtilities.saveToProperties(this, config);
516 * プロファイル選択ダイアログのプロファイルのサンプルイメージの背景色
518 * @return サンプルイメージの背景色
520 public Color getSampleImageBgColor() {
521 return sampleImageBgColor;
524 public static final String SAMPLE_IMAGE_BG_COLOR = "sampleImageBgColor";
526 public void setSampleImageBgColor(Color sampleImageBgColor) {
527 if (sampleImageBgColor == null) {
528 throw new IllegalArgumentException();
530 Color old = this.sampleImageBgColor;
531 if (old == null ? sampleImageBgColor != null : !old.equals(sampleImageBgColor)) {
532 this.sampleImageBgColor = sampleImageBgColor;
533 propChangeSupport.firePropertyChange(SAMPLE_IMAGE_BG_COLOR, old, sampleImageBgColor);
537 private Color sampleImageBgColor = Color.white;
541 * デフォルトのイメージ背景色を取得する.
543 * @return デフォルトのイメージ背景色
545 public Color getDefaultImageBgColor() {
546 return defaultImageBgColor;
549 public static final String DEFAULT_IMAGE_BG_COLOR = "defaultImageBgColor";
551 public void setDefaultImageBgColor(Color defaultImageBgColor) {
552 if (defaultImageBgColor == null) {
553 throw new IllegalArgumentException();
555 Color old = this.defaultImageBgColor;
556 if (old == null ? defaultImageBgColor != null : !old.equals(defaultImageBgColor)) {
557 this.defaultImageBgColor = defaultImageBgColor;
558 propChangeSupport.firePropertyChange(DEFAULT_IMAGE_BG_COLOR, old, defaultImageBgColor);
562 private Color defaultImageBgColor = Color.white;
567 * @return 使用中アイテムの背景色
569 public Color getCheckedItemBgColor() {
570 return checkedItemBgColor;
573 public static final String CHECKED_ITEM_BG_COLOR = "checkedItemBgColor";
575 public void setCheckedItemBgColor(Color checkedItemBgColor) {
576 if (checkedItemBgColor == null) {
577 throw new IllegalArgumentException();
579 Color old = this.checkedItemBgColor;
580 if (old == null ? checkedItemBgColor != null : !old.equals(checkedItemBgColor)) {
581 this.checkedItemBgColor = checkedItemBgColor;
582 propChangeSupport.firePropertyChange(CHECKED_ITEM_BG_COLOR, old, checkedItemBgColor);
586 private Color checkedItemBgColor = Color.cyan.brighter();
594 public Color getSelectedItemBgColor() {
595 return selectedItemBgColor;
598 public static final String SELECTED_ITEM_BG_COLOR = "selectedItemBgColor";
600 public void setSelectedItemBgColor(Color selectedItemBgColor) {
601 if (selectedItemBgColor == null) {
602 throw new IllegalArgumentException();
604 Color old = this.selectedItemBgColor;
605 if (old == null ? selectedItemBgColor != null : !old.equals(selectedItemBgColor)) {
606 this.selectedItemBgColor = selectedItemBgColor;
607 propChangeSupport.firePropertyChange(SELECTED_ITEM_BG_COLOR, old, selectedItemBgColor);
611 private Color selectedItemBgColor = Color.orange;
614 * 不備のあるデータ行の背景色を取得する.
616 * @return 不備のあるデータ行の背景色
618 public Color getInvalidBgColor() {
619 return invalidBgColor;
622 public static final String INVALID_BG_COLOR = "invalidBgColor";
624 public void setInvalidBgColor(Color invalidBgColor) {
625 if (invalidBgColor == null) {
626 throw new IllegalArgumentException();
628 Color old = this.invalidBgColor;
629 if (old == null ? invalidBgColor != null : !old.equals(invalidBgColor)) {
630 this.invalidBgColor = invalidBgColor;
631 propChangeSupport.firePropertyChange(INVALID_BG_COLOR, old, invalidBgColor);
635 private Color invalidBgColor = Color.red.brighter().brighter();
638 * JPEG画像変換時の圧縮率を取得する.
642 public float getCompressionQuality() {
643 return compressionQuality;
646 public static final String COMPRESSION_QUALITY = "compressionQuality";
648 public void setCompressionQuality(float compressionQuality) {
649 if (compressionQuality < .1f || compressionQuality > 1f) {
650 throw new IllegalArgumentException();
652 float old = this.compressionQuality;
653 if (old != compressionQuality) {
654 this.compressionQuality = compressionQuality;
655 propChangeSupport.firePropertyChange(COMPRESSION_QUALITY, old, compressionQuality);
659 private float compressionQuality = .8f;
662 * エクスポートウィザードのプリセットにパーツ不足時の警告色(前景色)を取得する.
664 * @return エクスポートウィザードのプリセットにパーツ不足時の警告色(前景色)
666 public Color getExportPresetWarningsForegroundColor() {
667 return exportPresetWarningsForegroundColor;
670 public static final String EXPORT_PRESET_WARNINGS_FOREGROUND_COLOR = "exportPresetWarningsForegroundColor";
672 public void setExportPresetWarningsForegroundColor(Color exportPresetWarningsForegroundColor) {
673 if (exportPresetWarningsForegroundColor == null) {
674 throw new IllegalArgumentException();
676 Color old = this.exportPresetWarningsForegroundColor;
677 if (old == null ? exportPresetWarningsForegroundColor != null
678 : !old.equals(exportPresetWarningsForegroundColor)) {
679 this.exportPresetWarningsForegroundColor = exportPresetWarningsForegroundColor;
680 propChangeSupport.firePropertyChange(EXPORT_PRESET_WARNINGS_FOREGROUND_COLOR, old,
681 exportPresetWarningsForegroundColor);
685 private Color exportPresetWarningsForegroundColor = Color.red;
688 * JARファイル転送用バッファサイズ.<br>
690 * @return JARファイル転送用バッファサイズ.
692 public int getJarTransferBufferSize() {
693 return jarTransferBufferSize;
696 public static final String JAR_TRANSFER_BUFFER_SIZE = "jarTransferBufferSize";
698 public void setJarTransferBufferSize(int jarTransferBufferSize) {
699 if (jarTransferBufferSize <= 0) {
700 throw new IllegalArgumentException();
702 int old = this.jarTransferBufferSize;
703 if (old != jarTransferBufferSize) {
704 this.jarTransferBufferSize = jarTransferBufferSize;
705 propChangeSupport.firePropertyChange(JAR_TRANSFER_BUFFER_SIZE, old, jarTransferBufferSize);
709 private int jarTransferBufferSize = 4096;
712 * ZIPファイル名のエンコーディング.<br>
714 * @return ZIPファイル名のエンコーディング.<br>
716 public String getZipNameEncoding() {
717 return zipNameEncoding;
720 public static final String ZIP_NAME_ENCODING = "zipNameEncoding";
722 public void setZipNameEncoding(String zipNameEncoding) {
723 if (zipNameEncoding == null) {
724 throw new IllegalArgumentException();
727 Charset.forName(zipNameEncoding);
728 } catch (Exception ex) {
729 throw new RuntimeException("unsupported charset: " + zipNameEncoding);
731 String old = this.zipNameEncoding;
732 if (old == null ? zipNameEncoding != null : !old.equals(zipNameEncoding)) {
733 this.zipNameEncoding = zipNameEncoding;
734 propChangeSupport.firePropertyChange(ZIP_NAME_ENCODING, old, zipNameEncoding);
738 private String zipNameEncoding = "csWindows31J";
741 * ディセーブルなテーブルのセルのフォアグラウンドカラーを取得する.
743 * @return ディセーブルなテーブルのセルのフォアグラウンドカラー
745 public Color getDisabledCellForgroundColor() {
746 return disabledCellForegroundColor;
749 public static final String DISABLED_CELL_FOREGROUND_COLOR = "disabledCellForegroundColor";
751 public void setDisabledCellForegroundColor(Color disabledCellForegroundColor) {
752 if (disabledCellForegroundColor == null) {
753 throw new IllegalArgumentException();
755 Color old = this.disabledCellForegroundColor;
756 if (old == null ? disabledCellForegroundColor != null : !old.equals(disabledCellForegroundColor)) {
757 this.disabledCellForegroundColor = disabledCellForegroundColor;
758 propChangeSupport.firePropertyChange(DISABLED_CELL_FOREGROUND_COLOR, old, disabledCellForegroundColor);
762 private Color disabledCellForegroundColor = Color.gray;
766 * ディレクトリを監視する間隔(mSec)を取得する.
768 * @return ディレクトリを監視する間隔(mSec)
770 public int getDirWatchInterval() {
771 return dirWatchInterval;
774 public static final String DIR_WATCH_INTERVAL = "dirWatchInterval";
776 public void setDirWatchInterval(int dirWatchInterval) {
777 if (dirWatchInterval <= 0) {
778 throw new IllegalArgumentException();
780 int old = this.dirWatchInterval;
781 if (old != dirWatchInterval) {
782 this.dirWatchInterval = dirWatchInterval;
783 propChangeSupport.firePropertyChange(DIR_WATCH_INTERVAL, old, dirWatchInterval);
787 private int dirWatchInterval = 7 * 1000;
792 * @return ディレクトリの監視を有効にする場合はtrue
794 public boolean isEnableDirWatch() {
795 return enableDirWatch;
798 public static final String ENABLE_DIR_WATCH = "enableDirWatch";
800 public void setEnableDirWatch(boolean enableDirWatch) {
801 boolean old = this.enableDirWatch;
802 if (old != enableDirWatch) {
803 this.enableDirWatch = enableDirWatch;
804 propChangeSupport.firePropertyChange(ENABLE_DIR_WATCH, old, enableDirWatch);
808 private boolean enableDirWatch = true;
811 * ファイル転送に使うバッファサイズ.<br>
815 public int getFileTransferBufferSize() {
816 return fileTransferBufferSize;
819 public static final String FILE_TRANSFER_BUFFER_SIZE = "fileTransferBufferSize";
821 public void setFileTransferBufferSize(int fileTransferBufferSize) {
822 if (fileTransferBufferSize <= 0) {
823 throw new IllegalArgumentException();
825 int old = this.fileTransferBufferSize;
826 if (old != fileTransferBufferSize) {
827 this.fileTransferBufferSize = fileTransferBufferSize;
828 propChangeSupport.firePropertyChange(FILE_TRANSFER_BUFFER_SIZE, old, fileTransferBufferSize);
832 private int fileTransferBufferSize = 4096;
835 * プレビューのインジケータを表示するまでのディレイ(mSec)を取得する.
837 * @return プレビューのインジケータを表示するまでのディレイ(mSec)
839 public long getPreviewIndicatorDelay() {
840 return previewIndeicatorDelay;
843 public static final String PREVIEW_INDEICATOR_DELAY = "previewIndeicatorDelay";
845 public void setPreviewIndeicatorDelay(long previewIndeicatorDelay) {
846 if (previewIndeicatorDelay < 0) {
847 throw new IllegalArgumentException();
849 long old = this.previewIndeicatorDelay;
850 if (old != previewIndeicatorDelay) {
851 this.previewIndeicatorDelay = previewIndeicatorDelay;
852 propChangeSupport.firePropertyChange(PREVIEW_INDEICATOR_DELAY, old, previewIndeicatorDelay);
856 private long previewIndeicatorDelay = 300;
859 * 情報ダイアログの編集ボタンを「開く」アクションにする場合はtrue、「編集」アクションにする場合はfalse
861 * @return trueならばOpen、falseならばEdit
863 public boolean isInformationDialogOpenMethod() {
864 return informationDialogOpenMethod;
867 public static final String INFORMATION_DIALOG_OPEN_METHOD = "informationDialogOpenMethod";
869 public void setInformationDialogOpenMethod(
870 boolean informationDialogOpenMethod) {
871 boolean old = this.informationDialogOpenMethod;
872 if (old != informationDialogOpenMethod) {
873 this.informationDialogOpenMethod = informationDialogOpenMethod;
874 propChangeSupport.firePropertyChange("informationDialogOpenMethod", old, informationDialogOpenMethod);
878 private boolean informationDialogOpenMethod = true;
882 * falseの場合は{@link ApplicationLogHandler}の実装に従って終了時に 必要なければログは削除される.<br>
884 * @return 常に残す場合はtrue、そうでなければfalse
886 public boolean isNoRemoveLog() {
890 public static final String NO_REMOVE_LOG = "noRemoveLog";
892 public void setNoRemoveLog(boolean noRemoveLog) {
893 boolean old = this.noRemoveLog;
894 if (old != noRemoveLog) {
895 this.noRemoveLog = noRemoveLog;
896 propChangeSupport.firePropertyChange(NO_REMOVE_LOG, old, noRemoveLog);
900 private boolean noRemoveLog = false;
908 public Color getGridColor() {
912 public static final String GRID_COLOR = "gridColor";
914 public void setGridColor(Color gridColor) {
915 if (gridColor == null) {
916 throw new IllegalArgumentException();
918 Color old = this.gridColor;
919 if (old == null ? gridColor != null : !old.equals(gridColor)) {
920 this.gridColor = gridColor;
921 propChangeSupport.firePropertyChange(GRID_COLOR, old, gridColor);
925 private Color gridColor = Color.gray;
928 * カラーダイアログの値が変更されたら、自動的にプレビューを更新するか?
930 * @return カラーダイアログの値が変更されたら、自動的にプレビューを更新する場合はtrue (デフォルトはtrue)
932 public boolean isEnableAutoColorChange() {
933 return enableAutoColorChange;
936 public static final String ENABLE_AUTO_COLOR_CHANGE = "enableAutoColorChange";
938 public void setEnableAutoColorChange(boolean enableAutoColorChange) {
939 boolean old = this.enableAutoColorChange;
940 if (old != enableAutoColorChange) {
941 this.enableAutoColorChange = enableAutoColorChange;
942 propChangeSupport.firePropertyChange(ENABLE_AUTO_COLOR_CHANGE, old, enableAutoColorChange);
946 private boolean enableAutoColorChange = true;
948 public static final String AUTHOR_EDIT_CONFLICT_BG_COLOR = "authorEditConflictBgColor";
950 public void setAuthorEditConflictBgColor(Color authorEditConflictBgColor) {
951 if (authorEditConflictBgColor == null) {
952 throw new IllegalArgumentException();
954 Color old = this.authorEditConflictBgColor;
955 if (old == null ? authorEditConflictBgColor != null : !old.equals(authorEditConflictBgColor)) {
956 this.authorEditConflictBgColor = authorEditConflictBgColor;
957 propChangeSupport.firePropertyChange(AUTHOR_EDIT_CONFLICT_BG_COLOR, old, authorEditConflictBgColor);
962 * パーツの作者編集時に複数作者を選択した場合のに入力ボックスの背景色
966 public Color getAuthorEditConflictBgColor() {
967 return authorEditConflictBgColor;
970 Color authorEditConflictBgColor = Color.yellow;
973 public static final String MAIN_FRAME_MAX_WIDTH = "mainFrameMaxWidth";
975 public void setMainFrameMaxWidth(int mainFrameMaxWidth) {
976 int old = mainFrameMaxWidth;
977 if (old != mainFrameMaxWidth) {
978 this.mainFrameMaxWidth = mainFrameMaxWidth;
979 propChangeSupport.firePropertyChange(MAIN_FRAME_MAX_WIDTH, old, mainFrameMaxWidth);
986 * @return メインフレームの初期表示時の最大幅
988 public int getMainFrameMaxWidth() {
989 return mainFrameMaxWidth;
992 private int mainFrameMaxWidth = 800;
994 public static final String MAIN_FRAME_MAX_HEIGHT = "mainFrameMaxHeight";
996 public void setMainFrameMaxHeight(int mainFrameMaxHeight) {
997 int old = this.mainFrameMaxHeight;
998 if (old != mainFrameMaxHeight) {
999 this.mainFrameMaxHeight = mainFrameMaxHeight;
1000 propChangeSupport.firePropertyChange(MAIN_FRAME_MAX_HEIGHT, old, mainFrameMaxHeight);
1005 * メインフレームの初期表示時の最大高さ
1007 * @return メインフレームの初期表示時の最大高さ
1009 public int getMainFrameMaxHeight() {
1010 return mainFrameMaxHeight;
1013 private int mainFrameMaxHeight = 600;
1017 * カラーダイアログで存在しないレイヤーをディセーブルにしない.
1019 * @return ディセーブルにしない場合はtrue
1021 public boolean isNotDisableLayerTab() {
1022 return notDisableLayerTab;
1025 public static final String NOT_DISABLE_LAYER_TAB = "notDisableLayerTab";
1027 public void setNotDisableLayerTab(boolean notDisableLayerTab) {
1028 boolean old = this.notDisableLayerTab;
1029 if (old != notDisableLayerTab) {
1030 this.notDisableLayerTab = notDisableLayerTab;
1031 propChangeSupport.firePropertyChange(NOT_DISABLE_LAYER_TAB, old, notDisableLayerTab);
1035 private boolean notDisableLayerTab;
1040 * この指定日を経過した古いログは削除される.<br>
1045 public long getPurgeLogDays() {
1046 return purgeLogDays;
1049 public static final String PURGE_LOG_DAYS = "purgeLogDays";
1051 public void setPurgeLogDays(long purgeLogDays) {
1052 long old = this.purgeLogDays;
1053 if (old != purgeLogDays) {
1054 this.purgeLogDays = purgeLogDays;
1055 propChangeSupport.firePropertyChange(PURGE_LOG_DAYS, old, purgeLogDays);
1059 private long purgeLogDays = 10;
1061 public String getPartsColorGroupPattern() {
1062 return partsColorGroupPattern;
1065 public static final String PARTS_COLOR_GROUP_PATTERN = "partsColorGroupPattern";
1067 public void setPartsColorGroupPattern(String pattern) {
1068 if (pattern != null && pattern.trim().length() > 0) {
1069 Pattern.compile(pattern);
1071 String old = this.partsColorGroupPattern;
1072 if (old == null ? pattern != null : !old.equals(pattern)) {
1073 this.partsColorGroupPattern = pattern;
1074 propChangeSupport.firePropertyChange(PARTS_COLOR_GROUP_PATTERN, old, pattern);
1078 private String partsColorGroupPattern = "^.*\\(@\\).*$";
1080 private Color selectPanelTitleColor = Color.BLUE;
1082 public Color getSelectPanelTitleColor() {
1083 return selectPanelTitleColor;
1086 public static final String SELECT_PANEL_TITLE_COLOR = "selectPanelTitleColor";
1088 public void setSelectPanelTitleColor(Color selectPanelTitleColor) {
1089 if (selectPanelTitleColor == null) {
1090 throw new IllegalArgumentException();
1092 Color old = this.selectPanelTitleColor;
1093 if (old == null ? selectPanelTitleColor != null : !old.equals(selectPanelTitleColor)) {
1094 this.selectPanelTitleColor = selectPanelTitleColor;
1095 propChangeSupport.firePropertyChange(SELECT_PANEL_TITLE_COLOR, old, selectPanelTitleColor);
1099 private boolean enableAutoShrinkPanel;
1101 public boolean isEnableAutoShrinkPanel() {
1102 return enableAutoShrinkPanel;
1105 public static final String ENABLE_AUTO_SHRINK_PANEL = "enableAutoShrinkPanel";
1107 public void setEnableAutoShrinkPanel(boolean enableAutoShrinkPanel) {
1108 boolean old = this.enableAutoShrinkPanel;
1109 if (old != enableAutoShrinkPanel) {
1110 this.enableAutoShrinkPanel = enableAutoShrinkPanel;
1111 propChangeSupport.firePropertyChange(ENABLE_AUTO_SHRINK_PANEL, old, enableAutoShrinkPanel);
1115 public boolean isDisableWatchDirIfNotWritable() {
1116 return disableWatchDirIfNotWritable;
1119 public static final String DISABLE_WATCH_DIR_IF_NOT_WRITABLE = "disableWatchDirIfNotWritable";
1121 public void setDisableWatchDirIfNotWritable(boolean disableWatchDirIfNotWritable) {
1122 boolean old = this.disableWatchDirIfNotWritable;
1123 if (old != disableWatchDirIfNotWritable) {
1124 this.disableWatchDirIfNotWritable = disableWatchDirIfNotWritable;
1125 propChangeSupport.firePropertyChange(DISABLE_WATCH_DIR_IF_NOT_WRITABLE, old, disableWatchDirIfNotWritable);
1129 private boolean disableWatchDirIfNotWritable = true;
1131 public static final String ENABLE_PNG_SUPPORT_FOR_WINDOWS = "enablePNGSupportForWindows";
1133 public void setEnablePNGSupportForWindows(boolean enablePNGSupportForWindows) {
1134 boolean old = this.enablePNGSupportForWindows;
1135 if (old != enablePNGSupportForWindows) {
1136 this.enablePNGSupportForWindows = enablePNGSupportForWindows;
1137 propChangeSupport.firePropertyChange(ENABLE_PNG_SUPPORT_FOR_WINDOWS, old, enablePNGSupportForWindows);
1141 public boolean isEnablePNGSupportForWindows() {
1142 return enablePNGSupportForWindows;
1145 private boolean enablePNGSupportForWindows = true;
1148 * 画像表示(通常モード)でオプティマイズを有効にする最大倍率.
1150 private double renderingOptimizeThresholdForNormal = 2.;
1152 public static final String RENDERING_OPTIMIZE_THRESHOLD_FOR_NORMAL = "renderingOptimizeThresholdForNormal";
1154 public void setRenderingOptimizeThresholdForNormal(
1155 double renderingOptimizeThresholdForNormal) {
1156 double old = this.renderingOptimizeThresholdForNormal;
1157 if (old != renderingOptimizeThresholdForNormal) {
1158 this.renderingOptimizeThresholdForNormal = renderingOptimizeThresholdForNormal;
1159 propChangeSupport.firePropertyChange(RENDERING_OPTIMIZE_THRESHOLD_FOR_NORMAL, old,
1160 renderingOptimizeThresholdForNormal);
1164 public double getRenderingOptimizeThresholdForNormal() {
1165 return renderingOptimizeThresholdForNormal;
1168 * 画像表示(チェックモード)でオプティマイズを有効にする最大倍率.
1170 private double renderingOptimizeThresholdForCheck = 0.;
1172 public static final String RENDERING_OPTIMIZE_THRESHOLD_FOR_CHECK = "renderingOptimizeThresholdForCheck";
1174 public void setRenderingOptimizeThresholdForCheck(
1175 double renderingOptimizeThresholdForCheck) {
1176 double old = this.renderingOptimizeThresholdForCheck;
1177 if (old != renderingOptimizeThresholdForCheck) {
1178 this.renderingOptimizeThresholdForCheck = renderingOptimizeThresholdForCheck;
1179 propChangeSupport.firePropertyChange(RENDERING_OPTIMIZE_THRESHOLD_FOR_CHECK, old,
1180 renderingOptimizeThresholdForCheck);
1184 public double getRenderingOptimizeThresholdForCheck() {
1185 return renderingOptimizeThresholdForCheck;
1191 private boolean enableInterpolationBicubic = true;
1193 public static final String ENABLE_INTERPOLATION_BICUBIC = "enableInterpolationBicubic";
1195 public void setEnableInterpolationBicubic(boolean enableInterpolationBicubic) {
1196 boolean old = this.enableInterpolationBicubic;
1197 if (old != enableInterpolationBicubic) {
1198 this.enableInterpolationBicubic = enableInterpolationBicubic;
1199 propChangeSupport.firePropertyChange(ENABLE_INTERPOLATION_BICUBIC, old, enableInterpolationBicubic);
1203 public boolean isEnableInterpolationBicubic() {
1204 return enableInterpolationBicubic;
1210 private String predefinedZoomRanges = "20, 50, 80, 100, 120, 150, 200, 300, 400, 800";
1212 public String getPredefinedZoomRanges() {
1213 return predefinedZoomRanges;
1216 public static final String PREDEFINED_ZOOM_RANGES = "predefinedZoomRanges";
1218 public void setPredefinedZoomRanges(String predefinedZoomRanges) {
1219 if (predefinedZoomRanges == null) {
1220 throw new IllegalArgumentException();
1222 String old = this.predefinedZoomRanges;
1223 if (old == null ? predefinedZoomRanges != null : !old.equals(predefinedZoomRanges)) {
1224 this.predefinedZoomRanges = predefinedZoomRanges;
1225 propChangeSupport.firePropertyChange(PREDEFINED_ZOOM_RANGES, old, predefinedZoomRanges);
1230 * ズームパネルを初期状態で表示するか?
1232 private boolean enableZoomPanel = true;
1234 public boolean isEnableZoomPanel() {
1235 return enableZoomPanel;
1238 public static final String ENABLE_ZOOM_PANEL = "enableZoomPanel";
1240 public void setEnableZoomPanel(boolean enableZoomPanel) {
1241 boolean old = this.enableZoomPanel;
1242 if (old != enableZoomPanel) {
1243 this.enableZoomPanel = enableZoomPanel;
1244 propChangeSupport.firePropertyChange(ENABLE_ZOOM_PANEL, old, enableZoomPanel);
1249 * ズームパネルをアクティブにする下部範囲
1251 private int zoomPanelActivationArea = 30;
1253 public int getZoomPanelActivationArea() {
1254 return zoomPanelActivationArea;
1257 public static final String ZOOM_PANEL_ACTIVATION_AREA = "zoomPanelActivationArea";
1259 public void setZoomPanelActivationArea(int zoomPanelActivationArea) {
1260 int old = this.zoomPanelActivationArea;
1261 if (old != zoomPanelActivationArea) {
1262 this.zoomPanelActivationArea = zoomPanelActivationArea;
1263 propChangeSupport.firePropertyChange(ZOOM_PANEL_ACTIVATION_AREA, old, zoomPanelActivationArea);
1270 private boolean enableRenderingHints = true;
1272 public static final String ENABLE_RENDERING_HINTS = "enableRenderingHints";
1274 public void setEnableRenderingHints(boolean enableRenderingHints) {
1275 boolean old = this.enableRenderingHints;
1276 if (old != enableRenderingHints) {
1277 this.enableRenderingHints = enableRenderingHints;
1278 propChangeSupport.firePropertyChange(ENABLE_RENDERING_HINTS, old, enableRenderingHints);
1282 public boolean isEnableRenderingHints() {
1283 return enableRenderingHints;
1289 private int drawGridMask = 2;
1291 public int getDrawGridMask() {
1292 return drawGridMask;
1295 public static final String DRAW_GRID_MASK = "drawGridMask";
1297 public void setDrawGridMask(int drawGridMask) {
1298 drawGridMask &= 0x03;
1299 int old = this.drawGridMask;
1300 if (old != drawGridMask) {
1301 this.drawGridMask = drawGridMask;
1302 propChangeSupport.firePropertyChange(DRAW_GRID_MASK, old, drawGridMask);
1306 private Color previewGridColor = new Color(0x7f7f0000, true);
1308 public Color getPreviewGridColor() {
1309 return previewGridColor;
1312 public static final String PREVIEW_GRID_COLOR = "previewGridColor";
1314 public void setPreviewGridColor(Color previewGridColor) {
1315 Color old = this.previewGridColor;
1316 if (old == null ? previewGridColor != null : !old.equals(previewGridColor)) {
1317 this.previewGridColor = previewGridColor;
1318 propChangeSupport.firePropertyChange(PREVIEW_GRID_COLOR, old, previewGridColor);
1322 private int previewGridSize = 20;
1324 public int getPreviewGridSize() {
1325 return previewGridSize;
1328 public static final String PREVIEW_GRID_SIZE = "previewGridSize";
1330 public void setPreviewGridSize(int previewGridSize) {
1331 int old = this.previewGridSize;
1332 if (old != previewGridSize) {
1333 this.previewGridSize = previewGridSize;
1334 propChangeSupport.firePropertyChange(PREVIEW_GRID_SIZE, old, previewGridSize);
1339 * チェックモード時の余白サイズ(片側)
1341 private int previewUnfilledSpaceForCheckMode = 0;
1343 public int getPreviewUnfilledSpaceForCheckMode() {
1344 return previewUnfilledSpaceForCheckMode;
1347 public static final String PREVIEW_UNFILLED_SPACE_FOR_CHECK_MODE = "previewUnfilledSpaceForCheckMode";
1349 public void setPreviewUnfilledSpaceForCheckMode(int previewUnfilledSpaceForCheckMode) {
1350 int old = this.previewUnfilledSpaceForCheckMode;
1351 if (old != previewUnfilledSpaceForCheckMode) {
1352 this.previewUnfilledSpaceForCheckMode = previewUnfilledSpaceForCheckMode;
1353 propChangeSupport.firePropertyChange(PREVIEW_UNFILLED_SPACE_FOR_CHECK_MODE, old,
1354 previewUnfilledSpaceForCheckMode);
1359 * チェックモードでツールチップを表示するか?
1361 private boolean enableCheckInfoTooltip = true;
1363 public boolean isEnableCheckInfoTooltip() {
1364 return enableCheckInfoTooltip;
1367 public static final String ENABLE_CHECK_INFO_TOOLTIP = "enableCheckInfoTooltip";
1369 public void setEnableCheckInfoTooltip(boolean enableCheckInfoTooltip) {
1370 boolean old = this.enableCheckInfoTooltip;
1371 if (old != enableCheckInfoTooltip) {
1372 this.enableCheckInfoTooltip = enableCheckInfoTooltip;
1373 propChangeSupport.firePropertyChange(ENABLE_CHECK_INFO_TOOLTIP, old, enableCheckInfoTooltip);
1378 * ホイールによるスクロールの単位.<br>
1380 private int wheelScrollUnit = 10;
1382 public int getWheelScrollUnit() {
1383 return wheelScrollUnit;
1386 public static final String WHEEL_SCROLL_UNIT = "wheelScrollUnit";
1388 public void setWheelScrollUnit(int wheelScrollUnit) {
1389 int old = this.wheelScrollUnit;
1390 if (old != wheelScrollUnit) {
1391 this.wheelScrollUnit = wheelScrollUnit;
1392 propChangeSupport.firePropertyChange(WHEEL_SCROLL_UNIT, old, wheelScrollUnit);
1397 * 壁紙にオフスクリーン描画を使用するか?.<br>
1398 * (あまり劇的なパフォーマンス効果はない.)
1400 private boolean enableOffscreenWallpaper = false;
1402 public boolean isEnableOffscreenWallpaper() {
1403 return enableOffscreenWallpaper;
1406 public static final String ENABLE_OFFSCREEN_WALLPAPER = "enableOffscreenWallpaper";
1408 public void setEnableOffscreenWallpaper(boolean enableOffscreenWallpaper) {
1409 boolean old = this.enableOffscreenWallpaper;
1410 if (old != enableOffscreenWallpaper) {
1411 this.enableOffscreenWallpaper = enableOffscreenWallpaper;
1412 propChangeSupport.firePropertyChange(ENABLE_OFFSCREEN_WALLPAPER, old, enableOffscreenWallpaper);
1419 private int offscreenWallpaperSize = 300;
1421 public int getOffscreenWallpaperSize() {
1422 return offscreenWallpaperSize;
1425 private static final String OFFSCREEN_WALLPAPER_SIZE = "offscreenWallpaperSize";
1427 public void setOffscreenWallpaperSize(int offscreenWallpaperSize) {
1428 int old = this.offscreenWallpaperSize;
1429 if (old != offscreenWallpaperSize) {
1430 this.offscreenWallpaperSize = offscreenWallpaperSize;
1431 propChangeSupport.firePropertyChange(OFFSCREEN_WALLPAPER_SIZE, old, offscreenWallpaperSize);
1439 private int randomChooserMaxHistory = 10;
1441 public int getRandomChooserMaxHistory() {
1442 return randomChooserMaxHistory;
1445 public static final String RANDOM_CHOOSER_MAX_HISTORY = "randomChooserMaxHistory";
1447 public void setRandomChooserMaxHistory(int randomChooserMaxHistory) {
1448 int old = this.randomChooserMaxHistory;
1449 if (old != randomChooserMaxHistory) {
1450 this.randomChooserMaxHistory = randomChooserMaxHistory;
1451 propChangeSupport.firePropertyChange(RANDOM_CHOOSER_MAX_HISTORY, old, randomChooserMaxHistory);
1456 * デフォルトのフォントサイズ、0以下の場合はシステム既定のまま
1458 private int defaultFontSize = 12;
1460 public int getDefaultFontSize() {
1461 return defaultFontSize;
1464 public static final String DEFAULT_FONT_SIZE = "defaultFontSize";
1466 public void setDefaultFontSize(int defaultFontSize) {
1467 int old = this.defaultFontSize;
1468 if (old != defaultFontSize) {
1469 this.defaultFontSize = defaultFontSize;
1470 propChangeSupport.firePropertyChange(DEFAULT_FONT_SIZE, old, defaultFontSize);
1475 * デフォルトのフォントファミリー、カンマ区切り
1477 private String fontPriority = "Lucida Grande";
1479 public String getFontPriority() {
1480 return fontPriority;
1483 public static final String FONT_PRIORITY = "fontPriority";
1485 public void setFontPriority(String fontPriority) {
1486 if (fontPriority == null) {
1487 throw new IllegalArgumentException();
1489 String old = this.fontPriority;
1490 if (old == null ? fontPriority != null : !old.equals(fontPriority)) {
1491 this.fontPriority = fontPriority;
1492 propChangeSupport.firePropertyChange(FONT_PRIORITY, old, fontPriority);
1497 * ウィンドウの位置、サイズ、スクロールバーの位置、ズームの状態を復元するか?
1499 private boolean enableRestoreWindow = false;
1501 public boolean isEnableRestoreWindow() {
1502 return enableRestoreWindow;
1505 public static final String ENABLE_RESTORE_WINDOW = "enableRestoreWindow";
1507 public void setEnableRestoreWindow(boolean enableRestoreWindow) {
1508 boolean old = this.enableRestoreWindow;
1509 if (old != enableRestoreWindow) {
1510 this.enableRestoreWindow = enableRestoreWindow;
1511 propChangeSupport.firePropertyChange(ENABLE_RESTORE_WINDOW, old, enableRestoreWindow);
1515 private boolean enableColorAdvancedSettings = true;
1517 public boolean isEnableColorAdvancedSettings() {
1518 return enableColorAdvancedSettings;
1521 public static final String ENABLE_COLOR_ADVANCED_SETTINGS = "enableColorAdvancedSettings";
1523 public void setEnableColorAdvancedSettings(boolean enableColorAdvancedSettings) {
1524 boolean old = this.enableColorAdvancedSettings;
1525 if (old != enableColorAdvancedSettings) {
1526 this.enableColorAdvancedSettings = enableColorAdvancedSettings;
1527 propChangeSupport.firePropertyChange(ENABLE_COLOR_ADVANCED_SETTINGS, old, enableRestoreWindow);