Changeset 9290b1a in sasview for src/sas/qtgui/PlotterBase.py


Ignore:
Timestamp:
Dec 16, 2016 12:43:18 PM (7 years ago)
Author:
Piotr Rozyczko <rozyczko@…>
Branches:
ESS_GUI, ESS_GUI_Docs, ESS_GUI_batch_fitting, ESS_GUI_bumps_abstraction, ESS_GUI_iss1116, ESS_GUI_iss879, ESS_GUI_iss959, ESS_GUI_opencl, ESS_GUI_ordering, ESS_GUI_sync_sascalc
Children:
d3ca363
Parents:
0ba0774
Message:

Added AddText? to plot, enabled legend drag - SASVIEW-378

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/sas/qtgui/PlotterBase.py

    r27313b7 r9290b1a  
    11import pylab 
     2import numpy 
    23 
    34from PyQt4 import QtGui 
     
    1314 
    1415DEFAULT_CMAP = pylab.cm.jet 
     16from sas.sasgui.plottools.binder import BindArtist 
     17 
    1518from sas.qtgui.ScaleProperties import ScaleProperties 
    1619from sas.qtgui.WindowTitle import WindowTitle 
    1720import sas.qtgui.PlotHelper as PlotHelper 
     21import sas.qtgui.PlotUtilities as PlotUtilities 
    1822 
    1923class PlotterBase(QtGui.QWidget): 
     
    5357        self.y_label = "log10(y)" 
    5458 
     59        # Mouse click related 
     60        self.x_click = None 
     61        self.y_click = None 
     62        self.event_pos = None 
     63        self.leftdown = False 
     64        self.gotLegend = 0 
     65 
     66        # Annotations 
     67        self.selectedText = None 
     68        self.textList = [] 
     69 
    5570        # Pre-define the Scale properties dialog 
    5671        self.properties = ScaleProperties(self, 
     
    6681        self.ax = self.figure.add_subplot(self.current_plot) 
    6782 
     83        # Remove this, DAMMIT 
     84        self.axes = [self.ax] 
     85 
    6886        # Set the background color to white 
    6987        self.canvas.figure.set_facecolor('#FFFFFF') 
     88 
     89        # Canvas event handlers 
     90        self.canvas.mpl_connect('button_release_event', self.onMplMouseUp) 
     91        self.canvas.mpl_connect('button_press_event', self.onMplMouseDown) 
     92        self.canvas.mpl_connect('motion_notify_event', self.onMplMouseMotion) 
     93        self.canvas.mpl_connect('pick_event', self.onMplPick) 
     94        self.canvas.mpl_connect('scroll_event', self.onMplWheel) 
    7095 
    7196        if not quickplot: 
     
    166191        """ 
    167192        Define common context menu and associated actions for the MPL widget 
    168         TODO: move to plotter1d/plotter2d 
    169193        """ 
    170194        raise NotImplementedError("Context menu method must be implemented in derived class.") 
     
    180204        Display the context menu 
    181205        """ 
    182         self.contextMenu.exec_(self.canvas.mapToGlobal(event.pos())) 
     206        event_pos = event.pos() 
     207        self.contextMenu.exec_(self.canvas.mapToGlobal(event_pos)) 
     208 
     209    def onMplMouseDown(self, event): 
     210        """ 
     211        Left button down and ready to drag 
     212        """ 
     213        # Check that the LEFT button was pressed 
     214        if event.button == 1: 
     215            self.leftdown = True 
     216            ax = event.inaxes 
     217            for text in self.textList: 
     218                if text.contains(event)[0]: # If user has clicked on text 
     219                    self.selectedText = text 
     220                    return 
     221 
     222            if ax != None: 
     223                self.xInit, self.yInit = event.xdata, event.ydata 
     224                try: 
     225                    self.x_click = float(event.xdata)  # / size_x 
     226                    self.y_click = float(event.ydata)  # / size_y 
     227                except: 
     228                    self.position = None 
     229 
     230    def onMplMouseUp(self, event): 
     231        """ 
     232        Set the data coordinates of the click 
     233        """ 
     234        self.x_click = event.xdata 
     235        self.y_click = event.ydata 
     236 
     237        # Check that the LEFT button was released 
     238        if event.button == 1: 
     239            self.leftdown = False 
     240            #self.leftup = True 
     241            self.selectedText = None 
     242 
     243        #release the legend 
     244        if self.gotLegend == 1: 
     245            self.gotLegend = 0 
     246 
     247    def onMplMouseMotion(self, event): 
     248        """ 
     249        Check if the left button is press and the mouse in moving. 
     250        Compute delta for x and y coordinates and then perform the drag 
     251        """ 
     252        if self.gotLegend == 1 and self.leftdown: 
     253            self.onLegendMotion(event) 
     254            return 
     255 
     256        if self.leftdown and self.selectedText is not None: 
     257            # User has clicked on text and is dragging 
     258            ax = event.inaxes 
     259            if ax != None: 
     260                # Only move text if mouse is within axes 
     261                self.selectedText.set_position((event.xdata, event.ydata)) 
     262                self.canvas.draw_idle() 
     263            else: 
     264                # User has dragged outside of axes 
     265                self.selectedText = None 
     266            return 
     267 
     268    def onMplPick(self, event): 
     269        """ 
     270        On pick legend 
     271        """ 
     272        legend = self.legend 
     273        if event.artist == legend: 
     274            # Get the box of the legend. 
     275            bbox = self.legend.get_window_extent() 
     276            # Get mouse coordinates at time of pick. 
     277            self.mouse_x = event.mouseevent.x 
     278            self.mouse_y = event.mouseevent.y 
     279            # Get legend coordinates at time of pick. 
     280            self.legend_x = bbox.xmin 
     281            self.legend_y = bbox.ymin 
     282            # Indicate we picked up the legend. 
     283            self.gotLegend = 1 
     284 
     285            #self.legend.legendPatch.set_alpha(0.5) 
     286 
     287    def onLegendMotion(self, event): 
     288        """ 
     289        On legend in motion 
     290        """ 
     291        ax = event.inaxes 
     292        if ax == None: 
     293            return 
     294        # Event occurred inside a plotting area 
     295        lo_x, hi_x = ax.get_xlim() 
     296        lo_y, hi_y = ax.get_ylim() 
     297        # How much the mouse moved. 
     298        x = mouse_diff_x = self.mouse_x - event.x 
     299        y = mouse_diff_y = self.mouse_y - event.y 
     300        # Put back inside 
     301        if x < lo_x: 
     302            x = lo_x 
     303        if x > hi_x: 
     304            x = hi_x 
     305        if y < lo_y: 
     306            y = lo_y 
     307        if y > hi_y: 
     308            y = hi_y 
     309        # Move the legend from its previous location by that same amount 
     310        loc_in_canvas = self.legend_x - mouse_diff_x, \ 
     311                        self.legend_y - mouse_diff_y 
     312        # Transform into legend coordinate system 
     313        trans_axes = self.legend.parent.transAxes.inverted() 
     314        loc_in_norm_axes = trans_axes.transform_point(loc_in_canvas) 
     315        self.legend_pos_loc = tuple(loc_in_norm_axes) 
     316        self.legend._loc = self.legend_pos_loc 
     317        # self.canvas.draw() 
     318        self.canvas.draw_idle() 
     319 
     320    def onMplWheel(self, event): 
     321        """ 
     322        Process mouse wheel as zoom events 
     323        """ 
     324        ax = event.inaxes 
     325        step = event.step 
     326 
     327        if ax != None: 
     328            # Event occurred inside a plotting area 
     329            lo, hi = ax.get_xlim() 
     330            lo, hi = PlotUtilities.rescale(lo, hi, step, 
     331                              pt=event.xdata, scale=ax.get_xscale()) 
     332            if not self.xscale == 'log' or lo > 0: 
     333                self._scale_xlo = lo 
     334                self._scale_xhi = hi 
     335                ax.set_xlim((lo, hi)) 
     336 
     337            lo, hi = ax.get_ylim() 
     338            lo, hi = PlotUtilities.rescale(lo, hi, step, pt=event.ydata, 
     339                              scale=ax.get_yscale()) 
     340            if not self.yscale == 'log' or lo > 0: 
     341                self._scale_ylo = lo 
     342                self._scale_yhi = hi 
     343                ax.set_ylim((lo, hi)) 
     344        else: 
     345            # Check if zoom happens in the axes 
     346            xdata, ydata = None, None 
     347            x, y = event.x, event.y 
     348 
     349            for ax in self.axes: 
     350                insidex, _ = ax.xaxis.contains(event) 
     351                if insidex: 
     352                    xdata, _ = ax.transAxes.inverted().transform_point((x, y)) 
     353                insidey, _ = ax.yaxis.contains(event) 
     354                if insidey: 
     355                    _, ydata = ax.transAxes.inverted().transform_point((x, y)) 
     356            if xdata is not None: 
     357                lo, hi = ax.get_xlim() 
     358                lo, hi = PlotUtilities.rescale(lo, hi, step, 
     359                                  bal=xdata, scale=ax.get_xscale()) 
     360                if not self.xscale == 'log' or lo > 0: 
     361                    self._scale_xlo = lo 
     362                    self._scale_xhi = hi 
     363                    ax.set_xlim((lo, hi)) 
     364            if ydata is not None: 
     365                lo, hi = ax.get_ylim() 
     366                lo, hi = PlotUtilities.rescale(lo, hi, step, bal=ydata, 
     367                                  scale=ax.get_yscale()) 
     368                if not self.yscale == 'log' or lo > 0: 
     369                    self._scale_ylo = lo 
     370                    self._scale_yhi = hi 
     371                    ax.set_ylim((lo, hi)) 
     372        self.canvas.draw_idle() 
    183373 
    184374    def clean(self): 
Note: See TracChangeset for help on using the changeset viewer.