All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.opentcs.operationsdesk.components.layer.LayersTableModel Maven / Gradle / Ivy

/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.operationsdesk.components.layer;

import static java.util.Objects.requireNonNull;

import java.util.List;
import java.util.Map;
import java.util.ResourceBundle;
import java.util.stream.Collectors;
import javax.swing.SwingUtilities;
import javax.swing.table.AbstractTableModel;
import org.opentcs.data.model.visualization.Layer;
import org.opentcs.data.model.visualization.LayerGroup;
import org.opentcs.guing.base.components.layer.LayerWrapper;
import org.opentcs.guing.common.components.layer.LayerChangeListener;
import org.opentcs.guing.common.components.layer.LayerEditor;
import org.opentcs.guing.common.components.layer.LayerGroupChangeListener;
import org.opentcs.guing.common.persistence.ModelManager;
import org.opentcs.operationsdesk.util.I18nPlantOverviewOperating;

/**
 * A table model for layers.
 */
class LayersTableModel
    extends
      AbstractTableModel
    implements
      LayerChangeListener,
      LayerGroupChangeListener {

  /**
   * The number of the "Ordinal" column.
   */
  public static final int COLUMN_ORDINAL = 0;
  /**
   * The number of the "Visible" column.
   */
  public static final int COLUMN_VISIBLE = 1;
  /**
   * The number of the "Name" column.
   */
  public static final int COLUMN_NAME = 2;
  /**
   * The number of the "Group" column.
   */
  public static final int COLUMN_GROUP = 3;
  /**
   * The number of the "Group visible" column.
   */
  public static final int COLUMN_GROUP_VISIBLE = 4;
  /**
   * The resource bundle to use.
   */
  private static final ResourceBundle BUNDLE
      = ResourceBundle.getBundle(I18nPlantOverviewOperating.LAYERS_PATH);
  /**
   * The column names.
   */
  private static final String[] COLUMN_NAMES = new String[]{
      BUNDLE.getString("layersTableModel.column_ordinal.headerText"),
      BUNDLE.getString("layersTableModel.column_visible.headerText"),
      BUNDLE.getString("layersTableModel.column_name.headerText"),
      BUNDLE.getString("layersTableModel.column_group.headerText"),
      BUNDLE.getString("layersTableModel.column_groupVisible.headerText")
  };
  /**
   * The column classes.
   */
  private static final Class[] COLUMN_CLASSES = new Class[]{
      Integer.class,
      Boolean.class,
      String.class,
      LayerGroup.class,
      Boolean.class
  };
  /**
   * The model manager.
   */
  private final ModelManager modelManager;
  /**
   * The layer editor.
   */
  private final LayerEditor layerEditor;

  /**
   * Creates a new instance.
   *
   * @param modelManager The model manager.
   * @param layerEditor The layer editor.
   */
  LayersTableModel(
      ModelManager modelManager,
      LayerEditor layerEditor
  ) {
    this.modelManager = requireNonNull(modelManager, "modelManager");
    this.layerEditor = requireNonNull(layerEditor, "layerEditor");
  }

  @Override
  public int getRowCount() {
    return getLayers().size();
  }

  @Override
  public int getColumnCount() {
    return COLUMN_NAMES.length;
  }

  @Override
  public Object getValueAt(int rowIndex, int columnIndex) {
    if (rowIndex < 0 || rowIndex >= getRowCount()) {
      return null;
    }

    Layer entry = getLayers().get(rowIndex);
    switch (columnIndex) {
      case COLUMN_ORDINAL:
        return entry.getOrdinal();
      case COLUMN_VISIBLE:
        return entry.isVisible();
      case COLUMN_NAME:
        return entry.getName();
      case COLUMN_GROUP:
        return getLayerGroups().get(entry.getGroupId());
      case COLUMN_GROUP_VISIBLE:
        return getLayerGroups().get(entry.getGroupId()).isVisible();
      default:
        throw new IllegalArgumentException("Invalid column index: " + columnIndex);
    }
  }

  @Override
  public String getColumnName(int columnIndex) {
    return COLUMN_NAMES[columnIndex];
  }

  @Override
  public Class getColumnClass(int columnIndex) {
    return COLUMN_CLASSES[columnIndex];
  }

  @Override
  public boolean isCellEditable(int rowIndex, int columnIndex) {
    switch (columnIndex) {
      case COLUMN_ORDINAL:
        return false;
      case COLUMN_VISIBLE:
        return true;
      case COLUMN_NAME:
        return false;
      case COLUMN_GROUP:
        return false;
      case COLUMN_GROUP_VISIBLE:
        return false;
      default:
        throw new IllegalArgumentException("Invalid column index: " + columnIndex);
    }
  }

  @Override
  public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
    if (rowIndex < 0 || rowIndex >= getRowCount()) {
      return;
    }

    if (aValue == null) {
      return;
    }

    Layer entry = getLayers().get(rowIndex);
    switch (columnIndex) {
      case COLUMN_ORDINAL:
        // Do nothing.
        break;
      case COLUMN_VISIBLE:
        layerEditor.setLayerVisible(entry.getId(), (boolean) aValue);
        break;
      case COLUMN_NAME:
        // Do nothing.
        break;
      case COLUMN_GROUP:
        // Do nothing.
        break;
      case COLUMN_GROUP_VISIBLE:
        // Do nothing.
        break;
      default:
        throw new IllegalArgumentException("Invalid column index: " + columnIndex);
    }
  }

  @Override
  public void layersInitialized() {
    // Once the layers are initialized we want to redraw the entire table to avoid any
    // display errors.
    executeOnEventDispatcherThread(() -> fireTableDataChanged());
  }

  @Override
  public void layersChanged() {
    // Update the entire table but don't use fireTableDataChanged() to preserve the current
    // selection.
    executeOnEventDispatcherThread(() -> fireTableRowsUpdated(0, getRowCount() - 1));
  }

  @Override
  public void layerAdded() {
  }

  @Override
  public void layerRemoved() {
  }

  @Override
  public void groupsInitialized() {
  }

  @Override
  public void groupsChanged() {
    // The visibility of a group, which we display as well, may have changed. Update the table.
    executeOnEventDispatcherThread(() -> fireTableRowsUpdated(0, getRowCount() - 1));
  }

  @Override
  public void groupAdded() {
  }

  @Override
  public void groupRemoved() {
  }

  private List getLayers() {
    return getLayerWrappers().values().stream()
        .map(wrapper -> wrapper.getLayer())
        .collect(Collectors.toList());
  }

  private Map getLayerWrappers() {
    return modelManager.getModel().getLayoutModel().getPropertyLayerWrappers().getValue();
  }

  private Map getLayerGroups() {
    return modelManager.getModel().getLayoutModel().getPropertyLayerGroups().getValue();
  }

  /**
   * Ensures the given runnable is executed on the EDT.
   * If the runnable is already being called on the EDT, the runnable is executed immediately.
   * Otherwise it is scheduled for execution on the EDT.
   * 

* Note: Deferring a runnable by scheduling it for execution on the EDT even though it would * have already been executed on the EDT may lead to exceptions due to data inconsistency. *

* * @param runnable The runnable. */ private void executeOnEventDispatcherThread(Runnable runnable) { if (SwingUtilities.isEventDispatchThread()) { runnable.run(); } else { SwingUtilities.invokeLater(runnable); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy