<commit_before>/*******************************************************************************
 * Copyright (c) 2010 Oak Ridge National Laboratory.
 * 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
 ******************************************************************************/
package org.csstudio.display.pvtable.ui;

import org.csstudio.display.pvtable.model.PVTableItem;
import org.csstudio.display.pvtable.model.PVTableModel;
import org.csstudio.display.pvtable.model.PVTableModelListener;
import org.csstudio.display.pvtable.model.TimestampHelper;
import org.csstudio.display.pvtable.model.VTypeHelper;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.layout.TableColumnLayout;
import org.eclipse.jface.viewers.CellEditor;
import org.eclipse.jface.viewers.CellLabelProvider;
import org.eclipse.jface.viewers.ColumnWeightData;
import org.eclipse.jface.viewers.EditingSupport;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TableViewerColumn;
import org.eclipse.jface.viewers.TextCellEditor;
import org.eclipse.jface.viewers.ViewerCell;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.ui.IWorkbenchActionConstants;
import org.eclipse.ui.IWorkbenchPartSite;
import org.epics.pvmanager.data.VType;

/** PV Table GUI
 *  @author <NAME>
 *  @author <NAME> - Original PVManager version of PVTable that used similar editing behavior
 */
public class PVTable implements PVTableModelListener
{
    private PVTableModel model = null;
    private TableViewer viewer;
    private Color changed_background;

    /** Initialize
     *  @param parent Parent widget
     *  @param site Workbench site or <code>null</code>
     */
    public PVTable(final Composite parent, final IWorkbenchPartSite site)
    {
        createComponents(parent);
        createContextMenu(viewer, site);
        
        viewer.getTable().addListener(SWT.Selection, new Listener()
        {
            @Override
            public void handleEvent(final Event event)
            {
                if (event.detail != SWT.CHECK)
                    return;
                // Toggle selection of PVTableItem, then update
                // the TableItem to reflect current state.
                // When instead updating the PVTableItem from the
                // TableItem's check mark, the result was inconsistent
                // behavior for selected rows: Could not un-check the
                // checkbox for a selected row...
                final TableItem tab_item = (TableItem) event.item;
                final PVTableItem item = (PVTableItem) tab_item.getData();
                if (item == PVTableModelContentProvider.NEW_ITEM)
                    item.setSelected(false);
                else
                    item.setSelected(! item.isSelected());
                tab_item.setChecked(item.isSelected());
            }
        });
        
        parent.addDisposeListener(new DisposeListener()
        {
            @Override
            public void widgetDisposed(DisposeEvent e)
            {
                if (model != null)
                {
                    model.removeListener(PVTable.this);
                    model.dispose();
                }
            }
        });
    }

    /** Create GUI components
     *  @param parent
     */
    private void createComponents(final Composite parent)
    {
        // TableColumnLayout requires table to be only child of parent. 
        // To assert that'll always be the case, create box.
        final Composite table_box = new Composite(parent, 0);
        parent.setLayout(new FillLayout());
        final TableColumnLayout layout = new TableColumnLayout();
        table_box.setLayout(layout);
        
        // Tried CheckboxTableViewer, but it lead to inconsistent refreshes:
        // Rows would appear blank. Didn't investigate further, stuck with TableViewer.
        viewer = new TableViewer(table_box, SWT.CHECK | SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER | SWT.VIRTUAL);
        
        final Table table = viewer.getTable();
        table.setHeaderVisible(true);
        table.setLinesVisible(true);
        
        changed_background = table.getDisplay().getSystemColor(SWT.COLOR_CYAN);
        
        final TableViewerColumn pv_column = createColumn(viewer, layout, "PV", 75, 100,
            new CellLabelProvider()
            {
                @Override
                public void update(final ViewerCell cell)
                {
                    final TableItem tab_item = (TableItem) cell.getItem();
                    final PVTableItem item = (PVTableItem) cell.getElement();
                    tab_item.setChecked(item.isSelected());
                    cell.setText(item.getName());
                    updateCommonCellSettings(cell, item);
                }
            });
        pv_column.setEditingSupport(new EditingSupport(viewer)
        {
            @Override
            protected boolean canEdit(final Object element)
            {
                return true;
            }
            
            @Override
            protected CellEditor getCellEditor(final Object element)
            {
                return new TextCellEditor(table);
            }

            @Override
            protected void setValue(final Object element, final Object value)
            {
                final String new_name = value.toString().trim();
                final PVTableItem item = (PVTableItem) element;
                
                if (item == PVTableModelContentProvider.NEW_ITEM)
                {   // Set name of magic NEW_ITEM: Add new item
                    model.addItem(new_name);
                    viewer.setItemCount(model.getItemCount() + 1);
                }
                else if (new_name.isEmpty())
                {   // Setting name to nothing: Remove item
                    model.removeItem(item);
                    viewer.remove(item);
//                    viewer.setItemCount(model.getItemCount() + 1);
                }
                else // Change name of existing item
                    item.updateName(new_name);
            }
            
            @Override
            protected Object getValue(final Object element)
            {
                final PVTableItem item = (PVTableItem) element;
                return item.getName();
            }
        });
        createColumn(viewer, layout, "Timestamp", 50, 100,
            new CellLabelProvider()
            {<commit_msg>o.c.display.pvtable: PV Name edit refresh fixes<commit_after>/*******************************************************************************
 * Copyright (c) 2010 Oak Ridge National Laboratory.
 * 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
 ******************************************************************************/
package org.csstudio.display.pvtable.ui;

import org.csstudio.display.pvtable.model.PVTableItem;
import org.csstudio.display.pvtable.model.PVTableModel;
import org.csstudio.display.pvtable.model.PVTableModelListener;
import org.csstudio.display.pvtable.model.TimestampHelper;
import org.csstudio.display.pvtable.model.VTypeHelper;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.layout.TableColumnLayout;
import org.eclipse.jface.viewers.CellEditor;
import org.eclipse.jface.viewers.CellLabelProvider;
import org.eclipse.jface.viewers.ColumnWeightData;
import org.eclipse.jface.viewers.EditingSupport;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TableViewerColumn;
import org.eclipse.jface.viewers.TextCellEditor;
import org.eclipse.jface.viewers.ViewerCell;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.ui.IWorkbenchActionConstants;
import org.eclipse.ui.IWorkbenchPartSite;
import org.epics.pvmanager.data.VType;

/** PV Table GUI
 *  @author <NAME>
 *  @author <NAME> - Original PVManager version of PVTable that used similar editing behavior
 */
public class PVTable implements PVTableModelListener
{
    private PVTableModel model = null;
    private TableViewer viewer;
    private Color changed_background;

    /** Initialize
     *  @param parent Parent widget
     *  @param site Workbench site or <code>null</code>
     */
    public PVTable(final Composite parent, final IWorkbenchPartSite site)
    {
        createComponents(parent);
        createContextMenu(viewer, site);
        
        viewer.getTable().addListener(SWT.Selection, new Listener()
        {
            @Override
            public void handleEvent(final Event event)
            {
                if (event.detail != SWT.CHECK)
                    return;
                // Toggle selection of PVTableItem, then update
                // the TableItem to reflect current state.
                // When instead updating the PVTableItem from the
                // TableItem's check mark, the result was inconsistent
                // behavior for selected rows: Could not un-check the
                // checkbox for a selected row...
                final TableItem tab_item = (TableItem) event.item;
                final PVTableItem item = (PVTableItem) tab_item.getData();
                if (item == PVTableModelContentProvider.NEW_ITEM)
                    item.setSelected(false);
                else
                    item.setSelected(! item.isSelected());
                tab_item.setChecked(item.isSelected());
            }
        });
        
        parent.addDisposeListener(new DisposeListener()
        {
            @Override
            public void widgetDisposed(DisposeEvent e)
            {
                if (model != null)
                {
                    model.removeListener(PVTable.this);
                    model.dispose();
                }
            }
        });
    }

    /** Create GUI components
     *  @param parent
     */
    private void createComponents(final Composite parent)
    {
        // TableColumnLayout requires table to be only child of parent. 
        // To assert that'll always be the case, create box.
        final Composite table_box = new Composite(parent, 0);
        parent.setLayout(new FillLayout());
        final TableColumnLayout layout = new TableColumnLayout();
        table_box.setLayout(layout);
        
        // Tried CheckboxTableViewer, but it lead to inconsistent refreshes:
        // Rows would appear blank. Didn't investigate further, stuck with TableViewer.
        viewer = new TableViewer(table_box, SWT.CHECK | SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER | SWT.VIRTUAL);
        
        final Table table = viewer.getTable();
        table.setHeaderVisible(true);
        table.setLinesVisible(true);
        
        changed_background = table.getDisplay().getSystemColor(SWT.COLOR_CYAN);
        
        final TableViewerColumn pv_column = createColumn(viewer, layout, "PV", 75, 100,
            new CellLabelProvider()
            {
                @Override
                public void update(final ViewerCell cell)
                {
                    final TableItem tab_item = (TableItem) cell.getItem();
                    final PVTableItem item = (PVTableItem) cell.getElement();
                    tab_item.setChecked(item.isSelected());
                    cell.setText(item.getName());
                    updateCommonCellSettings(cell, item);
                }
            });
        pv_column.setEditingSupport(new EditingSupport(viewer)
        {
            @Override
            protected boolean canEdit(final Object element)
            {
                return true;
            }
            
            @Override
            protected CellEditor getCellEditor(final Object element)
            {
                return new TextCellEditor(table);
            }

            @Override
            protected void setValue(final Object element, final Object value)
            {
                final String new_name = value.toString().trim();
                final PVTableItem item = (PVTableItem) element;
                
                if (item == PVTableModelContentProvider.NEW_ITEM)
                {   // Set name of magic NEW_ITEM: Add new item
                    if (new_name.isEmpty())
                        return;
                    model.addItem(new_name);
                    viewer.setInput(model);
                }
                else if (new_name.isEmpty())
                {   // Setting name to nothing: Remove item
                    model.removeItem(item);
                    viewer.remove(item);
                }
                else // Change name of existing item
                    item.updateName(new_name);
            }
            
            @Override
            protected Object getValue(final Object element)
            {
                final PVTableItem item = (PVTableItem) element;
                return item.getName();
            }
        });
        createColumn(viewer, layout, "Timestamp", 50, 100,
            new CellLabelProvider()
            {
{'fraction_non_alphanumeric': 0.10490670352453352, 'fraction_numerical': 0.0027643400138217, 'mean_word_length': 2.071746975164509, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, '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': '381948', 'n_tokens_mistral': 3860, 'n_tokens_neox': 3618, 'n_words': 879}