# 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 <curt@hibbs.com>
# 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

