/*
* 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;
import jetbrains.mps.editor.runtime.style.ShowBoundariesArea;
import jetbrains.mps.nodeEditor.braces.BracePair;
import jetbrains.mps.nodeEditor.braces.BracesFinder;
import jetbrains.mps.nodeEditor.selection.SingularSelectionUtil;
import jetbrains.mps.openapi.editor.cells.EditorCell;
import jetbrains.mps.openapi.editor.style.Style;
import jetbrains.mps.openapi.editor.style.StyleAttribute;
import jetbrains.mps.openapi.editor.style.StyleRegistry;
import org.jetbrains.annotations.Nullable;
import java.awt.Color;
import java.util.HashSet;
import java.util.Set;
public class BracesHighlighter {
// COLORS: Remove hardcoded colors
private static final Color BRACES_LEFT_HIGHLIGHT_COLOR = new Color(107, 142, 178);
private static Style ourMatchedBraceAttributes;
private final Set<EditorCell> myHighlightedCells = new HashSet<>();
private final Set<EditorCell> myLeftHighlightedCells = new HashSet<>();
private final EditorComponent myEditorComponent;
BracesHighlighter(EditorComponent editorComponent) {
myEditorComponent = editorComponent;
myEditorComponent.getSelectionManager().addSelectionListener((ec, oldSelection, newSelection) -> {
if (oldSelection == newSelection) {
return;
}
updateBracesSelection(SingularSelectionUtil.getSingleSelectedCell(newSelection));
});
}
public void updateBracesSelection(@Nullable EditorCell newSelection) {
BracePair cellsToHighlight = newSelection == null ? null : BracesFinder.findBracesToHighlight(newSelection);
if (cellsToHighlight == null) {
clearBracesSelection();
return;
}
selectBraces(cellsToHighlight);
}
private void clearBracesSelection() {
for (EditorCell editorCell : myHighlightedCells) {
Style cellStyle = editorCell.getStyle();
int highestPriority = 0;
for (StyleAttribute attribute : getMatchedBraceAttributes().getSpecifiedAttributes()) {
highestPriority = Math.max(editorCell.getStyle().getHighestPriority(attribute), highestPriority);
}
for (StyleAttribute attribute : getMatchedBraceAttributes().getSpecifiedAttributes()) {
cellStyle.set(attribute, highestPriority, null);
}
myEditorComponent.repaint(editorCell);
}
myHighlightedCells.clear();
for (EditorCell cell : myLeftHighlightedCells) {
myEditorComponent.leftUnhighlightCell((jetbrains.mps.nodeEditor.cells.EditorCell) cell);
}
myLeftHighlightedCells.clear();
}
private void selectBraces(BracePair bracePair) {
if (myHighlightedCells.size() == 2
&& myHighlightedCells.contains(bracePair.myFirstCell)
&& myHighlightedCells.contains(bracePair.mySecondCell)) {
// highlightedCells should not be changed
// selectBraces() method can be called as a result of EditorCell_Label.makePositionValid()
// makePositionValid() in turn can be called even if actual caret position was not changed,
// so nothing to change in highlightedCells..
return;
}
clearBracesSelection();
highlightInGutter(bracePair);
if (bracePair.myArea == ShowBoundariesArea.GUTTER_AND_EDITOR) {
highlightInEditor(bracePair);
}
}
private void highlightInEditor(BracePair bracePair) {
highlightCell(bracePair.myFirstCell);
highlightCell(bracePair.mySecondCell);
}
private void highlightInGutter(BracePair bracePair) {
if (bracePair.myFirstCell.getY() != bracePair.mySecondCell.getY()) {
((EditorComponent) bracePair.mySecondCell.getEditorComponent()).leftHighlightCells(
(jetbrains.mps.nodeEditor.cells.EditorCell) bracePair.mySecondCell,
(jetbrains.mps.nodeEditor.cells.EditorCell) bracePair.myFirstCell,
BRACES_LEFT_HIGHLIGHT_COLOR);
myLeftHighlightedCells.add(bracePair.myFirstCell);
myLeftHighlightedCells.add(bracePair.mySecondCell);
}
}
private void highlightCell(EditorCell editorCell) {
Style cellStyle = editorCell.getStyle();
int highestPriority = 0;
for (StyleAttribute attribute : getMatchedBraceAttributes().getSpecifiedAttributes()) {
highestPriority = Math.max(cellStyle.getHighestPriority(attribute), highestPriority);
}
for (StyleAttribute attribute : getMatchedBraceAttributes().getSpecifiedAttributes()) {
cellStyle.set(attribute, highestPriority + 1, getMatchedBraceAttributes().get(attribute));
}
myHighlightedCells.add(editorCell);
myEditorComponent.repaint(editorCell);
}
private static Style getMatchedBraceAttributes() {
if (ourMatchedBraceAttributes == null) {
ourMatchedBraceAttributes = StyleRegistry.getInstance().getStyle("MATCHED_BRACE_ATTRIBUTES");
}
return ourMatchedBraceAttributes;
}
}