001package jmri.jmrit.throttle;
002
003import java.util.ArrayList;
004import java.util.Iterator;
005
006import javax.swing.JFrame;
007
008import jmri.InstanceManagerAutoDefault;
009import jmri.util.JmriJFrame;
010
011import org.jdom2.Element;
012// import org.slf4j.Logger;
013// import org.slf4j.LoggerFactory;
014
015/**
016 * Interface for allocating and deallocating throttles frames. Not to be
017 * confused with ThrottleManager.
018 *
019 * @author Glen Oberhauser
020 */
021public class ThrottleFrameManager implements InstanceManagerAutoDefault {
022
023    private int activeFrame;
024
025    private ArrayList<ThrottleWindow> throttleWindows; // synchronized access
026
027    private ThrottlesPreferencesWindow throttlePreferencesFrame;
028    private JmriJFrame throttlesListFrame;
029    private ThrottlesListPanel throttlesListPanel;
030
031    /**
032     * Constructor for the ThrottleFrameManager object.
033     */
034    public ThrottleFrameManager() {
035        throttleWindows = new ArrayList<>(0);
036        buildThrottleListFrame();
037    }
038
039    /**
040     * Tell this manager that a new ThrottleWindow was created.
041     *
042     * @return The newly created ThrottleWindow
043     */
044    public ThrottleWindow createThrottleWindow() {
045        return createThrottleWindow((jmri.jmrix.ConnectionConfig) null);
046    }
047
048    /**
049     * Tell this manager that a new ThrottleWindow was created.
050     *
051     * @param connectionConfig the connection config
052     * @return The newly created ThrottleWindow
053     */
054    public ThrottleWindow createThrottleWindow(jmri.jmrix.ConnectionConfig connectionConfig) {
055        ThrottleWindow tw = new ThrottleWindow(connectionConfig);
056        tw.pack();
057        synchronized (this) {
058            throttleWindows.add(tw);
059            activeFrame = throttleWindows.indexOf(tw);
060        }
061        return tw;
062    }
063
064    /**
065     * Tell this manager that a new ThrottleWindow was created.
066     *
067     * @param e the xml element for the throttle window
068     * @return The newly created ThrottleWindow
069     */
070    public ThrottleWindow createThrottleWindow(Element e) {
071        ThrottleWindow tw = ThrottleWindow.createThrottleWindow(e);
072        tw.pack();
073        synchronized (this) {
074            throttleWindows.add(tw);
075            activeFrame = throttleWindows.indexOf(tw);
076        }
077        return tw;
078    }
079
080    /**
081     * Tell this manager that a new ThrottleFrame was created.
082     *
083     * @return The newly created ThrottleFrame
084     */
085    public ThrottleFrame createThrottleFrame() {
086        return createThrottleFrame(null);
087    }
088
089    /**
090     * Tell this manager that a new ThrottleFrame was created.
091     *
092     * @param connectionConfig the connection config
093     * @return The newly created ThrottleFrame
094     */
095    public ThrottleFrame createThrottleFrame(jmri.jmrix.ConnectionConfig connectionConfig) {
096        return createThrottleWindow(connectionConfig).getCurrentThrottleFrame();
097    }
098
099    /**
100     * Request that this manager destroy a throttle frame.
101     *
102     * @param frame The to-be-destroyed ThrottleFrame
103     */
104    public void requestThrottleWindowDestruction(ThrottleWindow frame) {
105        if (frame != null) {
106            destroyThrottleWindow(frame);
107            synchronized (this) {
108                throttleWindows.remove(frame);
109                if (!throttleWindows.isEmpty()) {
110                    requestFocusForNextThrottleWindow();
111                }
112            }
113        }
114    }
115
116    public synchronized void requestAllThrottleWindowsDestroyed() {
117        for (ThrottleWindow frame : throttleWindows) {
118            destroyThrottleWindow(frame);
119        }
120        throttleWindows = new ArrayList<>(0);
121    }
122
123    /**
124     * Perform the destruction of a ThrottleFrame. This method will not affect
125     * the throttleFrames list, thus ensuring no synchronozation problems.
126     *
127     * @param window The ThrottleFrame to be destroyed.
128     */
129    private void destroyThrottleWindow(ThrottleWindow window) {
130        window.dispose();
131    }
132
133    /**
134     * Retrieve an Iterator over all the ThrottleFrames in existence.
135     *
136     * @return The Iterator on the list of ThrottleFrames.
137     */
138    public synchronized Iterator<ThrottleWindow> getThrottleWindows() {
139        return throttleWindows.iterator();
140    }
141
142    public synchronized int getNumberThrottleWindows() {
143        return throttleWindows.size();
144    }
145
146    public synchronized void requestFocusForNextThrottleWindow() {
147        activeFrame = (activeFrame + 1) % throttleWindows.size();
148        ThrottleWindow tw = throttleWindows.get(activeFrame);
149        tw.requestFocus();
150        tw.toFront();
151    }
152
153    public synchronized void requestFocusForPreviousThrottleWindow() {
154        activeFrame--;
155        if (activeFrame < 0) {
156            activeFrame = throttleWindows.size() - 1;
157        }
158        ThrottleWindow tw = throttleWindows.get(activeFrame);
159        tw.requestFocus();
160        tw.toFront();
161    }
162
163    public synchronized ThrottleWindow getCurrentThrottleFrame() {
164        if (throttleWindows == null) {
165            return null;
166        }
167        if (throttleWindows.isEmpty()) {
168            return null;
169        }
170        return throttleWindows.get(activeFrame);
171    }
172
173    public ThrottlesListPanel getThrottlesListPanel() {
174        return throttlesListPanel;
175    }
176
177    private void buildThrottleListFrame() {
178        throttlesListFrame = new JmriJFrame(Bundle.getMessage("ThrottleListFrameTile"));
179        throttlesListPanel = new ThrottlesListPanel();
180        throttlesListFrame.setContentPane(throttlesListPanel);
181        throttlesListFrame.pack();
182    }
183
184    /*
185     * Show JMRI native throttle list window
186     *
187     */
188    public void showThrottlesList() {
189        if (throttlesListFrame == null) {
190            buildThrottleListFrame();
191        }
192        throttlesListFrame.setVisible(true);
193    }
194
195    /*
196     * Show throttle preferences window
197     *
198     */
199    public void showThrottlesPreferences() {
200        if (throttlePreferencesFrame == null) {
201            throttlePreferencesFrame = new ThrottlesPreferencesWindow(Bundle.getMessage("ThrottlePreferencesFrameTitle"));
202            throttlePreferencesFrame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
203            throttlePreferencesFrame.pack();
204        } else {
205            throttlePreferencesFrame.resetComponents();
206            throttlePreferencesFrame.revalidate();
207        }
208        throttlePreferencesFrame.setVisible(true);
209        throttlePreferencesFrame.requestFocus();
210    }
211
212    /*
213     * Apply curent throttle preferences to all throttle windows
214     *
215     */
216    public void applyPreferences() {
217        throttleWindows.forEach(frame -> {
218            frame.applyPreferences();
219        });
220        throttlesListPanel.applyPreferences();
221    }
222
223    // private final static Logger log = LoggerFactory.getLogger(ThrottleFrameManager.class);
224}