package com.alu.tat.client.util;
import java.util.ArrayList;  
import java.util.List;  

import com.google.gwt.core.client.GWT;  
import com.smartgwt.client.bean.BeanFactory;  

import com.smartgwt.client.core.Function;  
import com.smartgwt.client.data.DSCallback;  
import com.smartgwt.client.data.DSRequest;  
import com.smartgwt.client.data.DSResponse;  
import com.smartgwt.client.data.DataSource;  
import com.smartgwt.client.data.DataSourceField;  
import com.smartgwt.client.data.Record;  
 
import com.smartgwt.client.tools.EditContext;  
import com.smartgwt.client.tools.EditNode;  

import com.smartgwt.client.tools.PaletteNode;  
import com.smartgwt.client.tools.SelectedEditNodesUpdatedEvent;
import com.smartgwt.client.tools.SelectedEditNodesUpdatedHandler;

    import com.smartgwt.client.tools.TilePalette;  
import com.smartgwt.client.types.AnimationAcceleration;  
import com.smartgwt.client.types.ArrowStyle;  
import com.smartgwt.client.types.DSDataFormat;  
 
import com.smartgwt.client.types.FieldType;  

import com.smartgwt.client.util.SC;  
   import com.smartgwt.client.util.XMLSyntaxHiliter;

    import com.smartgwt.client.widgets.AnimationCallback;  
import com.smartgwt.client.widgets.Button;  
import com.smartgwt.client.widgets.Canvas;  

import com.smartgwt.client.widgets.Img;  
import com.smartgwt.client.widgets.Window;  

import com.smartgwt.client.widgets.drawing.DrawItem;  
import com.smartgwt.client.widgets.drawing.DrawCurve;  

import com.smartgwt.client.widgets.drawing.DrawLine;  

import com.smartgwt.client.widgets.drawing.DrawPane;  

import com.smartgwt.client.widgets.drawing.Gradient;  
import com.smartgwt.client.widgets.drawing.Point;  
import com.smartgwt.client.widgets.drawing.Shadow;  
import com.smartgwt.client.widgets.drawing.SimpleGradient;  
import com.smartgwt.client.widgets.events.ClickEvent;  
import com.smartgwt.client.widgets.events.ClickHandler;  
import com.smartgwt.client.widgets.events.KeyPressEvent;  
import com.smartgwt.client.widgets.events.KeyPressHandler;  
import com.smartgwt.client.widgets.form.DynamicForm;  
    import com.smartgwt.client.widgets.layout.HLayout;  
import com.smartgwt.client.widgets.layout.Layout;  
import com.smartgwt.client.widgets.layout.LayoutSpacer;  
import com.smartgwt.client.widgets.layout.VLayout;  
import com.smartgwt.client.widgets.tree.Tree;  
import com.smartgwt.client.widgets.tree.TreeNode;  
import com.smartgwt.client.widgets.viewer.DetailViewerField;  
      
    public class DiagrammingSample {  
      
		private static final String DESCRIPTION =
			"<p>With the Tools framework it is easy to create a simple drawing editor. "
            + "This example uses a palette of pre-configured DrawItems that can be dropped into the "
            + "target DrawPane. Position, size, and styling properties of the DrawItems are "
            + "automatically persisted.</p>"
            + "<p>This sample persists into a JavaScript variable.  Double-click or drag some "
            + "Draw Items into the Draw Pane, then click the \"Destroy and Recreate\" button to "
            + "save the state, destroy the DrawItems, and then recreate them.</p>";
        class SampleDrawingDataSource extends DataSource {  
            public SampleDrawingDataSource() {  
                setDataURL("data/sampleDrawingData.xml");  
                setDataFormat(DSDataFormat.XML);  
                setRecordXPath("//sample");  
      
                setFields(new DataSourceField("componentXml", FieldType.TEXT));  
            }  
        }  
      
        class DrawingEditContext extends EditContext {  
              
            private String sampleDrawing;  
      
            public DrawingEditContext() {  
                super();  
                this.setEnableInlineEdit(true);
                this.setCanSelectEditNodes(true);
                loadSampleDrawing();  
            }  
      
            private void setSampleDrawing(String componentXml) {  
                this.sampleDrawing = componentXml;  
                this.showSampleDrawing();  
            }  
              
            private void loadSampleDrawing() {  
                DataSource ds = new SampleDrawingDataSource();  
                ds.fetchData(null, new DSCallback() {  
					@Override
                    public void execute(DSResponse dsResponse, Object data, DSRequest dsRequest) {  
                        Record[] records = dsResponse.getData();  
                        if (records != null && records.length > 0) {  
                            setSampleDrawing(records[0].getAttribute("componentXml"));  
                        }  
                    }  
                }); 
            }  
      
            public void showSampleDrawing() {  
                this.destroyAll();  
      
                final DrawingEditContext self = this;  
                this.addPaletteNodesFromXML(this.sampleDrawing, null, null, new Function() {  
					@Override
                    public void execute() {  
                        self.configureDrawPane();  
                    }  
                });  
            }  
              
            private void configureDrawPane() {  
                // Node drops should be assigned to DrawPane  
                EditNode drawPaneEditNode = this.getDrawPaneEditNode(); 
                if(drawPaneEditNode!=null)
                	this.setDefaultParent(drawPaneEditNode);  
            }  
      
            private EditNode getDrawPaneEditNode() {  
                Tree editTree = this.getEditNodeTree();  
                EditNode rootNode = this.getRootEditNode();  
                TreeNode[] childNodes = editTree.getChildren(rootNode);  
                EditNode editNode = (childNodes != null && childNodes.length > 0 ? new EditNode(childNodes[0].getJsObj()) : null);  
      
                return editNode; 
                //return null;
            }

			
        } ; 
      
        private DrawingEditContext editContext;  
        private Gradient[] commonGradients;  
        private PaletteNode emptyDrawPanePaletteNode;  
      
        private VLayout vLayout;  
        //private DynamicForm exportForm;  
        //private DynamicForm itemPropertiesForm;  
      
        private static boolean enabledReflection = false;  
      
   

    protected boolean isTopIntro() {
        return true;
    }
        public interface MetaFactory extends BeanFactory.MetaFactory {  
            BeanFactory<Canvas> getCanvasBeanFactory();  
            BeanFactory<Img> getImgBeanFactory();  
            BeanFactory<DrawItemTile> getDrawItemTileBeanFactory();  
        }  
      
        private static void enableReflection() {  
            if (!enabledReflection) {  
                GWT.create(MetaFactory.class);  
                enabledReflection = true;  
            }  
        }  
      
        //@Override  
        public Canvas onModuleLoad() {  
           enableReflection();  
      
            if (commonGradients == null) commonGradients = createCommonGradients();  
            if (emptyDrawPanePaletteNode == null) emptyDrawPanePaletteNode = createEmptyDrawPanePaletteNode();  
      
            DrawItemTile.setCommonGradients(commonGradients);  
      
            TilePalette palette = createPalette();  
      
            // The editCanvas is the root component in which the items can be placed.  
            // This canvas will not be serialized - only the child nodes.  
            Canvas editCanvas = new Canvas("editCanvas");  
            editCanvas.setWidth100();  
            editCanvas.setBorder("1px solid black");  
            editCanvas.setCanFocus(true);  
            editCanvas.addKeyPressHandler(new KeyPressHandler() {  
                @Override  
                public void onKeyPress(KeyPressEvent event) {  
                    if ("Delete".equals(event.getKeyName())) {  
                        removeSelectedItems();  
                    }  
                }  
            });  
      
            editContext = new DrawingEditContext();  
            editContext.setDefaultPalette(palette);  
              
            PaletteNode rootComponent = new PaletteNode();  
            rootComponent.setType("Canvas");  
            rootComponent.setCanvasLiveObject(editCanvas);  
            editContext.setRootComponent(rootComponent);  
      
            // Set the defaultEditContext on palette which is used when double-clicking on components.  
            palette.setDefaultEditContext(editContext);  
            
            // Place editCanvas into editMode to allow paletteNode drops  
            EditNode editCanvasEditNode = editContext.getRootEditNode();  
            editCanvas.setEditMode(true, editContext, editCanvasEditNode);  
      
            // Start with an empty drawing until the sample is loaded  
            editContext.addFromPaletteNode(emptyDrawPanePaletteNode);  
            editContext.configureDrawPane();  
      
            editContext.addSelectedEditNodesUpdatedHandler(new SelectedEditNodesUpdatedHandler() {  
                @Override  
                public void onSelectedEditNodesUpdated(SelectedEditNodesUpdatedEvent event) {  
                    selectedEditNodesUpdated();  
                }  
            });  
      
            //exportForm = this.createExportForm();  
            //itemPropertiesForm = this.createItemPropertiesForm();  
      
            VLayout leftLayout = new VLayout();  
            leftLayout.setMembersMargin(5);  
            leftLayout.setMembers(palette);  
      
            VLayout rightLayout = new VLayout();  
            rightLayout.setWidth100();  
            rightLayout.setMembersMargin(5);  
            rightLayout.setMembers(editCanvas);  
      
            HLayout hLayout = new HLayout();  
            hLayout.setWidth100();  
            hLayout.setHeight100();  
            hLayout.setMembersMargin(20);  
            hLayout.setMembers(leftLayout, rightLayout);  
      
            vLayout = new VLayout();  
            vLayout.setWidth100();  
            vLayout.setHeight100();  
            vLayout.setMembersMargin(10);  
            vLayout.setMembers(hLayout);  
      
            //vLayout.draw();  
            return vLayout;
        }  
      
         // The following gradients are shared by various DrawItem shapes and are   
         // applied to the empty DrawPane as well as the palette tile DrawPanes  
        private Gradient[] createCommonGradients() {  
            final SimpleGradient ovalGradient = new SimpleGradient();  
            ovalGradient.setId("oval");  
            ovalGradient.setDirection(90);  
            ovalGradient.setStartColor("#ffffff");  
            ovalGradient.setEndColor("#99ccff");  
      
            final SimpleGradient diamondGradient = new SimpleGradient();  
            diamondGradient.setId("diamond");  
            diamondGradient.setDirection(90);  
            diamondGradient.setStartColor("#d3d3d3");  
            diamondGradient.setEndColor("#666699");  
      
            final SimpleGradient rectGradient = new SimpleGradient();  
            rectGradient.setId("rect");  
            rectGradient.setDirection(90);  
            rectGradient.setStartColor("#f5f5f5");  
            rectGradient.setEndColor("#a9b3b8");  
      
            final SimpleGradient triangleGradient = new SimpleGradient();  
            triangleGradient.setId("triangle");  
            triangleGradient.setDirection(90);  
            triangleGradient.setStartColor("#f5f5f5");  
            triangleGradient.setEndColor("#667766");  
      
            return new Gradient[] { ovalGradient, diamondGradient, rectGradient, triangleGradient };   
        }  
      
        private PaletteNode createEmptyDrawPanePaletteNode() {  
            // Empty DrawPane palette node use when clearing edit canvas  
            DrawPane defaults = new DrawPane();  
            // The DrawPane must be focusable in order for a keypress to trigger inline editing  
            // of a selected draw item whose EditProxy is configured with inlineEditEvent:"dblOrKeypress".  
            defaults.setCanFocus(true);  
            defaults.setWidth100();  
            defaults.setHeight100();  
            defaults.setGradients(commonGradients);  
      
            PaletteNode node = new PaletteNode();  
            node.setType("DrawPane");  
            node.setCanvasDefaults(defaults);  
      
            return node;  
        }  
      
        private TilePalette createPalette() {  
            TilePalette palette = new TilePalette();  
            palette.setWidth(270);  
            palette.setMinHeight(100);  
            palette.setTileWidth(80);  
            palette.setTileHeight(80);  
            palette.setCanDragTilesOut(true);  
            palette.setTileConstructor(DrawItemTile.class.getName());  
      
            // The regular TileGrid property "fields"  
            palette.setFields(new DetailViewerField("type"), new DetailViewerField("title", "Component"));  
      
            // We are supplying the component data inline for this example.  
            // However, ListPalette is a subclass of ListGrid, so you could  
            // also use a DataSource.  
            palette.setData(getPaletteData(palette.getTileWidth(), palette.getTileHeight()));  
      
            return palette;  
        }  
      
        // Creates PaletteNodes for each of different types of DrawItems.  The  
        // defaults of the nodes are set so that the shapes will fit in the grid  
        // tiles.  
        private static Record[] getPaletteData(int tileWidth, int tileHeight) {  
            // Creates PaletteNodes for each of the different types of DrawItems.  The  
            // defaults of the nodes are set so that the shapes will fit in the grid  
            // tiles.  
            final int topPadding = 2;  
            final int leftPadding = 2;  
            final int rightPadding = leftPadding;  
            final int bottomPadding = topPadding;  
            DrawLine lineDefaults;
            tileWidth -= (leftPadding + rightPadding);  
            tileHeight -= (topPadding + bottomPadding);  
      
            final int xc = leftPadding + (tileWidth / 2);  
            final int yc = topPadding + (tileHeight / 2);  
            final int width = tileWidth - leftPadding - rightPadding;  
            final int height = tileHeight - topPadding - bottomPadding;  
      
            // variables for the DrawRect:  
            final double smallAngle = Math.PI / 5;  
              
            final Point[] rectPoints = DrawPane.getPolygonPoints(  
                    width, height, xc, yc,   
                    new double[] {smallAngle, Math.PI - smallAngle, Math.PI + smallAngle, -smallAngle});  
      
            final int rectTop = rectPoints[1].getY();  
            final int rectLeft = rectPoints[1].getX();  
            final int rectWidth = rectPoints[3].getX() - rectLeft;  
            final int rectHeight = rectPoints[3].getX() - rectTop;  
      
            // Define the default properties for three DrawCurves.  
            DrawCurve curveDefaults = new DrawCurve();  
            curveDefaults.setStartPoint(new Point(200, 50));  
            curveDefaults.setEndPoint(new Point(300, 150));  
            curveDefaults.setControlPoint1(new Point(250, 0));  
            curveDefaults.setControlPoint2(new Point(250, 200));  
      
            DrawCurve oneArrowCurveDefaults = new DrawCurve();  
            oneArrowCurveDefaults.setEndArrow(ArrowStyle.BLOCK);  
            oneArrowCurveDefaults.setStartPoint(new Point(200, 50));  
            oneArrowCurveDefaults.setEndPoint(new Point(300, 150));  
            oneArrowCurveDefaults.setControlPoint1(new Point(250, 0));  
            oneArrowCurveDefaults.setControlPoint2(new Point(250, 200));  
      
            DrawCurve twoArrowCurveDefaults = new DrawCurve();  
            twoArrowCurveDefaults.setStartArrow(ArrowStyle.BLOCK);  
            twoArrowCurveDefaults.setEndArrow(ArrowStyle.BLOCK);  
            twoArrowCurveDefaults.setStartPoint(new Point(200, 50));  
            twoArrowCurveDefaults.setEndPoint(new Point(300, 150));  
            twoArrowCurveDefaults.setControlPoint1(new Point(250, 0));  
            twoArrowCurveDefaults.setControlPoint2(new Point(250, 200));  
      
            // Rescale the three DrawCurves to center them at (xc, yc) and to fit them within the  
            // width and height.  
            DrawPane.scaleAndCenterBezier(width, height - 20, xc, yc, curveDefaults.getStartPoint(), curveDefaults.getEndPoint(), curveDefaults.getControlPoint1(), curveDefaults.getControlPoint2());  
            DrawPane.scaleAndCenterBezier(width, height - 20, xc, yc, oneArrowCurveDefaults.getStartPoint(), oneArrowCurveDefaults.getEndPoint(), oneArrowCurveDefaults.getControlPoint1(), oneArrowCurveDefaults.getControlPoint2());  
            DrawPane.scaleAndCenterBezier(width, height - 20, xc, yc, twoArrowCurveDefaults.getStartPoint(), twoArrowCurveDefaults.getEndPoint(), twoArrowCurveDefaults.getControlPoint1(), twoArrowCurveDefaults.getControlPoint2());  
      
            List<PaletteNode> nodes = new ArrayList<PaletteNode>();  
      
            PaletteNode node = new PaletteNode();  
            node = new PaletteNode();  
            node.setTitle("Line w/arrow");  
            node.setType("DrawLine");  
            lineDefaults = new DrawLine();  
            lineDefaults.setStartPoint(new Point(Math.round(xc - width / 2), Math.round(yc - height / 2)));  
            lineDefaults.setEndPoint(new Point(Math.round(xc + width / 2), Math.round(yc + height / 2)));  
            lineDefaults.setEndArrow(ArrowStyle.BLOCK);  
            node.setDrawItemDefaults(lineDefaults);  
            nodes.add(node);  
      
      
            // Set default properties on the DrawItems offered in the palette.  
            for (PaletteNode n : nodes) {  
                DrawItem defaults = n.getDrawItemDefaults();  
                if (defaults == null) {  
                    defaults = new DrawItem();  
                    n.setDrawItemDefaults(defaults);  
                }  
                defaults.setKeepInParentRect(true);  
                defaults.setLineWidth(1);  
                Shadow shadow = new Shadow();  
                shadow.setColor("#333333");  
                shadow.setBlur(2);  
                shadow.setOffset(new Point(1,1));  
                if (!n.getType().equals("DrawLine") && !n.getType().equals("DrawCurve") &&  
                    !n.getType().equals("DrawLinePath"))  
                {  
                    defaults.setShadow(shadow);  
                }  
            }  
      
            return nodes.toArray(new PaletteNode[] {});  
        }  
      
       public Layout createButtonBar(final DrawingEditContext editContext, final Canvas editCanvas) {  
            Button showComponentXmlButton = new Button("Show Component XML");  
            showComponentXmlButton.setAutoFit(true);  
            showComponentXmlButton.addClickHandler(new ClickHandler() {  
                public void onClick(ClickEvent event) {  
                    String paletteNodes = editContext.serializeAllEditNodes();  
      
                    XMLSyntaxHiliter syntaxHiliter = new XMLSyntaxHiliter();  
                    String formattedText = syntaxHiliter.hilite(paletteNodes);  
                    Canvas canvas = new Canvas();  
                    canvas.setContents(formattedText);  
                    canvas.setCanSelectText(true);  
      
                    Window window = new Window();  
                    window.setWidth(Math.round(vLayout.getWidth() / 2));  
                    window.setDefaultHeight(Math.round(vLayout.getHeight() * 2/3));  
                    window.setTitle("Component XML");  
                    window.setAutoCenter(true);  
                    window.setShowMinimizeButton(false);  
                    window.setCanDragResize(true);  
                    window.setIsModal(true);  
                    window.setKeepInParentRect(true);  
                    window.addItem(canvas);  
      
                    window.show();  
                }  
            });  
      
            Button reloadSampleButton = new Button("Reload Sample Drawing");  
            reloadSampleButton.setAutoFit(true);  
            reloadSampleButton.addClickHandler(new ClickHandler() {  
                public void onClick(ClickEvent event) {  
                    // Recreate sample drawing  
                    editContext.showSampleDrawing();  
                }  
            });  
      
            Button clearButton = new Button("Clear Drawing");  
            clearButton.setAutoFit(true);  
            clearButton.addClickHandler(new ClickHandler() {  
                public void onClick(ClickEvent event) {  
                    // Destroy all the nodes  
                    editContext.destroyAll();  
      
                    // Create default DrawPane  
                    editContext.addFromPaletteNode(emptyDrawPanePaletteNode);  
                    editContext.configureDrawPane();  
                }  
            });  
      
            Button destroyAndRecreateButton = new Button("Destroy and Recreate");  
            destroyAndRecreateButton.setAutoFit(true);  
            destroyAndRecreateButton.addClickHandler(new ClickHandler() {  
                public void onClick(ClickEvent event) {  
                    // We save the editPane node data in a variable  
                    final String paletteNodes = editContext.serializeAllEditNodes();  
      
                    // Animate the disappearance of the editCanvas, since otherwise  
                    // everything happens at once.  
                    editCanvas.animateFade(0, new AnimationCallback() {  
                        public void execute(boolean earlyFinish) {  
                            // Once the animation is finished, destroy all the nodes  
                            editContext.destroyAll();  
      
                            // Then add them back from the serialized form  
                            editContext.addPaletteNodesFromXML(paletteNodes, null, null, new Function () {  
                                public void execute() {  
                                    editContext.configureDrawPane();  
                                }  
                            });  
      
                            // And make us visible again  
                            editCanvas.setOpacity(100);  
                        }  
                    }, 2000, AnimationAcceleration.SMOOTH_END);  
                }  
            });  
      
            LayoutSpacer leftSpace = new LayoutSpacer();  
            leftSpace.setWidth("*");  
      
            LayoutSpacer centerSpace = new LayoutSpacer();  
            centerSpace.setWidth(20);  
      
            LayoutSpacer rightSpace = new LayoutSpacer();  
            rightSpace.setWidth(20);  
      
            HLayout layout = new HLayout();  
            layout.setWidth100();  
            layout.setHeight(30);  
            layout.setMembersMargin(10);  
      
            layout.setMembers(leftSpace, showComponentXmlButton, centerSpace, reloadSampleButton, clearButton, rightSpace, destroyAndRecreateButton);  
      
            return layout;  
        } 
      
       
      
        private void selectedEditNodesUpdated() {  
            final DynamicForm form = null;  
      
            EditNode[] selection = this.getSelectedNodes();  
            if (selection.length == 0 || selection.length > 1 ||   
                selection[0].getLiveObject() instanceof DrawPane)   
            {  
                // No selection or multiple selection  
                form.getField("lineColor").disable();  
                form.getField("fillColor").disable();  
                form.getField("arrows").disable();  
                boolean disabled = (selection.length == 0);  
                form.getField("removeItem").setDisabled(disabled);  
      
                form.clearValue("lineColor");  
                form.clearValue("fillColor");  
                form.clearValue("arrows");  
            } else {  
                form.getField("removeItem").enable();  
                  
                // Enable only property controls that are applicable to selection  
                EditNode node = selection[0];  
                DrawItem item = node.getDrawItemLiveObject();  
                String itemClassName = SC.getSCClassName(item.getJsObj());  
                boolean supportsStartArrow = item.supportsStartArrow();  
                boolean supportsEndArrow = item.supportsEndArrow();  
      
                form.getField("lineColor").setDisabled(!SC.isMethodSupported(itemClassName, "setLineColor"));  
                form.getField("fillColor").setDisabled(!SC.isMethodSupported(itemClassName, "setFillColor"));  
                form.getField("arrows").setDisabled(!supportsStartArrow && !supportsEndArrow);  
      
                // Update the arrow selections based on the item's support  
                List<String> arrowsValueMap = new ArrayList<String>();  
                arrowsValueMap.add("None");  
                if (supportsStartArrow) arrowsValueMap.add("Start");  
                if (supportsEndArrow) arrowsValueMap.add("End");  
                if (supportsStartArrow && supportsEndArrow) arrowsValueMap.add("Both");  
                form.getField("arrows").setValueMap(arrowsValueMap.toArray(new String[] {}));  
      
                // Update the form with current values  
                String arrows = (item.getStartArrow() != null && item.getEndArrow() != null ? "Both" : (item.getStartArrow() != null? "Start" : (item.getEndArrow() != null ? "End" : "None")));  
                form.setValue("lineColor", item.getLineColor());  
                form.setValue("fillColor", item.getFillColor());  
                form.setValue("arrows", arrows);  
            }  
        }
      
       
      
        private EditNode[] getSelectedNodes() {  
            return (editContext != null ? editContext.getSelectedEditNodes() : new EditNode[] {});  
           // return null;
        }  
      
        private void removeSelectedItems() {  
            EditNode[] selection = this.getSelectedNodes();  
            for (EditNode editNode : selection) {  
                // Remove node from editContext and destroy it  
                this.editContext.removeNode(editNode);  
                editNode.getDrawItemLiveObject().destroy();  
            }  
        }  
      
          
    }  

