コード例 #1
0
    private void _tv_ItemClick(object sender, TVItemEventArgs e)
    {
        if (e.ModifierKeys != 0 || e.ClickCount != 1)
        {
            return;
        }
        var t = e.Item as RunningTask;
        var f = t.f;

        switch (e.MouseButton)
        {
        case MouseButton.Left:
            App.Model.SetCurrentFile(f);
            break;

        case MouseButton.Right:
            _tv.Select(t);
            var name = f.DisplayName;
            var m    = new popupMenu {
                RawText = true
            };
            m["End task  '" + name + "'"] = _ => App.Tasks.EndTask(t);
            m["End all  '" + name + "'"]  = _ => App.Tasks.EndTasksOf(f);
            m.Separator();
            m["Close\tM-click", disable : null == Panels.Editor.ZGetOpenDocOf(f)] = _ => App.Model.CloseFile(f, selectOther : true);
            //m.Separator();
            //m["Recent tasks and triggers..."] = _ => RecentTT.Show(); //rejected. It is in menu Run. Or would also need to show context menu when rclicked in empty space.
            m.Show();
            break;

        case MouseButton.Middle:
            App.Model.CloseFile(f, selectOther: true);
            break;
        }
    }
コード例 #2
0
ファイル: CiSnippets.cs プロジェクト: qmgindi/Au
    public static void Commit(SciCode doc, CiComplItem item, int codeLenDiff)
    {
        var    snippet = item as _CiComplItemSnippet;
        string s, usingDir;
        var    ci = item.ci;
        int    pos = ci.Span.Start, endPos = pos + ci.Span.Length + codeLenDiff;

        //list of snippets?
        var x = snippet.x;

        if (x.HasElements)
        {
            var a = snippet.x.Elements("list").ToArray();
            var m = new popupMenu();
            foreach (var v in a)
            {
                m.Add(v.Attr("item"));
            }
            m.FocusedItem = m.Items.First();
            int g = m.Show(MSFlags.ByCaret | MSFlags.Underline);
            if (g == 0)
            {
                return;
            }
            x = a[g - 1];
        }
        s = x.Value;

        //##directive -> #directive
        if (s.Starts('#') && doc.zText.Eq(pos - 1, '#'))
        {
            s = s[1..];
コード例 #3
0
        public static void End_task()
        {
            var f = App.Model.CurrentFile;

            if (f != null)
            {
                if (f.FindProject(out _, out var fMain))
                {
                    f = fMain;
                }
                if (App.Tasks.EndTasksOf(f))
                {
                    return;
                }
            }
            var a = App.Tasks.Items;

            if (a.Count > 0)
            {
                var m = new popupMenu {
                    RawText = true
                };
                m.Submenu("End task", m => {
                    foreach (var t in a)
                    {
                        m[t.f.DisplayName] = o => App.Tasks.EndTask(t);
                    }
                });
                m.Show();
            }
        }
コード例 #4
0
    void MouseTriggers()
    {
        //Add mouse triggers here.
        //To add triggers can be used triggerSnippet or menu TT -> New trigger. More info in Cookbook.
        //Click the Run button to apply changes after editing.



        if (!true)                                                                                                                //examples. To enable and test it, replace (!true) with (true) and run this script.
        {
            Triggers.Mouse[TMClick.Right, "Ctrl+Shift", TMFlags.ButtonModUp] = o => print.it("mouse trigger example", o.Trigger); //Ctrl+Shift+RightClick
            Triggers.Mouse[TMEdge.RightInCenter50] = o => {                                                                       //the right edge of the primary screen, center 50%
                var m = new popupMenu("example");
                m["A (mouse trigger example)"] = o => { };
                m["B"] = o => { };
                m.Submenu("C", m => {
                    m["D"] = o => { };
                    m["E"] = o => { };
                });
                m.Show();

                //To create menus can be used snippets. Start typing "menu" and you will see snippets in the completion list.
            };
            Triggers.Mouse[TMMove.LeftRightInCenter50, screen : TMScreen.Any] = o => wnd.switchActiveWindow(); //move the mouse quickly to the left and back in center 50% of any screen
            Triggers.Mouse[TMMove.RightLeftInCenter50, screen : TMScreen.Any] = o => keys.send("Ctrl+Tab");    //to the right and back. Ctrl+Tab should switch the active document.

            Triggers.FuncOf.NextTrigger     = o => keys.isScrollLock;                                          //example of a custom scope (aka context, condition)
            Triggers.Mouse[TMWheel.Forward] = o => print.it($"mouse trigger example: {o.Trigger} while ScrollLock is on");
        }
    }
コード例 #5
0
ファイル: Duiimage.cs プロジェクト: qmgindi/Au
    private void _bRect_Click(WBButtonClickArgs e)
    {
        if (_wnd.Is0)
        {
            return;
        }
        var m = new popupMenu();

        m["Rectangle of the captured image"] = o => _SetRect(_rect);
        m["Select rectangle..."]             = o => { if (_CaptureImageOrRect(true, out var r))
                                                      {
                                                          _SetRect(r.rect);
                                                      }
        };
        m.Show();
        void _SetRect(RECT k) => rectC.Set(true, k.ToStringFormat("({0}, {1}, {4}, {5})"));
    }
コード例 #6
0
ファイル: PanelOutline.cs プロジェクト: qmgindi/Au
    //unfinished, rejected, maybe in the future. Can't use just _pos. Need to get and update full spans.
    //	Maybe better add "manual sync" button instead of "auto sync" option.
    //void _Sync() {
    //	Debug.Assert(this.IsVisible && _oldTree != null);
    //	//print.it("sync");

    //	int pos = Panels.Editor.ZActiveDoc.zCurrentPos16; //todo: return if didn't change (use the position changed notification).
    //	_Item found = null;
    //	if (0 == (3 & App.Settings.outline_flags)) { //not sorted
    //		found = _Find(_oldTree);

    //		_Item _Find(_Item parent) {
    //			for (var v = parent.FirstChild; v != null; v = v.Next) {
    //				if (v._pos >= pos) return v;
    //				if (v.HasChildren) {
    //					var r = _Find(v);
    //					if (r != null) return r;
    //				}
    //			}
    //			return null;
    //		}
    //	}
    //	if (found != null) {
    //		print.it(found._text);

    //	}
    //}

    void _ContextMenu()
    {
        var m = new popupMenu();
        int flags = App.Settings.outline_flags, sort = flags & 3;

        m.AddRadio("Don't sort", sort == 0).Id            = 1;
        m.AddRadio("Sort by name", sort == 1).Id          = 2;
        m.AddRadio("Sort by kind and name", sort == 2).Id = 3;
        //m.AddRadio("Sort by kind and name", sort == 3).Id = 4; //sorting by kind+position probably not useful. Always sort by kind+name.
        //m.Separator();
        //m.AddCheck("Sync", 0 != (flags & 4), _ => App.Settings.outline_flags ^= 4);
        int i = m.Show(owner: this);

        if (i is >= 1 and <= 3)
        {
            App.Settings.outline_flags = (byte)((App.Settings.outline_flags & ~3) | (i - 1));
            if (_oldTree != null)
            {
                _oldTree = null;
                Update();
            }
        }
    }
コード例 #7
0
ファイル: _Script.cs プロジェクト: qmgindi/Au
    //class _Settings
    //{
    //	public string OneTwo { get; set; }
    //	public int ThreeFour { get; set; }
    //	public int Five { get; set; }
    //	public bool Six { get; set; }
    //	public string Seven { get; set; }
    //	public string Eight { get; set; } = "def";
    //}

    //void TestJson()
    //{
    //	var file = @"Q:\test\sett.json";
    //	var file2 = @"Q:\test\sett.xml";

    //	var v = new _Settings { OneTwo = "text ąčę", ThreeFour = 100 };

    //	for(int i = 0; i < 5; i++) {
    //		//100.ms();
    //		//perf.first();
    //		//var k1 = new JsonSerializerOptions { IgnoreNullValues = true, Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping, WriteIndented = true };
    //		//var b1 = JsonSerializer.SerializeToUtf8Bytes(v, k1);
    //		//perf.next();
    //		//File.WriteAllBytes(file, b1);
    //		//perf.nw();

    //		100.ms();
    //		perf.first();
    //		var b2 = File.ReadAllBytes(file);
    //		perf.next();
    //		var k2 = new JsonSerializerOptions { IgnoreNullValues = true };
    //		perf.next();
    //		v = JsonSerializer.Deserialize<_Settings>(b2, k2);
    //		perf.nw('J');
    //	}

    //	for(int i = 0; i < 5; i++) {
    //		//100.ms();
    //		//perf.first();
    //		//var r1 = new XElement("r");
    //		//r1.Add(new XElement("OneTwo", v.OneTwo));
    //		//r1.Add(new XElement("ThreeFour", v.ThreeFour.ToString()));
    //		//perf.next();
    //		//r1.Save(file2);
    //		//perf.nw();

    //		100.ms();
    //		perf.first();
    //		var r2 = XElement.Load(file2);
    //		perf.next();
    //		v = new _Settings();
    //		v.OneTwo = r2.Element("OneTwo").Value;
    //		var s2 = r2.Element("ThreeFour").Value;
    //		perf.nw('X');
    //		v.ThreeFour = s2.ToInt();
    //	}

    //	print.it(v.OneTwo, v.ThreeFour, v.Five, v.Six, v.Seven, v.Eight);

    //	//JsonDocument d; d.RootElement.
    //}

    //[DllImport("CppE")]
    //static extern int Cpp_Install(int step, string dir);

    //[DllImport("CppE")]
    //static extern int Cpp_Uninstall();


#if false
    void TestToolbar()
    {
        for (int i = 0; i < 1; i++)
        {
            var t = new toolbar("123");
            //t.NoText = true;
            //t.Border= TBBorder.Sizable3;t.Control.Text = "Toolbar";
            //t.Border = TBBorder.SizableWithCaptionX;

            //t["Find", @"Q:\app\find.ico"] = o => print.it(o);
            //t["Copy", @"Q:\app\copy.ico"] = o => print.it(o);
            //t.Separator("Tpi group");
            //t["Delete", @"Q:\app\delete.ico"] = o => print.it(o);
            //t["No image"] = o => print.it(o);
            //t["TT", tooltip: "WWWWWWWWWWWW WWWWWWWWWWWW WWWWWWWWWWWW WWWWWWWWWWWW WWWWWWWWWWWW WWWWWWWWWWWW WWWWWWWWWWWW WWWWWWWWWWWW WWWWWWWWWWWW WWWWWWWWWWWW WWWWWWWWWWWW WWWWWWWWWWWW WWWWWWWWWWWW WWWWWWWWWWWW WWWWWWWWWWWW "] = o => print.it(o);
            ////t.LastButton.DisplayStyle = ToolStripItemDisplayStyle.Image;
            ////t.LastButton.AutoToolTip = false;
            ////t.LastButton.ToolTipText = "ggg";
            //t.Separator();
            //t["Run", @"Q:\app\run.ico"] = o => print.it(o);
            //t.Separator("");
            //t["Paste text", @"Q:\app\paste.ico"] = o => print.it(o);
            //t.LastButton.ToolTipText = "Toooooltip";

            //t.ExtractIconPathFromCode = true;
            //t["Auto icon"] = o => print.it("notepad.exe");
            //t["Failed icon", @"Q:\app\-.ico"] = o => print.it(o);
            ////t.LastButton.DisplayStyle = ToolStripItemDisplayStyle.ImageAndText;
            ////t.Separator("");
            ////t.Add(new ToolStripTextBox { ToolTipText= "ToolStripTextBox", AutoSize=false, Width=50 });
            ////t.Add(new ToolStripComboBox { ToolTipText= "ToolStripComboBox", AutoSize=false, Width=50 });
            ////t.Add(new ToolStripTextBox());
            ////t.Add(new ToolStripTextBox());
            ////t.Add(new ToolStripTextBox());
            ////t.Add(new ToolStripButton("aaa"));
            ////t.Add(new ToolStripButton("bbb"));
            ////t["Multi\r\nline"] = o => print.it(o);

            //t["None"] = o => _B(TBBorder.None);
            //t["SWC"] = o => _B(TBBorder.SizableWithCaption);
            //t["Sizable1"] = o => _B(TBBorder.Sizable1);
            //t["Sizable2"] = o => _B(TBBorder.Sizable2);
            //t["Sizable3"] = o => _B(TBBorder.Sizable3);
            //t["Sizable3D"] = o => _B(TBBorder.Sizable3D);
            //t["Sizable"] = o => _B(TBBorder.Sizable);
            //t["FixedWithCaption"] = o => _B(TBBorder.FixedWithCaption);
            //t["SizableWithCaption"] = o => _B(TBBorder.SizableWithCaption);
            //t["Close"] = o => t.Close();

#if false
            var dd = new ToolStripDropDownButton("DD");
            t.Add(dd, @"Q:\app\find.ico");
            dd.DropDownOpening += (_, _) => {
                var m = new popupMenu(dd);
                m["one"] = o => print.it(o);
                using (m.Submenu("Sub")) {
                    m["si"] = o => print.it(o);
                }
            };
            var sb = new ToolStripSplitButton("SB");
            t.Add(sb, @"Q:\app\copy.ico", o => print.it(o));
#elif true
            //t.Control.Font = new Font("Courier New", 16);
            //t.Control.RightToLeft = RightToLeft.Yes;
            t.MenuButton("DD", m => {
                print.it("dd");
                //m.MultiShow = false;
                m["one"] = o => print.it(o);
                using (m.Submenu("Sub")) {
                    m["si"] = o => print.it(o);
                }
            }, @"Q:\app\find.ico", "MenuButton");
            t.SplitButton("SB", m => {
                m["one"] = o => print.it(o);
                //var sb = m.Control.OwnerItem as ToolStripSplitButton;
                //print.it(sb);
                //sb.DefaultItem = m.LastItem;
                using (m.Submenu("Sub")) {
                    m["si"] = o => print.it(o);
                }
            }, @"Q:\app\copy.ico", "SplitButton", o => print.it(o));
            t.Separator("");
            t[true, "DD2", @"Q:\app\delete.ico"] = m => {
                print.it("create menu");
                //m.MultiShow = false;
                m["one"] = o => print.it(o);
                using (m.Submenu("Sub")) {
                    m["si"] = o => print.it(o);
                }
            };
            //t.SplitButton("SB", o => {
            //	print.it(o);
            //}, m => {
            //	m["one"] = o => print.it(o);
            //	using(m.Submenu("Sub")) {
            //		m["si"] = o => print.it(o);
            //	}
            //}, @"Q:\app\copy.ico", "SplitButton");
            //Action<popupMenu> menu1 = m => {
            //	m["one"] = o => print.it(o);
            //	using(m.Submenu("Sub")) {
            //		m["si"] = o => print.it(o);
            //	}
            //};
            //t.MenuButton("DD", menu1, @"Q:\app\find.ico", "MenuButton");
#elif false
            t.MenuButton("DD", @"Q:\app\find.ico");
            t.Menu = m => {
                m["one"] = o => print.it(o);
                using (m.Submenu("Sub")) {
                    m["si"] = o => print.it(o);
                }
            };
#else
            t.MenuButton("DD", @"Q:\app\find.ico").Menu = m => {
                print.it("dd");
                //m.MultiShow = false;
                m["one"] = o => print.it(o);
                using (m.Submenu("Sub")) {
                    m["two"] = o => print.it(o);
                }
            };
            t.SplitButton("SB", o => print.it(o), @"Q:\app\copy.ico").Menu = m => {
                print.it("dd");
                m["one"] = o => print.it(o);
                using (m.Submenu("Sub")) {
                    m["two"] = o => print.it(o);
                }
            };
#endif
            //t.Separator("");
            ////t["GC"] = o => GC.Collect();

            //var dd = new ToolStripSplitButton("SB2", null, (_, _)=>print.it("click"));
            //t.Add(dd, @"Q:\app\delete.ico");
            //dd.DropDownOpening += (_, _) => {
            //	var m = new popupMenu();
            //	dd.DropDown = m.Control;
            //	m["one"] = o => print.it(o);
            //};
            //dd.ButtonClick += (_, _) => print.it("button click");
            //dd.DoubleClickEnabled = true;
            //dd.ButtonDoubleClick += (_, _) => print.it("button double click");

            //timer.after(3000, _ => {
            //	var c = t.Control.Items[0];
            //	c.Select();
            //});

            //void _B(TBBorder b){
            //	t.Border = b;
            //	//print.it(WndUtil.BorderWidth((wnd)t.Control));
            //}

            //t.Bounds = new Rectangle(i * 300 + 700, 200, 200, 200);
            t.Show();
            //t.Window.ActivateL();
            wait.doEvents(200);

            //for(int j = 1; j <= (int)TBBorder.SizableWithCaptionX; j++) {
            //	wait.doEvents(1000);
            //	t.Border = (TBBorder)j;
            //}

            //wait.doEvents(1000);
            //t.Border = TBBorder.FixedWithCaption;
            //wait.doEvents(3000);
            //t.Border = TBBorder.SizableWithCaption;

            //var m = new popupMenu();
            //using(m.Submenu("Sub")) {

            //}
            //m.Show()
        }

        //var c = new System.Windows.Forms.VisualStyles.VisualStyleRenderer(VisualStyleElement.Window.FrameLeft.Inactive).GetColor(ColorProperty.BorderColor);
        //print.it((uint)c.ToArgb());

        //timer.after(500, _ => {
        //	var w = (wnd)t.Control;
        //	//w.SetStyle(WS.DLGFRAME, SetAddRemove.Add);
        //});

        dialog.options.topmostIfNoOwnerWindow = true;
        dialog.show();

        //timer.after(10000, _ => Application.Exit());
        //Application.Run();
    }
コード例 #8
0
ファイル: DProperties.cs プロジェクト: qmgindi/Au
    public DProperties(FileNode f)
    {
        _f       = f;
        _isClass = f.IsClass;

        Owner = App.Wmain;
        Title = "Properties of " + _f.Name;

        var b = new wpfBuilder(this).WinSize(600).Columns(-1, 0);

        b.WinProperties(WindowStartupLocation.CenterOwner, showInTaskbar: false);
        b.R.Add(out info).Height(80).Margin("B8").Span(-1);
        b.R.StartStack(vertical: true);         //left column
        b.StartGrid().Columns(0, -1, 20, 0, -1.15)
        .R.Add("role", out role).Skip()
        .Add("testScript", out testScript).Validation(o => _ValidateFile(o, "testScript", FNFind.CodeFile));
        b.End();

        b.StartStack(out gRun, "Run", vertical: true);
        b.StartGrid().Columns(0, 120, -1, 0, 80)
        .Add("ifRunning", out ifRunning).Skip()
        .Add("uac", out uac);
        b.End();
        b.End().Brush(Brushes.OldLace);

        b.StartGrid(out gCompile, "Compile").Columns(0, 50, 20, 0, -1);
        b.R.Add(out optimize, "optimize").Skip(2)
        .Add("define", out define);
        b.R.Add("warningLevel", out warningLevel).Editable().Skip()
        .Add("noWarnings", out noWarnings);
        b.R.Add("testInternal", out testInternal);
        b.R.StartGrid().Columns(0, -1, 20, 0, -1)
        .Add("preBuild", out preBuild).Skip().Validation(o => _ValidateFile(o, "preBuild", FNFind.CodeFile))
        .Add("postBuild", out postBuild).Validation(o => _ValidateFile(o, "postBuild", FNFind.CodeFile));
        b.End();
        b.End().Brush(Brushes.OldLace);

        b.StartStack(out gAssembly, "Assembly", vertical: true);
        b.StartGrid().Columns(0, -1, 30)
        .Add("outputPath", out outputPath)
        .AddButton(out outputPathB, "...", _ButtonClick_outputPath)
        .End();
        b.StartGrid().Columns(0, -1, 20, 0, -1);
        b.R.Add("icon", out icon).Skip().Validation(o => _ValidateFile(o, "icon", FNFind.Any))
        .Add("manifest", out manifest).Validation(o => _ValidateFile(o, "manifest", FNFind.File));
        b.R.Add("sign", out sign).Skip().Validation(o => _ValidateFile(o, "sign", FNFind.File));
        b.StartStack()
        .Add(out console, "console")
        .Add(out bit32, "bit32").Margin(15)
        .Add(out xmlDoc, "xmlDoc").Margin(15)
        .End();
        b.End();
        b.End().Brush(Brushes.OldLace);

        b.End();
        b.StartStack(vertical: true).Margin("L20");         //right column
        b.StartGrid <GroupBox>("Add reference");
        b.R.AddButton(out addLibrary, "Library...", _ButtonClick_addLibrary);
        b.R.AddButton(out addNuget, "NuGet ▾", _ButtonClick_addNuget);
        b.R.AddButton(out addComRegistry, "COM ▾", _bAddComRegistry_Click).AddButton(out addComBrowse, "...", _bAddComBrowse_Click).Width(30);
        b.AddButton(out addProject, "Project ▾", _ButtonClick_addProject);
        b.End();
        b.StartStack <GroupBox>("Add file", vertical: true);
        b.AddButton(out addClassFile, "Class file ▾", _ButtonClick_addClass);
        b.AddButton(out addResource, "Resource ▾", _ButtonClick_addResource);
        b.End();
        b.StartStack(vertical: true).Add("Find in lists", out findInLists).Tooltip("In button drop-down lists show only items containing this text").End();
        //b.AddButton("Change icon", _ => DIcons.ZShow(true, _f.CustomIconName)).Margin("T8B8"); //rejected
        b.End();
        b.R.AddOkCancel();
        b.End();

        _meta = new MetaCommentsParser(_f);

        _role = _meta.role switch {
            "miniProgram" => Au.Compiler.ERole.miniProgram,
            "exeProgram" => Au.Compiler.ERole.exeProgram,
            "editorExtension" => Au.Compiler.ERole.editorExtension,
            "classLibrary" when _isClass => Au.Compiler.ERole.classLibrary,
            "classFile" when _isClass => Au.Compiler.ERole.classFile,
            _ => _isClass ? Au.Compiler.ERole.classFile : Au.Compiler.ERole.miniProgram,
        };
        _InitCombo(role, _isClass ? "miniProgram|exeProgram|editorExtension|classLibrary|classFile" : "miniProgram|exeProgram|editorExtension", null, (int)_role);
        testScript.Text = _f.TestScript?.ItemPath;
        //Run
        _InitCombo(ifRunning, "warn_restart|warn|cancel_restart|cancel|wait_restart|wait|run_restart|run|restart", _meta.ifRunning);
        _InitCombo(uac, "inherit|user|admin", _meta.uac);
        //Assembly
        outputPath.Text = _meta.outputPath;
        void _ButtonClick_outputPath(WBButtonClickArgs e)
        {
            var m = new popupMenu();

            m[_GetOutputPath(getDefault: true)] = o => outputPath.Text = o.ToString();
            bool isLibrary = _role == Au.Compiler.ERole.classLibrary;

            if (isLibrary)
            {
                m[@"%folders.ThisApp%\Libraries"] = o => outputPath.Text = o.ToString();
            }
            m["Browse..."] = o => {
                var initf = _GetOutputPath(getDefault: false, expandEnvVar: true);
                filesystem.createDirectory(initf);
                var d = new FileOpenSaveDialog(isLibrary ? "{4D1F3AFB-DA1A-45AC-8C12-41DDA5C51CDD}" : "{4D1F3AFB-DA1A-45AC-8C12-51DDA5C51CDD}")
                {
                    InitFolderFirstTime = initf,
                };
                if (d.ShowOpen(out string s, this, selectFolder: true))
                {
                    outputPath.Text = folders.unexpandPath(s);
                }
            };
            m.Show();
        }

        icon.Text     = _meta.icon;
        manifest.Text = _meta.manifest;
        sign.Text     = _meta.sign;
        if (_meta.console == "true")
        {
            console.IsChecked = true;
        }
        if (_meta.bit32 == "true")
        {
            bit32.IsChecked = true;
        }
        if (_meta.xmlDoc == "true")
        {
            xmlDoc.IsChecked = true;
        }
        //Compile
        if (_meta.optimize == "true")
        {
            optimize.IsChecked = true;
        }
        define.Text = _meta.define;
        _InitCombo(warningLevel, "5|4|3|2|1|0", _meta.warningLevel);
        noWarnings.Text   = _meta.noWarnings;
        testInternal.Text = _meta.testInternal;
        preBuild.Text     = _meta.preBuild;
        postBuild.Text    = _meta.postBuild;
コード例 #9
0
ファイル: dock.cs プロジェクト: qmgindi/Au
            void _CaptionContextMenu(_Node thisOrParentTab)
            {
                if (_IsDocument && !_leaf.addedLater)
                {
                    return;
                }
                var m = new popupMenu();

                bool canClose = _leaf?.canClose ?? false;

                if (canClose)
                {
                    m["Close\tM-click"] = _ => _UserClosing();
                }
                _DockStateItem(_DockState.Hide, canClose ? "Hide" : "Hide\tM-click");

                if (_state.Has(_DockState.Float))
                {
                    _DockStateItem(0, "Dock\tD-click");
                }
                else
                {
                    _DockStateItem(_DockState.Float, "Float\tD-click, drag");
                }

                m.Submenu("Caption at", m => {
                    _CaptionAtItem(Dock.Left);
                    _CaptionAtItem(Dock.Top);
                    _CaptionAtItem(Dock.Right);
                    _CaptionAtItem(Dock.Bottom);

                    void _CaptionAtItem(Dock ca)
                    {
                        m.AddRadio(ca.ToString(), ca == thisOrParentTab._captionAt, o => thisOrParentTab._SetCaptionAt(ca));
                    }
                });
                _ContextMenu_Move(m);
                _ShowSubmenus();

                //ContextMenuOpening?.Invoke(this, m);

                m.Show();

                void _DockStateItem(_DockState state, string text)
                {
                    m[text] = o => _SetDockState(state);
                }

                void _ShowSubmenus()
                {
                    var a = new List <_Node>();

                    foreach (var v in RootAncestor.Descendants())
                    {
                        if (v._IsStack || !v._state.Has(_DockState.Hide))
                        {
                            continue;
                        }
                        if (v._IsTab && v.Children().All(o => o._state.Has(_DockState.Hide)))
                        {
                            continue;
                        }
                        a.Add(v);
                    }
                    if (a.Count == 0)
                    {
                        return;
                    }
                    m.Separator();
                    a.Sort((x, y) => {
                        if (x._IsToolbar && !y._IsToolbar)
                        {
                            return(-1);
                        }
                        if (y._IsToolbar && !x._IsToolbar)
                        {
                            return(1);
                        }
                        return(string.Compare(x.ToString(), y.ToString(), true));
                    });
                    m.Submenu("Show", m => {
                        int i = 0;
                        foreach (var v in a)
                        {
                            if (i > 0 && a[i - 1]._IsToolbar != a[i]._IsToolbar)
                            {
                                m.Separator();
                            }
                            i++;
                            m[v.ToString()] = _ => v._Unhide();
                        }
#if DEBUG
                        if (a.Count > 1)
                        {
                            m.Separator();
                            m["Show all (debug)"] = _ => {
                                foreach (var v in a)
                                {
                                    v._Unhide();
                                }
                            };
                        }
#endif
                    });
                }

#if DEBUG
                m.Separator();
                m.Submenu("Debug", m => {
                    m["Invalidate window"] = _ => _Invalidate(_pm._ContainerWindow);
                    m["Invalidate floats"] = _ => {
                        foreach (var v in RootAncestor.Descendants())
                        {
                            if (v._floatWindow != null)
                            {
                                _Invalidate(v._floatWindow);
                            }
                        }
                    };
                    m.Add(0, "info: toggle ScrollLock if does not work", disable: true);
                });

                void _Invalidate(Window w)
                {
                    //if (keys.isScrollLock) Api.InvalidateRect(w.Hwnd(), IntPtr.Zero, true); //works
                    ////else w.UpdateLayout(); //no
                    //else w.InvalidateVisual(); //no

                    Api.InvalidateRect(w.Hwnd(), keys.isScrollLock);
                }
#endif
            }