source: trunk/eraser/Eraser.Util/ExtensionMethods/PathUtil.cs @ 2515

Revision 2515, 5.8 KB checked in by lowjoel, 3 years ago (diff)

Set svn:keywords and svn:eol-style on all the source files.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Rev URL
Line 
1/*
2 * $Id$
3 * Copyright 2008-2010 The Eraser Project
4 * Original Author: Joel Low <lowjoel@users.sourceforge.net>
5 * Modified By:
6 *
7 * This file is part of Eraser.
8 *
9 * Eraser is free software: you can redistribute it and/or modify it under the
10 * terms of the GNU General Public License as published by the Free Software
11 * Foundation, either version 3 of the License, or (at your option) any later
12 * version.
13 *
14 * Eraser is distributed in the hope that it will be useful, but WITHOUT ANY
15 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
16 * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
17 *
18 * A copy of the GNU General Public License can be found at
19 * <http://www.gnu.org/licenses/>.
20 */
21
22using System;
23using System.Collections.Generic;
24using System.Linq;
25using System.Text;
26using System.IO;
27using System.Drawing;
28using System.Windows.Forms;
29
30namespace Eraser.Util.ExtensionMethods
31{
32    /// <summary>
33    /// Additional Path utility methods.
34    /// </summary>
35    public class PathUtil
36    {
37        /// <summary>
38        /// Makes the first path relative to the second.
39        /// </summary>
40        /// <remarks>Modified from:
41        /// http://mrpmorris.blogspot.com/2007/05/convert-absolute-path-to-relative-path.html</remarks>
42        /// <param name="absolutePath">The path to use as the root of the relative path.</param>
43        /// <param name="relativeTo">The path to make relative.</param>
44        /// <returns>The relative path to the provided path.</returns>
45        public static string MakeRelativeTo(FileSystemInfo absolutePath, string relativeTo)
46        {
47            string[] absoluteDirectories = absolutePath.FullName.Split(
48                System.IO.Path.DirectorySeparatorChar, System.IO.Path.AltDirectorySeparatorChar);
49            string[] relativeDirectories = relativeTo.Split(
50                System.IO.Path.DirectorySeparatorChar, System.IO.Path.AltDirectorySeparatorChar);
51
52            //Get the shortest of the two paths
53            int length = absoluteDirectories.Length < relativeDirectories.Length ?
54                absoluteDirectories.Length : relativeDirectories.Length;
55
56            //Use to determine where in the loop we exited
57            int lastCommonRoot = -1;
58            int index;
59
60            //Find common root
61            for (index = 0; index < length; index++)
62                if (absoluteDirectories[index] == relativeDirectories[index])
63                    lastCommonRoot = index;
64                else
65                    break;
66
67            //If we didn't find a common prefix then throw
68            if (lastCommonRoot == -1)
69                throw new ArgumentException("Paths do not have a common base");
70
71            //Build up the relative path
72            StringBuilder relativePath = new StringBuilder();
73
74            //Add on the ..
75            for (index = lastCommonRoot + 1; index < absoluteDirectories.Length; index++)
76                if (absoluteDirectories[index].Length > 0)
77                    relativePath.Append("..\\");
78
79            //Add on the folders
80            for (index = lastCommonRoot + 1; index < relativeDirectories.Length - 1; index++)
81                relativePath.Append(relativeDirectories[index] + "\\");
82            if (lastCommonRoot < relativeDirectories.Length - 1)
83                relativePath.Append(relativeDirectories[relativeDirectories.Length - 1]);
84
85            return relativePath.ToString();
86        }
87
88        /// <summary>
89        /// Verifies if the path given is rooted at the given absolute path.
90        /// </summary>
91        /// <param name="absolutePath">The root path.</param>
92        /// <param name="path">The path to verify.</param>
93        /// <returns>True if the path provided is a subfolder/sub-file of the provided root path.</returns>
94        public static bool IsRootedAt(FileSystemInfo absolutePath, string path)
95        {
96            //Convert the path in question to an absolute path
97            if (!System.IO.Path.IsPathRooted(path))
98                path = System.IO.Path.GetFullPath(path);
99
100            //Split the directory path to its component folders
101            string[] absoluteDirectories = absolutePath.FullName.Split(
102                System.IO.Path.DirectorySeparatorChar, System.IO.Path.AltDirectorySeparatorChar);
103            string[] relativeDirectories = path.Split(
104                System.IO.Path.DirectorySeparatorChar, System.IO.Path.AltDirectorySeparatorChar);
105
106            //Compare element by element; if the absolute path compares till the end, the
107            //provided path is a subdirectory
108            for (int i = 0; i < absoluteDirectories.Length; ++i)
109                if (absoluteDirectories[i] != relativeDirectories[i])
110                    return false;
111
112            return true;
113        }
114
115        /// <summary>
116        /// Compacts the file path, fitting in the given width.
117        /// </summary>
118        /// <param name="longPath">The path to compact.</param>
119        /// <param name="newWidth">The target width of the text.</param>
120        /// <param name="drawFont">The font used for drawing the text.</param>
121        /// <returns>The compacted file path.</returns>
122        public static string GetCompactPath(string longPath, int newWidth, Font drawFont)
123        {
124            using (Control ctrl = new Control())
125            using (Graphics g = ctrl.CreateGraphics())
126            {
127                //First check if the source string is too long.
128                int width = g.MeasureString(longPath, drawFont).ToSize().Width;
129                if (width <= newWidth)
130                    return longPath;
131
132                //It is, shorten it.
133                int aveCharWidth = width / longPath.Length;
134                int charCount = newWidth / aveCharWidth;
135                StringBuilder builder = new StringBuilder();
136                builder.Append(longPath);
137                builder.EnsureCapacity(charCount);
138
139                while (g.MeasureString(builder.ToString(), drawFont).Width > newWidth)
140                {
141                    if (!NativeMethods.PathCompactPathEx(builder, longPath,
142                        (uint)charCount--, 0))
143                    {
144                        return string.Empty;
145                    }
146                }
147
148                return builder.ToString();
149            }
150        }
151
152        /// <summary>
153        /// Compacts the file path, fitting in the given width.
154        /// </summary>
155        /// <param name="longPath">The path to compact.</param>
156        /// <param name="newWidth">The target width of the text.</param>
157        /// <param name="control">The control on which this text is drawn. This is used
158        /// for font information.</param>
159        /// <returns>The compacted file path.</returns>
160        public static string GetCompactPath(string longPath, int newWidth, Control control)
161        {
162            return GetCompactPath(longPath, newWidth, control.Font);
163        }
164    }
165}
Note: See TracBrowser for help on using the repository browser.