Package org.sylfra.idea.plugins.revu.ui.forms.review.referential

Source Code of org.sylfra.idea.plugins.revu.ui.forms.review.referential.AbstractReferentialForm$ReferentialColumnInfo

package org.sylfra.idea.plugins.revu.ui.forms.review.referential;

import com.intellij.openapi.project.Project;
import com.intellij.ui.TableUtil;
import com.intellij.ui.table.TableView;
import com.intellij.util.ui.ColumnInfo;
import com.intellij.util.ui.ListTableModel;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.sylfra.idea.plugins.revu.RevuBundle;
import org.sylfra.idea.plugins.revu.model.IRevuEntity;
import org.sylfra.idea.plugins.revu.model.Review;
import org.sylfra.idea.plugins.revu.model.User;
import org.sylfra.idea.plugins.revu.ui.forms.AbstractUpdatableForm;
import org.sylfra.idea.plugins.revu.utils.RevuUtils;

import javax.swing.*;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.TableCellRenderer;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.List;

/**
* @author <a href="mailto:syllant@gmail.com">Sylvain FRANCOIS</a>
* @version $Id$
*/
public abstract class AbstractReferentialForm<T extends IRevuEntity<T>>
  extends AbstractUpdatableForm<ReferentialListHolder<T>>
{
  private final Project project;
  private JPanel contentPane;
  protected TableView<T> table;
  private List<AbstractTableAction<T>> actions;

  protected AbstractReferentialForm(@NotNull Project project)
  {
    this.project = project;
    buildUI();
  }

  private void buildUI()
  {
    createTable();

    actions = buildActions(buildDetailDialogFactory());
    JPanel pnButtons = createButtonsPanel(actions);

    // Used for error icon
    JLabel label = new JLabel("");
    label.setLabelFor(table);
   
    contentPane = new JPanel(new BorderLayout());
    contentPane.add(new JScrollPane(table), BorderLayout.CENTER);
    contentPane.add(pnButtons, BorderLayout.EAST);
    contentPane.add(label, BorderLayout.WEST);
  }

  protected java.util.List<AbstractTableAction<T>> buildActions(IDetailDialogFactory<T> detailDialogFactory)
  {
    java.util.List<AbstractTableAction<T>> result = new ArrayList<AbstractTableAction<T>>();

    AbstractTableAction<T> action = new AddAction<T>(table, detailDialogFactory);
    addUpdatableFormListener(action);
    result.add(action);

    action = new EditAction<T>(table, detailDialogFactory);
    addUpdatableFormListener(action);
    result.add(action);

    action = new RemoveAction<T>(table);
    addUpdatableFormListener(action);
    result.add(action);

    if (isTableSelectionMovable())
    {
      result.add(null);

      action = new MoveUpAction<T>(table);
      addUpdatableFormListener(action);
      result.add(action);

      action = new MoveDownAction<T>(table);
      addUpdatableFormListener(action);
      result.add(action);
    }

    return result;
  }

  protected abstract boolean isTableSelectionMovable();
  protected abstract IDetailDialogFactory<T> buildDetailDialogFactory();

  private JPanel createButtonsPanel(java.util.List<AbstractTableAction<T>> actions)
  {
    JPanel pnButtons = new JPanel();
    pnButtons.setLayout(new BoxLayout(pnButtons, BoxLayout.Y_AXIS));
    pnButtons.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));

    for (Action action : actions)
    {
      if (action == null)
      {
        JPanel separator = new JPanel();
        separator.setMaximumSize(new Dimension(Short.MAX_VALUE, 10));
        pnButtons.add(separator);
      }
      else
      {
        JButton button = new JButton(action);
        button.setMaximumSize(new Dimension(Short.MAX_VALUE, button.getPreferredSize().height));
        pnButtons.add(button);
      }
    }

    return pnButtons;
  }

  private void createTable()
  {
    ReferentialColumnInfo<T, ?>[] columnInfos = buildColumnInfos();
    for (ReferentialColumnInfo<T, ?> columnInfo : columnInfos)
    {
      addUpdatableFormListener(columnInfo);
    }

    table = new TableView<T>(new ListTableModel<T>(columnInfos))
    {
      @Override
      public TableCellRenderer getCellRenderer(int row, int column)
      {
        // Hum, why getCustomizedRenderer is not automatically called by TableView ?
        ColumnInfo columnInfo = getListTableModel().getColumnInfos()[convertColumnIndexToModel(column)];
        return columnInfo.getCustomizedRenderer(getListTableModel().getItems().get(row),
          super.getCellRenderer(row, column));
      }
    };
  }

  protected abstract ReferentialColumnInfo<T, ?>[] buildColumnInfos();

  public boolean isModified(@NotNull ReferentialListHolder<T> data)
  {
    List<T> items = new ArrayList<T>(table.getListTableModel().getItems());
    if (data.getLinkedItems() != null)
    {
      List<T> linkedItems = new ArrayList<T>(data.getLinkedItems());
      linkedItems.removeAll(data.getItems());
      items.removeAll(linkedItems);
    }
   
    return !items.equals(data.getItems());
  }

  protected void internalValidateInput(@Nullable ReferentialListHolder<T> data)
  {
  }

  protected void internalUpdateUI(ReferentialListHolder<T> data, boolean requestFocus)
  {
    List<T> items;
    if (data == null)
    {
      items = new ArrayList<T>();
    }
    else
    {
      items = new ArrayList<T>(data.getAllItems().size());
      for (T item : data.getAllItems())
      {
        items.add(item.clone());
      }
    }
   
    table.getListTableModel().setItems(items);
// @TODO
//    for (AbstractTableAction<T> action : actions)
//    {
//      if (action != null)
//      {
//        action.checkEnabled();
//      }
//    }
  }

  protected void internalUpdateData(@NotNull ReferentialListHolder<T> data)
  {
    List<T> items = new ArrayList<T>(table.getListTableModel().getItems());
    if (data.getLinkedItems() != null)
    {
      List<T> linkedItems = new ArrayList<T>(data.getLinkedItems());
      linkedItems.removeAll(data.getItems());
      items.removeAll(linkedItems);
    }
   
    data.setItems(items);
  }

  @Override
  protected void internalUpdateWriteAccess(ReferentialListHolder<T> data, @Nullable User user)
  {
  }

  public JComponent getPreferredFocusedComponent()
  {
    return table;
  }

  @NotNull
  public JPanel getContentPane()
  {
    return contentPane;
  }

  protected static interface IDetailDialogFactory<T extends IRevuEntity<T>>
  {
    @NotNull AbstractDetailDialog<T> createDialog();
  }

  protected static abstract class AbstractTableAction<T extends IRevuEntity> extends AbstractAction
    implements UpdatableFormListener<ReferentialListHolder<T>>
  {
    protected Review enclosingReview;
    protected ReferentialListHolder<T> referentialListHolder;
    protected final TableView<T> table;
    private User currentUser;

    protected AbstractTableAction(String name, TableView<T> table)
    {
      super(name);
      this.table = table;
      table.getSelectionModel().addListSelectionListener(new ListSelectionListener()
      {
        public void valueChanged(ListSelectionEvent e)
        {
          checkEnabled();
        }
      });
      checkEnabled();
    }

    public void checkEnabled()
    {
      setEnabled((currentUser != null) && (currentUser.hasRole(User.Role.ADMIN)) && isEnabledForSelection());
    }

    protected boolean isFromLinkedReferential()
    {
      if ((referentialListHolder == null) || (referentialListHolder.getLinkedItems() == null))
      {
        return false;
      }

      for (T item : table.getSelection())
      {
        if (referentialListHolder.getLinkedItems().contains(item))
        {
          return true;
        }
      }

      return false;
    }

    public void uiUpdated(Review enclosingReview, @Nullable ReferentialListHolder<T> data)
    {
      this.enclosingReview = enclosingReview;
      currentUser = RevuUtils.getCurrentUser(enclosingReview);
      referentialListHolder = data;

      checkEnabled();
    }

    public void dataUpdated(@NotNull ReferentialListHolder<T> data)
    {
    }

    protected abstract boolean isEnabledForSelection();
  }

  protected static abstract class AbstractDialogTableAction<T extends IRevuEntity<T>> extends AbstractTableAction<T>
  {
    protected final IDetailDialogFactory<T> detailDialogFactory;

    protected AbstractDialogTableAction(String name, TableView<T> table, IDetailDialogFactory<T> detailDialogFactory)
    {
      super(name, table);
      this.detailDialogFactory = detailDialogFactory;
    }

    protected void showDialog(T data)
    {
      AbstractDetailDialog<T> dialog = detailDialogFactory.createDialog();
      dialog.show(enclosingReview, data);
      if (dialog.isOK())
      {
        // Not very optimized, but this is what IDEA seems to use to update ListTableModel items
        // com.intellij.profile.codeInspection.ui.ProjectProfileConfigurable.MyTableModel.addRow()
        java.util.List<T> items = new ArrayList<T>(table.getListTableModel().getItems());
        T editedData = updateItems(dialog, items);
        table.getListTableModel().setItems(items);

        table.clearSelection();
        table.addSelection(editedData);
      }
    }

    protected abstract T updateItems(AbstractDetailDialog<T> dialog, java.util.List<T> items);
  }

  private static final class AddAction<T extends IRevuEntity<T>> extends AbstractDialogTableAction<T>
  {
    private AddAction(TableView<T> table, IDetailDialogFactory<T> detailDialogFactory)
    {
      super(RevuBundle.message("general.add.action"), table, detailDialogFactory);
    }

    public void actionPerformed(ActionEvent e)
    {
      showDialog(null);
    }

    protected T updateItems(AbstractDetailDialog<T> dialog, List<T> items)
    {
      T data = dialog.getData();
      items.add(data);

      return data;
    }

    protected boolean isEnabledForSelection()
    {
      return true;
    }
  }

  private static final class EditAction<T extends IRevuEntity<T>> extends AbstractDialogTableAction<T>
  {
    private EditAction(TableView<T> table, IDetailDialogFactory<T> detailDialogFactory)
    {
      super(RevuBundle.message("general.edit.action"), table, detailDialogFactory);
      table.addMouseListener(new MouseAdapter()
      {
        @Override
        public void mouseClicked(MouseEvent e)
        {
          if ((isEnabled()) && (e.getClickCount() == 2))
          {
            actionPerformed(null);
          }
        }
      });
    }

    public void actionPerformed(ActionEvent e)
    {
      showDialog(table.getSelectedObject());
    }

    protected T updateItems(AbstractDetailDialog<T> dialog, List<T> items)
    {
      T currentData = table.getSelectedObject();
      T newData = dialog.getData();
      items.set(items.indexOf(currentData), newData);

      return newData;
    }

    protected boolean isEnabledForSelection()
    {
      return ((!isFromLinkedReferential()) && (table.getSelectedRow() > -1));
    }
  }

  private static final class RemoveAction<T extends IRevuEntity> extends AbstractTableAction<T>
  {
    private RemoveAction(TableView<T> table)
    {
      super(RevuBundle.message("general.remove.action"), table);
    }

    public void actionPerformed(ActionEvent e)
    {
      TableUtil.removeSelectedItems(table);
    }

    protected boolean isEnabledForSelection()
    {
      return ((!isFromLinkedReferential()) && (table.getSelectedRow() > -1));
    }
  }

  private static abstract class AbstractMoveTableAction<T extends IRevuEntity> extends AbstractTableAction<T>
  {
    protected AbstractMoveTableAction(String name, TableView<T> table)
    {
      super(name, table);
    }

    protected void move(int offset)
    {
      // Not very optimized, but this is what IDEA seems to use to update ListTableModel items
      java.util.List<T> items = new ArrayList<T>(table.getListTableModel().getItems());
      T currentObject = table.getSelectedObject();
      T otherObject = items.get(table.getSelectedRow() + offset);
      items.set(table.getSelectedRow(), otherObject);
      items.set(table.getSelectedRow() + offset, currentObject);
      table.getListTableModel().setItems(items);

      table.clearSelection();
      table.addSelection(currentObject);
    }
  }

  private static final class MoveUpAction<T extends IRevuEntity> extends AbstractMoveTableAction<T>
  {
    private MoveUpAction(TableView<T> table)
    {
      super(RevuBundle.message("general.moveUp.action"), table);
    }

    public void actionPerformed(ActionEvent e)
    {
      move(-1);
    }

    protected boolean isEnabledForSelection()
    {
      return ((!isFromLinkedReferential()) && (table.getSelectedRow() > 0));
    }
  }

  private static final class MoveDownAction<T extends IRevuEntity> extends AbstractMoveTableAction<T>
  {
    private MoveDownAction(TableView<T> table)
    {
      super(RevuBundle.message("general.moveDown.action"), table);
    }

    public void actionPerformed(ActionEvent e)
    {
      move(1);
    }

    protected boolean isEnabledForSelection()
    {
      return ((!isFromLinkedReferential())
        && (table.getSelectedRow() > -1) && (table.getSelectedRow() < table.getRowCount() - 1));
    }
  }

  protected abstract static class ReferentialColumnInfo<Item extends IRevuEntity, Aspect>
    extends ColumnInfo<Item, Aspect> implements UpdatableFormListener<ReferentialListHolder<Item>>
  {
    private ReferentialListHolder<Item> referentialListHolder;

    public ReferentialColumnInfo(String name)
    {
      super(name);
    }

    @Override
    public TableCellRenderer getCustomizedRenderer(final Item item, final TableCellRenderer renderer)
    {
      if (renderer == null)
      {
        return null;
      }
     
      return new TableCellRenderer()
      {
        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus,
          int row, int column)
        {
          Component result = renderer.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
          if ((referentialListHolder != null)
            && ((referentialListHolder.getLinkedItems() != null)
            && (referentialListHolder.getLinkedItems().contains(item))
            && (!referentialListHolder.getItems().contains(item))))
          {
            result.setForeground(UIUtil.getInactiveTextColor());
          }
          else
          {
            result.setForeground(UIUtil.getActiveTextColor());
          }

          return result;
        }
      };
    }

    public void uiUpdated(Review enclosingReview, @Nullable ReferentialListHolder<Item> data)
    {
      this.referentialListHolder = data;
    }

    public void dataUpdated(@NotNull ReferentialListHolder<Item> data)
    {
    }
  }
}
TOP

Related Classes of org.sylfra.idea.plugins.revu.ui.forms.review.referential.AbstractReferentialForm$ReferentialColumnInfo

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.