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 }