Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Code Block
-(void)onInitializationDone
{
    ...    
    [_application BuildBlockLibrary];
}

File: AppDelegate.mmm

Code Block
@interface AppDelegate ()
{
    ...
    NSMutableArray* m_BlockLibrary;
}

-(void)BuildBlockLibrary
{
    // Prepare block library.
    NSString *bundlePath = [[aresDelegate resourceBundle] bundlePath];
    NSString *dwgSamplesPath = [bundlePath stringByAppendingString:@"/Support/Samples/Blocks"];
    NSArray *filePaths = [NSBundle pathsForResourcesOfType:@"dwg" inDirectory:dwgSamplesPath];

    m_BlockLibrary = [NSMutableArray array];
    for ( NSString* drawing in filePaths )
    {
        BlockDefinition* block = [[BlockDefinition alloc] init];
        
        block._blockFilePath = drawing;
        block._blockName = [drawing lastPathComponent];
        block._icon = [[CFxARESInstance instance] getDrawingThumbnail:drawing];
        
        [m_BlockLibrary addObject:block];
    }
}

DWG Expert - Insert blocks from external sources

Status
titleOBJ-C
Status
colourYellow
titleC++

The DWG Expert uses another class BlocksDelegate.m to construct a widget that can be used to show all available blocks. The widget is a common OBJ-C class, the NSObject<UITableViewDataSource, UITableViewDelegate>. The block library view processes all data from the block library the block name and the thumbnail. The block delegate is created and initialized in the ViewController.m, the table view is part of the ViewController and shows up accordingly. The final user action will happen on -(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath whenever a table cell is tapped. When the table cell is triggered the block insertion is initiated with a command sequenceusing -(void)runCommand:(NSString*)command.

File: ViewController.m

Code Block
- (void)viewDidLoad
{
    ...
    blockDelegate = [[BlocksDelegate alloc] init];

    UINib* blockItem = [UINib nibWithNibName:@"blockview" bundle:nil];
    [m_Blocks registerNib:blockItem forCellReuseIdentifier:@"block"];
    
    m_Blocks.dataSource = blockDelegate;
    m_Blocks.delegate = blockDelegate;

    AppDelegate* appDelegate = (AppDelegate*)[UIApplication sharedApplication].delegate;
    [blockDelegate SetBlocks:[appDelegate GetBlockDefinitions]];
    [m_Blocks reloadData];
    ...
}

File: BlocksDelegate.m

Code Block
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    BlockDefinition* blockDef = [m_Blocks objectAtIndex:indexPath.row];
    
    NSString* command = @"_-INSERTBLOCK\n\"";
    command = [command stringByAppendingString:blockDef._blockFilePath];
    command = [command stringByAppendingString:@"\"\n\\1.0\n1.0\n0.0\n"];
    
    [[CFxARESInstance instance] runCommand:command];
    
    [tableView deselectRowAtIndexPath:indexPath animated:NO];
}

DWG Expert - Create a custom UI for command prompts

Status
titleOBJ-C

Coming soon.

DWG Expert - Access entity properties

Status
titleOBJ-C
Status
colourYellow
titleC++

It may be necessary to run certain actions whenever an entity is selected. The CFxARESInstanceDelegate provides a method that informs the host application a selection has changed. The method -(void)mainSelectionSetChanged:(BOOL)isEmpty commonObjectClass:(NSString*)dxfClassName; calls a native method -(NSArray*)GetProperties from CFxNativeConnection to retrieve more information about the entities selected. The DWG Expert uses a simple UIAlertController to display the necessary entity properties. The Obj-C implementation of -(void)DisplayProperties:(NSArray*)properties is part of ViewController.m. DisplayProperties must be executed from the UI thread. A suitable method +(void)runOnUiThread:(dispatch_block_t)block is provided by [CFxARESInstance].

Image Added

File: ViewController.m

Code Block
-(void)DisplayProperties:(NSArray*)properties
{
    NSString *htmlString = @"<html><head><style> \
    table { \
      font-size: 1.3em; \
      width: 100%; \
    } \
    </style> \
    </head><body><table>";
    for (NSString* prop in properties) {
        NSString* key = [[prop componentsSeparatedByString:@","] objectAtIndex:0];
        NSString* value = [[prop componentsSeparatedByString:@","] objectAtIndex:1];
        NSString* row = [NSString stringWithFormat:@"<tr><td>%@</td><td>%@</td></tr>", key, value];
        htmlString = [htmlString stringByAppendingString:row];
    }
    htmlString = [htmlString stringByAppendingString:@"</table></body></html>"];
    UIAlertController *alert = [UIAlertController alertControllerWithTitle:nil
                                                                     message:nil
                                                              preferredStyle:UIAlertControllerStyleAlert];
    NSAttributedString *attributedStr = [[NSAttributedString alloc] initWithData:[htmlString dataUsingEncoding:NSUTF8StringEncoding]
               options:@{NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType,
                         NSCharacterEncodingDocumentAttribute: @(NSUTF8StringEncoding)}
    documentAttributes:nil error:nil];
    NSAttributedString *attributedTitle = [[NSAttributedString alloc] initWithString:@"Entity properties" attributes:@{NSFontAttributeName : [UIFont boldSystemFontOfSize:17], NSForegroundColorAttributeName :[UIColor blackColor]}];
    UIAlertAction *defaultAction = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) {
        // OK button tappped.
        [self dismissViewControllerAnimated:YES completion:^{ }];
        [[CFxARESInstance instance] emulateEscKeyPressed];
    }];
    [alert setValue:attributedStr forKey: @"attributedMessage"];
    [alert setValue:attributedTitle forKey:@"attributedTitle"];
    [alert addAction:defaultAction];
    
    UIView *firstSubview = alert.view.subviews.firstObject;
    UIView *alertContentView = firstSubview.subviews.firstObject;
    UIView *firstView = alertContentView.subviews.firstObject;
    firstView.backgroundColor = [UIColor whiteColor];
    
    [self presentViewController:alert animated:true completion:nil];
}


File: CFxAresDelegate.m

Code Block
-(void)mainSelectionSetChanged:(BOOL)isEmpty commonObjectClass:(NSString*)dxfClassName
{
    // User selected enitities, lets show/hide UI for working with selection.
    NSArray* properties = [[CFxNativeConnection GetNativeConnection] GetProperties];
    if (properties != nil && properties.count > 0)
    {
        [CFxARESInstance runOnUiThread:^
        {
            [[self getMainView] DisplayProperties:properties];
        }];
    }
}

File: CFxNativeConnection.mm

Code Block
std::vector< std::pair<OdString, OdString>> GetEntityProperties( OdDbEntityPtr pEntity )
{
    std::vector< std::pair<OdString, OdString>> properties;

    OdCmColor cmColor = pEntity->color();
    properties.push_back( std::make_pair( L"Color", cmColor.colorNameForDisplay() ));

    OdDbObjectId idLayer = pEntity->layerId();
    OdDbLayerTableRecordPtr pLayer = idLayer.openObject();
    properties.push_back( std::make_pair( L"Layer", pLayer->getName() ));

    OdDbObjectId idLinetype = pEntity->linetypeId();
    OdDbLinetypeTableRecordPtr pLinetype = idLinetype.openObject();
    properties.push_back( std::make_pair( L"Linetype", pLinetype->getName() ));

    double linetypeScale = pEntity->linetypeScale();
    CFxDatabasePtr pDB = pEntity->database();
    CFxString sLinetypeScale;
    if ( pDB->GetUnitsFormatter()->RealToString( sLinetypeScale, linetypeScale ) == RTNORM )
        properties.push_back( std::make_pair( L"LinetypeScale", sLinetypeScale.wide_strU() ));

    OdString sLineWeight;
    OdDb::LineWeight entityLineweight = pEntity->lineWeight();
    if( entityLineweight == OdDb::kLnWtByLayer )
        sLineWeight = L"ByLayer";
    else if( entityLineweight == OdDb::kLnWtByBlock )
        sLineWeight = "ByBlock";
    else if( entityLineweight == OdDb::kLnWtByLwDefault )
        sLineWeight = L"Default";
    else
    {
        int value = static_cast<int>( entityLineweight );
        double newValue;
        newValue = value / 100.0;

        sLineWeight.format( L"%2f mm", newValue );
    }
    properties.push_back( std::make_pair( L"Lineweight", sLineWeight ) );

    // Read Block Properties
    if( pEntity->isKindOf( OdDbBlockReference::desc() ) )
    {
        OdDbBlockReferencePtr pBlock = OdDbBlockReference::cast( pEntity );
        OdGePoint3d pt = pBlock->position();
        double dAngle = pBlock->rotation();
        OdGeScale3d scale = pBlock->scaleFactors();

        OdDbBlockTableRecordPtr pRecord = pBlock->blockTableRecord().openObject( OdDb::kForRead );
        OdString strBlockName;
        if( !pRecord.isNull() )
            strBlockName = pRecord->getName();

        properties.push_back( std::make_pair( L"Position X" , OdString().format(L"%f",pt.x ) ) );
        properties.push_back( std::make_pair( L"Position Y" , OdString().format(L"%f",pt.y ) ) );
        properties.push_back( std::make_pair( L"Position Z" , OdString().format(L"%f",pt.z ) ) );

        properties.push_back( std::make_pair( L"Scale X" , OdString().format(L"%f",scale.sx ) ) );
        properties.push_back( std::make_pair( L"Scale Y" , OdString().format(L"%f",scale.sy ) ) );
        properties.push_back( std::make_pair( L"Scale Z" , OdString().format(L"%f",scale.sz ) ) );

        properties.push_back( std::make_pair( L"Rotation" , OdString().format(L"%f", dAngle ) ) );
        properties.push_back( std::make_pair( L"Name" , strBlockName ) );
    }

    return properties;
}