001:package com.xoetrope.svgscanner;
002:
003:import java.awt.HeadlessException;
004:import java.awt.Component;
005:import java.awt.Color;
006:import java.awt.Point;
007:import java.awt.CardLayout;
008:import java.awt.event.ActionEvent;
009:import java.awt.event.FocusEvent;
010:import java.awt.event.ActionListener;
011:import java.awt.event.MouseEvent;
012:import java.io.IOException;
013:import java.io.File;
014:import java.io.BufferedWriter;
015:import java.io.Writer;
016:import java.io.FileWriter;
017:import java.util.EventObject;
018:import java.util.Vector;
019:import java.util.Collection;
020:import java.util.Collections;
021:
022:import javax.swing.JComponent;
023:import javax.swing.JOptionPane;
024:import javax.swing.JFileChooser;
025:import javax.swing.JColorChooser;
026:import javax.swing.JDialog;
027:import javax.swing.JPopupMenu;
028:import javax.swing.JMenuItem;
029:import javax.swing.SwingUtilities;
030:import javax.swing.colorchooser.AbstractColorChooserPanel;
031:
032:import com.xoetrope.swing.XCheckCombo;
033:import com.xoetrope.svgscanner.model.SynthModel;
034:import com.xoetrope.svgscanner.model.SynthElementHandler;
035:import com.xoetrope.svgscanner.wizard.BindingWizard;
036:
037:import com.xoetrope.swing.wizard.XWizard;
038:import com.xoetrope.swing.list.XAltListCellRenderer;
039:
040:import net.xoetrope.xui.XPage;
041:import net.xoetrope.xui.style.XStyle;
042:import net.xoetrope.swing.XEdit;
043:import net.xoetrope.swing.XCheckbox;
044:import net.xoetrope.swing.XComboBox;
045:import net.xoetrope.swing.XList;
046:import net.xoetrope.swing.XLabel;
047:import net.xoetrope.swing.XPanel;
048:import net.xoetrope.swing.XScrollPane;
049:import net.xoetrope.xui.data.XModel;
050:import net.xoetrope.xml.XmlElement;
051:import com.xoetrope.helper.AFileFilter;
052:import net.xoetrope.xui.data.XModelHelper;
053:import net.xoetrope.xui.helper.XuiUtilities;
054:import net.xoetrope.editor.color.ColorWheelPanel;
055:import net.xoetrope.editor.XEditorUtilities;
056:
057:
058:import net.xoetrope.optional.annotation.Find;
059:
060:import net.xoetrope.xml.XmlElement;
061:import net.xoetrope.xml.nanoxml.NanoXmlElement;
062:import net.xoetrope.xml.nanoxml.NanoXmlWriter;
063:
064:/**
065: *
066: * <p> Copyright (c) Xoetrope Ltd., 2001-2007, This software is licensed under
067: * the GNU Public License (GPL), please see license.txt for more details. If
068: * you make commercial use of this software you must purchase a commercial
069: * license from Xoetrope.</p>
070: * <p>$Revision: 1.7 $</p>
071: */
072:public class SynthBindings extends XPage implements ActionListener
073:{
074: @Find
075: private XList bindingList, stateList, propertiesList;
076:
077: @Find
078: private XScrollPane propertiesScroller;
079:
080: @Find
081: private XLabel propertiesLabel;
082:
083: @Find
084: private XEdit styleNameEdit;
085:
086: @Find
087: private XCheckCombo stateValueCombo;
088:
089: @Find
090: private XPanel cardPanel;
091:
092: private SynthModel synthModel;
093: private XmlElement bindingElement;
094:
095: private XmlElement styleElement; // List 1 selection
096: private XmlElement stateElement; // List 2 selection
097: private XmlElement propertyElement; // List 3 selection
098:
099: private XmlElement objectElement; // Property sheet object
100:
101: private SynthElementHandler synthElementHandler;
102: private JComponent focusObject;
103:
104: private Footer footer;
105:
106: private String[] styleElements = { "property", "defaultsProperty", "state", "font", "graphicsUtils", "insets", "painter", "imagePainter", "opaque", "inputMap", "iamgeIcon", "beansPersistence" };
107: private String[] stateElements = { "font", "color", "painter", "imagePainter", "beansPersistence" };
108: private String[] defaultList = { "default" };
109:
110: private XList sourceList;
111:
112: public SynthBindings()
113: {
114: synthModel = (SynthModel)((XModel)rootModel.get( "SynthModel" )).get();
115: }
116:
117: public void pageCreated()
118: {
119: XStyle style = project.getStyleManager().getStyle( "list/alt" );
120:
121: XAltListCellRenderer renderer = new XAltListCellRenderer();
122: renderer.setAltUnselectedColors( style.getStyleAsColor( XStyle.COLOR_FORE ), style.getStyleAsColor( XStyle.COLOR_BACK ));
123:
124: bindingList.setCellRenderer( renderer );
125: stateList.setCellRenderer( renderer );
126: propertiesList.setCellRenderer( renderer );
127: }
128:
129: public void pageActivated( )
130: {
131: footer = (Footer)pageMgr.getPage( "Footer" );
132: footer.setNext( "ImageViewer" );
133: }
134:
135: public void bindingChanged()
136: {
137: // Store the style name in case it has chnaged
138: styleNameChanged();
139:
140: stateList.removeAll();
141: bindingElement = styleElement = stateElement = null;
142:
143: String selection = (String)bindingList.getSelectedObject();
144: if ( selection != null ) {
145: bindingElement = synthModel.getBinding( selection );
146: if ( bindingElement == null ) {
147: JOptionPane.showMessageDialog( this , "The selected binding key is not in use in the current look and feel" );
148: styleNameEdit.setText( "" );
149: propertiesScroller.setEnabled( false );
150: propertiesLabel.setEnabled( false );
151: stateValueCombo.setEnabled( false );
152:
153: objectElement = null;
154: updateObjectEditor();
155: return;
156: }
157: else {
158: String styleName = bindingElement.getAttribute( "style" );
159: styleElement = synthModel.getStyle( styleName ).element;
160: styleNameEdit.setText( styleElement.getAttribute( "id" ));
161:
162: SynthModel.CrossReferenceElement styleXref = synthModel.getStyle( styleName );
163: Vector styleElements = styleXref.element.getChildren();
164: for ( Object obj : styleElements ) {
165: XmlElement xmlElement = (XmlElement)obj;
166: String name = xmlElement.getName();
167: SynthElementHandler seh = synthModel.getElementHandler( name );
168:
169: String styleElementName = seh.getName( xmlElement );
170: stateList.addItem( styleElementName );
171: }
172: stateList.setSelectedIndex( 0 );
173: }
174: }
175: }
176:
177: public void stateChanged()
178: {
179: // Store the state value in case it has changed
180: stateValueChanged();
181:
182: propertiesList.removeAll();
183: stateElement = propertyElement = null;
184:
185: int selIdx = stateList.getSelectedIndex();
186: if ( selIdx >= 0 ) {
187: stateElement = (XmlElement)styleElement.getChildren().elementAt( selIdx );
188:
189: String propertyName = stateElement.getName();
190: boolean isState = propertyName.equals( "state" );
191: propertiesScroller.setEnabled( isState );
192: propertiesList.setEnabled( isState );
193: propertiesLabel.setEnabled( isState );
194: stateValueCombo.setEnabled( isState );
195:
196: if ( isState ) {
197: stateValueCombo.setSelectedItem( stateElement.getAttribute( "value" ));
198: Vector propertyElements = stateElement.getChildren();
199: for ( Object sobj : propertyElements ) {
200: XmlElement sxmlElement = (XmlElement)sobj;
201: propertiesList.addItem( sxmlElement.getName());
202: }
203: propertiesList.setSelectedIndex( 0 );
204: }
205: else {
206: objectElement = stateElement;
207: stateElement = null;
208: stateValueCombo.clearSelection();
209: }
210: }
211: else
212: stateValueCombo.clearSelection();
213:
214: updateObjectEditor();
215: }
216:
217:
218: public void propertyChanged()
219: {
220: int selIdx = propertiesList.getSelectedIndex();
221: if ( selIdx >= 0 )
222: objectElement = propertyElement = (XmlElement)stateElement.getChildren().elementAt( selIdx );
223:
224: updateObjectEditor();
225: }
226:
227: public void updateObjectEditor()
228: {
229: // If we are switching components the last edit field being edited may not have saved its value
230: if ( focusObject != null ) {
231: String compName = focusObject.getName();
232: String attribName = getAttribute( "attrib", compName ).toString();
233: if ( attribName == null )
234: return;
235:
236: if ( focusObject instanceof XEdit )
237: synthElementHandler.setAttribute( attribName, ((XEdit)focusObject).getText());
238:
239: focusObject = null;
240: }
241:
242: synthElementHandler = null;
243: CardLayout cm = (CardLayout)cardPanel.getLayout();
244: if ( objectElement == null )
245: cm.show( cardPanel, "none" );
246: else {
247: String objectType = objectElement.getName();
248: String objectTypeLwr = objectType.toLowerCase();
249:
250: cm.show( cardPanel, objectType );
251:
252: synthElementHandler = SynthModel.getElementHandler( objectType );
253: if ( synthElementHandler != null ) {
254: synthElementHandler.setObject( objectElement );
255: synthElementHandler.updateUI( this );
256: }
257: else
258: cm.show( cardPanel, "none" );
259: }
260: }
261:
262: /**
263: * Find an image
264: */
265: public void imageFinder()
266: {
267: try {
268: String compName = ((Component)getCurrentEvent().getSource()).getName();
269: compName = getAttribute( "edit", compName ).toString();
270: XEdit edit = (XEdit)findComponent( compName );
271: String currentRes = edit.getText();
272:
273: JFileChooser chooser = new JFileChooser();
274: AFileFilter myFilter = new AFileFilter( "svg", "SVG files" );
275: myFilter.setDirMustExist( true );
276: myFilter.setFileMustExist( true );
277: chooser.setDialogTitle( "Please specify the location of the SVG file" );
278: chooser.setFileFilter( myFilter );
279: chooser.setFileSelectionMode( chooser.FILES_ONLY );
280: chooser.setMultiSelectionEnabled( false );
281:
282: String sourceFolder = XModelHelper.getString( rootModel, "sourceFolder" );
283: if ( sourceFolder.length() > 0 )
284: chooser.setCurrentDirectory( new File( sourceFolder ));
285:
286: if ( chooser.showOpenDialog( this ) == JFileChooser.APPROVE_OPTION ) {
287: File selectedFile = chooser.getSelectedFile();
288: String canonicalPath = chooser.getSelectedFile().getCanonicalPath();
289: String parentPath = selectedFile.getParent();
290: if ( canonicalPath.contains( sourceFolder )) {
291: String fileName = canonicalPath.substring( parentPath.length() + 1 );
292: edit.setText( fileName );
293: String attribName = getAttribute( "attrib", compName ).toString();
294: synthElementHandler.setAttribute( attribName, fileName );
295: }
296: }
297: }
298: catch ( Exception ex )
299: {
300: ex.printStackTrace();
301: }
302: }
303: /**
304: * Find a color
305: */
306: public void colorFinder()
307: {
308: try {
309: String compName = ((Component)getCurrentEvent().getSource()).getName();
310: compName = getAttribute( "edit", compName ).toString();
311: final XEdit edit = (XEdit)findComponent( compName );
312: final String attribName = getAttribute( "attrib", compName ).toString();
313:
314: String selectedColor = edit.getText();
315: if ( selectedColor.startsWith( "#" ))
316: selectedColor = selectedColor.substring( 1 );
317:
318: Color clr = (Color)XStyle.parseColor( selectedColor );
319: final JColorChooser colorChooser = new JColorChooser();
320:
321: AbstractColorChooserPanel[] oldPanels = colorChooser.getChooserPanels();
322: AbstractColorChooserPanel[] newPanels = new AbstractColorChooserPanel[ oldPanels.length + 1 ];
323: System.arraycopy( oldPanels, 0, newPanels, 1, oldPanels.length );
324: newPanels[ 0 ] = new ColorWheelPanel();
325: colorChooser.setChooserPanels( newPanels );
326:
327: //colorChooser.addChooserPanel( new ColorWheelPanel());
328: colorChooser.setColor( clr );
329: XEditorUtilities.setDefaultFont( colorChooser );
330:
331: JDialog dialog = JColorChooser.createDialog(
332: this ,
333: "Choose the new Color",
334: true,
335: colorChooser,
336: new ActionListener()
337: {
338: public void actionPerformed( ActionEvent e )
339: {
340: Color newColor = colorChooser.getColor();
341: String colorValue = "#" + XuiUtilities.colorToHexString( newColor );
342:// int r = newColor.getRed();
343:// int g = newColor.getGreen();
344:// int b = newColor.getBlue();
345:// int a = newColor.getAlpha();
346:// String colorValue = "#" +
347:// (( r < 16 ) ? "0" : "" ) + Integer.toString( r, 16 ) +
348:// (( g < 16 ) ? "0" : "" ) + Integer.toString( g, 16 ) +
349:// (( b < 16 ) ? "0" : "" ) + Integer.toString( b, 16 ) +
350:// (( a < 16 ) ? "0" : "" ) + ( a != 255 ? Integer.toString( a, 16 ) : "" );
351:
352: edit.setText( colorValue );
353: synthElementHandler.setAttribute( attribName, colorValue );
354: }
355: }, null
356: );
357: XuiUtilities.centerOnScreen( dialog );
358: dialog.setVisible( true );
359: }
360: catch ( Exception ex )
361: {
362: ex.printStackTrace();
363: }
364: }
365:
366: /**
367: * Store the value of the field associated with the event
368: */
369: public void storeValue()
370: {
371: focusObject = null;
372: if ( synthElementHandler == null )
373: return;
374:
375: EventObject eo = getCurrentEvent();
376: Component comp = (Component)eo.getSource();
377: String compName = comp.getName();
378: String attribName = getAttribute( "attrib", compName ).toString();
379: if ( attribName == null )
380: return;
381:
382: if ( comp instanceof XEdit ) {
383: if (( eo instanceof FocusEvent ) && (((FocusEvent)eo).getID() == FocusEvent.FOCUS_LOST ))
384: synthElementHandler.setAttribute( attribName, ((XEdit)comp).getText());
385: else
386: focusObject = (JComponent)comp;
387: }
388: else if ( comp instanceof XCheckbox )
389: synthElementHandler.setAttribute( attribName, ((XCheckbox)comp).isSelected() ? "true" : "false" );
390: else if ( comp instanceof XComboBox ) {
391: Object selObj = ((XComboBox)comp).getSelectedItem();
392: if ( selObj != null )
393: synthElementHandler.setAttribute( attribName, selObj.toString());
394: }
395: }
396:
397: /**
398: * The style name has changed
399: */
400: public void styleNameChanged()
401: {
402: EventObject eo = getCurrentEvent();
403: if ( styleElement != null ) {
404: if ( !( eo instanceof FocusEvent ) || (((FocusEvent)eo).getID() == FocusEvent.FOCUS_LOST )) {
405: String oldStyleName = styleElement.getAttribute( "id" );
406: String value = styleNameEdit.getText();
407: if ( !value.equals( oldStyleName )) {
408: styleElement.setAttribute( "id", value );
409: bindingElement.setAttribute( "style", value );
410:
411: // Update all usages
412: SynthModel.CrossReferenceElement styleXref = synthModel.getStyle( oldStyleName );
413: styleXref.id = value;
414: for ( String usage : styleXref.usages ) {
415: XmlElement binding = synthModel.getBinding( usage );
416: binding.setAttribute( "style", value );
417: }
418: }
419: }
420: }
421: }
422:
423: /**
424: * The style name has changed
425: */
426: public void stateValueChanged()
427: {
428: EventObject eo = getCurrentEvent();
429: if ( stateElement != null ) {
430: Object selObj = stateValueCombo.getEditor().getItem();
431: String newValue = selObj == null ? null : selObj.toString();
432: String oldValue = stateElement.getAttribute( "value" );
433: if ( newValue != null ) {
434: if ( !newValue.equals( oldValue ))
435: stateElement.setAttribute( "value", newValue );
436: }
437: else {
438: if ( oldValue != null )
439: stateElement.setAttribute( "value", null );
440: }
441: }
442: }
443:
444: public void generateXml()
445: {
446: try {
447: String outputFolder = XModelHelper.getString( project, rootModel, "outputFolder" );
448: FileWriter fw = new FileWriter( new File( outputFolder + File.separator + "test.synth" ));
449: Writer writer = new BufferedWriter( fw );
450: NanoXmlWriter xmlWriter = new NanoXmlWriter( writer );
451:
452: XmlElement synthElement = synthModel.getXml();
453:
454: xmlWriter.write( synthElement, true, 4 );
455: writer.flush();
456: writer.close();
457: fw.close();
458:
459: showMessage( "XML Generated", "You can find the generated XML at: " + outputFolder + File.separator + "test.synth" );
460: return;
461: }
462: catch ( IOException ex ) {
463: System.out.println( "Error generating file" );
464: }
465: }
466:
467: public void showBindingsMenu()
468: {
469: sourceList = bindingList;
470: MouseEvent me = (MouseEvent)getCurrentEvent();
471: if ( me.isPopupTrigger()) {
472: JPopupMenu popupMenu = new JPopupMenu( "Bindings" );
473: JMenuItem mi = new JMenuItem( "Add binding key..." );
474: mi.addActionListener( this );
475: popupMenu.add( mi );
476:
477: if ( bindingList.getSelectedIndex() >= 0 ){
478: popupMenu.addSeparator();
479:
480: mi = new JMenuItem( "Delete" );
481: mi.addActionListener( this );
482: popupMenu.add( mi );
483: }
484:
485: Point pt = me.getPoint();
486: Point vp = bindingList.getLocation();
487: vp = SwingUtilities.convertPoint( (Component)me.getSource(), 0, 0, bindingList );
488: popupMenu.show( bindingList, pt.x + vp.x, pt.y + vp.y );
489: }
490: }
491:
492: public void showStylesMenu()
493: {
494: sourceList = stateList;
495: MouseEvent me = (MouseEvent)getCurrentEvent();
496: if ( me.isPopupTrigger()) {
497: JPopupMenu popupMenu = new JPopupMenu( "Styles" );
498: JMenuItem mi = null;
499:
500: for ( String s : styleElements ) {
501: mi = new JMenuItem( "Add " + s + "..." );
502: mi.addActionListener( this );
503: mi.setActionCommand( s );
504: popupMenu.add( mi );
505: }
506:
507: if ( stateList.getSelectedIndex() >= 0 ){
508: popupMenu.addSeparator();
509:
510: mi = new JMenuItem( "Delete" );
511: mi.addActionListener( this );
512: popupMenu.add( mi );
513: }
514:
515: Point pt = me.getPoint();
516: Point vp = stateList.getLocation();
517: vp = SwingUtilities.convertPoint( (Component)me.getSource(), 0, 0, stateList );
518: popupMenu.show( stateList, pt.x + vp.x, pt.y + vp.y );
519: }
520: }
521:
522: public void showStatesMenu()
523: {
524: sourceList = propertiesList;
525: MouseEvent me = (MouseEvent)getCurrentEvent();
526: if ( me.isPopupTrigger() && sourceList.isEnabled()) {
527: JPopupMenu popupMenu = new JPopupMenu( "Properties" );
528: JMenuItem mi = null;
529:
530: for ( String s : stateElements ) {
531: mi = new JMenuItem( "Add " + s + "..." );
532: mi.addActionListener( this );
533: mi.setActionCommand( s );
534: popupMenu.add( mi );
535: }
536:
537: if ( propertiesList.getSelectedIndex() >= 0 ){
538: popupMenu.addSeparator();
539:
540: mi = new JMenuItem( "Delete" );
541: mi.addActionListener( this );
542: popupMenu.add( mi );
543: }
544:
545: Point pt = me.getPoint();
546: Point vp = propertiesList.getLocation();
547: vp = SwingUtilities.convertPoint( (Component)me.getSource(), 0, 0, propertiesList );
548: popupMenu.show( propertiesList, pt.x + vp.x, pt.y + vp.y );
549: }
550: }
551:
552: public void actionPerformed( ActionEvent ae )
553: {
554: String cmd = ae.getActionCommand();
555: if ( cmd.equals( "Add binding key..." )) {
556: String[] pages = { "wizard/bindingKeyWizard", "wizard/stylesWizard" };
557: BindingWizard wizard = new BindingWizard( project, pages, true );
558: wizard.setCaption( "<html><b>New binding wizard</b></html>");
559: wizard.setSize( 600, 300 );
560: wizard.showDialog( this );
561:
562: updateBoundComponentValues();
563: }
564: else if ( cmd.equals( "Delete" )) {
565:
566: }
567: else {
568: String binding = bindingElement.getAttribute( "key" );
569: String[] options = getOptions( binding, cmd );
570: String res = null;
571: if (( options == null ) || ( options.length == 0 ))
572: options = defaultList;
573:
574: res = (String)JOptionPane.showInputDialog( sourceList,
575: "Choose your options",
576: "Available " + cmd + " options",
577: JOptionPane.QUESTION_MESSAGE,
578: null,
579: options,
580: options[ 0 ] );
581:
582: if ( res == null )
583: return;
584:
585: if ( res.equals( options[ 0 ] ))
586: res = null;
587:
588: if ( sourceList == stateList ) {
589: addState( styleElement, binding, cmd, res );
590: bindingChanged();
591: }
592: else if ( sourceList == propertiesList ) {
593: addState( stateElement, binding, cmd, res );
594: stateChanged();
595: }
596: }
597: }
598:
599: private String[] getOptions( String bindingKey, String type )
600: {
601: XModel options = (XModel)rootModel.get( "bindingKeys/" + bindingKey + "/" + type );
602: String attrib = XModelHelper.getAttrib( options, "key" );
603: if ( attrib == null )
604: return new String[ 0 ];
605:
606: if ( attrib.length() == 0 )
607: attrib = "value";
608:
609: int numChildren = options.getNumChildren();
610: String[] res = new String[ numChildren ];
611: for ( int i = 0; i < numChildren; i++ ) {
612: res[ i ] = (String)XModelHelper.getAttrib( options.get( i ), attrib );
613: }
614:
615: return res;
616: }
617:
618: private void addState( XmlElement parent, String bindingKey, String type, String value )
619: {
620: XModel options = (XModel)rootModel.get( "bindingKeys/" + bindingKey + "/" + type );
621: NanoXmlElement newStateElement = new NanoXmlElement( type );
622: parent.addChild( newStateElement );
623:
624: if ( value == null )
625: return;
626:
627: String attrib = XModelHelper.getAttrib( options, "key" );
628: if ( attrib == null )
629: return;
630:
631: if ( attrib.length() == 0 )
632: attrib = "value";
633:
634: int numChildren = options.getNumChildren();
635: for ( int i = 0; i < numChildren; i++ ) {
636: XModel childNode = options.get( i );
637: String keyValue = (String)XModelHelper.getAttrib( childNode, attrib );
638: if ( value.equals( keyValue )) {
639: int numAttribs = childNode.getNumAttributes();
640: for ( int j = 0; j < numAttribs; j++ )
641: newStateElement.setAttribute( childNode.getAttribName( j ), childNode.getAttribValue( j ).toString());
642:
643: return;
644: }
645: }
646:
647: return;
648: }
649:}
|