package com.jbidwatcher.ui; /* * Copyright (c) 2000-2007, CyberFOX Software, Inc. All Rights Reserved. * * Developed by mrs (Morgan Schweers) */ import com.google.inject.Inject; import com.google.inject.Singleton; import com.jbidwatcher.ui.table.auctionTableModel; import com.jbidwatcher.util.config.JConfig; import com.jbidwatcher.util.queue.MessageQueue; import com.jbidwatcher.util.queue.MQFactory; import com.jbidwatcher.util.StringTools; import com.jbidwatcher.auction.AuctionEntry; import com.jbidwatcher.auction.Category; import com.jbidwatcher.auction.EntryCorral; import javax.swing.event.TableModelEvent; import java.util.*; import java.awt.Color; @Singleton public class FilterManager implements MessageQueue.Listener, FilterInterface { private final ListManager mList; private final JTabManager tabs; private final EntryCorral corral; @Inject private AuctionListHolderFactory alhFactory; private Map<String, AuctionListHolder> mIdentifierToList; private AuctionListHolder mMainTab = null; private AuctionListHolder mDefaultCompleteTab = null; private AuctionListHolder mDefaultSellingTab = null; @Inject protected FilterManager(ListManager listManager, JTabManager tabManager, final EntryCorral entryCorral) { mList = listManager; tabs = tabManager; corral = entryCorral; mIdentifierToList = new HashMap<String, AuctionListHolder>(); MQFactory.getConcrete("redraw").registerListener(this); MQFactory.getConcrete("delete").registerListener(new MessageQueue.Listener() { public void messageAction(Object deQ) { AuctionEntry ae = corral.takeForRead(deQ.toString()); // Lock the item deleteAuction(ae); ae = (AuctionEntry) corral.takeForWrite(deQ.toString()); // Lock the item corral.erase(ae.getIdentifier()); // Remove and unlock it } }); tabs.setFilterManager(this); } public void loadFilters() { mMainTab = mList.add(alhFactory.create("current", false, false)); mDefaultCompleteTab = mList.add(alhFactory.create("complete", true, false)); mDefaultSellingTab = mList.add(alhFactory.create("selling", false, false)); String tabName; int i = 0; do { tabName = JConfig.queryDisplayProperty("tabs.name." + i++); if (tabName != null && mList.findCategory(tabName) == null) { mList.add(alhFactory.create(tabName, false, true)); } } while (i < 3 || tabName != null); // Do at least the first three, and then keep going until we miss an index. } /** * Creates a new tab by copying the background color from the main tab, * looking for an existing set of column settings, and copying them as * well from the main tab if they don't already exist. * * @param newTab - The name of the new tab to create. * * @return - An AuctionListHolder that encapsulates the UI and List * for the new tab. */ AuctionListHolder addTab(String newTab) { Color mainBackground = mMainTab.getUI().getBackground(); Properties dispProps = JConfig.multiMatchDisplay(newTab + "."); if(dispProps.isEmpty()) { mMainTab.getUI().getColumnWidthsToProperties(dispProps, newTab); JConfig.addAllToDisplay(dispProps); } AuctionListHolder newList = alhFactory.create(newTab, false, true); newList.setBackground(mainBackground); mList.add(newList); Category.findOrCreateByName(newTab); return newList; } public void messageAction(Object deQ) { String cmd = deQ.toString(); if(StringTools.isNumberOnly(cmd)) { AuctionEntry ae = corral.takeForRead(cmd); if(ae != null) { // ae.reload(); AuctionListHolder old = mIdentifierToList.get(ae.getIdentifier()); AuctionListHolder newAuction = refilterAuction(ae); if (newAuction != null) { MQFactory.getConcrete("Swing").enqueue("Moved to " + newAuction.getList().getName() + " " + ae.getTitleAndComment()); if (old != null) old.getUI().redrawAll(); newAuction.getUI().redrawAll(); } else { auctionTableModel model = (auctionTableModel)tabs.getCurrentTable().getModel(); int row = model.findRow(ae); if(row == -1) { // Log that it's confused? } else { row = tabs.getCurrentTable().convertRowIndexToView(row); tabs.getCurrentTable().tableChanged(new TableModelEvent(model, row)); } } return; } } // Starting with #, and 6 hex digits long it's a color if(cmd.startsWith("#") && cmd.length() == 7) { mList.setBackground(Color.decode(cmd)); } else if(cmd.startsWith("#font")) { mList.adjustHeights(); } else { AuctionListHolder toSort = mList.findCategory(cmd); if(toSort != null) { toSort.getUI().sort(); } } } /** Delete an auction from the Auctions list that it's in. * * @param ae - The auction to delete. */ public void deleteAuction(AuctionEntry ae) { AuctionEntry deleteEntry = corral.takeForRead(ae.getIdentifier()); AuctionListHolder which = mIdentifierToList.get(deleteEntry.getIdentifier()); if(which != null) which.getUI().delEntry(ae); mIdentifierToList.remove(ae.getIdentifier()); } /** * Adds an auction entry to the appropriate Auctions list, based on * the loaded filters. * * @param ae - The auction to add. */ public void addAuction(AuctionEntry ae) { AuctionEntry newEntry = corral.takeForRead(ae.getIdentifier()); AuctionListHolder which = mIdentifierToList.get(newEntry.getIdentifier()); if(which != null) { // If it's already sorted into a Auctions list, tell that list // to handle it. if(which.getList().allowAddEntry(newEntry)) { which.getUI().addEntry(newEntry); } } else { AuctionListHolder sendTo = matchAuction(newEntry); // If we have no auction collections, then this isn't relevant. if(sendTo != null) { if (sendTo.getList().allowAddEntry(newEntry)) { sendTo.getUI().addEntry(newEntry); mIdentifierToList.put(newEntry.getIdentifier(), sendTo); } } } } /** * Currently auction entries can only be in one Auctions collection * at a time. There MUST be a default auction being returned by * matchAuction. It cannot return null right now. * * @param ae - The auction to locate the collection for. * @return - The collection currently holding the provided auction. */ private AuctionListHolder matchAuction(AuctionEntry ae) { if (!ae.isSticky() || ae.getCategory() == null) { // Hardcode seller and ended checks. if (ae.isSeller()) return mDefaultSellingTab; if (ae.isComplete()) return mDefaultCompleteTab; } String category = ae.getCategory(); // Now iterate over the auction Lists, looking for one named the // same as the AuctionEntry's 'category'. AuctionListHolder rval = mList.findCategory(category); if (rval != null) return rval; if (category != null && !category.startsWith("New Search")) return addTab(category); return mMainTab; } /** Currently auction entries can only be in one Auctions collection * at a time. This still searches all, just in case. In truth, it * should keep a list of Auctions that each AuctionEntry is part of. * There MUST be a default auction being returned by matchAuction. * The list of auctions should be a Map, mapping AuctionEntry values * to a List of Auctions that it's part of. * * @param ae - The auction entry to refilter. * * @return an Auctions entry if it moved the auction somewhere else, * and null if it didn't find the auction, or it was in the same * filter as it was before. */ private AuctionListHolder refilterAuction(AuctionEntry ae) { AuctionListHolder sendTo = matchAuction(ae); AuctionListHolder old = mIdentifierToList.get(ae.getIdentifier()); if(old == null && ae.getCategory() != null) { old = mList.findCategory(ae.getCategory()); if(old != null) mIdentifierToList.put(ae.getIdentifier(), old); } if(old != null) { String tabName = old.getList().getName(); if(sendTo.getList().isCompleted()) { String destination; if(ae.isBidOn() || ae.isSniped()) { if(ae.isHighBidder()) { destination = JConfig.queryConfiguration(tabName + ".won_target"); } else { destination = JConfig.queryConfiguration(tabName + ".lost_target"); } } else { destination = JConfig.queryConfiguration(tabName + ".other_target"); } if(destination != null) { if(destination.equals("<delete>")) { deleteAuction(ae); return null; } ae.setSticky(true); sendTo = mList.findCategory(destination); if(sendTo == null) sendTo = addTab(destination); } } } if(old == sendTo || old == null) { if(old == null) { JConfig.log().logMessage("For some reason oldAuctions is null, and nobody acknowledges owning it, for auction entry " + ae.getTitle()); } return null; } AuctionsUIModel oldUI = old.getUI(); AuctionsUIModel newUI = sendTo.getUI(); if(oldUI != null) oldUI.delEntry(ae); if(newUI != null) { ae.setCategory(sendTo.getList().getName()); newUI.addEntry(ae); } mIdentifierToList.put(ae.getIdentifier(), sendTo); return sendTo; } }