<commit_before>package org.csstudio.channel.widgets;

import gov.bnl.channelfinder.api.ChannelQuery.Result;
import gov.bnl.channelfinder.api.ChannelQuery;
import gov.bnl.channelfinder.api.ChannelUtil;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.csstudio.utility.pvmanager.widgets.ErrorBar;
import org.eclipse.jface.viewers.ISelectionProvider;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeItem;
import org.eclipse.ui.IMemento;

/**
 * A tree constructed by a query to channel finder and a set of properties.
 * 
 * @author carcassi
 * 
 */
public class ChannelTreeByPropertyWidget extends AbstractChannelQueryResultWidget
implements ConfigurableWidget {
	
	private Tree tree;
	private ErrorBar errorBar;
	private ISelectionProvider treeSelectionProvider;
	private List<String> properties = new ArrayList<String>();
	private String selectionPv = null;
	private LocalUtilityPvManagerBridge selectionWriter = null;
	private ChannelTreeByPropertyModel model;
	
	@Override
	public void setMenu(Menu menu) {
		super.setMenu(menu);
		tree.setMenu(menu);
	}
	
	/**
	 * The selection provider with the selected data in the tree,
	 * in terms of ChannelTreeByPropertyNode objects.
	 * Provided to add pop-up menu.
	 * 
	 * @return the selection provider
	 */
	public ISelectionProvider getTreeSelectionProvider() {
		return treeSelectionProvider;
	}
	
	public ChannelTreeByPropertyWidget(Composite parent, int style) {
		super(parent, style);
		
		// Close PV on dispose
		addDisposeListener(new DisposeListener() {
			
			@Override
			public void widgetDisposed(DisposeEvent e) {
				if (selectionWriter != null) {
					selectionWriter.close();
					selectionWriter = null;
				}
			}
		});
		
		GridLayout gridLayout = new GridLayout(1, false);
		gridLayout.verticalSpacing = 0;
		gridLayout.marginWidth = 0;
		gridLayout.marginHeight = 0;
		setLayout(gridLayout);
		tree = new Tree(this, SWT.VIRTUAL | SWT.BORDER);
		tree.addListener(SWT.SetData, new Listener() {
			public void handleEvent(Event event) {
				if (model != null) {
					TreeItem item = (TreeItem)event.item;
					TreeItem parentItem = item.getParentItem();
					ChannelTreeByPropertyNode parentNode;
					ChannelTreeByPropertyNode node;
					int index;
					if (parentItem == null) {
						parentNode = model.getRoot();
						index = tree.indexOf(item);
					} else {
						parentNode = (ChannelTreeByPropertyNode) parentItem.getData();
						index = parentItem.indexOf(item);
					}
					node = parentNode.getChild(index);
					item.setData(node);
					item.setText(node.getDisplayName());
					if (node.getChildrenNames() == null) {
						item.setItemCount(0);
					} else {
						item.setItemCount(node.getChildrenNames().size());
					}
				}
			}
		});
		tree.setItemCount(0);
		tree.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));
		tree.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				if (selectionWriter != null && tree.getSelectionCount() > 0) {
					selectionWriter.write(tree.getSelection()[0].getText());
				}
			}
			
			@Override
			public void widgetDefaultSelected(SelectionEvent e) {
				widgetSelected(e);
			}
		});
		treeSelectionProvider = SelectionProviders.treeItemDataSelectionProvider(tree);
		
		errorBar = new ErrorBar(this, SWT.NONE);
		errorBar.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false, 1, 1));
		
		addPropertyChangeListener(new PropertyChangeListener() {
			
			List<String> properties = Arrays.asList("properties");
			
			@Override
			public void propertyChange(PropertyChangeEvent evt) {
				if (properties.contains(evt.getPropertyName())) {
					computeTree();
				}
			}
		});
	}
	
	private void setLastException(Exception ex) {
		errorBar.setException(ex);
	}
	
	private boolean showChannelNames = true;
	
	public boolean isShowChannelNames() {
		return showChannelNames;
	}
	
	public void setShowChannelNames(boolean showChannelNames) {
		boolean oldShowChannelNames = showChannelNames;
		this.showChannelNames = showChannelNames;
		computeTree();
		changeSupport.firePropertyChange("showChannelNames", oldShowChannelNames, showChannelNames);
	}
	
	/**
	 * The properties, in the correct order, used to create the tree.
	 * 
	 * @return a list of property names
	 */
	public List<String> getProperties() {
		return properties;
	}<commit_msg>..channel.widgets: ChannelTree, error bar should be on top.<commit_after>package org.csstudio.channel.widgets;

import gov.bnl.channelfinder.api.ChannelQuery.Result;
import gov.bnl.channelfinder.api.ChannelQuery;
import gov.bnl.channelfinder.api.ChannelUtil;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.csstudio.utility.pvmanager.widgets.ErrorBar;
import org.eclipse.jface.viewers.ISelectionProvider;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeItem;
import org.eclipse.ui.IMemento;

/**
 * A tree constructed by a query to channel finder and a set of properties.
 * 
 * @author carcassi
 * 
 */
public class ChannelTreeByPropertyWidget extends AbstractChannelQueryResultWidget
implements ConfigurableWidget {
	
	private Tree tree;
	private ErrorBar errorBar;
	private ISelectionProvider treeSelectionProvider;
	private List<String> properties = new ArrayList<String>();
	private String selectionPv = null;
	private LocalUtilityPvManagerBridge selectionWriter = null;
	private ChannelTreeByPropertyModel model;
	
	@Override
	public void setMenu(Menu menu) {
		super.setMenu(menu);
		tree.setMenu(menu);
	}
	
	/**
	 * The selection provider with the selected data in the tree,
	 * in terms of ChannelTreeByPropertyNode objects.
	 * Provided to add pop-up menu.
	 * 
	 * @return the selection provider
	 */
	public ISelectionProvider getTreeSelectionProvider() {
		return treeSelectionProvider;
	}
	
	public ChannelTreeByPropertyWidget(Composite parent, int style) {
		super(parent, style);
		
		// Close PV on dispose
		addDisposeListener(new DisposeListener() {
			
			@Override
			public void widgetDisposed(DisposeEvent e) {
				if (selectionWriter != null) {
					selectionWriter.close();
					selectionWriter = null;
				}
			}
		});
		
		GridLayout gridLayout = new GridLayout(1, false);
		gridLayout.verticalSpacing = 0;
		gridLayout.marginWidth = 0;
		gridLayout.marginHeight = 0;
		setLayout(gridLayout);
		
		errorBar = new ErrorBar(this, SWT.NONE);
		errorBar.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false, 1, 1));
		
		addPropertyChangeListener(new PropertyChangeListener() {
			
			List<String> properties = Arrays.asList("properties");
			
			@Override
			public void propertyChange(PropertyChangeEvent evt) {
				if (properties.contains(evt.getPropertyName())) {
					computeTree();
				}
			}
		});
		
		tree = new Tree(this, SWT.VIRTUAL | SWT.BORDER);
		tree.addListener(SWT.SetData, new Listener() {
			public void handleEvent(Event event) {
				if (model != null) {
					TreeItem item = (TreeItem)event.item;
					TreeItem parentItem = item.getParentItem();
					ChannelTreeByPropertyNode parentNode;
					ChannelTreeByPropertyNode node;
					int index;
					if (parentItem == null) {
						parentNode = model.getRoot();
						index = tree.indexOf(item);
					} else {
						parentNode = (ChannelTreeByPropertyNode) parentItem.getData();
						index = parentItem.indexOf(item);
					}
					node = parentNode.getChild(index);
					item.setData(node);
					item.setText(node.getDisplayName());
					if (node.getChildrenNames() == null) {
						item.setItemCount(0);
					} else {
						item.setItemCount(node.getChildrenNames().size());
					}
				}
			}
		});
		tree.setItemCount(0);
		tree.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));
		tree.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				if (selectionWriter != null && tree.getSelectionCount() > 0) {
					selectionWriter.write(tree.getSelection()[0].getText());
				}
			}
			
			@Override
			public void widgetDefaultSelected(SelectionEvent e) {
				widgetSelected(e);
			}
		});
		treeSelectionProvider = SelectionProviders.treeItemDataSelectionProvider(tree);
	}
	
	private void setLastException(Exception ex) {
		errorBar.setException(ex);
	}
	
	private boolean showChannelNames = true;
	
	public boolean isShowChannelNames() {
		return showChannelNames;
	}
	
	public void setShowChannelNames(boolean showChannelNames) {
		boolean oldShowChannelNames = showChannelNames;
		this.showChannelNames = showChannelNames;
		computeTree();
		changeSupport.firePropertyChange("showChannelNames", oldShowChannelNames, showChannelNames);
	}
	
	/**
	 * The properties, in the correct order, used to create the tree.
	 * 
	 * @return a list of property names
	 */
	public List<String> getProperties() {
		return properties;
	}
{'fraction_non_alphanumeric': 0.10435307127777219, 'fraction_numerical': 0.0024127877752086056, 'mean_word_length': 4.255150554675119, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 13, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5941948', 'n_tokens_mistral': 3476, 'n_tokens_neox': 2950, 'n_words': 651}