public override GeoObjectList GetFeedback(Projection projection) { GetDistanceVector(out GeoPoint startPoint, out GeoPoint endPoint); if (mode.HasFlag(Mode.symmetric)) { GeoObjectList res = new GeoObjectList(); GeoPoint middlePoint = new GeoPoint(startPoint, endPoint); res.AddRange(projection.MakeArrow(middlePoint, startPoint, projection.ProjectionPlane, Projection.ArrowMode.circleArrow)); res.AddRange(projection.MakeArrow(middlePoint, endPoint, projection.ProjectionPlane, Projection.ArrowMode.circleArrow)); return(res); } else { return(projection.MakeArrow(startPoint, endPoint, projection.ProjectionPlane, Projection.ArrowMode.circleArrow)); } }
private bool Refresh() { validResult = false; if (facesToMove.Count > 0 && (facesToKeep.Count > 0 || axisToMove != null)) { FeedBack.ClearSelected(); GeoPoint startPoint = offsetStartPoint; GeoPoint endPoint = startPoint + originalOffset + currentOffset; switch (mode) { case Mode.forward: startPoint = offsetStartPoint; endPoint = startPoint + originalOffset + currentOffset; offsetFeedBack = Frame.ActiveView.Projection.MakeArrow(startPoint, endPoint, feedbackPlane, Projection.ArrowMode.circleArrow); break; case Mode.backward: startPoint = offsetStartPoint + originalOffset; endPoint = startPoint - originalOffset - currentOffset; offsetFeedBack = Frame.ActiveView.Projection.MakeArrow(startPoint, endPoint, feedbackPlane, Projection.ArrowMode.circleArrow); break; case Mode.symmetric: startPoint = offsetStartPoint + 0.5 * originalOffset; offsetFeedBack = Frame.ActiveView.Projection.MakeArrow(startPoint, startPoint + 0.5 * (originalOffset + currentOffset), feedbackPlane, Projection.ArrowMode.circleArrow); offsetFeedBack.AddRange(Frame.ActiveView.Projection.MakeArrow(startPoint, startPoint - 0.5 * (originalOffset + currentOffset), feedbackPlane, Projection.ArrowMode.circleArrow)); break; } offsetFeedBack.AddRange(facesToMove); offsetFeedBack.AddRange(moreForwardFaces); FeedBack.AddSelected(offsetFeedBack); Shell sh = null; for (int m = 0; m <= 1; m++) { // first try without moving connected faces, if this yields no result, try with moving connected faced Parametric parametric = new Parametric(shell); Dictionary <Face, GeoVector> allFacesToMove = new Dictionary <Face, GeoVector>(); switch (mode) { case Mode.forward: foreach (Face face in Extensions.Combine(facesToMove, moreForwardFaces)) { allFacesToMove[face] = currentOffset; } foreach (Face face in Extensions.Combine(facesToKeep, moreBackwardFaces)) { allFacesToMove[face] = GeoVector.NullVector; } break; case Mode.symmetric: foreach (Face face in Extensions.Combine(facesToMove, moreForwardFaces)) { allFacesToMove[face] = 0.5 * currentOffset; } foreach (Face face in Extensions.Combine(facesToKeep, moreBackwardFaces)) { allFacesToMove[face] = -0.5 * currentOffset; } break; case Mode.backward: foreach (Face face in Extensions.Combine(facesToKeep, moreBackwardFaces)) { allFacesToMove[face] = -currentOffset; } foreach (Face face in Extensions.Combine(facesToMove, moreForwardFaces)) { allFacesToMove[face] = GeoVector.NullVector; } break; } parametric.MoveFaces(allFacesToMove, currentOffset, m == 1); if (parametric.Apply()) { sh = parametric.Result(); if (sh != null) { ParametricDistanceProperty.Mode pmode = 0; if (m == 1) { pmode |= ParametricDistanceProperty.Mode.connected; } if (mode == Mode.symmetric) { pmode |= ParametricDistanceProperty.Mode.symmetric; } // create the ParametricDistanceProperty here, because here we have all the information parametric.GetDictionaries(out Dictionary <Face, Face> faceDict, out Dictionary <Edge, Edge> edgeDict, out Dictionary <Vertex, Vertex> vertexDict); // facesToKeep etc. contains original objects of the shell, affectedObjects contains objects of the sh = pm.Result() // the parametricProperty will be applied to sh, so we need the objects from sh object fromHere = null, toHere = null; if (distanceFromHere is Face fromFace) { fromHere = faceDict[fromFace]; } if (distanceFromHere is Edge fromEdge) { fromHere = edgeDict[fromEdge]; } if (distanceFromHere is Vertex fromVertex) { fromHere = vertexDict[fromVertex]; } if (distanceToHere is Face toFace) { toHere = faceDict[toFace]; } if (distanceToHere is Edge toEdge) { toHere = edgeDict[toEdge]; } if (distanceToHere is Vertex toVertex) { toHere = vertexDict[toVertex]; } if (mode == Mode.backward) { parametricProperty = new ParametricDistanceProperty("", Extensions.LookUp(Extensions.Combine(facesToMove, moreForwardFaces), faceDict), Extensions.LookUp(Extensions.Combine(facesToKeep, moreBackwardFaces), faceDict), parametric.GetAffectedObjects(), pmode, toHere, fromHere); } else { parametricProperty = new ParametricDistanceProperty("", Extensions.LookUp(Extensions.Combine(facesToKeep, moreBackwardFaces), faceDict), Extensions.LookUp(Extensions.Combine(facesToMove, moreForwardFaces), faceDict), parametric.GetAffectedObjects(), pmode, fromHere, toHere); } break; } } } if (sh != null) { ActiveObject = sh; validResult = true; return(true); } else { ActiveObject = shell.Clone(); return(false); } } return(false); }
private bool Refresh() { validResult = false; if (forwardFaces.Count > 0 && backwardFaces.Count > 0) { FeedBack.ClearSelected(); GeoPoint startPoint = point1; GeoPoint endPoint = point2; GeoVector dir = (point2 - point1).Normalized; double originalDistance = point2 | point1; switch (mode) { case Mode.forward: endPoint = point2 + (distance - originalDistance) * dir; offsetFeedBack = Frame.ActiveView.Projection.MakeArrow(startPoint, endPoint, feedbackPlane, Projection.ArrowMode.circleArrow); break; case Mode.backward: startPoint = point1 - (distance - originalDistance) * dir; offsetFeedBack = Frame.ActiveView.Projection.MakeArrow(endPoint, startPoint, feedbackPlane, Projection.ArrowMode.circleArrow); break; case Mode.symmetric: startPoint = point1 - 0.5 * (distance - originalDistance) * dir; endPoint = point2 + 0.5 * (distance - originalDistance) * dir; GeoPoint mp = new GeoPoint(startPoint, endPoint); offsetFeedBack = Frame.ActiveView.Projection.MakeArrow(mp, startPoint, feedbackPlane, Projection.ArrowMode.circleArrow); offsetFeedBack.AddRange(Frame.ActiveView.Projection.MakeArrow(mp, endPoint, feedbackPlane, Projection.ArrowMode.circleArrow)); break; } offsetFeedBack.AddRange(forwardFaces); offsetFeedBack.AddRange(backwardFaces); FeedBack.AddSelected(offsetFeedBack); Shell sh = null; for (int m = 0; m <= 1; m++) { // first try without moving connected faces, if this yields no result, try with moving connected faced Parametric parametric = new Parametric(shell); Dictionary <Face, GeoVector> allFacesToMove = new Dictionary <Face, GeoVector>(); GeoVector offset = (distance - originalDistance) * dir; switch (mode) { case Mode.forward: foreach (Face face in forwardFaces) { allFacesToMove[face] = offset; } foreach (Face face in backwardFaces) { allFacesToMove[face] = GeoVector.NullVector; } break; case Mode.symmetric: foreach (Face face in forwardFaces) { allFacesToMove[face] = 0.5 * offset; } foreach (Face face in backwardFaces) { allFacesToMove[face] = -0.5 * offset; } break; case Mode.backward: foreach (Face face in backwardFaces) { allFacesToMove[face] = -offset; } foreach (Face face in forwardFaces) { allFacesToMove[face] = GeoVector.NullVector; } break; } parametric.MoveFaces(allFacesToMove, offset, m == 1); if (parametric.Apply()) { sh = parametric.Result(); if (sh != null) { ParametricDistanceProperty.Mode pmode = 0; if (m == 1) { pmode |= ParametricDistanceProperty.Mode.connected; } if (mode == Mode.symmetric) { pmode |= ParametricDistanceProperty.Mode.symmetric; } // create the ParametricDistanceProperty here, because here we have all the information parametric.GetDictionaries(out Dictionary <Face, Face> faceDict, out Dictionary <Edge, Edge> edgeDict, out Dictionary <Vertex, Vertex> vertexDict); // facesToKeep etc. contains original objects of the shell, affectedObjects contains objects of the sh = pm.Result() // the parametricProperty will be applied to sh, so we need the objects from sh if (mode == Mode.backward) { parametricProperty = new ParametricDistanceProperty("", Extensions.LookUp(forwardFaces, faceDict), Extensions.LookUp(backwardFaces, faceDict), parametric.GetAffectedObjects(), pmode, point2, point1); } else { parametricProperty = new ParametricDistanceProperty("", Extensions.LookUp(backwardFaces, faceDict), Extensions.LookUp(forwardFaces, faceDict), parametric.GetAffectedObjects(), pmode, point1, point2); } break; } } } if (sh != null) { ActiveObject = sh; validResult = true; return(true); } else { ActiveObject = shell.Clone(); return(false); } } return(false); }
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); }