// This file is part of AceWiki. // Copyright 2008-2013, AceWiki developers. // // AceWiki is free software: you can redistribute it and/or modify it under the terms of the GNU // Lesser General Public License as published by the Free Software Foundation, either version 3 of // the License, or (at your option) any later version. // // AceWiki 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 // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License along with AceWiki. If // not, see http://www.gnu.org/licenses/. package ch.uzh.ifi.attempto.acewiki.gui; import java.awt.FontMetrics; import java.awt.image.BufferedImage; import java.util.ArrayList; import java.util.List; import nextapp.echo.app.Alignment; import nextapp.echo.app.Color; import nextapp.echo.app.Column; import nextapp.echo.app.Component; import nextapp.echo.app.Font; import nextapp.echo.app.Row; import nextapp.echo.app.event.ActionEvent; import nextapp.echo.app.event.ActionListener; import nextapp.echo.app.layout.RowLayoutData; import ch.uzh.ifi.attempto.acewiki.Wiki; import ch.uzh.ifi.attempto.acewiki.core.Comment; import ch.uzh.ifi.attempto.acewiki.core.LanguageUtils; import ch.uzh.ifi.attempto.acewiki.core.OntologyElement; import ch.uzh.ifi.attempto.acewiki.core.OntologyTextElement; import ch.uzh.ifi.attempto.acewiki.core.ModuleElement; import ch.uzh.ifi.attempto.base.TextElement; import ch.uzh.ifi.attempto.echocomp.HSpace; import ch.uzh.ifi.attempto.echocomp.MessageWindow; import ch.uzh.ifi.attempto.echocomp.SolidLabel; import ch.uzh.ifi.attempto.echocomp.VSpace; /** * This class represents a comment component consisting of a drop down menu and a comment text. * * @author Tobias Kuhn */ public class CommentComponent extends Column implements ActionListener { private static final long serialVersionUID = -540135972060005725L; private static final int COMMENT_TEXT_WIDTH = 800; private static FontMetrics fontMetrics = (new BufferedImage(2, 2, BufferedImage.TYPE_4BYTE_ABGR_PRE) .createGraphics()).getFontMetrics(new java.awt.Font("Verdana", java.awt.Font.ITALIC, 13)); private Comment comment; private Wiki wiki; private WikiPage hostPage; private Row commentRow = new Row(); private StatementMenu statementMenu; /** * Creates a new comment row. * * @param comment The comment to be shown. * @param hostPage The host page of the comment row. */ public CommentComponent(Comment comment, WikiPage hostPage) { this.comment = comment; this.hostPage = hostPage; this.wiki = hostPage.getWiki(); update(); } private void update() { statementMenu = new StatementMenu(StatementMenu.COMMENT_TYPE, wiki, this); if (!wiki.getConfig().isReadOnly()) { if (wiki.getConfig().isCommentingEnabled()) { statementMenu.addMenuEntry("acewiki_statementmenu_edit", "acewiki_statementmenu_editcommtooltip"); statementMenu.addMenuEntry("acewiki_statementmenu_delete", "acewiki_statementmenu_delcommtooltip"); statementMenu.addMenuSeparator(); } statementMenu.addMenuEntry("acewiki_statementmenu_addsent", "acewiki_statementmenu_addsenttooltip"); if (wiki.getConfig().isCommentingEnabled()) { statementMenu.addMenuEntry("acewiki_statementmenu_addcomm", "acewiki_statementmenu_addcommtooltip"); } } RowLayoutData layout = new RowLayoutData(); layout.setAlignment(new Alignment(Alignment.CENTER, Alignment.TOP)); statementMenu.setLayoutData(layout); Column c = new Column(); for (String s : (comment.getText() + " ").split("\\n")) { int indent = s.replaceFirst("^(\\s*).*$", "$1").length() * 5; s = s.replaceFirst("^\\s*", ""); if (indent > COMMENT_TEXT_WIDTH/2) indent = COMMENT_TEXT_WIDTH/2; for (Component comp : wrapText(s, COMMENT_TEXT_WIDTH-indent)) { Row r = new Row(); r.add(new VSpace(17)); r.add(new HSpace(indent)); r.add(comp); c.add(r); } } removeAll(); commentRow.removeAll(); commentRow.add(statementMenu); commentRow.add(new HSpace(5)); commentRow.add(c); commentRow.add(new HSpace(10)); add(commentRow); } public void actionPerformed(ActionEvent e) { if (e.getActionCommand().equals("acewiki_statementmenu_edit")) { wiki.log("page", "dropdown: edit comment: " + comment.getText()); if (!wiki.isEditable()) { wiki.showLoginWindow(); } else { wiki.showWindow(CommentEditorHandler.generateEditWindow( comment, (ArticlePage) hostPage )); } } else if (e.getActionCommand().equals("acewiki_statementmenu_addsent")) { wiki.log("page", "dropdown: add sentence"); if (!wiki.isEditable()) { wiki.showLoginWindow(); } else { wiki.showWindow(SentenceEditorHandler.generateCreationWindow( comment, (ArticlePage) hostPage )); } } else if (e.getActionCommand().equals("acewiki_statementmenu_addcomm")) { wiki.log("page", "dropdown: add comment"); if (!wiki.isEditable()) { wiki.showLoginWindow(); } else { wiki.showWindow(CommentEditorHandler.generateCreationWindow( comment, (ArticlePage) hostPage )); } } else if (e.getActionCommand().equals("acewiki_statementmenu_delete")) { wiki.log("page", "dropdown: delete comment: " + comment.getText()); if (!wiki.isEditable()) { wiki.showLoginWindow(); } else { wiki.showWindow(new MessageWindow( "acewiki_message_delstatementtitle", "acewiki_message_delcomment", null, this, "general_action_yes", "general_action_no" )); } } else if (e.getSource() instanceof MessageWindow && e.getActionCommand().equals("general_action_yes")) { wiki.log("page", "dropdown: delete confirmed: " + comment.getText()); comment.getArticle().remove(comment); wiki.update(); wiki.refresh(); } } // TODO: this is very ACE specific private List<Component> wrapText(String text, int width) { List<Component> wrappedText = new ArrayList<Component>(); String line = ""; Row row = new Row(); text = text.replaceAll("~", "~t"); while (text.matches(".*\\[\\[[^\\]]* [^\\]]*\\]\\].*")) { text = text.replaceAll("\\[\\[([^\\]]*) ([^\\]]*)\\]\\]", "[[$1_$2]]"); } text = text.replaceAll(" ", " ~b"); text = text.replaceAll("_of\\]\\]", " of]]"); text = text.replaceAll("_by\\]\\]", " by]]"); text = text.replaceAll("\\[\\[", "~b[["); text = text.replaceAll("\\]\\]", "]]~b"); text = text.replaceAll("~t", "~"); for (String s : text.split("~b")) { CommentPart cp = new CommentPart(s); if (line.length() == 0 || fontMetrics.stringWidth(line + cp.getText()) < width) { row.add(cp.getComponent()); line += cp.getText(); if (cp.getText().endsWith(" ")) row.add(new HSpace()); } else { wrappedText.add(row); row = new Row(); row.add(cp.getComponent()); line = cp.getText(); if (cp.getText().endsWith(" ")) row.add(new HSpace()); } } if (line.length() > 0) { wrappedText.add(row); } return wrappedText; } private class CommentPart extends Component { private static final long serialVersionUID = 8522664422692717971L; private Component comp; private String text; public CommentPart(String s) { if (s.startsWith("http://") || s.startsWith("https://") || s.startsWith("ftp://")) { comp = new WebLink(s); text = s; } else if (s.startsWith("[[") && s.endsWith("]]")) { String name = s.substring(2, s.length()-2); Wiki wiki = hostPage.getWiki(); TextElement te = wiki.getLanguageHandler().getTextOperator().createTextElement(name); if (te instanceof OntologyTextElement) { OntologyTextElement ote = (OntologyTextElement) te; OntologyElement oe = ote.getOntologyElement(); if (wiki.getConfig().isGrammarIntegrationEnabled() || !(oe instanceof ModuleElement)) { String t = LanguageUtils.getPrettyPrinted(oe.getWord(ote.getWordNumber())); comp = new WikiLink(oe, t, wiki, false); text = name; } } } if (comp == null) { SolidLabel label = new SolidLabel(s, Font.ITALIC); label.setForeground(new Color(120, 120, 120)); comp = label; text = s; } } public Component getComponent() { return comp; } public String getText() { return text; } } }