Kean Walmsley


  • About the Author
    Kean on Google+

August 2014

Sun Mon Tue Wed Thu Fri Sat
          1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31            








« Alias Sketch for AutoCAD on Labs | Main | Extending a set of AutoCAD lines using .NET »

January 29, 2010

Creating a nested layer group inside AutoCAD using .NET

As a comment on this previous post, MikeR posted this request:

Hi Kean, I'm the one that instigated this original question about group filters. That part is working fine and I can also set the active group filter in the file. Now I need to make parent & child filters. How can I add child filters to an existing parent filter at the root? Thanks, Mike

The below code is an update of that shown previously, the main addition being the CNLG command to create a nested layer group. I also took the chance to fix a minor bug (I forgot to let the user cancel at one place we request input) and to refactor some newly shared code into the SelectLayers() function.

Here’s the updated C# code:

using Autodesk.AutoCAD.ApplicationServices;

using Autodesk.AutoCAD.DatabaseServices;

using Autodesk.AutoCAD.EditorInput;

using Autodesk.AutoCAD.Runtime;

using Autodesk.AutoCAD.LayerManager;

using System.Collections.Generic;

 

namespace LayerFilters

{

  public class Commands

  {

    [CommandMethod("LLFS")]

    static public void ListLayerFilters()

    {

      Document doc =

        Application.DocumentManager.MdiActiveDocument;

      Database db = doc.Database;

      Editor ed = doc.Editor;

 

      // List the nested layer filters

 

      LayerFilterCollection lfc =

        db.LayerFilters.Root.NestedFilters;

 

      for (int i = 0; i < lfc.Count; i++)

      {

        LayerFilter lf = lfc[i];

        ed.WriteMessage(

          "\n{0} - {1} (can{2} be deleted)",

          i + 1,

          lf.Name,

          (lf.AllowDelete ? "" : "not")

        );

      }

    }

 

    [CommandMethod("CLFS")]

    static public void CreateLayerFilters()

    {

      Document doc =

        Application.DocumentManager.MdiActiveDocument;

      Database db = doc.Database;

      Editor ed = doc.Editor;

 

      try

      {

        // Get the existing layer filters

        // (we will add to them and set them back)

 

        LayerFilterTree lft =

          db.LayerFilters;

        LayerFilterCollection lfc =

          lft.Root.NestedFilters;

 

        // Create three new layer filters

 

        LayerFilter lf1 = new LayerFilter();

        lf1.Name = "Unlocked Layers";

        lf1.FilterExpression = "LOCKED==\"False\"";

 

        LayerFilter lf2 = new LayerFilter();

        lf2.Name = "White Layers";

        lf2.FilterExpression = "COLOR==\"7\"";

 

        LayerFilter lf3 = new LayerFilter();

        lf3.Name = "Visible Layers";

        lf3.FilterExpression =

          "OFF==\"False\" AND FROZEN==\"False\"";

 

        // Add them to the collection

 

        lfc.Add(lf1);

        lfc.Add(lf2);

        lfc.Add(lf3);

 

        // Set them back on the Database

 

        db.LayerFilters = lft;

 

        // List the layer filters, to see the new ones

 

        ListLayerFilters();

      }

      catch (Exception ex)

      {

        ed.WriteMessage(

          "\nException: {0}",

          ex.Message

        );

      }

    }

 

    [CommandMethod("CLG")]

    static public void CreateLayerGroup()

    {

      Document doc =

        Application.DocumentManager.MdiActiveDocument;

      Database db = doc.Database;

      Editor ed = doc.Editor;

 

      // A list of the layers' names & IDs contained

      // in the current database, sorted by layer name

 

      SortedList<string, ObjectId> ld =

        new SortedList<string, ObjectId>();

 

      // A list of the selected layers' IDs

 

      ObjectIdCollection lids =

        new ObjectIdCollection();

 

      // Start by populating the list of names/IDs

      // from the LayerTable

 

      Transaction tr =

        db.TransactionManager.StartTransaction();

      using (tr)

      {

        LayerTable lt =

          (LayerTable)tr.GetObject(

            db.LayerTableId,

            OpenMode.ForRead

          );

        foreach(ObjectId lid in lt)

        {

          LayerTableRecord ltr =

            (LayerTableRecord)tr.GetObject(

              lid,

              OpenMode.ForRead

          );

          ld.Add(ltr.Name, lid);

        }

      }

 

      // Display a numbered list of the available layers

 

      ed.WriteMessage("\nLayers available for group:");

 

      SelectLayers(ed, ld, lids);

 

      // Now we've selected our layers, let's create the group

 

      try

      {

        if (lids.Count > 0)

        {

          // Get the existing layer filters

          // (we will add to them and set them back)

 

          LayerFilterTree lft = db.LayerFilters;

          LayerFilterCollection lfc = lft.Root.NestedFilters;

 

          // Create a new layer group

 

          LayerGroup lg = new LayerGroup();

          lg.Name = "My Layer Group";

 

          // Add our layers' IDs to the list

 

          foreach (ObjectId id in lids)

            lg.LayerIds.Add(id);

 

          // Add the group to the collection

 

          lfc.Add(lg);

 

          // Set them back on the Database

 

          db.LayerFilters = lft;

 

          ed.WriteMessage(

            "\n\"{0}\" group created containing {1} layers.\n",

            lg.Name,

            lids.Count

          );

 

          // List the layer filters, to see the new group

 

          ListLayerFilters();

        }

      }

      catch (Exception ex)

      {

        ed.WriteMessage(

          "\nException: {0}",

          ex.Message

        );

      }

    }

 

    [CommandMethod("CNLG")]

    static public void CreateNestedLayerGroup()

    {

      Document doc =

        Application.DocumentManager.MdiActiveDocument;

      Database db = doc.Database;

      Editor ed = doc.Editor;

 

      // A list of the layers' names & IDs contained

      // in the current database, sorted by layer name

 

      SortedList<string, ObjectId> ld =

        new SortedList<string, ObjectId>();

 

      // A list of the selected layers' IDs

 

      ObjectIdCollection lids =

        new ObjectIdCollection();

 

      // Start by populating the list of names/IDs

      // from the LayerTable

 

      Transaction tr =

        db.TransactionManager.StartTransaction();

      using (tr)

      {

        LayerTable lt =

          (LayerTable)tr.GetObject(

            db.LayerTableId,

            OpenMode.ForRead

          );

        foreach (ObjectId lid in lt)

        {

          LayerTableRecord ltr =

            (LayerTableRecord)tr.GetObject(

              lid,

              OpenMode.ForRead

          );

          ld.Add(ltr.Name, lid);

        }

      }

 

      // Display a numbered list of the available layers

 

      ed.WriteMessage("\nLayers available for nested group:");

 

      SelectLayers(ed, ld, lids);

 

      // Now we've selected our layers, let's create the group

 

      try

      {

        if (lids.Count > 0)

        {

          // Get the existing layer filters

          // (we will add to them and set them back)

 

          LayerFilterTree lft = db.LayerFilters;

          LayerFilterCollection lfc = lft.Root.NestedFilters;

 

          Dictionary<int, int> idxMap = new Dictionary<int, int>();

 

          // List the nested layer filters

 

          int lfNum = 1;

 

          for (int i = 0; i < lfc.Count; i++)

          {

            LayerFilter lf = lfc[i];

 

            if (lf.AllowNested)

            {

              ed.WriteMessage(

                "\n{0} - {1}", lfNum, lf.Name

              );

              idxMap.Add(lfNum++, i);

            }

          }

 

          if (lfNum == 1)

          {

            ed.WriteMessage(

              "\nNo filters found that allow nesting."

            );

          }

          else

          {

            // We will ask the user to select from the list

 

            PromptIntegerOptions pio =

              new PromptIntegerOptions(

                "\nEnter number of parent filter: "

              );

            pio.LowerLimit = 1;

            pio.UpperLimit = lfNum;

            pio.AllowNone = false;

 

            PromptIntegerResult pir = ed.GetInteger(pio);

 

            if (pir.Status != PromptStatus.OK)

              return;

 

            LayerFilter parent = lfc[idxMap[pir.Value]];

 

            // Create a new layer group

 

            LayerGroup lg = new LayerGroup();

            lg.Name = "My Nested Layer Group";

 

            // Add the group to the collection

 

            parent.NestedFilters.Add(lg);

 

            // Add our layers' IDs to the list

 

            foreach (ObjectId id in lids)

              lg.LayerIds.Add(id);

 

            // Set them back on the Database

 

            db.LayerFilters = lft;

 

            ed.WriteMessage(

              "\n\"{0}\" nested group added to parent \"{1}\" " +

              "containing {2} layers.\n",

              lg.Name,

              parent.Name,

              lids.Count

            );

          }

        }

      }

      catch (Exception ex)

      {

        ed.WriteMessage(

          "\nException: {0}",

          ex.Message

        );

      }

    }

 

    private static void SelectLayers(

      Editor ed,

      SortedList<string, ObjectId> ld,

      ObjectIdCollection lids

    )

    {

      int i = 1;

      foreach (KeyValuePair<string, ObjectId> kv in ld)

      {

        ed.WriteMessage(

          "\n{0} - {1}",

          i++,

          kv.Key

        );

      }

 

      // We will ask the user to select from the list

 

      PromptIntegerOptions pio =

        new PromptIntegerOptions(

          "\nEnter number of layer to add: "

        );

      pio.LowerLimit = 1;

      pio.UpperLimit = ld.Count;

      pio.AllowNone = true;

 

      // And will do so in a loop, waiting for

      // Escape or Enter to terminate

 

      PromptIntegerResult pir;

      do

      {

        // Select one from the list

 

        pir = ed.GetInteger(pio);

 

        if (pir.Status == PromptStatus.OK)

        {

          // Get the layer's name

 

          string ln = ld.Keys[pir.Value - 1];

 

          // And then its ID

 

          ObjectId lid;

          ld.TryGetValue(ln, out lid);

 

          // Add the layer'd ID to the list, is it's not

          // already on it

 

          if (lids.Contains(lid))

          {

            ed.WriteMessage(

              "\nLayer \"{0}\" has already been selected.",

              ln

            );

          }

          else

          {

            lids.Add(lid);

            ed.WriteMessage(

              "\nAdded \"{0}\" to selected layers.",

              ln

            );

          }

        }

      } while (pir.Status == PromptStatus.OK);

    }

 

    [CommandMethod("DLF")]

    static public void DeleteLayerFilter()

    {

      Document doc =

        Application.DocumentManager.MdiActiveDocument;

      Database db = doc.Database;

      Editor ed = doc.Editor;

 

      ListLayerFilters();

 

      try

      {

        // Get the existing layer filters

        // (we will add to them and set them back)

 

        LayerFilterTree lft = db.LayerFilters;

        LayerFilterCollection lfc = lft.Root.NestedFilters;

 

        // Prompt for the index of the filter to delete

 

        PromptIntegerOptions pio =

          new PromptIntegerOptions(

          "\n\nEnter index of filter to delete"

          );

        pio.LowerLimit = 1;

        pio.UpperLimit = lfc.Count;

 

        PromptIntegerResult pir =

          ed.GetInteger(pio);

 

        if (pir.Status != PromptStatus.OK)

          return;

 

        // Get the selected filter

 

        LayerFilter lf = lfc[pir.Value - 1];

 

        // If it's possible to delete it, do so

 

        if (!lf.AllowDelete)

        {

          ed.WriteMessage(

            "\nLayer filter cannot be deleted."

          );

        }

        else

        {

          lfc.Remove(lf);

          db.LayerFilters = lft;

 

          ListLayerFilters();

        }

      }

      catch(Exception ex)

      {

        ed.WriteMessage(

          "\nException: {0}",

          ex.Message

        );

      }

    }

  }

}

To see this code in action, let’s start by creating a bunch of layers using the layer manager:

A bunch of new layers

Now let’s create a parent layer group using the CLG command:

Command: CLG

Layers available for group:

1 - 0

2 - Layer1

3 - Layer2

4 - Layer3

5 - Layer4

6 - Layer5

7 - Layer6

8 - Layer7

9 - Layer8

10 - Layer9

Enter number of layer to add: 2

Added "Layer1" to selected layers.

Enter number of layer to add: 3

Added "Layer2" to selected layers.

Enter number of layer to add: 4

Added "Layer3" to selected layers.

Enter number of layer to add:

 

"My Layer Group" group created containing 3 layers.

 

1 - My Layer Group (can be deleted)

2 - All Used Layers (cannot be deleted)

3 - Unreconciled New Layers (cannot be deleted)

4 - Viewport Overrides (cannot be deleted)

From here we can use the CNLG command to create our nested filter, selecting the newly-created parent:

Command: CNLG

Layers available for nested group:

1 - 0

2 - Layer1

3 - Layer2

4 - Layer3

5 - Layer4

6 - Layer5

7 - Layer6

8 - Layer7

9 - Layer8

10 - Layer9

Enter number of layer to add: 5

Added "Layer4" to selected layers.

Enter number of layer to add: 6

Added "Layer5" to selected layers.

Enter number of layer to add: 7

Added "Layer6" to selected layers.

Enter number of layer to add: 8

Added "Layer7" to selected layers.

Enter number of layer to add:

 

1 - My Layer Group

Enter number of parent filter: 1

 

"My Nested Layer Group" nested group added to parent "My Layer Group"

containing 4 layers.

Now let’s see the results in the layer manager. First the nested group with its four layers:

Our nested layer group

And now the parent group with the additional three layers (making seven, in total):

Our parent layer group

blog comments powered by Disqus

10 Random Posts