/* -*- mode: jde; c-basic-offset: 2; indent-tabs-mode: nil -*- */ /* Part of the Processing project - http://processing.org Copyright (c) 2005-06 Ignacio Manuel González Moreta Copyright (c) 2006 Ben Fry and Casey Reas This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package processing.app.tools; import java.awt.*; import java.awt.datatransfer.*; import java.awt.event.*; import javax.swing.*; import javax.swing.text.Segment; import processing.app.*; import processing.app.syntax.*; import processing.core.PApplet; /** * Format for Discourse Tool *
* Original code by owd. * Revised and updated for revision 0108 by Ben Fry (10 March 2006). * This code will later be removed but is included with release 0108+ * while features for the "Tools" menu are in testing. * * Updated for 0122 to simply copy the code directly to the clipboard, * rather than opening a new window. * * Notes from the original source: * Discourse.java This is a dirty-mix source. * NOTE that: No macs and no keyboard. Unreliable source. * Only format processing code using fontMetrics. * It works under my windows XP + PentiumIV + Processing 0091. */ public class DiscourseFormat { //static final String WINDOW_TITLE = "Format for Discourse by owd"; // p5 icon for the window //static Image icon; Editor editor; //JEditTextArea textarea; // JTextArea of the actual Editor JEditTextArea parent; //JFrame frame; boolean html; /** * Creates a new window with the formated (YaBB tags) sketchcode * from the actual Processing Tab ready to send to the processing discourse * web (copy & paste) */ public DiscourseFormat(Editor editor, boolean html) { this.editor = editor; this.parent = editor.textarea; this.html = html; /* textarea = new JEditTextArea(new PdeTextAreaDefaults()); textarea.setRightClickPopup(new DiscourseTextAreaPopup()); textarea.setTokenMarker(new PdeKeywords()); textarea.setHorizontalOffset(6); textarea.setEditable(false); // Create and set up the window. frame = new JFrame(WINDOW_TITLE); frame.setSize(500, 500); // set the window icon try { icon = Base.getImage("icon.gif", frame); frame.setIconImage(icon); } catch (Exception e) { } // fail silently, no big whup frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); Container pain = frame.getContentPane(); pain.setLayout(new BorderLayout()); pain.add(textarea, BorderLayout.CENTER); frame.setResizable(true); frame.pack(); frame.setLocation(100, 100); //frame.setVisible(true); */ } public void show() { // Format and render sketchcode // [code] tag cancels other tags, using [quote] StringBuffer cf = new StringBuffer(html ? " \n" : "[quote] \n");
// Line by line
for (int i = 0; i < parent.getLineCount(); i++) {
cf.append(formatCode(i));
}
cf.append(html ? "" : "[/quote]");
/*
// Send the text to the textarea
textarea.setText(cf.toString());
textarea.select(0, 0);
frame.show();
*/
StringSelection formatted = new StringSelection(cf.toString());
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
clipboard.setContents(formatted, new ClipboardOwner() {
public void lostOwnership(Clipboard clipboard, Transferable contents) {
// i don't care about ownership
}
});
editor.message((html ? "HTML" : "Forum") + "-formatted code has " +
"been copied to the clipboard.");
}
// A terrible headache...
public String formatCode(int line) {
StringBuffer cf = new StringBuffer();
// Segment
Segment lineSegment = new Segment();
TextAreaPainter painter = parent.getPainter();
TokenMarker tokenMarker = parent.getTokenMarker();
// Use painter's cached info for speed
FontMetrics fm = painter.getFontMetrics();
// get line text from parent textarea
parent.getLineText(line, lineSegment);
char[] segmentArray = lineSegment.array;
int limit = lineSegment.getEndIndex();
int segmentOffset = lineSegment.offset;
int segmentCount = lineSegment.count;
int width = 0; //parent.getHorizontalOffset();
int x = 0; //parent.getHorizontalOffset();
// If syntax coloring is disabled, do simple translation
if (tokenMarker == null) {
for (int j = 0; j < segmentCount; j++) {
char c = segmentArray[j + segmentOffset];
cf = cf.append(c); //concat(character(c));
int charWidth;
if (c == '\t') {
charWidth = (int) painter.nextTabStop(width, j) - width;
} else {
charWidth = fm.charWidth(c);
}
width += charWidth;
}
} else {
// If syntax coloring is enabled, we have to do this
// because tokens can vary in width
Token tokens;
if ((painter.getCurrentLineIndex() == line) &&
(painter.getCurrentLineTokens() != null)) {
tokens = painter.getCurrentLineTokens();
} else {
painter.setCurrentLineIndex(line);
//painter.currentLineIndex = line;
painter.setCurrentLineTokens(tokenMarker.markTokens(lineSegment, line));
tokens = painter.getCurrentLineTokens();
}
int offset = 0;
Toolkit toolkit = painter.getToolkit();
Font defaultFont = painter.getFont();
SyntaxStyle[] styles = painter.getStyles();
for (;;) {
byte id = tokens.id;
if (id == Token.END) {
if (segmentOffset + offset < limit) {
cf.append(segmentArray[segmentOffset + offset]);
} else {
cf.append('\n');
}
return cf.toString();
}
if (id == Token.NULL) {
fm = painter.getFontMetrics();
} else {
// Place open tags []
//cf.append("[color=" + color() + "]");
cf.append(html ? "" : "]");
if (styles[id].isBold())
cf.append(html ? "" : "[b]");
fm = styles[id].getFontMetrics(defaultFont);
}
int length = tokens.length;
for (int j = 0; j < length; j++) {
char c = segmentArray[segmentOffset + offset + j];
cf.append(c);
// Place close tags [/]
if (j == (length - 1) && id != Token.NULL && styles[id].isBold())
cf.append(html ? "" : "[/b]");
if (j == (length - 1) && id != Token.NULL)
cf.append(html ? "" : "[/color]");
int charWidth;
if (c == '\t') {
charWidth = (int) painter
.nextTabStop(width, offset + j)
- width;
} else {
charWidth = fm.charWidth(c);
}
width += charWidth;
}
offset += length;
tokens = tokens.next;
}
}
return cf.toString();
}
/**
* Returns the discourse popup menu. Another features can be added: format
* selected text with a determinated tag (I'm thinking about [url]selected
* text[/url])
*/
/*
class DiscourseTextAreaPopup extends JPopupMenu {
JMenuItem copyItem;
public DiscourseTextAreaPopup() {
JMenuItem item;
copyItem = new JMenuItem("Copy");
copyItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
textarea.copy();
}
});
this.add(copyItem);
item = new JMenuItem("Select All");
item.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
textarea.selectAll();
}
});
this.add(item);
}
// if no text is selected, disable copy menu item
public void show(Component component, int x, int y) {
if (textarea.isSelectionActive()) {
copyItem.setEnabled(true);
} else {
copyItem.setEnabled(false);
}
super.show(component, x, y);
}
}
*/
/*
// A false listener (use the mouse)
public class DiscourseListener {
public DiscourseListener(JEditTextArea thisTextarea) {
// I'm a... I know this gives peoblems, but all this code
// is a funny hacking experiment
thisTextarea.editorListener = parent.editorListener;
}
public boolean keyPressed(KeyEvent event) {
System.out.println("Is your mouse lone some tonight...");
return false;
}
}
*/
}