/*
Copyright 2008 Stefano Chizzolini. http://clown.stefanochizzolini.it
Contributors:
* Stefano Chizzolini (original code developer, http://www.stefanochizzolini.it)
This file should be part of the source code distribution of "PDF Clown library"
(the Program): see the accompanying README files for more info.
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, either expressed or implied; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the License for more details.
You should have received a copy of the GNU General Public License along with this
Program (see README files); if not, go to the GNU website (http://www.gnu.org/).
Redistribution and use, with or without modification, are permitted provided that such
redistributions retain the above copyright notice, license and disclaimer, along with
this list of conditions.
*/
using it.stefanochizzolini.clown.bytes;
using it.stefanochizzolini.clown.documents;
using it.stefanochizzolini.clown.documents.fileSpecs;
using it.stefanochizzolini.clown.documents.interaction.navigation.document;
using it.stefanochizzolini.clown.objects;
using System;
using System.Collections.Generic;
namespace it.stefanochizzolini.clown.documents.interaction.actions{
/**
<summary>'Change the view to a specified destination in a PDF file
embedded in another PDF file' action [PDF:1.6:8.5.3].</summary>
*/
public class GoToEmbedded
: Action
{
#region types
/**
<summary>Path information to the target document [PDF:1.6:8.5.3].</summary>
*/
public class TargetObject
: PdfObjectWrapper<PdfDictionary>
{
#region types
/**
<summary>Relationship between the target and the current document [PDF:1.6:8.5.3].</summary>
*/
public enum RelationEnum
{
/**
<summary>Parent.</summary>
*/
Parent,
/**
<summary>Child.</summary>
*/
Child
};
#endregion
#region static
#region fields
private static readonly Dictionary<RelationEnum,PdfName> RelationEnumCodes;
#endregion
#region constructors
static TargetObject()
{
RelationEnumCodes = new Dictionary<RelationEnum,PdfName>();
RelationEnumCodes[RelationEnum.Parent] = PdfName.P;
RelationEnumCodes[RelationEnum.Child] = PdfName.C;
}
#endregion
#region interface
#region private
/**
<summary>Gets the code corresponding to the given value.</summary>
*/
private static PdfName ToCode(
RelationEnum value
)
{return RelationEnumCodes[value];}
/**
<summary>Gets the relation corresponding to the given value.</summary>
*/
private static RelationEnum ToRelationEnum(
PdfName value
)
{
foreach(KeyValuePair<RelationEnum,PdfName> relation in RelationEnumCodes)
{
if(relation.Value.Equals(value))
return relation.Key;
}
throw new Exception("'" + value.Value + "' doesn't represent a valid relation.");
}
#endregion
#endregion
#endregion
#region dynamic
#region constructors
/**
<summary>Creates a new target representing the parent of the document.</summary>
*/
public TargetObject(
Document context,
TargetObject target
) : this(
context,
RelationEnum.Parent,
null,
null,
null,
target
)
{}
/**
<summary>Creates a new target located in the embedded files collection of the document.</summary>
*/
public TargetObject(
Document context,
string embeddedFileName,
TargetObject target
) : this(
context,
RelationEnum.Child,
embeddedFileName,
null,
null,
target
)
{}
/**
<summary>Creates a new target associated with a file attachment annotation.</summary>
*/
public TargetObject(
Document context,
object annotationPageRef,
object annotationRef,
TargetObject target
) : this(
context,
RelationEnum.Child,
null,
annotationPageRef,
annotationRef,
target
)
{}
/**
<summary>Creates a new target.</summary>
*/
private TargetObject(
Document context,
RelationEnum relation,
string embeddedFileName,
object annotationPageRef,
object annotationRef,
TargetObject target
) : base(
context.File,
new PdfDictionary()
)
{
Relation = relation;
EmbeddedFileName = embeddedFileName;
AnnotationPageRef = annotationPageRef;
AnnotationRef = annotationRef;
Target = target;
}
internal TargetObject(
PdfDirectObject baseObject,
PdfIndirectObject container
) : base(baseObject,container)
{}
#endregion
#region interface
#region public
public override object Clone(
Document context
)
{throw new NotImplementedException();}
/**
<summary>Gets/Sets the page reference to the file attachment annotation.</summary>
<returns>Either the (zero-based) number of the page in the current document containing the file attachment annotation,
or the name of a destination in the current document that provides the page number of the file attachment annotation.</returns>
*/
public object AnnotationPageRef
{
get
{
/*
NOTE: 'P' entry may be undefined.
*/
PdfDirectObject pageRefObject = BaseDataObject[PdfName.P];
if(pageRefObject == null)
return null;
if(pageRefObject is PdfInteger)
return ((PdfInteger)pageRefObject).Value;
return ((PdfString)pageRefObject).Value;
}
set
{
if(value == null)
{BaseDataObject.Remove(PdfName.P);}
else
{
PdfDirectObject pageRefObject;
if(value is int)
{pageRefObject = new PdfInteger((int)value);}
else if(value is string)
{pageRefObject = new PdfString((string)value);}
else
throw new ArgumentException("Wrong argument type: it MUST be either a page number Integer or a named destination String.");
BaseDataObject[PdfName.P] = pageRefObject;
}
}
}
/**
<summary>Gets/Sets the reference to the file attachment annotation.</summary>
<returns>Either the (zero-based) index of the annotation in the list of annotations
associated to the page specified by the annotationPageRef property, or the name of the annotation.</returns>
*/
public object AnnotationRef
{
get
{
/*
NOTE: 'A' entry may be undefined.
*/
PdfDirectObject annotationRefObject = BaseDataObject[PdfName.A];
if(annotationRefObject == null)
return null;
if(annotationRefObject is PdfInteger)
return ((PdfInteger)annotationRefObject).Value;
return ((PdfTextString)annotationRefObject).Value;
}
set
{
if(value == null)
{BaseDataObject.Remove(PdfName.A);}
else
{
PdfDirectObject annotationRefObject;
if(value is int)
{annotationRefObject = new PdfInteger((int)value);}
else if(value is string)
{annotationRefObject = new PdfTextString((string)value);}
else
throw new ArgumentException("Wrong argument type: it MUST be either an annotation index Integer or an annotation name String.");
BaseDataObject[PdfName.A] = annotationRefObject;
}
}
}
/**
<summary>Gets/Sets the embedded file name.</summary>
*/
public string EmbeddedFileName
{
get
{
/*
NOTE: 'N' entry may be undefined.
*/
PdfString fileNameObject = (PdfString)BaseDataObject[PdfName.N];
if(fileNameObject == null)
return null;
return (string)fileNameObject.Value;
}
set
{
if(value == null)
{BaseDataObject.Remove(PdfName.N);}
else
{BaseDataObject[PdfName.N] = new PdfString(value);}
}
}
/**
<summary>Gets/Sets the relationship between the target and the current document.</summary>
*/
public RelationEnum Relation
{
get
{
/*
NOTE: 'R' entry MUST exist.
*/
return ToRelationEnum((PdfName)BaseDataObject[PdfName.R]);
}
set
{BaseDataObject[PdfName.R] = ToCode(value);}
}
/**
<summary>Gets/Sets a further path information to the target document.</summary>
*/
public TargetObject Target
{
get
{
/*
NOTE: 'T' entry may be undefined.
*/
PdfDirectObject targetObject = BaseDataObject[PdfName.T];
if(targetObject == null)
return null;
return new TargetObject(targetObject,Container);
}
set
{
if(value == null)
{BaseDataObject.Remove(PdfName.T);}
else
{BaseDataObject[PdfName.T] = value.BaseObject;}
}
}
#endregion
#endregion
#endregion
}
#endregion
#region dynamic
#region constructors
/**
<summary>Creates a new embedded-goto action within the given document context,
pointing to a destination within a target document embedded within the same document.</summary>
*/
public GoToEmbedded(
Document context,
TargetObject target,
Destination destination
) : this(
context,
null,
target,
destination
)
{}
/**
<summary>Creates a new embedded-goto action within the given document context,
pointing to a destination within another document.</summary>
*/
public GoToEmbedded(
Document context,
FileSpec fileSpec,
Destination destination
) : this(
context,
fileSpec,
null,
destination
)
{}
/**
<summary>Creates a new embedded-goto action within the given document context.</summary>
*/
public GoToEmbedded(
Document context,
FileSpec fileSpec,
TargetObject target,
Destination destination
) : base(
context,
PdfName.GoToE
)
{
FileSpec = fileSpec;
Target = target;
Destination = destination;
}
internal GoToEmbedded(
PdfDirectObject baseObject,
PdfIndirectObject container
) : base(baseObject,container)
{}
#endregion
#region interface
#region public
public override object Clone(
Document context
)
{throw new NotImplementedException();}
/**
<summary>Gets/Sets the destination to jump to.</summary>
*/
public Destination Destination
{
get
{
/*
NOTE: 'D' entry MUST exist.
*/
PdfDirectObject destinationObject = BaseDataObject[PdfName.D];
if(destinationObject is PdfName) // Named destination.
return Document.Names.Destinations[
(string)((PdfName)destinationObject).Value
];
if(destinationObject is PdfString) // Named destination.
return Document.Names.Destinations[
(string)((PdfString)destinationObject).Value
];
return Destination.Wrap(
destinationObject,
Container
); // Explicit destination.
}
set
{
if(value == null)
throw new ArgumentException("Destination MUST be defined.");
BaseDataObject[PdfName.D] = value.BaseObject;
}
}
/**
<summary>Gets/Sets the file in which the destination is located, if different from the current one.</summary>
*/
public FileSpec FileSpec
{
get
{
/*
NOTE: 'F' entry may be undefined.
*/
PdfDirectObject fileSpecObject = BaseDataObject[PdfName.F];
if(fileSpecObject == null)
return null;
return new FileSpec(fileSpecObject,Container);
}
set
{
if(value == null)
{BaseDataObject.Remove(PdfName.F);}
else
{BaseDataObject[PdfName.F] = value.BaseObject;}
}
}
/**
<summary>Gets/Sets the action options.</summary>
*/
public OptionsEnum Options
{
get
{
OptionsEnum options = 0;
PdfDirectObject optionsObject = BaseDataObject[PdfName.NewWindow];
if(optionsObject != null
&& (bool)((PdfBoolean)optionsObject).Value)
{options |= OptionsEnum.NewWindow;}
return options;
}
set
{
if((value & OptionsEnum.NewWindow) == OptionsEnum.NewWindow)
{BaseDataObject[PdfName.NewWindow] = PdfBoolean.True;}
else if((value & OptionsEnum.SameWindow) == OptionsEnum.SameWindow)
{BaseDataObject[PdfName.NewWindow] = PdfBoolean.False;}
else
{BaseDataObject.Remove(PdfName.NewWindow);} // NOTE: Forcing the absence of this entry ensures that the viewer application should behave in accordance with the current user preference.
}
}
/**
<summary>Gets/Sets the path information to the target document.</summary>
*/
public TargetObject Target
{
get
{
/*
NOTE: 'T' entry may be undefined.
*/
PdfDirectObject targetObject = BaseDataObject[PdfName.T];
if(targetObject == null)
return null;
return new TargetObject(targetObject,Container);
}
set
{
if(value == null)
{BaseDataObject.Remove(PdfName.T);}
else
{BaseDataObject[PdfName.T] = value.BaseObject;}
}
}
#endregion
#endregion
#endregion
}
}
|