# Sketch - A Python-based interactive drawing program
# Copyright (C) 1998 by Bernhard Herzog
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Library General Public
# License as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	See the GNU
# Library General Public License for more details.
#
# You should have received a copy of the GNU Library General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307	USA

from types import TupleType

import pax

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

from Sketch.const import COMMAND
from Sketch import Publisher, const

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
