B
    ]t\2                 @   s   d Z ddlZddlmZ ddlmZ ddlmZ ddlm	Z
 G dd deZG dd deZG dd	 d	eZG d
d deZdS )z
`ToolManager`
    Class that makes the bridge between user interaction (key press,
    toolbar clicks, ..) and the actions in response to the user inputs.
    N)validate_stringlistc               @   s   e Zd ZdZdddZdS )	ToolEventz(Event for tool manipulation (add/remove)Nc             C   s   || _ || _|| _|| _d S )N)namesendertooldata)selfr   r   r   r    r	   :lib/python3.7/site-packages/matplotlib/backend_managers.py__init__   s    zToolEvent.__init__)N)__name__
__module____qualname____doc__r   r	   r	   r	   r
   r      s   r   c               @   s   e Zd ZdZdddZdS )ToolTriggerEventz.Event to inform that a tool has been triggeredNc             C   s   t | |||| || _d S )N)r   r   canvasevent)r   r   r   r   r   r   r	   r	   r
   r      s    zToolTriggerEvent.__init__)NN)r   r   r   r   r   r	   r	   r	   r
   r      s   r   c               @   s   e Zd ZdZdd ZdS )ToolManagerMessageEventzq
    Event carrying messages from toolmanager

    Messages usually get displayed to the user by the toolbar
    c             C   s   || _ || _|| _d S )N)r   r   message)r   r   r   r   r	   r	   r
   r   %   s    z ToolManagerMessageEvent.__init__N)r   r   r   r   r   r	   r	   r	   r
   r      s   r   c               @   s   e Zd ZdZd/ddZedd Zedd Zejd	d Zd0ddZ	dd Z
dd Zd1ddZedd Zdd Zdd Zdd Zdd Zdd Zdd  Zd!d" Zd#d$ Zd2d%d&Zd3d'd(Zd)d* Zed+d, Zd4d-d.ZdS )5ToolManageraZ  
    Helper class that groups all the user interactions for a Figure.

    Attributes
    ----------
    figure: `Figure`
    keypresslock: `widgets.LockDraw`
        `LockDraw` object to know if the `canvas` key_press_event is locked
    messagelock: `widgets.LockDraw`
        `LockDraw` object to know if the message is available to write
    Nc             C   sT   t d d | _i | _i | _i | _t | _t	
 | _t	
 | _d | _| | d S )NzTreat the new Tool classes introduced in v1.5 as experimental for now, the API will likely change in version 2.1 and perhaps the rcParam as well)warningswarn_key_press_handler_id_tools_keys_toggledcbookZCallbackRegistry
_callbackswidgetsZLockDrawkeypresslockZmessagelock_figure
set_figure)r   figurer	   r	   r
   r   8   s    


zToolManager.__init__c             C   s   | j s
dS | j jS )zCanvas managed by FigureManagerN)r   canvas)r   r	   r	   r
   r"   K   s    zToolManager.canvasc             C   s   | j S )zFigure that holds the canvas)r   )r   r	   r	   r
   r!   R   s    zToolManager.figurec             C   s   |  | d S )N)r    )r   r!   r	   r	   r
   r!   W   s    Tc             C   sR   | j r| j| j  || _|r0| jd| j| _ |rNx| j D ]
}||_q@W dS )z
        Bind the given figure to the tools.

        Parameters
        ----------
        figure : `.Figure`
        update_tools : bool
            Force tools to update figure
        Zkey_press_eventN)	r   r"   Zmpl_disconnectr   Zmpl_connect
_key_pressr   valuesr!   )r   r!   Zupdate_toolsr   r	   r	   r
   r    [   s    
zToolManager.set_figurec             C   s   | j ||S )a%  
        Connect event with string *s* to *func*.

        Parameters
        ----------
        s : String
            Name of the event

            The following events are recognized

            - 'tool_message_event'
            - 'tool_removed_event'
            - 'tool_added_event'

            For every tool added a new event is created

            - 'tool_trigger_TOOLNAME`
              Where TOOLNAME is the id of the tool.

        func : function
            Function to be called with signature
            def func(event)
        )r   Zconnect)r   sfuncr	   r	   r
   toolmanager_connecto   s    zToolManager.toolmanager_connectc             C   s   | j |S )a  
        Disconnect callback id *cid*

        Example usage::

            cid = toolmanager.toolmanager_connect('tool_trigger_zoom',
                                                  on_press)
            #...later
            toolmanager.toolmanager_disconnect(cid)
        )r   Z
disconnect)r   Zcidr	   r	   r
   toolmanager_disconnect   s    z"ToolManager.toolmanager_disconnectc             C   s.   |dkr| }d}t |||}| j|| dS )z! Emit a `ToolManagerMessageEvent`NZtool_message_event)r   r   process)r   r   r   r%   eventr	   r	   r
   message_event   s
    zToolManager.message_eventc             C   s   | j S )zCurrently toggled tools)r   )r   r	   r	   r
   active_toggle   s    zToolManager.active_togglec                s    fdd| j  D }|S )z
        Get the keymap associated with the specified tool

        Parameters
        ----------
        name : string
            Name of the Tool

        Returns
        -------
        list : list of keys associated with the Tool
        c                s   g | ]\}}| kr|qS r	   r	   ).0ki)r   r	   r
   
<listcomp>   s    z/ToolManager.get_tool_keymap.<locals>.<listcomp>)r   items)r   r   keysr	   )r   r
   get_tool_keymap   s    zToolManager.get_tool_keymapc             C   s    x|  |D ]}| j|= qW d S )N)r3   r   )r   r   r.   r	   r	   r
   _remove_keys   s    zToolManager._remove_keysc             G   sr   || j krtd| | | xL|D ]D}x>t|D ]2}|| jkr\td|| j| |f  || j|< q4W q&W dS )z
        Set the keymap to associate with the specified tool

        Parameters
        ----------
        name : string
            Name of the Tool
        keys : keys to associate with the Tool
        z%s not in ToolszKey %s changed from %s to %sN)r   KeyErrorr4   r   r   r   r   )r   r   r2   keyr.   r	   r	   r
   update_keymap   s    



zToolManager.update_keymapc             C   s^   |  |}|  t|ddr*| |d | | d}t|| |}| j|| | j|= dS )z
        Remove tool from `ToolManager`

        Parameters
        ----------
        name : string
            Name of the Tool
        toggledFZtoolmanagerZtool_removed_eventN)	get_toolZdestroygetattrtrigger_toolr4   r   r   r)   r   )r   r   r   r%   r*   r	   r	   r
   remove_tool   s    


zToolManager.remove_toolc             O   s   |  |}|stdt| || jkr<td | j| S || |f||}|| j|< |jdk	rp| ||j t|t	j
r|jdkr| jdt  n| j|jd |jr| |ddd || j | | |S )a  
        Add *tool* to `ToolManager`

        If successful adds a new event `tool_trigger_name` where **name** is
        the **name** of the tool, this event is fired everytime
        the tool is triggered.

        Parameters
        ----------
        name : str
            Name of the tool, treated as the ID, has to be unique
        tool : class_like, i.e. str or type
            Reference to find the class of the Tool to added.

        Notes
        -----
        args and kwargs get passed directly to the tools constructor.

        See Also
        --------
        matplotlib.backend_tools.ToolBase : The base class for tools.
        zImpossible to find class for %sz;A "Tool class" with the same name already exists, not addedN)_get_cls_to_instantiate
ValueErrorstrr   r   r   Zdefault_keymapr7   
isinstancetoolsToolToggleBaseradio_groupr   
setdefaultsetr8   _handle_toggler    r!   _tool_added_event)r   r   r   argskwargsZtool_clsZtool_objr	   r	   r
   add_tool   s&    







zToolManager.add_toolc             C   s"   d}t || |}| j|| d S )NZtool_added_event)r   r   r)   )r   r   r%   r*   r	   r	   r
   rG   "  s    zToolManager._tool_added_eventc             C   s   |j }|dkrH|j| jd kr2| jd |j n| jd |j dS | j| |jkr^d}n2| j| dkrt|j}n| | j| | || |j}|| j|< dS )a  
        Toggle tools, need to untoggle prior to using other Toggle tool
        Called from trigger_tool

        Parameters
        ----------
        tool: Tool object
        sender: object
            Object that wishes to trigger the tool
        canvasevent : Event
            Original Canvas event or None
        data : Object
            Extra data to pass to the tool when triggering
        N)rC   r   r   removeaddr;   )r   r   r   r   r   rC   r8   r	   r	   r
   rF   '  s     zToolManager._handle_togglec             C   sZ   t |trF|t kr t | }n&d}t|t t |gd}t||d}t|rR|S d S d S )Nbackend_tools   F)r@   r?   globals
__import__localsr:   callable)r   Zcallback_classmodZcurrent_moduler	   r	   r
   r=   T  s    

z#ToolManager._get_cls_to_instantiatec             C   s\   |  |}|dkrdS |dkr"| }| |||| d| }t|||||}| j|| dS )a  
        Trigger a tool and emit the tool_trigger_[name] event

        Parameters
        ----------
        name : string
            Name of the tool
        sender: object
            Object that wishes to trigger the tool
        canvasevent : Event
            Original Canvas event or None
        data : Object
            Extra data to pass to the tool when triggering
        Nztool_trigger_%s)r9   _trigger_toolr   r   r)   )r   r   r   r   r   r   r%   r*   r	   r	   r
   r;   e  s    
zToolManager.trigger_toolc             C   s8   |  |}t|tjr&| |||| |||| dS )zP
        Trigger on a tool

        Method to actually trigger the tool
        N)r9   r@   rA   rB   rF   Ztrigger)r   r   r   r   r   r   r	   r	   r
   rT     s    
zToolManager._trigger_toolc             C   sF   |j d ks| j rd S | j|j d }|d kr4d S | j||d d S )N)r   )r6   r   lockedr   getr;   )r   r*   r   r	   r	   r
   r#     s    zToolManager._key_pressc             C   s   | j S )z,Return the tools controlled by `ToolManager`)r   )r   r	   r	   r
   rA     s    zToolManager.toolsc             C   sF   t |tjr|j| jkr|S || jkr<|r8td|  dS | j| S )a  
        Return the tool object, also accepts the actual tool for convenience

        Parameters
        ----------
        name : str, ToolBase
            Name of the tool, or the tool itself
        warn : bool, optional
            If this method should give warnings.
        z$ToolManager does not control tool %sN)r@   rA   ZToolBaser   r   r   r   )r   r   r   r	   r	   r
   r9     s    
zToolManager.get_tool)N)T)N)NNN)NNN)T)r   r   r   r   r   propertyr"   r!   setterr    r'   r(   r+   r,   r3   r4   r7   r<   rJ   rG   rF   r=   r;   rT   r#   rA   r9   r	   r	   r	   r
   r   +   s0   


	8- 

	r   )r   r   Zmatplotlib.cbookr   Zmatplotlib.widgetsr   Zmatplotlib.rcsetupr   Zmatplotlib.backend_toolsrM   rA   objectr   r   r   r   r	   r	   r	   r
   <module>   s   	