from PSPApp import *
import PSPUtils

def ScriptProperties():
    return {
        'Author': u'Corel Corporation',
        'Copyright': u'Copyright (c) 2002-2006 Corel Corporation. All rights reserved.',
        'Description': "Place a caption on an image by expanding the canvas and placing the caption below the image.",
        'Host': u'Paint Shop Pro 9',
        'Host Version': u'9.00'
        }

FontName = PSPUtils.CaptionFontName2		# font name that will be used by the text
ExpandEdges = 0.1				# expand top, left and right by 10%
ExpandBottom = 0.15				# expand bottom by 15%

def Do(Environment):
    ''' Add a caption by doing the following steps:
        (Thanks to Angela Cable for advice on artistic aspect of this)
         1. Prompt the user for the caption.  If they press cancel abort
         2. Select the bottommost layer
         3. If we are starting on a background layer, promote it to a full layer. To keep
            things straight,rename the layer to 'Image'
         4. Add a new empty layer.  Call it Page Surface.
         5. Arrange the Page Surface to the bottom
         6. Increase the canvas size by 10% on the left, right and top,
            and by 15% on the bottom.
         7. Move the Page Surface layer into a layer group.  Call the group Album Page
         8. Select the Page Surface layer
         9. Flood fill it with white.
        10. Using the backdrop texture and a 192 grey, flood fill it again.
        11. Select the image layer again.
        12. Add drop shadow on a new layer.
        13. Arrange the layer into the Album page group
        14. Create a vector layer
        15. Place the caption text the user entered at the beginning on the image.
            Font used is set in the FontName variable
        16. Select the image layer again

       When done, the original layer is unchanged, and all of the new layers are placed
       inside of a layer group.  The canvas size is changed however.
    '''

    if PSPUtils.RequireADoc( Environment ) == App.Constants.Boolean.false:
        return
    
    # save off the target doc before we do anything
    Target = App.TargetDocument
    
    # we work with percentages for a number of things, and the expectation is that the
    # text should be visible - lets not support any image with a dimension less than 200
    if Target.Height < 200 or Target.Width < 200:
        App.Do( Environment, 'MsgBox', {
                'Buttons': App.Constants.MsgButtons.OK, 
                'Icon': App.Constants.MsgIcons.Stop, 
                'Text': PSPUtils.ImageTooSmallMsg,
                })
        return

    # if we are running on something that is not a flat image, suggest
    # that they flatten before continuing
    if PSPUtils.GetLayerCount( Environment, Target ) != 1:
        result = App.Do( Environment, 'MsgBox', {
                'Buttons': App.Constants.MsgButtons.YesNo, 
                'Icon': App.Constants.MsgIcons.Question, 
                'Text': PSPUtils.MultipleLayersMsg 
                })
        if result == 1: # yes
            App.Do( Environment, 'LayerMergeAll' )
    
            
    DefaultCaption = Target.Title
    ExtensionPos = DefaultCaption.rfind( '.' )
    if ExtensionPos != -1:
        DefaultCaption = DefaultCaption[ : ExtensionPos ]
    
    # prompt for the caption at the very beginning - if they press cancel in the dialog we
    # can return before any changes are made to the image
    # now prompt the user for the caption to user
    Result = App.Do( Environment, 'GetString', {
            'DefaultText': DefaultCaption,
            'DialogTitle': PSPUtils.CaptionTitle,
            'Prompt': PSPUtils.CaptionPrompt,
            'MaxLength': 40,
            'GeneralSettings': {
                'ExecutionMode': App.Constants.ExecutionMode.Interactive, 
                'AutoActionMode': App.Constants.AutoActionMode.Default
                }
        })
    if Result[ 'OKButton' ] == App.Constants.Boolean.false:
        return
    
    CaptionText = Result[ 'EnteredText' ]   # save this for later
  
    # go to the bottommost layer - this could throw an exception if we are already on the bottommost layer
    App.Do( Environment, 'SelectLayer', {
            'Path': ( 9999, -9999, [], App.Constants.Boolean.false),
            'GeneralSettings': {
                'ExecutionMode': App.Constants.ExecutionMode.Silent, 
                'AutoActionMode': App.Constants.AutoActionMode.Default
                }
            })
    
    # promote a background layer so that we can put a drop shadow on it
    if PSPUtils.LayerIsBackground( Environment, Target ):
        App.Do( Environment, 'LayerPromoteBackground', {
                'GeneralSettings': {
                    'ExecutionMode': App.Constants.ExecutionMode.Default, 
                    'AutoActionMode': App.Constants.AutoActionMode.Match
                    }
                })

        # promoting the background will give it a default name - give it a
        # modestly more descriptive name so that we can tell what is what
        App.Do( Environment, 'LayerProperties', {
                'General': {
                    'Name': PSPUtils.PromotedLayerName, 
                    }, 
                'GeneralSettings': {
                    'ExecutionMode': App.Constants.ExecutionMode.Silent, 
                    'AutoActionMode': App.Constants.AutoActionMode.Default
                    }
                })

    # now add a new layer
    App.Do( Environment, 'NewRasterLayer', {
            'General': {
                'Opacity': 100, 
                'Name': PSPUtils.PageSurfaceLayerName, 
                'IsVisible': App.Constants.Boolean.true, 
                }, 
            'GeneralSettings': {
                'ExecutionMode': App.Constants.ExecutionMode.Silent, 
                'AutoActionMode': App.Constants.AutoActionMode.Match
                }
            })

    # arrange the new layer to the bottom
    App.Do( Environment, 'LayerArrange', {
            'Path': (0,-1,[],App.Constants.Boolean.false), 
            'MoveAboveSibling': App.Constants.Boolean.false, 
            'GeneralSettings': {
                'ExecutionMode': App.Constants.ExecutionMode.Silent, 
                'AutoActionMode': App.Constants.AutoActionMode.Default
                }
            })

    # by the time we are done we are going to have added 3 layers - backdrop, text, and shadow.
    # to be tidy, lets wrap all of it in a layer group
    # create a layer group.  This will place the 'page surface' layer in the group
    App.Do( Environment, 'NewLayerGroup', {
            'General': {
                'Name': PSPUtils.AlbumPageLayerGroup, 
                }, 
            'GeneralSettings': {
                'ExecutionMode': App.Constants.ExecutionMode.Silent, 
                }
            })
    
    # select the 'page surface' layer so that the vector layer gets created above it
    App.Do( Environment, 'SelectLayer', {
            'Path': (0,0,[1],App.Constants.Boolean.false), 
            })

    # now increase the canvas size, based on the original size
    XAmount = int(Target.Width * ExpandEdges)
    YAmountTop = int(Target.Height * ExpandEdges)
    YAmountBottom = int(Target.Height * ExpandBottom)
    
    NewWidth = Target.Width + 2 * XAmount
    NewHeight = Target.Height + YAmountTop + YAmountBottom

    App.Do( Environment, 'ResizeCanvas', {
            'HoriPlace': App.Constants.HorizontalType.Custom, 
            'MaintainAspect': App.Constants.Boolean.false, 
            'NewDimUnits': App.Constants.UnitsOfMeasure.Pixels, 
            'NewHeight': NewHeight, 
            'NewWidth': NewWidth, 
            'OrigDimUnits': App.Constants.UnitsOfMeasure.Pixels, 
            'PlaceBottom': YAmountBottom, 
            'PlaceLeft': XAmount, 
            'PlaceRight': XAmount, 
            'PlaceTop': YAmountTop, 
            'VertPlace': App.Constants.VerticalType.Center, 
            'GeneralSettings': {
                'ExecutionMode': App.Constants.ExecutionMode.Silent, 
                'AutoActionMode': App.Constants.AutoActionMode.Match
                }
            })
    # we are still on the Backdrop layer - fill it with white
    App.Do( Environment, 'Fill', {
            'BlendMode': 0, 
            'MatchMode': 1, 
            'Material': {
                'Color': (255,255,255), 
                'Pattern': None, 
                'Gradient': None, 
                'Texture': None
                }, 
            'UseForground': App.Constants.Boolean.true, 
            'Opacity': 100, 
            'Point': (1, 1), 
            'SampleMerged': 0, 
            'Tolerance': 20, 
            'GeneralSettings': {
                'ExecutionMode': App.Constants.ExecutionMode.Default, 
                'AutoActionMode': App.Constants.AutoActionMode.Match
                }
            })
    
    # now fill it again with a light grey texture
    App.Do( Environment, 'Fill', {
            'BlendMode': 0, 
            'MatchMode': 1, 
            'Material': {
                'Color': (160,160,160), 
                'Pattern': None, 
                'Gradient': None, 
                'Texture': {
                    'Name': 'Corel_15_021', 
                    'Image': None, 
                    'Angle': 0.000, 
                    'Scale': 100.000
                    }
                }, 
            'UseForground': App.Constants.Boolean.true, 
            'Opacity': 100, 
            'Point': (1, 1), 
            'SampleMerged': 0, 
            'Tolerance': 20, 
            'GeneralSettings': {
                'ExecutionMode': App.Constants.ExecutionMode.Default, 
                'AutoActionMode': App.Constants.AutoActionMode.Match
                }
            })

    # now select the image layer
    App.Do( Environment, 'SelectLayer', {
            'Path': (1,1,[],App.Constants.Boolean.false), 
            'GeneralSettings': {
                'ExecutionMode': App.Constants.ExecutionMode.Silent, 
                'AutoActionMode': App.Constants.AutoActionMode.Default
                }
            })

    # place a drop shadow.  Make it a little bit more on the bottom than on the right
    # we put the drop shadow on a new layer so that the image layer remains untouched
    # drop shadow amount is 10 on the right and 12 on the bottom
    App.Do( Environment, 'DropShadow', {
            'Blur': 5.000, 
            'Color': (0,0,0), 
            'Horizontal': 10, 
            'Vertical': 12, 
            'NewLayer': App.Constants.Boolean.true, 
            'Opacity': 60, 
            'GeneralSettings': {
                'ExecutionMode': App.Constants.ExecutionMode.Silent, 
                'AutoActionMode': App.Constants.AutoActionMode.Match
                }
            })

    # The default name for a drop shadow is kind of lame.  Lets rename it
    App.Do( Environment, 'LayerProperties', {
            'General': {
                'Name': PSPUtils.DropShadowLayerName,
                'Opacity': 75,
                }, 
            'GeneralSettings': {
                'ExecutionMode': App.Constants.ExecutionMode.Silent, 
                'AutoActionMode': App.Constants.AutoActionMode.Default
                }
            })


    # placing the drop shadow added a new layer, and made it active.
    # let's arrange it into the group
    App.Do( Environment, 'LayerArrangeMoveIn' )
    
    # select one layer down to get back to the backdrop
    App.Do( Environment, 'SelectLayer', { 'Path': ( 0, -1, [], App.Constants.Boolean.false ) } )

    # now create a vector layer to put text on - creating the layer will make it active
    # we could let the text tool create the layer for us, but this way we get to name it
    App.Do( Environment, 'NewVectorLayer', {
            'General': {
                'Opacity': 100, 
                'Name': PSPUtils.CaptionTextLayerName, 
                }, 
            'GeneralSettings': {
                'ExecutionMode': App.Constants.ExecutionMode.Silent, 
                }
            })

    # finally place the text.  Make it centered in the X axis, and centered in the bottom
    # margin.  We make the text height 1/4 the margin amount, but never less than 12 pixels
    TextSize = max( 12, int(YAmountBottom / 4))
    
    TextBaseLine = Target.Height - (YAmountBottom / 4)
    App.Do( Environment, 'TextEx', {
            'Visibility': True, 
            'CreateAs': App.Constants.CreateAs.Vector, 
            'Fill': {
                'Color': (0,0,0), 
                'Pattern': None, 
                'Gradient': None, 
                'Texture': None
                }, 
            'Font': FontName, 
            'Italic': App.Constants.Boolean.true, 
            'Stroke': None,
            'PointSize': TextSize, 
            'Start': (Target.Width / 2, TextBaseLine), 
            'LineStyle': None,
            'LineWidth':0,
            'SetText': App.Constants.Justify.Center,
            'TextFlow': App.Constants.TextFlow.HorizontalDown, 
            'TextType': App.Constants.TextType.TextBase, 
            'AntialiasStyle': App.Constants.AntialiasEx.Smooth, 
            'Characters': unicode(CaptionText),
            'GeneralSettings': {
                'ExecutionMode': App.Constants.ExecutionMode.Default, 
                'AutoActionMode': App.Constants.AutoActionMode.Match,
                'Version': ((9,0,0),1)
                }
            })

    # finish with the image layer selected
    App.Do( Environment, 'SelectLayer', {
            'Path': (1,1,[],App.Constants.Boolean.false), 
            'GeneralSettings': {
                'ExecutionMode': App.Constants.ExecutionMode.Silent, 
                'AutoActionMode': App.Constants.AutoActionMode.Default
                }
            })

