2 * Copyright 2000-2009 JetBrains s.r.o.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 package com
.intellij
.uiDesigner
.designSurface
;
18 import com
.intellij
.uiDesigner
.CutCopyPasteSupport
;
19 import com
.intellij
.uiDesigner
.FormEditingUtil
;
20 import com
.intellij
.uiDesigner
.UIDesignerBundle
;
21 import com
.intellij
.uiDesigner
.core
.GridConstraints
;
22 import com
.intellij
.uiDesigner
.core
.Util
;
23 import com
.intellij
.uiDesigner
.radComponents
.RadComponent
;
24 import com
.intellij
.uiDesigner
.radComponents
.RadContainer
;
25 import org
.jetbrains
.annotations
.Nullable
;
28 import java
.awt
.Cursor
;
29 import java
.awt
.Dimension
;
30 import java
.awt
.Point
;
31 import java
.awt
.Rectangle
;
32 import java
.awt
.event
.KeyEvent
;
33 import java
.awt
.event
.MouseEvent
;
34 import java
.util
.Collections
;
35 import java
.util
.List
;
38 * @author Anton Katilin
39 * @author Vladimir Kondratyev
41 public final class ResizeProcessor
extends EventProcessor
{
42 private final RadComponent myComponent
;
43 private final int myResizeMask
;
44 private Point myLastPoint
;
45 private Rectangle myBounds
;
46 private Rectangle myOriginalBounds
;
47 private final RadContainer myOriginalParent
;
48 private final GuiEditor myEditor
;
49 private final GridConstraints myOriginalConstraints
;
50 private RadComponent myResizedCopy
;
52 public ResizeProcessor(final GuiEditor editor
, final RadComponent component
, final int resizeMask
){
54 if (component
.getParent() == null) {
55 throw new IllegalArgumentException("parent is null for " + component
);
58 myComponent
= component
;
59 myOriginalParent
= component
.getParent();
60 myOriginalConstraints
= component
.getConstraints();
62 final List
<RadComponent
> copyList
= CutCopyPasteSupport
.copyComponents(editor
, Collections
.singletonList(component
));
63 if (component
.getParent().getLayoutManager().isGrid() && copyList
!= null) {
64 myComponent
.setResizing(true);
65 Rectangle rc
= SwingUtilities
.convertRectangle(component
.getParent().getDelegee(),
66 component
.getBounds(),
67 myEditor
.getDragLayer());
68 component
.setDragging(true);
69 component
.setSelected(false);
71 myResizedCopy
= copyList
.get(0);
72 myResizedCopy
.setBounds(rc
);
73 myResizedCopy
.setSelected(true);
74 editor
.getDragLayer().add(myResizedCopy
.getDelegee());
76 myResizeMask
= resizeMask
;
78 setCursor(getResizeCursor());
81 protected void processKeyEvent(final KeyEvent e
){}
83 protected void processMouseEvent(final MouseEvent e
){
84 if (e
.getID() == MouseEvent
.MOUSE_PRESSED
) {
85 myLastPoint
= e
.getPoint();
86 myBounds
= myOriginalParent
.getLayoutManager().isGrid() ? myResizedCopy
.getBounds() : myComponent
.getBounds();
87 myOriginalBounds
= new Rectangle(myBounds
);
89 else if(e
.getID()==MouseEvent
.MOUSE_DRAGGED
){
90 final int dx
= e
.getX() - myLastPoint
.x
;
91 final int dy
= e
.getY() - myLastPoint
.y
;
93 if (myOriginalParent
.getLayoutManager().isGrid()) {
94 final Point point
= SwingUtilities
.convertPoint(myEditor
.getDragLayer(), e
.getX(), e
.getY(), myOriginalParent
.getDelegee());
95 putGridSpanFeedback(point
);
97 else if (myOriginalParent
.isXY()) {
98 myEditor
.getActiveDecorationLayer().removeFeedback();
99 setCursor(getResizeCursor());
105 final GridConstraints constraints
= myComponent
.getConstraints();
107 if ((myResizeMask
& Painter
.WEST_MASK
) != 0) {
109 myBounds
.width
-= dx
;
111 if ((myResizeMask
& Painter
.EAST_MASK
) != 0) {
112 myBounds
.width
+= dx
;
114 if ((myResizeMask
& Painter
.NORTH_MASK
) != 0) {
116 myBounds
.height
-= dy
;
118 if ((myResizeMask
& Painter
.SOUTH_MASK
) != 0) {
119 myBounds
.height
+= dy
;
122 final Dimension minSize
= myComponent
.getMinimumSize();
124 final Rectangle newBounds
= myOriginalParent
.getLayoutManager().isGrid() ? myResizedCopy
.getBounds() : myComponent
.getBounds();
126 // Component's bounds cannot be less the some minimum size
127 if (myBounds
.width
>= minSize
.width
) {
128 newBounds
.x
= myBounds
.x
;
129 newBounds
.width
= myBounds
.width
;
132 if((myResizeMask
& Painter
.WEST_MASK
) != 0){
133 newBounds
.x
= newBounds
.x
+newBounds
.width
-minSize
.width
;
134 newBounds
.width
= minSize
.width
;
136 else if ((myResizeMask
& Painter
.EAST_MASK
) != 0) {
137 newBounds
.width
= minSize
.width
;
141 if (myBounds
.height
>= minSize
.height
) {
142 newBounds
.y
= myBounds
.y
;
143 newBounds
.height
= myBounds
.height
;
146 if ((myResizeMask
& Painter
.NORTH_MASK
) != 0) {
147 newBounds
.y
= newBounds
.y
+ newBounds
.height
- minSize
.height
;
148 newBounds
.height
= minSize
.height
;
150 else if ((myResizeMask
& Painter
.SOUTH_MASK
) != 0) {
151 newBounds
.height
= minSize
.height
;
155 final Dimension size
= newBounds
.getSize();
156 Util
.adjustSize(myComponent
.getDelegee(), constraints
, size
);
157 newBounds
.width
= size
.width
;
158 newBounds
.height
= size
.height
;
160 if (myOriginalParent
.getLayoutManager().isGrid()) {
161 myResizedCopy
.setBounds(newBounds
);
164 if (myEditor
.ensureEditable()) {
165 myComponent
.setBounds(newBounds
);
171 myLastPoint
=e
.getPoint();
173 else if (e
.getID() == MouseEvent
.MOUSE_RELEASED
) {
174 boolean modified
= false;
175 myComponent
.getDelegee().setVisible(true);
176 myComponent
.setResizing(false);
177 myComponent
.setSelected(true);
178 if (myResizedCopy
!= null) {
179 myEditor
.getDragLayer().remove(myResizedCopy
.getDelegee());
181 if (myOriginalParent
.getLayoutManager().isGrid() && myEditor
.ensureEditable()) {
182 final Point point
= SwingUtilities
.convertPoint(myEditor
.getDragLayer(), e
.getX(), e
.getY(), myOriginalParent
.getDelegee());
183 Rectangle rcGrid
= getGridSpanGridRect(myOriginalParent
, myOriginalConstraints
, point
, myResizeMask
);
184 if (rcGrid
!= null && isGridSpanDropAllowed(rcGrid
)) {
185 GridConstraints oldConstraints
= (GridConstraints
) myOriginalConstraints
.clone();
186 myOriginalConstraints
.setColumn(rcGrid
.x
);
187 myOriginalConstraints
.setRow(rcGrid
.y
);
188 myOriginalConstraints
.setColSpan(rcGrid
.width
);
189 myOriginalConstraints
.setRowSpan(rcGrid
.height
);
190 myComponent
.fireConstraintsChanged(oldConstraints
);
197 myEditor
.getActiveDecorationLayer().removeFeedback();
198 myComponent
.setDragging(false);
200 if (myEditor
.ensureEditable()) {
201 myEditor
.refreshAndSave(true);
207 private Cursor
getResizeCursor() {
208 return Cursor
.getPredefinedCursor(Painter
.getResizeCursor(myResizeMask
));
211 private void putGridSpanFeedback(final Point point
) {
212 Rectangle rcGrid
= getGridSpanGridRect(myOriginalParent
, myOriginalConstraints
, point
, myResizeMask
);
213 if (rcGrid
!= null) {
214 Rectangle rc
= myOriginalParent
.getGridLayoutManager().getGridCellRangeRect(myOriginalParent
, rcGrid
.y
, rcGrid
.x
,
215 rcGrid
.y
+rcGrid
.height
-1, rcGrid
.x
+rcGrid
.width
-1);
216 String tooltip
= UIDesignerBundle
.message("resize.feedback", myComponent
.getDisplayName(), rcGrid
.height
, rcGrid
.width
);
217 myEditor
.getActiveDecorationLayer().putFeedback(myOriginalParent
.getDelegee(), rc
, tooltip
);
218 setCursor(isGridSpanDropAllowed(rcGrid
) ?
getResizeCursor() : FormEditingUtil
.getMoveNoDropCursor());
221 setCursor(getResizeCursor());
222 myEditor
.getActiveDecorationLayer().removeFeedback();
227 static Rectangle
getGridSpanGridRect(final RadContainer grid
,
228 final GridConstraints originalConstraints
,
230 final int resizeMask
) {
231 int rowAtMouse
= (resizeMask
& (Painter
.NORTH_MASK
| Painter
.SOUTH_MASK
)) != 0
232 ? grid
.getGridRowAt(point
.y
)
234 int colAtMouse
= (resizeMask
& (Painter
.WEST_MASK
| Painter
.EAST_MASK
)) != 0
235 ? grid
.getGridColumnAt(point
.x
)
237 if (rowAtMouse
!= -1 || colAtMouse
!= -1) {
238 final int origStartCol
= originalConstraints
.getColumn();
239 final int origEndCol
= originalConstraints
.getColumn() + originalConstraints
.getColSpan() - 1;
240 int startCol
= origStartCol
;
241 int endCol
= origEndCol
;
242 if (colAtMouse
>= 0) {
243 if ((resizeMask
& Painter
.WEST_MASK
) != 0 && colAtMouse
<= endCol
) {
245 startCol
= colAtMouse
;
247 else if ((resizeMask
& Painter
.EAST_MASK
) != 0 && colAtMouse
>= startCol
) {
252 final int origStartRow
= originalConstraints
.getRow();
253 final int origEndRow
= originalConstraints
.getRow() + originalConstraints
.getRowSpan() - 1;
254 int startRow
= origStartRow
;
255 int endRow
= origEndRow
;
256 if (rowAtMouse
>= 0) {
257 if ((resizeMask
& Painter
.NORTH_MASK
) != 0 && rowAtMouse
<= endRow
) {
258 startRow
= rowAtMouse
;
260 else if ((resizeMask
& Painter
.SOUTH_MASK
) != 0 && rowAtMouse
>= startRow
) {
265 return new Rectangle(startCol
, startRow
, endCol
-startCol
+1, endRow
-startRow
+1);
270 protected boolean cancelOperation(){
271 myComponent
.setBounds(myOriginalBounds
);
272 myComponent
.setResizing(false);
273 myComponent
.setDragging(false);
274 if (myResizedCopy
!= null) {
275 myEditor
.getDragLayer().remove(myResizedCopy
.getDelegee());
276 myResizedCopy
= null;
282 private boolean isGridSpanDropAllowed(final Rectangle rcGrid
) {
283 return myOriginalParent
.findComponentInRect(rcGrid
.y
, rcGrid
.x
, rcGrid
.height
, rcGrid
.width
) == null;