dabo Commit
Revision 6960
Date: 2011-11-04 05:16:02 -0700 (Fri, 04 Nov 2011)
Author: Jacekk
Trac: http://trac.dabodev.com/changeset/6960
Changed:
U trunk/dabo/ui/uiwx/__init__.py
A trunk/dabo/ui/uiwx/dNumericBox.py
Log:
Added specialized dNumericBox control class for handling numeric data types.
Diff:
Modified: trunk/dabo/ui/uiwx/__init__.py
===================================================================
--- trunk/dabo/ui/uiwx/__init__.py 2011-11-01 20:30:21 UTC (rev 6959)
+++ trunk/dabo/ui/uiwx/__init__.py 2011-11-04 12:16:02 UTC (rev 6960)
@@ -141,6 +141,7 @@
from dListControl import dListControl
from dBaseMenuBar import dBaseMenuBar
from dMaskedTextBox import dMaskedTextBox
+from dNumericBox import dNumericBox
try:
from dMediaControl import dMediaControl
except ImportError:
Added: trunk/dabo/ui/uiwx/dNumericBox.py
===================================================================
--- trunk/dabo/ui/uiwx/dNumericBox.py (rev 0)
+++ trunk/dabo/ui/uiwx/dNumericBox.py 2011-11-04 12:16:02 UTC (rev 6960)
@@ -0,0 +1,390 @@
+# -*- coding: utf-8 -*-
+import locale
+import decimal
+import wx
+import wx.lib.masked as masked
+import dabo
+if __name__ == "__main__":
+ dabo.ui.loadUI("wx")
+import dabo.dEvents as dEvents
+import dabo.dColors as dColors
+import dTextBoxMixin as dtbm
+import dDataControlMixin as ddcm
+from types import NoneType
+from dabo.ui import makeDynamicProperty
+from dabo.dLocalize import _
+
+
+class dNumericBox(dtbm.dTextBoxMixin, masked.NumCtrl):
+ """This is a specialized textbox class that maintains numeric values."""
+
+ def __init__(self, parent, properties=None, attProperties=None, *args,
**kwargs):
+ localeData = locale.localeconv()
+ enc = locale.getdefaultlocale()[1]
+ self._baseClass = dNumericBox
+ kwargs["integerWidth"] = self._extractKey((properties,
attProperties, kwargs),
+ "IntegerWidth", 10)
+ kwargs["fractionWidth"] = self._extractKey((properties,
attProperties, kwargs),
+ "DecimalWidth", 2)
+ kwargs["Alignment"] = self._extractKey((properties,
attProperties, kwargs),
+ "Alignment", "Right")
+ kwargs["selectOnEntry"] = self._extractKey((properties,
attProperties, kwargs),
+ "SelectOnEntry", self.SelectOnEntry)
+ groupChar = self._extractKey((properties, attProperties,
kwargs),
+ "GroupChar",
localeData["thousands_sep"].decode(enc))
+ # Group char can't be empty string.
+ if groupChar or groupChar >= " ":
+ kwargs["groupChar"] = groupChar
+ kwargs["groupDigits"] = True
+ else:
+ kwargs["groupChar"] = " "
+ kwargs["groupDigits"] = False
+ kwargs["autoSize"] = self._extractKey((properties,
attProperties, kwargs),
+ "AutoWidth", True)
+ kwargs["allowNegative"] = self._extractKey((properties,
attProperties, kwargs),
+ "AllowNegative", True)
+ kwargs["useParensForNegatives"] = self._extractKey((properties,
attProperties, kwargs),
+ "ParensForNegatives", False)
+ kwargs["decimalChar"] = self._extractKey((properties,
attProperties, kwargs),
+ "DecimalChar",
localeData["decimal_point"].decode(enc))
+ kwargs["foregroundColour"] = self._extractKey((properties,
attProperties, kwargs),
+ "ForeColor", "Black")
+ kwargs["validBackgroundColour"] = self._extractKey((properties,
attProperties, kwargs),
+ "BackColor",
wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOW))
+ kwargs["invalidBackgroundColour"] =
self._extractKey((properties, attProperties, kwargs),
+ "InvalidBackColor", "Yellow")
+ kwargs["signedForegroundColour"] =
self._extractKey((properties, attProperties, kwargs),
+ "SignedForeColor", "Red")
+ kwargs["allowNone"] = self._extractKey((properties,
attProperties, kwargs),
+ "AllowNoneValue", False)
+ kwargs["max"] = self._extractKey((properties, attProperties,
kwargs),
+ "MaxValue", None)
+ kwargs["min"] = self._extractKey((properties, attProperties,
kwargs),
+ "MinValue", None)
+ # Base class 'limited' property is inconvenient.
+ kwargs["limited"] = False
+ fontFace = self._extractKey((properties, attProperties,
kwargs), "FontFace", "")
+ if not fontFace and self.Application.Platform in ("Win",):
+ fontFace = "Tahoma"
+ if fontFace:
+ kwargs["FontFace"] = fontFace
+ dtbm.dTextBoxMixin.__init__(self, masked.NumCtrl, parent,
properties,
+ attProperties, *args, **kwargs)
+
+ #--- Public interface.
+
+ def flushValue(self):
+ # Because dTextBoxMixin method is improper here,
+ # we use superclass method instead.
+ return ddcm.dDataControlMixin.flushValue(self)
+
+ def getBlankValue(self):
+ dec = self.DecimalWidth
+ if dec > 0:
+ return decimal.Decimal("0.%s" % ("0" * dec))
+ else:
+ return 0
+
+ def GetParensForNegatives(self):
+ return self._useParensForNegatives
+
+ def update(self):
+ # Be very careful! If limits across allowed value,
+ # control value will be automatically reseted to default value.
+ maxVal = self.MaxValue
+ self.MaxValue = None
+ minVal = self.MinValue
+ self.MinValue = None
+ super(dNumericBox, self).update()
+ if not "MaxValue" in self._dynamic:
+ self.MaxValue = maxVal
+ if not "MinValue" in self._dynamic:
+ self.MinValue = minVal
+
+ #--- Internal class interface.
+
+ def _initEvents(self):
+ super(dNumericBox, self)._initEvents()
+ self.bindEvent(dEvents.GotFocus, self._onGotFocusFix)
+ self.bindEvent(dEvents.LostFocus, self._onLostFocusFix)
+
+ def _onGotFocusFix(self, evt):
+ dabo.ui.callAfter(self._fixInsertionPoint)
+
+
+ def _onLostFocusFix(self, evt):
+ if self.LimitValue:
+ max = self.MaxValue
+ min = self.MinValue
+ #if (max is not None and not (max >= self._value)) or \
+ # (min is not None and not (self._value
>= min)):
+ # evt.stop()
+ # self.setFocus()
+
+ def _onWxHit(self, evt, *args, **kwargs):
+ # This fix wx masked controls issue firing multiple EVT_TEXT
events.
+ if self._value != self.Value:
+ super(dNumericBox, self)._onWxHit(evt, *args, **kwargs)
+
+ def _fixInsertionPoint(self):
+ """Fixes insertion point position when value change or
+ when getting focus with mouse click."""
+ if self.Enabled and not self.ReadOnly:
+ dw = self.DecimalWidth
+ if dw > 0:
+ self.InsertionPoint = self._masklength - dw - 1
+ else:
+ self.InsertionPoint = self._masklength
+ if self.SelectOnEntry:
+ dabo.ui.callAfter(self.select, 0,
self.InsertionPoint)
+
+ #--- Properties methods.
+
+ def _getGroupChar(self):
+ if self.GetGroupDigits():
+ ret = self.GetGroupChar()
+ else:
+ ret = None
+ return ret
+
+ def _setGroupChar(self, val):
+ """Set GroupChar to None to avoid grouping."""
+ if self._constructed():
+ if val is None:
+ self.SetGroupDigits(False)
+ else:
+ self.SetGroupChar(val)
+ self.SetGroupDigits(True)
+ else:
+ self._properties["GroupChar"] = val
+
+ def _getAllowNegative(self):
+ return self.GetAllowNegative()
+
+ def _setAllowNegative(self, val):
+ if self._constructed():
+ self.SetAllowNegative(val)
+ else:
+ self._properties["AllowNegative"] = val
+
+ def _getAllowNoneValue(self):
+ return self.GetAllowNone()
+
+ def _setAllowNoneValue(self, val):
+ if self._constructed():
+ self.SetAllowNone(val)
+ else:
+ self._properties["AllowNoneValue"] = val
+
+ def _getAutoWidth(self):
+ return self.GetAutoSize()
+
+ def _setAutoWidth(self, val):
+ if self._constructed():
+ self.SetAutoSize(val)
+ else:
+ self._properties["AutoWidth"] = val
+
+ def _getLimitValue(self):
+ return getattr(self, "_limitValue", False)
+
+
+ def _setLimitValue(self, val):
+ self._limitValue = bool(val)
+
+ def _getMinValue(self):
+ val = self.GetMin()
+ if val is not None and self._lastDataType is decimal.Decimal:
+ val = decimal.Decimal(str(val))
+ return val
+
+ def _setMinValue(self, val):
+ if self._constructed():
+ if isinstance(val, decimal.Decimal):
+ val = float(val)
+ self.SetMin(val)
+ else:
+ self._properties["MinValue"] = val
+
+ def _getMaxValue(self):
+ val = self.GetMax()
+ if val is not None and self._lastDataType is decimal.Decimal:
+ val = decimal.Decimal(str(val))
+ return val
+
+ def _setMaxValue(self, val):
+ if self._constructed():
+ if isinstance(val, decimal.Decimal):
+ val = float(val)
+ self.SetMax(val)
+ else:
+ self._properties["MaxValue"] = val
+
+ def _getIntegerWidth(self):
+ return self.GetIntegerWidth()
+
+ def _setIntegerWidth(self, val):
+ if self._constructed():
+ self.SetIntegerWidth(val)
+ else:
+ self._properties["IntegerWidth"] = val
+
+ def _getInvalidBackColor(self):
+ return self.GetInvalidBackgroundColour()
+
+ def _setInvalidBackColor(self, val):
+ if self._constructed():
+ self.SetInvalidBackgroundColour(val)
+ else:
+ self._properties["InvalidBackColor"] = val
+
+ def _getDecimalChar(self):
+ return self.GetDecimalChar()
+
+ def _setDecimalChar(self, val):
+ if self._constructed():
+ self.SetDecimalChar(val)
+ else:
+ self._properties["DecimalChar"] = val
+
+ def _getDecimalWidth(self):
+ return self.GetFractionWidth()
+
+ def _setDecimalWidth(self, val):
+ if self._constructed():
+ self.SetFractionWidth(val)
+ else:
+ self._properties["DecimalWidth"] = val
+
+ def _getParensForNegatives(self):
+ return self.GetUseParensForNegatives()
+
+ def _setParensForNegatives(self, val):
+ if self._constructed():
+ self.SetUseParensForNegatives(val)
+ else:
+ self._properties["ParensForNegatives"] = val
+
+ def _getSignedForeColor(self):
+ return self.GetSignedForegroundColour()
+
+ def _setSignedForeColor(self, val):
+ if self._constructed():
+ self.SetSignedForegroundColour(val)
+ else:
+ self._properties["SignedForeColor"] = val
+
+ def _getValue(self):
+ val = ddcm.dDataControlMixin._getValue(self)
+ if self._lastDataType is decimal.Decimal:
+ val = decimal.Decimal(str(val))
+ elif self._lastDataType is NoneType:
+ chkVal = int(val)
+ if chkVal <> val:
+ val = decimal.Decimal(str(val))
+ elif chkVal <> 0:
+ val = chkVal
+ else:
+ val = None
+ return val
+
+ def _setValue(self, val):
+ self._lastDataType = type(val)
+ if self._lastDataType is decimal.Decimal:
+ val = float(val)
+ elif val is None:
+ val = float(0)
+ ddcm.dDataControlMixin._setValue(self, val)
+ dabo.ui.callAfter(self._fixInsertionPoint)
+
+ def _getSelectOnEntry(self):
+ try:
+ return self.GetSelectOnEntry()
+ except AttributeError:
+ return False
+
+ def _setSelectOnEntry(self, val):
+ self.SetSelectOnEntry(bool(val))
+
+ #--- Properties definitions.
+
+ AllowNegative = property(_getAllowNegative, _setAllowNegative, None,
+ _("""Enables/disables negative numbers. (bool)
+ Default=True"""))
+
+ AllowNoneValue = property(_getAllowNoneValue, _setAllowNoneValue, None,
+ _("""Enables/disables undefined value - None. (bool)
+ Default=False"""))
+
+ AutoWidth = property(_getAutoWidth, _setAutoWidth, None,
+ _("""Indicates whether or not the control should set
its own
+ width based on the integer and fraction widths. (bool)
+ Default=True"""))
+
+ DecimalChar = property(_getDecimalChar, _setDecimalChar, None,
+ _("""Defines character that will be used to represent
+ the decimal point. (str)
+ Default value comes from locale setting."""))
+
+ DecimalWidth = property(_getDecimalWidth, _setDecimalWidth, None,
+ _("""Tells how many decimal places to show for numeric
value. (int)
+ Default=2"""))
+
+ GroupChar = property(_getGroupChar, _setGroupChar, None,
+ _("""What grouping character will be used if allowed.
+ If set to None, no grouping is allowed. (str)
+ Default value comes from locale setting."""))
+
+ IntegerWidth = property(_getIntegerWidth, _setIntegerWidth, None,
+ _("""Indicates how many places to the right of any
decimal point
+ should be allowed in the control. (int)
+ Default=10"""))
+
+ InvalidBackColor = property(_getInvalidBackColor, _setInvalidBackColor,
None,
+ _("""Color value used for illegal values or values
+ out-of-bounds. (str)
+ Default='Yellow'"""))
+
+ LimitValue = property(_getLimitValue, _setLimitValue, None,
+ _("""Limit control value to Min and Max bounds. When
set to True,
+ if invalid, will be automatically reseted to default.
+ When False, only background color will change. (bool)
+ Default=False"""))
+
+ MaxValue = property(_getMaxValue, _setMaxValue, None,
+ _("""The maximum value that the control should allow.
+ Set to None if limit is disabled. (int, decimal)
+ Default=None"""))
+
+ MinValue = property(_getMinValue, _setMinValue, None,
+ _("""The minimum value that the control should allow.
+ Set to None if limit is disabled. (int, decimal)
+ Default=None"""))
+
+ ParensForNegatives = property(_getParensForNegatives,
_setParensForNegatives, None,
+ _("""If true, this will cause negative numbers to be
displayed with parens
+ rather than with sign mark. (bool)
+ Default=False"""))
+
+ SelectOnEntry = property(_getSelectOnEntry, _setSelectOnEntry, None,
+ _("""Specifies whether all text gets selected upon
receiving focus. (bool)
+ Default=False"""))
+
+ SignedForeColor = property(_getSignedForeColor, _setSignedForeColor,
None,
+ _("""Color value used for negative values of the
control. (str)
+ Default='Red'"""))
+
+ Value = property(_getValue, _setValue, None,
+ _("""Specifies the current state of the control (the
value of the field).
+ (int, Decimal)"""))
+
+ DynamicMaxValue = makeDynamicProperty(MaxValue)
+ DynamicMinValue = makeDynamicProperty(MinValue)
+
+
+if __name__ == "__main__":
+ import test
+
+ class _dNumericBoxTest(dNumericBox): pass
+
+ test.Test().runTest(_dNumericBoxTest)
_______________________________________________
Post Messages to: [email protected]
Subscription Maintenance: http://leafe.com/mailman/listinfo/dabo-dev
Searchable Archives: http://leafe.com/archives/search/dabo-dev
This message:
http://leafe.com/archives/byMID/[email protected]