package name.abuchen.portfolio.ui.wizards.security;
import java.text.MessageFormat;
import java.util.Objects;
import org.eclipse.core.databinding.UpdateValueStrategy;
import org.eclipse.core.databinding.beans.BeanProperties;
import org.eclipse.core.databinding.validation.IValidator;
import org.eclipse.core.databinding.validation.ValidationStatus;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.jface.databinding.swt.WidgetProperties;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.layout.GridLayoutFactory;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CTabFolder;
import org.eclipse.swt.custom.CTabItem;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.FormAttachment;
import org.eclipse.swt.layout.FormLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
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.Security;
import name.abuchen.portfolio.ui.Images;
import name.abuchen.portfolio.ui.Messages;
import name.abuchen.portfolio.ui.util.BindingHelper;
import name.abuchen.portfolio.ui.util.FormDataFactory;
public class EditSecurityDialog extends Dialog
{
private CTabFolder tabFolder;
private Label errorMessage;
private final EditSecurityModel model;
private final BindingHelper bindings;
private boolean showQuoteConfigurationInitially = false;
public EditSecurityDialog(Shell parentShell, Client client, Security security)
{
super(parentShell);
this.model = new EditSecurityModel(client, security);
this.bindings = new BindingHelper(model)
{
@Override
public void onValidationStatusChanged(IStatus status)
{
boolean isOK = status.getSeverity() == IStatus.OK;
if (errorMessage != null && !errorMessage.isDisposed())
errorMessage.setText(isOK ? "" : status.getMessage()); //$NON-NLS-1$
Button button = getButton(OK);
if (button != null && !button.isDisposed())
button.setEnabled(isOK);
}
};
}
public void setShowQuoteConfigurationInitially(boolean showQuoteConfigurationInitially)
{
this.showQuoteConfigurationInitially = showQuoteConfigurationInitially;
}
@Override
protected void configureShell(Shell newShell)
{
super.configureShell(newShell);
newShell.setText(model.getName() != null ? model.getName() : Messages.NewFileWizardSecurityTitle);
}
@Override
protected Point getInitialSize()
{
Point preferredSize = getShell().computeSize(SWT.DEFAULT, SWT.DEFAULT, true);
// create dialog with a minimum size
preferredSize.x = Math.max(preferredSize.x, 700);
preferredSize.y = Math.max(preferredSize.y, 500);
return preferredSize;
}
@Override
protected Control createContents(Composite parent)
{
Control contents = super.createContents(parent);
// When creating the binding helper, the ok button does not yet exist.
// Make sure that it has the correct initial enablement state as the
// data loaded might not validate.
getButton(OK).setEnabled("".equals(errorMessage.getText())); //$NON-NLS-1$
return contents;
}
@Override
protected Control createDialogArea(Composite parent)
{
Composite container = new Composite(parent, SWT.NONE);
GridDataFactory.fillDefaults().grab(true, true).applyTo(container);
GridLayoutFactory.fillDefaults().numColumns(1).margins(0, 0).spacing(0, 0).applyTo(container);
createUpperArea(container);
createTabFolder(container);
return container;
}
private void createUpperArea(Composite container)
{
Composite header = new Composite(container, SWT.NONE);
header.setBackground(container.getDisplay().getSystemColor(SWT.COLOR_WHITE));
header.setLayout(new FormLayout());
GridDataFactory.fillDefaults().grab(true, false).applyTo(header);
Label lblName = new Label(header, SWT.NONE);
lblName.setText(Messages.ColumnName);
lblName.setBackground(header.getBackground());
Text name = new Text(header, SWT.BORDER);
name.setBackground(header.getBackground());
errorMessage = new Label(header, SWT.NONE);
errorMessage.setForeground(Display.getDefault().getSystemColor(SWT.COLOR_DARK_RED));
errorMessage.setBackground(header.getBackground());
Label imageLabel = new Label(header, SWT.NONE);
imageLabel.setBackground(header.getBackground());
imageLabel.setImage(Images.BANNER.image());
// form layout
FormDataFactory.startingWith(imageLabel).right(new FormAttachment(100));
FormDataFactory.startingWith(lblName) //
.left(new FormAttachment(0, 5)).top(new FormAttachment(0, 10)) //
.thenRight(name).right(new FormAttachment(imageLabel, -10));
FormDataFactory.startingWith(errorMessage) //
.left(new FormAttachment(0, 5)).top(new FormAttachment(lblName, 10))
.right(new FormAttachment(imageLabel, -10));
// bind to model
bindings.getBindingContext().bindValue(WidgetProperties.text(SWT.Modify).observe(name), //
BeanProperties.value("name").observe(model), //$NON-NLS-1$
new UpdateValueStrategy().setAfterConvertValidator(new IValidator()
{
@Override
public IStatus validate(Object value)
{
String v = (String) value;
return v != null && v.trim().length() > 0 ? ValidationStatus.ok()
: ValidationStatus.error(MessageFormat.format(
Messages.MsgDialogInputRequired, Messages.ColumnName));
}
}), //
null);
}
private void createTabFolder(Composite container)
{
tabFolder = new CTabFolder(container, SWT.TOP | SWT.FLAT);
tabFolder.setBorderVisible(true);
GridDataFactory.fillDefaults().grab(true, true).applyTo(tabFolder);
tabFolder.addSelectionListener(new SelectionAdapter()
{
private AbstractPage current = null;
public void widgetSelected(SelectionEvent e)
{
if (current != null)
current.afterPage();
current = (AbstractPage) ((CTabItem) e.item).getData();
current.beforePage();
}
});
addPage(new SecurityMasterDataPage(model, bindings), Images.SECURITY.image());
addPage(new AttributesPage(model, bindings), null);
addPage(new SecurityTaxonomyPage(model, bindings), null);
addPage(new HistoricalQuoteProviderPage(model, bindings), null);
addPage(new LatestQuoteProviderPage(model, bindings), null);
tabFolder.setSelection(showQuoteConfigurationInitially ? 3 : 0);
// selection event not fired for initial selection
((AbstractPage) tabFolder.getSelection().getData()).beforePage();
}
private void addPage(AbstractPage page, Image image)
{
page.createControl(tabFolder);
CTabItem item = new CTabItem(tabFolder, SWT.NONE);
item.setImage(image);
item.setControl(page.getControl());
item.setText(page.getTitle());
item.setData(page);
}
@Override
protected boolean isResizable()
{
return true;
}
@Override
protected void okPressed()
{
((AbstractPage) tabFolder.getSelection().getData()).afterPage();
Security security = model.getSecurity();
// ask user what to do with existing quotes
boolean hasQuotes = !security.getPrices().isEmpty();
boolean feedChanged = !Objects.equals(model.getFeed(), security.getFeed());
boolean tickerChanged = !Objects.equals(model.getTickerSymbol(), security.getTickerSymbol());
boolean feedURLChanged = !Objects.equals(model.getFeedURL(), security.getFeedURL());
boolean currencyChanged = !Objects.equals(model.getCurrencyCode(), security.getCurrencyCode());
boolean quotesCanChange = feedChanged || tickerChanged || feedURLChanged || currencyChanged;
model.applyChanges();
if (hasQuotes && quotesCanChange)
{
MessageDialog dialog = new MessageDialog(getShell(), //
Messages.MessageDialogProviderChanged, null, //
Messages.MessageDialogProviderChangedText, //
MessageDialog.QUESTION, //
new String[] { Messages.MessageDialogProviderAnswerKeep,
Messages.MessageDialogProviderAnswerReplace },
0);
if (dialog.open() == 1)
security.removeAllPrices();
}
super.okPressed();
}
}