#!/usr/bin/env ruby

tmp = $LOAD_PATH.dup
$LOAD_PATH[0] = File.dirname($0)
tmp.length.times{|i| $LOAD_PATH[i+1] = tmp[i]}

$VERBOSE = nil

begin
  require "rubygems"
rescue
end

require "numru/gphys"
require "numru/gave/gave_config"
require "numru/gave/draw"

argv = ARGV

device = "dcl"
device = "vtk" if argv.delete("--with-vtk")
device = "dcl" if argv.delete("--with-dcl")

if device == "dcl"
  require "numru/gave/draw_dcl"
elsif device == "vtk"
  require "numru/gave/draw_vtk"
end



GAVE_VERSION = "1.2.1"
HP_URL_JA = "http://www.gfd-dennou.org/arch/ruby/products/gave/index-j.html"
HP_URL_EN = "http://www.gfd-dennou.org/arch/ruby/products/gave/index.html"

begin
  require "gettext"
  include GetText
  gettext_path = DATA_PATH+"/locale"
  bindtextdomain("gave",gettext_path,nil,charset="UTF-8")
rescue LoadError
  def _(str) str end
  class Locale
    def get; "C"; end
  end
end

module NumRu
  class GPhys
    alias :_initialize :initialize
    def initialize(*arg)
      _initialize(*arg)
      @funcs = Array.new
    end
    alias_method( "_slice".intern, "[]".intern)
    def [](*slicer)
      obj = self._slice(*slicer)
      obj.funcs = self.funcs
      return obj
    end
    alias :_cut :cut
    def cut(*args)
      obj = self._cut(*args)
      obj.funcs = self.funcs
      return obj
    end
    alias :_cyclic_ext :cyclic_ext
    def cyclic_ext(dim,modulo)
      obj = self._cyclic_ext(dim,modulo)
      obj.funcs = self.funcs
      return obj
    end
    def funcs
      @funcs.dup
    end
    attr_writer :funcs
  end
end

include NumRu


if GAVE_GTK_VERSION == 1
  require "gtk"
  require "gdk_pixbuf"
  module Gtk
    class Widget
      def set_size_request(*arg); set_usize(*arg); end
      def set_resizable(tf); set_policy(tf,tf,tf); end
      def set_resizable_and_shrink(tfr,tfs); set_policy(tfs,tfr,tfr); end
    end
    class Window
      def active?
	!visible?
      end
      def add_accel_group(accel)
	accel.attach(self)
      end
    end
    class Entry
      def text; get_text; end
      def text=(str); set_text(str.to_s); end
    end
    class ToggleButton
      def add_xpm(xpm, window)
	pix, mask = Gdk::Pixmap.create_from_xpm_d(window, nil, xpm)
	pixmap = Gtk::Pixmap.new(pix, mask)
	self.add(pixmap)
      end
    end
    class Label
      def selectable=(dummy) end
      def justify=(arg) set_justify(arg) end
      def wrap=(arg) set_line_wrap(arg) end
    end
    class Justification
      CENTER = Gtk::JUSTIFY_CENTER
    end
    class ItemFactory
      STOCK_ITEM = ITEM
      alias _create_items create_items
      def create_items(ary)
	ary2 = ary.collect{|a| [ a[0], a[2], a[1], a[4], a[5] ] }
        _create_items(ary2)
      end
      alias _create_item create_item
      def create_item(*ary,&proc)
        _create_item(ary[0],ary[2],ary[1],&Proc.new{|w| proc.call(ary[4],w)})
      end
    end
    class Stock
      OPEN = nil
      SAVE = nil
      QUIT = nil
    end
    class FileSelection
      def set_select_multiple(dummy); self; end
      def selections; [filename]; end
    end
  end
  class List
    def initialize
      @clist = Gtk::CList.new([_("name"),_("value")])
      @clist.set_usize(300,200)
      @clist.set_column_width(0,100)
    end
    def set_item(name, value)
      @clist.append([name, value])
    end
    def add_note(note, title)
      sw = Gtk::ScrolledWindow.new(nil,nil)
      sw.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC)
      sw.add(@clist.show)
      note.append_page_menu(sw.show, Gtk::Label.new(title), Gtk::Label.new(title))
    end
  end
  TOPLEVEL = Gtk::WINDOW_TOPLEVEL

elsif GAVE_GTK_VERSION ==2
  require "gtk2"
  require "numru/gave/fileselection"
  if defined?(DFileSelection)
    class DRbObject
      alias :_initialize :initialize
      def initialize(*arg)
        _initialize(*arg)
        @funcs = Array.new
      end
      def funcs
        @funcs.dup
      end
      attr_writer :funcs
    end
  end

  module Gtk
    class Widget
      def set_resizable_and_shrink(tfr,tfs); set_resizable(tfr).set_allow_shrink(false); end
    end
    class ToggleButton
      def add_xpm(xpm, dummy)
	image = Gtk::Image.new(Gdk::Pixbuf.new(xpm))
	self.add(image)
      end
    end
  end
  class List
    def initialize
      @model = Gtk::ListStore.new(String, String)
    end
    def set_item(name, value)
      iter = @model.append
      iter[0] = name
      iter[1] = value
    end
    def add_note(note, title)
      treeview = Gtk::TreeView.new(@model)
      treeview.append_column(Gtk::TreeViewColumn.new("name", Gtk::CellRendererText.new, {:text => 0}))
      treeview.append_column(Gtk::TreeViewColumn.new("value", Gtk::CellRendererText.new, {:text => 1}))
      sw = Gtk::ScrolledWindow.new(nil,nil)
      sw.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC)
      sw.add(treeview.show)
      note.append_page(sw.show, Gtk::Label.new(title))
    end
  end
  TOPLEVEL = Gtk::Window::TOPLEVEL
  Gtk.init
end


class Select_value
  attr_reader :index, :box
  def initialize(val)
    height=20
    @val = val
    @max = val.length-1
    @index = 0
    entry = Gtk::Entry.new
    entry.set_size_request(50,height)
    entry.set_editable(false)
    entry.set_text(val[0].to_s)
    @adjustment = Gtk::Adjustment.new(0,0,@max+1,1,10,1)
    @adjustment.signal_connect("value-changed"){|w|
      @index=w.value.round
      entry.set_text(val[@index].to_s)
    }
    @scale = Gtk::HScale::new(@adjustment)
    @scale.set_size_request(150,height)
    @scale.set_draw_value(false)
    @box = Gtk::HBox.new(false,0)
    @box.pack_start(entry, true, true, 0 )
    @box.pack_start(@scale)
    @box.set_sensitive(false)
  end
  def active; @box.set_sensitive(true); end
  def not_active; @box.set_sensitive(false); end
  def next
    if @index < @max then
      @adjustment.value = @index+1
    else
      @adjustment.value = 0
    end      
  end
  def val
    @val
  end
end

class Var_select < Gtk::Combo
  def initialize
    super
    entry.set_editable(false)
    not_active
  end
  def get; entry.text; end
  def set(array); set_popdown_strings(array); end
  def set_text(text); entry.text=text; end
  def active; set_sensitive(true); end
  def not_active
    set_sensitive(false)
    entry.set_text(_("cannot select"))
  end
  def signal; entry.signal_connect("changed"){yield};  end
#  def signal; entry.signal_connect("activate"){yield};  end
end


# draw tyep constant
LINE = 0
CONTOUR = 1
#MAP = 2
VECTOR = 3
SURFACE = 4

FUNC = 10
Funcs1 = ["mean","stddev","max","min"]
SFunc  = {"mean"=>_("mean"),"stddev"=>_("stddev"),"max"=>_("max"),"min"=>_("min")}

class String
  alias :_to_f :to_f
  def to_f
    if self==""
      return false
    else
      return self._to_f
    end
  end
end

class GAVE

  def min(x,y)
    x<y ? x : y
  end
  def max(x,y)
    x>y ? x : y
  end

  attr_accessor :autodraw
  def initialize(device)
    @autodraw = false

    @vars = Hash.new
    @dims = Hash.new

    accel = Gtk::AccelGroup.new

# FileSelection
    fs = Gtk::FileSelection.new("")
    fs.ok_button.signal_connect("clicked"){|w|
      fs.hide
      @filecall.call(fs.selections)
    }
    fs.cancel_button.signal_connect("clicked"){fs.hide}

    if defined?(DFileSelection)
      dfs = DFileSelection.new("Open druby")
      dfs.ok_button.signal_connect("clicked"){|w|
        dfs.hide
        file_open(dfs.selection)
      }
    end

# sub windows
    @subwindows = Array.new
    var_window = Gtk::Window.new(TOPLEVEL).set_title(_("Variable")).set_resizable(false)
    @subwindows.push var_window
    axis_window = Gtk::Window.new(TOPLEVEL).set_title(_("Axis")).set_resizable(false)
    @subwindows.push axis_window
    @dims_window = Gtk::Window.new(TOPLEVEL).set_title(_("Dimensions")).set_resizable(false) #set_policy(false,false,true)
    @subwindows.push @dims_window
    attr_window = Gtk::Window.new(TOPLEVEL).set_title(_("Attributes")).set_resizable_and_shrink(true,false) #set_policy(false,true,false)
    @subwindows.push attr_window
    movie_window = Gtk::Window.new(TOPLEVEL).set_title(_("Movie")).set_resizable(false)
    @subwindows.push movie_window
    map_window = Gtk::Window.new(TOPLEVEL).set_title(_("Map")).set_resizable(false)
    @subwindows.push map_window
    cont_window = Gtk::Window.new(TOPLEVEL).set_title(_("Parameter for Contour and Tone")).set_resizable(false)
    @subwindows.push cont_window
    vector_window = Gtk::Window.new(TOPLEVEL).set_title(_("Parameter for Vector")).set_resizable(false)
    @subwindows.push vector_window
    div_window = Gtk::Window.new(TOPLEVEL).set_title(_("Division")).set_resizable(false)
    @subwindows.push div_window
    if device == "vtk"
      surface_window = Gtk::Window.new(TOPLEVEL).set_title(_("Isovalue Surface")).set_resizable(false)
      @subwindows.push surface_window
    end
    p_w = Proc.new{|c,w| c.set_active(false); w.hide }
    var_window.signal_connect("delete-event"){|w,e| p_w.call(@check_var,w) }
    axis_window.signal_connect("delete-event"){|w,e| p_w.call(@check_axis,w) }
    @dims_window.signal_connect("delete-event"){|w,e| p_w.call(@check_dims,w) }
    attr_window.signal_connect("delete-event"){|w,e| p_w.call(@check_attr,w) }
    movie_window.signal_connect("delete-event"){|w,e| p_w.call(@check_movie,w) }
    map_window.signal_connect("delete-event"){|w,e| p_w.call(@check_map,w) }
    cont_window.signal_connect("delete-event"){|w,e| p_w.call(@check_level,w) }
    vector_window.signal_connect("delete-event"){|w,e| p_w.call(@check_vector,w) }
    if @device == "vtk"
      surface_window.signal_connect("delete-event"){|w,e| p_w.call(@check_surface,w) }
    end
    div_window.signal_connect("delete-event"){|w,e| p_w.call(@check_div,w) }

# Variable window
    @title_entry = Gtk::Entry.new
    @miss_entry = Gtk::Entry.new
    table = Gtk::Table.new(2,2,false)
    table.attach(Gtk::Label.new(_("title")),0,1,0,1)
    table.attach(@title_entry,1,2,0,1)
#    table.attach(Gtk::Label.new(_("missing value")),0,1,1,2)
#    table.attach(@miss_entry,1,2,1,2)
    var_window.add(table.show_all)

# Axis window
    @logxbutton = Gtk::CheckButton.new(_("log scale"))
    @x_title = Gtk::Entry.new
    @x_unit = Gtk::Entry.new
    @x_min = Gtk::Entry.new
    @x_max = Gtk::Entry.new
    table = Gtk::Table.new(2,5,false)
    table.attach(@logxbutton,1,2,0,1)
    table.attach(Gtk::Label.new(_("title")),0,1,1,2)
    table.attach(@x_title,1,2,1,2)
    table.attach(Gtk::Label.new(_("unit")),0,1,2,3)
    table.attach(@x_unit,1,2,2,3)
    table.attach(Gtk::Label.new(_("min")),0,1,3,4)
    table.attach(@x_min,1,2,3,4)
    table.attach(Gtk::Label.new(_("max")),0,1,4,5)
    table.attach(@x_max,1,2,4,5)
    @x_frame = Gtk::Frame.new(_("X-Axis"))
    @x_frame.add(table)

    @logybutton = Gtk::CheckButton.new(_("log scale"))
    @y_title = Gtk::Entry.new
    @y_unit = Gtk::Entry.new
    @y_min = Gtk::Entry.new
    @y_max = Gtk::Entry.new
    table = Gtk::Table.new(2,5,false)
    table.attach(@logybutton,1,2,0,1)
    table.attach(Gtk::Label.new(_("title")),0,1,1,2)
    table.attach(@y_title,1,2,1,2)
    table.attach(Gtk::Label.new(_("unit")),0,1,2,3)
    table.attach(@y_unit,1,2,2,3)
    table.attach(Gtk::Label.new(_("min")),0,1,3,4)
    table.attach(@y_min,1,2,3,4)
    table.attach(Gtk::Label.new(_("max")),0,1,4,5)
    table.attach(@y_max,1,2,4,5)
    @y_frame = Gtk::Frame.new(_("Y-Axis"))
    @y_frame.add(table)
    axisbox = Gtk::VBox.new
    axisbox.pack_start(@x_frame)
    axisbox.pack_start(@y_frame)
    axis_window.add(axisbox.show_all)

# Attributes window
    @attr_note = Gtk::Notebook::new()
    @attr_note.set_tab_pos(Gtk::POS_TOP)
    @attr_note.set_size_request(300, 200)
    @attr_note.set_scrollable(true)
    @attr_note.set_enable_popup(true)
    box = Gtk::VBox.new(false,0)
    box.pack_start(@attr_note)
    attr_window.add(box.show_all)

# Movie winsow
    start_xpm = ["11 11 2 1",  "  c None", "+  c black",
      "+          ",
      "+++        ",
      "+++++      ",
      "+++++++    ",
      "+++++++++  ",
      "+++++++++++",
      "+++++++++  ",
      "+++++++    ",
      "+++++      ",
      "+++        ",
      "+          "]
    stop_xpm = ["11 11 2 1", "   c None", "+  c black",
      "           ",
      " +++++++++ ",
      " +++++++++ ",
      " +++++++++ ",
      " +++++++++ ",
      " +++++++++ ",
      " +++++++++ ",
      " +++++++++ ",
      " +++++++++ ",
      " +++++++++ ",
      "           "]
    rec_xpm = ["11 11 2 1", "   c None", "+  c red",
      "    +++    ",
      "  +++++++  ",
      " +++++++++ ",
      " +++++++++ ",
      "+++++++++++",
      "+++++++++++",
      "+++++++++++",
      " +++++++++ ",
      " +++++++++ ",
      "  +++++++  ",
      "    +++    "]
    @movie = false
    @movie_step = 1.0
    @rec = false
    @fnum = "001"
    movie_window.realize
    start_button = Gtk::ToggleButton.new
    start_button.add_xpm(start_xpm, movie_window.window)
    stop_button = Gtk::ToggleButton.new
    stop_button.add_xpm(stop_xpm, movie_window.window)
    rec_button = Gtk::ToggleButton.new
    rec_button.add_xpm(rec_xpm, movie_window.window)
    start_button.signal_connect("clicked"){|w|
      if w.active? then
	@time = Time.now
	@movie = Gtk.idle_add{
	  if Time.now - @time > @movie_step then
	    draw_next
	    if @rec then
	      @draw.save_image("dcl"+@fnum+".png")
	      @fnum.next!
	    end
	    @time = Time.now
	  end
	  true
	}
      else
	Gtk.idle_remove(@movie)
      end
    }
    stop_button.signal_connect("clicked"){
      if start_button.active? then
	start_button.set_active(false)
	Gtk.idle_remove(@movie)
      end
    }
    rec_button.signal_connect("clicked"){|w|
      @rec = w.active?
    }
    @movie_combo = Gtk::Combo.new.set_size_request(50,30)
    @movie_combo.entry.set_editable(false)
    @movie_combo.entry.set_text("-")
    box1 = Gtk::HBox.new(false,0)
    box1.pack_start(@movie_combo)
    box1.pack_start(start_button)
    box1.pack_start(stop_button)
    box1.pack_start(rec_button)
    adjustment = Gtk::Adjustment.new(@movie_step,0.0,3,0.1,1,1)
    adjustment.signal_connect("value-changed"){|w|
      @movie_step=w.value
    }
    scale = Gtk::HScale.new(adjustment)
    scale.set_size_request(150,30)
    scale.set_update_policy(Gtk::UPDATE_DELAYED)
    scale.set_draw_value(false)
    box2 = Gtk::HBox.new(false,0)
    box2.pack_start(Gtk::Label.new(_("fast")))
    box2.pack_start(scale)
    box2.pack_start(Gtk::Label.new(_("slow")))
    @movie_box = Gtk::VBox.new(false,0)
    @movie_box.pack_start(box1)
    @movie_box.pack_start(box2)
    movie_window.add(@movie_box.show_all)

# Map window

    @map_type = {
      "rectangular coordinate" => 1,
      "logarithmic coordinate" => 4,
      "polar coordinate" => 5,
      "bipolar coordinate" => 6,
      "equidistant cylindrical projection" => 10,
      "Mercator's projection" => 11,
      "Mollweide's projection" => 12,
      "Hammer's projection" => 13,
      "Eckert VI projection" => 14,
      "Kitada's elliptic projection" => 15,
      "equidistant conical projection" => 20,
      "Lambert's equal-area conical projection" => 21,
      "Lambert's conformal conical projection" => 22,
      "Bonne's projection" => 23,
      "orthographic projection" => 30,
      "polar stereo projection" => 31,
      "azimuthal equidistant projection" => 32,
      "Lambert's azimuthal equal-area projection" => 33
    }
    @map_combo = Gtk::Combo.new
    @map_combo.entry.set_editable(false)
    @map_combo.set_popdown_strings(@map_type.to_a.sort{|a,b|a[1]<=>b[1]}.collect{|ary| _(ary[0])})
    @pole_lon = Gtk::Entry.new
    @pole_lat = Gtk::Entry.new
    @pole_rot = Gtk::Entry.new
    table = Gtk::Table.new(2,3,false)
    table.attach(Gtk::Label.new(_("longitude")),0,1,0,1)
    table.attach(@pole_lon,1,2,0,1)
    table.attach(Gtk::Label.new(_("latitude")),0,1,1,2)
    table.attach(@pole_lat,1,2,1,2)
    table.attach(Gtk::Label.new(_("rotation")),0,1,2,3)
    table.attach(@pole_rot,1,2,2,3)
    pole_frame = Gtk::Frame.new(_("Pole"))
    pole_frame.add(table)
    @map_check = Gtk::CheckButton.new(_("draw map")).set_active(true)
    box = Gtk::VBox.new(false,0)
    box.pack_start(@map_combo)
    box.pack_start(pole_frame.show_all)
    box.pack_start(@map_check)
    map_window.add(box.show_all)

# Level window
    @cont_min_entry = Gtk::Entry.new
    @cont_interval_entry = Gtk::Entry.new
    cont_manual_box = Gtk::HBox.new.set_sensitive(false)
    cont_manual_box.pack_start(Gtk::Label.new(_("min")))
    cont_manual_box.pack_start(@cont_min_entry)
    cont_manual_box.pack_start(Gtk::Label.new(_("interval")))
    cont_manual_box.pack_start(@cont_interval_entry)
    cont_auto_radio = Gtk::RadioButton.new(_("auto"))
    cont_manual_radio = Gtk::RadioButton.new(cont_auto_radio,_("manual"))
    cont_auto_radio.signal_connect("toggled"){|w|
      cont_manual_box.set_sensitive(false)
      @cont_level = false
    }
    cont_manual_radio.signal_connect("toggled"){|w|
      cont_manual_box.set_sensitive(true)
      @cont_level = true
    }
    cont_int_box = Gtk::HBox.new
    cont_int_box.pack_start(cont_auto_radio)
    cont_int_box.pack_start(cont_manual_radio)
    cont_int_box.pack_start(cont_manual_box)
    @cont_draw_button = Gtk::CheckButton.new(_("draw")).set_active(true)
    @cont_draw_button.signal_connect("toggled"){|w|
      cont_int_box.set_sensitive(w.active?)
    }
    cont_table = Gtk::Table.new(2,3,false)
    cont_table.attach(Gtk::Label.new(_("Contour")),0,2,0,1)
    cont_table.attach(@cont_draw_button,1,2,1,2)
    cont_table.attach(Gtk::Label.new(_("Contour")+" "+_("interval")),0,1,2,3)
    cont_table.attach(cont_int_box,1,2,2,3)

    @tone_min_entry = Gtk::Entry.new
    @tone_interval_entry = Gtk::Entry.new
    tone_manual_box = Gtk::HBox.new.set_sensitive(false)
    tone_manual_box.pack_start(Gtk::Label.new(_("min")))
    tone_manual_box.pack_start(@tone_min_entry)
    tone_manual_box.pack_start(Gtk::Label.new(_("interval")))
    tone_manual_box.pack_start(@tone_interval_entry)
    tone_auto_radio = Gtk::RadioButton.new(_("auto"))
    tone_manual_radio = Gtk::RadioButton.new(tone_auto_radio,_("manual"))
    tone_auto_radio.signal_connect("toggled"){|w|
      tone_manual_box.set_sensitive(false)
      @tone_level = false
    }
    tone_manual_radio.signal_connect("toggled"){|w|
      tone_manual_box.set_sensitive(true)
      @tone_level = true
    }
    tone_int_box = Gtk::HBox.new
    tone_int_box.pack_start(tone_auto_radio)
    tone_int_box.pack_start(tone_manual_radio)
    tone_int_box.pack_start(tone_manual_box)
    tone_method_e_radio = Gtk::RadioButton.new(_("Use")+" uetone")
    tone_method_f_radio = Gtk::RadioButton.new(tone_method_e_radio,_("Use")+" uetonf ("+_("cellular")+" "+_("algorithm")+")")
    tone_method_c_radio = Gtk::RadioButton.new(tone_method_e_radio,_("Use")+" uetonc ("+_("cellular")+" "+_("tiling")+")")
    @tone_method = "uetone"
    tone_method_e_radio.signal_connect("toggled"){ @tone_method = "uetone" }
    tone_method_f_radio.signal_connect("toggled"){ @tone_method = "uetonf" }
    tone_method_c_radio.signal_connect("toggled"){ @tone_method = "uetonc" }
    tone_method_e_radio.set_active(true)
    tone_method_box = Gtk::HBox.new
    tone_method_box.pack_start(tone_method_e_radio)
    tone_method_box.pack_start(tone_method_f_radio)
    tone_method_box.pack_start(tone_method_c_radio)
    @tone_draw_button = Gtk::CheckButton.new(_("draw")).set_active(true)
    @tone_draw_button.signal_connect("toggled"){|w|
      tone_int_box.set_sensitive(w.active?)
      tone_method_box.set_sensitive(w.active?)
    }
    tone_table = Gtk::Table.new(2,3,false)
    tone_table.attach(Gtk::Label.new(_("Tone")),0,2,0,1)
    tone_table.attach(@tone_draw_button,1,2,1,2)
    tone_table.attach(Gtk::Label.new(_("Tone")+" "+_("interval")),0,1,2,3)
    tone_table.attach(tone_int_box,1,2,2,3)
    tone_table.attach(Gtk::Label.new(_("Method")),0,1,3,4)
    tone_table.attach(tone_method_box,1,2,3,4)
    level_box = Gtk::VBox.new
    level_box.pack_start(cont_table)
    level_box.pack_start(Gtk::HSeparator.new)
    level_box.pack_start(tone_table)
    cont_window.add(level_box.show_all)

# Vector Window
    @vector_scale_x_entry = Gtk::Entry.new
    @vector_scale_y_entry = Gtk::Entry.new
    scale_entry_box = Gtk::HBox.new.set_sensitive(false)
    scale_entry_box.pack_start(Gtk::Label.new("X"))
    scale_entry_box.pack_start(@vector_scale_x_entry)
    scale_entry_box.pack_start(Gtk::Label.new("Y"))
    scale_entry_box.pack_start(@vector_scale_y_entry)
    check = Gtk::CheckButton.new(_("manual"))
    check.signal_connect("toggled"){|w|
      scale_entry_box.set_sensitive(w.active?)
      @vector_factor = w.active?
    }
    scale_box = Gtk::HBox.new
    scale_box.pack_start(check)
    scale_box.pack_start(scale_entry_box)

    @vector_thinout_x_entry = Gtk::Entry.new
    @vector_thinout_y_entry = Gtk::Entry.new
    thinout_entry_box = Gtk::HBox.new.set_sensitive(false)
    thinout_entry_box.pack_start(Gtk::Label.new("X"))
    thinout_entry_box.pack_start(@vector_thinout_x_entry)
    thinout_entry_box.pack_start(Gtk::Label.new("Y"))
    thinout_entry_box.pack_start(@vector_thinout_y_entry)
    check = Gtk::CheckButton.new(_("manual"))
    check.signal_connect("toggled"){|w|
      thinout_entry_box.set_sensitive(w.active?)
      @vector_thinout = w.active?
    }
    thinout_box = Gtk::HBox.new
    thinout_box.pack_start(check)
    thinout_box.pack_start(thinout_entry_box)

    vector_table = Gtk::Table.new(2,2,false)
    vector_table.attach(Gtk::Label.new(_("Scale")),0,1,0,1)
    vector_table.attach(scale_box,1,2,0,1)
    vector_table.attach(Gtk::Label.new(_("Thin out")),0,1,1,2)
    vector_table.attach(thinout_box,1,2,1,2)
    vector_window.add(vector_table.show_all)

# Isovalue Surface Window
    scale = Gtk::HScale.new(0,1,0.01)
    scale.set_size_request(200,40)
    scale.value = 0.5
    @surface_adjust = scale.adjustment
    surface_box = Gtk::HBox.new
    surface_box.pack_start(Gtk::Label.new(_("value")))
    surface_box.pack_start(scale)
    if device=="vtk"
      surface_window.add(surface_box.show_all)
    end

# Division Window
    @leng_div = Gtk::RadioButton.new(_("Lengthways"))
    @side_div = Gtk::RadioButton.new(@leng_div, _("Sideways"))
    @x_div = Gtk::Entry.new.set_text("1")
    @y_div = Gtk::Entry.new.set_text("1")
    val_table = Gtk::Table.new(2,3,false)
    val_table.attach(@leng_div,0,1,0,1)
    val_table.attach(@side_div,1,2,0,1)
    val_table.attach(Gtk::Label.new("X"),0,1,1,2)
    val_table.attach(@x_div,1,2,1,2)
    val_table.attach(Gtk::Label.new("Y"),0,1,2,3)
    val_table.attach(@y_div,1,2,2,3)
    val_table.set_sensitive(false)
    button = Gtk::CheckButton.new("divide")
    button.signal_connect("toggled"){|w|
      val_table.set_sensitive(w.active?)
    }
    div_box = Gtk::VBox.new
    div_box.pack_start(button)
    div_box.pack_start(val_table)
    div_window.add(div_box.show_all)

# Variable Combo
    @var_select = Var_select.new
    @var2_select = Var_select.new
    @axisx_select = Var_select.new
    @axisy_select = Var_select.new
    @axisz_select = Var_select.new
    @var_select.signal{set_var}
    @var2_select.signal{set_var2}
    @axisx_select.signal{set_axisx}
    @axisy_select.signal{set_axisy}
    @axisz_select.signal{set_axisz}

# figure type item
    select_type = Proc.new{|type|
      type = type[0] if type.class == Array
      @fig_type = type
      case type
      when LINE
        @fig_dimension = 1
#      when CONTOUR, VECTOR, MAP
      when CONTOUR, VECTOR, MAP
        @fig_dimension = 2
      when SURFACE
        @fig_dimension = 3
      end
      set_type
    }

    items = [
      ["/"+_("Line"), Gtk::ItemFactory::ITEM,nil,nil,select_type,LINE],
      ["/"+_("Contour")+" & "+_("Tone"), Gtk::ItemFactory::ITEM,nil,nil,select_type,CONTOUR],
#      ["/"+_("Map"), Gtk::ItemFactory::ITEM,nil,nil,select_type,MAP],
      ["/"+_("Vector"), Gtk::ItemFactory::ITEM,nil,nil,select_type,VECTOR]
    ]
    if device == "vtk"
      items.push ["/"+_("Surface"), Gtk::ItemFactory::ITEM,nil,nil,select_type,SURFACE]
      @enable_3d = true
    end
    type_itemfact = Gtk::ItemFactory.new(Gtk::ItemFactory::TYPE_OPTION_MENU, "<type>", accel)
    type_itemfact.create_items(items)
    @typeomenu = type_itemfact.get_widget("<type>")
    @typeomenu.set_sensitive(false)
    @typemenu = Array.new
    @typemenu[LINE] = type_itemfact.get_item("/"+_("Line"))
    @typemenu[CONTOUR] = type_itemfact.get_item("/"+_("Contour")+" & "+_("Tone"))
#    @typemenu[MAP] = type_itemfact.get_item("/"+_("Map"))
    @typemenu[VECTOR] = type_itemfact.get_item("/"+_("Vector"))
    if @enable_3d
      @typemenu[SURFACE] = type_itemfact.get_item("/"+_("Surface"))
    end


    select_func = Proc.new{|func|
      func = func[0] if func.class == Array
      set_func(func)
    }
    items = [ ["/"+_("Functions"), Gtk::ItemFactory::BRANCH ] ]
    Funcs1.each{|func|
      items.push( ["/"+_("Functions")+"/"+SFunc[func], Gtk::ItemFactory::ITEM, nil, nil, select_func, func ] )
    }
    type_itemfact.create_items(items)

# Draw button
    @crewindbutton = Gtk::CheckButton.new(_("new Window"))
    @drawbutton = Gtk::Button.new(_("draw")).set_sensitive(false)
    @drawbutton.signal_connect("clicked"){
      if @fig_type==FUNC
	exec_func
      else
	draw_x
      end
      }

# Select table
    table = Gtk::Table.new(2,7,false)
    i = 0
    table.attach(Gtk::Label.new(_("Variable")),0,1,i,i+1)
    table.attach(@var_select,1,2,i,i+1)
    i += 1
    table.attach(Gtk::Label.new(_("Variable")+"2"),0,1,i,i+1)
    table.attach(@var2_select,1,2,i,i+1)
    i += 1
    table.attach(Gtk::Label.new(_("Action")),0,1,i,i+1)
    table.attach(@typeomenu,1,2,i,i+1)
    i += 1
    table.attach(Gtk::Label.new("X-"+_("Axis")),0,1,i,i+1)
    table.attach(@axisx_select,1,2,i,i+1)
    i += 1
    table.attach(Gtk::Label.new("Y-"+_("Axis")),0,1,i,i+1)
    table.attach(@axisy_select,1,2,i,i+1)
    if @enable_3d
    i += 1
      table.attach(Gtk::Label.new("Z-"+_("Axis")),0,1,i,i+1)
      table.attach(@axisz_select,1,2,i,i+1)
    end
    i += 1
    table.attach(@crewindbutton,0,1,i,i+1)
    table.attach(@drawbutton,1,2,i,i+1)

# Main Menu
    p_f_o = Proc.new{
      fs.set_title(_("Open File"))
      fs.complete("*.nc")
      fs.hide_fileop_buttons
      fs.set_select_multiple(true)
      @filecall = Proc.new{|filenames| file_open(filenames)}
      fs.show
    }
    p_f_o2 = Proc.new{ dfs.show } if defined?(DFileSelection)
    p_f_si = Proc.new{
      if !@draw.nil?
        fs.set_title(_("Save Image"))
        fs.complete("*.png")
        fs.show_fileop_buttons
        fs.set_select_multiple(false)
        @filecall = Proc.new{|filenames|
          filename = filenames[0]
          if !FileTest.exist?(filename)
            @draw.save_image(filename)
          else
            dialog = Gtk::Dialog.new
            dialog.set_modal(true)
            dialog.vbox.pack_start(Gtk::Label.new("Can "+filename+" overwrite ?"))
            ok_button=Gtk::Button.new(_("OK"))
            ok_button.signal_connect("clicked"){dialog.destroy; @draw.save_image(filename)}
            cancel_button=Gtk::Button.new(_("Cancel"))
            cancel_button.signal_connect("clicked"){dialog.destroy}
            dialog.action_area.pack_start(ok_button)
            dialog.action_area.pack_start(cancel_button)
            dialog.show_all
          end
        }
        fs.show
      end
    }
    p_f_sc = Proc.new{
      if !@draw.nil?
        fs.set_title(_("Save Code"))
        fs.complete("*.rb")
        fs.show_fileop_buttons
        fs.set_select_multiple(false)
        @filecall = proc{|filenames|
          filename = filenames[0]
          if !FileTest.exist?(filename)
            @draw.save_code(filename)
          else
            dialog = Gtk::Dialog.new
            dialog.set_modal(true)
            dialog.vbox.pack_start(Gtk::Label.new("Can "+filename+" overwrite ?"))
            ok_button=Gtk::Button.new(_("OK"))
            ok_button.signal_connect("clicked"){dialog.destroy; @draw.save_code(filename)}
            cancel_button=Gtk::Button.new(_("Cancel"))
            cancel_button.signal_connect("clicked"){dialog.destroy}
            dialog.action_area.pack_start(ok_button)
            dialog.action_area.pack_start(cancel_button)
            dialog.show_all
          end
        }
        fs.show
      end
    }
    p_f_sn = Proc.new{
      if !@draw.nil?
        fs.set_title(_("Save NetCDF"))
        fs.complete("*.nc")
        fs.show_fileop_buttons
        fs.set_select_multiple(false)
        @filecall = proc{|filenames|
          filename = filenames[0]
          if !FileTest.exist?(filename)
            file = NetCDF.create(filename)
            gphys = @draw_data.gphys
            gphys = gphys.copy if !(GPhys===gphys)
            GPhys::IO.write(file,gphys)
            file.close
          else
            dialog = Gtk::Dialog.new
            dialog.set_modal(true)
            dialog.vbox.pack_start(Gtk::Label.new("Can "+filename+" overwrite ?"))
            ok_button=Gtk::Button.new(_("OK"))
            ok_button.signal_connect("clicked"){
              dialog.destroy
              file = NetCDF.create(filename)
              gphys = @draw_data.gphys
              gphys = gphys.copy if !(GPhys===gphys)
              GPhys::IO.write(file,gphys)
              file.close
            }
            cancel_button=Gtk::Button.new(_("Cancel"))
            cancel_button.signal_connect("clicked"){dialog.destroy}
            dialog.action_area.pack_start(ok_button)
            dialog.action_area.pack_start(cancel_button)
            dialog.show_all
          end
        }
        fs.show
      end
    }
    p_f_q = Proc.new{finish}

    p_t = Proc.new{|data|
      if data.class==Array
	window,w = data
      else
	window = data
	w = window
      end
      if w.active? then window.show else window.hide end
    }

    p_h_h = Proc.new{
      if Locale.get =~ /ja/
        url = HP_URL_JA
      else
        url = HP_URL_EN
      end
      system("mozilla -remote 'openURL(#{url})'")
    }
    p_h_a = Proc.new{
      dialog = Gtk::Dialog.new.set_title(_("About this program"))
      dialog.vbox.pack_start(Gtk::Label.new("\nGAVE version #{GAVE_VERSION}\n"))
      dialog.vbox.pack_start(Gtk::Label.new(_("This program is made by Seiya Nishizawa")))
      dialog.vbox.pack_start(Gtk::Label.new("seiya@kugi.kyoto-u.ac.jp\n"))
      ok_button=Gtk::Button.new(_("OK"))
      ok_button.signal_connect("clicked"){dialog.destroy}
      dialog.action_area.pack_start(ok_button)
      dialog.show_all
    }

    fileitem = [["/"+_("File")+"(_F)", Gtk::ItemFactory::BRANCH]]
    fileitem.push ["/"+_("File")+"(F)/"+_("Open")+"(_O)", Gtk::ItemFactory::STOCK_ITEM, "<control>O", Gtk::Stock::OPEN, p_f_o]
    fileitem.push ["/"+_("File")+"(F)/"+"Open DRuby", Gtk::ItemFactory::STOCK_ITEM, nil, Gtk::Stock::OPEN, p_f_o2] if defined?(DFileSelection)
    fileitem.push ["/"+_("File")+"(F)/"+_("Save Image")+"(_S)", Gtk::ItemFactory::STOCK_ITEM, "<control>S", Gtk::Stock::SAVE, p_f_si]
    fileitem.push ["/"+_("File")+"(F)/"+_("Save Code")+"(_C)", Gtk::ItemFactory::STOCK_ITEM, "<control>C", Gtk::Stock::SAVE, p_f_sc]
    fileitem.push ["/"+_("File")+"(F)/"+_("Save NetCDF")+"(_N)", Gtk::ItemFactory::STOCK_ITEM, "<control>N", Gtk::Stock::SAVE, p_f_sn]
    fileitem.push ["/"+_("File")+"(F)/"+_("Quit")+"(_Q)", Gtk::ItemFactory::STOCK_ITEM, "<control>Q", Gtk::Stock::QUIT, p_f_q]

    toolsitem = [["/"+_("Tools")+"(_T)", Gtk::ItemFactory::BRANCH]]
    toolsitem.push ["/"+_("Tools")+"(T)/"+_("Variable")+"(_V)", Gtk::ItemFactory::CHECK_ITEM, nil, nil, p_t, var_window]
    toolsitem.push ["/"+_("Tools")+"(T)/"+_("Axis")+"(_A)", Gtk::ItemFactory::CHECK_ITEM, nil, nil, p_t, axis_window]
    toolsitem.push ["/"+_("Tools")+"(T)/"+_("Dimensions")+"(_D)", Gtk::ItemFactory::CHECK_ITEM, nil, nil, p_t, @dims_window]
    toolsitem.push ["/"+_("Tools")+"(T)/"+_("Attributes")+"(_T)", Gtk::ItemFactory::CHECK_ITEM, nil, nil, p_t, attr_window]
    toolsitem.push ["/"+_("Tools")+"(T)/"+_("Movie")+"(_O)", Gtk::ItemFactory::CHECK_ITEM, nil, nil, p_t, movie_window]
    toolsitem.push ["/"+_("Tools")+"(T)/"+_("Map")+"(_M)", Gtk::ItemFactory::CHECK_ITEM, nil, nil, p_t, map_window]
    toolsitem.push ["/"+_("Tools")+"(T)/"+_("Contour")+" & "+_("Tone")+"(_C)", Gtk::ItemFactory::CHECK_ITEM, nil, nil, p_t, cont_window]
    toolsitem.push ["/"+_("Tools")+"(T)/"+_("Vector")+"(_E)", Gtk::ItemFactory::CHECK_ITEM, nil, nil, p_t, vector_window]
    toolsitem.push ["/"+_("Tools")+"(T)/"+_("Surface")+"(_S)", Gtk::ItemFactory::CHECK_ITEM, nil, nil, p_t, surface_window]
#    toolsitem.push ["/"+_("Tools")+"(T)/"+_("Division")+"(_I)", Gtk::ItemFactory::CHECK_ITEM, nil, nil, p_t, div_window]

    windowitem = [["/"+_("Windows")+"(_W)", Gtk::ItemFactory::BRANCH]]

    helpitem = [["/"+_("Help")+"(_H)", Gtk::ItemFactory::LAST_BRANCH]]
    helpitem.push ["/"+_("Help")+"(H)/"+_("HomePage")+"(_H)", Gtk::ItemFactory::ITEM, nil, nil, p_h_h]
    helpitem.push ["/"+_("Help")+"(H)/"+_("About")+"(_A)", Gtk::ItemFactory::ITEM, nil, nil, p_h_a]

    items = fileitem + toolsitem + windowitem+helpitem
    @main_itemfact = Gtk::ItemFactory.new(Gtk::ItemFactory::TYPE_MENU_BAR, "<main>", accel)
    @main_itemfact.create_items(items)

    @save_image = @main_itemfact.get_item("/"+_("File")+"(F)/"+_("Save Image")+"(S)").set_sensitive(false)
    @save_code = @main_itemfact.get_item("/"+_("File")+"(F)/"+_("Save Code")+"(C)").set_sensitive(false)
    @save_netcdf = @main_itemfact.get_item("/"+_("File")+"(F)/"+_("Save NetCDF")+"(N)").set_sensitive(false)

    @check_var = @main_itemfact.get_item("/"+_("Tools")+"(T)/"+_("Variable")+"(V)")
    @check_axis = @main_itemfact.get_item("/"+_("Tools")+"(T)/"+_("Axis")+"(A)")
    @check_dims = @main_itemfact.get_item("/"+_("Tools")+"(T)/"+_("Dimensions")+"(D)")
    @check_attr = @main_itemfact.get_item("/"+_("Tools")+"(T)/"+_("Attributes")+"(T)")
    @check_movie = @main_itemfact.get_item("/"+_("Tools")+"(T)/"+_("Movie")+"(O)")
    @check_map = @main_itemfact.get_item("/"+_("Tools")+"(T)/"+_("Map")+"(M)")
    @check_level = @main_itemfact.get_item("/"+_("Tools")+"(T)/"+_("Contour")+" & "+_("Tone")+"(_C)")
    @check_vector = @main_itemfact.get_item("/"+_("Tools")+"(T)/"+_("Vector")+"(E)")
    if device == "vtk"
      @check_surface = @main_itemfact.get_item("/"+_("Tools")+"(T)/"+_("Surface")+"(S)")
    end
#    @check_div = @main_itemfact.get_item("/"+_("Tools")+"(T)/"+_("Division")+"(L)")


# main window
    totalbox = Gtk::VBox.new(false,0)
    totalbox.pack_start(@main_itemfact.get_widget("<main>"),false,true,0)
    totalbox.pack_start(table,false,true,0)
    main_window = Gtk::Window.new(TOPLEVEL).set_resizable(false)
    main_window.set_title("gave")
    main_window.add(totalbox)
    main_window.signal_connect("delete-event"){false}
    main_window.signal_connect("destroy"){finish}
    main_window.add_accel_group(accel)
    main_window.show_all

  end

  def showwindows
    @subwindows.each{|w| w.show}
  end


  def set_title(str); @title_entry.text=str; end
  def get_title;      @title_entry.text;     end
#  def set_missing(val); @miss_entry.text=val.to_s; end
#  def get_missing;      @miss_entry.text.to_f;     end
  def set_div(ary)
    ary[0]==0 ? @leng_div.active=true : @side_div.active=true
    @x_div.text = ary[1].to_s
    @y_div.text = ary[2].to_s
  end
  def get_div
    [@leng_div.active? ? 0 : 1, @x_div.text.to_i, @y_div.text.to_i]
  end

  def set_axis_x_log(tf); @logxbutton.active=tf; end
  def get_axis_x_log;     @logxbutton.active?;   end
  def set_axis_x_title(str); @x_title.text=str; end
  def get_axis_x_title;      @x_title.text;     end
  def set_axis_x_unit(str); @x_unit.text=str; end
  def get_axis_x_unit;      @x_unit.text; end
  def set_axis_x_min(val); @x_min.text=val.to_s; end
  def get_axis_x_min;      @x_min.text.to_f    ; end
  def set_axis_x_max(val); @x_max.text=val.to_s; end
  def get_axis_x_max;      @x_max.text.to_f    ; end
  def set_axis_y_log(tf); @logybutton.active=tf; end
  def get_axis_y_log;     @logybutton.active?;   end
  def set_axis_y_title(str); @y_title.text=str; end
  def get_axis_y_title;      @y_title.text;     end
  def set_axis_y_unit(str); @y_unit.text=str; end
  def get_axis_y_unit;      @y_unit.text; end
  def set_axis_y_min(val); @y_min.text=val.to_s; end
  def get_axis_y_min;      @y_min.text.to_f    ; end
  def set_axis_y_max(val); @y_max.text=val.to_s; end
  def get_axis_y_max;      @y_max.text.to_f    ; end

# OpenFile
  def add_attr_list(varray,name=nil)
    attr_list = List.new
    varray.att_names.each{|n|
      val = varray.get_att(n)
      if val.class==NArray then
        val = val.to_a.join(",")
      end
      attr_list.set_item(n, val)
    }
    attr_list.add_note(@attr_note,name ? name : varray.name)
  end
  def open_var(gphys, filenames, filetype=nil)
    vn_o = gphys.name
    vn = vn_o
    unless gphys.rank==1 && gphys.axnames[0]==vn then
      if @vars.has_key?(vn)
        i=2
        while @vars.has_key?(vn = vn_o+"(#{i})")
          i+=1
        end
      end
      @vars[vn] = gphys
      filenames = [filenames] if !(Array===filenames)
      @vars[vn].funcs = [[filenames, filetype, vn_o]]
      gphys.axnames.each{|an|
        val = gphys.coord(an).val
        i = nil
        an_o = an
        while true
          an = i ? an_o+"(#{i})" : an
          if @dims.has_key?(an) then
            if @dims[an].val == val
              an = nil
              break
            end
          else
            break
          end
          i ? i+=1 : i=2
        end
        if an
          @dims[an] = Select_value.new(val)
          add_attr_list(gphys.coord(an_o),an)
        end
      }
      add_attr_list(gphys.data)
    end
  end

  def file_open(filenames)
    if ! (filenames[0]=~/^druby:\/\//)
      filename = filenames.collect{|fn|
        fn = fn.sub(/^file:\/\//,"")
        if fn=~/^http:\/\//
          fn
        else
          File.expand_path(fn)
        end
      }
      begin
        if filename.length==1
          file = nil
          GPhys::IO.var_names_except_coordinates(filename[0]).each{|vn|
            gphys = GPhys::IO.open(file ? file : filename[0],vn)
            file = gphys.data.file if file.nil?
            open_var(gphys,filename[0])
          }
#        attr_list = List.new
#        file.each_att{|att|
#          val = att.get
#          if val.class==NArray then
#            val = att.get.to_a.join(",")
#          end
#          attr_list.set_item(att.name, val)
#        }
#        attr_list.add_note(@attr_note, _("global"))
        else
          begin
            GPhys::IO.var_names_except_coordinates(filename).each{|vn|
              gphys = GPhys::IO.open(fn,vn)
              open_var(gphys,fn)
            }
          rescue
            filename.each{|fn|
              GPhys::IO.var_names_except_coordinates(fn).each{|vn|
                gphys = GPhys::IO.open(fn,vn)
                open_var(gphys, fn)
              }
#            attr_list = List.new
#            f.each_att{|att|
#              val = att.get
#              if val.class==NArray then
#                val = att.get.to_a.join(",")
#              end
#              attr_list.set_item(att.name, val)
#            }
#            attr_list.add_note(@attr_note, _("global")+" (#{File.basename(fn)})")
          }
          end
        end
      rescue
          error_message = $!.to_s
          print $!.to_s + $!.backtrace.join("\n")+"\n\n"
          dialog = Gtk::Dialog.new.set_title(_("Error Message"))
          dialog.set_modal(true)
          dialog.vbox.pack_start(Gtk::Label.new(filename[0]))
          dialog.vbox.pack_start(Gtk::Label.new(error_message))
          dialog.vbox.pack_start(Gtk::Label.new("in opening File"))
          ok_button=Gtk::Button.new(_("OK"))
          ok_button.signal_connect("clicked"){dialog.destroy}
          dialog.action_area.pack_start(ok_button)
          dialog.show_all
          clear_all
      end

    else
      ary = filenames[0].split("/")
      host = "druby://"+ary[2]
      path = ary[3..-1].join("/")
      raise "path is not given" if path==""
      tree = DRbObject.new(nil,host)
      gphys = tree.data(path)
      open_var(gphys, filenames, "druby")
    end

    clear_dim
    @dimtable = Gtk::Table.new(2, @dims.length, false)
    i=0
    @dims.keys.sort.each{|dim|
      @dimtable.attach(Gtk::Label.new(dim).set_size_request(30,20), 0, 1, i, i+1 )
      @dimtable.attach(@dims[dim].box, 1, 2, i, i+1 )
      i += 1
    }
    @dims_window.add(@dimtable.show_all)

    @var_select.set(@vars.keys.sort.reverse)
    @var_select.active
    set_var

  end

  def set_var
    vname = @var_select.get
    return if vname==_("cannot select") ||vname==""
    @vname = vname
    gphys = @vars[@vname]
    title = gphys.name
    title += "("+gphys.units.to_s+")" if gphys.units.to_s!=""
    set_title(title)
    ax = gphys.axnames
    type = @draw_data && @draw_data.type
    if ax.length == 1 then
      @typeomenu.set_history(LINE)
      @typemenu[LINE].activate
      @typeomenu.set_sensitive(false)
      axis = nil
      if type==LINE && ax.index(@x_name)
        axis = @x_name
      end
      clear_axisx
      @typeomenu.set_history(0)
      @typemenu[LINE].activate
      if axis
        @axisx_select.set_text(axis)
        set_axis_x_title( @draw_data.axis_x.title )
        set_axis_x_unit( @draw_data.axis_x.unit )
        set_axis_x_log( @draw_data.axis_x.log )
        set_axis_x_min( @draw_data.axis_x.min )
        set_axis_x_max( @draw_data.axis_x.max )
      end
    else
      if @enable_3d
        if ax.length == 2
          @typemenu[SURFACE].set_sensitive(false)
        else
          @typemenu[SURFACE].set_sensitive(true)
        end
      end
      axis = nil
      if type
        if @fig_dimension==2 && ax.index(@x_name) && ax.index(@y_name)
          axis = [@x_name,@y_name]
        elsif @fig_dimension==3 && ax.index(@x_name) && ax.index(@y_name) && ax.index(@z_name)
          axis = [@x_name,@y_name,@z_name]
        end
      end
      clear_axisx
      @axisx_select.set(ax)
      @axisx_select.set_text("")
      @typeomenu.set_sensitive(true)
      if axis
        @typeomenu.set_history(type)
        @typemenu[type].activate
        @axisx_select.set_text(axis[0])
        @axisy_select.set_text(axis[1])
        if @fig_dimension==3
          @axisz_select.set_text(axis[2])
        end
        set_axis_x_title( @draw_data.axis_x.title )
        set_axis_x_unit( @draw_data.axis_x.unit )
        set_axis_x_log( @draw_data.axis_x.log )
        set_axis_x_min( @draw_data.axis_x.min )
        set_axis_x_max( @draw_data.axis_x.max )

        set_axis_y_title( @draw_data.axis_y.title )
        set_axis_y_unit( @draw_data.axis_y.unit )
        set_axis_y_log( @draw_data.axis_y.log )
        set_axis_y_min( @draw_data.axis_y.min )
        set_axis_y_max( @draw_data.axis_y.max )
      else
        @typeomenu.set_history(CONTOUR)
        @typemenu[CONTOUR].activate
      end
    end
    if @autodraw
      @autodraw=false
      @drawbutton.clicked
    end
  end

  def set_var2
    vname = @var2_select.get
    if !(vname==_("cannot select") ||vname=="") then
      @vname2 = vname
      gphys1 = @vars[@vname2]
      gphys2 = @vars[@vname]
      title = gphys1.name+","+gphys2.name
      set_title(title)
    end
  end

  def set_type
    @drawbutton.children[0].set_text(_("draw"))
    clear_axisx
    if @vname.nil? then return end
    x_name = @vars[@vname].axnames[0]
=begin
    if @fig_type == MAP
      @vars[@vname].axnames.each{|dim|
        if dim.downcase=~/^(lon|x)/ then
          x_name = dim
          break
        end
      }
    end
=end
    if @fig_type == VECTOR
      vars2 = Array.new
      @vars.keys.sort.reverse.each{|name|
        v = @vars[name]
        next if name==@vname
        if v.shape == @vars[@vname].shape
          if v.rank.times{|i| break if v.coord(i).val!=@vars[@vname].coord(i).val }
            vars2.push name
          end
        end
      }
      if vars2.length>0
        @var2_select.set(vars2)
        @var2_select.active
        set_var2
      else
        @var2_select.not_active
        clear_axisx({"axisx_hide"=>true})
        return
      end
    else
      clear_var2("var2_hide")
    end
    @axisx_select.set_text(x_name)
    @axisx_select.active
    set_axisx
  end

  def set_func(func)
    @fig_type = FUNC
    @fig_dimension = 1
    @func_type = func
    @drawbutton.children[0].set_text(SFunc[func])
    clear_axisx
    @axisx_select.set_text(@vars[@vname].axnames[0])
    @axisx_select.active
    set_axisx
  end

  def set_axisx
    if @vname.nil? then return end
    clear_axisx
    name = @axisx_select.get
    if name==_("cannot select") || name=="" then
      clear_axisy
      return
    end
    @x_name = name
    set_axis_x_title(@x_name)
    x = @vars[@vname].coord(@x_name)
    x.att_names.each{|key|
      if key=~/unit/ then set_axis_x_unit(x.get_att(key)) end
    }
    @x_frame.set_sensitive(true)
    if @fig_type == FUNC then
      clear_axisy({"axisy_hide"=>true})
      func_ok
      return
    elsif @fig_dimension == 1
      clear_axisy({"axisy_hide"=>true})
      draw_ok
      return
    else
      clear_axisy
      ay = @vars[@vname].axnames
      ay.delete(@x_name)
      @axisy_select.set(ay)
      y_name = ay[0]
=begin
      if @fig_type == MAP then
        ay.each{|dim|
          if dim.downcase=~/^(lat|y)/ then
            y_name = dim
            flag = false
            break
          end
        }
      end
=end
      @axisy_select.set_text(y_name)
      @axisy_select.active
      set_axisy
      return
    end
  end
  def set_axisy
    if @vname.nil? then return end
    clear_axisy
    name = @axisy_select.get
    if name!=_("cannot select") && name!="" then
      @y_name = name
      set_axis_y_title(@y_name)
      y = @vars[@vname].coord(@y_name)
      y.att_names.each{|key|
	if key=~/unit/ then set_axis_y_unit(y.get_att(key)) end
      }
      @y_frame.set_sensitive(true)
      if @fig_dimension == 2
        clear_axisz({"axisz_hide"=>true})
        draw_ok
        return
      else
        clear_axisz
        az = @vars[@vname].axnames
        az.delete(@x_name)
        az.delete(@y_name)
        @axisz_select.set(az)
        z_name = az[0]
        @axisz_select.set_text(z_name)
        @axisz_select.active
        set_axisz
      end
    end
  end
  def set_axisz
    if @vname.nil? then return end
    clear_axisz
    name = @axisz_select.get
    if name!=_("cannot select") && name!="" then
      @z_name = name
      z = @vars[@vname].coord(@z_name)
      draw_ok
    end
  end

  def func_ok
    clear_draw
    @drawbutton.set_sensitive(true)
  end
  def draw_ok
    clear_draw
    dims = @vars[@vname].axnames
    dims.delete(@x_name)
    dims.delete(@y_name)
    dims.delete(@z_name)
    if dims.length!=0 then
      @movie_combo.set_popdown_strings(dims)
      @movie_box.set_sensitive(true)
      dims.each{|dn| @dims[dn].active }
    end
    @drawbutton.set_sensitive(true)
  end

  def clear_all(option={})
    clear_var(option)
  end
  def clear_var(option={})
    hide = option.delete("var_hide")
    if hide
      option["var2_hide"]=true
      option["axisx_hide"]=true
      option["axisy_hide"]=true
      option["axisz_hide"]=true
    end
    clear_dim
    clear_var2(option)
    clear_axisx(option)
    if @vname.nil? then return end
    @var_select.not_active if hide
    @vname = nil
  end
  def clear_var2(option={})
    hide = option.delete("var2_hide")
    if @vname2.nil? then return end
    @var2_select.not_active if hide
    @vname2 = nil
  end
  def clear_dim(option={})
    if !@dimtable.nil?
      @dimtable.hide
      @dims_window.remove(@dimtable)
      @dimtable.each{|w| @dimtable.remove(w)}
    end
  end
  def clear_axisx(option={})
    hide = option.delete("axisx_hide")
    if hide
      option["axisy_hide"]=true
      option["axisz_hide"]=true
    end
    clear_axisy(option)
    @axisx_select.not_active if hide
    @x_name = nil
    @x_frame.set_sensitive(false)
    set_axis_x_log(false)
    set_axis_x_title("")
    set_axis_x_unit("")
    set_axis_x_min(nil)
    set_axis_x_max(nil)
  end
  def clear_axisy(option={})
    hide = option.delete("axisy_hide")
    if hide
      option["axisz_hide"]=true
    end
    clear_draw(option)
    @axisy_select.not_active if hide
    @y_name = nil
    set_axis_y_log(false)
    set_axis_y_title("")
    set_axis_y_unit("")
    set_axis_y_min(nil)
    set_axis_y_max(nil)
  end
  def clear_axisz(option={})
    hide = option.delete("axisz_hide")
    clear_draw(option)
    @axisz_select.not_active if hide
    @z_name = nil
  end
  def clear_draw(option={})
    @drawbutton.set_sensitive(false)
    @dims.each_value{|dim| dim.not_active}
    @movie_box.set_sensitive(false)
    @movie_combo.entry.set_text("-")
    set_div([false,1,1])
  end

  def exec_func
    gphys = @vars[@vname]
    ofuncs = gphys.funcs
    min = get_axis_x_min
    max = get_axis_x_max
    min = gphys.coord(@x_name)[0].val[0] if !min
    max = gphys.coord(@x_name)[-1].val[0] if !max
    index = Array.new(gphys.rank)
    ix = gphys.axnames.index(@x_name)
    gphys.rank.times{|i|
      if i==ix then index[i] = min..max else index[i] = true end
    }
    func = [@func_type,ix,index]
    it = 0
    for var in @vars
      funcs = var[1].funcs
      if funcs.length==1 || funcs[0..-2]!=ofuncs || funcs[-1][0..1]!=func[0..1] then
	next
      elsif funcs[-1]==func
	it = false
	break
      elsif
	it += 1
      end
    end
    if it then
      if it>0 then add = "-#{it}" else add = "" end
      vn2 = "#{@vname} (#{@x_name} #{@func_type}#{add})"
      gphys = gphys.cut(*index)
      @vars[vn2] = gphys.send(@func_type,ix)
      @vars[vn2].funcs=(ofuncs.push([@func_type,ix,index]))
      @vars[vn2].name = vn2
      @var_select.not_active
      @var_select.set(@vars.keys.sort.reverse)
      @var_select.active
    end
  end

  def make_draw_data
    draw_data = Draw_data.new

    gphys = @vars[@vname]
    dims = gphys.axnames
    index = Array.new(dims.length)
    dims.each_with_index{|dim,i|
      if dim==@x_name||dim==@y_name||dim==@z_name then
        index[i] = 0..-1
      else
	index[i] = @dims[dim].index
      end
    }
    gphys = gphys[*index]
    if @fig_type==VECTOR
      gphys2 = @vars[@vname2]
      gphys2 = gphys2[*index]
    else
      gphys2 = nil
    end

    draw_data.type = @fig_type
    dims = gphys.axnames
    if @fig_dimension == 2
      if dims.index(@x_name)>dims.index(@y_name) then
        draw_data.transpose = true
      else
        draw_data.transpose = false
      end
    end
=begin
    if @fig_type==MAP
      gphys = gphys.cyclic_ext(@x_name,360)
    end
=end

    draw_data.axis_x.title = get_axis_x_title
    unit = get_axis_x_unit
    if unit != ""
      draw_data.axis_x.unit = unit
      if unit != gphys.coord(0).units.to_s
        coord = gphys.coord(0)
        gphys.axis(0).set_pos( coord.units.convert2(coord,Units.new(unit)) )
      end
    end
    draw_data.axis_y.title = get_axis_y_title
    unit = get_axis_y_unit
    if unit != ""
      draw_data.axis_y.unit = unit
      if @fig_type==CONTOUR || @fig_type==VECTOR
        if unit != gphys.coord(1).units.to_s
          coord = gphys.coord(1)
          gphys.axis(1).set_pos( coord.units.convert2(coord,Units.new(unit)) )
        end
      end
    end

    x = gphys.coord(@x_name).val
    min = get_axis_x_min
    max = get_axis_x_max
    unless min
      case gphys.axis(@x_name).draw_positive
      when true
        min = min(x[0],x[-1])
      when false
        min = max(x[0],x[-1])
      when nil
        min = x[0]
      end
    end
    unless max
      case gphys.axis(@x_name).draw_positive
      when true
        max = max(x[0],x[-1])
      when false
        max = min(x[0],x[-1])
      when nil
        max = x[-1]
      end
    end
    draw_data.axis_x.min = min
    draw_data.axis_x.max = max

    min = get_axis_y_min
    max = get_axis_y_max
    if @fig_dimension == 1
      min = gphys.data.min if !min
      min = min.val if !(Numeric===min)
      max = gphys.data.max if !max
      max = max.val if !(Numeric===max)
=begin
    elsif @fig_type==MAP
      lat = @pole_lat.text.to_f
      y = gphys.coord(@y_name).val
      if (!min)&&(!max)
        min,max = [y[0],y[-1]]
        if min*max < 0
          if min.abs<max.abs
            min = 0
            lat = max>0 ? 90 : -90 unless lat
          else
            max = 0
            lat = min>0 ? 90 : -90 unless lat
          end
        else
          lat = max > 0 ? 90 : -90 unless lat
        end
      elsif (!min)&&max
        min = y[0]
        lat = max>0 ? 90 : -90 unless lat
      elsif min&&(!max)
        max = y[-1]
        lat = min>0 ? 90 : -90 unless lat
      else
        if !lat
          if max.abs>min.abs
            lat = max>0 ? 90 : -90
          else
            lat = min>0 ? 90 : -90
          end
        end
      end
=end
    elsif
      y = gphys.coord(@y_name).val
      unless min
        case gphys.axis(@y_name).draw_positive
        when true
          min = min(y[0],y[-1])
        when false
          min = max(y[0],y[-1])
        when nil
          min = y[0]
        end
      end
      unless max
        case gphys.axis(@y_name).draw_positive
        when true
          max = max(y[0],y[-1])
        when false
          max = min(y[0],y[-1])
        when nil
          max = y[-1]
        end
      end
    end
    draw_data.axis_y.min = min
    draw_data.axis_y.max = max

    lon = @pole_lon.text.to_f || 0.0
    lat = @pole_lat.text.to_f || 0.0
    rot = @pole_rot.text.to_f || 0.0
    draw_data.map_pole = [lon,lat,rot]

    if @fig_dimension==3
      min = nil
      max = nil
      z = gphys.coord(@z_name).val
      unless min
        case gphys.axis(@z_name).draw_positive
        when true
          min = min(z[0],z[-1])
        when false
          min = max(z[0],z[-1])
        when nil
          min = z[0]
        end
      end
      unless max
        case gphys.axis(@z_name).draw_positive
        when true
          max = max(z[0],z[-1])
        when false
          max = min(z[0],z[-1])
        when nil
          max = z[-1]
        end
      end
      draw_data.axis_z.min = min
      draw_data.axis_z.max = max
    end

    log = get_axis_x_log
    if (min(draw_data.axis_x.min,draw_data.axis_x.max)<=0) && log then
      dialog = Gtk::Dialog.new.set_title(_("Error Message"))
      dialog.set_modal(true)
      dialog.vbox.pack_start(Gtk::Label.new(_("X-Axis")+" "+_("has negative value for log scale")))
      ok_button=Gtk::Button.new(_("OK"))
      ok_button.signal_connect("clicked"){dialog.destroy}
      dialog.action_area.pack_start(ok_button)
      dialog.show_all
      return
    end
    draw_data.axis_x.log = log

    log = get_axis_y_log
    if (min(draw_data.axis_y.min,draw_data.axis_y.max)<=0) and log then
      dialog = Gtk::Dialog.new.set_title(_("Error Message"))
      dialog.set_modal(true)
      dialog.vbox.pack_start(Gtk::Label.new(_("Y-Axis")+" "+_("has negative value for log scale")))
      ok_button=Gtk::Button.new(_("OK"))
      ok_button.signal_connect("clicked"){dialog.destroy}
      dialog.action_area.pack_start(ok_button)
      dialog.show_all
      return
    end
    draw_data.axis_y.log = log

    if @fig_dimension == 1
      x = draw_data.axis_x
      xmin = x.min
      xmax = x.max
      x = gphys.coord(0).val
      if (x[-1]-x[0])/(xmax-xmin) < 0
        xmin,xmax = [xmax,xmin]
      end
      gphys = gphys.cut(xmin..xmax)
    elsif @fig_dimension == 2
      x = draw_data.axis_x
      y = draw_data.axis_y
      if draw_data.transpose
        x,y = [y,x]
      end
      xmin = x.min
      xmax = x.max
      ymin = y.min
      ymax = y.max
      x = gphys.coord(0).val
      y = gphys.coord(1).val
      if (x[-1]-x[0])/(xmax-xmin) < 0
        xmin,xmax = [xmax,xmin]
      end
      if (y[-1]-y[0])/(ymax-ymin) < 0
        ymin,ymax = [ymax,ymin]
      end
      gphys = gphys.cut(xmin..xmax, ymin..ymax)
      if @fig_type==VECTOR
        gphys2 = gphys2.cut(xmin..xmax, ymin..ymax)
      end
    elsif @fig_dimension == 3
      x = draw_data.axis_x
      y = draw_data.axis_y
      z = draw_data.axis_z
      xmin = x.min
      xmax = x.max
      ymin = y.min
      ymax = y.max
      zmin = z.min
      zmax = z.max
      x = gphys.coord(0).val
      y = gphys.coord(1).val
      z = gphys.coord(2).val
      if (x[-1]-x[0])/(xmax-xmin) < 0
        xmin,xmax = [xmax,xmin]
      end
      if (y[-1]-y[0])/(ymax-ymin) < 0
        ymin,ymax = [ymax,ymin]
      end
      if (z[-1]-z[0])/(zmax-zmin) < 0
        zmin,zmax = [zmax,zmin]
      end
      gphys = gphys.cut(xmin..xmax, ymin..ymax, zmin..zmax)
    end


    

#    draw_data.missing_value = get_missing
    draw_data.title = get_title
#    if @fig_type==CONTOUR || @fig_type==MAP
    if @fig_type==CONTOUR
      if @cont_draw_button.active?
        draw_data.cont = true
        if @cont_level
          draw_data.cont_i = [@cont_min_entry.text.to_f,@cont_interval_entry.text.to_f]
        else
          draw_data.cont_i = nil
        end
      else
        draw_data.cont = nil
      end
      if @tone_draw_button.active?
        draw_data.tone = @tone_method
        if @tone_level
          draw_data.tone_i = [@tone_min_entry.text.to_f,@tone_interval_entry.text.to_f]
        else
          draw_data.tone_i = nil
        end
      else
        draw_data.tone = nil
      end
    end

#    if @fig_type==MAP then
      draw_data.map_type = @map_type[@map_combo.entry.text]
      draw_data.map_draw = @map_check.active?
#    else
#      draw_data.map_type = nil
#    end

    if @fig_type==VECTOR
      if @vector_thinout
        nx = @vector_thinout_x_entry.text.to_i
        ny = @vector_thinout_y_entry.text.to_i
      else
        nx = 0
        ny = 0
      end
      nx = 15 if nx<2
      ny = 15 if ny<2
      lenx = gphys.axis(0).length
      if lenx>nx
        stepx = (lenx/nx).floor
        nx = (lenx/stepx).floor
        ix = NArray.sint(nx).indgen(stepx/2,stepx)
      else
        nx = lenx
        ix = true
      end
      leny = gphys.axis(1).length
      if leny>ny
        stepy = (leny/ny).floor
        ny = (leny/stepy).floor
        iy = NArray.sint(ny).indgen(stepy/2,stepy)
      else
        ny = leny
        iy = true
      end
      ix,iy = [iy,ix] if draw_data.transpose
      @vector_thinout_x_entry.set_text(nx.to_s)
      @vector_thinout_y_entry.set_text(ny.to_s)

      gphys = gphys[ix,iy]
      gphys2 = gphys2[ix,iy]

      if @vector_factor
        draw_data.vector = [@vector_scale_x_entry.text.to_f,@vector_scale_y_entry.text.to_f]
      else
        draw_data.vector = nil
      end
    end

    if @fig_type == SURFACE
      draw_data.surface = @surface_adjust.value
    end


    draw_data.gphys = gphys
    draw_data.gphys2 = gphys2

    return draw_data
  end

  def add_window
    if defined?(@nwindows)
      @nwindows += 1
      type = "/"+_("Windows")+"(W)/1"
    else
      @dwindows = Array.new
      @nwindows = 1
      type = Gtk::ItemFactory::RADIO_ITEM
    end
    draw = Draw.new(@nwindows)
    @dwindows.push draw
    windowitem = [["/"+_("Windows")+"(_W)", Gtk::ItemFactory::BRANCH]]
    path = "/"+_("Windows")+"(W)/#{@nwindows}"
    @main_itemfact.create_item(path, type, nil, nil, @nwindows){|n, wid|
      if wid.active?
        @draw = @dwindows[n-1]
        @draw.show
      end
    }
    @main_itemfact.get_item(path).active = true
    draw
  end

  def draw_x
    @draw_data = make_draw_data
    @save_image.set_sensitive(true)
    @save_code.set_sensitive(true)
    @save_netcdf.set_sensitive(true)
    @draw = add_window if @draw.nil?|@crewindbutton.active?
    @draw.draw_x(@draw_data)
  end


  def draw_next
    dim = @movie_combo.entry.text
    return if dim=="-"
    @dims[dim].next 
    draw_x
  end

# start
  def start
    Gtk.main
  end

# quit
  def file_close
    clear_var
    @vars.clear
    @dims.clear
  end
  def finish
    file_close
    Gtk.main_quit
  end

end



$main = GAVE.new(device)

$main.autodraw = argv.delete("--draw") || argv.delete("-d")
$main.autodraw = argv.delete("-autodraw") || $main.autodraw # Obsolute

$main.showwindows if argv.delete("--show_windows") || argv.delete("-s")

badoptions = ""
argv.each{|str|
  if str[0..0] == "-"
    badoptions += str+","
  end
}
raise "No such options: #{badoptions.chop!}" if badoptions != ""

begin
  $main.file_open(argv) if argv.length!=0
  argv=[]

  $main.start
rescue
  dialog = Gtk::Dialog.new.set_title(_("Error Message"))
  dialog.set_modal(true)
  p $!.exception.message
  str = "\n"+$!.message+"\n"
  str += $!.backtrace.join("\n")+"\n\n"
  label = Gtk::Label.new(str)
  label.selectable=true
  label.justify=Gtk::Justification::CENTER
  dialog.vbox.pack_start(label)
  str = _("If this error have come from bug of this program, please report to")
  str += "\n<seiya@kugi.kyoto-u.ac.jp>\n"
  label = Gtk::Label.new(str)
  label.selectable=true
  label.justify=Gtk::Justification::CENTER
  label.wrap=true
  dialog.vbox.pack_start(label)
  ok_button=Gtk::Button.new(_("OK"))
  ok_button.signal_connect("clicked"){dialog.destroy}
  dialog.action_area.pack_start(ok_button)
  dialog.signal_connect("destroy"){Gtk.main_quit}
  dialog.show_all
  Gtk.main
#  $main.clear_var
#  $main.clear_var({"var_hide"=>true})
#  $main.set_var
  argv = []
  retry
end
