# -*- coding: utf-8 -*-

# Copyright (C) 2003-2006 by Igor E. Novikov
# Copyright (C) 1998 by Bernhard Herzog
#
# This library is covered by GNU Library General Public License.
# For more info see COPYRIGHTS file in sK1 root directory.

from types import TupleType

import pax

from Tkinter import IntVar, X, Y, LEFT, RIGHT, E
from tkext import PyWidget, MyEntry

from app.conf.const import COMMAND
from app.conf import const
from app import Publisher


cursors = (const.CurUp, const.CurUpDown, const.CurDown)

class MiniScroller(PyWidget, Publisher):

	def __init__(self, master=None, min = None, max = None, step = 1,
					variable = None, command = None, args = (), **kw):
		if not kw.has_key('width'):
			kw['width'] = 8
		apply(PyWidget.__init__, (self, master), kw)
		self.SetRange(min, max, step)
		self.variable = variable
		self.state = 0		# 1: up; 2: drag; 3: down
		self.rect_y = 0
		self.start = 0
		self.start_number = min
		if command:
			self.set_command(command, args)
		self.bind('<Motion>', self.MotionEvent)
		self.bind('<ButtonPress-1>', self.ButtonPressEvent)
		self.bind('<ButtonRelease-1>', self.ButtonReleaseEvent)

	def ResizedMethod(self, width, height):
		button_height = 4
		rect_y = (height - button_height) / 2
		self.top_poly = [(-1, rect_y), (width / 2, -1), (width, rect_y)]
		y = button_height + rect_y
		self.bot_poly = [(-1, y), (width, y), (width / 2, height)]
		self.rect_y = rect_y

	def SetRange(self, min, max, step = 1):
		self.min = min
		self.max = max
		self.step = step

	def set_command(self, command, args):
		if type(args) != TupleType:
			args = (args,)
		apply(self.Subscribe, (COMMAND, command,) + args)

	def invoke(self):
		self.issue(COMMAND)

	def RedrawMethod(self, region):
		button_height = 4
		win = self.tkwin
		width = win.width
		border = self.tkborder

		border.Draw3DRectangle(win, 0, self.rect_y, width, button_height, 2,
								pax.TK_RELIEF_RAISED)
		border.Draw3DPolygon(win, self.top_poly, -2, pax.TK_RELIEF_SUNKEN)
		border.Draw3DPolygon(win, self.bot_poly, -2, pax.TK_RELIEF_SUNKEN)

	def y_to_state(self, y):
		if y < self.rect_y:
			return 1
		elif y < self.rect_y + 4:
			return 2
		else:
			return 3

	def set_variable(self, y):
		if self.variable:
			number = self.start_number + self.step * (self.start - y)
			if self.min is not None and number < self.min:
				number = self.min
			if self.max is not None and number > self.max:
				number = self.max
			self.variable.set(number)

	def MotionEvent(self, event):
		if self.state == 0:
			self['cursor'] = cursors[self.y_to_state(event.y) - 1]
		elif self.state == 2:
			self.set_variable(event.y)

	def ButtonPressEvent(self, event):
		self.state = self.y_to_state(event.y)
		self.start = event.y
		if self.variable:
			self.start_number = self.variable.get()

	def ButtonReleaseEvent(self, event):
		state = self.state
		if state == 1:
			self.set_variable(self.start - 1)
		elif state == 2:
			self.set_variable(event.y)
		elif state == 3:
			self.set_variable(self.start + 1)
		if state != 0:
			self.invoke()
		self.state = 0



def create_mini_entry(top, master, command, vartype = IntVar,
						min = 0, max = None, step = 1, scroll_pad = 2):
	var_number = vartype(top)
	entry = MyEntry(master, textvariable = var_number, justify = RIGHT,
					width = 6, command = command)
	entry.pack(side = LEFT, expand = 1, fill = X, anchor = E)
	scroll = MiniScroller(master, variable = var_number, min = min, max = max,
							step = step)
	scroll.pack(side = LEFT, fill = Y, pady = scroll_pad)
	scroll.Subscribe(COMMAND, command)
	return var_number
