.NET

Reply
Active Member
mononull
Posts: 6
Registered: ‎11-01-2013
Message 1 of 13 (662 Views)
Accepted Solution

Editor.SelectAll() to get selection of object IDs not on locked layers

662 Views, 12 Replies
11-01-2013 09:11 AM

I'm trying to get the Editor class to select all entities in model space not on locked layers, and despite the documentation stating "Selects all objects in the current space in which are not locked or frozen."....it will always return the object IDs from all layers regardless of if they are locked, frozen, or even turned off.  I need it to return a selection set without entities on locked layers.  For most of my classes I am using TypedValue to define the entities I want to filter and then creating a SelectionFilter to pass as an argument to Editor.SelectAll(SelectionFilter).  Since SelectAll is selecting all entities regardless of the layer state, is it possible to create a TypedValue to use as a filter for the selection?  Again, my end goal is to select all entities of certain types on only unlocked layers.

 

Here is what I'm doing now.  Would be great if SelectAll actually ignored locked layers or if I could just add a new TypedValue to get entities on only unlocked layers.  Any help is appreciated.

TypedValue[] tvArr = new TypedValue[]
{
    new TypedValue(-4, "<OR")
    new TypedValue(0, "LINE")
    new TypedValue(0, "LWPOLYLINE")
    new TypedValue(0, "POLYLINE")
    new TypedValue(0, "SPLINE")
    new TypedValue(-4, "OR>")
}

PromptSelectionResult psr 
     = editor.SelectAll(new SelectionFilter(tvArr));

ObjectId[] objectIdArr = psr.Value.GetObjectIds();

 


EDIT:  I can create a list of all objects and then open each one for read to see if the layer it is on is locked, but that seems ridiculous I should have to include all the locked and unlocked objects in the same list and then check the layer state after the list is already made.  It works, but ideally this is not the way it should be done.  It's not very efficient.  If I don't want objects on locked layers I should disclude them before the list is finalized.

Hi,

 

If efficiency is the issue, here's a better implementation of the event handler using:

 // Private field used to pass the locked layer names to the event handler
private HashSet<string> locked;
[CommandMethod("TEST1")]
public void SelectionTest1()
{
Document doc = Application.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
Editor ed = doc.Editor;
TypedValue[] filter = new TypedValue[1] { new TypedValue(0, "LINE,LWPOLYLINE,POLYLINE,SPLINE") };
// Fill the HashSet with the locked layer names
this.locked = new HashSet<string>();
using (Transaction tr = db.TransactionManager.StartOpenCloseTransaction())
{
LayerTable lt = (LayerTable)tr.GetObject(db.LayerTableId, OpenMode.ForRead);
foreach (ObjectId id in lt)
{
LayerTableRecord ltr = (LayerTableRecord)tr.GetObject(id, OpenMode.ForRead);
if (ltr.IsLocked)
this.locked.Add(ltr.Name);
}
}
// Temporary register the event handler during the selection ed.SelectionAdded += ed_SelectionAdded; PromptSelectionResult psr = ed.SelectAll(new SelectionFilter(filter)); ed.SelectionAdded -= ed_SelectionAdded; if (psr.Status == PromptStatus.OK) ed.SetImpliedSelection(psr.Value); } // The event handler uses the HashSet to check if the entity layer is locked private void ed_SelectionAdded(object sender, SelectionAddedEventArgs e) { Database db = HostApplicationServices.WorkingDatabase; using (Transaction tr = db.TransactionManager.StartOpenCloseTransaction()) { ObjectId[] ids = e.AddedObjects.GetObjectIds(); for (int i = 0; i < ids.Length; i++) { Entity ent = (Entity)tr.GetObject(ids[i], OpenMode.ForRead); if (this.locked.Contains(ent.Layer)) e.Remove(i); } tr.Commit(); } }

 

Here's an example of the way purposed by Alfred (selection filter with the unlocked layer names)

 [CommandMethod("TEST2")]
public void SelectionTest2()
{
Document doc = Application.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
Editor ed = doc.Editor;
// Get all unlocked layaer names
List<string> unlocked = new List<string>();
using (Transaction tr = db.TransactionManager.StartOpenCloseTransaction())
{
LayerTable lt = (LayerTable)tr.GetObject(db.LayerTableId, OpenMode.ForRead);
foreach (ObjectId id in lt)
{
LayerTableRecord ltr = (LayerTableRecord)tr.GetObject(id, OpenMode.ForRead);
if (!ltr.IsLocked)
unlocked.Add(ltr.Name);
}
}
// Build a selection filter
TypedValue[] filter = new TypedValue[2]{
new TypedValue(0, "LINE,LWPOLYLINE,POLYLINE,SPLINE"),
new TypedValue(8, string.Join(",", GetUnlockedLayers(db)))
};
PromptSelectionResult psr = ed.SelectAll(new SelectionFilter(filter));
if (psr.Status == PromptStatus.OK)
ed.SetImpliedSelection(psr.Value);
}

 

I'm not certain the second one is more efficient than the first one, internally each entity have to be opened to use the layer part of the selection filter...

:

 

Distinguished Mentor
BlackBox_
Posts: 785
Registered: ‎02-25-2013
Message 2 of 13 (649 Views)

Re: Editor.SelectAll() to get selection of object IDs not on locked layers

11-01-2013 10:32 AM in reply to: mononull

I suspect you'd need to P/Invoke acedSSGet() using "_:L", as is done in LISP with (ssget "_:L"), or simply iterate the BlockTableRecord, and filter out DBObjects on locked layers.

 

HTH



"Potential has a shelf life." - Margaret Atwood


Autodesk Exchange Apps ~ Autoloader ~ AutoCAD Security


AutoCAD® 2014, and Civil 3D® 2014 Certified Professional ~ Autodesk® Authorized Developer

*Expert Elite*
_gile
Posts: 2,104
Registered: ‎04-29-2006
Message 3 of 13 (636 Views)

Re : Editor.SelectAll() to get selection of object IDs not on locked layers

11-01-2013 01:08 PM in reply to: mononull

Hi,

 

You can use an event handler for the Editor.SelectionAdded event:

 

        [CommandMethod("TEST")]
        public void SelectionTest()
        {
            Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
            TypedValue[] filter = 
new TypedValue[1] { new TypedValue(0, "LINE,LWPOLYLINE,POLYLINE,SPLINE") }; ed.SelectionAdded += ed_SelectionAdded; PromptSelectionResult psr = ed.SelectAll(new SelectionFilter(filter)); ed.SelectionAdded -= ed_SelectionAdded; if (psr.Status == PromptStatus.OK) ed.SetImpliedSelection(psr.Value); } private void ed_SelectionAdded(object sender, SelectionAddedEventArgs e) { Database db = HostApplicationServices.WorkingDatabase; using (Transaction tr = db.TransactionManager.StartOpenCloseTransaction()) { LayerTable lt = (LayerTable)tr.GetObject(db.LayerTableId, OpenMode.ForRead); ObjectId[] ids = e.AddedObjects.GetObjectIds(); for (int i = 0; i < ids.Length; i++) { Entity ent = (Entity)tr.GetObject(ids[i], OpenMode.ForRead); LayerTableRecord ltr =
(LayerTableRecord)tr.GetObject(lt[ent.Layer], OpenMode.ForRead); if (ltr.IsLocked) e.Remove(i); } tr.Commit(); } }

 

Another way, using a custom system variable is shown here:

http://www.theswamp.org/index.php?topic=40774.msg460479#msg460479

Gilles Chanteau
Active Member
mononull
Posts: 6
Registered: ‎11-01-2013
Message 4 of 13 (620 Views)

Re : Editor.SelectAll() to get selection of object IDs not on locked layers

11-01-2013 02:09 PM in reply to: _gile

Thanks Gile.  Using the event handler appears to still need to loop though the objectIds after the list is already defined.  I have a method of doing that now without the event handler.

Is there another way to get a selection set filtering out the locked layers...like a .NET equivalent to ssget "_:L" the other member posted?  I don't want the user to have to make the selection manually.  I also don't feel like it's necessary to have to create my own crossing window, or the like, with editor.GetSelection.  That's why I was originally using editor.SelectAll.  I might use the event handler or what I already wrote for now, so thanks.  But if anyone has a better way to get a selection set of specific object types on unlocked layers I'd love to hear it.

*Expert Elite*
_gile
Posts: 2,104
Registered: ‎04-29-2006
Message 5 of 13 (605 Views)

Re : Editor.SelectAll() to get selection of object IDs not on locked layers

11-01-2013 09:59 PM in reply to: mononull

Hi,

 

By my side I don't know any other way to filter out objects on locked layers when using Editor.SelectAll() method.

The .NET equivalent for the LISP (ssget "_:L" ...) would be PromptSelectionOptions.RejectObjectsonLockedLayers which is not available with Editor.SelectAll() as with LISP the "_:L" option cannot be combinated with the "X" one (SelectAll equivalent).

Gilles Chanteau
*Expert Elite*
Alfred.NESWADBA
Posts: 9,207
Registered: ‎06-29-2007
Message 6 of 13 (596 Views)

Re : Editor.SelectAll() to get selection of object IDs not on locked layers

11-02-2013 01:18 AM in reply to: mononull

Hi,

 

>> I have a method of doing that now without the event handler.

And that is ...?

 

One option might be to first scan the LayerTable to get a list of layers which are not locked, and use that list as a filter for .SelectAll

   new TypedValue(8, "LAYERA,LAYERC,LAYERX")

 

HTH, - alfred -

-------------------------------------------------------------------------
Alfred NESWADBA
Ingenieur Studio HOLLAUS ... www.hollaus.at
-------------------------------------------------------------------------
Active Member
mononull
Posts: 6
Registered: ‎11-01-2013
Message 7 of 13 (570 Views)

Re : Editor.SelectAll() to get selection of object IDs not on locked layers

11-04-2013 07:28 AM in reply to: Alfred.NESWADBA

    >> I have a method of doing that now without the event handler.

    And that is ...?

 

  • Getting a list of everything and then looping through each item to check if it's on a locked layer.  

 

I'll check out promptselectionoptions, but it needs to be independent of user input and selections.  Also, I didn't want to have to get the extents min and max, zoom, and create my own selection window if selectall could do all the work.  Thanks for the feedback.

*Expert Elite*
_gile
Posts: 2,104
Registered: ‎04-29-2006
Message 8 of 13 (550 Views)

Re : Editor.SelectAll() to get selection of object IDs not on locked layers

11-04-2013 10:04 PM in reply to: mononull

Hi,

 

If efficiency is the issue, here's a better implementation of the event handler using:

        // Private field used to pass the locked layer names to the event handler
        private HashSet<string> locked;

        [CommandMethod("TEST1")]
        public void SelectionTest1()
        {
            Document doc = Application.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            Editor ed = doc.Editor;
            TypedValue[] filter = new TypedValue[1] { new TypedValue(0, "LINE,LWPOLYLINE,POLYLINE,SPLINE") };

	    // Fill the HashSet with the locked layer names
            this.locked = new HashSet<string>();
            using (Transaction tr = db.TransactionManager.StartOpenCloseTransaction())
            {
                LayerTable lt = (LayerTable)tr.GetObject(db.LayerTableId, OpenMode.ForRead);
                foreach (ObjectId id in lt)
                {
                    LayerTableRecord ltr = (LayerTableRecord)tr.GetObject(id, OpenMode.ForRead);
                    if (ltr.IsLocked)
                        this.locked.Add(ltr.Name);
                }
            }
// Temporary register the event handler during the selection ed.SelectionAdded += ed_SelectionAdded; PromptSelectionResult psr = ed.SelectAll(new SelectionFilter(filter)); ed.SelectionAdded -= ed_SelectionAdded; if (psr.Status == PromptStatus.OK) ed.SetImpliedSelection(psr.Value); } // The event handler uses the HashSet to check if the entity layer is locked private void ed_SelectionAdded(object sender, SelectionAddedEventArgs e) { Database db = HostApplicationServices.WorkingDatabase; using (Transaction tr = db.TransactionManager.StartOpenCloseTransaction()) { ObjectId[] ids = e.AddedObjects.GetObjectIds(); for (int i = 0; i < ids.Length; i++) { Entity ent = (Entity)tr.GetObject(ids[i], OpenMode.ForRead); if (this.locked.Contains(ent.Layer)) e.Remove(i); } tr.Commit(); } }

 

Here's an example of the way purposed by Alfred (selection filter with the unlocked layer names)

        [CommandMethod("TEST2")]
        public void SelectionTest2()
        {
            Document doc = Application.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            Editor ed = doc.Editor;

            // Get all unlocked layaer names
            List<string> unlocked = new List<string>();
            using (Transaction tr = db.TransactionManager.StartOpenCloseTransaction())
            {
                LayerTable lt = (LayerTable)tr.GetObject(db.LayerTableId, OpenMode.ForRead);
                foreach (ObjectId id in lt)
                {
                    LayerTableRecord ltr = (LayerTableRecord)tr.GetObject(id, OpenMode.ForRead);
                    if (!ltr.IsLocked)
                        unlocked.Add(ltr.Name);
                }
            }

            // Build a selection filter
            TypedValue[] filter = new TypedValue[2]{ 
                new TypedValue(0, "LINE,LWPOLYLINE,POLYLINE,SPLINE"),
                new TypedValue(8, string.Join(",", GetUnlockedLayers(db))) 
            };

            PromptSelectionResult psr = ed.SelectAll(new SelectionFilter(filter));
            if (psr.Status == PromptStatus.OK)
                ed.SetImpliedSelection(psr.Value);
        }

 

I'm not certain the second one is more efficient than the first one, internally each entity have to be opened to use the layer part of the selection filter...

:

 

Gilles Chanteau
Moderator
Alexander.Rivilis
Posts: 1,431
Registered: ‎04-09-2008
Message 9 of 13 (528 Views)

Re : Editor.SelectAll() to get selection of object IDs not on locked layers

11-05-2013 05:24 AM in reply to: _gile

Hi, Gilles!

What about layer name has dot or comma? :smileyhappy:

1) Some symbols have to be quoted in this string.

2) I'm not sure that the length of string is unlimited. Moreover, as far as I remember, the length of the string should not be more than 255.


Пожалуйста не забывайте про Утвердить в качестве решения! Утвердить в качестве решения и Give Kudos!Баллы
Please remember to Accept Solution! Accept as Solution and Give Kudos!Kudos

*Expert Elite*
Alfred.NESWADBA
Posts: 9,207
Registered: ‎06-29-2007
Message 10 of 13 (513 Views)

Re : Editor.SelectAll() to get selection of object IDs not on locked layers

11-05-2013 09:40 AM in reply to: Alexander.Rivilis

Hi,

 

>> What about layer name has dot or comma?

How do you create layer with comma in the layername? Comma's are not allowed within layernames. Or have you found a way to include a comma I don't know?

 

>> the length of the string should not be more than 255

I have used a list of blocknames with commas and a length > 2000char for filtering .. always worked. So I guess that will work with layernames too.

 

- alfred -

-------------------------------------------------------------------------
Alfred NESWADBA
Ingenieur Studio HOLLAUS ... www.hollaus.at
-------------------------------------------------------------------------
Post to the Community

Have questions about Autodesk products? Ask the community.

New Post
Need installation help?

Start with some of our most frequented solutions or visit the Installation and Licensing Forum to get help installing your software.