/* * 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.cellMenu; import com.intellij.util.ui.UIUtil; import jetbrains.mps.nodeEditor.EditorComponent; import jetbrains.mps.nodeEditor.cells.TextLine; import jetbrains.mps.nodeEditor.ui.InputMethodListenerImpl; import jetbrains.mps.openapi.editor.style.StyleRegistry; import org.jetbrains.annotations.NotNull; import javax.swing.JPanel; import javax.swing.JWindow; import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Point; import java.awt.Rectangle; import java.awt.Window; import java.awt.event.InputMethodEvent; import java.awt.event.KeyEvent; /** * Author: Sergey Dmitriev. * Time: Oct 20, 2003 1:45:39 PM */ public class NodeSubstitutePatternEditor { private EditorWindow myEditorWindow; private boolean myEditorActivated; private String myCachedText = ""; private int myCachedCaretPosition; private int mySavedCaretPosition = 0; public void setText(String text) { if (myEditorActivated) { myEditorWindow.myTextLine.setText(text); myEditorWindow.relayout(); myEditorWindow.repaint(); } else { myCachedText = text; } } public boolean isActivated() { return myEditorActivated; } public String getText() { if (myEditorActivated) { return myEditorWindow.myTextLine.getText(); } return myCachedText; } public void setCaretPosition(int caretPosition) { if (myEditorActivated) { myEditorWindow.myTextLine.setCaretPosition(caretPosition); myEditorWindow.repaint(); } else { myCachedCaretPosition = caretPosition; } } public int getCaretPosition() { return myEditorWindow.myTextLine.getCaretPosition(); } public boolean processKeyPressed(KeyEvent keyEvent) { if (myEditorActivated) { if (keyEvent.getKeyCode() == KeyEvent.VK_SPACE && keyEvent.isControlDown()) { toggleReplaceMode(); return true; } return myEditorWindow.processKeyPressed(keyEvent); } return false; } public void toggleReplaceMode() { if (myEditorActivated) { TextLine textLine = myEditorWindow.myTextLine; if (mySavedCaretPosition != 0) { textLine.setCaretPosition(mySavedCaretPosition); mySavedCaretPosition = 0; } else { mySavedCaretPosition = textLine.getCaretPosition(); textLine.setCaretPosition(0); } myEditorWindow.repaint(); } else { if (mySavedCaretPosition != 0) { myCachedCaretPosition = mySavedCaretPosition; mySavedCaretPosition = 0; } else { mySavedCaretPosition = myCachedCaretPosition; myCachedCaretPosition = 0; } } } public boolean processKeyTyped(KeyEvent keyEvent) { if (myEditorActivated && myEditorWindow.processKeyTyped(keyEvent)) { mySavedCaretPosition = 0; return true; } return false; } public boolean processTextChanged(InputMethodEvent inputEvent) { if (myEditorActivated && myEditorWindow.processTextChanged(inputEvent)) { mySavedCaretPosition = 0; return true; } return false; } @NotNull public String getPattern() { if (myEditorActivated) { TextLine textLine = myEditorWindow.myTextLine; int caretPosition = textLine.getCaretPosition(); String text = textLine.getText(); return text.substring(0, caretPosition); } if (myCachedText == null) { return ""; } int caretPos = Math.min(myCachedText.length(), Math.max(myCachedCaretPosition, 0)); return myCachedText.substring(0, caretPos); } // ------------------ public void activate(Window owner, Point location, Dimension size, boolean show) { if (!myEditorActivated) { myEditorActivated = true; myEditorWindow = new EditorWindow(owner); myEditorWindow.setLocation(location); myEditorWindow.setMinimalSize(size); myEditorWindow.myTextLine.setText(myCachedText); myEditorWindow.myTextLine.setCaretPosition(myCachedCaretPosition); if (show) { myEditorWindow.relayout(); myEditorWindow.setVisible(true); } } } public void setLocation(Point point) { myEditorWindow.setLocation(point); } public Point getLeftBottomPosition() { Point location = myEditorWindow.getLocation(); location.translate(0, myEditorWindow.getSize().height); return location; } public int getHeight() { return myEditorWindow.getSize().height; } public void done() { if (myEditorActivated) { myEditorWindow.dispose(); myEditorActivated = false; mySavedCaretPosition = 0; } } private static class EditorWindow extends JWindow { private TextLine myTextLine; private Dimension myMinimalSize; private JPanel myPanel = new EditorPanel(); public EditorWindow(Window owner) { super(owner); myTextLine = new TextLine(""); add(myPanel); } public void setMinimalSize(Dimension size) { myMinimalSize = size; } public void relayout() { myTextLine.relayout(); int h = Math.max(myMinimalSize.height, myTextLine.getHeight()); int w = Math.max(myMinimalSize.width, getWidth()); w = Math.max(w, myTextLine.getWidth()); setSize(w, h); } public boolean processKeyTyped(KeyEvent keyEvent) { if (processKeyTypedInternal(keyEvent)) { relayout(); repaint(); return true; } return false; } public boolean processTextChanged(InputMethodEvent inputEvent) { String oldText = myTextLine.getText(); int caretPosition = myTextLine.getCaretPosition(); if (caretPosition > 0) { // replacing last symbol before the caret with the text from input method caretPosition--; } String text = InputMethodListenerImpl.getText(inputEvent); changeText(oldText.substring(0, caretPosition) + text); myTextLine.setCaretPosition(caretPosition + text.length()); relayout(); repaint(); return true; } private boolean processKeyTypedInternal(KeyEvent keyEvent) { String oldText = myTextLine.getText(); int caretPosition = myTextLine.getCaretPosition(); char keyChar = keyEvent.getKeyChar(); if (UIUtil.isReallyTypedEvent(keyEvent)) { changeText(oldText.substring(0, caretPosition) + keyChar/* + myText.substring(caretPosition)*/); myTextLine.setCaretPosition(caretPosition + 1); return true; } return false; } public boolean processKeyPressed(KeyEvent keyEvent) { if (processKeyPressedInternal(keyEvent)) { relayout(); repaint(); return true; } return false; } private boolean processKeyPressedInternal(KeyEvent keyEvent) { if (keyEvent.isControlDown()) { return false; } String oldText = myTextLine.getText(); int caretPosition = myTextLine.getCaretPosition(); if (keyEvent.getKeyCode() == KeyEvent.VK_BACK_SPACE) { if (caretPosition > 0) { changeText(oldText.substring(0, caretPosition - 1) + oldText.substring(caretPosition)); myTextLine.setCaretPosition(caretPosition - 1); return true; } else { return false; } } if (keyEvent.getKeyCode() == KeyEvent.VK_DELETE) { if (caretPosition < oldText.length()) { changeText(oldText.substring(0, caretPosition) + oldText.substring(caretPosition + 1)); return true; } else { return false; } } if (keyEvent.getKeyCode() == KeyEvent.VK_LEFT) { if (caretPosition > 0) { myTextLine.setCaretPosition(caretPosition - 1); return true; } else { return false; } } if (keyEvent.getKeyCode() == KeyEvent.VK_RIGHT) { if (caretPosition < oldText.length()) { myTextLine.setCaretPosition(caretPosition + 1); return true; } else { return false; } } return false; } protected void changeText(String text) { myTextLine.setText(text); } private class EditorPanel extends JPanel { @Override protected void paintComponent(Graphics g) { // COLORS: move colors to properties Rectangle bounds = g.getClipBounds(); g.setColor(StyleRegistry.getInstance().getSimpleColor(Color.YELLOW)); g.fillRect(bounds.x, bounds.y, bounds.width, bounds.height); g.setColor(StyleRegistry.getInstance().getSimpleColor(Color.GRAY)); g.drawRect(bounds.x, bounds.y, bounds.width - 1, bounds.height - 1); EditorComponent.turnOnAliasingIfPossible((Graphics2D) g); TextLine textLine = myTextLine; textLine.setSelected(false); textLine.setShowCaret(true); textLine.paint(g, 0, 0); } } } // private class EditorWindow }