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

List box header

dushyant
Booster

Hi,

I found that the list box header is also set using the list-box-header-strings-resource-ID, as below:

 

 

 

 

	// set texts:
	GS::UniString	headerName;
	RSGetIndString (&headerName, LAYER_DIALOG_LIST_BOX_HEADER_STRINGS_RESID, 1, ACAPI_GetOwnResModule());
	layerList.SetHeaderItemText (layerNameTab,		headerName);

	RSGetIndString (&headerName, LAYER_DIALOG_LIST_BOX_HEADER_STRINGS_RESID, 2, ACAPI_GetOwnResModule());
	layerList.SetHeaderItemText (statusTab,			headerName);

	RSGetIndString (&headerName, LAYER_DIALOG_LIST_BOX_HEADER_STRINGS_RESID, 3, ACAPI_GetOwnResModule());
	layerList.SetHeaderItemText (filterStatusTab,	headerName);

 

 

 

 

Though it can be set directly as:

 

 

 

 

	// set texts:
	buildMatList.SetHeaderItemText (BuildingMatNameTab,	"Building Material");
	buildMatList.SetHeaderItemText (PenIndexTab,		"cutFillPen");

 

 

 

 

What is the difference between the two? Which one is used in which case? What is the reason for setting the header using the resource IDs?

 

Also, what is the acceptable value range for the List Box Header Strings Resource ID? I saw it was set to 32593 when the GDLG and DLGH were 32591 (for a dialog box). I am using a palette, so GDLG and DLGH are 32500. What should be the ID for the List Box Header Strings in this case?

 

Thanks!

 

20 REPLIES 20

VEGH
Graphisoft
Graphisoft

The result of both methods are the same. But we used to put the localised resources in different modules than the executable. This way when the localized products are prepared the executable is the same for all languages, and only the dlls containing the language dependent content is varied. If not the code should be changed for each language (or some other tricks needed), and the whole executable needs to be rebuilt with every language.

The resource IDs can have any arbitrary value in [1 .. 32767], but must be unique.

Thanks!

dushyant
Booster
listBox.SetHeaderItemCount(3);

The header count can be set as above. How is it different from the following?

 

listBox.SetTabFieldCount(3);

 

 

Listbox header has two modes.

In the synchron mode the header item count and sizes are set by the Dialog Manager based upon the tab field count and sizes. Whenever tab count or a tab size canges the header will follow it. And0 tabfields will also follow the corresponding header item change automatically.

 

In the asynchron mode the header and the tabs are independent. You have to manage the header count and sizes. In this mode you can put one header item for multiple tabs, but this needs more work to manage. When something changes in the header the tabs should be set and vice versa.

Thanks a lot for clarifying both the modes.

When the synchron mode is set to 'true',  how can we set a minimum width value for each header?

The SetHeaderItemMinSize can be applied to set the min value of header items for sync and async listboxes also. But this limit effects only the mouse interaction. If a tab field size is set to a lesser value from the code then the header item size will have that value also in a synchron list since the header item sizes and tabfield sizes follow each other.

SetHeaderItemMinSize is what I needed. Thanks!

dushyant
Booster

I'm trying to set the width of each column of the list box based on panel-resize:

 

 

MyPalette::PanelResized(const DG::PanelResizeEvent& ev)
{
	BeginMoveResizeItems();
	listBox.Resize(ev.GetHorizontalChange(), ev.GetVerticalChange());
        short tabWidth = listBox.GetItemWidth() / 3; 
	short posBegin = 0;
	posBegin = listBox.GetTabFieldBeginPosition(1);
	listBox.SetTabFieldBeginEndPosition(1, posBegin, posBegin + tabWidth);
	posBegin = listBox.GetTabFieldBeginPosition(2);
	listBox.SetTabFieldBeginEndPosition(2, posBegin, posBegin + tabWidth);
	posBegin = listBox.GetTabFieldBeginPosition(3);
	listBox.SetTabFieldBeginEndPosition(3, posBegin, posBegin + tabWidth);
	EndMoveResizeItems();
}

 

 

This is only changing the width of the headers (though not as expected). The tab fields remain static, even though I have the synchron mode ON. Also it's odd why the header is changing as the Tab Field position is being set.

Does the synchron work with only the mouse interaction in this case too?

 

I even tried the following, but it makes no change in the header items or tab items:

	short headerItemChangeHorz = ev.GetHorizontalChange() / 3;
	short headerItemSize = 0;
	headerItemSize = listBox.GetHeaderItemSize(1);
	listBox.SetHeaderItemSize(1, headerItemSize + headerItemChangeHorz);
	headerItemSize = listBox.GetHeaderItemSize(2);
	listBox.SetHeaderItemSize(2, headerItemSize + headerItemChangeHorz);
	headerItemSize = listBox.GetHeaderItemSize(3);
	listBox.SetHeaderItemSize(3, headerItemSize + headerItemChangeHorz);

 

Well, about the second example: you are right, the synchron works with mouse interaction only. If you want to change the layout, the tabs need to be changed. As a result headers follow them.

 

The first code needs some adjustments also. On Windows when BeginMoveResizeItems is called te controls are switched to a kind of special state in the meaning that querying their sizes and positions result false values. In this case the move/resize actions are just logged by Windows internally. All the modifications are done at once when EndMoveResizeItems is called.

 

You can do the following in PanelResized:

BeginMoveResizeItems();
<Move and resize all items here>
EndMoveResizeItems();

listItemWidth = listBox.GetItemWidth (); // It has the new value now
<Layout listbox tabs here using listItemWidth>

Its best to do the layouting in a separate function which is called in the PanelResizeExited also. Sometimes fast resizing of the dialog result in inappropriate size columns which can be avoided this way.

Thanks for that info VEGH.

 

I have now put the listBox.Resize() and button.Move() within BeginMoveResizeItems() and EndMoveResizeItems(). And the tabs layouting after that.

Although I did have to change the value of begin-position for listBox.SetTabFieldBeginEndPosition(). I was trying to get the existing begin-position for each tab, but that was giving out some strange behaviour. So I just started with 0 for the first tab and added the tabWidth for the next tab. Now it works perfectly. Thanks again.

 

Do you know where I could find the documentation on list-boxes and other controls as button, checkbox, text, etc.? I could not find it on the online Archicad API Reference.

As far as I know Dialog Manager Documentation is part of the API DevKit.

I was only referring the online documentation. Will check out the DevKit docs.

Thanks a lot!

 

dushyant
Booster

Is the ListBoxSelectionChanged event only triggered when there's a manual (mouse interaction) selection by the user in the list box?

I am selecting the list box item as: 

listBox.SelectItem(1);

and the item does get selected in the list, but the following function is not called:

virtual void ListBoxSelectionChanged(const DG::ListBoxSelectionEvent& ev) override;

It's only called when the list box item is manually selected by a mouse-click.

Yes. In general DG notifications follow the changes only from user interactions.

If you create a change handler function you can call it from the DG notification and elsewhere also when a Set function is called.

dushyant
Booster

Which ones are you referring to as 'DG notifications' and 'change handler function'?

 

I mean DG notifications are ButtonClicked, ListBoxSelectionChanged and so on.

Handler function is what you implement to adjust dialog data or dialog item states.

Something like this:

void SometDialog::ButtonClicked (const DG::ButtonClickEvent& ev)
{
    MyClickHandlerToDoWhatever ();
}

 

This MyClickHandler can be called from elsewhere also.

dushyant
Booster

Ok. So ListBoxSelectionChange() was not being called when I changed the list-box-selection from MyChangeHandler();

dushyant
Booster

To get the data stored in a row in a list box as:

 

DGUserData data = DGListGetItemUserData(SelectionPaletteResId, ListBoxId, listItemIndex);

 

What kind of DGUserData value is to be set in:

DGListSetItemUserData (short dialId, short item, short listItem, DGUserData value);

DGUserData seems to be an integer:  typedef long long Int64; typedef Int64 IntPtr; typedef GS::IntPtr DGUserData;

 

You can put any arbirtary value in the userdata of each item as far as it fits in GS::IntPtr. We used to put there a pointer to some data (before the c++ world).

Now it is better/safer to attach c++ objects to the list items. These member functions can be used (please see DGListBox.hpp):

void SetItemObjectData (short listItem, GS::Ref<GS::Object> object);
GS::Ref<GS::Object> GetItemObjectData (short listItem) const;

 Any object inherited from the GS::Object can be used here in the GS::Ref.

Still looking?

Browse more topics

Back to forum

See latest solutions

Accepted solutions

Start a new discussion!