update copyright
[fedora-idea.git] / plugins / ui-designer / src / com / intellij / uiDesigner / GridChangeUtil.java
blobd2186717551342dbb2400a02362d0bbb3291ed53
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;
18 import com.intellij.uiDesigner.core.GridConstraints;
19 import com.intellij.uiDesigner.radComponents.RadAbstractGridLayoutManager;
20 import com.intellij.uiDesigner.radComponents.RadComponent;
21 import com.intellij.uiDesigner.radComponents.RadContainer;
22 import org.jetbrains.annotations.NotNull;
24 import java.awt.*;
26 /**
27 * @author Anton Katilin
28 * @author Vladimir Kondratyev
30 public final class GridChangeUtil {
31 private GridChangeUtil() {
34 public static void splitColumn(final RadContainer grid, final int columnIndex) {
35 splitCell(grid, columnIndex, false);
38 public static void splitRow(final RadContainer grid, final int rowIndex) {
39 splitCell(grid, rowIndex, true);
42 public static boolean isColumnEmpty(final RadContainer grid, final int columnIndex) {
43 return canDeleteCell(grid, columnIndex, false) == CellStatus.Empty;
46 public static boolean isRowEmpty(final RadContainer grid, final int rowIndex) {
47 return canDeleteCell(grid, rowIndex, true) == CellStatus.Empty;
50 /**
51 * @param cellIndex column or row index, depending on isRow parameter; must be in the range 0..grid.get{Row|Column}Count()-1
52 * @param isRow if true, row inserted, otherwise column
53 * @param isBefore if true, row/column will be inserted before row/column with given index, otherwise after
55 public static void insertRowOrColumn(final RadContainer grid, final int cellIndex, final boolean isRow, final boolean isBefore) {
56 check(grid, isRow, cellIndex);
58 final RadAbstractGridLayoutManager oldLayout = grid.getGridLayoutManager();
60 int beforeIndex = cellIndex;
61 if (!isBefore) {
62 // beforeIndex can actually be equal to get{Row|Column}Count an case we add row after the last row/column
63 beforeIndex++;
66 final LayoutManager newLayout = oldLayout.copyLayout(grid.getLayout(), isRow ? 1 : 0, isRow ? 0 : 1);
68 for (int i=grid.getComponentCount() - 1; i >= 0; i--){
69 final GridConstraints constraints = grid.getComponent(i).getConstraints();
70 final GridConstraints oldConstraints = (GridConstraints) constraints.clone();
71 adjustConstraintsOnInsert(constraints, isRow, beforeIndex, 1);
72 grid.getComponent(i).fireConstraintsChanged(oldConstraints);
75 grid.setLayout(newLayout);
78 public static void adjustConstraintsOnInsert(final GridConstraints constraints, final boolean isRow, final int beforeIndex,
79 final int count) {
80 if (constraints.getCell(isRow) >= beforeIndex) {
81 addToCell(constraints, isRow, count);
83 else if (isCellInsideComponent(constraints, isRow, beforeIndex)) {
84 // component belongs to the cell being resized - increment component's span
85 addToSpan(constraints, isRow, count);
89 /**
90 * @param cellIndex column or row index, depending on isRow parameter; must be in the range 0..grid.get{Row|Column}Count()-1
91 * @param isRow if true, row is splitted, otherwise column
93 public static void splitCell(final RadContainer grid, final int cellIndex, final boolean isRow) {
94 check(grid, isRow, cellIndex);
96 int insertedCells = grid.getGridLayoutManager().insertGridCells(grid, cellIndex, isRow, false, false);
98 for (int i=grid.getComponentCount() - 1; i >= 0; i--){
99 final RadComponent component = grid.getComponent(i);
100 final GridConstraints constraints = component.getConstraints();
102 if (constraints.getCell(isRow) + constraints.getSpan(isRow) - 1 == cellIndex) {
103 // component belongs to the cell being resized - increment component's span
104 GridConstraints oldConstraints = (GridConstraints)constraints.clone();
105 constraints.setSpan(isRow, constraints.getSpan(isRow) + insertedCells);
106 component.fireConstraintsChanged(oldConstraints);
111 public enum CellStatus {
112 Empty, Redundant, CanShift, Required
116 * @param cellIndex column or row index, depending on isRow parameter; must be in the range 0..grid.get{Row|Column}Count()-1
117 * @param isRow if true, row is deleted, otherwise column
118 * @return whether the specified column can be deleted
120 public static CellStatus canDeleteCell(@NotNull final RadContainer grid, final int cellIndex, final boolean isRow) {
121 check(grid, isRow, cellIndex);
123 // Do not allow to delete the single row/column
124 if(isRow && grid.getGridRowCount() <= grid.getGridLayoutManager().getMinCellCount()) {
125 return CellStatus.Required;
127 else if(!isRow && grid.getGridColumnCount() <= grid.getGridLayoutManager().getMinCellCount()) {
128 return CellStatus.Required;
131 boolean haveComponents = false;
132 boolean haveOrigins = false;
133 boolean haveSingleSpan = false;
134 for (int i = 0; i < grid.getComponentCount(); i++) {
135 final GridConstraints constraints = grid.getComponent(i).getConstraints();
136 final int cell = constraints.getCell(isRow);
137 final int span = constraints.getSpan(isRow);
139 if (cellIndex >= cell && cellIndex < cell+span) {
140 haveComponents = true;
141 if (cellIndex == cell) {
142 haveOrigins = true;
143 if (span == 1) {
144 haveSingleSpan = true;
149 if (haveSingleSpan)
150 return CellStatus.Required;
151 if (haveOrigins)
152 return CellStatus.CanShift;
153 if (haveComponents)
154 return CellStatus.Redundant;
155 return CellStatus.Empty;
158 public static boolean canDeleteCells(final RadContainer grid, final int[] cells, final boolean row) {
159 // for multiple cells, we can't determine if deleting all cells will have a correct result
160 for(int cell: cells) {
161 CellStatus status = canDeleteCell(grid, cell, row);
162 if (status != CellStatus.Empty) {
163 if (cells.length == 1 && status == CellStatus.Redundant) {
164 return true;
166 return false;
169 return true;
173 * @param cellIndex column or row index, depending on isRow parameter; must be in the range 0..grid.get{Row|Column}Count()-1
174 * @param isRow if true, row is deleted, otherwise column
176 public static void deleteCell(final RadContainer grid, final int cellIndex, final boolean isRow) {
177 check(grid, isRow, cellIndex);
178 if (canDeleteCell(grid, cellIndex, isRow) == CellStatus.Required) {
179 throw new IllegalArgumentException("cell cannot be deleted");
182 final RadAbstractGridLayoutManager oldLayout = grid.getGridLayoutManager();
184 final LayoutManager newLayout = oldLayout.copyLayout(grid.getLayout(), isRow ? -1 : 0, isRow ? 0 : -1);
186 for (int i=grid.getComponentCount() - 1; i >= 0; i--){
187 final GridConstraints constraints = grid.getComponent(i).getConstraints();
188 final GridConstraints oldConstraints = (GridConstraints) constraints.clone();
190 if (constraints.getCell(isRow) > cellIndex) {
191 // component starts after the cell being deleted - move it
192 addToCell(constraints, isRow, -1);
194 else if (isCellInsideComponent(constraints, isRow, cellIndex)) {
195 // component belongs to the cell being deleted - decrement component's span
196 addToSpan(constraints, isRow, -1);
198 grid.getComponent(i).fireConstraintsChanged(oldConstraints);
201 grid.setLayout(newLayout);
205 private static boolean isCellInsideComponent(final GridConstraints constraints, final boolean isRow, final int cellIndex) {
206 final int cell = constraints.getCell(isRow);
207 final int span = constraints.getSpan(isRow);
208 return cell <= cellIndex && cellIndex <= cell + span - 1;
212 * check whether passed container is grid and cellIndex is in proper range
214 private static void check(@NotNull RadContainer grid, final boolean isRow, final int cellIndex){
215 if (!grid.getLayoutManager().isGrid()){
216 throw new IllegalArgumentException("container must be grid");
219 final int cellCount = isRow ? grid.getGridRowCount() : grid.getGridColumnCount();
220 if (cellIndex == 0 && cellCount == 0) return;
221 if (cellIndex < 0 || cellIndex >= cellCount) {
222 throw new IllegalArgumentException("invalid index: " + cellIndex);
226 private static void addToCell(final GridConstraints constraints, final boolean isRow, final int delta){
227 if (isRow) {
228 constraints.setRow(constraints.getRow() + delta);
230 else {
231 constraints.setColumn(constraints.getColumn() + delta);
235 private static void addToSpan(final GridConstraints constraints, final boolean isRow, final int delta){
236 if (isRow) {
237 constraints.setRowSpan(constraints.getRowSpan() + delta);
239 else {
240 constraints.setColSpan(constraints.getColSpan() + delta);
244 public static void moveCells(final RadContainer container, final boolean isRow, final int[] cellsToMove, int targetCell) {
245 for(int i=0; i<cellsToMove.length; i++) {
246 final int sourceCell = cellsToMove[i];
247 moveCell(container, isRow, sourceCell, targetCell);
248 if (sourceCell < targetCell) {
249 for(int j=i+1; j<cellsToMove.length; j++) {
250 cellsToMove [j]--;
253 else {
254 targetCell++;
259 public static void moveCell(final RadContainer container, final boolean isRow, final int sourceCell, int targetCell) {
260 if (targetCell == sourceCell || targetCell == sourceCell+1) return;
261 // if column moved to left - components inbetween move to right, and vice versa
262 int delta = (sourceCell > targetCell) ? 1 : -1;
263 int startCell = Math.min(sourceCell, targetCell);
264 int endCell = Math.max(sourceCell, targetCell);
265 if (sourceCell < targetCell) targetCell--;
266 for(RadComponent c: container.getComponents()) {
267 GridConstraints constraints = c.getConstraints();
268 GridConstraints oldConstraints = (GridConstraints) constraints.clone();
269 final int aCell = constraints.getCell(isRow);
270 if (aCell == sourceCell) {
271 constraints.setCell(isRow, targetCell);
273 else if (aCell >= startCell && aCell < endCell) {
274 constraints.setCell(isRow, aCell + delta);
276 c.fireConstraintsChanged(oldConstraints);