Skip to end of metadata
Go to start of metadata

You are viewing an old version of this content. View the current version.

Compare with Current View Version History

« Previous Version 12 Next »

The DWG Expert addresses the possibilities to customize the core features especially in the ways to introduce more powerful tools to the UI part of the application.

 Features

  • List blocks from external sources 

  • Insert blocks from external sources

  • Create a custom UI for command prompts

  • Access entity properties

DWG Expert - List blocks from external sources JAVA C++

To accomplish a feature like a block library the DWG Expert introduces two separate classes. A class to describe the block Block.java (storing the block definition name and a corresponding thumbnail) and a class to manage all existing blocks BlockLibrary.java . The block library is created and initialized with all blocks from the assets using the method BuildBlockLibrary() when CFxARESDelegate triggers onInitializationDone(). The method onInitializationDone() is called  only once each application session. The block library uses getDrawingThumbnail() from singleton CFxARESInstance.instance() to create a block preview. 

File: BlockLibrary.java

void AddFile( String drawing )
{
   Bitmap preview = CFxARESInstance.instance().getDrawingThumbnail( drawing );
   Block blockDef = new Block();
   String blockName = "";
   String[] components = drawing.split( "/" );
   if ( components.length > 0 )
   {
       blockName = components[ components.length - 1 ];
       String[] nameComponents = blockName.split( "\\p{Punct}" );
       if ( nameComponents.length > 0 )
           blockName = nameComponents[ 0 ];
   }

   blockDef.m_Preview = preview;
   blockDef.m_Drawing = drawing;
   blockDef.m_BlockName = blockName;
   blockDef.m_Id = 0;
   m_Blocks.add( blockDef );
}

File: ARESDelegate.java

@Override
public void onInitializationDone()
{
...
   BuildBlockLibrary();
...
}

private void BuildBlockLibrary()
{
   m_BlockLibrary = new BlockLibrary();
   AssetManager assets = m_Host.getAssets();
   try
   {
       final String[] sampleDrawings = assets.list( "Blocks" );
       for ( String drawing : sampleDrawings )
       {
           String drawingPath = "assets:/Blocks/" + drawing;
           m_BlockLibrary.AddFile( drawingPath );
       }
   }

   catch (IOException e)
   {
       e.printStackTrace();
   }
}


DWG Expert - Insert blocks from external sources JAVA C++

The DWG Expert uses another class BlockLibraryView.java to construct a widget that can be used to show all available blocks. The widget is a common Java class, the RecyclerView. The block library view processes all data from the block library BlockLibrary.java the block name and the thumbnail. The final user action will happen on setOnClickListener() that is connected with a custom handler in  setOnDoInsertHandler(). When the handler is triggered the block insertion is initiated with a command sequence using runCommand().

BlockLibraryView.java

@Override
public void onBindViewHolder( ViewHolder viewHolder, final int position )
{
   final Block desc = localDataSet.get( position );
   viewHolder.m_Name.setText( desc.m_BlockName );
   viewHolder.m_Preview.setImageBitmap( desc.m_Preview );
   viewHolder.itemView.setOnClickListener(new View.OnClickListener()
   {
       @Override
       public void onClick(View v)
       {
           if ( m_Handler != null )
               m_Handler.doInsert( desc.m_Drawing, desc.m_BlockName );
       }
   });
}

MainActivity.java

public void DocumentCreated()
{
...
   BlockLibraryView.BlockAdapter adapter = new BlockLibraryView.BlockAdapter( m_ARES.GetBlockLibrary().m_Blocks );
   m_BlockPanel.setAdapter( adapter );
   adapter.setOnDoInsertHandler(new BlockLibraryView.BlockAdapter.OnDoInsert()
   {
       @Override
       public void doInsert(String drawingPath, String blockName)
       {
           String command = "_-INSERTBLOCK\n\"" + drawingPath + "\"\n\\1.0\n1.0\n0.0\n";
           CFxARESInstance.instance().runCommand( command );
       }
   });
}

DWG Expert - Create a custom UI for command prompts JAVA

Commands that are shipped by default also show up the default user input mask that may not suit well into the host applications surface. The CFxARESInstance allows to disable the predefined controls using the method switchStandardUserInput(). Once this is done it is necessary to create a custom input that cooperates with commands. Whenever a command requires an user action the custom input should request for corresponding values. This can be accomplished with the CFxUserInputDelegate.  The CFxUserInputDelegate informs the host application when an user interaction starts interactionStarted() or ends interactionEnded(). The DWG Expert controls a class UserInput.java that takes over the job of the delegate and the user interface. The class must be instantiated and registered as main CFxUserInputDelegate. Depending on the started interaction type the custom user input has to accept the command value or exit the command procedure. The DWG Expert relies on point input and demonstrates the use of acceptWithCoordinates() and cancel().

MainActivity.java

protected void onCreate(Bundle savedInstanceState)
{
...
   LinearLayout inputUI = findViewById( R.id.id_userinput );
   m_UserInput = new UserInput( inputUI );
}

public void OnApplicationStarted()
{
...
   CFxARESInstance.instance().userInput().delegate = m_UserInput;
}

CFxARESInstance.instance().switchStandardUserInput( false );

UserInput.java

public UserInput( LinearLayout view )
{
   ...
   m_Ok.setOnClickListener(new View.OnClickListener()
   {
       @Override
       public void onClick(View v)
       {
   ...
   CFxARESInstance.instance().userInput().acceptWithCoordinates( x, y, z );
       }
   });
   m_Cancel.setOnClickListener(new View.OnClickListener()
   {
       @Override
       public void onClick(View v)
       {
           CFxARESInstance.instance().userInput().cancel();
       }
   });
}

UserInput.java

@Override
public void interactionStarted(final String prompt, String[] keywords , int inputType ){...}

@Override
public void interactionEnded(){...}

DWG Expert - Access entity properties JAVA C++

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 mainSelectionSetChanged() calls a native method GetProperties() to retrieve more information about the entities selected. The DWG Expert uses a simple AlertDialog to display the necessary entity properties. The C++ implementation of GetProperties() is stored in Properties.cpp and compiled with the module JNI. Once libJNI.so is loaded , all methods are linked and available to be called.

Properties.java

public static native ArrayMap<String, String> GetProperties();

Properties.cpp

JNIEXPORT jobject JNICALL Java_com_graebert_userinput_Properties_GetProperties( JNIEnv * env, jclass clazz )
{
    CFxDocument* pDocument = ACTIVE_DOCUMENT();
    if ( pDocument == nullptr )
        return nullptr;

    CFxSelectionSet* pSelection = pDocument->GetFxMainSelectionSet();
    if ( pSelection->GetLength() != 1 )
        return nullptr;

    OdDbObjectId idSelected = pSelection->GetId( 0 );
    OdDbEntityPtr pSelectedEntity = idSelected.openObject();
    if ( pSelectedEntity.isNull() )
        return nullptr;

    auto properties = GetEntityProperties( pSelectedEntity );

    CFxObjectConstructor arrayCreator( "android/util/ArrayMap" );
    arrayCreator.Call();
    jobject arrayHandle = arrayCreator.GetResult();

    CFxObjectInvocation insertInvocation( "android/util/ArrayMap", "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;" );
    for ( auto& property : properties )
    {
        CFxJavaString key( property.first );
        CFxJavaString value( property.second );

        insertInvocation.Call( arrayHandle, key.GetJString(), value.GetJString() );
    }

    return GET_JAVA()->NewGlobalRef( arrayHandle );
}

ARESDelegate.java

@Override
public void mainSelectionSetChanged(boolean isEmpty, String commonObjectDxfClassName)
{
   final ArrayMap<String, String> res = Properties.GetProperties();
   if ( res != null && res.size() > 0 )
   {
       CFxARESInstance.instance().runOnUiThread(new Runnable()
       {
           @Override
           public void run()
           {
               m_Host.DisplayProperties( res );
           }
       });
   }
}

MainAcitivity.java

Properties.Adapter m_Adapter = null;

public void DisplayProperties( ArrayMap<String, String> properties )
{
   AlertDialog.Builder builder = new AlertDialog.Builder( this );
   builder.setTitle( "Entity properties" );
   RecyclerView grid = new RecyclerView( this );
   m_Adapter = new Properties.Adapter( properties );
   grid.setAdapter( m_Adapter );
   grid.setLayoutManager( new LinearLayoutManager( this ) );

   AlertDialog dialog = builder.create();
   dialog.setView( grid );
   dialog.setOnCancelListener(new DialogInterface.OnCancelListener()
   {
       @Override
       public void onCancel(DialogInterface dialog)
       {
           CFxARESInstance.instance().emulateEscKeyPressed();
       }
   });
   dialog.show();
}
  • No labels