コード例 #1
0
    def __init__(self, da):
        self.display_file = DisplayFile()
        self.draw_counter = 0
        self.da = da

        da_width = da.get_allocation().width
        da_height = da.get_allocation().height

        # Window and viewport start with the same size as the drawing area,
        # but compensating for the clipping border size (otherwise you
        # wouldn't see by default a point drawn at 0,0).
        self.window = Window(-cbz, -cbz, da_width - cbz, da_height - cbz)
        self.viewport = Viewport(-cbz, -cbz, da_width - cbz, da_height - cbz)

        self.transform = Transform()

        # Pass reference to window for Transform and Viewport
        self.transform.setWindow(self.window)
        self.viewport.setWindow(self.window)

        # To verify that both normalize() and denormalize() work
        # print(self.transform.normalize(0,0))
        # print(self.transform.normalize(self.window.getWidth(),self.window.getHeight()))
        # print(self.transform.denormalize(-1,-1))
        # print(self.transform.denormalize(1,1))

        self.projection = 'parallel'
コード例 #2
0
ファイル: window.py プロジェクト: telmotrooper/ine5420_pygtk
  def __init__(self, x_min, y_min, x_max, y_max):
    #print("({},{}) ({},{})".format(x_min, y_min, x_max, y_max))

    Window.x_min = x_min
    Window.y_min = y_min
    Window.x_max = x_max
    Window.y_max = y_max
    Window.transform = Transform()
    Window.display_file = DisplayFile()
コード例 #3
0
ファイル: handler.py プロジェクト: telmotrooper/ine5420_pygtk
    def __init__(self, builder, drawing_manager):
        self.builder = builder
        self.dm = drawing_manager
        self.transform = Transform()
        self.obj_handler = ObjHandler()
        self.clipping = Clipping()

        # References to GTK objects
        self.add_object_window = self.builder.get_object("AddObjectWindow")
        self.text_view = self.builder.get_object("Log")
        self.tree_view = self.builder.get_object("TreeView")

        self.obj_file_chooser = self.builder.get_object("ObjFileChooser")
        self.object_radio_button = self.builder.get_object("ObjectRadioButton")
        self.world_radio_button = self.builder.get_object("WorldRadioButton")
        self.point_radio_button = self.builder.get_object("PointRadioButton")
        self.rotate_x = self.builder.get_object("RotateX")
        self.rotate_y = self.builder.get_object("RotateY")
        self.object_rotation_angle = self.builder.get_object(
            "objectRotationAngle")
        self.object_units_for_moving = self.builder.get_object(
            "objectUnitsForMoving")
        self.line_clipping_cs = self.builder.get_object("LineClippingCS")
        self.line_clipping_lb = self.builder.get_object("LineClippingLB")
        self.window_selected = self.builder.get_object("WindowSelected")
        self.object_selected = self.builder.get_object("ObjectSelected")

        self.parallel_projection = self.builder.get_object(
            "ParallelProjectionRadioButton")
        self.perspective_projection = self.builder.get_object(
            "PerspectiveProjectionRadioButton")

        self.text_buffer = self.text_view.get_buffer()
        self.display_file = DisplayFile()
        self.display_file.setBuilder(builder)

        # Used to keep state of polygons and curves when points are added
        self.temp_polygon = []
        self.temp_curve = []
コード例 #4
0
class ObjHandler:
    def __init__(self):
        self.display_file = DisplayFile()

    def importFile(self, path):
        self.display_file.wipeOut()
        #print("{}".format(path))
        vertices = dict()
        vertice_counter = 0
        name = ""

        self.file = open(path, "r+")  # read and write

        for line in self.file:
            if (line[0] == "v"):  # store vertices in a dictionary
                vertice_counter += 1
                vertices[vertice_counter] = line

            elif (line[0] == "o"
                  ):  # store temporarily the name of the object to come
                match = re.findall(r"\S+", line)
                name = match[1]

            elif (line[0] == "p"):  # TODO: FINISH THIS
                match = re.findall(r"\S+", line)
                vertice_for_point = vertices[float(match[1])]
                match = re.findall(r"\S+", vertice_for_point)
                coord = {"x": float(match[1]), "y": float(match[2])}

                p1 = Point(name)
                p1.addCoords(coord["x"], coord["y"])
                self.display_file.addObject(p1)

            elif (line[0] == "l"):
                match = re.findall(r"\S+", line)

                if (len(match) == 3):  # line
                    l = Line(name)
                else:  # polygon
                    l = None

                    if (match[1] == match[-1]):
                        l = Polygon(name)
                    else:
                        l = Curve(name)

                for item in match:
                    if (
                            item != "l"
                    ):  # ignore the first character, only compute coordinates
                        vertice_for_point = vertices[float(item)]
                        match_vertice = re.findall(r"\S+", vertice_for_point)
                        coord = {
                            "x": float(match_vertice[1]),
                            "y": float(match_vertice[2])
                        }
                        l.addCoords(coord["x"], coord["y"])

                if (match[1] == match[-1]
                    ):  # if polygon (last coords == first coords)
                    l.popCoords()  # remove repeated coords

                self.display_file.addObject(l)

    def exportFile(self, path):
        output_file = open(path, "w+")  # write, overwrite and create if needed
        temp = ""  # this variable holds the objects related to the vertices
        vertice_counter = 0

        # Valid objects are:
        # - vertice (v) (these are always in the beginning of the file)
        # - point (p)
        # - line (l)
        # - object name (o)

        for obj in DisplayFile.objects:
            obj_type = obj.__class__.__name__
            w_coords = obj.getWorldCoords()

            if (obj_type == "Point"):
                vertice_counter += 1
                output_file.write("v {} {} 0\n".format(w_coords[0]["x"],
                                                       w_coords[0]["y"]))

                temp += "o {}\n".format(obj.getName())
                temp += "p {}\n".format(vertice_counter)

            elif (obj_type == "Line"):
                vertice_counter += 1
                output_file.write("v {} {} 0\n".format(w_coords[0]["x"],
                                                       w_coords[0]["y"]))
                vertice_counter += 1
                output_file.write("v {} {} 0\n".format(w_coords[1]["x"],
                                                       w_coords[1]["y"]))
                temp += "o {}\n".format(obj.getName())

                temp += "l {} {}\n".format(vertice_counter - 1,
                                           vertice_counter)

            elif (obj_type == "Polygon"):
                temp += "o {}\n".format(obj.getName())
                temp += "l"
                initial = vertice_counter + 1
                for coord in w_coords:
                    vertice_counter += 1
                    output_file.write("v {} {} 0\n".format(
                        coord["x"], coord["y"]))
                    temp += " {}".format(vertice_counter)
                temp += " {}\n".format(initial)

            elif (obj_type == "Curve"):
                temp += "o {}\n".format(obj.getName())
                temp += "l"
                for coord in w_coords:
                    vertice_counter += 1
                    output_file.write("v {} {} 0\n".format(
                        coord["x"], coord["y"]))
                    temp += " {}".format(vertice_counter)
                temp += "\n"

        output_file.write("{}\n".format(temp))
        output_file.close()
コード例 #5
0
 def __init__(self):
     self.display_file = DisplayFile()
コード例 #6
0
import numpy as np
from display_file import DisplayFile
from matrices import Matrices
from variables import clipping_border_size as cbz
from numpy.matlib import identity
from math import sin, cos, pi

display_file = DisplayFile()


class Transform:
    a, b = -1, 1

    def __init__(self):
        self.m = Matrices()

    def setWindow(self, window):
        Transform.window = window

    def normalize(self, x, y):
        # x' = (b-a) * ((x - min) / (max - min)) + a
        window = Transform.window
        a, b = self.a, self.b
        wmin_x, wmax_x = window.getMin()["x"] + cbz, window.getMax()["x"] - cbz
        wmin_y, wmax_y = window.getMin()["y"] + cbz, window.getMax()["y"] - cbz

        # print("(Transform) Window at ({},{}) ({},{})".format(wmin_x, wmin_y, wmax_x, wmax_y))

        new_x = (b - a) * ((x - wmin_x) / (wmax_x - wmin_x)) + a
        new_y = (b - a) * ((y - wmin_y) / (wmax_y - wmin_y)) + a
コード例 #7
0
class DrawingManager:
    def __init__(self, da):
        self.display_file = DisplayFile()
        self.draw_counter = 0
        self.da = da

        da_width = da.get_allocation().width
        da_height = da.get_allocation().height

        # Window and viewport start with the same size as the drawing area,
        # but compensating for the clipping border size (otherwise you
        # wouldn't see by default a point drawn at 0,0).
        self.window = Window(-cbz, -cbz, da_width - cbz, da_height - cbz)
        self.viewport = Viewport(-cbz, -cbz, da_width - cbz, da_height - cbz)

        self.transform = Transform()

        # Pass reference to window for Transform and Viewport
        self.transform.setWindow(self.window)
        self.viewport.setWindow(self.window)

        # To verify that both normalize() and denormalize() work
        # print(self.transform.normalize(0,0))
        # print(self.transform.normalize(self.window.getWidth(),self.window.getHeight()))
        # print(self.transform.denormalize(-1,-1))
        # print(self.transform.denormalize(1,1))

        self.projection = 'parallel'

    def setProjection(self, name):
        self.projection = name

    def getWindow(self):
        return self.window

    def redraw(self):
        self.da.queue_draw()

    def drawBackground(self, da, ctx):
        ctx.set_source_rgb(255, 255, 255)  # color white
        ctx.paint()

    def drawClippingBorder(self, da, ctx):
        ctx.set_line_width(1)
        ctx.set_source_rgb(255, 0, 0)  # color red

        ctx.move_to(cbz, cbz)
        ctx.line_to(self.window.getWidth() - cbz, cbz)
        ctx.line_to(self.window.getWidth() - cbz,
                    self.window.getHeight() - cbz)
        ctx.line_to(cbz, self.window.getHeight() - cbz)

        ctx.close_path()
        ctx.stroke()

    def draw(self, da, ctx):
        self.drawBackground(da, ctx)

        ctx.set_line_width(2)
        ctx.set_source_rgb(0, 0, 0)  # color black

        for i in self.display_file.getObjects():
            # print('Drawing object "{}"'.format(i.getName()))
            i.drawToViewport(ctx, self.viewport)

            self.draw_counter += 1
            # print("draw() #{0}".format(self.draw_counter))

        if (self.projection == 'perspective'):
            for i in self.display_file.getObjects3d():
                obj_perspectiva = copy.deepcopy(i)
                lista_pontos_3d = []
                for segmento in obj_perspectiva.segments:
                    lista_pontos_3d.append(segmento[0])
                    lista_pontos_3d.append(segmento[1])

                self.transform.perspectiva(lista_pontos_3d, 100)

                for s in obj_perspectiva.segments:
                    #print(s[0].x, s[0].y)
                    #print(s[1].x, s[1].y)

                    coords0 = self.viewport.transformadaViewPortCoordenada(
                        s[0].x, s[0].y)
                    coords1 = self.viewport.transformadaViewPortCoordenada(
                        s[1].x, s[1].y)
                    ctx.move_to(coords0['x'], coords0['y'])
                    ctx.line_to(coords1['x'], coords1['y'])

        else:
            for i in self.display_file.getObjects3d():
                for s in i.segments:
                    reta = [{
                        "x": s[0].x,
                        "y": s[0].y
                    }, {
                        "x": s[1].x,
                        "y": s[1].y
                    }]
                    clipping = Clipping()
                    coords = clipping.cohenSutherland(reta, self.window)
                    if (coords):
                        coords0 = self.viewport.transformadaViewPortCoordenada(
                            coords[0]['x'], coords[0]['y'])
                        coords1 = self.viewport.transformadaViewPortCoordenada(
                            coords[1]['x'], coords[1]['y'])
                        ctx.move_to(coords0['x'], coords0['y'])
                        ctx.line_to(coords1['x'], coords1['y'])

        ctx.stroke()

        self.drawClippingBorder(da, ctx)
コード例 #8
0
ファイル: handler.py プロジェクト: telmotrooper/ine5420_pygtk
class Handler:
    def __init__(self, builder, drawing_manager):
        self.builder = builder
        self.dm = drawing_manager
        self.transform = Transform()
        self.obj_handler = ObjHandler()
        self.clipping = Clipping()

        # References to GTK objects
        self.add_object_window = self.builder.get_object("AddObjectWindow")
        self.text_view = self.builder.get_object("Log")
        self.tree_view = self.builder.get_object("TreeView")

        self.obj_file_chooser = self.builder.get_object("ObjFileChooser")
        self.object_radio_button = self.builder.get_object("ObjectRadioButton")
        self.world_radio_button = self.builder.get_object("WorldRadioButton")
        self.point_radio_button = self.builder.get_object("PointRadioButton")
        self.rotate_x = self.builder.get_object("RotateX")
        self.rotate_y = self.builder.get_object("RotateY")
        self.object_rotation_angle = self.builder.get_object(
            "objectRotationAngle")
        self.object_units_for_moving = self.builder.get_object(
            "objectUnitsForMoving")
        self.line_clipping_cs = self.builder.get_object("LineClippingCS")
        self.line_clipping_lb = self.builder.get_object("LineClippingLB")
        self.window_selected = self.builder.get_object("WindowSelected")
        self.object_selected = self.builder.get_object("ObjectSelected")

        self.parallel_projection = self.builder.get_object(
            "ParallelProjectionRadioButton")
        self.perspective_projection = self.builder.get_object(
            "PerspectiveProjectionRadioButton")

        self.text_buffer = self.text_view.get_buffer()
        self.display_file = DisplayFile()
        self.display_file.setBuilder(builder)

        # Used to keep state of polygons and curves when points are added
        self.temp_polygon = []
        self.temp_curve = []

    def onDestroy(self, *args):
        Gtk.main_quit()

    def onImportObj(self, button):
        self.printToLog("onImportObj")
        self.obj_file_chooser.show_all()

    def onCancelFileImport(self, button):
        self.printToLog("onCancelFileImport")
        self.obj_file_chooser.hide()

    def onFileClicked(self, button):
        file_path = self.obj_file_chooser.get_filename()
        self.printToLog("onFileClicked ({})".format(file_path))
        self.obj_handler.importFile(file_path)
        self.obj_file_chooser.hide()

    def onExportObj(self, button):
        self.printToLog("onExportObj")
        self.obj_handler.exportFile("./file.obj")

    def onRotateWindowLeft(self, button):
        self.printToLog("onRotateWindowLeft")
        angle = int(self.object_rotation_angle.get_text())
        self.dm.getWindow().rotate(angle)
        self.dm.redraw()

    def onRotateWindowRight(self, button):
        self.printToLog("onRotateWindowRight")
        angle = float(self.object_rotation_angle.get_text())
        self.dm.getWindow().rotate(-angle)
        self.dm.redraw()

    def onAddObjectClicked(self, button):
        self.printToLog("onAddObjectClicked")
        add_object_window = self.builder.get_object("AddObjectWindow")
        add_object_window.show_all()

    def onAddCurvePoint(self, button):
        x_entry = self.builder.get_object("EntryXCurve").get_text()
        y_entry = self.builder.get_object("EntryYCurve").get_text()
        self.temp_curve.append({"x": x_entry, "y": y_entry})
        self.printToLog("onAddCurvePoint ({},{})".format(x_entry, y_entry))

    def onAddPolygonPoint(self, button):
        x_entry = self.builder.get_object("EntryXPolygon").get_text()
        y_entry = self.builder.get_object("EntryYPolygon").get_text()
        self.temp_polygon.append({"x": x_entry, "y": y_entry})
        self.printToLog("onAddPolygonPoint ({},{})".format(x_entry, y_entry))

    def onRemoveCurvePoint(self, button):
        if (len(self.temp_curve) > 0):
            self.temp_curve.pop()
        else:
            self.printToLog("No point to remove")

        self.printToLog("onRemoveCurvePoint")

    def onRemovePolygonPoint(self, button):
        if (len(self.temp_polygon) > 0):
            self.temp_polygon.pop()
        else:
            self.printToLog("No point to remove")

        self.printToLog("onRemovePolygonPoint")

    def onAddCurve(self, button):
        self.printToLog("onAddCurve")

        name = self.builder.get_object("CurveName").get_text()
        curve = Curve(name)

        for point in self.temp_curve:
            curve.addCoords(float(point["x"]), float(point["y"]))

        self.display_file.addObject(curve)
        self.temp_curve = []
        self.add_object_window.hide()

    def onAddPolygon(self, button):
        self.printToLog("onAddPolygon")

        name = self.builder.get_object("PolygonName").get_text()
        polygon = Polygon(name)

        for point in self.temp_polygon:
            polygon.addCoords(float(point["x"]), float(point["y"]))

        self.display_file.addObject(polygon)
        self.temp_polygon = []
        self.add_object_window.hide()

    def onAddCube(self, button):
        name = self.builder.get_object("3DName").get_text()

        segments = [[Point3D(50, 50, 0),
                     Point3D(50, 100, 0)],
                    [Point3D(50, 100, 0),
                     Point3D(150, 100, 0)],
                    [Point3D(150, 100, 0),
                     Point3D(150, 50, 0)],
                    [Point3D(150, 50, 0),
                     Point3D(50, 50, 0)],
                    [Point3D(50, 50, 50),
                     Point3D(50, 100, 50)],
                    [Point3D(50, 100, 50),
                     Point3D(150, 100, 50)],
                    [Point3D(150, 100, 50),
                     Point3D(150, 50, 50)],
                    [Point3D(150, 50, 50),
                     Point3D(50, 50, 50)],
                    [Point3D(50, 50, 0),
                     Point3D(50, 50, 50)],
                    [Point3D(50, 100, 0),
                     Point3D(50, 100, 50)],
                    [Point3D(150, 100, 0),
                     Point3D(150, 100, 50)],
                    [Point3D(150, 50, 0),
                     Point3D(150, 50, 50)]]

        obj3d = Object3D(segments, name)
        self.display_file.addObject3d(obj3d)
        self.add_object_window.hide()

    def onAddPoint(self, button):
        self.printToLog("onAddPoint")
        name_entry = self.builder.get_object("PointNameEntry")
        x_entry = self.builder.get_object("PointXEntry")
        y_entry = self.builder.get_object("PointYEntry")
        p1 = Point(name_entry.get_text())

        p1.addCoords(float(x_entry.get_text()), float(y_entry.get_text()))
        self.display_file.addObject(p1)
        self.add_object_window.hide()

    def onAddLine(self, button):
        self.printToLog("onAddLine")
        name_entry = self.builder.get_object("EntryNameNewLine")
        x1_entry = self.builder.get_object("EntryX1Line")
        y1_entry = self.builder.get_object("EntryY1Line")
        x2_entry = self.builder.get_object("EntryX2Line")
        y2_entry = self.builder.get_object("EntryY2Line")

        l1 = Line(name_entry.get_text())
        l1.addCoords(float(x1_entry.get_text()), float(y1_entry.get_text()))
        l1.addCoords(float(x2_entry.get_text()), float(y2_entry.get_text()))

        self.display_file.addObject(l1)
        self.add_object_window.hide()

    def onRemoveObjectClicked(self, button):
        self.printToLog("onRemoveObjectClicked")
        obj_list, index = self.tree_view.get_selection().get_selected()
        if index != None:
            self.display_file.removeObject(obj_list[index][2])
            obj_list.remove(index)
            self.dm.redraw()
        else:
            self.printToLog("No object selected")

    def onZoomOut(self, button):
        self.printToLog("onZoomOut")
        self.dm.getWindow().zoom(0.9)
        self.dm.redraw()

    def onZoomIn(self, button):
        self.printToLog("onZoomIn")
        self.dm.getWindow().zoom(1.1)
        self.dm.redraw()

    def onMoveObjectUp(self, button):
        if self.window_selected.get_active():
            return self.onMoveWindowUp(button)

        units = float(self.object_units_for_moving.get_text())
        self.printToLog("onMoveObjectUp")
        self.transform.move(self.tree_view, 0, units)

        self.dm.redraw()

    def onMoveObjectDown(self, button):
        if self.window_selected.get_active():
            return self.onMoveWindowDown(button)

        units = float(self.object_units_for_moving.get_text())
        self.printToLog("onMoveObjectDown")
        self.transform.move(self.tree_view, 0, -units)
        self.dm.redraw()

    def onMoveObjectLeft(self, button):
        if self.window_selected.get_active():
            return self.onMoveWindowLeft(button)

        units = float(self.object_units_for_moving.get_text())
        self.printToLog("onMoveObjectLeft")
        self.transform.move(self.tree_view, -units, 0)
        self.dm.redraw()

    def onMoveObjectRight(self, button):
        if self.window_selected.get_active():
            return self.onMoveWindowRight(button)

        units = float(self.object_units_for_moving.get_text())
        self.printToLog("onMoveObjectRight")
        self.transform.move(self.tree_view, units, 0)
        self.dm.redraw()

    def onLineClippingChanged(self, button):
        if self.line_clipping_cs.get_active():
            self.printToLog("Line clipping algorithm set to Cohen-Sutherland.")
            self.clipping.setlineClippingAlgorithm("cs")
        elif self.line_clipping_lb.get_active():
            self.printToLog("Line clipping algorithm set to Liang-Barsky.")
            self.clipping.setlineClippingAlgorithm("lb")

    def onProjectionChanged(self, button):
        if self.parallel_projection.get_active():
            self.printToLog("Parallel.")
            self.dm.setProjection('parallel')
        elif self.perspective_projection.get_active():
            self.printToLog("Perspective.")
            self.dm.setProjection('perspective')

    def onRotateObjectLeft(self, button):
        if self.window_selected.get_active():
            return self.onRotateWindowLeft(button)

        self.printToLog("onRotateObjectLeft")
        angle = int(self.object_rotation_angle.get_text())

        if self.object_radio_button.get_active():
            self.transform.rotate(self.tree_view, -angle, 'center', 0, 0)
        elif self.world_radio_button.get_active():
            self.transform.rotate(self.tree_view, -angle, 'world', 0, 0)
        elif self.point_radio_button.get_active():
            x = float(self.rotate_x.get_text())
            y = float(self.rotate_y.get_text())
            self.transform.rotate(self.tree_view, -angle, 'point', x, y)
        self.dm.redraw()

    def onRotateObjectRight(self, button):
        if self.window_selected.get_active():
            return self.onRotateWindowRight(button)

        self.printToLog("onRotateObjectRight")
        angle = int(self.object_rotation_angle.get_text())

        if self.object_radio_button.get_active():
            self.transform.rotate(self.tree_view, angle, 'center', 0, 0)
        elif self.world_radio_button.get_active():
            self.transform.rotate(self.tree_view, angle, 'world', 0, 0)
        elif self.point_radio_button.get_active():
            x = float(self.rotate_x.get_text())
            y = float(self.rotate_y.get_text())
            self.transform.rotate(self.tree_view, angle, 'point', x, y)

        self.dm.redraw()

    def OnRotateObjectUp(self, button):
        self.printToLog("OnRotateObjectUp")

        angle = int(self.object_rotation_angle.get_text())

        if self.object_radio_button.get_active():
            self.transform.rotate3d(self.tree_view, angle, 'center', 0, 0)
        elif self.world_radio_button.get_active():
            self.transform.rotate3d(self.tree_view, angle, 'world', 0, 0)
        elif self.point_radio_button.get_active():
            x = float(self.rotate_x.get_text())
            y = float(self.rotate_y.get_text())
            self.transform.rotate3d(self.tree_view, angle, 'point', x, y)

        self.dm.redraw()

    def OnRotateObjectDown(self, button):
        self.printToLog("OnRotateObjectDown")

        angle = int(self.object_rotation_angle.get_text())

        if self.object_radio_button.get_active():
            self.transform.rotate3d(self.tree_view, -angle, 'center', 0, 0)
        elif self.world_radio_button.get_active():
            self.transform.rotate3d(self.tree_view, -angle, 'world', 0, 0)
        elif self.point_radio_button.get_active():
            x = float(self.rotate_x.get_text())
            y = float(self.rotate_y.get_text())
            self.transform.rotate3d(self.tree_view, -angle, 'point', x, y)

        self.dm.redraw()

    def onScaleObjectUp(self, button):
        if self.window_selected.get_active():
            return self.onZoomIn(button)

        self.printToLog("onScaleObjectUp")

        self.transform.zoom(self.tree_view, 2, 2)
        self.dm.redraw()

    def onScaleObjectDown(self, button):
        if self.window_selected.get_active():
            return self.onZoomOut(button)

        self.printToLog("onScaleObjectDown")
        self.transform.zoom(self.tree_view, 0.5, 0.5)
        self.dm.redraw()

    def onMoveWindowUp(self, button):
        self.printToLog("onMoveWindowUp")
        units = float(self.object_units_for_moving.get_text())
        self.dm.getWindow().move(0, units)
        self.dm.redraw()

    def onMoveWindowDown(self, button):
        self.printToLog("onMoveWindowDown")
        units = float(self.object_units_for_moving.get_text())
        self.dm.getWindow().move(0, -units)
        self.dm.redraw()

    def onMoveWindowLeft(self, button):
        self.printToLog("onMoveWindowLeft")
        units = float(self.object_units_for_moving.get_text())
        self.dm.getWindow().move(-units, 0)
        self.dm.redraw()

    def onMoveWindowRight(self, button):
        self.printToLog("onMoveWindowRight")
        units = float(self.object_units_for_moving.get_text())
        self.dm.getWindow().move(units, 0)
        self.dm.redraw()

    def printToLog(self, text, end="\n"):
        buffer, view = self.text_buffer, self.text_view
        buffer.insert_at_cursor(text + end)
        view.scroll_to_mark(buffer.get_insert(), 0, 0, 0, 0)