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 protected void createFormSheetContent(final FormSheet fs) { 059 JPanel jpMain = new JPanel(); 060 JPanel jpTable = new JPanel(); 061 JPanel jpFilter = new JPanel(); 062 JPanel jpTableAndFilter = new JPanel(); 063 JPanel jpDescription = new JPanel(); 064 JScrollPane jsc = new JScrollPane(); 065 GridBagConstraints c = new GridBagConstraints(); 066 GridBagLayout gridbag = new GridBagLayout(); 067 final JComboBox jcbFilter = new JComboBox(SMarket.getArticleCategories()); 068 jcbFilter.addItemListener(new ItemListener() { 069 public void itemStateChanged(ItemEvent e) { 070 if (e.getStateChange() == e.SELECTED) { 071 int i = jcbFilter.getSelectedIndex(); 072 CFilter cf = new CFilter(source.getCatalog(null), i); //filter CatalogItems 073 CSOffer cs = (CSOffer)source.clone(); 074 try { 075 cs.changeArticleCatalog(cf); //make new CountingStock from 076 } //filtered CatalogItems 077 catch (Exception ex){ 078 ex.printStackTrace(); 079 } 080 //send new created CountingStock to table 081 stfs.setTableModel(new CountingStockTableModel(cs, null, null, true, ted)); 082 } 083 } 084 }); 085 final JTADescriptionArea da = new JTADescriptionArea(); 086 //add Listener to table that reacts on selection change 087 stfs.getTable().getSelectionModel().addListSelectionListener(new ListSelectionListener() { 088 public void valueChanged(ListSelectionEvent e) { 089 if (!e.getValueIsAdjusting()) { 090 da.setDescription(Conversions.recordToCIArticle(stfs.getSelectedRecord())); 091 } 092 } 093 }); 094 jpTableAndFilter.setLayout(gridbag); 095 c.gridx = 0; 096 c.weightx = 1; 097 c.weighty = 1; 098 c.gridy = 0; 099 c.fill = GridBagConstraints.BOTH; 100 gridbag.setConstraints(jpTable, c); 101 c.gridx = 1; 102 c.weightx = 0; 103 c.weighty = 1; 104 c.gridy = 0; 105 c.fill = GridBagConstraints.BOTH; 106 gridbag.setConstraints(jpFilter, c); 107 jpTableAndFilter.add(jpTable); 108 jpTable.setLayout(new BoxLayout(jpTable, BoxLayout.X_AXIS)); 109 jpTable.add(fs.getComponent()); 110 jpTableAndFilter.add(jpFilter); 111 jpFilter.add(jcbFilter); 112 jpDescription.setLayout(new BoxLayout(jpDescription, BoxLayout.X_AXIS)); 113 jpDescription.add(jsc); 114 jsc.setViewportView(da); 115 116 jpMain.setLayout(new BoxLayout(jpMain, BoxLayout.Y_AXIS)); 117 jpMain.add(jpTableAndFilter); 118 jpMain.add(Box.createVerticalStrut(10)); 119 jpMain.add(jpDescription); 120 121 fs.setComponent(jpMain); 122 fs.removeAllButtons(); 123 } 124 }); 125 return stfs; 126 } 127 } 128 129 /** 130 * The {@link util.swing.TableEntryDescriptor} used by {@link FSManagerOffer}. 131 */ 132 class TEDManagerOffer extends AbstractTableEntryDescriptor { 133 134 private Comparator sortOffer = new CmpNumbers(CmpNumbers.OFFER); 135 private Comparator sortBid = new CmpNumbers(CmpNumbers.BID); 136 private Comparator sortCount = new CmpNumbers(CmpNumbers.COUNT); 137 138 /** 139 * @return the number of the table's columns. 140 */ 141 public int getColumnCount() { 142 return 4; 143 } 144 145 /** 146 * @param nIndex the affected column. 147 * @return columns' names. 148 */ 149 public String getColumnName(int nIndex) { 150 return (new String[]{ "Artikel", "Einkaufspreis", "Verkaufspreis", "Anzahl"}) [nIndex]; 151 } 152 153 /** 154 * @param nIndex the affected column. 155 * @return columns' classes. They indicate how column's values should be aligned. 156 */ 157 public Class getColumnClass (int nIndex) { 158 return (new Class[] {String.class, Number.class, Number.class, Number.class}) [nIndex]; 159 } 160 161 /** 162 * @param oRecord the affected table record. 163 * @param nIndex the affected column. 164 * @return columns' values 165 */ 166 public Object getValueAt(Object oRecord, int nIndex) { 167 CountingStockTableModel.Record stockitem = null; 168 CIArticle article = Conversions.recordToCIArticle(oRecord); 169 int count = ((CountingStockTableModel.Record)oRecord).getCount(); 170 switch (nIndex) { 171 case 0: return article.getArticleName(); 172 case 1: return Conversions.doubleToCurrency(article.getOffer()); 173 case 2: return Conversions.doubleToCurrency(article.getBid()); 174 case 3: return new Integer(count).toString(); 175 } 176 return null; 177 } 178 179 /** 180 * Determines if columns can be sorted by the user. 181 * 182 * @param nIndex the affected column. 183 * @return <ul><li>true: columns can be sorted</li> 184 * <li>false: columns cannot be sorted</li></ul> 185 */ 186 public boolean canSortByColumn(int nIndex) { 187 return true; 188 } 189 190 /** 191 * @param nIndex the affected column. 192 * @return the {@link Comparator} to be used when sorting the column. 193 */ 194 public Comparator getColumnOrder(int nIndex) { 195 switch(nIndex) { 196 case 1: return sortOffer; 197 case 2: return sortBid; 198 case 3: return sortCount; 199 } 200 return null; 201 } 202 203 /** 204 * Determines editable columns. 205 * 206 * @param oRecord the affected table record. 207 * @param nIndex the affected column. 208 * @return <ul><li>true: column's cells are editable</li> 209 * <li>false: column's cells are not editable</li></ul> 210 */ 211 public boolean isElementEditable(Object oRecord, int nIndex) { 212 //3rd column, but only if market is not open 213 return nIndex == 2 && !SMarket.isOpen(); 214 } 215 216 /** 217 * Assigns the value to a table cell. 218 * 219 * @param oRecord the affected table record 220 * @param nIndex the affected column. 221 * @param oValue the new Object that is tried to be set as the table cell's content. 222 */ 223 public void setValueAt(Object oRecord, int nIndex, Object oValue) { 224 String newValueString = Conversions.convertComma((String)oValue); 225 226 if (newValueString != null) { 227 int newPrice = new Double(Double.parseDouble(newValueString)*100).intValue(); 228 if (newPrice >= 0) { 229 Conversions.recordToCIArticle(oRecord).setBid(new IntegerValue(newPrice)); 230 } 231 SMarket.getMonthlySalesStats().get(Conversions.recordToCIArticle(oRecord).getName()).newPriceSet( 232 SMarket.getTime(), newPrice); 233 } 234 } 235 236 /** 237 * Sets a {@link JTextField} as the editor for the editable column. 238 * 239 * @param nIndex the affected column. 240 * @return TableCellEditor of the affected column. 241 */ 242 public TableCellEditor getCellEditor(int nIndex) { 243 if (nIndex == 2) { 244 return new DefaultCellEditor(new JTextField()); 245 } 246 return null; 247 } 248 }