//----------------------------------------------------------------------------
// MainForm.cs
//
// Main form for C1ReportDesigner application
//
// This is a part of the C1ReportDesigner package.
// Copyright (C) GrapeCity, Inc
// All rights reserved.
//
// This source code is intended as a supplement to the
// C1ReportDesigner control and related documentation 
// provided with the product.
// See these sources for detailed information regarding the
// C1ReportDesigner product.
//----------------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Collections;
using System.Reflection;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.Xml;
using System.Xml.Serialization;
using Microsoft.Win32;
using System.Collections.Specialized;
using System.Text.RegularExpressions;
using System.Drawing.Text;
using System.Globalization;
using System.Drawing.Printing;
using System.Diagnostics;

using C1.Win.C1ReportDesigner;
using C1.C1Preview;
using C1.C1Preview.Export;
using C1.C1Report;
using C1.Win.C1Ribbon;
using ReportDesignerApp.Util;
using C1.Win.C1Command;
using C1.Win.C1Preview;
using C1.Win.Localization;
using C1.Win.C1Themes;
using C1.Util.Licensing;

namespace ReportDesignerApp
{
    public partial class MainForm : C1.Win.C1Ribbon.C1RibbonForm, ISite
    {
        #region Private data members
        internal const string DefatulTheme = "builtin:VS2013Light";
        private const int cMaxRecentFilesCount = 9;
        private const int DRAG_THRESHOLD = 3;
        private const double cDropFieldWidth = 1440 * 2; // 2 inch
        private const double cDropFieldHeight = 1440 / 3; // 1/3 inch
        private const int cMaxHistoryMenuSize = 10;
        // min/max zoom factors: (1000% is too much for the slider, so we use a narrower interval 10-500):
        private const double cMinZoom = 0.1;
        private const double cMaxZoom = 5;
        // strings:
        internal const string _regKey = @"Software\ComponentOne\C1ReportDesigner.2";
        internal static readonly string _exportFilter =
            Strings.MainForm.ExportFilter;

        //
        [System.Runtime.InteropServices.DllImport("user32.dll", CharSet = System.Runtime.InteropServices.CharSet.Auto)]
        public static extern int SetWindowLong(IntPtr hwnd, int nIndex, int dwNewLong);

#pragma warning disable 0618 // disable "obsolete" warning for some C1Report-specific export providers
        // keys are open file dialog filter indices (_exportFilter), values create corresponding exporters:
        private static Dictionary<int, Func<C1.C1Preview.Export.Exporter>> s_exporters = new Dictionary<int,Func<C1.C1Preview.Export.Exporter>>()
        {
            { 1, () => { var ex = new C1ReportHtmlExporter(); ex.Paged = true; return ex; } },
            { 2, () => { var ex = new C1ReportHtmlExporter(); ex.DrillDown = true; return ex; } },
            { 3, () => ExportProviders.ReportHTMLExportProvider.NewExporter() },
            { 4, () => { var ex = new C1ReportHtmlExporter(); ex.TableBased = true; return ex; } },
            { 5, () => { var ex = new PdfExporter(); ex.EmbedTrueTypeFonts = false; return ex; } },
            { 6, () => { var ex = new PdfExporter(); ex.EmbedTrueTypeFonts = true; return ex; } },
            { 7, () => ExportProviders.ReportRTFExportProvider.NewExporter() },
            { 8, () => ExportProviders.ReportRTFLabelsExportProvider.NewExporter() },
            { 9, () => ExportProviders.ReportExcelExportProvider.NewExporter() },
            { 10, () => ExportProviders.ReportOpenXmlExportProvider.NewExporter() },
            { 11, () => new ReportTIFFExportProvider().NewExporter() },
            { 12, () => ExportProviders.ReportTextExportProvider.NewExporter() },
            { 13, () => ExportProviders.ReportTextSinglePageExportProvider.NewExporter() },
            { 14, () => ExportProviders.ReportMetafileExportProvider.NewExporter() },
            { 15, () => ExportProviders.XpsExportProvider.NewExporter() },
            { 16, () => ExportProviders.C1dxExportProvider.NewExporter() },
        };
#pragma warning restore 0618

        private static Image s_CustomFieldImage;
        private static readonly float[] cFontSizes = new float[] { 8, 9, 10, 11, 12, 14, 16, 18, 20, 22, 24, 26, 28, 36, 48, 72 };
        public static Font DefaultAppFont;

        private bool _borland = false;
        private bool _dirty = false;
        private bool _lastRenderCancelled = false; // true if user stopped generation of the preview; used to re-generate the report when previewing again
        private string _fileName = string.Empty;
        private string _createInfo;

        // for use when invoked by C1Report at design time
        private bool _noFile = false;        // indicates we're editing a component, not a stand-alone XML file.
        private Hashtable _dataSchema = null;       // data schema available to component

        // user preferences
        private string _theme = string.Empty;
        internal AppConfig _appConfig;
        internal bool _autoSave = false;
        internal bool _loadOnStartUp = true;
        internal bool _embedImages = true;
        internal int _defaultExportIndex = 2; // Drilldown (index into filter is 1-based)
        internal string _defaultStyleName = string.Empty;
        internal bool _useFieldWrappers = false;
        internal bool _syntaxCheck = true;
        internal bool _syntaxColoring = true;
        internal Font _scriptEditorFont = new Font("Courier New", 9);
        internal Color _scriptEditorBackColor = Color.White;
        internal Color _scriptEditorForeColor = Color.Black;
        internal bool _scriptEditorAutoSave = false;
        internal bool _scriptEditorCalculatedFieldsOnly = false;
        internal bool _scriptEditorDataSourceFilterWarning = true;
        internal int _scriptEditorSplitWindowDistance = 0;
        internal string _scriptEditorLastItemKey0 = string.Empty;
        internal string _scriptEditorLastItemKey1 = string.Empty;
        internal bool _showExportOptions = true;
        internal IsolationLevel _isolationLevel = DataSource.c_DefIsolationLevel;

        // drag reports
        private int _downIndex;
        private Point _downPoint;
        private bool _dragSource = false;

        // drag fields
        private Point _fieldsPointDown;
        private int _fieldsIndexDown;

        //
        private DataFormats.Format _cfReport = DataFormats.GetFormat("cfC1Report");

        //
        private bool _clearOnImport = false;
        private ArrayList _importList; // << global list used to update UI

        //
        private bool _reportDesignMode = true;
        private bool _isPreviewRendering = false;
        private State _state = new State();
        private Actions _actions = new Actions();

        //
        private ArrayList _recentFiles;

        //
        private C1DockingTabPage _lastDesignPage;
        private C1DockingTabPage _lastPreviewPage;

        //
        private RibbonTab _lastDesignTab;

        //
        private int _UIUpdateCounter;

        // provides zoom scale with 100% in the middle:
        private ZoomSliderScale _zoomSliderScale;

        // UI update timer:
        private Timer _timer;
        private bool _timerUpdateNeeded = false;

        // "generation" for UpdateDbFieldsDesignerUI (so that it does not update with stale fields):
        private int _fieldsUpdaterGeneration = 0;

        // flag to handle form close while rendering report:
        private bool _closeRequestedWhileRendering = false;
        private C1.Win.C1Ribbon.RibbonButton rbtnExportC1DX;

        // custom fields constants
        private static readonly List<string> CustomFieldsAssemblyAliases = new List<string> {
            "c1.win.c1report.customfields",
            "c1.win.c1report.customfields.2",
            "c1.c1report.customfields.2",
            "c1.c1report.customfields.4",
        };

        private static readonly string CustomFieldsAssembly =
#if CLR45
            "C1.C1Report.CustomFields.4.5";
#elif CLR40
            "C1.C1Report.CustomFields.4";
#else
            "C1.C1Report.CustomFields.2";
#endif
        private static readonly string[] CustomFieldsClasses = new string[]
            {
                "C1.C1Report.CustomFields.Chart",
                "C1.C1Report.CustomFields.Gradient",
#if CLR45 || CLR40
                "C1.C1Report.CustomFields.SuperLabel",
                "C1.C1Report.CustomFields.QRCode",
                "C1.C1Report.CustomFields.Map",
#endif
            };

        #endregion

        #region ctors
        static MainForm()
        {
            s_CustomFieldImage = AppUtils.LoadResourceImage("CustomField.png");

            C1Report.Services.AddService(typeof(C1.C1Preview.IDesignerSettingPersistService), new SettingPersister());
        }

        public MainForm()
        {

            //
            InitializeComponent();
            

            // Set GWL_EXSTYLE WS_EX_COMPOSITED on the thumbnails panel, which reduces flicker
            // (but setting it on the whole form slows things down extremely, so just do it locally)
            // (see comment in C1PrintPreviewControl.Init() for explanation of OS version test):
            if (Environment.OSVersion.Platform == PlatformID.Win32NT && Environment.OSVersion.Version.Major >= 6)
                SetWindowLong(dtpPages.Handle, -20, 0x02000000);

            this.ramMain.Text = Strings.MainForm.RibbonApplicationButton;

            rbtnCheckForUpdates.Visible = false;

            // C1DX:
            this.rbtnExportC1DX = new C1.Win.C1Ribbon.RibbonButton();
            this.rbtnExportC1DX.Name = "rbtnExportC1DX";
            this.rbtnExportC1DX.Tag = "C1DX,c1dx,16";
            this.rbtnExportC1DX.Text = Strings.MainForm.ExportToC1dxText;
            this.rbtnExportC1DX.ToolTip = Strings.MainForm.ExportToC1dxToolTip;
            this.rmExportMore.Items.Add(this.rbtnExportC1DX);

            // set up reasonable initial size/position (will be overwritten if saved state exists):
            Screen scrn = System.Windows.Forms.Screen.FromPoint(Point.Empty);
            this.Location = Point.Empty;
            this.Location = new Point((int)(scrn.Bounds.Width * 0.1), (int)(scrn.Bounds.Height * 0.1));
            this.Size = new Size((int)(scrn.Bounds.Width * 0.8), (int)(scrn.Bounds.Height * 0.8));
            this.MinimumSize = new Size(400, 300);

            // zoom slider:
            Debug.Assert(cMinZoom >= Math.Round(Math.Max(_designer.MinZoomFactor, _preview.MinZoomFactor)));
            Debug.Assert(cMaxZoom <= Math.Round(Math.Min(_designer.MaxZoomFactor, _preview.MaxZoomFactor)));
            _zoomSliderScale = new ZoomSliderScale(cMinZoom, cMaxZoom, rtbZoom.Minimum, rtbZoom.Maximum);

            //
            DefaultAppFont = SystemInformation.MenuFont;
            AutoScaleMode = AutoScaleMode.None;
            Font = DefaultAppFont;

            // activate dtpPages tab by default
            _lastPreviewPage = dtpPages;
            _lastDesignPage = dtpReports;
            _lastDesignPage.Show();

            //
            _lastDesignTab = rtDesign;

            // fill rcbFontSize
            for (int i = 0; i < cFontSizes.Length; i++)
                rcbFontSize.Items.Add(new RibbonButton(cFontSizes[i].ToString()));

            //
            BorderWidthSetup();

            //
            UpdateFormCaption();

            // If this options is true then reports containing
            // dashes borders looks better
            _preview.CompatibilityOptions.DefaultSmoothingMode = true;

            // subscribe to EditorScriptItem.Written event:
            EditorScriptItem.Written += (ss, ee) => this.SetDirty();

            // set up timer for UI updates and other tasks:
            _timer = new Timer();
            _timer.Interval = 500;
            _timer.Tick += new EventHandler(_timer_Tick);
            _timer.Start();
        }
        #endregion

        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);
        }

        protected override void OnShown(EventArgs e)
        {
            HideSpash();
            base.OnShown(e);
        }

        #region Public properties
        public C1ReportDesigner Designer
        {
            get { return _designer; }
        }

        public bool CategorizeProperties
        {
            get { return _propGrid.PropertySort == PropertySort.CategorizedAlphabetical; }
            set { _propGrid.PropertySort = (value) ? PropertySort.CategorizedAlphabetical : PropertySort.Alphabetical; }
        }

        public bool UseFieldWrappers
        {
            get { return _useFieldWrappers; }
            set { _useFieldWrappers = value; }
        }

        public bool SortReportList
        {
            get { return _reportList.Sorting != SortOrder.None; }
            set { _reportList.Sorting = value ? SortOrder.Ascending : SortOrder.None; }
        }

        /// <summary>
        /// Gets or sets the current theme name, prefixed by:
        /// - "builtin:" - the theme is one of the built-in themes;
        /// - "custom:" - the theme is loaded from a file in the "Themes" sub-folder.
        /// </summary>
        public string Theme
        {
            get { return _theme; }
            set
            {
                if (_theme != value)
                {
                    _theme = value;
                    var tl = new C1ThemeLocator(_theme);
                    var theme = tl.GetTheme();
                    if (theme != null)
                    {
                        C1ThemeController.ApplyThemeToControlTree(this, theme);
                        C1ThemeController.ApplyThemeToObject(cmDesigner, theme);
                        C1ThemeController.ApplyThemeToObject(cmReport, theme);
                    }
                }
            }
        }
        #endregion

        #region Private
        private void BeginUIUpdate()
        {
            _UIUpdateCounter++;
        }

        private void EndUIUpdate()
        {
            _UIUpdateCounter--;
        }

        private void _timer_Tick(object sender, EventArgs e)
        {
            // Update UI:
            if (_timerUpdateNeeded)
            {
                _timerUpdateNeeded = false;
                //
                UpdateUIPreviewStatusBar(true);
                UpdateUINavigation(false);
                UpdateUIPreviewTools(false);
                UpdateUIZoom(false);
                UpdateUIPreviewStopRefresh(false);
            }
            // Handle delayed form close:
            if (_closeRequestedWhileRendering && !_state.PreviewRendering)
            {
                _closeRequestedWhileRendering = false;
                this.BeginInvoke(new MethodInvoker(delegate() { this.Close(); }));
            }
        }

        private void SetDesignMode(bool designMode)
        {
            // cancel current report, if any
            if (designMode && _reportRender.IsBusy)
            {
                _reportRender.Cancel = true;
                _reportDesignMode = true;
                return;
            }

            //
            _reportDesignMode = designMode;
            UpdateUI();

            // update form
            if (_designer.Visible)
            {
                if (dtpReports.Visible)
                    _lastDesignPage = dtpReports;
                else if (dtpProperties.Visible)
                    _lastDesignPage = dtpProperties;
                else if (dtpFields.Visible)
                    _lastDesignPage = dtpFields;

                _lastDesignTab = rbnMain.SelectedTab;
            }
            else
            {
                if (dtpPages.Visible)
                    _lastPreviewPage = dtpPages;
                else if (dtpOutline.Visible)
                    _lastPreviewPage = dtpOutline;
                else if (dtpPreviewFind.Visible)
                    _lastPreviewPage = dtpPreviewFind;
            }

            this.SuspendLayout();

            // In preview mode, the zoom factor dropdown is in the "zoom" group;
            // in design mode, we move it to "tools" group (seems to be the best place for it):
            RibbonMenu zoomMenu = this.rbtnZoom;
            if (designMode)
            {
                this.rgZoom.Items.Remove(this.rbtnZoom);
                this.rgTools.Items.Add(this.rbtnZoom);
            }
            else
            {
                this.rgTools.Items.Remove(this.rbtnZoom);
                this.rgZoom.Items.Add(this.rbtnZoom);
            }

            _designer.Visible = designMode;
            dtpReports.TabVisible = designMode;
            dtpProperties.TabVisible = designMode;
            dtpFields.TabVisible = designMode;

            _preview.Visible = !designMode;
            dtpOutline.TabVisible = !designMode;
            dtpPages.TabVisible = !designMode;
            dtpPreviewFind.TabVisible = !designMode;

            rtDesign.Visible = designMode;
            rtInsert.Visible = designMode;
            rtArrange.Visible = designMode;
            rtPageSetup.Visible = designMode;
            rtPreview.Visible = !designMode;

            this.ResumeLayout();

            if (designMode)
            {
                C1DockingTabPage dtp = _lastDesignPage == null ? dtpReports : _lastDesignPage;
                dtp.Show();

                _preview.Document = null;
                if (_lastDesignTab != null)
                    rbnMain.SelectedTab = _lastDesignTab;

                // update selection (this is causing update an UI)
                _designer_SelectionChanged(this, EventArgs.Empty);
            }
            else
            {
                C1DockingTabPage dtp = _lastPreviewPage == null ? dtpPages : _lastPreviewPage;
                dtp.Show();

                _preview.Document = null;
                if (_designer.Report != null)
                    RenderPreview(false);
            }

            ShowStatus();
            Update();
        }

        private void UpdateFormCaption()
        {
            var caption = string.Format(
                Strings.MainForm.AppCaptionFmt,
                Strings.MainForm.AppName,
                (_noFile ? Strings.MainForm.Component : (string.IsNullOrEmpty(_fileName) ? string.Empty : _fileName)),
                (_dirty ? " *" : string.Empty));
            Text = caption;
        }

        // save (or delete) temp file
        private void SaveTempFile(bool save)
        {
            if (save) // save file, designer will pick it up
            {
                SaveFile(false);
            }
            else // delete file, designer will cancel changes
            {
                if (File.Exists(_fileName))
                    File.Delete(_fileName);
            }
        }

        private void LoadCustomFields()
        {
            foreach (string fieldInfo in AppSettings.LoadList("customfields", MessageForm.Warn))
            {
                // get assembly, class name
                string[] arr = fieldInfo.Split(';');
                if (arr.Length < 2) continue;
                string asmName = arr[0];
                string clsName = arr[1];

                if (IsBuiltInCustomField(asmName, clsName)) continue;
                LoadCustomField(asmName, clsName);
            }

            LoadBuiltInCustomFields();

            // show "custom fields" group only if there are any custom fields:
            rgCustomFields.Visible = rgCustomFields.Items.Count > 0;
        }

        private bool IsBuiltInCustomField(string asmName, string clsName)
        {
            if (!CustomFieldsAssemblyAliases.Contains(asmName.ToLowerInvariant())) return false;

            foreach (string fieldName in CustomFieldsClasses)
            {
                if (string.Equals(fieldName, clsName, StringComparison.InvariantCultureIgnoreCase))
                    return true;
            }

            return false;
        }

        private void LoadCustomField(string asmName, string clsName)
        {
                // this could fail...
                try
                {
                    // load assembly, create custom field instance
#pragma warning disable 618
                    Assembly asm = Assembly.LoadWithPartialName(asmName);
#pragma warning restore 618
                    if (asm == null)
                    {
                        string msg = string.Format(Strings.MainForm.ErrCannotFindCustomFldAsmFmt, asmName);
                        throw new ApplicationException(msg);
                    }
                    object customField = asm.CreateInstance(clsName, true);
                    if (customField == null)
                    {
                        string msg = string.Format(Strings.MainForm.ErrCannotInstCustomFldFmt, clsName);
                        throw new ApplicationException(msg);
                    }

                    // check that the class derives from C1Report.Field
                    if (!customField.GetType().IsSubclassOf(typeof(Field)))
                    {
                        string msg = string.Format(Strings.MainForm.ErrCustomFldIsNotFieldFmt, clsName);
                        throw new ApplicationException(msg);
                    }

                    // get custom field description (for tooltip)
                    Type type = customField.GetType();
                    string desc;
                    object[] attDesc = type.GetCustomAttributes(typeof(DescriptionAttribute), false);
                    if (attDesc.Length > 0)
                        desc = ((DescriptionAttribute)attDesc[0]).Description;
                    else
                        desc = string.Format(Strings.MainForm.CustomFldDescriptionFmt, type.Name);

                    // get custom field image (for toolbar)
                    Image img = AppUtils.LoadResourceImage(asm, type.Name + ".bmp");
                    if (img == null)
                    {
                        img = AppUtils.LoadResourceImage(asm, type.Name + ".png");
                        if (img == null)
                            img = s_CustomFieldImage;
                    }
                    else
                    {
                        if (img is Bitmap)
                            ((Bitmap)img).MakeTransparent(Color.Red);
                    }

                    // add custom field to toolbar
                    RibbonToggleButton btn = new RibbonToggleButton();
                    btn.Tag = customField; // tag is clonable field
                    // tooltip header (the bold part at the top):
                    string ttHeader = string.Format(Strings.MainForm.CustomFldToolTipHeaderFmt, desc);
                    // tooltip body:
                    btn.ToolTip = string.Format(Strings.MainForm.CustomFldToolTipTemplateFmt,
                        ttHeader, string.Format(Strings.MainForm.CustomFldToolTipFmt, clsName, asmName));
                    //
                    btn.SmallImage = img;
                    btn.LargeImage = img;
                    btn.Text = desc;
                    if (rgCustomFields.Items.Count < 9)
                        btn.KeyTip = (rgCustomFields.Items.Count + 1).ToString();
                    rgCustomFields.Items.Add(btn);
                }
                catch (Exception x)
                {
                System.Diagnostics.Debug.WriteLine(string.Format("failed to load custom field '{0};{1}':\r\n{2}", asmName, clsName, x.Message));
            }
                }

        private void LoadBuiltInCustomFields()
        {
            foreach (string clsName in CustomFieldsClasses)
            {
                LoadCustomField(CustomFieldsAssembly, clsName);
            }
        }

        private void ClearRenderError()
        {
            rbtnRenderError.Visible = false;
            rsepRenderError.Visible = false;
            rbtnRenderError.ToolTip = string.Empty;
        }

        private void SetRenderError(string errorMessage)
        {
            rbtnRenderError.Visible = true;
            rsepRenderError.Visible = true;
            rbtnRenderError.ToolTip = errorMessage;
        }

        private bool RenderPreview(bool force)
        {
            // autosave
            if (_dirty && _autoSave)
                SaveFile(false);

            bool wasPreviewRendering = _isPreviewRendering;
            _isPreviewRendering = true;
            if (!wasPreviewRendering)
                UpdateUI();

            if (_lastRenderCancelled)
            {
                // if last generation was cancelled by user, we probably want to regenerate the report:
                force = true;
                _lastRenderCancelled = false;
            }

            try
            {
                // clear error info if any
                //ClearRenderError();

                // render the report
                Cursor = Cursors.WaitCursor;
                try
                {
                    // cancel if the report is busy
                    if (_reportRender.IsBusy)
                    {
                        _reportRender.Cancel = true;
                        return true;
                    }

                    if (!force)
                    {
                        // make report dirty if it has parameters
                        string rs = _reportRender.DataSource.RecordSource;
                        if (rs != null && rs.ToUpper().StartsWith("PARAMETERS"))
                            force = true;
                    }

                    // create a copy so the report fields won't be changed
                    // while rendering
                    string reportDefinition = _designer.Report.ReportDefinition;
                    _reportRender.DoEvents = _designer.Report.DoEvents;
                    if (force || _reportRender.ReportDefinition != reportDefinition)
                        // make report dirty to force re-render
                        // changes ReportDefinition automatically sets IsDirty to true
                        _reportRender.ReportDefinition = reportDefinition;

                    string conn = _reportRender.DataSource.ConnectionString;
                    if (conn != null && conn.Length > 0 && _dataSchema != null && _dataSchema.ContainsKey(conn))
                        _reportRender.DataSource.ConnectionString = string.Empty;

                    // render the report
                    _reportRender.SetCreationDevice(_designer.Report.CreationDevice, _designer.Report.CreationPrinterName);
                    _reportRender.DoEvents = true;
                    _preview.Document = _reportRender;
                    _lastRenderCancelled = _reportRender.Cancel;
                    ShowStatus(Strings.MainForm.Ready);
                    _preview.Focus();
                    if (_reportDesignMode)
                        SetDesignMode(true);
                    else
                        // report can be changed during rendering so we
                        // restore reportdefinition
                        _reportRender.SetReportDefinition(reportDefinition, false, false);
                    return true;
                }

                // Data access problem? allow user to fix the connection
                catch (DataAccessException x)
                {
                    // build error message
                    string errDetail;
                    if (x.InnerException != null && !string.IsNullOrEmpty(x.InnerException.Message))
                        errDetail = string.Format(Strings.MainForm.OpenDataSourceErrDetailFmt, x.InnerException.Message);
                    else
                        errDetail = string.Empty;
                    string msg = string.Format(Strings.MainForm.CannotOpenDataSourceFmt, errDetail);

                    // check if user wants to fix the connection
                    if (MessageForm.Ask(msg) != DialogResult.Yes)
                        return false;

                    // allow them to edit the connection string
                    using (DataSourceForm dlg = new DataSourceForm())
                    {
                        if (!dlg.EditDataSource(_designer.Report, _dataSchema))
                            return false;
                    }

                    // the user fixed a connection, so apply the fix to
                    // all other report that use the same bad connection
                    string badConn = _reportRender.DataSource.ConnectionString;
                    string goodConn = _designer.Report.DataSource.ConnectionString;
                    foreach (ReportItem ri in _reportList.Items)
                    {
                        DataSource ds = ri._report.DataSource;
                        if (ds.ConnectionString == badConn)
                            ds.ConnectionString = goodConn;
                    }

                    // report is dirty now
                    _dirty = true;

                    // fix is done, try to render again
                    return RenderPreview(false);
                }
                catch (Exception x) // show message for all other problems
                {
                    MessageForm.Warn(string.Format(Strings.MainForm.ErrRenderingReportFmt, x.Message));
                    return false;
                }
                finally
                {
                    Cursor = Cursors.Default;
                    // the wait cursor gets stuck in thumbnail view, *fix* it the hard way:
                    ptvMain.Cursor = Cursors.Default;
                }
            }
            finally
            {
                if (!wasPreviewRendering)
                {
                    _isPreviewRendering = false;
                    UpdateUI();
                }
            }
        }

        // configure based on command-line arguments passed by 
        // C1Report's ControlDesigner class
        private bool StartFromDesigner()
        {
            // check command-line arguments
            string[] args = Environment.GetCommandLineArgs();
            if (args.Length < 2 || !args[1].StartsWith("-design:"))
                return false;

            // configure application
            _noFile = true;
            _dirty = false;
            rbtnExit.Visible = false;
            rbtnCancelAndExit.Visible = true;
            rbtnSaveAndExit.Visible = true;

            // load report from temp file
            string fName = args[1].Substring(8);
            OpenFileInternal(fName, true);

            // load data schema from file
            _dataSchema = null;
            if (args.Length > 2 && args[2].StartsWith("-schema:"))
            {
                fName = args[2].Substring(8);
                if (File.Exists(fName))
                {
                    try
                    {
                        // load schema into hash table (for use with DataPicker)
                        FileStream fs = new FileStream(fName, FileMode.Open);
                        BinaryFormatter bf = new BinaryFormatter();
                        _dataSchema = (Hashtable)bf.Deserialize(fs);
                        fs.Close();
                    }
                    catch { }
                }
            }

            // show current state
            Activate();
            UpdateUI();

            // if there's no report (control was empty), invoke wizard and create a new report
            if (_reportList.Items.Count == 0)
                AddReport();

            // still no report? user probably canceled the wizard, so bail out.
            if (_reportList.Items.Count == 0)
            {
                Visible = false;
                SaveTempFile(false);
                Application.Exit();
            }

            // if the report contains connstring and recordsource, wire them up
            C1Report report = _designer.Report;
            DataSource ds = report.DataSource;
            string conn = ds.ConnectionString;
            if (conn != null && conn.Length > 0 && _dataSchema != null && _dataSchema.Contains(conn))
            {
                DataSet dset = (DataSet)_dataSchema[conn];
                string rs = ds.RecordSource;
                if (rs != null && rs.Length > 0 && dset.Tables.Contains(rs))
                    ds.Recordset = dset.Tables[rs];
            }

            // if the report contains no fields, invoke wizard
            if (report.Fields.Count == 0)
            {
                _reportList.Items.Clear();
                _designer.Report = null;
                AddReport();
            }

            // ready to work
            return true;
        }

        /// <summary>
        /// Edits a script.
        /// </summary>
        /// <param name="report">The host report.</param>
        /// <param name="script">The script to edit (may be null or empty for new scripts).</param>
        /// <param name="isExpression">true if the script is an expression (returns value), false otherwise.</param>
        /// <param name="result">OUT: the resulting (edited) script.</param>
        /// <returns>true if the user saved changes, false if cancelled.</returns>
        private bool EditScript(C1Report report, string script, bool isExpression, out string result)
        {
            rbtnScriptEditor.Pressed = true;
            try
            {
                result = script;
                using (Forms.ScriptEditorFormEx dlg = new Forms.ScriptEditorFormEx(this, report, script, isExpression))
                {
                    if (dlg.ShowDialog() == DialogResult.OK)
                    {
                        result = dlg.GetScript();
                        return true;
                    }
                }
                return false;
            }
            finally
            {
                rbtnScriptEditor.Pressed = false;
            }
        }

        private string _editExpression(C1Report report, string expression)
        {
            string result;
            EditScript(report, expression, true, out result);
            return result;
        }

        private string _editStatement(C1Report report, string statement)
        {
            string result;
            EditScript(report, statement, false, out result);
            return result;
        }

        // delegate for editing data sources
        private DialogResult _editDataSource(C1Report report)
        {
            using (DataSourceForm dlg = new DataSourceForm())
            {
                if (dlg.EditDataSource(report, _dataSchema))
                {
                    _dirty = true;
                    UpdateUI();
                    return DialogResult.OK;
                }
            }
            return DialogResult.Cancel;
        }

        private bool IsItemsEqual(RibbonItemCollection items1, List<string> items2)
        {
            if (items1.Count != items2.Count)
                return false;

            for (int i = 0; i < items2.Count; i++)
            {
                if (items1[i] is RibbonSeparator)
                {
                    if (items2[i] != "-")
                        return false;
                }
                else if (items1[i] is RibbonButton)
                {
                    if (items2[i] != ((RibbonButton)items1[i]).Text)
                        return false;
                }
                else
                    return false;
            }

            return true;
        }

        private static readonly FieldAlignEnum[][] s_TextAlignMatrix =
            {
                new FieldAlignEnum[] {FieldAlignEnum.LeftTop, FieldAlignEnum.CenterTop, FieldAlignEnum.RightTop, FieldAlignEnum.JustTop},
                new FieldAlignEnum[] {FieldAlignEnum.LeftMiddle, FieldAlignEnum.CenterMiddle, FieldAlignEnum.RightMiddle, FieldAlignEnum.JustMiddle},
                new FieldAlignEnum[] {FieldAlignEnum.LeftBottom, FieldAlignEnum.CenterBottom, FieldAlignEnum.RightBottom, FieldAlignEnum.JustBottom},
            };

        private void GetAlign(FieldAlignEnum align, out TextHorzAlign ha, out TextVertAlign va)
        {
            for (int x = 0; x < 4; x++)
                for (int y = 0; y < 3; y++)
                    if (s_TextAlignMatrix[y][x] == align)
                    {
                        ha = (TextHorzAlign)x;
                        va = (TextVertAlign)y;
                        return;
                    }
            ha = TextHorzAlign.Left;
            va = TextVertAlign.Top;
        }

        /// <summary>
        /// Updates a dropdown list with items from the passed list.
        /// </summary>
        /// <param name="menu">The menu to update.</param>
        /// <param name="items">The new items list.</param>
        /// <param name="enabled">Enable or disable the menu (if items is null or empty, this parameter is ignored unless the menu is a RibbonSplitButton).</param>
        private void UpdateDropDownField(RibbonDropDownBase menu, List<string> items, bool enabled)
        {
            if (items == null || items.Count == 0)
            {
                menu.Enabled = menu is RibbonSplitButton ? enabled : false;
                menu.Items.Clear();
            }
            else
            {
                menu.Enabled = enabled;
                // to imporve perfomance we compare current list of items with items parameter
                if (!IsItemsEqual(menu.Items, items))
                {
                    menu.Items.Clear();
                    foreach (string s in items)
                        if (s == "-")
                            menu.Items.Add(new RibbonSeparator());
                        else
                            menu.Items.Add(new RibbonButton(s));
                }
            }
        }

        private bool TryGetAction(string s, out Action a)
        {
            try
            {
                a = _actions[(ActionTypeEnum)Enum.Parse(typeof(ActionTypeEnum), s, false)];
                return true;
            }
            catch
            {
                a = null;
                return false;
            }
        }

        private void UpdateRibbonItems(IEnumerable items)
        {
            foreach (object o in items)
            {
                RibbonItem item = o as RibbonItem;
                if (item == null)
                    continue;

                string s = item.Tag as string;
                if (s == null)
                    continue;

                Action a;
                if (!TryGetAction(s, out a))
                    continue;

                item.Enabled = a.Enabled;
                RibbonToggleButton rtb = item as RibbonToggleButton;
                if (rtb != null)
                    rtb.Pressed = a.Pressed;

                RibbonComboBox rcb = item as RibbonComboBox;
                if (rcb != null)
                    rcb.Text = a.Text;

                RibbonEditBox reb = item as RibbonEditBox;
                if (reb != null)
                    reb.Text = a.Text;

                RibbonTrackBar rtbar = item as RibbonTrackBar;
                if (rtbar != null && rtbar.Value != a.Value)
                    rtbar.Value = Math.Min(Math.Max(a.Value, rtbar.Minimum), rtbar.Maximum);

                RibbonNumericBox rnbox = item as RibbonNumericBox;
                if (rnbox != null)
                    rnbox.Value = Math.Min(Math.Max(a.Value, rnbox.Minimum), rnbox.Maximum);

                RibbonLabel rbl = item as RibbonLabel;
                if (rbl != null)
                    rbl.Text = a.Text;

                RibbonColorPicker rcp = item as RibbonColorPicker;
                if (rcp != null)
                    rcp.Color = a.Color;
            }
        }

        private void UpdateCommands(bool update)
        {
            if (update)
                UpdateState();
            foreach (C1Command c in chMain.Commands)
            {
                string s = c.UserData as string;
                if (s == null)
                    continue;

                Action a;
                if (!TryGetAction(s, out a))
                    continue;

                c.Enabled = a.Enabled;
                c.Pressed = a.Pressed;
            }
        }

        /// <summary>
        /// Updates all designer db fields' lists.
        /// The actual updating is done in a separate thread so as to improve ui.
        /// </summary>
        /// <param name="report">The report (must not be null).</param>
        private void UpdateDbFieldsDesignerUI(C1Report report)
        {
            Debug.Assert(report != null);

            var gen = System.Threading.Interlocked.Increment(ref _fieldsUpdaterGeneration);

            lbFields.Enabled = false;
            var working = new List<string>() { Strings.MainForm.Working };
            UpdateDropDownField(rbtnFieldDataField, working, false);
            UpdateDropDownField(rbtnFieldBarCode, working, false);
            UpdateDropDownField(rbtnFieldCheckBox, working, false);
            UpdateDropDownField(rbtnFieldRtf, working, false);
            UpdateDropDownField(rbtnFieldPicture, working, false);

            List<string> txtFields = new List<string>(); // list of "text" fields
            List<string> picFields = new List<string>(); // list of "picture" fields

            var fieldsUpdater = new BackgroundWorker();
            fieldsUpdater.DoWork += (ss, ee) =>
            {
                try
                {
                    string[] arrTxts = report.DataSource.GetDBFieldList(true);
                    if (arrTxts != null)
                        foreach (string field in arrTxts)
                            txtFields.Add(field);
                    string[] arrPics = report.DataSource.GetDBFieldList(false);
                    if (arrPics != null)
                        foreach (string field in arrPics)
                            picFields.Add(field);
                    ee.Result = (int)ee.Argument;
                }
                catch
                {
                    ee.Result = null;
                }
            };
            fieldsUpdater.RunWorkerCompleted += (ss, ee) =>
            {
                // if error occurred or we became obsolete while getting the fields, don't do anything:
                if (ee.Result == null || (int)ee.Result != _fieldsUpdaterGeneration)
                    return;

                try
                {
                    // fill the fields panel:
                    lbFields.BeginUpdate();
                    lbFields.Items.Clear();
                    // add "text" fields:
                    txtFields.ForEach((s) => lbFields.Items.Add(new FieldListItem(s, false)));
                    // add "picture" fields to the list too (TODO/TBD: clarify with AlexM):
                    picFields.ForEach((s) => lbFields.Items.Add(new FieldListItem(s, true)));
                    lbFields.EndUpdate();
                    lbFields.Enabled = true;
                    // fill field-related dropdowns:
                    UpdateDropDownField(rbtnFieldDataField, txtFields, true);
                    UpdateDropDownField(rbtnFieldBarCode, txtFields, true);
                    UpdateDropDownField(rbtnFieldCheckBox, txtFields, true);
                    UpdateDropDownField(rbtnFieldRtf, txtFields, true);
                    UpdateDropDownField(rbtnFieldPicture, picFields, true);
                    // release background worker:
                    ((BackgroundWorker)ss).Dispose();
                }
                catch { }
            };
            fieldsUpdater.RunWorkerAsync(gen);
        }

        private void UpdateUIMode()
        {
            rbnMain.BeginUpdate();
            UpdateRibbonItems(rgMode.Items);
            rbnMain.EndUpdate();
        }

        private void UpdateUIFields(bool update)
        {
            if (update)
                UpdateState();
            rbnMain.BeginUpdate();
            try
            {
                if (_state.DesignMode && _designer.Report != null)
                {
                    rgFields.Enabled = rgCustomFields.Enabled = true;
                    // "field insert" buttons stay pressed for the duration of the field insert operation:
                    if (_designer.CreateFieldInfo == null)
                    {
                        System.Collections.ArrayList fieldButtons = new ArrayList();
                        fieldButtons.AddRange(rgFields.Items);
                        fieldButtons.AddRange(rgCustomFields.Items);
                        foreach (object ri in fieldButtons)
                        {
                            if (ri is RibbonSplitButton)
                                ((RibbonSplitButton)ri).Pressed = false;
                            else if (ri is RibbonToggleButton)
                                ((RibbonToggleButton)ri).Pressed = (RibbonToggleButton)ri == rbtnFieldArrow;
                        }
                    }
                    //
                    UpdateDbFieldsDesignerUI(_designer.Report);
                    UpdateDropDownField(rbtnFieldCalculated, CommonFields.GetFieldNames(), true);
                    //
                    List<string> subReports = new List<string>();
                    for (int i = 0; i < _reportList.Items.Count; i++)
                        if (i != _reportList.SelectedIndex)
                            subReports.Add(_reportList.Items[i].ToString());
                    UpdateDropDownField(rbtnFieldSubReport, subReports, true);
                }
                else
                    rgFields.Enabled = rgCustomFields.Enabled = false;
            }
            finally
            {
                rbnMain.EndUpdate();
            }
        }

        private void UpdateUITools(bool update)
        {
            if (update)
                UpdateState();
            rbnMain.BeginUpdate();
            try
            {
                UpdateRibbonItems(rgTools.Items);
                UpdateRibbonItems(rgPreviewTools.Items);
            }
            finally
            {
                rbnMain.EndUpdate();
            }
        }

        private void UpdateUIEdit(bool update)
        {
            if (update)
                UpdateState();
            rbnMain.BeginUpdate();
            try
            {
                UpdateRibbonItems(rgEdit.Items);
            }
            finally
            {
                rbnMain.EndUpdate();
            }
        }

        private void UpdateUIFont(bool update)
        {
            if (update)
                UpdateState();
            rbnMain.BeginUpdate();
            try
            {
                UpdateRibbonItems(ribbonToolBar1.Items);
                UpdateRibbonItems(ribbonToolBar2.Items);
            }
            finally
            {
                rbnMain.EndUpdate();

            }
        }

        private void UpdateUIBorders(bool update)
        {
            if (update)
                UpdateState();
            rbnMain.BeginUpdate();
            try
            {
                UpdateRibbonItems(rgBorder.Items);
                UpdateRibbonItems(rgalBorderStyle.Items);
                UpdateRibbonItems(ribbonToolBar5.Items);
                UpdateRibbonItems(ribbonToolBar6.Items);
                rgalBorderStyle.SelectedIndex = -1;
                foreach (RibbonGalleryItem item in rgalBorderStyle.Items)
                {
                    string s = item.Tag as string;
                    if (s == null)
                        continue;

                    Action a;
                    if (!TryGetAction(s, out a))
                        continue;

                    if (a.Value == _actions[ActionTypeEnum.BorderStyle].Value)
                    {
                        item.Selected = true;
                        break;
                    }
                }
            }
            finally
            {
                rbnMain.EndUpdate();
            }
        }

        //
        private void UpdateUIData(bool update)
        {
            if (update)
                UpdateState();
            rbnMain.BeginUpdate();
            try
            {
                UpdateRibbonItems(rgReport.Items);
            }
            finally
            {
                rbnMain.EndUpdate();
            }
        }

        // update all actions in application menu
        private void UpdateUIApplicationMenu(bool update)
        {
            if (update)
                UpdateState();
            rbnMain.BeginUpdate();
            try
            {
                UpdateRibbonItems(ramMain.LeftPaneItems);
            }
            finally
            {
                rbnMain.EndUpdate();
            }
        }

        private void UpdateUIFormat(bool update)
        {
            if (update)
                UpdateState();
            rbnMain.BeginUpdate();
            try
            {
                UpdateRibbonItems(rgAutoFormat.Items);
            }
            finally
            {
                rbnMain.EndUpdate();
            }
        }

        private void UpdateUIGrid(bool update)
        {
            if (update)
                UpdateState();
            rbnMain.BeginUpdate();
            try
            {
                UpdateRibbonItems(rgGrid.Items);
            }
            finally
            {
                rbnMain.EndUpdate();
            }
        }

        private void UpdateUIControlAlignment(bool update)
        {
            if (update)
                UpdateState();
            rbnMain.BeginUpdate();
            try
            {
                UpdateRibbonItems(rgControlAlignment.Items);
            }
            finally
            {
                rbnMain.EndUpdate();
            }
        }

        private void UpdateUISize(bool update)
        {
            if (update)
                UpdateState();
            rbnMain.BeginUpdate();
            try
            {
                UpdateRibbonItems(rgSize.Items);
            }
            finally
            {
                rbnMain.EndUpdate();
            }
        }

        private void UpdateUIPageSetup(bool update)
        {
            if (update)
                UpdateState();
            rbnMain.BeginUpdate();
            try
            {
                UpdateRibbonItems(rgPageLayout1.Items);
                UpdateRibbonItems(rgPageLayout2.Items);
            }
            finally
            {
                rbnMain.EndUpdate();
            }
        }

        private void UpdateUIPosition(bool update)
        {
            if (update)
                UpdateState();
            rbnMain.BeginUpdate();
            try
            {
                UpdateRibbonItems(rgPosition.Items);
            }
            finally
            {
                rbnMain.EndUpdate();
            }
        }

        private void UpdateUIZoom(bool update)
        {
            if (update)
                UpdateState();
            rbnMain.BeginUpdate();
            try
            {
                UpdateRibbonItems(rgZoom.Items);
                UpdateRibbonItems(rbtnZoom.Items);
                UpdateRibbonItems(rbtnZoomMorePages.Items);
                UpdateRibbonItems(sbMain.RightPaneItems);
            }
            finally
            {
                rbnMain.EndUpdate();
            }
        }

        private void UpdateUINavigation(bool update)
        {
            if (update)
                UpdateState();
            rbnMain.BeginUpdate();
            try
            {
                UpdateRibbonItems(ribbonToolBar4.Items);
                UpdateRibbonItems(ribbonToolBar3.Items);
            }
            finally
            {
                rbnMain.EndUpdate();
            }
        }

        private void UpdateUIPreviewTools(bool update)
        {
            if (update)
                UpdateState();
            rbnMain.BeginUpdate();
            try
            {
                UpdateRibbonItems(rgPreviewTools.Items);
            }
            finally
            {
                rbnMain.EndUpdate();
            }
        }

        private void UpdateUIPreviewStopRefresh(bool update)
        {
            if (update)
                UpdateState();
            rbnMain.BeginUpdate();
            try
            {
                UpdateRibbonItems(rgStopRefresh.Items);
                rbtnPreviewStop.Visible = rbtnPreviewStop.Enabled;
                rbtnPreviewRefresh.Visible = rbtnPreviewRefresh.Enabled;
            }
            finally
            {
                rbnMain.EndUpdate();
            }
        }

        private void UpdateUIExport(bool update)
        {
            if (update)
                UpdateState();
            rbnMain.BeginUpdate();
            try
            {
                rbtnExportHtml.Enabled = _actions[ActionTypeEnum.ExportHtml].Enabled;
                rbtnExportPdf.Enabled = _actions[ActionTypeEnum.ExportPdf].Enabled;
                rbtnExportRtf.Enabled = _actions[ActionTypeEnum.ExportRtf].Enabled;
                rbtnExportXls.Enabled = _actions[ActionTypeEnum.ExportXls].Enabled;
                rmExportMore.Enabled = _actions[ActionTypeEnum.ExportMore].Enabled;
                rbtnExportText.Enabled = _actions[ActionTypeEnum.ExportText].Enabled;
            }
            finally
            {
                rbnMain.EndUpdate();
            }
        }

        private void UpdateUIPreviewStatusBar(bool update)
        {
            if (update)
                UpdateState();
            BeginUIUpdate();
            sbMain.BeginUpdate();
            try
            {
                UpdateRibbonItems(sbMain.RightPaneItems);
                UpdateRibbonItems(ribbonToggleGroup1.Items);
            }
            finally
            {
                sbMain.EndUpdate();
                EndUIUpdate();
            }
        }

        private void UpdateState()
        {
            System.Diagnostics.Debug.WriteLine("UpdateState()");

            _state.HasReports = _reportList.Items.Count > 0;
            _state.HasCurrReport = _state.HasReports && _reportList.SelectedIndex > -1;
            _state.DesignMode = ReportDesignMode;
            if (_state.DesignMode && _designer.Report != null)
            {
                try
                {
                    _state.DesignerCanCut = _designer.ClipboardHandler.CanCut;
                    _state.DesignerCanPaste = _designer.ClipboardHandler.CanPaste;
                }
                catch (Exception ex)
                {
                    MessageForm.Error(string.Format(Strings.MainForm.ClipboardErrorFmt, ex.Message));
                    _state.DesignerCanCut = false;
                    _state.DesignerCanPaste = false;
                }
                _state.DesignerCanRedo = _designer.UndoStack.CanRedo;
                _state.DesignerCanUndo = _designer.UndoStack.CanUndo;
                _state.SelectedFieldCount = _designer.SelectedFieldCount;
            }
            else
            {
                _state.DesignerCanCut = false;
                _state.DesignerCanPaste = false;
                _state.DesignerCanRedo = false;
                _state.DesignerCanUndo = false;
                _state.SelectedFieldCount = -1;
            }
            _state.PreviewRendering = _isPreviewRendering;
            _state.DesignerFocused = _designer.Focused;
            _state.ReportListfocused = _reportList.Focused;

            int zf;
            if (_state.DesignMode)
                zf = (int)Math.Round(_designer.ZoomFactor * 100);
            else
                zf = (int)Math.Round(_preview.ZoomFactor * 100);
            // update actions
            _actions[ActionTypeEnum.New].Enabled = !_state.PreviewRendering;
            _actions[ActionTypeEnum.Open].Enabled = !_state.PreviewRendering;
            _actions[ActionTypeEnum.Close].Enabled = !_state.PreviewRendering && _state.HasReports;
            _actions[ActionTypeEnum.Save].Enabled = !_state.PreviewRendering && _state.HasReports;
            _actions[ActionTypeEnum.SaveAs].Enabled = !_state.PreviewRendering && _state.HasReports;
            _actions[ActionTypeEnum.Import].Enabled = !_state.PreviewRendering;
            _actions[ActionTypeEnum.Export].Enabled = !_state.PreviewRendering && _state.HasCurrReport && !_state.DesignMode;

            // stop/refresh preview:
            _actions[ActionTypeEnum.PreviewStop].Enabled = _state.HasCurrReport && !_state.DesignMode && _state.PreviewRendering;
            _actions[ActionTypeEnum.PreviewRefresh].Enabled = _state.HasCurrReport && !_state.DesignMode && !_state.PreviewRendering;

            //
            _actions[ActionTypeEnum.AlignCenter].Enabled =
                _actions[ActionTypeEnum.AlignMiddle].Enabled =
                _actions[ActionTypeEnum.AlignLeft].Enabled =
                _actions[ActionTypeEnum.AlignRight].Enabled =
                _actions[ActionTypeEnum.AlignTop].Enabled =
                _actions[ActionTypeEnum.AlignBottom].Enabled = _state.DesignMode && _state.HasCurrReport && !_designer.Locked && _state.SelectedFieldCount > 1;

            //
            _actions[ActionTypeEnum.GroupSort].Enabled =
                _actions[ActionTypeEnum.Database].Enabled =
                _actions[ActionTypeEnum.ReportInfo].Enabled =
                _actions[ActionTypeEnum.ScriptEditor].Enabled =
                _state.HasCurrReport && _state.DesignMode && !_state.PreviewRendering;

            //
            _actions[ActionTypeEnum.ModeDesign].Enabled = _state.HasCurrReport; // _state.DesignMode && _state.HasCurrReport;
            _actions[ActionTypeEnum.ModeDesign].Pressed = _state.DesignMode;
            _actions[ActionTypeEnum.ModePreview].Enabled = _state.HasCurrReport; // _state.DesignMode && _state.HasCurrReport;
            _actions[ActionTypeEnum.ModePreview].Pressed = !_state.DesignMode;
            //
            _actions[ActionTypeEnum.Cut].Enabled = _state.DesignMode && _state.HasCurrReport && _state.DesignerCanCut;
            _actions[ActionTypeEnum.Copy].Enabled = _state.DesignMode && _state.HasCurrReport && _state.DesignerCanCut;
            _actions[ActionTypeEnum.Paste].Enabled = _state.DesignMode && _state.HasCurrReport && _state.DesignerCanPaste;
            _actions[ActionTypeEnum.Delete].Enabled = _state.DesignMode && _state.HasCurrReport && _state.DesignerCanCut;
            _actions[ActionTypeEnum.Undo].Enabled = _state.DesignMode && _state.HasCurrReport && _state.DesignerCanUndo;
            _actions[ActionTypeEnum.Redo].Enabled = _state.DesignMode && _state.HasCurrReport && _state.DesignerCanRedo;

            //
            _actions[ActionTypeEnum.ExportHtml].Enabled =
                _actions[ActionTypeEnum.ExportPdf].Enabled =
                _actions[ActionTypeEnum.ExportRtf].Enabled =
                _actions[ActionTypeEnum.ExportText].Enabled =
                _actions[ActionTypeEnum.ExportXls].Enabled =
                _actions[ActionTypeEnum.ExportMore].Enabled = !_state.DesignMode && _state.HasCurrReport && !_state.PreviewRendering;

            //
            if (_state.DesignMode && _state.SelectedFieldCount > 0)
            {
                Field[] fields = _designer.SelectedFields;
                string fontName = fields[0].Font.Name;
                float? fontSize = fields[0].Font.Size;
                bool? fontBold = fields[0].Font.Bold;
                bool? fontItalic = fields[0].Font.Italic;
                bool? fontUnderline = fields[0].Font.Underline;
                TextHorzAlign haa;
                TextVertAlign vaa;
                GetAlign(fields[0].Align, out haa, out vaa);
                TextHorzAlign? horzAlign = haa;
                TextVertAlign? vertAlign = vaa;
                Color? foreColor = fields[0].ForeColor;
                Color? backColor = fields[0].BackColor;
                C1.C1Report.BorderStyleEnum? borderStyle = fields[0].BorderStyle;
                double? lineWidth = fields[0].LineWidth;
                Color? borderColor = fields[0].BorderColor;
                for (int i = 1; i < fields.Length; i++)
                {
                    if (fontName != fields[i].Font.Name)
                        fontName = null;
                    if (fontSize != fields[i].Font.Size)
                        fontSize = null;
                    if (fontBold != fields[i].Font.Bold)
                        fontBold = null;
                    if (fontItalic != fields[i].Font.Italic)
                        fontItalic = null;
                    if (fontUnderline != fields[i].Font.Underline)
                        fontUnderline = null;
                    TextHorzAlign ha;
                    TextVertAlign va;
                    GetAlign(fields[i].Align, out ha, out va);
                    if (horzAlign != ha)
                        horzAlign = null;
                    if (vertAlign != va)
                        vertAlign = null;
                    if (foreColor != fields[i].ForeColor)
                        foreColor = null;
                    if (backColor != fields[i].BackColor)
                        backColor = null;
                    if (borderStyle != fields[i].BorderStyle)
                        borderStyle = null;
                    if (lineWidth != fields[i].LineWidth)
                        lineWidth = null;
                    if (borderColor != fields[i].BorderColor)
                        borderColor = null;
                }
                //
                _actions[ActionTypeEnum.FontName].Enabled = true;
                _actions[ActionTypeEnum.FontName].Text = fontName;
                _actions[ActionTypeEnum.FontSize].Enabled = true;
                _actions[ActionTypeEnum.FontSize].Text = fontSize == null ? string.Empty : fontSize.ToString();
                _actions[ActionTypeEnum.FontSizeDown].Enabled = true;
                _actions[ActionTypeEnum.FontSizeUp].Enabled = true;
                //
                _actions[ActionTypeEnum.FontBold].Enabled = true;
                _actions[ActionTypeEnum.FontBold].Pressed = fontBold == true;
                _actions[ActionTypeEnum.FontItalic].Enabled = true;
                _actions[ActionTypeEnum.FontItalic].Pressed = fontItalic == true;
                _actions[ActionTypeEnum.FontUnderline].Enabled = true;
                _actions[ActionTypeEnum.FontUnderline].Pressed = fontUnderline == true;
                //
                _actions[ActionTypeEnum.TextAlignLeft].Enabled = true;
                _actions[ActionTypeEnum.TextAlignLeft].Pressed = horzAlign == TextHorzAlign.Left;
                _actions[ActionTypeEnum.TextAlignCenter].Enabled = true;
                _actions[ActionTypeEnum.TextAlignCenter].Pressed = horzAlign == TextHorzAlign.Center;
                _actions[ActionTypeEnum.TextAlignRight].Enabled = true;
                _actions[ActionTypeEnum.TextAlignRight].Pressed = horzAlign == TextHorzAlign.Right;
                _actions[ActionTypeEnum.TextAlignJustify].Enabled = true;
                _actions[ActionTypeEnum.TextAlignJustify].Pressed = horzAlign == TextHorzAlign.Justify;
                //
                _actions[ActionTypeEnum.TextColor].Enabled = true; // was foreColor != null; -- not sure why, i want to be able to change multiple colors even if they were different initially
                _actions[ActionTypeEnum.TextColor].Color = foreColor == null ? Color.Empty : (Color)foreColor;
                _actions[ActionTypeEnum.FillColor].Enabled = true; // see above backColor != null;
                _actions[ActionTypeEnum.FillColor].Color = backColor == null ? Color.Empty : (Color)backColor;
                // borders:
                _actions[ActionTypeEnum.BorderColor].Enabled = true;
                _actions[ActionTypeEnum.BorderColor].Color = borderColor == null ? Color.Empty : (Color)borderColor;
                _actions[ActionTypeEnum.BorderStyle].Enabled = true;
                _actions[ActionTypeEnum.BorderStyle].Text = borderStyle.ToString();
                _actions[ActionTypeEnum.BorderStyle].Value = borderStyle.HasValue ? (int)borderStyle.Value : -1;
                _actions[ActionTypeEnum.BorderWidth].Enabled = true;
                _actions[ActionTypeEnum.BorderWidth].Text = lineWidth.HasValue ? lineWidth.ToString() : string.Empty;
                // BorderStyle:
                _actions[ActionTypeEnum.BorderStyleNone].Enabled = true;
                _actions[ActionTypeEnum.BorderStyleNone].Value = (int)C1.C1Report.BorderStyleEnum.Transparent;
                _actions[ActionTypeEnum.BorderStyleSolid].Enabled = true;
                _actions[ActionTypeEnum.BorderStyleSolid].Value = (int)C1.C1Report.BorderStyleEnum.Solid;
                _actions[ActionTypeEnum.BorderStyleDash].Enabled = true;
                _actions[ActionTypeEnum.BorderStyleDash].Value = (int)C1.C1Report.BorderStyleEnum.Dash;
                _actions[ActionTypeEnum.BorderStyleDot].Enabled = true;
                _actions[ActionTypeEnum.BorderStyleDot].Value = (int)C1.C1Report.BorderStyleEnum.Dot;
                _actions[ActionTypeEnum.BorderStyleDashDot].Enabled = true;
                _actions[ActionTypeEnum.BorderStyleDashDot].Value = (int)C1.C1Report.BorderStyleEnum.DashDot;
                _actions[ActionTypeEnum.BorderStyleDashDotDot].Enabled = true;
                _actions[ActionTypeEnum.BorderStyleDashDotDot].Value = (int)C1.C1Report.BorderStyleEnum.DashDotDot;
            }
            else
            {
                _actions[ActionTypeEnum.FontName].Enabled = false;
                _actions[ActionTypeEnum.FontName].Text = string.Empty;
                _actions[ActionTypeEnum.FontSize].Enabled = false;
                _actions[ActionTypeEnum.FontSize].Text = string.Empty;
                _actions[ActionTypeEnum.FontSizeDown].Enabled = false;
                _actions[ActionTypeEnum.FontSizeUp].Enabled = false;
                //
                _actions[ActionTypeEnum.FontBold].Enabled = false;
                _actions[ActionTypeEnum.FontBold].Pressed = false;
                _actions[ActionTypeEnum.FontItalic].Enabled = false;
                _actions[ActionTypeEnum.FontItalic].Pressed = false;
                _actions[ActionTypeEnum.FontUnderline].Enabled = false;
                _actions[ActionTypeEnum.FontUnderline].Pressed = false;
                //
                _actions[ActionTypeEnum.TextAlignLeft].Enabled = false;
                _actions[ActionTypeEnum.TextAlignLeft].Pressed = false;
                _actions[ActionTypeEnum.TextAlignCenter].Enabled = false;
                _actions[ActionTypeEnum.TextAlignCenter].Pressed = false;
                _actions[ActionTypeEnum.TextAlignRight].Enabled = false;
                _actions[ActionTypeEnum.TextAlignRight].Pressed = false;
                _actions[ActionTypeEnum.TextAlignJustify].Enabled = false;
                _actions[ActionTypeEnum.TextAlignJustify].Pressed = false;
                //
                _actions[ActionTypeEnum.TextColor].Enabled = false;
                _actions[ActionTypeEnum.TextColor].Color = Color.Empty;
                // borders:
                _actions[ActionTypeEnum.BorderColor].Enabled = false;
                _actions[ActionTypeEnum.BorderColor].Color = Color.Empty;
                _actions[ActionTypeEnum.BorderStyle].Enabled = false;
                _actions[ActionTypeEnum.BorderStyle].Text = C1.C1Report.BorderStyleEnum.Transparent.ToString();
                _actions[ActionTypeEnum.BorderStyle].Value = (int)C1.C1Report.BorderStyleEnum.Transparent;
                _actions[ActionTypeEnum.BorderWidth].Enabled = false;
                _actions[ActionTypeEnum.BorderWidth].Text = string.Empty;
                //
                Section section = _designer.SelectedSection;
                if (section != null)
                {
                    _actions[ActionTypeEnum.FillColor].Enabled = true;
                    _actions[ActionTypeEnum.FillColor].Color = section.BackColor;
                }
            }

            //
            _actions[ActionTypeEnum.Styles].Enabled = _state.DesignMode;
            _actions[ActionTypeEnum.ApplyStyleToSelection].Enabled = _state.DesignMode && _state.SelectedFieldCount > 1; //  was >0 - why?
            _actions[ActionTypeEnum.FormatAsTableRow].Enabled = _state.DesignMode && _state.SelectedFieldCount > 1;

            //
            _actions[ActionTypeEnum.SnapToGrid].Enabled = _state.DesignMode;
            _actions[ActionTypeEnum.SnapToGrid].Pressed = _designer.Grid.Snap;
            _actions[ActionTypeEnum.ShowGrid].Enabled = _state.DesignMode;
            _actions[ActionTypeEnum.ShowGrid].Pressed = _designer.Grid.Visible;
            _actions[ActionTypeEnum.GridProperties].Enabled = _state.DesignMode;
            _actions[ActionTypeEnum.LockFields].Enabled = _state.DesignMode;
            _actions[ActionTypeEnum.LockFields].Pressed = _designer.Locked;
            _actions[ActionTypeEnum.ToggleLockOfSelectedFields].Enabled = _state.DesignMode && !_designer.Locked;
            bool? locked = _designer.IsSelectedFieldsLocked();
            if (locked.HasValue && locked.Value)
                _actions[ActionTypeEnum.ToggleLockOfSelectedFields].Text = Strings.MainForm.UnlockSelectedFields;
            else
                _actions[ActionTypeEnum.ToggleLockOfSelectedFields].Text = Strings.MainForm.LockSelectedFields;

            //
            _actions[ActionTypeEnum.PreviousView].Enabled = !_state.DesignMode && _state.HasCurrReport && !_state.PreviewRendering && _preview.CurrentHistoryEntryIndex > 0;
            _actions[ActionTypeEnum.NextView].Enabled = !_state.DesignMode && _state.HasCurrReport && !_state.PreviewRendering && _preview.CurrentHistoryEntryIndex < _preview.ViewHistory.Count - 1;
            _actions[ActionTypeEnum.EditPageNo].Enabled = !_state.DesignMode && _state.HasCurrReport && !_preview.Busy && _preview.Pages.Count > 0;
            _actions[ActionTypeEnum.EditPageNo].Text = (_preview.StartPageIdx + 1).ToString();
            _actions[ActionTypeEnum.LblPageCount].Enabled = !_state.DesignMode && _state.HasCurrReport && !_preview.Busy && _preview.Pages.Count > 0;
            _actions[ActionTypeEnum.LblPageCount].Text = _preview.Pages.Count > 0 ? string.Format(Strings.MainForm.OfPagesFmt, _preview.Pages.Count) : string.Empty;
            _actions[ActionTypeEnum.PreviousPage].Enabled = !_state.DesignMode && _state.HasCurrReport && !_state.PreviewRendering && _preview.StartPageIdx > 0;
            _actions[ActionTypeEnum.FirstPage].Enabled = !_state.DesignMode && _state.HasCurrReport && !_state.PreviewRendering && _preview.StartPageIdx > 0;
            _actions[ActionTypeEnum.NextPage].Enabled = !_state.DesignMode && _state.HasCurrReport && !_state.PreviewRendering && _preview.StartPageIdx < _preview.Pages.Count - 1;
            _actions[ActionTypeEnum.LastPage].Enabled = !_state.DesignMode && _state.HasCurrReport && !_state.PreviewRendering && _preview.StartPageIdx < _preview.Pages.Count - 1;

            //
            _actions[ActionTypeEnum.PageSize].Enabled = _state.HasCurrReport && !_state.PreviewRendering;
            _actions[ActionTypeEnum.PageSetup].Enabled = _state.HasCurrReport && !_state.PreviewRendering;
            _actions[ActionTypeEnum.PagePortrait].Enabled = _state.HasCurrReport && !_state.PreviewRendering;
            _actions[ActionTypeEnum.PagePortrait].Pressed = _state.HasCurrReport && _designer.Report.Layout.Orientation == OrientationEnum.Portrait;
            _actions[ActionTypeEnum.PageLandscape].Enabled = _state.HasCurrReport && !_state.PreviewRendering;
            _actions[ActionTypeEnum.PageLandscape].Pressed = _state.HasCurrReport && _designer.Report.Layout.Orientation == OrientationEnum.Landscape;

            //
            if (_state.DesignMode && _state.HasCurrReport && !_designer.Locked)
            {
                _actions[ActionTypeEnum.BringToFront].Enabled = _state.SelectedFieldCount > 0;
                _actions[ActionTypeEnum.SendToBack].Enabled = _state.SelectedFieldCount > 0;
                _actions[ActionTypeEnum.EqualHorizontalSpacing].Enabled = _state.SelectedFieldCount > 2;
                _actions[ActionTypeEnum.EqualVerticalSpacing].Enabled = _state.SelectedFieldCount > 2;
                _actions[ActionTypeEnum.IncreaseHorizontalSpacing].Enabled = _state.SelectedFieldCount > 1;
                _actions[ActionTypeEnum.IncreaseVerticalSpacing].Enabled = _state.SelectedFieldCount > 1;
                _actions[ActionTypeEnum.DecreaseHorizontalSpacing].Enabled = _state.SelectedFieldCount > 1;
                _actions[ActionTypeEnum.DecreaseVerticalSpacing].Enabled = _state.SelectedFieldCount > 1;
            }
            else
            {
                _actions[ActionTypeEnum.BringToFront].Enabled = false;
                _actions[ActionTypeEnum.SendToBack].Enabled = false;
                _actions[ActionTypeEnum.EqualHorizontalSpacing].Enabled = false;
                _actions[ActionTypeEnum.EqualVerticalSpacing].Enabled = false;
                _actions[ActionTypeEnum.IncreaseHorizontalSpacing].Enabled = false;
                _actions[ActionTypeEnum.IncreaseVerticalSpacing].Enabled = false;
                _actions[ActionTypeEnum.DecreaseHorizontalSpacing].Enabled = false;
                _actions[ActionTypeEnum.DecreaseVerticalSpacing].Enabled = false;
            }

            //
            _actions[ActionTypeEnum.PreviewPrint].Enabled = !_state.DesignMode && _state.HasCurrReport && !_state.PreviewRendering;

            //
            _actions[ActionTypeEnum.ViewSinglePage].Enabled = !_state.DesignMode && !_state.PreviewRendering;
            _actions[ActionTypeEnum.ViewSinglePage].Pressed = !_preview.Continuous && _preview.PageLayout == C1.Win.C1Preview.PageLayoutEnum.Normal;
            _actions[ActionTypeEnum.ViewContinuous].Enabled = !_state.DesignMode && !_state.PreviewRendering;
            _actions[ActionTypeEnum.ViewContinuous].Pressed = _preview.Continuous && _preview.PageLayout == C1.Win.C1Preview.PageLayoutEnum.Normal;
            _actions[ActionTypeEnum.ViewPagesFacing].Enabled = !_state.DesignMode && !_state.PreviewRendering;
            _actions[ActionTypeEnum.ViewPagesFacing].Pressed = !_preview.Continuous && _preview.PageLayout == C1.Win.C1Preview.PageLayoutEnum.Facing;
            _actions[ActionTypeEnum.ViewPagesFacingContinuous].Enabled = !_state.DesignMode && !_state.PreviewRendering;
            _actions[ActionTypeEnum.ViewPagesFacingContinuous].Pressed = _preview.Continuous && _preview.PageLayout == C1.Win.C1Preview.PageLayoutEnum.Facing;
            _actions[ActionTypeEnum.LblZoom].Enabled = true;
            _actions[ActionTypeEnum.LblZoom].Text = string.Format(Strings.MainForm.PercentFmt, zf);
            _actions[ActionTypeEnum.ZoomValue].Enabled = !_state.PreviewRendering;
            _actions[ActionTypeEnum.ZoomValue].Value = ZoomFactorToZoomSlider(zf);

            //
            _actions[ActionTypeEnum.HandTool].Enabled = !_state.DesignMode;
            _actions[ActionTypeEnum.HandTool].Pressed = !_state.DesignMode && _preview.MouseMode == MouseModeEnum.Hand;
            _actions[ActionTypeEnum.TextSelectTool].Enabled = !_state.DesignMode;
            _actions[ActionTypeEnum.TextSelectTool].Pressed = !_state.DesignMode && _preview.MouseMode == MouseModeEnum.Select;
            _actions[ActionTypeEnum.PreviewFind].Enabled = !_state.DesignMode && !_state.PreviewRendering;

            //
            _actions[ActionTypeEnum.PropertiesAlphabetical].Enabled = true;
            _actions[ActionTypeEnum.PropertiesAlphabetical].Pressed = _propGrid.PropertySort == PropertySort.Alphabetical;
            _actions[ActionTypeEnum.PropertiesCategorized].Enabled = true;
            _actions[ActionTypeEnum.PropertiesCategorized].Pressed = _propGrid.PropertySort == PropertySort.Categorized || _propGrid.PropertySort == PropertySort.CategorizedAlphabetical;
            _actions[ActionTypeEnum.PropertiesFilter].Enabled = true;
            _actions[ActionTypeEnum.PropertiesFilter].Pressed = _useFieldWrappers;

            //
            _actions[ActionTypeEnum.NewReport].Enabled = _state.DesignMode;
            try
            {
                _actions[ActionTypeEnum.PasteReport].Enabled = _state.DesignMode && !_state.PreviewRendering && GetReportDataPresent(Clipboard.GetDataObject());
            }
            catch (Exception ex)
            {
                MessageForm.Error(string.Format(Strings.MainForm.ClipboardErrorFmt, ex.Message));
                _actions[ActionTypeEnum.PasteReport].Enabled = false;
            }
            _actions[ActionTypeEnum.CutReport].Enabled = _state.DesignMode && !_state.PreviewRendering && _state.HasCurrReport;
            _actions[ActionTypeEnum.CopyReport].Enabled = _state.DesignMode && _state.HasCurrReport;
            _actions[ActionTypeEnum.DeleteReport].Enabled = _state.DesignMode && !_state.PreviewRendering && _state.HasCurrReport;
            _actions[ActionTypeEnum.MoveReportDown].Enabled = _state.DesignMode && !SortReportList && !_state.PreviewRendering && _reportList.SelectedIndex >= 0 && _reportList.SelectedIndex < _reportList.Items.Count - 1;
            _actions[ActionTypeEnum.MoveReportUp].Enabled = _state.DesignMode && !SortReportList && !_state.PreviewRendering && _reportList.SelectedIndex > 0;

            _actions[ActionTypeEnum.SelectedReport].Enabled = true;
            if (_state.HasCurrReport)
                _actions[ActionTypeEnum.SelectedReport].Text = string.Format(Strings.MainForm.ReportFmt, _designer.Report.ReportName);
            else
                _actions[ActionTypeEnum.SelectedReport].Text = Strings.MainForm.ReportNotSelected;

            //
            if (_state.DesignMode && _state.HasCurrReport && !_designer.Locked)
            {
                _actions[ActionTypeEnum.AlignToGrid].Enabled = _state.SelectedFieldCount > 0;
                _actions[ActionTypeEnum.SizeToGrid].Enabled = _state.SelectedFieldCount > 0;
                _actions[ActionTypeEnum.HeightToShortest].Enabled = _state.SelectedFieldCount > 1;
                _actions[ActionTypeEnum.HeightToTallest].Enabled = _state.SelectedFieldCount > 1;
                _actions[ActionTypeEnum.WidthToNarrowest].Enabled = _state.SelectedFieldCount > 1;
                _actions[ActionTypeEnum.WidthToWidest].Enabled = _state.SelectedFieldCount > 1;
            }
            else
            {
                _actions[ActionTypeEnum.AlignToGrid].Enabled = false;
                _actions[ActionTypeEnum.SizeToGrid].Enabled = false;
                _actions[ActionTypeEnum.HeightToShortest].Enabled = false;
                _actions[ActionTypeEnum.HeightToTallest].Enabled = false;
                _actions[ActionTypeEnum.WidthToNarrowest].Enabled = false;
                _actions[ActionTypeEnum.WidthToWidest].Enabled = false;
            }

            //
            _actions[ActionTypeEnum.ShowPropertyGrid].Enabled = _state.DesignMode;
            _actions[ActionTypeEnum.ShowFieldList].Enabled = _state.DesignMode;

            //
            _actions[ActionTypeEnum.ZoomOnePage].Enabled =

                _actions[ActionTypeEnum.ZoomTwoPages].Enabled =
                _actions[ActionTypeEnum.ZoomMorePages].Enabled =
                _actions[ActionTypeEnum.ZoomFourPages].Enabled =
                _actions[ActionTypeEnum.ZoomEightPages].Enabled =
                _actions[ActionTypeEnum.ZoomTwelvePages].Enabled =
                _actions[ActionTypeEnum.ZoomFitToWindow].Enabled = !_state.DesignMode && _state.HasCurrReport && !_state.PreviewRendering;
            _actions[ActionTypeEnum.Zoom].Enabled =
                _actions[ActionTypeEnum.Zoom10].Enabled =
                _actions[ActionTypeEnum.Zoom25].Enabled =
                _actions[ActionTypeEnum.Zoom50].Enabled =
                _actions[ActionTypeEnum.Zoom75].Enabled =
                _actions[ActionTypeEnum.Zoom100].Enabled =
                _actions[ActionTypeEnum.Zoom125].Enabled =
                _actions[ActionTypeEnum.Zoom150].Enabled =
                _actions[ActionTypeEnum.Zoom200].Enabled =
                _actions[ActionTypeEnum.Zoom500].Enabled = _state.HasCurrReport && !_state.PreviewRendering;
            //
            _actions[ActionTypeEnum.ZoomOnePage].Pressed = !_state.DesignMode && _state.HasCurrReport && _preview.Rows == 1 && _preview.Cols == 1;
            _actions[ActionTypeEnum.ZoomTwoPages].Pressed = !_state.DesignMode && _state.HasCurrReport && _preview.Rows == 1 && _preview.Cols == 2;
            _actions[ActionTypeEnum.ZoomFourPages].Pressed = (_preview.Rows == 2) && (_preview.Cols == 2);
            _actions[ActionTypeEnum.ZoomEightPages].Pressed = (_preview.Rows == 2) && (_preview.Cols == 4);
            _actions[ActionTypeEnum.ZoomTwelvePages].Pressed = (_preview.Rows == 3) && (_preview.Cols == 4);
            _actions[ActionTypeEnum.ZoomFitToWindow].Pressed = !_state.DesignMode && _preview.ZoomMode == C1.Win.C1Preview.ZoomModeEnum.WholePage;
            _actions[ActionTypeEnum.Zoom10].Pressed = zf == 10;
            _actions[ActionTypeEnum.Zoom25].Pressed = zf == 25;
            _actions[ActionTypeEnum.Zoom50].Pressed = zf == 50;
            _actions[ActionTypeEnum.Zoom75].Pressed = zf == 75;
            _actions[ActionTypeEnum.Zoom100].Pressed = zf == 100;
            _actions[ActionTypeEnum.Zoom125].Pressed = zf == 125;
            _actions[ActionTypeEnum.Zoom150].Pressed = zf == 150;
            _actions[ActionTypeEnum.Zoom200].Pressed = zf == 200;
            _actions[ActionTypeEnum.Zoom500].Pressed = zf == 500;
            //
            _actions[ActionTypeEnum.SelectAll].Enabled = _state.DesignMode && _reportList.Items.Count != 0;
            _actions[ActionTypeEnum.ShowSubreport].Enabled = _state.DesignMode && _reportList.Items.Count != 0;
            _actions[ActionTypeEnum.ShowSubreport].Pressed = _designer.ShowSubreportContent;
            _actions[ActionTypeEnum.LinkSubreport].Enabled = _state.DesignMode && _state.SelectedFieldCount > 0;
            _actions[ActionTypeEnum.EditSubreport].Enabled = _state.DesignMode && _state.SelectedFieldCount > 0;
        }

        // update UI (_mns, toolbars, etc)
        private void UpdateUI()
        {
            BeginUIUpdate();
            try
            {
                UpdateState();

                //
                UpdateUIApplicationMenu(false);

                //
                UpdateUIMode();

                //
                UpdateUIEdit(false);

                // 
                UpdateUIFont(false);

                //
                UpdateUIBorders(false);

                //
                UpdateUIData(false);

                //
                UpdateUIFields(false);

                //
                UpdateUITools(false);

                //
                UpdateUIFormat(false);

                //
                UpdateUIGrid(false);

                //
                UpdateUIControlAlignment(false);

                //
                UpdateUISize(false);

                //
                UpdateUIPageSetup(false);

                //
                UpdateUIPosition(false);

                //
                UpdateUIZoom(false);

                //
                UpdateUINavigation(false);

                //
                UpdateUIPreviewTools(false);

                //
                UpdateUIPreviewStopRefresh(false);

                //
                UpdateUIExport(false);

                //
                UpdateUIPreviewStatusBar(false);

                //
                UpdateCommands(false);

                //
                UpdateFormCaption();
            }
            finally
            {
                EndUIUpdate();
            }
        }

        private void FullUpdateUI()
        {
            if (UIUpdating)
                return;

            BeginUIUpdate();
            try
            {
                _designer.Refresh();
                object[] selectedObjects = _propGrid.SelectedObjects;
                _propGrid.SelectedObject = null;
                _propGrid.SelectedObjects = selectedObjects;
            }
            finally
            {
                EndUIUpdate();
            }
            UpdateUI();
        }

        private void SetDirty()
        {
            _dirty = true;
            FullUpdateUI();
        }

        // build a unique report name
        private bool EnsureUniqueName(C1Report rpt)
        {
            // already unique? no work
            if (IsUniqueName(rpt))
                return false;

            // make sure we have some kind of name
            string name = rpt.ReportName;
            if (string.IsNullOrEmpty(name))
                name = Strings.MainForm.FallbackReportName;

            // strip trailing digits
            string baseName = Regex.Replace(name, "(.+) [0-9]+$", "$1");

            // and append counter until unique
            for (int i = 1; ; i++)
            {
                string newName = string.Format("{0} {1}", baseName, i);
                if (IsUniqueName(rpt, newName))
                {
                    rpt.ReportName = newName;
                    return true;
                }
            }
        }

        // check whether a report name is valid (non empty, no duplicate)
        private bool IsUniqueName(C1Report rpt)
        {
            return IsUniqueName(rpt, rpt.ReportName);
        }

        private bool IsUniqueName(C1Report rpt, string name)
        {
            // don't allow empty names
            if (name == null || name.Length == 0)
                return false;

            // look for duplicates
            foreach (ReportItem item in this._reportList.Items)
            {
                if (item._report.Equals(rpt))
                    continue;
                if (string.Compare(name, item._report.ReportName, true) == 0)
                    return false;
            }

            // name is unique
            return true;
        }

        // start a new report definition file
        private bool NewFile()
        {
            return NewFile(false);
        }

        private bool NewFile(bool quiet)
        {
            // make sure changes aren't lost
            if (!quiet && !DiscardChangesOK())
                return false;

            // re-initialize everything
            lbFields.Items.Clear();
            _reportList.Items.Clear();
            _designer.Report = null;
            _fileName = string.Empty;
            _dirty = false;
            _preview.Document = null;
            ReportDesignMode = true;
            ShowStatus(Strings.MainForm.Ready);
            UpdateUI();

            // done
            return true;
        }

        private void RecentFileClick(object sender, EventArgs e)
        {
            string fileName = (string)((RibbonListItem)sender).Tag;
            if (!OpenFile(fileName))
                MessageForm.Warn(string.Format(Strings.MainForm.ErrCannotOpenRecentFmt, fileName));
        }

        private void AddRecentFile(string fileName)
        {
            int i = _recentFiles.IndexOf(fileName);
            if (i != -1)
            {
                object v = _recentFiles[0];
                _recentFiles[0] = _recentFiles[i];
                _recentFiles[i] = v;
            }
            else
            {
                if (_recentFiles.Count > cMaxRecentFilesCount)
                    _recentFiles.RemoveAt(_recentFiles.Count - 1);
                _recentFiles.Insert(0, fileName);
            }

            UpdateRecentFiles();
            AppSettings.SaveList("recentfiles", _recentFiles, false, MessageForm.Warn);
            if (_reportList != null && _reportList.SelectedItem != null)
                AppSettings.SaveValue("lastselectedreport", _reportList.SelectedItem.Text);
        }

        private void DeleteRecentFile(string fileName)
        {
            _recentFiles.Remove(fileName);
            UpdateRecentFiles();

            AppSettings.SaveList("recentfiles", _recentFiles, false, MessageForm.Warn);
        }

        private void UpdateRecentFiles()
        {
            for (int i = ramMain.RightPaneItems.Count - 1; i > 1; i--)
            {
                RibbonItem ri = ramMain.RightPaneItems[i];
                ramMain.RightPaneItems.RemoveAt(i);
                ri.Dispose();
            }

            for (int i = 0; i < _recentFiles.Count; i++)
            {
                string fn = (string)_recentFiles[i];

                RibbonListItem rli = new RibbonListItem();
                rli.Click += RecentFileClick;
                rli.Tag = fn;
                RibbonButton rb = new RibbonButton();
                if (i < 10)
                    rb.Text = string.Format(Strings.MainForm.NumberedRecentFileMenuFmt, i + 1, Path.GetFileName(fn));
                else
                    rb.Text = string.Format(Strings.MainForm.RecentFileMenuFmt, Path.GetFileName(fn));
                rb.ToolTip = Path.GetFullPath(fn);

                rli.Items.Add(rb);
                ramMain.RightPaneItems.Add(rli);
            }
        }

        private void InitRecentFiles()
        {
            _recentFiles = AppSettings.LoadList("recentfiles", MessageForm.Warn);
            UpdateRecentFiles();
        }

        // open report definition file
        private bool OpenFile()
        {
            // make sure changes aren't lost
            if (!DiscardChangesOK())
                return true; // << not an error

            // get file name
            using (OpenFileDialog dlg = new OpenFileDialog())
            {
                dlg.DereferenceLinks = true;
                dlg.Title = Strings.MainForm.OpenFileDlgTitle;
                dlg.DefaultExt = "xml";
                dlg.FileName = "*.xml";
                dlg.Filter = Strings.MainForm.FileFilter;
                dlg.FilterIndex = 0;
                if (dlg.ShowDialog() != DialogResult.OK)
                    return false;

                // open the file, update MRU list
                bool ok = true;
                Cursor = Cursors.WaitCursor;
                try
                {
                    OpenFileInternal(dlg.FileName);
                    AddRecentFile(dlg.FileName);
                    _fileName = dlg.FileName;
                }
                catch (Exception e)
                {
                    MessageForm.Warn(string.Format(Strings.MainForm.ErrCannotLoadReportFmt, dlg.FileName, e.Message));
                    DeleteRecentFile(dlg.FileName);
                    ok = false;
                }
                Cursor = Cursors.Default;
                return ok;
            }
        }

        private bool OpenFile(string fileName)
        {
            // make sure changes aren't lost
            if (!DiscardChangesOK())
                return true; // << not an error

            // go ahead and load the file
            bool ok = true;
            Cursor = Cursors.WaitCursor;
            try
            {
                OpenFileInternal(fileName);
                AddRecentFile(fileName);
                _fileName = fileName;
            }
            catch
            {
                DeleteRecentFile(fileName);
                ok = false;
            }
            Cursor = Cursors.Default;
            return ok;
        }

        private void OpenFileInternal(string fileName)
        {
            OpenFileInternal(fileName, false);
        }

        private void OpenFileInternal(string fileName, bool quiet)
        {
            // load XML document
            XmlDocument doc = new XmlDocument();
            doc.PreserveWhitespace = true;
            doc.Load(fileName);

            // get names from XmlDocument
            string[] reports = _reportRender.GetReportInfo(doc);
            if (reports == null)
            {
                if (!quiet)
                    MessageForm.Warn(string.Format(Strings.MainForm.ErrCannotFindAnyReportsFmt, fileName));
                return;
            }

            // load files
            _fileName = fileName;
            _reportList.BeginUpdate();
            _reportList.Items.Clear();
            int cnt = reports.Length;
            for (int i = 0; i < cnt; i++)
            {
                ShowStatus(string.Format(Strings.MainForm.LoadingReportOfReportsFmt, i + 1, cnt, reports[i]));
                C1Report report = new C1Report();
                try
                {
                    report.Load(doc, reports[i]);
                    _reportList.Items.Add(new ReportItem(report));
                }
                catch (Exception x)
                {
                    MessageForm.Warn(string.Format(Strings.MainForm.ErrCannotLoadReportFmt, reports[i], x.Message));
                }
            }
            _reportList.EndUpdate();
            // reset selected report, otherwise a report from the old file may remain loaded:
            _reportList.SelectedIndex = -1;

            // done loading, update lists and UI
            FinishLoading();
            _dirty = false;
            UpdateUI();

            //
            ShowStatus(Strings.MainForm.Ready);

            // try loading last edited report:
            string lastReport = AppSettings.LoadValue("lastselectedreport");
            if (!string.IsNullOrEmpty(lastReport))
            {
                for (int i = 0; i < _reportList.Items.Count; ++i)
                {
                    ReportItem ri = _reportList.Items[i] as ReportItem;
                    if (ri != null && ri.Text == lastReport)
                    {
                        _reportList.SelectedIndex = i;
                        break;
                    }
                }
            }

            if (_reportList.Items.Count > 0 && _reportList.SelectedIndex <= 0)
                _reportList.SelectedIndex = 0;
        }

        // start editing currently selected subreport
        private void OpenSubreport()
        {
            Field[] sel = _designer.SelectedFields;
            if (sel.Length > 0 && sel[0].Subreport != null)
            {
                C1Report subReport = sel[0].Subreport;
                for (int i = 0; i < _reportList.Items.Count; i++)
                {
                    ReportItem ri = _reportList.Items[i] as ReportItem;
                    if (ri != null && ri._report.ReportName == subReport.ReportName)
                    {
                        _reportList.SelectedIndex = i;
                        break;
                    }
                }
            }
        }

        // fix subreport references: replace subreports loaded into subreport 
        // fields with references to actual reports in the list.
        private void FinishLoading()
        {
            for (int i = 0; i < _reportList.Items.Count; i++)
            {
                // scan this report looking for fields with subreports
                ReportItem ri = _reportList.Items[i] as ReportItem;
                foreach (Field f in ri._report.Fields)
                {
                    if (f.Subreport == null)
                        continue;

                    // found subreport: replace embedded report with reference to report on the list
                    bool found = false;
                    string reportName = f.Subreport.ReportName;
                    foreach (ReportItem riSub in _reportList.Items)
                    {
                        if (String.Compare(riSub._report.ReportName, reportName, true) != 0)
                            continue;
                        f.Subreport = riSub._report;
                        found = true;
                        break;
                    }

                    // subreport not found: add it to the list and loop again
                    if (!found)
                    {
                        _reportList.Items.Add(new ReportItem(f.Subreport));
                        i = -1; // << restart from the top
                        break;
                    }
                }
            }

            // update report list (to feed subreport TypeConverter)
            UpdateReportList();

            // select the first report (if any)
            ReportDesignMode = true;
        }

        // update report list (to feed subreport TypeConverter)
        private void UpdateReportList()
        {
            // update list
            ArrayList al = new ArrayList();
            foreach (ReportItem ri in _reportList.Items)
                al.Add(ri._report);
            C1Report[] arr = (C1Report[])al.ToArray(typeof(C1Report));
            foreach (ReportItem ri in _reportList.Items)
                ri._report.ReportList = arr;

            // update icons
            _reportList.UpdateIcons();

            // very stupid fix, overwise listview looks wrong(it has empty first row)
            // in following scenarion:
            // - run report designer
            // - set reports tab to floating
            // - load report
            // - open reports tab, see that the list view has empty first row, it is a bug
            _reportList.View = View.LargeIcon;
            _reportList.View = View.Details;
        }

        // import Access and Crystal reports
        private bool ImportFile()
        {
            // get file name
            using (OpenFileDialog dlg = new OpenFileDialog())
            {
                dlg.DereferenceLinks = true;
                dlg.Title = Strings.MainForm.ImportReportDlgTitle;
                dlg.DefaultExt = "mdb";
                if (_borland)
                    dlg.Filter = Strings.MainForm.ImportFilterBorland;
                else
                    dlg.Filter = Strings.MainForm.ImportFilter;

                if (dlg.ShowDialog() != DialogResult.OK)
                    return false;

                // let user know we're working...
                ShowStatus(string.Format(Strings.MainForm.ImportingFromFmt, dlg.FileName));
                Cursor = Cursors.WaitCursor;

                // open the file, update MRU list
                IC1ReportImportFilter filter = null;
                try
                {
                    // build import filter class
                    string fileName = dlg.FileName.ToLower();
                    filter = (fileName.EndsWith(".rpt") && !_borland)
                        ? (IC1ReportImportFilter)new CrystalFilter()
                        : (IC1ReportImportFilter)new AccessFilter(this);

                    // import reports
                    _importList = new ArrayList();
                    filter.Loading += new EventHandler(_loading);
                    _clearOnImport = filter.Import(dlg.FileName, _importList);
                }
                catch (Exception e)
                {
                    MessageForm.Warn(string.Format(Strings.MainForm.ErrCannotImportReportFmt, dlg.FileName, e.Message));
                }
            }

            try
            {
                // update list
                if (_importList == null || _importList.Count <= 0)
                    return false;

                // clear existing list
                if (_clearOnImport)
                {
                    if (!NewFile())
                        return false;
                }

                // sort the imported list
                _importList.Sort(ReportsComparer.Instance);

                // add reports to list
                foreach (C1Report rpt in _importList)
                {
                    EnsureUniqueName(rpt);
                    _reportList.Items.Add(new ReportItem(rpt));
                }

                // update subreport references
                FinishLoading();
                _dirty = true;

                // select first new report
                if (_importList.Count > 0)
                {
                    foreach (ReportItem ri in _reportList.Items)
                    {
                        if (ri._report == _importList[0])
                        {
                            ri.Selected = true;
                            break;
                        }
                    }
                }

                // done
                return true;
            }
            finally
            {
                _importList = null;
                UpdateUI();
                Cursor = Cursors.Default;
                ShowStatus(Strings.MainForm.Ready);
            }
        }

        private void _loading(object sender, System.EventArgs e)
        {
            C1Report rpt = (C1Report)_importList[_importList.Count - 1];
            ShowStatus(string.Format(Strings.MainForm.ImportingReportFmt, rpt.ReportName));
        }

        // save report definition file
        private bool SaveFile(bool prompt)
        {
            // save current filename
            string fileName = _fileName;

            // save as usual
            bool retval = SaveFileInternal(prompt);

            // if we're editing a component, restore temp filename
            if (_noFile)
            {
                _fileName = fileName;
            }

            // return
            return retval;
        }

        private bool SaveFileInternal(bool prompt)
        {
            // get file name
            if (prompt || _fileName == null || _fileName.Length == 0)
            {
                using (SaveFileDialog dlg = new SaveFileDialog())
                {
                    dlg.DereferenceLinks = true;
                    dlg.Title = Strings.MainForm.SaveReportDlgTitle;
                    dlg.FileName = "*.xml";
                    dlg.DefaultExt = "xml";
                    dlg.Filter = Strings.MainForm.FileFilter;
                    dlg.FilterIndex = 0;
                    if (dlg.ShowDialog() != DialogResult.OK || dlg.FileName.Length == 0)
                        return false;
                    _fileName = dlg.FileName;
                    AddRecentFile(_fileName);
                }
            }

            // start long operation
            Cursor = Cursors.WaitCursor;

            // open xml file
            // (null encoding uses utf-8 and suppresses it from xml header)
            try
            {
                XmlTextWriter w = new XmlTextWriter(_fileName, null);
                w.Formatting = Formatting.Indented;
                w.Indentation = 2;
                w.WriteStartDocument();

                // write all reports to it
                w.WriteStartElement("Reports");
                int cnt = _reportList.Items.Count;
                for (int i = 0; i < cnt; i++)
                {
                    ReportItem ri = (ReportItem)_reportList.Items[i];
                    ShowStatus(string.Format(Strings.MainForm.SavingFmt, i + 1, cnt, ri.ToString()));
                    ri._report.Save(w, _embedImages, false);
                }
                w.WriteEndElement();

                // close the file
                w.Close();

                // saved successfully, no longer dirty
                _dirty = false;
                UpdateUI();
            }
            catch (Exception x)
            {
                MessageForm.Warn(x.Message);
                return false;
            }
            finally
            {
                Cursor = Cursors.Default;
            }

            // and be done
            return true;
        }

        // check whether user wants to save or discard current changes before loading a file
        internal bool DiscardChangesOK()
        {
            // no changes? we're OK then
            if (!_dirty)
                return true;

            // prompt user
            DialogResult dr = MessageForm.Ask(Strings.MainForm.SaveChangesQ, MessageBoxButtons.YesNoCancel);
            switch (dr)
            {
                case DialogResult.Yes:
                    return SaveFile(false);
                case DialogResult.No:
                    return true;
                case DialogResult.Cancel:
                    return false;
            }

            // should never get here
            return false;
        }

        // update status bar text
        private void ShowStatus()
        {
            ShowStatus(null);
        }

        private void ShowStatus(string msg)
        {
            if (ReportDesignMode)
            {
                foreach (RibbonItem ri in sbMain.RightPaneItems)
                {
                    if (ri.Name == "rlblZoom" ||
                        ri.Name == "rtbZoom" ||
                        ri.Name == "rlblSelectedReport" ||
                        ri.Name == "ribbonSeparator17")
                        continue;
                    ri.Visible = false;
                }
                if (msg != null)
                    rlblStatusBarText.Text = msg;
            }
            else
            {
                foreach (RibbonItem ri in sbMain.RightPaneItems)
                {
                    if (ri == rbtnRenderError || ri == rsepRenderError)
                        ri.Visible = !string.IsNullOrEmpty(rbtnRenderError.ToolTip);
                    else
                        ri.Visible = true;
                }

                if (msg != null)
                    rlblStatusBarText.Text = msg;
                UpdateUIPreviewStatusBar(true);
            }
            sbMain.Refresh();
        }

        private void ExportReport(C1Report report, string fileName, Exporter exporter)
        {
            if (report == null)
                return;

            Debug.Assert(exporter != null && exporter.ExportProvider.CanExportType(typeof(C1Report)));
            if (exporter == null)
                return;

            Cursor = Cursors.WaitCursor;
            ShowStatus(string.Format(Strings.MainForm.ExportingFmt, report.ReportName, fileName));
            try
            {
                // save report definition to detect changes while exporting
                string reportDefinition = report.ReportDefinition;
                // export:
                exporter.Document = report;
                exporter.ShowOptions = _showExportOptions;
                exporter.LongOperation += (sender, e) =>
                    ShowStatus(string.Format(Strings.MainForm.ExportingPercentFmt, report.ReportName, fileName, e.Complete));
                exporter.Export(fileName);
                // restore original if needed
                report.SetReportDefinition(reportDefinition, false, false);
            }
            catch (Exception e)
            {
                MessageForm.Warn(string.Format(Strings.MainForm.ErrCannotExportReportFmt, fileName, e.Message));
            }
            finally
            {
                ShowStatus(Strings.MainForm.Ready);
                Cursor = Cursors.Default;
            }
        }

        private void ExportReport()
        {
            ExportReport(_defaultExportIndex);
        }

        // export selected report
        private void ExportReport(int filterIndex)
        {
            // Prior to *.6.20121.54502, _designer.Report was used for export, not sure why.
            // This could lead to weird results - exporting partially generated reports:
            var report = _preview.Document as C1Report;
            if (report == null)
                return;

            // get export file name
            using (SaveFileDialog dlg = new SaveFileDialog())
            {
                dlg.DereferenceLinks = true;
                dlg.Title = Strings.MainForm.ExportReportDlgTitle;
                dlg.FileName = C1.C1Report.Util.Misc.CheckFileName(report.ReportName, "_");
                dlg.Filter = _exportFilter;
                dlg.FilterIndex = filterIndex;
                DialogResult dr = dlg.ShowDialog();
                if (dr != DialogResult.OK)
                    return;
                _defaultExportIndex = dlg.FilterIndex;

                // autosave
                if (_dirty && _autoSave)
                    SaveFile(false);

                // export:
                if (s_exporters.ContainsKey(dlg.FilterIndex))
                {
                    ExportReport(report, dlg.FileName, s_exporters[dlg.FilterIndex]());
                }
            }
        }

        // create a name for a new field
        internal string GetUniqueFieldName()
        {
            FieldCollection fields = _designer.Report.Fields;
            for (int i = 1; ; i++)
            {
                var name = string.Format(Strings.MainForm.NewFieldNameFmt, i);
                if (!fields.Contains(name))
                    return name;
            }
            // never gets here
        }

        #region Clipboard

        private bool GetReportDataPresent(IDataObject data)
        {
            return (data != null) ? data.GetDataPresent(_cfReport.Name) : false;
        }

        private IDataObject BuildDataObject()
        {
            ReportItem ri = _reportList.SelectedItem;
            if (ri == null)
                return null;
            return new DataObject(_cfReport.Name, ri._report.ReportDefinition);
        }

        private bool PasteDataObject(IDataObject obj)
        {
            string strDef = obj.GetData(_cfReport.Name) as string;
            if (strDef == null) return false;

            // create new report from definition
            C1Report rpt = new C1Report();
            rpt.ReportDefinition = strDef;

            // create new report item
            if (!_dragSource)
            {
                EnsureUniqueName(rpt);
            }
            ReportItem ri = new ReportItem(rpt);

            // add new report to list and select it
            if (_reportList.Sorting == SortOrder.None)
            {
                Point pt = _reportList.PointToClient(Control.MousePosition);
                ListViewItem item = _reportList.GetItemAt(pt.X, pt.Y);
                int index = item == null ? _reportList.Items.Count : item.Index;
                _reportList.Items.Insert(index, ri);
            }
            else
            {
                _reportList.Items.Add(ri);
            }
            _reportList.SelectedIndex = ri.Index;

            // done
            _dirty = true;
            UpdateUI();
            UpdateReportList();
            return true;
        }

        #endregion

        #endregion

        #region Internal
        // show wizard to create new report
        internal bool AddReport()
        {
            HideSpash();

            // get parameters for report wizard
            DataProvider dataProvider = DataProvider.OLEDB;
            string conn = null, rs = null;
            if (_designer.Report != null)
            {
                DataSource ds = _designer.Report.DataSource;
                conn = ds.ConnectionString;
                rs = ds.RecordSource;
                dataProvider = ds.DataProvider;
            }

            // show report wizard
            using (ReportWizard wizard = new ReportWizard(this))
            {
                // center on screen if the main form is not visible yet
                if (!Visible)
                {
                    wizard.StartPosition = FormStartPosition.CenterScreen;
                }

                // show the wizard
                ReportWizardResult result = wizard.ShowDialog(dataProvider, conn, rs, _dataSchema);

                // add report to list, preview or design it
                switch (result)
                {
                    // preview or design the new repot
                    case ReportWizardResult.Preview:
                    case ReportWizardResult.Design:

                        // rename the report if necessary
                        C1Report rpt = wizard.Report;
                        EnsureUniqueName(rpt);

                        // set report metadata
                        rpt.ReportInfo.Author = Environment.UserName;

                        // add the report to the list and select it
                        ListViewItem lvi = _reportList.Items.Add(new ReportItem(rpt));
                        _reportList.SelectedIndex = lvi.Index;

                        // set preview or design based on user choice
                        ReportDesignMode = (result == ReportWizardResult.Design);

                        // done
                        _dirty = true;
                        UpdateUI();
                        break;

                    // cancel...
                    default:
                        return false;
                }
            }

            // done...
            UpdateReportList();
            return true;
        }

        // delete current report (after user confirmation)
        internal bool DeleteReport()
        {
            return DeleteReport(false);
        }

        internal bool DeleteReport(bool quiet)
        {
            return DeleteReport(_reportList.SelectedItem, quiet);
        }

        internal bool DeleteReport(ReportItem ri, bool quiet)
        {
            // make sure we have an item to delete
            if (ri == null)
                return false;

            // warn user, this is not undoable
            if (!quiet)
            {
                DialogResult dr = MessageForm.Ask(string.Format(Strings.MainForm.ConfirmDeleteReportFmt, ri.ToString()), MessageBoxButtons.YesNo);
                if (dr != DialogResult.Yes)
                    return false;
            }

            // remove report from list
            int index = _reportList.SelectedIndex;
            _reportList.Items.Remove(ri);

            // update selection
            int count = _reportList.Items.Count;
            _reportList.SelectedIndex = (index < count) ? index : count - 1;

            // we're dirty
            _dirty = true;

            // update report list (to feed subreport TypeConverter)
            UpdateReportList();
            UpdateUI();
            return true;
        }

        /// <summary>
        /// Opens a specified URL in an external browser.
        /// Shows error message if there is an error.
        /// </summary>
        /// <param name="url">The URL to open.</param>
        internal static void OpenURL(string url)
        {
            try
            {
                System.Diagnostics.Process.Start(url);
            }
            catch (Exception ex)
            {
                MessageForm.Warn(string.Format(Strings.MainForm.HelpUrlErrorFmt, ex.Message));
            }
        }
        #endregion

        #region Private properties

        private bool ReportDesignMode
        {
            get { return _reportDesignMode; }
            set
            {
                // no work?
                if (value == _reportDesignMode)
                    return;
                SetDesignMode(value);
            }
        }

        private bool UIUpdating
        {
            get { return _UIUpdateCounter != 0; }
        }

        #endregion

        #region Nested types
        private class ReportsComparer : IComparer
        {
            public static ReportsComparer Instance = new ReportsComparer();

            #region IComparer Members
            int IComparer.Compare(object x, object y)
            {
                return string.Compare(((C1Report)x).ReportName, ((C1Report)y).ReportName, true);
            }
            #endregion
        }

        private enum ActionTypeEnum
        {
            New,
            Open,
            Close,
            Save,
            SaveAs,
            Import,
            Export,

            AlignCenter,
            AlignMiddle,
            AlignLeft,
            AlignRight,
            AlignTop,
            AlignBottom,

            GroupSort,
            Database,
            ReportInfo,
            ScriptEditor,

            Cut,
            Copy,
            Paste,
            Delete,
            Undo,
            Redo,
            SelectAll,

            ShowSubreport,
            LinkSubreport,
            EditSubreport,

            ExportHtml,
            ExportPdf,
            ExportRtf,
            ExportText,
            ExportXls,
            ExportMore,

            FontName,
            FontSize,
            FontSizeDown,
            FontSizeUp,
            FontBold,
            FontItalic,
            FontUnderline,
            TextAlignLeft,
            TextAlignCenter,
            TextAlignRight,
            TextAlignJustify,
            TextColor,
            FillColor,

            Styles,
            ApplyStyleToSelection,
            FormatAsTableRow,
            SnapToGrid,
            ShowGrid,
            GridProperties,
            LockFields,

            PreviousView,
            NextView,
            FirstPage,
            PreviousPage,
            NextPage,
            LastPage,
            EditPageNo,
            LblPageCount,

            PageSize,
            PageSetup,
            PagePortrait,
            PageLandscape,

            BringToFront,
            SendToBack,
            EqualHorizontalSpacing,
            EqualVerticalSpacing,
            IncreaseHorizontalSpacing,
            IncreaseVerticalSpacing,
            DecreaseHorizontalSpacing,
            DecreaseVerticalSpacing,

            PreviewPrint,

            ViewSinglePage,
            ViewContinuous,
            ViewPagesFacing,
            ViewPagesFacingContinuous,

            LblZoom,
            ZoomValue,

            HandTool,
            TextSelectTool,
            PreviewFind,

            PropertiesAlphabetical,
            PropertiesCategorized,
            PropertiesFilter,

            NewReport,
            PasteReport,
            CutReport,
            CopyReport,
            DeleteReport,
            MoveReportDown,
            MoveReportUp,

            AlignToGrid,
            SizeToGrid,
            HeightToShortest,
            HeightToTallest,
            WidthToNarrowest,
            WidthToWidest,

            ShowPropertyGrid,
            ShowFieldList,

            Zoom,
            ZoomOnePage,
            ZoomTwoPages,
            ZoomMorePages,
            ZoomFourPages,
            ZoomEightPages,
            ZoomTwelvePages,
            ZoomFitToWindow,
            Zoom10,
            Zoom25,
            Zoom50,
            Zoom75,
            Zoom100,
            Zoom125,
            Zoom150,
            Zoom200,
            Zoom500,

            ModeDesign,
            ModePreview,

            SelectedReport,

            ToggleLockOfSelectedFields,

            BorderColor,
            BorderWidth,
            BorderStyle,
            BorderStyleNone,
            BorderStyleSolid,
            BorderStyleDash,
            BorderStyleDot,
            BorderStyleDashDot,
            BorderStyleDashDotDot,

            PreviewStop,
            PreviewRefresh,
        }

        private class Action
        {
            public bool Enabled;
            public bool Pressed;
            public string Text;
            public Color Color;
            public int Value;
        }

        private class Actions
        {
            private Action[] _items;

            #region Constructors
            public Actions()
            {
                _items = new Action[Enum.GetValues(typeof(ActionTypeEnum)).Length];
                for (int i = 0; i < _items.Length; i++)
                    _items[i] = new Action();
            }
            #endregion

            #region Public properties
            public Action this[ActionTypeEnum index]
            {
                get { return _items[(int)index]; }
            }
            #endregion
        }

        private struct State
        {
            /// <summary>
            /// At least one report exists in the reports list.
            /// </summary>
            public bool HasReports;
            /// <summary>
            /// Report opened in preview or designer.
            /// </summary>
            public bool HasCurrReport;
            /// <summary>
            /// Design mode.
            /// </summary>
            public bool DesignMode;
            /// <summary>
            /// Preview mode and report currently rendering.
            /// </summary>
            public bool PreviewRendering;
            /// <summary>
            /// ReportList control focused.
            /// </summary>
            public bool ReportListfocused;
            /// <summary>
            /// Designer focused.
            /// </summary>
            public bool DesignerFocused;
            /// <summary>
            /// Result of _designer.ClipboardHandler.CanCut.
            /// </summary>
            public bool DesignerCanCut;
            /// <summary>
            /// Result of _designer.ClipboardHandler.CanPaste.
            /// </summary>
            public bool DesignerCanPaste;
            /// <summary>
            /// Result of _designer.UndoStack.CanUndo.
            /// </summary>
            public bool DesignerCanUndo;
            /// <summary>
            /// Result of _designer.UndoStack.CanRedo.
            /// </summary>
            public bool DesignerCanRedo;
            /// <summary>
            /// Count of fields in selected designer.
            /// </summary>
            public int SelectedFieldCount;
        }

        private enum TextHorzAlign
        {
            Left = 0,
            Center = 1,
            Right = 2,
            Justify = 3,
        }

        private enum TextVertAlign
        {
            Top = 0,
            Middle = 1,
            Bottom = 2,
        }
        #endregion

        #region ISite implementation

        IComponent ISite.Component
        {
            get { return this; }
        }

        IContainer ISite.Container
        {
            get { return this.components; }
        }

        bool ISite.DesignMode
        {
            get { return false; }
        }

        string ISite.Name
        {
            get { return string.Empty; }
            set { }
        }

        object IServiceProvider.GetService(Type serviceType)
        {
            return null;
        }

        #endregion

        private bool FindHideButton(Control.ControlCollection cc)
        {
            foreach (Control c in cc)
            {
                if (c is Button && c.Name == "m_btnHide")
                {
                    c.Visible = false;
                    return true;
                }
                if (FindHideButton(c.Controls))
                    return true;
            }
            return false;
        }

        private void MainForm_Load(object sender, EventArgs e)
        {
            try
            {
                MainForm_Load();
            }
            catch (Exception ex)
            {
                string msg;
                if (ex.InnerException != null)
                    msg = string.Format(CultureInfo.InvariantCulture,
                        Strings.MainForm.FatalExcInnerFmt,
                        ex.Message,
                        ex.InnerException);
                else
                    msg = string.Format(CultureInfo.InvariantCulture,
                        Strings.MainForm.FatalExcFmt,
                        ex.Message);
                MessageForm.Fatal(msg);
            }
        }

        private void MainForm_Load()
        {
            // hide the "Hide" button on "Find" tab
            FindHideButton(ptspMain.Controls);


            // load recent connections from registry if the
            // config file is empty (easier upgrade)
            ArrayList list = AppSettings.LoadList("recentconnections", MessageForm.Warn);
            if (list.Count == 0)
            {
                string subKey = _regKey + @"\Recent Connection List";
                using (RegistryKey key = Registry.CurrentUser.OpenSubKey(subKey))
                {
                    if (key != null)
                    {
                        string connList = key.GetValue("MRU", string.Empty) as string;
                        foreach (string conn in connList.Split('\t'))
                            if (conn.Length > 0 && !list.Contains(conn))
                                list.Add(conn);
                        AppSettings.SaveList("recentconnections", list, true, MessageForm.Warn);
                    }
                }
            }

            // initialize application state
            _appConfig = new AppConfig(this);
            _appConfig.LoadAppState();

            // default theme:
            if (string.IsNullOrEmpty(Theme))
                Theme = DefatulTheme;

            if (this.dtpReports.Parent == null)
                this.c1DockingTab1.Controls.Add(this.dtpReports);
            if (this.dtpFields.Parent == null)
                this.c1DockingTab1.Controls.Add(this.dtpFields);
            if (this.dtpProperties.Parent == null)
                this.c1DockingTab1.Controls.Add(this.dtpProperties);
            if (this.dtpPages.Parent == null)
                this.c1DockingTab1.Controls.Add(this.dtpPages);
            if (this.dtpOutline.Parent == null)
                this.c1DockingTab1.Controls.Add(this.dtpOutline);
            if (this.dtpPreviewFind.Parent == null)
                this.c1DockingTab1.Controls.Add(this.dtpPreviewFind);
            this.c1DockingTab1.Visible = true;

            // start in design mode
            SetDesignMode(true);

            // Insert 'mode' group (design/preview) into all tabs:
            rtInsert.Groups.Insert(0, rgMode);
            rtArrange.Groups.Insert(0, rgMode);
            rtPageSetup.Groups.Insert(0, rgMode);
            rtPreview.Groups.Insert(0, rgMode);

            // initialize main menu
            InitRecentFiles();

            // initialize custom fields
            LoadCustomFields();

            // initialize UI
            UpdateUI();

            // activate designer
            _designer.Select();

            // starting from designer: load info from temp files, configure designer
            if (StartFromDesigner())
                return;

            // load file specified in command line
            string[] args = Environment.GetCommandLineArgs();
            if (args.Length > 1 && File.Exists(args[1]))
                OpenFile(args[1]);
            else
            {
                // reload last file (quietly)
                if (_loadOnStartUp && _recentFiles.Count > 0)
                {
                    try
                    {
                        OpenFileInternal((string)_recentFiles[0], true);
                    }
                    catch
                    {
                    }
                }
            }

        }

        private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            // if form is closed while rendering, raise the flag and bail out;
            // close will be re-posted by the timer:
            if (_state.PreviewRendering)
            {
                _reportRender.Cancel = true;
                _closeRequestedWhileRendering = true;
                e.Cancel = true;
                return;
            }

            // when editing temp file, save changes and quit
            if (_noFile)
            {
                // confirm discarding changes
                if (_dirty)
                {
                    // prompt user
                    switch (MessageForm.Ask(Strings.MainForm.SaveChangesTempFileQ, MessageBoxButtons.YesNoCancel))
                    {
                        case DialogResult.No:
                            SaveTempFile(false);
                            return;
                        case DialogResult.Cancel:
                            e.Cancel = true;
                            return;
                    }
                }

                // default behavior, save and exit
                SaveTempFile(true);
                return;
            }

            // make sure we won't lose our changes
            if (!DiscardChangesOK())
            {
                e.Cancel = true;
                return;
            }

            // save app state for next time
            _appConfig.SaveAppState();
        }

        private void MainForm_KeyDown(object sender, KeyEventArgs e)
        {
            switch (e.KeyCode | e.Modifiers)
            {
                case Keys.Escape:
                    if (_state.DesignMode)
                    {
                        // this is ugly - designer does it itself, but doesn't seem to fire any event for that:
                        _designer.CreateFieldInfo = null;
                        UpdateUIFields(false);
                    }
                    else if (_state.PreviewRendering && _reportRender.IsBusy)
                    {
                        DoPreviewStop();
                        e.Handled = true;
                    }
                    break;
                // Delete
                case Keys.Delete:
                    if (_designer.Focused && _actions[ActionTypeEnum.Delete].Enabled)
                    {
                        DoDeleteFields();
                        e.Handled = true;
                    }
                    else if (_reportList.Focused && _actions[ActionTypeEnum.DeleteReport].Enabled)
                    {
                        DoDeleteReport();
                        e.Handled = true;
                    }
                    break;
                // Cut
                case Keys.Delete | Keys.Shift:
                case Keys.X | Keys.Control:
                    if (_designer.Focused && _actions[ActionTypeEnum.Cut].Enabled)
                    {
                        DoCutFields();
                        e.Handled = true;
                    }
                    else if (_reportList.Focused && _actions[ActionTypeEnum.CutReport].Enabled)
                    {
                        DoCutReport();
                        e.Handled = true;
                    }
                    break;
                // Copy
                case Keys.C | Keys.Control:
                case Keys.Insert | Keys.Control:
                    if (_designer.Focused && _actions[ActionTypeEnum.Copy].Enabled)
                    {
                        DoCopyFields();
                        e.Handled = true;
                    }
                    else if (_reportList.Focused && _actions[ActionTypeEnum.CopyReport].Enabled)
                    {
                        DoCopyReport();
                        e.Handled = true;
                    }
                    break;
                // Paste
                case Keys.Insert | Keys.Shift:
                case Keys.V | Keys.Control:
                    if (_designer.Focused && _actions[ActionTypeEnum.Paste].Enabled)
                    {
                        DoPasteFields();
                        e.Handled = true;
                    }
                    else if (_reportList.Focused && _actions[ActionTypeEnum.PasteReport].Enabled)
                    {
                        DoPasteReport();
                        e.Handled = true;
                    }
                    break;
                // New
                case Keys.N | Keys.Control:
                    if (_actions[ActionTypeEnum.New].Enabled)
                    {
                        DoNew();
                        e.Handled = true;
                    }
                    break;
                // New report
                case Keys.N | Keys.Control | Keys.Shift:
                    if (_actions[ActionTypeEnum.NewReport].Enabled)
                    {
                        DoNewReport();
                        e.Handled = true;
                    }
                    break;
                // Open
                case Keys.O | Keys.Control:
                    if (_actions[ActionTypeEnum.Open].Enabled)
                    {
                        DoOpen();
                        e.Handled = true;
                    }
                    break;
                // Save
                case Keys.S | Keys.Control:
                    if (_actions[ActionTypeEnum.Save].Enabled)
                    {
                        DoSave();
                        e.Handled = true;
                    }
                    break;
                // Print
                case Keys.P | Keys.Control:
                    if (_actions[ActionTypeEnum.PreviewPrint].Enabled)
                    {
                        DoPreviewPrint();
                        e.Handled = true;
                    }
                    break;
                // Preview
                case Keys.F5:
                    if (_actions[ActionTypeEnum.ModePreview].Enabled)
                    {
                        DoPreview();
                        e.Handled = true;
                    }
                    break;
                // Design
                case Keys.F5 | Keys.Shift:
                    if (_actions[ActionTypeEnum.ModeDesign].Enabled)
                    {
                        DoDesign();
                        e.Handled = true;
                    }
                    break;
                // Undo
                case Keys.Z | Keys.Control:
                    if (_actions[ActionTypeEnum.Undo].Enabled)
                    {
                        DoUndo();
                        e.Handled = true;
                    }
                    break;
                // Redo
                case Keys.Y | Keys.Control:
                    if (_actions[ActionTypeEnum.Redo].Enabled)
                    {
                        DoRedo();
                        e.Handled = true;
                    }
                    break;
                // FontBold
                case Keys.B | Keys.Control:
                    if (_actions[ActionTypeEnum.FontBold].Enabled)
                    {
                        DoFontStyle(rbtnFontBold);
                        e.Handled = true;
                    }
                    break;
                // FontItalic
                case Keys.I | Keys.Control:
                    if (_actions[ActionTypeEnum.FontItalic].Enabled)
                    {
                        DoFontStyle(rbtnFontItalic);
                        e.Handled = true;
                    }
                    break;
                // FontUnderline
                case Keys.U | Keys.Control:
                    if (_actions[ActionTypeEnum.FontUnderline].Enabled)
                    {
                        DoFontStyle(rbtnFontUnderline);
                        e.Handled = true;
                    }
                    break;
                // ShowGrid
                case Keys.G | Keys.Control:
                    if (_actions[ActionTypeEnum.ShowGrid].Enabled)
                    {
                        DoShowHideGrid();
                        e.Handled = true;
                    }
                    break;
                // HistoryBack
                case Keys.BrowserBack:
                case Keys.Left | Keys.Alt:
                    if (_actions[ActionTypeEnum.PreviousView].Enabled)
                    {
                        DoNavigation(rbtnPreviousView);
                        e.Handled = true;
                    }
                    break;
                // HistoryNext
                case Keys.BrowserForward:
                case Keys.Right | Keys.Alt:
                    if (_actions[ActionTypeEnum.NextView].Enabled)
                    {
                        DoNavigation(rbtnNextView);
                        e.Handled = true;
                    }
                    break;
                case Keys.F4:
                    if (_actions[ActionTypeEnum.ShowPropertyGrid].Enabled)
                    {
                        DoShowPropertyGrid();
                        e.Handled = true;
                    }
                    break;
                case Keys.F3:
                case Keys.F | Keys.Control:
                    if (_actions[ActionTypeEnum.PreviewFind].Enabled)
                    {
                        DoPreviewTool(rbtnPreviewFind);
                        e.Handled = true;
                    }
                    break;
            }
        }

        private void _reportList_SelectedIndexChanged(object sender, EventArgs e)
        {
            // show design view
            _designer.CreateFieldInfo = null;
            ReportDesignMode = true;

            // get selected report
            C1Report rpt = _reportList.SelectedItem != null ? _reportList.SelectedItem._report : null;

            // unhook old report from designer
            if (_designer.Report != null)
                _designer.Report.Site = null;

            // hook up custom editors and site (used to initialize editors)
            if (rpt != null)
            {
                rpt.EditStatement = new C1Report.EditExpressionDelegate(_editStatement);
                rpt.EditExpression = new C1Report.EditExpressionDelegate(_editExpression);
                rpt.EditDataSource = new C1Report.EditDataSourceDelegate(_editDataSource);
                rpt.Site = (ISite)this;
            }

            _designer.Report = rpt;

            // save the name of last edited report:
            if (_reportList.SelectedItem != null)
                AppSettings.SaveValue("lastselectedreport", _reportList.SelectedItem.Text);
        }

        private void _reportList_DoubleClick(object sender, EventArgs e)
        {
            DoPreview();
        }

        private void _reportList_AfterLabelEdit(object sender, LabelEditEventArgs e)
        {
            // get new name
            // ** note that newName is empty when you close the editor without changing anything,
            //    seems like a bug in the ListView control
            string newName = (e.Label == null) ? string.Empty : e.Label.Trim();

            // make sure new name is Valid (not empty and unique)
            ReportItem item = _reportList.Items[e.Item] as ReportItem;
            if (!IsUniqueName(item._report, newName))
            {
                if (newName.Length > 0)
                {
                    MessageForm.Warn(Strings.MainForm.ReportNameMustBeUnique);
                }
                e.CancelEdit = true;
                return;
            }

            // save new report name
            ReportItem ri = _reportList.Items[e.Item] as ReportItem;
            ri._report.ReportName = newName;

            // refresh property grid to show new report name
            _propGrid.Refresh();

            // update report list (to feed subreport TypeConverter)
            _dirty = true;
            UpdateUI();
            UpdateReportList();
        }

        private void _reportList_MouseDown(object sender, MouseEventArgs e)
        {
            // keep info to start dragging on mouse move
            if (e.Button == MouseButtons.Left)
            {
                _downIndex = _reportList.SelectedIndex;
                _downPoint = new Point(e.X, e.Y);
            }
        }

        private void _reportList_MouseMove(object sender, MouseEventArgs e)
        {
            // start dragging if...
            if ((Control.MouseButtons & MouseButtons.Left) != 0 &&	// left button is down, and
                _downIndex > -1 &&									// a report was selected, and
                _downIndex == _reportList.SelectedIndex &&			// still is, and
                (Math.Abs(_downPoint.X - e.X) > DRAG_THRESHOLD ||				// the mouse has moved at least
                Math.Abs(_downPoint.Y - e.Y) > DRAG_THRESHOLD))					// 3 pixels
            {
                // get report to drag
                ReportItem ri = _reportList.SelectedItem;

                // start dragging the report
                _dragSource = true;
                DragDropEffects effect = _reportList.DoDragDrop(BuildDataObject(), DragDropEffects.Copy | DragDropEffects.Move);
                _dragSource = false;
                System.Diagnostics.Debug.WriteLine(string.Format("DoDragDrop returned {0}", effect));

                // if it was a move, delete the report...
                if (effect == DragDropEffects.Move)
                    DeleteReport(ri, true);
            }
        }

        private void _reportList_DragOver(object sender, DragEventArgs e)
        {
            // dragging report definition files
            if ((e.AllowedEffect & DragDropEffects.Copy) != 0)
            {
                string[] fn = e.Data.GetData("FileDrop") as string[];
                if (fn != null && fn.Length == 1 && Path.GetExtension(fn[0]).ToLower().IndexOf('x') > -1)
                {
                    e.Effect = DragDropEffects.Copy;
                    return;
                }
            }

            // dragging reports
            if (GetReportDataPresent(e.Data))
            {
                // default behavior: copy with ctrl key
                e.Effect = ((Control.ModifierKeys & Keys.Control) != 0) ? DragDropEffects.Copy : DragDropEffects.Move;

                // only copy is allowed when source == target and the list is sorted
                if (_dragSource && SortReportList)
                {
                    e.Effect = DragDropEffects.Copy;
                }

                return;
            }
        }

        private void _reportList_DragDrop(object sender, DragEventArgs e)
        {
            // dropping report definition files
            if (e.Effect == DragDropEffects.Copy)
            {
                string[] fn = e.Data.GetData("FileDrop") as string[];
                if (fn != null && fn.Length > 0)
                {
                    OpenFile(fn[0]);
                    return;
                }
            }

            // dropping reports
            if (GetReportDataPresent(e.Data))
            {
                PasteDataObject(e.Data);
            }
        }

        private void _designer_SelectionChanged(object sender, EventArgs e)
        {
            // show field properties
            object[] sel = _designer.SelectedFields;
            if (sel.Length > 0)
            {
                // // show field wrappers / show raw fields
                _propGrid.SelectedObjects = (_useFieldWrappers) ? FieldWrapper.Create(sel) : sel;
            }
            else if (_designer.SelectedSection != null) // show section properties
            {
                _propGrid.SelectedObject = _designer.SelectedSection;
            }
            else if (_designer.Report != null) // show report properties
            {
                _propGrid.SelectedObject = _designer.Report;
            }
            else // nothing to show...
            {
                _propGrid.SelectedObject = null;
            }

            // update UI (_mns, toolbars, etc)
            _designer.CreateFieldInfo = null;
            UpdateUI();
        }

        private void _designer_ValuesChanged(object sender, EventArgs e)
        {
            _designer.CreateFieldInfo = null;
            SetDirty();
        }

        private void _designer_ReportChanged(object sender, EventArgs e)
        {
            _designer.UndoStack.Clear();
            UpdateUI();
        }

        private void _designer_ZoomFactorChanged(object sender, EventArgs e)
        {
            UpdateUIZoom(true);
        }

        private void _designer_KeyDown(object sender, KeyEventArgs e)
        {
            /*// switch focus to grid when user starts typing text
            if (!e.Alt && !e.Control && char.IsLetterOrDigit((char)e.KeyValue))
            {
                _propGrid.Focus();
            }

            // ignore delete key (we're handling it on the main form)
            if (e.KeyCode == Keys.Delete)
            {
                e.Handled = true;
            }*/
        }

        private void _designer_CreateField(object sender, CreateFieldEventArgs e)
        {
            // save undo info
            _designer.UndoStack.SaveState();

            // create new field
            string fldName = GetUniqueFieldName();
            FieldCollection fields = e.Section.Fields;
            Field field = fields.Add(fldName, null, e.FieldBounds);

            // set new field properties
            RibbonItem btn = e.CreateFieldInfo as RibbonItem;
            if (btn == rbtnFieldDataField)
            {
                field.Text = _createInfo != null ? _createInfo : field.Name; // was  "data"; -- why?
                field.Calculated = _createInfo != null;
            }
            else if (btn == rbtnFieldRtf)
            {
                field.Text = _createInfo != null ? _createInfo : "richText";
                field.Calculated = _createInfo != null;
                field.RTF = true;
            }
            else if (btn == rbtnFieldCheckBox)
            {
                field.Text = _createInfo != null ? _createInfo : "checkBox";
                field.Calculated = _createInfo != null;
                field.CheckBox = CheckBoxEnum.CheckBox;
            }
            else if (btn == rbtnFieldBarCode)
            {
                field.Text = _createInfo != null ? _createInfo : "BARCODE";
                field.Calculated = _createInfo != null;
#if (CLR40 || CLR45) && WINFORMS
                field.BarCode = BarCodeEnum.Code39x;
#else
                field.BarCode = BarCodeEnum.Code39;
#endif
            }
            else if (btn == rbtnFieldCalculated)
            {
                // this handles both common calculated fields and arbitrary forumlas
                CommonFields.SetupField(_designer.Report, field, _createInfo);
            }
            else if (btn == rbtnFieldPicture)
            {
                field.Picture = _createInfo;
                field.Calculated = false;
            }
            else if (btn == rbtnFieldSubReport)
            {
                foreach (ReportItem ri in _reportList.Items)
                {
                    if (ri.ToString() == _createInfo && ri._report != _designer.Report)
                    {
                        field.Subreport = ri._report;
                        field.CanGrow = true;
                        break;
                    }
                }
            }
            else if (btn == rbtnFieldPageBreak)
            {
                field.ForcePageBreak = ForcePageBreakEnum.After;
                field.Calculated = false;
            }
            else if (btn == rbtnFieldRectangle)
            {
                field.BorderStyle = C1.C1Report.BorderStyleEnum.Solid;
                field.Calculated = false;
            }
            else if (btn == rbtnFieldLine)
            {
                // check line slant
                LineSlantEnum ls = LineSlantEnum.NoSlant;
                Rectangle rc = e.ClientBounds;
                if (rc.Width >= rc.Height / 8 && rc.Height >= rc.Width / 8)
                {
                    Point pt = _designer.PointToClient(Control.MousePosition);
                    bool left = Math.Abs(pt.X - rc.X) < Math.Abs(pt.X - rc.Right);
                    bool top = Math.Abs(pt.Y - rc.Y) < Math.Abs(pt.Y - rc.Bottom);
                    ls = ((left && top) || (!left && !top))
                        ? LineSlantEnum.Down
                        : LineSlantEnum.Up;
                }

                // set field properties
                field.BorderStyle = C1.C1Report.BorderStyleEnum.Solid;
                field.Shape = new LineShape(ls);
                field.Calculated = false;
            }
            else if (btn.Tag is Field) // custom field
            {
                // remove field that we already added...
                fields.Remove(field);

                // clone custom field
                field = (Field)btn.Tag;
                field = (Field)field.Clone();

                // add clone to report
                field.Name = GetUniqueFieldName();
                field.Bounds = e.FieldBounds;
                fields.Add(field);
            }
            else
            {
                System.Diagnostics.Debug.Assert(false, "Unknown field creator object");
            }

            // report is dirty
            _dirty = true;

            // select the new field, zap creator
            _designer.CreateFieldInfo = null;
            _designer.SelectedFields = new Field[] { field };

            UpdateUI();

            // update report list icons
            if (btn == rbtnFieldSubReport)
                _reportList.UpdateIcons();
        }

        private void _designer_DoubleClick(object sender, EventArgs e)
        {
            OpenSubreport();
        }

        private void _propGrid_PropertyValueChanged(object s, PropertyValueChangedEventArgs e)
        {
            // update field picker when the user changes field/section names
            if (e.ChangedItem.PropertyDescriptor.Name == "Name")
            {
                _fieldPicker.Refresh();
            }

            // update list to ensure unique names and to update report list
            if (e.ChangedItem.PropertyDescriptor.Name == "ReportName")
            {
                ReportItem item = _reportList.SelectedItem as ReportItem;
                if (EnsureUniqueName(item._report))
                {
                    _propGrid.Invalidate();
                }
                item.Text = item._report.ReportName;
                UpdateReportList();
            }

            // update icons to show reports that contain subreports
            if (e.ChangedItem.PropertyDescriptor.Name == "Subreport")
            {
                _reportList.UpdateIcons();
            }

            // apply changes to designer
            _designer.Refresh();

            // remember whether we're dirty
            _dirty = true;
            UpdateUI();
        }

        private void _reportRender_StartPage(object sender, C1.C1Report.ReportEventArgs e)
        {
            UpdateUI();
            ShowStatus(string.Format(Strings.MainForm.RenderingPressEsc, _reportRender.ReportName));
        }

        void _reportRender_StartReport(object sender, System.EventArgs e)
        {
            // clear error info if any
            ClearRenderError();

            //
            _isPreviewRendering = true;
            UpdateUI();
            ShowStatus(string.Format(Strings.MainForm.Rendering, _designer.Report.ReportName));
            Cursor = Cursors.WaitCursor;
        }

        private void _reportRender_EndReport(object sender, EventArgs e)
        {
            _isPreviewRendering = false;
            UpdateUI();
            ShowStatus(Strings.MainForm.Ready);
            Cursor = Cursors.Default;
        }

        private void _reportRender_ReportError(object sender, C1.C1Report.ReportEventArgs e)
        {
            // build error message (no duplicates)
            string err = rbtnRenderError.ToolTip;
            if (err.IndexOf(e.Exception.Message) > -1)
                return;
            if (err.Length == 0)
                err = string.Format(
                    Strings.MainForm.ErrorsInReportFmt,
                    _reportRender.ReportName,
                    Strings.MainForm.ClickToCopyErrors);
            err += string.Format("\r\n- {0}", e.Exception.Message);

            // show error message and icon
            SetRenderError(err);
        }

        #region Ribbon events

        private void DoNew()
        {
            NewFile();
        }

        private void DoClose()
        {
            NewFile();
        }

        private void DoOpen()
        {
            OpenFile();
        }

        private void DoSave()
        {
            SaveFile(false);
        }

        private void DoSaveAs()
        {
            SaveFile(true);
        }

        private void DoImport()
        {
            ImportFile();
        }

        private void DoExport()
        {
            ExportReport();
        }

        private void DoCopyReport()
        {
            // copy report to clipboard
            if (_reportList.SelectedItem == null)
                return;

            try
            {
                Clipboard.SetDataObject(BuildDataObject());
            }
            catch (Exception ex)
            {
                MessageForm.Error(string.Format(Strings.MainForm.ClipboardErrorFmt, ex.Message));
            }
            UpdateUI();
        }

        private void DoCopyFields()
        {
            try
            {
                _designer.ClipboardHandler.Copy();
            }
            catch (Exception ex)
            {
                MessageForm.Error(string.Format(Strings.MainForm.ClipboardErrorFmt, ex.Message));
            }

            UpdateUI();
        }

        private void DoCutReport()
        {
            if (_reportList.SelectedItem != null)
            {
                try
                {
                    Clipboard.SetDataObject(BuildDataObject());
                    DeleteReport(true);
                }
                catch (Exception ex)
                {
                    MessageForm.Error(string.Format(Strings.MainForm.ClipboardErrorFmt, ex.Message));
                }
            }
        }

        private void DoCutFields()
        {
            _designer.UndoStack.SaveState();
            _dirty = true;
            try
            {
                _designer.ClipboardHandler.Cut();
            }
            catch (Exception ex)
            {
                MessageForm.Error(string.Format(Strings.MainForm.ClipboardErrorFmt, ex.Message));
            }
            _reportList.UpdateIcons();
            UpdateUI();
        }

        private void DoPasteReport()
        {
            try
            {
                PasteDataObject(Clipboard.GetDataObject());
            }
            catch (Exception ex)
            {
                MessageForm.Error(string.Format(Strings.MainForm.ClipboardErrorFmt, ex.Message));
            }
        }

        private void DoPasteFields()
        {
            _designer.UndoStack.SaveState();
            _dirty = true;
            try
            {
                _designer.ClipboardHandler.Paste();
            }
            catch (Exception ex)
            {
                MessageForm.Error(string.Format(Strings.MainForm.ClipboardErrorFmt, ex.Message));
            }
            _reportList.UpdateIcons();
            UpdateUI();
        }

        private void DoDeleteFields()
        {
            _designer.UndoStack.SaveState();
            _dirty = true;
            try
            {
                _designer.ClipboardHandler.Delete();
            }
            catch (Exception ex)
            {
                MessageForm.Error(string.Format(Strings.MainForm.ClipboardErrorFmt, ex.Message));
            }
            _reportList.UpdateIcons();
            UpdateUI();
        }

        private void DoDeleteReport()
        {
            DeleteReport();
        }

        private void DoMoveReportUp()
        {
            int selectedIndex = _reportList.SelectedIndex;
            if (selectedIndex <= 0)
                return;

            //
            ReportItem ri1 = (ReportItem)_reportList.Items[selectedIndex - 1];
            ReportItem ri2 = (ReportItem)_reportList.Items[selectedIndex];

            _reportList.BeginUpdate();
            ri1.Remove();
            ri2.Remove();
            _reportList.Items.Insert(selectedIndex - 1, ri2);
            _reportList.Items.Insert(selectedIndex, ri1);
            _reportList.FocusedItem = ri2;
            _reportList.EndUpdate();

            //
            SetDirty();
        }

        private void DoMoveReportDown()
        {
            int selectedIndex = _reportList.SelectedIndex;
            if (selectedIndex >= _reportList.Items.Count - 1)
                return;

            //
            ReportItem ri1 = (ReportItem)_reportList.Items[selectedIndex + 1];
            ReportItem ri2 = (ReportItem)_reportList.Items[selectedIndex];

            _reportList.BeginUpdate();
            ri1.Remove();
            ri2.Remove();
            _reportList.Items.Insert(selectedIndex, ri1);
            _reportList.Items.Insert(selectedIndex + 1, ri2);
            _reportList.FocusedItem = ri2;
            _reportList.EndUpdate();

            //
            SetDirty();
        }

        private void DoUndo()
        {
            TextBox tb = _designer.FieldEditor as TextBox;
            if (tb != null && tb.Focused)
                tb.Undo();
            else
                _designer.UndoStack.Undo();
        }

        private void DoRedo()
        {
            _designer.UndoStack.Redo();
        }

        private void DoExit()
        {
            if (DiscardChangesOK())
                Close();
        }

        private void DoSaveAndExit()
        {
            SaveTempFile(true);
            Close();
        }

        private void DoCancelAndExit()
        {
            SaveTempFile(false);
            Close();
        }

        private void DoNewReport()
        {
            AddReport();
        }

        private void DoDesign()
        {
            ReportDesignMode = true;
        }

        private void DoPreview()
        {
            ReportDesignMode = false;
        }

        private void DoGroupSort()
        {
            if (_designer.Report != null)
                using (GroupEditorForm dlg = new GroupEditorForm())
                {
                    if (dlg.ShowDialog(_designer.Report) == DialogResult.OK)
                        SetDirty();
                }
        }

        private void DoDatabase()
        {
            if (_designer.Report != null)
                using (DataSourceForm dlg = new DataSourceForm())
                {
                    if (dlg.EditDataSource(_designer.Report, _dataSchema))
                        SetDirty();
                }
        }

        private void DoReportInfo()
        {
            // get current report
            ReportItem ri = _reportList.SelectedItem;
            if (ri == null || ri._report == null)
                return;

            // show form
            using (ReportInfoForm f = new ReportInfoForm())
            {
                if (f.ShowDialog(ri._report) == DialogResult.OK)
                {
                    // apply new information to current report
                    ri._report.ReportInfo = f.ReportInfo.Clone();

                    // apply to all reports
                    if (f.ApplyToAll && _reportList.Items.Count > 1)
                    {
                        // confirm first
                        if (MessageForm.Ask(Strings.MainForm.ApplyToAllQ) == DialogResult.Yes)
                        {
                            foreach (ReportItem reportItem in _reportList.Items)
                            {
                                reportItem._report.ReportInfo = f.ReportInfo.Clone();
                            }
                        }
                    }
                    _designer.CreateFieldInfo = null;
                    SetDirty();
                }
            }
        }

        private void DoScriptEditor()
        {
            // NOTE: The dirty flag is set ty EditorScriptItem.Written handler.
            if (_designer.Report != null)
            {
                string result;
                EditScript(_designer.Report, _designer.Report.GlobalScripts, false, out result);
            }
        }

        private void DoPreviewPrint()
        {
            _preview.Print();
        }

        private void DoSetFontName()
        {
            Field[] fields = _designer.SelectedFields;
            if (fields == null || fields.Length <= 0)
                return;

            // check font name
            string fontName = rcbFontName.Text;
            using (InstalledFontCollection ifc = new InstalledFontCollection())
            {
                foreach (FontFamily ff in ifc.Families)
                    if (ff.Name == fontName)
                    {
                        _designer.UndoStack.SaveState();
                        foreach (Field field in fields)
                            field.Font.Name = fontName;
                        SetDirty();
                        return;
                    }
            }

            UpdateUIFont(true);
        }

        private void DoSetFontSize()
        {
            Field[] fields = _designer.SelectedFields;
            if (fields == null || fields.Length <= 0)
                return;

            // try parse text
            float fontSize;
            if (float.TryParse(rcbFontSize.Text, out fontSize) || float.TryParse(rcbFontSize.Text, NumberStyles.Any, CultureInfo.InvariantCulture, out fontSize))
            {
                _designer.UndoStack.SaveState();
                foreach (Field field in fields)
                    field.Font.Size = fontSize;
                SetDirty();
                return;
            }

            UpdateUIFont(true);
        }

        private void DoFontStyle(RibbonItem item)
        {
            Field[] fields = _designer.SelectedFields;
            if (fields == null || fields.Length <= 0)
                return;

            if (item == rbtnFontSizeDown)
            {
                _designer.UndoStack.SaveState();
                foreach (Field field in fields)
                    if (field.Font.Size > 1)
                        field.Font.Size--;
            }
            else if (item == rbtnFontSizeUp)
            {
                _designer.UndoStack.SaveState();
                foreach (Field field in fields)
                    field.Font.Size++;
            }
            else if (item == rbtnFontBold)
            {
                _designer.UndoStack.SaveState();
                foreach (Field field in fields)
                    field.Font.Bold = !field.Font.Bold;// rbtnFontBold.Pressed;
            }
            else if (item == rbtnFontItalic)
            {
                _designer.UndoStack.SaveState();
                foreach (Field field in fields)
                    field.Font.Italic = !field.Font.Italic;// rbtnFontItalic.Pressed;
            }
            else if (item == rbtnFontUnderline)
            {
                _designer.UndoStack.SaveState();
                foreach (Field field in fields)
                    field.Font.Underline = !field.Font.Underline;// rbtnFontUnderline.Pressed;
            }
            else if (item == rbtnTextColor)
            {
                _designer.UndoStack.SaveState();
                foreach (Field field in fields)
                    field.ForeColor = rbtnTextColor.Color;
            }
            else if (item == rbtnFillColor)
            {
                _designer.UndoStack.SaveState();
                foreach (Field field in fields)
                    field.BackColor = rbtnFillColor.Color;
            }

            SetDirty();
        }

        private void DoSetBackColor()
        {
            Field[] fields = _designer.SelectedFields;
            if (fields != null && fields.Length > 0)
                DoFontStyle(rbtnFillColor);
            else
            {
                Section section = _designer.SelectedSection;
                if (section != null)
                {
                    _designer.UndoStack.SaveState();
                    section.BackColor = rbtnFillColor.Color;
                    SetDirty();
                }
            }
        }

        private void DoTextAlign(RibbonItem item)
        {
            Field[] fields = _designer.SelectedFields;
            if (fields == null || fields.Length <= 0)
                return;

            _designer.UndoStack.SaveState();
            foreach (Field field in fields)
            {
                TextHorzAlign ha;
                TextVertAlign va;
                GetAlign(field.Align, out ha, out va);

                if (item == rbtnTextAlignLeft)
                    field.Align = s_TextAlignMatrix[(int)va][(int)TextHorzAlign.Left];
                else if (item == rbtnTextAlignCenter)
                    field.Align = s_TextAlignMatrix[(int)va][(int)TextHorzAlign.Center];
                else if (item == rbtnTextAlignRight)
                    field.Align = s_TextAlignMatrix[(int)va][(int)TextHorzAlign.Right];
                else if (item == rbtnTextAlignJustify)
                    field.Align = s_TextAlignMatrix[(int)va][(int)TextHorzAlign.Justify];
            }

            SetDirty();
        }

        #region Borders
        private void EnsureVisibleBorder(Field field, bool noWidth, bool noStyle)
        {
            if (!noWidth && field.LineWidth == 0)
                field.LineWidth = 10;
            if (!noStyle && field.BorderStyle == C1.C1Report.BorderStyleEnum.Transparent)
                field.BorderStyle = C1.C1Report.BorderStyleEnum.Solid;
        }

        private void DoBorderColor()
        {
            Field[] fields = _designer.SelectedFields;
            if (fields == null || fields.Length <= 0)
                return;

            _designer.UndoStack.SaveState();
            foreach (Field field in fields)
            {
                field.BorderColor = rclrBorderColor.Color;
                EnsureVisibleBorder(field, false, false);
            }
            SetDirty();
        }

        private void DoBorderWidth()
        {
            Field[] fields = _designer.SelectedFields;
            if (fields == null || fields.Length <= 0)
                return;

            double value;
            if (!double.TryParse(rcmbBorderWidth.Text, out value) || value < 0)
                value = 0;

            _designer.UndoStack.SaveState();
            foreach (Field field in fields)
            {
                field.LineWidth = value;
                if (value > 0)
                    EnsureVisibleBorder(field, true, false);
            }
            SetDirty();
        }

        private void DoBorderStyle(RibbonGalleryItem rgi)
        {
            if (rgi == null)
                return;

            Field[] fields = _designer.SelectedFields;
            if (fields == null || fields.Length <= 0)
                return;

            Action a;
            if (!TryGetAction(rgi.Tag as string, out a))
                return;

            C1.C1Report.BorderStyleEnum borderStyle;
            try
            {
                borderStyle = (C1.C1Report.BorderStyleEnum)a.Value;
            }
            catch
            {
                return;
            }

            _designer.UndoStack.SaveState();
            foreach (Field field in fields)
            {
                field.BorderStyle = borderStyle;
                if (borderStyle != C1.C1Report.BorderStyleEnum.Transparent)
                    EnsureVisibleBorder(field, false, true);
            }
            SetDirty();
        }


        private struct BorderWidthItem
        {
            public double Width;
            public string Text;
        };
        private static List<BorderWidthItem> s_borderWidths = new List<BorderWidthItem>()
        {
            new BorderWidthItem() { Width = 0, Text = "Zero"},
            new BorderWidthItem() { Width = 1, Text = "Hairline"},
            // the rest is taken from MS Word's border width dropdown:
            new BorderWidthItem() { Width = 5, Text = "� pt"},
            new BorderWidthItem() { Width = 10, Text = "� pt"},
            new BorderWidthItem() { Width = 15, Text = "� pt"},
            new BorderWidthItem() { Width = 20, Text = "1 pt"},
            new BorderWidthItem() { Width = 30, Text = "1� pt"},
            new BorderWidthItem() { Width = 45, Text = "2� pt"},
            new BorderWidthItem() { Width = 60, Text = "3 pt"},
            new BorderWidthItem() { Width = 90, Text = "4� pt"},
            new BorderWidthItem() { Width = 120, Text = "6 pt"},
        };

        private void BorderWidthSetup()
        {
            const string Sample = "Hairline"; // should be not smaller than the biggest text
            const int PadX = 4;
            const int PadY = 3;
            const int Gap = 8; // gap between text and line
            const int LineLength = 64;

            RibbonItemCollection items = rcmbBorderWidth.Items;
            items.BeginUpdate();
            foreach (BorderWidthItem bwi in s_borderWidths)
            {
                RibbonButton item = new RibbonButton(bwi.Width.ToString());
                item.OwnerDraw = true;
                item.MeasureItem += (ss, ee) =>
                {
                    SizeF s = ee.Graphics.MeasureString(Sample, this.Font, PointF.Empty, StringFormat.GenericDefault);
                    ee.ItemHeight = (int)Math.Round(s.Height + PadY * 2);
                    ee.ItemWidth = (int)Math.Round(s.Width + LineLength + PadX * 2 + Gap);
                };
                item.DrawItem += (ss, ee) =>
                    {
                        ee.DrawBackground();
                        using (Pen p = new Pen(ee.ForeColor, ((float)bwi.Width / 1440f) * ee.Graphics.DpiY))
                        using (SolidBrush b = new SolidBrush(ee.ForeColor))
                        using (var sf = new StringFormat(StringFormat.GenericDefault))
                        {
                            var offset = ee.Graphics.MeasureString(Sample, this.Font, PointF.Empty, StringFormat.GenericDefault).Width + PadX + Gap / 2;

                            sf.Alignment = StringAlignment.Far;
                            sf.LineAlignment = StringAlignment.Center;
                            ee.Graphics.DrawString(bwi.Text, this.Font, b, ee.Bounds.Left + offset - Gap / 2, ee.Bounds.Top + ee.Bounds.Height / 2, sf);
                            if (bwi.Width > 0)
                                ee.Graphics.DrawLine(p, ee.Bounds.Left + offset + Gap / 2, ee.Bounds.Top + ee.Bounds.Height / 2, ee.Bounds.Right - PadX, ee.Bounds.Top + ee.Bounds.Height / 2);
                        }
                    };
                items.Add(item);
            }
            items.EndUpdate();
        }
        #endregion

        private void DoCreateField(RibbonItem item)
        {
            if (item == rbtnFieldArrow)
            {
                _designer.CreateFieldInfo = null;
                _createInfo = null;
            }
            else if (item == rbtnFieldDataField || item == rbtnFieldRtf || item == rbtnFieldCheckBox || item == rbtnFieldBarCode ||
                item == rbtnFieldLine || item == rbtnFieldRectangle || item == rbtnFieldPageBreak)
            {
                _designer.CreateFieldInfo = item;
                _createInfo = null;
            }
            else if (item == rbtnFieldCalculated)
            {
#if !old_script_editor // todo: remove #else when dust settles
                string expression;
                if (EditScript(_designer.Report, string.Empty, true, out expression))
                {
                    _createInfo = expression;
                    if (_createInfo != null && _createInfo.Length > 0)
                        _designer.CreateFieldInfo = item;
                }
                else
                {
                    _designer.CreateFieldInfo = null;
                    item = rbtnFieldArrow; // to reset Pressed
                }
#else
                using (ScriptEditorForm dlg = new ScriptEditorForm(_designer.Report, true))
                {
                    if (dlg.ShowDialog() == DialogResult.OK)
                    {
                        _createInfo = dlg.Expression;
                        if (_createInfo != null && _createInfo.Length > 0)
                            _designer.CreateFieldInfo = item;
                    }
                    else
                    {
                        _designer.CreateFieldInfo = null;
                        item = rbtnFieldArrow; // to reset Pressed
                    }
                }
#endif
            }
            else if (item == rbtnFieldPicture)
            {
                using (OpenFileDialog dlg = new OpenFileDialog())
                {
                    dlg.DereferenceLinks = true;
                    dlg.Filter = Strings.MainForm.OpenImageFilter;
                    dlg.FileName = "*.bmp;*.dib;*.ico;*.cur;*.gif;*.jpg;*.wmf;*.emf;*.png";
                    dlg.FilterIndex = 0;
                    if (dlg.ShowDialog() == DialogResult.OK)
                    {
                        _createInfo = dlg.FileName;
                        _designer.CreateFieldInfo = rbtnFieldPicture;
                    }
                    else
                    {
                        _designer.CreateFieldInfo = null;
                        item = rbtnFieldArrow; // to reset Pressed
                    }
                }
            }
            else if (item.Parent is RibbonDropDownBase)
            {
                _designer.CreateFieldInfo = item.Parent;
                _createInfo = ((RibbonButton)item).Text;
            }
            else if (item.Tag is Field)
                _designer.CreateFieldInfo = item;

            // We keep the button that caused the action pressed for the duration of adding the field
            // (i.e. while mouse cursor is a cross), while un-pressing all other items:
            System.Collections.ArrayList fieldButtons = new ArrayList();
            fieldButtons.AddRange(rgFields.Items);
            fieldButtons.AddRange(rgCustomFields.Items);
            foreach (object ri in fieldButtons)
            {
                bool pressed = item != null && (ri == (object)item || ri == item.Parent);
                if (ri is RibbonSplitButton)
                    ((RibbonSplitButton)ri).Pressed = pressed;
                else if (ri is RibbonToggleButton)
                    ((RibbonToggleButton)ri).Pressed = pressed;
            }
        }

        private void DoPropertiesAlphabetical()
        {
            CategorizeProperties = false;
            UpdateCommands(true);
        }

        private void DoPropertiesCategorized()
        {
            CategorizeProperties = true;
            UpdateCommands(true);
        }

        private void DoPropertiesFilter()
        {
            UseFieldWrappers = !UseFieldWrappers;
            _designer_SelectionChanged(this, EventArgs.Empty);
            UpdateCommands(true);
        }

        private void DoShowPropertyGrid()
        {
            dtpProperties.Show();
            ActiveControl = _propGrid;
            UpdateUITools(true);
        }

        private void DoShowFieldList()
        {
            dtpFields.Show();
            ActiveControl = lbFields;
            UpdateUITools(true);
        }

        private void DoStyles()
        {
            using (ReportStyleForm f = new ReportStyleForm(this))
            {
                f.Designer = _designer;
                f.ShowDialog();
            }
        }

        private void DoApplyStyleToSelection()
        {
            Field[] fields = _designer.SelectedFields;
            if (fields == null || fields.Length <= 0)
                return;

            _designer.UndoStack.SaveState();
            Field refFld = fields[fields.Length - 1];
            foreach (Field field in fields)
            {
                if (field != refFld)
                {
                    field.Font = refFld.Font;
                    field.ForeColor = refFld.ForeColor;
                    field.BackColor = refFld.BackColor;
                    //f.BackStyle   = refFld.BackStyle;
                    field.Align = refFld.Align;
                    field.PictureAlign = refFld.PictureAlign;
                    field.BorderColor = refFld.BorderColor;
                    field.BorderStyle = refFld.BorderStyle;
                    field.LineWidth = refFld.LineWidth;
                    field.LineSpacing = refFld.LineSpacing;
                    field.MarginLeft = refFld.MarginLeft;
                    field.MarginTop = refFld.MarginTop;
                    field.MarginRight = refFld.MarginRight;
                    field.MarginBottom = refFld.MarginBottom;
                }
            }

            SetDirty();
        }

        private void DoSnapToGrid()
        {
            _designer.Grid.Snap = rbtnSnapToGrid.Pressed;
        }

        private void DoLockFields()
        {
            _designer.Locked = !_designer.Locked;
            UpdateUIGrid(true);
        }

        private void DoToggleLockOfSelectedFields()
        {
            _designer.ToggleLockOfSelectedFields();
        }

        private void DoShowHideGrid()
        {
            //_designer.Grid.Visible = rbtnShowGrid.Pressed;
            _designer.Grid.Visible = !_designer.Grid.Visible;
            UpdateUIGrid(true);
        }

        private void DoGridProperties()
        {
            _appConfig.ShowDialog("DesignPane");
            UpdateUI();
        }

        private void DoAlign(RibbonItem item)
        {
            if (item == rbtnAlignToGrid)
                _designer.AlignSelectedFields(AlignOperationEnum.AlignToGrid);
            else if (item == rbtnFormatAsTableRow)
                _designer.AlignSelectedFields(AlignOperationEnum.FormatAsTableRow);
            else if (item == rbtnAlignLeft)
                _designer.AlignSelectedFields(AlignOperationEnum.AlignLeft);
            else if (item == rbtnAlignCenter)
                _designer.AlignSelectedFields(AlignOperationEnum.AlignCenter);
            else if (item == rbtnAlignMiddle)
                _designer.AlignSelectedFields(AlignOperationEnum.AlignMiddle);
            else if (item == rbtnAlignRight)
                _designer.AlignSelectedFields(AlignOperationEnum.AlignRight);
            else if (item == rbtnAlignTop)
                _designer.AlignSelectedFields(AlignOperationEnum.AlignTop);
            else if (item == rbtnAlignBottom)
                _designer.AlignSelectedFields(AlignOperationEnum.AlignBottom);
            else if (item == rbtnSendToBack)
                _designer.AlignSelectedFields(AlignOperationEnum.SendToBack);
            else if (item == rbtnBringToFront)
                _designer.AlignSelectedFields(AlignOperationEnum.BringToFront);
            else if (item == rbtnEqualHorizontalSpacing)
                _designer.AlignSelectedFields(AlignOperationEnum.EqualHorizontalSpacing);
            else if (item == rbtnIncreaseHorizontalSpacing)
                _designer.AlignSelectedFields(AlignOperationEnum.IncreaseHorizontalSpacing);
            else if (item == rbtnDecreaseHorizontalSpacing)
                _designer.AlignSelectedFields(AlignOperationEnum.DecreaseHorizontalSpacing);
            else if (item == rbtnEqualVerticalSpacing)
                _designer.AlignSelectedFields(AlignOperationEnum.EqualVerticalSpacing);
            else if (item == rbtnIncreaseVerticalSpacing)
                _designer.AlignSelectedFields(AlignOperationEnum.IncreaseVerticalSpacing);
            else if (item == rbtnDecreaseVerticalSpacing)
                _designer.AlignSelectedFields(AlignOperationEnum.DecreaseVerticalSpacing);
            else if (item == rbtnSizeToGrid)
                _designer.AlignSelectedFields(AlignOperationEnum.SizeToGrid);
            else if (item == rbtnWidthToNarrowest)
                _designer.AlignSelectedFields(AlignOperationEnum.WidthToNarrowest);
            else if (item == rbtnWidthToWidest)
                _designer.AlignSelectedFields(AlignOperationEnum.WidthToWidest);
            else if (item == rbtnHeightToShortest)
                _designer.AlignSelectedFields(AlignOperationEnum.HeightToShortest);
            else if (item == rbtnHeightToTallest)
                _designer.AlignSelectedFields(AlignOperationEnum.HeightToTallest);
        }

        private void DoSetLayoutOrientation(bool landscape)
        {
            _designer.Report.Layout.Orientation = landscape ? OrientationEnum.Landscape : OrientationEnum.Portrait;

            SetDirty();

            // update preview
            if (!ReportDesignMode)
                RenderPreview(false);
        }

        private void DoPageSetup()
        {
            using (PageSetupDialog dlg = new PageSetupDialog())
            {
                dlg.PageSettings = _designer.Report.Document.DefaultPageSettings;

                // workaround .NET bug: PageSetupDialog doesn't handle metric units
                if (RegionInfo.CurrentRegion.IsMetric)
                {
                    Margins m = dlg.PageSettings.Margins;
                    m.Left = (int)(m.Left * 2.54);
                    m.Top = (int)(m.Top * 2.54);
                    m.Right = (int)(m.Right * 2.54);
                    m.Bottom = (int)(m.Bottom * 2.54);
                }

                DialogResult dr = dlg.ShowDialog();

                // update preview
                if (dr == DialogResult.OK)
                {
                    // update report layout from DefaultPageSettings
                    Layout layout = _designer.Report.Layout;
                    layout.UpdateFromPrintDoc();
                    layout.PaperSize = dlg.PageSettings.PaperSize.Kind;
                    layout.Orientation = (dlg.PageSettings.Landscape)
                        ? OrientationEnum.Landscape
                        : OrientationEnum.Portrait;

                    // we're dirty
                    SetDirty();

                    // update preview
                    if (!ReportDesignMode)
                        RenderPreview(false);
                }
            }
        }

        private void DoZoom(RibbonItem item)
        {
            if (_state.DesignMode)
                DoZoomDesigner(item);
            else
                DoZoomPreview(item);
        }

        private void DoZoomDesigner(RibbonItem item)
        {
            if (!_state.HasCurrReport)
                return;

            if (item.Parent as RibbonMenu == rbtnZoom)
                this.Designer.ZoomFactor = int.Parse(((string)item.Tag).Substring(4)) / 100.0f;
        }

        private void DoZoomPreview(RibbonItem item)
        {
            if (_preview.Busy)
                return;

            if (item == rbtnZoomFitToWindow)
                _preview.ZoomMode = ZoomModeEnum.WholePage;
            else if (item.Parent as RibbonMenu == rbtnZoom)
                _preview.ZoomFactor = int.Parse(((string)item.Tag).Substring(4)) / 100.0;
            else if (item == rbtnZoomOnePage)
                using (new C1PreviewPane.LayoutSection(_preview, HistorySavedActionsEnum.Layout))
                {
                    _preview.Continuous = true;
                    _preview.PageLayout = C1.Win.C1Preview.PageLayoutEnum.Normal;
                    _preview.Cols = 1;
                    _preview.Rows = 1;
                    _preview.ZoomMode = ZoomModeEnum.WholePage;
                }
            else if (item == rbtnZoomTwoPages)
                using (new C1PreviewPane.LayoutSection(_preview, HistorySavedActionsEnum.Layout))
                {
                    _preview.Continuous = true;
                    _preview.PageLayout = C1.Win.C1Preview.PageLayoutEnum.Custom;
                    _preview.Cols = 2;
                    _preview.Rows = 1;
                }
            else if (item == rbtnZoomFourPages)
                using (new C1PreviewPane.LayoutSection(_preview, HistorySavedActionsEnum.Layout))
                {
                    _preview.Continuous = false;
                    _preview.PageLayout = C1.Win.C1Preview.PageLayoutEnum.Custom;
                    _preview.Cols = 2;
                    _preview.Rows = 2;
                }
            else if (item == rbtnZoomEightPages)
                using (new C1PreviewPane.LayoutSection(_preview, HistorySavedActionsEnum.Layout))
                {
                    _preview.Continuous = false;
                    _preview.PageLayout = C1.Win.C1Preview.PageLayoutEnum.Custom;
                    _preview.Cols = 4;
                    _preview.Rows = 2;
                }
            else if (item == rbtnZoomTwelvePages)
                using (new C1PreviewPane.LayoutSection(_preview, HistorySavedActionsEnum.Layout))
                {
                    _preview.Continuous = false;
                    _preview.PageLayout = C1.Win.C1Preview.PageLayoutEnum.Custom;
                    _preview.Cols = 4;
                    _preview.Rows = 3;
                }
        }

        private void DoNavigation(RibbonItem item)
        {
            if (item == rbtnPreviousView)
                _preview.HistoryBack();
            else if (item == rbtnNextView)
                _preview.HistoryForward();
            else if (item == rbtnFirstPage)
                _preview.StartPageIdx = 0;
            else if (item == rbtnPreviousPage)
                _preview.StartPageIdx--;
            else if (item == rbtnNextPage)
                _preview.StartPageIdx++;
            else if (item == rbtnLastPage)
                _preview.StartPageIdx = _preview.Pages.Count - 1;
        }

        private void DoSetPageNo()
        {
            int v;
            if (int.TryParse(rebPageNo.Text, out v))
                _preview.StartPageIdx = v - 1;
        }

        private void DoPreviewTool(RibbonItem item)
        {
            if (item == rbtnHandTool)
                _preview.MouseMode = MouseModeEnum.Hand;
            else if (item == rbtnTextSelectTool)
                _preview.MouseMode = MouseModeEnum.Select;
            else if (item == rbtnPreviewFind)
            {
                dtpPreviewFind.Show();
                ActiveControl = ptspMain.Controls[0].Controls[2];
                UpdateUIPreviewTools(true);
            }
        }

        private void DoPreviousViewDropDown()
        {
            rbtnPreviousView.Items.Clear();
            for (int i = _preview.CurrentHistoryEntryIndex - 1, j = 0;
                        i >= 0 && j < cMaxHistoryMenuSize;
                        i--, j++)
            {
                ViewHistoryItem vhi = _preview.ViewHistory[i];
                RibbonButton btn = new RibbonButton(vhi.Caption);
                btn.Tag = vhi;
                rbtnPreviousView.Items.Add(btn);
            }
        }

        private void DoNextViewDropDown()
        {
            rbtnNextView.Items.Clear();
            for (int i = _preview.CurrentHistoryEntryIndex + 1, j = 0;
                        i < _preview.ViewHistory.Count && j < cMaxHistoryMenuSize;
                        i++, j++)
            {
                ViewHistoryItem vhi = _preview.ViewHistory[i];
                RibbonButton btn = new RibbonButton(vhi.Caption);
                btn.Tag = vhi;
                rbtnNextView.Items.Add(btn);
            }
        }

        private void DoHistoryItem(RibbonItem item)
        {
            ViewHistoryItem vhi = item.Tag as ViewHistoryItem;
            if (vhi == null)
                return;
            _preview.CurrentHistoryEntry = vhi;
        }

        private void DoPageLayout(RibbonItem item)
        {
            if (_preview.Busy)
                return;

            if (item == rbtnViewSinglePage)
                using (new C1PreviewPane.LayoutSection(_preview, HistorySavedActionsEnum.Layout))
                {
                    _preview.Continuous = false;
                    _preview.PageLayout = C1.Win.C1Preview.PageLayoutEnum.Normal;
                }
            else if (item == rbtnViewContinuous)
                using (new C1PreviewPane.LayoutSection(_preview, HistorySavedActionsEnum.Layout))
                {
                    _preview.Continuous = true;
                    _preview.PageLayout = C1.Win.C1Preview.PageLayoutEnum.Normal;
                }
            else if (item == rbtnViewPagesFacing)
                using (new C1PreviewPane.LayoutSection(_preview, HistorySavedActionsEnum.Layout))
                {
                    _preview.Continuous = false;
                    _preview.PageLayout = C1.Win.C1Preview.PageLayoutEnum.Facing;
                }
            else if (item == rbtnViewPagesFacingContinuous)
                using (new C1PreviewPane.LayoutSection(_preview, HistorySavedActionsEnum.Layout))
                {
                    _preview.Continuous = true;
                    _preview.PageLayout = C1.Win.C1Preview.PageLayoutEnum.Facing;
                }
        }

        /// <summary>
        /// Cancels current report generation, but does not exit preview.
        /// </summary>
        private void DoPreviewStop()
        {
            //ReportDesignMode = true;
            _reportRender.Cancel = true;
        }

        private void DoClosePrintPreview()
        {
            ReportDesignMode = true;
        }

        private void DoPreviewExport(RibbonItem item)
        {
            string tag = item.Tag as string;
            if (tag == null)
                return;

            string[] s = tag.Split(',');
            if (s.Length != 3)
                return;

            int filterIndex;
            if (int.TryParse(s[2], out filterIndex))
                ExportReport(filterIndex);
        }

        private void DoOptions()
        {
            _appConfig.ShowDialog();
            UpdateUI();
        }

        private void DoLinkSubreport()
        {
            using (LinkSubreportForm dlg = new LinkSubreportForm(_designer))
            {
                if (dlg.Init())
                {
                    DialogResult dr = dlg.ShowDialog();
                    if (dr == DialogResult.OK)
                        SetDirty();
                }
            }
        }

        private void DoEditSubreport()
        {
            OpenSubreport();
        }

        private void DoShowSubreport()
        {
            _designer.ShowSubreportContent = !_designer.ShowSubreportContent;
        }

        private void DoSelectAll()
        {
            FieldCollection fields = (_designer.SelectedSection == null)
                ? _designer.Report.Fields
                : _designer.SelectedSection.Fields;
            ArrayList al = new ArrayList();
            foreach (Field f in fields)
                al.Add(f);
            _designer.SelectedFields = (Field[])al.ToArray(typeof(Field));
        }

        private void DoAbout()
        {
            using (AppAboutForm dlg = NewAppAboutForm())
            {
                dlg.ShowDialog();
            }
        }

        private void RibbonChangeCommitted(RibbonItem item)
        {
            if (item == rcbFontName)
                DoSetFontName();
            else if (item == rcbFontSize)
                DoSetFontSize();
            else if (item == rebPageNo)
                DoSetPageNo();
        }

        private void RibbonChangeCanceled(RibbonItem item)
        {
            if (item == rcbFontName || item == rcbFontSize)
                UpdateUIFont(true);
        }

        private void RibbonColorChanged(RibbonColorPicker cb)
        {
            if (cb == rbtnTextColor)
                DoFontStyle(cb);
            else if (cb == rbtnFillColor)
                DoSetBackColor();
        }

        private void RibbonClick(RibbonItem item)
        {
            if (item == rbtnNew)
                DoNew();
            else if (item == rbtnClose)
                DoClose();
            else if (item == rbtnOpen)
                DoOpen();
            else if (item == rbtnSave)
                DoSave();
            else if (item == rbtnSaveAs)
                DoSaveAs();
            else if (item == rbtnImport)
                DoImport();
            else if (item == rbtnExport)
                DoExport();
            else if (item == rbtnPreviewPrint)
                DoPreviewPrint();
            else if (item == rbtnCut)
                DoCutFields();
            else if (item == rbtnCopy)
                DoCopyFields();
            else if (item == rbtnPaste)
                DoPasteFields();
            else if (item == rbtnDelete)
                DoDeleteFields();
            else if (item == rbtnUndo)
                DoUndo();
            else if (item == rbtnRedo)
                DoRedo();
            else if (item == rbtnExit)
                DoExit();
            else if (item == rbtnSaveAndExit)
                DoSaveAndExit();
            else if (item == rbtnCancelAndExit)
                DoCancelAndExit();
            else if (item == rbtnModePreview)
                DoPreview();
            else if (item == rbtnModeDesign)
                DoClosePrintPreview();
            else if (item == rbtnPreviewStop)
                DoPreviewStop();
            else if (item == rbtnPreviewRefresh)
                RenderPreview(true);
            else if (item == rbtnGroupSort)
                DoGroupSort();
            else if (item == rbtnDatabase)
                DoDatabase();
            else if (item == rbtnReportInfo)
                DoReportInfo();
            else if (item == rbtnScriptEditor)
                DoScriptEditor();
            else if (item.Group == rgFields || item.Group == rgCustomFields)
                DoCreateField(item);
            else if (item == rbtnFontBold || item == rbtnFontItalic || item == rbtnFontUnderline)
                DoFontStyle(item);
            else if (item == rbtnFontSizeDown || item == rbtnFontSizeUp)
                DoFontStyle(item);
            else if (item == rbtnTextAlignLeft || item == rbtnTextAlignCenter || item == rbtnTextAlignRight || item == rbtnTextAlignJustify)
                DoTextAlign(item);
            else if (item == rbtnShowPropertyGrid)
                DoShowPropertyGrid();
            else if (item == rbtnShowFieldList)
                DoShowFieldList();
            else if (item == rbtnStyles)
                DoStyles();
            else if (item == rbtnApplyStyleToSelection)
                DoApplyStyleToSelection();
            else if (item == rbtnShowGrid)
                DoShowHideGrid();
            else if (item == rbtnSnapToGrid)
                DoSnapToGrid();
            else if (item == rbtnLockFields)
                DoLockFields();
            else if (item == rbtnGridProperties)
                DoGridProperties();
            else if (item == rbtnFormatAsTableRow ||
                item == rbtnAlignToGrid ||
                item == rbtnFormatAsTableRow ||
                item == rbtnAlignLeft ||
                item == rbtnAlignCenter ||
                item == rbtnAlignMiddle ||
                item == rbtnAlignRight ||
                item == rbtnAlignTop ||
                item == rbtnAlignBottom ||
                item == rbtnSendToBack ||
                item == rbtnBringToFront ||
                item == rbtnEqualHorizontalSpacing ||
                item == rbtnIncreaseHorizontalSpacing ||
                item == rbtnDecreaseHorizontalSpacing ||
                item == rbtnEqualVerticalSpacing ||
                item == rbtnIncreaseVerticalSpacing ||
                item == rbtnDecreaseVerticalSpacing ||
                item == rbtnSizeToGrid ||
                item == rbtnWidthToNarrowest ||
                item == rbtnWidthToWidest ||
                item == rbtnHeightToShortest ||
                item == rbtnHeightToTallest)
                DoAlign(item);
            else if (item == rbtnPageLandscape1 || item == rbtnPageLandscape2)
                DoSetLayoutOrientation(true);
            else if (item == rbtnPagePortrait1 || item == rbtnPagePortrait2)
                DoSetLayoutOrientation(false);
            else if (item == rbtnPageSetup1 || item == rbtnPageSetup2)
                DoPageSetup();
            else if (item == rbtnPreviewPrint)
                DoPreviewPrint();
            else if (item.Parent as RibbonMenu == rbtnZoom ||
                item.Parent as RibbonMenu == rbtnZoomMorePages ||
                item == rbtnZoomTwoPages ||
                item == rbtnZoomOnePage)
                DoZoom(item);
            else if (item.Parent as RibbonItem == rbtnPreviousView ||
                item.Parent as RibbonItem == rbtnNextView)
                DoHistoryItem(item as RibbonItem);
            else if (item == rbtnPreviousView ||
                item == rbtnNextView ||
                item == rbtnFirstPage ||
                item == rbtnPreviousPage ||
                item == rbtnNextPage ||
                item == rbtnLastPage)
                DoNavigation(item);
            else if (item == rbtnHandTool ||
                item == rbtnTextSelectTool ||
                item == rbtnPreviewFind)
                DoPreviewTool(item);
            else if (item.Group == rgExport)
                DoPreviewExport(item);
            else if (item == rbtnOptions)
                DoOptions();
            else if (item == rbtnAbout2)
                DoAbout();
            else if (item == rbtnAbout || item == rbtnHelpContents)
                DoHelpContents();
            else if (item == rclrBorderColor || (item.Parent as RibbonColorPicker) == rclrBorderColor)
                DoBorderColor();
            else if ((item.Parent as RibbonGallery) == rgalBorderStyle)
                DoBorderStyle(item as RibbonGalleryItem);
            else if (item == rcmbBorderWidth || (item.Parent as RibbonComboBox) == rcmbBorderWidth)
                DoBorderWidth();
            // else?
        }

        private void DoErrorToClipboard()
        {
            try
            {
                Clipboard.SetText(rbtnRenderError.ToolTip);
            }
            catch (Exception ex)
            {
                MessageForm.Error(string.Format(Strings.MainForm.ClipboardErrorFmt, ex.Message));
            }
        }

        private void DoHelpContents()
        {
            OpenURL(Strings.MainForm.HelpUrl);
        }


        private void RibbonDropDown(RibbonItem item)
        {
            if (item == rbtnPreviousView)
                DoPreviousViewDropDown();
            else if (item == rbtnNextView)
                DoNextViewDropDown();
        }
        #endregion

        private void rbnMain_RibbonEvent(object sender, RibbonEventArgs e)
        {
            if (UIUpdating)
                return;

            //
            switch (e.EventType)
            {
                case RibbonEventType.Click:
                    RibbonClick(e.Item as RibbonItem);
                    break;
                case RibbonEventType.SelectedColorChanged:
                    RibbonColorChanged(e.Item as RibbonColorPicker);
                    break;
                case RibbonEventType.ChangeCommitted:
                    RibbonChangeCommitted(e.Item as RibbonItem);
                    break;
                case RibbonEventType.ChangeCanceled:
                    RibbonChangeCanceled(e.Item as RibbonItem);
                    break;
                case RibbonEventType.DropDown:
                    RibbonDropDown(e.Item as RibbonItem);
                    break;
            }
        }

        private void chMain_CommandClick(object sender, CommandClickEventArgs e)
        {
            if (e.Command == cNewReport)
                DoNewReport();
            else if (e.Command == cPasteReport)
                DoPasteReport();
            else if (e.Command == cCutReport)
                DoCutReport();
            else if (e.Command == cCopyReport)
                DoCopyReport();
            else if (e.Command == cDeleteReport)
                DoDeleteReport();
            else if (e.Command == cMoveReportUp)
                DoMoveReportUp();
            else if (e.Command == cMoveReportDown)
                DoMoveReportDown();
            else if (e.Command == cPropertiesAlphabetical)
                DoPropertiesAlphabetical();
            else if (e.Command == cPropertiesCategorized)
                DoPropertiesCategorized();
            else if (e.Command == cPropertiesFilter)
                DoPropertiesFilter();
            else if (e.Command == cmLinkSubreport)
                DoLinkSubreport();
            else if (e.Command == cmEditSubreport)
                DoEditSubreport();
            else if (e.Command == cmShowSubreport)
                DoShowSubreport();
            else if (e.Command == cmSelectAll)
                DoSelectAll();
            else if (e.Command == cmCutField)
                DoCutFields();
            else if (e.Command == cmCopyField)
                DoCopyFields();
            else if (e.Command == cmPasteField)
                DoPasteFields();
            else if (e.Command == cmDeleteField)
                DoDeleteFields();
            else if (e.Command == cmBringToFront)
                _designer.AlignSelectedFields(AlignOperationEnum.BringToFront);
            else if (e.Command == cmSendToBack)
                _designer.AlignSelectedFields(AlignOperationEnum.SendToBack);
            else if (e.Command == cLockFields)
                DoLockFields();
            else if (e.Command == cToggleLockOfSelectedFields)
                DoToggleLockOfSelectedFields();
            else if (e.Command == cScriptEditor)
                DoScriptEditor();
        }

        private void _preview_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            switch (e.PropertyName)
            {
                case "ZoomFactor":
                case "ZoomMode":
                case "StartPageIdx":
                case "PreviewScrollPosition":
                case "PageLayout":
                case "Cols":
                case "Rows":
                case "Continuous":
                case "CurrentHistoryEntry":
                case "MouseMode":
                case "ShowRulers":
                case "HideMargins":
                case "HideMarginsState":
                    _timerUpdateNeeded = true;
                    break;
                default:
                    break;
            }
        }

        private void rbtnViewSinglePage_Click(object sender, EventArgs e)
        {
            DoPageLayout(sender as RibbonItem);
        }

        private int ZoomFactorToZoomSlider(int zoomFactor)
        {
            return _zoomSliderScale == null ? rtbZoom.Value : _zoomSliderScale.SliderValue(zoomFactor / 100f);
        }

        private double ZoomSliderToZoomFactor(int zoomSlider)
        {
            return _zoomSliderScale == null ? 1 : _zoomSliderScale.ZoomFactor(zoomSlider);
        }

        private void rtbZoom_Scroll(object sender, EventArgs e)
        {
            if (UIUpdating)
                return;
            double zoom = ZoomSliderToZoomFactor(rtbZoom.Value);
            if (ReportDesignMode)
                this.Designer.ZoomFactor = (float)zoom;
            else
                _preview.ZoomFactor = zoom;
        }

        private void cmDesigner_Popup(object sender, EventArgs e)
        {
            // make sure we have the focus
            _designer.Focus();

            // get field under the mouse
            Point pt = _designer.PointToClient(Control.MousePosition);
            HitTestInfo hti = _designer.HitTest(pt.X, pt.Y);
            Field f = hti.Field;

            // no field there? no selection
            if (f == null)
            {
                _designer.SelectedFields = null;
            }

            // field not in selection? then select it
            if (f != null)
            {
                bool selected = false;
                foreach (Field sf in _designer.SelectedFields)
                {
                    if (sf != f) continue;
                    selected = true;
                    break;
                }
                if (!selected)
                    _designer.SelectedFields = new Field[] { f };
            }

            //
            UpdateCommands(true);
            // C1Command does not update Text of C1CommandLink when
            // C1Command.Text is changed so make it here
            c1CommandLink29.Text = _actions[ActionTypeEnum.ToggleLockOfSelectedFields].Text;
        }

        private void lbFields_MouseDown(object sender, MouseEventArgs e)
        {
            _fieldsPointDown = new Point(e.X, e.Y);
            _fieldsIndexDown = ((ListBox)sender).SelectedIndex;
        }

        private void lbFields_MouseMove(object sender, MouseEventArgs e)
        {
            if ((Control.MouseButtons & MouseButtons.Left) != 0)
            {
                int index = lbFields.SelectedIndex;
                if (index > -1 && index == _fieldsIndexDown)
                {
                    int offset = Math.Max(Math.Abs(e.X - _fieldsPointDown.X), Math.Abs(e.Y - _fieldsPointDown.Y));
                    if (offset > DRAG_THRESHOLD)
                        lbFields.DoDragDrop(lbFields, DragDropEffects.Move);
                }
            }
        }

        private void _designer_DragOver(object sender, DragEventArgs e)
        {
            if (lbFields.SelectedIndex < 0)
                return;

            Point pt = _designer.PointToClient(new Point(e.X, e.Y));
            HitTestInfo hti = _designer.HitTest(pt.X, pt.Y);
            if (hti.Section == null)
                return;

            e.Effect = DragDropEffects.Move;
        }

        private void _designer_DragDrop(object sender, DragEventArgs e)
        {
            if (lbFields.SelectedIndex < 0)
                return;

            ReportItem ri = _reportList.SelectedItem;
            if (ri == null || ri._report == null)
                return;

            Point pt = _designer.PointToClient(new Point(e.X, e.Y));
            HitTestInfo hti = _designer.HitTest(pt.X, pt.Y);
            if (hti.Section == null)
                return;

            var fi = lbFields.SelectedItem as FieldListItem;
            if (fi == null)
                return;

            int w = (int)Math.Round(cDropFieldWidth);
            int h = (int)Math.Round(cDropFieldHeight);
            var cfea = new CreateFieldEventArgs(
                hti.Section,
                new Rectangle(hti.X, hti.Y, w, h),
                new Rectangle((int)Math.Round(hti.SectionX), (int)Math.Round(hti.SectionY), w, h),
                fi.IsPicture ? (object)rbtnFieldPicture : (object)rbtnFieldDataField);
            _createInfo = fi.Name;
            _designer_CreateField(_designer, cfea);
        }

        private void rbtnRenderError_Click(object sender, EventArgs e)
        {
            DoErrorToClipboard();
        }

        private void rcmbBorderWidth_ChangeCommitted(object sender, EventArgs e)
        {
            DoBorderWidth();
        }

        #region Splash
        private static AppAboutForm s_appAboutForm = null;

        private static AppAboutForm NewAppAboutForm()
        {
            return new AppAboutForm(Strings.MainForm.NameInAboutBox);
        }
        
        public static void ShowSpash()
        {
            s_appAboutForm = NewAppAboutForm();
            s_appAboutForm.TopMost = true;
            s_appAboutForm.ShowInTaskbar = false;
            s_appAboutForm.ButtonOK.Visible = false;
            s_appAboutForm.TextBoxInfo.ScrollBars = ScrollBars.None;

            //
            C1.C1Preview.Forms.WarningForm.ShowingDialog += (o, e) => HideSpash();

            //
            s_appAboutForm.Show();
            Application.DoEvents();
        }

        public static void HideSpash()
        {
            if (s_appAboutForm != null)
            {
                s_appAboutForm.Hide();
                s_appAboutForm.Dispose();
                s_appAboutForm = null;
            }
        }
        #endregion

    }

    /// <summary>
    /// Represents a field in the fields list panel (lbFields).
    /// Used to differentiate between "text" and "picture" fields.
    /// </summary>
    internal class FieldListItem
    {
        public string Name
        {
            get;
            private set;
        }

        public bool IsPicture
        {
            get;
            private set;
        }

        public FieldListItem(string name, bool isPicture)
        {
            Name = name;
            IsPicture = isPicture;
        }

        public override string ToString()
        {
            return Name;
        }
    }

    /// <summary>
    /// CommonFields: helper class used for building fields with often-used expressions
    /// </summary>
    internal class CommonFields
    {
        private static ListDictionary _fieldList;
        private static List<string> _fieldNames;

        static CommonFields()
        {
            // build special field list
            _fieldList = new ListDictionary();

            _fieldList.Add(Strings.CommonFields.DatePrinted, "Format(Now, \"Medium Date\")");
            _fieldList.Add(Strings.CommonFields.TimePrinted, "Format(Now, \"Medium Time\")");
            _fieldList.Add("- ", string.Empty); // << extra space to keep unique key
            _fieldList.Add(Strings.CommonFields.DateCreated, "=Format(Now, \"Medium Date\")");
            _fieldList.Add(Strings.CommonFields.TimeCreated, "=Format(Now, \"Medium Time\")");
            _fieldList.Add("-  ", string.Empty); // << extra space to keep unique key
            _fieldList.Add(Strings.CommonFields.PageNumber, "[Page]");
            _fieldList.Add(Strings.CommonFields.PageCount, "[Pages]");
            _fieldList.Add(Strings.CommonFields.PageNOfM, "\"Page \" & [Page] & \" of \" & [Pages]");
            _fieldList.Add("-   ", string.Empty); // << extra space to keep unique key
            _fieldList.Add(Strings.CommonFields.ReportName, "Report.ReportName");

            // build string array with field names
            _fieldNames = new List<string>(_fieldList.Count);
            foreach (string fieldName in _fieldList.Keys)
                _fieldNames.Add(fieldName.TrimEnd());
        }

        public static List<string> GetFieldNames()
        {
            return _fieldNames;
        }

        public static void SetupField(C1Report report, Field f, string createInfo)
        {
            // get expression
            if (createInfo != null && _fieldList.Contains(createInfo))
            {
                string expression = _fieldList[createInfo] as string;
                // System.Diagnostics.Debug.Assert(expression != null);


                // if the field expression starts with an equals sign, evaluate
                // the expression at creation time and store the value
                if (expression.StartsWith("="))
                {
                    f.Text = report.Evaluate(expression.Substring(1)).ToString();
                    f.Calculated = false;
                }
                else // otherwise, evaluate at render time
                {
                    f.Text = expression;
                    f.Calculated = true;
                }
            }
            else
            {
                // arbitrary formula:
                f.Text = createInfo ?? "data";
                f.Calculated = createInfo != null;
            }
        }
    }
}
