DumbTab — Simplistic tab widget that behaves like push buttons
DumbTab
( | list tabs , |
term
contents
) ; |
This is a very simplistic approach to tabbed dialogs: The application specifies a number of tab headers and the page contents and takes care of most other things all by itself, in particular page switching. Each tab header behaves very much like a PushButton - as the user activates a tab header, the DumbTab widget simply returns the ID of that tab (or its text if it has no ID). The application should then take care of changing the page contents accordingly - call UI::ReplaceWidget() on the ReplacePoint specified as tab contents or similar actions (it might even just replace data in a Table or RichText widget if this is the tab contents). Hence the name DumbTab.
The items in the item list can either be simple strings or `item() terms with an optional ID for each individual item (which will be returned upon UI::UserInput() and related when the user selects this tab), a (mandatory) user-visible label and an (optional) flag that indicates that this tab is initially selected. If you specify only a string, UI::UserInput() will return this string.
This is a "special" widget, i.e. not all UIs necessarily support it. Check for availability with HasSpecialWidget( `DumbTab )
before using it.
![]() | Note |
---|---|
Please notice that using this kind of widget more often than not is the result of poor dialog or workflow design. Using tabs only hides complexity, but the complexity remains there. They do little to make problems simpler. This however should be the approach of choice for good user interfaces. It is very common for tabs to be overlooked by users if there are just two tabs to select from, so in this case better use an "Expert..." or "Details..." button - this gives much more clue to the user that there is more information available while at the same time clearly indicating that those other options are much less commonly used. If there are very many different views on data or if there are lots and lots of settings, you might consider using a tree for much better navigation. The Qt UI's wizard even has a built-in tree that can be used instead of the help panel. If you use a tree for navigation, unter all circumstances avoid using tabs at the same time - there is no way for the user to tell which tree nodes have tabs and which have not, making navigation even more difficult. KDE's control center or Mozilla's settings are very good examples how not to do that - you become bogged down for sure in all those tree nodes and tabs hidden within so many of them. |
if ( HasSpecialWidget( `DumbTab) {... `DumbTab( [ `item(`id(`page1), "Page &1" ), `item(`id(`page2), "Page &2" ) ], contents; }
// Minimalistic example for tab widget { if ( ! UI::HasSpecialWidget(`DumbTab ) ) { UI::OpenDialog( `VBox( `Label("Error: This UI doesn't support the DumbTab widget!"), `PushButton(`opt(`default), "&OK") ) ); UI::UserInput(); UI::CloseDialog(); return; } UI::OpenDialog( `VBox( `DumbTab( [ "Page 1", "Page 2", "Page 3" ], `RichText(`id(`contents), "Contents" ) ), `Right(`PushButton(`id(`close), "&Close" ) ) ) ); UI::DumpWidgetTree(); any input = nil; repeat { input = UI::UserInput(); if ( is( input, string ) ) { UI::ChangeWidget(`contents, `Value, (string) input ); } } until ( input == `close ); UI::CloseDialog(); }
// Typical usage example for tab widget { term address_page = `VBox( `Left( `Heading( "Address" ) ), `VSpacing(), `HCenter( `HSquash( `VBox( `HSpacing( 50 ), `InputField( "Name" ), `InputField( "E-Mail" ), `InputField( "Phone" ), `VSpacing(), `MultiLineEdit( "Comments" ), `VStretch() ) ) ) ); term overview_page = `VBox( `Left( `Heading( "DumbTab Widget Overview" ) ), `VSpacing(), `Label( "This kind of tab is pretty dumb - hence the name DumbTab.\n" + "You need to do most everything yourself.\n" + "Each tab behaves very much like a push button;\n" + "the YCP application is notified when the user clicks on a tab.\n" + "The application must take care to exchange the tab contents.\n" + "\n" + "Note: That means changes made in on tab are lost when switching\n" + "the tabs, e.g. text entered here in the address tab.") ); term style_hints_page = `VBox( `Left( `Heading( "GUI Style Hints" ) ), `VSpacing(), `Heading( "Using tabs is usually a result of poor dialog design." ), `VSpacing(), `Left( `Label( "Tabs hide complexity, they do not resolve it.\n" + "The problem remains just as complex as before,\n" + "only the user can no longer see it." ) ) ); UI::OpenDialog(`opt(`defaultsize), `VBox( `DumbTab( [ `item(`id(`address ), "&Address" ), `item(`id(`overview ), "&Overview" ), `item(`id(`style ), "GUI &Style Hints", true ) // true: selected ], `Left( `Top( `HVSquash( `VBox( `VSpacing(0.3), `HBox( `HSpacing(1), `ReplacePoint(`id(`tabContents ), style_hints_page ) ) ) ) ) ) ), `Right(`PushButton(`id(`close), "Cl&ose" ) ) ) ); while ( true ) { symbol widget = (symbol) UI::UserInput(); if ( widget == `close ) break; else if ( widget == `address ) UI::ReplaceWidget(`tabContents, address_page ); else if ( widget == `overview ) UI::ReplaceWidget(`tabContents, overview_page ); else if ( widget == `style ) UI::ReplaceWidget(`tabContents, style_hints_page ); } UI::CloseDialog(); }