UI designer is dumb-aware
[fedora-idea.git] / plugins / ui-designer / src / com / intellij / uiDesigner / actions / AbstractMoveSelectionAction.java
blobb47b3ab1085a1e563dc01ba5c3cb5cdbc220473f
1 /*
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.actions;
18 import com.intellij.openapi.actionSystem.AnAction;
19 import com.intellij.openapi.actionSystem.AnActionEvent;
20 import com.intellij.openapi.diagnostic.Logger;
21 import com.intellij.openapi.project.DumbAware;
22 import com.intellij.openapi.util.Ref;
23 import com.intellij.uiDesigner.FormEditingUtil;
24 import com.intellij.uiDesigner.designSurface.GuiEditor;
25 import com.intellij.uiDesigner.radComponents.RadAtomicComponent;
26 import com.intellij.uiDesigner.radComponents.RadComponent;
27 import com.intellij.uiDesigner.radComponents.RadContainer;
28 import org.jetbrains.annotations.NotNull;
30 import javax.swing.*;
31 import java.awt.*;
32 import java.util.ArrayList;
34 /**
35 * @author Anton Katilin
36 * @author Vladimir Kondratyev
38 abstract class AbstractMoveSelectionAction extends AnAction implements DumbAware {
39 private static final Logger LOG=Logger.getInstance("#com.intellij.uiDesigner.actions.MoveSelectionToRightAction");
41 private final GuiEditor myEditor;
42 private final boolean myExtend;
43 private final boolean myMoveToLast;
45 public AbstractMoveSelectionAction(@NotNull final GuiEditor editor, boolean extend, final boolean moveToLast) {
46 myEditor = editor;
47 myExtend = extend;
48 myMoveToLast = moveToLast;
51 public final void actionPerformed(final AnActionEvent e) {
52 final ArrayList<RadComponent> selectedComponents = FormEditingUtil.getSelectedComponents(myEditor);
53 final JComponent rootContainerDelegee = myEditor.getRootContainer().getDelegee();
54 if(selectedComponents.size() == 0){
55 moveToFirstComponent(rootContainerDelegee);
56 return;
58 RadComponent selectedComponent = myEditor.getSelectionLead();
59 if (selectedComponent == null || !selectedComponents.contains(selectedComponent)) {
60 selectedComponent = selectedComponents.get(0);
63 if (moveSelectionByGrid(selectedComponent) || myMoveToLast) {
64 return;
67 // 1. We need to get coordinates of all editor's component in the same
68 // coordinate system. For example, in the RadRootContainer rootContainerDelegee's coordinate system.
70 final ArrayList<RadComponent> components = new ArrayList<RadComponent>();
71 final ArrayList<Point> points = new ArrayList<Point>();
72 final RadComponent selectedComponent1 = selectedComponent;
73 FormEditingUtil.iterate(
74 myEditor.getRootContainer(),
75 new FormEditingUtil.ComponentVisitor<RadComponent>() {
76 public boolean visit(final RadComponent component) {
77 if (component instanceof RadAtomicComponent) {
78 if(selectedComponent1.equals(component)){
79 return true;
81 if (!FormEditingUtil.isComponentSwitchedInView(component)) {
82 return true;
84 components.add(component);
85 final JComponent _delegee = component.getDelegee();
86 final Point p = SwingUtilities.convertPoint(
87 _delegee,
88 new Point(0, 0),
89 rootContainerDelegee
91 p.x += _delegee.getWidth() / 2;
92 p.y += _delegee.getHeight() / 2;
93 points.add(p);
95 return true;
99 if(components.size() == 0){
100 return;
103 // 2.
104 final Point source = SwingUtilities.convertPoint(
105 selectedComponent.getDelegee(),
106 new Point(0, 0),
107 rootContainerDelegee
109 source.x += selectedComponent.getDelegee().getWidth() / 2;
110 source.y += selectedComponent.getDelegee().getHeight() / 2;
111 int min = Integer.MAX_VALUE;
112 int nextSelectedIndex = -1;
113 for(int i = points.size() - 1; i >= 0; i--){
114 final int distance = calcDistance(source, points.get(i));
115 if(distance < min){
116 min = distance;
117 nextSelectedIndex = i;
120 if(min == Integer.MAX_VALUE){
121 return;
124 LOG.assertTrue(nextSelectedIndex != -1);
125 final RadComponent component = components.get(nextSelectedIndex);
126 selectOrExtend(component);
129 private void selectOrExtend(final RadComponent component) {
130 if (myExtend) {
131 FormEditingUtil.selectComponent(myEditor, component);
133 else {
134 FormEditingUtil.selectSingleComponent(myEditor, component);
138 private void moveToFirstComponent(final JComponent rootContainerDelegee) {
139 final int[] minX = new int[]{Integer.MAX_VALUE};
140 final int[] minY = new int[]{Integer.MAX_VALUE};
141 final Ref<RadComponent> componentToBeSelected = new Ref<RadComponent>();
142 FormEditingUtil.iterate(
143 myEditor.getRootContainer(),
144 new FormEditingUtil.ComponentVisitor<RadComponent>() {
145 public boolean visit(final RadComponent component) {
146 if (component instanceof RadAtomicComponent) {
147 final JComponent _delegee = component.getDelegee();
148 final Point p = SwingUtilities.convertPoint(
149 _delegee,
150 new Point(0, 0),
151 rootContainerDelegee
153 if(minX[0] > p.x || minY[0] > p.y){
154 minX[0] = p.x;
155 minY[0] = p.y;
156 componentToBeSelected.set(component);
159 return true;
163 if(!componentToBeSelected.isNull()){
164 FormEditingUtil.selectComponent(myEditor, componentToBeSelected.get());
168 @Override
169 public void update(AnActionEvent e) {
170 e.getPresentation().setEnabled(!myEditor.getMainProcessor().isProcessorActive());
173 private boolean moveSelectionByGrid(final RadComponent selectedComponent) {
174 final RadContainer parent = selectedComponent.getParent();
175 if (parent == null || !parent.getLayoutManager().isGrid()) {
176 return false;
179 int row = selectedComponent.getConstraints().getRow();
180 int column = selectedComponent.getConstraints().getColumn();
182 RadComponent lastComponent = null;
183 do {
184 row += getRowMoveDelta();
185 column += getColumnMoveDelta();
186 if (row < 0 || row >= parent.getGridRowCount() || column < 0 || column >= parent.getGridColumnCount()) {
187 if (myMoveToLast) {
188 break;
190 return false;
193 final RadComponent component = parent.getComponentAtGrid(row, column);
194 if (component != null && component != selectedComponent) {
195 if (myMoveToLast) {
196 if (myExtend) {
197 FormEditingUtil.selectComponent(myEditor, component);
199 lastComponent = component;
201 else {
202 selectOrExtend(component);
203 return true;
206 } while(true);
208 if (lastComponent != null) {
209 selectOrExtend(lastComponent);
210 return true;
212 return false;
215 protected abstract int calcDistance(Point source, Point point);
217 protected int getColumnMoveDelta() {
218 return 0;
221 protected int getRowMoveDelta() {
222 return 0;