| /* |
| * Copyright 2000-2014 JetBrains s.r.o. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package com.intellij.uiDesigner.designSurface; |
| |
| import com.intellij.ide.DeleteProvider; |
| import com.intellij.ide.dnd.*; |
| import com.intellij.openapi.actionSystem.*; |
| import com.intellij.openapi.diagnostic.Logger; |
| import com.intellij.openapi.editor.colors.EditorColors; |
| import com.intellij.openapi.editor.colors.EditorColorsManager; |
| import com.intellij.openapi.util.Pair; |
| import com.intellij.ui.JBColor; |
| import com.intellij.ui.LightColors; |
| import com.intellij.uiDesigner.CaptionSelection; |
| import com.intellij.uiDesigner.FormEditingUtil; |
| import com.intellij.uiDesigner.GridChangeUtil; |
| import com.intellij.uiDesigner.GuiDesignerConfiguration; |
| import com.intellij.uiDesigner.componentTree.ComponentSelectionListener; |
| import com.intellij.uiDesigner.radComponents.RadAbstractGridLayoutManager; |
| import com.intellij.uiDesigner.radComponents.RadComponent; |
| import com.intellij.uiDesigner.radComponents.RadContainer; |
| import com.intellij.uiDesigner.radComponents.RadRootContainer; |
| import com.intellij.util.Alarm; |
| import com.intellij.util.ArrayUtil; |
| import com.intellij.util.NotNullProducer; |
| import com.intellij.util.ui.PlatformColors; |
| import com.intellij.util.ui.UIUtil; |
| import org.jetbrains.annotations.NotNull; |
| import org.jetbrains.annotations.Nullable; |
| |
| import javax.swing.*; |
| import javax.swing.event.ChangeEvent; |
| import javax.swing.event.ChangeListener; |
| import javax.swing.event.ListSelectionEvent; |
| import javax.swing.event.ListSelectionListener; |
| import java.awt.*; |
| import java.awt.event.*; |
| import java.util.ArrayList; |
| |
| /** |
| * @author yole |
| */ |
| public class GridCaptionPanel extends JPanel implements ComponentSelectionListener, DataProvider { |
| private static final Logger LOG = Logger.getInstance("#com.intellij.uiDesigner.designSurface.GridCaptionPanel"); |
| |
| private final GuiEditor myEditor; |
| private final boolean myIsRow; |
| private RadContainer mySelectedContainer; |
| private final DefaultListSelectionModel mySelectionModel = new DefaultListSelectionModel(); |
| private int myResizeLine = -1; |
| private int myDropInsertLine = -1; |
| private final LineFeedbackPainter myFeedbackPainter = new LineFeedbackPainter(); |
| private final DeleteProvider myDeleteProvider = new MyDeleteProvider(); |
| private final Alarm myAlarm = new Alarm(); |
| |
| public GridCaptionPanel(final GuiEditor editor, final boolean isRow) { |
| myEditor = editor; |
| myIsRow = isRow; |
| mySelectionModel.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); |
| mySelectionModel.addListSelectionListener(new ListSelectionListener() { |
| public void valueChanged(ListSelectionEvent e) { |
| repaint(); |
| myEditor.fireSelectedComponentChanged(); |
| } |
| }); |
| setBackground(getGutterColor()); |
| editor.addComponentSelectionListener(this); |
| |
| final MyMouseListener listener = new MyMouseListener(); |
| addMouseListener(listener); |
| addMouseMotionListener(listener); |
| addKeyListener(new MyKeyListener()); |
| setFocusable(true); |
| |
| DnDManager.getInstance().registerSource(new MyDnDSource(), this); |
| DnDManager.getInstance().registerTarget(new MyDnDTarget(), this); |
| |
| addFocusListener(new FocusAdapter() { |
| @Override public void focusGained(FocusEvent e) { |
| repaint(); |
| // ensure we don't have two repaints of properties panel - one from focus gain and another from click |
| myAlarm.addRequest(new Runnable() { |
| public void run() { |
| editor.fireSelectedComponentChanged(); |
| } |
| }, 1000); |
| } |
| |
| @Override public void focusLost(FocusEvent e) { |
| repaint(); |
| } |
| }); |
| } |
| |
| public static JBColor getGutterColor() { |
| return new JBColor(new NotNullProducer<Color>() { |
| @NotNull |
| @Override |
| public Color produce() { |
| Color color = EditorColorsManager.getInstance().getGlobalScheme().getColor(EditorColors.GUTTER_BACKGROUND); |
| return color == null ? UIUtil.getPanelBackground() : color; |
| } |
| }); |
| } |
| |
| public RadContainer getSelectedContainer() { |
| // when the selected component changes, and we have focus, PropertyInspector asks us about our container and selection. |
| // PropertyInspector's selection changed listener can be called before our own listener, so we need to update ourselves |
| // so that we don't return stale and invalid data. |
| checkSelectionChanged(); |
| return mySelectedContainer; |
| } |
| |
| public boolean isRow() { |
| return myIsRow; |
| } |
| |
| @Override public Dimension getPreferredSize() { |
| return new Dimension(16, 16); |
| } |
| |
| @Override |
| public Dimension getMinimumSize() { |
| return getPreferredSize(); |
| } |
| |
| @Override public void paintComponent(Graphics g) { |
| super.paintComponent(g); |
| Graphics2D g2d = (Graphics2D) g; |
| |
| final Rectangle bounds = getBounds(); |
| final int paintedSize = 8; |
| final int paintOffset = 7; |
| |
| RadContainer container = getSelectedGridContainer(); |
| if (container == null) { |
| return; |
| } |
| RadAbstractGridLayoutManager layout = container.getGridLayoutManager(); |
| int[] coords = layout.getGridCellCoords(container, myIsRow); |
| int[] sizes = layout.getGridCellSizes(container, myIsRow); |
| int count = myIsRow ? layout.getGridRowCount(container) : layout.getGridColumnCount(container); |
| |
| for(int i=0; i<count; i++) { |
| int x = myIsRow ? 0 : coords [i]; |
| int y = myIsRow ? coords [i] : 0; |
| Point pnt = SwingUtilities.convertPoint(container.getDelegee(), x, y, this); |
| |
| Rectangle rc = myIsRow |
| ? new Rectangle(bounds.x+paintOffset, pnt.y, paintedSize, sizes [i]) |
| : new Rectangle(pnt.x, bounds.y+paintOffset, sizes [i], paintedSize); |
| |
| g.setColor(getCaptionColor(i)); |
| g.fillRect(rc.x, rc.y, rc.width, rc.height); |
| |
| Rectangle rcDecoration = myIsRow |
| ? new Rectangle(bounds.x, pnt.y, bounds.width, sizes [i]) |
| : new Rectangle(pnt.x, bounds.y, sizes [i], bounds.height); |
| layout.paintCaptionDecoration(container, myIsRow, i, g2d, rcDecoration); |
| |
| Stroke oldStroke = g2d.getStroke(); |
| int deltaX = 0; |
| int deltaY = 0; |
| if (isFocusOwner() && i == mySelectionModel.getLeadSelectionIndex()) { |
| g.setColor(Color.BLACK); |
| g2d.setStroke(new BasicStroke(2.0f)); |
| deltaX = myIsRow ? 1 : 0; |
| deltaY = myIsRow ? 0 : 1; |
| } |
| else { |
| g.setColor(Color.DARK_GRAY); |
| } |
| g.drawRect(rc.x + deltaX, rc.y + deltaY, rc.width - deltaX, rc.height - deltaY); |
| g2d.setStroke(oldStroke); |
| } |
| |
| g.setColor(Color.DARK_GRAY); |
| if (myIsRow) { |
| g.drawLine(paintOffset+paintedSize, 0, paintOffset+paintedSize, bounds.height); |
| } |
| else { |
| g.drawLine(0, paintOffset+paintedSize, bounds.width, paintOffset+paintedSize); |
| } |
| |
| if (myDropInsertLine >= 0) { |
| int[] lines = myIsRow ? layout.getHorizontalGridLines(container) : layout.getVerticalGridLines(container); |
| int coord = lines [myDropInsertLine]; |
| if (myIsRow) { |
| coord = SwingUtilities.convertPoint(container.getDelegee(), 0, coord, this).y; |
| } |
| else { |
| coord = SwingUtilities.convertPoint(container.getDelegee(), coord, 0, this).x; |
| } |
| Stroke oldStroke = g2d.getStroke(); |
| g2d.setStroke(new BasicStroke(2.0f)); |
| g.setColor(PlatformColors.BLUE); |
| if (myIsRow) { |
| g.drawLine(bounds.x+1, coord, bounds.x+bounds.width-1, coord); |
| } |
| else { |
| g.drawLine(coord, bounds.y+1, coord, bounds.y+bounds.height-1); |
| } |
| |
| g2d.setStroke(oldStroke); |
| } |
| |
| } |
| |
| private Color getCaptionColor(final int i) { |
| if (mySelectionModel.isSelectedIndex(i)) { |
| return LightColors.BLUE; |
| } |
| if (mySelectedContainer != null) { |
| if (i >= 0 && i < mySelectedContainer.getGridCellCount(myIsRow)) { |
| final GridChangeUtil.CellStatus status = GridChangeUtil.canDeleteCell(mySelectedContainer, i, myIsRow); |
| if (status == GridChangeUtil.CellStatus.Empty || status == GridChangeUtil.CellStatus.Redundant) { |
| return Color.PINK; |
| } |
| } |
| } |
| return LightColors.GREEN; |
| } |
| |
| @Nullable private RadContainer getSelectedGridContainer() { |
| final ArrayList<RadComponent> selection = FormEditingUtil.getSelectedComponents(myEditor); |
| if (selection.size() == 1 && selection.get(0) instanceof RadContainer) { |
| RadContainer container = (RadContainer) selection.get(0); |
| if (container.getLayoutManager().isGrid() && (container.getParent() instanceof RadRootContainer || container.getComponentCount() > 0)) { |
| return container; |
| } |
| } |
| RadContainer container = FormEditingUtil.getSelectionParent(selection); |
| if (container == null && myEditor.getRootContainer().getComponentCount() > 0) { |
| final RadComponent topComponent = myEditor.getRootContainer().getComponent(0); |
| if (topComponent instanceof RadContainer) { |
| container = (RadContainer) topComponent; |
| } |
| } |
| if (container != null && !container.getLayoutManager().isGrid()) { |
| return null; |
| } |
| return container; |
| } |
| |
| public void selectedComponentChanged(GuiEditor source) { |
| checkSelectionChanged(); |
| repaint(); |
| } |
| |
| private void checkSelectionChanged() { |
| RadContainer container = getSelectedGridContainer(); |
| if (container != mySelectedContainer) { |
| mySelectedContainer = container; |
| mySelectionModel.clearSelection(); |
| repaint(); |
| } |
| } |
| |
| @Nullable public Object getData(String dataId) { |
| if (GuiEditor.DATA_KEY.is(dataId)) { |
| return myEditor; |
| } |
| if (CaptionSelection.DATA_KEY.is(dataId)) { |
| return new CaptionSelection(mySelectedContainer, myIsRow, getSelectedCells(null), mySelectionModel.getLeadSelectionIndex()); |
| } |
| if (PlatformDataKeys.DELETE_ELEMENT_PROVIDER.is(dataId)) { |
| return myDeleteProvider; |
| } |
| return myEditor.getData(dataId); |
| } |
| |
| public void attachToScrollPane(final JScrollPane scrollPane) { |
| scrollPane.getViewport().addChangeListener(new ChangeListener() { |
| public void stateChanged(ChangeEvent e) { |
| repaint(); |
| } |
| }); |
| } |
| |
| private boolean canResizeCells() { |
| return GuiDesignerConfiguration.getInstance(myEditor.getProject()).RESIZE_HEADERS && |
| mySelectedContainer != null && |
| mySelectedContainer.getGridLayoutManager().canResizeCells(); |
| } |
| |
| private int getCellAt(Point pnt) { |
| if (mySelectedContainer == null) return -1; |
| pnt = SwingUtilities.convertPoint(this, pnt, mySelectedContainer.getDelegee()); |
| return myIsRow ? mySelectedContainer.getGridRowAt(pnt.y) : mySelectedContainer.getGridColumnAt(pnt.x); |
| } |
| |
| public int[] getSelectedCells(@Nullable final Point dragOrigin) { |
| ArrayList<Integer> selection = new ArrayList<Integer>(); |
| RadContainer container = getSelectedGridContainer(); |
| if (container == null) { |
| return ArrayUtil.EMPTY_INT_ARRAY; |
| } |
| int size = getCellCount(); |
| for(int i=0; i<size; i++) { |
| if (mySelectionModel.isSelectedIndex(i)) { |
| selection.add(i); |
| } |
| } |
| if (selection.size() == 0 && dragOrigin != null) { |
| int cell = getCellAt(dragOrigin); |
| if (cell >= 0) { |
| return new int[] { cell }; |
| } |
| } |
| int[] result = new int[selection.size()]; |
| for(int i=0; i<selection.size(); i++) { |
| result [i] = selection.get(i).intValue(); |
| } |
| return result; |
| } |
| |
| private int getCellCount() { |
| final RadContainer gridContainer = getSelectedGridContainer(); |
| assert gridContainer != null; |
| return myIsRow ? gridContainer.getGridRowCount() : gridContainer.getGridColumnCount(); |
| } |
| |
| private class MyMouseListener extends MouseAdapter implements MouseMotionListener { |
| private static final int MINIMUM_RESIZED_SIZE = 8; |
| |
| @Override public void mouseExited(MouseEvent e) { |
| setCursor(Cursor.getDefaultCursor()); |
| } |
| |
| @Override public void mousePressed(MouseEvent e) { |
| if (mySelectedContainer == null) return; |
| requestFocus(); |
| Point pnt = SwingUtilities.convertPoint(GridCaptionPanel.this, e.getPoint(), |
| mySelectedContainer.getDelegee()); |
| if (canResizeCells()) { |
| myResizeLine = mySelectedContainer.getGridLayoutManager().getGridLineNear(mySelectedContainer, myIsRow, pnt, 4); |
| } |
| if (!checkShowPopupMenu(e)) { |
| int cell = getCellAt(e.getPoint()); |
| if (cell == -1) return; |
| if ((e.getModifiers() & MouseEvent.CTRL_MASK) != 0) { |
| mySelectionModel.addSelectionInterval(cell, cell); |
| } |
| else if ((e.getModifiers() & MouseEvent.SHIFT_MASK) != 0) { |
| mySelectionModel.addSelectionInterval(mySelectionModel.getAnchorSelectionIndex(), cell); |
| } |
| } |
| } |
| |
| @Override public void mouseReleased(MouseEvent e) { |
| setCursor(Cursor.getDefaultCursor()); |
| myEditor.getActiveDecorationLayer().removeFeedback(); |
| |
| if (myResizeLine > 0) { |
| Point pnt = SwingUtilities.convertPoint(GridCaptionPanel.this, e.getPoint(), |
| mySelectedContainer.getDelegee()); |
| doResize(pnt); |
| myResizeLine = -1; |
| } |
| |
| if (!checkShowPopupMenu(e)) { |
| int cell = getCellAt(e.getPoint()); |
| if (cell == -1) return; |
| if ((e.getModifiers() & (MouseEvent.CTRL_MASK | MouseEvent.SHIFT_MASK)) == 0) { |
| mySelectionModel.setSelectionInterval(cell, cell); |
| } |
| } |
| } |
| |
| private boolean checkShowPopupMenu(final MouseEvent e) { |
| int cell = getCellAt(e.getPoint()); |
| |
| if (cell >= 0 && e.isPopupTrigger()) { |
| if (!mySelectionModel.isSelectedIndex(cell)) { |
| mySelectionModel.setSelectionInterval(cell, cell); |
| } |
| ActionGroup group = mySelectedContainer.getGridLayoutManager().getCaptionActions(); |
| if (group != null) { |
| final ActionPopupMenu popupMenu = ActionManager.getInstance().createActionPopupMenu(ActionPlaces.UNKNOWN, group); |
| popupMenu.getComponent().show(GridCaptionPanel.this, e.getX(), e.getY()); |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| private void doResize(final Point pnt) { |
| int[] coords = mySelectedContainer.getGridLayoutManager().getGridCellCoords(mySelectedContainer, myIsRow); |
| int prevCoord = coords [myResizeLine-1]; |
| int newCoord = myIsRow ? pnt.y : pnt.x; |
| if (newCoord < prevCoord + MINIMUM_RESIZED_SIZE) { |
| return; |
| } |
| int newSize = newCoord - prevCoord; |
| |
| if (!myEditor.ensureEditable()) { |
| return; |
| } |
| |
| mySelectedContainer.getGridLayoutManager().processCellResized(mySelectedContainer, myIsRow, myResizeLine-1, newSize); |
| mySelectedContainer.revalidate(); |
| myEditor.refreshAndSave(true); |
| } |
| |
| public void mouseMoved(MouseEvent e) { |
| if (!canResizeCells()) { |
| return; |
| } |
| |
| Point pnt = SwingUtilities.convertPoint(GridCaptionPanel.this, e.getPoint(), |
| mySelectedContainer.getDelegee()); |
| int gridLine = mySelectedContainer.getGridLayoutManager().getGridLineNear(mySelectedContainer, myIsRow, pnt, 4); |
| |
| // first grid line may not be dragged |
| if (gridLine <= 0) { |
| setCursor(Cursor.getDefaultCursor()); |
| } |
| else if (myIsRow) { |
| setCursor(Cursor.getPredefinedCursor(Cursor.N_RESIZE_CURSOR)); |
| } |
| else { |
| setCursor(Cursor.getPredefinedCursor(Cursor.W_RESIZE_CURSOR)); |
| } |
| } |
| |
| public void mouseDragged(MouseEvent e) { |
| if (myResizeLine > 0) { |
| Point pnt = SwingUtilities.convertPoint(GridCaptionPanel.this, e.getPoint(), |
| mySelectedContainer.getDelegee()); |
| int[] coords = mySelectedContainer.getGridLayoutManager().getGridCellCoords(mySelectedContainer, myIsRow); |
| int prevCoord = coords [myResizeLine-1]; |
| int newCoord = myIsRow ? pnt.y : pnt.x; |
| if (newCoord < prevCoord + MINIMUM_RESIZED_SIZE) { |
| return; |
| } |
| int newSize = newCoord - prevCoord; |
| |
| String toolTip = mySelectedContainer.getGridLayoutManager().getCellResizeTooltip(mySelectedContainer, myIsRow, myResizeLine-1, newSize); |
| final ActiveDecorationLayer layer = myEditor.getActiveDecorationLayer(); |
| Rectangle rc; |
| if (myIsRow) { |
| rc = new Rectangle(0, e.getPoint().y, layer.getSize().width, 1); |
| } |
| else { |
| rc = new Rectangle(e.getPoint().x, 0, 1, layer.getSize().height); |
| } |
| layer.putFeedback(GridCaptionPanel.this, rc, myFeedbackPainter, toolTip); |
| } |
| } |
| } |
| |
| private static class LineFeedbackPainter implements FeedbackPainter { |
| public void paintFeedback(Graphics2D g, Rectangle rc) { |
| g.setColor(LightColors.YELLOW); |
| if (rc.width == 1) { |
| g.drawLine(rc.x, rc.y, rc.x, rc.y+rc.height); |
| } |
| else { |
| g.drawLine(rc.x, rc.y, rc.x+rc.width, rc.y); |
| } |
| } |
| } |
| |
| private class MyDeleteProvider implements DeleteProvider { |
| public void deleteElement(@NotNull DataContext dataContext) { |
| int[] selection = getSelectedCells(null); |
| if (selection.length > 0) { |
| FormEditingUtil.deleteRowOrColumn(myEditor, mySelectedContainer, selection, myIsRow); |
| } |
| } |
| |
| public boolean canDeleteElement(@NotNull DataContext dataContext) { |
| if (mySelectedContainer == null || mySelectionModel.isSelectionEmpty()) { |
| return false; |
| } |
| int[] selection = getSelectedCells(null); |
| return mySelectedContainer.getGridCellCount(myIsRow) - selection.length >= mySelectedContainer.getGridLayoutManager().getMinCellCount(); |
| } |
| } |
| |
| private class MyDnDSource implements DnDSource { |
| public boolean canStartDragging(DnDAction action, Point dragOrigin) { |
| LOG.debug("canStartDragging(): dragOrigin=" + dragOrigin); |
| if (myResizeLine != -1) { |
| LOG.debug("canStartDragging(): have resize line"); |
| return false; |
| } |
| RadContainer container = getSelectedGridContainer(); |
| if (container != null && |
| container.getGridLayoutManager().getGridLineNear(mySelectedContainer, myIsRow, dragOrigin, 4) != -1) { |
| LOG.debug("canStartDragging(): have gridline near"); |
| return false; |
| } |
| int[] selectedCells = getSelectedCells(dragOrigin); |
| for(int cell: selectedCells) { |
| if (!canDragCell(cell)) { |
| LOG.debug("canStartDragging(): cannot drag cell"); |
| return false; |
| } |
| } |
| LOG.debug("canStartDragging(): starting drag"); |
| return true; |
| } |
| |
| private boolean canDragCell(final int cell) { |
| if (mySelectedContainer == null) return false; |
| for(RadComponent c: mySelectedContainer.getComponents()) { |
| if (c.getConstraints().contains(myIsRow, cell) && c.getConstraints().getSpan(myIsRow) > 1) { |
| return false; |
| } |
| } |
| return true; |
| } |
| |
| public DnDDragStartBean startDragging(DnDAction action, Point dragOrigin) { |
| return new DnDDragStartBean(new MyDragBean(myIsRow, getSelectedCells(dragOrigin))); |
| } |
| |
| @Nullable |
| public Pair<Image, Point> createDraggedImage(DnDAction action, Point dragOrigin) { |
| return null; |
| } |
| |
| public void dragDropEnd() { |
| } |
| |
| public void dropActionChanged(final int gestureModifiers) { |
| } |
| } |
| |
| private class MyDnDTarget implements DnDTarget { |
| public boolean update(DnDEvent aEvent) { |
| aEvent.setDropPossible(false); |
| if (mySelectedContainer == null) { |
| return false; |
| } |
| if (!(aEvent.getAttachedObject() instanceof MyDragBean)) { |
| return false; |
| } |
| MyDragBean bean = (MyDragBean) aEvent.getAttachedObject(); |
| if (bean.isRow != myIsRow || bean.cells.length == 0) { |
| return false; |
| } |
| int gridLine = getDropGridLine(aEvent); |
| setDropInsertLine(gridLine); |
| aEvent.setDropPossible(gridLine >= 0); |
| if (gridLine >= 0) { |
| FeedbackPainter painter = myIsRow ? HorzInsertFeedbackPainter.INSTANCE : VertInsertFeedbackPainter.INSTANCE; |
| Rectangle rcFeedback = new Rectangle(mySelectedContainer.getDelegee().getSize()); |
| Rectangle cellRect = new Rectangle(gridLine, gridLine, 1, 1); |
| rcFeedback = GridInsertLocation.getInsertFeedbackPosition(myIsRow ? GridInsertMode.RowBefore : GridInsertMode.ColumnBefore, |
| mySelectedContainer, cellRect, rcFeedback); |
| myEditor.getActiveDecorationLayer().putFeedback(mySelectedContainer.getDelegee(), rcFeedback, painter, null); |
| } |
| else { |
| myEditor.getActiveDecorationLayer().removeFeedback(); |
| } |
| return false; |
| } |
| |
| private int getDropGridLine(final DnDEvent aEvent) { |
| final Point point = aEvent.getPointOn(mySelectedContainer.getDelegee()); |
| return mySelectedContainer.getGridLayoutManager().getGridLineNear(mySelectedContainer, myIsRow, point, 20); |
| } |
| |
| public void drop(DnDEvent aEvent) { |
| if (!(aEvent.getAttachedObject() instanceof MyDragBean)) { |
| return; |
| } |
| MyDragBean dragBean = (MyDragBean) aEvent.getAttachedObject(); |
| int targetCell = getDropGridLine(aEvent); |
| if (targetCell < 0) return; |
| mySelectedContainer.getGridLayoutManager().processCellsMoved(mySelectedContainer, myIsRow, dragBean.cells, targetCell); |
| mySelectionModel.clearSelection(); |
| mySelectedContainer.revalidate(); |
| myEditor.refreshAndSave(true); |
| cleanUpOnLeave(); |
| } |
| |
| public void cleanUpOnLeave() { |
| setDropInsertLine(-1); |
| myEditor.getActiveDecorationLayer().removeFeedback(); |
| } |
| |
| public void updateDraggedImage(Image image, Point dropPoint, Point imageOffset) { |
| } |
| |
| private void setDropInsertLine(final int i) { |
| if (myDropInsertLine != i) { |
| myDropInsertLine = i; |
| repaint(); |
| } |
| } |
| } |
| |
| private static class MyDragBean { |
| public boolean isRow; |
| public int[] cells; |
| |
| public MyDragBean(final boolean row, final int[] cells) { |
| isRow = row; |
| this.cells = cells; |
| } |
| } |
| |
| private class MyKeyListener extends KeyAdapter { |
| @Override public void keyPressed(KeyEvent e) { |
| if (e.getKeyCode() == KeyEvent.VK_HOME) { |
| mySelectionModel.setSelectionInterval(0, 0); |
| } |
| else if (e.getKeyCode() == KeyEvent.VK_END) { |
| int cellCount = getCellCount(); |
| mySelectionModel.setSelectionInterval(cellCount-1, cellCount-1); |
| } |
| else if (e.getKeyCode() == (myIsRow ? KeyEvent.VK_UP : KeyEvent.VK_LEFT)) { |
| moveSelection(e, -1); |
| } |
| else if (e.getKeyCode() == (myIsRow ? KeyEvent.VK_DOWN : KeyEvent.VK_RIGHT)) { |
| moveSelection(e, 1); |
| } |
| } |
| |
| private void moveSelection(final KeyEvent e, final int delta) { |
| int leadIndex = mySelectionModel.getLeadSelectionIndex(); |
| int newLeadIndex = leadIndex + delta; |
| if (newLeadIndex >= 0 && newLeadIndex < getCellCount()) { |
| if ((e.getModifiers() & KeyEvent.SHIFT_MASK) != 0) { |
| mySelectionModel.setSelectionInterval(mySelectionModel.getAnchorSelectionIndex(), newLeadIndex); |
| } |
| else { |
| mySelectionModel.setSelectionInterval(newLeadIndex, newLeadIndex); |
| } |
| } |
| } |
| } |
| } |