# HG changeset patch # User moel.mich # Date 1338131779 0 # Node ID 0c551e8818e056a1ca6a0f213ddcff69d2785e78 # Parent 3145aadca3d202a933e4123c642e95885a35647d Added the source code of Aga.Controls (TreeViewAdv for .Net) version 1.7.0.0. diff -r 3145aadca3d2 -r 0c551e8818e0 External/Aga.Controls/Aga.Controls.csproj --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/External/Aga.Controls/Aga.Controls.csproj Sun May 27 15:16:19 2012 +0000 @@ -0,0 +1,221 @@ + + + Debug + AnyCPU + 9.0.30729 + 2.0 + {E73BB233-D88B-44A7-A98F-D71EE158381D} + Library + Properties + Aga.Controls + Aga.Controls + + + + + + + + + + + 2.0 + + + + + true + full + false + bin\Debug\ + TRACE;DEBUG;PERF_TEST + prompt + 4 + -Microsoft.Design#CA1020;-Microsoft.Design#CA1060;-Microsoft.Design#CA1062;-Microsoft.Globalization#CA1301;-Microsoft.Globalization#CA1302;-Microsoft.Globalization#CA1303;-Microsoft.Globalization#CA1306;-Microsoft.Globalization#CA1304;-Microsoft.Globalization#CA1305;-Microsoft.Globalization#CA1300;-Microsoft.Maintainability#CA1501;-Microsoft.Mobility#CA1601;-Microsoft.Performance#CA1805;-Microsoft.Performance#CA1815;-Microsoft.Performance#CA1819;-Microsoft.Usage#CA2208 + true + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + true + + + + + + + + + + + + + + + + True + True + Resources.resx + + + + + + + + + + + + Component + + + Component + + + Component + + + Component + + + Component + + + + + + + + + + Component + + + Component + + + Component + + + + + + + Component + + + + + Component + + + + + + Component + + + Component + + + Component + + + + + + + Component + + + + + + + + + + + + + + + Component + + + + Component + + + Component + + + Component + + + + + Component + + + Component + + + + Component + + + + + + Component + + + TreeViewAdv.cs + + + + + + + + + + + + + + + + + Designer + ResXFileCodeGenerator + Resources.Designer.cs + + + TreeViewAdv.cs + + + + + + + + + + + + + + \ No newline at end of file diff -r 3145aadca3d2 -r 0c551e8818e0 External/Aga.Controls/BitmapHelper.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/External/Aga.Controls/BitmapHelper.cs Sun May 27 15:16:19 2012 +0000 @@ -0,0 +1,46 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Drawing; +using System.Runtime.InteropServices; +using System.Drawing.Imaging; + +namespace Aga.Controls +{ + public static class BitmapHelper + { + [StructLayout(LayoutKind.Sequential)] + private struct PixelData + { + public byte B; + public byte G; + public byte R; + public byte A; + } + + public static void SetAlphaChanelValue(Bitmap image, byte value) + { + if (image == null) + throw new ArgumentNullException("image"); + if (image.PixelFormat != PixelFormat.Format32bppArgb) + throw new ArgumentException("Wrong PixelFormat"); + + BitmapData bitmapData = image.LockBits(new Rectangle(0, 0, image.Width, image.Height), + ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb); + unsafe + { + PixelData* pPixel = (PixelData*)bitmapData.Scan0; + for (int i = 0; i < bitmapData.Height; i++) + { + for (int j = 0; j < bitmapData.Width; j++) + { + pPixel->A = value; + pPixel++; + } + pPixel += bitmapData.Stride - (bitmapData.Width * 4); + } + } + image.UnlockBits(bitmapData); + } + } +} diff -r 3145aadca3d2 -r 0c551e8818e0 External/Aga.Controls/GifDecoder.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/External/Aga.Controls/GifDecoder.cs Sun May 27 15:16:19 2012 +0000 @@ -0,0 +1,864 @@ +#pragma warning disable 675 // Bitwise-or operator used on a sign-extended operand + +#region Java Info +/** + * Class GifDecoder - Decodes a GIF file into one or more frames. + *
+ * Example:
+ *    GifDecoder d = new GifDecoder();
+ *    d.read("sample.gif");
+ *    int n = d.getFrameCount();
+ *    for (int i = 0; i < n; i++) {
+ *       BufferedImage frame = d.getFrame(i);  // frame i
+ *       int t = d.getDelay(i);  // display duration of frame in milliseconds
+ *       // do something with frame
+ *    }
+ * 
+ * No copyright asserted on the source code of this class. May be used for + * any purpose, however, refer to the Unisys LZW patent for any additional + * restrictions. Please forward any corrections to kweiner@fmsware.com. + * + * @author Kevin Weiner, FM Software; LZW decoder adapted from John Cristy's ImageMagick. + * @version 1.03 November 2003 + * + */ +#endregion + +using System; +using System.Collections; +using System.Drawing; +using System.Drawing.Imaging; +using System.IO; + +namespace Aga.Controls +{ + public class GifFrame + { + private Image _image; + public Image Image + { + get { return _image; } + } + + private int _delay; + public int Delay + { + get { return _delay; } + } + + public GifFrame(Image im, int del) + { + _image = im; + _delay = del; + } + } + + public class GifDecoder + { + public const int StatusOK = 0;//File read status: No errors. + public const int StatusFormatError = 1; //File read status: Error decoding file (may be partially decoded) + public const int StatusOpenError = 2; //Unable to open source. + + private Stream inStream; + private int status; + + private int width; // full image width + private int height; // full image height + private bool gctFlag; // global color table used + private int gctSize; // size of global color table + private int loopCount = 1; // iterations; 0 = repeat forever + + private int[] gct; // global color table + private int[] lct; // local color table + private int[] act; // active color table + + private int bgIndex; // background color index + private int bgColor; // background color + private int lastBgColor; // previous bg color + private int pixelAspect; // pixel aspect ratio + + private bool lctFlag; // local color table flag + private bool interlace; // interlace flag + private int lctSize; // local color table size + + private int ix, iy, iw, ih; // current image rectangle + private Rectangle lastRect; // last image rect + private Image image; // current frame + private Bitmap bitmap; + private Image lastImage; // previous frame + + private byte[] block = new byte[256]; // current data block + private int blockSize = 0; // block size + + // last graphic control extension info + private int dispose = 0; + // 0=no action; 1=leave in place; 2=restore to bg; 3=restore to prev + private int lastDispose = 0; + private bool transparency = false; // use transparent color + private int delay = 0; // delay in milliseconds + private int transIndex; // transparent color index + + private const int MaxStackSize = 4096; + // max decoder pixel stack size + + // LZW decoder working arrays + private short[] prefix; + private byte[] suffix; + private byte[] pixelStack; + private byte[] pixels; + + private ArrayList frames; // frames read from current file + private int frameCount; + private bool _makeTransparent; + + /** + * Gets the number of frames read from file. + * @return frame count + */ + public int FrameCount + { + get + { + return frameCount; + } + } + + /** + * Gets the first (or only) image read. + * + * @return BufferedImage containing first frame, or null if none. + */ + public Image Image + { + get + { + return GetFrame(0).Image; + } + } + + /** + * Gets the "Netscape" iteration count, if any. + * A count of 0 means repeat indefinitiely. + * + * @return iteration count if one was specified, else 1. + */ + public int LoopCount + { + get + { + return loopCount; + } + } + + public GifDecoder(Stream stream, bool makeTransparent) + { + _makeTransparent = makeTransparent; + if (Read(stream) != 0) + throw new InvalidOperationException(); + } + + /** + * Creates new frame image from current data (and previous + * frames as specified by their disposition codes). + */ + private int[] GetPixels(Bitmap bitmap) + { + int [] pixels = new int [ 3 * image.Width * image.Height ]; + int count = 0; + for (int th = 0; th < image.Height; th++) + { + for (int tw = 0; tw < image.Width; tw++) + { + Color color = bitmap.GetPixel(tw, th); + pixels[count] = color.R; + count++; + pixels[count] = color.G; + count++; + pixels[count] = color.B; + count++; + } + } + return pixels; + } + + private void SetPixels(int[] pixels) + { + int count = 0; + for (int th = 0; th < image.Height; th++) + { + for (int tw = 0; tw < image.Width; tw++) + { + Color color = Color.FromArgb( pixels[count++] ); + bitmap.SetPixel( tw, th, color ); + } + } + if (_makeTransparent) + bitmap.MakeTransparent(bitmap.GetPixel(0, 0)); + } + + private void SetPixels() + { + // expose destination image's pixels as int array + // int[] dest = + // (( int ) image.getRaster().getDataBuffer()).getData(); + int[] dest = GetPixels( bitmap ); + + // fill in starting image contents based on last image's dispose code + if (lastDispose > 0) + { + if (lastDispose == 3) + { + // use image before last + int n = frameCount - 2; + if (n > 0) + { + lastImage = GetFrame(n - 1).Image; + } + else + { + lastImage = null; + } + } + + if (lastImage != null) + { + // int[] prev = + // ((DataBufferInt) lastImage.getRaster().getDataBuffer()).getData(); + int[] prev = GetPixels( new Bitmap( lastImage ) ); + Array.Copy(prev, 0, dest, 0, width * height); + // copy pixels + + if (lastDispose == 2) + { + // fill last image rect area with background color + Graphics g = Graphics.FromImage( image ); + Color c = Color.Empty; + if (transparency) + { + c = Color.FromArgb( 0, 0, 0, 0 ); // assume background is transparent + } + else + { + c = Color.FromArgb( lastBgColor ) ; + // c = new Color(lastBgColor); // use given background color + } + Brush brush = new SolidBrush( c ); + g.FillRectangle( brush, lastRect ); + brush.Dispose(); + g.Dispose(); + } + } + } + + // copy each source line to the appropriate place in the destination + int pass = 1; + int inc = 8; + int iline = 0; + for (int i = 0; i < ih; i++) + { + int line = i; + if (interlace) + { + if (iline >= ih) + { + pass++; + switch (pass) + { + case 2 : + iline = 4; + break; + case 3 : + iline = 2; + inc = 4; + break; + case 4 : + iline = 1; + inc = 2; + break; + } + } + line = iline; + iline += inc; + } + line += iy; + if (line < height) + { + int k = line * width; + int dx = k + ix; // start of line in dest + int dlim = dx + iw; // end of dest line + if ((k + width) < dlim) + { + dlim = k + width; // past dest edge + } + int sx = i * iw; // start of line in source + while (dx < dlim) + { + // map color and insert in destination + int index = ((int) pixels[sx++]) & 0xff; + int c = act[index]; + if (c != 0) + { + dest[dx] = c; + } + dx++; + } + } + } + SetPixels( dest ); + } + + /** + * Gets the image contents of frame n. + * + * @return BufferedImage representation of frame. + */ + public GifFrame GetFrame(int n) + { + if ((n >= 0) && (n < frameCount)) + return (GifFrame)frames[n]; + else + throw new ArgumentOutOfRangeException(); + } + + /** + * Gets image size. + * + * @return GIF image dimensions + */ + public Size FrameSize + { + get + { + return new Size(width, height); + } + } + + /** + * Reads GIF image from stream + * + * @param BufferedInputStream containing GIF file. + * @return read status code (0 = no errors) + */ + private int Read( Stream inStream ) + { + Init(); + if ( inStream != null) + { + this.inStream = inStream; + ReadHeader(); + if (!Error()) + { + ReadContents(); + if (frameCount < 0) + { + status = StatusFormatError; + } + } + inStream.Close(); + } + else + { + status = StatusOpenError; + } + return status; + } + + + /** + * Decodes LZW image data into pixel array. + * Adapted from John Cristy's ImageMagick. + */ + private void DecodeImageData() + { + int NullCode = -1; + int npix = iw * ih; + int available, + clear, + code_mask, + code_size, + end_of_information, + in_code, + old_code, + bits, + code, + count, + i, + datum, + data_size, + first, + top, + bi, + pi; + + if ((pixels == null) || (pixels.Length < npix)) + { + pixels = new byte[npix]; // allocate new pixel array + } + if (prefix == null) prefix = new short[MaxStackSize]; + if (suffix == null) suffix = new byte[MaxStackSize]; + if (pixelStack == null) pixelStack = new byte[MaxStackSize + 1]; + + // Initialize GIF data stream decoder. + + data_size = Read(); + clear = 1 << data_size; + end_of_information = clear + 1; + available = clear + 2; + old_code = NullCode; + code_size = data_size + 1; + code_mask = (1 << code_size) - 1; + for (code = 0; code < clear; code++) + { + prefix[code] = 0; + suffix[code] = (byte) code; + } + + // Decode GIF pixel stream. + + datum = bits = count = first = top = pi = bi = 0; + + for (i = 0; i < npix;) + { + if (top == 0) + { + if (bits < code_size) + { + // Load bytes until there are enough bits for a code. + if (count == 0) + { + // Read a new data block. + count = ReadBlock(); + if (count <= 0) + break; + bi = 0; + } + datum += (((int) block[bi]) & 0xff) << bits; + bits += 8; + bi++; + count--; + continue; + } + + // Get the next code. + + code = datum & code_mask; + datum >>= code_size; + bits -= code_size; + + // Interpret the code + + if ((code > available) || (code == end_of_information)) + break; + if (code == clear) + { + // Reset decoder. + code_size = data_size + 1; + code_mask = (1 << code_size) - 1; + available = clear + 2; + old_code = NullCode; + continue; + } + if (old_code == NullCode) + { + pixelStack[top++] = suffix[code]; + old_code = code; + first = code; + continue; + } + in_code = code; + if (code == available) + { + pixelStack[top++] = (byte) first; + code = old_code; + } + while (code > clear) + { + pixelStack[top++] = suffix[code]; + code = prefix[code]; + } + first = ((int) suffix[code]) & 0xff; + + // Add a new string to the string table, + + if (available >= MaxStackSize) + break; + pixelStack[top++] = (byte) first; + prefix[available] = (short) old_code; + suffix[available] = (byte) first; + available++; + if (((available & code_mask) == 0) + && (available < MaxStackSize)) + { + code_size++; + code_mask += available; + } + old_code = in_code; + } + + // Pop a pixel off the pixel stack. + + top--; + pixels[pi++] = pixelStack[top]; + i++; + } + + for (i = pi; i < npix; i++) + { + pixels[i] = 0; // clear missing pixels + } + + } + + /** + * Returns true if an error was encountered during reading/decoding + */ + private bool Error() + { + return status != StatusOK; + } + + /** + * Initializes or re-initializes reader + */ + private void Init() + { + status = StatusOK; + frameCount = 0; + frames = new ArrayList(); + gct = null; + lct = null; + } + + /** + * Reads a single byte from the input stream. + */ + private int Read() + { + int curByte = 0; + try + { + curByte = inStream.ReadByte(); + } + catch (IOException) + { + status = StatusFormatError; + } + return curByte; + } + + /** + * Reads next variable length block from input. + * + * @return number of bytes stored in "buffer" + */ + private int ReadBlock() + { + blockSize = Read(); + int n = 0; + if (blockSize > 0) + { + try + { + int count = 0; + while (n < blockSize) + { + count = inStream.Read(block, n, blockSize - n); + if (count == -1) + break; + n += count; + } + } + catch (IOException) + { + } + + if (n < blockSize) + { + status = StatusFormatError; + } + } + return n; + } + + /** + * Reads color table as 256 RGB integer values + * + * @param ncolors int number of colors to read + * @return int array containing 256 colors (packed ARGB with full alpha) + */ + private int[] ReadColorTable(int ncolors) + { + int nbytes = 3 * ncolors; + int[] tab = null; + byte[] c = new byte[nbytes]; + int n = 0; + try + { + n = inStream.Read(c, 0, c.Length ); + } + catch (IOException) + { + } + if (n < nbytes) + { + status = StatusFormatError; + } + else + { + tab = new int[256]; // max size to avoid bounds checks + int i = 0; + int j = 0; + while (i < ncolors) + { + int r = ((int) c[j++]) & 0xff; + int g = ((int) c[j++]) & 0xff; + int b = ((int) c[j++]) & 0xff; + tab[i++] = ( int ) ( 0xff000000 | (r << 16) | (g << 8) | b ); + } + } + return tab; + } + + /** + * Main file parser. Reads GIF content blocks. + */ + private void ReadContents() + { + // read GIF file content blocks + bool done = false; + while (!(done || Error())) + { + int code = Read(); + switch (code) + { + + case 0x2C : // image separator + ReadImage(); + break; + + case 0x21 : // extension + code = Read(); + switch (code) + { + case 0xf9 : // graphics control extension + ReadGraphicControlExt(); + break; + + case 0xff : // application extension + ReadBlock(); + String app = ""; + for (int i = 0; i < 11; i++) + { + app += (char) block[i]; + } + if (app.Equals("NETSCAPE2.0")) + { + ReadNetscapeExt(); + } + else + Skip(); // don't care + break; + + default : // uninteresting extension + Skip(); + break; + } + break; + + case 0x3b : // terminator + done = true; + break; + + case 0x00 : // bad byte, but keep going and see what happens + break; + + default : + status = StatusFormatError; + break; + } + } + } + + /** + * Reads Graphics Control Extension values + */ + private void ReadGraphicControlExt() + { + Read(); // block size + int packed = Read(); // packed fields + dispose = (packed & 0x1c) >> 2; // disposal method + if (dispose == 0) + { + dispose = 1; // elect to keep old image if discretionary + } + transparency = (packed & 1) != 0; + delay = ReadShort() * 10; // delay in milliseconds + transIndex = Read(); // transparent color index + Read(); // block terminator + } + + /** + * Reads GIF file header information. + */ + private void ReadHeader() + { + String id = ""; + for (int i = 0; i < 6; i++) + { + id += (char) Read(); + } + if (!id.StartsWith("GIF")) + { + status = StatusFormatError; + return; + } + + ReadLSD(); + if (gctFlag && !Error()) + { + gct = ReadColorTable(gctSize); + bgColor = gct[bgIndex]; + } + } + + /** + * Reads next frame image + */ + private void ReadImage() + { + ix = ReadShort(); // (sub)image position & size + iy = ReadShort(); + iw = ReadShort(); + ih = ReadShort(); + + int packed = Read(); + lctFlag = (packed & 0x80) != 0; // 1 - local color table flag + interlace = (packed & 0x40) != 0; // 2 - interlace flag + // 3 - sort flag + // 4-5 - reserved + lctSize = 2 << (packed & 7); // 6-8 - local color table size + + if (lctFlag) + { + lct = ReadColorTable(lctSize); // read table + act = lct; // make local table active + } + else + { + act = gct; // make global table active + if (bgIndex == transIndex) + bgColor = 0; + } + int save = 0; + if (transparency) + { + save = act[transIndex]; + act[transIndex] = 0; // set transparent color if specified + } + + if (act == null) + { + status = StatusFormatError; // no color table defined + } + + if (Error()) return; + + DecodeImageData(); // decode pixel data + Skip(); + + if (Error()) return; + + frameCount++; + + // create new image to receive frame data + // image = + // new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB_PRE); + + bitmap = new Bitmap( width, height ); + image = bitmap; + SetPixels(); // transfer pixel data to image + + frames.Add(new GifFrame(bitmap, delay)); // add image to frame list + + if (transparency) + { + act[transIndex] = save; + } + ResetFrame(); + + } + + /** + * Reads Logical Screen Descriptor + */ + private void ReadLSD() + { + + // logical screen size + width = ReadShort(); + height = ReadShort(); + + // packed fields + int packed = Read(); + gctFlag = (packed & 0x80) != 0; // 1 : global color table flag + // 2-4 : color resolution + // 5 : gct sort flag + gctSize = 2 << (packed & 7); // 6-8 : gct size + + bgIndex = Read(); // background color index + pixelAspect = Read(); // pixel aspect ratio + } + + /** + * Reads Netscape extenstion to obtain iteration count + */ + private void ReadNetscapeExt() + { + do + { + ReadBlock(); + if (block[0] == 1) + { + // loop count sub-block + int b1 = ((int) block[1]) & 0xff; + int b2 = ((int) block[2]) & 0xff; + loopCount = (b2 << 8) | b1; + } + } while ((blockSize > 0) && !Error()); + } + + /** + * Reads next 16-bit value, LSB first + */ + private int ReadShort() + { + // read 16-bit value, LSB first + return Read() | (Read() << 8); + } + + /** + * Resets frame state for reading next image. + */ + private void ResetFrame() + { + lastDispose = dispose; + lastRect = new Rectangle(ix, iy, iw, ih); + lastImage = image; + lastBgColor = bgColor; + // int dispose = 0; + lct = null; + } + + /** + * Skips variable length blocks up to and including + * next zero length block. + */ + private void Skip() + { + do + { + ReadBlock(); + } while ((blockSize > 0) && !Error()); + } + } +} diff -r 3145aadca3d2 -r 0c551e8818e0 External/Aga.Controls/NumericTextBox.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/External/Aga.Controls/NumericTextBox.cs Sun May 27 15:16:19 2012 +0000 @@ -0,0 +1,189 @@ +using System; +using System.ComponentModel; +using System.Windows.Forms; +using System.Globalization; + + +namespace Aga.Controls +{ + /// + /// Restricts the entry of characters to digits, the negative sign, + /// the decimal point, and editing keystrokes (backspace). + /// It does not handle the AltGr key so any keys that can be created in any + /// combination with AltGr these are not filtered + /// + public class NumericTextBox : TextBox + { + private const int WM_PASTE = 0x302; + private NumberStyles numberStyle = NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingSign; + + /// + /// Restricts the entry of characters to digits, the negative sign, + /// the decimal point, and editing keystrokes (backspace). + /// It does not handle the AltGr key + /// + /// + protected override void OnKeyPress(KeyPressEventArgs e) + { + base.OnKeyPress(e); + + e.Handled = invalidNumeric(e.KeyChar); + } + + + /// + /// Main method for verifying allowed keypresses. + /// This does not catch cut paste copy ... operations. + /// + /// + /// + private bool invalidNumeric(char key) + { + bool handled = false; + + NumberFormatInfo numberFormatInfo = CultureInfo.CurrentCulture.NumberFormat; + string decimalSeparator = numberFormatInfo.NumberDecimalSeparator; + string negativeSign = numberFormatInfo.NegativeSign; + + string keyString = key.ToString(); + + if (Char.IsDigit(key)) + { + // Digits are OK + } + else if (AllowDecimalSeparator && keyString.Equals(decimalSeparator)) + { + if (Text.IndexOf(decimalSeparator) >= 0) + { + handled = true; + } + } + else if (AllowNegativeSign && keyString.Equals(negativeSign)) + { + if (Text.IndexOf(negativeSign) >= 0) + { + handled = true; + } + } + else if (key == '\b') + { + // Backspace key is OK + } + else if ((ModifierKeys & (Keys.Control)) != 0) + { + // Let the edit control handle control and alt key combinations + } + else + { + // Swallow this invalid key and beep + handled = true; + } + return handled; + } + + + /// + /// Method invoked when Windows sends a message. + /// + /// Message from Windows. + /// + /// This is over-ridden so that the user can not use + /// cut or paste operations to bypass the TextChanging event. + /// This catches ContextMenu Paste, Shift+Insert, Ctrl+V, + /// While it is generally frowned upon to override WndProc, no + /// other simple mechanism was apparent to simultaneously and + /// transparently intercept so many different operations. + /// + protected override void WndProc(ref Message m) + { + // Switch to handle message... + switch (m.Msg) + { + case WM_PASTE: + { + // Get clipboard object to paste + IDataObject clipboardData = Clipboard.GetDataObject(); + + // Get text from clipboard data + string pasteText = (string)clipboardData.GetData( + DataFormats.UnicodeText); + + // Get the number of characters to replace + int selectionLength = SelectionLength; + + // If no replacement or insertion, we are done + if (pasteText.Length == 0) + { + break; + } + else if (selectionLength != 0) + { + base.Text = base.Text.Remove(SelectionStart, selectionLength); + } + + bool containsInvalidChars = false; + foreach (char c in pasteText) + { + if (containsInvalidChars) + { + break; + } + else if (invalidNumeric(c)) + { + containsInvalidChars = true; + } + } + + if (!containsInvalidChars) + { + base.Text = base.Text.Insert(SelectionStart, pasteText); + } + + return; + } + + } + base.WndProc(ref m); + } + + + public int IntValue + { + get + { + int intValue; + Int32.TryParse(this.Text, numberStyle, CultureInfo.CurrentCulture.NumberFormat, out intValue); + return intValue; + } + } + + public decimal DecimalValue + { + get + { + decimal decimalValue; + Decimal.TryParse(this.Text, numberStyle, CultureInfo.CurrentCulture.NumberFormat, out decimalValue); + return decimalValue; + } + } + + + private bool allowNegativeSign; + [DefaultValue(true)] + public bool AllowNegativeSign + { + get { return allowNegativeSign; } + set { allowNegativeSign = value; } + } + + private bool allowDecimalSeparator; + [DefaultValue(true)] + public bool AllowDecimalSeparator + { + get { return allowDecimalSeparator; } + set { allowDecimalSeparator = value; } + } + + } + +} diff -r 3145aadca3d2 -r 0c551e8818e0 External/Aga.Controls/PerformanceAnalyzer.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/External/Aga.Controls/PerformanceAnalyzer.cs Sun May 27 15:16:19 2012 +0000 @@ -0,0 +1,136 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Diagnostics; + +namespace Aga.Controls +{ + /// + /// Is used to analyze code performance + /// + public static class PerformanceAnalyzer + { + public class PerformanceInfo + { + private string _name; + public string Name + { + get { return _name; } + } + + private int _count = 0; + public int Count + { + get { return _count; } + set { _count = value; } + } + + private double _totalTime = 0; + public double TotalTime + { + get { return _totalTime; } + set { _totalTime = value; } + } + + private Int64 _start; + public Int64 Start + { + get { return _start; } + set { _start = value; } + } + + public PerformanceInfo(string name) + { + _name = name; + } + } + + private static Dictionary _performances = new Dictionary(); + + public static IEnumerable Performances + { + get + { + return _performances.Values; + } + } + + [Conditional("DEBUG")] + public static void Start(string pieceOfCode) + { + PerformanceInfo info = null; + lock(_performances) + { + if (_performances.ContainsKey(pieceOfCode)) + info = _performances[pieceOfCode]; + else + { + info = new PerformanceInfo(pieceOfCode); + _performances.Add(pieceOfCode, info); + } + + info.Count++; + info.Start = TimeCounter.GetStartValue(); + } + } + + [Conditional("DEBUG")] + public static void Finish(string pieceOfCode) + { + lock (_performances) + { + if (_performances.ContainsKey(pieceOfCode)) + { + PerformanceInfo info = _performances[pieceOfCode]; + info.Count++; + info.TotalTime += TimeCounter.Finish(info.Start); + } + } + } + + public static void Reset() + { + _performances.Clear(); + } + + public static string GenerateReport() + { + return GenerateReport(0); + } + + public static string GenerateReport(string mainPieceOfCode) + { + if (_performances.ContainsKey(mainPieceOfCode)) + return GenerateReport(_performances[mainPieceOfCode].TotalTime); + else + return GenerateReport(0); + } + + public static string GenerateReport(double totalTime) + { + StringBuilder sb = new StringBuilder(); + int len = 0; + foreach (PerformanceInfo info in Performances) + len = Math.Max(info.Name.Length, len); + + sb.AppendLine("Name".PadRight(len) + " Count Total Time, ms Avg. Time, ms Percentage, %"); + sb.AppendLine("----------------------------------------------------------------------------------------------"); + foreach (PerformanceInfo info in Performances) + { + sb.Append(info.Name.PadRight(len)); + double p = 0; + double avgt = 0; + if (totalTime != 0) + p = info.TotalTime / totalTime; + if (info.Count > 0) + avgt = info.TotalTime * 1000 / info.Count; + string c = info.Count.ToString("0,0").PadRight(20); + string tt = (info.TotalTime * 1000).ToString("0,0.00").PadRight(20); + string t = avgt.ToString("0.0000").PadRight(20); + string sp = (p * 100).ToString("###").PadRight(20); + sb.AppendFormat(" " + c + tt + t + sp + "\n"); + } + return sb.ToString(); + } + } +} diff -r 3145aadca3d2 -r 0c551e8818e0 External/Aga.Controls/Properties/AssemblyInfo.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/External/Aga.Controls/Properties/AssemblyInfo.cs Sun May 27 15:16:19 2012 +0000 @@ -0,0 +1,15 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System; +using System.Security.Permissions; + +[assembly: ComVisible(false)] +[assembly: CLSCompliant(false)] +[assembly: SecurityPermission(SecurityAction.RequestMinimum, Execution = true)] + +[assembly: AssemblyTitle("Aga.Controls")] +[assembly: AssemblyCopyright("Copyright © Andrey Gliznetsov 2006 - 2009")] +[assembly: AssemblyDescription("http://sourceforge.net/projects/treeviewadv/")] + +[assembly: AssemblyVersion("1.7.0.0")] diff -r 3145aadca3d2 -r 0c551e8818e0 External/Aga.Controls/Properties/Resources.Designer.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/External/Aga.Controls/Properties/Resources.Designer.cs Sun May 27 15:16:19 2012 +0000 @@ -0,0 +1,133 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:2.0.50727.3053 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Aga.Controls.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "2.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Aga.Controls.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + internal static System.Drawing.Bitmap check { + get { + object obj = ResourceManager.GetObject("check", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + internal static byte[] DVSplit { + get { + object obj = ResourceManager.GetObject("DVSplit", resourceCulture); + return ((byte[])(obj)); + } + } + + internal static System.Drawing.Bitmap Folder { + get { + object obj = ResourceManager.GetObject("Folder", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + internal static System.Drawing.Bitmap FolderClosed { + get { + object obj = ResourceManager.GetObject("FolderClosed", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + internal static System.Drawing.Bitmap Leaf { + get { + object obj = ResourceManager.GetObject("Leaf", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + internal static byte[] loading_icon { + get { + object obj = ResourceManager.GetObject("loading_icon", resourceCulture); + return ((byte[])(obj)); + } + } + + internal static System.Drawing.Bitmap minus { + get { + object obj = ResourceManager.GetObject("minus", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + internal static System.Drawing.Bitmap plus { + get { + object obj = ResourceManager.GetObject("plus", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + internal static System.Drawing.Bitmap uncheck { + get { + object obj = ResourceManager.GetObject("uncheck", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + internal static System.Drawing.Bitmap unknown { + get { + object obj = ResourceManager.GetObject("unknown", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + } +} diff -r 3145aadca3d2 -r 0c551e8818e0 External/Aga.Controls/Properties/Resources.resx --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/External/Aga.Controls/Properties/Resources.resx Sun May 27 15:16:19 2012 +0000 @@ -0,0 +1,151 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 + + + + ..\Resources\check.bmp;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\resources\dvsplit.cur;System.Byte[], mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + ..\Resources\Folder.bmp;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\FolderClosed.bmp;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\resources\leaf.bmp;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\loading_icon;System.Byte[], mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + ..\Resources\minus.bmp;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\plus.bmp;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\uncheck.bmp;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\resources\unknown.bmp;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + \ No newline at end of file diff -r 3145aadca3d2 -r 0c551e8818e0 External/Aga.Controls/ResourceHelper.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/External/Aga.Controls/ResourceHelper.cs Sun May 27 15:16:19 2012 +0000 @@ -0,0 +1,48 @@ +using System; +using System.IO; +using System.Reflection; +using System.Windows.Forms; +using System.Collections.Generic; +using System.Text; + +namespace Aga.Controls +{ + public static class ResourceHelper + { + // VSpilt Cursor with Innerline (symbolisize hidden column) + private static Cursor _dVSplitCursor = GetCursor(Properties.Resources.DVSplit); + public static Cursor DVSplitCursor + { + get { return _dVSplitCursor; } + } + + private static GifDecoder _loadingIcon = GetGifDecoder(Properties.Resources.loading_icon); + public static GifDecoder LoadingIcon + { + get { return _loadingIcon; } + } + + /// + /// Help function to convert byte[] from resource into Cursor Type + /// + /// + /// + private static Cursor GetCursor(byte[] data) + { + using (MemoryStream s = new MemoryStream(data)) + return new Cursor(s); + } + + /// + /// Help function to convert byte[] from resource into GifDecoder Type + /// + /// + /// + private static GifDecoder GetGifDecoder(byte[] data) + { + using(MemoryStream ms = new MemoryStream(data)) + return new GifDecoder(ms, true); + } + + } +} diff -r 3145aadca3d2 -r 0c551e8818e0 External/Aga.Controls/Resources/DVSplit.cur Binary file External/Aga.Controls/Resources/DVSplit.cur has changed diff -r 3145aadca3d2 -r 0c551e8818e0 External/Aga.Controls/Resources/Folder.bmp Binary file External/Aga.Controls/Resources/Folder.bmp has changed diff -r 3145aadca3d2 -r 0c551e8818e0 External/Aga.Controls/Resources/FolderClosed.bmp Binary file External/Aga.Controls/Resources/FolderClosed.bmp has changed diff -r 3145aadca3d2 -r 0c551e8818e0 External/Aga.Controls/Resources/Leaf.bmp Binary file External/Aga.Controls/Resources/Leaf.bmp has changed diff -r 3145aadca3d2 -r 0c551e8818e0 External/Aga.Controls/Resources/check.bmp Binary file External/Aga.Controls/Resources/check.bmp has changed diff -r 3145aadca3d2 -r 0c551e8818e0 External/Aga.Controls/Resources/loading_icon Binary file External/Aga.Controls/Resources/loading_icon has changed diff -r 3145aadca3d2 -r 0c551e8818e0 External/Aga.Controls/Resources/minus.bmp Binary file External/Aga.Controls/Resources/minus.bmp has changed diff -r 3145aadca3d2 -r 0c551e8818e0 External/Aga.Controls/Resources/plus.bmp Binary file External/Aga.Controls/Resources/plus.bmp has changed diff -r 3145aadca3d2 -r 0c551e8818e0 External/Aga.Controls/Resources/uncheck.bmp Binary file External/Aga.Controls/Resources/uncheck.bmp has changed diff -r 3145aadca3d2 -r 0c551e8818e0 External/Aga.Controls/Resources/unknown.bmp Binary file External/Aga.Controls/Resources/unknown.bmp has changed diff -r 3145aadca3d2 -r 0c551e8818e0 External/Aga.Controls/StringCollectionEditor.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/External/Aga.Controls/StringCollectionEditor.cs Sun May 27 15:16:19 2012 +0000 @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.ComponentModel.Design; + +namespace Aga.Controls +{ + public class StringCollectionEditor : CollectionEditor + { + public StringCollectionEditor(Type type): base(type) + { + } + + protected override Type CreateCollectionItemType() + { + return typeof(string); + } + + protected override object CreateInstance(Type itemType) + { + return ""; + } + } +} diff -r 3145aadca3d2 -r 0c551e8818e0 External/Aga.Controls/TextHelper.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/External/Aga.Controls/TextHelper.cs Sun May 27 15:16:19 2012 +0000 @@ -0,0 +1,45 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Windows.Forms; +using System.Drawing; + +namespace Aga.Controls +{ + public static class TextHelper + { + public static StringAlignment TranslateAligment(HorizontalAlignment alignment) + { + if (alignment == HorizontalAlignment.Left) + return StringAlignment.Near; + else if (alignment == HorizontalAlignment.Right) + return StringAlignment.Far; + else + return StringAlignment.Center; + } + + public static TextFormatFlags TranslateAligmentToFlag(HorizontalAlignment alignment) + { + if (alignment == HorizontalAlignment.Left) + return TextFormatFlags.Left; + else if (alignment == HorizontalAlignment.Right) + return TextFormatFlags.Right; + else + return TextFormatFlags.HorizontalCenter; + } + + public static TextFormatFlags TranslateTrimmingToFlag(StringTrimming trimming) + { + if (trimming == StringTrimming.EllipsisCharacter) + return TextFormatFlags.EndEllipsis; + else if (trimming == StringTrimming.EllipsisPath) + return TextFormatFlags.PathEllipsis; + if (trimming == StringTrimming.EllipsisWord) + return TextFormatFlags.WordEllipsis; + if (trimming == StringTrimming.Word) + return TextFormatFlags.WordBreak; + else + return TextFormatFlags.Default; + } + } +} diff -r 3145aadca3d2 -r 0c551e8818e0 External/Aga.Controls/Threading/AbortableThreadPool.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/External/Aga.Controls/Threading/AbortableThreadPool.cs Sun May 27 15:16:19 2012 +0000 @@ -0,0 +1,118 @@ +// Stephen Toub +// stoub@microsoft.com + +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading; + +namespace Aga.Controls.Threading +{ + public class AbortableThreadPool + { + private LinkedList _callbacks = new LinkedList(); + private Dictionary _threads = new Dictionary(); + + public WorkItem QueueUserWorkItem(WaitCallback callback) + { + return QueueUserWorkItem(callback, null); + } + + public WorkItem QueueUserWorkItem(WaitCallback callback, object state) + { + if (callback == null) throw new ArgumentNullException("callback"); + + WorkItem item = new WorkItem(callback, state, ExecutionContext.Capture()); + lock (_callbacks) + { + _callbacks.AddLast(item); + } + ThreadPool.QueueUserWorkItem(new WaitCallback(HandleItem)); + return item; + } + + private void HandleItem(object ignored) + { + WorkItem item = null; + try + { + lock (_callbacks) + { + if (_callbacks.Count > 0) + { + item = _callbacks.First.Value; + _callbacks.RemoveFirst(); + } + if (item == null) + return; + _threads.Add(item, Thread.CurrentThread); + + } + ExecutionContext.Run(item.Context, + delegate { item.Callback(item.State); }, null); + } + finally + { + lock (_callbacks) + { + if (item != null) + _threads.Remove(item); + } + } + } + + public bool IsMyThread(Thread thread) + { + lock (_callbacks) + { + foreach (Thread t in _threads.Values) + { + if (t == thread) + return true; + } + return false; + } + } + + public WorkItemStatus Cancel(WorkItem item, bool allowAbort) + { + if (item == null) + throw new ArgumentNullException("item"); + lock (_callbacks) + { + LinkedListNode node = _callbacks.Find(item); + if (node != null) + { + _callbacks.Remove(node); + return WorkItemStatus.Queued; + } + else if (_threads.ContainsKey(item)) + { + if (allowAbort) + { + _threads[item].Abort(); + _threads.Remove(item); + return WorkItemStatus.Aborted; + } + else + return WorkItemStatus.Executing; + } + else + return WorkItemStatus.Completed; + } + } + + public void CancelAll(bool allowAbort) + { + lock (_callbacks) + { + _callbacks.Clear(); + if (allowAbort) + { + foreach (Thread t in _threads.Values) + t.Abort(); + } + } + } + } +} diff -r 3145aadca3d2 -r 0c551e8818e0 External/Aga.Controls/Threading/WorkItem.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/External/Aga.Controls/Threading/WorkItem.cs Sun May 27 15:16:19 2012 +0000 @@ -0,0 +1,45 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading; + +namespace Aga.Controls.Threading +{ + public sealed class WorkItem + { + private WaitCallback _callback; + private object _state; + private ExecutionContext _ctx; + + internal WorkItem(WaitCallback wc, object state, ExecutionContext ctx) + { + _callback = wc; + _state = state; + _ctx = ctx; + } + + internal WaitCallback Callback + { + get + { + return _callback; + } + } + + internal object State + { + get + { + return _state; + } + } + + internal ExecutionContext Context + { + get + { + return _ctx; + } + } + } +} diff -r 3145aadca3d2 -r 0c551e8818e0 External/Aga.Controls/Threading/WorkItemStatus.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/External/Aga.Controls/Threading/WorkItemStatus.cs Sun May 27 15:16:19 2012 +0000 @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Aga.Controls.Threading +{ + public enum WorkItemStatus + { + Completed, + Queued, + Executing, + Aborted + } +} diff -r 3145aadca3d2 -r 0c551e8818e0 External/Aga.Controls/TimeCounter.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/External/Aga.Controls/TimeCounter.cs Sun May 27 15:16:19 2012 +0000 @@ -0,0 +1,59 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Runtime.InteropServices; +using System.Diagnostics.CodeAnalysis; + +namespace Aga.Controls +{ + /// + /// High resolution timer, used to test performance + /// + public static class TimeCounter + { + private static Int64 _start; + + /// + /// Start time counting + /// + public static void Start() + { + _start = 0; + QueryPerformanceCounter(ref _start); + } + + public static Int64 GetStartValue() + { + Int64 t = 0; + QueryPerformanceCounter(ref t); + return t; + } + + /// + /// Finish time counting + /// + /// time in seconds elapsed from Start till Finish + public static double Finish() + { + return Finish(_start); + } + + public static double Finish(Int64 start) + { + Int64 finish = 0; + QueryPerformanceCounter(ref finish); + + Int64 freq = 0; + QueryPerformanceFrequency(ref freq); + return (finish - start) / (double)freq; + } + + [DllImport("Kernel32.dll")] + [return: MarshalAs(UnmanagedType.Bool)] + static extern bool QueryPerformanceCounter(ref Int64 performanceCount); + + [DllImport("Kernel32.dll")] + [return: MarshalAs(UnmanagedType.Bool)] + static extern bool QueryPerformanceFrequency(ref Int64 frequency); + } +} diff -r 3145aadca3d2 -r 0c551e8818e0 External/Aga.Controls/Tree/AutoRowHeightLayout.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/External/Aga.Controls/Tree/AutoRowHeightLayout.cs Sun May 27 15:16:19 2012 +0000 @@ -0,0 +1,151 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Drawing; +using Aga.Controls.Tree.NodeControls; + +namespace Aga.Controls.Tree +{ + public class AutoRowHeightLayout: IRowLayout + { + private DrawContext _measureContext; + private TreeViewAdv _treeView; + private List _rowCache; + + public AutoRowHeightLayout(TreeViewAdv treeView, int rowHeight) + { + _rowCache = new List(); + _treeView = treeView; + PreferredRowHeight = rowHeight; + _measureContext = new DrawContext(); + _measureContext.Graphics = Graphics.FromImage(new Bitmap(1, 1)); + } + + private int _rowHeight; + public int PreferredRowHeight + { + get { return _rowHeight; } + set { _rowHeight = value; } + } + + + public int PageRowCount + { + get + { + if (_treeView.RowCount == 0) + return 0; + else + { + int pageHeight = _treeView.DisplayRectangle.Height - _treeView.ColumnHeaderHeight; + int y = 0; + for (int i = _treeView.RowCount - 1; i >= 0; i--) + { + y += GetRowHeight(i); + if (y > pageHeight) + return Math.Max(0, _treeView.RowCount - 1 - i); + } + return _treeView.RowCount; + } + } + } + + public int CurrentPageSize + { + get + { + if (_treeView.RowCount == 0) + return 0; + else + { + int pageHeight = _treeView.DisplayRectangle.Height - _treeView.ColumnHeaderHeight; + int y = 0; + for (int i = _treeView.FirstVisibleRow; i < _treeView.RowCount; i++) + { + y += GetRowHeight(i); + if (y > pageHeight) + return Math.Max(0, i - _treeView.FirstVisibleRow); + } + return Math.Max(0, _treeView.RowCount - _treeView.FirstVisibleRow); + } + } + } + + public Rectangle GetRowBounds(int rowNo) + { + if (rowNo >= _rowCache.Count) + { + int count = _rowCache.Count; + int y = count > 0 ? _rowCache[count - 1].Bottom : 0; + for (int i = count; i <= rowNo; i++) + { + int height = GetRowHeight(i); + _rowCache.Add(new Rectangle(0, y, 0, height)); + y += height; + } + if (rowNo < _rowCache.Count - 1) + return Rectangle.Empty; + } + if (rowNo >= 0 && rowNo < _rowCache.Count) + return _rowCache[rowNo]; + else + return Rectangle.Empty; + } + + private int GetRowHeight(int rowNo) + { + if (rowNo < _treeView.RowMap.Count) + { + TreeNodeAdv node = _treeView.RowMap[rowNo]; + if (node.Height == null) + { + int res = 0; + _measureContext.Font = _treeView.Font; + foreach (NodeControl nc in _treeView.NodeControls) + { + int h = nc.GetActualSize(node, _measureContext).Height; + if (h > res) + res = h; + } + node.Height = res; + } + return node.Height.Value; + } + else + return 0; + } + + public int GetRowAt(Point point) + { + int py = point.Y - _treeView.ColumnHeaderHeight; + int y = 0; + for (int i = _treeView.FirstVisibleRow; i < _treeView.RowCount; i++) + { + int h = GetRowHeight(i); + if (py >= y && py < y + h) + return i; + else + y += h; + } + return -1; + } + + public int GetFirstRow(int lastPageRow) + { + int pageHeight = _treeView.DisplayRectangle.Height - _treeView.ColumnHeaderHeight; + int y = 0; + for (int i = lastPageRow; i >= 0; i--) + { + y += GetRowHeight(i); + if (y > pageHeight) + return Math.Max(0, i + 1); + } + return 0; + } + + public void ClearCache() + { + _rowCache.Clear(); + } + } +} diff -r 3145aadca3d2 -r 0c551e8818e0 External/Aga.Controls/Tree/ClassDiagram.cd --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/External/Aga.Controls/Tree/ClassDiagram.cd Sun May 27 15:16:19 2012 +0000 @@ -0,0 +1,84 @@ + + + + + + + Tree\TreeModel.cs + AAAkgAAAAAAQAGQAAAAAEAAAEAACQAAAUAAAAAAAAQE= + + + + + + + + + + + + Tree\TreePath.cs + GABAAAAAAAACAAAAAAIAAAAAAAAACAAAAAAAAAAAAAA= + + + + + + + + + + + Tree\Node.cs + AAAgABAAgCAAAAAAAgAEVAAQAAAQAAAIAAsgCAAAAAA= + + + + + + + + + + Tree\Node.cs + + + + + + + + Tree\NodeControls\NodeControl.cs + AAAAAAAAgAAAgsIAAAhAQAAwAAAAEAAAAEAIAAAAAAA= + + + + + + + + Tree\ITreeModel.cs + AAAEAAAAAAAAAEQAAAAAEAAAEAAAQAAAAAAAAAAAAAA= + + + + + + Tree\IToolTipProvider.cs + AAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAA= + + + \ No newline at end of file diff -r 3145aadca3d2 -r 0c551e8818e0 External/Aga.Controls/Tree/ColumnCollection.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/External/Aga.Controls/Tree/ColumnCollection.cs Sun May 27 15:16:19 2012 +0000 @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Collections.ObjectModel; + +namespace Aga.Controls.Tree +{ + /*internal class ColumnCollection: Collection + { + public int TotalWidth + { + get + { + int res = 0; + foreach (Column c in Items) + res += c.Width; + return res; + } + } + }*/ +} diff -r 3145aadca3d2 -r 0c551e8818e0 External/Aga.Controls/Tree/DrawContext.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/External/Aga.Controls/Tree/DrawContext.cs Sun May 27 15:16:19 2012 +0000 @@ -0,0 +1,60 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Drawing; +using Aga.Controls.Tree.NodeControls; + +namespace Aga.Controls.Tree +{ + public struct DrawContext + { + private Graphics _graphics; + public Graphics Graphics + { + get { return _graphics; } + set { _graphics = value; } + } + + private Rectangle _bounds; + public Rectangle Bounds + { + get { return _bounds; } + set { _bounds = value; } + } + + private Font _font; + public Font Font + { + get { return _font; } + set { _font = value; } + } + + private DrawSelectionMode _drawSelection; + public DrawSelectionMode DrawSelection + { + get { return _drawSelection; } + set { _drawSelection = value; } + } + + private bool _drawFocus; + public bool DrawFocus + { + get { return _drawFocus; } + set { _drawFocus = value; } + } + + private NodeControl _currentEditorOwner; + public NodeControl CurrentEditorOwner + { + get { return _currentEditorOwner; } + set { _currentEditorOwner = value; } + } + + private bool _enabled; + public bool Enabled + { + get { return _enabled; } + set { _enabled = value; } + } + } +} diff -r 3145aadca3d2 -r 0c551e8818e0 External/Aga.Controls/Tree/DropNodeValidatingEventArgs.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/External/Aga.Controls/Tree/DropNodeValidatingEventArgs.cs Sun May 27 15:16:19 2012 +0000 @@ -0,0 +1,28 @@ +using System; +using System.Drawing; + +namespace Aga.Controls.Tree +{ + public class DropNodeValidatingEventArgs: EventArgs + { + Point _point; + TreeNodeAdv _node; + + public DropNodeValidatingEventArgs(Point point, TreeNodeAdv node) + { + _point = point; + _node = node; + } + + public Point Point + { + get { return _point; } + } + + public TreeNodeAdv Node + { + get { return _node; } + set { _node = value; } + } + } +} diff -r 3145aadca3d2 -r 0c551e8818e0 External/Aga.Controls/Tree/DropPosition.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/External/Aga.Controls/Tree/DropPosition.cs Sun May 27 15:16:19 2012 +0000 @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Aga.Controls.Tree +{ + public struct DropPosition + { + private TreeNodeAdv _node; + public TreeNodeAdv Node + { + get { return _node; } + set { _node = value; } + } + + private NodePosition _position; + public NodePosition Position + { + get { return _position; } + set { _position = value; } + } + } +} diff -r 3145aadca3d2 -r 0c551e8818e0 External/Aga.Controls/Tree/EditorContext.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/External/Aga.Controls/Tree/EditorContext.cs Sun May 27 15:16:19 2012 +0000 @@ -0,0 +1,47 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Windows.Forms; +using System.Drawing; +using Aga.Controls.Tree.NodeControls; + +namespace Aga.Controls.Tree +{ + public struct EditorContext + { + private TreeNodeAdv _currentNode; + public TreeNodeAdv CurrentNode + { + get { return _currentNode; } + set { _currentNode = value; } + } + + private Control _editor; + public Control Editor + { + get { return _editor; } + set { _editor = value; } + } + + private NodeControl _owner; + public NodeControl Owner + { + get { return _owner; } + set { _owner = value; } + } + + private Rectangle _bounds; + public Rectangle Bounds + { + get { return _bounds; } + set { _bounds = value; } + } + + private DrawContext _drawContext; + public DrawContext DrawContext + { + get { return _drawContext; } + set { _drawContext = value; } + } + } +} diff -r 3145aadca3d2 -r 0c551e8818e0 External/Aga.Controls/Tree/Enums.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/External/Aga.Controls/Tree/Enums.cs Sun May 27 15:16:19 2012 +0000 @@ -0,0 +1,65 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Aga.Controls.Tree +{ + public enum DrawSelectionMode + { + None, Active, Inactive, FullRowSelect + } + + public enum TreeSelectionMode + { + Single, Multi, MultiSameParent + } + + public enum NodePosition + { + Inside, Before, After + } + + public enum VerticalAlignment + { + Top, Bottom, Center + } + + public enum IncrementalSearchMode + { + None, Standard, Continuous + } + + [Flags] + public enum GridLineStyle + { + None = 0, + Horizontal = 1, + Vertical = 2, + HorizontalAndVertical = 3 + } + + public enum ImageScaleMode + { + /// + /// Don't scale + /// + Clip, + /// + /// Scales image to fit the display rectangle, aspect ratio is not fixed. + /// + Fit, + /// + /// Scales image down if it is larger than display rectangle, taking aspect ratio into account + /// + ScaleDown, + /// + /// Scales image up if it is smaller than display rectangle, taking aspect ratio into account + /// + ScaleUp, + /// + /// Scales image to match the display rectangle, taking aspect ratio into account + /// + AlwaysScale, + + } +} diff -r 3145aadca3d2 -r 0c551e8818e0 External/Aga.Controls/Tree/FixedRowHeightLayout.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/External/Aga.Controls/Tree/FixedRowHeightLayout.cs Sun May 27 15:16:19 2012 +0000 @@ -0,0 +1,61 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Drawing; + +namespace Aga.Controls.Tree +{ + internal class FixedRowHeightLayout : IRowLayout + { + private TreeViewAdv _treeView; + + public FixedRowHeightLayout(TreeViewAdv treeView, int rowHeight) + { + _treeView = treeView; + PreferredRowHeight = rowHeight; + } + + private int _rowHeight; + public int PreferredRowHeight + { + get { return _rowHeight; } + set { _rowHeight = value; } + } + + public Rectangle GetRowBounds(int rowNo) + { + return new Rectangle(0, rowNo * _rowHeight, 0, _rowHeight); + } + + public int PageRowCount + { + get + { + return Math.Max((_treeView.DisplayRectangle.Height - _treeView.ColumnHeaderHeight) / _rowHeight, 0); + } + } + + public int CurrentPageSize + { + get + { + return PageRowCount; + } + } + + public int GetRowAt(Point point) + { + point = new Point(point.X, point.Y + (_treeView.FirstVisibleRow * _rowHeight) - _treeView.ColumnHeaderHeight); + return point.Y / _rowHeight; + } + + public int GetFirstRow(int lastPageRow) + { + return Math.Max(0, lastPageRow - PageRowCount + 1); + } + + public void ClearCache() + { + } + } +} diff -r 3145aadca3d2 -r 0c551e8818e0 External/Aga.Controls/Tree/IRowLayout.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/External/Aga.Controls/Tree/IRowLayout.cs Sun May 27 15:16:19 2012 +0000 @@ -0,0 +1,34 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Drawing; + +namespace Aga.Controls.Tree +{ + internal interface IRowLayout + { + int PreferredRowHeight + { + get; + set; + } + + int PageRowCount + { + get; + } + + int CurrentPageSize + { + get; + } + + Rectangle GetRowBounds(int rowNo); + + int GetRowAt(Point point); + + int GetFirstRow(int lastPageRow); + + void ClearCache(); + } +} diff -r 3145aadca3d2 -r 0c551e8818e0 External/Aga.Controls/Tree/IToolTipProvider.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/External/Aga.Controls/Tree/IToolTipProvider.cs Sun May 27 15:16:19 2012 +0000 @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Aga.Controls.Tree.NodeControls; + +namespace Aga.Controls.Tree +{ + public interface IToolTipProvider + { + string GetToolTip(TreeNodeAdv node, NodeControl nodeControl); + } +} diff -r 3145aadca3d2 -r 0c551e8818e0 External/Aga.Controls/Tree/ITreeModel.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/External/Aga.Controls/Tree/ITreeModel.cs Sun May 27 15:16:19 2012 +0000 @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Collections; + +namespace Aga.Controls.Tree +{ + public interface ITreeModel + { + IEnumerable GetChildren(TreePath treePath); + bool IsLeaf(TreePath treePath); + + event EventHandler NodesChanged; + event EventHandler NodesInserted; + event EventHandler NodesRemoved; + event EventHandler StructureChanged; + } +} diff -r 3145aadca3d2 -r 0c551e8818e0 External/Aga.Controls/Tree/IncrementalSearch.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/External/Aga.Controls/Tree/IncrementalSearch.cs Sun May 27 15:16:19 2012 +0000 @@ -0,0 +1,144 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Aga.Controls.Tree.NodeControls; +using System.ComponentModel; +using System.Drawing; +using System.Windows.Forms; + +namespace Aga.Controls.Tree +{ + internal class IncrementalSearch + { + private const int SearchTimeout = 300; //end of incremental search timeot in msec + + private TreeViewAdv _tree; + private TreeNodeAdv _currentNode; + private string _searchString = ""; + private DateTime _lastKeyPressed = DateTime.Now; + + public IncrementalSearch(TreeViewAdv tree) + { + _tree = tree; + } + + public void Search(Char value) + { + if (!Char.IsControl(value)) + { + Char ch = Char.ToLowerInvariant(value); + DateTime dt = DateTime.Now; + TimeSpan ts = dt - _lastKeyPressed; + _lastKeyPressed = dt; + if (ts.TotalMilliseconds < SearchTimeout) + { + if (_searchString == value.ToString()) + FirstCharSearch(ch); + else + ContinuousSearch(ch); + } + else + { + FirstCharSearch(ch); + } + } + } + + private void ContinuousSearch(Char value) + { + if (value == ' ' && String.IsNullOrEmpty(_searchString)) + return; //Ingnore leading space + + _searchString += value; + DoContinuousSearch(); + } + + private void FirstCharSearch(Char value) + { + if (value == ' ') + return; + + _searchString = value.ToString(); + TreeNodeAdv node = null; + if (_tree.SelectedNode != null) + node = _tree.SelectedNode.NextVisibleNode; + if (node == null) + node = _tree.Root.NextVisibleNode; + + if (node != null) + foreach (string label in IterateNodeLabels(node)) + { + if (label.StartsWith(_searchString)) + { + _tree.SelectedNode = _currentNode; + return; + } + } + } + + public virtual void EndSearch() + { + _currentNode = null; + _searchString = ""; + } + + protected IEnumerable IterateNodeLabels(TreeNodeAdv start) + { + _currentNode = start; + while(_currentNode != null) + { + foreach (string label in GetNodeLabels(_currentNode)) + yield return label; + + _currentNode = _currentNode.NextVisibleNode; + if (_currentNode == null) + _currentNode = _tree.Root; + + if (start == _currentNode) + break; + } + } + + private IEnumerable GetNodeLabels(TreeNodeAdv node) + { + foreach (NodeControl nc in _tree.NodeControls) + { + BindableControl bc = nc as BindableControl; + if (bc != null && bc.IncrementalSearchEnabled) + { + object obj = bc.GetValue(node); + if (obj != null) + yield return obj.ToString().ToLowerInvariant(); + } + } + } + + private bool DoContinuousSearch() + { + bool found = false; + if (!String.IsNullOrEmpty(_searchString)) + { + TreeNodeAdv node = null; + if (_tree.SelectedNode != null) + node = _tree.SelectedNode; + if (node == null) + node = _tree.Root.NextVisibleNode; + + if (!String.IsNullOrEmpty(_searchString)) + { + foreach (string label in IterateNodeLabels(node)) + { + if (label.StartsWith(_searchString)) + { + found = true; + _tree.SelectedNode = _currentNode; + break; + } + } + } + } + return found; + } + + } +} diff -r 3145aadca3d2 -r 0c551e8818e0 External/Aga.Controls/Tree/Input/ClickColumnState.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/External/Aga.Controls/Tree/Input/ClickColumnState.cs Sun May 27 15:16:19 2012 +0000 @@ -0,0 +1,45 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Windows.Forms; +using System.Drawing; + +namespace Aga.Controls.Tree +{ + internal class ClickColumnState : ColumnState + { + private Point _location; + + public ClickColumnState(TreeViewAdv tree, TreeColumn column, Point location) + : base(tree, column) + { + _location = location; + } + + public override void KeyDown(KeyEventArgs args) + { + } + + public override void MouseDown(TreeNodeAdvMouseEventArgs args) + { + } + + public override bool MouseMove(MouseEventArgs args) + { + if (TreeViewAdv.Dist(_location, args.Location) > TreeViewAdv.ItemDragSensivity + && Tree.AllowColumnReorder) + { + Tree.Input = new ReorderColumnState(Tree, Column, args.Location); + Tree.UpdateView(); + } + return true; + } + + public override void MouseUp(TreeNodeAdvMouseEventArgs args) + { + Tree.ChangeInput(); + Tree.UpdateView(); + Tree.OnColumnClicked(Column); + } + } +} diff -r 3145aadca3d2 -r 0c551e8818e0 External/Aga.Controls/Tree/Input/ColumnState.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/External/Aga.Controls/Tree/Input/ColumnState.cs Sun May 27 15:16:19 2012 +0000 @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Aga.Controls.Tree +{ + internal abstract class ColumnState : InputState + { + private TreeColumn _column; + public TreeColumn Column + { + get { return _column; } + } + + public ColumnState(TreeViewAdv tree, TreeColumn column) + : base(tree) + { + _column = column; + } + } +} diff -r 3145aadca3d2 -r 0c551e8818e0 External/Aga.Controls/Tree/Input/InputState.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/External/Aga.Controls/Tree/Input/InputState.cs Sun May 27 15:16:19 2012 +0000 @@ -0,0 +1,37 @@ +using System; +using System.Windows.Forms; +namespace Aga.Controls.Tree +{ + internal abstract class InputState + { + private TreeViewAdv _tree; + + public TreeViewAdv Tree + { + get { return _tree; } + } + + public InputState(TreeViewAdv tree) + { + _tree = tree; + } + + public abstract void KeyDown(System.Windows.Forms.KeyEventArgs args); + public abstract void MouseDown(TreeNodeAdvMouseEventArgs args); + public abstract void MouseUp(TreeNodeAdvMouseEventArgs args); + + /// + /// handle OnMouseMove event + /// + /// + /// true if event was handled and should be dispatched + public virtual bool MouseMove(MouseEventArgs args) + { + return false; + } + + public virtual void MouseDoubleClick(TreeNodeAdvMouseEventArgs args) + { + } + } +} diff -r 3145aadca3d2 -r 0c551e8818e0 External/Aga.Controls/Tree/Input/InputWithControl.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/External/Aga.Controls/Tree/Input/InputWithControl.cs Sun May 27 15:16:19 2012 +0000 @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Aga.Controls.Tree +{ + internal class InputWithControl: NormalInputState + { + public InputWithControl(TreeViewAdv tree): base(tree) + { + } + + protected override void DoMouseOperation(TreeNodeAdvMouseEventArgs args) + { + if (Tree.SelectionMode == TreeSelectionMode.Single) + { + base.DoMouseOperation(args); + } + else if (CanSelect(args.Node)) + { + args.Node.IsSelected = !args.Node.IsSelected; + Tree.SelectionStart = args.Node; + } + } + + protected override void MouseDownAtEmptySpace(TreeNodeAdvMouseEventArgs args) + { + } + } +} diff -r 3145aadca3d2 -r 0c551e8818e0 External/Aga.Controls/Tree/Input/InputWithShift.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/External/Aga.Controls/Tree/Input/InputWithShift.cs Sun May 27 15:16:19 2012 +0000 @@ -0,0 +1,69 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Aga.Controls.Tree +{ + internal class InputWithShift: NormalInputState + { + public InputWithShift(TreeViewAdv tree): base(tree) + { + } + + protected override void FocusRow(TreeNodeAdv node) + { + Tree.SuspendSelectionEvent = true; + try + { + if (Tree.SelectionMode == TreeSelectionMode.Single || Tree.SelectionStart == null) + base.FocusRow(node); + else if (CanSelect(node)) + { + SelectAllFromStart(node); + Tree.CurrentNode = node; + Tree.ScrollTo(node); + } + } + finally + { + Tree.SuspendSelectionEvent = false; + } + } + + protected override void DoMouseOperation(TreeNodeAdvMouseEventArgs args) + { + if (Tree.SelectionMode == TreeSelectionMode.Single || Tree.SelectionStart == null) + { + base.DoMouseOperation(args); + } + else if (CanSelect(args.Node)) + { + Tree.SuspendSelectionEvent = true; + try + { + SelectAllFromStart(args.Node); + } + finally + { + Tree.SuspendSelectionEvent = false; + } + } + } + + protected override void MouseDownAtEmptySpace(TreeNodeAdvMouseEventArgs args) + { + } + + private void SelectAllFromStart(TreeNodeAdv node) + { + Tree.ClearSelectionInternal(); + int a = node.Row; + int b = Tree.SelectionStart.Row; + for (int i = Math.Min(a, b); i <= Math.Max(a, b); i++) + { + if (Tree.SelectionMode == TreeSelectionMode.Multi || Tree.RowMap[i].Parent == node.Parent) + Tree.RowMap[i].IsSelected = true; + } + } + } +} diff -r 3145aadca3d2 -r 0c551e8818e0 External/Aga.Controls/Tree/Input/NormalInputState.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/External/Aga.Controls/Tree/Input/NormalInputState.cs Sun May 27 15:16:19 2012 +0000 @@ -0,0 +1,202 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Windows.Forms; + +namespace Aga.Controls.Tree +{ + internal class NormalInputState : InputState + { + private bool _mouseDownFlag = false; + + public NormalInputState(TreeViewAdv tree) : base(tree) + { + } + + public override void KeyDown(KeyEventArgs args) + { + if (Tree.CurrentNode == null && Tree.Root.Nodes.Count > 0) + Tree.CurrentNode = Tree.Root.Nodes[0]; + + if (Tree.CurrentNode != null) + { + switch (args.KeyCode) + { + case Keys.Right: + if (!Tree.CurrentNode.IsExpanded) + Tree.CurrentNode.IsExpanded = true; + else if (Tree.CurrentNode.Nodes.Count > 0) + Tree.SelectedNode = Tree.CurrentNode.Nodes[0]; + args.Handled = true; + break; + case Keys.Left: + if (Tree.CurrentNode.IsExpanded) + Tree.CurrentNode.IsExpanded = false; + else if (Tree.CurrentNode.Parent != Tree.Root) + Tree.SelectedNode = Tree.CurrentNode.Parent; + args.Handled = true; + break; + case Keys.Down: + NavigateForward(1); + args.Handled = true; + break; + case Keys.Up: + NavigateBackward(1); + args.Handled = true; + break; + case Keys.PageDown: + NavigateForward(Math.Max(1, Tree.CurrentPageSize - 1)); + args.Handled = true; + break; + case Keys.PageUp: + NavigateBackward(Math.Max(1, Tree.CurrentPageSize - 1)); + args.Handled = true; + break; + case Keys.Home: + if (Tree.RowMap.Count > 0) + FocusRow(Tree.RowMap[0]); + args.Handled = true; + break; + case Keys.End: + if (Tree.RowMap.Count > 0) + FocusRow(Tree.RowMap[Tree.RowMap.Count-1]); + args.Handled = true; + break; + case Keys.Subtract: + Tree.CurrentNode.Collapse(); + args.Handled = true; + args.SuppressKeyPress = true; + break; + case Keys.Add: + Tree.CurrentNode.Expand(); + args.Handled = true; + args.SuppressKeyPress = true; + break; + case Keys.Multiply: + Tree.CurrentNode.ExpandAll(); + args.Handled = true; + args.SuppressKeyPress = true; + break; + case Keys.A: + if (args.Modifiers == Keys.Control) + Tree.SelectAllNodes(); + break; + } + } + } + + public override void MouseDown(TreeNodeAdvMouseEventArgs args) + { + if (args.Node != null) + { + Tree.ItemDragMode = true; + Tree.ItemDragStart = args.Location; + + if (args.Button == MouseButtons.Left || args.Button == MouseButtons.Right) + { + Tree.BeginUpdate(); + try + { + Tree.CurrentNode = args.Node; + if (args.Node.IsSelected) + _mouseDownFlag = true; + else + { + _mouseDownFlag = false; + DoMouseOperation(args); + } + } + finally + { + Tree.EndUpdate(); + } + } + + } + else + { + Tree.ItemDragMode = false; + MouseDownAtEmptySpace(args); + } + } + + public override void MouseUp(TreeNodeAdvMouseEventArgs args) + { + Tree.ItemDragMode = false; + if (_mouseDownFlag && args.Node != null) + { + if (args.Button == MouseButtons.Left) + DoMouseOperation(args); + else if (args.Button == MouseButtons.Right) + Tree.CurrentNode = args.Node; + } + _mouseDownFlag = false; + } + + + private void NavigateBackward(int n) + { + int row = Math.Max(Tree.CurrentNode.Row - n, 0); + if (row != Tree.CurrentNode.Row) + FocusRow(Tree.RowMap[row]); + } + + private void NavigateForward(int n) + { + int row = Math.Min(Tree.CurrentNode.Row + n, Tree.RowCount - 1); + if (row != Tree.CurrentNode.Row) + FocusRow(Tree.RowMap[row]); + } + + protected virtual void MouseDownAtEmptySpace(TreeNodeAdvMouseEventArgs args) + { + Tree.ClearSelection(); + } + + protected virtual void FocusRow(TreeNodeAdv node) + { + Tree.SuspendSelectionEvent = true; + try + { + Tree.ClearSelectionInternal(); + Tree.CurrentNode = node; + Tree.SelectionStart = node; + node.IsSelected = true; + Tree.ScrollTo(node); + } + finally + { + Tree.SuspendSelectionEvent = false; + } + } + + protected bool CanSelect(TreeNodeAdv node) + { + if (Tree.SelectionMode == TreeSelectionMode.MultiSameParent) + { + return (Tree.SelectionStart == null || node.Parent == Tree.SelectionStart.Parent); + } + else + return true; + } + + protected virtual void DoMouseOperation(TreeNodeAdvMouseEventArgs args) + { + if (Tree.SelectedNodes.Count == 1 && args.Node != null && args.Node.IsSelected) + return; + + Tree.SuspendSelectionEvent = true; + try + { + Tree.ClearSelectionInternal(); + if (args.Node != null) + args.Node.IsSelected = true; + Tree.SelectionStart = args.Node; + } + finally + { + Tree.SuspendSelectionEvent = false; + } + } + } +} diff -r 3145aadca3d2 -r 0c551e8818e0 External/Aga.Controls/Tree/Input/ReorderColumnState.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/External/Aga.Controls/Tree/Input/ReorderColumnState.cs Sun May 27 15:16:19 2012 +0000 @@ -0,0 +1,101 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Drawing; +using System.Windows.Forms; + +namespace Aga.Controls.Tree +{ + internal class ReorderColumnState : ColumnState + { + #region Properties + + private Point _location; + public Point Location + { + get { return _location; } + } + + private Bitmap _ghostImage; + public Bitmap GhostImage + { + get { return _ghostImage; } + } + + private TreeColumn _dropColumn; + public TreeColumn DropColumn + { + get { return _dropColumn; } + } + + private int _dragOffset; + public int DragOffset + { + get { return _dragOffset; } + } + + #endregion + + public ReorderColumnState(TreeViewAdv tree, TreeColumn column, Point initialMouseLocation) + : base(tree, column) + { + _location = new Point(initialMouseLocation.X + Tree.OffsetX, 0); + _dragOffset = tree.GetColumnX(column) - initialMouseLocation.X; + _ghostImage = column.CreateGhostImage(new Rectangle(0, 0, column.Width, tree.ColumnHeaderHeight), tree.Font); + } + + public override void KeyDown(KeyEventArgs args) + { + args.Handled = true; + if (args.KeyCode == Keys.Escape) + FinishResize(); + } + + public override void MouseDown(TreeNodeAdvMouseEventArgs args) + { + } + + public override void MouseUp(TreeNodeAdvMouseEventArgs args) + { + FinishResize(); + } + + public override bool MouseMove(MouseEventArgs args) + { + _dropColumn = null; + _location = new Point(args.X + Tree.OffsetX, 0); + int x = 0; + foreach (TreeColumn c in Tree.Columns) + { + if (c.IsVisible) + { + if (_location.X < x + c.Width / 2) + { + _dropColumn = c; + break; + } + x += c.Width; + } + } + Tree.UpdateHeaders(); + return true; + } + + private void FinishResize() + { + Tree.ChangeInput(); + if (Column == DropColumn) + Tree.UpdateView(); + else + { + Tree.Columns.Remove(Column); + if (DropColumn == null) + Tree.Columns.Add(Column); + else + Tree.Columns.Insert(Tree.Columns.IndexOf(DropColumn), Column); + + Tree.OnColumnReordered(Column); + } + } + } +} \ No newline at end of file diff -r 3145aadca3d2 -r 0c551e8818e0 External/Aga.Controls/Tree/Input/ResizeColumnState.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/External/Aga.Controls/Tree/Input/ResizeColumnState.cs Sun May 27 15:16:19 2012 +0000 @@ -0,0 +1,57 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Windows.Forms; +using System.Security.Permissions; +using System.Drawing; + +namespace Aga.Controls.Tree +{ + internal class ResizeColumnState: ColumnState + { + private Point _initLocation; + private int _initWidth; + + public ResizeColumnState(TreeViewAdv tree, TreeColumn column, Point p) + : base(tree, column) + { + _initLocation = p; + _initWidth = column.Width; + } + + public override void KeyDown(KeyEventArgs args) + { + args.Handled = true; + if (args.KeyCode == Keys.Escape) + FinishResize(); + } + + public override void MouseDown(TreeNodeAdvMouseEventArgs args) + { + } + + public override void MouseUp(TreeNodeAdvMouseEventArgs args) + { + FinishResize(); + } + + private void FinishResize() + { + Tree.ChangeInput(); + Tree.FullUpdate(); + Tree.OnColumnWidthChanged(Column); + } + + public override bool MouseMove(MouseEventArgs args) + { + Column.Width = _initWidth + args.Location.X - _initLocation.X; + Tree.UpdateView(); + return true; + } + + public override void MouseDoubleClick(TreeNodeAdvMouseEventArgs args) + { + Tree.AutoSizeColumn(Column); + } + } +} diff -r 3145aadca3d2 -r 0c551e8818e0 External/Aga.Controls/Tree/ListModel.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/External/Aga.Controls/Tree/ListModel.cs Sun May 27 15:16:19 2012 +0000 @@ -0,0 +1,56 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Collections; + +namespace Aga.Controls.Tree +{ + public class ListModel : TreeModelBase + { + private IList _list; + + public int Count + { + get { return _list.Count; } + } + + public ListModel() + { + _list = new List(); + } + + public ListModel(IList list) + { + _list = list; + } + + public override IEnumerable GetChildren(TreePath treePath) + { + return _list; + } + + public override bool IsLeaf(TreePath treePath) + { + return true; + } + + public void AddRange(IEnumerable items) + { + foreach (object obj in items) + _list.Add(obj); + OnStructureChanged(new TreePathEventArgs(TreePath.Empty)); + } + + public void Add(object item) + { + _list.Add(item); + OnNodesInserted(new TreeModelEventArgs(TreePath.Empty, new int[] { _list.Count - 1 }, new object[] { item })); + } + + public void Clear() + { + _list.Clear(); + OnStructureChanged(new TreePathEventArgs(TreePath.Empty)); + } + } +} diff -r 3145aadca3d2 -r 0c551e8818e0 External/Aga.Controls/Tree/NativeMethods.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/External/Aga.Controls/Tree/NativeMethods.cs Sun May 27 15:16:19 2012 +0000 @@ -0,0 +1,74 @@ +using System; +using System.Drawing; +using System.Runtime.InteropServices; + + +namespace Aga.Controls.Tree +{ + internal static class NativeMethods + { + public const int DCX_WINDOW = 0x01; + public const int DCX_CACHE = 0x02; + public const int DCX_NORESETATTRS = 0x04; + public const int DCX_CLIPCHILDREN = 0x08; + public const int DCX_CLIPSIBLINGS = 0x10; + public const int DCX_PARENTCLIP = 0x20; + public const int DCX_EXCLUDERGN = 0x40; + public const int DCX_INTERSECTRGN = 0x80; + public const int DCX_EXCLUDEUPDATE = 0x100; + public const int DCX_INTERSECTUPDATE = 0x200; + public const int DCX_LOCKWINDOWUPDATE = 0x400; + public const int DCX_VALIDATE = 0x200000; + + public const int WM_THEMECHANGED = 0x031A; + public const int WM_NCPAINT = 0x85; + public const int WM_NCCALCSIZE = 0x83; + + public const int WS_BORDER = 0x800000; + public const int WS_EX_CLIENTEDGE = 0x200; + + public const int WVR_HREDRAW = 0x100; + public const int WVR_VREDRAW = 0x200; + public const int WVR_REDRAW = (WVR_HREDRAW | WVR_VREDRAW); + + [StructLayout(LayoutKind.Sequential)] + public struct NCCALCSIZE_PARAMS + { + public RECT rgrc0, rgrc1, rgrc2; + public IntPtr lppos; + } + + [StructLayout(LayoutKind.Sequential)] + public struct RECT + { + public int Left; + public int Top; + public int Right; + public int Bottom; + + public static RECT FromRectangle(Rectangle rectangle) + { + RECT result = new RECT(); + result.Left = rectangle.Left; + result.Top = rectangle.Top; + result.Right = rectangle.Right; + result.Bottom = rectangle.Bottom; + return result; + } + + public Rectangle ToRectangle() + { + return new Rectangle(Left, Top, Right - Left, Bottom - Top); + } + } + + [DllImport("user32.dll", SetLastError = true)] + public static extern IntPtr GetDCEx(IntPtr hWnd, IntPtr hrgnClip, int flags); + + [DllImport("user32.dll")] + public static extern int ReleaseDC(IntPtr hWnd, IntPtr hDC); + + [DllImport("user32.dll")] + public static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect); + } +} diff -r 3145aadca3d2 -r 0c551e8818e0 External/Aga.Controls/Tree/Node.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/External/Aga.Controls/Tree/Node.cs Sun May 27 15:16:19 2012 +0000 @@ -0,0 +1,257 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Collections.ObjectModel; +using System.Windows.Forms; +using System.Drawing; + +namespace Aga.Controls.Tree +{ + public class Node + { + #region NodeCollection + + private class NodeCollection : Collection + { + private Node _owner; + + public NodeCollection(Node owner) + { + _owner = owner; + } + + protected override void ClearItems() + { + while (this.Count != 0) + this.RemoveAt(this.Count - 1); + } + + protected override void InsertItem(int index, Node item) + { + if (item == null) + throw new ArgumentNullException("item"); + + if (item.Parent != _owner) + { + if (item.Parent != null) + item.Parent.Nodes.Remove(item); + item._parent = _owner; + item._index = index; + for (int i = index; i < Count; i++) + this[i]._index++; + base.InsertItem(index, item); + + TreeModel model = _owner.FindModel(); + if (model != null) + model.OnNodeInserted(_owner, index, item); + } + } + + protected override void RemoveItem(int index) + { + Node item = this[index]; + item._parent = null; + item._index = -1; + for (int i = index + 1; i < Count; i++) + this[i]._index--; + base.RemoveItem(index); + + TreeModel model = _owner.FindModel(); + if (model != null) + model.OnNodeRemoved(_owner, index, item); + } + + protected override void SetItem(int index, Node item) + { + if (item == null) + throw new ArgumentNullException("item"); + + RemoveAt(index); + InsertItem(index, item); + } + } + + #endregion + + #region Properties + + private TreeModel _model; + internal TreeModel Model + { + get { return _model; } + set { _model = value; } + } + + private NodeCollection _nodes; + public Collection Nodes + { + get { return _nodes; } + } + + private Node _parent; + public Node Parent + { + get { return _parent; } + set + { + if (value != _parent) + { + if (_parent != null) + _parent.Nodes.Remove(this); + + if (value != null) + value.Nodes.Add(this); + } + } + } + + private int _index = -1; + public int Index + { + get + { + return _index; + } + } + + public Node PreviousNode + { + get + { + int index = Index; + if (index > 0) + return _parent.Nodes[index - 1]; + else + return null; + } + } + + public Node NextNode + { + get + { + int index = Index; + if (index >= 0 && index < _parent.Nodes.Count - 1) + return _parent.Nodes[index + 1]; + else + return null; + } + } + + private string _text; + public virtual string Text + { + get { return _text; } + set + { + if (_text != value) + { + _text = value; + NotifyModel(); + } + } + } + + private CheckState _checkState; + public virtual CheckState CheckState + { + get { return _checkState; } + set + { + if (_checkState != value) + { + _checkState = value; + NotifyModel(); + } + } + } + + private Image _image; + public Image Image + { + get { return _image; } + set + { + if (_image != value) + { + _image = value; + NotifyModel(); + } + } + } + + private object _tag; + public object Tag + { + get { return _tag; } + set { _tag = value; } + } + + public bool IsChecked + { + get + { + return CheckState != CheckState.Unchecked; + } + set + { + if (value) + CheckState = CheckState.Checked; + else + CheckState = CheckState.Unchecked; + } + } + + public virtual bool IsLeaf + { + get + { + return false; + } + } + + #endregion + + public Node() + : this(string.Empty) + { + } + + public Node(string text) + { + _text = text; + _nodes = new NodeCollection(this); + } + + public override string ToString() + { + return Text; + } + + private TreeModel FindModel() + { + Node node = this; + while (node != null) + { + if (node.Model != null) + return node.Model; + node = node.Parent; + } + return null; + } + + protected void NotifyModel() + { + TreeModel model = FindModel(); + if (model != null && Parent != null) + { + TreePath path = model.GetPath(Parent); + if (path != null) + { + TreeModelEventArgs args = new TreeModelEventArgs(path, new int[] { Index }, new object[] { this }); + model.OnNodesChanged(args); + } + } + } + } +} diff -r 3145aadca3d2 -r 0c551e8818e0 External/Aga.Controls/Tree/NodeControlInfo.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/External/Aga.Controls/Tree/NodeControlInfo.cs Sun May 27 15:16:19 2012 +0000 @@ -0,0 +1,38 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Aga.Controls.Tree.NodeControls; +using System.Drawing; + +namespace Aga.Controls.Tree +{ + public struct NodeControlInfo + { + public static readonly NodeControlInfo Empty = new NodeControlInfo(null, Rectangle.Empty, null); + + private NodeControl _control; + public NodeControl Control + { + get { return _control; } + } + + private Rectangle _bounds; + public Rectangle Bounds + { + get { return _bounds; } + } + + private TreeNodeAdv _node; + public TreeNodeAdv Node + { + get { return _node; } + } + + public NodeControlInfo(NodeControl control, Rectangle bounds, TreeNodeAdv node) + { + _control = control; + _bounds = bounds; + _node = node; + } + } +} diff -r 3145aadca3d2 -r 0c551e8818e0 External/Aga.Controls/Tree/NodeControls/BaseTextControl.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/External/Aga.Controls/Tree/NodeControls/BaseTextControl.cs Sun May 27 15:16:19 2012 +0000 @@ -0,0 +1,314 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Drawing; +using System.Windows.Forms; +using System.Reflection; +using System.ComponentModel; + +namespace Aga.Controls.Tree.NodeControls +{ + public abstract class BaseTextControl : EditableControl + { + private TextFormatFlags _baseFormatFlags; + private TextFormatFlags _formatFlags; + private Pen _focusPen; + private StringFormat _format; + + #region Properties + + private Font _font = null; + public Font Font + { + get + { + if (_font == null) + return Control.DefaultFont; + else + return _font; + } + set + { + if (value == Control.DefaultFont) + _font = null; + else + _font = value; + } + } + + protected bool ShouldSerializeFont() + { + return (_font != null); + } + + private HorizontalAlignment _textAlign = HorizontalAlignment.Left; + [DefaultValue(HorizontalAlignment.Left)] + public HorizontalAlignment TextAlign + { + get { return _textAlign; } + set + { + _textAlign = value; + SetFormatFlags(); + } + } + + private StringTrimming _trimming = StringTrimming.None; + [DefaultValue(StringTrimming.None)] + public StringTrimming Trimming + { + get { return _trimming; } + set + { + _trimming = value; + SetFormatFlags(); + } + } + + private bool _displayHiddenContentInToolTip = true; + [DefaultValue(true)] + public bool DisplayHiddenContentInToolTip + { + get { return _displayHiddenContentInToolTip; } + set { _displayHiddenContentInToolTip = value; } + } + + private bool _useCompatibleTextRendering = false; + [DefaultValue(false)] + public bool UseCompatibleTextRendering + { + get { return _useCompatibleTextRendering; } + set { _useCompatibleTextRendering = value; } + } + + [DefaultValue(false)] + public bool TrimMultiLine + { + get; + set; + } + + #endregion + + protected BaseTextControl() + { + IncrementalSearchEnabled = true; + _focusPen = new Pen(Color.Black); + _focusPen.DashStyle = System.Drawing.Drawing2D.DashStyle.Dot; + + _format = new StringFormat(StringFormatFlags.LineLimit | StringFormatFlags.NoClip | StringFormatFlags.FitBlackBox | StringFormatFlags.MeasureTrailingSpaces); + _baseFormatFlags = TextFormatFlags.PreserveGraphicsClipping | + TextFormatFlags.PreserveGraphicsTranslateTransform; + SetFormatFlags(); + LeftMargin = 3; + } + + private void SetFormatFlags() + { + _format.Alignment = TextHelper.TranslateAligment(TextAlign); + _format.Trimming = Trimming; + + _formatFlags = _baseFormatFlags | TextHelper.TranslateAligmentToFlag(TextAlign) + | TextHelper.TranslateTrimmingToFlag(Trimming); + } + + public override Size MeasureSize(TreeNodeAdv node, DrawContext context) + { + return GetLabelSize(node, context); + } + + protected Size GetLabelSize(TreeNodeAdv node, DrawContext context) + { + return GetLabelSize(node, context, GetLabel(node)); + } + + protected Size GetLabelSize(TreeNodeAdv node, DrawContext context, string label) + { + PerformanceAnalyzer.Start("GetLabelSize"); + CheckThread(); + Font font = GetDrawingFont(node, context, label); + Size s = Size.Empty; + if (UseCompatibleTextRendering) + s = TextRenderer.MeasureText(label, font); + else + { + SizeF sf = context.Graphics.MeasureString(label, font); + s = new Size((int)Math.Ceiling(sf.Width), (int)Math.Ceiling(sf.Height)); + } + PerformanceAnalyzer.Finish("GetLabelSize"); + + if (!s.IsEmpty) + return s; + else + return new Size(10, Font.Height); + } + + protected Font GetDrawingFont(TreeNodeAdv node, DrawContext context, string label) + { + Font font = context.Font; + if (DrawTextMustBeFired(node)) + { + DrawEventArgs args = new DrawEventArgs(node, this, context, label); + args.Font = context.Font; + OnDrawText(args); + font = args.Font; + } + return font; + } + + protected void SetEditControlProperties(Control control, TreeNodeAdv node) + { + string label = GetLabel(node); + DrawContext context = new DrawContext(); + context.Font = control.Font; + control.Font = GetDrawingFont(node, context, label); + } + + public override void Draw(TreeNodeAdv node, DrawContext context) + { + if (context.CurrentEditorOwner == this && node == Parent.CurrentNode) + return; + + PerformanceAnalyzer.Start("BaseTextControl.Draw"); + string label = GetLabel(node); + Rectangle bounds = GetBounds(node, context); + Rectangle focusRect = new Rectangle(bounds.X, context.Bounds.Y, + bounds.Width, context.Bounds.Height); + + Brush backgroundBrush; + Color textColor; + Font font; + CreateBrushes(node, context, label, out backgroundBrush, out textColor, out font, ref label); + + if (backgroundBrush != null) + context.Graphics.FillRectangle(backgroundBrush, focusRect); + if (context.DrawFocus) + { + focusRect.Width--; + focusRect.Height--; + if (context.DrawSelection == DrawSelectionMode.None) + _focusPen.Color = SystemColors.ControlText; + else + _focusPen.Color = SystemColors.InactiveCaption; + context.Graphics.DrawRectangle(_focusPen, focusRect); + } + + PerformanceAnalyzer.Start("BaseTextControl.DrawText"); + if (UseCompatibleTextRendering) + TextRenderer.DrawText(context.Graphics, label, font, bounds, textColor, _formatFlags); + else + context.Graphics.DrawString(label, font, GetFrush(textColor), bounds, _format); + PerformanceAnalyzer.Finish("BaseTextControl.DrawText"); + + PerformanceAnalyzer.Finish("BaseTextControl.Draw"); + } + + private static Dictionary _brushes = new Dictionary(); + private static Brush GetFrush(Color color) + { + Brush br; + if (_brushes.ContainsKey(color)) + br = _brushes[color]; + else + { + br = new SolidBrush(color); + _brushes.Add(color, br); + } + return br; + } + + private void CreateBrushes(TreeNodeAdv node, DrawContext context, string text, out Brush backgroundBrush, out Color textColor, out Font font, ref string label) + { + textColor = SystemColors.ControlText; + backgroundBrush = null; + font = context.Font; + if (context.DrawSelection == DrawSelectionMode.Active) + { + textColor = SystemColors.HighlightText; + backgroundBrush = SystemBrushes.Highlight; + } + else if (context.DrawSelection == DrawSelectionMode.Inactive) + { + textColor = SystemColors.ControlText; + backgroundBrush = SystemBrushes.InactiveBorder; + } + else if (context.DrawSelection == DrawSelectionMode.FullRowSelect) + textColor = SystemColors.HighlightText; + + if (!context.Enabled) + textColor = SystemColors.GrayText; + + if (DrawTextMustBeFired(node)) + { + DrawEventArgs args = new DrawEventArgs(node, this, context, text); + args.Text = label; + args.TextColor = textColor; + args.BackgroundBrush = backgroundBrush; + args.Font = font; + + OnDrawText(args); + + textColor = args.TextColor; + backgroundBrush = args.BackgroundBrush; + font = args.Font; + label = args.Text; + } + } + + public string GetLabel(TreeNodeAdv node) + { + if (node != null && node.Tag != null) + { + object obj = GetValue(node); + if (obj != null) + return FormatLabel(obj); + } + return string.Empty; + } + + protected virtual string FormatLabel(object obj) + { + var res = obj.ToString(); + if (TrimMultiLine && res != null) + { + string[] parts = res.Split('\n'); + if (parts.Length > 1) + return parts[0] + "..."; + } + return res; + } + + public void SetLabel(TreeNodeAdv node, string value) + { + SetValue(node, value); + } + + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + if (disposing) + { + _focusPen.Dispose(); + _format.Dispose(); + } + } + + /// + /// Fires when control is going to draw a text. Can be used to change text or back color + /// + public event EventHandler DrawText; + protected virtual void OnDrawText(DrawEventArgs args) + { + TreeViewAdv tree = args.Node.Tree; + if (tree != null) + tree.FireDrawControl(args); + if (DrawText != null) + DrawText(this, args); + } + + protected virtual bool DrawTextMustBeFired(TreeNodeAdv node) + { + return DrawText != null || (node.Tree != null && node.Tree.DrawControlMustBeFired()); + } + } +} diff -r 3145aadca3d2 -r 0c551e8818e0 External/Aga.Controls/Tree/NodeControls/BindableControl.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/External/Aga.Controls/Tree/NodeControls/BindableControl.cs Sun May 27 15:16:19 2012 +0000 @@ -0,0 +1,194 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Reflection; +using System.ComponentModel; + +namespace Aga.Controls.Tree.NodeControls +{ + public abstract class BindableControl : NodeControl + { + private struct MemberAdapter + { + private object _obj; + private PropertyInfo _pi; + private FieldInfo _fi; + + public static readonly MemberAdapter Empty = new MemberAdapter(); + + public Type MemberType + { + get + { + if (_pi != null) + return _pi.PropertyType; + else if (_fi != null) + return _fi.FieldType; + else + return null; + } + } + + public object Value + { + get + { + if (_pi != null && _pi.CanRead) + return _pi.GetValue(_obj, null); + else if (_fi != null) + return _fi.GetValue(_obj); + else + return null; + } + set + { + if (_pi != null && _pi.CanWrite) + _pi.SetValue(_obj, value, null); + else if (_fi != null) + _fi.SetValue(_obj, value); + } + } + + public MemberAdapter(object obj, PropertyInfo pi) + { + _obj = obj; + _pi = pi; + _fi = null; + } + + public MemberAdapter(object obj, FieldInfo fi) + { + _obj = obj; + _fi = fi; + _pi = null; + } + } + + #region Properties + + private bool _virtualMode = false; + [DefaultValue(false), Category("Data")] + public bool VirtualMode + { + get { return _virtualMode; } + set { _virtualMode = value; } + } + + private string _propertyName = ""; + [DefaultValue(""), Category("Data")] + public string DataPropertyName + { + get { return _propertyName; } + set + { + if (_propertyName == null) + _propertyName = string.Empty; + _propertyName = value; + } + } + + private bool _incrementalSearchEnabled = false; + [DefaultValue(false)] + public bool IncrementalSearchEnabled + { + get { return _incrementalSearchEnabled; } + set { _incrementalSearchEnabled = value; } + } + + #endregion + + public virtual object GetValue(TreeNodeAdv node) + { + if (VirtualMode) + { + NodeControlValueEventArgs args = new NodeControlValueEventArgs(node); + OnValueNeeded(args); + return args.Value; + } + else + { + try + { + return GetMemberAdapter(node).Value; + } + catch (TargetInvocationException ex) + { + if (ex.InnerException != null) + throw new ArgumentException(ex.InnerException.Message, ex.InnerException); + else + throw new ArgumentException(ex.Message); + } + } + } + + public virtual void SetValue(TreeNodeAdv node, object value) + { + if (VirtualMode) + { + NodeControlValueEventArgs args = new NodeControlValueEventArgs(node); + args.Value = value; + OnValuePushed(args); + } + else + { + try + { + MemberAdapter ma = GetMemberAdapter(node); + ma.Value = value; + } + catch (TargetInvocationException ex) + { + if (ex.InnerException != null) + throw new ArgumentException(ex.InnerException.Message, ex.InnerException); + else + throw new ArgumentException(ex.Message); + } + } + } + + public Type GetPropertyType(TreeNodeAdv node) + { + return GetMemberAdapter(node).MemberType; + } + + private MemberAdapter GetMemberAdapter(TreeNodeAdv node) + { + if (node.Tag != null && !string.IsNullOrEmpty(DataPropertyName)) + { + Type type = node.Tag.GetType(); + PropertyInfo pi = type.GetProperty(DataPropertyName); + if (pi != null) + return new MemberAdapter(node.Tag, pi); + else + { + FieldInfo fi = type.GetField(DataPropertyName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); + if (fi != null) + return new MemberAdapter(node.Tag, fi); + } + } + return MemberAdapter.Empty; + } + + public override string ToString() + { + if (string.IsNullOrEmpty(DataPropertyName)) + return GetType().Name; + else + return string.Format("{0} ({1})", GetType().Name, DataPropertyName); + } + + public event EventHandler ValueNeeded; + private void OnValueNeeded(NodeControlValueEventArgs args) + { + if (ValueNeeded != null) + ValueNeeded(this, args); + } + + public event EventHandler ValuePushed; + private void OnValuePushed(NodeControlValueEventArgs args) + { + if (ValuePushed != null) + ValuePushed(this, args); + } + } +} diff -r 3145aadca3d2 -r 0c551e8818e0 External/Aga.Controls/Tree/NodeControls/ClassDiagram.cd --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/External/Aga.Controls/Tree/NodeControls/ClassDiagram.cd Sun May 27 15:16:19 2012 +0000 @@ -0,0 +1,105 @@ + + + + + + + Tree\NodeControls\NodeStateIcon.cs + ABAAAAAAAAQAQAAAAAAAAAAAAAAAAAAAQIAAAAAAAAA= + + + + + + Tree\NodeControls\BindableControl.cs + FAAAAAAQIBAQCgAEAAAAIAAAAAAAAAEMAAACAAAAAAE= + + + + + + Tree\NodeControls\NodeCheckBox.cs + AAEAAAAAAAACgkQCAAAAAAigAgAAEGABAAAIAAAAAAA= + + + + + + Tree\NodeControls\NodeControl.cs + AAAAAJAAgIgBkkoQAAgAQAAwAAABEIQAAEBIAAAAAAA= + + + + + + + + + Tree\NodeControls\NodeIcon.cs + ABAAAAAAAAAAAgAAAAAAAAAgAAAAAAAAAAAAAAAAAAA= + + + + + + Tree\NodeControls\NodePlusMinus.cs + AAAAAAAAAAAAAgAAAAAAAEAgAAAAMCAAAAAIACAAAAA= + + + + + + Tree\NodeControls\BaseTextControl.cs + AAAAICBQACAAIgACBCAEAQA8AgmFoAAwAAAAACACAMA= + + + + + + Tree\NodeControls\NodeTextBox.cs + QQQAhAAAADAMgAAAABAAAAAAAgEAIAAAAAAAAIAAAAA= + + + + + + Tree\NodeControls\EditableControl.cs + QQAgAAAACGgkAMAABAEEkADAEAAUEAAABAGoAAAAAQA= + + + + + + Tree\NodeControls\NodeComboBox.cs + wQACAAAAAAAMAEBAAAAAAABAAAAAAAABAAAAAAAAAAA= + + + + + + Tree\NodeControls\NodeNumericUpDown.cs + wQAAAACAAAAEAABAIAAQIAAAAAAAAAABAAAIAAAAAII= + + + + + + Tree\NodeControls\InteractiveControl.cs + AAAABAAAAAAAAAAACAAAAAAAABAAAQAAAAAAAAIAAAA= + + + + + + Tree\NodeControls\NodeDecimalTextBox.cs + AQAAAAAAAACAAAACAAAAAAQAAAAAIAAAAAgAAAAAAAA= + + + + + + Tree\NodeControls\NodeIntegerTextBox.cs + AQAAAAAAAAAAAAACAAAAAAQAAAAAIAAAAAAAAAAAAAA= + + + \ No newline at end of file diff -r 3145aadca3d2 -r 0c551e8818e0 External/Aga.Controls/Tree/NodeControls/DrawEventArgs.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/External/Aga.Controls/Tree/NodeControls/DrawEventArgs.cs Sun May 27 15:16:19 2012 +0000 @@ -0,0 +1,67 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Drawing; + +namespace Aga.Controls.Tree.NodeControls +{ + public class DrawEventArgs : NodeEventArgs + { + private DrawContext _context; + public DrawContext Context + { + get { return _context; } + } + + private Brush _textBrush; + [Obsolete("Use TextColor")] + public Brush TextBrush + { + get { return _textBrush; } + set { _textBrush = value; } + } + + private Brush _backgroundBrush; + public Brush BackgroundBrush + { + get { return _backgroundBrush; } + set { _backgroundBrush = value; } + } + + private Font _font; + public Font Font + { + get { return _font; } + set { _font = value; } + } + + private Color _textColor; + public Color TextColor + { + get { return _textColor; } + set { _textColor = value; } + } + + private string _text; + public string Text + { + get { return _text; } + set { _text = value; } + } + + + private EditableControl _control; + public EditableControl Control + { + get { return _control; } + } + + public DrawEventArgs(TreeNodeAdv node, EditableControl control, DrawContext context, string text) + : base(node) + { + _control = control; + _context = context; + _text = text; + } + } +} diff -r 3145aadca3d2 -r 0c551e8818e0 External/Aga.Controls/Tree/NodeControls/EditEventArgs.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/External/Aga.Controls/Tree/NodeControls/EditEventArgs.cs Sun May 27 15:16:19 2012 +0000 @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Windows.Forms; + +namespace Aga.Controls.Tree.NodeControls +{ + public class EditEventArgs : NodeEventArgs + { + private Control _control; + public Control Control + { + get { return _control; } + } + + public EditEventArgs(TreeNodeAdv node, Control control) + : base(node) + { + _control = control; + } + } +} diff -r 3145aadca3d2 -r 0c551e8818e0 External/Aga.Controls/Tree/NodeControls/EditableControl.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/External/Aga.Controls/Tree/NodeControls/EditableControl.cs Sun May 27 15:16:19 2012 +0000 @@ -0,0 +1,175 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Windows.Forms; +using System.Drawing; +using System.ComponentModel; + +namespace Aga.Controls.Tree.NodeControls +{ + public abstract class EditableControl : InteractiveControl + { + private Timer _timer; + private bool _editFlag; + + #region Properties + + private bool _editOnClick = false; + [DefaultValue(false)] + public bool EditOnClick + { + get { return _editOnClick; } + set { _editOnClick = value; } + } + + #endregion + + protected EditableControl() + { + _timer = new Timer(); + _timer.Interval = 500; + _timer.Tick += new EventHandler(TimerTick); + } + + private void TimerTick(object sender, EventArgs e) + { + _timer.Stop(); + if (_editFlag) + BeginEdit(); + _editFlag = false; + } + + public void SetEditorBounds(EditorContext context) + { + Size size = CalculateEditorSize(context); + context.Editor.Bounds = new Rectangle(context.Bounds.X, context.Bounds.Y, + Math.Min(size.Width, context.Bounds.Width), + Math.Min(size.Height, Parent.ClientSize.Height - context.Bounds.Y) + ); + } + + protected abstract Size CalculateEditorSize(EditorContext context); + + protected virtual bool CanEdit(TreeNodeAdv node) + { + return (node.Tag != null) && IsEditEnabled(node); + } + + public void BeginEdit() + { + if (Parent != null && Parent.CurrentNode != null && CanEdit(Parent.CurrentNode)) + { + CancelEventArgs args = new CancelEventArgs(); + OnEditorShowing(args); + if (!args.Cancel) + { + var editor = CreateEditor(Parent.CurrentNode); + Parent.DisplayEditor(editor, this); + } + } + } + + public void EndEdit(bool applyChanges) + { + if (Parent != null) + if (Parent.HideEditor(applyChanges)) + OnEditorHided(); + } + + public virtual void UpdateEditor(Control control) + { + } + + internal void ApplyChanges(TreeNodeAdv node, Control editor) + { + DoApplyChanges(node, editor); + OnChangesApplied(); + } + + internal void DoDisposeEditor(Control editor) + { + DisposeEditor(editor); + } + + protected abstract void DoApplyChanges(TreeNodeAdv node, Control editor); + + protected abstract Control CreateEditor(TreeNodeAdv node); + + protected abstract void DisposeEditor(Control editor); + + public virtual void Cut(Control control) + { + } + + public virtual void Copy(Control control) + { + } + + public virtual void Paste(Control control) + { + } + + public virtual void Delete(Control control) + { + } + + public override void MouseDown(TreeNodeAdvMouseEventArgs args) + { + _editFlag = (!EditOnClick && args.Button == MouseButtons.Left + && args.ModifierKeys == Keys.None && args.Node.IsSelected); + } + + public override void MouseUp(TreeNodeAdvMouseEventArgs args) + { + if (args.Node.IsSelected) + { + if (EditOnClick && args.Button == MouseButtons.Left && args.ModifierKeys == Keys.None) + { + Parent.ItemDragMode = false; + BeginEdit(); + args.Handled = true; + } + else if (_editFlag)// && args.Node.IsSelected) + _timer.Start(); + } + } + + public override void MouseDoubleClick(TreeNodeAdvMouseEventArgs args) + { + _editFlag = false; + _timer.Stop(); + } + + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + if (disposing) + _timer.Dispose(); + } + + #region Events + + public event CancelEventHandler EditorShowing; + protected void OnEditorShowing(CancelEventArgs args) + { + if (EditorShowing != null) + EditorShowing(this, args); + } + + public event EventHandler EditorHided; + protected void OnEditorHided() + { + if (EditorHided != null) + EditorHided(this, EventArgs.Empty); + } + + public event EventHandler ChangesApplied; + protected void OnChangesApplied() + { + if (ChangesApplied != null) + ChangesApplied(this, EventArgs.Empty); + } + + #endregion + } +} diff -r 3145aadca3d2 -r 0c551e8818e0 External/Aga.Controls/Tree/NodeControls/ExpandingIcon.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/External/Aga.Controls/Tree/NodeControls/ExpandingIcon.cs Sun May 27 15:16:19 2012 +0000 @@ -0,0 +1,83 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Drawing; +using System.Threading; +using System.Windows.Forms; + +namespace Aga.Controls.Tree.NodeControls +{ + /// + /// Displays an animated icon for those nodes, who are in expanding state. + /// Parent TreeView must have AsyncExpanding property set to true. + /// + public class ExpandingIcon: NodeControl + { + private static GifDecoder _gif = ResourceHelper.LoadingIcon; + private static int _index = 0; + private static volatile Thread _animatingThread; + private static object _lock = new object(); + + public override Size MeasureSize(TreeNodeAdv node, DrawContext context) + { + return ResourceHelper.LoadingIcon.FrameSize; + } + + protected override void OnIsVisibleValueNeeded(NodeControlValueEventArgs args) + { + args.Value = args.Node.IsExpandingNow; + base.OnIsVisibleValueNeeded(args); + } + + public override void Draw(TreeNodeAdv node, DrawContext context) + { + Rectangle rect = GetBounds(node, context); + Image img = _gif.GetFrame(_index).Image; + context.Graphics.DrawImage(img, rect.Location); + } + + public static void Start() + { + lock (_lock) + { + if (_animatingThread == null) + { + _index = 0; + _animatingThread = new Thread(new ThreadStart(IterateIcons)); + _animatingThread.IsBackground = true; + _animatingThread.Priority = ThreadPriority.Lowest; + _animatingThread.Start(); + } + } + } + + public static void Stop() + { + lock (_lock) + { + _index = 0; + _animatingThread = null; + } + } + + private static void IterateIcons() + { + while (_animatingThread != null) + { + if (_index < _gif.FrameCount - 1) + _index++; + else + _index = 0; + + if (IconChanged != null) + IconChanged(null, EventArgs.Empty); + + int delay = _gif.GetFrame(_index).Delay; + Thread.Sleep(delay); + } + System.Diagnostics.Debug.WriteLine("IterateIcons Stopped"); + } + + public static event EventHandler IconChanged; + } +} diff -r 3145aadca3d2 -r 0c551e8818e0 External/Aga.Controls/Tree/NodeControls/InteractiveControl.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/External/Aga.Controls/Tree/NodeControls/InteractiveControl.cs Sun May 27 15:16:19 2012 +0000 @@ -0,0 +1,38 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.ComponentModel; + +namespace Aga.Controls.Tree.NodeControls +{ + public abstract class InteractiveControl : BindableControl + { + private bool _editEnabled = false; + [DefaultValue(false)] + public bool EditEnabled + { + get { return _editEnabled; } + set { _editEnabled = value; } + } + + protected bool IsEditEnabled(TreeNodeAdv node) + { + if (EditEnabled) + { + NodeControlValueEventArgs args = new NodeControlValueEventArgs(node); + args.Value = true; + OnIsEditEnabledValueNeeded(args); + return Convert.ToBoolean(args.Value); + } + else + return false; + } + + public event EventHandler IsEditEnabledValueNeeded; + private void OnIsEditEnabledValueNeeded(NodeControlValueEventArgs args) + { + if (IsEditEnabledValueNeeded != null) + IsEditEnabledValueNeeded(this, args); + } + } +} diff -r 3145aadca3d2 -r 0c551e8818e0 External/Aga.Controls/Tree/NodeControls/LabelEventArgs.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/External/Aga.Controls/Tree/NodeControls/LabelEventArgs.cs Sun May 27 15:16:19 2012 +0000 @@ -0,0 +1,34 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Aga.Controls.Tree.NodeControls +{ + public class LabelEventArgs : EventArgs + { + private object _subject; + public object Subject + { + get { return _subject; } + } + + private string _oldLabel; + public string OldLabel + { + get { return _oldLabel; } + } + + private string _newLabel; + public string NewLabel + { + get { return _newLabel; } + } + + public LabelEventArgs(object subject, string oldLabel, string newLabel) + { + _subject = subject; + _oldLabel = oldLabel; + _newLabel = newLabel; + } + } +} diff -r 3145aadca3d2 -r 0c551e8818e0 External/Aga.Controls/Tree/NodeControls/NodeCheckBox.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/External/Aga.Controls/Tree/NodeControls/NodeCheckBox.cs Sun May 27 15:16:19 2012 +0000 @@ -0,0 +1,184 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Drawing; +using Aga.Controls.Properties; +using System.Reflection; +using System.Windows.Forms; +using System.Windows.Forms.VisualStyles; +using System.ComponentModel; + +namespace Aga.Controls.Tree.NodeControls +{ + public class NodeCheckBox : InteractiveControl + { + public const int ImageSize = 13; + + private Bitmap _check; + private Bitmap _uncheck; + private Bitmap _unknown; + + #region Properties + + private bool _threeState; + [DefaultValue(false)] + public bool ThreeState + { + get { return _threeState; } + set { _threeState = value; } + } + + #endregion + + public NodeCheckBox() + : this(string.Empty) + { + } + + public NodeCheckBox(string propertyName) + { + _check = Resources.check; + _uncheck = Resources.uncheck; + _unknown = Resources.unknown; + DataPropertyName = propertyName; + LeftMargin = 0; + } + + public override Size MeasureSize(TreeNodeAdv node, DrawContext context) + { + return new Size(ImageSize, ImageSize); + } + + public override void Draw(TreeNodeAdv node, DrawContext context) + { + Rectangle bounds = GetBounds(node, context); + CheckState state = GetCheckState(node); + if (Application.RenderWithVisualStyles) + { + VisualStyleRenderer renderer; + if (state == CheckState.Indeterminate) + renderer = new VisualStyleRenderer(VisualStyleElement.Button.CheckBox.MixedNormal); + else if (state == CheckState.Checked) + renderer = new VisualStyleRenderer(VisualStyleElement.Button.CheckBox.CheckedNormal); + else + renderer = new VisualStyleRenderer(VisualStyleElement.Button.CheckBox.UncheckedNormal); + renderer.DrawBackground(context.Graphics, new Rectangle(bounds.X, bounds.Y, ImageSize, ImageSize)); + } + else + { + Image img; + if (state == CheckState.Indeterminate) + img = _unknown; + else if (state == CheckState.Checked) + img = _check; + else + img = _uncheck; + context.Graphics.DrawImage(img, bounds.Location); + } + } + + protected virtual CheckState GetCheckState(TreeNodeAdv node) + { + object obj = GetValue(node); + if (obj is CheckState) + return (CheckState)obj; + else if (obj is bool) + return (bool)obj ? CheckState.Checked : CheckState.Unchecked; + else + return CheckState.Unchecked; + } + + protected virtual void SetCheckState(TreeNodeAdv node, CheckState value) + { + if (VirtualMode) + { + SetValue(node, value); + OnCheckStateChanged(node); + } + else + { + Type type = GetPropertyType(node); + if (type == typeof(CheckState)) + { + SetValue(node, value); + OnCheckStateChanged(node); + } + else if (type == typeof(bool)) + { + SetValue(node, value != CheckState.Unchecked); + OnCheckStateChanged(node); + } + } + } + + public override void MouseDown(TreeNodeAdvMouseEventArgs args) + { + if (args.Button == MouseButtons.Left && IsEditEnabled(args.Node)) + { + DrawContext context = new DrawContext(); + context.Bounds = args.ControlBounds; + Rectangle rect = GetBounds(args.Node, context); + if (rect.Contains(args.ViewLocation)) + { + CheckState state = GetCheckState(args.Node); + state = GetNewState(state); + SetCheckState(args.Node, state); + Parent.UpdateView(); + args.Handled = true; + } + } + } + + public override void MouseDoubleClick(TreeNodeAdvMouseEventArgs args) + { + args.Handled = true; + } + + private CheckState GetNewState(CheckState state) + { + if (state == CheckState.Indeterminate) + return CheckState.Unchecked; + else if(state == CheckState.Unchecked) + return CheckState.Checked; + else + return ThreeState ? CheckState.Indeterminate : CheckState.Unchecked; + } + + public override void KeyDown(KeyEventArgs args) + { + if (args.KeyCode == Keys.Space && EditEnabled) + { + Parent.BeginUpdate(); + try + { + if (Parent.CurrentNode != null) + { + CheckState value = GetNewState(GetCheckState(Parent.CurrentNode)); + foreach (TreeNodeAdv node in Parent.Selection) + if (IsEditEnabled(node)) + SetCheckState(node, value); + } + } + finally + { + Parent.EndUpdate(); + } + args.Handled = true; + } + } + + public event EventHandler CheckStateChanged; + protected void OnCheckStateChanged(TreePathEventArgs args) + { + if (CheckStateChanged != null) + CheckStateChanged(this, args); + } + + protected void OnCheckStateChanged(TreeNodeAdv node) + { + TreePath path = this.Parent.GetPath(node); + OnCheckStateChanged(new TreePathEventArgs(path)); + } + + } +} diff -r 3145aadca3d2 -r 0c551e8818e0 External/Aga.Controls/Tree/NodeControls/NodeComboBox.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/External/Aga.Controls/Tree/NodeControls/NodeComboBox.cs Sun May 27 15:16:19 2012 +0000 @@ -0,0 +1,232 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Drawing; +using System.Windows.Forms; +using System.Reflection; +using System.ComponentModel; +using System.Drawing.Design; + +namespace Aga.Controls.Tree.NodeControls +{ + public class NodeComboBox : BaseTextControl + { + #region Properties + + private int _editorWidth = 100; + [DefaultValue(100)] + public int EditorWidth + { + get { return _editorWidth; } + set { _editorWidth = value; } + } + + private int _editorHeight = 100; + [DefaultValue(100)] + public int EditorHeight + { + get { return _editorHeight; } + set { _editorHeight = value; } + } + + private List _dropDownItems; + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1002:DoNotExposeGenericLists")] + [Editor(typeof(StringCollectionEditor), typeof(UITypeEditor)), DesignerSerializationVisibility(DesignerSerializationVisibility.Content)] + public List DropDownItems + { + get { return _dropDownItems; } + } + + #endregion + + public event EventHandler CreatingEditor; + + public NodeComboBox() + { + _dropDownItems = new List(); + } + + protected override Size CalculateEditorSize(EditorContext context) + { + if (Parent.UseColumns) + { + if (context.Editor is CheckedListBox) + return new Size(context.Bounds.Size.Width, EditorHeight); + else + return context.Bounds.Size; + } + else + { + if (context.Editor is CheckedListBox) + return new Size(EditorWidth, EditorHeight); + else + return new Size(EditorWidth, context.Bounds.Height); + } + } + + protected override Control CreateEditor(TreeNodeAdv node) + { + Control c; + object value = GetValue(node); + if (IsCheckedListBoxRequired(node)) + c = CreateCheckedListBox(node); + else + c = CreateCombo(node); + OnCreatingEditor(new EditEventArgs(node, c)); + return c; + } + + protected override void DisposeEditor(Control editor) + { + } + + protected virtual void OnCreatingEditor(EditEventArgs args) + { + if (CreatingEditor != null) + CreatingEditor(this, args); + } + + protected virtual bool IsCheckedListBoxRequired(TreeNodeAdv node) + { + object value = GetValue(node); + if (value != null) + { + Type t = value.GetType(); + object[] arr = t.GetCustomAttributes(typeof(FlagsAttribute), false); + return (t.IsEnum && arr.Length == 1); + } + return false; + } + + private Control CreateCombo(TreeNodeAdv node) + { + ComboBox comboBox = new ComboBox(); + if (DropDownItems != null) + comboBox.Items.AddRange(DropDownItems.ToArray()); + comboBox.SelectedItem = GetValue(node); + comboBox.DropDownStyle = ComboBoxStyle.DropDownList; + comboBox.DropDownClosed += new EventHandler(EditorDropDownClosed); + SetEditControlProperties(comboBox, node); + return comboBox; + } + + private Control CreateCheckedListBox(TreeNodeAdv node) + { + CheckedListBox listBox = new CheckedListBox(); + listBox.CheckOnClick = true; + + object value = GetValue(node); + Type enumType = GetEnumType(node); + foreach (object obj in Enum.GetValues(enumType)) + { + object[] attributes = enumType.GetField(obj.ToString()).GetCustomAttributes(typeof(BrowsableAttribute), false); + if (attributes.Length == 0 || ((BrowsableAttribute)attributes[0]).Browsable) + listBox.Items.Add(obj, IsContain(value, obj)); + } + + SetEditControlProperties(listBox, node); + if (CreatingEditor != null) + CreatingEditor(this, new EditEventArgs(node, listBox)); + return listBox; + } + + protected virtual Type GetEnumType(TreeNodeAdv node) + { + object value = GetValue(node); + return value.GetType(); + } + + private bool IsContain(object value, object enumElement) + { + if (value == null || enumElement == null) + return false; + if (value.GetType().IsEnum) + { + int i1 = (int)value; + int i2 = (int)enumElement; + return (i1 & i2) == i2; + } + else + { + var arr = value as object[]; + foreach (object obj in arr) + if ((int)obj == (int)enumElement) + return true; + return false; + } + } + + protected override string FormatLabel(object obj) + { + var arr = obj as object[]; + if (arr != null) + { + StringBuilder sb = new StringBuilder(); + foreach (object t in arr) + { + if (sb.Length > 0) + sb.Append(", "); + sb.Append(t); + } + return sb.ToString(); + } + else + return base.FormatLabel(obj); + } + + void EditorDropDownClosed(object sender, EventArgs e) + { + EndEdit(true); + } + + public override void UpdateEditor(Control control) + { + if (control is ComboBox) + (control as ComboBox).DroppedDown = true; + } + + protected override void DoApplyChanges(TreeNodeAdv node, Control editor) + { + var combo = editor as ComboBox; + if (combo != null) + { + if (combo.DropDownStyle == ComboBoxStyle.DropDown) + SetValue(node, combo.Text); + else + SetValue(node, combo.SelectedItem); + } + else + { + var listBox = editor as CheckedListBox; + Type type = GetEnumType(node); + if (IsFlags(type)) + { + int res = 0; + foreach (object obj in listBox.CheckedItems) + res |= (int)obj; + object val = Enum.ToObject(type, res); + SetValue(node, val); + } + else + { + List list = new List(); + foreach (object obj in listBox.CheckedItems) + list.Add(obj); + SetValue(node, list.ToArray()); + } + } + } + + private bool IsFlags(Type type) + { + object[] atr = type.GetCustomAttributes(typeof(FlagsAttribute), false); + return atr.Length == 1; + } + + public override void MouseUp(TreeNodeAdvMouseEventArgs args) + { + if (args.Node != null && args.Node.IsSelected) //Workaround of specific ComboBox control behavior + base.MouseUp(args); + } + } +} diff -r 3145aadca3d2 -r 0c551e8818e0 External/Aga.Controls/Tree/NodeControls/NodeControl.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/External/Aga.Controls/Tree/NodeControls/NodeControl.cs Sun May 27 15:16:19 2012 +0000 @@ -0,0 +1,169 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Windows.Forms; +using System.Drawing; +using System.ComponentModel; + +namespace Aga.Controls.Tree.NodeControls +{ + [DesignTimeVisible(false), ToolboxItem(false)] + public abstract class NodeControl : Component + { + #region Properties + + private TreeViewAdv _parent; + [Browsable(false)] + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public TreeViewAdv Parent + { + get { return _parent; } + set + { + if (value != _parent) + { + if (_parent != null) + _parent.NodeControls.Remove(this); + + if (value != null) + value.NodeControls.Add(this); + } + } + } + + private IToolTipProvider _toolTipProvider; + [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public IToolTipProvider ToolTipProvider + { + get { return _toolTipProvider; } + set { _toolTipProvider = value; } + } + + private TreeColumn _parentColumn; + public TreeColumn ParentColumn + { + get { return _parentColumn; } + set + { + _parentColumn = value; + if (_parent != null) + _parent.FullUpdate(); + } + } + + private VerticalAlignment _verticalAlign = VerticalAlignment.Center; + [DefaultValue(VerticalAlignment.Center)] + public VerticalAlignment VerticalAlign + { + get { return _verticalAlign; } + set + { + _verticalAlign = value; + if (_parent != null) + _parent.FullUpdate(); + } + } + + private int _leftMargin = 0; + public int LeftMargin + { + get { return _leftMargin; } + set + { + if (value < 0) + throw new ArgumentOutOfRangeException(); + + _leftMargin = value; + if (_parent != null) + _parent.FullUpdate(); + } + } + #endregion + + internal virtual void AssignParent(TreeViewAdv parent) + { + _parent = parent; + } + + protected virtual Rectangle GetBounds(TreeNodeAdv node, DrawContext context) + { + Rectangle r = context.Bounds; + Size s = GetActualSize(node, context); + Size bs = new Size(r.Width - LeftMargin, Math.Min(r.Height, s.Height)); + switch (VerticalAlign) + { + case VerticalAlignment.Top: + return new Rectangle(new Point(r.X + LeftMargin, r.Y), bs); + case VerticalAlignment.Bottom: + return new Rectangle(new Point(r.X + LeftMargin, r.Bottom - s.Height), bs); + default: + return new Rectangle(new Point(r.X + LeftMargin, r.Y + (r.Height - s.Height) / 2), bs); + } + } + + protected void CheckThread() + { + if (Parent != null && Control.CheckForIllegalCrossThreadCalls) + if (Parent.InvokeRequired) + throw new InvalidOperationException("Cross-thread calls are not allowed"); + } + + public bool IsVisible(TreeNodeAdv node) + { + NodeControlValueEventArgs args = new NodeControlValueEventArgs(node); + args.Value = true; + OnIsVisibleValueNeeded(args); + return Convert.ToBoolean(args.Value); + } + + internal Size GetActualSize(TreeNodeAdv node, DrawContext context) + { + if (IsVisible(node)) + { + Size s = MeasureSize(node, context); + return new Size(s.Width + LeftMargin, s.Height); + } + else + return Size.Empty; + } + + public abstract Size MeasureSize(TreeNodeAdv node, DrawContext context); + + public abstract void Draw(TreeNodeAdv node, DrawContext context); + + public virtual string GetToolTip(TreeNodeAdv node) + { + if (ToolTipProvider != null) + return ToolTipProvider.GetToolTip(node, this); + else + return string.Empty; + } + + public virtual void MouseDown(TreeNodeAdvMouseEventArgs args) + { + } + + public virtual void MouseUp(TreeNodeAdvMouseEventArgs args) + { + } + + public virtual void MouseDoubleClick(TreeNodeAdvMouseEventArgs args) + { + } + + public virtual void KeyDown(KeyEventArgs args) + { + } + + public virtual void KeyUp(KeyEventArgs args) + { + } + + public event EventHandler IsVisibleValueNeeded; + protected virtual void OnIsVisibleValueNeeded(NodeControlValueEventArgs args) + { + if (IsVisibleValueNeeded != null) + IsVisibleValueNeeded(this, args); + } + } +} diff -r 3145aadca3d2 -r 0c551e8818e0 External/Aga.Controls/Tree/NodeControls/NodeControlValueEventArgs.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/External/Aga.Controls/Tree/NodeControls/NodeControlValueEventArgs.cs Sun May 27 15:16:19 2012 +0000 @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Aga.Controls.Tree.NodeControls +{ + public class NodeControlValueEventArgs : NodeEventArgs + { + private object _value; + public object Value + { + get { return _value; } + set { _value = value; } + } + + public NodeControlValueEventArgs(TreeNodeAdv node) + :base(node) + { + } + } +} diff -r 3145aadca3d2 -r 0c551e8818e0 External/Aga.Controls/Tree/NodeControls/NodeControlsCollection.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/External/Aga.Controls/Tree/NodeControls/NodeControlsCollection.cs Sun May 27 15:16:19 2012 +0000 @@ -0,0 +1,94 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.ComponentModel.Design; +using System.Collections.ObjectModel; +using System.ComponentModel; +using System.Drawing.Design; + +namespace Aga.Controls.Tree.NodeControls +{ + internal class NodeControlsCollection : Collection + { + private TreeViewAdv _tree; + + public NodeControlsCollection(TreeViewAdv tree) + { + _tree = tree; + } + + protected override void ClearItems() + { + _tree.BeginUpdate(); + try + { + while (this.Count != 0) + this.RemoveAt(this.Count - 1); + } + finally + { + _tree.EndUpdate(); + } + } + + protected override void InsertItem(int index, NodeControl item) + { + if (item == null) + throw new ArgumentNullException("item"); + + if (item.Parent != _tree) + { + if (item.Parent != null) + { + item.Parent.NodeControls.Remove(item); + } + base.InsertItem(index, item); + item.AssignParent(_tree); + _tree.FullUpdate(); + } + } + + protected override void RemoveItem(int index) + { + NodeControl value = this[index]; + value.AssignParent(null); + base.RemoveItem(index); + _tree.FullUpdate(); + } + + protected override void SetItem(int index, NodeControl item) + { + if (item == null) + throw new ArgumentNullException("item"); + + _tree.BeginUpdate(); + try + { + RemoveAt(index); + InsertItem(index, item); + } + finally + { + _tree.EndUpdate(); + } + } + } + + internal class NodeControlCollectionEditor : CollectionEditor + { + private Type[] _types; + + public NodeControlCollectionEditor(Type type) + : base(type) + { + _types = new Type[] { typeof(NodeTextBox), typeof(NodeIntegerTextBox), typeof(NodeDecimalTextBox), + typeof(NodeComboBox), typeof(NodeCheckBox), + typeof(NodeStateIcon), typeof(NodeIcon), typeof(NodeNumericUpDown), typeof(ExpandingIcon) }; + } + + protected override System.Type[] CreateNewItemTypes() + { + return _types; + } + } +} diff -r 3145aadca3d2 -r 0c551e8818e0 External/Aga.Controls/Tree/NodeControls/NodeDecimalTextBox.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/External/Aga.Controls/Tree/NodeControls/NodeDecimalTextBox.cs Sun May 27 15:16:19 2012 +0000 @@ -0,0 +1,46 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Drawing; +using System.Windows.Forms; +using System.Reflection; +using System.ComponentModel; + +namespace Aga.Controls.Tree.NodeControls +{ + public class NodeDecimalTextBox : NodeTextBox + { + private bool _allowDecimalSeparator = true; + [DefaultValue(true)] + public bool AllowDecimalSeparator + { + get { return _allowDecimalSeparator; } + set { _allowDecimalSeparator = value; } + } + + private bool _allowNegativeSign = true; + [DefaultValue(true)] + public bool AllowNegativeSign + { + get { return _allowNegativeSign; } + set { _allowNegativeSign = value; } + } + + protected NodeDecimalTextBox() + { + } + + protected override TextBox CreateTextBox() + { + NumericTextBox textBox = new NumericTextBox(); + textBox.AllowDecimalSeparator = AllowDecimalSeparator; + textBox.AllowNegativeSign = AllowNegativeSign; + return textBox; + } + + protected override void DoApplyChanges(TreeNodeAdv node, Control editor) + { + SetValue(node, (editor as NumericTextBox).DecimalValue); + } + } +} diff -r 3145aadca3d2 -r 0c551e8818e0 External/Aga.Controls/Tree/NodeControls/NodeEventArgs.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/External/Aga.Controls/Tree/NodeControls/NodeEventArgs.cs Sun May 27 15:16:19 2012 +0000 @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Aga.Controls.Tree.NodeControls +{ + public class NodeEventArgs : EventArgs + { + private TreeNodeAdv _node; + public TreeNodeAdv Node + { + get { return _node; } + } + + public NodeEventArgs(TreeNodeAdv node) + { + _node = node; + } + } +} diff -r 3145aadca3d2 -r 0c551e8818e0 External/Aga.Controls/Tree/NodeControls/NodeIcon.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/External/Aga.Controls/Tree/NodeControls/NodeIcon.cs Sun May 27 15:16:19 2012 +0000 @@ -0,0 +1,99 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Drawing; +using System.Windows.Forms; +using Aga.Controls.Properties; +using System.ComponentModel; + +namespace Aga.Controls.Tree.NodeControls +{ + public class NodeIcon : BindableControl + { + public NodeIcon() + { + LeftMargin = 1; + } + + public override Size MeasureSize(TreeNodeAdv node, DrawContext context) + { + Image image = GetIcon(node); + if (image != null) + return image.Size; + else + return Size.Empty; + } + + + public override void Draw(TreeNodeAdv node, DrawContext context) + { + Image image = GetIcon(node); + if (image != null) + { + Rectangle r = GetBounds(node, context); + if ( image.Width > 0 && image.Height > 0 ) + { + switch (_scaleMode) + { + case ImageScaleMode.Fit: + context.Graphics.DrawImage(image, r); + break; + case ImageScaleMode.ScaleDown: + { + float factor = Math.Min((float)r.Width / (float)image.Width, (float)r.Height / (float)image.Height); + if (factor < 1) + context.Graphics.DrawImage(image, r.X, r.Y, image.Width * factor, image.Height * factor); + else + context.Graphics.DrawImage(image, r.X, r.Y, image.Width, image.Height); + } break; + case ImageScaleMode.ScaleUp: + { + float factor = Math.Max((float)r.Width / (float)image.Width, (float)r.Height / (float)image.Height); + if (factor > 1) + context.Graphics.DrawImage(image, r.X, r.Y, image.Width * factor, image.Height * factor); + else + context.Graphics.DrawImage(image, r.X, r.Y, image.Width, image.Height); + } break; + case ImageScaleMode.AlwaysScale: + { + float fx = (float)r.Width / (float)image.Width; + float fy = (float)r.Height / (float)image.Height; + if (Math.Min(fx, fy) < 1) + { //scale down + float factor = Math.Min(fx, fy); + context.Graphics.DrawImage(image, r.X, r.Y, image.Width * factor, image.Height * factor); + } + else if (Math.Max(fx, fy) > 1) + { + float factor = Math.Max(fx, fy); + context.Graphics.DrawImage(image, r.X, r.Y, image.Width * factor, image.Height * factor); + } + else + context.Graphics.DrawImage(image, r.X, r.Y, image.Width, image.Height); + } break; + case ImageScaleMode.Clip: + default: + context.Graphics.DrawImage(image, r.X, r.Y, image.Width, image.Height); + break; + } + } + + } + } + + protected virtual Image GetIcon(TreeNodeAdv node) + { + return GetValue(node) as Image; + } + + private ImageScaleMode _scaleMode = ImageScaleMode.Clip; + [DefaultValue("Clip"), Category("Appearance")] + public ImageScaleMode ScaleMode + { + get { return _scaleMode; } + set { _scaleMode = value; } + } + + + } +} diff -r 3145aadca3d2 -r 0c551e8818e0 External/Aga.Controls/Tree/NodeControls/NodeIntegerTextBox.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/External/Aga.Controls/Tree/NodeControls/NodeIntegerTextBox.cs Sun May 27 15:16:19 2012 +0000 @@ -0,0 +1,37 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.ComponentModel; +using System.Windows.Forms; + +namespace Aga.Controls.Tree.NodeControls +{ + + public class NodeIntegerTextBox : NodeTextBox + { + private bool _allowNegativeSign = true; + [DefaultValue(true)] + public bool AllowNegativeSign + { + get { return _allowNegativeSign; } + set { _allowNegativeSign = value; } + } + + public NodeIntegerTextBox() + { + } + + protected override TextBox CreateTextBox() + { + NumericTextBox textBox = new NumericTextBox(); + textBox.AllowDecimalSeparator = false; + textBox.AllowNegativeSign = AllowNegativeSign; + return textBox; + } + + protected override void DoApplyChanges(TreeNodeAdv node, Control editor) + { + SetValue(node, (editor as NumericTextBox).IntValue); + } + } +} diff -r 3145aadca3d2 -r 0c551e8818e0 External/Aga.Controls/Tree/NodeControls/NodeNumericUpDown.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/External/Aga.Controls/Tree/NodeControls/NodeNumericUpDown.cs Sun May 27 15:16:19 2012 +0000 @@ -0,0 +1,115 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Drawing; +using System.Windows.Forms; +using System.Reflection; +using System.ComponentModel; +using System.Drawing.Design; + +namespace Aga.Controls.Tree.NodeControls +{ + public class NodeNumericUpDown : BaseTextControl + { + #region Properties + + private int _editorWidth = 100; + [DefaultValue(100)] + public int EditorWidth + { + get { return _editorWidth; } + set { _editorWidth = value; } + } + + private int _decimalPlaces = 0; + [Category("Data"), DefaultValue(0)] + public int DecimalPlaces + { + get + { + return this._decimalPlaces; + } + set + { + this._decimalPlaces = value; + } + } + + private decimal _increment = 1; + [Category("Data"), DefaultValue(1)] + public decimal Increment + { + get + { + return this._increment; + } + set + { + this._increment = value; + } + } + + private decimal _minimum = 0; + [Category("Data"), DefaultValue(0)] + public decimal Minimum + { + get + { + return _minimum; + } + set + { + _minimum = value; + } + } + + private decimal _maximum = 100; + [Category("Data"), DefaultValue(100)] + public decimal Maximum + { + get + { + return this._maximum; + } + set + { + this._maximum = value; + } + } + + #endregion + + public NodeNumericUpDown() + { + } + + protected override Size CalculateEditorSize(EditorContext context) + { + if (Parent.UseColumns) + return context.Bounds.Size; + else + return new Size(EditorWidth, context.Bounds.Height); + } + + protected override Control CreateEditor(TreeNodeAdv node) + { + NumericUpDown num = new NumericUpDown(); + num.Increment = Increment; + num.DecimalPlaces = DecimalPlaces; + num.Minimum = Minimum; + num.Maximum = Maximum; + num.Value = (decimal)GetValue(node); + SetEditControlProperties(num, node); + return num; + } + + protected override void DisposeEditor(Control editor) + { + } + + protected override void DoApplyChanges(TreeNodeAdv node, Control editor) + { + SetValue(node, (editor as NumericUpDown).Value); + } + } +} diff -r 3145aadca3d2 -r 0c551e8818e0 External/Aga.Controls/Tree/NodeControls/NodePlusMinus.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/External/Aga.Controls/Tree/NodeControls/NodePlusMinus.cs Sun May 27 15:16:19 2012 +0000 @@ -0,0 +1,94 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Drawing; +using Aga.Controls.Properties; +using System.Windows.Forms; +using System.Windows.Forms.VisualStyles; + +namespace Aga.Controls.Tree.NodeControls +{ + internal class NodePlusMinus : NodeControl + { + public const int ImageSize = 9; + public const int Width = 16; + private Bitmap _plus; + private Bitmap _minus; + + private VisualStyleRenderer _openedRenderer; + private VisualStyleRenderer OpenedRenderer + { + get + { + if (_openedRenderer == null) + _openedRenderer = new VisualStyleRenderer(VisualStyleElement.TreeView.Glyph.Opened); + return _openedRenderer; + + } + } + + private VisualStyleRenderer _closedRenderer; + private VisualStyleRenderer ClosedRenderer + { + get + { + if (_closedRenderer == null) + _closedRenderer = new VisualStyleRenderer(VisualStyleElement.TreeView.Glyph.Closed); + return _closedRenderer; + } + } + + public NodePlusMinus() + { + _plus = Resources.plus; + _minus = Resources.minus; + } + + public override Size MeasureSize(TreeNodeAdv node, DrawContext context) + { + return new Size(Width, Width); + } + + public override void Draw(TreeNodeAdv node, DrawContext context) + { + if (node.CanExpand) + { + Rectangle r = context.Bounds; + int dy = (int)Math.Round((float)(r.Height - ImageSize) / 2); + if (Application.RenderWithVisualStyles) + { + VisualStyleRenderer renderer; + if (node.IsExpanded) + renderer = OpenedRenderer; + else + renderer = ClosedRenderer; + renderer.DrawBackground(context.Graphics, new Rectangle(r.X, r.Y + dy, ImageSize, ImageSize)); + } + else + { + Image img; + if (node.IsExpanded) + img = _minus; + else + img = _plus; + context.Graphics.DrawImageUnscaled(img, new Point(r.X, r.Y + dy)); + } + } + } + + public override void MouseDown(TreeNodeAdvMouseEventArgs args) + { + if (args.Button == MouseButtons.Left) + { + args.Handled = true; + if (args.Node.CanExpand) + args.Node.IsExpanded = !args.Node.IsExpanded; + } + } + + public override void MouseDoubleClick(TreeNodeAdvMouseEventArgs args) + { + args.Handled = true; // Supress expand/collapse when double click on plus/minus + } + } +} diff -r 3145aadca3d2 -r 0c551e8818e0 External/Aga.Controls/Tree/NodeControls/NodeStateIcon.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/External/Aga.Controls/Tree/NodeControls/NodeStateIcon.cs Sun May 27 15:16:19 2012 +0000 @@ -0,0 +1,41 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Drawing; +using Aga.Controls.Properties; + +namespace Aga.Controls.Tree.NodeControls +{ + public class NodeStateIcon: NodeIcon + { + private Image _leaf; + private Image _opened; + private Image _closed; + + public NodeStateIcon() + { + _leaf = MakeTransparent(Resources.Leaf); + _opened = MakeTransparent(Resources.Folder); + _closed = MakeTransparent(Resources.FolderClosed); + } + + private static Image MakeTransparent(Bitmap bitmap) + { + bitmap.MakeTransparent(bitmap.GetPixel(0,0)); + return bitmap; + } + + protected override Image GetIcon(TreeNodeAdv node) + { + Image icon = base.GetIcon(node); + if (icon != null) + return icon; + else if (node.IsLeaf) + return _leaf; + else if (node.CanExpand && node.IsExpanded) + return _opened; + else + return _closed; + } + } +} diff -r 3145aadca3d2 -r 0c551e8818e0 External/Aga.Controls/Tree/NodeControls/NodeTextBox.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/External/Aga.Controls/Tree/NodeControls/NodeTextBox.cs Sun May 27 15:16:19 2012 +0000 @@ -0,0 +1,126 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Drawing; +using System.Windows.Forms; +using System.Reflection; +using System.ComponentModel; + +namespace Aga.Controls.Tree.NodeControls +{ + public class NodeTextBox : BaseTextControl + { + private const int MinTextBoxWidth = 30; + + public NodeTextBox() + { + } + + protected override Size CalculateEditorSize(EditorContext context) + { + if (Parent.UseColumns) + return context.Bounds.Size; + else + { + Size size = GetLabelSize(context.CurrentNode, context.DrawContext, _label); + int width = Math.Max(size.Width + Font.Height, MinTextBoxWidth); // reserve a place for new typed character + return new Size(width, size.Height); + } + } + + public override void KeyDown(KeyEventArgs args) + { + if (args.KeyCode == Keys.F2 && Parent.CurrentNode != null && EditEnabled) + { + args.Handled = true; + BeginEdit(); + } + } + + protected override Control CreateEditor(TreeNodeAdv node) + { + TextBox textBox = CreateTextBox(); + textBox.TextAlign = TextAlign; + textBox.Text = GetLabel(node); + textBox.BorderStyle = BorderStyle.FixedSingle; + textBox.TextChanged += EditorTextChanged; + textBox.KeyDown += EditorKeyDown; + _label = textBox.Text; + SetEditControlProperties(textBox, node); + return textBox; + } + + protected virtual TextBox CreateTextBox() + { + return new TextBox(); + } + + protected override void DisposeEditor(Control editor) + { + var textBox = editor as TextBox; + textBox.TextChanged -= EditorTextChanged; + textBox.KeyDown -= EditorKeyDown; + } + + private void EditorKeyDown(object sender, KeyEventArgs e) + { + if (e.KeyCode == Keys.Escape) + EndEdit(false); + else if (e.KeyCode == Keys.Enter) + EndEdit(true); + } + + private string _label; + private void EditorTextChanged(object sender, EventArgs e) + { + var textBox = sender as TextBox; + _label = textBox.Text; + Parent.UpdateEditorBounds(); + } + + protected override void DoApplyChanges(TreeNodeAdv node, Control editor) + { + var label = (editor as TextBox).Text; + string oldLabel = GetLabel(node); + if (oldLabel != label) + { + SetLabel(node, label); + OnLabelChanged(node.Tag, oldLabel, label); + } + } + + public override void Cut(Control control) + { + (control as TextBox).Cut(); + } + + public override void Copy(Control control) + { + (control as TextBox).Copy(); + } + + public override void Paste(Control control) + { + (control as TextBox).Paste(); + } + + public override void Delete(Control control) + { + var textBox = control as TextBox; + int len = Math.Max(textBox.SelectionLength, 1); + if (textBox.SelectionStart < textBox.Text.Length) + { + int start = textBox.SelectionStart; + textBox.Text = textBox.Text.Remove(textBox.SelectionStart, len); + textBox.SelectionStart = start; + } + } + + public event EventHandler LabelChanged; + protected void OnLabelChanged(object subject, string oldLabel, string newLabel) + { + if (LabelChanged != null) + LabelChanged(this, new LabelEventArgs(subject, oldLabel, newLabel)); + } + } +} diff -r 3145aadca3d2 -r 0c551e8818e0 External/Aga.Controls/Tree/SortedTreeModel.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/External/Aga.Controls/Tree/SortedTreeModel.cs Sun May 27 15:16:19 2012 +0000 @@ -0,0 +1,81 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Collections; + +namespace Aga.Controls.Tree +{ + public class SortedTreeModel: TreeModelBase + { + private ITreeModel _innerModel; + public ITreeModel InnerModel + { + get { return _innerModel; } + } + + private IComparer _comparer; + public IComparer Comparer + { + get { return _comparer; } + set + { + _comparer = value; + OnStructureChanged(new TreePathEventArgs(TreePath.Empty)); + } + } + + public SortedTreeModel(ITreeModel innerModel) + { + _innerModel = innerModel; + _innerModel.NodesChanged += new EventHandler(_innerModel_NodesChanged); + _innerModel.NodesInserted += new EventHandler(_innerModel_NodesInserted); + _innerModel.NodesRemoved += new EventHandler(_innerModel_NodesRemoved); + _innerModel.StructureChanged += new EventHandler(_innerModel_StructureChanged); + } + + void _innerModel_StructureChanged(object sender, TreePathEventArgs e) + { + OnStructureChanged(e); + } + + void _innerModel_NodesRemoved(object sender, TreeModelEventArgs e) + { + OnStructureChanged(new TreePathEventArgs(e.Path)); + } + + void _innerModel_NodesInserted(object sender, TreeModelEventArgs e) + { + OnStructureChanged(new TreePathEventArgs(e.Path)); + } + + void _innerModel_NodesChanged(object sender, TreeModelEventArgs e) + { + OnStructureChanged(new TreePathEventArgs(e.Path)); + } + + public override IEnumerable GetChildren(TreePath treePath) + { + if (Comparer != null) + { + ArrayList list = new ArrayList(); + IEnumerable res = InnerModel.GetChildren(treePath); + if (res != null) + { + foreach (object obj in res) + list.Add(obj); + list.Sort(Comparer); + return list; + } + else + return null; + } + else + return InnerModel.GetChildren(treePath); + } + + public override bool IsLeaf(TreePath treePath) + { + return InnerModel.IsLeaf(treePath); + } + } +} diff -r 3145aadca3d2 -r 0c551e8818e0 External/Aga.Controls/Tree/TreeColumn.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/External/Aga.Controls/Tree/TreeColumn.cs Sun May 27 15:16:19 2012 +0000 @@ -0,0 +1,371 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.ComponentModel; +using System.Windows.Forms; +using System.Drawing; +using System.Windows.Forms.VisualStyles; +using System.Drawing.Imaging; + +namespace Aga.Controls.Tree +{ + [TypeConverter(typeof(TreeColumn.TreeColumnConverter)), DesignTimeVisible(false), ToolboxItem(false)] + public class TreeColumn : Component + { + private class TreeColumnConverter : ComponentConverter + { + public TreeColumnConverter() + : base(typeof(TreeColumn)) + { + } + + public override bool GetPropertiesSupported(ITypeDescriptorContext context) + { + return false; + } + } + + private const int HeaderLeftMargin = 5; + private const int HeaderRightMargin = 5; + private const int SortOrderMarkMargin = 8; + + private TextFormatFlags _headerFlags; + private TextFormatFlags _baseHeaderFlags = TextFormatFlags.NoPadding | + TextFormatFlags.EndEllipsis | + TextFormatFlags.VerticalCenter | + TextFormatFlags.PreserveGraphicsTranslateTransform; + + #region Properties + + private TreeColumnCollection _owner; + internal TreeColumnCollection Owner + { + get { return _owner; } + set { _owner = value; } + } + + [Browsable(false)] + public int Index + { + get + { + if (Owner != null) + return Owner.IndexOf(this); + else + return -1; + } + } + + private string _header; + [Localizable(true)] + public string Header + { + get { return _header; } + set + { + _header = value; + OnHeaderChanged(); + } + } + + private string _tooltipText; + [Localizable(true)] + public string TooltipText + { + get { return _tooltipText; } + set { _tooltipText = value; } + } + + private int _width; + [DefaultValue(50), Localizable(true)] + public int Width + { + get + { + return _width; + } + set + { + if (_width != value) + { + _width = Math.Max(MinColumnWidth, value); + if (_maxColumnWidth > 0) + { + _width = Math.Min(_width, MaxColumnWidth); + } + OnWidthChanged(); + } + } + } + + private int _minColumnWidth; + [DefaultValue(0)] + public int MinColumnWidth + { + get { return _minColumnWidth; } + set + { + if (value < 0) + throw new ArgumentOutOfRangeException("value"); + + _minColumnWidth = value; + Width = Math.Max(value, Width); + } + } + + private int _maxColumnWidth; + [DefaultValue(0)] + public int MaxColumnWidth + { + get { return _maxColumnWidth; } + set + { + if (value < 0) + throw new ArgumentOutOfRangeException("value"); + + _maxColumnWidth = value; + if (value > 0) + Width = Math.Min(value, _width); + } + } + + private bool _visible = true; + [DefaultValue(true)] + public bool IsVisible + { + get { return _visible; } + set + { + _visible = value; + OnIsVisibleChanged(); + } + } + + private HorizontalAlignment _textAlign = HorizontalAlignment.Left; + [DefaultValue(HorizontalAlignment.Left)] + public HorizontalAlignment TextAlign + { + get { return _textAlign; } + set + { + if (value != _textAlign) + { + _textAlign = value; + _headerFlags = _baseHeaderFlags | TextHelper.TranslateAligmentToFlag(value); + OnHeaderChanged(); + } + } + } + + private bool _sortable = false; + [DefaultValue(false)] + public bool Sortable + { + get { return _sortable; } + set { _sortable = value; } + } + + private SortOrder _sort_order = SortOrder.None; + public SortOrder SortOrder + { + get { return _sort_order; } + set + { + if (value == _sort_order) + return; + _sort_order = value; + OnSortOrderChanged(); + } + } + + public Size SortMarkSize + { + get + { + if (Application.RenderWithVisualStyles) + return new Size(9, 5); + else + return new Size(7, 4); + } + } + #endregion + + public TreeColumn(): + this(string.Empty, 50) + { + } + + public TreeColumn(string header, int width) + { + _header = header; + _width = width; + _headerFlags = _baseHeaderFlags | TextFormatFlags.Left; + } + + public override string ToString() + { + if (string.IsNullOrEmpty(Header)) + return GetType().Name; + else + return Header; + } + + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + } + + #region Draw + + private static VisualStyleRenderer _normalRenderer; + private static VisualStyleRenderer _pressedRenderer; + private static VisualStyleRenderer _hotRenderer; + + private static void CreateRenderers() + { + if (Application.RenderWithVisualStyles && _normalRenderer == null) + { + _normalRenderer = new VisualStyleRenderer(VisualStyleElement.Header.Item.Normal); + _pressedRenderer = new VisualStyleRenderer(VisualStyleElement.Header.Item.Pressed); + _hotRenderer = new VisualStyleRenderer(VisualStyleElement.Header.Item.Hot); + } + } + + internal Bitmap CreateGhostImage(Rectangle bounds, Font font) + { + Bitmap b = new Bitmap(bounds.Width, bounds.Height, PixelFormat.Format32bppArgb); + Graphics gr = Graphics.FromImage(b); + gr.FillRectangle(SystemBrushes.ControlDark, bounds); + DrawContent(gr, bounds, font); + BitmapHelper.SetAlphaChanelValue(b, 150); + return b; + } + + internal void Draw(Graphics gr, Rectangle bounds, Font font, bool pressed, bool hot) + { + DrawBackground(gr, bounds, pressed, hot); + DrawContent(gr, bounds, font); + } + + private void DrawContent(Graphics gr, Rectangle bounds, Font font) + { + Rectangle innerBounds = new Rectangle(bounds.X + HeaderLeftMargin, bounds.Y, + bounds.Width - HeaderLeftMargin - HeaderRightMargin, + bounds.Height); + + if (SortOrder != SortOrder.None) + innerBounds.Width -= (SortMarkSize.Width + SortOrderMarkMargin); + + Size maxTextSize = TextRenderer.MeasureText(gr, Header, font, innerBounds.Size, TextFormatFlags.NoPadding); + Size textSize = TextRenderer.MeasureText(gr, Header, font, innerBounds.Size, _baseHeaderFlags); + + if (SortOrder != SortOrder.None) + { + int tw = Math.Min(textSize.Width, innerBounds.Size.Width); + + int x = 0; + if (TextAlign == HorizontalAlignment.Left) + x = innerBounds.X + tw + SortOrderMarkMargin; + else if (TextAlign == HorizontalAlignment.Right) + x = innerBounds.Right + SortOrderMarkMargin; + else + x = innerBounds.X + tw + (innerBounds.Width - tw) / 2 + SortOrderMarkMargin; + DrawSortMark(gr, bounds, x); + } + + if (textSize.Width < maxTextSize.Width) + TextRenderer.DrawText(gr, Header, font, innerBounds, SystemColors.ControlText, _baseHeaderFlags | TextFormatFlags.Left); + else + TextRenderer.DrawText(gr, Header, font, innerBounds, SystemColors.ControlText, _headerFlags); + } + + private void DrawSortMark(Graphics gr, Rectangle bounds, int x) + { + int y = bounds.Y + bounds.Height / 2 - 2; + x = Math.Max(x, bounds.X + SortOrderMarkMargin); + + int w2 = SortMarkSize.Width / 2; + if (SortOrder == SortOrder.Ascending) + { + Point[] points = new Point[] { new Point(x, y), new Point(x + SortMarkSize.Width, y), new Point(x + w2, y + SortMarkSize.Height) }; + gr.FillPolygon(SystemBrushes.ControlDark, points); + } + else if (SortOrder == SortOrder.Descending) + { + Point[] points = new Point[] { new Point(x - 1, y + SortMarkSize.Height), new Point(x + SortMarkSize.Width, y + SortMarkSize.Height), new Point(x + w2, y - 1) }; + gr.FillPolygon(SystemBrushes.ControlDark, points); + } + } + + internal static void DrawDropMark(Graphics gr, Rectangle rect) + { + gr.FillRectangle(SystemBrushes.HotTrack, rect.X-1, rect.Y, 2, rect.Height); + } + + internal static void DrawBackground(Graphics gr, Rectangle bounds, bool pressed, bool hot) + { + if (Application.RenderWithVisualStyles) + { + CreateRenderers(); + if (pressed) + _pressedRenderer.DrawBackground(gr, bounds); + else if (hot) + _hotRenderer.DrawBackground(gr, bounds); + else + _normalRenderer.DrawBackground(gr, bounds); + } + else + { + gr.FillRectangle(SystemBrushes.Control, bounds); + Pen p1 = SystemPens.ControlLightLight; + Pen p2 = SystemPens.ControlDark; + Pen p3 = SystemPens.ControlDarkDark; + if (pressed) + gr.DrawRectangle(p2, bounds.X, bounds.Y, bounds.Width, bounds.Height); + else + { + gr.DrawLine(p1, bounds.X, bounds.Y, bounds.Right, bounds.Y); + gr.DrawLine(p3, bounds.X, bounds.Bottom, bounds.Right, bounds.Bottom); + gr.DrawLine(p3, bounds.Right - 1, bounds.Y, bounds.Right - 1, bounds.Bottom - 1); + gr.DrawLine(p1, bounds.Left, bounds.Y + 1, bounds.Left, bounds.Bottom - 2); + gr.DrawLine(p2, bounds.Right - 2, bounds.Y + 1, bounds.Right - 2, bounds.Bottom - 2); + gr.DrawLine(p2, bounds.X, bounds.Bottom - 1, bounds.Right - 2, bounds.Bottom - 1); + } + } + } + + #endregion + + #region Events + + public event EventHandler HeaderChanged; + private void OnHeaderChanged() + { + if (HeaderChanged != null) + HeaderChanged(this, EventArgs.Empty); + } + + public event EventHandler SortOrderChanged; + private void OnSortOrderChanged() + { + if (SortOrderChanged != null) + SortOrderChanged(this, EventArgs.Empty); + } + + public event EventHandler IsVisibleChanged; + private void OnIsVisibleChanged() + { + if (IsVisibleChanged != null) + IsVisibleChanged(this, EventArgs.Empty); + } + + public event EventHandler WidthChanged; + private void OnWidthChanged() + { + if (WidthChanged != null) + WidthChanged(this, EventArgs.Empty); + } + + #endregion + } +} diff -r 3145aadca3d2 -r 0c551e8818e0 External/Aga.Controls/Tree/TreeColumnCollection.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/External/Aga.Controls/Tree/TreeColumnCollection.cs Sun May 27 15:16:19 2012 +0000 @@ -0,0 +1,98 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Collections.ObjectModel; +using System.ComponentModel; +using System.Windows.Forms; + +namespace Aga.Controls.Tree +{ + internal class TreeColumnCollection : Collection + { + private TreeViewAdv _treeView; + + public TreeColumnCollection(TreeViewAdv treeView) + { + _treeView = treeView; + } + + protected override void InsertItem(int index, TreeColumn item) + { + base.InsertItem(index, item); + BindEvents(item); + _treeView.UpdateColumns(); + } + + protected override void RemoveItem(int index) + { + UnbindEvents(this[index]); + base.RemoveItem(index); + _treeView.UpdateColumns(); + } + + protected override void SetItem(int index, TreeColumn item) + { + UnbindEvents(this[index]); + base.SetItem(index, item); + item.Owner = this; + BindEvents(item); + _treeView.UpdateColumns(); + } + + protected override void ClearItems() + { + foreach (TreeColumn c in Items) + UnbindEvents(c); + Items.Clear(); + _treeView.UpdateColumns(); + } + + private void BindEvents(TreeColumn item) + { + item.Owner = this; + item.HeaderChanged += HeaderChanged; + item.IsVisibleChanged += IsVisibleChanged; + item.WidthChanged += WidthChanged; + item.SortOrderChanged += SortOrderChanged; + } + + private void UnbindEvents(TreeColumn item) + { + item.Owner = null; + item.HeaderChanged -= HeaderChanged; + item.IsVisibleChanged -= IsVisibleChanged; + item.WidthChanged -= WidthChanged; + item.SortOrderChanged -= SortOrderChanged; + } + + void SortOrderChanged(object sender, EventArgs e) + { + TreeColumn changed = sender as TreeColumn; + //Only one column at a time can have a sort property set + if (changed.SortOrder != SortOrder.None) + { + foreach (TreeColumn col in this) + { + if (col != changed) + col.SortOrder = SortOrder.None; + } + } + _treeView.UpdateHeaders(); + } + + void WidthChanged(object sender, EventArgs e) + { + _treeView.ChangeColumnWidth(sender as TreeColumn); + } + + void IsVisibleChanged(object sender, EventArgs e) + { + _treeView.FullUpdate(); + } + + void HeaderChanged(object sender, EventArgs e) + { + _treeView.UpdateView(); + } + } +} diff -r 3145aadca3d2 -r 0c551e8818e0 External/Aga.Controls/Tree/TreeColumnEventArgs.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/External/Aga.Controls/Tree/TreeColumnEventArgs.cs Sun May 27 15:16:19 2012 +0000 @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Aga.Controls.Tree +{ + public class TreeColumnEventArgs: EventArgs + { + private TreeColumn _column; + public TreeColumn Column + { + get { return _column; } + } + + public TreeColumnEventArgs(TreeColumn column) + { + _column = column; + } + } +} diff -r 3145aadca3d2 -r 0c551e8818e0 External/Aga.Controls/Tree/TreeListAdapter.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/External/Aga.Controls/Tree/TreeListAdapter.cs Sun May 27 15:16:19 2012 +0000 @@ -0,0 +1,65 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Aga.Controls.Tree +{ + /// + /// Converts IEnumerable interface to ITreeModel. + /// Allows to display a plain list in the TreeView + /// + public class TreeListAdapter : ITreeModel + { + private System.Collections.IEnumerable _list; + + public TreeListAdapter(System.Collections.IEnumerable list) + { + _list = list; + } + + #region ITreeModel Members + + public System.Collections.IEnumerable GetChildren(TreePath treePath) + { + if (treePath.IsEmpty()) + return _list; + else + return null; + } + + public bool IsLeaf(TreePath treePath) + { + return true; + } + + public event EventHandler NodesChanged; + public void OnNodesChanged(TreeModelEventArgs args) + { + if (NodesChanged != null) + NodesChanged(this, args); + } + + public event EventHandler StructureChanged; + public void OnStructureChanged(TreePathEventArgs args) + { + if (StructureChanged != null) + StructureChanged(this, args); + } + + public event EventHandler NodesInserted; + public void OnNodeInserted(TreeModelEventArgs args) + { + if (NodesInserted != null) + NodesInserted(this, args); + } + + public event EventHandler NodesRemoved; + public void OnNodeRemoved(TreeModelEventArgs args) + { + if (NodesRemoved != null) + NodesRemoved(this, args); + } + + #endregion + } +} diff -r 3145aadca3d2 -r 0c551e8818e0 External/Aga.Controls/Tree/TreeModel.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/External/Aga.Controls/Tree/TreeModel.cs Sun May 27 15:16:19 2012 +0000 @@ -0,0 +1,127 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Collections.ObjectModel; + +namespace Aga.Controls.Tree +{ + /// + /// Provides a simple ready to use implementation of . Warning: this class is not optimized + /// to work with big amount of data. In this case create you own implementation of ITreeModel, and pay attention + /// on GetChildren and IsLeaf methods. + /// + public class TreeModel : ITreeModel + { + private Node _root; + public Node Root + { + get { return _root; } + } + + public Collection Nodes + { + get { return _root.Nodes; } + } + + public TreeModel() + { + _root = new Node(); + _root.Model = this; + } + + public TreePath GetPath(Node node) + { + if (node == _root) + return TreePath.Empty; + else + { + Stack stack = new Stack(); + while (node != _root) + { + stack.Push(node); + node = node.Parent; + } + return new TreePath(stack.ToArray()); + } + } + + public Node FindNode(TreePath path) + { + if (path.IsEmpty()) + return _root; + else + return FindNode(_root, path, 0); + } + + private Node FindNode(Node root, TreePath path, int level) + { + foreach (Node node in root.Nodes) + if (node == path.FullPath[level]) + { + if (level == path.FullPath.Length - 1) + return node; + else + return FindNode(node, path, level + 1); + } + return null; + } + + #region ITreeModel Members + + public System.Collections.IEnumerable GetChildren(TreePath treePath) + { + Node node = FindNode(treePath); + if (node != null) + foreach (Node n in node.Nodes) + yield return n; + else + yield break; + } + + public bool IsLeaf(TreePath treePath) + { + Node node = FindNode(treePath); + if (node != null) + return node.IsLeaf; + else + throw new ArgumentException("treePath"); + } + + public event EventHandler NodesChanged; + internal void OnNodesChanged(TreeModelEventArgs args) + { + if (NodesChanged != null) + NodesChanged(this, args); + } + + public event EventHandler StructureChanged; + public void OnStructureChanged(TreePathEventArgs args) + { + if (StructureChanged != null) + StructureChanged(this, args); + } + + public event EventHandler NodesInserted; + internal void OnNodeInserted(Node parent, int index, Node node) + { + if (NodesInserted != null) + { + TreeModelEventArgs args = new TreeModelEventArgs(GetPath(parent), new int[] { index }, new object[] { node }); + NodesInserted(this, args); + } + + } + + public event EventHandler NodesRemoved; + internal void OnNodeRemoved(Node parent, int index, Node node) + { + if (NodesRemoved != null) + { + TreeModelEventArgs args = new TreeModelEventArgs(GetPath(parent), new int[] { index }, new object[] { node }); + NodesRemoved(this, args); + } + } + + #endregion + } +} diff -r 3145aadca3d2 -r 0c551e8818e0 External/Aga.Controls/Tree/TreeModelBase.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/External/Aga.Controls/Tree/TreeModelBase.cs Sun May 27 15:16:19 2012 +0000 @@ -0,0 +1,46 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Aga.Controls.Tree +{ + public abstract class TreeModelBase: ITreeModel + { + public abstract System.Collections.IEnumerable GetChildren(TreePath treePath); + public abstract bool IsLeaf(TreePath treePath); + + + public event EventHandler NodesChanged; + protected void OnNodesChanged(TreeModelEventArgs args) + { + if (NodesChanged != null) + NodesChanged(this, args); + } + + public event EventHandler StructureChanged; + protected void OnStructureChanged(TreePathEventArgs args) + { + if (StructureChanged != null) + StructureChanged(this, args); + } + + public event EventHandler NodesInserted; + protected void OnNodesInserted(TreeModelEventArgs args) + { + if (NodesInserted != null) + NodesInserted(this, args); + } + + public event EventHandler NodesRemoved; + protected void OnNodesRemoved(TreeModelEventArgs args) + { + if (NodesRemoved != null) + NodesRemoved(this, args); + } + + public virtual void Refresh() + { + OnStructureChanged(new TreePathEventArgs(TreePath.Empty)); + } + } +} diff -r 3145aadca3d2 -r 0c551e8818e0 External/Aga.Controls/Tree/TreeModelEventArgs.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/External/Aga.Controls/Tree/TreeModelEventArgs.cs Sun May 27 15:16:19 2012 +0000 @@ -0,0 +1,50 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Aga.Controls.Tree +{ + public class TreeModelEventArgs: TreePathEventArgs + { + private object[] _children; + public object[] Children + { + get { return _children; } + } + + private int[] _indices; + public int[] Indices + { + get { return _indices; } + } + + /// + /// + /// + /// Path to a parent node + /// Child nodes + public TreeModelEventArgs(TreePath parent, object[] children) + : this(parent, null, children) + { + } + + /// + /// + /// + /// Path to a parent node + /// Indices of children in parent nodes collection + /// Child nodes + public TreeModelEventArgs(TreePath parent, int[] indices, object[] children) + : base(parent) + { + if (children == null) + throw new ArgumentNullException(); + + if (indices != null && indices.Length != children.Length) + throw new ArgumentException("indices and children arrays must have the same length"); + + _indices = indices; + _children = children; + } + } +} diff -r 3145aadca3d2 -r 0c551e8818e0 External/Aga.Controls/Tree/TreeNodeAdv.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/External/Aga.Controls/Tree/TreeNodeAdv.cs Sun May 27 15:16:19 2012 +0000 @@ -0,0 +1,443 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Runtime.Serialization; +using System.Security.Permissions; + +namespace Aga.Controls.Tree +{ + [Serializable] + public sealed class TreeNodeAdv : ISerializable + { + #region NodeCollection + private class NodeCollection : Collection + { + private TreeNodeAdv _owner; + + public NodeCollection(TreeNodeAdv owner) + { + _owner = owner; + } + + protected override void ClearItems() + { + while (this.Count != 0) + this.RemoveAt(this.Count - 1); + } + + protected override void InsertItem(int index, TreeNodeAdv item) + { + if (item == null) + throw new ArgumentNullException("item"); + + if (item.Parent != _owner) + { + if (item.Parent != null) + item.Parent.Nodes.Remove(item); + item._parent = _owner; + item._index = index; + for (int i = index; i < Count; i++) + this[i]._index++; + base.InsertItem(index, item); + } + + if (_owner.Tree != null && _owner.Tree.Model == null) + { + _owner.Tree.SmartFullUpdate(); + } + } + + protected override void RemoveItem(int index) + { + TreeNodeAdv item = this[index]; + item._parent = null; + item._index = -1; + for (int i = index + 1; i < Count; i++) + this[i]._index--; + base.RemoveItem(index); + + if (_owner.Tree != null && _owner.Tree.Model == null) + { + _owner.Tree.UpdateSelection(); + _owner.Tree.SmartFullUpdate(); + } + } + + protected override void SetItem(int index, TreeNodeAdv item) + { + if (item == null) + throw new ArgumentNullException("item"); + RemoveAt(index); + InsertItem(index, item); + } + } + #endregion + + #region Events + + public event EventHandler Collapsing; + internal void OnCollapsing() + { + if (Collapsing != null) + Collapsing(this, new TreeViewAdvEventArgs(this)); + } + + public event EventHandler Collapsed; + internal void OnCollapsed() + { + if (Collapsed != null) + Collapsed(this, new TreeViewAdvEventArgs(this)); + } + + public event EventHandler Expanding; + internal void OnExpanding() + { + if (Expanding != null) + Expanding(this, new TreeViewAdvEventArgs(this)); + } + + public event EventHandler Expanded; + internal void OnExpanded() + { + if (Expanded != null) + Expanded(this, new TreeViewAdvEventArgs(this)); + } + + #endregion + + #region Properties + + private TreeViewAdv _tree; + public TreeViewAdv Tree + { + get { return _tree; } + } + + private int _row; + public int Row + { + get { return _row; } + internal set { _row = value; } + } + + private int _index = -1; + public int Index + { + get + { + return _index; + } + } + + private bool _isSelected; + public bool IsSelected + { + get { return _isSelected; } + set + { + if (_isSelected != value) + { + if (Tree.IsMyNode(this)) + { + //_tree.OnSelectionChanging + if (value) + { + if (!_tree.Selection.Contains(this)) + _tree.Selection.Add(this); + + if (_tree.Selection.Count == 1) + _tree.CurrentNode = this; + } + else + _tree.Selection.Remove(this); + _tree.UpdateView(); + _tree.OnSelectionChanged(); + } + _isSelected = value; + } + } + } + + /// + /// Returns true if all parent nodes of this node are expanded. + /// + internal bool IsVisible + { + get + { + TreeNodeAdv node = _parent; + while (node != null) + { + if (!node.IsExpanded) + return false; + node = node.Parent; + } + return true; + } + } + + private bool _isLeaf; + public bool IsLeaf + { + get { return _isLeaf; } + internal set { _isLeaf = value; } + } + + private bool _isExpandedOnce; + public bool IsExpandedOnce + { + get { return _isExpandedOnce; } + internal set { _isExpandedOnce = value; } + } + + private bool _isExpanded; + public bool IsExpanded + { + get { return _isExpanded; } + set + { + if (value) + Expand(); + else + Collapse(); + } + } + + internal void AssignIsExpanded(bool value) + { + _isExpanded = value; + } + + private TreeNodeAdv _parent; + public TreeNodeAdv Parent + { + get { return _parent; } + } + + public int Level + { + get + { + if (_parent == null) + return 0; + else + return _parent.Level + 1; + } + } + + public TreeNodeAdv PreviousNode + { + get + { + if (_parent != null) + { + int index = Index; + if (index > 0) + return _parent.Nodes[index - 1]; + } + return null; + } + } + + public TreeNodeAdv NextNode + { + get + { + if (_parent != null) + { + int index = Index; + if (index < _parent.Nodes.Count - 1) + return _parent.Nodes[index + 1]; + } + return null; + } + } + + internal TreeNodeAdv BottomNode + { + get + { + TreeNodeAdv parent = this.Parent; + if (parent != null) + { + if (parent.NextNode != null) + return parent.NextNode; + else + return parent.BottomNode; + } + return null; + } + } + + internal TreeNodeAdv NextVisibleNode + { + get + { + if (IsExpanded && Nodes.Count > 0) + return Nodes[0]; + else + { + TreeNodeAdv nn = NextNode; + if (nn != null) + return nn; + else + return BottomNode; + } + } + } + + public bool CanExpand + { + get + { + return (Nodes.Count > 0 || (!IsExpandedOnce && !IsLeaf)); + } + } + + private object _tag; + public object Tag + { + get { return _tag; } + } + + private Collection _nodes; + internal Collection Nodes + { + get { return _nodes; } + } + + private ReadOnlyCollection _children; + public ReadOnlyCollection Children + { + get + { + return _children; + } + } + + private int? _rightBounds; + internal int? RightBounds + { + get { return _rightBounds; } + set { _rightBounds = value; } + } + + private int? _height; + internal int? Height + { + get { return _height; } + set { _height = value; } + } + + private bool _isExpandingNow; + internal bool IsExpandingNow + { + get { return _isExpandingNow; } + set { _isExpandingNow = value; } + } + + private bool _autoExpandOnStructureChanged = false; + public bool AutoExpandOnStructureChanged + { + get { return _autoExpandOnStructureChanged; } + set { _autoExpandOnStructureChanged = value; } + } + + #endregion + + public TreeNodeAdv(object tag) + : this(null, tag) + { + } + + internal TreeNodeAdv(TreeViewAdv tree, object tag) + { + _row = -1; + _tree = tree; + _nodes = new NodeCollection(this); + _children = new ReadOnlyCollection(_nodes); + _tag = tag; + } + + public override string ToString() + { + if (Tag != null) + return Tag.ToString(); + else + return base.ToString(); + } + + public void Collapse() + { + if (_isExpanded) + Collapse(true); + } + + public void CollapseAll() + { + Collapse(false); + } + + public void Collapse(bool ignoreChildren) + { + SetIsExpanded(false, ignoreChildren); + } + + public void Expand() + { + if (!_isExpanded) + Expand(true); + } + + public void ExpandAll() + { + Expand(false); + } + + public void Expand(bool ignoreChildren) + { + SetIsExpanded(true, ignoreChildren); + } + + private void SetIsExpanded(bool value, bool ignoreChildren) + { + if (Tree == null) + _isExpanded = value; + else + Tree.SetIsExpanded(this, value, ignoreChildren); + } + + #region ISerializable Members + + private TreeNodeAdv(SerializationInfo info, StreamingContext context) + : this(null, null) + { + int nodesCount = 0; + nodesCount = info.GetInt32("NodesCount"); + _isExpanded = info.GetBoolean("IsExpanded"); + _tag = info.GetValue("Tag", typeof(object)); + + for (int i = 0; i < nodesCount; i++) + { + TreeNodeAdv child = (TreeNodeAdv)info.GetValue("Child" + i, typeof(TreeNodeAdv)); + Nodes.Add(child); + } + + } + + [SecurityPermission(SecurityAction.Demand, SerializationFormatter = true)] + public void GetObjectData(SerializationInfo info, StreamingContext context) + { + info.AddValue("IsExpanded", IsExpanded); + info.AddValue("NodesCount", Nodes.Count); + if ((Tag != null) && Tag.GetType().IsSerializable) + info.AddValue("Tag", Tag, Tag.GetType()); + + for (int i = 0; i < Nodes.Count; i++) + info.AddValue("Child" + i, Nodes[i], typeof(TreeNodeAdv)); + + } + + #endregion + } +} diff -r 3145aadca3d2 -r 0c551e8818e0 External/Aga.Controls/Tree/TreeNodeAdvMouseEventArgs.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/External/Aga.Controls/Tree/TreeNodeAdvMouseEventArgs.cs Sun May 27 15:16:19 2012 +0000 @@ -0,0 +1,59 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Windows.Forms; +using System.Drawing; +using Aga.Controls.Tree.NodeControls; + +namespace Aga.Controls.Tree +{ + public class TreeNodeAdvMouseEventArgs : MouseEventArgs + { + private TreeNodeAdv _node; + public TreeNodeAdv Node + { + get { return _node; } + internal set { _node = value; } + } + + private NodeControl _control; + public NodeControl Control + { + get { return _control; } + internal set { _control = value; } + } + + private Point _viewLocation; + public Point ViewLocation + { + get { return _viewLocation; } + internal set { _viewLocation = value; } + } + + private Keys _modifierKeys; + public Keys ModifierKeys + { + get { return _modifierKeys; } + internal set { _modifierKeys = value; } + } + + private bool _handled; + public bool Handled + { + get { return _handled; } + set { _handled = value; } + } + + private Rectangle _controlBounds; + public Rectangle ControlBounds + { + get { return _controlBounds; } + internal set { _controlBounds = value; } + } + + public TreeNodeAdvMouseEventArgs(MouseEventArgs args) + : base(args.Button, args.Clicks, args.X, args.Y, args.Delta) + { + } + } +} diff -r 3145aadca3d2 -r 0c551e8818e0 External/Aga.Controls/Tree/TreePath.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/External/Aga.Controls/Tree/TreePath.cs Sun May 27 15:16:19 2012 +0000 @@ -0,0 +1,68 @@ +using System; +using System.Text; +using System.Collections.ObjectModel; + +namespace Aga.Controls.Tree +{ + public class TreePath + { + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")] + public static readonly TreePath Empty = new TreePath(); + + private object[] _path; + public object[] FullPath + { + get { return _path; } + } + + public object LastNode + { + get + { + if (_path.Length > 0) + return _path[_path.Length - 1]; + else + return null; + } + } + + public object FirstNode + { + get + { + if (_path.Length > 0) + return _path[0]; + else + return null; + } + } + + public TreePath() + { + _path = new object[0]; + } + + public TreePath(object node) + { + _path = new object[] { node }; + } + + public TreePath(object[] path) + { + _path = path; + } + + public TreePath(TreePath parent, object node) + { + _path = new object[parent.FullPath.Length + 1]; + for (int i = 0; i < _path.Length - 1; i++) + _path[i] = parent.FullPath[i]; + _path[_path.Length - 1] = node; + } + + public bool IsEmpty() + { + return (_path.Length == 0); + } + } +} diff -r 3145aadca3d2 -r 0c551e8818e0 External/Aga.Controls/Tree/TreePathEventArgs.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/External/Aga.Controls/Tree/TreePathEventArgs.cs Sun May 27 15:16:19 2012 +0000 @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Aga.Controls.Tree +{ + public class TreePathEventArgs : EventArgs + { + private TreePath _path; + public TreePath Path + { + get { return _path; } + } + + public TreePathEventArgs() + { + _path = new TreePath(); + } + + public TreePathEventArgs(TreePath path) + { + if (path == null) + throw new ArgumentNullException(); + + _path = path; + } + } +} diff -r 3145aadca3d2 -r 0c551e8818e0 External/Aga.Controls/Tree/TreeViewAdv.Designer.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/External/Aga.Controls/Tree/TreeViewAdv.Designer.cs Sun May 27 15:16:19 2012 +0000 @@ -0,0 +1,69 @@ +using System.Windows.Forms; + +namespace Aga.Controls.Tree +{ + partial class TreeViewAdv + { + private System.ComponentModel.IContainer components = null; + + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + if (_dragBitmap != null) _dragBitmap.Dispose(); + if (_dragTimer != null) _dragTimer.Dispose(); + if (_linePen != null) _linePen.Dispose(); + if (_markPen != null) _markPen.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + this._vScrollBar = new System.Windows.Forms.VScrollBar(); + this._hScrollBar = new System.Windows.Forms.HScrollBar(); + this._errorProvider = new System.Windows.Forms.ErrorProvider(this.components); + ((System.ComponentModel.ISupportInitialize)(this._errorProvider)).BeginInit(); + this.SuspendLayout(); + // + // _vScrollBar + // + this._vScrollBar.LargeChange = 1; + this._vScrollBar.Location = new System.Drawing.Point(0, 0); + this._vScrollBar.Maximum = 0; + this._vScrollBar.Name = "_vScrollBar"; + this._vScrollBar.Size = new System.Drawing.Size(13, 80); + this._vScrollBar.TabIndex = 1; + this._vScrollBar.ValueChanged += new System.EventHandler(this._vScrollBar_ValueChanged); + this._vScrollBar.Scroll += new System.Windows.Forms.ScrollEventHandler(this._vScrollBar_Scroll); + // + // _hScrollBar + // + this._hScrollBar.LargeChange = 1; + this._hScrollBar.Location = new System.Drawing.Point(0, 0); + this._hScrollBar.Maximum = 0; + this._hScrollBar.Name = "_hScrollBar"; + this._hScrollBar.Size = new System.Drawing.Size(80, 13); + this._hScrollBar.TabIndex = 2; + this._hScrollBar.ValueChanged += new System.EventHandler(this._hScrollBar_ValueChanged); + this._hScrollBar.Scroll += new System.Windows.Forms.ScrollEventHandler(this._hScrollBar_Scroll); + // + // TreeViewAdv + // + this.BackColor = System.Drawing.SystemColors.Window; + this.Controls.Add(this._vScrollBar); + this.Controls.Add(this._hScrollBar); + ((System.ComponentModel.ISupportInitialize)(this._errorProvider)).EndInit(); + this.ResumeLayout(false); + + } + #endregion + + private VScrollBar _vScrollBar; + private HScrollBar _hScrollBar; + private ErrorProvider _errorProvider; + } +} diff -r 3145aadca3d2 -r 0c551e8818e0 External/Aga.Controls/Tree/TreeViewAdv.Draw.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/External/Aga.Controls/Tree/TreeViewAdv.Draw.cs Sun May 27 15:16:19 2012 +0000 @@ -0,0 +1,308 @@ +using System; +using System.Drawing; +using System.Diagnostics; +using System.Drawing.Drawing2D; +using System.Windows.Forms; +using Aga.Controls.Tree.NodeControls; + +namespace Aga.Controls.Tree +{ + public partial class TreeViewAdv + { + public void AutoSizeColumn(TreeColumn column) + { + if (!Columns.Contains(column)) + throw new ArgumentException("column"); + + DrawContext context = new DrawContext(); + context.Graphics = Graphics.FromImage(new Bitmap(1, 1)); + context.Font = this.Font; + int res = 0; + for (int row = 0; row < RowCount; row++) + { + if (row < RowMap.Count) + { + int w = 0; + TreeNodeAdv node = RowMap[row]; + foreach (NodeControl nc in NodeControls) + { + if (nc.ParentColumn == column) + w += nc.GetActualSize(node, _measureContext).Width; + } + res = Math.Max(res, w); + } + } + + if (res > 0) + column.Width = res; + } + + private void CreatePens() + { + CreateLinePen(); + CreateMarkPen(); + } + + private void CreateMarkPen() + { + GraphicsPath path = new GraphicsPath(); + path.AddLines(new Point[] { new Point(0, 0), new Point(1, 1), new Point(-1, 1), new Point(0, 0) }); + CustomLineCap cap = new CustomLineCap(null, path); + cap.WidthScale = 1.0f; + + _markPen = new Pen(_dragDropMarkColor, _dragDropMarkWidth); + _markPen.CustomStartCap = cap; + _markPen.CustomEndCap = cap; + } + + private void CreateLinePen() + { + _linePen = new Pen(_lineColor); + _linePen.DashStyle = DashStyle.Dot; + } + + protected override void OnPaint(PaintEventArgs e) + { + BeginPerformanceCount(); + PerformanceAnalyzer.Start("OnPaint"); + + DrawContext context = new DrawContext(); + context.Graphics = e.Graphics; + context.Font = this.Font; + context.Enabled = Enabled; + + int y = 0; + int gridHeight = 0; + + if (UseColumns) + { + DrawColumnHeaders(e.Graphics); + y += ColumnHeaderHeight; + if (Columns.Count == 0 || e.ClipRectangle.Height <= y) + return; + } + + int firstRowY = _rowLayout.GetRowBounds(FirstVisibleRow).Y; + y -= firstRowY; + + e.Graphics.ResetTransform(); + e.Graphics.TranslateTransform(-OffsetX, y); + Rectangle displayRect = DisplayRectangle; + for (int row = FirstVisibleRow; row < RowCount; row++) + { + Rectangle rowRect = _rowLayout.GetRowBounds(row); + gridHeight += rowRect.Height; + if (rowRect.Y + y > displayRect.Bottom) + break; + else + DrawRow(e, ref context, row, rowRect); + } + + if ((GridLineStyle & GridLineStyle.Vertical) == GridLineStyle.Vertical && UseColumns) + DrawVerticalGridLines(e.Graphics, firstRowY); + + if (_dropPosition.Node != null && DragMode && HighlightDropPosition) + DrawDropMark(e.Graphics); + + e.Graphics.ResetTransform(); + DrawScrollBarsBox(e.Graphics); + + if (DragMode && _dragBitmap != null) + e.Graphics.DrawImage(_dragBitmap, PointToClient(MousePosition)); + + PerformanceAnalyzer.Finish("OnPaint"); + EndPerformanceCount(e); + } + + private void DrawRow(PaintEventArgs e, ref DrawContext context, int row, Rectangle rowRect) + { + TreeNodeAdv node = RowMap[row]; + context.DrawSelection = DrawSelectionMode.None; + context.CurrentEditorOwner = CurrentEditorOwner; + if (DragMode) + { + if ((_dropPosition.Node == node) && _dropPosition.Position == NodePosition.Inside && HighlightDropPosition) + context.DrawSelection = DrawSelectionMode.Active; + } + else + { + if (node.IsSelected && Focused) + context.DrawSelection = DrawSelectionMode.Active; + else if (node.IsSelected && !Focused && !HideSelection) + context.DrawSelection = DrawSelectionMode.Inactive; + } + context.DrawFocus = Focused && CurrentNode == node; + + OnRowDraw(e, node, context, row, rowRect); + + if (FullRowSelect) + { + context.DrawFocus = false; + if (context.DrawSelection == DrawSelectionMode.Active || context.DrawSelection == DrawSelectionMode.Inactive) + { + Rectangle focusRect = new Rectangle(OffsetX, rowRect.Y, ClientRectangle.Width, rowRect.Height); + if (context.DrawSelection == DrawSelectionMode.Active) + { + e.Graphics.FillRectangle(SystemBrushes.Highlight, focusRect); + context.DrawSelection = DrawSelectionMode.FullRowSelect; + } + else + { + e.Graphics.FillRectangle(SystemBrushes.InactiveBorder, focusRect); + context.DrawSelection = DrawSelectionMode.None; + } + } + } + + if ((GridLineStyle & GridLineStyle.Horizontal) == GridLineStyle.Horizontal) + e.Graphics.DrawLine(SystemPens.InactiveBorder, 0, rowRect.Bottom, e.Graphics.ClipBounds.Right, rowRect.Bottom); + + if (ShowLines) + DrawLines(e.Graphics, node, rowRect); + + DrawNode(node, context); + } + + private void DrawVerticalGridLines(Graphics gr, int y) + { + int x = 0; + foreach (TreeColumn c in Columns) + { + if (c.IsVisible) + { + x += c.Width; + gr.DrawLine(SystemPens.InactiveBorder, x - 1, y, x - 1, gr.ClipBounds.Bottom); + } + } + } + + private void DrawColumnHeaders(Graphics gr) + { + PerformanceAnalyzer.Start("DrawColumnHeaders"); + ReorderColumnState reorder = Input as ReorderColumnState; + int x = 0; + TreeColumn.DrawBackground(gr, new Rectangle(0, 0, ClientRectangle.Width + 2, ColumnHeaderHeight - 1), false, false); + gr.TranslateTransform(-OffsetX, 0); + foreach (TreeColumn c in Columns) + { + if (c.IsVisible) + { + if (x >= OffsetX && x - OffsetX < this.Bounds.Width)// skip invisible columns + { + Rectangle rect = new Rectangle(x, 0, c.Width, ColumnHeaderHeight - 1); + gr.SetClip(rect); + bool pressed = ((Input is ClickColumnState || reorder != null) && ((Input as ColumnState).Column == c)); + c.Draw(gr, rect, Font, pressed, _hotColumn == c); + gr.ResetClip(); + + if (reorder != null && reorder.DropColumn == c) + TreeColumn.DrawDropMark(gr, rect); + } + x += c.Width; + } + } + + if (reorder != null) + { + if (reorder.DropColumn == null) + TreeColumn.DrawDropMark(gr, new Rectangle(x, 0, 0, ColumnHeaderHeight)); + gr.DrawImage(reorder.GhostImage, new Point(reorder.Location.X + + reorder.DragOffset, reorder.Location.Y)); + } + PerformanceAnalyzer.Finish("DrawColumnHeaders"); + } + + public void DrawNode(TreeNodeAdv node, DrawContext context) + { + foreach (NodeControlInfo item in GetNodeControls(node)) + { + if (item.Bounds.Right >= OffsetX && item.Bounds.X - OffsetX < this.Bounds.Width)// skip invisible nodes + { + context.Bounds = item.Bounds; + context.Graphics.SetClip(context.Bounds); + item.Control.Draw(node, context); + context.Graphics.ResetClip(); + } + } + } + + private void DrawScrollBarsBox(Graphics gr) + { + Rectangle r1 = DisplayRectangle; + Rectangle r2 = ClientRectangle; + gr.FillRectangle(SystemBrushes.Control, + new Rectangle(r1.Right, r1.Bottom, r2.Width - r1.Width, r2.Height - r1.Height)); + } + + private void DrawDropMark(Graphics gr) + { + if (_dropPosition.Position == NodePosition.Inside) + return; + + Rectangle rect = GetNodeBounds(_dropPosition.Node); + int right = DisplayRectangle.Right - LeftMargin + OffsetX; + int y = rect.Y; + if (_dropPosition.Position == NodePosition.After) + y = rect.Bottom; + gr.DrawLine(_markPen, rect.X, y, right, y); + } + + private void DrawLines(Graphics gr, TreeNodeAdv node, Rectangle rowRect) + { + if (UseColumns && Columns.Count > 0) + gr.SetClip(new Rectangle(0, rowRect.Y, Columns[0].Width, rowRect.Bottom)); + + TreeNodeAdv curNode = node; + while (curNode != _root && curNode != null) + { + int level = curNode.Level; + int x = (level - 1) * _indent + NodePlusMinus.ImageSize / 2 + LeftMargin; + int width = NodePlusMinus.Width - NodePlusMinus.ImageSize / 2; + int y = rowRect.Y; + int y2 = y + rowRect.Height; + + if (curNode == node) + { + int midy = y + rowRect.Height / 2; + gr.DrawLine(_linePen, x, midy, x + width, midy); + if (curNode.NextNode == null) + y2 = y + rowRect.Height / 2; + } + + if (node.Row == 0) + y = rowRect.Height / 2; + if (curNode.NextNode != null || curNode == node) + gr.DrawLine(_linePen, x, y, x, y2); + + curNode = curNode.Parent; + } + + gr.ResetClip(); + } + + #region Performance + + private double _totalTime; + private int _paintCount; + + [Conditional("PERF_TEST")] + private void BeginPerformanceCount() + { + _paintCount++; + TimeCounter.Start(); + } + + [Conditional("PERF_TEST")] + private void EndPerformanceCount(PaintEventArgs e) + { + double time = TimeCounter.Finish(); + _totalTime += time; + string debugText = string.Format("FPS {0:0.0}; Avg. FPS {1:0.0}", + 1 / time, 1 / (_totalTime / _paintCount)); + e.Graphics.FillRectangle(Brushes.White, new Rectangle(DisplayRectangle.Width - 150, DisplayRectangle.Height - 20, 150, 20)); + e.Graphics.DrawString(debugText, Control.DefaultFont, Brushes.Gray, + new PointF(DisplayRectangle.Width - 150, DisplayRectangle.Height - 20)); + } + #endregion + + } +} diff -r 3145aadca3d2 -r 0c551e8818e0 External/Aga.Controls/Tree/TreeViewAdv.Editor.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/External/Aga.Controls/Tree/TreeViewAdv.Editor.cs Sun May 27 15:16:19 2012 +0000 @@ -0,0 +1,145 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Windows.Forms; +using Aga.Controls.Tree.NodeControls; +using System.Drawing; + +namespace Aga.Controls.Tree +{ + partial class TreeViewAdv + { + private TreeNodeAdv _editingNode; + + public EditableControl CurrentEditorOwner { get; private set; } + public Control CurrentEditor { get; private set; } + + public void HideEditor() + { + if (CurrentEditorOwner != null) + CurrentEditorOwner.EndEdit(false); + } + + internal void DisplayEditor(Control editor, EditableControl owner) + { + if (editor == null || owner == null || CurrentNode == null) + throw new ArgumentNullException(); + + HideEditor(false); + + CurrentEditor = editor; + CurrentEditorOwner = owner; + _editingNode = CurrentNode; + + editor.Validating += EditorValidating; + UpdateEditorBounds(); + UpdateView(); + editor.Parent = this; + editor.Focus(); + owner.UpdateEditor(editor); + } + + internal bool HideEditor(bool applyChanges) + { + if (CurrentEditor != null) + { + if (applyChanges) + { + if (!ApplyChanges()) + return false; + } + + //Check once more if editor was closed in ApplyChanges + if (CurrentEditor != null) + { + CurrentEditor.Validating -= EditorValidating; + CurrentEditorOwner.DoDisposeEditor(CurrentEditor); + + CurrentEditor.Parent = null; + CurrentEditor.Dispose(); + + CurrentEditor = null; + CurrentEditorOwner = null; + _editingNode = null; + } + } + return true; + } + + private bool ApplyChanges() + { + try + { + CurrentEditorOwner.ApplyChanges(_editingNode, CurrentEditor); + _errorProvider.Clear(); + return true; + } + catch (ArgumentException ex) + { + _errorProvider.SetError(CurrentEditor, ex.Message); + /*CurrentEditor.Validating -= EditorValidating; + MessageBox.Show(this, ex.Message, "Value is not valid", MessageBoxButtons.OK, MessageBoxIcon.Warning); + CurrentEditor.Focus(); + CurrentEditor.Validating += EditorValidating;*/ + return false; + } + } + + void EditorValidating(object sender, System.ComponentModel.CancelEventArgs e) + { + e.Cancel = !ApplyChanges(); + } + + public void UpdateEditorBounds() + { + if (CurrentEditor != null) + { + EditorContext context = new EditorContext(); + context.Owner = CurrentEditorOwner; + context.CurrentNode = CurrentNode; + context.Editor = CurrentEditor; + context.DrawContext = _measureContext; + SetEditorBounds(context); + } + } + + private void SetEditorBounds(EditorContext context) + { + foreach (NodeControlInfo info in GetNodeControls(context.CurrentNode)) + { + if (context.Owner == info.Control && info.Control is EditableControl) + { + Point p = info.Bounds.Location; + p.X += info.Control.LeftMargin; + p.X -= OffsetX; + p.Y -= (_rowLayout.GetRowBounds(FirstVisibleRow).Y - ColumnHeaderHeight); + int width = DisplayRectangle.Width - p.X; + if (UseColumns && info.Control.ParentColumn != null && Columns.Contains(info.Control.ParentColumn)) + { + Rectangle rect = GetColumnBounds(info.Control.ParentColumn.Index); + width = rect.Right - OffsetX - p.X; + } + context.Bounds = new Rectangle(p.X, p.Y, width, info.Bounds.Height); + ((EditableControl)info.Control).SetEditorBounds(context); + return; + } + } + } + + private Rectangle GetColumnBounds(int column) + { + int x = 0; + for (int i = 0; i < Columns.Count; i++) + { + if (Columns[i].IsVisible) + { + if (i < column) + x += Columns[i].Width; + else + return new Rectangle(x, 0, Columns[i].Width, 0); + } + } + return Rectangle.Empty; + } + } +} diff -r 3145aadca3d2 -r 0c551e8818e0 External/Aga.Controls/Tree/TreeViewAdv.Input.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/External/Aga.Controls/Tree/TreeViewAdv.Input.cs Sun May 27 15:16:19 2012 +0000 @@ -0,0 +1,558 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Windows.Forms; +using System.Drawing; +using Aga.Controls.Tree.NodeControls; +using System.Drawing.Imaging; +using System.Threading; + +namespace Aga.Controls.Tree +{ + public partial class TreeViewAdv + { + #region Keys + + protected override bool IsInputChar(char charCode) + { + return true; + } + + protected override bool IsInputKey(Keys keyData) + { + if (((keyData & Keys.Up) == Keys.Up) + || ((keyData & Keys.Down) == Keys.Down) + || ((keyData & Keys.Left) == Keys.Left) + || ((keyData & Keys.Right) == Keys.Right)) + return true; + else + return base.IsInputKey(keyData); + } + + internal void ChangeInput() + { + if ((ModifierKeys & Keys.Shift) == Keys.Shift) + { + if (!(Input is InputWithShift)) + Input = new InputWithShift(this); + } + else if ((ModifierKeys & Keys.Control) == Keys.Control) + { + if (!(Input is InputWithControl)) + Input = new InputWithControl(this); + } + else + { + if (!(Input.GetType() == typeof(NormalInputState))) + Input = new NormalInputState(this); + } + } + + protected override void OnKeyDown(KeyEventArgs e) + { + base.OnKeyDown(e); + if (!e.Handled) + { + if (e.KeyCode == Keys.ShiftKey || e.KeyCode == Keys.ControlKey) + ChangeInput(); + Input.KeyDown(e); + if (!e.Handled) + { + foreach (NodeControlInfo item in GetNodeControls(CurrentNode)) + { + item.Control.KeyDown(e); + if (e.Handled) + break; + } + } + } + } + + protected override void OnKeyUp(KeyEventArgs e) + { + base.OnKeyUp(e); + if (!e.Handled) + { + if (e.KeyCode == Keys.ShiftKey || e.KeyCode == Keys.ControlKey) + ChangeInput(); + if (!e.Handled) + { + foreach (NodeControlInfo item in GetNodeControls(CurrentNode)) + { + item.Control.KeyUp(e); + if (e.Handled) + return; + } + } + } + } + + protected override void OnKeyPress(KeyPressEventArgs e) + { + base.OnKeyPress(e); + if (!e.Handled) + _search.Search(e.KeyChar); + } + + #endregion + + #region Mouse + + private TreeNodeAdvMouseEventArgs CreateMouseArgs(MouseEventArgs e) + { + TreeNodeAdvMouseEventArgs args = new TreeNodeAdvMouseEventArgs(e); + args.ViewLocation = new Point(e.X + OffsetX, + e.Y + _rowLayout.GetRowBounds(FirstVisibleRow).Y - ColumnHeaderHeight); + args.ModifierKeys = ModifierKeys; + args.Node = GetNodeAt(e.Location); + NodeControlInfo info = GetNodeControlInfoAt(args.Node, e.Location); + args.ControlBounds = info.Bounds; + args.Control = info.Control; + return args; + } + + protected override void OnMouseWheel(MouseEventArgs e) + { + _search.EndSearch(); + if (SystemInformation.MouseWheelScrollLines > 0) + { + int lines = e.Delta / 120 * SystemInformation.MouseWheelScrollLines; + int newValue = _vScrollBar.Value - lines; + newValue = Math.Min(_vScrollBar.Maximum - _vScrollBar.LargeChange + 1, newValue); + newValue = Math.Min(_vScrollBar.Maximum, newValue); + _vScrollBar.Value = Math.Max(_vScrollBar.Minimum, newValue); + } + base.OnMouseWheel(e); + } + + protected override void OnMouseDown(MouseEventArgs e) + { + if (CurrentEditorOwner != null) + { + CurrentEditorOwner.EndEdit(true); + return; + } + + if (!Focused) + Focus(); + + _search.EndSearch(); + if (e.Button == MouseButtons.Left) + { + TreeColumn c; + c = GetColumnDividerAt(e.Location); + if (c != null) + { + Input = new ResizeColumnState(this, c, e.Location); + return; + } + c = GetColumnAt(e.Location); + if (c != null) + { + Input = new ClickColumnState(this, c, e.Location); + UpdateView(); + return; + } + } + + ChangeInput(); + TreeNodeAdvMouseEventArgs args = CreateMouseArgs(e); + + if (args.Node != null && args.Control != null) + args.Control.MouseDown(args); + + if (!args.Handled) + Input.MouseDown(args); + + base.OnMouseDown(e); + } + + protected override void OnMouseClick(MouseEventArgs e) + { + //TODO: Disable when click on plusminus icon + TreeNodeAdvMouseEventArgs args = CreateMouseArgs(e); + if (args.Node != null) + OnNodeMouseClick(args); + + base.OnMouseClick(e); + } + + protected override void OnMouseDoubleClick(MouseEventArgs e) + { + TreeNodeAdvMouseEventArgs args = CreateMouseArgs(e); + + if (args.Node != null && args.Control != null) + args.Control.MouseDoubleClick(args); + + if (!args.Handled) + { + if (args.Node != null) + OnNodeMouseDoubleClick(args); + else + Input.MouseDoubleClick(args); + + if (!args.Handled) + { + if (args.Node != null && args.Button == MouseButtons.Left) + args.Node.IsExpanded = !args.Node.IsExpanded; + } + } + + base.OnMouseDoubleClick(e); + } + + protected override void OnMouseUp(MouseEventArgs e) + { + TreeNodeAdvMouseEventArgs args = CreateMouseArgs(e); + if (Input is ResizeColumnState) + Input.MouseUp(args); + else + { + if (args.Node != null && args.Control != null) + args.Control.MouseUp(args); + if (!args.Handled) + Input.MouseUp(args); + + base.OnMouseUp(e); + } + } + + protected override void OnMouseMove(MouseEventArgs e) + { + if (Input.MouseMove(e)) + return; + + base.OnMouseMove(e); + SetCursor(e); + UpdateToolTip(e); + if (ItemDragMode && Dist(e.Location, ItemDragStart) > ItemDragSensivity + && CurrentNode != null && CurrentNode.IsSelected) + { + ItemDragMode = false; + _toolTip.Active = false; + OnItemDrag(e.Button, Selection.ToArray()); + } + } + + protected override void OnMouseLeave(EventArgs e) + { + _hotColumn = null; + UpdateHeaders(); + base.OnMouseLeave(e); + } + + private void SetCursor(MouseEventArgs e) + { + TreeColumn col; + col = GetColumnDividerAt(e.Location); + if (col == null) + _innerCursor = null; + else + { + if (col.Width == 0) + _innerCursor = ResourceHelper.DVSplitCursor; + else + _innerCursor = Cursors.VSplit; + } + + col = GetColumnAt(e.Location); + if (col != _hotColumn) + { + _hotColumn = col; + UpdateHeaders(); + } + } + + internal TreeColumn GetColumnAt(Point p) + { + if (p.Y > ColumnHeaderHeight) + return null; + + int x = -OffsetX; + foreach (TreeColumn col in Columns) + { + if (col.IsVisible) + { + Rectangle rect = new Rectangle(x, 0, col.Width, ColumnHeaderHeight); + x += col.Width; + if (rect.Contains(p)) + return col; + } + } + return null; + } + + internal int GetColumnX(TreeColumn column) + { + int x = -OffsetX; + foreach (TreeColumn col in Columns) + { + if (col.IsVisible) + { + if (column == col) + return x; + else + x += col.Width; + } + } + return x; + } + + internal TreeColumn GetColumnDividerAt(Point p) + { + if (p.Y > ColumnHeaderHeight) + return null; + + int x = -OffsetX; + TreeColumn prevCol = null; + Rectangle left, right; + foreach (TreeColumn col in Columns) + { + if (col.IsVisible) + { + if (col.Width > 0) + { + left = new Rectangle(x, 0, DividerWidth / 2, ColumnHeaderHeight); + right = new Rectangle(x + col.Width - (DividerWidth / 2), 0, DividerWidth / 2, ColumnHeaderHeight); + if (left.Contains(p) && prevCol != null) + return prevCol; + else if (right.Contains(p)) + return col; + } + prevCol = col; + x += col.Width; + } + } + + left = new Rectangle(x, 0, DividerWidth / 2, ColumnHeaderHeight); + if (left.Contains(p) && prevCol != null) + return prevCol; + + return null; + } + + TreeColumn _tooltipColumn; + private void UpdateToolTip(MouseEventArgs e) + { + TreeColumn col = GetColumnAt(e.Location); + if (col != null) + { + if (col != _tooltipColumn) + SetTooltip(col.TooltipText); + } + else + DisplayNodesTooltip(e); + _tooltipColumn = col; + } + + TreeNodeAdv _hotNode; + NodeControl _hotControl; + private void DisplayNodesTooltip(MouseEventArgs e) + { + if (ShowNodeToolTips) + { + TreeNodeAdvMouseEventArgs args = CreateMouseArgs(e); + if (args.Node != null && args.Control != null) + { + if (args.Node != _hotNode || args.Control != _hotControl) + SetTooltip(GetNodeToolTip(args)); + } + else + _toolTip.SetToolTip(this, null); + + _hotControl = args.Control; + _hotNode = args.Node; + } + else + _toolTip.SetToolTip(this, null); + } + + private void SetTooltip(string text) + { + if (!String.IsNullOrEmpty(text)) + { + _toolTip.Active = false; + _toolTip.SetToolTip(this, text); + _toolTip.Active = true; + } + else + _toolTip.SetToolTip(this, null); + } + + private string GetNodeToolTip(TreeNodeAdvMouseEventArgs args) + { + string msg = args.Control.GetToolTip(args.Node); + + BaseTextControl btc = args.Control as BaseTextControl; + if (btc != null && btc.DisplayHiddenContentInToolTip && String.IsNullOrEmpty(msg)) + { + Size ms = btc.GetActualSize(args.Node, _measureContext); + if (ms.Width > args.ControlBounds.Size.Width || ms.Height > args.ControlBounds.Size.Height + || args.ControlBounds.Right - OffsetX > DisplayRectangle.Width) + msg = btc.GetLabel(args.Node); + } + + if (String.IsNullOrEmpty(msg) && DefaultToolTipProvider != null) + msg = DefaultToolTipProvider.GetToolTip(args.Node, args.Control); + + return msg; + } + + #endregion + + #region DragDrop + + private bool _dragAutoScrollFlag = false; + private Bitmap _dragBitmap = null; + private System.Threading.Timer _dragTimer; + + private void StartDragTimer() + { + if (_dragTimer == null) + _dragTimer = new System.Threading.Timer(new TimerCallback(DragTimerTick), null, 0, 100); + } + + private void StopDragTimer() + { + if (_dragTimer != null) + { + _dragTimer.Dispose(); + _dragTimer = null; + } + } + + private void SetDropPosition(Point pt) + { + TreeNodeAdv node = GetNodeAt(pt); + OnDropNodeValidating(pt, ref node); + _dropPosition.Node = node; + if (node != null) + { + Rectangle first = _rowLayout.GetRowBounds(FirstVisibleRow); + Rectangle bounds = _rowLayout.GetRowBounds(node.Row); + float pos = (pt.Y + first.Y - ColumnHeaderHeight - bounds.Y) / (float)bounds.Height; + if (pos < TopEdgeSensivity) + _dropPosition.Position = NodePosition.Before; + else if (pos > (1 - BottomEdgeSensivity)) + _dropPosition.Position = NodePosition.After; + else + _dropPosition.Position = NodePosition.Inside; + } + } + + private void DragTimerTick(object state) + { + _dragAutoScrollFlag = true; + } + + private void DragAutoScroll() + { + _dragAutoScrollFlag = false; + Point pt = PointToClient(MousePosition); + if (pt.Y < 20 && _vScrollBar.Value > 0) + _vScrollBar.Value--; + else if (pt.Y > Height - 20 && _vScrollBar.Value <= _vScrollBar.Maximum - _vScrollBar.LargeChange) + _vScrollBar.Value++; + } + + public void DoDragDropSelectedNodes(DragDropEffects allowedEffects) + { + if (SelectedNodes.Count > 0) + { + TreeNodeAdv[] nodes = new TreeNodeAdv[SelectedNodes.Count]; + SelectedNodes.CopyTo(nodes, 0); + DoDragDrop(nodes, allowedEffects); + } + } + + private void CreateDragBitmap(IDataObject data) + { + if (UseColumns || !DisplayDraggingNodes) + return; + + TreeNodeAdv[] nodes = data.GetData(typeof(TreeNodeAdv[])) as TreeNodeAdv[]; + if (nodes != null && nodes.Length > 0) + { + Rectangle rect = DisplayRectangle; + Bitmap bitmap = new Bitmap(rect.Width, rect.Height); + using (Graphics gr = Graphics.FromImage(bitmap)) + { + gr.Clear(BackColor); + DrawContext context = new DrawContext(); + context.Graphics = gr; + context.Font = Font; + context.Enabled = true; + int y = 0; + int maxWidth = 0; + foreach (TreeNodeAdv node in nodes) + { + if (node.Tree == this) + { + int x = 0; + int height = _rowLayout.GetRowBounds(node.Row).Height; + foreach (NodeControl c in NodeControls) + { + Size s = c.GetActualSize(node, context); + if (!s.IsEmpty) + { + int width = s.Width; + rect = new Rectangle(x, y, width, height); + x += (width + 1); + context.Bounds = rect; + c.Draw(node, context); + } + } + y += height; + maxWidth = Math.Max(maxWidth, x); + } + } + + if (maxWidth > 0 && y > 0) + { + _dragBitmap = new Bitmap(maxWidth, y, PixelFormat.Format32bppArgb); + using (Graphics tgr = Graphics.FromImage(_dragBitmap)) + tgr.DrawImage(bitmap, Point.Empty); + BitmapHelper.SetAlphaChanelValue(_dragBitmap, 150); + } + else + _dragBitmap = null; + } + } + } + + protected override void OnDragOver(DragEventArgs drgevent) + { + ItemDragMode = false; + Point pt = PointToClient(new Point(drgevent.X, drgevent.Y)); + if (_dragAutoScrollFlag) + DragAutoScroll(); + SetDropPosition(pt); + UpdateView(); + base.OnDragOver(drgevent); + } + + protected override void OnDragEnter(DragEventArgs drgevent) + { + _search.EndSearch(); + DragMode = true; + CreateDragBitmap(drgevent.Data); + base.OnDragEnter(drgevent); + } + + protected override void OnDragLeave(EventArgs e) + { + DragMode = false; + UpdateView(); + base.OnDragLeave(e); + } + + protected override void OnDragDrop(DragEventArgs drgevent) + { + DragMode = false; + UpdateView(); + base.OnDragDrop(drgevent); + } + + #endregion + } +} diff -r 3145aadca3d2 -r 0c551e8818e0 External/Aga.Controls/Tree/TreeViewAdv.Properties.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/External/Aga.Controls/Tree/TreeViewAdv.Properties.cs Sun May 27 15:16:19 2012 +0000 @@ -0,0 +1,728 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.ComponentModel; +using System.Drawing; +using System.Drawing.Design; +using System.Windows.Forms; + +using Aga.Controls.Tree.NodeControls; + +namespace Aga.Controls.Tree +{ + public partial class TreeViewAdv + { + private Cursor _innerCursor = null; + + public override Cursor Cursor + { + get + { + if (_innerCursor != null) + return _innerCursor; + else + return base.Cursor; + } + set + { + base.Cursor = value; + } + } + + #region Internal Properties + + private IRowLayout _rowLayout; + + private bool _dragMode; + private bool DragMode + { + get { return _dragMode; } + set + { + _dragMode = value; + if (!value) + { + StopDragTimer(); + if (_dragBitmap != null) + _dragBitmap.Dispose(); + _dragBitmap = null; + } + else + StartDragTimer(); + } + } + + internal int ColumnHeaderHeight + { + get + { + if (UseColumns) + return _columnHeaderHeight; + else + return 0; + } + } + + /// + /// returns all nodes, which parent is expanded + /// + private IEnumerable VisibleNodes + { + get + { + TreeNodeAdv node = Root; + while (node != null) + { + node = node.NextVisibleNode; + if (node != null) + yield return node; + } + } + } + + private bool _suspendSelectionEvent; + internal bool SuspendSelectionEvent + { + get { return _suspendSelectionEvent; } + set + { + if (value != _suspendSelectionEvent) + { + _suspendSelectionEvent = value; + if (!_suspendSelectionEvent && _fireSelectionEvent) + OnSelectionChanged(); + } + } + } + + private List _rowMap; + internal List RowMap + { + get { return _rowMap; } + } + + private TreeNodeAdv _selectionStart; + internal TreeNodeAdv SelectionStart + { + get { return _selectionStart; } + set { _selectionStart = value; } + } + + private InputState _input; + internal InputState Input + { + get { return _input; } + set + { + _input = value; + } + } + + private bool _itemDragMode; + internal bool ItemDragMode + { + get { return _itemDragMode; } + set { _itemDragMode = value; } + } + + private Point _itemDragStart; + internal Point ItemDragStart + { + get { return _itemDragStart; } + set { _itemDragStart = value; } + } + + + /// + /// Number of rows fits to the current page + /// + internal int CurrentPageSize + { + get + { + return _rowLayout.CurrentPageSize; + } + } + + /// + /// Number of all visible nodes (which parent is expanded) + /// + internal int RowCount + { + get + { + return RowMap.Count; + } + } + + private int _contentWidth = 0; + private int ContentWidth + { + get + { + return _contentWidth; + } + } + + private int _firstVisibleRow; + internal int FirstVisibleRow + { + get { return _firstVisibleRow; } + set + { + HideEditor(); + _firstVisibleRow = value; + UpdateView(); + } + } + + private int _offsetX; + public int OffsetX + { + get { return _offsetX; } + private set + { + HideEditor(); + _offsetX = value; + UpdateView(); + } + } + + public override Rectangle DisplayRectangle + { + get + { + Rectangle r = ClientRectangle; + //r.Y += ColumnHeaderHeight; + //r.Height -= ColumnHeaderHeight; + int w = _vScrollBar.Visible ? _vScrollBar.Width : 0; + int h = _hScrollBar.Visible ? _hScrollBar.Height : 0; + return new Rectangle(r.X, r.Y, r.Width - w, r.Height - h); + } + } + + private List _selection; + internal List Selection + { + get { return _selection; } + } + + #endregion + + #region Public Properties + + #region DesignTime + + private bool _shiftFirstNode; + [DefaultValue(false), Category("Behavior")] + public bool ShiftFirstNode + { + get { return _shiftFirstNode; } + set { _shiftFirstNode = value; } + } + + private bool _displayDraggingNodes; + [DefaultValue(false), Category("Behavior")] + public bool DisplayDraggingNodes + { + get { return _displayDraggingNodes; } + set { _displayDraggingNodes = value; } + } + + private bool _fullRowSelect; + [DefaultValue(false), Category("Behavior")] + public bool FullRowSelect + { + get { return _fullRowSelect; } + set + { + _fullRowSelect = value; + UpdateView(); + } + } + + private bool _useColumns; + [DefaultValue(false), Category("Behavior")] + public bool UseColumns + { + get { return _useColumns; } + set + { + _useColumns = value; + FullUpdate(); + } + } + + private bool _allowColumnReorder; + [DefaultValue(false), Category("Behavior")] + public bool AllowColumnReorder + { + get { return _allowColumnReorder; } + set { _allowColumnReorder = value; } + } + + private bool _showLines = true; + [DefaultValue(true), Category("Behavior")] + public bool ShowLines + { + get { return _showLines; } + set + { + _showLines = value; + UpdateView(); + } + } + + private bool _showPlusMinus = true; + [DefaultValue(true), Category("Behavior")] + public bool ShowPlusMinus + { + get { return _showPlusMinus; } + set + { + _showPlusMinus = value; + FullUpdate(); + } + } + + private bool _showNodeToolTips = false; + [DefaultValue(false), Category("Behavior")] + public bool ShowNodeToolTips + { + get { return _showNodeToolTips; } + set { _showNodeToolTips = value; } + } + + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "value"), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic"), DefaultValue(true), Category("Behavior"), Obsolete("No longer used")] + public bool KeepNodesExpanded + { + get { return true; } + set {} + } + + private ITreeModel _model; + /// + /// The model associated with this . + /// + /// + /// + [Browsable(false)] + public ITreeModel Model + { + get { return _model; } + set + { + if (_model != value) + { + AbortBackgroundExpandingThreads(); + if (_model != null) + UnbindModelEvents(); + _model = value; + CreateNodes(); + FullUpdate(); + if (_model != null) + BindModelEvents(); + } + } + } + + // Tahoma is the default font + private static Font _font = new Font("Tahoma", 8.25F, FontStyle.Regular, GraphicsUnit.Point, ((byte)(0)), false); + /// + /// The font to render content in. + /// + [Category("Appearance"), Description("The font to render TreeViewAdv content in.")] + public override Font Font + { + get + { + return (base.Font); + } + set + { + if (value == null) + base.Font = _font; + else + { + if (value == DefaultFont) + base.Font = _font; + else + base.Font = value; + } + } + } + public override void ResetFont() + { + Font = null; + } + private bool ShouldSerializeFont() + { + return (!Font.Equals(_font)); + } + // End font property + + private BorderStyle _borderStyle = BorderStyle.Fixed3D; + [DefaultValue(BorderStyle.Fixed3D), Category("Appearance")] + public BorderStyle BorderStyle + { + get + { + return this._borderStyle; + } + set + { + if (_borderStyle != value) + { + _borderStyle = value; + base.UpdateStyles(); + } + } + } + + private bool _autoRowHeight = false; + /// + /// Set to true to expand each row's height to fit the text of it's largest column. + /// + [DefaultValue(false), Category("Appearance"), Description("Expand each row's height to fit the text of it's largest column.")] + public bool AutoRowHeight + { + get + { + return _autoRowHeight; + } + set + { + _autoRowHeight = value; + if (value) + _rowLayout = new AutoRowHeightLayout(this, RowHeight); + else + _rowLayout = new FixedRowHeightLayout(this, RowHeight); + FullUpdate(); + } + } + + private GridLineStyle _gridLineStyle = GridLineStyle.None; + [DefaultValue(GridLineStyle.None), Category("Appearance")] + public GridLineStyle GridLineStyle + { + get + { + return _gridLineStyle; + } + set + { + if (value != _gridLineStyle) + { + _gridLineStyle = value; + UpdateView(); + OnGridLineStyleChanged(); + } + } + } + + private int _rowHeight = 16; + [DefaultValue(16), Category("Appearance")] + public int RowHeight + { + get + { + return _rowHeight; + } + set + { + if (value <= 0) + throw new ArgumentOutOfRangeException("value"); + + _rowHeight = value; + _rowLayout.PreferredRowHeight = value; + FullUpdate(); + } + } + + private TreeSelectionMode _selectionMode = TreeSelectionMode.Single; + [DefaultValue(TreeSelectionMode.Single), Category("Behavior")] + public TreeSelectionMode SelectionMode + { + get { return _selectionMode; } + set { _selectionMode = value; } + } + + private bool _hideSelection; + [DefaultValue(false), Category("Behavior")] + public bool HideSelection + { + get { return _hideSelection; } + set + { + _hideSelection = value; + UpdateView(); + } + } + + private float _topEdgeSensivity = 0.3f; + [DefaultValue(0.3f), Category("Behavior")] + public float TopEdgeSensivity + { + get { return _topEdgeSensivity; } + set + { + if (value < 0 || value > 1) + throw new ArgumentOutOfRangeException(); + _topEdgeSensivity = value; + } + } + + private float _bottomEdgeSensivity = 0.3f; + [DefaultValue(0.3f), Category("Behavior")] + public float BottomEdgeSensivity + { + get { return _bottomEdgeSensivity; } + set + { + if (value < 0 || value > 1) + throw new ArgumentOutOfRangeException("value should be from 0 to 1"); + _bottomEdgeSensivity = value; + } + } + + private bool _loadOnDemand; + [DefaultValue(false), Category("Behavior")] + public bool LoadOnDemand + { + get { return _loadOnDemand; } + set { _loadOnDemand = value; } + } + + private bool _unloadCollapsedOnReload = false; + [DefaultValue(false), Category("Behavior")] + public bool UnloadCollapsedOnReload + { + get { return _unloadCollapsedOnReload; } + set { _unloadCollapsedOnReload = value; } + } + + private int _indent = 19; + [DefaultValue(19), Category("Behavior")] + public int Indent + { + get { return _indent; } + set + { + _indent = value; + UpdateView(); + } + } + + private Color _lineColor = SystemColors.ControlDark; + [Category("Behavior")] + public Color LineColor + { + get { return _lineColor; } + set + { + _lineColor = value; + CreateLinePen(); + UpdateView(); + } + } + + private Color _dragDropMarkColor = Color.Black; + [Category("Behavior")] + public Color DragDropMarkColor + { + get { return _dragDropMarkColor; } + set + { + _dragDropMarkColor = value; + CreateMarkPen(); + } + } + + private float _dragDropMarkWidth = 3.0f; + [DefaultValue(3.0f), Category("Behavior")] + public float DragDropMarkWidth + { + get { return _dragDropMarkWidth; } + set + { + _dragDropMarkWidth = value; + CreateMarkPen(); + } + } + + private bool _highlightDropPosition = true; + [DefaultValue(true), Category("Behavior")] + public bool HighlightDropPosition + { + get { return _highlightDropPosition; } + set { _highlightDropPosition = value; } + } + + private TreeColumnCollection _columns; + [Category("Behavior"), DesignerSerializationVisibility(DesignerSerializationVisibility.Content)] + public Collection Columns + { + get { return _columns; } + } + + private NodeControlsCollection _controls; + [Category("Behavior"), DesignerSerializationVisibility(DesignerSerializationVisibility.Content)] + [Editor(typeof(NodeControlCollectionEditor), typeof(UITypeEditor))] + public Collection NodeControls + { + get + { + return _controls; + } + } + + private bool _asyncExpanding; + /// + /// When set to true, node contents will be read in background thread. + /// + [Category("Behavior"), DefaultValue(false), Description("Read children in a background thread when expanding.")] + public bool AsyncExpanding + { + get { return _asyncExpanding; } + set { _asyncExpanding = value; } + } + + #endregion + + #region RunTime + + private IToolTipProvider _defaultToolTipProvider = null; + [Browsable(false)] + public IToolTipProvider DefaultToolTipProvider + { + get { return _defaultToolTipProvider; } + set { _defaultToolTipProvider = value; } + } + + [Browsable(false)] + public IEnumerable AllNodes + { + get + { + if (_root.Nodes.Count > 0) + { + TreeNodeAdv node = _root.Nodes[0]; + while (node != null) + { + yield return node; + if (node.Nodes.Count > 0) + node = node.Nodes[0]; + else if (node.NextNode != null) + node = node.NextNode; + else + node = node.BottomNode; + } + } + } + } + + private DropPosition _dropPosition; + [Browsable(false)] + public DropPosition DropPosition + { + get { return _dropPosition; } + set { _dropPosition = value; } + } + + private TreeNodeAdv _root; + [Browsable(false)] + public TreeNodeAdv Root + { + get { return _root; } + } + + private ReadOnlyCollection _readonlySelection; + [Browsable(false)] + public ReadOnlyCollection SelectedNodes + { + get + { + return _readonlySelection; + } + } + + [Browsable(false)] + public TreeNodeAdv SelectedNode + { + get + { + if (Selection.Count > 0) + { + if (CurrentNode != null && CurrentNode.IsSelected) + return CurrentNode; + else + return Selection[0]; + } + else + return null; + } + set + { + if (SelectedNode == value) + return; + + BeginUpdate(); + try + { + if (value == null) + { + ClearSelectionInternal(); + } + else + { + if (!IsMyNode(value)) + throw new ArgumentException(); + + ClearSelectionInternal(); + value.IsSelected = true; + CurrentNode = value; + EnsureVisible(value); + } + } + finally + { + EndUpdate(); + } + } + } + + private TreeNodeAdv _currentNode; + [Browsable(false)] + public TreeNodeAdv CurrentNode + { + get { return _currentNode; } + internal set { _currentNode = value; } + } + + [Browsable(false)] + public int ItemCount + { + get { return RowMap.Count; } + } + + /// + /// Indicates the distance the content is scrolled to the left + /// + [Browsable(false)] + public int HorizontalScrollPosition + { + get + { + if (_hScrollBar.Visible) + return _hScrollBar.Value; + else + return 0; + } + } + + #endregion + + #endregion + + } +} diff -r 3145aadca3d2 -r 0c551e8818e0 External/Aga.Controls/Tree/TreeViewAdv.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/External/Aga.Controls/Tree/TreeViewAdv.cs Sun May 27 15:16:19 2012 +0000 @@ -0,0 +1,1196 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.ComponentModel; +using System.Drawing; +using System.Security.Permissions; +using System.Threading; +using System.Windows.Forms; +using System.Collections; + +using Aga.Controls.Tree.NodeControls; +using Aga.Controls.Threading; + + +namespace Aga.Controls.Tree +{ + /// + /// Extensible advanced implemented in 100% managed C# code. + /// Features: Model/View architecture. Multiple column per node. Ability to select + /// multiple tree nodes. Different types of controls for each node column: + /// , Icon, Label... Drag and Drop highlighting. Load on + /// demand of nodes. Incremental search of nodes. + /// + public partial class TreeViewAdv : Control + { + private const int LeftMargin = 7; + internal const int ItemDragSensivity = 4; + private readonly int _columnHeaderHeight; + private const int DividerWidth = 9; + private const int DividerCorrectionGap = -2; + + private Pen _linePen; + private Pen _markPen; + private bool _suspendUpdate; + private bool _needFullUpdate; + private bool _fireSelectionEvent; + private NodePlusMinus _plusMinus; + private ToolTip _toolTip; + private DrawContext _measureContext; + private TreeColumn _hotColumn; + private IncrementalSearch _search; + private List _expandingNodes = new List(); + private AbortableThreadPool _threadPool = new AbortableThreadPool(); + + #region Public Events + + [Category("Action")] + public event ItemDragEventHandler ItemDrag; + private void OnItemDrag(MouseButtons buttons, object item) + { + if (ItemDrag != null) + ItemDrag(this, new ItemDragEventArgs(buttons, item)); + } + + [Category("Behavior")] + public event EventHandler NodeMouseClick; + private void OnNodeMouseClick(TreeNodeAdvMouseEventArgs args) + { + if (NodeMouseClick != null) + NodeMouseClick(this, args); + } + + [Category("Behavior")] + public event EventHandler NodeMouseDoubleClick; + private void OnNodeMouseDoubleClick(TreeNodeAdvMouseEventArgs args) + { + if (NodeMouseDoubleClick != null) + NodeMouseDoubleClick(this, args); + } + + [Category("Behavior")] + public event EventHandler ColumnWidthChanged; + internal void OnColumnWidthChanged(TreeColumn column) + { + if (ColumnWidthChanged != null) + ColumnWidthChanged(this, new TreeColumnEventArgs(column)); + } + + [Category("Behavior")] + public event EventHandler ColumnReordered; + internal void OnColumnReordered(TreeColumn column) + { + if (ColumnReordered != null) + ColumnReordered(this, new TreeColumnEventArgs(column)); + } + + [Category("Behavior")] + public event EventHandler ColumnClicked; + internal void OnColumnClicked(TreeColumn column) + { + if (ColumnClicked != null) + ColumnClicked(this, new TreeColumnEventArgs(column)); + } + + [Category("Behavior")] + public event EventHandler SelectionChanged; + internal void OnSelectionChanged() + { + if (SuspendSelectionEvent) + _fireSelectionEvent = true; + else + { + _fireSelectionEvent = false; + if (SelectionChanged != null) + SelectionChanged(this, EventArgs.Empty); + } + } + + [Category("Behavior")] + public event EventHandler Collapsing; + private void OnCollapsing(TreeNodeAdv node) + { + if (Collapsing != null) + Collapsing(this, new TreeViewAdvEventArgs(node)); + } + + [Category("Behavior")] + public event EventHandler Collapsed; + private void OnCollapsed(TreeNodeAdv node) + { + if (Collapsed != null) + Collapsed(this, new TreeViewAdvEventArgs(node)); + } + + [Category("Behavior")] + public event EventHandler Expanding; + private void OnExpanding(TreeNodeAdv node) + { + if (Expanding != null) + Expanding(this, new TreeViewAdvEventArgs(node)); + } + + [Category("Behavior")] + public event EventHandler Expanded; + private void OnExpanded(TreeNodeAdv node) + { + if (Expanded != null) + Expanded(this, new TreeViewAdvEventArgs(node)); + } + + [Category("Behavior")] + public event EventHandler GridLineStyleChanged; + private void OnGridLineStyleChanged() + { + if (GridLineStyleChanged != null) + GridLineStyleChanged(this, EventArgs.Empty); + } + + [Category("Behavior")] + public event ScrollEventHandler Scroll; + protected virtual void OnScroll(ScrollEventArgs e) + { + if (Scroll != null) + Scroll(this, e); + } + + [Category("Behavior")] + public event EventHandler RowDraw; + protected virtual void OnRowDraw(PaintEventArgs e, TreeNodeAdv node, DrawContext context, int row, Rectangle rowRect) + { + if (RowDraw != null) + { + TreeViewRowDrawEventArgs args = new TreeViewRowDrawEventArgs(e.Graphics, e.ClipRectangle, node, context, row, rowRect); + RowDraw(this, args); + } + } + + /// + /// Fires when control is going to draw. Can be used to change text or back color + /// + [Category("Behavior")] + public event EventHandler DrawControl; + + internal bool DrawControlMustBeFired() + { + return DrawControl != null; + } + + internal void FireDrawControl(DrawEventArgs args) + { + OnDrawControl(args); + } + + protected virtual void OnDrawControl(DrawEventArgs args) + { + if (DrawControl != null) + DrawControl(this, args); + } + + + [Category("Drag Drop")] + public event EventHandler DropNodeValidating; + protected virtual void OnDropNodeValidating(Point point, ref TreeNodeAdv node) + { + if (DropNodeValidating != null) + { + DropNodeValidatingEventArgs args = new DropNodeValidatingEventArgs(point, node); + DropNodeValidating(this, args); + node = args.Node; + } + } + #endregion + + public TreeViewAdv() + { + InitializeComponent(); + SetStyle(ControlStyles.AllPaintingInWmPaint + | ControlStyles.UserPaint + | ControlStyles.OptimizedDoubleBuffer + | ControlStyles.ResizeRedraw + | ControlStyles.Selectable + , true); + + + if (Application.RenderWithVisualStyles) + _columnHeaderHeight = 20; + else + _columnHeaderHeight = 17; + + //BorderStyle = BorderStyle.Fixed3D; + _hScrollBar.Height = SystemInformation.HorizontalScrollBarHeight; + _vScrollBar.Width = SystemInformation.VerticalScrollBarWidth; + _rowLayout = new FixedRowHeightLayout(this, RowHeight); + _rowMap = new List(); + _selection = new List(); + _readonlySelection = new ReadOnlyCollection(_selection); + _columns = new TreeColumnCollection(this); + _toolTip = new ToolTip(); + + _measureContext = new DrawContext(); + _measureContext.Font = Font; + _measureContext.Graphics = Graphics.FromImage(new Bitmap(1, 1)); + + Input = new NormalInputState(this); + _search = new IncrementalSearch(this); + CreateNodes(); + CreatePens(); + + ArrangeControls(); + + _plusMinus = new NodePlusMinus(); + _controls = new NodeControlsCollection(this); + + Font = _font; + ExpandingIcon.IconChanged += ExpandingIconChanged; + } + + void ExpandingIconChanged(object sender, EventArgs e) + { + if (IsHandleCreated && !IsDisposed) + BeginInvoke(new MethodInvoker(DrawIcons)); + } + + private void DrawIcons() + { + using (Graphics gr = Graphics.FromHwnd(this.Handle)) + { + //Apply the same Graphics Transform logic as used in OnPaint. + int y = 0; + if (UseColumns) + { + y += ColumnHeaderHeight; + if (Columns.Count == 0) + return; + } + int firstRowY = _rowLayout.GetRowBounds(FirstVisibleRow).Y; + y -= firstRowY; + gr.ResetTransform(); + gr.TranslateTransform(-OffsetX, y); + + DrawContext context = new DrawContext(); + context.Graphics = gr; + for (int i = 0; i < _expandingNodes.Count; i++) + { + foreach (NodeControlInfo item in GetNodeControls(_expandingNodes[i])) + { + if (item.Control is ExpandingIcon) + { + Rectangle bounds = item.Bounds; + if (item.Node.Parent == null && UseColumns) + bounds.Location = Point.Empty; // display root expanding icon at 0,0 + + context.Bounds = bounds; + item.Control.Draw(item.Node, context); + } + } + } + } + } + + #region Public Methods + + public TreePath GetPath(TreeNodeAdv node) + { + if (node == _root) + return TreePath.Empty; + else + { + Stack stack = new Stack(); + while (node != _root && node != null) + { + stack.Push(node.Tag); + node = node.Parent; + } + return new TreePath(stack.ToArray()); + } + } + + public TreeNodeAdv GetNodeAt(Point point) + { + NodeControlInfo info = GetNodeControlInfoAt(point); + return info.Node; + } + + public NodeControlInfo GetNodeControlInfoAt(Point point) + { + if (point.X < 0 || point.Y < 0) + return NodeControlInfo.Empty; + + int row = _rowLayout.GetRowAt(point); + if (row < RowCount && row >= 0) + return GetNodeControlInfoAt(RowMap[row], point); + else + return NodeControlInfo.Empty; + } + + private NodeControlInfo GetNodeControlInfoAt(TreeNodeAdv node, Point point) + { + Rectangle rect = _rowLayout.GetRowBounds(FirstVisibleRow); + point.Y += (rect.Y - ColumnHeaderHeight); + point.X += OffsetX; + foreach (NodeControlInfo info in GetNodeControls(node)) + if (info.Bounds.Contains(point)) + return info; + + if (FullRowSelect) + return new NodeControlInfo(null, Rectangle.Empty, node); + else + return NodeControlInfo.Empty; + } + + public void BeginUpdate() + { + _suspendUpdate = true; + SuspendSelectionEvent = true; + } + + public void EndUpdate() + { + _suspendUpdate = false; + if (_needFullUpdate) + FullUpdate(); + else + UpdateView(); + SuspendSelectionEvent = false; + } + + public void ExpandAll() + { + _root.ExpandAll(); + } + + public void CollapseAll() + { + _root.CollapseAll(); + } + + /// + /// Expand all parent nodes, andd scroll to the specified node + /// + public void EnsureVisible(TreeNodeAdv node) + { + if (node == null) + throw new ArgumentNullException("node"); + + if (!IsMyNode(node)) + throw new ArgumentException(); + + TreeNodeAdv parent = node.Parent; + while (parent != _root) + { + parent.IsExpanded = true; + parent = parent.Parent; + } + ScrollTo(node); + } + + /// + /// Make node visible, scroll if needed. All parent nodes of the specified node must be expanded + /// + /// + public void ScrollTo(TreeNodeAdv node) + { + if (node == null) + throw new ArgumentNullException("node"); + + if (!IsMyNode(node)) + throw new ArgumentException(); + + if (node.Row < 0) + CreateRowMap(); + + int row = -1; + + if (node.Row < FirstVisibleRow) + row = node.Row; + else + { + int pageStart = _rowLayout.GetRowBounds(FirstVisibleRow).Top; + int rowBottom = _rowLayout.GetRowBounds(node.Row).Bottom; + if (rowBottom > pageStart + DisplayRectangle.Height - ColumnHeaderHeight) + row = _rowLayout.GetFirstRow(node.Row); + } + + if (row >= _vScrollBar.Minimum && row <= _vScrollBar.Maximum) + _vScrollBar.Value = row; + } + + public void ClearSelection() + { + BeginUpdate(); + try + { + ClearSelectionInternal(); + } + finally + { + EndUpdate(); + } + } + + internal void ClearSelectionInternal() + { + while (Selection.Count > 0) + { + var t = Selection[0]; + t.IsSelected = false; + Selection.Remove(t); //hack + } + } + + #endregion + + protected override void OnSizeChanged(EventArgs e) + { + ArrangeControls(); + SafeUpdateScrollBars(); + base.OnSizeChanged(e); + } + + private void ArrangeControls() + { + int hBarSize = _hScrollBar.Height; + int vBarSize = _vScrollBar.Width; + Rectangle clientRect = ClientRectangle; + + _hScrollBar.SetBounds(clientRect.X, clientRect.Bottom - hBarSize, + clientRect.Width - vBarSize, hBarSize); + + _vScrollBar.SetBounds(clientRect.Right - vBarSize, clientRect.Y, + vBarSize, clientRect.Height - hBarSize); + } + + private void SafeUpdateScrollBars() + { + if (InvokeRequired) + BeginInvoke(new MethodInvoker(UpdateScrollBars)); + else + UpdateScrollBars(); + } + + private void UpdateScrollBars() + { + UpdateVScrollBar(); + UpdateHScrollBar(); + UpdateVScrollBar(); + UpdateHScrollBar(); + _hScrollBar.Width = DisplayRectangle.Width; + _vScrollBar.Height = DisplayRectangle.Height; + } + + private void UpdateHScrollBar() + { + _hScrollBar.Maximum = ContentWidth; + _hScrollBar.LargeChange = Math.Max(DisplayRectangle.Width, 0); + _hScrollBar.SmallChange = 5; + _hScrollBar.Visible = _hScrollBar.LargeChange < _hScrollBar.Maximum; + _hScrollBar.Value = Math.Min(_hScrollBar.Value, _hScrollBar.Maximum - _hScrollBar.LargeChange + 1); + } + + private void UpdateVScrollBar() + { + _vScrollBar.Maximum = Math.Max(RowCount - 1, 0); + _vScrollBar.LargeChange = _rowLayout.PageRowCount; + _vScrollBar.Visible = (RowCount > 0) && (_vScrollBar.LargeChange <= _vScrollBar.Maximum); + _vScrollBar.Value = Math.Min(_vScrollBar.Value, _vScrollBar.Maximum - _vScrollBar.LargeChange + 1); + } + + protected override CreateParams CreateParams + { + [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)] + get + { + CreateParams res = base.CreateParams; + switch (BorderStyle) + { + case BorderStyle.FixedSingle: + res.Style |= 0x800000; + break; + case BorderStyle.Fixed3D: + res.ExStyle |= 0x200; + break; + } + return res; + } + } + + protected override void OnGotFocus(EventArgs e) + { + UpdateView(); + ChangeInput(); + base.OnGotFocus(e); + } + + protected override void OnFontChanged(EventArgs e) + { + base.OnFontChanged(e); + _measureContext.Font = Font; + FullUpdate(); + } + + internal IEnumerable GetNodeControls(TreeNodeAdv node) + { + if (node == null) + yield break; + Rectangle rowRect = _rowLayout.GetRowBounds(node.Row); + foreach (NodeControlInfo n in GetNodeControls(node, rowRect)) + yield return n; + } + + internal IEnumerable GetNodeControls(TreeNodeAdv node, Rectangle rowRect) + { + if (node == null) + yield break; + + int y = rowRect.Y; + int x = (node.Level - 1) * _indent + LeftMargin; + int width = 0; + if (node.Row == 0 && ShiftFirstNode) + x -= _indent; + Rectangle rect = Rectangle.Empty; + + if (ShowPlusMinus) + { + width = _plusMinus.GetActualSize(node, _measureContext).Width; + rect = new Rectangle(x, y, width, rowRect.Height); + if (UseColumns && Columns.Count > 0 && Columns[0].Width < rect.Right) + rect.Width = Columns[0].Width - x; + + yield return new NodeControlInfo(_plusMinus, rect, node); + x += width; + } + + if (!UseColumns) + { + foreach (NodeControl c in NodeControls) + { + Size s = c.GetActualSize(node, _measureContext); + if (!s.IsEmpty) + { + width = s.Width; + rect = new Rectangle(x, y, width, rowRect.Height); + x += rect.Width; + yield return new NodeControlInfo(c, rect, node); + } + } + } + else + { + int right = 0; + foreach (TreeColumn col in Columns) + { + if (col.IsVisible && col.Width > 0) + { + right += col.Width; + for (int i = 0; i < NodeControls.Count; i++) + { + NodeControl nc = NodeControls[i]; + if (nc.ParentColumn == col) + { + Size s = nc.GetActualSize(node, _measureContext); + if (!s.IsEmpty) + { + bool isLastControl = true; + for (int k = i + 1; k < NodeControls.Count; k++) + if (NodeControls[k].ParentColumn == col) + { + isLastControl = false; + break; + } + + width = right - x; + if (!isLastControl) + width = s.Width; + int maxWidth = Math.Max(0, right - x); + rect = new Rectangle(x, y, Math.Min(maxWidth, width), rowRect.Height); + x += width; + yield return new NodeControlInfo(nc, rect, node); + } + } + } + x = right; + } + } + } + } + + internal static double Dist(Point p1, Point p2) + { + return Math.Sqrt(Math.Pow(p1.X - p2.X, 2) + Math.Pow(p1.Y - p2.Y, 2)); + } + + public void FullUpdate() + { + HideEditor(); + if (InvokeRequired) + BeginInvoke(new MethodInvoker(UnsafeFullUpdate)); + else + UnsafeFullUpdate(); + } + + private void UnsafeFullUpdate() + { + _rowLayout.ClearCache(); + CreateRowMap(); + SafeUpdateScrollBars(); + UpdateView(); + _needFullUpdate = false; + } + + internal void UpdateView() + { + if (!_suspendUpdate) + Invalidate(false); + } + + internal void UpdateHeaders() + { + Invalidate(new Rectangle(0, 0, Width, ColumnHeaderHeight)); + } + + internal void UpdateColumns() + { + FullUpdate(); + } + + private void CreateNodes() + { + Selection.Clear(); + SelectionStart = null; + _root = new TreeNodeAdv(this, null); + _root.IsExpanded = true; + if (_root.Nodes.Count > 0) + CurrentNode = _root.Nodes[0]; + else + CurrentNode = null; + } + + internal void ReadChilds(TreeNodeAdv parentNode) + { + ReadChilds(parentNode, false); + } + + internal void ReadChilds(TreeNodeAdv parentNode, bool performFullUpdate) + { + if (!parentNode.IsLeaf) + { + parentNode.IsExpandedOnce = true; + parentNode.Nodes.Clear(); + + if (Model != null) + { + IEnumerable items = Model.GetChildren(GetPath(parentNode)); + if (items != null) + foreach (object obj in items) + { + AddNewNode(parentNode, obj, -1); + if (performFullUpdate) + FullUpdate(); + } + } + + if (parentNode.AutoExpandOnStructureChanged) + parentNode.ExpandAll(); + } + } + + private void AddNewNode(TreeNodeAdv parent, object tag, int index) + { + TreeNodeAdv node = new TreeNodeAdv(this, tag); + AddNode(parent, index, node); + } + + private void AddNode(TreeNodeAdv parent, int index, TreeNodeAdv node) + { + if (index >= 0 && index < parent.Nodes.Count) + parent.Nodes.Insert(index, node); + else + parent.Nodes.Add(node); + + node.IsLeaf = Model.IsLeaf(GetPath(node)); + if (node.IsLeaf) + node.Nodes.Clear(); + if (!LoadOnDemand || node.IsExpandedOnce) + ReadChilds(node); + } + + private struct ExpandArgs + { + public TreeNodeAdv Node; + public bool Value; + public bool IgnoreChildren; + } + + public void AbortBackgroundExpandingThreads() + { + _threadPool.CancelAll(true); + for (int i = 0; i < _expandingNodes.Count; i++) + _expandingNodes[i].IsExpandingNow = false; + _expandingNodes.Clear(); + Invalidate(); + } + + internal void SetIsExpanded(TreeNodeAdv node, bool value, bool ignoreChildren) + { + ExpandArgs eargs = new ExpandArgs(); + eargs.Node = node; + eargs.Value = value; + eargs.IgnoreChildren = ignoreChildren; + + if (AsyncExpanding && LoadOnDemand && !_threadPool.IsMyThread(Thread.CurrentThread)) + { + WaitCallback wc = delegate(object argument) { SetIsExpanded((ExpandArgs)argument); }; + _threadPool.QueueUserWorkItem(wc, eargs); + } + else + SetIsExpanded(eargs); + } + + private void SetIsExpanded(ExpandArgs eargs) + { + bool update = !eargs.IgnoreChildren && !AsyncExpanding; + if (update) + BeginUpdate(); + try + { + if (IsMyNode(eargs.Node) && eargs.Node.IsExpanded != eargs.Value) + SetIsExpanded(eargs.Node, eargs.Value); + + if (!eargs.IgnoreChildren) + SetIsExpandedRecursive(eargs.Node, eargs.Value); + } + finally + { + if (update) + EndUpdate(); + } + } + + internal void SetIsExpanded(TreeNodeAdv node, bool value) + { + if (Root == node && !value) + return; //Can't collapse root node + + if (value) + { + OnExpanding(node); + node.OnExpanding(); + } + else + { + OnCollapsing(node); + node.OnCollapsing(); + } + + if (value && !node.IsExpandedOnce) + { + if (AsyncExpanding && LoadOnDemand) + { + AddExpandingNode(node); + node.AssignIsExpanded(true); + Invalidate(); + } + ReadChilds(node, AsyncExpanding); + RemoveExpandingNode(node); + } + node.AssignIsExpanded(value); + SmartFullUpdate(); + + if (value) + { + OnExpanded(node); + node.OnExpanded(); + } + else + { + OnCollapsed(node); + node.OnCollapsed(); + } + } + + private void RemoveExpandingNode(TreeNodeAdv node) + { + node.IsExpandingNow = false; + _expandingNodes.Remove(node); + if (_expandingNodes.Count <= 0) + ExpandingIcon.Stop(); + } + + private void AddExpandingNode(TreeNodeAdv node) + { + node.IsExpandingNow = true; + _expandingNodes.Add(node); + ExpandingIcon.Start(); + } + + internal void SetIsExpandedRecursive(TreeNodeAdv root, bool value) + { + for (int i = 0; i < root.Nodes.Count; i++) + { + TreeNodeAdv node = root.Nodes[i]; + node.IsExpanded = value; + SetIsExpandedRecursive(node, value); + } + } + + private void CreateRowMap() + { + RowMap.Clear(); + int row = 0; + _contentWidth = 0; + foreach (TreeNodeAdv node in VisibleNodes) + { + node.Row = row; + RowMap.Add(node); + if (!UseColumns) + { + _contentWidth = Math.Max(_contentWidth, GetNodeWidth(node)); + } + row++; + } + if (UseColumns) + { + _contentWidth = 0; + foreach (TreeColumn col in _columns) + if (col.IsVisible) + _contentWidth += col.Width; + } + } + + private int GetNodeWidth(TreeNodeAdv node) + { + if (node.RightBounds == null) + { + Rectangle res = GetNodeBounds(GetNodeControls(node, Rectangle.Empty)); + node.RightBounds = res.Right; + } + return node.RightBounds.Value; + } + + internal Rectangle GetNodeBounds(TreeNodeAdv node) + { + return GetNodeBounds(GetNodeControls(node)); + } + + private Rectangle GetNodeBounds(IEnumerable nodeControls) + { + Rectangle res = Rectangle.Empty; + foreach (NodeControlInfo info in nodeControls) + { + if (res == Rectangle.Empty) + res = info.Bounds; + else + res = Rectangle.Union(res, info.Bounds); + } + return res; + } + + private void _vScrollBar_ValueChanged(object sender, EventArgs e) + { + FirstVisibleRow = _vScrollBar.Value; + } + + private void _hScrollBar_ValueChanged(object sender, EventArgs e) + { + OffsetX = _hScrollBar.Value; + } + + private void _vScrollBar_Scroll(object sender, ScrollEventArgs e) + { + OnScroll(e); + } + + private void _hScrollBar_Scroll(object sender, ScrollEventArgs e) + { + OnScroll(e); + } + + internal void SmartFullUpdate() + { + if (_suspendUpdate) + _needFullUpdate = true; + else + FullUpdate(); + } + + internal bool IsMyNode(TreeNodeAdv node) + { + if (node == null) + return false; + + if (node.Tree != this) + return false; + + while (node.Parent != null) + node = node.Parent; + + return node == _root; + } + + internal void UpdateSelection() + { + bool flag = false; + + if (!IsMyNode(CurrentNode)) + CurrentNode = null; + if (!IsMyNode(_selectionStart)) + _selectionStart = null; + + for (int i = Selection.Count - 1; i >= 0; i--) + if (!IsMyNode(Selection[i])) + { + flag = true; + Selection.RemoveAt(i); + } + + if (flag) + OnSelectionChanged(); + } + + internal void ChangeColumnWidth(TreeColumn column) + { + if (!(_input is ResizeColumnState)) + { + FullUpdate(); + OnColumnWidthChanged(column); + } + } + + public TreeNodeAdv FindNode(TreePath path) + { + return FindNode(path, false); + } + + public TreeNodeAdv FindNode(TreePath path, bool readChilds) + { + if (path.IsEmpty()) + return _root; + else + return FindNode(_root, path, 0, readChilds); + } + + private TreeNodeAdv FindNode(TreeNodeAdv root, TreePath path, int level, bool readChilds) + { + if (!root.IsExpandedOnce && readChilds) + ReadChilds(root); + + for (int i = 0; i < root.Nodes.Count; i++) + { + TreeNodeAdv node = root.Nodes[i]; + if (node.Tag == path.FullPath[level]) + { + if (level == path.FullPath.Length - 1) + return node; + else + return FindNode(node, path, level + 1, readChilds); + } + } + return null; + } + + public TreeNodeAdv FindNodeByTag(object tag) + { + return FindNodeByTag(_root, tag); + } + + private TreeNodeAdv FindNodeByTag(TreeNodeAdv root, object tag) + { + foreach (TreeNodeAdv node in root.Nodes) + { + if (node.Tag == tag) + return node; + TreeNodeAdv res = FindNodeByTag(node, tag); + if (res != null) + return res; + } + return null; + } + + public void SelectAllNodes() + { + SuspendSelectionEvent = true; + try + { + if (SelectionMode == TreeSelectionMode.MultiSameParent) + { + if (CurrentNode != null) + { + foreach (TreeNodeAdv n in CurrentNode.Parent.Nodes) + n.IsSelected = true; + } + } + else if (SelectionMode == TreeSelectionMode.Multi) + { + SelectNodes(Root.Nodes); + } + } + finally + { + SuspendSelectionEvent = false; + } + } + + private void SelectNodes(Collection nodes) + { + foreach (TreeNodeAdv n in nodes) + { + n.IsSelected = true; + if (n.IsExpanded) + SelectNodes(n.Nodes); + } + } + + #region ModelEvents + private void BindModelEvents() + { + _model.NodesChanged += new EventHandler(_model_NodesChanged); + _model.NodesInserted += new EventHandler(_model_NodesInserted); + _model.NodesRemoved += new EventHandler(_model_NodesRemoved); + _model.StructureChanged += new EventHandler(_model_StructureChanged); + } + + private void UnbindModelEvents() + { + _model.NodesChanged -= new EventHandler(_model_NodesChanged); + _model.NodesInserted -= new EventHandler(_model_NodesInserted); + _model.NodesRemoved -= new EventHandler(_model_NodesRemoved); + _model.StructureChanged -= new EventHandler(_model_StructureChanged); + } + + private void _model_StructureChanged(object sender, TreePathEventArgs e) + { + if (e.Path == null) + throw new ArgumentNullException(); + + TreeNodeAdv node = FindNode(e.Path); + if (node != null) + { + if (node != Root) + node.IsLeaf = Model.IsLeaf(GetPath(node)); + + var list = new Dictionary(); + SaveExpandedNodes(node, list); + ReadChilds(node); + RestoreExpandedNodes(node, list); + + UpdateSelection(); + SmartFullUpdate(); + } + //else + // throw new ArgumentException("Path not found"); + } + + private void RestoreExpandedNodes(TreeNodeAdv node, Dictionary list) + { + if (node.Tag != null && list.ContainsKey(node.Tag)) + { + node.IsExpanded = true; + foreach (var child in node.Children) + RestoreExpandedNodes(child, list); + } + } + + private void SaveExpandedNodes(TreeNodeAdv node, Dictionary list) + { + if (node.IsExpanded && node.Tag != null) + { + list.Add(node.Tag, null); + foreach (var child in node.Children) + SaveExpandedNodes(child, list); + } + } + + private void _model_NodesRemoved(object sender, TreeModelEventArgs e) + { + TreeNodeAdv parent = FindNode(e.Path); + if (parent != null) + { + if (e.Indices != null) + { + List list = new List(e.Indices); + list.Sort(); + for (int n = list.Count - 1; n >= 0; n--) + { + int index = list[n]; + if (index >= 0 && index <= parent.Nodes.Count) + parent.Nodes.RemoveAt(index); + else + throw new ArgumentOutOfRangeException("Index out of range"); + } + } + else + { + for (int i = parent.Nodes.Count - 1; i >= 0; i--) + { + for (int n = 0; n < e.Children.Length; n++) + if (parent.Nodes[i].Tag == e.Children[n]) + { + parent.Nodes.RemoveAt(i); + break; + } + } + } + } + UpdateSelection(); + SmartFullUpdate(); + } + + private void _model_NodesInserted(object sender, TreeModelEventArgs e) + { + if (e.Indices == null) + throw new ArgumentNullException("Indices"); + + TreeNodeAdv parent = FindNode(e.Path); + if (parent != null) + { + for (int i = 0; i < e.Children.Length; i++) + AddNewNode(parent, e.Children[i], e.Indices[i]); + } + SmartFullUpdate(); + } + + private void _model_NodesChanged(object sender, TreeModelEventArgs e) + { + TreeNodeAdv parent = FindNode(e.Path); + if (parent != null && parent.IsVisible && parent.IsExpanded) + { + if (InvokeRequired) + BeginInvoke(new UpdateContentWidthDelegate(ClearNodesSize), e, parent); + else + ClearNodesSize(e, parent); + SmartFullUpdate(); + } + } + + private delegate void UpdateContentWidthDelegate(TreeModelEventArgs e, TreeNodeAdv parent); + private void ClearNodesSize(TreeModelEventArgs e, TreeNodeAdv parent) + { + if (e.Indices != null) + { + foreach (int index in e.Indices) + { + if (index >= 0 && index < parent.Nodes.Count) + { + TreeNodeAdv node = parent.Nodes[index]; + node.Height = node.RightBounds = null; + } + else + throw new ArgumentOutOfRangeException("Index out of range"); + } + } + else + { + foreach (TreeNodeAdv node in parent.Nodes) + { + foreach (object obj in e.Children) + if (node.Tag == obj) + { + node.Height = node.RightBounds = null; + } + } + } + } + #endregion + } +} diff -r 3145aadca3d2 -r 0c551e8818e0 External/Aga.Controls/Tree/TreeViewAdv.resx --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/External/Aga.Controls/Tree/TreeViewAdv.resx Sun May 27 15:16:19 2012 +0000 @@ -0,0 +1,132 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 + + + 127, 17 + + + 17, 17 + + + 236, 17 + + + False + + \ No newline at end of file diff -r 3145aadca3d2 -r 0c551e8818e0 External/Aga.Controls/Tree/TreeViewAdvCancelEventArgs.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/External/Aga.Controls/Tree/TreeViewAdvCancelEventArgs.cs Sun May 27 15:16:19 2012 +0000 @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Aga.Controls.Tree +{ + public class TreeViewAdvCancelEventArgs : TreeViewAdvEventArgs + { + private bool _cancel; + + public bool Cancel + { + get { return _cancel; } + set { _cancel = value; } + } + + public TreeViewAdvCancelEventArgs(TreeNodeAdv node) + : base(node) + { + } + + } +} diff -r 3145aadca3d2 -r 0c551e8818e0 External/Aga.Controls/Tree/TreeViewAdvEventArgs.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/External/Aga.Controls/Tree/TreeViewAdvEventArgs.cs Sun May 27 15:16:19 2012 +0000 @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Aga.Controls.Tree +{ + public class TreeViewAdvEventArgs : EventArgs + { + private TreeNodeAdv _node; + + public TreeNodeAdv Node + { + get { return _node; } + } + + public TreeViewAdvEventArgs(TreeNodeAdv node) + { + _node = node; + } + } +} diff -r 3145aadca3d2 -r 0c551e8818e0 External/Aga.Controls/Tree/TreeViewRowDrawEventArgs.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/External/Aga.Controls/Tree/TreeViewRowDrawEventArgs.cs Sun May 27 15:16:19 2012 +0000 @@ -0,0 +1,46 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Windows.Forms; +using System.Drawing; + +namespace Aga.Controls.Tree +{ + public class TreeViewRowDrawEventArgs: PaintEventArgs + { + TreeNodeAdv _node; + DrawContext _context; + int _row; + Rectangle _rowRect; + + public TreeViewRowDrawEventArgs(Graphics graphics, Rectangle clipRectangle, TreeNodeAdv node, DrawContext context, int row, Rectangle rowRect) + : base(graphics, clipRectangle) + { + _node = node; + _context = context; + _row = row; + _rowRect = rowRect; + } + + public TreeNodeAdv Node + { + get { return _node; } + } + + public DrawContext Context + { + get { return _context; } + } + + public int Row + { + get { return _row; } + } + + public Rectangle RowRect + { + get { return _rowRect; } + } + } + +} diff -r 3145aadca3d2 -r 0c551e8818e0 External/Aga.Controls/license.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/External/Aga.Controls/license.txt Sun May 27 15:16:19 2012 +0000 @@ -0,0 +1,25 @@ +The BSD License + +Copyright (c) 2009, Andrey Gliznetsov (a.gliznetsov@gmail.com) + +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided +that the following conditions are met + +- Redistributions of source code must retain the above copyright notice, this list of conditions +and the following disclaimer. +- Redistributions in binary form must reproduce the above copyright notice, this list of conditions +and the following disclaimer in the documentation andor other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +AS IS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file