001    package market.stdform;
002    
003    import java.awt.GridBagConstraints;
004    import java.awt.GridBagLayout;
005    import java.awt.event.ItemEvent;
006    import java.awt.event.ItemListener;
007    import java.util.Comparator;
008    
009    import javax.swing.Box;
010    import javax.swing.BoxLayout;
011    import javax.swing.DefaultCellEditor;
012    import javax.swing.JComboBox;
013    import javax.swing.JPanel;
014    import javax.swing.JScrollPane;
015    import javax.swing.JTextField;
016    import javax.swing.event.ListSelectionEvent;
017    import javax.swing.event.ListSelectionListener;
018    import javax.swing.table.TableCellEditor;
019    
020    import market.CFilter;
021    import market.CIArticle;
022    import market.CSOffer;
023    import market.Conversions;
024    import market.SMarket;
025    import market.swing.CmpNumbers;
026    import market.swing.JTADescriptionArea;
027    import sale.FormSheet;
028    import sale.FormSheetContentCreator;
029    import util.swing.AbstractTableEntryDescriptor;
030    import util.swing.TableEntryDescriptor;
031    import data.IntegerValue;
032    import data.stdforms.SingleTableFormSheet;
033    import data.swing.CountingStockTableModel;
034    
035    /**
036     * This FormSheet displays the market's stock. The contained table allows editing of the bid
037     * when the market is closed.
038     */
039    public class FSManagerOffer {
040    
041        /**
042         * Creates a {@link SingleTableFormSheet} with some extra components. The look of the table is
043         * defined by the {@link TEDManagerOffer}.
044         *
045         * @return the created SingleTableFormSheet.
046         */
047        public static SingleTableFormSheet create() {
048            final TableEntryDescriptor ted = new TEDManagerOffer();
049            final CSOffer source = SMarket.getOffer();
050            final SingleTableFormSheet stfs = SingleTableFormSheet.create(
051                    "Bestands- und Preisübersicht",
052                    source,
053                    null,                         //UIGate
054                    true,                         //show zeros
055                    ted                           //TED
056            );
057            stfs.addContentCreator(new FormSheetContentCreator() {
058                            private static final long serialVersionUID = 847788860579998662L;
059                            protected void createFormSheetContent(final FormSheet fs) {
060                    JPanel jpMain = new JPanel();
061                    JPanel jpTable = new JPanel();
062                    JPanel jpFilter = new JPanel();
063                    JPanel jpTableAndFilter = new JPanel();
064                    JPanel jpDescription = new JPanel();
065                    JScrollPane jsc = new JScrollPane();
066                    GridBagConstraints c = new GridBagConstraints();
067                    GridBagLayout gridbag = new GridBagLayout();
068                    final JComboBox jcbFilter = new JComboBox(SMarket.getArticleCategories());
069                    jcbFilter.addItemListener(new ItemListener() {
070                        public void itemStateChanged(ItemEvent e) {
071                            if (e.getStateChange() == ItemEvent.SELECTED) {
072                                int i = jcbFilter.getSelectedIndex();
073                                CFilter cf = new CFilter(source.getCatalog(null), i); //filter CatalogItems
074                                CSOffer cs = (CSOffer)source.clone();
075                                try {
076                                    cs.changeArticleCatalog(cf);  //make new CountingStock from
077                                }                                 //filtered CatalogItems
078                                catch (Exception ex){
079                                    ex.printStackTrace();
080                                }
081                                //send new created CountingStock to table
082                                stfs.setTableModel(new CountingStockTableModel(cs, null, null, true, ted));
083                            }
084                        }
085                    });
086                    final JTADescriptionArea da = new JTADescriptionArea();
087                    //add Listener to table that reacts on selection change
088                    stfs.getTable().getSelectionModel().addListSelectionListener(new ListSelectionListener() {
089                        public void valueChanged(ListSelectionEvent e) {
090                            if (!e.getValueIsAdjusting()) {
091                                da.setDescription(Conversions.recordToCIArticle(stfs.getSelectedRecord()));
092                            }
093                        }
094                    });
095                    jpTableAndFilter.setLayout(gridbag);
096                        c.gridx = 0;
097                        c.weightx = 1;
098                        c.weighty = 1;
099                        c.gridy = 0;
100                        c.fill = GridBagConstraints.BOTH;
101                      gridbag.setConstraints(jpTable, c);
102                        c.gridx = 1;
103                        c.weightx = 0;
104                        c.weighty = 1;
105                        c.gridy = 0;
106                        c.fill = GridBagConstraints.BOTH;
107                      gridbag.setConstraints(jpFilter, c);
108                    jpTableAndFilter.add(jpTable);
109                    jpTable.setLayout(new BoxLayout(jpTable, BoxLayout.X_AXIS));
110                    jpTable.add(fs.getComponent());
111                    jpTableAndFilter.add(jpFilter);
112                        jpFilter.add(jcbFilter);
113                    jpDescription.setLayout(new BoxLayout(jpDescription, BoxLayout.X_AXIS));
114                    jpDescription.add(jsc);
115                        jsc.setViewportView(da);
116    
117                    jpMain.setLayout(new BoxLayout(jpMain, BoxLayout.Y_AXIS));
118                    jpMain.add(jpTableAndFilter);
119                    jpMain.add(Box.createVerticalStrut(10));
120                    jpMain.add(jpDescription);
121    
122                    fs.setComponent(jpMain);
123                    fs.removeAllButtons();
124                }
125            });
126            return stfs;
127        }
128    }
129    
130    /**
131     * The {@link util.swing.TableEntryDescriptor} used by {@link FSManagerOffer}.
132     */
133    class TEDManagerOffer extends AbstractTableEntryDescriptor {
134    
135        /**
136             * ID for serialization.
137             */
138            private static final long serialVersionUID = 653410593044329787L;
139            private Comparator<Object> sortOffer = new CmpNumbers(CmpNumbers.OFFER);
140        private Comparator<Object> sortBid   = new CmpNumbers(CmpNumbers.BID);
141        private Comparator<Object> sortCount = new CmpNumbers(CmpNumbers.COUNT);
142    
143        /**
144         * @return the number of the table's columns.
145         */
146        public int getColumnCount() {
147            return 4;
148        }
149    
150        /**
151         * @param nIndex the affected column.
152         * @return columns' names.
153         */
154        public String getColumnName(int nIndex) {
155            return (new String[]{ "Artikel", "Einkaufspreis", "Verkaufspreis", "Anzahl"}) [nIndex];
156        }
157    
158        /**
159         * @param nIndex the affected column.
160         * @return columns' classes. They indicate how column's values should be aligned.
161         */
162        public Class<?> getColumnClass  (int nIndex) {
163            return (new Class[] {String.class, Number.class, Number.class, Number.class}) [nIndex];
164        }
165    
166        /**
167         * @param oRecord the affected table record.
168         * @param nIndex the affected column.
169         * @return columns' values
170         */
171        public Object getValueAt(Object oRecord, int nIndex) {
172            CIArticle article = Conversions.recordToCIArticle(oRecord);
173            int count = ((CountingStockTableModel.Record)oRecord).getCount();
174            switch (nIndex) {
175                case 0: return article.getArticleName();
176                case 1: return Conversions.doubleToCurrency(article.getOffer());
177                case 2: return Conversions.doubleToCurrency(article.getBid());
178                case 3: return new Integer(count).toString();
179            }
180            return null;
181        }
182    
183        /**
184         * Determines if columns can be sorted by the user.
185         *
186         * @param nIndex the affected column.
187         * @return <ul><li>true: columns can be sorted</li>
188         *              <li>false: columns cannot be sorted</li></ul>
189         */
190        public boolean canSortByColumn(int nIndex) {
191            return true;
192        }
193    
194        /**
195         * @param nIndex the affected column.
196         * @return the {@link Comparator} to be used when sorting the column.
197         */
198        public Comparator<Object> getColumnOrder(int nIndex) {
199            switch(nIndex) {
200                case 1: return sortOffer;
201                case 2: return sortBid;
202                case 3: return sortCount;
203            }
204            return null;
205        }
206    
207        /**
208         * Determines editable columns.
209         *
210         * @param oRecord the affected table record.
211         * @param nIndex the affected column.
212         * @return <ul><li>true: column's cells are editable</li>
213         *              <li>false: column's cells are not editable</li></ul>
214         */
215        public boolean isElementEditable(Object oRecord, int nIndex) {
216            //3rd column, but only if market is not open
217            return nIndex == 2 && !SMarket.isOpen();
218        }
219    
220        /**
221         * Assigns the value to a table cell.
222         *
223         * @param oRecord the affected table record
224         * @param nIndex the affected column.
225         * @param oValue the new Object that is tried to be set as the table cell's content.
226         */
227        public void setValueAt(Object oRecord, int nIndex, Object oValue) {
228            String newValueString = Conversions.convertComma((String)oValue);
229    
230            if (newValueString != null) {
231                int newPrice = new Double(Double.parseDouble(newValueString)*100).intValue();
232                if (newPrice >= 0) {
233                    Conversions.recordToCIArticle(oRecord).setBid(new IntegerValue(newPrice));
234                }
235                SMarket.getMonthlySalesStats().get(Conversions.recordToCIArticle(oRecord).getName()).newPriceSet(
236                        SMarket.getTime(), newPrice);
237            }
238        }
239    
240        /**
241         * Sets a {@link JTextField} as the editor for the editable column.
242         *
243         * @param nIndex the affected column.
244         * @return TableCellEditor of the affected column.
245         */
246        public TableCellEditor getCellEditor(int nIndex) {
247            if (nIndex == 2) {
248                 return new DefaultCellEditor(new JTextField());
249            }
250            return null;
251        }
252    }