code: def boundedMoveShape(self, shapes, pos):
      if type(shapes).__name__ != "list":
          shapes = [shapes]
      if self.outOfPixmap(pos):
          return False  # No need to move
      o1 = pos + self.offsets[0]
      if self.outOfPixmap(o1):
          pos -= QPointF(min(0, o1.x()), min(0, o1.y()))
      o2 = pos + self.offsets[1]
      if self.outOfPixmap(o2):
          pos += QPointF(
              min(0, self.pixmap.width() - o2.x()),
              min(0, self.pixmap.height() - o2.y()),
          )
      # The next line tracks the new position of the cursor
      # relative to the shape, but also results in making it
      # a bit "shaky" when nearing the border and allows it to
      # go outside of the shape's area for some reason. XXX
      # self.calculateOffsets(self.selectedShape, pos)
      dp = pos - self.prevPoint
      if dp:
          for shape in shapes:
              shape.moveBy(dp)
              shape.close()
          self.prevPoint = pos
          return True
      return False
  
imports: import copy
  from PyQt5.QtCore import Qt, pyqtSignal, QPointF, QPoint
  from PyQt5.QtGui import QPainter, QBrush, QColor, QPixmap
  from PyQt5.QtWidgets import QWidget, QMenu, QApplication
  from libs.shape import Shape
  from libs.utils import distance
label_desc: Use image node_id 26 for calling the Canvas obj's underlying member method code with example usage: obj.boundedMoveShape(shapes, pos) and returns: False, False, True