/* * Copyright 2003-2011 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 jetbrains.mps.nodeEditor.cellLayout; import gnu.trove.TIntArrayList; import jetbrains.mps.editor.runtime.TextBuilderImpl; import jetbrains.mps.editor.runtime.style.CellAlign; import jetbrains.mps.editor.runtime.style.DefaultBaseLine; import jetbrains.mps.editor.runtime.style.StyleAttributes; import jetbrains.mps.openapi.editor.TextBuilder; import jetbrains.mps.openapi.editor.cells.EditorCell; import jetbrains.mps.openapi.editor.cells.EditorCell_Collection; import java.util.Deque; import java.util.LinkedList; /** * User: Sergey Dmitriev * Date: Jan 19, 2005 */ public class CellLayout_Vertical extends AbstractCellLayout { private boolean myGridLayout = false; public void setGridLayout(boolean gridLayout) { myGridLayout = gridLayout; } boolean isGridLayout() { return myGridLayout; } @Override public boolean canBeFolded() { return true; } @Override public void doLayout(EditorCell_Collection editorCells) { Iterable<EditorCell> cells = editorCells.getContentCells(); EditorCell closingBrace = editorCells.getClosingBrace(); EditorCell openingBrace = editorCells.getOpeningBrace(); boolean usesBraces = editorCells.usesBraces(); if (usesBraces) { closingBrace.relayout(); openingBrace.moveTo(editorCells.getX(), editorCells.getY()); openingBrace.relayout(); } final int x = usesBraces ? editorCells.getX() + openingBrace.getWidth() : editorCells.getX(); final int y = editorCells.getY(); int lastCellWidth; int braceIndent = 0; int width = 0; int height = 0; for (EditorCell editorCell : cells) { editorCell.moveTo(x, y + height + editorCell.getTopInset()); editorCell.relayout(); int cellHeight = editorCell.getHeight(); int indent = getBracesIndent(editorCell); braceIndent = Math.max(indent, braceIndent); height += cellHeight /*+ editorCell.getTopInset() + editorCell.getBottomInset()*/; } for (EditorCell editorCell : cells) { lastCellWidth = editorCell.getWidth(); int indent = getBracesIndent(editorCell); int delta = braceIndent - indent; width = Math.max(width, lastCellWidth + delta); } for (EditorCell editorCell : cells) { int cellX = editorCell.getX(); int cellY = editorCell.getY(); int newCellX = cellX; CellAlign cellAlign = editorCell.getStyle().get(StyleAttributes.HORIZONTAL_ALIGN); if (cellAlign == CellAlign.CENTER && !myGridLayout) { newCellX = cellX + (width - editorCell.getWidth()) / 2; } else if (cellAlign == CellAlign.RIGHT && !myGridLayout) { newCellX = cellX + width - editorCell.getWidth(); } if (newCellX != cellX) { editorCell.moveTo(newCellX, cellY); editorCell.relayout(); } } editorCells.setArtificialBracesIndent(braceIndent); for (EditorCell editorCell : cells) { int cellX = editorCell.getX(); int cellY = editorCell.getY(); int indent = getBracesIndent(editorCell); int newCellX = cellX - indent + braceIndent; if (newCellX != cellX) { editorCell.moveTo(newCellX, cellY); editorCell.relayout(); } } if (myGridLayout) { TIntArrayList columnWidths = new TIntArrayList(); for (EditorCell editorCell : cells) { if (editorCell instanceof EditorCell_Collection && ((EditorCell_Collection) editorCell).getCellLayout() instanceof CellLayout_Horizontal) { EditorCell_Collection collectionCell = (EditorCell_Collection) editorCell; int columnNumber = 0; for (EditorCell columnCell : collectionCell) { if (columnNumber < columnWidths.size()) { columnWidths.set(columnNumber, Math.max(columnWidths.get(columnNumber), columnCell.getWidth())); } else { columnWidths.add(columnCell.getWidth()); } columnNumber++; } } } for (EditorCell editorCell : cells) { if (editorCell instanceof EditorCell_Collection && ((EditorCell_Collection) editorCell).getCellLayout() instanceof CellLayout_Horizontal) { EditorCell_Collection collectionCell = (EditorCell_Collection) editorCell; int lineWidth = 0; int columnNumber = 0; for (EditorCell columnCell : collectionCell) { setX(columnCell, x + lineWidth); int columnWidth = columnWidths.get(columnNumber); columnCell.setWidth(columnWidth); lineWidth += columnWidth; columnNumber++; } editorCell.setWidth(lineWidth); width = Math.max(width, lineWidth); } } } if (usesBraces) { closingBrace.setY(y + height - closingBrace.getHeight()); if (myGridLayout) { closingBrace.setX(x + width); width += closingBrace.getWidth(); } else { EditorCell lastCell = editorCells.lastContentCell(); while ((lastCell instanceof EditorCell_Collection) && !((EditorCell_Collection) lastCell).isCollapsed()) { lastCell = ((EditorCell_Collection) lastCell).lastCell(); } if (lastCell == null) { lastCell = editorCells.lastContentCell() != null ? editorCells.lastContentCell() : openingBrace; } closingBrace.setX(lastCell.getX() + lastCell.getWidth()/*x + lastCellWidth*/); width = Math.max(width, (closingBrace.getX() - x) + closingBrace.getWidth()); } width += openingBrace.getWidth(); } editorCells.setWidth(width); editorCells.setHeight(height); } private void setX(EditorCell cell, int newX) { int deltaX = newX - cell.getX(); Deque<EditorCell> cellsToMove = new LinkedList<EditorCell>(); cellsToMove.add(cell); while (!cellsToMove.isEmpty()) { EditorCell nextCell = cellsToMove.removeFirst(); nextCell.setX(nextCell.getX() + deltaX); if (nextCell instanceof EditorCell_Collection) { for (EditorCell childCell : ((EditorCell_Collection) nextCell)) { cellsToMove.addLast(childCell); } } } } private int getBracesIndent(EditorCell cell) { return cell instanceof EditorCell_Collection ? ((EditorCell_Collection) cell).getBracesIndent() : 0; } @Override public int getRightInternalInset(EditorCell_Collection editorCell_collection) { return editorCell_collection.isEmpty() ? 0 : editorCell_collection.firstCell().getRightInset(); } @Override public TextBuilder doLayoutText(Iterable<EditorCell> editorCells) { TextBuilder result = new TextBuilderImpl(); for (EditorCell editorCell : editorCells) { result.appendToTheBottom(editorCell.renderText()); } return result; } @Override public int getAscent(EditorCell_Collection editorCells) { for (EditorCell cell : editorCells) { if (cell.getStyle().get(StyleAttributes.BASE_LINE_CELL)) { return cell.getY() - editorCells.getY() + cell.getAscent(); } } DefaultBaseLine bL = editorCells.getStyle().get(StyleAttributes.DEFAULT_BASE_LINE); int result = 0; for (EditorCell cell : editorCells) { result = cell.getAscent(); if (result > 0) { break; } } switch (bL) { case FIRST: // default behavior return result; case CENTER: return Math.max(result, editorCells.getHeight() / 2); case LAST: if (!editorCells.isEmpty()) { EditorCell lastCell = editorCells.lastCell(); return lastCell.getY() - editorCells.getY() + lastCell.getAscent(); } } return 0; } public String toString() { return "Vertical"; } @Override public void requestRelayout(EditorCell_Collection editorCells) { super.requestRelayout(editorCells); if (myGridLayout) { for (EditorCell childCell : editorCells) { if (childCell instanceof EditorCell_Collection) { for (EditorCell innerCell : (EditorCell_Collection) childCell) { innerCell.requestRelayout(); } } else { childCell.requestRelayout(); } } } } }