/*
* (c) 2005-2009 Carlos G�mez Rodr�guez, todos los derechos reservados / all rights reserved.
* Licencia en license/bsd.txt / License in license/bsd.txt
*
* Created at regulus on 23-jul-2005 22:27:32
* as file JSyntaxBSHCodePanel.java on package org.f2o.absurdum.puck.gui.panels
*/
package org.f2o.absurdum.puck.gui.panels.code;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.util.StringTokenizer;
import javax.swing.Action;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JEditorPane;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JSeparator;
import javax.swing.JTextPane;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
import javax.swing.event.CaretEvent;
import javax.swing.event.CaretListener;
import javax.swing.text.BadLocationException;
import javax.swing.text.EditorKit;
import javax.swing.undo.UndoManager;
import jsyntaxpane.CompoundUndoMan;
import jsyntaxpane.DefaultSyntaxKit;
import jsyntaxpane.actions.DocumentSearchData;
import jsyntaxpane.components.Markers;
import org.f2o.absurdum.puck.gui.SpacingPanel;
import org.f2o.absurdum.puck.gui.codeassist.CodeAssistMenuHandler;
import org.f2o.absurdum.puck.gui.codeassist.CodeInsertActionBuilder;
import org.f2o.absurdum.puck.gui.panels.EntityPanel;
import org.f2o.absurdum.puck.i18n.UIMessages;
import org.f2o.absurdum.puck.util.swing.EnhancedJEditTextArea;
import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea;
import org.fife.ui.rsyntaxtextarea.SyntaxConstants;
import org.fife.ui.rtextarea.RTextScrollPane;
import org.jedit.syntax.JEditTextArea;
import org.jedit.syntax.JavaTokenMarker;
import org.jedit.syntax.SyntaxDocument;
import org.jedit.syntax.TextAreaDefaults;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.Text;
/**
* @author carlos
*
* Created at regulus, 23-jul-2005 22:27:32
*/
public class RSyntaxBSHCodePanel extends BSHCodePanel
{
/**The code editing component in this code panel*/
private RSyntaxTextArea theTextArea;
/**Button to enlarge the code, opening a frame*/
private JButton enlButton = new JButton(UIMessages.getInstance().getMessage("button.enl"));
/**Frame opened when the enlarge button is pressed*/
private RSyntaxBSHCodeFrame auxFrame;
/**Context attribute: specifies which type of panel it is, used to know which code templates are available on menus*/
private String context;
/**Entity panel corresponding to this code panel, if any*/
private EntityPanel entityPanel;
/**Label for line numbers*/
final JLabel lineNumLabel = new JLabel(" : ");
public void unsetCodeFrame()
{
auxFrame = null;
}
/**
* Updates the line number label. May be pulled up.
*/
private void updateLineNumberLabel()
{
int line = RSyntaxBSHCodeFrame.getCaretRowPosition(theTextArea);
int column = RSyntaxBSHCodeFrame.getCaretColumnPosition(theTextArea);
lineNumLabel.setText((line+1) + " : " + (column+1));
}
/**
* Obtains the context attribute.
* @return
*/
public String getContext()
{
return context;
}
public RSyntaxBSHCodePanel ( )
{
this ( "noContext" );
}
//jsyntax-specific:
/*
private DocumentSearchData searchData = null;
private void saveSearchDialogs()
{
searchData = (DocumentSearchData)jep.getDocument().getProperty("SearchData");
}
void restoreSearchDialogs()
{
jep.getDocument().putProperty("SearchData",searchData);
}
*/
public RSyntaxBSHCodePanel ( String context )
{
this ( context, null );
}
public String getPanelName()
{
if ( entityPanel == null )
return "Code editing";
else
return entityPanel.getPanelName() + " - " + "Code editing";
}
public RSyntaxBSHCodePanel ( String context , EntityPanel ep )
{
this.context = context;
this.entityPanel = ep;
setBorder(BorderFactory.createTitledBorder(UIMessages.getInstance().getMessage("bsh.code")));
//jep = new JEditorPane();
//jsyntax-specific:
/*
TextAreaDefaults tad = new TextAreaDefaults();
tad.rows = 25;
tad.cols = 80;
DefaultSyntaxKit.initKit();
*/
//theTextArea = new RSyntaxTextArea(25,80);
theTextArea = RSyntaxTextAreaRegistry.getInstance().createSmallTextArea(25,80);
//jep = new JEditTextArea(tad);
setLayout(new BorderLayout());
auxFrame = new RSyntaxBSHCodeFrame(getPanelName(),theTextArea,context,this);
RTextScrollPane jsp = new RTextScrollPane(theTextArea);
jsp.setFoldIndicatorEnabled(true);
jsp.setPreferredSize(new Dimension(120,70));
add(new SpacingPanel(jsp),BorderLayout.CENTER);
JPanel southPanel = new JPanel();
southPanel.setLayout(new BorderLayout());
southPanel.add(enlButton,BorderLayout.CENTER);
JPanel lineNumPanel = new JPanel();
lineNumPanel.add(lineNumLabel);
lineNumPanel.setMinimumSize(new Dimension(200,100));
lineNumPanel.setPreferredSize(new Dimension(40,1));
southPanel.add(lineNumPanel,BorderLayout.EAST);
add(new SpacingPanel(southPanel),BorderLayout.SOUTH);
//add(enlButton,BorderLayout.SOUTH);
enlButton.addActionListener ( new ActionListener()
{
public void actionPerformed ( ActionEvent evt )
{
//Markers.removeMarkers(jep); //jsyntax-specific
//jep.getDocument().putProperty("SearchData",null); //with this we discard the find/replace dialog instances associated with the document.
//saveSearchDialogs(); //jsyntax-specific
//TODO: remove the previous line when JSyntaxPane is updated so that dialogs are associated to (document,editor) pairs rather than to documents.
//Doing this refresh seemed to be necessary with JSyntaxPane for some reason I don't remember. But with RSyntaxTextArea, it's counterproductive
//(the setDocument() it does seems to clear the undo history for some reason):
//auxFrame.refresh();
auxFrame.setVisible(true);
}
}
);
//jep.addPopupMenu(CodeAssistMenuHandler.getInstance().getMenuForContext(context, new CodeInsertActionBuilder(jep)));
theTextArea.addCaretListener ( new CaretListener()
{
public void caretUpdate(CaretEvent e)
{
updateLineNumberLabel();
}
}
);
RSyntaxBSHCodeFrame.setDefaults ( theTextArea );
RSyntaxBSHCodeFrame.configureMenus ( theTextArea , context );
RSyntaxBSHCodeFrame.configureSyncedMenus ( auxFrame.getTextArea() , theTextArea );
auxFrame.refresh(); //because configureSyncedMenus sets a theme and that overrides the font size with an undesirable font size.
}
public String getCode()
{
return theTextArea.getText();
}
public Node getXML ( Document d )
{
if (theTextArea.getText() == null || theTextArea.getText().length() == 0)
return null;
Element result = d.createElement("Code");
result.setAttribute("language","BeanShell");
/*
System.err.println(this);
System.err.println(jep.getText());
String text = jep.getText();
System.err.println("t1: " + text.indexOf("\n"));
System.err.println("t2: " + text.indexOf("\n\r"));
System.err.println("t3: " + text.indexOf("\r"));
System.err.println("t4: " +text.indexOf("\r\n"));
System.err.println("t5: " +text.indexOf("\n\n"));
try
{
text = jep.getDocument().getText(0, jep.getDocument().getLength()-1);
}
catch ( BadLocationException ble ) {}
System.err.println("t1: " + text.indexOf("\n"));
System.err.println("t2: " + text.indexOf("\n\r"));
System.err.println("t3: " + text.indexOf("\r"));
System.err.println("t4: " +text.indexOf("\r\n"));
System.err.println("t5: " +text.indexOf("\n\n"));
*/
//result.appendChild(d.createCDATASection(jep.getText()));
try
{
result.appendChild(d.createCDATASection(theTextArea.getDocument().getText(0, theTextArea.getDocument().getLength())));
}
catch ( BadLocationException ble ) { ble.printStackTrace(); }
return result;
}
//from Code node
public void initFromXML ( org.w3c.dom.Node n )
{
NodeList nl = n.getChildNodes();
String theCode = "";
//jep.setText("");
for ( int i = 0 ; i < nl.getLength() ; i++ )
{
Node child = nl.item(i);
if ( child instanceof Text )
{
theCode = theCode + child.getNodeValue();
//jep.setText(jep.getText()+child.getNodeValue());
}
}
theTextArea.setText(theCode.trim());
//jsyntaxpane.SyntaxDocument)jep.getDocument()).clearUndos(); //jsyntax-specific
theTextArea.discardAllEdits(); //this should do the same.
}
}