XMLContainer container = new XMLContainer();
container.getAccessiblity().setText( "<test></test>" );
...
// After terminating to use the container we dispose it
// This operation is necessary for the garbage collector job
// Except if you initialize the container with the second constructor
XMLContainer( true )
container.dispose();
com.japisoft.xmlpad.toolkit.SingleDocumentEditor.showEditor(
"c:/conf.xml", false );
com.japisoft.xmlpad.toolkit.MultipleDocumentEditor.showEditor(
new File( "c:/tmp/xmlpad/xmlpad/samples/xml-data" ), null );
package demo;
import com.japisoft.xmlpad.XMLContainer;
import java.awt.*;
import javax.swing.*;
/** Simple component usage */
public class Demo extends JFrame {
public Demo() {
getContentPane().add( new XMLContainer().getView()
);
setSize( new Dimension( 550,
400 ) );
setTitle( "XMLPad simple
demo" );
setVisible( true );
}
public static void main( String[] args ) {
new Demo();
}
}
package demo;
import com.japisoft.xmlpad.*;
import com.japisoft.xmlpad.action.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
/** Simple usage of the <code>XMLContainer</code>
toolbar action model
@version 1.1
*/
public class Demo extends JFrame {
public Demo() {
XMLContainer
mContainer = new XMLContainer();
getContentPane().add(
mContainer.getView() );
setSize( new Dimension( 550,
400 ) );
setTitle( "JXMLPad
application demo" );
resetMenu(
mContainer.getToolBarModel() );
setVisible( true );
}
private void resetMenu( ToolBarModel model ) {
JMenuBar menuBar = new
JMenuBar();
JMenu file = new JMenu(
"File" );
menuBar.add( file );
setJMenuBar( menuBar );
// I retreive all Action
instances from the
// current ActionModel
Action[] fileAction = new
Action[] {
ActionModel.getActionByName(
ActionModel.NEW_ACTION ),
ActionModel.getActionByName(
ActionModel.LOAD_ACTION ),
ActionModel.getActionByName(
ActionModel.SAVE_ACTION ),
ActionModel.getActionByName(
ActionModel.SAVEAS_ACTION )
};
buildMenu( fileAction, file
);
}
private void buildMenu( Action[] actions, JMenu menu
) {
for ( int i = 0; i <
actions.length; i++ ) {
JMenuItem item = ( JMenuItem )menu.add( actions[ i ] );
item.setText( "" + actions[ i ].getValue( "ACTION.NAME" ) );
}
}
}
package demo;
import javax.swing.*;
import com.japisoft.xmlpad.XMLContainer;
/** Here an applet demonstration usage with JXMLPAD */
public class AppletDemo extends JApplet
{
public AppletDemo() {
super();
initUI();
}
private void initUI() {
getContentPane().add( new XMLContainer().getView() );
}
}
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
<!-- @(#)SwingApplet.html 1.1
97/07/02 -->
<html>
<body>
<!-- HTML CONVERTER -->
<OBJECT
classid="clsid:CAFEEFAC-0014-0000-0001-ABCDEFFEDCBA"
WIDTH = "600" HEIGHT = "400"
codebase="http://java.sun.com/products/plugin/autodl/jinstall-1_4_0_01-win.c
ab#Version=1,4,0,10">
<PARAM NAME = "CODE" VALUE = "demo.AppletDemo" >
<PARAM NAME = "ARCHIVE" VALUE = "../lib/xmlpad.
./lib/xmlpad.jar
" >
<PARAM NAME = "JAVA_CODEBASE" VALUE = "classes">
<PARAM NAME="type"
VALUE="application/x-java-applet;jpi-version=1.4.0_01">
<PARAM NAME="scriptable" VALUE="false">
<COMMENT>
<EMBED
type="application/x-java-applet;jpi-version=1.4.0_01"
CODE
= "demo.AppletDemo"
ARCHIVE = "../lib/xmlpad.jar"
JAVA_CODEBASE = "classes"
WIDTH = "600"
HEIGHT = "400"
scriptable="false"
pluginspage="http://java.sun.com/products/plugin/index.html#download">
<NOEMBED>
</NOEMBED>
</EMBED>
</COMMENT>
</OBJECT>
<!--
<APPLET CODE = "demo.AppletDemo" CODEBASE="res" ARCHIVE =
"
../lib/xmlpad.
./lib/xmlpad.jar
" WIDTH = "600" HEIGHT
= "400">
</APPLET>
-->
<!--"END_CONVERTED_APPLET"-->
</body>
</html>
public class MultipleDocumentEditor extends JFrame implements
ChangeListener {
private JToolBar toolBar;
private JTabbedPane tabbedPane;
private MultipleDocumentEditor() {
super( "Multiple editor" );
// Connection listeners for
adapting the ActionModel
to the current XMLContainer
tabbedPane.addChangeListener(
this );
}
public void stateChanged(ChangeEvent e) {
XMLContainer
container = ( XMLContainer )tabbedPane.getSelectedComponent();
ActionModel.resetActionState(
container.getEditor(), container );
}
public static MultipleDocumentEditor showEditor(
String[] files ) throws FileNotFoundException, IOException {
...
ActionModel.buildToolBar(
frame.toolBar );
// Build all containers
for ( int i = 0; i <
files.length; i++ ) {
// Calling
this constructor, the container will be automatically disposed if
// we remove it
from the tabbedpane, else we will have to call the dispose method
XMLContainer
container = new XMLContainer( true );
container.setToolBarAvailable( false );
...
}
...
}
public class InternalFrameSample implements WindowListener {
public void windowActivated(WindowEvent e) {}
public void windowClosed(WindowEvent e) {}
public void windowClosing(WindowEvent e) {
// Freeing all inner resources
// We stop using editor1 and editor2
editor1.dispose();
editor2.dispose();
}
public void windowDeactivated(WindowEvent e) {}
public void windowDeiconified(WindowEvent e) {}
public void windowIconified(WindowEvent e) {}
public void windowOpened(WindowEvent e) {}
public InternalFrameSample() {
init();
}
private XMLContainer editor1;
private XMLContainer editor2;
public void init() {
JFrame frame = new JFrame();
frame.addWindowListener( this );
JDesktopPane dp = new JDesktopPane();
// Add two inner frame
JInternalFrame editorFrameOne = new JInternalFrame();
editorFrameOne.setTitle( "My editor 1" );
// This constructor avoids XMLContainer for freeing automatically its inner reference
editor1 = new XMLContainer();
editor1.setText( "<?xml version='1.0'?>\n<test></test>" );
editorFrameOne.getContentPane().add( editor1.getView() );
editorFrameOne.setResizable( true );
dp.add( editorFrameOne );
editorFrameOne.setSize( 200, 200 );
editorFrameOne.setVisible( true );
editorFrameTwo.setVisible( true );
frame.getContentPane().add( dp );
frame.setSize( 400, 400 );
frame.setVisible( true );
}h. Tag View
XMLContainer container = new XMLContainer();
// Remove the NEW_ACTION for the default toolbar only for THIS container
container.getToolBarModel().removeAction( ActionModel.getActionByName(
Action.NEW_ACTION ) );
// Add a new one for THIS container
container.getPopupModel().addAction( myNewAction() );
// Add another one on the tree for THIS container
container.getTreePopupModel().addAction( myTreeAction() );
ActionModel.replaceActionByName(ActionModel.NEW_ACTION,
new NewAction() );
// Here my New action that write a default JSP page
class NewAction extends XMLAction
{
public NewAction() {
//
Get the same icon than the default New action
super( ActionModel.NEW_ACTION );
}
public void notifyXMLContainer()
{
// Initializing the
action for this container ?
// setEnabled( ... )
}
public void notifyAction() {
container.setText( "<%@page language=\"java\"%>\n" +
"<html>\n" +
"<body>\n" +
"</body>\n" +
"</html>" );
}
public String getName() {
return ActionModel.NEW_ACTION;
}
}
// Disable the parse and format action
ActionModel.setEnabledAction( ActionModel.REFRESH_ACTION, false );
ActionModel.setEnabledAction( ActionModel.FORMAT_ACTION, false );
// run the new action
ActionModel.activeActionByName(ActionModel.NEW_ACTION);
you can also active an action for another component
context calling
// run the new action on another component
ActionModel.activeActionByName(ActionModel.NEW_ACTION,
myXMLContainer, myXMLEditor );
factory=com.japisoft.xmlpad.ComponentFactory
look=com.japisoft.xmlpad.look.MozillaLook
tree=true
location=true
fontname=Dialog
fontsize=12
action.file.1=com.japisoft.xmlpad.action.NewAction
action.file.2=com.japisoft.xmlpad.action.LoadAction
action.file.3=com.japisoft.xmlpad.action.SaveAsAction
action.edit.1=com.japisoft.xmlpad.action.CutAction
action.edit.2=com.japisoft.xmlpad.action.CopyAction
action.edit.3=com.japisoft.xmlpad.action.PasteAction
groupOrder=file,edit
Name |
ActionModel Default |
Role |
New |
Yes |
Build a new XML document. This action uses the XMLTemplate
class for building a new page. |
Load |
Yes | Load an XML document |
SaveAs |
Yes | Save an XML document |
Copy |
Yes | Copy a text |
Cut |
Yes | Cut a text |
Paste |
Yes | Paste a text |
Undo |
Yes | Undo the last action but this is a new document
action |
Redo |
Yes | Redo the last action but to undo action has been
called |
Parse | Yes | Parse the current document and show any error in
red |
Search |
Yes | Parse the current document and show a tree for
easily navigating |
Split |
Yes | Split the current editor in two ones |
Format |
Yes | Ident the current XML text. |
Tree
visibility |
False |
Show/Hide the realtime tree |
Copy
node |
Yes |
Copy the current tree node |
Cut node |
Yes |
Cut the current tree node |
Comment
node |
Yes |
Comment the current tree node |
Select
node |
Yes |
Select the current tree node in
text |
Edit
node |
Yes |
Use the editor model : VIII |
addTagDescriptor
method
on the SyntaxHelper.
<!-- Here a minimal DTD for JSP page -->
<!ELEMENT html (head,body)>
<!ELEMENT head (title)>
<!ELEMENT title #PCDATA>
<!ELEMENT body
(jsp:include|jsp:getProperty|jsp:setProperty|jsp:useBean)>
<!ELEMENT jsp:include EMPTY>
<!ATTLIST jsp:include
page CDATA #REQUIRED>
<!ELEMENT jsp:getProperty EMPTY>
<!ATTLIST jsp:getProperty
name CDATA #REQUIRED
property CDATA #REQUIRED>
<!ELEMENT jsp:setProperty EMPTY>
<!ATTLIST jsp:setProperty
property CDATA #REQUIRED
value CDATA #REQUIRED>
<!ELEMENT jsp:useBean EMPTY>
<!ATTLIST jsp:useBean
id CDATA #REQUIRED
scope CDATA #REQUIRED>
<!DOCTYPE Module SYSTEM
"file:///home/japisoft/test/project/myDTD.dtd">
public class Demo extends JFrame implements LocationListener {
private JLabel sb;
public Demo() {
XMLContainer container;
getContentPane().add( ( container = new
XMLContainer() ).getView()
);
getContentPane().add( sb = new JLabel( "..." ),
BorderLayout.SOUTH );
setSize( new Dimension( 550, 400 ) );
setTitle( "XMLPad statusbar demo" );
// Disable the inner statusbar
container.setStatusBarAvailable(
false );
// Connect the listener for location
container.addLocationListener(
this );
setVisible( true );
}
public void locationChanged(
LocationEvent e ) {
sb.setText( e.getXPathLocation()
);
}
}
setStatusBarAvailable( false )
else two status bars would be visible.
GreenTheme.install();
JFrame fr = new JFrame();
XMLContainer container = new XMLContainer();
//We don't want the element view
//container.setElementView( null );
fr.getContentPane().add( container.getView() );
fr.setSize( 300, 300 );
fr.setVisible( true );
For defining or updating a theme, look at the UIManager section for a complete properties listing. Note that the following Look and Feel system will be deprecated. We advise you to use the UIManager for commodity.
Here a sample from the default lookAndFeel : package com.japisoft.xmleditor.look;
import java.awt.*;
import com.japisoft.xmleditor.bean.XMLEditor;
import com.japisoft.xmleditor.bean.XMLTemplate;
/**
* Default look for the <code>XMLEditor</code>
*
* @author (c) 2002 JAPISoft
* @version 1.0
* @see Look
* @see LookManager */
public class DefaultLook implements Look
{
public DefaultLook() {
super();
}
public void install( XMLContainer container,XMLEditor
editor ) {
editor.setErrorLineColor(
new Color( 200, 0, 0 ) );
// Syntax Colorization
editor.setCommentColor( new
Color( 255, 0, 0 ) );
// <? and <!
editor.setDeclarationColor(
Color.gray.darker() );
editor.setDocTypeColor(
Color.gray.darker() );
editor.setTagColor(
Color.green.darker().darker() );
editor.setLiteralColor(
Color.blue );
// Tag delimiter
editor.setTagDelimiterHighlight( true );
editor.setTagDelimiterHighlightColor( editor.getTagColor().brighter() );
// Att delimiter
editor.setAttDelimiterHighlight( true );
editor.setAttDelimiterHighlightColor( new Color( 100, 100, 150 ) );
editor.setCaretColor(
Color.black );
editor.setEntityColor(
Color.blue );
editor.setSelectionLineColor( new Color( 150, 150, 230 ) );
editor.setBackground(
Color.lightGray );
editor.setForeground(
Color.black );
editor.setDeclarationFont(
new Font( null, Font.BOLD, 10 ) );
editor.setDocTypeFont( new
Font( null, Font.BOLD, 10 ) );
editor.getCaret().setBlinkRate( 500 );
// Template
XMLTemplate
template = new XMLTemplate();
template.setComment( "
Version : 1.0, Date : " + new java.util.Date() );
editor.setTemplate( template
);
}
public void uninstall( XMLEditor
editor ) {
}
}
com.japisoft.xmlpad.look.XMLPadLook |
The default one |
com.japisoft.xmlpad.look.MozillaLook |
A very similar look than the
default one except on the tree part |
com.japisoft.xmlpad.look.IELook |
An "Internet explorer" look |
Property name |
Property role |
Default value |
factory |
Components for the XMLContainer like the
toolbar, the editor... |
com.japisoft.xmlpad.ComponentFactory |
look |
The Default lookAndFeel |
com.japisoft.xmlpad.look.XMLPadLook |
tree |
Show the real time tree |
true |
location |
Localize the current cursor in the tree |
true |
fontname |
Font name |
Dialog |
fontsize |
Font size |
12 |
public class DefaultEditor implements Editor {
/** Accept all text node : by checking
<code>isText</code> */
public boolean accept(SimpleNode node) {
return ( node.isText() );
}
/*
* Edit a text node by showing a Text dialog
*/
public void edit(EditorContext context) {
XMLContainer container =
context.getXMLContainer();
...
context.setResult(
dialog.getText() );
}
}
"Different vendors provide different implementations of this abstract class. Java chooses the one to use based on the following conditions in order of preference:
The value of the javax.xml.parsers.DocumentBuilderFactory Java system property
The value of the javax.xml.parsers.DocumentBuilderFactory property specified in the lib/jaxp.properties properties file in the JRE directory
The first value found in a META-INF/services/javax.xml.parsers.DocumentBuilderFactory file in the JAR files available to the runtime
The platform default (org.apache.crimson.jaxp.DocumentBuilderFactoryImpl in Sun’s JDK 1.4)."
System.setProperty( "javax.xml.parsers.SAXParserFactory",
"org.apache.xerces.jaxp.SAXParserFactoryImpl" );
# Copy action, you can override these values
LABEL=Copy
TOOLTIP=Copy the current selection
#MNEMONIC=C
ACCELERATOR=ctrl C
#GROUP=Edit
#ICON=com/japisoft/xmlpad/ac
# Copy action, you can override these values
LABEL=Copier
TOOLTIP=Copier la sélection
#MNEMONIC=C
ACCELERATOR=ctrl C
#GROUP=Edit
#ICON=com/japisoft/xmlpad/action/edit/CopyAction16.gif
Note about the ACCELERATOR property : you can specify a cross-platform
menu activator using '*'. For instance '* C' means
ctrl C for XP by command C for Mac OS X.
// Here a sub class for the internal frame that contains an XMLContainer
public class DemoInternalFrame2 extends JInternalFrame {
private XMLContainer container;
// This is the common tree and we specify the first one having the focus
public DemoInternalFrame2( JTree sharedTree, boolean focus ) {
super();
container = new XMLContainer();
// This is the initial focus
if ( focus )
container.focus();
else
container.unfocus();
// We shared this tree
container.setTreeDelegate( sharedTree );
getContentPane().add( container );
// Here a listener for detecting that our container looses the focus
addInternalFrameListener( new CustomInternalFrameAdapter() );
}
// It is important to have only one container having the focus at a time
class CustomInternalFrameAdapter extends InternalFrameAdapter {
public void internalFrameClosed( InternalFrameEvent e ) {
// We dispose the container
container.dispose();
}
public void internalFrameActivated( InternalFrameEvent e) {
// We unfocus the previous focus container
JDesktopPane dp = getDesktopPane();
JInternalFrame[] frame = dp.getAllFrames();
for ( int i = 0; i < frame.length; i++ ) {
if ( frame[ i ] instanceof DemoInternalFrame2 ) {
if ( ( ( DemoInternalFrame2 )frame[ i ] ).container.hasFocus() ) {
( ( DemoInternalFrame2 )frame[ i ] ).container.unfocus();
break;
}
}
}
// Notify the container that he has the focus
container.focus();
}
}
public static void main( String[] args ) {
JFrame fr = new JFrame();
final JDesktopPane dp = new JDesktopPane();
fr.getContentPane().add( dp );
JInternalFrame treeFrame = new JInternalFrame( "Tree" );
// We build here the tree shared by several XMLContainer
final JTree sharedTree = new JTree();
// We update the "look-and-feel" of the tree
LookManager.install( sharedTree );
treeFrame.getContentPane().add( sharedTree );
dp.add( treeFrame );
treeFrame.setBounds( 10, 10, 100, 300 );
treeFrame.setResizable( true );
treeFrame.setVisible( true );
// Editor 1
DemoInternalFrame2 innerFrame1 = new DemoInternalFrame2( sharedTree, true );
dp.add( innerFrame1 );
innerFrame1.setBounds( 150, 10, 200, 300 );
innerFrame1.setResizable( true );
innerFrame1.setClosable( true );
innerFrame1.setVisible( true );
// Editor 2
...In this sample we have one shared tree between two internal frames. Each time a frame is activated with call the
}
public class DemoBookmark extends JFrame {
private BookmarkContext bookmarks;
private XMLContainer container;
public DemoBookmark() {
container = new XMLContainer();
container.setBookmarkContext(
bookmarks = new DefaultBookmarkContext(
new ImageIcon( getClass().getResource( "bookmark.gif" ) ),
new Color( 200, 200, 250 ) ) );
// We add an action inside the container toolbar for listing the bookmarked lines
container.getToolBarModel().addAction(
new ListBookmarks() );
getContentPane().add( container.getView() );
}
// Action that lists the "bookmarked" lines
class ListBookmarks extends AbstractAction {
public ListBookmarks() {
putValue(
Action.SMALL_ICON,
new ImageIcon( getClass().getResource( "bookmark.gif" ) ) );
}
public void actionPerformed( ActionEvent e ) {
XMLDocument doc = container.getDocument();
// We get all the current marks
BookmarkModel model = bookmarks.getModel();
for ( int i = 0; i < model.getBookmarkCount(); i++ ) {
BookmarkPosition pos = model.getBookmarkPositionAt( i );
int offset = pos.getOffset();
// We convert the offset to a line number
int line = doc.getDefaultRootElement().getElementIndex( offset );
System.out.println( "Bookmark at " + line );
}
}
}
public static void main(String[] args) {
DemoBookmark frame = new DemoBookmark();
frame.setBounds( 10, 10, 600, 400 );
frame.setVisible( true );
}
}
package test;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import com.japisoft.dtdparser.DTDMapper;
import com.japisoft.dtdparser.node.RootDTDNode;
/**
* Here a sample for loading and managing a DTD from the
* classpath
* @author (c) 2004 JAPISoft / http://www.japisoft.com
* @version 1.0
* */
public class ClasspathDTDMapper implements DTDMapper {
// We override the DTD url
for using this local foo.dtd available
// From the classpath
public InputStream
getStream( String url ) throws IOException {
if ( "http://www.foo.com/foo.dtd".equals( url ) )
return getClass().getResourceAsStream( "foo.dtd" );
return null;
}
// We have no cache
public boolean
isCachedEnabled() {
return false;
}
// We use this feature
available only if the cache is enabled
public File
updateCache(RootDTDNode root, String url) {
return null;
}
}
DTDMapperFactory.setDTDMapper( new
ClasspathDTDMapper() );
setRelaxNGValidationLocation
method from the SchemaAccessibility class (available from the
XMLContainer). Inside this locator, an inputstream or a reader is
available. XMLContainer container = new XMLContainer();
container.getSchemaAccessibility().setRelaxNG( new SchemaLocator(
getClass().getResourceAsStream( "foo.rng" ) ) );