classdef polariMBTitle < internal.polariMouseBehavior
    
    methods
        function obj = polariMBTitle(locStr,isButtonDown)
            % locStr: 'top', 'bottom'
            % isButtonDown: true for the button-down mouse button behavior
            
            if strcmpi(locStr,'top')
                if nargin > 1 && isButtonDown
                    obj.InstallFcn  = @showToolTipAndPtr_titleDown;
                    obj.MotionEvent = @wbdrag_title;
                    obj.DownEvent   = [];
                    obj.UpEvent     = @(p,ev)wbup_title(p,ev,'top');
                    obj.ScrollEvent = [];
                else
                    obj.InstallFcn  = @showToolTipAndPtr_title;
                    obj.MotionEvent = @(p,ev)wbmotion_title(p,ev,'top');
                    obj.DownEvent   = @(p,ev)wbdown_title(p,ev,'top');
                    obj.UpEvent     = [];
                    obj.ScrollEvent = [];
                end
            else
                % 'bottom'
                if nargin > 1 && isButtonDown
                    obj.InstallFcn  = @showToolTipAndPtr_titleDown;
                    obj.MotionEvent = @wbdrag_title;
                    obj.DownEvent   = [];
                    obj.UpEvent     = @(p,ev)wbup_title(p,ev,'bottom');
                    obj.ScrollEvent = [];
                else
                    obj.InstallFcn  = @showToolTipAndPtr_title;
                    obj.MotionEvent = @(p,ev)wbmotion_title(p,ev,'bottom');
                    obj.DownEvent   = @(p,ev)wbdown_title(p,ev,'bottom');
                    obj.UpEvent     = [];
                    obj.ScrollEvent = [];
                end
            end
        end
    end
end

function wbmotion_title(p,ev,loc)
% Hovering over top or bottom title

s = computeHoverLocation(p,ev);
if p.ChangedState
    p.ChangedState = false;
    hoverOverTitle(p,loc,'start');
else
    % Check on a pending deferred change.  We might add a
    % pending change when graphically editing title text.  We
    % service this request when mouse next moves.
    executeDelayedParamChanges(p);
    
    if ~s.overTitleTop && ~s.overTitleBottom
        hoverOverTitle(p,loc,'stop');
        autoChangeMouseBehavior(p,s);
    end
end
end

function wbdown_title(p,ev,loc)
% Clicked on title
%
% Begin double-click or drag-and-drop change in title position.

isTop = strcmpi(loc,'top');
if isTop
    hWidget = p.hTitleTop;
else
    hWidget = p.hTitleBottom;
end

p.hFigure.CurrentPoint = ev.Point;
st = p.hFigure.SelectionType;
if strcmpi(st,'open')
    % double-click on title text
    %
    % Start edit mode
    hWidget.Editing = 'on';
    
    return
elseif strcmpi(st,'alt')
    % right-click: this action launches the context menu.
    %
    % Prevent further reaction to right-click here, so we don't
    % do any hilite and confuse the user when the context menu
    % launches.
    resetToolTip(p);
    return
end

% Install mouse pointer icon
setptr(p.hFigure,'uddrag');

% Get mouse coords before other work
ax = p.hAxes;
% xxx Could use hgconvertunits here
o = ax.Units;
ax.Units = 'normalized';
pt = p.hAxes.CurrentPoint;
ax.Units = o;

% Clicked on span readout for this polari instance.
% Get position, units are pixels for this uicontrol:
ci.isTop = isTop;
%ci.OrigPos = hWidget.Position(1:2);
ci.OrigPt = pt(1,1:2);

% One-time creation of event payload, with dummy location set
% to origin:
ci.EventData = internal.polariEvent([0 0]);

% Disable mouse in all other instances of polari within
% this figure
[ci.OtherPolariInstances, ci.OtherPolariPrevEna] = ...
    enableMouseInOtherInstances(p,false);

% Reuse the cache for span readout, since we're mutually
% exclusive with that:
p.SpanReadout_CacheInfo = ci;

if isTop
    changeMouseBehavior(p,'titletop_buttondown');
else
    changeMouseBehavior(p,'titlebottom_buttondown');
end
end

function wbdrag_title(p,ev)

% Drag span readout
%  - graphical updates to position

p.hFigure.CurrentPoint = ev.Point;
updateTitleOffset(p);
end

function wbup_title(p,ev,loc)

% Set point into axes:
p.hFigure.CurrentPoint = ev.Point;

% We're reusing span readout cache for title cache
ci = p.SpanReadout_CacheInfo;

% Set final offset, clear out temp variable
%
% Order matters here:
% - title will update when .Title*Offset changes
% - must set .pTitleOffset_Temp = 0 BEFORE Offset changes
% - must set Title*Offset to total in one shot
t = p.pTitleOffset_Temp;
p.pTitleOffset_Temp = 0;
if ci.isTop
    p.TitleTopOffset = p.TitleTopOffset + t;
else
    p.TitleBottomOffset = p.TitleBottomOffset + t;
end

% Enable mouse in all other instances of polari within
% this figure
%
% Get list of other instances from cache before clearing it.
% Removes need to recompute list.
enableMouseInOtherInstances(p,true, ...
    ci.OtherPolariInstances, ...
    ci.OtherPolariPrevEna);

% Clear out drag-cache, so we release marker handles etc
p.SpanReadout_CacheInfo = [];

% Update mouse handlers, and kick it once manually for mouse
% pointer updates etc:
%
% Check where mouse is to determine next step:
s = computeHoverLocation(p,ev);
if s.overTitleTop || s.overTitleBottom
    if s.overTitleTop
        changeMouseBehavior(p,'titletop');
    else
        changeMouseBehavior(p,'titlebottom');
    end
else
    % No longer hovering over a title
    hoverOverTitle(p,loc,'stop');
    autoChangeMouseBehavior(p,s);
end
end

function hoverOverTitle(p,loc,mode)
% Highlight selected title
%
% this is NOT "edit mode", it's just "hover select"
%
% loc: 'top','bottom'
% mode: 'start','stop'

if strcmpi(loc,'top')
    h = p.hTitleTop;
else
    h = p.hTitleBottom;
end
if strcmpi(mode,'start')
    h.EdgeColor = 'k';
else
    h.EdgeColor = 'none';
end
end

function updateTitleOffset(p)
% Change position of title offset interactively.
% Only for use during mouse drags.

hax = p.hAxes;
u = hax.Units;
hax.Units = 'normalized';
pt = hax.CurrentPoint; % in norm units, 0-1
ci = p.SpanReadout_CacheInfo;
tmp = pt(1,1:2) - ci.OrigPt; % points units
hax.Units = u;

% If bottom title is being dragged, reverse the sign
ydel = tmp(2); % change in mouse position, y-coord only
if ci.isTop
    place = 'top';
    off = p.TitleTopOffset;
else
    place = 'bottom';
    off = p.TitleBottomOffset;
    ydel = -ydel;  % correction needed for bottom
end

% Constrain total motion:
%  - half a radius distance from nominal
t = ydel + off;
t = max(-0.5,min(0.5,t));
ydel = t - off;

% Update title position
%
% - Adds pTitleOffset_Temp to offset during drags
% - Must call update manually as the _Temp property doesn't
%   trigger automatic updates
p.pTitleOffset_Temp = ydel;
updateTitlePos(p,place);
end

function showToolTipAndPtr_titleDown(p)
setptr(p.hFigure,'uddrag');
resetToolTip(p);
end

function showToolTipAndPtr_title(p)
setptr(p.hFigure,'hand');
if p.ToolTips && ~isempty(p.hToolTip) && isvalid(p.hToolTip)
    start(p.hToolTip, ...
        {'Drag to move, double-click to edit', ...
        '''k'' for keywords, ''+/-'' to change size'});
end
end
