Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
/*
Part of the Processing project - http://processing.org
Copyright (c) 2012-16 The Processing Foundation
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License version 2
as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation, Inc.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package processing.app.syntax;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.GeneralPath;
import java.util.List;
import javax.swing.text.BadLocationException;
import javax.swing.text.Segment;
import javax.swing.text.Utilities;
import processing.app.Mode;
import processing.app.Problem;
import processing.app.ui.Editor;
/**
* Adds support to TextAreaPainter for background colors,
* and the left hand gutter area with background color and text.
*/
public class PdeTextAreaPainter extends TextAreaPainter {
public Color errorUnderlineColor;
public Color warningUnderlineColor;
protected Font gutterTextFont;
protected Color gutterTextColor;
protected Color gutterPastColor;
protected Color gutterLineHighlightColor;
public PdeTextAreaPainter(JEditTextArea textArea, TextAreaDefaults defaults) {
super(textArea, defaults);
// Handle mouse clicks to toggle breakpoints
addMouseListener(new MouseAdapter() {
long lastTime; // OS X seems to be firing multiple mouse events
public void mousePressed(MouseEvent event) {
// Don't toggle breakpoints when the debugger isn't enabled
// https://github.com/processing/processing/issues/3306
if (getEditor().isDebuggerEnabled()) {
long thisTime = event.getWhen();
if (thisTime - lastTime > 100) {
if (event.getX() < Editor.LEFT_GUTTER) {
int offset = textArea.xyToOffset(event.getX(), event.getY());
if (offset >= 0) {
int lineIndex = textArea.getLineOfOffset(offset);
getEditor().toggleBreakpoint(lineIndex);
}
}
lastTime = thisTime;
}
}
}
});
}
/**
* Loads theme for TextAreaPainter. This is handled here because in the olden
* days, Modes had different visual design. Now, these are just pulling the
* defaults from the standard theme, though there may be minor additions or
* overrides added in a Mode's own theme.txt file.
*/
public void setMode(Mode mode) {
errorUnderlineColor = mode.getColor("editor.error.underline.color");
warningUnderlineColor = mode.getColor("editor.warning.underline.color");
gutterTextFont = mode.getFont("editor.gutter.text.font");
gutterTextColor = mode.getColor("editor.gutter.text.color");
gutterPastColor = new Color(gutterTextColor.getRed(),
gutterTextColor.getGreen(),
gutterTextColor.getBlue(),
96);
gutterLineHighlightColor = mode.getColor("editor.gutter.linehighlight.color");
}
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
/**
* Paint a line. Paints the gutter (with background color and text)
* then the line (background color and text).
*
* @param gfx the graphics context
* @param tokenMarker
* @param line 0-based line number
* @param x horizontal position
*/
@Override
protected void paintLine(Graphics gfx, int line, int x, TokenMarkerState marker) {
try {
// TODO This line is causing NPEs randomly ever since I added the
// toggle for Java Mode/Debugger toolbar. [Manindra]
super.paintLine(gfx, line, x + Editor.LEFT_GUTTER, marker);
} catch (Exception e) {
e.printStackTrace();
}
paintLeftGutter(gfx, line, x);
paintErrorLine(gfx, line, x);
}
/**
* Paints the underline for an error/warning line
*/
protected void paintErrorLine(Graphics gfx, int line, int x) {
List problems = getEditor().findProblems(line);
for (Problem problem : problems) {
int startOffset = problem.getStartOffset();
int stopOffset = problem.getStopOffset();
int lineOffset = textArea.getLineStartOffset(line);
int wiggleStart = Math.max(startOffset, lineOffset);
int wiggleStop = Math.min(stopOffset, textArea.getLineStopOffset(line));
int y = textArea.lineToY(line) + fm.getLeading() + fm.getMaxDescent();
try {
String badCode = null;
String goodCode = null;
try {
SyntaxDocument doc = textArea.getDocument();
badCode = doc.getText(wiggleStart, wiggleStop - wiggleStart);
goodCode = doc.getText(lineOffset, wiggleStart - lineOffset);
//log("paintErrorLine() LineText GC: " + goodCode);
//log("paintErrorLine() LineText BC: " + badCode);
} catch (BadLocationException bl) {
// Error in the import statements or end of code.
// System.out.print("BL caught. " + ta.getLineCount() + " ,"
// + line + " ,");
// log((ta.getLineStopOffset(line) - start - 1));
return;
}
int trimmedLength = badCode.trim().length();
int rightTrimmedLength = trimRight(badCode).length();
int leftTrimLength = rightTrimmedLength - trimmedLength;
// Fix offsets when bad code is just whitespace
if (trimmedLength == 0) {
leftTrimLength = 0;
rightTrimmedLength = badCode.length();
}
int x1 = textArea.offsetToX(line, goodCode.length() + leftTrimLength);
int x2 = textArea.offsetToX(line, goodCode.length() + rightTrimmedLength);
if (x1 == x2) x2 += fm.stringWidth(" ");
int y1 = y + fm.getHeight() - 2;
if (line != problem.getLineNumber()) {
x1 = Editor.LEFT_GUTTER; // on the following lines, wiggle extends to the left border
}
gfx.setColor(errorUnderlineColor);
if (problem.isWarning()) {
gfx.setColor(warningUnderlineColor);
}
paintSquiggle(gfx, y1, x1, x2);
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* Paint the gutter: draw the background, draw line numbers, break points.
* @param gfx the graphics context
* @param line 0-based line number
* @param x horizontal position
*/
protected void paintLeftGutter(Graphics gfx, int line, int x) {
int y = textArea.lineToY(line) + fm.getLeading() + fm.getMaxDescent();
if (line == textArea.getSelectionStopLine()) {
gfx.setColor(gutterLineHighlightColor);
gfx.fillRect(0, y, Editor.LEFT_GUTTER, fm.getHeight());
} else {
//gfx.setColor(getJavaTextArea().gutterBgColor);
gfx.setClip(0, y, Editor.LEFT_GUTTER, fm.getHeight());
gfx.drawImage(((PdeTextArea) textArea).getGutterGradient(), 0, 0, getWidth(), getHeight(), this);
gfx.setClip(null); // reset
}
String text = null;
if (getEditor().isDebuggerEnabled()) {
text = getPdeTextArea().getGutterText(line);
}
gfx.setColor(line < textArea.getLineCount() ? gutterTextColor : gutterPastColor);
// if (line >= textArea.getLineCount()) {
// //gfx.setColor(new Color(gutterTextColor.getRGB(), );
// }
int textRight = Editor.LEFT_GUTTER - Editor.GUTTER_MARGIN;
int textBaseline = textArea.lineToY(line) + fm.getHeight();
if (text != null) {
if (text.equals(PdeTextArea.BREAK_MARKER)) {
drawDiamond(gfx, textRight - 8, textBaseline - 8, 8, 8);
} else if (text.equals(PdeTextArea.STEP_MARKER)) {
//drawRightArrow(gfx, textRight - 7, textBaseline - 7, 7, 6);
drawRightArrow(gfx, textRight - 7, textBaseline - 7.5f, 7, 7);
}
} else {
// if no special text for a breakpoint, just show the line number
text = String.valueOf(line + 1);
//text = makeOSF(String.valueOf(line + 1));
gfx.setFont(gutterTextFont);
// ((Graphics2D) gfx).setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
// RenderingHints.VALUE_TEXT_ANTIALIAS_OFF);
// Right-align the text
char[] txt = text.toCharArray();
int tx = textRight - gfx.getFontMetrics().charsWidth(txt, 0, txt.length);
// Using 'fm' here because it's relative to the editor text size,
// not the numbers in the gutter
Utilities.drawTabbedText(new Segment(txt, 0, text.length()),
tx, textBaseline, gfx, this, 0);
}
}
static private void drawDiamond(Graphics g,
float x, float y, float w, float h) {
Graphics2D g2 = (Graphics2D) g;
GeneralPath path = new GeneralPath();
path.moveTo(x + w/2, y);
path.lineTo(x + w, y + h/2);
path.lineTo(x + w/2, y + h);
path.lineTo(x, y + h/2);
path.closePath();
g2.fill(path);
}
static private void drawRightArrow(Graphics g,
float x, float y, float w, float h) {
Graphics2D g2 = (Graphics2D) g;
GeneralPath path = new GeneralPath();
path.moveTo(x, y);
path.lineTo(x + w, y + h/2);
path.lineTo(x, y + h);
path.closePath();
g2.fill(path);
}
/**
* Remove all trailing whitespace from a line
*/
static private String trimRight(String str) {
int i = str.length() - 1;
while (i >= 0 && Character.isWhitespace(str.charAt(i))) {
i--;
}
return str.substring(0, i+1);
}
static private void paintSquiggle(Graphics g, int y, int x1, int x2) {
int xx = x1;
while (xx < x2) {
g.drawLine(xx, y, xx + 2, y + 1);
xx += 2;
g.drawLine(xx, y + 1, xx + 2, y);
xx += 2;
}
}
@Override
public String getToolTipText(MouseEvent event) {
int line = event.getY() / getFontMetrics().getHeight() + textArea.getFirstLine();
if (line >= 0 || line < textArea.getLineCount()) {
List problems = getEditor().findProblems(line);
for (Problem problem : problems) {
int lineStart = textArea.getLineStartOffset(line);
int lineEnd = textArea.getLineStopOffset(line);
int errorStart = problem.getStartOffset();
int errorEnd = problem.getStopOffset() + 1;
int startOffset = Math.max(errorStart, lineStart) - lineStart;
int stopOffset = Math.min(errorEnd, lineEnd) - lineStart;
int x = event.getX();
if (x >= textArea.offsetToX(line, startOffset) &&
x <= textArea.offsetToX(line, stopOffset)) {
getEditor().statusToolTip(this, problem.getMessage(), problem.isError());
return super.getToolTipText(event);
}
}
}
setToolTipText(null);
return super.getToolTipText(event);
}
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
@Override
public int getScrollWidth() {
// TODO https://github.com/processing/processing/issues/3591
return super.getWidth() - Editor.LEFT_GUTTER;
}
public Editor getEditor() {
return getPdeTextArea().editor;
}
public PdeTextArea getPdeTextArea() {
return (PdeTextArea) textArea;
}
}