001package jmri.jmrit.display.palette;
002
003import java.awt.datatransfer.DataFlavor;
004import java.awt.datatransfer.UnsupportedFlavorException;
005import java.io.IOException;
006
007import javax.swing.Box;
008import javax.swing.BoxLayout;
009import javax.swing.JComponent;
010import javax.swing.JLabel;
011import javax.swing.JPanel;
012import javax.swing.JSpinner;
013import javax.swing.JTextField;
014import javax.swing.SpinnerNumberModel;
015import javax.swing.event.ChangeEvent;
016import javax.swing.event.ChangeListener;
017import javax.swing.event.ListSelectionEvent;
018
019import jmri.Memory;
020import jmri.jmrit.catalog.NamedIcon;
021import jmri.jmrit.display.DisplayFrame;
022import jmri.jmrit.display.Editor;
023import jmri.jmrit.display.MemoryComboIcon;
024import jmri.jmrit.display.MemoryIcon;
025import jmri.jmrit.display.MemoryInputIcon;
026import jmri.jmrit.display.MemorySpinnerIcon;
027import jmri.jmrit.display.PreviewPanel;
028import jmri.jmrit.picker.PickListModel;
029import jmri.util.swing.JmriJOptionPane;
030
031public class MemoryItemPanel extends TableItemPanel<Memory> implements ChangeListener {
032
033    enum Type {
034        READONLY, READWRITE, SPINNER, COMBO
035    }
036    JSpinner _spinner;
037    String[] list = {"Item1", "Item2", "Item3"};
038
039    public MemoryItemPanel(DisplayFrame parentFrame, String type, String family, PickListModel<jmri.Memory> model) {
040        super(parentFrame, type, family, model);
041    }
042
043    @Override
044    public void init() {
045        if (!_initialized) {
046            add(initTablePanel(_model));
047            initIconFamiliesPanel();
048            add(_iconFamilyPanel);
049            _previewPanel = new PreviewPanel(_frame, _dragIconPanel, _iconPanel, true);
050            add(_previewPanel);
051            _initialized = true;
052        }
053    }
054
055    @Override
056    protected JPanel instructions() {
057        JPanel blurb = new JPanel();
058        blurb.setLayout(new BoxLayout(blurb, BoxLayout.Y_AXIS));
059        blurb.add(Box.createVerticalStrut(ItemPalette.STRUT_SIZE));
060        blurb.add(new JLabel(Bundle.getMessage("AddMemoryToPanel")));
061        blurb.add(new JLabel(Bundle.getMessage("MemoryDragStart")));
062        blurb.add(new JLabel(Bundle.getMessage("MemoryDragFix")));
063        blurb.add(Box.createVerticalStrut(ItemPalette.STRUT_SIZE));
064        blurb.add(new JLabel(Bundle.getMessage("DecorateMemory")));
065        blurb.add(Box.createVerticalStrut(ItemPalette.STRUT_SIZE));
066        JPanel panel = new JPanel();
067        panel.add(blurb);
068        return panel;
069    }
070
071    @Override
072    protected void hideIcons() {
073    }
074
075    /**
076     * CENTER Panel
077     */
078    MemoryIcon _readMem;
079    MemoryInputIcon _writeMem;
080    MemorySpinnerIcon _spinMem;
081    MemoryComboIcon _comboMem;
082
083    @Override
084    protected void initIconFamiliesPanel() {
085        _iconFamilyPanel = new JPanel();
086        _iconFamilyPanel.setLayout(new BoxLayout(_iconFamilyPanel, BoxLayout.Y_AXIS));
087        _iconFamilyPanel.setOpaque(true);
088        if (!_update) {
089            _iconFamilyPanel.add(instructions());
090        }
091
092        makeDragIconPanel();
093        makeDndIcon(null);
094        log.debug("initIconFamiliesPanel done");
095    }
096
097    @Override
098    protected void makeDndIcon(java.util.HashMap<String, NamedIcon> iconMap) {
099        if (_update) {
100            return;
101        }
102        JPanel panel = new JPanel();
103        panel.setOpaque(false);
104        panel.setLayout(new java.awt.GridBagLayout());
105        Editor editor = _frame.getEditor();
106        java.awt.GridBagConstraints c = new java.awt.GridBagConstraints();
107        c.gridwidth = 1;
108        c.gridheight = 1;
109        c.gridx = 0;
110        c.gridy = 0;
111        c.anchor = java.awt.GridBagConstraints.CENTER;
112        c.weightx = 1.0;
113
114        JLabel label = new JLabel(Bundle.getMessage("ReadWriteMemory"));
115        label.setOpaque(false);
116        panel.add(label, c);
117        c.gridy = 1;
118        _writeMem = new MemoryInputIcon(5, editor);
119        panel.add(makeDragIcon(_writeMem, Type.READWRITE), c);
120
121        c.gridx = 1;
122        c.gridy = 0;
123        c.anchor = java.awt.GridBagConstraints.CENTER;
124        label = new JLabel(Bundle.getMessage("ReadMemory"));
125        label.setOpaque(false);
126        panel.add(label, c);
127        c.gridy = 1;
128        _readMem = new MemoryIcon("_____", editor);
129        panel.add(makeDragIcon(_readMem, Type.READONLY), c);
130
131        c.gridx = 2;
132        c.gridy = 0;
133        label = new JLabel(Bundle.getMessage("SpinnerMemory"));
134        label.setOpaque(false);
135        panel.add(label, c);
136        c.gridy = 1;
137        _spinMem = new MemorySpinnerIcon(editor);
138        panel.add(makeDragIcon(_spinMem, Type.SPINNER), c);
139
140        c.gridx = 3;
141        c.gridy = 0;
142        label = new JLabel(Bundle.getMessage("ComboMemory"));
143        label.setOpaque(false);
144        panel.add(label, c);
145        c.gridy = 1;
146        String[] list = {"item1", "Item2", "Item3"};
147        _comboMem = new MemoryComboIcon(editor, list);
148        panel.add(makeDragIcon(_comboMem, Type.COMBO), c);
149
150        _spinner = new JSpinner(new SpinnerNumberModel(0, 0, 100, 1));
151        JTextField field = ((JSpinner.DefaultEditor) _spinner.getEditor()).getTextField();
152        field.setColumns(2);
153        field.setText("5");
154        _spinner.setMaximumSize(_spinner.getPreferredSize());
155        _spinner.addChangeListener(this);
156        c.gridx = 1;
157        c.gridy = 2;
158        c.gridwidth = 2;
159        c.anchor = java.awt.GridBagConstraints.CENTER;
160        panel.add(_spinner, c);
161
162        c.gridy = 3;
163        c.anchor = java.awt.GridBagConstraints.NORTH;
164        label = new JLabel(Bundle.getMessage("MemoryWidth"));
165        label.setOpaque(false);
166        panel.add(label, c);
167
168        _dragIconPanel.add(panel);
169        _dragIconPanel.invalidate();
170    }
171
172    private JPanel makeDragIcon(JComponent mem, Type type) {
173        JPanel panel = new JPanel();
174        panel.setOpaque(false);
175        JPanel comp;
176        try {
177            comp = getDragger(new DataFlavor(Editor.POSITIONABLE_FLAVOR), type, mem);
178            comp.setOpaque(false);
179            comp.setToolTipText(Bundle.getMessage("ToolTipDragIcon"));
180        } catch (java.lang.ClassNotFoundException cnfe) {
181            log.error("Unable to find class supporting {}", Editor.POSITIONABLE_FLAVOR, cnfe);
182            comp = new JPanel();
183        }
184        panel.add(comp);
185        return panel;
186    }
187
188    /*
189     * Set column width for InputMemoryIcon.
190     */
191    @Override
192    public void stateChanged(ChangeEvent e) {
193        if (log.isDebugEnabled()) {
194            log.debug("stateChanged: class= {}, value= {}", _spinner.getValue().getClass().getName(),
195                    _spinner.getValue());
196        }
197        Integer nCols = (Integer) _spinner.getValue();
198        _writeMem.setNumColumns(nCols);
199    }
200
201    /**
202     * ListSelectionListener action from table.
203     */
204    @Override
205    public void valueChanged(ListSelectionEvent e) {
206        if (_table == null) {
207            return;
208        }
209        int row = _table.getSelectedRow();
210        log.debug("Table valueChanged: row= {}", row);
211        if (row >= 0) {
212            if (_updateButton != null) {
213                _updateButton.setEnabled(true);
214                _updateButton.setToolTipText(null);
215            }
216        } else {
217            if (_updateButton != null) {
218                _updateButton.setEnabled(false);
219                _updateButton.setToolTipText(Bundle.getMessage("ToolTipPickFromTable"));
220            }
221            _dragIconPanel.removeAll();
222            makeDragIconPanel();
223            makeDndIcon(null); // use override
224        }
225        validate();
226    }
227
228    protected IconDragJComponent getDragger(DataFlavor flavor, Type type, JComponent comp) {
229        return new IconDragJComponent(flavor, type, comp);
230    }
231
232    protected class IconDragJComponent extends DragJComponent {
233
234        Type _memType;
235
236        public IconDragJComponent(DataFlavor flavor, Type type, JComponent comp) {
237            super(flavor, comp);
238            _memType = type;
239        }
240
241        @Override
242        protected boolean okToDrag() {
243            Memory bean = getDeviceNamedBean();
244            if (bean == null) {
245                JmriJOptionPane.showMessageDialog(this, Bundle.getMessage("noRowSelected"),
246                        Bundle.getMessage("WarningTitle"), JmriJOptionPane.WARNING_MESSAGE);
247                return false;
248            }
249            return true;
250        }
251
252        @Override
253        public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException {
254            if (!isDataFlavorSupported(flavor)) {
255                return null;
256            }
257            Memory bean = getDeviceNamedBean();
258            if (bean == null) {
259                log.error("IconDragJComponent.getTransferData: Memory is null!");
260                return null;
261            }
262
263            Editor editor = _frame.getEditor();
264            if (flavor.isMimeTypeEqual(Editor.POSITIONABLE_FLAVOR)) {
265                int numCols = 5;
266                try {
267                    ((JSpinner.DefaultEditor) _spinner.getEditor()).commitEdit();
268                    SpinnerNumberModel spinModel = (SpinnerNumberModel) _spinner.getModel();
269                    if (log.isDebugEnabled()) {
270                        log.debug("MemoryDnD.createTransferable: spinCols= {}", spinModel.getNumber().intValue());
271                    }
272                    numCols = spinModel.getNumber().intValue();
273                } catch (java.text.ParseException pe) {
274                    log.error("MemoryDnD.createTransferable: ", pe);
275                }
276                switch (_memType) {
277                    case READONLY:
278                        MemoryIcon m = new MemoryIcon("", editor);
279                        m.setMemory(bean.getDisplayName());
280//                        m.setSize(m.getPreferredSize().width, m.getPreferredSize().height);
281                        m.getPopupUtility().setFixedWidth(numCols*10);
282                        m.setLevel(Editor.MEMORIES);
283                        return m;
284                    case READWRITE:
285                        MemoryInputIcon mi = new MemoryInputIcon(numCols, editor);
286                        mi.setMemory(bean.getDisplayName());
287                        mi.setSize(mi.getPreferredSize().width, mi.getPreferredSize().height);
288                        mi.setLevel(Editor.MEMORIES);
289                        return mi;
290                    case SPINNER:
291                        MemorySpinnerIcon ms = new MemorySpinnerIcon(editor);
292                        ms.setMemory(bean.getDisplayName());
293                        ms.setSize(ms.getPreferredSize().width, ms.getPreferredSize().height);
294                        ms.setLevel(Editor.MEMORIES);
295                        return ms;
296                    case COMBO:
297                        MemoryComboIcon mc = new MemoryComboIcon(editor, list);
298                        mc.setMemory(bean.getDisplayName());
299                        mc.setSize(mc.getPreferredSize().width, mc.getPreferredSize().height);
300                        mc.setLevel(Editor.MEMORIES);
301                        return mc;
302                    default:
303                        // fall through
304                        break;
305                }
306            } else if (DataFlavor.stringFlavor.equals(flavor)) {
307                return _itemType + " icons for \"" + bean.getDisplayName() + "\"";
308            }
309            return null;
310        }
311    }
312
313    private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(MemoryItemPanel.class);
314
315}