# This file is an application of the SWT module. JRubyUtils::RubyObjectBrowser may be
# used to show the contents of an object.
#--
#   The contents of this file are subject to the Mozilla Public License
#   Version 1.1 (the "License"); you may not use this file except in
#   compliance with the License. You may obtain a copy of the License at
#   http://www.mozilla.org/MPL/
#
#   Software distributed under the License is distributed on an "AS IS"
#   basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
#   License for the specific language governing rights and limitations
#   under the License.
#
#   The Initial Developer of the Original Code is Johannes Rudolph.
#   Portions created by the Initial Developer are Copyright (C) 2006
#   the Initial Developer. All Rights Reserved.
#
#   Contributor(s):
#      Johannes Rudolph <johannes.rudolph@gmail.com>

class Method
  # get the name of the method
  def name
    method_field=Java::JavaClass.for_name('org.jruby.RubyMethod').declared_field('methodName')
    method_field.accessible=true
    Java::java_to_ruby(method_field.value(Java::ruby_to_java(self)))
  end
end

class ::SWT::TreeBuilder
  include_class 'org.eclipse.swt.graphics.Image'
  include_class 'org.eclipse.swt.widgets.Display'
  def i(o)
    @@image_cache={} unless defined? @@image_cache
    return @@image_cache[o] if @@image_cache.has_key? o
    res=File.expand_path(File.dirname(__FILE__)+"/../../"+o)
    Image.new Display.getCurrent,res
  end
end

# some JRuby utilities
module JRubyUtils
  # A Browser of objects for JRuby
  #
  # link:../docs/object-tree.jpg
  class RubyObjectBrowser
    class << self
      # Builds a tree which shows the structure of the given object
      def object_tree(object)
        SWT::Builder.go do
          shell "JRuby Object Viewer by JR - visit http://virtual-void.net" do
            tree(:verticalFill=>true,:horizontalFill=>true) do
              child do
                object {object}
                @object=container do
                  label {|o|o.inspect}
                  image {i("icons/arrow_right.gif")}

                  # instance variables node
                  child "instance_variables" do
                    image {i("icons/flag_blue.gif")}
                    children(lambda{|o|o.instance_variables.sort.collect! {|x|{:object=>o,:name=>x}  }}) do
                      image {i("icons/flag_blue.gif")}
                      label {|v|v[:name]}
                      child do
                        object {|ar|
                          #puts "Object: #{ar}"
                          #name.last.instance_variable_get name
                          ar[:object].instance_variable_get ar[:name]
                        }
                        label {|o|o.to_s}
                        link {@object}
                      end
                    end
                  end

                  # methods node
                  child "methods" do
                    image {i("icons/page_text.gif")}
                    children(lambda {|o|
                               o.methods.sort.collect! do |name|
                                 {:method=>name,:object=>o}
                               end
                             }) do
                      image {i("icons/page_text.gif")}
                      label {|h|h[:method]}

                      # execute method if it has no arguments
                      conditional lambda{|h|
                        (-1..0).include? h[:object].method(h[:method]).arity
                      } do
                        child do
                          object do |h|
                            begin
                              o=h[:object].dup
                              o.send(h[:method])
                            rescue Exception=>exc
                              exc
                            end
                          end
                          link {@object}
                        end
                      end
                    end
                  end

                  # class node
                  child "class" do
                    object {|o|o.class}
                    @class=container do
                      image {i("icons/icon_component.gif")}

                      child do
                        image {i("icons/icon_component.gif")}
                        label{|c|c.to_s}
                        child "class_variables" do
                          image{i("icons/flag_red.gif")}
                          children(lambda{|c|c.class_variables.sort.collect! { |x|{:class=>c,:name=>x}}}) do
                            image{i("icons/flag_red.gif")}
                            label{|horizontalFill|h[:name]}
                            child do
                              image{i("icons/arrow_right.gif")}
                              label{|horizontalFill|h[:class].class_eval h[:name]}
                            end
                          end
                        end
                        link{@object}
                      end

                      # superclass node if appropriate
                      conditional lambda{|c|c.superclass}do
                        child "superclass" do
                          image {i("icons/icon_component.gif")}
                          object{|c|c.superclass}
                          link{@class}
                        end
                      end
                    end
                  end
                end
              end
            end
          end
        end
      end
    end
  end
end
