simplyhtml-0_16_07/src/com/ 40755 0 0 0 12113727344 12634 5 ustar 0 0 simplyhtml-0_16_07/src/com/lightdev/ 40755 0 0 0 12113727343 14441 5 ustar 0 0 simplyhtml-0_16_07/src/com/lightdev/app/ 40755 0 0 0 12113727343 15221 5 ustar 0 0 simplyhtml-0_16_07/src/com/lightdev/app/shtm/ 40755 0 0 0 12113727344 16175 5 ustar 0 0 simplyhtml-0_16_07/src/com/lightdev/app/shtm/help/ 40755 0 0 0 12113727344 17125 5 ustar 0 0 simplyhtml-0_16_07/src/com/lightdev/app/shtm/help/JavaHelpSearch/ 40755 0 0 0 12113727343 21744 5 ustar 0 0 simplyhtml-0_16_07/src/com/lightdev/app/shtm/help/images/ 40755 0 0 0 12113727343 20371 5 ustar 0 0 simplyhtml-0_16_07/src/com/lightdev/app/shtm/help/topic1/ 40755 0 0 0 12113727343 20323 5 ustar 0 0 simplyhtml-0_16_07/src/com/lightdev/app/shtm/help/topic1/topic5/ 40755 0 0 0 12113727343 21526 5 ustar 0 0 simplyhtml-0_16_07/src/com/lightdev/app/shtm/help/topic15/ 40755 0 0 0 12113727343 20410 5 ustar 0 0 simplyhtml-0_16_07/src/com/lightdev/app/shtm/help/topic15/topic163/ 40755 0 0 0 12113727343 21760 5 ustar 0 0 simplyhtml-0_16_07/src/com/lightdev/app/shtm/help/topic15/topic60/ 40755 0 0 0 12113727343 21674 5 ustar 0 0 simplyhtml-0_16_07/src/com/lightdev/app/shtm/help/topic16/ 40755 0 0 0 12113727344 20412 5 ustar 0 0 simplyhtml-0_16_07/src/com/lightdev/app/shtm/help/topic16/topic103/ 40755 0 0 0 12113727343 21753 5 ustar 0 0 simplyhtml-0_16_07/src/com/lightdev/app/shtm/help/topic16/topic120/ 40755 0 0 0 12113727343 21752 5 ustar 0 0 simplyhtml-0_16_07/src/com/lightdev/app/shtm/help/topic16/topic128/ 40755 0 0 0 12113727343 21762 5 ustar 0 0 simplyhtml-0_16_07/src/com/lightdev/app/shtm/help/topic16/topic140/ 40755 0 0 0 12113727344 21755 5 ustar 0 0 simplyhtml-0_16_07/src/com/lightdev/app/shtm/help/topic16/topic152/ 40755 0 0 0 12113727344 21760 5 ustar 0 0 simplyhtml-0_16_07/src/com/lightdev/app/shtm/help/topic16/topic168/ 40755 0 0 0 12113727344 21767 5 ustar 0 0 simplyhtml-0_16_07/src/com/lightdev/app/shtm/help/topic16/topic173/ 40755 0 0 0 12113727344 21763 5 ustar 0 0 simplyhtml-0_16_07/src/com/lightdev/app/shtm/help/topic16/topic34/ 40755 0 0 0 12113727344 21677 5 ustar 0 0 simplyhtml-0_16_07/src/com/lightdev/app/shtm/help/topic16/topic4/ 40755 0 0 0 12113727344 21614 5 ustar 0 0 simplyhtml-0_16_07/src/com/lightdev/app/shtm/help/topic16/topic4/topic12/ 40755 0 0 0 12113727344 23075 5 ustar 0 0 simplyhtml-0_16_07/src/com/lightdev/app/shtm/help/topic16/topic4/topic20/ 40755 0 0 0 12113727344 23074 5 ustar 0 0 simplyhtml-0_16_07/src/com/lightdev/app/shtm/help/topic16/topic4/topic25/ 40755 0 0 0 12113727344 23101 5 ustar 0 0 simplyhtml-0_16_07/src/com/lightdev/app/shtm/help/topic16/topic4/topic39/ 40755 0 0 0 12113727344 23106 5 ustar 0 0 simplyhtml-0_16_07/src/com/lightdev/app/shtm/help/topic16/topic62/ 40755 0 0 0 12113727344 21700 5 ustar 0 0 simplyhtml-0_16_07/src/com/lightdev/app/shtm/help/topic16/topic74/ 40755 0 0 0 12113727344 21703 5 ustar 0 0 simplyhtml-0_16_07/src/com/lightdev/app/shtm/help/topic16/topic86/ 40755 0 0 0 12113727344 21706 5 ustar 0 0 simplyhtml-0_16_07/src/com/lightdev/app/shtm/help/topic22/ 40755 0 0 0 12113727344 20407 5 ustar 0 0 simplyhtml-0_16_07/src/com/lightdev/app/shtm/plugin/ 40755 0 0 0 12113727344 17473 5 ustar 0 0 simplyhtml-0_16_07/src/com/lightdev/app/shtm/resources/ 40755 0 0 0 12113727344 20207 5 ustar 0 0 simplyhtml-0_16_07/src/com/sun/ 40755 0 0 0 12113727344 13441 5 ustar 0 0 simplyhtml-0_16_07/src/com/sun/demo/ 40755 0 0 0 12113727344 14365 5 ustar 0 0 simplyhtml-0_16_07/src/de/ 40755 0 0 0 12113727344 12446 5 ustar 0 0 simplyhtml-0_16_07/src/de/calcom/ 40755 0 0 0 12113727344 13704 5 ustar 0 0 simplyhtml-0_16_07/src/de/calcom/cclib/ 40755 0 0 0 12113727344 14760 5 ustar 0 0 simplyhtml-0_16_07/src/de/calcom/cclib/text/ 40755 0 0 0 12113727344 15744 5 ustar 0 0 simplyhtml-0_16_07/src/MANIFEST.MF 100644 0 0 242 12113727343 13562 0 ustar 0 0 Manifest-Version: 1.0
Main-Class: com.lightdev.app.shtm.App
Class-Path: SimplyHTML.jar jhall.jar SimplyHTMLHelp.jar gnu-regexp.jar
Created-By: Dimitri Polivaev
simplyhtml-0_16_07/src/build.xml 100644 0 0 10360 12113727343 14013 0 ustar 0 0 AboutBox
.
*
* @param parent the parent frame of the about box
*/
public AboutBox(final Frame parent) {
super(parent);
enableEvents(AWTEvent.WINDOW_EVENT_MASK);
closeButton.addActionListener(this);
closeButton.setText(Util.getResourceString("closeBtnName"));
constructFrame();
setTitle(Util.getResourceString("aboutFrameTitle"));
pack();
}
/**
* construct the dialog contents
*/
private void constructFrame() {
/** initialize dialog components */
final Container contentPane = getContentPane();
final JPanel infoPane = new JPanel();
final JPanel imagePane = new JPanel();
final JPanel textPane = new JPanel();
final JPanel buttonPane = new JPanel();
final JPanel northPane = new JPanel();
final JPanel emptyPane = new JPanel();
final LicensePane licPane = new LicensePane(new Dimension(650, 200), LICENSE);
final JLabel imageLabel = new JLabel(new ImageIcon(this.getClass().getResource(
Util.getResourceString("splashImage"))));
final JLabel emptyLabel = new JLabel("");
final JLabel appTitleLabel = new JLabel(FrmMain.APP_NAME);
final JLabel appStageLabel = new JLabel(FrmMain.VERSION);
final JLabel appCopyrightLabel = new JLabel("Copyright (c) 2002-2008 Ulrich Hilger, Dimitry Polivaev");
final JLabel appHomepageLabel = new JLabel("http://simplyhtml.sf.net/");
/* set the dialog title */
setTitle("About this application");
/* highlight the application name with an appropriate font */
appTitleLabel.setFont(new Font("SansSerif", Font.BOLD, 12));
/* load the application image into a panel */
imagePane.setLayout(new FlowLayout());
imagePane.add(imageLabel);
imagePane.setBorder(new EtchedBorder(EtchedBorder.LOWERED));
/**
* textPane is the panel where all the application infos are shown.
* Infos are shown in a one columns grid of labels, each on one row.
*/
textPane.setLayout(new GridLayout(6, 1, 5, 5));
textPane.add(emptyLabel);
textPane.add(appTitleLabel);
textPane.add(appStageLabel);
textPane.add(appCopyrightLabel);
textPane.add(appHomepageLabel);
/**
* infoPane shows the application image and the application info text
* in a one row, two column grid.
*/
infoPane.setLayout(new GridLayout(1, 2, 5, 5));
infoPane.add(imagePane);
infoPane.add(textPane);
/**
* northPane is a helper pane to show application image and application
* info text left aligned in the upper left corner of the dialog.
*/
northPane.setLayout(new BorderLayout());
northPane.add(infoPane, BorderLayout.WEST);
northPane.add(emptyPane, BorderLayout.CENTER);
/* panel for showing the close button at the dialog bottom */
buttonPane.setLayout(new FlowLayout());
buttonPane.add(closeButton);
/**
* now put together all parts of above application info and combine them
* with license information
*/
contentPane.setLayout(new BorderLayout());
contentPane.add(northPane, BorderLayout.NORTH);
contentPane.add(licPane, BorderLayout.CENTER);
contentPane.add(buttonPane, BorderLayout.SOUTH);
}
/**
* dispose the dialog properly in case of window close events
*/
protected void processWindowEvent(final WindowEvent e) {
if (e.getID() == WindowEvent.WINDOW_CLOSING) {
cancel();
}
super.processWindowEvent(e);
}
/**
* dispose the dialog
*/
private void cancel() {
dispose();
}
/**
* implements the ActionListener interface to be notified of
* clicks onto the ok button. Closes and disposes the dialog in this case.
*/
public void actionPerformed(final ActionEvent e) {
if (e.getSource() == closeButton) {
cancel();
}
}
}
simplyhtml-0_16_07/src/com/lightdev/app/shtm/AbstractPlugin.java 100644 0 0 31662 12113727343 22106 0 ustar 0 0 /*
* SimplyHTML, a word processor based on Java, HTML and CSS
* Copyright (C) 2002 Ulrich Hilger
*
* 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 com.lightdev.app.shtm;
import java.util.Locale;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
import java.util.prefs.Preferences;
import javax.swing.Action;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JMenuItem;
/**
* Base class for plug-ins of application SimplyHTML.
*
*
Defines some common methods for reuse in plug-ins. All
* settings such as dockLocation or activation state
* of a plug-in are stored persistently in a preferences file
* with the help of class Prefs
. The preferences
* file is valid for the current user, so each user has own
* plug-in settings.
Menus are constructed with the help of class
* DynamicResource
. This class needs menu definitions
* accessible in a .properties file as described in the API docs
* of DynamicResource
. I.e., methods of class
* AbstractPlugin
only work as defined herein when
* accompanied by such .properties file accordingly.
Constructor may not have parameters so that * java.lang.Class.newInstance can be used on it.
*/ public AbstractPlugin() { //System.out.println("AbstractPlugin constructor"); /*SecurityManager security = System.getSecurityManager(); if (security != null) { security. } */ prefs = Preferences.userNodeForPackage(getClass()); } /** * init the plug-in * * this is called by the PluginManager directly after instantiating the plug-in */ public void initPlugin(final SHTMLPanelImpl owner) { this.owner = owner; } /** * create the plug-in menu */ protected void createPluginMenu() { if (pluginMenuId != null) { pMenu = owner.dynRes.createMenu(AbstractPlugin.textResources, pluginMenuId); } } /** * create the help menu */ protected void createHelpMenu() { if (helpMenuId != null) { hMenu = owner.dynRes.createMenu(AbstractPlugin.textResources, helpMenuId); initHelpMenu(); } } public void initHelpMenu() { } /** * create a frame for the component of this plug-in, if it * has a JComponent to display. */ protected void createFrame() { if (c != null) { frame = new JFrame(getGUIName()); frame.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE); frame.setSize(300, 400); frame.getContentPane().add(c); } frame.pack(); } /** * create, show or hide frame as needed, depending * on a given dock location * * @param location the dock location of the plug-in, one of * DOCK_LOCATION_TOP, DOCK_LOCATION_BOTTOM, * DOCK_LOCATION.LEFT, DOCK_LOCATION_RIGHT or DOCK_LOCATION_NONE, if the * component shall not dock. */ protected void createFrameAsNeeded(final int location) { if (location == SHTMLPlugin.DOCK_LOCATION_NONE) { if ((frame == null) && (c != null)) { createFrame(); } if (frame != null) { frame.setVisible(true); } } else { if (frame != null) { frame.setVisible(false); } } } /* ----------- SimplyHTML plugin interface implementation start --------- */ /** * initialize the plugin * * @param owner the owner of this plug-in * @param internalName the internal name this plug-in shall have * @param pluginMenuId the id of the plug-in menu in the TextResources, * or null if no plugin-in menu is to be created * @param helpMenuId the id of the help menu for this plug-in in the * TextResources, or null if no help menu is to be created */ public void initPlugin(final SHTMLPanel owner, final String internalName, final String pluginMenuId, final String helpMenuId) { this.owner = (SHTMLPanelImpl) owner; this.internalName = internalName; this.pluginMenuId = pluginMenuId; this.helpMenuId = helpMenuId; try { //System.out.println("AbstractPlugin this.getClass.getName=" + this.getClass().getName()); if (SHTMLPanelImpl.pluginManager != null) { final ClassLoader plLoader = SHTMLPanelImpl.pluginManager.getPluginLoader(); if (plLoader != null) { final ResourceBundle resourceBundle = ResourceBundle.getBundle(this.getClass().getName(), Locale.getDefault(), plLoader); textResources = new DefaultTextResources(resourceBundle); //System.out.println("AbstractPlugin plLoader != null, resources=" + resources); } else { final DefaultTextResources instance = new DefaultTextResources(ResourceBundle.getBundle(this .getClass().getName(), Locale.getDefault())); textResources = instance; //System.out.println("AbstractPlugin plLoader == null, resources=" + resources); } } else { final DefaultTextResources instance = new DefaultTextResources(ResourceBundle.getBundle(this.getClass() .getName(), Locale.getDefault())); textResources = instance; //System.out.println("AbstractPlugin pluginManager = null, resources=" + resources); } active = prefs.getBoolean(internalName + PREFSID_PLUGIN_ACTIVE, true); dockLocation = prefs.getInt(internalName + PREFSID_PLUGIN_DOCK_LOCATION, SHTMLPlugin.DOCK_LOCATION_LEFT); createFrameAsNeeded(dockLocation); } catch (final MissingResourceException mre) { Util.errMsg(null, this.getClass().getName() + ".properties not found", mre); } } /** * set the owner of this plug-in * * @param owner the main frame of the instance of SimplyHTML creating the plug-in */ public void setOwner(final SHTMLPanelImpl owner) { this.owner = owner; } /** * get the owner of this plug-in * * @return the owner of this plug-in */ public SHTMLPanelImpl getOwner() { return owner; } /** * set status of plug-in and persistently store setting in * a preferences file * * @param isActive indicates whether or not the plug-in shall be activated */ public void setStatus(final boolean isActive) { active = isActive; prefs.putBoolean(getInternalName() + PREFSID_PLUGIN_ACTIVE, isActive); try { prefs.flush(); } catch (final Exception e) { Util.errMsg(null, e.getMessage(), e); } } /** * set the location the component returned by getDockComponent() * shall be docked at. Persistently store setting in * a preferences file. * * @param location the dock location, one of DOCK_LOCATION_TOP, DOCK_LOCATION_BOTTOM, * DOCK_LOCATION.LEFT, DOCK_LOCATION_RIGHT or DOCK_LOCATION_NONE, if the * component shall not dock. */ public void setDockLocation(final int location) { dockLocation = location; prefs.putInt(getInternalName() + PREFSID_PLUGIN_DOCK_LOCATION, location); try { prefs.flush(); } catch (final Exception e) { Util.errMsg(null, e.getMessage(), e); } createFrameAsNeeded(location); } /** * get a menu of actions this plug-in provides. * *JMenu
is a decendant of JMenuItem
* so this method may return a single menu item up to a whole
* structure of submenus in its return value.
JMenu
is a decendant of JMenuItem
* so this method may return a single menu item up to a whole
* structure of submenus in its return value.
AnchorDialog
*
* @param parent the parent dialog of this dialog
* @param title the dialog title
* @param doc the document to edit anchors of
*/
public AnchorDialog(final Dialog parent, final String title, final Document doc) {
super(parent, title, helpTopicId);
initDialog(doc, null/*, renderMode*/);
}
/**
* create an AnchorDialog
*
* @param parent the parent frame of this dialog
* @param title the dialog title
* @param doc the document to edit anchors of
*/
public AnchorDialog(final Frame parent, final String title, final Document doc) {
super(parent, title, helpTopicId);
initDialog(doc, null/*, renderMode*/);
}
/**
* create an AnchorDialog
*
* @param parent the parent frame of this dialog
* @param title the dialog title
* @param url the document url
*/
public AnchorDialog(final Dialog parent, final String title, final URL url) {
super(parent, title, helpTopicId);
initDialog(null, url/*, renderMode*/);
}
/**
* create an AnchorDialog
*
* @param parent the parent frame of this dialog
* @param title the dialog title
* @param url the document url
*/
public AnchorDialog(final Frame parent, final String title, final URL url) {
super(parent, title, helpTopicId);
initDialog(null, url/*, renderMode*/);
}
/**
* initialize this AnchorDialog
*
* If a document is passed, anchors of this document * are edited. If doc is null and a url is passed, this * document is loaded (and saved).
* * @param doc the document to edit anchors of, or null * @param url the url to load a document from, or null */ private void initDialog(final Document doc, final URL url) { this.url = url; //this.renderMode = renderMode; // create anchor panel final JPanel anchorPanel = new JPanel(new BorderLayout()); anchorPanel.setBorder(new TitledBorder(new EtchedBorder(EtchedBorder.LOWERED), Util .getResourceString("anchorPanelLabel"))); //getAnchors(doc); anchorList = new JList(/*anchorTable.keySet().toArray()*/); anchorPanel.add(new JScrollPane(anchorList), BorderLayout.CENTER); anchorList.addListSelectionListener(this); addAnchor = new JButton(Util.getResourceString("addImgBtnTitle")); addAnchor.addActionListener(this); delAnchor = new JButton(Util.getResourceString("delImgBtnTitle")); delAnchor.addActionListener(this); // use a help panel to add add/del buttons JPanel helpPanel = new JPanel(); helpPanel.add(addAnchor); helpPanel.add(delAnchor); anchorPanel.add(helpPanel, BorderLayout.SOUTH); // init DocumentPane if (doc != null) { needsSaving = false; dp = new DocumentPane(/*renderMode*/); doc.addDocumentListener(this); dp.setDocument(doc); this.doc = doc; } else { needsSaving = true; dp = new DocumentPane(url, 1/*, renderMode*/); this.doc = dp.getDocument(); } // init editor to our needs editor = dp.getEditor(); editor.setEditable(false); editor.addCaretListener(this); // create document panel final JPanel docPanel = new JPanel(new BorderLayout()); docPanel.setBorder(new TitledBorder(new EtchedBorder(EtchedBorder.LOWERED), Util .getResourceString("docPanelLabel"))); docPanel.add(editor, BorderLayout.CENTER); // use a help panel to properly align anchorPanel and docPanel helpPanel = new JPanel(new BorderLayout()); helpPanel.add(anchorPanel, BorderLayout.WEST); helpPanel.add(docPanel, BorderLayout.CENTER); // get content pane of DialogShell to add components to final Container contentPane = super.getContentPane(); ((JComponent) contentPane).setPreferredSize(new Dimension(600, 500)); contentPane.add(helpPanel, BorderLayout.CENTER); // add help button // cause optimal placement of all elements pack(); updateAnchorList(); addAnchor.setEnabled(false); delAnchor.setEnabled(false); } /** * overridden to addd some custom cleanup upon closing of dialog */ public void dispose() { editor.removeCaretListener(this); doc.removeDocumentListener(this); super.dispose(); } /** * re-display the list of anchors of the document */ private void updateAnchorList() { getAnchors(doc); anchorList.setListData(anchorTable.keySet().toArray()); } /** * get the anchors of a given document * * @param doc the document to get anchors from */ private void getAnchors(final Document doc) { HTML.Tag.A.toString(); Object nameAttr; Object link; anchorTable.clear(); final ElementIterator eli = new ElementIterator(doc); Element elem = eli.first(); while (elem != null) { link = elem.getAttributes().getAttribute(HTML.Tag.A); if (link != null) { nameAttr = ((AttributeSet) link).getAttribute(HTML.Attribute.NAME); if (nameAttr != null) { //model.addElement(nameAttr); anchorTable.put(nameAttr, elem); } } elem = eli.next(); } } /** * get an anchor name and add it at the current editor location */ private void doAddAnchor() { final String anchorName = Util.nameInput(null, "", ".*", "addAnchorTitle", "addAnchorText"); if (anchorName != null) { editor.insertAnchor(anchorName); saveChanges(); updateAnchorList(); } } /** * save changes to the document */ private void saveChanges() { if (needsSaving) { if (url != null) { try { dp.saveDocument(/*renderMode*/); } catch (final Exception e) { Util.errMsg(this, e.getMessage(), e); } } } } /** * Gets the anchor currently selected in the list of anchors. * * @return the anchor name, or null if none is selected */ public String getAnchor() { String anchorName = null; if (anchorList.getSelectedIndex() > -1) { anchorName = anchorList.getSelectedValue().toString(); } return anchorName; } /** * remove an anchor from the document */ private void doDelAnchor() { final String anchorName = anchorList.getSelectedValue().toString(); dp.getEditor().removeAnchor(anchorName); saveChanges(); updateAnchorList(); } /** * ActionListener implementatin for proper handling of * buttons */ public void actionPerformed(final ActionEvent e) { final Object src = e.getSource(); if (src.equals(addAnchor)) { doAddAnchor(); } else if (src.equals(delAnchor)) { doDelAnchor(); } else { super.actionPerformed(e); } } /** * ListSelectionListener implementation to properly react to * changes in the list of anchors */ public void valueChanged(final ListSelectionEvent e) { final Object src = e.getSource(); if (src.equals(anchorList)) { //if(!ignoreAnchorListChanges) { final Highlighter h = editor.getHighlighter(); final Highlighter.HighlightPainter p = new DefaultHighlighter.DefaultHighlightPainter(Color.yellow); final Object o = anchorList.getSelectedValue(); if (o != null) { final Element elem = (Element) anchorTable.get(anchorList.getSelectedValue()); final int start = elem.getStartOffset(); int end = elem.getEndOffset(); try { if (end == start) { end = start + 3; } editor.select(start, end); h.removeAllHighlights(); h.addHighlight(start, end, p); } catch (final BadLocationException ble) { ble.printStackTrace(); } } //} } } /** * CaretListener implementation to adjust 'add anchor' button * according to whether or not a selection is present in the document * to possibly add an anchor to */ public void caretUpdate(final CaretEvent e) { final Object src = e.getSource(); if (src.equals(editor)) { addAnchor.setEnabled(editor.getSelectionStart() != editor.getSelectionEnd()); delAnchor.setEnabled(anchorList.getSelectedIndex() > -1); } } /* -------- DocumentListener implementation start ------------*/ /** * listens to inserts into the document to track whether or not the document * needs to be saved. */ public void insertUpdate(final DocumentEvent e) { updateAnchorList(); } /** * listens to removes into the document to track whether or not the document * needs to be saved. */ public void removeUpdate(final DocumentEvent e) { updateAnchorList(); } /** * listens to changes on the document to track whether or not the document * needs to be saved. */ public void changedUpdate(final DocumentEvent e) { updateAnchorList(); } /* -------- DocumentListener implementation end ------------*/ } simplyhtml-0_16_07/src/com/lightdev/app/shtm/App.java 100644 0 0 5202 12113727343 17653 0 ustar 0 0 /* * SimplyHTML, a word processor based on Java, HTML and CSS * Copyright (C) 2002 Ulrich Hilger * * 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 com.lightdev.app.shtm; import java.util.prefs.Preferences; import javax.swing.UIManager; /** * Main class of application SimplyHTML. * *This class contains method main and opens the application's main * frame.
* * @author Ulrich Hilger * @author Light Development * @author http://www.lightdev.com * @author info@lightdev.com * @author published under the terms and conditions of the * GNU General Public License, * for details see file gpl.txt in the distribution * package of this software * * */ public class App { //Main method public static void main(final String[] args) { try { final Preferences prefs = Preferences .userNodeForPackage(Class.forName("com.lightdev.app.shtm.PrefsDialog")); UIManager.setLookAndFeel(prefs.get(PrefsDialog.PREFSID_LOOK_AND_FEEL, UIManager.getCrossPlatformLookAndFeelClassName())); /* The following line causes UIManager to correctly handle alignments of menu items when they do not have an icon. At the Java Developer Connection, SKelvin writes: "If the UI class does not find an icon it can't calculate its width :-) It won't work if you just set the property to null (don't ask me why), but setting to any type other than icon works." (see http://forum.java.sun.com/thread.jsp?forum=57&thread=126150) */ //UIManager.put("Menu.checkIcon", new ImageIcon("") ); UIManager.put("Menu.checkIcon", UIManager.get("MenuItem.checkIcon")); } catch (final Exception e) { e.printStackTrace(); } FrmMain.run(); // create an instance of the app's main window } } simplyhtml-0_16_07/src/com/lightdev/app/shtm/AttributeComboBox.java 100644 0 0 16767 12113727343 22571 0 ustar 0 0 /* * SimplyHTML, a word processor based on Java, HTML and CSS * Copyright (C) 2002 Ulrich Hilger * * 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 com.lightdev.app.shtm; import javax.swing.JComboBox; import javax.swing.text.AttributeSet; import javax.swing.text.SimpleAttributeSet; import javax.swing.text.StyleConstants; import javax.swing.text.html.CSS; import javax.swing.text.html.HTML; /** * ComboBox to show and manipulate an attribute out * of a given set of attribute values. * * @author Ulrich Hilger * @author Light Development * @author http://www.lightdev.com * @author info@lightdev.com * @author published under the terms and conditions of the * GNU General Public License, * for details see file gpl.txt in the distribution * package of this software * * */ class AttributeComboBox extends JComboBox implements AttributeComponent { /** CSS attribute key associated with this component */ private final Object attributeKey; /** HTML attribute key associated with this component */ private final Object htmlAttributeKey; /** attribute names associated with the items of this component */ private final String[] names; /** indicates wether or not a call to setValue is the initial one */ private int setValCount = 0; /** stores the initial value for tracking changes */ private int originalIndex = -2; /** * construct anAttributeComboBox
*
* @param items the items to appear in the list of this component
* @param names the attributes to associate with items
* (in the same order)
* @param key the CSS attribute key this component represents
* @param htmlKey the HTL attribute key this component represents
*
* @see getValue
*/
public AttributeComboBox(final String[] items, final String[] names, final Object key, final Object htmlKey) {
super(items);
this.names = names;
attributeKey = key;
htmlAttributeKey = htmlKey;
}
/**
* set the value of this AttributeComponent
*
* @param a the set of attributes possibly having an
* attribute this component can display
*
* @return true, if the set of attributes had a matching attribute,
* false if not
*/
public boolean setValue(final AttributeSet a) {
//System.out.println("AttributeComboBox setValue");
//de.calcom.cclib.html.HTMLDiag hd = new de.calcom.cclib.html.HTMLDiag();
//hd.listAttributes(a, 2);
boolean success = false;
Object valObj;
if (attributeKey != null) {
valObj = a.getAttribute(attributeKey);
if (valObj == null && htmlAttributeKey != null) {
valObj = a.getAttribute(htmlAttributeKey);
if (valObj != null) {
success = setValue(valObj);
}
}
/*
correction start: missing list-style-type attribute from style sheet
*/
else if (valObj == null && attributeKey.equals(CSS.Attribute.LIST_STYLE_TYPE)) {
final Object name = a.getAttribute(StyleConstants.NameAttribute);
if (name != null && name.toString().equalsIgnoreCase(HTML.Tag.UL.toString())) {
success = setValue("disc");
}
else if (name != null && name.toString().equalsIgnoreCase(HTML.Tag.OL.toString())) {
success = setValue("decimal");
}
}
if (valObj == null && htmlAttributeKey != null) {
if (htmlAttributeKey.equals(HTML.Attribute.ALIGN) || htmlAttributeKey.equals(HTML.Attribute.VALIGN)) {
success = setValue(names[0]);
}
}
/*
correction end: missing list-style-type attribute from style sheet
*/
else {
//System.out.println("AttributeComboBox setValue value=" + valObj);
success = setValue(valObj);
}
}
else {
if (htmlAttributeKey != null) {
valObj = a.getAttribute(htmlAttributeKey);
if (valObj != null) {
success = setValue(valObj);
}
}
}
return success;
}
public void reset() {
setValCount = 0;
originalIndex = -2;
}
private boolean setValue(final Object valObj) {
if (valObj != null) {
final String valStr = valObj.toString();
int i = 0;
while (!valStr.equalsIgnoreCase(names[i])) {
i++;
if(i >= names.length)
return false;
}
setSelectedIndex(i);
if (++setValCount < 2) {
originalIndex = i;
}
return true;
}
return false;
}
/**
* get the value of this AttributeComponent
*
* If one an attribute key is not set, the value will not * be returned for that attribute key. If both attribute keys are * set, two attributes with identical value are returned. Up * to J2SE 1.4, the Java language does not render * CSS.Attribute.VERTICAL_ALIGN but it does render HTML.Attribute.VALIGN. * Some browsers handle it vice versa, so it is useful to * store both attributes.
* * @return the value selected from this component */ public AttributeSet getValue() { final SimpleAttributeSet a = new SimpleAttributeSet(); final int value = getSelectedIndex(); //System.out.println("AttributeComboBox getValue originalIndex=" + originalIndex + " value=" + value); if (originalIndex != value) { //System.out.println("changed " + attributeKey + " originalIndex=" + originalIndex + " value=" + value); if (attributeKey != null) { Util.styleSheet().addCSSAttribute(a, (CSS.Attribute) attributeKey, names[value]); //a.addAttribute(attributeKey, names[value]); } if (htmlAttributeKey != null) { a.addAttribute(htmlAttributeKey, names[value]); } } return a; } public AttributeSet getValue(final boolean includeUnchanged) { if (includeUnchanged) { final SimpleAttributeSet a = new SimpleAttributeSet(); final int value = getSelectedIndex(); if (attributeKey != null) { Util.styleSheet().addCSSAttribute(a, (CSS.Attribute) attributeKey, names[value]); } if (htmlAttributeKey != null) { a.addAttribute(htmlAttributeKey, names[value]); } return a; } else { return getValue(); } } } simplyhtml-0_16_07/src/com/lightdev/app/shtm/AttributeComponent.java 100644 0 0 3676 12113727343 22776 0 ustar 0 0 /* * SimplyHTML, a word processor based on Java, HTML and CSS * Copyright (C) 2002 Ulrich Hilger * * 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 com.lightdev.app.shtm; import javax.swing.text.AttributeSet; /** * Defines a set of methods common to components bound to AttributeSets. * * @author Ulrich Hilger * @author Light Development * @author http://www.lightdev.com * @author info@lightdev.com * @author published under the terms and conditions of the * GNU General Public License, * for details see file gpl.txt in the distribution * package of this software * * */ interface AttributeComponent { /** * set the value of thisAttributeComponent
*
* @param a the set of attributes possibly having an
* attribute this component can display
*
* @return true, if the set of attributes had a matching attribute,
* false if not
*/
public boolean setValue(AttributeSet a);
/**
* get the value of this AttributeComponent
*
* @return the value selected from this component
*/
public AttributeSet getValue();
public AttributeSet getValue(boolean includeUnchanged);
}
simplyhtml-0_16_07/src/com/lightdev/app/shtm/AttributeMapper.java 100644 0 0 12676 12113727343 22300 0 ustar 0 0 /*
* SimplyHTML, a word processor based on Java, HTML and CSS
* Copyright (C) 2002 Ulrich Hilger
*
* 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 com.lightdev.app.shtm;
import javax.swing.text.AttributeSet;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.html.CSS;
import javax.swing.text.html.HTML;
/**
* Maps HTML and CSS attributes to their equivalents to * compensate discrepancies in HTML and CSS rendering of * various different view environments.
* *Introduced in stage 5 this class only contains hard wired * fixes to certain discrepancies. Should there come up an increased * number of necessary fixes in future stages, a more generic way * of mapping (such as through a Hashtable of from/to values), etc. * will be done.
* * @author Ulrich Hilger * @author Light Development * @author http://www.lightdev.com * @author info@lightdev.com * @author published under the terms and conditions of the * GNU General Public License, * for details see file gpl.txt in the distribution * package of this software * * */ class AttributeMapper extends SimpleAttributeSet { public static final int toCSS = 0; public static final int toHTML = 1; public static final int toJava = 2; public AttributeMapper() { super(); } public AttributeMapper(final AttributeSet a) { super(a); } public AttributeSet getMappedAttributes(final int direction) { switch (direction) { case toCSS: mapToCSSAttributes(); break; case toHTML: mapToHTMLAttributes(); break; case toJava: mapToJavaAttributes(); break; } //System.out.println("AttributeMapper transformed attributes="); //de.calcom.cclib.html.HTMLDiag hd = new de.calcom.cclib.html.HTMLDiag(); //hd.listAttributes(this, 2); return this; } private void mapToCSSAttributes() { final Object cssFontSize = getAttribute(CSS.Attribute.FONT_SIZE); if (cssFontSize != null) { final int fontNumber = Integer.parseInt(cssFontSize.toString()); addAttribute(CSS.Attribute.FONT_SIZE, SHTMLPanelImpl.FONT_SIZES[fontNumber - 1] + "pt"); } mapToHTMLAttributes(); } private void mapToHTMLAttributes() { final Object cssFontFamily = getAttribute(CSS.Attribute.FONT_FAMILY); if (cssFontFamily != null) { if (cssFontFamily.toString().equalsIgnoreCase("SansSerif")) { addAttribute(CSS.Attribute.FONT_FAMILY, "SansSerif, Sans-Serif"); //System.out.println("mapToHTMLAttributes SansSerif, Sans-Serif"); } else if (cssFontFamily.toString().indexOf("Monospaced") > -1) { addAttribute(CSS.Attribute.FONT_FAMILY, "Monospace, Monospaced"); } } } private void mapToJavaAttributes() { final Object htmlFontFace = getAttribute(HTML.Attribute.FACE); final Object cssFontFamily = getAttribute(CSS.Attribute.FONT_FAMILY); if (htmlFontFace != null) { if (cssFontFamily != null) { removeAttribute(HTML.Attribute.FACE); if (cssFontFamily.toString().indexOf("Sans-Serif") > -1) { Util.styleSheet().addCSSAttribute(this, CSS.Attribute.FONT_FAMILY, "SansSerif"); } else if (cssFontFamily.toString().indexOf("Monospace") > -1) { Util.styleSheet().addCSSAttribute(this, CSS.Attribute.FONT_FAMILY, "Monospaced"); } } else { removeAttribute(HTML.Attribute.FACE); if (htmlFontFace.toString().indexOf("Sans-Serif") > -1) { Util.styleSheet().addCSSAttribute(this, CSS.Attribute.FONT_FAMILY, "SansSerif"); } else if (htmlFontFace.toString().indexOf("Monospace") > -1) { Util.styleSheet().addCSSAttribute(this, CSS.Attribute.FONT_FAMILY, "Monospaced"); } else { Util.styleSheet().addCSSAttribute(this, CSS.Attribute.FONT_FAMILY, htmlFontFace.toString()); } } } else { if (cssFontFamily != null) { if (cssFontFamily.toString().indexOf("Sans-Serif") > -1) { Util.styleSheet().addCSSAttribute(this, CSS.Attribute.FONT_FAMILY, "SansSerif"); } else if (cssFontFamily.toString().indexOf("Monospace") > -1) { Util.styleSheet().addCSSAttribute(this, CSS.Attribute.FONT_FAMILY, "Monospaced"); } } } } } simplyhtml-0_16_07/src/com/lightdev/app/shtm/AttributePanel.java 100644 0 0 10600 12113727343 22074 0 ustar 0 0 /* * SimplyHTML, a word processor based on Java, HTML and CSS * Copyright (C) 2002 Ulrich Hilger * * 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 com.lightdev.app.shtm; import java.awt.event.ContainerEvent; import java.awt.event.ContainerListener; import java.util.Enumeration; import java.util.Vector; import javax.swing.JPanel; import javax.swing.text.AttributeSet; import javax.swing.text.SimpleAttributeSet; /** * Panel set a group of attributes. * *Abstract base class for other panels such as margin or style panel.
* * @author Ulrich Hilger * @author Light Development * @author http://www.lightdev.com * @author info@lightdev.com * @author published under the terms and conditions of the * GNU General Public License, * for details see file gpl.txt in the distribution * package of this software * * */ abstract class AttributePanel extends JPanel implements AttributeComponent, ContainerListener { /** container for all AttributeComponents shown on this AttributePanel */ private final Vector components = new Vector(); /** * construct a new AttributePanel */ public AttributePanel() { super(); this.addContainerListener(this); } /** * set the value of thisAttributeComponent
*
* @param a the set of attributes possibly having an
* attribute this component can display
*
* @return true, if the set of attributes had a matching attribute,
* false if not
*/
public boolean setValue(final AttributeSet a) {
/*
System.out.println("AttributePanel setValue");
de.calcom.cclib.html.HTMLDiag hd = new de.calcom.cclib.html.HTMLDiag();
hd.listAttributes(a, 4);
System.out.println("\r\n");
*/
boolean result = true;
final Enumeration elements = components.elements();
AttributeComponent ac;
while (elements.hasMoreElements()) {
ac = (AttributeComponent) elements.nextElement();
if (!ac.setValue(a)) {
result = false;
}
}
return result;
}
/**
* get the value of this AttributeComponent
*
* @return the value selected from this component
*/
public AttributeSet getValue() {
final SimpleAttributeSet attributes = new SimpleAttributeSet();
final Enumeration elements = components.elements();
AttributeComponent ac;
while (elements.hasMoreElements()) {
ac = (AttributeComponent) elements.nextElement();
attributes.addAttributes(ac.getValue());
}
return attributes;
}
public AttributeSet getValue(final boolean includeUnchanged) {
if (includeUnchanged) {
final SimpleAttributeSet attributes = new SimpleAttributeSet();
final Enumeration elements = components.elements();
AttributeComponent ac;
while (elements.hasMoreElements()) {
ac = (AttributeComponent) elements.nextElement();
attributes.addAttributes(ac.getValue(includeUnchanged));
}
return attributes;
}
else {
return getValue();
}
}
public void componentAdded(final ContainerEvent e) {
final Object component = e.getChild();
if (component instanceof AttributeComponent) {
components.add(component);
}
}
public void componentRemoved(final ContainerEvent e) {
final Object component = e.getChild();
if (component instanceof AttributeComponent) {
components.remove(component);
}
}
}
simplyhtml-0_16_07/src/com/lightdev/app/shtm/BorderPanel.java 100644 0 0 21652 12113727343 21357 0 ustar 0 0 /*
* SimplyHTML, a word processor based on Java, HTML and CSS
* Copyright (C) 2002 Ulrich Hilger
*
* 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 com.lightdev.app.shtm;
import java.awt.Color;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.util.Enumeration;
import java.util.Vector;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.border.EtchedBorder;
import javax.swing.border.TitledBorder;
import javax.swing.text.AttributeSet;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.html.CSS;
/**
* Panel to show and manipulate border settings for a rectangular
* object such as a table cell
*
* @author Ulrich Hilger
* @author Light Development
* @author http://www.lightdev.com
* @author info@lightdev.com
* @author published under the terms and conditions of the
* GNU General Public License,
* for details see file gpl.txt in the distribution
* package of this software
*
*
*/
class BorderPanel extends JPanel implements AttributeComponent {
private final Vector components = new Vector();
/** the attributes for border width */
private CombinedAttribute bWidth;
/** the attributes for border color */
private CombinedAttribute bColor;
/** the color value to compare to for determining changes */
private String oColor;
/** the width value to compare to for determining changes */
private String oWidth;
/** indicates if a call to setValue is for initial setting or for changes */
private int setValueCalls = 0;
public BorderPanel() {
super();
// set layout
final GridBagLayout g = new GridBagLayout();
setLayout(g);
// constraints to use on our GridBagLayout
final GridBagConstraints c = new GridBagConstraints();
addSettings(g, c, Util.getResourceString("topLabel"), CombinedAttribute.ATTR_TOP, 0, 0);
addSettings(g, c, Util.getResourceString("rightLabel"), CombinedAttribute.ATTR_RIGHT, 1, 1);
addSettings(g, c, Util.getResourceString("bottomLabel"), CombinedAttribute.ATTR_BOTTOM, 1, 0);
addSettings(g, c, Util.getResourceString("leftLabel"), CombinedAttribute.ATTR_LEFT, 0, 1);
}
private void addSettings(final GridBagLayout g, final GridBagConstraints c, final String title, final int side,
final int x, final int y) {
final BorderSettings bs = new BorderSettings(title, side);
Util.addGridBagComponent(this, bs, g, c, x, y, GridBagConstraints.WEST);
components.addElement(bs);
}
/**
* set the value of this AttributeComponent
*
* @param a the set of attributes possibly having an
* attribute this component can display
*
* @return true, if the set of attributes had a matching attribute,
* false if not
*/
public boolean setValue(final AttributeSet a) {
final boolean success = true;
final Enumeration e = components.elements();
bWidth = new CombinedAttribute(CSS.Attribute.BORDER_WIDTH, a, true);
bColor = new CombinedAttribute(CSS.Attribute.BORDER_COLOR, a, true);
if (++setValueCalls < 2) {
oColor = bColor.getAttribute();
oWidth = bWidth.getAttribute();
}
while (e.hasMoreElements()) {
((BorderSettings) e.nextElement()).setValue(bWidth, bColor);
}
return success;
}
/**
* get the value of this AttributeComponent
*
* @return the value selected from this component
*/
public AttributeSet getValue() {
final SimpleAttributeSet set = new SimpleAttributeSet();
BorderSettings bs;
for (int i = 0; i < components.size(); i++) {
bs = (BorderSettings) components.elementAt(i);
bColor.setAttribute(i, bs.getBorderColor());
bWidth.setAttribute(i, bs.getBorderWidth());
}
String newValue = bColor.getAttribute();
newValue = bWidth.getAttribute(CombinedAttribute.ATTR_TOP);
Util.styleSheet().addCSSAttribute(set, CSS.Attribute.BORDER_TOP_WIDTH, newValue);
Util.styleSheet().addCSSAttribute(set, CSS.Attribute.BORDER_RIGHT_WIDTH, newValue);
Util.styleSheet().addCSSAttribute(set, CSS.Attribute.BORDER_BOTTOM_WIDTH, newValue);
Util.styleSheet().addCSSAttribute(set, CSS.Attribute.BORDER_LEFT_WIDTH, newValue);
return set;
}
public AttributeSet getValue(final boolean includeUnchanged) {
if (includeUnchanged) {
final SimpleAttributeSet set = new SimpleAttributeSet();
BorderSettings bs;
for (int i = 0; i < components.size(); i++) {
bs = (BorderSettings) components.elementAt(i);
bColor.setAttribute(i, bs.getBorderColor());
bWidth.setAttribute(i, bs.getBorderWidth());
}
String newValue = bColor.getAttribute();
newValue = bWidth.getAttribute(CombinedAttribute.ATTR_TOP);
Util.styleSheet().addCSSAttribute(set, CSS.Attribute.BORDER_TOP_WIDTH, newValue);
Util.styleSheet().addCSSAttribute(set, CSS.Attribute.BORDER_RIGHT_WIDTH, newValue);
Util.styleSheet().addCSSAttribute(set, CSS.Attribute.BORDER_BOTTOM_WIDTH, newValue);
Util.styleSheet().addCSSAttribute(set, CSS.Attribute.BORDER_LEFT_WIDTH, newValue);
return set;
}
else {
return getValue();
}
}
/**
* Panel to show and manipulate border settings
*/
private class BorderSettings extends JPanel {
/** the border side */
private final int side;
/** selector for border width */
private final SizeSelectorPanel bWidth;
/** selector for border color */
private final ColorPanel bColor;
/**
* construct a BorderSettings
panel
*
* @param title the title of this object
* @param borderKey the attribute key for the border width this
* object represents
* @param colorKey the attribute key for the border color this
* object represents
*/
public BorderSettings(final String title, final int side) {
super();
this.side = side;
// set layout
final GridBagLayout g = new GridBagLayout();
setLayout(g);
// constraints to use on our GridBagLayout
final GridBagConstraints c = new GridBagConstraints();
// set border and title
setBorder(new TitledBorder(new EtchedBorder(EtchedBorder.LOWERED), title));
// add the width control and label
Util.addGridBagComponent(this, new JLabel(Util.getResourceString("borderWidthLabel")), g, c, 0, 0,
GridBagConstraints.EAST);
bWidth = new SizeSelectorPanel(CSS.Attribute.BORDER_WIDTH, null, false, SizeSelectorPanel.TYPE_LABEL);
Util.addGridBagComponent(this, bWidth, g, c, 1, 0, GridBagConstraints.WEST);
// add the color control and label
Util.addGridBagComponent(this, new JLabel(Util.getResourceString("borderColorLabel")), g, c, 0, 1,
GridBagConstraints.EAST);
bColor = new ColorPanel(null, Color.black, CSS.Attribute.BORDER_COLOR);
Util.addGridBagComponent(this, bColor, g, c, 1, 1, GridBagConstraints.WEST);
}
public String getBorderColor() {
return bColor.getAttr();
}
public String getBorderWidth() {
return bWidth.getAttr();
}
/**
* set the value of this AttributeComponent
*
* @param color the CombinedAttribute
to take the color from
*
*/
public void setValue(final CombinedAttribute borderWidths, final CombinedAttribute borderColors) {
String attr = borderColors.getAttribute(side);
//System.out.println("BorderSettings setValue attr='" + attr + "'");
if (attr != null) {
bColor.setValue(attr);
}
attr = borderWidths.getAttribute(side);
if (attr != null) {
bWidth.setValue(attr);
}
}
}
}
simplyhtml-0_16_07/src/com/lightdev/app/shtm/BoundariesPanel.java 100644 0 0 13576 12113727343 22243 0 ustar 0 0 /*
* SimplyHTML, a word processor based on Java, HTML and CSS
* Copyright (C) 2002 Ulrich Hilger
*
* 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 com.lightdev.app.shtm;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.util.Vector;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.text.AttributeSet;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.html.CSS;
/**
* Panel to show and manipulate boundaries of a rectangular object
* such as a table cell.
*
* @author Ulrich Hilger
* @author Light Development
* @author http://www.lightdev.com
* @author info@lightdev.com
* @author published under the terms and conditions of the
* GNU General Public License,
* for details see file gpl.txt in the distribution
* package of this software
*
*
*/
class BoundariesPanel extends JPanel implements AttributeComponent {
/** the components used for single attributes */
private final Vector components = new Vector();
/** the attributes represented by this compoent */
private CombinedAttribute ca;
/** the value to compare to determine changes */
private String originalValue;
/** indicates if a call to setValue is for initial setting or for changes */
private int setValueCalls = 0;
/** the attribute key this component represents */
private final Object key;
/**
* construct a BoundariesPanel
.
*/
public BoundariesPanel(final Object attrKey) {
super();
key = attrKey;
// set layout
final GridBagLayout g = new GridBagLayout();
setLayout(g);
// constraints to use on our GridBagLayout
final GridBagConstraints c = new GridBagConstraints();
Util.addGridBagComponent(this, new JLabel(Util.getResourceString("topLabel")), g, c, 0, 0,
GridBagConstraints.EAST);
Util.addGridBagComponent(this, new JLabel(Util.getResourceString("rightLabel")), g, c, 2, 0,
GridBagConstraints.EAST);
Util.addGridBagComponent(this, new JLabel(Util.getResourceString("bottomLabel")), g, c, 0, 1,
GridBagConstraints.EAST);
Util.addGridBagComponent(this, new JLabel(Util.getResourceString("leftLabel")), g, c, 2, 1,
GridBagConstraints.EAST);
addSizeSelector(g, c, attrKey, 1, 0); // top
addSizeSelector(g, c, attrKey, 3, 0); // right
addSizeSelector(g, c, attrKey, 1, 1); // bottom
addSizeSelector(g, c, attrKey, 3, 1); // left
}
private void addSizeSelector(final GridBagLayout g, final GridBagConstraints c, final Object attr, final int x,
final int y) {
final SizeSelectorPanel ssp = new SizeSelectorPanel(attr, null, false, SizeSelectorPanel.TYPE_LABEL);
Util.addGridBagComponent(this, ssp, g, c, x, y, GridBagConstraints.WEST);
components.addElement(ssp);
}
/**
* set the value of this AttributeComponent
*
* @param a the set of attributes possibly having an
* attribute this component can display
*
* @return true, if the set of attributes had a matching attribute,
* false if not
*/
public boolean setValue(final AttributeSet a) {
final boolean success = true;
ca = new CombinedAttribute(key, a, true);
if (++setValueCalls < 2) {
originalValue = ca.getAttribute();
}
SizeSelectorPanel ssp;
for (int i = 0; i < components.size(); i++) {
ssp = (SizeSelectorPanel) components.elementAt(i);
ssp.setValue(ca.getAttribute(i));
}
return success;
}
/**
* get the value of this AttributeComponent
*
* @return the value selected from this component
*/
public AttributeSet getValue() {
final SimpleAttributeSet set = new SimpleAttributeSet();
SizeSelectorPanel ssp;
for (int i = 0; i < components.size(); i++) {
ssp = (SizeSelectorPanel) components.elementAt(i);
if (ssp.valueChanged()) {
ca.setAttribute(i, ssp.getAttr());
}
}
final String newValue = ca.getAttribute();
if (!originalValue.equalsIgnoreCase(newValue)) {
set.addAttribute(key, newValue);
Util.styleSheet().addCSSAttribute(set, (CSS.Attribute) key, newValue);
}
return set;
}
public AttributeSet getValue(final boolean includeUnchanged) {
if (includeUnchanged) {
final SimpleAttributeSet set = new SimpleAttributeSet();
SizeSelectorPanel ssp;
for (int i = 0; i < components.size(); i++) {
ssp = (SizeSelectorPanel) components.elementAt(i);
ca.setAttribute(i, ssp.getAttr());
}
final String newValue = ca.getAttribute();
set.addAttribute(key, newValue);
Util.styleSheet().addCSSAttribute(set, (CSS.Attribute) key, newValue);
return set;
}
else {
return getValue();
}
}
public void reset() {
setValueCalls = 0;
originalValue = null;
}
}
simplyhtml-0_16_07/src/com/lightdev/app/shtm/CSSWriter.java 100644 0 0 13665 12113727343 21014 0 ustar 0 0 /*
* SimplyHTML, a word processor based on Java, HTML and CSS
* Copyright (C) 2002 Ulrich Hilger
*
* 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 com.lightdev.app.shtm;
import java.io.IOException;
import java.io.Writer;
import java.util.Enumeration;
import javax.swing.text.AttributeSet;
import javax.swing.text.Style;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyleContext;
import javax.swing.text.html.StyleSheet;
/**
* A writer for writing a StyleSheet
into a CSS file.
*
* @author Ulrich Hilger
* @author Light Development
* @author http://www.lightdev.com
* @author info@lightdev.com
* @author published under the terms and conditions of the
* GNU General Public License,
* for details see file gpl.txt in the distribution
* package of this software
*
*/
class CSSWriter {
/** spaces for indent */
private char[] indentChars;
/** new line character sequence */
private final String newLine = System.getProperty("line.separator");
/** the writer to write to */
private final Writer writer;
/** the style sheet to write */
private final StyleSheet styleSheet;
/** indent length */
private int indentLen;
/**
* construct a new CSSWriter
*
* @param writer the writer to write to
* @param styleSheet the StyleSheet to write
*/
public CSSWriter(final Writer writer, final StyleSheet styleSheet) {
this.writer = writer;
this.styleSheet = styleSheet;
}
/** write the style sheet to the given writer */
public void write() throws IOException {
final Enumeration rules = styleSheet.getStyleNames();
while (rules.hasMoreElements()) {
writeRule((String) rules.nextElement());
try {
Thread.currentThread();
Thread.sleep(0, 1);
}
catch (final Exception e) {
}
}
}
/**
* write out a rule with a given name
*
* Takes the style with the given name from the style sheet passed in the * constructor and writes it to the writer passed in the constructor.
. * * @param ruleName the name of the rule to write out * * @exception IOException if i/o fails */ private void writeRule(final String ruleName) throws IOException { writeRule(ruleName, styleSheet.getStyle(ruleName)); } /** * write out a rule with a given name and style * *Takes the style passed in paramter 'rule' and writes it under * the given name to the writer passed in the constructor.
. * @param ruleName the name of the rule to write out * @apram rule the style to write out * * @exception IOException if i/o fails */ public void writeRule(final String ruleName, final AttributeSet rule) throws IOException { //System.out.println("CSSWriter writeRule ruleName=" + ruleName); indentLen = ruleName.length() + 3; if (!ruleName.equalsIgnoreCase(StyleContext.DEFAULT_STYLE)) { writer.write(ruleName); writer.write(" { "); writeStyle(rule); writer.write(newLine); } } /** * write a given style * *A style is an AttributeSet which can have other * AttributeSets in the value field of one of its Attributes. * Therefore this is recursively called whenever an Attribute * contains another AttributeSet.
* * @param style theStyle
to write
*
* @return true, if the style was closed in this run of recursion,
* false if not
*/
private boolean writeStyle(final AttributeSet style) throws IOException {
boolean closed = false;
final Enumeration names = style.getAttributeNames();
Object value;
Object key;
int count = 0;
while (names.hasMoreElements()) {
key = names.nextElement();
value = style.getAttribute(key);
if ((!key.equals(StyleConstants.NameAttribute)) && (!key.equals(StyleConstants.ResolveAttribute))) {
if (count > 0) {
writer.write(newLine);
indent(indentLen);
}
else {
count++;
}
writer.write(key.toString());
writer.write(":");
writer.write(value.toString());
writer.write(";");
}
else {
if (key.equals(StyleConstants.ResolveAttribute)) {
closed = writeStyle((Style) value);
}
}
}
if (!closed) {
writer.write(" }");
writer.write(newLine);
closed = true;
}
return closed;
}
/**
* indent by a given number of characters
*
* @param len the number of characters to indent
*/
private void indent(final int len) throws IOException {
if (indentChars == null || len > indentChars.length) {
indentChars = new char[len];
for (int i = 0; i < len; i++) {
indentChars[i] = ' ';
}
}
writer.write(indentChars, 0, len);
}
}
simplyhtml-0_16_07/src/com/lightdev/app/shtm/ColorPanel.java 100644 0 0 25350 12113727343 21217 0 ustar 0 0 /*
* SimplyHTML, a word processor based on Java, HTML and CSS
* Copyright (C) 2002 Ulrich Hilger
*
* 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 com.lightdev.app.shtm;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.SystemColor;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Enumeration;
import java.util.EventListener;
import java.util.EventObject;
import java.util.Vector;
import javax.swing.JButton;
import javax.swing.JColorChooser;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.UIManager;
import javax.swing.text.AttributeSet;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.html.CSS;
import javax.swing.text.html.HTML;
/**
* a panel to display and change a color setting
*
* @author Ulrich Hilger
* @author Light Development
* @author http://www.lightdev.com
* @author info@lightdev.com
* @author published under the terms and conditions of the
* GNU General Public License,
* for details see file gpl.txt in the distribution
* package of this software
*
*
*/
class ColorPanel extends JPanel implements ActionListener, AttributeComponent {
/** the component showing the chosen color */
JTextField colorDisplay = new JTextField();
/** default color */
private final Color defaultColor;
/** the attribute key, this component returns values for */
private final Object attributeKey;
/** value to compare for determining changes */
private Color originalColor;
/** indicates if setValue is called initially */
private int setValCount = 0;
private final JColorChooser colorChooserPane = new JColorChooser();
/**
* construct a color panel
*
* @param title the title of the color panel
* @param col the color to be displayed first
* @param titleFont font for title
* @param key the attribute key this component shall return color values for
*/
public ColorPanel(final String title, final Color col, final Object key) {
super(new BorderLayout(5, 5));
defaultColor = col;
attributeKey = key;
/** adjust the color display */
colorDisplay.setBackground(col);
Dimension dim = new Dimension(20, 15);
colorDisplay.setMinimumSize(dim);
colorDisplay.setMaximumSize(dim);
colorDisplay.setPreferredSize(dim);
colorDisplay.setEditable(false);
/** a button to open a color chooser window */
final JButton browseButton = new JButton();
browseButton.setText("...");
dim = new Dimension(20, 15);
browseButton.setMinimumSize(dim);
browseButton.setMaximumSize(dim);
browseButton.setPreferredSize(dim);
browseButton.addActionListener(this);
/** a helper panel for proper component placement */
final JPanel eastPanel = new JPanel(new FlowLayout());
eastPanel.add(colorDisplay);
eastPanel.add(browseButton);
/** set the title */
if ((title != null) && (title.length() > 0)) {
final JLabel titleLabel = new JLabel(title);
titleLabel.setFont(UIManager.getFont("TextField.font"));
add(titleLabel, BorderLayout.WEST);
add(eastPanel, BorderLayout.EAST);
}
else {
add(eastPanel, BorderLayout.WEST);
}
}
/**
* get the selected color
*
* @return the selected color
*/
public Color getColor() {
return colorDisplay.getBackground();
}
/**
* set the selected color
*
* @param color the selected color
*/
private void setColor(final Color color) {
//System.out.println("ColorPanel setColor attributeKey=" + attributeKey + ", color=" + color);
colorDisplay.setBackground(color);
if (++setValCount < 2) {
originalColor = color;
}
fireColorChanged();
}
/**
* open a color chooser when a 'Browse' button
* is clicked and change the associated color
* display accordingly, when another color
* is selected from the color chooser
*/
public void actionPerformed(final ActionEvent e) {
final Color color = showColorChooserDialog();
if (color != null) {
setValCount++;
setColor(color);
}
}
private Color showColorChooserDialog() {
// the listener for OK button of the Color Choose Dialog:
class ColorTracker implements ActionListener {
JColorChooser chooser;
Color color;
public ColorTracker(final JColorChooser c) {
chooser = c;
}
public void actionPerformed(final ActionEvent e) {
color = chooser.getColor();
}
}
colorChooserPane.setColor(colorDisplay.getBackground()); // setting up the current text color
final ColorTracker ok = new ColorTracker(colorChooserPane);
final JDialog dialog = JColorChooser.createDialog(this, "Select Color", true, colorChooserPane, ok, null);
dialog.setVisible(true); // blocks until user brings dialog down...
dialog.dispose();
return ok.color;
}
/**
* set the value of this AttributeComponent
*
* @param a the set of attributes possibly having an
* attribute this component can display
*
* @return true, if the set of attributes had a matching attribute,
* false if not
*/
public boolean setValue(final AttributeSet a) {
Color newSelection = null;
if (getAttributeKey() == CSS.Attribute.COLOR) {
newSelection = Util.styleSheet().getForeground(a);
}
if (getAttributeKey() == CSS.Attribute.BACKGROUND_COLOR) {
newSelection = Util.styleSheet().getBackground(a);
if (newSelection == null) {
newSelection = SystemColor.text;
}
}
if (newSelection != null) {
setColor(newSelection);
return true;
}
return false;
}
public void setValue(final String value) {
//System.out.println("ColorPanel setValue value=" + value);
try {
setColor(new Color(Integer.parseInt(value.toString().substring(1).toUpperCase(), 16)));
}
catch (final Exception e) {
try {
//setColor(Util.styleSheet().getForeground(a));
//System.out.println("ColorPanel setValue value=" + value + "=" + Color.getColor(value));
setColor(Color.getColor(value));
}
catch (final Exception e2) {
Util.errMsg(null, null, e2);
}
}
}
public String getAttr() {
final String color = "#" + Integer.toHexString(getColor().getRGB()).substring(2);
return color;
}
/**
* get the value of this AttributeComponent
*
* @return the value selected from this component
*/
public AttributeSet getValue() {
final SimpleAttributeSet set = new SimpleAttributeSet();
final Color value = getColor();
if (value != originalColor) {
final String color = "#" + Integer.toHexString(value.getRGB()).substring(2);
Util.styleSheet().addCSSAttribute(set, (CSS.Attribute) getAttributeKey(), color);
if (getAttributeKey() == CSS.Attribute.COLOR) {
set.addAttribute(HTML.Attribute.COLOR, color);
}
else if (getAttributeKey() == CSS.Attribute.BACKGROUND_COLOR) {
set.addAttribute(HTML.Attribute.BGCOLOR, color);
}
}
return set;
}
public AttributeSet getValue(final boolean includeUnchanged) {
if (includeUnchanged) {
final SimpleAttributeSet set = new SimpleAttributeSet();
final Color value = getColor();
final String color = "#" + Integer.toHexString(value.getRGB()).substring(2);
try {
Util.styleSheet().addCSSAttribute(set, (CSS.Attribute) getAttributeKey(), color);
}
catch (final Exception e) {
set.addAttribute(getAttributeKey(), color);
}
//System.out.println("ColorPanel getValue color=" + color);
return set;
}
else {
return getValue();
}
}
/**
* get the attribute key this object was created for
*
* @return the attribute key this ColorPanel returns values for
*/
public Object getAttributeKey() {
return attributeKey;
}
/* -------------- event listener implementation start ----------- */
/** the listeners for ColorPanelEvents */
private final Vector listeners = new Vector(0);
/**
* add an event listener.
*
* @param listener the event listener to add
*/
public void addColorPanelListener(final ColorPanelListener listener) {
listeners.addElement(listener);
}
/**
* remove an event listener.
*
* @param listener the event listener to remove
*/
public void removeColorPanelListener(final ColorPanelListener listener) {
listeners.removeElement(listener);
}
/** fire a color changed event to all registered listeners */
void fireColorChanged() {
final Enumeration listenerList = listeners.elements();
while (listenerList.hasMoreElements()) {
((ColorPanelListener) listenerList.nextElement()).colorChanged(new ColorPanelEvent(this));
}
}
/** the event object definition for ColorPanels */
class ColorPanelEvent extends EventObject {
public ColorPanelEvent(final Object source) {
super(source);
}
}
/** the event listener definition for ColorPanels */
interface ColorPanelListener extends EventListener {
public void colorChanged(ColorPanelEvent e);
}
/* -------------- event listener implementation end ----------- */
}
simplyhtml-0_16_07/src/com/lightdev/app/shtm/CombinedAttribute.java 100644 0 0 30353 12113727343 22564 0 ustar 0 0 /*
* SimplyHTML, a word processor based on Java, HTML and CSS
* Copyright (C) 2002 Ulrich Hilger
*
* 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 com.lightdev.app.shtm;
import java.util.Enumeration;
import java.util.Vector;
import javax.swing.text.AttributeSet;
import javax.swing.text.html.CSS;
/**
* A class to represent an attribute combining several other attributes.
*
* The CSS 1.0 specification * defines 'shorthand properties' which can hold more than * one value separated by blanks. Depending on the number of values inside * the property the values are applied following a fixed ratio.
* *Following is an excerpt of the spec for CSS property
* border-width
* There can be from one to four values, with the following interpretation: * one value: all four border widths are set to that value * two values: top and bottom border widths are set to the * first value, right and left are set to the second * three values: top is set to the first, right and left are set to * the second, bottom is set to the third * four values: top, right, bottom and left, respectively ** *
In SimplyHTML this spec is used on properties margin, * padding, border-width and border-color
* * @author Ulrich Hilger * @author Light Development * @author http://www.lightdev.com * @author info@lightdev.com * @author published under the terms and conditions of the * GNU General Public License, * for details see file gpl.txt in the distribution * package of this software * * */ class CombinedAttribute { /** index of top value */ public static final int ATTR_TOP = 0; /** index of right value */ public static final int ATTR_RIGHT = 1; /** index of bottom value */ public static final int ATTR_BOTTOM = 2; /** index of left value */ public static final int ATTR_LEFT = 3; /** the values of thisCombinedAttribute
*/
private final String[] values = new String[4];
/**
* the attribute key the values of this
* CombinedAttribute
belong to
*/
private final Object attributeKey;
/** indicates which sides were present in the attribute set */
private final boolean[] present = new boolean[4];
/** table with attribute names from the source attribute set */
private final Vector aNames = new Vector();
/** indicates if attributes of parent elements shall be used */
private final boolean includeParents;
/**
* construct a CombinedAttribute
for a certain
* attribute out of a given set of attributes
*
* @param key the attribute key to get single attribute values from
* @param a the set of attributes to get the attribute of type 'key'
*/
public CombinedAttribute(final Object key, final AttributeSet a, final boolean includeParents) {
attributeKey = key;
this.includeParents = includeParents;
// get names in this attribute set to filter out parent attributes later
final Enumeration names = a.getAttributeNames();
while (names.hasMoreElements()) {
aNames.addElement(names.nextElement());
}
// now load attributes into this object
final Object attr = a.getAttribute(key);
if (attr != null) {
//System.out.println(" construct CombinedAttribute attr=" + attr);
copyValues(Util.tokenize(attr.toString(), " "));
}
else {
copyValues(key, a);
}
}
/**
* copy the values for individual border settings from a given
* set of attributes into the structure top, right, bottom, left of
* this CombinedAttribute
*
* Used in cases where attributes are not found for a 'shorthand * property' such as PADDING or MARGIN.
* * @param key the 'shorthand property' to copy individual attributes for * @param a the set of attributes to copy from */ private void copyValues(final Object key, final AttributeSet a) { if (key.equals(CSS.Attribute.BORDER_WIDTH)) { setValue(ATTR_TOP, CSS.Attribute.BORDER_TOP_WIDTH, a); setValue(ATTR_RIGHT, CSS.Attribute.BORDER_RIGHT_WIDTH, a); setValue(ATTR_BOTTOM, CSS.Attribute.BORDER_BOTTOM_WIDTH, a); setValue(ATTR_LEFT, CSS.Attribute.BORDER_LEFT_WIDTH, a); } else if (key.equals(CSS.Attribute.PADDING)) { setValue(ATTR_TOP, CSS.Attribute.PADDING_TOP, a); setValue(ATTR_RIGHT, CSS.Attribute.PADDING_RIGHT, a); setValue(ATTR_BOTTOM, CSS.Attribute.PADDING_BOTTOM, a); setValue(ATTR_LEFT, CSS.Attribute.PADDING_LEFT, a); } else if (key.equals(CSS.Attribute.MARGIN)) { setValue(ATTR_TOP, CSS.Attribute.MARGIN_TOP, a); setValue(ATTR_RIGHT, CSS.Attribute.MARGIN_RIGHT, a); setValue(ATTR_BOTTOM, CSS.Attribute.MARGIN_BOTTOM, a); setValue(ATTR_LEFT, CSS.Attribute.MARGIN_LEFT, a); } } /** * set the value of a certain side from a given attribute key and * set of attributes. * * @param side the side to set the value for, one of ATTR_TOP, * ATTR_RIGHT, ATTR_BOTTOM and ATTR_LEFT * @param key the attribute key to get the value from * @param a the set of attributes to get the value from */ private void setValue(final int side, final Object key, final AttributeSet a) { if ((includeParents) || ((!includeParents) && (aNames.contains(key)))) { // filter out parent attributes final Object attr = a.getAttribute(key); if (attr != null) { values[side] = attr.toString(); present[side] = true; } else { values[side] = defaultValue(attributeKey); present[side] = true; } } else { // key not present, set default value values[side] = defaultValue(attributeKey); present[side] = false; } } /** * determine whether or not the set of attributes this *CombinedAttribute
was created from contained any
* of the attributes in this CombinedAttribute
*
* Can be used for instance to determine whether or not this
* CombinedAttribute
should be written
CombinedAttribute
contains
* default values only, false if not
*/
public boolean isEmpty() {
boolean notEmpty = false;
int i = 0;
while (!notEmpty && i < present.length) {
notEmpty = present[i];
i++;
}
return !notEmpty;
}
/**
* get the default value for a given key
*
* @param key the attribute key to get the default value for
*
* @return the default value for the given key
*/
private String defaultValue(final Object key) {
String value = "0";
if (key.equals(CSS.Attribute.BORDER_COLOR)) {
value = "#000000";
}
return value;
}
/**
* get the side opposite of a given side
*
* @param side the side to get the opposite of
*
* @return the opposite side of the given side
*/
public int getOppositeSide(final int side) {
int oppositeSide = -1;
switch (side) {
case ATTR_TOP:
oppositeSide = ATTR_BOTTOM;
break;
case ATTR_RIGHT:
oppositeSide = ATTR_LEFT;
break;
case ATTR_BOTTOM:
oppositeSide = ATTR_TOP;
break;
case ATTR_LEFT:
oppositeSide = ATTR_RIGHT;
break;
}
return oppositeSide;
}
/**
* copy the atribute value(s) found in a 'shorthand property' such
* as PADDING or MARGIN into the structure top, right, bottom, left of
* this CombinedAttribute
*
* @param v the array of Strings holding the found values
*/
private void copyValues(final String[] v) {
switch (v.length) {
case 1:
for (int i = 0; i < values.length; i++) {
values[i] = v[0];
}
break;
case 2:
values[ATTR_TOP] = v[ATTR_TOP];
values[ATTR_RIGHT] = v[ATTR_RIGHT];
values[ATTR_BOTTOM] = v[ATTR_TOP];
values[ATTR_LEFT] = v[ATTR_RIGHT];
break;
case 3:
values[ATTR_TOP] = v[ATTR_TOP];
values[ATTR_RIGHT] = v[ATTR_RIGHT];
values[ATTR_BOTTOM] = v[ATTR_BOTTOM];
values[ATTR_LEFT] = v[ATTR_RIGHT];
break;
case 4:
for (int i = 0; i < values.length; i++) {
values[i] = v[i];
}
break;
}
}
/**
* set one attribute of this CombinedAttribute
*
* @param side the side to set the attribute for, one of ATTR_TOP,
* ATTR_RIGHT, ATTR_BOTTOM, ATTR_LEFT
* @param value the attribute value to set
*/
public void setAttribute(final int side, final String value) {
values[side] = value;
}
/**
* get one attribute of this CombinedAttribute
*
* @param side the side to get the attribute for, one of ATTR_TOP,
* ATTR_RIGHT, ATTR_BOTTOM, ATTR_LEFT
*
* @return the attribute value for the specified side or null, if the
* attribute key provided in the constructor was not found
*/
public String getAttribute(final int side) {
return values[side];
}
/**
* get the attribute key this CombinedAttribute
represents
*
* @return the attribute key
*/
public Object getAttributeKey() {
return attributeKey;
}
/**
* get all values of this CombinedAttribute
* as one attribute.
*
* @return a String having all values delimited by blanks
* in the order top right, bottom, left or null if no
* attributes were found
*/
public String getAttribute() {
String result = null;
final StringBuffer buf = new StringBuffer();
if (values[0] != null) {
buf.append(values[0]);
int additionalValueCount = 3;
if (values[ATTR_RIGHT].equalsIgnoreCase(values[ATTR_LEFT])) {
--additionalValueCount; // total 3
if (values[ATTR_TOP].equalsIgnoreCase(values[ATTR_BOTTOM])) {
--additionalValueCount; // total 2
if (values[ATTR_TOP].equalsIgnoreCase(values[ATTR_RIGHT])) {
--additionalValueCount; // total 1
}
}
}
appendValues(buf, additionalValueCount);
result = buf.toString();
}
return result;
}
/**
* append a given number of values to a given output buffer
* starting with ATTR_RIGHT and necessarily continuing
* with ATTR_BOTTOM and ATTR_LEFT ( helper method to getAttribute() )
*
* @param buf the output buffer to append to
* @param count the number of values to append
*/
private void appendValues(final StringBuffer buf, final int count) {
for (int i = 1; i < count + 1; i++) {
buf.append(' ');
buf.append(values[i]);
}
}
}
simplyhtml-0_16_07/src/com/lightdev/app/shtm/DefaultTextResources.java 100644 0 0 3561 12113727343 23265 0 ustar 0 0 /*
* SimplyHTML, a word processor based on Java, HTML and CSS
* Created on 23.11.2006
* Copyright (C) 2006 Dimitri Polivaev
*
* 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 com.lightdev.app.shtm;
import java.util.MissingResourceException;
import java.util.Properties;
import java.util.ResourceBundle;
/**
* Default implementation of TextResources based on java.util.ResourceBundle
*
* @author Dimitri Polivaev
* 14.01.2007
*/
public class DefaultTextResources implements TextResources {
private final Properties properties;
private final ResourceBundle resources;
public DefaultTextResources(final ResourceBundle languageResources) {
this(languageResources, null);
}
public DefaultTextResources(final ResourceBundle languageResources, final Properties properties) {
super();
resources = languageResources;
this.properties = properties;
}
public String getString(final String pKey) {
try {
return resources.getString(pKey);
}
catch (final MissingResourceException ex) {
if (properties != null) {
return properties.getProperty(pKey);
}
throw ex;
}
}
}
simplyhtml-0_16_07/src/com/lightdev/app/shtm/DialogShell.java 100644 0 0 15356 12113727343 21355 0 ustar 0 0 /*
* SimplyHTML, a word processor based on Java, HTML and CSS
* Copyright (C) 2002 Ulrich Hilger
*
* 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 com.lightdev.app.shtm;
import java.awt.AWTEvent;
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.Dialog;
import java.awt.FlowLayout;
import java.awt.Frame;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.WindowEvent;
import javax.swing.AbstractButton;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JPanel;
/**
* Base class for other dialogs of application SimplyHTML.
*
* @author Ulrich Hilger
* @author Light Development
* @author http://www.lightdev.com
* @author info@lightdev.com
* @author published under the terms and conditions of the
* GNU General Public License,
* for details see file gpl.txt in the distribution
* package of this software
*
*
*/
class DialogShell extends JDialog implements ActionListener {
/** panel containing dialog buttons */
protected JPanel buttonPanel;
/** button to confirm the operation */
protected AbstractButton okButton;
/** button to cancel the operation */
protected AbstractButton cancelButton;
/** button to display context sensitive help */
protected AbstractButton helpButton;
/**
* the result of the operation, one of RESULT_CANCEL and RESULT_OK
*/
private int result;
/** result value for a cancelled operation */
public static int RESULT_CANCEL = 1;
/** result value for a confirmed operation */
public static int RESULT_OK = 0;
/** id of associated help topic (if any) */
protected String helpTopicId = null;
/** Listens to enter and cancel. */
private KeyListener completionKeyListener = null;
/**
* constructor
*
* @param parent the parent dialog
* @param title the title for this dialog
*/
public DialogShell(final Dialog parent, final String title) {
super(parent, title);
buildDialog();
}
/**
* constructor
*
* @param parent the parent frame
* @param title the title for this dialog
*/
public DialogShell(final Frame parent, final String title) {
super(parent, title);
buildDialog();
}
/**
* constructor
*
* @param parent the parent frame
* @param title the title for this dialog
* @param helpTopicId the id of the help topic to display for this dialog
*/
public DialogShell(final Frame parent, final String title, final String helpTopicId) {
super(parent, title);
this.helpTopicId = helpTopicId;
buildDialog();
}
/**
* constructor
*
* @param parent the parent dialog
* @param title the title for this dialog
* @param helpTopicId the id of the help topic to display for this dialog
*/
public DialogShell(final Dialog parent, final String title, final String helpTopicId) {
super(parent, title);
this.helpTopicId = helpTopicId;
buildDialog();
}
/**
* create dialog components
*/
private void buildDialog() {
enableEvents(AWTEvent.WINDOW_EVENT_MASK);
// construct dialog buttons
okButton = new JButton(Util.getResourceString("okBtnName"));
cancelButton = new JButton(Util.getResourceString("cancelBtnName"));
cancelButton.addActionListener(this);
okButton.addActionListener(this);
// construct button panel
buttonPanel = new JPanel(new FlowLayout());
buttonPanel.add(okButton);
buttonPanel.add(cancelButton);
// construct help button
if (helpTopicId != null) {
try {
helpButton = SHTMLHelpBroker.createHelpButton(helpTopicId);
helpButton.setText(Util.getResourceString("helpLabel"));
buttonPanel.add(helpButton);
}
catch (final NoClassDefFoundError e) {
helpTopicId = null;
}
}
// add all to content pane of dialog
final Container contentPane = getContentPane();
contentPane.setLayout(new BorderLayout(5, 5));
contentPane.add(buttonPanel, BorderLayout.SOUTH);
}
/**
* dispose the dialog properly in case of window close events
*/
protected void processWindowEvent(final WindowEvent e) {
if (e.getID() == WindowEvent.WINDOW_CLOSING) {
cancel();
}
super.processWindowEvent(e);
}
/**
* cancel the operation
*/
protected void cancel() {
result = RESULT_CANCEL;
dispose();
}
/**
* confirm the operation
*/
protected void confirm() {
result = RESULT_OK;
dispose();
}
/**
* get the result of the operation performed in this dialog
*
* @return the result, one of RESULT_OK and RESULT_CANCEL
*/
public int getResult() {
return result;
}
/**
* implements the ActionListener interface to be notified of
* clicks onto the ok and cancel button.
*/
public void actionPerformed(final ActionEvent e) {
final Object src = e.getSource();
if (src == cancelButton) {
cancel();
}
else if (src == okButton) {
confirm();
}
}
protected KeyListener getCompletionKeyListener() {
if (completionKeyListener == null) {
completionKeyListener = new KeyAdapter() {
public void keyPressed(final KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_ESCAPE) {
e.consume();
cancel();
}
else if (e.getKeyCode() == KeyEvent.VK_ENTER) {
e.consume();
confirm();
}
}
};
}
return completionKeyListener;
}
}
simplyhtml-0_16_07/src/com/lightdev/app/shtm/DocNameMissingException.java 100644 0 0 3675 12113727343 23666 0 ustar 0 0 /*
* SimplyHTML, a word processor based on Java, HTML and CSS
* Copyright (C) 2002 Ulrich Hilger
*
* 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 com.lightdev.app.shtm;
/**
* Signals that the name of a document in SimplyHTML is not yet set.
*
* @author Ulrich Hilger
* @author Light Development
* @author http://www.lightdev.com
* @author info@lightdev.com
* @author published under the terms and conditions of the
* GNU General Public License,
* for details see file gpl.txt in the distribution
* package of this software
*
*
*/
class DocNameMissingException extends Exception {
/**
* Constructs a DocNameMissingException
with null
* as its error detail message.
*/
public DocNameMissingException() {
super();
}
/**
* Constructs an IOException
with the specified detail
* message. The error message string s
can later be
* retrieved by the {@link java.lang.Throwable#getMessage}
* method of class java.lang.Throwable
.
*
* @param s the detail message.
*/
public DocNameMissingException(final String s) {
super(s);
}
}
simplyhtml-0_16_07/src/com/lightdev/app/shtm/DocumentPane.java 100644 0 0 105263 12113727343 21565 0 ustar 0 0 /*
* SimplyHTML, a word processor based on Java, HTML and CSS
* Copyright (C) 2002 Ulrich Hilger
*
* 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 com.lightdev.app.shtm;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Font;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.StringWriter;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Enumeration;
import java.util.EventObject;
import java.util.Vector;
import javax.swing.JComponent;
import javax.swing.JEditorPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.Document;
import javax.swing.text.html.HTMLDocument;
import javax.swing.text.html.StyleSheet;
import com.sun.demo.ExampleFileFilter;
/**
* GUI representation of a document.
*
* Swing already uses three types of classes to implement a model, view, * controller (MVC) approach for a document:
* *JTextComponent - the view implementation
* Document - the model implementation
* EditorKit - the controller implementation
For a GUI representation of a document, additional parts are needed, such * as a JScrollPane as well as listeners and fields to track the state of * the document while it is represented on a GUI.
* *DocumentPane
wraps all those elements to implement a single
* document centric external view to all elements.
If for instance an application wants to create a new document, it simply * creates an instance of this class instead of having to implement own * methods for instatiating each element (editor pane, scroll pane, etc.) * separately.
* * @author Ulrich Hilger * @author Light Development * @author http://www.lightdev.com * @author info@lightdev.com * @author published under the terms and conditions of the * GNU General Public License, * for details see file gpl.txt in the distribution * package of this software * * */ class DocumentPane extends JPanel implements DocumentListener, ChangeListener { /** the editor displaying the document in layout view */ private final SHTMLEditorPane editorPane; /** the editor displaying the document in HTML code view */ private final SyntaxPane sourceEditorPane; /** temporary storage location for this document */ private File docTempDir = null; /** the save thread, if a save operation is in progress */ public Thread saveThread = null; /** indicator if a save operation was succesful */ public boolean saveSuccessful = false; /** indicates if the document text has changed */ private boolean documentChanged = false; /** * @param documentChanged The documentChanged to set. */ private void setDocumentChanged(final boolean documentChanged) { this.documentChanged = documentChanged; } /** * @return Returns the documentChanged. */ private boolean isDocumentChanged() { return documentChanged; } /** indicates if the document text has changed */ private boolean htmlChanged = true; /** * @param htmlChanged The htmlChanged to set. */ private void setHtmlChanged(final boolean htmlChanged) { this.htmlChanged = htmlChanged; } /** * @return Returns the htmlChanged. */ private boolean isHtmlChanged() { return htmlChanged; } /** the name of the document */ private String docName; /** the file the current style sheet was loaded from, if any */ private final File loadedStyleSheet = null; /** the URL the document was loaded from (if applicable)*/ private URL sourceUrl = null; /** JTabbedPane for our views */ private JComponent paneHoldingScrollPanes; private final JScrollPane richViewScrollPane; private final JScrollPane sourceViewScrollPane; public static final int VIEW_TAB_LAYOUT = 0; public static final int VIEW_TAB_HTML = 1; /** * a save place for sourceUrl, when a document is to be saved * under a new name and this fails */ private URL savedUrl = null; /** indicates if this document was loaded froma file */ private boolean loadedFromFile = false; /** default document name */ private String DEFAULT_DOC_NAME = "Untitled"; /** default name for style sheet, when saved */ public static String DEFAULT_STYLE_SHEET_NAME = "style.css"; /** number for title of a new document */ private int newDocNo; private int activeView; //private int renderMode; /** * construct a newDocumentPane
.
*
* A document still has to be either created or loaded after using * this constructor, so it is better to use the constructor doing this * right away instead.
*/ public DocumentPane(/*int renderMode*/) { super(); // EditorPane and ScrollPane for layout view editorPane = new SHTMLEditorPane(); final SHTMLEditorKit kit = new SHTMLEditorKit(/*renderMode*/); //kit.resetStyleSheet(); editorPane.setEditorKit(kit); richViewScrollPane = new JScrollPane(); // create a new JScrollPane, richViewScrollPane.getViewport().setView(editorPane); // ..add the editor pane to it // EditorPane and ScrollPane for html view sourceEditorPane = new SyntaxPane(); sourceEditorPane.setFont(new Font("Monospaced", Font.PLAIN, 12)); //sourceEditorPane.addKeyListener(rkw); sourceViewScrollPane = new JScrollPane(); sourceViewScrollPane.getViewport().setView(sourceEditorPane); // Tabbed pane for HTML and layout views if (Util.showViewsInTabs()) { paneHoldingScrollPanes = new JTabbedPane(); paneHoldingScrollPanes.add(richViewScrollPane, VIEW_TAB_LAYOUT); paneHoldingScrollPanes.add(sourceViewScrollPane, VIEW_TAB_HTML); final JTabbedPane tabbedPane = (JTabbedPane) paneHoldingScrollPanes; tabbedPane.setTabPlacement(JTabbedPane.BOTTOM); tabbedPane.setTitleAt(VIEW_TAB_LAYOUT, Util.getResourceString("layoutTabTitle")); tabbedPane.setTitleAt(VIEW_TAB_HTML, Util.getResourceString("htmlTabTitle")); tabbedPane.addChangeListener(this); setLayout(new BorderLayout()); add(paneHoldingScrollPanes, BorderLayout.CENTER); } else { paneHoldingScrollPanes = new JPanel(new BorderLayout()); paneHoldingScrollPanes.add(richViewScrollPane, BorderLayout.CENTER); activeView = VIEW_TAB_LAYOUT; //BorderLayout DOES NOT allow two parts with ..CENTER. //paneHoldingScrollPanes.add(sourceViewScrollPane, BorderLayout.CENTER); //sourceViewScrollPane.setVisible(false); //paneHoldingScrollPanes.addChangeListener(this); setLayout(new BorderLayout()); add(paneHoldingScrollPanes, BorderLayout.CENTER); } setDocumentChanged(false); // no changes so far setPreferredSize(new Dimension(550, 550)); } /** * construct a new DocumentPane with either a new Document or an exisiting * Document that is to be loaded into the DocumentPane upon construction. * * @param docToLoad the document to be loaded. If this is null, a new * Document is created upon construction of the DocumentPane * @param newDocNo the number a new document shall have in the * title as long as it is not saved (such as in 'Untitled1'). If an * existing document shall be loaded, this number is ignored */ public DocumentPane(final URL docToLoad, final int newDocNo/*, int renderMode*/) { this(/*renderMode*/); DEFAULT_DOC_NAME = Util.getResourceString("defaultDocName"); if (docToLoad != null) { loadDocument(docToLoad); } else { this.newDocNo = newDocNo; createNewDocument(); } } /** * get theJEditorPane
of this DocumentPane
*
* @return the JEditorPane of this DocumentPane
*/
public SHTMLEditorPane getEditor() {
return editorPane;
}
/**
* get the SyntaxPane
of this DocumentPane
*
* @return the SyntaxPane of this DocumentPane
*/
public SyntaxPane getHtmlEditor() {
return sourceEditorPane;
}
/**
* @return the selected tab index
*/
public int getSelectedTab() {
if (paneHoldingScrollPanes instanceof JTabbedPane) {
return ((JTabbedPane) paneHoldingScrollPanes).getSelectedIndex();
}
return activeView;
}
/**
* create a new HTMLDocument and attach it to the editor
*/
public void createNewDocument() {
try {
final SHTMLEditorKit kit = (SHTMLEditorKit) editorPane.getEditorKit();
final SHTMLDocument doc = (SHTMLDocument) kit.createDefaultDocument();
//insertStyleRef(doc); // create style sheet reference in HTML header tag
//styles = kit.getStyleSheet();
doc.addDocumentListener(this); // listen to changes
doc.setBase(createTempDir());
editorPane.setDocument(doc); // let the document be edited in our editor
//doc.putProperty(Document.TitleProperty, getDocumentName());
final boolean useStyle = Util.useSteStyleSheet();
if (useStyle) {
doc.insertStyleRef();
}
}
catch (final Exception e) {
Util.errMsg(this, e.getMessage(), e);
}
}
public void setDocument(final Document docToSet) {
try {
editorPane.getEditorKit();
final HTMLDocument doc = (HTMLDocument) getDocument();
if (doc != null) {
doc.removeDocumentListener(this);
}
docToSet.addDocumentListener(this); // listen to changes
editorPane.setDocument(docToSet); // let the document be edited in our editor
}
catch (final Exception e) {
Util.errMsg(this, e.getMessage(), e);
}
}
/**
* create temporary directory for a newly created document
* so that images can be stored and referenced until the document
* is saved.
*
* @return URL of created temporary document directoy
*/
private URL createTempDir() throws MalformedURLException {
docTempDir = new File(SHTMLPanelImpl.getAppTempDir().getAbsolutePath() + File.separator + getDocumentName()
+ File.separator);
return docTempDir.toURI().toURL();
}
/**
* remove the temporary storage created for this DocumentPane
*/
public void deleteTempDir() {
if (docTempDir != null) {
Util.deleteDir(docTempDir);
docTempDir = null;
}
}
/**
* load a document found at a certain URL.
*
* @param url the URL to look for the document
*/
public void loadDocument(final URL url) {
try {
final SHTMLEditorKit kit = (SHTMLEditorKit) editorPane.getEditorKit();
final SHTMLDocument doc = (SHTMLDocument) kit.createEmptyDocument();
doc.putProperty("IgnoreCharsetDirective", new Boolean(true));
doc.setBase(new File(url.getPath()).getParentFile().toURI().toURL()); // set the doc base
final InputStream in = url.openStream(); // get an input stream
kit.read(in, doc, 0); // ..and read the document contents from it
in.close(); // .. then properly close the stream
doc.addDocumentListener(this); // listen to changes
editorPane.setDocument(doc); // let the document be edited in our editor
setSource(url); // remember where the document came from
loadedFromFile = true;
}
catch (final Exception ex) {
Util.errMsg(this, "An exception occurred while loading the file", ex);
ex.printStackTrace();
}
}
/**
* load the rules from a given style sheet file into a new StyleSheet
object.
*
* @param cssFile the file object referring to the style sheet to load from
*
* @return the style sheet with rules loaded
*/
private StyleSheet loadStyleSheet(final File cssFile) throws MalformedURLException, IOException {
final StyleSheet s = new StyleSheet();
s.importStyleSheet(cssFile.toURI().toURL());
return s;
}
/**
* saves the document to the file specified in the source of the
* DocumentPane
and creates the associated style sheet.
*
* The actual save process only is done, when there is a name to save
* to. The class(es) calling this method have to make sure that a
* name for new documents is requested from the user, for instance.
*
* The desired name and location for the save need then to be set using method
* setSource prior to a call to this method
*
* @throws DocNameMissingException to ensure the caller gets notified
* that a save did not take place because of a missing name
* and location
*/
public void saveDocument() throws DocNameMissingException {
if (!saveInProgress()) {
saveThread = Thread.currentThread(); // store thread for saveInProgress
saveSuccessful = false; // if something goes wrong, this remains false
File file = null;
try {
if (sourceUrl != null) {
/* write the HTML document */
if (getSelectedTab() == VIEW_TAB_HTML) {
editorPane.setText(sourceEditorPane.getText());
}
final SHTMLDocument doc = (SHTMLDocument) getDocument();
final OutputStream os = new FileOutputStream(sourceUrl.getPath());
final OutputStreamWriter osw = new OutputStreamWriter(os);
final SHTMLWriter hw = new SHTMLWriter(osw, doc);
hw.write();
osw.flush();
osw.close();
os.flush();
os.close();
/* write the style sheet */
if (doc.hasStyleRef()) {
saveStyleSheet();
}
/*
copy image directory,
if new document or saved from different location
*/
saveImages();
/* clean up */
//System.out.println("DocumentPane textChanged = false");
setDocumentChanged(false); // indicate no changes pending anymore after the save
file = new File(sourceUrl.getPath()).getParentFile();
((HTMLDocument) getDocument()).setBase(file.toURI().toURL()); // set the doc base
deleteTempDir();
//System.out.println("DocumentPane saveSuccessful = true");
saveSuccessful = true; // signal that saving was successful
}
else {
saveThread = null;
throw new DocNameMissingException();
}
}
catch (final MalformedURLException mue) {
if (file != null) {
Util.errMsg(this, "Can not create a valid URL for\n" + file.getAbsolutePath(), mue);
}
else {
Util.errMsg(this, mue.getMessage(), mue);
}
}
catch (final Exception e) {
if (savedUrl != null) {
sourceUrl = savedUrl;
}
Util.errMsg(this, "An exception occurred while saving the file", e);
}
saveThread = null;
savedUrl = sourceUrl;
}
}
/**
* determine the directory this DocumentPane
references image
* files from
*
* @return the directory image files referenced by this
* DocumentPane
are found
*/
public File getImageDir() {
File srcDir = null;
if (savedUrl == null && newDocNo > 0) {
// new Document: use temp dir as source
srcDir = new File(docTempDir + File.separator + SHTMLPanelImpl.IMAGE_DIR + File.separator);
}
else {
if (savedUrl == null) {
// document has been saved before: source is 'sourceUrl'
srcDir = new File(new File(sourceUrl.getPath()).getParent() + File.separator + SHTMLPanelImpl.IMAGE_DIR
+ File.separator);
}
else {
/*
document has been saved before but now is
to be saved under new name: source is 'old' url
*/
srcDir = new File(new File(savedUrl.getPath()).getParent() + File.separator + SHTMLPanelImpl.IMAGE_DIR
+ File.separator);
}
}
return srcDir;
}
/**
* save image files
*/
private void saveImages() {
final File srcDir = getImageDir();
final File destDir = new File(new File(sourceUrl.getPath()).getParent() + File.separator
+ SHTMLPanelImpl.IMAGE_DIR + File.separator);
try {
if (srcDir.exists()) {
final ExampleFileFilter filter = new ExampleFileFilter();
filter.addExtension("gif");
filter.addExtension("jpg");
filter.addExtension("jpeg");
final File[] imgFiles = srcDir.listFiles();
for (int i = 0; i < imgFiles.length; i++) {
Util.copyFile(imgFiles[i],
new File(destDir.getAbsolutePath() + File.separator + imgFiles[i].getName()));
}
}
}
catch (final Exception e) {
Util.errMsg(this, e.getMessage(), e);
}
}
/**
* indicates whether or not a save process is in progress
*
* @return true, if a save process is going on, else false
*/
public boolean saveInProgress() {
//System.out.println("DocumentPane.saveInProgress=" + (saveThread != null) + " for document " + getDocumentName());
return saveThread != null;
}
/**
* Saves the style sheet of this document to a CSS file.
*
* With stage 8, saves a style sheet by merging it with the existing * one with the same name/location. Styles in this style sheet overwrite * styles in the already existing style sheet.
*/ public void saveStyleSheet() throws IOException { final SHTMLDocument doc = (SHTMLDocument) getDocument(); final StyleSheet styles = doc.getStyleSheet(); final String styleSheetName = getStyleSheetName(); if (styleSheetName != null) { final File styleSheetFile = new File(new URL(styleSheetName).getFile()); if (!styleSheetFile.exists()) { // no styles present at save location, create new style sheet styleSheetFile.createNewFile(); } else { if (loadedFromFile) { if ((savedUrl == null) || (!savedUrl.getPath().equals(sourceUrl.getPath()))) { /* this style sheet was loaded from somewhere else and now is being saved at a new location where a style sheet exists havig the same name --> merge */ mergeStyleSheets(loadStyleSheet(styleSheetFile), styles); } else { /* same location where styles originally came from, overwrite existing styles with new version */ styleSheetFile.delete(); styleSheetFile.createNewFile(); } } else { /* this style sheet was newly created and now is being saved at a location where a style sheet exists havig the same name --> merge */ mergeStyleSheets(loadStyleSheet(styleSheetFile), styles); } } final OutputStream os = new FileOutputStream(styleSheetFile); final OutputStreamWriter osw = new OutputStreamWriter(os); CSSWriter cssWriter; cssWriter = new CSSWriter(osw, styles); cssWriter.write(); osw.close(); os.close(); } } /** * Merges two style sheets by adding all the rules found * in the source style sheet that are not contained * in the destination style sheet. Assumes the rules * of src and dest are already loaded. * * @param sourceStyleSheet the source StyleSheet * @param destinationStyleSheet the destination StyleSheet */ private void mergeStyleSheets(final StyleSheet sourceStyleSheet, final StyleSheet destinationStyleSheet) throws IOException { String name; Object elem; final Vector srcNames = Util.getStyleNames(sourceStyleSheet); final Vector destNames = Util.getStyleNames(destinationStyleSheet); final StringWriter sw = new StringWriter(); final StringBuffer buf = sw.getBuffer(); final CSSWriter cssWriter = new CSSWriter(sw, null); for (int i = 0; i < srcNames.size(); i++) { elem = srcNames.get(i); name = elem.toString(); if (destNames.indexOf(elem) < 0) { buf.delete(0, buf.length()); cssWriter.writeRule(name, sourceStyleSheet.getStyle(name)); destinationStyleSheet.removeStyle(name); destinationStyleSheet.addRule(buf.toString()); } } } /** * get the URL of the style sheet of this document * *The name is built by
This is only to be used when it is made sure, * that the document is saved at the location specified * by 'source'.
* * @param the URL of the source this document is to be loaded from */ public void setSource(final URL source) { savedUrl = sourceUrl; sourceUrl = source; final String fName = source.getFile(); docName = fName.substring(fName.lastIndexOf("/") + 1); fireNameChanged(); } /** * get the source, this document was having before its current sourceUrl * was set. * * @return the source URL before a name change */ public URL getOldSource() { if (savedUrl == null) { return sourceUrl; } else { return savedUrl; } } /** * get the source this document can be loaded from * * @return the URL this document can be loaded from */ public URL getSource() { return sourceUrl; } /** * indicates whether or not this document was newly created and not saved so * far. * * @return true, if this is a new document that has not been saved so far */ public boolean isNewDoc() { return sourceUrl == null; } /** * get the document of thisDocumentPane
*
* @return the Document
of this DocumentPane
*/
public Document getDocument() {
return editorPane.getDocument();
}
HTMLDocument getHTMLDocument() {
return (HTMLDocument) sourceEditorPane.getDocument();
}
/**
* Switches between the rich text view and the source view, given
* tabbed panes are not used. Has no corresponding action; calling
* this method is up to the caller application of SimplyHTML; the
* application should call the method of the same name available at
* SHTMLPanel.
*/
public void switchViews() {
if (paneHoldingScrollPanes instanceof JTabbedPane) {
return;
}
// [ Tabbed pane not used ]
if (activeView == VIEW_TAB_LAYOUT) {
setHTMLView();
paneHoldingScrollPanes.remove(richViewScrollPane);
paneHoldingScrollPanes.add(sourceViewScrollPane);
activeView = VIEW_TAB_HTML;
}
else {
setLayoutView();
paneHoldingScrollPanes.remove(sourceViewScrollPane);
paneHoldingScrollPanes.add(richViewScrollPane);
activeView = VIEW_TAB_LAYOUT;
}
}
/**
* Switches the DocumentPane to HTML view.
*/
private void setHTMLView() {
try {
editorPane.getDocument().removeDocumentListener(this);
final StringWriter stringWriter = new StringWriter();
if (isHtmlChanged()) {
editorPane.getEditorKit().write(stringWriter, editorPane.getDocument(), 0,
editorPane.getDocument().getLength());
stringWriter.close();
String newText = stringWriter.toString();
if (!Util.preferenceIsTrue("writeHead", "true")) {
newText = newText.replaceAll("(?ims).*?(