001/* An action for editing documentation.
002
003 Copyright (c) 2006-2014 The Regents of the University of California.
004 All rights reserved.
005 Permission is hereby granted, without written agreement and without
006 license or royalty fees, to use, copy, modify, and distribute this
007 software and its documentation for any purpose, provided that the above
008 copyright notice and the following two paragraphs appear in all copies
009 of this software.
010
011 IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY
012 FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
013 ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
014 THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
015 SUCH DAMAGE.
016
017 THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
018 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
019 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
020 PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
021 CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
022 ENHANCEMENTS, OR MODIFICATIONS.
023
024 PT_COPYRIGHT_VERSION_2
025 COPYRIGHTENDKEY
026
027 */
028package ptolemy.vergil.basic;
029
030import java.awt.Frame;
031import java.awt.event.ActionEvent;
032import java.util.Iterator;
033import java.util.List;
034
035import ptolemy.actor.gui.Configuration;
036import ptolemy.actor.gui.EditParametersDialog;
037import ptolemy.data.expr.Parameter;
038import ptolemy.kernel.util.Attribute;
039import ptolemy.kernel.util.ChangeRequest;
040import ptolemy.kernel.util.IllegalActionException;
041import ptolemy.kernel.util.InternalErrorException;
042import ptolemy.kernel.util.NamedObj;
043import ptolemy.moml.MoMLChangeRequest;
044import ptolemy.vergil.actor.DocApplicationSpecializer;
045import ptolemy.vergil.toolbox.FigureAction;
046
047///////////////////////////////////////////////////////////////////
048//// CustomizeDocumentationAction
049
050/**
051 An action for editing instance-specific documentation.
052
053 @author Edward A. Lee
054 @version $Id$
055 @since Ptolemy II 5.2
056 @Pt.ProposedRating Red (eal)
057 @Pt.AcceptedRating Red (johnr)
058 */
059@SuppressWarnings("serial")
060public class CustomizeDocumentationAction extends FigureAction {
061
062    /** Construct an instance of this action. */
063    public CustomizeDocumentationAction() {
064        super("Customize Documentation");
065    }
066
067    ///////////////////////////////////////////////////////////////////
068    ////                         public methods                    ////
069
070    /** Perform the action by first ensuring that the target has an
071     *  instance of DocAttribute, and then opening an edit parameters
072     *  dialog on that attribute.
073     */
074    @Override
075    public void actionPerformed(ActionEvent e) {
076        super.actionPerformed(e);
077        final NamedObj target = getTarget();
078        boolean done = false;
079        // If the object does not contain an attribute of class
080        // DocAttribute, then create one.  Then open a dialog to edit
081        // the parameters of the first such encountered attribute.
082        List docAttributeList = null;
083
084        if (target != null) {
085            Parameter docApplicationSpecializerParameter = null;
086            try {
087                //find the configuration
088                List configsList = Configuration.configurations();
089                Configuration config = null;
090                for (Iterator it = configsList.iterator(); it.hasNext();) {
091                    config = (Configuration) it.next();
092                    if (config != null) {
093                        break;
094                    }
095                }
096                if (config == null) {
097                    throw new InternalErrorException(target, null,
098                            "Failed to find configuration");
099                }
100
101                // Check to see if the configuration has a
102                // _docApplicationSpecializer parameter and if it does,
103                // let it handle the customization
104
105                docApplicationSpecializerParameter = (Parameter) config
106                        .getAttribute("_docApplicationSpecializer",
107                                Parameter.class);
108            } catch (IllegalActionException iae) {
109                // Ignore.  just let the default action happen
110                System.out.println("Error getting the documentation "
111                        + "specializer: " + iae.getMessage());
112            }
113
114            if (docApplicationSpecializerParameter != null) {
115                // If there is a docApplicationSpecializer, use it to
116                // customize the documentation since it knows about
117                // the special doc attribute
118
119                String docApplicationSpecializerClassName = docApplicationSpecializerParameter
120                        .getExpression();
121                try {
122                    Class docApplicationSpecializerClass = Class
123                            .forName(docApplicationSpecializerClassName);
124                    final DocApplicationSpecializer docApplicationSpecializer = (DocApplicationSpecializer) docApplicationSpecializerClass
125                            .newInstance();
126                    String docAttributeClassName = docApplicationSpecializer
127                            .getDocumentationAttributeClassName();
128                    Class docAttributeClass = Class
129                            .forName(docAttributeClassName);
130                    if (docApplicationSpecializerClass != null
131                            && docAttributeClass != null) {
132                        docAttributeList = target
133                                .attributeList(docAttributeClass);
134                    }
135
136                    if (docAttributeList.size() == 0) {
137                        docApplicationSpecializer
138                                .handleDocumentationAttributeDoesNotExist(
139                                        getFrame(), target);
140
141                    } else { //edit the existing attribute
142                        final Attribute docAttribute = (Attribute) docAttributeList
143                                .get(docAttributeList.size() - 1);
144                        ChangeRequest request = new ChangeRequest(this,
145                                "Customize documentation.") {
146                            @Override
147                            protected void _execute() throws Exception {
148                                //_editDocAttribute(getFrame(), docAttribute, target);
149                                docApplicationSpecializer.editDocumentation(
150                                        getFrame(), docAttribute, target);
151                            }
152                        };
153                        target.requestChange(request);
154                    }
155                } catch (Throwable throwable) {
156                    System.out.println(
157                            "Failed to call doc application specializer "
158                                    + "class \""
159                                    + docApplicationSpecializerClassName
160                                    + "\" on class \""
161                                    + docApplicationSpecializerClassName
162                                    + "\".");
163                }
164                done = true;
165            }
166
167            if (!done) {
168                //assign the docAttributeList the default DocAttribute if it
169                //wasn't assigned by the specializer
170                docAttributeList = target.attributeList(DocAttribute.class);
171                if (docAttributeList.size() == 0) {
172                    // Create a doc attribute, then edit its parameters.
173                    String moml = "<property name=\"" + "DocAttribute"
174                            + "\" class=\"ptolemy.vergil.basic.DocAttribute\"/>";
175                    MoMLChangeRequest request = new MoMLChangeRequest(this,
176                            target, moml) {
177                        @Override
178                        protected void _execute() throws Exception {
179                            super._execute();
180                            List docAttributes = target
181                                    .attributeList(DocAttribute.class);
182
183                            // There shouldn't be more than one of
184                            // these, but if there are, the new one is
185                            // the last one.
186
187                            DocAttribute attribute = (DocAttribute) docAttributes
188                                    .get(docAttributes.size() - 1);
189                            _editDocAttribute(getFrame(), attribute, target);
190                        }
191                    };
192                    target.requestChange(request);
193                } else {
194
195                    // In case there is more than one such attribute,
196                    // get the last one.
197
198                    final DocAttribute attribute = (DocAttribute) docAttributeList
199                            .get(docAttributeList.size() - 1);
200
201                    // Do the update in a change request because it may
202                    // modify the DocAttribute parameter.
203
204                    ChangeRequest request = new ChangeRequest(this,
205                            "Customize documentation.") {
206                        @Override
207                        protected void _execute() throws Exception {
208
209                            // In case parameters or ports have been
210                            // added since the DocAttribute was
211                            // constructed, refresh it.
212
213                            attribute.refreshParametersAndPorts();
214                            _editDocAttribute(getFrame(), attribute, target);
215                        }
216                    };
217                    target.requestChange(request);
218                }
219            }
220        }
221    }
222
223    ///////////////////////////////////////////////////////////////////
224    ////                         private methods                   ////
225
226    /** Edit the specified documentation attribute.
227     *  @param owner The owning frame.
228     *  @param attribute The attribute to edit.
229     *  @param target The target whose documentation is being edited.
230     */
231    private void _editDocAttribute(Frame owner, DocAttribute attribute,
232            NamedObj target) {
233        new EditParametersDialog(owner, attribute,
234                "Edit Documentation for " + target.getName());
235    }
236}