# GLINT graphical package management
# Copyright (C) 1995 Red Hat, Inc
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

from Tkinter import *
from rhtkinter import *
from group import *
from package import *
from packageset import *
from icon import *

class PackageArea(RHFrame):
    def createPackage(self, x, y, ix, package):
	pass 
    def createGroup(self, x, y, ix, group):
	pass 
    def redrawDisplay(self, e = None):
	pass 
    def changeGroup(self, group, newWin):
	pass 
    def setGroup(self, group):
	pass 

    def __init__(self, Master=None):
	RHFrame.__init__(self, Master)

class CustomCommand(RHFrame):
    def __init__(self, command, arg):
	self.command = command
	self.arg = arg

    def call(self):
	self.command(self.arg)
	
class NestedArea(PackageArea):

    c = Canvas()
    back = c['background']
    c.destroy()

    defaultPackageImage = RHPhoto()
    defaultPackageImage.transparentColor(back)
    defaultPackageImage.read("defpackage.gif")

    defaultFolderImage = RHPhoto()
    defaultFolderImage.read("deffolder.gif")

    backImage = RHPhoto()
    backImage.read("back.gif")

    def createPackage(self, x, y, xoff, package):
	ix = x + xoff
	backdrop = self.C.create_polygon(ix, y, ix + 68, y, ix + 68, y + 68,
					 ix, y + 68 ,
					 { 'fill' : self.C['back'] } )
	self.C.addtag('back', 'withtag', backdrop)

	if (package.getIcon()):
	    f = open("/tmp/glint.gif", "w")
	    f.write(package.getIcon())
	    f.close()
	    image = RHPhoto()
	    image.read("/tmp/glint.gif")
	
	    self.imageList.append(image)

	    pack = self.C.create_image(ix+34, y+34, 
			    { 'image' : image } )
	else:
	    pack = self.C.create_image(ix+34, y+34, 
			    { 'image' : self.defaultPackageImage } )

	self.C.addtag('icon', 'withtag', pack)
	text = self.C.create_text(ix + 34, y + 72, { 'text' :package.getName()})
	rev = self.C.create_text(ix + 34, y + 82, 
				 { 'text' : package.getRevision() } )

	self.map[backdrop] = package;
	self.map[pack] = package;
	self.map[text] = package;
	self.map[rev] = package;
	self.type[package] = 'package'

	icon = BackIcon(self.C, pack, backdrop)
	if (package.selected):
	    icon.select()

	package.addSelectCallback(icon.selectCallback, self, None)

    def createGroup(self, x, y, xoff, group):
	ix = x + xoff
	backdrop = self.C.create_polygon(ix, y, ix + 68, y, ix + 68, y + 68,
					 ix, y + 68, 
					 { 'fill' : self.C['back'] } )
	self.C.addtag('back', 'withtag', backdrop)
	folder = self.C.create_image(ix+34, y+34, 
			{ 'image' : self.defaultFolderImage } )
	self.C.addtag('icon', 'withtag', folder)
	text = self.C.create_text(ix + 34, y + 72, { 'text' : group.getName()} )
	num = self.C.create_text(ix + 34, y + 34, 
		{ 'text' : group.getSelectedString() } )

	self.map[backdrop] = group
	self.map[folder] = group
	self.map[text] = group
	self.map[num] = group
	self.type[group] = 'group'

	group.addSelectCallback(self.countChanged, self, num)

    def createBack(self, xoff):
	ix = 0 + xoff
	backdrop = self.C.create_polygon(xoff, 0, 68, xoff, 0, 68, xoff, 68, 
					 xoff, 68, 
					 { 'fill' : self.C['back'] } )
	self.C.addtag('back', 'withtag', backdrop)
	folder = self.C.create_image(ix+34, 34,
			{ 'image' : self.backImage } )
	self.C.addtag('icon', 'withtag', folder)
	text = self.C.create_text(34 + xoff, 72, { 'text' : 'Back' } )

	icon = BackIcon(self.C, folder, backdrop)

	self.map[backdrop] = icon;
	self.map[folder] = icon;
	self.map[text] = icon;
	self.type[icon] = 'back'

    def countChanged(self, group, text):
	self.C.itemconfig(text, { 'text' : group.getSelectedString() } )
	self.selectCallback()

    def selectCallback(self, selected = None, icon = None):
	if (self.showSize):
	    self.Selected['text'] = ("Packages selected: %d (%dkb)" % 
		    (self.group.getRoot().getNumberSelected(),
		     self.group.getRoot().getSelectedSize() / 1024))
	else:
	    self.Selected['text'] = ("Packages selected: %d" % 
		    (self.group.getRoot().getNumberSelected()))

    def redrawCallback(self, group = None, data = None):
	if (self.group.empty()):
	    group = self.group
	    while (group.empty() and group.getParent()):
		group = group.getParent()
	    self.changeGroup(group, 0)
	else:
	    self.redrawDisplay()

    def showMenu(self, event):
	itemtup = event.widget.find_withtag("current")
	if (itemtup):
	    (item, ) = itemtup;
	    thing = self.map[item]

	    if (self.type[thing] == 'group'):
		self.currGroupMenuGroup = thing
		self.groupMenu.postev(event)
	    elif (self.type[thing] == 'package'):
		self.currPackageMenuPackage = thing
		self.packageMenu.postev(event)

    def oneClick(self, event):
	itemtup = event.widget.find_withtag("current")
	if (itemtup):
	    (item, ) = itemtup;
	    thing = self.map[item]

	    if (self.type[thing] == 'package'):
		thing = self.map[item]
		thing.toggleSelect()

    def newWindow(self, event = None):
	itemtup = event.widget.find_withtag("current")
	if (itemtup):
	    (item, ) = itemtup;
	    thing = self.map[item]

	    if (self.type[thing] == 'group'):
		self.changeGroup(thing, 1)

    def twoClicks(self, event):
	itemtup = event.widget.find_withtag("current")
	if (itemtup):
	    (item, ) = itemtup;
	    thing = self.map[item]

	    if (self.type[thing] == 'back'):
		self.popGroup()
	    elif (self.type[thing] == 'group'):
		self.changeGroup(thing, 0)

    def cleanupCanvas(self):
	for thing in self.type.keys():
	    if (self.type[thing] != 'back'):
		thing.removeSelectCallback(self)
	self.type = {}
	self.imageList = []
	self.C.delete("all")

    def cleanup(self):
	self.cleanupCanvas()
	self.type = {}
	if (self.group):
	    self.group.getRoot().removeSelectCallback(self)
	    self.group.removeRedrawCallback(self)

    def redrawDisplay(self, e = None):
	self.cleanupCanvas()

	if (e):
	    self.C['width'] = e.width - 4  
	maxLabelLen = 0
	maxLabel = ""
	for group in (self.group.getSubgroups() + 
			self.group.getPackageSet().getPackages()):
	    name = group.getName()
	    length = len(name)
	    if (length > maxLabelLen):
		maxLabelLen = length
		maxLabel = name

	text = self.C.create_text(0, 0, { 'text' : maxLabel } )
	(x1, y1, x2, y2) = self.C.bbox(text)
	itemwidth = x2 - x1 + 6
	if (itemwidth < 72):
	    itemwidth = 72
	if (x1 < -25):
	    ix = - (x1 + 25)
	else:
	    ix = 0
	self.C.delete("all")
	
	x = 0
	y = 0 
	width = string.atoi(self.C['width'])

	self.Path['text'] = "Path: " + self.group.getPath()

	if (self.group.getParent() == None):
	    self.backfolder = None
	else :
	    self.createBack(ix)
	    x = itemwidth

	for group in self.group.getSubgroups():
	    self.createGroup(x, y, ix, group)
	    x = x + itemwidth;
	    if (x + itemwidth > width) :
		x = 0
		y = y + 95

	for package in self.group.getPackageSet().getPackages():
	    self.createPackage(x, y, ix, package)
	    x = x + itemwidth;
	    if (x + itemwidth > width):
		x = 0
		y = y + 95

	if (x > 0):
	    y = y + 95

	self.C['scrollregion'] = '0 0 %d %d' % (width, y)

    def getGroup(self):
	return self.group

    def setGroup(self, group):
	self.cleanup()
	self.group = group;
	self.group.getRoot().addSelectCallback(self.selectCallback, self, None)
	self.group.addRedrawCallback(self.redrawCallback, self, None)
	self.redrawDisplay();
	self.selectCallback()

    def popGroup(self):
	parent = self.group.getParent()
	if (parent == None):
	    return
	self.setGroup(parent)

    def changeGroup(self, group, newWin):
	self.parent.changeGroup(group, newWin)

    def pushGroup(self, group):
	self.setGroup(group)

    def createWidgets(self):
	self.C = Canvas(self, { 'width' : '400'} )
        self.C.bind("<1>", self.oneClick)
        self.C.bind("<3>", self.showMenu)
        self.C.bind("<Double-1>", self.twoClicks)
        self.C.bind("<Double-2>", self.newWindow)
        self.C.bind("<Configure>", self.redrawDisplay)

	self.VscrollF = Frame(self)
	self.Vscroll = Scrollbar(self.VscrollF, { 'orient' : 'vertical' ,
				         'command' : self.C.yview } )
	self.C['yscrollcommand'] = self.Vscroll.set;

	self.PathF = Frame(self)
	self.Path = Label(self.PathF, { 'text' : 'Path:' , 'relief' : 'raised',
				  'anchor' : 'w' } )
	
	self.Path.pack({ 'side' : 'left', 'anchor' : 'w' , 'expand' : '1', 
				'fill' : 'x' } )
	self.PathF.pack({ 'anchor' : 'w' , 'fill' : 'x' } )

	self.SelectedF = Frame(self)
	self.Selected = Label(self.SelectedF, { 'text' : 'Size:' , 
				                'relief' : 'raised',
				                'anchor' : 'w' } )
	self.Selected.pack({ 'side' : 'left', 'anchor' : 'w' , 'expand' : '1', 
			     'fill' : 'x' } )
	self.SelectedF.pack({ 'anchor' : 'w' , 'fill' :'x', 'side' :'bottom' } )

	self.Vscroll.pack({ 'side' : 'top', 'expand' : '1', 'fill' : 'y'})
	self.VscrollF.pack({ 'side' : 'right', 'fill' : 'y'})

	self.C.pack({ 'expand' : '1', 'fill' : 'both' })

    def addToMenus(self, label, command):
	self.packageMenu.add('command', { 'label' : label,
				   'command' : CustomCommand(self.menuCall, 
							 (command, "p")).call } )
	self.groupMenu.add('command', { 'label' : label,
				   'command' : CustomCommand(self.menuCall,
							 (command, "g")).call } )

    def menuCall(self, info):
	(command, arg) = info
	if (arg == 'g'):
	    packages = self.currGroupMenuGroup.getPackages()
	    command(packages)
	else:
	    packages = PackageSet()
	    packages.addPackage(self.currPackageMenuPackage)
	    command(packages)

    def selectMenuChoice(self, packages):
	packages.selectAll()

    def unselectMenuChoice(self, packages):
	packages.unselectAll()
 
    def createPopups(self):
	self.packageMenu = Popup()
	self.groupMenu = Popup()
	self.addToMenus('Select', self.selectMenuChoice)
	self.addToMenus('Unselect', self.unselectMenuChoice)

    def __init__(self, showSize, Master = None):
	PackageArea.__init__(self, Master)
	self.group = None
	self.type = {}
	self.map = {}
	self.imageList = []
	self.showSize = showSize
	self.createWidgets()
	self.createPopups()
	self.pack()
	self.parent = Master
