]> git.tuebingen.mpg.de Git - gsu.git/blob - gui
gui: Implement descriptive tree items.
[gsu.git] / gui
1 #!/bin/bash
2 # Copyright (C) 2006 Andre Noll
3 # Licensed under the LGPL, version 3. See COPYING and COPYING.LESSER.
4
5 if [[ "$(type -t _gsu_setup)" != "function" ]]; then
6         gsu_dir=${gsu_dir:-${BASH_SOURCE[0]%/*}}
7         . "$gsu_dir/common" || exit 1
8         _gsu_setup
9 fi
10
11 _gsu_node_name_pattern='[a-zA-Z_]'
12
13 _get_geometry()
14 {
15         local x y
16         result="$(stty size)"
17         if (($? != 0)); then
18                 gsu_msg "fatal: could not get terminal geometry"
19                 exit 1
20         fi
21         x="${result#* }"
22         y="${result%% *}"
23         ((x > 190)) && x=190
24         result="$y $x"
25 }
26
27 _set_dialog_ret()
28 {
29         local ec="$1"
30
31         case "$ec" in
32         0) ret=$GSU_SUCCESS;;
33         1|255) ret=1;; # cancelled
34         *)
35                 result="dialog exit code $ec"
36                 ret=-$E_GSU_DIALOG
37         esac
38 }
39
40 # Open a dialog box which asks the user to input a text
41 #
42 # Usage: gsu_input_box <text> <init>
43 #
44 # <text> is displayed above of the input field, which is is preset to <init>.
45 # The entered text is returned in $result. On success (user pressed OK)
46 # the function returns zero. If the user selected Cancel, the return value is
47 # one. On dialog errors, a negative error code is returned.
48 gsu_inputbox()
49 {
50         local g text="$1" init="$2"
51
52         _get_geometry
53         g="$result"
54         result="$(dialog --inputbox "$text" $g "$init" 3>&1 1>&2 2>&3 3>&-)"
55         _set_dialog_ret $?
56 }
57
58 # Show the given file in a text box
59 #
60 # Usage: gsu_textbox <path>
61 #
62 # The box has an OK button which closes the box when activated.
63 gsu_textbox()
64 {
65         local g file="$1"
66
67         _get_geometry
68         g="$result"
69
70         ret=-$E_GSU_DIALOG
71         result='textbox'
72         dialog --textbox "$file" $g
73         _set_dialog_ret $?
74 }
75
76 # Show a message in a text box
77 #
78 # Usage: gsu_msgbox <text>
79 #
80 # This is like gsu_textbox() but the text is passed as a string.
81 gsu_msgbox()
82 {
83         local tmp
84
85         # Some versions of dialog segfault if the text is too long. Hence we
86         # always use a temporary file.
87         gsu_make_tempfile 'gsu_msgbox.XXXXXXXXXX'
88         ((ret < 0)) && return
89         tmp="$result"
90         trap "rm -f $tmp" EXIT
91         echo "$1" > "$tmp"
92         gsu_textbox "$tmp"
93         rm -f "$tmp" # ignore errors
94 }
95
96 _gsu_menu()
97 {
98         local header=$1 dflt_item=$2
99         local geom
100
101         shift 2
102         _get_geometry
103         geom=$result
104         result="$(dialog --no-lines --no-items \
105                 --default-item "$dflt_item" \
106                 --menu "$gsu_banner_txt"$'\n'"Current location: $header" \
107                 $geom 16 "$@" 3>&1 1>&2 2>&3 3>&-)"
108         _set_dialog_ret $?
109 }
110
111 _get_level()
112 {
113         local tmp="${1%%$_gsu_node_name_pattern*}"
114         result="${#tmp}"
115 }
116
117 _get_subtree()
118 {
119         local tree="$1" root="${2%/}"
120         local first TAB='       '
121
122         ret=-$E_GSU_MENU_TREE
123         result="subtree grep failed"
124         first="$(grep -n "$TAB\{1,\}$root/" <<< "$tree")" || return
125         [[ -z "$first" ]] && return
126
127         line_num="${first%%:*}"
128         _get_level "${first#*:}"
129         level="$result"
130
131         #echo "line: $line_num, root: $root, indent level: $level"
132         result="$(sed -e "1,${line_num}d;" <<< "$tree" \
133                 | sed -e "/^$TAB\{1,$level\}$_gsu_node_name_pattern/,\$d" \
134                 | sed -e "/^$TAB\{$((level + 2))\}/d")"
135         if (($? != 0)); then
136                 ret=-$E_GSU_MENU_TREE
137                 result="sed command for subtree $root failed"
138                 return
139         fi
140         ret=$GSU_SUCCESS
141 }
142
143 _get_root_nodes()
144 {
145         local tree="$1" TAB='   '
146
147         result="$(grep "^${TAB}${_gsu_node_name_pattern}" <<< "$tree")"
148         if (($? != 0)); then
149                 ret=-$E_GSU_MENU_TREE
150                 result="root node grep failed"
151                 return
152         fi
153         ret=$GSU_SUCCESS
154 }
155
156 _browse()
157 {
158         local root_item=$1 tree=$2 subtree=$3
159         local -a items arr
160         local -A ids
161         local old_root dflt_item
162         local item id OIFS
163         local -i i=0
164
165         while read -a arr; do
166                 ((${#arr[@]} == 0)) && continue
167                 id=${arr[0]}
168                 if ((${#arr[@]} > 1)); then
169                         unset arr[0];
170                         item=${arr[*]}
171                         if [[ "${id:$((${#id} - 1)):1}" == '/' ]]; then
172                                 item+=/
173                         else
174                                 item="• $item"
175                         fi
176                 else
177                         item=$id
178                 fi
179                 items[$i]=$item
180                 ids["$item"]=$id
181                 let i++
182         done <<< "$subtree"
183         dflt_item=${items[0]}
184         while :; do
185                 _gsu_menu "$root_item" "$dflt_item" "${items[@]}"
186                 ((ret < 0)) && return
187                 [[ -z "$result" ]] && return # menu was cancelled
188                 dflt_item=$result
189                 id=${ids["$result"]}
190                 if [[ "${id:$((${#id} - 1)):1}" == '/' ]]; then
191                         _get_subtree "$tree" "$id"
192                         ((ret < 0)) && return
193                         _browse "${dflt_item%/}" "$tree" "$result"
194                         ((ret < 0)) && return
195                         continue
196                 fi
197                 eval ${gsu_name}_${id}
198         done
199 }
200
201 gsu_gui()
202 {
203         local tree="$1" subtree
204
205         type -t dialog &> /dev/null
206         if (($? != 0)); then
207                 gsu_msg "dialog executable not found"
208                 exit 1
209         fi
210         _get_root_nodes "$tree"
211         subtree="$result"
212         _browse 'Main menu' "$tree" "$subtree"
213 }