def tsGetStdioPositionAndSize(self):
        '''
        Return position and size of window used for redirected output.
        '''
        if not self.ts_PyOnDemandStdioWindow:
 
            # Establish defaults until attributes finalized
            theRedirectedPos = wxPoint(-1, -1)
            theRedirectedSize = wxSize(450, 300)

        else:

            try:
                self.Display = wxDisplay(self)
                theClientArea = self.Display.theRedirectedStdioArea

                theRedirectedSize = wxSize(theClientArea.width,
                                           theClientArea.height)

                theRedirectedPos = wxPoint(
                    theClientArea.x,
                    theClientArea.y)
            except Exception, getError:
                theRedirectedPos = wxPoint(-1, -1)
                theRedirectedSize = wxSize(450, 300)
                self.logger.debug(
                    '  GetStdioPositionAndSize Exception. %s' % getError)
                msg = 'GetStdioPositionAndSize Exception: %s' % str(getError)
                raise tse.ProgramException(tse.APPLICATION_TRAP, msg)
    def tsGetBorderCharacterDimensions(self, thickness):
        """
        Return width and height of border character in pixels.

        Parameter:

        thickness --- Border line thickness in pixels.
        """
        if thickness == -1:

            if wx.USE_BORDER_BY_DEFAULT:

                # Default (1-pixel) border required.
                dimensions = wxSize(wx.pixelWidthPerCharacter, wx.pixelHeightPerCharacter)
            else:

                # No border required.
                dimensions = wxSize(0, 0)

        elif thickness == 0:

            # No border required.
            dimensions = wxSize(0, 0)

        else:

            # Override thickness and apply default (1-pixel) border.
            dimensions = wxSize(
                min(1, thickness) * wx.pixelWidthPerCharacter, min(1, thickness) * wx.pixelHeightPerCharacter
            )

        return dimensions
    def tsBestSize(self):
        """
        """
        borderThickness = self.tsIsBorderThickness(style=self.ts_Style, pixels=True)

        maxWidth = 0
        maxHeight = 0
        for choice in self.ts_Choices:
            buttonText = self.tsStripAcceleratorTextLabel(choice)
            if len(buttonText) > maxWidth:
                maxWidth = len(buttonText)
                maxHeight += 1

        if self.ts_Style & wx.RA_VERTICAL:
            # Vertical
            best = wxSize(
                (maxWidth * wx.pixelWidthPerCharacter + 2 * borderThickness.width),
                (maxHeight * wx.pixelHeightPerCharacter + 2 * borderThickness.height),
            )

        elif self.ts_Style & wx.RA_HORIZONTAL:
            # Horizontal
            best = wxSize(
                (maxWidth * wx.pixelWidthPerCharacter + 2 * borderThickness.width),
                (maxHeight * wx.pixelHeightPerCharacter + 2 * borderThickness.height),
            )

        else:
            # TBD - Should this be allowed?
            best = wxSize(
                (maxWidth * wx.pixelWidthPerCharacter + 2 * borderThickness.width),
                (maxHeight * wx.pixelHeightPerCharacter + 2 * borderThickness.height),
            )

        return best
    def tsBestSize(self):
        '''
        '''
        borderThickness = self.tsIsBorderThickness(
            style=self.ts_Style, pixels=True)

        gaugeThickness = 1
        gaugeLength = 10
 
        if self.ts_Style & wx.SB_VERTICAL:
            # Vertical
            best = wxSize(
                (gaugeThickness * wx.pixelWidthPerCharacter + \
                 2 * borderThickness.width),
                (gaugeLength * wx.pixelHeightPerCharacter + \
                 2 * borderThickness.height))
        else:
            # Horizontal
            best = wxSize(
                (gaugeLength * wx.pixelWidthPerCharacter + \
                 2 * borderThickness.width),
                (gaugeThickness * wx.pixelHeightPerCharacter + \
                 2 * borderThickness.height))

        return (best)
    def SizeFromMajorMinor(self, major, minor):
        '''
        '''
        if self.ts_Orientation == wx.HORIZONTAL:

            return (wxSize(major, minor))

        else: # wxVERTICAL

            return (wxSize(minor, major))
    def CreateOutputWindow(self, st):
        '''
        Create frame and text control. Append st (text) to output. Show the
        frame and bind the frame OnCloseButtton to the event.
        '''
        # TBD - Under Construction. The class wxTextCtrl is not available.
        if not (self.ts_Frame is None):
            return
 
        try:
            self.ts_Frame = wxFrame(
                self.ts_Parent,
                id=-1,
                title=self.ts_Title,
                pos=wxPoint(self.ts_Rect.x, self.ts_Rect.y),
                size=wxSize(self.ts_Rect.width, self.ts_Rect.height),
                style=self.ts_Style,
                name=self.ts_Name)
        except Exception as frameError:
            self.logger.error(
                '  CreateOutputWindow: frameError. %s' % frameError)
            msg = 'CreateOutputWindow Frame Error: %s' % str(frameError)
            raise tse.ProgramException(tse.APPLICATION_TRAP, msg)

        if self.ts_Frame.display.HasColors:
            self.ts_Markup = wx.ThemeToUse['Stdio']['Markup']['DEFAULT']
        else:
            self.ts_Markup = None

        try:
            self.ts_Text  = wxTextCtrl(
                self.ts_Frame,
                id=-1,
                value=wx.EmptyString,
                pos=wxPoint(
                    self.ts_ClientRect.x + self.ts_Margin.width,
                    self.ts_ClientRect.y + self.ts_Margin.height),
                size=wxSize(
                    self.ts_ClientRect.width - 2 * self.ts_Margin.width,
                    self.ts_ClientRect.height - 2 * self.ts_Margin.height),
                style=0, # wx.TE_MULTILINE |wx.TE_READONLY,
                validator=wx.DefaultValidator,
                name=wx.TextCtrlNameStr)
        except Exception as textCtrError:
            self.logger.error(
                '  CreateOutputWindow: textCtlError. %s' % textCtrError)
            msg = 'CreateOutputWindow textCtr Error: %s' % str(textCtrError)
            raise tse.ProgramException(tse.APPLICATION_TRAP, msg)

        # Skip this since text has been pre-cached in self.write
        # before invocation of self.CreateOutputWindow.
        if False:
            self.ts_Text.AppendText(st)

        self.ts_Frame.Show(True)
    def AddSpacer(self, size):
        '''
        '''
        if self.IsVertical():
            item = wxSize(0, size)
        else:
            item = wxSize(size, 0)

        child = self.Add(item, proportion=0, flag=0, border=0, userData=None)

        # Register the child in the wxSizerItemList
        self.ts_Children.Add(child)

        return (child)
    def __init__(self, window, size):
        """
        Create a new caret object.
        """
        theClass = "Caret"

        wx.RegisterFirstCallerClassName(self, theClass)

        ##        self.tsBeginClassRegistration(theClass, id)
        try:

            self.logger = tsLogger.TsLogger(
                threshold=tsLogger.ERROR, start=time.time(), name=tsLogger.StandardOutputFile
            )

        except AttributeError as e:

            self.logger = None
            msg = "tsWxCaret.__init__: Exception = %s" % e
            raise tse.ProgramException(tse.APPLICATION_TRAP, msg)

        self.ts_Position = wxPoint(0, 0)
        self.ts_Size = wxSize(0, 0)

        self.ts_Window = window
        self.ts_visibility = wx.caretNormal
        self.theScreen = tsGTUI.GraphicalTextUserInterface(theClass)
        self.theScreen.curs_set(self.ts_visibility)
    def tsGetClientArea(self, pixels=True):
        '''
        Returns the bounding rectangle the client area of the Dialog.
        '''
        parent = self.ts_Parent
        pos = wxPoint(self.ts_Rect.x, self.ts_Rect.y)
        size = wxSize(self.ts_Rect.width, self.ts_Rect.height)
        style = self.ts_Style
        name = self.ts_Name

        (myRect, myClientRect) = self.tsDialogWindowLayout(
            parent, pos, size, style, name)

        if self.ts_Rect != myRect:

            # My Area changed after by new feature
            fmt1 = 'Wrong layout. myRect (%s) ' % str(myRect)
            fmt2 = 'changed from self.ts_Rect (%s) ' % str(self.ts_Rect)
            fmt3 = 'in tsWxFrame.tsGetClientArea'
            msg = fmt1 + fmt2 + fmt3
            self.logger.wxASSERT_MSG(
                (self.ts_Rect == myRect),
                msg)

            self.ts_Rect = myRect

        if self.ts_ClientRect != myClientRect:

            # Client Area changed after by new feature
            self.ts_ClientRect = myClientRect

        return (self.ts_ClientRect)
    def ShowFullScreen(self, show, style):
        '''
        '''
        # TBD - Under Construction.
        # Extent resize of the top level window to include its children.
        theDisplay = self.Display
 
        theDisplayPos = wxPoint(theDisplay.ClientArea.x,
                                theDisplay.ClientArea.y)

        theDisplaySize = wxSize(theDisplay.ClientArea.width,
                                theDisplay.ClientArea.height)

        self.logger.debug(
            '      ShowFullScreen (screen): pos=%s; size=%s.' % (
                str(theDisplayPos), str(theDisplaySize)))

        self.Rect = wxRect(theDisplayPos.x,
                           theDisplayPos.y,
                           theDisplaySize.width,
                           theDisplaySize.height)

        self.logger.debug(
            '      Need Event to ShowFullScreen (rect): %s.' % (
                str(self.Rect)))

        return (show)
    def tsShow(self):
        """
        Create and update MenuBar specific native GUI.
        """
        if self.tsIsShowPermitted:

            if self.ts_Handle is None:

                myRect = wxRect(
                    self.ts_Parent.Rect.x + wx.pixelWidthPerCharacter,
                    self.ts_Parent.Rect.y + wx.pixelHeightPerCharacter,
                    self.ts_Parent.Rect.width - 2 * wx.pixelWidthPerCharacter,
                    wx.ThemeToUse["MenuBar"]["WindowHeight"],
                )

                thePosition = wxPoint(myRect.x, myRect.y)
                theSize = wxSize(myRect.width, myRect.height)

                # TBD - Update Class geometry.
                ##            self.ts_Rect = myRect
                ##            self.logger.debug(
                ##                '_show: myRect=%s; Rect = %s' % (myRect, self.ts_Rect))

                self.Create(
                    self, id=-1, pos=thePosition, size=theSize, style=self.ts_Style, name=self.Name, pixels=True
                )

            try:
                self.tsRegisterShowOrder()
            except Exception as e:
                self.logger.error("%s; %s" % (__title__, e))

            self.tsUpdate()
    def __init__(self, orient=wx.HORIZONTAL):
        '''
        Constructor for a wx.BoxSizer. orient may be one of wx.VERTICAL
        or wx.HORIZONTAL for creating either a column sizer or a row sizer.
        '''
        theClass = 'BoxSizer'

        wx.RegisterFirstCallerClassName(self, theClass)

        Sizer.__init__(self)

        self.tsBeginClassRegistration(theClass, id)

        # either wxHORIZONTAL or wxVERTICAL
        self.ts_Orientation = orient

        # the sum of proportion of all of our elements
        self.ts_TotalProportion = 0

        # minimal size needed for this sizer as calculated by
        # the last call to our CalcMin()
        self.ts_MinSize = DEFAULT_SIZE

        # minimal size needed for this sizer as calculated, by
        # calcMin, for the containing window (panel), the parent
        # of those subpanels managed by this BoxSizer instance.
        self.ts_CalcMinArea = []
        self.ts_CalcMinAreaProportion = []
        self.ts_CalcMinKind = []
        self.ts_CalcMinWindow = []
        self.ts_ClientArea = []
        self.ts_ContainingWindow = None
        self.ts_MinSize = wxSize(0, 0)
        self.ts_SizeMinThis = []
        self.ts_TotalFixedSize = wxSize(0, 0)
        self.ts_TotalProportion = 0

##        self.ts_SizeMinThis = None
##        self.ts_CalcMinArea = None
##        self.ts_CalcMinAreaProportion = None
##        self.ts_CalcMinKind = None
##        self.ts_CalcMinWindow = None
##        self.ts_ClientArea = None
##        self.ts_ContainingWindow = None
        self.ts_RecalcArea = None

        self.tsEndClassRegistration(theClass)
    def CalcMin(self):
        '''
        Calculate the total minimum width and height needed by all items
        in the sizer according to this sizer layout algorithm.

        This method is abstract and has to be overwritten by any derived
        class.

        Here, the sizer will do the actual calculation of its childrens
        minimal sizes.

        Implemented in wxGridBagSizer, and wxBoxSizer.
        '''
        width = 0
        height = 0
        for i in range(0, self.ts_Children.GetCount()):
            node = self.ts_Children.GetIndex(i)

            item = node.GetUserData()

            size = wxSize(0, 0)
            if (isinstance(self, Window)):
                try:
                    parent = self.ts_Parent
                    theClientRect = parent.ClientArea
                except AttributeError:
                    parent = None
                    theClientRect = wxRect(0, 0, 0, 0)

                width = theClientRect.width
                height = theClientRect.height
                minSize = wxSize(width, height)

                self.logger.debug(
                    'CalcMin: item=%s; minSize=%s; width=%s; height=%s' % (
                    str(item), str(minSize), str(width), str(height)))

                size = minSize
                self.logger.debug('CalcMin: size=%s' % size)

            return (size)
    def tsShow(self):
        '''
        Shows or hides the window. You may need to call Raise for a top
        level window if you want to bring it to top, although this is not
        needed if Show is called immediately after the frame creation.
        Returns True if the window has been shown or hidden or False if
        nothing was done because it already was in the requested state.
        '''
        if self.tsIsShowPermitted:

            if self.ts_Handle is None:

                myRect = wxRect(
                    self.ts_Parent.Rect.Left,
                    (self.ts_Parent.Rect.Bottom - \
                     wx.ThemeToUse['StatusBar']['WindowHeight'] - \
                     wx.pixelHeightPerCharacter),
                    self.ts_Parent.Rect.width,
                    wx.ThemeToUse['StatusBar']['WindowHeight'])

                thePosition = wxPoint(myRect.x, myRect.y)
                theSize = wxSize(myRect.width, myRect.height)

                # TBD - Update Class geometry.
                self.ts_Rect = myRect
                self.logger.debug(
                    'tsShow: myRect=%s; Rect = %s' % (myRect, self.ts_Rect))

                self.ts_BaseRect = self.ts_Rect
                if DEBUG:
                    print('tsShow: myRect=%s; Rect = %s' % (myRect, self.ts_Rect))

                self.Create(self,
                            id=-1,
                            pos=thePosition,
                            size=theSize,
                            style=self.ts_Style,
                            name=self.Name,
                            pixels=True)

            try:
                self.tsRegisterShowOrder()
            except Exception, e:
                self.logger.error('%s; %s' % (__title__, e))

            self.tsUpdate()
    def GetDefaultSize(self):
        '''
        Returns the default button size for this platform.
        '''
        thickness = self.tsIsBorderThickness(
            style=self.ts_Style, pixels=False)

        if False:
            width = (len(self.ts_ButtonText) + 1) * wx.pixelWidthPerCharacter

            height = (1) * wx.pixelHeightPerCharacter
        else:
            width = (thickness.width + \
                     len(self.ts_ButtonText) + 1) * wx.pixelWidthPerCharacter

            height = (thickness.height + 1) * wx.pixelHeightPerCharacter

        return (wxSize(width, height))
예제 #16
0
    def tsSetStdioWindowAttributes(self,
                                   title=None,
                                   pos=None,
                                   size=None,
                                   style=None,
                                   name=None):
        '''
        Set the title, position, size, style and name of the output window
        if the stdio has been redirected.
        '''
        if self.stdioWin:
            # TBD - Cannot set attributes when window does not exist.
            myRect = self.Display.theRedirectedStdioArea
            if title is not None:
                self.stdioWin.title = title
            else:
                self.stdioWin.title = wx.ThemeToUse['Stdio']['Title']

            if pos is not None:
                self.stdioWin.pos = pos
            else:
                self.stdioWin.pos = wxPoint(myRect.x, myRect.y)

            if size is not None:
                self.stdioWin.size = size
            else:
                self.stdioWin.size = wxSize(myRect.width, myRect.height)

            if style is not None:
                self.stdioWin.style = style
            elif wx.ThemeToUse['Stdio']['Title'] == wx.StdioRedirectedTitleStr:
                self.stdioWin.style = wx.DEFAULT_STDIO_STYLE
            else:
                self.stdioWin.style = wx.DEFAULT_FRAME_STYLE

            if name is not None:
                self.stdioWin.name = name
            elif wx.ThemeToUse['Stdio']['Title'] == wx.StdioRedirectedTitleStr:
                self.stdioWin.name = wx.StdioNameStr
            else:
                self.stdioWin.name = wx.FrameNameStr
    def CalcMin(self):
        '''
        This method is where the sizer will do the actual calculation of its
        childrens minimal sizes. You should not need to call this directly
        as it is called by Layout

        Modeled after TBD in sizer.cpp file of wxWidgets.
        '''
        width = 0
        height = 0
        for item in self.GetChildren():
            # calculate the total minimum width and height needed
            # by all items in the sizer according to this sizer's
            # layout algorithm.
            minSize = item.MinSize
            width += minSize.width
            height += minSize.height

        size = wxSize(width, height)
        self.logger.debug('CalcMin: size=%s' % size)

        return (size)
    def CreateOutputWindow(self, st):
        '''
        Create frame and text control. Append st (text) to output. Show the
        frame and bind the frame OnCloseButtton to the event.
        '''
        # TBD - Under Construction. The class wxTextCtrl is not available.
        if not (self.ts_Frame is None):
            return
 
        try:
            self.ts_Frame = wxFrame(
                self.ts_Parent,
                id=-1,
                title=self.ts_Title,
                pos=wxPoint(self.ts_Rect.x, self.ts_Rect.y),
                size=wxSize(self.ts_Rect.width, self.ts_Rect.height),
                style=self.ts_Style,
                name=self.ts_Name)
        except Exception, frameError:
            self.logger.error(
                '  CreateOutputWindow: frameError. %s' % frameError)
            msg = 'CreateOutputWindow Frame Error: %s' % str(frameError)
            raise tse.ProgramException(tse.APPLICATION_TRAP, msg)
    def __init__(
        self,
        parent,
        id=wx.ID_ANY,
        label=wx.EmptyString,
        pos=wx.DefaultPosition,
        size=wx.DefaultSize,
        choices=wx.PyEmptyStringArray,
        majorDimension=0,
        style=wx.RA_HORIZONTAL,
        validator=wx.DefaultValidator,
        name=wx.RadioBoxNameStr,
    ):
        """
        Create a Control. Normally you should only call this from a
        subclass __init__ as a plain old wx.Control is not very useful.
        """
        # Also, remember that wx.RA_SPECIFY_COLS means that we arrange buttons
        # in left to right order and GetMajorDim() is the number of columns
        # while wx.RA_SPECIFY_ROWS means that the buttons are arranged top to
        # bottom and GetMajorDim() is the number of rows.
        theClass = "RadioBox"

        # Capture initial caller parametsrs before they are changed
        self.caller_parent = parent
        self.caller_id = id
        self.caller_label = label
        self.caller_pos = pos
        self.caller_size = size
        self.caller_choices = choices
        self.caller_majorDimension = majorDimension
        self.caller_style = style
        self.caller_validator = validator
        self.caller_name = name

        wx.RegisterFirstCallerClassName(self, theClass)

        Control.__init__(self, parent, id=id, pos=pos, size=size, style=style, validator=validator, name=name)

        self.tsBeginClassRegistration(theClass, id)

        if DEBUG:
            self.logger.debug("               self: %s" % self)
            self.logger.debug("             parent: %s" % parent)
            self.logger.debug("                 id: %s" % self.ts_Id)
            self.logger.debug("         AssignedId: %s" % self.ts_AssignedId)
            self.logger.debug("              label: %s" % label)
            self.logger.debug("                pos: %s" % str(pos))
            self.logger.debug("               size: %s" % str(size))
            self.logger.debug("            choices: %s" % choices)
            self.logger.debug("     majorDimension: %s" % majorDimension)
            self.logger.debug("              style: 0x%X" % style)
            #            self.logger.debug('          validator: 0x%X' % validator)
            self.logger.debug("               name: %s" % name)

        self.ts_Default = False

        self.ts_Name = name
        self.ts_Parent = parent

        theTopLevelClass = self
        self.SetTopLevelAncestor(theTopLevelClass)

        if parent is None:
            self.ts_GrandParent = None
        else:
            self.ts_GrandParent = parent.Parent

        if False:
            # Leaves artifacts of different color than parent background.
            self.ts_BackgroundColour = wx.ThemeToUse["BackgroundColour"].lower()
            self.ts_ForegroundColour = wx.ThemeToUse["ForegroundColour"].lower()
        else:
            self.ts_BackgroundColour = self.Parent.ts_BackgroundColour
            self.ts_ForegroundColour = self.Parent.ts_ForegroundColour

        self.ts_Choices = choices
        self.ts_Count = len(choices)
        self.ts_Label = label
        self.ts_MajorDimension = max(majorDimension, self.ts_Count)
        self.ts_Style = style
        self.ts_Validator = validator

        myRect, myClientRect = self.tsRadioBoxLayout(parent, pos, size, style, name)
        self.ts_Rect = myRect
        self.ts_ClientRect = myClientRect

        bestSize = self.tsBestSize()
        ##        style = 0

        self.ts_ItemLabel = []
        self.ts_ItemEnabled = []
        self.ts_ItemHelpText = []
        self.ts_ItemToolTip = []
        self.ts_ItemShown = []
        self.ts_ItemWindow = []

        # TBD - Verify scaling.
        if self.ts_Style & wx.RA_HORIZONTAL:
            itemWidth = bestSize.width // (self.ts_MajorDimension + 1)
        else:
            itemWidth = bestSize.width

        for item in range(self.ts_Count):
            self.ts_ItemLabel.append(self.ts_Choices[item])
            self.ts_ItemHelpText.append(self.ts_ItemLabel[item])
            self.ts_ItemToolTip.append(self.ts_ItemLabel[item])
            self.ts_ItemShown.append(True)

            if item == 0:
                self.ts_ItemEnabled.append(True)
            else:
                self.ts_ItemEnabled.append(False)

            # TBD - Under Construction.
            if self.ts_Style & wx.RA_HORIZONTAL:
                # Horizontal layout
                posTBD = wxPoint(
                    self.Rect.x + (item * itemWidth + 2) * wx.pixelWidthPerCharacter,
                    self.Rect.y + (2) * wx.pixelHeightPerCharacter,
                )
            else:
                # Vertical layout
                posTBD = wxPoint(
                    self.Rect.x + (2) * wx.pixelWidthPerCharacter, self.Rect.y + (item + 2) * wx.pixelHeightPerCharacter
                )

            ##            sizeTBD = wxSize(
            ##                (len('(*)  ') + len(
            ##                    self.ts_ItemLabel[item])) * wx.pixelWidthPerCharacter,
            ##                wx.pixelHeightPerCharacter)

            sizeTBD = wxSize(
                (len("(*)  ") + len(self.tsStripAcceleratorTextLabel(self.ts_ItemLabel[item])))
                * wx.pixelWidthPerCharacter,
                wx.pixelHeightPerCharacter,
            )

            self.ts_ItemWindow.append(
                wxRadioButton(
                    self,
                    id=wx.ID_ANY,
                    label=self.ts_ItemLabel[item],
                    pos=posTBD,
                    size=sizeTBD,
                    style=(self.ts_Style & wx.ALIGN_LEFT | self.ts_Style & wx.ALIGN_RIGHT | wx.NO_BORDER),
                    validator=wx.DefaultValidator,
                    name=self.ts_ItemLabel[item],
                )
            )

            self.ts_ItemWindow[item].SetValue(self.ts_ItemEnabled[item])

        if self.ts_Style & wx.RA_HORIZONTAL:
            self.ts_ColumnCount = self.ts_MajorDimension
            self.ts_RowCount = 1

        elif self.ts_Style & wx.RA_VERTICAL:
            self.ts_ColumnCount = 1
            self.ts_RowCount = self.ts_MajorDimension

        else:
            # TBD - Temporary dimension
            self.ts_ColumnCount = self.ts_MajorDimension
            rows, cols = divmod(self.ts_Count, self.ts_MajorDimension)
            if cols == 0:
                self.ts_RowCount = rows
            else:
                self.ts_RowCount = rows + 1

        self.ts_Selection = 0
        self.ts_StringSelection = 0

        # Automatically Bind all mouse events ASAP (now).
        # Will register event in the SystemEventTable.
        event = EVT_COMMAND_LEFT_CLICK
        handler = self.tsOnLeftClick
        source = self
        self.Bind(event, handler, source, useSystemEventTable=True)

        # Automatically Bind all Radio Button events ASAP (now).
        # Will register event in the SystemEventTable.
        event = EVT_RADIOBUTTON
        handler = self.tsOnRadioButtonClick
        source = self
        self.Bind(event, handler, source, useSystemEventTable=True)

        self.tsEndClassRegistration(theClass)
    def __init__(self,
                 parent,
                 id=wx.ID_ANY,
                 bitmap=None,
                 splashStyle=0,
                 milliseconds=0,
                 pos=wx.DefaultPosition,
                 size=wx.DefaultSize,
                 style=wx.DEFAULT_SPLASHSCREEN_STYLE):
        '''
        Construct class.
        '''
        theClass = 'SplashScreen'

        # Capture initial caller parametsrs before they are changed
        self.caller_bitmap = bitmap
        self.caller_splashStyle = splashStyle
        self.caller_milliseconds = milliseconds
        self.caller_parent = parent
        self.caller_id = id
        self.caller_pos = pos
        self.caller_size = size
        self.caller_style = style

        wx.RegisterFirstCallerClassName(self, theClass)

        TopLevelWindow.__init__(self)

        self.tsBeginClassRegistration(theClass, id)

##        size = wxSize(500, 300)
        Frame.__init__(
            self,
            parent,
            id=wx.ID_ANY,
            title=wx.EmptyString,
            pos=pos,
            size=size,
            style=wx.BORDER_SIMPLE, #wx.DEFAULT_SPLASHSCREEN_STYLE,
            name=wx.SplashScreenNameStr)

        splashWindow = self
        splashWindow.ts_ForegroundColour = wx.COLOR_RED
        splashWindow.ts_BackgroundColour = wx.COLOR_WHITE

        self.ts_SplashStyle = splashStyle
        self.ts_SplashWindow = splashWindow
        self.ts_SplashTimeout = milliseconds

        self.ts_bitmap = wxTextCtrl(
            splashWindow,
            id=-1,
            value=wx.EmptyString,
            pos=wxPoint(
                splashWindow.ts_ClientRect.x + wx.pixelWidthPerCharacter,
                splashWindow.ts_ClientRect.y + wx.pixelHeightPerCharacter),
            size=wxSize(
                splashWindow.ts_ClientRect.width - (
                    2 * wx.pixelWidthPerCharacter),
                splashWindow.ts_ClientRect.height -(
                    2 * wx.pixelHeightPerCharacter)),
            style=0, # wx.TE_MULTILINE |wx.TE_READONLY,
            validator=wx.DefaultValidator,
            name=wx.TextCtrlNameStr)

        self.ts_bitmap.AppendText(bitmap)
        self.ts_bitmap.Show()

        self.SetFocus()

##        print('SplashScreen: Show')
##        self.Show()
##        print('SplashScreen: Sleep(%d)' % self.ts_SplashTimeout)
##        time.sleep(self.ts_SplashTimeout / 1000)
##        print('SplashScreen: Hide')
##        self.Hide()

        self.tsEndClassRegistration(theClass)
 def GetSize(self):
     '''
     '''
     return (wxSize(w=self.ts_width, h=self.ts_height))
    def tsScrollBarGaugeLayout(self, parent, pos, size, style, name):
        '''
        Calculate position and size of gauge based upon arguments.
        '''
        if (not (self.ts_Handle is None)):

            # Inhibit operation once self.ts_Handle has been
            # assigned a curses window identifier.
            return (self.ts_Rect, self.ts_ClientRect)
 
        thePosition = self.tsGetClassInstanceFromTuple(pos, wxPoint)
        theSize = self.tsGetClassInstanceFromTuple(size, wxSize)

        theDefaultPosition = self.tsGetClassInstanceFromTuple(
            wx.DefaultPosition, wxPoint)
 
        theDefaultSize = self.tsGetClassInstanceFromTuple(
            wx.DefaultSize, wxSize)

        label = self.ts_Name

        if theSize == theDefaultSize:
            # theDefaultSize

            theLabelSize = theSize
            self.logger.debug(
                '      theLabelSize (begin): %s' % theLabelSize)

            if label is wx.EmptyString:
                # TBD - Adjust for cursor width
                theLabelSize = wxSize(
                    (len(label) + len('[]')) * wx.pixelWidthPerCharacter,
                    wx.pixelHeightPerCharacter)

            elif label.find('\n') == -1:
                # TBD - Remove adjustment for extra cursor width
                theLabelSize = wxSize(
                    (len(label) + len('[ ]')) * wx.pixelWidthPerCharacter,
                    wx.pixelHeightPerCharacter)
            else:
                # TBD - Remove adjustment for extra cursor width
                theLines = label.split('\n')
                maxWidth = 0
                maxHeight = len(theLines)
                for aLine in theLines:
                    if len(aLine) > maxWidth:
                        maxWidth = len(aLine)
                theLabelSize = wxSize(
                    (maxWidth + len('[ ]')) * wx.pixelWidthPerCharacter,
                    maxHeight * wx.pixelHeightPerCharacter)

            self.logger.debug(
                '      theLabelSize (end): %s' % theLabelSize)

            if False and thePosition == theDefaultPosition:
                # theDefaultPosition

                myRect = wxRect(parent.ClientArea.x,
                                parent.ClientArea.y,
                                theLabelSize.width,
                                theLabelSize.height)

            else:
                # Not theDefaultPosition

                myRect = wxRect(thePosition.x,
                                thePosition.y,
                                theLabelSize.width,
                                theLabelSize.height)

        else:
            # Not theDefaultSize

            if False and thePosition == theDefaultPosition:
                # theDefaultPosition

                myRect = wxRect(parent.ClientArea.x,
                                parent.ClientArea.y,
                                theSize.width,
                                theSize.height)

            else:
                # Not theDefaultPosition

                myRect = wxRect(thePosition.x,
                                thePosition.y,
                                theSize.width,
                                theSize.height)

        myClientRect = wxRect(myRect.x,
                              myRect.y,
                              myRect.width,
                              myRect.height)

        if ((self.Parent.ts_Style & wx.SB_HORIZONTAL) or \
            (self.Parent.ts_Style & wx.HSCROLL)):

            self.ts_GaugeThumbLines = (
                self.ts_ClientRect.width // wx.pixelWidthPerCharacter)

        else:

            self.ts_GaugeThumbLines = (
                self.ts_ClientRect.height // wx.pixelHeightPerCharacter)

        self.ts_Rect = myRect
        self.ts_ClientRect = myClientRect

        self.tsTrapIfTooSmall(name, myRect)
        fmt = 'parent=%s; pos=%s; size=%s; ' + \
              'name="%s"; label="%s"; myRect=%s'
        msg = fmt % (parent, str(pos), str(size), name, label, str(myRect))

        self.logger.debug('    tsScrollBarGaugeLayout: %s' % msg)

        return (myRect, myClientRect)
    def tsTextEntryDialogLayout(self, parent, pos, size, style, name):
        '''
        Calculate position and size of dialog based upon arguments.
        '''
        # Example Layout (wxPython TextEntryDialog)
        #
        #   Key:
        #       Caption = "Eh?"
        #       Message = "What is your favorite programming language?"
        #       Value   = "Python is the best!"
        #       Buttons = "OK" and "Cancel"
        #
        #   Layout:
        #       Title    = Caption
        #       VSizer1  = Message Line(s)
        #       VSizer2  = Value Line(s)
        #       VSizer3  = Horizontal Separator (TextLine)
        #       VSizer4  = Button(s)
        #       HSizer1  = Spacer (variable size)
        #       HSizer2  = OK Button (fixed size)
        #       HSizer3  = Cancel Button (fixed size)
        #
        # wxPython-Style (pixel-mode)
        #
        # +---------------------------------------------------------+
        # | Caption                                              [X]|
        # +---------------------------------------------------------+
        # | What is your favorite programming language?             |
        # |  +---------------------------------------------------+  |
        # |  |Python is the best!                                |  |
        # |  +---------------------------------------------------+  |
        # | ------------------------------------------------------- |
        # |                              +----------+ +----------+  |
        # |                              [    OK    ] [  Cancel  ]  |
        # |                              +----------+ +----------+  |
        # +---------------------------------------------------------+
        #
        # tsWxGTUI-Style (character-mode)
        #
        # +- Caption -------------------------------------- [?][X] -+
        # +---------------------------------------------------------+
        # | What is your favorite programming language?             |
        # |  +---------------------------------------------------+  |
        # |  |Python is the best!                                |  |
        # |  +---------------------------------------------------+  |
        # | ------------------------------------------------------- |
        # |                              [    OK    ] [  Cancel  ]  |
        # +---------------------------------------------------------+
        if (not (self.ts_Handle is None)):

            # Inhibit operation once self.ts_Handle has been
            # assigned a curses window identifier.
            return (self.ts_Rect, self.ts_ClientRect)

        thePosition = self.tsGetClassInstanceFromTuple(pos, wxPoint)
        theSize = self.tsGetClassInstanceFromTuple(size, wxSize)
        theBorder = self.tsIsBorderThickness(style, pixels=True)

        theDefaultPosition = self.tsGetClassInstanceFromTuple(
            wx.DefaultPosition, wxPoint)

        theDefaultSize = self.tsGetClassInstanceFromTuple(
            wx.DefaultSize, wxSize)

        if thePosition == theDefaultPosition and \
           theSize == theDefaultSize:

            if parent is None:

                myRect = wxRect(self.display.ClientArea.x,
                                self.display.ClientArea.y,
                                self.display.ClientArea.width,
                                self.display.ClientArea.height)
                myRect = self.display.ClientArea

            else:

                myRect = parent.GetClientArea(pixels=True)

        elif thePosition == theDefaultPosition:

            myRect = wxRect(self.display.ClientArea.x,
                            self.display.ClientArea.y,
                            theSize.width,
                            theSize.height)

        elif theSize == theDefaultSize:

            theDisplaySize = wxSize(
                self.display.ClientArea.width,
                self.display.ClientArea.height)

            myRect = wxRect(
                thePosition.x,
                thePosition.y,
                theDisplaySize.width - thePosition.x,
                theDisplaySize.height - thePosition.y)

        else:

            myRect = wxRect(thePosition.x,
                            thePosition.y,
                            theSize.width,
                            theSize.height)

            theDisplayRect = self.display.GetClientArea()
            if not theDisplayRect.InsideRect(myRect):
                myRect = wxRect(
                    max(thePosition.x, theDisplayRect.x),
                    max(thePosition.y, theDisplayRect.y),
                    min(theSize.width, theDisplayRect.width),
                    min(theSize.height, theDisplayRect.height - 1))

            if not theDisplayRect.InsideRect(myRect):
                myRect = theDisplayRect

        myClientRect = wxRect(myRect.x + theBorder.width,
                              myRect.y + theBorder.height,
                              myRect.width - 2 * theBorder.width,
                              myRect.height - 2 * theBorder.height)

        self.tsTrapIfTooSmall(name, myRect)
        msg = 'parent=%s; pos=%s; size=%s; name=%s; title=%s; myRect=%s' % \
              (parent, pos, size, name, self.Title, myRect)

        self.logger.debug('tsTextEntryDialog.' + \
                          'tsTextEntryDialogLayout: %s' % msg)

        return (myRect, myClientRect)
    def tsTrapIfTooSmall(self, name, myRect):
        '''
        '''
        # TBD - Under Construction.
        if True:
            return

        minScreenDimensions = wx.ThemeToUse['MinScreenDimensions']
        minScreenWidth = minScreenDimensions['FrameWidth']
        minScreenHeight = minScreenDimensions['FrameHeight'] + \
                          minScreenDimensions['MenuBarHeight'] + \
                          minScreenDimensions['ToolBarHeight'] + \
                          minScreenDimensions['StatusBarHeight'] + \
                          minScreenDimensions['RedirectionHeight'] + \
                          minScreenDimensions['TaskBarHeight']

        minClientHeight = minScreenDimensions['FrameHeight'] + \
                          minScreenDimensions['MenuBarHeight'] + \
                          minScreenDimensions['ToolBarHeight'] + \
                          minScreenDimensions['StatusBarHeight']

        minWidth = minScreenWidth

        if name == wx.TaskBarNameStr:
            minHeight = minScreenDimensions['TaskBarHeight']

        elif name == wx.StdioNameStr:
            minHeight = minScreenDimensions['RedirectionHeight']

        else:

            minHeight = minClientHeight

        minScreenSize = wxSize(minScreenWidth // wx.pixelWidthPerCharacter,
                               minScreenHeight // wx.pixelHeightPerCharacter)

        mySize = wxSize(myRect.width // wx.pixelWidthPerCharacter,
                        myRect.height // wx.pixelHeightPerCharacter)

        minSize = wxSize(minWidth // wx.pixelWidthPerCharacter,
                         minHeight // wx.pixelHeightPerCharacter)

        actualScreen = self.display.GetGeometry(pixels=True)
 
        actualScreenWidth = actualScreen.width
        actualScreenHeight = actualScreen.height
        actualScreenSize = wxSize(actualScreenWidth, actualScreenHeight)

        if actualScreenSize.width < minScreenSize.width:

            fmt = '  Screen "%s" width (%d) is too small.' + \
                  ' Please make screen at least (%d) columns'
            abortMsg = fmt % (self.display.Name,
                              actualScreenSize.width,
                              minScreenSize.width)

            self.logger.error('    tsTrapIfTooSmall: %s' % abortMsg)

            raise tse.UserInterfaceException(
                tse.GRAPHICAL_WINDOW_NOT_VALID, abortMsg)

        if actualScreenSize.height < minScreenSize.height:

            fmt = '  Screen "%s" height (%d) is too small.' + \
                  ' Please make screen at least (%d) lines'
            abortMsg = fmt % (self.display.Name,
                              actualScreenSize.height,
                              minScreenSize.height)

            self.logger.error('    tsTrapIfTooSmall: %s' % abortMsg)

            raise tse.UserInterfaceException(
                tse.GRAPHICAL_WINDOW_NOT_VALID, abortMsg)

        if mySize.width < minSize.width:

            fmt = '  Window "%s" width (%d) is too small.' + \
                  ' Please make screen at least (%d) columns'
            abortMsg = fmt % (name, mySize.width, minSize.width)

            self.logger.error('    tsTrapIfTooSmall: %s' % abortMsg)

            raise tse.UserInterfaceException(
                tse.GRAPHICAL_WINDOW_NOT_VALID, abortMsg)

        if mySize.height < minSize.height:

            fmt = '  Window "%s" height (%d) is too small.' + \
                  ' Please make screen at least (%d) lines'
            abortMsg = fmt % (name, mySize.height, minSize.height)

            self.logger.error('    tsTrapIfTooSmall: %s' % abortMsg)

            raise tse.UserInterfaceException(
                tse.GRAPHICAL_WINDOW_NOT_VALID, abortMsg)
from tsWxSizerItem import SizerItem as wxSizerItem
from tsWxStaticBox import StaticBox

#---------------------------------------------------------------------------

##DEBUG = True
DEBUG = wx.Debug_GUI_Launch | \
        wx.Debug_GUI_Progress | \
        wx.Debug_GUI_Termination | \
        wx.Debug_GUI_Exceptions

##VERBOSE = True
VERBOSE = wx.Debug_GUI_Configuration

DEFAULT_POS = wxPoint(wx.DefaultPosition)
DEFAULT_SIZE = wxSize(wx.DefaultSize)

#---------------------------------------------------------------------------
 
class StaticBoxSizer(BoxSizer):
    '''
    Class to establish a sizer derived from wxBoxSizer but adds a static
    box around the sizer.

    The static box may be either created independently or the sizer may
    create it itself as a convenience. In any case, the sizer owns the
    wxStaticBox control and will delete it in the wxStaticBoxSizer
    destructor.

    Note that since wxWidgets 2.9.1 you are encouraged to create the
    windows which are added to wxStaticBoxSizer as children of wxStaticBox
    def tsRadioButtonLayout(self, parent, pos, size, style, name):
        '''
        Calculate position and size of button based upon arguments.
        '''
        if (not (self.ts_Handle is None)):

            # Inhibit operation once self.ts_Handle has been
            # assigned a curses window identifier.
            return (self.ts_Rect, self.ts_ClientRect)
 
        if style is None:
            # Prevent pylint warning.
            pass

        thePosition = self.tsGetClassInstanceFromTuple(pos, wxPoint)
        theSize = self.tsGetClassInstanceFromTuple(size, wxSize)

        theDefaultPosition = self.tsGetClassInstanceFromTuple(
            wx.DefaultPosition, wxPoint)
 
        theDefaultSize = self.tsGetClassInstanceFromTuple(
            wx.DefaultSize, wxSize)


        label = self.ts_ButtonText

        if theSize == theDefaultSize:
            # theDefaultSize
##            print('default size layout label="%s"; pos=%s size=%s' % (
##                label, pos, size))

            theLabelSize = theSize
            self.logger.debug(
                '      theLabelSize (begin): %s' % theLabelSize)

            maxWidth = self.ts_Parent.ts_ClientRect.width - (
                2 * wx.pixelWidthPerCharacter)

            if label is wx.EmptyString:
                # TBD - Adjust for cursor width
                theLabelSize = wxSize(maxWidth, wx.pixelHeightPerCharacter)

            elif label.find('\n') == -1:
                # TBD - Remove adjustment for extra cursor width
                theLabelSize = wxSize(
                    (len(label) + len('[ ]')) * wx.pixelWidthPerCharacter,
                    wx.pixelHeightPerCharacter)
            else:
                # TBD - Remove adjustment for extra cursor width
                theLines = label.split('\n')
                maxWidth = 0
                maxHeight = len(theLines)
                for aLine in theLines:
                    if len(aLine) > maxWidth:
                        maxWidth = len(aLine)
                theLabelSize = wxSize(
                    (maxWidth + len('[ ]')) * wx.pixelWidthPerCharacter,
                    maxHeight * wx.pixelHeightPerCharacter)

            self.logger.debug(
                '      theLabelSize (end): %s' % theLabelSize)

            if False and thePosition == theDefaultPosition:
                # theDefaultPosition

                myRect = wxRect(parent.ClientArea.x,
                                parent.ClientArea.y,
                                theLabelSize.width,
                                theLabelSize.height)

            else:
                # Not theDefaultPosition

                myRect = wxRect(thePosition.x,
                                thePosition.y,
                                theLabelSize.width,
                                theLabelSize.height)

        else:
            # Not theDefaultSize
##            print('not default size layout label="%s"; pos=%s size=%s' % (
##                label, pos, size))

            if False and thePosition == theDefaultPosition:
                # theDefaultPosition

                myRect = wxRect(parent.ClientArea.x,
                                parent.ClientArea.y,
                                theSize.width,
                                theSize.height)

            else:
                # Not theDefaultPosition

                myRect = wxRect(thePosition.x,
                                thePosition.y,
                                theSize.width,
                                theSize.height)

##        theDisplayRect = self.Display.GetClientArea()
##        if not theDisplayRect.InsideRect(myRect):
##            myRect = wxRect(
##                max(thePosition.x, theDisplayRect.x),
##                max(thePosition.y, theDisplayRect.y),
##                min(theSize.width, theDisplayRect.width),
##                min(theSize.height, theDisplayRect.height - 1))

##        if not theDisplayRect.InsideRect(myRect):
##            myRect = theDisplayRect

        myClientRect = wxRect(myRect.x,
                              myRect.y,
                              myRect.width,
                              myRect.height)

        self.tsTrapIfTooSmall(name, myRect)
        fmt = 'parent=%s; pos=%s; size=%s; ' + \
              'name="%s"; label="%s"; myRect=%s'
        msg = fmt % (parent, str(pos), str(size), name, label, str(myRect))

        self.logger.debug('    tsRadioButtonLayout: %s' % msg)

        return (myRect, myClientRect)
    def tsStaticTextLayout(self, parent, pos, size, style, name):
        '''
        Calculate position and size of static text based upon arguments.
        '''
        if (not (self.ts_Handle is None)):

            # Inhibit operation once self.ts_Handle has been
            # assigned a curses window identifier.
            return (self.ts_Rect, self.ts_ClientRect)
 
        thePosition = self.tsGetClassInstanceFromTuple(pos, wxPoint)
        theSize = self.tsGetClassInstanceFromTuple(size, wxSize)
        theBorder = self.tsIsBorderThickness(style, pixels=True)

        theDefaultPosition = self.tsGetClassInstanceFromTuple(
            wx.DefaultPosition, wxPoint)
 
        theDefaultSize = self.tsGetClassInstanceFromTuple(
            wx.DefaultSize, wxSize)

        label = self.ts_Text

        if theSize == theDefaultSize:
            # theDefaultSize

            theLabelSize = theSize
            self.logger.debug(
                '      theLabelSize (begin): %s' % theLabelSize)

            if label is None:
                # TBD - Adjust for cursor width
                theLabelSize = wxSize(0, 0)
                self.logger.warning(
                    'theLabelSize: %s for None' % theLabelSize)
            elif label is wx.EmptyString:
                # TBD - Adjust for cursor width
                theLabelSize = wxSize(wx.pixelWidthPerCharacter,
                                      wx.pixelHeightPerCharacter)
            elif label.find('\n') == -1:
                # TBD - Remove adjustment for extra cursor width
                theLabelSize = wxSize(
                    (len(label) + 0) * wx.pixelWidthPerCharacter,
                    wx.pixelHeightPerCharacter)
            else:
                # TBD - Remove adjustment for extra cursor width
                theLines = label.split('\n')
                maxWidth = 0
                maxHeight = len(theLines)
                for aLine in theLines:
                    if len(aLine) > maxWidth:
                        maxWidth = len(aLine)
                theLabelSize = wxSize(
                    (maxWidth + 0) * wx.pixelWidthPerCharacter,
                    maxHeight * wx.pixelHeightPerCharacter)

            self.logger.debug(
                '      theLabelSize (end): %s' % theLabelSize)

            if thePosition == theDefaultPosition:
                # theDefaultPosition

                myRect = wxRect(parent.ClientRect.x,
                                parent.ClientRect.y,
                                theLabelSize.width,
                                theLabelSize.height)

            else:
                # Not theDefaultPosition

                myRect = wxRect(thePosition.x,
                                thePosition.y,
                                theLabelSize.width,
                                theLabelSize.height)

        else:
            # Not theDefaultSize

            if thePosition == theDefaultPosition:
                # theDefaultPosition

                myRect = wxRect(parent.ClientRect.x,
                                parent.ClientRect.y,
                                theSize.width,
                                theSize.height)

            else:
                # Not theDefaultPosition

                myRect = wxRect(thePosition.x,
                                thePosition.y,
                                theSize.width,
                                theSize.height)

##        theDisplayRect = self.Display.GetClientArea()
##        if not theDisplayRect.InsideRect(myRect):
##            myRect = wxRect(
##                max(thePosition.x, theDisplayRect.x),
##                max(thePosition.y, theDisplayRect.y),
##                min(theSize.width, theDisplayRect.width),
##                min(theSize.height, theDisplayRect.height - 1))

##        if not theDisplayRect.InsideRect(myRect):
##            myRect = theDisplayRect

        myClientRect = wxRect(myRect.x,
                              myRect.y,
                              myRect.width,
                              myRect.height)

        self.tsTrapIfTooSmall(name, myRect)
        msg = 'parent=%s; pos=%s; size=%s; name=%s; label=%s; myRect=%s' % \
              (parent, pos, size, name, label, myRect)

        self.logger.debug('    tsStaticTextLayout: %s' % msg)

        return (myRect, myClientRect)
    def tsButtonLayout(self, parent, pos, size, style, name):
        """
        Calculate position and size of button based upon arguments.
        """
        if not (self.ts_Handle is None):

            # Inhibit operation once self.ts_Handle has been
            # assigned a curses window identifier.
            return (self.ts_Rect, self.ts_ClientRect)

        if style is None:
            # Prevent pylint warning.
            pass

        thePosition = self.tsGetClassInstanceFromTuple(pos, wxPoint)
        theSize = self.tsGetClassInstanceFromTuple(size, wxSize)

        theDefaultPosition = self.tsGetClassInstanceFromTuple(wx.DefaultPosition, wxPoint)

        theDefaultSize = self.tsGetClassInstanceFromTuple(wx.DefaultSize, wxSize)

        label = self.ts_ButtonText

        # Ignore UseClientArea because cursor wraps beyond bottom
        # when last character has been output.
        if self.ts_UseClientArea:
            offset = wxPoint(0, 0)
        else:
            offset = wxPoint(0, 0)

        if theSize == theDefaultSize:
            # theDefaultSize

            theLabelSize = theSize
            self.logger.debug("      theLabelSize (begin): %s" % theLabelSize)

            if label is wx.EmptyString:
                # TBD - Adjust for cursor width
                theLabelSize = wxSize((len(label) + len("[]")) * wx.pixelWidthPerCharacter, wx.pixelHeightPerCharacter)

            elif label.find("\n") == -1:
                # TBD - Remove adjustment for extra cursor width
                theLabelSize = wxSize((len(label) + len("[ ]")) * wx.pixelWidthPerCharacter, wx.pixelHeightPerCharacter)
            else:
                # TBD - Remove adjustment for extra cursor width
                theLines = label.split("\n")
                maxWidth = 0
                maxHeight = len(theLines)
                for aLine in theLines:
                    if len(aLine) > maxWidth:
                        maxWidth = len(aLine)
                theLabelSize = wxSize(
                    (maxWidth + len("[ ]")) * wx.pixelWidthPerCharacter, maxHeight * wx.pixelHeightPerCharacter
                )

            self.logger.debug("      theLabelSize (end): %s" % theLabelSize)

            if thePosition == theDefaultPosition:
                # theDefaultPosition

                myRect = wxRect(parent.ClientArea.x, parent.ClientArea.y, theLabelSize.width, theLabelSize.height)

            else:
                # Not theDefaultPosition

                myRect = wxRect(
                    offset.x + thePosition.x, offset.y + thePosition.y, theLabelSize.width, theLabelSize.height
                )

        else:
            # Not theDefaultSize

            if thePosition == theDefaultPosition:
                # theDefaultPosition

                myRect = wxRect(parent.ClientArea.x, parent.ClientArea.y, theSize.width, theSize.height)

            else:
                # Not theDefaultPosition

                myRect = wxRect(offset.x + thePosition.x, offset.y + thePosition.y, theSize.width, theSize.height)

        ##        theDisplayRect = self.Display.GetClientArea()
        ##        if not theDisplayRect.InsideRect(myRect):
        ##            myRect = wxRect(
        ##                max(thePosition.x, theDisplayRect.x),
        ##                max(thePosition.y, theDisplayRect.y),
        ##                min(theSize.width, theDisplayRect.width),
        ##                min(theSize.height, theDisplayRect.height - 1))

        ##        if not theDisplayRect.InsideRect(myRect):
        ##            myRect = theDisplayRect

        myClientRect = wxRect(myRect.x, myRect.y, myRect.width, myRect.height)

        self.tsTrapIfTooSmall(name, myRect)
        fmt = "parent=%s; pos=%s; size=%s; " + 'name="%s"; label="%s"; myRect=%s'
        msg = fmt % (parent, str(pos), str(size), name, label, str(myRect))

        self.logger.debug("    tsButtonLayout: %s" % msg)

        return (myRect, myClientRect)
    def CalcMin(self):
        '''
        Calculate the total minimum width and height needed by all items
        in the sizer according to this sizer layout algorithm.
        '''
        # The minimal size for the sizer should be big enough to allocate
        # its element at least its minimal size but also, and this is the
        # non-trivial part, to respect the children proportion. To satisfy
        # the latter condition we must find the greatest min-size-to-
        # proportion ratio for all elements with non-zero proportion.

        # This sizer instance only manages a single parent's client area.
        # Unlike wxWidgets, a parent's client area depends on size of
        # Top Level Window (Frame or Dialog) that depends on initial size
        # of Display Screen which was manually set by a System Operator.

        sizerClientArea = self.FindSizerClientArea()
        self.logger.debug(
            'StaticBoxSizer.CalcMin: sizerClientArea=%s' % str(
                sizerClientArea))

        self.ts_CalcMinArea = []
        self.ts_CalcMinAreaProportion = []
        self.ts_CalcMinKind = []
        self.ts_CalcMinWindow = []
        self.ts_ClientArea = []
        self.ts_ContainingWindow = None
        self.ts_MinSize = wxSize(0, 0)
        self.ts_SizeMinThis = []
        self.ts_TotalFixedSize = wxSize(0, 0)
        self.ts_TotalProportion = 0

        for i in range(0, self.ts_Children.GetCount()):
            node = self.ts_Children.GetIndex(i)

            item =  node.GetUserData()
            msg = 'StaticBoxSizer.CalcMin: item[%d]=%s' % (i, str(item))
##            print(msg)
            self.logger.debug(msg)

            if (True or item.IsShown()):

                # sizeMinThis = item.CalcMin()
                # TBD - Not sure if the following is equivalent.

                if (item.ts_Kind == wx.Item_None):

                    msg = 'Kind: %s' % 'Item_None'
                    sizeMinThis = wxSize(0, 0)
                    self.ts_CalcMinWindow += [None]

                elif (item.ts_Kind == wx.Item_Sizer):

                    msg = 'Kind: %s' % 'Item_Sizer'
                    self.ts_Sizer.Layout()
                    self.ts_CalcMinWindow += [None]
                    sizeMinThis = item.ts_Sizer.Size

                elif (item.ts_Kind == wx.Item_Spacer):

                    msg = 'Kind: %s' % 'Item_Spacer'
                    self.ts_CalcMinWindow += [None]
                    sizeMinThis = item.ts_Spacer.Size

                elif (item.ts_Kind == wx.Item_Window):

                    msg = 'Kind: %s' % 'Item_Window'
                    self.ts_CalcMinWindow += [item.ts_Window]
                    parent = item.ts_Window.ts_Parent
                    clientArea = parent.ClientArea

                    if (clientArea == sizerClientArea):

                        theRect = parent.Rect
                        theClientArea = parent.ClientArea
                        print('StaticBoxSizer.CalcMin: ' + \
                              'Rect=%s; ClientArea=%s' % (
                                  str(theRect),
                                  str(theClientArea)))

                    else:

                        theRect = parent.Rect
                        theClientArea = parent.ClientArea
                        print(
                            'StaticBoxSizer.CalcMin: ' + \
                            'Rect=%s; ClientArea=%s' % (
                                str(theRect),
                                str(theClientArea)))
                        self.logger.error(
                            'StaticBoxSizer.CalcMin: ' + \
                            'Rect=%s; ClientArea=%s' % (
                                str(theRect),
                                str(theClientArea)))

                    msg = '%s; Parent.clientArea=%s' % (msg, str(clientArea))
                    sizeMinThis = wxSize(clientArea.width, clientArea.height)

                    if (self.ts_ContainingWindow is None):

                        self.ts_ContainingWindow = parent
                        self.ts_ClientArea = clientArea

                    elif (self.ts_ContainingWindow == parent):

                        pass

                    else:

                        fmt1 = 'StaticBoxSizer.CalcMin: '
                        fmt2 = 'Rejected Parent=%s' % str(parent)
                        fmt3 = 'Previous Parent=%s' % str(
                            self.ts_ContainingWindow)
                        msgError = fmt1 + fmt2 + fmt3
                        print(msgError)
                        self.logger.error(msgError)

                elif (item.ts_Kind == wx.Item_Max):

                    msg = 'Kind: %s' % 'Item_Max'
                    self.ts_CalcMinWindow += [None]
                    sizeMinThis = wxSize(0, 0)

                else:

                    msg = 'Kind: %s' % 'Item_Unknown'
                    self.ts_CalcMinWindow += [None]
                    sizeMinThis = wxSize(0, 0)

                self.logger.debug(msg)

                propThis = item.GetProportion()

                self.ts_CalcMinArea += [sizeMinThis]
                self.ts_CalcMinAreaProportion += [propThis]
                self.ts_CalcMinKind += [item.ts_Kind]
                self.ts_SizeMinThis += [sizeMinThis]

                if (propThis != 0):

                    # Adjustable size item

                    self.ts_TotalProportion += propThis

                    msg = 'StaticBoxSizer.CalcMin: ' + \
                          'item[%d]=%s; totalProp= %s' % (
                              i, str(item), str(self.ts_TotalProportion))
                    self.logger.debug(msg)

                else:

                    # Fixed size item

                    self.ts_TotalFixedSize += sizeMinThis

                    msg = 'StaticBoxSizer.CalcMin: ' + \
                          'item[%d]=%s; totalFixed= %s' % (
                              i, str(item), str(self.ts_TotalFixedSize))
                    self.logger.debug(msg)

        for i in range(0, self.ts_Children.GetCount()):

            if (self.ts_Orientation == wx.HORIZONTAL):

                orientation = 'HORIZONTAL'
                self.ts_CalcMinArea[i].height = self.ts_ClientArea.height

                if (self.ts_CalcMinAreaProportion[i] == 0):

                    self.ts_CalcMinArea[
                        i].width = self.ts_SizeMinThis[i].width

                else:

                    scalableWidth = self.ts_ClientArea.width - \
                                    self.ts_TotalFixedSize.width

                    self.ts_CalcMinArea[i].width = int(0.5 + (
                        scalableWidth * (
                            float(self.ts_CalcMinAreaProportion[i]) /
                            float(self.ts_TotalProportion))))

            else:

                orientation = '  VERTICAL'
                self.ts_CalcMinArea[i].width = self.ts_ClientArea.width

                if (self.ts_CalcMinAreaProportion[i] == 0):

                    self.ts_CalcMinArea[
                        i].height = self.ts_SizeMinThis[i].height

                else:

                    scalableHeight = self.ts_ClientArea.height - \
                                     self.ts_TotalFixedSize.height

                    self.ts_CalcMinArea[i].height = int(0.5 + (
                        scalableHeight * (
                            float(self.ts_CalcMinAreaProportion[i]) /
                            float(self.ts_TotalProportion))))

                if True:

                    # Adjust to be multiple of standard character size
                    self.ts_CalcMinArea[i].width = (
                        (self.ts_CalcMinArea[i].width // \
                         wx.pixelWidthPerCharacter) * \
                        wx.pixelWidthPerCharacter)

                    self.ts_CalcMinArea[i].height = (
                        (self.ts_CalcMinArea[i].height // \
                         wx.pixelHeightPerCharacter) * \
                        wx.pixelHeightPerCharacter)

            fmt1 = '%s CalcMinArea[%d]: width=%3d; height=%3d; ' % (
                orientation,
                i,
                int(self.ts_CalcMinArea[i].width),
                int(self.ts_CalcMinArea[i].height))

            fmt2 = 'totalProportion=%3d' % int(self.ts_TotalProportion)

            self.logger.debug(fmt1 + fmt2)

        theCalcMinSize = self.GetSizeInMajorDir(self.ts_ClientArea)
        self.logger.debug('theCalcMinSize=%d' % theCalcMinSize)
        return (theCalcMinSize)
    def tsDialogWindowLayout(self, parent, pos, size, style, name):
        '''
        Calculate position and size of dialog based upon arguments.
        '''
        if (not (self.ts_Handle is None)):

            # Inhibit operation once self.ts_Handle has been
            # assigned a curses window identifier.
            return (self.ts_Rect, self.ts_ClientRect)

        thePosition = self.tsGetClassInstanceFromTuple(pos, wxPoint)
        theSize = self.tsGetClassInstanceFromTuple(size, wxSize)
        theBorder = self.tsIsBorderThickness(style, pixels=True)

        theDefaultPosition = self.tsGetClassInstanceFromTuple(
            wx.DefaultPosition, wxPoint)

        theDefaultSize = self.tsGetClassInstanceFromTuple(
            wx.DefaultSize, wxSize)

        if thePosition == theDefaultPosition and \
           theSize == theDefaultSize:

            if parent is None:

##                myRect = wxRect(self.display.ClientArea.x,
##                                self.display.ClientArea.y,
##                                self.display.ClientArea.width,
##                                self.display.ClientArea.height)
                myRect = self.display.ClientArea

            else:

                myRect = parent.GetClientArea(pixels=True)

        elif thePosition == theDefaultPosition:

            myRect = wxRect(self.display.ClientArea.x,
                            self.display.ClientArea.y,
                            theSize.width,
                            theSize.height)

        elif theSize == theDefaultSize:

            theDisplaySize = wxSize(
                self.display.ClientArea.width,
                self.display.ClientArea.height)

            myRect = wxRect(
                thePosition.x,
                thePosition.y,
                theDisplaySize.width - thePosition.x,
                theDisplaySize.height - thePosition.y)

        else:

            myRect = wxRect(thePosition.x,
                            thePosition.y,
                            theSize.width,
                            theSize.height)

            theDisplayRect = self.display.GetClientArea()
            if not theDisplayRect.InsideRect(myRect):
                myRect = wxRect(
                    max(thePosition.x, theDisplayRect.x),
                    max(thePosition.y, theDisplayRect.y),
                    min(theSize.width, theDisplayRect.width),
                    min(theSize.height, theDisplayRect.height - 1))

            if not theDisplayRect.InsideRect(myRect):
                myRect = theDisplayRect

        myClientRect = wxRect(myRect.x + theBorder.width,
                              myRect.y + theBorder.height,
                              myRect.width - 2 * theBorder.width,
                              myRect.height - 2 * theBorder.height)

        self.tsTrapIfTooSmall(name, myRect)
        msg = 'parent=%s; pos=%s; size=%s; name=%s; title=%s; myRect=%s' % \
              (parent, pos, size, name, self.Title, myRect)

        self.logger.debug('    tsDialogWindowLayout: %s' % msg)

        return (myRect, myClientRect)