[wxPython-users] Many Similar Dialogs For Date Entry

Christopher Barker Chris.Barker at noaa.gov
Thu Feb 1 16:21:59 PST 2007


Rich,

>   Rather than re-inventing the wheel, and having it out of round, =


always a good idea!

> Creating 18 classes, each slightly different from the others is inelegant
> and prone to be a maintenance nightmare. I suppose that one base class wi=
th
> the others inheriting from it might work

yes, that's what OO is about.

However, if what you are looking for is 18 slightly different Panels for =

entering the data, then subclassing could help, but would be a pain =

non-the-less.

What this calls for is dynamic GUI building. This is exactly why I'm not =

a fan of point-an-click GUI builders. In a case like this, you don't =

want to point and click your way to making 18 panels -- you want the =

panels to be generated by code.

I have a simple example of this that I've enclosed. It's a simple Unit =

converter. The Units and conversion factors are defined as data, then a =

Panel for each type of unit (length, velocity, etc) is created on the =

fly. This way I can just add new units to the data, and the whole thing =

just works. There are a couple of oddballs that are still written by =

hand and added in, but most of it works fine.

Your case is more complicated, but the same principle should work, =

define each curve in terms of it's name and parameters required. They =

should be similar enough that you can auto-build a panel to collect the =

data.

-Chris

-- =

Christopher Barker, Ph.D.
Oceanographer

Emergency Response Division
NOAA/NOS/OR&R            (206) 526-6959   voice
7600 Sand Point Way NE   (206) 526-6329   fax
Seattle, WA  98115       (206) 526-6317   main reception

Chris.Barker at noaa.gov
-------------- next part --------------
#!/usr/bin/env python2.4
## there is a pythonw on OS-X, and I add one on Linux, so the #! line can s=
tay the same
import sys

try:
    # let's see if it's local (for development)
    import UnitConversion as UC
except ImportError:
    print "importing installed Unitconversion"
    import Hazmat.UnitConversion as UC
    =

## This is for bundling up with Py2app or py2exe
## wxversion does not work with those.
if not hasattr(sys, "frozen"):
    import wxversion
    wxversion.select("2.6")
    ## Note: it may well work with other versions, but it's been tested on =
2.6.
import wx

class ConverterPanel(wx.Panel):
    def __init__(self, parent, id, UnitType):
    =

        wx.Panel.__init__(self, parent, id, wx.DefaultPosition,style=3Dwx.S=
UNKEN_BORDER)

        self.UnitType =3D UnitType
        Units =3D UC.GetUnitNames(UnitType)
        Units.sort()
        =

        self.FromUnits =3D wx.Choice(self, wx.ID_ANY, wx.DefaultPosition, w=
x.DefaultSize, Units)
        self.FromUnits.SetSelection(0)

        self.ToUnits =3D wx.Choice(self, wx.ID_ANY, wx.DefaultPosition, wx.=
DefaultSize, Units)
        self.ToUnits.SetSelection(0)

        self.InputBox =3D wx.TextCtrl(self, wx.ID_ANY, "", wx.DefaultPositi=
on, (100,-1))
        self.OutBox =3D wx.TextCtrl(self, wx.ID_ANY, "", wx.DefaultPosition=
, (100,-1), style =3D wx.TE_READONLY)
        =

        Grid =3D wx.FlexGridSizer(6, 2, 5, 20)

        Grid.Add(wx.StaticText(self, -1, "Convert from:", wx.DefaultPositio=
n, wx.DefaultSize),0,wx.ALIGN_LEFT)
        Grid.Add((20, 1), 1) # adding a spacer

        Grid.Add(self.InputBox, 0, wx.ALIGN_LEFT)
        Grid.Add(self.FromUnits,0, wx.ALIGN_RIGHT)

        Grid.Add((20, 20), 1) # adding a spacer
        Grid.Add((20, 20), 1) # adding a spacer

        Grid.Add(wx.StaticText(self, -1, "Convert To:", wx.DefaultPosition,=
 wx.DefaultSize),0,wx.ALIGN_LEFT)
        Grid.Add((20, 1), 1) # adding a spacer

        Grid.Add(self.OutBox, 0, wx.ALIGN_LEFT)
        Grid.Add(self.ToUnits, 0, wx.ALIGN_RIGHT)

        Grid.Layout()
        OuterBox =3D wx.BoxSizer(wx.VERTICAL)
        OuterBox.Add((20, 20), 0)
        Label =3D wx.StaticText(self, -1, UnitType, wx.DefaultPosition, wx.=
DefaultSize)
        of =3D Label.GetFont()
        Font =3D wx.Font(int(of.GetPointSize() * 2), of.GetFamily(), wx.NOR=
MAL, wx.NORMAL)
        Label.SetFont(Font)

        OuterBox.Add(Label, 0, wx.ALIGN_CENTER)
        OuterBox.Add(Grid, 0, wx.ALIGN_CENTER|wx.ALL, 30)
        OuterBox.Layout()

        self.SetAutoLayout(True)
        self.SetSizer(OuterBox)
        self.Fit()

        self.InputBox.Bind(wx.EVT_TEXT, self.Recalculate)
        self.FromUnits.Bind(wx.EVT_CHOICE, self.Recalculate)
        self.ToUnits.Bind(wx.EVT_CHOICE, self.Recalculate)

    def Recalculate(self,event):
        try:
            from_string =3D self.InputBox.GetValue()
            =

            # this is not quite really sigfigs, as all zeros are
            # counted, but it looks better it is set to a minimum of 4
            # figures and maximum of 7, as there are no more than 7
            # digits in the conversion factors
            sigfigs =3D min( max(len(from_string.split("e")[0].replace(".",=
"")), 4), 7)

            from_val =3D float(from_string)
            from_unit =3D self.FromUnits.GetStringSelection()
            to_unit =3D self.ToUnits.GetStringSelection()

            to_val =3D UC.Convert(self.UnitType, from_unit, to_unit, from_v=
al)
            =

            format_string =3D "%%.%ig"%sigfigs
            self.OutBox.SetValue(format_string%(to_val,))# this displays on=
ly 6 sigfigs...
        except ValueError:
            self.OutBox.SetValue("")

class LatLongPanel(wx.Panel):
    def __init__(self, *args, **kwargs):

        kwargs['style'] =3D wx.SUNKEN_BORDER

        wx.Panel.__init__(self, *args, **kwargs)


        self.TopPanel =3D wx.Panel(self, style =3D wx.TAB_TRAVERSAL|wx.NO_B=
ORDER) =


        self.DegreesBox =3D wx.TextCtrl(self.TopPanel, size=3D(80,-1))
        self.MinutesBox =3D wx.TextCtrl(self.TopPanel, size=3D(80,-1))
        self.SecondsBox =3D wx.TextCtrl(self.TopPanel, size=3D(80,-1))

        self.DecimalDegreesBox =3D wx.TextCtrl(self, size=3D(100,-1),style =
=3D wx.TE_READONLY)


        self.DegreesMinBox =3D wx.TextCtrl(self, size=3D(100,-1),style =3D =
wx.TE_READONLY)

        self.DegMinSecBox =3D wx.TextCtrl(self, size=3D(100,-1),style =3D w=
x.TE_READONLY)

        #self.DecimalDegreesBox.Bind(wx.EVT_SET_FOCUS, self.OnDDFocus)
        #self.DegreesMinBox.Bind(wx.EVT_SET_FOCUS, self.OnDDFocus)
        #self.DegMinSecBox.Bind(wx.EVT_SET_FOCUS, self.OnDDFocus)

        DMSSizer =3D wx.GridSizer(2, 3, 1, 5)
        DMSSizer.Add(wx.StaticText(self.TopPanel, label=3D"Degrees:"))
        DMSSizer.Add(wx.StaticText(self.TopPanel, label=3D"Minutes:"))
        DMSSizer.Add(wx.StaticText(self.TopPanel, label=3D"Seconds:"))

        DMSSizer.Add(self.DegreesBox, 0, wx.RIGHT, 5)
        DMSSizer.Add(self.MinutesBox, 0, wx.RIGHT, 5)
        DMSSizer.Add(self.SecondsBox, 0, )

        self.TopPanel.SetSizerAndFit(DMSSizer)

        OutputSizer =3D wx.FlexGridSizer(3, 2, 5, 5)
        OutputSizer.AddGrowableCol(2)
       =

        OutputSizer.Add(wx.StaticText(self, label=3D"Decimal Degrees:"))
        OutputSizer.Add(self.DecimalDegreesBox, 1)
        OutputSizer.Add(wx.StaticText(self, label=3D"Deg - Min:"))
        OutputSizer.Add(self.DegreesMinBox,1)
        OutputSizer.Add(wx.StaticText(self, label=3D"Deg - Min - Sec:"))
        OutputSizer.Add(self.DegMinSecBox, 1)

        VertBox =3D wx.BoxSizer(wx.VERTICAL)

        VertBox.Add((20, 20), 0)
        Label =3D wx.StaticText(self, label=3D"Latitude/Longitude")
        of =3D Label.GetFont()
        Font =3D wx.Font(int(of.GetPointSize() * 2), of.GetFamily(), wx.NOR=
MAL, wx.NORMAL)
        Label.SetFont(Font)

        VertBox.Add((20, 20), 1)
        VertBox.Add(Label,    0, wx.ALIGN_CENTER_HORIZONTAL)
        VertBox.Add((20, 20), 1)
        VertBox.Add(self.TopPanel, 0, wx.ALL, 10)
        VertBox.Add(OutputSizer, 0, wx.ALL|wx.GROW, 0)
        VertBox.Add((20, 20), 1)

        OuterBox =3D wx.BoxSizer(wx.HORIZONTAL)
        OuterBox.Add((1,1), 1)
        OuterBox.Add(VertBox, 0)
        OuterBox.Add((1,1), 1)
        =

        self.DegreesBox.Bind(wx.EVT_TEXT, self.Recalculate)
        self.MinutesBox.Bind(wx.EVT_TEXT, self.Recalculate)
        self.SecondsBox.Bind(wx.EVT_TEXT, self.Recalculate)

        self.SetSizerAndFit(OuterBox)

    LLC =3D UC.LatLongConverter

    def OnDDFocus(self, event=3DNone):
        if sys.platform =3D=3D "linux2":
            # this is needed on GTK, not on win32
            self.DegreesBox.SetFocus()
        pass

    def Recalculate(self,event):
        try:
            values =3D []
            for box in (self.DegreesBox, self.MinutesBox, self.SecondsBox ):
                t =3D box.GetValue()
                if t.strip() =3D=3D "":
                    values.append(0.0)
                else:
                    values.append(float(t))

            DecDeg =3D self.LLC.ToDecDeg(*values)

            self.DecimalDegreesBox.SetValue(self.LLC.ToDecDeg(DecDeg, ustri=
ng=3DTrue))
            self.DegreesMinBox.SetValue(self.LLC.ToDegMin(DecDeg, True) )
            self.DegMinSecBox.SetValue(self.LLC.ToDegMinSec(DecDeg, True) )

        except ValueError:
            self.DecimalDegreesBox.SetValue("")
            self.DegreesMinBox.SetValue("")
            self.DegMinSecBox.SetValue("")


class ConverterFrame(wx.Frame):
    def __init__(self,parent, id, title, position, size):
        wx.Frame.__init__(self, parent, id, title, position, size)

        ## Set up the MenuBar
        =

        MenuBar =3D wx.MenuBar()
        if not sys.platform =3D=3D "darwin":
            file_menu =3D wx.Menu()
            file_menu.Append(wx.ID_EXIT, "E&xit","Terminate the program")
            MenuBar.Append(file_menu, "&File")
        help_menu =3D wx.Menu()
        help_menu.Append(wx.ID_ABOUT, "&About",
                                "More information About this program")
        MenuBar.Append(help_menu, "&Help")
        self.SetMenuBar(MenuBar)
        =

        wx.EVT_MENU(self, wx.ID_EXIT,self.OnQuit)
        wx.EVT_MENU(self, wx.ID_ABOUT, self.OnAbout)
        =

        wx.EVT_CLOSE(self, self.OnCloseWindow)
        =

        MainSizer =3D wx.BoxSizer(wx.HORIZONTAL)
        self.MainSizer =3D MainSizer

        ButtonSizer =3D wx.BoxSizer(wx.VERTICAL)

        self.Panels =3D {}
        BiggestSize =3D (0,0)
        for UnitType in UC.GetUnitTypes():
            # create Panel
            Panel =3D ConverterPanel(self, -1, UnitType)
            Panel.Show(False)
            size =3D Panel.GetBestSize()
            BiggestSize =3D ( max(size[0],BiggestSize[0]), max(size[1],Bigg=
estSize[1]) )
            =

            # create Button
            ID =3D wx.NewId()
            ButtonSizer.Add(wx.Button(self, ID, UnitType),
                            0,
                            wx.EXPAND|wx.ALL,
                            3)
            self.Panels[ID] =3D Panel

            ### set up the events:
            wx.EVT_BUTTON(self, ID, self.OnButtonPress)
        ## Add the LatLonPanel:
        Panel =3D LatLongPanel(self)
        Panel.Show(False)
        size =3D Panel.GetBestSize()
        BiggestSize =3D ( max(size[0],BiggestSize[0]), max(size[1],BiggestS=
ize[1]) )
            =

        # create Button
        ID =3D wx.NewId()
        ButtonSizer.Add(wx.Button(self, ID, "Lat-Long"),
                        0,
                        wx.EXPAND|wx.ALL,
                        3)
        self.Panels[ID] =3D Panel

        ### set up the button event:
        wx.EVT_BUTTON(self, ID, self.OnButtonPress)
            =

        ButtonSizer.Layout()
        MainSizer.Add(ButtonSizer, 0, wx.ALIGN_TOP|wx.ALL, 6)

        ## Reset the sizes of all the Panels to match the biggest one
        for Panel in self.Panels.values():
            Panel.SetSize(BiggestSize)
            Panel.SetSizeHintsSz(BiggestSize)

        ##Add all the Panels
        for ID in self.Panels:
            CurrentPanel =3D  self.Panels[ID]
            MainSizer.Add(CurrentPanel, 1, wx.GROW|wx.ALL,4)
            MainSizer.Show(CurrentPanel, False)
        self.CurrentPanel =3D self.Panels.values()[0]
        MainSizer.Show(self.CurrentPanel)
        self.SetSizerAndFit(MainSizer)
        self.SetSizeHintsSz(self.GetSize(), self.GetSize())
            =

    def OnButtonPress(self,event):
        ID =3D event.GetId()
        self.MainSizer.Show(self.CurrentPanel, False)
        self.CurrentPanel =3D self.Panels[ID]
        self.MainSizer.Show(self.CurrentPanel)
        self.MainSizer.Layout()

    def OnAbout(self, event):
        dlg =3D wx.MessageDialog(self, "This is a small program that \n"
                               "Provides some handy conversions.\n"
                               "If you find any errors, or want\n"
                               "additional units added, tell Chris Barker:\=
n"
                               "Chris.Barker at noaa.gov",
                               "About Converter", wx.OK | wx.ICON_INFORMATI=
ON)
        dlg.ShowModal()
        dlg.Destroy()
        =

        =

    def OnQuit(self,event):
        self.Close(True)
        =

    def OnCloseWindow(self, event):
        self.Destroy()


class App(wx.App):
    def OnInit(self):
        frame =3D ConverterFrame(None,
                               wx.ID_ANY,
                               "Unit Converter",
                               wx.DefaultPosition,
                               wx.DefaultSize)
        =

        self.SetTopWindow(frame)
        frame.Show(True)
        return True

if __name__ =3D=3D "__main__":
    app =3D App(0)
    app.MainLoop()
    =

#### test Lat/longif =

##if __name__ =3D=3D "__main__":
##    app =3D wx.App(0)
##    frame =3D wx.Frame(None)
##    panel =3D LatLongPanel(frame)
##    frame.Fit()
##    frame.Show()
##    app.MainLoop()
    =

    =

    =

    =

    =

    =

    =

    =

    =

    =

    =

    =

    =

    =

    =

    =

    =

-------------- next part --------------
#!/usr/bin/env python2.4

__version__ =3D "1.0.0"

ConvertDataUnits =3D {
# All lengths in terms of meter

"Length" : {"meter"      : (1.0,["m","meters","metre"]),
            "centimeter" : (0.01,["cm", "centimeters"]),
            "millimeter"  : (0.001,["mm","millimeters"]),
            "micron"  : (0.000001,["microns"]),
            "kilometer"  : (1000.0,["km","kilometers"]),
            "foot"        : (0.3048,["ft", "feet"]),
            "inch"      : (0.0254,["in","inches"]),
            "yard"       : (0.9144,[ "yrd","yards"]),
            "mile"       : (1609.344,["mi", "miles"]),
            "nautical mile" : (1852.0,["nm","nauticalmiles"]),
            "fathom"  : (1.8288,["fthm", "fathoms"]),
            "latitude degree": (111120.0,["latitudedegrees"]),
            "latitude minute": (1852.0,["latitudeminutes"])
            },

# All Areas in terms of square meter
"Area" : {"square meter"  : (1.0,["m^2","sq m","squaremeter"]),
          "square centimeter": (.0001,["cm^2","sq cm"]),
          "square kilometer"  : (1e6,["km^2","sq km","squarekilometer"]),
          "acre"  : (4046.8564,["acres"]),
          "square mile"  : (2589988.1,["sq miles","squaremile"]),
          "square yard"  : (0.83612736,["sq yards","squareyards"]),
          "square foot"  : (0.09290304,["ft^2", "sq foot","square feet"]),
          "square inch"  : (0.00064516,["in^2", "sq inch","square inches"]),
          "hectar"  : (10000.0,["hectares"]),
          },

# All volumes in terms of cubic meter
"Volume" : {"cubic meter"  : (1.0,["m^3","cu m","cubic meter"]),
            "cubic centimeter"  : (1e-6,["cm^3","cu cm"]),
            "barrels (petroleum)" : (.1589873,["bbl","barrels","barrel","bb=
ls",]),
            "liter"        : (1e-3,["l","liters"]),
            "US gallon"       : (0.0037854118,["gal","gallons","gallon","us=
gal"]),
            "cubic foot"    : (0.028316847,["ft^3","cu feet","cubicfeet"]),
            "cubic inch"    : (16.387064e-6,["in^3","cu inch","cubicinches"=
]),
            },

# All Temperature units in K (multiply by, add)
"Temperature" : {"Kelvin"  : ((1.0, 0.0),["K","degrees k","degrees k","degr=
ees kelvin","degree kelvin","deg k"]),
                 "centigrade"     : ((1.0, 273.16),["C","degrees c","degree=
s celsius","degree celsius","deg c"]),
                 "farenheight"  : ((0.55555555555555558, (273.16*9/5 - 32) =
),["F","degrees f","degree f","degrees farenheight","deg f"]),
                 },

# All Mass units in Kg (weight is taken to be mass at standard g)
"Mass" : {"kilograms"  : (1.0,["kg","kilogram"]),
          "pound"     : (0.45359237,["lb","pounds","lbs"]),
          "gram"  : (.001,["g","grams"]),
          "ton"   : (907.18474, ["tons","uston"]),
          "metric ton" : (1000.0, ["tonnes","metric tons"]),
          "slug"       : (14.5939, ["slugs"]),
          "ounce"       : (.028349523, ["oz","ounces"]),
          },

# All Time In second
"Time" : {"second"  : (1.0,["sec","seconds"]),
          "minute"  : (60.0,["min","minutes"]),
          "hour"    : (3600.0,["hr","hours","hrs"]),
          "day"     : (86400.0,["day","days"]),
          },
# All Velocities in meter per second
"Velocity" : {"meter per second"  : (1.0,["m/s","meters per second","mps"]),
              "centimeter per second"  : (.01,["cm/s"]),
              "kilometer per hour"  : (0.277777,["km/h", "km/hr"]),
              "knot"  : (0.514444,["knots","kts"]),
              "mile per hour"  : (0.44704,["mph","miles per hour"]),
              "foot per second"  : (0.3048,["ft/s", "feet per second", "fee=
t/s"]),
              },
# All Discharges in cubic meter per second
"Discharge" : {"cubic meter per second"  : (1.0,["m^3/s","cu m/s","cms"]),
               "liter per second"    : (0.001,["l/s","lps"]),
               "cubic foot per second"    : (.02831685,["cfs","cu feet/s","=
feet^3/s"]),
               "gallon per hour"  : (1.0515032833333335e-06,["gal/hr"]),
               "gallon per minute" : (6.3090197000000006e-05,["gal/min", "g=
pm"]),
               "gallon per second"  : ( 0.0037854118,["gal/s"]),
               "barrel per hour"  : ( 4.4163138888888885e-05,["bbl/hr"]),
               },

"Kinematic Viscosity" : {"Stoke": (1.0,["St","stokes"]),
                         "centistoke": (.01,["cSt","centistokes"]),
                         "square centimeter per second": (1.0,["cm^2/s"]),
                         "square meter per second": (10000,["m^2/s"]),
                         "square inches per second": (6.4516,["in^2/s"]),
                         #"poise" : (["P"])
                         },
### Density in g/cc
"Density" : {"grams per cubic centimeter"  : (1.0,["g/cm^3"]),
             "specific gravity"  : (1.0,["S","Spec grav","SG"]),
             "kilograms per cubic meter" : (.001,["kg/m^3"]),
             "pounds per cubic foot":  (0.016018463,["lbs/ft^3"]),
             "API"  : (1,["api"]),# this is special cased in the code.
             },

### Concentration in water in PPM
"Concentration In Water" : {"part per million"  : (1.0,["ppm","parts per mi=
llion"]),
                            "part per billion"  : (.001,["ppb", "parts per =
billion"]),
                            "part per thousand"  : (1000,["ppt", "parts per=
 thousand"]),
                            "fraction" : (1e6,["fraction", "mass per mass"]=
),
                            "percent":  (1e4,["%", "parts per hundred", "pe=
r cent"]),
                            "kilograms per cubic meter":  (1000,["kg/m^3","=
kg/m3"]),
                            "pound per cubic foot": (16018.463, ["lb/ft^3"]=
),
                            "milligram per liter": (1.0, ["mg/l"]),
                            "microgram per liter": (0.001, ["ug/l"]),
                          }
}


def Simplify(String):
    """
    Simplify(String)

    returns the string with the whitespace and capitalization removed
    """
    return "".join(String.lower().split())

def GetUnitTypes():
    return ConvertDataUnits.keys()

def GetUnitNames(UnitType):
    return ConvertDataUnits[UnitType].keys()

class ConverterClass:
    def __init__(self, TypeName, UnitsDict):
        self.Name =3D TypeName

        self.Synonyms =3D {}
        self.Convertdata =3D {}
        for PrimaryName, data in UnitsDict.items():
            # strip out whitespace and capitalization
            Pname =3D Simplify(PrimaryName)
            self.Convertdata[Pname] =3D data[0]
            self.Synonyms[Pname] =3D Pname
            for synonym in data[1]:
                self.Synonyms[Simplify(synonym)] =3D Pname

    def Convert(self, FromUnit, ToUnit, Value):

        """
        Convert(FromUnit, ToUnit, Value)

        returns a new value, in the units of ToUnit.

        """
        FromUnit =3D Simplify(FromUnit)
        ToUnit =3D Simplify(ToUnit)

        try:
            FromUnit =3D self.Synonyms[FromUnit]
        except KeyError:
            raise InvalidUnitError(FromUnit, self.Name)
        try:
            ToUnit =3D self.Synonyms[ToUnit]
        except KeyError:
            raise InvalidUnitError(ToUnit, self.Name)

        return Value * self.Convertdata[FromUnit] / self.Convertdata[ToUnit]

# the special case classes:
class TempConverterClass(ConverterClass):
    def Convert(self, FromUnit, ToUnit, Value):

        """
        Convert(FromUnit, ToUnit, Value)

        returns a new value, in the units of ToUnit.

        """

        FromUnit =3D Simplify(FromUnit)
        ToUnit =3D Simplify(ToUnit)

        try:
            FromUnit =3D self.Synonyms[FromUnit]
        except KeyError:
            raise InvalidUnitError(FromUnit, self.Name)
        try:
            ToUnit =3D self.Synonyms[ToUnit]
        except KeyError:
            raise InvalidUnitError(ToUnit, self.Name)

        A1 =3D self.Convertdata[FromUnit][0]
        B1 =3D self.Convertdata[FromUnit][1]
        A2 =3D self.Convertdata[ToUnit][0]
        B2 =3D self.Convertdata[ToUnit][1]

        #to_val =3D (round((from_val * A1 + B1),13) - round(B2,13))*A2 # ro=
unding to get rid of cancelation error
        to_val =3D ((Value + B1)*A1/A2)-B2
        return to_val

class DensityConverterClass(ConverterClass):
    =

    def Convert(self, FromUnit, ToUnit, Value):

        """
        Convert(FromUnit, ToUnit, Value)

        returns a new value, in the units of ToUnit.

        """

        FromUnit =3D Simplify(FromUnit)
        ToUnit =3D Simplify(ToUnit)
         =

        try:
            FromUnit =3D self.Synonyms[FromUnit]
        except KeyError:
            raise InvalidUnitError(FromUnit, self.Name)
        try:
            ToUnit =3D self.Synonyms[ToUnit]
        except KeyError:
            raise InvalidUnitError(ToUnit, self.Name)

        if FromUnit =3D=3D "api": # another Special case (could I do this t=
he same as temp?)
            Value =3D 141.5/(Value + 131.5)
            FromUnit =3D "specificgravity"
        if ToUnit =3D=3D "api":
            ToVal =3D 141.5/(Value * self.Convertdata[FromUnit]) - 131.5
        else:
            ToVal =3D Value * self.Convertdata[FromUnit] / self.Convertdata=
[ToUnit]
        return ToVal

class LatLongConverterClass:
    def ToDecDeg(self, d=3D0, m=3D0, s=3D0, ustring =3D False):
        """

        DecDegrees =3D ToDecDeg(d=3D0, m=3D0, s=3D0)
        =

        converts degrees, minutes, seconds to decimal degrees (returned as =
a Float).
        """
        if  m < 0 or s < 0:
            raise ValueError("Minutes and Seconds have to be positive")
        if d < 0:
            Sign =3D -1
            d =3D -d
        else:
            Sign =3D 1
        DecDegrees =3D Sign * (d + m/60.0 + s/3600.0)

        if ustring:
            return u"%.6f\xb0"%(DecDegrees)
        else:
            return DecDegrees

    def ToDegMin(self, DecDegrees, ustring =3D False):
        """
        Converts from decimal (binary float) degrees to:
          Degrees, Minutes

        If the optional paramter: "ustring" is True,
        a unicode string is returned

        """

        if DecDegrees < 0:
            Sign =3D -1
            DecDegrees =3D -DecDegrees
        else:
            Sign =3D 1


        Degrees =3D int(DecDegrees)
        DecMinutes =3D (DecDegrees - Degrees + 1e-14) * 60# add a tiny bit =
to avoid rounding issues
        if ustring:
            return u"%i\xb0 %.3f'"%(Sign*Degrees, DecMinutes)
        else:
            return (Sign*Degrees, DecMinutes)

    def ToDegMinSec(self,DecDegrees, ustring =3D False):

        """
        Converts from decimal (binary float) degrees to:
          Degrees, Minutes, Seconds

        If the optional paramter: "ustring" is True,
        a unicode string is returned

        """
        if DecDegrees < 0:
            Sign =3D -1
            DecDegrees =3D -DecDegrees
        else:
            Sign =3D 1
        =

        Degrees =3D int(DecDegrees)
        DecMinutes =3D (DecDegrees - Degrees + 1e-14) * 60# add a tiny bit =
to avoid rounding issues

        Minutes =3D int(DecMinutes)
        Seconds =3D round(((DecMinutes - Minutes) * 60), 10 )
        if ustring:
            return u"%i\xb0 %i' %.2f\""%(Sign*Degrees, Minutes, Seconds)
        else:
            return (Sign * Degrees, Minutes, Seconds)
        =

  =


# create the converter objects
LatLongConverter =3D LatLongConverterClass()
Converters =3D {}
for (unittype,data) in ConvertDataUnits.items():
    if unittype.lower() =3D=3D 'temperature':
        Converters["temperature"] =3D TempConverterClass(unittype, data)
    elif unittype.lower() =3D=3D 'density':
        Converters["density"] =3D DensityConverterClass(unittype, data)
    else:
        Converters[Simplify(unittype)] =3D ConverterClass(unittype, data)

def Convert(UnitType, FromUnit, ToUnit, Value):
    UnitType=3D Simplify(UnitType)
    try:
        Converter =3D Converters[UnitType]
    except:
        raise InvalidUnitTypeError(UnitType)

    return Converter.Convert(FromUnit, ToUnit, Value )


### This is used by TapInput

def GetUnitAbbreviation(Units):
    # Abbreviation for units is a first element of synonyms list
    try:
        (UnitType,unit) =3D NameTable[Units]
    except KeyError:
        raise UnitConversionError("%s is not in UnitConverter Code"%Units)

    return(ConvertDataUnits[UnitType][unit][1][0])

class UnitConversionError(Exception):
    """
    Exception type for unit conversion errors

    perhaps this should be subclassed more, but at the moment, I just pass =
a message back

    """
    def __init__(self,message):
        self.message =3D message

    def __str__(self):
        return self.message

class InvalidUnitError(UnitConversionError):
    """
    Exception raised when a unit is not in the Unitconversion database

    """
    def __init__(self, unit, type =3D ""):
        self.unit =3D unit
        self.type =3D type

    def __str__(self):
        return "The unit: %s is not in the list for Unit Type: %s"%(self.un=
it, self.type)

class InvalidUnitTypeError(UnitConversionError):
    """
    Exception raised when a unit is not in the Unitconversion database

    """
    def __init__(self, unitType):
        self.unitType =3D unitType

    def __str__(self):
        return "The unit type: %s is not in the UnitConversion database"%se=
lf.unitType
    =

class MismatchedUnitError(UnitConversionError):
    """
    Exception raised when a unit is not in the Unitconversion database

    """
    def __init__(self, FromUnit, FromUnitType, ToUnit, ToUnitType):
        self.FromUnit     =3D  FromUnit    =

        self.FromUnitType =3D  FromUnitType
        self.ToUnit       =3D  ToUnit      =

        self.ToUnitType   =3D  ToUnitType  =


    def __str__(self):
        #return "a test string"
        return "The unit: %s of  type %s is not compatible with %s of type =
%s"% \
               (self.FromUnit, self.FromUnitType, self.ToUnit, self.ToUnitT=
ype)
    =

    =


















More information about the wxpython-users mailing list