function yx=slidder(varargin)
%virtual 2D slider for GUI parameter selection, integer or float (NaN below minX, minY)
%with 'dataaspectratio' toggle
%Call:
% yx=slidder([axlims,][integersc])
% both inputs real, of class 'double', integersc>0,
% axlims =main selection intervals, similar to >> axlims=axis
%
%Input:
% axlims, default [0 1 0 1], main xy-intervals, [minX maxX minY maxY], any vector
% with 4 elements, 1-st and 2-nd for X, 3-rd and 4-th for Y. The values
% below minY, minX are returned as NaN
%
% integersc: a two-function scalar input, default 1+eps (no rescaling):
% 1-st fcn: if round(integersc)==integersc, the output is rounded up to integers
% 2-nd fcn: if set, the default axlims is rescaled as axlims*integersc
%Output:
% yx =[y , x] - values
% Remark: one can override maxX and maxY by dragging the mouse pointer above
% them. The overriding increases if the decreased SLIDDER window is put to most left bottom position
% Call examples:
% yx=slidder %'float' slider from (0, 1)
% yx=slidder(10) %integer slider from (0, 10)
% yx=slidder(20) %integer slider from (0, 20)
% yx=slidder(30*(1+eps)) %'float' slider from (0, 30*(1+eps))
%
% yx=slidder([minX maxX minY maxY]) %'float' slider from input axlims
% yx=slidder([minX maxX minY maxY],integersc) %for integersc==round(integersc), or
% yx=slidder(integersc,[minX maxX minY maxY]) % the output is rounded up
% Vassili Pastushenko FEB 6-2008
%=============================================================
C=varargin; %save inputs
%set defaults and check input vars
parsque %parse input queue
integerflag=integersc==round(integersc); %decides on rounding up
%Open slidder figure, adjust axes, define NaN borders
slif=figure;
axis(axlims);
axis tight;
bor=axlims([1 3]); %lower borders
%set(gca,'dataaspectratio',[1 1 1])
xx=xlim;
yy=ylim;
dx=diff(xx);
dy=diff(yy);
if integerflag&&norm([dx dy])<50
intgrid
else
grid on
end
currax=gca;
%get(currax,'position')
set(currax,'fontsize',14,'box','on')
title('Drag ver-hor params. Repeat or finish')
text(xx(1)-.17*dx,yy(1)-.07*dy,'NaN','fontsize',15,'color','r')
text(xx(2)+.06*dx,mean(yy),' Finish ','backgroundcolor', [1 .4 .4], 'fontsize',18,'rotation',90,'horizontalalignment','center')
%xy=[0 0];
hx=xlabel('NaN','fontsize',17);
hy=ylabel('NaN','fontsize',17);
saspect=get(currax,'dataaspectratio'); %Save ASPECTratio
fhan={@toggleaspect,saspect};
uicontrol('units','normalized','position',[.18,.001,.25,.055],'style','togglebutton', 'string','tog.aspectratio','callback',fhan,'fontsize',14);
deciret=false; %initial value of DECIsion to RETurn
%Dragging parameters
while 1
decide % different actions after mouse click or button down
if deciret
yx=[str2num(get(hy,'string')),str2num( get(hx,'string'))];
voice=sum(~isnan(yx));
if voice>0
cheer(voice);
else
o_o;
end
clear fhan
delete(slif)
return
end
set(slif,'WindowButtonMotionFcn',@followpointer,'WindowButtonUpFcn',@stopmouse);
uiwait
end
function followpointer(obj,cas)
xy=get(currax,'currentpoint');
xy=xy(2:3);
xy(xy<bor)=NaN;
if integerflag
xy=round(xy);
end
set(hy,'string',num2str(xy(2)))
set(hx,'string',num2str(xy(1)))
end
function stopmouse(obj,cas)
%recover WindowButtonFcn's Motion and Up
set(slif,'WindowButtonMotionFcn',[],'WindowButtonUpFcn',[]);
uiresume
end
function decide
waitforbuttonpress
dd=get(gca,'currentpoint');
dd=dd(2:3);
XXX=xlim;
deciret=dd(1)>XXX(2);
end
function parsque
%set defaults
axlims=[0 1 0 1]; %default axis
integersc=1+eps; %no rounding up, no rescaling
N=numel(C);
rescale=N==1; %assuming input were integersc
if N>2
error('Too many inputs')
end
for i=1:N
loc=C{i};
id=class(loc);
if ~strmatch(id,'double','exact')
error('Double expected') %only class 'double' expected
end
if isscalar(loc)
if ~isreal(loc)||loc<=0,error('positive integersc expected');end
integersc=loc;
end
if numel(loc)==4
if ~isreal(loc),error('real axlims expected');end
axlims=loc(:)';
axlims(1:2)=sort(axlims(1:2));
axlims(3:4)=sort(axlims(3:4));
rescale=false;
end
end
if rescale
axlims=axlims*integersc; %default axlims rescaled
end
end
function intgrid
XX=ceil(xx(1)):floor(xx(2));
YY=ceil(yy(1)):floor(yy(2))';
XP=repmat(XX,numel(YY),1);
YP=repmat(YY,1,numel(XX));
hold on
plot(XP(:),YP(:),'b.')
hold off
end
function toggleaspect(ob,cas,saspect)
cur=get(currax,'dataaspectratio');
if norm(cur-[1 1 1])>1e-3
set(currax,'dataaspectratio',[1 1 1])
else
set(currax,'dataaspectratio',saspect)
end
end
end