package com.jbidwatcher.ui.commands;
/*
* Copyright (c) 2000-2007, CyberFOX Software, Inc. All Rights Reserved.
*
* Developed by mrs (Morgan Schweers)
*/
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import javax.swing.*;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.*;
import java.util.List;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
import com.cyberfox.util.platform.Path;
import com.cyberfox.util.platform.Platform;
import com.github.rjeschke.txtmark.Processor;
import com.jbidwatcher.ui.*;
import com.jbidwatcher.util.config.*;
import com.jbidwatcher.ui.config.JConfigFrame;
import com.jbidwatcher.ui.util.*;
import com.jbidwatcher.util.db.Database;
import com.jbidwatcher.util.queue.MQFactory;
import com.jbidwatcher.util.queue.AuctionQObject;
import com.jbidwatcher.util.queue.MessageQueue;
import com.jbidwatcher.util.services.ActivityMonitor;
import com.jbidwatcher.util.xml.XMLElement;
import com.jbidwatcher.util.html.JHTMLOutput;
import com.jbidwatcher.util.html.JHTML;
import com.jbidwatcher.util.*;
import com.jbidwatcher.util.Currency;
import com.jbidwatcher.util.Constants;
import com.jbidwatcher.auction.*;
import com.jbidwatcher.auction.server.AuctionServerManager;
import com.jbidwatcher.auction.AuctionServerInterface;
import com.l2fprod.common.swing.JFontChooser;
public class UserActions implements MessageQueue.Listener {
private Map<String, AbstractCommand> commands = new HashMap<String,AbstractCommand>();
private static JTabManager mTabs = JTabManager.getInstance();
private static JConfigFrame jcf = null;
private static SearchFrame _searchFrame = null;
private OptionUI _oui = new OptionUI();
private static StringBuffer _colorHelp = null;
private static StringBuffer _aboutText = null;
private static StringBuffer _licenseText = null;
private static StringBuffer _needHelp = null;
private static StringBuffer _donate = null;
private boolean _in_deleting = false;
private ScriptManager mScriptFrame;
static Class[] sCommandClasses = {
FAQCommand.class,
};
public void addCommand(String cmdName, AbstractCommand commandObject) {
commands.put(cmdName, commandObject);
}
public UserActions() {
if (sCommandClasses == null) {
JConfig.log().logMessage("Interactive commands not loaded!");
} else {
for (Class klass : sCommandClasses) {
try {
AbstractCommand cmd = (AbstractCommand) klass.newInstance();
commands.put(cmd.getCommand(), cmd);
} catch (InstantiationException e) {
JConfig.log().handleException("Failed to create command for " + klass, e);
} catch (IllegalAccessException e) {
JConfig.log().handleException("Bad access exception when creating command for " + klass, e);
}
}
}
}
// Message Listener stuff
public static final String ADD_AUCTION="ADD ";
private static final String GET_SERVER_TIME="GETTIME";
private static final String SEARCH="SEARCH";
public static final String MY_EBAY="My eBay";
public void messageAction(Object deQ) {
if(deQ instanceof String) {
handleStringMessage(deQ);
}
if(deQ instanceof ActionTriple) {
ActionTriple action = (ActionTriple)deQ;
DoAction(action.getSource(), action.getCommand(), action.getAuction());
}
}
private void handleStringMessage(Object deQ) {
String commandStr = (String) deQ;
if(commandStr.startsWith(ADD_AUCTION)) {
String auctionSource = commandStr.substring(ADD_AUCTION.length());
cmdAddAuction(auctionSource);
} else if(commandStr.equals(MY_EBAY)) {
DoGetMyeBay();
} else if(commandStr.equals(GET_SERVER_TIME)) {
/**
* Resynchronize with the server's 'official' time, so as to make sure
* not to miss a snipe, for example. This does NOT happen inline with
* the call, it's queued to happen later because otherwise it could
* impact interactivity.
*/
if (JConfig.queryConfiguration("timesync.enabled", "true").equals("true")) {
MQFactory.getConcrete("auction_manager").enqueue("TIMECHECK");
}
} else if(commandStr.equals(SEARCH)) {
DoSearch();
} else if(commandStr.equals("About " + Constants.PROGRAM_NAME)) {
DoAbout();
} else if (commandStr.equals("Clear Donation")) {
UndoDonate();
} else if(commandStr.equals("Need Help")) {
DoNeedHelp();
} else if(commandStr.equals("Metrics")) {
doMetrics();
} else if(commandStr.equals("Configure")) {
DoConfigure();
} else if(commandStr.equals("Upload")) {
DoUploadAuctions();
} else {
AbstractCommand cmd = commands.get(commandStr);
if(cmd != null) cmd.execute();
else {
JConfig.log().logDebug("Received unrecognized 'user' message: " + commandStr);
}
}
}
private void cmdAddAuction(String auctionSource) {
if(auctionSource.regionMatches(true, 0, "<html>", 0, 6)) {
auctionSource = JHTML.getFirstContent(auctionSource);
}
auctionSource = auctionSource.trim();
String id = AuctionServerManager.getInstance().getServer().stripId(auctionSource);
if(EntryFactory.isInvalid(true, id)) {
AuctionEntry found = AuctionEntry.findByIdentifier(id);
if (found != null) {
JConfig.log().logMessage("Found auction " + id + " in category " + found.getCategory());
mTabs.showEntry(found);
}
} else {
EntryFactory.getInstance().conditionallyAddEntry(true, id, mTabs.getCurrentTableTitle());
}
}
private void DoHideShowToolbar() {
MQFactory.getConcrete("Swing").enqueue("TOOLBAR");
}
private void DoSearch() {
if(_searchFrame == null) {
_searchFrame = new SearchFrame();
} else {
_searchFrame.show();
}
}
private void DoScripting() {
if(JConfig.scriptingEnabled()) {
if (mScriptFrame == null) mScriptFrame = new ScriptManager();
MQFactory.getConcrete("scripting").enqueue("SHOW");
} else {
// Warn the user that scripting is not enabled.
}
}
private void DoChooseFont() {
JFontChooser jfc = new JFontChooser();
jfc.setSelectedFont(myTableCellRenderer.getDefaultFont());
Font chosen = jfc.showFontDialog(null, "Please choose the default font for the auction table");
if(chosen != null) {
myTableCellRenderer.setDefaultFont(chosen);
MQFactory.getConcrete("redraw").enqueue("#font");
}
}
private void DoShowLastError(Component src, AuctionEntry passedAE) {
AuctionEntry ae = passedAE;
int[] rowList = mTabs.getPossibleRows();
if(ae == null && rowList.length == 0 || rowList.length > 1) {
JOptionPane.showMessageDialog(src, "You must select a single auction to view the error page for.",
"Error view", JOptionPane.PLAIN_MESSAGE);
return;
}
if(ae == null) ae = (AuctionEntry) mTabs.getIndexedEntry(rowList[0]);
StringBuffer wholeStatus = ae.getErrorPage();
Dimension statusBox = new Dimension(756, 444);
_oui.showHTMLDisplay(new JHTMLOutput("Error Page", wholeStatus).getStringBuffer(), statusBox, "Error Page...");
}
private void DoDebugWin(AuctionEntry ae) {
MQFactory.getConcrete("won").enqueue(ae.getIdentifier());
}
/**
* @brief Display a list of the items to be deleted, and let the
* user choose whether to delete them or not.
*
* @param src - The component that the items came from.
* @param passedAE - The specific item, if one in particular was chosen.
*/
private void DoDelete(Component src, AuctionEntry passedAE) {
AuctionEntry ae = passedAE;
if(_in_deleting) return;
_in_deleting = true;
StringBuffer wholeDelete = new StringBuffer();
int[] rowList = mTabs.getPossibleRows();
if(ae == null && rowList.length == 0) {
_in_deleting = false;
JOptionPane.showMessageDialog(src, "You must select an auction to delete.", "Delete error", JOptionPane.PLAIN_MESSAGE);
return;
}
if(JConfig.queryConfiguration("prompt.hide_delete_confirm", "false").equals("true")) {
silentDelete(ae, rowList);
_in_deleting = false;
return;
}
ArrayList<AuctionEntry> deleteIds = new ArrayList<AuctionEntry>();
Dimension statusBox;
if(rowList.length != 0 && rowList.length != 1) {
wholeDelete.append("<table border=0 spacing=0 width=\"100%\">");
wholeDelete.append("<tr><td><u><b>Item Number</b></u></td><td><u><b>Title</b></u></td></tr>");
for(int i = 0; i<rowList.length; i++) {
AuctionEntry tempEntry = (AuctionEntry) mTabs.getIndexedEntry(rowList[i]);
deleteIds.add(tempEntry);
String color = "FFFFFF";
if( (i % 2) == 1) {
color = "C0C0C0";
}
wholeDelete.append("<tr><td bgcolor=#").
append(color).
append("><b>").
append(tempEntry.getIdentifier()).
append("</b></td><td bgcolor=#").
append(color).
append('>').
append(tempEntry.getTitle()).
append("</td></tr>");
}
wholeDelete.append("</table>");
// This is magic, but the idea is that a line is roughly 30
// pixels, the heading adds 30, but we don't want it to get
// larger than 756x372, so as to keep 800x600 users capable of
// reading it.
statusBox = new Dimension(756, Math.min(372, rowList.length * 27 + 90));
} else {
if(rowList.length == 1) {
ae = (AuctionEntry) mTabs.getIndexedEntry(rowList[0]);
}
if ((ae == null)) {
throw new IllegalArgumentException();
}
wholeDelete.append("<table border=0 spacing=0 width=\"100%\"><tr><td><b>").
append(ae.getIdentifier()).
append("</b></td><td>").
append(ae.getTitle()).
append("</td></tr></table>");
deleteIds.add(ae);
statusBox = new Dimension(756, 115);
}
List<String> buttons = new ArrayList<String>();
buttons.add("TEXT Are you sure you want to delete these auctions: ");
buttons.add("Yes");
buttons.add("TEXT ");
buttons.add("No, Cancel");
buttons.add("CHECK Don't prompt in the future.");
MyActionListener al = new MyActionListener() {
boolean mDontPrompt = false;
public void actionPerformed(ActionEvent listen_ae) {
String actionString = listen_ae.getActionCommand();
if(actionString.equals("Don't prompt in the future.")) {
JCheckBox jch = (JCheckBox) listen_ae.getSource();
mDontPrompt = jch.isSelected();
} else {
if(actionString.equals("Yes")) {
// Delete all those items...
for (EntryInterface entry : mEntries) {
entry.cancelSnipe(false);
MQFactory.getConcrete("delete").enqueue(entry.getIdentifier());
DeletedEntry.create(entry.getIdentifier());
}
// Just pass the list of ids down to a low-level 'delete multiple' method.
AuctionEntry.deleteAll(mEntries);
if(mDontPrompt) {
JConfig.setConfiguration("prompt.hide_delete_confirm", "true");
}
}
m_within.dispose();
m_within = null;
}
}
};
al.setEntries(deleteIds);
JFrame newFrame = _oui.showChoiceTextDisplay(new JHTMLOutput("Deleting", wholeDelete).getStringBuffer(), statusBox, "Deleting...", buttons, "Items to delete...", al);
al.setFrame(newFrame);
_in_deleting = false;
}
private void silentDelete(AuctionEntry ae, int[] rowList) {
final ArrayList<AuctionEntry> entries = new ArrayList<AuctionEntry>();
if(rowList.length != 0 && rowList.length != 1) {
for(int aRowList : rowList) {
AuctionEntry tempEntry = (AuctionEntry) mTabs.getIndexedEntry(aRowList);
entries.add(tempEntry);
}
} else {
if(rowList.length == 1) {
ae = (AuctionEntry) mTabs.getIndexedEntry(rowList[0]);
}
if(ae != null) entries.add(ae);
}
Thread deleteThread = new Thread(new Runnable() {
public void run() {
String logMsg = "Deleting " + entries.size() + " entries";
JConfig.log().logDebug(logMsg);
Thread.currentThread().setName(logMsg);
for (AuctionEntry deleteId : entries) {
AuctionsManager.getInstance().delEntry(deleteId);
}
}
});
deleteThread.start();
}
private void DoConfigure() {
if(jcf == null) {
jcf = new JConfigFrame();
} else {
jcf.show();
}
}
private static Pattern digitSearch = Pattern.compile("[0-9]+");
private void DoPasteFromClipboard() {
String auctionId = Clipboard.getClipboardString();
String original = auctionId;
if(auctionId.charAt(0) == '<') {
auctionId = JHTML.getFirstContent(auctionId);
if(auctionId.charAt(0) < '0' || auctionId.charAt(0) > '9') {
Matcher digits = digitSearch.matcher(auctionId);
if(digits.find()) auctionId = digits.group();
if(auctionId == null) {
JConfig.log().logDebug("Failed to paste auction id: " + original);
}
}
}
if(auctionId != null) {
MQFactory.getConcrete("user").enqueue(ADD_AUCTION + auctionId);
}
}
private String makeUsefulString(AuctionEntry ae) {
Currency currentPrice = ae.getCurrentPrice();
String result;
if(ae.isSeller()) {
result = ae.getHighBidder();
if(result == null) result = "";
} else {
result = ae.getSellerName();
}
result += " " + ae.getIdentifier() + " " + currentPrice + " (" + ae.getTitle() + ")\n";
return result;
}
/**
* @brief Copy data from the items, in a format similar to one I use
* for tracking things in a plain text file. Gets less use these days.
*
* @param src - The source component, for error messages.
* @param ae - The AuctionEntry, in case it's just a single unselected one.
*/
private void DoCopy(Component src, AuctionEntry ae) {
DoCopySomething(src, ae, DO_COPY_DATA, "No auctions selected to copy!", "");
}
private void DoAdd(Component src) {
String keyModifier = Platform.isMac() ? "Cmd" : "Ctrl";
String prompt = "<html><body>Enter the auction number to add <small>(Press " + keyModifier + "-V to paste)</small></body></html>";
String endResult = promptString(src, prompt, "Adding");
// They closed the window or cancelled.
if (endResult == null) return;
endResult = endResult.trim();
MQFactory.getConcrete("user").enqueue(ADD_AUCTION + endResult);
}
/*****************/
private Record getFirstResult(ResultSet rs) throws SQLException {
Record rval = new Record();
ResultSetMetaData rsm = rs.getMetaData();
if (rsm != null) {
if (rs.next()) {
for (int i = 1; i <= rsm.getColumnCount(); i++) {
rval.put(rs.getMetaData().getColumnName(i).toLowerCase(), rs.getString(i));
}
}
}
rs.close();
return rval;
}
private void DoSQL(Component src) {
String sql = promptString(src, "Enter the command to run", "Executing");
if (sql == null || sql.length() == 0) return;
sql = sql.trim();
try {
Database db = new Database(null);
Statement s = db.getStatement();
boolean resultType = db.executeCanonicalizedSQL(s, sql);
if(resultType) {
ResultSet rs = s.getResultSet();
Record r = getFirstResult(rs);
MQFactory.getConcrete("Swing").enqueue("ALERT " + r.dump());
} else {
MQFactory.getConcrete("Swing").enqueue("ALERT " + s.getUpdateCount());
}
} catch (ClassNotFoundException e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
} catch (SQLException e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
} catch (InstantiationException e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
} catch (IllegalAccessException e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
}
}
private String promptString(Component src, String prePrompt, String preTitle) {
return(_oui.promptString(src, prePrompt, preTitle, ""));
}
private String promptString(Component src, String prePrompt, String preTitle, String preFill) {
return(_oui.promptString(src, prePrompt, preTitle, preFill));
}
private void CancelSnipe(Component src, AuctionEntry ae) {
int[] rowList = mTabs.getPossibleRows();
int len = rowList.length;
if(ae == null && len == 0) {
JOptionPane.showMessageDialog(src, "You must select an auction to be able to cancel snipes.",
"Snipe-cancel error", JOptionPane.PLAIN_MESSAGE);
return;
}
if(len != 0) {
for (int aRowList : rowList) {
AuctionEntry tempEntry = (AuctionEntry) mTabs.getIndexedEntry(aRowList);
// Metrics
if(tempEntry.isSniped()) {
JConfig.getMetrics().trackEvent("snipe", "cancel");
}
tempEntry.cancelSnipe(false);
MQFactory.getConcrete("redraw").enqueue(tempEntry.getIdentifier());
}
} else {
// Metrics
if (ae.isSniped()) {
JConfig.getMetrics().trackEvent("snipe", "cancel");
}
ae.cancelSnipe(false);
MQFactory.getConcrete("redraw").enqueue(ae.getIdentifier());
}
}
private void DoShowTime(Component src, AuctionEntry ae) {
AuctionServerInterface as = AuctionServerManager.getInstance().getServer();
if(ae != null) as = ae.getServer();
String prompt = "<html><body><table>";
prompt += "<tr><td><b>Current time:</b></td><td>" + new Date() + "</td></tr>";
prompt += "<tr><td><b>Page load time:</td><td>" + as.getPageRequestTime() + "</td></tr>";
prompt += "<tr><td><b>eBay time delta:</td><td>" + as.getServerTimeDelta() + "</td></tr>";
prompt += "</table></body></html>";
JOptionPane jop = new JOptionPane(prompt, JOptionPane.INFORMATION_MESSAGE);
JDialog jdTime = jop.createDialog(src, "Auction Server Time Information");
jdTime.addWindowListener(new WindowAdapter() {
public void windowDeactivated(WindowEvent ev) {
ev.getWindow().toFront();
}
});
jdTime.setVisible(true);
}
private void DoInformation(Component src, EntryInterface ae) {
int[] rowList = mTabs.getPossibleRows();
int len = rowList.length;
if(ae == null && len == 0) {
JOptionPane.showMessageDialog(src, "Must select an auction to get information about.",
"Information error", JOptionPane.PLAIN_MESSAGE);
return;
}
showComplexInformation(rowList);
}
private int getInteger(String cfgValue, int defaultValue) {
int rval = defaultValue;
try {
String prop = JConfig.queryDisplayProperty(cfgValue);
if(prop != null) {
rval = Integer.parseInt(prop);
}
} catch(Exception ignored) {
// Ignore it, since rval is already set to the default.
}
return rval;
}
private void showComplexInformation(int[] rowList) {
StringBuffer prompt = new StringBuffer();
for (int aRowList : rowList) {
AuctionEntry stepAE = (AuctionEntry) mTabs.getIndexedEntry(aRowList);
prompt.append(stepAE.getPresenter().buildInfo(true)).append("<hr>");
}
int width = getInteger("info.width", 620);
int height = getInteger("info.height", 440);
Dimension statusBox = new Dimension(width, height);
ArrayList<String> buttons = new ArrayList<String>(2);
buttons.add("Continue");
MyActionListener al = new MyActionListener() {
public void actionPerformed(ActionEvent listen_ae) {
m_within.dispose();
m_within = null;
}
};
final JFrame newFrame = _oui.showChoiceTextDisplay(new JHTMLOutput("Information", prompt).getStringBuffer(), statusBox, "Information...", buttons, null, al);
newFrame.addComponentListener(new ComponentAdapter() {
public void componentResized(ComponentEvent e) {
JConfig.setDisplayConfiguration("info.width", Integer.toString(newFrame.getWidth()));
JConfig.setDisplayConfiguration("info.height", Integer.toString(newFrame.getHeight()));
}
});
al.setFrame(newFrame);
}
private boolean dangerousSnipeWarning(Component src) {
String warning =
"Two or more of your auctions complete within the snipe time of\n" +
"another. What will happen is that if the first of those is bid on,\n" +
"the second WILL be bid on as well. This is very unlikely to be what\n" +
"you want. It is strongly recommended that you cancel the multisnipe\n" +
"and check the end times of your auctions, only selecting auctions\n" +
"which end more than your snipe timer seconds apart.";
Object options[] = { "Cancel", "Proceed" };
int choiceResult = JOptionPane.showOptionDialog(src, warning, "Dangerous Multisnipe", JOptionPane.DEFAULT_OPTION, JOptionPane.WARNING_MESSAGE, null, options, options[0]);
return choiceResult == 0 || choiceResult == JOptionPane.CLOSED_OPTION;
}
/*
* Brute force check all snipe times vs. all other snipe times, first.
*/
private boolean checkIfDangerousMultiSnipe(Component src, int[] rowList, MultiSnipe ms) {
boolean foundDangerousSnipe=false;
for(int i = 0; i<rowList.length && !foundDangerousSnipe; i++) {
AuctionEntry ae1 = (AuctionEntry) mTabs.getIndexedEntry(rowList[i]);
if(ms != null) {
if(!ms.isSafeToAdd(ae1)) foundDangerousSnipe = true;
}
for(int j = i + 1; j<rowList.length && !foundDangerousSnipe; j++) {
AuctionEntry ae2 = (AuctionEntry) mTabs.getIndexedEntry(rowList[j]);
if(!MultiSnipe.isSafeMultiSnipe(ae1, ae2)) {
foundDangerousSnipe = true;
}
}
}
return foundDangerousSnipe && dangerousSnipeWarning(src);
}
private void DoMultiSnipe(Component src) {
if(JConfig.isPrerelease() || true) {
JOptionPane.showMessageDialog(src, "Creating new multi-snipes is disabled in this version, as the underlying high-bidder detection code isn't currently working.", "MultiSniping Disabled", JOptionPane.WARNING_MESSAGE);
return;
}
int[] rowList = mTabs.getPossibleRows();
Currency baseAllBid = Currency.NoValue();
// You must select multiple auctions to make this work.
if(rowList.length == 0) {
JOptionPane.showMessageDialog(src, "No auctions selected to set to MultiSnipe mode!", "Error setting multisnipe", JOptionPane.PLAIN_MESSAGE);
return;
}
// Go through the list of auctions to make sure they're all the
// same currency, and other similar requirements.
MultiSnipe aeMS = null;
int i;
boolean seenCurrencyWarning = false;
for(i=0; i<rowList.length; i++) {
AuctionEntry tempAE = (AuctionEntry) mTabs.getIndexedEntry(rowList[i]);
Currency curBid = tempAE.getCurBid();
if(tempAE.getServer().isDefaultUser()) {
JOptionPane.showMessageDialog(src, "One or more of your auctions to multisnipe is on a server that you have not\n" +
"entered your user account information for. Go to the the " + tempAE.getServer().getName() + " configuration tab,\n" +
"and fill it out.",
"No auction account error", JOptionPane.PLAIN_MESSAGE);
return;
}
if(tempAE.isComplete()) {
JOptionPane.showMessageDialog(src, "You cannot place a multi-snipe on a set of entries that include an ended auction",
"Snipe error", JOptionPane.PLAIN_MESSAGE);
return;
}
if(tempAE.isPrivate()) {
JOptionPane.showMessageDialog(src, "Multisnipes cannot include private auctions. Unfortunately,\n" +
"private auctions make it impossible under certain circumstances\n" +
"to know if a bid was ultimately the winner or not. The two\n" +
"potential answers are to either fail conservatively (think you\n" +
"won, and cancel later multisnipes), or fail liberally (think\n" +
"you lost, and allow later multisnipes). Neither is a good\n" +
"solution, so private auctions are barred from multisnipe groups.",
"Private auction/multisnipe error", JOptionPane.PLAIN_MESSAGE);
return;
}
Currency minBid;
try {
minBid = curBid.add(tempAE.getServer().getMinimumBidIncrement(curBid, tempAE.getNumBidders()));
} catch(Currency.CurrencyTypeException cte) {
// Don't worry about different currencies, here, it just
// means the auctions are in a different currency than the
// server can do 'minimum next bid' calculations with.
minBid = curBid;
}
try {
if(baseAllBid.isNull()) {
baseAllBid = curBid;
} else if(baseAllBid.less(minBid)) {
baseAllBid = curBid;
}
} catch(Currency.CurrencyTypeException cte) {
if(!seenCurrencyWarning) {
// THIS is a failure, because it means that some of the
// auctions selected have a different currency than each
// other. VERY bad.
int rval = JOptionPane.showConfirmDialog(src,
"You really should not include auctions in different\n" +
"currencies in a multi-snipe group. It's a really\n" +
" bad idea, because the snipe value may mean different\n" +
"values in each currency. Click cancel to go back and\n" +
"only choose auctions to multisnipe that are in one currency.\n" +
"If you click OK, you are responsible for handling the\n" +
"currency conversion factors by yourself.",
"Problem setting multisnipe", JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE);
if (rval == JOptionPane.CANCEL_OPTION || rval == JOptionPane.CLOSED_OPTION) return;
}
seenCurrencyWarning = true;
}
MultiSnipe ms = MultiSnipeManager.getInstance().getForAuctionIdentifier(tempAE.getIdentifier());
// IF one of the auctions we're adding is already multi-sniped,
// then we're adding this auction into that one's list.
if(ms != null) {
if(aeMS != null && aeMS.getIdentifier() != ms.getIdentifier()) {
// WHOA! Cannot add an auction to TWO multi-snipe groups
// at once!
JOptionPane.showMessageDialog(src,
"Cannot add auctions to two multi-snipe auctions\n" +
"at once. Cancel the snipes on one auction or set\n" +
"of auctions, and then retry the action.",
"Error setting multisnipe", JOptionPane.PLAIN_MESSAGE);
return;
}
if(aeMS == null) {
aeMS = ms;
}
}
}
if(checkIfDangerousMultiSnipe(src, rowList, aeMS)) return;
if(aeMS == null) {
// Build the snipe value prompt
String prompt = "<html><body><table>";
prompt += "<tr><td>Highest current bid:</td><td>" + baseAllBid + "</td></tr>";
prompt += "<tr><td>Number of auctions selected:</td><td>" + rowList.length + "</td></tr>";
prompt += "</table>";
prompt += "Approximate minimum bid across all selected auctions is " + baseAllBid + "<br>";
prompt += "<i>Do not enter any punctuation or currency symbols<br>other than the optional decimal point.</i><br>";
prompt += "How much do you wish to snipe?</body></html>";
SnipeDialog sd = new SnipeDialog();
sd.clear();
sd.setPrompt(prompt);
sd.pack();
Rectangle rec = OptionUI.findCenterBounds(sd.getPreferredSize());
sd.setLocation(rec.x, rec.y);
sd.setVisible(true);
if(sd.isCancelled() || sd.getAmount().length() == 0) {
JConfig.log().logDebug("Establishing multi-auction snipe canceled during snipe dialog");
return;
}
String snipeAmount = sd.getAmount();
boolean subtractShipping = sd.subtractShipping();
// Have the user select a text background color to identify this
// group of related snipes.
Color groupColor = JColorChooser.showDialog(src, "Select a background color for this multi-snipe group", null);
if(groupColor == null) {
JConfig.log().logDebug("Establishing multi-auction snipe canceled during color selection");
return;
}
// Construct a new multisnipe entry, if one wasn't found from the
// list they selected...
aeMS = new MultiSnipe(groupColor, Currency.getCurrency(baseAllBid.fullCurrencyName(), snipeAmount), subtractShipping);
aeMS.saveDB();
}
// Metrics
JConfig.getMetrics().trackEventValue("snipe", "multi", Integer.toString(rowList.length));
for(i=0; i<rowList.length; i++) {
AuctionEntry stepAE = (AuctionEntry)mTabs.getIndexedEntry(rowList[i]);
MultiSnipeManager.getInstance().addAuctionToMultisnipe(stepAE.getIdentifier(), aeMS);
MQFactory.getConcrete("redraw").enqueue(stepAE.getIdentifier());
}
}
private String genBidSnipeHTML(AuctionEntry ae, Currency minBid) {
String prompt = "<html><body><table>";
prompt += "<tr><td>Title:</td><td>" + ae.getTitle() + "</td></tr>";
prompt += "<tr><td>Current bid:</td><td>" + ae.getCurBid() + "</td></tr>";
if(ae.getShipping() != null && !ae.getShipping().isNull()) {
prompt += "<tr><td>Shipping:</td><td>" + ae.getShipping() + "</td></tr>";
}
String highBidder = ae.getHighBidder();
if(highBidder == null || highBidder.equals("null")) highBidder = "(n/a)";
prompt += "<tr><td>High bidder:</td><td>" + highBidder + "</td></tr>";
prompt += "<tr><td>Seller:</td><td>" + ae.getSellerName() + "</td></tr>";
prompt += "</table>";
if(minBid != null) {
prompt += "Minimum legal bid is " + minBid + "<br>";
} else {
prompt += "Cannot calculate minimum legal bid for this currency.<br>";
}
prompt += "<i>Do not enter any punctuation or currency symbols<br>other than the optional decimal point.</i><br>";
return(prompt);
}
private void DoSnipe(Component src, AuctionEntry passedAE) {
AuctionEntry ae = passedAE;
int[] rowList = mTabs.getPossibleRows();
if(rowList.length > 1) {
DoMultiSnipe(src);
return;
}
if(rowList.length == 1) {
ae = (AuctionEntry) mTabs.getIndexedEntry(rowList[0]);
}
if (ae == null) {
JOptionPane.showMessageDialog(src, "You have not chosen an auction to snipe on!",
"Snipe error", JOptionPane.PLAIN_MESSAGE);
return;
}
if(ae.getServer().isDefaultUser()) {
JOptionPane.showMessageDialog(src, "You cannot snipe on an auction without first entering your\n" +
"user account information on the " + ae.getServer().getName() + " configuration tab.",
"No auction account error", JOptionPane.PLAIN_MESSAGE);
return;
}
if(ae.isComplete()) {
JOptionPane.showMessageDialog(src, "You cannot place a snipe on an ended auction",
"Snipe error", JOptionPane.PLAIN_MESSAGE);
return;
}
Currency minimumNextBid;
try {
minimumNextBid = ae.getCurBid().add(ae.getServer().getMinimumBidIncrement(ae.getCurBid(), ae.getNumBidders()));
} catch(Currency.CurrencyTypeException cte) {
minimumNextBid = null;
}
String prompt = genBidSnipeHTML(ae, minimumNextBid);
prompt += "</body></html>";
String previous = "";
if(ae.isSniped()) previous = ae.getSnipeAmount().getValueString();
SnipeDialog sd = new SnipeDialog(previous);
sd.clear();
sd.setPrompt(prompt);
sd.pack();
Rectangle rec = OptionUI.findCenterBounds(sd.getPreferredSize());
sd.setLocation(rec.x, rec.y);
sd.setVisible(true);
if(sd.isCancelled() || sd.getAmount().length() == 0) return;
String snipeAmount = sd.getAmount();
try {
Currency bidAmount = Currency.getCurrency(ae.getCurBid().fullCurrencyName(), snipeAmount);
if(sd.subtractShipping()) {
Currency shipping = ae.getShippingWithInsurance();
if(shipping != null && !shipping.isNull()) {
bidAmount = bidAmount.subtract(shipping);
}
}
boolean wasSniped = ae.isSniped();
ae.prepareSnipe(bidAmount);
// Metrics
if (wasSniped) {
JConfig.getMetrics().trackEvent("snipe", "changed");
} else {
JConfig.getMetrics().trackEvent("snipe", "new");
}
} catch(NumberFormatException nfe) {
JOptionPane.showMessageDialog(src, "You have entered a bad price for your snipe.\n" +
snipeAmount + " is not a valid snipe.\n" +
"Punctuation (other than a decimal point) and currency symbols are not legal.",
"Bad snipe value", JOptionPane.PLAIN_MESSAGE);
return;
} catch (Currency.CurrencyTypeException e) {
JConfig.log().handleException("Couldn't subtract shipping from bid amount.", e);
return;
}
// if(JConfig.queryConfiguration("message.sniped", null) == null) { ... }
MQFactory.getConcrete("redraw").enqueue(ae.getIdentifier());
_oui.promptWithCheckbox(src, "Sniped for: " + ae.getSnipeAmount(), "Snipe Alert", "message.sniped", JOptionPane.PLAIN_MESSAGE, JOptionPane.OK_OPTION);
}
private void DoShipping(Component src, AuctionEntry ae) {
if(ae == null) {
JOptionPane.showMessageDialog(src, "You have not chosen an auction to set the shipping for!",
"Shipping-set error", JOptionPane.PLAIN_MESSAGE);
return;
}
String prompt = "<html><body>" + ae.getPresenter().buildInfo(false);
prompt += "<br><b>How much is shipping?</b></body></html>";
String endResult = promptString(src, prompt, "Shipping");
// They closed the window
if (endResult == null) {
return;
}
Currency shippingAmount;
try {
if(endResult != null) endResult = endResult.replace(',', '.');
shippingAmount = Currency.getCurrency(ae.getCurrentPrice().fullCurrencyName(), endResult);
} catch(NumberFormatException nfe) {
JOptionPane.showMessageDialog(src, "You have entered a bad shipping amount.\n" +
endResult + " is not a valid shipping cost.\n" +
"Punctuation (other than a decimal point) and currency symbols are not legal.\n" +
"The currency used is always the same as the auction.",
"Bad shipping value", JOptionPane.PLAIN_MESSAGE);
return;
}
if(shippingAmount != null) {
ae.setShipping(shippingAmount);
MQFactory.getConcrete("redraw").enqueue(ae.getIdentifier());
}
}
private boolean anyBiddingErrors(Component src, AuctionEntry ae) {
if (ae == null) {
JOptionPane.showMessageDialog(src, "You have not chosen an auction to bid on!",
"Bid error", JOptionPane.PLAIN_MESSAGE);
return true;
}
if(ae.getServer().isDefaultUser()) {
JOptionPane.showMessageDialog(src, "You cannot bid on an auction without first entering your\n" +
"user account information on the " + ae.getServer().getName() + " configuration tab.",
"No auction account error", JOptionPane.PLAIN_MESSAGE);
return true;
}
if(ae.isComplete()) {
JOptionPane.showMessageDialog(src, "You cannot place a bid on an ended auction",
"Bid error", JOptionPane.PLAIN_MESSAGE);
return true;
}
return false;
}
// TODO -- Add the ability to pick a quantity to buy, defaulting to 1.
private void DoBuy(Component src, AuctionEntry ae) {
if(anyBiddingErrors(src, ae)) return;
int endResult = _oui.promptWithCheckbox(src, "This will buy the item outright at the price of " + ae.getBuyNow() + ".\nIs this what you want?",
"Buy Item", "prompt.bin_confirm");
if(endResult != JOptionPane.CANCEL_OPTION && endResult != JOptionPane.CLOSED_OPTION) {
MQFactory.getConcrete(ae.getServer().getFriendlyName()).enqueueBean(new AuctionQObject(AuctionQObject.BID, new AuctionBuy(ae, Currency.NoValue(), 1), "none"));
}
}
private void DoBid(Component src, AuctionEntry ae) {
if(anyBiddingErrors(src, ae)) return;
Currency minimumNextBid;
try {
minimumNextBid = ae.getCurBid().add(ae.getServer().getMinimumBidIncrement(ae.getCurBid(), ae.getNumBidders()));
} catch(Currency.CurrencyTypeException cte) {
minimumNextBid = null;
}
String prompt = genBidSnipeHTML(ae, minimumNextBid);
prompt += "How much do you wish to bid?</body></html>";
String endResult;
if(minimumNextBid != null) {
endResult = promptString(src, prompt, "Bidding", Float.toString((float) minimumNextBid.getValue()));
} else {
endResult = promptString(src, prompt, "Bidding");
}
// They closed the window
if (endResult == null) {
return;
}
Currency bidAmount;
try {
if(endResult != null) endResult = endResult.replace(',','.');
bidAmount = Currency.getCurrency(ae.getCurBid().fullCurrencyName(), endResult);
} catch(NumberFormatException nfe) {
JOptionPane.showMessageDialog(src, "You have entered a bad price for your bid.\n" +
endResult + " is not a valid bid.\n" +
"Punctuation (other than a decimal point) and currency symbols are not legal.",
"Bad bid value", JOptionPane.PLAIN_MESSAGE);
return;
}
MQFactory.getConcrete(ae.getServer().getFriendlyName()).enqueueBean(new AuctionQObject(AuctionQObject.BID, new AuctionBid(ae, bidAmount, 1), "none"));
}
private void DoShowInBrowser(Component src, AuctionEntry inAuction) {
AuctionEntry ae = inAuction;
int[] rowList = mTabs.getPossibleRows();
// TODO -- It would be nice to be able to show multiple items.
if(rowList.length != 0) {
ae = (AuctionEntry) mTabs.getIndexedEntry(rowList[0]);
} else {
if(ae == null) {
JOptionPane.showMessageDialog(src, "Cannot launch browser from menu, you must select an auction.", "Menu Error", JOptionPane.PLAIN_MESSAGE);
return;
}
}
showInBrowser(ae);
}
/**
* @brief Show an auction entry in the browser.
*
* @param inEntry - The auction entry to load up and display in the users browser.
*/
public void showInBrowser(AuctionEntry inEntry) {
final String entryId = inEntry.getIdentifier();
String doLocalServer = JConfig.queryConfiguration("server.enabled", "false");
String browseTo;
if (doLocalServer.equals("false")) {
browseTo = inEntry.getBrowseableURL();
} else {
String localServerPort = JConfig.queryConfiguration("server.port", Constants.DEFAULT_SERVER_PORT_STRING);
if (inEntry.isInvalid()) {
browseTo = "http://localhost:" + localServerPort + "/cached_" + entryId;
} else {
browseTo = "http://localhost:" + localServerPort + '/' + entryId;
}
}
JConfig.getMetrics().trackEvent("browse", "auction");
MQFactory.getConcrete("browse").enqueue(browseTo);
}
private void DeleteComment(AuctionEntry ae) {
if(ae == null) {
JConfig.log().logMessage("Auction selected to delete comment from is null, unexpected error!");
return;
}
ae.setComment("");
MQFactory.getConcrete("redraw").enqueue(ae.getIdentifier());
}
private void DoComment(Component src, AuctionEntry inAuction) {
if(inAuction == null) {
JConfig.log().logMessage("Auction selected to comment on is null, unexpected error!");
return;
}
String curComment = inAuction.getComment();
if(curComment == null) curComment = "";
String endResult = promptString(src, "Enter a comment for: " + inAuction.getTitle(), "Commenting", curComment);
if(endResult == null) return;
inAuction.setComment(endResult);
MQFactory.getConcrete("redraw").enqueue(inAuction.getIdentifier());
}
private void ShowComment(Component src, AuctionEntry inAuction) {
if(inAuction == null) {
JConfig.log().logMessage("Can't show comments from menu items yet.");
return;
}
JOptionPane.showMessageDialog(src, inAuction.getComment(), "Comment", JOptionPane.PLAIN_MESSAGE);
}
private void DoUpdateAll() {
AuctionEntry.forceUpdateActive();
EntryCorral.getInstance().clear();
}
private void DoStopUpdating(Component src) {
int endResult = _oui.promptWithCheckbox(src, "This will terminate all searches, as well as\nall updates that are currently pending.\n\nStop all searches?", "Stop updating/searching", "prompt.search_stop");
if(endResult != JOptionPane.CANCEL_OPTION &&
endResult != JOptionPane.CLOSED_OPTION) {
AuctionServerManager.getInstance().cancelSearches();
// Clear all dropped or programmatically added auctions.
MQFactory.getConcrete("drop").clear();
PauseManager.getInstance().pause();
}
}
private void DoUpdate(Component src, AuctionEntry inAuction) {
int[] rowList = mTabs.getPossibleRows();
if(rowList.length != 0) {
for (int aRowList : rowList) {
AuctionEntry tempEntry = (AuctionEntry) mTabs.getIndexedEntry(aRowList);
tempEntry.setNeedsUpdate();
}
} else {
if(inAuction == null) {
JOptionPane.showMessageDialog(src, "No auction selected to update.", "No auction to update", JOptionPane.INFORMATION_MESSAGE);
} else {
inAuction.setNeedsUpdate();
}
}
}
private void DoSetNotEnded(AuctionEntry whichAuction) {
int[] rowList = mTabs.getPossibleRows();
if (rowList.length != 0) {
for (int aRowList : rowList) {
AuctionEntry tempEntry = (AuctionEntry) mTabs.getIndexedEntry(aRowList);
tempEntry.setComplete(false);
tempEntry.setNeedsUpdate();
}
} else {
whichAuction.setComplete(false);
whichAuction.setNeedsUpdate();
}
}
private void DoResetServerTime() {
// Always resets the server time based on the 'default' server.
MQFactory.getConcrete("user").enqueue(GET_SERVER_TIME);
}
private final static StringBuffer badAbout = new StringBuffer("Error loading About text! (D'oh!) Email <a href=\"mailto:cyberfox@jbidwatcher.com\">me</a>!");
private final static StringBuffer badLicense = new StringBuffer("Error loading License text! Please visit <a href=\"http://www.jbidwatcher.com/by-nc-sa-amended.shtml\">http://http://www.jbidwatcher.com/by-nc-sa-amended.shtml</a>!");
static private JFrame aboutFrame = null;
private void DoAbout() {
if(aboutFrame == null) {
Dimension aboutBoxSize = new Dimension(495, 245);
if(_aboutText == null) {
_aboutText = JBHelp.loadHelp("/help/about.jbh", "About " + Constants.PROGRAM_NAME + "...");
}
aboutFrame = _oui.showHTMLDisplay(_aboutText != null ? _aboutText : badAbout, aboutBoxSize, "About " + Constants.PROGRAM_NAME);
} else {
aboutFrame.setVisible(true);
}
}
static private JFrame licenseFrame = null;
private void DoLicense() {
if(licenseFrame == null) {
Dimension licenseBoxSize = new Dimension(600, 245);
if(_licenseText == null) {
_licenseText = JBHelp.loadHelp("/help/COPYING.html", "License for " + Constants.PROGRAM_NAME + "...");
}
licenseFrame = _oui.showHTMLDisplay(_licenseText != null ? _licenseText : badLicense, licenseBoxSize, "License for " + Constants.PROGRAM_NAME);
} else {
licenseFrame.setVisible(true);
}
}
static private JFrame needHelpFrame = null;
private void DoNeedHelp() {
if(needHelpFrame == null) {
Dimension boxSize = new Dimension(507, 300);
if(_needHelp == null) {
_needHelp = JBHelp.loadHelp("/help/need_help.jbh", "/help/need_help.md", "A Message from the JBidwatcher Author");
}
if(_needHelp != null) {
needHelpFrame = _oui.showHTMLDisplay(_needHelp, boxSize, "A Message from Morgan Schweers");
}
} else {
needHelpFrame.setVisible(true);
}
}
private void doMetrics() {
Dimension boxSize = new Dimension(400, 220);
String text = "**I would very much appreciate it if you would allow JBidwatcher to collect _anonymous_ usage statistics to " +
"help me know what to improve.**\n\nBy clicking 'Yes' you agree that JBidwatcher may collect and report usage data for " +
"support purposes, and to help me improve the quality of JBidwatcher and related applications and services.\n\n" +
"<small>You can learn more about what is collected [here](http://www.jbidwatcher.com/help/metrics). Thank you!";
StringBuffer sb = new StringBuffer(Processor.process(text));
_oui.showTextDisplayWithButtons(sb, boxSize, "Please help me make JBidwatcher better", "metrics.optin", "No", "false", "Yes", "true");
}
static private JFrame donateFrame = null;
private void DoDonate() {
if (donateFrame == null) {
Dimension boxSize = new Dimension(495, 245);
if (_donate == null) {
_donate = JBHelp.loadHelp("/help/donate.jbh", "A Message from the JBidwatcher Author");
}
if (_donate != null) {
donateFrame = _oui.showHTMLDisplay(_donate, boxSize, "A Message from Morgan Schweers");
}
} else {
donateFrame.setVisible(true);
}
}
private void UndoDonate() {
boolean alreadyClicked = JConfig.queryConfiguration("donation.clicked", "false").equals("true");
if(donateFrame != null) donateFrame.setVisible(false);
JConfig.setConfiguration("donation.clicked", "true");
JBidToolBar.getInstance().hideDonation();
if(!alreadyClicked) JOptionPane.showMessageDialog(null, "The donation button has been removed; you can still access the donation screen from Help | Donate.", "Removed donation button", JOptionPane.INFORMATION_MESSAGE);
}
private static final StringBuffer EMPTY_LOG = new StringBuffer("The log is empty.");
private void showLog(final LogProvider provider, String frameName) {
Dimension logBoxSize = new Dimension(625, 500);
StringBuffer logText = provider.getLog();
if(logText == null || logText.length() == 0) {
logText = EMPTY_LOG;
}
final JBidFrame logFrame = _oui.getTextDisplay(logText, logBoxSize, Constants.PROGRAM_NAME + " " + frameName, false);
JButton logButton = new JButton("Submit Log");
logButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
DoSubmitLogFile();
}
});
JButton refreshButton = new JButton("Refresh");
refreshButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
logFrame.getEditor().setText(provider.getLog().toString());
}
});
JPanel buttonBox = new JPanel(new BorderLayout());
buttonBox.add(logButton, BorderLayout.EAST);
buttonBox.add(refreshButton, BorderLayout.WEST);
logFrame.add(buttonBox, BorderLayout.SOUTH);
logFrame.pack();
logFrame.setSize(logBoxSize.width, logBoxSize.height);
logFrame.setVisible(true);
logFrame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
}
private void DoViewLog() {
showLog(ErrorMonitor.getInstance(), "Log");
}
private void DoViewActivity() {
showLog(ActivityMonitor.getInstance(), "Activity Log");
}
private void DoSerialize() {
System.out.println(AuctionServerManager.getInstance().toXML());
}
private void DoUploadAuctions() {
String fname = AuctionsManager.getInstance().saveAuctions();
MQFactory.getConcrete("my").enqueue("SYNC " + fname);
}
private void DoLoad(String fname) {
String canonicalFName = fname;
if(canonicalFName == null) {
canonicalFName = JConfig.queryConfiguration("savefile", "auctions.xml");
String oldFname = canonicalFName;
canonicalFName = Path.getCanonicalFile(canonicalFName, "jbidwatcher", true);
if(!canonicalFName.equals(oldFname)) {
JConfig.setConfiguration("savefile", canonicalFName);
}
}
try {
XMLElement xmlFile = new XMLElement(true);
InputStreamReader isr = new InputStreamReader(new FileInputStream(canonicalFName));
xmlFile.parseFromReader(isr);
AuctionServerManager.getInstance().fromXML(xmlFile);
} catch(IOException e) {
JConfig.log().handleException("Error loading XML file with auctions: " + canonicalFName, e);
}
}
private void DoCloseDown() {
MQFactory.getConcrete("Swing").enqueue("QUIT");
}
private void DoSave(Component src) {
String didSave = AuctionsManager.getInstance().saveAuctions();
System.gc();
if(didSave != null) {
// JOptionPane.showMessageDialog(src, "Auctions Saved!", "Save Complete", JOptionPane.INFORMATION_MESSAGE);
_oui.promptWithCheckbox(src, "Auctions saved!", "Save Complete", "prompt.savecomplete", JOptionPane.PLAIN_MESSAGE, JOptionPane.OK_OPTION);
} else {
JOptionPane.showMessageDialog(src, "An error occurred in saving the auctions!", "Save Failed", JOptionPane.INFORMATION_MESSAGE);
}
}
/**
* @brief Given an action value, and an auction entry, return the
* right string associated with that action.
*
* @param action - The action we're looking to do.
* @param ae - The entry to retrieve the data from.
*
* @return - A string containing the relevant data from ae.
*/
private String getActionValue(int action, AuctionEntry ae) {
switch(action) {
case DO_COPY_URL:
return ae.getBrowseableURL();
case DO_COPY_ID:
return ae.getIdentifier();
case DO_COPY_DATA:
return makeUsefulString(ae);
default:// Don't do anything...
}
return "";
}
private static final int DO_COPY_URL = 0;
private static final int DO_COPY_ID = 1;
private static final int DO_COPY_DATA = 2;
/**
* @brief Copy some data into the clipboard, based on the action
* parameter, seperated by the seperator parameter.
*
* @param src - The source component, for error messages.
* @param passedAE - The AuctionEntry, in case it's just a single unselected one.
* @param action - The action to perform (defined just before this function).
* @param fail_msg - The message to display in a dialog on failure.
* @param seperator - The string to seperate selected results with.
*/
private void DoCopySomething(Component src, AuctionEntry passedAE, int action, String fail_msg, String seperator) {
AuctionEntry ae = passedAE;
int[] rowList = mTabs.getPossibleRows();
if(ae == null && rowList.length == 0) {
JOptionPane.showMessageDialog(src, fail_msg, "Error copying", JOptionPane.PLAIN_MESSAGE);
return;
}
if(rowList.length != 0 && rowList.length != 1) {
StringBuffer sb = new StringBuffer();
for(int i = 0; i<rowList.length; i++) {
AuctionEntry tempEntry = (AuctionEntry) mTabs.getIndexedEntry(rowList[i]);
if(i != 0) sb.append(seperator);
sb.append(getActionValue(action, tempEntry));
}
Clipboard.setClipboardString(sb.toString());
} else {
// Shortcut to not have to create and destroy a Stringbuffer
if(rowList.length == 1) ae = (AuctionEntry) mTabs.getIndexedEntry(rowList[0]);
Clipboard.setClipboardString(getActionValue(action, ae));
}
}
/**
* @brief Copy the URLs for all the selected items into the clipboard.
*
* @param src - The component we're on.
* @param ae - The auction entry, if just one was selected.
*/
private void DoCopyURL(Component src, AuctionEntry ae) {
DoCopySomething(src, ae, DO_COPY_URL, "No auctions selected to copy URLs of!", "\n");
}
/**
* @brief Copy the IDs for all the selected items into the clipboard.
*
* @param src - The component we're on.
* @param ae - The auction entry, if just one was selected.
*/
private void DoCopyID(Component src, AuctionEntry ae) {
DoCopySomething(src, ae, DO_COPY_ID, "No auctions selected to copy IDs of!", ", ");
}
private void DoHelp(Component src) {
// Not really implemented yet... -- BUGBUG (need to write help!)
JOptionPane.showMessageDialog(src,
"I'm very sorry, but help has not been implemented yet.\n" +
"If you'd like to assist in getting help up, you could\n" +
"write me an email at cyberfox@jbidwatcher.com\n" +
"describing how you use a particular part of JBidwatcher,\n" +
"and I'll try to collect those into contextual help options.",
"Sorry, no help!", JOptionPane.INFORMATION_MESSAGE);
}
private final static StringBuffer badColors = new StringBuffer("Error loading Color help text! (D'oh!) Email <a href=\"mailto:cyberfox%40jbidwatcher.com\">me</a>!");
private static JFrame helpFrame = null;
private void DoHelpColors() {
if(helpFrame == null) {
Dimension chSize = new Dimension(495, 245);
if(_colorHelp == null) {
_colorHelp = JBHelp.loadHelp("/help/colors.jbh", "Help on Colors");
}
helpFrame = _oui.showHTMLDisplay(_colorHelp != null ? _colorHelp : badColors, chSize, "Help on color use in JBidwatcher");
} else {
helpFrame.setVisible(true);
}
}
protected void DoCheckUpdates() {
// Force the 'last known version' to be the current, so that users can check
// later, and have it still find the new version.
JConfig.setConfiguration("updates.last_version", Constants.PROGRAM_VERS);
MQFactory.getConcrete("update").enqueue("INTERACTIVE");
}
protected void DoSetSelectionColor(Component src) {
String oldColor = JConfig.queryConfiguration("selection.color");
if(oldColor == null) oldColor = "C6A646";
Color selectionColor = JColorChooser.showDialog(src, "Choose a selection-background color", MultiSnipe.reverseColor(oldColor));
if(selectionColor == null) return;
JConfig.setConfiguration("selection.color", MultiSnipe.makeRGB(selectionColor));
}
protected void DoSetBackgroundColor(Component src) {
Color bgColor = JColorChooser.showDialog(src, "Select a background color for your auction tables", null);
if(bgColor == null) {
return;
}
MQFactory.getConcrete("redraw").enqueue("#" + Integer.toHexString(bgColor.getRGB() & 0x00ffffff));
myTableCellRenderer.resetBehavior();
JConfig.setConfiguration("background", MultiSnipe.makeRGB(bgColor));
}
private void DoClearDeleted(Component src) {
int clearedCount = AuctionsManager.getInstance().clearDeleted();
_oui.promptWithCheckbox(src, "Cleared " + clearedCount + " deleted entries.", "Clear Complete", "prompt.clear_complete", JOptionPane.PLAIN_MESSAGE, JOptionPane.OK_OPTION);
}
protected void DoAction(Object src, String actionString, Object whichAuction) {
DoAction(src, actionString, (AuctionEntry)whichAuction);
}
protected void DoAction(Object src, String actionString, AuctionEntry whichAuction) {
Component c_src;
if(src instanceof Component) {
c_src = (Component)src;
} else {
c_src = null;
}
AbstractCommand cmd = commands.get(actionString);
if(cmd != null) {
cmd.setSource(c_src);
cmd.setAuction(whichAuction);
cmd.setSelected(mTabs.getPossibleRows());
cmd.execute();
} else if(actionString.equals("Save")) DoSave(c_src);
else if (actionString.equals("Clear Deleted")) DoClearDeleted(c_src);
else if (actionString.equals("Add") || actionString.equals("Add New")) DoAdd(c_src);
else if (actionString.equals("StopUpdating")) DoStopUpdating(c_src);
else if (actionString.equals("Help")) DoHelp(c_src);
else if (actionString.equals("Multiple Snipe")) DoMultiSnipe(c_src);
else if (actionString.equals("Set Background Color")) DoSetBackgroundColor(c_src);
else if(actionString.equals("Load")) DoLoad(null);
else if(actionString.equals("Configure")) DoConfigure();
else if(actionString.equals("Check Updates")) DoCheckUpdates();
else if(actionString.equals("Check For Updates")) DoCheckUpdates();
else if(actionString.equals("Exit")) DoCloseDown();
else if(actionString.equals("Explain Colors And Icons")) DoHelpColors();
else if(actionString.equals("SQL")) DoSQL(c_src);
else if(actionString.equals("Serialize")) DoSerialize();
else if(actionString.equals("Upload")) DoUploadAuctions();
else if(actionString.equals("Paste")) DoPasteFromClipboard();
else if(actionString.equals("UpdateAll")) DoUpdateAll();
else if(actionString.equals("Resync")) DoResetServerTime();
else if (actionString.equals("About " + Constants.PROGRAM_NAME)) DoAbout();
else if (actionString.equals("About")) DoAbout();
else if (actionString.equals("Need Help")) DoNeedHelp();
else if (actionString.equals("Donate")) DoDonate();
else if (actionString.equals("Clear Donation")) UndoDonate();
else if (actionString.equals("License")) DoLicense();
else if (actionString.equals("Toolbar")) DoHideShowToolbar();
else if (actionString.equals("Search")) DoSearch();
else if (actionString.equals("Scripting")) DoScripting();
else if (actionString.equals("View Log")) DoViewLog();
else if (actionString.equals("View Activity")) DoViewActivity();
else if (actionString.equals("Submit Log File")) DoSubmitLogFile();
else if (actionString.equals("Restart")) DoRestart();
else if (actionString.equals("Font")) DoChooseFont();
else if (actionString.equals("Metrics")) doMetrics();
else if (actionString.equals("Selection Color")) DoSetSelectionColor(c_src);
else if (actionString.equals("CopyURL")) DoCopyURL(c_src, whichAuction);
else if (actionString.equals("CopyID")) DoCopyID(c_src, whichAuction);
else if (actionString.equals("Delete")) DoDelete(c_src, whichAuction);
else if(actionString.equals("Information")) DoInformation(c_src, whichAuction);
else if(actionString.equals("Update")) DoUpdate(c_src, whichAuction);
else if(actionString.equals("Browse")) DoShowInBrowser(c_src, whichAuction);
// else if(actionString.equals("Status")) DoShowStatus(c_src, whichAuction);
else if(actionString.equals("Show Time Info")) DoShowTime(c_src, whichAuction);
else if(actionString.equals("ShowError")) DoShowLastError(c_src, whichAuction);
else if(actionString.equals("Report")) DoReportProblem(c_src, whichAuction);
else if(actionString.equals("Bid")) DoBid(c_src, whichAuction);
else if(actionString.equals("Buy")) DoBuy(c_src, whichAuction);
else if(actionString.equals("Shipping")) DoShipping(c_src, whichAuction);
else if (actionString.equals("Cancel Snipe")) CancelSnipe(c_src, whichAuction);
else if (actionString.equals("Add Comment")) DoComment(c_src, whichAuction);
else if (actionString.equals("View Comment")) ShowComment(c_src, whichAuction);
else if (actionString.equals("Copy")) DoCopy(c_src, whichAuction);
else if (actionString.equals("Snipe")) DoSnipe(c_src, whichAuction);
else if(actionString.equals("NotEnded")) DoSetNotEnded(whichAuction);
else if(actionString.equals("Remove Comment")) DeleteComment(whichAuction);
else if (actionString.equals("Mark as Won")) DoDebugWin(whichAuction);
else if(actionString.equals("Dump")) JConfig.log().logDebug("Dump requested.");
else if(actionString.equals("Forum")) MQFactory.getConcrete("browse").enqueue("http://forum.jbidwatcher.com");
else if(actionString.equals("My JBidwatcher")) MQFactory.getConcrete("browse").enqueue("http://my.jbidwatcher.com");
else if(actionString.equals("Report Bug")) MQFactory.getConcrete("browse").enqueue("http://jbidwatcher.lighthouseapp.com/projects/8037-jbidwatcher/tickets");
else JConfig.log().logDebug('[' + actionString + ']');
}
private void DoGetMyeBay() {
AuctionQObject loadMyeBay = new AuctionQObject(AuctionQObject.LOAD_MYITEMS, null, "current");
MQFactory.getConcrete(AuctionServerManager.getInstance().getServer().getFriendlyName()).enqueueBean(loadMyeBay);
}
private SubmitLogDialog mLogSubmitDialog;
private void DoSubmitLogFile() {
if(mLogSubmitDialog == null) {
mLogSubmitDialog = new SubmitLogDialog();
}
SwingUtilities.invokeLater(new Runnable() {
public void run() {
mLogSubmitDialog.showDialog();
}
});
}
private void DoRestart() {
String launcher = System.getenv("JBIDWATCHER_LAUNCHER");
if(JConfig.debugging && launcher != null) {
// TODO -- Make this more graceful
System.exit(100);
} else {
JOptionPane.showMessageDialog(null, "Restart does not work without being run from the JBidLauncher script.", "Restart Failed", JOptionPane.PLAIN_MESSAGE);
}
}
private void DoReportProblem(Component src, AuctionEntry auction) {
String endResult = promptString(src, "What's wrong with: " + auction.getTitle(), "Reporting a problem", "");
if(endResult == null) endResult = "";
auction.setLastStatus(endResult);
MQFactory.getConcrete("report").enqueue(auction.getIdentifier());
}
}