<s> import math <EOL> import IECore <EOL> import Gaffer <EOL> import GafferUI <EOL> QtGui = GafferUI . _qtImport ( "<STR_LIT>" ) <EOL> class NumericWidget ( GafferUI . TextWidget ) : <EOL> ValueChangedReason = IECore . Enum . create ( "<STR_LIT>" , "<STR_LIT>" , "<STR_LIT>" , "<STR_LIT>" , "<STR_LIT>" , "<STR_LIT>" , "<STR_LIT>" ) <EOL> def __init__ ( self , value , parenting = None ) : <EOL> GafferUI . TextWidget . __init__ ( self , "<STR_LIT>" , parenting = parenting ) <EOL> self . __dragValue = None <EOL> self . __dragStart = None <EOL> self . __keyPressConnection = self . keyPressSignal ( ) . connect ( Gaffer . WeakMethod ( self . __keyPress ) ) <EOL> self . __buttonPressConnection = self . buttonPressSignal ( ) . connect ( Gaffer . WeakMethod ( self . __buttonPress ) ) <EOL> self . __dragBeginConnection = self . dragBeginSignal ( ) . connect ( Gaffer . WeakMethod ( self . __dragBegin ) ) <EOL> self . __dragEnterConnection = self . dragEnterSignal ( ) . connect ( Gaffer . WeakMethod ( self . __dragEnter ) ) <EOL> self . __dragMoveConnection = self . dragMoveSignal ( ) . connect ( Gaffer . WeakMethod ( self . __dragMove ) ) <EOL> self . __dragEndConnection = self . dragEndSignal ( ) . connect ( Gaffer . WeakMethod ( self . __dragEnd ) ) <EOL> self . __editingFinishedConnection = self . editingFinishedSignal ( ) . connect ( Gaffer . WeakMethod ( self . __editingFinished ) ) <EOL> self . __numericType = None <EOL> self . setValue ( value ) <EOL> def setValue ( self , value ) : <EOL> self . __setValueInternal ( value , self . ValueChangedReason . SetValue ) <EOL> def getValue ( self ) : <EOL> return self . __numericType ( self . getText ( ) ) <EOL> def valueChangedSignal ( self ) : <EOL> try : <EOL> return self . __valueChangedSignal <EOL> except AttributeError : <EOL> self . __valueChangedSignal = Gaffer . Signal2 ( ) <EOL> return self . __valueChangedSignal <EOL> @ classmethod <EOL> def changesShouldBeMerged ( cls , firstReason , secondReason ) : <EOL> if type ( firstReason ) != type ( secondReason ) : <EOL> return False <EOL> return ( firstReason , secondReason ) in ( <EOL> ( cls . ValueChangedReason . DragBegin , cls . ValueChangedReason . DragMove ) , <EOL> ( cls . ValueChangedReason . DragMove , cls . ValueChangedReason . DragMove ) , <EOL> ( cls . ValueChangedReason . DragMove , cls . ValueChangedReason . DragEnd ) , <EOL> ( cls . ValueChangedReason . Increment , cls . ValueChangedReason . Increment ) , <EOL> ) <EOL> @ staticmethod <EOL> def valueToString ( value ) : <EOL> if type ( value ) is int : <EOL> return str ( value ) <EOL> else : <EOL> return ( "<STR_LIT>" % value ) . rstrip ( '<STR_LIT:0>' ) . rstrip ( '<STR_LIT:.>' ) <EOL> def __valueToString ( self , value ) : <EOL> return self . valueToString ( self . __numericType ( value ) ) <EOL> def __keyPress ( self , widget , event ) : <EOL> assert ( widget is self ) <EOL> if not self . getEditable ( ) : <EOL> return False <EOL> if event . key == "<STR_LIT>" : <EOL> self . __incrementIndex ( self . getCursorPosition ( ) , <NUM_LIT:1> ) <EOL> return True <EOL> elif event . key == "<STR_LIT>" : <EOL> self . __incrementIndex ( self . getCursorPosition ( ) , - <NUM_LIT:1> ) <EOL> return True <EOL> return False <EOL> def __incrementIndex ( self , index , increment ) : <EOL> text = self . getText ( ) <EOL> if '<STR_LIT:.>' in text : <EOL> decimalIndex = text . find ( "<STR_LIT:.>" ) <EOL> if decimalIndex >= index : <EOL> index += <NUM_LIT:1> <EOL> else : <EOL> decimalIndex = len ( text ) - <NUM_LIT:1> <EOL> powIndex = decimalIndex - index <EOL> value = self . __numericType ( text ) <EOL> value += increment * self . __numericType ( pow ( <NUM_LIT:10> , powIndex ) ) <EOL> self . __setValueInternal ( value , self . ValueChangedReason . Increment ) <EOL> newText = self . getText ( ) <EOL> oldLengthBefore , oldHasPeriod , oldLengthAfter = [ len ( item ) for item in text . lstrip ( "<STR_LIT:->" ) . partition ( "<STR_LIT:.>" ) ] <EOL> newLengthBefore , newHasPeriod , newLengthAfter = [ len ( item ) for item in newText . lstrip ( "<STR_LIT:->" ) . partition ( "<STR_LIT:.>" ) ] <EOL> headPadding = "<STR_LIT:0>" * max ( <NUM_LIT:0> , oldLengthBefore - newLengthBefore ) <EOL> tailPadding = "<STR_LIT:0>" * max ( <NUM_LIT:0> , oldLengthAfter - newLengthAfter ) <EOL> if not newHasPeriod and tailPadding : <EOL> tailPadding = "<STR_LIT:.>" + tailPadding <EOL> if newText [ <NUM_LIT:0> ] == "<STR_LIT:->" : <EOL> newText = "<STR_LIT:->" + headPadding + newText [ <NUM_LIT:1> : ] + tailPadding <EOL> else : <EOL> newText = headPadding + newText + tailPadding <EOL> self . setText ( newText ) <EOL> if '<STR_LIT:.>' in newText : <EOL> newDecimalIndex = newText . find ( "<STR_LIT:.>" ) <EOL> newIndex = newDecimalIndex - powIndex <EOL> if powIndex >= <NUM_LIT:0> : <EOL> newIndex -= <NUM_LIT:1> <EOL> else : <EOL> newIndex = len ( newText ) - <NUM_LIT:1> - powIndex <EOL> if newIndex < <NUM_LIT:0> : <EOL> newIndex = <NUM_LIT:0> <EOL> self . setCursorPosition ( newIndex ) <EOL> def __buttonPress ( self , widget , event ) : <EOL> if not self . getEditable ( ) : <EOL> return False <EOL> if event . buttons != GafferUI . ButtonEvent . Buttons . Left : <EOL> return False <EOL> if event . modifiers != GafferUI . ModifiableEvent . Modifiers . Control and event . modifiers != GafferUI . ModifiableEvent . Modifiers . ShiftControl : <EOL> return False <EOL> self . __dragValue = self . getValue ( ) <EOL> return True <EOL> def __dragBegin ( self , widget , event ) : <EOL> if self . __dragValue is None : <EOL> return None <EOL> self . __dragStart = event . line . p0 . x <EOL> return IECore . NullObject . defaultNullObject ( ) <EOL> def __dragEnter ( self , widget , event ) : <EOL> if event . sourceWidget is self and self . __dragStart is not None : <EOL> self . __setValueFromDrag ( event , self . ValueChangedReason . DragBegin ) <EOL> return True <EOL> return False <EOL> def __dragMove ( self , widget , event ) : <EOL> self . __setValueFromDrag ( event , self . ValueChangedReason . DragMove ) <EOL> return True <EOL> def __dragEnd ( self , widget , event ) : <EOL> self . __setValueFromDrag ( event , self . ValueChangedReason . DragEnd ) <EOL> self . __dragValue = None <EOL> self . __dragStart = None <EOL> return True <EOL> def __setValueFromDrag ( self , event , reason ) : <EOL> move = event . line . p0 . x - self . __dragStart <EOL> offset = <NUM_LIT:0> <EOL> if event . modifiers == GafferUI . ModifiableEvent . Modifiers . Control : <EOL> offset = <NUM_LIT> * move <EOL> elif event . modifiers == GafferUI . ModifiableEvent . Modifiers . ShiftControl : <EOL> offset = <NUM_LIT> * math . pow ( move , <NUM_LIT:3> ) <EOL> newValue = self . __numericType ( float ( self . __dragValue ) + offset ) <EOL> self . __setValueInternal ( newValue , reason ) <EOL> def __editingFinished ( self , widget ) : <EOL> assert ( widget is self ) <EOL> self . setText ( self . __valueToString ( self . getValue ( ) ) ) <EOL> self . __emitValueChanged ( self . ValueChangedReason . Edit ) <EOL> def __setValueInternal ( self , value , reason ) : <EOL> numericType = type ( value ) <EOL> assert ( numericType is int or numericType is float ) <EOL> if self . __numericType is not numericType : <EOL> self . __numericType = numericType <EOL> if self . __numericType is int : <EOL> validator = QtGui . QIntValidator ( self . _qtWidget ( ) ) <EOL> else : <EOL> validator = QtGui . QDoubleValidator ( self . _qtWidget ( ) ) <EOL> validator . setDecimals ( <NUM_LIT:4> ) <EOL> validator . setNotation ( QtGui . QDoubleValidator . StandardNotation ) <EOL> self . _qtWidget ( ) . setValidator ( validator ) <EOL> text = self . __valueToString ( value ) <EOL> dragBeginOrEnd = reason in ( self . ValueChangedReason . DragBegin , self . ValueChangedReason . DragEnd ) <EOL> if text == self . getText ( ) and not dragBeginOrEnd : <EOL> return <EOL> self . setText ( text ) <EOL> self . __emitValueChanged ( reason ) <EOL> def __emitValueChanged ( self , reason ) : <EOL> try : <EOL> signal = self . __valueChangedSignal <EOL> except AttributeError : <EOL> return <EOL> signal ( self , reason ) </s>
