protected override void OnClick(EventArgs e) { MenuWithHandler definition = (Tag as MenuWithHandler); if (definition.Target != null) { definition.Target.OnCommand(definition.ID); } // Sometimes all menu texts are blank. I cannot reproduce it. I guess, it is because the menus are not disposed. I debugged by overriding Dispose of ContextMenuWithHandler // If a menu item is clicked, the menu disappears and can be disposed. This is forced here. But if the menu disappears because of some other reason (ESC, click somewhere else) // Dispose doesn't get called until maybe much later or when the form closes. ContextMenuWithHandler toDispose = null; Menu parent = this.Parent; while (parent != null) { if (parent is ContextMenuWithHandler cmh) { toDispose = cmh; break; } if (parent is MenuItem mi) { parent = mi.Parent; } else { break; } } toDispose?.Dispose(); }
protected override void OnMeasureItem(System.Windows.Forms.MeasureItemEventArgs e) { MenuWithHandler definition = Tag as MenuWithHandler; if (this.Text == "-") { e.ItemHeight = 3; } else { Font f = SystemInformation.MenuFont; string toMeassure = this.Text; if (!string.IsNullOrEmpty(definition.Shortcut)) { toMeassure += " " + definition.Shortcut; } SizeF sz = e.Graphics.MeasureString(toMeassure, SystemInformation.MenuFont); if (this.Parent is MainMenu) { e.ItemHeight = SystemInformation.MenuHeight; e.ItemWidth = (int)sz.Width; // TopLevel hat kein Bildchen } else { e.ItemHeight = ButtonImages.ButtonImageList.ImageSize.Height + 6; // 3 oben, 3 unten e.ItemWidth = (ButtonImages.ButtonImageList.ImageSize.Width + 6) + ButtonImages.ButtonImageList.ImageSize.Width / 2 + (int)sz.Width; // (Bildchen + 3 links + 3 rechts) + TextOffset + Textbreite } } }
public MenuItemWithHandler(MenuWithHandler definition) : base() { OwnerDraw = true; Text = definition.Text; Tag = definition; if (!string.IsNullOrEmpty(definition.Shortcut)) { Shortcut = ShortcutFromString(definition.Shortcut); ShowShortcut = definition.ShowShortcut; } // no need for the following, if Update //CommandState commandState = new CommandState(); //if (definition.Target.OnUpdateCommand(definition.ID, commandState)) //{ // Enabled = commandState.Enabled; // Checked = commandState.Checked; // doubleChecked = commandState.Checked; //} if (definition.SubMenus != null) { MenuItem[] sub = new MenuItem[definition.SubMenus.Length]; for (int i = 0; i < definition.SubMenus.Length; i++) { sub[i] = new MenuItemWithHandler(definition.SubMenus[i]); } MenuItems.AddRange(sub); } }
protected override void OnSelect(EventArgs e) { MenuWithHandler definition = (Tag as MenuWithHandler); if (definition.Target != null) { definition.Target.OnSelected(definition, true); } base.OnSelect(e); }
private void UpdateMRUMenu(MenuItem mi, string[] mruFiles) { if (mi.IsParent) { foreach (MenuItem mmi in mi.MenuItems) { UpdateMRUMenu(mmi, mruFiles); } } else { MenuItemWithHandler mid = mi as MenuItemWithHandler; if (mid != null) { MenuWithHandler mwh = mid.Tag as MenuWithHandler; if (mwh != null) { string MenuId = mwh.ID; if (MenuId.StartsWith("MenuId.File.Mru.File")) { string filenr = MenuId.Substring("MenuId.File.Mru.File".Length); try { int n = int.Parse(filenr); if (n <= mruFiles.Length && n > 0) { string[] parts = mruFiles[mruFiles.Length - n].Split(';'); if (parts.Length > 1) { mid.Text = parts[0]; } } } catch (FormatException) { } catch (OverflowException) { } } } } } }
protected override void OnPopup(EventArgs e) { if (this.IsParent) { foreach (MenuItem mi in MenuItems) { MenuWithHandler definition = (mi.Tag as MenuWithHandler); if (definition != null) { if (definition.Target != null) { CommandState commandState = new CommandState(); if (definition.Target.OnUpdateCommand(definition.ID, commandState)) { mi.Enabled = commandState.Enabled; mi.Checked = commandState.Checked; (mi as MenuItemWithHandler).doubleChecked = commandState.Checked; } else { //IFrameInternal frm = FrameImpl.MainFrame as IFrameInternal; //bool handled = false; //if (frm != null) frm.UpdateContextMenu(miid.mTarget, miid.mID, commandState, ref handled); //if (handled) //{ // miid.Enabled = commandState.Enabled; // miid.Checked = commandState.Checked; // miid.doubleChecked = commandState.Checked; //} } } } } } base.OnPopup(e); }
void ICommandHandler.OnSelected(MenuWithHandler selectedMenuItem, bool selected) { }
public virtual void OnSelected(MenuWithHandler selectedMenuItem, bool selected) { }
public override void OnSelected(MenuWithHandler selectedMenuItem, bool selected) { }
protected override void OnDrawItem(System.Windows.Forms.DrawItemEventArgs e) { MenuWithHandler definition = Tag as MenuWithHandler; if (this.Text == "-") { Rectangle LeftSquare = e.Bounds; Rectangle Text = e.Bounds; LeftSquare.Width = ButtonImages.ButtonImageList.ImageSize.Width + 6; Text.Offset(LeftSquare.Width, 0); Text.Width -= LeftSquare.Width; LinearGradientBrush leftBrush = new LinearGradientBrush(LeftSquare, SystemColors.ControlLightLight, SystemColors.ControlDark, LinearGradientMode.Horizontal); e.Graphics.FillRectangle(leftBrush, LeftSquare); e.Graphics.FillRectangle(SystemBrushes.ControlLightLight, Text); e.Graphics.DrawLine(SystemPens.Control, e.Bounds.Left + (ButtonImages.ButtonImageList.ImageSize.Width + 6) + ButtonImages.ButtonImageList.ImageSize.Width / 2, e.Bounds.Top + 1, e.Bounds.Right, e.Bounds.Top + 1); } else { if (this.Parent is MainMenu) { if ((e.State & DrawItemState.HotLight) != 0) { Color c = Color.FromArgb( ((int)SystemColors.ActiveCaption.R + 2 * (int)SystemColors.ControlLightLight.R) / 3, ((int)SystemColors.ActiveCaption.G + 2 * (int)SystemColors.ControlLightLight.G) / 3, ((int)SystemColors.ActiveCaption.B + 2 * (int)SystemColors.ControlLightLight.B) / 3); e.Graphics.FillRectangle(new SolidBrush(c), e.Bounds); e.Graphics.DrawLine(SystemPens.ControlText, e.Bounds.Left, e.Bounds.Top, e.Bounds.Right - 1, e.Bounds.Top); e.Graphics.DrawLine(SystemPens.ControlText, e.Bounds.Right - 1, e.Bounds.Top, e.Bounds.Right - 1, e.Bounds.Bottom - 1); e.Graphics.DrawLine(SystemPens.ControlText, e.Bounds.Right - 1, e.Bounds.Bottom - 1, e.Bounds.Left, e.Bounds.Bottom - 1); e.Graphics.DrawLine(SystemPens.ControlText, e.Bounds.Left, e.Bounds.Bottom - 1, e.Bounds.Left, e.Bounds.Top); } else { e.Graphics.FillRectangle(SystemBrushes.Control, e.Bounds); } float TextX = e.Bounds.Left; float TextY = e.Bounds.Top + (e.Bounds.Height - SystemInformation.MenuFont.GetHeight(e.Graphics)) / 2; StringFormat sf = StringFormat.GenericDefault; sf.HotkeyPrefix = System.Drawing.Text.HotkeyPrefix.Show; Brush textBrush; if (!Enabled) { textBrush = SystemBrushes.FromSystemColor(SystemColors.GrayText); } else { textBrush = SystemBrushes.WindowText; } e.Graphics.DrawString(this.Text, SystemInformation.MenuFont, textBrush, TextX, TextY, sf); } else { Rectangle LeftSquare = e.Bounds; Rectangle Text = e.Bounds; LeftSquare.Width = ButtonImages.ButtonImageList.ImageSize.Width + 6; Text.Offset(LeftSquare.Width, 0); Text.Width -= LeftSquare.Width; LinearGradientBrush leftBrush = new LinearGradientBrush(LeftSquare, SystemColors.ControlLightLight, SystemColors.ControlDark, LinearGradientMode.Horizontal); if ((e.State & DrawItemState.Selected) != 0) { Color c = Color.FromArgb( ((int)SystemColors.ActiveCaption.R + 2 * (int)SystemColors.ControlLightLight.R) / 3, ((int)SystemColors.ActiveCaption.G + 2 * (int)SystemColors.ControlLightLight.G) / 3, ((int)SystemColors.ActiveCaption.B + 2 * (int)SystemColors.ControlLightLight.B) / 3); e.Graphics.FillRectangle(new SolidBrush(c), e.Bounds); e.Graphics.DrawLine(SystemPens.ControlText, e.Bounds.Left, e.Bounds.Top, e.Bounds.Right - 1, e.Bounds.Top); e.Graphics.DrawLine(SystemPens.ControlText, e.Bounds.Right - 1, e.Bounds.Top, e.Bounds.Right - 1, e.Bounds.Bottom - 1); e.Graphics.DrawLine(SystemPens.ControlText, e.Bounds.Right - 1, e.Bounds.Bottom - 1, e.Bounds.Left, e.Bounds.Bottom - 1); e.Graphics.DrawLine(SystemPens.ControlText, e.Bounds.Left, e.Bounds.Bottom - 1, e.Bounds.Left, e.Bounds.Top); } else { e.Graphics.FillRectangle(leftBrush, LeftSquare); e.Graphics.FillRectangle(SystemBrushes.ControlLightLight, Text); } float TextX = e.Bounds.Left + (ButtonImages.ButtonImageList.ImageSize.Width + 6) + ButtonImages.ButtonImageList.ImageSize.Width / 2; float TextY = e.Bounds.Top + (e.Bounds.Height - SystemInformation.MenuFont.GetHeight(e.Graphics)) / 2; StringFormat sf = StringFormat.GenericDefault; sf.HotkeyPrefix = System.Drawing.Text.HotkeyPrefix.Show; Brush textBrush; if (!Enabled) { textBrush = SystemBrushes.FromSystemColor(SystemColors.GrayText); } else { textBrush = SystemBrushes.WindowText; } e.Graphics.DrawString(this.Text, SystemInformation.MenuFont, textBrush, TextX, TextY, sf); string shortcut = definition.Shortcut;// GetShortcutString(); if (!string.IsNullOrEmpty(shortcut)) { SizeF sz = e.Graphics.MeasureString(shortcut, SystemInformation.MenuFont); e.Graphics.DrawString(shortcut, SystemInformation.MenuFont, textBrush, e.Bounds.Right - e.Bounds.Height / 2 - sz.Width, TextY, sf); } int dx = (e.Bounds.Height - ButtonImages.ButtonImageList.ImageSize.Height) / 2; if (definition.ImageIndex >= 0) { int ind = definition.ImageIndex; if (ind >= 10000) { ind = ind - 10000 + ButtonImages.OffsetUserImages; } if (Enabled) { ButtonImages.ButtonImageList.Draw(e.Graphics, e.Bounds.Left + 3, e.Bounds.Top + 3, ind); } else { ControlPaint.DrawImageDisabled(e.Graphics, ButtonImages.ButtonImageList.Images[ind], e.Bounds.Left + 3, e.Bounds.Top + 3, Color.FromArgb(0, 0, 0, 0)); } } if ((e.State & DrawItemState.Checked) != 0 || doubleChecked) { if (definition.ImageIndex < 0) { ButtonImages.ButtonImageList.Draw(e.Graphics, e.Bounds.Left + 3, e.Bounds.Top + 3, 84); // the red check mark } int x1 = e.Bounds.Left + 1; int y1 = e.Bounds.Top + 1; int x2 = x1 + ButtonImages.ButtonImageList.ImageSize.Width + 4; int y2 = y1 + ButtonImages.ButtonImageList.ImageSize.Height + 4; e.Graphics.DrawLine(SystemPens.ControlText, x1, y1, x2, y1); e.Graphics.DrawLine(SystemPens.ControlText, x2, y1, x2, y2); e.Graphics.DrawLine(SystemPens.ControlText, x2, y2, x1, y2); e.Graphics.DrawLine(SystemPens.ControlText, x1, y2, x1, y1); } } } }
private List <MenuWithHandler> GetFacesSubmenus(Face face) { List <MenuWithHandler> res = new List <MenuWithHandler>(); if (face.IsFillet()) { HashSet <Face> connectedFillets = new HashSet <Face>(); CollectConnectedFillets(face, connectedFillets); FeatureCommandHandler fch = new FeatureCommandHandler(connectedFillets.ToArray(), this, "MenuId.Fillet"); MenuWithHandler fr = new MenuWithHandler("MenuId.Fillet.ChangeRadius"); fr.OnCommand = (menuId) => { ParametricsRadius pr = new ParametricsRadius(connectedFillets.ToArray(), soa.Frame, true); soa.Frame.SetAction(pr); return(true); }; fr.OnSelected = (mh, selected) => { currentMenuSelection.Clear(); currentMenuSelection.AddRange(connectedFillets.ToArray()); currentView.Invalidate(PaintBuffer.DrawingAspect.Select, currentView.DisplayRectangle); }; MenuWithHandler fd = new MenuWithHandler("MenuId.Fillet.Remove"); fd.OnCommand = (menuId) => { Face[] involvedFaces = connectedFillets.ToArray(); Shell orgShell = involvedFaces[0].Owner as Shell; if (orgShell != null) { RemoveFillet rf = new RemoveFillet(involvedFaces[0].Owner as Shell, new HashSet <Face>(involvedFaces)); Shell sh = rf.Result(); if (sh != null) { using (soa.Frame.Project.Undo.UndoFrame) { sh.CopyAttributes(orgShell); IGeoObjectOwner owner = orgShell.Owner; owner.Remove(orgShell); owner.Add(sh); } } } soa.ResetMode(); return(true); }; fd.OnSelected = (mh, selected) => { currentMenuSelection.Clear(); currentMenuSelection.AddRange(connectedFillets.ToArray()); currentView.Invalidate(PaintBuffer.DrawingAspect.Select, currentView.DisplayRectangle); }; fch.SubMenus = new MenuWithHandler[] { fr, fd }; res.Add(fch); } IEnumerable <Face> connected = face.GetSameSurfaceConnected(); // if (connected.Any()) { List <Face> lconnected = new List <Face>(connected); lconnected.Add(face); BoundingCube ext = BoundingCube.EmptyBoundingCube; foreach (Face fc in connected) { ext.MinMax(fc.GetExtent(0.0)); } // maybe a full sphere, cone, cylinder or torus: // except for the sphere: position axis // except for the cone: change radius or diameter // for the cone: smaller and larger diameter // for cone and cylinder: total length if (face.Surface is CylindricalSurface || face.Surface is CylindricalSurfaceNP || face.Surface is ToroidalSurface) { MenuWithHandler mh = new MenuWithHandler("MenuId.FeatureDiameter"); mh.OnCommand = (menuId) => { ParametricsRadius pr = new ParametricsRadius(lconnected.ToArray(), soa.Frame, false); soa.Frame.SetAction(pr); return(true); }; mh.OnSelected = (menuId, selected) => { currentMenuSelection.Clear(); currentMenuSelection.AddRange(lconnected.ToArray()); currentView.Invalidate(PaintBuffer.DrawingAspect.Select, currentView.DisplayRectangle); }; res.Add(mh); } if (face.Surface is CylindricalSurface || face.Surface is CylindricalSurfaceNP || face.Surface is ConicalSurface) { Line axis = null; if (face.Surface is ICylinder cyl) { axis = cyl.Axis.Clip(ext); } if (face.Surface is ConicalSurface cone) { axis = cone.AxisLine(face.Domain.Bottom, face.Domain.Top); } MenuWithHandler mh = new MenuWithHandler("MenuId.AxisPosition"); mh.OnCommand = (menuId) => { ParametricsDistanceActionOld pd = new ParametricsDistanceActionOld(lconnected, axis, soa.Frame); soa.Frame.SetAction(pd); return(true); }; mh.OnSelected = (menuId, selected) => { currentMenuSelection.Clear(); currentMenuSelection.AddRange(lconnected.ToArray()); currentView.Invalidate(PaintBuffer.DrawingAspect.Select, currentView.DisplayRectangle); }; res.Add(mh); } } if (face.Surface is PlaneSurface pls) { // try to find parallel outline edges to modify the distance Edge[] outline = face.OutlineEdges; for (int j = 0; j < outline.Length - 1; j++) { for (int k = j + 1; k < outline.Length; k++) { if (outline[j].Curve3D is Line l1 && outline[k].Curve3D is Line l2) { if (Precision.SameDirection(l1.StartDirection, l2.StartDirection, false)) { // two parallel outline lines, we could parametrize the distance Edge o1 = outline[j]; Edge o2 = outline[k]; // outline[i] is not captured correctly for the anonymous method. I don't know why. With local copies, it works. double lmin = double.MaxValue; double lmax = double.MinValue; double p = Geometry.LinePar(l1.StartPoint, l1.EndPoint, l2.StartPoint); lmin = Math.Min(lmin, p); lmax = Math.Max(lmax, p); p = Geometry.LinePar(l1.StartPoint, l1.EndPoint, l2.EndPoint); lmin = Math.Max(Math.Min(lmin, p), 0); lmax = Math.Min(Math.Max(lmax, p), 1); GeoPoint p1 = Geometry.LinePos(l1.StartPoint, l1.EndPoint, (lmin + lmax) / 2.0); GeoPoint p2 = Geometry.DropPL(p1, l2.StartPoint, l2.EndPoint); if ((p1 | p2) > Precision.eps) { MenuWithHandler mh = new MenuWithHandler("MenuId.EdgeDistance"); Line feedback = Line.TwoPoints(p1, p2); GeoObjectList feedbackArrow = currentView.Projection.MakeArrow(p1, p2, pls.Plane, Projection.ArrowMode.circleArrow); mh.OnCommand = (menuId) => { ParametricsDistanceActionOld pd = new ParametricsDistanceActionOld(o1, o2, feedback, pls.Plane, soa.Frame); soa.Frame.SetAction(pd); return(true); }; mh.OnSelected = (m, selected) => { currentMenuSelection.Clear(); currentMenuSelection.AddRange(feedbackArrow); currentMenuSelection.Add(o1.OtherFace(face)); currentMenuSelection.Add(o2.OtherFace(face)); currentView.Invalidate(PaintBuffer.DrawingAspect.Select, currentView.DisplayRectangle); }; res.Add(mh); } } } } } } if (res.Count > 6) { List <MenuWithHandler> lm = new List <MenuWithHandler>(); for (int i = 4; i < res.Count; i++) { lm.Add(res[i]); } res.RemoveRange(4, lm.Count); MenuWithHandler subMenu = new MenuWithHandler("MenuId.More"); subMenu.SubMenus = lm.ToArray(); res.Add(subMenu); } return(res); }
void ICommandHandler.OnSelected(MenuWithHandler selectedMenuItem, bool selected) { selectActionContextMenu.currentMenuSelection.Clear(); selectActionContextMenu.currentMenuSelection.AddRange(involvedFaces); selectActionContextMenu.currentView.Invalidate(PaintBuffer.DrawingAspect.Select, selectActionContextMenu.currentView.DisplayRectangle); }
private void ShowContextMenu(Point mousePoint, IView vw) { currentView = vw; GeoObjectList result = new GeoObjectList(); int pickRadius = soa.Frame.GetIntSetting("Select.PickRadius", 5); Projection.PickArea pa = vw.Projection.GetPickSpace(new Rectangle(mousePoint.X - pickRadius, mousePoint.Y - pickRadius, pickRadius * 2, pickRadius * 2)); IActionInputView pm = vw as IActionInputView; GeoObjectList fl = vw.Model.GetObjectsFromRect(pa, new Set <Layer>(pm.GetVisibleLayers()), PickMode.onlyFaces, null); // returns all the face under the cursor // in most cases there is only a single face, which is of interest, only when we have two solids with same or overlapping faces // and one of them is not selectable without also selecting the other, we want both. faces = new List <Face>(); shells = new List <Shell>(); // only Shells, which are not part of a Solid solids = new List <Solid>(); features = new List <IEnumerable <Face> >(); double delta = vw.Model.Extent.Size * 1e-4; double mindist = double.MaxValue; for (int i = 0; i < fl.Count; i++) { if (fl[i] is Face face) // this should always be the case { double z = face.Position(pa.FrontCenter, pa.Direction, 0); if (z < mindist) { if (z < mindist - delta) { faces.Clear(); } faces.Add(face); mindist = z; } } } HashSet <Edge> relevantEdges = new HashSet <Edge>(); for (int i = 0; i < faces.Count; i++) { relevantEdges.UnionWith(faces[i].AllEdges); if (faces[i].Owner is Shell shell) { if (shell.Owner is Solid sld) { if (!solids.Contains(sld)) { solids.Add(sld); } } else { if (!shells.Contains(shell)) { shells.Add(shell); } } } } for (int i = 0; i < faces.Count; i++) { if (faces[i].Owner is Shell shell) { for (int j = 0; j < faces[i].OutlineEdges.Length; j++) { Edge edg = faces[i].OutlineEdges[j]; if (edg.IsPartOfHole(edg.OtherFace(faces[i]))) { Face otherFace = edg.OtherFace(faces[i]); if (otherFace != null) { Edge[] hole = otherFace.GetHole(edg); List <Edge[]> loops = new List <Edge[]> { hole }; List <IEnumerable <Face> > lfeatures = new List <IEnumerable <Face> >(); List <IEnumerable <Face> > lids = new List <IEnumerable <Face> >(); HashSet <Face> startWith = new HashSet <Face>(); foreach (Edge edge in hole) { startWith.Add(edge.OtherFace(otherFace)); // all faces that are connected to the hole in "otherFace" } shell.FeaturesFromEdges(loops, lfeatures, lids, startWith); for (int k = 0; k < lfeatures.Count; k++) { if (lfeatures[k].Count() < shell.Faces.Length * 0.5) { features.Add(lfeatures[k]); } } } } } } } curves = vw.Model.GetObjectsFromRect(pa, new Set <Layer>(pm.GetVisibleLayers()), PickMode.onlyEdges, null); // returns edges and curves edges = new List <Edge>(); // we only accept edges, which belong to one of the selected faces for (int i = curves.Count - 1; i >= 0; --i) { if (curves[i].Owner is Edge edge) { if (relevantEdges.Contains(edge)) { edges.Add(edge); } else { double z = curves[i].Position(pa.FrontCenter, pa.Direction, 0); if (z - delta < mindist) { edges.Add(edge); // this is an edge in front of the closest face } } curves.Remove(i); } else { double z = curves[i].Position(pa.FrontCenter, pa.Direction, 0); if (z - delta > mindist) { curves.Remove(i); } } } // now we have curves, edges, faces, shells and solids (text, hatch, block, dimension not yet implemented) from the right click // we also need access to the already selected edges and faces to GeoObjectList selobj = soa.GetSelectedObjects(); HashSet <Edge> selectedEdges = new HashSet <Edge>(); HashSet <Face> selectedFaces = new HashSet <Face>(); foreach (IGeoObject go in selobj) { if (go is ICurve && go.Owner is Edge edg) { selectedEdges.Add(edg); } if (go is Face fc) { selectedFaces.Add(fc); } } List <MenuWithHandler> cm = new List <MenuWithHandler>(); Shell owningShell = null; if (edges.Count > 0) { owningShell = (edges[0].Owner as Face).Owner as Shell; } if (owningShell == null && faces.Count > 0) { owningShell = (faces[0].Owner as Shell); } if (owningShell == null && selectedFaces.Count > 0) { owningShell = selectedFaces.First().Owner as Shell; } if (owningShell == null && selectedEdges.Count > 0) { owningShell = (selectedEdges.First().Owner as Face).Owner as Shell; } if (owningShell != null) { for (int i = 0; i < features.Count; i++) { List <Face> featureI = new List <Face>(features[i]); MenuWithHandler mh = new MenuWithHandler("MenuId.Feature"); mh.OnSelected = (m, selected) => { currentMenuSelection.Clear(); currentMenuSelection.AddRange(featureI.ToArray()); currentView.Invalidate(PaintBuffer.DrawingAspect.Select, currentView.DisplayRectangle); }; MenuWithHandler positionFeature = new MenuWithHandler("MenuId.Feature.Position"); MenuWithHandler nameFeature = new MenuWithHandler("MenuId.Feature.Name"); mh.SubMenus = new MenuWithHandler[] { positionFeature, nameFeature }; // this is very rudimentary. We have to provide a version of ParametricsDistanceAction, where you can select from and to object. Only axis is implemented Shell shell = featureI[0].Owner as Shell; GeoObjectList fa = shell.FeatureAxis; Line axis = null; foreach (IGeoObject geoObject in fa) { Face axisOf = geoObject.UserData.GetData("CADability.AxisOf") as Face; if (axisOf != null) { if (featureI.Contains(axisOf)) { axis = geoObject as Line; } } if (axis != null) { break; } } positionFeature.OnCommand = (menuId) => { ParametricsDistanceActionOld pd = new ParametricsDistanceActionOld(featureI, soa.Frame); soa.Frame.SetAction(pd); return(true); }; positionFeature.OnSelected = (menuId, selected) => { currentMenuSelection.Clear(); currentMenuSelection.AddRange(featureI.ToArray()); currentView.Invalidate(PaintBuffer.DrawingAspect.Select, currentView.DisplayRectangle); }; nameFeature.OnCommand = (menuId) => { string name = shell.GetNewFeatureName(); shell.AddFeature(name, featureI); if (shell.Owner is Solid sld) { soa.SetSelectedObject(sld); IPropertyEntry toEdit = soa.Frame.ControlCenter.FindItem(name); if (toEdit != null) { List <IPropertyEntry> parents = new List <IPropertyEntry>(); if (toEdit != null) { IPropertyEntry p = toEdit; while ((p = p.Parent as IPropertyEntry) != null) { parents.Add(p); } IPropertyPage propertyPage = parents[parents.Count - 1].Parent as IPropertyPage; if (propertyPage != null) { for (int k = parents.Count - 1; k >= 0; --k) { propertyPage.OpenSubEntries(parents[k], true); } toEdit.StartEdit(false); } } } } return(true); }; nameFeature.OnSelected = (menuId, selected) => { currentMenuSelection.Clear(); currentMenuSelection.AddRange(featureI.ToArray()); currentView.Invalidate(PaintBuffer.DrawingAspect.Select, currentView.DisplayRectangle); }; cm.Add(mh); } } for (int i = 0; i < curves.Count; i++) { // No implementation for simple curves yet. // We would need a logical connection structure as in vertex->edge->face->shell in 2d curves, which we currently do not have. Face faceWithAxis = (curves[i] as IGeoObject).UserData.GetData("CADability.AxisOf") as Face; if (faceWithAxis != null) { MenuWithHandler mh = new MenuWithHandler("MenuId.Axis"); mh.SubMenus = GetFacesSubmenus(faceWithAxis).ToArray(); mh.Target = this; IGeoObject curveI = curves[i] as IGeoObject; mh.OnSelected = (m, selected) => { currentMenuSelection.Clear(); currentMenuSelection.Add(curveI); currentView.Invalidate(PaintBuffer.DrawingAspect.Select, currentView.DisplayRectangle); }; cm.Add(mh); } } for (int i = 0; i < edges.Count; i++) { MenuWithHandler mh = new MenuWithHandler(); mh.ID = "MenuId.Edge." + i.ToString(); mh.Text = StringTable.GetString("MenuId.Edge", StringTable.Category.label); List <MenuWithHandler> lmh = new List <MenuWithHandler>(); MenuWithHandler selectMoreEdges = new MenuWithHandler("MenuId.SelectMoreEdges"); lmh.Add(selectMoreEdges); Edge edgeI = edges[i]; selectMoreEdges.OnCommand = (menuId) => { soa.SetSelectedObject(edgeI.Curve3D as IGeoObject); soa.OverwriteMode(PickMode.onlyEdges); return(true); }; lmh.AddRange(edges[i].GetContextMenu(soa.Frame)); mh.SubMenus = lmh.ToArray(); mh.Target = this; cm.Add(mh); } for (int i = 0; i < faces.Count; i++) { MenuWithHandler mh = new MenuWithHandler(); mh.ID = "MenuId.Face." + i.ToString(); mh.Text = StringTable.GetString("MenuId.Face", StringTable.Category.label); List <MenuWithHandler> lmh = new List <MenuWithHandler>(); MenuWithHandler selectMoreFaces = new MenuWithHandler("MenuId.SelectMoreFaces"); lmh.Add(selectMoreFaces); Face faceI = faces[i]; selectMoreFaces.OnCommand = (menuId) => { soa.SetSelectedObject(faceI); soa.OverwriteMode(PickMode.onlyFaces); return(true); }; lmh.AddRange(GetFacesSubmenus(faces[i])); if (owningShell != null) { double thickness = owningShell.GetGauge(faces[i], out HashSet <Face> frontSide, out HashSet <Face> backSide); if (thickness != double.MaxValue && frontSide.Count > 0) { MenuWithHandler gauge = new MenuWithHandler("MenuId.Gauge"); gauge.OnCommand = (menuId) => { ParametricsOffset po = new ParametricsOffset(frontSide, backSide, soa.Frame, thickness); soa.Frame.SetAction(po); return(true); }; gauge.OnSelected = (menuId, selected) => { currentMenuSelection.Clear(); currentMenuSelection.AddRange(frontSide.ToArray()); currentMenuSelection.AddRange(backSide.ToArray()); currentView.Invalidate(PaintBuffer.DrawingAspect.Select, currentView.DisplayRectangle); }; lmh.Add(gauge); } int n = owningShell.GetFaceDistances(faces[i], out List <Face> distanceTo, out List <double> distance, out List <GeoPoint> pointsFrom, out List <GeoPoint> pointsTo); for (int j = 0; j < n; j++) { if (backSide == null || !backSide.Contains(distanceTo[j])) // this is not already used as gauge { HashSet <Face> capturedFaceI = new HashSet <Face>(new Face[] { faces[i] }); HashSet <Face> capturedDistTo = new HashSet <Face>(new Face[] { distanceTo[j] }); double capturedDistance = distance[j]; GeoPoint capturedPoint1 = pointsFrom[j]; GeoPoint capturedPoint2 = pointsTo[j]; GeoObjectList feedbackArrow = currentView.Projection.MakeArrow(pointsFrom[j], pointsTo[j], currentView.Projection.ProjectionPlane, Projection.ArrowMode.circleArrow); MenuWithHandler faceDist = new MenuWithHandler("MenuId.FaceDistance"); faceDist.OnCommand = (menuId) => { ParametricsDistanceAction pd = new ParametricsDistanceAction(capturedFaceI, capturedDistTo, capturedPoint1, capturedPoint2, soa.Frame); soa.Frame.SetAction(pd); return(true); }; faceDist.OnSelected = (menuId, selected) => { currentMenuSelection.Clear(); currentMenuSelection.AddRange(capturedFaceI.ToArray()); currentMenuSelection.AddRange(capturedDistTo.ToArray()); currentMenuSelection.AddRange(feedbackArrow); currentView.Invalidate(PaintBuffer.DrawingAspect.Select, currentView.DisplayRectangle); }; lmh.Add(faceDist); } } } mh.SubMenus = lmh.ToArray(); mh.Target = this; cm.Add(mh); //cm.AddRange(GetFacesSubmenus(faces)); } for (int i = 0; i < faces.Count; i++) { if (faces[i].Owner is Shell shell) { Shell sh = shell.FeatureFromFace(faces[i]); } } for (int i = 0; i < edges.Count; i++) { if (edges[i].PrimaryFace.Owner is Shell shell) { //shell.FeatureFromEdges(edges[i].PrimaryFace); } } for (int i = 0; i < shells.Count; i++) { MenuWithHandler mh = new MenuWithHandler(); mh.ID = "MenuId.Shell." + i.ToString(); mh.Text = StringTable.GetString("MenuId.Shell", StringTable.Category.label); mh.SubMenus = shells[i].GetContextMenu(soa.Frame); mh.Target = this; cm.Add(mh); } for (int i = 0; i < solids.Count; i++) { MenuWithHandler mh = new MenuWithHandler(); mh.ID = "MenuId.Solid." + i.ToString(); mh.Text = StringTable.GetString("MenuId.Solid", StringTable.Category.label); mh.SubMenus = solids[i].GetContextMenu(soa.Frame); mh.Target = this; cm.Add(mh); } { // selection independent menu items MenuWithHandler mh = new MenuWithHandler(); mh.ID = "MenuId.Show"; mh.Text = StringTable.GetString("MenuId.Show", StringTable.Category.label); MenuWithHandler mhShowHidden = new MenuWithHandler(); mhShowHidden.ID = "MenuId.ShowHidden"; mhShowHidden.Text = StringTable.GetString("MenuId.ShowHidden", StringTable.Category.label); mhShowHidden.OnCommand = (menuId) => { foreach (IGeoObject geoObject in vw.Model) { if (geoObject.Layer != null && geoObject.Layer.Name == "CADability.Hidden") { Layer layer = geoObject.UserData.GetData("CADability.OriginalLayer") as Layer; if (layer != null) { geoObject.Layer = layer; } } } return(true); }; MenuWithHandler mhShowAxis = new MenuWithHandler(); mhShowAxis.ID = "MenuId.ShowAxis"; mhShowAxis.Text = StringTable.GetString("MenuId.ShowAxis", StringTable.Category.label); mhShowAxis.OnCommand = (menuId) => { bool isOn = false; foreach (IGeoObject geoObject in vw.Model) { Shell shell = null; if (geoObject is Solid solid) { shell = solid.Shells[0]; } else if (geoObject is Shell sh) { shell = sh; } if (shell != null && shell.FeatureAxis.Count > 0) { isOn = shell.FeatureAxis[0].IsVisible; break; } } using (vw.Canvas.Frame.Project.Undo.UndoFrame) { foreach (IGeoObject geoObject in vw.Model) { if (geoObject is Solid solid) { solid.ShowFeatureAxis = !isOn; } else if (geoObject is Shell shell) { shell.ShowFeatureAxis = !isOn; } } } return(true); }; mhShowAxis.OnUpdateCommand = (menuId, commandState) => { bool isOn = false; foreach (IGeoObject geoObject in vw.Model) { Shell shell = null; if (geoObject is Solid solid) { shell = solid.Shells[0]; } else if (geoObject is Shell sh) { shell = sh; } if (shell != null && shell.FeatureAxis.Count > 0) { isOn = shell.FeatureAxis[0].IsVisible; break; } } commandState.Checked = isOn; return(true); }; mh.SubMenus = new MenuWithHandler[] { mhShowHidden, mhShowAxis }; mh.Target = this; cm.Add(mh); } vw.SetPaintHandler(PaintBuffer.DrawingAspect.Select, new PaintView(OnRepaintSelect)); mousePoint.X += vw.DisplayRectangle.Width / 8; // find a better place for the menu position, using the extent of the objects vw.Canvas.ShowContextMenu(cm.ToArray(), mousePoint, ContextMenuCollapsed); }