
"""Demonstrates the little square issue."""

import time
import numpy as np
import wx

# Some variables to control testing various options.
_use_panel = True         # True to add a wx.Panel to the wx.Frame;
                          # False to not use a wx.Panel.
                          # The parent of the wx.StaticBitmap is then either
                          # the wx.Panel, or the plain wx.Frame.
_background_color = 'Red' # None to use wx.NullColour for the background;
                          # a str (eg. 'Red' to select a background color.
_refresh = False          # True to call Refresh() immediately after creating
                          # the wx.StaticBitmap; False to not make the call.
_sleep_s = 0.25           # Sleep time (seconds) between toggling from one
                          # image to the other.
_use_wit = True           # True to start an instance of the Widget Inspection
                          # Tool; False to not start it.


# =============================================================================
class Frame1(wx.Frame):
    """Frame class to show little square issue."""

    # -------------------------------------------------------------------------
    def __init__(self):
        super(Frame1, self).__init__(parent=None, id=wx.ID_ANY,
                                     title='Little square', size=(720, 600))

        # The parent window of the wx.StaticBitmap will either be the wx.Frame
        # itself, or a wx.Panel.
        self._parent_wnd = wx.Panel(self) if _use_panel else self
        # Set the background color.
        self._parent_wnd.SetBackgroundColour(wx.NullColour
                                             if (_background_color is None)
                                             else _background_color)

        # Variable to control toggling images.
        self._keep_looping = False
        # Currently-displayed static bitmap.
        self._sbmp = None

        # Add a status bar
        self._statusbar = self.CreateStatusBar()
        self._write_status_message()
        # Bind to a keystroke, so we can start and stop toggling images.
        self.Bind(wx.EVT_CHAR_HOOK, self.OnCharhook)
        return

    # -------------------------------------------------------------------------
    def _write_status_message(self):
        """Write instructions to status bar."""
        self._statusbar.SetStatusText('Press any key to stop toggling.'
                                      if self._keep_looping else
                                      'Press any key to start toggling.')
        return

    # -------------------------------------------------------------------------
    def OnCharhook(self, event):
        """Respond to a keystroke by starting or stopping the loop."""
        self._keep_looping = not self._keep_looping
        self._write_status_message()
        if self._keep_looping:
            self._start_loop()
        return

    # -------------------------------------------------------------------------
    def _start_loop(self):
        """Start toggling between images."""
        image1, image2 = Frame1.generate_images()
        i = 0

        while self._keep_looping:
            # Show a bitmap of the current image.
            self._sbmp = wx.StaticBitmap(self._parent_wnd, wx.ID_ANY,
                                         wx.Bitmap(image1 if (i & 0x01) else
                                                   image2))
            i ^= 1
            if _refresh:
                self._parent_wnd.Refresh()
            wx.Yield()
            time.sleep(_sleep_s)
            wx.Yield()
        return

    # -------------------------------------------------------------------------
    @staticmethod
    def generate_images():
        """Generate two wx.Image instances with different colors."""
        nrows, ncols = 480, 640
        arr = np.empty((nrows, ncols, 3), dtype=np.uint8)
        for plane, value in enumerate([50, 75, 100]):  # RGB components
            arr[:, :, plane] = value
        arr2 = np.copy(arr)
        arr2 += 100          # Brighter image.
        return wx.Image(ncols, nrows, arr), wx.Image(ncols, nrows, arr2)


# =============================================================================
class MainApp(wx.App):
    """MainApp class."""

    # -------------------------------------------------------------------------
    def OnInit(self):
        """OnInit for the application."""
        self._frame = Frame1()
        self._frame.Show(True)
        self.SetTopWindow(self._frame)
        return True


# =============================================================================
if __name__ == '__main__':
    app = MainApp()
    if _use_wit:
        import wx.lib.inspection
        wx.lib.inspection.InspectionTool().Show()
    app.MainLoop()
