package name.abuchen.portfolio.ui.dialogs.transactions;
import static name.abuchen.portfolio.ui.util.FormDataFactory.startingWith;
import static name.abuchen.portfolio.ui.util.SWTHelper.amountWidth;
import static name.abuchen.portfolio.ui.util.SWTHelper.currencyWidth;
import static name.abuchen.portfolio.ui.util.SWTHelper.widest;
import java.time.LocalDate;
import javax.inject.Inject;
import javax.inject.Named;
import org.eclipse.core.databinding.beans.BeanProperties;
import org.eclipse.core.databinding.observable.value.IObservableValue;
import org.eclipse.core.databinding.validation.MultiValidator;
import org.eclipse.core.databinding.validation.ValidationStatus;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.e4.ui.services.IServiceConstants;
import org.eclipse.jface.databinding.swt.WidgetProperties;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import name.abuchen.portfolio.model.Client;
import name.abuchen.portfolio.model.Portfolio;
import name.abuchen.portfolio.model.PortfolioTransferEntry;
import name.abuchen.portfolio.model.Security;
import name.abuchen.portfolio.money.Values;
import name.abuchen.portfolio.ui.Messages;
import name.abuchen.portfolio.ui.dialogs.transactions.SecurityTransferModel.Properties;
import name.abuchen.portfolio.ui.util.DateTimePicker;
import name.abuchen.portfolio.ui.util.SimpleDateTimeSelectionProperty;
public class SecurityTransferDialog extends AbstractTransactionDialog
{
private final class PortfoliosMustBeDifferentValidator extends MultiValidator
{
IObservableValue source;
IObservableValue target;
public PortfoliosMustBeDifferentValidator(IObservableValue source, IObservableValue target)
{
this.source = source;
this.target = target;
}
@Override
protected IStatus validate()
{
Object from = source.getValue();
Object to = target.getValue();
return from != null && to != null && from != to ? ValidationStatus.ok()
: ValidationStatus.error(Messages.MsgPortfolioMustBeDifferent);
}
}
private Client client;
@Inject
public SecurityTransferDialog(@Named(IServiceConstants.ACTIVE_SHELL) Shell parentShell, Client client)
{
super(parentShell);
this.client = client;
setModel(new SecurityTransferModel(client));
}
private SecurityTransferModel model()
{
return (SecurityTransferModel) this.model;
}
@Override
protected void createFormElements(Composite editArea)
{
//
// input elements
//
// security
ComboInput securities = new ComboInput(editArea, Messages.ColumnSecurity);
securities.value.setInput(including(client.getActiveSecurities(), model().getSecurity()));
securities.bindValue(Properties.security.name(), Messages.MsgMissingSecurity);
securities.bindCurrency(Properties.securityCurrencyCode.name());
// source portfolio
ComboInput source = new ComboInput(editArea, Messages.ColumnAccountFrom);
source.value.setInput(including(client.getActivePortfolios(), model().getSourcePortfolio()));
IObservableValue sourceObservable = source.bindValue(Properties.sourcePortfolio.name(),
Messages.MsgPortfolioFromMissing);
source.bindCurrency(Properties.sourcePortfolioLabel.name());
// target portfolio
ComboInput target = new ComboInput(editArea, Messages.ColumnAccountTo);
target.value.setInput(including(client.getActivePortfolios(), model().getTargetPortfolio()));
IObservableValue targetObservable = target.bindValue(Properties.targetPortfolio.name(),
Messages.MsgPortfolioToMissing);
target.bindCurrency(Properties.targetPortfolioLabel.name());
MultiValidator validator = new PortfoliosMustBeDifferentValidator(sourceObservable, targetObservable);
context.addValidationStatusProvider(validator);
// date
Label lblDate = new Label(editArea, SWT.RIGHT);
lblDate.setText(Messages.ColumnDate);
DateTimePicker valueDate = new DateTimePicker(editArea);
context.bindValue(new SimpleDateTimeSelectionProperty().observe(valueDate.getControl()),
BeanProperties.value(Properties.date.name()).observe(model));
// amount
Input shares = new Input(editArea, Messages.ColumnShares);
shares.bindValue(Properties.shares.name(), Messages.ColumnShares, Values.Share, true);
Input quote = new Input(editArea, "x " + Messages.ColumnQuote); //$NON-NLS-1$
quote.bindBigDecimal(Properties.quote.name(), Values.Quote.pattern());
quote.bindCurrency(Properties.securityCurrencyCode.name());
Input amount = new Input(editArea, "="); //$NON-NLS-1$
amount.bindValue(Properties.amount.name(), Messages.ColumnAmount, Values.Amount, true);
amount.bindCurrency(Properties.securityCurrencyCode.name());
// note
Label lblNote = new Label(editArea, SWT.LEFT);
lblNote.setText(Messages.ColumnNote);
Text valueNote = new Text(editArea, SWT.BORDER);
context.bindValue(WidgetProperties.text(SWT.Modify).observe(valueNote),
BeanProperties.value(Properties.note.name()).observe(model));
//
// form layout
//
int amountWidth = amountWidth(amount.value);
int currencyWidth = currencyWidth(amount.currency);
startingWith(securities.value.getControl(), securities.label).suffix(securities.currency)
.thenBelow(source.value.getControl()).label(source.label).suffix(source.currency)
.thenBelow(target.value.getControl()).label(target.label).suffix(target.currency)
.thenBelow(valueDate.getControl()).label(lblDate)
// shares - quote - amount
.thenBelow(shares.value).width(amountWidth).label(shares.label).thenRight(quote.label)
.thenRight(quote.value).width(amountWidth).thenRight(quote.currency).width(currencyWidth)
.thenRight(amount.label).thenRight(amount.value).width(amountWidth).thenRight(amount.currency)
.width(currencyWidth);
startingWith(shares.value).thenBelow(valueNote).left(securities.value.getControl()).right(amount.value)
.label(lblNote);
int widest = widest(securities.label, source.label, target.label, lblDate, amount.label, lblNote);
startingWith(securities.label).width(widest);
WarningMessages warnings = new WarningMessages(this);
warnings.add(() -> model().getDate().isAfter(LocalDate.now()) ? Messages.MsgDateIsInTheFuture : null);
warnings.add(() -> new StockSplitWarning().check(model().getSecurity(), model().getDate()));
model.addPropertyChangeListener(Properties.security.name(), e -> warnings.check());
model.addPropertyChangeListener(Properties.date.name(), e -> warnings.check());
}
@Override
public void setSecurity(Security security)
{
model().setSecurity(security);
}
@Override
public void setPortfolio(Portfolio portfolio)
{
model().setSourcePortfolio(portfolio);
}
public void setEntry(PortfolioTransferEntry entry)
{
model().setSource(entry);
}
}