# Sketch - A Python-based interactive drawing program
# Copyright (C) 1997, 1998, 1999, 2000, 2002 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

#
#	A Dialog for managing dynamic styles
#

from string import atoi

import Sketch
from Sketch import _, config
from Sketch.const import STYLE, SELECTION, COMMAND
from Sketch.warn import pdebug
from Sketch.Graphics.properties import property_names, property_titles, \
     property_types, FillProperty, LineProperty, FontProperty
from Tkinter import Button, Scrollbar, Frame, Checkbutton, Label, StringVar, \
     IntVar
from Tkinter import RIGHT, BOTTOM, X, Y, BOTH, LEFT, TOP, W, DISABLED, NORMAL,\
     END
from tkext import UpdatedButton, UpdatedListbox, MyEntry, MessageDialog

import skpixmaps
pixmaps = skpixmaps.PixmapTk

from sketchdlg import PropertyPanel, SKModal

class StylePanel(PropertyPanel):

    title = _("Styles")
    receivers = PropertyPanel.receivers[:]

    def __init__(self, master, main_window, doc):
	PropertyPanel.__init__(self, master, main_window, doc,
			       name = 'styledlg')

    def build_dlg(self):
	top = self.top

	button = UpdatedButton(top, text = _("Close"), name = 'close',
				       command = self.close_dlg)
	button.pack(side = BOTTOM, expand = 0, fill = X)
	button = UpdatedButton(top, text = _("Apply"),
			       command = self.apply_style,
			       sensitivecb = self.can_apply)
	button.pack(side = BOTTOM, expand = 0, fill = X)
	self.Subscribe(SELECTION, button.Update)

	button = UpdatedButton(top, text = _("Delete"),
			       command = self.remove_style,
			       sensitivecb = self.can_remove)
	button.pack(side = BOTTOM, expand = 0, fill = X)

	list_frame = Frame(top)
	list_frame.pack(side = TOP, expand = 1, fill = BOTH)

	sb_vert = Scrollbar(list_frame, takefocus = 0)
	sb_vert.pack(side = RIGHT, fill = Y)
	styles = UpdatedListbox(list_frame, name = 'list')
	styles.pack(expand = 1, fill = BOTH)
	styles.Subscribe(COMMAND, self.apply_style)
	sb_vert['command'] = (styles, 'yview')
	styles['yscrollcommand'] = (sb_vert, 'set')
	self.styles = styles

    def init_from_doc(self):
	self.styles_changed()
	self.Update()
	self.issue(SELECTION)

    def Update(self):
	self.styles.select_clear(0, END)
	properties = self.document.CurrentProperties()
	for name in properties.DynamicStyleNames():
	    idx = self.style_names.index(name)
	    self.styles.select_set(idx)
	    self.styles.see(idx)

    receivers.append((STYLE, 'styles_changed'))
    def styles_changed(self):
	self.style_names = self.document.GetStyleNames()
	self.styles.SetList(self.style_names)
	self.Update()

    can_apply = PropertyPanel.doc_has_selection

    def apply_style(self):
	sel = self.styles.curselection()
	if sel:
	    index = atoi(sel[0])
	    self.document.AddStyle(self.style_names[index])

    def can_remove(self):
	len(self.styles.curselection()) == 1

    def remove_style(self):
	sel = self.styles.curselection()
	if sel:
	    index = atoi(sel[0])
	    self.document.RemoveDynamicStyle(self.style_names[index])


class CreateStyleDlg(SKModal):

    title = _("Create Style")

    def __init__(self, master, object, style_names, **kw):
	self.object = object
	self.style_names = style_names
	apply(SKModal.__init__, (self, master), kw)

    def __del__(self):
	if __debug__:
	    pdebug('__del__', '__del__', self)

    def build_dlg(self):
	top = self.top

	self.var_style_name = StringVar(top)
	entry_name = MyEntry(top, textvariable = self.var_style_name,
					command = self.ok, width = 15)
	entry_name.pack(side = TOP, fill = X)

	properties = self.object.Properties()
	self.flags = {}
	for prop in property_names:
	    type = property_types[prop]
	    if type == FillProperty:
		state = self.object.has_fill and NORMAL or DISABLED
	    elif type == LineProperty:
		state = self.object.has_line and NORMAL or DISABLED
	    elif type == FontProperty:
		state = self.object.has_font and NORMAL or DISABLED
	    else:
		# unknown property type!
		continue
	    long, short = property_titles[prop]
	    self.flags[prop] = var = IntVar(top)
	    var.set(state == NORMAL)
	    radio = Checkbutton(top, text = long, state = state,
				variable = var)
	    radio.pack(side = TOP, anchor = W)

	but_frame = Frame(top)
	but_frame.pack(side = TOP, fill = BOTH, expand = 1)

	button = Button(but_frame, text = _("OK"), command = self.ok)
	button.pack(side = LEFT, expand = 1)
	button = Button(but_frame, text = _("Cancel"), command = self.cancel)
	button.pack(side = RIGHT, expand = 1)

	entry_name.focus()

    def ok(self, *args):
	name = self.var_style_name.get()
	if not name:
	    MessageDialog(self.top, title =_("Create Style"),
			  message = _("Please enter a style name."),
			  icon = 'info')
	    return
	if name in self.style_names:
	    MessageDialog(self.top, title =_("Create Style"),
			  message = _("The name `%(name)s' is already used.\n"
				      "Please choose another one.") % locals(),
			  icon = 'info')
	    return

	which_properties = []
	for prop, var in self.flags.items():
	    if var.get():
		which_properties.append(prop)
	self.close_dlg((name, which_properties))


def GetStyleName(master, object, style_names):
    dlg = CreateStyleDlg(master, object, style_names)
    return dlg.RunDialog()






class SetDefaultPropertiesDlg(SKModal):

    title = _("Set Default Properties")

    def __init__(self, master, category):
	self.category = category
	SKModal.__init__(self, master, name = 'setdefaults')

    def build_dlg(self):
	top = self.top

        label = Label(top, name = 'label',
                      text = _("Please select the object categories whose "
                               "default properties you want to change"))
        label.pack(side = TOP, anchor = W)
        frame = Frame(top)
        frame.pack(side = TOP)
        self.var_graphics = IntVar(top)
        if self.category != 'font':
            self.var_graphics.set(1)
        button = Checkbutton(frame, text = _("Graphics Objects"),
                             state = (self.category == 'font'
                                      and DISABLED or NORMAL),
                             variable = self.var_graphics)
        button.pack(side = TOP, anchor = W)
        self.var_text = IntVar(top)
        if self.category == 'font':
            self.var_text.set(1)
        button = Checkbutton(frame, text = _("Text Objects"),
                             state = (self.category == 'line'
                                      and DISABLED or NORMAL),
                             variable = self.var_text)
        button.pack(side = TOP, anchor = W)

	but_frame = Frame(top)
	but_frame.pack(side = TOP, fill = BOTH, expand = 1)

	button = Button(but_frame, text = _("OK"), command = self.ok)
	button.pack(side = LEFT, expand = 1)
	button = Button(but_frame, text = _("Cancel"), command = self.cancel)
	button.pack(side = RIGHT, expand = 1)

    def ok(self, *args):
	which_properties = (self.var_graphics.get(),
                            self.var_text.get())
	self.close_dlg(which_properties)


def WhichDefaultStyles(master, category = 0):
    dlg = SetDefaultPropertiesDlg(master, category)
    return dlg.RunDialog()


def set_properties(master, document, title, category, kw):
    if document.HasSelection():
        document.BeginTransaction(title)
        try:
            apply(document.SetProperties, (), kw)
        finally:
            document.EndTransaction()
    else:
        if config.preferences.set_default_properties:
            # remove the if_type_present argument if present. The font
            # dialog uses it in a kludgy way to avoid setting the font
            # on a non-text object.
            if kw.has_key("if_type_present"):
                del kw["if_type_present"]
            which = WhichDefaultStyles(master, category = category)
            if which:
                if which[0]:
                    Sketch.Graphics.properties.set_graphics_defaults(kw)
                if which[1]:
                    Sketch.Graphics.properties.set_text_defaults(kw)
