use of processing.app.SketchCode in project processing by processing.
the class Debugger method javaToSketchLine.
/**
* Translate a line (index) from java space to sketch space.
* @param javaLine the java line id
* @return the corresponding sketch line id or null if failed to translate
*/
public LineID javaToSketchLine(LineID javaLine) {
Sketch sketch = editor.getSketch();
// it may belong to a pure java file created in the sketch
// try to find an exact filename match and check the extension
SketchCode tab = editor.getTab(javaLine.fileName());
if (tab != null && tab.isExtension("java")) {
// can translate 1:1
return originalToRuntimeLine(javaLine);
}
// java file name needs to match the sketches filename
if (!javaLine.fileName().equals(sketch.getName() + ".java")) {
return null;
}
// get the last tab that has an offset not greater than the java line number
for (int i = sketch.getCodeCount() - 1; i >= 0; i--) {
tab = sketch.getCode(i);
// the tab's offset must not be greater than the java line number
if (tab.isExtension("pde") && tab.getPreprocOffset() <= javaLine.lineIdx()) {
final int index = javaLine.lineIdx() - tab.getPreprocOffset();
return originalToRuntimeLine(new LineID(tab.getFileName(), index));
}
}
return null;
}
use of processing.app.SketchCode in project processing by processing.
the class ChangeDetector method checkFiles.
// Synchronize, we are running async and touching fields
private synchronized void checkFiles() {
List<String> filenames = new ArrayList<>();
sketch.getSketchCodeFiles(filenames, null);
SketchCode[] codes = sketch.getCode();
// Separate codes with and without files
Map<Boolean, List<SketchCode>> existsMap = Arrays.stream(codes).collect(Collectors.groupingBy(code -> filenames.contains(code.getFileName())));
// ADDED FILES
List<String> codeFilenames = Arrays.stream(codes).map(SketchCode::getFileName).collect(Collectors.toList());
// Get filenames which are in filesystem but don't have code
List<String> addedFilenames = filenames.stream().filter(f -> !codeFilenames.contains(f)).collect(Collectors.toList());
// Show prompt if there are any added files which were not previously ignored
boolean added = addedFilenames.stream().anyMatch(f -> !ignoredAdditions.contains(f));
// REMOVED FILES
// Get codes which don't have file
List<SketchCode> removedCodes = Optional.ofNullable(existsMap.get(Boolean.FALSE)).orElse(Collections.emptyList());
// Show prompt if there are any removed codes which were not previously ignored
boolean removed = removedCodes.stream().anyMatch(code -> !ignoredRemovals.contains(code));
/// MODIFIED FILES
// Get codes which have file with different modification time
List<SketchCode> modifiedCodes = Optional.ofNullable(existsMap.get(Boolean.TRUE)).orElse(Collections.emptyList()).stream().filter(code -> {
long fileLastModified = code.getFile().lastModified();
long codeLastModified = code.getLastModified();
long diff = fileLastModified - codeLastModified;
return fileLastModified == 0L || diff > MODIFICATION_WINDOW_MILLIS;
}).collect(Collectors.toList());
// Show prompt if any open codes were modified
boolean modified = !modifiedCodes.isEmpty();
boolean ask = added || removed || modified;
if (DEBUG) {
System.out.println("ask: " + ask + "\n" + "added filenames: " + addedFilenames + ",\n" + "ignored added: " + ignoredAdditions + ",\n" + "removed codes: " + removedCodes + ",\n" + "ignored removed: " + ignoredRemovals + ",\n" + "modified codes: " + modifiedCodes);
}
// dismissing the prompt and we get another prompt before we even finished.
try {
// Wait for EDT to finish its business
// We need to stay in synchronized scope because of ignore lists
EventQueue.invokeAndWait(() -> {
// Show prompt if something interesting happened
if (ask && showReloadPrompt()) {
// She said yes!!!
if (sketch.getMainFile().exists()) {
sketch.reload();
editor.rebuildHeader();
} else {
// Mark everything as modified so that it saves properly
for (SketchCode code : codes) {
code.setModified(true);
}
try {
sketch.save();
} catch (Exception e) {
//if that didn't work, tell them it's un-recoverable
Messages.showError("Reload Failed", "The main file for this sketch was deleted\n" + "and could not be rewritten.", e);
}
}
// Sketch was reloaded, clear ignore lists
ignoredAdditions.clear();
ignoredRemovals.clear();
return;
}
// Update ignore lists to get rid of old stuff
ignoredAdditions = addedFilenames;
ignoredRemovals = removedCodes;
// If something changed, set modified flags and modification times
if (!removedCodes.isEmpty() || !modifiedCodes.isEmpty()) {
Stream.concat(removedCodes.stream(), modifiedCodes.stream()).forEach(code -> {
code.setModified(true);
code.setLastModified();
});
// Not sure if this is needed
editor.rebuildHeader();
}
});
} catch (InterruptedException ignore) {
} catch (InvocationTargetException e) {
Messages.loge("exception in ChangeDetector", e);
}
}
use of processing.app.SketchCode in project processing by processing.
the class Editor method handlePrint.
/**
* Handler for File → Print.
*/
public void handlePrint() {
statusNotice(Language.text("editor.status.printing"));
StringBuilder html = new StringBuilder("<html><body>");
for (SketchCode tab : sketch.getCode()) {
html.append("<b>" + tab.getPrettyName() + "</b><br>");
html.append(textarea.getTextAsHtml((SyntaxDocument) tab.getDocument()));
html.append("<br>");
}
// Don't want last <br>.
html.setLength(html.length() - 4);
html.append("</body></html>");
JTextPane jtp = new JTextPane();
// Needed for good line wrapping; otherwise one very long word breaks
// wrapping for the whole document.
jtp.setEditorKit(new HTMLEditorKit() {
public ViewFactory getViewFactory() {
return new HTMLFactory() {
public View create(Element e) {
View v = super.create(e);
if (!(v instanceof javax.swing.text.html.ParagraphView))
return v;
else
return new javax.swing.text.html.ParagraphView(e) {
protected SizeRequirements calculateMinorAxisRequirements(int axis, SizeRequirements r) {
r = super.calculateMinorAxisRequirements(axis, r);
r.minimum = 1;
return r;
}
};
}
};
}
});
jtp.setFont(new Font(Preferences.get("editor.font.family"), Font.PLAIN, 10));
jtp.setText(// Not in a <pre>.
html.toString().replace("\n", "<br>").replaceAll("(?<! ) ", // Allow line wrap.
" "));
//printerJob = null;
if (printerJob == null) {
printerJob = PrinterJob.getPrinterJob();
}
if (pageFormat != null) {
//System.out.println("setting page format " + pageFormat);
printerJob.setPrintable(jtp.getPrintable(null, null), pageFormat);
} else {
printerJob.setPrintable(jtp.getPrintable(null, null));
}
// set the name of the job to the code name
printerJob.setJobName(sketch.getCurrentCode().getPrettyName());
if (printerJob.printDialog()) {
try {
printerJob.print();
statusNotice(Language.text("editor.status.printing.done"));
} catch (PrinterException pe) {
statusError(Language.text("editor.status.printing.error"));
pe.printStackTrace();
}
} else {
statusNotice(Language.text("editor.status.printing.canceled"));
}
//printerJob = null; // clear this out?
}
use of processing.app.SketchCode in project processing by processing.
the class EditorHeader method paintComponent.
public void paintComponent(Graphics screen) {
if (screen == null)
return;
Sketch sketch = editor.getSketch();
// possible?
if (sketch == null)
return;
Dimension size = getSize();
if ((size.width != sizeW) || (size.height != sizeH)) {
if ((size.width > imageW) || (size.height > imageH)) {
// nix the image and recreate, it's too small
offscreen = null;
} else {
// if the image is larger than necessary, no need to change
sizeW = size.width;
sizeH = size.height;
}
}
if (offscreen == null) {
sizeW = size.width;
sizeH = size.height;
imageW = sizeW;
imageH = sizeH;
offscreen = Toolkit.offscreenGraphics(this, imageW, imageH);
}
Graphics g = offscreen.getGraphics();
// need to set this each time through
g.setFont(font);
if (fontAscent == 0) {
fontAscent = (int) Toolkit.getAscent(g);
}
Graphics2D g2 = Toolkit.prepareGraphics(g);
// Toolkit.dpiStroke(g2);
g.drawImage(gradient, 0, 0, imageW, imageH, this);
if (tabs.length != sketch.getCodeCount()) {
tabs = new Tab[sketch.getCodeCount()];
for (int i = 0; i < tabs.length; i++) {
tabs[i] = new Tab(i);
}
visitOrder = new Tab[sketch.getCodeCount() - 1];
}
int leftover = TAB_BETWEEN + ARROW_TAB_WIDTH;
int tabMax = getWidth() - leftover;
// reset all tab positions
for (Tab tab : tabs) {
SketchCode code = sketch.getCode(tab.index);
tab.textVisible = true;
tab.lastVisited = code.lastVisited();
// hide extensions for .pde files
boolean hide = editor.getMode().hideExtension(code.getExtension());
tab.text = hide ? code.getPrettyName() : code.getFileName();
// if modified, add the li'l glyph next to the name
// if (code.isModified()) {
// tab.text += " ยง";
// }
tab.textWidth = (int) font.getStringBounds(tab.text, g2.getFontRenderContext()).getWidth();
}
// try to make everything fit
if (!placeTabs(Editor.LEFT_GUTTER, tabMax, null)) {
// always show the tab with the sketch's name
int index = 0;
// stock the array backwards so the rightmost tabs are closed by default
for (int i = tabs.length - 1; i > 0; --i) {
visitOrder[index++] = tabs[i];
}
// sort on when visited
Arrays.sort(visitOrder);
// Keep shrinking the tabs one-by-one until things fit properly
for (int i = 0; i < visitOrder.length; i++) {
tabs[visitOrder[i].index].textVisible = false;
if (placeTabs(Editor.LEFT_GUTTER, tabMax, null)) {
break;
}
}
}
// now actually draw the tabs
if (!placeTabs(Editor.LEFT_GUTTER, tabMax - ARROW_TAB_WIDTH, g2)) {
// draw the dropdown menu target at the right of the window
menuRight = tabMax;
menuLeft = menuRight - ARROW_TAB_WIDTH;
} else {
// draw the dropdown menu target next to the tabs
menuLeft = tabs[tabs.length - 1].right + TAB_BETWEEN;
menuRight = menuLeft + ARROW_TAB_WIDTH;
}
// draw the two pixel line that extends left/right below the tabs
g.setColor(tabColor[SELECTED]);
// can't be done with lines, b/c retina leaves tiny hairlines
g.fillRect(Editor.LEFT_GUTTER, TAB_BOTTOM, editor.getTextArea().getWidth() - Editor.LEFT_GUTTER, Toolkit.zoom(2));
// draw the tab for the menu
g.setColor(tabColor[UNSELECTED]);
drawTab(g, menuLeft, menuRight, false, true);
// draw the arrow on the menu tab
g.setColor(arrowColor);
GeneralPath trianglePath = new GeneralPath();
float x1 = menuLeft + (ARROW_TAB_WIDTH - ARROW_WIDTH) / 2f;
float x2 = menuLeft + (ARROW_TAB_WIDTH + ARROW_WIDTH) / 2f;
trianglePath.moveTo(x1, ARROW_TOP);
trianglePath.lineTo(x2, ARROW_TOP);
trianglePath.lineTo((x1 + x2) / 2, ARROW_BOTTOM);
trianglePath.closePath();
g2.fill(trianglePath);
screen.drawImage(offscreen, 0, 0, imageW, imageH, null);
}
use of processing.app.SketchCode in project processing by processing.
the class MarkerColumn method recalculateMarkerPositions.
private void recalculateMarkerPositions() {
if (errorPoints != null && errorPoints.size() > 0) {
Sketch sketch = editor.getSketch();
SketchCode code = sketch.getCurrentCode();
int currentTab = sketch.getCurrentCodeIndex();
// do not divide by zero
int totalLines = PApplet.max(1, code.getLineCount());
int visibleLines = editor.getTextArea().getVisibleLines();
totalLines = PApplet.max(totalLines, visibleLines);
// top scroll button
int topMargin = 20;
// bottom scroll button and horizontal scrollbar
int bottomMargin = 40;
int height = getHeight() - topMargin - bottomMargin;
for (LineMarker m : errorPoints) {
Problem problem = m.problem;
if (problem.getTabIndex() != currentTab)
continue;
// Ratio of error line to total lines
float ratio = (problem.getLineNumber() + 1) / ((float) totalLines);
// Ratio multiplied by height of the error bar
float y = topMargin + ratio * height;
m.y = (int) y;
}
}
}
Aggregations