function s = edit(Constr,Container)
%EDIT  Builds timeresponse constraint parameter editor.

%   Authors: P. Gahinet, A.Stothert
%   Copyright 1986-2004 The MathWorks, Inc. 
%   $Revision: 1.1.6.2 $ $Date: 2004/12/26 21:51:49 $

import com.mathworks.mwt.*;
%import com.mathworks.mwswing.*;

% Definitions
Prefs = cstprefs.tbxprefs;
GL_41 = java.awt.GridLayout(4,1,0,3);
LEFT  = MWLabel.LEFT;
CENTER = MWLabel.CENTER;
BWEST = MWBorderLayout.WEST;
BCENTER = MWBorderLayout.CENTER;
BEAST = MWBorderLayout.EAST;

% Labels
P1 = MWPanel(GL_41); 
Container.add(P1,BWEST);
L = cell(4,1);
Text = {xlate('Select edge to edit');...
   xlate('Time');...
   xlate('Magnitude');...
   xlate('Weight')};
for ct=1:numel(L)
    Label = MWLabel(sprintf('%s:',Text{ct}),LEFT); 
    P1.add(Label);  
    Label.setFont(Prefs.JavaFontP);
    L{ct} = Label;
end

%Edge Selector
EdgeP  = MWPanel(GL_41);
EdgeCB = MWChoice;
for ct = 1:size(Constr.xCoords,1)
   EdgeCB.addItem(num2str(ct));
end
EdgeP.add(EdgeCB);

% Text fields
P6 = MWPanel(MWBorderLayout(0,0));
Container.add(P6,BCENTER);
P2 = MWPanel(MWBorderLayout(7,0)); 
P6.add(P2,BWEST);
T = cell(4,3);
% Column #1
P3 = MWPanel(GL_41);  P2.add(P3,BWEST);
P3.add(EdgeCB);   T{1,1} = EdgeCB;
W = MWTextField(10); 
P3.add(W);   W.setFont(Prefs.JavaFontP);  T{2,1} = W;
W = MWTextField(10); 
P3.add(W);   W.setFont(Prefs.JavaFontP);  T{3,1} = W;
W = MWTextField(10); 
P3.add(W); T{4,1} = W;
% Column #2
P4 = MWPanel(GL_41);   P2.add(P4,BCENTER);
P4.add(MWLabel('',LEFT));
W = MWLabel(sprintf('to'),CENTER); 
P4.add(W);   W.setFont(Prefs.JavaFontP);  T{2,2} = W;
W = MWLabel(sprintf('to'),CENTER); 
P4.add(W);   W.setFont(Prefs.JavaFontP);  T{3,2} = W;
% Column #3
P5 = MWPanel(GL_41);   P2.add(P5,BEAST);
P5.add(MWLabel('',LEFT));
W = MWTextField(10); 
P5.add(W);   W.setFont(Prefs.JavaFontP);  T{2,3} = W;
W = MWTextField(10); 
P5.add(W);   W.setFont(Prefs.JavaFontP);  T{3,3} = W;

% Callbacks
Callback = {@LocalChangeEdge Constr T};
set(T{1,1},'ItemStateChangedCallback',Callback)
Callback = {@LocalEditCoord Constr T 1 'Time'};
set(T{2,1},'ActionPerformedCallback',Callback,'FocusLostCallback',Callback)
Callback = {@LocalEditCoord Constr T 1 'Magnitude'};
set(T{3,1},'ActionPerformedCallback',Callback,'FocusLostCallback',Callback)
Callback = {@LocalEditCoord Constr T 2 'Time'};
set(T{2,3},'ActionPerformedCallback',Callback,'FocusLostCallback',Callback)
Callback = {@LocalEditCoord Constr T 2 'Magnitude'};
set(T{3,3},'ActionPerformedCallback',Callback,'FocusLostCallback',Callback)
Callback = {@LocalEditWeight Constr T};
set(T{4,1},'ActionPerformedCallback',Callback,'FocusLostCallback',Callback)

% Initialize text field values
LocalUpdateText([],[],Constr,T);

% Update listeners (track changes in constraint data)
props = [Constr.findprop('Time');...
      Constr.findprop('Magnitude');...
      Constr.findprop('TimeUnits');...
      Constr.findprop('MagnitudeUnits'); ...
      Constr.findprop('SelectedEdge')];
Listener = handle.listener(Constr,props,'PropertyPostSet',{@LocalUpdateText Constr T});
Listener = [Listener; ...
   handle.listener(Constr,'DataChanged',{@LocalUpdateText Constr T})];

% Save other handles
s = struct('Panels',{{P1;P2;P3;P4;P5;P6}},'Handles',{[L ; T(:)]},'Listeners',Listener);

%--------------------------------------------------------------------------
function LocalChangeEdge(eventsrc,eventdata,Constr,T)

NewEdge = str2double(T{1,1}.getSelectedItem);
if any(NewEdge~=Constr.SelectedEdge(1)) && ...
      (NewEdge > 0) && ...
      (NewEdge <= size(Constr.Time,1)) 
   Constr.SelectedEdge = NewEdge;
   LocalUpdateText([],[],Constr,T);
end

%--------------------------------------------------------------------------
function LocalUpdateText(eventsrc,eventdata,Constr,T)

% Updates text fields from contraint data
f = unitconv(Constr.Time(Constr.SelectedEdge,:),Constr.TimeUnits,Constr.getDisplayUnits('XUnits'));
mag = Constr.Magnitude(Constr.SelectedEdge,:);
mag(abs(mag)<1e-3) = 0;
mag = unitconv(mag,Constr.MagnitudeUnits,Constr.getDisplayUnits('YUnits'));
if T{1,1}.getItemCount ~= size(Constr.Time,1)
   %Added or deleted edge, need to reset combobox item list
   Callback = get(T{1,1},'ItemStateChangedCallback');
   %Disable combobox callbacks
   set(T{1,1},'ItemStateChangedCallback','')
   T{1,1}.removeAll;
   for ct = 1:size(Constr.Time,1)
      T{1,1}.addItem(num2str(ct));
   end
   T{1,1}.select(Constr.SelectedEdge(1)-1);
   set(T{1,1},'ItemStateChangedCallback',Callback)
else
   T{1,1}.select(Constr.SelectedEdge(1)-1);
end
set(T{2,1},'Text',sprintf('%.3g',f(1)))
set(T{2,3},'Text',sprintf('%.3g',f(2)))
set(T{3,1},'Text',sprintf('%.3g',mag(1)))
set(T{3,3},'Text',sprintf('%.3g',mag(2)))
set(T{4,1},'Text',sprintf('%.3g',Constr.Weight(Constr.SelectedEdge(1))))

%--------------------------------------------------------------------------
function v = LocalEvaluate(TextField)
% Evaluate text field content
s = get(TextField,'Text');
if isempty(s)
   v = [];
else
   v = evalin('base',s,'[]');
   if ~isequal(size(v),[1 1]) || ~isreal(v),
      v = [];
   end
end

%--------------------------------------------------------------------------
function LocalEditCoord(TextField,eventData,Constr,T,jx,WhichCoord)

%Find axes units
switch WhichCoord
   case 'Time'
      Units = 'XUnits';
   case 'Magnitude'
      Units = 'YUnits';
end

% Update min or max time
v = unitconv(LocalEvaluate(TextField),...
   Constr.getDisplayUnits(Units), ...
   Constr.([WhichCoord,'Units'])(Constr.SelectedEdge));

% Get new range 
Range = Constr.(WhichCoord)(Constr.SelectedEdge,:);
if ~isempty(v)
   Range(jx) = v;
end

% Update data
if isequal(Constr.(WhichCoord),Range)
   % No change: resync text
   LocalUpdateText([],[],Constr,T);
else
   T = Constr.recordon;
   Constr.(WhichCoord)(Constr.SelectedEdge,:) = Range;
   Constr.recordoff(T);
   % Update display and notify observers
   Constr.send('DataChangeFinished');
   update(Constr)
end

%--------------------------------------------------------------------------
function LocalEditWeight(TextField,eventData,Constr,T)

% Update min or max time
%v = get(TextField,'Value');
v = LocalEvaluate(TextField);

%Limit weight to valid range 
v = max(0,min(v,1));

%If the value has changed update the object
idx = Constr.SelectedEdge(1);
if v == Constr.Weight(idx)
   % No change: resync text
   LocalUpdateText([],[],Constr,T);
else
   T = Constr.recordon;
   Constr.Weight(idx) = v;
   Constr.recordoff(T);
   % Update display and notify observers
   update(Constr)
end
