Česky
Kamil Dudka

Tiny programs (C, C++, C#, ...)

File detail

Name:DownloadCategoryBrowser.cs [Download]
Location: tiny > MW5 > proj2 > proj2 > UserControls
Size:13.7 KB
Last modification:2007-08-29 17:43

Source code

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
 
namespace proj2.UserControls
{
    public partial class CategoryBrowser : UserControl
    {
        private dbDataSet dataSet;
        private dbDataSet.productCategoriesDataTable pcTable;
 
        /// <summary>
        /// StatusMessageEventHandler event parameter structure
        /// </summary>
        public class StatusMessageEventArgs: EventArgs
        {
            private string msg;
            public StatusMessageEventArgs(string statusMessage)
            {
                msg = statusMessage;
            }
            public string StatusMessageText { get { return msg; } }
        }
 
        public event EventHandler ChangesMade;
 
        /// <summary>
        /// EventHandler to delegate status info messages to parent component
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public delegate void StatusMessageEventHandler (object sender, StatusMessageEventArgs e);
 
        /// <summary>
        /// Event to delegate status info messages to parent component
        /// </summary>
        public event StatusMessageEventHandler StatusMessageChanged;
        public void AddToToolBarDropDown(ToolStripItem item)
        {
            toolStripDropDownButton1.DropDownItems.Add(item);
        }
 
        private void onChangesMade()
        {
            if (null != ChangesMade)
                ChangesMade(this, EventArgs.Empty);
        }
 
        // Internal status info message text storage
        private string statusMessage;
 
        // Internal status info message text property
        private string StatusMessageText
        {
            get { return statusMessage; }
            set
            {
                string tmp = statusMessage;
                statusMessage = value;
                if (
                        null != StatusMessageChanged &&
                        tmp != statusMessage)
                    StatusMessageChanged(this, new StatusMessageEventArgs(statusMessage));
            }
        }
 
        /// <summary>
        /// CategoryEditor form instance
        /// </summary>
        private CategoryEditor categoryEditor;
        public CategoryBrowser()
        {
            categoryEditor = new CategoryEditor();
            InitializeComponent();
        }
 
        // TODO: Use this.BindingContext
        [
            DescriptionAttribute ("DataSet to bind to. Typed DataSet dbDataSet.xsd expected."),
            Browsable(false),
            DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)
        ]
        public dbDataSet DataSource
        {
            get { return listBox1.DataSource as dbDataSet; }
            set
            {
                listBox1.DataSource = value;
                dataSet = (dbDataSet)value;
                pcTable = (dbDataSet.productCategoriesDataTable)
                    dataSet.Tables["productCategories"];
 
                categoryEditor.CategoryNameMaxLength = pcTable.Columns["name"].MaxLength;
                categoryEditor.CategoryDescriptionMaxLength = pcTable.Columns["description"].MaxLength;
            }
        }
 
        /// <summary>
        /// Reeturn CurrencyManager due to this.BindingContext
        /// </summary>
        private CurrencyManager currencyManager
        {
            get { return (CurrencyManager) this.BindingContext[DataSource, "productCategories"]; }
        }
 
        /// <summary>
        /// Return current "productCategories" row due to this.BindingContext
        /// </summary>
        private dbDataSet.productCategoriesRow currentRow
        {
            get
            {
                DataRowView view =
                    (DataRowView)
                    currencyManager.Current;
                return (dbDataSet.productCategoriesRow)view.Row;
            }
        }
 
        private int pointToIndex(Point loc)
        {
            if (loc.Y > listBox1.Items.Count * listBox1.ItemHeight)
                return ListBox.NoMatches;
            else
                return listBox1.IndexFromPoint(loc);
        }
 
        /// <summary>
        /// Handle click (especiali right-button click) on ListBox client area.
        /// Switch corresponding context menu.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void contextMenuStrip2_MouseDown(object sender, MouseEventArgs e)
        {
            int index = pointToIndex (e.Location);
            if (index == ListBox.NoMatches)
            {
                listBox1.ContextMenuStrip = contextMenuStrip1;
            }
            else
            {
                listBox1.ContextMenuStrip = contextMenuStrip2;
                listBox1.SelectedIndex = index;
            }
        }
 
        /// <summary>
        /// Show dialog "Create new category" dialog
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void createnewToolStripMenuItem_Click(object sender, EventArgs e)
        {
            // Show dialog
            categoryEditor.CategoryIdVisibility = false;
            categoryEditor.CategoryName = "<name>";
            categoryEditor.CategoryDescription = "";
            if (DialogResult.Cancel == categoryEditor.ShowDialog())
                return;
 
            // Create row
            dbDataSet.productCategoriesRow row =
                (dbDataSet.productCategoriesRow)
                pcTable.NewRow();
            row.name = categoryEditor.CategoryName;
            row.description = categoryEditor.CategoryDescription;
            pcTable.AddproductCategoriesRow(row);
 
            // Select new row as current
            CurrencyManager manager = currencyManager;
            manager.Position = manager.Count - 1;
 
            // Advertise changes
            onChangesMade();
            StatusMessageText = "Added new category (ID = " + currentRow.id.ToString() + ")...";
        }
 
        /// <summary>
        /// Transform Listbox item index to corresponding DataRow object
        /// </summary>
        /// <param name="index">ListBox item index</param>
        /// <returns>Corresponding DataRow object</returns>
        private dbDataSet.productCategoriesRow ListBoxIndexToRow(int index)
        {
            if (index < 0)
                return null;
            DataView filter = new DataView(dataSet.Tables["productCategories"]);
            filter.RowStateFilter = (DataViewRowState)
                (DataRowState.Added |
                DataRowState.Modified |
                DataRowState.Unchanged);
 
            if (index >= filter.Count)
                return null;
            dbDataSet.productCategoriesRow row =
                (dbDataSet.productCategoriesRow)
                filter[index].Row;
            if (
                row == null ||
                (0 != (row.RowState &
                (DataRowState.Deleted | DataRowState.Detached))))
                return null;
            return row;
        }
 
        /// <summary>
        /// Draw ListBox item. Note, that ListBox.DrawMode must be set to OwnerDrawFixed or OwnerDrawVariable.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void listBox1_DrawItem(object sender, DrawItemEventArgs e)
        {
            // Read row data
            dbDataSet.productCategoriesRow row = ListBoxIndexToRow(e.Index);
            if (null == row)
                return;
            string strName = row.name;
            string strId = row.id.ToString();
            string strDescription = row.description;
 
            // Init drawing
            e.DrawBackground();
            Rectangle bounds = e.Bounds;
            using (Brush brush = new SolidBrush (Color.Red))
            using (Font font = new Font (listBox1.Font, FontStyle.Bold)) {
                // Draw category name
                Size textSize = TextRenderer.MeasureText(strName, font);
                bounds.Height = textSize.Height;
                e.Graphics.DrawString(strName, font, brush, bounds);
                bounds.X += textSize.Width;
                bounds.Width -= textSize.Width;
            }
            using (Brush brush = new SolidBrush(e.ForeColor))
            {
                // Draw category ID
                string idStr = "(" + strId + ")";
                Size textSize = TextRenderer.MeasureText(idStr, listBox1.Font);
                e.Graphics.DrawString(idStr, listBox1.Font, brush, bounds);
 
                // Draw category description
                bounds.X = e.Bounds.X;
                bounds.Y += textSize.Height;
                bounds.Width = e.Bounds.Width;
                e.Graphics.DrawString("  " + strDescription, listBox1.Font, brush, bounds);
            }
            e.DrawFocusRectangle();
        }
 
        // TODO: Use system-wide implementation of max(a, b)
        private T max<T>(T a, T b) where T:IComparable
        {
            return (a.CompareTo(b)>0) ? a : b;
        }
 
        /// <summary>
        /// Compute ListBox item width. Note, that ListBox.DrawMode must be set to OwnerDrawVariable.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void listBox1_MeasureItem(object sender, MeasureItemEventArgs e)
        {
            // Right margin
            // FIXME: This should not be hard-coded
            const int iRightMargin = 25;
 
            // Read row data
            dbDataSet.productCategoriesRow row = ListBoxIndexToRow(e.Index);
            if (null == row)
                return;
 
            using (Font font = new Font(listBox1.Font, FontStyle.Bold))
            {
                // Width: name + id
                e.ItemWidth = max(
                    e.ItemWidth,
                    TextRenderer.MeasureText(row.name + "(" + row.id + ")", font).Width);
            }
 
            // Width: description
            e.ItemWidth = max(
                e.ItemWidth,
                TextRenderer.MeasureText(row.description, listBox1.Font).Width);
 
            // Compare width to recent value and increase if needed
            listBox1.HorizontalExtent = max(
                listBox1.HorizontalExtent,
                e.ItemWidth + iRightMargin);
        }
 
        /// <summary>
        /// Show CategoryEditor dialog
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void editToolStripMenuItem_Click(object sender, EventArgs e)
        {
            // Show dialog
            categoryEditor.CategoryIdVisibility = true;
            categoryEditor.CategoryIdEnabled = false;
            categoryEditor.CategoryId = currentRow.id;
            categoryEditor.CategoryName = currentRow.name;
            categoryEditor.CategoryDescription = currentRow.description;
            if (DialogResult.Cancel == categoryEditor.ShowDialog())
                return;
 
            // Save changes to DataSet
            currentRow.name = categoryEditor.CategoryName;
            currentRow.description = categoryEditor.CategoryDescription;
 
            // Advertise changes
            onChangesMade();
            StatusMessageText = "Changes made to category \"" + currentRow.name + "\" with ID " + currentRow.id.ToString() + "...";
        }
 
        /// <summary>
        /// Delete category from DataSet (after user confirmation)
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void deleteToolStripMenuItem_Click(object sender, EventArgs e)
        {
            // Ask user
            string strId = currentRow.id.ToString();
            string strName = currentRow.name;
            if (DialogResult.Cancel == MessageBox.Show(
                "Are you sure to delete product category \"" +
                strName + "\"" + " with ID " + strId + "?",
                strName,
                MessageBoxButtons.OKCancel,
                MessageBoxIcon.Exclamation))
                return;
 
            DataRow[] childRows = currentRow.GetChildRows(DataSource.Relations[0]);
            if (childRows.Length != 0)
            {
                if (DialogResult.Cancel == MessageBox.Show(
                    "Category \"" + strName + "\"" + " with ID " + strId +
                    " is not empty. All products in this category will be deleted!",
                    strName,
                    MessageBoxButtons.OKCancel,
                    MessageBoxIcon.Exclamation))
                    return;
 
                // Delete products in catefory
                foreach (dbDataSet.productsRow row in childRows)
                    DataSource.products.RemoveproductsRow(row);
            }
 
            // Delete category
            currentRow.Delete();
 
            // Advertise changes
            onChangesMade();
            StatusMessageText = "Deleted category \"" + strName + "\" with ID " + strId + "...";
        }
 
 
        /// <summary>
        /// Handle double-click on ListBox client area
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void listBox1_DoubleClick(object sender, MouseEventArgs e)
        {
            if (ListBox.NoMatches == pointToIndex (e.Location))
                return;
            editToolStripMenuItem_Click(this, EventArgs.Empty);
        }
    }
}