001/* An attribute that creates an editor pane to configure its container. 002 003 Copyright (c) 1998-2018 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.actor.gui; 029 030import java.awt.Color; 031import java.awt.Component; 032import java.util.LinkedList; 033import java.util.List; 034import java.util.Set; 035 036import javax.swing.JLabel; 037import javax.swing.JTabbedPane; 038 039import ptolemy.kernel.util.Attribute; 040import ptolemy.kernel.util.Decorator; 041import ptolemy.kernel.util.DecoratorAttributes; 042import ptolemy.kernel.util.IllegalActionException; 043import ptolemy.kernel.util.NameDuplicationException; 044import ptolemy.kernel.util.NamedObj; 045import ptolemy.kernel.util.Settable; 046import ptolemy.util.MessageHandler; 047 048/////////////////////////////////////////////////////////////////// 049//// EditorPaneFactory 050 051/** 052 This is an attribute that can create a pane (called a "configuration 053 widget") for interactively configuring its container. To use this, 054 place an instance of this class (or a derived class) inside a Ptolemy II 055 object. When the user double clicks on the icon for that object, 056 or selects Configure from the context menu, then a dialog is opened 057 containing the pane returned by createEditorPane(). 058 <p> 059 In this base class, the createEditorPane() method creates an 060 instance of PtolemyQuery with one entry for each parameter in 061 the container. This is the default mechanism 062 for editing parameters. Derived classes may override this 063 method to present radically different interfaces to the user. 064 For example, a digital filter actor could present a filter 065 design interface. A plotter actor could present a panel for 066 configuring a plot. A file reader actor could present a file 067 browser. 068 069 @see Configurer 070 @author Steve Neuendorffer and Edward A. Lee 071 @version $Id$ 072 @since Ptolemy II 0.4 073 @Pt.ProposedRating Red (eal) 074 @Pt.AcceptedRating Red (johnr) 075 */ 076public class EditorPaneFactory extends Attribute { 077 /** Construct a factory with the specified container and name. 078 * @param container The container. 079 * @param name The name of the factory. 080 * @exception IllegalActionException If the factory is not of an 081 * acceptable attribute for the container. 082 * @exception NameDuplicationException If the name coincides with 083 * an attribute already in the container. 084 */ 085 public EditorPaneFactory(NamedObj container, String name) 086 throws IllegalActionException, NameDuplicationException { 087 super(container, name); 088 } 089 090 /////////////////////////////////////////////////////////////////// 091 //// public methods //// 092 093 /** Return a new widget for configuring the container. In this 094 * base class, this method defers to the static createEditorPane method. 095 * Subclasses that implement specialized interaction should override 096 * this method to create an appropriate type of component. 097 * @return A new widget for configuring the container. 098 */ 099 public Component createEditorPane() { 100 return createEditorPane(getContainer()); 101 } 102 103 /** Return a new default widget for configuring the specified object. 104 * This is used by the Configurer for objects that do not contain 105 * an instance of EditorPaneFactory as an attribute. The resulting 106 * component is an instance of the PtolemyQuery class that can be 107 * used to edit the parameters of the object. 108 * @param object The object to be configured. 109 * @return An instance of the PtolemyQuery class that is created 110 * with styles according to the type given in each visible attribute. 111 */ 112 public static Component createEditorPane(NamedObj object) { 113 // If there are decorators for the specified object, then we 114 // want to return a JTabbedPane with one tab for the parameters 115 // of the object, and one tab for parameters provided by each 116 // decorator. If there are no decorators, we can simply return 117 // a PtolemyQuery for the specified object. 118 JTabbedPane tabs = null; 119 try { 120 Set<Decorator> decorators = object.decorators(); 121 for (Decorator decorator : decorators) { 122 DecoratorAttributes decoratorAttributes = object 123 .getDecoratorAttributes(decorator); 124 125 if (decoratorAttributes != null) { 126 decoratorAttributes.updateContent(); 127 PtolemyQuery decoratorQuery = new PtolemyQuery(object); 128 decoratorQuery.setAlignmentY(Component.TOP_ALIGNMENT); 129 decoratorQuery.setTextWidth(DEFAULT_QUERY_WIDTH); 130 decoratorQuery 131 .addText( 132 "Decorator providing the parameters below: " 133 + decorator.getFullName(), 134 Color.BLACK, 0); 135 boolean foundDecoratorAttribute = false; 136 137 for (Object attribute : decoratorAttributes 138 .attributeList()) { 139 if (attribute instanceof Settable) { 140 Settable settable = (Settable) attribute; 141 if (Configurer.isVisible(object, settable)) { 142 foundDecoratorAttribute = true; 143 decoratorQuery.addStyledEntry(settable); 144 145 } 146 } 147 } 148 if (foundDecoratorAttribute) { 149 if (tabs == null) { 150 tabs = new JTabbedPane(); 151 Component mainTab = createEditorPane(object, 152 new PtolemyQuery(object)); 153 tabs.addTab(object.getDisplayName(), mainTab); 154 } 155 tabs.addTab(decorator.getName(), decoratorQuery); 156 } 157 } 158 } 159 } catch (IllegalActionException e) { 160 MessageHandler.error("Invalid decorator value", e); 161 } 162 163 if (tabs == null) { 164 // No decorators. 165 PtolemyQuery query = new PtolemyQuery(object); 166 query.setTextWidth(DEFAULT_QUERY_WIDTH); 167 return createEditorPane(object, query); 168 } else { 169 return tabs; 170 } 171 } 172 173 /** Return a new default widget for configuring the specified object. 174 * This is used by the Configurer for objects that do not contain 175 * an instance of EditorPaneFactory as an attribute. The resulting 176 * component is an instance of the PtolemyQuery class that 177 * @param object The object to be configured. 178 * @param query The query to which new entries for the object are to be 179 * added. 180 * @return An instance of the PtolemyQuery class that is created 181 * with styles according to the type given in each visible attribute. 182 */ 183 public static Component createEditorPane(NamedObj object, 184 PtolemyQuery query) { 185 query.setTextWidth(DEFAULT_QUERY_WIDTH); 186 boolean foundOne = false; 187 List<Settable> parameters = new LinkedList<Settable>( 188 object.attributeList(Settable.class)); 189 190 for (Settable parameter : parameters) { 191 if (Configurer.isVisible(object, parameter)) { 192 foundOne = true; 193 query.addStyledEntry(parameter); 194 } 195 } 196 197 if (!foundOne) { 198 return new JLabel(object.getName() + " has no parameters."); 199 } 200 201 return query; 202 } 203 204 /** Default width for a query. */ 205 public static int DEFAULT_QUERY_WIDTH = 40; 206}