From c7e94301ecbc3f1c8c10573ad72fb8651fafb98c Mon Sep 17 00:00:00 2001 From: youssefsoli Date: Wed, 23 Nov 2022 21:26:06 -0500 Subject: [PATCH] Added persistence to the bitmap display settings This was achieved by using the pre-existing global settings object and adding functionality for saving and retrieving integer-based preferences. --- src/main/java/mars/Settings.java | 164 +++++++++++++++++++++- src/main/java/mars/tools/BitmapDisplay.kt | 25 +++- 2 files changed, 182 insertions(+), 7 deletions(-) diff --git a/src/main/java/mars/Settings.java b/src/main/java/mars/Settings.java index 3f48205..2de46b6 100644 --- a/src/main/java/mars/Settings.java +++ b/src/main/java/mars/Settings.java @@ -305,6 +305,18 @@ public class Settings extends Observable */ public static final int REGISTER_HIGHLIGHT_FOREGROUND = 11; + + /** + * Available integer-based settings + */ + public enum IntegerSetting + { + UNIT_WIDTH, + UNIT_HEIGHT, + DISPLAY_WIDTH, + DISPLAY_HEIGHT, + } + /* Properties file used to hold default settings. */ private static final String settingsFile = "Settings"; @@ -351,6 +363,8 @@ public class Settings extends Observable */ private static final String[] defaultColorSettingsValues = {"0x00e0e0e0", "0", "0x00ffffff", "0", "0x00ffff99", "0", "0x0033ff00", "0", "0x0099ccff", "0", "0x0099cc55", "0"}; + private static final int[] defaultIntegerSettingsValues = {2, 2, 512, 256}; + private static final String SYNTAX_STYLE_COLOR_PREFIX = "SyntaxStyleColor_"; private static final String SYNTAX_STYLE_BOLD_PREFIX = "SyntaxStyleBold_"; @@ -385,6 +399,8 @@ public class Settings extends Observable private final String[] colorSettingsValues; + private final int[] integerSettingsValues; + private final Preferences preferences; /* ************************************************************************** @@ -427,6 +443,7 @@ public class Settings extends Observable fontStyleSettingsValues = new String[fontStyleSettingsKeys.length]; fontSizeSettingsValues = new String[fontSizeSettingsKeys.length]; colorSettingsValues = new String[colorSettingsKeys.length]; + integerSettingsValues = new int[IntegerSetting.values().length]; // This determines where the values are actually stored. Actual implementation // is platform-dependent. For Windows, they are stored in Registry. To see, // run regedit and browse to: HKEY_CURRENT_USER\Software\JavaSoft\Prefs\mars @@ -1221,7 +1238,7 @@ public class Settings extends Observable } /** - * Get Color object for specified settings key. Returns null if key is not found or its value is not a valid color + * Get Integer object for specified settings key. Returns null if key is not found or its value is not a valid color * encoding. * * @param key the Setting key @@ -1268,6 +1285,54 @@ public class Settings extends Observable return getColorValueByPosition(position, defaultColorSettingsValues); } + /** + * Get int for specified settings key. Returns null if key is not found or its value is not a valid int + * encoding. + * + * @param key the Setting key + * @return corresponding int, or null if key not found or value not valid int + */ + public int getIntegerSettingByKey(IntegerSetting key) + { + return getIntegerValueByKey(key, integerSettingsValues); + } + + /** + * Get default int value for specified settings key. Returns null if key is not found or its value is not a valid + * integer encoding. + * + * @param key the Setting key + * @return corresponding default int, or null if key not found or value not valid integer + */ + public int getDefaultIntegerSettingByKey(IntegerSetting key) + { + return getIntegerValueByKey(key, defaultIntegerSettingsValues); + } + + /** + * Get int for specified settings name (a static constant). Returns null if argument invalid or its value + * is not a valid integer encoding. + * + * @param position the Setting name (see list of static constants) + * @return corresponding int, or null if argument invalid or value not valid integer + */ + public int getIntegerSettingByPosition(int position) + { + return getIntegerValueByPosition(position, integerSettingsValues); + } + + /** + * Get default int for specified settings name (a static constant). Returns null if argument invalid or its + * value is not a valid integer encoding. + * + * @param position the Setting name (see list of static constants) + * @return corresponding default int, or null if argument invalid or value not valid integer + */ + public int getDefaultIntegerSettingByPosition(int position) + { + return getIntegerValueByPosition(position, defaultIntegerSettingsValues); + } + /** * Set value of a boolean setting given its id and the value. * @@ -1380,6 +1445,38 @@ public class Settings extends Observable } } + /** + * Set int for specified settings key. Has no effect if key is invalid. + * + * @param key the Setting key + * @param number the integer to save + */ + public void setIntegerSettingByKey(IntegerSetting key, int number) + { + for (int i = 0; i < IntegerSetting.values().length; i++) + { + if (key.equals(IntegerSetting.values()[i])) + { + setIntegerSettingByPosition(i, number); + return; + } + } + } + + /** + * Set int for specified settings name (a static constant). Has no effect if invalid. + * + * @param position the Setting name (see list of static constants) + * @param number the integer to save + */ + public void setIntegerSettingByPosition(int position, int number) + { + if (position >= 0 && position < IntegerSetting.values().length) + { + setIntegerSetting(position, number); + } + } + ///////////////////////////////////////////////////////////////////////// // // PRIVATE HELPER METHODS TO DO THE REAL WORK @@ -1413,6 +1510,7 @@ public class Settings extends Observable fontSizeSettingsValues[i] = defaultFontSizeSettingsValues[i]; } System.arraycopy(defaultColorSettingsValues, 0, colorSettingsValues, 0, colorSettingsValues.length); + System.arraycopy(defaultIntegerSettingsValues, 0, integerSettingsValues, 0, integerSettingsValues.length); initializeEditorSyntaxStyles(); } @@ -1475,6 +1573,40 @@ public class Settings extends Observable return color; } + // Used by setter methods for integer-based settings + private void setIntegerSetting(int settingIndex, int number) + { + integerSettingsValues[settingIndex] = number; + saveIntegerSetting(settingIndex); + } + + // Get int for this key value. Get it from values array provided as argument (could be either + // the current or the default settings array). + private int getIntegerValueByKey(IntegerSetting key, int[] values) + { + int number = 0; + for (int i = 0; i < IntegerSetting.values().length; i++) + { + if (key.equals(IntegerSetting.values()[i])) + { + return getIntegerValueByPosition(i, values); + } + } + return 0; + } + + // Get int for this key array position. Get it from values array provided as argument (could be either + // the current or the default settings array). + private int getIntegerValueByPosition(int position, int[] values) + { + int number = 0; + if (position >= 0 && position < IntegerSetting.values().length) + { + number = values[position]; + } + return number; + } + // Maybe someday I'll convert the whole shebang to use Maps. In the meantime, we use // linear search of array. Not a huge deal as settings are little-used. @@ -1555,6 +1687,13 @@ public class Settings extends Observable colorSettingsValues[i] = defaultColorSettingsValues[i] = settingValue; } } + for (int i = 0; i < IntegerSetting.values().length; i++) { + settingValue = Globals.getPropertyEntry(filename, IntegerSetting.values()[i].name()); + if (settingValue != null) + { + integerSettingsValues[i] = defaultIntegerSettingsValues[i] = Integer.parseInt(settingValue); + } + } } catch (Exception e) { @@ -1590,6 +1729,11 @@ public class Settings extends Observable { colorSettingsValues[i] = preferences.get(colorSettingsKeys[i], colorSettingsValues[i]); } + + for (int i = 0; i < IntegerSetting.values().length; i++) + { + integerSettingsValues[i] = preferences.getInt(IntegerSetting.values()[i].name(), integerSettingsValues[i]); + } getEditorSyntaxStyleSettingsFromPreferences(); } @@ -1669,6 +1813,24 @@ public class Settings extends Observable } } + // Save the key-value pair in the Properties object and assure it is written to persisent storage. + private void saveIntegerSetting(int index) + { + try + { + preferences.putInt(IntegerSetting.values()[index].name(), integerSettingsValues[index]); + preferences.flush(); + } + catch (SecurityException se) + { + // cannot write to persistent storage for security reasons + } + catch (BackingStoreException bse) + { + // unable to communicate with persistent storage (strange days) + } + } + /* * Private helper to do the work of converting a string containing Text diff --git a/src/main/java/mars/tools/BitmapDisplay.kt b/src/main/java/mars/tools/BitmapDisplay.kt index f054ff5..f2b3bc4 100644 --- a/src/main/java/mars/tools/BitmapDisplay.kt +++ b/src/main/java/mars/tools/BitmapDisplay.kt @@ -1,6 +1,7 @@ package mars.tools import mars.Globals +import mars.Settings.IntegerSetting.* import mars.detectRadix import mars.mips.hardware.* import mars.toHex @@ -309,37 +310,46 @@ class BitmapDisplay : AbstractMarsToolAndApplication // UI components and layout for left half of GUI, where settings are specified. private fun buildOrganizationArea(): JComponent { + unitWidth = Globals.getSettings().getIntegerSettingByKey(UNIT_WIDTH) + val unitWidthOptions = arrayOf(1, 2, 4, 8, 16, 32) val uiUnitWidthSelector = JComboBox(arrayOf(1, 2, 4, 8, 16, 32)).apply { isEditable = false background = backgroundColor - selectedIndex = 1 + selectedIndex = unitWidthOptions.indexOf(unitWidth) toolTipText = "Width in pixels of rectangle representing memory word" addActionListener { unitWidth = getInt() + Globals.getSettings().setIntegerSettingByKey(UNIT_WIDTH, unitWidth) grid = createNewGrid() reset() } } - val uiUnitHeightSelector = JComboBox(arrayOf(1, 2, 4, 8, 16, 32)).apply { + unitHeight = Globals.getSettings().getIntegerSettingByKey(UNIT_HEIGHT) + val unitHeightOptions = arrayOf(1, 2, 4, 8, 16, 32) + val uiUnitHeightSelector = JComboBox(unitHeightOptions).apply { isEditable = false background = backgroundColor - selectedIndex = 1 + selectedIndex = unitHeightOptions.indexOf(unitHeight) toolTipText = "Height in pixels of rectangle representing memory word" addActionListener { unitHeight = getInt() + Globals.getSettings().setIntegerSettingByKey(UNIT_HEIGHT, unitHeight) grid = createNewGrid() reset() } } + displayWidth = Globals.getSettings().getIntegerSettingByKey(DISPLAY_WIDTH) + val displayWidthOptions = arrayOf(64, 128, 256, 512, 1024) val uiWidthSelector = JComboBox(arrayOf(64, 128, 256, 512, 1024)).apply { isEditable = false background = backgroundColor - selectedIndex = 3 + selectedIndex = displayWidthOptions.indexOf(displayWidth) toolTipText = "Total width in pixels of display area" addActionListener { displayWidth = getInt() + Globals.getSettings().setIntegerSettingByKey(DISPLAY_WIDTH, displayWidth) canvas.preferredSize = displayDimension canvas.size = displayDimension grid = createNewGrid() @@ -347,13 +357,16 @@ class BitmapDisplay : AbstractMarsToolAndApplication } } - val uiHeightSelector = JComboBox(arrayOf(64, 128, 256, 512, 1024)).apply { + displayHeight = Globals.getSettings().getIntegerSettingByKey(DISPLAY_HEIGHT) + val displayHeightOptions = arrayOf(64, 128, 256, 512, 1024) + val uiHeightSelector = JComboBox(displayHeightOptions).apply { isEditable = false background = backgroundColor - selectedIndex = 2 + selectedIndex = displayHeightOptions.indexOf(displayHeight) toolTipText = "Total height in pixels of display area" addActionListener { displayHeight = getInt() + Globals.getSettings().setIntegerSettingByKey(DISPLAY_HEIGHT, displayHeight) canvas.preferredSize = displayDimension canvas.size = displayDimension grid = createNewGrid()