Package com.jbidwatcher.ui

Source Code of com.jbidwatcher.ui.AuctionsUIModel

package com.jbidwatcher.ui;
/*
* Copyright (c) 2000-2007, CyberFOX Software, Inc. All Rights Reserved.
*
* Developed by mrs (Morgan Schweers)
*/

import com.cyberfox.util.platform.Platform;
import com.jbidwatcher.auction.*;
import com.jbidwatcher.ui.table.auctionTableModel;
import com.jbidwatcher.util.config.*;
import com.jbidwatcher.util.Currency;
import com.jbidwatcher.util.Constants;
import com.jbidwatcher.util.queue.MQFactory;
import com.jbidwatcher.ui.util.*;
import com.jbidwatcher.ui.table.TableColumnController;
import com.jbidwatcher.ui.table.CSVExporter;
import com.jbidwatcher.ui.table.AuctionTable;
import com.jbidwatcher.util.queue.PlainMessageQueue;

import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.event.TableModelEvent;
import javax.swing.table.TableColumn;
import javax.swing.table.TableModel;
import javax.swing.table.TableRowSorter;
import java.awt.*;
import java.awt.event.ActionListener;
import java.awt.dnd.DropTarget;
import java.io.IOException;
import java.util.*;
import java.util.List;

public class AuctionsUIModel {
  private Auctions _dataModel;
  private JTable _table;
  private JScrollPane _scroller;
  /** @noinspection FieldCanBeLocal*/
  private DropTarget[] _targets;  /* This can't be local, otherwise it gets GC'ed, which is bad. */
  private Color _bgColor;
  private JPrintable _print;
  private CSVExporter _export;
  private JPanel mPanel;

  private static final myTableCellRenderer _myRenderer = new myTableCellRenderer();
  private TableModel model;
  private final TableRowSorter<TableModel> sorter;

  /**
   * @brief Construct a new UI model for a provided auction list.
   * @param newAuctionList - The auction list to use as a 'backing
   *        store' for displaying lists of auctions.
   * @param tableContextMenu - The context menu to present for this table.
   * @param frameContextMenu - The context menu to present for whitespace outside the table.
   * @param cornerButtonListener - The button to sit above the scrollbar.
   */
  public AuctionsUIModel(Auctions newAuctionList, JContext tableContextMenu, final JContext frameContextMenu, ActionListener cornerButtonListener) {
    _dataModel = newAuctionList;

    _targets = new DropTarget[2];

    model = new auctionTableModel(_dataModel.getList());

    _table = new AuctionTable(_dataModel.getName(), model);
    if(newAuctionList.isCompleted()) {
      if(_table.convertColumnIndexToView(TableColumnController.END_DATE) == -1) {
        _table.addColumn(new TableColumn(TableColumnController.END_DATE, Constants.DEFAULT_COLUMN_WIDTH, _myRenderer, null));
      }
    }
    if(JConfig.queryConfiguration("show_shipping", "false").equals("true")) {
      if(_table.convertColumnIndexToView(TableColumnController.SHIPPING_INSURANCE) == -1) {
        _table.addColumn(new TableColumn(TableColumnController.SHIPPING_INSURANCE));
      }
      JConfig.killAll("show_shipping");
    }

    // provide sufficient vertical height in the rows for micro-thumbnails list view
    adjustRowHeight();

    sorter = new TableRowSorter<TableModel>(_table.getModel());
    _table.setRowSorter(sorter);
    _table.addMouseListener(tableContextMenu);
    if(Platform.isMac() || JConfig.queryConfiguration("ui.useCornerButton", "true").equals("true")) {
      _scroller = new JScrollPane(_table, ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
    } else {
      _scroller = new JScrollPane(_table, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
    }

    //  This is a button to manage the custom columns for the current tab.
    if(JConfig.queryConfiguration("ui.useCornerButton", "true").equals("true")) {
      JButton cornerButton = new JButton("*");
      cornerButton.addActionListener(cornerButtonListener);
      _scroller.setCorner(ScrollPaneConstants.UPPER_RIGHT_CORNER, cornerButton);
    }

    _bgColor = UIManager.getColor("window");
    _scroller.setViewport(new JViewport() {
      private Image image;

      {
        setBackground(_bgColor);
        addMouseListener(frameContextMenu);
        setView(_table);

        try {
          image = ImageIO.read(JConfig.getResource("/jbidwatch.jpg"));
        } catch (IOException e) {
          image = null;
        }
      }

      public void paintComponent(Graphics g) {
        super.paintComponent(g);
        if(image != null && _table.getRowCount() == 0) {
          int imageW = image.getWidth(null);
          int imageH = image.getHeight(null);

          Graphics2D g2d = (Graphics2D) g;
          AlphaComposite comp = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f);
          Composite oldComp = g2d.getComposite();
          g2d.setComposite(comp);
          int xloc = getWidth()/2 - imageW/2 - 2;
          int yloc = getHeight()/2 - imageH/2 - 2;

          g2d.drawImage(image, xloc, yloc, this);

          g2d.setComposite(oldComp);
        }
      }
    });

    JDropListener _dropEar;
    if(newAuctionList.isCompleted()) {
      _dropEar = new JDropListener(new TargetDrop());
    } else {
      _dropEar = new JDropListener(new TargetDrop(_dataModel.getName(), new ImageDropResolver() {
        public void handle(String imgUrl, Point location) {
          int rowPoint = _table.rowAtPoint(location);
          AuctionEntry whichAuction = (AuctionEntry)_table.getValueAt(rowPoint, -1);
          DeletedEntry.deleteThumbnails(whichAuction.getIdentifier());
          whichAuction.getAuction().setThumbnailURL(imgUrl);
          ((PlainMessageQueue)MQFactory.getConcrete("thumbnail")).enqueueObject(whichAuction.getAuction());
        }
      }));
    }
    _targets[0] = new DropTarget(_scroller.getViewport(), _dropEar);
    _targets[1] = new DropTarget(_table, _dropEar);

    _targets[0].setActive(true);
    _targets[1].setActive(true);

    _print = new JPrintable(_table);
    _export = new CSVExporter(_table);
    _table.setDefaultRenderer(String.class, _myRenderer);
    _table.setDefaultRenderer(Icon.class, _myRenderer);

    mPanel = new JPanel();
    mPanel.setLayout(new BorderLayout());
    mPanel.add(_scroller, BorderLayout.CENTER);
    addSumMonitor(_table);
    JPanel statusPanel = new TabStatusPanel(_dataModel.getName());
    mPanel.add(statusPanel, BorderLayout.NORTH);
  }

  public JPanel getPanel() {
    return mPanel;
  }

  private void addSumMonitor(JTable table) {
    table.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
      public void valueChanged(ListSelectionEvent event) {
        updateSum();
      }
    });
  }

  private void updateSum() {
    int[] rowList = _table.getSelectedRows();
    String total = sum(rowList);

    if(total == null) {
      MQFactory.getConcrete("Swing").enqueue("PRICE  "); // A blank space to clear the price
    } else {
      MQFactory.getConcrete("Swing").enqueue("PRICE " + rowList.length + " / " + total);
    }
  }

  /**
   * @brief Pick and return a value from the entry that best describes
   * how much COULD be spent on it by the buyer.
   *
   * For an item not bid on, it's the current bid price.  For an item
   * the user has bid on, it's their maximum bid.  For an item the
   * user has a snipe set for, it's the maximum of their snipe bid.
   * If the item is closed, it's just the current bid price.
   *
   * @param checkEntry - The AuctionEntry to operate on.
   *
   * @return - A currency value containing either the current bid, the
   * users high bid, or the users snipe bid.
   */
  private static Currency getBestBidValue(AuctionEntry checkEntry) {
    return checkEntry.bestValue();
  }

  public TableRowSorter<TableModel> getTableSorter() { return sorter; }
  public JTable getTable() { return _table; }

  private static Currency addUSD(Currency inCurr, AuctionEntry ae) {
    boolean newCurrency = (inCurr == null || inCurr.isNull());
    Currency currentUSPrice = ae.getCurrentUSPrice();
    try {
      if(ae.getShippingWithInsurance().isNull()) {
        if(newCurrency) {
          return currentUSPrice;
        }
        return inCurr.add(currentUSPrice);
      }

      if(newCurrency) {
        inCurr = currentUSPrice.add(Currency.convertToUSD(currentUSPrice, ae.getCurrentPrice(), ae.getShippingWithInsurance()));
      } else {
        inCurr = inCurr.add(currentUSPrice.add(Currency.convertToUSD(currentUSPrice, ae.getCurrentPrice(), ae.getShippingWithInsurance())));
      }
    } catch(Currency.CurrencyTypeException cte) {
      JConfig.log().handleException("This should have been cleaned up.", cte);
    }
    return inCurr;
  }

  private static Currency addNonUSD(Currency inCurr, AuctionEntry ae) {
    boolean newCurrency = inCurr == null || inCurr.isNull();
    try {
      if(ae.getShippingWithInsurance().isNull()) {
        if(newCurrency) {
          return getBestBidValue(ae);
        }
        return inCurr.add(getBestBidValue(ae));
      }

      if(newCurrency) {
        inCurr = getBestBidValue(ae).add(ae.getShippingWithInsurance());
      } else {
        inCurr = inCurr.add(getBestBidValue(ae).add(ae.getShippingWithInsurance()));
      }
    } catch(Currency.CurrencyTypeException cte) {
      JConfig.log().handleException("This should have been cleaned up.", cte);
    }

    return inCurr;
  }

  protected String sum(int[] rowList) {
    boolean approx = false, i18n = true;
    Currency accum = null;
    Currency withShipping = null;
    Currency withRealShipping = null;
    Currency realAccum = null;

    try {
      for (int aRowList : rowList) {
        AuctionEntry ae2;
        try {
          ae2 = (AuctionEntry) _table.getValueAt(aRowList, -1);
        } catch (ClassCastException cce) {
          ae2 = null;
        } catch (IndexOutOfBoundsException bounds) {
          ae2 = null;
          approx = true;
        }
        if (ae2 != null) {
          Currency currentUSPrice = ae2.getCurrentUSPrice();

          if (accum == null) {
            accum = currentUSPrice;
            realAccum = getBestBidValue(ae2);
            withShipping = addUSD(withShipping, ae2);
            withRealShipping = addNonUSD(withRealShipping, ae2);
          } else {
            if (!currentUSPrice.isNull() && !accum.isNull() && currentUSPrice.getCurrencyType() != Currency.NONE) {
              accum = accum.add(currentUSPrice);
              withShipping = addUSD(withShipping, ae2);

              //  If we're still trying to do the internationalization
              //  thing, then try to keep track of the 'real' total.
              if (i18n) {
                //noinspection NestedTryStatement
                try {
                  realAccum = realAccum.add(getBestBidValue(ae2));
                  withRealShipping = addNonUSD(withRealShipping, ae2);
                } catch (Currency.CurrencyTypeException cte) {
                  //  We can't handle multiple non-USD currency types, so
                  //  we stop trying to do the internationalization thing.
                  i18n = false;
                }
              }
            }
          }
          if (ae2.getCurrentPrice().getCurrencyType() != Currency.US_DOLLAR) approx = true;
        }
      }
    } catch(Currency.CurrencyTypeException e) {
      JConfig.log().handleException("Sum currency exception!", e);
      return null;
    } catch(ArrayIndexOutOfBoundsException ignored) {
      JConfig.log().logDebug("Selection of " + rowList.length + " items changed out from under 'sum'.");
      return null;
    } catch(NullPointerException npe) {
      JConfig.log().logDebug("sum got NPE - this is common during delete operations");
      return null;
    } catch(Exception e) {
      JConfig.log().handleException("Sum serious exception!", e);
      return null;
    }

    if(accum == null || accum.isNull()) {
      return null;
    }

    String sAndH = "s/h";
    if(!Locale.getDefault().equals(Locale.US)) sAndH = "p/p";

    //  If we managed to do the i18n thing through it all, and we have
    //  some real values, return it.
    if(i18n && realAccum != null) {
      StringBuffer result = new StringBuffer(realAccum.toString());
      if(withRealShipping != null && !realAccum.equals(withRealShipping)) {
        result.append(" (").append(withRealShipping).append(" with ").append(sAndH).append(')');
      }
      return result.toString();
    }

    if(approx) {
      String result;
      if(withShipping != null && !accum.equals(withShipping)) {
        result = "About " + accum.toString() + " (" + withShipping + " with " + sAndH + ')';
      } else {
        result = "About " + accum.toString();
      }
      return result;
    }

    if(withShipping != null && !accum.equals(withShipping)) {
      return accum.toString() + " (" + withShipping + " with " + sAndH + ')';
    }

    return accum.toString();
  }

  /**
   * @brief Sets the background color for this tab to the passed in color.
   *
   * @param bgColor - The color to set the background to.
   */
  public void setBackground(Color bgColor) {
    _scroller.getViewport().setBackground(bgColor);
    _table.setBackground(bgColor);
    _bgColor = bgColor;
  }

  /**
   * @brief Return the background color this was set to.
   *
   * @return - The color, if any, this tab was set to.
   */
  public Color getBackground() {
    return _bgColor;
  }

  /**
   * Delete an auction entry, using that auction entry to match against.
   * This also tells the auction entry to unregister itself!
   *
   * @param inEntry - The auction entry to delete.
   */
  public void delEntry(EntryInterface inEntry) {
    ((auctionTableModel)model).delete(inEntry);
  }

  /**
   * Add an AuctionEntry that has already been created, denying
   * duplicates, but allowing duplicates where both have useful
   * information that is not the same.
   *
   * @param aeNew - The new auction entry to add to the tables.
   */
  public void addEntry(EntryInterface aeNew) {
    if (aeNew != null && ((auctionTableModel)model).insert(aeNew) == -1) {
      JConfig.log().logMessage("JBidWatch: Bad auction entry, cannot add!");
    }
  }

  public boolean toggleField(String field) {
    boolean rval;
    int modelColumn = TableColumnController.getInstance().getColumnNumber(field);
    if(_table.convertColumnIndexToView(modelColumn) == -1) {
      TableColumn newColumn = new TableColumn(modelColumn, Constants.DEFAULT_COLUMN_WIDTH, _myRenderer, null);
      if(modelColumn == TableColumnController.THUMBNAIL) newColumn.setMinWidth(75);
      _table.addColumn(newColumn);
      rval = true;
    } else {
      _table.removeColumn(_table.getColumn(field));
      rval = false;
    }

    adjustRowHeight();

    return rval;
  }

  // hack and a half - but adding a row height attribute for columns seems like overkill
  public void adjustRowHeight() {
    Font def = myTableCellRenderer.getDefaultFont();
    Graphics g = _table.getGraphics();
    int defaultHeight;

    if(def == null || g == null) {
      defaultHeight = Constants.DEFAULT_ROW_HEIGHT;
    } else {
      FontMetrics metrics = g.getFontMetrics(def);
      defaultHeight = metrics.getMaxAscent() + metrics.getMaxDescent() + metrics.getLeading()+4;
    }

    int thumbnailIndex = _table.convertColumnIndexToView(TableColumnController.THUMBNAIL);
    if (thumbnailIndex != -1) {
      defaultHeight = Math.max(Constants.MICROTHUMBNAIL_ROW_HEIGHT, defaultHeight);
    }
    _table.setRowHeight(Math.max(defaultHeight, Constants.DEFAULT_ROW_HEIGHT));
    if(def != null) {
      _table.getTableHeader().setFont(def);
    }
  }

  public List<String> getColumns() {
    ArrayList<String> al = new ArrayList<String>();
    for(int i = 0; i<_table.getColumnCount(); i++) {
      al.add(_table.getColumnName(i));
    }

    return al;
  }

  public boolean export(String fname) {
    return _export.export(fname);
  }

  /**
   * @brief Print this table.
   *
   */
  public void print() {
    _print.doPrint();
  }

  /**
   * @brief Convert current column widths into display properties to
   * be saved for a future session.
   *
   * @param addToProps - The properties object to add the column widths to.
   * @param name - The category name to get the info from.
   */
  public void getColumnWidthsToProperties(Properties addToProps, String name) {
    for(int j = 0; j<_table.getColumnCount(); j++) {
      TableColumn ct;
      try {
        ct = _table.getColumn(_table.getColumnName(j));
      } catch(IllegalArgumentException iae) {
        JConfig.log().logMessage("Column can't be retrieved from the table: " + _table.getColumnName(j));
        ct = null;
      }
        //      ColumnProps cp = new ColumnProps(_dataModel.getColumnName(j), j, ct.getWidth());
      //noinspection StringContatenationInLoop
      if(ct != null) addToProps.setProperty(name + '.' + _table.getColumnName(j), Integer.toString(j) + '.' + Integer.toString(ct.getWidth()));
    }
  }

  public void getColumnWidthsToProperties(Properties addToProps) {
    getColumnWidthsToProperties(addToProps, _dataModel.getName());
  }

  public void sort() {
    sorter.sort();
  }

  public void redrawAll() {
    _table.tableChanged(new TableModelEvent(model));
  }
}
TOP

Related Classes of com.jbidwatcher.ui.AuctionsUIModel

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.