001/*
002 * This file is part of McIDAS-V
003 *
004 * Copyright 2007-2023
005 * Space Science and Engineering Center (SSEC)
006 * University of Wisconsin - Madison
007 * 1225 W. Dayton Street, Madison, WI 53706, USA
008 * https://www.ssec.wisc.edu/mcidas
009 * 
010 * All Rights Reserved
011 * 
012 * McIDAS-V is built on Unidata's IDV and SSEC's VisAD libraries, and
013 * some McIDAS-V source code is based on IDV and VisAD source code.  
014 * 
015 * McIDAS-V is free software; you can redistribute it and/or modify
016 * it under the terms of the GNU Lesser Public License as published by
017 * the Free Software Foundation; either version 3 of the License, or
018 * (at your option) any later version.
019 * 
020 * McIDAS-V is distributed in the hope that it will be useful,
021 * but WITHOUT ANY WARRANTY; without even the implied warranty of
022 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
023 * GNU Lesser Public License for more details.
024 * 
025 * You should have received a copy of the GNU Lesser Public License
026 * along with this program.  If not, see http://www.gnu.org/licenses.
027 */
028package edu.wisc.ssec.mcidasv.startupmanager.options;
029
030import static edu.wisc.ssec.mcidasv.startupmanager.options.OptionMaster.EMPTY_STRING;
031import static edu.wisc.ssec.mcidasv.startupmanager.options.OptionMaster.QUOTE_STRING;
032import static edu.wisc.ssec.mcidasv.startupmanager.options.OptionMaster.SET_PREFIX;
033
034import java.awt.event.KeyAdapter;
035import java.awt.event.KeyEvent;
036
037import javax.swing.JTextField;
038import javax.swing.SwingUtilities;
039
040import edu.wisc.ssec.mcidasv.startupmanager.Platform;
041import edu.wisc.ssec.mcidasv.startupmanager.StartupManager;
042import edu.wisc.ssec.mcidasv.startupmanager.options.OptionMaster.OptionPlatform;
043import edu.wisc.ssec.mcidasv.startupmanager.options.OptionMaster.Type;
044import edu.wisc.ssec.mcidasv.startupmanager.options.OptionMaster.Visibility;
045import edu.wisc.ssec.mcidasv.util.MakeToString;
046
047//import org.slf4j.Logger;
048//import org.slf4j.LoggerFactory;
049
050public class TextOption extends AbstractOption {
051
052    /** Logging object. */
053//    private static final Logger logger = LoggerFactory.getLogger(TextOption.class);
054
055    /** Text field value. */
056    private String value;
057
058    /**
059     * Create a startup option that allows the user to supply arbitrary text.
060     *
061     * <p><b>NOTE:</b> {@code null} is not a permitted value for any of this
062     * constructor's parameters.</p>
063     *
064     * @param id Identifier for this startup option.
065     * @param label Brief description suitable for a GUI label.
066     * @param defaultValue Default value for this startup option.
067     * @param optionPlatform Platforms where this option may be applied.
068     * @param optionVisibility Whether or not the option is presented via the GUI.
069     */
070    public TextOption(final String id, final String label, 
071        final String defaultValue, final OptionPlatform optionPlatform,
072        final Visibility optionVisibility) 
073    {
074        super(id, label, Type.TEXT, optionPlatform, optionVisibility);
075        value = defaultValue;
076    }
077
078    /**
079     * Builds a {@link JTextField} containing the text value specified in the
080     * constructor.
081     *
082     * @return {@code JTextField} to present to the user.
083     */
084    public JTextField getComponent() {
085        final JTextField tf = new JTextField(value, 10);
086        tf.addKeyListener(new KeyAdapter() {
087            @Override public void keyReleased(final KeyEvent e) {
088                setValue(tf.getText());
089            }
090        });
091        if (!onValidPlatform()) {
092            SwingUtilities.invokeLater(() -> tf.setEnabled(false));
093        }
094        return tf;
095    }
096
097    /**
098     * Returns the user's input (or the default value).
099     *
100     * @return Input or default value.
101     */
102    public String getValue() {
103//        logger.trace("returning value='{}'", value);
104        return value;
105    }
106
107    /**
108     * Stores the user's input.
109     *
110     * @param newValue User input. Should not be {@code null}; use a zero
111     * length {@code String} to specify an empty value.
112     */
113    public void setValue(final String newValue) {
114//        logger.trace("overwrite value='{}' with newValue='{}'", value, newValue);
115        value = newValue;
116    }
117
118    /**
119     * Initializes the current option using a relevant variable from the
120     * startup script.
121     *
122     * @param text Line from the startup script that represents the current
123     * option. {@code null} is not allowed.
124     *
125     * @throws IllegalArgumentException if {@code text} is not in the proper
126     * format for the current platform.
127     */
128    @Override public void fromPrefsFormat(final String text) {
129        if (!isValidPrefFormat(text)) {
130            throw new IllegalArgumentException("Incorrect syntax for this platform: " + text);
131        }
132        String copy = new String(text);
133        if (StartupManager.getInstance().getPlatform() == Platform.WINDOWS) {
134            copy = copy.replace(SET_PREFIX, EMPTY_STRING);
135        }
136        int splitAt = copy.indexOf('=');
137        if (splitAt >= 0) {
138            setValue(removeOutermostQuotes(copy.substring(splitAt + 1)));
139        } else {
140            setValue(EMPTY_STRING);
141        }
142    }
143
144    /**
145     * {@code String} representation of this {@code TextOption}.
146     *
147     * @return {@code String} that looks something like
148     * {@literal "[TextOption@7825114a: optionId=BLAH value=USER INPUT]"}.
149     */
150    public String toString() {
151        return MakeToString.fromInstance(this)
152                           .add("optionId", getOptionId())
153                           .addQuoted("value", getValue()).toString();
154    }
155
156    /**
157     * If the given {@code String} begins and ends with
158     * {@link OptionMaster#QUOTE_STRING}, this method will return the given
159     * {@code String} without the {@literal "outermost"} quote pair. Otherwise
160     * the {@code String} is returned without modification.
161     *
162     * @param value {@code String} from which the outermost pair of quotes
163     * should be removed. Cannot be {@code null}.
164     *
165     * @return Either {@code value} with the outermost pair of quotes removed,
166     * or {@code value}, unmodified.
167     */
168    public static String removeOutermostQuotes(final String value) {
169        String returnValue = value;
170        if (value.startsWith(QUOTE_STRING) && value.endsWith(QUOTE_STRING)) {
171            returnValue = value.substring(1, value.length() - 1);
172        }
173        return returnValue;
174    }
175}