Package org.geoforge.worldwind.builder.editor

Source Code of org.geoforge.worldwind.builder.editor.GfrEditorObjShpPlnAbs

package org.geoforge.worldwind.builder.editor;

/* Copyright (C) 2001, 2011 United States Government as represented by
the Administrator of the National Aeronautics and Space Administration.
All Rights Reserved.
*/

import gov.nasa.worldwind.View;
import gov.nasa.worldwind.WorldWind;
import gov.nasa.worldwind.WorldWindow;
import gov.nasa.worldwind.avlist.AVKey;
import gov.nasa.worldwind.geom.LatLon;
import gov.nasa.worldwind.geom.Line;
import gov.nasa.worldwind.geom.Position;
import gov.nasa.worldwind.geom.Vec4;
import gov.nasa.worldwind.globes.Globe;
import gov.nasa.worldwind.layers.AbstractLayer;
import gov.nasa.worldwind.pick.PickedObjectList;
import gov.nasa.worldwind.render.*;
import gov.nasa.worldwind.render.airspaces.editor.AirspaceEditorUtil;
import gov.nasa.worldwind.render.markers.BasicMarkerAttributes;
import gov.nasa.worldwind.render.markers.Marker;
import gov.nasa.worldwind.render.markers.MarkerRenderer;
import gov.nasa.worldwind.util.Logging;
import gov.nasa.worldwind.util.UnitsFormat;
import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.util.ArrayList;
import org.geoforge.java.awt.font.GfrUtilFont;
import org.geoforge.lang.handler.IGfrHandlerLifeCycleObject;
import org.geoforge.worldwind.builder.marker.GfrMrkMoveAbs;
import org.geoforge.worldwind.builder.marker.GfrMrkMoveHoriz;
import org.geoforge.worldwind.builder.marker.GfrMrkMoveVert;

/**
* An abstract class defining common functionality and fields for editors used in the RigidShapeBuilder example.  These
* include field variables and getters and setters for the shape's annotations that are displayed during editing (and
* related labels), references to the current WorldWindow and mouse location, flags indicating whether the editor is
* currently _blnArmed and whether annotations should be shown, as well as fields indicating the current action being
* performed, the current _strModeEdit, and the current _intModeAltitude.
* <p/>
* In addition, the class contains several helper functions related to displaying annotations, which all editors should
* be able to do.
*
* @author ccrick
* @version $Id: AbstractShapeEditor.java 1 2011-07-16 23:22:47Z dcollins $
*
* modified: bantchao
*/

abstract public class GfrEditorObjShpPlnAbs extends AbstractLayer implements
        IGfrHandlerLifeCycleObject,
        MouseListener,
        MouseMotionListener
{
   // BEG PLINE
  
   final static protected String MOVE_POLYGON_ACTION = "EditorShapePolylineAbs.MovePolygonAction";
   
    protected GfrMrkMoveAbs _cpmActive_;
    protected AbstractShape _pol_ = null;
   

    protected MarkerRenderer _mrr;
    protected java.util.List<Marker> _lstMarkerControlPoints;

    protected BasicMarkerAttributes _bmaControlVertex;
    protected BasicMarkerAttributes _bmaControlHeight;

    protected int _intIndexControlPointActive;
  
    abstract protected boolean removeVertex(GfrMrkMoveHoriz vertexToRemove);
    abstract protected void setHeightPolyline(Point previousMousePoint, Point mousePoint);
    abstract protected void addVertex(Point mousePoint);
    abstract protected void _assembleVertexControlPoints_(DrawContext dc);
    abstract protected void moveControlPoint(GfrMrkMoveHoriz controlPoint, Point lastMousePoint, Point moveToPoint);
   
    public void setPolyline(AbstractShape shp)
    {
        if (shp == null)
        {
            String message = "nullValue.Shape";
            Logging.logger().severe(message);
            throw new IllegalArgumentException(message);
        }

        this._pol_ = shp;
    }
  
  
  
  
   // END PLINE
  
  
  
  
    /**
     * Labels used in the annotations which are displayed during editing to show the current value of various shape
     * parameters.  Actual label values are retrieved from the World Wind message resource bundle.
     */
    public static final String ANGLE_LABEL = "MeasureTool.AngleLabel";
    public static final String AREA_LABEL = "MeasureTool.AreaLabel";
    public static final String LENGTH_LABEL = "MeasureTool.LengthLabel";
    public static final String PERIMETER_LABEL = "MeasureTool.PerimeterLabel";
    public static final String RADIUS_LABEL = "MeasureTool.RadiusLabel";
    public static final String HEIGHT_LABEL = "MeasureTool.HeightLabel";
    public static final String WIDTH_LABEL = "MeasureTool.WidthLabel";
    public static final String HEADING_LABEL = "MeasureTool.HeadingLabel";
    public static final String TILT_LABEL = "MeasureTool.TiltLabel";
    public static final String ROLL_LABEL = "MeasureTool.RollLabel";
    public static final String EAST_SKEW_LABEL = "MeasureTool.EastSkewLabel";
    public static final String NORTH_SKEW_LABEL = "MeasureTool.NorthSkewLabel";
    public static final String CENTER_LATITUDE_LABEL = "MeasureTool.CenterLatitudeLabel";
    public static final String CENTER_LONGITUDE_LABEL = "MeasureTool.CenterLongitudeLabel";
    public static final String CENTER_ALTITUDE_LABEL = "MeasureTool.CenterAltitudeLabel";
    public static final String LATITUDE_LABEL = "MeasureTool.LatitudeLabel";
    public static final String LONGITUDE_LABEL = "MeasureTool.LongitudeLabel";
    public static final String ALTITUDE_LABEL = "MeasureTool.AltitudeLabel";
    public static final String ACCUMULATED_LABEL = "MeasureTool.AccumulatedLabel";
    public static final String MAJOR_AXIS_LABEL = "MeasureTool.MajorAxisLabel";
    public static final String MINOR_AXIS_LABEL = "MeasureTool.MinorAxisLabel";

    protected WorldWindow _wwd;
    protected Point _pntMouse;

    protected ScreenAnnotation _san;  // an _san for displaying current values of various shape parameters
    protected AnnotationAttributes _aas; // attributes controlling the look-and-feel of the _san
   
    protected UnitsFormat _uft;  // class for uniformly formatting the units used in _san values

    protected boolean _blnArmed;
    protected boolean _blnShowAnnotation = true;
    protected boolean _blnAboveGround = false;

    protected long _lngFrameTimestamp = -1;
    protected String _strActionActive;

    protected String _strModeEdit;
    protected int _intModeAltitude = WorldWind.ABSOLUTE;
   
 
   
    protected GfrEditorObjShpPlnAbs()
    {
        super();
       
        // BEG PLINE
        this._mrr = new MarkerRenderer();
        this._mrr.setKeepSeparated(false);
        this._mrr.setOverrideMarkerElevation(false);
        this._mrr.setEnablePickSizeReturn(true);
       
        // END PLINE
    }
   
    @Override
    public void mouseMoved(MouseEvent e) {}
   
    @Override
    public void mouseEntered(MouseEvent e) {}
   
    @Override
    public void mouseExited(MouseEvent e) {}
   
    @Override
    public boolean init()
    {
       // BEG PLINE
       this.assembleMarkerAttributes();
        this._initializeAnnotation();
        this._uft = new UnitsFormat();
      
       // END PLINE
        return true;
    }
   
    @Override
    public void destroy()
    {
       // BEG PLINE
       if (this._mrr != null)
        {
            this._mrr = null;
        }
      
       // END PLINE
    }
   
    public String getEditMode()
    {
        return this._strModeEdit;
    }


    public WorldWindow getWorldWindow()
    {
        return this._wwd;
    }

    public void setWorldWindow(WorldWindow wwd)
    {
        if (this._wwd == wwd)
            return;

        if (this._wwd != null)
        {
            this._wwd.getInputHandler().removeMouseListener(this);
            this._wwd.getInputHandler().removeMouseMotionListener(this);
        }

        this._wwd = wwd;

        if (this._wwd != null)
        {
            this._wwd.getInputHandler().addMouseListener(this);
            this._wwd.getInputHandler().addMouseMotionListener(this);
        }
    }

    public boolean isArmed()
    {
        return this._blnArmed;
    }

    public void setArmed(boolean armed)
    {
        this._blnArmed = armed;
    }

    public int getAltitudeMode()
    {
        return this._intModeAltitude;
    }

    public void setAltitudeMode(int altitudeMode)
    {
        this._intModeAltitude = altitudeMode;
    }

    public boolean isShowAnnotation()
    {
        return this._blnShowAnnotation;
    }

    public void setShowAnnotation(boolean state)
    {
        this._blnShowAnnotation = state;
    }

    public boolean isAboveGround()
    {
        return this._blnAboveGround;
    }

    public void setAboveGround(boolean state)
    {
        this._blnAboveGround = state;
    }

    public String getLabel(String labelName)
    {
        if (labelName == null)
        {
            String msg = Logging.getMessage("nullValue.LabelName");
            Logging.logger().severe(msg);
            throw new IllegalArgumentException(msg);
        }

        String label = this.getStringValue(labelName);

        if (label != null)
            return label;
        else
        {
            if (this._uft == null)
                this._uft = new UnitsFormat();

            return this._uft.getStringValue(labelName);
        }
    }

    public void setLabel(String labelName, String label)
    {
        if (labelName != null && labelName.length() > 0)
            this.setValue(labelName, label);
    }

    protected void _setAnnotationAttributes(AnnotationAttributes attributes)
    {
        this._aas = attributes;
    }

    protected AnnotationAttributes _getAnnotationAttributes()
    {
        return this._aas;
    }

   

    protected void _initializeAnnotation()
    {
        // Annotation attributes
        this._setInitialLabels();

        this._aas = new AnnotationAttributes();
        this._aas.setFrameShape(AVKey.SHAPE_NONE);
        this._aas.setInsets(new Insets(0, 0, 0, 0));
        this._aas.setDrawOffset(new Point(0, 10));
        this._aas.setTextAlign(AVKey.CENTER);
        this._aas.setEffect(AVKey.TEXT_EFFECT_OUTLINE);
       
        Font fntAas = GfrUtilFont.s_get(Font.BOLD, 14);
        this._aas.setFont(fntAas);
       
        this._aas.setTextColor(Color.WHITE);
        this._aas.setBackgroundColor(Color.BLACK);
        this._aas.setSize(new Dimension(220, 0));

        this._san = new ScreenAnnotation("", new Point(0, 0), this._aas);
        this._san.getAttributes().setVisible(false);
        this._san.getAttributes().setDrawOffset(null); // use defaults
    }

    protected void _setInitialLabels()
    {
        this.setLabel(ACCUMULATED_LABEL, Logging.getMessage(ACCUMULATED_LABEL));
        this.setLabel(ANGLE_LABEL, Logging.getMessage(ANGLE_LABEL));
        this.setLabel(AREA_LABEL, Logging.getMessage(AREA_LABEL));
        this.setLabel(CENTER_LATITUDE_LABEL, Logging.getMessage(CENTER_LATITUDE_LABEL));
        this.setLabel(CENTER_LONGITUDE_LABEL, Logging.getMessage(CENTER_LONGITUDE_LABEL));
        this.setLabel(CENTER_ALTITUDE_LABEL, Logging.getMessage(CENTER_ALTITUDE_LABEL));
        this.setLabel(HEADING_LABEL, Logging.getMessage(HEADING_LABEL));
        this.setLabel(TILT_LABEL, Logging.getMessage(TILT_LABEL));
        this.setLabel(ROLL_LABEL, Logging.getMessage(ROLL_LABEL));
        this.setLabel(EAST_SKEW_LABEL, Logging.getMessage(EAST_SKEW_LABEL));
        this.setLabel(NORTH_SKEW_LABEL, Logging.getMessage(NORTH_SKEW_LABEL));
        this.setLabel(HEIGHT_LABEL, Logging.getMessage(HEIGHT_LABEL));
        this.setLabel(LATITUDE_LABEL, Logging.getMessage(LATITUDE_LABEL));
        this.setLabel(LONGITUDE_LABEL, Logging.getMessage(LONGITUDE_LABEL));
        this.setLabel(ALTITUDE_LABEL, Logging.getMessage(ALTITUDE_LABEL));
        this.setLabel(LENGTH_LABEL, Logging.getMessage(LENGTH_LABEL));
        this.setLabel(MAJOR_AXIS_LABEL, Logging.getMessage(MAJOR_AXIS_LABEL));
        this.setLabel(MINOR_AXIS_LABEL, Logging.getMessage(MINOR_AXIS_LABEL));
        this.setLabel(PERIMETER_LABEL, Logging.getMessage(PERIMETER_LABEL));
        this.setLabel(RADIUS_LABEL, Logging.getMessage(RADIUS_LABEL));
        this.setLabel(WIDTH_LABEL, Logging.getMessage(WIDTH_LABEL));
    }

    protected boolean _arePositionsRedundant(Position posA, Position posB)
    {
        if (posA == null || posB == null)
            return false;

        String aLat = this._uft.angleNL("", posA.getLatitude());
        String bLat = this._uft.angleNL("", posB.getLatitude());

        if (!aLat.equals(bLat))
            return false;

        String aLon = this._uft.angleNL("", posA.getLongitude());
        String bLon = this._uft.angleNL("", posB.getLongitude());

        if (!aLon.equals(bLon))
            return false;

        String aAlt = this._uft.lengthNL("", posA.getAltitude());
        String bAlt = this._uft.lengthNL("", posB.getAltitude());

        return aAlt.equals(bAlt);
    }
   
   
   
    // BEG PLINE
    //*************************************************************
    // ***************** Polygon manipulation *********************
    //*************************************************************
   
   

    protected void movePolyline(Point previousMousePoint, Point mousePoint)
    {
        // Intersect a ray through each mouse point, with a geoid passing through the reference elevation.
        // If either ray fails to intersect the geoid, then ignore this event. Use the difference between the two
        // intersected positions to move the control point's location.

        View view = this._wwd.getView();
        Globe globe = this._wwd.getModel().getGlobe();

        Position refPos = this._pol_.getReferencePosition();
        if (refPos == null)
            return;

        Line ray = view.computeRayFromScreenPoint(mousePoint.getX(), mousePoint.getY());
        Line previousRay = view.computeRayFromScreenPoint(previousMousePoint.getX(), previousMousePoint.getY());

        Vec4 vec = AirspaceEditorUtil.intersectGlobeAt(this._wwd, refPos.getElevation(), ray);
        Vec4 previousVec = AirspaceEditorUtil.intersectGlobeAt(this._wwd, refPos.getElevation(), previousRay);

        if (vec == null || previousVec == null)
        {
            return;
        }

        Position pos = globe.computePositionFromPoint(vec);
        Position previousPos = globe.computePositionFromPoint(previousVec);
        LatLon change = pos.subtract(previousPos);

        this._pol_.move(new Position(change.getLatitude(), change.getLongitude(), 0.0));
    }
   
    // ----
   
    protected String formatMeasurements(Position pos)
    {
        StringBuilder sb = new StringBuilder();


        // if "activeControlPoint" is in fact one of the control points
        if (!this._arePositionsRedundant(pos, this._pol_.getReferencePosition()))
        {
            sb.append(this._uft.angleNL(this.getLabel(LATITUDE_LABEL), pos.getLatitude()));
            sb.append(this._uft.angleNL(this.getLabel(LONGITUDE_LABEL), pos.getLongitude()));
            sb.append(this._uft.lengthNL(this.getLabel(ALTITUDE_LABEL), pos.getAltitude()));
        }

        // if "activeControlPoint" is the shape itself
        if (this._pol_.getReferencePosition() != null)
        {
            sb.append(this._uft.angleNL(this.getLabel(CENTER_LATITUDE_LABEL),
                this._pol_.getReferencePosition().getLatitude()));
            sb.append(this._uft.angleNL(this.getLabel(CENTER_LONGITUDE_LABEL),
                this._pol_.getReferencePosition().getLongitude()));
            sb.append(this._uft.lengthNL(this.getLabel(CENTER_ALTITUDE_LABEL),
                this._pol_.getReferencePosition().getAltitude()));
        }

        return sb.toString();
    }
   
 
    protected void _assembleHeightControlPoints_()
    {
        if (this._lstMarkerControlPoints.size() < 2)
            return;

        // Add one control point for the height between the first and second vertices.
        // TODO: ensure that this control point is visible
        Position firstVertex = this._lstMarkerControlPoints.get(0).getPosition();
        Position secondVertex = this._lstMarkerControlPoints.get(1).getPosition();

        Globe globe = this._wwd.getModel().getGlobe();

        // Get cartesian points for the vertices
        Vec4 firstPoint = globe.computePointFromPosition(firstVertex);
        Vec4 secondPoint = globe.computePointFromPosition(secondVertex);

        // Find the midpoint of the line segment that connects the vertices
        Vec4 halfwayPoint = firstPoint.add3(secondPoint).divide3(2.0);

        Position halfwayPosition = globe.computePositionFromPoint(halfwayPoint);
       
        this._lstMarkerControlPoints.add(new GfrMrkMoveVert(halfwayPosition, halfwayPoint,
            this._bmaControlHeight, this._lstMarkerControlPoints.size()));
    }

   
 
    public void setEditMode(String editMode)
    {
       // void
    }
   
    public void clearIt()
    {
        this._lstMarkerControlPoints.clear();
     
    }

    protected void _assembleControlPoints_(DrawContext dc)
    {
        // Control points are re-computed each frame
       
        if (this._lstMarkerControlPoints!=null && this._lstMarkerControlPoints.size() > 0)
        {
            // TODO: clean-up
            this._lstMarkerControlPoints.clear();
        }
       
        this._lstMarkerControlPoints = new ArrayList<Marker>();

        this._assembleVertexControlPoints_(dc);
        this._assembleHeightControlPoints_();
    }


    @Override
    protected void doRender(DrawContext dc)
    {
        if (this._lngFrameTimestamp != dc.getFrameTimeStamp())
        {
            this._assembleControlPoints_(dc);
            this._lngFrameTimestamp = dc.getFrameTimeStamp();
        }

        this._mrr.render(dc, this._lstMarkerControlPoints);

        if (this._san != null && isShowAnnotation())
        {
            this._san.render(dc);
        }
    }

    @Override
    protected void doPick(DrawContext dc, Point point)
    {
        this.doRender(dc); // Same logic for picking and rendering
    }

    protected void assembleMarkerAttributes()
    {
        this._bmaControlVertex = new BasicMarkerAttributes();
        this._bmaControlVertex.setMaterial(Material.ORANGE);

        this._bmaControlHeight = new BasicMarkerAttributes();
        this._bmaControlHeight.setMaterial(Material.RED);
    }

    //*******************************************************
    // ***************** Event handling *********************
    //*******************************************************

 
    @Override
    public void mousePressed(MouseEvent e)
    {
        this._pntMouse = e.getPoint();

        Object topObject = null;
        PickedObjectList pickedObjects = this._wwd.getObjectsAtCurrentPosition();
        if (pickedObjects != null)
            topObject = pickedObjects.getTopObject();

        if (topObject instanceof GfrMrkMoveAbs)
        {
            this._cpmActive_ = (GfrMrkMoveAbs) topObject;
            this._strActionActive = this._cpmActive_.getType();

            setShowAnnotation(true);
            updateAnnotation(this._cpmActive_.getPosition());

            // update controlPointIndex;
            int i = 0;
           
            for (Marker controlPoint : this._lstMarkerControlPoints)
            {
                if (controlPoint.equals(topObject))
                    break;
                i++;
            }
           
            this._intIndexControlPointActive = i;
            e.consume();
        }
       
        else if (topObject == this._pol_)
        {
            this._strActionActive = MOVE_POLYGON_ACTION;

            // set the shape to be the "active control point"
            this._intIndexControlPointActive = -1;

            setShowAnnotation(true);
            updateAnnotation(this._pol_.getReferencePosition());
            e.consume();
        }
    }

    @Override
    public void mouseDragged(MouseEvent e)
    {
        Point lastMousePoint = this._pntMouse;
        this._pntMouse = e.getPoint();

        if (lastMousePoint == null)
            lastMousePoint = this._pntMouse;

        // update _san
        if (isShowAnnotation())
        {
            if (this._intIndexControlPointActive < 0)
                updateAnnotation(this._pol_.getReferencePosition());
            else if (this._lstMarkerControlPoints != null)
                updateAnnotation(this._lstMarkerControlPoints.get(this._intIndexControlPointActive).getPosition());
        }

        if (GfrMrkMoveHoriz.MOVE_VERTEX_ACTION.equals(this._strActionActive))
        {
            if (this._cpmActive_ instanceof GfrMrkMoveHoriz)
            {
                this.moveControlPoint((GfrMrkMoveHoriz) this._cpmActive_, lastMousePoint, this._pntMouse);
                e.consume();
            }
        }
       
        else if (GfrMrkMoveVert.CHANGE_HEIGHT_ACTION.equals(this._strActionActive))
        {
            if (this._cpmActive_ instanceof GfrMrkMoveVert)
            {
                this.setHeightPolyline(lastMousePoint, this._pntMouse);
                e.consume();
            }
        }
       
        else if (MOVE_POLYGON_ACTION.equals(this._strActionActive))
        {
            this.movePolyline(lastMousePoint, this._pntMouse);
            e.consume();
        }
    }
  
    @Override
    public void mouseReleased(MouseEvent e)
    {
        this._strActionActive = null;

        setShowAnnotation(false);
        updateAnnotation(null);
        e.consume();
       
        this._cpmActive_ = null;
    }

   

   
  

    /**
     * Determine the point at which a ray intersects a the globe at the elevation of the polygon.
     *
     * @param ray Ray to intersect with the globe.
     *
     * @return The point at which the ray intersects the globe at the elevation of the polygon.
     */
    protected Vec4 _intersectPolygonAltitudeAt(Line ray)
    {
        //  If there are control points computed, use the elevation of the first control point as the polygon elevation.
        // Otherwise, if there are no control points, intersect the globe at sea level
        double elevation = 0.0;
        if (this._lstMarkerControlPoints.size() > 0)
        {
            elevation = this._lstMarkerControlPoints.get(0).getPosition().getElevation();
        }
       
        return AirspaceEditorUtil.intersectGlobeAt(this._wwd, elevation, ray);
    }


    public void updateAnnotation(Position pos)
    {
        if (pos == null)
        {
            if (this._san != null)
               this._san.getAttributes().setVisible(false);
           
            return;
        }

        String displayString = this._getDisplayString_(pos);

        if (displayString == null)
        {
            this._san.getAttributes().setVisible(false);
            return;
        }

        this._san.setText(displayString);

        Vec4 screenPoint = this._computeAnnotationPosition_(pos);
        if (screenPoint != null)
            this._san.setScreenPoint(new Point((int) screenPoint.x, (int) screenPoint.y));

        this._san.getAttributes().setVisible(true);
    }
   
    //*******************************************************
    // ***************** Event handling *********************
    //*******************************************************
   
    @Override
    public void mouseClicked(MouseEvent e)
    {
        if (this.isArmed())
        {
            if (e.getButton() == MouseEvent.BUTTON1 && e.getClickCount() == 2)
            {
                Object topObject = null;
                PickedObjectList pickedObjects = this._wwd.getObjectsAtCurrentPosition();
                if (pickedObjects != null)
                    topObject = pickedObjects.getTopObject();

                if (topObject instanceof GfrMrkMoveHoriz)
                {
                    if (this.removeVertex((GfrMrkMoveHoriz) topObject))
                        e.consume();
                }
               
                // !!!!
               
                else if (topObject instanceof GfrMrkMoveVert)
                {
                    // -----
                     System.out.println("topObject instanceof MrkMoveVert, preventing remove");
                }
               
                else
                {
                    this.addVertex(e.getPoint());
                    e.consume();
                }
            }
        }
    }
   
    // ----
    // beg private

    private Vec4 _computeAnnotationPosition_(Position pos)
    {
        Vec4 surfacePoint = this._wwd.getSceneController().getTerrain().getSurfacePoint(
            pos.getLatitude(), pos.getLongitude());
       
        if (surfacePoint == null)
        {
            Globe globe = this._wwd.getModel().getGlobe();
           
            surfacePoint = globe.computePointFromPosition(pos.getLatitude(), pos.getLongitude(),
                globe.getElevation(pos.getLatitude(), pos.getLongitude()));
        }

        return this._wwd.getView().project(surfacePoint);
    }

    private String _getDisplayString_(Position pos)
    {
        String displayString = null;

        if (pos != null)
        {
            displayString = this.formatMeasurements(pos);
        }

        return displayString;
    }
   
   
    // END PLINE
}
TOP

Related Classes of org.geoforge.worldwind.builder.editor.GfrEditorObjShpPlnAbs

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.