Skip to content

Commit

Permalink
Allow sorting of classifications when editing instruments
Browse files Browse the repository at this point in the history
Issue: #4341
  • Loading branch information
buchen committed Dec 22, 2024
1 parent 9ee56b3 commit e08e4b5
Show file tree
Hide file tree
Showing 2 changed files with 112 additions and 21 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,16 @@

/* package */final class EditSecurityModel extends BindingHelper.Model
{
public enum SortOrder
{
/** by natural order, i.e., the order defined by the taxonomy */
NATURAL,
/** by name */
NAME,
/** by weight */
WEIGHT
}

static class TaxonomyDesignation extends BindingHelper.Model
{
private Taxonomy taxonomy;
Expand All @@ -28,6 +38,8 @@ static class TaxonomyDesignation extends BindingHelper.Model

private List<ClassificationLink> links = new ArrayList<>();

private SortOrder sortOrder = SortOrder.NATURAL;

public TaxonomyDesignation(Taxonomy taxonomy, final Security security)
{
this.taxonomy = taxonomy;
Expand Down Expand Up @@ -60,6 +72,16 @@ public List<ClassificationLink> getLinks()
return links;
}

public SortOrder getSortOrder()
{
return sortOrder;
}

public void setSortOrder(SortOrder sortOrder)
{
this.sortOrder = sortOrder;
}

@Override
public void applyChanges()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,6 @@
import org.eclipse.jface.databinding.viewers.typed.ViewerProperties;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.layout.GridLayoutFactory;
import org.eclipse.jface.resource.FontDescriptor;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.resource.LocalResourceManager;
import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.ComboViewer;
import org.eclipse.jface.viewers.LabelProvider;
Expand All @@ -31,7 +28,8 @@
import org.eclipse.swt.events.ControlEvent;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.RowLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
Expand All @@ -43,9 +41,12 @@
import name.abuchen.portfolio.money.Values;
import name.abuchen.portfolio.ui.Images;
import name.abuchen.portfolio.ui.Messages;
import name.abuchen.portfolio.ui.UIConstants;
import name.abuchen.portfolio.ui.util.BindingHelper;
import name.abuchen.portfolio.ui.wizards.security.EditSecurityModel.ClassificationLink;
import name.abuchen.portfolio.ui.wizards.security.EditSecurityModel.SortOrder;
import name.abuchen.portfolio.ui.wizards.security.EditSecurityModel.TaxonomyDesignation;
import name.abuchen.portfolio.util.TextUtil;

public class SecurityTaxonomyPage extends AbstractPage
{
Expand Down Expand Up @@ -131,7 +132,7 @@ private static final class GreaterThanZeroValidator implements IValidator<Intege
@Override
public IStatus validate(Integer value)
{
int weight = (Integer) value;
int weight = value;
return weight > 0 ? ValidationStatus.ok()
: ValidationStatus.error(Messages.EditWizardMasterDataMsgWeightEqualsZero);
}
Expand All @@ -141,7 +142,6 @@ public IStatus validate(Integer value)
private final EditSecurityModel model;
private final BindingHelper bindings;
private ScrolledComposite scrolledComposite;
private Font boldFont;
private List<ValidationStatusProvider> validators = new ArrayList<>();

public SecurityTaxonomyPage(EditSecurityModel model, BindingHelper bindings)
Expand All @@ -154,14 +154,10 @@ public SecurityTaxonomyPage(EditSecurityModel model, BindingHelper bindings)
@Override
public void createControl(Composite parent)
{
LocalResourceManager resources = new LocalResourceManager(JFaceResources.getResources(), parent);

boldFont = resources.create(FontDescriptor.createFrom(parent.getFont()).setStyle(SWT.BOLD));

scrolledComposite = new ScrolledComposite(parent, SWT.H_SCROLL | SWT.V_SCROLL);
setControl(scrolledComposite);
Composite container = new Composite(scrolledComposite, SWT.NULL);
GridLayoutFactory.fillDefaults().numColumns(2).margins(5, 5).applyTo(container);
GridLayoutFactory.fillDefaults().margins(5, 5).applyTo(container);

scrolledComposite.setContent(container);
scrolledComposite.setExpandVertical(true);
Expand All @@ -182,22 +178,56 @@ public void controlResized(ControlEvent e)
private void createTaxonomySection(final Composite taxonomyPicker, final TaxonomyDesignation designation)
{
// label
Label label = new Label(taxonomyPicker, SWT.NONE);
label.setFont(boldFont);
Composite heading = new Composite(taxonomyPicker, SWT.NONE);
boolean isFirst = designation.equals(model.getDesignations().get(0));
GridDataFactory.fillDefaults().indent(0, isFirst ? 0 : 20).applyTo(heading);

GridLayoutFactory.fillDefaults().numColumns(2).applyTo(heading);

Label label = new Label(heading, SWT.NONE);
label.setData(UIConstants.CSS.CLASS_NAME, UIConstants.CSS.HEADING1);
label.setText(designation.getTaxonomy().getName());
GridDataFactory.fillDefaults().align(SWT.BEGINNING, SWT.CENTER).applyTo(label);

boolean isFirst = designation.equals(model.getDesignations().get(0));
if (designation.getLinks().size() > 1)
{
Composite sortBlock = new Composite(heading, SWT.NONE);
GridDataFactory.fillDefaults().align(SWT.END, SWT.END).grab(true, true).applyTo(sortBlock);

GridDataFactory.fillDefaults().grab(true, false).span(2, 1).align(SWT.BEGINNING, SWT.CENTER)
.indent(0, isFirst ? 0 : 20).applyTo(label);
sortBlock.setLayout(new RowLayout());

Link option = new Link(sortBlock, SWT.UNDERLINE_LINK);
option.setText(designation.getSortOrder() != SortOrder.NATURAL ? "<a>" + Messages.ColumnTaxonomy + "</a>" //$NON-NLS-1$ //$NON-NLS-2$
: "\u25B2 " + Messages.ColumnTaxonomy); //$NON-NLS-1$
option.addSelectionListener(SelectionListener.widgetSelectedAdapter(e -> {
designation.setSortOrder(SortOrder.NATURAL);
recreateTaxonomyPicker(taxonomyPicker);
}));

option = new Link(sortBlock, SWT.UNDERLINE_LINK);
option.setText(designation.getSortOrder() != SortOrder.NAME ? "<a>" + Messages.ColumnName + "</a>" //$NON-NLS-1$ //$NON-NLS-2$
: "\u25B2 " + Messages.ColumnName); //$NON-NLS-1$
option.addSelectionListener(SelectionListener.widgetSelectedAdapter(e -> {
designation.setSortOrder(SortOrder.NAME);
recreateTaxonomyPicker(taxonomyPicker);
}));

option = new Link(sortBlock, SWT.UNDERLINE_LINK);
option.setText(designation.getSortOrder() != SortOrder.WEIGHT ? "<a>" + Messages.ColumnWeight + "</a>" //$NON-NLS-1$ //$NON-NLS-2$
: "\u25BC " + Messages.ColumnWeight); //$NON-NLS-1$
option.addSelectionListener(SelectionListener.widgetSelectedAdapter(e -> {
designation.setSortOrder(SortOrder.WEIGHT);
recreateTaxonomyPicker(taxonomyPicker);
}));
}

// drop-down selection block
addBlock(taxonomyPicker, designation);

// add button
Link link = new Link(taxonomyPicker, SWT.UNDERLINE_LINK);
link.setText(Messages.EditWizardMasterDataLinkNewCategory);
GridDataFactory.fillDefaults().span(2, 1).indent(0, 5).align(SWT.BEGINNING, SWT.CENTER).applyTo(link);
GridDataFactory.fillDefaults().indent(0, 5).align(SWT.BEGINNING, SWT.CENTER).applyTo(link);

link.addSelectionListener(new SelectionAdapter()
{
Expand All @@ -219,6 +249,45 @@ private void addBlock(final Composite taxonomyPicker, final TaxonomyDesignation
final List<IObservableValue<Integer>> weightObservables = new ArrayList<>();
final List<IObservableValue<?>> classificationObservables = new ArrayList<>();

switch (designation.getSortOrder())
{
case NATURAL:
designation.getLinks().sort((r, l) -> {
var right = r.getClassification();
var left = l.getClassification();

if (right == null && left == null)
return 0;
if (right == null)
return 1;
if (left == null)
return -1;

return designation.getElements().indexOf(right) - designation.getElements().indexOf(left);
});
break;
case NAME:
designation.getLinks().sort((r, l) -> {
var right = r.getClassification();
var left = l.getClassification();

if (right == null && left == null)
return 0;
if (right == null)
return 1;
if (left == null)
return -1;

return TextUtil.compare(right.getName(), left.getName());
});
break;
case WEIGHT:
designation.getLinks().sort((firstLink, secondLink) -> Integer.compare(secondLink.getWeight(),
firstLink.getWeight()));
break;
default:
}

if (designation.getLinks().size() == 1
&& designation.getLinks().get(0).getWeight() == Classification.ONE_HUNDRED_PERCENT)
{
Expand Down Expand Up @@ -246,7 +315,7 @@ private void addSimpleBlock(Composite picker, TaxonomyDesignation designation, f
Composite block = new Composite(picker, SWT.NONE);
block.setBackground(picker.getBackground());
block.setData(link);
GridDataFactory.fillDefaults().span(2, 1).applyTo(block);
GridDataFactory.fillDefaults().applyTo(block);
GridLayoutFactory.fillDefaults().numColumns(2).applyTo(block);

addDropDown(block, designation, classificationObservables);
Expand All @@ -259,7 +328,7 @@ private void addFullBlock(Composite picker, TaxonomyDesignation designation, fin
{
Composite block = new Composite(picker, SWT.NONE);
block.setData(link);
GridDataFactory.fillDefaults().span(2, 1).applyTo(block);
GridDataFactory.fillDefaults().applyTo(block);
GridLayoutFactory.fillDefaults().numColumns(3).applyTo(block);

addSpinner(block, link, weightObservables);
Expand Down Expand Up @@ -381,8 +450,8 @@ private void addSpinner(Composite block, ClassificationLink link, List<IObservab
private void createTaxonomyPicker(Composite container)
{
final Composite taxonomyPicker = new Composite(container, SWT.NONE);
GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER).span(2, 1).grab(true, false).applyTo(taxonomyPicker);
GridLayoutFactory.fillDefaults().numColumns(2).margins(0, 0).spacing(0, 0).applyTo(taxonomyPicker);
GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER).grab(true, false).applyTo(taxonomyPicker);
GridLayoutFactory.fillDefaults().margins(0, 0).spacing(0, 0).applyTo(taxonomyPicker);

for (TaxonomyDesignation designation : model.getDesignations())
createTaxonomySection(taxonomyPicker, designation);
Expand Down

0 comments on commit e08e4b5

Please sign in to comment.