diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 2c073bc..52e5f13 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -1,5 +1,12 @@ PDFBinder changelog =================== +Version 1.3 +----------- + * Ability to accept password to open PDF. (Requires owner password) + * Select which pages of each file should appear in the output + * Files can be added by adding a txt file manifest. + - password and page number selections can be added to each line with the filename delimited by a "|" + - eg. "D:\work\project1\file1.pdf|Passw0rd|2-8,13,1,1,25-" Version 1.2 ----------- diff --git a/PDF Binder file collation format sample.txt b/PDF Binder file collation format sample.txt new file mode 100644 index 0000000..c0ab145 --- /dev/null +++ b/PDF Binder file collation format sample.txt @@ -0,0 +1,3 @@ +C:\guide_driving_test.pdf||38,24-40,70 +C:\gum stablisers in icecream_usage.pdf||2- +C:/rebate sheet template 2014.pdf \ No newline at end of file diff --git a/src/PDFBInderSetup/PDFBinderSetup.vdproj b/src/PDFBInderSetup/PDFBinderSetup.vdproj index d24da57..4db15f6 100644 --- a/src/PDFBInderSetup/PDFBinderSetup.vdproj +++ b/src/PDFBInderSetup/PDFBinderSetup.vdproj @@ -21,14 +21,14 @@ } "Entry" { - "MsmKey" = "8:_334B958DF4E2498E9F250950853E2FBC" - "OwnerKey" = "8:_UNDEFINED" + "MsmKey" = "8:_2DE6EF1ABB79F2AA4737A51FF7D76E09" + "OwnerKey" = "8:_25297E5AFFCA4729843496065CE8331B" "MsmSig" = "8:_UNDEFINED" } "Entry" { - "MsmKey" = "8:_7A7D4121338B9A976525C35D744FC34C" - "OwnerKey" = "8:_25297E5AFFCA4729843496065CE8331B" + "MsmKey" = "8:_334B958DF4E2498E9F250950853E2FBC" + "OwnerKey" = "8:_UNDEFINED" "MsmSig" = "8:_UNDEFINED" } "Entry" @@ -58,7 +58,7 @@ "Entry" { "MsmKey" = "8:_UNDEFINED" - "OwnerKey" = "8:_7A7D4121338B9A976525C35D744FC34C" + "OwnerKey" = "8:_2DE6EF1ABB79F2AA4737A51FF7D76E09" "MsmSig" = "8:_UNDEFINED" } } @@ -125,16 +125,6 @@ "ComponentsUrl" = "8:" "Items" { - "{EDC2488A-8267-493A-A98E-7D9C3B36CDF3}:Microsoft.Net.Framework.3.5.SP1" - { - "Name" = "8:.NET Framework 3.5 SP1" - "ProductCode" = "8:Microsoft.Net.Framework.3.5.SP1" - } - "{EDC2488A-8267-493A-A98E-7D9C3B36CDF3}:Microsoft.Windows.Installer.3.1" - { - "Name" = "8:Windows Installer 3.1" - "ProductCode" = "8:Microsoft.Windows.Installer.3.1" - } } } } @@ -200,7 +190,7 @@ { "Name" = "8:.NET Framework" "Message" = "8:[VSDNETMSG]" - "FrameworkVersion" = "8:2.0.50727" + "FrameworkVersion" = "8:ANY" "AllowLaterVersions" = "11:FALSE" "InstallUrl" = "8:http://go.microsoft.com/fwlink/?LinkId=76617" } @@ -208,10 +198,21 @@ } "File" { - "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_334B958DF4E2498E9F250950853E2FBC" + "{9F6F8455-1EF1-4B85-886A-4223BCC8E7F7}:_2DE6EF1ABB79F2AA4737A51FF7D76E09" { - "SourcePath" = "8:setup-banner.jpg" - "TargetName" = "8:setup-banner.jpg" + "AssemblyRegister" = "3:1" + "AssemblyIsInGAC" = "11:FALSE" + "AssemblyAsmDisplayName" = "8:itextsharp, Version=4.1.6.0, Culture=neutral, PublicKeyToken=8354ae6d2174ddca" + "ScatterAssemblies" + { + "_2DE6EF1ABB79F2AA4737A51FF7D76E09" + { + "Name" = "8:iTextSharp.dll" + "Attributes" = "3:512" + } + } + "SourcePath" = "8:iTextSharp.dll" + "TargetName" = "8:" "Tag" = "8:" "Folder" = "8:_A9D432D1BD184FBBBA449A695853B61D" "Condition" = "8:" @@ -225,24 +226,13 @@ "PackageAs" = "3:1" "Register" = "3:1" "Exclude" = "11:FALSE" - "IsDependency" = "11:FALSE" + "IsDependency" = "11:TRUE" "IsolateTo" = "8:" } - "{9F6F8455-1EF1-4B85-886A-4223BCC8E7F7}:_7A7D4121338B9A976525C35D744FC34C" + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_334B958DF4E2498E9F250950853E2FBC" { - "AssemblyRegister" = "3:1" - "AssemblyIsInGAC" = "11:FALSE" - "AssemblyAsmDisplayName" = "8:itextsharp, Version=4.1.2.0, Culture=neutral, PublicKeyToken=8354ae6d2174ddca" - "ScatterAssemblies" - { - "_7A7D4121338B9A976525C35D744FC34C" - { - "Name" = "8:itextsharp.dll" - "Attributes" = "3:512" - } - } - "SourcePath" = "8:itextsharp.dll" - "TargetName" = "8:" + "SourcePath" = "8:setup-banner.jpg" + "TargetName" = "8:setup-banner.jpg" "Tag" = "8:" "Folder" = "8:_A9D432D1BD184FBBBA449A695853B61D" "Condition" = "8:" @@ -256,7 +246,7 @@ "PackageAs" = "3:1" "Register" = "3:1" "Exclude" = "11:FALSE" - "IsDependency" = "11:TRUE" + "IsDependency" = "11:FALSE" "IsolateTo" = "8:" } "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_830F5153980D43C59906B09D0D07B2F9" @@ -387,7 +377,7 @@ "Name" = "8:Microsoft Visual Studio" "ProductName" = "8:PDFBinder" "ProductCode" = "8:{8BA03AC2-579F-41CD-A250-740137D86F7A}" - "PackageCode" = "8:{C2BDFFB1-1BF4-4BE1-9DDC-D22E8E551D7E}" + "PackageCode" = "8:{70345C84-5946-4D5B-AF91-053F70F1A334}" "UpgradeCode" = "8:{9B78857D-281F-4FA4-918F-AE20C1B6C342}" "AspNetVersion" = "8:4.0.30319.0" "RestartWWWService" = "11:FALSE" diff --git a/src/PDFBinder.sln b/src/PDFBinder.sln index 1c4204d..dd81ed5 100644 --- a/src/PDFBinder.sln +++ b/src/PDFBinder.sln @@ -1,6 +1,8 @@  -Microsoft Visual Studio Solution File, Format Version 11.00 -# Visual Studio 2010 +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0.31101.0 +MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PDFBinder", "PDFBinder\PDFBinder.csproj", "{C4013FBF-4357-4580-9E6F-8EF23D5B04E4}" EndProject Project("{54435603-DBB4-11D2-8724-00A0C9A8B90C}") = "PDFBinderSetup", "PDFBinderSetup\PDFBinderSetup.vdproj", "{D3AE3A9A-5943-4C92-8241-1EA35FBF7F63}" @@ -13,9 +15,10 @@ Global GlobalSection(ProjectConfigurationPlatforms) = postSolution {C4013FBF-4357-4580-9E6F-8EF23D5B04E4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {C4013FBF-4357-4580-9E6F-8EF23D5B04E4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C4013FBF-4357-4580-9E6F-8EF23D5B04E4}.Debug|Any CPU.Deploy.0 = Debug|Any CPU {C4013FBF-4357-4580-9E6F-8EF23D5B04E4}.Release|Any CPU.ActiveCfg = Release|Any CPU {C4013FBF-4357-4580-9E6F-8EF23D5B04E4}.Release|Any CPU.Build.0 = Release|Any CPU - {D3AE3A9A-5943-4C92-8241-1EA35FBF7F63}.Debug|Any CPU.ActiveCfg = Debug + {D3AE3A9A-5943-4C92-8241-1EA35FBF7F63}.Debug|Any CPU.ActiveCfg = Release {D3AE3A9A-5943-4C92-8241-1EA35FBF7F63}.Release|Any CPU.ActiveCfg = Release EndGlobalSection GlobalSection(SolutionProperties) = preSolution diff --git a/src/PDFBinder/Binder.cs b/src/PDFBinder/Binder.cs index 9c62706..eca90b3 100644 --- a/src/PDFBinder/Binder.cs +++ b/src/PDFBinder/Binder.cs @@ -19,11 +19,151 @@ using System; using System.IO; +using System.Collections; +using System.Collections.Generic; using iTextSharp.text; using iTextSharp.text.pdf; namespace PDFBinder { + + + public class PageNumberGeneratorGenerator : IEnumerable + { + public String pagesIntent; + public PageNumberGeneratorGenerator(String pagesIntent) + { + this.pagesIntent = pagesIntent; + } + public IEnumerator GetEnumerator() { + return new PageNumberGenerator(this.pagesIntent, LastPage); + } + IEnumerator IEnumerable.GetEnumerator() + { + return new PageNumberGenerator(this.pagesIntent, LastPage); + } + + private int lastPage = 0; + public int LastPage + { + get { return lastPage; } + set { lastPage = value; } + } + } + + public class PageNumberGenerator : IEnumerator + { + public class PageRange + { + public int begin; + public int end; + } + private int lastPage = 0; + public int LastPage + { + get { return lastPage; } + set { lastPage = value; } + } + + public bool selectAll = true; + public List ranges = new List(); + private List.Enumerator placeKeeper; + private int lastPageGenerated = 0; + public PageNumberGenerator(String pagesIntent, int lastPage) + { + List output = new List(); + string[] regions = pagesIntent.Split(','); + LastPage = lastPage; + foreach (string r in regions) + { + if (r.Length == 0) + { + continue; + } + string[] endpointsStrings = r.Split('-'); + if (endpointsStrings.Length > 2) { + throw new ArgumentException(); + } + PageRange pr = new PageRange(); + bool ok = int.TryParse(endpointsStrings[0], out pr.begin); + if (endpointsStrings.Length == 2 ) { + if (endpointsStrings[1] == "") { + pr.end = 0; + } else { + ok &= int.TryParse(endpointsStrings[1], out pr.end); + } + } + if (!ok) { + throw new ArgumentException("Region couldn't be parsed " + r); + } + ranges.Add(pr); + selectAll = false; + } + placeKeeper = ranges.GetEnumerator(); + } + public void Reset() + { + placeKeeper = ranges.GetEnumerator(); + } + + void IDisposable.Dispose() + { + ranges = null; + placeKeeper.Dispose(); + } + public int Current + { + get { return lastPageGenerated; } + } + + object IEnumerator.Current + { + get { return Current; } + } + + public bool MoveNext() + { + if (selectAll) + { + lastPageGenerated += 1; + return (lastPageGenerated <= LastPage); + } + int nextPage = lastPageGenerated + 1; + bool bMoveForwardToNextRange = false; + if (placeKeeper.Current == null) + { + bMoveForwardToNextRange = true; + + } + else if (placeKeeper.Current.end == 0) // support open-ended selection "5-". + { + if (nextPage > LastPage) + { + bMoveForwardToNextRange = true; + } + } else if (nextPage > placeKeeper.Current.end) + { + bMoveForwardToNextRange = true; + } + + if (bMoveForwardToNextRange) + { + if (placeKeeper.MoveNext()) + { + nextPage = placeKeeper.Current.begin; + } + else + { + return false; + } + } + + lastPageGenerated = nextPage; + return true; + } + } + + class Combiner : IDisposable { private readonly Document _document; @@ -55,31 +195,105 @@ public void AddFile(string fileName) reader.Close(); } - public void Dispose() + public void AddFile(string fileName, byte[] password, String pages) { - _document.Close(); + try + { + var reader = new PdfReader(fileName, password); + PageNumberGeneratorGenerator png = new PageNumberGeneratorGenerator(pages); + AddPages(reader, png); + reader.Close(); + } + catch (BadPasswordException bpe) + { + AddFile(fileName); + return; + } } - public static SourceTestResult TestSourceFile(string fileName) + private void AddPage(PdfReader reader, int p) { - try + var size = reader.GetPageSizeWithRotation(p); + _document.SetPageSize(size); + _document.NewPage(); + var page = _pdfCopy.GetImportedPage(reader, p); + if (page != null) { - PdfReader reader = new PdfReader(fileName); - bool ok = !reader.IsEncrypted() || - (reader.Permissions & PdfWriter.AllowAssembly) == PdfWriter.AllowAssembly; - reader.Close(); + _pdfCopy.AddPage(page); + } + else + { + throw new PdfException("Null page returned: " + p ); + } + } - return ok ? SourceTestResult.Ok : SourceTestResult.Protected; + private void AddPages(PdfReader reader, PageNumberGeneratorGenerator png) + { + png.LastPage = reader.NumberOfPages; + + try + { + foreach (int p in png) + { + AddPage(reader, p); + } + } catch (Exception pdfe) { + System.Diagnostics.Debug.Write(pdfe); + throw new PdfException(pdfe.Message); } - catch + } + + + public void Dispose() + { + _document.Close(); + } + + + public static SourceTestResult TestSourceFile(string fileName, byte[] password) + { + bool tryAgain = false; + while (true) { - return SourceTestResult.Unreadable; + try + { + PdfReader reader; + if (!tryAgain) + { + reader = new PdfReader(fileName); + } + else + { + reader = new PdfReader(fileName, password); + } + + bool ok = !reader.IsEncrypted() || reader.IsOpenedWithFullPermissions || + (reader.Permissions & PdfWriter.AllowAssembly) == PdfWriter.AllowAssembly; + reader.Close(); + + return ok ? SourceTestResult.Ok : SourceTestResult.Protected; + } + catch (iTextSharp.text.pdf.BadPasswordException bpe) + { + if (tryAgain) + { + return SourceTestResult.PasswordRequired; + } + else + { + tryAgain = true; + } + } + catch (Exception) + { + return SourceTestResult.Unreadable ; + } } } public enum SourceTestResult { - Ok, Unreadable, Protected + Ok, Unreadable, Protected, PasswordRequired } } } diff --git a/src/PDFBinder/MainForm.Designer.cs b/src/PDFBinder/MainForm.Designer.cs index 52251ad..232d408 100644 --- a/src/PDFBinder/MainForm.Designer.cs +++ b/src/PDFBinder/MainForm.Designer.cs @@ -28,11 +28,12 @@ protected override void Dispose(bool disposing) /// private void InitializeComponent() { + this.components = new System.ComponentModel.Container(); System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainForm)); - this.inputListBox = new System.Windows.Forms.ListBox(); this.toolStrip1 = new System.Windows.Forms.ToolStrip(); this.addFileButton = new System.Windows.Forms.ToolStripButton(); this.removeButton = new System.Windows.Forms.ToolStripButton(); + this.RemoveAllButton = new System.Windows.Forms.ToolStripButton(); this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator(); this.moveUpButton = new System.Windows.Forms.ToolStripButton(); this.moveDownButton = new System.Windows.Forms.ToolStripButton(); @@ -42,29 +43,19 @@ private void InitializeComponent() this.addFileDialog = new System.Windows.Forms.OpenFileDialog(); this.progressBar = new System.Windows.Forms.ProgressBar(); this.helpLabel = new System.Windows.Forms.Label(); + this.FileListPanel = new System.Windows.Forms.FlowLayoutPanel(); + this.labelTitleFileName = new System.Windows.Forms.Label(); + this.labelTitlePages = new System.Windows.Forms.Label(); + this.toolTip1 = new System.Windows.Forms.ToolTip(this.components); this.toolStrip1.SuspendLayout(); this.SuspendLayout(); // - // inputListBox - // - this.inputListBox.AllowDrop = true; - this.inputListBox.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) - | System.Windows.Forms.AnchorStyles.Left) - | System.Windows.Forms.AnchorStyles.Right))); - this.inputListBox.FormattingEnabled = true; - this.inputListBox.Location = new System.Drawing.Point(4, 30); - this.inputListBox.Name = "inputListBox"; - this.inputListBox.Size = new System.Drawing.Size(422, 147); - this.inputListBox.TabIndex = 0; - this.inputListBox.SelectedIndexChanged += new System.EventHandler(this.inputListBox_SelectedIndexChanged); - this.inputListBox.DragDrop += new System.Windows.Forms.DragEventHandler(this.inputListBox_DragDrop); - this.inputListBox.DragEnter += new System.Windows.Forms.DragEventHandler(this.inputListBox_DragEnter); - // // toolStrip1 // this.toolStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { this.addFileButton, this.removeButton, + this.RemoveAllButton, this.toolStripSeparator1, this.moveUpButton, this.moveDownButton, @@ -81,21 +72,31 @@ private void InitializeComponent() this.addFileButton.Image = ((System.Drawing.Image)(resources.GetObject("addFileButton.Image"))); this.addFileButton.ImageTransparentColor = System.Drawing.Color.Magenta; this.addFileButton.Name = "addFileButton"; - this.addFileButton.Size = new System.Drawing.Size(75, 22); + this.addFileButton.Size = new System.Drawing.Size(77, 22); this.addFileButton.Text = "Add file..."; this.addFileButton.Click += new System.EventHandler(this.addFileButton_Click); // // removeButton // - this.removeButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; this.removeButton.Enabled = false; this.removeButton.Image = ((System.Drawing.Image)(resources.GetObject("removeButton.Image"))); this.removeButton.ImageTransparentColor = System.Drawing.Color.Magenta; this.removeButton.Name = "removeButton"; - this.removeButton.Size = new System.Drawing.Size(23, 22); + this.removeButton.Size = new System.Drawing.Size(116, 22); this.removeButton.Text = "Remove selected"; this.removeButton.Click += new System.EventHandler(this.removeButton_Click); // + // RemoveAllButton + // + this.RemoveAllButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text; + this.RemoveAllButton.Enabled = false; + this.RemoveAllButton.Image = ((System.Drawing.Image)(resources.GetObject("RemoveAllButton.Image"))); + this.RemoveAllButton.ImageTransparentColor = System.Drawing.Color.Magenta; + this.RemoveAllButton.Name = "RemoveAllButton"; + this.RemoveAllButton.Size = new System.Drawing.Size(55, 22); + this.RemoveAllButton.Text = "Clear All"; + this.RemoveAllButton.Click += new System.EventHandler(this.ClearAllButton_Click); + // // toolStripSeparator1 // this.toolStripSeparator1.Name = "toolStripSeparator1"; @@ -134,7 +135,7 @@ private void InitializeComponent() this.completeButton.Image = ((System.Drawing.Image)(resources.GetObject("completeButton.Image"))); this.completeButton.ImageTransparentColor = System.Drawing.Color.Magenta; this.completeButton.Name = "completeButton"; - this.completeButton.Size = new System.Drawing.Size(51, 22); + this.completeButton.Size = new System.Drawing.Size(54, 22); this.completeButton.Text = "Bind!"; this.completeButton.Click += new System.EventHandler(this.combineButton_Click); // @@ -146,43 +147,85 @@ private void InitializeComponent() // addFileDialog // this.addFileDialog.DefaultExt = "pdf"; - this.addFileDialog.Filter = "PDF documents|*.pdf"; + this.addFileDialog.Filter = "All supported types|*.pdf;*.txt|PDF documents|*.pdf|Plain text list of PDFs|*.txt" + + ""; this.addFileDialog.Multiselect = true; + this.addFileDialog.FileOk += new System.ComponentModel.CancelEventHandler(this.addFileDialog_FileOk); // // progressBar // - this.progressBar.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) - | System.Windows.Forms.AnchorStyles.Right))); - this.progressBar.Location = new System.Drawing.Point(4, 183); + this.progressBar.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.progressBar.Location = new System.Drawing.Point(0, 203); + this.progressBar.MaximumSize = new System.Drawing.Size(0, 16); this.progressBar.Name = "progressBar"; - this.progressBar.Size = new System.Drawing.Size(422, 16); + this.progressBar.Size = new System.Drawing.Size(0, 16); this.progressBar.TabIndex = 2; this.progressBar.Visible = false; // // helpLabel // - this.helpLabel.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) - | System.Windows.Forms.AnchorStyles.Right))); + this.helpLabel.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); this.helpLabel.AutoSize = true; - this.helpLabel.Location = new System.Drawing.Point(4, 183); + this.helpLabel.Location = new System.Drawing.Point(4, 203); this.helpLabel.Name = "helpLabel"; this.helpLabel.Size = new System.Drawing.Size(0, 13); this.helpLabel.TabIndex = 3; // + // FileListPanel + // + this.FileListPanel.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.FileListPanel.AutoScroll = true; + this.FileListPanel.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; + this.FileListPanel.Location = new System.Drawing.Point(0, 42); + this.FileListPanel.MinimumSize = new System.Drawing.Size(423, 150); + this.FileListPanel.Name = "FileListPanel"; + this.FileListPanel.Size = new System.Drawing.Size(429, 158); + this.FileListPanel.TabIndex = 4; + // + // labelTitleFileName + // + this.labelTitleFileName.AutoSize = true; + this.labelTitleFileName.Location = new System.Drawing.Point(15, 27); + this.labelTitleFileName.Name = "labelTitleFileName"; + this.labelTitleFileName.Size = new System.Drawing.Size(52, 13); + this.labelTitleFileName.TabIndex = 5; + this.labelTitleFileName.Text = "File name"; + this.labelTitleFileName.Visible = false; + // + // labelTitlePages + // + this.labelTitlePages.AutoSize = true; + this.labelTitlePages.Location = new System.Drawing.Point(345, 27); + this.labelTitlePages.Name = "labelTitlePages"; + this.labelTitlePages.Size = new System.Drawing.Size(37, 13); + this.labelTitlePages.TabIndex = 5; + this.labelTitlePages.Text = "Pages"; + this.labelTitlePages.Visible = false; + // // MainForm // + this.AllowDrop = true; this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.ClientSize = new System.Drawing.Size(429, 202); + this.ClientSize = new System.Drawing.Size(429, 222); + this.Controls.Add(this.labelTitlePages); + this.Controls.Add(this.labelTitleFileName); this.Controls.Add(this.progressBar); + this.Controls.Add(this.FileListPanel); this.Controls.Add(this.helpLabel); this.Controls.Add(this.toolStrip1); - this.Controls.Add(this.inputListBox); this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); - this.MinimumSize = new System.Drawing.Size(437, 229); + this.MinimumSize = new System.Drawing.Size(445, 260); this.Name = "MainForm"; this.Text = "PDFBinder"; - this.TopMost = true; + this.Load += new System.EventHandler(this.MainForm_Load); + this.DragDrop += new System.Windows.Forms.DragEventHandler(this.inputListBox_DragDrop); + this.DragEnter += new System.Windows.Forms.DragEventHandler(this.inputListBox_DragEnter); + this.KeyDown += new System.Windows.Forms.KeyEventHandler(this.MainForm_KeyDown); this.toolStrip1.ResumeLayout(false); this.toolStrip1.PerformLayout(); this.ResumeLayout(false); @@ -192,7 +235,6 @@ private void InitializeComponent() #endregion - private System.Windows.Forms.ListBox inputListBox; private System.Windows.Forms.ToolStrip toolStrip1; private System.Windows.Forms.ToolStripButton addFileButton; private System.Windows.Forms.ToolStripButton moveUpButton; @@ -205,6 +247,11 @@ private void InitializeComponent() private System.Windows.Forms.OpenFileDialog addFileDialog; private System.Windows.Forms.ProgressBar progressBar; private System.Windows.Forms.Label helpLabel; + private System.Windows.Forms.ToolStripButton RemoveAllButton; + private System.Windows.Forms.FlowLayoutPanel FileListPanel; + private System.Windows.Forms.Label labelTitleFileName; + private System.Windows.Forms.Label labelTitlePages; + private System.Windows.Forms.ToolTip toolTip1; } } diff --git a/src/PDFBinder/MainForm.cs b/src/PDFBinder/MainForm.cs index a5753e5..3209a8b 100644 --- a/src/PDFBinder/MainForm.cs +++ b/src/PDFBinder/MainForm.cs @@ -5,58 +5,205 @@ using System.Drawing; using System.Text; using System.Windows.Forms; +using iTextSharp.text.pdf; namespace PDFBinder { public partial class MainForm : Form { + + public List selectedItems = new List(); + public Control selectionPendingItem = null; + public Boolean selectionMode = true; + + + public void ResetItemSelection() + { + selectionPendingItem = null; + selectionMode = true; + } + public bool SelectRangeEnd(Control endOfSelectionItem) + { + if (null != selectionPendingItem) { + int start = Math.Min(FileListPanel.Controls.IndexOf(selectionPendingItem), FileListPanel.Controls.IndexOf(endOfSelectionItem)); + int end = Math.Max(FileListPanel.Controls.IndexOf(selectionPendingItem), FileListPanel.Controls.IndexOf(endOfSelectionItem)); + + for (int i = start; i <= end ; i++) { + ((PdfItem)FileListPanel.Controls[i]).Selected = selectionMode; + } + + return true; + } + else + { + return false; + } + } + public MainForm() { InitializeComponent(); UpdateUI(); } + + public static byte[] StrToByteArray(string str) + { + System.Text.UTF8Encoding encoding = new System.Text.UTF8Encoding(); + return encoding.GetBytes(str); + } + + private Dictionary passwords = new Dictionary(); + + private byte[] currentPassword = null; public void AddInputFile(string file) { - switch (Combiner.TestSourceFile(file)) + // to open a text file with a list of pdfs (or further text files, i guess) to be added + if (file.EndsWith(".txt")) + { + string[] pdf_files = System.IO.File.ReadAllLines(file); + foreach (string item in pdf_files) + { + AddInputFile(item); + } + // txt file itself is not to be bound in to the output pdf. + return; + } + + // support password in txt manifest files delimited by pipe character "|" + // support page selection in txt manifest files + string filename = null; + string password = null; + string pageSelections = ""; + string[] item_info = file.Split('|'); + if (item_info.Length > 0) { - case Combiner.SourceTestResult.Unreadable: - MessageBox.Show(string.Format("File could not be opened as a PDF document:\n\n{0}", file), "Illegal file type", MessageBoxButtons.OK, MessageBoxIcon.Error); - break; - case Combiner.SourceTestResult.Protected: - MessageBox.Show(string.Format("PDF document does not allow copying:\n\n{0}", file), "Permission denied", MessageBoxButtons.OK, MessageBoxIcon.Hand); - break; - case Combiner.SourceTestResult.Ok: - inputListBox.Items.Add(file); - break; + filename = item_info[0]; + if (item_info.Length > 1) + { + password = item_info[1]; + } + pageSelections = ""; + if (item_info.Length > 2) + { + pageSelections = item_info[2]; + } + } + + if (! System.IO.File.Exists(filename)) + { + MessageBox.Show(string.Format("File not found:\n\n{0}", filename), "File not found", MessageBoxButtons.OK, MessageBoxIcon.Error); + return; + } + + Boolean tryAgain = true; + Boolean newPassword = false; + while (tryAgain || newPassword) { + newPassword = false; + switch (Combiner.TestSourceFile(filename, currentPassword)) + { + case Combiner.SourceTestResult.Unreadable: + MessageBox.Show(string.Format("File could not be opened as a PDF document:\n\n{0}", filename), "Illegal file type", MessageBoxButtons.OK, MessageBoxIcon.Error); + break; + case Combiner.SourceTestResult.Protected: + MessageBox.Show(string.Format("PDF document does not allow copying:\n\n{0}", filename), "Permission denied", MessageBoxButtons.OK, MessageBoxIcon.Hand); + break; + case Combiner.SourceTestResult.Ok: + // inputListBox.Items.Add(file); + + PdfItem pi = new PdfItem(); + pi.BinderParentForm = this; + pi.FileName = filename; + pi.PageDescriptor = pageSelections; + pi.Selected = false; + FileListPanel.Controls.Add(pi); + if (password != null) { + currentPassword = StrToByteArray(password); + } + passwords[file] = currentPassword; + break; + case Combiner.SourceTestResult.PasswordRequired: + if (tryAgain) + { + PasswordEntry pe = new PasswordEntry(); + pe.Prompt = "Password required for file: \n" + file; + DialogResult dr = pe.ShowDialog(this); + + if (dr == System.Windows.Forms.DialogResult.OK) { + currentPassword = StrToByteArray(pe.Password); + newPassword = true; + } + } + else + { + MessageBox.Show(string.Format("Password supplied didn't open PDF document:\n\n{0}", file), "Bad password", MessageBoxButtons.OK, MessageBoxIcon.Hand); + } + break; + } + tryAgain = false; } } public void UpdateUI() { - if (inputListBox.Items.Count < 2) + bool isPopulated = (FileListPanel.Controls.Count > 0); + + if (!isPopulated) { - completeButton.Enabled = false; - helpLabel.Text = "Drop PDF-documents in the box above, or choose \"add document\" from the toolbar"; + helpLabel.Text = "Drop PDF-documents in the box above, or choose \"Add file...\" from the toolbar"; } else { - completeButton.Enabled = true; helpLabel.Text = "Click the \"bind!\" button when you are done adding documents"; } - if (inputListBox.SelectedIndex < 0) + completeButton.Enabled = isPopulated; + RemoveAllButton.Enabled = isPopulated; + labelTitleFileName.Visible = isPopulated; + labelTitlePages.Visible = isPopulated; + + + if (selectedItems.Count < 1) { removeButton.Enabled = moveUpButton.Enabled = moveDownButton.Enabled = false; } else { removeButton.Enabled = true; - moveUpButton.Enabled = (inputListBox.SelectedIndex > 0); - moveDownButton.Enabled = (inputListBox.SelectedIndex < inputListBox.Items.Count - 1); + moveUpButton.Enabled = GetLowestSelectedIndex() > 0; + moveDownButton.Enabled = GetHighestSelectedIndex() < FileListPanel.Controls.Count - 1; } } + private int GetHighestSelectedIndex() + { + int max = -1; + + foreach (PdfItem pi in selectedItems) + { + int thisIndex = FileListPanel.Controls.IndexOf(pi); + if (thisIndex > max) + { + max = thisIndex; + } + } + return max; + } + private int GetLowestSelectedIndex() + { + int min = FileListPanel.Controls.Count - 1; + + foreach (PdfItem pi in selectedItems) + { + int thisIndex = FileListPanel.Controls.IndexOf(pi); + if (thisIndex < min) + { + min = thisIndex; + } + } + return min; + } + private void inputListBox_DragEnter(object sender, DragEventArgs e) { e.Effect = e.Data.GetDataPresent(DataFormats.FileDrop, false) ? DragDropEffects.All : DragDropEffects.None; @@ -75,27 +222,74 @@ private void inputListBox_DragDrop(object sender, DragEventArgs e) UpdateUI(); } - private void combineButton_Click(object sender, EventArgs e) + private void combineFiles(string saveFileName, out int countFilesBound, out string diagnostic) { - if (saveFileDialog.ShowDialog() == DialogResult.OK) + diagnostic = ""; + using (var combiner = new Combiner(saveFileName)) { - using (var combiner = new Combiner(saveFileDialog.FileName)) + progressBar.Visible = true; + this.Enabled = false; + + int i = 0; + foreach (PdfItem pi in FileListPanel.Controls) { - progressBar.Visible = true; - this.Enabled = false; + try + { + byte[] pw; + bool found_pw = passwords.TryGetValue(pi.FileName, out pw); + if (found_pw && pw != null) + { + combiner.AddFile(pi.FileName, pw, pi.PageDescriptor); + } + else + { + combiner.AddFile(pi.FileName, new byte[0], pi.PageDescriptor); + } - for (int i = 0; i < inputListBox.Items.Count; i++) + + } + catch (PdfException pdfe) { - combiner.AddFile((string)inputListBox.Items[i]); - progressBar.Value = (int)(((i + 1) / (double)inputListBox.Items.Count) * 100); + diagnostic += pi.FileName + ": " + pdfe.Message + "\n"; } + i += 1; + progressBar.Value = (int)(((i) / (double)FileListPanel.Controls.Count) * 100); + } + + countFilesBound = i; + + + return; + } + + } + + private void combineButton_Click(object sender, EventArgs e) + { + string diagnostic = null; + int successfullyBoundFilesCount = 0; + if (saveFileDialog.ShowDialog() == DialogResult.OK) + { + try + { + combineFiles(saveFileDialog.FileName, out successfullyBoundFilesCount, out diagnostic); + } + catch (System.IO.IOException ioe) + { + // this happens if empty document is created + MessageBox.Show("Error closing bound document. " + ioe.Message); + } - this.Enabled = true; - progressBar.Visible = false; + this.Enabled = true; + progressBar.Visible = false; + if (diagnostic != "") + { + MessageBox.Show("There were some problems binding the files:\n\n" + diagnostic); } System.Diagnostics.Process.Start(saveFileDialog.FileName); + } } @@ -107,35 +301,86 @@ private void addFileButton_Click(object sender, EventArgs e) { AddInputFile(file); } - UpdateUI(); } } - private void inputListBox_SelectedIndexChanged(object sender, EventArgs e) + private void removeButton_Click(object sender, EventArgs e) { + RemoveSelected(); + } + + private void moveItemButton_Click(object sender, EventArgs e) + { + foreach (PdfItem pi in selectedItems) + { + int index = FileListPanel.Controls.IndexOf(pi); + if (sender == moveUpButton) + index--; + if (sender == moveDownButton) + index++; + FileListPanel.Controls.SetChildIndex(pi, index); + } + ResetItemSelection(); UpdateUI(); } - private void removeButton_Click(object sender, EventArgs e) + public void RemoveSelected() { + + int indexOfTopSelected = GetLowestSelectedIndex(); + if (FileListPanel.HasChildren) + { + RemoveItems(selectedItems.ToArray()); + } + selectedItems.Clear(); + + if (FileListPanel.Controls.Count > indexOfTopSelected) + { + ((PdfItem)FileListPanel.Controls[indexOfTopSelected]).Selected = true; + } + + ResetItemSelection(); + UpdateUI(); + } + + void RemoveItems(Control[] removeList) { - inputListBox.Items.Remove(inputListBox.SelectedItem); + foreach (Control pi in removeList) + { + FileListPanel.Controls.Remove(pi); + } } - private void moveItemButton_Click(object sender, EventArgs e) + private void ClearAllButton_Click(object sender, EventArgs e) { - object dataItem = inputListBox.SelectedItem; - int index = inputListBox.SelectedIndex; + if (FileListPanel.HasChildren) + { + Control[] removeList = new Control[FileListPanel.Controls.Count]; + FileListPanel.Controls.CopyTo(removeList,0); + RemoveItems(removeList); + } + selectedItems.Clear(); + ResetItemSelection(); + UpdateUI(); + } - if (sender == moveUpButton) - index--; - if (sender == moveDownButton) - index++; + private void MainForm_Load(object sender, EventArgs e) + { + toolTip1.SetToolTip(labelTitlePages, "Pages can be left blank for all, or a list of pages. e.g. \"8,16-22,45\""); + } - inputListBox.Items.Remove(dataItem); - inputListBox.Items.Insert(index, dataItem); + private void MainForm_KeyDown(object sender, KeyEventArgs e) + { + if (!(e.KeyData == Keys.Delete)) + { + return; + } + RemoveSelected(); + } + + private void addFileDialog_FileOk(object sender, CancelEventArgs e) + { - inputListBox.SelectedIndex = index; } } } \ No newline at end of file diff --git a/src/PDFBinder/MainForm.resx b/src/PDFBinder/MainForm.resx index cb1fc7a..fb453c5 100644 --- a/src/PDFBinder/MainForm.resx +++ b/src/PDFBinder/MainForm.resx @@ -124,74 +124,87 @@ iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 - YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAnVJREFUOE+tk+9L - U1EYx/1btIhgBYpGRoI/iBKMxEulTpvk1HTNTVvkdHfT3Jy7y4m/5oaZBW3lthjpppvTkYqZOLV0kXod - SrRRBEFt7O23e4PdUZgvogcOnDefz3Oe7zknJeV/FzUnS+v2SslOl5hun6yLyl8Ko7IXVXSzXUCKn91I - O7If5WsitJ6myNP1QaxGFhH8uoH1LyvwhJxQecWot1yL1IyVEIdKWFjtFsd8e04c/NjD3KcpWOgRPN4x - wrlvwdLnV6AW5BCMFMcqzEW/S7Q+aaraLQ1P79qw930bo9v9GFjrhiGghjGox1CQgmGzE9MHTpBeEQjT - pXCJsSCVO4nWI1EOL2vw4dsm03EIg1sUdG9USJRmTQ7FogjKZQnc+w5cf3QBRX25Sk7ABjYVcjBHteLB - age6VhSQzzVyggYHH/dmq3BnpgLmd3r0L7XjouE8zQmUE7Vx/8cpDL/XM3ArB/65kXrKoJyvhy04ivzu - rDgnaHVWxydD46A2SHQE7h4pIP11sAcfIkeTnhTIHALaFKBg3NKh9bUI0vlq1NivciK2M7uavXwMBzTo - 8bchu/N0cgTJeKXylp2AK2SDfF6IJr/g18yJYuFGdylk0xVw7VpR0HsWmR28ZIj1lvLU2idEmPQ2YIJ+ - zgXGghI3u1iYj8kdC27bypF5nxc+pTqevEY2jJtjV4hK8+VYi0sINyMxBbQgZ2uhmBHCtNoFFwOLbKXI - VJ2MpZMnDn+NZeZCghjIjxSb89C7QML61gjrhhE6fwvye84wMC/yVzhxJcV9eWmFhhyygDpH5+qyotna - jGgWE1hGO4/MaDt29Gf6l5/9E6HYz36xqhCWAAAAAElFTkSuQmCC + YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAJ8SURBVDhPrZP9S1NRGMfv3zKLIJaQaFQk+EKUYCReKl+b + 5Evq0k1b5HR3c02du+bEt+tGmQVt5bYa6aabLyMVM3Fq6SL1OpRoowiC2vDXb/fWtSFaEPSB89vz+Z7z + POcc4r9DTyriWr1ySueqYhuHiyKKF5KI4pmErbVLqKonV+OEsoOhx2tIvacm/HipBwvhGQS+LGPp8zw8 + QSc03ipUWC6HSweySaF8L7yseV4eHd90Yvv7JiY/jsDC3sPDdQbOLQtmP70EPa2EhMmKFpgz94box+Wi + Jrc8NLphw+a3NfSvdaF7sRVGfxOYQBt6AzSMKzqMbjtBeaUgTedD2Uy6SNC5AI9M3TfXjPdfV7gde9Gz + SsPwWoNdmheVUM1IoZ6Twb3lwJUHZ5HZmaIWdILgBzYSdHBHteLughYt8yooJ6sFHah05OP2RBFujhXA + /LYNXbONOGc8wwo6QaiHind8H0bQ966Nk+sFbT9yTy7UUxWwBfqRpo3fEXSCqHcW7wwHB0EvU9D6bwnl + ++EDKN912AP3kaw5GgtQOCSsyU+DWTWg/pUU8qlilNovCdovkV+13nz0+ZvR7mvAKV18rAXZYKG63E7C + FbRBOVWCGp/kZ8+78HK1OweK0QK4NqxI7ziJRK04NsQKS56o7BEZoryVGGKf/h4YL8rc/OLlfAyvW3DD + lofEO+LQMc3h2DXyXBu4SBYyF6J1rhK4uRCTXw9qogyqsRKYFlrg4mSpLQeJGlH0OHXk4NeYa84gye60 + cJY5FR3TFKxvGFiXGRh8dUhrP8HJ4vAf5V2yOlPjMozJVDp9mk0xJEWS9AmRJG5gCY1iKqHh0N8/079D + ED8A07zPKpBMK/UAAAAASUVORK5CYII= iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 - YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAmBJREFUOE+tk+1L - U3EUx/1bXFEYWGC+KEKoKHJu7rHN5R65Nd2WsYilKbvDNIOSxTR8Ec6a61Er36i1CZEp2oOjB0WlqzG1 - 3dqoNb13c1vKtzloJk1fRAe+L7+f8/t9zzk5Of+75qqqOH6j0TpboadmdFrmo07DTGtV1CRRbh1Xyzlb - 9lswmSQzRiP9vdWO+NAzJMbHkHgzDLa3C/NmPd6rJbRPKZBkhayZZysr2aVHXVidmUbS+xhJtwNJ51X8 - fNCOlVEvgnVmvCrjsa8VRzdC5gyG3Fl9RYC558YqNYHkjcuIOGxYtNcift2GRAuJePN5xPvvY+EMgVHp - kcCQ+HBu5iV+g4EMNVixMuFLd1xuJRG+YkGs8fQGMRcIxHtu452gCC+kRWQG8CkVWLTnDpLdTkSaq/FN - I82qpWoCrL0eQVsNnov2UxnAtJ6IJTw9SLbaELlkxmYVVPARNqqx6GzDAK8glgFMEZrYcrcL8SYzYhcr - twSE9EostrfBw9/9B0CjoMLN9Vh2kGDOqbDWKavKBYg01GG+zgIvN3/9CxMaOUnJShDr7kTkpAxhvfgv - AF3GA31CjKj7JoaFe/GUm7ce4gedOPetWhJYMOkQfehKBxhSCtMQWlEKWpYyy4RgOzswqZWirzgv0Fuy - fX2Ma2H4FDzJS1kx6z+lRPSuCz+aSASJcnxRKRButIK91YEplQi93J1sX/GO7Ns4mtqwkeOH6DHxAXyt - tSDcci2tzzVnMcgvSJl30Zuaf49kWH6QMyjYZx0QFVLe0kLGw93D9JXmU09K8qz9x7ZtfUz/ctm/ACIv - 0vPrY3daAAAAAElFTkSuQmCC + YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAJiSURBVDhPrZP7S1NhHMbP37IVwQoJyh+KECqSnJfdbHO5 + eZJTBzczFmGasjNMMygx1OiHcNZcV5cJMc0MIvMGpXRRVDor1LVTG7U2dza3pTxt68QSZxD0wPPb83le + 3u/7fYn/rsWqKvGC0Wj+QNOsiyRD7xOeJ/XsLFVqni7TiIVYZrkrK1Ws0ch962hFdOQZYtOTiL0aBe/s + wZKJxtsyFTelk6mE+HolYVdFBb/c24M11zziQw8Rt7chbr2MH/c7sToxBG+9CWOKAv6lNnd9yaLBIHLR + tCd01441dgbx6xcRaLMg2FqH6FULYu0Moi1nER24B/cpChOqQ54R5UGRgBPEgsHA+BrNWJ2ZSp240sHA + f6kakaaT6xw6RyHadwtvZDl4UZzDCDhBfEwMLNx3G3GHFYGWGnwlizN6uYYC39oAr6UWzxV7WQEniBmK + isSe9CHeYUHgggmbyasthN9YhqD1GgZzd0QEPFlARlYcNkSbTYicrxDiG5Us8NE6BDuTBZJ0wRxZwvpb + GrDSxiB0Rp8KZnSpDIHGeizVV2NImvXHFUgNw6rzEXF0I3BcDT+t3ABzJQXgjioRtt/AqHw3BqWS9BDf + lStFr/Uqj7uyHOEHttTAfDr5L1BbBE6dgNVy8N1dmD1WjP48iceZvzX9jElNaQtUY4o8fuGEDuE7Nnxv + ZuClSvFZr4W/yQz+Zhfm9Ar0SkV8f962zNs4kdiw8SMHuEnlPnypq4a//UrKn2pPY7hwFx5Jt3Obwr81 + qtkvHpbtMT9VZLNOaXbIKd0ZchZlsY/zJeaBw1v+/pn+XQTxE2kZ0otdc+AqAAAAAElFTkSuQmCC + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAIDSURBVDhPpZLrS5NhGMb3j4SWh0oRQVExD4gonkDpg4hG + YKxG6WBogkMZKgPNCEVJFBGdGETEvgwyO9DJE5syZw3PIlPEE9pgBCLZ5XvdMB8Ew8gXbl54nuf63dd9 + 0OGSnwCahxbPRNPAPMw9Xpg6ZmF46kZZ0xSKzJPIrhpDWsVnpBhGkKx3nAX8Pv7z1zg8OoY/cITdn4fw + bf/C0kYAN3Ma/w3gWfZL5kzTKBxjWyK2DftwI9tyMYCZKXbNHaD91bLYJrDXsYbrWfUKwJrPE9M2M1Oc + VzOOpHI7Jr376Hi9ogHqFIANO0/MmmmbmSmm9a8ze+I4MrNWAdjtoJgWcx+PSzg166yZZ8xM8XvXDix9 + c4jIqFYAjoriBV9AhEPv1mH/sonogha0afbZMMZz+yreTGyhpusHwtNNCsA5U1zS4BLxzJIfg299qO32 + Ir7UJtZfftyATqeT+8o2D8JSjQrAJblrncYL7ZJ2+bfaFnC/1S1NjL3diRat7qrO7wLRP3HjWsojBeCo + mDEo5mNjuweFGvjWg2EBhCbpkW78htSHHwRyNdmgAFzPEee2iFkzayy2OLXzT4gr6UdUnlXrullsxxQ+ + kx0g8BTA3aZlButjSTyjODq/WcQcW/B/Je4OQhLvKQDnzN1mp0nnkvAhR8VuMzNrpm1mpjgkoVwB/v8D + TgDQASA1MVpwzwAAAABJRU5ErkJggg== iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 - YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAATpJREFUOE9jYKAl - KD6cejLvQOoRsuwoPJJ2seNU3f/WE9X/07fHnCfakPoroWxFh9Jut5+q+b/82rz/S6/M+V97oPh/3Org - m6GrQtkIGlR4MHl33p6k783HKv8vvjLr/8LLM/63Ha79H7rE/3vwHM8dBA2AKUjdEv1//qVp/+dcmPI/ - dU3s/8BZHhZEawYpjF8b9n/W+cn/Z5yb8D9glsd/kjSDFEcuC/g/9Uzf/8mnu/97TXIi3YDgeV7/J57q - +t93sv2/c5cN6Qb4THX933O89X/nsab/tk1mpBvg1mv/v/1o4//Ww3X/zaoMSTfAvtXyf9Oh2v8NB6v+ - GxRpk26AZa3x/7oDlf9r9pf9185WI90A41Ld/1V7S/5X7C36r5aqRLoBunka/zUzVf+rpij+V0qQI90A - YhMOAOHQlzjkvPH+AAAAAElFTkSuQmCC + YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAE8SURBVDhPY6ApKD6cejLvQOoRKJc0UHgk7WLHqbr/rSeq + /6dvjzkPFSYM6q+EshUdSrvdfqrm//Jr8/4vvTLnf+2B4v9xq4Nvhq4KZYMqww0KDybvztua9L35WOX/ + xVdm/V94ecb/tsO1//2X+H8PnuO5A6qMMEjdEv1//qVp/+dcmPI/dU3s/8BZHhZQKeJA/Nqw/7POT/4/ + 49yE/wGzPP5DhYkHkcsC/k890/d/8unu/16TnEg3IHie1/+Jp7r+951s/+/cZUO6AT5TXf/3HG/933ms + 6b9tkxnpBrj12v9vP9r4v/Vw3X+zKkPSDbBvtfzfdKj2f8PBqv8GRdqkG2BZa/y/7kDl/5r9Zf+1s9VI + N8C4VPd/1d6S/xV7i/6rpSqRboBunsZ/zUzV/6opiv+VEuRIN4A4wMAAALvElytY0LimAAAAAElFTkSu + QmCC iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 - YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAATdJREFUOE9jYKAV - KDme8b/4WPr/gkOp/3P3Jf0n2Z6io2n/V99Y9H/l9QX/M3bEkm5A/oHk/8uvzfu/9Mqc/8mbIkk3IGt3 - /P/FV2b9X3h5xv/YVcGkG5C6Jfr//EvT/s+5MOV/+CI/0g2IXxv2f9b5yf9nnJvwP2CWB+kGRC4L+D/1 - TN//yae7/3tNciLdgOB5Xv8nnur633ey/b9zlw3pBvhMdf3fc7z1f+expv+2TWakGeAxzcUidJbf//aj - jf9bD9f9N6syJN4Az4lOO1x7rL7nrE3933So9n/Dwar/AZO8/+vkqn9XT1feTTBFhtZrsdk1WdwMnxn4 - v+5A5f+a/WX/vXvd/qulKdzWCtViI2gATIFRqe55336P/149rv9VUpUuEq0RWaFmpsoR5RS5k2RpJlYT - AOV+lFsgsrmSAAAAAElFTkSuQmCC + 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 + 7UEAAAAASUVORK5CYII= @@ -200,6 +213,9 @@ 348, 17 + + 474, 17 + AAABAAQAEBAAAAEACABoBQAARgAAABgYAAABAAgAyAYAAK4FAAAgIAAAAQAgAKgQAAB2DAAAMDAAAAEA diff --git a/src/PDFBinder/PDFBinder.csproj b/src/PDFBinder/PDFBinder.csproj index 9ef3b1b..deaf878 100644 --- a/src/PDFBinder/PDFBinder.csproj +++ b/src/PDFBinder/PDFBinder.csproj @@ -14,11 +14,28 @@ 512 - application.res + E:\work\dotnet\pdfbinder\src\PDFBinder\application.res 3.5 + false + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + true + 2 + 1.0.0.%2a + false + true + true true @@ -37,6 +54,29 @@ prompt 4 + + 40038AB39C635999A9FB4B8B0830C363811B7D0E + + + PDFBinder_TemporaryKey.pfx + + + false + + + false + + + Custom + + + + PDFBinder.Program + + + false + + False @@ -59,12 +99,30 @@ MainForm.cs + + Form + + + PasswordEntry.cs + + + UserControl + + + PdfItem.cs + MainForm.cs Designer + + PasswordEntry.cs + + + PdfItem.cs + ResXFileCodeGenerator Resources.Designer.cs @@ -76,6 +134,7 @@ True + SettingsSingleFileGenerator Settings.Designer.cs @@ -92,6 +151,21 @@ + + + False + .NET Framework 3.5 SP1 Client Profile + false + + + False + .NET Framework 3.5 SP1 + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/src/PDFBinder/PdfItem.Designer.cs b/src/PDFBinder/PdfItem.Designer.cs new file mode 100644 index 0000000..a7511c3 --- /dev/null +++ b/src/PDFBinder/PdfItem.Designer.cs @@ -0,0 +1,91 @@ +namespace PDFBinder +{ + partial class PdfItem + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + this.FileNameLabel = new System.Windows.Forms.Label(); + this.PageSelection_textBox = new System.Windows.Forms.TextBox(); + this.toolTip1 = new System.Windows.Forms.ToolTip(this.components); + this.SuspendLayout(); + // + // FileNameLabel + // + this.FileNameLabel.AutoEllipsis = true; + this.FileNameLabel.AutoSize = true; + this.FileNameLabel.Location = new System.Drawing.Point(19, 4); + this.FileNameLabel.MaximumSize = new System.Drawing.Size(300, 0); + this.FileNameLabel.Name = "FileNameLabel"; + this.FileNameLabel.Padding = new System.Windows.Forms.Padding(0, 0, 0, 5); + this.FileNameLabel.Size = new System.Drawing.Size(35, 18); + this.FileNameLabel.TabIndex = 0; + this.FileNameLabel.Text = "label1"; + this.FileNameLabel.Click += new System.EventHandler(this.PdfItem_Click); + // + // PageSelection_textBox + // + this.PageSelection_textBox.Location = new System.Drawing.Point(320, 1); + this.PageSelection_textBox.Name = "PageSelection_textBox"; + this.PageSelection_textBox.Size = new System.Drawing.Size(76, 20); + this.PageSelection_textBox.TabIndex = 1; + this.PageSelection_textBox.TextChanged += new System.EventHandler(this.PageSelection_textBox_TextChanged); + // + // toolTip1 + // + this.toolTip1.AutomaticDelay = 100; + this.toolTip1.AutoPopDelay = 5000; + this.toolTip1.InitialDelay = 100; + this.toolTip1.ReshowDelay = 20; + // + // PdfItem + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.AutoSize = true; + this.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; + this.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.Controls.Add(this.PageSelection_textBox); + this.Controls.Add(this.FileNameLabel); + this.Margin = new System.Windows.Forms.Padding(0); + this.MaximumSize = new System.Drawing.Size(400, 60); + this.MinimumSize = new System.Drawing.Size(400, 20); + this.Name = "PdfItem"; + this.Size = new System.Drawing.Size(398, 24); + this.Click += new System.EventHandler(this.PdfItem_Click); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.Label FileNameLabel; + private System.Windows.Forms.TextBox PageSelection_textBox; + private System.Windows.Forms.ToolTip toolTip1; + } +} diff --git a/src/PDFBinder/PdfItem.cs b/src/PDFBinder/PdfItem.cs new file mode 100644 index 0000000..8fb8f7d --- /dev/null +++ b/src/PDFBinder/PdfItem.cs @@ -0,0 +1,101 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Drawing; +using System.Data; +using System.Text; +using System.Windows.Forms; + +namespace PDFBinder +{ + public partial class PdfItem : UserControl + { + public PdfItem() + { + InitializeComponent(); + + BinderParentForm = (MainForm)ParentForm; + } + + private MainForm binderParentForm; + public MainForm BinderParentForm + { + get { return binderParentForm; } + set { binderParentForm = value; } + } + + private String fileName; + public String FileName { + get { return fileName;} + set { fileName = value; this.FileNameLabel.Text = fileName; this.toolTip1.SetToolTip(this.FileNameLabel, fileName); } + } + + private String pageDescriptor; + public String PageDescriptor { + get { return pageDescriptor;} + set { pageDescriptor = value; this.PageSelection_textBox.Text = pageDescriptor; } + } + + private bool selected; + public bool Selected + { + get { return selected; } + set + { + this.selected = value; + if (this.selected) + { + this.BackColor = SystemColors.Highlight; + this.ForeColor = SystemColors.HighlightText; + BinderParentForm.selectedItems.Add(this); + } + else + { + this.BackColor = SystemColors.Control; + this.ForeColor = SystemColors.ControlText; + if (BinderParentForm.selectedItems.Contains(this)) + { + BinderParentForm.selectedItems.Remove(this); + } + } + } + } + + private void PdfItem_Click(object sender, EventArgs e) + { + bool handled = false; + if ((ModifierKeys & Keys.Control) == Keys.Control) // keydown + { + this.Selected = !this.Selected; + handled = true; + // not handling control+shift, getting carried away. + } + else if ((ModifierKeys & Keys.Shift) == Keys.Shift) + { + // the other end of a selection, perhaps. + handled = BinderParentForm.SelectRangeEnd(this); + } + + if (!handled) + { + // no keyboard modifier, just select + List tmpSelected = new List(); + tmpSelected.AddRange(BinderParentForm.selectedItems); + foreach (PdfItem pi in tmpSelected) + { + pi.Selected = false; + } + this.Selected = true; + + BinderParentForm.selectionMode = true; + binderParentForm.selectionPendingItem = this; + } + BinderParentForm.UpdateUI(); + } + + private void PageSelection_textBox_TextChanged(object sender, EventArgs e) + { + PageDescriptor = PageSelection_textBox.Text; + } + } +} diff --git a/src/PDFBinder/PdfItem.resx b/src/PDFBinder/PdfItem.resx new file mode 100644 index 0000000..850792f --- /dev/null +++ b/src/PDFBinder/PdfItem.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + \ No newline at end of file diff --git a/src/PDFBinder/Properties/AssemblyInfo.cs b/src/PDFBinder/Properties/AssemblyInfo.cs index b1f979d..cb483a4 100644 --- a/src/PDFBinder/Properties/AssemblyInfo.cs +++ b/src/PDFBinder/Properties/AssemblyInfo.cs @@ -28,4 +28,4 @@ [assembly: ComVisible(false)] -[assembly: AssemblyVersion("1.2.*")] +[assembly: AssemblyVersion("1.3.*")]