package hirondelle.stocks.portfolio;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import java.util.logging.*;
import java.util.*;
import hirondelle.stocks.quotes.Stock;
import hirondelle.stocks.util.Args;
import hirondelle.stocks.util.ui.StandardEditor;
import hirondelle.stocks.util.ui.UiUtil;
import hirondelle.stocks.util.Util;
public final class EditPortfolioAction extends AbstractAction {
public EditPortfolioAction (CurrentPortfolio aCurrentPortfolio, JFrame aFrame) {
super("Portfolio...", UiUtil.getEmptyIcon());
Args.checkForNull(aCurrentPortfolio);
Args.checkForNull(aFrame);
fCurrentPortfolio = aCurrentPortfolio;
fModel = new Model();
fFrame = aFrame;
putValue(SHORT_DESCRIPTION, "Edit the stocks in this portfolio");
putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_E, KeyEvent.CTRL_MASK));
putValue(LONG_DESCRIPTION, "Add, change, delete operations on stocks in portfolio.");
putValue(MNEMONIC_KEY, new Integer(KeyEvent.VK_P) );
}
@Override public void actionPerformed(ActionEvent aEvent) {
fLogger.info("Edit the list of stocks in the current portfolio.");
initWorkingCopy();
showDialog();
}
private CurrentPortfolio fCurrentPortfolio;
private Set<Stock> fWorkingCopy;
private JList<Model> fStockSelector;
private Model fModel;
private JFrame fFrame;
private static final Logger fLogger = Util.getLogger(EditPortfolioAction.class);
private void initWorkingCopy(){
fWorkingCopy = new TreeSet<Stock>( fCurrentPortfolio.getStocks() );
fLogger.fine("Working copy inited to: " + fWorkingCopy);
}
private void synchDisplayWithWorkingCopy(){
fStockSelector.setSelectedIndex(0);
fStockSelector.updateUI();
}
private void showDialog(){
Editor editor = new Editor("Edit Portfolio", fFrame);
editor.showDialog();
}
private JComponent getStockSelector(){
fStockSelector = new JList<Model>(fModel);
fStockSelector.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
fStockSelector.setToolTipText ("Choose item, then change or delete using buttons");
JScrollPane scrollPane = new JScrollPane(fStockSelector);
return scrollPane;
}
private JComponent getCommandColumn(){
JButton add = new JButton("Add...");
add.setMnemonic(KeyEvent.VK_A); add.addActionListener( new ActionListener() {
@Override public void actionPerformed(ActionEvent e) {
addStock();
}
});
class ChangeAction extends EditAction {
ChangeAction(){
super("Change...", KeyEvent.VK_C);
}
@Override public void actionPerformed(ActionEvent event){
changeSelectedStock();
}
}
JButton change = new JButton( new ChangeAction() );
class DeleteAction extends EditAction {
DeleteAction() {
super("Delete", KeyEvent.VK_D);
}
@Override public void actionPerformed(ActionEvent e){
deleteSelectedStock();
}
}
JButton delete = new JButton( new DeleteAction() );
java.util.List<JComponent> buttons = new ArrayList<>();
buttons.add(add);
buttons.add(change);
buttons.add(delete);
return UiUtil.getCommandColumn(buttons);
}
private void addStock(){
StockEditor stockEditor = new StockEditor(fFrame);
Stock newStock = stockEditor.addStock();
fLogger.fine("Adding stock to working copy: " + newStock);
if ( newStock != null ) {
fWorkingCopy.add(newStock);
synchDisplayWithWorkingCopy();
}
}
private void changeSelectedStock(){
fLogger.fine("Changing stock...");
Stock selectedStock = getSelectedStock();
StockEditor stockEditor = new StockEditor(fFrame);
Stock changedStock = stockEditor.changeStock(selectedStock);
if ( changedStock != null ) {
fWorkingCopy.remove(selectedStock);
fWorkingCopy.add(changedStock);
synchDisplayWithWorkingCopy();
}
}
private void deleteSelectedStock(){
Stock selectedStock = getSelectedStock();
fWorkingCopy.remove(selectedStock);
synchDisplayWithWorkingCopy();
}
private Stock getSelectedStock(){
int idx = fStockSelector.getSelectionModel().getLeadSelectionIndex();
Collection<Stock> collection = fWorkingCopy; java.util.List<Stock> stocks = new ArrayList<>(collection);
return stocks.get(idx);
}
private boolean isSelectionPresent() {
return ! fStockSelector.getSelectionModel().isSelectionEmpty();
}
private abstract class EditAction extends AbstractAction implements ListSelectionListener{
EditAction(String aText, int aMnemonic){
super(aText);
putValue(MNEMONIC_KEY, new Integer(aMnemonic) );
setEnabled(false);
fStockSelector.getSelectionModel().addListSelectionListener(this);
}
@Override public void valueChanged(ListSelectionEvent event) {
fLogger.fine("Firing EditAction.valueChanged");
setEnabled(isSelectionPresent());
}
}
private final class Editor extends StandardEditor {
Editor(String aTitle, JFrame aParent){
super(aTitle, aParent, StandardEditor.CloseAction.HIDE);
}
@Override protected JComponent getEditorUI () {
JPanel content = new JPanel();
content.setLayout(new BoxLayout(content, BoxLayout.X_AXIS));
content.add( getStockSelector());
content.add( getCommandColumn() );
return content;
}
@Override protected void okAction() {
if (fWorkingCopy.equals(fCurrentPortfolio.getStocks())) {
fLogger.fine("No detected change in underlying stocks.");
}
else {
fLogger.fine("Detected change in underlying stocks.");
fCurrentPortfolio.setStocks(fWorkingCopy);
fCurrentPortfolio.setNeedsSave(true);
fCurrentPortfolio.notifyObservers();
}
dispose();
}
}
private final class Model extends AbstractListModel {
@Override public Object getElementAt(int aRowIndex) {
Collection<Stock> collection = fWorkingCopy;
java.util.List<Stock> list = new ArrayList<>(collection);
Stock stock = list.get(aRowIndex);
return stock.getName();
}
@Override public int getSize() {
return fWorkingCopy.size();
}
}
}