function eventpnl(this,eventPanel)

%% Builds events panel for @tsnode
import javax.swing.*;

%% Create the node panel and components
localBuildPanel(this,eventPanel);
set(eventPanel,'ResizeFcn',{@localEventsResize this})

%% Temporary listeners to update table visibility when the enclosing panel
%% visibility is modified
h = handle(eventPanel);
this.addListeners(handle.listener(h,h.findprop('Visible'),'PropertyPostSet',...
    {@localSetVisible h}));

%% Listener to the events stored in the timeseries
this.addListeners(handle.listener(this.Timeseries,...
    'datachange',...
    {@localEventsChange this.Timeseries this.Handles.eventTable}));
localEventsChange([],[],this.Timeseries,this.Handles.eventTable)

function localBuildPanel(h,PNLevents)

import javax.swing.*;

%% Events panel
h.Handles.BTNaddEvent = uicontrol('Style','pushbutton','Parent',PNLevents, ...
    'Units','Pixels','String','Add event','Callback',{@localAddEvent h},...
    'Units','Characters');
h.Handles.BTNdelEvent = uicontrol('Style','pushbutton','Parent',PNLevents, ...
    'Units','Pixels','String','Delete event','Callback',{@localDelEvent h},... 
    'Units','Characters');
[h.Handles.eventTable, h.Handles.PNLeventTable] = ...
    tsuitable(ancestor(PNLevents,'figure'),cell([0,3]), ...
    {'Name','Description','Time'},'Position',[0 0 1 1]);
tsCustomizeUitable(h.Handles.eventTable);
set(h.Handles.eventTable,'DataChangedcallback',...
    {@localEventTimeChange h},'Visible',false);
set(h.Handles.PNLeventTable,'Parent',PNLevents,'Units','Pixels','Visible','off')
awtinvoke(h.Handles.eventTable.getTable,'setSelectionMode(I)',...
        ListSelectionModel.SINGLE_SELECTION);
awtinvoke(h.Handles.eventTable.getTable,'setCellSelectionEnabled(Z)',false);
awtinvoke(h.Handles.eventTable.getTable,'setRowSelectionAllowed(Z)',true);
awtinvoke(h.Handles.eventTable.getTable,'setAutoResizeMode(I)',...
    JTable.AUTO_RESIZE_ALL_COLUMNS)

function localSetVisible(es,ed,h)

children = h.find('-depth',inf,'-isa','uicontainer');
if ~isempty(children)
    set(children,'Visible',get(h,'Visible'));
end

function localEventsChange(eventSrc,eventData,ts,eventTable)

%% Listener callback to @eventsnode "Events" property which keeps the event
%% table in sync
tableData = cell(length(ts.Events),3);
for k=1:length(ts.Events)
    if ischar(ts.Events(k).EventData)
        tableData(k,:) = {ts.Events(k).Name, ts.Events(k).EventData, ts.Events(k).getTimeStr{1}};
    else
        tableData(k,:) = {ts.Events(k).Name, '', ts.Events(k).getTimeStr{1}};
    end
end

%% Passive table data change
eventTable.setData(tableData);

function localEventTimeChange(eventSrc,eventData,h)

%% Callback which reacts to changes in the event time made in the events
%% table

%% Find the data which was changed
startRow = eventData.getEvent.getFirstRow+1;
col = eventData.getEvent.getColumn+1;

%% Look for the event who's time has changed
%% Time change
if col==3
    I = find(strcmp(h.Handles.eventTable.Data(startRow,1),get(h.Timeseries.events,{'Name'})));
    if ~isempty(I)
        % Compute the new event time in the right frame of reference
        if ~isempty(h.Timeseries.TimeInfo.StartDate)
            try
                evtime = datenum(h.Handles.eventTable.Data(startRow,3));
            catch %Abort
                localEventsChange([],[],h.Timeseries,h.Handles.eventTable)
                return
            end
            
            evtime = (evtime-datenum(h.Timeseries.TimeInfo.StartDate))*...
                tsunitconv(h.Timeseries.TimeInfo.Units,'days');
        else
            evtime = eval(h.Handles.eventTable.Data(startRow,3),'[]');
            if isempty(evtime) || ~isscalar(evtime) %Abort
                localEventsChange([],[],h.Timeseries,h.Handles.eventTable)
                return
            end
        end
        
        % Create transaction
        T = tsguis.transaction;
        recorder = tsguis.recorder;

        % Update the event time
        h.Timeseries.events(I(1)).Time = evtime;

        % Record action
        if strcmp(recorder.Recording,'on')
            T.addbuffer('%% Modifying event time');
            T.addbuffer(['e = find(' h.Timeseries.Name '.Events,' , ...
                '''Name'',''' , h.Timeseries.events(I(1)).Name, ''');']);
            T.addbuffer(['e.Time = ' num2str(evtime) ';'],h.Timeseries);
        end

        % Store transaction
        T.commit;
        recorder.pushundo(T);   
        
        % Send a datachange event to the affected time series
        h.Timeseries.send('datachange')
    end
%% Name change    
elseif col==1
    evname = h.Handles.eventTable.Data(startRow,1);
    if isempty(evname) || ~ischar(evname)% Abort
        localEventsChange([],[],h.Timeseries,h.Handles.eventTable)
        return
    end   

    % Create transaction
    T = tsguis.transaction;
    recorder = tsguis.recorder;
   
    
    % Record action
    if strcmp(recorder.Recording,'on')
        T.addbuffer('%% Modifying event name');
        T.addbuffer(['e = find(' h.Timeseries.Name '.Events,' , ...
            '''Name'',''' , h.Timeseries.events(startRow).Name, ''');']);
        T.addbuffer(['e.Name = ''' evname ''';'],h.Timeseries);
    end

    % Update the name
    h.Timeseries.events(startRow).Name = evname;
    h.Timeseries.send('datachange')
    
    % Store transaction
    T.commit;
    recorder.pushundo(T);                   
        
%% Description change
elseif col==2
    h.Timeseries.events(startRow).EventData = h.Handles.eventTable.Data(startRow,2);
end
    
function localAddEvent(es,ed,h)

%% Get the properties of the new event
selrows = h.Tstable.Table.getTable.getSelectedRows+1;
defaulttime = [];
if ~isempty(selrows)
    defaulttime = h.Tstable.Table.Data(selrows(1),1);
end

if ~isempty(h.Timeseries.TimeInfo.StartDate)
    if ~isempty(defaulttime) && ischar(defaulttime)
        e = tsnewevent(defaulttime);
    else
        e = tsnewevent(h.Timeseries.TimeInfo.StartDate);
    end
    if isempty(e)
        return
    end
    e.Time = (e.Time-datenum(h.Timeseries.TimeInfo.StartDate))*...
        tsunitconv(h.Timeseries.TimeInfo.Units,'days');
else
    if ~isempty(defaulttime) && isnumeric(defaulttime)
        e = tsnewevent(defaulttime);
    else
        e = tsnewevent;
    end
    if isempty(e)
        return
    end
end

%% Create transaction
T = tsguis.transaction;
recorder = tsguis.recorder;
        
%% Update the list of events
h.Timeseries.addevent(e);

%% Record action
if strcmp(recorder.Recording,'on')
    T.addbuffer('%% Add a new event');
    T.addbuffer(['e = tsdata.event(''' e.Name ''',' sprintf('%f',e.Time) ,');']);
    T.addbuffer([h.Timeseries.Name '.addevent(e);'],h.Timeseries);
end

%% Store transaction
T.commit;
recorder.pushundo(T);
        
function localDelEvent(es,ed,h)

selrow = h.Handles.eventTable.getTable.getSelectedRow+1;
if selrow>=1
    thiseventname = h.Handles.eventTable.Data(selrow,1);
    ind = find(strcmp(thiseventname,get(h.Timeseries.Events,{'Name'})));
    
    % Create transaction
    T = tsguis.transaction;
    recorder = tsguis.recorder;

    % Update the list of events
    h.Timeseries.Events(ind) = [];
    
    %% Record action
    if strcmp(recorder.Recording,'on')
        T.addbuffer('%% Delete event');
        T.addbuffer(['ind = strcmp(''' thiseventname ''',get(' h.Timeseries.Name '.Events,{''Name''}));']);
        T.addbuffer([h.Timeseries.Name '.Events(ind) = [];'],h.Timeseries);
    end

    % Store transaction
    T.commit;
    recorder.pushundo(T);
end
h.Timeseries.send('datachange')

function localEventsResize(es,ed,h)

%% Resize function for events panel
% use max to allow only positive positions
pos = get(es,'Position');
set(h.Handles.BTNaddEvent,'Position',[max(1,pos(3)-30) 1 14 1.46]);
set(h.Handles.BTNdelEvent,'Position',[max(1,pos(3)-15) 1 14 1.46]);
tablepos = hgconvertunits(ancestor(h.Handles.PNLeventTable,'figure'),...
    [1 3.46 max(1,pos(3)-2) max(1,pos(4)-4.46)],'Characters','Pixels',...
    get(h.Handles.PNLeventTable,'Parent'));
set(h.Handles.PNLeventTable,'Position',tablepos);

