TheSwamp

Code Red => ARX Programming => Topic started by: LE on March 16, 2006, 09:30:10 PM

Title: Add row in a Table - Question
Post by: LE on March 16, 2006, 09:30:10 PM
What method, should I need to use in order to have the new row added, in real time ?

When I run the below code, it does work but I need to select [grip], the table in order to have the Table updated.

Thanks!

Code: [Select]
static void LESQsomefunctions_ADDROW(void)
{
ads_name ename;
ads_point ptres;
if ( acedEntSel( "\nSelect TABLE:", ename, ptres ) == RTNORM ) {
AcDbTable *pTable = NULL;
AcDbObjectId entId;
acdbGetObjectId( entId, ename );
acdbTransactionManager->startTransaction();
if ( acdbTransactionManager->getObject(
( AcDbObject*& )pTable, entId, AcDb::kForRead) == Acad::eOk) {
if ( pTable->isKindOf( AcDbTable::desc() ) ) {
pTable->upgradeOpen();
if (( pTable->insertRows( pTable->numRows(),
pTable->rowHeight( 1 ) ) == Acad::eOk ) &&
( pTable->generateLayout() == Acad::eOk )) {
acutPrintf( "\nAdded one row and table updated." );
} else {
acutPrintf( "\nTable not updated." );
}
}// end of is AcDbTable
}// end of getObject
acdbTransactionManager->endTransaction();
}// end of acedEntSel
}//end of command ADDROWS
Title: Re: Add row in a Table - Question
Post by: Kerry on March 16, 2006, 09:35:41 PM
Do you need to Commit   the transaction in CPP ?
Title: Re: Add row in a Table - Question
Post by: LE on March 16, 2006, 09:46:29 PM
Do you need to Commit   the transaction in CPP ?

That is not available as function on ARX, I know what that function does in .NET, now what happens is that it is needed to wait for the transactionEnded() signal and after that, do the modifications... hmm...

It is contradictory, since when it is used the transaction manager, the good about it is to not care of closing objects.... unless [and it is possible] I am wrong...

I will change my code to use smart pointers... and see what happens.

Thanks.
Title: Re: Add row in a Table - Question
Post by: MickD on March 16, 2006, 09:51:15 PM
it seems .net commit wraps the ::endTransaction() method.

from the doc's
Quote
virtual Acad::ErrorStatus

endTransaction() = 0;

Ends the top transaction, committing all changes to objects obtained within that transaction. Also clears the undo marker associated with the transaction out of the undo file for all transaction-resident objects (this means resident in any transaction).


Luis, does it work with a regen in the editor??
Title: Re: Add row in a Table - Question
Post by: LE on March 16, 2006, 09:58:15 PM
it seems .net commit wraps the ::endTransaction() method.

from the doc's
Quote
virtual Acad::ErrorStatus

endTransaction() = 0;

Ends the top transaction, committing all changes to objects obtained within that transaction. Also clears the undo marker associated with the transaction out of the undo file for all transaction-resident objects (this means resident in any transaction).


Luis, does it work with a regen in the editor??

It is the same part of the help that I just read, my friend.... editor [drawing session?]... no it does not do it magically..... as Kerry mentioned...

Grrrrr......
Title: Re: Add row in a Table - Question
Post by: LE on March 16, 2006, 10:03:54 PM
Got it... here is the code that works, using smart pointers!

Code: [Select]
static void LESQsomefunctions_ADDROW(void)
{
ads_name ename;
ads_point ptres;
Acad::ErrorStatus es;
if ( acedEntSel( "\nSelect TABLE:", ename, ptres ) == RTNORM ) {
AcDbObjectId objId;
acdbGetObjectId( objId, ename );
AcDbObjectPointer<AcDbTable> pTable( objId, AcDb::kForWrite );
if ( ( es = pTable.openStatus() ) == Acad::eOk ) {
if (( pTable->insertRows( pTable->numRows(),
pTable->rowHeight( 1 ) ) == Acad::eOk) &&
( pTable->generateLayout() == Acad::eOk )) {
acutPrintf( "\nAdded one row and table updated." );
}
} else {
acutPrintf("\nIt is not a TABLE or it can not be opened: %s",
acadErrorStatusText( es ) );
}
}
}//end of command ADDROW
Title: Re: Add row in a Table - Question
Post by: MickD on March 16, 2006, 10:17:52 PM
hmm, loose memory, no good 'ay.


.... editor [drawing session?]


sort of, the editor as I referred to it is just that, the place where the user edits the currently active document and is an object in its own right (a Windows UI object).
The only time you should use the editor is for user interaction/input otherwise everything else can be done directly on the database object. That's why it's not good practice to use sendCommand etc. as you're playing with an interface to a different object (Windows) and could cause unnecessary overhead and troubles ;)
Title: Re: Add row in a Table - Question
Post by: LE on March 16, 2006, 10:25:20 PM
Thanks Mick;

On my previous code using the transaction manager, it is not possible, it has to be done following the normal way of opening an object, do the changes and later closing them, Or go the smart pointer route...

I can see the magic Kerry was referring....  :-)
Title: Re: Add row in a Table - Question
Post by: Alexander Rivilis on March 17, 2006, 04:45:59 AM
Thanks Mick;

On my previous code using the transaction manager, it is not possible, it has to be done following the normal way of opening an object, do the changes and later closing them, Or go the smart pointer route...

I can see the magic Kerry was referring....  :-)
You was not right. You Can use transaction manager. Look at this code and compare with yours code:
Code: [Select]
  static void TableAddRow(void)
  {
    ads_name ename;
    ads_point ptres;
    if ( acedEntSel( "\nSelect TABLE: ", ename, ptres ) == RTNORM ) {
      AcDbObject *pObj = NULL;
      AcDbObjectId entId;
      acdbGetObjectId( entId, ename );
      acdbTransactionManager->startTransaction();
      if (acdbTransactionManager->getObject(pObj, entId, AcDb::kForWrite) == Acad::eOk) {
        AcDbTable *pTable = AcDbTable::cast(pObj);
        if (pTable &&
            pTable->insertRows(pTable->numRows(),pTable->rowHeight(1)) == Acad::eOk &&
            pTable->generateLayout() == Acad::eOk) {
          acutPrintf( "\nAdded one row and table updated." );
        } else {
          acutPrintf( "\nTable not updated." );
        }
      }
      acdbTransactionManager->endTransaction();
    }
  }
In other words You can not use acdbTransactionManager->getObject(...,AcDb::kForRead) and after then use upgradeOpen(). upgradeOpen() is valid only with objects not in transaction.
Title: Re: Add row in a Table - Question
Post by: Kerry on March 17, 2006, 04:59:09 AM
Hello Alexander, thanks for posting.

Do you compile that as managed code only ?
Title: Re: Add row in a Table - Question
Post by: Alexander Rivilis on March 17, 2006, 05:04:12 AM
Hello Alexander, thanks for posting.

Do you compile that as managed code only ?


No! I've compiled that code as native and tested it in AutoCAD 2006 SP1.
Title: Re: Add row in a Table - Question
Post by: Kerry on March 17, 2006, 05:10:02 AM
Thanks, I'm not a CPP'er really, but I had a suspicion that transaction were used with native as well as managed.

I Hope you enjoy your time here :-)
Title: Re: Add row in a Table - Question
Post by: Alexander Rivilis on March 17, 2006, 05:17:53 AM
I'm CPP'er and Lisp'er.  And in 99.9% I'm using only native code in C++. For managed code I prefer C#. But in C# I'm beginner.
Title: Re: Add row in a Table - Question
Post by: Glenn R on March 17, 2006, 06:46:45 AM
Rivilis is quite correct Luis. You can use transactions in the code you posted. However, is it better than using smart pointer objects and checking all return codes...open for debate.
Smart pointers let you take some syntactical shortcuts in my opinion, however, transactions are Adesk's *preferred* method is transactions and have their own benefits.

The only thing I would change in Rivilis's code is to add the explicit use of abortTransaction() in the 'else' clause of the 'if' statement.

Now that I think about it, that 'if' statement is a bit unclear, so I would re-write myself. A general rule I adopted in C++ is to bail out immediately if a condition is not met...and my 'if' statements/switch etc. statement would reflect this.

Example:

if (!Whatever)
  return;

// Continue processing here.

instead of:

if (Whatever) {
  // Dome some lengthy and very much indented code here.
}

Just some bourbon ramblings.

Cheers,
Glenn.

P.S. I *miss* my C++.... < sigh >
Title: Re: Add row in a Table - Question
Post by: Alexander Rivilis on March 17, 2006, 06:53:34 AM
...
The only thing I would change in Rivilis's code is to add the explicit use of abortTransaction() in the 'else' clause of the 'if' statement.
...
I also agree with you! :)
Another style of code:
Code: [Select]
class Trans
{
public:
   Trans()  { tr = acTransactionManagerPtr()->startTransaction(); }
  ~Trans()  {
    if (tr == acTransactionManagerPtr()->topTransaction()) {
      acTransactionManagerPtr()->endTransaction();
    }
  }
  AcTransactionManager *operator->() {return acTransactionManagerPtr();};
private: 
  AcTransaction *tr;
};

class TransExpt {}; 

static void TableAddRow(void)
{
  ads_name ename;
  ads_point ptres;
  if ( acedEntSel( "\nSelect TABLE: ", ename, ptres ) == RTNORM ) {
    AcDbObject *pObj = NULL;
    AcDbObjectId entId;
    acdbGetObjectId( entId, ename );
    Trans tr;
    try {
      if (tr->getObject(pObj, entId, AcDb::kForWrite) != Acad::eOk)
        throw TransExpt();
      AcDbTable *pTable = AcDbTable::cast(pObj);
      if (!pTable)  throw TransExpt();
      if (pTable->insertRows(pTable->numRows(),pTable->rowHeight(1)) != Acad::eOk)
        throw TransExpt();
      if (pTable->generateLayout() != Acad::eOk)
        throw TransExpt();
      tr->flushGraphics();
      acutPrintf( "\nAdded one row and table updated." );
    }
    catch (TransExpt) {
      acutPrintf( "\nTable not updated." );
      tr->abortTransaction();
    }
  }
}
Title: Re: Add row in a Table - Question
Post by: LE on March 17, 2006, 09:54:18 AM
You was not right. You Can use transaction manager. Look at this code and compare with yours code:
Code: [Select]
  static void TableAddRow(void)
  }
In other words You can not use acdbTransactionManager->getObject(...,AcDb::kForRead) and after then use upgradeOpen(). upgradeOpen() is valid only with objects not in transaction.

Thank you Alex;

I mention that on a previous post

Quote
That is not available as function on ARX, I know what that function does in .NET, now what happens is that it is needed to wait for the transactionEnded() signal and after that, do the modifications... hmm...

It is contradictory, since when it is used the transaction manager, the good about it is to not care of closing objects.... unless [and it is possible] I am wrong... <<<<<<<<<<<<<<

I will change my code to use smart pointers... and see what happens.

Great, now I will understand this part :-)

Using the smart pointer's route, the code is more straight forward, compact and easy to understand..... [I will go back to what I read about transaction. too.... I see that it was just very minor changes you did]

Rock & Roll !!!
Title: Re: Add row in a Table - Question
Post by: LE on March 17, 2006, 10:21:46 AM
This one works too, by taking out the upgradeOpen() and using AcDb::kForWrite

I see you are using cast(), what is the benefit on that Alex ?

Thanks!

Code: [Select]
static void LESQsomefunctions_ADDROW(void)
{
ads_name ename;
ads_point ptres;
if ( acedEntSel( "\nSelect TABLE:", ename, ptres ) == RTNORM ) {
AcDbTable *pTable = NULL;
AcDbObjectId entId;
acdbGetObjectId( entId, ename );
acdbTransactionManager->startTransaction();
if ( acdbTransactionManager->getObject(
( AcDbObject*& )pTable, entId, AcDb::kForWrite) == Acad::eOk) {
if ( pTable->isKindOf( AcDbTable::desc() ) ) {
if (( pTable->insertRows( pTable->numRows(),
pTable->rowHeight( 1 ) ) == Acad::eOk ) &&
( pTable->generateLayout() == Acad::eOk )) {
acutPrintf( "\nAdded one row and table updated." );
} else {
acutPrintf( "\nTable not updated." );
}
}// end of is AcDbTable
}// end of getObject
acdbTransactionManager->endTransaction();
}// end of acedEntSel
}
Title: Re: Add row in a Table - Question
Post by: LE on March 17, 2006, 10:26:22 AM
Rivilis is quite correct Luis. You can use transactions in the code you posted. However, is it better than using smart pointer objects and checking all return codes...open for debate.
Smart pointers let you take some syntactical shortcuts in my opinion, however, transactions are Adesk's *preferred* method is transactions and have their own benefits.

Glenn;

Yes, I want to know not just one method or way... great comments.


Thanks!
Title: Re: Add row in a Table - Question
Post by: Alexander Rivilis on March 17, 2006, 11:20:02 AM
I see you are using cast(), what is the benefit on that Alex ?
I'd like using CLASS::cast() method. I think that this method more elegant than isKindOf(CLASS::desc() )   and can be useful for classes derived from CLASS.
And what about this code: http://www.theswamp.org/index.php?topic=9125.msg117509#msg117509 ?
For immediately updating graphic I used acTransactionManagerPtr()->flushGraphics()
Title: Re: Add row in a Table - Question
Post by: LE on March 17, 2006, 11:30:17 AM
I'd like using CLASS::cast() method. I think that this method more elegant than isKindOf(CLASS::desc() )   and can be useful for classes derived from CLASS.
And what about this code: http://www.theswamp.org/index.php?topic=9125.msg117509#msg117509 ?
For immediately updating graphic I used acTransactionManagerPtr()->flushGraphics()

Thank you Alex;

Great sample BTW.... !

I would be implementing your code style in my next training code....  :-)

[I'm still learning....]

Regards,
Luis.
Title: Re: Add row in a Table - Question
Post by: LE on March 17, 2006, 11:46:46 AM
Good;

I just tested your code Alex, and works nice, I will be using this as a template, for my future coding!... and it is great, Class is something I still need to digest...  :-)


Thanks.

Code: [Select]
class Trans
{
public:
 }
Title: Re: Add row in a Table - Question
Post by: Alexander Rivilis on March 17, 2006, 12:00:20 PM
I just tested your code Alex, and works nice, I will be using this as a template, for my future coding!... and it is great, Class is something I still need to digest...  :-)
:-) I am glad to help you!!!