# Purpose: Setup and initialize the core gui interfaces # # $Id: appframe.rb,v 1.11 2005/09/16 07:55:33 ljulliar Exp $ # # Authors: Curt Hibbs # Contributors: # # This file is part of the FreeRIDE project # # This application is free software; you can redistribute it and/or # modify it under the terms of the Ruby license defined in the # COPYING file. # # Copyright (c) 2001 Curt Hibbs. All rights reserved. # begin require 'rubygems' require_gem 'fxruby', '>= 1.2.0', '< 1.4.0' rescue LoadError require 'fox12' end require 'fox12/colors' require 'rubyide_fox_gui/fxscintilla/scintilla' module FreeRIDE module FoxRenderer ## # This is the module that renders application-frames using # FOX. # class AppFrame extend FreeBASE::StandardPlugin def AppFrame.start(plugin) component_slot = plugin["/system/ui/components/AppFrame"] component_slot.subscribe do |event, slot| if (event == :notify_slot_add && slot.parent == component_slot) app = Fox::FXApp.new("FreeRIDE", "FreeRIDE") r = Renderer.new(plugin, slot, app) app.create plugin["/system/ui/messagepump"].set_proc do begin app.run rescue exc_box = FreerideExceptionBox.new(r,"#{$!.class}: #{$!.message}\n\n#{$@.join("\n")}") if exc_box.execute == MBOX_CLICKED_YES plugin['/system/ui/components/EditPane'].each_slot {|ep| ep.manager.save} end # raise the exception again for the text console raise ensure plugin["/system/shutdown"].call(1) end end end end component_slot.each_slot { |slot| slot.notify(:notify_slot_add) } plugin.transition(FreeBASE::RUNNING) end ## # Each instance of this class is responsible for rendering an application-frame component # class Renderer < Fox::FXMainWindow include Fox attr_reader :plugin def initialize(plugin, slot, app) @plugin = plugin @slot = slot @app = app @command = @slot["/system/ui/commands"] @plugin.log_info << "AppFrame started" # use the FR mini icon for the main window mi_path = "#{plugin.plugin_configuration.full_base_path}/icons/bullseye.ico" mi = Fox::FXICOIcon.new(@app, File.open(mi_path, "rb").read) super(@app, @slot.data, mi, mi, DECOR_ALL) FXToolTip.new(@app, TOOLTIP_NORMAL) appFrameSetup connect(SEL_CLOSE) { @plugin["/system/ui/commands"].manager.command("App/Services/Shutdown").invoke } @plugin["/system/state/all_plugins_loaded"].subscribe do |event, slot| self.recalc self.forceRefresh end end def create super x = @plugin.properties["Location/X"] y = @plugin.properties["Location/Y"] width = @plugin.properties["Location/Width"] height = @plugin.properties["Location/Height"] x ||= 1 y ||= 1 width ||= 800 height ||= 600 position(x,y,width,height) if x==1 show(PLACEMENT_SCREEN) else show end end def appFrameSetup @menubar = FXMenuBar.new(self, LAYOUT_SIDE_TOP|LAYOUT_FILL_X) FXHorizontalSeparator.new(self, LAYOUT_SIDE_TOP|SEPARATOR_GROOVE|LAYOUT_FILL_X); @toolbar = FXToolBar.new(self, LAYOUT_SIDE_TOP|LAYOUT_FILL_X,0, 0, 0, 0, 4, 4, 0, 0, 0, 0) @statusbar = FXStatusBar.new(self, LAYOUT_SIDE_BOTTOM|LAYOUT_FILL_X|STATUSBAR_WITH_DRAGCORNER) # Vertical splitter svFrame contains the south dock bar at the # bottom and a horizontal splitter in the upper part which itself # contains the East Dock bar, the Scintilla widget and the West # dock bar. @svFrame = FXSplitter.new(self, LAYOUT_FILL_X|LAYOUT_FILL_Y| SPLITTER_TRACKING|SPLITTER_VERTICAL|SPLITTER_REVERSED) @shFrame = FXSplitter.new(@svFrame, LAYOUT_FILL_X|LAYOUT_FILL_Y| SPLITTER_TRACKING|SPLITTER_HORIZONTAL) @dockbar_west = FXVerticalFrame.new(@shFrame, FRAME_THICK|LAYOUT_FILL_X|LAYOUT_FILL_Y) @dockbar_west.width = 0 @dockbar_west.padRight = 0 @dockbar_west.padTop = 0 @dockbar_west.padLeft = 0 @dockbar_west.padBottom = 0 # Scintilla widget is in the middle @contentFrame = FXHorizontalFrame.new(@shFrame, FRAME_THICK|LAYOUT_FILL_X|LAYOUT_FILL_Y) @contentFrame.width = self.width - 30 @contentFrame.padRight = 0 @contentFrame.padTop = 0 @contentFrame.padLeft = 0 @contentFrame.padBottom = 0 # dockbar south at the bottom of the vertical frame @dockbar_south = FXHorizontalFrame.new(@svFrame, FRAME_THICK|LAYOUT_FILL_X|LAYOUT_FILL_Y) @dockbar_south.padRight = 0 @dockbar_south.padTop = 0 @dockbar_south.padLeft = 0 @dockbar_south.padBottom = 0 @dockbar_south.height = 0 @plugin["/system/ui/fox/FXApp"].data = @app @plugin["/system/ui/fox/FXMainWindow"].data = self @plugin["/system/ui/fox/FXMenuBar"].data = @menubar @plugin["/system/ui/fox/FXToolBar"].data = @toolbar @plugin["/system/ui/fox/FXStatusBar"].data = @statusbar @plugin["/system/ui/fox/contentFrame"].data = @contentFrame @plugin["/system/ui/fox/dockbar/west/frame"].data = @dockbar_west @plugin["/system/ui/fox/dockbar/west/textAngle"].data = -90 @plugin["/system/ui/fox/dockbar/south/frame"].data = @dockbar_south @plugin["/system/ui/fox/dockbar/south/textAngle"].data = 0 @plugin.log_info << "Dockbar UI components positioned OK!" #LJ@app.create @running = true # BGB - START # was: # @plugin["/system/ui/messagepump"].set_proc do # begin # @app.run # rescue # exc_box = FreerideExceptionBox.new(self,"#{$!.class}: #{$!.message}\n\n#{$@.join("\n")}") # if exc_box.execute == MBOX_CLICKED_YES # @plugin['/system/ui/components/EditPane'].each_slot {|ep| ep.manager.save} # end # # raise the exception again for the text console # raise # ensure # @running = false # @plugin["/system/shutdown"].call(1) # end # end # now: # BGB - END end def shutdown @plugin.properties["Location/Width"] = self.width @plugin.properties["Location/Height"] = self.height @plugin.properties["Location/X"] = self.x @plugin.properties["Location/Y"] = self.y @app.handle(self, Fox.MKUINT(Fox::FXApp::ID_QUIT, Fox::SEL_COMMAND), nil) end end class FreerideExceptionBox < Fox::FXDialogBox include Fox include Responder HORZ_PAD = 30 VERT_PAD = 2 def initialize(owner,text) FXMAPFUNC(SEL_COMMAND, ID_CANCEL, :onCmdClickedNo) FXMAPFUNC(SEL_COMMAND, ID_ACCEPT, :onCmdClickedYes) # Invoke base class initialize function first super(owner, "FreeRIDE went south...", DECOR_TITLE|DECOR_BORDER|DECOR_CLOSE|DECOR_RESIZE) self.width = 580 self.height = 430 self.padLeft = 0 self.padRight = 0 content = FXVerticalFrame.new(self,LAYOUT_FILL_X|LAYOUT_FILL_Y) #info = FXHorizontalFrame.new(content,LAYOUT_TOP|LAYOUT_LEFT|LAYOUT_FILL_X|LAYOUT_FILL_Y,0,0,0,0,10,10,10,10); #FXLabel.new(info,nil,ic,ICON_BEFORE_TEXT|LAYOUT_TOP|LAYOUT_LEFT|LAYOUT_FILL_X|LAYOUT_FILL_Y) FXLabel.new(content,"Unhandled Exception Caught:",nil,JUSTIFY_LEFT|ICON_BEFORE_TEXT|LAYOUT_TOP|LAYOUT_LEFT|LAYOUT_FILL_X) text_area = FXText.new(content,nil,0,JUSTIFY_LEFT|TEXT_READONLY|LAYOUT_TOP|LAYOUT_LEFT|LAYOUT_FILL_X|LAYOUT_FILL_Y) text_area.text = text FXLabel.new(content,"Please report the bug to http://rubyforge.org/tracker/?group_id=31\n\nWould you like to save modified files now?",nil,JUSTIFY_LEFT|ICON_BEFORE_TEXT|LAYOUT_TOP|LAYOUT_LEFT|LAYOUT_FILL_X) FXHorizontalSeparator.new(content,SEPARATOR_GROOVE|LAYOUT_TOP|LAYOUT_LEFT|LAYOUT_FILL_X) buttons = FXHorizontalFrame.new(content,LAYOUT_TOP|LAYOUT_LEFT|LAYOUT_FILL_X|PACK_UNIFORM_WIDTH,0,0,0,0,10,10,10,10) initial = FXButton.new(buttons,"&Yes",nil,self,ID_ACCEPT,BUTTON_INITIAL|BUTTON_DEFAULT|FRAME_RAISED|FRAME_THICK|LAYOUT_TOP|LAYOUT_LEFT|LAYOUT_CENTER_X,0,0,0,0,HORZ_PAD,HORZ_PAD,VERT_PAD,VERT_PAD) FXButton.new(buttons,"&No",nil,self,ID_CANCEL,BUTTON_DEFAULT|FRAME_RAISED|FRAME_THICK|LAYOUT_TOP|LAYOUT_LEFT|LAYOUT_CENTER_X,0,0,0,0,HORZ_PAD,HORZ_PAD,VERT_PAD,VERT_PAD) initial.setFocus end def onCmdClickedYes(sender, sel, ptr) getApp.stopModal(self,MBOX_CLICKED_YES) hide return 1 end def onCmdClickedNo(sender, sel, ptr) getApp.stopModal(self,MBOX_CLICKED_NO) hide return 1 end end end end end