其实是我之前写的《简单的文本编辑器》增强版。简单的文本编辑器
因为是要发送邮件的,所以要生成的其实是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是字体和字号如果同时设置可能有一个属性会失效。等我调整好之后会重新更新代码。