Tree — Scrollable tree selection
Tree
( | string label , |
itemList
items
) ; |
items
the items contained in the tree
itemList ::= [ item [ , item ] [ , item ] ... ] item ::= string | `item( [ `id( string ),] string [ , true | false ] [ , itemList ] )
The boolean parameter inside `item() indicates whether or not the respective tree item should be opened by default - if it has any subitems and if the respective UI is capable of closing and opening subtrees. If the UI cannot handle this, all subtrees will always be open.
A tree widget provides a selection from a hierarchical tree structure. The semantics are very much like those of a SelectionBox. Unlike the SelectionBox, however, tree items may have subitems that in turn may have subitems etc.
Each item has a label string, optionally preceded by an ID. If the item has subitems, they are specified as a list of items after the string.
The tree widget will not perform any sorting on its own: The items are always sorted by insertion order. The application needs to handle sorting itself, if desired.
Note: The Qt version of the Wizard widget also provides a built-in tree with an API that is (sometimes) easier to use.
// Simple tree example { UI::OpenDialog( `VBox( `Tree(`id(`dest_dir), "Select destination directory:", [ `item(`id(`root), "/" , true, [ `item(`id(`etc), "etc", [ `item("opt"), `item("SuSEconfig"), `item("X11") ] ), `item("usr", false, [ "bin", "lib", `item("share", [ "man", "info", "emacs" ] ), `item(`id(`usr_local),"local"), `item("X11R6", [ "bin", "lib", "share", "man", "etc" ] ) ] ), `item(`id(`opt), "opt", true, [ "kde", "netscape", "Office51" ] ), `item("home"), "work", `item(`id(`other), "<other>") ] ) ] ), `HBox( `PushButton(`id(`sel_opt), `opt(`hstretch), "/&opt" ), `PushButton(`id(`sel_usr), `opt(`hstretch), "/&usr" ), `PushButton(`id(`sel_usr_local), `opt(`hstretch), "/usr/&local" ) ), `PushButton(`id(`ok), `opt(`default), "&OK") ) ); any id = nil; repeat { id = UI::UserInput(); if ( id == `sel_usr) UI::ChangeWidget(`dest_dir, `CurrentItem, "usr" ); else if ( id == `sel_usr_local) UI::ChangeWidget(`dest_dir, `CurrentItem, `usr_local ); else if ( id == `sel_opt) UI::ChangeWidget(`dest_dir, `CurrentItem, `opt ); } until ( id == `ok ); // Get the input from the tree. // // Notice: The return value of UI::UserInput() does NOT return this value! // Rather, it returns the ID of the widget (normally the PushButton) // that caused UI::UserInput() to return. any dest_dir = UI::QueryWidget(`dest_dir, `CurrentItem); y2debug( "Selected: %1", dest_dir ); if ( dest_dir == nil ) dest_dir = ""; // Close the dialog. // Remember to read values from the dialog's widgets BEFORE closing it! UI::CloseDialog(); // Pop up a new dialog to echo the selection. UI::OpenDialog( `VBox( `Label( sformat( "Selected destination directory: %1", dest_dir ) ), `PushButton(`opt(`default), "&OK") ) ); UI::UserInput(); UI::CloseDialog(); }
{ // Build a dialog with a tree for directory selection, three // buttons with common values and a label that directly echoes any // selected directory. // // The tree in this example uses the `notify option that makes // UI::UserInput() return immediately as soon as the user selects a // tree item rather than the default behaviour which waits for the // user to activate a button. UI::OpenDialog( `VBox( `MinHeight( 14, `Tree(`id(`dest_dir), `opt(`notify), "Select destination directory:", [ `item(`id(`root), "/" , true, [ `item(`id(`etc), "etc", [ `item("opt"), `item("SuSEconfig"), `item("X11") ] ), `item("usr", false, [ "bin", "lib", `item("share", [ "man", "info", "emacs" ] ), `item(`id(`usr_local),"local"), `item("X11R6", [ "bin", "lib", "share", "man", "etc" ] ) ] ), `item(`id(`opt), "opt", true, [ "kde", "netscape", "Office51" ] ), `item("home"), "work", `item(`id(`other), "<other>") ] ) ] ) ), `HBox( `PushButton(`id(`sel_opt ), `opt(`hstretch), "/&opt" ), `PushButton(`id(`sel_usr ), `opt(`hstretch), "/&usr" ), `PushButton(`id(`sel_usr_local ), `opt(`hstretch), "/usr/&local" ), `PushButton(`id(`none ), `opt(`hstretch), "none" ) ), `HBox( `Label("Current Value:"), `Label(`id(`echo), `opt(`outputField, `hstretch), "?????????") ), `PushButton(`id(`ok), `opt(`default), "&OK") ) ); any id = nil; repeat { id = UI::UserInput(); if ( id == `sel_usr ) UI::ChangeWidget(`dest_dir, `CurrentItem, "usr" ); else if ( id == `sel_usr_local ) UI::ChangeWidget(`dest_dir, `CurrentItem, `usr_local ); else if ( id == `sel_opt ) UI::ChangeWidget(`dest_dir, `CurrentItem, `opt ); else if ( id == `none ) UI::ChangeWidget(`dest_dir, `CurrentItem, nil ); UI::ChangeWidget(`echo, `Value, ""); any current_dir = UI::QueryWidget(`dest_dir, `CurrentItem); if ( current_dir != nil ) UI::ChangeWidget(`echo, `Value, sformat( "%1", current_dir ) ); y2milestone( "Items:\n%1", UI::QueryWidget(`dest_dir, `Items ) ); y2milestone( "OpenItems: %1", UI::QueryWidget(`dest_dir, `OpenItems ) ); y2milestone( "Current Branch: %1", UI::QueryWidget(`dest_dir, `CurrentBranch ) ); } until ( id == `ok ); // Close the dialog. // Remember to read values from the dialog's widgets BEFORE closing it! UI::CloseDialog(); }
{ // Build a dialog with a tree for directory selection, three // buttons with common values and a label that directly echoes any // selected directory. // // The tree in this example uses the `notify option that makes // UI::UserInput() return immediately as soon as the user selects a // tree item rather than the default behaviour which waits for the // user to activate a button. UI::OpenDialog( `MinWidth( 50, `VBox( `Tree(`id(`dest_dir), `opt(`notify), "Select destination directory:", [ `item( "/" , true, [ `item( "etc", [ `item("opt"), `item("SuSEconfig"), `item("X11") ] ), `item( "usr", false, [ "bin", "lib", `item("share", [ "man", "info", "emacs" ] ), `item( "local" ), `item("X11R6", [ "bin", "lib", "share", "man", "etc" ] ) ] ), `item( "opt", true, [ "kde", "netscape", "Office51" ] ), `item("home"), "work", `item( "<other>") ] ) ] ), `HBox( `PushButton(`id(`sel_opt), `opt(`hstretch), "/&opt" ), `PushButton(`id(`sel_usr), `opt(`hstretch), "/&usr" ), `PushButton(`id(`sel_usr_local), `opt(`hstretch), "/usr/&local" ) ), `HBox( `HWeight( 2, `Label("Current Item:") ), `HWeight( 5, `Label(`id(`echoItem), `opt(`outputField, `hstretch), "") ) ), `HBox( `HWeight( 2, `Label("Current Branch:") ), `HWeight( 5, `Label(`id(`echoBranch), `opt(`outputField, `hstretch), "") ) ), `HBox( `HWeight( 2, `Label("Current Path:") ), `HWeight( 5, `Label(`id(`echoPath), `opt(`outputField, `hstretch), "") ) ), `PushButton(`id(`ok), `opt(`default), "&OK") ) ) ); any id = nil; repeat { id = UI::UserInput(); if ( id == `sel_usr) UI::ChangeWidget( `id( `dest_dir ), `CurrentItem, "usr" ); else if ( id == `sel_usr_local) UI::ChangeWidget( `id( `dest_dir ), `CurrentItem, "local" ); else if ( id == `sel_opt) UI::ChangeWidget( `id( `dest_dir ), `CurrentItem, "opt" ); else if ( id == `dest_dir) { any current_dir = UI::QueryWidget(`dest_dir, `CurrentItem ); if ( current_dir != nil ) UI::ChangeWidget( `id( `echoItem ), `Value, sformat( "%1", current_dir ) ); list<string> current_branch = (list<string>) UI::QueryWidget(`dest_dir, `CurrentBranch ); if ( current_branch != nil ) { UI::ChangeWidget(`echoBranch, `Value, sformat( "%1", current_branch) ); string current_path = mergestring( current_branch, "/" ); if ( size( current_path ) > 2 ) // Remove duplicate "/" at start current_path = substring( current_path, 1, size( current_path )-1 ); UI::ChangeWidget(`echoPath, `Value, sformat( "%1", current_path ) ); } } } until ( id == `ok ); // Close the dialog. // Remember to read values from the dialog's widgets BEFORE closing it! UI::CloseDialog(); }
// Tree with icons { UI::OpenDialog( `VBox( `Heading( "YaST2 Mini Control Center" ), `Tree(`id(`mod), "Modules", [ `item(`id( "country" ), `icon( "yast-yast-language.png" ), "Localization", true, [ `item(`id( "keyboard" ), `icon( "yast-keyboard.png" ), "Keyboard" ), `item(`id( "timezone" ), `icon( "yast-timezone.png" ), "Time zone" ) ] ), `item(`id( "mouse" ), `icon( "yast-mouse.png" ), "Mouse" ), `item(`id( "lan" ), `icon( "yast-lan.png" ), "Network" ), `item(`id( "sw_single" ), `icon( "yast-software.png" ), "Software" ) ] ), `PushButton(`id(`ok), `opt(`default), "&OK") ) ); UI::UserInput(); UI::CloseDialog(); }
// Example showing how to replace Tree items { list pizza_list = [ "Pizza Napoli", "Pizza Funghi", "Pizza Salami", "Pizza Hawaii" ]; list pasta_list = [ "Spaghetti", "Rigatoni", "Tortellini" ]; list veggie_toppings = [ "Cheese", "Mushrooms", "Pepperoni", "Rucola", "Tomatoes" ]; list meat_toppings = [ "Ham", "Salami", "Tuna" ]; list menu = [ `item( `id ( `pizza_branch ), "Pizza", true, pizza_list ), `item( `id ( `pasta_branch ), "Pasta", true, pasta_list) ]; list toppings = [ `item( `id ( `meat_branch ), "Meat", true, meat_toppings ), `item( `id ( `veggie_branch ), "Veggie", true, veggie_toppings) ]; UI::OpenDialog( `VBox( `Tree(`id(`listing), "Daily &Specials:", menu ), `HBox( `PushButton(`id(`menu), "&Menu" ), `PushButton(`id(`toppings), "&Toppings" ), `PushButton(`id(`empty), "&None" ) ), `PushButton(`id(`ok), "&OK" ) ) ); symbol button = nil; do { button = (symbol) UI::UserInput(); if ( button == `menu ) UI::ChangeWidget(`listing, `Items, menu); if ( button == `toppings ) UI::ChangeWidget(`listing, `Items, toppings ); if ( button == `empty ) UI::ChangeWidget(`listing, `Items, [] ); } while ( button != `ok ); string order = (string) UI::QueryWidget(`listing, `CurrentItem ); UI::CloseDialog(); // // Show the result // UI::OpenDialog(`VBox( `Label( sformat( "Your order: %1", order ) ), `PushButton(`opt(`default), "&OK" ) ) ); UI::UserInput(); UI::CloseDialog(); }
// Advanced example of using the Wizard widget. // // Note: YCP applications are discouraged from using the Wizard widget directly. // Use the Wizard module instead. { if ( ! UI::HasSpecialWidget(`Wizard) ) { y2error( "This works only with UIs that provide the wizard widget!" ); return; } string help_text = "<p>This is a help text.</p>" + "<p>It should be helpful.</p>" + "<p>If it isn't helpful, it should rather not be called a <i>help text</i>.</p>"; UI::OpenDialog(`opt(`defaultsize ), `Wizard(`opt(`treeEnabled), `back, "&Back", `abort, "Ab&ort", `next, "&Next" ) ); // UI::DumpWidgetTree(); UI::WizardCommand(`SetDialogIcon( "/usr/share/YaST2/theme/current/icons/22x22/apps/YaST.png" ) ); UI::WizardCommand(`SetDialogHeading( "Welcome to the YaST2 installation" ) ); UI::WizardCommand(`SetHelpText( help_text ) ); UI::WizardCommand(`AddTreeItem( "", "First Toplevel Item" , "tl1" ) ); UI::WizardCommand(`AddTreeItem( "", "Second Toplevel Item", "tl2" ) ); UI::WizardCommand(`AddTreeItem( "", "Third Toplevel Item" , "tl3" ) ); UI::WizardCommand(`AddTreeItem( "tl1", "First Sublevel" , "1-1" ) ); UI::WizardCommand(`AddTreeItem( "tl1", "Second Sublevel" , "1-2" ) ); UI::WizardCommand(`AddTreeItem( "tl1", "Third Sublevel" , "1-3" ) ); UI::WizardCommand(`AddTreeItem( "tl2", "First Sublevel" , "2-1" ) ); UI::WizardCommand(`AddTreeItem( "tl2", "Second Sublevel" , "2-2" ) ); UI::WizardCommand(`AddTreeItem( "tl2", "Third Sublevel" , "2-3" ) ); UI::WizardCommand(`AddTreeItem( "1-2", "First 3rd level " , "3rd 1" ) ); UI::WizardCommand(`AddTreeItem( "1-2", "Second 3rd level " , "3rd 2" ) ); UI::WizardCommand(`AddTreeItem( "1-2", "Item without ID" , "" ) ); UI::WizardCommand(`SelectTreeItem( "3rd 1" ) ); UI::WizardCommand(`AddMenu( "&File", "file-menu" ) ); UI::WizardCommand(`AddMenu( "&Edit", "edit-menu" ) ); UI::WizardCommand(`AddMenu( "&Options", "opt-menu" ) ); UI::WizardCommand(`AddMenuEntry ( "file-menu", "&New", "file-new" ) ); UI::WizardCommand(`AddMenuEntry ( "file-menu", "&Open", "file-open" ) ); UI::WizardCommand(`AddSubMenu ( "file-menu", "Open &Recent", "file-recent" ) ); UI::WizardCommand(`AddMenuEntry ( "file-menu", "&Save", "file-save" ) ); UI::WizardCommand(`AddMenuEntry ( "file-menu", "Save &As", "file-save-as" ) ); UI::WizardCommand(`AddMenuEntry ( "file-recent", "/tmp/test1", "recent-test1" ) ); UI::WizardCommand(`AddMenuEntry ( "file-recent", "/tmp/test2", "recent-test2" ) ); UI::WizardCommand(`AddMenuEntry ( "edit-menu", "C&ut", "edit-cut" ) ); UI::WizardCommand(`AddMenuEntry ( "edit-menu", "C&opy", "edit-copy" ) ); UI::WizardCommand(`AddMenuEntry ( "edit-menu", "&Paste", "edit-paste" ) ); UI::WizardCommand(`AddMenuEntry ( "opt-menu", "&Settings", "opt-settings" ) ); UI::WizardCommand(`AddMenuSeparator ( "opt-menu" ) ); UI::WizardCommand(`AddMenuEntry ( "opt-menu", "Activate &Hypersonic Transducer", "frank-n-furter" ) ); while ( true ) { map event = UI::WaitForEvent(); y2milestone( "Got event: %1", event ); if ( event[ "ID" ]:nil == `abort ) break; y2milestone( "Tree selection: %1", UI::QueryWidget(`id(`wizard), `CurrentItem ) ); } UI::CloseDialog(); }