time | Calls | line |
---|
| | 456 | function [propargs, ch, strings] = process_inputs(leg,ax,argin,new_legend)
|
| | 457 |
|
| | 458 |
|
| | 459 |
|
< 0.001 | 8 | 460 | propargs = {}; % user-specified PV pairs
|
< 0.001 | 8 | 461 | ch = [];
|
< 0.001 | 8 | 462 | strings = {};
|
| | 463 |
|
| | 464 |
|
| | 465 | % @TODO - we need to remove this or start deprecating it. We have 4
|
| | 466 | % options:
|
| | 467 | % a) do nothing: explicitly ignore ?-DynamicLegend?, i.e. remove it from the input args and continue (16a behavior). If we do this the 16b behavior will actually be compatible with 14a, but in spite of ?-DynamicLegend? and not because of it.
|
| | 468 | % b) same as a), but also WARN that this arg is not longer needed because ?AutoUpdate? ?on? is the new default behavior.
|
| | 469 | % c) completely ignore ?-DynamicLegend?, legend(?-DynamicLegend?) will produce one item with this string, but also WARN
|
| | 470 | % d) completely ignore ?-DynamicLegend?, and don?t even WARN since this was never documented syntax.
|
< 0.001 | 8 | 471 | if ~isempty(argin) && istextscalar(argin{1}) && strcmpi(argin{1},'-DynamicLegend')
|
| | 472 | argin(1) = [];
|
| | 473 | if isempty(argin)
|
| | 474 | return;
|
| | 475 | end
|
< 0.001 | 8 | 476 | end
|
| | 477 |
|
| | 478 | % Find PV Paris - assume any valid Legend property is the start of the P/V
|
| | 479 | % pair list
|
< 0.001 | 8 | 480 | labelsInArray = false;
|
< 0.001 | 8 | 481 | children = [];
|
< 0.001 | 8 | 482 | if ~isempty(argin)
|
0.003 | 8 | 483 | fieldnames = lower(get_legend_properties(leg));
|
< 0.001 | 8 | 484 | for i=1:numel(argin)
|
< 0.001 | 16 | 485 | arg = argin{i};
|
0.005 | 16 | 486 | if istextscalarvector(arg) && ismember(lower(arg),fieldnames)
|
< 0.001 | 8 | 487 | propargs = argin(i:end);
|
< 0.001 | 8 | 488 | argin = argin(1:i-1);
|
< 0.001 | 8 | 489 | break
|
< 0.001 | 8 | 490 | end
|
< 0.001 | 8 | 491 | end
|
| | 492 |
|
< 0.001 | 8 | 493 | if ~isempty(argin)
|
| | 494 | % Process leading (non-PV pair) inputs and determine strings, children and options
|
< 0.001 | 8 | 495 | n = 1;
|
< 0.001 | 8 | 496 | nargs = numel(argin);
|
| | 497 |
|
< 0.001 | 8 | 498 | while n <= nargs
|
< 0.001 | 8 | 499 | if istextscalar(argin{n})
|
| | 500 | strings{end+1} = char(argin{n}); %#ok<AGROW> % single item string
|
< 0.001 | 8 | 501 | elseif isnumeric(argin{n}) && length(argin{n})==4 && ...
|
| | 502 | (n > 1 || ~all(ishghandle(argin{n})))
|
| | 503 | % to use position vector either it must not be the first argument,
|
| | 504 | % or if it is, then the values must not all be handles - in which
|
| | 505 | % case the argument will be considered to be the plot children
|
| | 506 | % This is an undocumented API for backwards compatibility with
|
| | 507 | % Basic Fitting.
|
| | 508 | position = argin{n};
|
| | 509 | fig = ancestor(ax,'figure');
|
| | 510 | position = hgconvertunits(fig,position,'points','normalized', fig);
|
| | 511 | center = position(1:2)+position(3:4)/2;
|
| | 512 | % .001 is a small number so that legend will resize to fit and centered
|
| | 513 | position = [center-.001 0.001 0.001];
|
| | 514 | propargs = {propargs{:}, 'Position',position};
|
| | 515 | propargs = {propargs{:}, 'Location','none'};
|
< 0.001 | 8 | 516 | elseif iscell(argin{n}) || isstring(argin{n})|| iscategorical(argin{n})
|
< 0.001 | 8 | 517 | labelsInArray = true;
|
0.001 | 8 | 518 | if iscategorical(argin{n})
|
| | 519 | argin{n} = string(argin{n});
|
< 0.001 | 8 | 520 | end
|
0.001 | 8 | 521 | strings = cellstr(argin{n});
|
| | 522 | % prepend any remaining elements of argin to propargs
|
< 0.001 | 8 | 523 | if n < nargs
|
| | 524 | propargs = [argin(n+1:end),propargs];
|
| | 525 | break;
|
< 0.001 | 8 | 526 | end
|
| | 527 | elseif n==1 && all(all(ishghandle(argin{n})))
|
| | 528 | % found handles to put in legend
|
| | 529 | % make sure to return objects, not doubles
|
| | 530 | children=handle(argin{n});
|
| | 531 | else
|
| | 532 | error(message('MATLAB:legend:UnknownParameter'));
|
| | 533 |
|
< 0.001 | 8 | 534 | end
|
< 0.001 | 8 | 535 | n = n + 1;
|
< 0.001 | 8 | 536 | end
|
< 0.001 | 8 | 537 | strings = strings(:).';
|
< 0.001 | 8 | 538 | end
|
< 0.001 | 8 | 539 | end
|
| | 540 |
|
| | 541 |
|
| | 542 | % Process plot children and legend labels
|
< 0.001 | 8 | 543 | fewerStringsThanPlots = false;
|
< 0.001 | 8 | 544 | internalPropArgs = {};
|
< 0.001 | 8 | 545 | removeEntries = false;
|
< 0.001 | 8 | 546 | if ~isempty(children) || ~isempty(strings) || new_legend
|
| | 547 | % process children and strings if either:
|
| | 548 | % - children or strings are passed in
|
| | 549 | % - a new legend is being created
|
| | 550 | % this call removes all items from an existing legend
|
| | 551 |
|
< 0.001 | 8 | 552 | if ~isempty(children)
|
| | 553 | % check that all children from user are Legendable
|
| | 554 | validateLegendable(children);
|
| | 555 | auto_children = false;
|
| | 556 | ch = children;
|
| | 557 |
|
| | 558 | % get all Legendable objects
|
| | 559 | ch_all = getLegendableChildren(ax);
|
| | 560 | ch_exclude = setdiff(ch_all,ch);
|
< 0.001 | 8 | 561 | else
|
| | 562 | % if isempty(children), get children from axes
|
< 0.001 | 8 | 563 | auto_children = true;
|
0.063 | 8 | 564 | ch = getLegendableChildren(ax);
|
< 0.001 | 8 | 565 | ch_exclude = [];
|
< 0.001 | 8 | 566 | end
|
| | 567 |
|
| | 568 | % make sure we have column vectors
|
< 0.001 | 8 | 569 | ch = ch(:);
|
< 0.001 | 8 | 570 | ch_exclude = ch_exclude(:);
|
| | 571 |
|
| | 572 | % if str is empty, create strings
|
< 0.001 | 8 | 573 | if isempty(strings)
|
| | 574 | if auto_children && length(ch) > 50
|
| | 575 | % only automatically add first 50 to cut down on huge lists
|
| | 576 | ch = ch(1:50);
|
| | 577 | end
|
| | 578 | % flag when the user specifies fewer label strings than there are
|
| | 579 | % legendable children. This may be used in make_legend to provide
|
| | 580 | % extra warning information.
|
| | 581 | if numel(strings) < numel(ch)
|
| | 582 | fewerStringsThanPlots = true;
|
| | 583 | end
|
< 0.001 | 8 | 584 | else
|
| | 585 | % expand strings if possible
|
| | 586 | % legend(p(1:2),['a';'b'])
|
< 0.001 | 8 | 587 | if (length(ch) ~= 1) && (length(strings) == 1) && (size(strings{1},1) > 1)
|
| | 588 | strings = cellstr(strings{1});
|
< 0.001 | 8 | 589 | end
|
| | 590 |
|
| | 591 | % trim children or strings
|
< 0.001 | 8 | 592 | num_str = numel(strings);
|
< 0.001 | 8 | 593 | num_ch = numel(ch);
|
| | 594 | % flag when the user specifies fewer label strings than there are
|
| | 595 | % legendable children. This may be used in make_legend to provide
|
| | 596 | % extra warning information.
|
< 0.001 | 8 | 597 | if num_str < num_ch
|
| | 598 | fewerStringsThanPlots = true;
|
< 0.001 | 8 | 599 | end
|
< 0.001 | 8 | 600 | if num_str ~= num_ch
|
| | 601 | if ~auto_children || num_str > num_ch
|
| | 602 | warning(message('MATLAB:legend:IgnoringExtraEntries'));
|
| | 603 | end
|
| | 604 | if num_str > num_ch
|
| | 605 | strings = strings(1:num_ch);
|
| | 606 | else
|
| | 607 | % user passed in more objects than strings
|
| | 608 | % add extra objects to the exclude list
|
| | 609 | ch_exclude = [ch_exclude; ch(num_str+1:end)];
|
| | 610 | ch = ch(1:num_str);
|
| | 611 | end
|
< 0.001 | 8 | 612 | end
|
< 0.001 | 8 | 613 | end
|
| | 614 |
|
< 0.001 | 8 | 615 | internalPropArgs = [internalPropArgs,{'PlotChildren_I'},{ch}];
|
< 0.001 | 8 | 616 | internalPropArgs = [internalPropArgs,{'PlotChildrenExcluded_I'},{ch_exclude}];
|
< 0.001 | 8 | 617 | internalPropArgs = [internalPropArgs,{'PlotChildrenSpecified'},{[]}];
|
< 0.001 | 8 | 618 | if ~auto_children
|
| | 619 | internalPropArgs = [internalPropArgs,{'PlotChildrenSpecified'},{ch}];
|
< 0.001 | 8 | 620 | end
|
| | 621 |
|
< 0.001 | 8 | 622 | removeEntries = true;
|
< 0.001 | 8 | 623 | end
|
| | 624 |
|
| | 625 | %%%%% Error checking before setting any state on legend
|
| | 626 |
|
| | 627 | % validate and process user-specified PV pairs
|
< 0.001 | 8 | 628 | if ~isempty(propargs)
|
| | 629 | % create local vars to support handling of special Location values
|
| | 630 | % farther down.
|
< 0.001 | 8 | 631 | locations = {};
|
< 0.001 | 8 | 632 | locationAbbrevs = {};
|
< 0.001 | 8 | 633 | if any(strcmpi(propargs,'location'))
|
| | 634 | % Get location strings long and short form. The short form is the
|
| | 635 | % long form without any of the lower case characters.
|
| | 636 | % hard code the enumeration values until we can query the datatype directly
|
< 0.001 | 8 | 637 | locations = {'North','South','East', 'West','NorthEast','SouthEast','NorthWest','SouthWest','NorthOutside','SouthOutside','EastOutside','WestOutside','NorthEastOutside','SouthEastOutside','NorthWestOutside','SouthWestOutside','Best','BestOutside','none'};
|
< 0.001 | 8 | 638 | locationAbbrevs = cell(1,length(locations));
|
< 0.001 | 8 | 639 | for k=1:length(locations)
|
< 0.001 | 152 | 640 | str = locations{k};
|
0.001 | 152 | 641 | locationAbbrevs{k} = str(str>='A' & str<='Z');
|
< 0.001 | 152 | 642 | end
|
< 0.001 | 8 | 643 | end
|
| | 644 |
|
| | 645 | % check that every p is a property
|
| | 646 | % check for special Location values
|
< 0.001 | 8 | 647 | numPropArgs = numel(propargs);
|
< 0.001 | 8 | 648 | for i=1:2:numPropArgs
|
< 0.001 | 8 | 649 | if ~any(strcmpi(fieldnames,propargs{i}))
|
| | 650 | tryAddingWarningAboutLabelAmbiguity(labelsInArray,fewerStringsThanPlots,propargs{1});
|
| | 651 | try
|
| | 652 | m = message('MATLAB:legend:UnknownProperty', ['''' propargs{ i } '''']);
|
| | 653 | catch
|
| | 654 | m = message('MATLAB:legend:UnknownProperty', '');
|
| | 655 | end
|
| | 656 | throw(MException(m));
|
< 0.001 | 8 | 657 | end
|
| | 658 |
|
| | 659 | % Look for (...,'Location',POS) or (...,'Location',LOCATION_ABBREV)
|
< 0.001 | 8 | 660 | if strcmpi(propargs{i},'location')
|
< 0.001 | 8 | 661 | if i < numPropArgs
|
< 0.001 | 8 | 662 | if isnumeric(propargs{i+1}) && length(propargs{i+1})==4
|
| | 663 | % found 'Location', POS
|
| | 664 | position = propargs{i+1};
|
| | 665 | propargs{i+1} = 'none';
|
| | 666 | propargs = {propargs{:}, 'Position',position};
|
< 0.001 | 8 | 667 | elseif istextscalar(propargs{i+1})
|
< 0.001 | 8 | 668 | abbrevsCmp = strcmpi(propargs{i+1}, locationAbbrevs);
|
< 0.001 | 8 | 669 | if any(abbrevsCmp)
|
| | 670 | % found 'Location', ABBREV
|
| | 671 | propargs{i+1} = locations{abbrevsCmp};
|
< 0.001 | 8 | 672 | end
|
< 0.001 | 8 | 673 | end
|
< 0.001 | 8 | 674 | end
|
< 0.001 | 8 | 675 | end
|
< 0.001 | 8 | 676 | end
|
< 0.001 | 8 | 677 | end
|
| | 678 |
|
| | 679 |
|
| | 680 |
|
| | 681 |
|
| | 682 |
|
| | 683 |
|
< 0.001 | 8 | 684 | lcl_propargs = propargs;
|
< 0.001 | 8 | 685 | if ~isempty(lcl_propargs)
|
| | 686 | % first handle odd number of PV pairs
|
< 0.001 | 8 | 687 | if mod(numel(lcl_propargs),2) == 1
|
| | 688 | tryAddingWarningAboutLabelAmbiguity(labelsInArray,fewerStringsThanPlots,lcl_propargs{1});
|
| | 689 | throw(MException(message('MATLAB:legend:NameValueMismatch')));
|
< 0.001 | 8 | 690 | end
|
| | 691 | % now try setting the pv pairs. If the first pv pair errors try to add
|
| | 692 | % a helpful warning since it may be because they meany the property to
|
| | 693 | % be interpreted as a label.
|
0.103 | 8 | 694 | tmp_leg = matlab.graphics.illustration.Legend;
|
< 0.001 | 8 | 695 | try
|
0.018 | 8 | 696 | set(tmp_leg,lcl_propargs{1:2});
|
< 0.001 | 8 | 697 | lcl_propargs(1:2) = [];
|
| | 698 | catch ME
|
| | 699 | delete(tmp_leg);
|
| | 700 | tryAddingWarningAboutLabelAmbiguity(labelsInArray,fewerStringsThanPlots,lcl_propargs{1});
|
| | 701 | throw(ME);
|
< 0.001 | 8 | 702 | end
|
| | 703 | % set remaining pv pairs, if any
|
< 0.001 | 8 | 704 | if ~isempty(lcl_propargs)
|
| | 705 | try
|
| | 706 | set(tmp_leg,lcl_propargs{:});
|
| | 707 | catch ME
|
| | 708 | delete(tmp_leg);
|
| | 709 | throw(ME);
|
| | 710 | end
|
< 0.001 | 8 | 711 | end
|
0.010 | 8 | 712 | delete(tmp_leg);
|
< 0.001 | 8 | 713 | end
|
| | 714 |
|
| | 715 | % update legend state
|
< 0.001 | 8 | 716 | if ~isempty(internalPropArgs)
|
0.012 | 8 | 717 | set(leg,internalPropArgs{:});
|
< 0.001 | 8 | 718 | end
|
< 0.001 | 8 | 719 | if removeEntries
|
0.002 | 8 | 720 | removeAllEntries(leg);
|
< 0.001 | 8 | 721 | end
|
Other subfunctions in this file are not included in this listing.