/*
Embroidery Reader - an application to view .pes embroidery designs

Copyright (C) 2019 Nathan Crawford
 
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.
 
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA.

A copy of the full GPL 2 license can be found in the docs directory.
You can contact me at http://www.njcrawford.com/contact
*/


using System;
using System.Drawing;
using System.Windows.Forms;
using System.Reflection;
using System.Drawing.Imaging;
using System.Drawing.Drawing2D;

namespace embroideryReader
{
    public partial class frmMain : Form
    {
        private string[] args;
        private Pen drawPen = Pens.Black;
        private Bitmap DrawArea;
        private PesFile.PesFile design;
        private EmbroideryReaderSettings settings = new EmbroideryReaderSettings();

        private const String APP_TITLE = "Embroidery Reader";

        private Translation translation;

        private float designScale = 1.0f;
        private Size panel2LastUpdateSize;
        private bool maximizeChanged = false;
        private int designRotation = 0;
        private string loadedFileName = "";

        public frmMain()
        {
            InitializeComponent();
            args = Environment.GetCommandLineArgs();
        }

        private void LoadSettings(bool reload)
        {
            if (settings.backgroundColorEnabled)
            {
                panel2.BackColor = settings.backgroundColor;
            }
            else
            {
                panel2.BackColor = Color.FromKnownColor(KnownColor.Control);
            }
            if (!reload)
            {
                if (settings.windowMaximized)
                {
                    // Check maximized first
                    this.WindowState = FormWindowState.Maximized;
                }
                else
                {
                    // Not maximized, restore last saved window size
                    this.Width = settings.windowWidth;
                    this.Height = settings.windowHeight;
                }
            }
            SetDesignScaleSetting(1.0f, settings.AutoScaleDesign, false);
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            // Set app window title
            this.Text = APP_TITLE;

            // Load and check settings
            LoadSettings(false);
            
            // Load translation
            LoadTranslatedStrings(settings.translation);

            // Load design, if specified
            if (args.Length > 1)
            {
                OpenFile(args[1]);
            }
        }

        // WndProc values
        // See https://msdn.microsoft.com/en-us/library/windows/desktop/ms646360(v=vs.85).aspx for more info
        const int WM_SYSCOMMAND = 0x0112;
        const int SC_MAXIMIZE = 0xF030;
        const int SC_MINIMIZE = 0xF020;
        const int SC_RESTORE = 0xF120;
        const int SC_WPARAM_MASK = 0xFFF0;

        // Override WndProc to capture maximize and restore events
        protected override void WndProc(ref Message m)
        {
            if (m.Msg == WM_SYSCOMMAND)
            {
                // Check your window state here
                int maskedWParam = m.WParam.ToInt32() & SC_WPARAM_MASK;
                if (maskedWParam == SC_MAXIMIZE ||
                    maskedWParam == SC_MINIMIZE ||
                    maskedWParam == SC_RESTORE)
                {
                    maximizeChanged = true;
                }
            }
            base.WndProc(ref m);
        }

        public static bool CheckColorFromStrings(string red, string green, string blue)
        {
            byte redByte;
            byte greenByte;
            byte blueByte;
            bool retval = false;
            if (String.IsNullOrEmpty(red) || String.IsNullOrEmpty(green) || String.IsNullOrEmpty(blue))
            {
                retval = false;
            }
            else
            {
                try
                {
                    redByte = Convert.ToByte(red);
                    greenByte = Convert.ToByte(green);
                    blueByte = Convert.ToByte(blue);
                    retval = true;
                }
                catch (FormatException /* ex */)
                {
                    retval = false;
                }
                catch (OverflowException /* ex */)
                {
                    retval = false;
                }
            }
            return retval;
        }

        public static Color MakeColorFromStrings(string red, string green, string blue)
        {
            if (CheckColorFromStrings(red, green, blue))
            {
                return Color.FromArgb(Convert.ToByte(red), Convert.ToByte(green), Convert.ToByte(blue));
            }
            else
            {
                return Color.Red;
            }
        }

        private void UpdateDesignImage()
        {
            if(design == null)
            {
                // No design loaded - nothing to update
                return;
            }

            // Assume 96 DPI until we can come up with a better way to calculate it
            float screenDPI = 96;

            Bitmap tempImage = design.DesignToBitmap((float)settings.threadThickness, (settings.filterStiches), settings.filterStitchesThreshold, (screenDPI / design.NativeDPI));

            // Rotate image
            switch (designRotation)
            {
                case 90:
                    tempImage.RotateFlip(RotateFlipType.Rotate90FlipNone);
                    break;
                case 180:
                    tempImage.RotateFlip(RotateFlipType.Rotate180FlipNone);
                    break;
                case 270:
                    tempImage.RotateFlip(RotateFlipType.Rotate270FlipNone);
                    break;
            }

            // Scale image
            if (fitToWindowToolStripMenuItem.Checked)
            {
                // Calculate size of image based on available drawing area
                float windowWidth = panel2.Width - 3;
                float windowHeight = panel2.Height - 3;
                
                // Figure out which dimension is more constrained
                float widthScale = windowWidth / tempImage.Width;
                float heightScale = windowHeight / tempImage.Height;
                if (widthScale < heightScale)
                {
                    designScale = widthScale;
                }
                else
                {
                    designScale = heightScale;
                }
            }

            int width = (int)(tempImage.Width * designScale);
            int height = (int)(tempImage.Height * designScale);

            if (width < 1 || height < 1)
            {
                // Image area is too small to update
                return;
            }

            if (width != tempImage.Width || height != tempImage.Height)
            {
                // Scale image code from http://stackoverflow.com/questions/1922040/resize-an-image-c-sharp
                Rectangle destRect = new Rectangle(0, 0, width, height);
                Bitmap scaledImage = new Bitmap(width, height);

                scaledImage.SetResolution(tempImage.HorizontalResolution, tempImage.VerticalResolution);

                using (var graphics = Graphics.FromImage(scaledImage))
                {
                    graphics.CompositingMode = CompositingMode.SourceCopy;
                    graphics.CompositingQuality = CompositingQuality.HighQuality;
                    graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
                    graphics.SmoothingMode = SmoothingMode.HighQuality;
                    graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;

                    using (var wrapMode = new ImageAttributes())
                    {
                        wrapMode.SetWrapMode(WrapMode.TileFlipXY);
                        graphics.DrawImage(tempImage, destRect, 0, 0, tempImage.Width, tempImage.Height, GraphicsUnit.Pixel, wrapMode);
                    }
                }
                // Keep the scaled image and dispose the intermediate image
                tempImage.Dispose();
                tempImage = scaledImage;
            }

            // About to abandon the current DrawArea object, dispose it now
            if(DrawArea != null)
            {
                DrawArea.Dispose();
                DrawArea = null;
            }

            // Add transparency grid
            if (settings.transparencyGridEnabled)
            {
                DrawArea = new Bitmap(tempImage.Width, tempImage.Height);
                using (Graphics g = Graphics.FromImage(DrawArea))
                {
                    Color gridColor = settings.transparencyGridColor;
                    using (Pen gridPen = new Pen(gridColor))
                    {
                        int gridSize = settings.transparencyGridSize;
                        for (int xStart = 0; (xStart * gridSize) < DrawArea.Width; xStart++)
                        {
                            for (int yStart = 0; (yStart * gridSize) < DrawArea.Height; yStart++)
                            {
                                // Fill even columns in even rows and odd columns in odd rows
                                if ((xStart % 2) == (yStart % 2))
                                {
                                    g.FillRectangle(gridPen.Brush, (xStart * gridSize), (yStart * gridSize), gridSize, gridSize);
                                }
                            }
                        }
                    }

                    g.DrawImage(tempImage, 0, 0);

                    // Done with tempImage
                    tempImage.Dispose();
                    tempImage = null;
                }
            }
            else
            {
                // Keeping the object tempImage was pointing at, so don't dispose it
                DrawArea = tempImage;
            }

            panel1.Width = DrawArea.Width;
            panel1.Height = DrawArea.Height;
            panel1.Invalidate();

            panel2LastUpdateSize = panel2.Size;

            // Update window title
            this.Text = System.IO.Path.GetFileName(loadedFileName) + " (" + (designScale * 100).ToString("0") + "%) - " + APP_TITLE;
        }

        private void OpenFile(string filename)
        {
            if (!System.IO.File.Exists(filename))
            {
                // "An error occured while reading the file:"
                MessageBox.Show(Translation.StringID.ERROR_FILE + Environment.NewLine + "File \"" + filename + "\" does not exist", "File not found", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                return;
            }

            try
            {
                design = new PesFile.PesFile(filename);
            }
            catch(System.IO.IOException ioex)
            {
                // "An error occured while reading the file:"
                MessageBox.Show(Translation.StringID.ERROR_FILE + Environment.NewLine + filename + ":" + Environment.NewLine + ioex.Message, "IOException", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                design = null;
            }
            catch(PesFile.PECFormatException pecex)
            {
                // "This file is either corrupt or not a valid PES file."
                MessageBox.Show(Translation.StringID.ERROR_FILE + Environment.NewLine + filename + ":" + Environment.NewLine + pecex.Message, "PECFormatException", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                design = null;
            }

            loadedFileName = filename;
            if (design != null)
            {
                UpdateDesignImage();

                if (design.GetFormatWarning())
                {
                    toolStripStatusLabel1.Text = translation.GetTranslatedString(Translation.StringID.UNSUPPORTED_FORMAT); // "The format of this file is not completely supported";
                }
                else if (design.GetColorWarning())
                {
                    toolStripStatusLabel1.Text = translation.GetTranslatedString(Translation.StringID.COLOR_WARNING); // "Colors shown for this design may be inaccurate"
                }
                else
                {
                    toolStripStatusLabel1.Text = "";
                }

                copyToolStripMenuItem.Enabled = true;
                saveDebugInfoToolStripMenuItem.Enabled = true;
                printPreviewToolStripMenuItem.Enabled = true;
                printToolStripMenuItem.Enabled = true;
                rotateLeftToolStripMenuItem.Enabled = true;
                rotateRightToolStripMenuItem.Enabled = true;
                refreshToolStripMenuItem.Enabled = true;
                zoomToolStripMenuItem.Enabled = true;
                showDebugInfoToolStripMenuItem.Enabled = true;
                saveAsBitmapToolStripMenuItem.Enabled = true;
                panel2.Select();
            }
            else
            {
                copyToolStripMenuItem.Enabled = false;
                saveDebugInfoToolStripMenuItem.Enabled = false;
                printPreviewToolStripMenuItem.Enabled = false;
                printToolStripMenuItem.Enabled = false;
                rotateLeftToolStripMenuItem.Enabled = false;
                rotateRightToolStripMenuItem.Enabled = false;
                refreshToolStripMenuItem.Enabled = false;
                showDebugInfoToolStripMenuItem.Enabled = false;
                saveAsBitmapToolStripMenuItem.Enabled = false;
            }
        }

        private void openToolStripMenuItem_Click(object sender, EventArgs e)
        {
            string filename;
            if (settings.lastOpenFileFolder != null)
            {
                openFileDialog1.InitialDirectory = settings.lastOpenFileFolder;
            }
            openFileDialog1.FileName = "";
            openFileDialog1.Filter = translation.GetTranslatedString(Translation.StringID.FILE_TYPE_PES) + " (*.pes)|*.pes|" + // "Embroidery Files (*.pes)|*.pes|
                translation.GetTranslatedString(Translation.StringID.FILE_TYPE_ALL) + " (*.*)|*.*"; // All Files (*.*)|*.*";
            if (openFileDialog1.ShowDialog() == DialogResult.OK)
            {
                filename = openFileDialog1.FileName;
                if (!System.IO.File.Exists(filename))
                {
                    return;
                }
                else
                {
                    settings.lastOpenFileFolder = System.IO.Path.GetDirectoryName(filename);
                    OpenFile(filename);
                }
            }
        }

        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void panel1_Paint(object sender, PaintEventArgs e)
        {
            if (DrawArea != null)
            {
                e.Graphics.DrawImage(DrawArea, 0, 0);
            }
        }

        private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
        {
            string message = String.Format(translation.GetTranslatedString(Translation.StringID.ABOUT_MESSAGE), CurrentVersion()); // "EmbroideryReader version " + currentVersion() + ". This program reads and displays embroidery designs from .PES files."
            //message += Environment.NewLine;
            //message += Environment.NewLine + "GUI GDI count: " + GuiResources.GetGuiResourcesGDICount();
            //message += Environment.NewLine + "GUI USER count: " + GuiResources.GetGuiResourcesUserCount();
            //message += Environment.NewLine + ".Net framework version: " + Environment.Version;
            MessageBox.Show(message);
        }

        private void checkForUpdateToolStripMenuItem_Click(object sender, EventArgs e)
        {
            EmbroideryReaderUpdates updater = new EmbroideryReaderUpdates(settings.updateLocation, null, null);
            updater.waitForInfo();

            if (updater.GetLastError() != "")
            {
                MessageBox.Show(translation.GetTranslatedString(Translation.StringID.ERROR_UPDATE) + // "Encountered an error while checking for updates: "
                    updater.GetLastError());
            }
            else if (updater.IsUpdateAvailable())
            {
                if (MessageBox.Show(String.Format(translation.GetTranslatedString(Translation.StringID.NEW_VERSION_MESSAGE),
                    updater.VersionAvailable(), updater.getReleaseDate().ToShortDateString(), CurrentVersion()) + // "Version " + updater.VersionAvailable() + " was released on " + updater.getReleaseDate().ToShortDateString() + ". You have version " + currentVersion() + "."
                    Environment.NewLine +
                    translation.GetTranslatedString(Translation.StringID.NEW_VERSION_QUESTION), // "Would you like to go to the Embroidery Reader website to download or find out more about the new version?",
                    translation.GetTranslatedString(Translation.StringID.NEW_VERSION_TITLE), // "New version available",
                    MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
                {
                    try
                    {
                        System.Diagnostics.Process.Start(updater.getMoreInfoURL());
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show(translation.GetTranslatedString(Translation.StringID.ERROR_WEBPAGE) + // "An error occured while trying to open the webpage:"
                             Environment.NewLine + ex.ToString());
                    }
                }
            }
            else
            {
                MessageBox.Show(translation.GetTranslatedString(Translation.StringID.NO_UPDATE) + // "No updates are available right now."
                     Environment.NewLine + 
                     String.Format(translation.GetTranslatedString(Translation.StringID.LATEST_VERSION),
                     updater.VersionAvailable(), CurrentVersion())); // "(Latest version is " + updater.VersionAvailable() + ", you have version " + currentVersion() + ")");
            }
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (this.WindowState == FormWindowState.Maximized)
            {
                settings.windowMaximized = true;
            }
            else
            {
                settings.windowMaximized = false;

                if (this.WindowState == FormWindowState.Normal)
                {
                    // If window is not minimized or maximized, save current size
                    settings.windowWidth = this.Width;
                    settings.windowHeight = this.Height;
                }
            }
            try
            {
                settings.save();
            }
            catch (System.IO.IOException /*ioex*/)
            {
                // Ignore IO exceptions when saving settings file, to deal with crashes caused by
                // closing many windows at once.

                // This isn't a great way to handle the problem, but it's better than getting
                // the same automated error report over and over.
            }
        }

        private string CurrentVersion()
        {
            return Assembly.GetExecutingAssembly().GetName().Version.ToString();
        }

        private void saveDebugInfoToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (design != null)
            {
                try
                {
                    string debugFile = design.SaveDebugInfo();
                    MessageBox.Show(String.Format(translation.GetTranslatedString(Translation.StringID.DEBUG_INFO_SAVED), // "Saved debug info to " + debugFile
                        debugFile));
                }
                catch (Exception ex)
                {
                    MessageBox.Show(translation.GetTranslatedString(Translation.StringID.ERROR_DEBUG) + // "There was an error while saving debug info:"
                        Environment.NewLine + ex.ToString());
                }
            }
            else
            {
                MessageBox.Show(translation.GetTranslatedString(Translation.StringID.NO_DESIGN)); // "No design loaded."
            }
        }

        private void preferencesToolStripMenuItem_Click(object sender, EventArgs e)
        {
            frmSettingsDialog tempForm = new frmSettingsDialog();
            tempForm.settingsToModify = settings;
            tempForm.setTranslation = translation;
            if (tempForm.ShowDialog() == DialogResult.OK)
            {
                settings = tempForm.settingsToModify;
                LoadSettings(true);
                UpdateDesignImage();
            }
            LoadTranslatedStrings(settings.translation);
        }

        private void printToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (printDialog1.ShowDialog() == DialogResult.OK)
            {
                printDocument1.Print();
            }
        }

        private void printDocument1_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e)
        {
            if (design != null)
            {
                // Note: scaling based on reported printer DPI may produce terrible results in some
                // cases. The reported DPI can even be a negative number, which indicates a general print
                // quality. So, future self, for the sake of your sanity... just don't do it. :-)
                // See https://msdn.microsoft.com/en-us/library/system.drawing.printing.printerresolution.x(v=vs.110).aspx
                // for more detail.

                // Calculate scale values for print graphics object (100 dpi seems to be the default
                // for the printer graphics object)
                double graphicsXScaleFactor = (100.0 / design.NativeDPI);
                double graphicsYScaleFactor = (100.0 / design.NativeDPI);

                // Check for scale out of range
                if(graphicsXScaleFactor < 0.001 || graphicsXScaleFactor > 100.0)
                {
                    throw new ArgumentOutOfRangeException("Print X graphics scale is '" + graphicsXScaleFactor + "', expected range is 0.001 - 100.0");
                }
                if (graphicsYScaleFactor < 0.001 || graphicsYScaleFactor > 100.0)
                {
                    throw new ArgumentOutOfRangeException("Print Y graphics scale is '" + graphicsYScaleFactor + "', expected range is 0.001 - 100.0");
                }

                // Set print graphics object scale and draw the image
                e.Graphics.ScaleTransform((float)graphicsXScaleFactor, (float)graphicsYScaleFactor);
                using (Bitmap tempDrawArea = design.DesignToBitmap((float)settings.threadThickness, settings.filterStiches, settings.filterStitchesThreshold, 1.0f))
                {
                    e.Graphics.DrawImage(tempDrawArea, 30, 30);
                }
            }
        }

        private void printPreviewToolStripMenuItem_Click(object sender, EventArgs e)
        {
            try
            {
                printPreviewDialog1.Document = printDocument1;
                printPreviewDialog1.ShowDialog();
            }
            catch(System.Drawing.Printing.InvalidPrinterException pex)
            {
                MessageBox.Show("Unable to find a default printer: " + pex.Message + Environment.NewLine + Environment.NewLine + "Possible reasons include: no printers are installed, or no printer is set as the default.");
            }
        }

        private void copyToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (DrawArea != null)
            {
                Clipboard.Clear();
                using (Bitmap temp = new Bitmap(DrawArea.Width, DrawArea.Height, System.Drawing.Imaging.PixelFormat.Format24bppRgb))
                {
                    using (Graphics tempGraph = Graphics.FromImage(temp))
                    {
                        tempGraph.FillRectangle(Brushes.White, 0, 0, temp.Width, temp.Height);
                        tempGraph.DrawImageUnscaled(DrawArea, 0, 0);
                    }
                    Clipboard.SetImage(temp);
                }
            }
        }

        private void refreshToolStripMenuItem_Click(object sender, EventArgs e)
        {
            designRotation = 0;
            UpdateDesignImage();
        }

        private void rotateLeftToolStripMenuItem_Click(object sender, EventArgs e)
        {
            designRotation -= 90;
            if(designRotation < 0)
            {
                designRotation += 360;
            }
            UpdateDesignImage();
        }

        private void rotateRightToolStripMenuItem_Click(object sender, EventArgs e)
        {
            designRotation += 90;
            if (designRotation >= 360)
            {
                designRotation -= 360;
            }
            UpdateDesignImage();
        }

        private void showDebugInfoToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (design != null)
            {
                try
                {
                    frmTextbox theform = new frmTextbox();
                    theform.showText(design.GetDebugInfo());
                }
                catch (Exception ex)
                {
                    MessageBox.Show(translation.GetTranslatedString(Translation.StringID.ERROR_DEBUG) + // "There was an error while saving debug info:"
                        Environment.NewLine + ex.ToString());
                }
            }
            else
            {
                MessageBox.Show(translation.GetTranslatedString(Translation.StringID.NO_DESIGN)); // "No design loaded."
            }
        }

        private void saveAsBitmapToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (DrawArea != null)
            {
                using (Bitmap temp = new Bitmap(DrawArea.Width, DrawArea.Height, System.Drawing.Imaging.PixelFormat.Format24bppRgb))
                {
                    using (Graphics tempGraph = Graphics.FromImage(temp))
                    {
                        tempGraph.FillRectangle(Brushes.White, 0, 0, temp.Width, temp.Height);
                        tempGraph.DrawImageUnscaled(DrawArea, 0, 0);
                    }
                    saveFileDialog1.FileName = "";
                    // "Bitmap (*.bmp)|*.bmp|PNG (*.png)|*.png|JPEG (*.jpg)|*.jpg|GIF (*.gif)|*.gif|TIFF (*.tif)|*.tif|All Files (*.*)|*.*"
                    saveFileDialog1.Filter = translation.GetTranslatedString(Translation.StringID.FILE_TYPE_BMP) + " (*.bmp)|*.bmp|" +
                        translation.GetTranslatedString(Translation.StringID.FILE_TYPE_PNG) + " (*.png)|*.png|" +
                        translation.GetTranslatedString(Translation.StringID.FILE_TYPE_JPG) + " (*.jpg)|*.jpg|" +
                        translation.GetTranslatedString(Translation.StringID.FILE_TYPE_GIF) + " (*.gif)|*.gif|" +
                        translation.GetTranslatedString(Translation.StringID.FILE_TYPE_TIFF) + " (*.tif)|*.tif|" +
                        translation.GetTranslatedString(Translation.StringID.FILE_TYPE_ALL) + " (*.*)|*.*";
                    if (settings.lastSaveImageLocation != null)
                    {
                        saveFileDialog1.InitialDirectory = settings.lastSaveImageLocation;
                    }
                    if (saveFileDialog1.ShowDialog() == DialogResult.OK)
                    {
                        string filename = "";
                        filename = saveFileDialog1.FileName;
                        System.Drawing.Imaging.ImageFormat format;
                        switch (System.IO.Path.GetExtension(filename).ToLower())
                        {
                            case ".bmp": format = System.Drawing.Imaging.ImageFormat.Bmp; break;
                            case ".png": format = System.Drawing.Imaging.ImageFormat.Png; break;
                            case ".jpg": format = System.Drawing.Imaging.ImageFormat.Jpeg; break;
                            case ".gif": format = System.Drawing.Imaging.ImageFormat.Gif; break;
                            case ".tif": format = System.Drawing.Imaging.ImageFormat.Tiff; break;
                            default: format = System.Drawing.Imaging.ImageFormat.Bmp; break;
                        }
                        temp.Save(filename, format);
                        ShowStatus(translation.GetTranslatedString(Translation.StringID.IMAGE_SAVED), 5000); // "Image saved"
                        settings.lastSaveImageLocation = System.IO.Path.GetDirectoryName(filename);
                    }
                }
            }
        }

        private void ShowStatus(string text, int msec)
        {
            toolStripStatusLabel2.Text = text;
            timer1.Interval = msec;
            timer1.Enabled = true;
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            toolStripStatusLabel2.Text = "";
        }

        private void LoadTranslatedStrings(String translationName)
        {
            translation = new Translation(translationName);

            // File menu
            fileToolStripMenuItem.Text = translation.GetTranslatedString(Translation.StringID.MENU_FILE);
            openToolStripMenuItem.Text = translation.GetTranslatedString(Translation.StringID.MENU_OPEN);
            saveAsBitmapToolStripMenuItem.Text = translation.GetTranslatedString(Translation.StringID.MENU_SAVE_IMAGE);
            printToolStripMenuItem.Text = translation.GetTranslatedString(Translation.StringID.MENU_PRINT);
            printPreviewToolStripMenuItem.Text = translation.GetTranslatedString(Translation.StringID.MENU_PRINT_PREVIEW);
            exitToolStripMenuItem.Text = translation.GetTranslatedString(Translation.StringID.MENU_EXIT);

            // Edit menu
            editToolStripMenuItem.Text = translation.GetTranslatedString(Translation.StringID.MENU_EDIT);
            copyToolStripMenuItem.Text = translation.GetTranslatedString(Translation.StringID.MENU_COPY);
            preferencesToolStripMenuItem.Text = translation.GetTranslatedString(Translation.StringID.MENU_PREFS);

            // View menu
            viewToolStripMenuItem.Text = translation.GetTranslatedString(Translation.StringID.MENU_VIEW);
            rotateLeftToolStripMenuItem.Text = translation.GetTranslatedString(Translation.StringID.ROTATE_LEFT);
            rotateRightToolStripMenuItem.Text = translation.GetTranslatedString(Translation.StringID.ROTATE_RIGHT);
            refreshToolStripMenuItem.Text = translation.GetTranslatedString(Translation.StringID.MENU_RESET);
            zoomToolStripMenuItem.Text = translation.GetTranslatedString(Translation.StringID.MENU_SCALE_ZOOM);
            fitToWindowToolStripMenuItem.Text = translation.GetTranslatedString(Translation.StringID.MENU_FIT_TO_WINDOW);

            // Help menu
            helpToolStripMenuItem.Text = translation.GetTranslatedString(Translation.StringID.MENU_HELP);
            checkForUpdateToolStripMenuItem.Text = translation.GetTranslatedString(Translation.StringID.CHECK_UPDATE);
            saveDebugInfoToolStripMenuItem.Text = translation.GetTranslatedString(Translation.StringID.SAVE_DEBUG);
            showDebugInfoToolStripMenuItem.Text = translation.GetTranslatedString(Translation.StringID.SHOW_DEBUG);
            aboutToolStripMenuItem.Text = translation.GetTranslatedString(Translation.StringID.MENU_ABOUT);
        }

        private void SetDesignScaleSetting(float scale, bool autoSize, bool updateDesign)
        {
            if(autoSize)
            {
                fitToWindowToolStripMenuItem.Checked = true;
                settings.AutoScaleDesign = true;
            }
            else
            {
                fitToWindowToolStripMenuItem.Checked = false;
                settings.AutoScaleDesign = false;
                designScale = scale;
            }
            
            if (updateDesign)
            {
                UpdateDesignImage();
            }
        }

        private void scale100ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            SetDesignScaleSetting(1.0f, false, true);
        }

        private void scale90ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            SetDesignScaleSetting(0.9f, false, true);
        }

        private void scale80ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            SetDesignScaleSetting(0.8f, false, true);
        }

        private void scale70ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            SetDesignScaleSetting(0.7f, false, true);
        }

        private void scale60ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            SetDesignScaleSetting(0.6f, false, true);
        }

        private void scale50ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            SetDesignScaleSetting(0.5f, false, true);
        }

        private void scale40ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            SetDesignScaleSetting(0.4f, false, true);
        }

        private void scale30ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            SetDesignScaleSetting(0.3f, false, true);
        }

        private void scale20ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            SetDesignScaleSetting(0.2f, false, true);
        }

        private void scale10ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            SetDesignScaleSetting(0.1f, false, true);
        }

        private void scale5ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            SetDesignScaleSetting(0.05f, false, true);
        }

        private void fitToWindowToolStripMenuItem_Click(object sender, EventArgs e)
        {
            // Toggle checked state
            fitToWindowToolStripMenuItem.Checked = !fitToWindowToolStripMenuItem.Checked;
            // Update design
            SetDesignScaleSetting(1.0f, fitToWindowToolStripMenuItem.Checked, true);
        }

        private void frmMain_ResizeEnd(object sender, EventArgs e)
        {
            // Finished resize, update design scale if set to fit-to-window.
            // This event also captures window move events, so check if the size
            // of panel2 has changed to see if it's really a resize event.
            if (fitToWindowToolStripMenuItem.Checked && panel2LastUpdateSize != panel2.Size)
            {
                UpdateDesignImage();
            }
        }

        private void panel2_Resize(object sender, EventArgs e)
        {
            // This event is the one we really want, but it fires much too 
            // frequently during a resize event. So, let ReziseEnd handle most
            // of the cases and only process this after a window maximize or
            // restore.
            if(maximizeChanged)
            {
                maximizeChanged = false;
                
                if (fitToWindowToolStripMenuItem.Checked)
                {
                    UpdateDesignImage();
                }
            }
        }
    }
}
