extract_curves 0.0.1-i586-linux
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CVS/Entries +4 -0
- data/CVS/Repository +1 -0
- data/CVS/Root +1 -0
- data/bin/CVS/Entries +5 -0
- data/bin/CVS/Repository +1 -0
- data/bin/CVS/Root +1 -0
- data/bin/ec_rect2polar.rb +22 -0
- data/bin/ec_rev_lines.rb +5 -0
- data/bin/ec_sph_area.rb +30 -0
- data/bin/extract_curves.rb +2145 -0
- data/ruby_ext/CVS/Entries +1 -0
- data/ruby_ext/CVS/Repository +1 -0
- data/ruby_ext/CVS/Root +1 -0
- data/ruby_ext/pav/CVS/Entries +14 -0
- data/ruby_ext/pav/CVS/Repository +1 -0
- data/ruby_ext/pav/CVS/Root +1 -0
- data/ruby_ext/pav/extconf.rb +22 -0
- data/ruby_ext/pav/pav.so +0 -0
- data/ruby_libs/CVS/Entries +1 -0
- data/ruby_libs/CVS/Repository +1 -0
- data/ruby_libs/CVS/Root +1 -0
- data/ruby_libs/pav/CVS/Entries +20 -0
- data/ruby_libs/pav/CVS/Repository +1 -0
- data/ruby_libs/pav/CVS/Root +1 -0
- data/ruby_libs/pav/attr_cache.rb +211 -0
- data/ruby_libs/pav/attr_cache.t1.rb +32 -0
- data/ruby_libs/pav/cache.rb +31 -0
- data/ruby_libs/pav/dbg_log.rb +458 -0
- data/ruby_libs/pav/floatsio.rb +53 -0
- data/ruby_libs/pav/generator_cache.rb +165 -0
- data/ruby_libs/pav/gtk/CVS/Entries +4 -0
- data/ruby_libs/pav/gtk/CVS/Repository +1 -0
- data/ruby_libs/pav/gtk/CVS/Root +1 -0
- data/ruby_libs/pav/gtk/button.rb +130 -0
- data/ruby_libs/pav/gtk/icons.rb +87 -0
- data/ruby_libs/pav/gtk/toolbar.rb +192 -0
- data/ruby_libs/pav/heap.rb +54 -0
- data/ruby_libs/pav/icons/CVS/Entries +17 -0
- data/ruby_libs/pav/icons/CVS/Repository +1 -0
- data/ruby_libs/pav/icons/CVS/Root +1 -0
- data/ruby_libs/pav/icons/alt_handle.xpm +3832 -0
- data/ruby_libs/pav/icons/alt_handle_hover.xpm +3368 -0
- data/ruby_libs/pav/icons/alt_handle_pressed.xpm +3828 -0
- data/ruby_libs/pav/icons/extract_curves/CVS/Entries +6 -0
- data/ruby_libs/pav/icons/extract_curves/CVS/Repository +1 -0
- data/ruby_libs/pav/icons/extract_curves/CVS/Root +1 -0
- data/ruby_libs/pav/icons/extract_curves/extract_curves-icon-rgb.ppm +14 -0
- data/ruby_libs/pav/icons/extract_curves/extract_curves-logo-rgb.gif +0 -0
- data/ruby_libs/pav/icons/extract_curves/trace_mark.xpm +38 -0
- data/ruby_libs/pav/icons/handle.xpm +213 -0
- data/ruby_libs/pav/icons/next.xpm +29 -0
- data/ruby_libs/pav/icons/next_hover.xpm +315 -0
- data/ruby_libs/pav/icons/next_pressed.xpm +144 -0
- data/ruby_libs/pav/icons/prev.xpm +29 -0
- data/ruby_libs/pav/icons/prev_hover.xpm +315 -0
- data/ruby_libs/pav/icons/prev_pressed.xpm +144 -0
- data/ruby_libs/pav/icons/vnext.xpm +29 -0
- data/ruby_libs/pav/icons/vprev.xpm +29 -0
- data/ruby_libs/pav/numeric/CVS/Entries +2 -0
- data/ruby_libs/pav/numeric/CVS/Repository +1 -0
- data/ruby_libs/pav/numeric/CVS/Root +1 -0
- data/ruby_libs/pav/numeric/ext.rb +13 -0
- data/ruby_libs/pav/pav_find.rb +90 -0
- data/ruby_libs/pav/pix/CVS/Entries +11 -0
- data/ruby_libs/pav/pix/CVS/Repository +1 -0
- data/ruby_libs/pav/pix/CVS/Root +1 -0
- data/ruby_libs/pav/pix/aapix.rb +378 -0
- data/ruby_libs/pav/pix/blob.rb +543 -0
- data/ruby_libs/pav/pix/circle.rb +73 -0
- data/ruby_libs/pav/pix/contour/CVS/Entries +5 -0
- data/ruby_libs/pav/pix/contour/CVS/Repository +1 -0
- data/ruby_libs/pav/pix/contour/CVS/Root +1 -0
- data/ruby_libs/pav/pix/contour/calc_situations.rb +9 -0
- data/ruby_libs/pav/pix/contour/carp_calc.rb +212 -0
- data/ruby_libs/pav/pix/contour/situations.dmp +0 -0
- data/ruby_libs/pav/pix/contour/situations.rb +21 -0
- data/ruby_libs/pav/pix/contour.rb +644 -0
- data/ruby_libs/pav/pix/curve.rb +1508 -0
- data/ruby_libs/pav/pix/img_obj.rb +751 -0
- data/ruby_libs/pav/pix/node.rb +712 -0
- data/ruby_libs/pav/pix/node_grp.rb +853 -0
- data/ruby_libs/pav/pix/shaved_core.rb +534 -0
- data/ruby_libs/pav/pix/subpix.rb +212 -0
- data/ruby_libs/pav/pix.rb +402 -0
- data/ruby_libs/pav/rand_accessible.rb +16 -0
- data/ruby_libs/pav/rangeset.rb +63 -0
- data/ruby_libs/pav/search.rb +210 -0
- data/ruby_libs/pav/set.rb +20 -0
- data/ruby_libs/pav/string/CVS/Entries +6 -0
- data/ruby_libs/pav/string/CVS/Repository +1 -0
- data/ruby_libs/pav/string/CVS/Root +1 -0
- data/ruby_libs/pav/string/bits.rb +523 -0
- data/ruby_libs/pav/string/ext.rb +58 -0
- data/ruby_libs/pav/string/observable.rb +155 -0
- data/ruby_libs/pav/string/text.rb +79 -0
- data/ruby_libs/pav/string/words.rb +42 -0
- data/ruby_libs/pav/sub_arr.rb +55 -0
- data/ruby_libs/pav/traced_obj.rb +79 -0
- metadata +147 -0
| @@ -0,0 +1,2145 @@ | |
| 1 | 
            +
            #!/usr/bin/ruby
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            require 'gtk2'
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            if str = Gtk.check_version(2, 6, 0)
         | 
| 6 | 
            +
            	puts "This program requires GTK+ 2.6.0 or later"
         | 
| 7 | 
            +
            	puts str
         | 
| 8 | 
            +
            	exit
         | 
| 9 | 
            +
            end
         | 
| 10 | 
            +
             | 
| 11 | 
            +
            require 'thread'
         | 
| 12 | 
            +
            require 'pav/pix'
         | 
| 13 | 
            +
            require 'pav/dbg_log'
         | 
| 14 | 
            +
            require 'pav/floatsio'
         | 
| 15 | 
            +
            require 'pav/pix/blob'
         | 
| 16 | 
            +
            require 'pav/pix/curve'
         | 
| 17 | 
            +
            require 'pav/gtk/icons'
         | 
| 18 | 
            +
            require 'pav/attr_cache'
         | 
| 19 | 
            +
            require 'pav/string/ext'
         | 
| 20 | 
            +
            require 'pav/gtk/toolbar'
         | 
| 21 | 
            +
            require 'pav/pix/contour'
         | 
| 22 | 
            +
            require 'pav/pix/img_obj'
         | 
| 23 | 
            +
            require 'pav/string/words'
         | 
| 24 | 
            +
            require 'pav/pix/shaved_core'
         | 
| 25 | 
            +
             | 
| 26 | 
            +
            Gtk.init
         | 
| 27 | 
            +
             | 
| 28 | 
            +
            module PPix
         | 
| 29 | 
            +
             | 
| 30 | 
            +
            class Blob
         | 
| 31 | 
            +
            	attr_accessor :extract_curves_args
         | 
| 32 | 
            +
            end
         | 
| 33 | 
            +
             | 
| 34 | 
            +
            class Curve
         | 
| 35 | 
            +
            	self.img_obj_add_to_sub_objs :shaved_core
         | 
| 36 | 
            +
            	
         | 
| 37 | 
            +
            	def shaved_core
         | 
| 38 | 
            +
            		ec =self.curve_carpet.blob.extract_curves_args['extract_curves']
         | 
| 39 | 
            +
            		self.c_shaved_core(ec.min_hair_len, ec.min_hair_lp_len)
         | 
| 40 | 
            +
            	end
         | 
| 41 | 
            +
            	
         | 
| 42 | 
            +
            	def delete_shaved_core
         | 
| 43 | 
            +
            		self.c_delete_shaved_core
         | 
| 44 | 
            +
            	end
         | 
| 45 | 
            +
            end
         | 
| 46 | 
            +
             | 
| 47 | 
            +
            end
         | 
| 48 | 
            +
             | 
| 49 | 
            +
            class ECLogProgrBar < PLogProgrBar
         | 
| 50 | 
            +
            	attr_reader :progr_bar, :progr_box, :progr_label
         | 
| 51 | 
            +
            	
         | 
| 52 | 
            +
            	def initialize(dbg_log, progr_bar, progr_label, progr_box)
         | 
| 53 | 
            +
            		super(dbg_log)
         | 
| 54 | 
            +
            		@progr_bar = progr_bar
         | 
| 55 | 
            +
            		@progr_label = progr_label
         | 
| 56 | 
            +
            		@progr_box = progr_box
         | 
| 57 | 
            +
            		@progr_label.text = ""
         | 
| 58 | 
            +
            		@progr_bar.orientation = @progr_bar_orientation = 0
         | 
| 59 | 
            +
            		@progr_bar.fraction = 0.0
         | 
| 60 | 
            +
            		@progr_bar.show_text = false
         | 
| 61 | 
            +
            		@progr_box.pack_start(@progr_bar)
         | 
| 62 | 
            +
            		@progr_box.pack_start(@progr_label, false, false)
         | 
| 63 | 
            +
            		@tot_progr_units = 100.0
         | 
| 64 | 
            +
            		i = -1
         | 
| 65 | 
            +
            		Gtk.main_iteration_do(false) while (i += 1) < 10 &&
         | 
| 66 | 
            +
            			Gtk.events_pending?
         | 
| 67 | 
            +
            	end
         | 
| 68 | 
            +
            	
         | 
| 69 | 
            +
            	def total_progr_units=(val)
         | 
| 70 | 
            +
            		super(val)
         | 
| 71 | 
            +
            		if val
         | 
| 72 | 
            +
            			@progr_bar.show_text = true
         | 
| 73 | 
            +
            		else
         | 
| 74 | 
            +
            			@progr_bar.show_text = false
         | 
| 75 | 
            +
            		end
         | 
| 76 | 
            +
            		i = -1
         | 
| 77 | 
            +
            		Gtk.main_iteration_do(false) while (i += 1) < 10 &&
         | 
| 78 | 
            +
            			Gtk.events_pending?
         | 
| 79 | 
            +
            	end
         | 
| 80 | 
            +
            	
         | 
| 81 | 
            +
            	def disp_progr(progr_units_change)
         | 
| 82 | 
            +
            		if self.total_progr_units
         | 
| 83 | 
            +
            			if self.show_as[0,1] == "%"
         | 
| 84 | 
            +
            				pct =  self.fmt_str % (100.0*self.progr_units /
         | 
| 85 | 
            +
            					self.total_progr_units)
         | 
| 86 | 
            +
            			else
         | 
| 87 | 
            +
            				pct = "#{self.progr_units}/#{
         | 
| 88 | 
            +
            					self.total_progr_units}"
         | 
| 89 | 
            +
            			end
         | 
| 90 | 
            +
            			pct += self.show_as[1, self.show_as.length-1]
         | 
| 91 | 
            +
            			@progr_bar.fraction = Float(self.progr_units) /
         | 
| 92 | 
            +
            				self.total_progr_units
         | 
| 93 | 
            +
            		else
         | 
| 94 | 
            +
            			while self.progr_units > @tot_progr_units
         | 
| 95 | 
            +
            				@tot_progr_units *= 2
         | 
| 96 | 
            +
            				@progr_bar_orientation += 1
         | 
| 97 | 
            +
            			end
         | 
| 98 | 
            +
            			if self.show_as[0,1] == "%"
         | 
| 99 | 
            +
            				pct = ""
         | 
| 100 | 
            +
            			else
         | 
| 101 | 
            +
            				pct = "#{self.progr_units}" +
         | 
| 102 | 
            +
            					self.show_as[1,self.show_as.length-1]
         | 
| 103 | 
            +
            			end
         | 
| 104 | 
            +
            			@progr_bar.fraction = Float(self.progr_units) /
         | 
| 105 | 
            +
            				@tot_progr_units
         | 
| 106 | 
            +
            			@progr_bar.orientation = @progr_bar_orientation %= 2
         | 
| 107 | 
            +
            		end
         | 
| 108 | 
            +
            		@progr_label.text = pct
         | 
| 109 | 
            +
            		i = -1
         | 
| 110 | 
            +
            		Gtk.main_iteration_do(false) while (i += 1) < 10 &&
         | 
| 111 | 
            +
            			Gtk.events_pending?
         | 
| 112 | 
            +
            	end
         | 
| 113 | 
            +
            	
         | 
| 114 | 
            +
            	def finish
         | 
| 115 | 
            +
            		super
         | 
| 116 | 
            +
            		@progr_box.remove(@progr_label)
         | 
| 117 | 
            +
            		@progr_box.remove(@progr_bar)
         | 
| 118 | 
            +
            		i = -1
         | 
| 119 | 
            +
            		Gtk.main_iteration_do(false) while (i += 1) < 10 &&
         | 
| 120 | 
            +
            			Gtk.events_pending?
         | 
| 121 | 
            +
            	end
         | 
| 122 | 
            +
            end
         | 
| 123 | 
            +
             | 
| 124 | 
            +
            class StatusbarIO < IO
         | 
| 125 | 
            +
            	attr_reader :dbg_log, :statusbar, :tee_to, :last_ln
         | 
| 126 | 
            +
            	
         | 
| 127 | 
            +
            	def initialize(dbg_log, statusbar, tee_to=nil)
         | 
| 128 | 
            +
            		@dbg_log = dbg_log
         | 
| 129 | 
            +
            		@statusbar = statusbar
         | 
| 130 | 
            +
            		@tee_to = tee_to
         | 
| 131 | 
            +
            		@last_ln = ""
         | 
| 132 | 
            +
            	end
         | 
| 133 | 
            +
            	
         | 
| 134 | 
            +
            	def print_to_statusbar(str)
         | 
| 135 | 
            +
            		(@last_ln + str).each_line { |ln| @last_ln = ln }
         | 
| 136 | 
            +
            		@last_ln.eval_backspace!(@dbg_log.backspc)
         | 
| 137 | 
            +
            		@statusbar.pop(0)
         | 
| 138 | 
            +
            		@statusbar.push(0, @last_ln.chomp)
         | 
| 139 | 
            +
            		i = -1
         | 
| 140 | 
            +
            		Gtk.main_iteration_do(false) while (i += 1) < 10 &&
         | 
| 141 | 
            +
            			Gtk.events_pending?
         | 
| 142 | 
            +
            	end
         | 
| 143 | 
            +
            	
         | 
| 144 | 
            +
            	def print(str)
         | 
| 145 | 
            +
            		@tee_to.print(str) if @tee_to
         | 
| 146 | 
            +
            		self.print_to_statusbar(str)
         | 
| 147 | 
            +
            	end
         | 
| 148 | 
            +
            	
         | 
| 149 | 
            +
            	def puts(str)
         | 
| 150 | 
            +
            		@tee_to.puts(str) if @tee_to
         | 
| 151 | 
            +
            		self.print_to_statusbar(str)
         | 
| 152 | 
            +
            	end
         | 
| 153 | 
            +
            	
         | 
| 154 | 
            +
            	def tty?
         | 
| 155 | 
            +
            		if @tee_to
         | 
| 156 | 
            +
            			@tee_to.tty?
         | 
| 157 | 
            +
            		else
         | 
| 158 | 
            +
            			true
         | 
| 159 | 
            +
            		end
         | 
| 160 | 
            +
            	end
         | 
| 161 | 
            +
            end
         | 
| 162 | 
            +
             | 
| 163 | 
            +
            class ExtractCurvesApp < Gtk::Window
         | 
| 164 | 
            +
            	VERSION = [0, 0, 1]
         | 
| 165 | 
            +
            	VERSION_SUFFIX = "-beta"
         | 
| 166 | 
            +
            	MARK_WAYS = ["mark", "blink", "trace"]
         | 
| 167 | 
            +
            	
         | 
| 168 | 
            +
            	attr_reader :min_hair_len, :min_hair_lp_len
         | 
| 169 | 
            +
            	
         | 
| 170 | 
            +
            	def initialize
         | 
| 171 | 
            +
            		@job = nil
         | 
| 172 | 
            +
            		@in_progr = Mutex.new
         | 
| 173 | 
            +
            		@pixbuf = nil
         | 
| 174 | 
            +
            		@pixbuf_backing = @pixbuf_marked = @pixbuf_blinking = nil
         | 
| 175 | 
            +
            		@pixbuf_marked_objs = []
         | 
| 176 | 
            +
            		@pixbuf_blinking_objs = []
         | 
| 177 | 
            +
            		@pixbuf_traced_objs = []
         | 
| 178 | 
            +
            		@pixbuf_traced_obj_i = @pixbuf_traced_pix_i = 0
         | 
| 179 | 
            +
            		@blink_area = @blink_area_rect = nil
         | 
| 180 | 
            +
            		@drw_area_in_procs = false
         | 
| 181 | 
            +
            		@blob = nil
         | 
| 182 | 
            +
            		@external_contours = true
         | 
| 183 | 
            +
            		@min_hair_len = 10
         | 
| 184 | 
            +
            		@min_hair_lp_len = 10
         | 
| 185 | 
            +
            		@min_subblob_size = 1
         | 
| 186 | 
            +
            		@min_outer_lp_length = 0
         | 
| 187 | 
            +
            		@mark_blob = {""=>"blink"}
         | 
| 188 | 
            +
            		@pixels_mark_proc = proc { |pix| self.pixels_mark(pix) }
         | 
| 189 | 
            +
            		@pixels_unmark_proc = proc { |pix| self.pixels_unmark(pix) }
         | 
| 190 | 
            +
            		@fuzzy_clr_r = @fuzzy_clr_g = @fuzzy_clr_b = 10
         | 
| 191 | 
            +
            		@fuzzy_clr_h = @fuzzy_clr_s = @fuzzy_clr_v = 0.0
         | 
| 192 | 
            +
            		@clr_match_scheme = "rgb"
         | 
| 193 | 
            +
            		@clr_show_scheme = "rgb"
         | 
| 194 | 
            +
            		@pix_trace_tm_out = 100
         | 
| 195 | 
            +
            		@contour_geometry = 8
         | 
| 196 | 
            +
            		@ctxt_menu_m_cb = self.method("ctxt_menu_m_cb").to_proc
         | 
| 197 | 
            +
            		@ctxt_menu_d_cb = self.method("ctxt_menu_d_cb").to_proc
         | 
| 198 | 
            +
            		@ctxt_menu_s_cb = self.method("ctxt_menu_s_cb").to_proc
         | 
| 199 | 
            +
            		@ctxt_menu_e_cb = self.method("ctxt_menu_e_cb").to_proc
         | 
| 200 | 
            +
            		super(Gtk::Window::TOPLEVEL)
         | 
| 201 | 
            +
            		self.set_title("Extract Curves")
         | 
| 202 | 
            +
            		begin
         | 
| 203 | 
            +
            		  icon = Gdk::Pixbuf.new(PGtk.find_icon_file(
         | 
| 204 | 
            +
            		   'pav/icons/extract_curves/extract_curves-icon-rgb.ppm').to_s)
         | 
| 205 | 
            +
            		  self.set_icon(icon)
         | 
| 206 | 
            +
            		rescue IOError, Gdk::PixbufError
         | 
| 207 | 
            +
            		  warn self.class.name + ".initialize: Error: Failed to load " +
         | 
| 208 | 
            +
            		  	"icon:\n" + $!.class.name + ": #{$!}\n\tfrom " +
         | 
| 209 | 
            +
            			$!.backtrace.join("\n\tfrom ")
         | 
| 210 | 
            +
            		end
         | 
| 211 | 
            +
            		@trace_mark = Gdk::Pixbuf.new(PGtk.find_icon_file(
         | 
| 212 | 
            +
            			'pav/icons/extract_curves/trace_mark.xpm'))
         | 
| 213 | 
            +
            		quit_cb = proc { self.destroy; true }
         | 
| 214 | 
            +
            		signal_connect('delete_event', &quit_cb)
         | 
| 215 | 
            +
            		set_default_size(450, 450)
         | 
| 216 | 
            +
            		
         | 
| 217 | 
            +
            		# Root container:
         | 
| 218 | 
            +
            		table = Gtk::Table.new(1, 4, false)
         | 
| 219 | 
            +
            		add(table)
         | 
| 220 | 
            +
            		
         | 
| 221 | 
            +
            		# Menubar:
         | 
| 222 | 
            +
            		accel_group = Gtk::AccelGroup.new
         | 
| 223 | 
            +
            		add_accel_group(accel_group)
         | 
| 224 | 
            +
            		open_cb = self.method("open_cb").to_proc
         | 
| 225 | 
            +
            		load_blob_cb = self.method('load_blob_cb').to_proc
         | 
| 226 | 
            +
            		save_cb = proc { |*args|
         | 
| 227 | 
            +
            			objs = @pixbuf_marked_objs + @pixbuf_blinking_objs +
         | 
| 228 | 
            +
            				@pixbuf_traced_objs
         | 
| 229 | 
            +
            			return if objs.empty?
         | 
| 230 | 
            +
            			self.save_img_obj(*objs)
         | 
| 231 | 
            +
            		}
         | 
| 232 | 
            +
            		cancel_cb = proc { |*args| Thread.kill(@job) if @job }
         | 
| 233 | 
            +
            		ctxt_cb = proc { |*args| self.img_pop_context_menu  }
         | 
| 234 | 
            +
            		del_cb = proc { |*args| return unless @blob
         | 
| 235 | 
            +
            			self.img_exit_blob
         | 
| 236 | 
            +
            			@pixbuf.delete_blob(@blob)
         | 
| 237 | 
            +
            			self.del_blob
         | 
| 238 | 
            +
            			@blob = nil
         | 
| 239 | 
            +
            		}
         | 
| 240 | 
            +
            		zoom_100_cb = proc { |widget, event|
         | 
| 241 | 
            +
            			win, x, y, state = @drw_area.window.pointer
         | 
| 242 | 
            +
            			width = @drw_area.allocation.width
         | 
| 243 | 
            +
            			height = @drw_area.allocation.height
         | 
| 244 | 
            +
            			if x >= 0 && x < width && y >= 0 && y < height
         | 
| 245 | 
            +
            				@scrl_win.window.cursor = Gdk::Cursor.new(
         | 
| 246 | 
            +
            					Gdk::Cursor::TARGET)
         | 
| 247 | 
            +
            			end
         | 
| 248 | 
            +
            			self.drw_area_in_procs = true
         | 
| 249 | 
            +
            			@spinbtn_x.value = 1
         | 
| 250 | 
            +
            			@spinbtn_y.value = 1
         | 
| 251 | 
            +
            			self.drw_area_in_procs = false
         | 
| 252 | 
            +
            			@scrl_win.window.cursor = nil }
         | 
| 253 | 
            +
            		zoom_fit_cb = proc { |widget, event|
         | 
| 254 | 
            +
            		  if @pixbuf
         | 
| 255 | 
            +
            			win, x, y, state = @drw_area.window.pointer
         | 
| 256 | 
            +
            			width = @drw_area.allocation.width
         | 
| 257 | 
            +
            			height = @drw_area.allocation.height
         | 
| 258 | 
            +
            			if x >= 0 && x < width && y >= 0 && y < height
         | 
| 259 | 
            +
            				@scrl_win.window.cursor = Gdk::Cursor.new(
         | 
| 260 | 
            +
            					Gdk::Cursor::TARGET)
         | 
| 261 | 
            +
            			end
         | 
| 262 | 
            +
            			self.drw_area_in_procs = true
         | 
| 263 | 
            +
            			k = [Float(@scrl_win.allocation.width-10)/@pixbuf.width,
         | 
| 264 | 
            +
            			  Float(@scrl_win.allocation.height-10)/@pixbuf.height].
         | 
| 265 | 
            +
            			  min
         | 
| 266 | 
            +
            			@spinbtn_x.value = k
         | 
| 267 | 
            +
            			@spinbtn_y.value = k
         | 
| 268 | 
            +
            			self.drw_area_in_procs = false
         | 
| 269 | 
            +
            			@scrl_win.window.cursor = nil
         | 
| 270 | 
            +
            		  end
         | 
| 271 | 
            +
            		}
         | 
| 272 | 
            +
            		zoom_in_cb = proc { |widget, event|
         | 
| 273 | 
            +
            			win, x, y, state = @drw_area.window.pointer
         | 
| 274 | 
            +
            			width = @drw_area.allocation.width
         | 
| 275 | 
            +
            			height = @drw_area.allocation.height
         | 
| 276 | 
            +
            			if x >= 0 && x < width && y >= 0 && y < height
         | 
| 277 | 
            +
            				@scrl_win.window.cursor = Gdk::Cursor.new(
         | 
| 278 | 
            +
            					Gdk::Cursor::TARGET)
         | 
| 279 | 
            +
            			end
         | 
| 280 | 
            +
            			self.drw_area_in_procs = true
         | 
| 281 | 
            +
            			@spinbtn_x.value = @kx*1.5
         | 
| 282 | 
            +
            			@spinbtn_y.value = @ky*1.5
         | 
| 283 | 
            +
            			self.drw_area_in_procs = false
         | 
| 284 | 
            +
            			@scrl_win.window.cursor = nil }
         | 
| 285 | 
            +
            		zoom_out_cb = proc { |wgt, ev|
         | 
| 286 | 
            +
            			win, x, y, state = @drw_area.window.pointer
         | 
| 287 | 
            +
            			width = @drw_area.allocation.width
         | 
| 288 | 
            +
            			height = @drw_area.allocation.height
         | 
| 289 | 
            +
            			if x >= 0 && x < width && y >= 0 && y < height
         | 
| 290 | 
            +
            				@scrl_win.window.cursor = Gdk::Cursor.new(
         | 
| 291 | 
            +
            					Gdk::Cursor::TARGET)
         | 
| 292 | 
            +
            			end
         | 
| 293 | 
            +
            			self.drw_area_in_procs = true
         | 
| 294 | 
            +
            			@spinbtn_x.value = @kx/1.5
         | 
| 295 | 
            +
            			@spinbtn_y.value = @ky/1.5
         | 
| 296 | 
            +
            			self.drw_area_in_procs = false
         | 
| 297 | 
            +
            			@scrl_win.window.cursor = nil }
         | 
| 298 | 
            +
            		item_factory = Gtk::ItemFactory.new(
         | 
| 299 | 
            +
            			Gtk::ItemFactory::TYPE_MENU_BAR, '<main>', accel_group)
         | 
| 300 | 
            +
            		item_factory.create_items([
         | 
| 301 | 
            +
            			["/_File"],
         | 
| 302 | 
            +
            			["/File/_Open ...",  "<StockItem>", "<control>O",
         | 
| 303 | 
            +
            			 Gtk::Stock::OPEN, open_cb],
         | 
| 304 | 
            +
            			["/File/_Load blob ...", "<StockItem>", "<control>L",
         | 
| 305 | 
            +
            			 Gtk::Stock::OPEN, load_blob_cb],
         | 
| 306 | 
            +
            			["/File/_Save ...",  "<StockItem>", "<control>S",
         | 
| 307 | 
            +
            			 Gtk::Stock::SAVE, save_cb],
         | 
| 308 | 
            +
            			["/File/sep1",   "<Separator>", nil, nil],
         | 
| 309 | 
            +
            			["/File/_Quit",  "<StockItem>", "<control>Q",
         | 
| 310 | 
            +
            			 Gtk::Stock::QUIT, quit_cb],
         | 
| 311 | 
            +
            			["/_Edit"],
         | 
| 312 | 
            +
            			["/Edit/_Select blob"],
         | 
| 313 | 
            +
            			["/Edit/_Delete blob", "<StockItem>", "KP_Delete", 
         | 
| 314 | 
            +
            			 Gtk::Stock::DELETE, del_cb],
         | 
| 315 | 
            +
            			["/Edit/Cont_ext menu ...", "<Item>", "<control>E",
         | 
| 316 | 
            +
            			 nil, ctxt_cb],
         | 
| 317 | 
            +
            			["/_View"],
         | 
| 318 | 
            +
            			["/View/_Center selection", "<StockItem>", "c",
         | 
| 319 | 
            +
            			 Gtk::Stock::FIND,
         | 
| 320 | 
            +
            			 self.method('center_selection_cb').to_proc],
         | 
| 321 | 
            +
            			["/View/Center _marked", "<StockItem>", "<control>M",
         | 
| 322 | 
            +
            			 Gtk::Stock::FIND,self.method('center_objs_cb').to_proc,
         | 
| 323 | 
            +
            			 @pixbuf_marked_objs],
         | 
| 324 | 
            +
            			["/View/Center _blinking", "<StockItem>", "<control>B",
         | 
| 325 | 
            +
            			 Gtk::Stock::FIND,self.method('center_objs_cb').to_proc,
         | 
| 326 | 
            +
            			 @pixbuf_blinking_objs],
         | 
| 327 | 
            +
            			["/View/Center _traced", "<StockItem>", "<control>T",
         | 
| 328 | 
            +
            			 Gtk::Stock::FIND,self.method('center_objs_cb').to_proc,
         | 
| 329 | 
            +
            			 @pixbuf_traced_objs],
         | 
| 330 | 
            +
            			["/View/Zoom _100", "<StockItem>", "equal",
         | 
| 331 | 
            +
            			 Gtk::Stock::ZOOM_100, zoom_100_cb],
         | 
| 332 | 
            +
            			["/View/Zoom _fit", "<StockItem>", "asterisk",
         | 
| 333 | 
            +
            			 Gtk::Stock::ZOOM_FIT, zoom_fit_cb],
         | 
| 334 | 
            +
            			["/View/Zoom _in", "<StockItem>", "plus",
         | 
| 335 | 
            +
            			 Gtk::Stock::ZOOM_IN, zoom_in_cb],
         | 
| 336 | 
            +
            			["/View/Zoom _out", "<StockItem>", "minus",
         | 
| 337 | 
            +
            			 Gtk::Stock::ZOOM_OUT, zoom_out_cb],
         | 
| 338 | 
            +
            			["/_Help"],
         | 
| 339 | 
            +
            			["/Help/_About",  "<StockItem>", nil, Gtk::Stock::ABOUT,
         | 
| 340 | 
            +
            			                   self.method("about_cb").to_proc],
         | 
| 341 | 
            +
            		])
         | 
| 342 | 
            +
            		@select_blob_menu_branch = item_factory.get_widget(
         | 
| 343 | 
            +
            			'<main>/Edit').children.first
         | 
| 344 | 
            +
            		table.attach(item_factory.get_widget('<main>'),
         | 
| 345 | 
            +
            			# X direction            # Y direction
         | 
| 346 | 
            +
            			0, 1,                    0, 1,
         | 
| 347 | 
            +
            			Gtk::EXPAND | Gtk::FILL, 0,
         | 
| 348 | 
            +
            			0,                       0)
         | 
| 349 | 
            +
            		
         | 
| 350 | 
            +
            		# Toolbars:
         | 
| 351 | 
            +
            		tooltips = Gtk::Tooltips.new
         | 
| 352 | 
            +
            		tb_box = Gtk::HBox.new(false, 3)
         | 
| 353 | 
            +
            		toolbar = PGtk::Toolbar.new
         | 
| 354 | 
            +
            		toolbar.append(Gtk::Stock::OPEN,
         | 
| 355 | 
            +
            			"Open image file for curve recognition (^O)", &open_cb)
         | 
| 356 | 
            +
            		toolbar.append(Gtk::Stock::SAVE,
         | 
| 357 | 
            +
            		  "Save all marked, blinking and traced image objects to a " +
         | 
| 358 | 
            +
            			"file (^S)",
         | 
| 359 | 
            +
            		  &save_cb)
         | 
| 360 | 
            +
            		#toolbar.append(Gtk::Stock::CANCEL,
         | 
| 361 | 
            +
            		#  "Cancel the last started operation (^C)", &cancel_cb)
         | 
| 362 | 
            +
            		toolbar.append_space
         | 
| 363 | 
            +
            		toolbar.append(Gtk::Stock::QUIT, "Quit program (^Q)", &quit_cb)
         | 
| 364 | 
            +
            		tb_box.pack_start(toolbar, false, false)
         | 
| 365 | 
            +
            		# Options toolbar:
         | 
| 366 | 
            +
            		subtb = PGtk::Toolbar.new
         | 
| 367 | 
            +
            		subtb.dir_size_request = 400
         | 
| 368 | 
            +
            		tb_box.pack_start(subtb, true, true)
         | 
| 369 | 
            +
            		# Trace delay:
         | 
| 370 | 
            +
            		vbox = Gtk::VBox.new(true, 1)
         | 
| 371 | 
            +
            		subtb.append(vbox, "Time in miliseconds between the display " +
         | 
| 372 | 
            +
            			"of two subsequent pixels in an image object when " +
         | 
| 373 | 
            +
            			"tracing.", nil)
         | 
| 374 | 
            +
            		label = Gtk::Label.new("Trace delay:")
         | 
| 375 | 
            +
            		vbox.pack_start(label, false, false)
         | 
| 376 | 
            +
            		@trace_delay_adj = Gtk::Adjustment.new(@pix_trace_tm_out, 10.0,
         | 
| 377 | 
            +
            			100000.0, 1.0, 50.0, 50.0)
         | 
| 378 | 
            +
            		@trace_delay_spinbtn = Gtk::SpinButton.new(@trace_delay_adj,0,0)
         | 
| 379 | 
            +
            		tooltips.set_tip(@trace_delay_spinbtn, "Time in miliseconds " +
         | 
| 380 | 
            +
            			"spent by the tracing pixel at a given pixel position "+
         | 
| 381 | 
            +
            			"before moving to the next one when tracing an image " +
         | 
| 382 | 
            +
            			"object.", nil)
         | 
| 383 | 
            +
            		@trace_delay_adj.signal_connect("value_changed") { |wgt, ev|
         | 
| 384 | 
            +
            			self.pix_trace_tm_out=@trace_delay_spinbtn.value }
         | 
| 385 | 
            +
            		vbox.pack_start(@trace_delay_spinbtn, false, false)
         | 
| 386 | 
            +
            		# Compare pixel color to:
         | 
| 387 | 
            +
            		cmp_pix_clr_to_cb = proc { |data, wgt|
         | 
| 388 | 
            +
            			@cmp_pix_to = Gtk::ItemFactory.path_from_widget(wgt)
         | 
| 389 | 
            +
            			@cmp_pix_to[0, '<cmp_to>/'.length] = ''
         | 
| 390 | 
            +
            			if @cmp_pix_to == 'Blob mean color in circle; R='
         | 
| 391 | 
            +
            				@cmp_pix_hbox.pack_start(
         | 
| 392 | 
            +
            					@pix_cmp_circ_r_spinbtn)
         | 
| 393 | 
            +
            			else
         | 
| 394 | 
            +
            				@cmp_pix_hbox.remove(@pix_cmp_circ_r_spinbtn)
         | 
| 395 | 
            +
            			end
         | 
| 396 | 
            +
            		}
         | 
| 397 | 
            +
            		vbox = Gtk::VBox.new(true, 1)
         | 
| 398 | 
            +
            		subtb.append_space
         | 
| 399 | 
            +
            		subtb.append(vbox)
         | 
| 400 | 
            +
            		label = Gtk::Label.new("Compare matched pixel's color to:")
         | 
| 401 | 
            +
            		vbox.pack_start(label, true, true, 0)
         | 
| 402 | 
            +
            		@cmp_pix_hbox = Gtk::HBox.new(false, 0)
         | 
| 403 | 
            +
            		vbox.pack_start(@cmp_pix_hbox, true, true, 0)
         | 
| 404 | 
            +
            		optmenu = Gtk::OptionMenu.new
         | 
| 405 | 
            +
            		item_factory = Gtk::ItemFactory.new(Gtk::ItemFactory::TYPE_MENU,
         | 
| 406 | 
            +
            			'<cmp_to>', accel_group)
         | 
| 407 | 
            +
            		item_factory.create_items([
         | 
| 408 | 
            +
            			['/'+(@cmp_pix_to="Blob 8 neighbors' colors"), "<Item>",
         | 
| 409 | 
            +
            				nil, nil, cmp_pix_clr_to_cb],
         | 
| 410 | 
            +
            			["/Blob 4 neighbors' colors", "<Item>", nil, nil,
         | 
| 411 | 
            +
            				cmp_pix_clr_to_cb],
         | 
| 412 | 
            +
            			["/Blob mean color", "<Item>", nil, nil,
         | 
| 413 | 
            +
            				cmp_pix_clr_to_cb],
         | 
| 414 | 
            +
            			["/Blob mean color in circle; R=", "<Item>", nil, nil,
         | 
| 415 | 
            +
            				cmp_pix_clr_to_cb],
         | 
| 416 | 
            +
            		])
         | 
| 417 | 
            +
            		optmenu.menu = item_factory.get_widget('<cmp_to>')
         | 
| 418 | 
            +
            		@cmp_pix_hbox.pack_start(optmenu, false, false, 0)
         | 
| 419 | 
            +
            		adj = Gtk::Adjustment.new(1.0,1.0,1e6,1.0,10.0,1.0)
         | 
| 420 | 
            +
            		@pix_cmp_circ_r_spinbtn = Gtk::SpinButton.new(adj, 0, 0)
         | 
| 421 | 
            +
            		@cmp_pix_hbox.pack_start(@pix_cmp_circ_r_spinbtn,false,false,0)
         | 
| 422 | 
            +
            		# Color match tolerance:
         | 
| 423 | 
            +
            		match_clr_scheme_cb = proc { |data, wgt|
         | 
| 424 | 
            +
            			if Gtk::ItemFactory.path_from_widget(wgt).ends_with(
         | 
| 425 | 
            +
            			"RGB")
         | 
| 426 | 
            +
            				return if @clr_match_scheme == "rgb"
         | 
| 427 | 
            +
            				@clr_match_scheme = "rgb"
         | 
| 428 | 
            +
            				@clr_match_vbox.remove(@hsv_item_box)
         | 
| 429 | 
            +
            				@clr_match_vbox.pack_start(@rgb_item_box)
         | 
| 430 | 
            +
            			else
         | 
| 431 | 
            +
            				return if @clr_match_scheme == "hsv"
         | 
| 432 | 
            +
            				@clr_match_scheme = "hsv"
         | 
| 433 | 
            +
            				@clr_match_vbox.remove(@rgb_item_box)
         | 
| 434 | 
            +
            				@clr_match_vbox.pack_start(@hsv_item_box)
         | 
| 435 | 
            +
            			end
         | 
| 436 | 
            +
            		}
         | 
| 437 | 
            +
            		@clr_match_vbox = Gtk::VBox.new(true, 1)
         | 
| 438 | 
            +
            		label = Gtk::Label.new("Color matching tolerance:")
         | 
| 439 | 
            +
            		@clr_match_vbox.pack_start(label)
         | 
| 440 | 
            +
            		optmenu = Gtk::OptionMenu.new
         | 
| 441 | 
            +
            		item_factory = Gtk::ItemFactory.new(Gtk::ItemFactory::TYPE_MENU,
         | 
| 442 | 
            +
            			'<clr_scheme>', accel_group)
         | 
| 443 | 
            +
            		item_factory.create_items([
         | 
| 444 | 
            +
            			["/RGB", "<Item>", nil, nil, match_clr_scheme_cb],
         | 
| 445 | 
            +
            			["/HSV", "<Item>", nil, nil, match_clr_scheme_cb],
         | 
| 446 | 
            +
            		])
         | 
| 447 | 
            +
            		optmenu.menu = item_factory.get_widget('<clr_scheme>')
         | 
| 448 | 
            +
            		subtb.append_space
         | 
| 449 | 
            +
            		subtb.append(optmenu)
         | 
| 450 | 
            +
            		@rgb_item_box = Gtk::HBox.new(true, 2)
         | 
| 451 | 
            +
            		@clr_match_vbox.pack_start(@rgb_item_box, false, false)
         | 
| 452 | 
            +
            		#@clr_match_vbox.attach(@rgb_item_box, 0,1, 1,2, 0, 0, 0, 0)
         | 
| 453 | 
            +
            		subtb.append(@clr_match_vbox, nil, nil)
         | 
| 454 | 
            +
            		# Red:
         | 
| 455 | 
            +
            		hbox = Gtk::HBox.new(false, 1)
         | 
| 456 | 
            +
            		label = Gtk::Label.new("R:"); label.set_alignment(0, 0.5)
         | 
| 457 | 
            +
            		hbox.pack_start(label, false, false)
         | 
| 458 | 
            +
            		@fuzzy_clr_adj_r=Gtk::Adjustment.new(@fuzzy_clr_r, 0.0, 255.0,
         | 
| 459 | 
            +
            			1.0, 10.0, 1.0)
         | 
| 460 | 
            +
            		@fuzzy_clr_spinbtn_r = Gtk::SpinButton.new(@fuzzy_clr_adj_r,0,0)
         | 
| 461 | 
            +
            		tooltips.set_tip(@fuzzy_clr_spinbtn_r, ttip="When identifying "+
         | 
| 462 | 
            +
            			"a blob, match adjacent pixels whose color components "+
         | 
| 463 | 
            +
            			"differ not more than these settings.", nil)
         | 
| 464 | 
            +
            		@fuzzy_clr_adj_r.signal_connect("value_changed") { |wgt, ev|
         | 
| 465 | 
            +
            			@fuzzy_clr_r=@fuzzy_clr_spinbtn_r.value_as_int }
         | 
| 466 | 
            +
            		hbox.pack_start(@fuzzy_clr_spinbtn_r, false, false)
         | 
| 467 | 
            +
            		@rgb_item_box.pack_start(hbox)
         | 
| 468 | 
            +
            		# Green:
         | 
| 469 | 
            +
            		hbox = Gtk::HBox.new(false, 1)
         | 
| 470 | 
            +
            		label = Gtk::Label.new("G:"); label.set_alignment(0, 0.5)
         | 
| 471 | 
            +
            		hbox.pack_start(label, false, false)
         | 
| 472 | 
            +
            		@fuzzy_clr_adj_g=Gtk::Adjustment.new(@fuzzy_clr_g, 0.0, 255.0,
         | 
| 473 | 
            +
            			1.0, 10.0, 1.0)
         | 
| 474 | 
            +
            		@fuzzy_clr_spinbtn_g = Gtk::SpinButton.new(@fuzzy_clr_adj_g,0,0)
         | 
| 475 | 
            +
            		tooltips.set_tip(@fuzzy_clr_spinbtn_g, ttip, nil)
         | 
| 476 | 
            +
            		@fuzzy_clr_adj_g.signal_connect("value_changed") { |wgt, ev|
         | 
| 477 | 
            +
            			@fuzzy_clr_g=@fuzzy_clr_spinbtn_g.value_as_int }
         | 
| 478 | 
            +
            		hbox.pack_start(@fuzzy_clr_spinbtn_g, false, false)
         | 
| 479 | 
            +
            		@rgb_item_box.pack_start(hbox)
         | 
| 480 | 
            +
            		# Blue:
         | 
| 481 | 
            +
            		hbox = Gtk::HBox.new(false, 1)
         | 
| 482 | 
            +
            		label = Gtk::Label.new("B:"); label.set_alignment(0, 0.5)
         | 
| 483 | 
            +
            		hbox.pack_start(label, false, false)
         | 
| 484 | 
            +
            		@fuzzy_clr_adj_b=Gtk::Adjustment.new(@fuzzy_clr_b, 0.0, 255.0,
         | 
| 485 | 
            +
            			1.0, 10.0, 1.0)
         | 
| 486 | 
            +
            		@fuzzy_clr_spinbtn_b = Gtk::SpinButton.new(@fuzzy_clr_adj_b,0,0)
         | 
| 487 | 
            +
            		tooltips.set_tip(@fuzzy_clr_spinbtn_b, ttip, nil)
         | 
| 488 | 
            +
            		@fuzzy_clr_adj_b.signal_connect("value_changed") { |wgt, ev|
         | 
| 489 | 
            +
            			@fuzzy_clr_b=@fuzzy_clr_spinbtn_b.value_as_int }
         | 
| 490 | 
            +
            		hbox.pack_start(@fuzzy_clr_spinbtn_b, false, false)
         | 
| 491 | 
            +
            		@rgb_item_box.pack_start(hbox)
         | 
| 492 | 
            +
            		# Hue:
         | 
| 493 | 
            +
            		@hsv_item_box = Gtk::HBox.new(true, 2)
         | 
| 494 | 
            +
            		hbox = Gtk::HBox.new(false, 1)
         | 
| 495 | 
            +
            		label = Gtk::Label.new("H:"); label.set_alignment(0, 0.5)
         | 
| 496 | 
            +
            		hbox.pack_start(label, false, false)
         | 
| 497 | 
            +
            		@fuzzy_clr_adj_h=Gtk::Adjustment.new(0.0,0.0,360.0,1.0,10.0,1.0)
         | 
| 498 | 
            +
            		@fuzzy_clr_spinbtn_h = Gtk::SpinButton.new(@fuzzy_clr_adj_h,0,0)
         | 
| 499 | 
            +
            		tooltips.set_tip(@fuzzy_clr_spinbtn_h, ttip, nil)
         | 
| 500 | 
            +
            		@fuzzy_clr_adj_h.signal_connect("value_changed") { |wgt, ev|
         | 
| 501 | 
            +
            			@fuzzy_clr_h=@fuzzy_clr_spinbtn_h.value / 360.0 }
         | 
| 502 | 
            +
            		hbox.pack_start(@fuzzy_clr_spinbtn_h, false, false)
         | 
| 503 | 
            +
            		@hsv_item_box.pack_start(hbox)
         | 
| 504 | 
            +
            		# Saturation:
         | 
| 505 | 
            +
            		hbox = Gtk::HBox.new(false, 1)
         | 
| 506 | 
            +
            		label = Gtk::Label.new("S:"); label.set_alignment(0, 0.5)
         | 
| 507 | 
            +
            		hbox.pack_start(label, false, false)
         | 
| 508 | 
            +
            		@fuzzy_clr_adj_s=Gtk::Adjustment.new(0.0,0.0,100.0,1.0,10.0,1.0)
         | 
| 509 | 
            +
            		@fuzzy_clr_spinbtn_s = Gtk::SpinButton.new(@fuzzy_clr_adj_s,0,0)
         | 
| 510 | 
            +
            		tooltips.set_tip(@fuzzy_clr_spinbtn_s, ttip, nil)
         | 
| 511 | 
            +
            		@fuzzy_clr_adj_s.signal_connect("value_changed") { |wgt, ev|
         | 
| 512 | 
            +
            			@fuzzy_clr_s=@fuzzy_clr_spinbtn_s.value / 100.0 }
         | 
| 513 | 
            +
            		hbox.pack_start(@fuzzy_clr_spinbtn_s, false, false)
         | 
| 514 | 
            +
            		@hsv_item_box.pack_start(hbox)
         | 
| 515 | 
            +
            		# Value:
         | 
| 516 | 
            +
            		hbox = Gtk::HBox.new(false, 1)
         | 
| 517 | 
            +
            		label = Gtk::Label.new("V:"); label.set_alignment(0, 0.5)
         | 
| 518 | 
            +
            		hbox.pack_start(label, false, false)
         | 
| 519 | 
            +
            		@fuzzy_clr_adj_v=Gtk::Adjustment.new(0.0,0.0,100.0,1.0,10.0,1.0)
         | 
| 520 | 
            +
            		@fuzzy_clr_spinbtn_v = Gtk::SpinButton.new(@fuzzy_clr_adj_v,0,0)
         | 
| 521 | 
            +
            		tooltips.set_tip(@fuzzy_clr_spinbtn_v, ttip, nil)
         | 
| 522 | 
            +
            		@fuzzy_clr_adj_v.signal_connect("value_changed") { |wgt, ev|
         | 
| 523 | 
            +
            			@fuzzy_clr_v=@fuzzy_clr_spinbtn_v.value / 100.0 }
         | 
| 524 | 
            +
            		hbox.pack_start(@fuzzy_clr_spinbtn_v, false, false)
         | 
| 525 | 
            +
            		@hsv_item_box.pack_start(hbox)
         | 
| 526 | 
            +
            		@clr_match_vbox.pack_start(@hsv_item_box, false, false)
         | 
| 527 | 
            +
            		# Contour geometry:
         | 
| 528 | 
            +
            		ctr_geom_cb = proc { |data, wgt|
         | 
| 529 | 
            +
            			@contour_geometry = Gtk::ItemFactory.path_from_widget(
         | 
| 530 | 
            +
            				wgt)[-1,1].to_i
         | 
| 531 | 
            +
            		}
         | 
| 532 | 
            +
            		optmenu = Gtk::OptionMenu.new
         | 
| 533 | 
            +
            		item_factory = Gtk::ItemFactory.new(Gtk::ItemFactory::TYPE_MENU,
         | 
| 534 | 
            +
            			'<ctr_geom>', accel_group)
         | 
| 535 | 
            +
            		item_factory.create_items([
         | 
| 536 | 
            +
            			["/8", "<Item>", nil, nil, ctr_geom_cb],
         | 
| 537 | 
            +
            			["/4", "<Item>", nil, nil, ctr_geom_cb],
         | 
| 538 | 
            +
            		])
         | 
| 539 | 
            +
            		optmenu.menu = item_factory.get_widget('<ctr_geom>')
         | 
| 540 | 
            +
            		hbox = Gtk::HBox.new(false, 1)
         | 
| 541 | 
            +
            		hbox.pack_start(Gtk::Label.new("Contour\ngeometry:"),true,true)
         | 
| 542 | 
            +
            		hbox.pack_start(optmenu)
         | 
| 543 | 
            +
            		subtb.append_space
         | 
| 544 | 
            +
            		subtb.append(hbox)
         | 
| 545 | 
            +
            		# External contours?
         | 
| 546 | 
            +
            		btn = Gtk::CheckButton.new("E_xternal\ncontours")
         | 
| 547 | 
            +
            		btn.active = @external_contours = true
         | 
| 548 | 
            +
            		subtb.append_space
         | 
| 549 | 
            +
            		subtb.append(btn)
         | 
| 550 | 
            +
            		btn.signal_connect('clicked') { |wgt|
         | 
| 551 | 
            +
            			@external_contours = wgt.active? }
         | 
| 552 | 
            +
            		
         | 
| 553 | 
            +
            		# Min. subblob size, outer lp len, hair length, ...:
         | 
| 554 | 
            +
            		vbox = Gtk::VBox.new(true, 1)
         | 
| 555 | 
            +
            		subtb.append_space
         | 
| 556 | 
            +
            		subtb.append(vbox, nil, nil)
         | 
| 557 | 
            +
            		# Min. subblob size:
         | 
| 558 | 
            +
            		hbox = Gtk::HBox.new(false, 1)
         | 
| 559 | 
            +
            		#vbox.pack_start(hbox, false, false)
         | 
| 560 | 
            +
            		label = Gtk::Label.new("Min. subblob size:")
         | 
| 561 | 
            +
            		label.set_alignment(0.5, 0.5)
         | 
| 562 | 
            +
            		vbox.pack_start(label, false, false)
         | 
| 563 | 
            +
            		vbox.pack_start(hbox, false, false)
         | 
| 564 | 
            +
            		adj = Gtk::Adjustment.new(@min_subblob_size, 1.0, 1e12,
         | 
| 565 | 
            +
            			1.0, 100.0, 0.0)
         | 
| 566 | 
            +
            		@min_subblob_size_spinbtn = Gtk::SpinButton.new(adj, 0, 0)
         | 
| 567 | 
            +
            		@min_subblob_size_spinbtn.set_snap_to_ticks(true)
         | 
| 568 | 
            +
            		tooltips.set_tip(@min_subblob_size_spinbtn, "Blobs surrounded "+
         | 
| 569 | 
            +
            			"by a blob in detection, containing less than these " +
         | 
| 570 | 
            +
            			"many pixels will be incorporated in the surronding " +
         | 
| 571 | 
            +
            			"blob.", nil)
         | 
| 572 | 
            +
            		hbox.pack_start(@min_subblob_size_spinbtn, false, false)
         | 
| 573 | 
            +
            		adj.signal_connect("value_changed") { |wgt, ev|
         | 
| 574 | 
            +
            			@min_subblob_size = @min_subblob_size_spinbtn.value.to_i
         | 
| 575 | 
            +
            		}
         | 
| 576 | 
            +
            		label = Gtk::Label.new("pix"); label.set_alignment(0, 0.5)
         | 
| 577 | 
            +
            		hbox.pack_start(label, false, false)
         | 
| 578 | 
            +
            		# Min. outer loop length:
         | 
| 579 | 
            +
            		vbox = Gtk::VBox.new(true, 1)
         | 
| 580 | 
            +
            		subtb.append_space
         | 
| 581 | 
            +
            		subtb.append(vbox, nil, nil)
         | 
| 582 | 
            +
            		label = Gtk::Label.new("Min. outer loop len.:")
         | 
| 583 | 
            +
            		label.set_alignment(0.5, 0.5)
         | 
| 584 | 
            +
            		vbox.pack_start(label, false, false)
         | 
| 585 | 
            +
            		hbox = Gtk::HBox.new(false, 1)
         | 
| 586 | 
            +
            		vbox.pack_start(hbox, false, false)
         | 
| 587 | 
            +
            		adj = Gtk::Adjustment.new(@min_outer_lp_length, 1.0, 1e12,
         | 
| 588 | 
            +
            			1.0, 100.0, 0.0)
         | 
| 589 | 
            +
            		@min_outer_lp_length_spinbtn = Gtk::SpinButton.new(adj, 0, 0)
         | 
| 590 | 
            +
            		@min_outer_lp_length_spinbtn.set_snap_to_ticks(true)
         | 
| 591 | 
            +
            		tooltips.set_tip(@min_outer_lp_length_spinbtn, "Drop loops " +
         | 
| 592 | 
            +
            			"from a blob's outer contour carpet of length less " +
         | 
| 593 | 
            +
            			"than this one.", nil)
         | 
| 594 | 
            +
            		hbox.pack_start(@min_outer_lp_length_spinbtn, false, false)
         | 
| 595 | 
            +
            		adj.signal_connect("value_changed") { |wgt, ev|
         | 
| 596 | 
            +
            			@min_outer_lp_length =
         | 
| 597 | 
            +
            				@min_outer_lp_length_spinbtn.value.to_i
         | 
| 598 | 
            +
            		}
         | 
| 599 | 
            +
            		label = Gtk::Label.new("pix"); label.set_alignment(0, 0.5)
         | 
| 600 | 
            +
            		hbox.pack_start(label, false, false)
         | 
| 601 | 
            +
            		# Min. hair length:
         | 
| 602 | 
            +
            		vbox = Gtk::VBox.new(true, 1)
         | 
| 603 | 
            +
            		subtb.append_space
         | 
| 604 | 
            +
            		subtb.append(vbox, nil, nil)
         | 
| 605 | 
            +
            		hbox = Gtk::HBox.new(false, 1)
         | 
| 606 | 
            +
            		vbox.pack_start(hbox, true, true)
         | 
| 607 | 
            +
            		label = Gtk::Label.new("Min. hair length:")
         | 
| 608 | 
            +
            		label.set_alignment(0.5, 0.5)
         | 
| 609 | 
            +
            		hbox.pack_start(label, true, true)
         | 
| 610 | 
            +
            		hbox = Gtk::HBox.new(false, 1)
         | 
| 611 | 
            +
            		vbox.pack_start(hbox, false, false)
         | 
| 612 | 
            +
            		adj = Gtk::Adjustment.new(@min_hair_len, 0.0, 1e12,
         | 
| 613 | 
            +
            			1.0, 100.0, 0.0)
         | 
| 614 | 
            +
            		@min_hair_len_spinbtn = Gtk::SpinButton.new(adj, 0, 0)
         | 
| 615 | 
            +
            		@min_hair_len_spinbtn.set_snap_to_ticks(false)
         | 
| 616 | 
            +
            		tooltips.set_tip(@min_hair_len_spinbtn, "Branches of the " +
         | 
| 617 | 
            +
            			"curve of length less than this one will be shaved " +
         | 
| 618 | 
            +
            			"off for curve's shaved core.", nil)
         | 
| 619 | 
            +
            		hbox.pack_start(@min_hair_len_spinbtn, false, false)
         | 
| 620 | 
            +
            		adj.signal_connect("value_changed") { |wgt, ev|
         | 
| 621 | 
            +
            			@min_hair_len = @min_hair_len_spinbtn.value }
         | 
| 622 | 
            +
            		label = Gtk::Label.new("pix")
         | 
| 623 | 
            +
            		label.set_alignment(0, 0.5)
         | 
| 624 | 
            +
            		hbox.pack_start(label, false, false)
         | 
| 625 | 
            +
            		# Min. hair loop length:
         | 
| 626 | 
            +
            		vbox = Gtk::VBox.new(true, 1)
         | 
| 627 | 
            +
            		subtb.append_space
         | 
| 628 | 
            +
            		subtb.append(vbox, nil, nil)
         | 
| 629 | 
            +
            		hbox = Gtk::HBox.new(false, 1)
         | 
| 630 | 
            +
            		vbox.pack_start(hbox, false, false)
         | 
| 631 | 
            +
            		label = Gtk::Label.new("Min. hair loop len.:")
         | 
| 632 | 
            +
            		label.set_alignment(0.5, 0.5)
         | 
| 633 | 
            +
            		hbox.pack_end(label, false, false)
         | 
| 634 | 
            +
            		hbox = Gtk::HBox.new(false, 1)
         | 
| 635 | 
            +
            		vbox.pack_start(hbox, false, false)
         | 
| 636 | 
            +
            		adj = Gtk::Adjustment.new(@min_hair_lp_len, 0.0, 1e12,
         | 
| 637 | 
            +
            			1.0, 100.0, 0.0)
         | 
| 638 | 
            +
            		@min_hair_lp_len_spinbtn = Gtk::SpinButton.new(adj, 0, 0)
         | 
| 639 | 
            +
            		@min_hair_lp_len_spinbtn.set_snap_to_ticks(false)
         | 
| 640 | 
            +
            		tooltips.set_tip(@min_hair_lp_len_spinbtn, "Shortest loops of "+
         | 
| 641 | 
            +
            			"the curve of length less than this one will be " +
         | 
| 642 | 
            +
            			"deloopified for curve's shaved core.", nil)
         | 
| 643 | 
            +
            		hbox.pack_start(@min_hair_lp_len_spinbtn, false, false)
         | 
| 644 | 
            +
            		adj.signal_connect("value_changed") { |wgt, ev|
         | 
| 645 | 
            +
            			@min_hair_lp_len = @min_hair_lp_len_spinbtn.value }
         | 
| 646 | 
            +
            		label = Gtk::Label.new("pix")
         | 
| 647 | 
            +
            		label.set_alignment(0, 0.5)
         | 
| 648 | 
            +
            		hbox.pack_start(label, false, false)
         | 
| 649 | 
            +
            		
         | 
| 650 | 
            +
            		table.attach(tb_box,
         | 
| 651 | 
            +
            			# X direction            # Y direction
         | 
| 652 | 
            +
            			0, 1,                    1, 2,
         | 
| 653 | 
            +
            			Gtk::EXPAND | Gtk::FILL, 0,
         | 
| 654 | 
            +
            			0,                       0)
         | 
| 655 | 
            +
            		
         | 
| 656 | 
            +
            		# Image display frame:
         | 
| 657 | 
            +
            		@scrl_win = Gtk::ScrolledWindow.new
         | 
| 658 | 
            +
            		@scrl_win.set_policy(Gtk::POLICY_AUTOMATIC,
         | 
| 659 | 
            +
            			Gtk::POLICY_AUTOMATIC)
         | 
| 660 | 
            +
            		@scrl_win.shadow_type = Gtk::SHADOW_IN
         | 
| 661 | 
            +
            		table.attach(@scrl_win,
         | 
| 662 | 
            +
            			# X direction            # Y direction
         | 
| 663 | 
            +
            			0, 1,                    2, 3,
         | 
| 664 | 
            +
            			Gtk::EXPAND | Gtk::FILL, Gtk::EXPAND | Gtk::FILL,
         | 
| 665 | 
            +
            			0,                       0)
         | 
| 666 | 
            +
            		self.set_default_size(200, 200)
         | 
| 667 | 
            +
            		@drw_area = Gtk::DrawingArea.new
         | 
| 668 | 
            +
            		@scrl_win.add_with_viewport(@drw_area)
         | 
| 669 | 
            +
            		img_expose_cb = self.method("img_expose_cb").to_proc
         | 
| 670 | 
            +
            		img_motion_notify_cb=self.method("img_motion_notify_cb").to_proc
         | 
| 671 | 
            +
            		img_button_press_cb = self.method("img_button_press_cb").to_proc
         | 
| 672 | 
            +
            		@drw_area.signal_connect('expose_event', &img_expose_cb)
         | 
| 673 | 
            +
            		@drw_area.signal_connect('motion_notify_event',
         | 
| 674 | 
            +
            			&img_motion_notify_cb)
         | 
| 675 | 
            +
            		@drw_area.signal_connect('button_press_event',
         | 
| 676 | 
            +
            			&img_button_press_cb)
         | 
| 677 | 
            +
            		@drw_area.events |=	Gdk::Event::LEAVE_NOTIFY_MASK |
         | 
| 678 | 
            +
            					Gdk::Event::BUTTON_PRESS_MASK |
         | 
| 679 | 
            +
            					Gdk::Event::POINTER_MOTION_MASK |
         | 
| 680 | 
            +
            					Gdk::Event::POINTER_MOTION_HINT_MASK
         | 
| 681 | 
            +
            		@scrl_win.hadjustment.signal_connect('value_changed',
         | 
| 682 | 
            +
            			&img_motion_notify_cb)
         | 
| 683 | 
            +
            		@scrl_win.vadjustment.signal_connect('value_changed',
         | 
| 684 | 
            +
            			&img_motion_notify_cb)
         | 
| 685 | 
            +
            		
         | 
| 686 | 
            +
            		# x, y, kx, ky, statusbar:
         | 
| 687 | 
            +
            		bottom_box = Gtk::VBox.new(false, 3)
         | 
| 688 | 
            +
            		@progr_bar = Gtk::ProgressBar.new
         | 
| 689 | 
            +
            		@progr_label = Gtk::Label.new
         | 
| 690 | 
            +
            		@progr_bar_box = Gtk::HBox.new(false, 0)
         | 
| 691 | 
            +
            		@progr_bar_box.pack_start(@progr_bar)
         | 
| 692 | 
            +
            		@progr_bar_box.pack_start(@progr_label, false, false)
         | 
| 693 | 
            +
            		bottom_box.pack_start(@progr_bar_box)
         | 
| 694 | 
            +
            		hbox = Gtk::HBox.new(false, 3)
         | 
| 695 | 
            +
            		bottom_box.pack_start(hbox)
         | 
| 696 | 
            +
            		table.attach(bottom_box,
         | 
| 697 | 
            +
            			# X direction            # Y direction
         | 
| 698 | 
            +
            			0, 1,                    3, 4,
         | 
| 699 | 
            +
            			Gtk::EXPAND | Gtk::FILL, 0,
         | 
| 700 | 
            +
            			0,                       0)
         | 
| 701 | 
            +
            		
         | 
| 702 | 
            +
            		label = Gtk::Label.new("x="); label.set_alignment(1, 0.5)
         | 
| 703 | 
            +
            		hbox.pack_start(label, false, false)
         | 
| 704 | 
            +
            		@label_x = Gtk::Label.new; @label_x.set_alignment(0,0.5)
         | 
| 705 | 
            +
            		hbox.pack_start(@label_x,false,false)
         | 
| 706 | 
            +
            		label = Gtk::Label.new("y="); label.set_alignment(1, 0.5)
         | 
| 707 | 
            +
            		hbox.pack_start(label, false, false)
         | 
| 708 | 
            +
            		@label_y = Gtk::Label.new; @label_y.set_alignment(0,0.5)
         | 
| 709 | 
            +
            		hbox.pack_start(@label_y, false, false)
         | 
| 710 | 
            +
            		
         | 
| 711 | 
            +
            		# kx:
         | 
| 712 | 
            +
            		label = Gtk::Label.new("kx=")
         | 
| 713 | 
            +
            		label.set_alignment(1, 0.5)
         | 
| 714 | 
            +
            		hbox.pack_start(label, false, false)
         | 
| 715 | 
            +
            		adj = Gtk::Adjustment.new(1.0, 1.0e-10, 1000.0, 1.0, 5.0, 1.0)
         | 
| 716 | 
            +
            		@spinbtn_x = Gtk::SpinButton.new(adj, 0, 3)
         | 
| 717 | 
            +
            		adj.signal_connect("value_changed") { |wgt, ev|
         | 
| 718 | 
            +
            			self.kx=@spinbtn_x.value }
         | 
| 719 | 
            +
            		hbox.pack_start(@spinbtn_x, false, false)
         | 
| 720 | 
            +
            		#@scrl_win.hadjustment.step_increment =
         | 
| 721 | 
            +
            		@kx = 1
         | 
| 722 | 
            +
            		
         | 
| 723 | 
            +
            		# ky:
         | 
| 724 | 
            +
            		label = Gtk::Label.new("ky=")
         | 
| 725 | 
            +
            		label.set_alignment(1, 0.5)
         | 
| 726 | 
            +
            		hbox.pack_start(label, false, false)
         | 
| 727 | 
            +
            		adj = Gtk::Adjustment.new(1.0, 1.0e-10, 1000.0, 1.0, 5.0, 1.0)
         | 
| 728 | 
            +
            		@spinbtn_y = Gtk::SpinButton.new(adj, 0, 3)
         | 
| 729 | 
            +
            		adj.signal_connect("value_changed") { |wgt, ev|
         | 
| 730 | 
            +
            			self.ky=@spinbtn_y.value }
         | 
| 731 | 
            +
            		hbox.pack_start(@spinbtn_y, false, false)
         | 
| 732 | 
            +
            		#@scrl_win.vadjustment.step_increment =
         | 
| 733 | 
            +
            		@ky = 1
         | 
| 734 | 
            +
            		
         | 
| 735 | 
            +
            		# RGB/HSV:
         | 
| 736 | 
            +
            		show_clr_scheme_cb = proc { |data, wgt|
         | 
| 737 | 
            +
            			if Gtk::ItemFactory.path_from_widget(wgt).ends_with(
         | 
| 738 | 
            +
            			"RGB:")
         | 
| 739 | 
            +
            				@clr_show_scheme = "rgb"
         | 
| 740 | 
            +
            			else
         | 
| 741 | 
            +
            				@clr_show_scheme = "hsv"
         | 
| 742 | 
            +
            			end
         | 
| 743 | 
            +
            		}
         | 
| 744 | 
            +
            		optmenu = Gtk::OptionMenu.new
         | 
| 745 | 
            +
            		item_factory = Gtk::ItemFactory.new(Gtk::ItemFactory::TYPE_MENU,
         | 
| 746 | 
            +
            			'<clr_scheme>', accel_group)
         | 
| 747 | 
            +
            		item_factory.create_items([
         | 
| 748 | 
            +
            			["/RGB:","<Item>","<control>R",nil,show_clr_scheme_cb],
         | 
| 749 | 
            +
            			["/HSV:","<Item>","<control>H",nil,show_clr_scheme_cb],
         | 
| 750 | 
            +
            		])
         | 
| 751 | 
            +
            		optmenu.menu = item_factory.get_widget('<clr_scheme>')
         | 
| 752 | 
            +
            		hbox.pack_start(optmenu, false, false)
         | 
| 753 | 
            +
            		@label_clr = Gtk::Label.new
         | 
| 754 | 
            +
            		@label_clr.width_chars = 11
         | 
| 755 | 
            +
            		@label_clr.set_alignment(0, 0.5)
         | 
| 756 | 
            +
            		hbox.pack_start(@label_clr,false,false)
         | 
| 757 | 
            +
            		
         | 
| 758 | 
            +
            		# Statusbar:
         | 
| 759 | 
            +
            		@statusbar = Gtk::Statusbar.new
         | 
| 760 | 
            +
            		hbox.pack_start(@statusbar, true, true)
         | 
| 761 | 
            +
            		
         | 
| 762 | 
            +
            		# Timeout:
         | 
| 763 | 
            +
            		@prev_traced_x = @prev_traced_y = 0
         | 
| 764 | 
            +
            		@pix_trace_proc = proc {
         | 
| 765 | 
            +
            			tx = @prev_traced_x*@kx; ty = @prev_traced_y*@ky
         | 
| 766 | 
            +
            			if @kx >= @trace_mark.width
         | 
| 767 | 
            +
            				tw = @kx.ceil
         | 
| 768 | 
            +
            			else
         | 
| 769 | 
            +
            				tw = @trace_mark.width
         | 
| 770 | 
            +
            				tx = tx + @kx/2.0 - tw/2.0 
         | 
| 771 | 
            +
            			end
         | 
| 772 | 
            +
            			if @ky >= @trace_mark.height
         | 
| 773 | 
            +
            				th = @ky.ceil
         | 
| 774 | 
            +
            			else
         | 
| 775 | 
            +
            				th = @trace_mark.height
         | 
| 776 | 
            +
            				ty = ty + @ky/2.0 - th/2.0 
         | 
| 777 | 
            +
            			end
         | 
| 778 | 
            +
            			@drw_area.window.invalidate(Gdk::Rectangle.new(tx, ty,
         | 
| 779 | 
            +
            				tw+1, th+1), false)
         | 
| 780 | 
            +
            		  	if (obj = @pixbuf_traced_objs[@pixbuf_traced_obj_i])
         | 
| 781 | 
            +
            				if (@pixbuf_traced_pix_i+=1) >= obj.length
         | 
| 782 | 
            +
            					if (@pixbuf_traced_obj_i += 1) >=
         | 
| 783 | 
            +
            					@pixbuf_traced_objs.length
         | 
| 784 | 
            +
            						@pixbuf_traced_obj_i = 0
         | 
| 785 | 
            +
            					end
         | 
| 786 | 
            +
            					@pixbuf_traced_pix_i = 0
         | 
| 787 | 
            +
            				end
         | 
| 788 | 
            +
            			else
         | 
| 789 | 
            +
            				@pixbuf_traced_obj_i = 0
         | 
| 790 | 
            +
            				@pixbuf_traced_pix_i = 0
         | 
| 791 | 
            +
            			end
         | 
| 792 | 
            +
            			if (obj = @pixbuf_traced_objs[@pixbuf_traced_obj_i]) &&
         | 
| 793 | 
            +
            			(pix = obj[@pixbuf_traced_pix_i])
         | 
| 794 | 
            +
            				@prev_traced_x = pix.x + @pixbuf.border_width
         | 
| 795 | 
            +
            				@prev_traced_y = pix.y + @pixbuf.border_width
         | 
| 796 | 
            +
            				tx = @prev_traced_x*@kx; ty = @prev_traced_y*@ky
         | 
| 797 | 
            +
            				if @kx >= @trace_mark.width
         | 
| 798 | 
            +
            					tw = @kx.ceil
         | 
| 799 | 
            +
            				else
         | 
| 800 | 
            +
            					tw = @trace_mark.width
         | 
| 801 | 
            +
            					tx = tx + @kx/2.0 - tw/2.0 
         | 
| 802 | 
            +
            				end
         | 
| 803 | 
            +
            				if @ky >= @trace_mark.height
         | 
| 804 | 
            +
            					th = @ky.ceil
         | 
| 805 | 
            +
            				else
         | 
| 806 | 
            +
            					th = @trace_mark.height
         | 
| 807 | 
            +
            					ty = ty + @ky/2.0 - th/2.0 
         | 
| 808 | 
            +
            				end
         | 
| 809 | 
            +
            				@drw_area.window.invalidate(Gdk::Rectangle.new(
         | 
| 810 | 
            +
            					tx, ty, tw+1, th+1), false)
         | 
| 811 | 
            +
            			end
         | 
| 812 | 
            +
            			true
         | 
| 813 | 
            +
            		}
         | 
| 814 | 
            +
            		self.add_timeouts
         | 
| 815 | 
            +
            		
         | 
| 816 | 
            +
            		signal_connect('destroy'){ self.remove_timeouts; Gtk.main_quit }
         | 
| 817 | 
            +
            		
         | 
| 818 | 
            +
            		self.show_all
         | 
| 819 | 
            +
            		Gtk.main_iteration
         | 
| 820 | 
            +
            		@cmp_pix_hbox.remove(@pix_cmp_circ_r_spinbtn)
         | 
| 821 | 
            +
            		@clr_match_vbox.remove(@hsv_item_box)
         | 
| 822 | 
            +
            		@progr_bar_box.remove(@progr_label)
         | 
| 823 | 
            +
            		@progr_bar_box.remove(@progr_bar)
         | 
| 824 | 
            +
            		subtb.hide
         | 
| 825 | 
            +
            		Gtk.main_iteration
         | 
| 826 | 
            +
            		if $VERBOSE || $DEBUG
         | 
| 827 | 
            +
            			tee_to = $stdout
         | 
| 828 | 
            +
            		else
         | 
| 829 | 
            +
            			tee_to = nil
         | 
| 830 | 
            +
            		end
         | 
| 831 | 
            +
            		#$PDbgLog.outp = StatusbarIO.new($PDbgLog, @statusbar, tee_to)
         | 
| 832 | 
            +
            		$PDbgLog.progr_class = ECLogProgrBar
         | 
| 833 | 
            +
            		$PDbgLog.progr_init_args = [@progr_bar, @progr_label,
         | 
| 834 | 
            +
            			@progr_bar_box]
         | 
| 835 | 
            +
            	end
         | 
| 836 | 
            +
            	
         | 
| 837 | 
            +
            	def add_timeouts
         | 
| 838 | 
            +
            	  #$PDbgLog.sig_call(self)
         | 
| 839 | 
            +
            	  #$PDbgLog.puts_msg caller(1).join("\t\n")
         | 
| 840 | 
            +
            	  unless @blink_timeout_id
         | 
| 841 | 
            +
            		t = Gdk::Screen.default.get_setting("gtk-cursor-blink-time")
         | 
| 842 | 
            +
            		@blink_timeout_id = Gtk.timeout_add(t ? t.to_i : 1000) {
         | 
| 843 | 
            +
            			#return true if @job && @job.alive?
         | 
| 844 | 
            +
            			if @pixbuf_blinking
         | 
| 845 | 
            +
            				if @pixbuf_backing.equal?(@pixbuf_blinking)
         | 
| 846 | 
            +
            					@pixbuf_backing = @pixbuf_marked
         | 
| 847 | 
            +
            				else
         | 
| 848 | 
            +
            					@pixbuf_backing = @pixbuf_blinking
         | 
| 849 | 
            +
            				end
         | 
| 850 | 
            +
            				@drw_area.window.invalidate(@blink_area_rect,
         | 
| 851 | 
            +
            					false) if @blink_area_rect
         | 
| 852 | 
            +
            			end
         | 
| 853 | 
            +
            			true
         | 
| 854 | 
            +
            		}
         | 
| 855 | 
            +
            	  end
         | 
| 856 | 
            +
            	  unless @pix_trace_timeout_id
         | 
| 857 | 
            +
            		@pix_trace_timeout_id = Gtk.timeout_add(@pix_trace_tm_out,
         | 
| 858 | 
            +
            			&@pix_trace_proc)
         | 
| 859 | 
            +
            	  end
         | 
| 860 | 
            +
            	  #$PDbgLog.sig_return("Done.")
         | 
| 861 | 
            +
            	end
         | 
| 862 | 
            +
            	
         | 
| 863 | 
            +
            	def remove_timeouts
         | 
| 864 | 
            +
            		#$PDbgLog.sig_call(self)
         | 
| 865 | 
            +
            		#$PDbgLog.puts_msg caller(1).join("\t\n")
         | 
| 866 | 
            +
            		if @blink_timeout_id
         | 
| 867 | 
            +
            			Gtk.timeout_remove(@blink_timeout_id)
         | 
| 868 | 
            +
            			@blink_timeout_id = nil
         | 
| 869 | 
            +
            		end
         | 
| 870 | 
            +
            		if @pix_trace_timeout_id
         | 
| 871 | 
            +
            			Gtk.timeout_remove(@pix_trace_timeout_id)
         | 
| 872 | 
            +
            			@pix_trace_timeout_id = nil
         | 
| 873 | 
            +
            		end
         | 
| 874 | 
            +
            		#$PDbgLog.sig_return("Done.")
         | 
| 875 | 
            +
            	end
         | 
| 876 | 
            +
            	
         | 
| 877 | 
            +
            	def show_exc_dialog
         | 
| 878 | 
            +
            		dialog = Gtk::MessageDialog.new(self,
         | 
| 879 | 
            +
            			Gtk::Dialog::MODAL | Gtk::Dialog::DESTROY_WITH_PARENT,
         | 
| 880 | 
            +
            			Gtk::MessageDialog::ERROR,
         | 
| 881 | 
            +
            			Gtk::MessageDialog::BUTTONS_CLOSE)
         | 
| 882 | 
            +
            		dialog.title = $!.class.name
         | 
| 883 | 
            +
            		dialog.markup = "<b>#{$!.class.name}:</b> <b><i>#{$!.to_s}</i></b>\n\tfrom #{$!.backtrace.join("\n\tfrom ")}"
         | 
| 884 | 
            +
            		dialog.run
         | 
| 885 | 
            +
            		dialog.destroy
         | 
| 886 | 
            +
            	end
         | 
| 887 | 
            +
            	
         | 
| 888 | 
            +
            	def drw_area_in_procs=(val)
         | 
| 889 | 
            +
            		if val
         | 
| 890 | 
            +
            			return if @drw_area_in_procs
         | 
| 891 | 
            +
            			@drw_area_in_procs = true
         | 
| 892 | 
            +
            			@scrl_win.freeze_child_notify
         | 
| 893 | 
            +
            		else
         | 
| 894 | 
            +
            			return unless @drw_area_in_procs
         | 
| 895 | 
            +
            			@drw_area_in_procs = false
         | 
| 896 | 
            +
            			@scrl_win.thaw_child_notify
         | 
| 897 | 
            +
            			@drw_area.queue_draw
         | 
| 898 | 
            +
            		end
         | 
| 899 | 
            +
            	end
         | 
| 900 | 
            +
            	
         | 
| 901 | 
            +
            	def pixbuf=(val)
         | 
| 902 | 
            +
            		@pixbuf_backing = @pixbuf_marked = @pixbuf_blinking = nil
         | 
| 903 | 
            +
            		@pixbuf = val
         | 
| 904 | 
            +
            		if @pixbuf.bits_per_sample != 8
         | 
| 905 | 
            +
            			raise NotImplementError,
         | 
| 906 | 
            +
            			  "pixbuf with #{@pixbuf.bits_per_sample} bits/sample"
         | 
| 907 | 
            +
            		end
         | 
| 908 | 
            +
            		if @pixbuf.n_channels == 3
         | 
| 909 | 
            +
            			@pixbuf_drw_meth = Gdk::RGB.method("draw_rgb_image")
         | 
| 910 | 
            +
            		elsif @pixbuf.n_channels == 4
         | 
| 911 | 
            +
            			@pixbuf_drw_meth = Gdk::RGB.method("draw_rgb_32_image")
         | 
| 912 | 
            +
            		else
         | 
| 913 | 
            +
            			raise NotImplementError,
         | 
| 914 | 
            +
            				"pixbuf with #{@pixbuf.n_channels} channels"
         | 
| 915 | 
            +
            		end
         | 
| 916 | 
            +
            		@pixbuf = @pixbuf.add_border(1)
         | 
| 917 | 
            +
            		@pixbuf_blinking = nil
         | 
| 918 | 
            +
            		@pixbuf_backing = @pixbuf_marked = @pixbuf.dup
         | 
| 919 | 
            +
            		@blob = nil
         | 
| 920 | 
            +
            		@blink_area_rect = nil
         | 
| 921 | 
            +
            		@pixbuf_marked_objs.clear
         | 
| 922 | 
            +
            		@pixbuf_blinking_objs.clear
         | 
| 923 | 
            +
            		@pixbuf_traced_objs.clear
         | 
| 924 | 
            +
            		@drw_area.set_size_request(@pixbuf.width*@kx,@pixbuf.height*@ky)
         | 
| 925 | 
            +
            		@scrl_win.queue_draw
         | 
| 926 | 
            +
            		@label_x.width_chars = @pixbuf.width.to_s.length
         | 
| 927 | 
            +
            		@label_y.width_chars = @pixbuf.height.to_s.length
         | 
| 928 | 
            +
            	end
         | 
| 929 | 
            +
            	
         | 
| 930 | 
            +
            	def kx=(val)
         | 
| 931 | 
            +
            		return if val == @kx
         | 
| 932 | 
            +
            		#@scrl_win.hadjustment.step_increment =
         | 
| 933 | 
            +
            		dx = val - @kx
         | 
| 934 | 
            +
            		@kx = val
         | 
| 935 | 
            +
            		return unless @pixbuf
         | 
| 936 | 
            +
            		if @blink_area
         | 
| 937 | 
            +
            			@blink_area_rect = Gdk::Rectangle.new(
         | 
| 938 | 
            +
            				(@blink_area.x + @pixbuf.border_width)*@kx,
         | 
| 939 | 
            +
            				(@blink_area.y + @pixbuf.border_width)*@ky,
         | 
| 940 | 
            +
            				(@blink_area.width*@kx).ceil + 1,
         | 
| 941 | 
            +
            				(@blink_area.height*@ky).ceil + 1)
         | 
| 942 | 
            +
            		end
         | 
| 943 | 
            +
            		win, x, y, state = *@drw_area.window.pointer
         | 
| 944 | 
            +
            		@drw_area.set_size_request(@pixbuf.width*@kx,@pixbuf.height*@ky)
         | 
| 945 | 
            +
            		viewport = @scrl_win.children[0]
         | 
| 946 | 
            +
            		win, vx, vy, state = viewport.window.pointer
         | 
| 947 | 
            +
            		width = viewport.allocation.width
         | 
| 948 | 
            +
            		height = viewport.allocation.height
         | 
| 949 | 
            +
            		if @drw_area.allocation.width > width
         | 
| 950 | 
            +
            		  if vx >= 0 && vx < width && vy >= 0 && vy < height
         | 
| 951 | 
            +
            		  	viewport.hadjustment.value += x*dx / (@kx-dx)
         | 
| 952 | 
            +
            		  else
         | 
| 953 | 
            +
            		  	k_x = viewport.hadjustment.value + width/2
         | 
| 954 | 
            +
            		  	viewport.hadjustment.value += k_x*dx / (@kx-dx)
         | 
| 955 | 
            +
            		  end
         | 
| 956 | 
            +
            		end
         | 
| 957 | 
            +
            		@scrl_win.queue_draw
         | 
| 958 | 
            +
            	end
         | 
| 959 | 
            +
            	
         | 
| 960 | 
            +
            	def ky=(val)
         | 
| 961 | 
            +
            		return if val == @ky
         | 
| 962 | 
            +
            		#@scrl_win.vadjustment.step_increment =
         | 
| 963 | 
            +
            		dy = val - @ky
         | 
| 964 | 
            +
            		@ky = val
         | 
| 965 | 
            +
            		return unless @pixbuf
         | 
| 966 | 
            +
            		if @blink_area
         | 
| 967 | 
            +
            			@blink_area_rect = Gdk::Rectangle.new(
         | 
| 968 | 
            +
            				(@blink_area.x + @pixbuf.border_width)*@kx,
         | 
| 969 | 
            +
            				(@blink_area.y + @pixbuf.border_width)*@ky,
         | 
| 970 | 
            +
            				(@blink_area.width*@kx).ceil + 1,
         | 
| 971 | 
            +
            				(@blink_area.height*@ky).ceil + 1)
         | 
| 972 | 
            +
            		end
         | 
| 973 | 
            +
            		win, x, y, state = *@drw_area.window.pointer
         | 
| 974 | 
            +
            		@drw_area.set_size_request(@pixbuf.width*@kx,@pixbuf.height*@ky)
         | 
| 975 | 
            +
            		viewport = @scrl_win.children[0]
         | 
| 976 | 
            +
            		win, vx, vy, state = viewport.window.pointer
         | 
| 977 | 
            +
            		width = viewport.allocation.width
         | 
| 978 | 
            +
            		height = viewport.allocation.height
         | 
| 979 | 
            +
            		if @drw_area.allocation.height > height
         | 
| 980 | 
            +
            		  if vx >= 0 && vx < width && vy >= 0 && vy < height
         | 
| 981 | 
            +
            		  	viewport.vadjustment.value += y*dy / (@ky-dy)
         | 
| 982 | 
            +
            		  else
         | 
| 983 | 
            +
            		  	k_y = viewport.vadjustment.value + height/2
         | 
| 984 | 
            +
            		  	viewport.vadjustment.value += k_y*dy / (@ky-dy)
         | 
| 985 | 
            +
            		  end
         | 
| 986 | 
            +
            		end
         | 
| 987 | 
            +
            		@scrl_win.queue_draw
         | 
| 988 | 
            +
            	end
         | 
| 989 | 
            +
            	
         | 
| 990 | 
            +
            	def pix_trace_tm_out=(val)
         | 
| 991 | 
            +
            		return if val == @pix_trace_tm_out
         | 
| 992 | 
            +
            		@pix_trace_tm_out = val
         | 
| 993 | 
            +
            		if @pix_trace_timeout_id
         | 
| 994 | 
            +
            			Gtk.timeout_remove(@pix_trace_timeout_id)
         | 
| 995 | 
            +
            			@pix_trace_timeout_id = Gtk.timeout_add(
         | 
| 996 | 
            +
            				@pix_trace_tm_out, &@pix_trace_proc)
         | 
| 997 | 
            +
            		end
         | 
| 998 | 
            +
            	end
         | 
| 999 | 
            +
            	
         | 
| 1000 | 
            +
            	def center_selection_cb(*args)
         | 
| 1001 | 
            +
            		min_x = min_y = 1.0/0.0
         | 
| 1002 | 
            +
            		max_x = max_y = 0
         | 
| 1003 | 
            +
            		pr = proc { |obj|
         | 
| 1004 | 
            +
            			min_x = obj.img_obj_min_ax.floor if
         | 
| 1005 | 
            +
            				obj.img_obj_min_ax.floor < min_x
         | 
| 1006 | 
            +
            			max_x = obj.img_obj_max_ax.ceil if
         | 
| 1007 | 
            +
            				obj.img_obj_max_ax.ceil > max_x
         | 
| 1008 | 
            +
            			min_y = obj.img_obj_min_ay.floor if
         | 
| 1009 | 
            +
            				obj.img_obj_min_ay.floor < min_y
         | 
| 1010 | 
            +
            			max_y = obj.img_obj_max_ay.ceil if
         | 
| 1011 | 
            +
            				obj.img_obj_max_ay.ceil > max_y
         | 
| 1012 | 
            +
            		}
         | 
| 1013 | 
            +
            		@pixbuf_marked_objs.each(&pr)
         | 
| 1014 | 
            +
            		@pixbuf_blinking_objs.each(&pr)
         | 
| 1015 | 
            +
            		@pixbuf_traced_objs.each(&pr)
         | 
| 1016 | 
            +
            		c_x = (min_x + max_x) * @kx / 2
         | 
| 1017 | 
            +
            		c_y = (min_y + max_y) * @ky / 2
         | 
| 1018 | 
            +
            		alloc = @scrl_win.children[0].allocation
         | 
| 1019 | 
            +
            		tmp = c_x - alloc.width/2
         | 
| 1020 | 
            +
            		@scrl_win.hadjustment.value = tmp > 0 ? tmp : 0
         | 
| 1021 | 
            +
            		tmp = c_y - alloc.height/2
         | 
| 1022 | 
            +
            		@scrl_win.vadjustment.value = tmp > 0 ? tmp : 0
         | 
| 1023 | 
            +
            	end
         | 
| 1024 | 
            +
            	
         | 
| 1025 | 
            +
            	def center_objs_cb(objs, widget)
         | 
| 1026 | 
            +
            		min_x = min_y = 1.0/0.0
         | 
| 1027 | 
            +
            		max_x = max_y = 0
         | 
| 1028 | 
            +
            		objs.each { |obj|
         | 
| 1029 | 
            +
            			min_x = obj.img_obj_min_ax.floor if
         | 
| 1030 | 
            +
            				obj.img_obj_min_ax.floor < min_x
         | 
| 1031 | 
            +
            			max_x = obj.img_obj_max_ax.ceil if
         | 
| 1032 | 
            +
            				obj.img_obj_max_ax.ceil > max_x
         | 
| 1033 | 
            +
            			min_y = obj.img_obj_min_ay.floor if
         | 
| 1034 | 
            +
            				obj.img_obj_min_ay.floor < min_y
         | 
| 1035 | 
            +
            			max_y = obj.img_obj_max_ay.ceil if
         | 
| 1036 | 
            +
            				obj.img_obj_max_ay.ceil > max_y
         | 
| 1037 | 
            +
            		}
         | 
| 1038 | 
            +
            		c_x = (min_x + max_x) * @kx / 2
         | 
| 1039 | 
            +
            		c_y = (min_y + max_y) * @ky / 2
         | 
| 1040 | 
            +
            		alloc = @scrl_win.children[0].allocation
         | 
| 1041 | 
            +
            		tmp = c_x - alloc.width/2
         | 
| 1042 | 
            +
            		@scrl_win.hadjustment.value = tmp > 0 ? tmp : 0
         | 
| 1043 | 
            +
            		tmp = c_y - alloc.height/2
         | 
| 1044 | 
            +
            		@scrl_win.vadjustment.value = tmp > 0 ? tmp : 0
         | 
| 1045 | 
            +
            	end
         | 
| 1046 | 
            +
            	
         | 
| 1047 | 
            +
            	def write_img_obj(file, obj)
         | 
| 1048 | 
            +
            		#$PDbgLog.sig_call(self)
         | 
| 1049 | 
            +
            		#$PDbgLog.puts_msg "file: #{file.inspect}, obj: #{obj}"
         | 
| 1050 | 
            +
            		obj.each { |pix|
         | 
| 1051 | 
            +
            			file.puts "#{pix.ax}\t#{pix.ay}"
         | 
| 1052 | 
            +
            		}
         | 
| 1053 | 
            +
            		#$PDbgLog.sig_return
         | 
| 1054 | 
            +
            	end
         | 
| 1055 | 
            +
            	
         | 
| 1056 | 
            +
            	def open_imagef(fpath)
         | 
| 1057 | 
            +
            		begin
         | 
| 1058 | 
            +
            			self.pixbuf = PPix::Pixbuf.new(fpath)
         | 
| 1059 | 
            +
            			dir, name = *File.split(fpath)
         | 
| 1060 | 
            +
            			self.title = "#{name} #{@pixbuf.picture_width}x#{
         | 
| 1061 | 
            +
            			  @pixbuf.picture_height} (#{dir}) -- Extract Curves"
         | 
| 1062 | 
            +
            		rescue IOError, Gdk::PixbufError
         | 
| 1063 | 
            +
            			self.show_exc_dialog
         | 
| 1064 | 
            +
            		end
         | 
| 1065 | 
            +
            	end
         | 
| 1066 | 
            +
            	
         | 
| 1067 | 
            +
            	def load_blob_cb(*args)
         | 
| 1068 | 
            +
            		return false unless @pixbuf && @in_progr.try_lock
         | 
| 1069 | 
            +
            		dialog = Gtk::FileChooserDialog.new("Open blob", self,
         | 
| 1070 | 
            +
            			Gtk::FileChooser::ACTION_OPEN, "gnome-vfs",
         | 
| 1071 | 
            +
            			[Gtk::Stock::OPEN, Gtk::Dialog::RESPONSE_ACCEPT],
         | 
| 1072 | 
            +
            			[Gtk::Stock::CANCEL, Gtk::Dialog::RESPONSE_CANCEL])
         | 
| 1073 | 
            +
            		dialog.add_shortcut_folder("/tmp") if File.directory?("/tmp")
         | 
| 1074 | 
            +
            		fpath = nil
         | 
| 1075 | 
            +
            		resp = dialog.run
         | 
| 1076 | 
            +
            		fpath = dialog.filename
         | 
| 1077 | 
            +
            		dialog.destroy
         | 
| 1078 | 
            +
            		i = -1
         | 
| 1079 | 
            +
            		Gtk.main_iteration_do(false) while (i += 1) < 10 &&
         | 
| 1080 | 
            +
            			Gtk.events_pending?
         | 
| 1081 | 
            +
            		if resp != Gtk::Dialog::RESPONSE_ACCEPT || !fpath
         | 
| 1082 | 
            +
            			@in_progr.unlock
         | 
| 1083 | 
            +
            			return
         | 
| 1084 | 
            +
            		end
         | 
| 1085 | 
            +
            		begin
         | 
| 1086 | 
            +
            		  File.open(fpath, 'r') { |f|
         | 
| 1087 | 
            +
            		  	blob = nil
         | 
| 1088 | 
            +
            			FloatsInp.new(f).each_rec { |rec| x, y = *rec
         | 
| 1089 | 
            +
            				x = x.to_i; y = y.to_i
         | 
| 1090 | 
            +
            				next unless x >= 0 && x<@pixbuf.picture_width &&
         | 
| 1091 | 
            +
            					y >= 0 && y < @pixbuf.picture_height &&
         | 
| 1092 | 
            +
            					@pixbuf.blob_id_at?(x, y, 0)
         | 
| 1093 | 
            +
            				unless blob
         | 
| 1094 | 
            +
            					blob_id = @pixbuf.add_blob(blob =
         | 
| 1095 | 
            +
            					  PPix::Blob.new(@pixbuf,
         | 
| 1096 | 
            +
            						@contour_geometry,
         | 
| 1097 | 
            +
            						@external_contours,
         | 
| 1098 | 
            +
            						@min_outer_lp_length))
         | 
| 1099 | 
            +
            					blob.blob_id = blob_id
         | 
| 1100 | 
            +
            				end
         | 
| 1101 | 
            +
            				blob.add(@pixbuf.get_pix(x, y))
         | 
| 1102 | 
            +
            			}
         | 
| 1103 | 
            +
            			if blob
         | 
| 1104 | 
            +
            				self.img_exit_blob
         | 
| 1105 | 
            +
            				@blob = blob
         | 
| 1106 | 
            +
            				@blob.extract_curves_args =
         | 
| 1107 | 
            +
            					{'extract_curves' => self,
         | 
| 1108 | 
            +
            					 'ctxt_menu_known_objs' => Set.new}
         | 
| 1109 | 
            +
            				self.img_enter_blob
         | 
| 1110 | 
            +
            				self.add_blob
         | 
| 1111 | 
            +
            			end
         | 
| 1112 | 
            +
            		  }
         | 
| 1113 | 
            +
            		rescue IOError
         | 
| 1114 | 
            +
            			self.show_exc_dialog
         | 
| 1115 | 
            +
            		ensure
         | 
| 1116 | 
            +
            			@in_progr.unlock
         | 
| 1117 | 
            +
            		end
         | 
| 1118 | 
            +
            	end
         | 
| 1119 | 
            +
            	
         | 
| 1120 | 
            +
            	def open_cb(*args)
         | 
| 1121 | 
            +
            		return false unless @in_progr.try_lock
         | 
| 1122 | 
            +
            		dialog = Gtk::FileChooserDialog.new(
         | 
| 1123 | 
            +
            			"Open raster image file for curve extraction", nil,
         | 
| 1124 | 
            +
            			Gtk::FileChooser::ACTION_OPEN, "gnome-vfs",
         | 
| 1125 | 
            +
            			[Gtk::Stock::OPEN, Gtk::Dialog::RESPONSE_ACCEPT],
         | 
| 1126 | 
            +
            			[Gtk::Stock::CANCEL, Gtk::Dialog::RESPONSE_CANCEL])
         | 
| 1127 | 
            +
            		
         | 
| 1128 | 
            +
            		# Filters:
         | 
| 1129 | 
            +
            		filters = []
         | 
| 1130 | 
            +
            		filter_any = Gtk::FileFilter.new
         | 
| 1131 | 
            +
            		filter_any.name = "Recognized Images"
         | 
| 1132 | 
            +
            		filter_any.add_pixbuf_formats
         | 
| 1133 | 
            +
            		filter = Gtk::FileFilter.new; filter.name = "JPEG"
         | 
| 1134 | 
            +
            		filter.add_pattern(pat="*.jpg"); filter_any.add_pattern(pat)
         | 
| 1135 | 
            +
            		filter.add_pattern(pat="*.JPG"); filter_any.add_pattern(pat)
         | 
| 1136 | 
            +
            		filter.add_pattern(pat="*.jpeg"); filter_any.add_pattern(pat)
         | 
| 1137 | 
            +
            		filter.add_pattern(pat="*.JPEG"); filter_any.add_pattern(pat)
         | 
| 1138 | 
            +
            		filters << filter
         | 
| 1139 | 
            +
            		filter = Gtk::FileFilter.new; filter.name = "GIF"
         | 
| 1140 | 
            +
            		filter.add_pattern(pat="*.gif"); filter_any.add_pattern(pat)
         | 
| 1141 | 
            +
            		filter.add_pattern(pat="*.GIF"); filter_any.add_pattern(pat)
         | 
| 1142 | 
            +
            		filters << filter
         | 
| 1143 | 
            +
            		filter = Gtk::FileFilter.new; filter.name = "BitMap"
         | 
| 1144 | 
            +
            		filter.add_pattern(pat="*.bmp"); filter_any.add_pattern(pat)
         | 
| 1145 | 
            +
            		filter.add_pattern(pat="*.BMP"); filter_any.add_pattern(pat)
         | 
| 1146 | 
            +
            		filters << filter
         | 
| 1147 | 
            +
            		filter = Gtk::FileFilter.new; filter.name = "Portable PixMap"
         | 
| 1148 | 
            +
            		filter.add_pattern(pat="*.ppm"); filter_any.add_pattern(pat)
         | 
| 1149 | 
            +
            		filter.add_pattern(pat="*.PPM"); filter_any.add_pattern(pat)
         | 
| 1150 | 
            +
            		filters << filter
         | 
| 1151 | 
            +
            		filter = Gtk::FileFilter.new
         | 
| 1152 | 
            +
            		filter.name = "Portable Network Graphics"
         | 
| 1153 | 
            +
            		filter.add_pattern(pat="*.png"); filter_any.add_pattern(pat)
         | 
| 1154 | 
            +
            		filter.add_pattern(pat="*.PNG"); filter_any.add_pattern(pat)
         | 
| 1155 | 
            +
            		filters << filter
         | 
| 1156 | 
            +
            		dialog.add_filter(filter_any)
         | 
| 1157 | 
            +
            		filter = Gtk::FileFilter.new; filter.name = "All files"
         | 
| 1158 | 
            +
            		filter.add_pattern("*")
         | 
| 1159 | 
            +
            		dialog.add_filter(filter)
         | 
| 1160 | 
            +
            		filters.each { |f| dialog.add_filter(f) }
         | 
| 1161 | 
            +
            		
         | 
| 1162 | 
            +
            		dialog.add_shortcut_folder("/tmp") if File.directory?("/tmp")
         | 
| 1163 | 
            +
            		fpath = nil
         | 
| 1164 | 
            +
            		resp = dialog.run
         | 
| 1165 | 
            +
            		fpath = dialog.filename
         | 
| 1166 | 
            +
            		dialog.destroy
         | 
| 1167 | 
            +
            		i = -1
         | 
| 1168 | 
            +
            		Gtk.main_iteration_do(false) while (i += 1) < 10 &&
         | 
| 1169 | 
            +
            			Gtk.events_pending?
         | 
| 1170 | 
            +
            		if resp != Gtk::Dialog::RESPONSE_ACCEPT || !fpath
         | 
| 1171 | 
            +
            			@in_progr.unlock
         | 
| 1172 | 
            +
            			return
         | 
| 1173 | 
            +
            		end
         | 
| 1174 | 
            +
            		begin
         | 
| 1175 | 
            +
            			self.open_imagef(fpath)
         | 
| 1176 | 
            +
            		ensure
         | 
| 1177 | 
            +
            			@in_progr.unlock
         | 
| 1178 | 
            +
            		end
         | 
| 1179 | 
            +
            	end
         | 
| 1180 | 
            +
            	
         | 
| 1181 | 
            +
            	def arr_del_obj(arr, which)
         | 
| 1182 | 
            +
            		#$PDbgLog.sig_call(self)
         | 
| 1183 | 
            +
            		obj_i = nil
         | 
| 1184 | 
            +
            		arr.each_with_index { |obj, idx|
         | 
| 1185 | 
            +
            			#$PDbgLog.print_msg " obj#{idx}:%x" % obj.object_id
         | 
| 1186 | 
            +
            			if obj.equal?(which)
         | 
| 1187 | 
            +
            				obj_i = idx
         | 
| 1188 | 
            +
            				break
         | 
| 1189 | 
            +
            			end
         | 
| 1190 | 
            +
            		}
         | 
| 1191 | 
            +
            		if obj_i
         | 
| 1192 | 
            +
            			#$PDbgLog.print_msg "; obj_i=#{obj_i}"
         | 
| 1193 | 
            +
            			arr[obj_i,1] = nil
         | 
| 1194 | 
            +
            		else
         | 
| 1195 | 
            +
            			warn "#{self.class.name}.arr_del_obj: Image object "+
         | 
| 1196 | 
            +
            				"to remove not found!"
         | 
| 1197 | 
            +
            		end
         | 
| 1198 | 
            +
            		#$PDbgLog.sig_return
         | 
| 1199 | 
            +
            	end
         | 
| 1200 | 
            +
            	
         | 
| 1201 | 
            +
            	def xy_toggle_buf(buf, x, y, pix_done, rowstride, pix_length)
         | 
| 1202 | 
            +
            		unless pix_done[k=[y, x]]
         | 
| 1203 | 
            +
            			  s = @pixbuf.ofs0 + y*rowstride + x*pix_length
         | 
| 1204 | 
            +
            			  s.upto(s + pix_length - 1) { |i|
         | 
| 1205 | 
            +
            				buf[i] ^= 0xff
         | 
| 1206 | 
            +
            			  }
         | 
| 1207 | 
            +
            			  pix_done[k] = true
         | 
| 1208 | 
            +
            		end
         | 
| 1209 | 
            +
            	end
         | 
| 1210 | 
            +
            	
         | 
| 1211 | 
            +
            	def xy_toggle_2bufs(buf1, buf2, x, y, pix_done, rowstride, pix_length)
         | 
| 1212 | 
            +
            		unless pix_done[k=[y, x]]
         | 
| 1213 | 
            +
            			  s = @pixbuf.ofs0 + y*rowstride + x*pix_length
         | 
| 1214 | 
            +
            			  s.upto(s + pix_length - 1) { |i|
         | 
| 1215 | 
            +
            				buf1[i] ^= 0xff
         | 
| 1216 | 
            +
            				buf2[i] ^= 0xff
         | 
| 1217 | 
            +
            			  }
         | 
| 1218 | 
            +
            			  pix_done[k] = true
         | 
| 1219 | 
            +
            		end
         | 
| 1220 | 
            +
            	end
         | 
| 1221 | 
            +
            	
         | 
| 1222 | 
            +
            	def pixels_mark_toggle(which)
         | 
| 1223 | 
            +
            		#$PDbgLog.sig_call(self)
         | 
| 1224 | 
            +
            		#$PDbgLog.puts_msg("#{which.length} pixel#{
         | 
| 1225 | 
            +
            		#	which.length==1? "" : "s"}")
         | 
| 1226 | 
            +
            		pix_done = {}
         | 
| 1227 | 
            +
            		rowstride = @pixbuf.rowstride; pix_length = @pixbuf.pix_length
         | 
| 1228 | 
            +
            		marked_pix = @pixbuf_marked.pixels
         | 
| 1229 | 
            +
            		if @pixbuf_blinking
         | 
| 1230 | 
            +
            			blinking_pix = @pixbuf_blinking.pixels
         | 
| 1231 | 
            +
            			which.each { |pt| ax, ay = pt.ax, pt.ay
         | 
| 1232 | 
            +
            				x1 = ax.floor; y1 = ay.floor
         | 
| 1233 | 
            +
            				x2 = ax.ceil; y2 = ay.ceil
         | 
| 1234 | 
            +
            				self.xy_toggle_2bufs(marked_pix, blinking_pix,
         | 
| 1235 | 
            +
            					x1, y1, pix_done, rowstride, pix_length)
         | 
| 1236 | 
            +
            				if x1 != x2
         | 
| 1237 | 
            +
            				  if y1 != y2
         | 
| 1238 | 
            +
            					self.xy_toggle_2bufs(marked_pix,
         | 
| 1239 | 
            +
            					  blinking_pix, x2, y1, pix_done,
         | 
| 1240 | 
            +
            					  rowstride, pix_length)
         | 
| 1241 | 
            +
            					self.xy_toggle_2bufs(marked_pix,
         | 
| 1242 | 
            +
            					  blinking_pix, x1, y2, pix_done,
         | 
| 1243 | 
            +
            					  rowstride, pix_length)
         | 
| 1244 | 
            +
            					self.xy_toggle_2bufs(marked_pix,
         | 
| 1245 | 
            +
            					  blinking_pix, x2, y2, pix_done,
         | 
| 1246 | 
            +
            					  rowstride, pix_length)
         | 
| 1247 | 
            +
            				  else
         | 
| 1248 | 
            +
            					self.xy_toggle_2bufs(marked_pix,
         | 
| 1249 | 
            +
            					  blinking_pix, x2, y1, pix_done,
         | 
| 1250 | 
            +
            					  rowstride, pix_length)
         | 
| 1251 | 
            +
            				  end
         | 
| 1252 | 
            +
            				elsif y1 != y2
         | 
| 1253 | 
            +
            					self.xy_toggle_2bufs(marked_pix,
         | 
| 1254 | 
            +
            					  blinking_pix, x1, y2, pix_done,
         | 
| 1255 | 
            +
            					  rowstride, pix_length)
         | 
| 1256 | 
            +
            				end
         | 
| 1257 | 
            +
            			}
         | 
| 1258 | 
            +
            		else
         | 
| 1259 | 
            +
            			which.each { |pt| ax, ay = pt.ax, pt.ay
         | 
| 1260 | 
            +
            				x1 = ax.floor; y1 = ay.floor
         | 
| 1261 | 
            +
            				x2 = ax.ceil; y2 = ay.ceil
         | 
| 1262 | 
            +
            				self.xy_toggle_buf(marked_pix, x1, y1, pix_done,
         | 
| 1263 | 
            +
            					rowstride, pix_length)
         | 
| 1264 | 
            +
            				if x1 != x2
         | 
| 1265 | 
            +
            				  if y1 != y2
         | 
| 1266 | 
            +
            					self.xy_toggle_buf(marked_pix, x2, y1,
         | 
| 1267 | 
            +
            					  pix_done, rowstride, pix_length)
         | 
| 1268 | 
            +
            					self.xy_toggle_buf(marked_pix, x1, y2,
         | 
| 1269 | 
            +
            					  pix_done, rowstride, pix_length)
         | 
| 1270 | 
            +
            					self.xy_toggle_buf(marked_pix, x2, y2,
         | 
| 1271 | 
            +
            					  pix_done, rowstride, pix_length)
         | 
| 1272 | 
            +
            				  else
         | 
| 1273 | 
            +
            					self.xy_toggle_buf(marked_pix, x2, y1,
         | 
| 1274 | 
            +
            					  pix_done, rowstride, pix_length)
         | 
| 1275 | 
            +
            				  end
         | 
| 1276 | 
            +
            				elsif y1 != y2
         | 
| 1277 | 
            +
            					self.xy_toggle_buf(marked_pix, x1, y2,
         | 
| 1278 | 
            +
            					  pix_done, rowstride, pix_length)
         | 
| 1279 | 
            +
            				end
         | 
| 1280 | 
            +
            			}
         | 
| 1281 | 
            +
            		end
         | 
| 1282 | 
            +
            		@drw_area.window.invalidate(Gdk::Rectangle.new(
         | 
| 1283 | 
            +
            			(which.img_obj_min_ax.floor+@pixbuf.border_width)*@kx,
         | 
| 1284 | 
            +
            			(which.img_obj_min_ay.floor+@pixbuf.border_width)*@ky,
         | 
| 1285 | 
            +
            			(which.img_obj_max_ax.ceil+1-which.img_obj_min_x) *@kx,
         | 
| 1286 | 
            +
            			(which.img_obj_max_ay.ceil+1-which.img_obj_min_y) *@ky),
         | 
| 1287 | 
            +
            			false)
         | 
| 1288 | 
            +
            		#$PDbgLog.sig_return
         | 
| 1289 | 
            +
            	end
         | 
| 1290 | 
            +
            	
         | 
| 1291 | 
            +
            	def pixels_blink_toggle(which)
         | 
| 1292 | 
            +
            		unless @pixbuf_blinking
         | 
| 1293 | 
            +
            			@pixbuf_blinking = @pixbuf_marked.dup
         | 
| 1294 | 
            +
            		end
         | 
| 1295 | 
            +
            		pix_done = {}
         | 
| 1296 | 
            +
            		rowstride = @pixbuf.rowstride; pix_length = @pixbuf.pix_length
         | 
| 1297 | 
            +
            		blinking_pix = @pixbuf_blinking.pixels
         | 
| 1298 | 
            +
            		which.each { |pt| ax, ay = pt.ax, pt.ay
         | 
| 1299 | 
            +
            			x1 = ax.floor; y1 = ay.floor
         | 
| 1300 | 
            +
            			x2 = ax.ceil; y2 = ay.ceil
         | 
| 1301 | 
            +
            			self.xy_toggle_buf(blinking_pix, x1, y1, pix_done,
         | 
| 1302 | 
            +
            				rowstride, pix_length)
         | 
| 1303 | 
            +
            			if x1 != x2
         | 
| 1304 | 
            +
            			  if y1 != y2
         | 
| 1305 | 
            +
            				self.xy_toggle_buf(blinking_pix, x2, y1,
         | 
| 1306 | 
            +
            				  pix_done, rowstride, pix_length)
         | 
| 1307 | 
            +
            				self.xy_toggle_buf(blinking_pix, x1, y2,
         | 
| 1308 | 
            +
            				  pix_done, rowstride, pix_length)
         | 
| 1309 | 
            +
            				self.xy_toggle_buf(blinking_pix, x2, y2,
         | 
| 1310 | 
            +
            				  pix_done, rowstride, pix_length)
         | 
| 1311 | 
            +
            			  else
         | 
| 1312 | 
            +
            				self.xy_toggle_buf(blinking_pix, x2, y1,
         | 
| 1313 | 
            +
            				  pix_done, rowstride, pix_length)
         | 
| 1314 | 
            +
            			  end
         | 
| 1315 | 
            +
            			elsif y1 != y2
         | 
| 1316 | 
            +
            				self.xy_toggle_buf(blinking_pix, x1, y2,
         | 
| 1317 | 
            +
            				  pix_done, rowstride, pix_length)
         | 
| 1318 | 
            +
            			end
         | 
| 1319 | 
            +
            		}
         | 
| 1320 | 
            +
            		@drw_area.window.invalidate(Gdk::Rectangle.new(
         | 
| 1321 | 
            +
            			(which.img_obj_min_ax.floor+@pixbuf.border_width)*@kx,
         | 
| 1322 | 
            +
            			(which.img_obj_min_ay.floor+@pixbuf.border_width)*@ky,
         | 
| 1323 | 
            +
            		1+((which.img_obj_max_ax.ceil+1-which.img_obj_min_x)*@kx).ceil,
         | 
| 1324 | 
            +
            		1+((which.img_obj_max_ay.ceil+1-which.img_obj_min_y)*@ky).ceil),
         | 
| 1325 | 
            +
            			false)
         | 
| 1326 | 
            +
            	end
         | 
| 1327 | 
            +
            	
         | 
| 1328 | 
            +
            	def pixels_mark(which)
         | 
| 1329 | 
            +
            		self.pixels_mark_toggle(which)
         | 
| 1330 | 
            +
            		@pixbuf_marked_objs.push(which)
         | 
| 1331 | 
            +
            	end
         | 
| 1332 | 
            +
            	
         | 
| 1333 | 
            +
            	def pixels_unmark(which)
         | 
| 1334 | 
            +
            		self.pixels_mark_toggle(which)
         | 
| 1335 | 
            +
            		self.arr_del_obj(@pixbuf_marked_objs, which)
         | 
| 1336 | 
            +
            	end
         | 
| 1337 | 
            +
            	
         | 
| 1338 | 
            +
            	def pixels_blink(which)
         | 
| 1339 | 
            +
            		self.pixels_blink_toggle(which)
         | 
| 1340 | 
            +
            		@pixbuf_blinking_objs.push(which)
         | 
| 1341 | 
            +
            		return if which.empty?
         | 
| 1342 | 
            +
            		@blink_area = Gdk::Rectangle.new(
         | 
| 1343 | 
            +
            			which.first.x, which.first.y, 0, 0) unless @blink_area
         | 
| 1344 | 
            +
            		end_x = [@blink_area.x + @blink_area.width-1,
         | 
| 1345 | 
            +
            			which.img_obj_max_ax.ceil].max
         | 
| 1346 | 
            +
            		end_y = [@blink_area.y + @blink_area.height-1,
         | 
| 1347 | 
            +
            			which.img_obj_max_ay.ceil].max
         | 
| 1348 | 
            +
            		@blink_area.x = [@blink_area.x, which.img_obj_min_ax.floor].min
         | 
| 1349 | 
            +
            		@blink_area.y = [@blink_area.y, which.img_obj_min_ay.floor].min
         | 
| 1350 | 
            +
            		@blink_area.width = end_x - @blink_area.x + 1
         | 
| 1351 | 
            +
            		@blink_area.height = end_y - @blink_area.y + 1
         | 
| 1352 | 
            +
            		if @blink_area_rect
         | 
| 1353 | 
            +
            			@blink_area_rect.x =
         | 
| 1354 | 
            +
            				(@blink_area.x + @pixbuf.border_width)*@kx
         | 
| 1355 | 
            +
            			@blink_area_rect.width = (@blink_area.width*@kx).ceil+1
         | 
| 1356 | 
            +
            			@blink_area_rect.y =
         | 
| 1357 | 
            +
            				(@blink_area.y + @pixbuf.border_width)*@ky
         | 
| 1358 | 
            +
            			@blink_area_rect.height =(@blink_area.height*@ky).ceil+1
         | 
| 1359 | 
            +
            		else
         | 
| 1360 | 
            +
            			@blink_area_rect = Gdk::Rectangle.new(
         | 
| 1361 | 
            +
            				(@blink_area.x + @pixbuf.border_width)*@kx,
         | 
| 1362 | 
            +
            				(@blink_area.y + @pixbuf.border_width)*@ky,
         | 
| 1363 | 
            +
            				(@blink_area.width*@kx).ceil + 1,
         | 
| 1364 | 
            +
            				(@blink_area.height*@ky).ceil + 1)
         | 
| 1365 | 
            +
            		end
         | 
| 1366 | 
            +
            	end
         | 
| 1367 | 
            +
            	
         | 
| 1368 | 
            +
            	def pixels_unblink(which)
         | 
| 1369 | 
            +
            		self.pixels_blink_toggle(which) if @pixbuf_blinking
         | 
| 1370 | 
            +
            		self.arr_del_obj(@pixbuf_blinking_objs, which)
         | 
| 1371 | 
            +
            		return if which.empty?
         | 
| 1372 | 
            +
            		end_x = @blink_area.x + @blink_area.width - 1
         | 
| 1373 | 
            +
            		end_y = @blink_area.y + @blink_area.height - 1
         | 
| 1374 | 
            +
            		if which.img_obj_max_ax.ceil >= end_x ||
         | 
| 1375 | 
            +
            		which.img_obj_min_ax.floor <= @blink_area.x ||
         | 
| 1376 | 
            +
            		which.img_obj_max_ay.ceil >= end_y ||
         | 
| 1377 | 
            +
            		which.img_obj_min_ay.floor <= @blink_area.y
         | 
| 1378 | 
            +
            		  if @pixbuf_blinking_objs.empty?
         | 
| 1379 | 
            +
            			@blink_area = nil
         | 
| 1380 | 
            +
            			@blink_area_rect = nil
         | 
| 1381 | 
            +
            		  else
         | 
| 1382 | 
            +
            			end_x = @blink_area.x = @pixbuf_blinking_objs[0].first.x
         | 
| 1383 | 
            +
            			end_y = @blink_area.y = @pixbuf_blinking_objs[0].first.y
         | 
| 1384 | 
            +
            			@pixbuf_blinking_objs.each { |obj|
         | 
| 1385 | 
            +
            				@blink_area.x = [@blink_area.x,
         | 
| 1386 | 
            +
            					obj.img_obj_min_ax.floor].min
         | 
| 1387 | 
            +
            				end_x = [end_x, obj.img_obj_max_ax.ceil].max
         | 
| 1388 | 
            +
            				@blink_area.y = [@blink_area.y,
         | 
| 1389 | 
            +
            					obj.img_obj_min_ay.floor].min
         | 
| 1390 | 
            +
            				end_y = [end_y, obj.img_obj_max_ay.ceil].max
         | 
| 1391 | 
            +
            			}
         | 
| 1392 | 
            +
            			@blink_area.width = end_x - @blink_area.x + 1
         | 
| 1393 | 
            +
            			@blink_area.height = end_y - @blink_area.y + 1
         | 
| 1394 | 
            +
            			@blink_area_rect.x =
         | 
| 1395 | 
            +
            				(@blink_area.x + @pixbuf.border_width)*@kx
         | 
| 1396 | 
            +
            			@blink_area_rect.width = (@blink_area.width*@kx).ceil+1
         | 
| 1397 | 
            +
            			@blink_area_rect.y =
         | 
| 1398 | 
            +
            				(@blink_area.y + @pixbuf.border_width)*@ky
         | 
| 1399 | 
            +
            			@blink_area_rect.height =(@blink_area.height*@ky).ceil+1
         | 
| 1400 | 
            +
            		  end
         | 
| 1401 | 
            +
            		end
         | 
| 1402 | 
            +
            	end
         | 
| 1403 | 
            +
            	
         | 
| 1404 | 
            +
            	def pixels_trace(which)
         | 
| 1405 | 
            +
            		@pixbuf_traced_objs.push(which)
         | 
| 1406 | 
            +
            	end
         | 
| 1407 | 
            +
            	
         | 
| 1408 | 
            +
            	def pixels_untrace(which)
         | 
| 1409 | 
            +
            		self.arr_del_obj(@pixbuf_traced_objs, which)
         | 
| 1410 | 
            +
            	end
         | 
| 1411 | 
            +
            	
         | 
| 1412 | 
            +
            	def img_exit_blob
         | 
| 1413 | 
            +
            		#$PDbgLog.sig_call(self)
         | 
| 1414 | 
            +
            		while !@pixbuf_marked_objs.empty?
         | 
| 1415 | 
            +
            		#  $PDbgLog.puts_msg "unmark "+@pixbuf_marked_objs.first.inspect
         | 
| 1416 | 
            +
            			self.pixels_unmark(@pixbuf_marked_objs.first)
         | 
| 1417 | 
            +
            		end
         | 
| 1418 | 
            +
            		while !@pixbuf_blinking_objs.empty?
         | 
| 1419 | 
            +
            			#$PDbgLog.puts_msg "unblink " +
         | 
| 1420 | 
            +
            			#	@pixbuf_blinking_objs.first.inspect
         | 
| 1421 | 
            +
            			self.pixels_unblink(@pixbuf_blinking_objs.first)
         | 
| 1422 | 
            +
            		end
         | 
| 1423 | 
            +
            		while !@pixbuf_traced_objs.empty?
         | 
| 1424 | 
            +
            	#	  $PDbgLog.puts_msg "untrace "+@pixbuf_traced_objs.first.inspect
         | 
| 1425 | 
            +
            			self.pixels_untrace(@pixbuf_traced_objs.first)
         | 
| 1426 | 
            +
            		end
         | 
| 1427 | 
            +
            		#$PDbgLog.sig_call(self)
         | 
| 1428 | 
            +
            	end
         | 
| 1429 | 
            +
            	
         | 
| 1430 | 
            +
            	def ref_img_obj(path)
         | 
| 1431 | 
            +
            		#$PDbgLog.sig_call(self)
         | 
| 1432 | 
            +
            		#$PDbgLog.print_msg "path=#{path.inspect}:"
         | 
| 1433 | 
            +
            		obj = @blob
         | 
| 1434 | 
            +
            		path = path[1...path.length] if path.starts_with("/")
         | 
| 1435 | 
            +
            		while path.length > 0
         | 
| 1436 | 
            +
            			if (i = path.index("/"))
         | 
| 1437 | 
            +
            				attr_name = path[0, i].downcase_first
         | 
| 1438 | 
            +
            				path = path[i+1...path.length]
         | 
| 1439 | 
            +
            			else
         | 
| 1440 | 
            +
            				attr_name = path.downcase_first
         | 
| 1441 | 
            +
            				path = ""
         | 
| 1442 | 
            +
            			end
         | 
| 1443 | 
            +
            			#$PDbgLog.print_msg "obj=#{obj}:methods=#{[obj.
         | 
| 1444 | 
            +
            			#	public_methods.sort-Object.methods].inspect},"
         | 
| 1445 | 
            +
            			#$PDbgLog.print_msg "path=#{path.inspect},attr_name=#{
         | 
| 1446 | 
            +
            			#	attr_name.inspect} "
         | 
| 1447 | 
            +
            			if attr_name =~ /([A-Za-z =?]+) ([0-9]+)/
         | 
| 1448 | 
            +
            				i = $2.to_i
         | 
| 1449 | 
            +
            				attr_name = $1.gsub(" ", "_")
         | 
| 1450 | 
            +
            				#$PDbgLog.print_msg "attr_name=#{attr_name.
         | 
| 1451 | 
            +
            				#	inspect}, i=#{i} "
         | 
| 1452 | 
            +
            				if obj.public_methods.include?(attr_name)
         | 
| 1453 | 
            +
            					obj = obj.send(attr_name)[i]
         | 
| 1454 | 
            +
            				elsif obj.public_methods.include?(mname=
         | 
| 1455 | 
            +
            				attr_name.plural)
         | 
| 1456 | 
            +
            					obj = obj.send(mname)[i]
         | 
| 1457 | 
            +
            				else
         | 
| 1458 | 
            +
            					#$PDbgLog.sig_return(
         | 
| 1459 | 
            +
            					#	"no indexed method: nil")
         | 
| 1460 | 
            +
            					return nil
         | 
| 1461 | 
            +
            				end
         | 
| 1462 | 
            +
            			else
         | 
| 1463 | 
            +
            			  attr_name.gsub!(" ", "_")
         | 
| 1464 | 
            +
            			  if obj.public_methods.include?(attr_name)
         | 
| 1465 | 
            +
            				obj = obj.send(attr_name)
         | 
| 1466 | 
            +
            			  else
         | 
| 1467 | 
            +
            				#$PDbgLog.sig_return("no method #{attr_name.
         | 
| 1468 | 
            +
            				#	inspect}: nil")
         | 
| 1469 | 
            +
            				return nil
         | 
| 1470 | 
            +
            			  end
         | 
| 1471 | 
            +
            			end
         | 
| 1472 | 
            +
            		end
         | 
| 1473 | 
            +
            		#$PDbgLog.sig_return(obj)
         | 
| 1474 | 
            +
            		obj
         | 
| 1475 | 
            +
            	end
         | 
| 1476 | 
            +
            	
         | 
| 1477 | 
            +
            	def img_enter_blob
         | 
| 1478 | 
            +
            		#$PDbgLog.sig_call(self)
         | 
| 1479 | 
            +
            		self.remove_timeouts
         | 
| 1480 | 
            +
            		@mark_blob.each_pair { |path, mw|
         | 
| 1481 | 
            +
            			next if !(obj = self.ref_img_obj(path)) || obj.empty?
         | 
| 1482 | 
            +
            			#$PDbgLog.puts_msg path + ": " + mw
         | 
| 1483 | 
            +
            			self.method("pixels_"+mw).call(obj)
         | 
| 1484 | 
            +
            		}
         | 
| 1485 | 
            +
            		self.add_timeouts
         | 
| 1486 | 
            +
            		#$PDbgLog.sig_return
         | 
| 1487 | 
            +
            	end
         | 
| 1488 | 
            +
            	
         | 
| 1489 | 
            +
            	def img_motion_notify_cb(*args)
         | 
| 1490 | 
            +
            		win, x, y, state = *@drw_area.window.pointer
         | 
| 1491 | 
            +
            		x = (x/@kx).to_i; y = (y/@ky).to_i
         | 
| 1492 | 
            +
            		if !@pixbuf || x < 0 || x >= @pixbuf.width || y < 0 ||
         | 
| 1493 | 
            +
            		y >= @pixbuf.height
         | 
| 1494 | 
            +
            			@label_x.text = "   "
         | 
| 1495 | 
            +
            			@label_y.text = "   "
         | 
| 1496 | 
            +
            			return
         | 
| 1497 | 
            +
            		end
         | 
| 1498 | 
            +
            		@label_x.text = "%-3d" % (rx=x - @pixbuf.border_width)
         | 
| 1499 | 
            +
            		@label_y.text = "%-3d" % (ry=y - @pixbuf.border_width)
         | 
| 1500 | 
            +
            		if rx >= 0 && rx < @pixbuf.picture_width &&
         | 
| 1501 | 
            +
            		ry >= 0 && ry <  @pixbuf.picture_height
         | 
| 1502 | 
            +
            		  rgb = *@pixbuf.get_pix(rx, ry).color_rgb
         | 
| 1503 | 
            +
            		  if @clr_show_scheme == "rgb"
         | 
| 1504 | 
            +
            			clr_text = "%3d,%3d,%3d" % rgb
         | 
| 1505 | 
            +
            		  else
         | 
| 1506 | 
            +
            		  	h, s, v = *@pixbuf.get_pix(rx,ry).color_hsv
         | 
| 1507 | 
            +
            			clr_text = "%3.0f,%3.0f,%3.0f" %
         | 
| 1508 | 
            +
            				[360.0*h, 100.0*s, 100.0*v]
         | 
| 1509 | 
            +
            		  end
         | 
| 1510 | 
            +
            		  bg = "\#%02x%02x%02x" % rgb
         | 
| 1511 | 
            +
            		  fg = "\#%02x%02x%02x" % [rgb[0] > 127 ? 0 : 255,
         | 
| 1512 | 
            +
            			rgb[1] > 127 ? 0 : 255, rgb[2] > 127 ? 0 : 255]
         | 
| 1513 | 
            +
            		  @label_clr.set_markup("<span foreground=\"#{fg
         | 
| 1514 | 
            +
            		  	}\" background=\"#{bg}\">#{clr_text}</span>")
         | 
| 1515 | 
            +
            		end
         | 
| 1516 | 
            +
            		true
         | 
| 1517 | 
            +
            	end
         | 
| 1518 | 
            +
            	
         | 
| 1519 | 
            +
            	def img_expose_cb(drw_area, event)
         | 
| 1520 | 
            +
            		#$PDbgLog.sig_call(self)
         | 
| 1521 | 
            +
            		#$PDbgLog.print_msg "area: #{event.area.x}, #{event.area.y}, #{
         | 
| 1522 | 
            +
            		#	event.area.width}, #{event.area.height}: "
         | 
| 1523 | 
            +
            		if !@pixbuf || !@pixbuf_backing || !@pixbuf_drw_meth ||
         | 
| 1524 | 
            +
            		(x0=event.area.x/@kx) >= @pixbuf.width ||
         | 
| 1525 | 
            +
            		(y0=event.area.y/@ky) >= @pixbuf.height || @drw_area_in_procs
         | 
| 1526 | 
            +
            			#$PDbgLog.sig_return(@drw_area_in_procs)
         | 
| 1527 | 
            +
            			return @drw_area_in_procs
         | 
| 1528 | 
            +
            		end
         | 
| 1529 | 
            +
            		#$PDbgLog.puts_msg "pb_pix_cnt=#{@pixbuf.width*@pixbuf.height}"
         | 
| 1530 | 
            +
            		pb = @pixbuf_backing
         | 
| 1531 | 
            +
            		pb_pix = pb.pixels
         | 
| 1532 | 
            +
            		end_x = (event.area.x + event.area.width-1)/@kx
         | 
| 1533 | 
            +
            		end_y = (event.area.y + event.area.height-1)/@ky
         | 
| 1534 | 
            +
            		end_x = @pixbuf.width-1 if end_x >= @pixbuf.width
         | 
| 1535 | 
            +
            		end_y = @pixbuf.height-1 if end_y >= @pixbuf.height
         | 
| 1536 | 
            +
            		rowstride = @pixbuf.rowstride; pix_length = @pixbuf.pix_length
         | 
| 1537 | 
            +
            		ofs = ofs0 = y0 * rowstride + x0 * pix_length
         | 
| 1538 | 
            +
            		end_ofs = end_y * rowstride + end_x * pix_length
         | 
| 1539 | 
            +
            		width = end_x-x0 + 1; width_stride = width * pix_length
         | 
| 1540 | 
            +
            		height = end_y-y0 + 1
         | 
| 1541 | 
            +
            		t_width_stride = width_stride - pix_length
         | 
| 1542 | 
            +
            		#sub_x0 = @kx - event.area.x % @kx
         | 
| 1543 | 
            +
            		#sub_y0 = @ky - event.area.y % @ky
         | 
| 1544 | 
            +
            		view_width = (width*@kx).ceil + 1
         | 
| 1545 | 
            +
            		view_height = (height*@ky).ceil + 1
         | 
| 1546 | 
            +
            		start_x = event.area.x; start_y = event.area.y
         | 
| 1547 | 
            +
            		#$PDbgLog.print_msg "x0=#{x0}, y0=#{y0}, sub_x0=#{sub_x0
         | 
| 1548 | 
            +
            		#	}, sub_y0=#{sub_y0}, end_x=#{end_x}, end_y=#{end_y
         | 
| 1549 | 
            +
            		#	}, rowstride=#{rowstride}, pix_length=#{pix_length} "
         | 
| 1550 | 
            +
            		if (trc_obj = @pixbuf_traced_objs[@pixbuf_traced_obj_i]) &&
         | 
| 1551 | 
            +
            		(trc_pix = trc_obj[@pixbuf_traced_pix_i]) && (trc_pix_ofs=
         | 
| 1552 | 
            +
            		@pixbuf.ofs0+rowstride*trc_pix.y+pix_length*trc_pix.x) >= ofs0&&
         | 
| 1553 | 
            +
            		trc_pix_ofs <= end_ofs
         | 
| 1554 | 
            +
            			trc_pix_ofs.upto(trc_pix_ofs+pix_length-1) { |tmp_ofs|
         | 
| 1555 | 
            +
            				pb_pix[tmp_ofs] ^= 0xff
         | 
| 1556 | 
            +
            			}
         | 
| 1557 | 
            +
            			tw = @trace_mark.width
         | 
| 1558 | 
            +
            			tx = tx0 = (@kx*(trc_pix.x+@pixbuf.border_width+0.5) -
         | 
| 1559 | 
            +
            				tw/2 - start_x).to_i
         | 
| 1560 | 
            +
            			if tx < 0
         | 
| 1561 | 
            +
            				tw += tx
         | 
| 1562 | 
            +
            				tx = 0
         | 
| 1563 | 
            +
            			end
         | 
| 1564 | 
            +
            			e_x = ((@pixbuf.width+2*@pixbuf.border_width)*@kx).ceil
         | 
| 1565 | 
            +
            			tw = e_x - tx if tx + tw > e_x
         | 
| 1566 | 
            +
            			th = @trace_mark.height
         | 
| 1567 | 
            +
            			ty = ty0 = (@ky*(trc_pix.y+@pixbuf.border_width+0.5) -
         | 
| 1568 | 
            +
            				th/2 - start_y).to_i
         | 
| 1569 | 
            +
            			if ty < 0
         | 
| 1570 | 
            +
            				th += ty
         | 
| 1571 | 
            +
            				ty = 0
         | 
| 1572 | 
            +
            			end
         | 
| 1573 | 
            +
            			e_y = ((@pixbuf.height+2*@pixbuf.border_width)*@ky).ceil
         | 
| 1574 | 
            +
            			th = e_y - ty if ty + th > e_y
         | 
| 1575 | 
            +
            		else
         | 
| 1576 | 
            +
            			trc_pix = nil
         | 
| 1577 | 
            +
            		end
         | 
| 1578 | 
            +
            		sc_pb = pb.gdk_scaled(@kx, @ky, start_x, start_y,
         | 
| 1579 | 
            +
            		  view_width, view_height, @kx < 1 || @ky < 1 ?
         | 
| 1580 | 
            +
            		  Gdk::Pixbuf::INTERP_BILINEAR : Gdk::Pixbuf::INTERP_NEAREST);
         | 
| 1581 | 
            +
            		if trc_pix
         | 
| 1582 | 
            +
            			sc_pb.composite!(@trace_mark,tx,ty, tw,th, tx0,ty0, 1,1,
         | 
| 1583 | 
            +
            			  Gdk::Pixbuf::INTERP_NEAREST, 255)
         | 
| 1584 | 
            +
            			trc_pix_ofs.upto(trc_pix_ofs+pix_length-1) { |tmp_ofs|
         | 
| 1585 | 
            +
            				pb_pix[tmp_ofs] ^= 0xff
         | 
| 1586 | 
            +
            			}
         | 
| 1587 | 
            +
            		end
         | 
| 1588 | 
            +
            		#@pixbuf_drw_meth.call(drw_area.window,drw_area.style.black_gc,
         | 
| 1589 | 
            +
            		#	event.area.x, event.area.y,
         | 
| 1590 | 
            +
            		#	(width-1)*@kx + sub_x0,(height-1)*@ky + sub_y0,
         | 
| 1591 | 
            +
            		#	Gdk::RGB::Dither::NORMAL, pixels, rowstride,
         | 
| 1592 | 
            +
            		#	(width-1)*@kx + sub_x0, (height-1)*@ky + sub_y0)
         | 
| 1593 | 
            +
            		#@pixbuf_drw_meth.call(drw_area.window,drw_area.style.black_gc,
         | 
| 1594 | 
            +
            		#	event.area.x, event.area.y,
         | 
| 1595 | 
            +
            		#	event.area.width, event.area.height,
         | 
| 1596 | 
            +
            		#	Gdk::RGB::Dither::NORMAL, pixels, rowstride,
         | 
| 1597 | 
            +
            		#	event.area.width, event.area.height)
         | 
| 1598 | 
            +
            		@pixbuf_drw_meth.call(drw_area.window,drw_area.style.black_gc,
         | 
| 1599 | 
            +
            			start_x, start_y, view_width, view_height,
         | 
| 1600 | 
            +
            			Gdk::RGB::Dither::NORMAL, sc_pb.pixels, sc_pb.rowstride,
         | 
| 1601 | 
            +
            			view_width, view_height)
         | 
| 1602 | 
            +
            		#$PDbgLog.sig_return
         | 
| 1603 | 
            +
            		true
         | 
| 1604 | 
            +
            	end
         | 
| 1605 | 
            +
            	
         | 
| 1606 | 
            +
            	def add_blob
         | 
| 1607 | 
            +
            		#$PDbgLog.sig_call(self)
         | 
| 1608 | 
            +
            		items = []
         | 
| 1609 | 
            +
            		sel_cb = proc { |bl, wgt|
         | 
| 1610 | 
            +
            			return if bl.equal?(@blob)
         | 
| 1611 | 
            +
            			#$PDbgLog.sig_call(self)
         | 
| 1612 | 
            +
            			#$PDbgLog.puts_msg "bl: #{bl.inspect}"
         | 
| 1613 | 
            +
            			self.img_exit_blob
         | 
| 1614 | 
            +
            			@blob = bl
         | 
| 1615 | 
            +
            			self.img_enter_blob
         | 
| 1616 | 
            +
            			#$PDbgLog.sig_return
         | 
| 1617 | 
            +
            		}
         | 
| 1618 | 
            +
            		if @pixbuf
         | 
| 1619 | 
            +
            			@pixbuf.blob_id2ref_arr.each { |blob|
         | 
| 1620 | 
            +
            				items << ["/Blob #{blob.blob_id} (#{blob.length
         | 
| 1621 | 
            +
            				  } pix)", "<Item>", nil, nil, sel_cb, blob]
         | 
| 1622 | 
            +
            			}
         | 
| 1623 | 
            +
            		end
         | 
| 1624 | 
            +
            		item_factory = Gtk::ItemFactory.new(Gtk::ItemFactory::TYPE_MENU,
         | 
| 1625 | 
            +
            			'<blobs>', nil)
         | 
| 1626 | 
            +
            		item_factory.create_items(items)
         | 
| 1627 | 
            +
            		oldmenu = @select_blob_menu_branch.submenu
         | 
| 1628 | 
            +
            		@select_blob_menu_branch.submenu = item_factory.get_widget(
         | 
| 1629 | 
            +
            			'<blobs>')
         | 
| 1630 | 
            +
            		oldmenu.destroy
         | 
| 1631 | 
            +
            		#$PDbgLog.sig_return
         | 
| 1632 | 
            +
            	end
         | 
| 1633 | 
            +
            	
         | 
| 1634 | 
            +
            	alias_method :del_blob, :add_blob
         | 
| 1635 | 
            +
            	
         | 
| 1636 | 
            +
            	def img_get_objs_at(drw_arr, event)
         | 
| 1637 | 
            +
            		return false unless @pixbuf
         | 
| 1638 | 
            +
            		## Pop the motion event and allow the registering of the next:
         | 
| 1639 | 
            +
            		#win, x, y, state = event.window.pointer
         | 
| 1640 | 
            +
            		x, y = event.x.to_i, event.y.to_i
         | 
| 1641 | 
            +
            		x = (x/@kx).to_i - @pixbuf.border_width
         | 
| 1642 | 
            +
            		y = (y/@ky).to_i - @pixbuf.border_width
         | 
| 1643 | 
            +
            		return true if x < 0 || x >= @pixbuf.picture_width ||
         | 
| 1644 | 
            +
            			y < 0 || y >= @pixbuf.picture_height ||
         | 
| 1645 | 
            +
            			(@blob && @pixbuf.blob_id_at?(x, y, @blob.blob_id))
         | 
| 1646 | 
            +
            		$PDbgLog.sig_call(self)
         | 
| 1647 | 
            +
            		self.img_exit_blob
         | 
| 1648 | 
            +
            		if @cmp_pix_to == "Blob mean color in circle; R="
         | 
| 1649 | 
            +
            			cmp_pix_to = ['Blob mean color in a circle',
         | 
| 1650 | 
            +
            				@pix_cmp_circ_r_spinbtn.value_as_int]
         | 
| 1651 | 
            +
            		else
         | 
| 1652 | 
            +
            			cmp_pix_to = @cmp_pix_to
         | 
| 1653 | 
            +
            		end
         | 
| 1654 | 
            +
            		$PDbgLog.print_msg "Getting blob(#{x}, #{y}): cmp. to: #{
         | 
| 1655 | 
            +
            			cmp_pix_to.inspect}, #{@clr_match_scheme} tolerance: "
         | 
| 1656 | 
            +
            		if @clr_match_scheme == "rgb"
         | 
| 1657 | 
            +
            		  $PDbgLog.print_msg "#{@fuzzy_clr_r},#{@fuzzy_clr_g},#{
         | 
| 1658 | 
            +
            		  	@fuzzy_clr_b}"
         | 
| 1659 | 
            +
            		  toler_1 = @fuzzy_clr_r
         | 
| 1660 | 
            +
            		  toler_2 = @fuzzy_clr_g
         | 
| 1661 | 
            +
            		  toler_3 = @fuzzy_clr_b
         | 
| 1662 | 
            +
            		else
         | 
| 1663 | 
            +
            		  $PDbgLog.print_msg "#{@fuzzy_clr_h},#{@fuzzy_clr_s},#{
         | 
| 1664 | 
            +
            		  	@fuzzy_clr_v}"
         | 
| 1665 | 
            +
            		  toler_1 = @fuzzy_clr_h
         | 
| 1666 | 
            +
            		  toler_2 = @fuzzy_clr_s
         | 
| 1667 | 
            +
            		  toler_3 = @fuzzy_clr_v
         | 
| 1668 | 
            +
            		end
         | 
| 1669 | 
            +
            		$PDbgLog.puts_msg "; contour geometry=#{@contour_geometry
         | 
| 1670 | 
            +
            			}, external contours?=#{@external_contours
         | 
| 1671 | 
            +
            			}, min. subblob size=#{@min_subblob_size}."
         | 
| 1672 | 
            +
            		@blob = @pixbuf.get_pix(x,y).blob(@contour_geometry,
         | 
| 1673 | 
            +
            			@external_contours, @min_subblob_size-1,
         | 
| 1674 | 
            +
            			@min_outer_lp_length, &PPix::Blob.mk_get_neighbs_proc(
         | 
| 1675 | 
            +
            			@clr_match_scheme, cmp_pix_to, toler_1,toler_2,toler_3))
         | 
| 1676 | 
            +
            		@blob.extract_curves_args =
         | 
| 1677 | 
            +
            			{'extract_curves' => self,
         | 
| 1678 | 
            +
            			 'ctxt_menu_known_objs' => Set.new} unless
         | 
| 1679 | 
            +
            			 	@blob.extract_curves_args
         | 
| 1680 | 
            +
            		self.img_enter_blob
         | 
| 1681 | 
            +
            		self.add_blob
         | 
| 1682 | 
            +
            		$PDbgLog.sig_return
         | 
| 1683 | 
            +
            		true
         | 
| 1684 | 
            +
            	end
         | 
| 1685 | 
            +
            	
         | 
| 1686 | 
            +
            	def mark_blob_switch_obj(obj, path, new_mark_way)
         | 
| 1687 | 
            +
            		#$PDbgLog.sig_call(self)
         | 
| 1688 | 
            +
            		#$PDbgLog.print_msg "path=#{path.inspect}"
         | 
| 1689 | 
            +
            		new_mark_way = new_mark_way.downcase
         | 
| 1690 | 
            +
            		return if @mark_blob[path] == new_mark_way ||
         | 
| 1691 | 
            +
            			(!MARK_WAYS.include?(new_mark_way) && !@mark_blob[path])
         | 
| 1692 | 
            +
            		if mw=@mark_blob[path]
         | 
| 1693 | 
            +
            			self.method("pixels_un"+mw).call(obj)
         | 
| 1694 | 
            +
            		end
         | 
| 1695 | 
            +
            		if MARK_WAYS.include?(new_mark_way)
         | 
| 1696 | 
            +
            			self.method("pixels_"+new_mark_way).call(obj)
         | 
| 1697 | 
            +
            			@mark_blob[path] = new_mark_way
         | 
| 1698 | 
            +
            		else
         | 
| 1699 | 
            +
            			@mark_blob.delete(path)
         | 
| 1700 | 
            +
            		end
         | 
| 1701 | 
            +
            		#$PDbgLog.sig_return
         | 
| 1702 | 
            +
            	end
         | 
| 1703 | 
            +
            	
         | 
| 1704 | 
            +
            	def save_img_obj(*objs)
         | 
| 1705 | 
            +
            		dialog = Gtk::FileChooserDialog.new("Save image object to file",
         | 
| 1706 | 
            +
            			nil, Gtk::FileChooser::ACTION_SAVE, "gnome-vfs",
         | 
| 1707 | 
            +
            			[Gtk::Stock::SAVE, Gtk::Dialog::RESPONSE_ACCEPT],
         | 
| 1708 | 
            +
            			[Gtk::Stock::CANCEL, Gtk::Dialog::RESPONSE_CANCEL])
         | 
| 1709 | 
            +
            		resp = dialog.run
         | 
| 1710 | 
            +
            		path = dialog.filename
         | 
| 1711 | 
            +
            		dialog.destroy
         | 
| 1712 | 
            +
            		return if resp != Gtk::Dialog::RESPONSE_ACCEPT
         | 
| 1713 | 
            +
            		if FileTest.exist?(path)
         | 
| 1714 | 
            +
            			dialog = Gtk::Dialog.new('Output File Exists',
         | 
| 1715 | 
            +
            				self, Gtk::Dialog::MODAL |
         | 
| 1716 | 
            +
            				Gtk::Dialog::DESTROY_WITH_PARENT,
         | 
| 1717 | 
            +
            				['_Replace', 0],
         | 
| 1718 | 
            +
            				['_Extend with new objects', 1],
         | 
| 1719 | 
            +
            				[Gtk::Stock::CANCEL, 2])
         | 
| 1720 | 
            +
            			hbox = Gtk::HBox.new(false, 0)
         | 
| 1721 | 
            +
            			hbox.set_border_width(8)
         | 
| 1722 | 
            +
            			dialog.vbox.pack_start(hbox, false, false, 0)
         | 
| 1723 | 
            +
            			hbox.pack_start(Gtk::Image.new(
         | 
| 1724 | 
            +
            			  Gtk::Stock::DIALOG_QUESTION, Gtk::IconSize::DIALOG),
         | 
| 1725 | 
            +
            			  false, false, 0)
         | 
| 1726 | 
            +
            			label = Gtk::Label.new
         | 
| 1727 | 
            +
            			label.markup = "File <b>#{path}</b> already exists."
         | 
| 1728 | 
            +
            			hbox.pack_start(label, false, false, 0)
         | 
| 1729 | 
            +
            			hbox.show_all
         | 
| 1730 | 
            +
            			resp = dialog.run
         | 
| 1731 | 
            +
            			dialog.destroy
         | 
| 1732 | 
            +
            			return if resp == 2
         | 
| 1733 | 
            +
            			mode = ['w', 'a'].at(resp)
         | 
| 1734 | 
            +
            		else
         | 
| 1735 | 
            +
            			mode = 'w'
         | 
| 1736 | 
            +
            		end
         | 
| 1737 | 
            +
            		begin
         | 
| 1738 | 
            +
            			open(path, mode) { |file| objs.each { |obj|
         | 
| 1739 | 
            +
            				self.write_img_obj(file, obj)
         | 
| 1740 | 
            +
            			}}
         | 
| 1741 | 
            +
            		rescue IOError
         | 
| 1742 | 
            +
            			self.show_exc_dialog
         | 
| 1743 | 
            +
            		end
         | 
| 1744 | 
            +
            	end
         | 
| 1745 | 
            +
            	
         | 
| 1746 | 
            +
            	def each_img_obj_with_details(obj, parent, attr_name, attr_key=nil,
         | 
| 1747 | 
            +
            	path="", excl_set={}, &block)
         | 
| 1748 | 
            +
            		#$PDbgLog.sig_call(self)
         | 
| 1749 | 
            +
            		#$PDbgLog.print_msg "path=#{path.inspect}: "
         | 
| 1750 | 
            +
            		obj.get_sub_img_objs(excl_set).each_pair { |name, val|
         | 
| 1751 | 
            +
            			#$PDbgLog.print_msg "#{name} "
         | 
| 1752 | 
            +
            			if val.kind_of?(PPix::ImageObject)
         | 
| 1753 | 
            +
            				self.each_img_obj_with_details(val,obj,name,nil,
         | 
| 1754 | 
            +
            					path+"/"+name.cap_first.gsub("_", " "),
         | 
| 1755 | 
            +
            					excl_set,&block)
         | 
| 1756 | 
            +
            			elsif val.kind_of?(Array)
         | 
| 1757 | 
            +
            				if name[-1,1] == "s"
         | 
| 1758 | 
            +
            					rname = name.singular.cap_first
         | 
| 1759 | 
            +
            				else
         | 
| 1760 | 
            +
            					rname = name.cap_first
         | 
| 1761 | 
            +
            				end
         | 
| 1762 | 
            +
            				rname.gsub!("_", " ")
         | 
| 1763 | 
            +
            				val.each_with_index { |v, i|
         | 
| 1764 | 
            +
            					self.each_img_obj_with_details(v, obj,
         | 
| 1765 | 
            +
            						name, i, path+"/#{rname} #{i}",
         | 
| 1766 | 
            +
            						excl_set, &block)
         | 
| 1767 | 
            +
            				}
         | 
| 1768 | 
            +
            			else
         | 
| 1769 | 
            +
            				warn "#{self.class.name
         | 
| 1770 | 
            +
            				  }.each_img_obj_with_details_: " +
         | 
| 1771 | 
            +
            				  "NotImplementError: Image object container " +
         | 
| 1772 | 
            +
            				  "of type #{val.class.name}; ignoring #{path
         | 
| 1773 | 
            +
            				  }/#{name}"
         | 
| 1774 | 
            +
            			end
         | 
| 1775 | 
            +
            		}
         | 
| 1776 | 
            +
            		yield(obj, parent, attr_name, attr_key, path)
         | 
| 1777 | 
            +
            		#$PDbgLog.sig_return
         | 
| 1778 | 
            +
            	end
         | 
| 1779 | 
            +
            	
         | 
| 1780 | 
            +
            	def ctxt_menu_m_cb(spec, widget)
         | 
| 1781 | 
            +
            		return true unless widget.active?
         | 
| 1782 | 
            +
            		obj, path = *spec
         | 
| 1783 | 
            +
            		mw = Gtk::ItemFactory.path_from_widget(widget)
         | 
| 1784 | 
            +
            		mw = mw['<root>/'.length...mw.length]
         | 
| 1785 | 
            +
            		#$PDbgLog.sig_call(self)
         | 
| 1786 | 
            +
            		#$PDbgLog.puts_msg("path=#{path.inspect}, mw=#{mw}")
         | 
| 1787 | 
            +
            		self.mark_blob_switch_obj(obj, path, mw)
         | 
| 1788 | 
            +
            		#$PDbgLog.sig_return
         | 
| 1789 | 
            +
            		true
         | 
| 1790 | 
            +
            	end
         | 
| 1791 | 
            +
            	
         | 
| 1792 | 
            +
            	def ctxt_menu_d_cb(spec, widget)
         | 
| 1793 | 
            +
            		obj,parent,parent_mfactory,attr_name,path,del_meth,del_args =
         | 
| 1794 | 
            +
            			*spec
         | 
| 1795 | 
            +
            		del_meth.call(*del_args)
         | 
| 1796 | 
            +
            		#$PDbgLog.sig_call(self)
         | 
| 1797 | 
            +
            		if obj.equal?(@blob)
         | 
| 1798 | 
            +
            			self.img_exit_blob
         | 
| 1799 | 
            +
            			self.del_blob
         | 
| 1800 | 
            +
            			@blob = nil
         | 
| 1801 | 
            +
            		else
         | 
| 1802 | 
            +
            			#$PDbgLog.puts_msg "obj: #{obj.object_id
         | 
| 1803 | 
            +
            			#  }, parent: #{parent.object_id}; marked: #{
         | 
| 1804 | 
            +
            			#  @pixbuf_marked_objs.collect { |o|
         | 
| 1805 | 
            +
            			#  o.object_id }.inspect }; blinking: #{
         | 
| 1806 | 
            +
            			#  @pixbuf_blinking_objs.collect { |o|
         | 
| 1807 | 
            +
            			#  o.object_id }.inspect }; traced: #{
         | 
| 1808 | 
            +
            			#  @pixbuf_traced_objs.collect { |o| o.object_id
         | 
| 1809 | 
            +
            			#  }.inspect }"
         | 
| 1810 | 
            +
            			#$PDbgLog.puts_msg(path)
         | 
| 1811 | 
            +
            			pos = nil
         | 
| 1812 | 
            +
            			item = nil
         | 
| 1813 | 
            +
            			parent_menu = parent_mfactory.get_widget('<root>')
         | 
| 1814 | 
            +
            			if obj.kind_of?(Array) || obj.kind_of?(Hash)
         | 
| 1815 | 
            +
            			  dtext = 'Delete ' + attr_name.gsub('_', ' ')
         | 
| 1816 | 
            +
            			  parent_menu.children.each_with_index { |item, pos|
         | 
| 1817 | 
            +
            				next unless (text = item.children[0])
         | 
| 1818 | 
            +
            				text = text.text
         | 
| 1819 | 
            +
            				break if text == dtext
         | 
| 1820 | 
            +
            			  }
         | 
| 1821 | 
            +
            			  parent_menu.remove(item); item.destroy
         | 
| 1822 | 
            +
            			  aname=attr_name.cap_first; aname.gsub!('_',' ')
         | 
| 1823 | 
            +
            			  aname = (aname[-1,1] == 's' ? aname.singular : aname)
         | 
| 1824 | 
            +
            			  aname.concat(' ')
         | 
| 1825 | 
            +
            			  p = parent_menu.children.length
         | 
| 1826 | 
            +
            			  while (p -= 1) >= 0
         | 
| 1827 | 
            +
            			  	i = parent_menu.children.at(p)
         | 
| 1828 | 
            +
            				next unless (text = i.children[0])
         | 
| 1829 | 
            +
            				text = text.text
         | 
| 1830 | 
            +
            			  	self.mark_blob_switch_obj(obj, path+'/'+text,
         | 
| 1831 | 
            +
            					"None")
         | 
| 1832 | 
            +
            				if text.starts_with(aname)
         | 
| 1833 | 
            +
            					pos = p
         | 
| 1834 | 
            +
            					parent_menu.remove(i); i.destroy
         | 
| 1835 | 
            +
            				end
         | 
| 1836 | 
            +
            			  end
         | 
| 1837 | 
            +
            			  if obj.kind_of?(Array)
         | 
| 1838 | 
            +
            				obj.each { |o| @blob.extract_curves_args[
         | 
| 1839 | 
            +
            				  'ctxt_menu_known_objs'].delete(o.object_id) }
         | 
| 1840 | 
            +
            			  else
         | 
| 1841 | 
            +
            				obj.each_value { |o| @blob.extract_curves_args[
         | 
| 1842 | 
            +
            				  'ctxt_menu_known_objs'].delete(o.object_id) }
         | 
| 1843 | 
            +
            			  end
         | 
| 1844 | 
            +
            			  epath = path
         | 
| 1845 | 
            +
            			else
         | 
| 1846 | 
            +
            			  self.mark_blob_switch_obj(obj, path, "None")
         | 
| 1847 | 
            +
            			  parent_menu.children.each_with_index { |item, pos|
         | 
| 1848 | 
            +
            				submenu = item.submenu
         | 
| 1849 | 
            +
            				break if submenu && submenu.children.detect{|ch|
         | 
| 1850 | 
            +
            					ch.object_id == widget.object_id }
         | 
| 1851 | 
            +
            			  }
         | 
| 1852 | 
            +
            			  @blob.extract_curves_args['ctxt_menu_known_objs'].
         | 
| 1853 | 
            +
            				delete(obj.object_id)
         | 
| 1854 | 
            +
            			  parent_menu.remove(item); item.destroy
         | 
| 1855 | 
            +
            			  epath = path[0, path.rindex('/')]
         | 
| 1856 | 
            +
            			end
         | 
| 1857 | 
            +
            			m = attr_name.cap_first; m.gsub!('_', ' ')
         | 
| 1858 | 
            +
            			parent_mfactory.create_item('/'+m, '<StockItem>', nil,
         | 
| 1859 | 
            +
            			  Gtk::Stock::EXECUTE, [parent, attr_name, epath,
         | 
| 1860 | 
            +
            			  parent_mfactory], &@ctxt_menu_e_cb)
         | 
| 1861 | 
            +
            			item = parent_mfactory.get_widget('/'+m)
         | 
| 1862 | 
            +
            			parent_menu.remove(item)
         | 
| 1863 | 
            +
            			parent_menu.insert(item, pos)
         | 
| 1864 | 
            +
            		end
         | 
| 1865 | 
            +
            		#$PDbgLog.sig_return
         | 
| 1866 | 
            +
            		true
         | 
| 1867 | 
            +
            	end
         | 
| 1868 | 
            +
            	
         | 
| 1869 | 
            +
            	def ctxt_menu_s_cb(obj, widget)
         | 
| 1870 | 
            +
            		path = Gtk::ItemFactory.path_from_widget(widget)
         | 
| 1871 | 
            +
            		self.save_img_obj(obj)
         | 
| 1872 | 
            +
            		true
         | 
| 1873 | 
            +
            	end
         | 
| 1874 | 
            +
            	
         | 
| 1875 | 
            +
            	def ctxt_menu_e_cb(spec, widget)
         | 
| 1876 | 
            +
            		pobj, attr_name, path, parent_mfactory = *spec
         | 
| 1877 | 
            +
            		self.remove_timeouts
         | 
| 1878 | 
            +
            		val = pobj.method(attr_name).call
         | 
| 1879 | 
            +
            		self.add_timeouts
         | 
| 1880 | 
            +
            		if @blob.extract_curves_args['ctxt_menu_known_objs'].include?(
         | 
| 1881 | 
            +
            		val.object_id)
         | 
| 1882 | 
            +
            			subitems = []
         | 
| 1883 | 
            +
            		elsif val.kind_of?(PPix::ImageObject)
         | 
| 1884 | 
            +
            			aname=attr_name.cap_first; aname.gsub!('_',' ')
         | 
| 1885 | 
            +
            			subitems = [Gtk::MenuItem.new(aname)]
         | 
| 1886 | 
            +
            			subitems[0].submenu=self.img_obj_mk_ctxt_menu(val, pobj,
         | 
| 1887 | 
            +
            			  parent_mfactory, path + '/' + aname, attr_name, nil)
         | 
| 1888 | 
            +
            			@blob.extract_curves_args['ctxt_menu_known_objs'] <<
         | 
| 1889 | 
            +
            				val.object_id
         | 
| 1890 | 
            +
            		elsif val.kind_of?(Array)
         | 
| 1891 | 
            +
            		  if !val.empty? &&
         | 
| 1892 | 
            +
            		  val.first.kind_of?(PPix::ImageObject)
         | 
| 1893 | 
            +
            			subitems = []
         | 
| 1894 | 
            +
            			aname=attr_name.cap_first; aname.gsub!('_',' ')
         | 
| 1895 | 
            +
            			aname = (aname[-1,1] == 's' ? aname.singular :
         | 
| 1896 | 
            +
            				aname)
         | 
| 1897 | 
            +
            			pfx = path + '/' + aname
         | 
| 1898 | 
            +
            			val.each_with_index { |obj, i| next if obj.empty?
         | 
| 1899 | 
            +
            			  item = Gtk::MenuItem.new(aname + " #{i}")
         | 
| 1900 | 
            +
            			  item.submenu = self.img_obj_mk_ctxt_menu(obj, pobj,
         | 
| 1901 | 
            +
            			    parent_mfactory, pfx + " #{i}", attr_name, i)
         | 
| 1902 | 
            +
            			  subitems << item
         | 
| 1903 | 
            +
            			  @blob.extract_curves_args['ctxt_menu_known_objs'] <<
         | 
| 1904 | 
            +
            				obj.object_id
         | 
| 1905 | 
            +
            			}
         | 
| 1906 | 
            +
            			if pobj.methods.include?(dmeth="delete_"+attr_name)
         | 
| 1907 | 
            +
            				parent_mfactory.create_item(text='/Delete '+
         | 
| 1908 | 
            +
            				  attr_name.gsub('_', ' '), '<StockItem>', '',
         | 
| 1909 | 
            +
            				  Gtk::Stock::DELETE, [val, pobj,
         | 
| 1910 | 
            +
            				  parent_mfactory, attr_name, path,
         | 
| 1911 | 
            +
            				  pobj.method(dmeth), []], &@ctxt_menu_d_cb)
         | 
| 1912 | 
            +
            				item = parent_mfactory.get_widget('<root>'+text)
         | 
| 1913 | 
            +
            				parent_menu=parent_mfactory.get_widget('<root>')
         | 
| 1914 | 
            +
            				parent_menu.remove(item)
         | 
| 1915 | 
            +
            				pos = parent_menu.children.length
         | 
| 1916 | 
            +
            				parent_menu.children.reverse_each { |i|
         | 
| 1917 | 
            +
            					pos -= 1
         | 
| 1918 | 
            +
            					break if i.gtype ==
         | 
| 1919 | 
            +
            					  GLib::Type['GtkRadioMenuItem']
         | 
| 1920 | 
            +
            				}
         | 
| 1921 | 
            +
            				parent_menu.insert(item, pos-MARK_WAYS.length-1)
         | 
| 1922 | 
            +
            			end
         | 
| 1923 | 
            +
            		  end
         | 
| 1924 | 
            +
            		elsif val.kind_of?(Hash)
         | 
| 1925 | 
            +
            		  unless val.empty?
         | 
| 1926 | 
            +
            		   flag = false
         | 
| 1927 | 
            +
            		   val.each_value { |v|
         | 
| 1928 | 
            +
            			flag=v.kind_of?(PPix::ImageObject); break }
         | 
| 1929 | 
            +
            		   if flag
         | 
| 1930 | 
            +
            			subitems = []
         | 
| 1931 | 
            +
            			aname=attr_name.cap_first; aname.gsub!('_',' ')
         | 
| 1932 | 
            +
            			aname = (aname[-1,1] == 's' ? aname.singular :
         | 
| 1933 | 
            +
            				aname)
         | 
| 1934 | 
            +
            			pfx = path + '/' + aname
         | 
| 1935 | 
            +
            			val.each_pair { |key, obj| next if obj.empty?
         | 
| 1936 | 
            +
            			  item = Gtk::MenuItem.new(aname + " #{key}")
         | 
| 1937 | 
            +
            			  item.submenu = self.img_obj_mk_ctxt_menu(obj, pobj,
         | 
| 1938 | 
            +
            			    parent_mfactory, pfx + " #{key}", attr_name, key)
         | 
| 1939 | 
            +
            			  subitems << item
         | 
| 1940 | 
            +
            			  @blob.extract_curves_args['ctxt_menu_known_objs'] <<
         | 
| 1941 | 
            +
            				obj.object_id
         | 
| 1942 | 
            +
            			}
         | 
| 1943 | 
            +
            			if pobj.methods.include?(dmeth="delete_"+attr_name)
         | 
| 1944 | 
            +
            				parent_mfactory.create_item(text='/Delete '+
         | 
| 1945 | 
            +
            				  attr_name.gsub('_', ' '), '<StockItem>', '',
         | 
| 1946 | 
            +
            				  Gtk::Stock::DELETE, [val, pobj,
         | 
| 1947 | 
            +
            				  parent_mfactory, attr_name, path,
         | 
| 1948 | 
            +
            				  pobj.method(dmeth), []], &@ctxt_menu_d_cb)
         | 
| 1949 | 
            +
            				item = parent_mfactory.get_widget('<root>'+text)
         | 
| 1950 | 
            +
            				parent_menu=parent_mfactory.get_widget('<root>')
         | 
| 1951 | 
            +
            				parent_menu.remove(item)
         | 
| 1952 | 
            +
            				pos = parent_menu.children.length
         | 
| 1953 | 
            +
            				parent_menu.children.reverse_each { |i|
         | 
| 1954 | 
            +
            					pos -= 1
         | 
| 1955 | 
            +
            					break if i.gtype ==
         | 
| 1956 | 
            +
            					  GLib::Type['GtkRadioMenuItem']
         | 
| 1957 | 
            +
            				}
         | 
| 1958 | 
            +
            				parent_menu.insert(item, pos-MARK_WAYS.length-1)
         | 
| 1959 | 
            +
            			end
         | 
| 1960 | 
            +
            		   end
         | 
| 1961 | 
            +
            		  end
         | 
| 1962 | 
            +
            		end
         | 
| 1963 | 
            +
            		pos = nil
         | 
| 1964 | 
            +
            		item = nil
         | 
| 1965 | 
            +
            		parent_menu = parent_mfactory.get_widget('<root>')
         | 
| 1966 | 
            +
            		parent_menu.children.each_with_index { |item, pos|
         | 
| 1967 | 
            +
            			break if item.object_id == widget.object_id }
         | 
| 1968 | 
            +
            		parent_menu.remove(item)
         | 
| 1969 | 
            +
            		item.destroy
         | 
| 1970 | 
            +
            		if subitems
         | 
| 1971 | 
            +
            			subitems.reverse.each { |item|
         | 
| 1972 | 
            +
            				parent_menu.insert(item, pos)
         | 
| 1973 | 
            +
            				item.show_all
         | 
| 1974 | 
            +
            			}
         | 
| 1975 | 
            +
            		end
         | 
| 1976 | 
            +
            	end
         | 
| 1977 | 
            +
            	
         | 
| 1978 | 
            +
            	def img_obj_mk_ctxt_menu(obj, parent, parent_mfactory, path, attr_name,
         | 
| 1979 | 
            +
            	attr_key)
         | 
| 1980 | 
            +
            		#$PDbgLog.sig_call(self)
         | 
| 1981 | 
            +
            		#$PDbgLog.print_msg "path=#{path.inspect}: "
         | 
| 1982 | 
            +
            		mfactory = Gtk::ItemFactory.new(Gtk::ItemFactory::TYPE_MENU,
         | 
| 1983 | 
            +
            			'<root>', nil)
         | 
| 1984 | 
            +
            		meths = obj.img_obj_possible_sub_obj_meths unless
         | 
| 1985 | 
            +
            			(meths = obj.class.img_obj_sub_obj_meths)
         | 
| 1986 | 
            +
            		menu = mfactory.get_widget('<root>')
         | 
| 1987 | 
            +
            		unless meths.empty?
         | 
| 1988 | 
            +
            			meths.each { |meth|
         | 
| 1989 | 
            +
            				m = meth.cap_first; m.gsub!('_', ' ')
         | 
| 1990 | 
            +
            				mfactory.create_item('/'+m, '<StockItem>', nil,
         | 
| 1991 | 
            +
            				  Gtk::Stock::EXECUTE, [obj,meth,path,mfactory],
         | 
| 1992 | 
            +
            				  &@ctxt_menu_e_cb)
         | 
| 1993 | 
            +
            			}
         | 
| 1994 | 
            +
            			mfactory.create_item('/sep1', '<Separator>')
         | 
| 1995 | 
            +
            		end
         | 
| 1996 | 
            +
            		mw = MARK_WAYS[0]
         | 
| 1997 | 
            +
            		mfactory.create_item('/_'+mw.cap_first,
         | 
| 1998 | 
            +
            			'<RadioItem>', nil, nil, [obj, path], &@ctxt_menu_m_cb)
         | 
| 1999 | 
            +
            		fpath = '/' + mw.cap_first
         | 
| 2000 | 
            +
            		MARK_WAYS[1, MARK_WAYS.length].each { |mw|
         | 
| 2001 | 
            +
            			mfactory.create_item('/_' + mw.cap_first, fpath,
         | 
| 2002 | 
            +
            				nil, nil, [obj, path], &@ctxt_menu_m_cb)
         | 
| 2003 | 
            +
            		}
         | 
| 2004 | 
            +
            		mfactory.create_item('/_None', fpath,
         | 
| 2005 | 
            +
            			nil, nil, [obj, path], &@ctxt_menu_m_cb)
         | 
| 2006 | 
            +
            		cur_mw = @mark_blob[path] || 'none'
         | 
| 2007 | 
            +
            		mfactory.get_widget('/'+cur_mw.cap_first).activate
         | 
| 2008 | 
            +
            		mfactory.create_item('/sep2', '<Separator>')
         | 
| 2009 | 
            +
            		if attr_key
         | 
| 2010 | 
            +
            		  if parent.methods.include?(dmeth="delete_"+attr_name.singular)
         | 
| 2011 | 
            +
            			mfactory.create_item('/_Delete', '<StockItem>', nil,
         | 
| 2012 | 
            +
            			  Gtk::Stock::DELETE, [obj,parent,parent_mfactory,
         | 
| 2013 | 
            +
            			    attr_name,path,parent.method(dmeth),[attr_key]],
         | 
| 2014 | 
            +
            			  &@ctxt_menu_d_cb)
         | 
| 2015 | 
            +
            		  end
         | 
| 2016 | 
            +
            		elsif parent.methods.include?(dmeth="delete_"+attr_name)
         | 
| 2017 | 
            +
            			mfactory.create_item('/_Delete', '<StockItem>', nil,
         | 
| 2018 | 
            +
            			  Gtk::Stock::DELETE, [obj,parent,parent_mfactory,
         | 
| 2019 | 
            +
            			    attr_name,path,parent.method(dmeth),[]],
         | 
| 2020 | 
            +
            			  &@ctxt_menu_d_cb)
         | 
| 2021 | 
            +
            		end
         | 
| 2022 | 
            +
            		mfactory.create_item('/_Save', '<StockItem>', '',
         | 
| 2023 | 
            +
            			Gtk::Stock::SAVE, obj, &@ctxt_menu_s_cb)
         | 
| 2024 | 
            +
            		mfactory.get_widget('<root>')
         | 
| 2025 | 
            +
            		#$PDbgLog.sig_return
         | 
| 2026 | 
            +
            	end
         | 
| 2027 | 
            +
            	
         | 
| 2028 | 
            +
            	def img_get_context_menu
         | 
| 2029 | 
            +
            		return nil unless @blob
         | 
| 2030 | 
            +
            		tmp = @blob.extract_curves_args['ctxt_menu']
         | 
| 2031 | 
            +
            		return tmp if tmp
         | 
| 2032 | 
            +
            		$PDbgLog.sig_call(self)
         | 
| 2033 | 
            +
            		tmp = @blob.extract_curves_args['ctxt_menu'] =
         | 
| 2034 | 
            +
            			self.img_obj_mk_ctxt_menu(@blob, @pixbuf, nil, "",
         | 
| 2035 | 
            +
            				"blob", @blob)
         | 
| 2036 | 
            +
            		item = Gtk::MenuItem.new("Blob #{@blob.blob_id}:")
         | 
| 2037 | 
            +
            		item.sensitive = false
         | 
| 2038 | 
            +
            		tmp.prepend(item)
         | 
| 2039 | 
            +
            		$PDbgLog.sig_return
         | 
| 2040 | 
            +
            		tmp
         | 
| 2041 | 
            +
            	end
         | 
| 2042 | 
            +
            	
         | 
| 2043 | 
            +
            	def img_pop_context_menu
         | 
| 2044 | 
            +
            	  menu = nil
         | 
| 2045 | 
            +
            	  #@job = Thread.new(Thread.current) {
         | 
| 2046 | 
            +
            	#	Thread.stop
         | 
| 2047 | 
            +
            	#	$PDbgLog.sig_call(self)
         | 
| 2048 | 
            +
            		menu = self.img_get_context_menu
         | 
| 2049 | 
            +
            	#	$PDbgLog.sig_return("OK")
         | 
| 2050 | 
            +
            	  #}
         | 
| 2051 | 
            +
            	  #@job.run
         | 
| 2052 | 
            +
            	  #Thread.pass while @job.alive?
         | 
| 2053 | 
            +
            		return unless menu
         | 
| 2054 | 
            +
            		$PDbgLog.sig_call(self)
         | 
| 2055 | 
            +
            		#$PDbgLog.puts_msg "#{(menu.methods.sort - Object.methods).
         | 
| 2056 | 
            +
            		#	join("\n")}"
         | 
| 2057 | 
            +
            		menu.visible = true
         | 
| 2058 | 
            +
            		menu.activate
         | 
| 2059 | 
            +
            		menu.parent.modal = true
         | 
| 2060 | 
            +
            		menu.parent.window_position = Gtk::Window::POS_MOUSE
         | 
| 2061 | 
            +
            		menu.parent.show_all
         | 
| 2062 | 
            +
            		menu.grab_focus
         | 
| 2063 | 
            +
            		
         | 
| 2064 | 
            +
            		while menu.visible?
         | 
| 2065 | 
            +
            			Gtk.main_iteration
         | 
| 2066 | 
            +
            		end
         | 
| 2067 | 
            +
            		#menu.destroy
         | 
| 2068 | 
            +
            		@scrl_win.queue_draw
         | 
| 2069 | 
            +
            		$PDbgLog.sig_return("Done.")
         | 
| 2070 | 
            +
            	end
         | 
| 2071 | 
            +
            	
         | 
| 2072 | 
            +
            	def img_button_press_cb(drw_area, event)
         | 
| 2073 | 
            +
            		#$PDbgLog.sig_call(self)
         | 
| 2074 | 
            +
            		unless @in_progr.try_lock
         | 
| 2075 | 
            +
            			#$PDbgLog.sig_return(false)
         | 
| 2076 | 
            +
            			return false
         | 
| 2077 | 
            +
            		end
         | 
| 2078 | 
            +
            		case event.button
         | 
| 2079 | 
            +
            		  when 1 then self.img_get_objs_at(drw_area, event)
         | 
| 2080 | 
            +
            		  when 3 then self.img_pop_context_menu
         | 
| 2081 | 
            +
            		end
         | 
| 2082 | 
            +
            		@in_progr.unlock
         | 
| 2083 | 
            +
            		#$PDbgLog.sig_return(true)
         | 
| 2084 | 
            +
            		return true
         | 
| 2085 | 
            +
            	end
         | 
| 2086 | 
            +
            	
         | 
| 2087 | 
            +
            	def about_cb(*args)
         | 
| 2088 | 
            +
            		authors = ["Pavel Penev <pavpen@berkeley.edu>"]
         | 
| 2089 | 
            +
            		documentors = []
         | 
| 2090 | 
            +
            		license = %Q[
         | 
| 2091 | 
            +
            This program is free software; you can redistribute it and/or
         | 
| 2092 | 
            +
            modify it under the terms of the GNU General Public License as
         | 
| 2093 | 
            +
            published by the Free Software Foundation; either version 2 of the
         | 
| 2094 | 
            +
            License, or (at your option) any later version.
         | 
| 2095 | 
            +
             | 
| 2096 | 
            +
            This program is distributed in the hope that it will be useful,
         | 
| 2097 | 
            +
            but WITHOUT ANY WARRANTY; without even the implied warranty of
         | 
| 2098 | 
            +
            MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
         | 
| 2099 | 
            +
            General Public License for more details.
         | 
| 2100 | 
            +
             | 
| 2101 | 
            +
            You should have received a copy of the GNU General Public
         | 
| 2102 | 
            +
            License along with the Gnome Library; see the file COPYING.LIB.  If not,
         | 
| 2103 | 
            +
            write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
         | 
| 2104 | 
            +
            Boston, MA 02111-1307, USA.
         | 
| 2105 | 
            +
            ]
         | 
| 2106 | 
            +
            		transparent = Gdk::Pixbuf.new(PGtk.find_icon_file(
         | 
| 2107 | 
            +
            			"pav/icons/extract_curves/extract_curves-logo-rgb.gif"))
         | 
| 2108 | 
            +
            			#.add_alpha(true, 0xff, 0xff, 0xff)
         | 
| 2109 | 
            +
            		
         | 
| 2110 | 
            +
            		Gtk::AboutDialog.set_email_hook {|about, link|
         | 
| 2111 | 
            +
            			puts "send mail to #{link}"
         | 
| 2112 | 
            +
            		}
         | 
| 2113 | 
            +
            		Gtk::AboutDialog.set_url_hook {|about, link|
         | 
| 2114 | 
            +
            			puts "show url #{link}"
         | 
| 2115 | 
            +
            		}
         | 
| 2116 | 
            +
            		Gtk::AboutDialog.show(self,
         | 
| 2117 | 
            +
            			:name => "Extract Curves",
         | 
| 2118 | 
            +
            			:version => VERSION.join(".") + VERSION_SUFFIX,
         | 
| 2119 | 
            +
            			:copyright => "(C) 2005 Pavel Minev Penev",
         | 
| 2120 | 
            +
            			:license => license,
         | 
| 2121 | 
            +
            			#:website => "http://www.gtk.org",
         | 
| 2122 | 
            +
            			:comments => "Program to identify the specific " +
         | 
| 2123 | 
            +
            				"characteristics of a motion which produced a "+
         | 
| 2124 | 
            +
            				"geometric curve.",
         | 
| 2125 | 
            +
            			:authors => authors,
         | 
| 2126 | 
            +
            			#:documenters => documentors,
         | 
| 2127 | 
            +
            			:logo => transparent)
         | 
| 2128 | 
            +
            	end
         | 
| 2129 | 
            +
            end
         | 
| 2130 | 
            +
             | 
| 2131 | 
            +
            if ARGV[0]
         | 
| 2132 | 
            +
              case ARGV[0]
         | 
| 2133 | 
            +
                when '--version'
         | 
| 2134 | 
            +
            	puts ExtractCurvesApp::VERSION.join('.')
         | 
| 2135 | 
            +
            	exit 0
         | 
| 2136 | 
            +
                when '--file-path'
         | 
| 2137 | 
            +
            	puts File.expand_path(__FILE__)
         | 
| 2138 | 
            +
            	exit 0
         | 
| 2139 | 
            +
              end
         | 
| 2140 | 
            +
            end
         | 
| 2141 | 
            +
            #PApp.new(ExtractCurvesApp).run
         | 
| 2142 | 
            +
            app_win = ExtractCurvesApp.new
         | 
| 2143 | 
            +
            app_win.show_all
         | 
| 2144 | 
            +
            app_win.open_imagef(ARGV[0]) if ARGV[0]
         | 
| 2145 | 
            +
            Gtk.main
         |