#!ruby

require "exifreader"
require "nomenclature"
require "find"

require "fox"
require "tempfile"

include Fox

# vim:set noet:set ts=3:set sts=3:
# vim:set shiftwidth=3:


# icons from http://primates.ximian.com/~tigert/new_stock_project/

class ExifViewer < FXMainWindow

  include Responder

  BROKEN_ICON = "icon/stock_broken_image.png"
  FOLDER_OPEN = "icon/stock_open.png"

  ID_CLICKEDITEM,
  ID_LAST = enum(FXMainWindow::ID_LAST, 47)

  RHEIGHT = -1
  RWIDTH = -1
  # for the initial application size, nothing important
  NCOL = 5

  VERSION = "1.1.0"
  # chore task
  # deals with picture rendering in the table
  def onChore(sender,sel,ptr)
	 if @disable_chore_button.state && @index!=nil && @pic_list.length > @index
		current_file = @pic_list[@index]
		# if the current file is a file (its thumbnail is itself)
		if FileTest.file?(current_file)
		  display(@pic_list[@index])
		end
		self.status=(@pic_list.length-@index).to_s+" items remaining"
		@progressbar.setTotal(@pic_list.length)
		@progressbar.setProgress(@index)
		@index += 1
	 end
	 if @index && @index==@pic_list.length
		# we are at the end of the list
		@disable_chore_button.disable
		# done
		self.status=@pic_list.length.to_s+" items"
		
		@progressbar.setTotal(1)
		@progressbar.setProgress(0)
		@progressbar.disable
		
		@index += 1
	 end
	 @chore = getApp().addChore(method(:onChore))
  end
  # show file in the list called by onChore
  def display(file)
	 image = JPEGImage.new()
	 begin
		image.load_from_file(file)
		  
		ifd1 = image.getElementByTagName("IFD1")
		if ifd1!=nil
		  icon = FXJPGIcon.new(getApp(),ifd1.thumb_data)
		  if RHEIGHT!=-1 && RWIDTH!=-1
			 if icon.width>RWIDTH ||icon.height>RHEIGHT
				if icon.width>RWIDTH && (icon.width.to_f/RWIDTH)>(icon.height.to_f/RHEIGHT)
				  new_w=RWIDTH
				  new_h=icon.height*RWIDTH/icon.width
				elsif icon.height>RHEIGHT && (icon.height.to_f/RHEIGHT)>(icon.width.to_f/RWIDTH)
				  new_h=RHEIGHT
				  new_w=icon.width*RHEIGHT/icon.height
				end
				icon.scale(new_w,new_h)
			 end
		  end
		  icon.create
		else
			 # no IFD1 available
		end
	 rescue ArgumentError
	 end
	 @iconlist.setItemBigIcon(@list.index(file),icon)
	 if image.comment
		@iconlist.setItemText( @list.index(file), image.comment.to_s )
	 end
	 return 1
  end
  def onContextMenuOpen(sender, sel, event)
	 if event.moved then return 1 end
	 
	 item_num = @iconlist.getItemAt( event.win_x, event.win_y )
	 
	 file = @list[item_num]
	 popup = EVContextMenu.new self, file, FileTest.directory?(file)
	 popup.create
	 popup.popup(nil, event.root_x, event.root_y)
	 popup.grabKeyboard
	 getApp().runModalWhileShown popup
	 return 1
  
  end
  # changes the statusbar
  def status=(t)
	 @statusbar.setText( t )
  end
  # someone clicked on an item
	def onDblClickItem(sender, sel, ptr)
	 
	 #@context_popup.popdown # doesn't seem to work..
	 
	 file = @list[ptr]
	 if FileTest.directory?(file)
		begin
		  Dir.chdir(file)
		  redraw_list
		rescue Errno::EACCES
		  self.status="Permission Denied to enter "+file
		else
		  self.status="Entering "+file
		end
	 else

		show_detail_window(@list[ptr])
	 end
  end
  #show the details for the file file
  def show_detail_window(file)
	 info = FXImageInfoDialog.new(self,file)
	 info.execute(PLACEMENT_SCREEN)
  end
  # redraw the current list 
  # we probably just changeg the current folder
  def redraw_list
	 d = Dir.entries(".")
	 # TODO: get the real list of hdd available...
	 d.push("C:","D:","E:","F:")
	 
	 @iconlist.clearItems
	 # display empty boxes
	 d.reject{ |f| FileTest.file?(f)}.sort.each{ |f|
		item = FXIconItem.new(f, @folder_icon )

		@list[@iconlist.appendItem(item)]=f
	 }
	 @pic_list = d.reject{ |f|
		FileTest.directory?(f) || !(f=~/\.jpe?g$/i) 
	 }.sort
	 # set default icon
	 @pic_list.each{ |f|
		icon = @broken_image_icon
		icon = @folder_icon if FileTest.directory?(f)
		item = FXIconItem.new(f,icon,nil)
		@list[@iconlist.appendItem(item)]=f
	 }
	 # start the drawing
	 @disable_chore_button.enable
	 @index = 0
  end
  # $Id: ExifViewer.rb,v 1.10 2003/03/18 23:44:36 oct Exp $
  def initialize(anApp)
	 if RHEIGHT!=-1 && RWIDTH!=-1
		super(anApp, "COM Marker Viewer "+VERSION, nil, nil, DECOR_ALL,
				0, 0, NCOL*(RWIDTH+20)+30+200, RHEIGHT*5, 0, 0)
	 else
		super(anApp, "COM Marker Viewer "+VERSION, nil, nil, DECOR_ALL,
				0, 0, NCOL*100+30+200, 100*5, 0, 0)
	 end
		 
	
	 frame = FXVerticalFrame.new(self, LAYOUT_FILL_X|LAYOUT_FILL_Y)
	 
	 @folder_icon = FXPNGIcon.new(getApp(),File.open(FOLDER_OPEN,"rb").read(), FXRGB(0,0,0))
	 
	 
	 @broken_image_icon = FXPNGIcon.new( getApp(), File.open( BROKEN_ICON, "rb" ).read(), FXRGB( 0, 0, 0 ) )

	 buttonbox = FXHorizontalFrame.new( frame, LAYOUT_FILL_X, 0, 0, 0, 20 )
	 @disable_chore_button = FXToggleButton.new( buttonbox, "GO","Abort" )
	 @iconlist = FXIconList.new( frame, nil, 0, ICONLIST_BIG_ICONS|LAYOUT_FILL_X|LAYOUT_FILL_Y|ICONLIST_COLUMNS )
	
	vframe = FXHorizontalFrame.new(frame, LAYOUT_FILL_X)
	
	 # code inspired from Lyle
	@statusbar = FXLabel.new(vframe, "Ready.", nil, 
		JUSTIFY_LEFT|FRAME_SUNKEN|LAYOUT_SIDE_BOTTOM|LAYOUT_FILL_X)
	 @progressbar = FXProgressBar.new( vframe, nil, 0, 
		FRAME_SUNKEN|LAYOUT_CENTER_Y|LAYOUT_FIX_WIDTH, 0, 0, 200, 2,2,5,5)
	 
	 
	 # handles left click
	 @iconlist.connect(SEL_DOUBLECLICKED,method(:onDblClickItem))
	 # handles right click
	 @iconlist.connect( SEL_RIGHTBUTTONRELEASE, method(:onContextMenuOpen) )
  end
  def create
	 super
	 @list=[]
	 @index = nil
	 @disable_chore_button.state = true
	 
	 @chore = getApp().addChore(method(:onChore))
	 
	 @folder_icon.create
	 @broken_image_icon.create
	 
	 self.show(PLACEMENT_SCREEN)
	 redraw_list
  end
end
class EVContextMenu < FXMenuPane
  def initialize window, name, isFolder = true
	 super window
	 
	 @window = window
	 @isFolder = isFolder
	 @name = name
	 
	 if @isFolder
		titlename = "Folder: "+@name
	 else
		titlename = "File: "+@name
	 end
	 a = FXOption.new(self, titlename)
	 a.disable
	 FXOption.new(self, "Choose Thumbnail").connect(SEL_COMMAND) { 
		ExifViewer.new(getApp())
	 }
	 FXOption.new(self, "Exclude From HTML")
	 # TODO implement COM Marker comment !
	 a = FXOption.new(self, "Rename")
	 a.disable
	 FXOption.new(self, "Set name").connect(SEL_COMMAND) {
			i = JPEGImage.new()
			i.load_from_file(@name)
			i.comment="Altered By Rubum"
			i = nil
			#window.display(@name)
	 }
  end
end
 
class FXImageInfoDialog < FXDialogBox
  def initialize(aWindow, file)
	 super(aWindow, "Details for "+file, DECOR_ALL, 0,0, 640, 400)
	 
	 
	 frame = FXVerticalFrame.new(self, LAYOUT_FILL_X| LAYOUT_FILL_Y)
	 # the central splitter
	 @big_splitter = FXSplitter.new(frame, SPLITTER_NORMAL |
			 LAYOUT_FILL_X | LAYOUT_FILL_Y )
	 # the treelist on the left
	 @treelist = FXTreeList.new(@big_splitter, 0, nil, 0, 
			 TREELIST_SHOWS_LINES|TREELIST_SHOWS_BOXES|
			 TREELIST_NORMAL | LAYOUT_FILL_X | LAYOUT_FILL_Y, 0, 0, 300, 0)
	 # the image on the right
	 @image_view = FXImageView.new(@big_splitter, nil, nil, 0, 
			 LAYOUT_FILL_X | LAYOUT_FILL_Y)
	 # the bottom close button
	 buttonbox = FXHorizontalFrame.new(frame, LAYOUT_FILL_X, 0, 0, 0, 20)
	 ok_button = FXButton.new(buttonbox, "OK")
	 @file = file
  end
  def create
		getApp.beginWaitCursor;
	 img = fill_info
	 super
	 rheight = @image_view.height
	 rwidth = @image_view.width
	 # keep ratio
	 if img.width>rwidth ||img.height>rheight
		if img.width>rwidth && (img.width.to_f/rwidth)>(img.height.to_f/rheight)
		  new_w=rwidth
		  new_h=img.height*rwidth/img.width
		elsif img.height>rheight && (img.height.to_f/rheight)>(img.width.to_f/rwidth)
		  new_h=rheight
		  new_w=img.width*rheight/img.height
		end
		img.scale(new_w,new_h)
	 end
	 img.create
	 @image_view.setImage(img)
	 getApp.endWaitCursor;
	 
  end
  def fill_info
	 image = JPEGImage.new()
	 image.load_from_file(@file)
	 #ifd1 = image.getElementByTagName("IFD1")
	 #		if ifd1!=nil
	 #  img = FXJPGImage.new(getApp(),ifd1.thumb_data)
	 #else
		file = FXFileStream.new
		file.open(@file, FXStreamLoad)
		img = FXJPGImage.new(getApp())
		img.loadPixels(file)
	 #end
			
	 exif = @treelist.addItemLast(nil, "EXIF")
	 image.listTag.each{ |tag| 
		if tag.short_name!=nil
		  @treelist.addItemLast(exif, tag.short_name.gsub(/([A-Z])/,' \1')+" : "+tag.value.inspect)
		else
		  @treelist.addItemLast(exif, "Unknown Tag("+"%04x"%tag.marker_type+")")
		end
	 }
	 @treelist.expandTree(exif)
	 return img
  end
end


theApp = FXApp.new("COM Marker Viewer", "Pierre Baillet")
ExifViewer.new(theApp)
theApp.create
theApp.run


#vim6:set noet
