#! ruby -Ks

Usage = <<EOT
  Clip2Jpg.rb .. ver.0.03 2003-12-20 take_tk

  クリップボードから画像を取り入れて、枠を区切ってＪＰＥＧファイルに
落とす。・・次のような使い方を想定しています。

  （１）  PrtScrn で画面をクリップボードにコピーする。
  （２）  Clip2Jpg.rb を起動する。・・クリップボードがある場合には自
        動的に読み込まれた状態で始まります。
  （３）  マウスで必要な枠を適当に定める。・・マウスボタンをあげると、
        クリップした部分だけが表示される画面になります。Ctrl+X で元
        の画面とクリップ画面とを切り替えることが出来ます。
  （４）  カーソルキーで枠を微調整する。・・カーソルキーだけだと右
        下の点を移動し、Shift を押しながらだと左上の点を移動します。
  （５）  Ctrl+S でファイルにセーブする。

  ＊  現在のバージョンでは取り込んだ絵が大きくてもスクロールしません。
      右端、下端は扱えませんのでご注意ください。
EOT
if ARGV[0] == '--help'
  print Usage
  exit
end
    ##
    ##  -- load library
    ##
require 'phi'
include Phi
require 'dialogs'
require 'jpeg'
require 'ini'       ##  ver. 0.02
require "pngobject" ##  ver. 0.03
Png = PNGObject
    ##
    ##  -- グローバル変数
    ##
$form_caption = 'clip2jpg .. Clipboard to JPeg file'

$ini = IniFile.new('clip2jpg')
$prev_file = $ini['prev_file','prev_file','']	# ""

$dragging = false
$filter = 'Bitmap(*.bmp)|*.bmp'+
         '|Jpeg(*.jpg)|*.jpg'+
         '|Png(*.png)|*.png'+
         '|All Grahic Files|*.bmp;*.jpg;*.png'
$filter_bmp = 1
$filter_jpg = 2
$filter_png = 3
$filter_all = 4

$rubber_rect = Rect.new

  def $rubber_rect.initialize
    @cx = 0
    @cy = 0
  end
$rubber_rect.initialize

  def $rubber_rect.set_area(x,y)
    @cx = x
    @cy = y
    return self
  end

  def $rubber_rect.inside?(x,y)
    return (( (0..@cx)===x ) and ( (0..@cy)===y ) ) # 2000-10-23(月)
  end

  def $rubber_rect.start(x,y)
    if inside?(x,y)
      @start_x = self.left = self.right  = x
      @start_y = self.top  = self.bottom = y
    end
    return self
  end

  def $rubber_rect.move_to(x,y)
    if @start_x && @start_y && inside?(x,y)
      if x < @start_x
        self.left  = x
        self.right = @start_x
      else
        self.right = x
        self.left  = @start_x
      end
      if y < @start_y
        self.top    = y
        self.bottom = @start_y
      else
        self.top    = @start_y
        self.bottom = y
      end
    end
    return self
  end

  def $rubber_rect.alive?
    s = self
    return (( s.top != s.bottom ) and ( s.left != s.right ))
  end

  def $rubber_rect.expand(left, top, right, bottom)
    left   += self.left
    top    += self.top
    right  += self.right
    bottom += self.bottom
    if inside?(left, top) && inside?(right, bottom)
      self.left   = left
      self.top    = top
      self.right  = right
      self.bottom = bottom
    end
    self
  end

    ##
    ##  Bitmap.new は相当コストが高そうなので、あらかじめ作っておく。
    ##
$tmp_bmp = Bitmap.new

    ##
    ##  --  フォーム
    ##
$form = Form.new :form1
$form.caption = $form_caption

$src_image = Image.new $form, :src_image1
$src_image.align = Phi::AL_CLIENT

$dst_image = Image.new $form, :dst_image1
$dst_image.align = Phi::AL_CLIENT
$dst_image.visible = false

$shape = Shape.new $form, :shape1
$shape.visible = false
$shape.brush.style = Phi::BS_CLEAR
$shape.pen.style = Phi::PS_DOT
$shape.drag_cursor = Phi::CR_CROSS

    ##
    ##  →c:\progra~1\borland\delphi5\source\vcl\consts.pas[SmkcBkSp]
    ##
Phi.new_menu $form, :menu, [
  Phi.new_item('&Paste(Ctrl+V)'     , 'Ctrl+V'      , :mi_paste),
  Phi.new_item('E&xchange'          , 'Ctrl+X'      , :mi_exchange),
  Phi.new_item('&Cursors'           , ''            , :mi_cursors ).add(
    Phi.new_item('Up    Floor'      , 'Up'          , :mi_up),
    Phi.new_item('Down  Floor'      , 'Down'        , :mi_down),
    Phi.new_item('Left  RightWall'  , 'Left'        , :mi_left),
    Phi.new_item('Right RightWall'  , 'Right'       , :mi_right),
    Phi.new_item('Up    Ceil'       , 'Shift+Up'    , :mi_sup),
    Phi.new_item('Down  Ceil'       , 'Shift+Down'  , :mi_sdown),
    Phi.new_item('Left  LeftWall'   , 'Shift+Left'  , :mi_sleft),
    Phi.new_item('Right LeftWall'   , 'Shift+Right' , :mi_sright)
  ),
  Phi.new_item('&Save'              , 'Ctrl+S'      , :mi_save),
  Phi.new_item('&File'              , ''            , :mi_file ).add(
    Phi.new_item('&Open'            , 'Ctrl+O'      , :mi_open),
    Phi.new_item('&Save'            , ''            , :mi_save2),
    Phi.new_item('E&xit'            , ''            , :mi_exit)
  ),
  Phi.new_item('&Help'              , ''            , :mi_help)
]
$form.menu_attr_flatten

$form.mi_exit.on_click   = proc { exit }

$form.mi_help.on_click   = proc do
  Phi.message_dlg( Usage , Phi::MT_CONFIRMATION, [Phi::MB_OK])
end

$form.mi_exchange.on_click = proc { exchange_image }
def exchange_image( for_src=nil )
  if for_src.nil?
    for_src = $dst_image.visible
  end
  fm = Phi::SCREEN.form1
  if for_src
    $src_image.visible = true
    $dst_image.visible = false
  else
    copy_image
    $dst_image.visible = true
    $src_image.visible = false
  end
  fm.mi_paste.enabled = for_src
  fm.mi_open.enabled = for_src
  fm.mi_save.enabled = ! for_src
end
    ##
    ##  TCanvas.ClipRect は書き込み禁止なので使えない。
    ## 「bm = di.picture.bitmap」で直接やると、画像がちらつく。
    ##
def copy_image
  if $rubber_rect.alive?
    rr = $rubber_rect
    si = $src_image
    di = $dst_image
    bm = $tmp_bmp
    bm.width = 0
    bm.width  = di.width  = si.width
    bm.height = di.height = si.height
    bm.canvas.copy_rect rr , si.picture.bitmap.canvas , rr
    di.picture.assign bm
  end
end

    ##
    ##  ---  ファイル・クリップボード関係
    ##

    ##
    ##  save と save2 とは同じものだが、
    ##  save はメニュートップにあり、クリップ画面でのみ使用可能。
    ##  save2 は File メニューの下にあり、常に使用可能。
    ##
$form.mi_save  .on_click = proc { save }
$form.mi_save2 .on_click = proc { save }
def save
  dlg = SaveDialog.new
  dlg.file_name = $prev_file
  dlg.filter = $filter
  case $prev_file
  when /\.bmp$/i
    dlg.filter_index = $filter_bmp
  when /\.png$/i
    dlg.filter_index = $filter_png
  else
    dlg.filter_index = $filter_jpg    ##  JPeg
  end
  if dlg.execute
        ##  メモリ上は常に bmp 形式。
    if $src_image.visible
      bm = $src_image.picture.bitmap
    else
      bm = $tmp_bmp
      dc = $dst_image.picture.bitmap.canvas
      rr = $rubber_rect
      height = rr.bottom - rr.top
      width  = rr.right  - rr.left
      bm.height = height
      bm.width  = width
      bm.canvas.copy_rect Rect.new(0,0,width,height) , dc , rr
    end
    name = dlg.file_name
    case name
    when /\.jpe?g$/i , /\.bmp$/i, /\.png$/i
    else
      case dlg.filter_index
      when $filter_bmp ; name += ".bmp"
      when $filter_jpg ; name += ".jpg"
      when $filter_png ; name += ".png"
      end
    end
    case name
    when /\.jpe?g$/i
      dst = Jpeg.new
      dst.assign bm
      dst.save name
    when /\.bmp$/i
      bm.save name
    when /\.png$/i
      dst = Png.new
      dst.assign bm
      dst.save name
    else
      Phi.message_dlg('画像形式が分かりません',
            Phi::MT_CONFIRMATION, [Phi::MB_OK])
      return
    end
    $prev_file = dlg.file_name
    $ini['prev_file','prev_file'] = $prev_file	# 2000-10-24(火)
    $form.caption = $form_caption + ' .. ' + $prev_file
  end
end

$form.mi_open.on_click = proc do
  dlg = OpenDialog.new
  dlg.file_name = $prev_file
  dlg.filter = $filter
  dlg.filter_index = $filter_all    ##  all graphic
  if dlg.execute
        ##  メモリ上は常に bmp 形式。
    name = dlg.file_name
    bmp = $tmp_bmp
    case name
    when /\.jpe?g$/i
      src = Jpeg.new
      src.load name
      bmp.assign src
    when /\.bmp$/i
      bmp.load name
    when /\.png$/i
      src = Png.new
      src.load name
      bmp.assign src
    else
      Phi.message_dlg('画像形式が分かりません',
            Phi::MT_CONFIRMATION, [Phi::MB_OK])
      break
    end
    si = $src_image
    sp = $src_image.picture
    sp.bitmap.assign bmp
    si.width  = sp.bitmap.width
    si.height = sp.bitmap.height
    $rubber_rect.set_area( sp.width , sp.height )
    $prev_file =   dlg.file_name
    $ini['prev_file','prev_file'] = $prev_file	# 2000-10-24(火)
    $form.caption = $form_caption + ' .. ' + $prev_file
    $shape.visible = false
  end
end

$form.mi_paste .on_click = proc { paste }
def paste
  cb = Phi::CLIPBOARD
  if cb.has_format?(Phi::CF_BITMAP)
    si = $src_image
    sp = $src_image.picture
    sp.assign cb
    si.width  = sp.bitmap.width
    si.height = sp.bitmap.height
    $rubber_rect.set_area( sp.width , sp.height )
    $form.caption = $form_caption + ' .. Clipboard'
    $shape.visible = false
  end
end

    ##
    ##  --  ゴムバンド
    ##
$src_image.on_mouse_down = proc do |sender,btn,sft,x,y|
  if btn == Phi::MB_LEFT
    $shape.rect = $rubber_rect.start( x,y )
    $shape.show
    $dragging = true
    $form.mi_cursors.enabled = false
  end
end

$src_image.on_mouse_move = proc do |sender,sft,x,y|
  if $dragging
    $shape.rect = $rubber_rect.move_to( x,y )
  end
end

$src_image.on_mouse_up = proc do |sender,btn,sft,x,y|
  if $dragging
    $dragging = false
    $form.mi_cursors.enabled = true
    exchange_image if $rubber_rect.alive?
  end
end

$form.mi_up     .on_click = proc { expand_rect  0, 0, 0,-1 }
$form.mi_down   .on_click = proc { expand_rect  0, 0, 0,+1 }
$form.mi_left   .on_click = proc { expand_rect  0, 0,-1, 0 }
$form.mi_right  .on_click = proc { expand_rect  0, 0,+1, 0 }
$form.mi_sup    .on_click = proc { expand_rect  0,-1, 0, 0 }
$form.mi_sdown  .on_click = proc { expand_rect  0,+1, 0, 0 }
$form.mi_sleft  .on_click = proc { expand_rect -1, 0, 0, 0 }
$form.mi_sright .on_click = proc { expand_rect +1, 0, 0, 0 }

def expand_rect(left, top, right, bottom)
  $shape.rect = $rubber_rect.expand left, top, right, bottom
  copy_image if $dst_image.visible
end

    ##
    ##  --  初期設定
    ##
def fix_size
    sc = Phi::SCREEN
    fm = Phi::SCREEN.form1

    width  = sc.width/4*3
    height = sc.height/4*3
    left   = (sc.width - width )/2
    top    = (sc.height- height)/2

    fm.width  = width
    fm.height = height
    fm.left   = left
    fm.top    = top

    ##
    ##  ここを有効にすると、スクロールバーが出るが、
    ##  スクロール時の調整が面倒なので、
    ##  このバージョンではスクロール不可とする。
    ##
    ##$src_image.align = Phi::AL_NONE
    ##$dst_image.align = Phi::AL_NONE

    ##fm.window_state = Phi::WS_MAXIMIZED
end

exchange_image( true )
paste
fix_size
$form.show
Phi.mainloop
