/* * Copyright 2000-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 com.intellij.formatting; import org.jetbrains.annotations.NotNull; /** * {@link BlockAlignmentProcessor} implementation for {@link Alignment} that * {@link Alignment.Anchor#RIGHT anchors to the right block edge}. * * @author Denis Zhdanov * @since 4/28/11 4:06 PM */ public class RightEdgeAlignmentProcessor extends AbstractBlockAlignmentProcessor { @Override protected IndentData calculateAlignmentAnchorIndent(@NotNull Context context) { LeafBlockWrapper offsetResponsibleBlock = context.alignment.getOffsetRespBlockBefore(context.targetBlock); if (offsetResponsibleBlock == null) { return null; } final WhiteSpace whiteSpace = offsetResponsibleBlock.getWhiteSpace(); if (whiteSpace.containsLineFeeds()) { return new IndentData(whiteSpace.getIndentSpaces() + offsetResponsibleBlock.getSymbolsAtTheLastLine(), whiteSpace.getSpaces()); } else { final int targetIndent = CoreFormatterUtil.getStartColumn(offsetResponsibleBlock) + offsetResponsibleBlock.getSymbolsAtTheLastLine(); final AbstractBlockWrapper prevIndentedBlock = CoreFormatterUtil.getIndentedParentBlock(context.targetBlock); if (prevIndentedBlock == null) { return new IndentData(0, targetIndent); } else { final int parentIndent = prevIndentedBlock.getWhiteSpace().getIndentOffset(); return new IndentData(parentIndent, targetIndent - parentIndent); } } } @Override protected boolean applyIndentToTheFirstBlockOnLine(@NotNull IndentData alignmentAnchorIndent, @NotNull Context context) { WhiteSpace whiteSpace = context.targetBlock.getWhiteSpace(); int indentSpaces = alignmentAnchorIndent.getIndentSpaces(); int spaces = alignmentAnchorIndent.getSpaces() - context.targetBlock.getSymbolsAtTheLastLine(); if (spaces < 0) { indentSpaces += spaces; spaces = 0; } if (indentSpaces >= 0) { whiteSpace.setSpaces(spaces, indentSpaces); return true; } if (whiteSpace.getTotalSpaces() > 0) { // The general idea is that there is a possible case that particular block that starts new line is much wider than its // preceding aligned block and its white space is not empty. We may move it to the left then trying to preserve its // indent. // // Example: // block11 block12 // test-block-that-has-rather-big-width-and-aligned-to-block12 // Let's say, the last block has indent '10', hence, the result would be: // block11 block12 // test-block-that-has-rather-big-width-and-aligned-to-block12 CompositeBlockWrapper parent = context.targetBlock.getParent(); if (parent != null) { IndentData childOffset = CoreFormatterUtil.getIndent( context.indentOptions, context.targetBlock, context.targetBlock.getStartOffset() ); if (whiteSpace.getTotalSpaces() > childOffset.getTotalSpaces()) { int leftShift = whiteSpace.getTotalSpaces() - childOffset.getTotalSpaces(); if (leftShift >= whiteSpace.getSpaces()) { spaces = 0; indentSpaces = whiteSpace.getIndentSpaces() - (leftShift - whiteSpace.getSpaces()); } else { spaces = whiteSpace.getSpaces() - leftShift; indentSpaces = whiteSpace.getIndentSpaces(); } } whiteSpace.setSpaces(spaces, indentSpaces); } } return false; } @Override protected int getAlignmentIndentDiff(@NotNull IndentData alignmentAnchorIndent, @NotNull Context context) { IndentData indentBeforeBlock = context.targetBlock.getNumberOfSymbolsBeforeBlock(); int numberOfSymbolsBeforeBlock = indentBeforeBlock.getTotalSpaces() + context.targetBlock.getSymbolsAtTheLastLine(); return alignmentAnchorIndent.getTotalSpaces() - numberOfSymbolsBeforeBlock; } }