1# Copyright (C) 2007 Jeremy S. Sanders 2# Email: Jeremy Sanders <jeremy@jeremysanders.net> 3# 4# This program is free software; you can redistribute it and/or modify 5# it under the terms of the GNU General Public License as published by 6# the Free Software Foundation; either version 2 of the License, or 7# (at your option) any later version. 8# 9# This program is distributed in the hope that it will be useful, 10# but WITHOUT ANY WARRANTY; without even the implied warranty of 11# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12# GNU General Public License for more details. 13# 14# You should have received a copy of the GNU General Public License along 15# with this program; if not, write to the Free Software Foundation, Inc., 16# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 17############################################################################## 18 19"""A colorbar widget for the image widget. Should show the scale of 20the image.""" 21 22from __future__ import division 23from .. import qtall as qt 24import numpy as N 25 26from .. import document 27from .. import setting 28from .. import utils 29from ..helpers import qtloops 30 31from . import widget 32from . import axis 33 34def _(text, disambiguation=None, context='ColorBar'): 35 """Translate text.""" 36 return qt.QCoreApplication.translate(context, text, disambiguation) 37 38class ColorBar(axis.Axis): 39 """Color bar for showing scale of image. 40 41 This naturally is descended from an axis 42 """ 43 44 typename='colorbar' 45 allowusercreation = True 46 description = _('Image color bar') 47 isaxis = False 48 49 @classmethod 50 def addSettings(klass, s): 51 """Construct list of settings.""" 52 axis.Axis.addSettings(s) 53 54 s.add( setting.WidgetChoice('widgetName', '', 55 descr=_('Corresponding widget'), 56 widgettypes=('image', 'xy', 'nonorthpoint'), 57 usertext = _('Widget')), 0 ) 58 59 s.get('log').readonly = True 60 s.get('datascale').readonly = True 61 62 s.add( setting.AlignHorzWManual( 'horzPosn', 63 'right', 64 descr = _('Horizontal position'), 65 usertext=_('Horz posn'), 66 formatting=True) ) 67 s.add( setting.AlignVertWManual( 'vertPosn', 68 'bottom', 69 descr = _('Vertical position'), 70 usertext=_('Vert posn'), 71 formatting=True) ) 72 s.add( setting.DistanceOrAuto('width', 'Auto', 73 descr = _('Width of colorbar'), 74 usertext=_('Width'), 75 formatting=True) ) 76 s.add( setting.DistanceOrAuto('height', 'Auto', 77 descr = _('Height of colorbar'), 78 usertext=_('Height'), 79 formatting=True) ) 80 81 s.add( setting.Float( 'horzManual', 82 0., 83 descr = _('Manual horizontal fractional position'), 84 usertext=_('Horz manual'), 85 formatting=True) ) 86 s.add( setting.Float( 'vertManual', 87 0., 88 descr = _('Manual vertical fractional position'), 89 usertext=_('Vert manual'), 90 formatting=True) ) 91 92 s.add( setting.Line('Border', descr = _('Colorbar border line'), 93 usertext=_('Border')), 94 pixmap='settings_border') 95 96 s.add( setting.SettingBackwardCompat('image', 'widgetName', None) ) 97 98 @classmethod 99 def allowedParentTypes(klass): 100 from . import graph, grid, nonorthgraph 101 return (graph.Graph, grid.Grid, nonorthgraph.NonOrthGraph) 102 103 @property 104 def userdescription(self): 105 return _("widget='%s', label='%s'") % ( 106 self.settings.widgetName, self.settings.label) 107 108 def chooseName(self): 109 """Get name of widget.""" 110 111 # override axis naming of x and y 112 return widget.Widget.chooseName(self) 113 114 def _axisDraw(self, posn, parentposn, outerbounds, painter, phelper): 115 """Do actual drawing.""" 116 117 s = self.settings 118 119 # get height of label font 120 bounds = self.computeBounds(parentposn, phelper) 121 122 font = s.get('Label').makeQFont(phelper) 123 painter.setFont(font) 124 fontheight = utils.FontMetrics(font, painter.device()).height() 125 126 horz = s.direction == 'horizontal' 127 128 # use above to estimate width and height if necessary 129 w = s.get('width') 130 if w.isAuto(): 131 if horz: 132 totalwidth = bounds[2] - bounds[0] - 2*fontheight 133 else: 134 totalwidth = fontheight 135 else: 136 totalwidth = w.convert(painter) 137 138 h = s.get('height') 139 if h.isAuto(): 140 if horz: 141 totalheight = fontheight 142 else: 143 totalheight = bounds[3] - bounds[1] - 2*fontheight 144 else: 145 totalheight = h.convert(painter) 146 147 # work out horizontal position 148 h = s.horzPosn 149 if h == 'left': 150 bounds[0] += fontheight 151 bounds[2] = bounds[0] + totalwidth 152 elif h == 'right': 153 bounds[2] -= fontheight 154 bounds[0] = bounds[2] - totalwidth 155 elif h == 'centre': 156 delta = (bounds[2]-bounds[0]-totalwidth)/2. 157 bounds[0] += delta 158 bounds[2] -= delta 159 elif h == 'manual': 160 bounds[0] += (bounds[2]-bounds[0])*s.horzManual 161 bounds[2] = bounds[0] + totalwidth 162 163 # work out vertical position 164 v = s.vertPosn 165 if v == 'top': 166 bounds[1] += fontheight 167 bounds[3] = bounds[1] + totalheight 168 elif v == 'bottom': 169 bounds[3] -= fontheight 170 bounds[1] = bounds[3] - totalheight 171 elif v == 'centre': 172 delta = (bounds[3]-bounds[1]-totalheight)/2. 173 bounds[1] += delta 174 bounds[3] -= delta 175 elif v == 'manual': 176 bounds[1] += (bounds[3]-bounds[1])*s.vertManual 177 bounds[3] = bounds[1] + totalheight 178 179 # FIXME: this is ugly - update bounds in helper state 180 phelper.states[(self,0)].bounds = bounds 181 182 # do no painting if hidden or no image 183 imgwidget = s.get('widgetName').findWidget() 184 if s.hide: 185 return bounds 186 187 self.updateAxisLocation(bounds) 188 189 # update image if necessary with new settings 190 if imgwidget is not None: 191 minval, maxval, axisscale, cmapname, trans, invert = \ 192 imgwidget.getColorbarParameters() 193 194 cmap = self.document.evaluate.getColormap(cmapname, invert) 195 196 img = utils.makeColorbarImage( 197 minval, maxval, axisscale, cmap, trans, 198 direction=s.direction) 199 else: 200 # couldn't find widget 201 minval, maxval, axisscale = 0., 1., 'linear' 202 img = None 203 204 s.get('log').setSilent(axisscale == 'log') 205 self.setAutoRange([minval, maxval]) 206 self.computePlottedRange(force=True) 207 208 # now draw image on axis... 209 minpix, maxpix = self.graphToPlotterCoords( 210 bounds, N.array([minval, maxval]) ) 211 212 routside = qt.QRectF( 213 bounds[0], bounds[1], 214 bounds[2]-bounds[0], bounds[3]-bounds[1] ) 215 216 # really draw the img 217 if img is not None: 218 # coordinates to draw image and to clip rectangle 219 if s.direction == 'horizontal': 220 c = [ minpix, bounds[1], maxpix, bounds[3] ] 221 cl = [ self.coordParr1, bounds[1], self.coordParr2, bounds[3] ] 222 else: 223 c = [ bounds[0], maxpix, bounds[2], minpix ] 224 cl = [ bounds[0], self.coordParr1, bounds[2], self.coordParr2 ] 225 r = qt.QRectF(c[0], c[1], c[2]-c[0], c[3]-c[1]) 226 rclip = qt.QRectF(cl[0], cl[1], cl[2]-cl[0], cl[3]-cl[1]) 227 228 painter.save() 229 painter.setClipRect(rclip & routside) 230 painter.drawImage(r, img) 231 #qtloops.plotImageAsRects(painter, r, img) 232 painter.restore() 233 234 # if there's a border 235 if not s.Border.hide: 236 painter.setPen( s.get('Border').makeQPen(painter) ) 237 painter.setBrush( qt.QBrush() ) 238 painter.drawRect( routside ) 239 240 # actually draw axis 241 axis.Axis._axisDraw(self, bounds, parentposn, None, painter, 242 phelper) 243 244# allow the factory to instantiate a colorbar 245document.thefactory.register( ColorBar ) 246