/* * Copyright 2009 Georgios "cyberpython" Migdos cyberpython@gmail.com * * 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. */ /* * EditorView.java * * Created on 21 Δεκέμβριος 2008, 7:50 μμ */ package minijed.editor; import java.awt.Color; import java.awt.Font; import java.awt.FontMetrics; import java.awt.Graphics; import java.awt.GraphicsEnvironment; import java.awt.Point; import java.awt.image.BufferedImage; import java.io.BufferedWriter; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.util.Vector; import javax.swing.JEditorPane; import javax.swing.JPopupMenu; import javax.swing.event.CaretEvent; import javax.swing.event.CaretListener; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; import javax.swing.event.UndoableEditEvent; import javax.swing.event.UndoableEditListener; import javax.swing.text.BadLocationException; import javax.swing.text.DefaultHighlighter; import javax.swing.text.DefaultHighlighter.DefaultHighlightPainter; import javax.swing.text.EditorKit; import jsyntaxpane.SyntaxDocument; import jsyntaxpane.SyntaxStyles; import jsyntaxpane.TokenType; import jsyntaxpane.lexers.MiniJavaLexer; /** * * @author cyberpython */ public class EditorView extends javax.swing.JPanel implements DocumentListener, CaretListener, UndoableEditListener { private boolean newFile; private boolean modified; private String Title; private File storage; private SyntaxDocument document; private EditorViewContainer container; private String UNTITLED; private JPopupMenu popupMenu; /** Creates new form EditorView */ public EditorView() { preInit(null, 0, null); initComponents(); postInit(); } /** Creates new form EditorView */ public EditorView(EditorViewContainer container) { preInit(null, 0, container); initComponents(); postInit(); } public EditorView(int documentCount, EditorViewContainer container) { preInit(null, documentCount, container); initComponents(); postInit(); } public EditorView(File input, EditorViewContainer container) { preInit(input, -1, container); initComponents(); postInit(input); } private void preInit(File input, int documentCount, EditorViewContainer container) { UNTITLED = "Untitled"; this.container = container; this.storage = input; if (storage == null) { newFile = true; Title = UNTITLED + "-" + String.valueOf(documentCount); } else { newFile = false; Title = storage.getName(); } modified = false; } private void postInit() { if (container != null) { container.notifyDocumentModified(getTitleWithModificationIndicator(), modified); } } private void postInit(File f) { this.storage = f; this.Title = storage.getName(); this.newFile = false; if (container != null) { container.notifyDocumentModified(getTitleWithModificationIndicator(), modified); } } public void initEditor(JPopupMenu popupmenu, Font f, String[] colors) { //jEditorPane1.setTransferHandler(null); this.popupMenu = popupmenu; jsyntaxpane.DefaultSyntaxKit.initKit(); jEditorPane1.setContentType("text/minijava"); jEditorPane1.setFont(f); if (this.isNewFile()) { createEmptyFile(); } else { loadFile(this.storage); } this.setEditorColors(colors); jEditorPane1.getDocument().addDocumentListener(this); jEditorPane1.addCaretListener(this); jEditorPane1.getDocument().addUndoableEditListener(this); container.notifyCaretChanged(null); jEditorPane1.invalidate(); } public void insertText(String text) { this.jEditorPane1.replaceSelection(text); } public Font getEditorFont() { return jEditorPane1.getFont(); } public JEditorPane getEditorPane(){ return this.jEditorPane1; } public SyntaxDocument getDocument(){ return this.document; } public void requestFocusOnEditor(){ this.jEditorPane1.requestFocus(); } public void clearHighlights(){ this.jEditorPane1.getHighlighter().removeAllHighlights(); } public void highlightCurrentLine(Color highlightColor){ int position = jEditorPane1.getCaretPosition(); int lineStart = document.getLineStartOffset(position); int lineEnd = document.getLineEndOffset(position); DefaultHighlightPainter redPainter = new DefaultHighlighter.DefaultHighlightPainter( highlightColor ); try { this.jEditorPane1.getHighlighter().addHighlight( lineStart, lineEnd, redPainter ); } catch(BadLocationException ble) { } } public Object highlight(int start, int end, Color highlightColor){ DefaultHighlightPainter redPainter = new DefaultHighlighter.DefaultHighlightPainter( highlightColor ); try { return this.jEditorPane1.getHighlighter().addHighlight( start, end, redPainter ); } catch(BadLocationException ble) { return null; } } public void print(){ ((JMiniJavaEditorPane)jEditorPane1).printContents(); } public Color getKeywordColor(){ try{ return SyntaxStyles.getInstance().getStyle(TokenType.KEYWORD).getColor(); } catch(Exception e){ return Color.BLACK; } } public Vector<Font> getFixedWidthFonts(){ Vector<Font> result = new Vector<Font>(); int size = 14; int wWidth = -1; int iWidth = -1; GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); BufferedImage tmp = new BufferedImage(100, 100, BufferedImage.TYPE_INT_RGB); Graphics g = tmp.getGraphics(); String[] fontNames = ge.getAvailableFontFamilyNames(); Font f =null; FontMetrics fm = null; for(int i=0; i<fontNames.length; i++){ f = new Font(fontNames[i], Font.PLAIN, size); fm = g.getFontMetrics(f); wWidth = fm.charWidth('W'); iWidth = fm.charWidth('i'); if((wWidth!=0) && (wWidth == iWidth) ){ result.add(f); } } return result; } public Color[] getEditorColors(){ Color[] colors = new Color[8]; SyntaxStyles styles = SyntaxStyles.getInstance(); colors[0] = styles.getStyle(TokenType.KEYWORD).getColor(); colors[1] = styles.getStyle(TokenType.NUMBER).getColor(); colors[2] = styles.getStyle(TokenType.STRING).getColor(); colors[3] = styles.getStyle(TokenType.OPERATOR).getColor(); colors[4] = styles.getStyle(TokenType.COMMENT).getColor(); colors[5] = styles.getStyle(TokenType.TYPE).getColor(); colors[6] = styles.getStyle(TokenType.IDENTIFIER).getColor(); colors[7] = styles.getStyle(TokenType.DEFAULT).getColor(); return colors; } public String[] getEditorColorsAsStrings(){ String[] colors = new String[8]; SyntaxStyles styles = SyntaxStyles.getInstance(); colors[0] = styles.getStyle(TokenType.KEYWORD).getColorString(); colors[1] = styles.getStyle(TokenType.NUMBER).getColorString(); colors[2] = styles.getStyle(TokenType.STRING).getColorString(); colors[3] = styles.getStyle(TokenType.OPERATOR).getColorString(); colors[4] = styles.getStyle(TokenType.COMMENT).getColorString(); colors[5] = styles.getStyle(TokenType.TYPE).getColorString(); colors[6] = styles.getStyle(TokenType.IDENTIFIER).getColorString(); colors[7] = styles.getStyle(TokenType.DEFAULT).getColorString(); return colors; } public void setEditorColors(Color[] colors){ if(colors.length>=8){ SyntaxStyles styles = SyntaxStyles.getInstance(); styles.getStyle(TokenType.KEYWORD).setColorString(colorToHex(colors[0])); styles.getStyle(TokenType.NUMBER).setColorString(colorToHex(colors[1])); styles.getStyle(TokenType.STRING).setColorString(colorToHex(colors[2])); styles.getStyle(TokenType.OPERATOR).setColorString(colorToHex(colors[3])); styles.getStyle(TokenType.COMMENT).setColorString(colorToHex(colors[4])); styles.getStyle(TokenType.TYPE).setColorString(colorToHex(colors[5])); styles.getStyle(TokenType.IDENTIFIER).setColorString(colorToHex(colors[6])); styles.getStyle(TokenType.DEFAULT).setColorString(colorToHex(colors[7])); } } public void setEditorColors(String[] colors){ if(colors.length>=8){ SyntaxStyles styles = SyntaxStyles.getInstance(); styles.getStyle(TokenType.KEYWORD).setColorString(colors[0]); styles.getStyle(TokenType.NUMBER).setColorString(colors[1]); styles.getStyle(TokenType.STRING).setColorString(colors[2]); styles.getStyle(TokenType.OPERATOR).setColorString(colors[3]); styles.getStyle(TokenType.COMMENT).setColorString(colors[4]); styles.getStyle(TokenType.TYPE).setColorString(colors[5]); styles.getStyle(TokenType.IDENTIFIER).setColorString(colors[6]); styles.getStyle(TokenType.DEFAULT).setColorString(colors[7]); } } private String colorToHex(Color c){ int r = c.getRed(); int g = c.getGreen(); int b = c.getBlue(); String R = Integer.toHexString(r); String G = Integer.toHexString(g); String B = Integer.toHexString(b); if(R.length()==1){R = "0"+R;} if(G.length()==1){G = "0"+G;} if(B.length()==1){B = "0"+B;} return "0x"+R+G+B; } public void setEditorFont(Font font){ jEditorPane1.setFont(font); } public boolean getModified() { return this.modified; } public boolean isModified() { return this.modified; } public void setModified(boolean modified) { this.modified = modified; if (container != null) { container.notifyDocumentModified(getTitleWithModificationIndicator(), modified); } } public boolean isNewFile() { return this.newFile; } public File getFile() { return this.storage; } public String getTitle() { return this.Title; } public String getTitleWithModificationIndicator() { String s = new String(this.Title); if (this.modified) { s = s + "*"; } return s; } public String getSelectedText() { return this.jEditorPane1.getSelectedText(); } public Point getCaretPosition(){ int absoluteOffset = jEditorPane1.getCaretPosition(); int y = document.getLineNumberAt(absoluteOffset); int x = absoluteOffset - document.getLineStartOffset(absoluteOffset); return new Point(x, y); } public int getSelectionStart(){ return jEditorPane1.getSelectionStart(); } public void reset(int documentCount) { this.jEditorPane1.setText(""); this.storage = null; this.Title = UNTITLED + "-" + documentCount; this.newFile = true; setModified(false); } private void createEmptyFile() { this.document = new SyntaxDocument(new MiniJavaLexer()); jEditorPane1.setDocument(this.document); jEditorPane1.setCaretPosition(0); setModified(false); this.document.clearUndos(); } private boolean loadFile(File f) { try { this.document = new SyntaxDocument(new MiniJavaLexer()); jEditorPane1.setDocument(this.document); EditorKit kit = jEditorPane1.getEditorKit(); kit.read(new InputStreamReader(new FileInputStream(f), "UTF-8"), this.document, 0); jEditorPane1.setCaretPosition(0); setModified(false); this.document.clearUndos(); return true; } catch (FileNotFoundException fnfe) { return false; } catch (IOException ioe) { return false; } catch (Exception e) { e.printStackTrace(System.err); return false; } } public boolean saveFile(File f) { try { OutputStreamWriter w = new OutputStreamWriter(new FileOutputStream(f), "UTF-8"); BufferedWriter bw = new BufferedWriter(w); bw.write(jEditorPane1.getText()); bw.flush(); bw.close(); w.close(); this.storage = f; this.newFile = false; this.Title = storage.getName(); setModified(false); return true; } catch (IOException ioe) { return false; } } public void undo() { this.document.doUndo(); } public void redo() { this.document.doRedo(); } public boolean canUndo() { return this.document.canUndo(); } public boolean canRedo() { return this.document.canRedo(); } public void cut() { this.jEditorPane1.cut(); } public void copy() { this.jEditorPane1.copy(); } public void paste() { this.jEditorPane1.paste(); } public void deleteSelection() { this.jEditorPane1.replaceSelection(""); } public void selectAll() { this.jEditorPane1.selectAll(); } // <editor-fold defaultstate="expanded" desc="DocumentListener implementation"> /* IMPLEMENTATION OF THE DOCUMENTLISTENER INTERFACE : */ public void insertUpdate(DocumentEvent e) { setModified(true); } public void removeUpdate(DocumentEvent e) { setModified(true); } public void changedUpdate(DocumentEvent e) { setModified(true); } /* ----------------------------------------------------- */ // </editor-fold> // <editor-fold defaultstate="expanded" desc="CaretListener implementation"> public void caretUpdate(CaretEvent e) { this.container.notifyCaretChanged(e); } /* ----------------------------------------------------- */ // </editor-fold> // <editor-fold defaultstate="expanded" desc="UndoableEditListener implementation"> public void undoableEditHappened(UndoableEditEvent evt) { if (evt.getEdit().isSignificant()) { if(!canUndo()){ container.notifyFirstUndoableEditHappened(evt); } } } /* ----------------------------------------------------- */ // </editor-fold> /** This method is called from within the constructor to * initialize the form. * WARNING: Do NOT modify this code. The content of this method is * always regenerated by the Form Editor. */ @SuppressWarnings("unchecked") // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents private void initComponents() { jScrollPane1 = new javax.swing.JScrollPane(); jEditorPane1 = new JMiniJavaEditorPane(); setName("Form"); // NOI18N jScrollPane1.setName("jScrollPane1"); // NOI18N org.jdesktop.application.ResourceMap resourceMap = org.jdesktop.application.Application.getInstance(minijed.MiniJedApp.class).getContext().getResourceMap(EditorView.class); jEditorPane1.setBackground(resourceMap.getColor("jEditorPane1.background")); // NOI18N jEditorPane1.setName("jEditorPane1"); // NOI18N jEditorPane1.addMouseListener(new java.awt.event.MouseAdapter() { public void mouseClicked(java.awt.event.MouseEvent evt) { jEditorPane1MouseClicked(evt); } public void mousePressed(java.awt.event.MouseEvent evt) { jEditorPane1MousePressed(evt); } public void mouseReleased(java.awt.event.MouseEvent evt) { jEditorPane1MouseReleased(evt); } }); jScrollPane1.setViewportView(jEditorPane1); javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); this.setLayout(layout); layout.setHorizontalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 476, Short.MAX_VALUE) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(jScrollPane1, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 352, Short.MAX_VALUE) ); }// </editor-fold>//GEN-END:initComponents private void jEditorPane1MouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_jEditorPane1MouseClicked }//GEN-LAST:event_jEditorPane1MouseClicked private void jEditorPane1MousePressed(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_jEditorPane1MousePressed if (evt.isPopupTrigger()) { this.popupMenu.show(evt.getComponent(), evt.getX(), evt.getY()); } }//GEN-LAST:event_jEditorPane1MousePressed private void jEditorPane1MouseReleased(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_jEditorPane1MouseReleased if (evt.isPopupTrigger()) { this.popupMenu.show(evt.getComponent(), evt.getX(), evt.getY()); } }//GEN-LAST:event_jEditorPane1MouseReleased // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JEditorPane jEditorPane1; private javax.swing.JScrollPane jScrollPane1; // End of variables declaration//GEN-END:variables }