#!/usr/bin/env python

# TODO make PgUp PgDown drag the selection along

import pygtk
pygtk.require("2.0")
import gtk
import os
from iconsize import IS

iconPaths = [
]

def sortbyname(ofiles):
	nfiles = {}
	for fpath in ofiles:
		fname = os.path.basename(fpath)

		if not fname in nfiles: nfiles[fname] = []

		nfiles[fname].append(fpath)

	ks = nfiles.keys()
	ks.sort()

	xfiles = []
	for k in ks:
		blu = nfiles[k]
		blu.sort()
		for bl in blu: xfiles.append(bl)

	return xfiles

def pathylistdir(dname, currentDepth = 0, recursive = True):
	nfiles = []
	try:
		files = os.listdir(dname)
		for fname in files:
			if fname.startswith("."): continue
			fpath = dname + os.sep + fname

			if os.path.isfile(fpath):
				nfiles.append(fpath)
			elif os.path.isdir(fpath) and recursive == True:
				if currentDepth < 10:
					xfs = pathylistdir(fpath, currentDepth + 1)
					for xf in xfs: nfiles.append(xf)
	except:
		pass

	return nfiles

class GIconChooser(gtk.Dialog):
	global IS
	def __init__(self, parent, iconsize = int(IS * 1.5), title = None):
		gtk.Dialog.__init__(self, parent = parent)

		try:
			if title != None:
				ot = title
			else:
				ot = parent.get_title()
		except:
			ot = ""
			pass

		if title != None:
			if ot != "":
				self.set_title("%s - %s" % (ot, title))
			else:
				self.set_title(title)
		else:
			if ot != "":
				self.set_title(ot)
			else:
				pass
				#self.set_title(myapp)

		self.iconsize = iconsize
		self.cols = 7
		self.padx = 5
		self.pady = 5

		self.icons = {}
		self.iconsR = {}

		self.add_button(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL)
		self.add_button(gtk.STOCK_OK, gtk.RESPONSE_OK)

		self.set_default_response(gtk.RESPONSE_OK)

		self.table = gtk.Table(1, self.cols)
		self.table.show()

		self.seb = gtk.EventBox()
		self.seb.add_events(gtk.gdk.KEY_PRESS | gtk.gdk.KEY_RELEASE)
		self.seb.connect("key-press-event", self.seb_key_press_event_cb)

		self.seb.show()

		self.sw = gtk.ScrolledWindow()
		self.sw.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)

		self.viewport = gtk.Viewport()
		self.viewport.add(self.table)
		self.viewport.show()

		self.sw.add(self.viewport)

		#= self.sw.add_with_viewport(self.table)
		self.sw.show()

		self.seb.add(self.sw)

		nameL = gtk.Label("Name:")
		nameL.show()
		self.nameE = gtk.Entry()
		self.nameE.connect("changed", self.name_changed_cb)
		self.nameE.show()

		self.hname = gtk.HBox(False, 5)
		self.hname.pack_start(nameL, False, False)
		self.hname.pack_start(self.nameE, True, True)
		self.hname.show()

		self.vbox.pack_start(self.seb, True, True)
		self.vbox.pack_start(self.hname, False, False)
		self.refresh()
		self.set_size_request(-1, 400)

		self.choosed = None
		self.choosedPos = None

		self.viewport.get_vadjustment().connect("value-changed", self.viewport_valueChanged_cb)
		self.internalValueChanged = False

	def viewport_valueChanged_cb(self, widget):
		if self.internalValueChanged == True: return

		self.choosedPos = None

	def name_changed_cb(self, nameE):
		if self.internalSetText == True:
			return

		search = self.nameE.get_text()

		for icon in self.icons.values():
			if icon["name"].startswith(search):
				self.choose(icon["eb"])
				return

	def refresh(self):
		# TODO clear table, set row count to 0/1

		for icon in self.icons.values():
			icon["eb"].destroy()

		self.table.resize(1, self.cols)

		x = 0
		y = 0
		cols = self.cols
		self.icons = {}
		self.iconsR = {}

		files = []
		files = files + pathylistdir("/usr/share/pixmaps", recursive = False)
		files = files + pathylistdir("/usr/share/icons")

		files = sortbyname(files)

		for fname in files:
			try:
				pb = gtk.gdk.pixbuf_new_from_file(fname)
				pb = pb.scale_simple(self.iconsize, self.iconsize, gtk.gdk.INTERP_NEAREST)
				img = gtk.Image()
				img.set_from_pixbuf(pb)
				img.show()
				eb = gtk.EventBox()
				#eb.add_events(gtk.gdk.KEY_PRESS | gtk.gdk.KEY_RELEASE)
				eb.connect("button-press-event", self.eb_button_press_event_cb)
				eb.connect("key-press-event", self.key_press_event_cb)
				eb.add(img)
				eb.show()
				self.table.attach(eb, x, x + 1, y, y + 1, 0, 0, self.padx, self.pady)

				key = "%d,%d" % (x, y)
				name = os.path.basename(fname)
				self.icons[key] = { "path": fname, "pb": pb, "eb": eb, "x": x, "y": y, "name": name }
				self.iconsR[eb] = key

				x = x + 1
				if x >= cols:
					x = 0
					y = y + 1
			except:
				pass

		self.lasty = y

	def eb_button_press_event_cb(self, eb, event):

		self.choose(eb)

		if event.type == gtk.gdk._2BUTTON_PRESS:
			self.response(gtk.RESPONSE_OK)

	def choose(self, eb):
		try:
			key = self.iconsR[eb]
			icon = self.icons[key]
		except:
			return

		if self.choosed != None:
			try:
				okey = self.iconsR[self.choosed]
				oicon = self.icons[okey]
				pb = oicon["pb"]
				self.choosed.get_children()[0].set_from_pixbuf(pb)
			except:
				pass

			self.choosed = None

		self.choosed = eb
		pb = icon["pb"]

		try:
			pm = gtk.gdk.Pixmap(self.window, pb.get_width(), pb.get_height(), -1)
			#pm, mask = pb.render_pixmap_and_mask(0)

			gc = pm.new_gc()
			w = pb.get_width()
			h = pb.get_height()

			cFore = gtk.gdk.color_parse("#0000F0")
			gc.set_rgb_fg_color(cFore)
			pm.draw_rectangle(gc, True, 0, 0, w, h)

			#draw_pixbuf
			pb.render_to_drawable(pm, gc, 0, 0, 0, 0, w, h, gtk.gdk.RGB_DITHER_NONE, 0, 0)

			cmap = pm.get_colormap()
			#pb = gtk.gdk.Pixbuf()
			pb = pb.copy()
			pb.get_from_drawable(pm, cmap, 0, 0, 0, 0, w, h)
		except:
			raise
			pb = pb.scale_simple(self.iconsize + 8, self.iconsize + 8, gtk.gdk.INTERP_NEAREST)

		eb.get_children()[0].set_from_pixbuf(pb)

		x = icon["x"]
		y = icon["y"]
		
		self.choosedPos = x,y
		self.internalSetText = True
		self.nameE.set_text(icon["name"])
		self.internalSetText = False

		va = (self.viewport.allocation.width, self.viewport.allocation.height)
		ta = (self.table.allocation.width, self.table.allocation.height)

		if va[1] >= ta[1]: # table small enough
			return # too bad

		if self.choosed == None:
			return

		#key = self.iconsR[self.choosed]
		#icon = self.icons[key]

		global IS

		tia = [(IS + self.padx * 2), (IS + self.pady * 2)]
		tir = [- self.padx, - self.pady]
		ca = self.choosed.allocation
		tip = [ca.x, ca.y, ca.x + ca.width, ca.y + ca.height]

		vaj = self.viewport.get_vadjustment()

		vaju = vaj.get_property("upper")
		vajv = vaj.get_value()

		# vajv 0......... 0
		# vajv upper..... ta[1]-tia[1] + tir[1] .... upper
		# vajv v......... tip[3] ................... v

		vajv = vaju * tip[1] / (ta[1]) #-tia[1] + tir[1])
		vajv2 = vaju * tip[3] / (ta[1]) #-tia[1] + tir[1])

		self.internalValueChanged = True
		#vaj.set_value(vajv)
		vaj.clamp_page(vajv, vajv2)
		self.internalValueChanged = False

	def newCursor(self):
		global IS

		va = (self.viewport.allocation.width, self.viewport.allocation.height)
		ta = (self.table.allocation.width, self.table.allocation.height)

		tia = [(IS + self.padx * 2), (IS + self.pady * 2)]
		tir = [- self.padx, - self.pady]


		vaj = self.viewport.get_vadjustment()

		vaju = vaj.get_property("upper")
		vajv = vaj.get_value()

		# vajv upper..... ta[1]-tia[1] + tir[1] .... upper
		# vajv v......... tip[3] ................... v

		#print vajv, vaju, (ta[1]-tia[1] + tir[1])
		
		cy = int((ta[1]-tia[1] + tir[1]) * vajv / vaju  - tir[1])

		sorty = []
		for key, icon in self.icons.items():
			ay = icon["eb"].allocation.y
			if ay >= cy: sorty.append((ay, icon))

		sorty.sort()
		y = 0

		try:
			y = sorty[0][1]["y"]
		except:
			y = 0
		
		if y > self.lasty: y = self.lasty

		return 0,y

	def seb_key_press_event_cb(self, widget, event):
		return self.key_press_event_cb(None, event)

	def key_press_event_cb(self, widget, event):
		if self.choosedPos != None:
			x,y = self.choosedPos
		else:
			x,y = None,None

		if x == None:
			x, y = self.newCursor()
		elif event.keyval == gtk.gdk.keyval_from_name("Down"):
			y = y + 1
		elif event.keyval == gtk.gdk.keyval_from_name("Up"):
			y = y - 1
		elif event.keyval == gtk.gdk.keyval_from_name("Right"):
			x = x + 1
		elif event.keyval == gtk.gdk.keyval_from_name("Left"):
			x = x - 1
		else:
			return False

		if x < 0 or y < 0 or x >= self.cols or y > self.lasty:
			return True

		try:
			key = "%d,%d" % (x,y)
			eb = self.icons[key]["eb"]
			self.choose(eb)
		except:
			raise
			pass

		return True

	def getChosen(self):
		try:
				key = self.iconsR[self.choosed]
				icon = self.icons[key]
				return icon["path"]
		except:
			return None

if __name__ == "__main__":
	ic = GIconChooser(parent = None)
	if ic.run() == gtk.RESPONSE_OK:
		print ic.getChosen()

	#gtk.main()

