Close

Relief for ODA Team in Ukraine

Learn more
ODA Drawings SDK
Example of Working with the Layer Table Object

This example demonstrates working with the layer table object for adding, renaming, deleting, recovering, modifying, and printing layer record objects. This example uses a console menu for the following operations: printing the list of accessible layers [L], printing specific properties of all layers contained in the table [P], exposing predefined layers [E], creating predefined layers [X], creating a new layer and adding it in the table [A], renaming an existing layer [N], deleting an existing layer [D], recovering a deleted layer [R], setting a layer to be the active layer [S], and generating usage data [U].

The ModifyLayers() function requires a pointer to the database object and implements a console menu for the listed operations. The function creates a loop that inquires about the operation and uses the switch statement to select whether the case must be performed. The ModifyLayers() function uses the PrintListPredefinedLayers() function for displaying information about predefined layers of the database, PrintLayerProperties() function for displaying specific properties of the layer record object, ModifyLayerProperties() function for modifying specific properties of the selected layer record object, and EntryRecordName() function for entering the layer name, checking whether the name is correct, and for checking whether the name exists or is absent form the table. The EntryRecordName() function returns the entered name as an OdString value when the name is correct for the specified options, or it returns an empty string when the name is incorrect or is in conflict with other names. The ModifyLayers() function obtains a smart pointer to the layer table object using the getLayerTableId() method of the passed database object. Before the loop, the function creates an iterator using the newIterator() method of the layer table object and declares the smart pointer to the layer record object. The ModifyLayers() function processes user actions in the loop until the user selects the [Q] operation.

When the user selects [L], the ModifyLayers() function prints the list of layer names accessed in the layer table. The function uses the iterator for traversing through the layer table, getRecord() method of the Iterator object for getting the pointer to each layer record object, and getName() method for displaying the name of each layer record object to which the iterator refers. When the user selects [P], the function prints the specific properties of all layer record objects contained in the layer table object, including objects marked as "erased". The function uses the iterator for traversing through the layer table and the PrintLayerProperties() function for displaying specific properties of the layer record objects to which the iterator refers. For [P] operation, the function initializes the start() method of the iterator using parameters: True – beginning with the first record to the end record of the table, False – the record marked as unerased or erased, and uses the step() method of the iterator using parameters: True – traversing to the next record in the table, False – including unerased and erased records. For [L] operation, the function initializes the arguments of the start() and step() methods using default values:  True – beginning with the first record to the next record, and True – only unerased records. When a layer record object has been permanently deleted, the getRecord() method returns NULL and the function and iterator skip the record. When the user selects [U], the function generates usage data for layers and goes to the [P] operation for displaying the specific properties.

When the user selects [A], the ModifyLayers() function inquires about the name of a new layer record object using the EntryRecordName() function. The name must be absent from the layer table because the table cannot contain duplicate records; the function passes the kMustAbsent value as the second argument for checking the new name. If the entered name is correct and absent from the table, the function creates a new layer record object using its static pseudo-constructor. Then, the function sets the specified name for the created layer record object using its setName() method, and adds the new layer in the layer table using the add() method of the layer table object. The function uses the try…catch statement to catch exceptions when the object is added. If the addition is successful, the function goes to the [L] operation for printing of the layer list. When an exception occurs, the function displays an error message and breaks to the console menu.

When the user selects [N], the ModifyLayers() function inquires about the name of the existing layer record object to be renamed and the new name using the EntryRecordName() function for both names. The first name must exist in the layer table; the function passes the kMustExist value as a second argument for checking the entered name. The second name must be absent from the layer table because the table cannot contain duplicate records; the function passes the kMustAbsent value as the second argument for checking the new name. If the first entered name is correct and exists in the table, the function gets the smart pointer to the existing layer record object specified by the first name using the getAt() method of the layer table object and opens it in write mode. Then, the function sets the second name as a new name of the opened layer record object using its setName() method. The function uses the try…catch statement to catch exceptions when the object changes the name. When an exception occurs, the function displays an error message and breaks to the console menu.

When the user selects [D], the ModifyLayers() function inquires about the name of the existing layer record object to be deleted using the EntryRecordName() function. The name must exist in the layer table; the function passes the kMustExist value as the second argument for checking the entered name. If the entered name is correct and exists in the table, the ModifyLayers() function gets a smart pointer to the corresponding layer record object using the getAt() method of the layer table object and opens it in write mode. The function passes a False value for the third argument of the getAt() method to identify the unerased record of the table. If the getAt() method returns a pointer to the specified layer record object, the function calls the erase() method of the layer record object and passes to it a True value as an argument. The erase(true) method marks the layer record object as "erased" and keeps it in the table if and only if the database is performing an undo operation, otherwise the object is deleted permanently. After deletion, the function checks the result returned by the erase() method. If the result is zero, the deletion is successful, and the function breaks to the console menu. If the result is non-zero, the function displays an error message using the getErrorDescription() method of the host object.

When the user selects [R], the ModifyLayers() function inquires about the name of the deleted layer record object to be recovered using the EntryRecordName() function. The inquired name must be absent from the layer table because the deleted record is not accessible in the table; the function passes the kMustAbsent value as a second argument for checking the entered name. If the entered name is correct and is absent from the table, the ModifyLayers() function tries to get a smart pointer to the corresponding layer record object using the getAt() method of the layer table object and open it in write mode; the function passes a True value for the third argument of the getAt() method to identify the erased record of the table. If the getAt() method returns NULL, the layer record object was deleted permanently and recovery is impossible. In this case, the function displays an error message and breaks to the the console menu. If the getAt() method returns a pointer to the deleted layer record object, the function calls the erase() method of the layer record object and passes to it a False value as an argument. The erase(false) method marks the layer record object as "unerased" and the record becomes accessible in the table. After recovery, the function checks the result returned by the erase() method. If the result is zero, the recovery is successful, and the function breaks to the the console menu. If the result is non-zero, the function displays an error message using the getErrorDescription() method of the host object.

When the user selects [M], the ModifyLayers() function inquires about the name of the existing layer record object to be modified using the EntryRecordName() function. The name must exist in the layer table; the function passes the kMustExist value as the second argument for checking the entered name. If the entered name is correct and exists in the table, the ModifyLayers() function gets the smart pointer to the corresponding layer record object using the getAt() method of the layer table object and opens it in write mode. Then, the function calls the ModifyLayerProperties() function that organizes its own console menu for modifying specific properties of the specified layer record object.

When the user selects [S], the ModifyLayers() function inquires about the name of the existing layer record object which should be active using the EntryRecordName() function. The name must exist in the layer table; the function passes the kMustExist value as a second argument for checking the entered name. If the entered name is correct and exists in the table, the ModifyLayers() function gets the Object ID of the layer record object using the getAt() method and passes the Object ID as an argument of the setCLAYER() method of the database object. The setCLAYER() method makes the specified layer the active layer.

When the user selects [E], the ModifyLayers() function displays the predefined layers using the getCLAYER() method of the database object and the PrintListPredefinedLayers() function. The getCLAYER() method returns the Object ID of the current active layer. The PrintListPredefinedLayers() function requires a pointer to the database object and displays information about predefined layers of the database; the function gets the Object ID for each predefined layer using the following methods of the database object: getLayerZeroId() – gets the Zero layer, getLayerDefpointsId() – gets the Defpoints layer, getLayerAdskId() – gets the Constraints layer or SystemLights layer. The database contains the Zero layer initially, but other layers can be absent — the PrintListPredefinedLayers() function checks each returned Object ID to see whether the ID is OdDb::kNull. If the Object ID is not kNull, the predefined layer exists and the function gets a smart pointer to it using the safeOpenObject() method and gets its name using the getName() method. The getLayerAdskId() method requires the layer type to be returned as an argument of the OdDb::LayerAdskType enumerator (kLayerSystemLights or kLayerConstraints).

When the user selects [X], the ModifyLayers() function creates the predefined layers. The getLayerDefpointsId() requires True value as an argument for creating the Defpoints layer when it is absent. The getLayerAdskId() either requires the OdDb::kLayerConstraints enumerator as the first argument and True value as second argument for creating the Constraints layer when it is absent or the OdDb::kLayerSystemLights enumerator as the first argument and True value as a second argument for creating the SystemLights layer when it is absent.

When the user selects [Q], the function ends the loop and returns in the calling function.

The ModifyLayers() function has the following implementation:


#include "..\Common\DemoMain.h"
#include "DbLayerTable.h"
#include "DbLayerTableRecord.h"
#include <iostream>
using namespace std;

void PrintLayerProperties(OdDbLayerTableRecord* pLayer);
void ModifyLayerProperties(OdDbLayerTableRecord* pLayer);

void ModifyLayers(OdDbDatabase* pDb)
{
  wchar_t ch = L'L';
  OdString sName;
  OdResult result;

  OdDbLayerTablePtr pLayers = pDb->getLayerTableId().safeOpenObject(OdDb::kForWrite);
  OdDbSymbolTableIteratorPtr itLayer = pLayers->newIterator();
  OdDbLayerTableRecordPtr pLayer;

  wcout << L"\n\nStart modifying of layers"
        << L"\nLayer's Table: " << pLayers->handle().ascii() 
        << L", Class: " << OdDbLayerTable::desc()->name() 
        << L", Record: " << OdDbLayerTableRecord::desc()->name()
        << L", Iterator: " << itLayer->isA()->name() << L"\n";

  do {
    switch(ch)
    {
      case L'A':          // Add a new layer
      case L'a':
        wcout << L"\nEntry the name of a new layer:>";
        if((sName = EntryRecordName(pLayers, kMustAbsent)).isEmpty()) break;

        pLayer = OdDbLayerTableRecord::createObject();
        
        try {
          pLayer->setName(sName);     
          pLayers->add(pLayer);
        }
        catch(OdError& e)
        {
          wcout << L"\nError: " << e.code() << L" - " << e.description() << L"\n";
          pLayer->erase();
          break;
        }


      case L'L':          // List the accessible layers
      case L'l':
        wcout << L"\nList of the accessible layers:\n"; 
        for(itLayer->start() ; !itLayer->done() ; itLayer->step())
        {
          wcout << "\"" << itLayer->getRecord()->getName() << L"\"\n";
        }
        break;


      case L'U':          // Generate usage data for layers
      case L'u':
        pLayers->generateUsageData();


      case L'P':          // Print the specific properties of all layers
      case L'p':
        wcout << L"\nList the specific properties of layers:"; 
        for(itLayer->start(true, false) ; !itLayer->done() ; itLayer->step(true, false))
        {
          pLayer = itLayer->getRecord(OdDb::kForRead, true);
 	  PrintLayerProperties(pLayer.get());
        }
        wcout << L"\n";
        break;


      case L'S':          // Set the current active layer
      case L's':
        wcout << L"\nEntry the layer name to be set active:>";
        if((sName = EntryRecordName(pLayers, kMustExist)).isEmpty()) break;

        pDb->setCLAYER(pLayers->getAt(sName));
        break;


      case L'E':          // Expose the predefined layers
      case L'e':
        pLayer = pDb->getCLAYER().safeOpenObject();
        wcout << L"\nCurrent active layer: \"" << pLayer->getName() << L"\"";
        PrintListPredefinedLayers(pDb);
        break;


      case L'X':          // Create the predefined layers
      case L'x':
        pDb->getLayerDefpointsId(true);
        pDb->getLayerAdskId(OdDb::kLayerConstraints, true);
        pDb->getLayerAdskId(OdDb::kLayerSystemLights, true);
        PrintListPredefinedLayers(pDb);
        break;


      case L'N':          // Rename the selected layer
      case L'n':
        wcout << L"\nEntry the layer name to be renamed:>";
        if((sName = EntryRecordName(pLayers, kMustExist)).isEmpty()) break;

        pLayer = pLayers->getAt(sName, OdDb::kForWrite);

        wcout << L"\nEntry the new layer name:>";
        if((sName = EntryRecordName(pLayers, kMustAbsent)).isEmpty()) break;

        try {
          pLayer->setName(sName);     
        }
        catch(OdError& e) { wcout << L"\nError: " << e.code() << L" - " << e.description() << L"\n"; }
        break;


      case L'D':          // Delete the selected layer
      case L'd':
        wcout << L"\nEntry the layer name to be deleted:>";
        if((sName = EntryRecordName(pLayers, kMustExist)).isEmpty()) break;

        pLayer = pLayers->getAt(sName, OdDb::kForWrite, false);

        if(pLayer->objectId() == pDb->getLayerZeroId())
        {
          wcout << L"\nError: Zero layer can not be deleted\n";
          break;
        }
        if(pLayer->objectId() == pDb->getCLAYER())
        {
          wcout << L"\nError: Current active layer can not be deleted\n";
          break;
        }

        result = pLayer->erase(true);

        if(result) wcout << L"\nError: " << result << L" - " << pDb->appServices()->getErrorDescription(result) << L"\n"; 
        break;


      case L'R':          // Recover the deleted layer
      case L'r':
        wcout << L"\nEntry the layer name to be recovered:>";
        if((sName = EntryRecordName(pLayers, kMustAbsent)).isEmpty()) break;

        pLayer = pLayers->getAt(sName, OdDb::kForWrite, true);

        if(pLayer.isNull())
        {
          wcout << L"\nThe layer \"" << sName << L"\" - was deleted permanently\n";
          break;
        }

        result = pLayer->erase(false);
				
        if(result) wcout << L"\nError: " << result << L" - " << pDb->appServices()->getErrorDescription(result) << L"\n"; 
        break;


      case L'M':          // Modify the selected layer
      case L'm':
       	wcout << L"\nEntry the layer name to be modified:>";
        if((sName = EntryRecordName(pLayers, kMustExist)).isEmpty()) break;

        pLayer = pLayers->getAt(sName, OdDb::kForWrite);

        ModifyLayerProperties(pLayer.get());
        break;


      case L'\0':         // Skip an action
        break;

      default:
        wcout << L"Error: Incorrect operation\n";
    }
    wcout << L"\nL. List the accessible layers";
    wcout << L"\nP. Print the properties of all layers";
    wcout << L"\nE. Expose the predefined layers";
    wcout << L"\nX. Create the predefined layers";
    wcout << L"\nA. Add a new layer";
    wcout << L"\nS. Set the current active layer";
    wcout << L"\nN. Rename the selected layer";
    wcout << L"\nM. Modify the selected layer";
    wcout << L"\nD. Delete the selected layer";
    wcout << L"\nR. Recover the deleted layer";
    wcout << L"\nU. Generate usage data for layers";
    wcout << L"\nQ. Quit";
    wcout << L"\nSelect operation:>";
    wcin >> ch;
  }
  while(ch != L'Q' && ch != L'q');

  wcout << L"Stop modifying of layers\n";
}


void PrintListPredefinedLayers(OdDbDatabase* pDb)
{
  OdDbObjectId ID;
  OdDbLayerTableRecordPtr pLayer;

  ID = pDb->getLayerZeroId();
  if(ID.isNull())
    wcout << L"\nZero Layer is undefined";
  else 
  {
    pLayer = ID.safeOpenObject(OdDb::kForRead);
    wcout << L"\nZero layer: \"" << pLayer->getName() << L"\"";
  }

  ID = pDb->getLayerDefpointsId();
  if(ID.isNull())
    wcout << L"\nDefpoints layer is undefined";
  else 
  {
    pLayer = ID.safeOpenObject(OdDb::kForRead);
    wcout << L"\nDefpoints layer: \"" << pLayer->getName() << L"\"";
  }

  ID = pDb->getLayerAdskId(OdDb::kLayerConstraints);
  if(ID.isNull())
    wcout << L"\nConstraints layer is undefined";
  else 
  {
    pLayer = ID.safeOpenObject(OdDb::kForRead);
    wcout << L"\nConstraints layer: \"" << pLayer->getName() << L"\"";
  }

  ID = pDb->getLayerAdskId(OdDb::kLayerSystemLights);
  if(ID.isNull())
    wcout << L"\nSystemLights layer is undefined\n";
  else 
  {
    pLayer = ID.safeOpenObject(OdDb::kForRead);
    wcout << L"\nSystemLights layer: \"" << pLayer->getName() << L"\"\n";
  }
}

Testing gives the following results:


Start modifying of layers
Layer's Table: 2, Class: AcDbLayerTable, Record: AcDbLayerTableRecord, Iterator: OdDbSymbolTableIterator

List of the accessible layers:
"0"

L. List the accessible layers
P. Print the properties of all layers
E. Expose the predefined layers
X. Create the predefined layers
A. Add a new layer
S. Set the current active layer
N. Rename the selected layer
M. Modify the selected layer
D. Delete the selected layer
R. Recover the deleted layer
U. Generate usage data for layers
Q. Quit
Select operation:>

When the operation is A-"Add a new layer":


Entry the name of a new layer:>underlayer
List of the accessible layers:
"0"
"underlayer"

When the operation is A-"Add a new layer" and the name exists in the table:


Entry the name of a new layer:>0
Error: the name "0" - already exists

When the operation is A-"Add a new layer" and the name is incorrect:


Entry the name of a new layer:>S?b*r:c"
Error: the name contains inadmissible letters: <>/\":;?,|=`

When the operation is N-"Rename the selected layer":


Entry the layer name to be renamed:>underlayer
Entry the new layer name:>substrate

When the operation is N-"Rename the selected layer" and the name is absent from the table:


Entry the layer name to be renamed:>underlayer
Error: the name "underlayer" - is not found

When the operation is N-"Rename the selected layer" and the name is incorrect:


Entry the layer name to be renamed:>substrate
Entry the new layer name:>S?b*r:c"
Error: the name contains inadmissible letters: <>/\":;?,|=`

When the operation is N-"Rename the selected layer" and the new name exists in the table:


Entry the layer name to be renamed:>substrate
Entry the new layer name:>0
Error: the name "0" - already exists

Repeat the operation A-"Add a new layer":


Entry the name of a new layer:>BasePlan
List of the accessible layers:
"0"
"substrate"
"BasePlan"

When the operation is S-"Set the current active layer":


Entry the layer name to be set active:>BasePlan

When the operation is E-"Expose the predefined layers":


Current active layer: "BasePlan"
Zero layer: "0"
Defpoints layer is undefined
Constraints layer is undefined
SystemLights layer is undefined

When the operation is D-"Delete the selected layer":


Entry the layer name to be deleted:>substrate

When the operation is D-"Delete the selected layer" and the name is absent from the table or the record is already deleted:


Entry the layer name to be deleted:>substrate
Error: the name "substrate" - is not found

When the operation is D-"Delete the selected layer" and the layer is active or is predefined:


Entry the layer name to be deleted:>BasePlan
Error: Current active layer can not be deleted

Entry the layer name to be deleted:>0
Error: Zero layer can not be deleted

When the operation is M-"Modify the selected layer":


Entry the layer name to be modified:>BasePlan
Start modifying of the layer properties

Selected layer: "BasePlan"
W. Set the lineweight
D. Set the description
L. Set the lock status
A. Set the plot status
O. Set the on-off status
F. Set the freeze status
H. Set the hidden status
R. Set the reconcile status
C. Set the color value
I. Set the color index
Y. Set the linetype object
M. Set the material object
T. Set the transparency value
P. Print the specific properties
Q. Quit
Select operation:>L

Entry the Lock status [L-lock|U-unlock]:>L
Status is set to: Locked

Select operation:>L

Entry the On-Off status [F-turn off|N-turn on]:>F
Status is set to: OFF

Select operation:>I

Current color index: 7
Entry a new color index [1...255]:>24
Color is set to: [byACI=24]

Select operation:>Q
Stop modifying of the layer properties

When the operation is U-"Generate usage data for layers" and P-"Print the specific properties of all layers":


List the specific properties of layers:
H=10
  Name = "0"
  Status: unerased,resident
  Description: "Zero Layer"
  Layer_Status: InUse, Thawed, ON, Unlocked, Plotable, Shown
  Lineweight:[kLnWtByLwDefault]
  Linetype: [16-"Continuous"-Linetype]
  Material: [2E-"Global"-Material]
  Color: [Foreground]
  Transparency: [byAlpha=100.0%]
H=3F
  Name = "substrate"
  Status: erased,resident
  Description: ""
  Layer_Status: Unused, Thawed, ON, Unlocked, Plotable, Shown
  Lineweight: [kLnWtByLwDefault]
  Linetype: [16-"Continuous"-Linetype]
  Material: [2E-"Global"-Material]
  Color: [Foreground]
  Transparency: [byAlpha=100.0%]
H=40
  Name = "BasePlan"
  Status: unerased,resident,modified
  Description: ""
  Layer_Status: InUse, Thawed, OFF, Locked, Plotable, Shown
  Lineweight: [kLnWtByLwDefault]
  Linetype: [16-"Continuous"-Linetype]
  Material: [2E-"Global"-Material]
  Color: [byACI=24]
  Transparency: [byAlpha=100.0%]

When the operation is L-"List the accessible layers":


List of the accessible layers:
"0"
"BasePlan"

When the operation is R-"Recover the deleted layer":


Entry the layer name to be recovered:>substrate

When the operation is L-"List the accessible layers":


List of the accessible layers:
"0"
"substrate"
"BasePlan"

When the operation is R-"Recover the deleted layer" and the name is absent from the table or the record is permanently deleted:


Entry the layer name to be recovered:>underlayer
The layer "underlayer" - was deleted permanently

When the operation is X-"Create the predefined layers":


Zero layer: "0"
Defpoints layer: "Defpoints"
Constraints layer: "*ADSK_CONSTRAINTS"
SystemLights layer: "*ADSK_SYSTEM_LIGHTS"

When the operation is L-"List the accessible layers":


List of the accessible layers:
"0"
"substrate"
"BasePlan"
"Defpoints"
"*ADSK_CONSTRAINTS"
"*ADSK_SYSTEM_LIGHTS"

When the operation is N-"Rename the selected layer" and the name is predefined:


Entry the layer name to be renamed:>*ADSK_CONSTRAINTS
Entry the new layer name:>Constraints

Entry the layer name to be renamed:>*ADSK_SYSTEM_LIGHTS
Entry the new layer name:>Linghts

Repeating the operation L-"List the accessible layers" and E-"Expose the predefined layers":


List of the accessible layers:
"0"
"substrate"
"BasePlan"
"Defpoints"
"Constraints"
"Linghts"

Current active layer: "BasePlan"
Zero layer: "0"
Defpoints layer: "Defpoints"
Constraints layer is undefined
SystemLights layer is undefined

Repeating the operation X-"Create the predefined layers" and L-"List the accessible layers":


Zero layer: "0"
Defpoints layer: "Defpoints"
Constraints layer: "*ADSK_CONSTRAINTS"
SystemLights layer: "*ADSK_SYSTEM_LIGHTS"

List of the accessible layers:
"0"
"substrate"
"BasePlan"
"Defpoints"
"Constraints"
"Linghts"
"*ADSK_CONSTRAINTS"
"*ADSK_SYSTEM_LIGHTS"

Use the Q-"Quit" operation to exit:


Stop modifying of layers

See Also

Working with Layers

Organization of Layers

Example of Working with the Layer Record Object

Example of Using the Record–Table and Dictionary Interfaces for Entering Names

Copyright © 2002 – 2022. Open Design Alliance. All rights reserved.