#Boa:Frame:Frame1

import wx

import matplotlib
matplotlib.interactive(True)
matplotlib.use('WXAgg')
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg
from matplotlib.figure import Figure

def create(parent):
    return Frame1(parent)

[wxID_FRAME1, wxID_FRAME1NOTEBOOK1, wxID_FRAME1PANEL1, 
] = [wx.NewId() for _init_ctrls in range(3)]

class PlotPanel(wx.Panel):    
    def __init__(self, parent,id = -1, color = None,\
        dpi = None, style = wx.NO_FULL_REPAINT_ON_RESIZE, **kwargs):
        self.gotLegend = 0  #to begin, legend is not picked.
        
        self.parent = parent
        self.line_collections_list = []

        wx.Panel.__init__(self, parent, **kwargs)
        
        self.figure = Figure(None, dpi)
        self.canvas = FigureCanvasWxAgg( self, -1, self.figure )

        #Connect all the mpl events
        self.canvas.mpl_connect('motion_notify_event', self.on_motion)
        self.canvas.mpl_connect('pick_event', self.on_pick)
        self.canvas.mpl_connect('button_release_event', self.on_release)

        self._SetInitialSize()
        
        self.Bind(wx.EVT_SIZE, self._onSize)

        self.draw()

    #a few sizing issues, not relevant to this draggable legend point.
    def _onSize(self, event):
        self._SetSize()
        event.Skip()
        
    def _SetSize( self ):
        pixels = tuple( self.GetClientSize() )
        self.SetSize( pixels )
        self.canvas.SetSize( pixels )
        self.figure.set_size_inches( float( pixels[0] )/self.figure.get_dpi(),
                                     float( pixels[1] )/self.figure.get_dpi() )
    
    def _SetInitialSize(self,):
        pixels = self.parent.GetClientSize()
        self.canvas.SetSize(pixels)
        self.figure.set_size_inches( (pixels[0])/self.figure.get_dpi(), 
         (pixels[1])/self.figure.get_dpi(), forward=True )
        
    def draw(self): 
        self.subplot = self.figure.add_subplot(111)
        line, = self.subplot.plot([1],[6],'o',picker=5) 
        if self.gotLegend == 0:  #need to prevent it from keep appending each time if it is just moving legend.
            self.line_collections_list.append(line)    
        
        #Legend.
        self.legend = self.subplot.legend(self.line_collections_list, ['1'], numpoints=1)
        self.legend.set_picker(self.my_legend_picker)
        
    #pick up the legend patch
    def my_legend_picker(self, legend, event): 
        return self.legend.legendPatch.contains(event)   
    
    #pick the legend
    def on_pick(self, event):    
        legend = self.legend
        if event.artist == legend:
            bbox = self.legend.get_window_extent()  #gets the box of the legend.
            self.mouse_x = event.mouseevent.x  #get mouse coordinates at time of pick.
            self.mouse_y = event.mouseevent.y
            print 'mouse x position at pick time', self.mouse_x
            print 'mouse y position at pick time', self.mouse_y
            self.legend_x = bbox.xmin          #get legend coordinates at time of pick.
            self.legend_y = bbox.ymin 
            print 'Legend x position @ pick time = ', self.legend_x
            print 'Legend y position @ pick time= ', self.legend_y
            self.gotLegend = 1  #indicates we picked up the legend.

    #drag the legend
    def on_motion(self, event):  
        if self.gotLegend == 1:
            x = mouse_diff_x = self.mouse_x - event.x  #how much the mouse moved.
            y = mouse_diff_y = self.mouse_y - event.y
            
            print 'motion_event.x =', event.x
            print 'motion_event.y =', event.y
            print 'mouse moved x = ', mouse_diff_x
            print 'mouse moved y = ', mouse_diff_y
            
            #move the legend from its previous location by that same amount
            loc_in_canvas = self.legend_x - mouse_diff_x, self.legend_y - mouse_diff_y
            #transform into legend coordinate system
            loc_in_norm_axes = self.legend.parent.transAxes.inverted().transform_point(loc_in_canvas)
            self.legend._loc = tuple(loc_in_norm_axes)
            
            self.canvas.draw()
        
    #release the legend    
    def on_release(self, event):
        if self.gotLegend == 1:
            self.gotLegend = 0
            print 'legend released'
            
class Frame1(wx.Frame):
    def _init_coll_boxSizer1_Items(self, parent):
        # generated method, don't edit

        parent.AddWindow(self.notebook1, 1, border=0, flag=wx.EXPAND)

    def _init_sizers(self):
        # generated method, don't edit
        self.boxSizer1 = wx.BoxSizer(orient=wx.VERTICAL)

        self._init_coll_boxSizer1_Items(self.boxSizer1)

        self.panel1.SetSizer(self.boxSizer1)

    def _init_ctrls(self, prnt):
        # generated method, don't edit
        wx.Frame.__init__(self, id=wxID_FRAME1, name='', parent=prnt,
              pos=wx.Point(333, 202), size=wx.Size(592, 474),
              style=wx.DEFAULT_FRAME_STYLE,
              title='moving the legend accurately')
        self.SetClientSize(wx.Size(584, 440))

        self.panel1 = wx.Panel(id=wxID_FRAME1PANEL1, name='panel1', parent=self,
              pos=wx.Point(0, 0), size=wx.Size(584, 440),
              style=wx.TAB_TRAVERSAL)

        self.notebook1 = wx.Notebook(id=wxID_FRAME1NOTEBOOK1, name='notebook1',
              parent=self.panel1, pos=wx.Point(0, 0), size=wx.Size(584, 440),
              style=0)

        self._init_sizers()

    def __init__(self, parent):
        self._init_ctrls(parent)
        graph = PlotPanel(self.notebook1)     
        self.notebook1.AddPage(graph,'graph')

if __name__ == '__main__':
    app = wx.PySimpleApp(1)  #set to wx.PySimpleApp() for no stdout window.
    frame = create(None)
    frame.Show()

    app.MainLoop()
