# gTabs

Definition: | include pGUI.e gdx id = gTabs([gdx children={},] [rdx tabchange=NULL,] string attributes="", dword_seq args={})
Description: | NB WOEFULLY INCOMPLETE: no further work is planned until after the basics of layout management are sorted out... Creates a native container for composing elements in hidden layers with only one layer visible, which can be interactively controlled via a line of tabs with titles. Also known as a notebook in some systems. children: List of elements|titles|images for each tab, see notes. It can be empty. tabchange: an optional procedure, which should be invoked whenever the user changes the selected tab. For more information on the attributes and args parameters see gSetAttributes(). This is a paranormalised function (see technicalia). Returns: the identifier of the created element.
pwa/p2js: | Supported.
See Also: | gImage, gButton
Example: |
    -- demo\xpGUI\gTabs.exw
    include xpGUI.e
    --constant xpm = ...(code omitted for brevity)
    gdx tabs = gTabs({{"First",xpm},"Second","Third","Fourth"}),
        dlg = gDialog(tabs,"gTabs","SIZE=240x80")
    gShow(dlg)
    gMainLoop()
Notes: | There are at least two very distinct uses of a tab control. The first, which is depicted above and I shall dub "obvious", has a fixed number of tabs with different interface elements on each, only one set of which is visible at any given time. The second, which is(/will be) used by xpEditer and I shall dub "virtual", does not actually have a body as such on each tab, and it becomes the sole responsibility of the application (rather than xpGUI) to change the contents of some other (unspecified) display element, and for that matter to independently ensure the sizes of the tab bar and that any corresponding contents remain in sync, if/when appropriate. In the case of xpEditer the latter is achieved simply by putting them in the same gVbox(). Each element of children can therefore be a gdx, title, {gdx,title[,image]}, or {title[,image]}, where title is a string. Note that gTabs does not support an image [see gImage() for details] with no text. The children parameter is expected to be reasonably homogenous: while some child tabs might not have an image, they should either all have a gdx or none. It also makes little sense to specify half the titles via the children parameter and the other half via the TABTITLE attribute, and there is certainly no guarantee of consistent cross-platform behaviour should both be provided. Overriding it after display is fine, but should two different titles have been specified before display, I simply don’t care which shows up. A completely missing title on any tab is not likely to look very good either, and of course within that statement I’m including a run-time crash that rudely terminates the entire application, but equally I am not about to guarantee it will not work, just look like it has been dragged through a hedge backwards. Mnemonics on tab titles are only formally supported in the fixed "obvious"/with-gdx case: ymmv, the fundamental issue is with removing/replacing mnemonics, and besides which it is probably not a good GUI design to have say Alt H only available half the time. Note that xpEditer uses a "virtual" gTabs and a single gCanvas that is fully redrawn on tab change, and likewise filedump.exw does a similar trick over a single gTable, hence neither should be copied or studied for more traditional uses, by which I specifically mean where selecting a different tab automatically hides some controls and displays some others. Neither of those make any attempt to use mnemonics on tab titles, either. DEV... The tab control can be created with no children and filled dynamically using IupAppend. There is no "IupTabItem", instead the children can be any standard element, with IupHbox and IupVbox being the most likely/useful. A tab control with no children is not officially supported. xpEditer uses [or is planned to] a fake "<empty>" tab (disabled) to cover that case, and filedump is not intended to be runnable without a file to show. !! Its children automatically receives a name when the child is appended or inserted into the tabs. ? Differently from IupZbox, IupTabs does NOT depend on the VISIBLE attribute. In GTK, when the tabs buttons are scrolled, the active tab is also changed. When you change the active tab the focus is usually not changed. If you want to control the focus behavior call IupSetFocus in the TABCHANGE_CB handler. Unfortunately this does not works in GTK and in Motif, because in both systems the focus will be set by the system after the handler is called. Notice that there is no attribute to disable a single tab. This is a design decision of all native toolkits, not a IUP decision. It is so because a disabled tab is a confusing interface situation. In Windows, when an IupValuator is inside an IupTabs, the tabs disappear when the mouse moves over it after being used in the valuator. A workaround is to put the valuator inside an IupFrame and then inside the IupTabs, so the problem does not occur. ? The utility functions IupSetAttributeId, IupGetAttributeId, IupGetIntId, IupGetFloatId, IupSetIntId, and IupSetFloatId can also be used here. Note that the C function IupSetfAttributeId is not wrapped by pGUI, however that functionality is covered by the optional parameters of IupSetStrAttributeId. They work just like the respective traditional set and get functions, but the attribute string is complemented with the id value. For example IupSetAttributeId(ih, "TABTITLE", 3, value) is the same as IupSetAttribute(ih, "TABTITLE3", value) These functions are faster than the traditional functions because they do not need to parse the attribute name string and the application does not need to concatenate the attribute name with the id. The C function IupTabsv is not wrapped: children must be a sequence, rather than a pointer to dword-null-terminated memory.
Attributes: |
? COUNT | (read-only) (non inheritable) returns the number of tabs. Same value returned by IupGetChildCount. (since 3.3)
? EXPAND | (non inheritable) The default value is "YES".
? SHOWCLOSE | [Windows and GTK Only] (non inheritable) enables the close button on each tab. Default value: "NO". In Windows the close button imply the classic visual for the control. By default when closed the tab is hidden. To change that behavior use the TABCLOSE_CB handler. (since 3.10)
? SIZE | (non inheritable) The default size is the smallest size that fits its largest child. All child elements are considered even invisible ones.
? VALUE | (non inheritable) Changes the active tab by its handle. The value passed must be the handle of a child contained in the tabs. When the tabs is created, the first element inserted is set as the visible child.
? VALUEPOS | (non inheritable) Changes the active tab by its position, starting at 0. When the tabs is created, the first element inserted is set as the visible child. In GTK, inside the handler the returned value is still the previous one.
also | ACTIVE, FONT, MINSIZE, MAXSIZE, SIZE, TIP, VISIBLE.
Attributes: | (non inheritable, at children only)
? TABTITLE | Same as TABTITLEn but set in each child. (TESTME:) Works only if set before the child is added to the tabs.
? TABIMAGE | Same as TABIMAGEn but set in each child. (TESTME:) Works only if set before the child is added to the tabs.
Handlers: |
? TABCHANGED | Handler called when the user shifts the active tab. procedure tabchange(gdx id, integer new_pos, old_pos) id: identifier of the element that activated the event. new_pos: the new tab position selected by the user old_pos: the previously selected tab position
? TABCLOSE_CB | [Windows and GTK Only] Handler called when the user clicks on the close button. Called only when SHOWCLOSE=Yes. function tabclose_cb(Ihandle ih, integer pos) ih: identifier of the element that activated the event. pos: the tab position Returns: the tab will be hidden if the handler returns XPG_DEFAULT or if it does not exists. If XPG_CONTINUE is returned the tab is removed and its children are destroyed. If XPG_IGNORE is returned does nothing.
also | CLICK, KEY: All common handlers are supported.
Technicalia | As this is a paranormalised function, and with no expectation that you should attempt to memorise this lot, except maybe "qraa", you can assume that all of the following are potentially perfectly valid, with the fairly obvious restrictions that any parameters must be in strict qraa-order, and no args without attributes:
                            gTabs()
                            gTabs(tabchange)
                            gTabs(tabchange, attributes)
                            gTabs(tabchange, attributes, args)
                            gTabs(attributes, args)
                            gTabs(attributes)
                            gTabs(children)
                            gTabs(children, tabchange)
                            gTabs(children, attributes)
                            gTabs(children, attributes, args)
                            gTabs(children, tabchange, attributes)
                            gTabs(children, tabchange, attributes, args)  -- (the full set)
Note that in practice children and tabchange are actually defined as object, and attributes as a sequence rather than a string, but they are all manually and thoroughly verified to be of the documented types, after being repositioned via xpGUI.e/paranormalise_qraa(). Also as per the notes section above, the elements of children can be any of six different formats.