HTML代码生成

其实是我之前写的《简单的文本编辑器》增强版。简单的文本编辑器

因为是要发送邮件的,所以要生成的其实是html代码。原理是将使用JTextPane的setContentType("text/html");将其内容设置为html内容,这样使用getText()方法的时候获取的就是html的代码。不过其自动生成的代码在显示高亮和设置字体方面有问题,所以做了特殊处理。另外,我还重写了JTextPane的复制、粘贴、和剪切方法,使剪切板能够连同格式一起操作。相对博客之前的版本,我新添加了右键菜单,在右键菜单中添加了复制、粘贴,剪切还有清空内容四个功能。剪切板的代码在我的另外一篇博客里:支持对象的剪切板 。

下面为我更新后的代码。代码行数有点多,主要是为了调用方便自己将创建组件的方法进行了封装。另:使用了allopy.jar皮肤包,下载地址:http://download.csdn.net/detail/levelmini/7298205


import java.awt.Color;
import java.awt.Component;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Point;
import java.awt.Toolkit;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JColorChooser;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JEditorPane;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.JTextPane;
import javax.swing.JWindow;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.border.LineBorder;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
import javax.swing.text.EditorKit;
import javax.swing.text.MutableAttributeSet;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyledDocument;
import javax.swing.text.StyledEditorKit;
import javax.swing.text.html.HTML;
import javax.swing.text.html.HTMLDocument;
import javax.swing.text.html.HTMLEditorKit;

import org.dom4j.CDATA;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;
import org.dom4j.tree.FlyweightCDATA;

import com.microproposal.util.CopyContent;
import com.microproposal.util.CopyObj;
import com.microproposal.util.SerialTransferable;


/**转载请注明出处:http://blog.csdn.net/levelmini*/
public class ModifyMail extends JFrame {
	
	private static final long serialVersionUID = -4780581099315563633L;


	private final int WIDTH = 550;
	private final int HEIGHT = 410;
	private static final Font FONT1 = new Font("宋体", Font.BOLD, 14);
	private static final Font FONT2 = new Font("宋体", Font.PLAIN, 12);
	private static JPanel panel ;
	private JComboBox<String> cbFont,cb;
	private JComboBox<Integer>cbSize;
	private Color color = Color.BLACK;
	JTextPane jtp;
	JButton mail;
	JDialog dialog;
	JTextField th;
	JLabel sub;
	InputWindow window = null;
	private String tm = "营业";
	public ModifyMail(JDialog d) {
		if (d != null) {
			d.setVisible(false);
			dialog = d;			
		}
		JLabel label1 = getJLabel("选择要修改的文件", FONT1);
		String[] option = {"Trade","Medical","National-Trade","National-Medical","Team 汇总报告","SubRegion 汇总报告 - Trade","SubRegion 汇总报告 - Medical","邮件签名"};
		cb= new JComboBox<String>(option); 
		JButton refresh = getButton("刷新", refresh());
		JPanel p1 = getJPanel(label1,cb,refresh);
		
		JLabel label2 = getJLabel("主题:",FONT1);
		th = getTextField(25, true);
		th.setHorizontalAlignment(JTextField.RIGHT);
		sub = getJLabel("XX销售奖金报告("+tm+")",FONT2);
		JPanel p2 = getJPanel(label2,th,sub);
		
		Icon icon = getIcon("font_color.png");
		JButton fontColor = getButton("", icon, "字体颜色",getFontColor());
		icon = getIcon("highLight.png");
		JButton heightLight = getButton("", icon, "高亮显示",getHighColor());
		// GraphicsEnvironment是一个抽象类,不能实例化,只能用其中的静态方法获取一个实例
//		GraphicsEnvironment environment = GraphicsEnvironment.getLocalGraphicsEnvironment();
		//字体选择
//		String [] str = environment.getAvailableFontFamilyNames();// 获取系统字体
		String [] str = {"Arial","微软雅黑","宋体"};
		cbFont = new JComboBox<String>(str);
		cbFont.setSelectedItem("微软雅黑");//默认宋体
		cbFont.setToolTipText("字体选择");
		cbFont.addActionListener(getFontName());
		//字号选择
		Integer [] size = {9,10,11,12,13,14,15,16,17,18,19,20,21,22};
		cbSize = new JComboBox<Integer>(size);
		cbSize.setSelectedItem(11);
		cbSize.setToolTipText("字号选择");
		cbSize.addActionListener(getFontSize());
		//加粗
		icon = getIcon("Bold.png");
		JButton bold = getButton("", icon, "加粗", getBold());
		//斜体
		icon = getIcon("Italic.png");
		JButton italic = getButton("", icon, "斜体", getItalic());
		//下划线
		icon = getIcon("Underline.png");
		JButton underline = getButton("", icon, "下划线", getUnderLine());
		icon = getIcon("link.png");
		mail = getButton("", icon, "超链接", getHyperLink());
		final JPanel functionPane = getJPanel(cbFont,cbSize,fontColor,heightLight,bold,italic,underline,mail);
		functionPane.setVisible(true);
		
		jtp = new JTextPane(){

			private static final long serialVersionUID = -4609295445059037145L;

			@Override
			public void copy(){
				int start = jtp.getSelectionStart();
				int end = jtp.getSelectionEnd();
				if (start == end) {
					return;
				}
				HTMLDocument doc = (HTMLDocument) jtp.getStyledDocument();
				CopyContent c = new CopyContent();					
				for (int i = start; i < end; i++) {
					javax.swing.text.Element e = doc.getCharacterElement(i);
					if (e.getName().equals("content")) {
						try {
							CopyObj obj = new CopyObj();
							obj.setAs(e.getAttributes());
							obj.setContent(jtp.getText(i, 1));
							c.add(obj);
						} catch (BadLocationException e1) {
							e1.printStackTrace();
						}
					}
				}
				Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
				SerialTransferable transferable = new SerialTransferable(c);
				clipboard.setContents(transferable, null);
			}
			@Override
			public void paste(){
				Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
				HTMLDocument doc = (HTMLDocument) jtp.getStyledDocument(); 
				int start = jtp.getSelectionStart();
				int end = jtp.getSelectionEnd();
				try {
					if (start < end) {	//如果有选中的数据则移除选中的数据
						doc.remove(start, end-start);
					}
					DataFlavor text_flavor = DataFlavor.stringFlavor; 
					DataFlavor obj_flavor = new DataFlavor("application/x-java-serialized-object;class=com.microproposal.util.CopyContent");
					if (clipboard.isDataFlavorAvailable(obj_flavor)) {	//这个判断一定要写在前面,否则会多粘贴出来东西。
						CopyContent object = (CopyContent) clipboard.getData(obj_flavor);
						int i = 0;
						for (CopyObj obj : object) {
							doc.insertString(start+i, obj.getContent(), obj.getAs());
							i++;
						}
					} else if (clipboard.isDataFlavorAvailable(text_flavor)) {
						String str = (String) clipboard.getData(text_flavor);
						doc.insertString(start, str, null);
					} 
				} catch (ClassNotFoundException e) {
					JOptionPane.showMessageDialog(this, e);
				} catch (UnsupportedFlavorException e) {
					JOptionPane.showMessageDialog(this, e);
				} catch (IOException e) {
					JOptionPane.showMessageDialog(this, e);
				} catch (BadLocationException e) {
					e.printStackTrace();
				}
			}
			public void cut(){
				this.copy();
				HTMLDocument doc = (HTMLDocument) jtp.getStyledDocument(); 
				int start = jtp.getSelectionStart();
				int end = jtp.getSelectionEnd();
					if (start < end) {	//如果有选中的数据则移除选中的数据
						try {
							doc.remove(start, end-start);
						} catch (BadLocationException e) {
							e.printStackTrace();
						}
					}
			}
		};
		jtp.setFont(FONT1);
		jtp.setContentType("text/html");
		jtp.setCursor(new Cursor(Cursor.TEXT_CURSOR));
		JMenuItem copy = new JMenuItem("Copy");
		copy.addActionListener(new ActionListener(){
			@Override
			public void actionPerformed(ActionEvent e) {
				jtp.copy();
			}
		});
		
		JMenuItem paste = new JMenuItem("Paste");
		paste.addActionListener(new ActionListener(){
			@Override
			public void actionPerformed(ActionEvent e) {
				jtp.paste();
			}
		});
		JMenuItem cut = new JMenuItem("Cut");
		cut.addActionListener(new ActionListener(){
			@Override
			public void actionPerformed(ActionEvent e) {
				jtp.cut();
			}
		});
		
		JMenuItem clear = new JMenuItem("Clear");
		clear.addActionListener(new ActionListener(){
			@Override
			public void actionPerformed(ActionEvent e) {
				jtp.setText("");
			}
		});
		
		final JPopupMenu menu = getPopupMenu(copy,paste,cut,clear);
		jtp.addMouseListener(new MouseAdapter(){
			@Override
			public void mouseClicked(MouseEvent e) {
				if (e.getButton() != MouseEvent.BUTTON3) {
					return;
				}
				menu.show(jtp, e.getX(), e.getY());
			}
		});
		JScrollPane jsp = new JScrollPane(jtp);
		jsp.setPreferredSize(new Dimension(530,200));
		JPanel p3 = getJPanel(jsp);
		
		JButton ok = getButton("保存",getSave());
		JButton cancel = getButton("取消",new ActionListener(){
			@Override
			public void actionPerformed(ActionEvent e) {
				ModifyMail.this.dispose();
				if (dialog != null) {
					dialog.setVisible(true);					
				} else {
					System.exit(0);
				}
			}
		});
		/*
		 //测试用的按钮。
		  JButton getClipBoard = getButton("剪切板内容",new ActionListener(){
			@Override
			public void actionPerformed(ActionEvent e){
				Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
				DataFlavor df = DataFlavor.stringFlavor;
				String s = null;
				try {
					s =clipboard.getData(df).toString();
				} catch (UnsupportedFlavorException e1) {
					e1.printStackTrace();
				} catch (IOException e1) {
					e1.printStackTrace();
				}
				System.out.println(s);
			}
		});
		JButton getContent = getButton("getContent",new ActionListener(){
			@Override
			public void actionPerformed(ActionEvent e){
				System.out.println(jtp.getText());
			}
		});*/
	
		JPanel p4 = getJPanel(ok,cancel);
		
		panel = getJPanel(p1,p2,functionPane,p3,p4);
		
		init();
		this.addWindowListener(new WindowAdapter(){
			@Override
			public void windowClosed(WindowEvent e) {
				super.windowClosed(e);
				if (dialog != null) {
					dialog.setVisible(true);					
				} else {
					System.exit(0);
				}
			}
		});
		this.addComponentListener(new ComponentAdapter(){
			@Override
			public void componentMoved(ComponentEvent e) {
				
			}
		});
	}

	/**
	 * 获取文件中的文本
	 * @return
	 */
	private ActionListener refresh() {
		return new ActionListener(){
			@Override
			public void actionPerformed(ActionEvent e) {
				String file = cb.getSelectedItem().toString();
				String node = "";
				if(file.endsWith("邮件签名")){
					node = "foot";
					th.setEditable(false);
				} else {
					th.setEditable(true);
				}
				if (file.equals("National-Trade")) {
					node = "deptTrade";
					tm="营业";
				}
				if (file.equals("National-Medical")) {
					node = "deptMedical";
					tm="医务";
				}
				if (file.equals("Trade")) {
					node = "areaTrade";
					tm="营业";
				}
				if (file.equals("Medical")) {
					node = "areaMedical";
					tm="医务";
				}
				if(file.equals("Team 汇总报告")){
					node = "team";
				}
				if (file.equals("SubRegion 汇总报告 - Trade")) {
					node = "subregionTrade";
					tm="营业";
				}
				if (file.equals("SubRegion 汇总报告 - Medical")) {
					node = "subregionMedical";
					tm="医务";
				}
				
				//"Team 汇总报告","SubRegion 汇总报告 - Trade","SubRegion 汇总报告 - Medical"
				jtp.setText("");
				HTMLEditorKit htmledit=new HTMLEditorKit();  
				HTMLDocument doc=(HTMLDocument) jtp.getDocument();
				String [] mail = read(node);
				String html = mail[0];
				String theme = mail[1];
				th.setText(theme);
				sub.setText(" XX销售奖金报告("+tm+")");
				try {
					htmledit.insertHTML(doc, 0, html, 0, 0, null);
				} catch (BadLocationException e1) {
					e1.printStackTrace();
				} catch (IOException e1) {
					e1.printStackTrace();
				}
			}
		};
	}

	private ActionListener getSave() {
		return new ActionListener(){
			@Override
			public void actionPerformed(ActionEvent e) {
				//获取修改的文件
				String file = cb.getSelectedItem().toString();
				//获取内容
				String content = jtp.getText();
				//处理内容
				content = content.split("<body>")[1];
				content = content.split("</body>")[0];
				
				//使用dom4j对mailbody.xml进行修改
				String node = "";
				if(file.endsWith("邮件签名")){
					node = "foot";
					th.setEditable(false);
				}
				if (file.equals("National-Trade")) {
					node = "deptTrade";
				}
				if (file.equals("National-Medical")) {
					node = "deptMedical";
				}
				if (file.equals("Trade")) {
					node = "areaTrade";
				}
				if (file.equals("Medical")) {
					node = "areaMedical";
				}
				if(file.equals("Team 汇总报告")){
					node = "team";
				}
				if (file.equals("SubRegion 汇总报告 - Trade")) {
					node = "subregionTrade";
				}
				if (file.equals("SubRegion 汇总报告 - Medical")) {
					node = "subregionMedical";
				}
				save(node,content,th.getText());
				showMessage("修改" + file + "成功!", "修改成功", "ok.png");
			}
		};
	}

	private ActionListener getHyperLink() {
		return new ActionListener(){
			@Override
			public void actionPerformed(ActionEvent e) {
				if (window == null) {
					window = new InputWindow();					
				} else {
					window.setVisible(true);
				}
			}
		};
	}

	private ActionListener getUnderLine() {
		return new ActionListener(){
			@Override
			public void actionPerformed(ActionEvent e) {
				if (jtp != null) {
					StyledEditorKit kit = getStyledEditorKit(jtp);
					MutableAttributeSet attr = kit.getInputAttributes();
					boolean underline = (StyleConstants.isUnderline(attr)) ? false : true;
					SimpleAttributeSet sas = new SimpleAttributeSet();
					StyleConstants.setUnderline(sas, underline);
					setCharacterAttributes(jtp, sas, false);
					jtp.grabFocus();
				}
			}
		};
	}

	private ActionListener getFontColor() {
		return new ActionListener(){
			@Override
			public void actionPerformed(ActionEvent e) {
				Color c = color;
				color = JColorChooser.showDialog(panel, "选择颜色", Color.BLACK);
				color = (color==null?c:color);//这句废话是为了保证没选择任何颜色关闭调色板后,能还原原来的颜色
				if (jtp != null) {
					MutableAttributeSet attr = new SimpleAttributeSet();
					StyleConstants.setForeground(attr, color);
					setCharacterAttributes(jtp, attr, false);
				}
				jtp.grabFocus();
			}
		};
	}

	private ActionListener getFontName() {
		return new ActionListener(){
			@Override
			public void actionPerformed(ActionEvent e) {
				String fontName = cbFont.getSelectedItem().toString();
				if (jtp != null) {
					MutableAttributeSet attr = new SimpleAttributeSet();
					StyleConstants.setFontFamily(attr, fontName);
					setCharacterAttributes(jtp, attr, false);
				}
				jtp.grabFocus();
			}
		};
	}

	private ActionListener getFontSize() {
		return new ActionListener(){
			@Override
			public void actionPerformed(ActionEvent e) {
				int fontSize = (Integer) cbSize.getSelectedItem();
				if (jtp != null) {
					//使用HTMLEditorKit显示高亮
					HTMLEditorKit htmledit=new HTMLEditorKit();
					HTMLDocument doc = (HTMLDocument) jtp.getDocument();
					//获取选择的内容
					String cont = jtp.getSelectedText();
					
					//获取选择的位置
					int start = jtp.getSelectionStart();
					int end = jtp.getSelectionEnd();
					//设置内容
					cont = new StringBuffer("<span style=\"font-size:")
					.append(fontSize).append(".0 pt\">")
					.append(cont)
					.append("</span>")
					.toString();
					try {
						//这里一定要先从end插入然后再删除,否则选中第一个字符换字体的时候会出问题
						htmledit.insertHTML(doc, end, cont, 0, 0, HTML.Tag.SPAN);
						
						doc.remove(start, end - start);
					} catch (BadLocationException ex) {
						ex.printStackTrace();
					} catch (IOException e1) {
						e1.printStackTrace();
					};
					
				}
				jtp.grabFocus();
			}
		};
	}
	/**
	 * 初始化界面
	 */
	void init() {
		MutableAttributeSet attr = new SimpleAttributeSet();
		StyleConstants.setFontFamily(attr, "宋体");
		StyleConstants.setFontSize(attr, 12);
		jtp.getStyledDocument().setCharacterAttributes(0, 0, attr, false);
		
		// 设置程序显示在屏幕中间
		Dimension size = Toolkit.getDefaultToolkit().getScreenSize();
		int w = size.width;
		int h = size.height;
		int x = (w - WIDTH) / 2;
		int y = (h - HEIGHT) / 2;
		this.add(panel);
		this.setBounds(x, y, WIDTH, HEIGHT);
		this.setResizable(false);
		this.setTitle("Mailbody Editor");
		this.setVisible(true);
		this.setAlwaysOnTop(false);
		this.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
	}

	/**
	 * 加粗
	 * @return
	 */
	private ActionListener getBold(){
		return new ActionListener(){
			@Override
			public void actionPerformed(ActionEvent e) {
				if (jtp != null) {
					StyledEditorKit kit = getStyledEditorKit((JEditorPane)jtp);
					MutableAttributeSet attr = kit.getInputAttributes();
					boolean bold = (StyleConstants.isBold(attr)) ? false : true;
					SimpleAttributeSet sas = new SimpleAttributeSet();
					StyleConstants.setBold(sas, bold);
					setCharacterAttributes(jtp, sas, false);
				}
				jtp.grabFocus();
			}
		};
	}
	private ActionListener getItalic(){
		return new ActionListener(){
			@Override
			public void actionPerformed(ActionEvent e) {
				if (jtp != null) {
					StyledEditorKit kit = getStyledEditorKit(jtp);
					MutableAttributeSet attr = kit.getInputAttributes();
					boolean italic = (StyleConstants.isItalic(attr)) ? false : true;
					SimpleAttributeSet sas = new SimpleAttributeSet();
					StyleConstants.setItalic(sas, italic);
					setCharacterAttributes(jtp, sas, false);
				}
				jtp.grabFocus();
			}
		};
	}
	
	
	public JLabel getJLabel(String text, Font font) {
		JLabel label = new JLabel(text);
		label.setFont(font);
		return label;
	}
	/**
	 * 设置高亮
	 * @return
	 */
	private ActionListener getHighColor(){
		return new ActionListener(){
			@Override
			public void actionPerformed(ActionEvent e) {
				Color c = color;
				color = JColorChooser.showDialog(panel, "选择颜色", Color.BLACK);
				color = (color==null?c:color);//这句废话是为了保证没选择任何颜色关闭调色板后,能还原原来的颜色
				//------------------------------------------------------------------
				
				//使用HTMLEditorKit显示高亮
				HTMLEditorKit htmledit=new HTMLEditorKit();
				HTMLDocument doc = (HTMLDocument) jtp.getDocument();
				//获取选择的内容
				String cont = jtp.getSelectedText();
				
				//获取选择的位置
				int start = jtp.getSelectionStart();
				int end = jtp.getSelectionEnd();
				//设置内容
				cont = new StringBuffer("<span style=\"background-color:rgb(")
				.append(color.getRed()).append(",")
				.append(color.getGreen()).append(",")
				.append(color.getBlue()).append(")\">")
				.append(cont)
				.append("</span>")
				.toString();
				try {
					//这里一定要先从end插入然后再删除,否则选中第一个字符高亮的时候会出问题
					htmledit.insertHTML(doc, end, cont, 0, 0, HTML.Tag.SPAN);
					doc.remove(start, end - start);
				} catch (BadLocationException ex) {
					ex.printStackTrace();
				} catch (IOException e1) {
					e1.printStackTrace();
				}
				
				//---------------------------------------------------------------------

				jtp.grabFocus();
			}
		};
	}
	
	
	/**
	 * 获取一个JTextField
	 * 
	 * @param name
	 *            输入框的名字
	 * @param length
	 *            输入框长度
	 * @param editable
	 *            是否可编辑
	 * @param formatText
	 *            默认显示的内容
	 * @param toolTip
	 *            提示信息
	 * @return JTextField
	 */
	public JTextField getTextField(String name, int length, boolean editable,
			String formatText, String toolTip) {
		JTextField text = new JTextField(formatText, length);
		text.setName(name);
		text.setEditable(editable);
		text.setToolTipText(toolTip);
		text.setFont(FONT2);
		return text;
	}

	/**
	 * 获取一个JTextField
	 * 
	 * @param length
	 *            输入框长度
	 * @param editable
	 *            是否可编辑
	 * @return
	 */
	public JTextField getTextField(int length, boolean editable) {
		return getTextField(null, length, editable, null, null);
	}

	/**
	 * 获取一个JTextField
	 * 
	 * @param 输入框的名字
	 * @param length
	 *            输入框长度
	 * @param editable
	 *            是否可编辑
	 * @return
	 */
	public JTextField getTextField(String name, int length, boolean editable) {
		return getTextField(name, length, editable, null, null);
	}
	/**
	 * 获取一个带有监听器的JButton
	 * 
	 * @param text
	 *            button上显示的内容
	 * @param name
	 *            按钮的名字
	 * @param l
	 *            监听器。传入NULL则点击按钮显示文件选择器
	 * @return JButton
	 */
	public JButton getButton(String text, Icon icon, String name, ActionListener l) {
		final JButton button = new JButton(text);
		button.setName(name);
		button.setIcon(icon);
		button.setToolTipText(name);
		if (l != null) {
			button.addActionListener(l);
		} else {
			button.addActionListener(null);
		}
		return button;
	}

	/**
	 * 获取一个带有监听器的JButton
	 * 
	 * @param text
	 *            button上显示的内容
	 * @param l
	 *            监听器。传入NULL则点击按钮显示文件选择器
	 * @return JButton
	 */
	public JButton getButton(String text, ActionListener l) {
		return getButton(text, null,text, l);
	}

	/**
	 * 返回一个JPanel。如果传入组件,则将传入的组件添加到这个JPanel中再返回
	 * 
	 * @param name
	 *            容器的名字
	 * @param component
	 *            任意多个JComponent类型组件,按照要添加的顺序传入
	 * @return JPanel
	 */
	public JPanel getJPanel(String name, JComponent... component) {
		JPanel panel = new JPanel();
		panel.setName(name);
		if (component != null) {
			for (JComponent c : component) {
				panel.add(c);
			}
		}
		panel.setBackground(new Color(241, 241, 241));
		return panel;
	}

	/**
	 * 返回一个JPanel。如果传入组件,则将传入的组件添加到这个JPanel中再返回
	 * 
	 * @param component
	 *            任意多个JComponent类型 组件
	 * @return JPanel
	 */
	public JPanel getJPanel(JComponent... component) {
		return getJPanel(null, component);
	}

	public JPopupMenu getPopupMenu(JMenuItem ... items){
		JPopupMenu menu = new JPopupMenu();
		if (items != null && items.length > 0) {
			for (JMenuItem item : items) {
				menu.add(item);
			}
		}
		return menu;
	}
	/**
	 * 获取 Icon 图标
	 * 
	 * @param path
	 *            图标名
	 * @return icon
	 */
	public static Icon getIcon(String name) {
		return new ImageIcon(getImage(name));
	}

	/**
	 * 获取 Image 图像
	 * 
	 * @param name
	 *            图像名
	 * @return Image
	 */
	public static Image getImage(String name) {
		String path = "res/icon/";
		path = path + name;
		Image image = Toolkit.getDefaultToolkit().getImage(path);
		return image;
	}

	protected static final StyledEditorKit getStyledEditorKit(JEditorPane e) {
		EditorKit k = e.getEditorKit();
		if (k instanceof StyledEditorKit) {
			return (StyledEditorKit) k;
		}
		throw new IllegalArgumentException("EditorKit must be StyledEditorKit");
	}
	protected static final StyledDocument getStyledDocument(JEditorPane e) {
		Document d = e.getDocument();
		if (d instanceof StyledDocument) {
			return (StyledDocument) d;
		}
		throw new IllegalArgumentException("document must be StyledDocument");
	}
	public static final void setCharacterAttributes(JEditorPane editor, AttributeSet attr, boolean replace) {
		int p0 = editor.getSelectionStart();
		int p1 = editor.getSelectionEnd();
		if (p0 != p1) {
			StyledDocument doc = getStyledDocument(editor);
			doc.setCharacterAttributes(p0, p1 - p0, attr, replace);
		}
		StyledEditorKit k = getStyledEditorKit(editor);
		MutableAttributeSet inputAttributes = k.getInputAttributes();
		if (replace) {
			inputAttributes.removeAttributes(inputAttributes);
		}
		inputAttributes.addAttributes(attr);
	} 

	void showInfo(String message, String title, String icon) {
		JOptionPane.showMessageDialog(panel, message, title,
				JOptionPane.INFORMATION_MESSAGE, getIcon(icon));
	}


	
	/**
	 * 运行程序的主要方法。 主要功能:应用主题、创建面板
	 */
	public static void invokeApp(final JDialog g) {
		try {
			SwingUtilities.invokeLater(new Runnable() {
				public void run() {
					try {
						JFrame.setDefaultLookAndFeelDecorated(true);
						JDialog.setDefaultLookAndFeelDecorated(true);
						UIManager
								.setLookAndFeel("com.incors.plaf.alloy.AlloyLookAndFeel");

						new ModifyMail(g).init();
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
			});
		} catch (Exception e) {
			e.printStackTrace();
		}
	}


	public void setButtonsEnable(boolean enabled) {
		Component[] component = ((JPanel) panel.getComponent(6))
				.getComponents();
		for (Component comp : component) {
			comp.setEnabled(enabled);
		}
	}
	
	private class InputWindow extends JWindow{

		private static final long serialVersionUID = -8362686600399865786L;
		JTextField content,link;
		public InputWindow() {
			super(ModifyMail.this);
			Point p = mail.getLocationOnScreen();
			setBounds(p.x-135,p.y+25,200,90);
			JLabel c = getJLabel("文字:",FONT2);
			content = getTextField(23, true);
			content.setToolTipText("显示的文字");
			
			JLabel l = getJLabel("链接:", FONT2);
			link = getTextField(23, true);
			link.setToolTipText("链接地址");
			
			JButton add = getButton("添加", insertLink());
			JButton cancel = getButton("取消",calcel());
			
			JPanel panel = getJPanel(c,content,l,link,add,cancel);
			panel.setLayout(new FlowLayout(FlowLayout.RIGHT));
			panel.setBackground(Color.WHITE);
			panel.setBorder(LineBorder.createBlackLineBorder());
			super.add(panel);
			setBackground(Color.WHITE);
			setVisible(true);
			setDefaultCloseOperation(DISPOSE_ON_CLOSE);
		}

		private ActionListener calcel() {
			return new ActionListener(){
				@Override
				public void actionPerformed(ActionEvent e) {
					InputWindow.this.dispose();
					jtp.grabFocus();
				}
			};
		}
		
		
		@Override
		public void paint(Graphics g) {
			Point p = mail.getLocationOnScreen();
			setBounds(p.x-135,p.y+25,200,90);
			super.paint(g);
		}


		/**
		 * 插入链接
		 * @return
		 */
		private ActionListener insertLink() {
			return new ActionListener(){
				@Override
				public void actionPerformed(ActionEvent e) {
					//文字
					String contentString = content.getText().trim();
					//链接 
					String url = link.getText().trim();
					//判断是否输入了文字
					if (null == contentString || "".equals((contentString.trim()))) {
						contentString = url;
					}
					
					//判断是超链接还是邮箱后拼接字符串
					StringBuffer str = new StringBuffer("<a href=\"");
					if (url.contains("@")) {
						str.append("mailto:");
					} 
					str.append(url).append("\">").append(contentString).append("</a>");
					
					contentString = str.toString();
					//获取光标位置
					int pos = jtp.getSelectionStart();
					int end = jtp.getSelectionEnd();
					try {
						//使用HTMLEditorKit插入超链接
						HTMLEditorKit htmledit=new HTMLEditorKit();  
						HTMLDocument doc=(HTMLDocument) jtp.getDocument();
						doc.remove(pos, end-pos);
						htmledit.insertHTML(doc, pos, contentString, 0, 0, HTML.Tag.A);
						htmledit.insertHTML(doc, pos, " ", 0, 0, HTML.Tag.SPAN);
					} catch (BadLocationException e1) {
						e1.printStackTrace();
					} catch (IOException e1) {
						e1.printStackTrace();
					}
					content.setText("");
					link.setText("");
					InputWindow.this.setVisible(false);
					jtp.grabFocus();
				}
			};
		}
	}

	/**
	 * 保存内容到mailbody.xml
	 */
	private void save(String nodeName,String content,String themes){
		SAXReader reader = new SAXReader();
		File file = new File("conf\\mailbody.xml");
		org.dom4j.Document doc = null;
		try {
			doc = reader.read(file);
			doc.setXMLEncoding("UTF-8");
		} catch (DocumentException e) {
			e.printStackTrace();
		}
		Element root = doc.getRootElement();
		Element node = root.element(nodeName);
		Element contentNode = node.element("content");
		Element theme = node.element("theme");

		//将编辑器中自动生成的font标签替换为span标签
		content = content.replaceAll("<font size=\"", "<span style=\"font-size:");
		content = content.replaceAll("</font>", "</span>");
		content = content.trim().replaceAll("\n\n", "<br/>");//将换行替换为html中的换行
//		content = content.trim().replaceAll("\t","    ");//制表符替换为四个空格
		//删除content中所有多余的div标签和span标签
		content = replace(content,"div","span");
		content = "<div style=\"font-size:11.0pt;font-family: \'微软雅黑\',\'sans-serif\'\">\r\n"+content+"\r\n</div>";
		
		CDATA cdata = new FlyweightCDATA(content.trim());
		contentNode.clearContent();
		contentNode.add(cdata);
		theme.clearContent();
		theme.setText(themes);
		try {
			//设置输出的XML的格式
			OutputFormat out = OutputFormat.createPrettyPrint();
			//设置输出的编码方式
			out.setEncoding("UTF-8");
			//去空格
			out.setTrimText(true);
			// 设置XML文档的位置
			XMLWriter writer = new XMLWriter(new FileOutputStream(file),out);
			file.delete();
			// 向XML文档中写入数据
			writer.write(doc);
			// 关闭流
			writer.close();
		} catch (Exception ex) {
			ex.printStackTrace();
		}
	}

	/**
	 * 以数组形式返回 mailbody.xml 中的内容。0:邮件内容。1:邮件主题
	 * @param nodeName
	 * @return
	 */
	private String[] read(String nodeName){
		SAXReader reader = new SAXReader();
		File file = new File("conf\\mailbody.xml");
		org.dom4j.Document doc = null;
		try {
			doc = reader.read(file);
			doc.setXMLEncoding("UTF-8");
		} catch (DocumentException e) {
			e.printStackTrace();
		}
		Element root = doc.getRootElement();
		Element node = root.element(nodeName);
		Element content = node.element("content");
		Element theme = node.element("theme");
		String [] mail = new String[2];
		mail[0] = content.getText();
		mail[1] = theme.getText();
		return mail;
	}
	
	/**
	 * 显示提示信息
	 * 
	 * @param message
	 *            提示信息
	 * @param title
	 *            提示信息框的标题
	 * @param icon
	 *            提示信息的图标
	 */
	private static void showMessage(String message, String title, String icon) {
		JOptionPane.showMessageDialog(panel, message, title,
				JOptionPane.INFORMATION_MESSAGE, getIcon(icon));
	}
	
	/**
	 * 替换source中s内含有的所有的标签
	 * @param source
	 * @param s
	 * @return
	 */
	private static String replace(String source ,String ... s){
		//如果传null或者空的字符串数组则直接返回一个空字符串
		if (s==null || s.length == 0) {
			return "";
		}
		for (int i = 0; i < s.length; i++) {
			source = replace(source,s[i],countStr(source, s[i]));
		    counter = 0;
		}
		
		return source;
	}
	
	private static int counter;
    /**
     * 判断内容中中包含指定标签的个数
      * @param str1 内容
     * @param str2 指定标签的内容,如:<code>< div ></code>,则传<code>div</code>
     * @return 重复的个数
     */
    public static int countStr(String str1, String str2) {
    	String tag = "<"+str2 + ">";
        if (str1.indexOf(tag) == -1) {
	        return 0;
        } else if (str1.indexOf(tag) != -1) {
	        counter++;
	        countStr(str1.substring(str1.indexOf(tag) +
                   tag.length()), str2);
               return counter;
        }
	        return 0;
    }
    
    /**
     * 按照重复的个数替换多余的标签
     * @param str1 源字符串
     * @param str2 要重复的标签
     * @param count 重复的个数
     * @return 替换所有重复标签后的新字符串
     */
    public static String replace(String str1 ,String str2 ,int count){
    	for (int i = 0; i < count; i++) {
			str1 = replaceLast(str1, str2, "");
		}
    	return str1;
    }
    
    /**
     * 按照就近原则替换标签
     * @param sourceString 源字符串
     * @param regex 要替换的标签
     * @param replacement 要把标签替换成此字符串
     * @return 替换后的字符串
     */
    public static String replaceLast(String sourceString ,String regex, String replacement){
    	String stag = "<"+regex+">";
    	String etag = "</"+regex+">";
    	int index = sourceString.lastIndexOf(stag);
    	String head = sourceString.substring(0, index);
    	String s = sourceString.substring(index);
    	s = s.replaceFirst(stag, replacement);
    	s = s.replaceFirst(etag, replacement);
    	return head+s;
    }
	
	public static void main(String[] args) {
		ModifyMail.invokeApp(null);
	}
}

运行效果图如下:




至此,html代码生成的小工具就写好了,已经有了几个基本的功能。更高级一些的功能,如排版之类的功能,等到客户有需求的时候再去开发吧。现在只能手动敲空格排版。

现在一直此代码的一个小bug是字体和字号如果同时设置可能有一个属性会失效。等我调整好之后会重新更新代码。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值