# Purpose: Setup and initialize the dock bar gui interfaces
#
# $Id: source_browser.rb,v 1.3 2004/10/05 19:45:37 ljulliar Exp $
#
# Authors:  NISHIO Mizuho
# Contributors: Rich Kilmer
#
# 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) 2002 NISHIO Mizuho. All rights reserved.
#

require 'rubyide_tools_fox_source_browser/source_tree'

module FreeRIDE
  module FoxRenderer
    
    class SourceBrowser
      include Fox
      extend FreeBASE::StandardPlugin
      
      def self.start(plugin)
        # Handle icons
        plugin['/system/ui/icons/SourceBrowser'].subscribe do |event, slot|
          if event == :notify_slot_add
            app = plugin['/system/ui/fox/FXApp'].data
            path = "#{plugin.plugin_configuration.full_base_path}/icons/#{slot.name}.png"
            if FileTest.exist?(path)
              slot.data = Fox::FXPNGIcon.new(app, File.open(path, "rb").read)
              slot.data.create
            end
          end
        end
        
        # Add command
        browser = SourceBrowser.new(plugin)
        plugin["/system/ui/commands"].manager.add("App/View/SourceBrowser","Source Browser","View Source Navigation Tree") do |cmd_slot|
          browser.toggle
        end
        plugin["/system/ui/commands"].manager.command("App/View/SourceBrowser").icon = "/system/ui/icons/SourceBrowser/ruby_file"
        plugin["/system/ui/keys"].manager.bind("App/View/SourceBrowser", :F7)
        
        plugin["/system/ui/current/ToolBar"].manager.add_command("View", "App/View/SourceBrowser")
        
        # Insert the inspector in the Tools menu
        viewmenu = plugin["/system/ui/components/MenuPane/View_menu"].manager
        viewmenu.add_command("App/View/SourceBrowser")
        viewmenu.uncheck("App/View/SourceBrowser")
        
        
        plugin["/system/state/all_plugins_loaded"].subscribe do |event, slot|
          if slot.data == true
            if plugin.properties["Open"]
              browser.toggle
            end
          end
        end

	# run the thread polling for file update that needs refresh
	Thread.new(plugin, browser) do |plugin, browser|
	  file_sizes = Hash.new
	  while true
	    sleep 5
	    if plugin['/system/ui/current/EditPane'].is_link_slot? && browser.visible? 
	      length = plugin['/system/ui/current/EditPane/actions/get_text_length'].invoke
	      filename = plugin['/system/ui/current/EditPane'].data

	      if (file_sizes[filename] != length)
		browser.update
		file_sizes[filename] = length
	      end
	    end
	  end
	end
        
        plugin.transition(FreeBASE::RUNNING)
      end
      
      def initialize(plugin)
        @docked = false
        @plugin = plugin
        @cmd_mgr = plugin['/system/ui/commands'].manager
        @dockpane_slot = plugin['/system/ui/components/DockPane'].manager.add("Source View")
        main_window = @plugin["/system/ui/fox/FXMainWindow"].data
        frm = Fox::FXHorizontalFrame.new(main_window, FRAME_SUNKEN|LAYOUT_FILL_X|LAYOUT_FILL_Y,0,0,0,0,0,0,0,0)      
        @tree = SourceTree.new(frm, plugin)
        @viewmenu = plugin["/system/ui/components/MenuPane/View_menu"].manager
        frm.hSpacing = 0
        frm.vSpacing = 0
        frm.hide
        frm.create
        @dockpane_slot.data = frm
        def @tree.on_selected(node)
          line_no = self.get_node_data(node)
          editpane = @plugin["/system/ui/current/EditPane"].manager
          if editpane
            editpane.set_cursor_line(line_no+1)
          end
        end
        @plugin['/system/ui/current'].subscribe do |event, slot|
          if slot.name=="EditPane" && @docked
            if event == :notify_slot_link
              update
            elsif event==:notify_slot_unlink
              @tree.clear_nodes
            end
          end
        end
      end
      
      def visible?
	@dockpane_slot.manager.current?
      end

      def toggle
        unless @docked
          @dockpane_slot.manager.dock('west')
          @docked = true
          @viewmenu.check("App/View/SourceBrowser")
          update
          @checked = true
          @plugin.properties["Open"] = true
        else
          if @checked
            @dockpane_slot.manager.hide
            @viewmenu.uncheck("App/View/SourceBrowser")
            @checked = false
            @plugin.properties["Open"] = false
          else
            @dockpane_slot.manager.show
            @checked = true
            @viewmenu.check("App/View/SourceBrowser")
            @plugin.properties["Open"] = true
          end
        end
      end
      
      def update
          editpane = @plugin["/system/ui/current/EditPane"].manager
          if editpane
            source = editpane.parse_code
            @tree.clear_nodes
            append_to_tree(source.top_level_context, @tree.root_node) if source
            expandTree(@tree)
          end
      end
      
      def expandTree(treeList, item=nil)
        item = treeList unless item
        item.each do |child|
          treeList.expandTree(child)
          expandTree(treeList, child)
        end
      end
      
      
      def append_to_tree(source_tree, node, icon=nil)
        if source_tree.name == ""
          name = @plugin["/system/ui/current/EditPane"].data
          icon = @plugin["/system/ui/icons/SourceBrowser/ruby_file"].data
        else
          name = source_tree.name
        end
        
        new_node = @tree.add_child_node(node, name, icon)
        @tree.set_node_data(new_node, source_tree.start_point.line_no)
      
        source_tree.each_singleton_method do |meth|
          n = @tree.add_child_node(new_node, meth.name, @plugin["/system/ui/icons/SourceBrowser/method"].data)  
          @tree.set_node_data(n, meth.start_point.line_no)
        end
      
        source_tree.each_method do |meth|
          n = @tree.add_child_node(new_node, meth.name, @plugin["/system/ui/icons/SourceBrowser/method"].data)  
          @tree.set_node_data(n, meth.start_point.line_no)
        end
        
        source_tree.each_module do |mod|
          append_to_tree(mod, new_node, @plugin["/system/ui/icons/SourceBrowser/module"].data)
        end
        
        source_tree.each_singleton_class do |c|
          append_to_tree(c, new_node, @plugin["/system/ui/icons/SourceBrowser/class"].data)
        end
        
        source_tree.each_class do |klass|
          append_to_tree(klass, new_node, @plugin["/system/ui/icons/SourceBrowser/class"].data)
        end
        
      end

      
    end
    
  end
end
