001package apps;
002
003import java.awt.event.ActionEvent;
004import java.beans.PropertyChangeEvent;
005import java.util.List;
006import java.util.ResourceBundle;
007import javax.swing.BoxLayout;
008import javax.swing.ButtonGroup;
009import javax.swing.JComponent;
010import javax.swing.JLabel;
011import javax.swing.JPanel;
012import javax.swing.JRadioButton;
013import jmri.InstanceManager;
014import jmri.SystemConnectionMemo;
015import jmri.managers.ManagerDefaultSelector;
016import jmri.profile.Profile;
017import jmri.profile.ProfileManager;
018import jmri.swing.PreferencesPanel;
019import jmri.util.javaworld.GridLayout2;
020import jmri.util.swing.JmriPanel;
021import org.openide.util.lookup.ServiceProvider;
022
023/**
024 * Provide GUI to configure InstanceManager defaults.
025 *
026 * @author Bob Jacobsen Copyright (C) 2010
027 * @since 2.9.5
028 */
029@ServiceProvider(service = PreferencesPanel.class)
030public final class ManagerDefaultsConfigPane extends JmriPanel implements PreferencesPanel {
031
032    private static final ResourceBundle rb = ResourceBundle.getBundle("apps.AppsConfigBundle");
033    private boolean dirty = false;
034
035    public ManagerDefaultsConfigPane() {
036
037        setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
038
039        matrix = new JPanel();
040        add(matrix);
041        InstanceManager.getDefault(ManagerDefaultSelector.class).addPropertyChangeListener((PropertyChangeEvent e) -> {
042            if (e.getPropertyName().equals("Updated")) {
043                update();
044            }
045        });
046        update();
047    }
048
049    JPanel matrix;
050
051    /**
052     * Invoke when first displayed to load and present options.
053     */
054    public void update() {
055        log.debug(" update start");
056        matrix.removeAll();
057
058        // this doesn't find non-migrated systems, how do we handle that eventually?
059        List<SystemConnectionMemo> connList = InstanceManager.getList(SystemConnectionMemo.class);
060        if (!connList.isEmpty()) {
061            log.debug("   update of {} connections", connList.size());
062            reloadConnections(connList);
063        } else {
064            log.debug("   update with no new-form system connections configured");
065            matrix.add(new JLabel("No new-form system connections configured"));
066        }
067        log.debug(" update end");
068    }
069
070    void reloadConnections(List<SystemConnectionMemo> connList) {
071        log.debug(" reloadConnections start");
072        ManagerDefaultSelector manager = InstanceManager.getDefault(ManagerDefaultSelector.class);
073        matrix.setLayout(new GridLayout2(connList.size() + 1, manager.knownManagers.length + 1));
074        matrix.add(new JLabel(""));
075
076        for (ManagerDefaultSelector.Item item : manager.knownManagers) {
077            log.trace("   Add typeName {}", item.typeName);
078            matrix.add(new JLabel(item.typeName));
079        }
080        groups = new ButtonGroup[manager.knownManagers.length];
081        for (int i = 0; i < manager.knownManagers.length; i++) {
082            groups[i] = new ButtonGroup();
083        }
084        boolean[] selected = new boolean[manager.knownManagers.length];
085        for (int x = 0; x < connList.size(); x++) { // up to down
086            SystemConnectionMemo memo = connList.get(x);
087            String connectionName = memo.getUserName();
088            log.trace("   Connection name {}", connectionName);
089            matrix.add(new JLabel(connectionName));
090            int i = 0;
091            for (ManagerDefaultSelector.Item item : manager.knownManagers) { // left to right
092                log.trace("      item {}", item.typeName);
093                if (memo.provides(item.managerClass)) {
094                    JRadioButton r = new SelectionButton(connectionName, item.typeName, item.managerClass, this);
095                    matrix.add(r);
096                    groups[i].add(r);
097                    if (!selected[i] && manager.getDefault(item.managerClass) == null) {
098                        log.trace("      setting selected based on default");
099                        r.setSelected(true);
100                        selected[i] = true;
101                    }
102                } else {
103                    // leave a blank
104                    JRadioButton r = new JRadioButton();
105                    r.setToolTipText(Bundle.getMessage("TooltipDefaultnotValid", connectionName, dropTags(item.typeName)));
106                    r.setEnabled(false);
107                    matrix.add(r);
108                }
109                i++; //we need to increment 'i' as we are going onto the next group even if we added a blank button
110            }
111        }
112        revalidate();
113        log.debug(" reloadConnections end");
114    }
115
116    ButtonGroup[] groups;
117
118    @Override
119    public String getPreferencesItem() {
120        return "DEFAULTS"; // NOI18N
121    }
122
123    @Override
124    public String getPreferencesItemText() {
125        return rb.getString("MenuDefaults"); // NOI18N
126    }
127
128    @Override
129    public String getTabbedPreferencesTitle() {
130        return rb.getString("TabbedLayoutDefaults"); // NOI18N
131    }
132
133    @Override
134    public String getLabelKey() {
135        return rb.getString("LabelTabbedLayoutDefaults"); // NOI18N
136    }
137
138    @Override
139    public JComponent getPreferencesComponent() {
140        return this;
141    }
142
143    @Override
144    public boolean isPersistant() {
145        return true;
146    }
147
148    @Override
149    public String getPreferencesTooltip() {
150        return null;
151    }
152
153    @Override
154    public void savePreferences() {
155        Profile profile = ProfileManager.getDefault().getActiveProfile();
156        if (profile != null) {
157            InstanceManager.getDefault(ManagerDefaultSelector.class).savePreferences(profile);
158        }
159    }
160
161    @Override
162    public boolean isDirty() {
163        return this.dirty;
164    }
165
166    @Override
167    public boolean isRestartRequired() {
168        return this.isDirty();
169    }
170
171    @Override
172    public boolean isPreferencesValid() {
173        return InstanceManager.getDefault(ManagerDefaultSelector.class).isPreferencesValid(ProfileManager.getDefault().getActiveProfile());
174    }
175
176    private static String dropTags(String s) {
177        //while (s.contains("<")) {
178            return s.replaceAll("</?[a-zA-Z]*>"," ");
179        //}
180    }
181    
182    /**
183     * Captive class to track changes.
184     */
185    static final class SelectionButton extends JRadioButton {
186
187        SelectionButton(String connectionName, String managerName, Class<?> managerClass, ManagerDefaultsConfigPane pane) {
188            super();
189            this.managerClass = managerClass;
190            this.connectionName = connectionName;
191            // we want to remove tags from the manager name
192            this.managerName = dropTags(managerName);
193
194            // for screen readers
195            setToolTipText(makeToolTipText());
196            
197            log.trace("      SelectionButton ctor for {} as {}", connectionName, managerName);
198            if (connectionName.equals(InstanceManager.getDefault(ManagerDefaultSelector.class).getDefault(managerClass))) {
199                this.setSelected(true);
200            }
201
202            addActionListener((ActionEvent e) -> {
203                if (isSelected()) {
204                    InstanceManager.getDefault(ManagerDefaultSelector.class).setDefault(SelectionButton.this.managerClass, SelectionButton.this.connectionName);
205                    pane.dirty = true;
206                    setToolTipText(Bundle.getMessage("TooltipDefaultSelectedRestart", this.connectionName, this.managerName)); // update the tooltip when selected
207                }
208            });
209
210        }
211        String connectionName;
212        String managerName;
213        Class<?> managerClass;
214        
215        private String makeToolTipText() { 
216            return (isSelected()? Bundle.getMessage("TooltipDefaultSelected", connectionName, managerName):
217                    Bundle.getMessage("TooltipDefaultNotSelected", connectionName, managerName));
218        }
219
220        @Override
221        public void setSelected(boolean t) {
222            super.setSelected(t);
223            log.debug("SelectionButton setSelected called with {}", t);
224            setToolTipText(makeToolTipText());
225            if (t) {
226                InstanceManager.getDefault(ManagerDefaultSelector.class).setDefault(this.managerClass, this.connectionName);
227            }
228        }
229    }
230
231    private final static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(ManagerDefaultsConfigPane.class);
232
233}