function tspanel(h)

% create 2 panels containing time series objects
localBuildPanel(h);
% listen to the add and remove events of all the objects 
h.addlisteners(handle.listener(h.getRoot.Tsviewer.Tsnode,'ObjectChildAdded',...
    {@localUpdateTables h}));
h.addlisteners(handle.listener(h.getRoot.Tsviewer.Tsnode,'ObjectChildRemoved',...
    {@localUpdateTables h}));
% listen to the selection change event from the two lists
h.addlisteners(handle.listener(h,'tschanged',...
    {@localUpdateTsBoxes h}));
% initialize edit boxes and lists
localUpdateTsBoxes([],[],h)
localUpdateTables([],[],h)


function localBuildPanel(h)

import javax.swing.*;

%% X axis panel
h.Handles.PNLXts = uipanel('Parent',h.Handles.PNLTs,'Units','Characters','Bordertype','none');
h.Handles.LBLtsxlabel = uicontrol('Style','text','String','Time series 1',...
    'HorizontalAlignment','left','Parent',h.Handles.PNLXts,'Units','characters');
h.Handles.BTNtsx= uicontrol('Style','pushbutton','String','Select',...
    'Parent',h.Handles.PNLXts,'Units','characters');
h.Handles.TXTtsx = uicontrol('Style','edit','HorizontalAlignment','left',...
    'Parent',h.Handles.PNLXts,'Units','characters','Backgroundcolor',[1 1 1]);
set(h.Handles.TXTtsx,'Callback',{@localAddTs h.Handles.TXTtsx h 'x'})
[h.Handles.tsTableX, h.Handles.PNLTsTableX] = tsuitable(cell(0,2),...
    {'Name','Number of Columns'},'Parent',ancestor(h.Handles.PNLXts,'figure'));
set(h.Handles.PNLTsTableX,'Parent',h.Handles.PNLXts,'Units','Characters')
set(h.Handles.BTNtsx,'Callback',{@localSelectTs h.Handles.tsTableX h.Handles.TXTtsx})   

%% Y axis panel
h.Handles.PNLYts = uipanel('Parent',h.Handles.PNLTs,'Units','Characters','Bordertype','none');
h.Handles.LBLtsylabel = uicontrol('Style','text','String','Time series 2',...
    'HorizontalAlignment','left','Parent',h.Handles.PNLYts,'Units','characters');
h.Handles.BTNtsy= uicontrol('Style','pushbutton','String','Select',...
    'Parent',h.Handles.PNLYts,'Units','characters');
h.Handles.TXTtsy = uicontrol('Style','edit','HorizontalAlignment','left',...
    'Parent',h.Handles.PNLYts,'Units','characters','Backgroundcolor',[1 1 1]);
set(h.Handles.TXTtsy,'Callback',{@localAddTs h.Handles.TXTtsy h 'y'});
[h.Handles.tsTableY, h.Handles.PNLTsTableY] = tsuitable(cell(0,2),...
    {'Name','Number of Columns'},'Parent',ancestor(h.Handles.PNLYts,'figure'));
set(h.Handles.PNLTsTableY,'Parent',h.Handles.PNLYts,'Units','Characters')
set(h.Handles.BTNtsy,'Callback',{@localSelectTs h.Handles.tsTableY h.Handles.TXTtsy}) 

% set resize function for the two lists
set(h.Handles.PNLXts,'ResizeFcn',{@localXYPnlResize h.Handles.LBLtsxlabel ...
    h.Handles.BTNtsx h.Handles.TXTtsx h.Handles.PNLTsTableX})
set(h.Handles.PNLYts,'ResizeFcn',{@localXYPnlResize h.Handles.LBLtsylabel ...
    h.Handles.BTNtsy h.Handles.TXTtsy h.Handles.PNLTsTableY})

%% Customize tables
set(h.Handles.tsTableX.TableScrollPane.getRowHeader,'Visible','off');
awtinvoke(h.Handles.tsTableX.getTable,'setSelectionMode',...
    ListSelectionModel.SINGLE_SELECTION);
awtinvoke(h.Handles.tsTableX.getTable,'setCellSelectionEnabled',false);
awtinvoke(h.Handles.tsTableX.getTable,'setRowSelectionAllowed',true);
awtinvoke(h.Handles.tsTableX.getTable,'setAutoResizeMode',...
    JTable.AUTO_RESIZE_ALL_COLUMNS);
% awtinvoke(h.Handles.tsTableX.getTable,'setColumnEditable',0,0);
% awtinvoke(h.Handles.tsTableX.getTable,'setColumnEditable',1,0);
h.Handles.tsTableX.getTable.setColumnEditable(0,0);
h.Handles.tsTableX.getTable.setColumnEditable(1,0);
set(h.Handles.tsTableY.TableScrollPane.getRowHeader,'Visible','off');
awtinvoke(h.Handles.tsTableY.getTable,'setSelectionMode',...
    ListSelectionModel.SINGLE_SELECTION);
awtinvoke(h.Handles.tsTableY.getTable,'setCellSelectionEnabled',false);
awtinvoke(h.Handles.tsTableY.getTable,'setRowSelectionAllowed',true);
awtinvoke(h.Handles.tsTableY.getTable,'setAutoResizeMode',JTable.AUTO_RESIZE_ALL_COLUMNS);
% awtinvoke(h.Handles.tsTableY.getTable,'setColumnEditable',0,0);
% awtinvoke(h.Handles.tsTableY.getTable,'setColumnEditable',1,0);
h.Handles.tsTableY.getTable.setColumnEditable(0,0);
h.Handles.tsTableY.getTable.setColumnEditable(1,0);

% set resize function for the main panel
set(h.Handles.PNLTs,'ResizeFcn',{@localTsPanelResize h.Handles.PNLXts h.Handles.PNLYts})
% call it now
localTsPanelResize(h.Handles.PNLXts,[],h.Handles.PNLXts,h.Handles.PNLYts)


function localXYPnlResize(thisPnl,ed,LBLts,BTNts,TXTts,PNLTsTable)
%% XY Panel resize callback

%% Make the table and edit box take up all the horizontal space
pos = get(thisPnl,'Position');
set(LBLts,'Position',[2 max(1,pos(4)-3.25) 35 1.5]);
set(TXTts,'Position',[35 max(1,pos(4)-3) max(1,pos(3)-38-17) 1.5]);
set(PNLTsTable,'Position',[2 2 max(1,pos(3)-23) max(1,pos(4)-6)]);
set(BTNts,'Position',[max(1,pos(3)-18) 2 15 1.5]);
%drawnow


function localTsPanelResize(PNLts,ed,PNLXts,PNLYts)
%% Resize fcn for each time series pane;

%% Get sizes and margins
bmargin = 1;
pos = get(PNLts,'Position');
pnlheight = (max(1,pos(4)-3*bmargin))/2;
%% Set positions
set(PNLXts,'Position',[bmargin 2*bmargin+pnlheight max(1,pos(3)-2*bmargin) pnlheight]);
set(PNLYts,'Position',[bmargin bmargin max(1,pos(3)-2*bmargin) pnlheight]);


function localUpdateTables(es,ed,h)
% callback for ts objects update

if ~isempty(ed) && strcmp(ed.Type,'ObjectChildRemoved')
    tsnodes = setdiff(h.getRoot.Tsviewer.Tsnode.getChildren,ed.Child);
else
    tsnodes = h.getRoot.Tsviewer.Tsnode.getChildren;
end
tableData = cell(size(tsnodes,1),2);
tableData = cell(size(tsnodes,1),2);
for k=1:length(tsnodes)
    tableData(k,:) = {tsnodes(k).Label sprintf('%d',size(tsnodes(k).Timeseries.Data,2))};
end    
h.Handles.tsTableY.setData(tableData);
h.Handles.tsTableX.setData(tableData);


function localSelectTs(es,ed,tsTable,TXTts)
% callback for ts objects selection

selectedRow = tsTable.getTable.getSelectedRow+1;
if selectedRow>0 % Use {} so that 'default' will show
    set(TXTts,'String',{tsTable.Data(selectedRow,1)})
end
returncallback = get(TXTts,'Callback');
feval(returncallback{1},[],[],returncallback{2:end});


function localAddTs(es,ed,TXTts,h,pos)
%% Callback for x and y time series text boxes

tsnodes = h.getRoot.Tsviewer.Tsnode.getChildren;
ind = find(strcmp(deblank(get(TXTts,'String')),get(tsnodes,{'Label'})));
if ~isempty(ind)
    h.addTs(tsnodes(ind(1)).Timeseries,pos);
elseif strcmpi(pos,'x') && ~isempty(h.Timeseries1)
    h.removets(h.Timeseries1)
elseif strcmpi(pos,'y') && ~isempty(h.Timeseries2)
    h.removets(h.Timeseries2)
end


function localUpdateTsBoxes(es,ed,h)
%% Callback for the listeners to the Timeseries1 and Timeseries2 properties
%% which update the edit boxes
if ~isempty(h.Timeseries2)
    set(h.Handles.TXTtsy,'String',{h.Timeseries2.Name});
else
    set(h.Handles.TXTtsy,'String','');
end
if ~isempty(h.Timeseries1)
    set(h.Handles.TXTtsx,'String',{h.Timeseries1.Name});
else
    set(h.Handles.TXTtsx,'String','');
end