| /* |
| * Copyright 2000-2009 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.uiDesigner.CutCopyPasteSupport; |
| import com.intellij.uiDesigner.FormEditingUtil; |
| import com.intellij.uiDesigner.UIDesignerBundle; |
| import com.intellij.uiDesigner.core.GridConstraints; |
| import com.intellij.uiDesigner.core.Util; |
| import com.intellij.uiDesigner.radComponents.RadComponent; |
| import com.intellij.uiDesigner.radComponents.RadContainer; |
| import org.jetbrains.annotations.Nullable; |
| |
| import javax.swing.*; |
| import java.awt.Cursor; |
| import java.awt.Dimension; |
| import java.awt.Point; |
| import java.awt.Rectangle; |
| import java.awt.event.KeyEvent; |
| import java.awt.event.MouseEvent; |
| import java.util.Collections; |
| import java.util.List; |
| |
| /** |
| * @author Anton Katilin |
| * @author Vladimir Kondratyev |
| */ |
| public final class ResizeProcessor extends EventProcessor { |
| private final RadComponent myComponent; |
| private final int myResizeMask; |
| private Point myLastPoint; |
| private Rectangle myBounds; |
| private Rectangle myOriginalBounds; |
| private final RadContainer myOriginalParent; |
| private final GuiEditor myEditor; |
| private final GridConstraints myOriginalConstraints; |
| private RadComponent myResizedCopy; |
| |
| public ResizeProcessor(final GuiEditor editor, final RadComponent component, final int resizeMask){ |
| myEditor = editor; |
| if (component.getParent() == null) { |
| throw new IllegalArgumentException("parent is null for " + component); |
| } |
| |
| myComponent = component; |
| myOriginalParent = component.getParent(); |
| myOriginalConstraints = component.getConstraints(); |
| |
| final List<RadComponent> copyList = CutCopyPasteSupport.copyComponents(editor, Collections.singletonList(component)); |
| if (component.getParent().getLayoutManager().isGrid() && copyList != null) { |
| myComponent.setResizing(true); |
| Rectangle rc = SwingUtilities.convertRectangle(component.getParent().getDelegee(), |
| component.getBounds(), |
| myEditor.getDragLayer()); |
| component.setDragging(true); |
| component.setSelected(false); |
| |
| myResizedCopy = copyList.get(0); |
| myResizedCopy.setBounds(rc); |
| myResizedCopy.setSelected(true); |
| editor.getDragLayer().add(myResizedCopy.getDelegee()); |
| } |
| myResizeMask = resizeMask; |
| |
| setCursor(getResizeCursor()); |
| } |
| |
| protected void processKeyEvent(final KeyEvent e){} |
| |
| protected void processMouseEvent(final MouseEvent e){ |
| if (e.getID() == MouseEvent.MOUSE_PRESSED) { |
| myLastPoint = e.getPoint(); |
| myBounds = myOriginalParent.getLayoutManager().isGrid() ? myResizedCopy.getBounds() : myComponent.getBounds(); |
| myOriginalBounds = new Rectangle(myBounds); |
| } |
| else if(e.getID()==MouseEvent.MOUSE_DRAGGED){ |
| final int dx = e.getX() - myLastPoint.x; |
| final int dy = e.getY() - myLastPoint.y; |
| |
| if (myOriginalParent.getLayoutManager().isGrid()) { |
| final Point point = SwingUtilities.convertPoint(myEditor.getDragLayer(), e.getX(), e.getY(), myOriginalParent.getDelegee()); |
| putGridSpanFeedback(point); |
| } |
| else if (myOriginalParent.isXY()) { |
| myEditor.getActiveDecorationLayer().removeFeedback(); |
| setCursor(getResizeCursor()); |
| } |
| else { |
| return; |
| } |
| |
| final GridConstraints constraints = myComponent.getConstraints(); |
| |
| if ((myResizeMask & Painter.WEST_MASK) != 0) { |
| myBounds.x += dx; |
| myBounds.width -= dx; |
| } |
| if ((myResizeMask & Painter.EAST_MASK) != 0) { |
| myBounds.width += dx; |
| } |
| if ((myResizeMask & Painter.NORTH_MASK) != 0) { |
| myBounds.y += dy; |
| myBounds.height -= dy; |
| } |
| if ((myResizeMask & Painter.SOUTH_MASK) != 0) { |
| myBounds.height += dy; |
| } |
| |
| final Dimension minSize = myComponent.getMinimumSize(); |
| |
| final Rectangle newBounds = myOriginalParent.getLayoutManager().isGrid() ? myResizedCopy.getBounds() : myComponent.getBounds(); |
| |
| // Component's bounds cannot be less the some minimum size |
| if (myBounds.width >= minSize.width) { |
| newBounds.x = myBounds.x; |
| newBounds.width = myBounds.width; |
| } |
| else { |
| if((myResizeMask & Painter.WEST_MASK) != 0){ |
| newBounds.x = newBounds.x+newBounds.width-minSize.width; |
| newBounds.width = minSize.width; |
| } |
| else if ((myResizeMask & Painter.EAST_MASK) != 0) { |
| newBounds.width = minSize.width; |
| } |
| } |
| |
| if (myBounds.height >= minSize.height) { |
| newBounds.y = myBounds.y; |
| newBounds.height = myBounds.height; |
| } |
| else { |
| if ((myResizeMask & Painter.NORTH_MASK) != 0) { |
| newBounds.y = newBounds.y + newBounds.height - minSize.height; |
| newBounds.height = minSize.height; |
| } |
| else if ((myResizeMask & Painter.SOUTH_MASK) != 0) { |
| newBounds.height = minSize.height; |
| } |
| } |
| |
| final Dimension size = newBounds.getSize(); |
| Util.adjustSize(myComponent.getDelegee(), constraints, size); |
| newBounds.width = size.width; |
| newBounds.height = size.height; |
| |
| if (myOriginalParent.getLayoutManager().isGrid()) { |
| myResizedCopy.setBounds(newBounds); |
| } |
| else { |
| if (myEditor.ensureEditable()) { |
| myComponent.setBounds(newBounds); |
| } |
| } |
| |
| myEditor.refresh(); |
| |
| myLastPoint=e.getPoint(); |
| } |
| else if (e.getID() == MouseEvent.MOUSE_RELEASED) { |
| boolean modified = false; |
| myComponent.getDelegee().setVisible(true); |
| myComponent.setResizing(false); |
| myComponent.setSelected(true); |
| if (myResizedCopy != null) { |
| myEditor.getDragLayer().remove(myResizedCopy.getDelegee()); |
| } |
| if (myOriginalParent.getLayoutManager().isGrid() && myEditor.ensureEditable()) { |
| final Point point = SwingUtilities.convertPoint(myEditor.getDragLayer(), e.getX(), e.getY(), myOriginalParent.getDelegee()); |
| Rectangle rcGrid = getGridSpanGridRect(myOriginalParent, myOriginalConstraints, point, myResizeMask); |
| if (rcGrid != null && isGridSpanDropAllowed(rcGrid)) { |
| GridConstraints oldConstraints = (GridConstraints) myOriginalConstraints.clone(); |
| myOriginalConstraints.setColumn(rcGrid.x); |
| myOriginalConstraints.setRow(rcGrid.y); |
| myOriginalConstraints.setColSpan(rcGrid.width); |
| myOriginalConstraints.setRowSpan(rcGrid.height); |
| myComponent.fireConstraintsChanged(oldConstraints); |
| modified = true; |
| } |
| } |
| else { |
| modified = true; |
| } |
| myEditor.getActiveDecorationLayer().removeFeedback(); |
| myComponent.setDragging(false); |
| if (modified) { |
| if (myEditor.ensureEditable()) { |
| myEditor.refreshAndSave(true); |
| } |
| } |
| } |
| } |
| |
| private Cursor getResizeCursor() { |
| return Cursor.getPredefinedCursor(Painter.getResizeCursor(myResizeMask)); |
| } |
| |
| private void putGridSpanFeedback(final Point point) { |
| Rectangle rcGrid = getGridSpanGridRect(myOriginalParent, myOriginalConstraints, point, myResizeMask); |
| if (rcGrid != null) { |
| Rectangle rc = myOriginalParent.getGridLayoutManager().getGridCellRangeRect(myOriginalParent, rcGrid.y, rcGrid.x, |
| rcGrid.y+rcGrid.height-1, rcGrid.x+rcGrid.width-1); |
| String tooltip = UIDesignerBundle.message("resize.feedback", myComponent.getDisplayName(), rcGrid.height, rcGrid.width); |
| myEditor.getActiveDecorationLayer().putFeedback(myOriginalParent.getDelegee(), rc, tooltip); |
| setCursor(isGridSpanDropAllowed(rcGrid) ? getResizeCursor() : FormEditingUtil.getMoveNoDropCursor()); |
| } |
| else { |
| setCursor(getResizeCursor()); |
| myEditor.getActiveDecorationLayer().removeFeedback(); |
| } |
| } |
| |
| @Nullable |
| static Rectangle getGridSpanGridRect(final RadContainer grid, |
| final GridConstraints originalConstraints, |
| final Point point, |
| final int resizeMask) { |
| int rowAtMouse = (resizeMask & (Painter.NORTH_MASK | Painter.SOUTH_MASK)) != 0 |
| ? grid.getGridRowAt(point.y) |
| : -1; |
| int colAtMouse = (resizeMask & (Painter.WEST_MASK | Painter.EAST_MASK)) != 0 |
| ? grid.getGridColumnAt(point.x) |
| : -1; |
| if (rowAtMouse != -1 || colAtMouse != -1) { |
| final int origStartCol = originalConstraints.getColumn(); |
| final int origEndCol = originalConstraints.getColumn() + originalConstraints.getColSpan() - 1; |
| int startCol = origStartCol; |
| int endCol = origEndCol; |
| if (colAtMouse >= 0) { |
| if ((resizeMask & Painter.WEST_MASK) != 0 && colAtMouse <= endCol) { |
| // resize to left |
| startCol = colAtMouse; |
| } |
| else if ((resizeMask & Painter.EAST_MASK) != 0 && colAtMouse >= startCol) { |
| endCol = colAtMouse; |
| } |
| } |
| |
| final int origStartRow = originalConstraints.getRow(); |
| final int origEndRow = originalConstraints.getRow() + originalConstraints.getRowSpan() - 1; |
| int startRow = origStartRow; |
| int endRow = origEndRow; |
| if (rowAtMouse >= 0) { |
| if ((resizeMask & Painter.NORTH_MASK) != 0 && rowAtMouse <= endRow) { |
| startRow = rowAtMouse; |
| } |
| else if ((resizeMask & Painter.SOUTH_MASK) != 0 && rowAtMouse >= startRow) { |
| endRow = rowAtMouse; |
| } |
| } |
| |
| return new Rectangle(startCol, startRow, endCol-startCol+1, endRow-startRow+1); |
| } |
| return null; |
| } |
| |
| protected boolean cancelOperation(){ |
| myComponent.setBounds(myOriginalBounds); |
| myComponent.setResizing(false); |
| myComponent.setDragging(false); |
| if (myResizedCopy != null) { |
| myEditor.getDragLayer().remove(myResizedCopy.getDelegee()); |
| myResizedCopy = null; |
| } |
| myEditor.refresh(); |
| return true; |
| } |
| |
| private boolean isGridSpanDropAllowed(final Rectangle rcGrid) { |
| return myOriginalParent.findComponentInRect(rcGrid.y, rcGrid.x, rcGrid.height, rcGrid.width) == null; |
| } |
| } |