70001968 Custom Action Line example

Article 70001968
Type HowTo
Product WebJS
Version 8
Date Added 5/11/2021 12:00:00 AM
Fixed 9.9002.0.2 (5/17/2021 12:00:00 AM)
Submitted by Bogumil Styczen

Summary

In the Custom Action Lines example we will show how we can create a custom action polyline and let the user decide on the fly if he wants to draw a closed polyline or not, be able to undo every segment of the polyline, or cancel the whole command action.

Solution

In this example we will show how we can create a custom action polyline and let the user decide on the fly if he wants to draw a closed polyline or not,
be able to undo every segment of the polyline, or cancel the whole command action.
In the solution you will find the necessary code with comments that we need to achive what we want so imagine that we have on our HTML page a canvas, a butoon which starts a new custom polyline
and a command list from where the user selects if he wants to close the polyline, undo a segment, finish the command or cancel the operation.
You will find the whole example on our WebLibrary Samples -> Sample 24.



        var vdcanvas; // keep the vdcanvas control global for quick access inside the functions since it is the only one in the this page

        function vdrawInitPageLoad() {//Intiallize theweb control inside this function.It must be called inside onload event of this page
            vdcanvas = vdmanager.AttachCanvas("canvas"); //create a new web control andattch it to the canvas elemement
            vdcanvas.vdPrompt = _vdPrompt;
            vdcanvas.New();// open a new empty drawing
        }
        function _vdPrompt(ender, msg) {
            printInfo('prompt', msg);
        }
        function printInfo(infoId, text) {

            if (text === undefined || text === null) return;
            var info = document.getElementById(infoId);
            if (info == undefined) return;
            info.innerHTML = ":" + text ;
        }

        //
        function customlines() {
            vdcanvas.ActiveAction().cancel();// cancel every other action
            vdcanvas.GetUserPoint(_onActioncmdLineStateChanged); // call the GetUserPoint() and begin a user action in order to set the first point of the line.
        }

        function MyCustomActionRefresh(action) {
            if (action.mycustomdata && action.mycustomdata.VertexList.Items.length > 1) {
                
                action.draw(true); // refresh and stop diplaying the last point
                action.draw(); // refresh and diplay the user line with the start point, the previous point of the polyline
            }
        }
        function MyCustomActionDoExtraDraw(action) {// here we will diplay on the user line, the distance between the reference point and the cursor position and also the angle
            var vdraw = action.vdrawOwner();
            var ptref = action.ReferencePoint; //get the reference point in world Coordinate System
            if (!ptref || !action.mycustomdata) return; //do nothing if the action is not waiting for a user reference point
            var ptcur = action.CurrentPoint; //get the current mouse location in world Coordinate system
            var dist = vdgeo.Distance3D(ptref, ptcur); //get the distance between reference and current point in drawing units
            var angle = vdgeo.GetAngle(ptref, ptcur); //get the angle counter-clockwise relative to x direction in radians
            var angledeg = vdgeo.RadiansToDegrees(angle); //convert the angle in degrees
            if (angle > vdgeo.HALF_PI && angle < vdgeo.VD_270PI) angle += vdgeo.PI; //change the angle to be horizondally readable          
            //create a temporary text and draw it in the center of user raber reference line
            var midpt = vdgeo.MidPoint(ptref, ptcur);
            var txtSize = vdraw.GetPixelSize() * 15;
            var textvalue = dist.toFixed(2) + '<' + angledeg.toFixed(2);
            var txt = vdraw.AddText(textvalue, txtSize, midpt, vdConst.VdConstHorJust_VdTextHorCenter, vdConst.VdConstVerJust_VdTextVerBottom, angle, false, {});
            txt.PenColor = vdConst.colorFromString("255,255,0");
            vdraw.DrawEntity(txt);
        }
        function MyCustomActionFinish(action) {
            var vdraw = action.vdrawOwner();
            var layout = vdraw.GetActiveLayout();
            if (action.mycustomdata && action.mycustomdata.VertexList.Items.length > 1) {
                // if there is a polyline object and has VertexList.Items.length > 1
                action.cancel(); // we cancel the action

                // add the figure on the entities of the active layout which is also will get a new handle id. draw it and refresh.
                vdraw.scriptCommand.RegisterFigure(action.mycustomdata, true, true);              
            }
            action.customMode = undefined;
            action.mycustomdata = undefined;

        }

        // here starts the user action. The first time the 'status' will be 'start'
        function _onActioncmdLineStateChanged(action, status) {

            var pt; // a point variable
            var vdraw = action.vdrawOwner(); // get the vdObject from action.vdrawOwner()
            if (!action.customMode) action.customMode = 'PickStart'; 

            if (action.customMode == 'PickStart') {// for the first point
                if (status == 'start') {
                    vdraw.Prompt('pick start point');
                } else if (status == 'end') {// if the status is end, clear the prompt
                    vdraw.Prompt('');
                    if (!action.IsCanceled()) {// if the action is not canceled by user
                        pt = action.SelectedPoint();// the pt value will be the selected user point
                        action.customMode = 'PickNext'; //change the customMode see next if
                        action.mycustomdata = vdraw.AddPolyline([pt], false, {});// create a new polyline, we do not add it on the entities of the active layout by using the '{}' 
                        //and we do not draw it because later on the finish action we will draw it and add it on the entities
                        vdraw.GetUserLine(_onActioncmdLineStateChanged, pt); //start a new user get reference point
                    } else {
                        //action canceled probably by right click click nothing will added command finished
                        MyCustomActionFinish(action);
                    }

                }
            } else if (action.customMode == 'PickNext') {
                if (status == 'start') {
                    vdraw.Prompt('pick next point or Close or Undo');

                } else if (status == 'end') {
                    vdraw.Prompt('');
                    if (!action.IsCanceled()) {// if the action is not canceled by user
                        pt = action.SelectedPoint(); // the pt value will be the selected user point
                        action.mycustomdata.VertexList.Items.push([pt[X], pt[Y], pt[Z], 0.0]); // push the new point into the VertexList of the polyline
                        vdraw.UpdateFig(action.mycustomdata);//update the polyline
                        vdraw.GetUserLine(_onActioncmdLineStateChanged, pt); //start a new user get reference point
                    } else {
                        MyCustomActionFinish(action); //action canceled probably by right click click nothing will added command finished
                    }
                } else if (status == 'draw') {
                    var render = action.render;// get the render from the action
                    pt = action.DrawPoint();// draw the action point
                    action.mycustomdata.VertexList.Items.push([pt[X], pt[Y], pt[Z], 0.0]);//push the new point into the VertexList of the polyline
                    vdraw.UpdateFig(action.mycustomdata); //update the polyline
                    vdraw.DrawEntity(action.mycustomdata, render); //draw the polyline
                    action.mycustomdata.VertexList.Items.pop(); //pop the 'pt' from the VertexList of the polyline
                    vdraw.UpdateFig(action.mycustomdata); //update the polyline
                    MyCustomActionDoExtraDraw(action); // call the MyCustomActionDoExtraDraw which displays the distance and the angle between a reference point and the cursor position
                } else if (status == 'close') {// if the user choose 'close' for the polyline
                    if (action.mycustomdata.VertexList.Items.length > 2) {
                        action.mycustomdata.VertexList.Items.push(action.mycustomdata.VertexList.Items[0]);// we push to the VertexList a new point which is the start point of the polyline
                        vdraw.UpdateFig(action.mycustomdata); //update the polyline
                        MyCustomActionFinish(action);// finish the action
                    }

                } else if (status == 'undo') {// when user choose undo and the polylinr VertexList.Items.length > 0
                    if (action.mycustomdata.VertexList.Items.length > 0) {
                        action.mycustomdata.VertexList.Items.pop();// we pop the last added point
                        vdraw.UpdateFig(action.mycustomdata); //update the polyline
                       
                    }
                    if (action.mycustomdata.VertexList.Items.length == 0) {//when there is no point into the VertexList
                        MyCustomActionFinish(action);// we finish the action
                        customlines();//and start a new user action for the first point of a new polyline
                    } else {
                         // there is a point to undo, we set as reference point the last added point on the VertexList
                        action.ReferencePoint = action.mycustomdata.VertexList.Items[action.mycustomdata.VertexList.Items.length - 1];                                      
                        MyCustomActionRefresh(action);// refresh the display 
                    }
                }
            }

        }
        //the command list from where the user chooses the prefered action
        function action_execute(commandlist) {
            var command = commandlist.value;
            commandlist.value = "none";
            var myaction = vdcanvas.ActiveAction();
            if (!myaction.customMode) return;

            switch (command) {
                case "cancel":
                    vdcanvas.ActiveAction().cancel();
                    break;
                case "close":
                    _onActioncmdLineStateChanged(myaction, 'close');
                    break;
                case "undo":
                    _onActioncmdLineStateChanged(myaction, 'undo');
                    break;
                default:
                    break;


            }

        }
       

Send comments on this topic.