001/* 002 * Copyright (c) 2004-2007 by Michael Connor. All Rights Reserved. 003 * 004 * Redistribution and use in source and binary forms, with or without 005 * modification, are permitted provided that the following conditions are met: 006 * 007 * o Redistributions of source code must retain the above copyright notice, 008 * this list of conditions and the following disclaimer. 009 * 010 * o Redistributions in binary form must reproduce the above copyright notice, 011 * this list of conditions and the following disclaimer in the documentation 012 * and/or other materials provided with the distribution. 013 * 014 * o Neither the name of FormLayoutBuilder or Michael Connor nor the names of 015 * its contributors may be used to endorse or promote products derived 016 * from this software without specific prior written permission. 017 * 018 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 019 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 020 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 021 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 022 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 023 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 024 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 025 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 026 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 027 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 028 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 029 */ 030/* 031 * NewComponentDialog.java 032 * 033 * Created on March 24, 2005, 6:49 PM 034 */ 035 036package org.mlc.swing.layout; 037 038import java.awt.Component; 039import java.awt.Window; 040import java.awt.event.ActionEvent; 041import java.awt.event.ActionListener; 042 043import javax.swing.JButton; 044import javax.swing.JDialog; 045import javax.swing.JFrame; 046import javax.swing.JLabel; 047import javax.swing.JPanel; 048import javax.swing.JScrollPane; 049import javax.swing.JTextArea; 050import javax.swing.JTextField; 051import javax.swing.WindowConstants; 052 053import com.jgoodies.forms.factories.Borders; 054import com.jgoodies.forms.factories.ButtonBarFactory; 055 056import bsh.Interpreter; 057 058/** 059 * When performing drag-and-drop from the component palette to the table, 060 * this class is used to define or edit a component's settings. These 061 * settings include the import, declaration, configuration lines which 062 * will be used to generate the code for the component. The same settings 063 * are used to create a 'preview' component to be shown in the preview 064 * window. 065 * 066 * @author Michael Connor 067@version $Id$ 068@since Ptolemy II 8.0 069 */ 070@SuppressWarnings("serial") 071public class NewComponentDialog extends JPanel { 072 JLabel componentNameLabel = new JLabel("Name"); 073 JTextField componentNameTextField = new JTextField(); 074 075 JLabel importsLabel = new JLabel("Imports"); 076 JTextArea importsComponent = createTextArea(3, 40); 077 078 JLabel declarationsLabel = new JLabel("Declarations"); 079 JTextArea declarationsComponent = createTextArea(3, 40); 080 081 JLabel configureLabel = new JLabel("Configure"); 082 JTextArea configureComponent = createTextArea(4, 40); 083 084 JLabel addToContainerLabel = new JLabel("Add"); 085 JTextArea addToContainerComponent = createTextArea(3, 40); 086 087 JLabel removeFromContainerLabel = new JLabel("Remove"); 088 JTextArea removeFromContainerComponent = createTextArea(2, 40); 089 090 JLabel previewLabel = new JLabel("Preview"); 091 JScrollPane previewComponent = new JScrollPane(); 092 093 JButton prevButton = new JButton("Preview"); 094 JButton okButton = new JButton("OK"); 095 JButton cancelButton = new JButton("Cancel"); 096 Component buttonBar = ButtonBarFactory.buildRightAlignedBar( 097 new JButton[] { prevButton, okButton, cancelButton }); 098 099 ComponentDef componentDef; 100 private String preview; 101 Window myOwner; 102 private boolean success = false; 103 104 public boolean succeeded() { 105 return success; 106 } 107 108 /** Creates a new instance of NewComponentDialog */ 109 public NewComponentDialog(Window owner) { 110 myOwner = owner; 111 LayoutConstraintsManager layoutConstraintsManager = LayoutConstraintsManager 112 .getLayoutConstraintsManager(this.getClass() 113 .getResourceAsStream("editableLayoutConstraints.xml")); 114 115 this.setBorder(Borders.DIALOG_BORDER); 116 117 layoutConstraintsManager.setLayout("newComponentPanel", this); 118 119 // here we add the controls to the container. you may 120 // need to change the name of panel 121 add(new JScrollPane(removeFromContainerComponent), 122 "removeFromContainerComponent"); 123 124 add(configureLabel, "configureLabel"); 125 add(new JScrollPane(importsComponent), "importsComponent"); 126 add(new JScrollPane(declarationsComponent), "declarationsComponent"); 127 add(new JScrollPane(configureComponent), "configureComponent"); 128 add(new JScrollPane(addToContainerComponent), 129 "addToContainerComponent"); 130 add(buttonBar, "buttonBar"); 131 add(declarationsLabel, "declarationsLabel"); 132 add(componentNameLabel, "componentNameLabel"); 133 add(importsLabel, "importsLabel"); 134 add(addToContainerLabel, "addToContainerLabel"); 135 add(componentNameTextField, "componentNameTextField"); 136 add(removeFromContainerLabel, "removeFromContainerLabel"); 137 138 add(previewLabel, "previewLabel"); 139 add(previewComponent, "previewComponent"); 140 141 prevButton.addActionListener(new ActionListener() { 142 @Override 143 public void actionPerformed(ActionEvent e) { 144 doPreview(); 145 } 146 }); 147 okButton.addActionListener(new ActionListener() { 148 @Override 149 public void actionPerformed(ActionEvent e) { 150 success = true; 151 componentDef.add = getAdd(); 152 componentDef.configure = getConfiguration(); 153 componentDef.declarations = getDeclarations(); 154 componentDef.name = componentNameTextField.getText().trim(); 155 componentDef.imports = getImports(); 156 UserPrefs.getPrefs().saveWinLoc("newcomp", myOwner); 157 myOwner.setVisible(false); 158 } 159 }); 160 cancelButton.addActionListener(new ActionListener() { 161 @Override 162 public void actionPerformed(ActionEvent e) { 163 success = false; 164 UserPrefs.getPrefs().saveWinLoc("newcomp", myOwner); 165 myOwner.setVisible(false); 166 } 167 }); 168 } 169 170 // class PreviewThread implements Runnable { 171 // 172 // boolean running = true; 173 // 174 // public void run() { 175 // while (running) { 176 // } 177 // } 178 // } 179 180 /** 181 Get an instance of the specified component. In FormLayoutMaker, 182 this instance is placed in the preview panel. 183 <p> 184 For example, if the component is a JButton, this method is the 185 equivalent of <code>new JButton(<i>text</i>)</code>. 186 187 @return Component An instance of the component, null if there 188 is a problem in the specification. [It is recommended that the 189 'Preview' button should be clicked before exiting the dialog.] 190 */ 191 public Component getInstance() { 192 Component component = null; 193 String script; 194 if (preview == null || preview.length() == 0) { 195 script = getImports() + "\n" + getDeclarations() + "\n" 196 + getConfiguration(); 197 } else { 198 script = preview.trim(); 199 } 200 String componentName = componentNameTextField.getText(); 201 script = script.replaceAll("\\$\\{name\\}", componentName); 202 203 Interpreter interpreter = new Interpreter(); 204 interpreter.setStrictJava(true); 205 206 JPanel temporaryContainer = null; 207 try { 208 209 interpreter.set("container", temporaryContainer); 210 interpreter.eval(script); 211 component = (Component) interpreter.get(componentName); 212 213 } catch (bsh.EvalError error) { 214 System.out.println(error); 215 } 216 return component; 217 } 218 219 private void doPreview() { 220 Component component = getInstance(); 221 if (component == null) { 222 return; 223 } 224 JPanel temporaryContainer = new JPanel(); 225 temporaryContainer.add(component); 226 if (temporaryContainer != null) { 227 previewComponent.setViewportView(temporaryContainer); 228 } 229 } 230 231 /** Get the component's name */ 232 public String getComponentName() { 233 return componentNameTextField.getText(); 234 } 235 236 public void setComponentName(String componentName) { 237 componentNameTextField.setText(componentName); 238 } 239 240 /** Get the component's <imports> section. */ 241 public String getImports() { 242 return importsComponent.getText().trim(); 243 } 244 245 /** Get the component's <declarations> section. */ 246 public String getDeclarations() { 247 return declarationsComponent.getText().trim(); 248 } 249 250 /** Get the component's <configuration> section. */ 251 public String getConfiguration() { 252 return configureComponent.getText().trim(); 253 } 254 255 public String getAdd() { 256 String res = addToContainerComponent.getText(); 257 return cleanString(res); 258 } 259 260 public void setRemove(String remove) { 261 removeFromContainerComponent.setText(remove); 262 } 263 264 public void setComponentDef(ComponentDef componentDef) { 265 editComponentDef(componentDef.clone()); 266 } 267 268 public void editComponentDef(ComponentDef componentDef) { 269 this.componentDef = componentDef; 270 271 importsComponent.setText(cleanString(componentDef.imports)); 272 declarationsComponent.setText(cleanString(componentDef.declarations)); 273 configureComponent.setText(cleanString(componentDef.configure)); 274 addToContainerComponent.setText(cleanString(componentDef.add)); 275 removeFromContainerComponent.setText(cleanString(componentDef.remove)); 276 preview = cleanString(componentDef.preview); 277 } 278 279 /** Cleans a string. Removes extra newlines. 280 * 281 * @param instr 282 * @return A clean string. 283 */ 284 private String cleanString(String instr) { 285 if (instr == null) { 286 return instr; 287 } 288 289 // Java 1.5 library method 290 // while ( res.contains("\n\n") ) 291 // KBR 09/05/05 Reworked to deal with leading space for multiline 292 // sections. 293 String[] outstrs = instr.split("\n"); 294 String outstr = ""; 295 for (String outstr2 : outstrs) { 296 String tmp = outstr2.trim(); 297 outstr += tmp + (tmp.length() > 0 ? "\n" : ""); 298 } 299 return outstr; 300 } 301 302 private static JTextArea createTextArea(int rows, int cols) { 303 JTextArea textArea = new JTextArea(rows, cols); 304 //KBR linewrap makes longer sections hard to work with 305 // textArea.setWrapStyleWord(true); 306 // textArea.setLineWrap(true); 307 return textArea; 308 } 309 310 /** 311 * Creates and displays a dialog for editing a component's settings. See 312 * {@link #doDialog(JFrame,ComponentDef)} for an example. 313 */ 314 public static NewComponentDialog editDialog(JFrame owner, 315 ComponentDef componentDef) { 316 JDialog dlg = new JDialog(owner, "Edit Component", true); 317 UserPrefs.getPrefs().useSavedBounds("newcomp", dlg); 318 dlg.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); 319 NewComponentDialog panel = new NewComponentDialog(dlg); 320 panel.editComponentDef(componentDef); 321 panel.setComponentName(componentDef.name); 322 dlg.getContentPane().add(panel); 323 dlg.pack(); 324 dlg.setVisible(true); 325 return panel; 326 } 327 328 /** 329 * Creates and displays a dialog for defining a new component's settings. The 330 * dialog should be used as follows: 331 * <code> 332 * NewComponentDialog dlg = NewComponentDialog.doDialog(frame, componentDef); 333 * if (dlg.succeeded()) { 334 * [do something with dlg.componentDef] 335 * } 336 * </code> 337 */ 338 public static NewComponentDialog doDialog(JFrame owner, 339 ComponentDef componentDef) { 340 JDialog dlg = new JDialog(owner, "New Component", true); 341 UserPrefs.getPrefs().useSavedBounds("newcomp", dlg); 342 dlg.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); 343 NewComponentDialog panel = new NewComponentDialog(dlg); 344 panel.setComponentDef(componentDef); 345 panel.setComponentName("untitled"); 346 dlg.getContentPane().add(panel); 347 dlg.pack(); 348 dlg.setVisible(true); 349 return panel; 350 } 351 352 /** Unit testing. 353 */ 354 public static void main(String[] args) { 355 JFrame frame = new JFrame(); 356 frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); 357 NewComponentDialog dialog = new NewComponentDialog(frame); 358 359 ComponentDef componentDef = new ComponentDef(); 360 componentDef.imports = "import javax.swing.JLabel;"; 361 componentDef.declarations = "JLabel ${name} = new JLabel(\"Hello World\");"; 362 componentDef.configure = ""; 363 componentDef.add = "${container}.add(${name}, \"${name}\");"; 364 componentDef.remove = "${container}.remove($name);"; 365 dialog.setComponentName("untitled"); 366 dialog.setComponentDef(componentDef); 367 368 frame.getContentPane().add(dialog); 369 frame.pack(); 370 frame.setVisible(true); 371 } 372 373}