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.HashSet;
18 import java.util.List;
19 import java.util.Locale;
21 import java.util.Properties;
23 import java.util.logging.Level;
24 import java.util.logging.Logger;
25 import java.util.regex.Pattern;
27 import charactermanaj.util.ApplicationLogHandler;
28 import charactermanaj.util.BeanPropertiesUtilities;
29 import charactermanaj.util.BeanPropertiesUtilities.PropertyAccessor;
30 import charactermanaj.util.BeanPropertiesUtilities.PropertyAccessorMap;
31 import charactermanaj.util.ConfigurationDirUtilities;
34 * アプリケーションの全域にわたる設定.<br>
35 * アプリケーション設定は、クラスパス上のリソース、コートベース直下のappConfig.xml、ユーザーごとのappConfig.xmlの順に読み込まれます.<br>
36 * 設定値は{@link BeanPropertiesUtilities}によってXMLプロパティファイルとして永続化されます。<br>
39 * @see BeanPropertiesUtilities
41 public final class AppConfig {
46 private static final String CONFIG_NAME = "appConfig.xml";
49 * 全ユーザー用キャラクターディレクトリのシステムプロパティのキー名.<br>
51 public static final String COMMON_CHARACTER_DIR_PROPERTY_NAME = "character.dir";
56 private static final String DEFAULT_SPECIFICATION_VERSION = "1.0";
62 private static final Logger logger = Logger.getLogger(AppConfig.class.getName());
68 private static final AppConfig singleton = new AppConfig();
73 private final PropertyChangeSupport propChangeSupport = new PropertyChangeSupport(this);
76 public void addPropertyChangeListener(PropertyChangeListener listener) {
77 propChangeSupport.addPropertyChangeListener(listener);
80 public void removePropertyChangeListener(PropertyChangeListener listener) {
81 propChangeSupport.removePropertyChangeListener(listener);
84 public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) {
85 propChangeSupport.addPropertyChangeListener(propertyName, listener);
88 public void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) {
89 propChangeSupport.removePropertyChangeListener(propertyName, listener);
97 public static AppConfig getInstance() {
104 private AppConfig() {
108 private String implementationVersion;
110 private String specificationVersion;
114 * ビルドされたjarパッケージからバージョン情報を取得する.<br>
115 * クラスパスの実行からのバージョンは常に「develop」となる.<br>
119 public String getImplementationVersion() {
120 return implementationVersion;
125 * ビルドされたjarパッケージからバージョン情報を取得する.<br>
126 * クラスパスの実行からのバージョンは常に「develop」となる.<br>
130 public String getSpecificationVersion() {
131 return specificationVersion;
135 * ビルドされたjarパッケージからバージョン情報を取得する.<br>
136 * クラスパスの実行からのバージョンは常に「develop」となる.<br>
138 private void loadAppVersions() {
139 Package pak = this.getClass().getPackage();
140 String implementationVersion = "develop";
141 String specificationVersion = DEFAULT_SPECIFICATION_VERSION;
143 String vInfo = pak.getImplementationVersion();
144 if (vInfo != null && implementationVersion.trim().length() > 0) {
145 implementationVersion = vInfo.trim();
147 String specVInfo = pak.getSpecificationVersion();
148 if (specVInfo != null && specVInfo.trim().length() > 0) {
149 specificationVersion = specVInfo.trim();
153 this.implementationVersion = implementationVersion;
154 this.specificationVersion = specificationVersion;
158 * 設定ファイルのロケール固有版へのファイル末尾の修飾文字列を読み込み順に取得する.
159 * @param locale ロケール、nullの場合はデフォルト
160 * @return ロケールを表すファイル末尾の修飾文字列の読み込み順のリスト
162 private String[] getLocalizedSuffix(Locale locale) {
163 if (locale == null) {
164 locale = Locale.getDefault();
167 String language = locale.getLanguage();
168 String country = locale.getCountry();
169 String variant = locale.getVariant();
171 return new String[] {
174 "_" + language + "_" + country,
175 "_" + language + "_" + country + "_" + variant,
180 * 指定されたファイル名の拡張子の前にロケール固有の修飾文字列を付与したリスト作成して返す.
182 * @param locale ロケール、nullの場合はデフォルト
183 * @return ロケールの検索順序でのロケール固有の修飾文字列が付与されたファイルのリスト
185 private List<File> expandLocalizedSuffix(File base, Locale locale) {
186 String path = base.getPath();
188 int pt = path.lastIndexOf(".");
191 left = path.substring(0, pt);
192 right = path.substring(pt);
199 ArrayList<File> files = new ArrayList<File>();
200 for (String suffix : getLocalizedSuffix(locale)) {
201 String newPath = left + suffix + right;
202 //System.out.println("newpath=" + newPath);
203 files.add(new File(newPath));
209 * 設定ファイルの読み込み順序で、読み込むべきURIのリストを返す.<br>
211 * <li>(1) リソース上の/appConfig.xml</li>
212 * <li>(2) appConfigFileシステムプロパティで指定されたファイル</li>
213 * <li>(3) コードベース下のappConfig.xml</li>
214 * <li>(4) アプリケーションデータ保存先のappConfig.xml</li>
216 * appConfigFileシステムプロパティがある場合は、(1)(2)の順。 <br>
217 * 指定がない場合は、(1)(3)(4)の順に読み取る.<br>
219 * @return 優先順位での設定ファイルの読み込み先URIのリスト
220 * @throws IOException
222 public List<URI> getCandidateURIs() throws IOException {
223 List<URI> uris = new ArrayList<URI>();
224 // リソース中の既定 (ロケール識別あり)
225 for (File localizedFile : expandLocalizedSuffix(new File(getClass()
226 .getResource("/" + CONFIG_NAME).getPath()), null)) {
227 uris.add(localizedFile.toURI());
230 String specifiedAppConfig = System.getProperty("appConfigFile");
231 if (specifiedAppConfig != null) {
232 // システムプロパティでappConfig.xmlを明示している場合は、それを読み込む。
233 // (appConfigFileシステムプロパティが空の場合は、リソース埋め込みの既定の設定だけをよみこむ)
234 if (specifiedAppConfig.trim().length() > 0) {
235 File specifiedAppConfigFile = new File(specifiedAppConfig);
236 uris.add(specifiedAppConfigFile.toURI());
240 // システムプロパティて明示していない場合は、まずコードベースを使用する.(ロケール識別あり)
241 File codeBase = ConfigurationDirUtilities.getApplicationBaseDir();
242 for (File localizedFile : expandLocalizedSuffix(new File(codeBase,
243 CONFIG_NAME).getCanonicalFile(), null)) {
244 uris.add(localizedFile.toURI());
247 // システムプロパティて明示していない場合は、次にユーザディレクトリを使用する.
248 File userDataDir = ConfigurationDirUtilities.getUserDataDir();
249 uris.add(new File(userDataDir, CONFIG_NAME).toURI());
255 * 保存先の試行順序ごとのファイルのリスト。
259 public List<File> getPrioritySaveFileList() {
260 ArrayList<File> saveFiles = new ArrayList<File>();
262 String specifiedAppConfig = System.getProperty("appConfigFile");
263 if (specifiedAppConfig != null) {
264 // システムプロパティでappConfig.xmlを明示している場合
265 if (specifiedAppConfig.trim().length() > 0) {
266 File specifiedAppConfigFile = new File(specifiedAppConfig);
267 if (!specifiedAppConfigFile.exists()
268 || specifiedAppConfigFile.canWrite()) {
269 // まだ存在しないか、書き込み可能である場合のみ候補とする.
270 saveFiles.add(specifiedAppConfigFile);
274 // システムプロパティappConfigFileがなければユーザディレクトリへ書き込む
275 // ユーザディレクトリは常に候補とする.
276 File userDataDir = ConfigurationDirUtilities.getUserDataDir();
277 saveFiles.add(new File(userDataDir, CONFIG_NAME));
285 * 存在しないか、読み取りに失敗した場合は、該当ファイルはスキップされる.<br>
287 public void loadConfig() {
288 Properties config = new Properties();
290 for (URI uri : getCandidateURIs()) {
292 continue; // リソースがない場合はnullになる
294 // ファイルの実在チェック (チェックできる場合のみ)
295 if ("file".equals(uri.getScheme())) {
296 File file = new File(uri);
297 if (!file.exists()) {
298 logger.log(Level.CONFIG, "appConfig.xml is not found.:" + file);
302 // appConfig.xmlの読み込みを行う.
303 // Properties#loadFromXML() はXMLからキーを読み取り、既存のキーに対して上書きする.
304 // XMLに存在しないキーは読み込み前のままなので、繰り返し呼び出すことで「重ね合わせ」することができる.
306 URL resourceURL = uri.toURL();
307 InputStream is = resourceURL.openStream();
309 config.loadFromXML(is);
310 logger.log(Level.CONFIG, "appConfig.xml is loaded.:" + uri);
315 } catch (FileNotFoundException ex) {
316 logger.log(Level.CONFIG, "appConfig.xml is not found.: " + uri, ex);
317 // 無視する (無い場合は十分にありえるので「情報」レベルでログ。)
318 } catch (Exception ex) {
319 logger.log(Level.WARNING, "appConfig.xml loading failed.: " + uri, ex);
324 } catch (IOException ex) {
325 throw new RuntimeException("appConfig.xml loading failed.", ex);
326 } catch (RuntimeException ex) {
327 throw new RuntimeException("appConfig.xml loading failed.", ex);
329 BeanPropertiesUtilities.loadFromProperties(this, config);
333 * プロパティをアプリケーションデータの指定した保存先に保存する.
335 * @throws IOException
338 public void saveConfig(List<File> prioritySaveFiles) throws IOException {
339 Properties config = getProperties();
340 IOException oex = null;
341 for (File configStore : prioritySaveFiles) {
343 OutputStream os = new BufferedOutputStream(
344 new FileOutputStream(configStore));
346 config.storeToXML(os, CONFIG_NAME, "UTF-8");
353 } catch (IOException ex) {
354 logger.log(Level.WARNING, "アプリケーション設定の保存に失敗しました" + ex, ex);
359 // 例外が発生していれば、最後の例外を返す.
366 * プロパティをアプリケーションデータの保存先に保存する.
368 * @throws IOException
371 public void saveConfig() throws IOException {
372 saveConfig(getPrioritySaveFileList());
376 * Propertiesの値を設定した場合に設定できない項目があるかチェックする.<br>
377 * このメソッドを呼び出しても、アプリケーション設定自身は何も影響されない.<br>
381 * @return 設定できなかったプロパティキーのコレクション、問題なければ空が返される.
383 public static Set<String> checkProperties(Map<String, Object> props) {
385 throw new IllegalArgumentException();
387 AppConfig dummy = new AppConfig(); // アプリケーションから参照されないダミーのインスタンスを作成する.
388 return update(props, dummy);
393 * Propertiesの値で設定を更新する.<br>
397 * @return 設定できなかったプロパティキーのコレクション、問題なければ空が返される.
399 public Set<String> update(Map<String, Object> props) {
400 return update(props, this);
404 * Propertiesの値で設定を更新する.<br>
409 * 適用するAppConfigのインスタンス(ドライランと本番の切り替え用)
410 * @return 設定できなかったプロパティキーのコレクション、問題なければ空が返される.
412 private static Set<String> update(Map<String, Object> props, AppConfig bean) {
414 throw new IllegalArgumentException();
416 HashSet<String> rejectedNames = new HashSet<String>();
418 PropertyAccessorMap accessorMap = BeanPropertiesUtilities.getPropertyAccessorMap(AppConfig.class);
419 accessorMap.setBean(bean);
421 for (Map.Entry<String, Object> propEntry : props.entrySet()) {
422 String name = propEntry.getKey();
423 Object value = propEntry.getValue();
425 PropertyAccessor accessor = accessorMap.get(name);
426 if (accessor == null) {
428 rejectedNames.add(name);
432 Class<?> propertyType = accessor.getPropertyType();
433 if (propertyType.isPrimitive() && value == null) {
434 // プリミティブ型なのにnullは入れられない
435 rejectedNames.add(name);
440 accessor.setValue(value);
442 } catch (Exception ex) {
443 // 何らかの理由でプロパティの設定に失敗している場合
444 rejectedNames.add(name);
445 logger.log(Level.WARNING, "invalid propery: " + name + " /val=" + value, ex);
449 return rejectedNames;
453 * このアプリケーション設定をプロパティに書き出して返します.<br>
457 public Properties getProperties() {
458 Properties config = new Properties();
459 BeanPropertiesUtilities.saveToProperties(this, config);
465 * プロファイル選択ダイアログのプロファイルのサンプルイメージの背景色
467 * @return サンプルイメージの背景色
469 public Color getSampleImageBgColor() {
470 return sampleImageBgColor;
473 public static final String SAMPLE_IMAGE_BG_COLOR = "sampleImageBgColor";
475 public void setSampleImageBgColor(Color sampleImageBgColor) {
476 if (sampleImageBgColor == null) {
477 throw new IllegalArgumentException();
479 Color old = this.sampleImageBgColor;
480 if (old == null ? sampleImageBgColor != null : !old.equals(sampleImageBgColor)) {
481 this.sampleImageBgColor = sampleImageBgColor;
482 propChangeSupport.firePropertyChange(SAMPLE_IMAGE_BG_COLOR, old, sampleImageBgColor);
486 private Color sampleImageBgColor = Color.white;
490 * デフォルトのイメージ背景色を取得する.
492 * @return デフォルトのイメージ背景色
494 public Color getDefaultImageBgColor() {
495 return defaultImageBgColor;
498 public static final String DEFAULT_IMAGE_BG_COLOR = "defaultImageBgColor";
500 public void setDefaultImageBgColor(Color defaultImageBgColor) {
501 if (defaultImageBgColor == null) {
502 throw new IllegalArgumentException();
504 Color old = this.defaultImageBgColor;
505 if (old == null ? defaultImageBgColor != null : !old.equals(defaultImageBgColor)) {
506 this.defaultImageBgColor = defaultImageBgColor;
507 propChangeSupport.firePropertyChange(DEFAULT_IMAGE_BG_COLOR, old, defaultImageBgColor);
511 private Color defaultImageBgColor = Color.white;
516 * @return 使用中アイテムの背景色
518 public Color getCheckedItemBgColor() {
519 return checkedItemBgColor;
522 public static final String CHECKED_ITEM_BG_COLOR = "checkedItemBgColor";
524 public void setCheckedItemBgColor(Color checkedItemBgColor) {
525 if (checkedItemBgColor == null) {
526 throw new IllegalArgumentException();
528 Color old = this.checkedItemBgColor;
529 if (old == null ? checkedItemBgColor != null : !old.equals(checkedItemBgColor)) {
530 this.checkedItemBgColor = checkedItemBgColor;
531 propChangeSupport.firePropertyChange(CHECKED_ITEM_BG_COLOR, old, checkedItemBgColor);
535 private Color checkedItemBgColor = Color.cyan.brighter();
543 public Color getSelectedItemBgColor() {
544 return selectedItemBgColor;
547 public static final String SELECTED_ITEM_BG_COLOR = "selectedItemBgColor";
549 public void setSelectedItemBgColor(Color selectedItemBgColor) {
550 if (selectedItemBgColor == null) {
551 throw new IllegalArgumentException();
553 Color old = this.selectedItemBgColor;
554 if (old == null ? selectedItemBgColor != null : !old.equals(selectedItemBgColor)) {
555 this.selectedItemBgColor = selectedItemBgColor;
556 propChangeSupport.firePropertyChange(SELECTED_ITEM_BG_COLOR, old, selectedItemBgColor);
560 private Color selectedItemBgColor = Color.orange;
563 * 不備のあるデータ行の背景色を取得する.
565 * @return 不備のあるデータ行の背景色
567 public Color getInvalidBgColor() {
568 return invalidBgColor;
571 public static final String INVALID_BG_COLOR = "invalidBgColor";
573 public void setInvalidBgColor(Color invalidBgColor) {
574 if (invalidBgColor == null) {
575 throw new IllegalArgumentException();
577 Color old = this.invalidBgColor;
578 if (old == null ? invalidBgColor != null : !old.equals(invalidBgColor)) {
579 this.invalidBgColor = invalidBgColor;
580 propChangeSupport.firePropertyChange(INVALID_BG_COLOR, old, invalidBgColor);
584 private Color invalidBgColor = Color.red.brighter().brighter();
587 * JPEG画像変換時の圧縮率を取得する.
591 public float getCompressionQuality() {
592 return compressionQuality;
595 public static final String COMPRESSION_QUALITY = "compressionQuality";
597 public void setCompressionQuality(float compressionQuality) {
598 if (compressionQuality < .1f || compressionQuality > 1f) {
599 throw new IllegalArgumentException();
601 float old = this.compressionQuality;
602 if (old != compressionQuality) {
603 this.compressionQuality = compressionQuality;
604 propChangeSupport.firePropertyChange(COMPRESSION_QUALITY, old, compressionQuality);
608 private float compressionQuality = .8f;
611 * エクスポートウィザードのプリセットにパーツ不足時の警告色(前景色)を取得する.
613 * @return エクスポートウィザードのプリセットにパーツ不足時の警告色(前景色)
615 public Color getExportPresetWarningsForegroundColor() {
616 return exportPresetWarningsForegroundColor;
619 public static final String EXPORT_PRESET_WARNINGS_FOREGROUND_COLOR = "exportPresetWarningsForegroundColor";
621 public void setExportPresetWarningsForegroundColor(Color exportPresetWarningsForegroundColor) {
622 if (exportPresetWarningsForegroundColor == null) {
623 throw new IllegalArgumentException();
625 Color old = this.exportPresetWarningsForegroundColor;
626 if (old == null ? exportPresetWarningsForegroundColor != null
627 : !old.equals(exportPresetWarningsForegroundColor)) {
628 this.exportPresetWarningsForegroundColor = exportPresetWarningsForegroundColor;
629 propChangeSupport.firePropertyChange(EXPORT_PRESET_WARNINGS_FOREGROUND_COLOR, old,
630 exportPresetWarningsForegroundColor);
634 private Color exportPresetWarningsForegroundColor = Color.red;
637 * JARファイル転送用バッファサイズ.<br>
639 * @return JARファイル転送用バッファサイズ.
641 public int getJarTransferBufferSize() {
642 return jarTransferBufferSize;
645 public static final String JAR_TRANSFER_BUFFER_SIZE = "jarTransferBufferSize";
647 public void setJarTransferBufferSize(int jarTransferBufferSize) {
648 if (jarTransferBufferSize <= 0) {
649 throw new IllegalArgumentException();
651 int old = this.jarTransferBufferSize;
652 if (old != jarTransferBufferSize) {
653 this.jarTransferBufferSize = jarTransferBufferSize;
654 propChangeSupport.firePropertyChange(JAR_TRANSFER_BUFFER_SIZE, old, jarTransferBufferSize);
658 private int jarTransferBufferSize = 4096;
661 * ZIPファイル名のエンコーディング.<br>
663 * @return ZIPファイル名のエンコーディング.<br>
665 public String getZipNameEncoding() {
666 return zipNameEncoding;
669 public static final String ZIP_NAME_ENCODING = "zipNameEncoding";
671 public void setZipNameEncoding(String zipNameEncoding) {
672 if (zipNameEncoding == null) {
673 throw new IllegalArgumentException();
676 Charset.forName(zipNameEncoding);
677 } catch (Exception ex) {
678 throw new RuntimeException("unsupported charset: " + zipNameEncoding);
680 String old = this.zipNameEncoding;
681 if (old == null ? zipNameEncoding != null : !old.equals(zipNameEncoding)) {
682 this.zipNameEncoding = zipNameEncoding;
683 propChangeSupport.firePropertyChange(ZIP_NAME_ENCODING, old, zipNameEncoding);
687 private String zipNameEncoding = "csWindows31J";
690 * ディセーブルなテーブルのセルのフォアグラウンドカラーを取得する.
692 * @return ディセーブルなテーブルのセルのフォアグラウンドカラー
694 public Color getDisabledCellForgroundColor() {
695 return disabledCellForegroundColor;
698 public static final String DISABLED_CELL_FOREGROUND_COLOR = "disabledCellForegroundColor";
700 public void setDisabledCellForegroundColor(Color disabledCellForegroundColor) {
701 if (disabledCellForegroundColor == null) {
702 throw new IllegalArgumentException();
704 Color old = this.disabledCellForegroundColor;
705 if (old == null ? disabledCellForegroundColor != null : !old.equals(disabledCellForegroundColor)) {
706 this.disabledCellForegroundColor = disabledCellForegroundColor;
707 propChangeSupport.firePropertyChange(DISABLED_CELL_FOREGROUND_COLOR, old, disabledCellForegroundColor);
711 private Color disabledCellForegroundColor = Color.gray;
715 * ディレクトリを監視する間隔(mSec)を取得する.
717 * @return ディレクトリを監視する間隔(mSec)
719 public int getDirWatchInterval() {
720 return dirWatchInterval;
723 public static final String DIR_WATCH_INTERVAL = "dirWatchInterval";
725 public void setDirWatchInterval(int dirWatchInterval) {
726 if (dirWatchInterval <= 0) {
727 throw new IllegalArgumentException();
729 int old = this.dirWatchInterval;
730 if (old != dirWatchInterval) {
731 this.dirWatchInterval = dirWatchInterval;
732 propChangeSupport.firePropertyChange(DIR_WATCH_INTERVAL, old, dirWatchInterval);
736 private int dirWatchInterval = 7 * 1000;
741 * @return ディレクトリの監視を有効にする場合はtrue
743 public boolean isEnableDirWatch() {
744 return enableDirWatch;
747 public static final String ENABLE_DIR_WATCH = "enableDirWatch";
749 public void setEnableDirWatch(boolean enableDirWatch) {
750 boolean old = this.enableDirWatch;
751 if (old != enableDirWatch) {
752 this.enableDirWatch = enableDirWatch;
753 propChangeSupport.firePropertyChange(ENABLE_DIR_WATCH, old, enableDirWatch);
757 private boolean enableDirWatch = true;
760 * ファイル転送に使うバッファサイズ.<br>
764 public int getFileTransferBufferSize() {
765 return fileTransferBufferSize;
768 public static final String FILE_TRANSFER_BUFFER_SIZE = "fileTransferBufferSize";
770 public void setFileTransferBufferSize(int fileTransferBufferSize) {
771 if (fileTransferBufferSize <= 0) {
772 throw new IllegalArgumentException();
774 int old = this.fileTransferBufferSize;
775 if (old != fileTransferBufferSize) {
776 this.fileTransferBufferSize = fileTransferBufferSize;
777 propChangeSupport.firePropertyChange(FILE_TRANSFER_BUFFER_SIZE, old, fileTransferBufferSize);
781 private int fileTransferBufferSize = 4096;
784 * プレビューのインジケータを表示するまでのディレイ(mSec)を取得する.
786 * @return プレビューのインジケータを表示するまでのディレイ(mSec)
788 public long getPreviewIndicatorDelay() {
789 return previewIndeicatorDelay;
792 public static final String PREVIEW_INDEICATOR_DELAY = "previewIndeicatorDelay";
794 public void setPreviewIndeicatorDelay(long previewIndeicatorDelay) {
795 if (previewIndeicatorDelay < 0) {
796 throw new IllegalArgumentException();
798 long old = this.previewIndeicatorDelay;
799 if (old != previewIndeicatorDelay) {
800 this.previewIndeicatorDelay = previewIndeicatorDelay;
801 propChangeSupport.firePropertyChange(PREVIEW_INDEICATOR_DELAY, old, previewIndeicatorDelay);
805 private long previewIndeicatorDelay = 300;
808 * 情報ダイアログの編集ボタンを「開く」アクションにする場合はtrue、「編集」アクションにする場合はfalse
810 * @return trueならばOpen、falseならばEdit
812 public boolean isInformationDialogOpenMethod() {
813 return informationDialogOpenMethod;
816 public static final String INFORMATION_DIALOG_OPEN_METHOD = "informationDialogOpenMethod";
818 public void setInformationDialogOpenMethod(
819 boolean informationDialogOpenMethod) {
820 boolean old = this.informationDialogOpenMethod;
821 if (old != informationDialogOpenMethod) {
822 this.informationDialogOpenMethod = informationDialogOpenMethod;
823 propChangeSupport.firePropertyChange("informationDialogOpenMethod", old, informationDialogOpenMethod);
827 private boolean informationDialogOpenMethod = true;
831 * falseの場合は{@link ApplicationLogHandler}の実装に従って終了時に 必要なければログは削除される.<br>
833 * @return 常に残す場合はtrue、そうでなければfalse
835 public boolean isNoRemoveLog() {
839 public static final String NO_REMOVE_LOG = "noRemoveLog";
841 public void setNoRemoveLog(boolean noRemoveLog) {
842 boolean old = this.noRemoveLog;
843 if (old != noRemoveLog) {
844 this.noRemoveLog = noRemoveLog;
845 propChangeSupport.firePropertyChange(NO_REMOVE_LOG, old, noRemoveLog);
849 private boolean noRemoveLog = false;
857 public Color getGridColor() {
861 public static final String GRID_COLOR = "gridColor";
863 public void setGridColor(Color gridColor) {
864 if (gridColor == null) {
865 throw new IllegalArgumentException();
867 Color old = this.gridColor;
868 if (old == null ? gridColor != null : !old.equals(gridColor)) {
869 this.gridColor = gridColor;
870 propChangeSupport.firePropertyChange(GRID_COLOR, old, gridColor);
874 private Color gridColor = Color.gray;
877 * カラーダイアログの値が変更されたら、自動的にプレビューを更新するか?
879 * @return カラーダイアログの値が変更されたら、自動的にプレビューを更新する場合はtrue (デフォルトはtrue)
881 public boolean isEnableAutoColorChange() {
882 return enableAutoColorChange;
885 public static final String ENABLE_AUTO_COLOR_CHANGE = "enableAutoColorChange";
887 public void setEnableAutoColorChange(boolean enableAutoColorChange) {
888 boolean old = this.enableAutoColorChange;
889 if (old != enableAutoColorChange) {
890 this.enableAutoColorChange = enableAutoColorChange;
891 propChangeSupport.firePropertyChange(ENABLE_AUTO_COLOR_CHANGE, old, enableAutoColorChange);
895 private boolean enableAutoColorChange = true;
897 public static final String AUTHOR_EDIT_CONFLICT_BG_COLOR = "authorEditConflictBgColor";
899 public void setAuthorEditConflictBgColor(Color authorEditConflictBgColor) {
900 if (authorEditConflictBgColor == null) {
901 throw new IllegalArgumentException();
903 Color old = this.authorEditConflictBgColor;
904 if (old == null ? authorEditConflictBgColor != null : !old.equals(authorEditConflictBgColor)) {
905 this.authorEditConflictBgColor = authorEditConflictBgColor;
906 propChangeSupport.firePropertyChange(AUTHOR_EDIT_CONFLICT_BG_COLOR, old, authorEditConflictBgColor);
911 * パーツの作者編集時に複数作者を選択した場合のに入力ボックスの背景色
915 public Color getAuthorEditConflictBgColor() {
916 return authorEditConflictBgColor;
919 Color authorEditConflictBgColor = Color.yellow;
922 public static final String MAIN_FRAME_MAX_WIDTH = "mainFrameMaxWidth";
924 public void setMainFrameMaxWidth(int mainFrameMaxWidth) {
925 int old = mainFrameMaxWidth;
926 if (old != mainFrameMaxWidth) {
927 this.mainFrameMaxWidth = mainFrameMaxWidth;
928 propChangeSupport.firePropertyChange(MAIN_FRAME_MAX_WIDTH, old, mainFrameMaxWidth);
935 * @return メインフレームの初期表示時の最大幅
937 public int getMainFrameMaxWidth() {
938 return mainFrameMaxWidth;
941 private int mainFrameMaxWidth = 800;
943 public static final String MAIN_FRAME_MAX_HEIGHT = "mainFrameMaxHeight";
945 public void setMainFrameMaxHeight(int mainFrameMaxHeight) {
946 int old = this.mainFrameMaxHeight;
947 if (old != mainFrameMaxHeight) {
948 this.mainFrameMaxHeight = mainFrameMaxHeight;
949 propChangeSupport.firePropertyChange(MAIN_FRAME_MAX_HEIGHT, old, mainFrameMaxHeight);
956 * @return メインフレームの初期表示時の最大高さ
958 public int getMainFrameMaxHeight() {
959 return mainFrameMaxHeight;
962 private int mainFrameMaxHeight = 600;
966 * カラーダイアログで存在しないレイヤーをディセーブルにしない.
968 * @return ディセーブルにしない場合はtrue
970 public boolean isNotDisableLayerTab() {
971 return notDisableLayerTab;
974 public static final String NOT_DISABLE_LAYER_TAB = "notDisableLayerTab";
976 public void setNotDisableLayerTab(boolean notDisableLayerTab) {
977 boolean old = this.notDisableLayerTab;
978 if (old != notDisableLayerTab) {
979 this.notDisableLayerTab = notDisableLayerTab;
980 propChangeSupport.firePropertyChange(NOT_DISABLE_LAYER_TAB, old, notDisableLayerTab);
984 private boolean notDisableLayerTab;
989 * この指定日を経過した古いログは削除される.<br>
994 public long getPurgeLogDays() {
998 public static final String PURGE_LOG_DAYS = "purgeLogDays";
1000 public void setPurgeLogDays(long purgeLogDays) {
1001 long old = this.purgeLogDays;
1002 if (old != purgeLogDays) {
1003 this.purgeLogDays = purgeLogDays;
1004 propChangeSupport.firePropertyChange(PURGE_LOG_DAYS, old, purgeLogDays);
1008 private long purgeLogDays = 10;
1010 public String getPartsColorGroupPattern() {
1011 return partsColorGroupPattern;
1014 public static final String PARTS_COLOR_GROUP_PATTERN = "partsColorGroupPattern";
1016 public void setPartsColorGroupPattern(String pattern) {
1017 if (pattern != null && pattern.trim().length() > 0) {
1018 Pattern.compile(pattern);
1020 String old = this.partsColorGroupPattern;
1021 if (old == null ? pattern != null : !old.equals(pattern)) {
1022 this.partsColorGroupPattern = pattern;
1023 propChangeSupport.firePropertyChange(PARTS_COLOR_GROUP_PATTERN, old, pattern);
1027 private String partsColorGroupPattern = "^.*\\(@\\).*$";
1029 private Color selectPanelTitleColor = Color.BLUE;
1031 public Color getSelectPanelTitleColor() {
1032 return selectPanelTitleColor;
1035 public static final String SELECT_PANEL_TITLE_COLOR = "selectPanelTitleColor";
1037 public void setSelectPanelTitleColor(Color selectPanelTitleColor) {
1038 if (selectPanelTitleColor == null) {
1039 throw new IllegalArgumentException();
1041 Color old = this.selectPanelTitleColor;
1042 if (old == null ? selectPanelTitleColor != null : !old.equals(selectPanelTitleColor)) {
1043 this.selectPanelTitleColor = selectPanelTitleColor;
1044 propChangeSupport.firePropertyChange(SELECT_PANEL_TITLE_COLOR, old, selectPanelTitleColor);
1048 private boolean enableAutoShrinkPanel;
1050 public boolean isEnableAutoShrinkPanel() {
1051 return enableAutoShrinkPanel;
1054 public static final String ENABLE_AUTO_SHRINK_PANEL = "enableAutoShrinkPanel";
1056 public void setEnableAutoShrinkPanel(boolean enableAutoShrinkPanel) {
1057 boolean old = this.enableAutoShrinkPanel;
1058 if (old != enableAutoShrinkPanel) {
1059 this.enableAutoShrinkPanel = enableAutoShrinkPanel;
1060 propChangeSupport.firePropertyChange(ENABLE_AUTO_SHRINK_PANEL, old, enableAutoShrinkPanel);
1064 public boolean isDisableWatchDirIfNotWritable() {
1065 return disableWatchDirIfNotWritable;
1068 public static final String DISABLE_WATCH_DIR_IF_NOT_WRITABLE = "disableWatchDirIfNotWritable";
1070 public void setDisableWatchDirIfNotWritable(boolean disableWatchDirIfNotWritable) {
1071 boolean old = this.disableWatchDirIfNotWritable;
1072 if (old != disableWatchDirIfNotWritable) {
1073 this.disableWatchDirIfNotWritable = disableWatchDirIfNotWritable;
1074 propChangeSupport.firePropertyChange(DISABLE_WATCH_DIR_IF_NOT_WRITABLE, old, disableWatchDirIfNotWritable);
1078 private boolean disableWatchDirIfNotWritable = true;
1080 public static final String ENABLE_PNG_SUPPORT_FOR_WINDOWS = "enablePNGSupportForWindows";
1082 public void setEnablePNGSupportForWindows(boolean enablePNGSupportForWindows) {
1083 boolean old = this.enablePNGSupportForWindows;
1084 if (old != enablePNGSupportForWindows) {
1085 this.enablePNGSupportForWindows = enablePNGSupportForWindows;
1086 propChangeSupport.firePropertyChange(ENABLE_PNG_SUPPORT_FOR_WINDOWS, old, enablePNGSupportForWindows);
1090 public boolean isEnablePNGSupportForWindows() {
1091 return enablePNGSupportForWindows;
1094 private boolean enablePNGSupportForWindows = true;
1097 * 画像表示(通常モード)でオプティマイズを有効にする最大倍率.
1099 private double renderingOptimizeThresholdForNormal = 2.;
1101 public static final String RENDERING_OPTIMIZE_THRESHOLD_FOR_NORMAL = "renderingOptimizeThresholdForNormal";
1103 public void setRenderingOptimizeThresholdForNormal(
1104 double renderingOptimizeThresholdForNormal) {
1105 double old = this.renderingOptimizeThresholdForNormal;
1106 if (old != renderingOptimizeThresholdForNormal) {
1107 this.renderingOptimizeThresholdForNormal = renderingOptimizeThresholdForNormal;
1108 propChangeSupport.firePropertyChange(RENDERING_OPTIMIZE_THRESHOLD_FOR_NORMAL, old,
1109 renderingOptimizeThresholdForNormal);
1113 public double getRenderingOptimizeThresholdForNormal() {
1114 return renderingOptimizeThresholdForNormal;
1117 * 画像表示(チェックモード)でオプティマイズを有効にする最大倍率.
1119 private double renderingOptimizeThresholdForCheck = 0.;
1121 public static final String RENDERING_OPTIMIZE_THRESHOLD_FOR_CHECK = "renderingOptimizeThresholdForCheck";
1123 public void setRenderingOptimizeThresholdForCheck(
1124 double renderingOptimizeThresholdForCheck) {
1125 double old = this.renderingOptimizeThresholdForCheck;
1126 if (old != renderingOptimizeThresholdForCheck) {
1127 this.renderingOptimizeThresholdForCheck = renderingOptimizeThresholdForCheck;
1128 propChangeSupport.firePropertyChange(RENDERING_OPTIMIZE_THRESHOLD_FOR_CHECK, old,
1129 renderingOptimizeThresholdForCheck);
1133 public double getRenderingOptimizeThresholdForCheck() {
1134 return renderingOptimizeThresholdForCheck;
1140 private boolean enableInterpolationBicubic = true;
1142 public static final String ENABLE_INTERPOLATION_BICUBIC = "enableInterpolationBicubic";
1144 public void setEnableInterpolationBicubic(boolean enableInterpolationBicubic) {
1145 boolean old = this.enableInterpolationBicubic;
1146 if (old != enableInterpolationBicubic) {
1147 this.enableInterpolationBicubic = enableInterpolationBicubic;
1148 propChangeSupport.firePropertyChange(ENABLE_INTERPOLATION_BICUBIC, old, enableInterpolationBicubic);
1152 public boolean isEnableInterpolationBicubic() {
1153 return enableInterpolationBicubic;
1159 private String predefinedZoomRanges = "20, 50, 80, 100, 120, 150, 200, 300, 400, 800";
1161 public String getPredefinedZoomRanges() {
1162 return predefinedZoomRanges;
1165 public static final String PREDEFINED_ZOOM_RANGES = "predefinedZoomRanges";
1167 public void setPredefinedZoomRanges(String predefinedZoomRanges) {
1168 if (predefinedZoomRanges == null) {
1169 throw new IllegalArgumentException();
1171 String old = this.predefinedZoomRanges;
1172 if (old == null ? predefinedZoomRanges != null : !old.equals(predefinedZoomRanges)) {
1173 this.predefinedZoomRanges = predefinedZoomRanges;
1174 propChangeSupport.firePropertyChange(PREDEFINED_ZOOM_RANGES, old, predefinedZoomRanges);
1179 * ズームパネルを初期状態で表示するか?
1181 private boolean enableZoomPanel = true;
1183 public boolean isEnableZoomPanel() {
1184 return enableZoomPanel;
1187 public static final String ENABLE_ZOOM_PANEL = "enableZoomPanel";
1189 public void setEnableZoomPanel(boolean enableZoomPanel) {
1190 boolean old = this.enableZoomPanel;
1191 if (old != enableZoomPanel) {
1192 this.enableZoomPanel = enableZoomPanel;
1193 propChangeSupport.firePropertyChange(ENABLE_ZOOM_PANEL, old, enableZoomPanel);
1198 * ズームパネルをアクティブにする下部範囲
1200 private int zoomPanelActivationArea = 30;
1202 public int getZoomPanelActivationArea() {
1203 return zoomPanelActivationArea;
1206 public static final String ZOOM_PANEL_ACTIVATION_AREA = "zoomPanelActivationArea";
1208 public void setZoomPanelActivationArea(int zoomPanelActivationArea) {
1209 int old = this.zoomPanelActivationArea;
1210 if (old != zoomPanelActivationArea) {
1211 this.zoomPanelActivationArea = zoomPanelActivationArea;
1212 propChangeSupport.firePropertyChange(ZOOM_PANEL_ACTIVATION_AREA, old, zoomPanelActivationArea);
1219 private boolean enableRenderingHints = true;
1221 public static final String ENABLE_RENDERING_HINTS = "enableRenderingHints";
1223 public void setEnableRenderingHints(boolean enableRenderingHints) {
1224 boolean old = this.enableRenderingHints;
1225 if (old != enableRenderingHints) {
1226 this.enableRenderingHints = enableRenderingHints;
1227 propChangeSupport.firePropertyChange(ENABLE_RENDERING_HINTS, old, enableRenderingHints);
1231 public boolean isEnableRenderingHints() {
1232 return enableRenderingHints;
1238 private int drawGridMask = 2;
1240 public int getDrawGridMask() {
1241 return drawGridMask;
1244 public static final String DRAW_GRID_MASK = "drawGridMask";
1246 public void setDrawGridMask(int drawGridMask) {
1247 drawGridMask &= 0x03;
1248 int old = this.drawGridMask;
1249 if (old != drawGridMask) {
1250 this.drawGridMask = drawGridMask;
1251 propChangeSupport.firePropertyChange(DRAW_GRID_MASK, old, drawGridMask);
1255 private Color previewGridColor = new Color(0x7f7f0000, true);
1257 public Color getPreviewGridColor() {
1258 return previewGridColor;
1261 public static final String PREVIEW_GRID_COLOR = "previewGridColor";
1263 public void setPreviewGridColor(Color previewGridColor) {
1264 Color old = this.previewGridColor;
1265 if (old == null ? previewGridColor != null : !old.equals(previewGridColor)) {
1266 this.previewGridColor = previewGridColor;
1267 propChangeSupport.firePropertyChange(PREVIEW_GRID_COLOR, old, previewGridColor);
1271 private int previewGridSize = 20;
1273 public int getPreviewGridSize() {
1274 return previewGridSize;
1277 public static final String PREVIEW_GRID_SIZE = "previewGridSize";
1279 public void setPreviewGridSize(int previewGridSize) {
1280 int old = this.previewGridSize;
1281 if (old != previewGridSize) {
1282 this.previewGridSize = previewGridSize;
1283 propChangeSupport.firePropertyChange(PREVIEW_GRID_SIZE, old, previewGridSize);
1288 * チェックモード時の余白サイズ(片側)
1290 private int previewUnfilledSpaceForCheckMode = 0;
1292 public int getPreviewUnfilledSpaceForCheckMode() {
1293 return previewUnfilledSpaceForCheckMode;
1296 public static final String PREVIEW_UNFILLED_SPACE_FOR_CHECK_MODE = "previewUnfilledSpaceForCheckMode";
1298 public void setPreviewUnfilledSpaceForCheckMode(int previewUnfilledSpaceForCheckMode) {
1299 int old = this.previewUnfilledSpaceForCheckMode;
1300 if (old != previewUnfilledSpaceForCheckMode) {
1301 this.previewUnfilledSpaceForCheckMode = previewUnfilledSpaceForCheckMode;
1302 propChangeSupport.firePropertyChange(PREVIEW_UNFILLED_SPACE_FOR_CHECK_MODE, old,
1303 previewUnfilledSpaceForCheckMode);
1308 * チェックモードでツールチップを表示するか?
1310 private boolean enableCheckInfoTooltip = true;
1312 public boolean isEnableCheckInfoTooltip() {
1313 return enableCheckInfoTooltip;
1316 public static final String ENABLE_CHECK_INFO_TOOLTIP = "enableCheckInfoTooltip";
1318 public void setEnableCheckInfoTooltip(boolean enableCheckInfoTooltip) {
1319 boolean old = this.enableCheckInfoTooltip;
1320 if (old != enableCheckInfoTooltip) {
1321 this.enableCheckInfoTooltip = enableCheckInfoTooltip;
1322 propChangeSupport.firePropertyChange(ENABLE_CHECK_INFO_TOOLTIP, old, enableCheckInfoTooltip);
1327 * ホイールによるスクロールの単位.<br>
1329 private int wheelScrollUnit = 10;
1331 public int getWheelScrollUnit() {
1332 return wheelScrollUnit;
1335 public static final String WHEEL_SCROLL_UNIT = "wheelScrollUnit";
1337 public void setWheelScrollUnit(int wheelScrollUnit) {
1338 int old = this.wheelScrollUnit;
1339 if (old != wheelScrollUnit) {
1340 this.wheelScrollUnit = wheelScrollUnit;
1341 propChangeSupport.firePropertyChange(WHEEL_SCROLL_UNIT, old, wheelScrollUnit);
1346 * 壁紙にオフスクリーン描画を使用するか?.<br>
1347 * (あまり劇的なパフォーマンス効果はない.)
1349 private boolean enableOffscreenWallpaper = false;
1351 public boolean isEnableOffscreenWallpaper() {
1352 return enableOffscreenWallpaper;
1355 public static final String ENABLE_OFFSCREEN_WALLPAPER = "enableOffscreenWallpaper";
1357 public void setEnableOffscreenWallpaper(boolean enableOffscreenWallpaper) {
1358 boolean old = this.enableOffscreenWallpaper;
1359 if (old != enableOffscreenWallpaper) {
1360 this.enableOffscreenWallpaper = enableOffscreenWallpaper;
1361 propChangeSupport.firePropertyChange(ENABLE_OFFSCREEN_WALLPAPER, old, enableOffscreenWallpaper);
1368 private int offscreenWallpaperSize = 300;
1370 public int getOffscreenWallpaperSize() {
1371 return offscreenWallpaperSize;
1374 private static final String OFFSCREEN_WALLPAPER_SIZE = "offscreenWallpaperSize";
1376 public void setOffscreenWallpaperSize(int offscreenWallpaperSize) {
1377 int old = this.offscreenWallpaperSize;
1378 if (old != offscreenWallpaperSize) {
1379 this.offscreenWallpaperSize = offscreenWallpaperSize;
1380 propChangeSupport.firePropertyChange(OFFSCREEN_WALLPAPER_SIZE, old, offscreenWallpaperSize);
1388 private int randomChooserMaxHistory = 10;
1390 public int getRandomChooserMaxHistory() {
1391 return randomChooserMaxHistory;
1394 public static final String RANDOM_CHOOSER_MAX_HISTORY = "randomChooserMaxHistory";
1396 public void setRandomChooserMaxHistory(int randomChooserMaxHistory) {
1397 int old = this.randomChooserMaxHistory;
1398 if (old != randomChooserMaxHistory) {
1399 this.randomChooserMaxHistory = randomChooserMaxHistory;
1400 propChangeSupport.firePropertyChange(RANDOM_CHOOSER_MAX_HISTORY, old, randomChooserMaxHistory);
1405 * デフォルトのフォントサイズ、0以下の場合はシステム既定のまま
1407 private int defaultFontSize = 12;
1409 public int getDefaultFontSize() {
1410 return defaultFontSize;
1413 public static final String DEFAULT_FONT_SIZE = "defaultFontSize";
1415 public void setDefaultFontSize(int defaultFontSize) {
1416 int old = this.defaultFontSize;
1417 if (old != defaultFontSize) {
1418 this.defaultFontSize = defaultFontSize;
1419 propChangeSupport.firePropertyChange(DEFAULT_FONT_SIZE, old, defaultFontSize);
1424 * デフォルトのフォントファミリー、カンマ区切り
1426 private String fontPriority = "Lucida Grande";
1428 public String getFontPriority() {
1429 return fontPriority;
1432 public static final String FONT_PRIORITY = "fontPriority";
1434 public void setFontPriority(String fontPriority) {
1435 if (fontPriority == null) {
1436 throw new IllegalArgumentException();
1438 String old = this.fontPriority;
1439 if (old == null ? fontPriority != null : !old.equals(fontPriority)) {
1440 this.fontPriority = fontPriority;
1441 propChangeSupport.firePropertyChange(FONT_PRIORITY, old, fontPriority);
1446 * ウィンドウの位置、サイズ、スクロールバーの位置、ズームの状態を復元するか?
1448 private boolean enableRestoreWindow = false;
1450 public boolean isEnableRestoreWindow() {
1451 return enableRestoreWindow;
1454 public static final String ENABLE_RESTORE_WINDOW = "enableRestoreWindow";
1456 public void setEnableRestoreWindow(boolean enableRestoreWindow) {
1457 boolean old = this.enableRestoreWindow;
1458 if (old != enableRestoreWindow) {
1459 this.enableRestoreWindow = enableRestoreWindow;
1460 propChangeSupport.firePropertyChange(ENABLE_RESTORE_WINDOW, old, enableRestoreWindow);
1464 private boolean enableColorAdvancedSettings = true;
1466 public boolean isEnableColorAdvancedSettings() {
1467 return enableColorAdvancedSettings;
1470 public static final String ENABLE_COLOR_ADVANCED_SETTINGS = "enableColorAdvancedSettings";
1472 public void setEnableColorAdvancedSettings(boolean enableColorAdvancedSettings) {
1473 boolean old = this.enableColorAdvancedSettings;
1474 if (old != enableColorAdvancedSettings) {
1475 this.enableColorAdvancedSettings = enableColorAdvancedSettings;
1476 propChangeSupport.firePropertyChange(ENABLE_COLOR_ADVANCED_SETTINGS, old, enableRestoreWindow);