Developer forum
cancel
Showing results for 
Search instead for 
Did you mean: 

How to group items in list view

ggiloyan
Newcomer
Hello,

I would like to know how i can achieve grouping of list items in my list view. I attached an image to show what I want to achieve.

I need to use the code in c++. I know how to make a normal list view:
 // -----------------------------------------------------------------------------
// Set/adjust the dialog items
// -----------------------------------------------------------------------------

static void ListDataDlg_Set (short 	dialId, DGUserData userData)
{
	API_ListData	listdata;
	char			keyStr[NAME_LEN2];
	char			codeStr[NAME_LEN2];
	Int32			count;
	Int32			i;
	bool			filter;

	if (userData == 0L) {
		return;
	}

	 

	listdata = *((API_ListData *) (userData));

	listdata.header.setIndex = (short) DGPopUpGetItemUserData (dialId, DBSetPopupItem,
				(short) DGGetItemValLong (dialId, DBSetPopupItem));

	GS::UniString temp = DGGetItemText (dialId, KeyEditTextItem);
	CHTruncate (UniStringToConstCString (temp), keyStr, NAME_LEN2);
	temp = DGGetItemText (dialId, CodeEditTextItem);
	CHTruncate (UniStringToConstCString (temp), codeStr, NAME_LEN2);

	switch (DGGetItemValLong (dialId, TypeIDPopupItem)) {

		case 1:		listdata.header.typeID = API_ComponentID;
					CHCopyC (keyStr, listdata.component.keycode);
					CHCopyC (codeStr, listdata.component.code);
					DGEnableItem (dialId, KeyEditTextItem);
					break;

		case 2:		listdata.header.typeID = API_DescriptorID;
					CHCopyC (keyStr, listdata.descriptor.keycode);
					CHCopyC (codeStr, listdata.descriptor.code);
					DGEnableItem (dialId, KeyEditTextItem);
					break;

		case 3:		listdata.header.typeID = API_KeyID;
					CHCopyC (codeStr, listdata.key.code);
					DGDisableItem (dialId, KeyEditTextItem);
					break;

		case 4:		listdata.header.typeID = API_UnitID;
					CHCopyC (codeStr, listdata.unit.code);
					DGDisableItem (dialId, KeyEditTextItem);
					break;
	}

	DGListDeleteItem (dialId, SearchListItem, DG_ALL_ITEMS);

	filter = (DGGetCheckedRadio (dialId, 1) == FilterRadioItem);
	Search_ListData (&listdata, &count, filter);

	if (count < 1 || listHdl == NULL)
		return;

	for (i = 1; i <= count; i++)
		DGListInsertItem (dialId, SearchListItem, DG_LIST_BOTTOM);

	SetDGList (dialId, count);
	DGListSelectItem (dialId, SearchListItem, 1);

	return;
}		// ListDataDlg_Set

static void		Search_ListData (API_ListData *param, Int32 *count, bool filter)
{
	API_ListData	listdata;
	Int32			i;
	Int32			beginIndex, endIndex;
	GSErrCode		err;

	listdata	= *param;
	*count		= 0;
	err			= NoError;

	/* ACAPI_ListData_Search fails if keyCode is an empty string */

	/* ------- Search it ------- */
	if (filter && (param->header.typeID == API_UnitID || param->header.typeID == API_KeyID ||
		(param->header.typeID == API_ComponentID && strlen (param->component.code) != 0) ||
		(param->header.typeID == API_DescriptorID && strlen (param->descriptor.code) != 0))) {

		err = ACAPI_ListData_Search (&listdata);

		if (err == NoError)
			err = ACAPI_ListData_Get (&listdata);

		if (err == NoError) {
			err = AppendList (&listdata, count);
			if (listdata.header.typeID == API_DescriptorID)
				BMKillHandle (&listdata.descriptor.name);
		}
	} else {

	/* ------ Search list ------ */
		if (filter) {
			err = ACAPI_ListData_Search (&listdata);
			if (err != NoError)
				return;

			beginIndex = listdata.header.index;
		} else
			beginIndex = 1;

		err = ACAPI_ListData_GetNum (param->header.setIndex, param->header.typeID, &endIndex);
		if (err != NoError)
			return;

		BNZeroMemory (&listdata, sizeof (API_ListData));
		listdata.header.typeID	 = param->header.typeID;
		listdata.header.setIndex = param->header.setIndex;

		for (i = beginIndex; i <= endIndex; i++) {

			listdata.header.index		= i;
			err = ACAPI_ListData_Get (&listdata);
			if (err != NoError)
				break;

			if (filter) {
				if (listdata.header.typeID == API_ComponentID &&
					!CHEqualCStrings (listdata.component.keycode, param->component.keycode))
					break;

				if	(listdata.header.typeID == API_DescriptorID &&
					!CHEqualCStrings (listdata.descriptor.keycode, param->descriptor.keycode)) {

					BMKillHandle (&listdata.descriptor.name);
					break;
				}
			}

			if (err == NoError) {
				err = AppendList (&listdata, count);
				if (listdata.header.typeID == API_DescriptorID)
					BMKillHandle (&listdata.descriptor.name);
			}

			if (err != NoError)
				return;
		}
	}

	return;
}		// Search_ListData

But how can I group those items under a header like in the example.

Thanks
4 REPLIES 4

Erenford
Newcomer
The one in the picture is from GDL though, not the API Dialog Manager. In GDL its merely setting an object's parameter as title type and setting the parameters below it as its children.

The closest imitation I could think of is using a ListBox and setting up a column for the "arrow down/right" toggle icon which when click, will populate that listitem's children. And then when clicked again will delete all those children.
Archicad 25 3002 INT FULL
Archicad 24 6004 INT FULL
Visual Studio Professional 2019
Win 10 Pro 64-bit (10.0 build 19043)
Intel Core i7-4790 CPU @3.60GHz

ggiloyan
Newcomer
Thank you for your answer...

I understand that the upper one is from GDL. I also know how to make these when creating my custom GDL objects. But the lower one (with the IFC properties etc.) seems to be some UI class/element.

So as an example, in the DevKit in C++ I can make a list view with: DG::SingleSelListView

Like this I would also expect some class to make this kind of list, or is such class not available in the DevKit?

Hope you can clear this up.
Thanks!

ReignBough
Booster
You can create a class/structure that uses flags the same as the modifier flags of API_AddParType (or you can set your own modifier flags). Then modify it whenever you "toggle" an item in the list. Then re-populate the list. Something like (populate list with parameter of a LibPart):
bool isOpen = false;
//... clear list before loop
for (... i = 0; i < cnt; i++)
{
    if (flags & API_ParFlag_Hidden)
        continue;

    // check if parent or child
    if (flags & API_ParFlag_Child)
    {
        // skip if parent is "close"
        if (!isOpen)
            continue;
    }
    // set isOpen if item is not child
    else
    {
        isOpen = (flags & API_ParFlag_Open) > 0;
    }

    //... populate list here checking if it is disabled, bold, separator, etc.
}
~ReignBough~
ARCHICAD 24 INT 4018 FULL (from AC18)
Windows 10 Pro, Intel Core i7-4790 CPU @ 3.60GHz, 32.0GB RAM, 64-bit OS

ggiloyan
Newcomer
I already did listview grouping by this way. Thanks

Still looking?

Browse more topics

Back to forum

See latest solutions

Accepted solutions

Start a new discussion!