diff options
Diffstat (limited to 'apol/range_selector.tcl')
-rw-r--r-- | apol/range_selector.tcl | 156 |
1 files changed, 156 insertions, 0 deletions
diff --git a/apol/range_selector.tcl b/apol/range_selector.tcl new file mode 100644 index 0000000..8234394 --- /dev/null +++ b/apol/range_selector.tcl @@ -0,0 +1,156 @@ +# Copyright (C) 2001-2007 Tresys Technology, LLC +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +namespace eval Apol_Widget { + variable vars +} + +# Creates a widget that lets the user select an MLS range and a range +# search type (exact, subset, superset). If the second argument is +# not "" then add a checkbutton that enables/disables the entire +# widget. +proc Apol_Widget::makeRangeSelector {path rangeMatchText {enableText "MLS range"} args} { + variable vars + array unset vars $path:* + set vars($path:range) {} + set vars($path:range_rendered) {} + set vars($path:search_type) $::APOL_QUERY_EXACT + + set f [frame $path] + set range_frame [frame $f.range] + set range2_frame [frame $f.range2] + pack $range_frame $range2_frame -side left -expand 0 -anchor nw + + if {$enableText != {}} { + set vars($path:enable) 0 + set range_cb [checkbutton $range_frame.enable -text $enableText \ + -variable Apol_Widget::vars($path:enable)] + pack $range_cb -side top -expand 0 -anchor nw + trace add variable Apol_Widget::vars($path:enable) write [list Apol_Widget::_toggle_range_selector $path $range_cb] + } + set range_display [eval Entry $range_frame.display -textvariable Apol_Widget::vars($path:range_rendered) -width 20 -editable 0 $args] + set range_button [button $range_frame.button -text "Select Range..." -state disabled -command [list Apol_Widget::_show_mls_range_dialog $path]] + trace add variable Apol_Widget::vars($path:range) write [list Apol_Widget::_update_range_display $path] + pack $range_display -side top -expand 1 -fill x -anchor nw + pack $range_button -side top -expand 0 -anchor ne + if {$enableText != {}} { + pack configure $range_display -padx 4 + pack configure $range_button -padx 4 + } + + # range search type + set range_label [label $range2_frame.label -text "Range matching:" \ + -state disabled] + set range_exact [radiobutton $range2_frame.exact -text "Exact matches" \ + -state disabled \ + -value $::APOL_QUERY_EXACT \ + -variable Apol_Widget::vars($path:search_type)] + set range_subset [radiobutton $range2_frame.subset -text "$rangeMatchText containing range" \ + -state disabled \ + -value $::APOL_QUERY_SUB \ + -variable Apol_Widget::vars($path:search_type)] + set range_superset [radiobutton $range2_frame.superset -text "$rangeMatchText within range" \ + -state disabled \ + -value $::APOL_QUERY_SUPER \ + -variable Apol_Widget::vars($path:search_type)] + pack $range_label $range_exact $range_subset $range_superset \ + -side top -expand 0 -anchor nw + + return $f +} + +proc Apol_Widget::setRangeSelectorState {path newState} { + if {$newState == 0 || $newState == "disabled"} { + set new_state disabled + } else { + set new_state normal + } + foreach w {display button} { + $path.range.$w configure -state $new_state + } + foreach w {label exact subset superset} { + $path.range2.$w configure -state $new_state + } +} + +proc Apol_Widget::setRangeSelectorCompleteState {path newState} { + if {$newState == 0 || $newState == "disabled"} { + set new_state disabled + } else { + set new_state normal + } + catch {$path.range.enable configure -state $new_state} +} + +proc Apol_Widget::clearRangeSelector {path} { + set Apol_Widget::vars($path:range) {} + set Apol_Widget::vars($path:search_type) $::APOL_QUERY_EXACT + catch {set Apol_Widget::vars($path:enable) 0} +} + +proc Apol_Widget::getRangeSelectorState {path} { + return $Apol_Widget::vars($path:enable) +} + +# Return a 2-uple containing the range value (an instance of an +# apol_mls_range_t) and the search type (one of APOL_QUERY_EXACT, +# APOL_QUERY_SUB, or APOL_QUERY_SUPER). Caller must delete the range +# afterwards. Note that the range could be an empty string if none is +# set. +proc Apol_Widget::getRangeSelectorValue {path} { + variable vars + if {$vars($path:range) != {}} { + set range [new_apol_mls_range_t $vars($path:range)] + } else { + set range {} + } + list $range $vars($path:search_type) +} + +########## private functions below ########## + +proc Apol_Widget::_toggle_range_selector {path cb name1 name2 op} { + if {$Apol_Widget::vars($path:enable)} { + Apol_Widget::setRangeSelectorState $path normal + } else { + Apol_Widget::setRangeSelectorState $path disabled + } +} + +proc Apol_Widget::_show_mls_range_dialog {path} { + $path.range.button configure -state disabled + set range [Apol_Range_Dialog::getRange $Apol_Widget::vars($path:range)] + if {$range != {}} { + set Apol_Widget::vars($path:range) $range + $range -acquire + } + + $path.range.button configure -state normal + # the trace on this variable will trigger [_update_range_display] + # to execute +} + +proc Apol_Widget::_update_range_display {path name1 name2 op} { + variable vars + set display $path.range.display + if {$vars($path:range) == {}} { + set vars($path:range_rendered) {} + $display configure -helptext {} + } else { + set s [$vars($path:range) render $::ApolTop::policy] + set vars($path:range_rendered) $s + $display configure -helptext $vars($path:range_rendered) + } +} |