package name.abuchen.portfolio.ui.views.taxonomy;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.ActionContributionItem;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.resource.LocalResourceManager;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StackLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.ToolBar;
import name.abuchen.portfolio.model.Client;
import name.abuchen.portfolio.model.Taxonomy;
import name.abuchen.portfolio.snapshot.ClientSnapshot;
import name.abuchen.portfolio.ui.AbstractFinanceView;
import name.abuchen.portfolio.ui.Images;
import name.abuchen.portfolio.ui.Messages;
import name.abuchen.portfolio.ui.PortfolioPart;
import name.abuchen.portfolio.ui.util.AbstractDropDown;
import name.abuchen.portfolio.ui.util.ClientFilterDropDown;
import name.abuchen.portfolio.ui.util.SimpleAction;
public class TaxonomyView extends AbstractFinanceView implements PropertyChangeListener
{
/** preference key: store last active view as index */
private String identifierView;
/** preference key: include unassigned category in charts */
private String identifierUnassigned;
/** preference key: order by taxonomy in stack chart */
private String identifierOrderByTaxonomy;
/** preference key: node expansion state in definition viewer */
private String expansionStateDefinition;
/** preference key: node expansion state in rebalancing viewer */
private String expansionStateReblancing;
private TaxonomyModel model;
private Taxonomy taxonomy;
private ClientFilterDropDown clientFilter;
private Composite container;
private List<Action> viewActions = new ArrayList<>();
@Override
protected String getDefaultTitle()
{
return taxonomy.getName();
}
@Override
public void init(PortfolioPart part, Object parameter)
{
super.init(part, parameter);
this.taxonomy = (Taxonomy) parameter;
this.identifierView = TaxonomyView.class.getSimpleName() + "-VIEW-" + taxonomy.getId(); //$NON-NLS-1$
this.identifierUnassigned = TaxonomyView.class.getSimpleName() + "-UNASSIGNED-" + taxonomy.getId(); //$NON-NLS-1$
this.identifierOrderByTaxonomy = TaxonomyView.class.getSimpleName() + "-ORDERBYTAXONOMY-" + taxonomy.getId(); //$NON-NLS-1$
this.expansionStateDefinition = TaxonomyView.class.getSimpleName() + "-EXPANSION-DEFINITION-" //$NON-NLS-1$
+ taxonomy.getId();
this.expansionStateReblancing = TaxonomyView.class.getSimpleName() + "-EXPANSION-REBALANCE-" //$NON-NLS-1$
+ taxonomy.getId();
this.model = make(TaxonomyModel.class, taxonomy);
this.model.setExcludeUnassignedCategoryInCharts(part.getPreferenceStore().getBoolean(identifierUnassigned));
this.model.setOrderByTaxonomyInStackChart(part.getPreferenceStore().getBoolean(identifierOrderByTaxonomy));
this.model.setExpansionStateDefinition(part.getPreferenceStore().getString(expansionStateDefinition));
this.model.setExpansionStateRebalancing(part.getPreferenceStore().getString(expansionStateReblancing));
this.taxonomy.addPropertyChangeListener(this);
}
@Override
public void propertyChange(PropertyChangeEvent event)
{
updateTitle(taxonomy.getName());
}
@Override
public void dispose()
{
taxonomy.removePropertyChangeListener(this);
Control[] children = container.getChildren();
for (Control control : children)
{
Page page = (Page) control.getData();
page.dispose();
}
// store preferences *after* disposing pages -> allow pages to update
// the model
getPreferenceStore().setValue(identifierUnassigned, model.isUnassignedCategoryInChartsExcluded());
getPreferenceStore().setValue(identifierOrderByTaxonomy, model.isOrderByTaxonomyInStackChart());
getPreferenceStore().setValue(expansionStateDefinition, model.getExpansionStateDefinition());
getPreferenceStore().setValue(expansionStateReblancing, model.getExpansionStateRebalancing());
super.dispose();
}
@Override
protected void addButtons(final ToolBar toolBar)
{
addView(toolBar, Messages.LabelViewTaxonomyDefinition, Images.VIEW_TABLE, 0);
addView(toolBar, Messages.LabelViewReBalancing, Images.VIEW_REBALANCING, 1);
addView(toolBar, Messages.LabelViewPieChart, Images.VIEW_PIECHART, 2);
addView(toolBar, Messages.LabelViewTreeMap, Images.VIEW_TREEMAP, 3);
addView(toolBar, Messages.LabelViewStackedChart, Images.VIEW_STACKEDCHART, 4);
addFilterButton(toolBar);
addExportButton(toolBar);
addConfigButton(toolBar);
}
private void addFilterButton(ToolBar toolBar)
{
this.clientFilter = new ClientFilterDropDown(toolBar, getClient(), getPreferenceStore(), filter -> {
Client filteredClient = filter.filter(getClient());
ClientSnapshot snapshot = ClientSnapshot.create(filteredClient, model.getCurrencyConverter(),
LocalDate.now());
model.setClientSnapshot(snapshot);
model.fireTaxonomyModelChange(model.getVirtualRootNode());
});
}
private void addExportButton(ToolBar toolBar)
{
AbstractDropDown.create(toolBar, Messages.MenuExportData, Images.EXPORT.image(), SWT.NONE,
(dropdown, manager) -> {
StackLayout layout = (StackLayout) container.getLayout();
if (layout.topControl != null)
((Page) layout.topControl.getData()).exportMenuAboutToShow(manager);
});
}
private void addConfigButton(ToolBar toolBar)
{
AbstractDropDown.create(toolBar, Messages.MenuShowHideColumns, Images.CONFIG.image(), SWT.NONE,
(dropdown, manager) -> {
StackLayout layout = (StackLayout) container.getLayout();
if (layout.topControl != null)
((Page) layout.topControl.getData()).configMenuAboutToShow(manager);
});
}
@Override
public void notifyModelUpdated()
{
Client filteredClient = this.clientFilter.getSelectedFilter().filter(getClient());
ClientSnapshot snapshot = ClientSnapshot.create(filteredClient, model.getCurrencyConverter(), LocalDate.now());
model.setClientSnapshot(snapshot);
model.fireTaxonomyModelChange(model.getVirtualRootNode());
}
private void addView(final ToolBar toolBar, String label, Images image, final int index)
{
Action showDefinition = new SimpleAction(label, Action.AS_CHECK_BOX, a -> activateView(index));
showDefinition.setImageDescriptor(image.descriptor());
showDefinition.setToolTipText(label);
new ActionContributionItem(showDefinition).fill(toolBar, -1);
viewActions.add(showDefinition);
}
@Override
protected Control createBody(Composite parent)
{
LocalResourceManager resources = new LocalResourceManager(JFaceResources.getResources(), parent);
TaxonomyNodeRenderer renderer = new TaxonomyNodeRenderer(resources);
container = new Composite(parent, SWT.NONE);
StackLayout layout = new StackLayout();
container.setLayout(layout);
Page[] pages = new Page[] { make(DefinitionViewer.class, model, renderer), //
make(ReBalancingViewer.class, model, renderer), //
make(PieChartViewer.class, model, renderer), //
make(TreeMapViewer.class, model, renderer), //
make(StackedChartViewer.class, model, renderer) };
for (Page page : pages)
{
Control control = page.createControl(container);
control.setData(page);
}
activateView(getPart().getPreferenceStore().getInt(identifierView));
model.addDirtyListener(this::markDirty);
return container;
}
private void activateView(final int index)
{
StackLayout layout = (StackLayout) container.getLayout();
Control[] children = container.getChildren();
if (index >= 0 && index < children.length)
{
if (layout.topControl != null)
((Page) layout.topControl.getData()).afterPage();
((Page) children[index].getData()).beforePage();
layout.topControl = children[index];
container.layout();
for (int ii = 0; ii < viewActions.size(); ii++)
viewActions.get(ii).setChecked(index == ii);
getPart().getPreferenceStore().setValue(identifierView, index);
}
}
}