/*
* Copyright (C) 2014 Alec Dhuse
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*/
package co.foldingmap.GUISupport.components;
import co.foldingmap.GUISupport.FileExtensionFilter;
import co.foldingmap.GUISupport.panels.FileChoicePanel;
import co.foldingmap.Logger;
import co.foldingmap.ResourceHelper;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.ArrayList;
import javax.swing.*;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.StyleConstants;
import javax.swing.text.html.HTML;
import javax.swing.text.html.HTMLDocument;
import javax.swing.text.html.HTMLEditorKit;
/**
*
* @author Alec
*/
public class HtmlTextArea extends JPanel implements ActionListener, KeyListener {
public static int APPLE_COMMAND = 4;
public static int CONTROL = 2;
protected ArrayList<String> includedImages;
protected boolean addingImage, openParagraphTag;
protected ColorChooserPopupDialog colorChooserPopupDialog;
protected Dialog parentWindow;
protected FileChoicePanel fileChoicePanel;
protected HTMLDocument htmlDocument;
protected HTMLEditorKit defaultHTMLEditorKit;
protected HyperlinkPopupDialog hyperlinkPopupDialog;
protected JButton buttonAddImageOk, buttonAddImageCancel;
protected JButton buttonColors, buttonImage, buttonLink;
protected JPanel pannelAddImage, pannelAddImageButtons, panelButtons, panelCenter;
protected JScrollPane mainScroll;
protected JTextPane mainText;
protected JToggleButton buttonBold, buttonItalics, buttonUnderLine;
protected Popup colorPopup, imagePopup, newLinkPopup;
protected PopupFactory mainPopupFactory;
protected SimpleAttributeSet style;
/**
* Constructor for objects of class HtmlTextArea
*/
public HtmlTextArea(Dialog parentWindow) {
init();
this.parentWindow = parentWindow;
this.includedImages = new ArrayList<String>();
this.setLayout(new BorderLayout());
this.add(panelButtons, BorderLayout.NORTH);
this.add(panelCenter, BorderLayout.CENTER);
panelCenter.add(mainScroll, BorderLayout.CENTER);
pannelAddImage.add(fileChoicePanel);
pannelAddImage.add(pannelAddImageButtons);
pannelAddImageButtons.add(buttonAddImageOk);
pannelAddImageButtons.add(buttonAddImageCancel);
panelButtons.add(buttonImage);
panelButtons.add(buttonLink);
panelButtons.add(buttonColors);
panelButtons.add(buttonBold);
panelButtons.add(buttonItalics);
panelButtons.add(buttonUnderLine);
buttonBold.addActionListener(this);
buttonColors.addActionListener(this);
buttonImage.addActionListener(this);
buttonItalics.addActionListener(this);
buttonLink.addActionListener(this);
buttonUnderLine.addActionListener(this);
buttonAddImageOk.addActionListener(this);
buttonAddImageCancel.addActionListener(this);
// buttonBold.setBorder(new MetalBorders.ButtonBorder());
// buttonColors.setBorder(new MetalBorders.ButtonBorder());
// buttonImage.setBorder(new MetalBorders.ButtonBorder());
// buttonItalics.setBorder(new MetalBorders.ButtonBorder());
// buttonLink.setBorder(new MetalBorders.ButtonBorder());
// buttonUnderLine.setBorder(new MetalBorders.ButtonBorder());
buttonBold.setActionCommand("Bold");
buttonColors.setActionCommand("Colors");
buttonImage.setActionCommand("Image");
buttonItalics.setActionCommand("Italics");
buttonLink.setActionCommand("Link");
buttonUnderLine.setActionCommand("Underline");
mainText.addKeyListener(this);
createNewParagraph();
openParagraphTag = true;
}
@Override
public void actionPerformed(ActionEvent ae) {
AbstractButton initiatingAbstractButton;
Object initiatingObject;
String objectText, objectActionCommand;
try {
initiatingObject = ae.getSource();
if (initiatingObject instanceof AbstractButton) {
initiatingAbstractButton = (AbstractButton) initiatingObject;
objectText = initiatingAbstractButton.getText();
objectActionCommand = initiatingAbstractButton.getActionCommand();
} else {
objectText = initiatingObject.toString();
objectActionCommand = ae.getActionCommand();
}
if (objectActionCommand.equals("Bold")) {
changeBold(buttonBold.isSelected());
} else if (initiatingObject == buttonAddImageCancel) {
addImage();
} else if (initiatingObject == buttonAddImageOk) {
addImage(fileChoicePanel.getText());
addImage();
} else if (objectActionCommand.equals("Colors")) {
if (colorChooserPopupDialog == null) {
openColorChooserPopupDialog();
} else {
colorChooserPopupDialog.hideDialog();
colorChooserPopupDialog = null;
}
} else if (objectText.equals("ColorChooserPopupDialog")) {
if (objectActionCommand.equals(ColorChooserPopupDialog.COMMAND_COLOR_SELECTED))
changeColor(colorChooserPopupDialog.getSelectedColor());
colorChooserPopupDialog.hideDialog();
colorChooserPopupDialog = null;
} else if (objectText.equals("HyperlinkPopupDialog")) {
if (objectActionCommand.equals(HyperlinkPopupDialog.COMMAND_OK))
addLink(hyperlinkPopupDialog.getLinkText(), hyperlinkPopupDialog.getLinkURL());
hyperlinkPopupDialog = null;
} else if (objectActionCommand.equals("Image")) {
addImage();
} else if (objectActionCommand.equals("Italics")) {
changeItalics(buttonItalics.isSelected());
} else if (objectActionCommand.equals("Link")) {
if (hyperlinkPopupDialog == null) {
openHyperlinkPopupDialog();
} else {
hyperlinkPopupDialog.hideDialog();
hyperlinkPopupDialog = null;
}
} else if (objectActionCommand.equals("Underline")) {
changeUnderline(buttonUnderLine.isSelected());
}
} catch (Exception e) {
Logger.log(Logger.ERR, "Error in HtmlTextArea.actionPerformed - " + e);
}
}
public void addImage2() {
if (addingImage == false) {
fileChoicePanel.clear();
panelCenter.add(pannelAddImage, BorderLayout.NORTH);
addingImage = true;
} else {
panelCenter.remove(pannelAddImage);
addingImage = false;
}
panelCenter.revalidate();
}
public void addImage(String file) {
int caretPos;
String imageHtml;
try {
caretPos = mainText.getCaretPosition();
imageHtml = "<img src=\"" + "file:" + file + "\" align=\"top\" />";
defaultHTMLEditorKit.insertHTML(htmlDocument, caretPos, imageHtml, 0, 0, HTML.Tag.IMG);
mainText.setStyledDocument(htmlDocument);
} catch (Exception e) {
Logger.log(Logger.ERR, "Error in HtmlTextArea.addImage(String) - " + e);
}
}
public void addImage() {
FileDialog fileDialog;
FileExtensionFilter fileExtensionFilter;
try {
fileDialog = new FileDialog(parentWindow, "Open File", FileDialog.LOAD);
fileExtensionFilter = new FileExtensionFilter();
fileExtensionFilter.addExtension("gif");
fileExtensionFilter.addExtension("jpg");
fileExtensionFilter.addExtension("png");
fileDialog.setFilenameFilter(fileExtensionFilter);
fileDialog.setVisible(true);
String fileName = fileDialog.getDirectory() + fileDialog.getFile();
includedImages.add(fileName);
addImage(fileName);
} catch (Exception e) {
Logger.log(Logger.ERR, "Error in HtmlTextArea.addImage() - " + e);
}
}
public void addLink(String linkText, String linkURL) {
try {
int caretPos = mainText.getCaretPosition();
String linkHtml = "<a href=\"" + linkURL + "\">" + linkText + "</a>";
if ( (!linkText.equals("")) && (linkURL.equals(""))) {
defaultHTMLEditorKit.insertHTML(htmlDocument, caretPos, linkHtml, 0, 0, HTML.Tag.A);
mainText.setStyledDocument(htmlDocument);
}
} catch (Exception e) {
Logger.log(Logger.ERR, "Error in HtmlTextArea.addLink() - " + e);
}
}
public void changeBold(boolean bold) {
if (bold) {
StyleConstants.setBold(style, true);
} else {
StyleConstants.setBold(style, false);
}
mainText.setCharacterAttributes(style, false);
mainText.grabFocus();
}
public void changeColor(Color c) {
StyleConstants.setForeground(style, c);
mainText.setCharacterAttributes(style, false);
buttonColors.setForeground(c);
mainText.grabFocus();
}
public void changeItalics(boolean italic) {
if (italic) {
StyleConstants.setItalic(style, true);
} else {
StyleConstants.setItalic(style, false);
}
mainText.setCharacterAttributes(style, false);
mainText.grabFocus();
}
public void changeUnderline(boolean underline) {
if (underline) {
StyleConstants.setUnderline(style, true);
} else {
StyleConstants.setUnderline(style, false);
}
mainText.setCharacterAttributes(style, false);
mainText.grabFocus();
}
public final void createNewParagraph() {
try {
int caretPos = mainText.getCaretPosition();
String paragraphHtml = "<p>";
defaultHTMLEditorKit.insertHTML(htmlDocument, caretPos, paragraphHtml, 0, 0, HTML.Tag.P);
mainText.setStyledDocument(htmlDocument);
} catch (Exception e) {
Logger.log(Logger.ERR, "Error in HtmlTextArea.keyPressed - " + e);
}
}
public void endParagraph() {
try {
int caretPos = mainText.getCaretPosition();
String paragraphHtml = "</p>";
defaultHTMLEditorKit.insertHTML(htmlDocument, caretPos, paragraphHtml, 0, 0, HTML.Tag.P);
mainText.setStyledDocument(htmlDocument);
} catch (Exception e) {
Logger.log(Logger.ERR, "Error in HtmlTextArea.keyPressed - " + e);
}
}
public String getHtml() {
if (openParagraphTag)
endParagraph();
return mainText.getText();
}
public ArrayList<String> getIncludedImages() {
return includedImages;
}
private void init() {
try {
ResourceHelper resourceHelper = ResourceHelper.getInstance();
addingImage = false;
buttonAddImageCancel = new JButton("Cancel");
buttonAddImageOk = new JButton("Ok");
buttonBold = new JToggleButton(resourceHelper.getImage("text_bold.png"));
buttonColors = new JButton("A");
buttonImage = new JButton(resourceHelper.getImage("image.png"));
buttonItalics = new JToggleButton(resourceHelper.getImage("text_italic.png"));
buttonLink = new JButton(resourceHelper.getImage("link.png"));
buttonUnderLine = new JToggleButton(resourceHelper.getImage("text_underline.png"));
fileChoicePanel = new FileChoicePanel(parentWindow, FileChoicePanel.OPEN);
htmlDocument = new HTMLDocument();
defaultHTMLEditorKit = new HTMLEditorKit();
mainPopupFactory = new PopupFactory();
mainText = new JTextPane();
mainScroll = new JScrollPane(mainText);
pannelAddImage = new JPanel(new GridLayout(2, 1, 2, 2));
pannelAddImageButtons = new JPanel();
panelButtons = new JPanel();
panelCenter = new JPanel(new BorderLayout());
style = new SimpleAttributeSet();
buttonColors.setForeground(Color.BLACK);
buttonColors.setFont(buttonColors.getFont().deriveFont(Font.BOLD));
buttonBold.setMargin( new Insets(4, 4, 4, 4));
buttonColors.setMargin( new Insets(4, 5, 4, 5));
buttonImage.setMargin( new Insets(4, 4, 4, 4));
buttonItalics.setMargin( new Insets(4, 4, 4, 4));
buttonLink.setMargin( new Insets(4, 4, 4, 4));
buttonUnderLine.setMargin(new Insets(4, 4, 4, 4));
buttonColors.setMaximumSize(new Dimension(30, 30));
buttonColors.setPreferredSize(new Dimension(30, 30));
mainText.setStyledDocument(htmlDocument);
mainText.setEditorKit(defaultHTMLEditorKit);
this.setPreferredSize(new Dimension(375, 280));
//this.setBorder(LineBorder.createGrayLineBorder());
} catch (Exception e) {
Logger.log(Logger.ERR, "Error in HTMLTextArea.init - " + e);
}
}
@Override
public void keyPressed(KeyEvent ke) {
try {
//special formating, so when the user presses enter a <br/> tag is inserted.
if (ke.getKeyCode() == KeyEvent.VK_ENTER) {
int caretPos = mainText.getCaretPosition();
String lineBreakHtml = "<br />";
defaultHTMLEditorKit.insertHTML(htmlDocument, caretPos, lineBreakHtml, 0, 0, HTML.Tag.BR);
mainText.setStyledDocument(htmlDocument);
}
} catch (Exception e) {
Logger.log(Logger.ERR, "Error in HtmlTextArea.keyPressed - " + e);
}
}
@Override
public void keyReleased(KeyEvent e) {}
@Override
public void keyTyped(KeyEvent e) {
char keyChar;
int modifiers;
keyChar = e.getKeyChar();
modifiers = e.getModifiers();
if ((modifiers == CONTROL) || (modifiers == APPLE_COMMAND)) {
switch (keyChar) {
case 'c':
mainText.copy();
break;
case 'p':
mainText.paste();
break;
case 'x':
mainText.cut();
break;
}
}
}
public void openColorChooserPopupDialog() {
int x, y;
try {
x = parentWindow.getX() + buttonColors.getX();
y = parentWindow.getY() + (buttonColors.getY() + buttonColors.getHeight() + 125);
colorChooserPopupDialog = new ColorChooserPopupDialog(this);
colorChooserPopupDialog.addActionListener(this);
colorChooserPopupDialog.showColorChooserDialog(x, y);
} catch (Exception e) {
Logger.log(Logger.ERR, "Error in HtmlTextArea.openColorChooserPopupDialog() - " + e);
}
}
public void openHyperlinkPopupDialog() {
int x, y;
try {
x = parentWindow.getX() + buttonLink.getX();
y = parentWindow.getY() + (buttonLink.getY() + buttonLink.getHeight() + 125);
hyperlinkPopupDialog = new HyperlinkPopupDialog(this);
hyperlinkPopupDialog.addActionListener(this);
hyperlinkPopupDialog.showHyperlinkDialog(x, y);
} catch (Exception e) {
Logger.log(Logger.ERR, "Error in HtmlTextArea.openHyperlinkPopupDialog() - " + e);
}
}
@Override
public void paint(Graphics g) {
Container parent;
int height, width, x, y;
x = this.getX();
y = this.getY();
parent = this.getParent();
height = parent.getHeight() - y - 10;
width = parent.getWidth() - 10;
this.setPreferredSize(new Dimension(width, height));
super.paint(g);
}
public void setHtml(String html) {
mainText.setText(html);
openParagraphTag = false;
}
}