/* * StandaloneTextArea.java - A TextArea that can be embedded in applications * :tabSize=4:indentSize=4:noTabs=false: * :folding=explicit:collapseFolds=1: * * Copyright (C) 1999, 2005 Slava Pestov * Portions copyright (C) 2000 Ollie Rutherfurd * Portions copyright (C) 2006 Matthieu Casanova * Portions copyright (C) 2008 Dakshinamurthy Karra * * 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 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 org.gjt.sp.jedit.textarea; //{{{ Imports import java.awt.Color; import java.awt.Font; import java.io.Closeable; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.util.Properties; import javax.swing.JFrame; import javax.swing.WindowConstants; import org.gjt.sp.jedit.IPropertyManager; import org.gjt.sp.jedit.JEditBeanShellAction; import org.gjt.sp.jedit.Mode; import org.gjt.sp.jedit.JEditActionSet; import org.gjt.sp.jedit.datatransfer.RichJEditTextTransferableService; import org.gjt.sp.jedit.datatransfer.StringTransferableService; import org.gjt.sp.jedit.datatransfer.TransferHandler; import org.gjt.sp.jedit.input.AbstractInputHandler; import org.gjt.sp.jedit.buffer.DefaultFoldHandlerProvider; import org.gjt.sp.jedit.buffer.DummyFoldHandler; import org.gjt.sp.jedit.buffer.ExplicitFoldHandler; import org.gjt.sp.jedit.buffer.FoldHandler; import org.gjt.sp.jedit.buffer.IndentFoldHandler; import org.gjt.sp.jedit.buffer.JEditBuffer; import org.gjt.sp.jedit.buffer.KillRing; import org.gjt.sp.jedit.syntax.Chunk; import org.gjt.sp.jedit.syntax.ModeProvider; import org.gjt.sp.jedit.syntax.ParserRuleSet; import org.gjt.sp.jedit.syntax.SyntaxStyle; import org.gjt.sp.jedit.syntax.TokenMarker; import org.gjt.sp.util.IOUtilities; import org.gjt.sp.util.Log; import org.gjt.sp.util.SyntaxUtilities; //}}} /** jEdit's standalone text component. * * Use this class to embed a jEdit TextArea into other applications. * * Example: * <code> * class MyTextArea extends StandaloneTextArea * { * static final Properties props = new Properties(); * static IPropertyManager propertyManager; * * static * { * props = new Properties(); * load(props); * propertyManager = new IPropertyManager() { * public String getProperty() { * return props.getProperty(); * } * } * } * * public MyTextArea() * { * super(propertyManager); * } * } * </code> * * See jedit.props for properties that can be set. * * @author Slava Pestov * @author John Gellene (API documentation) @author Matthieu Casanova * @version $Id$ */ public class StandaloneTextArea extends TextArea { //{{{ Instance variables private final IPropertyManager propertyManager; //}}} //{{{ StandaloneTextArea constructor /** * Creates a new StandaloneTextArea. A reference to the propertyManager is saved and used to read the properties * when {@link StandaloneTextArea#propertiesChanged()} is called. * * @param propertyManager the property manager that contains both shortcut bindings and UI information */ public StandaloneTextArea(IPropertyManager propertyManager) { super(propertyManager, null); this.propertyManager = propertyManager; initInputHandler(); setMouseHandler(new TextAreaMouseHandler(this)); // todo : make TextareaTransferHandler standalone // textArea.setTransferHandler(new TextAreaTransferHandler()); JEditActionSet<JEditBeanShellAction> actionSet = new StandaloneActionSet(propertyManager, this, TextArea.class.getResource("textarea.actions.xml")); addActionSet(actionSet); actionSet.load(); actionSet.initKeyBindings(); //{{{ init Style property manager if (SyntaxUtilities.propertyManager == null) { SyntaxUtilities.propertyManager = propertyManager; } //}}} initTextArea(); DefaultFoldHandlerProvider foldHandlerProvider = new DefaultFoldHandlerProvider(); FoldHandler.foldHandlerProvider = foldHandlerProvider; foldHandlerProvider.addFoldHandler(new ExplicitFoldHandler()); foldHandlerProvider.addFoldHandler(new IndentFoldHandler()); foldHandlerProvider.addFoldHandler(new DummyFoldHandler()); JEditBuffer buffer = new JEditBuffer(); TokenMarker tokenMarker = new TokenMarker(); tokenMarker.addRuleSet(new ParserRuleSet("text","MAIN")); buffer.setTokenMarker(tokenMarker); setBuffer(buffer); String property = propertyManager.getProperty("buffer.undoCount"); int undoCount = 100; if (property != null) try { undoCount = Integer.parseInt(property); } catch (NumberFormatException e) { } this.buffer.setUndoLimit(undoCount); Mode mode = new Mode("text"); mode.setTokenMarker(tokenMarker); ModeProvider.instance.addMode(mode); KillRing.setInstance(new KillRing()); KillRing.getInstance().propertiesChanged(100); } //}}} //{{{ initTextArea() method /** * Initializes the text area by re-reading the properties from the property manager passed to the * constructor. */ private void initTextArea() { initPainter(); initGutter(); setCaretBlinkEnabled(getBooleanProperty( "view.caretBlink")); setElectricScroll(getIntegerProperty( "view.electricBorders",0)); if (buffer == null) return ; String property = propertyManager.getProperty("buffer.undoCount"); int undoCount = 100; if (property != null) { try { undoCount = Integer.parseInt(property); } catch (NumberFormatException e) { } } buffer.setUndoLimit(undoCount); } //}}} //{{{ initGutter() method private void initGutter() { Gutter gutter = getGutter(); gutter.setExpanded(getBooleanProperty( "view.gutter.lineNumbers")); int interval = getIntegerProperty( "view.gutter.highlightInterval",5); gutter.setHighlightInterval(interval); gutter.setCurrentLineHighlightEnabled(getBooleanProperty( "view.gutter.highlightCurrentLine")); gutter.setStructureHighlightEnabled(getBooleanProperty( "view.gutter.structureHighlight")); gutter.setStructureHighlightColor( getColorProperty("view.gutter.structureHighlightColor")); gutter.setBackground( getColorProperty("view.gutter.bgColor")); gutter.setForeground( getColorProperty("view.gutter.fgColor")); gutter.setHighlightedForeground( getColorProperty("view.gutter.highlightColor")); gutter.setFoldColor( getColorProperty("view.gutter.foldColor")); gutter.setCurrentLineForeground( getColorProperty("view.gutter.currentLineColor")); String alignment = getProperty( "view.gutter.numberAlignment"); if ("right".equals(alignment)) { gutter.setLineNumberAlignment(Gutter.RIGHT); } else if ("center".equals(alignment)) { gutter.setLineNumberAlignment(Gutter.CENTER); } else // left == default case { gutter.setLineNumberAlignment(Gutter.LEFT); } gutter.setFont(getFontProperty("view.gutter.font")); int width = getIntegerProperty( "view.gutter.borderWidth",3); gutter.setBorder(width, getColorProperty("view.gutter.focusBorderColor"), getColorProperty("view.gutter.noFocusBorderColor"), painter.getBackground()); } //}}} //{{{ initPainter() method /** * Init the painter of this textarea. * */ private void initPainter() { TextAreaPainter painter = getPainter(); painter.setBlockCaretEnabled(false); painter.setFont(getFontProperty("view.font")); painter.setStructureHighlightEnabled(getBooleanProperty( "view.structureHighlight")); painter.setStructureHighlightColor( getColorProperty("view.structureHighlightColor")); painter.setEOLMarkersPainted(getBooleanProperty( "view.eolMarkers")); String emc = getProperty("view.eolMarkerChar"); if (emc.length() > 0) painter.setEOLMarkerChar(emc); painter.setEOLMarkerColor( getColorProperty("view.eolMarkerColor")); painter.setWrapGuidePainted(getBooleanProperty( "view.wrapGuide")); painter.setWrapGuideColor( getColorProperty("view.wrapGuideColor")); painter.setCaretColor( getColorProperty("view.caretColor")); painter.setSelectionColor( getColorProperty("view.selectionColor")); painter.setMultipleSelectionColor( getColorProperty("view.multipleSelectionColor")); painter.setBackground( getColorProperty("view.bgColor")); painter.setForeground( getColorProperty("view.fgColor")); painter.setBlockCaretEnabled(getBooleanProperty( "view.blockCaret")); painter.setThickCaretEnabled(getBooleanProperty( "view.thickCaret")); painter.setLineHighlightEnabled(getBooleanProperty( "view.lineHighlight")); painter.setLineHighlightColor( getColorProperty("view.lineHighlightColor")); painter.setAntiAlias(new AntiAlias(getProperty("view.antiAlias"))); painter.setFractionalFontMetricsEnabled(getBooleanProperty( "view.fracFontMetrics")); painter.setSelectionFgColor(getColorProperty( "view.selectionFgColor")); painter.setSelectionFgColorEnabled(getBooleanProperty( "view.selectionFg")); String defaultFont = getProperty("view.font"); int defaultFontSize = getIntegerProperty("view.fontsize",12); painter.setStyles(SyntaxUtilities.loadStyles(defaultFont,defaultFontSize)); SyntaxStyle[] foldLineStyle = new SyntaxStyle[4]; for(int i = 0; i <= 3; i++) { foldLineStyle[i] = SyntaxUtilities.parseStyle( getProperty("view.style.foldLine." + i), defaultFont,defaultFontSize,true); } painter.setFoldLineStyle(foldLineStyle); } //}}} //{{{ // The following methods are copied from jEdit.java and refer to the propertyManager passed // to the constructor. //}}} //{{{ getProperty() method public String getProperty(String name) { return propertyManager.getProperty(name); } //}}} //{{{ getBooleanProperty() methods /** * Returns the value of a boolean property. * @param name The property */ private boolean getBooleanProperty(String name) { return getBooleanProperty(name,false); } /** * Returns the value of a boolean property. * @param name The property * @param def The default value */ private boolean getBooleanProperty(String name, boolean def) { String value = getProperty(name); if(value == null) return def; else if("true".equals(value) || "yes".equals(value) || "on".equals(value)) return true; else if("false".equals(value) || "no".equals(value) || "off".equals(value)) return false; else return def; } //}}} //{{{ getIntegerProperty() method /** * Returns the value of an integer property. * @param name The property * @param def The default value * @since jEdit 4.0pre1 */ private int getIntegerProperty(String name, int def) { String value = getProperty(name); if(value == null) return def; else { try { return Integer.parseInt(value.trim()); } catch(NumberFormatException nf) { return def; } } } //}}} //{{{ getFontProperty() methods /** * Returns the value of a font property. The family is stored * in the <code><i>name</i></code> property, the font size is stored * in the <code><i>name</i>size</code> property, and the font style is * stored in <code><i>name</i>style</code>. For example, if * <code><i>name</i></code> is <code>view.gutter.font</code>, the * properties will be named <code>view.gutter.font</code>, * <code>view.gutter.fontsize</code>, and * <code>view.gutter.fontstyle</code>. * * @param name The property * @since jEdit 4.0pre1 */ private Font getFontProperty(String name) { return getFontProperty(name,null); } /** * Returns the value of a font property. The family is stored * in the <code><i>name</i></code> property, the font size is stored * in the <code><i>name</i>size</code> property, and the font style is * stored in <code><i>name</i>style</code>. For example, if * <code><i>name</i></code> is <code>view.gutter.font</code>, the * properties will be named <code>view.gutter.font</code>, * <code>view.gutter.fontsize</code>, and * <code>view.gutter.fontstyle</code>. * * @param name The property * @param def The default value * @since jEdit 4.0pre1 */ private Font getFontProperty(String name, Font def) { String family = getProperty(name); String sizeString = getProperty(name + "size"); String styleString = getProperty(name + "style"); if(family == null || sizeString == null || styleString == null) return def; else { int size; try { size = Integer.parseInt(sizeString); } catch(NumberFormatException nf) { return def; } int style; try { style = Integer.parseInt(styleString); } catch(NumberFormatException nf) { return def; } return new Font(family,style,size); } } //}}} //{{{ getColorProperty() methods /** * Returns the value of a color property. * @param name The property name * @since jEdit 4.0pre1 */ private Color getColorProperty(String name) { return getColorProperty(name,Color.black); } /** * Returns the value of a color property. * @param name The property name * @param def The default value * @since jEdit 4.0pre1 */ private Color getColorProperty(String name, Color def) { String value = getProperty(name); if(value == null) return def; else return SyntaxUtilities.parseColor(value, def); } //}}} //{{{ propertiesChanged() method /** * Reinitializes the textarea by reading the properties from the property manager */ @Override public void propertiesChanged() { getInputHandler().removeAllKeyBindings(); JEditActionSet<JEditBeanShellAction>[] actionSets = getActionContext().getActionSets(); for (JEditActionSet<JEditBeanShellAction> actionSet : actionSets) { actionSet.initKeyBindings(); } Chunk.propertiesChanged(propertyManager); initBuffer(); initTextArea(); super.propertiesChanged(); } //}}} //{{{ initBuffer() method /** * Reinitializes the buffer by reading the properties from the property manager */ private void initBuffer() { String[] bufferProperties = { "lineSeparator", "encodingAutodetect", "tabSize", "indentSize", "noTabs", "defaultMode", "undoCount", "wrap", "maxLineLen", "wordBreakChars", "noWordSep", "camelCasedWords", "folding", "collapseFolds" }; for (String bufferProperty : bufferProperties) { String value = getProperty("buffer." + bufferProperty); if (value == null) buffer.unsetProperty(bufferProperty); else buffer.setProperty(bufferProperty, value); } buffer.propertiesChanged(); } // }}} //{{{ createTextArea() method /** * Create a standalone TextArea. * If you want to use it in jEdit, please use {@link JEditEmbeddedTextArea#JEditEmbeddedTextArea()} * * @return a textarea * @since 4.3pre13 */ public static StandaloneTextArea createTextArea() { final Properties props = new Properties(); props.putAll(loadProperties("/keymaps/jEdit_keys.props")); props.putAll(loadProperties("/org/gjt/sp/jedit/jedit.props")); StandaloneTextArea textArea = new StandaloneTextArea(new IPropertyManager() { public String getProperty(String name) { return props.getProperty(name); } }); textArea.getBuffer().setProperty("folding", "explicit"); return textArea; } // }}} //{{{ loadProperties() method private static Properties loadProperties(String fileName) { Properties props = new Properties(); File file; if (fileName.charAt(0) == '/') file = new File(fileName.substring(1)); else file = new File(fileName); InputStream in = null; try { if (file.isFile()) { in = new FileInputStream(file); } else { in = TextArea.class.getResourceAsStream(fileName); } props.load(in); } catch (IOException e) { Log.log(Log.ERROR, TextArea.class, e); } finally { IOUtilities.closeQuietly((Closeable)in); } return props; } //}}} //{{{ StandaloneActionSet class /** * The actionSet for standalone textArea. * @author Matthieu Casanova */ public static class StandaloneActionSet extends JEditActionSet<JEditBeanShellAction> { private final IPropertyManager iPropertyManager; private final TextArea textArea; public StandaloneActionSet(IPropertyManager iPropertyManager, TextArea textArea, URL url) { super(null, url); this.iPropertyManager = iPropertyManager; this.textArea = textArea; } @Override protected JEditBeanShellAction[] getArray(int size) { return new JEditBeanShellAction[size]; } @Override protected String getProperty(String name) { return iPropertyManager.getProperty(name); } public AbstractInputHandler getInputHandler() { return textArea.getInputHandler(); } @Override protected JEditBeanShellAction createBeanShellAction(String actionName, String code, String selected, boolean noRepeat, boolean noRecord, boolean noRememberLast) { return new JEditBeanShellAction(actionName,code,selected,noRepeat,noRecord,noRememberLast); } } //}}} static { TransferHandler.getInstance().registerTransferableService(new RichJEditTextTransferableService()); TransferHandler.getInstance().registerTransferableService(new StringTransferableService()); } //{{{ main() method public static void main(String[] args) { JFrame frame = new JFrame(); TextArea text = createTextArea(); Mode mode = new Mode("xml"); mode.setProperty("file","modes/xml.xml"); ModeProvider.instance.addMode(mode); text.getBuffer().setMode(mode); frame.getContentPane().add(text); frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); frame.pack(); frame.setVisible(true); } //}}} }