Drag and Drop(Line Objects)

by

 

Drag and Drop Line Objects From wthin any axes in any figure.

Mouse_over_lineObj(varargin)
function Mouse_over_lineObj(varargin)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% NAME: Mouse_over_lineObj
% 
% AUTHOR: Rasam aliazizi (email: rasama@hotmail.co.uk; rasam.alizizi@liv.ac.uk;)
%
% PURPOSE: provide drag and drop with line Objects in an axes.
% 
%Example: Mouse_over_lineObj(fig), Mouse_over_lineObj(gcf), 
%         Mouse_over_lineObj([fig1, fig2, fig3, ....]),
%
%Mouse_over_lineObj, requres handles to figure/s as its input. it will then
%associate the drag and drop functionality will line objects in all or some
%of those figures if there are any. it will simply returns with no error or
%warning if it does not find any line object/s in any of those figure/s.
%you can drag any line objects and drop it either within another axes in
%the same figure or another figure. or you can drop the line objects
%outside the figure, in this case Mouse_over_lineObj, will create a new
%figure with interactive functionality associated. 
%these include: save the content of gca to EXCEL, interctive zooming and
%fitting the curves tight to their axes. you also have access to all matlab
%graphical tools.
%function allows you to drag and drop multiple times at any order and will
%nicely adopt it self to user's benefit. the later is hard to explain!
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
clc,
narginchk(1, 1),
if ~all(arrayfun(@ishandle, varargin{1}))
    error(['Function expects its argument to be handle to a valid figure object.' ...
        'If multiple an array of handles are supplied then all must valid handle of figure objects.']);
else
   InputType = get(varargin{1}, 'type');
end
if ~all(strcmp(InputType, 'figure'))
    error(['Function expects its argument to be handle to a valid figure object.' ...
        'If multiple an array of handles are supplied then all must valid handle of figure objects.']);
else
    S.fig = varargin{1};
end
S.ax = findobj(S.fig, 'type', 'axes');
if isempty(S.ax)
    return,
else
    set(S.ax,'unit','pix');
    S.AXP = get(S.ax,'pos');
    S.LineH = findobj(S.ax, 'type', 'line');
    if isempty(S.LineH)
        return,
    end
end
%dragging is the variable that holds the handle to the dragged line object.
dragging = [];
objecttype = 'line';
set(S.LineH,'ButtonDownFcn',@button_down);

    function button_down(src,event)
        %button down detected, on a line OBJECT.
        % src - the object that is the source of the event, the line object to be
        % dragged
        % evnt - empty for this property
        %Object highlighted when selected.
        sel_typ = get(gcbf,'SelectionType');
        switch sel_typ 
            case 'normal'                
                setptr(gcf, 'hand');     
                set(src,'Selected','on', 'HitTest', 'on',...
                    'userdata', [get(get(src, 'parent'), 'xlim') get(get(src, 'parent'), 'ylim')])         
                dragging = src; %S.LineH(1), OR S.LineH(2), which ever that is selected, will be dragged.
                %to drag both or all lines Objs use, S.LineH
                %line below provides the currentfunctionality to all subsequent
                %figures.
                set(get(get(dragging, 'parent'), 'parent'), 'WindowButtonUpFcn',@dropObject),
                %illustrate to user that dragging in progress...                
                point1 = get(gcf,'CurrentPoint');
                rect = [point1(1,1) point1(1,2) 50 50];
                dragrect(rect);               
            case 'extend'
                disp('User did a shift-click')
                set(src,'Selected','on')
                dragging = [];
            case 'alt'
                disp('User did a control-click')
                set(src,'Selected','on')
                set(src,'SelectionHighlight','off')
                dragging = [];
            case 'open'
                %don't use open with normal...
                disp('User double clicked.')
                set(src,'Selected','on')
                dragging = [];
        end
    end
%call back associated with line objects outside the mother figure. if this
%is disabled and removed from the code then it is possible to move the line
%objects back to the mother figure from an outside figure.
    function button_down2(varargin)
        %do nothing...
    end
    function dropObject(hObject,eventdata)
        %newP = get(gcf,'CurrentPoint'); 

        %check if mouse is within the boundray of axes 2 when user let go of
        %the mouse. other axis may be added here for greater flexibility.
        %[left, bottom, width, height]
        
        %set the dropping source to a particular axes if you want here.
        %get rid of the marked area (%%) and add && tf to the if statement.
        %then set the handle of the source of dropping (axes) appropriately.
        
        %{
    tf = S.AXP{2}(1) <= newP(1) && newP(1) <= S.AXP{2}(1) + S.AXP{2}(3) && ...
        newP(2) >= S.AXP{2}(2) && newP(2) <= S.AXP{2}(2) + S.AXP{2}(4);
        %}
        if ~isempty(dragging) 
            %%
            [ObjHandle infig] = overobj2();
            dropaxeshandle = get(ObjHandle, 'type');
            if strcmp(dropaxeshandle, 'axes')
                set(dragging, 'parent', ObjHandle);%S.ax(2)
                set(get(ObjHandle, 'children'),'ButtonDownFcn',@button_down);
                set(dragging,'Selected','off')
                dragging = [];
            elseif ~strcmp(dropaxeshandle, 'axes')...
                    && infig
                disp(['can not drop in, ' get(ObjHandle, 'style') ', (type:' dropaxeshandle ')'])
                set(dragging,'Selected','off')
            else
                limz = get(dragging, 'userdata');
                %sort the position of new figure window.
                screenpos = get(0, 'screensize');
                mpos = get(0, 'pointerlocation');mpos(3)=860;mpos(4)=448;
                %make sure that figure is always within the boundary of
                %user's screen.
                if (mpos(4)+mpos(2))-screenpos(4)>0
                    offset1 = (mpos(4)+mpos(2))-screenpos(4);
                else
                    offset1 = 0;
                end
                if (mpos(3)+mpos(1))-screenpos(3)>0
                    offset2 = (mpos(3)+mpos(1))-screenpos(3);
                else
                    offset2 = 0;
                end
                %create the new figure window.
                outfig = figure('outerposition', [mpos(1)-offset2 mpos(2)-offset1 mpos(3) mpos(4)],...
                    'color', [1 0.7 0.5], 'resize', 'off', 'tag', 'copycopy');
                closeh = uicontrol('style', 'pushbutton', 'string', 'close',...
                    'position', [20 5 60 20],'backgroundcolor', get(outfig, 'color'),...
                    'callback', {@close_callback, outfig});checkpos = get(closeh, 'position');
                uicontrol('style', 'pushbutton', 'string', 'Save to Excel',...
                    'position', [mpos(3)-checkpos(1)-checkpos(3)*2 checkpos(2) checkpos(3)*2 20],'backgroundcolor', get(outfig, 'color'),...
                    'callback', {@excel_callback, outfig});
                checkh = uicontrol('style', 'radio', 'string', 'Full span', 'value', 0, ...
                    'backgroundcolor', get(outfig, 'color'), ...
                    'position', [checkpos(1)+checkpos(3)+5 checkpos(2) checkpos(3)+5 checkpos(4)]);checkpos2 = get(checkh, 'position');
                magnifyh = uicontrol('style', 'radio', 'string', 'Enable Magnification', 'value', 0, ...
                    'backgroundcolor', get(outfig, 'color'), ...
                    'position', [checkpos2(1)+checkpos2(3)+5 checkpos2(2) checkpos2(3)+15 checkpos2(4)],...
                    'tooltipstring', 'Enable magnification');
                set(checkh, 'callback', {@check_callback, checkh, limz})
                set(magnifyh, 'callback', {@magnifyh_callback, magnifyh})
                outFig = axes();
                set(outFig, 'xlim', [limz(1) limz(2)], 'ylim', [limz(3) limz(4)]);
                set(dragging, 'parent', outFig);
                set(get(outFig, 'children'),'ButtonDownFcn',@button_down);
                %disp('failed to drop outside figure.')
                set(dragging,'Selected','off')
                dragging = [];
            end
        end
        setptr(gcf, 'arrow');
        %delete copies of figures created by user action if they are empty
        %of line objects... this is done via tagging the copied features
        %with string 'copycopy'.
        H_to_current_figs = findobj(0, 'type', 'figure', 'tag', 'copycopy');
        if ~isempty(H_to_current_figs)
            for i = 1:length(H_to_current_figs)
                if isempty(findobj(H_to_current_figs(i), 'type', 'line'))
                    delete(H_to_current_figs(i)),
                end
            end
        end
    end

    function [h infig] = overobj2(varargin)
        infig = 1;
        % Ensure root units are pixels
        oldUnits = get(0,'units');set(0,'units','pixels');
        % Get the figure beneath the mouse pointer & mouse pointer pos
        fig = get(0,'PointerWindow'); 
        p = get(0,'PointerLocation');
        set(0,'units',oldUnits);
        
        % Look for quick exit (if mouse pointer is not over any figure)
        if fig==0,  
            h=[]; 
            %infig = 0 means that mouse is not over any matlab window, any.
            infig = 0;
            return;
        end
        
        % Compute figure offset of mouse pointer in pixels
        figPos = getpixelposition(fig);
        x = (p(1)-figPos(1));
        y = (p(2)-figPos(2));
        
        % Loop over all figure descendents
        c = findobj(get(fig,'Children'),varargin{:});
        %cc = get(findobj(get(fig,'Children'),varargin{:}), 'type')
        for h = c',
            % If descendent contains the mouse pointer position, exit
            try
                r = getpixelposition(h);
                if (x>r(1)) && (x<r(1)+r(3)) && (y>r(2)) && (y<r(2)+r(4))
                    return
                end
            catch
                %ignore error and look for axes object.
            end
        end
        h = [];
    end

    function close_callback(hObject,eventdata, outfig)
        mh = msgbox('This will perminantely remove the data.');
        waitfor(mh);
        delete(outfig);
    end
    function check_callback(hObject,eventdata, checkh, limz)
        if get(checkh, 'value')
            axis tight,
        else
            axis(limz),
        end
    end
    function excel_callback(hObject,eventdata, outfig)
        fig2xls_2(gcf),
    end
    function magnifyh_callback(hObject,eventdata, magnifyh)
        %NOTE: the set functions below, assures that the two functionality 
        %of magnification and drag and drop, won't interfere. i.e. when
        %magnification is enabled then drag and dropping is disabled and
        %vice versa. this is done by setting the buttondownfcn,
        %windowbuttondownfcn and windowbuttonupfcn accordingly at different
        %user request.
        if get(magnifyh, 'value')
            magnify(gcf),
            %findobj(gca, 'type', objecttype)=handle of line object in current axes.
            set(findobj(gca, 'type', objecttype),'ButtonDownFcn', '');
            set(magnifyh, 'string', 'Enable D&D', 'tooltipstring', 'Enable interactive Drag and Drop.'),
        else
            set(gcf, 'WindowButtonUpFcn', @dropObject, 'WindowButtonDownFcn', ''),
            set(findobj(gca, 'type', objecttype),'ButtonDownFcn',@button_down);
            set(magnifyh, 'string', 'Enable Magnification', 'tooltipstring', 'Enable Interactive magnification.'),
        end
    end

end

Contact us