classdef TSDropDownPopup < toolpack.component.component
  % Toolstrip drop-down popup.
  
  % Author(s): Bora Eryilmaz
  % Revised:
  % Copyright 2010-2012 The MathWorks, Inc.
  
  % ----------------------------------------------------------------------------
  properties (GetAccess = public, SetAccess = private)
    % List items
    Items
    % List style ('text_only', 'icon_text', or 'icon_text_description')
    Style
  end
  
  properties (Dependent, Access = public)
    % Index of currently selected item (integer, default = 0)
    SelectedIndex
  end
  
  % ----------------------------------------------------------------------------
  events
    % Event sent upon selecting a list item.
    ListItemSelected
  end
  
  % ----------------------------------------------------------------------------
  % Public methods
  methods
    function this = TSDropDownPopup(items, style)
      % Creates a toolstrip popup associated with a component.
      %
      % Example:
      %   items(1) = struct(...
      %     'Title', 'Custom Plots', ...
      %     'Description', '', ...
      %     'Icon', [], ...
      %     'Help', [], ...
      %     'Header', true);
      %   items(2) = struct(...
      %     'Title', 'Remove Plot', ...
      %     'Description', 'Removes a plot', ...
      %     'Icon', toolpack.component.Icon.PRINT, ...
      %     'Help', '<empty>', ...
      %     'Header', false);
      %
      %   style = 'icon_text_description';
      %
      %   popup = toolpack.component.TSDropDownPopup(items)
      %   popup = toolpack.component.TSDropDownPopup(items, style)
      
      this = this@toolpack.component.component;
      this.Items = items;
      if nargin < 2
        % toolpack.component.TSDropDownPopup(items)
        this.Style = 'icon_text_description';
      else
        % toolpack.component.TSDropDownPopup(items, style)
        this.Style = style;
      end
      
      cls = 'com.mathworks.toolstrip.components.popups.PopupList';
      this.Peer = javaObjectEDT(cls, LocalCreateList(this.Items));
      this.Peer.setListStyle( LocalJavaListStyle(this.Style) );
      addListItemSelectedListener( this, {@LocalListItemSelected, this} )
    end
    
    function set.Style(this, value)
      % SET function for Style property.
      value = controllib.internal.util.hString2Char(value);
      if ~ischar(value)
        ctrlMsgUtils.error('Controllib:toolpack:InvalidPropertyValue', 'Style')
      end
      value = lower(value);
      values = {'text_only', 'icon_text', 'icon_text_description', ...
        'single_line_description', 'large_icon_text'};
      if ~any(strcmp(value,values))
        ctrlMsgUtils.error('Controllib:toolpack:InvalidPropertyValue', 'Style')
      end
      this.Style = value;
    end
    
    function value = get.SelectedIndex(this)
      % GET function for SelectedIndex property.
      value = this.Peer.getSelectedIndex + 1;
    end
    
    function set.SelectedIndex(this, value)
      % SET function for SelectedIndex property.
      this.Peer.setSelectedIndex(value-1);
    end
    
    function show(this, invoker)
      cls = 'com.mathworks.toolstrip.sections.ToolstripSections';
      javaMethodEDT('showPopup', cls, invoker.Peer, this.Peer);
    end
  end
  
  methods (Access = private)
    function addListItemSelectedListener(this, fcn)
      % Do not modify. Use as is to prevent Java memory leaks.
      L = addlistener(this.Peer, 'ListItemSelected', fcn);
      this.Listeners = [this.Listeners; L];
    end
  end
end

% ------------------------------------------------------------------------------
% Local functions
function LocalListItemSelected(~,~,obj)
obj.notify('ListItemSelected')
end

function List = LocalCreateList(listItems)
% Create headers and items from the specified struct array elements.
import com.mathworks.toolstrip.components.popups.*;
n = length(listItems);
List = javaArray('com.mathworks.toolstrip.components.popups.ListItem', n);

for k = 1:length(listItems)
  item = listItems(k);
  % Create headers and items
  if isfield(item,'Header') && ~isempty(item.Header) && item.Header
    % Header
    if isfield(item, 'Style') && ~isempty(item.Style)
      style =  LocalJavaListStyle(item.Style);
    else
      style = [];
    end
    List(k) = ListItem.newHeader(item.Title, style);
  elseif isfield(item,'SubPopup') && ~isempty(item.SubPopup) && isa(item.SubPopup,'toolpack.component.TSDropDownPopup')
    % create item with sub-popup
    if isfield(item, 'Icon') && ~isempty(item.Icon)
        icon = item.Icon.Peer;
    else
        icon = [];
    end
    List(k) = ListItem.newSubList(item.Title,item.Title,icon,item.SubPopup.Peer);
    if isfield(item, 'Description') && ~isempty(item.Description)
        desc = item.Description;
    else
        desc = '';
    end
    List(k).getAttributes().setAttribute(List(k).DESCRIPTION, desc);
    if isfield(item, 'Help') && ~isempty(item.Help)
        help = item.Help;
    else
        help = '';
    end
    List(k).getAttributes().setAttribute(List(k).HELP, help);
  else
    % Item
    if isfield(item, 'Icon') && ~isempty(item.Icon)
      icon = item.Icon.Peer;
    else
      icon = [];
    end
    if isfield(item, 'Description') && ~isempty(item.Description)
      desc = item.Description;
    else
      desc = '';
    end
    if isfield(item, 'Help') && ~isempty(item.Help)
      help = item.Help;
    else
      help = '';
    end
    List(k) = ListItem.newItem(item.Title, item.Title, desc, help, icon);
  end
end
end

function javaStyle = LocalJavaListStyle(style)
switch style
  case 'text_only'
    javaStyle = com.mathworks.toolstrip.components.popups.ListStyle.TEXT_ONLY;
  case 'icon_text'
    javaStyle = com.mathworks.toolstrip.components.popups.ListStyle.ICON_TEXT;
  case 'icon_text_description'
    javaStyle = com.mathworks.toolstrip.components.popups.ListStyle.ICON_TEXT_DESCRIPTION;
  case 'single_line_description'
    javaStyle = com.mathworks.toolstrip.components.popups.ListStyle.SINGLE_LINE_DESCRIPTION;
  case 'large_icon_text'
    javaStyle = com.mathworks.toolstrip.components.popups.ListStyle.LARGE_ICON_TEXT;
end
end
