Author Topic: ora extension support  (Read 2953 times)

shrike

  • Guest
ora extension support
« on: January 20, 2011, 11:46:04 pm »
Hi, i've just started using mypaint and i love it so much.

I'm used to work under Windows so I spent some times in last days looking for:

  • a Paint.net filetype plugin (I prefere to use it instead of Gimp for easy tasks)
  • a decent preview support in explorer
  • a thumbnail shell extension in explorer

Looking for the Paint.net filetype support I also discoverd Pinta, that has native support for .ora files and that, at first sight, seems to be good enough to replace Paint.Net in what I meant to do.

Anyway I had already spent some times over Paint.net plugin, and at this link http://forums.getpaint.net/index.php?/topic/20538-ora-attempt/ it's possibile to find last code version and on open discussion regarding code issues.

About preview support instead, I implemented an .ora preview file handler starting from this article: http://msdn.microsoft.com/en-us/magazine/cc163487.aspx. In the article it's explained how to implement different preview file handler (very usefull indeed) and one of the handler is for .zip file, so I've just extended it (moving also from J# java.util.zip to ICSharpCode.SharpZipLib.Zip) and I've implemented an .ora preview file handler that uses the thumbnail.png contained into the .ora file as default preview and, double clicking over the image, shows also a treeview with the .ora content.

In the following code I've left the original MsdnMag strings and namespace of Stephen Toub's code:

1st implementation: only image preview:
Code: [Select]

using System;
using System.IO;
using System.Text;
using System.Diagnostics;
using System.Windows.Forms;
using System.Runtime.InteropServices;

using ICSharpCode.SharpZipLib.Zip;

using System.Collections;
using System.Collections.Generic;
using System.Drawing;


namespace MsdnMag
{
    [PreviewHandler("MSDN Magazine ORA Preview Handler", ".ora", "{1EB81F89-78AF-42bf-A59C-7E31AE0B0BE2}")]
    [ProgId("MsdnMag.OraPreviewHandler")]
    [Guid("C9ED3380-3878-4b5d-AE65-6EE71CF8F615")]
    [ClassInterface(ClassInterfaceType.None)]
    [ComVisible(true)]
    public sealed class OraPreviewHandler : FileBasedPreviewHandler
    {
        protected override PreviewHandlerControl CreatePreviewHandlerControl()
        {
            return new OraPreviewHandlerControl();
        }

        private sealed class OraPreviewHandlerControl : FileBasedPreviewHandlerControl
        {
            public override void Load(FileInfo file)
            {
                ZipFile zip = new ZipFile(file.FullName);
                ZipEntry entry = zip.GetEntry("Thumbnails/thumbnail.png");
                Stream inStream = zip.GetInputStream(entry);
                Bitmap bmp = new Bitmap(inStream);
                PictureBox pictureBox = new PictureBox();
                pictureBox.Size = new Size(bmp.Width, bmp.Height);
                pictureBox.Image = bmp;
                pictureBox.Dock = DockStyle.Fill;
                Controls.Add(pictureBox);
                zip.Close();
            }
        }
    }
}

2nd implementation: image and treeview preview:
Code: [Select]
using System;
using System.IO;
using System.Text;
using System.Diagnostics;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Collections;
using System.Collections.Generic;
using System.Drawing;
using ICSharpCode.SharpZipLib.Zip;

namespace MsdnMag
{
    [PreviewHandler("MSDN Magazine ORA Preview Handler", ".ora", "{1EB81F89-78AF-42bf-A59C-7E31AE0B0BE2}")]
    [ProgId("MsdnMag.OraPreviewHandler")]
    [Guid("C9ED3380-3878-4b5d-AE65-6EE71CF8F615")]
    [ClassInterface(ClassInterfaceType.None)]
    [ComVisible(true)]
    public sealed class OraPreviewHandler : FileBasedPreviewHandler
    {
        protected override PreviewHandlerControl CreatePreviewHandlerControl()
        {
            return new OraPreviewHandlerControl();
        }

        private sealed class OraPreviewHandlerControl : FileBasedPreviewHandlerControl
        {
            public override void Load(FileInfo file)
            {
                TreeView folderView = new TreeView();
                folderView.ImageList = _iconProvider.Icons;
                folderView.FullRowSelect = true;
                folderView.ShowLines = true;
                folderView.ShowPlusMinus = true;
                folderView.ShowRootLines = true;
                folderView.LabelEdit = false;
                folderView.BorderStyle = BorderStyle.None;
                folderView.TreeViewNodeSorter = new NodeSorter();

                List<string> filenames = new List<string>();
                ZipFile zip = new ZipFile(file.FullName);

                IEnumerator entryEnum = zip.GetEnumerator();
                ZipEntry entry = null;
                while (entryEnum.MoveNext())
                {
                    entry = (ZipEntry)entryEnum.Current;
                    if (!entry.IsDirectory)
                        filenames.Add(entry.Name);
                }

                //Get preview bmp
                Bitmap bmp = null;
                entry = zip.GetEntry("Thumbnails/thumbnail.png");
                Stream inStream = zip.GetInputStream(entry);
                bmp = new Bitmap(inStream);
                zip.Close();


                TreeNode root = ConvertFilenamesToTreeRoot(file.Name, filenames);
                folderView.Nodes.Add(root);
                root.Expand();

                folderView.DoubleClick += delegate
                {
                    if (folderView.SelectedNode != null && folderView.SelectedNode.Tag as string != null)
                    {
                        TreeNode selectedNode = folderView.SelectedNode;
                        ZipFile zipToOpen = new ZipFile(file.FullName);
                        string tempPath = ExtractZipEntryToFile((string)selectedNode.Tag, zipToOpen);
                        zipToOpen.Close();
                        Process.Start(tempPath);
                    }
                };

                PictureBox pictureBox = new PictureBox();
                pictureBox.Size = new Size(bmp.Width, bmp.Height);
                pictureBox.Image = bmp;
                pictureBox.Dock = DockStyle.Top;
                folderView.Location = new Point(0, bmp.Height + 5);
                folderView.Size = new Size(bmp.Width, 500);
                folderView.Visible = false;
                pictureBox.DoubleClick += delegate
                {
                    //Swap folderView visibility
                    folderView.Visible = !folderView.Visible;
                };
                Controls.Add(pictureBox);
                Controls.Add(folderView);
            }


            private class NodeSorter : IComparer
            {
                int IComparer.Compare(object x, object y)
                {
                    TreeNode node1 = (TreeNode)x;
                    TreeNode node2 = (TreeNode)y;

                    string tag1 = node1.Tag as string;
                    string tag2 = node2.Tag as string;

                    if (tag1 == null && tag2 == null) return StrCmpLogicalW(node1.Text, node2.Text);
                    else if (tag1 == tag2) return 0;
                    else if (tag1 == null) return -1;
                    else if (tag2 == null) return 1;
                    else return StrCmpLogicalW(tag1, tag2);
                }

                [DllImport("shlwapi.dll", CharSet = CharSet.Unicode, ExactSpelling = true)]
                private static extern int StrCmpLogicalW(string strA, string strB);
            }

            private TreeNode ConvertFilenamesToTreeRoot(string rootName, IEnumerable<string> names)
            {
                TreeNode rootNode = new TreeNode(rootName);
                rootNode.ImageIndex = _iconProvider.FolderIndex;
                foreach (string name in names)
                {
                    string[] pathParts = name.Split(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar);
                    TreeNode parent = rootNode;
                    for(int i=0; i<pathParts.Length; i++)
                    {
                        string pathPart = pathParts[i];
                        TreeNode[] foundNodes = parent.Nodes.Find(pathPart, false);
                        TreeNode partNode;
                        if (foundNodes.Length == 0 || i == pathParts.Length-1)
                        {
                            partNode = new TreeNode(pathPart);
                            partNode.Name = pathPart;
                            parent.Nodes.Add(partNode);
                            if (i == pathParts.Length - 1)
                            {
                                partNode.ImageIndex = _iconProvider.GetIconIndexForFile(name);
                                partNode.Tag = name;
                            }
                            else partNode.ImageIndex = _iconProvider.FolderIndex;
                        }
                        else
                        {
                            partNode = foundNodes[0];
                        }
                        partNode.SelectedImageIndex = partNode.ImageIndex;
                        parent = partNode;
                    }
                }
                return rootNode;
            }

            private static string ExtractZipEntryToFile(string entryName, ZipFile zip)
            {
                ZipEntry entry = zip.GetEntry(entryName);

                Stream from = zip.GetInputStream(entry);
                string tempPath = Path.GetTempPath() + Path.GetFileName(entry.Name);
                Stream to = new FileStream(tempPath, FileMode.Create);

                byte[] buffer = new byte[0x1000];
                int amountRead;
                while ((amountRead = from.Read(buffer, 0, buffer.Length)) > 0) to.Write(buffer, 0, amountRead);

                from.Close();
                to.Close();

                return tempPath;
            }

            private FileTypeIconProvider _iconProvider = new FileTypeIconProvider();

            protected override void Dispose(bool disposing)
            {
                if (disposing && _iconProvider != null)
                {
                    _iconProvider.Dispose();
                    _iconProvider = null;
                }
                base.Dispose(disposing);
            }
        }
    }
}

Whenever I'll have some free times I'm going to look after thumbnail shell extension (I've already some example to start with and it should not be so difficult).


jonnor

  • Guest
Re: ora extension support
« Reply #1 on: January 24, 2011, 02:31:52 am »
Nice work!
If you put a license on your work you may put this under the source control repository we have at http://www.gitorious.org/openraster/openraster-misc. Make sure you actually have a right to license it the way you want, you might not if it derives from code in an article for instance. Also, when you have something useful, please consider putting it on http://create.freedesktop.org/wiki/OpenRaster (the official website), and tell people via the create mailing list.

shrike

  • Guest
Re: ora extension support
« Reply #2 on: January 24, 2011, 10:28:00 pm »
Thaks. About the Paint.Net plugin I did nothing more than some fixes to someone else's code, so I will post there suggesting the same you said to me.

About the preview file handler instead I will contact the autor to check if there's any issues about extending the tutorial code the way I did.