//----------------------------------------------------------------------------
// MainForm.cs
//
// Main form for C1ReportDesigner application
//
// This is a part of the C1ReportDesigner package.
// Copyright (C) ComponentOne LLC
// 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.C1Report;
using C1.Win.C1Ribbon;
using ReportDesignerApp.Util;
using C1.Win.C1Command;
using C1.Win.C1Preview;

namespace ReportDesignerApp
{
    public partial class MainForm : C1.Win.C1Ribbon.C1RibbonForm, ISite
    {
        private const string _clickHereToCopy = "(click here to copy the error list to the clipboard)\r\n";
        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 _szCompanyName = "ComponentOne";
        internal const string _szAppName = "C1ReportDesigner";
        internal const string _regKey = @"Software\ComponentOne\C1ReportDesigner.2";
        internal const string _fileFilter = "Report Definition Files (*.xml)|*.xml|All Files|*.*";
        internal const string _exportFilter =
            "Paged HTML (*.htm)|*.htm|" +
            "Drilldown HTML (*.htm)|*.htm|" +
            "Plain HTML (*.htm)|*.htm|" +
            "PDF (system fonts) (*.pdf)|*.pdf|" +
            "PDF (embedded fonts) (*.pdf)|*.pdf|" +
            "Rich Text Format (*.rtf)|*.rtf|" +
            "RTF (fixed positioning) (*.rtf)|*.rtf|" +
            "Microsoft Excel 97 (*.xls)|*.xls|" +
            "Microsoft Excel 2007 - OpenXml (*.xlsx)|*.xlsx|" + // <<B250>>
            "Tag Image File Format (*.tif)|*.tif|" +
            "Text (*.txt)|*.txt|" +
            "Single Page Text (*.txt)|*.txt|" +
            "Compressed Metafile (*.zip)|*.zip";

        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 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 _htSchema = null;       // data schema available to component

        // user preferences
        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 bool _showExportOptions = true;

        // 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;

        // flag to handle form close while rendering report:
        private bool _closeRequestedWhileRendering = false;

        // event telling the splash screen to go away:
        internal event EventHandler SplashOff = null;

        static MainForm()
        {
            s_CustomFieldImage = AppUtils.LoadResourceImage("CustomField.png");
        }

        public MainForm()
        {
            ShowSplash();

            InitializeComponent();

            // 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()));

            //
            UpdateFormCaption();

            //
            rbtnFieldDataField.ArrowVisible = false;
            rbtnFieldBarCode.ArrowVisible = false;
            rbtnFieldBoundPicture.ArrowVisible = false;
            rbtnFieldCheckBox.ArrowVisible = false;
            rbtnFieldSubReport.ArrowVisible = false;
            rbtnFieldRtf.ArrowVisible = false;
            rbtnFieldSubReport.ArrowVisible = false;
            rbtnFieldCommonCalculated.ArrowVisible = false;

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

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

        internal void OnSplashOff()
        {
            if (SplashOff != null)
                SplashOff(this, EventArgs.Empty);
        }

        #region Public properties

        [Browsable(false)]
        public C1Ribbon Ribbon
        {
            get { return rbnMain; }
        }

        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; }
        }

        #endregion

        #region Private

        private void BeginUIUpdate()
        {
            _UIUpdateCounter++;
        }

        private void EndUIUpdate()
        {
            _UIUpdateCounter--;
        }

        private void ShowSplash()
        {
            AboutForm splash = new AboutForm();
#if !DEBUG
            splash.TopMost = true;
            splash.ControlBox = false;
            splash.FormBorderStyle = FormBorderStyle.None;
            splash.ShowInTaskbar = false;
#endif
            System.Diagnostics.Debug.Assert(this.OwnedForms.Length == 0);
            splash.Owner = this;
            splash.BackgroundImageLayout = ImageLayout.Stretch;
            Assembly asmb = Assembly.GetExecutingAssembly();
            using (Stream s = asmb.GetManifestResourceStream("ReportDesignerApp.Resources.SplashBackground.png"))
                splash.BackgroundImage = Image.FromStream(s);
            Button b = splash.AcceptButton as Button;
            System.Diagnostics.Debug.Assert(b != null);
            if (b != null)
            {
                b.Parent = null;
                Label l = new Label();
                l.TextAlign = ContentAlignment.MiddleCenter;
                l.Text = "Loading...";
                l.Font = new Font(l.Font, FontStyle.Italic);
                l.Location = b.Location;
                l.Size = b.Size;
                l.BackgroundImageLayout = ImageLayout.Stretch;
                using (Stream s = asmb.GetManifestResourceStream("ReportDesignerApp.Resources.SplashLoading.png"))
                    l.BackgroundImage = Image.FromStream(s);
                l.Parent = splash;
            }
            this.SplashOff += new EventHandler(MainForm_SplashOff);
            splash.Show(this);
            Application.DoEvents();
        }

        void MainForm_SplashOff(object sender, EventArgs e)
        {
            this.SplashOff -= new EventHandler(MainForm_SplashOff);
            Form splash = this.OwnedForms[0];
            splash.Hide();
            splash.Dispose();
        }

        private void _timer_Tick(object sender, EventArgs e)
        {
            // Update UI:
            if (_timerUpdateNeeded)
            {
                _timerUpdateNeeded = false;
                //
                UpdateUIPreviewStatusBar(true);
                UpdateUINavigation(false);
                UpdateUIPreviewTools(false);
                UpdateUIZoom(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;
            rtArrange.Visible = designMode;
            rtPageSetup.Visible = designMode;
            rtPreview.Visible = !designMode;

            this.ResumeLayout();

            if (designMode)
            {
                _preview.Document = null;
                if (_lastDesignPage == null)
                    dtpReports.Show();
                else
                    _lastDesignPage.Show();

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

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

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

            ShowStatus();
            Update();
        }

        private void UpdateFormCaption()
        {
            string caption = _szAppName;
            if (_noFile)
            {
                caption += " - [Component]";
            }
            else if (_fileName.Length > 0)
            {
                caption += " - " + _fileName;
            }
            if (_dirty) caption += " *";
            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()
        {
            bool firstField = true;
            foreach (string fieldInfo in AppSettings.LoadList("customfields"))
            {
                // get assembly, class name
                string[] arr = fieldInfo.Split(';');
                if (arr.Length < 2) continue;
                string asmName = arr[0];
                string clsName = arr[1];

                // 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("Custom field Assembly '{0}' (or one of its dependencies) not found.", asmName);
                        throw new ApplicationException(msg);
                    }
                    object customField = asm.CreateInstance(clsName, true);
                    if (customField == null)
                    {
                        string msg = string.Format("Cannot instantiate class '{0}'.\r\n", clsName) +
                            "Check custom field class name in .settings file (it should include the namespace).";
                        throw new ApplicationException(msg);
                    }

                    // check that the class derives from C1Report.Field
                    if (!customField.GetType().IsSubclassOf(typeof(Field)))
                    {
                        string msg = string.Format("Class '{0}' does not derive from C1Report.Field and cannot be used as a custom field.\r\n", clsName) +
                            "Check customfields entry in .settings file.";
                        throw new ApplicationException(msg);
                    }

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

                    // 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 separator before the first custom field
                    if (firstField)
                    {
                        firstField = false;
                        rgFields.Items.Add(new RibbonSeparator());
                    }

                    // add custom field to toolbar
                    RibbonButton btn = new RibbonButton();
                    btn.Tag = customField; // tag is clonable field
                    btn.ToolTip = "Add " + desc; // tooltip is field description
                    btn.SmallImage = img;
                    rgFields.Items.Add(btn);
                }
                catch (Exception x)
                {
                    System.Diagnostics.Debug.WriteLine(string.Format("failed to load custom field '{0}':\r\n{1}", fieldInfo, x.Message));
                }
            }
        }

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

        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();

            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;
                    }

                    // create a copy so the report fields won't be changed while rendering <<B170>>
                    string reportDefinition = _designer.Report.ReportDefinition;
                    _reportRender.DoEvents = _designer.Report.DoEvents;
                    if (_reportRender.ReportDefinition != reportDefinition)
                        _reportRender.ReportDefinition = reportDefinition;

                    // don't use CopyFrom here: it does a shallow copy of the subreports,
                    // which would allow scripts to change the subreport definition.
                    //_reportRender.CopyFrom(_designer.Report);

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

                    // make report dirty to force re-render <<B202>>
                    if (force)
                    {
                        _reportRender.Clear();
                        _reportRender.ReportDefinition = reportDefinition;
                    }

                    // cannot get data at design time, so render as unbound <<B187>>
                    string conn = _reportRender.DataSource.ConnectionString;
                    if (conn != null && conn.Length > 0 && _htSchema != null && _htSchema.Contains(conn))
                        _reportRender.DataSource.ConnectionString = string.Empty;

                    // render the report
                    _reportRender.DoEvents = true;
                    _preview.Document = _reportRender;
                    _preview.Focus();
                    if (_reportDesignMode)
                        SetDesignMode(true);
                    return true;
                }

                // Data access problem? allow user to fix the connection
                catch (DataAccessException x)
                {
                    // build error message <<B132>>
                    string msg = "Failed to open the specified data source.";
                    if (x.InnerException != null && x.InnerException.Message.Length > 0)
                        msg += "\r\n\r\n** Error details:\r\n" + x.InnerException.Message;
                    msg += "\r\n\r\nWould you like to edit the data source?";

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

                    // allow them to edit the connection string
                    using (DataSourceForm dlg = new DataSourceForm())
                    {
                        if (dlg.ShowDialog(_designer.Report, _htSchema) != DialogResult.OK)
                            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
                {
                    Warn("Error rendering report:\r\n" + x.Message);
                    return false;
                }

                // always fix the cursor
                finally
                {
                    Cursor = Cursors.Default;
                }
            }
            finally
            {
                if (!wasPreviewRendering)
                {
                    _isPreviewRendering = false;
                    UpdateUI();
                }
            }
        }

        // configure based on command-line arguments passed by 
        // C1Report's ControlDesigner class <<B80>>
        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
            _htSchema = 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();
                        _htSchema = (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 && _htSchema != null && _htSchema.Contains(conn))
            {
                DataSet dset = (DataSet)_htSchema[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;
        }

        // delegate for editing scripts
        private static string _editExpression(C1Report report, string expression)
        {
            using (ScriptEditorForm dlg = new ScriptEditorForm(report, true))
            {
                InitScriptEditorForm(dlg, report, expression);
                if (dlg.ShowDialog() == DialogResult.OK)
                    expression = dlg.Expression;
            }
            return expression;
        }

        private static string _editStatement(C1Report report, string statement)
        {
            using (ScriptEditorForm dlg = new ScriptEditorForm(report, false))
            {
                InitScriptEditorForm(dlg, report, statement);
                if (dlg.ShowDialog() == DialogResult.OK)
                    statement = dlg.Expression;
            }
            return statement;
        }

        private static void InitScriptEditorForm(ScriptEditorForm dlg, C1Report report, string expression)
        {
            dlg.Expression = expression;
            if (report.Site != null)
            {
                MainForm frm = report.Site.Component as MainForm;
                if (frm != null)
                {
                    dlg.EditorFont = frm._scriptEditorFont;
                    dlg.SyntaxCheck = frm._syntaxCheck;
                    dlg.SyntaxColoring = frm._syntaxColoring;
                }
            }
        }

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

        // display a warning
        private void Warn(string msg)
        {
            OnSplashOff();
            MessageBox.Show(msg, _szAppName, MessageBoxButtons.OK, MessageBoxIcon.Information);
        }

        // display a question
        private DialogResult Ask(string msg, MessageBoxButtons buttons)
        {
            OnSplashOff();
            return MessageBox.Show(msg, _szAppName, buttons, MessageBoxIcon.Question);
        }

        private DialogResult Ask(string msg)
        {
            return Ask(msg, MessageBoxButtons.YesNo);
        }

        private bool IsItemsEqual(RibbonItemCollection items1, string[] items2)
        {
            if (items1.Count != items2.Length)
                return false;

            for (int i = 0; i < items2.Length; 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;
        }

        private void UpdateDropDownField(RibbonMenu menu, string[] items)
        {
            if (items == null || items.Length <= 0)
                menu.Enabled = false;
            else
            {
                menu.Enabled = true;
                // 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);

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

                // TFS ~~6723. Updating color pickers' colors ensures that:
                // (a) RibbonEventType.SelectedColorChanged is only fired when a real change took place, and
                // (b) when the picker's dropdown is opened, current item's color is highlighted.
                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;
            }
        }

        private void UpdateUIFields(bool update)
        {
            if (update)
                UpdateState();
            rbnMain.BeginUpdate();
            try
            {
                if (_state.DesignMode && _designer.Report != null)
                {
                    rgFields.Enabled = true;
                    // go over all fields and fill drop-down menus
                    string[] allFields = _designer.Report.DataSource.GetDBFieldList(true);
                    UpdateDropDownField(rbtnFieldDataField, allFields);
                    UpdateDropDownField(rbtnFieldBarCode, allFields);
                    UpdateDropDownField(rbtnFieldCheckBox, allFields);
                    UpdateDropDownField(rbtnFieldRtf, allFields);
                    UpdateDropDownField(rbtnFieldCommonCalculated, CommonFields.GetFieldNames());
                    UpdateDropDownField(rbtnFieldBoundPicture, _designer.Report.DataSource.GetDBFieldList(false));
                    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.ToArray());
                }
                else
                    rgFields.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(rgEdit1.Items);
                UpdateRibbonItems(rgEdit2.Items);
                UpdateRibbonItems(rgEdit3.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 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 UpdateUIPreviewPrint(bool update)
        {
            if (update)
                UpdateState();
            rbnMain.BeginUpdate();
            try
            {
                UpdateRibbonItems(rgPreviewPrint.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 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)
            {
                _state.DesignerCanCut = _designer.ClipboardHandler.CanCut;
                _state.DesignerCanPaste = _designer.ClipboardHandler.CanPaste;
                _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;

            //
            _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 = _state.HasCurrReport && _state.DesignMode && !_state.PreviewRendering;

            //
            _actions[ActionTypeEnum.Preview].Enabled = _state.DesignMode && _state.HasCurrReport;
            _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;
                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;
                }
                //
                _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 = foreColor != null;
                _actions[ActionTypeEnum.TextColor].Color = foreColor == null ? Color.Empty : (Color)foreColor;
                _actions[ActionTypeEnum.FillColor].Enabled = backColor != null;
                _actions[ActionTypeEnum.FillColor].Color = backColor == null ? Color.Empty : (Color)backColor;
            }
            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;
                //
                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 > 0;
            _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.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("of {0}", _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 > 1;
                _actions[ActionTypeEnum.EqualVerticalSpacing].Enabled = _state.SelectedFieldCount > 1;
                _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("{0}%", 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;
            _actions[ActionTypeEnum.PasteReport].Enabled = _state.DesignMode && !_state.PreviewRendering && GetReportDataPresent(Clipboard.GetDataObject());
            _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 = "Report: " + _designer.Report.ReportName;
            }
            else
            {
                _actions[ActionTypeEnum.SelectedReport].Text = "Report: Not selected";
            }

            //
            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 = _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);

                //
                UpdateUIEdit(false);

                // 
                UpdateUIFont(false);

                //
                UpdateUIData(false);

                //
                UpdateUIFields(false);

                //
                UpdateUITools(false);

                //
                UpdateUIFormat(false);

                //
                UpdateUIGrid(false);

                //
                UpdateUIControlAlignment(false);

                //
                UpdateUISize(false);

                //
                UpdateUIPageSetup(false);

                //
                UpdateUIPosition(false);

                //
                UpdateUIPreviewPrint(false);

                //
                UpdateUIZoom(false);

                //
                UpdateUINavigation(false);

                //
                UpdateUIPreviewTools(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 <<B166>>
            string name = rpt.ReportName;
            if (name == null || name.Length == 0)
                name = "Report";

            // 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; // <<IP281>> reset to design mode (APRDS000324)
            ShowStatus("Ready");
            UpdateUI();

            // done
            return true;
        }

        private void RecentFileClick(object sender, EventArgs e)
        {
            string fileName = (string)((RibbonListItem)sender).Tag;
            if (!OpenFile(fileName))
                Warn(string.Format("File '{0}' cannot be opened and has been removed from the recent file list.", 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);
        }

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

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

        private void UpdateFields(C1Report report)
        {
            lbFields.BeginUpdate();
            try
            {
                lbFields.Items.Clear();

                if (report != null)
                {
                    try
                    {
                        string[] arr = report.DataSource.GetDBFieldList(true);
                        if (arr != null)
                        {
                            foreach (string field in arr)
                                lbFields.Items.Add(field);
                        }
                    }
                    catch
                    {
                    }
                }
            }
            finally
            {
                lbFields.EndUpdate();
            }
        }

        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("&{0}  {1}", i + 1, Path.GetFileName(fn));
                else
                    rb.Text = string.Format("   {0}", Path.GetFileName(fn));
                rli.Items.Add(rb);
                ramMain.RightPaneItems.Add(rli);
            }
        }

        private void InitRecentFiles()
        {
            _recentFiles = AppSettings.LoadList("recentfiles");
            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 = "Open Report Definition File";
                dlg.DefaultExt = "xml";
                dlg.FileName = "*.xml";
                dlg.Filter = _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)
                {
                    Warn(string.Format("Cannot load '{0}' because of the following error:\r\n{1}", 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)
                    Warn(string.Format("Cannot find any reports in '{0}'.\r\nPlease make sure the file contains Reports and that the reports have Names.", 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("Loading {0} of {1}: '{2}'", i + 1, cnt, reports[i]));
                C1Report report = new C1Report();
                try
                {
                    report.Load(doc, reports[i]);
                    _reportList.Items.Add(new ReportItem(report));
                }
                catch (Exception x)
                {
                    Warn(string.Format("Failed to load report '{0}' because of the following error:\r\n{1}", reports[i], x.Message));
                }
            }
            _reportList.EndUpdate();

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

            //
            ShowStatus("Ready");

            // and select the first report on the list <<B92>>
            if (_reportList.Items.Count > 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 = "Import Report Definition";
                dlg.DefaultExt = "mdb";
                // dlg.FileName = "*.mdb"; <<IP194>> (APRDS000215)
                if (_borland)
                {
                    dlg.Filter = "Microsoft Access Reports (*.mdb,*.adp)|*.mdb;*.adp|" +
                        "All Files (*.*)|*.*";
                }
                else
                {
                    dlg.Filter = "All Supported Formats (*.mdb,*.adp,*.rpt)|*.mdb;*.adp;*.rpt|" +
                        "Microsoft Access Reports (*.mdb,*.adp)|*.mdb;*.adp|" +
                        "Crystal Reports (*.rpt)|*.rpt|" +
                        "All Files (*.*)|*.*";
                }
                if (dlg.ShowDialog() != DialogResult.OK)
                    return false;

                // let user know we're working...
                ShowStatus(string.Format("Importing from '{0}'...", 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)
                {
                    Warn(string.Format("Could not import '{0}' correctly because of the following error:\r\n{1}", 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("Ready");
            }
        }

        private void _loading(object sender, System.EventArgs e)
        {
            C1Report rpt = (C1Report)_importList[_importList.Count - 1];
            ShowStatus(string.Format("Importing '{0}'...", 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 <<B165>>
            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 = "Save Report Definition File";
                    dlg.FileName = "*.xml";
                    dlg.DefaultExt = "xml";
                    dlg.Filter = _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 <<B110>>
            // (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("Saving {0} of {1}: '{2}'", 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) // <<B114>>
            {
                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
        private bool DiscardChangesOK()
        {
            // no changes? we're OK then
            if (!_dirty)
                return true;

            // prompt user
            DialogResult dr = Ask("Would you like to save the changes you made to this file?", MessageBoxButtons.YesNoCancel);
            switch (dr)
            {
                case DialogResult.Yes:
                    return SaveFile(false); // <<B132>>
                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(string fileName, FileFormatEnum fileFormat)
        {
            Cursor = Cursors.WaitCursor;
            ShowStatus(string.Format("Exporting '{0}' to '{1}'...", _designer.Report.ReportName, fileName));
            try
            {
                try
                {
                    // save report definition to detect changes while exporting <<B141>>
                    string reportDefinition = _designer.Report.ReportDefinition;

#if !use_c1report_original_RenderToFile // using ExportProvider allows to show export options (preview mostly) (TFS~~4505)
                    C1.C1Preview.Export.ExportProvider provider = null;
                    foreach (C1.C1Preview.Export.ExportProvider ep in C1.C1Preview.Export.ExportProviders.RegisteredProviders)
                        if (ep.C1ReportFileFormat == fileFormat)
                        {
                            provider = ep;
                            break;
                        }
                    if (provider != null)
                    {
                        C1.C1Preview.Export.Exporter ex = provider.NewExporter();
#if skip_dima // todo/tbd: include this when report export provide realistic longOperation calls (now it is only 0%->100% - not good)
                        ex.LongOperation +=
                            (sender, e) =>
                            {
                                ShowStatus(string.Format("Exporting '{0}' to '{1}', {2:0.0%} complete", _designer.Report.ReportName, fileName, e.Complete));
                            };
#endif
                        ex.Document = _designer.Report;
                        ex.ShowOptions = _showExportOptions;
                        ex.Export(fileName);
                    }
#else
                    // export to file
                    _designer.Report.RenderToFile(fileName, fileFormat);
#endif

                    // restore original if needed <<B141>>
                    if (_designer.Report.ReportDefinition != reportDefinition)
                        _designer.Report.ReportDefinition = reportDefinition;
                }
                catch (Exception e)
                {
                    Warn(string.Format("Failed to export '{0}' because of the following error:\r\n{1}", fileName, e.Message));
                }
            }
            finally
            {
                ShowStatus("Ready");
            }
            Cursor = Cursors.Default;
        }

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

        // export selected report
        private void ExportReport(int filterIndex)
        {
            // sanity <<B158>>
            System.Diagnostics.Debug.Assert(_designer.Report != null);
            if (_designer.Report == null)
                return;

            // get export file name
            using (SaveFileDialog dlg = new SaveFileDialog())
            {
                dlg.DereferenceLinks = true;
                dlg.Title = "Export Report to File";
                dlg.FileName = Regex.Replace(_designer.Report.ReportName, @"[:\\\.]", "_"); // <<B164>>
                dlg.Filter = _exportFilter;
                dlg.FilterIndex = filterIndex;
                DialogResult dr = dlg.ShowDialog();
                if (dr != DialogResult.OK)
                    return;
                _defaultExportIndex = dlg.FilterIndex;

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

                // get file format
                string ext = Path.GetExtension(dlg.FileName).ToLower();
                FileFormatEnum fileFormat = FileFormatEnum.HTML;
                switch (ext)
                {
                    case ".pdf": fileFormat = FileFormatEnum.PDF; break;
                    case ".rtf": fileFormat = FileFormatEnum.RTF; break;
                    case ".xls": fileFormat = FileFormatEnum.Excel; break;
                    case ".xlsx": fileFormat = FileFormatEnum.OpenXml; break; // <<B250>>
                    case ".tif": fileFormat = FileFormatEnum.TIFF; break;
                    case ".txt": fileFormat = FileFormatEnum.Text; break;
                    case ".zip": fileFormat = FileFormatEnum.Metafile; break;
                }
                if (fileFormat == FileFormatEnum.HTML ||
                    fileFormat == FileFormatEnum.PDF ||
                    fileFormat == FileFormatEnum.RTF ||
                    fileFormat == FileFormatEnum.Text)
                {
                    switch (dlg.FilterIndex)
                    {
                        case 1: fileFormat = FileFormatEnum.HTMLPaged; break;
                        case 2: fileFormat = FileFormatEnum.HTMLDrillDown; break;
                        case 3: fileFormat = FileFormatEnum.HTML; break;
                        case 4: fileFormat = FileFormatEnum.PDF; break;
                        case 5: fileFormat = FileFormatEnum.PDFEmbedFonts; break;
                        case 6: fileFormat = FileFormatEnum.RTF; break;
                        case 7: fileFormat = FileFormatEnum.RTFLabels; break; // <<IP194>>
                        case 8: fileFormat = FileFormatEnum.Excel; break;
                        case 9: fileFormat = FileFormatEnum.OpenXml; break; // <<B250>>
                        case 10: fileFormat = FileFormatEnum.TIFF; break;
                        case 11: fileFormat = FileFormatEnum.Text; break;
                        case 12: fileFormat = FileFormatEnum.TextSinglePage; break; // <<IP189>>
                    }
                }

                // start exporting
                ExportReport(dlg.FileName, fileFormat);
            }
        }

        // create a name for a new field
        internal string GetUniqueFieldName()
        {
            FieldCollection fields = _designer.Report.Fields;
            for (int i = 1; ; i++)
            {
                string name = "Field" + i.ToString();
                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()
        {
            // get parameters for report wizard
            string conn = null, rs = null;
            if (_designer.Report != null)
            {
                DataSource ds = _designer.Report.DataSource;
                conn = ds.ConnectionString;
                rs = ds.RecordSource;
            }

            // 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(conn, rs, _htSchema);

                // 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 <<B192>>
                        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 = Ask(string.Format("Are you sure you want to delete the '{0}' report?\r\nThis action cannot be undone.", 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;
        }

        #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,

            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,

            Preview,

            SelectedReport,
        }

        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; } // <<IP193>> APRDS000242
        }

        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)
            {
                // does not work with Japanese translation (TFS~~6615): if (c is Button && c.Text == "Hide")
                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)
        {
            // hide the "Hide" button on "Find" tab
            FindHideButton(ptspMain.Controls);

            // save app startup path (to start from IDE)
            using (RegistryKey key = Registry.CurrentUser.CreateSubKey(_regKey))
            {
                if (key != null)
                {
                    key.SetValue("ApplicationPath", Application.ExecutablePath);
                    _borland = (key != null && key.GetValue("OEM") != null); // <<B153>>
                }
            }

            // load recent connections from registry if the
            // config file is empty (easier upgrade) <<B152>>
            ArrayList list = AppSettings.LoadList("recentconnections");
            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);
                    }
                }
            }

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

            // start in design mode
            SetDesignMode(true);

            // 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 <<B62>>
            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 <<B62>>
            if (_noFile)
            {
                // confirm discarding changes <<B132>>
                if (_dirty)
                {
                    // prompt user
                    switch (Ask("Would you like to save the changes you made to this report?", 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.PreviewRendering && _reportRender.IsBusy)
                    {
                        _reportRender.Cancel = true;
                        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.Preview].Enabled)
                    {
                        DoPreview();
                        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;

            //
            UpdateFields(rpt);

            // 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;
            }

            // assign it to designer (after hooking up site) <<IP193>>
            _designer.Report = rpt;
        }

        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 <<B167>>
            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)
                {
                    Warn("Sorry, report names must be unique. Please choose a different name.");
                }
                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 == rbtnFieldLabel)
            {
                field.Text = field.Name;
                field.Calculated = false;
            }
            else if (btn == rbtnFieldDataField || btn == rbtnFieldCalculated)
            {
                field.Text = _createInfo != null ? _createInfo : "data";
                field.Calculated = _createInfo != null;
            }
            else if (btn == rbtnFieldCommonCalculated)
            {
                CommonFields.SetupField(_designer.Report, field, _createInfo);
            }
            else if (btn == rbtnFieldBoundPicture)
            {
                field.Picture = _createInfo;
                field.Calculated = false;
            }
            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;
                field.BarCode = BarCodeEnum.Code39;
            }
            else if (btn == rbtnFieldRtf)
            {
                field.Text = _createInfo != null ? _createInfo : "richText";
                field.Calculated = _createInfo != null;
                field.RTF = true;
            }
            else if (btn == rbtnFieldUnboundPicture)
            {
                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.LineSlant = 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("Rendering '{0}' (Press ESC to Cancel)...", _reportRender.ReportName));
        }

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

            //
            _isPreviewRendering = true;
            UpdateUI();
            ShowStatus(string.Format("Rendering '{0}'...", _designer.Report.ReportName));
            Cursor = Cursors.WaitCursor;
        }

        private void _reportRender_EndReport(object sender, EventArgs e)
        {
            _isPreviewRendering = false;
            UpdateUI();
            ShowStatus("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("** Report [{0}] contains errors:\r\n{1}",
                    _reportRender.ReportName,
                    _clickHereToCopy);
            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;

            Clipboard.SetDataObject(BuildDataObject());
            UpdateUI();
        }

        private void DoCopyFields()
        {
            _designer.ClipboardHandler.Copy();
            UpdateUI();
        }

        private void DoCutReport()
        {
            if (_reportList.SelectedItem != null)
            {
                Clipboard.SetDataObject(BuildDataObject());
                DeleteReport(true);
            }
        }

        private void DoCutFields()
        {
            _designer.UndoStack.SaveState();
            _dirty = true;
            _designer.ClipboardHandler.Cut();
            _reportList.UpdateIcons(); // <<B83>>
            UpdateUI();
        }

        private void DoPasteReport()
        {
            PasteDataObject(Clipboard.GetDataObject());
        }

        private void DoPasteFields()
        {
            _designer.UndoStack.SaveState();
            _dirty = true;
            _designer.ClipboardHandler.Paste();
            _reportList.UpdateIcons(); // <<B83>>
            UpdateUI();
        }

        private void DoDeleteFields()
        {
            _designer.UndoStack.SaveState();
            _dirty = true;
            _designer.ClipboardHandler.Delete();
            _reportList.UpdateIcons(); // <<B83>>
            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())
                Application.Exit();
        }

        private void DoSaveAndExit()
        {
            SaveTempFile(true);
            Application.Exit();
        }

        private void DoCancelAndExit()
        {
            SaveTempFile(false);
            Application.Exit();
        }

        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())
                {
                    DialogResult dr = dlg.ShowDialog(_designer.Report, _htSchema);
                    if (dr == DialogResult.OK)
                        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 (Ask("Are you sure you want to apply this information to all reports?") == DialogResult.Yes)
                        {
                            foreach (ReportItem reportItem in _reportList.Items)
                            {
                                reportItem._report.ReportInfo = f.ReportInfo.Clone();
                            }
                        }
                    }
                    _designer.CreateFieldInfo = null;
                    SetDirty();
                }
            }
        }

        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();
        }

        private void DoCreateField(RibbonItem item)
        {
            if (item == rbtnFieldArrow)
            {
                _designer.CreateFieldInfo = null;
                _createInfo = null;
            }
            else if (item.Parent is RibbonMenu)
            {
                _designer.CreateFieldInfo = item.Parent;
                _createInfo = ((RibbonButton)item).Text;
            }
            else if (item == rbtnFieldUnboundPicture)
            {
                using (OpenFileDialog dlg = new OpenFileDialog())
                {
                    dlg.DereferenceLinks = true;
                    dlg.Filter = "All Image Files|*.bmp;*.png;*.gif;*.jpg;*.dib;*.ico;*.cur;*.wmf;*.emf|Bitmaps (*.bmp;*.dib)|*.bmp;*.dib|Icons & Cursors (*.ico;*.cur)|*.ico;*.cur|Web Images (*.gif;*.jpg;*.png)|*.gif;*.jpg;*.png|Metafiles (*.wmf;*.emf)|*.wmf;*.emf|All Files (*.*)|*.*";
                    dlg.FileName = "*.bmp;*.dib;*.ico;*.cur;*.gif;*.jpg;*.wmf;*.emf;*.png";
                    dlg.FilterIndex = 0;
                    if (dlg.ShowDialog() == DialogResult.OK)
                    {
                        _createInfo = dlg.FileName;
                        _designer.CreateFieldInfo = rbtnFieldUnboundPicture;
                    }
                }
            }
            else if (item == rbtnFieldCalculated)
            {
                using (ScriptEditorForm dlg = new ScriptEditorForm(_designer.Report, true))
                {
                    if (dlg.ShowDialog() == DialogResult.OK)
                    {
                        _createInfo = dlg.Expression;
                        if (_createInfo != null && _createInfo.Length > 0)
                            _designer.CreateFieldInfo = rbtnFieldCalculated;
                    }
                }
            }
            else if (item == rbtnFieldLabel || item == rbtnFieldLine || item == rbtnFieldRectangle || item == rbtnFieldPageBreak)
            {
                _designer.CreateFieldInfo = item;
            }
            else if (item.Tag is Field)
                _designer.CreateFieldInfo = item;
        }

        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 = rbtnLockFields.Pressed;
        }

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

        private void DoGridProperties()
        {
            _appConfig.ShowDialog();
            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 <<B175>>
                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;
                }
        }

        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 (AboutForm dlg = new AboutForm())
                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 == rbtnCut1 || item == rbtnCut2 || item == rbtnCut3)
                DoCutFields();
            else if (item == rbtnCopy1 || item == rbtnCopy2 || item == rbtnCopy3)
                DoCopyFields();
            else if (item == rbtnPaste1 || item == rbtnPaste2 || item == rbtnPaste3)
                DoPasteFields();
            else if (item == rbtnDelete1 || item == rbtnDelete2 || item == rbtnDelete3)
                DoDeleteFields();
            else if (item == rbtnUndo1 || item == rbtnUndo2 || item == rbtnUndo3)
                DoUndo();
            else if (item == rbtnRedo1 || item == rbtnRedo2 || item == rbtnRedo3)
                DoRedo();
            else if (item == rbtnExit)
                DoExit();
            else if (item == rbtnSaveAndExit)
                DoSaveAndExit();
            else if (item == rbtnCancelAndExit)
                DoCancelAndExit();
            else if (item == rbtnPreview1 || item == rbtnPreview2 || item == rbtnPreview3)
                DoPreview();
            else if (item == rbtnGroupSort)
                DoGroupSort();
            else if (item == rbtnDatabase)
                DoDatabase();
            else if (item == rbtnReportInfo)
                DoReportInfo();
            else if (item.Group == rgFields)
                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 == rbtnClosePrintPreview)
                DoClosePrintPreview();
            else if (item.Group == rgExport)
                DoPreviewExport(item);
            else if (item == rbtnOptions)
                DoOptions();
            else if (item == rbtnAbout2)
                DoAbout();
            else if (item == rbtnAbout || item == rbtnHelpContents)
                DoHelpContents();
        }

        private void DoErrorToClipboard()
        {
            Clipboard.SetText(rbtnRenderError.ToolTip);
        }

        private void DoHelpContents()
        {
            try
            {
                System.Diagnostics.Process.Start(@"http://helpcentral.componentone.com/nethelp/c1report/default.htm?turl=workingwithc1reportdesigner1.htm");
            }
            catch (Exception e)
            {
                Warn(string.Format("Can't show online help:\r\n{0}", e.Message));
            }
        }

        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);
        }

        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);
        }

        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;

            //
            Field fld = new Field();
            fld.Name = GetUniqueFieldName();
            fld.Calculated = true;
            fld.Text = lbFields.SelectedItem.ToString();
            fld.Section = hti.Section.Type;
            fld.Left = hti.SectionX;
            fld.Top = hti.SectionY;
            fld.Width = cDropFieldWidth;
            fld.Height = cDropFieldHeight;
            ri._report.Fields.Add(fld);

            _designer.Refresh();
            _designer.SelectedFields = new Field[] { fld };
        }

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

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

        #region Constructors

        static CommonFields()
        {
            // build special field list
            _fieldList = new ListDictionary();
            _fieldList.Add("Date Printed", "Format(Now, \"Medium Date\")");
            _fieldList.Add("Time Printed", "Format(Now, \"Medium Time\")");
            _fieldList.Add("-", string.Empty); // << extra space to keep unique key
            _fieldList.Add("Date Created", "=Format(Now, \"Medium Date\")");
            _fieldList.Add("Time Created", "=Format(Now, \"Medium Time\")");
            _fieldList.Add("- ", string.Empty); // << extra space to keep unique key
            _fieldList.Add("Page Number", "[Page]");
            _fieldList.Add("Page Count", "[Pages]");
            _fieldList.Add("Page n of m", "\"Page \" & [Page] & \" of \" & [Pages]");
            _fieldList.Add("-  ", string.Empty); // << extra space to keep unique key
            _fieldList.Add("Report Name", "Report.ReportName");

            // build string array with field names
            _fieldNames = new string[_fieldList.Count];
            int i = 0;
            foreach (string fieldName in _fieldList.Keys)
                _fieldNames[i++] = fieldName.TrimEnd();
        }

        #endregion

        #region Public static

        public static string[] GetFieldNames()
        {
            return _fieldNames;
        }

        public static void SetupField(C1Report report, Field f, string fieldName)
        {
            // get expression
            string expression = _fieldList[fieldName] 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;
            }
        }

        #endregion
    }
}

