# HG changeset patch
# User Adam H Aitkenhead <adamhaitkenhead@gmail.com>
# Date 1369340966 -3600
# Node ID 17fa3e0cc33f1267cf9ee8eee96ec34a4db1f429
# Parent  e9d0b8252a0a031322e1f8b2387b779f90df6bcb
line.m: Enable color cycling, and improve ML compatibility for X and Y of different size (bug #39036)

* line.m: Enable color cycling
* __line__.m: Enable color cycling, and improve ML compatibility for X and Y of different sizes (bug #39036)
* __plt__.m: Now calls __line__.m instead of line.m

diff -r e9d0b8252a0a -r 17fa3e0cc33f scripts/plot/line.m
--- a/scripts/plot/line.m	Tue May 21 20:08:22 2013 +0200
+++ b/scripts/plot/line.m	Thu May 23 21:29:26 2013 +0100
@@ -33,6 +33,13 @@
 
 function h = line (varargin)
 
+  if (isempty (findobj ("type", "axes")))
+    newplot ();
+  else
+    __next_line_color__ (true);
+    __next_line_style__ (true);
+  endif
+
   ## make a default line object, and make it the current axes for
   ## the current figure.
   tmp = __line__ (gca (), varargin{:});
diff -r e9d0b8252a0a -r 17fa3e0cc33f scripts/plot/private/__line__.m
--- a/scripts/plot/private/__line__.m	Tue May 21 20:08:22 2013 +0200
+++ b/scripts/plot/private/__line__.m	Thu May 23 21:29:26 2013 +0100
@@ -1,4 +1,5 @@
 ## Copyright (C) 2005-2012 John W. Eaton
+## Copyright (C) 2013 Adam H Aitkenhead
 ##
 ## This file is part of Octave.
 ##
@@ -34,43 +35,109 @@
   endif
 
   nvargs = numel (varargin);
+ 
+  ## Check the input property-value pairs
+  pxdata = [];
+  pydata = [];
+  pzdata = [];
+  pcolor = [];
+  plinestyle = [];
+  pmarker = [];
+  for i = 1:nvargs-1
+    if (ischar (varargin{i}))
+      if (strcmpi (varargin{i}, "xdata"))
+        pxdata = i;
+        if (! isnumeric (varargin{i+1}))
+          error('line: X must be numeric')
+        endif
+      elseif (strcmpi (varargin{i}, "ydata"))
+        pydata = i;
+        if (! isnumeric (varargin{i+1}))
+          error('line: Y must be numeric')
+        endif
+      elseif (strcmpi (varargin{i}, "zdata"))
+        pzdata = i;
+        if (! isnumeric (varargin{i+1}))
+          error('line: Z must be numeric')
+        endif
+      elseif (strcmpi (varargin{i}, "color"))
+        pcolor = i;
+      elseif strcmpi (varargin{i}, "linestyle")
+        plinestyle = i;
+      elseif strcmpi (varargin{i}, "marker")
+        pmarker = i;
+      endif
+    endif
+  endfor
 
-  if (nvargs > 1 && ! ischar (varargin{1}) && ! ischar (varargin{2}))
-    if (nvargs > 2 && ! ischar (varargin{3}))
-      num_data_args = 3;
+  ## Check the number of data arguments
+  num_data_args = !isempty(pxdata) + !isempty(pydata) + !isempty(pzdata);
+  if num_data_args == 3
+    n = [pxdata, pydata, pzdata] + 1;
+  elseif num_data_args == 2
+    n = [pxdata, pydata] + 1;
+    if ! isempty (pzdata)
+      error('line: X and Y must be provided as inputs for a 2D plot')
+    endif
+  elseif num_data_args == 1
+    error('line: X and Y must be provided as inputs (or X,Y,Z for 3D)')
+  elseif num_data_args == 0
+    if (nvargs > 1 && ! ischar (varargin{1}) && ! ischar (varargin{2}))
+      if (nvargs > 2 && ! ischar (varargin{3}))
+        num_data_args = 3;
+      else
+        num_data_args = 2;
+      endif
     else
-      num_data_args = 2;
+      num_data_args = 0;
     endif
-  else
-    num_data_args = 0;
+    n = 1:num_data_args;
   endif
 
-  if (num_data_args > 0 && ! size_equal (varargin{1:num_data_args}))
-    n = 1:num_data_args;
-    m = cellfun (@numel, varargin(1:num_data_args));
-    [~, m] = max (m);
-    b = ones (size (varargin{m(1)}));
-    try
-      varargin(n) = cellfun (@(x) bsxfun (@times, b, x), varargin(n), "uniformoutput", false);
-    catch
-      error ("line: number of X, Y, and Z points must be equal");
-    end_try_catch
+  ## Rearrange the data as necessary
+  if (num_data_args > 0 && ! size_equal (varargin{n}))
+    szn = zeros (num_data_args,2);
+    for i = 1:num_data_args
+      szn(i,:) = size (varargin{n(i)});
+    endfor
+    szmax = szn(find(sum (szn,2)==max (sum (szn,2)), 1, 'first'), :);
+   
+    ## Check each of X,Y,Z to see if they need to be reoriented
+    for i = 1:num_data_args
+      if ! isequal(szn(i,:),szmax)
+        if isequal(szn(i,end:-1:1),szmax)
+          varargin{n(i)} = varargin{n(i)}';
+        elseif ismember(1,szn(i,:))
+          ## Handle the case where either X or Y is a vector
+          tmp = (szn(i,:)==1);
+          if szn(i,!tmp) != szmax(!tmp)
+            varargin{n(i)} = varargin{n(i)}';
+          endif
+          tmp = find (size (varargin{n(i)})==1);
+          if tmp==1
+            varargin{n(i)} = repmat( varargin{n(i)}, szmax(tmp), 1);
+            for i = 1:num_data_args
+              varargin{n(i)} = varargin{n(i)}';
+            endfor
+          elseif tmp==2
+            varargin{n(i)} = repmat( varargin{n(i)}, 1, szmax(tmp));
+          endif
+        endif
+      endif
+    endfor
   endif
 
-  if (rem (nvargs - num_data_args, 2) != 0)
+  ## Check the number of property/value pairs
+  if (rem (nvargs - num_data_args - !isempty(pxdata) - !isempty(pydata) - !isempty(pzdata), 2) != 0)
     error ("line: invalid number of PROPERTY / VALUE pairs");
   endif
-
-  other_args = {};
-  if (nvargs > num_data_args)
-    other_args = varargin(num_data_args+1:end);
-  endif
-
+  
+  ## Check whether the data describes one or multiple lines
   nlines = 0;
   nvecpts = 0;
   ismat = false (1, 3);
   for i = 1:num_data_args
-    tmp = varargin{i}(:,:);
+    tmp = varargin{n(i)}(:,:);
     if (isvector (tmp))
       nlines = max (1, nlines);
       if (! isscalar (tmp))
@@ -84,21 +151,21 @@
       ismat(i) = true;
       nlines = max (columns (tmp), nlines);
     endif
-    varargin{i} = tmp;
+    varargin{n(i)} = tmp;
   endfor
 
+  ## Set the behaviour when X,Y,Z are not given as inputs (Matlab compatibility)
   if (num_data_args == 0)
     varargin = {[0, 1], [0, 1]};
+    n = 1:2;
     num_data_args = 2;
     nlines = 1;
   endif
 
-  handles = zeros (nlines, 1);
-
+  ## Read the x,y,z data into the cell 'data'
   data = cell (1, 3);
-
   if (num_data_args > 1)
-    data(1:num_data_args) = varargin(1:num_data_args);
+    data(1:num_data_args) = varargin(n);
     for i = 1:num_data_args
       if (islogical (data{i}))
         data(i) = double (data{i});
@@ -108,21 +175,65 @@
     endfor
   endif
 
+  ## Remove the 'XData', 'YData', ZData' property labels
+  xyzlabel = false(numel(varargin),1);
+  for i = 1:numel(varargin)
+    if ischar(varargin{i})
+      if strcmpi(varargin{i},'XData') || strcmpi(varargin{i},'YData') || strcmpi(varargin{i},'ZData')
+        xyzlabel(i) = true;
+      endif
+    endif
+  endfor
+  varargin = varargin(!xyzlabel);
+
   data_args = reshape ({"xdata", "ydata", "zdata"; data{:}}, [1, 6]);
   mask = reshape ([false(1,3); ismat], [1, 6]);
 
+  ## Cycle through the default colors, linestyles and markers if they are not
+  ## defined by a property-value pair
+  options = __default_plot_options__ ();
+  options = repmat (options(:), nlines, 1);
+  if (nvargs > num_data_args)
+    argoptions = varargin(num_data_args+1:end);
+  else
+    argoptions = {};
+  endif
+  other_args = {};
+  for i = 1:nlines
+    other_args{i} = argoptions;
+    if isempty (pcolor)
+      color = options(i).color;
+      if (isempty (color))
+        color = __next_line_color__ ();
+      endif
+      other_args{i}{end+1} = "color";
+      other_args{i}{end+1} = color;
+    endif
+    linestyle = options(i).linestyle;
+    marker = options(i).marker;
+    if (isempty (marker) && isempty (linestyle))
+      [linestyle, marker] = __next_line_style__ ();
+    endif
+    if isempty (plinestyle)
+      other_args{i}{end+1} = "linestyle";
+      other_args{i}{end+1} = linestyle;
+    endif
+    if isempty (pmarker)
+      other_args{i}{end+1} = "marker";
+      other_args{i}{end+1} = marker;
+    endif
+  endfor
+
+  handles = zeros (nlines, 1);
   for i = 1:nlines
     tmp = data(ismat);
     if (! size_equal (tmp)
         || (nvecpts != 0 && any (nvecpts != cellfun ("size", tmp, 1))))
       error ("line: data size_mismatch");
     endif
-
     data_args(mask) = cellfun (@(x) x(:,i), data(ismat),
                                "uniformoutput", false);
-
-    handles(i) = __go_line__ (p, data_args{:}, other_args{:});
-
+    handles(i) = __go_line__ (p, data_args{:}, other_args{i}{:});
   endfor
 
   if (nargout > 0)
diff -r e9d0b8252a0a -r 17fa3e0cc33f scripts/plot/private/__plt__.m
--- a/scripts/plot/private/__plt__.m	Tue May 21 20:08:22 2013 +0200
+++ b/scripts/plot/private/__plt__.m	Thu May 23 21:29:26 2013 +0100
@@ -297,9 +297,9 @@
           color = __next_line_color__ ();
         endif
 
-        retval(i) = line (x(:,i), y(:,i), "color", color,
-                          "linestyle", linestyle,
-                          "marker", marker, properties{:});
+        retval(i) =__line__ (gca (), x(:,i), y(:,i), "color", color,
+                             "linestyle", linestyle,
+                             "marker", marker, properties{:});
       endfor
     else
       error ("__plt2mm__: arguments must be a matrices");
@@ -361,9 +361,9 @@
         color = __next_line_color__ ();
       endif
 
-      retval(i) = line (x(:,i), y, "color", color,
-                        "linestyle", linestyle,
-                        "marker", marker, properties{:});
+      retval(i) =__line__ (gca (), x(:,i), y, "color", color,
+                           "linestyle", linestyle,
+                           "marker", marker, properties{:});
     endfor
   else
     error ("__plt2mv__: arguments must be a matrices");
@@ -403,9 +403,9 @@
       color = __next_line_color__ ();
     endif
 
-    retval = line (x, y, "color", color,
-                   "linestyle", linestyle,
-                   "marker", marker, properties{:});
+    retval =__line__ (gca (), x, y, "color", color,
+                      "linestyle", linestyle,
+                      "marker", marker, properties{:});
   else
     error ("__plt2ss__: arguments must be scalars");
   endif
@@ -443,9 +443,9 @@
         color = __next_line_color__ ();
       endif
 
-      retval(i) = line (x, y(i), "color", color,
-                        "linestyle", linestyle,
-                        "marker", marker, properties{:});
+      retval(i) =__line__ (gca (), x, y(i), "color", color,
+                           "linestyle", linestyle,
+                           "marker", marker, properties{:});
     endfor
   else
     error ("__plt2sv__: first arg must be scalar, second arg must be vector");
@@ -504,9 +504,9 @@
         color = __next_line_color__ ();
       endif
 
-      retval(i) = line (x, y(:,i), "color", color,
-                        "linestyle", linestyle,
-                        "marker", marker, properties{:});
+      retval(i) =__line__ (gca (), x, y(:,i), "color", color,
+                           "linestyle", linestyle,
+                           "marker", marker, properties{:});
     endfor
   else
     error ("__plt2vm__: arguments must be a matrices");
@@ -545,9 +545,9 @@
         color = __next_line_color__ ();
       endif
 
-      retval(i) = line (x(i), y, "color", color,
-                        "linestyle", linestyle,
-                        "marker", marker, properties{:});
+      retval(i) =__line__ (gca (), x(i), y, "color", color,
+                           "linestyle", linestyle,
+                           "marker", marker, properties{:});
     endfor
   else
     error ("__plt2vs__: first arg must be vector, second arg must be scalar");
@@ -601,9 +601,9 @@
       color = __next_line_color__ ();
     endif
 
-    retval = line (x, y, "color", color,
-              "linestyle", linestyle,
-              "marker", marker, properties{:});
+    retval =__line__ (gca (), x, y, "color", color,
+                      "linestyle", linestyle,
+                      "marker", marker, properties{:});
   else
     error ("__plt2vv__: vector lengths must match");
   endif
