/*
* Copyright (c) 2004-2011 Marco Maccaferri and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Marco Maccaferri - initial API and implementation
*/
package org.eclipsetrader.ui.internal.charts.views;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.io.InputStream;
import java.io.StringReader;
import java.io.StringWriter;
import java.net.URI;
import java.util.Collections;
import java.util.Comparator;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.IJobChangeEvent;
import org.eclipse.core.runtime.jobs.JobChangeAdapter;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.ActionContributionItem;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.IMenuListener;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.preference.PreferenceDialog;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.window.SameShellProvider;
import org.eclipse.jface.window.Window;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.BusyIndicator;
import org.eclipse.swt.dnd.DND;
import org.eclipse.swt.dnd.DropTarget;
import org.eclipse.swt.dnd.Transfer;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.printing.PrintDialog;
import org.eclipse.swt.printing.Printer;
import org.eclipse.swt.printing.PrinterData;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.IMemento;
import org.eclipse.ui.ISaveablePart;
import org.eclipse.ui.ISharedImages;
import org.eclipse.ui.IViewSite;
import org.eclipse.ui.IWorkbenchActionConstants;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.XMLMemento;
import org.eclipse.ui.actions.ActionFactory;
import org.eclipse.ui.dialogs.PropertyDialogAction;
import org.eclipse.ui.part.ViewPart;
import org.eclipsetrader.core.charts.OHLCDataSeries;
import org.eclipsetrader.core.charts.repository.IChartTemplate;
import org.eclipsetrader.core.feed.IHistory;
import org.eclipsetrader.core.feed.TimeSpan;
import org.eclipsetrader.core.instruments.ISecurity;
import org.eclipsetrader.core.internal.charts.repository.ChartTemplate;
import org.eclipsetrader.core.repositories.IPropertyConstants;
import org.eclipsetrader.core.repositories.IRepositoryService;
import org.eclipsetrader.core.views.IViewChangeListener;
import org.eclipsetrader.core.views.IViewItem;
import org.eclipsetrader.core.views.ViewEvent;
import org.eclipsetrader.ui.charts.BaseChartViewer;
import org.eclipsetrader.ui.charts.ChartCanvas;
import org.eclipsetrader.ui.charts.ChartObjectFactoryTransfer;
import org.eclipsetrader.ui.charts.ChartRowViewItem;
import org.eclipsetrader.ui.charts.ChartView;
import org.eclipsetrader.ui.charts.ChartViewItem;
import org.eclipsetrader.ui.charts.IChartEditorListener;
import org.eclipsetrader.ui.charts.IChartObject;
import org.eclipsetrader.ui.internal.UIActivator;
import org.eclipsetrader.ui.internal.charts.DataImportJob;
import org.eclipsetrader.ui.internal.charts.ImportDataPage;
import org.eclipsetrader.ui.internal.charts.Period;
import org.eclipsetrader.ui.internal.charts.PeriodList;
public class ChartViewPart extends ViewPart implements ISaveablePart {
public static final String VIEW_ID = "org.eclipsetrader.ui.chart"; //$NON-NLS-1$
public static final String K_VIEWS = "Views"; //$NON-NLS-1$
public static final String K_URI = "uri"; //$NON-NLS-1$
public static final String K_TEMPLATE = "template"; //$NON-NLS-1$
public static final String K_PRIVATE_TEMPLATE = "private-template"; //$NON-NLS-1$
public static final String K_PERIOD = "period"; //$NON-NLS-1$
public static final String K_RESOLUTION = "resolution"; //$NON-NLS-1$
public static final String K_SHOW_TOOLTIPS = "show-tooltips"; //$NON-NLS-1$
public static final String K_ZOOM_FACTOR = "zoom-factor"; //$NON-NLS-1$
public static final String K_SHOW_CURRENT_PRICE = "show-current-price"; //$NON-NLS-1$
public static final String K_SHOW_CURRENT_BOOK = "show-current-book"; //$NON-NLS-1$
private URI uri;
private ISecurity security;
private IChartTemplate template;
private BaseChartViewer viewer;
private ChartView view;
private IHistory history;
private IHistory subsetHistory;
private ChartViewDropTarget dropListener;
private boolean dirty;
private IDialogSettings dialogSettings;
private Action cutAction;
private Action copyAction;
private Action pasteAction;
private Action deleteAction;
private Action propertiesAction;
private Action zoomOutAction;
private Action zoomInAction;
private Action zoomResetAction;
private Action updateAction;
private Action periodAllAction;
private ContributionItem[] periodActions;
private Action currentPriceLineAction;
private CurrentPriceLineFactory currentPriceLineFactory;
private Action currentBookAction;
private CurrentBookFactory currentBookFactory;
IMemento memento;
IPreferenceStore preferenceStore;
private class ContributionItem extends ActionContributionItem {
private final Period period;
public ContributionItem(final Period period) {
super(new Action(period.getDescription(), Action.AS_RADIO_BUTTON) {
@Override
public void run() {
setPeriod(period.getPeriod(), period.getResolution());
}
});
this.period = period;
}
public Period getPeriod() {
return period;
}
}
private PropertyChangeListener propertyChangeListener = new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
if (IPropertyConstants.BARS.equals(evt.getPropertyName())) {
TimeSpan resolution = TimeSpan.fromString(dialogSettings.get(K_RESOLUTION));
view.setRootDataSeries(new OHLCDataSeries(security.getName(), subsetHistory.getAdjustedOHLC(), resolution));
Display.getDefault().asyncExec(new Runnable() {
@Override
public void run() {
if (!viewer.getControl().isDisposed()) {
refreshChart();
}
}
});
}
}
};
private IViewChangeListener viewChangeListener = new IViewChangeListener() {
@Override
public void viewChanged(ViewEvent event) {
scheduleLoadJob();
setDirty();
}
};
private IPropertyChangeListener preferenceChangeListener = new IPropertyChangeListener() {
@Override
public void propertyChange(org.eclipse.jface.util.PropertyChangeEvent event) {
IPreferenceStore preferences = (IPreferenceStore) event.getSource();
if (UIActivator.PREFS_SHOW_TOOLTIPS.equals(event.getProperty())) {
viewer.setShowTooltips(preferences.getBoolean(UIActivator.PREFS_SHOW_TOOLTIPS));
}
if (UIActivator.PREFS_SHOW_SCALE_TOOLTIPS.equals(event.getProperty())) {
viewer.setShowScaleTooltips(preferences.getBoolean(UIActivator.PREFS_SHOW_SCALE_TOOLTIPS));
}
if (UIActivator.PREFS_CROSSHAIR_ACTIVATION.equals(event.getProperty())) {
viewer.setCrosshairMode(preferences.getInt(UIActivator.PREFS_CROSSHAIR_ACTIVATION));
}
if (UIActivator.PREFS_CROSSHAIR_SUMMARY_TOOLTIP.equals(event.getProperty())) {
viewer.setDecoratorSummaryTooltips(preferences.getBoolean(UIActivator.PREFS_CROSSHAIR_SUMMARY_TOOLTIP));
}
if (UIActivator.PREFS_CHART_PERIODS.equals(event.getProperty())) {
updatePeriodActions();
}
}
};
private Action printAction = new Action(Messages.ChartViewPart_PrintAction) {
@Override
public void run() {
PrintDialog dialog = new PrintDialog(getViewSite().getShell(), SWT.NONE);
PrinterData data = dialog.open();
if (data == null) {
return;
}
if (data.printToFile) {
data.fileName = "print.out"; // TODO you probably want to ask the user for a filename //$NON-NLS-1$
}
Printer printer = new Printer(data);
try {
Rectangle printerBounds = printer.getClientArea();
Rectangle trimBounds = printer.computeTrim(printerBounds.x, printerBounds.y, printerBounds.width, printerBounds.height);
System.out.println(printerBounds + ", " + trimBounds); //$NON-NLS-1$
if (printer.startJob(getPartName())) {
viewer.print(printer);
printer.endJob();
}
} catch (Throwable e) {
e.printStackTrace();
} finally {
printer.dispose();
}
}
};
public ChartViewPart() {
}
/* (non-Javadoc)
* @see org.eclipse.ui.part.ViewPart#init(org.eclipse.ui.IViewSite, org.eclipse.ui.IMemento)
*/
@Override
public void init(IViewSite site, IMemento memento) throws PartInitException {
super.init(site, memento);
this.memento = memento;
this.preferenceStore = UIActivator.getDefault().getPreferenceStore();
try {
dialogSettings = UIActivator.getDefault().getDialogSettings().getSection(K_VIEWS).getSection(site.getSecondaryId());
uri = new URI(dialogSettings.get(K_URI));
IRepositoryService repositoryService = UIActivator.getDefault().getRepositoryService();
security = repositoryService.getSecurityFromURI(uri);
String privateTemplate = dialogSettings.get(K_PRIVATE_TEMPLATE);
if (privateTemplate != null) {
template = unmarshal(privateTemplate);
}
if (template == null) {
IPath templatePath = new Path("data"); //$NON-NLS-1$
if (dialogSettings.get(K_TEMPLATE) != null) {
templatePath = templatePath.append(dialogSettings.get(K_TEMPLATE));
}
else {
templatePath = templatePath.append("basic-template.xml");
}
InputStream stream = FileLocator.openStream(UIActivator.getDefault().getBundle(), templatePath, false);
template = unmarshal(stream);
}
} catch (Exception e) {
Status status = new Status(IStatus.ERROR, UIActivator.PLUGIN_ID, Messages.ChartViewPart_LoadingErrorMessage + site.getSecondaryId(), e);
UIActivator.getDefault().getLog().log(status);
}
site.setSelectionProvider(new SelectionProvider());
createActions();
createPeriodActions();
IActionBars actionBars = site.getActionBars();
IMenuManager menuManager = actionBars.getMenuManager();
menuManager.add(new Separator("periods.top")); //$NON-NLS-1$
menuManager.add(new Separator("periods")); //$NON-NLS-1$
menuManager.add(new Separator("periods.bottom")); //$NON-NLS-1$
menuManager.add(currentPriceLineAction);
menuManager.add(currentBookAction);
menuManager.appendToGroup("periods.top", periodAllAction); //$NON-NLS-1$
if (periodActions != null) {
for (int i = 0; i < periodActions.length; i++) {
menuManager.appendToGroup("periods", periodActions[i]);
}
}
IToolBarManager toolBarManager = actionBars.getToolBarManager();
toolBarManager.add(new Separator("additions")); //$NON-NLS-1$
toolBarManager.add(updateAction);
TimeSpan periodTimeSpan = TimeSpan.fromString(dialogSettings.get(K_PERIOD));
TimeSpan resolutionTimeSpan = TimeSpan.fromString(dialogSettings.get(K_RESOLUTION));
setPeriodActionSelection(periodTimeSpan, resolutionTimeSpan);
actionBars.setGlobalActionHandler(cutAction.getId(), cutAction);
actionBars.setGlobalActionHandler(copyAction.getId(), copyAction);
actionBars.setGlobalActionHandler(pasteAction.getId(), pasteAction);
actionBars.setGlobalActionHandler(deleteAction.getId(), deleteAction);
actionBars.setGlobalActionHandler(ActionFactory.PRINT.getId(), printAction);
ToolAction toolAction = new ToolAction(Messages.ChartViewPart_LineAction, this, "org.eclipsetrader.ui.charts.tools.line");
actionBars.setGlobalActionHandler(toolAction.getId(), toolAction);
toolAction = new ToolAction(Messages.ChartViewPart_FiboLineAction, this, "org.eclipsetrader.ui.charts.tools.fiboline");
actionBars.setGlobalActionHandler(toolAction.getId(), toolAction);
toolAction = new ToolAction(Messages.ChartViewPart_FanLineAction, this, "org.eclipsetrader.ui.charts.tools.fanline");
actionBars.setGlobalActionHandler(toolAction.getId(), toolAction);
toolAction = new ToolAction(Messages.ChartViewPart_FiboArcAction, this, "org.eclipsetrader.ui.charts.tools.fiboarc");
actionBars.setGlobalActionHandler(toolAction.getId(), toolAction);
actionBars.setGlobalActionHandler(zoomInAction.getActionDefinitionId(), zoomInAction);
actionBars.setGlobalActionHandler(zoomOutAction.getActionDefinitionId(), zoomOutAction);
actionBars.setGlobalActionHandler(zoomResetAction.getActionDefinitionId(), zoomResetAction);
actionBars.setGlobalActionHandler(propertiesAction.getId(), propertiesAction);
actionBars.updateActionBars();
}
/* (non-Javadoc)
* @see org.eclipse.ui.part.ViewPart#saveState(org.eclipse.ui.IMemento)
*/
@Override
public void saveState(IMemento memento) {
memento.putInteger(K_ZOOM_FACTOR, viewer.getZoomFactor());
int[] weights = viewer.getWeights();
if (weights.length > 1) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < weights.length; i++) {
if (i != 0) {
sb.append(";"); //$NON-NLS-1$
}
sb.append(weights[i]);
}
memento.putString("weights", sb.toString()); //$NON-NLS-1$
}
super.saveState(memento);
}
protected void createActions() {
ISharedImages sharedImages = getViewSite().getWorkbenchWindow().getWorkbench().getSharedImages();
zoomInAction = new Action(Messages.ChartViewPart_ZoomInAction) {
@Override
public void run() {
int factor = viewer.getZoomFactor();
viewer.setZoomFactor(factor + 1);
zoomOutAction.setEnabled(true);
zoomResetAction.setEnabled(true);
}
};
zoomInAction.setId("zoomIn"); //$NON-NLS-1$
zoomInAction.setActionDefinitionId("org.eclipsetrader.ui.charts.zoomIn"); //$NON-NLS-1$
zoomOutAction = new Action(Messages.ChartViewPart_ZoomOutAction) {
@Override
public void run() {
int factor = viewer.getZoomFactor();
if (factor > 0) {
viewer.setZoomFactor(factor - 1);
}
zoomOutAction.setEnabled(factor != 1);
zoomResetAction.setEnabled(factor != 1);
}
};
zoomOutAction.setId("zoomOut"); //$NON-NLS-1$
zoomOutAction.setActionDefinitionId("org.eclipsetrader.ui.charts.zoomOut"); //$NON-NLS-1$
zoomResetAction = new Action(Messages.ChartViewPart_NormalSizeAction) {
@Override
public void run() {
viewer.setZoomFactor(0);
zoomOutAction.setEnabled(false);
zoomResetAction.setEnabled(false);
}
};
zoomResetAction.setId("zoomReset"); //$NON-NLS-1$
zoomResetAction.setActionDefinitionId("org.eclipsetrader.ui.charts.zoomReset"); //$NON-NLS-1$
zoomOutAction.setEnabled(false);
zoomResetAction.setEnabled(false);
periodAllAction = new Action(Messages.ChartViewPart_AllPeriodAction, IAction.AS_RADIO_BUTTON) {
@Override
public void run() {
setPeriod(null, TimeSpan.days(1));
}
};
cutAction = new Action(Messages.ChartViewPart_CutAction) {
@Override
public void run() {
}
};
cutAction.setId("cut"); //$NON-NLS-1$
cutAction.setActionDefinitionId("org.eclipse.ui.edit.cut"); //$NON-NLS-1$
cutAction.setImageDescriptor(sharedImages.getImageDescriptor(ISharedImages.IMG_TOOL_CUT));
cutAction.setDisabledImageDescriptor(sharedImages.getImageDescriptor(ISharedImages.IMG_TOOL_CUT_DISABLED));
cutAction.setEnabled(false);
copyAction = new Action(Messages.ChartViewPart_CopyAction) {
@Override
public void run() {
}
};
copyAction.setId("copy"); //$NON-NLS-1$
copyAction.setActionDefinitionId("org.eclipse.ui.edit.copy"); //$NON-NLS-1$
copyAction.setImageDescriptor(sharedImages.getImageDescriptor(ISharedImages.IMG_TOOL_COPY));
copyAction.setDisabledImageDescriptor(sharedImages.getImageDescriptor(ISharedImages.IMG_TOOL_COPY_DISABLED));
copyAction.setEnabled(false);
pasteAction = new Action(Messages.ChartViewPart_PasteAction) {
@Override
public void run() {
}
};
pasteAction.setId("copy"); //$NON-NLS-1$
pasteAction.setActionDefinitionId("org.eclipse.ui.edit.paste"); //$NON-NLS-1$
pasteAction.setImageDescriptor(sharedImages.getImageDescriptor(ISharedImages.IMG_TOOL_PASTE));
pasteAction.setDisabledImageDescriptor(sharedImages.getImageDescriptor(ISharedImages.IMG_TOOL_PASTE_DISABLED));
pasteAction.setEnabled(false);
deleteAction = new Action(Messages.ChartViewPart_DeleteAction) {
@Override
public void run() {
IStructuredSelection selection = (IStructuredSelection) getViewSite().getSelectionProvider().getSelection();
if (!selection.isEmpty()) {
if (MessageDialog.openConfirm(getViewSite().getShell(), getPartName(), Messages.ChartViewPart_DeleteConfirmMessage)) {
ChartViewItem viewItem = (ChartViewItem) selection.getFirstElement();
ChartRowViewItem rowViewItem = (ChartRowViewItem) viewItem.getParent();
if (rowViewItem.getItemCount() == 1) {
rowViewItem.getParentView().removeRow(rowViewItem);
}
else {
rowViewItem.removeChildItem(viewItem);
}
}
}
}
};
deleteAction.setId("delete"); //$NON-NLS-1$
deleteAction.setActionDefinitionId("org.eclipse.ui.edit.delete"); //$NON-NLS-1$
deleteAction.setImageDescriptor(sharedImages.getImageDescriptor(ISharedImages.IMG_TOOL_DELETE));
deleteAction.setDisabledImageDescriptor(sharedImages.getImageDescriptor(ISharedImages.IMG_TOOL_DELETE_DISABLED));
deleteAction.setEnabled(false);
updateAction = new Action(Messages.ChartViewPart_UpdateAction) {
@Override
public void run() {
doUpdate();
}
};
updateAction.setId("update"); //$NON-NLS-1$
updateAction.setImageDescriptor(UIActivator.getImageDescriptor("icons/etool16/refresh.gif")); //$NON-NLS-1$
updateAction.setEnabled(true);
propertiesAction = new PropertyDialogAction(new SameShellProvider(getViewSite().getShell()), getSite().getSelectionProvider()) {
@Override
public void run() {
PreferenceDialog dialog = createDialog();
if (dialog != null) {
if (dialog.open() == Window.OK) {
IStructuredSelection selection = (IStructuredSelection) getSite().getSelectionProvider().getSelection();
ChartViewItem viewItem = (ChartViewItem) selection.getFirstElement();
((ChartRowViewItem) viewItem.getParent()).refresh();
refreshChart();
setDirty();
}
}
}
};
propertiesAction.setId(ActionFactory.PROPERTIES.getId());
propertiesAction.setActionDefinitionId("org.eclipse.ui.file.properties"); //$NON-NLS-1$
propertiesAction.setEnabled(false);
currentPriceLineAction = new Action(Messages.ChartViewPart_ShowCurrentPriceAction, IAction.AS_CHECK_BOX) {
@Override
public void run() {
currentPriceLineFactory.setEnable(isChecked());
dialogSettings.put(K_SHOW_CURRENT_PRICE, isChecked());
}
};
currentBookAction = new Action(Messages.ChartViewPart_ShowBookAction, IAction.AS_CHECK_BOX) {
@Override
public void run() {
currentBookFactory.setEnable(isChecked());
dialogSettings.put(K_SHOW_CURRENT_BOOK, isChecked());
}
};
}
/* (non-Javadoc)
* @see org.eclipse.ui.part.WorkbenchPart#createPartControl(org.eclipse.swt.widgets.Composite)
*/
@Override
public void createPartControl(Composite parent) {
viewer = new BaseChartViewer(parent, SWT.NONE);
viewer.addSelectionChangedListener(new ISelectionChangedListener() {
@Override
public void selectionChanged(SelectionChangedEvent event) {
handleSelectionChanged((IStructuredSelection) event.getSelection());
handleActionsEnablement();
}
});
viewer.getEditor().addListener(new IChartEditorListener() {
@Override
public void applyEditorValue() {
refreshChart();
setDirty();
}
@Override
public void cancelEditor() {
}
});
Transfer[] transferTypes = new Transfer[] {
ChartObjectFactoryTransfer.getInstance(),
};
DropTarget dropTarget = new DropTarget(viewer.getControl(), DND.DROP_COPY | DND.DROP_MOVE);
dropTarget.setTransfer(transferTypes);
dropTarget.addDropListener(dropListener = new ChartViewDropTarget(viewer));
viewer.setShowTooltips(preferenceStore.getBoolean(UIActivator.PREFS_SHOW_TOOLTIPS));
viewer.setShowScaleTooltips(preferenceStore.getBoolean(UIActivator.PREFS_SHOW_SCALE_TOOLTIPS));
viewer.setCrosshairMode(preferenceStore.getInt(UIActivator.PREFS_CROSSHAIR_ACTIVATION));
viewer.setDecoratorSummaryTooltips(preferenceStore.getBoolean(UIActivator.PREFS_CROSSHAIR_SUMMARY_TOOLTIP));
preferenceStore.addPropertyChangeListener(preferenceChangeListener);
if (memento != null) {
if (memento.getString(K_ZOOM_FACTOR) != null) {
int factor = memento.getInteger(K_ZOOM_FACTOR);
viewer.setZoomFactor(factor);
zoomOutAction.setEnabled(factor != 0);
zoomResetAction.setEnabled(factor != 0);
}
}
createContextMenu();
currentPriceLineFactory = new CurrentPriceLineFactory();
currentPriceLineFactory.setSecurity(security);
currentPriceLineFactory.setEnable(dialogSettings.getBoolean(K_SHOW_CURRENT_PRICE));
currentPriceLineAction.setChecked(dialogSettings.getBoolean(K_SHOW_CURRENT_PRICE));
currentBookFactory = new CurrentBookFactory();
currentBookFactory.setSecurity(security);
currentBookFactory.setEnable(dialogSettings.getBoolean(K_SHOW_CURRENT_BOOK));
currentBookAction.setChecked(dialogSettings.getBoolean(K_SHOW_CURRENT_BOOK));
if (security != null && template != null) {
setPartName(NLS.bind("{0} - {1}", new Object[] { //$NON-NLS-1$
security.getName(), template.getName(),
}));
view = new ChartView(template);
ChartRowViewItem rowItem = (ChartRowViewItem) view.getItems()[0];
ChartViewItem viewItem = new ChartViewItem(rowItem, currentPriceLineFactory);
rowItem.addChildItem(0, viewItem);
viewItem = new ChartViewItem(rowItem, currentBookFactory);
rowItem.addChildItem(0, viewItem);
view.addViewChangeListener(viewChangeListener);
scheduleLoadJob();
}
}
void createContextMenu() {
MenuManager menuMgr = new MenuManager("#popupMenu", "popupMenu"); //$NON-NLS-1$ //$NON-NLS-2$
menuMgr.setRemoveAllWhenShown(true);
menuMgr.addMenuListener(new IMenuListener() {
@Override
public void menuAboutToShow(IMenuManager menuManager) {
menuManager.add(new Separator("top")); //$NON-NLS-1$
menuManager.add(cutAction);
menuManager.add(copyAction);
menuManager.add(pasteAction);
menuManager.add(new Separator());
menuManager.add(deleteAction);
menuManager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));
menuManager.add(propertiesAction);
}
});
viewer.getControl().setMenu(menuMgr.createContextMenu(viewer.getControl()));
getSite().registerContextMenu(menuMgr, getSite().getSelectionProvider());
}
void scheduleLoadJob() {
final Display display = viewer.getControl().getDisplay();
if (subsetHistory != null) {
PropertyChangeSupport propertyChangeSupport = (PropertyChangeSupport) subsetHistory.getAdapter(PropertyChangeSupport.class);
if (propertyChangeSupport != null) {
propertyChangeSupport.removePropertyChangeListener(propertyChangeListener);
}
}
ChartLoadJob job = new ChartLoadJob(security);
job.addJobChangeListener(new JobChangeAdapter() {
@Override
public void done(IJobChangeEvent event) {
final ChartLoadJob job = (ChartLoadJob) event.getJob();
history = job.getHistory();
subsetHistory = job.getSubsetHistory();
view.setRootDataSeries(new OHLCDataSeries(security.getName(), subsetHistory.getAdjustedOHLC(), job.getResolutionTimeSpan()));
display.asyncExec(new Runnable() {
@Override
public void run() {
if (viewer.getControl().isDisposed()) {
return;
}
if (memento == null) {
memento = XMLMemento.createWriteRoot("root"); //$NON-NLS-1$
}
saveState(memento);
TimeSpan resolutionTimeSpan = TimeSpan.fromString(dialogSettings.get(K_RESOLUTION));
if (resolutionTimeSpan == null) {
resolutionTimeSpan = TimeSpan.days(1);
}
viewer.setResolutionTimeSpan(resolutionTimeSpan);
dropListener.setView(view);
PropertyChangeSupport propertyChangeSupport = (PropertyChangeSupport) subsetHistory.getAdapter(PropertyChangeSupport.class);
if (propertyChangeSupport != null) {
propertyChangeSupport.addPropertyChangeListener(propertyChangeListener);
}
refreshChart();
}
});
}
});
job.setTimeSpan(TimeSpan.fromString(dialogSettings.get(K_PERIOD)));
job.setResolutionTimeSpan(TimeSpan.fromString(dialogSettings.get(K_RESOLUTION)));
job.setName(Messages.ChartViewPart_LoadingText + getPartName());
job.setUser(true);
job.schedule();
}
/* (non-Javadoc)
* @see org.eclipse.ui.part.WorkbenchPart#setFocus()
*/
@Override
public void setFocus() {
viewer.getControl().setFocus();
}
/* (non-Javadoc)
* @see org.eclipse.ui.part.WorkbenchPart#dispose()
*/
@Override
public void dispose() {
view.removeViewChangeListener(viewChangeListener);
if (subsetHistory != null) {
PropertyChangeSupport propertyChangeSupport = (PropertyChangeSupport) subsetHistory.getAdapter(PropertyChangeSupport.class);
if (propertyChangeSupport != null) {
propertyChangeSupport.removePropertyChangeListener(propertyChangeListener);
}
}
if (UIActivator.getDefault() != null) {
IPreferenceStore preferences = UIActivator.getDefault().getPreferenceStore();
preferences.removePropertyChangeListener(preferenceChangeListener);
}
super.dispose();
}
protected void handleSelectionChanged(IStructuredSelection selection) {
if (selection.size() != 1 || !(selection.getFirstElement() instanceof IChartObject)) {
getViewSite().getSelectionProvider().setSelection(StructuredSelection.EMPTY);
return;
}
ChartViewItemFinder finder = new ChartViewItemFinder((IChartObject) selection.getFirstElement());
view.accept(finder);
if (finder.getViewItem() == null) {
getViewSite().getSelectionProvider().setSelection(new StructuredSelection(view));
}
else {
getViewSite().getSelectionProvider().setSelection(new StructuredSelection(finder.getViewItem()));
}
}
protected void handleActionsEnablement() {
IStructuredSelection selection = (IStructuredSelection) getViewSite().getSelectionProvider().getSelection();
IViewItem viewItem = (IViewItem) selection.getFirstElement();
cutAction.setEnabled(!selection.isEmpty() && viewItem != null && viewItem.getAdapter(MainChartFactory.class) == null);
copyAction.setEnabled(!selection.isEmpty() && viewItem != null && viewItem.getAdapter(MainChartFactory.class) == null);
deleteAction.setEnabled(!selection.isEmpty() && viewItem != null && viewItem.getAdapter(MainChartFactory.class) == null);
propertiesAction.setEnabled(!selection.isEmpty());
}
/* (non-Javadoc)
* @see org.eclipse.ui.ISaveablePart#doSave(org.eclipse.core.runtime.IProgressMonitor)
*/
@Override
public void doSave(IProgressMonitor monitor) {
try {
String privateTemplate = marshal(view.getTemplate());
dialogSettings.put(K_PRIVATE_TEMPLATE, privateTemplate);
clearDirty();
} catch (Exception e) {
e.printStackTrace();
}
}
/* (non-Javadoc)
* @see org.eclipse.ui.ISaveablePart#doSaveAs()
*/
@Override
public void doSaveAs() {
}
protected void setDirty() {
if (!dirty) {
dirty = true;
firePropertyChange(PROP_DIRTY);
}
}
protected void clearDirty() {
if (dirty) {
dirty = false;
firePropertyChange(PROP_DIRTY);
}
}
/* (non-Javadoc)
* @see org.eclipse.ui.ISaveablePart#isDirty()
*/
@Override
public boolean isDirty() {
return dirty;
}
/* (non-Javadoc)
* @see org.eclipse.ui.ISaveablePart#isSaveAsAllowed()
*/
@Override
public boolean isSaveAsAllowed() {
return false;
}
/* (non-Javadoc)
* @see org.eclipse.ui.ISaveablePart#isSaveOnCloseNeeded()
*/
@Override
public boolean isSaveOnCloseNeeded() {
return dirty;
}
/* (non-Javadoc)
* @see org.eclipse.ui.part.WorkbenchPart#getAdapter(java.lang.Class)
*/
@Override
@SuppressWarnings("unchecked")
public Object getAdapter(Class adapter) {
if (adapter.isAssignableFrom(BaseChartViewer.class)) {
return viewer;
}
if (adapter.isAssignableFrom(ChartCanvas.class)) {
return viewer.getSelectedChartCanvas();
}
if (adapter.isAssignableFrom(ChartView.class)) {
return view;
}
if (adapter.isAssignableFrom(IChartTemplate.class)) {
return template;
}
if (adapter.isAssignableFrom(ISecurity.class)) {
return security;
}
if (adapter.isAssignableFrom(IDialogSettings.class)) {
return dialogSettings;
}
return super.getAdapter(adapter);
}
private String marshal(IChartTemplate object) throws Exception {
StringWriter string = new StringWriter();
JAXBContext jaxbContext = JAXBContext.newInstance(ChartTemplate.class);
Marshaller marshaller = jaxbContext.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.FALSE);
marshaller.setProperty(Marshaller.JAXB_ENCODING, "UTF-8"); //$NON-NLS-1$
marshaller.marshal(object, string);
return string.toString();
}
private ChartTemplate unmarshal(String string) throws Exception {
JAXBContext jaxbContext = JAXBContext.newInstance(ChartTemplate.class);
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
return (ChartTemplate) unmarshaller.unmarshal(new StringReader(string));
}
private ChartTemplate unmarshal(InputStream stream) throws Exception {
JAXBContext jaxbContext = JAXBContext.newInstance(ChartTemplate.class);
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
return (ChartTemplate) unmarshaller.unmarshal(stream);
}
protected void refreshChart() {
BusyIndicator.showWhile(Display.getCurrent(), new Runnable() {
@Override
public void run() {
ChartRowViewItem[] rowViewItem = (ChartRowViewItem[]) view.getAdapter(ChartRowViewItem[].class);
if (rowViewItem != null) {
IChartObject[][] input = new IChartObject[rowViewItem.length][];
for (int i = 0; i < input.length; i++) {
input[i] = (IChartObject[]) rowViewItem[i].getAdapter(IChartObject[].class);
}
viewer.setInput(input);
if (memento != null && memento.getString("weights") != null) { //$NON-NLS-1$
String[] s = memento.getString("weights").split(";"); //$NON-NLS-1$ //$NON-NLS-2$
int[] weights = viewer.getWeights();
for (int i = 0; i < weights.length && i < s.length; i++) {
weights[i] = Integer.valueOf(s[i]);
}
viewer.setWeights(weights);
}
}
}
});
}
public void setPeriod(TimeSpan period, TimeSpan resolution) {
dialogSettings.put(K_PERIOD, period != null ? period.toString() : (String) null);
dialogSettings.put(K_RESOLUTION, resolution != null ? resolution.toString() : (String) null);
periodAllAction.setChecked(period == null);
setPeriodActionSelection(period, resolution);
scheduleLoadJob();
}
protected void doUpdate() {
TimeSpan[] aggregation = new TimeSpan[] {
TimeSpan.days(1),
TimeSpan.minutes(1),
};
IDialogSettings dialogSettings = UIActivator.getDefault().getDialogSettings().getSection(ImportDataPage.class.getName());
if (dialogSettings != null) {
String[] s = dialogSettings.getArray("AGGREGATION");
if (s != null && s.length != 0) {
aggregation = new TimeSpan[s.length];
for (int i = 0; i < aggregation.length; i++) {
aggregation[i] = TimeSpan.fromString(s[i]);
}
}
}
DataImportJob job = new DataImportJob(security, DataImportJob.INCREMENTAL, null, null, aggregation);
job.setUser(true);
job.schedule();
}
protected void updatePeriodActions() {
IActionBars actionBars = getViewSite().getActionBars();
IMenuManager menuManager = actionBars.getMenuManager();
if (periodActions != null) {
for (int i = 0; i < periodActions.length; i++) {
menuManager.remove(periodActions[i]);
periodActions[i].dispose();
}
periodActions = null;
}
createPeriodActions();
if (periodActions != null) {
for (int i = 0; i < periodActions.length; i++) {
menuManager.appendToGroup("periods", periodActions[i]);
}
}
TimeSpan periodTimeSpan = TimeSpan.fromString(dialogSettings.get(K_PERIOD));
TimeSpan resolutionTimeSpan = TimeSpan.fromString(dialogSettings.get(K_RESOLUTION));
setPeriodActionSelection(periodTimeSpan, resolutionTimeSpan);
actionBars.updateActionBars();
}
public void createPeriodActions() {
try {
JAXBContext jaxbContext = JAXBContext.newInstance(PeriodList.class);
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
StringReader stream = new StringReader(UIActivator.getDefault().getPreferenceStore().getString(UIActivator.PREFS_CHART_PERIODS));
PeriodList list = (PeriodList) unmarshaller.unmarshal(stream);
Collections.sort(list, new Comparator<Period>() {
@Override
public int compare(Period o1, Period o2) {
if (o1.getPeriod().higherThan(o2.getPeriod())) {
return -1;
}
if (o2.getPeriod().higherThan(o1.getPeriod())) {
return 1;
}
return 0;
}
});
periodActions = new ContributionItem[list.size()];
for (int i = 0; i < periodActions.length; i++) {
periodActions[i] = new ContributionItem(list.get(i));
}
} catch (Exception e) {
e.printStackTrace();
}
}
public void setPeriodActionSelection(TimeSpan period, TimeSpan resolution) {
if (periodActions != null) {
for (int i = 0; i < periodActions.length; i++) {
periodActions[i].getAction().setChecked(periodActions[i].getPeriod().equalsTo(period, resolution));
}
}
}
}