EditNumbers correction/limiting

THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

On 02/03/2007 at 23:20, xxxxxxxx wrote:

User Information:
Cinema 4D Version:    
Platform:   Windows  ; Mac  ;  Mac OSX  ; 
Language(s) :     C++  ;

---------
If, like me, you are fed up with or struggling with dialog numerical entry boxes never updating properly or holding to the limit set with SetReal() et al, here is a method that seems to work:

// GeDialog.Message  
//*---------------------------------------------------------------------------*  
LONG MyDialog::Message(const BaseContainer& msg, BaseContainer& result)  
//*---------------------------------------------------------------------------*  
{  
     // Looking for Action messages with Value Change or Value subs  
     if ((msg.GetId() == BFM_ACTION) && (msg.GetLong(BFM_ACTION_VALCHG) || msg.GetLong(BFM_ACTION_VALUE)))  
     {  
          // Get the 'gadget' ID for which this message has been sent  
          LONG     action = msg.GetLong(BFM_ACTION_ID);  
          // objScaling  
          if (action == IP_SET_IMPORTSCALE)  
          {  
               // The Parser* parser must either be allocated somewhere with  
               //       parser = Parser::Alloc();  
               //      if (!parser) raise an error notification  
               // OR  
               // you can allocate it temporarily here using  
               //      AutoAlloc<Parser> parser;  
               //      if (!parser) raise an error notification  
               // Use the parser to do numerical evaluations and determine invalid input  
               String     expression;  
               Real     rval;  
               LONG     lval;  
               GetString(IP_SET_IMPORTSCALE, expression);  
               if (parser->Eval(expression, &lval;, &rval;, UNIT_NONE, ANGLE_DEG, 10))  
               {  
                    // This is the valid range - if not valid, use the current value  
                    if ((rval < 1.0f) || (rval > 10000.0f))     rval = settings->GetObjScaling();  
                    // Store the new value if valid  
                    else                                             settings->SetObjScaling(rval);  
               }  
               // The parser failed, use the current value  
               else                                                  rval = settings->GetObjScaling();  
               // Set the value (whether current of new)  
               SetReal(IP_SET_IMPORTSCALE, rval, 1.0f, 10000.0f, 1.0f, FORMAT_REAL);  
          }  
     }  
     return GeDialog::Message(msg, result);  
}

For LONG values, just use FtoL() to convert after parsing and use a LONG value for retrieval of the current value.

I really wish that the GUI handling here was less laborious and more internalized so that such measures were unnecessary. This works very well to maintain the value, but only if using the arrows or if, after typing a new value, the tab or enter key is hit. To be even more pedantic, one must use even more Draconian checks (at the keystroke entry level). Programmers should be doing:

MakeNumberButton(ID, initvalue, minrange, maxrange, step);

and all considerations beyond should either be internally automatic or have simple test-correction callback methodologies. Computers have been around for like sixty years - and yet I still have to outline every minute detail of logic for even the most rudimentary tasks. Computers are as dumb as the original Babbage engine, just more bells & whistles... 😉

THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

On 04/03/2007 at 22:26, xxxxxxxx wrote:

An update. Well, that has a flaw in it (msg.GetLong(BFM_ACTION_VALUE)). If 0 or 0.0 is valid, this will fail to update on that value.

What I've found is that if you do the same thing for each action in GeDialog::Command(), this works. So do this instead:

// GeDialog.Command  
//*---------------------------------------------------------------------------*  
Bool IPPDialog::Command(LONG id, const BaseContainer& msg)  
//*---------------------------------------------------------------------------*  
{  
     switch (id)  
     {  
          ...  
          case IP_SET_IMPORTSCALE:  
          {  
               String     expression;  
               Real     rval;  
               LONG     lval;  
               GetString(IP_SET_IMPORTSCALE, expression);  
               if (parser->Eval(expression, &lval;, &rval;, UNIT_NONE, ANGLE_DEG, 10))  
               {  
                    if ((rval < 1.0f) || (rval > 10000.0f))     rval = settings->GetObjScaling();  
                    else                                             settings->SetObjScaling(rval);  
               }  
               else                                                  rval = settings->GetObjScaling();  
               SetReal(IP_SET_IMPORTSCALE, rval, 1.0f, 10000.0f, 1.0f, FORMAT_REAL);  
          }  
          ...  
     }  
     return TRUE;  
}  

And that seems to work both with the arrows and typed in entries (with a Tab or Enter as previously noted).

THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

On 05/03/2007 at 03:49, xxxxxxxx wrote:

Hey Rob,

thank you very much for sharing! It´s a pity to see that one needs to spend time on such issues. 😕