On 13/09/2013 at 13:33, xxxxxxxx wrote:
Hi Scott,
Originally posted by xxxxxxxx
What are these?:
COLUMN_SELECTED
value
You can have multiple columns in a TreeViewCustomGui, these columns are specified by passing
a BaseContainer to TreeViewCustomGui::SetLayout(). The column parameter represents the column
the TreeView polls you for data. COLUMN_SELECTED served as an example, being a symbol for a
column of the TreeView. You need it to distinguish between the columns in the tree-view. Imagine
you have two columns in your tree-view that have a checkbox!
Originally posted by xxxxxxxx
The problem is I don't really understand the the logic of how these function pairs work:
SetCheck-ISChecked
Select-IsSelcted
Open-IsOpened
etc...
The documentation is quite concise about this. The TreeViewCustomGui polls your TreeViewFunctions
object for information. It asks "is the element selected?", "is the element opened (unfolded)?",
"is the checkbox checked?", etc.
Furthermore, it tells you "an element got selected/deselected", "an element got folded/unfolded",
"a checkbox was checked/unchecked", etc.
Originally posted by xxxxxxxx
Using simple logic. You would logically think that we would use the Set,Select,Open functions to tell C4D to do something.
And you would logically think that the IsSet,IsSelected, IsOpen functions would act like receivers of those other functions. And react to them.
No, in this case you are the one implementing that functionality. You must see it from the
perspective of the TreeViewCustomGui. Eg. if you were writing the TreeView, and you receive a
mouse event and come to the conclusion that an element was selected by the user, you'd do
void* element = // some element returned by TreeViewFunctions::GetNext()/GetDown()/etc.
// ...
if (element_got_selected) {
my_tree_view_functions.Select(root, ud, element, SELECTION_ADD);
}
Originally posted by xxxxxxxx
Bool mytoggle;
virtual LONG IsChecked(void* root, void* userdata, void* obj, LONG lColumn) //Note: lColumn returns the LV_CHECKBOX ID
{
return TRUE;
}
virtual void SetCheck(void* root, void* userdata, void* obj, LONG lColumn, Bool bCheck, const BaseContainer &bcMsg)
{
//This method only returns a value if IsChecked() is set to LV_CHECKBOX_ENABLED
bCheck = IsChecked(root, userdata, obj, lColumn); //Gets the bit value returned from IsChecked()
mytoggle = !mytoogle
if(mytoggle == TRUE)
bCheck = LV_CHECKBOX_ENABLED //Make IsChecked() enable the checkbox
else
bCheck = 0 //Make IsChecked return 0 (not checked or enabled)
}
The logic for this thing makes absolutely no sense at all to me.
This is why things need to documented properly, and clearly.
It is not the documentation that is lacking of information here. You are missing an important point.
You have one variable for all the elements in your tree-view. The change to that variable will affect
all checkboxes. Simple as that.
You usually store the data in the object that you use to represent your tree structure, the obj
parameter. In the example from my previous post, I demonstrated implementing the IsChecked()
method assuming you are representing a structure of BaseObjects.
This is a quite complete example. The whole thing is straight forward to implement. I have
written it from scratch and did not try to compile it, but it should serve its purpose of
demonstration very well.
>
> class MyTreeViewFunctions : public TreeViewFunctions {
>
> public:
>
> virtual void* GetFirst(void* root, void* ud) {
> BaseDocument* doc = GetActiveDocument();
> if (doc) return doc->GetFirstObject();
> else return NULL;
> }
>
> virtual void* GetNext(void* root, void* ud, void* obj) {
> BaseObject* op = static_cast<BaseObject*>(obj);
> if (op) return op->GetNext();
> else return NULL;
> }
>
> virtual void* GetPred(void* root, void* ud, void* obj) {
> BaseObject* op = static_cast<BaseObject*>(obj);
> if (op) return op->GetPred();
> else return NULL;
> }
>
> virtual void* GetDown(void* root, void* ud, void* obj) {
> BaseObject* op = static_cast<BaseObject*>(obj);
> if (op) return op->GetDown();
> else return NULL;
> }
>
> virtual void* GetUp(void* root, void* ud, void* obj) {
> BaseObject* op = static_cast<BaseObject*>(obj);
> if (op) return op->GetUp();
> else return NULL;
> }
>
> virtual Bool IsSelected(void* root, void* ud, void* obj) {
> BaseObject* op = static_cast<BaseObject*>(obj);
> if (op) return op->GetBit(BIT_ACTIVE);
> else return FALSE;
> }
>
> virtual void Select(void* root, void* ud, void* obj, LONG mode) {
> BaseObject* op = static_cast<BaseObject*>(obj);
> BaseDocument* doc = GetActiveDocument();
>
> switch (mode) {
> case SELECTION_NEW:
> if (doc) doc->SetActiveObject(NULL);
> case SELECTION_ADD:
> if (op) op->SetBit(BIT_ACTIVE);
> break;
> case SELECTION_SUB:
> if (op) op->DelBit(BIT_ACTIVE);
> break;
> }
> }
>
> virtual Bool IsOpened(void* root, void* ud, void* obj) {
> BaseObject* op = static_cast<BaseObject*>(obj);
> if (op) return op->GetBit(BIT_OFOLD);
> else return FALSE;
> }
>
> virtual void Open(void* root, void* ud, void* obj, Bool mode) {
> BaseObject* op = static_cast<BaseObject*>(obj);
> if (op) {
> if (mode) op->SetBit(BIT_OFOLD);
> else op->DelBit(BIT_OFOLD);
> }
> }
>
> virtual String GetName(void* root, void* ud, void* obj) {
> BaseObject* op = static_cast<BaseObject*>(obj);
> if (op) return op->GetName();
> else return "???";
> }
>
> virtual Bool IsChecked(void* root, void* ud, void* obj, LONG column) {
> BaseObject* op = static_cast<BaseObject*>(obj);
>
> LONG state = 0;
> switch (column) {
> case COLUMN_HIDDEN:
> if (op) {
> state |= LV_CHECKBOX_ENABLED;
>
> // If the object is hidden in the Object Manager, the checkbox should
> // be checked.
> if (op->GetNBit(NBIT_OHIDE)) {
> state |= LV_CHECKBOX_CHECKED;
> }
> }
> break;
> }
>
> return state;
> }
>
> virtual void SetCheck(void* root, void* ud, void* obj, LONG column, Bool chcked, const BaseContainer& msg) {
> BaseObject* op = static_cast<BaseObject*>(obj);
>
> switch (column) {
> case COLUMN_SELECTED:
> if (op) {
> // Hide the object if the checkbox was checked, unhide if it was unchecked.
> NBITCONTROL control;
> if (checked) control = NBITCONTROL_SET;
> else control = NBITCONTROL_CLEAR;
> op->SetNBit(NBIT_OHIDE, control);
> }
> }
> }
>
> }
>
> class MyDialog : public GeDialog {
>
> TreeViewCustomGui* m_tree;
> MyTreeViewFunctions m_functions;
>
> public:
>
> virtual Bool CreateLayout() {
> // Create a TreeViewCustomGui here
> }
>
> virtual Bool InitValues() {
> if (m_tree) {
> BaseContainer layout;
> layout.SetLong(COLUMN_NAME, LV_TREE);
> layout.SetLong(COLUMN_HIDDEN, LV_CHECKBOX);
> m_tree->SetLayout(2, layout);
> m_tree->SetHeaderText(COLUMN_NAME, "Name");
> m_tree->SetHeaderText(COLUMN_HIDDEN, "Hidden");
> m_tree->SetRoot(NULL, &m_functions, NULL);
> m_tree->Refresh();
> }
>
> return TRUE;
> }
>
> };
Originally posted by xxxxxxxx
Why is this so difficult to do?
All I want to do is be able select a checkbox on each individual tree item. And when I do that, it makes the object in the same cell active.
Why is this such a huge massive thing to accomplish?
See above, you can't store ONE value for MANY objects and expect it to work like that. (Maybe
looking at some data-relationship models might help you too).
Best regards,
-Niklas