from PSPApp import *
import PSPUtils
import os.path

def ScriptProperties():
    return {
        'Author': u'Corel Corporation',
        'Copyright': u'Copyright (c) 2002-2006 Corel Corporation. All rights reserved.',
        'Description': "Make a pseudo-palette - a series of squares filled with solid colors",
        'Host': u'Paint Shop Pro 9',
        'Host Version': u'9.00',
        }


def Do(Environment):
    if PSPUtils.RequireADoc( Environment ) == App.Constants.Boolean.false:
        return
    
    # all of these formats have palettes, and we need a paletted image.
    PalettedFormats = [ App.Constants.PixelFormat.Index1, App.Constants.PixelFormat.Index4,
                        App.Constants.PixelFormat.Index8, App.Constants.PixelFormat.Grey,
                        App.Constants.PixelFormat.GreyA ]
    
    # is the current image paletted?  If not, give them the option to reduce color depth
    Info = App.Do( Environment, 'ReturnImageInfo', {'GeneralSettings': {'Version': ((9,0,0),1) }} )

    if not Info['PixelFormat'] in PalettedFormats:
        result = App.Do(Environment,  'MsgBox', {
                'Buttons': App.Constants.MsgButtons.YesNo, 
                'Icon': App.Constants.MsgIcons.Question, 
                'Text': PSPUtils.RequiresPaletted,
                'GeneralSettings': {'Version': ((9,0,0),1) }
                })
        if result == 0:
            return
        else:
            # always do this interactively, even if the script as a whole is silent
            App.Do( Environment, 'DecreaseColorsToX', {
                        'GeneralSettings': {
                            'ExecutionMode': App.Constants.ExecutionMode.Interactive, 
                            'AutoActionMode': App.Constants.AutoActionMode.Match,
                            'Version': ((9,0,0),1)
                            }
                        })

            # get a new copy of the image info since it just changed
            Info = App.Do( Environment, 'ReturnImageInfo', {'GeneralSettings': {'Version': ((9,0,0),1) }} )

    # Save the palette we just generated
    PalName, Ext = os.path.splitext(App.TargetDocument.Title)
    App.Do( Environment, 'SavePalette', {
            'Filename': PalName, 
            'Format': App.Constants.PaletteFormat.PSPPaletteFormat, 
            'Overwrite': App.Constants.Boolean.true, 
            'GeneralSettings': {
                'ExecutionMode': App.Constants.ExecutionMode.Interactive,
                'AutoActionMode': App.Constants.AutoActionMode.Match,
                'Version': ((9,0,0),1)
                }
            })
            
    ColorList = Info[ 'PaletteColorList' ]
    if not ColorList:
        print PSPUtils.NoPaletteFound
        return

    # now make a pseudo-palette - an image with little swatches of color against a solid
    # background.  Make the background a medium grey, and separate each swatch by 2 pixels
    # of grout.  Each color square is 10x10
    # *** Change these parameters for a different output image
    MakePseudoPalette( Environment, ColorList, GroutColor=(128,128,128), GroutWidth=2,
                       ColorsPerRow=16, TileSize=(10,10), ButtonMargin=0 )

    # we just created a new image - just leave it open for the user to decide what to do



# Create a new image that appears somewhat like a palette - a series of color swatches 
# organized into rows and columns. The resulting image can be customized by setting the
# parameters appropriately.
# ColorList - list of (r,g,b) tuples with the colors to use.  Must be between 2 and 1024
# GroutColor - underlying color of the image, seen between the color tiles.  Defaults to
#              medium grey
# GroutWidth - how much grout is seen between color tiles.  Defaults to 2 pixels.
# ColorsPerRow - number of tiles on each row.  Along with TileSize[0], determines
#                the width of the image. Defaults to 16
# TileSize - (x,y) size tuple.  A rectangle of that size will be filled with each color.
#            along with length of the colorlist and ColorsPerRow, determines the resulting
#            size of the image.  Defaults to (10,10)
# ButtonMargin - how much of a buttonize effect to apply to each color tile.  Default of 0
#                means no buttonize is done.  A buttonize of 2 yields a slight 3D effect.
def MakePseudoPalette( Environment, ColorList, GroutColor=(0,0,0),
                       GroutWidth=2, ColorsPerRow=16, TileSize=(10,10), ButtonMargin=0):
    # lets put some sanity checks on our arguments - these values are arbitrary for the
    # most part, so if you don't like them, change them.
    if not GroutWidth in range(0,20):
        print PSPUtils.GroutWidthMsg
        return 0
    if not ColorsPerRow in range(1,100):
        print PSPUtils.ColorsPerRowMsg
        return 0
    if not TileSize[0] in range(2, 50):
        print PSPUtils.TileSizeMsg
        return 0
    if not TileSize[1] in range(2, 50):
        print PSPUtils.TileSizeMsg
        return 0
    if not len(ColorList) in range( 2, 1024 ):
        print PSPUtils.NumColorsMsg
        return 0
    if not ButtonMargin in range( 0, min(TileSize)/2 ):
        print PSPUtils.ButtonMarginMsg
        return 0
    
    # run through the list of colors we were given and remove consecutive duplicates
    # this will address the issue of reducing to an odd number of colors, but permit
    # duplicates to occur in the middle of the color list
    OldColor = ( 1000, 0, 0 )   # not a legal color value, so should never occur in nature
    iStartDup = 0
    iCurrentIndex = 0
    
    for Color in ColorList:
        if Color != OldColor:
            iStartDup = iCurrentIndex
            OldColor = Color
            
        iCurrentIndex += 1

    if iStartDup + 1 < len(ColorList):
        ColorList = ColorList[ 0 : iStartDup+1 ]

    # start by determining how big a document we want to create
    NumRows = (len(ColorList) + ColorsPerRow - 1) / ColorsPerRow
    Height = (NumRows * TileSize[1]) + ((NumRows + 1) * GroutWidth)
    Width = (ColorsPerRow * TileSize[0]) + ((ColorsPerRow + 1) * GroutWidth)

    # make an image of the proper size using a background of the grout color
    App.Do( Environment, 'NewFile', {
            'Width': Width,
            'Height': Height, 
            'ColorDepth': App.Constants.Colordepth.SixteenMillionColor, 
            'DimensionUnits': App.Constants.DimensionType.Pixels, 
            'FillMaterial': {
                'Color': GroutColor, 
                'Pattern': None, 
                'Gradient': None, 
                'Texture': None
                }, 
            'Transparent': App.Constants.Boolean.false, 
            'VectorBackground': App.Constants.Boolean.false,
            'LayerType': 1,
            'GeneralSettings': {
                'ExecutionMode': App.Constants.ExecutionMode.Silent, 
                'AutoActionMode': App.Constants.AutoActionMode.Match,
                'Version': ((9,0,0),1)
                }
            })

    TargetDoc = App.ActiveDocument
    
    # now iterate across the list of colors
    RowNumber = 0
    ColNumber = 0
    RowStart = GroutWidth
    ColStart = GroutWidth
    Index = 0 
    for Color in ColorList:
        # just send data to the output so they know something is happening.
        print PSPUtils.ColorIs % (Index, Color[0], Color[1], Color[2])
        Index += 1
        
        # when we reach the end of a row reset our column and advance row
        if ColNumber >= ColorsPerRow:
            ColNumber = 0
            RowNumber += 1
            RowStart += TileSize[1] + GroutWidth
            ColStart = GroutWidth

        # make a selection of the rectangle this color should cover
        App.Do( Environment, 'Selection', {
                'General': {
                    'Mode': App.Constants.SelectionOperation.Replace, 
                    'Antialias': App.Constants.Boolean.false, 
                    'Feather': 0
                    }, 
                'SelectionShape': App.Constants.SelectionShape.Rectangle, 
                'Start': (ColStart, RowStart), 
                'End': (ColStart + TileSize[0], RowStart + TileSize[1]), 
                'GeneralSettings': {
                    'ExecutionMode': App.Constants.ExecutionMode.Silent, 
                    'AutoActionMode': App.Constants.AutoActionMode.Match,
                    'Version': ((9,0,0),1)
                    }
                }, TargetDoc )

        # fill it with the color
        App.Do( Environment, 'Fill', {
                'BlendMode': 0, 
                'MatchMode': 1, 
                'Material': {
                    'Color': Color, 
                    'Pattern': None, 
                    'Gradient': None, 
                    'Texture': None
                    }, 
                'UseForground': App.Constants.Boolean.true, 
                'Opacity': 100, 
                'Point': (ColStart+1, RowStart+1), 
                'SampleMerged': 0, 
                'Tolerance': 20, 
                'GeneralSettings': {
                    'ExecutionMode': App.Constants.ExecutionMode.Silent, 
                    'AutoActionMode': App.Constants.AutoActionMode.Match,
                    'Version': ((9,0,0),1)
                    }
                }, TargetDoc )

        # buttonize the color if requested
        if ButtonMargin != 0:
            App.Do( Environment, 'Buttonize', {
                'Width': ButtonMargin, 
                'Height': ButtonMargin, 
                'Transparent': App.Constants.Boolean.false, 
                'Color': (255,255,255), 
                'Opacity': 75, 
                'GeneralSettings': {
                    'ExecutionMode': App.Constants.ExecutionMode.Silent, 
                    'AutoActionMode': App.Constants.AutoActionMode.Match,
                    'Version': ((9,0,0),1)
                    }
                }, TargetDoc)

        # go on to the next column        
        ColNumber += 1
        ColStart += TileSize[0] + GroutWidth
        
    # select none to get rid of the selection on the last color square.
    App.Do( Environment, 'SelectNone', { 'GeneralSettings': {'Version': ((9,0,0),1) } }, TargetDoc )
    
    return 1 # success
