package net.bitpot.railways.gui; import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.diagnostic.Logger; import com.intellij.ui.PopupHandler; import com.intellij.ui.table.JBTable; import com.intellij.util.ArrayUtil; import net.bitpot.railways.models.Route; import net.bitpot.railways.models.RouteTableModel; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.awt.*; import java.awt.event.MouseEvent; /** * We should add some behavior to default JTable to be able copy custom data. * * Our component (JTable) should implement DataProvider interface. In this * case when action is invoked in context of this component, we will be able to * pass our own data to the action handler. */ public class RoutesTable extends JBTable implements DataProvider { @SuppressWarnings("unused") private static Logger log = Logger.getInstance(RoutesTable.class.getName()); /** * Constructs a default <code>JTable</code> that is initialized with a default * data model, a default column model, and a default selection * model. */ public RoutesTable() { super(); addMouseListener(new MyPopupHandler()); } /** * Method returns custom data object. It's useful for replacing IDE's data providers by custom ones. * * @param dataId Data key * @return Data object. */ @Nullable @Override public Object getData(@NonNls String dataId) { // Good example of usage is in com.intellij.openapi.editor.impl.EditorComponentImpl (see getData method) if (PlatformDataKeys.SELECTED_ITEMS.is(dataId)) return getSelectedRoutes(); if (PlatformDataKeys.SELECTED_ITEM.is(dataId)) return getSelectedRoute(); return null; } @Nullable private Route getSelectedRoute() { int selectedId = convertRowIndexToModel(getSelectedRow()); if (selectedId < 0) return null; return ((RouteTableModel) getModel()).getRoute(selectedId); } @NotNull private Route[] getSelectedRoutes() { RouteTableModel model = (RouteTableModel) getModel(); int[] selectedRows = getSelectedRows(); Route[] selectedRoutes = new Route[selectedRows.length]; for(int i = 0; i < selectedRows.length; i++) { selectedRoutes[i] = model.getRoute(convertRowIndexToModel(selectedRows[i])); } return selectedRoutes; } private class MyPopupHandler extends PopupHandler { @Override public void mousePressed(MouseEvent e) { handleRightClick(e); super.mousePressed(e); } @Override public void mouseReleased(MouseEvent e) { handleRightClick(e); super.mouseReleased(e); } private void handleRightClick(MouseEvent e) { if (!SwingUtilities.isRightMouseButton(e) || !e.isPopupTrigger()) return; // Before showing the popup, we should update selection properly: // * if right-clicked on existing selection - do nothing. // * if clicked outside current selection - clear it and select // only item that was clicked. int clickedRowIndex = rowAtPoint(e.getPoint()); boolean isSelectionClicked = ArrayUtil.indexOf(getSelectedRows(), clickedRowIndex) >= 0; if (!isSelectionClicked && clickedRowIndex >= 0 && clickedRowIndex < getRowCount()) { setRowSelectionInterval(clickedRowIndex, clickedRowIndex); } } @Override public void invokePopup(Component comp, int x, int y) { ActionManager actMgr = ActionManager.getInstance(); ActionGroup group = (ActionGroup) ActionManager.getInstance().getAction("railways.PopupMenu"); ActionPopupMenu popupMenu = actMgr.createActionPopupMenu(ActionPlaces.UNKNOWN, group); popupMenu.getComponent().show(comp, x, y); } } }