소스 검색

wxGUI: more Python 3.10 fixes (#2050)

* wxGUI/gui_core: SpinCtrl widget require integer min, max param arg
* wxGUI/gui_core: add ConvertParamArgToInt mixin class for conversion args, kwargs float value to the int
* wxGUI/gui_core: Rect widget require integer x, y param arg
* wxGUI/gui_core: PseudoDC widget DrawRectangle method require integer x, y, width, height param arg
* wxGUI/psmap: wx.MemoryDC widget DrawBitmap method require integer x, y param arg
* wxGUI/psmap: wx.Rect widget Inflate method require integer dx, dy param arg
* wxGUI/gui_core: PseudoDC widget DrawBitmap method require integer x, y param arg
* wxGUI/gui_core: PseudoDC widget DrawCircle method require integer x, y, radius param arg
* wxGUI/gui_core: PseudoDC widget DrawLinePoint method require integer x1, y1, x2, y2 param arg
* wxGUI/gui_core: Rect widget CenterIn method require wx.Rect r param arg
* wxGUI/gui_core: PseudoDC widget SetIdBounds method require wx.Rect rect param arg

Co-authored-by: Tomas Zigo <tomas.zigo@slovanet.sk>
Anna Petrasova 3 년 전
부모
커밋
ecd13587d7

+ 10 - 6
gui/wxpython/animation/frame.py

@@ -28,8 +28,8 @@ import grass.script as gcore
 import grass.temporal as tgis
 from core import globalvar
 from gui_core.widgets import IntegerValidator
-from gui_core.wrap import StaticText, TextCtrl
-from core.gcmd import RunCommand
+from gui_core.wrap import StaticText, TextCtrl, Slider
+from core.gcmd import RunCommand, GWarning
 
 from animation.mapwindow import AnimationWindow
 from animation.provider import BitmapProvider, BitmapPool, \
@@ -380,10 +380,14 @@ class AnimationSliderBase(wx.Panel):
     def __init__(self, parent):
         wx.Panel.__init__(self, parent=parent, id=wx.ID_ANY)
         self.label1 = StaticText(self, id=wx.ID_ANY)
-        self.slider = wx.Slider(self, id=wx.ID_ANY, style=wx.SL_HORIZONTAL)
-        self.indexField = TextCtrl(self, id=wx.ID_ANY, size=(40, -1),
-                                   style=wx.TE_PROCESS_ENTER | wx.TE_RIGHT,
-                                   validator=IntegerValidator())
+        self.slider = Slider(self, id=wx.ID_ANY, style=wx.SL_HORIZONTAL)
+        self.indexField = TextCtrl(
+            self,
+            id=wx.ID_ANY,
+            size=(40, -1),
+            style=wx.TE_PROCESS_ENTER | wx.TE_RIGHT,
+            validator=IntegerValidator(),
+        )
 
         self.callbackSliderChanging = None
         self.callbackSliderChanged = None

+ 1 - 1
gui/wxpython/animation/provider.py

@@ -813,7 +813,7 @@ def createNoDataBitmap(imageWidth, imageHeight, text="No data"):
     dc.SetFont(wx.Font(pointSize=40, family=wx.FONTFAMILY_SCRIPT,
                        style=wx.FONTSTYLE_NORMAL, weight=wx.FONTWEIGHT_BOLD))
     tw, th = dc.GetTextExtent(text)
-    dc.DrawText(text, (imageWidth - tw) / 2, (imageHeight - th) / 2)
+    dc.DrawText(text, (imageWidth - tw) // 2, (imageHeight - th) // 2)
     dc.SelectObject(wx.NullBitmap)
     return bitmap
 

+ 1 - 1
gui/wxpython/gmodeler/frame.py

@@ -1257,7 +1257,7 @@ class ModelCanvas(ogl.ShapeCanvas):
         self.SetDiagram(self.diagram)
         self.diagram.SetCanvas(self)
 
-        self.SetScrollbars(20, 20, 2000 / 20, 2000 / 20)
+        self.SetScrollbars(20, 20, 2000 // 20, 2000 // 20)
 
         self.Bind(wx.EVT_KEY_UP, self.OnKeyUp)
         self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)

+ 18 - 4
gui/wxpython/gui_core/dialogs.py

@@ -48,8 +48,20 @@ from gui_core.widgets import SingleSymbolPanel, GListCtrl, SimpleValidator, \
     MapValidator
 from core.settings import UserSettings
 from core.debug import Debug
-from gui_core.wrap import Button, CheckListBox, EmptyBitmap, HyperlinkCtrl, \
-    Menu, NewId, SpinCtrl, StaticBox, StaticText, TextCtrl
+from core.utils import is_shell_running
+from gui_core.wrap import (
+    Button,
+    CheckListBox,
+    EmptyBitmap,
+    HyperlinkCtrl,
+    Menu,
+    NewId,
+    Slider,
+    SpinCtrl,
+    StaticBox,
+    StaticText,
+    TextCtrl,
+)
 
 
 class SimpleDialog(wx.Dialog):
@@ -1791,8 +1803,10 @@ class SetOpacityDialog(wx.Dialog):
         sizer = wx.BoxSizer(wx.VERTICAL)
 
         box = wx.GridBagSizer(vgap=5, hgap=5)
-        self.value = wx.Slider(
-            panel, id=wx.ID_ANY, value=int(self.opacity * 100),
+        self.value = Slider(
+            panel,
+            id=wx.ID_ANY,
+            value=int(self.opacity * 100),
             style=wx.SL_HORIZONTAL | wx.SL_AUTOTICKS | wx.SL_TOP | wx.SL_LABELS,
             minValue=0, maxValue=100, size=(350, -1))
 

+ 3 - 3
gui/wxpython/gui_core/forms.py

@@ -1344,9 +1344,9 @@ class CmdPanel(wx.Panel):
                         which_sizer.Add(win, proportion=0,
                                         flag=style, border=5)
 
-                elif p.get('type', '') == 'integer':
-                    minValue = -1e9
-                    maxValue = 1e9
+                elif p.get("type", "") == "integer":
+                    minValue = int(-1e9)
+                    maxValue = int(1e9)
                     value = self._getValue(p)
 
                     win = SpinCtrl(

+ 27 - 15
gui/wxpython/gui_core/widgets.py

@@ -89,8 +89,20 @@ from grass.pydispatch.signal import Signal
 from core import globalvar
 from core.gcmd import GMessage, GError
 from core.debug import Debug
-from gui_core.wrap import Button, SearchCtrl, StaticText, StaticBox, \
-    TextCtrl, Menu, Rect, EmptyBitmap, ListCtrl, NewId, CheckListCtrlMixin
+from gui_core.wrap import (
+    Button,
+    SearchCtrl,
+    Slider,
+    StaticText,
+    StaticBox,
+    TextCtrl,
+    Menu,
+    Rect,
+    EmptyBitmap,
+    ListCtrl,
+    NewId,
+    CheckListCtrlMixin,
+)
 
 
 class NotebookController:
@@ -416,13 +428,13 @@ class NumTextCtrl(TextCtrl):
         pass
 
 
-class FloatSlider(wx.Slider):
+class FloatSlider(Slider):
     """Class derived from wx.Slider for floats"""
 
     def __init__(self, **kwargs):
         Debug.msg(1, "FloatSlider.__init__()")
-        wx.Slider.__init__(self, **kwargs)
-        self.coef = 1.
+        Slider.__init__(self, **kwargs)
+        self.coef = 1.0
         # init range
         self.minValueOrig = 0
         self.maxValueOrig = 1
@@ -505,7 +517,7 @@ class SymbolButton(BitmapTextButton):
     def DrawRecord(self, dc, size):
         """Draw record symbol"""
         dc.SetBrush(wx.Brush(wx.Colour(255, 0, 0)))
-        dc.DrawCircle(size[0] / 2, size[1] / 2, size[0] / 2)
+        dc.DrawCircle(size[0] // 2, size[1] // 2, size[0] // 2)
 
     def DrawStop(self, dc, size):
         """Draw stop symbol"""
@@ -515,15 +527,14 @@ class SymbolButton(BitmapTextButton):
     def DrawPlay(self, dc, size):
         """Draw play symbol"""
         dc.SetBrush(wx.Brush(wx.Colour(0, 255, 0)))
-        points = (wx.Point(0, 0), wx.Point(0, size[1]), wx.Point(size[0],
-                                                                 size[1] / 2))
+        points = (wx.Point(0, 0), wx.Point(0, size[1]), wx.Point(size[0], size[1] // 2))
         dc.DrawPolygon(points)
 
     def DrawPause(self, dc, size):
         """Draw pause symbol"""
         dc.SetBrush(wx.Brush(wx.Colour(50, 50, 50)))
-        dc.DrawRectangle(0, 0, 2 * size[0] / 5, size[1])
-        dc.DrawRectangle(3 * size[0] / 5, 0, 2 * size[0] / 5, size[1])
+        dc.DrawRectangle(0, 0, 2 * size[0] // 5, size[1])
+        dc.DrawRectangle(3 * size[0] // 5, 0, 2 * size[0] // 5, size[1])
 
 
 class StaticWrapText(GenStaticText):
@@ -1548,14 +1559,15 @@ class PictureComboBox(OwnerDrawnComboBox):
         # for painting the items in the popup
         bitmap = self.GetPictureBitmap(self.GetString(item))
         if bitmap:
-            dc.DrawBitmap(
-                bitmap, r.x, r.y + (r.height - bitmap.GetHeight()) / 2)
+            dc.DrawBitmap(bitmap, r.x, r.y + (r.height - bitmap.GetHeight()) // 2)
             width = bitmap.GetWidth() + 10
         else:
             width = 0
-        dc.DrawText(self.GetString(item),
-                    r.x + width,
-                    (r.y + 0) + (r.height - dc.GetCharHeight()) / 2)
+        dc.DrawText(
+            self.GetString(item),
+            r.x + width,
+            (r.y + 0) + (r.height - dc.GetCharHeight()) // 2,
+        )
 
     def OnMeasureItem(self, item):
         """Overridden from OwnerDrawnComboBox, should return the height.

+ 67 - 8
gui/wxpython/gui_core/wrap.py

@@ -52,7 +52,28 @@ else:
 if wxPythonPhoenix and CheckWxVersion([4, 0, 3, 0]):
     from wx import NewIdRef as NewId
 else:
-    from wx import NewId
+    from wx import NewId  # noqa: F401
+
+
+def convertToInt(argsOrKwargs, roundVal=False):
+    """Convert args, kwargs float value to int
+
+    :param tuple/list/dict argsOrKwargs: args or kwargs
+    :param bool roundVal: True if you want round float value
+
+    return list or dict
+    """
+    result = {} if isinstance(argsOrKwargs, dict) else []
+    j = None
+    for i in argsOrKwargs:
+        if isinstance(result, dict):
+            i, j = argsOrKwargs[i], i
+        if isinstance(i, float):
+            if roundVal:
+                i = round(i)
+            i = int(i)
+        result.update({j: i}) if j else result.append(i)
+    return result
 
 
 def BitmapFromImage(image, depth=-1):
@@ -122,6 +143,23 @@ class Panel(wx.Panel):
             wx.Panel.SetToolTipString(self, tip)
 
 
+class Slider(wx.Slider):
+    """Wrapper around wx.Slider to have more control
+    over the widget on different platforms/wxpython versions"""
+
+    def __init__(self, *args, **kwargs):
+        args = convertToInt(argsOrKwargs=args)
+        kwargs = convertToInt(argsOrKwargs=kwargs)
+
+        wx.Slider.__init__(self, *args, **kwargs)
+
+    def SetRange(self, minValue, maxValue):
+        wx.Slider.SetRange(self, int(minValue), int(maxValue))
+
+    def SetValue(self, value):
+        wx.Slider.SetValue(self, int(value))
+
+
 class SpinCtrl(wx.SpinCtrl):
     """Wrapper around wx.SpinCtrl to have more control
     over the widget on different platforms"""
@@ -129,6 +167,8 @@ class SpinCtrl(wx.SpinCtrl):
     gtk3MinSize = 130
 
     def __init__(self, *args, **kwargs):
+        args = convertToInt(argsOrKwargs=args)
+        kwargs = convertToInt(argsOrKwargs=kwargs)
         if gtk3:
             if 'size' in kwargs:
                 kwargs['size'] = wx.Size(max(self.gtk3MinSize, kwargs['size'][0]), kwargs['size'][1])
@@ -481,11 +521,13 @@ class PseudoDC(wx.adv.PseudoDC if wxPythonPhoenix else wx.PseudoDC):
     def __init__(self, *args, **kwargs):
         super(PseudoDC, self).__init__(*args, **kwargs)
 
-    def DrawLinePoint(self, pt1, pt2):
+    def DrawLinePoint(self, *args, **kwargs):
+        args = convertToInt(argsOrKwargs=args, roundVal=True)
+        kwargs = convertToInt(argsOrKwargs=kwargs, roundVal=True)
         if wxPythonPhoenix:
-            super(PseudoDC, self).DrawLine(pt1, pt2)
+            super(PseudoDC, self).DrawLine(*args, **kwargs)
         else:
-            super(PseudoDC, self).DrawLinePoint(pt1, pt2)
+            super(PseudoDC, self).DrawLinePoint(*args, **kwargs)
 
     def DrawRectangleRect(self, rect):
         if wxPythonPhoenix:
@@ -501,6 +543,21 @@ class PseudoDC(wx.adv.PseudoDC if wxPythonPhoenix else wx.PseudoDC):
         if not wxPythonPhoenix:
             super(PseudoDC, self).EndDrawing()
 
+    def DrawRectangle(self, *args, **kwargs):
+        args = convertToInt(argsOrKwargs=args, roundVal=True)
+        kwargs = convertToInt(argsOrKwargs=kwargs, roundVal=True)
+        super(PseudoDC, self).DrawRectangle(*args, **kwargs)
+
+    def DrawBitmap(self, *args, **kwargs):
+        args = convertToInt(argsOrKwargs=args, roundVal=True)
+        kwargs = convertToInt(argsOrKwargs=kwargs, roundVal=True)
+        super(PseudoDC, self).DrawBitmap(*args, **kwargs)
+
+    def DrawCircle(self, *args, **kwargs):
+        args = convertToInt(argsOrKwargs=args, roundVal=True)
+        kwargs = convertToInt(argsOrKwargs=kwargs, roundVal=True)
+        super(PseudoDC, self).DrawCircle(*args, **kwargs)
+
 
 class ClientDC(wx.ClientDC):
     """Wrapper around wx.ClientDC to have more control
@@ -519,13 +576,15 @@ class Rect(wx.Rect):
     """Wrapper around wx.Rect to have more control
     over the widget on different platforms/wxpython versions"""
     def __init__(self, *args, **kwargs):
+        args = convertToInt(argsOrKwargs=args)
+        kwargs = convertToInt(argsOrKwargs=kwargs)
         wx.Rect.__init__(self, *args, **kwargs)
 
     def ContainsXY(self, x, y):
         if wxPythonPhoenix:
-            return wx.Rect.Contains(self, x=x, y=y)
+            return wx.Rect.Contains(self, x=int(x), y=int(y))
         else:
-            return wx.Rect.ContainsXY(self, x, y)
+            return wx.Rect.ContainsXY(self, int(x), int(y))
 
     def ContainsRect(self, rect):
         if wxPythonPhoenix:
@@ -535,9 +594,9 @@ class Rect(wx.Rect):
 
     def OffsetXY(self, dx, dy):
         if wxPythonPhoenix:
-            return wx.Rect.Offset(self, dx, dy)
+            return wx.Rect.Offset(self, int(dx), int(dy))
         else:
-            return wx.Rect.OffsetXY(self, dx, dy)
+            return wx.Rect.OffsetXY(self, int(dx), int(dy))
 
 
 class CheckBox(wx.CheckBox):

+ 7 - 6
gui/wxpython/mapswipe/frame.py

@@ -22,6 +22,7 @@ import grass.script as grass
 
 from gui_core.mapdisp import DoubleMapFrame
 from gui_core.dialogs import GetImageHandlers
+from gui_core.wrap import Slider
 from mapwin.base import MapWindowProperties
 from core.render import Map
 from mapdisp import statusbar as sb
@@ -52,8 +53,8 @@ class SwipeMapFrame(DoubleMapFrame):
         #
         self.splitter = MapSplitter(parent=self, id=wx.ID_ANY)
 
-        self.sliderH = wx.Slider(self, id=wx.ID_ANY, style=wx.SL_HORIZONTAL)
-        self.sliderV = wx.Slider(self, id=wx.ID_ANY, style=wx.SL_VERTICAL)
+        self.sliderH = Slider(self, id=wx.ID_ANY, style=wx.SL_HORIZONTAL)
+        self.sliderV = Slider(self, id=wx.ID_ANY, style=wx.SL_VERTICAL)
 
         self.mapWindowProperties = MapWindowProperties()
         self.mapWindowProperties.setValuesFromUserSettings()
@@ -610,11 +611,11 @@ class SwipeMapFrame(DoubleMapFrame):
         self.GetSecondWindow().SetMode(mode)
         # hide/show slider
         if self.splitter.GetSplitMode() == wx.SPLIT_HORIZONTAL:
-            self._mgr.GetPane('sliderV').Show(mode == 'swipe')
-            size = self.splitter.GetSize()[1] / 2
+            self._mgr.GetPane("sliderV").Show(mode == "swipe")
+            size = self.splitter.GetSize()[1] // 2
         else:
-            self._mgr.GetPane('sliderH').Show(mode == 'swipe')
-            size = self.splitter.GetSize()[0] / 2
+            self._mgr.GetPane("sliderH").Show(mode == "swipe")
+            size = self.splitter.GetSize()[0] // 2
         # set sash in the middle
         self.splitter.SetSashPosition(size)
         self.slider.SetValue(size)

+ 39 - 37
gui/wxpython/nviz/tools.py

@@ -52,8 +52,19 @@ from modules.colorrules import ThematicVectorTable
 from core.settings import UserSettings
 from gui_core.widgets import ScrolledPanel, NumTextCtrl, FloatSlider, SymbolButton
 from gui_core.gselect import Select
-from gui_core.wrap import Window, SpinCtrl, PseudoDC, ToggleButton, Button, \
-    TextCtrl, ToggleButton, StaticText, StaticBox, CheckListBox, ColourSelect
+from gui_core.wrap import (
+    Window,
+    SpinCtrl,
+    PseudoDC,
+    ToggleButton,
+    Button,
+    TextCtrl,
+    Slider,
+    StaticText,
+    StaticBox,
+    CheckListBox,
+    ColourSelect,
+)
 from core.debug import Debug
 from nviz.mapwindow import wxUpdateProperties, wxUpdateView,\
     wxUpdateLight, wxUpdateCPlane
@@ -2972,14 +2983,11 @@ class NvizToolWindow(FN.FlatNotebook):
         gridSizer.Add(label, pos=(4, 0),
                       flag=wx.ALIGN_CENTER_VERTICAL)
         # sliders
-        for i, coord in enumerate(('x1', 'x2')):
-            slider = wx.Slider(
-                parent=panel,
-                id=wx.ID_ANY,
-                minValue=0,
-                maxValue=100,
-                value=0)
-            self.win['volume']['slice']['slider_' + coord] = slider.GetId()
+        for i, coord in enumerate(("x1", "x2")):
+            slider = Slider(
+                parent=panel, id=wx.ID_ANY, minValue=0, maxValue=100, value=0
+            )
+            self.win["volume"]["slice"]["slider_" + coord] = slider.GetId()
             slider.Bind(wx.EVT_SPIN, self.OnSlicePositionChange)
             slider.Bind(
                 wx.EVT_SCROLL_THUMBRELEASE,
@@ -2987,14 +2995,11 @@ class NvizToolWindow(FN.FlatNotebook):
             gridSizer.Add(slider, pos=(1, i + 1),
                           flag=wx.ALIGN_CENTER | wx.EXPAND)
 
-        for i, coord in enumerate(('y1', 'y2')):
-            slider = wx.Slider(
-                parent=panel,
-                id=wx.ID_ANY,
-                minValue=0,
-                maxValue=100,
-                value=0)
-            self.win['volume']['slice']['slider_' + coord] = slider.GetId()
+        for i, coord in enumerate(("y1", "y2")):
+            slider = Slider(
+                parent=panel, id=wx.ID_ANY, minValue=0, maxValue=100, value=0
+            )
+            self.win["volume"]["slice"]["slider_" + coord] = slider.GetId()
             slider.Bind(wx.EVT_SPIN, self.OnSlicePositionChange)
             slider.Bind(
                 wx.EVT_SCROLL_THUMBRELEASE,
@@ -3002,14 +3007,11 @@ class NvizToolWindow(FN.FlatNotebook):
             gridSizer.Add(slider, pos=(2, i + 1),
                           flag=wx.ALIGN_CENTER | wx.EXPAND)
 
-        for i, coord in enumerate(('z1', 'z2')):
-            slider = wx.Slider(
-                parent=panel,
-                id=wx.ID_ANY,
-                minValue=0,
-                maxValue=100,
-                value=0)
-            self.win['volume']['slice']['slider_' + coord] = slider.GetId()
+        for i, coord in enumerate(("z1", "z2")):
+            slider = Slider(
+                parent=panel, id=wx.ID_ANY, minValue=0, maxValue=100, value=0
+            )
+            self.win["volume"]["slice"]["slider_" + coord] = slider.GetId()
             slider.Bind(wx.EVT_SPIN, self.OnSlicePositionChange)
             slider.Bind(
                 wx.EVT_SCROLL_THUMBRELEASE,
@@ -3070,7 +3072,7 @@ class NvizToolWindow(FN.FlatNotebook):
         if floatSlider:
             slider = FloatSlider(**kwargs)
         else:
-            slider = wx.Slider(**kwargs)
+            slider = Slider(**kwargs)
 
         slider.SetName('slider')
         if bind[0]:
@@ -5080,14 +5082,14 @@ class NvizToolWindow(FN.FlatNotebook):
         self.pageChanging = True
         Debug.msg(1, "NvizToolWindow.UpdatePage(): %s", pageId)
 
-        if pageId == 'view':
-            self.SetPage('view')
-            hmin = self.mapWindow.iview['height']['min']
-            hmax = self.mapWindow.iview['height']['max']
-            hval = self.mapWindow.iview['height']['value']
-            zmin = self.mapWindow.view['z-exag']['min']
-            zmax = self.mapWindow.view['z-exag']['max']
-            zval = self.mapWindow.view['z-exag']['value']
+        if pageId == "view":
+            self.SetPage("view")
+            hmin = int(self.mapWindow.iview["height"]["min"])
+            hmax = int(self.mapWindow.iview["height"]["max"])
+            hval = int(self.mapWindow.iview["height"]["value"])
+            zmin = int(self.mapWindow.view["z-exag"]["min"])
+            zmax = self.mapWindow.view["z-exag"]["max"]
+            zval = self.mapWindow.view["z-exag"]["value"]
 
             for control in ('slider', 'text'):
                 try:
@@ -5748,8 +5750,8 @@ class PositionWindow(Window):
             y = y * h
         self.pdc.Clear()
         self.pdc.BeginDrawing()
-        self.pdc.DrawLine(w / 2, h / 2, x, y)
-        self.pdc.DrawCircle(x, y, 5)
+        self.pdc.DrawLine(w // 2, h // 2, int(x), int(y))
+        self.pdc.DrawCircle(int(x), int(y), 5)
         self.pdc.EndDrawing()
 
     def OnPaint(self, event):

+ 4 - 4
gui/wxpython/psmap/dialogs.py

@@ -5315,7 +5315,7 @@ class TextDialog(PsmapDialog):
             self.effect['highlightCtrl'].SetValue(False)
             self.effect['highlightColor'].SetColour(convertRGB('grey'))
 
-        self.effect['highlightWidth'].SetValue(float(self.textDict['hwidth']))
+        self.effect["highlightWidth"].SetValue(int(float(self.textDict["hwidth"])))
 
         if self.textDict['border'] is None:
             self.textDict['border'] = 'none'
@@ -5327,7 +5327,7 @@ class TextDialog(PsmapDialog):
             self.effect['borderCtrl'].SetValue(False)
             self.effect['borderColor'].SetColour(convertRGB('black'))
 
-        self.effect['borderWidth'].SetValue(float(self.textDict['width']))
+        self.effect['borderWidth'].SetValue(int(float(self.textDict['width'])))
 
         gridBagSizer.Add(self.effect['backgroundCtrl'], pos=(
             0, 0), flag=wx.ALIGN_CENTER_VERTICAL, border=0)
@@ -6090,8 +6090,8 @@ class ImageDialog(PsmapDialog):
             dc.SelectObject(buffer)
             dc.SetBrush(dc.GetBrush())
             dc.Clear()
-            posX = self.previewSize[0] / 2 - bitmap.GetWidth() / 2
-            posY = self.previewSize[1] / 2 - bitmap.GetHeight() / 2
+            posX = self.previewSize[0] // 2 - bitmap.GetWidth() // 2
+            posY = self.previewSize[1] // 2 - bitmap.GetHeight() // 2
             dc.DrawBitmap(bitmap, posX, posY)
             self.imagePanel.image['preview'].SetBitmap(buffer)
             dc.SelectObject(wx.NullBitmap)

+ 40 - 43
gui/wxpython/psmap/frame.py

@@ -921,8 +921,8 @@ class PsMapFrame(wx.Frame):
         """creates a wx.Font object from selected postscript font. To be
         used for estimating bounding rectangle of text"""
 
-        fontsize = textDict['fontsize'] * self.canvas.currScale
-        fontface = textDict['font'].split('-')[0]
+        fontsize = round(textDict["fontsize"] * self.canvas.currScale)
+        fontface = textDict["font"].split("-")[0]
         try:
             fontstyle = textDict['font'].split('-')[1]
         except IndexError:
@@ -1375,34 +1375,27 @@ class PsMapBufferedWindow(wx.Window):
             fromU = 'inch'
             toU = 'pixel'
             scale = self.currScale
-            pRectx = units.convert(
-                value=- pRect.x,
-                fromUnit='pixel',
-                toUnit='inch') / scale  # inch, real, negative
-            pRecty = units.convert(
-                value=- pRect.y,
-                fromUnit='pixel',
-                toUnit='inch') / scale
-        Width = units.convert(
-            value=rect.GetWidth(),
-            fromUnit=fromU,
-            toUnit=toU) * scale
-        Height = units.convert(
-            value=rect.GetHeight(),
-            fromUnit=fromU,
-            toUnit=toU) * scale
-        X = units.convert(
-            value=(
-                rect.GetX() - pRectx),
-            fromUnit=fromU,
-            toUnit=toU) * scale
-        Y = units.convert(
-            value=(
-                rect.GetY() - pRecty),
-            fromUnit=fromU,
-            toUnit=toU) * scale
-
-        return Rect2D(X, Y, Width, Height)
+            pRectx = (
+                units.convert(value=-pRect.x, fromUnit="pixel", toUnit="inch") / scale
+            )  # inch, real, negative
+            pRecty = (
+                units.convert(value=-pRect.y, fromUnit="pixel", toUnit="inch") / scale
+            )
+        Width = units.convert(value=rect.GetWidth(), fromUnit=fromU, toUnit=toU) * scale
+        Height = (
+            units.convert(value=rect.GetHeight(), fromUnit=fromU, toUnit=toU) * scale
+        )
+        X = (
+            units.convert(value=(rect.GetX() - pRectx), fromUnit=fromU, toUnit=toU)
+            * scale
+        )
+        Y = (
+            units.convert(value=(rect.GetY() - pRecty), fromUnit=fromU, toUnit=toU)
+            * scale
+        )
+        if canvasToPaper:
+            return Rect2D(X, Y, Width, Height)
+        return Rect2D(int(X), int(Y), int(Width), int(Height))
 
     def SetPage(self):
         """Sets and changes page, redraws paper"""
@@ -1423,7 +1416,7 @@ class PsMapBufferedWindow(wx.Window):
 
         x = cW / 2 - pW / 2
         y = cH / 2 - pH / 2
-        self.DrawPaper(Rect(x, y, pW, pH))
+        self.DrawPaper(Rect(int(x), int(y), int(pW), int(pH)))
 
     def modifyRectangle(self, r):
         """Recalculates rectangle not to have negative size"""
@@ -2220,7 +2213,7 @@ class PsMapBufferedWindow(wx.Window):
             bounds = self.pdcPaper.GetIdBounds(self.pageId)
         else:
             bounds = self.pdcImage.GetIdBounds(self.imageId)
-        zoomP = bounds.Inflate(bounds.width / 20, bounds.height / 20)
+        zoomP = bounds.Inflate(round(bounds.width / 20), round(bounds.height / 20))
         zoomFactor, view = self.ComputeZoom(zoomP)
         self.Zoom(zoomFactor, view)
 
@@ -2269,7 +2262,7 @@ class PsMapBufferedWindow(wx.Window):
             text = '\n'.join(self.itemLabels[drawid])
             w, h, lh = dc.GetFullMultiLineTextExtent(text)
             textExtent = (w, h)
-            textRect = Rect(0, 0, *textExtent).CenterIn(bb)
+            textRect = Rect(0, 0, *textExtent).CenterIn(Rect(*bb))
             r = map(int, bb)
             while not Rect(*r).ContainsRect(textRect) and size >= 8:
                 size -= 2
@@ -2277,7 +2270,7 @@ class PsMapBufferedWindow(wx.Window):
                 dc.SetFont(font)
                 pdc.SetFont(font)
                 textExtent = dc.GetTextExtent(text)
-                textRect = Rect(0, 0, *textExtent).CenterIn(bb)
+                textRect = Rect(0, 0, *textExtent).CenterIn(Rect(*bb))
             pdc.SetTextForeground(wx.Colour(100, 100, 100, 200))
             pdc.SetBackgroundMode(wx.TRANSPARENT)
             pdc.DrawLabel(text=text, rect=textRect)
@@ -2287,10 +2280,10 @@ class PsMapBufferedWindow(wx.Window):
                            y=bb[1] + bb[3] / 2,
                            radius=bb[2] / 2)
 
-        elif pdctype == 'line':
-            pdc.DrawLinePoint(lineCoords[0], lineCoords[1])
+        elif pdctype == "line":
+            pdc.DrawLinePoint(*lineCoords[0], *lineCoords[1])
 
-        pdc.SetIdBounds(drawid, bb)
+        pdc.SetIdBounds(drawid, Rect(*bb))
         pdc.EndDrawing()
         self.Refresh()
 
@@ -2439,9 +2432,9 @@ class PsMapBufferedWindow(wx.Window):
         self.pdcPaper.SetBrush(self.brush['paper'])
         self.pdcPaper.DrawRectangleRect(rect)
 
-        self.pdcPaper.SetPen(self.pen['margins'])
-        self.pdcPaper.SetBrush(self.brush['margins'])
-        self.pdcPaper.DrawRectangle(x, y, w, h)
+        self.pdcPaper.SetPen(self.pen["margins"])
+        self.pdcPaper.SetBrush(self.brush["margins"])
+        self.pdcPaper.DrawRectangle(int(x), int(y), int(w), int(h))
 
         self.pdcPaper.SetIdBounds(self.pageId, rect)
         self.pdcPaper.EndDrawing()
@@ -2458,7 +2451,7 @@ class PsMapBufferedWindow(wx.Window):
         iH = iH * self.currScale
         x = cW / 2 - iW / 2
         y = cH / 2 - iH / 2
-        imageRect = Rect(x, y, iW, iH)
+        imageRect = Rect(int(x), int(y), int(iW), int(iH))
 
         return imageRect
 
@@ -2579,5 +2572,9 @@ class PsMapBufferedWindow(wx.Window):
 
     def ScaleRect(self, rect, scale):
         """Scale rectangle"""
-        return Rect(rect.GetLeft() * scale, rect.GetTop() * scale,
-                       rect.GetSize()[0] * scale, rect.GetSize()[1] * scale)
+        return Rect(
+            int(rect.GetLeft() * scale),
+            int(rect.GetTop() * scale),
+            int(rect.GetSize()[0] * scale),
+            int(rect.GetSize()[1] * scale),
+        )