From: <car...@us...> - 2012-04-23 18:15:04
|
Revision: 10314 http://octave.svn.sourceforge.net/octave/?rev=10314&view=rev Author: carandraug Date: 2012-04-23 17:37:57 +0000 (Mon, 23 Apr 2012) Log Message: ----------- zenity: big changes, using inputParser class from general to parse options Modified Paths: -------------- trunk/octave-forge/main/zenity/DESCRIPTION trunk/octave-forge/main/zenity/inst/private/zenity_options.m trunk/octave-forge/main/zenity/inst/zenity_calendar.m trunk/octave-forge/main/zenity/inst/zenity_entry.m trunk/octave-forge/main/zenity/inst/zenity_file_selection.m trunk/octave-forge/main/zenity/inst/zenity_list.m trunk/octave-forge/main/zenity/inst/zenity_message.m trunk/octave-forge/main/zenity/inst/zenity_notification.m trunk/octave-forge/main/zenity/inst/zenity_progress.m Added Paths: ----------- trunk/octave-forge/main/zenity/NEWS Modified: trunk/octave-forge/main/zenity/DESCRIPTION =================================================================== --- trunk/octave-forge/main/zenity/DESCRIPTION 2012-04-23 15:59:35 UTC (rev 10313) +++ trunk/octave-forge/main/zenity/DESCRIPTION 2012-04-23 17:37:57 UTC (rev 10314) @@ -9,6 +9,8 @@ calendar windows, text entries, file selection dialogs, lists, message windows, icons in the notification area, and windows for large amount of text. +Autoload: no +Depends: general (>= 1.3.0) +SystemRequirements: zenity (>= 2.16) License: GPLv3+ -SystemRequirements: zenity (>= 2.16) Url: http://octave.sf.net Added: trunk/octave-forge/main/zenity/NEWS =================================================================== --- trunk/octave-forge/main/zenity/NEWS (rev 0) +++ trunk/octave-forge/main/zenity/NEWS 2012-04-23 17:37:57 UTC (rev 10314) @@ -0,0 +1,9 @@ +Summary of important user-visible changes for zenity 1.0.0: +------------------------------------------------------------------- + + ** IMPORTANT NOTE: all functions have a completely new API incompatible + with the previous releases + + ** Check individual functions for many news options + + ** package is now dependent on general (>= 1.3.0) Modified: trunk/octave-forge/main/zenity/inst/private/zenity_options.m =================================================================== --- trunk/octave-forge/main/zenity/inst/private/zenity_options.m 2012-04-23 15:59:35 UTC (rev 10313) +++ trunk/octave-forge/main/zenity/inst/private/zenity_options.m 2012-04-23 17:37:57 UTC (rev 10314) @@ -1,4 +1,4 @@ -## Copyright (C) 2010 Carnë Draug <car...@gm...> +## Copyright (C) 2010, 2012 Carnë Draug <car...@gm...> ## ## 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 @@ -14,7 +14,7 @@ ## this program; if not, see <http://www.gnu.org/licenses/>. ## -*- texinfo -*- -## @deftypefn {Function File} {@var{options} =} zenity_options (@var{dialog}, @var{param1}, @var{value1}, @dots{}) +## @deftypefn {Function File} @var{options} = zenity_options (@var{dialog}, @var{param1}, @var{value1}, @dots{}) ## This function is not intended for users but for the other functions of the ## zenity package. Returns the structure @var{options} that holds the processed ## @var{param} and @var{value} for the function of the zenity package @@ -44,46 +44,92 @@ varargin = varargin{1}; # because other functions varargin is this varargin - ## Create empty variables in case user does not set them - op.title = op.width = op.height = op.timeout = op.icon = ""; - if ( !ischar(dialog) ) + p = inputParser; + + is_single_number = @(x) isscalar (x) && isnumeric (x); + + ## despite that we are setting defaults with inputParser we don't actually + ## want them. If they are not set, we want to use the user's zenity default + ## to be used. As such, we simply set something valid and will discard them + ## if after parsing, they show up on p.UsingDefaults + + ## add general options to all zenity dialogs + p = p.addParamValue ("height", 1, is_single_number); + p = p.addParamValue ("icon", "", @ischar); + p = p.addParamValue ("timeout", 1, is_single_number); + p = p.addParamValue ("title", "", @ischar); + p = p.addParamValue ("width", 1, is_single_number); + + if (!ischar (dialog)) error ("Type of dialog should be a string"); - elseif (strcmpi(dialog, "calendar")) - op.text = op.day = op.month = op.year = ""; - elseif (strcmpi(dialog, "entry")) - op.password = op.entry = ""; - elseif (strcmpi(dialog, "file selection")) - op.directory = op.filename = op.filter = op.multiple = op.save = ""; - elseif (strcmpi(dialog, "list")) - op.separator = op.text = op.hide = op.print_col = op.no_head = ""; - op.multiple = op.radio = op.check = op.editable = ""; - op.hide_max = op.hide_min = op.print_max = op.print_min = ""; - op.print_numel = op.num_out = ""; - elseif (strcmpi(dialog, "message")) - op.type = op.wrap = op.ok = op.cancel = ""; - elseif (strcmpi(dialog, "new notification")) - op.text = ""; - elseif (strcmpi(dialog, "piped notification")) - op.text = op.message = op.visible = ""; - elseif (strcmpi(dialog, "new progress")) - op.percent = op.text = op.auto_close = ""; - op.pulsate = op.auto_kill = op.hide_cancel = ""; - elseif (strcmpi(dialog, "piped progress")) - op.percent = op.text = ""; - elseif (strcmpi(dialog, "new scale")) + elseif (strcmpi (dialog, "calendar")) + p = p.addParamValue ("day", 1, is_single_number); # zenity still works when dates + p = p.addParamValue ("month", 1, is_single_number); # are invalid (day 35 of month 13) + p = p.addParamValue ("text", "", @ischar); + p = p.addParamValue ("year", 1, is_single_number); # we should do the same + + elseif (strcmpi (dialog, "entry")) + p = p.addParamValue ("entry", "", @ischar); + p = p.addSwitch ("password"); + + elseif (strcmpi (dialog, "file selection")) + p = p.addSwitch ("directory"); + p = p.addParamValue ("filename", "", @ischar); + ## TODO add support for multiple filters (might need changes to @inputParser) + p = p.addParamValue ("filter", "", @ischar); + p = p.addSwitch ("multiple"); + p = p.addSwitch ("overwrite"); + p = p.addSwitch ("save"); + + elseif (strcmpi (dialog, "list")) + p = p.addSwitch ("checklist"); + p = p.addSwitch ("editable"); + p = p.addParamValue ("hide_column", 1, @(x) isnumeric (x) && isreal (x) && x > 0); + p = p.addSwitch ("multiple"); + p = p.addSwitch ("no_headers"); + p = p.addParamValue ("numeric_output", "error", @(x) ischar (x) && any (strcmpi (x, {"error", "NaN"}))); + p = p.addParamValue ("print_column", 1, @(x) isnumeric (x) && isreal (x) && x >= 0); + p = p.addSwitch ("radiolist"); + p = p.addParamValue ("text", "", @ischar); + + elseif (strcmpi (dialog, "message")) + p = p.addParamValue ("cancel", "", @ischar); + p = p.addSwitch ("no_wrap"); + p = p.addParamValue ("ok", "", @ischar); + p = p.addParamValue ("type", "error", @(x) ischar (x) && any (strcmpi (x, {"error", "info", "question", "warning"}))); + + elseif (strcmpi (dialog, "new notification")) + p = p.addParamValue ("text", "", @ischar); + + elseif (strcmpi (dialog, "piped notification")) + p = p.addParamValue ("text", "", @ischar); + p = p.addParamValue ("message", "", @ischar); + p = p.addParamValue ("visible", "on", @(x) ischar (x) && any (strcmpi (x, {"off", "on"}))); + + elseif (strcmpi (dialog, "new progress")) + p = p.addSwitch ("auto_close"); + p = p.addSwitch ("auto_kill"); + p = p.addSwitch ("hide_cancel"); + p = p.addParamValue ("percentage", 1, @(x) is_single_number (x) && x >= 0 && x <= 100); + p = p.addSwitch ("pulsate"); + p = p.addParamValue ("text", "", @ischar); + + elseif (strcmpi (dialog, "piped progress")) + p = p.addParamValue ("text", "", @ischar); + p = p.addParamValue ("percentage", 1, @(x) is_single_number (x) && x >= 0 && x <= 100); + + elseif (strcmpi (dialog, "new scale")) op.text = op.ini = op.start = ""; op.hide = op.end = op.step = ""; - elseif (strcmpi(dialog, "piped scale")) - elseif (strcmpi(dialog, "text info")) + elseif (strcmpi (dialog, "piped scale")) + elseif (strcmpi (dialog, "text info")) else error ("The type of dialog '%s' is not supported", dialog); endif - ## In case no options were set, stop here and return the empty strings - if (numel(varargin) == 1 && isempty(varargin{1})) - return - endif - + p = p.parse(varargin{:}); + op = p.Results; + key = fieldnames (op); ## Identifies when it's being called to process stuff to send through pipes ## since that will have major differences in the processing if ( any (strcmpi(dialog, {"piped notification", "piped progress", "piped scale"})) ) @@ -92,384 +138,136 @@ pipelining = 0; endif - ## Here's the guidelines for the processing: - ## - the parameteres and values are case insensitive - ## - if a parameter is being defined twice, return an error - ## - if a parameter requires a value but this is not given, return an error - ## - check if the rigth type of value is given (char or scalar) and return an - ## error if not - - ## This will hold the index of varargin that's currently being processed - narg = 1; - - ## This will ONLY process the input when the output WON'T be sent through a - ## pipe. See the next while block for when it is - while (narg <= numel (varargin)) + for ii = 1: numel (key) if (pipelining) - break # Move to the next while to process the input + break # Move to the next loop to process the input + elseif (any (strcmp (key{ii}, p.UsingDefaults))) + op = setfield (op, key{ii}, ""); + continue endif - param = varargin{narg++}; - - if (narg <= numel(varargin)) # Check if we are already in the last index - value = varargin{narg}; # this is only for readability later on. - else # Writing varargin{narg} in all conditions - value = ""; # is a pain and makes it even more confusing - endif - - if ( !ischar(param) ) - error ("All parameters must be strings."); - - ## Process ALL GENERAL OPTIONS first - elseif (strcmpi(param,"title")) # General - title - narg = sanity_checks ("char", param, value, op.title, narg); - op.title = sprintf('--title="%s"', value); - elseif (strcmpi(param,"width")) # General - width - narg = sanity_checks ("scalar", param, value, op.width, narg); - op.width = sprintf('--width="%i"', value); - elseif (strcmpi(param,"height")) # General - height - narg = sanity_checks ("scalar", param, value, op.height, narg); - op.height = sprintf('--height="%i"', value); - elseif (strcmpi(param,"timeout")) # General - timeout - narg = sanity_checks ("scalar", param, value, op.timeout, narg); - op.timeout = sprintf('--timeout="%i"', value); - elseif (strcmpi(param,"icon")) # General - icon - narg = sanity_checks ("char", param, value, op.icon, narg); - if (strcmpi(value, "error")) - op.icon = '--window-icon="error"'; - elseif (strcmpi(value, "info")) - op.icon = '--window-icon="info"'; - elseif (strcmpi(value, "question")) - op.icon = '--window-icon="question"'; - elseif (strcmpi(value, "warning")) - op.icon = '--window-icon="warning"'; - else - op.icon = sprintf('--window-icon="%s"', value); - endif - - ## Process options for ZENITY_ENTRY - elseif ( strcmpi(dialog, "entry") ) - if (strcmpi(param,"entry")) # Entry - entry text - narg = sanity_checks ("char", param, value, op.entry, narg); - op.entry = sprintf('--entry-text="%s"', value); - elseif (strcmpi(param,"password")) # Entry - password - narg = sanity_checks ("indie", param, value, op.password, narg); - op.password = "--hide-text"; - else - error ("Parameter '%s' is not supported for '%s' dialog.", param, dialog); - endif - - ## Process options for ZENITY_FILE_SELECTION - elseif ( strcmpi(dialog, "file selection") ) - if (strcmpi(param,"directory")) # File selection - directory - narg = sanity_checks ("indie", param, value, op.directory, narg); - op.directory = "--directory"; - elseif (strcmpi(param,"filename")) # File selection - filename - narg = sanity_checks ("char", param, value, op.filename, narg); - op.filename = sprintf('--filename="%s"', value); - elseif (strcmpi(param,"filter")) # File selection - file filter - narg = sanity_checks ("multiple-char", param, value, op.directory, narg); - op.filter = sprintf('%s --file-filter="%s"', op.filter, value); - elseif (strcmpi(param,"multiple")) # File selection - multiple - narg = sanity_checks ("indie", param, value, op.multiple, narg); - op.multiple = "--multiple"; - elseif (strcmpi(param,"overwrite")) # File selection - overwrite - narg = sanity_checks ("indie", param, value, op.overwrite, narg); - op.overwrite = "--confirm-overwrite"; - elseif (strcmpi(param,"save")) # File selection - save - narg = sanity_checks ("indie", param, value, op.save, narg); - op.save = "--save"; - else - error ("Parameter '%s' is not supported for '%s' dialog.", param, dialog); - endif - - ## Process options for ZENITY_MESSAGE - elseif ( strcmpi(dialog, "message") ) - if (strcmpi(param,"type")) # Message - type - narg = sanity_checks ("valueless", param, value, op.type, narg); - if (strcmpi(value,"error")) - op.type = "--error"; - elseif (strcmpi(value,"info")) - op.type = "--info"; - elseif (strcmpi(value,"question")) - op.type = "--question"; - elseif (strcmpi(value,"warning")) - op.type = "--warning"; - else - error ("Non supported type of message dialog '%s'", value); - endif - elseif (strcmpi(param,"wrap")) # Message - wrap - narg = sanity_checks ("indie", param, value, op.wrap, narg); - op.wrap = "--no-wrap"; - elseif (strcmpi(param,"ok button")) # Message - OK button - narg = sanity_checks ("char", param, value, op.ok, narg); - op.ok = sprintf('--ok-label="%s"', value); - elseif (strcmpi(param,"cancel button")) # Message - cancel button - narg = sanity_checks ("char", param, value, op.cancel, narg); - op.cancel = sprintf('--cancel-label="%s"', value); - else - error ("Parameter '%s' is not supported for '%s' dialog.", param, dialog); - endif - - ## Process options for ZENITY_NOTIFICATION (creating new) - elseif ( strcmpi(dialog, "new notification") ) - if (strcmpi(param,"text")) # Notification - text - narg = sanity_checks ("char", param, value, op.text, narg); - op.text = sprintf('--text="%s"', value); - else - error ("Parameter '%s' is not supported for '%s' dialog.", param, dialog); - endif - - ## Process options for ZENITY_LIST - elseif ( strcmpi(dialog, "list") ) - if (strcmpi(param,"text")) # List - text - narg = sanity_checks ("char", param, value, op.text, narg); - op.text = sprintf('--text="%s"', value); - elseif (strcmpi(param,"no headers")) # List - no headers - narg = sanity_checks ("indie", param, value, op.no_head, narg); - op.no_head = "--hide-header"; - elseif (strcmpi(param,"editable")) # List - editable - narg = sanity_checks ("indie", param, value, op.editable, narg); - op.editable = "--editable"; - elseif (strcmpi(param,"multiple")) # List - multiple - narg = sanity_checks ("indie", param, value, op.multiple, narg); - op.multiple = "--multiple"; - elseif (strcmpi(param,"radiolist")) # List - radiolist - narg = sanity_checks ("indie", param, value, op.radio, narg); - op.radio = "--radiolist"; - elseif (strcmpi(param,"checklist")) # List - checklist - narg = sanity_checks ("indie", param, value, op.check, narg); - op.check = "--checklist"; - elseif (strcmpi(param,"numeric output")) # List - numeric output - narg = sanity_checks ("char", param, value, op.num_out, narg); - op.num_out = value; - elseif (strcmpi(param,"hide column")) # List - hide column - narg = sanity_checks ("num", param, value, op.hide, narg); - op.hide_min = min(value(:)); - op.hide_max = max(value(:)); + switch key{ii} + case {"auto_close"} op.auto_close = "--auto-close"; + case {"auto_kill"} op.auto_kill = "--auto-kill"; + case {"cancel"} op.cancel = sprintf('--cancel-label="%s"', op.(key{ii})); + case {"checklist"} op.checklist = "--checklist"; + case {"day"} op.day = sprintf('--day="%d"', round(op.(key{ii}))); + case {"directory"} op.directory = "--directory"; + case {"editable"} op.editable = "--editable"; + case {"entry"} op.entry = sprintf('--entry-text="%s"', op.(key{ii})); + case {"filename"} op.filename = sprintf('--filename="%s"', op.(key{ii})); + ## TODO add support for multiple filters (might need changes to @inputParser) + case {"filter"} op.filter = sprintf('--file-filter="%s"', op.(key{ii})); + case {"hide_cancel"} op.hide_cancel = "--no-cancel"; + case {"hide_column"} + op.hide_min = min(op.(key{ii})(:)); + op.hide_max = max(op.(key{ii})(:)); tmp = ""; - for i = 1:numel(value) - str = num2str(value(i)); + for i = 1:numel(op.(key{ii})) + str = num2str(op.(key{ii})(i)); tmp = sprintf('%s%s,', tmp, str); endfor - op.hide = sprintf('--hide-column="%s"', tmp); - elseif (strcmpi(param,"print column")) # List - print column - narg = sanity_checks ("num", param, value, op.print_col, narg); - op.print_min = min(value(:)); - op.print_max = max(value(:)); - op.print_numel = numel(value); + op.hide_column = sprintf('--hide-column="%s"', tmp); + case {"height"} op.height = sprintf('--height="%i"', round(op.(key{ii}))); + case {"icon"} + switch tolower (op.(key{ii})) + case {"error"} + op.icon = '--window-icon="error"'; + case {"info"} + op.icon = '--window-icon="info"'; + case {"question"} + op.icon = '--window-icon="question"'; + case {"warning"} + op.icon = '--window-icon="warning"'; + otherwise + op.icon = sprintf('--window-icon="%s"', op.(key{ii})); + endswitch + case {"month"} op.month = sprintf('--month="%d"', round(op.(key{ii}))); + case {"multiple"} op.multiple = "--multiple"; + case {"no_headers"} op.no_headers = "--hide-header"; + case {"no_wrap"} op.no_wrap = "--no-wrap"; + case {"numeric_output"} op.numeric_output = op.(key{ii}); + case {"ok"} op.ok = sprintf('--ok-label="%s"', op.(key{ii})); + case {"overwrite"} op.overwrite = "--confirm-overwrite"; + case {"password"} op.password = "--hide-text"; + case {"print_column"} + op.print_min = min(op.(key{ii})(:)); + op.print_max = max(op.(key{ii})(:)); + op.print_numel = numel(op.(key{ii})); tmp = ""; - for i = 1:numel(value) - if (value == 0) + for i = 1:numel(op.(key{ii})) + if (op.(key{ii}) == 0) tmp = "all" break endif - str = num2str(value(i)); + str = num2str(op.(key{ii})(i)); tmp = sprintf('%s%s,', tmp, str); endfor - op.print_col = sprintf('--print-column="%s"', tmp); - else - error ("Parameter '%s' is not supported for '%s' dialog.", param, dialog); - endif + op.print_column = sprintf('--print-column="%s"', tmp); + case {"pulsate"} op.pulsate = "--pulsate"; + case {"percentage"} op.percentage = sprintf('--percentage="%i"', floor(op.(key{ii}))); + case {"radiolist"} op.radiolist = "--radiolist"; + case {"save"} op.save = "--save"; + case {"text"} op.text = sprintf('--text="%s"', op.(key{ii})); + case {"timeout"} op.timeout = sprintf('--timeout="%i"', round(op.(key{ii}))); + case {"title"} op.title = sprintf('--title="%s"', op.(key{ii})); + case {"type"} + switch tolower (op.(key{ii})) + case {"error"} + op.type = "--error"; + case {"info"} + op.type = "--info"; + case {"question"} + op.type = "--question"; + case {"warning"} + op.type = "--warning"; + endswitch + case {"width"} op.width = sprintf('--width="%i"', round(op.(key{ii}))); + case {"year"} op.year = sprintf('--year="%d"', round(op.(key{ii}))); + otherwise + error ("Something unexpected happened when parsing options. Invalid value %s", key{ii}); + endswitch + endfor - ## Process options for ZENITY_PROGRESS (creating new) - elseif ( strcmpi(dialog, "new progress") ) - if (strcmpi(param,"text")) # Progress - text - narg = sanity_checks ("char", param, value, op.text, narg); - op.text = sprintf('--text="%s"', value); - elseif (strcmpi(param,"auto close")) # Progress - auto close - narg = sanity_checks ("indie", param, value, op.auto_close, narg); - op.auto_close = "--auto-close"; - elseif (strcmpi(param,"auto kill")) # Progress - auto close - narg = sanity_checks ("indie", param, value, op.auto_kill, narg); - op.auto_kill = "--auto-kill"; - elseif (strcmpi(param,"hide cancel")) # Progress - hide cancel - narg = sanity_checks ("indie", param, value, op.hide_cancel, narg); - op.hide_cancel = "--no-cancel"; - elseif (strcmpi(param,"pulsate")) # Progress - pulsate - narg = sanity_checks ("indie", param, value, op.pulsate, narg); - op.pulsate = "--pulsate"; - elseif (strcmpi(param,"percentage")) # Progress - percentage - narg = sanity_checks ("scalar", param, value, op.percent, narg); - if (value < 0 || value > 100) - error("Percentage must be between '0' and '100' but it was set to '%g'", value) - endif - ## floor must be used to round, so to avoid returning 100, which in the - ## the case of having auto-close set, would close the dialog too soon - op.percent = sprintf('--percentage="%i"', floor(value)); - else - error ("Parameter '%s' is not supported for '%s' dialog.", param, dialog); - endif - - ## Process options for ZENITY_CALENDAR - elseif ( strcmpi(dialog, "calendar") ) - if (strcmpi(param,"text")) # Calendar - text - narg = sanity_checks ("char", param, value, op.text, narg); - op.text = sprintf('--text="%s"', value); - elseif (strcmpi(param,"day")) # Calendar - day - narg = sanity_checks ("scalar", param, value, op.day, narg); - value = round (value); - if (value < 1 || value > 31) error("Default selection '%d' for day", value); endif - op.day = sprintf('--day="%d"', value); - elseif (strcmpi(param,"month")) # Calendar - month - narg = sanity_checks ("scalar", param, value, op.month, narg); - value = round (value); - if (value < 1 || value > 12) error("Invalid default selection '%d' for month", value); endif - op.month = sprintf('--month="%d"', value); - elseif (strcmpi(param,"year")) # Calendar - day - narg = sanity_checks ("scalar", param, value, op.year, narg); - value = round (value); - op.year = sprintf('--year="%d"', value); - else - error ("Parameter '%s' is not supported for '%s' dialog.", param, dialog); - endif - - else - error ("Parameter '%s' is not supported.", param); - endif - - endwhile - - - ## This will ONLY process the input when the output WILL be sent through a - ## pipe. See the previous while block when creating new dialogs - while (narg <= numel (varargin)) + for ii = 1: numel (key) if (!pipelining) break # It should have already been processed in the previous while block but it doesn't hurt to check again + elseif (any (strcmp (key{ii}, p.UsingDefaults))) + op = setfield (op, key{ii}, ""); + continue endif - param = varargin{narg++}; + switch key{ii} + case {"icon"} + switch tolower (op.(key{ii})) + case {"error"} + op.icon = 'icon: error'; + case {"info"} + op.icon = 'icon: info'; + case {"question"} + op.icon = 'icon: question'; + case {"warning"} + op.icon = 'icon: warning'; + otherwise + op.icon = sprintf('icon: %s', value); + endswitch + case {"message"} op.message = sprintf('message: %s', op.(key{ii})); + case {"percentage"} op.percentage = sprintf('%i', op.(key{ii})); + case {"text"} + switch dialog + case {"piped notification"} + op.text = sprintf('tooltip: %s', op.(key{ii})); + case {"piped progress"} + op.text = sprintf('# %s', op.(key{ii})); + endswitch + case {"visible"} + switch tolower (op.(key{ii})) + case {"on"} + op.visible = "visible: true"; + case {"off"} + op.visible = "visible: false"; + endswitch + otherwise + error ("Something unexpected happened when parsing options. Invalid value %s", key{ii}); + endswitch + endfor - if (narg <= numel(varargin)) # Check if we are already in the last index - value = varargin{narg}; # this is only for readability later on - else # Writing varargin{narg} in all conditions - value = ""; # is a pain and makes it even more confusing - endif - - ## Process options for ZENITY_NOTIFICATION (pipelining) - if ( strcmpi(dialog, "piped notification") ) - if (strcmpi(param,"text")) # Notification - text - narg = sanity_checks ("char", param, value, op.text, narg); - op.text = sprintf('tooltip: %s', value); - elseif (strcmpi(param,"message")) # Notification - message - narg = sanity_checks ("char", param, value, op.message, narg); - op.message = sprintf('message: %s', value); - elseif (strcmpi(param,"visible")) # Notification - message - narg = sanity_checks ("char", param, value, op.message, narg); - if (strcmpi(value, "on")) - op.visible = "visible: true"; - elseif (strcmpi(value, "off")) - op.visible = "visible: false"; - else - error ("'%s' is not a valid value for the parameter '%s'", value, param) - endif - elseif (strcmpi(param,"icon")) # Notification - icon - narg = sanity_checks ("char", param, value, op.icon, narg); - if (strcmpi(value, "error")) - op.icon = 'icon: error'; - elseif (strcmpi(value, "info")) - op.icon = 'icon: info'; - elseif (strcmpi(value, "question")) - op.icon = 'icon: question'; - elseif (strcmpi(value, "warning")) - op.icon = 'icon: warning'; - else - op.icon = sprintf('icon: %s', value); - endif - else - error ("Parameter '%s' is not supported for '%s' dialog.", param, dialog); - endif - - ## Process options for ZENITY_PROGRESS (pipelining) - elseif ( strcmpi(dialog, "piped progress") ) - if (strcmpi(param,"text")) # Progress - text - narg = sanity_checks ("char", param, value, op.text, narg); - op.text = sprintf('# %s', value); - elseif (strcmpi(param,"percentage")) # Progress - percentage - narg = sanity_checks ("scalar", param, value, op.percent, narg); - if (value < 0 || value > 100) - error("Percentage must be between '0' and '100' but it was set to '%g'", value) - endif - ## floor must be used to round, so to avoid returning 100, which in the - ## the case of having auto-close set, would close the dialog too soon - op.percent = sprintf('%i', floor(value)); - else - error ("Parameter '%s' is not supported for '%s' dialog.", param, dialog); - endif - - else - error ("Parameter '%s' is not supported.", param); - endif - endwhile - - ## Set the DEFAULTS - if (strcmpi(dialog,"message")) # Defaults for message - if ( isempty(op.type) ) - op.type = "--info"; - endif - elseif (strcmpi(dialog,"new notification")) # Defaults for notification - if ( isempty(op.icon) ) - op.icon = '--window-icon="warning"'; - endif - endif - endfunction - -################################################################################ -## Extra functions -################################################################################ -function narg = sanity_checks (type, param, value, previous, narg) - if (strcmpi(type,"char")) # Value must be string - if (previous) - idx = strfind(previous, "="); - error ("Parameter '%s' set twice, with values '%s' and '%g'.", ... - param, previous(idx(1)+2:end-1), value); - elseif ( isempty(value) || !ischar(value) ) - error ("Parameter '%s' requires a string as value.", param); - endif - narg++; - - elseif (strcmpi(type,"scalar")) # Value must be scalar - if (previous) - idx = strfind(previous, "="); - error ("Parameter '%s' set twice, with values '%s' and '%g'.", ... - param, previous(idx(1)+2:end-1), value); - elseif ( isempty(value) || !isscalar(value) ) - error ("Parameter '%s' requires a scalar as value.", param); - endif - narg++; - - elseif (strcmpi(type,"indie")) # Independent parameter - if (previous) - error ("Parameter '%s' set twice.", param); - endif - - elseif (strcmpi(type,"valueless")) # Valueless parameter - if (previous) - error ("Parameter '%s' set twice, with values '%s' and '%s'.", ... - param, previous(3:end), value); - elseif ( isempty(value) || !ischar(value) ) - error ("Parameter '%s' requires a string as value.", param); - endif - narg++; - - elseif (strcmpi(type,"multiple-char")) # Value can be set more than once - if ( isempty(value) || !ischar(value) ) - error ("Parameter '%s' requires a string as value.", param); - endif - narg++; - - elseif (strcmpi(type,"num")) # Value can be set more than once - if (previous) - idx = strfind(previous, "="); - error ("Parameter '%s' set twice, with values '%s' and '%g'.", ... - param, previous(idx(1)+2:end-1), value); - elseif ( isempty(value) || !isnumeric(value) ) - error ("Parameter '%s' requires a numeric as value.", param); - endif - narg++; - - - else - error ("Non supported type for sanity_checks '%s'.", type) - endif - -endfunction Modified: trunk/octave-forge/main/zenity/inst/zenity_calendar.m =================================================================== --- trunk/octave-forge/main/zenity/inst/zenity_calendar.m 2012-04-23 15:59:35 UTC (rev 10313) +++ trunk/octave-forge/main/zenity/inst/zenity_calendar.m 2012-04-23 17:37:57 UTC (rev 10314) @@ -1,5 +1,5 @@ ## Copyright (C) 2006 S\xF8ren Hauberg <so...@ha...> -## Copyright (C) 2010 Carn\xEB Draug <car...@gm...> +## Copyright (C) 2010, 2012 Carn\xEB Draug <car...@gm...> ## ## 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 Modified: trunk/octave-forge/main/zenity/inst/zenity_entry.m =================================================================== --- trunk/octave-forge/main/zenity/inst/zenity_entry.m 2012-04-23 15:59:35 UTC (rev 10313) +++ trunk/octave-forge/main/zenity/inst/zenity_entry.m 2012-04-23 17:37:57 UTC (rev 10314) @@ -1,5 +1,5 @@ ## Copyright (C) 2006 S\xF8ren Hauberg <so...@ha...> -## Copyright (C) 2010 Carn\xEB Draug <car...@gm...> +## Copyright (C) 2010, 2012 Carn\xEB Draug <car...@gm...> ## ## 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 Modified: trunk/octave-forge/main/zenity/inst/zenity_file_selection.m =================================================================== --- trunk/octave-forge/main/zenity/inst/zenity_file_selection.m 2012-04-23 15:59:35 UTC (rev 10313) +++ trunk/octave-forge/main/zenity/inst/zenity_file_selection.m 2012-04-23 17:37:57 UTC (rev 10314) @@ -1,5 +1,5 @@ ## Copyright (C) 2006 S\xF8ren Hauberg <so...@ha...> -## Copyright (C) 2010 Carn\xEB Draug <car...@gm...> +## Copyright (C) 2010, 2012 Carn\xEB Draug <car...@gm...> ## ## 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 @@ -36,17 +36,18 @@ ## Sets the default selected file. Requires a string as value. ## ## @item filter -## Sets a filename filter. Requires a string as value. Multiple filters can be -## set with multiple calls of this parameter, or one filter can be made with -## multiple regexp. Filters can also be named which blocks the user from actualy -## seeing the filter.. The following examples shows how to create two filters, -## two named filters, one filter for two different extensions, and the same -## filter but named: +## Sets a filename filter. Requires a string as value. Only one filter can be set +## but it can have multiple regex. Filters can also be named which blocks the user +## from actually seeing the filter. ## @example -## @code{zenity_file_selection ("filter", "*.txt", "filter", "*.m")} -## @code{zenity_file_selection ("filter", "text files| *.txt", "filter", "octave files| *.m")} -## @code{zenity_file_selection ("filter", "*.tif *.png")} -## @code{zenity_file_selection ("filter", "Images | *.tif *.png")} +## @group +## ## only txt files will be selectable +## zenity_file_selection ("filter", "*.txt") +## ## both txt and m files will be selectable +## zenity_file_selection ("filter", "*.txt *.m") +## ## both txt and m files will be selectable but the users will see `text files' +## zenity_file_selection ("filter", "Text files | *.txt *.m") +## @end group ## @end example ## ## @item icon @@ -87,6 +88,26 @@ ## @seealso{zenity_list, zenity_entry, zenity_message, zenity_text_info} ## @end deftypefn +## TODO +## for some time (but only on the development version, never released version) it +## was possible to set multiple filters filter with this function (see the help text created below). +## This was when using a manual parsing of the options. Once using @inputParser +## this was no longer working. Maybe when inputParser allows for an option to be +## used multiple times... all the code is ready for this, just uncomment some lines +## @item filter +## Sets a filename filter. Requires a string as value. Multiple filters can be +## set with multiple calls of this parameter, or one filter can be made with +## multiple regexp. Filters can also be named which blocks the user from actualy +## seeing the filter.. The following examples shows how to create two filters, +## two named filters, one filter for two different extensions, and the same +## filter but named: +## @example +## @code{zenity_file_selection ("filter", "*.txt", "filter", "*.m")} +## @code{zenity_file_selection ("filter", "text files| *.txt", "filter", "octave files| *.m")} +## @code{zenity_file_selection ("filter", "*.tif *.png")} +## @code{zenity_file_selection ("filter", "Images | *.tif *.png")} +## @end example + function [files, status] = zenity_file_selection(varargin) ## Update figures so they are show before the dialog. To not be shown at this Modified: trunk/octave-forge/main/zenity/inst/zenity_list.m =================================================================== --- trunk/octave-forge/main/zenity/inst/zenity_list.m 2012-04-23 15:59:35 UTC (rev 10313) +++ trunk/octave-forge/main/zenity/inst/zenity_list.m 2012-04-23 17:37:57 UTC (rev 10314) @@ -1,5 +1,5 @@ ## Copyright (C) 2006 S\xF8ren Hauberg <so...@ha...> -## Copyright (C) 2010 Carn\xEB Draug <car...@gm...> +## Copyright (C) 2010, 2012 Carn\xEB Draug <car...@gm...> ## ## 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 @@ -28,10 +28,12 @@ ## @code{Height}, will have the values @code{120cm} and @code{180cm}: ## ## @example +## @group ## columns = @{"Age", "Height"@} -## data = @{"10", "120cm", -## "20"; "180cm"@} +## data = @{"10", "120cm" +## "20", "180cm"@} ## zenity_list(columns, data) +## @end group ## @end example ## ## @var{selected} holds a string with the value of the first column of the @@ -68,13 +70,15 @@ ## with the strings @code{FreeBSD} and @code{Linux}. ## ## @example +## @group ## columns = @{"", "OS"@} -## data = @{"true" , "FreeBSD", -## "true" , "Linux", +## data = @{"true" , "FreeBSD" +## "true" , "Linux" ## "false", "NetBSD" -## "false", "OpenBSD", +## "false", "OpenBSD" ## "false", "OpenSolaris"@} ## zenity_list(columns, data, "checklist") +## @end group ## @end example ## ## @item editable @@ -85,7 +89,7 @@ ## @item height ## Sets the height of the dialog window. Requires a scalar as value. ## -## @item hide column +## @item hide_column ## Hides the specified columns from the user. Requires a numeric data type as ## value. Multiple columns can be selected with ranges or matrixes. If ## @option{radiolist} or @option{checklist} are set, the first @@ -97,15 +101,17 @@ ## not shown and holds the numbers. ## ## @example +## @group ## columns = @{"", "Foods", "not visible"@} ## data = @{"true" , "Ice cream", "1" ## "false", "Danish", "2" ## "false", "Soup", "3" ## "false", "Lasagne", "4"@} -## zenity_list(columns, data, "radiolist", "hide column", 3, "print column", 3) +## zenity_list(columns, data, "radiolist", "hide_column", 3, "print_column", 3) +## @end group ## @end example ## -## @item no headers +## @item no_headers ## Doesn't show the headers. No value is required. @var{columns} still needs to ## be defined and have the right size but may be a cell array of empty ## strings. Since the headers are hidden, the user cannot sort the values of the @@ -126,7 +132,7 @@ ## Allows multiple rows to be selected. No value is required. It cannot be set ## with @option{radiolist} and is automatically set when @option{checklist} is set. ## -## @item numeric output +## @item numeric_output ## Returns @var{selected} as a matrix and numeric values (double precision type) ## instead of cell array of strings. It uses the function str2double for the ## conversion. Requires a string as value. Possible values are: @@ -138,7 +144,7 @@ ## Returns @code{NaN} for the values it is unable to convert. ## @end table ## -## @item print column +## @item print_column ## The numbers of the columns whose values should be returned. Requires a numeric ## data type as value. Multiple columns can be selected with ranges or matrixes, ## and all columns can be selected with the scalar @code{0}. If the @@ -225,54 +231,48 @@ ## Sanity checks ## by using numel(col) instead of columns, allows to not worry on the dimension they are placed if (columns(data) != numel(col)) - error("Size of 'columns' (%g) is different than the number of columns in 'data' (%g).", ... + error("size of 'columns' (%g) is different than the number of columns in 'data' (%g).", ... numel(col), columns(data)) + elseif (!all (cellfun (@ischar, data))) + error ("all elements in 'data' must be strings."); + elseif (!all (cellfun (@ischar, col))) + error ("all elements in 'col' must be strings."); endif - for i = 1:numel(data) - if (!ischar(data{i})) - error ("Index '%g' of the argument 'data' is not a string.", i); - endif - endfor - for i = 1:numel(col) - if (!ischar(col{i})) - error ("Index '%g' of the argument 'columns' is not a string.", i); - endif - endfor - options = zenity_options ("list", varargin); + options = zenity_options ("list", varargin); ## More sanity checks - if ( !isempty(options.check) && !isempty(options.radio) ) + if ( !isempty(options.checklist) && !isempty(options.radiolist) ) error ("Parameter 'checklist' cannot be set together with 'radiolist'.") - elseif( !isempty(options.multiple) && !isempty(options.radio) ) + elseif( !isempty(options.multiple) && !isempty(options.radiolist) ) error ("Parameter 'multiple' cannot be set together with 'radiolist'.") - elseif ( !isempty(options.editable) && !isempty(options.radio) ) + elseif ( !isempty(options.editable) && !isempty(options.radiolist) ) error ("Parameter 'editable' cannot be set together with 'radiolist'.") - elseif ( !isempty(options.editable) && !isempty(options.check) ) + elseif ( !isempty(options.editable) && !isempty(options.checklist) ) error ("Parameter 'editable' cannot be set together with 'checklist'.") - elseif ( options.hide_min == 1 && (!isempty(options.check) || !isempty(options.radio)) ) + elseif ( !isempty(options.hide_column) && options.hide_min == 1 && (!isempty(options.checklist) || !isempty(options.radiolist)) ) error ("'hide column' cannot have a value of 1 when 'checklist' and 'radiolist' are set."); - elseif ( options.print_min == 1 && (!isempty(options.check) || !isempty(options.radio)) ) + elseif ( !isempty(options.print_column) && options.print_min == 1 && (!isempty(options.checklist) || !isempty(options.radiolist)) ) error ("'print column' cannot have a value of 1 when 'checklist' and 'radiolist' are set."); - elseif ( options.print_min == 0 && options.print_numel > 1) + elseif ( !isempty(options.print_column) && options.print_min == 0 && options.print_numel > 1) error ("Value of 0 (all) found as value for parameter 'print column' as part of multiple values. If desired, it must be set as scalar."); - elseif ( options.hide_max > numel(col) ) + elseif ( !isempty(options.hide_column) && options.hide_max > numel(col) ) error ("Value %g found for the parameter 'hide column' and is larger than the number of columns.", options.hide_max) - elseif ( options.print_max > numel(col) ) + elseif ( !isempty(options.print_column) && options.print_max > numel(col) ) error ("Value %g found for the parameter 'print column' and is larger than the number of columns.", options.print_max) - elseif ( options.print_min < 0 ) + elseif ( !isempty(options.print_column) && options.print_min < 0 ) error ("Negative value '%g' found for the parameter 'print column'.", options.print_min) - elseif ( options.hide_min < 1 ) + elseif ( !isempty(options.hide_column) && options.hide_min < 1 ) error ("Parameter 'hide column' cannot have values smaller than 1 (found minimun as '%g').", options.hide_min) endif - if ( !isempty(options.check) ) + if ( !isempty(options.checklist) ) for i = 1:rows(data) if ( !strcmpi(data{i,1},"true") && !strcmpi(data{i,1},"false") ) error ("All cells on the first column of 'data' must be either 'true' or 'false' when 'radiolist' or 'checklist' are set."); endif endfor - elseif (!isempty(options.radio) ) + elseif (!isempty(options.radiolist) ) seen_true = 0; for i = 1:rows(data) if ( !strcmpi(data{i,1},"true") && !strcmpi(data{i,1},"false") ) @@ -304,15 +304,15 @@ options.timeout, ... options.separator, ... options.text, ... - options.hide, ... - options.print_col, ... + options.hide_column, ... + options.print_column, ... options.multiple, ... - options.radio, ... - options.check, ... + options.radiolist, ... + options.checklist, ... options.editable, ... options.icon, ... options.col, ... - options.no_head, ... + options.no_headers, ... options.data); cmd = sprintf ("zenity --list %s", pre_cmd); @@ -325,18 +325,18 @@ # Exit code 5 = The dialog has been closed because the timeout has been reached # If it would be possible for the function to return more than one value - if ( !isempty(options.check) || !isempty(options.multiple) || options.print_numel > 1) + if ( !isempty(options.checklist) || !isempty(options.multiple) || (!isempty(options.print_column) && options.print_numel > 1)) multi = 1; else multi = 0; endif # Calculate the number of expected columns - if ( options.print_min == 0 && (options.check || options.radio) ) + if ( !isempty(options.print_column) && options.print_min == 0 && (options.checklist || options.radiolist) ) expec_col = numel(col) -1; - elseif (options.print_min == 0) + elseif (!isempty(options.print_column) && options.print_min == 0) expec_col = numel(col); - elseif (options.print_min != 0) + elseif (!isempty(options.print_column) && options.print_min != 0) expec_col = options.print_numel; else expec_col = 1; @@ -394,13 +394,13 @@ ## cell array gives an error on str2double. However, in the future (gnome ## bug #651948) this may be changed. When it does, the condition should accept ## status == 5 AND check if the cell array is not completely empty - if (status == 0 && options.num_out) + if (status == 0 && options.numeric_output) val = str2double(val); - if (strcmpi(options.num_out, "error")) + if (strcmpi(options.numeric_output, "error")) if ( any(isnan( val(:) )) ) error("Conversion of output to numeric form was unsucessful") endif - elseif (strcmpi(options.num_out, "nan")) + elseif (strcmpi(options.numeric_output, "nan")) ## Do nothing else error("Unknow value '%s' for the parameter 'numeric output'", option.num_out) Modified: trunk/octave-forge/main/zenity/inst/zenity_message.m =================================================================== --- trunk/octave-forge/main/zenity/inst/zenity_message.m 2012-04-23 15:59:35 UTC (rev 10313) +++ trunk/octave-forge/main/zenity/inst/zenity_message.m 2012-04-23 17:37:57 UTC (rev 10314) @@ -1,5 +1,5 @@ ## Copyright (C) 2006 S\xF8ren Hauberg <so...@ha...> -## Copyright (C) 2010 Carn\xEB Draug <car...@gm...> +## Copyright (C) 2010, 2012 Carn\xEB Draug <car...@gm...> ## ## 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 @@ -54,18 +54,18 @@ ## @item warning ## @end table ## -## @item OK button +## @item ok ## Sets the the text to show on the @option{OK} button if type of message is set ## to @option{question}. Requires a string as value. ## -## @item cancel button +## @item cancel ## Sets the the text to show on the @option{cancel} button if type of message is ## set to @option{question}. Requires a string as value. ## ## @item title ## Sets the title of the window. Requires a string as value. ## -## @item no-wrap +## @item no_wrap ## Disables text wrapping. No value is required. ## ## @item width @@ -102,6 +102,10 @@ options = zenity_options ("message", varargin); + if ( isempty(options.type)) + options.type = "--info"; + endif + ## Sanity checks if ( !strcmpi(options.type, "--question") && (options.ok || options.cancel)) error("Paremeters 'ok button' and 'cancel button' can only bet set in 'question' messages") @@ -110,7 +114,7 @@ pre_cmd = sprintf("%s ", ... options.type, ... text, ... - options.wrap, ... + options.no_wrap, ... options.title, ... options.icon, ... options.width, ... Modified: trunk/octave-forge/main/zenity/inst/zenity_notification.m =================================================================== --- trunk/octave-forge/main/zenity/inst/zenity_notification.m 2012-04-23 15:59:35 UTC (rev 10313) +++ trunk/octave-forge/main/zenity/inst/zenity_notification.m 2012-04-23 17:37:57 UTC (rev 10314) @@ -1,5 +1,5 @@ ## Copyright (C) 2006 S\xF8ren Hauberg <so...@ha...> -## Copyright (C) 2010 Carn\xEB Draug <car...@gm...> +## Copyright (C) 2010, 2012 Carn\xEB Draug <car...@gm...> ## ## 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 @@ -43,10 +43,12 @@ ## notification panel. Trough all the example, the text stays @samp{working}. ## ## @example +## @group ## h = zenity_notification ("text", "working", "icon", "info") ## zenity_notification (h, "message", "step 1 started") ## zenity_notification (h, "message", "error during step 1", "icon", "error") ## zenity_notification (h, "close") +## @end group ## @end example ## ## All @var{parameters} are optional but if given, may require a corresponding @@ -122,7 +124,7 @@ warning ("There's %g argument(s) after '%s' which will be ignored", (nargin-2), varargin{1}) endif try - sta = pclose(handle); + sta = fclose (handle); catch sta = -1; end_try_catch @@ -133,6 +135,10 @@ return endif options = zenity_options ("piped notification", varargin); + if ( isempty(options.icon)) + options.type = "--info"; + endif + ## Must add the new line only if they exist or zenity will complain about ## not being able to parse some of the lines. ## Atention to whitespace after the command. Example: @@ -164,7 +170,7 @@ pre_cmd = sprintf("%s ", ... options.icon, ... options.text, ... - options.timeout); + options.timeout) cmd = sprintf("zenity --notification --listen %s", pre_cmd); try sta = popen(cmd, "w"); Modified: trunk/octave-forge/main/zenity/inst/zenity_progress.m =================================================================== --- trunk/octave-forge/main/zenity/inst/zenity_progress.m 2012-04-23 15:59:35 UTC (rev 10313) +++ trunk/octave-forge/main/zenity/inst/zenity_progress.m 2012-04-23 17:37:57 UTC (rev 10314) @@ -1,5 +1,5 @@ ## Copyright (C) 2006 S\xF8ren Hauberg <so...@ha...> -## Copyright (C) 2010 Carn\xEB Draug <car...@gm...> +## Copyright (C) 2010, 2012 Carn\xEB Draug <car...@gm...> ## ## 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 @@ -35,14 +35,14 @@ ## @item text ## Sets the text of the dialog window. Requires a string as value. ## -## @item auto close +## @item auto_close ## When the bar reachs @code{100}, automatically closes the dialog window. Requires no value. ## -## @item auto kill +## @item auto_kill ## If the @option{cancel} button is pressed, it will kill the parent process ## (@abbr{i.e.} the program that is calling the function). Requires no value. ## -## @item hide cancel +## @item hide_cancel ## Hides the @option{cancel} button from the dialog window (the user can still ## close the window with its functions). Requires no value. ## @@ -84,7 +84,7 @@ ## The fourth form of the @command{zenity_progress} function finishes the progress ## bar, given the handle @var{h} followed by the string @code{close}. This will ## move the progress bar to the end and wait for the user to press -## @option{OK}. To avoid this behaviour, @option{auto close} can be set when +## @option{OK}. To avoid this behaviour, @option{auto_close} can be set when ## creating the progress bar. Returns @code{0} on success and @code{-1} on error. ## ## @strong{Note:} ultimately, the availability of some parameters is dependent @@ -130,12 +130,12 @@ ## " #test text" <-- no error, but does nothing ## "#test text" <-- changes text for 'test text ## "# test text" <-- exactly the same as above - options.text = add_newline (options.text); - options.percent = add_newline (options.percent); + options.text = add_newline (options.text); + options.percentage = add_newline (options.percentage); pre_cmd = sprintf("%s", ... options.text, ... - options.percent); + options.percentage); try ## just in case someone has been playing with the pipe, flush it before fflush (handle); @@ -154,7 +154,7 @@ options.timeout, ... options.icon, ... options.text, ... - options.percent, ... + options.percentage, ... options.auto_close, ... options.pulsate, ... options.auto_kill,... This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |