001package jmri;
002
003import java.awt.*;
004import java.beans.PropertyChangeListener;
005import java.util.ArrayList;
006import java.util.HashMap;
007
008import javax.annotation.CheckForNull;
009import javax.annotation.Nonnull;
010
011/**
012 * Interface for the User Preferences Manager.
013 * <p>
014 * The User Message Preference Manager keeps track of the options that a user
015 * has selected in messages where they have selected "Remember this setting for
016 * next time"
017 *
018 * @see jmri.managers.JmriUserPreferencesManager
019 *
020 * @author Kevin Dickerson Copyright (C) 2010
021 */
022public interface UserPreferencesManager {
023
024    String PREFERENCES_UPDATED = "PreferencesUpdated"; // NOI18N
025
026    void setLoading();
027
028    void finishLoading();
029
030    /**
031     * Enquire as to the state of a user preference.
032     * <p>
033     * Preferences that have not been set will be considered to be false.
034     * <p>
035     * The name is free-form, but to avoid ambiguity it should start with the
036     * package name (package.Class) for the primary using class.
037     *
038     * @param name the name of the preference
039     * @return the state or false if never set
040     */
041    boolean getSimplePreferenceState(String name);
042
043    /**
044     * This is used to remember the last selected state of a checkBox and thus
045     * allow that checkBox to be set to a true state when it is next
046     * initialized. This can also be used anywhere else that a simple yes/no,
047     * true/false type preference needs to be stored.
048     * <p>
049     * It should not be used for remembering if a user wants to suppress a
050     * message as there is no means in the GUI for the user to reset the flag.
051     * setPreferenceState() should be used in this instance The name is
052     * free-form, but to avoid ambiguity it should start with the package name
053     * (package.Class) for the primary using class.
054     *
055     * @param name  A unique name to identify the state being stored
056     * @param state simple boolean
057     */
058    void setSimplePreferenceState(String name, boolean state);
059
060    /**
061     * Enquire as to the state of a user preference.
062     * <p>
063     * Preferences that have not been set will be considered to be defaultState.
064     * <p>
065     * The name is free-form, but to avoid ambiguity it should start with the
066     * package name (package.Class) for the primary using class.
067     *
068     * @param name the name of the preference
069     * @param defaultState the default state if not set
070     * @return the state or defaultState if never set
071     */
072    boolean getCheckboxPreferenceState(String name, boolean defaultState);
073
074    /**
075     * This is used to remember the last selected state of a checkBox and thus
076     * allow that checkBox to be set to a true state when it is next
077     * initialized. This can also be used anywhere else that a simple yes/no,
078     * true/false type preference needs to be stored.
079     * <p>
080     * It should not be used for remembering if a user wants to suppress a
081     * message as there is no means in the GUI for the user to reset the flag.
082     * setPreferenceState() should be used in this instance The name is
083     * free-form, but to avoid ambiguity it should start with the package name
084     * (package.Class) for the primary using class.
085     *
086     * @param name  A unique name to identify the state being stored
087     * @param state simple boolean
088     */
089    void setCheckboxPreferenceState(String name, boolean state);
090
091    /**
092     * Returns an ArrayList of the check box states set as true.
093     *
094     * @return list of simple preferences names
095     */
096    ArrayList<String> getSimplePreferenceStateList();
097
098    /**
099     * Used to save the state of checkboxes which can suppress messages from
100     * being displayed. This method should be used by the initiating code in
101     * conjunction with the preferenceItemDetails. Here the items are stored
102     * against a specific class and access to change them is made available via
103     * the GUI, in the preference manager.
104     * <p>
105     * The strClass parameter does not have to be the exact class name of the
106     * initiating code, but can be one where the information is related and
107     * therefore can be grouped together with.
108     * <p>
109     * Both the strClass and item although free form, should make up a unique
110     * reference.
111     *
112     * @param strClass The class that this preference should be stored or
113     *                 grouped with.
114     * @param item     The specific item that is to be stored
115     * @param state    Boolean state of the item.
116     */
117    void setPreferenceState(String strClass, String item, boolean state);
118
119    /**
120     * Returns the state of a given item registered against a specific class or
121     * item.
122     *
123     * @param strClass name of the class for this preference
124     * @param item     name of the item for which the state is being retrieved
125     * @return the state or false if not set
126     */
127    boolean getPreferenceState(String strClass, String item);
128
129    /**
130     * Register details about a particular preference, so that it can be
131     * displayed in the GUI and provide a meaning full description when
132     * presented to the user.
133     *
134     * @param strClass    A string form of the class that the preference is
135     *                    stored or grouped with
136     * @param item        The specific item that is being stored
137     * @param description A meaningful description of the item that the user
138     *                    will understand
139     */
140    void setPreferenceItemDetails(String strClass, String item, String description);
141
142    /**
143     * Returns a list of preferences that are registered against a specific
144     * class.
145     *
146     * @param strClass the class name
147     * @return the list of preference names
148     */
149    ArrayList<String> getPreferenceList(String strClass);
150
151    /**
152     * Returns the itemName of the n preference in the given class
153     *
154     * @param strClass the name of the class
155     * @param n        the position in an array
156     * @return the name of the preference or null if non-existent
157     */
158    @CheckForNull
159    String getPreferenceItemName(String strClass, int n);
160
161    /**
162     * Returns the description of the given item preference in the given class
163     *
164     * @param strClass the name of the class
165     * @param item     the name of the item
166     * @return the description of the preference
167     */
168    @CheckForNull
169    String getPreferenceItemDescription(String strClass, String item);
170
171    /**
172     * Enquire as to the state of a user preference for the current session.
173     * <p>
174     * Preferences that have not been set will be considered to be false.
175     * <p>
176     * The name is free-form, but to avoid ambiguity it should start with the
177     * package name (package.Class) for the primary using class.
178     *
179     * @param name the name of the preference
180     * @return the state or false if not set
181     */
182    boolean getSessionPreferenceState(String name);
183
184    /**
185     * Used to suppress messages for the current session, the information is not
186     * stored, can not be changed via the GUI.
187     * <p>
188     * This can be used to help prevent over loading the user with repetitive
189     * error messages such as turnout not found while loading a panel file due
190     * to a connection failing. The name is free-form, but to avoid ambiguity it
191     * should start with the package name (package.Class) for the primary using
192     * class.
193     *
194     * @param name  A unique identifier for preference.
195     * @param state suppression state of the item.
196     */
197    void setSessionPreferenceState(String name, boolean state);
198
199    // The reset is used after the preferences have been loaded for the first time
200    void resetChangeMade();
201
202    /**
203     * Show an info message ("don't forget ...") with a given dialog title and
204     * user message. Use a given preference name to determine whether to show it
205     * in the future. The combination of the classString and item parameters
206     * should form a unique value.
207     *
208     * @param title       message Box title
209     * @param message     message to be displayed
210     * @param classString name of the calling class
211     * @param item        name of the specific item this is used for
212     */
213    void showInfoMessage(String title, String message, String classString, String item);
214
215    /**
216     * Show an info message ("don't forget ...") with a given dialog title and
217     * user message.
218     * Use a given preference name to determine whether to show it in the future.
219     * The combination of the classString and item parameters should form a unique value.
220     *
221     * @param parentComponent Used to improve Dialog display, can be null.
222     * @param title       message Box title
223     * @param message     message to be displayed
224     * @param classString name of the calling class
225     * @param item        name of the specific item this is used for
226     */
227    void showInfoMessage(@CheckForNull Component parentComponent, String title,
228        String message, String classString, String item);
229    
230    /**
231     * Show an error message ("don't forget ...") with a given dialog title and
232     * user message. Use a given preference name to determine whether to show it
233     * in the future. added flag to indicate that the message should be
234     * suppressed JMRI session only. The classString and item
235     * parameters should form a unique value
236     *
237     * @param title          Message Box title
238     * @param message        Message to be displayed
239     * @param classString    String value of the calling class
240     * @param item           String value of the specific item this is used for
241     * @param sessionOnly    Means this message will be suppressed in this JMRI
242     *                       session and not be remembered
243     * @param alwaysRemember Means that the suppression of the message will be
244     *                       saved
245     */
246    void showErrorMessage(String title, String message, String classString,
247        String item, boolean sessionOnly, boolean alwaysRemember);
248
249    /**
250     * Show an error message ("don't forget ...") with a given dialog title and
251     * user message.
252     * Use a given preference name to determine whether to show it in the future.
253     * Flag to indicate that the message should be suppressed JMRI session only.
254     * The classString and item parameters should form a unique value.
255     *
256     * @param parentComponent Used to improve Dialog display, can be null.
257     * @param title          Message Box title
258     * @param message        Message to be displayed
259     * @param classString    String value of the calling class
260     * @param item           String value of the specific item this is used for
261     * @param sessionOnly    Means this message will be suppressed in this JMRI
262     *                       session and not be remembered
263     * @param alwaysRemember Means that the suppression of the message will be
264     *                       saved
265     */
266    void showErrorMessage(@CheckForNull Component parentComponent, String title,
267        String message, String classString, String item, boolean sessionOnly, boolean alwaysRemember);
268
269    /**
270     * Show an info message ("don't forget ...") with a given dialog title and
271     * user message. Use a given preference name to determine whether to show it
272     * in the future. added flag to indicate that the message should be
273     * suppressed JMRI session only. The classString and item
274     * parameters should form a unique value
275     *
276     * @param title          Message Box title
277     * @param message        Message to be displayed
278     * @param classString    String value of the calling class
279     * @param item           String value of the specific item this is used for
280     * @param sessionOnly    Means this message will be suppressed in this JMRI
281     *                       session and not be remembered
282     * @param alwaysRemember Means that the suppression of the message will be
283     *                       saved
284     */
285    void showInfoMessage(String title, String message, String classString, String item, boolean sessionOnly, boolean alwaysRemember);
286
287    /**
288     * Show an info message ("don't forget ...") with a given dialog title and
289     * user message.
290     * Use a given preference name to determine whether to show it in the future.
291     * Flag to indicate that the message should be suppressed JMRI session only.
292     * The classString and item parameters should form a unique value.
293     *
294     * @param parentComponent Used to improve Dialog display, can be null.
295     * @param title          Message Box title
296     * @param message        Message to be displayed
297     * @param classString    String value of the calling class
298     * @param item           String value of the specific item this is used for
299     * @param sessionOnly    Means this message will be suppressed in this JMRI
300     *                       session and not be remembered
301     * @param alwaysRemember Means that the suppression of the message will be
302     *                       saved
303     */
304    void showInfoMessage(@CheckForNull Component parentComponent, String title,
305        String message, String classString, String item, boolean sessionOnly, boolean alwaysRemember);
306
307    /**
308     * Show a warning message ("don't forget ...") with a given dialog title and
309     * user message. Use a given preference name to determine whether to show it
310     * in the future. added flag to indicate that the message should be
311     * suppressed JMRI session only. The classString and item
312     * parameters should form a unique value
313     *
314     * @param title          Message Box title
315     * @param message        Message to be displayed
316     * @param classString    String value of the calling class
317     * @param item           String value of the specific item this is used for
318     * @param sessionOnly    Means this message will be suppressed in this JMRI
319     *                       session and not be remembered
320     * @param alwaysRemember Means that the suppression of the message will be
321     *                       saved
322     */
323    void showWarningMessage(String title, String message, String classString,
324        String item, boolean sessionOnly, boolean alwaysRemember);
325
326    /**
327     * Show a warning message ("don't forget ...") with a given dialog title and
328     * user message.
329     * Use a given preference name to determine whether to show it in the future.
330     * Flag to indicate that the message should be suppressed JMRI session only.
331     * The classString and item parameters should form a unique value.
332     *
333     * @param parentComponent Used to improve Dialog display, can be null.
334     * @param title          Message Box title
335     * @param message        Message to be displayed
336     * @param classString    String value of the calling class
337     * @param item           String value of the specific item this is used for
338     * @param sessionOnly    Means this message will be suppressed in this JMRI
339     *                       session and not be remembered
340     * @param alwaysRemember Means that the suppression of the message will be
341     *                       saved
342     */
343    void showWarningMessage(@CheckForNull Component parentComponent, String title,
344        String message, String classString, String item, boolean sessionOnly, boolean alwaysRemember);
345
346    /**
347     * The last selected value in a given combo box.
348     *
349     * @param comboBoxName the combo box name
350     * @return the selected value
351     */
352    @CheckForNull
353    String getComboBoxLastSelection(String comboBoxName);
354
355    /**
356     * Set the last selected value in a given combo box.
357     * <p>
358     * The name is free-form, but to avoid ambiguity it should start with the
359     * package name (package.Class) for the primary using class, followed by an
360     * identifier for the combo box.
361     *
362     * @param comboBoxName the combo box name
363     * @param lastValue    the selected value
364     */
365    void setComboBoxLastSelection(String comboBoxName, String lastValue);
366
367    Dimension getScreen();
368
369    /**
370     * Check if saving preferences is allowed.
371     *
372     * @return true if saving is allowed; false otherwise
373     */
374    boolean isSaveAllowed();
375
376    /**
377     * Set if saving preferences is allowed. When setting true, preferences will
378     * be saved immediately if needed.
379     * <p>
380     * <strong>Note</strong> only set false if a number of preferences will be
381     * set together to avoid excessive disk I/O while setting preferences.
382     * <p>
383     * <strong>Note</strong> remember to allow saving as soon as blocking saving
384     * is no longer needed.
385     *
386     * @param saveAllowed true to allow saving; false to block saving
387     */
388    void setSaveAllowed(boolean saveAllowed);
389
390    void removePropertyChangeListener(PropertyChangeListener l);
391
392    void addPropertyChangeListener(PropertyChangeListener l);
393
394    /**
395     * Get the description of a class/group registered with the preferences.
396     *
397     * @param strClass the class name
398     * @return the description
399     */
400    @Nonnull
401    String getClassDescription(String strClass);
402
403    /**
404     * Get the list of the classes registered with the preference manager.
405     *
406     * @return the list of class names
407     */
408    @Nonnull
409    ArrayList<String> getPreferencesClasses();
410
411    /**
412     * Given that we know the class as a string, we will try and attempt to
413     * gather details about the preferences that has been added, so that we can
414     * make better sense of the details in the preferences window.
415     * <p>
416     * This looks for specific methods within the class called
417     * "getClassDescription" and "setMessagePreferenceDetails". If found it will
418     * invoke the methods, this will then trigger the class to send details
419     * about its preferences back to this code.
420     *
421     * @param strClass description to use for the class
422     */
423    void setClassDescription(String strClass);
424
425    /**
426     * Add descriptive details about a specific message box, so that if it needs
427     * to be reset in the preferences, then it is easily identifiable. displayed
428     * to the user in the preferences GUI.
429     *
430     * @param strClass      String value of the calling class/group
431     * @param item          String value of the specific item this is used for.
432     * @param description   A meaningful description that can be used in a label
433     *                      to describe the item
434     * @param options       A map of the integer value of the option against a
435     *                      meaningful description.
436     * @param defaultOption The default option for the given item.
437     */
438    void setMessageItemDetails(String strClass, String item, String description, HashMap<Integer, String> options, int defaultOption);
439
440    /**
441     * Returns a map of the value against description of the different items in
442     * a given class. This information can then be used to build a Combo box.
443     *
444     * @param strClass Class or group of the given item
445     * @param item     the item which we wish to return the details about.
446     * @return map of choices
447     */
448    HashMap<Integer, String> getChoiceOptions(String strClass, String item);
449
450    /**
451     * Get the number of Multiple Choice items registered with a given class.
452     *
453     * @param strClass the class name
454     * @return number of items
455     */
456    int getMultipleChoiceSize(String strClass);
457
458    /**
459     * Get a list of all the multiple choice items registered with a given
460     * class.
461     *
462     * @param strClass the class name
463     * @return list of item names
464     */
465    ArrayList<String> getMultipleChoiceList(String strClass);
466
467    /**
468     * Get the nth item name in a given class.
469     *
470     * @param strClass the class name
471     * @param n        the position
472     * @return the item name
473     */
474    String getChoiceName(String strClass, int n);
475
476    /**
477     * Get the a meaningful description of a given item in a given class or
478     * group.
479     *
480     * @param strClass the class name
481     * @param item     the item name
482     * @return the item description
483     */
484    String getChoiceDescription(String strClass, String item);
485
486    /**
487     * Get the current value of a given item in a given class.
488     *
489     * @param strClass the class name
490     * @param item     the item name
491     * @return the value
492     */
493    int getMultipleChoiceOption(String strClass, String item);
494
495    /**
496     * Returns the default value of a given item in a given class
497     *
498     * @param strClass the class name
499     * @param choice   the item name
500     * @return the default value
501     */
502    int getMultipleChoiceDefaultOption(String strClass, String choice);
503
504    /**
505     * Sets the value of a given item in a given class, by its string
506     * description.
507     *
508     * @param strClass the class name
509     * @param choice   the item name
510     * @param value    the item value description
511     */
512    void setMultipleChoiceOption(String strClass, String choice, String value);
513
514    /**
515     * Sets the value of a given item in a given class, by its integer value.
516     *
517     * @param strClass the class name
518     * @param choice   the item name
519     * @param value    the item value
520     */
521    void setMultipleChoiceOption(String strClass, String choice, int value);
522
523    /**
524     * Get the combined size of both types of items registered.
525     *
526     * @param strClass the class name
527     * @return number of registered preferences
528     */
529    int getPreferencesSize(String strClass);
530
531    /**
532     * Saves the last location of a given component on the screen.
533     * <p>
534     * The jmri.util.JmriJFrame, will automatically use the class name of the
535     * frame if the class name returned is equal to jmri.util.JmriJFrame, the
536     * location is not stored
537     *
538     * @param strClass This is a unique identifier for window location being
539     *                 saved
540     * @param location The x,y location of the window given in a Point
541     */
542    void setWindowLocation(String strClass, Point location);
543
544    /**
545     * Saves the last size of a given component on the screen
546     * <p>
547     * The jmri.util.JmriJFrame, will automatically use the class name of the
548     * frame if the class name returned is equal to jmri.util.JmriJFrame, the
549     * size is not stored
550     *
551     * @param strClass This is a unique identifier for window size being saved
552     * @param dim      The width, height size of the window given in a Dimension
553     */
554    void setWindowSize(String strClass, Dimension dim);
555
556    /**
557     * Get the x,y location of a given Window.
558     *
559     * @param strClass the class name
560     * @return the location
561     */
562    Point getWindowLocation(String strClass);
563
564    /**
565     * Returns the width, height size of a given Window
566     *
567     * @param strClass the class name
568     * @return the size
569     */
570    Dimension getWindowSize(String strClass);
571
572    ArrayList<String> getWindowList();
573
574    /**
575     * Check if there are properties for the given class
576     *
577     * @param strClass class to check
578     * @return true if properties for strClass are maintained; false otherwise
579     */
580    boolean hasProperties(String strClass);
581
582    boolean getSaveWindowSize(String strClass);
583
584    boolean getSaveWindowLocation(String strClass);
585
586    /**
587     * Set if window sizes should be saved for a given class. Method has no
588     * effect if strClass is null or equals {@code jmri.util.JmriJFrame}.
589     *
590     * @param strClass name of the class
591     * @param b        true if window sizes should be saved; false otherwise
592     */
593    void setSaveWindowSize(String strClass, boolean b);
594
595    /**
596     * Set if window locations should be saved for a given class. Method has no
597     * effect if strClass is null or equals {@code jmri.util.JmriJFrame}.
598     *
599     * @param strClass name of the class
600     * @param b        true if window locations should be saved; false otherwise
601     */
602    void setSaveWindowLocation(String strClass, boolean b);
603
604    /**
605     * Attach a key/value pair to the given class, which can be retrieved later.
606     * These are not bound properties as yet, and don't throw events on
607     * modification. Key must not be null.
608     *
609     * @param strClass class to use
610     * @param key      Prior to 4.3.5, this could be an Object.
611     * @param value    value to use
612     */
613    void setProperty(String strClass, String key, Object value);
614
615    /**
616     * Retrieve the value associated with a key in a given class If no value has
617     * been set for that key, returns null.
618     *
619     * @param strClass class to use
620     * @param key      item to retrieve
621     * @return stored value
622     */
623    Object getProperty(String strClass, String key);
624
625    /**
626     * Retrieve the complete current set of keys for a given class.
627     *
628     * @param strClass class to use
629     * @return complete set of keys
630     */
631    java.util.Set<String> getPropertyKeys(String strClass);
632
633    /*
634     Example informational message dialog box.
635
636     final UserPreferencesManager p;
637     p = jmri.InstanceManager.getDefault(jmri.UserPreferencesManager.class);
638     if (p.getProperty("thisClass", "routeSaveMsg") { // NOI18N
639         final JDialog dialog = new JDialog();
640         dialog.setTitle(Bundle.getMessage(""ReminderTitle")); // I18N
641         dialog.setLocationRelativeTo(null);
642         dialog.setDefaultCloseOperation(javax.swing.JFrame.DISPOSE_ON_CLOSE);
643         JPanel container = new JPanel();
644         container.setBorder(BorderFactory.createEmptyBorder(10,10,10,10));
645         container.setLayout(new BoxLayout(container, BoxLayout.Y_AXIS));
646
647         JLabel question = new JLabel("Remember to save your Route information.", JLabel.CENTER); // I18N
648         question.setAlignmentX(Component.CENTER_ALIGNMENT);
649         container.add(question);
650
651         JButton okButton = new JButton(Bundle.getMessage("ButtonOK");
652         JPanel buttons = new JPanel();
653         button.setAlignmentX(Component.CENTER_ALIGNMENT);
654         buttons.add(okButton);
655         container.add(buttons);
656
657         final JCheckBox remember = new JCheckBox(Bundle.getMessage("DontRemind");
658         remember.setAlignmentX(Component.CENTER_ALIGNMENT);
659         remember.setFont(remember.getFont().deriveFont(10f));
660         container.add(remember);
661
662         okButton.addActionListener(new ActionListener() {
663             public void actionPerformed(ActionEvent e) {
664                 p.setProperty("thisClass", "routeSaveMsg", remember.isSelected()) // NOI18N
665             }
666             dialog.dispose();
667         }
668         });
669
670         dialog.getContentPane().add(container);
671         dialog.pack();
672         dialog.setModal(true);
673         dialog.setVisible(true);
674     }
675
676 */
677
678 /*
679     Example question message dialog box.
680
681     final DefaultUserMessagePreferences p;
682     p = jmri.InstanceManager.getDefault(jmri.UserPreferencesManager.class);
683     if (p.getProperty("thisClass", "QuitAfterSave") == 0x00) { // NOI18N
684         final JDialog dialog = new JDialog();
685         dialog.setTitle(Bundle.getMessage("MessageShortQuitWarning")); // I18N
686         dialog.setLocationRelativeTo(null);
687         dialog.setDefaultCloseOperation(javax.swing.JFrame.DISPOSE_ON_CLOSE);
688         JPanel container = new JPanel();
689         container.setBorder(BorderFactory.createEmptyBorder(10,10,10,10));
690         container.setLayout(new BoxLayout(container, BoxLayout.Y_AXIS));
691
692         JLabel question = new JLabel(Bundle.getMessage("MessageLongQuitWarning")); // resource is in # AppsConfigBundle.properties
693         question.setAlignmentX(Component.CENTER_ALIGNMENT);
694         container.add(question);
695
696         final JCheckBox remember = new JCheckBox(Bundle.getMessage("MessageRememberSetting")); // I18N
697         remember.setFont(remember.getFont().deriveFont(10f));
698         remember.setAlignmentX(Component.CENTER_ALIGNMENT);
699
700         JButton yesButton = new JButton(Bundle.getMessage("ButtonYes"));
701         JButton noButton = new JButton(Bundle.getMessage("ButtonNo"));
702         JPanel buttons = new JPanel();
703         buttons.setAlignmentX(Component.CENTER_ALIGNMENT);
704         buttons.add(yesButton);
705         buttons.add(noButton);
706         container.add(buttons);
707
708         noButton.addActionListener(new ActionListener(){
709             public void actionPerformed(ActionEvent e) {
710                 if (remember.isSelected()) {
711                    p.setProperty("thisClass", "QuitAfterSave", 0x01) // NOI18N
712                 }
713                 dialog.dispose();
714             }
715         });
716
717         yesButton.addActionListener(new ActionListener(){
718             public void actionPerformed(ActionEvent e) {
719                 if (remember.isSelected()) {
720                    p.setProperty("thisClass", "QuitAfterSave", 0x02); // NOI18N
721                 }
722                 dialog.dispose();
723             }
724         });
725         container.add(remember);
726         container.setAlignmentX(Component.CENTER_ALIGNMENT);
727         container.setAlignmentY(Component.CENTER_ALIGNMENT);
728         dialog.getContentPane().add(container);
729         dialog.pack();
730         dialog.setModal(true);
731         dialog.setVisible(true);
732     }
733     */
734
735}