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 }