
jdplus.toolkit.desktop.plugin.ui.calendar.CompositeGregorianCalendarPanel Maven / Gradle / Ivy
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package jdplus.toolkit.desktop.plugin.ui.calendar;
import jdplus.toolkit.desktop.plugin.DemetraIcons;
import jdplus.toolkit.desktop.plugin.beans.PropertyChangeSource;
import jdplus.main.desktop.design.SwingProperty;
import jdplus.toolkit.desktop.plugin.properties.NodePropertySetBuilder;
import jdplus.toolkit.desktop.plugin.util.IDialogDescriptorProvider;
import jdplus.toolkit.desktop.plugin.util.ListenerState;
import jdplus.toolkit.base.api.timeseries.calendars.CalendarManager;
import jdplus.toolkit.base.api.timeseries.regression.ModellingContext;
import jdplus.toolkit.base.api.util.Arrays2;
import jdplus.toolkit.base.api.util.Constraint;
import jdplus.toolkit.base.api.util.WeightedItem;
import org.openide.DialogDescriptor;
import org.openide.explorer.ExplorerManager;
import org.openide.nodes.*;
import org.openide.util.WeakListeners;
import org.openide.util.lookup.Lookups;
import javax.swing.*;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import java.awt.*;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.util.List;
import java.util.*;
/**
*
* @author Philippe Charles
*/
public class CompositeGregorianCalendarPanel extends JPanel implements ExplorerManager.Provider, IDialogDescriptorProvider {
// PROPERTIES DEFINITION
public static final String CALENDAR_NAME_PROPERTY = "calendarName";
public static final String WEIGHTED_ITEMS_PROPERTY = "weightedItems";
// PROPERTIES
private String calendarName;
private List> weightedItems;
// OTHER
final ExplorerManager em;
final NameTextFieldListener nameTextFieldListener;
final ListOfWeightedItem childFactory;
final String initialCalendarName;
/**
* Creates new form NationalCalendarPanel
*/
public CompositeGregorianCalendarPanel(String initialCalendarName) {
this.initialCalendarName = initialCalendarName;
this.calendarName = initialCalendarName != null ? initialCalendarName : "";
this.weightedItems = Collections.emptyList();
this.em = new ExplorerManager();
initComponents();
childFactory = new ListOfWeightedItem();
em.setRootContext(new AbstractNode(Children.create(childFactory, false)));
this.nameTextFieldListener = new NameTextFieldListener();
treeTableView1.setRootVisible(false);
treeTableView1.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
WeightedItemNode template = new WeightedItemNode(new WeightedItemBean(""));
treeTableView1.setProperties(template.getPropertySets()[0].getProperties());
nameTextField.setText(calendarName);
nameTextField.getDocument().addDocumentListener(nameTextFieldListener);
addPropertyChangeListener(evt -> {
switch (evt.getPropertyName()) {
case CompositeGregorianCalendarPanel.CALENDAR_NAME_PROPERTY:
onCalendarNameChange();
break;
case CompositeGregorianCalendarPanel.WEIGHTED_ITEMS_PROPERTY:
onWeightedItemsChange();
break;
}
});
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// //GEN-BEGIN:initComponents
private void initComponents() {
jLabel1 = new javax.swing.JLabel();
nameTextField = new javax.swing.JTextField();
treeTableView1 = new org.openide.explorer.view.TreeTableView();
jLabel1.setText("Name:");
org.jdesktop.layout.GroupLayout layout = new org.jdesktop.layout.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
.add(org.jdesktop.layout.GroupLayout.TRAILING, layout.createSequentialGroup()
.addContainerGap()
.add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.TRAILING)
.add(treeTableView1, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 502, Short.MAX_VALUE)
.add(org.jdesktop.layout.GroupLayout.LEADING, nameTextField)
.add(org.jdesktop.layout.GroupLayout.LEADING, layout.createSequentialGroup()
.add(jLabel1)
.add(0, 0, Short.MAX_VALUE)))
.addContainerGap())
);
layout.setVerticalGroup(
layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
.add(layout.createSequentialGroup()
.add(4, 4, 4)
.add(jLabel1)
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
.add(nameTextField, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(org.jdesktop.layout.LayoutStyle.UNRELATED)
.add(treeTableView1, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 270, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
.addContainerGap(org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
);
}// //GEN-END:initComponents
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JLabel jLabel1;
private javax.swing.JTextField nameTextField;
private org.openide.explorer.view.TreeTableView treeTableView1;
// End of variables declaration//GEN-END:variables
//
protected void onCalendarNameChange() {
if (nameTextFieldListener.state == ListenerState.READY) {
nameTextFieldListener.state = ListenerState.SUSPENDED;
nameTextField.setText(calendarName);
nameTextFieldListener.state = ListenerState.READY;
}
}
protected void onWeightedItemsChange() {
if (childFactory.state == ListenerState.READY) {
childFactory.state = ListenerState.SUSPENDED;
Map tmp = new HashMap<>();
for (WeightedItem o : weightedItems) {
tmp.put(o.getItem(), o.getWeight());
}
for (WeightedItemBean o : childFactory.beans) {
Double weight = tmp.get(o.getName());
if (weight != null) {
o.setUsed(true);
o.setWeight(weight);
} else {
o.setUsed(false);
o.setWeight(0);
}
}
childFactory.refreshData();
childFactory.state = ListenerState.READY;
}
}
//
//
public String getCalendarName() {
return calendarName;
}
public void setCalendarName(String calendarName) {
String old = this.calendarName;
this.calendarName = calendarName != null ? calendarName : "";
firePropertyChange(CALENDAR_NAME_PROPERTY, old, this.calendarName);
}
public List> getWeightedItems() {
return weightedItems;
}
public void setWeightedItems(List> weightedItems) {
List> old = this.weightedItems;
this.weightedItems = weightedItems != null ? weightedItems : Collections.emptyList();
firePropertyChange(WEIGHTED_ITEMS_PROPERTY, old, this.weightedItems);
}
//
@Override
public ExplorerManager getExplorerManager() {
return em;
}
public static class WeightedItemBean implements PropertyChangeSource.WithWeakListeners {
// PROPERTIES DEFINITIONS
@SwingProperty
public static final String NAME_PROPERTY = "name";
@SwingProperty
public static final String USED_PROPERTY = "used";
@SwingProperty
public static final String WEIGHT_PROPERTY = "weight";
@lombok.experimental.Delegate(types = PropertyChangeSource.class)
private final PropertyChangeSupport broadcaster = new PropertyChangeSupport(this);
// PROPERTIES
private String name;
private boolean used;
private double weight;
public WeightedItemBean(String name) {
this.name = name;
this.used = false;
this.weight = 0d;
}
//
public String getName() {
return name;
}
public void setName(String name) {
String old = this.name;
this.name = name;
broadcaster.firePropertyChange(NAME_PROPERTY, old, this.name);
}
public boolean isUsed() {
return used;
}
public void setUsed(boolean used) {
boolean old = this.used;
this.used = used;
broadcaster.firePropertyChange(USED_PROPERTY, old, this.used);
}
public double getWeight() {
return weight;
}
public void setWeight(double weight) {
double old = this.weight;
this.weight = weight;
broadcaster.firePropertyChange(WEIGHT_PROPERTY, old, this.weight);
}
//
public WeightedItem toItem() {
return new WeightedItem<>(name, weight);
}
}
static class WeightedItemNode extends AbstractNode implements PropertyChangeListener {
public WeightedItemNode(WeightedItemBean bean) {
super(Children.LEAF, Lookups.singleton(bean));
setName(bean.getName());
bean.addWeakPropertyChangeListener(this);
}
@Override
public Image getIcon(int type) {
return DemetraIcons.CALENDAR_16.getImageIcon().getImage();
}
@Override
public String getHtmlDisplayName() {
WeightedItemBean bean = getLookup().lookup(WeightedItemBean.class);
return bean.isUsed() ? ("" + getDisplayName() + "") : getDisplayName();
}
@Override
public void propertyChange(PropertyChangeEvent evt) {
fireDisplayNameChange(null, getDisplayName());
}
@Override
protected Sheet createSheet() {
WeightedItemBean bean = getLookup().lookup(WeightedItemBean.class);
Sheet result = super.createSheet();
NodePropertySetBuilder b = new NodePropertySetBuilder();
b.withBoolean()
.select(bean, "used")
.display("Used")
.add();
b.withDouble()
.select(bean, "weight")
.min(0)
.display("Weight")
.add();
result.put(b.build());
return result;
}
}
class ListOfWeightedItem extends ChildFactory implements NodeListener {
public final List beans = new ArrayList<>();
ListenerState state = ListenerState.READY;
public ListOfWeightedItem() {
for (String o : ModellingContext.getActiveContext().getCalendars().getNames()) {
if (!o.equals(initialCalendarName)) {
beans.add(new WeightedItemBean(o));
}
}
}
public void refreshData() {
refresh(true);
fireDataChange();
}
void fireDataChange() {
if (state == ListenerState.READY) {
state = ListenerState.SENDING;
List> tmp = new ArrayList<>();
for (WeightedItemBean o : beans) {
if (o.isUsed()) {
tmp.add(o.toItem());
}
}
setWeightedItems(tmp);
state = ListenerState.READY;
}
}
@Override
protected boolean createKeys(List toPopulate) {
toPopulate.addAll(beans);
return true;
}
@Override
protected Node createNodeForKey(WeightedItemBean key) {
Node result = new WeightedItemNode(key);
result.addNodeListener(WeakListeners.create(NodeListener.class, this, result));
return result;
}
@Override
public void propertyChange(PropertyChangeEvent evt) {
String p = evt.getPropertyName();
if (p.equals(Node.PROP_DISPLAY_NAME)) {
fireDataChange();
}
}
@Override
public void childrenAdded(NodeMemberEvent ev) {
}
@Override
public void childrenRemoved(NodeMemberEvent ev) {
}
@Override
public void childrenReordered(NodeReorderEvent ev) {
}
@Override
public void nodeDestroyed(NodeEvent ev) {
}
}
private class NameTextFieldListener implements DocumentListener {
ListenerState state = ListenerState.READY;
void update() {
if (state == ListenerState.READY) {
state = ListenerState.SENDING;
setCalendarName(nameTextField.getText());
state = ListenerState.READY;
}
}
@Override
public void insertUpdate(DocumentEvent e) {
update();
}
@Override
public void removeUpdate(DocumentEvent e) {
update();
}
@Override
public void changedUpdate(DocumentEvent e) {
}
}
@Override
public DialogDescriptor createDialogDescriptor(String title) {
return new CompositeDialogDescriptor(this, title);
}
private static class CompositeDialogDescriptor extends CustomDialogDescriptor {
CompositeDialogDescriptor(CompositeGregorianCalendarPanel p, String title) {
super(p, title, new CompositeConstraintData(p, p.getCalendarName()));
validate(CompositeConstraints.values());
}
@Override
public void propertyChange(PropertyChangeEvent evt) {
switch (evt.getPropertyName()) {
case CALENDAR_NAME_PROPERTY:
validate(CompositeConstraints.CALENDAR_NAME);
break;
case WEIGHTED_ITEMS_PROPERTY:
break;
}
}
}
private static class CompositeConstraintData {
final CompositeGregorianCalendarPanel panel;
final String originalName;
final CalendarManager manager;
CompositeConstraintData(CompositeGregorianCalendarPanel panel, String originalName) {
this.panel = panel;
this.originalName = originalName;
this.manager = ModellingContext.getActiveContext().getCalendars();
}
}
private enum CompositeConstraints implements Constraint {
CALENDAR_NAME {
@Override
public String check(CompositeConstraintData t) {
String name = t.panel.getCalendarName();
if (name.isEmpty()) {
return "The name of the calendar cannot be empty";
}
if (!t.originalName.equals(name) && t.manager.contains(name)) {
return "The name of the calendar is already used";
}
return null;
}
}
}
@Override
protected void firePropertyChange(String propertyName, Object oldValue, Object newValue) {
if (!Arrays2.arrayEquals(oldValue, newValue)) {
super.firePropertyChange(propertyName, oldValue, newValue);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy