This example demonstrates working with the layout dictionary object for adding, renaming, deleting, modifying, and printing layout objects. This example uses a console menu that represents the following operations: printing a list of the accessible layouts [L], printing specific properties of all layouts contained in the dictionary [P], printing a list of the associated blocks [B], exposing predefined layouts [E], creating a new layout and adding it in the dictionary [A], renaming an existing layout [N], setting a layout to be active [S], switching the current layout tab [T], displaying the system variable information [V], deleting an existing layout [D], and modifying the specific properties of a selected layout [M].
#include "..\Common\DemoMain.h"
#include "DbLayout.h"
#include "DbDictionary.h"
#include "DbBlockTable.h"
#include "DbBlockTableRecord.h"
#include <iostream>
using namespace std;
// Example of Working with the Layout Object
void PrintLayoutProperties(OdDbLayout* pLayout);
void ModifyLayoutProperties(OdDbLayout* pLayout);
// Example of Entering and Displaying 3D Point Objects
bool EntryPoint3d(OdGePoint3d& point);
OdString AboutPoint3d(const OdGePoint3d& point);
// Example of Entering and Displaying 2D Point Objects
bool EntryPoint2d(OdGePoint2d& point);
OdString AboutPoint2d(const OdGePoint2d& point);
// Example of Using the Record-Table and Dictionary Interfaces for Entering Names
OdString EntryRecordName(OdDbObject* pCollection, enum enumCheckName isExist = kDontCheck);
// Example of Using the Record–Table and Dictionary Interfaces for Getting Information about Objects
OdString AboutDbObject(OdDbObjectId idObject);
void PrintObjectProperties(OdDbObject* pObject);
The ModifyLayouts() function requires a pointer to the database object in which it manipulates the layouts. The function organizes a loop that inquires about the operation code and uses the switch statement to select whether the case must be performed. The function processes user actions in the loop until the user selects the [Q] operation. The function uses the PrintLayoutProperties() function for displaying the specific properties of a layout object, the ModifyLayoutProperties() function for modifying the properties of an existing layout object, and the EntryRecordName() function for entering the layout name and checking whether this name is correct and exists or is absent from the dictionary. The function obtains the smart pointer to the layout dictionary using the getLayoutDictionaryId() method of the passed database object. Before the loop, the function declares a smart pointer to the iterator and a smart pointer to the layout object.
When the user selects [L], the function displays a list of the layout names that are accessible in the dictionary. The function uses an iterator for traversing through the dictionary and the name() method of the iterator for displaying the name of each layout object to which the iterator refers.
When the user selects [P], the function prints the specific properties of all layout objects contained in the dictionary. The function uses an iterator for traversing through the dictionary and the getObject() method of the iterator for getting the smart pointer of the layout object to which the iterator refers. The function displays the common object properties using the PrintObjectProperties() function and the specific layout properties using the PrintLayoutProperties() function. To traverse through the dictionary, the function creates a new iterator for each traverse using the newIterator() method, organizes a loop if the traverse is not completed using the done() method, moves the iterator to the next layout object using the next() method, and gets the pointer to each layout instance using the getObject() method of the iterator and get() method of the smart pointer.
When the user selects [B], the function displays a list of the block names that are associated with layouts. The function obtains the smart pointer to the block table object in which blocks are stored using the getBlockTableId() method of the passed database object. The function uses an iterator for traversing through the block table, the getRecord() method of the iterator for getting a smart pointer of the block record object from the block table, the isLayout() method of the block record object for checking whether this block is associated with a layout, the getName() method of the block record object for displaying its name, and the getLayoutId() method of the block record object for getting the ID of the associated layout object. The function uses the AboutDbObject() function for displaying information about associated objects using its object IDs.
When the user selects [A], the function inquires about the layout name using the EntryRecordName() function. The name must be absent from the dictionary because the dictionary cannot contain duplicate names. The function passes the kMustAbsent value as an argument for checking the new name. If the entered name is correct and is absent, the function suggests two variants for creating a new layout:
When the user selects [N], the function inquires about the name of the existing layout object to be renamed and prompts for a new name using the EntryRecordName() function. The first name must exist in the dictionary; the function passes the kMustExist value as an argument for checking the entered name. The second name must be absent from the dictionary because it cannot contain duplicates; the function passes the kMustAbsent value as an argument for checking the new name. If both names are correct, the function suggests two variants for renaming:
When the user selects [T], the function requests the layout type and prompts: M-model or P-paper. The function calls the setTILEMODE() method of the database object and passes to it a True value if the user enters 'M' or a False value if the user enters 'P'. After setting, the function checks and displays the current layout type using the getTILEMODE() method of the database.
When the user selects [E], the function displays the current active layout object using the currentLayoutId() method and the block record object using the getActiveLayoutBTRId() method of the database object. These methods return the object IDs. The function gets smart pointers using the safeOpenObject() method and displays the names using the getName() and getLayoutName() methods.
When the user selects [S], the function inquires about the name of the existing layout object which should be active using the EntryRecordName() function and passes to it the kMustExist value as an argument for checking the name. If the entered name is correct, the function gets the ID of the layout object using the getAt() method, calls the setCurrentLayout() method of the database object, passing to it the ID as an argument, and goes to the [E] operation. The setCurrentLayout() method makes the specified layout active and switches the layout type for TILEMODE if it is necessary.
When the user selects [D], the function inquires about the name of the existing layout object to be deleted using the EntryRecordName() function. The name must exist in the dictionary; the function passes the kMustExist value as an argument for checking the entered name. If the entered name is correct and exists, the function suggests two variants for deleting:
When the user selects [M], the function inquires about the name of the existing layout object to be modified using the EntryRecordName() function. The name must exist in the dictionary; the function passes the kMustExist value as an argument for checking the entered name. If the entered name is correct and exists, the function gets a smart pointer to the layout object specified by the name using the getAt() method and opens it in write mode. Then, the function calls the ModifyLayoutProperties() function that organizes its own console menu for modifying the specific properties of the specified layout object.
When the user selects [V], the function displays the predefined layout settings using methods of the database object:
To get the current active layout, this operation uses the getSysVar() method, passing to it the "CTAB" name. The function uses the AboutDbObject() function for printing information about objects obtained as an object ID.
When the user selects [Q], the function ends the loop and returns to the calling function.
The ModifyLayouts() function has the following implementation:
void ModifyLayouts(OdDbDatabase* pDb)
{
wchar_t ch = L'L';
OdString sName, sNewName;
OdResult result;
OdDbDictionaryPtr pLayouts = pDb->getLayoutDictionaryId().safeOpenObject(OdDb::kForWrite);
OdDbDictionaryIteratorPtr itLayout;
OdDbLayoutPtr pLayout;
OdDbBlockTablePtr pBlocks = pDb->getBlockTableId().safeOpenObject(OdDb::kForWrite);
OdDbSymbolTableIteratorPtr itBlock = pBlocks->newIterator();
OdDbBlockTableRecordPtr pBlock;
wcout << L"\n\nStart testing of layouts";
wcout << L"\nLayout Class: " << OdDbLayout::desc()->name()
<< L", Container: " << pLayouts->handle().ascii()
<< L", " << pLayouts->isA()->name() << L"\n";
do {
switch(ch)
{
case L'A': // Add a new layout
case L'a':
wcout << L"\nEntry the name of a new layout:>";
if((sName = EntryRecordName(pLayouts, kMustAbsent)).isEmpty()) break;
try {
if(ch == L'a') // Creating through dictionary interface
{
pLayout = OdDbLayout::createObject();
pLayout->setLayoutName(sName);
pLayouts->setAt(sName, pLayout);
pBlock = OdDbBlockTableRecord::createObject();
pBlock->setName(sName);
pBlocks->add(pBlock);
pLayout->setTabOrder( pDb->countLayouts() );
pLayout->setBlockTableRecordId( pBlock->objectId() );
pBlock->setLayoutId( pLayout->objectId() );
}
else // Creating through database interface
pDb->createLayout(sName);
}
catch(OdError& e)
{
wcout << L"\nError: " << e.code() << L" - " << e.description() << L"\n";
pLayout->erase();
pBlock->erase();
break;
}
case L'L': // List the accessible layouts
case L'l':
wcout << L"\nList of layouts:\n";
for(itLayout = pLayouts->newIterator() ; !itLayout->done() ; itLayout->next())
wcout << L"\"" << itLayout->name() << L"\"\n";
break;
case L'P': // Print the specific properties of all layouts
case L'p':
wcout << L"\nList of layouts:";
for(itLayout = pLayouts->newIterator() ; !itLayout->done() ; itLayout->next())
{
pLayout = itLayout->getObject();
wcout << L"\nH=" << pLayout->handle().ascii();
PrintObjectProperties(pLayout);
wcout << L"\n ------ Specific Properties";
PrintLayoutProperties(pLayout.get());
}
wcout << L"\n";
break;
case L'B': // List the associated blocks
case L'b':
wcout << L"\nList of associated blocks:\n";
for(itBlock->start() ; !itBlock->done() ; itBlock->step())
{
pBlock = itBlock->getRecord();
if(pBlock->isLayout())
wcout << L"\"" << pBlock->getName() << L"\", "
<< AboutDbObject( pBlock->getLayoutId() ) << "\n";
}
break;
case L'N': // Rename the selected layout
case L'n':
wcout << L"\nEntry the name of the layout to be renamed:>" ;
if((sName = EntryRecordName(pLayouts, kMustExist)).isEmpty()) break;
pLayout = pLayouts->getAt(sName, OdDb::kForWrite);
wcout << L"\nEntry the new name of the layout:>";
if((sNewName = EntryRecordName(pLayouts, kMustAbsent)).isEmpty()) break;
try {
if(ch == L'n') // Renaming through dictionary interface
pLayout->setLayoutName(sNewName);
else // Renaming through database interface
pDb->renameLayout(sName, sNewName);
}
catch(OdError& e) { wcout << L"\nError: " << e.code() << L" - " << e.description() << L"\n"; }
break;
case L'D': // Delete the selected layout
case L'd':
wcout << L"\nEntry the name of the layout to be deleted:>" ;
if((sName = EntryRecordName(pLayouts, kMustExist)).isEmpty()) break;
if(ch == L'd') // Deleting through dictionary interface
{
pLayout = pLayouts->remove(sName).safeOpenObject(OdDb::kForWrite);
result = pLayout->erase(true);
if(result != eOk) wcout << L"\nError: " << result << L" - "
<< pDb->appServices()->getErrorDescription(result) << L"\n";
}
else // Deleting through database interface
{ try {
pDb->deleteLayout(sName);
}
catch(OdError& e) { wcout << L"\nError: " << e.code() << L" - " << e.description() << L"\n"; }
}
break;
case L'M': // Modify the selected layout
case L'm':
wcout << L"\nEntry the name of the layout to be modified:>" ;
if((sName = EntryRecordName(pLayouts, kMustExist)).isEmpty()) break;
pLayout = pLayouts->getAt(sName, OdDb::kForWrite);
ModifyLayoutProperties(pLayout.get());
break;
case L'T': // Switch the current tab
case L't':
wcout << L"\nSwitch the current tab [M-model|P-paper]:>";
wcin >> ch;
if(ch == L'M' || ch == L'm') pDb->setTILEMODE(true);
else if(ch == L'P' || ch == L'p') pDb->setTILEMODE(false);
wcout << L"Current tab is set to " << (pDb->getTILEMODE() ? L"Model" : L"Layout") << L"\n";
break;
case L'S': // Set the current active layout
case L's':
wcout << L"\nEntry the layout name to be set active:>";
if((sName = EntryRecordName(pLayouts, kMustExist)).isEmpty()) break;
pDb->setCurrentLayout(pLayouts->getAt(sName));
case L'E': // Expose the predefined layouts
case L'e':
pLayout = pDb->currentLayoutId().safeOpenObject();
pBlock = pDb->getActiveLayoutBTRId().safeOpenObject();
wcout << L"\nCurrent block record: \"" << pBlock->getName() << L"\"";
wcout << L"\nCurrent active layout: \"" << pLayout->getLayoutName() << L"\"";
break;
case L'V': // Print the system variable information
case L'v':
wcout << L"\nSystem variable information:"
<< L"\nCurrent tab type: " << (pDb->getTILEMODE() ? L"Model" : L"Layout")
<< L"\nCurrent tab object: " << AboutDbObject(pDb->getSysVar(L"CTAB")->getObjectId(pDb))
<< L"\nModel space object: " << AboutDbObject(pDb->getModelSpaceId())
<< L"\nPaper space object: " << AboutDbObject(pDb->getPaperSpaceId())
<< L"\nCurrent model minimum extents: " << AboutPoint3d(pDb->getEXTMIN())
<< L"\nCurrent model maximum extents: " << AboutPoint3d(pDb->getEXTMAX())
<< L"\nCurrent model lower-left limits: " << AboutPoint2d(pDb->getLIMMIN())
<< L"\nCurrent model upper-right limits: " << AboutPoint2d(pDb->getLIMMAX())
<< L"\nObjects outside model limits are " << ((pDb->getLIMCHECK()) ? L"disallowed" : L"allowed")
<< L"\nDefault elevation in model space: " << pDb->getELEVATION()
<< L"\nCurrent paper minimum extents: " << AboutPoint3d(pDb->getPEXTMIN())
<< L"\nCurrent paper maximum extents: " << AboutPoint3d(pDb->getPEXTMAX())
<< L"\nCurrent paper lower-left limits: " << AboutPoint2d(pDb->getPLIMMIN())
<< L"\nCurrent paper upper-right limits: " << AboutPoint2d(pDb->getPLIMMAX())
<< L"\nObjects outside paper limits are " << ((pDb->getPLIMCHECK()) ? L"disallowed" : L"allowed")
<< L"\nDefault elevation in paper space: " << pDb->getPELEVATION()
<< L"\n";
break;
case L'\0': // Skip an action
break;
default:
wcout << L"Incorrect operation\n";
}
wcout << L"\nA. Add a new layout"
<< L"\nT. Switch the current tab"
<< L"\nN. Rename the selected layout"
<< L"\nM. Modify the selected layout"
<< L"\nD. Delete the selected layout"
<< L"\nB. List the associated blocks"
<< L"\nL. List the accessible layouts"
<< L"\nE. Expose the predefined layouts"
<< L"\nS. Set the current active layout"
<< L"\nP. Print the properties of all layouts"
<< L"\nV. Print the system variable information"
<< L"\nQ. Quit";
wcout << L"\nSelect operation:>";
wcin >> ch;
}
while(ch != L'Q' && ch != L'q');
wcout << L"Stop testing of layouts\n";
}
Testing gives the following results:
Start testing of layouts
Layout Class: AcDbLayout, Container: 1A, AcDbDictionary
List of layouts:
"Model"
"Layout1"
"Layout2"
A. Add a new layout
T. Switch the current tab
N. Rename the selected layout
M. Modify the selected layout
D. Delete the selected layout
B. List the associated blocks
L. List the accessible layouts
E. Expose the predefined layouts
S. Set the current active layout
P. Print the properties of all layouts
V. Print the system variable information
Q. Quit
Select operation:>
When the operation is a-"Add a new layout" (first variant):
Entry the name of a new layout:>myLayout
List of layouts:
"Layout1"
"Model"
"Layout2"
"myLayout"
When the operation is A-"Add a new layout" (second variant):
Entry the name of a new layout:>Layout3
List of layouts:
"Model"
"Layout1"
"Layout2"
"Layout3"
"myLayout"
When the operation is B-"List the associated blocks":
List of associated blocks:
"*Model_Space", [22-"Model"-Layout]
"*Paper_Space", [1E-"Layout1"-Layout]
"*Paper_Space0", [26-"Layout2"-Layout]
"*Paper_Space2", [6E-"Layout3"-Layout]
"myLayout", [72-"myLayout"-Layout]
When the operation is E-"Expose the predefined layouts":
Current block record: "*Model_Space"
Current active layout: "Model"
When the operation is T-"Switch the current tab":
Switch the current tab [M-model|P-paper]:>P
Current tab is set to Layout
When the operation is E-"Expose the predefined layouts":
Current block record: "*Paper_Space"
Current active layout: "Layout1"
When the operation is S-"Set the current active layout":
Entry the layout name to be set active:>layout3
Current block record: "*Paper_Space"
Current active layout: "Layout3"
When the operation is B-"List the associated blocks":
List of associated blocks:
"*Model_Space", [22-"Model"-Layout]
"*Paper_Space", [6E-"Layout3"-Layout]
"*Paper_Space0", [26-"Layout2"-Layout]
"*Paper_Space2", [1E-"Layout1"-Layout]
"myLayout", [72-"myLayout"-Layout]
When the operation is a-"Add a new layout" and the name exists in the dictionary:
Entry the name of a new layout:>layout1
Error: the name "layout1" - already exists
When the operation is a-"Add a new layout" and the name is incorrect:
Entry the name of a new layout:>A:0?
Error: the name contains inadmissible letters: <>/\":;?,|=`
When the operation is n-"Rename the selected layout" (first variant):
Entry the name of the layout to be renamed:>myLayout
Entry the new name of the layout:>Sheet
When the operation is N-"Rename the selected layout" (second variant):
Entry the name of the layout to be renamed:>layout2
Entry the new name of the layout:>Section A-A
When the operation is N-"Rename the selected layout" and the name is absent:
Entry the name of the layout to be renamed:>AAA
Error: the name "AAA" - is not found
When the operation is N-"Rename the selected layout" and the name is predefined:
Entry the new name of the layout:>Screen
Error: 234 - Model Space Layout can't be renamed
When the operation is L-"List the accessible layouts":
List of layouts:
"Layout1"
"Model"
"Section A-A"
"layout3"
"Sheet"
When the operation is d-"Delete the selected layout" (first variant):
Entry the name of the layout to be deleted:>layout1
When the operation is D-"Delete the selected layout" (second variant):
Entry the name of the layout to be deleted:>Section A-A
When the operation is D-"Delete the selected layout" and the name is absent or the layout was already deleted:
Entry the name of the layout to be deleted:>Section A-A
Error: the name "Section A-A" - is not found
When the operation is D-"Delete the selected layout" and the name is predefined:
Entry the name of the layout to be deleted:>model
Error: 229 - Model Space Layout can't be deleted
When the operation is M-"Modify the selected layout":
Entry the name of the layout to be modified:>Sheet
Start modifying of the layout properties
Selected layout: "Sheet"
V. Active viewport
G. Append geometry
N. Set the tab order
I. Set the insertion base
M. Set the minimum extents
H. Set the maximum extents
L. Set the lower-left limits
U. Set the upper-right limits
E. Print the geometry extents
P. Print the whole properties
p. Print the specific properties
T. Switch the tab selected status
O. Switch the outside limits status
S. Switch the linetype scale status
A. Switch the annotative display status
B. Associate with the block record object
D. Disassociate with the block record object
Q. Quit
Select operation:>Q
Stop modifying of the layout properties
When the operation is P-"Print the specific properties of all layouts":
List of layouts:
H=22
Type: AcDbLayout
Status: unerased,resident,forRead
Database:
------ Specific Properties
Key = <Model>
Name = "Model"
Type = Model
Block = [1F-"*Model_Space"-Block]
Active Viewport = [29-"*Active"-Viewport]
Overall Viewport = [Db:kNull]
Tab Order = 0
Insertion base = (0,0,0)
Minimum extents = (1e+020,1e+020,1e+020)
Maximum extents = (-1e+020,-1e+020,-1e+020)
Lower-left limits = (0,0)
Upper-right limits = (12,9)
Tab selected status = Off
Outside limits status = Off
Linetype scale status = On
Annotative display status = Off
H=6F
Type: AcDbLayout
Status: unerased,resident,forRead
Database:
------ Specific Properties
Key = <layout3>
Name = "layout3"
Type = Paper
Block = [6E-"*Paper_Space"-Block]
Active Viewport = [74-Viewport]
Overall Viewport = [74-Viewport]
Tab Order = 2
Insertion base = (0,0,0)
Minimum extents = (0,0,0)
Maximum extents = (0,0,0)
Lower-left limits = (-0.25,-0.25)
Upper-right limits = (10.75,8.25)
Tab selected status = Off
Outside limits status = Off
Linetype scale status = On
Annotative display status = Off
H=72
Type: AcDbLayout
Status: unerased,resident,forRead
Database:
------ Specific Properties
Key = <Sheet>
Name = "Sheet"
Type = Paper
Block = [73-"myLayout"-Block]
Active Viewport = [Db:kNull]
Overall Viewport = [Db:kNull]
Tab Order = 4
Insertion base = (0,0,0)
Minimum extents = (0,0,0)
Maximum extents = (0,0,0)
Lower-left limits = (0,0)
Upper-right limits = (0,0)
Tab selected status = Off
Outside limits status = Off
Linetype scale status = On
Annotative display status = Off
When the operation is V-"Print the system variable information":
System variable information:
Current tab type: Layout
Current tab object: [6F-"layout3"-Layout]
Model space object: [1F-"*Model_Space"-Block]
Paper space object: [6E-"*Paper_Space"-Block]
Current model minimum extents: (1e+020,1e+020,1e+020)
Current model maximum extents: (-1e+020,-1e+020,-1e+020)
Current model lower-left limits: (0,0)
Current model upper-right limits: (12,9)
Objects outside model limits are allowed
Default elevation in model space: 0
Current paper minimum extents: (0,0,0)
Current paper maximum extents: (0,0,0)
Current paper lower-left limits: (-0.25,-0.25)
Current paper upper-right limits: (10.75,8.25)
Objects outside paper limits are allowed
Default elevation in paper space: 0
Use the Q-"Quit" operation to exit:
Stop testing of layouts
Example of Working with the Layout Object
Copyright © 2002 – 2021. Open Design Alliance. All rights reserved.
|