#!/usr/bin/env ruby

$LOAD_PATH.push File.dirname($0)

require "numru/gphys"
require "numru/dcl"
require "numru/gave/draw"

GAVE_VERSION = "1.0.0-beta5"

begin
  require "gettext"
  include GetText
  gettext_path = "/usr/share/locale"
#  bindtextdomain("gave",gettext_path)
  bindtextdomain("gave",gettext_path,nil,charset="UTF-8")
rescue LoadError
  def _(str); str; end
end

module NumRu
  class GPhys
    def axnames
      @grid.axnames.dup
    end
    alias :_initialize :initialize
    def initialize(*arg)
      _initialize(*arg)
      @funcs = Array.new
    end
    def funcs
      @funcs.dup
    end
    attr_writer :funcs
  end
end


include NumRu

if !defined?(DCL.gtk_version)
  def DCL.gtk_version
    return [1]
  end
end

if DCL.gtk_version[0]==1 then
  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 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
    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)
      note.append_page_menu(@clist.show, Gtk::Label.new(title), Gtk::Label.new(title))
    end
  end
  TOPLEVEL = Gtk::WINDOW_TOPLEVEL

elsif DCL.gtk_version[0]==2 then
  require "gtk2"
  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}))
      note.append_page(treeview.show, Gtk::Label.new(title))
    end
  end
  TOPLEVEL = Gtk::Window::TOPLEVEL
  Gtk.init
end


class Select_value
  attr_reader :index, :box
  def initialize(var)
    height=20
    @max = var.length-1
    @index = 0
    entry = Gtk::Entry.new
    entry.set_size_request(50,height)
    entry.set_editable(false)
    entry.set_text(var[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(var[@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
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 = 1
CONTOUR = 2
MAP = 3

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

  attr_accessor :autodraw
  def initialize
    @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}

# 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
    level_window = Gtk::Window.new(TOPLEVEL).set_title(_("Levels for Contour and Tone")).set_resizable(false)
    @subwindows.push level_window
    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) }
    level_window.signal_connect("delete-event"){|w,e| p_w.call(@check_level,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)
    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
    @maps =  [_("ORTHOGRAPHIC"),_("POLAR STEREO"),_("AZIMUTHAL"),_("AZIMUTHAL EQ. AREA")]
    @map_combo = Gtk::Combo.new
    @map_combo.entry.set_editable(false)
    @map_combo.set_popdown_strings(@maps)
    box = Gtk::VBox.new(false,0)
    box.pack_start(@map_combo)
    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
    }
    box = Gtk::HBox.new
    box.pack_start(cont_auto_radio)
    box.pack_start(cont_manual_radio)
    box.pack_start(cont_manual_box)
    cont_box = Gtk::VBox.new
    cont_box.pack_start(Gtk::Label.new(_("Contour")))
    cont_box.pack_start(box)
    @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
    }
    box = Gtk::HBox.new
    box.pack_start(tone_auto_radio)
    box.pack_start(tone_manual_radio)
    box.pack_start(tone_manual_box)
    tone_box = Gtk::VBox.new
    tone_box.pack_start(Gtk::Label.new(_("Tone")))
    tone_box.pack_start(box)
    level_box = Gtk::VBox.new
    level_box.pack_start(cont_box)
    level_box.pack_start(Gtk::HSeparator.new)
    level_box.pack_start(tone_box)
    level_window.add(level_box.show_all)

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

# figure type item
    select_type = Proc.new{|type|
      type = type[0] if type.class == Array
      @fig_type = type
      set_type
    }

    items = [
      ["/"+_("Line"), Gtk::ItemFactory::ITEM,nil,nil,select_type,LINE],
      ["/"+_("Contour"), Gtk::ItemFactory::ITEM,nil,nil,select_type,CONTOUR],
      ["/"+_("Map"), Gtk::ItemFactory::ITEM,nil,nil,select_type,MAP]
    ]
    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)
    @linemenu = type_itemfact.get_item("/"+_("Line"))
    @contourmenu = type_itemfact.get_item("/"+_("Contour"))

    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
    @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,6,false)
    table.attach(Gtk::Label.new(_("Variable")),0,1,0,1)
    table.attach(@var_select,1,2,0,1)
    table.attach(Gtk::Label.new(_("Action")),0,1,1,2)
    table.attach(@typeomenu,1,2,1,2)
    table.attach(Gtk::Label.new(_("X-Axis")),0,1,2,3)
    table.attach(@axisx_select,1,2,2,3)
    table.attach(Gtk::Label.new(_("Y-Axis")),0,1,3,4)
    table.attach(@axisy_select,1,2,3,4)
    table.attach(@drawbutton,1,2,5,6)

# 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_si = Proc.new{
      return 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
    }
    p_f_sc = Proc.new{
      return 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
    }
    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_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
    }

    items = [
      ["/"+_("File")+"(_F)", Gtk::ItemFactory::BRANCH],
             ["/"+_("File")+"(F)/"+_("Open")+"(_O)", Gtk::ItemFactory::STOCK_ITEM, "<control>O", Gtk::Stock::OPEN, p_f_o],
             ["/"+_("File")+"(F)/"+_("Save Image")+"(_S)", Gtk::ItemFactory::STOCK_ITEM, "<control>S", Gtk::Stock::SAVE, p_f_si],
             ["/"+_("File")+"(F)/"+_("Save Code")+"(_C)", Gtk::ItemFactory::STOCK_ITEM, "<control>C", Gtk::Stock::SAVE, p_f_sc],
             ["/"+_("File")+"(F)/"+_("Quit")+"(_Q)", Gtk::ItemFactory::STOCK_ITEM, "<control>Q", Gtk::Stock::QUIT, p_f_q],

      ["/"+_("Tools")+"(_T)", Gtk::ItemFactory::BRANCH],
             ["/"+_("Tools")+"(_T)/"+_("Variable")+"(_V)", Gtk::ItemFactory::CHECK_ITEM, nil, nil, p_t, var_window],
             ["/"+_("Tools")+"(_T)/"+_("Axis")+"(_A)", Gtk::ItemFactory::CHECK_ITEM, nil, nil, p_t, axis_window],
             ["/"+_("Tools")+"(_T)/"+_("Dimensions")+"(_D)", Gtk::ItemFactory::CHECK_ITEM, nil, nil, p_t, @dims_window],
             ["/"+_("Tools")+"(_T)/"+_("Attributes")+"(_T)", Gtk::ItemFactory::CHECK_ITEM, nil, nil, p_t, attr_window],
             ["/"+_("Tools")+"(_T)/"+_("Movie")+"(_O)", Gtk::ItemFactory::CHECK_ITEM, nil, nil, p_t, movie_window],
             ["/"+_("Tools")+"(_T)/"+_("Map")+"(_M)", Gtk::ItemFactory::CHECK_ITEM, nil, nil, p_t, map_window],
             ["/"+_("Tools")+"(_T)/"+_("Level")+"(_L)", Gtk::ItemFactory::CHECK_ITEM, nil, nil, p_t, level_window],

      ["/"+_("Help")+"(_H)", Gtk::ItemFactory::LAST_BRANCH],
             ["/"+_("Help")+"(_H)/"+_("About")+"(_A)", Gtk::ItemFactory::ITEM, nil, nil, p_h_a]
]
    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)

    @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)/"+_("Level")+"(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 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_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 file_open(filenames)
    filename = filenames.collect{|fn| File.expand_path(fn)}
    begin
      @file = NetCDF.open(filename[0],mode="r")
      @filetype = "netcdf"
    rescue
      error_message1 = $!.to_s
      begin
        @file = GrADS_Gridded.open(filename[0],mode="r")
        @filetype = "grads"
      rescue
        error_message2 = $!.to_s
        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_message1))
        dialog.vbox.pack_start(Gtk::Label.new(error_message2))
        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
        return
      end
    end

    @filename = filename
      
    clear_var
    @vars.clear
    @dims.clear
    @dimtable.hide if !@dimtable.nil?

    filename = filename[0] if filename.length==1
    var_names = @file.var_names
    var_names.length.times{|i|
      vn = var_names[i]
      var = @file.var(vn)
      dims = var.dim_names
      if !( (dims.length==1) && (dims[0]==vn) ) && ! @vars.has_key?(vn) then
	if  @filetype=="netcdf"
	  @vars[vn] = GPhys::NetCDF_IO.open(filename,vn)
	elsif @filetype=="grads"
	  @vars[vn] = GPhys::GrADS_IO.open(filename,vn)
	else
	  raise "filetype is not netcdf and grads"
	end
        @vars[vn].funcs = [vn]
        @vars[vn].axnames.each_index{|j|
          an = @vars[vn].axnames[j]
          if !@dims.has_key?(an) then
            @dims[an] = Select_value.new(@vars[vn].coord(j).val)
          end
      }
      end

      attr_list = List.new
      var.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,vn)
    }

    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"))

    @dimtable = Gtk::Table.new(2, @dims.length, false)
    i=0
    @dims.each_key{|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
    if @filename.nil? then return end
    vname = @var_select.get
    if !(vname==_("cannot select") ||vname=="") then
      @vname = vname
      gphys = @vars[@vname]
      title = gphys.name
      title += "("+gphys.units.to_s+")" if gphys.units.to_s!=""
      set_title(title)
#      gphys.data.att_names.each{|key|
#	value = gphys.data.get_att(key)
#	if key=~/miss/ then set_missing(value[0]) end
#	if key=~/name/ then set_title(value) end
#	if key=~/unit/ then
#          set_title(get_title+"("+value+")")
#	end
#      }
      ax = gphys.axnames
      clear_axisx
      if ax.length == 1 then
	@typeomenu.set_sensitive(false)
	@typeomenu.set_history(0)
	@linemenu.activate
      else
	@typeomenu.set_sensitive(true)
	@typeomenu.set_history(1)
	@axisx_select.set(ax)
	@contourmenu.activate
      end
    end
  end

  def set_type
    if @filename.nil? then return end
    @drawbutton.children[0].set_text(_("draw"))
    clear_axisx
    if @vname.nil? then return end
    x_name = @vars[@vname].axnames[0]
    if @fig_type==MAP
      @vars[@vname].axnames.each{|dim|
        if dim.downcase=~/^(lon|x)/ then
          x_name = dim
          break
        end
      }
    end
    @axisx_select.set_text(x_name)
    @axisx_select.active
  end

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

  def set_axisx
    if @vname.nil? then return end
    clear_axisx(1)
    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
      func_ok
      return
    elsif @fig_type == LINE
      clear_axisy
      draw_ok
      return
    else
      clear_axisy(1)
      ay = @vars[@vname].axnames
      ay.delete(@x_name)
      @axisy_select.set(ay)
      y_name = ay[0]
      if @fig_type == MAP then
        ay.each{|dim|
          if dim.downcase=~/^(lat|y)/ then
            y_name = dim
            flag = false
            break
          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
    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)
      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)
    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)
    if @autodraw
      draw_x
      @autodraw=false
    end
  end

  def clear_all
    clear_var
    @filename = nil
    @filetype = nil
  end
  def clear_var(*switch)
    clear_axisx
    if @vname.nil? then return end
    @var_select.not_active if switch.length==0
    @vname = nil
  end
  def clear_axisx(*switch)
    clear_axisy
    @axisx_select.not_active if switch.length==0
    @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(*switch)
    clear_draw
    @axisy_select.not_active if switch.length==0
    @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_draw
    @drawbutton.set_sensitive(false)
    @dims.each_value{|dim| dim.not_active}
    @movie_box.set_sensitive(false)
    @movie_combo.entry.set_text("-")
  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
    clear_var(1)
    set_var
  end

  def make_draw_data
    draw_data = Draw_data.new
    draw_data.filename = @filename
    draw_data.filetype = @filetype

    gphys = @vars[@vname]
    dims = gphys.axnames
    index = Array.new(dims.length)
    dims.each_with_index{|dim,i|
      if dim==@x_name||dim==@y_name then
	index[i] = 0..-1
      else
	index[i] = @dims[dim].index
      end
    }
    draw_data.gphys = gphys[*index]
    draw_data.gphys.funcs = gphys.funcs
    draw_data.type = @fig_type
    dims = draw_data.gphys.axnames
    if @fig_type!=LINE
      if dims.index(@x_name)>dims.index(@y_name) then
        draw_data.transpose = true
      else
        draw_data.transpose = false
      end
    end

    x = draw_data.gphys.coord(@x_name)
    min = get_axis_x_min
    max = get_axis_y_max
    min = x[0].val[0] if !min
    max = x[-1].val[0] if !max
    draw_data.axis_x.min = min
    draw_data.axis_x.max = max
    min = get_axis_y_min
    max = get_axis_y_max
    if @fig_type==LINE
      min = draw_data.gphys.data.min if !min
      min = min.val if !(Numeric===min)
      max = draw_data.gphys.data.max if !max
      max = max.val if !(Numeric===max)
    else
      y = draw_data.gphys.coord(@y_name)
      min = y[0].val[0] if !min
      max = y[-1].val[0] if !max
    end
    draw_data.axis_y.min = min
    draw_data.axis_y.max = max

    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

    draw_data.axis_x.title = get_axis_x_title
    draw_data.axis_x.unit = get_axis_x_unit
    draw_data.axis_y.title = get_axis_y_title
    draw_data.axis_y.unit = get_axis_y_unit
#    draw_data.missing_value = get_missing
    draw_data.title = get_title
    if @cont_level
      draw_data.cont=[@cont_min_entry.text.to_f,@cont_interval_entry.text.to_f]
    else
      draw_data.cont=nil
    end
    if @tone_level
      draw_data.tone=[@tone_min_entry.text.to_f,@tone_interval_entry.text.to_f]
    else
      draw_data.tone=nil
    end

    if @fig_type==MAP then
      draw_data.map_type=@maps.index(@map_combo.entry.text)+30
    end

    return draw_data
  end

  def draw_x
    draw_data = make_draw_data
    @save_code.set_sensitive(true)
    @save_image.set_sensitive(true)
    @draw = Draw.new if @draw.nil?
    @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
    if @file then
      clear_var
      @file.close
      @file = nil
      @filetype = nil
      @vars.clear
      @dimtable.hide
      @dims.clear
    end
  end
  def finish
    file_close
    Gtk.main_quit
  end

end



argv = ARGV

$main = GAVE.new
$main.autodraw = argv.delete("-autodraw")
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, prease 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.show_all
  $main.clear_var(0)
  $main.set_var
  retry
end

