Package org.fusesource.ide.commons.ui.config

Source Code of org.fusesource.ide.commons.ui.config.TableConfiguration

/*******************************************************************************
* Copyright (c) 2013 Red Hat, Inc.
* Distributed under license by Red Hat, Inc. All rights reserved.
* This program is 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
*
* Contributors:
*     Red Hat, Inc. - initial API and implementation
******************************************************************************/

package org.fusesource.ide.commons.ui.config;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;

import org.eclipse.jface.viewers.CellLabelProvider;
import org.eclipse.jface.viewers.ColumnViewer;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeColumn;
import org.fusesource.ide.commons.Activator;
import org.fusesource.ide.commons.IFlushable;
import org.fusesource.ide.commons.PreferencesHelper;
import org.fusesource.ide.commons.ui.IConfigurableColumns;
import org.fusesource.ide.commons.ui.Tables;
import org.fusesource.ide.commons.util.Strings;
import org.osgi.service.prefs.Preferences;


/**
* Configuration details of a table. These will be stored in
*
* .metadata/.plugins/org.eclipse.core.runtime/.settings/org.fusesource.ide.commons.prefs
*/
public class TableConfiguration implements IFlushable {
  protected static final int CONFIG_UPDATE_ONMOVE_DELAY = 1500;
  protected static final String COLUMN_NAME_SEPARATOR = ",";
  protected static final String COLUMN_ORDER = "columnOrder";
  private AtomicInteger moveEventCounter = new AtomicInteger();
  private static Map<String,TableConfiguration> defaultCache = new HashMap<String,TableConfiguration>();
  private List<ColumnConfiguration> columnConfigurations;
  private Map<String,ColumnConfiguration> columnMap;
  private final Preferences node;
  private boolean cleared;
  private Listener tableColumnListener = new Listener() {
        @Override
        public void handleEvent(Event event) {
            final int value = moveEventCounter.incrementAndGet();
            final TableColumn column = (TableColumn) event.widget;
            // when we've stopped moving update the columns
            event.display.timerExec(CONFIG_UPDATE_ONMOVE_DELAY, new Runnable() {
                @Override
                public void run() {
                    if (moveEventCounter.compareAndSet(value, 0)) {
                        //Activator.getLogger().debug("We are the last move event at counter: " + value + " so updating the config model");
                        if (column == null || column.isDisposed()) {
                            return;
                        }
                        onColumnsMoved(column.getParent());
                    }
                }
            });
        }
    };
    private Listener treeColumnListener = new Listener() {
        @Override
        public void handleEvent(Event event) {
            final int value = moveEventCounter.incrementAndGet();
            final TreeColumn column = (TreeColumn) event.widget;
            // when we've stopped moving update the columns
            event.display.timerExec(CONFIG_UPDATE_ONMOVE_DELAY, new Runnable() {
                @Override
                public void run() {
                    if (moveEventCounter.compareAndSet(value, 0)) {
                        if (column == null || column.isDisposed()) {
                            return;
                        }
                        //Activator.getLogger().debug("We are the last move event at counter: " + value + " so updating the config model");
                        onColumnsMoved(column.getParent());
                    }
                }
            });
        }
    };

  public TableConfiguration(Preferences node) {
    this.node = node;
  }

  @Override
  public String toString() {
    return "TableConfguration(" + node + ")";
  }

  /**
   * Loads a set of defaults for the table for the given view class
   */
  public static TableConfiguration loadDefault(Class<?> aClass) {
    return loadDefault(aClass.getName());
  }

  /**
   * Loads a set of defaults for the table for the given view ID
   */
  public static synchronized TableConfiguration loadDefault(String className) {
    TableConfiguration answer = defaultCache.get(className);
    if (answer == null) {
      Preferences node = PreferencesHelper.defaultNode(className, PreferencesHelper.KEY_TABLE_COLUMNS);
      answer = new TableConfiguration(node);
      defaultCache.put(className, answer);
    }
    return answer;
  }

  /**
   * Loads a set of configurations for the table for the given view class
   */
  public static TableConfiguration loadConfiguration(Class<?> aClass) {
    return loadConfiguration(aClass.getName());
  }

  /**
   * Loads a set of configurations for the table for the given view ID, applying the defaults
   * for any missing configurations
   */
  public static TableConfiguration loadConfiguration(String className) {
    // lets apply the defaults
    TableConfiguration defaults = TableConfiguration.loadDefault(className);

    Preferences node = PreferencesHelper.configurationNode(className, PreferencesHelper.KEY_TABLE_COLUMNS);
    TableConfiguration answer = new TableConfiguration(node);

    // lets add the defaults for columns with no current configuration
    answer.addDefaults(defaults);
    return answer;
  }


  /**
   * Flushes any changes to the configuration to the underlying preferences store
   */
  @Override
  public void flush() {
    PreferencesHelper.flush(node);
  }

  /**
   * Clears all the configuration
   */
  public void clear() {
    cleared = true;
    try {
      Preferences parent = node.parent();
      node.removeNode();
      if (parent != null) {
        PreferencesHelper.flush(parent);
      }
    } catch (Exception e) {
      Activator.getLogger().error("Failed to clear " + this + ". " + e, e);
    }
  }

  public boolean isCleared() {
    return cleared;
  }

  public void reload() {
    columnConfigurations = null;
  }

  public boolean hasColumns() {
    return getColumnConfigurations().size() > 0;
  }


  /**
   * Returns the configuration for the given column, creating a new one if necessary
   */
  public ColumnConfiguration column(String name) {
    return column(name, node.node(name));
  }

  /**
   * Returns the configuration for the given column, creating a new one if necessary
   */
  public ColumnConfiguration column(String name, Preferences node) {
    ColumnConfiguration config = getConfiguration(name);
    if (config == null) {
      config = new ColumnConfiguration(name, node);
      addColumn(config);
    }
    return config;
  }

  protected ColumnConfiguration addColumn(ColumnConfiguration config) {
    getColumnConfigurations().add(config);
    updateColumnOrder(this.columnConfigurations);
    flushIndexes();
    return config;
  }

  public List<ColumnConfiguration> getColumnConfigurations() {
    if (columnConfigurations == null) {
      // lazy load from the preferences
      loadConfigurations();
    }
    return columnConfigurations;
  }

  protected void loadConfigurations() {
    List<ColumnConfiguration> list = new ArrayList<ColumnConfiguration>();
    // String[] childrenNames = node.childrenNames();
    // lets load them in order they were sorted
    String text = node.get(COLUMN_ORDER, "");
    if (text != null && text.length() > 0) {
      String[] childrenNames = text.split(COLUMN_NAME_SEPARATOR);
      for (String name : childrenNames) {
        ColumnConfiguration config = new ColumnConfiguration(name, node.node(name));
        list.add(config);
      }
    }
    setColumnConfigurations(list);
  }

  public void setColumnConfigurations(List<ColumnConfiguration> columnConfigurations) {
    List<String> names = updateColumnOrder(columnConfigurations);

    // now lets remove any names not in the new ordered collection
    if (this.columnConfigurations != null) {
      for (ColumnConfiguration oldConfig : this.columnConfigurations) {
        String name = oldConfig.getName();
        if (!names.contains(name)) {
          node.remove(name);
        }
      }
    }
    this.columnConfigurations = columnConfigurations;
    flushIndexes();
  }

  protected List<String> updateColumnOrder(List<ColumnConfiguration> columnConfigurations) {
    List<String> names = getColumnNames(columnConfigurations);
    String columnOrderText = Strings.join(COLUMN_NAME_SEPARATOR, names.toArray());
    node.put(COLUMN_ORDER, columnOrderText);

    //Activator.getLogger().debug("Updated columns to: " + names);
    return names;
  }

  private List<String> getColumnNames(List<ColumnConfiguration> list) {
    List<String> answer = new ArrayList<String>();
    for (ColumnConfiguration config : list) {
      answer.add(config.getName());
    }
    return answer;
  }

  protected void flushIndexes() {
    synchronized (this) {
      this.columnMap = null;
    }
  }

  public Map<String,ColumnConfiguration> getColumnMap() {
    synchronized (this) {
      List<ColumnConfiguration> list = getColumnConfigurations();
      if (columnMap == null) {
        columnMap = new HashMap<String, ColumnConfiguration>();
        for (ColumnConfiguration column : list) {
          columnMap.put(column.getName(), column);
        }
      }
      return columnMap;
    }
  }

  /**
   * Returns the column configuration for the given column name or returns null if it does not exist
   */
  public ColumnConfiguration getConfiguration(String columnName) {
    return getColumnMap().get(columnName);
  }

  /**
   * Returns a sorted list of default column names by using the sort order defined in the table configuration first,
   * then any remaining columns afterwards
   */
  public List<String> sortDefaultColumnNames(Collection<String> columnNames) {
    Set<String> existing = new HashSet<String>(columnNames);
    List<String> answer = new ArrayList<String>();
    List<ColumnConfiguration> list = getColumnConfigurations();
    for (ColumnConfiguration config : list) {
      String name = config.getName();
      if (existing.contains(name)) {
        answer.add(name);
      }
    }
    for (String name : columnNames) {
      if (!answer.contains(name)) {
        answer.add(name);
      }
    }
    return answer;
  }

  /**
   * Ensures that the given list of columns are created and visible if we have any configuration so far.
   */
  public void addDefaultColumns(List<String> columns) {
    for (String name : columns) {
      column(name);
    }
  }

  /**
   * Lets add the default configurations if there are any to any column not already configured in some way
   */
  public void addDefaults(TableConfiguration defaults) {
    List<ColumnConfiguration> list = defaults.getColumnConfigurations();
    for (ColumnConfiguration column : list) {
      defaultColumn(column);
    }

  }

  /**
   * Ensures we have the default column configuration created; or add this one if not
   */
  public void defaultColumn(ColumnConfiguration defaultValues) {
    ColumnConfiguration current = getConfiguration(defaultValues.getName());
    if (current == null) {
      current = addColumn(defaultValues);
    }
    // lets default size if present
    int width = defaultValues.getWidth();
    if (width > 0 && current.getWidth() == 0) {
      current.setWidth(width);
    }
    String labelProviderStyle = defaultValues.getLabelProviderStyle();
    if (labelProviderStyle != null) {
      current.setLabelProviderStyle(labelProviderStyle);

    }
    CellLabelProvider labelProvider = defaultValues.getLabelProvider();
    if (labelProvider != null) {
      current.setLabelProvider(labelProvider);
    }
  }

  /**
   * Called when the user moves columns around themselves using drag and drop in the table viewer
   */
  public void onColumnsMoved(Table table) {
    if (isCleared() || table == null || table.isDisposed()) {
      //Activator.getLogger().debug("Ignoring move events as configuration is cleared");
      return;
    }
    List<ColumnConfiguration> newOrder = new ArrayList<ColumnConfiguration>();
    TableColumn[] columns = Tables.getColumns(table);
    if (columns.length > 0) {
      int[] columnOrder = table.getColumnOrder();
      for (int idx : columnOrder) {
        if (idx >= 0 && idx < columns.length) {
          TableColumn column = columns[idx];
          if (column != null && !column.isDisposed()) {
            String name = column.getText();
            ColumnConfiguration config = column(name);
            newOrder.add(config);
          }
        }
      }
    }
    if (columns.length > 1 && newOrder.size() > 1) {
      makeOtherColumnsInvisilbe(newOrder);
      Activator.getLogger().debug("Flushing column configuration with newOrder: " + newOrder + " and columns: " + columns.length);
      flush();
    }
  }

  /**
   * Called when the user moves columns around themselves using drag and drop in the tree viewer
   */
  public void onColumnsMoved(Tree tree) {
    if (isCleared() || tree == null || tree.isDisposed()) {
      //Activator.getLogger().debug("Ignoring move events as configuration is cleared");
      return;
    }
    List<ColumnConfiguration> newOrder = new ArrayList<ColumnConfiguration>();
    TreeColumn[] columns = tree.getColumns();
    int[] columnOrder = tree.getColumnOrder();
    for (int idx : columnOrder) {
      if (idx >= 0 && idx < columns.length) {
        TreeColumn column = columns[idx];
        if (column != null && !column.isDisposed()) {
          String name = column.getText();
          ColumnConfiguration config = column(name);
          newOrder.add(config);
        }
      }
    }
    makeOtherColumnsInvisilbe(newOrder);
    flush();
  }

  protected void makeOtherColumnsInvisilbe(List<ColumnConfiguration> newOrder) {
    // lets add any ignored columns to the configuration so they are hidden next time
    Set<ColumnConfiguration> addedColumns = new HashSet<ColumnConfiguration>(newOrder);
    List<ColumnConfiguration> list = getColumnConfigurations();
    for (ColumnConfiguration config : list) {
      if (!addedColumns.contains(config)) {
        config.setVisible(false);
        newOrder.add(config);
      }
    }
    setColumnConfigurations(newOrder);
  }

  public void addListener(IConfigurableColumns configurableColumns) {
    // TODO there's no generic hook yet for doing listening of the underlying node...
  }

  public void removeListener(IConfigurableColumns configurableColumns) {
    // TODO there's no generic hook yet for doing listening of the underlying node...
  }

    public void addColumnListeners(final ColumnViewer viewer) {
        if (viewer instanceof TreeViewer) {
            addColumnListeners((TreeViewer) viewer);
        } else if (viewer instanceof TableViewer) {
            addColumnListeners((TableViewer) viewer);
        }
    }
   
  public void addColumnListeners(final TableViewer viewer) {
    TableColumn[] columns = viewer.getTable().getColumns();
    for (TableColumn column : columns) {
      addColumnListeners(viewer, column);
    }
  }

  public void addColumnListeners(final TreeViewer viewer) {
    TreeColumn[] columns = viewer.getTree().getColumns();
    for (TreeColumn column : columns) {
      addColumnListeners(viewer, column);
    }
  }

  protected void addColumnListeners(final TableViewer viewer, final TableColumn column) {
    // TODO ignore listeners if we're disposing the columns to update it!!!
    column.addListener(SWT.Move, tableColumnListener);

  }

  protected void addColumnListeners(final TreeViewer viewer, final TreeColumn column) {
    column.addListener(SWT.Move, treeColumnListener);
  }

    public void removeColumnListeners(final ColumnViewer viewer) {
        if (viewer instanceof TreeViewer) {
            removeColumnListeners((TreeViewer) viewer);
        } else if (viewer instanceof TableViewer) {
            removeColumnListeners((TableViewer) viewer);
        }
    }
   
    public void removeColumnListeners(final TableViewer viewer) {
        moveEventCounter.set(0);
        TableColumn[] columns = viewer.getTable().getColumns();
        for (TableColumn column : columns) {
            removeColumnListeners(viewer, column);
        }
    }

    public void removeColumnListeners(final TreeViewer viewer) {
        moveEventCounter.set(0);
        TreeColumn[] columns = viewer.getTree().getColumns();
        for (TreeColumn column : columns) {
            removeColumnListeners(viewer, column);
        }
    }

    protected void removeColumnListeners(final TableViewer viewer, final TableColumn column) {
        // TODO ignore listeners if we're disposing the columns to update it!!!
        column.removeListener(SWT.Move, tableColumnListener);

    }

    protected void removeColumnListeners(final TreeViewer viewer, final TreeColumn column) {
        column.removeListener(SWT.Move, treeColumnListener);
    }

}
TOP

Related Classes of org.fusesource.ide.commons.ui.config.TableConfiguration

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.