Class | OldFoxGUI |
In: |
OldFoxGUI.rb
|
Parent: | FXMainWindow |
DEG | = | Math::PI / 180 | Converts degrees to radians |
Initialize a new RubyLogo application window and its components.
# File OldFoxGUI.rb, line 29 def initialize(app) begin super(app, "RubyLogo", FXPNGIcon.new(app, File.open("icon.png", "rb"){|f| f.read}, 0, 0, 40, 40), nil, DECOR_ALL, 50, 50, 1000, 650) rescue StandardError super(app, "RubyLogo", nil, nil, DECOR_ALL, 50, 50, 1000, 650) end FXTooltip.new(app) # Menu bar and buttons at the top of the main window menubar = FXMenubar.new(self, LAYOUT_SIDE_TOP|LAYOUT_FILL_X|PACK_UNIFORM_WIDTH, 0,0,0,0,0,0,0,0, 20) begin pushNew = FXButton.new(menubar, "&New\t\tCreate new logo script", FXPNGIcon.new(app, File.open("new.png", "rb"){|f| f.read}, 0, 0, 40, 40), nil, 0, FRAME_RAISED|BUTTON_TOOLBAR|ICON_BEFORE_TEXT) rescue StandardError pushNew = FXButton.new(menubar, "&New\t\tCreate new logo script", nil, nil, 0, FRAME_RAISED|BUTTON_TOOLBAR|ICON_BEFORE_TEXT) end pushNew.connect(SEL_COMMAND, method(:btnNew)) pushNew.tipText = "New" pushNew.backColor = FXRGB(205,205,205) begin pushLoad = FXButton.new(menubar, "&Load\t\tLoad logo script", FXPNGIcon.new(app, File.open("load.png", "rb"){|f| f.read}, 0, 0, 40, 40), nil, 0, FRAME_RAISED|BUTTON_TOOLBAR|ICON_BEFORE_TEXT) rescue StandardError pushLoad = FXButton.new(menubar, "&Load\t\tLoad logo script", nil, nil, 0, FRAME_RAISED|BUTTON_TOOLBAR|ICON_BEFORE_TEXT) end pushLoad.connect(SEL_COMMAND, method(:btnLoad)) pushLoad.tipText = "Load Script" pushLoad.backColor = FXRGB(205,205,205) begin pushSave = FXButton.new(menubar, "&Save\t\tSave logo script", FXPNGIcon.new(app, File.open("save.png", "rb"){|f| f.read}, 0, 0, 40, 40), nil, 0, FRAME_RAISED|BUTTON_TOOLBAR|ICON_BEFORE_TEXT) rescue StandardError pushSave = FXButton.new(menubar, "&Save\t\tSave logo script", nil, nil, 0, FRAME_RAISED|BUTTON_TOOLBAR|ICON_BEFORE_TEXT) end pushSave.connect(SEL_COMMAND, method(:btnSave)) pushSave.tipText = "Save Script" pushSave.backColor = FXRGB(205,205,205) begin pushRun = FXButton.new(menubar, "&Run\t\tRun logo script", FXPNGIcon.new(app, File.open("run.png", "rb"){|f| f.read}, 0, 0, 40, 40), nil, 0, FRAME_RAISED|BUTTON_TOOLBAR|ICON_BEFORE_TEXT) rescue StandardError pushRun = FXButton.new(menubar, "&Run\t\tRun logo script", nil, nil, 0, FRAME_RAISED|BUTTON_TOOLBAR|ICON_BEFORE_TEXT) end pushRun.connect(SEL_COMMAND, method(:btnRun)) pushRun.tipText = "Run" pushRun.backColor = FXRGB(205,205,205) begin pushExit = FXButton.new(menubar, "&Exit\t\tExit program", FXPNGIcon.new(app, File.open("exit.png", "rb"){|f| f.read}, 0, 0, 40, 40), nil, 0, FRAME_RAISED|BUTTON_TOOLBAR|LAYOUT_RIGHT|ICON_BEFORE_TEXT) rescue StandardError pushExit = FXButton.new(menubar, "&Exit\t\tExit program", nil, nil, 0, FRAME_RAISED|BUTTON_TOOLBAR|LAYOUT_RIGHT|ICON_BEFORE_TEXT) end pushExit.connect(SEL_COMMAND) {exit} pushExit.tipText = "Exit" pushExit.backColor = FXRGB(205,205,205) begin pushHelp = FXButton.new(menubar, "&Help\t\tShow help page", FXPNGIcon.new(app, File.open("help.png", "rb"){|f| f.read}, 0, 0, 40, 40), nil, 0, FRAME_RAISED|BUTTON_TOOLBAR|LAYOUT_RIGHT|ICON_BEFORE_TEXT) rescue StandardError pushHelp = FXButton.new(menubar, "&Help\t\tShow help page", nil, nil, 0, FRAME_RAISED|BUTTON_TOOLBAR|LAYOUT_RIGHT|ICON_BEFORE_TEXT) end pushHelp.connect(SEL_COMMAND, method(:btnHelp)) pushHelp.tipText = "Help" pushHelp.backColor = FXRGB(205,205,205) # Status bar at the bottom of the main window @statusbar = FXStatusbar.new(self, LAYOUT_SIDE_BOTTOM|LAYOUT_FILL_X) @statusbar.statusline.normalText = "RubyLogo" @turtleinfo = FXLabel.new(@statusbar, "", nil, LAYOUT_RIGHT|LAYOUT_FILL_Y|FRAME_SUNKEN, 0, 0) # Layout composites for the main area of the user interface splith = FXSplitter.new(self, LAYOUT_FILL_X|LAYOUT_FILL_Y|SPLITTER_HORIZONTAL|SPLITTER_TRACKING, 0, 0) splitv = FXSplitter.new(splith, LAYOUT_FILL_X|SPLITTER_VERTICAL|SPLITTER_TRACKING|SPLITTER_REVERSED, 0, 0, 400) editbox = FXPacker.new(splitv, LAYOUT_FILL_X|LAYOUT_FILL_Y, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) # Input line which sends entered Logo commands immediately to the parser @cmdline = FXTextField.new(editbox, 0, nil, 0, LAYOUT_SIDE_BOTTOM|LAYOUT_FILL_X|FRAME_GROOVE|TEXTFIELD_ENTER_ONLY) @cmdline.backColor = FXRGB(255, 255, 255) @cmdline.textColor = FXRGB(0, 0, 0) @cmdline.connect(SEL_COMMAND, method(:lineEval)) # Editor window for Logo programs @editor = FXText.new(editbox, nil, 0, LAYOUT_FILL_X|LAYOUT_FILL_Y|VSCROLLER_ALWAYS) @editor.backColor = FXRGB(255, 255, 255) @editor.textColor = FXRGB(0, 0, 0) @editor.tabColumns = 2 # Read-only terminal area for status and error messages @terminal = FXText.new(splitv, nil, 0, LAYOUT_FILL_X|VSCROLLER_ALWAYS|TEXT_READONLY, 0, 0, 400, 100) @terminal.backColor = FXRGB(50, 50, 50) @terminal.textColor = FXRGB(0, 255, 0) @terminal.tabColumns = 2 # Drawing area for the turtle @scrollwin = FXScrollWindow.new(splith, LAYOUT_FILL_X|LAYOUT_FILL_Y) scrollfix = FXPacker.new(@scrollwin, LAYOUT_FILL_X|LAYOUT_FILL_Y, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) # scrollwin has wrong range associated to its scrollbars # manually update to known real values @scrollwin.verticalScrollbar.range = 5000 @scrollwin.horizontalScrollbar.range = 5000 replaceTurtle # create new turtle for the drawing area @turtlearea = FXCanvas.new(scrollfix, nil, 0, LAYOUT_FIX_WIDTH|LAYOUT_FIX_HEIGHT, 0, 0, 5000, 5000) @turtlearea.connect(SEL_PAINT) { |sender, sel, event| FXDCWindow.new(@turtlearea, event) { |terrarium| # drawing area background terrarium.foreground = @tortoise.background terrarium.fillRectangle(event.rect.x, event.rect.y, event.rect.w, event.rect.h) # lines drawn by the turtle @tortoise.getLines { |line| terrarium.foreground = line.color # defaults to 'black' if not a valid color begin # move coordinates to adapt to drawing area terrarium.drawLine(line.startx+2500, 2500-line.starty, line.endx+2500, 2500-line.endy) rescue RangeError @tortoise.log "ERROR: Drawing coordinates out of range" writeLog @tortoise.messages end } drawTurtle(terrarium) # draw turtle at its current position } } refreshTurtle # update status for turtle end
Action when the button ‘Help’ is pushed. Open a LogoGUIInfoBox message window containing helpful information.
# File OldFoxGUI.rb, line 253 def btnHelp(sender, sel, event) infobox = OldFoxGUIInfoBox.new(self) infobox.execute(PLACEMENT_SCREEN) end
Action when the button ‘Load’ is pushed. Open a file browser and load the selected file into the editor area.
# File OldFoxGUI.rb, line 197 def btnLoad(sender, sel, event) openDialog = FXFileDialog.new(self, "Load Script") openDialog.patternList = ["Logo (*.logo)", "All Files (*)"] if openDialog.execute(PLACEMENT_SCREEN) != 0 btnNew(sender, sel, event) # clear all before loading new file begin File.open(openDialog.filename) { |file| @editor.setText(file.read) } rescue StandardError => error FXMessageBox.error(self, MBOX_OK, "Error", "#{error}") end end return 1 end
Action when the button ‘Run’ is pushed. Let the Parser evaluate the current contents of the editor window and display the corresponding actions of the Turtle.
# File OldFoxGUI.rb, line 243 def btnRun(sender, sel, event) replaceTurtle @statusbar.statusline.text = "Please wait. Parser is busy." @lineparser.parse(@editor.text) refreshTurtle end
Action when the button ‘Save’ is pushed. Open a file browser and save the contents of the editor area to the entered file.
# File OldFoxGUI.rb, line 214 def btnSave(sender, sel, event) saveDialog = FXFileDialog.new(self, "Save Script") saveDialog.patternList = ["Logo (*.logo)", "All Files (*)"] if saveDialog.execute(PLACEMENT_SCREEN) != 0 if File.exists? saveDialog.filename if MBOX_CLICKED_NO == FXMessageBox.warning(self, MBOX_YES_NO, "Overwrite File?", "File #{saveDialog.filename} already exists. Overwrite?") return 1 end end begin File.open(saveDialog.filename, "w") { |file| file.write(@editor.text) } rescue Errno::ENOSPC => error File.delete(saveDialog.filename) if File.exist?(saveDialog.filename) FXMessageBox.error(self, MBOX_OK, "Error", "#{error}") rescue EOFError => error File.delete(saveDialog.filename) if File.exist?(saveDialog.filename) FXMessageBox.error(self, MBOX_OK, "Error", "#{error}") rescue StandardError => error FXMessageBox.error(self, MBOX_OK, "Error", "#{error}") end end return 1 end
Draw the Turtle to the drawing area. The Turtle has the shape of an arrowhead and is drawn in it’s current pen color.
# File OldFoxGUI.rb, line 281 def drawTurtle(drawarea) if @tortoise.visible drawarea.foreground = @tortoise.color # rotate and move turtle to adapt to drawing area coordinate system dr = @tortoise.direction + 180 x0 = @tortoise.posx+2500 y0 = 2500-@tortoise.posy x1 = x0 + 20 * Math.cos((dr-45) * DEG) y1 = y0 + 20 * Math.sin((dr-45) * DEG) x2 = x0 + 20 * Math.cos((dr+225) * DEG) y2 = y0 + 20 * Math.sin((dr+225) * DEG) x3 = x0 + 20 * Math.cos((dr+90) * DEG) y3 = y0 + 20 * Math.sin((dr+90) * DEG) begin drawarea.drawLine(x0, y0, x1, y1) drawarea.drawLine(x0, y0, x2, y2) drawarea.drawLine(x1, y1, x3, y3) drawarea.drawLine(x2, y2, x3, y3) rescue RangeError @tortoise.log "ERROR: Turtle coordinates out of range" writeLog @tortoise.messages end end end
Evaluate the contents of the input line
# File OldFoxGUI.rb, line 260 def lineEval(sender, sel, event) @editor.setText(@editor.text.chomp+"\n"+event+"\n") @cmdline.setText("") @editor.makePositionVisible(@editor.getLength) @lineparser.parse(event+"\n") refreshTurtle @tortoise.clearMessages end
Update the drawn image, message log and status line information. Check if the color attribute of the Turtle is a compatible color string and replace it if necessary.
# File OldFoxGUI.rb, line 320 def refreshTurtle # GUI defaults to 'black' for unknown color names. Let's tell our turtle @tortoise.color = "black" if fxcolorfromname(@tortoise.color) == 0 # Default background should be white. Catch invalid names and replace @tortoise.background = "white" if @tortoise.background != "black" && fxcolorfromname(@tortoise.background) == 0 # don't show color if pen is up @tortoise.pen ? currentcol = @tortoise.color : currentcol = "NONE" @turtleinfo.text = sprintf("Position: %.2f, %.2f Direction: %.2f° Color: \ #{currentcol} BG: #{@tortoise.background}", @tortoise.posx, @tortoise.posy, @tortoise.direction) writeLog @tortoise.messages @turtlearea.update end
Replace the Turtle with a new object instance and associate a new Parser object to it.
# File OldFoxGUI.rb, line 309 def replaceTurtle @terminal.setText("") @tortoise = LogoTurtle.new(0, 0, 0, "black", "white") @lineparser = LogoParser.new(@tortoise) @scrollwin.setPosition(-2210, -2210) end