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 }