View Javadoc

1   /*
2    * Copyright (c) 2004-2005 by Michael Connor. All Rights Reserved.
3    *
4    * Redistribution and use in source and binary forms, with or without
5    * modification, are permitted provided that the following conditions are met:
6    *
7    *  o Redistributions of source code must retain the above copyright notice,
8    *    this list of conditions and the following disclaimer.
9    *
10   *  o Redistributions in binary form must reproduce the above copyright notice,
11   *    this list of conditions and the following disclaimer in the documentation
12   *    and/or other materials provided with the distribution.
13   *
14   *  o Neither the name of FormLayoutBuilder or Michael Connor nor the names of
15   *    its contributors may be used to endorse or promote products derived
16   *    from this software without specific prior written permission.
17   *
18   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19   * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
20   * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21   * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
22   * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23   * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24   * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
25   * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26   * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
27   * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
28   * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29   */
30  /*
31   * NewComponentDialog.java
32   *
33   * Created on March 24, 2005, 6:49 PM
34   */
35  
36  package org.mlc.swing.layout;
37  
38  import bsh.Interpreter;
39  import com.jgoodies.forms.factories.Borders;
40  import com.jgoodies.forms.factories.ButtonBarFactory;
41  import java.awt.Component;
42  import java.awt.Window;
43  import java.awt.event.*;
44  import javax.swing.*;
45  
46  /***
47   * When performing drag-and-drop from the component palette to the table,
48   * this class is used to define or edit a component's settings. These
49   * settings include the import, declaration, configuration lines which
50   * will be used to generate the code for the component. The same settings
51   * are used to create a 'preview' component to be shown in the preview
52   * window.
53   *
54   * @author Michael Connor
55   */
56  @SuppressWarnings("serial")
57  public class NewComponentDialog extends JPanel
58  {
59    JLabel componentNameLabel = new JLabel("Name");
60    JTextField componentNameTextField = new JTextField();
61  
62    JLabel importsLabel = new JLabel("Imports");
63    JTextArea importsComponent = createTextArea(3, 40);
64  
65    JLabel declarationsLabel = new JLabel("Declarations");
66    JTextArea declarationsComponent = createTextArea(3, 40);
67  
68    JLabel configureLabel = new JLabel("Configure");
69    JTextArea configureComponent = createTextArea(4, 40);
70  
71    JLabel addToContainerLabel = new JLabel("Add");
72    JTextArea addToContainerComponent = createTextArea(3, 40);
73  
74    JLabel removeFromContainerLabel = new JLabel("Remove");
75    JTextArea removeFromContainerComponent = createTextArea(2, 40);
76  
77    JLabel previewLabel = new JLabel("Preview");
78    JScrollPane previewComponent = new JScrollPane();
79  
80    JButton prevButton = new JButton("Preview");
81    JButton okButton = new JButton("OK");
82    JButton cancelButton = new JButton("Cancel");
83    Component buttonBar = ButtonBarFactory.buildRightAlignedBar(new JButton[] {
84        prevButton, okButton, cancelButton });
85  
86    ComponentDef componentDef;
87    private String preview;
88    Window myOwner;
89    private boolean success = false;
90  
91    public boolean succeeded()
92    {
93      return success;
94    }
95  
96    /*** Creates a new instance of NewComponentDialog */
97    public NewComponentDialog(Window owner)
98    {
99      myOwner = owner;
100     LayoutConstraintsManager layoutConstraintsManager = LayoutConstraintsManager
101         .getLayoutConstraintsManager(NewComponentDialog.class.getResourceAsStream(
102             "editableLayoutConstraints.xml"));
103 
104     this.setBorder(Borders.DIALOG_BORDER);
105 
106     layoutConstraintsManager.setLayout("newComponentPanel", this);
107 
108     // here we add the controls to the container. you may
109     // need to change the name of panel
110     add(new JScrollPane(removeFromContainerComponent),
111         "removeFromContainerComponent");
112 
113     add(configureLabel, "configureLabel");
114     add(new JScrollPane(importsComponent), "importsComponent");
115     add(new JScrollPane(declarationsComponent), "declarationsComponent");
116     add(new JScrollPane(configureComponent), "configureComponent");
117     add(new JScrollPane(addToContainerComponent), "addToContainerComponent");
118     add(buttonBar, "buttonBar");
119     add(declarationsLabel, "declarationsLabel");
120     add(componentNameLabel, "componentNameLabel");
121     add(importsLabel, "importsLabel");
122     add(addToContainerLabel, "addToContainerLabel");
123     add(componentNameTextField, "componentNameTextField");
124     add(removeFromContainerLabel, "removeFromContainerLabel");
125 
126     add(previewLabel, "previewLabel");
127     add(previewComponent, "previewComponent");
128 
129     prevButton.addActionListener(new ActionListener()
130     {
131       public void actionPerformed(ActionEvent e)
132       {
133         doPreview();
134       }
135     });
136     okButton.addActionListener(new ActionListener()
137     {
138       public void actionPerformed(ActionEvent e)
139       {
140         success = true;
141         componentDef.add = getAdd();
142         componentDef.configure = getConfiguration();
143         componentDef.declarations = getDeclarations();
144         componentDef.name = componentNameTextField.getText().trim();
145         componentDef.imports = getImports();
146         UserPrefs.getPrefs().saveWinLoc("newcomp", myOwner);
147         myOwner.setVisible(false);
148       }
149     });
150     cancelButton.addActionListener(new ActionListener()
151     {
152       public void actionPerformed(ActionEvent e)
153       {
154         success = false;
155         UserPrefs.getPrefs().saveWinLoc("newcomp", myOwner);
156         myOwner.setVisible(false);
157       }
158     });
159   }
160 
161   // class PreviewThread implements Runnable {
162   //
163   // boolean running = true;
164   //
165   // public void run() {
166   // while (running) {
167   // }
168   // }
169   // }
170 
171   /***
172   Get an instance of the specified component. In FormLayoutMaker,
173   this instance is placed in the preview panel.
174   <p>
175   For example, if the component is a JButton, this method is the
176   equivalent of <code>new JButton(<i>text</i>)</code>.
177 
178   @return Component An instance of the component, null if there
179   is a problem in the specification. [It is recommended that the
180   'Preview' button should be clicked before exiting the dialog.]
181   */
182   public Component getInstance()
183   {
184     Component component = null;
185     String script;
186     if (preview == null || preview.length() == 0)
187       script = getImports() + "\n" + getDeclarations() + "\n"
188           + getConfiguration();
189     else
190       script = preview.trim();
191     String componentName = componentNameTextField.getText();
192     script = script.replaceAll("//$//{name//}", componentName);
193 
194     Interpreter interpreter = new Interpreter();
195     interpreter.setStrictJava(true);
196 
197     JPanel temporaryContainer = null;
198     try
199     {
200 
201       interpreter.set("container", temporaryContainer);
202       interpreter.eval(script);
203       component = (Component) interpreter.get(componentName);
204 
205     }
206     catch (bsh.EvalError error)
207     {
208       System.out.println(error);
209     }
210     return component;
211   }
212 
213   private void doPreview()
214   {
215     Component component = getInstance();
216     if (component == null)
217       return;
218     JPanel temporaryContainer = new JPanel();
219     temporaryContainer.add(component);
220     if (temporaryContainer != null)
221     {
222       previewComponent.setViewportView(temporaryContainer);
223     }
224   }
225 
226   /*** Get the component's name */
227   public String getComponentName()
228   {
229     return componentNameTextField.getText();
230   }
231 
232   public void setComponentName(String componentName)
233   {
234     componentNameTextField.setText(componentName);
235   }
236 
237   /*** Get the component's <imports> section. */
238   public String getImports()
239   {
240     return importsComponent.getText().trim();
241   }
242 
243   /*** Get the component's <declarations> section. */
244   public String getDeclarations()
245   {
246     return declarationsComponent.getText().trim();
247   }
248 
249   /*** Get the component's <configuration> section. */
250   public String getConfiguration()
251   {
252     return configureComponent.getText().trim();
253   }
254 
255   public String getAdd()
256   {
257     String res = addToContainerComponent.getText();
258     return cleanString(res);
259   }
260 
261   public void setRemove(String remove)
262   {
263     removeFromContainerComponent.setText(remove);
264   }
265 
266   public void setComponentDef(ComponentDef componentDef)
267   {
268     editComponentDef(componentDef.clone());
269   }
270 
271   public void editComponentDef(ComponentDef componentDef)
272   {
273     this.componentDef = componentDef;
274 
275     importsComponent.setText(cleanString(componentDef.imports));
276     declarationsComponent.setText(cleanString(componentDef.declarations));
277     configureComponent.setText(cleanString(componentDef.configure));
278     addToContainerComponent.setText(cleanString(componentDef.add));
279     removeFromContainerComponent.setText(cleanString(componentDef.remove));
280     preview = cleanString(componentDef.preview);
281   }
282 
283   /*** Cleans a string. Removes extra newlines.
284    *
285    * @param instr
286    * @return
287    */
288   private String cleanString(String instr)
289   {
290     if ( instr == null )
291       return instr;
292 
293 // Java 1.5 library method
294 //    while ( res.contains("\n\n") )
295     // KBR 09/05/05 Reworked to deal with leading space for multiline
296     // sections.
297     String [] outstrs = instr.split("\n");
298     StringBuffer outstr = new StringBuffer();
299     for ( int i = 0 ; i < outstrs.length; i++ )
300     {
301       String tmp = outstrs[i].trim();
302       outstr.append(tmp.length() > 0 ? (tmp + "\n") : "");
303     }
304     return outstr.toString();
305   }
306 
307   private static JTextArea createTextArea(int rows, int cols)
308   {
309     JTextArea textArea = new JTextArea(rows, cols);
310 //KBR linewrap makes longer sections hard to work with
311 //    textArea.setWrapStyleWord(true);
312 //    textArea.setLineWrap(true);
313     return textArea;
314   }
315 
316   /***
317   * Creates and displays a dialog for editing a component's settings. See
318   * @see doDialog for an example.
319   */
320   public static NewComponentDialog editDialog(JFrame owner,
321       ComponentDef componentDef)
322   {
323     JDialog dlg = new JDialog(owner, "Edit Component", true);
324     UserPrefs.getPrefs().useSavedBounds("newcomp",dlg);
325     dlg.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
326     NewComponentDialog panel = new NewComponentDialog(dlg);
327     panel.editComponentDef(componentDef);
328     panel.setComponentName(componentDef.name);
329     dlg.getContentPane().add(panel);
330     dlg.pack();
331     dlg.setVisible(true);
332     return panel;
333   }
334 
335   /***
336   * Creates and displays a dialog for defining a new component's settings. The
337     dialog should be used as follows:
338     <code>
339 NewComponentDialog dlg = NewComponentDialog.doDialog(frame, componentDef);
340 if (dlg.succeeded())
341 {
342   [do something with dlg.componentDef]
343 }
344 <code>
345   */
346   public static NewComponentDialog doDialog(JFrame owner,
347       ComponentDef componentDef)
348   {
349     JDialog dlg = new JDialog(owner, "New Component", true);
350     UserPrefs.getPrefs().useSavedBounds("newcomp",dlg);
351     dlg.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
352     NewComponentDialog panel = new NewComponentDialog(dlg);
353     panel.setComponentDef(componentDef);
354     panel.setComponentName("untitled");
355     dlg.getContentPane().add(panel);
356     dlg.pack();
357     dlg.setVisible(true);
358     return panel;
359   }
360 
361   /*** Unit testing.
362   */
363   public static void main(String[] args)
364   {
365     JFrame frame = new JFrame();
366     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
367     NewComponentDialog dialog = new NewComponentDialog(frame);
368 
369     ComponentDef componentDef = new ComponentDef();
370     componentDef.imports = "import javax.swing.JLabel;";
371     componentDef.declarations = "JLabel ${name} = new JLabel(\"Hello World\");";
372     componentDef.configure = "";
373     componentDef.add = "${container}.add(${name}, \"${name}\");";
374     componentDef.remove = "${container}.remove($name);";
375     dialog.setComponentName("untitled");
376     dialog.setComponentDef(componentDef);
377 
378     frame.getContentPane().add(dialog);
379     frame.pack();
380     frame.setVisible(true);
381   }
382 
383 }