# File scribble22.rb, line 149
  def initialize(app)
    # Call base class initializer first
    super(app, "Scribble Application", nil, nil, DECOR_ALL,
      0, 0, 700, 700)
                @dataString = ""

# Erzeugt ein DataTarget mit einem ColorValue
    @colorTarget = FXDataTarget.new(FXColor::Red)

    # Construct a horizontal frame to hold the main window's contents
    @contents = FXHorizontalFrame.new(self,
      LAYOUT_SIDE_TOP|LAYOUT_FILL_X|LAYOUT_FILL_Y, 0, 0, 0, 0, 0, 0, 0, 0)

    # Left pane contains the canvas
    @canvasFrame = FXVerticalFrame.new(@contents,
      FRAME_SUNKEN|LAYOUT_FILL_X|LAYOUT_FILL_Y|LAYOUT_TOP|LAYOUT_LEFT,
      0, 0, 0, 0, 10, 10, 10, 10)

    # Place a label above the canvas
    FXLabel.new(@canvasFrame, "Canvas Frame", nil,
      JUSTIFY_CENTER_X|LAYOUT_FILL_X)

    # Horizontal divider line
    FXHorizontalSeparator.new(@canvasFrame, SEPARATOR_GROOVE|LAYOUT_FILL_X)

    # Drawing canvas
    @canvas = FXCanvas.new(@canvasFrame, nil, 0,
      LAYOUT_FILL_X|LAYOUT_FILL_Y|LAYOUT_TOP|LAYOUT_LEFT)
    @canvas.connect(SEL_PAINT) do |sender, sel, event|
      FXDCWindow.new(@canvas, event) do |dc|
        dc.foreground = @canvas.backColor
        dc.fillRectangle(event.rect.x, event.rect.y, event.rect.w, event.rect.h)
                                
                                end
    end

        


    @canvas.connect(SEL_LEFTBUTTONPRESS) do
      @canvas.grab
      @mouseDown = true
    end
    @canvas.connect(SEL_MOTION) do |sender, sel, event|
      if (@mouseDown and @scribbleMode.value)
        # Get device context for the canvas
        dc = FXDCWindow.new(@canvas)
                                
        # Set the foreground color for drawing
        dc.foreground = @drawColor.rgba
                                
        # Draw a line from the previous mouse coordinates to the current ones
        if @mirrorMode.value
          cW = @canvas.width
          cH = @canvas.height
          dc.drawLine(cW-event.last_x, event.last_y,
                      cW-event.win_x, event.win_y)
          dc.drawLine(event.last_x, cH-event.last_y,
                      event.win_x, cH-event.win_y)
          dc.drawLine(cW-event.last_x, cH-event.last_y,
                      cW-event.win_x, cH-event.win_y)
        end
                
                                dc.drawLine(event.last_x, event.last_y, event.win_x, event.win_y)
 
# Speichert die Koordinaten eines Zeichenvorgangs als String     
                                @dataString = @dataString<<event.last_x.to_s<< 
                                                                                        "a"<<event.last_y.to_s<< 
                                                                                        "a"<<event.win_x.to_s << 
                                                                                        "a"<< event.win_y.to_s<< "b"
                                
                        
        
                                # We have drawn something, so now the canvas is dirty
        @dirty = true

        # Release the DC immediately
        dc.end
      end
    end
    @canvas.connect(SEL_LEFTBUTTONRELEASE) do |sender, sel, event|
      @canvas.ungrab
      if @mouseDown
        # Get device context for the canvas
        dc = FXDCWindow.new(@canvas)

        # Set the foreground color for drawing
        dc.foreground = @drawColor.rgba

        # Draw a line from the previous mouse coordinates to the current ones
        dc.drawLine(event.last_x, event.last_y, event.win_x, event.win_y)

        # We have drawn something, so now the canvas is dirty
        @dirty = true

        # Mouse no longer down
        @mouseDown = false

        # Release this DC immediately
        dc.end
      end
    end


# Zeichnet die das übergebene Polynom mit den übergeben Parametern
                        def drawFunction(function,zoomTarget,zoomValue,xCoordTarget,yCoordTarget)
                                        FXDCWindow.new(@canvas) do |dc|
                                        dc.foreground = @canvas.backColor
                                        dc.fillRectangle(0, 0, @canvas.width, @canvas.height)
                                        @dirty = false
                                
# Regulärer Ausdruck zur Zerlegung des Polynoms in Monome
                                        monomExp = /([\+|-]?\d+\.\d+\*x\*\*\d+)/

                                        functionArray = function.to_s.scan(monomExp)
                                        zoom   = zoomTarget.to_s.to_f+0.5
                                        xCoord = xCoordTarget.to_s.to_f
                                        yCoord = yCoordTarget.to_s.to_f

# neue Polynominstanz                                   
                                        @pol= Polynom.new

# Ermitteln der Koeffizienten und Exponenten
# jedes einzelnen Monoms mit Hilfe von reg. Ausdrücken
                                        for i in 0..functionArray.length-1 do
                                                coeff = functionArray[i].to_s.scan(/[\+|-]?\d+.\d+/)[0].to_f
                                                exp   = functionArray[i].to_s.scan(/\d+/)[2].to_i
                                                monom=Monom.new(coeff,exp)
                                                @pol.extPoly(monom)
                                        end
                                        
# Nullstelle des Polynoms zur Justierung von Koordinatenursprung und Zoomfaktor
                                        intersectY = @pol.evalPoly(0)

# Berechnung des nötigen Zoomfaktors
                        if !zoomValue        
                                        const =50
                                        if intersectY > 0
                                                while intersectY*const > yCoord
                                                        const = const/2
                                                end
                                        else
                                                if intersectY != 0
                                                        while (intersectY*const).abs > (@canvas.height-yCoord)
                                                                const = const/2
                                                        end
                                                end
                                        end        
                        else
                                const = zoom
                        end
                        
# Zeichnen und Skalieren der y-Achse                            
                                        dc.foreground = 'black'
                                        dc.drawLine(xCoord, 0, xCoord, @canvas.height)
                                        i = yCoord
                                        j = yCoord
                                        while ((i.abs+j.abs) <= 2*@canvas.height)
                                                dc.drawLine(xCoord-5, i+const, xCoord+5, i+const)
                                                i += const
                                                dc.drawLine(xCoord-5, j-const, xCoord+5, j-const)
                                                j -= const
                                        end
                                        
# Zeichnen und Skalieren der x-Achse
                                        dc.drawLine(0, yCoord, @canvas.width, yCoord)
                                        i = xCoord
                                        j = xCoord
                                        while ((i.abs+j.abs) <= 2*@canvas.width)
                                                dc.drawLine(i+const, yCoord-5, i+const, yCoord+5)
                                                i += const
                                                dc.drawLine(j-const, yCoord-5, j-const, yCoord+5)
                                                j -= const
                                        end
                                        
# Berechnen und Zeichnen der Funktion
                                        dc.foreground = @drawColor.rgba
                                        i=-12*(50/const)
                                        while i<12*(50/const)
                                                dc.drawPoint(xCoord+i*const      , yCoord-@pol.evalPoly(i)*const)
                                                dc.drawLine(xCoord+(i-0.1)*const , yCoord-@pol.evalPoly(i-0.1)*const,
                                                                                                xCoord+i*const       , yCoord-@pol.evalPoly(i)*const)
                                                i=i+0.1
                                        end
                                end
                        end                          

                        

    # Right pane for the buttons
    @buttonFrame = FXVerticalFrame.new(@contents,
      FRAME_SUNKEN|LAYOUT_FILL_Y|LAYOUT_TOP|LAYOUT_LEFT,
      0, 0, 0, 0, 10, 10, 10, 10)

  
                
                # Label above the buttons
    FXLabel.new(@buttonFrame, "Button Frame", nil,
      JUSTIFY_CENTER_X|LAYOUT_FILL_X)

    # Horizontal divider line
    FXHorizontalSeparator.new(@buttonFrame,
      SEPARATOR_RIDGE|LAYOUT_FILL_X)

    # Enable or disable mirror mode
    @mirrorMode = FXDataTarget.new(false)
    FXCheckButton.new(@buttonFrame, "Mirror", @mirrorMode, FXDataTarget::ID_VALUE, CHECKBUTTON_NORMAL|LAYOUT_FILL_X)
        
# Ein- und Ausschalten des manuellen Zoommodus
    @scribbleMode = FXDataTarget.new(false)
    FXCheckButton.new(@buttonFrame, "Scibble", @scribbleMode, FXDataTarget::ID_VALUE, CHECKBUTTON_NORMAL|LAYOUT_FILL_X)

                # Horizontal divider line
    FXHorizontalSeparator.new(@buttonFrame,
    SEPARATOR_RIDGE|LAYOUT_FILL_X)

        
        
    # Button to clear the canvas
    clearButton = FXButton.new(@buttonFrame, "&Clear", nil, nil, 0,
      FRAME_THICK|FRAME_RAISED|LAYOUT_FILL_X|LAYOUT_TOP|LAYOUT_LEFT,
      0, 0, 0, 0, 10, 10, 5, 5)
    clearButton.connect(SEL_COMMAND) do
      FXDCWindow.new(@canvas) do |dc|
        dc.foreground = @canvas.backColor
        dc.fillRectangle(0, 0, @canvas.width, @canvas.height)
        @dirty = false
# Löschen des Speicherstrings
                                @dataString = ""
      end
    end
    clearButton.connect(SEL_UPDATE) do |sender, sel, ptr|
      # This procedure handles the update message sent by the Clear button
      # to its target. Every widget in FOX receives a message (SEL_UPDATE)
      # during idle processing, asking it to update itself. For example,
      # buttons could be enabled or disabled as the state of the application
      # changes.
      #
      # In this case, we'll disable the sender (the Clear button) when the
      # canvas has already been cleared (i.e. it's "clean"), and enable it when
      # it has been painted (i.e. it's "dirty").
      message = @dirty ? FXWindow::ID_ENABLE : FXWindow::ID_DISABLE
      sender.handle(self, MKUINT(message, SEL_COMMAND), nil)
                end
                


# Zeichnen eines geladenen Bildes       
        def drawLoadedPicture(str)
                        dc = FXDCWindow.new(@canvas)
                        dc.foreground = @canvas.backColor
                        dc.fillRectangle(0, 0, @canvas.width, @canvas.height)
                        dc.foreground = @drawColor.rgba
                        
                        stringArray = str.scan(/-?\d+/)

# Auslesen der 4 Koordinaten mit Hilfe von reg. Ausdrücken                      
                        while stringArray.length != 0
                                dc.drawLine(stringArray[0].to_i, stringArray[1].to_i, stringArray[2].to_i, stringArray[3].to_i)
                                stringArray.delete_at(0)
                                stringArray.delete_at(0)
                                stringArray.delete_at(0)
                                stringArray.delete_at(0)
                        end
                        @dirty = true
        end
        
#Save-Button zum Speichern eines gezeichneten Bildes    
                        saveButton = FXButton.new(@buttonFrame, "&Save", nil, nil, 0,
                                                                                                                                FRAME_THICK|FRAME_RAISED|LAYOUT_FILL_X|LAYOUT_TOP|LAYOUT_LEFT,
                                                                                                                                0, 0, 0, 0, 10, 10, 5, 5)
                        
                        saveButton.connect(SEL_COMMAND)do
                                                File.open("Bild","w") do |f|
                                                Marshal.dump(@dataString,f)
                                                end
                        end

#Load-Button zum Laden eines gespeicherten Bildes       
                        loadButton = FXButton.new(@buttonFrame, "&Load", nil, nil, 0,
                                                                                                                                FRAME_THICK|FRAME_RAISED|LAYOUT_FILL_X|LAYOUT_TOP|LAYOUT_LEFT,
                                                                                                                                0, 0, 0, 0, 10, 10, 5, 5)
                
                        loadButton.connect(SEL_COMMAND)do
                                                File.open("Bild") do |f|
                                                str=(Marshal.load(f))
                                                drawLoadedPicture(str)
                                                end
                        end



# DialogBoxButton       zum Erzeugen des Dialogfensters
                        dialButton = FXButton.new(@buttonFrame, "&DialogBox", nil, nil, 0,
                                                                                                                                FRAME_THICK|FRAME_RAISED|LAYOUT_FILL_X|LAYOUT_TOP|LAYOUT_LEFT,
                                                                                                                                0, 0, 0, 0, 10, 10, 5, 5)       

                        dialButton.connect(SEL_COMMAND)do
                                                if !@scribbleMode.value
                                                                dialog=DialogWindow.new(self)
                                                                dialog.execute
                        end

                        dialButton.connect(SEL_UPDATE) do |sender, sel, ptr|
                                                                message = !@scribbleMode.value ? FXWindow::ID_ENABLE : FXWindow::ID_DISABLE
                                                                sender.handle(self, MKUINT(message, SEL_COMMAND), nil)
                        end

end

        

                # Exit button
                        FXButton.new(@buttonFrame, "&Exit", nil, app, FXApp::ID_QUIT,
                                                                         FRAME_THICK|FRAME_RAISED|LAYOUT_FILL_X|LAYOUT_TOP|LAYOUT_LEFT,
                                                                         0, 0, 0, 0, 10, 10, 5, 5)
                                                                         

# Label und ColorWell zur Festlegung der Zeichenfarbe
    FXLabel.new(@buttonFrame, "&Color", nil,
                                                                LAYOUT_LEFT|LAYOUT_TOP|LAYOUT_LEFT)
    
                @drawColor = FXColorWell.new(@buttonFrame, 0, @colorTarget, FXDataTarget::ID_VALUE,
                                                                                                                                 LAYOUT_CENTER_X|FRAME_SUNKEN|FRAME_THICK|LAYOUT_LEFT)
    @drawColor.connect(SEL_COMMAND, method(:onCmdWell))


    # Initialize other member variables
    @mouseDown = false
    @dirty = false
  end