Move the RSS button down to the status bar, along with the price summary information. Fix up the status text area to fit itself between the two. Remove the status line from individual tabs, and generally clean up the status bar handling. by mrs, 08 Nov, 2009 09:21 AM
Diff this changeset:
AuctionsUIModel.java
cyberfox 1   package com.jbidwatcher.ui;
cyberfox 2   /*
cyberfox 3    * Copyright (c) 2000-2007, CyberFOX Software, Inc. All Rights Reserved.
cyberfox 4    *
cyberfox 5    * Developed by mrs (Morgan Schweers)
cyberfox 6    */
cyberfox 7   
mrs      8   import com.jbidwatcher.util.config.*;
cyberfox 9   import com.jbidwatcher.util.Currency;
mrs      10  import com.jbidwatcher.util.Constants;
mrs      11  import com.jbidwatcher.util.queue.MQFactory;
cyberfox 12  import com.jbidwatcher.auction.AuctionEntry;
cyberfox 13  import com.jbidwatcher.auction.Auctions;
mrs      14  import com.jbidwatcher.auction.EntryInterface;
mrs      15  import com.jbidwatcher.ui.util.*;
mrs      16  import com.jbidwatcher.ui.table.TableColumnController;
mrs      17  import com.jbidwatcher.ui.table.CSVExporter;
mrs      18  import com.jbidwatcher.ui.table.TableSorter;
mrs      19  import com.jbidwatcher.ui.table.AuctionTable;
mrs      20  import com.jbidwatcher.platform.Platform;
cyberfox 21  
cyberfox 22  import javax.swing.*;
cyberfox 23  import javax.swing.event.ListSelectionEvent;
cyberfox 24  import javax.swing.event.ListSelectionListener;
mrs      25  import javax.swing.event.TableModelEvent;
mrs      26  import javax.swing.event.TableModelListener;
cyberfox 27  import javax.swing.table.TableColumn;
cyberfox 28  import java.awt.*;
mrs      29  import java.awt.event.ActionListener;
cyberfox 30  import java.awt.dnd.DropTarget;
cyberfox 31  import java.util.*;
cyberfox 32  import java.util.List;
cyberfox 33  
cyberfox 34  public class AuctionsUIModel {
cyberfox 35    private Auctions _dataModel;
cyberfox 36    private JTable _table;
cyberfox 37    private JScrollPane _scroller;
cyberfox 38    /** @noinspection FieldCanBeLocal*/
cyberfox 39    private DropTarget[] _targets;  /* This can't be local, otherwise it gets GC'ed, which is bad. */
cyberfox 40    private Color _bgColor;
cyberfox 41    private JPrintable _print;
mrs      42    private CSVExporter _export;
mrs      43    private JPanel mPanel;
cyberfox 44  
cyberfox 45    private static final myTableCellRenderer _myRenderer = new myTableCellRenderer();
mrs      46    private TableSorter _tSort;
cyberfox 47  
cyberfox 48    /**
cyberfox 49     * @brief Construct a new UI model for a provided auction list.
cyberfox 50     * @param newAuctionList - The auction list to use as a 'backing
mrs      51     *        store' for displaying lists of auctions.
mrs      52     * @param tableContextMenu - The context menu to present for this table.
mrs      53     * @param frameContextMenu - The context menu to present for whitespace outside the table.
mrs      54     * @param cornerButtonListener - The button to sit above the scrollbar.
cyberfox 55     */
mrs      56    public AuctionsUIModel(Auctions newAuctionList, JContext tableContextMenu, JContext frameContextMenu, ActionListener cornerButtonListener) {
cyberfox 57      _dataModel = newAuctionList;
cyberfox 58  
cyberfox 59      _targets = new DropTarget[2];
cyberfox 60  
mrs      61      _tSort = new TableSorter(_dataModel.getName(), "Time left", new auctionTableModel(_dataModel.getList()));
mrs      62  
mrs      63      _table = new AuctionTable(_dataModel.getName(), _tSort);
cyberfox 64      if(newAuctionList.isCompleted()) {
cyberfox 65        if(_table.convertColumnIndexToView(TableColumnController.END_DATE) == -1) {
mrs      66          _table.addColumn(new TableColumn(TableColumnController.END_DATE, Constants.DEFAULT_COLUMN_WIDTH, _myRenderer, null));
cyberfox 67        }
cyberfox 68      }
cyberfox 69      if(JConfig.queryConfiguration("show_shipping", "false").equals("true")) {
cyberfox 70        if(_table.convertColumnIndexToView(TableColumnController.SHIPPING_INSURANCE) == -1) {
cyberfox 71          _table.addColumn(new TableColumn(TableColumnController.SHIPPING_INSURANCE));
cyberfox 72        }
cyberfox 73        JConfig.killAll("show_shipping");
cyberfox 74      }
mrs      75  
mrs      76      // provide sufficient vertical height in the rows for micro-thumbnails list view
mrs      77      adjustRowHeight();
mrs      78  
mrs      79      _table.addMouseListener(tableContextMenu);
mrs      80      _tSort.addMouseListenerToHeaderInTable(_table);
mrs      81      if(Platform.isMac() || JConfig.queryConfiguration("ui.useCornerButton", "true").equals("true")) {
cyberfox 82        _scroller = new JScrollPane(_table, ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
cyberfox 83      } else {
cyberfox 84        _scroller = new JScrollPane(_table, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
cyberfox 85      }
cyberfox 86  
mrs      87      //  This is a button to manage the custom columns for the current tab.
mrs      88      if(JConfig.queryConfiguration("ui.useCornerButton", "true").equals("true")) {
mrs      89        JButton cornerButton = new JButton("*");
mrs      90        cornerButton.addActionListener(cornerButtonListener);
mrs      91        _scroller.setCorner(ScrollPaneConstants.UPPER_RIGHT_CORNER, cornerButton);
cyberfox 92      }
cyberfox 93  
cyberfox 94      _bgColor = UIManager.getColor("window");
cyberfox 95      _scroller.getViewport().setBackground(_bgColor);
mrs      96      _scroller.getViewport().addMouseListener(frameContextMenu);
cyberfox 97  
cyberfox 98      JDropListener _dropEar;
cyberfox 99      if(newAuctionList.isCompleted()) {
mrs      100       _dropEar = new JDropListener(new TargetDrop());
cyberfox 101     } else {
mrs      102       _dropEar = new JDropListener(new TargetDrop(_dataModel.getName()));
cyberfox 103     }
cyberfox 104     _targets[0] = new DropTarget(_scroller.getViewport(), _dropEar);
cyberfox 105     _targets[1] = new DropTarget(_table, _dropEar);
cyberfox 106 
cyberfox 107     _targets[0].setActive(true);
cyberfox 108     _targets[1].setActive(true);
cyberfox 109 
cyberfox 110     _print = new JPrintable(_table);
mrs      111     _export = new CSVExporter(_table);
cyberfox 112     _table.setDefaultRenderer(String.class, _myRenderer);
cyberfox 113     _table.setDefaultRenderer(Icon.class, _myRenderer);
cyberfox 114 
mrs      115     mPanel = new JPanel();
mrs      116     mPanel.setLayout(new BorderLayout());
mrs      117     mPanel.add(_scroller, BorderLayout.CENTER);
mrs      118     addSumMonitor(_table, _tSort);
mrs      119     JPanel statusPanel = new TabStatusPanel(_dataModel.getName());
mrs      120     mPanel.add(statusPanel, BorderLayout.NORTH);
cyberfox 121   }
cyberfox 122 
mrs      123   public JPanel getPanel() {
mrs      124     return mPanel;
mrs      125   }
mrs      126 
mrs      127   private void addSumMonitor(JTable table, TableSorter sort) {
mrs      128     table.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
cyberfox 129       public void valueChanged(ListSelectionEvent event) {
mrs      130         updateSum();
cyberfox 131       }
cyberfox 132     });
mrs      133 
mrs      134     sort.addTableModelListener(new TableModelListener() {
mrs      135       public void tableChanged(TableModelEvent tableModelEvent) {
mrs      136         updateSum();
mrs      137       }
mrs      138     });
cyberfox 139   }
cyberfox 140 
mrs      141   private void updateSum() {
mrs      142     int[] rowList = _table.getSelectedRows();
mrs      143     String total = sum(rowList);
mrs      144 
mrs      145     if(total == null) {
mrs      146       MQFactory.getConcrete("Swing").enqueue("PRICE  "); // A blank space to clear the price
mrs      147     } else {
mrs      148       MQFactory.getConcrete("Swing").enqueue("PRICE " + rowList.length + " / " + total);
mrs      149     }
mrs      150   }
mrs      151 
cyberfox 152   /**
cyberfox 153    * @brief Pick and return a value from the entry that best describes
cyberfox 154    * how much COULD be spent on it by the buyer.
cyberfox 155    *
cyberfox 156    * For an item not bid on, it's the current bid price.  For an item
cyberfox 157    * the user has bid on, it's their maximum bid.  For an item the
cyberfox 158    * user has a snipe set for, it's the maximum of their snipe bid.
cyberfox 159    * If the item is closed, it's just the current bid price.
cyberfox 160    *
cyberfox 161    * @param checkEntry - The AuctionEntry to operate on.
cyberfox 162    *
cyberfox 163    * @return - A currency value containing either the current bid, the
cyberfox 164    * users high bid, or the users snipe bid.
cyberfox 165    */
cyberfox 166   private static Currency getBestBidValue(AuctionEntry checkEntry) {
mrs      167     return checkEntry.bestValue();
cyberfox 168   }
cyberfox 169 
mrs      170   //  A single accessor...
mrs      171   public TableSorter getTableSorter() { return _tSort; }
mrs      172 
mrs      173   private static Currency addUSD(Currency inCurr, AuctionEntry ae) {
cyberfox 174     boolean newCurrency = (inCurr == null || inCurr.isNull());
cyberfox 175     try {
cyberfox 176       if(ae.getShippingWithInsurance().isNull()) {
cyberfox 177         if(newCurrency) {
cyberfox 178           return ae.getUSCurBid();
cyberfox 179         }
cyberfox 180         return inCurr.add(ae.getUSCurBid());
cyberfox 181       }
cyberfox 182 
cyberfox 183       if(newCurrency) {
cyberfox 184         inCurr = ae.getUSCurBid().add(Currency.convertToUSD(ae.getUSCurBid(), ae.getCurBid(), ae.getShippingWithInsurance()));
cyberfox 185       } else {
cyberfox 186         inCurr = inCurr.add(ae.getUSCurBid().add(Currency.convertToUSD(ae.getUSCurBid(), ae.getCurBid(), ae.getShippingWithInsurance())));
cyberfox 187       }
cyberfox 188     } catch(Currency.CurrencyTypeException cte) {
mrs      189       JConfig.log().handleException("This should have been cleaned up.", cte);
cyberfox 190     }
cyberfox 191     return inCurr;
cyberfox 192   }
cyberfox 193 
cyberfox 194   private static Currency addNonUSD(Currency inCurr, AuctionEntry ae) {
cyberfox 195     boolean newCurrency = inCurr == null || inCurr.isNull();
cyberfox 196     try {
cyberfox 197       if(ae.getShippingWithInsurance().isNull()) {
cyberfox 198         if(newCurrency) {
cyberfox 199           return ae.getCurBid();
cyberfox 200         }
cyberfox 201         return inCurr.add(ae.getCurBid());
cyberfox 202       }
cyberfox 203 
cyberfox 204       if(newCurrency) {
cyberfox 205         inCurr = ae.getCurBid().add(ae.getShippingWithInsurance());
cyberfox 206       } else {
cyberfox 207         inCurr = inCurr.add(ae.getCurBid().add(ae.getShippingWithInsurance()));
cyberfox 208       }
cyberfox 209     } catch(Currency.CurrencyTypeException cte) {
mrs      210       JConfig.log().handleException("This should have been cleaned up.", cte);
cyberfox 211     }
cyberfox 212 
cyberfox 213     return inCurr;
cyberfox 214   }
cyberfox 215 
cyberfox 216   protected String sum(int[] rowList) {
cyberfox 217     boolean approx = false, i18n = true;
cyberfox 218     Currency accum = null;
cyberfox 219     Currency withShipping = null;
cyberfox 220     Currency withRealShipping = null;
cyberfox 221     Currency realAccum = null;
cyberfox 222 
cyberfox 223     try {
cyberfox 224       for (int aRowList : rowList) {
cyberfox 225         AuctionEntry ae2;
cyberfox 226         try {
cyberfox 227           ae2 = (AuctionEntry) _table.getValueAt(aRowList, -1);
cyberfox 228         } catch (IndexOutOfBoundsException bounds) {
cyberfox 229           ae2 = null;
cyberfox 230           approx = true;
cyberfox 231         }
cyberfox 232         if (ae2 != null) {
cyberfox 233           if (accum == null) {
cyberfox 234             accum = ae2.getUSCurBid();
cyberfox 235             realAccum = getBestBidValue(ae2);
cyberfox 236             withShipping = addUSD(withShipping, ae2);
cyberfox 237             withRealShipping = addNonUSD(withRealShipping, ae2);
cyberfox 238           } else {
cyberfox 239             Currency stepVal = ae2.getUSCurBid();
cyberfox 240             if (!stepVal.isNull() && !accum.isNull() && stepVal.getCurrencyType() != Currency.NONE) {
cyberfox 241               accum = accum.add(stepVal);
cyberfox 242               withShipping = addUSD(withShipping, ae2);
cyberfox 243 
cyberfox 244               //  If we're still trying to do the internationalization
cyberfox 245               //  thing, then try to keep track of the 'real' total.
cyberfox 246               if (i18n) {
cyberfox 247                 //noinspection NestedTryStatement
cyberfox 248                 try {
cyberfox 249                   realAccum = realAccum.add(getBestBidValue(ae2));
cyberfox 250                   withRealShipping = addNonUSD(withRealShipping, ae2);
cyberfox 251                 } catch (Currency.CurrencyTypeException cte) {
cyberfox 252                   //  We can't handle multiple non-USD currency types, so
cyberfox 253                   //  we stop trying to do the internationalization thing.
cyberfox 254                   i18n = false;
cyberfox 255                 }
cyberfox 256               }
cyberfox 257             }
cyberfox 258           }
cyberfox 259           if (ae2.getCurBid().getCurrencyType() != Currency.US_DOLLAR) approx = true;
cyberfox 260         }
cyberfox 261       }
cyberfox 262     } catch(Currency.CurrencyTypeException e) {
mrs      263       JConfig.log().handleException("Sum currency exception!", e);
cyberfox 264       return null;
cyberfox 265     } catch(ArrayIndexOutOfBoundsException ignored) {
mrs      266       JConfig.log().logDebug("Selection of " + rowList.length + " items changed out from under 'sum'.");
cyberfox 267       return null;
mrs      268     } catch(NullPointerException npe) {
mrs      269       JConfig.log().logDebug("sum got NPE - this is common during delete operations");
mrs      270       return null;
cyberfox 271     } catch(Exception e) {
mrs      272       JConfig.log().handleException("Sum serious exception!", e);
cyberfox 273       return null;
cyberfox 274     }
cyberfox 275 
cyberfox 276     if(accum == null || accum.isNull()) {
cyberfox 277       return null;
cyberfox 278     }
cyberfox 279 
cyberfox 280     String sAndH = "s/h";
cyberfox 281     if(!Locale.getDefault().equals(Locale.US)) sAndH = "p/p";
cyberfox 282 
cyberfox 283     //  If we managed to do the i18n thing through it all, and we have
cyberfox 284     //  some real values, return it.
cyberfox 285     if(i18n && realAccum != null) {
cyberfox 286       StringBuffer result = new StringBuffer(realAccum.toString());
cyberfox 287       if(withRealShipping != null && !realAccum.equals(withRealShipping)) {
cyberfox 288         result.append(" (").append(withRealShipping).append(" with ").append(sAndH).append(')');
cyberfox 289       }
cyberfox 290       return result.toString();
cyberfox 291     }
cyberfox 292 
cyberfox 293     if(approx) {
cyberfox 294       String result;
cyberfox 295       if(withShipping != null && !accum.equals(withShipping)) {
mrs      296         result = "About " + accum.toString() + " (" + withShipping + " with " + sAndH + ')';
cyberfox 297       } else {
mrs      298         result = "About " + accum.toString();
cyberfox 299       }
cyberfox 300       return result;
cyberfox 301     }
cyberfox 302 
cyberfox 303     if(withShipping != null && !accum.equals(withShipping)) {
cyberfox 304       return accum.toString() + " (" + withShipping + " with " + sAndH + ')';
cyberfox 305     }
cyberfox 306 
cyberfox 307     return accum.toString();
cyberfox 308   }
cyberfox 309 
cyberfox 310   /**
cyberfox 311    * @brief Sets the background color for this tab to the passed in color.
cyberfox 312    *
cyberfox 313    * @param bgColor - The color to set the background to.
cyberfox 314    */
cyberfox 315   public void setBackground(Color bgColor) {
cyberfox 316     _scroller.getViewport().setBackground(bgColor);
cyberfox 317     _table.setBackground(bgColor);
cyberfox 318     _bgColor = bgColor;
cyberfox 319   }
cyberfox 320 
cyberfox 321   /**
cyberfox 322    * @brief Return the background color this was set to.
cyberfox 323    *
cyberfox 324    * @return - The color, if any, this tab was set to.
cyberfox 325    */
cyberfox 326   public Color getBackground() {
cyberfox 327     return _bgColor;
cyberfox 328   }
cyberfox 329 
cyberfox 330   /**
mrs      331    * Delete an auction entry, using that auction entry to match against.
mrs      332    * This also tells the auction entry to unregister itself!
mrs      333    *
mrs      334    * @param inEntry - The auction entry to delete.
mrs      335    */
mrs      336   public void delEntry(EntryInterface inEntry) {
mrs      337     _tSort.delete(inEntry);
mrs      338   }
mrs      339 
mrs      340   /**
mrs      341    * Add an AuctionEntry that has already been created, denying
mrs      342    * duplicates, but allowing duplicates where both have useful
mrs      343    * information that is not the same.
mrs      344    *
mrs      345    * @param aeNew - The new auction entry to add to the tables.
mrs      346    */
mrs      347   public void addEntry(EntryInterface aeNew) {
mrs      348     if (aeNew != null) {
mrs      349       if (_tSort.insert(aeNew) == -1) {
mrs      350         JConfig.log().logMessage("JBidWatch: Bad auction entry, cannot add!");
mrs      351       }
mrs      352     }
mrs      353   }
mrs      354 
cyberfox 355   public boolean toggleField(String field) {
mrs      356     boolean rval;
cyberfox 357     int modelColumn = TableColumnController.getInstance().getColumnNumber(field);
cyberfox 358     if(_table.convertColumnIndexToView(modelColumn) == -1) {
mrs      359       _table.addColumn(new TableColumn(modelColumn, Constants.DEFAULT_COLUMN_WIDTH, _myRenderer, null));
mrs      360       rval = true;
cyberfox 361     } else {
cyberfox 362       _table.removeColumn(_table.getColumn(field));
mrs      363       _tSort.removeColumn(field, _table);
mrs      364       rval = false;
cyberfox 365     }
mrs      366 
mrs      367     adjustRowHeight();
mrs      368 
mrs      369     return rval;
mrs      370   }
mrs      371 
mrs      372   // hack and a half - but adding a row height attribute for columns seems like overkill
mrs      373   public void adjustRowHeight() {
mrs      374     Font def = myTableCellRenderer.getDefaultFont();
mrs      375     Graphics g = _table.getGraphics();
mrs      376     int defaultHeight;
mrs      377 
mrs      378     if(def == null || g == null) {
mrs      379       defaultHeight = Constants.DEFAULT_ROW_HEIGHT;
mrs      380     } else {
mrs      381       FontMetrics metrics = g.getFontMetrics(def);
mrs      382       defaultHeight = metrics.getMaxAscent() + metrics.getMaxDescent() + metrics.getLeading()+4;
mrs      383     }
mrs      384 
mrs      385     if (_table.convertColumnIndexToView(TableColumnController.THUMBNAIL) != -1) {
mrs      386       defaultHeight = Math.max(Constants.MICROTHUMBNAIL_ROW_HEIGHT, defaultHeight);
mrs      387     }
mrs      388     _table.setRowHeight(Math.max(defaultHeight, Constants.DEFAULT_ROW_HEIGHT));
mrs      389     if(def != null) {
mrs      390       _table.getTableHeader().setFont(def);
mrs      391     }
cyberfox 392   }
cyberfox 393 
cyberfox 394   public List<String> getColumns() {
cyberfox 395     ArrayList<String> al = new ArrayList<String>();
cyberfox 396     for(int i = 0; i<_table.getColumnCount(); i++) {
cyberfox 397       al.add(_table.getColumnName(i));
cyberfox 398     }
cyberfox 399 
cyberfox 400     return al;
cyberfox 401   }
cyberfox 402 
cyberfox 403   public boolean export(String fname) {
cyberfox 404     return _export.export(fname);
cyberfox 405   }
cyberfox 406 
cyberfox 407   /**
cyberfox 408    * @brief Print this table.
cyberfox 409    *
cyberfox 410    */
cyberfox 411   public void print() {
cyberfox 412     _print.doPrint();
cyberfox 413   }
cyberfox 414 
cyberfox 415   /**
cyberfox 416    * @brief Convert current column widths into display properties to
cyberfox 417    * be saved for a future session.
cyberfox 418    *
cyberfox 419    * @param addToProps - The properties object to add the column widths to.
cyberfox 420    * @param name - The category name to get the info from.
cyberfox 421    */
cyberfox 422   public void getColumnWidthsToProperties(Properties addToProps, String name) {
cyberfox 423     for(int j = 0; j<_table.getColumnCount(); j++) {
cyberfox 424       TableColumn ct;
cyberfox 425       try {
cyberfox 426         ct = _table.getColumn(_table.getColumnName(j));
cyberfox 427       } catch(IllegalArgumentException iae) {
mrs      428         JConfig.log().logMessage("Column can't be retrieved from the table: " + _table.getColumnName(j));
cyberfox 429         ct = null;
cyberfox 430       }
cyberfox 431         //      ColumnProps cp = new ColumnProps(_dataModel.getColumnName(j), j, ct.getWidth());
cyberfox 432       //noinspection StringContatenationInLoop
cyberfox 433       if(ct != null) addToProps.setProperty(name + '.' + _table.getColumnName(j), Integer.toString(j) + '.' + Integer.toString(ct.getWidth()));
cyberfox 434     }
cyberfox 435   }
cyberfox 436 
cyberfox 437   public void getColumnWidthsToProperties(Properties addToProps) {
cyberfox 438     getColumnWidthsToProperties(addToProps, _dataModel.getName());
cyberfox 439   }
cyberfox 440 
mrs      441   public void sort() {
mrs      442     _tSort.sort();
mrs      443   }
mrs      444 
mrs      445   public void redrawAll() {
mrs      446     _tSort.tableChanged(new TableModelEvent(_tSort));
mrs      447   }
cyberfox 448 }

Check out the code: svn co jbidwatcher/trunk/src/com/jbidwatcher/ui/AuctionsUIModel.java