开发手册 - SimpleComposer界面开发 - CAD工具

来自MDCS wiki
跳到导航 跳到搜索

SimpleComposer支持自定义CAD工具。开发者可以设计CAD工具来自动写入标签、调整站点姿态等,从而方便现场人员使用系统。开发者只需要在插件里声明一个公共类,继承CADTool,并增加CADToolDescriptor即可在界面中添加该工具。添加的CAD工具位置如下图所示:

CADTool放置位置

相关的接口如下:

    public abstract class CADEventHandler
    {
        public virtual void OnSelect() //当选中某个元素的时候触发

        public virtual void OnDelete(Prop props) //当某个元素删除时触发

        public virtual void OnAdd(Prop prop) //当某个元素新建的时候触发
    }

    public abstract class CADTool
    {
        public abstract void Invoke();
    }
    public class CADToolDescriptor : Attribute
    {
        public enum Place
        {
            SceneTool, //场景工具,显示在场景面板-工具下拉菜单中
            CarTool, //车辆工具,显示在车辆面板-工具下拉菜单中
            ProjectTool //工程工具,显示在“插件”按钮中
        }
        public string name;
        public string shortcut;
        public Place place = Place.SceneTool;
    }

以下是一个例子

[CADToolDescriptor(name = "批量增删改字段", shortcut = "Ctrl+Alt+M")]
public class BatchFields:CADTool
{
    public override void Invoke()
    {
        if (InputBox.ShowDialog("输入要增加或修改的字段名称和值,格式为\r\n[字段]:[值],若要删除只需要写字段名", "参数增删改", "name:val") ==
            DialogResult.OK)
        {
            foreach (var sel in SimpleMonitor.selected)
            {
                var obj = sel;
                var dict = (Dictionary<string, string>)obj.GetType().GetField("fields").GetValue(obj);
                var idx = InputBox.ResultValue.IndexOf(':');
                if (idx == -1)
                {
                    // remove.
                    dict.Remove(InputBox.ResultValue);
                    continue;
                }

                var key = InputBox.ResultValue.Substring(0, idx);
                var val = InputBox.ResultValue.Substring(idx + 1);
                var fi = obj.GetType().GetField(key);
                if (fi != null)
                {
                    fi.SetValue(obj, TypeDescriptor.GetConverter(fi.FieldType).ConvertFromString(val));
                }
                else
                    dict[key] = val;
            }
        }
    }
}

注:以上例子第9行处使用了SimpleMonitor.selected来访问选择的元素。SimpleMonitor.selected也可以用来写入应该选择哪些元素。 CADTool中可以使用所有SimpleMonitor支持的UI操作类型。比如:

var target = await Program.UI.getPoint(); //用于获取一个位置。
var site = await Program.UI.getPoint(new getPointOptions() { site = true }); //获取一个位置,这个位置必须是站点
var shelfLane = await Program.UI.GetTrack(true); //获取一个路段。参数true表示要将这个路段放入选择

更复杂的鼠标事件

如果获取位置/路段等方法不够用,也可以使用全功能的鼠标注册事件(较为繁琐):registerDownevent:

[MethodMember(name = "精确移动", desc = "选择一个方向,然后输入移动距离")]
public async void PreciseMove()
{
    var pp = getPainter("cad");
    SimpleMonitor.registerDownevent((_,_) =>
    {
        if (InputBox.ShowDialog("输入位移距离,单位mm", "位移", "0") != DialogResult.OK) return;
        var str = InputBox.ResultValue;
        if (str == null || !float.TryParse(str, out var d)) return;
        var dx = mouseX - x;
        var dy = mouseY - y;
        var dd = Math.Sqrt(dx * dx + dy * dy);
        dx /= (float)dd;
        dy /= (float)dd;
        x += dx * d;
        y += dy * d;
        clearDownevent();
        Task.Delay(1000).ContinueWith(p => pp.clear());
    }, cancelEvent: () => { pp.clear(); }, preselect: (sender, args) =>
    {
        pp.clear();
        pp.drawLine(Pens.Red, x, y, mouseX, mouseY);
    });
}

registerDownevent的说明如下:

public static void registerDownevent(
UIMouseEvent start=null, //鼠标点击时触发。
Action cancelEvent = null, //动作取消时触发(点击右键为取消),一般还要调用clearDownevent()来清除鼠标事件。
UIMouseEvent drag = null, //拖动时触发
UIMouseEvent release = null, //动作结束时触发
UIMouseEvent preselect = null //刚开始拖动时触发
)
//可以使用SimpleMonitor.mouseX/mouseY来获取鼠标在地图上的坐标,