#!/usr/bin/env ruby # -*- ruby -*- # Copyright 2000, 2001 by Jim Weirich (jweirich@one.net). # All rights reserved. # Permission is granted for use, copying, modification, distribution, # and distribution of modified versions of this work as long as the # above copyright notice is included. require 'gem/utils' require 'gem/whenmissing' require 'observer' require 'tk' ###################################################################### # Namespace for GemFinder classes. # module Gem #################################################################### # Model for supporting lists of classes. # class ListModel include Observable include GemUtils attr_reader :source, :items, :selection_index attr_accessor :selection_monitor def initialize @source = "" @items = [] @selection_index = -1 @selection_monitor = nil end def fill_from (klass) @source = klass.to_s update_items @selection_index = -1 notify end def select (index) @selection_index = index do_select(index) end def use_class_model (cm) @class_model = cm @class_model.add_observer(self) end def update if @class_model.selection && @class_model.selection != "" then fill_from (@class_model.selection) end end def notify changed notify_observers end private def do_select (index) @selection_monitor.select_name(@items[index].to_s) if @selection_monitor end end #################################################################### class ClassListModel < ListModel attr_reader :selection attr_accessor :include_system # Regular expression matching classes to omit from class lists Class_reject_filter = /^(Errno::.*|fatal)$/ def initialize super @include_system = true @selection = "" end def select_name (name) index = @items.index(name).when_missing { @items.index(name + " (M)") } select(index) if index end def include_system= (value) @include_system = value fill_from ("") notify end private # -------------------------------------------------------- def do_select (index) return unless (Integer === index) @selection = @items[index].dup @selection.sub!(/ \(M\)/, "") notify end def update_items if @include_system then @items = classes else @items = remove_system_classes(classes) end @items.sort! end def classes items = [] ObjectSpace.each_object(Module) { |n| if n.to_s !~ Class_reject_filter then items << (n.to_s + ((Class === n) ? "" : " (M)")) end } items end def remove_system_classes(class_list) class_list.reject { |m| name = (m =~ /^(\w+)/) ? $1 : m @@system_names[name] } end # Class attributes and methods ------------------------------------- @@system_names = {} def ClassListModel.record_system_modules system_modules = [] ObjectSpace.each_object (Module) { |m| system_modules << m } system_modules << TkVirtualEvent system_modules.each { |m| @@system_names[m.to_s] = true } end end #################################################################### class MethodListModel < ListModel def initialize (finder) super() @finder = finder end private def update_items @items = @finder.methods(@source) end end #################################################################### class ModuleListModel < ListModel private def update_items @items = class_for(@source).included_modules.sort end end #################################################################### class ChildListModel < ListModel private def update_items classes = [] ObjectSpace.each_object(Class) { |c| classes << c } parent = class_for(@source) @items = classes.select { |c| child_of?(parent, c) } @items.sort! {|a,b| a.to_s <=> b.to_s} end def child_of? (parent, candidate_child) return (candidate_child.superclass == parent or candidate_child.included_modules.member?(parent)) end end #################################################################### class ClassBrowserModel attr_reader :class_model, :child_model, :module_model, :method_model def initialize (finder) @class_model = ClassListModel.new @child_model = ChildListModel.new @module_model = ModuleListModel.new @method_model = MethodListModel.new (finder) @method_model.use_class_model(class_model) @child_model.use_class_model(class_model) @module_model.use_class_model(class_model) @child_model.selection_monitor = @class_model @module_model.selection_monitor = @class_model end def fill @class_model.fill_from ("") end end end # end of GEM module