#! ruby -Ks
#-- dfm_to_rb.rb

require "phi"

if __FILE__  == $0
  p "Wait for .. loading all library of Apollo"
  begin
    require "phi-all"
  rescue Exception
    require "File_merge_path"
    require "File_split3"
  end
else
  require "File_merge_path"
  require "File_split3"
end
require "lang/SimpleGetText"

class Dfm_to_rb
  DEFAULT_DFM_PATH = "c:/program files/borland/delphi6/projects/unit1.dfm"
  DEFAULT_RB_PATH  = File.merge_path($0,"sample")
end

begin
  # needs .. ptstore_ex.rb, ptstore.rb & tmarshal.rb
  require "ptstore_ex"
  PATH_SAVER = :ptstore_ex 
rescue Exception
  require "pstore"
  PATH_SAVER = :pstore
  PSTORE_PATH = $0.sub(/\..*$/,".ps")
end

######## automatically made by itself ########

#! ruby -Ks
# please add "require"s you need

class Dfm_to_rb
  attr :form
  attr :button_copy
  attr :button_open
  attr :button_save
  attr :button_select
  attr :button_test
  attr :check_box_copied
  attr :check_box_saved
  attr :edit_dfm
  attr :edit_target_dir
  attr :edit_target_name
  attr :group_box1
  attr :label1
  attr :label_dfm
  attr :label_rb
  attr :memo1
  attr :open_dialog1
  attr :panel1
  attr :panel2
  attr :panel3
  attr :panel4
  attr :radio_button_beta
  attr :radio_button_class
  attr :save_dialog1
  attr :save_dialog2
  attr :status_bar1

  def initialize(*args)
    @form = Phi.load_from_dfm("dfm_to_rb.dfm")
    @button_copy = form.panel1.panel4.button_copy
    @button_open = form.panel1.panel4.button_open
    @button_save = form.panel1.panel4.button_save
    @button_select = form.panel1.panel3.button_select
    @button_test = form.panel1.panel4.button_test
    @check_box_copied = form.panel1.panel3.check_box_copied
    @check_box_saved = form.panel1.panel3.check_box_saved
    @edit_dfm = form.panel1.panel3.edit_dfm
    @edit_target_dir = form.panel1.panel3.edit_target_dir
    @edit_target_name = form.panel1.panel3.edit_target_name
    @group_box1 = form.panel1.panel4.group_box1
    @label1 = form.panel1.panel3.label1
    @label_dfm = form.panel1.panel3.label_dfm
    @label_rb = form.panel1.panel3.label_rb
    @memo1 = form.panel2.memo1
    @open_dialog1 = form.open_dialog1
    @panel1 = form.panel1
    @panel2 = form.panel2
    @panel3 = form.panel1.panel3
    @panel4 = form.panel1.panel4
    @radio_button_beta = form.panel1.panel4.group_box1.radio_button_beta
    @radio_button_class = form.panel1.panel4.group_box1.radio_button_class
    @save_dialog1 = form.save_dialog1
    @save_dialog2 = form.save_dialog2
    @status_bar1 = form.status_bar1

    #### ---- ####

    @form.width += 100
    @radio_button_beta.on_click = proc{convert}
    @radio_button_class.on_click = proc{convert}
    @radio_button_class.checked = true
    self.dfm_path = get_default_dfm_path
    self.rb_path  = get_default_rb_path
    @button_open.on_click = proc{button_open_click}
    @button_test.on_click = proc{button_test_click}
    @button_select.on_click = proc{button_select_click}
    @button_copy.on_click = proc{button_copy_click}
    @button_save.on_click = proc{button_save_click}
    @edit_dfm.on_change = proc{edit_dfm_change}
    @check_box_copied.on_click = proc{check_box_copied_click}

    # String#_ method replace to Japanese .. see locale/dfm_to_rb.rb_ja
    #
    @check_box_copied.hint = "showing whether DFM-file was copied to Target"._
    @check_box_saved.hint = "showing whether DB-file was wrote to Target"._
    @radio_button_beta.hint = "to make a Flat type rb-file"._
    @radio_button_class.hint = "to make a Class oriented rb-file"._
    @button_open.hint = "to select DFM-file as a source"._
    @button_test.hint = "to test run the rb-file which was automatically made. "._
    @button_select.hint = "select Targer directory"._
    @button_copy.hint = "to copy DFM-file from source to Targer directory"._
    @button_save.hint = "to write RB-file to Target directory"._
    @edit_dfm.hint = "input path of DFM-file. "._
    @edit_target_dir.hint = "input Target directory."._
    @edit_target_name.hint = "input Target Name (RB-file, DFM-file in common)"._
    @memo1.hint = "RB-file which was automatically made. "._
    Phi::APPLICATION.on_hint = proc do |sender|
      say sender.hint
    end
  end

  #### class methods ####

  def check_box_copied_click
    convert
  end

  def self.access_names(dfm_path)
    form = Phi.load_from_dfm(dfm_path)
    base_name = File.merge_path(dfm_path,"",[:n])
    file_name = base_name + ".rb"
    class_name = base_name.capitalize
    obj_name = base_name.downcase
    names = []
    access_names = proc{|name,receiver| # receiver = "form"
      access_name = receiver ? "#{receiver}.#{name}" : name
      names.push [name, access_name] if receiver
      eval(access_name).singleton_methods.each{|sub_name|
       access_names.call(sub_name,access_name)
      }
    }
    access_names.call("form",nil)
    return names.sort
  end

  def self.dfm_to_class_text(dfm_path)
    names = access_names(dfm_path)
    base_name = File.merge_path(dfm_path,"",[:n])
    file_name = base_name + ".rb"
    class_name = base_name.capitalize
    obj_name = base_name.downcase
    text = <<MMMM
#! ruby -Ks
#-- #{file_name}
# please remove 'require "phi-all"'
# and add "require"s you need
require "phi-all"
require "phi"

class #{class_name}
  attr :form
#{names.collect{|name,access_name| "  attr :#{name}\n"}}
  def initialize(*args)
    @form = Phi.load_from_dfm(#{dfm_path.inspect})
#{names.collect{|name,access_name| "    @#{name} = #{access_name}\n"}}
  end
end # class #{class_name}

if __FILE__ == $0
  #{obj_name} = #{class_name}.new
  #{obj_name}.form.show
  Phi.mainloop
end
MMMM
  end # def dfm_to_class_text

  def self.dfm_to_class(dfm_path)
    puts dfm_to_class_text(dfm_path)
  end

  def self.dfm_to_beta_text(dfm_path)
    names = access_names(dfm_path)
    base_name = File.merge_path(dfm_path,"",[:n])
    file_name = base_name + ".rb"
    class_name = base_name.capitalize
    obj_name = base_name.downcase
    text = <<MMMM
#! ruby -Ks
#-- #{file_name}
# please remove 'require "phi-all"'
# and add "require"s you need
require "phi-all"
require "phi"

form = Phi.load_from_dfm(#{dfm_path.inspect})
#{names.collect{|name,access_name| "#{name} = #{access_name}\n"}}

if __FILE__ == $0
  form.show
  Phi.mainloop
end
MMMM
  end # dfm_to_beta_text

  def self.dfm_to_beta(dfm_path)
    puts dfm_to_beta_text(dfm_path)
  end

  #### instance methods ####

  def make_memo1_hint
    msg = "RB-file which was automatically made. "._
    msg += ( @check_box_copied.checked ? "Copied"._ : "Original"._ )+" DFM-file, "._
    msg += ( @radio_button_class.checked ? "Class oriented"._ : "Flat type"._ )+" RB-file."._
    @memo1.hint = msg
  end

  def edit_dfm_change
    if File.exist?(edit_dfm.text)
      convert
    else
      @memo1.clear
    end
  end

  def button_save_click
    dst_path = rb_path + ".rb"
    if File.exist?(dst_path)
      msg = <<MMMM._
%s
is already exist.
recommended that it's more safty to copy to old file
through clip board (copy & paste)
than to overwrite it.
Do you want to overwrite old file?
MMMM
      unless Phi::MR_OK == Phi.message_dlg(msg % [dst_path],
          Phi::MT_WARNING, [Phi::MB_OK,Phi::MB_CANCEL])
        say("canceld")
        return
      end
    end
    @memo1.lines.save(dst_path)
    say("wrote to %s"._ % [dst_path])
    @check_box_saved.checked = true
  end

  def say(v)
    @status_bar1.simple_text = v
  end

  def button_copy_click
    if /^sample$/i =~ @edit_target_name.text
      button_select_click
    end
    src_path = @edit_dfm.text
    dst_path = rb_path+".dfm"
    if Phi::MR_OK == Phi.message_dlg("to copy \n'%s' \nto \n'%s'"._ % [src_path,dst_path],
        Phi::MT_CONFIRMATION, [Phi::MB_OK,Phi::MB_CANCEL])
      File.open(dst_path,"wb"){|d|d.write(File.open(src_path,"rb"){|s|s.read})}
      @check_box_copied.checked = true
      convert
    end
  rescue
    say $!
  end

  def button_select_click
    @save_dialog1.file_name = rb_path
    @save_dialog1.title = "select Target Directory"
    if @save_dialog1.execute
      self.rb_path = @save_dialog1.file_name
    end
  end

  def button_test_click
    begin
      say "test start"
      path = File.merge_path(rb_path,'temp.rb')
      @memo1.lines.save(path)
      `#{File.split3(Phi::APPLICATION.exe_name)[0]}apollo_q "#{path}"`
      say "test end"
    rescue
      @memo1.lines.text = $!+"\n"+$@.join("\n")
      say "test fail"
    end
  end

  def convert # read file of @edit_dfm.text to @memo1.text
    say "converting"
    ok_msg = "Convert OK"
    if @check_box_copied.checked
      src_path = File.merge_path(rb_path,".dfm")
      ok_msg << " for copied DFM file"
    else
      src_path = @edit_dfm.text
      ok_msg << " for Delphi's DFM file"
    end
    begin
      if @radio_button_class.checked
        rb_text = self.class.dfm_to_class_text(src_path)
        ok_msg << " to Normal(classed) RB file"
      else
        rb_text = self.class.dfm_to_beta_text(src_path)
        ok_msg << " to Flat(non classed) RB file"
      end
    rescue
      @error_reason = ""
      @memo1.lines.text = "\n\n #{$!}\n"+$@.join("\n")
      case $!
      when /OBJECT/
        @error_reason = "not text type DFM. Please save DFM as text by Delphi."._
      end
      @memo1.lines[0] = @error_reason
      say "convert fail"
      return
    end
    @memo1.lines.text = rb_text
    @check_box_saved.checked = false
    make_memo1_hint
    say ok_msg
  end

  def button_open_click
    old_name = @edit_target_name.text
    old_target_name = File.split3(@edit_dfm.text)[1].downcase
    auto_rename = ((/Sample/i =~ old_name) || old_name.strip.empty? || (old_name.downcase == old_target_name))
    @open_dialog1.file_name = @edit_dfm.text
    @open_dialog1.default_ext = "dfm"
    @open_dialog1.filter = "dfm|*.dfm|all|*.*"
    if @open_dialog1.execute
      new_target_name = File.split3(@open_dialog1.file_name)[1]
      @edit_target_name.text = new_target_name if auto_rename
      self.dfm_path = @open_dialog1.file_name
    end
  end

  def get_default_dfm_path
    ret = load_store(:dfm_path)
    return ret.is_a?(String) ? ret : DEFAULT_DFM_PATH
  end

  def dfm_path=(v)
    @edit_dfm.text = v
    @check_box_copied.checked = false
    convert
    save_store(:dfm_path,v)
  end

  def dfm_path
    return @edit_dfm.text
  end

  def rb_path=(v)
    d,n,e = File.split3(v)
    @edit_target_dir.text = d
    @edit_target_name.text = n
    @check_box_copied.checked = false
    save_store(:rb_path, v)
  end

  def rb_path
    @edit_target_dir.text + @edit_target_name.text
  end

  def get_default_rb_path
    ret = load_store(:rb_path)
    return ret.is_a?(String) ? ret : DEFAULT_RB_PATH
  end

  def load_store(sym)
    case PATH_SAVER
    when :ptstore_ex
      return PTStore_ex[sym]
    when :pstore
      return PStore.new(PSTORE_PATH).transaction{|s|s[sym]}
    end
  end

  def save_store(sym, val)
    case PATH_SAVER
    when :ptstore_ex
      PTStore_ex[sym] = val
    when :pstore
      PStore.new(PSTORE_PATH).transaction{|s|s[sym]=val}
    end
  end

end # class Dfm_to_rb

if __FILE__ == $0
  dfm_to_rb = Dfm_to_rb.new
  dfm_to_rb.form.show
  Phi.mainloop
end

