ListView gizmo Questions



  • On 06/07/2013 at 17:27, xxxxxxxx wrote:

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

    ---------
    Hi,
    I'm loading the names of my currently selected objects into a ListView gizmo. Then clicking on the entries to select/unselect those objects.
    LMB selects them and RMB deselects them.
    It's working. But I've run into some rather strange behaviors.

    Q#1: Can we toggle the selection state (the highlighting) of LV entries on/off?
    Right now I don't see any way to deselect the entries. Other than selecting another one. Which is very poor. Because I have my LV gizmo set up to select/unselect objects in the scene.
    When I unselect the object by clicking the entry in the LV gizmo. I need the entry to not be selected(highlighted) anymore.
    I don't see anything in the SDK that allows us to unselect LV entries. So once we select one of the LV entries...It looks like we're foobared. And there's no way to make none selected(highlighted) as far as I can see.
    Am I missing something?

    Q#2: I'm not able to get many of the messgaes like: LV_GETLINEHEIGHT to work.
    They always return a zero value. Please see the example below.

    Q#3: The GetItem() function is giving me crazy garbage results.
    I'm assuming that this function is used to grab the data from a LV entry and save it into a container. Then we can use this to get the values for each entry.
    However...I'm getting crazy jibberish out of it. Please see the example below

      
      //Executes if the user selects an item in the ListView gizmo that's already been selected(highlighted)  
      case LV_SIMPLE_FOCUSITEM_NC:  
          {  
                      GePrint(LongToString(msg.GetLong(LV_GETLINEHEIGHT)));      //<------Always returns zero!!  
                      //These also don't work: LV_LMOUSEDOWN, LV_GETCOLUMNWIDTH  
      
      
          BaseContainer bc;  
          Bool entryName1 = myListView.GetItem(0,&bc);    //Grab the first LV item and save it into bc  
          Bool entryName2 = myListView.GetItem(1,&bc);    //Grab the second LV item and save it into bc  
          Bool entryName3 = myListView.GetItem(2,&bc);    //Grab the third LV item and save it into bc      
          GePrint(bc.GetString(entryName1));  //<--does not work!?  
          GePrint(bc.GetString(entryName2));  //<--does not work!?  
          GePrint(bc.GetString(entryName3));  //<--does not work!?  
      
          //Ok..So I'm not getting any returns from my base container using the ID#'s I provided it with  
          //So Lets loop though the container to see if there really is anything in it at all  
          LONG i=0;  
          while (bc.GetIndexId(i) != NOTOK)  
          {  
              Real id = bc.GetIndexId(i);  
              GePrint(RealToString(id));  //Prints 1851878757!? ..what is this crazy number?  
              GePrint(bc.GetString(id));  //<--This does print the string value..But only for the last entry(entryName3)!!!  
                                          //Why does this only return the last LV entry I added to the bc and none of the others?  
              i++;  
          }  
          }  
          break;
    

    -ScottA



  • On 06/07/2013 at 19:08, xxxxxxxx wrote:

    Why are you using the Bool return of GetItem() to retrieve the string in the container?  The return only tells you *if* the value was retrieved into the container.  Use the Column ID to reference the list entry items column by column.

    You should also be using separate containers for each item (or reusing the same one in a loop).



  • On 06/07/2013 at 21:34, xxxxxxxx wrote:

    That was just something I tried because nothing was working for me Robert.
    I did managed to figure out how to get the text data for each entry using the GetItemLine() function.

        //Executes if the user selects an item in the ListView gizmo that's already been selected(highlighted)  
      case LV_SIMPLE_FOCUSITEM_NC:  
      {  
      //GePrintF("Focus set id: %d, col: %d",msg.GetLong(LV_SIMPLE_ITEM_ID),msg.GetLong(LV_SIMPLE_COL_ID));      
      //GePrintF("CheckBox changed, id: %d, col: %d, val: %p",msg.GetLong(LV_SIMPLE_ITEM_ID),msg.GetLong(LV_SIMPLE_COL_ID),msg.GetVoid(LV_SIMPLE_DATA));                          
      //GePrint(LongToString(msg.GetLong(LV_GETLINECOUNT))); //works..Gets the Selected LV entry number  
      //GePrint(LongToString(listview1.GetItemCount()) );    //works..Gets the number of LV entries  
      //GePrint(LongToString(msg.GetLong(LV_GETLINEHEIGHT))); //These don't work: LV_LMOUSEDOWN,LV_GETCOLUMNWIDTH,LV_GETLINEHEIGHT  
      //GePrint(LongToString(msg.GetBool(LV_GETLINESELECTED)));//nope..not working  
      
      LONG count = listview1.GetItemCount();  
      BaseContainer bc;  
      for (LONG i=0;i<count;i++)  
      {  
          LONG id;  
          listview1.GetItemLine(i,&id,&bc);    //Get each entry's index and text data and store them in the id & bc variables  
          GePrint(LongToString(id));           //Prints the ID#s in the id variable  
          GePrint(bc.GetString(1851878757));   //Prints the text values in the bc container..Works but that weird ID# is very odd                      
          }  
      }  
      break;
    

    But the problem is it only works in the SDK listview example. And it doesn't work in my plugin.
    My plugin does not use a hard coded struct to set up the LV IDs and text values.
    My plugin uses a GeDynamicArray to hold the data. Which then gets copied into a BaseContainer. Then that container fills in the LV gizmo entries.
    There's something about the way I'm doing this that is making the GetItemLine() function not return each entry's text values. All I can get is the ID#s. And I don't know why this is happening.

    Plus. I'm still not able to figure out how to get all the various other options like LV_GETLINEHEIGHT, LV_GETLINESELECTED, etc. to work properly.
    I can't figure out how to get them working. Even in the SDK example.

    -ScottA



  • On 07/07/2013 at 04:57, xxxxxxxx wrote:

    Originally posted by xxxxxxxx

    <ADDRESS>
    User Information:
    Cinema 4D Version:   13 
    Platform:   Windows  ;   
    Language(s) :    
    C++  ;

    ---------
    </ADDRESS>
    Q#1: Can we toggle the selection state (the highlighting) of LV entries on/off?Right now I don't see any way to deselect the entries. Other than selecting another one. Which is very poor. Because I have my LV gizmo set up to select/unselect objects in the scene. When I unselect the object by clicking the entry in the LV gizmo. I need the entry to not be selected(highlighted) anymore.I don't see anything in the SDK that allows us to unselect LV entries. So once we select one of the LV entries...It looks like we're foobared. And there's no way to make none selected(highlighted) as far as I can see.Am I missing something?

    Ctrl-click on the selected item to de-select it.

    Steve



  • On 07/07/2013 at 07:55, xxxxxxxx wrote:

    Thanks Steve.
    But I meant is there a way to do that with code?

    What I'd like it to do is toggle the highlight state:
    -If I select an entry that's not selected. It highlights it.
    -If I select an entry that's highlighted. It un-highlights it.
    Or
    -If I LMB click on an entry. It highlights it.
    -If I RMB click on an entry. It un-highlights it.

    -ScottA



  • On 07/07/2013 at 10:02, xxxxxxxx wrote:

    I've finally managed to figure out how to write the code for those options that I couldn't get to work before.
    Here's an example of looping through the LV gizmo and getting things like selection state, line height, and the text values for each entry:

      
      //Executes if the user selects an item in the ListView gizmo that's already been selected(highlighted)  
      case LV_SIMPLE_FOCUSITEM_NC:  
      {  
      LONG count = listview1.GetItemCount();                  //Counts the number of entries in the LV gizmo  
      BaseContainer bc;                                       //Create a container to store the data we find in the LV gizmo below  
      for (LONG i=0;i<count;i++)  
      {  
          LONG id;                                            //Store each LV entry's ID# in this variable  
          listview1.GetItemLine(i,&id,&bc);                   //Get each entry's index and text data and store them in the id & bc variables  
          GePrint(LongToString(id));                          //Prints the ID#s in the id variable  
          LONG entryID = msg.GetLong(LV_GETLINECOUNT);        //Gets the ID# of each entry(does NOT! count them..per the docs!!!) and assigns it to a variable  
          LONG h = msg.GetLong(id,LV_GETLINEHEIGHT);          //Get the height value of each entry and assigns it to a variable  
          LONG s = msg.GetLong(LV_GETLINESELECTED,entryID);   //Gets the selected entry and assigns it to a variable  
          GePrint("ID#: " + LongToString(entryID));  
          GePrint("Height: " + LongToString(h));  
          GePrint("Selected Entry: " + LongToString(s));  
          GePrint(bc.GetString(1851878757));                  //Prints the text values in the bc container..Works but that weird ID# is very odd                  
          }  
      }  
      break;
    

    This info should really be added to the docs so people don't have to spend days trying to figure it all out like I just had to do.

    -ScottA



  • On 07/07/2013 at 20:22, xxxxxxxx wrote:

    I discovered something very important about the column's ID# in the ListView gizmo that I would like to share also.
    The column's ID is very important. Because it's a key part in extracting the text data values from the LV entries.

    Here's an example:

      
    COL = 1001  
      
    Bool ListViewDialog::InitValues(void)  
    {  
      //Set up the LV gizmo using a BaseContainer for it's options  
      
      BaseContainer layout;  
      layout = BaseContainer();  
      layout.SetLong(COL, LV_COLUMN_TEXT); //COL is the ID# for the column..We will use this ID later on  
      myListView.SetLayout(1,layout);  
      myListView.DataChanged();   
      
      return TRUE;  
    }  
      
      
    Bool ListViewDialog::Command(LONG id,const BaseContainer &msg)  
    {  
      BaseDocument *doc = GetActiveDocument();  
      switch (id)  
      {  
          case GADGET_LISTVIEW:  
          {  
          switch (msg.GetLong(BFM_ACTION_VALUE))  
              {  
                  //Executes once if the user selects an item in the ListView gizmo that's already been selected(highlighted)  
                  case LV_SIMPLE_FOCUSITEM_NC:  
                  {  
       
                      BaseContainer bc;       //Create a new BaseContainer that will hold the text values we get with GetItemLine()  
                      LONG id;                //Create a variable to hold the ID values for each LV entry we get with GetItemLine()  
      
                      //Gets the selected LV entry (it's ID#)  
                      LONG itemID = msg.GetLong(LV_GETLINECOUNT);  
      
                      //GetItemLine() gets the specific entry based on the ID#  you give it (itemID)  
                      //Then it stores the ID# in the id variable & the text value in bc variable  
                      myListView.GetItemLine(itemID, &id, &bc);  
      
      
                      //Here's where the column ID is very important. And comes into play  
                      //Normally you would retrieve the string values in bc like this: bc.GetString(Some ID#)  
                      //You might expect the ID to be something like 0,1,2,3, etc...  
                      //But you have to use the column's ID here to retrieve the string values for each LV entry  
        
                      String textValue = bc.GetString(COL); //<--- Notice how the column ID is used here to get the text in each LV entry  
                      GePrint(textValue);  
                  }  
                  break;  
      
              }  
          }  
          break;  
      
      return TRUE;  
    }
    

    This information should also be added the docs.

    -ScottA



  • On 08/07/2013 at 03:17, xxxxxxxx wrote:

    As I said.  There is an example in the cinema4dsdk samples that shows this explicitly. :)



  • On 08/07/2013 at 07:41, xxxxxxxx wrote:

    The last problem I have left to solve is deselecting the LV entries.
    I still can't find a solution for this.

    -ScottA



  • On 08/07/2013 at 09:46, xxxxxxxx wrote:

    Found it.
    Using BaseSelect we can use Deselect() on a specific LV entry. Or DeselectAll() to deselect all of the entries.

    Example:

        AutoAlloc<BaseSelect> selection;  
      
      //Executes when the user RMB clicks on an LV entry  
      case LV_SIMPLE_RMOUSE:  
      {  
          selection->DeselectAll();                //Deselect all the entries in memory only  
          myListView.SetSelection(selection);      //Apply the selection setting to the LV in memory only  
          myListView.DataChanged();                //Apply the selection changes to the LV from memory so none of them are highlighted  
          EventAdd();  
      }  
      break;
    

    It took me a while. But I found it. 🙂

    -ScottA


Log in to reply