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 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 mouseReleased(MouseEvent e) {
            // Here we override default behavior of mouseReleased to add implementation of
            // row selection by right-click before popup is shown.
            // Also we keep selection when user clicked outside rows to be
            // consistent with IDE behavior
            if (e.getButton() == MouseEvent.BUTTON3) {
                int r = rowAtPoint(e.getPoint());
                boolean isSelectionClicked = ArrayUtil.indexOf(getSelectedRows(), r) >= 0;

                if (!isSelectionClicked && r >= 0 && r < getRowCount()) {
                    setRowSelectionInterval(r, r);
                }
            }

            // And finally we can show handle popup
            super.mouseReleased(e);
        }


        @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);
        }
    }
}
@@ -448,16 +448,38 @@
 lable;%0A%0A
+import javax.swing.*;%0A
 import j
@@ -2667,29 +2667,28 @@
 c void mouse
-Relea
+Pres
 sed(MouseEve
@@ -2711,329 +2711,652 @@
     
-// Here we override default behavior of mouseReleased to add implementation of%0A            // row selection by right-click before popup is shown.%0A            // Also we keep selection when user clicked outside rows to be%0A            // consistent with IDE behavior%0A            if (e.getButton() == MouseEvent.BUTTON3) %7B%0A 
+handleRightClick(e);%0A            super.mousePressed(e);%0A        %7D%0A%0A        @Override%0A        public void mouseReleased(MouseEvent e) %7B%0A            handleRightClick(e);%0A            super.mouseReleased(e);%0A        %7D%0A%0A        private void handleRightClick(MouseEvent e) %7B%0A            if (!SwingUtilities.isRightMouseButton(e) %7C%7C !e.isPopupTrigger())%0A                return;%0A%0A            // Before showing the popup, we should update selection properly:%0A            //  * if right-clicked on existing selection - do nothing.%0A            //  * if clicked outside current selection - clear it and select%0A            //    only item that was clicked.%0A
     
@@ -3367,16 +3367,27 @@
     
-   
 int 
-r
+clickedRowIndex
  = r
@@ -3423,20 +3423,16 @@
         
-    
 boolean 
@@ -3451,16 +3451,36 @@
 licked =
+%0A                   
  ArrayUt
@@ -3509,17 +3509,31 @@
 Rows(), 
-r
+clickedRowIndex
 ) %3E= 0;%0A
@@ -3533,20 +3533,16 @@
  %3E= 0;%0A%0A
-    
         
@@ -3576,19 +3576,67 @@
  && 
-r %3E= 0 && r
+clickedRowIndex %3E= 0 &&%0A                    clickedRowIndex
  %3C g
@@ -3667,20 +3667,16 @@
         
-   
- 
 setRowSe
@@ -3695,135 +3695,56 @@
 val(
-r, r);%0A                %7D%0A            %7D%0A%0A            // And finally we can show handle popup%0A            super.mouseReleased(e);
+clickedRowIndex, clickedRowIndex);%0A            %7D
 %0A   
@@ -3747,25 +3747,24 @@
 %0A        %7D%0A%0A
-%0A
         @Ove

Update selection on right-click before popup menu is shown