001    // This file is part of AceWiki.
002    // Copyright 2008-2012, AceWiki developers.
003    // 
004    // AceWiki is free software: you can redistribute it and/or modify it under the terms of the GNU
005    // Lesser General Public License as published by the Free Software Foundation, either version 3 of
006    // the License, or (at your option) any later version.
007    // 
008    // AceWiki is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
009    // even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
010    // Lesser General Public License for more details.
011    // 
012    // You should have received a copy of the GNU Lesser General Public License along with AceWiki. If
013    // not, see http://www.gnu.org/licenses/.
014    
015    package ch.uzh.ifi.attempto.acewiki.gui;
016    
017    import java.awt.FontMetrics;
018    import java.awt.image.BufferedImage;
019    import java.util.ArrayList;
020    import java.util.List;
021    
022    import nextapp.echo.app.Alignment;
023    import nextapp.echo.app.Color;
024    import nextapp.echo.app.Column;
025    import nextapp.echo.app.Component;
026    import nextapp.echo.app.Font;
027    import nextapp.echo.app.Row;
028    import nextapp.echo.app.event.ActionEvent;
029    import nextapp.echo.app.event.ActionListener;
030    import nextapp.echo.app.layout.RowLayoutData;
031    import ch.uzh.ifi.attempto.acewiki.Wiki;
032    import ch.uzh.ifi.attempto.acewiki.core.Comment;
033    import ch.uzh.ifi.attempto.acewiki.core.LanguageUtils;
034    import ch.uzh.ifi.attempto.acewiki.core.OntologyElement;
035    import ch.uzh.ifi.attempto.acewiki.core.OntologyTextElement;
036    import ch.uzh.ifi.attempto.base.TextElement;
037    import ch.uzh.ifi.attempto.echocomp.HSpace;
038    import ch.uzh.ifi.attempto.echocomp.MessageWindow;
039    import ch.uzh.ifi.attempto.echocomp.SolidLabel;
040    import ch.uzh.ifi.attempto.echocomp.VSpace;
041    
042    /**
043     * This class represents a comment component consisting of a drop down menu and a comment text.
044     * 
045     * @author Tobias Kuhn
046     */
047    public class CommentComponent extends Column implements ActionListener {
048    
049            private static final long serialVersionUID = -540135972060005725L;
050            
051            private static final int COMMENT_TEXT_WIDTH = 800;
052            
053            private static FontMetrics fontMetrics =
054                    (new BufferedImage(2, 2, BufferedImage.TYPE_4BYTE_ABGR_PRE)
055                    .createGraphics()).getFontMetrics(new java.awt.Font("Verdana", java.awt.Font.ITALIC, 13));
056            
057            private Comment comment;
058            private Wiki wiki;
059            private WikiPage hostPage;
060            
061            private Row commentRow = new Row();
062            private StatementMenu statementMenu;
063            
064            /**
065             * Creates a new comment row.
066             * 
067             * @param comment The comment to be shown.
068             * @param hostPage The host page of the comment row.
069             */
070            public CommentComponent(Comment comment, WikiPage hostPage) {
071                    this.comment = comment;
072                    this.hostPage = hostPage;
073                    this.wiki = hostPage.getWiki();
074                    update();
075            }
076            
077            private void update() {
078                    statementMenu = new StatementMenu(StatementMenu.COMMENT_TYPE, wiki, this);
079                    if (!wiki.isReadOnly()) {
080                            statementMenu.addMenuEntry("Edit...", "Edit this comment");
081                            statementMenu.addMenuEntry("Delete", "Delete this comment from the article");
082                            statementMenu.addMenuSeparator();
083                            statementMenu.addMenuEntry("Add Sentence...", "Add a new sentence here");
084                            statementMenu.addMenuEntry("Add Comment...", "Add a new comment here");
085                    }
086                    RowLayoutData layout = new RowLayoutData();
087                    layout.setAlignment(new Alignment(Alignment.CENTER, Alignment.TOP));
088                    statementMenu.setLayoutData(layout);
089                    Column c = new Column();
090                    for (String s : (comment.getText() + " ").split("\\n")) {
091                            int indent = s.replaceFirst("^(\\s*).*$", "$1").length() * 5;
092                            s = s.replaceFirst("^\\s*", "");
093                            if (indent > COMMENT_TEXT_WIDTH/2) indent = COMMENT_TEXT_WIDTH/2;
094                            for (Component comp : wrapText(s, COMMENT_TEXT_WIDTH-indent)) {
095                                    Row r = new Row();
096                                    r.add(new VSpace(17));
097                                    r.add(new HSpace(indent));
098                                    r.add(comp);
099                                    c.add(r);
100                            }
101                    }
102                    
103                    removeAll();
104                    commentRow.removeAll();
105                    commentRow.add(statementMenu);
106                    commentRow.add(new HSpace(5));
107                    commentRow.add(c);
108                    commentRow.add(new HSpace(10));
109                    add(commentRow);
110            }
111    
112            public void actionPerformed(ActionEvent e) {
113                    if (e.getActionCommand().equals("Edit...")) {
114                            wiki.log("page", "dropdown: edit comment: " + comment.getText());
115                            if (!wiki.isEditable()) {
116                                    wiki.showLoginWindow();
117                            } else {
118                                    wiki.showWindow(CommentEditorHandler.generateEditWindow(
119                                                    comment,
120                                                    (ArticlePage) hostPage
121                                            ));
122                            }
123                    } else if (e.getActionCommand().equals("Add Sentence...")) {
124                            wiki.log("page", "dropdown: add sentence");
125                            if (!wiki.isEditable()) {
126                                    wiki.showLoginWindow();
127                            } else {
128                                    wiki.showWindow(SentenceEditorHandler.generateCreationWindow(
129                                                    comment,
130                                                    (ArticlePage) hostPage
131                                            ));
132                            }
133                    } else if (e.getActionCommand().equals("Add Comment...")) {
134                            wiki.log("page", "dropdown: add comment");
135                            if (!wiki.isEditable()) {
136                                    wiki.showLoginWindow();
137                            } else {
138                                    wiki.showWindow(CommentEditorHandler.generateCreationWindow(
139                                                    comment,
140                                                    (ArticlePage) hostPage
141                                            ));
142                            }
143                    } else if (e.getActionCommand().equals("Delete")) {
144                            wiki.log("page", "dropdown: delete sentence: " + comment.getText());
145                            if (!wiki.isEditable()) {
146                                    wiki.showLoginWindow();
147                            } else {
148                                    wiki.showWindow(new MessageWindow(
149                                                    "Delete",
150                                                    "Do you really want to delete this comment?",
151                                                    null,
152                                                    this,
153                                                    "Yes", "No"
154                                            ));
155                            }
156                    } else if (e.getSource() instanceof MessageWindow && e.getActionCommand().equals("Yes")) {
157                            wiki.log("page", "dropdown: delete confirmed: " + comment.getText());
158                            comment.getArticle().remove(comment);
159                            wiki.update();
160                            wiki.refresh();
161                    }
162            }
163            
164            private List<Component> wrapText(String text, int width) {
165                    List<Component> wrappedText = new ArrayList<Component>();
166                    String line = "";
167                    Row row = new Row();
168                    text = text.replaceAll("~", "~t");
169                    while (text.matches(".*\\[\\[[^\\]]* [^\\]]*\\]\\].*")) {
170                            text = text.replaceAll("\\[\\[([^\\]]*) ([^\\]]*)\\]\\]", "[[$1_$2]]");
171                    }
172                    text = text.replaceAll(" ", " ~b");
173                    text = text.replaceAll("_of\\]\\]", " of]]");
174                    text = text.replaceAll("_by\\]\\]", " by]]");
175                    text = text.replaceAll("\\[\\[", "~b[[");
176                    text = text.replaceAll("\\]\\]", "]]~b");
177                    text = text.replaceAll("~t", "~");
178                    for (String s : text.split("~b")) {
179                            CommentPart cp = new CommentPart(s);
180                            if (line.length() == 0 || fontMetrics.stringWidth(line + cp.getText()) < width) {
181                                    row.add(cp.getComponent());
182                                    line += cp.getText();
183                                    if (cp.getText().endsWith(" ")) row.add(new HSpace());
184                            } else {
185                                    wrappedText.add(row);
186                                    row = new Row();
187                                    row.add(cp.getComponent());
188                                    line = cp.getText();
189                                    if (cp.getText().endsWith(" ")) row.add(new HSpace());
190                            }
191                    }
192                    if (line.length() > 0) {
193                            wrappedText.add(row);
194                    }
195                    return wrappedText;
196            }
197            
198            
199            private class CommentPart extends Component {
200                    
201                    private static final long serialVersionUID = 8522664422692717971L;
202                    
203                    private Component comp;
204                    private String text;
205                    
206                    public CommentPart(String s) {
207                            if (s.startsWith("http://") || s.startsWith("https://") || s.startsWith("ftp://")) {
208                                    comp = new WebLink(s);
209                                    text = s;
210                            } else if (s.startsWith("[[") && s.endsWith("]]")) {
211                                    String name = s.substring(2, s.length()-2);
212                                    Wiki wiki = hostPage.getWiki();
213                                    TextElement te = wiki.getLanguageHandler().getTextOperator().createTextElement(name);
214                                    if (te instanceof OntologyTextElement) {
215                                            OntologyTextElement ote = (OntologyTextElement) te;
216                                            OntologyElement oe = ote.getOntologyElement();
217                                            String t = LanguageUtils.getPrettyPrinted(oe.getWord(ote.getWordNumber()));
218                                            comp = new WikiLink(oe, t, wiki, false);
219                                            text = name;
220                                    }
221                            }
222                            if (comp == null) {
223                                    SolidLabel label = new SolidLabel(s, Font.ITALIC);
224                                    label.setForeground(new Color(120, 120, 120));
225                                    comp = label;
226                                    text = s;
227                            }
228                    }
229                    
230                    public Component getComponent() {
231                            return comp;
232                    }
233                    
234                    public String getText() {
235                            return text;
236                    }
237                    
238            }
239    
240    }