001    // This file is part of the Attempto Java Packages.
002    // Copyright 2008-2009, Attempto Group, University of Zurich (see http://attempto.ifi.uzh.ch).
003    //
004    // The Attempto Java Packages is free software: you can redistribute it and/or modify it under the
005    // terms of the GNU Lesser General Public License as published by the Free Software Foundation,
006    // either version 3 of the License, or (at your option) any later version.
007    //
008    // The Attempto Java Packages is distributed in the hope that it will be useful, but WITHOUT ANY
009    // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
010    // PURPOSE. See the GNU Lesser General Public License for more details.
011    //
012    // You should have received a copy of the GNU Lesser General Public License along with the Attempto
013    // Java Packages. If 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.Graphics2D;
019    import java.awt.image.BufferedImage;
020    import java.util.ArrayList;
021    
022    import nextapp.echo2.app.Alignment;
023    import nextapp.echo2.app.Color;
024    import nextapp.echo2.app.Column;
025    import nextapp.echo2.app.Component;
026    import nextapp.echo2.app.Font;
027    import nextapp.echo2.app.Row;
028    import nextapp.echo2.app.event.ActionEvent;
029    import nextapp.echo2.app.event.ActionListener;
030    import nextapp.echo2.app.layout.RowLayoutData;
031    import ch.uzh.ifi.attempto.acewiki.Wiki;
032    import ch.uzh.ifi.attempto.acewiki.core.ontology.Comment;
033    import ch.uzh.ifi.attempto.acewiki.core.ontology.OntologyElement;
034    import ch.uzh.ifi.attempto.acewiki.gui.editor.CommentEditorWindow;
035    import ch.uzh.ifi.attempto.acewiki.gui.editor.SentenceEditorHandler;
036    import ch.uzh.ifi.attempto.acewiki.gui.page.ArticlePage;
037    import ch.uzh.ifi.attempto.acewiki.gui.page.WikiPage;
038    import ch.uzh.ifi.attempto.echocomp.HSpace;
039    import ch.uzh.ifi.attempto.echocomp.MessageWindow;
040    import ch.uzh.ifi.attempto.echocomp.SolidLabel;
041    import ch.uzh.ifi.attempto.echocomp.VSpace;
042    
043    /**
044     * This class represents a comment row that consists of a drop down menu and a comment text.
045     * 
046     * @author Tobias Kuhn
047     */
048    public class CommentRow extends Column implements ActionListener {
049    
050            private static final long serialVersionUID = -540135972060005725L;
051            
052            private static final int COMMENT_TEXT_WIDTH = 800;
053            
054            private static FontMetrics fontMetrics =
055                    ((Graphics2D) new BufferedImage(2, 2, BufferedImage.TYPE_4BYTE_ABGR_PRE)
056                    .createGraphics()).getFontMetrics(new java.awt.Font("Verdana", java.awt.Font.ITALIC, 13));
057            
058            private Comment comment;
059            private Wiki wiki;
060            private WikiPage hostPage;
061            
062            private Row commentRow = new Row();
063            private DropDownMenu dropDown;
064            
065            /**
066             * Creates a new comment row.
067             * 
068             * @param comment The comment to be shown.
069             * @param hostPage The host page of the comment row.
070             */
071            public CommentRow(Comment comment, WikiPage hostPage) {
072                    this.comment = comment;
073                    this.hostPage = hostPage;
074                    this.wiki = hostPage.getWiki();
075                    update();
076            }
077            
078            private void update() {
079                    dropDown = new DropDownMenu("gray", this);
080                    dropDown.addMenuEntry("Edit...");
081                    dropDown.addMenuEntry("Add Sentence...");
082                    dropDown.addMenuEntry("Add Comment...");
083                    dropDown.addMenuEntry("Delete");
084                    RowLayoutData layout = new RowLayoutData();
085                    layout.setAlignment(new Alignment(Alignment.CENTER, Alignment.TOP));
086                    dropDown.setLayoutData(layout);
087                    Column c = new Column();
088                    for (String s : (comment.getText() + " ").split("\\n")) {
089                            int indent = s.replaceFirst("^(\\s*).*$", "$1").length() * 5;
090                            s = s.replaceFirst("^\\s*", "");
091                            if (indent > COMMENT_TEXT_WIDTH/2) indent = COMMENT_TEXT_WIDTH/2;
092                            for (Component comp : wrapText(s, COMMENT_TEXT_WIDTH-indent)) {
093                                    Row r = new Row();
094                                    r.add(new VSpace(17));
095                                    r.add(new HSpace(indent));
096                                    r.add(comp);
097                                    c.add(r);
098                            }
099                    }
100                    
101                    removeAll();
102                    commentRow.removeAll();
103                    commentRow.add(dropDown);
104                    commentRow.add(new HSpace(5));
105                    commentRow.add(c);
106                    commentRow.add(new HSpace(10));
107                    add(commentRow);
108            }
109    
110            public void actionPerformed(ActionEvent e) {
111                    if (e.getActionCommand().equals("Edit...")) {
112                            wiki.log("page", "dropdown: edit comment: " + comment.getText());
113                            wiki.showWindow(new CommentEditorWindow(comment, (ArticlePage) hostPage, true));
114                    } else if (e.getActionCommand().equals("Add Sentence...")) {
115                            wiki.log("page", "dropdown: add sentence");
116                            wiki.showWindow(SentenceEditorHandler.generatePreditorAddWindow(comment, (ArticlePage) hostPage));
117                    } else if (e.getActionCommand().equals("Add Comment...")) {
118                            wiki.log("page", "dropdown: add comment");
119                            wiki.showWindow(new CommentEditorWindow(comment, (ArticlePage) hostPage, false));
120                    } else if (e.getActionCommand().equals("Delete")) {
121                            wiki.log("page", "dropdown: delete sentence: " + comment.getText());
122                            wiki.showWindow(new MessageWindow("Delete", "Do you really want to delete this comment?", null, this, "Yes", "No"));
123                    } else if (e.getSource() instanceof MessageWindow && e.getActionCommand().equals("Yes")) {
124                            wiki.log("page", "dropdown: delete confirmed: " + comment.getText());
125                            comment.getOwner().remove(comment);
126                            wiki.update();
127                            wiki.refresh();
128                    }
129            }
130            
131            private ArrayList<Component> wrapText(String text, int width) {
132                    ArrayList<Component> wrappedText = new ArrayList<Component>();
133                    String line = "";
134                    Row row = new Row();
135                    text = text.replaceAll("~", "~t").replaceAll(" ", " ~b").replaceAll("\\[\\[", "~b[[").replaceAll("\\]\\]", "]]~b").replaceAll("~t", "~");
136                    for (String s : text.split("~b")) {
137                            CommentPart cp = new CommentPart(s);
138                            if (line.length() == 0 || fontMetrics.stringWidth(line + cp.getText()) < width) {
139                                    row.add(cp.getComponent());
140                                    line += cp.getText();
141                                    if (cp.getText().endsWith(" ")) row.add(new HSpace());
142                            } else {
143                                    wrappedText.add(row);
144                                    row = new Row();
145                                    row.add(cp.getComponent());
146                                    line = cp.getText();
147                                    if (cp.getText().endsWith(" ")) row.add(new HSpace());
148                            }
149                    }
150                    if (line.length() > 0) {
151                            wrappedText.add(row);
152                    }
153                    return wrappedText;
154            }
155            
156            
157            private class CommentPart extends Component {
158                    
159                    private static final long serialVersionUID = 8522664422692717971L;
160                    
161                    private Component comp;
162                    private String text;
163                    
164                    public CommentPart(String s) {
165                            if (s.startsWith("http://") || s.startsWith("https://") || s.startsWith("ftp://")) {
166                                    comp = new WebLink(s);
167                                    text = s;
168                            } else if (s.startsWith("[[") && s.endsWith("]]")) {
169                                    String name = s.substring(2, s.length()-2);
170                                    OntologyElement oe = hostPage.getWiki().getOntology().get(name);
171                                    if (oe != null) {
172                                            comp = new WikiLink(oe, hostPage.getWiki());
173                                            text = name;
174                                    }
175                            }
176                            if (comp == null) {
177                                    SolidLabel label = new SolidLabel(s, Font.ITALIC);
178                                    label.setForeground(new Color(170, 170, 170));
179                                    comp = label;
180                                    text = s;
181                            }
182                    }
183                    
184                    public Component getComponent() {
185                            return comp;
186                    }
187                    
188                    public String getText() {
189                            return text;
190                    }
191                    
192            }
193    
194    }