Module Gnumed.wxpython.gmImageWidgets

GNUmed image display widgets.

Classes

class cImageDisplay (parent, ID, bitmap, **kwargs)
Expand source code
class cImageDisplay(wx.lib.statbmp.GenStaticBitmap):
        """Control showing an image."""
        def __init__(self, parent, ID, bitmap, **kwargs):
                self.__empty_bmp = wx.Bitmap(wx.Image(1, 1, True))
                super().__init__(parent, ID, self.__empty_bmp, **kwargs)
                self.__init_ui()
                self.__filename = None
                self.__zoom_count = 0
                self.__min_width = 25
                self.__current_rotation = 0             # in degrees
                self.__callback_on_lclick = None
                self.refresh()

        #--------------------------------------------------------
        def process_char(self, char) -> bool:
                """Call action based on character.

                Returns:
                        True/False based on whether the character mapped to a command.
                """
                match char:
                        case 'r':
                                self.__current_rotation += 90
                                if self.__current_rotation == 360:
                                        self.__current_rotation = 0
                                self.refresh()
                        case 'l':
                                self.__current_rotation -= 90
                                if self.__current_rotation == -360:
                                        self.__current_rotation = 0
                                self.refresh()
                        case 'o':
                                self.__zoom_count = 0
                                self.__current_rotation = 0
                                self.refresh()
                        case '+':
                                self.__zoom_count += 1
                                self.refresh()
                        case '-':
                                self.__zoom_count -= 1
                                self.refresh()
                        case _:
                                return False

                return True

        #--------------------------------------------------------
        def process_keycode(self, keycode) -> bool:
                """Call action based on translated key code.

                Returns:
                        True/False based on whether the key code mapped to a command.
                """
                return False
#               match keycode:
#                       case 317: print('scroll down')
#                       case 315: print('scroll up')
#                       case 314: print('scroll left')
#                       case 316: print('scroll right')
#                       case _:
#                               print('bmp/unmapped keycode:', keycode)
#                               return False
#
#               return True

        #--------------------------------------------------------
        # event handlers
        #--------------------------------------------------------
        def _on_bitmap_leftclicked(self, event):
                event.Skip()
                self.SetFocus()
                if not self.__callback_on_lclick:
                        return

                self.__callback_on_lclick()

        #--------------------------------------------------------
        def _on_char(self, event):
                uk = event.UnicodeKey
                if uk != wx.WXK_NONE:
                        if not self.process_char(chr(uk)):
                                event.Skip()
                        return

                kc = event.KeyCode
                if kc != wx.WXK_NONE:
                        self.process_keycode(kc)
                        if not self.process_keycode(kc):
                                event.Skip()
                        return

                event.Skip()

        #--------------------------------------------------------
        # properties
        #--------------------------------------------------------
        def __get_filename(self):
                return self.__filename

        def __set_filename(self, filename:str):
                if filename != self.__filename:
                        self.__zoom_count = 0
                        self.__current_rotation = 0
                self.__filename = filename
                self.refresh()

        filename = property(__get_filename, __set_filename)

        #--------------------------------------------------------
        # internal helpers
        #--------------------------------------------------------
        def __init_ui(self):
                self.Bind(wx.EVT_LEFT_UP, self._on_bitmap_leftclicked)
                self.Bind(wx.EVT_CHAR, self._on_char)

        #--------------------------------------------------------
        def __adjust_bitmap(self):
                img_data = None
                bitmap = None
                try:
                        img_data = wx.Image(self.__filename, wx.BITMAP_TYPE_ANY)
                        orig_width = img_data.GetWidth()
                except Exception:
                        _log.exception('cannot load image from [%s]', self.__filename)
                        return False

                if self.__zoom_count != 0:
                        zoom_step = orig_width // 10
                        target_width = orig_width + (zoom_step * self.__zoom_count)
                        target_width = max(target_width, self.__min_width)
                        try:
                                orig_height = img_data.GetHeight()
                                target_height = round((orig_height / orig_width) * target_width)
                                if target_height and target_width:
                                        img_data.Rescale(target_width, target_height, quality = wx.IMAGE_QUALITY_HIGH)
                                else:
                                        _log.debug('cannot resize image [%s] to %sx%s', self.__filename, target_width, target_height)
                        except Exception:
                                _log.exception('cannot resize image [%s]', self.__filename)
                                return False

                try:
                        for cnt in range(abs(self.__current_rotation) // 90):
                                img_data = img_data.Rotate90(clockwise = self.__current_rotation > 0)
                except Exception:
                        _log.exception('cannot rotate image from [%s]', self.__filename)
                        return False

                try:
                        bitmap = wx.Bitmap(img_data)
                except Exception:
                        _log.exception('cannot create bitmap from image in [%s]', self.__filename)
                        return False

                return bitmap

        #--------------------------------------------------------
        def refresh(self):
                self.SetBitmap(self.__empty_bmp)
                if not self.__filename:
                        return None

                bitmap = self.__adjust_bitmap()
                if not bitmap:
                        return False

                self.SetBitmap(bitmap)
                return True

Control showing an image.

Default class constructor.

:param parent: parent window, must not be None; :param integer ID: window identifier. A value of -1 indicates a default value; :param wx.Bitmap bitmap: the static bitmap used in the control; :param pos: the control position. A value of (-1, -1) indicates a default position, chosen by either the windowing system or wxPython, depending on platform; :param size: the control size. A value of (-1, -1) indicates a default size, chosen by either the windowing system or wxPython, depending on platform; :param integer style: the underlying :class:wx.Control style; :param string name: the widget name.

:type parent: :class:wx.Window :type pos: tuple or :class:wx.Point :type size: tuple or :class:wx.Size

Ancestors

  • wx.lib.statbmp.GenStaticBitmap
  • wx._core.Control
  • wx._core.Window
  • wx._core.WindowBase
  • wx._core.EvtHandler
  • wx._core.Object
  • wx._core.Trackable
  • sip.wrapper
  • sip.simplewrapper

Instance variables

prop filename
Expand source code
def __get_filename(self):
        return self.__filename

Methods

def process_char(self, char) ‑> bool
Expand source code
def process_char(self, char) -> bool:
        """Call action based on character.

        Returns:
                True/False based on whether the character mapped to a command.
        """
        match char:
                case 'r':
                        self.__current_rotation += 90
                        if self.__current_rotation == 360:
                                self.__current_rotation = 0
                        self.refresh()
                case 'l':
                        self.__current_rotation -= 90
                        if self.__current_rotation == -360:
                                self.__current_rotation = 0
                        self.refresh()
                case 'o':
                        self.__zoom_count = 0
                        self.__current_rotation = 0
                        self.refresh()
                case '+':
                        self.__zoom_count += 1
                        self.refresh()
                case '-':
                        self.__zoom_count -= 1
                        self.refresh()
                case _:
                        return False

        return True

Call action based on character.

Returns

True/False based on whether the character mapped to a command.

def process_keycode(self, keycode) ‑> bool
Expand source code
def process_keycode(self, keycode) -> bool:
        """Call action based on translated key code.

        Returns:
                True/False based on whether the key code mapped to a command.
        """
        return False

Call action based on translated key code.

Returns

True/False based on whether the key code mapped to a command.

def refresh(self)
Expand source code
def refresh(self):
        self.SetBitmap(self.__empty_bmp)
        if not self.__filename:
                return None

        bitmap = self.__adjust_bitmap()
        if not bitmap:
                return False

        self.SetBitmap(bitmap)
        return True